Esempio n. 1
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);
  }
Esempio n. 2
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();
   }
 }
  /**
   * 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);
    }
  }
Esempio n. 4
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);
          }
        }
      }
    }
Esempio n. 5
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);
    }
  }
Esempio n. 6
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;
  }
Esempio n. 7
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());
    }
  }
 public void cancelPingKeepAliveTimeoutTaskIfStarted() {
   if (pingKeepAliveTimeoutTask != null && pingKeepAliveTimeoutTask.getSipTimerTask() != null) {
     try {
       keepAliveSemaphore.acquire();
     } catch (InterruptedException e) {
       logger.logError("Couldn't acquire keepAliveSemaphore");
       return;
     }
     try {
       if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
         logger.logDebug(
             "~~~ cancelPingKeepAliveTimeoutTaskIfStarted for MessageChannel(key="
                 + key
                 + "), clientAddress="
                 + peerAddress
                 + ", clientPort="
                 + peerPort
                 + ", timeout="
                 + keepAliveTimeout
                 + ")");
       }
       sipStack.getTimer().cancel(pingKeepAliveTimeoutTask);
     } finally {
       keepAliveSemaphore.release();
     }
   }
 }
 public ConnectionOrientedMessageChannel(SIPTransactionStack sipStack) {
   this.sipStack = sipStack;
   this.keepAliveTimeout = sipStack.getReliableConnectionKeepAliveTimeout();
   if (keepAliveTimeout > 0) {
     keepAliveSemaphore = new Semaphore(1);
   }
 }
Esempio n. 10
0
  /** Run method specified by runnnable. */
  public void run() {
    // Assume no thread pooling (bug fix by spierhj)
    ThreadAuditor.ThreadHandle threadHandle = null;

    while (true) {
      // Create a new string message parser to parse the list of messages.
      if (myParser == null) {
        myParser = new StringMsgParser();
        myParser.setParseExceptionListener(this);
      }
      // messages that we write out to him.
      DatagramPacket packet;

      if (sipStack.threadPoolSize != -1) {
        synchronized (((UDPMessageProcessor) messageProcessor).messageQueue) {
          while (((UDPMessageProcessor) messageProcessor).messageQueue.isEmpty()) {
            // Check to see if we need to exit.
            if (!((UDPMessageProcessor) messageProcessor).isRunning) return;
            try {
              // We're part of a thread pool. Ask the auditor to
              // monitor this thread.
              if (threadHandle == null) {
                threadHandle = sipStack.getThreadAuditor().addCurrentThread();
              }

              // Send a heartbeat to the thread auditor
              threadHandle.ping();

              // Wait for packets
              // Note: getPingInterval returns 0 (infinite) if the
              // thread auditor is disabled.
              ((UDPMessageProcessor) messageProcessor)
                  .messageQueue.wait(threadHandle.getPingIntervalInMillisecs());
            } catch (InterruptedException ex) {
              if (!((UDPMessageProcessor) messageProcessor).isRunning) return;
            }
          }
          packet =
              (DatagramPacket) ((UDPMessageProcessor) messageProcessor).messageQueue.removeFirst();
        }
        this.incomingPacket = packet;
      } else {
        packet = this.incomingPacket;
      }

      // Process the packet. Catch and log any exception we may throw.
      try {
        processIncomingDataPacket(packet);
      } catch (Exception e) {

        sipStack.logWriter.logError("Error while processing incoming UDP packet", e);
      }

      if (sipStack.threadPoolSize == -1) {
        return;
      }
    }
  }
Esempio n. 11
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.logStackTraceOnMessageSend) {
      if (sipMessage instanceof SIPRequest && ((SIPRequest) sipMessage).getRequestLine() != null) {
        /*
         * We dont want to log empty trace messages.
         */
        this.sipStack.logWriter.logStackTrace(LogWriter.TRACE_MESSAGES);
      } else {
        this.sipStack.logWriter.logStackTrace(LogWriter.TRACE_MESSAGES);
      }
    }

    // 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);
            sipStack.logWriter.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.logWriter.logError("An exception occured while sending message", ex);
      throw new IOException("An exception occured while sending message");
    } finally {
      if (sipStack.logWriter.isLoggingEnabled(ServerLog.TRACE_MESSAGES))
        logMessage(sipMessage, peerAddress, peerPort, time);
    }
  }
Esempio n. 12
0
  /** Release the transaction semaphore. */
  public void releaseSem() {
    try {

      this.toListener = false;
      this.semRelease();

    } catch (Exception ex) {
      sipStack.getStackLogger().logError("Unexpected exception releasing sem", ex);
    }
  }
Esempio n. 13
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);
   }
 }
Esempio n. 14
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);
    }
  }
Esempio n. 15
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);
   }
 }
Esempio n. 16
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;
   }
 }
Esempio n. 17
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);
   }
 }
Esempio n. 18
0
  /**
   * Constructor. We create one of these in order to process an incoming message.
   *
   * @param stack is the SIP sipStack.
   * @param messageProcessor is the creating message processor.
   * @param packet is the incoming datagram packet.
   */
  protected UDPMessageChannel(
      SIPTransactionStack stack, UDPMessageProcessor messageProcessor, DatagramPacket packet) {

    this.incomingPacket = packet;
    super.messageProcessor = messageProcessor;
    this.sipStack = stack;

    // jeand : Create a new string message parser to parse the list of messages.
    myParser = sipStack.getMessageParserFactory().createMessageParser(sipStack);

    this.myAddress = messageProcessor.getIpAddress().getHostAddress();
    this.myPort = messageProcessor.getPort();
    mythread = new Thread(this);
    mythread.setDaemon(true);

    mythread.start();
  }
Esempio n. 19
0
 /** Constructor. */
 public DefaultRouter(SipStack sipStack, String defaultRoute) {
   this.sipStack = (SipStackImpl) sipStack;
   if (defaultRoute != null) {
     try {
       this.defaultRoute =
           (Hop)
               this.sipStack
                   .getAddressResolver()
                   .resolveAddress((Hop) (new HopImpl(defaultRoute)));
     } catch (IllegalArgumentException ex) {
       // The outbound proxy is optional. If specified it should be host:port/transport.
       ((SIPTransactionStack) sipStack)
           .getStackLogger()
           .logError("Invalid default route specification - need host:port/transport");
       throw ex;
     }
   }
 }
 public SelectiveCharParser(SIPTransactionStack stack, Properties configurationProperties) {
   logger = stack.getStackLogger();
   if (headersToParse.size() < 1) {
     boolean headersToParseFound = false;
     if (configurationProperties != null) {
       String headersToParseString = configurationProperties.getProperty(HEADERS_TO_PARSE);
       if (headersToParseString != null) {
         headersToParse.clear();
         StringTokenizer stringTokenizer = new StringTokenizer(headersToParseString, ",");
         while (stringTokenizer.hasMoreTokens()) {
           String headerToParse = stringTokenizer.nextToken();
           headersToParse.add(headerToParse.trim().toLowerCase());
         }
         headersToParseFound = true;
       }
     }
     if (!headersToParseFound) {
       headersToParse.add(FromHeader.NAME.toLowerCase());
       headersToParse.add(ToHeader.NAME.toLowerCase());
       headersToParse.add(CSeqHeader.NAME.toLowerCase());
       headersToParse.add(CallIdHeader.NAME.toLowerCase());
       headersToParse.add(MaxForwardsHeader.NAME.toLowerCase());
       headersToParse.add(ViaHeader.NAME.toLowerCase());
       headersToParse.add(ContactHeader.NAME.toLowerCase());
       headersToParse.add(RecordRouteHeader.NAME.toLowerCase());
       headersToParse.add(RouteHeader.NAME.toLowerCase());
       headersToParse.add(ContentLengthHeader.NAME.toLowerCase());
       headersToParse.add(SubscriptionStateHeader.NAME.toLowerCase());
       headersToParse.add(EventHeader.NAME.toLowerCase());
     }
     if (logger.isLoggingEnabled()) {
       logger.logDebug("Headers to parse : ");
       for (String headerToParse : headersToParse) {
         logger.logDebug(headerToParse);
       }
     }
   }
 }
Esempio n. 21
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!");
        }
      }
    }
  }
Esempio n. 22
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);
  }
Esempio n. 23
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!);
    }
  }
Esempio n. 24
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");
 }
Esempio n. 25
0
 /** Set the passToListener flag to true. */
 public void setPassToListener() {
   if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
     sipStack.getStackLogger().logDebug("setPassToListener()");
   }
   this.toListener = true;
 }
  /**
   * Gets invoked by the parser as a callback on successful message parsing (i.e. no parser errors).
   *
   * @param sipMessage Message to process (this calls the application for processing the message).
   *     <p>Jvb: note that this code is identical to TCPMessageChannel, refactor some day
   */
  public void processMessage(SIPMessage sipMessage) throws Exception {
    try {
      if (sipMessage.getFrom() == null
          || sipMessage.getTo() == null
          || sipMessage.getCallId() == null
          || sipMessage.getCSeq() == null
          || sipMessage.getViaHeaders() == null) {

        if (logger.isLoggingEnabled()) {
          String badmsg = sipMessage.encode();
          logger.logError("bad message " + badmsg);
          logger.logError(">>> Dropped Bad Msg");
        }
        return;
      }

      sipMessage.setRemoteAddress(this.peerAddress);
      sipMessage.setRemotePort(this.getPeerPort());
      sipMessage.setLocalAddress(this.getMessageProcessor().getIpAddress());
      sipMessage.setLocalPort(this.getPort());
      // Issue 3: https://telestax.atlassian.net/browse/JSIP-3
      sipMessage.setPeerPacketSourceAddress(this.peerAddress);
      sipMessage.setPeerPacketSourcePort(this.peerPort);

      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 SIPRequest) {
        Via v = (Via) viaList.getFirst();
        // the peer address and tag it appropriately.
        Hop hop = sipStack.addressResolver.resolveAddress(v.getHop());
        this.peerProtocol = v.getTransport();
        // if(peerPortAdvertisedInHeaders <= 0) {
        int hopPort = v.getPort();
        if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
          logger.logDebug(
              "hop port = "
                  + hopPort
                  + " for request "
                  + sipMessage
                  + " for this channel "
                  + this
                  + " key "
                  + key);
        }
        if (hopPort <= 0) {
          // if port is 0 we assume the default port for TCP
          this.peerPortAdvertisedInHeaders = 5060;
        } else {
          this.peerPortAdvertisedInHeaders = hopPort;
        }
        if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
          logger.logDebug(
              "3.Storing peerPortAdvertisedInHeaders = "
                  + peerPortAdvertisedInHeaders
                  + " for this channel "
                  + this
                  + " key "
                  + key);
        }
        // }
        // may be needed to reconnect, when diff than peer address
        if (peerAddressAdvertisedInHeaders == null) {
          peerAddressAdvertisedInHeaders = hop.getHost();
          if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
            logger.logDebug(
                "3.Storing peerAddressAdvertisedInHeaders = "
                    + peerAddressAdvertisedInHeaders
                    + " for this channel "
                    + this
                    + " key "
                    + key);
          }
        }

        try {
          if (mySock != null) { // selfrouting makes socket = null
            // https://jain-sip.dev.java.net/issues/show_bug.cgi?id=297
            this.peerAddress = mySock.getInetAddress();
          }
          // Check to see if the received parameter matches
          // the peer address and tag it appropriately.

          // JvB: dont do this. It is both costly and incorrect
          // Must set received also when it is a FQDN, regardless
          // whether
          // it resolves to the correct IP address
          // InetAddress sentByAddress =
          // InetAddress.getByName(hop.getHost());
          // JvB: if sender added 'rport', must always set received
          boolean hasRPort = v.hasParameter(Via.RPORT);
          if (!hasRPort && v.getPort() != peerPort) {
            // https://github.com/RestComm/jain-sip/issues/79
            if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
              logger.logDebug(
                  "setting rport since viaPort "
                      + v.getPort()
                      + " different than peerPacketSourcePort "
                      + peerPort
                      + " so that the response can be routed back");
            }
            hasRPort = true;
          }
          if (hasRPort || !hop.getHost().equals(this.peerAddress.getHostAddress())) {
            v.setParameter(Via.RECEIVED, this.peerAddress.getHostAddress());
          }
          // @@@ hagai
          // JvB: technically, may only do this when Via already
          // contains
          // rport
          v.setParameter(Via.RPORT, Integer.toString(this.peerPort));
        } catch (java.text.ParseException ex) {
          InternalErrorHandler.handleException(ex);
        }
        // Use this for outgoing messages as well.
        if (!this.isCached && mySock != null) { // self routing makes
          // mySock=null
          // https://jain-sip.dev.java.net/issues/show_bug.cgi?id=297
          this.isCached = true;
          int remotePort = ((java.net.InetSocketAddress) mySock.getRemoteSocketAddress()).getPort();
          String key = IOHandler.makeKey(mySock.getInetAddress(), remotePort);
          if (this.messageProcessor instanceof NioTcpMessageProcessor) {
            // https://java.net/jira/browse/JSIP-475 don't use iohandler in case of NIO
            // communications of the socket will leak in the iohandler sockettable
            ((NioTcpMessageProcessor) this.messageProcessor)
                .nioHandler.putSocket(key, mySock.getChannel());
          } else {
            sipStack.ioHandler.putSocket(key, mySock);
          }
          // since it can close the socket it needs to be after the mySock usage otherwise
          // it the socket will be disconnected and NPE will be thrown in some edge cases
          ((ConnectionOrientedMessageProcessor) this.messageProcessor).cacheMessageChannel(this);
        }
      }

      // Foreach part of the request header, fetch it and process it

      long receptionTime = System.currentTimeMillis();
      //

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

        if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
          logger.logDebug("----Processing Message---");
        }
        if (logger.isLoggingEnabled(ServerLogger.TRACE_MESSAGES)) {

          sipStack.serverLogger.logMessage(
              sipMessage,
              this.getPeerHostPort().toString(),
              this.messageProcessor.getIpAddress().getHostAddress()
                  + ":"
                  + this.messageProcessor.getPort(),
              false,
              receptionTime);
        }
        // Check for reasonable size - reject message
        // if it is too long.
        if (sipStack.getMaxMessageSize() > 0
            && sipRequest.getSize()
                    + (sipRequest.getContentLength() == null
                        ? 0
                        : sipRequest.getContentLength().getContentLength())
                > sipStack.getMaxMessageSize()) {
          SIPResponse sipResponse = sipRequest.createResponse(SIPResponse.MESSAGE_TOO_LARGE);
          byte[] resp = sipResponse.encodeAsBytes(this.getTransport());
          this.sendMessage(resp, false);
          throw new Exception("Message size exceeded");
        }

        String sipVersion = ((SIPRequest) sipMessage).getRequestLine().getSipVersion();
        if (!sipVersion.equals("SIP/2.0")) {
          SIPResponse versionNotSupported =
              ((SIPRequest) sipMessage)
                  .createResponse(Response.VERSION_NOT_SUPPORTED, "Bad SIP version " + sipVersion);
          this.sendMessage(versionNotSupported.encodeAsBytes(this.getTransport()), false);
          throw new Exception("Bad version ");
        }

        String method = ((SIPRequest) sipMessage).getMethod();
        String cseqMethod = ((SIPRequest) sipMessage).getCSeqHeader().getMethod();

        if (!method.equalsIgnoreCase(cseqMethod)) {
          SIPResponse sipResponse = sipRequest.createResponse(SIPResponse.BAD_REQUEST);
          byte[] resp = sipResponse.encodeAsBytes(this.getTransport());
          this.sendMessage(resp, false);
          throw new Exception("Bad CSeq method" + sipMessage + " method " + method);
        }

        // Stack could not create a new server request interface.
        // maybe not enough resources.
        ServerRequestInterface sipServerRequest = sipStack.newSIPServerRequest(sipRequest, this);

        if (sipServerRequest != null) {
          try {
            sipServerRequest.processRequest(sipRequest, this);
          } finally {
            if (sipServerRequest instanceof SIPTransaction) {
              SIPServerTransaction sipServerTx = (SIPServerTransaction) sipServerRequest;
              if (!sipServerTx.passToListener()) ((SIPTransaction) sipServerRequest).releaseSem();
            }
          }
        } else {
          if (sipStack.sipMessageValve
              == null) { // Allow message valves to nullify messages without error
            SIPResponse response = sipRequest.createResponse(Response.SERVICE_UNAVAILABLE);

            RetryAfter retryAfter = new RetryAfter();

            // Be a good citizen and send a decent response code back.
            try {
              retryAfter.setRetryAfter((int) (10 * (Math.random())));
              response.setHeader(retryAfter);
              this.sendMessage(response);
            } catch (Exception e) {
              // IGNore
            }
            if (logger.isLoggingEnabled())
              logger.logWarning("Dropping message -- could not acquire semaphore");
          }
        }
      } else {
        SIPResponse sipResponse = (SIPResponse) sipMessage;
        // JvB: dont do this
        // if (sipResponse.getStatusCode() == 100)
        // sipResponse.getTo().removeParameter("tag");
        try {
          sipResponse.checkHeaders();
        } catch (ParseException ex) {
          if (logger.isLoggingEnabled())
            logger.logError("Dropping Badly formatted response message >>> " + sipResponse);
          return;
        }
        // This is a response message - process it.
        // Check the size of the response.
        // If it is too large dump it silently.
        if (sipStack.getMaxMessageSize() > 0
            && sipResponse.getSize()
                    + (sipResponse.getContentLength() == null
                        ? 0
                        : sipResponse.getContentLength().getContentLength())
                > sipStack.getMaxMessageSize()) {
          if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG))
            logger.logDebug("Message size exceeded");
          return;
        }

        ServerResponseInterface sipServerResponse =
            sipStack.newSIPServerResponse(sipResponse, this);
        if (sipServerResponse != null) {
          try {
            if (sipServerResponse instanceof SIPClientTransaction
                && !((SIPClientTransaction) sipServerResponse).checkFromTag(sipResponse)) {
              if (logger.isLoggingEnabled())
                logger.logError("Dropping response message with invalid tag >>> " + sipResponse);
              return;
            }

            sipServerResponse.processResponse(sipResponse, this);
          } finally {
            if (sipServerResponse instanceof SIPTransaction
                && !((SIPTransaction) sipServerResponse).passToListener()) {
              // Note that the semaphore is released in event
              // scanner if the
              // request is actually processed by the Listener.
              ((SIPTransaction) sipServerResponse).releaseSem();
            }
          }
        } else {
          logger.logWarning(
              "Application is blocked -- could not acquire semaphore -- dropping response");
        }
      }
    } finally {
    }
  }
Esempio n. 27
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();
    }
  }
Esempio n. 28
0
 /** Close the encapsulated channel. */
 public void close() {
   this.encapsulatedChannel.close();
   if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG))
     sipStack.getStackLogger().logDebug("Closing " + this.encapsulatedChannel);
 }
Esempio n. 29
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;
  }
  public void rescheduleKeepAliveTimeout(long newKeepAliveTimeout) {
    //        long now = System.currentTimeMillis();
    //        long lastKeepAliveReceivedTimeOrNow = lastKeepAliveReceivedTime == 0 ? now :
    // lastKeepAliveReceivedTime;
    //
    //        long newScheduledTime =  lastKeepAliveReceivedTimeOrNow + newKeepAliveTimeout;

    StringBuilder methodLog = new StringBuilder();

    if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
      methodLog.append(
          "~~~ rescheduleKeepAliveTimeout for MessageChannel(key="
              + key
              + "), clientAddress="
              + peerAddress
              + ", clientPort="
              + peerPort
              + ", timeout="
              + keepAliveTimeout
              + "): newKeepAliveTimeout=");
      if (newKeepAliveTimeout == Long.MAX_VALUE) {
        methodLog.append("Long.MAX_VALUE");
      } else {
        methodLog.append(newKeepAliveTimeout);
      }
      //            methodLog.append(", lastKeepAliveReceivedTimeOrNow=");
      //            methodLog.append(lastKeepAliveReceivedTimeOrNow);
      //            methodLog.append(", newScheduledTime=");
      //            methodLog.append(newScheduledTime);
    }

    //        long delay = newScheduledTime > now ? newScheduledTime - now : 1;
    try {
      keepAliveSemaphore.acquire();
    } catch (InterruptedException e) {
      logger.logWarning("Couldn't acquire keepAliveSemaphore");
      return;
    }
    try {
      if (pingKeepAliveTimeoutTask == null) {
        pingKeepAliveTimeoutTask = new KeepAliveTimeoutTimerTask();
        if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
          methodLog.append(", scheduling pingKeepAliveTimeoutTask to execute after ");
          methodLog.append(keepAliveTimeout / 1000);
          methodLog.append(" seconds");
          logger.logDebug(methodLog.toString());
        }
        sipStack.getTimer().schedule(pingKeepAliveTimeoutTask, keepAliveTimeout);
      } else {
        if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
          logger.logDebug(
              "~~~ cancelPingKeepAliveTimeout for MessageChannel(key="
                  + key
                  + "), clientAddress="
                  + peerAddress
                  + ", clientPort="
                  + peerPort
                  + ", timeout="
                  + keepAliveTimeout
                  + ")");
        }
        sipStack.getTimer().cancel(pingKeepAliveTimeoutTask);
        pingKeepAliveTimeoutTask = new KeepAliveTimeoutTimerTask();
        if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
          methodLog.append(", scheduling pingKeepAliveTimeoutTask to execute after ");
          methodLog.append(keepAliveTimeout / 1000);
          methodLog.append(" seconds");
          logger.logDebug(methodLog.toString());
        }
        sipStack.getTimer().schedule(pingKeepAliveTimeoutTask, keepAliveTimeout);
      }
    } finally {
      keepAliveSemaphore.release();
    }
  }