Package org.cipango.server

Source Code of org.cipango.server.ConnectorManager

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

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.concurrent.atomic.AtomicLong;

import javax.servlet.ServletException;
import javax.servlet.sip.Address;
import javax.servlet.sip.SipServletMessage;
import javax.servlet.sip.SipServletResponse;
import javax.servlet.sip.SipURI;
import javax.servlet.sip.URI;

import org.cipango.server.log.AccessLog;
import org.cipango.sip.NameAddr;
import org.cipango.sip.SipGenerator;
import org.cipango.sip.SipHeaders;
import org.cipango.sip.Via;
import org.cipango.util.SystemUtil;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.Buffers;
import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.util.LazyList;
import org.eclipse.jetty.util.MultiException;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.component.LifeCycle;
import org.eclipse.jetty.util.log.Log;

public class ConnectorManager extends AbstractLifeCycle implements Buffers, SipHandler
{
    private static final int DEFAULT_MTU = 1500;
    private static final int DEFAULT_MESSAGE_SIZE = 16*1024; // FIXME
    private static final int MAX_MESSAGE_SIZE = 64*1024;
   
    private Server _server;
  
    private SipConnector[] _connectors;
    private int _mtu;
   
    private SipGenerator _sipGenerator;
   
    private AccessLog _accessLog;
   
    private final AtomicLong _receivedStats = new AtomicLong();
    private final AtomicLong _sentStats = new AtomicLong();
   
    private transient long _nbParseErrors;
   
    private ArrayList<Buffer> _buffers;
    private int _messageSize = 10000;
   
    private int _largeMessageSize = MAX_MESSAGE_SIZE;
   
    public ConnectorManager()
    {
        _mtu = SystemUtil.getIntOrDefault("sip.mtu", DEFAULT_MTU);
    }
   
    public void addConnector(SipConnector connector)
    {
        setConnectors((SipConnector[]) LazyList.addToArray(getConnectors(), connector, SipConnector.class));
    }
   
    public SipConnector[] getConnectors()
    {
        return _connectors;
    }
   
    public SipConnector getDefaultConnector()
    {
      if (_connectors == null || _connectors.length == 0)
        return null;
      return _connectors[0];
    }
   
    public void setConnectors(SipConnector[] connectors)
    {
        if (connectors != null)
        {
            for (int i = 0; i < connectors.length; i++)
            {
                SipConnector connector = connectors[i];
                connector.setServer(_server);
                connector.setHandler(this);
            }
        }
        if (_server != null)
          _server.getContainer().update(this, _connectors, connectors, "connectors");
        _connectors = connectors;
    }
   
    public void setServer(org.eclipse.jetty.server.Server server)
    {
      _server = (Server) server;
    }
   
    public Server getServer()
    {
      return _server;
    }
   
    public Address getContact(int type)
    {
        SipConnector sc = findConnector(type, null);
        return new NameAddr((URI) sc.getSipUri().clone());
        //return (Address) findTransport(type, null).getContact().clone();
    }
   
   
    protected void doStart() throws Exception
    {
      super.doStart();

        if (_buffers != null)
        _buffers.clear();
      else
        _buffers = new ArrayList<Buffer>();
       
        _sipGenerator = new SipGenerator();
       
        if (_accessLog instanceof LifeCycle)
        {
          try
          {
            ((LifeCycle) _accessLog).start();
          }
          catch (Exception e)
          {
            Log.warn("failed to start access log", e);
          }
        }
       
        if (_connectors != null)
        {
          for (int i = 0; i < _connectors.length; i++)
          {
              SipConnector connector = _connectors[i];
              connector.start();
          }
        }
    }

    protected void doStop() throws Exception
    {
        MultiException mex = new MultiException();
       
        if (_connectors != null)
        {
            for (int i = _connectors.length; i--> 0;)
            {
                try
                {
                    _connectors[i].stop();
                }
                catch(Throwable e)
                {
                    mex.add(e);
                }
            }
        }
       

      if (_accessLog instanceof LifeCycle)
        try { ((LifeCycle) _accessLog).stop(); } catch (Throwable t) { Log.warn(t); }
       
        super.doStop();
       
        mex.ifExceptionThrow();
    }
   
    public SipConnector findConnector(int type, InetAddress addr)
    {
        for (int i = 0; i < _connectors.length; i++)
        {
            SipConnector t = _connectors[i];
            if (t.getTransportOrdinal() == type)
                return t;
        }
        return _connectors[0];
    }
   
    public void messageReceived()
    {
      _receivedStats.incrementAndGet();
    }
   
    public void messageSent()
    {
        _sentStats.incrementAndGet();
    }
       
    public void handle(SipServletMessage message) throws IOException, ServletException
    {  
      SipMessage msg = (SipMessage) message;
     
      messageReceived();
     
      if (_accessLog != null)
        _accessLog.messageReceived(msg, msg.getConnection());
       
        if (preValidateMessage((SipMessage) message))
    {
          if (msg.isRequest())
            {
                Via via = msg.getTopVia();
                String remoteAddr = msg.getRemoteAddr();
               
                String host = via.getHost();
                if (host.indexOf('[') != -1)
                {
                  // As there is multiple presentation of an IPv6 address, normalize it.
                  host = InetAddress.getByName(host).getHostAddress();
                }
               
                if (!host.equals(remoteAddr))
                    via.setReceived(remoteAddr);

                if (via.getRport() != null)
                    via.setRport(Integer.toString(message.getRemotePort()));
            }

            getServer().handle(msg);
    }
    else
    {
      _nbParseErrors++;
   
    }
   
    public boolean isLocalUri(URI uri)
    {
        if (!uri.isSipURI())
            return false;
       
        SipURI sipUri = (SipURI) uri;

        if (!sipUri.getLrParam())
            return false;

        String host = sipUri.getHost();
       
        // Normalize IPv6 address
    if (host.indexOf("[") != -1)
    {
      try
      {
        host = InetAddress.getByName(host).getHostAddress();
      }
      catch (UnknownHostException e)
      {
        Log.ignore(e);
      }
    }
   
        for (int i = 0; i < _connectors.length; i++)
        {
            SipConnector connector = _connectors[i];
           
            String connectorHost = connector.getSipUri().getHost();
           
            boolean samePort = connector.getPort() == sipUri.getPort() || sipUri.getPort() == -1;
            if (samePort)
            {
              if ((connectorHost.equals(host) || connector.getAddr().getHostAddress().equals(host)))
              {
                if (sipUri.getPort() != -1)
                  return true;
               
                // match on host address and port is not set ==> NAPTR case
                if (connector.getAddr().getHostAddress().equals(host)
                    && connector.getPort() != connector.getDefaultPort())
                {
                  return false;
                }
                return true;
              }
            }
        }
        return false;
    }
   
    public void send(SipMessage message, SipConnection connection) throws IOException
    {
      Buffer buffer = getBuffer(_messageSize);
      _sipGenerator.generate(buffer, message);
     
      try
      {
        connection.write(buffer);
       
        if (_accessLog != null)
          _accessLog.messageSent(message, connection);
            messageSent();
      }
      finally
      {
        returnBuffer(buffer);
      }
    }
   
    public SipConnection sendRequest(SipRequest request, int transport, InetAddress address, int port) throws IOException
    {  
      SipConnector connector = findConnector(transport, address);
     
        Via via = request.getTopVia();
       
        via.setTransport(connector.getTransport());
        via.setHost(connector.getSipUri().getHost());
        via.setPort(connector.getSipUri().getPort());
               
        // TODO mtu

        SipConnection connection = connector.getConnection(address, port);
        send(request, connection);
       
        return connection;
    }
   
    public void sendResponse(SipResponse response) throws IOException
    {
      SipRequest request = (SipRequest) response.getRequest();
      SipConnection connection = null;
     
      if (request != null)
        connection = request.getConnection();
     
      sendResponse(response, connection);
    }
   
    public void sendResponse(SipResponse response, SipConnection connection) throws IOException
    {
      if (connection == null || !connection.getConnector().isReliable() || !connection.isOpen())
      {
        Via via = response.getTopVia();
       
        SipConnector connector = null;
        InetAddress address = null;
       
        if (connection != null)
        {
          connector = connection.getConnector();
          address = connection.getRemoteAddress();
        }
        else
        {
          int transport = SipConnectors.getOrdinal(via.getTransport());
          address = InetAddress.getByName(via.getHost());
         
          connector = findConnector(transport, address);
        }
       
      int port = -1;
     
      String srport = via.getRport();
          if (srport != null)
          {
              port = Integer.parseInt(srport);
          }
          else
          {
              port = via.getPort();
              if (port == -1)
                  port = connection.getConnector().getDefaultPort();
          }
          connection = connector.getConnection(address, port);
      }
      send(response, connection);
    }
   
    /*
    public void send(SipResponse response, SipRequest request) throws IOException
    {
      SipConnector connector = null;
     
      if (request != null && request.getEndpoint() != null)
      {
      SipEndpoint endpoint = request.getEndpoint();
        connector = endpoint.getConnector();
       
        if (connector.isReliable() && endpoint.isOpen())
        {
            Buffer buffer = getBuffer(_messageSize);
            _sipGenerator.generate(buffer, response);
        try
        {
          endpoint.getConnector().doSend(buffer, endpoint);
         
          for (int i = 0; _loggers != null && i < _loggers.length; i++)
          {
            EndPoint ep = (EndPoint) endpoint;
                _loggers[i].messageSent(
                    response,
                    connector.getTransportOrdinal(),
                    ep.getLocalAddr(),
                    ep.getLocalPort(),
                    ep.getRemoteAddr(),
                    ep.getRemotePort());                   
          }
          messageSent();
          return;
        }
        finally
        {
          returnBuffer(buffer);
        }
        }
      }

      int transport = -1;
      InetAddress address = null;
      int port = -1;
     
      if (request != null)
        transport = request.transport();
      else
        transport = SipConnectors.getOrdinal(response.getTopVia().getTransport());
     

        Via via = response.getTopVia();
       
    if (request != null)
      address = request.remoteAddress();
    else
      address = InetAddress.getByName(via.getHost());
     
      if (connector == null)
        connector = findConnector(transport, address);
       
        String srport = via.getRport();
        if (srport != null)
        {
            port = Integer.parseInt(srport);
        }
        else
        {
            port = via.getPort();
            if (port == -1)
                port = SipConnectors.getDefaultPort(transport);
        }
       
        Buffer buffer = getBuffer(_messageSize);
      _sipGenerator.generate(buffer, response);
      try
      {
        connector.send(buffer, address, port);
      }
      finally
      {
        returnBuffer(buffer);
      }
     
     
      for (int i = 0; _loggers != null && i < _loggers.length; i++)
          _loggers[i].messageSent(
              response,
              connector.getTransportOrdinal(),
              connector.getAddr().getHostAddress(),
              connector.getPort(),
              address.getHostAddress(),
              port); 
       
        messageSent();
    }
    */
   
    public Buffer getBuffer(int size)
    {
    if (size == _messageSize)
    {
      synchronized (_buffers)
      {
        if (_buffers.size() == 0)
          return newBuffer(size);
              return (Buffer) _buffers.remove(_buffers.size() - 1);
            }
        }
    else
      return newBuffer(size);
    }
   
    public void returnBuffer(Buffer buffer)
    {
        buffer.clear();
        int c = buffer.capacity();
        if (c == _messageSize)
        {
          synchronized (_buffers)
          {
              _buffers.add(buffer);
          }
        }
    }
   
    public Buffer newBuffer(int size)
    {
      return new ByteArrayBuffer(size);
    }
   
   
    public static void putStringUTF8(Buffer buffer, String s)
    {
        byte[] bytes = null;
        try
        {
            bytes = s.getBytes("UTF-8");
        }
        catch (UnsupportedEncodingException e)
        {
            throw new RuntimeException();
        }
        buffer.put(bytes);
    }
  
    public void setAccessLog(AccessLog accessLog)
    {

        if (getServer() != null)
            getServer().getContainer().update(this, _accessLog, accessLog, "accessLog", false);
       
        _accessLog = accessLog;
       
        try
        {
          if (isRunning() && _accessLog instanceof LifeCycle)
            ((LifeCycle) accessLog).start();
        }
        catch (Exception e)
        {
            Log.warn(e);
        }
    }
   
    public long getMessagesReceived()
    {
        return _receivedStats.get();
    }
   
    public long getMessagesSent()
    {
        return _sentStats.get();
    }
   
  public long getNbParseError()
  {
    long val = _nbParseErrors;
    for (int i = 0; _connectors != null && i <_connectors.length; i++)
    {
      val += _connectors[i].getNbParseError();
    }
    return val;
  }
   
    public void statsReset()
    {
      _receivedStats.set(0);
      _sentStats.set(0);
     
        _nbParseErrors = 0;
        for (int i = 0; _connectors != null && i <_connectors.length; i++)
        {
       _connectors[i].statsReset();
    }
    }
      
  public boolean preValidateMessage(SipMessage message)
  {
    boolean valid = true;
    try
    {
      if (!isUnique(SipHeaders.FROM_BUFFER, message)
          || !isUnique(SipHeaders.TO_BUFFER, message)
          || !isUnique(SipHeaders.CALL_ID_BUFFER, message)
          || !isUnique(SipHeaders.CSEQ_BUFFER, message))
      {
        valid = false;
      }
      else if (message.getTopVia() == null
          || message.getFrom() == null
          || message.getTo() == null
          || message.getCSeq() == null)
      {
        Log.info("Received bad message: unparsable required headers");
        valid = false;
      }
      message.getAddressHeader("contact");
       
      if (message instanceof SipRequest)
      {
        SipRequest request = (SipRequest) message;
        if (request.getRequestURI() == null)
          valid = false;
        request.getTopRoute();
        if (!request.getCSeq().getMethod().equals(request.getMethod()))
        {
          Log.info("Received bad request: CSeq method does not match");
          valid = false;
        }
      }
      else
      {
        int status = ((SipResponse) message).getStatus();
        if (status < 100 || status > 699)
        {
          Log.info("Received bad response: Invalid status code: " + status);
          valid = false;
        }
      }
    }
    catch (Exception e)
    {
      Log.info("Received bad message: Some headers are not parsable: {}", e);
      Log.debug("Received bad message: Some headers are not parsable", e);
      valid = false;
    }
       
    try
    {
      if (!valid
          && message instanceof SipRequest
          && !message.isAck()
          && message.getTopVia() != null)
      {
        // TODO send response stateless
        SipResponse response =
          (SipResponse) ((SipRequest) message).createResponse(SipServletResponse.SC_BAD_REQUEST);
        sendResponse(response);
      }
    }
    catch (Exception e)
    {
      Log.ignore(e);
    }
   
    return valid;
  }
 
  private boolean isUnique(Buffer headerName, SipMessage message)
  {
    Iterator it = message.getFields().getValues(headerName);
    if (!it.hasNext())
    {
      Log.info("Received bad message: Missing required header: " + headerName);
      return false;
    }
    it.next();
    if (it.hasNext())
      Log.info("Received bad message: Duplicate header: " + headerName);
    return !it.hasNext();
  }

  public AccessLog getAccessLog()
  {
    return _accessLog;
  }
    
  public Buffer getBuffer() {
    // TODO Auto-generated method stub
    return null;
  }

  public Buffer getHeader() {
    // TODO Auto-generated method stub
    return null;
  }


}
TOP

Related Classes of org.cipango.server.ConnectorManager

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.