Home | History | Annotate | Download | only in stack
      1 /*
      2  * Conditions Of Use
      3  *
      4  * This software was developed by employees of the National Institute of
      5  * Standards and Technology (NIST), an agency of the Federal Government.
      6  * Pursuant to title 15 Untied States Code Section 105, works of NIST
      7  * employees are not subject to copyright protection in the United States
      8  * and are considered to be in the public domain.  As a result, a formal
      9  * license is not needed to use the software.
     10  *
     11  * This software is provided by NIST as a service and is expressly
     12  * provided "AS IS."  NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
     13  * OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
     14  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
     15  * AND DATA ACCURACY.  NIST does not warrant or make any representations
     16  * regarding the use of the software or the results thereof, including but
     17  * not limited to the correctness, accuracy, reliability or usefulness of
     18  * the software.
     19  *
     20  * Permission to use this software is contingent upon your acceptance
     21  * of the terms of this agreement
     22  *
     23  * .
     24  *
     25  */
     26 /*****************************************************************************
     27  *   Product of NIST/ITL Advanced Networking Technologies Division (ANTD).    *
     28  *****************************************************************************/
     29 
     30 package gov.nist.javax.sip.stack;
     31 
     32 import gov.nist.core.InternalErrorHandler;
     33 import gov.nist.core.ServerLogger;
     34 import gov.nist.core.StackLogger;
     35 import gov.nist.core.ThreadAuditor;
     36 import gov.nist.javax.sip.SIPConstants;
     37 import gov.nist.javax.sip.header.CSeq;
     38 import gov.nist.javax.sip.header.CallID;
     39 import gov.nist.javax.sip.header.From;
     40 import gov.nist.javax.sip.header.RequestLine;
     41 import gov.nist.javax.sip.header.StatusLine;
     42 import gov.nist.javax.sip.header.To;
     43 import gov.nist.javax.sip.header.Via;
     44 import gov.nist.javax.sip.header.ViaList;
     45 import gov.nist.javax.sip.message.SIPMessage;
     46 import gov.nist.javax.sip.message.SIPRequest;
     47 import gov.nist.javax.sip.message.SIPResponse;
     48 import gov.nist.javax.sip.parser.ParseExceptionListener;
     49 import gov.nist.javax.sip.parser.StringMsgParser;
     50 
     51 import java.io.IOException;
     52 import java.io.OutputStream;
     53 import java.net.DatagramPacket;
     54 import java.net.DatagramSocket;
     55 import java.net.InetAddress;
     56 import java.net.Socket;
     57 import java.text.ParseException;
     58 import java.util.HashSet;
     59 import java.util.Hashtable;
     60 import java.util.TimerTask;
     61 
     62 import javax.sip.address.Hop;
     63 
     64 /*
     65  * Kim Kirby (Keyvoice) suggested that duplicate checking should be added to the
     66  * stack (later removed). Lamine Brahimi suggested a single threaded behavior
     67  * flag be added to this. Niklas Uhrberg suggested that thread pooling support
     68  * be added to this for performance and resource management. Peter Parnes found
     69  * a bug with this code that was sending it into an infinite loop when a bad
     70  * incoming message was parsed. Bug fix by viswashanti.kadiyala (at) antepo.com.
     71  * Hagai Sela addded fixes for NAT traversal. Jeroen van Bemmel fixed up for
     72  * buggy clients (such as windows messenger) and added code to return
     73  * BAD_REQUEST. David Alique fixed an address recording bug. Jeroen van Bemmel
     74  * fixed a performance issue where the stack was doing DNS lookups (potentially
     75  * unnecessary). Ricardo Bora (Natural Convergence ) added code that prevents
     76  * the stack from exitting when an exception is encountered.
     77  *
     78  */
     79 
     80 /**
     81  * This is the UDP Message handler that gets created when a UDP message needs to
     82  * be processed. The message is processed by creating a String Message parser
     83  * and invoking it on the message read from the UDP socket. The parsed structure
     84  * is handed off via a SIP stack request for further processing. This stack
     85  * structure isolates the message handling logic from the mechanics of sending
     86  * and recieving messages (which could be either udp or tcp.
     87  *
     88  *
     89  * @author M. Ranganathan <br/>
     90  *
     91  *
     92  *
     93  * @version 1.2 $Revision: 1.66 $ $Date: 2010/01/14 05:15:49 $
     94  */
     95 public class UDPMessageChannel extends MessageChannel implements
     96         ParseExceptionListener, Runnable, RawMessageChannel {
     97 
     98 
     99     /**
    100      * SIP Stack structure for this channel.
    101      */
    102     protected SIPTransactionStack sipStack;
    103 
    104     /**
    105      * The parser we are using for messages received from this channel.
    106      */
    107     protected StringMsgParser myParser;
    108 
    109     /**
    110      * Where we got the stuff from
    111      */
    112     private InetAddress peerAddress;
    113 
    114     private String myAddress;
    115 
    116     private int peerPacketSourcePort;
    117 
    118     private InetAddress peerPacketSourceAddress;
    119 
    120     /**
    121      * Reciever port -- port of the destination.
    122      */
    123     private int peerPort;
    124 
    125     /**
    126      * Protocol to use when talking to receiver (i.e. when sending replies).
    127      */
    128     private String peerProtocol;
    129 
    130     protected int myPort;
    131 
    132     private DatagramPacket incomingPacket;
    133 
    134     private long receptionTime;
    135 
    136     /*
    137      * A table that keeps track of when the last pingback was sent to a given remote IP address
    138      * and port. This is for NAT compensation. This stays in the table for 1 seconds and prevents
    139      * infinite loop. If a second pingback happens in that period of time, it will be dropped.
    140      */
    141     private Hashtable<String,PingBackTimerTask> pingBackRecord = new Hashtable<String,PingBackTimerTask>();
    142 
    143     class PingBackTimerTask extends TimerTask {
    144         String ipAddress;
    145         int port;
    146 
    147         public PingBackTimerTask(String ipAddress, int port) {
    148             this.ipAddress = ipAddress;
    149             this.port = port;
    150             pingBackRecord.put(ipAddress + ":" + port, this);
    151         }
    152         @Override
    153         public void run() {
    154            pingBackRecord.remove(ipAddress + ":" + port);
    155         }
    156         @Override
    157         public int hashCode() {
    158             return (ipAddress + ":" + port).hashCode();
    159         }
    160     }
    161 
    162     /**
    163      * Constructor - takes a datagram packet and a stack structure Extracts the
    164      * address of the other from the datagram packet and stashes away the
    165      * pointer to the passed stack structure.
    166      *
    167      * @param stack
    168      *            is the shared SIPStack structure
    169      * @param messageProcessor
    170      *            is the creating message processor.
    171      */
    172     protected UDPMessageChannel(SIPTransactionStack stack,
    173             UDPMessageProcessor messageProcessor) {
    174         super.messageProcessor = messageProcessor;
    175         this.sipStack = stack;
    176 
    177         Thread mythread = new Thread(this);
    178 
    179         this.myAddress = messageProcessor.getIpAddress().getHostAddress();
    180         this.myPort = messageProcessor.getPort();
    181 
    182         mythread.setName("UDPMessageChannelThread");
    183         mythread.setDaemon(true);
    184         mythread.start();
    185 
    186     }
    187 
    188     /**
    189      * Constructor. We create one of these in order to process an incoming
    190      * message.
    191      *
    192      * @param stack
    193      *            is the SIP sipStack.
    194      * @param messageProcessor
    195      *            is the creating message processor.
    196      * @param packet
    197      *            is the incoming datagram packet.
    198      */
    199     protected UDPMessageChannel(SIPTransactionStack stack,
    200             UDPMessageProcessor messageProcessor, DatagramPacket packet) {
    201 
    202         this.incomingPacket = packet;
    203         super.messageProcessor = messageProcessor;
    204         this.sipStack = stack;
    205 
    206         this.myAddress = messageProcessor.getIpAddress().getHostAddress();
    207         this.myPort = messageProcessor.getPort();
    208         Thread mythread = new Thread(this);
    209         mythread.setDaemon(true);
    210         mythread.setName("UDPMessageChannelThread");
    211 
    212         mythread.start();
    213 
    214     }
    215 
    216     /**
    217      * Constructor. We create one of these when we send out a message.
    218      *
    219      * @param targetAddr
    220      *            INET address of the place where we want to send messages.
    221      * @param port
    222      *            target port (where we want to send the message).
    223      * @param sipStack
    224      *            our SIP Stack.
    225      */
    226     protected UDPMessageChannel(InetAddress targetAddr, int port,
    227             SIPTransactionStack sipStack, UDPMessageProcessor messageProcessor) {
    228         peerAddress = targetAddr;
    229         peerPort = port;
    230         peerProtocol = "UDP";
    231         super.messageProcessor = messageProcessor;
    232         this.myAddress = messageProcessor.getIpAddress().getHostAddress();
    233         this.myPort = messageProcessor.getPort();
    234         this.sipStack = sipStack;
    235         if (sipStack.isLoggingEnabled()) {
    236             this.sipStack.getStackLogger().logDebug("Creating message channel "
    237                     + targetAddr.getHostAddress() + "/" + port);
    238         }
    239     }
    240 
    241     /**
    242      * Run method specified by runnnable.
    243      */
    244     public void run() {
    245         // Assume no thread pooling (bug fix by spierhj)
    246         ThreadAuditor.ThreadHandle threadHandle = null;
    247 
    248         while (true) {
    249             // Create a new string message parser to parse the list of messages.
    250             if (myParser == null) {
    251                 myParser = new StringMsgParser();
    252                 myParser.setParseExceptionListener(this);
    253             }
    254             // messages that we write out to him.
    255             DatagramPacket packet;
    256 
    257             if (sipStack.threadPoolSize != -1) {
    258                 synchronized (((UDPMessageProcessor) messageProcessor).messageQueue) {
    259                     while (((UDPMessageProcessor) messageProcessor).messageQueue
    260                             .isEmpty()) {
    261                         // Check to see if we need to exit.
    262                         if (!((UDPMessageProcessor) messageProcessor).isRunning)
    263                             return;
    264                         try {
    265                             // We're part of a thread pool. Ask the auditor to
    266                             // monitor this thread.
    267                             if (threadHandle == null) {
    268                                 threadHandle = sipStack.getThreadAuditor()
    269                                         .addCurrentThread();
    270                             }
    271 
    272                             // Send a heartbeat to the thread auditor
    273                             threadHandle.ping();
    274 
    275                             // Wait for packets
    276                             // Note: getPingInterval returns 0 (infinite) if the
    277                             // thread auditor is disabled.
    278                             ((UDPMessageProcessor) messageProcessor).messageQueue
    279                                     .wait(threadHandle
    280                                             .getPingIntervalInMillisecs());
    281                         } catch (InterruptedException ex) {
    282                             if (!((UDPMessageProcessor) messageProcessor).isRunning)
    283                                 return;
    284                         }
    285                     }
    286                     packet = (DatagramPacket) ((UDPMessageProcessor) messageProcessor).messageQueue
    287                             .removeFirst();
    288 
    289                 }
    290                 this.incomingPacket = packet;
    291             } else {
    292                 packet = this.incomingPacket;
    293             }
    294 
    295             // Process the packet. Catch and log any exception we may throw.
    296             try {
    297                 processIncomingDataPacket(packet);
    298             } catch (Exception e) {
    299 
    300                 sipStack.getStackLogger().logError(
    301                         "Error while processing incoming UDP packet", e);
    302             }
    303 
    304             if (sipStack.threadPoolSize == -1) {
    305                 return;
    306             }
    307         }
    308     }
    309 
    310     /**
    311      * Process an incoming datagram
    312      *
    313      * @param packet
    314      *            is the incoming datagram packet.
    315      */
    316     private void processIncomingDataPacket(DatagramPacket packet)
    317             throws Exception {
    318         this.peerAddress = packet.getAddress();
    319         int packetLength = packet.getLength();
    320         // Read bytes and put it in a eueue.
    321         byte[] bytes = packet.getData();
    322         byte[] msgBytes = new byte[packetLength];
    323         System.arraycopy(bytes, 0, msgBytes, 0, packetLength);
    324 
    325         // Do debug logging.
    326         if (sipStack.isLoggingEnabled()) {
    327             this.sipStack.getStackLogger()
    328                     .logDebug("UDPMessageChannel: processIncomingDataPacket : peerAddress = "
    329                             + peerAddress.getHostAddress() + "/"
    330                             + packet.getPort() + " Length = " + packetLength);
    331 
    332         }
    333 
    334         SIPMessage sipMessage = null;
    335         try {
    336             this.receptionTime = System.currentTimeMillis();
    337             sipMessage = myParser.parseSIPMessage(msgBytes);
    338             myParser = null;
    339         } catch (ParseException ex) {
    340             myParser = null; // let go of the parser reference.
    341             if (sipStack.isLoggingEnabled()) {
    342                 this.sipStack.getStackLogger().logDebug("Rejecting message !  "
    343                         + new String(msgBytes));
    344                 this.sipStack.getStackLogger().logDebug("error message "
    345                         + ex.getMessage());
    346                 this.sipStack.getStackLogger().logException(ex);
    347             }
    348 
    349 
    350             // JvB: send a 400 response for requests (except ACK)
    351             // Currently only UDP, @todo also other transports
    352             String msgString = new String(msgBytes, 0, packetLength);
    353             if (!msgString.startsWith("SIP/") && !msgString.startsWith("ACK ")) {
    354 
    355                 String badReqRes = createBadReqRes(msgString, ex);
    356                 if (badReqRes != null) {
    357                     if (sipStack.isLoggingEnabled()) {
    358                         sipStack.getStackLogger().logDebug(
    359                                 "Sending automatic 400 Bad Request:");
    360                         sipStack.getStackLogger().logDebug(badReqRes);
    361                     }
    362                     try {
    363                         this.sendMessage(badReqRes.getBytes(), peerAddress,
    364                                 packet.getPort(), "UDP", false);
    365                     } catch (IOException e) {
    366                         this.sipStack.getStackLogger().logException(e);
    367                     }
    368                 } else {
    369                     if (sipStack.isLoggingEnabled()) {
    370                         sipStack
    371                                 .getStackLogger()
    372                                 .logDebug(
    373                                         "Could not formulate automatic 400 Bad Request");
    374                     }
    375                 }
    376             }
    377 
    378             return;
    379         }
    380         // No parse exception but null message - reject it and
    381         // march on (or return).
    382         // exit this message processor if the message did not parse.
    383 
    384         if (sipMessage == null) {
    385             if (sipStack.isLoggingEnabled()) {
    386                 this.sipStack.getStackLogger().logDebug("Rejecting message !  + Null message parsed.");
    387             }
    388             if (pingBackRecord.get(packet.getAddress().getHostAddress() + ":" + packet.getPort()) == null ) {
    389                 byte[] retval = "\r\n\r\n".getBytes();
    390                 DatagramPacket keepalive = new DatagramPacket(retval,0,retval.length,packet.getAddress(),packet.getPort());
    391                 ((UDPMessageProcessor)this.messageProcessor).sock.send(keepalive);
    392                 this.sipStack.getTimer().schedule(new PingBackTimerTask(packet.getAddress().getHostAddress(),
    393                             packet.getPort()), 1000);
    394             }
    395             return;
    396         }
    397         ViaList viaList = sipMessage.getViaHeaders();
    398         // Check for the required headers.
    399         if (sipMessage.getFrom() == null || sipMessage.getTo() == null
    400                 || sipMessage.getCallId() == null
    401                 || sipMessage.getCSeq() == null
    402                 || sipMessage.getViaHeaders() == null) {
    403             String badmsg = new String(msgBytes);
    404             if (sipStack.isLoggingEnabled()) {
    405                 this.sipStack.getStackLogger().logError("bad message " + badmsg);
    406                 this.sipStack.getStackLogger().logError(">>> Dropped Bad Msg "
    407                         + "From = " + sipMessage.getFrom() + "To = "
    408                         + sipMessage.getTo() + "CallId = "
    409                         + sipMessage.getCallId() + "CSeq = "
    410                         + sipMessage.getCSeq() + "Via = "
    411                         + sipMessage.getViaHeaders());
    412             }
    413             return;
    414         }
    415         // For a request first via header tells where the message
    416         // is coming from.
    417         // For response, just get the port from the packet.
    418         if (sipMessage instanceof SIPRequest) {
    419             Via v = (Via) viaList.getFirst();
    420             Hop hop = sipStack.addressResolver.resolveAddress(v.getHop());
    421             this.peerPort = hop.getPort();
    422             this.peerProtocol = v.getTransport();
    423 
    424             this.peerPacketSourceAddress = packet.getAddress();
    425             this.peerPacketSourcePort = packet.getPort();
    426             try {
    427                 this.peerAddress = packet.getAddress();
    428                 // Check to see if the received parameter matches
    429                 // the peer address and tag it appropriately.
    430 
    431 
    432                 boolean hasRPort = v.hasParameter(Via.RPORT);
    433                 if (hasRPort
    434                         || !hop.getHost().equals(
    435                                 this.peerAddress.getHostAddress())) {
    436                     v.setParameter(Via.RECEIVED, this.peerAddress
    437                             .getHostAddress());
    438                 }
    439 
    440                 if (hasRPort) {
    441                     v.setParameter(Via.RPORT, Integer
    442                             .toString(this.peerPacketSourcePort));
    443                 }
    444             } catch (java.text.ParseException ex1) {
    445                 InternalErrorHandler.handleException(ex1);
    446             }
    447 
    448         } else {
    449 
    450             this.peerPacketSourceAddress = packet.getAddress();
    451             this.peerPacketSourcePort = packet.getPort();
    452             this.peerAddress = packet.getAddress();
    453             this.peerPort = packet.getPort();
    454             this.peerProtocol = ((Via) viaList.getFirst()).getTransport();
    455         }
    456 
    457         this.processMessage(sipMessage);
    458 
    459     }
    460 
    461     /**
    462      * Actually proces the parsed message.
    463      *
    464      * @param sipMessage
    465      */
    466     public void processMessage(SIPMessage sipMessage) {
    467 
    468         if (sipMessage instanceof SIPRequest) {
    469             SIPRequest sipRequest = (SIPRequest) sipMessage;
    470 
    471             // This is a request - process it.
    472             // So far so good -- we will commit this message if
    473             // all processing is OK.
    474             if (sipStack.getStackLogger().isLoggingEnabled(ServerLogger.TRACE_MESSAGES)) {
    475 
    476                 this.sipStack.serverLogger.logMessage(sipMessage, this
    477                         .getPeerHostPort().toString(), this.getHost() + ":"
    478                         + this.myPort, false, receptionTime);
    479 
    480             }
    481             ServerRequestInterface sipServerRequest = sipStack
    482                     .newSIPServerRequest(sipRequest, this);
    483             // Drop it if there is no request returned
    484             if (sipServerRequest == null) {
    485                 if (sipStack.isLoggingEnabled()) {
    486                     this.sipStack.getStackLogger()
    487                             .logWarning("Null request interface returned -- dropping request");
    488                 }
    489 
    490 
    491                 return;
    492             }
    493             if (sipStack.isLoggingEnabled())
    494                 this.sipStack.getStackLogger().logDebug("About to process "
    495                         + sipRequest.getFirstLine() + "/" + sipServerRequest);
    496             try {
    497                 sipServerRequest.processRequest(sipRequest, this);
    498             } finally {
    499                 if (sipServerRequest instanceof SIPTransaction) {
    500                     SIPServerTransaction sipServerTx = (SIPServerTransaction) sipServerRequest;
    501                     if (!sipServerTx.passToListener()) {
    502                         ((SIPTransaction) sipServerRequest).releaseSem();
    503                     }
    504                 }
    505             }
    506             if (sipStack.isLoggingEnabled())
    507                 this.sipStack.getStackLogger().logDebug("Done processing "
    508                         + sipRequest.getFirstLine() + "/" + sipServerRequest);
    509 
    510             // So far so good -- we will commit this message if
    511             // all processing is OK.
    512 
    513         } else {
    514             // Handle a SIP Reply message.
    515             SIPResponse sipResponse = (SIPResponse) sipMessage;
    516             try {
    517                 sipResponse.checkHeaders();
    518             } catch (ParseException ex) {
    519                 if (sipStack.isLoggingEnabled())
    520                     sipStack.getStackLogger()
    521                             .logError("Dropping Badly formatted response message >>> "
    522                                     + sipResponse);
    523                 return;
    524             }
    525             ServerResponseInterface sipServerResponse = sipStack
    526                     .newSIPServerResponse(sipResponse, this);
    527             if (sipServerResponse != null) {
    528                 try {
    529                     if (sipServerResponse instanceof SIPClientTransaction
    530                             && !((SIPClientTransaction) sipServerResponse)
    531                                     .checkFromTag(sipResponse)) {
    532                         if (sipStack.isLoggingEnabled())
    533                             sipStack.getStackLogger()
    534                                     .logError("Dropping response message with invalid tag >>> "
    535                                             + sipResponse);
    536                         return;
    537                     }
    538 
    539                     sipServerResponse.processResponse(sipResponse, this);
    540                 } finally {
    541                     if (sipServerResponse instanceof SIPTransaction
    542                             && !((SIPTransaction) sipServerResponse)
    543                                     .passToListener())
    544                         ((SIPTransaction) sipServerResponse).releaseSem();
    545                 }
    546 
    547                 // Normal processing of message.
    548             } else {
    549                 if (sipStack.isLoggingEnabled()) {
    550                     this.sipStack.getStackLogger().logDebug("null sipServerResponse!");
    551                 }
    552             }
    553 
    554         }
    555     }
    556 
    557     /**
    558      * JvB: added method to check for known buggy clients (Windows Messenger) to
    559      * fix the port to which responses are sent
    560      *
    561      * checks for User-Agent: RTC/1.3.5470 (Messenger 5.1.0701)
    562      *
    563      * JvB 22/7/2006 better to take this out for the moment, it is only a
    564      * problem in rare cases (unregister)
    565      *
    566      * private final boolean isBuggyClient( SIPRequest r ) { UserAgent uah =
    567      * (UserAgent) r.getHeader( UserAgent.NAME ); if (uah!=null) {
    568      * java.util.ListIterator i = uah.getProduct(); if (i.hasNext()) { String p =
    569      * (String) uah.getProduct().next(); return p.startsWith( "RTC" ); } }
    570      * return false; }
    571      */
    572 
    573     /**
    574      * Implementation of the ParseExceptionListener interface.
    575      *
    576      * @param ex
    577      *            Exception that is given to us by the parser.
    578      * @throws ParseException
    579      *             If we choose to reject the header or message.
    580      */
    581     public void handleException(ParseException ex, SIPMessage sipMessage,
    582             Class hdrClass, String header, String message)
    583             throws ParseException {
    584         if (sipStack.isLoggingEnabled())
    585             this.sipStack.getStackLogger().logException(ex);
    586         // Log the bad message for later reference.
    587         if ((hdrClass != null)
    588                 && (hdrClass.equals(From.class) || hdrClass.equals(To.class)
    589                         || hdrClass.equals(CSeq.class)
    590                         || hdrClass.equals(Via.class)
    591                         || hdrClass.equals(CallID.class)
    592                         || hdrClass.equals(RequestLine.class) || hdrClass
    593                         .equals(StatusLine.class))) {
    594         	if (sipStack.isLoggingEnabled()) {
    595         		sipStack.getStackLogger().logError("BAD MESSAGE!");
    596             	sipStack.getStackLogger().logError(message);
    597         	}
    598             throw ex;
    599         } else {
    600             sipMessage.addUnparsed(header);
    601         }
    602     }
    603 
    604     /**
    605      * Return a reply from a pre-constructed reply. This sends the message back
    606      * to the entity who caused us to create this channel in the first place.
    607      *
    608      * @param sipMessage
    609      *            Message string to send.
    610      * @throws IOException
    611      *             If there is a problem with sending the message.
    612      */
    613     public void sendMessage(SIPMessage sipMessage) throws IOException {
    614         if (sipStack.isLoggingEnabled() && this.sipStack.isLogStackTraceOnMessageSend()) {
    615             if ( sipMessage instanceof SIPRequest &&
    616                     ((SIPRequest)sipMessage).getRequestLine() != null) {
    617                 /*
    618                  * We dont want to log empty trace messages.
    619                  */
    620                 this.sipStack.getStackLogger().logStackTrace(StackLogger.TRACE_INFO);
    621             } else {
    622                 this.sipStack.getStackLogger().logStackTrace(StackLogger.TRACE_INFO);
    623             }
    624         }
    625 
    626         // Test and see where we are going to send the messsage. If the message
    627         // is sent back to oursleves, just
    628         // shortcircuit processing.
    629         long time = System.currentTimeMillis();
    630         try {
    631             for (MessageProcessor messageProcessor : sipStack
    632                     .getMessageProcessors()) {
    633                 if (messageProcessor.getIpAddress().equals(this.peerAddress)
    634                         && messageProcessor.getPort() == this.peerPort
    635                         && messageProcessor.getTransport().equals(
    636                                 this.peerProtocol)) {
    637                     MessageChannel messageChannel = messageProcessor
    638                             .createMessageChannel(this.peerAddress,
    639                                     this.peerPort);
    640                     if (messageChannel instanceof RawMessageChannel) {
    641                         ((RawMessageChannel) messageChannel)
    642                                 .processMessage(sipMessage);
    643                         if (sipStack.isLoggingEnabled())
    644                         	sipStack.getStackLogger().logDebug("Self routing message");
    645                         return;
    646                     }
    647 
    648                 }
    649             }
    650 
    651             byte[] msg = sipMessage.encodeAsBytes( this.getTransport() );
    652 
    653             sendMessage(msg, peerAddress, peerPort, peerProtocol,
    654                     sipMessage instanceof SIPRequest);
    655 
    656         } catch (IOException ex) {
    657             throw ex;
    658         } catch (Exception ex) {
    659             sipStack.getStackLogger().logError("An exception occured while sending message",ex);
    660             throw new IOException(
    661                     "An exception occured while sending message");
    662         } finally {
    663             if (sipStack.getStackLogger().isLoggingEnabled(ServerLogger.TRACE_MESSAGES) && !sipMessage.isNullRequest())
    664                 logMessage(sipMessage, peerAddress, peerPort, time);
    665             else if (sipStack.getStackLogger().isLoggingEnabled(ServerLogger.TRACE_DEBUG))
    666                 sipStack.getStackLogger().logDebug("Sent EMPTY Message");
    667         }
    668     }
    669 
    670     /**
    671      * Send a message to a specified receiver address.
    672      *
    673      * @param msg
    674      *            string to send.
    675      * @param peerAddress
    676      *            Address of the place to send it to.
    677      * @param peerPort
    678      *            the port to send it to.
    679      * @throws IOException
    680      *             If there is trouble sending this message.
    681      */
    682     protected void sendMessage(byte[] msg, InetAddress peerAddress,
    683             int peerPort, boolean reConnect) throws IOException {
    684         // Via is not included in the request so silently drop the reply.
    685         if (sipStack.isLoggingEnabled() && this.sipStack.isLogStackTraceOnMessageSend() ) {
    686             this.sipStack.getStackLogger().logStackTrace(StackLogger.TRACE_INFO);
    687         }
    688         if (peerPort == -1) {
    689             if (sipStack.isLoggingEnabled()) {
    690                 this.sipStack.getStackLogger().logDebug(getClass().getName()
    691                         + ":sendMessage: Dropping reply!");
    692             }
    693             throw new IOException("Receiver port not set ");
    694         } else {
    695             if (sipStack.isLoggingEnabled()) {
    696                 this.sipStack.getStackLogger().logDebug("sendMessage " + peerAddress.getHostAddress() + "/"
    697                         + peerPort + "\n" + "messageSize =  "  + msg.length + " message = " + new String(msg)) ;
    698                 this.sipStack.getStackLogger().logDebug("*******************\n");
    699             }
    700 
    701         }
    702         DatagramPacket reply = new DatagramPacket(msg, msg.length, peerAddress,
    703                 peerPort);
    704         try {
    705             DatagramSocket sock;
    706             boolean created = false;
    707 
    708             if (sipStack.udpFlag) {
    709                 // Use the socket from the message processor (for firewall
    710                 // support use the same socket as the message processor
    711                 // socket -- feature request # 18 from java.net). This also
    712                 // makes the whole thing run faster!
    713                 sock = ((UDPMessageProcessor) messageProcessor).sock;
    714 
    715                 // Bind the socket to the stack address in case there
    716                 // are multiple interfaces on the machine (feature reqeust
    717                 // by Will Scullin) 0 binds to an ephemeral port.
    718                 // sock = new DatagramSocket(0,sipStack.stackInetAddress);
    719             } else {
    720                 // bind to any interface and port.
    721                 sock = new DatagramSocket();
    722                 created = true;
    723             }
    724             sock.send(reply);
    725             if (created)
    726                 sock.close();
    727         } catch (IOException ex) {
    728             throw ex;
    729         } catch (Exception ex) {
    730             InternalErrorHandler.handleException(ex);
    731         }
    732     }
    733 
    734     /**
    735      * Send a message to a specified receiver address.
    736      *
    737      * @param msg
    738      *            message string to send.
    739      * @param peerAddress
    740      *            Address of the place to send it to.
    741      * @param peerPort
    742      *            the port to send it to.
    743      * @param peerProtocol
    744      *            protocol to use to send.
    745      * @throws IOException
    746      *             If there is trouble sending this message.
    747      */
    748     protected void sendMessage(byte[] msg, InetAddress peerAddress,
    749             int peerPort, String peerProtocol, boolean retry)
    750             throws IOException {
    751         // Via is not included in the request so silently drop the reply.
    752         if (peerPort == -1) {
    753             if (sipStack.isLoggingEnabled()) {
    754                 this.sipStack.getStackLogger().logDebug(getClass().getName()
    755                         + ":sendMessage: Dropping reply!");
    756             }
    757             throw new IOException("Receiver port not set ");
    758         } else {
    759             if (sipStack.isLoggingEnabled()) {
    760                 this.sipStack.getStackLogger().logDebug( ":sendMessage " + peerAddress.getHostAddress() + "/"
    761                         + peerPort + "\n" + " messageSize = " + msg.length);
    762             }
    763         }
    764         if (peerProtocol.compareToIgnoreCase("UDP") == 0) {
    765             DatagramPacket reply = new DatagramPacket(msg, msg.length,
    766                     peerAddress, peerPort);
    767 
    768             try {
    769                 DatagramSocket sock;
    770                 if (sipStack.udpFlag) {
    771                     sock = ((UDPMessageProcessor) messageProcessor).sock;
    772 
    773                 } else {
    774                     // bind to any interface and port.
    775                     sock = sipStack.getNetworkLayer().createDatagramSocket();
    776                 }
    777                 if (sipStack.isLoggingEnabled()) {
    778                     this.sipStack.getStackLogger().logDebug("sendMessage "
    779                             + peerAddress.getHostAddress() + "/" + peerPort
    780                             + "\n" + new String(msg));
    781                 }
    782                 sock.send(reply);
    783                 if (!sipStack.udpFlag)
    784                     sock.close();
    785             } catch (IOException ex) {
    786                 throw ex;
    787             } catch (Exception ex) {
    788                 InternalErrorHandler.handleException(ex);
    789             }
    790 
    791         } else {
    792             // Use TCP to talk back to the sender.
    793             Socket outputSocket = sipStack.ioHandler.sendBytes(
    794                     this.messageProcessor.getIpAddress(), peerAddress,
    795                     peerPort, "tcp", msg, retry,this);
    796             OutputStream myOutputStream = outputSocket.getOutputStream();
    797             myOutputStream.write(msg, 0, msg.length);
    798             myOutputStream.flush();
    799             // The socket is cached (dont close it!);
    800         }
    801     }
    802 
    803     /**
    804      * get the stack pointer.
    805      *
    806      * @return The sip stack for this channel.
    807      */
    808     public SIPTransactionStack getSIPStack() {
    809         return sipStack;
    810     }
    811 
    812     /**
    813      * Return a transport string.
    814      *
    815      * @return the string "udp" in this case.
    816      */
    817     public String getTransport() {
    818         return SIPConstants.UDP;
    819     }
    820 
    821     /**
    822      * get the stack address for the stack that received this message.
    823      *
    824      * @return The stack address for our sipStack.
    825      */
    826     public String getHost() {
    827         return messageProcessor.getIpAddress().getHostAddress();
    828     }
    829 
    830     /**
    831      * get the port.
    832      *
    833      * @return Our port (on which we are getting datagram packets).
    834      */
    835     public int getPort() {
    836         return ((UDPMessageProcessor) messageProcessor).getPort();
    837     }
    838 
    839     /**
    840      * get the name (address) of the host that sent me the message
    841      *
    842      * @return The name of the sender (from the datagram packet).
    843      */
    844     public String getPeerName() {
    845         return peerAddress.getHostName();
    846     }
    847 
    848     /**
    849      * get the address of the host that sent me the message
    850      *
    851      * @return The senders ip address.
    852      */
    853     public String getPeerAddress() {
    854         return peerAddress.getHostAddress();
    855     }
    856 
    857     protected InetAddress getPeerInetAddress() {
    858         return peerAddress;
    859     }
    860 
    861     /**
    862      * Compare two UDP Message channels for equality.
    863      *
    864      * @param other
    865      *            The other message channel with which to compare oursleves.
    866      */
    867     public boolean equals(Object other) {
    868 
    869         if (other == null)
    870             return false;
    871         boolean retval;
    872         if (!this.getClass().equals(other.getClass())) {
    873             retval = false;
    874         } else {
    875             UDPMessageChannel that = (UDPMessageChannel) other;
    876             retval = this.getKey().equals(that.getKey());
    877         }
    878 
    879         return retval;
    880     }
    881 
    882     public String getKey() {
    883         return getKey(peerAddress, peerPort, "UDP");
    884     }
    885 
    886     public int getPeerPacketSourcePort() {
    887         return peerPacketSourcePort;
    888     }
    889 
    890     public InetAddress getPeerPacketSourceAddress() {
    891         return peerPacketSourceAddress;
    892     }
    893 
    894     /**
    895      * Get the logical originator of the message (from the top via header).
    896      *
    897      * @return topmost via header sentby field
    898      */
    899     public String getViaHost() {
    900         return this.myAddress;
    901     }
    902 
    903     /**
    904      * Get the logical port of the message orginator (from the top via hdr).
    905      *
    906      * @return the via port from the topmost via header.
    907      */
    908     public int getViaPort() {
    909         return this.myPort;
    910     }
    911 
    912     /**
    913      * Returns "false" as this is an unreliable transport.
    914      */
    915     public boolean isReliable() {
    916         return false;
    917     }
    918 
    919     /**
    920      * UDP is not a secure protocol.
    921      */
    922     public boolean isSecure() {
    923         return false;
    924     }
    925 
    926     public int getPeerPort() {
    927         return peerPort;
    928     }
    929 
    930     public String getPeerProtocol() {
    931         return this.peerProtocol;
    932     }
    933 
    934     /**
    935      * Close the message channel.
    936      */
    937     public void close() {
    938     }
    939 
    940 
    941 }
    942