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