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 Wangpackage gov.nist.javax.sip.stack; 30600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 31600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.*; 32600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.message.*; 33600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.parser.*; 34600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.core.*; 35600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.net.*; 36600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.io.*; 37600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.text.ParseException; 38600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.TimerTask; 39600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 40600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.address.Hop; 41600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 42600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/* 43600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Ahmet Uyar <auyar@csit.fsu.edu>sent in a bug report for TCP operation of the JAIN sipStack. 44600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Niklas Uhrberg suggested that a mechanism be added to limit the number of simultaneous open 45600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * connections. The TLS Adaptations were contributed by Daniel Martinez. Hagai Sela contributed a 46600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * bug fix for symmetric nat. Jeroen van Bemmel added compensation for buggy clients ( Microsoft 47600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * RTC clients ). Bug fixes by viswashanti.kadiyala@antepo.com, Joost Yervante Damand 48600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 49600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 50600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/** 51600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * This is a stack abstraction for TCP connections. This abstracts a stream of parsed messages. 52600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * The SIP sipStack starts this from the main SIPStack class for each connection that it accepts. 53600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * It starts a message parser in its own thread and talks to the message parser via a pipe. The 54600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * message parser calls back via the parseError or processMessage functions that are defined as 55600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * part of the SIPMessageListener interface. 56600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 57600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @see gov.nist.javax.sip.parser.PipelinedMsgParser 58600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 59600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 60600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @author M. Ranganathan <br/> 61600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 62600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @version 1.2 $Revision: 1.59 $ $Date: 2009/11/20 04:45:53 $ 63600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 64600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangpublic class TCPMessageChannel extends MessageChannel implements SIPMessageListener, Runnable, 65600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang RawMessageChannel { 66600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 67600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private Socket mySock; 68600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 69600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private PipelinedMsgParser myParser; 70600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 71600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected InputStream myClientInputStream; // just to pass to thread. 72600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 73600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected OutputStream myClientOutputStream; 74600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 75600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected String key; 76600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 77600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected boolean isCached; 78600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 79600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected boolean isRunning; 80600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 81600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private Thread mythread; 82600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 83600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected SIPTransactionStack sipStack; 84600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 85600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected String myAddress; 86600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 87600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected int myPort; 88600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 89600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected InetAddress peerAddress; 90600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 91600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected int peerPort; 92600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 93600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected String peerProtocol; 94600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 95600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Incremented whenever a transaction gets assigned 96600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // to the message channel and decremented when 97600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // a transaction gets freed from the message channel. 98600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // protected int useCount; 99600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 100600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private TCPMessageProcessor tcpMessageProcessor; 101600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 102600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected TCPMessageChannel(SIPTransactionStack sipStack) { 103600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack = sipStack; 104600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 105600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 106600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 107600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 108600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Constructor - gets called from the SIPStack class with a socket on accepting a new client. 109600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * All the processing of the message is done here with the sipStack being freed up to handle 110600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * new connections. The sock input is the socket that is returned from the accept. Global data 111600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * that is shared by all threads is accessible in the Server structure. 112600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 113600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param sock Socket from which to read and write messages. The socket is already connected 114600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * (was created as a result of an accept). 115600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 116600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param sipStack Ptr to SIP Stack 117600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 118600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 119600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected TCPMessageChannel(Socket sock, SIPTransactionStack sipStack, 120600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang TCPMessageProcessor msgProcessor) throws IOException { 121600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 122600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 123600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug("creating new TCPMessageChannel "); 124600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logStackTrace(); 125600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 126600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang mySock = sock; 127600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang peerAddress = mySock.getInetAddress(); 128600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang myAddress = msgProcessor.getIpAddress().getHostAddress(); 129600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang myClientInputStream = mySock.getInputStream(); 130600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang myClientOutputStream = mySock.getOutputStream(); 131600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang mythread = new Thread(this); 132600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang mythread.setDaemon(true); 133600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang mythread.setName("TCPMessageChannelThread"); 134600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Stash away a pointer to our sipStack structure. 135600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack = sipStack; 136600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.peerPort = mySock.getPort(); 137600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 138600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.tcpMessageProcessor = msgProcessor; 139600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.myPort = this.tcpMessageProcessor.getPort(); 140600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Bug report by Vishwashanti Raj Kadiayl 141600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang super.messageProcessor = msgProcessor; 142600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Can drop this after response is sent potentially. 143600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang mythread.start(); 144600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 145600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 146600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 147600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Constructor - connects to the given inet address. Acknowledgement -- Lamine Brahimi (IBM 148600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Zurich) sent in a bug fix for this method. A thread was being uncessarily created. 149600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 150600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param inetAddr inet address to connect to. 151600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param sipStack is the sip sipStack from which we are created. 152600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @throws IOException if we cannot connect. 153600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 154600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected TCPMessageChannel(InetAddress inetAddr, int port, SIPTransactionStack sipStack, 155600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang TCPMessageProcessor messageProcessor) throws IOException { 156600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 157600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug("creating new TCPMessageChannel "); 158600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logStackTrace(); 159600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 160600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.peerAddress = inetAddr; 161600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.peerPort = port; 162600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.myPort = messageProcessor.getPort(); 163600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.peerProtocol = "TCP"; 164600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack = sipStack; 165600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.tcpMessageProcessor = messageProcessor; 166600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.myAddress = messageProcessor.getIpAddress().getHostAddress(); 167600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Bug report by Vishwashanti Raj Kadiayl 168600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.key = MessageChannel.getKey(peerAddress, peerPort, "TCP"); 169600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang super.messageProcessor = messageProcessor; 170600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 171600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 172600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 173600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 174600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Returns "true" as this is a reliable transport. 175600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 176600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public boolean isReliable() { 177600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return true; 178600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 179600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 180600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 181600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Close the message channel. 182600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 183600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void close() { 184600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 185600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (mySock != null) { 186600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang mySock.close(); 187600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang mySock = null; 188600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 189600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 190600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug("Closing message Channel " + this); 191600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (IOException ex) { 192600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 193600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug("Error closing socket " + ex); 194600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 195600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 196600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 197600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 198600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get my SIP Stack. 199600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 200600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return The SIP Stack for this message channel. 201600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 202600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public SIPTransactionStack getSIPStack() { 203600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return sipStack; 204600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 205600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 206600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 207600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * get the transport string. 208600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 209600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return "tcp" in this case. 210600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 211600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public String getTransport() { 212600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return "TCP"; 213600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 214600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 215600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 216600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * get the address of the client that sent the data to us. 217600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 218600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return Address of the client that sent us data that resulted in this channel being 219600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * created. 220600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 221600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public String getPeerAddress() { 222600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (peerAddress != null) { 223600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return peerAddress.getHostAddress(); 224600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else 225600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return getHost(); 226600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 227600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 228600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected InetAddress getPeerInetAddress() { 229600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return peerAddress; 230600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 231600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 232600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public String getPeerProtocol() { 233600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.peerProtocol; 234600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 235600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 236600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 237600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Send message to whoever is connected to us. Uses the topmost via address to send to. 238600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 239600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param msg is the message to send. 240600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param retry 241600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 242600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private void sendMessage(byte[] msg, boolean retry) throws IOException { 243600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 244600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 245600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Patch from kircuv@dev.java.net (Issue 119 ) This patch avoids the case where two 246600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * TCPMessageChannels are now pointing to the same socket.getInputStream(). 247600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 248600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * JvB 22/5 removed 249600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 250600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Socket s = this.sipStack.ioHandler.getSocket(IOHandler.makeKey( 251600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // this.peerAddress, this.peerPort)); 252600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Socket sock = this.sipStack.ioHandler.sendBytes(this.messageProcessor.getIpAddress(), 253600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.peerAddress, this.peerPort, this.peerProtocol, msg, retry, this); 254600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 255600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Created a new socket so close the old one and stick the new 256600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // one in its place but dont do this if it is a datagram socket. 257600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // (could have replied via udp but received via tcp!). 258600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // if (mySock == null && s != null) { 259600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // this.uncache(); 260600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // } else 261600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sock != mySock && sock != null) { 262600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 263600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (mySock != null) 264600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang mySock.close(); 265600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (IOException ex) { 266600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 267600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang mySock = sock; 268600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.myClientInputStream = mySock.getInputStream(); 269600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.myClientOutputStream = mySock.getOutputStream(); 270600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Thread thread = new Thread(this); 271600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang thread.setDaemon(true); 272600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang thread.setName("TCPMessageChannelThread"); 273600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang thread.start(); 274600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 275600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 276600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 277600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 278600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 279600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Return a formatted message to the client. We try to re-connect with the peer on the other 280600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * end if possible. 281600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 282600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param sipMessage Message to send. 283600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @throws IOException If there is an error sending the message 284600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 285600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void sendMessage(SIPMessage sipMessage) throws IOException { 286600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang byte[] msg = sipMessage.encodeAsBytes(this.getTransport()); 287600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 288600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang long time = System.currentTimeMillis(); 289600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 290600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // JvB: also retry for responses, if the connection is gone we should 291600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // try to reconnect 292600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sendMessage(msg, /* sipMessage instanceof SIPRequest */true); 293600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 294600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.sipStack.getStackLogger().isLoggingEnabled(ServerLogger.TRACE_MESSAGES)) 295600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang logMessage(sipMessage, peerAddress, peerPort, time); 296600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 297600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 298600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 299600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Send a message to a specified address. 300600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 301600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param message Pre-formatted message to send. 302600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param receiverAddress Address to send it to. 303600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param receiverPort Receiver port. 304600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @throws IOException If there is a problem connecting or sending. 305600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 306600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void sendMessage(byte message[], InetAddress receiverAddress, int receiverPort, 307600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang boolean retry) throws IOException { 308600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (message == null || receiverAddress == null) 309600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new IllegalArgumentException("Null argument"); 310600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Socket sock = this.sipStack.ioHandler.sendBytes(this.messageProcessor.getIpAddress(), 311600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang receiverAddress, receiverPort, "TCP", message, retry, this); 312600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sock != mySock && sock != null) { 313600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (mySock != null) { 314600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 315600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Delay the close of the socket for some time in case it is being used. 316600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 317600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getTimer().schedule(new TimerTask() { 318600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang @Override 319600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public boolean cancel() { 320600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 321600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang mySock.close(); 322600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang super.cancel(); 323600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (IOException ex) { 324600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 325600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 326600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return true; 327600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 328600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 329600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang @Override 330600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void run() { 331600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 332600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang mySock.close(); 333600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (IOException ex) { 334600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 335600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 336600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 337600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang }, 8000); 338600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 339600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 340600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang mySock = sock; 341600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.myClientInputStream = mySock.getInputStream(); 342600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.myClientOutputStream = mySock.getOutputStream(); 343600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // start a new reader on this end of the pipe. 344600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Thread mythread = new Thread(this); 345600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang mythread.setDaemon(true); 346600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang mythread.setName("TCPMessageChannelThread"); 347600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang mythread.start(); 348600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 349600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 350600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 351600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 352600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 353600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Exception processor for exceptions detected from the parser. (This is invoked by the parser 354600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * when an error is detected). 355600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 356600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param sipMessage -- the message that incurred the error. 357600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param ex -- parse exception detected by the parser. 358600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param header -- header that caused the error. 359600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @throws ParseException Thrown if we want to reject the message. 360600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 361600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void handleException(ParseException ex, SIPMessage sipMessage, Class hdrClass, 362600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String header, String message) throws ParseException { 363600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 364600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logException(ex); 365600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Log the bad message for later reference. 366600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if ((hdrClass != null) 367600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && (hdrClass.equals(From.class) || hdrClass.equals(To.class) 368600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || hdrClass.equals(CSeq.class) || hdrClass.equals(Via.class) 369600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || hdrClass.equals(CallID.class) || hdrClass.equals(RequestLine.class) || hdrClass 370600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .equals(StatusLine.class))) { 371600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 372600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 373600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Encountered Bad Message \n" + sipMessage.toString()); 374600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 375600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 376600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // JvB: send a 400 response for requests (except ACK) 377600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Currently only UDP, @todo also other transports 378600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String msgString = sipMessage.toString(); 379600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!msgString.startsWith("SIP/") && !msgString.startsWith("ACK ")) { 380600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 381600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String badReqRes = createBadReqRes(msgString, ex); 382600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (badReqRes != null) { 383600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 384600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug("Sending automatic 400 Bad Request:"); 385600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug(badReqRes); 386600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 387600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 388600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sendMessage(badReqRes.getBytes(), this.getPeerInetAddress(), this 389600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getPeerPort(), false); 390600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (IOException e) { 391600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack.getStackLogger().logException(e); 392600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 393600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 394600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 395600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 396600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Could not formulate automatic 400 Bad Request"); 397600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 398600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 399600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 400600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 401600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw ex; 402600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 403600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipMessage.addUnparsed(header); 404600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 405600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 406600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 407600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 408600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Gets invoked by the parser as a callback on successful message parsing (i.e. no parser 409600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * errors). 410600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 411600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param sipMessage Mesage to process (this calls the application for processing the 412600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * message). 413600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 414600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void processMessage(SIPMessage sipMessage) throws Exception { 415600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 416600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipMessage.getFrom() == null 417600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || // sipMessage.getFrom().getTag() 418600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // == null || 419600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipMessage.getTo() == null || sipMessage.getCallId() == null 420600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || sipMessage.getCSeq() == null || sipMessage.getViaHeaders() == null) { 421600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String badmsg = sipMessage.encode(); 422600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 423600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug(">>> Dropped Bad Msg"); 424600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug(badmsg); 425600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 426600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 427600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 428600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 429600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 430600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ViaList viaList = sipMessage.getViaHeaders(); 431600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // For a request 432600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // first via header tells where the message is coming from. 433600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // For response, this has already been recorded in the outgoing 434600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // message. 435600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipMessage instanceof SIPRequest) { 436600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Via v = (Via) viaList.getFirst(); 437600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Hop hop = sipStack.addressResolver.resolveAddress(v.getHop()); 438600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.peerProtocol = v.getTransport(); 439600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 440600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.peerAddress = mySock.getInetAddress(); 441600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Check to see if the received parameter matches 442600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // the peer address and tag it appropriately. 443600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 444600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // JvB: dont do this. It is both costly and incorrect 445600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Must set received also when it is a FQDN, regardless 446600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // whether 447600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // it resolves to the correct IP address 448600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // InetAddress sentByAddress = 449600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // InetAddress.getByName(hop.getHost()); 450600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // JvB: if sender added 'rport', must always set received 451600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (v.hasParameter(Via.RPORT) 452600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || !hop.getHost().equals(this.peerAddress.getHostAddress())) { 453600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang v.setParameter(Via.RECEIVED, this.peerAddress.getHostAddress()); 454600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 455600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // @@@ hagai 456600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // JvB: technically, may only do this when Via already 457600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // contains 458600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // rport 459600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang v.setParameter(Via.RPORT, Integer.toString(this.peerPort)); 460600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (java.text.ParseException ex) { 461600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang InternalErrorHandler.handleException(ex, sipStack.getStackLogger()); 462600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 463600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Use this for outgoing messages as well. 464600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!this.isCached) { 465600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ((TCPMessageProcessor) this.messageProcessor).cacheMessageChannel(this); 466600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.isCached = true; 467600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int remotePort = ((java.net.InetSocketAddress) mySock.getRemoteSocketAddress()).getPort(); 468600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String key = IOHandler.makeKey(mySock.getInetAddress(), remotePort); 469600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.ioHandler.putSocket(key, mySock); 470600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 471600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 472600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 473600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 474600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Foreach part of the request header, fetch it and process it 475600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 476600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang long receptionTime = System.currentTimeMillis(); 477600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 478600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipMessage instanceof SIPRequest) { 479600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // This is a request - process the request. 480600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPRequest sipRequest = (SIPRequest) sipMessage; 481600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Create a new sever side request processor for this 482600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // message and let it handle the rest. 483600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 484600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 485600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug("----Processing Message---"); 486600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 487600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 488600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Check for reasonable size - reject message 489600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // if it is too long. 490600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.sipStack.getStackLogger().isLoggingEnabled(ServerLogger.TRACE_MESSAGES)) { 491600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.serverLogger.logMessage(sipMessage, this.getPeerHostPort().toString(), 492600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.getMessageProcessor().getIpAddress().getHostAddress() + ":" 493600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + this.getMessageProcessor().getPort(), false, receptionTime); 494600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 495600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 496600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 497600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.getMaxMessageSize() > 0 498600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && sipRequest.getSize() 499600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + (sipRequest.getContentLength() == null ? 0 : sipRequest 500600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getContentLength().getContentLength()) > sipStack 501600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getMaxMessageSize()) { 502600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPResponse sipResponse = sipRequest 503600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .createResponse(SIPResponse.MESSAGE_TOO_LARGE); 504600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang byte[] resp = sipResponse.encodeAsBytes(this.getTransport()); 505600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sendMessage(resp, false); 506600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new Exception("Message size exceeded"); 507600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 508600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 509600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ServerRequestInterface sipServerRequest = sipStack.newSIPServerRequest( 510600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipRequest, this); 511600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 512600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipServerRequest != null) { 513600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 514600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipServerRequest.processRequest(sipRequest, this); 515600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } finally { 516600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipServerRequest instanceof SIPTransaction) { 517600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPServerTransaction sipServerTx = (SIPServerTransaction) sipServerRequest; 518600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!sipServerTx.passToListener()) 519600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ((SIPTransaction) sipServerRequest).releaseSem(); 520600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 521600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 522600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 523600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 524600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack.getStackLogger() 525600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .logWarning("Dropping request -- could not acquire semaphore in 10 sec"); 526600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 527600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 528600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 529600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPResponse sipResponse = (SIPResponse) sipMessage; 530600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // JvB: dont do this 531600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // if (sipResponse.getStatusCode() == 100) 532600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // sipResponse.getTo().removeParameter("tag"); 533600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 534600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipResponse.checkHeaders(); 535600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (ParseException ex) { 536600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 537600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger() 538600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .logError("Dropping Badly formatted response message >>> " 539600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + sipResponse); 540600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 541600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 542600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // This is a response message - process it. 543600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Check the size of the response. 544600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // If it is too large dump it silently. 545600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.getMaxMessageSize() > 0 546600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && sipResponse.getSize() 547600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + (sipResponse.getContentLength() == null ? 0 : sipResponse 548600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getContentLength().getContentLength()) > sipStack 549600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getMaxMessageSize()) { 550600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 551600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack.getStackLogger().logDebug("Message size exceeded"); 552600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 553600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 554600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 555600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ServerResponseInterface sipServerResponse = sipStack.newSIPServerResponse( 556600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipResponse, this); 557600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipServerResponse != null) { 558600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 559600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipServerResponse instanceof SIPClientTransaction 560600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && !((SIPClientTransaction) sipServerResponse) 561600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .checkFromTag(sipResponse)) { 562600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 563600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger() 564600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .logError("Dropping response message with invalid tag >>> " 565600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + sipResponse); 566600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 567600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 568600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 569600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipServerResponse.processResponse(sipResponse, this); 570600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } finally { 571600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipServerResponse instanceof SIPTransaction 572600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && !((SIPTransaction) sipServerResponse).passToListener()) 573600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ((SIPTransaction) sipServerResponse).releaseSem(); 574600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 575600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 576600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack 577600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getStackLogger() 578600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .logWarning( 579600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Application is blocked -- could not acquire semaphore -- dropping response"); 580600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 581600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 582600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } finally { 583600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 584600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 585600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 586600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 587600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * This gets invoked when thread.start is called from the constructor. Implements a message 588600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * loop - reading the tcp connection and processing messages until we are done or the other 589600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * end has closed. 590600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 591600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void run() { 592600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Pipeline hispipe = null; 593600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Create a pipeline to connect to our message parser. 594600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang hispipe = new Pipeline(myClientInputStream, sipStack.readTimeout, 595600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ((SIPTransactionStack) sipStack).getTimer()); 596600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Create a pipelined message parser to read and parse 597600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // messages that we write out to him. 598600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang myParser = new PipelinedMsgParser(this, hispipe, this.sipStack.getMaxMessageSize()); 599600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Start running the parser thread. 600600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang myParser.processInput(); 601600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // bug fix by Emmanuel Proulx 602600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int bufferSize = 4096; 603600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.tcpMessageProcessor.useCount++; 604600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.isRunning = true; 605600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 606600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (true) { 607600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 608600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang byte[] msg = new byte[bufferSize]; 609600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int nbytes = myClientInputStream.read(msg, 0, bufferSize); 610600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // no more bytes to read... 611600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (nbytes == -1) { 612600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang hispipe.write("\r\n\r\n".getBytes("UTF-8")); 613600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 614600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.maxConnections != -1) { 615600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang synchronized (tcpMessageProcessor) { 616600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang tcpMessageProcessor.nConnections--; 617600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang tcpMessageProcessor.notify(); 618600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 619600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 620600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang hispipe.close(); 621600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang mySock.close(); 622600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (IOException ioex) { 623600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 624600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 625600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 626600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang hispipe.write(msg, 0, nbytes); 627600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 628600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (IOException ex) { 629600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Terminate the message. 630600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 631600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang hispipe.write("\r\n\r\n".getBytes("UTF-8")); 632600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (Exception e) { 633600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // InternalErrorHandler.handleException(e); 634600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 635600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 636600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 637600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 638600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug("IOException closing sock " + ex); 639600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 640600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.maxConnections != -1) { 641600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang synchronized (tcpMessageProcessor) { 642600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang tcpMessageProcessor.nConnections--; 643600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // System.out.println("Notifying!"); 644600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang tcpMessageProcessor.notify(); 645600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 646600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 647600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang mySock.close(); 648600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang hispipe.close(); 649600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (IOException ioex) { 650600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 651600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (Exception ex1) { 652600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Do nothing. 653600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 654600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 655600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (Exception ex) { 656600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang InternalErrorHandler.handleException(ex, sipStack.getStackLogger()); 657600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 658600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 659600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } finally { 660600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.isRunning = false; 661600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.tcpMessageProcessor.remove(this); 662600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.tcpMessageProcessor.useCount--; 663600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang myParser.close(); 664600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 665600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 666600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 667600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 668600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected void uncache() { 669600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (isCached && !isRunning) { 670600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.tcpMessageProcessor.remove(this); 671600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 672600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 673600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 674600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 675600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Equals predicate. 676600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 677600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param other is the other object to compare ourselves to for equals 678600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 679600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 680600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public boolean equals(Object other) { 681600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 682600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!this.getClass().equals(other.getClass())) 683600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return false; 684600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else { 685600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang TCPMessageChannel that = (TCPMessageChannel) other; 686600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.mySock != that.mySock) 687600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return false; 688600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else 689600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return true; 690600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 691600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 692600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 693600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 694600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get an identifying key. This key is used to cache the connection and re-use it if 695600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * necessary. 696600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 697600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public String getKey() { 698600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.key != null) { 699600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.key; 700600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 701600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.key = MessageChannel.getKey(this.peerAddress, this.peerPort, "TCP"); 702600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.key; 703600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 704600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 705600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 706600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 707600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the host to assign to outgoing messages. 708600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 709600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return the host to assign to the via header. 710600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 711600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public String getViaHost() { 712600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return myAddress; 713600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 714600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 715600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 716600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the port for outgoing messages sent from the channel. 717600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 718600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return the port to assign to the via header. 719600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 720600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public int getViaPort() { 721600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return myPort; 722600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 723600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 724600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 725600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the port of the peer to whom we are sending messages. 726600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 727600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return the peer port. 728600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 729600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public int getPeerPort() { 730600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return peerPort; 731600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 732600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 733600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public int getPeerPacketSourcePort() { 734600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.peerPort; 735600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 736600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 737600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public InetAddress getPeerPacketSourceAddress() { 738600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.peerAddress; 739600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 740600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 741600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 742600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * TCP Is not a secure protocol. 743600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 744600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public boolean isSecure() { 745600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return false; 746600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 747600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang} 748