Package org.cipango.kaleo.sip.location

Source Code of org.cipango.kaleo.sip.location.RegistrarServlet

// ========================================================================
// 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.location;

import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Locale;
import java.util.TimeZone;

import javax.servlet.ServletException;
import javax.servlet.sip.Address;
import javax.servlet.sip.SipFactory;
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.Subscription;
import org.cipango.kaleo.event.Subscription.Reason;
import org.cipango.kaleo.event.Subscription.State;
import org.cipango.kaleo.location.Binding;
import org.cipango.kaleo.location.LocationService;
import org.cipango.kaleo.location.Registration;
import org.cipango.kaleo.location.event.RegEventPackage;
import org.cipango.kaleo.location.event.RegResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

  private LocationService _locationService;
  private RegEventPackage _regEventPackage;
 
  private int _minExpires = 5; // 60;
  private int _maxExpires = 3600;
  private int _defaultExpires = 3600;
 
  private DateFormat _dateFormat;
  private SipFactory _sipFactory;
 
  private Logger _log = LoggerFactory.getLogger(RegistrarServlet.class);
 
  public void init()
  {
    _dateFormat = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss z", Locale.US);
    _dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
   
    _sipFactory = (SipFactory) getServletContext().getAttribute(SIP_FACTORY);
   
    _locationService = (LocationService) getServletContext().getAttribute(LocationService.class.getName());
    _regEventPackage = (RegEventPackage) getServletContext().getAttribute(RegEventPackage.class.getName());
  }
 
  protected void doRegister(SipServletRequest register) throws IOException, ServletException
  {
    String aor = URIUtil.toCanonical(register.getTo().getURI());
   
    ListIterator<String> it2 = register.getHeaders(Constants.REQUIRE);
    if (it2.hasNext())
    {
      SipServletResponse response = register.createResponse(SipServletResponse.SC_BAD_EXTENSION);
      while (it2.hasNext())
        response.addHeader(Constants.UNSUPPORTED, it2.next());
      response.send();
      return;
    }
   
    long now = System.currentTimeMillis();
    List<Binding> bindings;

    Registration record = _locationService.get(aor);
   
    record.addListener(_regEventPackage.getRegistrationListener());
   
    try
    {
      bindings = record.getBindings();
      if (bindings == null)
        bindings = Collections.emptyList();
       
      Iterator<Address> it = register.getAddressHeaders(Constants.CONTACT);
      if (it.hasNext())
      {
        List<Address> contacts = new ArrayList<Address>();
        boolean wildcard = false;
       
        while (it.hasNext())
        {
          Address contact = it.next();
          if (contact.isWildcard())
          {
            wildcard = true;
            if (it.hasNext() || contacts.size() > 0 || register.getExpires() > 0)
            {
              register.createResponse(SipServletResponse.SC_BAD_REQUEST, "Invalid wildcard").send();
              return;
            }
          }
          contacts.add(contact);
        }
       
        String callId = register.getCallId();
        int cseq;
        try
        {
          String s = register.getHeader(Constants.CSEQ);
          cseq = Integer.parseInt(s.substring(0, s.indexOf(' ')));
        }
        catch (Exception e)
        {
          register.createResponse(SipServletResponse.SC_BAD_REQUEST).send();
          return;
        }
       
        if (wildcard)
        {
          for (Binding binding : bindings)
          {
            if (callId.equals(binding.getCallId()) && cseq < binding.getCSeq())
            {
              _log.debug("Got lower CSeq for aor {} and call-ID {}", aor, binding.getCallId());
              register.createResponse(SipServletResponse.SC_SERVER_INTERNAL_ERROR, "Lower CSeq").send();
              return;
            }
          }
          if (_log.isDebugEnabled())
            _log.debug("removing all bindings for aor " + aor);
          record.removeAllBindings();
        }
        else
        {       
          for (Address contact : contacts)
          {
            int expires = -1;
            expires = contact.getExpires();
            if (expires < 0)
              expires = register.getExpires();
           
            if (expires != 0)
            {
              if (expires < 0)
                expires = _defaultExpires;
              if (expires > _maxExpires)
                expires = _maxExpires;
              if (expires < _minExpires)
              {
                SipServletResponse response = register.createResponse(SipServletResponse.SC_INTERVAL_TOO_BRIEF);
                response.addHeader(Constants.MIN_EXPIRES, Integer.toString(_minExpires));
                response.send();
                return;
              }
            }
            Binding binding = null;
           
            for (int i = 0; i < bindings.size() && binding == null; i++)
            {
              binding = bindings.get(i);
              if (!contact.getURI().equals(binding.getContact()))
                binding = null;
            }
            if (binding != null)
            {
              if (callId.equals(binding.getCallId()) && cseq < binding.getCSeq())
              {
                _log.debug("Got lower CSeq for aor {} and call-ID {}", aor, binding.getCallId());
                register.createResponse(SipServletResponse.SC_SERVER_INTERNAL_ERROR, "Lower CSeq").send();
                return;
              }
              if (expires == 0)
              {
                if (_log.isDebugEnabled())
                  _log.debug("removing binding {} for aor {}", binding, aor);
                record.removeBinding(binding);
              }
              else
              {
                if (_log.isDebugEnabled())
                  _log.debug("updating binding {} for aor {}", binding, aor);
                record.updateBinding(binding, contact.getURI(), callId, cseq, now + expires*1000);
              }
            }
           
            if (binding == null && expires != 0)
            {
              binding = new Binding(contact.getURI(), callId, cseq, now + expires*1000);
             
              if (_log.isDebugEnabled())
                _log.debug("adding binding {} to aor {}", binding, aor);
              record.addBinding(binding);
            }
          }
        }
        bindings = record.getBindings();
      }
    }
    finally
    {
      _locationService.put(record);
    }
   
    SipServletResponse ok = register.createResponse(SipServletResponse.SC_OK);
    ok.addHeader(Constants.DATE, _dateFormat.format(new Date(now)));
    if (bindings != null)
    {
      for (Binding binding : bindings)
      {
        Address address = _sipFactory.createAddress(binding.getContact());
        address.setExpires((int) ((binding.getExpirationTime() - now) / 1000));
        ok.addAddressHeader(Constants.CONTACT, address,false);
      }
    }
    ok.send();
  }

  @Override
  protected void doSubscribe(SipServletRequest subscribe) throws ServletException,
      IOException
  {
    String event = subscribe.getHeader(Constants.EVENT);
   
    if (event == null || !(event.equals(_regEventPackage.getName())))
    {
      SipServletResponse response = subscribe.createResponse(SipServletResponse.SC_BAD_EVENT);
      response.addHeader(Constants.ALLOW_EVENTS, _regEventPackage.getName());
      response.send();
      response.getApplicationSession().invalidate();
      return;
    }
   
    if(!checkAcceptHeader(subscribe))
      return;
       
    int expires = subscribe.getExpires();
    if (expires != -1)
    {
      if (expires != 0)
      {
        if (expires < _regEventPackage.getMinExpires())
        {
          SipServletResponse response = subscribe.createResponse(SipServletResponse.SC_INTERVAL_TOO_BRIEF);
          response.addHeader(Constants.MIN_EXPIRES, Integer.toString(_regEventPackage.getMinExpires()));
          response.send();
          response.getApplicationSession().invalidate();
          return;
        }
        else if (expires > _regEventPackage.getMaxExpires())
        {
          expires = _regEventPackage.getMaxExpires();
        }
      }
    }
    else
    {
      expires = _regEventPackage.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;
      }
    }
   
    RegResource regResource = _regEventPackage.get(uri);
   
    try
    {
      Subscription subscription = null;
     
      if (expires == 0)
      {
        subscription = regResource.removeSubscription(session.getId());
       
        if (subscription == null)
        {
          subscription = new Subscription(regResource, session, -1);
        }
        else
        {
          subscription.setExpirationTime(System.currentTimeMillis());
          if (_log.isDebugEnabled())
            _log.debug("removed reg subscription {} to registration resource {}",
              subscription.getSession().getId(), regResource.getUri());
       
        subscription.setState(Subscription.State.TERMINATED, Reason.TIMEOUT);
      }
      else
      {
        long now = System.currentTimeMillis();
       
        subscription = regResource.getSubscription(session.getId());
   
        if (subscription == null)
        {
          subscription = new Subscription(regResource, session, now + expires*1000);
          subscription.setState(State.ACTIVE, Reason.SUBSCRIBE);
          regResource.addSubscription(subscription);
         
          session.setAttribute(Constants.SUBSCRIPTION_ATTRIBUTE, uri);
         
          if (_log.isDebugEnabled())
            _log.debug("added reg subscription {} to registration resource {}",
                subscription.getSession().getId(), regResource.getUri());
        }
        else
        {
          subscription.setExpirationTime(now + expires * 1000);
         
          if (_log.isDebugEnabled())
            _log.debug("refreshed reg subscription {} to registration resource {}",
                subscription.getSession().getId(), regResource.getUri());
        }
      }
     
      int code = (subscription.getState() != Subscription.State.PENDING) ?
          SipServletResponse.SC_OK : SipServletResponse.SC_ACCEPTED;
     
      SipServletResponse response = subscribe.createResponse(code);
      response.setExpires(expires);
      response.send();
       
      _regEventPackage.notify(subscription);
    }
    finally
    {
      _regEventPackage.put(regResource);
    }
  }
 
  private boolean checkAcceptHeader(SipServletRequest subscribe) throws IOException
  {
    List<String> supported = _regEventPackage.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.location.RegistrarServlet

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.