📄 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 org.apache.log4j.Logger;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 = ""; } private static Logger logger = Logger.getLogger(PresentityManager.class); 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) { logger.debug("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) { logger.debug(" 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) { logger .debug(" 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 { logger .debug(" PM.processSubscribe - new subscription, Not accepted"); // this new subscription was declined. return responseCode; } } // New subscriptions should be notified immediately initialNotifyQueue.add((Object) subscriber); logger .debug(" 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) { logger.debug("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) { logger.debug("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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -