Search in sources :

Example 16 with SIPRequest

use of gov.nist.javax.sip.message.SIPRequest in project XobotOS by xamarin.

the class SIPDialog method sendRequest.

public void sendRequest(ClientTransaction clientTransactionId, boolean allowInterleaving) throws TransactionDoesNotExistException, SipException {
    if ((!allowInterleaving) && clientTransactionId.getRequest().getMethod().equals(Request.INVITE)) {
        new Thread((new ReInviteSender(clientTransactionId))).start();
        return;
    }
    SIPRequest dialogRequest = ((SIPClientTransaction) clientTransactionId).getOriginalRequest();
    if (sipStack.isLoggingEnabled())
        sipStack.getStackLogger().logDebug("dialog.sendRequest " + " dialog = " + this + "\ndialogRequest = \n" + dialogRequest);
    if (clientTransactionId == null)
        throw new NullPointerException("null parameter");
    if (dialogRequest.getMethod().equals(Request.ACK) || dialogRequest.getMethod().equals(Request.CANCEL))
        throw new SipException("Bad Request Method. " + dialogRequest.getMethod());
    // JvB: added, allow re-sending of BYE after challenge
    if (byeSent && isTerminatedOnBye() && !dialogRequest.getMethod().equals(Request.BYE)) {
        if (sipStack.isLoggingEnabled())
            sipStack.getStackLogger().logError("BYE already sent for " + this);
        throw new SipException("Cannot send request; BYE already sent");
    }
    if (dialogRequest.getTopmostVia() == null) {
        Via via = ((SIPClientTransaction) clientTransactionId).getOutgoingViaHeader();
        dialogRequest.addHeader(via);
    }
    if (!this.getCallId().getCallId().equalsIgnoreCase(dialogRequest.getCallId().getCallId())) {
        if (sipStack.isLoggingEnabled()) {
            sipStack.getStackLogger().logError("CallID " + this.getCallId());
            sipStack.getStackLogger().logError("RequestCallID = " + dialogRequest.getCallId().getCallId());
            sipStack.getStackLogger().logError("dialog =  " + this);
        }
        throw new SipException("Bad call ID in request");
    }
    // Set the dialog back pointer.
    ((SIPClientTransaction) clientTransactionId).setDialog(this, this.dialogId);
    this.addTransaction((SIPTransaction) clientTransactionId);
    // Enable the retransmission filter for the transaction
    ((SIPClientTransaction) clientTransactionId).isMapped = true;
    From from = (From) dialogRequest.getFrom();
    To to = (To) dialogRequest.getTo();
    // tag assignment is OK.
    if (this.getLocalTag() != null && from.getTag() != null && !from.getTag().equals(this.getLocalTag()))
        throw new SipException("From tag mismatch expecting  " + this.getLocalTag());
    if (this.getRemoteTag() != null && to.getTag() != null && !to.getTag().equals(this.getRemoteTag())) {
        if (sipStack.isLoggingEnabled())
            this.sipStack.getStackLogger().logWarning("To header tag mismatch expecting " + this.getRemoteTag());
    }
    /*
         * The application is sending a NOTIFY before sending the response of the dialog.
         */
    if (this.getLocalTag() == null && dialogRequest.getMethod().equals(Request.NOTIFY)) {
        if (!this.getMethod().equals(Request.SUBSCRIBE))
            throw new SipException("Trying to send NOTIFY without SUBSCRIBE Dialog!");
        this.setLocalTag(from.getTag());
    }
    try {
        if (this.getLocalTag() != null)
            from.setTag(this.getLocalTag());
        if (this.getRemoteTag() != null)
            to.setTag(this.getRemoteTag());
    } catch (ParseException ex) {
        InternalErrorHandler.handleException(ex);
    }
    Hop hop = ((SIPClientTransaction) clientTransactionId).getNextHop();
    if (sipStack.isLoggingEnabled()) {
        sipStack.getStackLogger().logDebug("Using hop = " + hop.getHost() + " : " + hop.getPort());
    }
    try {
        MessageChannel messageChannel = sipStack.createRawMessageChannel(this.getSipProvider().getListeningPoint(hop.getTransport()).getIPAddress(), this.firstTransactionPort, hop);
        MessageChannel oldChannel = ((SIPClientTransaction) clientTransactionId).getMessageChannel();
        // Remove this from the connection cache if it is in the
        // connection
        // cache and is not yet active.
        oldChannel.uncache();
        // Not configured to cache client connections.
        if (!sipStack.cacheClientConnections) {
            oldChannel.useCount--;
            if (sipStack.isLoggingEnabled())
                sipStack.getStackLogger().logDebug("oldChannel: useCount " + oldChannel.useCount);
        }
        if (messageChannel == null) {
            /*
                 * At this point the procedures of 8.1.2 and 12.2.1.1 of RFC3261 have been tried
                 * but the resulting next hop cannot be resolved (recall that the exception thrown
                 * is caught and ignored in SIPStack.createMessageChannel() so we end up here with
                 * a null messageChannel instead of the exception handler below). All else
                 * failing, try the outbound proxy in accordance with 8.1.2, in particular: This
                 * ensures that outbound proxies that do not add Record-Route header field values
                 * will drop out of the path of subsequent requests. It allows endpoints that
                 * cannot resolve the first Route URI to delegate that task to an outbound proxy.
                 * 
                 * if one considers the 'first Route URI' of a request constructed according to
                 * 12.2.1.1 to be the request URI when the route set is empty.
                 */
            if (sipStack.isLoggingEnabled())
                sipStack.getStackLogger().logDebug("Null message channel using outbound proxy !");
            Hop outboundProxy = sipStack.getRouter(dialogRequest).getOutboundProxy();
            if (outboundProxy == null)
                throw new SipException("No route found! hop=" + hop);
            messageChannel = sipStack.createRawMessageChannel(this.getSipProvider().getListeningPoint(outboundProxy.getTransport()).getIPAddress(), this.firstTransactionPort, outboundProxy);
            if (messageChannel != null)
                ((SIPClientTransaction) clientTransactionId).setEncapsulatedChannel(messageChannel);
        } else {
            ((SIPClientTransaction) clientTransactionId).setEncapsulatedChannel(messageChannel);
            if (sipStack.isLoggingEnabled()) {
                sipStack.getStackLogger().logDebug("using message channel " + messageChannel);
            }
        }
        if (messageChannel != null)
            messageChannel.useCount++;
        // See if we need to release the previously mapped channel.
        if ((!sipStack.cacheClientConnections) && oldChannel != null && oldChannel.useCount <= 0)
            oldChannel.close();
    } catch (Exception ex) {
        if (sipStack.isLoggingEnabled())
            sipStack.getStackLogger().logException(ex);
        throw new SipException("Could not create message channel", ex);
    }
    try {
        // Increment before setting!!
        localSequenceNumber++;
        dialogRequest.getCSeq().setSeqNumber(getLocalSeqNumber());
    } catch (InvalidArgumentException ex) {
        sipStack.getStackLogger().logFatalError(ex.getMessage());
    }
    try {
        ((SIPClientTransaction) clientTransactionId).sendMessage(dialogRequest);
        /*
             * Note that if the BYE is rejected then the Dialog should bo back to the ESTABLISHED
             * state so we only set state after successful send.
             */
        if (dialogRequest.getMethod().equals(Request.BYE)) {
            this.byeSent = true;
            /*
                 * Dialog goes into TERMINATED state as soon as BYE is sent. ISSUE 182.
                 */
            if (isTerminatedOnBye()) {
                this.setState(DialogState._TERMINATED);
            }
        }
    } catch (IOException ex) {
        throw new SipException("error sending message", ex);
    }
}
Also used : Hop(javax.sip.address.Hop) From(gov.nist.javax.sip.header.From) IOException(java.io.IOException) SIPRequest(gov.nist.javax.sip.message.SIPRequest) DialogDoesNotExistException(javax.sip.DialogDoesNotExistException) InvalidArgumentException(javax.sip.InvalidArgumentException) ParseException(java.text.ParseException) ObjectInUseException(javax.sip.ObjectInUseException) SipException(javax.sip.SipException) IOException(java.io.IOException) TransactionDoesNotExistException(javax.sip.TransactionDoesNotExistException) Via(gov.nist.javax.sip.header.Via) InvalidArgumentException(javax.sip.InvalidArgumentException) To(gov.nist.javax.sip.header.To) ParseException(java.text.ParseException) SipException(javax.sip.SipException)

Example 17 with SIPRequest

use of gov.nist.javax.sip.message.SIPRequest in project XobotOS by xamarin.

the class MessageChannel method sendMessage.

/**
     * Send a formatted message to the specified target.
     * 
     * @param sipMessage Message to send.
     * @param hop hop to send it to.
     * @throws IOException If there is an error sending the message
     */
public void sendMessage(SIPMessage sipMessage, Hop hop) throws IOException {
    long time = System.currentTimeMillis();
    InetAddress hopAddr = InetAddress.getByName(hop.getHost());
    try {
        for (MessageProcessor messageProcessor : getSIPStack().getMessageProcessors()) {
            if (messageProcessor.getIpAddress().equals(hopAddr) && messageProcessor.getPort() == hop.getPort() && messageProcessor.getTransport().equals(hop.getTransport())) {
                MessageChannel messageChannel = messageProcessor.createMessageChannel(hopAddr, hop.getPort());
                if (messageChannel instanceof RawMessageChannel) {
                    ((RawMessageChannel) messageChannel).processMessage(sipMessage);
                    if (getSIPStack().isLoggingEnabled())
                        getSIPStack().getStackLogger().logDebug("Self routing message");
                    return;
                }
            }
        }
        byte[] msg = sipMessage.encodeAsBytes(this.getTransport());
        this.sendMessage(msg, hopAddr, hop.getPort(), sipMessage instanceof SIPRequest);
    } catch (IOException ioe) {
        throw ioe;
    } catch (Exception ex) {
        if (this.getSIPStack().getStackLogger().isLoggingEnabled(ServerLogger.TRACE_ERROR)) {
            this.getSIPStack().getStackLogger().logError("Error self routing message cause by: ", ex);
        }
        // TODO: When moving to Java 6, use the IOExcpetion(message, exception) constructor
        throw new IOException("Error self routing message");
    } finally {
        if (this.getSIPStack().getStackLogger().isLoggingEnabled(ServerLogger.TRACE_MESSAGES))
            logMessage(sipMessage, hopAddr, hop.getPort(), time);
    }
}
Also used : IOException(java.io.IOException) InetAddress(java.net.InetAddress) SIPRequest(gov.nist.javax.sip.message.SIPRequest) ParseException(java.text.ParseException) IOException(java.io.IOException)

Example 18 with SIPRequest

use of gov.nist.javax.sip.message.SIPRequest in project XobotOS by xamarin.

the class StringMsgParser method processFirstLine.

private SIPMessage processFirstLine(String firstLine) throws ParseException {
    SIPMessage message;
    if (!firstLine.startsWith(SIPConstants.SIP_VERSION_STRING)) {
        message = new SIPRequest();
        try {
            RequestLine requestLine = new RequestLineParser(firstLine + "\n").parse();
            ((SIPRequest) message).setRequestLine(requestLine);
        } catch (ParseException ex) {
            if (this.parseExceptionListener != null)
                this.parseExceptionListener.handleException(ex, message, RequestLine.class, firstLine, rawStringMessage);
            else
                throw ex;
        }
    } else {
        message = new SIPResponse();
        try {
            StatusLine sl = new StatusLineParser(firstLine + "\n").parse();
            ((SIPResponse) message).setStatusLine(sl);
        } catch (ParseException ex) {
            if (this.parseExceptionListener != null) {
                this.parseExceptionListener.handleException(ex, message, StatusLine.class, firstLine, rawStringMessage);
            } else
                throw ex;
        }
    }
    return message;
}
Also used : SIPResponse(gov.nist.javax.sip.message.SIPResponse) SIPMessage(gov.nist.javax.sip.message.SIPMessage) ParseException(java.text.ParseException) SIPRequest(gov.nist.javax.sip.message.SIPRequest)

Example 19 with SIPRequest

use of gov.nist.javax.sip.message.SIPRequest in project XobotOS by xamarin.

the class DialogFilter method processRequest.

/**
     * Process a request. Check for various conditions in the dialog that can result in the
     * message being dropped. Possibly return errors for these conditions.
     * 
     * @exception SIPServerException is thrown when there is an error processing the request.
     */
public void processRequest(SIPRequest sipRequest, MessageChannel incomingMessageChannel) {
    // Generate the wrapper JAIN-SIP object.
    if (sipStack.isLoggingEnabled())
        sipStack.getStackLogger().logDebug("PROCESSING INCOMING REQUEST " + sipRequest + " transactionChannel = " + transactionChannel + " listening point = " + listeningPoint.getIPAddress() + ":" + listeningPoint.getPort());
    if (listeningPoint == null) {
        if (sipStack.isLoggingEnabled())
            sipStack.getStackLogger().logDebug("Dropping message: No listening point registered!");
        return;
    }
    SipStackImpl sipStack = (SipStackImpl) transactionChannel.getSIPStack();
    SipProviderImpl sipProvider = listeningPoint.getProvider();
    if (sipProvider == null) {
        if (sipStack.isLoggingEnabled())
            sipStack.getStackLogger().logDebug("No provider - dropping !!");
        return;
    }
    if (sipStack == null)
        InternalErrorHandler.handleException("Egads! no sip stack!");
    // Look for the registered SIPListener for the message channel.
    SIPServerTransaction transaction = (SIPServerTransaction) this.transactionChannel;
    if (transaction != null) {
        if (sipStack.isLoggingEnabled())
            sipStack.getStackLogger().logDebug("transaction state = " + transaction.getState());
    }
    String dialogId = sipRequest.getDialogId(true);
    SIPDialog dialog = sipStack.getDialog(dialogId);
    /*
         * Check if we got this request on the contact address of the dialog If not the dialog
         * does not belong to this request. We check this condition if a contact address has been
         * assigned to the dialog. Forgive the sins of B2BUA's that like to record route ACK's
         */
    if (dialog != null && sipProvider != dialog.getSipProvider()) {
        Contact contact = dialog.getMyContactHeader();
        if (contact != null) {
            SipUri contactUri = (SipUri) (contact.getAddress().getURI());
            String ipAddress = contactUri.getHost();
            int contactPort = contactUri.getPort();
            String contactTransport = contactUri.getTransportParam();
            if (contactTransport == null)
                contactTransport = "udp";
            if (contactPort == -1) {
                if (contactTransport.equals("udp") || contactTransport.equals("tcp"))
                    contactPort = 5060;
                else
                    contactPort = 5061;
            }
            // dialog to the request.
            if (ipAddress != null && (!ipAddress.equals(listeningPoint.getIPAddress()) || contactPort != listeningPoint.getPort())) {
                if (sipStack.isLoggingEnabled()) {
                    sipStack.getStackLogger().logDebug("nulling dialog -- listening point mismatch!  " + contactPort + "  lp port = " + listeningPoint.getPort());
                }
                dialog = null;
            }
        }
    }
    /*
         * RFC 3261 8.2.2.2 Merged requests: If the request has no tag in the To header field, the
         * UAS core MUST check the request against ongoing transactions. If the From tag, Call-ID,
         * and CSeq exactly match those associated with an ongoing transaction, but the request
         * does not match that transaction (based on the matching rules in Section 17.2.3), the
         * UAS core SHOULD generate a 482 (Loop Detected) response and pass it to the server
         * transaction. This support is only enabled when the stack has been instructed to
         * function with Automatic Dialog Support.
         */
    if (sipProvider.isAutomaticDialogSupportEnabled() && sipProvider.isDialogErrorsAutomaticallyHandled() && sipRequest.getToTag() == null) {
        SIPServerTransaction sipServerTransaction = sipStack.findMergedTransaction(sipRequest);
        if (sipServerTransaction != null) {
            this.sendLoopDetectedResponse(sipRequest, transaction);
            return;
        }
    }
    if (sipStack.isLoggingEnabled()) {
        sipStack.getStackLogger().logDebug("dialogId = " + dialogId);
        sipStack.getStackLogger().logDebug("dialog = " + dialog);
    }
    // endpoint, then the stack strips off the route header.
    if (sipRequest.getHeader(Route.NAME) != null && transaction.getDialog() != null) {
        RouteList routes = sipRequest.getRouteHeaders();
        Route route = (Route) routes.getFirst();
        SipUri uri = (SipUri) route.getAddress().getURI();
        int port;
        if (uri.getHostPort().hasPort()) {
            port = uri.getHostPort().getPort();
        } else {
            if (listeningPoint.getTransport().equalsIgnoreCase("TLS"))
                port = 5061;
            else
                port = 5060;
        }
        String host = uri.getHost();
        if ((host.equals(listeningPoint.getIPAddress()) || host.equalsIgnoreCase(listeningPoint.getSentBy())) && port == listeningPoint.getPort()) {
            if (routes.size() == 1)
                sipRequest.removeHeader(Route.NAME);
            else
                routes.removeFirst();
        }
    }
    if (sipRequest.getMethod().equals(Request.REFER) && dialog != null && sipProvider.isDialogErrorsAutomaticallyHandled()) {
        /*
             * An agent responding to a REFER method MUST return a 400 (Bad Request) if the
             * request contained zero or more than one Refer-To header field values.
             */
        ReferToHeader sipHeader = (ReferToHeader) sipRequest.getHeader(ReferTo.NAME);
        if (sipHeader == null) {
            this.sendBadRequestResponse(sipRequest, transaction, "Refer-To header is missing");
            return;
        }
        /*
             * A refer cannot be processed until we have either sent or received an ACK.
             */
        SIPTransaction lastTransaction = ((SIPDialog) dialog).getLastTransaction();
        if (lastTransaction != null && sipProvider.isDialogErrorsAutomaticallyHandled()) {
            SIPRequest lastRequest = (SIPRequest) lastTransaction.getRequest();
            if (lastTransaction instanceof SIPServerTransaction) {
                if (!((SIPDialog) dialog).isAckSeen() && lastRequest.getMethod().equals(Request.INVITE)) {
                    this.sendRequestPendingResponse(sipRequest, transaction);
                    return;
                }
            } else if (lastTransaction instanceof SIPClientTransaction) {
                long cseqno = lastRequest.getCSeqHeader().getSeqNumber();
                String method = lastRequest.getMethod();
                if (method.equals(Request.INVITE) && !dialog.isAckSent(cseqno)) {
                    this.sendRequestPendingResponse(sipRequest, transaction);
                    return;
                }
            }
        }
    } else if (sipRequest.getMethod().equals(Request.UPDATE)) {
        /*
             * Got an UPDATE method and the user dialog does not exist and the user wants to be a
             * User agent.
             * 
             */
        if (sipProvider.isAutomaticDialogSupportEnabled() && dialog == null) {
            this.sendCallOrTransactionDoesNotExistResponse(sipRequest, transaction);
            return;
        }
    } else if (sipRequest.getMethod().equals(Request.ACK)) {
        if (transaction != null && transaction.isInviteTransaction()) {
            // take care of it.
            if (sipStack.isLoggingEnabled())
                sipStack.getStackLogger().logDebug("Processing ACK for INVITE Tx ");
        } else {
            if (sipStack.isLoggingEnabled())
                sipStack.getStackLogger().logDebug("Processing ACK for dialog " + dialog);
            if (dialog == null) {
                if (sipStack.isLoggingEnabled()) {
                    sipStack.getStackLogger().logDebug("Dialog does not exist " + sipRequest.getFirstLine() + " isServerTransaction = " + true);
                }
                SIPServerTransaction st = sipStack.getRetransmissionAlertTransaction(dialogId);
                if (st != null && st.isRetransmissionAlertEnabled()) {
                    st.disableRetransmissionAlerts();
                }
                /*
                     * JvB: must never drop ACKs that dont match a transaction! One cannot be sure
                     * if it isn't an ACK for a 2xx response
                     * 
                     */
                SIPServerTransaction ackTransaction = sipStack.findTransactionPendingAck(sipRequest);
                /*
                     * Found a transaction ( that we generated ) which is waiting for ACK. So ACK
                     * it and return.
                     */
                if (ackTransaction != null) {
                    if (sipStack.isLoggingEnabled())
                        sipStack.getStackLogger().logDebug("Found Tx pending ACK");
                    try {
                        ackTransaction.setAckSeen();
                        sipStack.removeTransaction(ackTransaction);
                        sipStack.removeTransactionPendingAck(ackTransaction);
                    } catch (Exception ex) {
                        if (sipStack.isLoggingEnabled()) {
                            sipStack.getStackLogger().logError("Problem terminating transaction", ex);
                        }
                    }
                    return;
                }
            } else {
                if (!dialog.handleAck(transaction)) {
                    if (!dialog.isSequnceNumberValidation()) {
                        if (sipStack.isLoggingEnabled()) {
                            sipStack.getStackLogger().logDebug("Dialog exists with loose dialog validation " + sipRequest.getFirstLine() + " isServerTransaction = " + true + " dialog = " + dialog.getDialogId());
                        }
                        SIPServerTransaction st = sipStack.getRetransmissionAlertTransaction(dialogId);
                        if (st != null && st.isRetransmissionAlertEnabled()) {
                            st.disableRetransmissionAlerts();
                        }
                    } else {
                        if (sipStack.isLoggingEnabled()) {
                            sipStack.getStackLogger().logDebug("Dropping ACK - cannot find a transaction or dialog");
                        }
                        SIPServerTransaction ackTransaction = sipStack.findTransactionPendingAck(sipRequest);
                        if (ackTransaction != null) {
                            if (sipStack.isLoggingEnabled())
                                sipStack.getStackLogger().logDebug("Found Tx pending ACK");
                            try {
                                ackTransaction.setAckSeen();
                                sipStack.removeTransaction(ackTransaction);
                                sipStack.removeTransactionPendingAck(ackTransaction);
                            } catch (Exception ex) {
                                if (sipStack.isLoggingEnabled()) {
                                    sipStack.getStackLogger().logError("Problem terminating transaction", ex);
                                }
                            }
                        }
                        return;
                    }
                } else {
                    transaction.passToListener();
                    dialog.addTransaction(transaction);
                    dialog.addRoute(sipRequest);
                    transaction.setDialog(dialog, dialogId);
                    if (sipRequest.getMethod().equals(Request.INVITE) && sipProvider.isDialogErrorsAutomaticallyHandled()) {
                        sipStack.putInMergeTable(transaction, sipRequest);
                    }
                    if (sipStack.deliverTerminatedEventForAck) {
                        try {
                            sipStack.addTransaction(transaction);
                            transaction.scheduleAckRemoval();
                        } catch (IOException ex) {
                        }
                    } else {
                        transaction.setMapped(true);
                    }
                }
            }
        }
    } else if (sipRequest.getMethod().equals(Request.PRACK)) {
        if (sipStack.isLoggingEnabled())
            sipStack.getStackLogger().logDebug("Processing PRACK for dialog " + dialog);
        if (dialog == null && sipProvider.isAutomaticDialogSupportEnabled()) {
            if (sipStack.isLoggingEnabled()) {
                sipStack.getStackLogger().logDebug("Dialog does not exist " + sipRequest.getFirstLine() + " isServerTransaction = " + true);
            }
            if (sipStack.isLoggingEnabled()) {
                sipStack.getStackLogger().logDebug("Sending 481 for PRACK - automatic dialog support is enabled -- cant find dialog!");
            }
            SIPResponse notExist = sipRequest.createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST);
            try {
                sipProvider.sendResponse(notExist);
            } catch (SipException e) {
                sipStack.getStackLogger().logError("error sending response", e);
            }
            if (transaction != null) {
                sipStack.removeTransaction(transaction);
                transaction.releaseSem();
            }
            return;
        } else if (dialog != null) {
            if (!dialog.handlePrack(sipRequest)) {
                if (sipStack.isLoggingEnabled())
                    sipStack.getStackLogger().logDebug("Dropping out of sequence PRACK ");
                if (transaction != null) {
                    sipStack.removeTransaction(transaction);
                    transaction.releaseSem();
                }
                return;
            } else {
                try {
                    sipStack.addTransaction(transaction);
                    dialog.addTransaction(transaction);
                    dialog.addRoute(sipRequest);
                    transaction.setDialog(dialog, dialogId);
                } catch (Exception ex) {
                    InternalErrorHandler.handleException(ex);
                }
            }
        } else {
            if (sipStack.isLoggingEnabled())
                sipStack.getStackLogger().logDebug("Processing PRACK without a DIALOG -- this must be a proxy element");
        }
    } else if (sipRequest.getMethod().equals(Request.BYE)) {
        // Check for correct sequence numbering of the BYE
        if (dialog != null && !dialog.isRequestConsumable(sipRequest)) {
            if (sipStack.isLoggingEnabled())
                sipStack.getStackLogger().logDebug("Dropping out of sequence BYE " + dialog.getRemoteSeqNumber() + " " + sipRequest.getCSeq().getSeqNumber());
            if (dialog.getRemoteSeqNumber() >= sipRequest.getCSeq().getSeqNumber() && transaction.getState() == TransactionState.TRYING) {
                this.sendServerInternalErrorResponse(sipRequest, transaction);
            }
            // If the stack knows about the tx, then remove it.
            if (transaction != null)
                sipStack.removeTransaction(transaction);
            return;
        } else if (dialog == null && sipProvider.isAutomaticDialogSupportEnabled()) {
            // Drop bye's with 481 if dialog does not exist.
            // If dialog support is enabled then
            // there must be a dialog associated with the bye
            // No dialog could be found and requests on this
            // provider. Must act like a user agent -- so drop the request.
            // NOTE: if Automatic dialog support is not enabled,
            // then it is the application's responsibility to
            // take care of this error condition possibly.
            SIPResponse response = sipRequest.createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST);
            response.setReasonPhrase("Dialog Not Found");
            if (sipStack.isLoggingEnabled())
                sipStack.getStackLogger().logDebug("dropping request -- automatic dialog " + "support enabled and dialog does not exist!");
            try {
                transaction.sendResponse(response);
            } catch (SipException ex) {
                sipStack.getStackLogger().logError("Error in sending response", ex);
            }
            // If the stack knows about the tx, then remove it.
            if (transaction != null) {
                sipStack.removeTransaction(transaction);
                transaction.releaseSem();
                transaction = null;
            }
            return;
        }
        // to manage its own dialog layer.
        if (transaction != null && dialog != null) {
            try {
                if (sipProvider == dialog.getSipProvider()) {
                    sipStack.addTransaction(transaction);
                    dialog.addTransaction(transaction);
                    transaction.setDialog(dialog, dialogId);
                }
            } catch (IOException ex) {
                InternalErrorHandler.handleException(ex);
            }
        }
        if (sipStack.isLoggingEnabled()) {
            sipStack.getStackLogger().logDebug("BYE Tx = " + transaction + " isMapped =" + transaction.isTransactionMapped());
        }
    } else if (sipRequest.getMethod().equals(Request.CANCEL)) {
        SIPServerTransaction st = (SIPServerTransaction) sipStack.findCancelTransaction(sipRequest, true);
        if (sipStack.isLoggingEnabled()) {
            sipStack.getStackLogger().logDebug("Got a CANCEL, InviteServerTx = " + st + " cancel Server Tx ID = " + transaction + " isMapped = " + transaction.isTransactionMapped());
        }
        // Check if we can process the CANCEL request.
        if (sipRequest.getMethod().equals(Request.CANCEL)) {
            // default action and avoid bothering the listener.
            if (st != null && st.getState() == SIPTransaction.TERMINATED_STATE) {
                // just respond OK to the CANCEL and bail.
                if (sipStack.isLoggingEnabled())
                    sipStack.getStackLogger().logDebug("Too late to cancel Transaction");
                // send OK and just ignore the CANCEL.
                try {
                    transaction.sendResponse(sipRequest.createResponse(Response.OK));
                } catch (Exception ex) {
                    if (ex.getCause() != null && ex.getCause() instanceof IOException) {
                        st.raiseIOExceptionEvent();
                    }
                }
                return;
            }
            if (sipStack.isLoggingEnabled())
                sipStack.getStackLogger().logDebug("Cancel transaction = " + st);
        }
        if (transaction != null && st != null && st.getDialog() != null) {
            // Found an invite tx corresponding to the CANCEL.
            // Set up the client tx and pass up to listener.
            transaction.setDialog((SIPDialog) st.getDialog(), dialogId);
            dialog = (SIPDialog) st.getDialog();
        } else if (st == null && sipProvider.isAutomaticDialogSupportEnabled() && transaction != null) {
            // Could not find a invite tx corresponding to the CANCEL.
            // Automatic dialog support is enabled so I must behave like
            // an endpoint on this provider.
            // Send the error response for the cancel.
            SIPResponse response = sipRequest.createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST);
            if (sipStack.isLoggingEnabled()) {
                sipStack.getStackLogger().logDebug("dropping request -- automatic dialog support " + "enabled and INVITE ST does not exist!");
            }
            try {
                sipProvider.sendResponse(response);
            } catch (SipException ex) {
                InternalErrorHandler.handleException(ex);
            }
            if (transaction != null) {
                sipStack.removeTransaction(transaction);
                transaction.releaseSem();
            }
            return;
        }
        // statefully handled.
        if (st != null) {
            try {
                if (transaction != null) {
                    sipStack.addTransaction(transaction);
                    transaction.setPassToListener();
                    transaction.setInviteTransaction(st);
                    // Dont let the INVITE and CANCEL be concurrently
                    // processed.
                    st.acquireSem();
                }
            } catch (Exception ex) {
                InternalErrorHandler.handleException(ex);
            }
        }
    } else if (sipRequest.getMethod().equals(Request.INVITE)) {
        SIPTransaction lastTransaction = dialog == null ? null : dialog.getInviteTransaction();
        if (dialog != null && transaction != null && lastTransaction != null && sipRequest.getCSeq().getSeqNumber() > dialog.getRemoteSeqNumber() && lastTransaction instanceof SIPServerTransaction && sipProvider.isDialogErrorsAutomaticallyHandled() && dialog.isSequnceNumberValidation() && lastTransaction.isInviteTransaction() && lastTransaction.getState() != TransactionState.COMPLETED && lastTransaction.getState() != TransactionState.TERMINATED && lastTransaction.getState() != TransactionState.CONFIRMED) {
            if (sipStack.isLoggingEnabled()) {
                sipStack.getStackLogger().logDebug("Sending 500 response for out of sequence message");
            }
            this.sendServerInternalErrorResponse(sipRequest, transaction);
            return;
        }
        /*
             * Saw an interleaved invite before ACK was sent. RFC 3261 Chapter 14. A UAS that
             * receives an INVITE on a dialog while an INVITE it had sent on that dialog is in
             * progress MUST return a 491 (Request Pending) response to the received INVITE.
             */
        lastTransaction = (dialog == null ? null : dialog.getLastTransaction());
        if (dialog != null && sipProvider.isDialogErrorsAutomaticallyHandled() && lastTransaction != null && lastTransaction.isInviteTransaction() && lastTransaction instanceof ClientTransaction && lastTransaction.getLastResponse() != null && lastTransaction.getLastResponse().getStatusCode() == 200 && !dialog.isAckSent(lastTransaction.getLastResponse().getCSeq().getSeqNumber())) {
            if (sipStack.isLoggingEnabled()) {
                sipStack.getStackLogger().logDebug("Sending 491 response for client Dialog ACK not sent.");
            }
            this.sendRequestPendingResponse(sipRequest, transaction);
            return;
        }
        if (dialog != null && lastTransaction != null && sipProvider.isDialogErrorsAutomaticallyHandled() && lastTransaction.isInviteTransaction() && lastTransaction instanceof ServerTransaction && !dialog.isAckSeen()) {
            if (sipStack.isLoggingEnabled()) {
                sipStack.getStackLogger().logDebug("Sending 491 response for server Dialog ACK not seen.");
            }
            this.sendRequestPendingResponse(sipRequest, transaction);
            return;
        }
    }
    if (sipStack.isLoggingEnabled()) {
        sipStack.getStackLogger().logDebug("CHECK FOR OUT OF SEQ MESSAGE " + dialog + " transaction " + transaction);
    }
    if (dialog != null && transaction != null && !sipRequest.getMethod().equals(Request.BYE) && !sipRequest.getMethod().equals(Request.CANCEL) && !sipRequest.getMethod().equals(Request.ACK) && !sipRequest.getMethod().equals(Request.PRACK)) {
        if (!dialog.isRequestConsumable(sipRequest)) {
            // Drop the request
            if (sipStack.isLoggingEnabled()) {
                sipStack.getStackLogger().logDebug("Dropping out of sequence message " + dialog.getRemoteSeqNumber() + " " + sipRequest.getCSeq());
            }
            if (dialog.getRemoteSeqNumber() >= sipRequest.getCSeq().getSeqNumber() && sipProvider.isDialogErrorsAutomaticallyHandled() && (transaction.getState() == TransactionState.TRYING || transaction.getState() == TransactionState.PROCEEDING)) {
                this.sendServerInternalErrorResponse(sipRequest, transaction);
            }
            return;
        }
        try {
            if (sipProvider == dialog.getSipProvider()) {
                sipStack.addTransaction(transaction);
                // This will set the remote sequence number.
                dialog.addTransaction(transaction);
                dialog.addRoute(sipRequest);
                transaction.setDialog(dialog, dialogId);
            }
        } catch (IOException ex) {
            transaction.raiseIOExceptionEvent();
            sipStack.removeTransaction(transaction);
            return;
        }
    }
    RequestEvent sipEvent;
    if (sipStack.isLoggingEnabled()) {
        sipStack.getStackLogger().logDebug(sipRequest.getMethod() + " transaction.isMapped = " + transaction.isTransactionMapped());
    }
    if (dialog == null && sipRequest.getMethod().equals(Request.NOTIFY)) {
        SIPClientTransaction pendingSubscribeClientTx = sipStack.findSubscribeTransaction(sipRequest, listeningPoint);
        if (sipStack.isLoggingEnabled()) {
            sipStack.getStackLogger().logDebug("PROCESSING NOTIFY  DIALOG == null " + pendingSubscribeClientTx);
        }
        /*
             * RFC 3265: Upon receiving a NOTIFY request, the subscriber should check that it
             * matches at least one of its outstanding subscriptions; if not, it MUST return a
             * "481 Subscription does not exist" response unless another 400- or -class response
             * is more appropriate.
             */
        if (sipProvider.isAutomaticDialogSupportEnabled() && pendingSubscribeClientTx == null && !sipStack.deliverUnsolicitedNotify) {
            /*
                 * This is the case of the UAC receiving a Stray NOTIFY for which it has not
                 * previously sent out a SUBSCRIBE and for which it does not have an established
                 * dialog.
                 */
            try {
                if (sipStack.isLoggingEnabled()) {
                    sipStack.getStackLogger().logDebug("Could not find Subscription for Notify Tx.");
                }
                Response errorResponse = sipRequest.createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST);
                errorResponse.setReasonPhrase("Subscription does not exist");
                sipProvider.sendResponse(errorResponse);
                return;
            } catch (Exception ex) {
                sipStack.getStackLogger().logError("Exception while sending error response statelessly", ex);
                return;
            }
        }
        // notify to this dialog and pass it up.
        if (pendingSubscribeClientTx != null) {
            // The response to the pending subscribe tx can try to create
            // a dialog at the same time that the notify is trying to
            // create a dialog. Thus we cannot process both at the
            // same time.
            transaction.setPendingSubscribe(pendingSubscribeClientTx);
            // The transaction gets assigned to the dialog from the
            // outgoing subscribe. First see if anybody claimed the
            // default Dialog for the outgoing Subscribe request.
            SIPDialog subscriptionDialog = (SIPDialog) pendingSubscribeClientTx.getDefaultDialog();
            // TODO -- refactor this. Can probably be written far cleaner.
            if (subscriptionDialog == null || subscriptionDialog.getDialogId() == null || !subscriptionDialog.getDialogId().equals(dialogId)) {
                // the notify.
                if (subscriptionDialog != null && subscriptionDialog.getDialogId() == null) {
                    subscriptionDialog.setDialogId(dialogId);
                } else {
                    subscriptionDialog = pendingSubscribeClientTx.getDialog(dialogId);
                }
                if (sipStack.isLoggingEnabled()) {
                    sipStack.getStackLogger().logDebug("PROCESSING NOTIFY Subscribe DIALOG " + subscriptionDialog);
                }
                // the SUBSCRIBE on the subscribe tx.
                if (subscriptionDialog == null && (sipProvider.isAutomaticDialogSupportEnabled() || pendingSubscribeClientTx.getDefaultDialog() != null)) {
                    Event event = (Event) sipRequest.getHeader(EventHeader.NAME);
                    if (sipStack.isEventForked(event.getEventType())) {
                        subscriptionDialog = SIPDialog.createFromNOTIFY(pendingSubscribeClientTx, transaction);
                    }
                }
                if (subscriptionDialog != null) {
                    transaction.setDialog(subscriptionDialog, dialogId);
                    subscriptionDialog.setState(DialogState.CONFIRMED.getValue());
                    sipStack.putDialog(subscriptionDialog);
                    pendingSubscribeClientTx.setDialog(subscriptionDialog, dialogId);
                    if (!transaction.isTransactionMapped()) {
                        this.sipStack.mapTransaction(transaction);
                        // Let the listener see it if it just got
                        // created.
                        // otherwise, we have already processed the tx
                        // so
                        // we dont want the listener to see it.
                        transaction.setPassToListener();
                        try {
                            this.sipStack.addTransaction(transaction);
                        } catch (Exception ex) {
                        }
                    }
                }
            } else {
                // The subscription default dialog is our dialog.
                // Found a subscrbe dialog for the NOTIFY
                // So map the tx.
                transaction.setDialog(subscriptionDialog, dialogId);
                dialog = subscriptionDialog;
                if (!transaction.isTransactionMapped()) {
                    this.sipStack.mapTransaction(transaction);
                    // Let the listener see it if it just got created.
                    // otherwise, we have already processed the tx so
                    // we dont want the listener to see it.
                    transaction.setPassToListener();
                    try {
                        this.sipStack.addTransaction(transaction);
                    } catch (Exception ex) {
                    }
                }
                sipStack.putDialog(subscriptionDialog);
                if (pendingSubscribeClientTx != null) {
                    subscriptionDialog.addTransaction(pendingSubscribeClientTx);
                    pendingSubscribeClientTx.setDialog(subscriptionDialog, dialogId);
                }
            }
            if (transaction != null && ((SIPServerTransaction) transaction).isTransactionMapped()) {
                // Shadow transaction has been created and the stack
                // knows
                // about it.
                sipEvent = new RequestEvent((SipProvider) sipProvider, (ServerTransaction) transaction, subscriptionDialog, (Request) sipRequest);
            } else {
                // Shadow transaction has been created but the stack
                // does
                // not know
                // about it.
                sipEvent = new RequestEvent((SipProvider) sipProvider, null, subscriptionDialog, (Request) sipRequest);
            }
        } else {
            if (sipStack.isLoggingEnabled()) {
                sipStack.getStackLogger().logDebug("could not find subscribe tx");
            }
            // Got a notify out of the blue - just pass it up
            // for stateless handling by the application.
            sipEvent = new RequestEvent(sipProvider, null, null, (Request) sipRequest);
        }
    } else {
        // The listener can create the dialog if needed.
        if (transaction != null && (((SIPServerTransaction) transaction).isTransactionMapped())) {
            sipEvent = new RequestEvent(sipProvider, (ServerTransaction) transaction, dialog, (Request) sipRequest);
        } else {
            sipEvent = new RequestEvent(sipProvider, null, dialog, (Request) sipRequest);
        }
    }
    sipProvider.handleEvent(sipEvent, transaction);
}
Also used : SIPClientTransaction(gov.nist.javax.sip.stack.SIPClientTransaction) RouteList(gov.nist.javax.sip.header.RouteList) SipUri(gov.nist.javax.sip.address.SipUri) SIPServerTransaction(gov.nist.javax.sip.stack.SIPServerTransaction) SIPRequest(gov.nist.javax.sip.message.SIPRequest) SIPResponse(gov.nist.javax.sip.message.SIPResponse) SIPTransaction(gov.nist.javax.sip.stack.SIPTransaction) ReferToHeader(javax.sip.header.ReferToHeader) ServerTransaction(javax.sip.ServerTransaction) SIPServerTransaction(gov.nist.javax.sip.stack.SIPServerTransaction) Route(gov.nist.javax.sip.header.Route) SIPClientTransaction(gov.nist.javax.sip.stack.SIPClientTransaction) ClientTransaction(javax.sip.ClientTransaction) RequestEvent(javax.sip.RequestEvent) Request(javax.sip.message.Request) SIPRequest(gov.nist.javax.sip.message.SIPRequest) IOException(java.io.IOException) InvalidArgumentException(javax.sip.InvalidArgumentException) SipException(javax.sip.SipException) IOException(java.io.IOException) ObjectInUseException(javax.sip.ObjectInUseException) Contact(gov.nist.javax.sip.header.Contact) Response(javax.sip.message.Response) SIPResponse(gov.nist.javax.sip.message.SIPResponse) SIPDialog(gov.nist.javax.sip.stack.SIPDialog) RequestEvent(javax.sip.RequestEvent) Event(gov.nist.javax.sip.header.Event) ResponseEvent(javax.sip.ResponseEvent) SipException(javax.sip.SipException) SipProvider(javax.sip.SipProvider)

Example 20 with SIPRequest

use of gov.nist.javax.sip.message.SIPRequest in project XobotOS by xamarin.

the class DialogFilter method processResponse.

/*
     * (non-Javadoc)
     * 
     * @see gov.nist.javax.sip.stack.ServerResponseInterface#processResponse(gov.nist.javax.sip.message.SIPResponse,
     *      gov.nist.javax.sip.stack.MessageChannel)
     */
public void processResponse(SIPResponse sipResponse, MessageChannel incomingChannel) {
    String dialogID = sipResponse.getDialogId(false);
    SIPDialog sipDialog = this.sipStack.getDialog(dialogID);
    String method = sipResponse.getCSeq().getMethod();
    if (sipStack.isLoggingEnabled()) {
        sipStack.getStackLogger().logDebug("PROCESSING INCOMING RESPONSE: " + sipResponse.encodeMessage());
    }
    if (sipStack.checkBranchId() && !Utils.getInstance().responseBelongsToUs(sipResponse)) {
        if (sipStack.isLoggingEnabled()) {
            sipStack.getStackLogger().logError("Detected stray response -- dropping");
        }
        return;
    }
    if (listeningPoint == null) {
        if (sipStack.isLoggingEnabled())
            sipStack.getStackLogger().logDebug("Dropping message: No listening point" + " registered!");
        return;
    }
    SipProviderImpl sipProvider = listeningPoint.getProvider();
    if (sipProvider == null) {
        if (sipStack.isLoggingEnabled()) {
            sipStack.getStackLogger().logDebug("Dropping message:  no provider");
        }
        return;
    }
    if (sipProvider.getSipListener() == null) {
        if (sipStack.isLoggingEnabled()) {
            sipStack.getStackLogger().logDebug("Dropping message:  no sipListener registered!");
        }
        return;
    }
    SIPClientTransaction transaction = (SIPClientTransaction) this.transactionChannel;
    // 3PCC).
    if (sipDialog == null && transaction != null) {
        sipDialog = transaction.getDialog(dialogID);
        if (sipDialog != null && sipDialog.getState() == DialogState.TERMINATED)
            sipDialog = null;
    }
    if (sipStack.isLoggingEnabled())
        sipStack.getStackLogger().logDebug("Transaction = " + transaction + " sipDialog = " + sipDialog);
    if (this.transactionChannel != null) {
        String originalFrom = ((SIPRequest) this.transactionChannel.getRequest()).getFromTag();
        if (originalFrom == null ^ sipResponse.getFrom().getTag() == null) {
            if (sipStack.isLoggingEnabled())
                sipStack.getStackLogger().logDebug("From tag mismatch -- dropping response");
            return;
        }
        if (originalFrom != null && !originalFrom.equalsIgnoreCase(sipResponse.getFrom().getTag())) {
            if (sipStack.isLoggingEnabled())
                sipStack.getStackLogger().logDebug("From tag mismatch -- dropping response");
            return;
        }
    }
    if (sipStack.isDialogCreated(method) && sipResponse.getStatusCode() != 100 && sipResponse.getFrom().getTag() != null && sipResponse.getTo().getTag() != null && sipDialog == null) {
        if (sipProvider.isAutomaticDialogSupportEnabled()) {
            if (this.transactionChannel != null) {
                if (sipDialog == null) {
                    // There could be an existing dialog for this response.
                    sipDialog = sipStack.createDialog((SIPClientTransaction) this.transactionChannel, sipResponse);
                    this.transactionChannel.setDialog(sipDialog, sipResponse.getDialogId(false));
                }
            } else {
                sipDialog = this.sipStack.createDialog(sipProvider, sipResponse);
            }
        }
    } else {
        // Have a dialog but could not find transaction.
        if (sipDialog != null && transaction == null && sipDialog.getState() != DialogState.TERMINATED) {
            if (sipResponse.getStatusCode() / 100 != 2) {
                if (sipStack.isLoggingEnabled())
                    sipStack.getStackLogger().logDebug("status code != 200 ; statusCode = " + sipResponse.getStatusCode());
            } else if (sipDialog.getState() == DialogState.TERMINATED) {
                if (sipStack.isLoggingEnabled()) {
                    sipStack.getStackLogger().logDebug("Dialog is terminated -- dropping response!");
                }
                // It could be late arriving.
                if (sipResponse.getStatusCode() / 100 == 2 && sipResponse.getCSeq().getMethod().equals(Request.INVITE)) {
                    try {
                        Request ackRequest = sipDialog.createAck(sipResponse.getCSeq().getSeqNumber());
                        sipDialog.sendAck(ackRequest);
                    } catch (Exception ex) {
                        sipStack.getStackLogger().logError("Error creating ack", ex);
                    }
                }
                return;
            } else {
                boolean ackAlreadySent = false;
                if (sipDialog.isAckSeen() && sipDialog.getLastAckSent() != null) {
                    if (sipDialog.getLastAckSent().getCSeq().getSeqNumber() == sipResponse.getCSeq().getSeqNumber() && sipResponse.getDialogId(false).equals(sipDialog.getLastAckSent().getDialogId(false))) {
                        // the last ack sent corresponded to this 200
                        ackAlreadySent = true;
                    }
                }
                // 200 retransmission for the final response.
                if (ackAlreadySent && sipResponse.getCSeq().getMethod().equals(sipDialog.getMethod())) {
                    try {
                        // dont pass up the null transaction
                        if (sipStack.isLoggingEnabled())
                            sipStack.getStackLogger().logDebug("resending ACK");
                        sipDialog.resendAck();
                        return;
                    } catch (SipException ex) {
                    // What to do here ?? kill the dialog?
                    }
                }
            }
        }
    // Pass the response up to the application layer to handle
    // statelessly.
    }
    if (sipStack.isLoggingEnabled())
        sipStack.getStackLogger().logDebug("sending response to TU for processing ");
    if (sipDialog != null && sipResponse.getStatusCode() != 100 && sipResponse.getTo().getTag() != null) {
        sipDialog.setLastResponse(transaction, sipResponse);
    }
    ResponseEventExt responseEvent = new ResponseEventExt(sipProvider, (ClientTransactionExt) transaction, sipDialog, (Response) sipResponse);
    if (sipResponse.getCSeq().getMethod().equals(Request.INVITE)) {
        ClientTransactionExt originalTx = this.sipStack.getForkedTransaction(sipResponse.getTransactionId());
        responseEvent.setOriginalTransaction(originalTx);
    }
    sipProvider.handleEvent(responseEvent, transaction);
}
Also used : SIPClientTransaction(gov.nist.javax.sip.stack.SIPClientTransaction) SIPDialog(gov.nist.javax.sip.stack.SIPDialog) Request(javax.sip.message.Request) SIPRequest(gov.nist.javax.sip.message.SIPRequest) SipException(javax.sip.SipException) SIPRequest(gov.nist.javax.sip.message.SIPRequest) InvalidArgumentException(javax.sip.InvalidArgumentException) SipException(javax.sip.SipException) IOException(java.io.IOException) ObjectInUseException(javax.sip.ObjectInUseException)

Aggregations

SIPRequest (gov.nist.javax.sip.message.SIPRequest)32 IOException (java.io.IOException)17 ParseException (java.text.ParseException)17 SipException (javax.sip.SipException)16 InvalidArgumentException (javax.sip.InvalidArgumentException)10 SIPResponse (gov.nist.javax.sip.message.SIPResponse)9 Via (gov.nist.javax.sip.header.Via)8 ObjectInUseException (javax.sip.ObjectInUseException)8 SIPClientTransaction (gov.nist.javax.sip.stack.SIPClientTransaction)6 SIPDialog (gov.nist.javax.sip.stack.SIPDialog)6 DialogDoesNotExistException (javax.sip.DialogDoesNotExistException)6 TransactionDoesNotExistException (javax.sip.TransactionDoesNotExistException)6 Hop (javax.sip.address.Hop)6 SipURI (javax.sip.address.SipURI)4 ListeningPointImpl (gov.nist.javax.sip.ListeningPointImpl)3 From (gov.nist.javax.sip.header.From)3 Route (gov.nist.javax.sip.header.Route)3 To (gov.nist.javax.sip.header.To)3 SIPServerTransaction (gov.nist.javax.sip.stack.SIPServerTransaction)3 SIPTransaction (gov.nist.javax.sip.stack.SIPTransaction)3