Checking requests that come in through SNMP - snmp

So I'm still in the process of learning SNMP, please go easy. I'm using snmp4j, not just the libraries but I've loaded the source code and I'm not against modifying the source if it gets me what I need. I've programmed an agent and a test client. What I want to do is be able to check the requests coming in from the test client and specifically listening for a "set" request to a specific OID.
The current way I'm thinking about doing it is catching the request right after it runs the snmp4j method fireProcessMessage (located in the package org.snmp4j.transport.DefaultUdpTranportMapping) but I don't know how an agent queries its own mib for an oid. Is there a method that the agent uses to get OID values from its mib?
Or Is there a better way to catch a specific SET request? Is it even possible to do what I want? Basically what I want to do is run another process if the client sets a certain OID value to 1(true).

It can be done by extending the CommandProcessor
and implementing RequestHandler
like i have done
public class SNMPRequestProcessor extends CommandProcessor
{
SetHandler setHandler = new SetHandler ();
public SNMPRequestProcessor()
{
//Your code
}
#Override
protected void processRequest(CommandResponderEvent command, CoexistenceInfo cinfo, RequestHandler handler)
{
synchronized (command) {
if (command.getPDU().getType() == PDU.SET) {
super.processRequest(command, cinfo, setHandler);
}
super.processRequest(command, cinfo, handler);
}
}
/**
* Handler for process set request which update to the database
*
*/
class SetHandler implements RequestHandler
{
#Override
public boolean isSupported(int mode)
{
return mode == PDU.SET;
}
#Override
public void processPdu(Request request, MOServer server)
{
//your code
}
}
}

I have no experience with the agent side of snmp4j, but I recommend to pose this question on the official mailing list: http://lists.agentpp.org/pipermail/snmp4j/. It is quite active, you'll have a good answer in a few hours.

Related

folder structure for scraping in Laravel, using Goutte

I am a bit confused about my folder structure for the scraping code. Using console/commands, not the controller. So, in the handle function I am writing the whole scraping code. But should I suppose to do that? Or... what is the best approach for this?
UPDATED
If I understand correctly the answer below. It should look like this right now.
calling services
class siteControl extends Command
{
protected $signature = 'bot:scrape {website_id}';
protected $description = 'target a portal site and scrape';
public function __construct()
{
parent::__construct();
}
public function handle()
{
$website_id = $this->argument("website_id");
if ($website_id == 1) {
$portal = "App\Services\Site1";
}
$crawler = new $portal;
$crawler->run();
}
}
in handle method
class Site1 extends Utility
{
public function __construct()
{
parent::__construct();
}
public function run()
{
echo "method runs";
}
}
abstract:
use Goutte\Client;
abstract class Utility implements SiteInterfaces
{
protected $client;
public function __construct()
{
$this->client = new Client();
}
}
interfaces:
namespace App\Services;
interface SiteInterfaces
{
public function run();
}
and finally, I should write the whole scraping code inside the run() method? Please correct me If wrong about this... I am searching the best solution.
A best practice would be to call a separate service from your command handle() method. That way you could reuse that same service in a controller for instance.
The technical version:
Your application is given a specific thing to do (a command if you will). This command comes from outside of your application, which can be a anything from a web controller, to an API controller or a CLI application. In terms of hexagonal architecture this is called a port.
Once the application receives such a command it should not care which port it came from. By handling all similar commands in a single spot (a command handler) it does not have to worry about the origins of the command.
So to give you a short overview:
[Web request] [CLI command] <-- these are ports
\ /
\ /
\ /
[Command] <--- this is a method call to your service
|
|
|
[Command handler] <--- this is the service doing the actual work
Updated my answer
Based on the code you provided I implemented what I mentioned above like so:
app/Console/Command/BotScrapeCommand.php
This is the CLI command I mentioned above. All this class has to do is:
1. Gather input arguments; (website_id) in this case
2. Wrap those arguments in a command
3. Fire off the command using the command handler
namespace App\Console\Commands;
use App\Command\ScrapePortalSiteCommand;
use CommandHandler\ScrapePortalSiteCommandHandler;
class BotScrapeCommand extends Command
{
protected $signature = 'bot:scrape {website_id}';
protected $description = 'target a portal site and scrape';
public function handle(ScrapePortalSiteCommandHandler $handler)
{
$portalSiteId = $this->argument("website_id");
$command = new ScrapePortalSiteCommand($portalSiteId);
$handler->handle($command);
}
}
app/Command/ScapePortalSiteCommand.php
This is the Command I mentioned above. Its job is to wrap all input arguments in a class, which can be used by a command handler.
namespace App\Command;
class ScrapePortalSiteCommand
{
/**
* #var int
*/
private $portalSiteId;
public function __construct(int $portalSiteId)
{
$this->portalSiteId = $portalSiteId;
}
public function getPortalSiteId(): int
{
return $this->portalSiteId;
}
}
app/CommandHandler/ScrapePortalSiteCommandHandler.php
The command handler should implement logic based on its command. In this case that's figuring out which crawler to pick, then fire that one off.
namespace App\CommandHandler;
use App\Command\ScrapePortalSiteCommand;
use App\Crawler\PortalSite1Crawler;
use App\Crawler\PortalSiteCrawlerInterface;
use InvalidArgumentException;
class ScrapePortalSiteCommandHandler
{
public function handle(ScrapePortalSiteCommand $command): void
{
$crawler = $this->getCrawlerForPortalSite($command->getPortalSiteId());
$crawler->crawl();
}
private function getCrawlerForPortalSite(int $portalSiteId): PortalSiteCrawlerInterface {
switch ($portalSiteId) {
case 1:
return new PortalSite1Crawler();
default:
throw new InvalidArgumentException(
sprintf('No crawler configured for portal site with id "%s"', $portalSiteId)
);
}
}
}
app/Crawler/PortalSiteCrawlerInterface.php
This interface is there to make sure all crawlers can be called in similar fashion. Additionally it makes for nice type hinting.
namespace App\Crawler;
interface PortalSiteCrawlerInterface
{
public function crawl(): void;
}
app/Crawler/PortalSite1Crawler.php
This is where the implementation of the actual scraping goes.
namespace App\Crawler;
class PortalSite1Crawler implements PortalSiteCrawlerInterface
{
public function crawl(): void
{
// Crawl your site here
}
}
Another update
As you had some additional questions I've updated my answer once more.
:void
The use of : void in a method declaration means the method will not return anything. In a same way public function getPortalSiteId(): int means this method will always return an integer. The use of return typehints was added to PHP 7 and is not specific to Laravel. More information on return typehints can be found in the PHP documentation.
Commands and handlers
The use of commands and command handlers is a best practice which is part of the command bus pattern. This pattern describes an universal way of dealing with user input (a command). This post offers a nice explanation on commands and handlers. Additionally, this blog post describes in more details what a command bus is, how it's used and what the advantages are. Please note that in the code I've provided the bus implementation itself is skipped. In my opinion you do not need it per se, but in some cases it does add value.

Spring Web-Flux: How to return a Flux to a web client on request?

We are working with spring boot 2.0.0.BUILD_SNAPSHOT and spring boot webflux 5.0.0 and currently we cant transfer a flux to a client on request.
Currently I am creating the flux from an iterator:
public Flux<ItemIgnite> getAllFlux() {
Iterator<Cache.Entry<String, ItemIgnite>> iterator = this.getAllIterator();
return Flux.create(flux -> {
while(iterator.hasNext()) {
flux.next(iterator.next().getValue());
}
});
}
And on request I am simply doing:
#RequestMapping(value="/all", method=RequestMethod.GET, produces="application/json")
public Flux<ItemIgnite> getAllFlux() {
return this.provider.getAllFlux();
}
When I now locally call localhost:8080/all after 10 seconds I get a 503 status code. Also as at client when I request /all using the WebClient:
public Flux<ItemIgnite> getAllPoducts(){
WebClient webClient = WebClient.create("http://localhost:8080");
Flux<ItemIgnite> f = webClient.get().uri("/all").accept(MediaType.ALL).exchange().flatMapMany(cr -> cr.bodyToFlux(ItemIgnite.class));
f.subscribe(System.out::println);
return f;
}
Nothing happens. No data is transferred.
When I do the following instead:
public Flux<List<ItemIgnite>> getAllFluxMono() {
return Flux.just(this.getAllList());
}
and
#RequestMapping(value="/allMono", method=RequestMethod.GET, produces="application/json")
public Flux<List<ItemIgnite>> getAllFluxMono() {
return this.provider.getAllFluxMono();
}
It is working. I guess its because all data is already finished loading and just transferred to the client as it usually would transfer data without using a flux.
What do I have to change to get the flux streaming the data to the web client which requests those data?
EDIT
I have data inside an ignite cache. So my getAllIterator is loading the data from the ignite cache:
public Iterator<Cache.Entry<String, ItemIgnite>> getAllIterator() {
return this.igniteCache.iterator();
}
EDIT
adding flux.complete() like #Simon Baslé suggested:
public Flux<ItemIgnite> getAllFlux() {
Iterator<Cache.Entry<String, ItemIgnite>> iterator = this.getAllIterator();
return Flux.create(flux -> {
while(iterator.hasNext()) {
flux.next(iterator.next().getValue());
}
flux.complete(); // see here
});
}
Solves the 503 problem in the browser. But it does not solve the problem with the WebClient. There is still no data transferred.
EDIT 3
using publishOn with Schedulers.parallel():
public Flux<ItemIgnite> getAllFlux() {
Iterator<Cache.Entry<String, ItemIgnite>> iterator = this.getAllIterator();
return Flux.<ItemIgnite>create(flux -> {
while(iterator.hasNext()) {
flux.next(iterator.next().getValue());
}
flux.complete();
}).publishOn(Schedulers.parallel());
}
Does not change the result.
Here I post you what the WebClient receives:
value :[Item ID: null, Product Name: null, Product Group: null]
complete
So it seems like he is getting One item (out of over 35.000) and the values are null and he is finishing after.
One thing that jumps out is that you never call flux.complete() in your create.
But there's actually a factory operator that is tailored to transform an Iterable to a Flux, so you could just do Flux.fromIterable(this)
Edit: in case your Iterator is hiding complexity like a DB request (or any blocking I/O), be advised this spells trouble: anything blocking in a reactive chain, if not isolated on a dedicated execution context using publishOn, has the potential to block not only the entire chain but other reactive processes has well (as threads can and will be used by multiple reactive processes).
Neither create nor fromIterable do anything in particular to protect from blocking sources. I think you are facing that kind of issue, judging from the hang you get with the WebClient.
The problem was my Object ItemIgnite which I transfer. The system Flux seems not to be able to handle this. Because If I change my original code to the following:
public Flux<String> getAllFlux() {
Iterator<Cache.Entry<String, ItemIgnite>> iterator = this.getAllIterator();
return Flux.create(flux -> {
while(iterator.hasNext()) {
flux.next(iterator.next().getValue().toString());
}
});
}
Everything is working fine. Without publishOn and without flux.complete(). Maybe someone has an idea why this is working.

Where to filter Identity 2.0 claim ticket in a WebAPI app?

ASP.NET apps using OWIN permit multiple Identity sources (Facebook, Google, etc.). Most of the provider-specifc information those sources provide is irrelevant to my app, potentially even large, and I don't want it in my cookies all session. My app is primarily WebAPI, but I suspect the question applies equally to MVC and WebForms.
For now, all I need is an integer account ID. Where/when should I reconstruct the identity, after external authentication?
For example, here is one way I could filter claims:
public ReplaceExistingClaims(ClaimsIdentity identity) {
{
Claim customClaim = GetCustomClaimFromDbForIdentity(identity);
foreach (Claim claim in ClaimsIdentity.Claims) ClaimsIdentity.RemoveClaim(claim);
ClaimsIdentity.AddClaim(customClaim);
}
And following are two different places I could inject those claims changes:
var facebookAuthenticationOptions = new FacebookAuthenticationOptions
{
Provider = new FacebookAuthenticationProvider
{
OnAuthenticated = context =>
{
ReplaceExistingClaims(context.Identity);
return Task.FromResult(0);
}
}
};
Above, I know I can hook an individual provider from Startup IF it provides an Authenticated event. I have two conceptual problems with this. One: it requires me to write and wire up my code separately for each provider I plug in. Two: there is no requirement for providers to provide this event. Both of these make me feel like there must be a different intended insertion point for my code.
public ActionResult ExternalLoginCallback(string returnUrl)
{
ReplaceExistingClaims((ClaimsIdentity)User.Identity);
new RedirectResult(returnUrl);
}
Above, I know I can put code in ExternalLoginCallback. But this happens too late for two reasons. One: The user has already been issued a ticket I consider invalid, but the default [Authorized] considers valid because it's signed by me, and now they are making requests to my site with it. There could even be race conditions here. Two: There is no guarantee the browser will visit this redirect, and I'd prefer from a design perspective if it didn't have to, e.g. to simplify my WebAPI client code.
To the best of my knowledge, the best solution will meet these requirements:
same code applies to all providers
client receives my custom ticket from my server (e.g. without image claims)
client never receives another ticket format from my server
the authentication process requires the minimum possible HTTP round-trips
token-refresh and other core identity features are still available
once a user is [Authorize]d, no further account transformation is necessary
database/repository access is feasible during ticket generation
Some pages I'm researching, for my own notes:
How do I access Microsoft.Owin.Security.xyz OnAuthenticated context AddClaims values?
https://katanaproject.codeplex.com/SourceControl/latest#src/Microsoft.Owin.Security.Facebook/FacebookAuthenticationHandler.cs
https://katanaproject.codeplex.com/workitem/82
https://www.simple-talk.com/dotnet/.net-framework/creating-custom-oauth-middleware-for-mvc-5/
You have to implement DelegationHandler and put all your authentication routines in it.
Register at Application start (DI usage is enabled):
private static void RegisterHandlers(HttpConfiguration config)
{
var authHandler = new MyFacebookAuthHandler();
config.MessageHandlers.Add(authHandler);
}
And this is an example of implementation:
public class MyFacebookAuthHandler : DelegationHandler
{
public override sealed Task<HttpResponseMessage> OnSendAsync(HttpRequestMessage request,
CancellationToken cancellationToken)
{
try
{
// Process credentials
// Probably you have to save some auth information to HttpContext.Current
// Or throw NotAuthorizedException
}
catch(NotAuthorizedException ex)
{
return request.CreateErrorResponse(HttpStatusCode.Unauthorized, ex).ToCompletedTask();
}
catch (Exception ex)
{
return request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex).ToCompletedTask();
}
return base.OnSendAsync(request, cancellationToken);
}
}
The ClaimsAuthenticationManager class is specifically for this.
https://msdn.microsoft.com/en-us/library/system.security.claims.claimsauthenticationmanager(v=vs.110).aspx
Code sample from that reference:
class SimpleClaimsAuthenticatonManager : ClaimsAuthenticationManager
{
public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
{
if (incomingPrincipal != null && incomingPrincipal.Identity.IsAuthenticated == true)
{
((ClaimsIdentity)incomingPrincipal.Identity).AddClaim(new Claim(ClaimTypes.Role, "User"));
}
return incomingPrincipal;
}
}

How to add DropListener to drop text in a draw2d Label

I am Trying to add a dropListener so I can Drop and text into a draw2d Label ,in GEf Editor , Can anyone help how Can I do that. An example will be great.
To respond to drop events on a GEF edit part viewer you have to install on the viewer itself an implementation of org.eclipse.jface.util.TransferDropTargetListener that understands transfers of type org.eclipse.swt.dnd.TextTransfer and that creates some kind of org.eclipse.gef.Request that can be handled by an org.eclipse.gef.EditPolicy installed on the target org.eclipse.gef.EditPart.
You have to understand that both the Request and the EditPolicy allow you to customize the drop behavior on a EditPart basis. As a consequence, I can show you an example that is actually fully functional, but feel free to customize it to your real needs.
First create the TransferDropTargetListener:
public class TextTransferDropTargetListener extends AbstractTransferDropTargetListener {
public TextTransferDropTargetListener(EditPartViewer viewer) {
super(viewer, TextTransfer.getInstance());
}
#Override
protected void handleDragOver() {
getCurrentEvent().feedback = DND.FEEDBACK_SCROLL | DND.FEEDBACK_EXPAND;
super.handleDragOver();
}
#Override
protected Request createTargetRequest() {
return new ChangeBoundsRequest(REQ_ADD);
}
#Override
protected void updateTargetRequest() {
ChangeBoundsRequest request = (ChangeBoundsRequest) getTargetRequest();
request.setEditParts(Collections.EMPTY_LIST);
request.setLocation(getDropLocation());
}
#Override
protected void handleDrop() {
super.handleDrop();
if (getCurrentEvent().detail != DND.DROP_NONE) {
getViewer().setSelection(StructuredSelection.EMPTY);
getViewer().getControl().setFocus();
}
}
#Override
protected Command getCommand() {
String text = (String) getCurrentEvent().data;
List<IEntityPart> editParts = new ArrayList<IEntityPart>();
//
// using the 'text' variable you have to create
// a new EditPart that would eventually replace the old one.
//
editParts.add(createNewLabelPart());
ChangeBoundsRequest request = (ChangeBoundsRequest) getTargetRequest();
request.setEditParts(editParts);
return super.getCommand();
}
}
then install the listener in the graphical viewer constructor using the following statement:
addDropTargetListener(new TextTransferDropTargetListener(this));
finally ensure that an EditPolicy that understands requests of type REQ_ADD (maybe you already added one that extends LayoutEditPolicy or ContainerEditPolicy) is installed on the target EditPart, which is usually done in the AbstractEditPart.createEditPolicies().
To better understand the chain of responsibilities, I suggest you to have a look at the super implementation of the TransferDropTargetListener.getCommand() method.

Automatically detect when storing an object with ServiceStack.Redis

I am looking for a way to subscribe to events like Storing a specific object type to ServiceStack.Redis.
For example I may
using (var redisClient = new RedisClient())
using (var redisMyObjects = redisClient.As<MyObject>())
{
redisMyObjects.Store(myObject);//<-- I want this to trigger an event somehow
}
Is there anything like a OnStore event which I can hook too, anything out of the box? if not, is there any recommendation about how this should be done?
I don't think there is anything you can hook into (could be wrong).
Two options that came to mind:
1 - Make an extension method
2 - Publish a message to store your object and have a handler that listens for a response and does something. This is probably overkill since it's heading into the publish/subscribe realm. But, I think, worth looking into. (Basic example here and see Pub/Sub here).
Extension Method
public static class RedisClientExtensions
{
public static void StoreWithTrigger<T>(this IRedisTypedClient<T> redisClient, T value, Action<T> trigger)
{
redisClient.Store(value);
trigger(value);
}
}
Using ExtensionMethod
public void MyMethod()
{
using (var redisClient = new RedisClient())
using (var redisMyObjects = redisClient.As<MyObject>())
{
redisMyObjects.StoreWithTrigger<MyObject>(new MyObject(), TriggerEvent);//<-- I want this to trigger an event somehow
}
}
private void TriggerEvent<T>(T value)
{
//dosomething
}
Hope this gives you some ideas.

Resources