Asterisk MessageSend to multiple devices using PJSIP - webrtc

I currently have a setup using WebRTC -> Asterisk where I can call and send messages. When I make a call from A -> B all of B's registered devices get called (so if he is logged in several times).
However using MessageSend the SIP message is only delivered to one registered, not all. How can I make it send to all registered devices?
Is it possible, if not is there any other way it can be done inside of Asterisk?
(Using Asterisk 15.5).
Thanks!

Asterisk (at least when using PJSIP) and a given endpoint strips any URI details and will only use the endpoint and does not loop over all registered contacts.
From messge.c 'msg_send_exec'
Gets the outbound from res_pjsip_messaging.c 'get_outbound_endpoint'
/* attempt to extract the endpoint name */
if ((aor_uri = strchr(name, '/'))) {
/* format was 'endpoint/(aor_name | uri)' */
*aor_uri++ = '\0';
} else if ((aor_uri = strchr(name, '#'))) {
/* format was 'endpoint#domain' - discard the domain */
*aor_uri = '\0';
/*
* We may want to match without any user options getting
* in the way.
*/
AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(name);
}
/* at this point, if name is not empty then it
might be an endpoint, so try to retrieve it */
if (ast_strlen_zero(name)
|| !(endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
name))) {
/* an endpoint was not found, so assume sending directly
to a uri and use the default outbound endpoint */
*uri = ast_strdup(to);
return ast_sip_default_outbound_endpoint();
}
From what I understant if you only use a URI (like pjsip:123.12.123.12:1234) it will just look for the default endpoint which will always be the same.

Related

User destinations in a multi-server environment? (Spring WebSocket and RabbitMQ)

The documentation for Spring WebSockets states:
4.4.13. User Destinations
An application can send messages targeting a specific user, and Spring’s STOMP support recognizes destinations prefixed with "/user/" for this purpose. For example, a client might subscribe to the destination "/user/queue/position-updates". This destination will be handled by the UserDestinationMessageHandler and transformed into a destination unique to the user session, e.g. "/queue/position-updates-user123". This provides the convenience of subscribing to a generically named destination while at the same time ensuring no collisions with other users subscribing to the same destination so that each user can receive unique stock position updates.
Is this supposed to work in a multi-server environment with RabbitMQ as broker?
As far as I can tell, the queue name for a user is generated by appending the simpSessionId. When using the recommended client library stomp.js this results in the first user getting the queue name "/queue/position-updates-user0", the next gets "/queue/position-updates-user1" and so on.
This in turn means the first users to connect to different servers will subscribe to the same queue ("/queue/position-updates-user0").
The only reference to this I can find in the documentation is this:
In a multi-application server scenario a user destination may remain unresolved because the user is connected to a different server. In such cases you can configure a destination to broadcast unresolved messages to so that other servers have a chance to try. This can be done through the userDestinationBroadcast property of the MessageBrokerRegistry in Java config and the user-destination-broadcast attribute of the message-broker element in XML.
But this only makes the it possible to communicate with a user from a different server than the one where the web socket is established.
I feel I'm missing something? Is there anyway to configure Spring to be able to safely use MessagingTemplate.convertAndSendToUser(principal.getName(), destination, payload) in a multi-server environment?
If they need to be authenticated (I assume their credentials are stored in a database) you can always use their database unique user id to subscribe to.
What I do is when a user logs in they are automatically subscribed to two topics an account|system topic for system wide broadcasts and account|<userId> topic for specific broadcasts.
You could try something like notification|<userid> for each person to subscribe to then send messages to that topic and they will receive it.
Since user Ids are unique to each user you shouldn't have an issue within a clustered environment as long as each environment is hitting the same database information.
Here is my send method:
public static boolean send(Object msg, String topic) {
try {
String destination = topic;
String payload = toJson(msg); //jsonfiy the message
Message<byte[]> message = MessageBuilder.withPayload(payload.getBytes("UTF-8")).build();
template.send(destination, message);
return true;
} catch (Exception ex) {
logger.error(CommService.class.getName(), ex);
return false;
}
}
My destinations are preformatted so if i want to send a message to user with id of one the destinations looks something like /topic/account|1.
Ive created a ping pong controller that tests websockets for users who connect to see if their environment allows for websockets. I don't know if this will help you but this does work in my clustered environment.
/**
* Play ping pong between the client and server to see if web sockets work
* #param input the ping pong input
* #return the return data to check for connectivity
* #throws Exception exception
*/
#MessageMapping("/ping")
#SendToUser(value="/queue/pong", broadcast=false) // send only to the session that sent the request
public PingPong ping(PingPong input) throws Exception {
int receivedBytes = input.getData().length;
int pullBytes = input.getPull();
PingPong response = input;
if (pullBytes == 0) {
response.setData(new byte[0]);
} else if (pullBytes != receivedBytes) {
// create random byte array
byte[] data = randomService.nextBytes(pullBytes);
response.setData(data);
}
return response;
}

Scan for rabbit exchanges from iOS

I'm trying to write something for my iOS app, using RMQClient that scans for existing exchanges on a rabbitmq server. I came up with this so far.
class AMQPExchangeScanner {
static func scan() {
let connection:RMQConnection = RMQConnection(uri: "amqp://user:user#abc.def.com:5672", delegate: RMQConnectionDelegateLogger())
connection.start()
for exchangeName in Foo.pastExchanges() {
let channel = connection.createChannel()
let exchange = channel.fanout(exchangeName, options: .passive)
"scan \(exchangeName) \(exchange)".print()
channel.close()
}
}
}
I'm not sure how to determine if the exchange actually exists though. The print() statement prints exchange objects. I get a whole bunch of output in the console. I had hoped that I would get back an optional so I could do something like
if let exchange... {
}
But that doesn't appear to be the case. How do I programmatically check if the exchange is real or not? Or get at those errors? Do I need my own connection delegate and have to parse a bunch of text?
The best way to scan for existing exchanges is using rabbitmq management HTTP API - it would be under /api/exchanges.
For a single exchange you could call the declare method, with passive parameter set accordingly (quoting from here):
for the declare method
This method creates an exchange if it does not already exist, and if
the exchange exists, verifies that it is of the correct and expected
class.
for the passive bit
If set, the server will reply with Declare-Ok if the exchange already
exists with the same name, and raise an error if not.
...
If not set and the exchange exists, the server MUST check that the existing exchange has the same values for type, durable, and arguments fields. The server MUST respond with Declare-Ok if the requested exchange matches these fields, and MUST raise a channel exception if not.

Interfax developer account configuration for multiple recipients

I want to configure an interfax account for sending and receiving faxes.
Can anyone tell me how to send/receive a test fax?
I know about the .sendFax() and .GetList() methods, but how do I send fax to myself (in test account)?
I followed the article,
Receive incoming faxes via callback to a web application
it works fine. But it only gives you intimation that you have received fax.
Edit:
You can set feedback url and use the parameter which they asked. When interfax will receive fax for you, it will send it to your feedback url and it will go directly to your database (If you set this in page load event).
You can use following code
MessageItem[] faxList = null;
Inbound inbound = new Inbound();
ListType messageListType = ListType.NewMessages;
int interFaxResult = inbound.GetList(AppConfig.InterfaxUsername, AppConfig.InterfaxPassword, messageListType, AppConfig.InterfaxMaxitems, ref faxList);
if (interFaxResult == 0)
{
// Save faxes in DB
}

Options for creating dynamic filters (xpath) in a Camel route

I've the following static route that is loaded at my server startup. It listens for UDP messages on a port and pushes these messages to the seda queue defined in the route below.
from("mina:udp://hostipaddress:9998?sync=false").wireTap(
"seda:sometag?size=100&blockWhenFull=true&multipleConsumers=true");
Now I can have multiple clients that want to receive/subscribe to these messages. They also want to dynamically select which feeds they need.
Each client send a subscription request (REST) to the server (implemented using Spring-MVC, Jetty, Camel).
As soon as the server receives a request I create a new Camel route that looks like:
from("seda:sometag?multipleConsumers=true")
.routeId(RouteIdCreator.createRouteId(toIP, toPort, "sometag"))
.filter()
.xpath(this.xpathFilter).unmarshal().jaxb("sometag").marshal()
.json().wireTap("mina:udp://client_ip_address:20001?sync=false");
Once this route is deployed it will start to send UDP messages to the client_ip_address: 20001 (as specified in the dynamic route above.)
The client can send different filters to the server.
In case this server receives the new filter it does the following
1. checks if there is a route running (based on client ip and port)
2. If there is route running it stops that route and deletes this route with the older filter
3. It then recreates a new route which differs from the last route only in the xpathfilter.
My issue is that step 2 takes a lot of time (to stop and restart)
Is there is a way to resolve this issue?
Basically I want to change the XPath expression in the route without stops/migrating the route.
PS: I've also posted this on the official Camel mailing list.
You can try to store the xpath filter in a database (basically a simple table with the ip and the filter associated) when you receive a new subscription. Then you can read this filter from the database in the route, and use it as a filter.
from("seda:sometag?multipleConsumers=true")
.routeId(RouteIdCreator.createRouteId(toIP, toPort, "sometag"))
.setHeader("ip").constant(client_ip_adresse)
.filter().xpath(simple("${bean:xpathFilterComponent?methode=find}"))
.unmarshal().jaxb("sometag").marshal()
.json().wireTap("mina:udp://client_ip_address:20001?sync=false");
And your bean should look like
public class XpathFilterCompnent {
public void save(String ip, String filter){
//store a filter for an ip in database, when a subscription is received
}
public void find(#Header("ip") String ip){
String filter = ... //retreive filter from database
return filter;
}
}

How to check email using a vb.net application

I am looking for a vb.net code for receiving e-mails without using any 3rd party libraries. I want to check Unread messages, Inbox and Sent messages. A Working sample is appreciated.
What is the default port for SMTP , is it port 25 (is it the same for all SMTP mail servers?). Which is more flexible in my case POP3 or IMAP ?
Edit:
Someone please give me a sample working code for receiving mail using lumisoft (pop) in vb.net
From lumisoft Help.
/*
To make this code to work, you need to import following namespaces:
using LumiSoft.Net.Mime;
using LumiSoft.Net.POP3.Client;
*/
using(POP3_Client c = new POP3_Client()){
c.Connect("ivx",WellKnownPorts.POP3);
c.Authenticate("test","test",true);
// Get first message if there is any
if(c.Messages.Count > 0){
// Do your suff
// Parse message
Mime m = Mime.Parse(c.Messages[0].MessageToByte());
string from = m.MainEntity.From;
string subject = m.MainEntity.Subject;
// ...
}
}
Pop is more supported and most servers have it on if you want to implement your own pop service a good place to start is the rfc.