📄 presentitymanager.java
字号:
package gov.nist.sip.proxy.presenceserver;import gov.nist.sip.proxy.*;import java.util.*;import javax.sip.Dialog;import javax.sip.address.*;import java.io.File;import javax.sip.message.*;import javax.sip.header.*;import gov.nist.sip.proxy.presenceserver.pidfparser.*;/** Implements a presetity manager. * * @author Henrik Leion * @version 0.1 * */public class PresentityManager implements Runnable { protected HashMap subscribers; protected HashMap notifiers; protected HashMap resourcelists; protected HashMap virtualSubscriptions; protected PresenceServer presenceServer; protected boolean isRunning; /** A list of all registered notifiers. The objects are only referenced * to from this hashtable, and removing them from it should delete them **/ private LinkedList initialNotifyQueue; private String resourceListDir; public XMLcpimParser xmlCpimParser; public XMLResourceListParser xmlResourceListParser; public PresentityManager(PresenceServer presenceServer) { subscribers = new HashMap(); initialNotifyQueue = new LinkedList(); notifiers = new HashMap(); resourcelists = new HashMap(); virtualSubscriptions = new HashMap(); this.presenceServer = presenceServer; this.isRunning = true; new Thread(this).start(); xmlCpimParser = new XMLcpimParser(); xmlResourceListParser = new XMLResourceListParser(this); resourceListDir = ""; } public void stop() { this.isRunning = false; } //************************** // Processing methods //************************** /** Creates or updates a subscription. * New subscriptions with expires=0 are called fetchers, they only require one notification * @returns responseCode **/ public synchronized int processSubscribe(Request request, Dialog dialog, int expires) { ProxyDebug.println("PresenceServer, processSubscribeRequest: \n" + request); if (isResourceListSubscriber(request)) { //ResourceLists demand a little special handling return processResourceListSubscribe(request, dialog, expires); } int responseCode; String notifierKey = getKey((Message)request, "To"); String subscriberKey = getKey((Message)request, "From"); String subscriberId = dialog.getDialogId(); Notifier notifier = (Notifier)notifiers.get(notifierKey); Subscriber subscriber = (Subscriber)subscribers.get(subscriberId); if (subscriber!=null) { ProxyDebug.println(" PM.processSubscribe - updating old subscription"); if (expires == 0) { //remove old subscription, send notify responseCode = notifier.removeSubscriber(subscriberKey); subscriber.setSubscriptionState("terminated"); } else if (notifier.hasSubscriber(subscriberId)) { //Update subscription, don't send Notify //Authorize subscriber responseCode = notifier.authorize(subscriberKey,Request.SUBSCRIBE); if (responseCode==Response.OK) { subscriber.setExpires(expires); subscriber.setSubscriptionState("active"); } else if (responseCode==Response.ACCEPTED) { subscriber.setExpires(expires); subscriber.setSubscriptionState("pending"); } else { subscriber.setSubscriptionState("terminated"); } return responseCode; } else { //subscriber object exists, but is not a subscriber //to this notifier. Possibly the subscriberId (dialogId) has been reused //don't send notify return Response.SERVER_INTERNAL_ERROR; } } else { //subscriber object does not exist (The dialogId was unmatched) //Authorize subscriber and create object responseCode = notifier.authorize(subscriberKey,Request.SUBSCRIBE); if (responseCode==Response.OK) { subscriber = createSubscriber(request,subscriberKey,dialog,expires); subscriber.setExpires(expires); subscriber.setSubscriptionState("active"); subscriber.updateNotifyBody(notifier.getFullState()); initialNotifyQueue.add((Object)subscriber); if (expires > 0) { subscribers.put((Object)subscriberId, (Object)subscriber); notifier.addSubscriber(subscriberKey,subscriberId, "active"); } } else if (responseCode==Response.ACCEPTED) { ProxyDebug.println(" PM.processSubscribe - new subscription, Accepted"); subscriber = (Subscriber)createSubscriber(request,subscriberKey,dialog,expires); subscriber.setExpires(expires); subscriber.setSubscriptionState("pending"); subscriber.updateNotifyBody(notifier.getOfflineState()); if (expires > 0) { subscribers.put((Object)subscriberId, (Object)subscriber); notifier.addSubscriber(subscriberKey,subscriberId, "pending"); } } else { ProxyDebug.println(" PM.processSubscribe - new subscription, Not accepted"); //this new subscription was declined. return responseCode; } } //New subscriptions should be notified immediately initialNotifyQueue.add((Object)subscriber); ProxyDebug.println(" PM.processSubscribe finished, added subscriber to NotifyQueue: " + initialNotifyQueue.toString()); return responseCode; } /** Sets up a subscription to a resourcelist. A Resourcelist is a subclassed * Subscriber. * * */ private int processResourceListSubscribe(Request request, Dialog dialog, int expires) { ProxyDebug.println("PresenceServer, processResourceListSubscribe"); String resourceListURI = getKey((Message)request, "To"); String subscriberKey = getKey((Message)request, "From"); String subscriberId = dialog.getDialogId(); int responseCode; //Check if ResourceListSubscriber already exists. In that case // just add the new subscriber ResourceList resourceList = (ResourceList)subscribers.get(resourceListURI); if (resourceList!=null) { //authorize responseCode = resourceList.authorize(subscriberKey,Request.SUBSCRIBE); SubscriberMultipart subscriber = new SubscriberMultipart(subscriberKey,dialog,expires); subscriber.setExpires(expires); subscriber.setSubscriptionState("active"); subscriber.updateNotifyBody(resourceList.getNotifyBody()); if (expires > 0) { subscribers.put((Object)subscriberId, (Object)subscriber); resourceList.addSubscriber(subscriberKey,subscriberId, "active"); } } else { //We have to parse the resourcelist and get all Notifiers and start all // VirtualSubscriptions File resourceListFile = new File(resourceListDir,resourceListURI); if(resourceListFile.length()<1) { return Response.NOT_FOUND; } resourceList = new ResourceList(resourceListURI, null, expires, resourceListFile); SubscriberMultipart subscriber = new SubscriberMultipart(subscriberKey, dialog, expires); subscriber.setRlmiFile(resourceListFile); //Parse file and retrieve a list of all entities Vector entities = xmlResourceListParser.getNotifiers(resourceListFile); Iterator it = entities.iterator(); while (it.hasNext()) { String uri = (String)it.next(); //1. Is it a notifier? => notifier.addSubscriber(resourceList); Notifier notifier = (Notifier)notifiers.get(uri); synchronized (notifier) { if (notifier!=null) { subscriber.updateNotifyBody(notifier.getFullState()); if (expires>0) //resourcelists have no dialog, URL is used instead notifier.addSubscriber(resourceList.getSubscriberURL(), resourceList.getSubscriberURL(), //resourcelists have no dialog, URI is used instead "active"); continue; } } //2. Is it another resourceList? ResourceList parentResourceList = (ResourceList)subscribers.get(uri); synchronized(parentResourceList) { if (parentResourceList != null) { continue; } } //3. Is it external? //4. Are we responsible for it, but it hasn't registered? } responseCode = Response.OK; } return responseCode; } /** * Extra sendNotify for the special case * when the initial notify of a new subscripion is * to be send. This is required since the response * to the subscription must be sent before the Notify * and fetchers and terminated subscriptions are lost * when the processSubscribe method finishes. **/ protected synchronized void sendInitialNotify() { ListIterator it = initialNotifyQueue.listIterator(); while (it.hasNext()) { Subscriber subscriber = (Subscriber)it.next(); presenceServer.sendNotifyRequest(subscriber); } } /** * Responsible for updating internal Notifier state and updating * internal states of it's subscribers. * If expires!=0, creates a Notify object else all subscribers * are notified and the Notifier object is deleted.<p /> * TODO <ul> * <li>Add fields for contacts, accept-headers and allow-events in * Notify object and constructor</li> * </ul> **/ public void processRegister (String notifierKey, int expires, String contact) { synchronized(notifiers) { Notifier notifier = (Notifier)notifiers.get(notifierKey); if ((notifier != null) && (expires == 0)) { //Remove Notifier contact String tupleId = notifier.removeContact(contact); //Update subscribers //This should be done if the subscribers support Partial presence /* Collection notifiersSubscriberKeys = notifier.getSubscribers(); Iterator it = notifiersSubscriberKeys.iterator(); String text = "<removed><t_id>" + tupleId + "</t_id></removed>"; while (it.hasNext()) { String dialogId = (String)it.next(); Subscriber subscriber = (Subscriber)subscribers.get(dialogId); subscriber.updateNotifyBody(text); } */ } else if ((notifier == null) && (expires != 0)) { //Create Notifier notifier = new Notifier(notifierKey,expires,contact); notifiers.put(notifierKey, notifier); } else if ((notifier != null) && ((expires != 0) || (contact != null))) { //Update Notifier if (contact != null) { notifier.addContact(contact); } if (expires != 0) { notifier.setExpires(expires); } } else { //Trying to update a non-existing Notifier } } } /** This method is called for static (uploaded registrations). * * No contact address is specified for uploaded registrations. */ protected void processRegister(String notifierKey, int expires) { synchronized (notifiers) { Notifier notifier = new Notifier(notifierKey,expires, null); notifiers.put(notifierKey, notifier); } } /** * Responsible for updating Notifier internal state and also * updating all it's subscribers accordingly.<br> * * Todo: <ul> * <li>Verification</li> * </ul> * * See draft-ietf-sip-publish-02, chapter 6. * * Valid responses are 412 (Precondition failed), 423 (Interval too brief), * 403 (Forbidden), 489 (Bad Event), 415 (Unsupported Media Type), * 200 (OK) * The 404 (Not found) response is taken care of by Proxy. */ public synchronized int processPublish(Request request) { ProxyDebug.println("PresenceServer, processPublish"); String notifierKey = getKey((Message)request, "To"); String publisherKey = getKey((Message)request, "From"); Notifier notifier = (Notifier)notifiers.get(notifierKey); int responseCode; //Step 1 is performed by Proxy //Steps 2-3 are performed by PresentityManager //4. Authorize, return 403 if Forbidden responseCode = notifier.authorize(publisherKey, "PUBLISH"); if (responseCode == Response.FORBIDDEN) return responseCode; //5. Examine event header EventHeader eventHeader = (EventHeader)request.getHeader(EventHeader.NAME); if ((eventHeader == null) || !(notifier.hasEvent(eventHeader.getEventType() ))) { return Response.BAD_EVENT; } //6. Examine If-Match header Header ifMatchHeader = (Header)request.getHeader("SIP-If-Match"); String entityTag = new String(); if(ifMatchHeader != null) { String ifMatchString = ifMatchHeader.toString(); int colon = ifMatchString.indexOf(":"); entityTag = ifMatchString.substring(colon+1).trim(); } //if(more than one entity-tag) return 400(Invalid request) //7. Expiration header // This is ignored for now, published data is used until // updated //8. Process body if (responseCode==Response.OK) { Object content = request.getContent(); String newBody = null;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -