Skip to main content

[CAFE] using presence in CAFE

Posted by erikvandervelden on April 13, 2010 at 7:36 AM PDT

In my last blog entry I described the generic user procedures as used in CAFE.
These procedures can be used for registration and various parts of presence.

In this installment I will go a bit deeper into the presence related user procedures, showing how to publish presence information on behalf of a user and subscribe to presence information.
And since presence information in CAFE is (currently) bound to the groups, I'll also show a bit of the group management.

Basic presence concepts

In brief; Presence gives information about the status of a user.
This can be as simple as "I'm busy" or as complicated as "I have these and these services, I'm willing to chat, but not interested in phone calls,  I have these devices, I'm on holiday, I'm in a happy mood." etc.

The presence documents describing the status are normally presented as a XML document in the PIDF format.
When using CAFE you do not have to be able to create or parse such documents yourselves, as CAFE provides APIs for accessing the most commonly used elements in this document.
For the set of elements we make accessible via the API we follow standards such as OMA SIMPLE and RCS.

I'll try to briefly describe how presence works in an IMS network. Only the basics, as there is much more to it then I have space for here.

Presence is done by a publish-subscribe model.

presencesource aka publication

A user publishes her presence in a presence server somewhere in the network. Or an application can do it on behalf of the user, using CAFE. The presenceSource userprocedure is used for this.
A publication has a certain expiry time (as explained in the previous blog entry).

presencewatcher aka subscription

Other users (or applications on behalf of a user) can access or watch this presence information if they are authorized to do so. The CAFE user procedure object for this is the presenceWatcher.

There are two ways to access this information, by polling or by subscribing.
Just like publications, subscriptions have a certain expiry time. In fact, the polling method is implemented as subscription that immediately expires.
When starting a subscription you will get the current status.
When the status changes (e.g., because the user publishes a new presence document), the subscriber is asynchronously notified.

grouping

Normally, a user is not interested in the presece information of just one other subscriber but wants to keep track of the presence information of a group of subscriber, e.g., all his friends, or all the colleagues.
For this group management comes into the picture. A user can create groups and subscribe to groups. Then the notifications can contain multiple presence documents of group members, but otherwise there is not much difference.

Note that in CAFE we only support group based subscriptions at the moment, although the plan is to add user-based subscriptions later.

 Authorization

It would not be good if just everybody could see your presence. In order to manage who is authorized to see its presence a user can create a set of rules.
Rules are created via XCAP and can become quite complex. However, there are some standard templates for rules for which CAFE offers support.

  • RCS - this is a reprocical system where a you have one group of users which you want to monitor (called the rcs group). All the users on this list automatically are allowed to watch your presence as well.
  • OMA white list - you have to explicitly allow uses to access your status. Users that are not explicitly allowed are not authorized to see your status.
  • OMA black list - this is the reverse, only if you explicitly disallow somebody that user will not be allowed to access your status, everybody else is.
  • For all of these there is also a polite variant. If somebody is politely blocked, it means that he does not know he is blocked. Instead he will see an almost empty presence status and not the actual presence.

For convenience purposes the default behaviour of the simulator is to allow access to the presence data if no rules have been defined.
Probably this is not inline with an actual IMS network and might change without warning in future releases :-)

datamodel

I'll give a very short overview of the presence document here.

A presence document normally consists of

  • zero or one personInformation element
  • zero or more service information elements
  • zero or more device information elements

The person information element contains information about the person (suprise), like the moods, the activities and the availability (called overridingWillingness in OMA).
There are some convenience methods defined in CAFE to set both the activity and the willingness, as these is the most used combination to represent the status.

The service information element gives information about the availability of the different services the user has (chat, video, etc.)

The device information can give information about devices used by the services and their status.

In general the person information is probably the most interesting, unless you are catering for an RCS user, in which case service information gets interesting as well.

All the elements can have free text in the form of notes.

How does this map to CAFE?

 I will show with some code fragments how to use these APIs in CAFE. In the next blog I wil try show some consistent application, e.g., combining presence with call setup.

configuration

In an IMS network the group management would work against a XCAP server located in the network and the publications and subscriptions would be routed to a presence server.
However, CAFE comes with its own simulator, that offers a subset of the IMS functionality.

In order to use the simulator the following configuration has to be in your communication  bean.

@CommunicationBean(domainProxy = "<sip:127.0.0.1:5060>",
                   xcapRoot = "http://127.0.0.1:8080/PresenceAndGroupManagementSimulator")
public class SimpleCommsBean {
...

This has to be present even if your application is not interested in any events!

If you want to communicate with a IMS network the addresses have to be modified accordingly,.

publication

Here is how an application would publish information on behalf on a user (e.g., in an HTTP servlet or communication bean).

    @Context
    CommunicationSession session;

....

    private void publishStatus() {
        PresenceSource ps = session.createPresenceSource("test");
        ps.createPersonOnlineActivity("playing2");
        ps.update();
    }

Typically an application would publish the presence once a user logs in to the application and unpublish it when the user logs out.
The unpublish would done by invoking end() on presenceSource.

The expiry handling would be done in a communication bean and could look something like this:

@CommunicationBean(domainProxy = "<sip:164.48.50.97:5060>",
                   xcapRoot = "http://127.0.0.1:8080/PresenceAndGroupManagementSimulator")
public class SimpleCommsBean {
    @Context
    CommunicationSession session;

    @Context
    CommunicationContext context;

    @UserProcedureEvent(type = UserProcedureEvent.Type.STARTED)
    void handleStarted() {
        System.err.println("SimpleCommsBean.handleStarted()");
    }

    @UserProcedureEvent(type = UserProcedureEvent.Type.REFRESHED)
    void handleRefreshed() {
        System.err.println("SimpleCommsBean.handleRefreshed()");
    }

    @UserProcedureEvent(type = UserProcedureEvent.Type.ABOUTTOEXPIRE)
    void handleAboutToExpire() {
        if (userIsStillLoggedIn(context.getParticipant().getName())) {
            context.getUserProcedure().update();
        }
    }

    @UserProcedureEvent(type = UserProcedureEvent.Type.REFRESHFAILED)
    void handleRefreshFailed() {
        System.out.println("SimpleCommsBean.handleRefreshFailed()");
    }
}

Currently there would be only one publication document per CAFE application per user. So if an application tries to create the same presencesource, it will actually retrieve the existing one if this is still valid.
This is a limitation, as normally the application could in fact publish multiple documents per user, which would be aggregated by IMS into one document per user.
One of the ways in which the simulator is not on par with a full IMS network is that the simulator does not do an aggregation of different presencesource for the same user into one presence document. So watch out!

authorization

Like I stated above, by default the simulator allows access to presence data, but to be more consistent we should probably create authorization documents.

You can do this conditionally, i.e., only if no rules template has been used yet, and when the user logs-in.
This is what it would look like.
(We assume that service was injected as above).

private void conditionallyCreateRuleSet() {
    RuleSetType type = service.getRuleSetType("alice");
    if (type == null) {
        service.createRuleSetFromTemplate("alice", RuleSetType.OMA_BLACKLIST);
    }

group management

Since we do not allow subscription to individual users, we have to create a group before we can subscribe. Groups are persistent entities, normally.
However, the simulator does not store anything persistently (yet). This means that it is only persistent as long as you do not restart the AS and do not undeploy the last CAFE application....

Here is how you create a group and add some users to it. You can also get existing groups.

    Group myfriends = service.createGroup("myfriends", "alice");
    myfriends.createOrModifyBuddy("bob", "bobby");
    myfriends.createOrModifyBuddy("carol", "my best friend");

subscription

Finally, we are ready to subscribe to a group.
Again, since subscription is user procedure, it does have a lifetime and needs refresh as described in the previous blog entry or as done above for presenceSource.

A subscription that has an expiration time of 0 is also called a polling subscribe.

    PresenceWatcher watcher = myfriends.startWatching(session);
    watcher.setExpirationTime(new Date()); // create with "now" or something in the past
    // TODO we should probably allow null as a special value meaning "now"
    watcher.update();

If no expiration is specified the default is used (3600 seconds).

    PresenceWatcher watcher = myfriends.startWatching(session);
    watcher.update();

 Now we are ready to receive asynchronous notifications.

Create a new communication bean or modify your existing communication bean to handle the notification event.
You can then access the status updates in the message or the cached

    @UserProcedureEvent(type = UserProcedureEvent.Type.NOTIFICATION)
    void handleNotification() {
        PresenceMessage message = (PresenceMessage) context.getUserProcedure().getMessage();
        PeerPresentity[] modifiedPeers = message.getPeerPresentities();
        for (PeerPresentity peerPresentity : modifiedPeers) {
            // only the just modified ones
            if (peerPresentity.getSubscriptionState().equals(SubscriptionState.ACTIVE)) {
                PresenceDocument peerstatus = peerPresentity.getPresenceDocument();
                peerstatus.getXML();
                String[] activities = peerstatus.getPersonInformation().getActivities();
                // should add NULL check
            } else {
                System.out.println("subscription not (yet) accepted - state is " +
                       peerPresentity.getSubscriptionState());
            }
        }
        // cached version of all the statuses including the latest received ones
        Map<String, PeerPresentity> allPeers =
                     ((PresenceWatcher) context.getUserProcedure()).getPeerPresentities();
        // allow easy access to a specific user
        PeerPresentity johnsStatus = allPeers.get("sip:john@example.com");
        // TODO this should be fixed so that get("john") also works....

WatcherInfoSubscriber

There is one missing, which is the watcherInfoSubscriber.
This can be used to subscribe to be notified when other people want to start watching your presence.

 

The idea is that when somebody starts watching you get notified and can accept or reject this specific user.
For the example used above, the black list, it is not needed to actually take an explicit action when somebody subscribes, the default action is to allow the watcher.
But for RCS and the whitelist variants a presenceWatcher starts out in the pending state until the user explicitly allows or blocks the watcher.

Unfortunately, this is not fully implemented.

XCAP

Some things, like the group management and the rules management are implemented using XCAP.
CAFE only offers a small subset of all the XCAP functionality via its API.
However, CAFE comes with an XCAP library that allows for more finegrained manipulation, e.g., if you want to add your own rules to the created template.

The XCAP library can be the topic of a separate blog entry.

Conclusion

This give just a taste of the user procedures for presence.
So use the presenceSource for publishing presence.
For subscribing, create a group of users, and create a presenceWatcher for that group.
Don't forget that these are user procedures, i.e., they can expire and may need to be refreshed as described in the previous blog entry.

I'll try to do an actual example using the presence user procedures soon.

Use the javadoc, explore the user procedures and start writing those bug reports :-)

Related Topics >>

Comments

help for connection to IMS network.

Good material.........but is annotation sufficient to establish a connection to IMS network from cafe application? can i know the class or api that can be used to establish a connection? Iam trying to gain some knowledge on cafe...please help Regards, Suneetha

Hi Suneetha, Using the

Hi Suneetha,

Using the domainProxy annotations in the communicationBean determine where the PUBLISH and SUBSCRIBE messages are sent. Using the xcaproot determines the same for the XCAP HTTP requests.
So if you replace the values mentioned in the example which point to the simulator, to values that correspond to your IMS network, it should work.

There is still one problem with the authentication, which you can solve by denoting the AS as a trusted AS, which is possible in most IMS networks.