We need to invoke URL contains the caller number each time there is an inbound call, we are using Grandstream UCM6204 PBX.
There is a function called SendURL() that can be used through Asterisk, I connected to Asterisk using PuTTy but I'm not sure what to do next?
After doing some research, I found that I couldn't have direct access to Asterisk through UCM devices, which will not allow us to modify the dial plan.
Is the only approach by creating a third party application to communicate with AMI and do the job? Problem with this scenario that this application should be online and working 24/7.
I wrote C# code to accomplish this, but it is not working as expected.
public FormMain()
{
InitializeComponent();
AstCon = new ManagerConnection(ConfigurationManager.AppSettings["astHost"],
int.Parse(ConfigurationManager.AppSettings["astPort"]),
ConfigurationManager.AppSettings["astUser"], ConfigurationManager.AppSettings["astPass"]);
AstCon.NewState += astCon_NewState;
AstCon.ConnectionState += astCon_ConnectionState;
try
{
AstCon.Login();
}
catch (Exception ex)
{
MessageBox.Show(
$"Error connecting to {ConfigurationManager.AppSettings["astHost"]}. Error: {ex.Message}");
// Terminate Application
Application.Exit();
}
}
private void astCon_NewState(object sender, NewStateEvent e)
{
if (e.ChannelStateDesc.ToLower() == "ring" && e.Connectedlinenum == "6401")
{
if (ConfigurationManager.AppSettings["ScreenPopPath"] != null)
{
var runString = ConfigurationManager.AppSettings["ScreenPopPath"];
runString = runString.Replace("{callerid-number}", e.CallerId);
Process.Start(runString);
}
}
}
void astCon_ConnectionState(object sender, ConnectionStateEvent e)
{
connectionStateLbl.Text = AstCon.IsConnected() ? $"Connected to: {AstCon.Username}#{AstCon.Hostname}" : $"Disconnected, reconnecting to {AstCon.Hostname}...";
}
}
You can use CURL function. But for invoke it need understand PBX dialplan and hooks
You can use external AMI app.
You can read CEL events in database.
Related
I'm implementing an enricher pattern (https://www.enterpriseintegrationpatterns.com/patterns/messaging/DataEnricher.html) using a command/consumer queue where the consumer is the enricher and publishes the enriched message to a separate endpoint (SQL database in this case). The consumer is running as a HostedService which implements cancellation token.
Because I'm consuming commands from one transport and publishing events to another there is a possibility that the transport I'm publishing to is down while the one I'm consuming from is up. In that case I'd like to log an error and stop my Hosted service. However, I cannot see how that would work since whatever calls the Handle method already handles exceptions, and I cannot access my cancellation token. Does anyone have any ideas?
This is a draft of what I want to do.
public async Task Handle(EditedEventData message)
{
var enricher = _enricherFactory.GetEnricher(message);
object #event = await enricher.EnrichAsync(message);
var transformers = _transformerFactory.GetTransformers(message);
var messages = new List<object>();
foreach (var transformer in transformers)
{
messages.AddRange(transformer.Transform(#event, message));
}
foreach (var item in messages)
{
try
{
await _bus.Publish(item);
}
catch (Exception ex)
{
_logger.LogCritical("Publishing event message {#item} failed with error {ex}", item, ex);
//how do I exit from here?
}
}
}
If I were you, I would come up with some kind of application service, e.g. IApplicationControlService, which you can configure to be injected into your handlers using whichever IoC container you're using.
It could look somewhat like this:
public interface IApplicationControlService
{
void RequestApplicationShutdown();
}
and then your code could simply
public class YourHandler : IHandleMessages<EditedEventData>
{
readonly IApplicationControlService applicationControlService;
public YourHandler(IApplicationControlService applicationControlService)
{
this.applicationControlService = applicationControlService;
}
public async Task Handle(EditedEventData message)
{
// (...)
foreach (var item in messages)
{
try
{
await _bus.Publish(item);
}
catch (Exception ex)
{
_logger.LogCritical("Publishing event message {#item} failed with error {ex}", item, ex);
applicationControlService.RequestApplicationShutdown();
}
}
}
}
to request the application be stopped, when an error occurs.
An implementation of IApplicationControlService could then be something like
public class BruteForceApplicationControlService : IApplicationControlService
{
public void RequestApplicationShutdown()
{
Environment.FailFast("you should probably not do THIS 😉");
}
}
or something more gentle 😁 – the point is, that you will be able to provide a way to request your application to shut down "from the outside", most likely from the place where your application is assembled (i.e. the "composition root")
if i receive a HttpServerRequest in a Handler, is it somehow possible to publish the request?
I want to implement a small demo website with an index.html and an unknown number of sub sites. At first there should be a main vert.x module, which starts the HttpServer. In this main module it should be possible to add other dependent modules. I will call them submodules now. I don't know how many submodules i will have later, but each submodule should contain the logic to handle the http response for a specific URL (the sub html files). I guess i have to do the same for the WebSocketHandler...
A small example of the code inside the start():
//My Main Module:
vertx.createHttpServer().requestHandler(new Handler<HttpServerRequest>() {
public void handle(HttpServerRequest req) {
vertx.eventBus().publish("HTTP_REQUEST_CONSTANT", req);
}
}).listen(8080);
// My submodule 1
vertx.eventBus().registerHandler("HTTP_REQUEST_CONSTANT", new Handler<HttpServerRequest>() {
#Override
public void handle(HttpServerRequest req) {
if (req.uri().equals("/")) {
req.response();
}
}
});
// Other submodules which handles other URLs
Or any other solutions? I just don't wanna have the logic for sub sites in the main module.
Edit: Or could i call the vertx.createHttpServer() method in each submodule?
I have a similar Vert.x based application and I ended up doing the following:
I have a HttpServerVerticle that is started from the MainVerticle. There I created an HttpServer with several matchers. Each matcher receives a request and forwards it to a dedicated verticle through theEventBus. Upon getting the response from a dedicated verticle it writes the answer to the response.
Here is a code snippet:
RouteMatcher restMatcher = new RouteMatcher();
EventBus eventBus = vertx.eventBus();
HttpServer httpServer = vertx.createHttpServer();
restMatcher.post("/your/url",
r -> {
r.bodyHandler(requestBody -> {
final int length = requestBody.length();
if(length == 0) {
//return bad request
r.response().setStatusCode(HttpResponseStatus.BAD_REQUEST.code());
r.response().end();
return;
}
eventBus.send("your.address.here",
requestBody.getString(0, length),
new Handler<Message<JsonObject>>(){
#Override
public void handle(Message<JsonObject> message) {
//return the response from the other verticle
r.response().setStatusCode(HttpResponseStatus.OK.code());
if (message.body() != null) {
r.response().end(message.body().toString());
}
else{
r.response().end();
}
}
});
});
});
httpServer.requestHandler(restMatcher);
httpServer.listen(yourPort,yourHost);
In the dedicated verticle you register a listener to the address:
vertx.eventBus().registerHandler("your.address.here", this::yourHandlerMethod);
The handler method would look something like the following:
protected void yourHandlerMethod(Message<String> message){
// do your magic, produce an answer
message.reply(answer);
}
This way you separate your logic from your HTTP mappings and can have different pieces of logic in separate verticles using multiple event bus addresses.
Hope this helps.
I am working on making a scheduler, just like Windows Scheduler using Quartz.Net.
In Windows Scheduler, there is an option to stop a task from running if it takes more than the specified time. I have to implement the same in my scheduler.
But I am not able to find any extension method/setting to configure Trigger or Job accordingly.
I request some inputs or suggestions for it.
You can write small code to set a custom timout running on another thread. Implement IInterruptableJob interface and make a call to its Interrupt() method from that thread when the job should be interrupted. You can modify the following sample code as per your need. Please make necessary checks/config inputs wherever required.
public class MyCustomJob : IInterruptableJob
{
private Thread runner;
public void Execute(IJobExecutionContext context)
{
int timeOutInMinutes = 20; //Read this from some config or db.
TimeSpan timeout = TimeSpan.FromMinutes(timeOutInMinutes);
//Run your job here.
//As your job needs to be interrupted, let us create a new task for that.
var task = new Task(() =>
{
Thread.Sleep(timeout);
Interrupt();
});
task.Start();
runner = new Thread(PerformScheduledWork);
runner.Start();
}
private void PerformScheduledWork()
{
//Do what you wish to do in the schedled task.
}
public void Interrupt()
{
try
{
runner.Abort();
}
catch (Exception)
{
//log it!
}
finally
{
//do what you wish to do as a clean up task.
}
}
}
I wanted to checking my database table for periodically.So how can i create a webservice and how can i configure it.
basically what you need is, something which is always running and hence can make periodic calls.
There are a number of ways to do it
(Since ASP.NET hence) You can make a Windows Service, and host this service on your server, since server is always running, this Windows Service will make request to your webservice, update database or watever you want
You can use SQL Jobs to do it. You can call a webservice from a job, through a SSIS (Sql Server Integration Service) Package. These packages are very very robust in nature, they can do almost any db activity that you want them to do, including webservice request.
And finally, you can use third party tools such as Quartz.Net
References:
this is how you can call a webservice through a windows service.
this is how you can call a webservice through a ssis package.
this is how you can integrate a SSIS package in a SQL Job
this is how you can create a windows service
this is how you can create a SSIS package
this is how you can get answer/tutorial of almost anything
Example:
simplest of all of these would be a Windows Service. Making a windows service and hosting it on the machine(server) is very easy, use one of the given links (specially the last link). Usually, in Windows Service, you do some activity in OnStart event. you can place a timer inside this OnStart and upon TimerTick(), you can request your webservice.
something like this:
class Program : ServiceBase
{
System.Timers.Timer timer;
static void Main(string[] args)
{
ServiceBase.Run(new Program());
}
public Program()
{
this.ServiceName = "My Service";
}
protected override void OnStart(string[] args)
{
base.OnStart(args);
InitializeTimer();
}
protected override void OnStop()
{
base.OnStop();
//TODO: clean up any variables and stop any threads
}
protected void InitializeTimer()
{
try
{
if (timer == null)
{
timer = new System.Timers.Timer();
timer.Enabled = true;
timer.AutoReset = true;
timer.Interval = 60000 * 1;
timer.Enabled = true;
timer.Elapsed += timer_Elapsed;
}
}
catch (Exception ex)
{
Utility.WriteLog("Exception InitialiseTimer : " + ex.Message.ToString());
}
finally
{
}
}
protected void timer_Elapsed(object source, System.Timers.ElapsedEventArgs e)
{
TimerTick();
timer.Interval = 60000 * Convert.ToDouble(ConfigurationManager.AppSettings["TimerInerval"]);
}
private void TimerTick()
{
try
{
DownloadFromFTPandValidate objDownLoadandValidate = new DownloadFromFTPandValidate();
objDownLoadandValidate.ProcessMain();
}
catch (Exception ex)
{
Utility.WriteLog("Exception InitialiseTimer : " + ex.Message.ToString());
}
}
}
Here, class DownloadFromFTPandValidate wraps the code to db activity. It shd give you an idea.
You will need a job scheduler for periodical task. I recommend you a good one. Check out this link: http://quartznet.sourceforge.net/
Why not using a trigger on your table which runs a stored procedure once data was modified, then use the xp_cmdshell to access the commandline form your stored procedure so you can run for example a batch file or whatever.
I'm using the following HttpModule to stop a couple of IPs that constantly attempt to spam my contact form. I don't get the spam as they trigger System.Web.HttpRequestValidationException but I do get the Exception report in my email inbox. It's not quite as annoying but almost.
I eventually want to test against either a list of IPs from the database or maybe implement the HttpBL api to test against known blacklisted IPs but doing this on every request seems to be overkill. Either way I do it, whether using IPs in the database or making requests to an external blacklist at every page request surely seems unnecessary. Can you point me in the direction of checking this once and if the IP passes the test the first time to stop checking?
using System;
using System.Web;
namespace DomainModel.Services
{
public class BlockIPModule : IHttpModule
{
public void Dispose() {}
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(Application_BeginRequest);
}
private void Application_BeginRequest(object sender, EventArgs e)
{
HttpContext context = ((HttpApplication)sender).Context;
string currentIP = context.Request.UserHostAddress;
if (!IsIpValid(currentIP))
{
context.Response.StatusCode = 403;
}
}
private bool IsIpValid(string checkIP)
{
return (checkIP != "213.5.70.205" && checkIP != "188.92.75.82");
}
}
}
updated code removed - terrible idea.
HTTP is stateless, and therefore, you really do have to check each request. You could cache the blacklist of IP addresses so you don't have to load it each time, but you'll still need to always run some test.
If you have control over it, the other option would be to do some filtering on your router. That would free your code from having to do it.