If you subcribe a Consumer in Flex, you need to assign a ChannelSet to the Consumer. In my case, I create a ChannelSet and then add a Channel to that ChannelSet.
Apparently, the added channel is the current channel of the ChannelSet. But what if I would add two Channels to the ChannelSet? Do I need to set the currentChannel before subcribing?
If there are two channels in the ChannelCet, and I trigger the login method on the ChannelSet, will both Channels be authenticated and connected?
The ChannelSet will use the Channel that was added first and fall back to the other channels in case a Channel cannot be reached. The currentChannel property is a read-only property that points to the channel currently in use.
Here's the info from the docs:
Regardless of clustering, if a Channel
cannot connect or looses connectivity,
the ChannelSet will advance to its
next available Channel and attempt to
reconnect. This allows the ChannelSet
to hunt through Channels that use
different protocols, ports, etc., in
search of one that can connect to its
endpoint successfully.
About logging in: calling login() on the ChannelSet will use the same linear lookup of Channels and will authenticate on the first Channel. If you add another channel, it will be added to the list of channels and if it needs to be used, the ChannelSet will authenticate on the new Channel as well (since the credentials are saved). At least, that is what I can deduct from looking at the code of ChannelSet in the Flex SDK.
Related
I have seen examples that manually keep track of users that are connected but is there a way to determine if a client is connected when using IUserIdProvider?
IUserIdProvider interface allows you to specify how will SignalR assign user id to connection based on request. It doesn't have any direct support for monitoring if user is online.
To monitor online presence, you have to handle OnConnected, OnDisconnected and OnReconnected events in hub and store information about users in some storage (for example static class, database, etc.). Example can be found here: http://www.asp.net/signalr/overview/guide-to-the-api/mapping-users-to-connections#inmemory
The SignalR server hub does not retain a list of groups so I assume that when I send out a broadcast message to a group it is sent to everyone connected to the hub and the clients filter out the message based on their participating groups. If I send a message to a specific group it seems that it is sent down the wire to everyone and can be intercepted by someone not in the specified group who knows how to use a browser debugger. If I want to have a secure broadcast (not even sent over the wire to some clients) I assume I need separate hubs or do I need separate sub domains?
Separate hubs do not sound like a good idea. While you probably can validate users on connect and refuse connections for non-authorized users what if you need a way to create isolated hubs dynamically. If however this functionality is enough for you you can use the Authorize attribute to secure either hubs or hub methods.
For cases where you do need to replicate the same functionality for different groups of users you can use SignalR groups but you need to verify that the user belongs to the group each time he connects. The SignalR documentation contains an example on how to do that verification. Note that everyone can try to connect to your groups and you should validate upon connection and not depend on the fact that you do not call the add method for a certain client.
SignalR only sends to the clients in the group. It's just a design issue that you can't retrieve a list of connections in a group. Groups, as pretty much everything else in SignalR, are subscription based, so the server knows which connections need to receive a message, but it's buried deep in the internals.
I would point you to the relevant server-side code, but don't have time to look it up right now.
It's easy to see in the client-side code though since it's not a lot of code - so you can verify there is no filtering going on there.
Groups also aren't separated per hub.
I'm making a web application which should be able to monitor calls on my Asterisk server. I can connect to ARI with Javascript WebSocket on URL ws://(host):8088/ari/events?app=dialer and it works. The problem is that I only get events from calls that are made over ARI. Calls made from other clients like Zoiper are not registered. On the other hand, Asterisk has AJAM which uses long polling on http://(host):8088/rawman?action=waitevent and it registers calls from all the clients, (ARI, Zoiper and others) but there's only information who is calling (caller), not whom (callee).
So, my question is, how can I get real time call events that show who is calling who, from all the clients, (preferably) with WebSockets. Thanks.
ARI uses a subscription based model for events. Quoting from the documentation on the wiki:
Resources in Asterisk do not, by default, send events about themselves to a connected ARI application. In order to get events about resources, one of three things must occur:
The resource must be a channel that entered into a Stasis dialplan application. A subscription is implicitly created in this case. The
subscription is implicitly destroyed when the channel leaves the
Stasis dialplan application.
While a channel is in a Stasis dialplan application, the channel may interact with other resources - such as a bridge. While channels
interact with the resource, a subscription is made to that resource.
When no more channels in a Stasis dialplan application are interacting
with the resource, the implicit subscription is destroyed.
At any time, an ARI application may make a subscription to a resource in Asterisk through application operations. While that
resource exists, the ARI application owns the subscription.
So, the reason you get events about a channel over your ARI WebSocket is because it went into the Stasis dialplan application. That isn't, however, the only way to get events.
If you're interested in events from other event sources, you can subscribe to those resources using the applications resource. For example, if I wanted to receive all events that were in relation to PJSIP endpoint "Alice", I would subscribe using the following:
POST https://localhost:8080/ari/applications/my_app/subscription?eventSource=endpoint:PJSIP%2FAlice
Note that subscriptions to endpoints implicitly subscribe you to all channels that are created for that endpoint. If you want to subscribe to all endpoints of a particular technology, you can also subscribe to the resource itself:
POST https://localhost:8080/ari/applications/my_app/subscription?eventSource=endpoint:PJSIP
ws://(host):8088/ari/events?app=dialer&subscibeAll=true
Adding SubscribeAll=true make what you want =)
May be help someone:
Subscribe to all events on channels, bridge and endpoints
POST http://localhost:8088/ari/applications/appName/subscription?api_key=user:password&eventSource=channel:,bridge:,endpoint:
Unsubscribe
DELETE http://localhost:8088/ari/applications/appName/subscription?api_key=user:password&eventSource=channel:__AST_CHANNEL_ALL_TOPIC,bridge:__AST_BRIDGE_ALL_TOPIC,endpoint:__AST_ENDPOINT_ALL_TOPIC
For more clarity regarding what Matt Jordan has already provided, here's an example of doing what he suggests with ari-py:
import ari
import logging
logging.basicConfig(level=logging.ERROR)
client = ari.connect('http://localhost:8088', 'username', 'password')
postRequest=client.applications.subscribe(applicationName=["NameOfAppThatWillReapThisEvent-ThisAppShouldBeRunning"], eventSource="endpoint:PJSIP/alice")
print postRequest
Hy,
I'm using the signalR library on a project to handle an notification and chat modules. I've a table on an database to keep a track of online users.
The HUB for chat is inheriting IDisconnect where i disconnect the user. After disconnecting the user, i warm the users about that event. At this point, i check if the disconnect user is the client. If it's, then i call an method on HUB to reconnect the user (just update the table).
I do this because with the current implementation, once the user closes a tab on the browser it calls the Disconnect task but he could have another tab opened.
I've not tested (with larger requests) this module yet, but on my development server it could take a few seconds between the IDisconnect event, and the request from the user to connect again.
I'm concerned with my implementation to handle disconnected users from the chat but i can't see another way to improve this.
If possible, could someone give me a advice on this, or this is the only solution that i've?
Update: I ended up using a singleton class to store all the users and their connections id from signalr. This way i can get the id from user during the disconnect task (at this point you don't have any httpcontext to get the user information, but you can always get the user id with the connection id of signalr from the array in the singleton class).
20-02-2013 Although the above solution was doing the job, i had the need to scale my project. My solution was to use Redis to store all user connections, and take benefit of key expiration time on disconnect events. During the reconnect i check if the key is in pending state (gonna expire in a few minutes).
You can check out how JabbR, a multi-room chat application built on top of SignalR, solves this problem: https://github.com/JabbR/JabbR/blob/master/JabbR/Hubs/Chat.cs
It basically keeps a 1:N mapping of User<->ConnectionId, so when the last connection is disconnected the user can be marked as "offline".
I'm trying to create a module for a flex application, and I want to send notifications to clients. I've been looking at the BlazeDS messaging service to push out the notifications to clients, but I want to be able to send certain updates to certain clients. The Flex notification framework doesn't seem to allow this - if we have a field in the message with a value of the user's user id for example, any client could theoretically subscribe to all messages for any given user id, and there's no verification on the server side to make sure that the client that has subscribed is logged in as that user id.
Is there something I've missed here, or is the best way to handle this writing my own polling mechanism on the client side?
There is indeed a solution for this in the APIs. The first step is to write a class which extends the FlexClientOutboundQueueProcessor class. You need to override one method:
public void add(List outboundQueue, Message message);
Basically all you need to do is write some logic to determine whether you should make the following call:
outboundQueue.add(message)
Simply put, if you don't add the message to the queue, then the message won't be pushed to the client. The other important method in this class is:
FlexClient getFlexClient()
Which you can use to get the associated FlexSession and ultimately the authentication information that presumably exists in your app.
Once this is done, you just need to register the processor with the appropriate channels. Simply add this element within the "properties" element of the "channel-definition" element:
<flex-client-outbound-queue-processor class="com.foo.YourProcessor"/>
I believe you can also specify a nested "properties" element for the queue processor but I don't believe it's required.
You can use subtopics for this as long as you disable wildcard subscriptions.