コード例 #1
0
    protected void runTask() {
      SIPTransaction transaction = SIPTransaction.this;
      // release the connection associated with this transaction.
      SIPTransactionStack sipStack = transaction.getSIPStack();

      if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
        sipStack.getStackLogger().logDebug("LingerTimer: run() : " + getTransactionId());
      }

      if (transaction instanceof SIPClientTransaction) {
        sipStack.removeTransaction(transaction);
        transaction.close();

      } else if (transaction instanceof ServerTransaction) {
        // Remove it from the set
        if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG))
          sipStack.getStackLogger().logDebug("removing" + transaction);
        sipStack.removeTransaction(transaction);
        if ((!sipStack.cacheServerConnections) && --transaction.encapsulatedChannel.useCount <= 0) {
          // Close the encapsulated socket if stack is configured
          transaction.close();
        } else {
          if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)
              && (!sipStack.cacheServerConnections)
              && transaction.isReliable()) {
            int useCount = transaction.encapsulatedChannel.useCount;
            sipStack.getStackLogger().logDebug("Use Count = " + useCount);
          }
        }
      }
    }
コード例 #2
0
  /**
   * Send a message to a specified receiver address.
   *
   * @param msg string to send.
   * @param peerAddress Address of the place to send it to.
   * @param peerPort the port to send it to.
   * @throws IOException If there is trouble sending this message.
   */
  protected void sendMessage(byte[] msg, InetAddress peerAddress, int peerPort, boolean reConnect)
      throws IOException {
    // Via is not included in the request so silently drop the reply.
    if (sipStack.isLoggingEnabled() && this.sipStack.isLogStackTraceOnMessageSend()) {
      this.sipStack.getStackLogger().logStackTrace(StackLogger.TRACE_INFO);
    }
    if (peerPort == -1) {
      if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
        this.sipStack
            .getStackLogger()
            .logDebug(getClass().getName() + ":sendMessage: Dropping reply!");
      }
      throw new IOException("Receiver port not set ");
    } else {
      if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
        this.sipStack
            .getStackLogger()
            .logDebug(
                "sendMessage "
                    + peerAddress.getHostAddress()
                    + "/"
                    + peerPort
                    + "\n"
                    + "messageSize =  "
                    + msg.length
                    + " message = "
                    + new String(msg));
        this.sipStack.getStackLogger().logDebug("*******************\n");
      }
    }
    DatagramPacket reply = new DatagramPacket(msg, msg.length, peerAddress, peerPort);
    try {
      DatagramSocket sock;
      boolean created = false;

      if (sipStack.udpFlag) {
        // Use the socket from the message processor (for firewall
        // support use the same socket as the message processor
        // socket -- feature request # 18 from java.net). This also
        // makes the whole thing run faster!
        sock = ((UDPMessageProcessor) messageProcessor).sock;

        // Bind the socket to the stack address in case there
        // are multiple interfaces on the machine (feature reqeust
        // by Will Scullin) 0 binds to an ephemeral port.
        // sock = new DatagramSocket(0,sipStack.stackInetAddress);
      } else {
        // bind to any interface and port.
        sock = new DatagramSocket();
        created = true;
      }
      sock.send(reply);
      if (created) sock.close();
    } catch (IOException ex) {
      throw ex;
    } catch (Exception ex) {
      InternalErrorHandler.handleException(ex);
    }
  }
コード例 #3
0
  /**
   * Return a reply from a pre-constructed reply. This sends the message back to the entity who
   * caused us to create this channel in the first place.
   *
   * @param sipMessage Message string to send.
   * @throws IOException If there is a problem with sending the message.
   */
  public void sendMessage(SIPMessage sipMessage) throws IOException {
    if (sipStack.isLoggingEnabled() && this.sipStack.isLogStackTraceOnMessageSend()) {
      if (sipMessage instanceof SIPRequest && ((SIPRequest) sipMessage).getRequestLine() != null) {
        /*
         * We dont want to log empty trace messages.
         */
        this.sipStack.getStackLogger().logStackTrace(StackLogger.TRACE_INFO);
      } else {
        this.sipStack.getStackLogger().logStackTrace(StackLogger.TRACE_INFO);
      }
    }

    // Test and see where we are going to send the messsage. If the message
    // is sent back to oursleves, just
    // shortcircuit processing.
    long time = System.currentTimeMillis();
    try {
      for (MessageProcessor messageProcessor : sipStack.getMessageProcessors()) {
        if (messageProcessor.getIpAddress().equals(this.peerAddress)
            && messageProcessor.getPort() == this.peerPort
            && messageProcessor.getTransport().equals(this.peerProtocol)) {
          MessageChannel messageChannel =
              messageProcessor.createMessageChannel(this.peerAddress, this.peerPort);
          if (messageChannel instanceof RawMessageChannel) {
            ((RawMessageChannel) messageChannel).processMessage(sipMessage);
            if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG))
              sipStack.getStackLogger().logDebug("Self routing message");
            return;
          }
        }
      }

      byte[] msg = sipMessage.encodeAsBytes(this.getTransport());

      sendMessage(msg, peerAddress, peerPort, peerProtocol, sipMessage instanceof SIPRequest);

    } catch (IOException ex) {
      throw ex;
    } catch (Exception ex) {
      sipStack.getStackLogger().logError("An exception occured while sending message", ex);
      throw new IOException("An exception occured while sending message");
    } finally {
      if (sipStack.getStackLogger().isLoggingEnabled(ServerLogger.TRACE_MESSAGES)
          && !sipMessage.isNullRequest()) logMessage(sipMessage, peerAddress, peerPort, time);
      else if (sipStack.getStackLogger().isLoggingEnabled(ServerLogger.TRACE_DEBUG))
        sipStack.getStackLogger().logDebug("Sent EMPTY Message");
    }
  }
コード例 #4
0
  /**
   * Sets the request message that this transaction handles.
   *
   * @param newOriginalRequest Request being handled.
   */
  public void setOriginalRequest(SIPRequest newOriginalRequest) {

    // Branch value of topmost Via header
    String newBranch;

    if (this.originalRequest != null
        && (!this.originalRequest
            .getTransactionId()
            .equals(newOriginalRequest.getTransactionId()))) {
      sipStack.removeTransactionHash(this);
    }
    // This will be cleared later.

    this.originalRequest = newOriginalRequest;

    // just cache the control information so the
    // original request can be released later.
    this.method = newOriginalRequest.getMethod();
    this.from = (From) newOriginalRequest.getFrom();
    this.to = (To) newOriginalRequest.getTo();
    // Save these to avoid concurrent modification exceptions!
    this.toTag = this.to.getTag();
    this.fromTag = this.from.getTag();
    this.callId = (CallID) newOriginalRequest.getCallId();
    this.cSeq = newOriginalRequest.getCSeq().getSeqNumber();
    this.event = (Event) newOriginalRequest.getHeader("Event");
    this.transactionId = newOriginalRequest.getTransactionId();

    originalRequest.setTransaction(this);

    // If the message has an explicit branch value set,
    newBranch = ((Via) newOriginalRequest.getViaHeaders().getFirst()).getBranch();
    if (newBranch != null) {
      if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG))
        sipStack.getStackLogger().logDebug("Setting Branch id : " + newBranch);

      // Override the default branch with the one
      // set by the message
      setBranch(newBranch);

    } else {
      if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG))
        sipStack
            .getStackLogger()
            .logDebug("Branch id is null - compute TID!" + newOriginalRequest.encode());
      setBranch(newOriginalRequest.getTransactionId());
    }
  }
コード例 #5
0
  /**
   * Transaction constructor.
   *
   * @param newParentStack Parent stack for this transaction.
   * @param newEncapsulatedChannel Underlying channel for this transaction.
   */
  protected SIPTransaction(
      SIPTransactionStack newParentStack, MessageChannel newEncapsulatedChannel) {

    sipStack = newParentStack;
    this.semaphore = new Semaphore(1, true);

    encapsulatedChannel = newEncapsulatedChannel;
    // Record this to check if the address has changed before sending
    // message to avoid possible race condition.
    this.peerPort = newEncapsulatedChannel.getPeerPort();
    this.peerAddress = newEncapsulatedChannel.getPeerAddress();
    this.peerInetAddress = newEncapsulatedChannel.getPeerInetAddress();
    // @@@ hagai
    this.peerPacketSourcePort = newEncapsulatedChannel.getPeerPacketSourcePort();
    this.peerPacketSourceAddress = newEncapsulatedChannel.getPeerPacketSourceAddress();
    this.peerProtocol = newEncapsulatedChannel.getPeerProtocol();
    if (this.isReliable()) {
      encapsulatedChannel.useCount++;
      if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG))
        sipStack
            .getStackLogger()
            .logDebug(
                "use count for encapsulated channel" + this + " " + encapsulatedChannel.useCount);
    }

    this.currentState = null;

    disableRetransmissionTimer();
    disableTimeoutTimer();
    eventListeners = Collections.synchronizedSet(new HashSet<SIPTransactionEventListener>());

    // Always add the parent stack as a listener
    // of this transaction
    addEventListener(newParentStack);
  }
コード例 #6
0
 /**
  * Changes the state of this transaction.
  *
  * @param newState New state of this transaction.
  */
 public void setState(TransactionState newState) {
   // PATCH submitted by sribeyron
   if (currentState == TransactionState.COMPLETED) {
     if (newState != TransactionState.TERMINATED && newState != TransactionState.CONFIRMED)
       newState = TransactionState.COMPLETED;
   }
   if (currentState == TransactionState.CONFIRMED) {
     if (newState != TransactionState.TERMINATED) newState = TransactionState.CONFIRMED;
   }
   if (currentState != TransactionState.TERMINATED) currentState = newState;
   else newState = currentState;
   // END OF PATCH
   if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
     sipStack
         .getStackLogger()
         .logDebug(
             "Transaction:setState "
                 + newState
                 + " "
                 + this
                 + " branchID = "
                 + this.getBranch()
                 + " isClient = "
                 + (this instanceof SIPClientTransaction));
     sipStack.getStackLogger().logStackTrace();
   }
 }
コード例 #7
0
 /**
  * Log a message into the log file.
  *
  * @param message message to log into the log file.
  */
 private void logMessage(String message) {
   // String tname = Thread.currentThread().getName();
   checkLogFile();
   String logInfo = message;
   if (printWriter != null) {
     printWriter.println(logInfo);
   }
   if (sipStack.isLoggingEnabled()) {
     stackLogger.logInfo(logInfo);
   }
 }
コード例 #8
0
 /**
  * Implementation of the ParseExceptionListener interface.
  *
  * @param ex Exception that is given to us by the parser.
  * @throws ParseException If we choose to reject the header or message.
  */
 public void handleException(
     ParseException ex, SIPMessage sipMessage, Class hdrClass, String header, String message)
     throws ParseException {
   if (sipStack.isLoggingEnabled()) this.sipStack.getStackLogger().logException(ex);
   // Log the bad message for later reference.
   if ((hdrClass != null)
       && (hdrClass.equals(From.class)
           || hdrClass.equals(To.class)
           || hdrClass.equals(CSeq.class)
           || hdrClass.equals(Via.class)
           || hdrClass.equals(CallID.class)
           || hdrClass.equals(RequestLine.class)
           || hdrClass.equals(StatusLine.class))) {
     if (sipStack.isLoggingEnabled()) {
       sipStack.getStackLogger().logError("BAD MESSAGE!");
       sipStack.getStackLogger().logError(message);
     }
     throw ex;
   } else {
     sipMessage.addUnparsed(header);
   }
 }
コード例 #9
0
  protected void semRelease() {
    try {
      if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
        sipStack.getStackLogger().logDebug("semRelease ]]]]" + this);
        sipStack.getStackLogger().logStackTrace();
      }
      this.isSemaphoreAquired = false;
      this.semaphore.release();

    } catch (Exception ex) {
      sipStack.getStackLogger().logError("Unexpected exception releasing sem", ex);
    }
  }
コード例 #10
0
  /**
   * Enables a timeout event to occur for this transaction after the number of ticks passed to this
   * method.
   *
   * @param tickCount Number of ticks before this transaction times out.
   */
  protected final void enableTimeoutTimer(int tickCount) {
    if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG))
      sipStack
          .getStackLogger()
          .logDebug(
              "enableTimeoutTimer "
                  + this
                  + " tickCount "
                  + tickCount
                  + " currentTickCount = "
                  + timeoutTimerTicksLeft);

    timeoutTimerTicksLeft = tickCount;
  }
コード例 #11
0
 /**
  * Constructor. We create one of these when we send out a message.
  *
  * @param targetAddr INET address of the place where we want to send messages.
  * @param port target port (where we want to send the message).
  * @param sipStack our SIP Stack.
  */
 protected UDPMessageChannel(
     InetAddress targetAddr,
     int port,
     SIPTransactionStack sipStack,
     UDPMessageProcessor messageProcessor) {
   peerAddress = targetAddr;
   peerPort = port;
   peerProtocol = "UDP";
   super.messageProcessor = messageProcessor;
   this.myAddress = messageProcessor.getIpAddress().getHostAddress();
   this.myPort = messageProcessor.getPort();
   this.sipStack = sipStack;
   if (sipStack.isLoggingEnabled()) {
     this.sipStack.logWriter.logDebug(
         "Creating message channel " + targetAddr.getHostAddress() + "/" + port);
   }
 }
コード例 #12
0
  /**
   * Constructor. We create one of these when we send out a message.
   *
   * @param targetAddr INET address of the place where we want to send messages.
   * @param port target port (where we want to send the message).
   * @param sipStack our SIP Stack.
   */
  protected UDPMessageChannel(
      InetAddress targetAddr,
      int port,
      SIPTransactionStack sipStack,
      UDPMessageProcessor messageProcessor) {
    peerAddress = targetAddr;
    peerPort = port;
    peerProtocol = "UDP";
    super.messageProcessor = messageProcessor;
    this.myAddress = messageProcessor.getIpAddress().getHostAddress();
    this.myPort = messageProcessor.getPort();
    this.sipStack = sipStack;
    // jeand : Create a new string message parser to parse the list of messages.
    myParser = sipStack.getMessageParserFactory().createMessageParser(sipStack);

    if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
      this.sipStack
          .getStackLogger()
          .logDebug("Creating message channel " + targetAddr.getHostAddress() + "/" + port);
    }
  }
コード例 #13
0
 /**
  * A given tx can process only a single outstanding event at a time. This semaphore gaurds
  * re-entrancy to the transaction.
  */
 public boolean acquireSem() {
   boolean retval = false;
   try {
     if (sipStack.getStackLogger().isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
       sipStack.getStackLogger().logDebug("acquireSem [[[[" + this);
       sipStack.getStackLogger().logStackTrace();
     }
     if (this.sipStack.maxListenerResponseTime == -1) {
       this.semaphore.acquire();
       retval = true;
     } else {
       retval = this.semaphore.tryAcquire(this.sipStack.maxListenerResponseTime, TimeUnit.SECONDS);
     }
     if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG))
       sipStack.getStackLogger().logDebug("acquireSem() returning : " + retval);
     return retval;
   } catch (Exception ex) {
     sipStack.getStackLogger().logError("Unexpected exception acquiring sem", ex);
     InternalErrorHandler.handleException(ex);
     return false;
   } finally {
     this.isSemaphoreAquired = retval;
   }
 }
コード例 #14
0
  /**
   * Send a message to a specified receiver address.
   *
   * @param msg message string to send.
   * @param peerAddress Address of the place to send it to.
   * @param peerPort the port to send it to.
   * @param peerProtocol protocol to use to send.
   * @throws IOException If there is trouble sending this message.
   */
  protected void sendMessage(
      byte[] msg, InetAddress peerAddress, int peerPort, String peerProtocol, boolean retry)
      throws IOException {
    // Via is not included in the request so silently drop the reply.
    if (peerPort == -1) {
      if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
        this.sipStack
            .getStackLogger()
            .logDebug(getClass().getName() + ":sendMessage: Dropping reply!");
      }
      throw new IOException("Receiver port not set ");
    } else {
      if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
        this.sipStack
            .getStackLogger()
            .logDebug(
                ":sendMessage "
                    + peerAddress.getHostAddress()
                    + "/"
                    + peerPort
                    + "\n"
                    + " messageSize = "
                    + msg.length);
      }
    }
    if (peerProtocol.compareToIgnoreCase("UDP") == 0) {
      DatagramPacket reply = new DatagramPacket(msg, msg.length, peerAddress, peerPort);

      try {
        DatagramSocket sock;
        if (sipStack.udpFlag) {
          sock = ((UDPMessageProcessor) messageProcessor).sock;

        } else {
          // bind to any interface and port.
          sock = sipStack.getNetworkLayer().createDatagramSocket();
        }
        if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
          this.sipStack
              .getStackLogger()
              .logDebug(
                  "sendMessage "
                      + peerAddress.getHostAddress()
                      + "/"
                      + peerPort
                      + "\n"
                      + new String(msg));
        }
        sock.send(reply);
        if (!sipStack.udpFlag) sock.close();
      } catch (IOException ex) {
        throw ex;
      } catch (Exception ex) {
        InternalErrorHandler.handleException(ex);
      }

    } else {
      // Use TCP to talk back to the sender.
      Socket outputSocket =
          sipStack.ioHandler.sendBytes(
              this.messageProcessor.getIpAddress(), peerAddress, peerPort, "tcp", msg, retry, this);
      OutputStream myOutputStream = outputSocket.getOutputStream();
      myOutputStream.write(msg, 0, msg.length);
      myOutputStream.flush();
      // The socket is cached (dont close it!);
    }
  }
コード例 #15
0
  public void checkLogFile() {
    if (logFileName == null || traceLevel < TRACE_MESSAGES) {
      // Dont create a log file if tracing is
      // disabled.
      return;
    }
    try {
      File logFile = new File(logFileName);
      if (!logFile.exists()) {
        logFile.createNewFile();
        printWriter = null;
      }
      // Append buffer to the end of the file unless otherwise specified
      // by the user.
      if (printWriter == null) {
        boolean overwrite =
            Boolean.valueOf(
                configurationProperties.getProperty("gov.nist.javax.sip.SERVER_LOG_OVERWRITE"));

        FileWriter fw = new FileWriter(logFileName, !overwrite);

        printWriter = new PrintWriter(fw, true);
        printWriter.println(
            "<!-- "
                + "Use the  Trace Viewer in src/tools/tracesviewer to"
                + " view this  trace  \n"
                + "Here are the stack configuration properties \n"
                + "javax.sip.IP_ADDRESS= "
                + configurationProperties.getProperty("javax.sip.IP_ADDRESS")
                + "\n"
                + "javax.sip.STACK_NAME= "
                + configurationProperties.getProperty("javax.sip.STACK_NAME")
                + "\n"
                + "javax.sip.ROUTER_PATH= "
                + configurationProperties.getProperty("javax.sip.ROUTER_PATH")
                + "\n"
                + "javax.sip.OUTBOUND_PROXY= "
                + configurationProperties.getProperty("javax.sip.OUTBOUND_PROXY")
                + "\n"
                + "-->");
        printWriter.println(
            "<description\n logDescription=\""
                + description
                + "\"\n name=\""
                + configurationProperties.getProperty("javax.sip.STACK_NAME")
                + "\"\n auxInfo=\""
                + auxInfo
                + "\"/>\n ");
        if (auxInfo != null) {

          if (sipStack.isLoggingEnabled()) {
            stackLogger.logDebug(
                "Here are the stack configuration properties \n"
                    + "javax.sip.IP_ADDRESS= "
                    + configurationProperties.getProperty("javax.sip.IP_ADDRESS")
                    + "\n"
                    + "javax.sip.ROUTER_PATH= "
                    + configurationProperties.getProperty("javax.sip.ROUTER_PATH")
                    + "\n"
                    + "javax.sip.OUTBOUND_PROXY= "
                    + configurationProperties.getProperty("javax.sip.OUTBOUND_PROXY")
                    + "\n"
                    + "gov.nist.javax.sip.CACHE_CLIENT_CONNECTIONS= "
                    + configurationProperties.getProperty(
                        "gov.nist.javax.sip.CACHE_CLIENT_CONNECTIONS")
                    + "\n"
                    + "gov.nist.javax.sip.CACHE_SERVER_CONNECTIONS= "
                    + configurationProperties.getProperty(
                        "gov.nist.javax.sip.CACHE_SERVER_CONNECTIONS")
                    + "\n"
                    + "gov.nist.javax.sip.REENTRANT_LISTENER= "
                    + configurationProperties.getProperty("gov.nist.javax.sip.REENTRANT_LISTENER")
                    + "gov.nist.javax.sip.THREAD_POOL_SIZE= "
                    + configurationProperties.getProperty("gov.nist.javax.sip.THREAD_POOL_SIZE")
                    + "\n");
            stackLogger.logDebug(" ]]> ");
            stackLogger.logDebug("</debug>");
            stackLogger.logDebug(
                "<description\n logDescription=\""
                    + description
                    + "\"\n name=\""
                    + stackIpAddress
                    + "\"\n auxInfo=\""
                    + auxInfo
                    + "\"/>\n ");
            stackLogger.logDebug("<debug>");
            stackLogger.logDebug("<![CDATA[ ");
          }
        } else {

          if (sipStack.isLoggingEnabled()) {
            stackLogger.logDebug(
                "Here are the stack configuration properties \n" + configurationProperties + "\n");
            stackLogger.logDebug(" ]]>");
            stackLogger.logDebug("</debug>");
            stackLogger.logDebug(
                "<description\n logDescription=\""
                    + description
                    + "\"\n name=\""
                    + stackIpAddress
                    + "\" />\n");
            stackLogger.logDebug("<debug>");
            stackLogger.logDebug("<![CDATA[ ");
          }
        }
      }
    } catch (IOException ex) {

    }
  }
コード例 #16
0
  /**
   * Process an incoming datagram
   *
   * @param packet is the incoming datagram packet.
   */
  private void processIncomingDataPacket(DatagramPacket packet) throws Exception {
    this.peerAddress = packet.getAddress();
    int packetLength = packet.getLength();
    // Read bytes and put it in a eueue.
    byte[] bytes = packet.getData();
    byte[] msgBytes = new byte[packetLength];
    System.arraycopy(bytes, 0, msgBytes, 0, packetLength);

    // Do debug logging.
    if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
      this.sipStack
          .getStackLogger()
          .logDebug(
              "UDPMessageChannel: processIncomingDataPacket : peerAddress = "
                  + peerAddress.getHostAddress()
                  + "/"
                  + packet.getPort()
                  + " Length = "
                  + packetLength);
    }

    SIPMessage sipMessage = null;
    try {
      this.receptionTime = System.currentTimeMillis();
      sipMessage = myParser.parseSIPMessage(msgBytes, true, false, this);
      //            myParser = null;
    } catch (ParseException ex) {
      //            myParser = null; // let go of the parser reference.
      if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
        this.sipStack.getStackLogger().logDebug("Rejecting message !  " + new String(msgBytes));
        this.sipStack.getStackLogger().logDebug("error message " + ex.getMessage());
        this.sipStack.getStackLogger().logException(ex);
      }

      // JvB: send a 400 response for requests (except ACK)
      // Currently only UDP, @todo also other transports
      String msgString = new String(msgBytes, 0, packetLength);
      if (!msgString.startsWith("SIP/") && !msgString.startsWith("ACK ")) {

        String badReqRes = createBadReqRes(msgString, ex);
        if (badReqRes != null) {
          if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
            sipStack.getStackLogger().logDebug("Sending automatic 400 Bad Request:");
            sipStack.getStackLogger().logDebug(badReqRes);
          }
          try {
            this.sendMessage(badReqRes.getBytes(), peerAddress, packet.getPort(), "UDP", false);
          } catch (IOException e) {
            this.sipStack.getStackLogger().logException(e);
          }
        } else {
          if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
            sipStack.getStackLogger().logDebug("Could not formulate automatic 400 Bad Request");
          }
        }
      }

      return;
    }
    // No parse exception but null message - reject it and
    // march on (or return).
    // exit this message processor if the message did not parse.

    if (sipMessage == null) {
      if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
        this.sipStack.getStackLogger().logDebug("Rejecting message !  + Null message parsed.");
      }
      String key = packet.getAddress().getHostAddress() + ":" + packet.getPort();
      if (pingBackRecord.get(key) == null && sipStack.getMinKeepAliveInterval() > 0) {
        byte[] retval = "\r\n\r\n".getBytes();
        DatagramPacket keepalive =
            new DatagramPacket(retval, 0, retval.length, packet.getAddress(), packet.getPort());
        PingBackTimerTask task =
            new PingBackTimerTask(packet.getAddress().getHostAddress(), packet.getPort());
        this.pingBackRecord.put(key, task);
        this.sipStack.getTimer().schedule(task, sipStack.getMinKeepAliveInterval() * 1000);
        ((UDPMessageProcessor) this.messageProcessor).sock.send(keepalive);
      } else {
        sipStack.getStackLogger().logDebug("Not sending ping back");
      }
      return;
    }
    Via topMostVia = sipMessage.getTopmostVia();
    // Check for the required headers.
    if (sipMessage.getFrom() == null
        || sipMessage.getTo() == null
        || sipMessage.getCallId() == null
        || sipMessage.getCSeq() == null
        || topMostVia == null) {
      String badmsg = new String(msgBytes);
      if (sipStack.isLoggingEnabled()) {
        this.sipStack.getStackLogger().logError("bad message " + badmsg);
        this.sipStack
            .getStackLogger()
            .logError(
                ">>> Dropped Bad Msg "
                    + "From = "
                    + sipMessage.getFrom()
                    + "To = "
                    + sipMessage.getTo()
                    + "CallId = "
                    + sipMessage.getCallId()
                    + "CSeq = "
                    + sipMessage.getCSeq()
                    + "Via = "
                    + sipMessage.getViaHeaders());
      }
      return;
    }
    // For a request first via header tells where the message
    // is coming from.
    // For response, just get the port from the packet.
    if (sipMessage instanceof SIPRequest) {
      Hop hop = sipStack.addressResolver.resolveAddress(topMostVia.getHop());
      this.peerPort = hop.getPort();
      this.peerProtocol = topMostVia.getTransport();

      this.peerPacketSourceAddress = packet.getAddress();
      this.peerPacketSourcePort = packet.getPort();
      try {
        this.peerAddress = packet.getAddress();
        // Check to see if the received parameter matches
        // the peer address and tag it appropriately.

        boolean hasRPort = topMostVia.hasParameter(Via.RPORT);
        if (hasRPort || !hop.getHost().equals(this.peerAddress.getHostAddress())) {
          topMostVia.setParameter(Via.RECEIVED, this.peerAddress.getHostAddress());
        }

        if (hasRPort) {
          topMostVia.setParameter(Via.RPORT, Integer.toString(this.peerPacketSourcePort));
        }
      } catch (java.text.ParseException ex1) {
        InternalErrorHandler.handleException(ex1);
      }

    } else {

      this.peerPacketSourceAddress = packet.getAddress();
      this.peerPacketSourcePort = packet.getPort();
      this.peerAddress = packet.getAddress();
      this.peerPort = packet.getPort();
      this.peerProtocol = topMostVia.getTransport();
    }

    this.processMessage(sipMessage);
  }
コード例 #17
0
  /**
   * Actually proces the parsed message.
   *
   * @param sipMessage
   */
  public void processMessage(SIPMessage sipMessage) {

    if (sipMessage instanceof SIPRequest) {
      SIPRequest sipRequest = (SIPRequest) sipMessage;

      // This is a request - process it.
      // So far so good -- we will commit this message if
      // all processing is OK.
      if (sipStack.getStackLogger().isLoggingEnabled(ServerLogger.TRACE_MESSAGES)) {

        this.sipStack.serverLogger.logMessage(
            sipMessage,
            this.getPeerHostPort().toString(),
            this.getHost() + ":" + this.myPort,
            false,
            receptionTime);
      }
      final ServerRequestInterface sipServerRequest =
          sipStack.newSIPServerRequest(sipRequest, this);
      // Drop it if there is no request returned
      if (sipServerRequest == null) {
        if (sipStack.isLoggingEnabled()) {
          this.sipStack
              .getStackLogger()
              .logWarning("Null request interface returned -- dropping request");
        }

        return;
      }
      if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG))
        this.sipStack
            .getStackLogger()
            .logDebug("About to process " + sipRequest.getFirstLine() + "/" + sipServerRequest);
      try {
        sipServerRequest.processRequest(sipRequest, this);
      } finally {
        if (sipServerRequest instanceof SIPTransaction) {
          SIPServerTransaction sipServerTx = (SIPServerTransaction) sipServerRequest;
          if (!sipServerTx.passToListener()) {
            ((SIPTransaction) sipServerRequest).releaseSem();
          }
        }
      }
      if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG))
        this.sipStack
            .getStackLogger()
            .logDebug("Done processing " + sipRequest.getFirstLine() + "/" + sipServerRequest);

      // So far so good -- we will commit this message if
      // all processing is OK.

    } else {
      // Handle a SIP Reply message.
      SIPResponse sipResponse = (SIPResponse) sipMessage;
      try {
        sipResponse.checkHeaders();
      } catch (ParseException ex) {
        if (sipStack.isLoggingEnabled())
          sipStack
              .getStackLogger()
              .logError("Dropping Badly formatted response message >>> " + sipResponse);
        return;
      }
      ServerResponseInterface sipServerResponse = sipStack.newSIPServerResponse(sipResponse, this);
      if (sipServerResponse != null) {
        try {
          if (sipServerResponse instanceof SIPClientTransaction
              && !((SIPClientTransaction) sipServerResponse).checkFromTag(sipResponse)) {
            if (sipStack.isLoggingEnabled())
              sipStack
                  .getStackLogger()
                  .logError("Dropping response message with invalid tag >>> " + sipResponse);
            return;
          }

          sipServerResponse.processResponse(sipResponse, this);
        } finally {
          if (sipServerResponse instanceof SIPTransaction
              && !((SIPTransaction) sipServerResponse).passToListener())
            ((SIPTransaction) sipServerResponse).releaseSem();
        }

        // Normal processing of message.
      } else {
        if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
          this.sipStack.getStackLogger().logDebug("null sipServerResponse!");
        }
      }
    }
  }
コード例 #18
0
 /**
  * Extract identities from certificates exchanged over TLS, based on guidelines from
  * draft-ietf-sip-domain-certs-04.
  *
  * @return list of authenticated identities
  */
 public List<String> extractCertIdentities() throws SSLPeerUnverifiedException {
   if (this.getMessageChannel() instanceof TLSMessageChannel) {
     List<String> certIdentities = new ArrayList<String>();
     Certificate[] certs = getPeerCertificates();
     if (certs == null) {
       if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
         sipStack.getStackLogger().logDebug("No certificates available");
       }
       return certIdentities;
     }
     for (Certificate cert : certs) {
       X509Certificate x509cert = (X509Certificate) cert;
       Collection<List<?>> subjAltNames = null;
       try {
         subjAltNames = x509cert.getSubjectAlternativeNames();
       } catch (CertificateParsingException ex) {
         if (sipStack.isLoggingEnabled()) {
           sipStack.getStackLogger().logError("Error parsing TLS certificate", ex);
         }
       }
       // subjAltName types are defined in rfc2459
       final Integer dnsNameType = 2;
       final Integer uriNameType = 6;
       if (subjAltNames != null) {
         if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
           sipStack.getStackLogger().logDebug("found subjAltNames: " + subjAltNames);
         }
         // First look for a URI in the subjectAltName field
         // as per draft-ietf-sip-domain-certs-04
         for (List<?> altName : subjAltNames) {
           // 0th position is the alt name type
           // 1st position is the alt name data
           if (altName.get(0).equals(uriNameType)) {
             SipURI altNameUri;
             try {
               altNameUri = new AddressFactoryImpl().createSipURI((String) altName.get(1));
               String altHostName = altNameUri.getHost();
               if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
                 sipStack
                     .getStackLogger()
                     .logDebug("found uri " + altName.get(1) + ", hostName " + altHostName);
               }
               certIdentities.add(altHostName);
             } catch (ParseException e) {
               if (sipStack.isLoggingEnabled()) {
                 sipStack
                     .getStackLogger()
                     .logError("certificate contains invalid uri: " + altName.get(1));
               }
             }
           }
         }
         // DNS An implementation MUST accept a domain name system
         // identifier as a SIP domain identity if and only if no other
         // identity is found that matches the "sip" URI type described
         // above.
         if (certIdentities.isEmpty()) {
           for (List<?> altName : subjAltNames) {
             if (altName.get(0).equals(dnsNameType)) {
               if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
                 sipStack.getStackLogger().logDebug("found dns " + altName.get(1));
               }
               certIdentities.add(altName.get(1).toString());
             }
           }
         }
       } else {
         // If and only if the subjectAltName does not appear in the
         // certificate, the implementation MAY examine the CN field of the
         // certificate. If a valid DNS name is found there, the
         // implementation MAY accept this value as a SIP domain identity.
         String dname = x509cert.getSubjectDN().getName();
         String cname = "";
         try {
           Pattern EXTRACT_CN = Pattern.compile(".*CN\\s*=\\s*([\\w*\\.]+).*");
           Matcher matcher = EXTRACT_CN.matcher(dname);
           if (matcher.matches()) {
             cname = matcher.group(1);
             if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
               sipStack.getStackLogger().logDebug("found CN: " + cname + " from DN: " + dname);
             }
             certIdentities.add(cname);
           }
         } catch (Exception ex) {
           if (sipStack.isLoggingEnabled()) {
             sipStack.getStackLogger().logError("exception while extracting CN", ex);
           }
         }
       }
     }
     return certIdentities;
   } else throw new UnsupportedOperationException("Not a TLS channel");
 }
コード例 #19
0
 /** Set the passToListener flag to true. */
 public void setPassToListener() {
   if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
     sipStack.getStackLogger().logDebug("setPassToListener()");
   }
   this.toListener = true;
 }
コード例 #20
0
  /**
   * Process the message through the transaction and sends it to the SIP peer.
   *
   * @param messageToSend Message to send to the SIP peer.
   */
  public void sendMessage(final SIPMessage messageToSend) throws IOException {
    // Use the peer address, port and transport
    // that was specified when the transaction was
    // created. Bug was noted by Bruce Evangelder
    // soleo communications.
    try {
      final RawMessageChannel channel = (RawMessageChannel) encapsulatedChannel;
      for (MessageProcessor messageProcessor : sipStack.getMessageProcessors()) {
        boolean addrmatch =
            messageProcessor
                .getIpAddress()
                .getHostAddress()
                .toString()
                .equals(this.getPeerAddress());
        if (addrmatch
            && messageProcessor.getPort() == this.getPeerPort()
            && messageProcessor.getTransport().equalsIgnoreCase(this.getPeerProtocol())) {
          if (channel instanceof TCPMessageChannel) {
            try {

              Runnable processMessageTask =
                  new Runnable() {

                    public void run() {
                      try {
                        ((TCPMessageChannel) channel)
                            .processMessage(
                                (SIPMessage) messageToSend.clone(), getPeerInetAddress());
                      } catch (Exception ex) {
                        if (getSIPStack()
                            .getStackLogger()
                            .isLoggingEnabled(ServerLogger.TRACE_ERROR)) {
                          getSIPStack()
                              .getStackLogger()
                              .logError("Error self routing message cause by: ", ex);
                        }
                      }
                    }
                  };
              getSIPStack().getSelfRoutingThreadpoolExecutor().execute(processMessageTask);

            } catch (Exception e) {
              sipStack.getStackLogger().logError("Error passing message in self routing", e);
            }
            if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG))
              sipStack.getStackLogger().logDebug("Self routing message");
            return;
          }
          if (channel instanceof RawMessageChannel) {
            try {

              Runnable processMessageTask =
                  new Runnable() {

                    public void run() {
                      try {
                        ((RawMessageChannel) channel)
                            .processMessage((SIPMessage) messageToSend.clone());
                      } catch (Exception ex) {
                        if (getSIPStack()
                            .getStackLogger()
                            .isLoggingEnabled(ServerLogger.TRACE_ERROR)) {
                          getSIPStack()
                              .getStackLogger()
                              .logError("Error self routing message cause by: ", ex);
                        }
                      }
                    }
                  };
              getSIPStack().getSelfRoutingThreadpoolExecutor().execute(processMessageTask);
            } catch (Exception e) {
              sipStack.getStackLogger().logError("Error passing message in self routing", e);
            }
            if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG))
              sipStack.getStackLogger().logDebug("Self routing message");
            return;
          }
        }
      }
      encapsulatedChannel.sendMessage(messageToSend, this.peerInetAddress, this.peerPort);
    } finally {
      this.startTransactionTimer();
    }
  }
コード例 #21
0
  /**
   * Process an incoming datagram
   *
   * @param packet is the incoming datagram packet.
   */
  private void processIncomingDataPacket(DatagramPacket packet) throws Exception {
    this.peerAddress = packet.getAddress();
    int packetLength = packet.getLength();
    // Read bytes and put it in a eueue.
    byte[] bytes = packet.getData();
    byte[] msgBytes = new byte[packetLength];
    System.arraycopy(bytes, 0, msgBytes, 0, packetLength);

    // Do debug logging.
    if (sipStack.isLoggingEnabled()) {
      this.sipStack.logWriter.logDebug(
          "UDPMessageChannel: processIncomingDataPacket : peerAddress = "
              + peerAddress.getHostAddress()
              + "/"
              + packet.getPort()
              + " Length = "
              + packetLength);
    }

    SIPMessage sipMessage = null;
    try {
      this.receptionTime = System.currentTimeMillis();
      sipMessage = myParser.parseSIPMessage(msgBytes);
      myParser = null;
    } catch (ParseException ex) {
      myParser = null; // let go of the parser reference.
      if (sipStack.isLoggingEnabled()) {
        this.sipStack.logWriter.logDebug("Rejecting message !  " + new String(msgBytes));
        this.sipStack.logWriter.logDebug("error message " + ex.getMessage());
        this.sipStack.logWriter.logException(ex);
      }

      // JvB: send a 400 response for requests (except ACK)
      // Currently only UDP, @todo also other transports
      String msgString = new String(msgBytes, 0, packetLength);
      if (!msgString.startsWith("SIP/") && !msgString.startsWith("ACK ")) {

        String badReqRes = createBadReqRes(msgString, ex);
        if (badReqRes != null) {
          if (sipStack.isLoggingEnabled()) {
            sipStack.getLogWriter().logDebug("Sending automatic 400 Bad Request:");
            sipStack.getLogWriter().logDebug(badReqRes);
          }
          try {
            this.sendMessage(badReqRes.getBytes(), peerAddress, packet.getPort(), "UDP", false);
          } catch (IOException e) {
            this.sipStack.logWriter.logException(e);
          }
        } else {
          if (sipStack.isLoggingEnabled()) {
            sipStack.getLogWriter().logDebug("Could not formulate automatic 400 Bad Request");
          }
        }
      }

      return;
    }
    // No parse exception but null message - reject it and
    // march on (or return).
    // exit this message processor if the message did not parse.

    if (sipMessage == null) {
      if (sipStack.isLoggingEnabled()) {
        this.sipStack.logWriter.logDebug("Rejecting message !  + Null message parsed.");
      }
      return;
    }
    ViaList viaList = sipMessage.getViaHeaders();
    // Check for the required headers.
    if (sipMessage.getFrom() == null
        || sipMessage.getTo() == null
        || sipMessage.getCallId() == null
        || sipMessage.getCSeq() == null
        || sipMessage.getViaHeaders() == null) {
      String badmsg = new String(msgBytes);
      if (sipStack.isLoggingEnabled()) {
        this.sipStack.logWriter.logError("bad message " + badmsg);
        this.sipStack.logWriter.logError(
            ">>> Dropped Bad Msg "
                + "From = "
                + sipMessage.getFrom()
                + "To = "
                + sipMessage.getTo()
                + "CallId = "
                + sipMessage.getCallId()
                + "CSeq = "
                + sipMessage.getCSeq()
                + "Via = "
                + sipMessage.getViaHeaders());
      }

      sipStack.logWriter.logError("BAD MESSAGE!");

      return;
    }
    // For a request first via header tells where the message
    // is coming from.
    // For response, just get the port from the packet.
    if (sipMessage instanceof SIPRequest) {
      Via v = (Via) viaList.getFirst();
      Hop hop = sipStack.addressResolver.resolveAddress(v.getHop());
      this.peerPort = hop.getPort();
      this.peerProtocol = v.getTransport();

      this.peerPacketSourceAddress = packet.getAddress();
      this.peerPacketSourcePort = packet.getPort();
      try {
        this.peerAddress = packet.getAddress();
        // Check to see if the received parameter matches
        // the peer address and tag it appropriately.

        boolean hasRPort = v.hasParameter(Via.RPORT);
        if (hasRPort || !hop.getHost().equals(this.peerAddress.getHostAddress())) {
          v.setParameter(Via.RECEIVED, this.peerAddress.getHostAddress());
        }

        if (hasRPort) {
          v.setParameter(Via.RPORT, Integer.toString(this.peerPacketSourcePort));
        }
      } catch (java.text.ParseException ex1) {
        InternalErrorHandler.handleException(ex1);
      }

    } else {

      this.peerPacketSourceAddress = packet.getAddress();
      this.peerPacketSourcePort = packet.getPort();
      this.peerAddress = packet.getAddress();
      this.peerPort = packet.getPort();
      this.peerProtocol = ((Via) viaList.getFirst()).getTransport();
    }

    this.processMessage(sipMessage);
  }
コード例 #22
0
  /**
   * A method that can be used to test if an incoming request belongs to this transction. This does
   * not take the transaction state into account when doing the check otherwise it is identical to
   * isMessagePartOfTransaction. This is useful for checking if a CANCEL belongs to this
   * transaction.
   *
   * @param requestToTest is the request to test.
   * @return true if the the request belongs to the transaction.
   */
  public boolean doesCancelMatchTransaction(SIPRequest requestToTest) {

    // List of Via headers in the message to test
    ViaList viaHeaders;
    // Topmost Via header in the list
    Via topViaHeader;
    // Branch code in the topmost Via header
    String messageBranch;
    // Flags whether the select message is part of this transaction
    boolean transactionMatches;

    transactionMatches = false;

    if (this.getOriginalRequest() == null
        || this.getOriginalRequest().getMethod().equals(Request.CANCEL)) return false;
    // Get the topmost Via header and its branch parameter
    viaHeaders = requestToTest.getViaHeaders();
    if (viaHeaders != null) {

      topViaHeader = (Via) viaHeaders.getFirst();
      messageBranch = topViaHeader.getBranch();
      if (messageBranch != null) {

        // If the branch parameter exists but
        // does not start with the magic cookie,
        if (!messageBranch.toLowerCase().startsWith(SIPConstants.BRANCH_MAGIC_COOKIE_LOWER_CASE)) {

          // Flags this as old
          // (RFC2543-compatible) client
          // version
          messageBranch = null;
        }
      }

      // If a new branch parameter exists,
      if (messageBranch != null && this.getBranch() != null) {

        // If the branch equals the branch in
        // this message,
        if (getBranch().equalsIgnoreCase(messageBranch)
            && topViaHeader
                .getSentBy()
                .equals(((Via) getOriginalRequest().getViaHeaders().getFirst()).getSentBy())) {
          transactionMatches = true;
          if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG))
            sipStack.getStackLogger().logDebug("returning  true");
        }

      } else {
        // If this is an RFC2543-compliant message,
        // If RequestURI, To tag, From tag,
        // CallID, CSeq number, and top Via
        // headers are the same,
        if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG))
          sipStack.getStackLogger().logDebug("testing against " + getOriginalRequest());

        if (getOriginalRequest().getRequestURI().equals(requestToTest.getRequestURI())
            && getOriginalRequest().getTo().equals(requestToTest.getTo())
            && getOriginalRequest().getFrom().equals(requestToTest.getFrom())
            && getOriginalRequest()
                .getCallId()
                .getCallId()
                .equals(requestToTest.getCallId().getCallId())
            && getOriginalRequest().getCSeq().getSeqNumber()
                == requestToTest.getCSeq().getSeqNumber()
            && topViaHeader.equals(getOriginalRequest().getViaHeaders().getFirst())) {

          transactionMatches = true;
        }
      }
    }

    // JvB: Need to pass the CANCEL to the listener! Retransmitted INVITEs
    // set it to false
    if (transactionMatches) {
      this.setPassToListener();
    }
    return transactionMatches;
  }
コード例 #23
0
 /** Close the encapsulated channel. */
 public void close() {
   this.encapsulatedChannel.close();
   if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG))
     sipStack.getStackLogger().logDebug("Closing " + this.encapsulatedChannel);
 }