/** * Add a new server transaction to the set of existing transactions. Add it to the top of the list * so an incoming ack has less work to do in order to find the transaction. * * @param serverTransaction -- server transaction to add to the set. */ public void addTransaction(SIPServerTransaction serverTransaction) throws IOException { if (LogWriter.needsLogging) logWriter.logMessage("added transaction " + serverTransaction); synchronized (serverTransactions) { this.serverTransactions.add(0, serverTransaction); serverTransaction.map(); } addTransactionHash(serverTransaction); serverTransaction.startTransactionTimer(); }
/** * Find the transaction corresponding to a given request. * * @param sipMessage request for which to retrieve the transaction. * @param isServer search the server transaction table if true. * @return the transaction object corresponding to the request or null if no such mapping exists. */ public SIPTransaction findTransaction(SIPMessage sipMessage, boolean isServer) { SIPTransaction retval = null; if (isServer) { Via via = sipMessage.getTopmostVia(); if (via.getBranch() != null) { String key = sipMessage.getTransactionId(); synchronized (this.serverTransactionTable) { retval = (SIPTransaction) serverTransactionTable.get(key); if (LogWriter.needsLogging) logMessage("looking for key " + key); if (retval != null && retval.isMessagePartOfTransaction(sipMessage)) return retval; } } // Need to scan the table for old style transactions (RFC 2543 // style) synchronized (this.serverTransactions) { Iterator<SIPServerTransaction> it = serverTransactions.iterator(); while (it.hasNext()) { SIPServerTransaction sipServerTransaction = (SIPServerTransaction) it.next(); if (sipServerTransaction.isMessagePartOfTransaction(sipMessage)) return sipServerTransaction; } } } else { Via via = sipMessage.getTopmostVia(); if (via.getBranch() != null) { String key = sipMessage.getTransactionId(); synchronized (this.clientTransactionTable) { retval = (SIPTransaction) clientTransactionTable.get(key); if (retval != null && retval.isMessagePartOfTransaction(sipMessage)) return retval; } } // Need to scan the table for old style transactions (RFC 2543 // style) synchronized (this.clientTransactions) { Iterator<SIPClientTransaction> it = clientTransactions.iterator(); while (it.hasNext()) { SIPClientTransaction clientTransaction = (SIPClientTransaction) it.next(); if (clientTransaction.isMessagePartOfTransaction(sipMessage)) return clientTransaction; } } } return null; }
public SIPServerTransaction findPendingTransaction(SIPRequest requestReceived) { SIPServerTransaction currentTransaction; Iterator<SIPServerTransaction> transactionIterator; synchronized (pendingTransactions) { transactionIterator = pendingTransactions.iterator(); currentTransaction = null; while (transactionIterator.hasNext() && currentTransaction == null) { SIPServerTransaction nextTransaction = (SIPServerTransaction) transactionIterator.next(); // If this transaction should handle this request, if (nextTransaction.isMessagePartOfTransaction(requestReceived)) { // Mark this transaction as the one // to handle this message currentTransaction = nextTransaction; } } } return currentTransaction; }
/** * Get the transaction to cancel. Search the server transaction table for a transaction that * matches the given transaction. */ public SIPTransaction findCancelTransaction(SIPRequest cancelRequest, boolean isServer) { if (LogWriter.needsLogging) { logWriter.logMessage( "findCancelTransaction request= \n" + cancelRequest + "\nfindCancelRequest isServer=" + isServer); } if (isServer) { synchronized (this.serverTransactions) { Iterator<SIPServerTransaction> li = this.serverTransactions.iterator(); while (li.hasNext()) { SIPTransaction transaction = (SIPTransaction) li.next(); // SIPRequest sipRequest = (SIPRequest) (transaction // .getRequest()); SIPServerTransaction sipServerTransaction = (SIPServerTransaction) transaction; if (sipServerTransaction.doesCancelMatchTransaction(cancelRequest)) return sipServerTransaction; } } } else { synchronized (this.clientTransactions) { Iterator<SIPClientTransaction> li = this.clientTransactions.iterator(); while (li.hasNext()) { SIPTransaction transaction = (SIPTransaction) li.next(); // SIPRequest sipRequest = (SIPRequest) (transaction // .getRequest()); SIPClientTransaction sipClientTransaction = (SIPClientTransaction) transaction; if (sipClientTransaction.doesCancelMatchTransaction(cancelRequest)) return sipClientTransaction; } } } if (LogWriter.needsLogging) logWriter.logMessage("Could not find transaction for cancel request"); return null; }
/** * Handles a new SIP request. It finds a server transaction to handle this message. If none * exists, it creates a new transaction. * * @param requestReceived Request to handle. * @param requestMessageChannel Channel that received message. * @return A server transaction. */ protected ServerRequestInterface newSIPServerRequest( SIPRequest requestReceived, MessageChannel requestMessageChannel) { // Iterator through all server transactions Iterator<SIPServerTransaction> transactionIterator; // Next transaction in the set SIPServerTransaction nextTransaction; // Transaction to handle this request SIPServerTransaction currentTransaction; String key = requestReceived.getTransactionId(); currentTransaction = (SIPServerTransaction) serverTransactionTable.get(key); if (currentTransaction == null || !currentTransaction.isMessagePartOfTransaction(requestReceived)) { // Loop through all server transactions synchronized (serverTransactions) { transactionIterator = serverTransactions.iterator(); currentTransaction = null; while (transactionIterator.hasNext() && currentTransaction == null) { nextTransaction = (SIPServerTransaction) transactionIterator.next(); // If this transaction should handle this request, if (nextTransaction.isMessagePartOfTransaction(requestReceived)) { // Mark this transaction as the one // to handle this message currentTransaction = nextTransaction; } } // If no transaction exists to handle this message if (currentTransaction == null) { currentTransaction = findPendingTransaction(requestReceived); if (currentTransaction != null) return currentTransaction; currentTransaction = createServerTransaction(requestMessageChannel); currentTransaction.setOriginalRequest(requestReceived); if (!isDialogCreated(requestReceived.getMethod())) { // Dialog is not created - can we find the state? // If so, then create a transaction and add it. String dialogId = requestReceived.getDialogId(true); SIPDialog dialog = getDialog(dialogId); // Sequence numbers are supposed to increment. // avoid processing old sequence numbers and // delivering the same request up to the // application if the request has already been seen. // Special handling applies to ACK processing. if (dialog != null && (requestReceived.getMethod().equals(Request.ACK) || requestReceived.getCSeq().getSequenceNumber() > dialog.getRemoteSequenceNumber())) { // Found a dialog. if (LogWriter.needsLogging) logWriter.logMessage("adding server transaction " + currentTransaction); serverTransactions.add(0, currentTransaction); addTransactionHash(currentTransaction); currentTransaction.startTransactionTimer(); currentTransaction.isMapped = true; } } else { // Create the transaction but dont map it. String dialogId = requestReceived.getDialogId(true); SIPDialog dialog = getDialog(dialogId); // This is a dialog creating request that is part of an // existing dialog (eg. re-Invite). Re-invites get a non // null server transaction Id (unlike the original // invite). if (dialog != null && requestReceived.getCSeq().getSequenceNumber() > dialog.getRemoteSequenceNumber()) { currentTransaction.map(); if (LogWriter.needsLogging) logWriter.logMessage("adding server transaction " + currentTransaction); serverTransactions.add(0, currentTransaction); addTransactionHash(currentTransaction); currentTransaction.startTransactionTimer(); currentTransaction.toListener = true; } } } } } // Set ths transaction's encapsulated request // interface from the superclass currentTransaction.setRequestInterface( super.newSIPServerRequest(requestReceived, currentTransaction)); return currentTransaction; }
/** * 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.logWriter.isLoggingEnabled(ServerLog.TRACE_MESSAGES)) { this.sipStack.serverLog.logMessage( sipMessage, this.getPeerHostPort().toString(), this.getHost() + ":" + this.myPort, false, receptionTime); } ServerRequestInterface sipServerRequest = sipStack.newSIPServerRequest(sipRequest, this); // Drop it if there is no request returned if (sipServerRequest == null) { if (sipStack.isLoggingEnabled()) { this.sipStack.logWriter.logWarning("Null request interface returned -- dropping request"); } return; } if (sipStack.isLoggingEnabled()) this.sipStack.logWriter.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()) this.sipStack.logWriter.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.logWriter.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.logWriter.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()) { this.sipStack.logWriter.logDebug("null sipServerResponse!"); } } } }