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 United 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.core.StackLogger; 32600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.SipStackImpl; 33600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 34600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.io.*; 35600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.net.*; 36600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.Enumeration; 37600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.concurrent.ConcurrentHashMap; 38600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.concurrent.Semaphore; 39600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.concurrent.TimeUnit; 40600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 41600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.net.ssl.HandshakeCompletedListener; 42600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.net.ssl.SSLSocket; 43600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 44600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/* 45600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * TLS support Added by Daniel J.Martinez Manzano <dani@dif.um.es> 46600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 47600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 48600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 49600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/** 50600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Low level Input output to a socket. Caches TCP connections and takes care of re-connecting to 51600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * the remote party if the other end drops the connection 52600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 53600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @version 1.2 54600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 55600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @author M. Ranganathan <br/> 56600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 57600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 58600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 59600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 60600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangclass IOHandler { 61600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 62600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private Semaphore ioSemaphore = new Semaphore(1); 63600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 64600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private SipStackImpl sipStack; 65600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 66600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private static String TCP = "tcp"; 67600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 68600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Added by Daniel J. Martinez Manzano <dani@dif.um.es> 69600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private static String TLS = "tls"; 70600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 71600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // A cache of client sockets that can be re-used for 72600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // sending tcp messages. 73600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private ConcurrentHashMap<String, Socket> socketTable; 74600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 75600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected static String makeKey(InetAddress addr, int port) { 76600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return addr.getHostAddress() + ":" + port; 77600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 78600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 79600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 80600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected IOHandler(SIPTransactionStack sipStack) { 81600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack = (SipStackImpl) sipStack; 82600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.socketTable = new ConcurrentHashMap<String, Socket>(); 83600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 84600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 85600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 86600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected void putSocket(String key, Socket sock) { 87600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang socketTable.put(key, sock); 88600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 89600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 90600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 91600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected Socket getSocket(String key) { 92600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return (Socket) socketTable.get(key); 93600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 94600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 95600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected void removeSocket(String key) { 96600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang socketTable.remove(key); 97600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 98600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 99600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 100600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * A private function to write things out. This needs to be synchronized as writes can occur 101600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * from multiple threads. We write in chunks to allow the other side to synchronize for large 102600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * sized writes. 103600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 104600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private void writeChunks(OutputStream outputStream, byte[] bytes, int length) 105600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throws IOException { 106600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Chunk size is 16K - this hack is for large 107600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // writes over slow connections. 108600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang synchronized (outputStream) { 109600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // outputStream.write(bytes,0,length); 110600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int chunksize = 8 * 1024; 111600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang for (int p = 0; p < length; p += chunksize) { 112600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int chunk = p + chunksize < length ? chunksize : length - p; 113600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang outputStream.write(bytes, p, chunk); 114600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 115600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 116600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang outputStream.flush(); 117600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 118600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 119600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 120600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Creates and binds, if necessary, a socket connected to the specified destination address 121600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * and port and then returns its local address. 122600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 123600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param dst the destination address that the socket would need to connect to. 124600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param dstPort the port number that the connection would be established with. 125600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param localAddress the address that we would like to bind on (null for the "any" address). 126600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param localPort the port that we'd like our socket to bind to (0 for a random port). 127600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 128600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return the SocketAddress that this handler would use when connecting to the specified 129600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * destination address and port. 130600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 131600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @throws IOException 132600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 133600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public SocketAddress obtainLocalAddress(InetAddress dst, int dstPort, 134600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang InetAddress localAddress, int localPort) throws IOException { 135600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String key = makeKey(dst, dstPort); 136600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 137600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Socket clientSock = getSocket(key); 138600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 139600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (clientSock == null) { 140600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang clientSock = sipStack.getNetworkLayer().createSocket(dst, dstPort, localAddress, 141600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang localPort); 142600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang putSocket(key, clientSock); 143600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 144600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 145600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return clientSock.getLocalSocketAddress(); 146600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 147600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 148600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 149600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 150600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Send an array of bytes. 151600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 152600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param receiverAddress -- inet address 153600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param contactPort -- port to connect to. 154600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param transport -- tcp or udp. 155600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param retry -- retry to connect if the other end closed connection 156600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @throws IOException -- if there is an IO exception sending message. 157600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 158600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 159600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public Socket sendBytes(InetAddress senderAddress, InetAddress receiverAddress, 160600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int contactPort, String transport, byte[] bytes, boolean retry, 161600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang MessageChannel messageChannel) throws IOException { 162600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int retry_count = 0; 163600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int max_retry = retry ? 2 : 1; 164600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Server uses TCP transport. TCP client sockets are cached 165600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int length = bytes.length; 166600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 167600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 168600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "sendBytes " + transport + " inAddr " + receiverAddress.getHostAddress() 169600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + " port = " + contactPort + " length = " + length); 170600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 171600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled() && sipStack.isLogStackTraceOnMessageSend()) { 172600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logStackTrace(StackLogger.TRACE_INFO); 173600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 174600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (transport.compareToIgnoreCase(TCP) == 0) { 175600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String key = makeKey(receiverAddress, contactPort); 176600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // This should be in a synchronized block ( reported by 177600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Jayashenkhar ( lucent ). 178600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 179600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 180600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang boolean retval = this.ioSemaphore.tryAcquire(10000, TimeUnit.MILLISECONDS); 181600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!retval) { 182600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new IOException( 183600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Could not acquire IO Semaphore after 10 seconds -- giving up "); 184600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 185600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (InterruptedException ex) { 186600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new IOException("exception in acquiring sem"); 187600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 188600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Socket clientSock = getSocket(key); 189600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 190600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 191600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 192600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (retry_count < max_retry) { 193600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (clientSock == null) { 194600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 195600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug("inaddr = " + receiverAddress); 196600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug("port = " + contactPort); 197600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 198600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // note that the IP Address for stack may not be 199600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // assigned. 200600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // sender address is the address of the listening point. 201600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // in version 1.1 all listening points have the same IP 202600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // address (i.e. that of the stack). In version 1.2 203600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // the IP address is on a per listening point basis. 204600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang clientSock = sipStack.getNetworkLayer().createSocket(receiverAddress, 205600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang contactPort, senderAddress); 206600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang OutputStream outputStream = clientSock.getOutputStream(); 207600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang writeChunks(outputStream, bytes, length); 208600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang putSocket(key, clientSock); 209600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang break; 210600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 211600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 212600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang OutputStream outputStream = clientSock.getOutputStream(); 213600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang writeChunks(outputStream, bytes, length); 214600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang break; 215600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (IOException ex) { 216600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 217600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 218600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "IOException occured retryCount " + retry_count); 219600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // old connection is bad. 220600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // remove from our table. 221600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang removeSocket(key); 222600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 223600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang clientSock.close(); 224600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (Exception e) { 225600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 226600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang clientSock = null; 227600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retry_count++; 228600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 229600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 230600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 231600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } finally { 232600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ioSemaphore.release(); 233600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 234600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 235600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (clientSock == null) { 236600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 237600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 238600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug(this.socketTable.toString()); 239600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logError( 240600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Could not connect to " + receiverAddress + ":" + contactPort); 241600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 242600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 243600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new IOException("Could not connect to " + receiverAddress + ":" 244600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + contactPort); 245600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else 246600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return clientSock; 247600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 248600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Added by Daniel J. Martinez Manzano <dani@dif.um.es> 249600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Copied and modified from the former section for TCP 250600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (transport.compareToIgnoreCase(TLS) == 0) { 251600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String key = makeKey(receiverAddress, contactPort); 252600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 253600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang boolean retval = this.ioSemaphore.tryAcquire(10000, TimeUnit.MILLISECONDS); 254600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!retval) 255600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new IOException("Timeout acquiring IO SEM"); 256600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (InterruptedException ex) { 257600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new IOException("exception in acquiring sem"); 258600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 259600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Socket clientSock = getSocket(key); 260600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 261600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 262600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (retry_count < max_retry) { 263600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (clientSock == null) { 264600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 265600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug("inaddr = " + receiverAddress); 266600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug("port = " + contactPort); 267600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 268600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 269600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang clientSock = sipStack.getNetworkLayer().createSSLSocket(receiverAddress, 270600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang contactPort, senderAddress); 271600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SSLSocket sslsock = (SSLSocket) clientSock; 272600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang HandshakeCompletedListener listner = new HandshakeCompletedListenerImpl( 273600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang (TLSMessageChannel) messageChannel); 274600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ((TLSMessageChannel) messageChannel) 275600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .setHandshakeCompletedListener(listner); 276600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sslsock.addHandshakeCompletedListener(listner); 277600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sslsock.setEnabledProtocols(sipStack.getEnabledProtocols()); 278600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sslsock.startHandshake(); 279600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 280600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang OutputStream outputStream = clientSock.getOutputStream(); 281600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang writeChunks(outputStream, bytes, length); 282600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang putSocket(key, clientSock); 283600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang break; 284600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 285600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 286600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang OutputStream outputStream = clientSock.getOutputStream(); 287600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang writeChunks(outputStream, bytes, length); 288600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang break; 289600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (IOException ex) { 290600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 291600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logException(ex); 292600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // old connection is bad. 293600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // remove from our table. 294600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang removeSocket(key); 295600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 296600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang clientSock.close(); 297600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (Exception e) { 298600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 299600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang clientSock = null; 300600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retry_count++; 301600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 302600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 303600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 304600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } finally { 305600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ioSemaphore.release(); 306600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 307600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (clientSock == null) { 308600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new IOException("Could not connect to " + receiverAddress + ":" 309600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + contactPort); 310600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else 311600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return clientSock; 312600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 313600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 314600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // This is a UDP transport... 315600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang DatagramSocket datagramSock = sipStack.getNetworkLayer().createDatagramSocket(); 316600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang datagramSock.connect(receiverAddress, contactPort); 317600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang DatagramPacket dgPacket = new DatagramPacket(bytes, 0, length, receiverAddress, 318600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang contactPort); 319600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang datagramSock.send(dgPacket); 320600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang datagramSock.close(); 321600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return null; 322600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 323600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 324600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 325600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 326600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 327600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Close all the cached connections. 328600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 329600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void closeAll() { 330600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang for (Enumeration<Socket> values = socketTable.elements(); values.hasMoreElements();) { 331600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Socket s = (Socket) values.nextElement(); 332600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 333600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang s.close(); 334600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (IOException ex) { 335600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 336600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 337600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 338600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 339600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 340600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang} 341