Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
  * Conditions Of Use
  *
  * This software was developed by employees of the National Institute of
  * Standards and Technology (NIST), and others.
  * This software is has been contributed to the public domain.
  * As a result, a formal license is not needed to use the software.
  *
  * This software is provided "AS IS."
 * NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
 * OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
 * AND DATA ACCURACY.  NIST does not warrant or make any representations
 * regarding the use of the software or the results thereof, including but
 * not limited to the correctness, accuracy, reliability or usefulness of
 * the software.
 *
 *
 */
 package test.tck.msgflow.callflows.subsnotify;
 
 import javax.sip.*;
 
 
 import  test.tck.msgflow.callflows.ProtocolObjects;
 
 
 import java.util.*;

This implements a simple forking proxy to test proper handling of multiple NOTIFYs. An initial SUBSCRIBE request (i.e. without to-tag) is forked two times to the same destination. Each response should have a different to-tag; this proxy only passes the first 2xx response through, and discards the second NOTIFYs should go directly to the Contact announced in the SUBSCRIBE, hence this proxy won't see them

Author(s):
Jeroen van Bemmel
 
 
 public class Forker implements SipListener {
 
     private static AddressFactory addressFactory;
 
     private static MessageFactory messageFactory;
 
     private static HeaderFactory headerFactory;
 
     private static SipStack sipStack;
 
     private SipProvider sipProvider;
 
Flag to test UAC behavior for non-RFC3261 proxies. In particular, they dont set the 'lr' flag and perform strict routing, ie replace the request URI with the topmost Route header
 
     private static boolean nonRFC3261Proxy;
 
     private static Logger logger = Logger.getLogger(Forker.class);
     static {
         try {
             .addAppender(new FileAppender(new SimpleLayout(),
                     "logs/forkeroutputlog.txt"));
         } catch (Exception ex) {
             throw new RuntimeException(ex);
         }
     }

    
Adds a suitable Record-Route header to the given request or response

Parameters:
r
Throws:
ParseException
SipException
 
     private void recordRoute(Message mString uniqueIdthrows ParseException,
             SipException {
         Address me = .createAddress("<sip:127.0.0.1:" + 
                 + ";id=" + uniqueId + '>');
         if (!)
             ((SipURIme.getURI()).setLrParam();
         m.addFirst(rr);
    }
    public void processRequest(RequestEvent re) {
        Request request = re.getRequest();
        ServerTransaction st = re.getServerTransaction();
        
                .info("\n\nRequest " + request.getMethod() + " received at "
                        + .getStackName()
                        + " with server transaction id " + st);
        try {
            if (request.getMethod().equals(.)) {
                processSubscribe(rest);
            } else if (request.getMethod().equals(.)) { // because
                // of
                // Record-Routing
                .info("Got NOTIFY, forwarding statelessly...");
                Request newRequest = (Requestrequest.clone();
                // Forward it without creating a transaction
                // RFC3265 says: "proxy MUST record-route the initial SUBSCRIBE
                // and
                // any dialog-establishing NOTIFY requests
                // Use from tag as unique id, for debugging
                FromHeader from = (FromHeadernewRequest
                        .getHeader(.);
                recordRoute(newRequestfrom.getTag());
                if ( st != null )
                    this..put( ((ViaHeaderrequest.getHeader(.)).getBranch(), st);
                doForwardStateless(newRequestst);
            } else {
                Response notImplemented = .createResponse(
                        .request);
                ((SipProviderre.getSource()).sendResponse(notImplemented);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    
Process the invite request.
    public void processSubscribe(RequestEvent reServerTransaction st) {
        Request request = (Request)re.getRequest();
        try {
            .info("forker: got an Subscribe -> forking or forwarding");
            // Check if it is in-dialog or not
            ToHeader to = (ToHeaderrequest.getHeader(.);
            if (to.getTag() == null) {
                
                        .info("forker: got a dialog-creating Subscribe forking twice");
                if (st == null) {
                    st = ((SipProviderre.getSource())
                            .getNewServerTransaction(request);
                }
                AbstractSubsnotifyTestCase.assertTrue(
                        "Proxy: dialog stateless operation expected"st
                                .getDialog() == null);
                // Subscriber added a Route to us; remove it could check its
                // 'id' here)
                Request newRequest = (Requestrequest.clone();
                newRequest.removeFirst(.);
                doFork(newRequestst, 5070);
                doFork(newRequestst, 5071);
            } else {
                
                        .info("forker: got a mid-dialog Subscribe, forwarding statelessly...");
                // Forward it statelessly
                Request newRequest = (Requestrequest.clone();
                doForwardStateless(newRequestst);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            .error("unexpected exception"ex);
            AbstractSubsnotifyTestCase.fail("unexpected exception");
        }
    }

    
Mapping of Via branch IDs to the corresponding ServerTransaction, used for forwarding responses
    private final Map CTtoST = new HashMap();
    private String transport;
    private int port;
    public Forker(ProtocolObjects protObjects) {
         = protObjects.addressFactory;
         = protObjects.messageFactory;
         = protObjects.headerFactory;
         = protObjects.sipStack;
         = protObjects.transport;
    }
    private void doFork(Request origServerTransaction stint port)
            throws Exception {
        ViaHeader myVia = .createViaHeader("127.0.0.1",
                .getListeningPoint("udp").getPort(), "udp"null);
        Request forked = (Requestorig.clone();
        forked.addHeader(myVia);
        // Note: BIG Gotcha: Need to do this before creating the
        // ClientTransaction!
        if () {
            SipURI suri = .createSipURI(null"127.0.0.1");
            suri.setPort(port);
            forked.setRequestURI(suri);
        } else {
                    .createAddress("<sip:127.0.0.1;lr>"));
            ((SipURIroute.getAddress().getURI()).setPort(port);
            forked.addHeader(route);
        }
        // Add a Record-Route header, to test that separate dialog instances are
        // correctly created at the subscriber
        // This causes us to receive NOTIFYs too
        recordRoute(forked, Integer.toString(port));
        AbstractSubsnotifyTestCase.assertTrue("Stateless operation -- should not create a dialog "ct.getDialog() == null );
        .put(ctst);
        ct.sendRequest(); // gets sent to the outbound proxy == Notifier
    }
    private void doForwardStateless(Request origServerTransaction st)
            throws ParseExceptionInvalidArgumentExceptionSipException {
        // To forward statelessly, we need to keep the stack from
        // creating a ST for us.
        // Internally a dialog is created for the SUBSCRIBE, unless
        // dialog support
        // XXX bug: if I use branch==null here, the stack assigns a random int
        // without magic cookie
        //
        // Latest wisdom from RFC3261 says to simply copy branch from current
        // top via
        // when forwarding statelessly
        //
        ViaHeader top = (ViaHeaderorig.getHeader(.);
        ViaHeader myVia = .createViaHeader("127.0.0.1",
                "udp"top.getBranch());
        orig.addFirst(myVia);
        if () {
            RouteHeader route = (RouteHeaderorig.getHeader("Route");
            if (route != null) {
                orig.removeFirst("Route");
                orig.setRequestURI(route.getAddress().getURI());
            }
        } else {
            orig.removeFirst(.); // points at us
        }
        // To forward statelessly, we need to keep the stack from creating a ST
        // for us.
        // Internally a dialog is created for the SUBSCRIBE, unless dialog
        // support
        // is switched off (see initialization)
        if (st != null) {
            
                    .info("Would like to forward statelessly, but ST!=null! Problem...");
            .info("st == " + st);
        }
        .sendRequest(orig);
    }
    public void processResponse(ResponseEvent responseReceivedEvent) {
        .info("Got a response");
        Response response = (ResponseresponseReceivedEvent.getResponse().clone();
        ClientTransaction ct = responseReceivedEvent.getClientTransaction();
        .info("Dialog = " + responseReceivedEvent.getDialog());
        .info("Response received with client transaction id " + ct + ": "
                + response.getStatusCode());
        if (ct == null) {
            .info("Assuming NOTIFY response, forwarding...");
            // NOTIFYs are forwarded without transaction, do the same for their
            // responses
            response.removeFirst(.);
            try {
                String branchId = ((ViaHeaderresponse.getHeader(.)).getBranch();
                ServerTransaction st = this..get(branchId);
                if ( st != null) {
                    st.sendResponse(response);
                    this..remove(branchId);
                } else {
                    .sendResponse(response);
                }
            } catch (SipException e) {
                AbstractSubsnotifyTestCase.fail("Unexpected exception seen",e);
            } catch (InvalidArgumentException ex) {
                AbstractSubsnotifyTestCase.fail("Unexpected exception seen",ex);
            }
        } else {
            ServerTransaction st = (ServerTransaction.get(ct);
            if (st != null) {
                // only forward the first response
                synchronized (st) {
                    if (st.getState() == .) {
                        response.removeFirst(.);
                        try {
                            st.sendResponse(response);
                        } catch (SipException e) {
                            e.printStackTrace();
                        } catch (InvalidArgumentException e) {
                            e.printStackTrace();
                        }
                    } else {
                        .info("Discarding second response");
                    }
                    .remove(ct);
                }
            } else {
                .info("No ST found");
            }
        }
    }
    public void processTimeout(javax.sip.TimeoutEvent timeoutEvent) {
        Transaction transaction;
        if (timeoutEvent.isServerTransaction()) {
            transaction = timeoutEvent.getServerTransaction();
        } else {
            transaction = timeoutEvent.getClientTransaction();
        }
        .info("state = " + transaction.getState());
        .info("Transaction Time out");
    }
    public SipProvider createProvider(int newPort) {
        try {
            this. = newPort;
            ListeningPoint lp = .createListeningPoint("127.0.0.1",
                    );
            this. = .createSipProvider(lp);
            this..setAutomaticDialogSupportEnabled(false);
            .info("sip provider " + );
        } catch (Exception ex) {
            .error(ex.getMessage());
            ex.printStackTrace();
             = null;
        }
        return ;
    }
    public void processIOException(IOExceptionEvent exceptionEvent) {
    }
    public void processTransactionTerminated(
            TransactionTerminatedEvent transactionTerminatedEvent) {
        // TODO Auto-generated method stub
    }
    public void processDialogTerminated(
            DialogTerminatedEvent dialogTerminatedEvent) {
        // TODO Auto-generated method stub
    }
New to GrepCode? Check out our FAQ X