Package org.cipango.example

Source Code of org.cipango.example.ProxyRegistrarServlet$BindingScavenger

// ========================================================================
// Copyright 2007-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.example;

import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.SortedSet;
import java.util.TimeZone;
import java.util.Timer;
import java.util.TimerTask;
import java.util.TreeSet;

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.SipURI;

public class ProxyRegistrarServlet extends SipServlet
{
  private static final long serialVersionUID = 5425892819952843296L;
 
  private int _minExpires = 60;
  private int _maxExpires = 86400;
  private int _defaultExpires = 3600;
 
  private Map<String, SortedSet<Binding>> _bindings;
  private SipFactory _sipFactory;
  private Timer _timer;
  private DateFormat _dateFormat;
 
  @Override
  public void init()
  {
    _sipFactory = (SipFactory) getServletContext().getAttribute(SipServlet.SIP_FACTORY);
    _bindings = new HashMap<String, SortedSet<Binding>>();
   
    getServletContext().setAttribute(Binding.class.getName(), _bindings);
   
    _timer = new Timer();
    _timer.scheduleAtFixedRate(new BindingScavenger(), 5000, 5000);
   
    _dateFormat = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss z", Locale.US);
    _dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
  }
 
  public String getAor(Address address)
  {
    SipURI uri = (SipURI) address.getURI();
    return "sip:" + uri.getUser() + "@" + uri.getHost().toLowerCase();
  }
 
  protected SortedSet<Binding> getBindings(String aor, boolean create)
  {
    SortedSet<Binding> bindings;
    synchronized (_bindings)
    {
      bindings = _bindings.get(aor);
     
      if (bindings == null && create)
      {
        bindings = new TreeSet<Binding>();
        _bindings.put(aor, bindings);
      }
    }
    return bindings;
  }
 
  @Override
  protected void doRegister(SipServletRequest register) throws IOException, ServletException
  {
    try
    {
      String aor = getAor(register.getTo());
     
      SortedSet<Binding> bindings = getBindings(aor, true);
     
      synchronized (bindings)
      {
        Iterator<Address> it = register.getAddressHeaders("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("cseq");
            cseq = Integer.parseInt(s.substring(0, s.indexOf(' ')));
          }
          catch (Exception e)
          {
            register.createResponse(SipServletResponse.SC_BAD_REQUEST, e.getMessage()).send();
            return;
          }
         
          if (wildcard)
          {
            for (Binding binding : bindings)
            {
              if (callId.equals(binding.getCallId()) && cseq < binding.getCseq())
              {
                register.createResponse(SipServletResponse.SC_SERVER_INTERNAL_ERROR,
                    "Lower cseq").send();
                return;
              }
              bindings.remove(binding);
            }
          }
          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;
                }
                else if (expires < _minExpires)
                {
                  SipServletResponse response = register.createResponse(423);
                  response.addHeader("Min-Expires", Integer.toString(_minExpires));
                  response.send();
                  return;
                }
              }
              boolean exist = false;
             
              Iterator<Binding> it2 = bindings.iterator();
              while (it2.hasNext())
              {
                Binding binding = it2.next();
               
                if (contact.getURI().equals(binding.getContact()))
                {
                  exist = true;
                  if (callId.equals(binding.getCallId()) && cseq < binding.getCseq())
                  {
                    register.createResponse(SipServletResponse.SC_SERVER_INTERNAL_ERROR,
                        "Lower CSeq").send();
                    return;
                  }
                  if (expires == 0)
                  {
                    it2.remove();
                  }
                  else
                  {
                    binding.setCallId(callId);
                    binding.setCseq(cseq);
                    binding.setExpires(expires);
                    binding.setQ(contact.getQ());
                  }
                }
              }
              if (!exist && expires != 0)
              {
                Binding binding = new Binding(aor, contact.getURI());
                binding.setCallId(callId);
                binding.setCseq(cseq);
                binding.setExpires(expires);
                binding.setQ(contact.getQ());
                bindings.add(binding);
              }
            }
          }
        }
       
        // Empty bindings set are removed in the scavenger to prevent deadlocks.
       
        SipServletResponse ok = register.createResponse(SipServletResponse.SC_OK);
        if (bindings.size() > 0)
        {
          for (Binding binding : bindings)
          {
            Address address = _sipFactory.createAddress(binding.getContact());
            address.setExpires(binding.getExpires());
            address.setQ(binding.getQ());
            ok.addAddressHeader("contact", address, false);
          }
        }
        ok.addHeader("Date", _dateFormat.format(new Date()));
        ok.send();
     
    }
    catch (Throwable e) {
      log("Caught unexpected exception on REGISTER processing", e);
      SipServletResponse response = register.createResponse(SipServletResponse.SC_SERVER_INTERNAL_ERROR);
      response.setContent(e, "text/stackTrace");
      response.send();
    }
    finally
    {
      register.getApplicationSession().invalidate();
    }
  }
 
  protected void proxy(SipServletRequest request) throws ServletException, IOException
  {
    if (!request.isInitial())
      return;
   
    String aor = getAor(request.getTo());
   
    SortedSet<Binding > bindings = getBindings(aor, false);
       
    if (bindings != null && bindings.size() > 0)
    {
      synchronized (bindings)
      {
        Binding binding = bindings.first();
        request.getProxy().proxyTo(binding.getContact());
      }
    }
    else
    {
      request.createResponse(SipServletResponse.SC_NOT_FOUND).send();
   
  }

  @Override
  protected void doRequest(SipServletRequest request) throws ServletException, IOException
  {
    String method = request.getMethod();
    if ("REGISTER".equalsIgnoreCase(method))
      doRegister(request);
    else
      proxy(request);   
  }
 
  @Override
  public void destroy()
  {
    _timer.cancel();
  }
 
  class BindingScavenger extends TimerTask
  {
    public void run() {
      synchronized (_bindings)
      {
        Iterator<SortedSet<Binding>> it = _bindings.values().iterator();
        long now = System.currentTimeMillis();
        while (it.hasNext()) {
          SortedSet<Binding> list = it.next();
          synchronized (list)
          {
            Iterator<Binding> it2 = list.iterator();
            while (it2.hasNext()) {
              Binding binding = (Binding) it2.next();
              if (binding.getAbsoluteExpires() <= now)
                it2.remove();
            }
            if (list.isEmpty())
              it.remove();
          }
        }
      }
    }
  }
}
TOP

Related Classes of org.cipango.example.ProxyRegistrarServlet$BindingScavenger

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.