Search in sources :

Example 1 with RecordRouteList

use of gov.nist.javax.sip.header.RecordRouteList 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 RecordRouteList

use of gov.nist.javax.sip.header.RecordRouteList 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 RecordRouteList

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

the class SIPDialog method addRoute.

/**
     * Add a Route list extracted from a SIPRequest to this Dialog.
     * 
     * @param sipRequest
     */
public synchronized void addRoute(SIPRequest sipRequest) {
    if (sipStack.isLoggingEnabled()) {
        sipStack.getStackLogger().logDebug("setContact: dialogState: " + this + "state = " + this.getState());
    }
    if (this.dialogState == CONFIRMED_STATE && SIPRequest.isTargetRefresh(sipRequest.getMethod())) {
        this.doTargetRefresh(sipRequest);
    }
    if (this.dialogState == CONFIRMED_STATE || this.dialogState == TERMINATED_STATE) {
        return;
    }
    // Fix for issue #225: mustn't learn Route set from mid-dialog requests
    if (sipRequest.getToTag() != null)
        return;
    // Incoming Request has the route list
    RecordRouteList rrlist = sipRequest.getRecordRouteHeaders();
    // order
    if (rrlist != null) {
        this.addRoute(rrlist);
    } else {
        // Set the rotue list to the last seen route list.
        this.routeList = new RouteList();
    }
    // put the contact header from the incoming request into
    // the route set. JvB: some duplication here, ref. doTargetRefresh
    ContactList contactList = sipRequest.getContactHeaders();
    if (contactList != null) {
        this.setRemoteTarget((ContactHeader) contactList.getFirst());
    }
}
Also used : RecordRouteList(gov.nist.javax.sip.header.RecordRouteList) RouteList(gov.nist.javax.sip.header.RouteList) RecordRouteList(gov.nist.javax.sip.header.RecordRouteList) ContactList(gov.nist.javax.sip.header.ContactList)

Example 4 with RecordRouteList

use of gov.nist.javax.sip.header.RecordRouteList 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 5 with RecordRouteList

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

the class SIPResponse method createRequest.

/**
     * Generate a request from a response.
     *
     * @param requestURI -- the request URI to assign to the request.
     * @param via -- the Via header to assign to the request
     * @param cseq -- the CSeq header to assign to the request
     * @param from -- the From header to assign to the request
     * @param to -- the To header to assign to the request
     * @return -- the newly generated sip request.
     */
public SIPRequest createRequest(SipUri requestURI, Via via, CSeq cseq, From from, To to) {
    SIPRequest newRequest = new SIPRequest();
    String method = cseq.getMethod();
    newRequest.setMethod(method);
    newRequest.setRequestURI(requestURI);
    this.setBranch(via, method);
    newRequest.setHeader(via);
    newRequest.setHeader(cseq);
    Iterator headerIterator = getHeaders();
    while (headerIterator.hasNext()) {
        SIPHeader nextHeader = (SIPHeader) headerIterator.next();
        // Some headers do not belong in a Request ....
        if (SIPMessage.isResponseHeader(nextHeader) || nextHeader instanceof ViaList || nextHeader instanceof CSeq || nextHeader instanceof ContentType || nextHeader instanceof ContentLength || nextHeader instanceof RecordRouteList || nextHeader instanceof RequireList || // JvB: added
        nextHeader instanceof ContactList || nextHeader instanceof ContentLength || nextHeader instanceof ServerHeader || nextHeader instanceof ReasonHeader || nextHeader instanceof SessionExpires || nextHeader instanceof ReasonList) {
            continue;
        }
        if (nextHeader instanceof To)
            nextHeader = (SIPHeader) to;
        else if (nextHeader instanceof From)
            nextHeader = (SIPHeader) from;
        try {
            newRequest.attachHeader(nextHeader, false);
        } catch (SIPDuplicateHeaderException e) {
            //Should not happen!
            e.printStackTrace();
        }
    }
    try {
        // JvB: all requests need a Max-Forwards
        newRequest.attachHeader(new MaxForwards(70), false);
    } catch (Exception d) {
    }
    if (MessageFactoryImpl.getDefaultUserAgentHeader() != null) {
        newRequest.setHeader(MessageFactoryImpl.getDefaultUserAgentHeader());
    }
    return newRequest;
}
Also used : RequireList(gov.nist.javax.sip.header.RequireList) SessionExpires(gov.nist.javax.sip.header.extensions.SessionExpires) ReasonList(gov.nist.javax.sip.header.ReasonList) CSeq(gov.nist.javax.sip.header.CSeq) ContentType(gov.nist.javax.sip.header.ContentType) MaxForwards(gov.nist.javax.sip.header.MaxForwards) ContactList(gov.nist.javax.sip.header.ContactList) From(gov.nist.javax.sip.header.From) ReasonHeader(javax.sip.header.ReasonHeader) ParseException(java.text.ParseException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) ViaList(gov.nist.javax.sip.header.ViaList) SIPHeader(gov.nist.javax.sip.header.SIPHeader) Iterator(java.util.Iterator) RecordRouteList(gov.nist.javax.sip.header.RecordRouteList) ServerHeader(javax.sip.header.ServerHeader) ContentLength(gov.nist.javax.sip.header.ContentLength) To(gov.nist.javax.sip.header.To)

Aggregations

RecordRouteList (gov.nist.javax.sip.header.RecordRouteList)7 RecordRoute (gov.nist.javax.sip.header.RecordRoute)4 Route (gov.nist.javax.sip.header.Route)3 RouteList (gov.nist.javax.sip.header.RouteList)3 AddressImpl (gov.nist.javax.sip.address.AddressImpl)2 ContactList (gov.nist.javax.sip.header.ContactList)2 SIPHeader (gov.nist.javax.sip.header.SIPHeader)2 SIPRequest (gov.nist.javax.sip.message.SIPRequest)2 ParseException (java.text.ParseException)2 Iterator (java.util.Iterator)2 SipException (javax.sip.SipException)2 SipURI (javax.sip.address.SipURI)2 CSeq (gov.nist.javax.sip.header.CSeq)1 Contact (gov.nist.javax.sip.header.Contact)1 ContentLength (gov.nist.javax.sip.header.ContentLength)1 ContentType (gov.nist.javax.sip.header.ContentType)1 From (gov.nist.javax.sip.header.From)1 MaxForwards (gov.nist.javax.sip.header.MaxForwards)1 RSeq (gov.nist.javax.sip.header.RSeq)1 ReasonList (gov.nist.javax.sip.header.ReasonList)1