1600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/* 2600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Conditions Of Use 3600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 4600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * This software was developed by employees of the National Institute of 5600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Standards and Technology (NIST), an agency of the Federal Government. 6600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Pursuant to title 15 Untied States Code Section 105, works of NIST 7600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * employees are not subject to copyright protection in the United States 8600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * and are considered to be in the public domain. As a result, a formal 9600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * license is not needed to use the software. 10600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 11600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * This software is provided by NIST as a service and is expressly 12600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED 13600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF 14600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT 15600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * AND DATA ACCURACY. NIST does not warrant or make any representations 16600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * regarding the use of the software or the results thereof, including but 17600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * not limited to the correctness, accuracy, reliability or usefulness of 18600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * the software. 19600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 20600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Permission to use this software is contingent upon your acceptance 21600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * of the terms of this agreement 22600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 23600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * . 24600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 25600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 26600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/***************************************************************************** 27600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Product of NIST/ITL Advanced Networking Technologies Division (ANTD). * 28600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *****************************************************************************/ 29600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 30600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangpackage gov.nist.javax.sip.stack; 31600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 32600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.core.InternalErrorHandler; 33600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.core.ServerLogger; 34600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.core.StackLogger; 35600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.core.ThreadAuditor; 36600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.SIPConstants; 37600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.CSeq; 38600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.CallID; 39600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.From; 40600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.RequestLine; 41600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.StatusLine; 42600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.To; 43600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.Via; 44600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.ViaList; 45600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.message.SIPMessage; 46600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.message.SIPRequest; 47600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.message.SIPResponse; 48600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.parser.ParseExceptionListener; 49600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.parser.StringMsgParser; 50600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 51600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.io.IOException; 52600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.io.OutputStream; 53600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.net.DatagramPacket; 54600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.net.DatagramSocket; 55600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.net.InetAddress; 56600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.net.Socket; 57600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.text.ParseException; 58600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.HashSet; 59600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.Hashtable; 60600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.TimerTask; 61600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 62600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.address.Hop; 63600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 64600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/* 65600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Kim Kirby (Keyvoice) suggested that duplicate checking should be added to the 66600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * stack (later removed). Lamine Brahimi suggested a single threaded behavior 67600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * flag be added to this. Niklas Uhrberg suggested that thread pooling support 68600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * be added to this for performance and resource management. Peter Parnes found 69600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * a bug with this code that was sending it into an infinite loop when a bad 70600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * incoming message was parsed. Bug fix by viswashanti.kadiyala@antepo.com. 71600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Hagai Sela addded fixes for NAT traversal. Jeroen van Bemmel fixed up for 72600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * buggy clients (such as windows messenger) and added code to return 73600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * BAD_REQUEST. David Alique fixed an address recording bug. Jeroen van Bemmel 74600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * fixed a performance issue where the stack was doing DNS lookups (potentially 75600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * unnecessary). Ricardo Bora (Natural Convergence ) added code that prevents 76600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * the stack from exitting when an exception is encountered. 77600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 78600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 79600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 80600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/** 81600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * This is the UDP Message handler that gets created when a UDP message needs to 82600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * be processed. The message is processed by creating a String Message parser 83600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * and invoking it on the message read from the UDP socket. The parsed structure 84600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * is handed off via a SIP stack request for further processing. This stack 85600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * structure isolates the message handling logic from the mechanics of sending 86600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * and recieving messages (which could be either udp or tcp. 87600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 88600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 89600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @author M. Ranganathan <br/> 90600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 91600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 92600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 93600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @version 1.2 $Revision: 1.66 $ $Date: 2010/01/14 05:15:49 $ 94600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 95600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangpublic class UDPMessageChannel extends MessageChannel implements 96600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ParseExceptionListener, Runnable, RawMessageChannel { 97600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 98600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 99600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 100600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * SIP Stack structure for this channel. 101600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 102600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected SIPTransactionStack sipStack; 103600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 104600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 105600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * The parser we are using for messages received from this channel. 106600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 107600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected StringMsgParser myParser; 108600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 109600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 110600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Where we got the stuff from 111600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 112600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private InetAddress peerAddress; 113600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 114600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private String myAddress; 115600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 116600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private int peerPacketSourcePort; 117600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 118600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private InetAddress peerPacketSourceAddress; 119600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 120600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 121600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Reciever port -- port of the destination. 122600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 123600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private int peerPort; 124600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 125600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 126600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Protocol to use when talking to receiver (i.e. when sending replies). 127600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 128600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private String peerProtocol; 129600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 130600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected int myPort; 131600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 132600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private DatagramPacket incomingPacket; 133600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 134600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private long receptionTime; 135600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 136600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 137600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * A table that keeps track of when the last pingback was sent to a given remote IP address 138600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * and port. This is for NAT compensation. This stays in the table for 1 seconds and prevents 139600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * infinite loop. If a second pingback happens in that period of time, it will be dropped. 140600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 141600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private Hashtable<String,PingBackTimerTask> pingBackRecord = new Hashtable<String,PingBackTimerTask>(); 142600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 143600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang class PingBackTimerTask extends TimerTask { 144600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String ipAddress; 145600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int port; 146600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 147600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public PingBackTimerTask(String ipAddress, int port) { 148600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.ipAddress = ipAddress; 149600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.port = port; 150600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang pingBackRecord.put(ipAddress + ":" + port, this); 151600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 152600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang @Override 153600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void run() { 154600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang pingBackRecord.remove(ipAddress + ":" + port); 155600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 156600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang @Override 157600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public int hashCode() { 158600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return (ipAddress + ":" + port).hashCode(); 159600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 160600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 161600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 162600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 163600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Constructor - takes a datagram packet and a stack structure Extracts the 164600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * address of the other from the datagram packet and stashes away the 165600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * pointer to the passed stack structure. 166600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 167600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param stack 168600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * is the shared SIPStack structure 169600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param messageProcessor 170600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * is the creating message processor. 171600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 172600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected UDPMessageChannel(SIPTransactionStack stack, 173600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang UDPMessageProcessor messageProcessor) { 174600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang super.messageProcessor = messageProcessor; 175600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack = stack; 176600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 177600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Thread mythread = new Thread(this); 178600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 179600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.myAddress = messageProcessor.getIpAddress().getHostAddress(); 180600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.myPort = messageProcessor.getPort(); 181600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 182600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang mythread.setName("UDPMessageChannelThread"); 183600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang mythread.setDaemon(true); 184600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang mythread.start(); 185600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 186600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 187600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 188600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 189600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Constructor. We create one of these in order to process an incoming 190600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * message. 191600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 192600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param stack 193600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * is the SIP sipStack. 194600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param messageProcessor 195600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * is the creating message processor. 196600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param packet 197600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * is the incoming datagram packet. 198600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 199600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected UDPMessageChannel(SIPTransactionStack stack, 200600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang UDPMessageProcessor messageProcessor, DatagramPacket packet) { 201600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 202600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.incomingPacket = packet; 203600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang super.messageProcessor = messageProcessor; 204600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack = stack; 205600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 206600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.myAddress = messageProcessor.getIpAddress().getHostAddress(); 207600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.myPort = messageProcessor.getPort(); 208600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Thread mythread = new Thread(this); 209600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang mythread.setDaemon(true); 21005ea84203978f79842df1d0d17ebaf30073ef1b1Chung-yih Wang mythread.setName("UDPMessageChannelThread"); 211600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 212600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang mythread.start(); 213600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 214600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 215600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 216600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 217600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Constructor. We create one of these when we send out a message. 218600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 219600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param targetAddr 220600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * INET address of the place where we want to send messages. 221600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param port 222600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * target port (where we want to send the message). 223600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param sipStack 224600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * our SIP Stack. 225600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 226600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected UDPMessageChannel(InetAddress targetAddr, int port, 227600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPTransactionStack sipStack, UDPMessageProcessor messageProcessor) { 228600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang peerAddress = targetAddr; 229600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang peerPort = port; 230600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang peerProtocol = "UDP"; 231600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang super.messageProcessor = messageProcessor; 232600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.myAddress = messageProcessor.getIpAddress().getHostAddress(); 233600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.myPort = messageProcessor.getPort(); 234600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack = sipStack; 235600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 236600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack.getStackLogger().logDebug("Creating message channel " 237600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + targetAddr.getHostAddress() + "/" + port); 238600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 239600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 240600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 241600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 242600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Run method specified by runnnable. 243600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 244600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void run() { 245600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Assume no thread pooling (bug fix by spierhj) 246600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ThreadAuditor.ThreadHandle threadHandle = null; 247600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 248600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (true) { 249600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Create a new string message parser to parse the list of messages. 250600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (myParser == null) { 251600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang myParser = new StringMsgParser(); 252600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang myParser.setParseExceptionListener(this); 253600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 254600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // messages that we write out to him. 255600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang DatagramPacket packet; 256600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 257600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.threadPoolSize != -1) { 258600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang synchronized (((UDPMessageProcessor) messageProcessor).messageQueue) { 259600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (((UDPMessageProcessor) messageProcessor).messageQueue 260600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .isEmpty()) { 261600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Check to see if we need to exit. 262600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!((UDPMessageProcessor) messageProcessor).isRunning) 263600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 264600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 265600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // We're part of a thread pool. Ask the auditor to 266600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // monitor this thread. 267600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (threadHandle == null) { 268600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang threadHandle = sipStack.getThreadAuditor() 269600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .addCurrentThread(); 270600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 271600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 272600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Send a heartbeat to the thread auditor 273600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang threadHandle.ping(); 274600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 275600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Wait for packets 276600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Note: getPingInterval returns 0 (infinite) if the 277600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // thread auditor is disabled. 278600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ((UDPMessageProcessor) messageProcessor).messageQueue 279600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .wait(threadHandle 280600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getPingIntervalInMillisecs()); 281600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (InterruptedException ex) { 282600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!((UDPMessageProcessor) messageProcessor).isRunning) 283600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 284600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 285600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 286600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang packet = (DatagramPacket) ((UDPMessageProcessor) messageProcessor).messageQueue 287600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .removeFirst(); 288600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 289600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 290600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.incomingPacket = packet; 291600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 292600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang packet = this.incomingPacket; 293600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 294600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 295600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Process the packet. Catch and log any exception we may throw. 296600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 297600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang processIncomingDataPacket(packet); 298600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (Exception e) { 299600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 300600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logError( 301600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Error while processing incoming UDP packet", e); 302600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 303600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 304600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.threadPoolSize == -1) { 305600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 306600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 307600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 308600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 309600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 310600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 311600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Process an incoming datagram 312600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 313600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param packet 314600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * is the incoming datagram packet. 315600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 316600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private void processIncomingDataPacket(DatagramPacket packet) 317600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throws Exception { 318600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.peerAddress = packet.getAddress(); 319600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int packetLength = packet.getLength(); 320600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Read bytes and put it in a eueue. 321600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang byte[] bytes = packet.getData(); 322600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang byte[] msgBytes = new byte[packetLength]; 323600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang System.arraycopy(bytes, 0, msgBytes, 0, packetLength); 324600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 325600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Do debug logging. 326600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 327600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack.getStackLogger() 328600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .logDebug("UDPMessageChannel: processIncomingDataPacket : peerAddress = " 329600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + peerAddress.getHostAddress() + "/" 330600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + packet.getPort() + " Length = " + packetLength); 331600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 332600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 333600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 334600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPMessage sipMessage = null; 335600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 336600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.receptionTime = System.currentTimeMillis(); 337600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipMessage = myParser.parseSIPMessage(msgBytes); 338600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang myParser = null; 339600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (ParseException ex) { 340600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang myParser = null; // let go of the parser reference. 341600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 342600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack.getStackLogger().logDebug("Rejecting message ! " 343600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + new String(msgBytes)); 344600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack.getStackLogger().logDebug("error message " 345600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + ex.getMessage()); 346600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack.getStackLogger().logException(ex); 347600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 348600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 349600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 350600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // JvB: send a 400 response for requests (except ACK) 351600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Currently only UDP, @todo also other transports 352600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String msgString = new String(msgBytes, 0, packetLength); 353600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!msgString.startsWith("SIP/") && !msgString.startsWith("ACK ")) { 354600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 355600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String badReqRes = createBadReqRes(msgString, ex); 356600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (badReqRes != null) { 357600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 358600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 359600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Sending automatic 400 Bad Request:"); 360600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug(badReqRes); 361600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 362600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 363600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sendMessage(badReqRes.getBytes(), peerAddress, 364600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang packet.getPort(), "UDP", false); 365600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (IOException e) { 366600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack.getStackLogger().logException(e); 367600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 368600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 369600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 370600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack 371600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getStackLogger() 372600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .logDebug( 373600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Could not formulate automatic 400 Bad Request"); 374600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 375600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 376600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 377600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 378600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 379600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 380600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // No parse exception but null message - reject it and 381600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // march on (or return). 382600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // exit this message processor if the message did not parse. 383600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 384600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipMessage == null) { 385600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 386600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack.getStackLogger().logDebug("Rejecting message ! + Null message parsed."); 387600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 388600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (pingBackRecord.get(packet.getAddress().getHostAddress() + ":" + packet.getPort()) == null ) { 389600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang byte[] retval = "\r\n\r\n".getBytes(); 390600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang DatagramPacket keepalive = new DatagramPacket(retval,0,retval.length,packet.getAddress(),packet.getPort()); 391600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ((UDPMessageProcessor)this.messageProcessor).sock.send(keepalive); 392600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack.getTimer().schedule(new PingBackTimerTask(packet.getAddress().getHostAddress(), 393600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang packet.getPort()), 1000); 394600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 395600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 396600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 397600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ViaList viaList = sipMessage.getViaHeaders(); 398600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Check for the required headers. 399600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipMessage.getFrom() == null || sipMessage.getTo() == null 400600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || sipMessage.getCallId() == null 401600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || sipMessage.getCSeq() == null 402600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || sipMessage.getViaHeaders() == null) { 403600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String badmsg = new String(msgBytes); 404600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 405600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack.getStackLogger().logError("bad message " + badmsg); 406600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack.getStackLogger().logError(">>> Dropped Bad Msg " 407600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "From = " + sipMessage.getFrom() + "To = " 408600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + sipMessage.getTo() + "CallId = " 409600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + sipMessage.getCallId() + "CSeq = " 410600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + sipMessage.getCSeq() + "Via = " 411600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + sipMessage.getViaHeaders()); 412600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 413600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 414600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 415600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // For a request first via header tells where the message 416600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // is coming from. 417600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // For response, just get the port from the packet. 418600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipMessage instanceof SIPRequest) { 419600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Via v = (Via) viaList.getFirst(); 420600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Hop hop = sipStack.addressResolver.resolveAddress(v.getHop()); 421600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.peerPort = hop.getPort(); 422600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.peerProtocol = v.getTransport(); 423600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 424600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.peerPacketSourceAddress = packet.getAddress(); 425600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.peerPacketSourcePort = packet.getPort(); 426600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 427600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.peerAddress = packet.getAddress(); 428600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Check to see if the received parameter matches 429600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // the peer address and tag it appropriately. 430600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 431600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 432600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang boolean hasRPort = v.hasParameter(Via.RPORT); 433600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (hasRPort 434600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || !hop.getHost().equals( 435600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.peerAddress.getHostAddress())) { 436600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang v.setParameter(Via.RECEIVED, this.peerAddress 437600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getHostAddress()); 438600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 439600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 440600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (hasRPort) { 441600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang v.setParameter(Via.RPORT, Integer 442600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .toString(this.peerPacketSourcePort)); 443600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 444600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (java.text.ParseException ex1) { 445600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang InternalErrorHandler.handleException(ex1); 446600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 447600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 448600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 449600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 450600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.peerPacketSourceAddress = packet.getAddress(); 451600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.peerPacketSourcePort = packet.getPort(); 452600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.peerAddress = packet.getAddress(); 453600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.peerPort = packet.getPort(); 454600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.peerProtocol = ((Via) viaList.getFirst()).getTransport(); 455600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 456600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 457600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.processMessage(sipMessage); 458600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 459600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 460600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 461600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 462600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Actually proces the parsed message. 463600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 464600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param sipMessage 465600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 466600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void processMessage(SIPMessage sipMessage) { 467600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 468600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipMessage instanceof SIPRequest) { 469600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPRequest sipRequest = (SIPRequest) sipMessage; 470600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 471600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // This is a request - process it. 472600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // So far so good -- we will commit this message if 473600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // all processing is OK. 474600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.getStackLogger().isLoggingEnabled(ServerLogger.TRACE_MESSAGES)) { 475600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 476600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack.serverLogger.logMessage(sipMessage, this 477600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getPeerHostPort().toString(), this.getHost() + ":" 478600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + this.myPort, false, receptionTime); 479600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 480600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 481600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ServerRequestInterface sipServerRequest = sipStack 482600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .newSIPServerRequest(sipRequest, this); 483600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Drop it if there is no request returned 484600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipServerRequest == null) { 485600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 486600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack.getStackLogger() 487600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .logWarning("Null request interface returned -- dropping request"); 488600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 489600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 490600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 491600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 492600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 493600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 494600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack.getStackLogger().logDebug("About to process " 495600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + sipRequest.getFirstLine() + "/" + sipServerRequest); 496600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 497600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipServerRequest.processRequest(sipRequest, this); 498600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } finally { 499600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipServerRequest instanceof SIPTransaction) { 500600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPServerTransaction sipServerTx = (SIPServerTransaction) sipServerRequest; 501600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!sipServerTx.passToListener()) { 502600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ((SIPTransaction) sipServerRequest).releaseSem(); 503600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 504600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 505600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 506600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 507600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack.getStackLogger().logDebug("Done processing " 508600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + sipRequest.getFirstLine() + "/" + sipServerRequest); 509600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 510600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // So far so good -- we will commit this message if 511600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // all processing is OK. 512600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 513600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 514600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Handle a SIP Reply message. 515600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPResponse sipResponse = (SIPResponse) sipMessage; 516600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 517600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipResponse.checkHeaders(); 518600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (ParseException ex) { 519600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 520600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger() 521600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .logError("Dropping Badly formatted response message >>> " 522600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + sipResponse); 523600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 524600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 525600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ServerResponseInterface sipServerResponse = sipStack 526600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .newSIPServerResponse(sipResponse, this); 527600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipServerResponse != null) { 528600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 529600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipServerResponse instanceof SIPClientTransaction 530600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && !((SIPClientTransaction) sipServerResponse) 531600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .checkFromTag(sipResponse)) { 532600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 533600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger() 534600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .logError("Dropping response message with invalid tag >>> " 535600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + sipResponse); 536600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 537600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 538600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 539600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipServerResponse.processResponse(sipResponse, this); 540600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } finally { 541600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipServerResponse instanceof SIPTransaction 542600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && !((SIPTransaction) sipServerResponse) 543600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .passToListener()) 544600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ((SIPTransaction) sipServerResponse).releaseSem(); 545600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 546600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 547600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Normal processing of message. 548600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 549600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 550600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack.getStackLogger().logDebug("null sipServerResponse!"); 551600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 552600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 553600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 554600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 555600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 556600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 557600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 558600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * JvB: added method to check for known buggy clients (Windows Messenger) to 559600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * fix the port to which responses are sent 560600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 561600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * checks for User-Agent: RTC/1.3.5470 (Messenger 5.1.0701) 562600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 563600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * JvB 22/7/2006 better to take this out for the moment, it is only a 564600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * problem in rare cases (unregister) 565600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 566600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * private final boolean isBuggyClient( SIPRequest r ) { UserAgent uah = 567600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * (UserAgent) r.getHeader( UserAgent.NAME ); if (uah!=null) { 568600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * java.util.ListIterator i = uah.getProduct(); if (i.hasNext()) { String p = 569600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * (String) uah.getProduct().next(); return p.startsWith( "RTC" ); } } 570600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * return false; } 571600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 572600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 573600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 574600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Implementation of the ParseExceptionListener interface. 575600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 576600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param ex 577600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Exception that is given to us by the parser. 578600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @throws ParseException 579600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * If we choose to reject the header or message. 580600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 581600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void handleException(ParseException ex, SIPMessage sipMessage, 582600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Class hdrClass, String header, String message) 583600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throws ParseException { 584600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 585600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack.getStackLogger().logException(ex); 586600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Log the bad message for later reference. 587600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if ((hdrClass != null) 588600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && (hdrClass.equals(From.class) || hdrClass.equals(To.class) 589600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || hdrClass.equals(CSeq.class) 590600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || hdrClass.equals(Via.class) 591600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || hdrClass.equals(CallID.class) 592600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || hdrClass.equals(RequestLine.class) || hdrClass 593600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .equals(StatusLine.class))) { 594600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 595600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logError("BAD MESSAGE!"); 596600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logError(message); 597600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 598600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw ex; 599600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 600600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipMessage.addUnparsed(header); 601600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 602600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 603600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 604600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 605600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Return a reply from a pre-constructed reply. This sends the message back 606600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * to the entity who caused us to create this channel in the first place. 607600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 608600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param sipMessage 609600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Message string to send. 610600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @throws IOException 611600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * If there is a problem with sending the message. 612600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 613600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void sendMessage(SIPMessage sipMessage) throws IOException { 614600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled() && this.sipStack.isLogStackTraceOnMessageSend()) { 615600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if ( sipMessage instanceof SIPRequest && 616600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ((SIPRequest)sipMessage).getRequestLine() != null) { 617600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 618600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * We dont want to log empty trace messages. 619600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 620600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack.getStackLogger().logStackTrace(StackLogger.TRACE_INFO); 621600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 622600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack.getStackLogger().logStackTrace(StackLogger.TRACE_INFO); 623600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 624600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 625600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 626600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Test and see where we are going to send the messsage. If the message 627600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // is sent back to oursleves, just 628600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // shortcircuit processing. 629600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang long time = System.currentTimeMillis(); 630600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 631600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang for (MessageProcessor messageProcessor : sipStack 632600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getMessageProcessors()) { 633600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (messageProcessor.getIpAddress().equals(this.peerAddress) 634600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && messageProcessor.getPort() == this.peerPort 635600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && messageProcessor.getTransport().equals( 636600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.peerProtocol)) { 637600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang MessageChannel messageChannel = messageProcessor 638600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .createMessageChannel(this.peerAddress, 639600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.peerPort); 640600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (messageChannel instanceof RawMessageChannel) { 641600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ((RawMessageChannel) messageChannel) 642600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .processMessage(sipMessage); 643600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 644600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug("Self routing message"); 645600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 646600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 647600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 648600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 649600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 650600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 651600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang byte[] msg = sipMessage.encodeAsBytes( this.getTransport() ); 652600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 653600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sendMessage(msg, peerAddress, peerPort, peerProtocol, 654600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipMessage instanceof SIPRequest); 655600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 656600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (IOException ex) { 657600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw ex; 658600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (Exception ex) { 659600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logError("An exception occured while sending message",ex); 660600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new IOException( 661600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "An exception occured while sending message"); 662600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } finally { 663600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.getStackLogger().isLoggingEnabled(ServerLogger.TRACE_MESSAGES) && !sipMessage.isNullRequest()) 664600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang logMessage(sipMessage, peerAddress, peerPort, time); 665600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else if (sipStack.getStackLogger().isLoggingEnabled(ServerLogger.TRACE_DEBUG)) 666600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug("Sent EMPTY Message"); 667600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 668600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 669600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 670600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 671600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Send a message to a specified receiver address. 672600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 673600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param msg 674600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * string to send. 675600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param peerAddress 676600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Address of the place to send it to. 677600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param peerPort 678600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * the port to send it to. 679600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @throws IOException 680600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * If there is trouble sending this message. 681600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 682600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected void sendMessage(byte[] msg, InetAddress peerAddress, 683600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int peerPort, boolean reConnect) throws IOException { 684600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Via is not included in the request so silently drop the reply. 685600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled() && this.sipStack.isLogStackTraceOnMessageSend() ) { 686600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack.getStackLogger().logStackTrace(StackLogger.TRACE_INFO); 687600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 688600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (peerPort == -1) { 689600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 690600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack.getStackLogger().logDebug(getClass().getName() 691600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + ":sendMessage: Dropping reply!"); 692600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 693600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new IOException("Receiver port not set "); 694600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 695600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 696600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack.getStackLogger().logDebug("sendMessage " + peerAddress.getHostAddress() + "/" 697600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + peerPort + "\n" + "messageSize = " + msg.length + " message = " + new String(msg)) ; 698600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack.getStackLogger().logDebug("*******************\n"); 699600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 700600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 701600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 702600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang DatagramPacket reply = new DatagramPacket(msg, msg.length, peerAddress, 703600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang peerPort); 704600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 705600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang DatagramSocket sock; 706600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang boolean created = false; 707600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 708600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.udpFlag) { 709600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Use the socket from the message processor (for firewall 710600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // support use the same socket as the message processor 711600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // socket -- feature request # 18 from java.net). This also 712600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // makes the whole thing run faster! 713600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sock = ((UDPMessageProcessor) messageProcessor).sock; 714600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 715600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Bind the socket to the stack address in case there 716600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // are multiple interfaces on the machine (feature reqeust 717600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // by Will Scullin) 0 binds to an ephemeral port. 718600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // sock = new DatagramSocket(0,sipStack.stackInetAddress); 719600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 720600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // bind to any interface and port. 721600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sock = new DatagramSocket(); 722600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang created = true; 723600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 724600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sock.send(reply); 725600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (created) 726600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sock.close(); 727600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (IOException ex) { 728600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw ex; 729600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (Exception ex) { 730600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang InternalErrorHandler.handleException(ex); 731600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 732600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 733600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 734600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 735600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Send a message to a specified receiver address. 736600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 737600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param msg 738600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * message string to send. 739600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param peerAddress 740600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Address of the place to send it to. 741600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param peerPort 742600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * the port to send it to. 743600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param peerProtocol 744600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * protocol to use to send. 745600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @throws IOException 746600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * If there is trouble sending this message. 747600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 748600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected void sendMessage(byte[] msg, InetAddress peerAddress, 749600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int peerPort, String peerProtocol, boolean retry) 750600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throws IOException { 751600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Via is not included in the request so silently drop the reply. 752600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (peerPort == -1) { 753600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 754600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack.getStackLogger().logDebug(getClass().getName() 755600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + ":sendMessage: Dropping reply!"); 756600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 757600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new IOException("Receiver port not set "); 758600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 759600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 760600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack.getStackLogger().logDebug( ":sendMessage " + peerAddress.getHostAddress() + "/" 761600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + peerPort + "\n" + " messageSize = " + msg.length); 762600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 763600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 764600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (peerProtocol.compareToIgnoreCase("UDP") == 0) { 765600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang DatagramPacket reply = new DatagramPacket(msg, msg.length, 766600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang peerAddress, peerPort); 767600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 768600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 769600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang DatagramSocket sock; 770600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.udpFlag) { 771600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sock = ((UDPMessageProcessor) messageProcessor).sock; 772600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 773600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 774600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // bind to any interface and port. 775600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sock = sipStack.getNetworkLayer().createDatagramSocket(); 776600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 777600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 778600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack.getStackLogger().logDebug("sendMessage " 779600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + peerAddress.getHostAddress() + "/" + peerPort 780600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "\n" + new String(msg)); 781600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 782600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sock.send(reply); 783600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!sipStack.udpFlag) 784600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sock.close(); 785600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (IOException ex) { 786600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw ex; 787600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (Exception ex) { 788600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang InternalErrorHandler.handleException(ex); 789600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 790600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 791600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 792600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Use TCP to talk back to the sender. 793600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Socket outputSocket = sipStack.ioHandler.sendBytes( 794600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.messageProcessor.getIpAddress(), peerAddress, 795600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang peerPort, "tcp", msg, retry,this); 796600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang OutputStream myOutputStream = outputSocket.getOutputStream(); 797600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang myOutputStream.write(msg, 0, msg.length); 798600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang myOutputStream.flush(); 799600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // The socket is cached (dont close it!); 800600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 801600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 802600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 803600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 804600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * get the stack pointer. 805600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 806600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return The sip stack for this channel. 807600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 808600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public SIPTransactionStack getSIPStack() { 809600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return sipStack; 810600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 811600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 812600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 813600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Return a transport string. 814600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 815600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return the string "udp" in this case. 816600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 817600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public String getTransport() { 818600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return SIPConstants.UDP; 819600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 820600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 821600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 822600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * get the stack address for the stack that received this message. 823600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 824600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return The stack address for our sipStack. 825600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 826600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public String getHost() { 827600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return messageProcessor.getIpAddress().getHostAddress(); 828600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 829600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 830600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 831600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * get the port. 832600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 833600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return Our port (on which we are getting datagram packets). 834600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 835600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public int getPort() { 836600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return ((UDPMessageProcessor) messageProcessor).getPort(); 837600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 838600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 839600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 840600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * get the name (address) of the host that sent me the message 841600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 842600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return The name of the sender (from the datagram packet). 843600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 844600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public String getPeerName() { 845600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return peerAddress.getHostName(); 846600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 847600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 848600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 849600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * get the address of the host that sent me the message 850600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 851600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return The senders ip address. 852600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 853600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public String getPeerAddress() { 854600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return peerAddress.getHostAddress(); 855600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 856600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 857600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected InetAddress getPeerInetAddress() { 858600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return peerAddress; 859600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 860600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 861600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 862600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Compare two UDP Message channels for equality. 863600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 864600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param other 865600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * The other message channel with which to compare oursleves. 866600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 867600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public boolean equals(Object other) { 868600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 869600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (other == null) 870600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return false; 871600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang boolean retval; 872600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!this.getClass().equals(other.getClass())) { 873600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval = false; 874600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 875600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang UDPMessageChannel that = (UDPMessageChannel) other; 876600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval = this.getKey().equals(that.getKey()); 877600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 878600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 879600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return retval; 880600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 881600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 882600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public String getKey() { 883600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return getKey(peerAddress, peerPort, "UDP"); 884600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 885600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 886600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public int getPeerPacketSourcePort() { 887600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return peerPacketSourcePort; 888600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 889600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 890600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public InetAddress getPeerPacketSourceAddress() { 891600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return peerPacketSourceAddress; 892600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 893600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 894600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 895600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the logical originator of the message (from the top via header). 896600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 897600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return topmost via header sentby field 898600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 899600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public String getViaHost() { 900600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.myAddress; 901600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 902600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 903600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 904600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the logical port of the message orginator (from the top via hdr). 905600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 906600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return the via port from the topmost via header. 907600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 908600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public int getViaPort() { 909600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.myPort; 910600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 911600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 912600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 913600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Returns "false" as this is an unreliable transport. 914600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 915600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public boolean isReliable() { 916600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return false; 917600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 918600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 919600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 920600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * UDP is not a secure protocol. 921600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 922600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public boolean isSecure() { 923600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return false; 924600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 925600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 926600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public int getPeerPort() { 927600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return peerPort; 928600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 929600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 930600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public String getPeerProtocol() { 931600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.peerProtocol; 932600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 933600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 934600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 935600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Close the message channel. 936600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 937600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void close() { 938600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 939600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 940600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 941600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang} 942