Package org.cipango.kaleo.sip.presence

Source Code of org.cipango.kaleo.sip.presence.PresenceServlet

// ========================================================================
// Copyright 2008-2009 NEXCOM Systems
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ========================================================================

package org.cipango.kaleo.sip.presence;

import java.io.IOException;
import java.util.Iterator;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.sip.SipServlet;
import javax.servlet.sip.SipServletRequest;
import javax.servlet.sip.SipServletResponse;
import javax.servlet.sip.SipSession;

import org.cipango.kaleo.Constants;
import org.cipango.kaleo.URIUtil;
import org.cipango.kaleo.event.ContentHandler;
import org.cipango.kaleo.event.Subscription;
import org.cipango.kaleo.event.Subscription.Reason;
import org.cipango.kaleo.event.Subscription.State;
import org.cipango.kaleo.presence.PresenceEventPackage;
import org.cipango.kaleo.presence.Presentity;
import org.cipango.kaleo.presence.SoftState;
import org.cipango.kaleo.presence.policy.PolicyManager;
import org.cipango.kaleo.presence.policy.PolicyManager.SubHandling;
import org.cipango.kaleo.presence.watcherinfo.WatcherInfoEventPackage;
import org.cipango.kaleo.presence.watcherinfo.WatcherResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class PresenceServlet extends SipServlet
{
  private static final long serialVersionUID = 1L;

  private final Logger _log = LoggerFactory.getLogger(PresenceServlet.class);
 
  private PresenceEventPackage _presence;
  private WatcherInfoEventPackage _watcherInfo;
  private PolicyManager _policyManager;
  //private Notifier<Presentity> _notifier;
 
  public void init()
  {
    _presence = (PresenceEventPackage) getServletContext().getAttribute(PresenceEventPackage.class.getName());
    _watcherInfo = (WatcherInfoEventPackage) getServletContext().getAttribute(WatcherInfoEventPackage.class.getName());
    _policyManager = (PolicyManager) getServletContext().getAttribute(PolicyManager.class.getName());
  }
 
  protected void doPublish(SipServletRequest publish) throws ServletException, IOException
  {
    Presentity presentity = null;
    try
    {
      String event = publish.getHeader(Constants.EVENT);
 
      if (event == null || !event.equals(_presence.getName()))
      {
        SipServletResponse response = publish.createResponse(SipServletResponse.SC_BAD_EVENT);
        response.addHeader(Constants.ALLOW_EVENTS, _presence.getName());
        response.send();
        return;
      }
 
      String uri = URIUtil.toCanonical(publish.getRequestURI());
 
      int expires = publish.getExpires();
      if (expires != -1)
      {
        if(expires != 0)
        {
          if (expires < _presence.getMinStateExpires())
          {
            SipServletResponse response = publish.createResponse(SipServletResponse.SC_INTERVAL_TOO_BRIEF);
            response.addHeader(Constants.MIN_EXPIRES, Integer.toString(_presence.getMinStateExpires()));
            response.send();
            return;
          }
          else if (expires > _presence.getMaxStateExpires())
            expires = _presence.getMaxStateExpires();
        }
      }
      else
      {
        expires = _presence.getDefaultStateExpires();
      }
 
      String contentType = publish.getContentType();
 
      List<String> supported = _presence.getSupportedContentTypes();
      if (contentType != null && !(supported.contains(contentType)))
      {
        SipServletResponse response = publish.createResponse(SipServletResponse.SC_UNSUPPORTED_MEDIA_TYPE);
        for (String s : supported)
          response.addHeader(Constants.ACCEPT, s);
        response.send();
        return;
      }
 
      byte[] raw = publish.getRawContent();
      Object content = null;
 
      if (raw != null)
      {
        if (contentType == null)
        {
          SipServletResponse response = publish.createResponse(SipServletResponse.SC_UNSUPPORTED_MEDIA_TYPE);
          for (String s : supported)
            response.addHeader(Constants.ACCEPT, s);
          response.send();
          return;
        }
        ContentHandler<?> handler = _presence.getContentHandler(contentType);   
        try
        {
          content = handler.getContent(raw);
        }
        catch (Exception e)
        {
          if (_log.isDebugEnabled())
            _log.debug("invalid content {}", e);
         
          publish.createResponse(SipServletResponse.SC_BAD_REQUEST).send();
          return;
        }
      }
      String etag = publish.getHeader(Constants.SIP_IF_MATCH);
      long now = System.currentTimeMillis();
 
      presentity = _presence.get(uri);
   

      if (etag == null)
      {
        if (content == null)
        {
          publish.createResponse(SipServletResponse.SC_BAD_REQUEST).send();
          return;
        }
        SoftState state = presentity.addState(contentType, content, now + expires*1000);
       
        if (_log.isDebugEnabled())
          _log.debug("added state {} to presentity {}", state.getETag(), presentity);
       
        SipServletResponse response = publish.createResponse(SipServletResponse.SC_OK);
        response.setExpires(expires);
        response.setHeader(Constants.SIP_ETAG, state.getETag());
        response.send();
      }
      else
      {
        SoftState state = presentity.getState(etag);
        if (state == null)
        {
          publish.createResponse(SipServletResponse.SC_CONDITIONAL_REQUEST_FAILED).send();
          return;
        }
        if (expires == 0)
        {
          if (_log.isDebugEnabled())
            _log.debug("removed state {} from presentity {}", state.getETag(), presentity);
         
          presentity.removeState(etag);
        }
        else
        {
          if (content != null)
          {
            presentity.modifyState(state, contentType, content, now + expires*1000);
           
            if (_log.isDebugEnabled())
              _log.debug("modified state {} (new etag {}) from presentity {}",
                  new Object[] {etag, state.getETag(), presentity});
          }
          else
          {
            presentity.refreshState(state, now + expires*1000);
            if (_log.isDebugEnabled())
              _log.debug("refreshed state {} (new etag {}) from presentity {}",
                  new Object[] {etag, state.getETag(), presentity});
          }
        }
        SipServletResponse response = publish.createResponse(SipServletResponse.SC_OK);
        response.setExpires(expires);
        response.setHeader(Constants.SIP_ETAG, state.getETag());
        response.send();
      }
    }
    finally
    {
      if (presentity != null)
        _presence.put(presentity);
      publish.getApplicationSession().invalidate();
    }
  }

  protected void doSubscribe(SipServletRequest subscribe) throws ServletException, IOException
  {
    String event = subscribe.getHeader(Constants.EVENT);
   
    if (_presence.getName().equals(event))
      doPresenceSubscribe(subscribe);
    else if (_watcherInfo.getName().equals(event))
      doWatcherInfoSubscribe(subscribe);
    else
    {
      SipServletResponse response = subscribe.createResponse(SipServletResponse.SC_BAD_EVENT);
      response.addHeader(Constants.ALLOW_EVENTS, _presence.getName());
      response.send();
      response.getApplicationSession().invalidate();
      return;
    }   
  }
 
  protected void doPresenceSubscribe(SipServletRequest subscribe) throws ServletException, IOException
 
    if(!checkAcceptHeader(subscribe, false))
      return;
       
    int expires = subscribe.getExpires();
    if (expires != -1)
    {
      if (expires != 0)
      {
        if (expires < _presence.getMinExpires())
        {
          SipServletResponse response = subscribe.createResponse(SipServletResponse.SC_INTERVAL_TOO_BRIEF);
          response.addHeader(Constants.MIN_EXPIRES, Integer.toString(_presence.getMinExpires()));
          response.send();
          response.getApplicationSession().invalidate();
          return;
        }
        else if (expires > _presence.getMaxExpires())
        {
          expires = _presence.getMaxExpires();
        }
      }
    }
    else
    {
      expires = _presence.getDefaultExpires();
    }
   
    SipSession session = subscribe.getSession();
    String uri = null;
   
    if (subscribe.isInitial())
    {
      uri = URIUtil.toCanonical(subscribe.getRequestURI());
    }
    else
    {
      uri = (String) session.getAttribute(Constants.SUBSCRIPTION_ATTRIBUTE);
      if (uri == null)
      {
        subscribe.createResponse(SipServletResponse.SC_CALL_LEG_DONE).send();
        subscribe.getApplicationSession().invalidate();
        return;
      }
    }
       
    Presentity presentity = _presence.get(uri);
   
    String subscriberUri = null;
    if (subscribe.getAddressHeader(Constants.P_ASSERTED_IDENTITY) != null)
      subscriberUri = URIUtil.toCanonical(subscribe.getAddressHeader(Constants.P_ASSERTED_IDENTITY).getURI());
    else
      subscriberUri = URIUtil.toCanonical(subscribe.getFrom().getURI());
   
    try
    {     
      SubHandling subHandling = _policyManager.getPolicy(subscriberUri, presentity);
      if (subHandling == SubHandling.BLOCK)
      {
        _log.debug("Reject presence subscription from {} to {} due to policy", subscriberUri, presentity.getUri());
        SipServletResponse response = subscribe.createResponse(SipServletResponse.SC_FORBIDDEN);
        response.send();
        return;
      }
     
      Subscription subscription = null;
     
      if (expires == 0)
      {
        subscription = presentity.removeSubscription(session.getId());
       
        if (subscription == null)
        {
          subscription = new Subscription(presentity, session, -1, subscriberUri);
          subscription.addListener(_watcherInfo.getSubscriptionListener());
        }
        else
        {
          subscription.setExpirationTime(System.currentTimeMillis());
          if (_log.isDebugEnabled())
            _log.debug("removed presence subscription {} to presentity {}",
              subscription.getSession().getId(), presentity.getUri());
       
        if (subHandling == SubHandling.CONFIRM)
          subscription.setState(Subscription.State.WAITING, Reason.TIMEOUT, subHandling == SubHandling.ALLOW);
        else
          subscription.setState(Subscription.State.TERMINATED, Reason.TIMEOUT, subHandling == SubHandling.ALLOW);
      }
      else
      {
        long now = System.currentTimeMillis();
       
        subscription = presentity.getSubscription(session.getId());
   
        if (subscription == null)
        {
          subscription = new Subscription(presentity, session, now + expires*1000, subscriberUri);
          subscription.addListener(_watcherInfo.getSubscriptionListener());
          presentity.addSubscription(subscription);
         
          switch (subHandling)
          {
          case ALLOW:
            subscription.setState(State.ACTIVE, Reason.SUBSCRIBE, true);
            break;
          case CONFIRM:
            subscription.setState(State.PENDING, Reason.SUBSCRIBE, false);
            break;
          case POLITE_BLOCK:
            subscription.setState(State.ACTIVE, Reason.SUBSCRIBE, false);
            break;
          default:
            break;
          }
         
          session.setAttribute(Constants.SUBSCRIPTION_ATTRIBUTE, uri);
         
          if (_log.isDebugEnabled())
            _log.debug("added presence subscription {} to presentity {}",
                subscription.getId(), presentity.getUri());
        }
        else
        {
          subscription.setExpirationTime(now + expires * 1000);
         
          if (_log.isDebugEnabled())
            _log.debug("refreshed presence subscription {} to presentity {}",
                subscription.getSession().getId(), presentity.getUri());
        }
      }
     
      int code = (subscription.getState() != Subscription.State.PENDING) ?
          SipServletResponse.SC_OK : SipServletResponse.SC_ACCEPTED;
     
      SipServletResponse response = subscribe.createResponse(code);
      response.setExpires(expires);
      response.send();
     
      // Ensure 200/SUBSCRIBE is received before NOTIFY
      try { Thread.sleep(50); } catch (Exception e) {}
      _presence.notify(subscription);
    }
    finally
    {
      _presence.put(presentity);
    }
  }
 
  protected void doWatcherInfoSubscribe(SipServletRequest subscribe) throws ServletException, IOException
 
    if(!checkAcceptHeader(subscribe, true))
      return;
       
    int expires = subscribe.getExpires();
    if (expires != -1)
    {
      if (expires != 0)
      {
        if (expires < _watcherInfo.getMinExpires())
        {
          SipServletResponse response = subscribe.createResponse(SipServletResponse.SC_INTERVAL_TOO_BRIEF);
          response.addHeader(Constants.MIN_EXPIRES, Integer.toString(_presence.getMinExpires()));
          response.send();
          response.getApplicationSession().invalidate();
          return;
        }
        else if (expires > _watcherInfo.getMaxExpires())
        {
          expires = _watcherInfo.getMaxExpires();
        }
      }
    }
    else
    {
      expires = _watcherInfo.getDefaultExpires();
    }
   
    SipSession session = subscribe.getSession();
    String uri = null;
   
    if (subscribe.isInitial())
    {
      uri = URIUtil.toCanonical(subscribe.getRequestURI());
    }
    else
    {
      uri = (String) session.getAttribute(Constants.SUBSCRIPTION_ATTRIBUTE);
      if (uri == null)
      {
        subscribe.createResponse(SipServletResponse.SC_CALL_LEG_DONE).send();
        subscribe.getApplicationSession().invalidate();
        return;
      }
    }
       
    WatcherResource resource = _watcherInfo.get(uri);
   
    String subscriberUri = null;
    if (subscribe.getAddressHeader(Constants.P_ASSERTED_IDENTITY) != null)
      subscriberUri = URIUtil.toCanonical(subscribe.getAddressHeader(Constants.P_ASSERTED_IDENTITY).getURI());
    else
      subscriberUri = URIUtil.toCanonical(subscribe.getFrom().getURI());
   
    try
    {
      Subscription subscription = null;
     
      if (expires == 0)
      {
        subscription = resource.removeSubscription(session.getId());
       
        if (subscription == null)
          subscription = new Subscription(resource, session, -1, subscriberUri);
        else
        {
          subscription.setExpirationTime(System.currentTimeMillis());
          if (_log.isDebugEnabled())
            _log.debug("removed presence.winfo subscription {} to resource {}",
              subscription.getSession().getId(), resource.getUri());
       
        subscription.setState(Subscription.State.TERMINATED, Reason.TIMEOUT);
      }
      else
      {
        long now = System.currentTimeMillis();
       
        subscription = resource.getSubscription(session.getId());
   
        if (subscription == null)
        {
          subscription = new Subscription(resource, session, now + expires*1000, subscriberUri);
          subscription.setState(State.ACTIVE, Reason.SUBSCRIBE);
          resource.addSubscription(subscription);
         
          session.setAttribute(Constants.SUBSCRIPTION_ATTRIBUTE, uri);
         
          if (_log.isDebugEnabled())
            _log.debug("added presence.winfo subscription {} to resource {}",
                subscription.getSession().getId(), resource.getUri());
        }
        else
        {
          subscription.setExpirationTime(now + expires * 1000);
         
          if (_log.isDebugEnabled())
            _log.debug("refreshed presence.winfo subscription {} to resource {}",
                subscription.getSession().getId(), resource.getUri());
        }
      }
     
      int code = (subscription.getState() != Subscription.State.PENDING) ?
          SipServletResponse.SC_OK : SipServletResponse.SC_ACCEPTED;
     
      SipServletResponse response = subscribe.createResponse(code);
      response.setExpires(expires);
      response.send();
       
      _watcherInfo.notify(subscription);
    }
    finally
    {
      _watcherInfo.put(resource);
    }
  }
 
  private boolean checkAcceptHeader(SipServletRequest subscribe, boolean winfo) throws IOException
  {
   
    List<String> supported;
    if (winfo)
      supported = _watcherInfo.getSupportedContentTypes();
    else
      supported = _presence.getSupportedContentTypes();
   
    Iterator<String> it = subscribe.getHeaders(Constants.ACCEPT);
    if (!it.hasNext())
      return true;
    while (it.hasNext())
    {
      String contentType = it.next();
      if (contentType.equals("") ||  supported.contains(contentType))
        return true;
    }
    SipServletResponse response = subscribe.createResponse(SipServletResponse.SC_UNSUPPORTED_MEDIA_TYPE);
    for (String s : supported)
      response.addHeader(Constants.ACCEPT, s);

    response.send();
    response.getApplicationSession().invalidate();
    return false;
  }
}
TOP

Related Classes of org.cipango.kaleo.sip.presence.PresenceServlet

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.