Package org.cafesip.jiplet

Examples of org.cafesip.jiplet.JipletDialog


        if (originalRequest.getMethod().equals(Request.CANCEL))
        {
            // reply to the canceled request and maybe to the received CANCEL
            // and also send CANCELs to pending client transactions
            JipletDialog jdialog = jiplet.getDialog(serverTransaction
                    .getDialog(), true);
            Transaction firstTransaction = (Transaction) jdialog
                    .getAttribute("firstTransaction");
            if (firstTransaction == null)
            {
                throw new JipletException(
                        "ERROR, RequestForwarding Cancel, the first transaction"
                                + " for the  dialog is null");
            }

            if (firstTransaction instanceof ClientTransaction)
            {
                return;
            }

            ServerTransaction firstServerTransaction = (ServerTransaction) firstTransaction;

            try
            {
                // send 487 Request Terminated reply to canceled request
                Response response = messageFactory.createResponse(
                        Response.REQUEST_TERMINATED, firstServerTransaction
                                .getRequest());
                firstServerTransaction.sendResponse(response);
            }
            catch (InvalidArgumentException e)
            {
                // inapplicable - it only happens if the Response was created
                // by Dialog.createReliableProvisionalResponse(int) and the
                // application calls ServerTransaction.sendResponse() to send it
                JipletLogger
                        .error("Cancel response sending failed  - invalid send method used.");
            }

            // find the response context
            TransactionsMapping transactionsMapping = jdialog
                    .getTransactionsMapping();
            Vector clientTransactions = transactionsMapping
                    .getClientTransactions(firstServerTransaction);
            if (clientTransactions == null || clientTransactions.isEmpty())
            {
                // RFC states to send the CANCEL statelessly in this case
                forwardRequestStatelessly(sipProvider, clonedRequest,
                        originalRequest, serverTransaction);
                return;
            }

            try
            {
                // send OK to CANCEL
                Response response = messageFactory.createResponse(Response.OK,
                        originalRequest);
                serverTransaction.sendResponse(response);
            }
            catch (InvalidArgumentException e)
            {
                JipletLogger
                        .error("Cancel response sending failed  - invalid send method used.");
            }

            for (Enumeration e = clientTransactions.elements(); e
                    .hasMoreElements();)
            {
                ClientTransaction ct = (ClientTransaction) e.nextElement();

                // check if the client transaction can be canceled.
                if (ct.getState().equals(TransactionState.COMPLETED)
                        || ct.getState().equals(TransactionState.TERMINATED))
                {
                    continue;
                }

                try
                {
                    JipletDialog clientJipletDialog = (JipletDialog) ct
                            .getDialog().getApplicationData();
                    if (clientJipletDialog != null)
                    {
                        ClientTransaction client = clientJipletDialog
                                .getSipProvider().getNewClientTransaction(
                                        ct.createCancel());
                        client.sendRequest();
                    }
                    else
                    {
                        ClientTransaction client = sipProvider
                                .getNewClientTransaction(ct.createCancel());
                        client.sendRequest();
                    }
                }
                catch (Exception ex)
                {
                    jiplet
                            .error("Couldn't statefully forward CANCEL : Exception "
                                    + ex.getClass().getName()
                                    + " : "
                                    + ex.getMessage()
                                    + "\n"
                                    + JipletLogger.getStackTrace(ex));
                }
            }
           
            clientTransactions.clear();

            return;

        }

        // FROM TAG UPDATE FOR METHODS DIALOG CREATOR

        // DIALOG CHECK

        // Note that the jiplet server is actually implemented as a back
        // to back User Agent.
        Dialog dialog = null;
        if (serverTransaction != null)
        {
            dialog = serverTransaction.getDialog();
        }

        DialogState dialogState = null;
        if (dialog != null)
            dialogState = dialog.getState();
        if ((dialogState == null) || (proxy.isReset() == true))
        {
            ClientTransaction clientTransaction = sipProvider
                    .getNewClientTransaction(clonedRequest);
            clientTransaction.sendRequest();

            // register for response
            jiplet.registerForResponse(clonedRequest, 60000L);

            if (dialog != null)
            {
                JipletDialog jdata = jiplet.getDialog(serverTransaction
                        .getDialog(), true);
                TransactionsMapping transactionsMapping = jdata
                        .getTransactionsMapping();
                transactionsMapping.addMapping(serverTransaction,
                        clientTransaction);

                if (clientTransaction.getDialog() != null)
                {
                    JipletDialog clientDialog = jiplet.getDialog(
                            clientTransaction.getDialog(), true);
                    if (clientDialog.getSipProvider() == null)
                    {
                        clientDialog.setSipProvider(sipProvider);
                    }
                }
            }

            return;
View Full Code Here


     */
    private void forwardRequestThroughDialog(SipProvider sipProvider,
            ServerTransaction serverTransaction, Request clonedRequest,
            Dialog dialog) throws JipletException, SipException, ParseException
    {
        JipletDialog jdata = jiplet.getDialog(serverTransaction.getDialog(),
                true);
        TransactionsMapping transactionsMapping = jdata
                .getTransactionsMapping();

        Dialog peerDialog = transactionsMapping
                .getPeerDialog(serverTransaction);

        if (peerDialog == null)
        {
            ClientTransaction ct = sipProvider
                    .getNewClientTransaction(clonedRequest);
            ct.sendRequest();
            transactionsMapping.addMapping(serverTransaction, ct);
           
            if (ct.getDialog() != null)
            {
                JipletDialog clientDialog = jiplet.getDialog(
                        ct.getDialog(), true);
                if (clientDialog.getSipProvider() == null)
                {
                    clientDialog.setSipProvider(sipProvider);
                }
            }
        }
        else if (clonedRequest.getMethod().equals(Request.ACK))
        {
            peerDialog.sendAck(clonedRequest);
        }
        else
        {

            Request dialogRequest = peerDialog.createRequest(clonedRequest
                    .getMethod());
            Object content = clonedRequest.getContent();
            if (content != null)
            {
                ContentTypeHeader contentTypeHeader = (ContentTypeHeader) clonedRequest
                        .getHeader(ContentTypeHeader.NAME);
                if (contentTypeHeader != null)
                    dialogRequest.setContent(content, contentTypeHeader);
            }

            // Copy all the headers from the original request to the
            // dialog created request:
            ListIterator l = clonedRequest.getHeaderNames();
            while (l.hasNext())
            {
                String name = (String) l.next();
                Header header = dialogRequest.getHeader(name);
                if (header == null)
                {
                    ListIterator li = clonedRequest.getHeaders(name);
                    if (li != null)
                    {
                        while (li.hasNext())
                        {
                            Header h = (Header) li.next();
                            dialogRequest.addHeader(h);
                        }
                    }
                }
                else
                {
                    if (header instanceof ViaHeader)
                    {
                        ListIterator li = clonedRequest.getHeaders(name);
                        if (li != null)
                        {
                            dialogRequest.removeHeader(name);
                            Vector v = new Vector();
                            while (li.hasNext())
                            {
                                Header h = (Header) li.next();
                                v.addElement(h);
                            }
                            for (int k = (v.size() - 1); k >= 0; k--)
                            {
                                Header h = (Header) v.elementAt(k);
                                dialogRequest.addHeader(h);
                            }
                        }
                    }
                }
            }

            JipletDialog clientDialog = jiplet.getDialog(peerDialog, false);
            ClientTransaction clientTransaction = clientDialog.getSipProvider()
                    .getNewClientTransaction(dialogRequest);
            peerDialog.sendRequest(clientTransaction);
            transactionsMapping
                    .addMapping(serverTransaction, clientTransaction);

View Full Code Here

                    .warn("Could not obtain the SIP dialog while canceling a proxy."
                            + " Cannot cancel the proxy");
            return;
        }

        JipletDialog jdialog = jiplet.getDialog(serverTransaction.getDialog(),
                false);
        if (jdialog == null)
        {
            JipletLogger
                    .warn("Could not obtain the SIP dialog while canceling a proxy."
                            + " Cannot cancel the proxy");
            return;
        }

        TransactionsMapping transactionsMapping = jdialog
                .getTransactionsMapping();
        if (transactionsMapping == null)
        {
            JipletLogger
                    .warn("Could not obtain the jiplet dialog mapping while canceling a proxy."
                            + " This should not happen");
            return;
        }

        Transaction t = (Transaction) jdialog.getAttribute("firstTransaction");
        if (t == null)
        {
            JipletLogger
                    .warn("Could not find the first transaction while canceling a proxy."
                            + " Cannot cancel the proxy");
            return;
        }
       
        if (t instanceof ClientTransaction)
        {
            JipletLogger
                    .warn("Found the first transaction in the dialog to be a client transaction while canceling a proxy."
                            + " Cannot cancel the proxy");
            return;
        }

        ServerTransaction firstServerTransaction = (ServerTransaction) t;
        Vector transactions = transactionsMapping
                .getClientTransactions(firstServerTransaction);
        if (transactions == null || transactions.isEmpty())
        {
            // this is an error condition and should not happen
            JipletLogger
                    .error("While canceling a proxy request, found empty client transaction in the transaction map for the dialog. ");
            return;
        }

        for (Enumeration en = transactions.elements(); en.hasMoreElements();)
        {
            ClientTransaction ct = (ClientTransaction) en.nextElement();

            // check if the client transaction can be canceled.
            if (ct.getState().equals(TransactionState.COMPLETED)
                    || ct.getState().equals(TransactionState.TERMINATED))
            {
                continue;
            }

            try
            {
                JipletDialog clientJipletDialog = (JipletDialog) ct.getDialog()
                        .getApplicationData();
                if (clientJipletDialog != null)
                {
                    ClientTransaction client = clientJipletDialog
                            .getSipProvider().getNewClientTransaction(
                                    ct.createCancel());
                    client.sendRequest();
                }
                else
View Full Code Here

        if (clientTransaction == null || clientTransaction.getDialog() == null)
        {
            return false;
        }

        JipletDialog jd = jiplet
                .getDialog(clientTransaction.getDialog(), false);
        if (jd == null)
        {
            return false;
        }

        TransactionsMapping transactionsMapping = jd.getTransactionsMapping();
        ServerTransaction serverTransaction = transactionsMapping
                .getServerTransaction(clientTransaction);

        if (serverTransaction != null)
        {
View Full Code Here

                            transactionsMapping = new TransactionsMapping(
                                    jiplet, serverTransaction);
                           
                            // save server transaction side SipProvider in JipletDialog
                            Dialog serverDialog = serverTransaction.getDialog();
                            JipletDialog jd = jiplet.getDialog(serverDialog, true);
                            jd.setSipProvider((SipProvider) request.getSource());
                        }
                    }
                    catch (TransactionAlreadyExistsException e)
                    {
                        if (jiplet.isDebugEnabled() == true)
                        {
                            jiplet.debug("The request message to be proxied"
                                    + " is a retransmission, we drop it!");
                        }
                    }
                }
            }

            // 2. Preprocess routing information (Section 16.4)

            /*
             * The proxy MUST inspect the Request-URI of the request. If the
             * Request-URI of the request contains a value this proxy previously
             * placed into a Record-Route header field (see Section 16.6 item
             * 4), the proxy MUST replace the Request-URI in the request with
             * the last value from the Route header field, and remove that value
             * from the Route header field. The proxy MUST then proceed as if it
             * received this modified request. ..... (idem to below:) 16.12. The
             * proxy will inspect the URI in the topmost Route header field
             * value. If it indicates this proxy, the proxy removes it from the
             * Route header field (this route node has been reached).
             */

            ListIterator routes = msg.getHeaders(RouteHeader.NAME);
            if (routes != null)
            {
                if (routes.hasNext())
                {
                    RouteHeader routeHeader = (RouteHeader) routes.next();
                    Address routeAddress = routeHeader.getAddress();
                    SipURI routeSipURI = (SipURI) routeAddress.getURI();

                    String h = routeSipURI.getHost();
                    int port = routeSipURI.getPort();

                    if (jiplet.hasAddress(h, port) == true)
                    {
                        if (jiplet.isDebugEnabled() == true)
                        {
                            jiplet
                                    .debug("A request message to be proxied has this proxy in the route header. "
                                            + " We are going to remove the first route from "
                                            + " the RouteHeader");
                        }
                        routes.remove();
                    }
                }
            }

            // 3. Determine target(s) for the request (Section 16.5)

            /*
             * The set of targets will either be predetermined by the contents
             * of the request or will be obtained from an abstract location
             * service. Each target in the set is represented as a URI.
             */

            /*
             * If the Request-URI of the request contains an maddr parameter,
             * the Request-URI MUST be placed into the target set as the only
             * target URI, and the proxy MUST proceed to Section 16.6.
             */

            URI requestURI = msg.getRequestURI();
            if (requestURI.isSipURI())
            {
                SipURI requestSipURI = (SipURI) requestURI;
                if (requestSipURI.getMAddrParam() != null)
                {
                    uris.clear();
                    uris.add(requestURI);
                    if (jiplet.isDebugEnabled() == true)
                        jiplet
                                .debug("While proxying a request, "
                                        + " the only target is the Request-URI (mAddr parameter)");

                    // 4. Forward the request
                    RequestForwarding forwarder = new RequestForwarding(jiplet,
                            this, request,
                            serverTransaction, stateful, addRecordRoute);
                    forwarder.forwardRequest(uris);
                    return;
                }
            }

            if (stateful == true)
            {
                // Forward to next hop but dont reply OK right away for the
                // BYE. Bye is end-to-end not hop by hop!
                if (msg.getMethod().equals(Request.BYE))
                {
                    if (serverTransaction == null)
                    {
                        if (jiplet.isDebugEnabled() == true)
                            jiplet
                                    .debug("While proxying a request, null server transaction for BYE");
                        return;
                    }

                    Dialog d = serverTransaction.getDialog();
                    TransactionsMapping transactionsMapping = jiplet.getDialog(
                            d, true).getTransactionsMapping();
                    Dialog peerDialog = transactionsMapping
                            .getPeerDialog(serverTransaction);
                    Request clonedRequest = (Request) msg.clone();
                    FromHeader from = (FromHeader) clonedRequest
                            .getHeader(FromHeader.NAME);
                    from.removeParameter("tag");
                    ToHeader to = (ToHeader) clonedRequest
                            .getHeader(ToHeader.NAME);
                    to.removeParameter("tag");
                   
                    if (peerDialog.getState() != null)
                    {
                        JipletDialog clientDialog = jiplet.getDialog(peerDialog, false);
                        SipProvider clientProvider = clientDialog.getSipProvider();
                        ListeningPoint lp = clientProvider.getListeningPoints()[0];
                        // TODO, need to save the right transport - save LP instead of SipProvider?
                        // (in JipletDialog)
                        ViaHeader via = jiplet.getHeaderFactory().createViaHeader(lp.getIPAddress(),
                                    lp.getPort(), lp.getTransport(), null);
                        clonedRequest.addHeader(via);   
                       
                        ClientTransaction newct = clientProvider
                                .getNewClientTransaction(clonedRequest);
                        transactionsMapping
                                .addMapping(serverTransaction, newct);
                        peerDialog.sendRequest(newct);
                        jiplet.registerForResponse(clonedRequest, 60000L);
                        return;
                    }
                    else
                    {
                        // the peer dialog is not yet established so bail out.
                        // this is a client error - client is sending BYE
                        // before dialog establishment.
                        jiplet
                                .warn("While proxying a SIP request, bad dialog state - BYE dropped");
                        return;
                    }
                }
                // NEW CODE added by Amit to handle ACK and CANCEL
                else if (msg.getMethod().equals(Request.ACK))
                {
                    if (serverTransaction == null)
                    {
                        if (jiplet.isDebugEnabled() == true)
                            jiplet
                                    .debug("While proxying an ACK request, null server transaction");
                        return;
                    }

                    Dialog d = serverTransaction.getDialog();
                    TransactionsMapping transactionsMapping = jiplet.getDialog(
                            d, true).getTransactionsMapping();
                    Dialog peerDialog = transactionsMapping
                            .getPeerDialog(serverTransaction);
                    Request clonedRequest = (Request) msg.clone();
                    if (peerDialog.getState() != null)
                    {
                        peerDialog.sendAck(clonedRequest);
                    }
                    return;
                }
                else if (msg.getMethod().equals(Request.CANCEL))
                {
                    if (serverTransaction == null)
                    {
                        if (jiplet.isDebugEnabled() == true)
                            jiplet
                                    .debug("While proxying a CANCEL request, null server transaction for BYE");
                        return;
                    }

                    Dialog d = serverTransaction.getDialog();
                    JipletDialog jd = jiplet.getDialog(d, true);
                    TransactionsMapping transactionsMapping = jd
                            .getTransactionsMapping();

                    Vector transactions = transactionsMapping
                            .getClientTransactions((ServerTransaction) jd
                                    .getAttribute("firstTransaction"));
                   
                    if (transactions == null || transactions.isEmpty())
                    {
                        return;
                    }

                    for (Enumeration en = transactions.elements(); en
                            .hasMoreElements();)
                    {
                        ClientTransaction ct = (ClientTransaction) en
                                .nextElement();

                        // check if the client transaction can be canceled.
                        if (ct.getState().equals(TransactionState.COMPLETED)
                                || ct.getState().equals(
                                        TransactionState.TERMINATED))
                        {
                            continue;
                        }
                       
                        JipletDialog clientJipletDialog = (JipletDialog) ct.getDialog().getApplicationData();
                        if (clientJipletDialog != null)
                        {
                            ClientTransaction client = clientJipletDialog.getSipProvider().getNewClientTransaction(ct.createCancel());
                            client.sendRequest();
                        }
                    }
                }
                // END NEW CODE
View Full Code Here

    /** Creates new TransactionsTable */
    public TransactionsMapping(Jiplet jiplet, ServerTransaction serverTransaction)
    {
        this.jiplet = jiplet;
        Dialog serverDialog = serverTransaction.getDialog();
        JipletDialog jd = jiplet.getDialog(serverDialog, true);
        table = new Hashtable();
        jd.setTransactionsMapping(this);
       
        jd.setAttribute("firstTransaction", serverTransaction);
    }
View Full Code Here

            if (ct != null)
                return ct.getDialog();
        }
        else
        {
            JipletDialog jdialog = jiplet.getDialog(serverTransaction.getDialog(),
                    false);
            if (jdialog == null)
            {
                JipletLogger
                        .warn("Could not obtain the SIP dialog while finding the peer dialog."
                                + " Cannot proxy anything to the peer");
                return null;
            }
           
            Transaction transaction = (Transaction) jdialog.getAttribute("firstTransaction");
            if (transaction == null)
            {
                JipletLogger
                        .warn("Could not find the first transaction while finding the peer dialog."
                                + " Cannot proxy anything to the peer");
View Full Code Here

            return;
        }
       
        Vector clients = getClientTransactions(serverTransaction);
        Dialog dialog = serverTransaction.getDialog();
        JipletDialog jd = jiplet.getDialog(dialog, true);
        TransactionsMapping map = jd.getTransactionsMapping();
        Dialog clientDialog = clientTransaction.getDialog();
        JipletDialog cjd = jiplet.getDialog(clientDialog, true);
        cjd.setTransactionsMapping(map);
       
        // save first transaction on client side, if this is the first
        if (cjd.getAttribute("firstTransaction") == null)
        {
            cjd.setAttribute("firstTransaction", clientTransaction);
        }
       
         if (clients == null)
        {
            clients = new Vector();
View Full Code Here

            if (clientTransaction.getDialog() == null)
                return;
            else
            {
                JipletDialog jd = jiplet.getDialog(clientTransaction
                        .getDialog(), true);
                transactionsMapping = jd.getTransactionsMapping();
            }

            // 1. Find the appropriate response context

            /*
             * The jiplet locates the "response context" it created before
             * forwarding the original request using the key described in
             * Section 16.6. The remaining processing steps take place in this
             * context.
             */

            // I guess it is done by the stack....
            // 2. Update timer C for provisional responses
            // I guess it is done by the stack....
            // 3. Via
            /*
             * The jiplet removes the topmost Via header field value from the
             * response. If no Via header field values remain in the response,
             * the response was meant for this element and MUST NOT be
             * forwarded. The remainder of the processing described in this
             * section is not performed on this message, the UAC processing
             * rules described in Section 8.1.3 are followed instead (transport
             * layer processing has already occurred).
             */

            ListIterator viaList = response.getHeaders(ViaHeader.NAME);
            viaList.next();
            viaList.remove();
            if (!viaList.hasNext())
            {
                return;
            }

            // 4. Add response to context

            // The stack takes care of that...

            // 5. Check response for forwarding

            /*
             * Until a final response has been sent on the server transaction,
             * the following responses MUST be forwarded immediately: - Any
             * provisional response other than 100 (Trying) - Any 2xx response
             */

            if (response.getStatusCode() == Response.TRYING)
            {
                return;
            }

            if (response.getStatusCode() == Response.REQUEST_TERMINATED)
            {
                return;
            }

            CSeqHeader cseqHeader = (CSeqHeader) response
                    .getHeader(CSeqHeader.NAME);

            // No special processing for OK related to SUBSCIRBE and NOTIFY
            if (presenceServer && response.getStatusCode() == Response.OK
                    && cseqHeader.getMethod().equals(Request.SUBSCRIBE))
            {
                return;
            }

            if (presenceServer && response.getStatusCode() == Response.OK
                    && cseqHeader.getMethod().equals(Request.NOTIFY))
            {
                return;
            }

            // 6. Choosing the best response

            /*
             * A jiplet MUST NOT insert a tag into the To header field of a 1xx
             * or 2xx response if the request did not contain one. A jiplet MUST
             * NOT modify the tag in the To header field of a 1xx or 2xx
             * response.
             *
             * An element SHOULD preserve the To tag when simply forwarding a
             * 3-6xx response to a request that did not contain a To tag.
             *
             * A jiplet MUST NOT modify the To tag in any forwarded response to
             * a request that contains a To tag.
             */

            // 7. Aggregate Authorization Header Field Values
            // 8. Record-Route (we may modify it before sending, see further
            // below)
            // 9. Forward response
            /*
             * 16.7. 9. Forward response: The jiplet MUST pass the response to
             * the server transaction associated with the response context. This
             * will result in the response being sent to the location now
             * indicated in the topmost Via header field value. If the server
             * transaction is no longer available to handle the transmission,
             * the element MUST forward the response statelessly by sending it
             * to the server transport. The server transaction might indicate
             * failure to send the response or signal a timeout in its state
             * machine. These errors would be logged for diagnostic purposes as
             * appropriate, but the protocol requires no remedial action from
             * the jiplet.
             */
            ServerTransaction serverTransaction = transactionsMapping
                    .getServerTransaction(clientTransaction);

            // For forking:
            if ((response.getStatusCode() == Response.UNAUTHORIZED || response
                    .getStatusCode() == Response.DECLINE)
                    && serverTransaction != null)
            {
                // check the busy or decline
                Vector clientsTransactionList = transactionsMapping
                        .getClientTransactions(serverTransaction);
                if (clientsTransactionList != null
                        && clientsTransactionList.size() > 1)
                {
                    transactionsMapping.removeMapping(clientTransaction);
                }
            }

            // For forking:
            if (response.getStatusCode() == Response.OK
                    && serverTransaction != null)
            {
                Dialog peerDialog = serverTransaction.getDialog();
                Vector clientsTransactionList = transactionsMapping
                        .getClientTransactions(serverTransaction);

                if (peerDialog != null && peerDialog.getState() != null
                        && peerDialog.getState().equals(DialogState.CONFIRMED)
                        && clientsTransactionList != null
                        && clientsTransactionList.size() > 1)
                {
                    Dialog dialog = clientTransaction.getDialog();
                    Request byeRequest = dialog.createRequest(Request.BYE);

                    ClientTransaction ct = responseProvider
                            .getNewClientTransaction(byeRequest);
                    dialog.sendRequest(ct);

                    // we have to remove the transaction from the table:
                    transactionsMapping.removeMapping(clientTransaction);
                    return;
                }
                else
                {
                    if (serverTransaction != null)
                        transactionsMapping.addMapping(serverTransaction,
                                clientTransaction);
                }
            }

            if (serverTransaction == null)
            {
                ListeningPoint defaultLP = jiplet.getListeningPointDefault();
                jiplet.getSipProvider(defaultLP).sendResponse(response);
                return;
            }
            else
            {
                // we can try to modify the tags:
                Dialog dialog = serverTransaction.getDialog();
                if (dialog != null)
                {
                    String localTag = dialog.getLocalTag();
                    String remoteTag = dialog.getRemoteTag();
                    ToHeader toHeader = (ToHeader) response
                            .getHeader(ToHeader.NAME);
                    FromHeader fromHeader = (FromHeader) response
                            .getHeader(FromHeader.NAME);

                    if (localTag != null && remoteTag != null)
                    {
                        if (dialog.isServer())
                        {
                            toHeader.setTag(localTag);
                        }
                        else
                        {
                            fromHeader.setTag(remoteTag);
                        }
                    }
                }

                // 8. Record-Route - modify record route header if needed
                /*
                 * If the selected response contains a Record-Route header field
                 * value originally provided by this proxy, the proxy MAY choose
                 * to rewrite the value before forwarding the response. This
                 * allows the proxy to provide different URIs for itself to the
                 * next upstream and downstream elements. A proxy may choose to
                 * use this mechanism for any reason. For instance, it is useful
                 * for multi-homed hosts.
                 */

                ListIterator rrHeaders = response
                        .getHeaders(RecordRouteHeader.NAME);
                while (rrHeaders.hasNext())
                {
                    // look for the 1st one to replace, replace it & get out
                    RecordRouteHeader rr = (RecordRouteHeader) rrHeaders.next();
                    URI uri = rr.getAddress().getURI();
                    if (uri instanceof SipURI)
                    {
                        SipURI sipURI = (SipURI) uri;
                        // is this a record route header we added?
                        if (jiplet.hasAddress(sipURI.getHost(), sipURI
                                .getPort()))
                        {
                            // does this one need replacing?
                            String user = sipURI.getUser();
                            if (user != null)
                            {
                                StringTokenizer tok = new StringTokenizer(user,
                                        "-");
                                if (tok.countTokens() == 2)
                                {
                                    SipURI sourceURI = jiplet
                                            .getAddressFactory().createSipURI(
                                                    null, tok.nextToken());

                                    sourceURI.setPort(Integer.valueOf(
                                            tok.nextToken()).intValue());
                                    sourceURI.setLrParam();

                                    // rewrite it back into the RR header
                                    rr.getAddress().setURI(sourceURI);
                                    rrHeaders.set(rr);
                                    break;
                                }
                            }
                        }
                    }
                }

                try
                {
                    serverTransaction.sendResponse(response);
                }
                catch (InvalidArgumentException e)
                {
                    // this exception only happens if the Response was created
                    // by Dialog.createReliableProvisionalResponse(int) and the
                    // application calls ServerTransaction.sendResponse() to
                    // send it
                    JipletLogger
                            .error("Response forwarding failed - invalid send method for reliable provisional response - need to add a check for this and call dialog method sendReliableProvisionalResponse() instead. Response = \n"
                                    + response.toString());
                }
            }

            /** ************************************************************************ */
            /** ************ 10. Generate CANCELs ******* */
            /** ************************************************************************* */
            /*
             * If the forwarded response was a final response, the jiplet MUST
             * generate a CANCEL request for all pending client transactions
             * associated with this response context. A jiplet SHOULD also
             * generate a CANCEL request for all pending client transactions
             * associated with this response context when it receives a 6xx
             * response. A pending client transaction is one that has received a
             * provisional response, but no final response (it is in the
             * proceeding state) and has not had an associated CANCEL generated
             * for it. Generating CANCEL requests is described in Section 9.1.
             */

            if (response.getStatusCode() == Response.OK
                    || (response.getStatusCode() >= Response.BUSY_EVERYWHERE && response
                            .getStatusCode() <= Response.SESSION_NOT_ACCEPTABLE))
            {
                Vector clientsTransactionList = transactionsMapping
                        .getClientTransactions(serverTransaction);

                for (Enumeration e = clientsTransactionList.elements(); e
                        .hasMoreElements();)
                {
                    ClientTransaction ctr = (ClientTransaction) e.nextElement();
                    if (ctr != clientTransaction)
                    {
                        TransactionState transactionState = ctr.getState();
                        if (transactionState == null
                                || transactionState.getValue() == TransactionState.PROCEEDING
                                        .getValue())
                        {

                            /*
                             * 9.1: The following procedures are used to
                             * construct a CANCEL request. The Request-URI,
                             * Call-ID, To, the numeric part of CSeq, and From
                             * header fields in the CANCEL request MUST be
                             * identical to those in the request being
                             * cancelled, including tags. A CANCEL constructed
                             * by a client MUST have only a single Via header
                             * field value matching the top Via value in the
                             * request being cancelled. Using the same values
                             * for these header fields allows the CANCEL to be
                             * matched with the request it cancels (Section 9.2
                             * indicates how such matching occurs). However, the
                             * method part of the CSeq header field MUST have a
                             * value of CANCEL. This allows it to be identified
                             * and processed as a transaction in its own right
                             * (See Section 17).
                             *
                             * If the request being cancelled contains a Route
                             * header field, the CANCEL request MUST include
                             * that Route header field's values.
                             */
                            Request cancelRequest = ctr.createCancel();

                            // Let's keep only the top most via header:
                            ListIterator cancelViaList = cancelRequest
                                    .getHeaders(ViaHeader.NAME);
                            cancelRequest.removeHeader(ViaHeader.NAME);
                            cancelRequest.addHeader((ViaHeader) cancelViaList
                                    .next());

                            SipURI localAddr = (SipURI) ctr.getDialog()
                                    .getLocalParty().getURI();
                            SipProvider p = jiplet.getSipProvider(localAddr
                                    .getHost(), localAddr.getPort());

                            if (p == null)
                            {
                                ListeningPoint defaultLP = jiplet
                                        .getListeningPointDefault();
                                p = jiplet.getSipProvider(defaultLP);
                            }

                            ClientTransaction ct = p
                                    .getNewClientTransaction(cancelRequest);
                            ct.sendRequest();
                        }
                    }
                }
            }
        }
        finally
        {
            if (clientTransaction != null
                    && clientTransaction.getState().equals(
                            TransactionState.COMPLETED))
            {
                if (clientTransaction.getDialog() != null)
                {
                    JipletDialog jd = jiplet.getDialog(clientTransaction
                            .getDialog(), true);
                    transactionsMapping = jd.getTransactionsMapping();

                    if (transactionsMapping != null)
                        transactionsMapping.removeMapping(clientTransaction);
                }
            }
View Full Code Here

TOP

Related Classes of org.cafesip.jiplet.JipletDialog

Copyright © 2018 www.massapicom. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.