Search in sources :

Example 1 with RecordRoute

use of gov.nist.javax.sip.header.RecordRoute in project XobotOS by xamarin.

the class SIPDialog method setLastResponse.

/**
     * Set the last response for this dialog. This method is called for updating the dialog state
     * when a response is either sent or received from within a Dialog.
     * 
     * @param transaction -- the transaction associated with the response
     * @param sipResponse -- the last response to set.
     */
public void setLastResponse(SIPTransaction transaction, SIPResponse sipResponse) {
    this.callIdHeader = sipResponse.getCallId();
    int statusCode = sipResponse.getStatusCode();
    if (statusCode == 100) {
        if (sipStack.isLoggingEnabled())
            sipStack.getStackLogger().logWarning("Invalid status code - 100 in setLastResponse - ignoring");
        return;
    }
    this.lastResponse = sipResponse;
    this.setAssigned();
    // Adjust state of the Dialog state machine.
    if (sipStack.isLoggingEnabled()) {
        sipStack.getStackLogger().logDebug("sipDialog: setLastResponse:" + this + " lastResponse = " + this.lastResponse.getFirstLine());
    }
    if (this.getState() == DialogState.TERMINATED) {
        if (sipStack.isLoggingEnabled()) {
            sipStack.getStackLogger().logDebug("sipDialog: setLastResponse -- dialog is terminated - ignoring ");
        }
        // This is handy for late arriving OK's that we want to ACK.
        if (sipResponse.getCSeq().getMethod().equals(Request.INVITE) && statusCode == 200) {
            this.lastInviteOkReceived = Math.max(sipResponse.getCSeq().getSeqNumber(), this.lastInviteOkReceived);
        }
        return;
    }
    String cseqMethod = sipResponse.getCSeq().getMethod();
    if (sipStack.isLoggingEnabled()) {
        sipStack.getStackLogger().logStackTrace();
        sipStack.getStackLogger().logDebug("cseqMethod = " + cseqMethod);
        sipStack.getStackLogger().logDebug("dialogState = " + this.getState());
        sipStack.getStackLogger().logDebug("method = " + this.getMethod());
        sipStack.getStackLogger().logDebug("statusCode = " + statusCode);
        sipStack.getStackLogger().logDebug("transaction = " + transaction);
    }
    // responses.
    if (transaction == null || transaction instanceof ClientTransaction) {
        if (sipStack.isDialogCreated(cseqMethod)) {
            // Make a final tag assignment.
            if (getState() == null && (statusCode / 100 == 1)) {
                /*
                     * Guard aginst slipping back into early state from confirmed state.
                     */
                // Was (sipResponse.getToTag() != null || sipStack.rfc2543Supported)
                setState(SIPDialog.EARLY_STATE);
                if ((sipResponse.getToTag() != null || sipStack.rfc2543Supported) && this.getRemoteTag() == null) {
                    setRemoteTag(sipResponse.getToTag());
                    this.setDialogId(sipResponse.getDialogId(false));
                    sipStack.putDialog(this);
                    this.addRoute(sipResponse);
                }
            } else if (getState() != null && getState().equals(DialogState.EARLY) && statusCode / 100 == 1) {
                /*
                     * This case occurs for forked dialog responses. The To tag can change as a
                     * result of the forking. The remote target can also change as a result of the
                     * forking.
                     */
                if (cseqMethod.equals(getMethod()) && transaction != null && (sipResponse.getToTag() != null || sipStack.rfc2543Supported)) {
                    setRemoteTag(sipResponse.getToTag());
                    this.setDialogId(sipResponse.getDialogId(false));
                    sipStack.putDialog(this);
                    this.addRoute(sipResponse);
                }
            } else if (statusCode / 100 == 2) {
                if (cseqMethod.equals(getMethod()) && (sipResponse.getToTag() != null || sipStack.rfc2543Supported) && this.getState() != DialogState.CONFIRMED) {
                    setRemoteTag(sipResponse.getToTag());
                    this.setDialogId(sipResponse.getDialogId(false));
                    sipStack.putDialog(this);
                    this.addRoute(sipResponse);
                    setState(SIPDialog.CONFIRMED_STATE);
                }
                // Capture the OK response for later use in createAck
                if (cseqMethod.equals(Request.INVITE)) {
                    this.lastInviteOkReceived = Math.max(sipResponse.getCSeq().getSeqNumber(), this.lastInviteOkReceived);
                }
            } else if (statusCode >= 300 && statusCode <= 699 && (getState() == null || (cseqMethod.equals(getMethod()) && getState().getValue() == SIPDialog.EARLY_STATE))) {
                /*
                     * This case handles 3xx, 4xx, 5xx and 6xx responses. RFC 3261 Section 12.3 -
                     * dialog termination. Independent of the method, if a request outside of a
                     * dialog generates a non-2xx final response, any early dialogs created
                     * through provisional responses to that request are terminated.
                     */
                setState(SIPDialog.TERMINATED_STATE);
            }
            /*
                 * This code is in support of "proxy" servers that are constructed as back to back
                 * user agents. This could be a dialog in the middle of the call setup path
                 * somewhere. Hence the incoming invite has record route headers in it. The
                 * response will have additional record route headers. However, for this dialog
                 * only the downstream record route headers matter. Ideally proxy servers should
                 * not be constructed as Back to Back User Agents. Remove all the record routes
                 * that are present in the incoming INVITE so you only have the downstream Route
                 * headers present in the dialog. Note that for an endpoint - you will have no
                 * record route headers present in the original request so the loop will not
                 * execute.
                 */
            if (this.getState() != DialogState.CONFIRMED && this.getState() != DialogState.TERMINATED) {
                if (originalRequest != null) {
                    RecordRouteList rrList = originalRequest.getRecordRouteHeaders();
                    if (rrList != null) {
                        ListIterator<RecordRoute> it = rrList.listIterator(rrList.size());
                        while (it.hasPrevious()) {
                            RecordRoute rr = (RecordRoute) it.previous();
                            Route route = (Route) routeList.getFirst();
                            if (route != null && rr.getAddress().equals(route.getAddress())) {
                                routeList.removeFirst();
                            } else
                                break;
                        }
                    }
                }
            }
        } else if (cseqMethod.equals(Request.NOTIFY) && (this.getMethod().equals(Request.SUBSCRIBE) || this.getMethod().equals(Request.REFER)) && sipResponse.getStatusCode() / 100 == 2 && this.getState() == null) {
            // This is a notify response.
            this.setDialogId(sipResponse.getDialogId(true));
            sipStack.putDialog(this);
            this.setState(SIPDialog.CONFIRMED_STATE);
        } else if (cseqMethod.equals(Request.BYE) && statusCode / 100 == 2 && isTerminatedOnBye()) {
            // Dialog will be terminated when the transction is terminated.
            setState(SIPDialog.TERMINATED_STATE);
        }
    } else {
        if (cseqMethod.equals(Request.BYE) && statusCode / 100 == 2 && this.isTerminatedOnBye()) {
            /*
                 * Only transition to terminated state when 200 OK is returned for the BYE. Other
                 * status codes just result in leaving the state in COMPLETED state.
                 */
            this.setState(SIPDialog.TERMINATED_STATE);
        } else {
            boolean doPutDialog = false;
            if (getLocalTag() == null && sipResponse.getTo().getTag() != null && sipStack.isDialogCreated(cseqMethod) && cseqMethod.equals(getMethod())) {
                setLocalTag(sipResponse.getTo().getTag());
                doPutDialog = true;
            }
            if (statusCode / 100 != 2) {
                if (statusCode / 100 == 1) {
                    if (doPutDialog) {
                        setState(SIPDialog.EARLY_STATE);
                        this.setDialogId(sipResponse.getDialogId(true));
                        sipStack.putDialog(this);
                    }
                } else {
                    // see https://jain-sip.dev.java.net/servlets/ReadMsg?list=users&msgNo=797
                    if (statusCode == 489 && (cseqMethod.equals(Request.NOTIFY) || cseqMethod.equals(Request.SUBSCRIBE))) {
                        if (sipStack.isLoggingEnabled())
                            sipStack.getStackLogger().logDebug("RFC 3265 : Not setting dialog to TERMINATED for 489");
                    } else {
                        // see rfc 5057 for better explanation
                        if (!this.isReInvite() && getState() != DialogState.CONFIRMED) {
                            this.setState(SIPDialog.TERMINATED_STATE);
                        }
                    }
                }
            } else {
                /*
                     * JvB: RFC4235 says that when sending 2xx on UAS side, state should move to
                     * CONFIRMED
                     */
                if (this.dialogState <= SIPDialog.EARLY_STATE && (cseqMethod.equals(Request.INVITE) || cseqMethod.equals(Request.SUBSCRIBE) || cseqMethod.equals(Request.REFER))) {
                    this.setState(SIPDialog.CONFIRMED_STATE);
                }
                if (doPutDialog) {
                    this.setDialogId(sipResponse.getDialogId(true));
                    sipStack.putDialog(this);
                }
                /*
                     * We put the dialog into the table. We must wait for ACK before re-INVITE is
                     * sent
                     */
                if (transaction.getState() != TransactionState.TERMINATED && sipResponse.getStatusCode() == Response.OK && cseqMethod.equals(Request.INVITE) && this.isBackToBackUserAgent) {
                    /*
                             * Acquire the flag for re-INVITE so that we cannot re-INVITE before
                             * ACK is received.
                             */
                    if (!this.takeAckSem()) {
                        if (sipStack.isLoggingEnabled()) {
                            sipStack.getStackLogger().logDebug("Delete dialog -- cannot acquire ackSem");
                        }
                        this.delete();
                        return;
                    }
                }
            }
        }
    }
}
Also used : ClientTransaction(javax.sip.ClientTransaction) RecordRouteList(gov.nist.javax.sip.header.RecordRouteList) ListeningPoint(javax.sip.ListeningPoint) RecordRoute(gov.nist.javax.sip.header.RecordRoute) Route(gov.nist.javax.sip.header.Route) RecordRoute(gov.nist.javax.sip.header.RecordRoute)

Example 2 with RecordRoute

use of gov.nist.javax.sip.header.RecordRoute in project XobotOS by xamarin.

the class SIPDialog method addRoute.

/**
     * Add a route list extracted from a record route list. If this is a server dialog then we
     * assume that the record are added to the route list IN order. If this is a client dialog
     * then we assume that the record route headers give us the route list to add in reverse
     * order.
     * 
     * @param recordRouteList -- the record route list from the incoming message.
     */
private void addRoute(RecordRouteList recordRouteList) {
    try {
        if (this.isClientDialog()) {
            // This is a client dialog so we extract the record
            // route from the response and reverse its order to
            // careate a route list.
            this.routeList = new RouteList();
            // start at the end of the list and walk backwards
            ListIterator li = recordRouteList.listIterator(recordRouteList.size());
            boolean addRoute = true;
            while (li.hasPrevious()) {
                RecordRoute rr = (RecordRoute) li.previous();
                if (addRoute) {
                    Route route = new Route();
                    AddressImpl address = ((AddressImpl) ((AddressImpl) rr.getAddress()).clone());
                    route.setAddress(address);
                    route.setParameters((NameValueList) rr.getParameters().clone());
                    this.routeList.add(route);
                }
            }
        } else {
            // This is a server dialog. The top most record route
            // header is the one that is closest to us. We extract the
            // route list in the same order as the addresses in the
            // incoming request.
            this.routeList = new RouteList();
            ListIterator li = recordRouteList.listIterator();
            boolean addRoute = true;
            while (li.hasNext()) {
                RecordRoute rr = (RecordRoute) li.next();
                if (addRoute) {
                    Route route = new Route();
                    AddressImpl address = ((AddressImpl) ((AddressImpl) rr.getAddress()).clone());
                    route.setAddress(address);
                    route.setParameters((NameValueList) rr.getParameters().clone());
                    routeList.add(route);
                }
            }
        }
    } finally {
        if (sipStack.getStackLogger().isLoggingEnabled()) {
            Iterator it = routeList.iterator();
            while (it.hasNext()) {
                SipURI sipUri = (SipURI) (((Route) it.next()).getAddress().getURI());
                if (!sipUri.hasLrParam()) {
                    if (sipStack.isLoggingEnabled()) {
                        sipStack.getStackLogger().logWarning("NON LR route in Route set detected for dialog : " + this);
                        sipStack.getStackLogger().logStackTrace();
                    }
                }
            }
        }
    }
}
Also used : ListIterator(java.util.ListIterator) Iterator(java.util.Iterator) AddressImpl(gov.nist.javax.sip.address.AddressImpl) RouteList(gov.nist.javax.sip.header.RouteList) RecordRouteList(gov.nist.javax.sip.header.RecordRouteList) ListIterator(java.util.ListIterator) SipURI(javax.sip.address.SipURI) RecordRoute(gov.nist.javax.sip.header.RecordRoute) Route(gov.nist.javax.sip.header.Route) RecordRoute(gov.nist.javax.sip.header.RecordRoute)

Example 3 with RecordRoute

use of gov.nist.javax.sip.header.RecordRoute in project XobotOS by xamarin.

the class SIPClientTransaction method createAck.

/*
     * (non-Javadoc)
     * 
     * @see javax.sip.ClientTransaction#createAck()
     */
public Request createAck() throws SipException {
    SIPRequest originalRequest = this.getOriginalRequest();
    if (originalRequest == null)
        throw new SipException("bad state " + getState());
    if (getMethod().equalsIgnoreCase(Request.ACK)) {
        throw new SipException("Cannot ACK an ACK!");
    } else if (lastResponse == null) {
        throw new SipException("bad Transaction state");
    } else if (lastResponse.getStatusCode() < 200) {
        if (sipStack.isLoggingEnabled()) {
            sipStack.getStackLogger().logDebug("lastResponse = " + lastResponse);
        }
        throw new SipException("Cannot ACK a provisional response!");
    }
    SIPRequest ackRequest = originalRequest.createAckRequest((To) lastResponse.getTo());
    // Pull the record route headers from the last reesponse.
    RecordRouteList recordRouteList = lastResponse.getRecordRouteHeaders();
    if (recordRouteList == null) {
        // request URI.
        if (lastResponse.getContactHeaders() != null && lastResponse.getStatusCode() / 100 != 3) {
            Contact contact = (Contact) lastResponse.getContactHeaders().getFirst();
            javax.sip.address.URI uri = (javax.sip.address.URI) contact.getAddress().getURI().clone();
            ackRequest.setRequestURI(uri);
        }
        return ackRequest;
    }
    ackRequest.removeHeader(RouteHeader.NAME);
    RouteList routeList = new RouteList();
    // start at the end of the list and walk backwards
    ListIterator<RecordRoute> li = recordRouteList.listIterator(recordRouteList.size());
    while (li.hasPrevious()) {
        RecordRoute rr = (RecordRoute) li.previous();
        Route route = new Route();
        route.setAddress((AddressImpl) ((AddressImpl) rr.getAddress()).clone());
        route.setParameters((NameValueList) rr.getParameters().clone());
        routeList.add(route);
    }
    Contact contact = null;
    if (lastResponse.getContactHeaders() != null) {
        contact = (Contact) lastResponse.getContactHeaders().getFirst();
    }
    if (!((SipURI) ((Route) routeList.getFirst()).getAddress().getURI()).hasLrParam()) {
        // Contact may not yet be there (bug reported by Andreas B).
        Route route = null;
        if (contact != null) {
            route = new Route();
            route.setAddress((AddressImpl) ((AddressImpl) (contact.getAddress())).clone());
        }
        Route firstRoute = (Route) routeList.getFirst();
        routeList.removeFirst();
        javax.sip.address.URI uri = firstRoute.getAddress().getURI();
        ackRequest.setRequestURI(uri);
        if (route != null)
            routeList.add(route);
        ackRequest.addHeader(routeList);
    } else {
        if (contact != null) {
            javax.sip.address.URI uri = (javax.sip.address.URI) contact.getAddress().getURI().clone();
            ackRequest.setRequestURI(uri);
            ackRequest.addHeader(routeList);
        }
    }
    return ackRequest;
}
Also used : RecordRouteList(gov.nist.javax.sip.header.RecordRouteList) RouteList(gov.nist.javax.sip.header.RouteList) SIPRequest(gov.nist.javax.sip.message.SIPRequest) SipURI(javax.sip.address.SipURI) Contact(gov.nist.javax.sip.header.Contact) RecordRoute(gov.nist.javax.sip.header.RecordRoute) RecordRouteList(gov.nist.javax.sip.header.RecordRouteList) AddressImpl(gov.nist.javax.sip.address.AddressImpl) SipException(javax.sip.SipException) RecordRoute(gov.nist.javax.sip.header.RecordRoute) Route(gov.nist.javax.sip.header.Route)

Example 4 with RecordRoute

use of gov.nist.javax.sip.header.RecordRoute in project XobotOS by xamarin.

the class RecordRouteParser method parse.

/**
     * parse the String message and generate the RecordRoute List Object
     * @return SIPHeader the RecordRoute List object
     * @throws ParseException if errors occur during the parsing
     */
public SIPHeader parse() throws ParseException {
    RecordRouteList recordRouteList = new RecordRouteList();
    if (debug)
        dbg_enter("RecordRouteParser.parse");
    try {
        this.lexer.match(TokenTypes.RECORD_ROUTE);
        this.lexer.SPorHT();
        this.lexer.match(':');
        this.lexer.SPorHT();
        while (true) {
            RecordRoute recordRoute = new RecordRoute();
            super.parse(recordRoute);
            recordRouteList.add(recordRoute);
            this.lexer.SPorHT();
            char la = lexer.lookAhead(0);
            if (la == ',') {
                this.lexer.match(',');
                this.lexer.SPorHT();
            } else if (la == '\n')
                break;
            else
                throw createParseException("unexpected char");
        }
        return recordRouteList;
    } finally {
        if (debug)
            dbg_leave("RecordRouteParser.parse");
    }
}
Also used : RecordRouteList(gov.nist.javax.sip.header.RecordRouteList) RecordRoute(gov.nist.javax.sip.header.RecordRoute)

Aggregations

RecordRoute (gov.nist.javax.sip.header.RecordRoute)4 RecordRouteList (gov.nist.javax.sip.header.RecordRouteList)4 Route (gov.nist.javax.sip.header.Route)3 AddressImpl (gov.nist.javax.sip.address.AddressImpl)2 RouteList (gov.nist.javax.sip.header.RouteList)2 SipURI (javax.sip.address.SipURI)2 Contact (gov.nist.javax.sip.header.Contact)1 SIPRequest (gov.nist.javax.sip.message.SIPRequest)1 Iterator (java.util.Iterator)1 ListIterator (java.util.ListIterator)1 ClientTransaction (javax.sip.ClientTransaction)1 ListeningPoint (javax.sip.ListeningPoint)1 SipException (javax.sip.SipException)1