Пример #1
0
  /**
   * Constructor - gets called from the SIPStack class with a socket on accepting a new client. All
   * the processing of the message is done here with the sipStack being freed up to handle new
   * connections. The sock input is the socket that is returned from the accept. Global data that is
   * shared by all threads is accessible in the Server structure.
   *
   * @param sock Socket from which to read and write messages. The socket is already connected (was
   *     created as a result of an accept).
   * @param sipStack Ptr to SIP Stack
   */
  protected TCPMessageChannel(
      Socket sock,
      SIPTransactionStack sipStack,
      TCPMessageProcessor msgProcessor,
      String threadName)
      throws IOException {

    super(sipStack);
    if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
      logger.logDebug("creating new TCPMessageChannel ");
      logger.logStackTrace();
    }
    mySock = sock;
    peerAddress = mySock.getInetAddress();
    myAddress = msgProcessor.getIpAddress().getHostAddress();
    myClientInputStream = mySock.getInputStream();
    myClientOutputStream = mySock.getOutputStream();
    mythread = new Thread(this);
    mythread.setDaemon(true);
    mythread.setName(threadName);
    this.peerPort = mySock.getPort();
    this.key = MessageChannel.getKey(peerAddress, peerPort, "TCP");

    this.myPort = msgProcessor.getPort();
    // Bug report by Vishwashanti Raj Kadiayl
    super.messageProcessor = msgProcessor;
    // Can drop this after response is sent potentially.
    mythread.start();
  }
Пример #2
0
  /**
   * Constructor - connects to the given inet address. Acknowledgement -- Lamine Brahimi (IBM
   * Zurich) sent in a bug fix for this method. A thread was being uncessarily created.
   *
   * @param inetAddr inet address to connect to.
   * @param sipStack is the sip sipStack from which we are created.
   * @throws IOException if we cannot connect.
   */
  protected TCPMessageChannel(
      InetAddress inetAddr,
      int port,
      SIPTransactionStack sipStack,
      TCPMessageProcessor messageProcessor)
      throws IOException {

    super(sipStack);
    if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
      logger.logDebug("creating new TCPMessageChannel ");
      logger.logStackTrace();
    }
    this.peerAddress = inetAddr;
    this.peerPort = port;
    this.myPort = messageProcessor.getPort();
    this.peerProtocol = "TCP";
    this.myAddress = messageProcessor.getIpAddress().getHostAddress();
    // Bug report by Vishwashanti Raj Kadiayl
    this.key = MessageChannel.getKey(peerAddress, peerPort, "TCP");
    super.messageProcessor = messageProcessor;
  }
  /**
   * Constructor - connects to the given inet address. Acknowledgement -- Lamine Brahimi (IBM
   * Zurich) sent in a bug fix for this method. A thread was being unnecessarily created.
   *
   * @param inetAddr inet address to connect to.
   * @param sipStack is the sip stack from which we are created.
   * @param messageProcessor to whom a parsed message is passed
   * @throws IOException if we cannot connect.
   */
  protected TCPMessageChannel(
      String inetAddr, int port, SIPMessageStack sipStack, TCPMessageProcessor messageProcessor)
      throws IOException {

    this.peerAddress = inetAddr;
    this.peerPort = port;
    this.myPort = messageProcessor.getPort();
    this.peerProtocol = "TCP";
    this.stack = sipStack;
    this.tcpMessageProcessor = messageProcessor;
    this.myAddress = sipStack.getHostAddress();
    // Bug report by Vishwashanti Raj Kadiayl
    super.messageProcessor = messageProcessor;
    this.key = "TCP" + ":" + stack.ioHandler.makeKey(peerAddress, peerPort);

    if (LogWriter.needsLogging)
      LogWriter.logMessage(
          "Created new TCP Message Channel "
              + this
              + " with key "
              + key
              + "\nprocessor: "
              + messageProcessor);
  }
  /**
   * Gets invoked by the parser as a callback on successful message parsing (i.e. no parser errors).
   *
   * @param sipMessage Mesage to process (this calls the application for processing the message).
   */
  public void processMessage(Message sipMessage) {

    if (!stack.isAlive()) {
      if (LogWriter.needsLogging)
        LogWriter.logMessage(
            LogWriter.TRACE_DEBUG,
            "MsgChannel " + this + " is dropping message as the stack is closing");
      return; // drop messages when closing, avoid Exceptions
    }

    try {
      if (LogWriter.needsLogging)
        LogWriter.logMessage(
            "[TCPMessageChannel]-> Processing incoming message: " + sipMessage.getFirstLine());
      if (sipMessage.getFromHeader() == null
          || sipMessage.getTo() == null
          || sipMessage.getCallId() == null
          || sipMessage.getCSeqHeader() == null
          || sipMessage.getViaHeaders() == null) {
        String badmsg = sipMessage.encode();
        if (LogWriter.needsLogging) {
          ServerLog.logMessage("bad message " + badmsg);
          ServerLog.logMessage(">>> Dropped Bad Msg");
        }
        stack.logBadMessage(badmsg);
        return;
      }

      ViaList viaList = sipMessage.getViaHeaders();
      // For a request
      // first via header tells where the message is coming from.
      // For response, this has already been recorded in the outgoing
      // message.
      if (sipMessage instanceof Request) {
        ViaHeader v = (ViaHeader) viaList.first();
        if (v.hasPort()) {
          viaPort = v.getPort();
        } else {
          viaPort = SIPMessageStack.DEFAULT_PORT;
        }
        this.peerProtocol = v.getTransport();
        try {
          if (peerPort == -1) peerPort = mySock.getPort();
          this.peerAddress = mySock.getAddress();

          // Log this because it happens when the remote host identifies
          // as a FQDN but this is not resolvable to an IP by the OS.
          // S40 doesn't have DNS settings, for instance, so if the APN
          // is not able to resolve all the addresses of the SIP/IMS core,
          // this problem will appear.
          if (peerAddress == null && LogWriter.needsLogging)
            LogWriter.logMessage(
                LogWriter.TRACE_EXCEPTION, "WARNING! Socket.getAddress() returned 'null'!!!");

          // Be warned, the host comparison may fail if socket.getAddress()
          // returns a domain name as the Via Host will be a numeric IP.
          // FIXME: No idea. Doing a DNS lookup or reverse DNS lookup
          // can be misleading because they can be non-matching, that is,
          // DNS(peerAddressName) != ReverseDNS(peerAddressIP)
          if (v.hasParameter(ViaHeader.RPORT) || !v.getHost().equals(this.peerAddress)) {
            if (LogWriter.needsLogging)
              LogWriter.logMessage(
                  LogWriter.TRACE_MESSAGES,
                  "WARNING! \"Received\" parameter "
                      + "has been temporarily disabled. Response will be sent to topmost Via Host: "
                      + v.getHost());
            this.peerAddress = v.getHost();
            //		                if (LogWriter.needsLogging)
            //			                   LogWriter.logMessage(LogWriter.TRACE_MESSAGES, "Adding
            // \"received\" parameter" +
            //			                   		" to incoming request with value: " + peerAddress +
            //			                   		" because it doesn't match the Via host " + v.getHost());
            //						v.setParameter(ViaHeader.RECEIVED, this.peerAddress);

          }

          if (v.hasParameter(ViaHeader.RPORT))
            v.setParameter(ViaHeader.RPORT, Integer.toString(this.peerPort));

          /*
           * If socket is invalid, close it because it is useless and dangerous.
           * Also if we ran out of slots for new sockets, as this could prevent
           * incoming connections from being accepted.
           */
          if (mySock.getAddress() == null
              || (stack.maxConnections != -1
                  && tcpMessageProcessor.getNumConnections() >= stack.maxConnections)) {
            stack.ioHandler.disposeSocket(mySock, myClientInputStream, myClientOutputStream);
            mySock = null;
            myClientInputStream = null;
            myClientOutputStream = null;
            if (stack.maxConnections != -1) {
              synchronized (tcpMessageProcessor) {
                tcpMessageProcessor.decreaseNumConnections();
                tcpMessageProcessor.notify();
              }
            }
          }
          // reuse socket even for outgoing requests
          else if (!this.isCached) {
            ((TCPMessageProcessor) this.messageProcessor).cacheMessageChannel(this);
            String key = "TCP" + ":" + stack.ioHandler.makeKey(peerAddress, peerPort);
            stack.ioHandler.putSocket(key, mySock, myClientOutputStream, myClientInputStream);
          }

        } catch (IOException e) {
          e.printStackTrace();
        }
      }

      // System.out.println("receiver address = " + receiverAddress);

      // For each part of the request header, fetch it and process it
      long receptionTime = System.currentTimeMillis();

      if (sipMessage instanceof Request) {
        // This is a request - process the request.
        Request sipRequest = (Request) sipMessage;
        // Create a new sever side request processor for this
        // message and let it handle the rest.

        if (LogWriter.needsLogging) {
          LogWriter.logMessage("----Processing Message---");
        }

        // TODO: check maximum size of request

        SIPServerRequestInterface sipServerRequest = stack.newSIPServerRequest(sipRequest, this);

        if (sipServerRequest != null) {
          try {
            sipServerRequest.processRequest(sipRequest, this);

            ServerLog.logMessage(
                sipMessage,
                sipRequest.getViaHost() + ":" + sipRequest.getViaPort(),
                stack.getHostAddress() + ":" + stack.getPort(this.getTransport()),
                false,
                receptionTime);
          } catch (SIPServerException ex) {
            ServerLog.logMessage(
                sipMessage,
                sipRequest.getViaHost() + ":" + sipRequest.getViaPort(),
                stack.getHostAddress() + ":" + stack.getPort(this.getTransport()),
                ex.getMessage(),
                false,
                receptionTime);
            handleException(ex);
          }

        } else {
          if (LogWriter.needsLogging)
            LogWriter.logMessage("Dropping request -- null sipServerRequest");
        }

      } else {
        // This is a response message - process it.
        Response sipResponse = (Response) sipMessage;

        // TODO: check maximum size of the response

        SIPServerResponseInterface sipServerResponse =
            stack.newSIPServerResponse(sipResponse, this);

        if (LogWriter.needsLogging)
          LogWriter.logMessage("got a response interface " + sipServerResponse);

        try {
          // Responses with no ClienTransaction associated will not be processed
          // as they may cause a NPE in the EventScanner thread.
          if (sipServerResponse != null) sipServerResponse.processResponse(sipResponse, this);
          else {
            if (LogWriter.needsLogging) {
              LogWriter.logMessage("null sipServerResponse!");
            }
          }
        } catch (SIPServerException ex) {
          // An error occured processing the message -- just log it.
          ServerLog.logMessage(
              sipMessage,
              getPeerAddress().toString() + ":" + getPeerPort(),
              stack.getHostAddress() + ":" + stack.getPort(this.getTransport()),
              ex.getMessage(),
              false,
              receptionTime);
          // Ignore errors while processing responses??
        }
      }
    } catch (Exception ee) {
      if (stack.isAlive()) {
        throw new RuntimeException(ee.getClass() + ":" + ee.getMessage());
      }
      // else ignore exceptions
    } finally {
      //            this.tcpMessageProcessor.useCount --;
    }
  }