1/* 2 * Conditions Of Use 3 * 4 * This software was developed by employees of the National Institute of 5 * Standards and Technology (NIST), an agency of the Federal Government. 6 * Pursuant to title 15 Untied States Code Section 105, works of NIST 7 * employees are not subject to copyright protection in the United States 8 * and are considered to be in the public domain. As a result, a formal 9 * license is not needed to use the software. 10 * 11 * This software is provided by NIST as a service and is expressly 12 * provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED 13 * OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF 14 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT 15 * AND DATA ACCURACY. NIST does not warrant or make any representations 16 * regarding the use of the software or the results thereof, including but 17 * not limited to the correctness, accuracy, reliability or usefulness of 18 * the software. 19 * 20 * Permission to use this software is contingent upon your acceptance 21 * of the terms of this agreement 22 * 23 * . 24 * 25 */ 26package gov.nist.javax.sip; 27 28import gov.nist.core.ServerLogger; 29import gov.nist.core.StackLogger; 30import gov.nist.core.net.AddressResolver; 31import gov.nist.core.net.NetworkLayer; 32import gov.nist.core.net.SslNetworkLayer; 33import gov.nist.javax.sip.clientauthutils.AccountManager; 34import gov.nist.javax.sip.clientauthutils.AuthenticationHelper; 35import gov.nist.javax.sip.clientauthutils.AuthenticationHelperImpl; 36import gov.nist.javax.sip.clientauthutils.SecureAccountManager; 37import gov.nist.javax.sip.parser.StringMsgParser; 38import gov.nist.javax.sip.stack.DefaultMessageLogFactory; 39import gov.nist.javax.sip.stack.DefaultRouter; 40import gov.nist.javax.sip.stack.MessageProcessor; 41import gov.nist.javax.sip.stack.SIPTransactionStack; 42 43import java.io.BufferedReader; 44import java.io.IOException; 45import java.io.InputStream; 46import java.io.InputStreamReader; 47import java.lang.reflect.Constructor; 48import java.lang.reflect.InvocationTargetException; 49import java.net.InetAddress; 50import java.util.Hashtable; 51import java.util.LinkedList; 52import java.util.Properties; 53import java.util.StringTokenizer; 54import java.util.concurrent.Semaphore; 55import java.util.concurrent.TimeUnit; 56 57import javax.sip.InvalidArgumentException; 58import javax.sip.ListeningPoint; 59import javax.sip.ObjectInUseException; 60import javax.sip.PeerUnavailableException; 61import javax.sip.ProviderDoesNotExistException; 62import javax.sip.SipException; 63import javax.sip.SipListener; 64import javax.sip.SipProvider; 65import javax.sip.SipStack; 66import javax.sip.TransportNotSupportedException; 67import javax.sip.address.Router; 68import javax.sip.header.HeaderFactory; 69import javax.sip.message.Request; 70 71/** 72 * Implementation of SipStack. 73 * 74 * The JAIN-SIP stack is initialized by a set of properties (see the JAIN SIP 75 * documentation for an explanation of these properties 76 * {@link javax.sip.SipStack} ). In addition to these, the following are 77 * meaningful properties for the NIST SIP stack (specify these in the property 78 * array when you create the JAIN-SIP statck): 79 * <ul> 80 * 81 * <li><b>gov.nist.javax.sip.TRACE_LEVEL = integer </b><br/> 82 * <b> Use of this property is still supported but deprecated. Please use 83 * gov.nist.javax.sip.STACK_LOGGER and gov.nist.javax.sip.SERVER_LOGGER for 84 * integration with logging frameworks and for custom formatting of log records. 85 * </b> This property is used by the built in log4j based logger. You can use 86 * the standard log4j level names here (i.e. ERROR, INFO, WARNING, OFF, DEBUG, 87 * TRACE) If this is set to INFO or above, then incoming valid messages are 88 * logged in SERVER_LOG. If you set this to 32 and specify a DEBUG_LOG then vast 89 * amounts of trace information will be dumped in to the specified DEBUG_LOG. 90 * The server log accumulates the signaling trace. <a href="{@docRoot} 91 * /tools/tracesviewer/tracesviewer.html"> This can be viewed using the trace 92 * viewer tool .</a> Please send us both the server log and debug log when 93 * reporting non-obvious problems. You can also use the strings DEBUG or INFO 94 * for level 32 and 16 respectively. If the value of this property is set to 95 * LOG4J, then the effective log levels are determined from the log4j settings 96 * file (e.g. log4j.properties). The logger name for the stack is specified 97 * using the gov.nist.javax.sip.LOG4J_LOGGER_NAME property. By default log4j 98 * logger name for the stack is the same as the stack name. For example, <code> 99 * properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "LOG4J"); 100 * properties.setProperty("gov.nist.javax.sip.LOG4J_LOGGER_NAME", "SIPStackLogger"); 101 * </code> allows you to now control logging in the stack entirely using log4j 102 * facilities.</li> 103 * 104 * <li><b>gov.nist.javax.sip.LOG_FACTORY = classpath </b> <b> Use of this 105 * property is still supported but deprecated. Please use 106 * gov.nist.javax.sip.STACK_LOGGER and gov.nist.javax.sip.SERVER_LOGGER for 107 * integration with logging frameworks and for custom formatting of log records. 108 * </b> <br/> 109 * The fully qualified classpath for an implementation of the MessageLogFactory. 110 * The stack calls the MessageLogFactory functions to format the log for 111 * messages that are received or sent. This function allows you to log auxiliary 112 * information related to the application or environmental conditions into the 113 * log stream. The log factory must have a default constructor.</li> 114 * 115 * <li><b>gov.nist.javax.sip.SERVER_LOG = fileName </b><br/> 116 * <b> Use of this property is still supported but deprecated. Please use 117 * gov.nist.javax.sip.STACK_LOGGER and gov.nist.javax.sip.SERVER_LOGGER for 118 * integration with logging frameworks and for custom formatting of log records. 119 * </b> Log valid incoming messages here. If this is left null AND the 120 * TRACE_LEVEL is above INFO (or TRACE) then the messages are printed to stdout. 121 * Otherwise messages are logged in a format that can later be viewed using the 122 * trace viewer application which is located in the tools/tracesviewer 123 * directory. <font color=red> Mail this to us with bug reports. </font></li> 124 * 125 * <li><b>gov.nist.javax.sip.DEBUG_LOG = fileName </b> <b> Use of this property 126 * is still supported but deprecated. Please use gov.nist.javax.sip.STACK_LOGGER 127 * and gov.nist.javax.sip.SERVER_LOGGER for integration with logging frameworks 128 * and for custom formatting of log records. </b> <br/> 129 * Where the debug log goes. <font color=red> Mail this to us with bug reports. 130 * </font></li> 131 * 132 * <li><b>gov.nist.javax.sip.LOG_MESSAGE_CONTENT = true|false </b><br/> 133 * Set true if you want to capture content into the log. Default is false. A bad 134 * idea to log content if you are using SIP to push a lot of bytes through TCP.</li> 135 * 136 * <li><b>gov.nist.javax.sip.LOG_STACK_TRACE_ON_MESSAGE_SEND = true|false </b><br/> 137 * Set true if you want to to log a stack trace at INFO level for each message 138 * send. This is really handy for debugging.</li> 139 * 140 * <li><b>gov.nist.javax.sip.STACK_LOGGER = full path name to the class 141 * implementing gov.nist.core.StackLogger interface</b><br/> 142 * If this property is defined the sip stack will try to instantiate it through 143 * a no arg constructor. This allows to use different logging implementations 144 * than the ones provided by default to log what happens within the stack while 145 * processing SIP messages. If this property is not defined, the default sip 146 * stack LogWriter will be used for logging</li> 147 * 148 * <li><b>gov.nist.javax.sip.SERVER_LOGGER = full path name to the class 149 * implementing gov.nist.core.ServerLogger interface</b><br/> 150 * If this property is defined the sip stack will try to instantiate it through 151 * a no arg constructor. This allows to use different logging implementations 152 * than the ones provided by default to log sent/received messages by the sip 153 * stack. If this property is not defined, the default sip stack ServerLog will 154 * be used for logging</li> 155 * 156 * <li><b>gov.nist.javax.sip.AUTOMATIC_DIALOG_ERROR_HANDLING = [true|false] </b> 157 * <br/> 158 * Default is <it>true</it>. This is also settable on a per-provider basis. This 159 * flag is set to true by default. When set 160 * to <it>false</it> the following behaviors are enabled: 161 * 162 * 163 * <li>Turn off Merged requests Loop Detection: The following behavior is turned off 164 * : If the request has no tag in the To header field, the UAS core MUST check 165 * the request against ongoing transactions. If the From tag, Call-ID, and CSeq 166 * exactly match those associated with an ongoing transaction, but the request 167 * does not match that transaction (based on the matching rules in Section 168 * 17.2.3), the UAS core SHOULD generate a 482 (Loop Detected) response and pass 169 * it to the server transaction. 170 * 171 * </ul> 172 * 173 * <li><b>gov.nist.javax.sip.IS_BACK_TO_BACK_USER_AGENT = [true|false] </b> <br/> 174 * Default is <it>false</it> This property controls a setting on the Dialog 175 * objects that the stack manages. Pure B2BUA applications should set this flag 176 * to <it>true</it>. This property can also be set on a per-dialog basis. 177 * Setting this to <it>true</it> imposes serialization on re-INVITE and makes 178 * the sending of re-INVITEs asynchronous. The sending of re-INVITE is 179 * controlled as follows : If the previous in-DIALOG request was an invite 180 * ClientTransaction then the next re-INVITEs that uses the dialog will wait 181 * till an ACK has been sent before admitting the new re-INVITE. If the previous 182 * in-DIALOG transaction was a INVITE ServerTransaction then Dialog waits for 183 * ACK before re-INVITE is allowed to be sent. If a dialog is not ACKed within 184 * 32 seconds, then the dialog is torn down and a BYE sent to the peer.</li> 185 * <li><b>gov.nist.javax.sip.MAX_MESSAGE_SIZE = integer</b> <br/> 186 * Maximum size of content that a TCP connection can read. Must be at least 4K. 187 * Default is "infinity" -- ie. no limit. This is to prevent DOS attacks 188 * launched by writing to a TCP connection until the server chokes.</li> 189 * 190 * <li><b>gov.nist.javax.sip.DELIVER_TERMINATED_EVENT_FOR_NULL_DIALOG = [true|false] </b><br/> 191 * If set to false (the default), the application does NOT get notified when a Dialog in the 192 * NULL state is terminated. ( Dialogs in the NULL state are not associated with an actual SIP Dialog. 193 * They are a programming convenience. A Dialog is in the NULL state before the first response for the 194 * Dialog forming Transaction). If set to true, the SipListener will get a DialogTerminatedEvent 195 * when a Dialog in the NULL state is terminated. 196 * </li> 197 * 198 * <li><b>gov.nist.javax.sip.CACHE_SERVER_CONNECTIONS = [true|false] </b> <br/> 199 * Default value is true. Setting this to false makes the Stack close the server 200 * socket after a Server Transaction goes to the TERMINATED state. This allows a 201 * server to protectect against TCP based Denial of Service attacks launched by 202 * clients (ie. initiate hundreds of client transactions). If true (default 203 * action), the stack will keep the socket open so as to maximize performance at 204 * the expense of Thread and memory resources - leaving itself open to DOS 205 * attacks.</li> 206 * 207 * 208 * <li><b>gov.nist.javax.sip.CACHE_CLIENT_CONNECTIONS = [true|false] </b> <br/> 209 * Default value is true. Setting this to false makes the Stack close the server 210 * socket after a Client Transaction goes to the TERMINATED state. This allows a 211 * client release any buffers threads and socket connections associated with a 212 * client transaction after the transaction has terminated at the expense of 213 * performance.</li> 214 * 215 * <li><b>gov.nist.javax.sip.THREAD_POOL_SIZE = integer </b> <br/> 216 * Concurrency control for number of simultaneous active threads. If 217 * unspecificed, the default is "infinity". This feature is useful if you are 218 * trying to build a container. 219 * <ul> 220 * <li> 221 * <li>If this is not specified, <b> and the listener is re-entrant</b>, each 222 * event delivered to the listener is run in the context of a new thread.</li> 223 * <li>If this is specified and the listener is re-entrant, then the stack will 224 * run the listener using a thread from the thread pool. This allows you to 225 * manage the level of concurrency to a fixed maximum. Threads are pre-allocated 226 * when the stack is instantiated.</li> 227 * <li>If this is specified and the listener is not re-entrant, then the stack 228 * will use the thread pool thread from this pool to parse and manage the state 229 * machine but will run the listener in its own thread.</li> 230 * </ul> 231 * 232 * <li><b>gov.nist.javax.sip.REENTRANT_LISTENER = true|false </b> <br/> 233 * Default is false. Set to true if the listener is re-entrant. If the listener 234 * is re-entrant then the stack manages a thread pool and synchronously calls 235 * the listener from the same thread which read the message. Multiple 236 * transactions may concurrently receive messages and this will result in 237 * multiple threads being active in the listener at the same time. The listener 238 * has to be written with this in mind. <b> If you want good performance on a 239 * multithreaded machine write your listener to be re-entrant and set this 240 * property to be true </b></li> 241 * 242 * <li><b>gov.nist.javax.sip.MAX_CONNECTIONS = integer </b> <br/> 243 * Max number of simultaneous TCP connections handled by stack.</li> 244 * 245 * <li><b>gov.nist.javax.sip.MAX_SERVER_TRANSACTIONS = integer </b> <br/> 246 * Maximum size of server transaction table. The low water mark is 80% of the 247 * high water mark. Requests are selectively dropped in the lowater mark to 248 * highwater mark range. Requests are unconditionally accepted if the table is 249 * smaller than the low water mark. The default highwater mark is 5000</li> 250 * 251 * <li><b>gov.nist.javax.sip.MAX_CLIENT_TRANSACTIONS = integer </b> <br/> 252 * Max number of active client transactions before the caller blocks and waits 253 * for the number to drop below a threshold. Default is unlimited, i.e. the 254 * caller never blocks and waits for a client transaction to become available 255 * (i.e. it does its own resource management in the application).</li> 256 * 257 * <li><b>gov.nist.javax.sip.PASS_INVITE_NON_2XX_ACK_TO_LISTENER = true|false 258 * </b> <br/> 259 * If true then the listener will see the ACK for non-2xx responses for server 260 * transactions. This is not standard behavior per RFC 3261 (INVITE server 261 * transaction state machine) but this is a useful flag for testing. The TCK 262 * uses this flag for example.</li> 263 * 264 * <li><b>gov.nist.javax.sip.MAX_LISTENER_RESPONSE_TIME = Integer </b> <br/> 265 * Max time (seconds) before sending a response to a server transaction. If a 266 * response is not sent within this time period, the transaction will be deleted 267 * by the stack. Default time is "infinity" - i.e. if the listener never 268 * responds, the stack will hang on to a reference for the transaction and 269 * result in a memory leak. 270 * 271 * <li><b>gov.nist.javax.sip.DELIVER_TERMINATED_EVENT_FOR_ACK = [true|false]</b> 272 * <br/> 273 * Default is <it>false</it>. ACK Server Transaction is a Pseuedo-transaction. 274 * If you want termination notification on ACK transactions (so all server 275 * transactions can be handled uniformly in user code during cleanup), then set 276 * this flag to <it>true</it>.</li> 277 * 278 * <li><b>gov.nist.javax.sip.READ_TIMEOUT = integer </b> <br/> 279 * This is relevant for incoming TCP connections to prevent starvation at the 280 * server. This defines the timeout in miliseconds between successive reads 281 * after the first byte of a SIP message is read by the stack. All the sip 282 * headers must be delivered in this interval and each successive buffer must be 283 * of the content delivered in this interval. Default value is -1 (ie. the stack 284 * is wide open to starvation attacks) and the client can be as slow as it wants 285 * to be.</li> 286 * 287 * <li><b>gov.nist.javax.sip.NETWORK_LAYER = classpath </b> <br/> 288 * This is an EXPERIMENTAL property (still under active devlopment). Defines a 289 * network layer that allows a client to have control over socket allocations 290 * and monitoring of socket activity. A network layer should implement 291 * gov.nist.core.net.NetworkLayer. The default implementation simply acts as a 292 * wrapper for the standard java.net socket layer. This functionality is still 293 * under active development (may be extended to support security and other 294 * features).</li> 295 * 296 * <li><b>gov.nist.javax.sip.ADDRESS_RESOLVER = classpath </b><br/> 297 * The fully qualified class path for an implementation of the AddressResolver 298 * interface. The AddressResolver allows you to support lookup schemes for 299 * addresses that are not directly resolvable to IP adresses using 300 * getHostByName. Specifying your own address resolver allows you to customize 301 * address lookup. The default address resolver is a pass-through address 302 * resolver (i.e. just returns the input string without doing a resolution). See 303 * gov.nist.javax.sip.DefaultAddressResolver.</li> 304 * 305 * <li><b>gov.nist.javax.sip.AUTO_GENERATE_TIMESTAMP= [true| false] </b><br/> 306 * (default is false) Automatically generate a getTimeOfDay timestamp for a 307 * retransmitted request if the original request contained a timestamp. This is 308 * useful for profiling.</li> 309 * 310 * <li><b>gov.nist.javax.sip.THREAD_AUDIT_INTERVAL_IN_MILLISECS = long </b> <br/> 311 * Defines how often the application intends to audit the SIP Stack about the 312 * health of its internal threads (the property specifies the time in 313 * miliseconds between successive audits). The audit allows the application to 314 * detect catastrophic failures like an internal thread terminating because of 315 * an exception or getting stuck in a deadlock condition. Events like these will 316 * make the stack inoperable and therefore require immediate action from the 317 * application layer (e.g., alarms, traps, reboot, failover, etc.) Thread audits 318 * are disabled by default. If this property is not specified, audits will 319 * remain disabled. An example of how to use this property is in 320 * src/examples/threadaudit.</li> 321 * 322 * 323 * 324 * <li><b>gov.nist.javax.sip.COMPUTE_CONTENT_LENGTH_FROM_MESSAGE_BODY = 325 * [true|false] </b> <br/> 326 * Default is <it>false</it> If set to <it>true</it>, when you are creating a 327 * message from a <it>String</it>, the MessageFactory will compute the content 328 * length from the message content and ignore the provided content length 329 * parameter in the Message. Otherwise, it will use the content length supplied 330 * and generate a parse exception if the content is truncated. 331 * 332 * <li><b>gov.nist.javax.sip.CANCEL_CLIENT_TRANSACTION_CHECKED = [true|false] 333 * </b> <br/> 334 * Default is <it>true</it>. This flag is added in support of load balancers or 335 * failover managers where you may want to cancel ongoing transactions from a 336 * different stack than the original stack. If set to <it>false</it> then the 337 * CANCEL client transaction is not checked for the existence of the INVITE or 338 * the state of INVITE when you send the CANCEL request. Hence you can CANCEL an 339 * INVITE from a different stack than the INVITE. You can also create a CANCEL 340 * client transaction late and send it out after the INVITE server transaction 341 * has been Terminated. Clearly this will result in protocol errors. Setting the 342 * flag to true ( default ) enables you to avoid common protocol errors.</li> 343 * 344 * <li><b>gov.nist.javax.sip.IS_BACK_TO_BACK_USER_AGENT = [true|false] </b> <br/> 345 * Default is <it>false</it> This property controls a setting on the Dialog 346 * objects that the stack manages. Pure B2BUA applications should set this flag 347 * to <it>true</it>. This property can also be set on a per-dialog basis. 348 * Setting this to <it>true</it> imposes serialization on re-INVITE and makes 349 * the sending of re-INVITEs asynchronous. The sending of re-INVITE is 350 * controlled as follows : If the previous in-DIALOG request was an invite 351 * ClientTransaction then the next re-INVITEs that uses the dialog will wait 352 * till an ACK has been sent before admitting the new re-INVITE. If the previous 353 * in-DIALOG transaction was a INVITE ServerTransaction then Dialog waits for 354 * ACK before re-INVITE is allowed to be sent. If a dialog is not ACKed within 355 * 32 seconds, then the dialog is torn down and a BYE sent to the peer.</li> 356 * 357 * 358 * <li><b>gov.nist.javax.sip.RECEIVE_UDP_BUFFER_SIZE = int </b> <br/> 359 * Default is <it>8*1024</it>. This property control the size of the UDP buffer 360 * used for SIP messages. Under load, if the buffer capacity is overflown the 361 * messages are dropped causing retransmissions, further increasing the load and 362 * causing even more retransmissions. Good values to this property for servers 363 * is a big number in the order of 8*8*1024.</li> 364 * 365 * <li><b>gov.nist.javax.sip.SEND_UDP_BUFFER_SIZE = int </b> <br/> 366 * Default is <it>8*1024</it>. This property control the size of the UDP buffer 367 * used for SIP messages. Under load, if the buffer capacity is overflown the 368 * messages are dropped causing retransmissions, further increasing the load and 369 * causing even more retransmissions. Good values to this property for servers 370 * is a big number in the order of 8*8*1024 or higher.</li> 371 * 372 * <li><b>gov.nist.javax.sip.CONGESTION_CONTROL_ENABLED = boolean </b> Defailt 373 * is true. If set to true stack will enforce queue length limitation for UDP. 374 * The Max queue size is 5000 messages. The minimum queue size is 2500 messages. 375 * </li> 376 * 377 * <li><b>gov.nist.javax.sip.DELIVER_UNSOLICITED_NOTIFY = [true|false] </b> <br/> 378 * Default is <it>false</it>. This flag is added to allow Sip Listeners to 379 * receive all NOTIFY requests including those that are not part of a valid 380 * dialog.</li> 381 * 382 * <li><b>gov.nist.javax.sip.REJECT_STRAY_RESPONSES = [true|false] </b> Default 383 * is <it>false</it> A flag that checks responses to test whether the response 384 * corresponds to a via header that was previously generated by us. Note that 385 * setting this flag implies that the stack will take control over setting the 386 * VIA header for Sip Requests sent through the stack. The stack will attach a 387 * suffix to the VIA header branch and check any response arriving at the stack 388 * to see if that response suffix is present. If it is not present, then the 389 * stack will silently drop the response.</li> 390 * 391 * <li><b>gov.nist.javax.sip.MAX_FORK_TIME_SECONDS = integer </b> Maximum time for which the original 392 * transaction for which a forked response is received is tracked. This property 393 * is only relevant to Dialog Stateful applications ( User Agents or B2BUA). 394 * When a forked response is received in this time interval from when the original 395 * INVITE client transaction was sent, the stack will place the original INVITE 396 * client transction in the ResponseEventExt and deliver that to the application. 397 * The event handler can get the original transaction from this event. </li> 398 * 399 * * <li><b>gov.nist.javax.sip.TLS_CLIENT_PROTOCOLS = String </b> 400 * Comma-separated list of protocols to use when creating outgoing TLS connections. 401 * The default is "SSLv3, SSLv2Hello, TLSv1". 402 * Some servers do not support SSLv2Hello, so override to "SSLv3, TLSv1". 403 * </li> 404 405 * <li><b>javax.net.ssl.keyStore = fileName </b> <br/> 406 * Default is <it>NULL</it>. If left undefined the keyStore and trustStore will 407 * be left to the java runtime defaults. If defined, any TLS sockets created 408 * (client and server) will use the key store provided in the fileName. The 409 * trust store will default to the same store file. A password must be provided 410 * to access the keyStore using the following property: <br> 411 * <code> 412 * properties.setProperty("javax.net.ssl.keyStorePassword", "<password>"); 413 * </code> <br> 414 * The trust store can be changed, to a separate file with the following 415 * setting: <br> 416 * <code> 417 * properties.setProperty("javax.net.ssl.trustStore", "<trustStoreFileName location>"); 418 * </code> <br> 419 * If the trust store property is provided the password on the trust store must 420 * be the same as the key store. <br> 421 * <br> 422 * <b> Note that the stack supports the extensions that are defined in 423 * SipStackExt. These will be supported in the next release of JAIN-SIP. You 424 * should only use the extensions that are defined in this class. </b> 425 * 426 * 427 * @version 1.2 $Revision: 1.115 $ $Date: 2010/01/10 00:13:14 $ 428 * 429 * @author M. Ranganathan <br/> 430 * 431 * 432 * 433 * 434 */ 435public class SipStackImpl extends SIPTransactionStack implements 436 javax.sip.SipStack, SipStackExt { 437 438 private EventScanner eventScanner; 439 440 private Hashtable<String, ListeningPointImpl> listeningPoints; 441 442 private LinkedList<SipProviderImpl> sipProviders; 443 444 /** 445 * Max datagram size. 446 */ 447 public static final Integer MAX_DATAGRAM_SIZE = 8 * 1024; 448 449 // Flag to indicate that the listener is re-entrant and hence 450 // Use this flag with caution. 451 boolean reEntrantListener; 452 453 SipListener sipListener; 454 455 // If set to true then a transaction terminated event is 456 // delivered for ACK transactions. 457 boolean deliverTerminatedEventForAck = false; 458 459 // If set to true then the application want to receive 460 // unsolicited NOTIFYs, ie NOTIFYs that don't match any dialog 461 boolean deliverUnsolicitedNotify = false; 462 463 // Stack semaphore (global lock). 464 private Semaphore stackSemaphore = new Semaphore(1); 465 466 // RFC3261: TLS_RSA_WITH_AES_128_CBC_SHA MUST be supported 467 // RFC3261: TLS_RSA_WITH_3DES_EDE_CBC_SHA SHOULD be supported for backwards 468 // compat 469 private String[] cipherSuites = { 470 "TLS_RSA_WITH_AES_128_CBC_SHA", // AES difficult to get with 471 // c++/Windows 472 // "TLS_RSA_WITH_3DES_EDE_CBC_SHA", // Unsupported by Sun impl, 473 "SSL_RSA_WITH_3DES_EDE_CBC_SHA", // For backwards comp., C++ 474 475 // JvB: patch from Sebastien Mazy, issue with mismatching 476 // ciphersuites 477 "TLS_DH_anon_WITH_AES_128_CBC_SHA", 478 "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA", }; 479 480 // Supported protocols for TLS client: can be overridden by application 481 private String[] enabledProtocols = { 482 "SSLv3", 483 "SSLv2Hello", 484 "TLSv1" 485 }; 486 487 /** 488 * Creates a new instance of SipStackImpl. 489 */ 490 491 protected SipStackImpl() { 492 super(); 493 NistSipMessageFactoryImpl msgFactory = new NistSipMessageFactoryImpl( 494 this); 495 super.setMessageFactory(msgFactory); 496 this.eventScanner = new EventScanner(this); 497 this.listeningPoints = new Hashtable<String, ListeningPointImpl>(); 498 this.sipProviders = new LinkedList<SipProviderImpl>(); 499 500 } 501 502 /** 503 * ReInitialize the stack instance. 504 */ 505 private void reInitialize() { 506 super.reInit(); 507 this.eventScanner = new EventScanner(this); 508 this.listeningPoints = new Hashtable<String, ListeningPointImpl>(); 509 this.sipProviders = new LinkedList<SipProviderImpl>(); 510 this.sipListener = null; 511 512 } 513 514 /** 515 * Return true if automatic dialog support is enabled for this stack. 516 * 517 * @return boolean, true if automatic dialog support is enabled for this 518 * stack 519 */ 520 boolean isAutomaticDialogSupportEnabled() { 521 return super.isAutomaticDialogSupportEnabled; 522 } 523 524 /** 525 * Constructor for the stack. 526 * 527 * @param configurationProperties 528 * -- stack configuration properties including NIST-specific 529 * extensions. 530 * @throws PeerUnavailableException 531 */ 532 public SipStackImpl(Properties configurationProperties) 533 throws PeerUnavailableException { 534 this(); 535 String address = configurationProperties 536 .getProperty("javax.sip.IP_ADDRESS"); 537 try { 538 /** Retrieve the stack IP address */ 539 if (address != null) { 540 // In version 1.2 of the spec the IP address is 541 // associated with the listening point and 542 // is not madatory. 543 super.setHostAddress(address); 544 545 } 546 } catch (java.net.UnknownHostException ex) { 547 throw new PeerUnavailableException("bad address " + address); 548 } 549 550 /** Retrieve the stack name */ 551 String name = configurationProperties 552 .getProperty("javax.sip.STACK_NAME"); 553 if (name == null) 554 throw new PeerUnavailableException("stack name is missing"); 555 super.setStackName(name); 556 String stackLoggerClassName = configurationProperties 557 .getProperty("gov.nist.javax.sip.STACK_LOGGER"); 558 // To log debug messages. 559 if (stackLoggerClassName == null) 560 stackLoggerClassName = "gov.nist.core.LogWriter"; 561 try { 562 Class<?> stackLoggerClass = Class.forName(stackLoggerClassName); 563 Class<?>[] constructorArgs = new Class[0]; 564 Constructor<?> cons = stackLoggerClass 565 .getConstructor(constructorArgs); 566 Object[] args = new Object[0]; 567 StackLogger stackLogger = (StackLogger) cons.newInstance(args); 568 stackLogger.setStackProperties(configurationProperties); 569 super.setStackLogger(stackLogger); 570 } catch (InvocationTargetException ex1) { 571 throw new IllegalArgumentException( 572 "Cound not instantiate stack logger " 573 + stackLoggerClassName 574 + "- check that it is present on the classpath and that there is a no-args constructor defined", 575 ex1); 576 } catch (Exception ex) { 577 throw new IllegalArgumentException( 578 "Cound not instantiate stack logger " 579 + stackLoggerClassName 580 + "- check that it is present on the classpath and that there is a no-args constructor defined", 581 ex); 582 } 583 584 String serverLoggerClassName = configurationProperties 585 .getProperty("gov.nist.javax.sip.SERVER_LOGGER"); 586 // To log debug messages. 587 if (serverLoggerClassName == null) 588 serverLoggerClassName = "gov.nist.javax.sip.stack.ServerLog"; 589 try { 590 Class<?> serverLoggerClass = Class 591 .forName(serverLoggerClassName); 592 Class<?>[] constructorArgs = new Class[0]; 593 Constructor<?> cons = serverLoggerClass 594 .getConstructor(constructorArgs); 595 Object[] args = new Object[0]; 596 this.serverLogger = (ServerLogger) cons.newInstance(args); 597 serverLogger.setSipStack(this); 598 serverLogger.setStackProperties(configurationProperties); 599 } catch (InvocationTargetException ex1) { 600 throw new IllegalArgumentException( 601 "Cound not instantiate server logger " 602 + stackLoggerClassName 603 + "- check that it is present on the classpath and that there is a no-args constructor defined", 604 ex1); 605 } catch (Exception ex) { 606 throw new IllegalArgumentException( 607 "Cound not instantiate server logger " 608 + stackLoggerClassName 609 + "- check that it is present on the classpath and that there is a no-args constructor defined", 610 ex); 611 } 612 613 // Default router -- use this for routing SIP URIs. 614 // Our router does not do DNS lookups. 615 this.outboundProxy = configurationProperties 616 .getProperty("javax.sip.OUTBOUND_PROXY"); 617 618 this.defaultRouter = new DefaultRouter(this, outboundProxy); 619 620 /** Retrieve the router path */ 621 String routerPath = configurationProperties 622 .getProperty("javax.sip.ROUTER_PATH"); 623 if (routerPath == null) 624 routerPath = "gov.nist.javax.sip.stack.DefaultRouter"; 625 626 try { 627 Class<?> routerClass = Class.forName(routerPath); 628 Class<?>[] constructorArgs = new Class[2]; 629 constructorArgs[0] = javax.sip.SipStack.class; 630 constructorArgs[1] = String.class; 631 Constructor<?> cons = routerClass.getConstructor(constructorArgs); 632 Object[] args = new Object[2]; 633 args[0] = (SipStack) this; 634 args[1] = outboundProxy; 635 Router router = (Router) cons.newInstance(args); 636 super.setRouter(router); 637 } catch (InvocationTargetException ex1) { 638 getStackLogger() 639 .logError( 640 "could not instantiate router -- invocation target problem", 641 (Exception) ex1.getCause()); 642 throw new PeerUnavailableException( 643 "Cound not instantiate router - check constructor", ex1); 644 } catch (Exception ex) { 645 getStackLogger().logError("could not instantiate router", 646 (Exception) ex.getCause()); 647 throw new PeerUnavailableException("Could not instantiate router", 648 ex); 649 } 650 651 // The flag that indicates that the default router is to be ignored. 652 String useRouterForAll = configurationProperties 653 .getProperty("javax.sip.USE_ROUTER_FOR_ALL_URIS"); 654 this.useRouterForAll = true; 655 if (useRouterForAll != null) { 656 this.useRouterForAll = "true".equalsIgnoreCase(useRouterForAll); 657 } 658 659 /* 660 * Retrieve the EXTENSION Methods. These are used for instantiation of 661 * Dialogs. 662 */ 663 String extensionMethods = configurationProperties 664 .getProperty("javax.sip.EXTENSION_METHODS"); 665 666 if (extensionMethods != null) { 667 java.util.StringTokenizer st = new java.util.StringTokenizer( 668 extensionMethods); 669 while (st.hasMoreTokens()) { 670 String em = st.nextToken(":"); 671 if (em.equalsIgnoreCase(Request.BYE) 672 || em.equalsIgnoreCase(Request.INVITE) 673 || em.equalsIgnoreCase(Request.SUBSCRIBE) 674 || em.equalsIgnoreCase(Request.NOTIFY) 675 || em.equalsIgnoreCase(Request.ACK) 676 || em.equalsIgnoreCase(Request.OPTIONS)) 677 throw new PeerUnavailableException("Bad extension method " 678 + em); 679 else 680 this.addExtensionMethod(em); 681 } 682 } 683 String keyStoreFile = configurationProperties 684 .getProperty("javax.net.ssl.keyStore"); 685 String trustStoreFile = configurationProperties 686 .getProperty("javax.net.ssl.trustStore"); 687 if (keyStoreFile != null) { 688 if (trustStoreFile == null) { 689 trustStoreFile = keyStoreFile; 690 } 691 String keyStorePassword = configurationProperties 692 .getProperty("javax.net.ssl.keyStorePassword"); 693 try { 694 this.networkLayer = new SslNetworkLayer(trustStoreFile, 695 keyStoreFile, keyStorePassword.toCharArray(), 696 configurationProperties 697 .getProperty("javax.net.ssl.keyStoreType")); 698 } catch (Exception e1) { 699 getStackLogger().logError( 700 "could not instantiate SSL networking", e1); 701 } 702 } 703 704 // Set the auto dialog support flag. 705 super.isAutomaticDialogSupportEnabled = configurationProperties 706 .getProperty("javax.sip.AUTOMATIC_DIALOG_SUPPORT", "on") 707 .equalsIgnoreCase("on"); 708 709 super.isAutomaticDialogErrorHandlingEnabled = configurationProperties 710 .getProperty("gov.nist.javax.sip.AUTOMATIC_DIALOG_ERROR_HANDLING","true") 711 .equals(Boolean.TRUE.toString()); 712 if ( super.isAutomaticDialogSupportEnabled ) { 713 super.isAutomaticDialogErrorHandlingEnabled = true; 714 } 715 716 if (configurationProperties 717 .getProperty("gov.nist.javax.sip.MAX_LISTENER_RESPONSE_TIME") != null) { 718 super.maxListenerResponseTime = Integer 719 .parseInt(configurationProperties 720 .getProperty("gov.nist.javax.sip.MAX_LISTENER_RESPONSE_TIME")); 721 if (super.maxListenerResponseTime <= 0) 722 throw new PeerUnavailableException( 723 "Bad configuration parameter gov.nist.javax.sip.MAX_LISTENER_RESPONSE_TIME : should be positive"); 724 } else { 725 super.maxListenerResponseTime = -1; 726 } 727 728 729 730 this.deliverTerminatedEventForAck = configurationProperties 731 .getProperty( 732 "gov.nist.javax.sip.DELIVER_TERMINATED_EVENT_FOR_ACK", 733 "false").equalsIgnoreCase("true"); 734 735 this.deliverUnsolicitedNotify = configurationProperties.getProperty( 736 "gov.nist.javax.sip.DELIVER_UNSOLICITED_NOTIFY", "false") 737 .equalsIgnoreCase("true"); 738 739 String forkedSubscriptions = configurationProperties 740 .getProperty("javax.sip.FORKABLE_EVENTS"); 741 if (forkedSubscriptions != null) { 742 StringTokenizer st = new StringTokenizer(forkedSubscriptions); 743 while (st.hasMoreTokens()) { 744 String nextEvent = st.nextToken(); 745 this.forkedEvents.add(nextEvent); 746 } 747 } 748 749 // The following features are unique to the NIST implementation. 750 751 /* 752 * gets the NetworkLayer implementation, if any. Note that this is a 753 * NIST only feature. 754 */ 755 756 final String NETWORK_LAYER_KEY = "gov.nist.javax.sip.NETWORK_LAYER"; 757 758 if (configurationProperties.containsKey(NETWORK_LAYER_KEY)) { 759 String path = configurationProperties 760 .getProperty(NETWORK_LAYER_KEY); 761 try { 762 Class<?> clazz = Class.forName(path); 763 Constructor<?> c = clazz.getConstructor(new Class[0]); 764 networkLayer = (NetworkLayer) c.newInstance(new Object[0]); 765 } catch (Exception e) { 766 throw new PeerUnavailableException( 767 "can't find or instantiate NetworkLayer implementation: " 768 + path); 769 } 770 } 771 772 final String ADDRESS_RESOLVER_KEY = "gov.nist.javax.sip.ADDRESS_RESOLVER"; 773 774 if (configurationProperties.containsKey(ADDRESS_RESOLVER_KEY)) { 775 String path = configurationProperties 776 .getProperty(ADDRESS_RESOLVER_KEY); 777 try { 778 Class<?> clazz = Class.forName(path); 779 Constructor<?> c = clazz.getConstructor(new Class[0]); 780 this.addressResolver = (AddressResolver) c 781 .newInstance(new Object[0]); 782 } catch (Exception e) { 783 throw new PeerUnavailableException( 784 "can't find or instantiate AddressResolver implementation: " 785 + path); 786 } 787 } 788 789 String maxConnections = configurationProperties 790 .getProperty("gov.nist.javax.sip.MAX_CONNECTIONS"); 791 if (maxConnections != null) { 792 try { 793 this.maxConnections = new Integer(maxConnections).intValue(); 794 } catch (NumberFormatException ex) { 795 if (isLoggingEnabled()) 796 getStackLogger().logError( 797 "max connections - bad value " + ex.getMessage()); 798 } 799 } 800 801 String threadPoolSize = configurationProperties 802 .getProperty("gov.nist.javax.sip.THREAD_POOL_SIZE"); 803 if (threadPoolSize != null) { 804 try { 805 this.threadPoolSize = new Integer(threadPoolSize).intValue(); 806 } catch (NumberFormatException ex) { 807 if (isLoggingEnabled()) 808 this.getStackLogger().logError( 809 "thread pool size - bad value " + ex.getMessage()); 810 } 811 } 812 813 String serverTransactionTableSize = configurationProperties 814 .getProperty("gov.nist.javax.sip.MAX_SERVER_TRANSACTIONS"); 815 if (serverTransactionTableSize != null) { 816 try { 817 this.serverTransactionTableHighwaterMark = new Integer( 818 serverTransactionTableSize).intValue(); 819 this.serverTransactionTableLowaterMark = this.serverTransactionTableHighwaterMark * 80 / 100; 820 // Lowater is 80% of highwater 821 } catch (NumberFormatException ex) { 822 if (isLoggingEnabled()) 823 this.getStackLogger() 824 .logError( 825 "transaction table size - bad value " 826 + ex.getMessage()); 827 } 828 } else { 829 // Issue 256 : consistent with MAX_CLIENT_TRANSACTIONS, if the MAX_SERVER_TRANSACTIONS is not set 830 // we assume the transaction table size can grow unlimited 831 this.unlimitedServerTransactionTableSize = true; 832 } 833 834 String clientTransactionTableSize = configurationProperties 835 .getProperty("gov.nist.javax.sip.MAX_CLIENT_TRANSACTIONS"); 836 if (clientTransactionTableSize != null) { 837 try { 838 this.clientTransactionTableHiwaterMark = new Integer( 839 clientTransactionTableSize).intValue(); 840 this.clientTransactionTableLowaterMark = this.clientTransactionTableLowaterMark * 80 / 100; 841 // Lowater is 80% of highwater 842 } catch (NumberFormatException ex) { 843 if (isLoggingEnabled()) 844 this.getStackLogger() 845 .logError( 846 "transaction table size - bad value " 847 + ex.getMessage()); 848 } 849 } else { 850 this.unlimitedClientTransactionTableSize = true; 851 } 852 853 super.cacheServerConnections = true; 854 String flag = configurationProperties 855 .getProperty("gov.nist.javax.sip.CACHE_SERVER_CONNECTIONS"); 856 857 if (flag != null && "false".equalsIgnoreCase(flag.trim())) { 858 super.cacheServerConnections = false; 859 } 860 861 super.cacheClientConnections = true; 862 String cacheflag = configurationProperties 863 .getProperty("gov.nist.javax.sip.CACHE_CLIENT_CONNECTIONS"); 864 865 if (cacheflag != null && "false".equalsIgnoreCase(cacheflag.trim())) { 866 super.cacheClientConnections = false; 867 } 868 869 String readTimeout = configurationProperties 870 .getProperty("gov.nist.javax.sip.READ_TIMEOUT"); 871 if (readTimeout != null) { 872 try { 873 874 int rt = Integer.parseInt(readTimeout); 875 if (rt >= 100) { 876 super.readTimeout = rt; 877 } else { 878 System.err.println("Value too low " + readTimeout); 879 } 880 } catch (NumberFormatException nfe) { 881 // Ignore. 882 if (isLoggingEnabled()) 883 getStackLogger().logError("Bad read timeout " + readTimeout); 884 } 885 } 886 887 // Get the address of the stun server. 888 889 String stunAddr = configurationProperties 890 .getProperty("gov.nist.javax.sip.STUN_SERVER"); 891 892 if (stunAddr != null) 893 this.getStackLogger().logWarning( 894 "Ignoring obsolete property " 895 + "gov.nist.javax.sip.STUN_SERVER"); 896 897 String maxMsgSize = configurationProperties 898 .getProperty("gov.nist.javax.sip.MAX_MESSAGE_SIZE"); 899 900 try { 901 if (maxMsgSize != null) { 902 super.maxMessageSize = new Integer(maxMsgSize).intValue(); 903 if (super.maxMessageSize < 4096) 904 super.maxMessageSize = 4096; 905 } else { 906 // Allow for "infinite" size of message 907 super.maxMessageSize = 0; 908 } 909 } catch (NumberFormatException ex) { 910 if (isLoggingEnabled()) 911 getStackLogger().logError( 912 "maxMessageSize - bad value " + ex.getMessage()); 913 } 914 915 String rel = configurationProperties 916 .getProperty("gov.nist.javax.sip.REENTRANT_LISTENER"); 917 this.reEntrantListener = (rel != null && "true".equalsIgnoreCase(rel)); 918 919 // Check if a thread audit interval is specified 920 String interval = configurationProperties 921 .getProperty("gov.nist.javax.sip.THREAD_AUDIT_INTERVAL_IN_MILLISECS"); 922 if (interval != null) { 923 try { 924 // Make the monitored threads ping the auditor twice as fast as 925 // the audits 926 getThreadAuditor().setPingIntervalInMillisecs( 927 Long.valueOf(interval).longValue() / 2); 928 } catch (NumberFormatException ex) { 929 if (isLoggingEnabled()) 930 getStackLogger().logError( 931 "THREAD_AUDIT_INTERVAL_IN_MILLISECS - bad value [" 932 + interval + "] " + ex.getMessage()); 933 } 934 } 935 936 // JvB: added property for testing 937 this 938 .setNon2XXAckPassedToListener(Boolean 939 .valueOf( 940 configurationProperties 941 .getProperty( 942 "gov.nist.javax.sip.PASS_INVITE_NON_2XX_ACK_TO_LISTENER", 943 "false")).booleanValue()); 944 945 this.generateTimeStampHeader = Boolean.valueOf( 946 configurationProperties.getProperty( 947 "gov.nist.javax.sip.AUTO_GENERATE_TIMESTAMP", "false")) 948 .booleanValue(); 949 950 String messageLogFactoryClasspath = configurationProperties 951 .getProperty("gov.nist.javax.sip.LOG_FACTORY"); 952 if (messageLogFactoryClasspath != null) { 953 try { 954 Class<?> clazz = Class.forName(messageLogFactoryClasspath); 955 Constructor<?> c = clazz.getConstructor(new Class[0]); 956 this.logRecordFactory = (LogRecordFactory) c 957 .newInstance(new Object[0]); 958 } catch (Exception ex) { 959 if (isLoggingEnabled()) 960 getStackLogger() 961 .logError( 962 "Bad configuration value for LOG_FACTORY -- using default logger"); 963 this.logRecordFactory = new DefaultMessageLogFactory(); 964 } 965 966 } else { 967 this.logRecordFactory = new DefaultMessageLogFactory(); 968 } 969 970 boolean computeContentLength = configurationProperties.getProperty( 971 "gov.nist.javax.sip.COMPUTE_CONTENT_LENGTH_FROM_MESSAGE_BODY", 972 "false").equalsIgnoreCase("true"); 973 StringMsgParser 974 .setComputeContentLengthFromMessage(computeContentLength); 975 976 String tlsClientProtocols = configurationProperties.getProperty( 977 "gov.nist.javax.sip.TLS_CLIENT_PROTOCOLS"); 978 if (tlsClientProtocols != null) 979 { 980 StringTokenizer st = new StringTokenizer(tlsClientProtocols, " ,"); 981 String[] protocols = new String[st.countTokens()]; 982 983 int i=0; 984 while (st.hasMoreTokens()) { 985 protocols[i++] = st.nextToken(); 986 } 987 this.enabledProtocols = protocols; 988 } 989 990 super.rfc2543Supported = configurationProperties.getProperty( 991 "gov.nist.javax.sip.RFC_2543_SUPPORT_ENABLED", "true") 992 .equalsIgnoreCase("true"); 993 994 super.cancelClientTransactionChecked = configurationProperties 995 .getProperty( 996 "gov.nist.javax.sip.CANCEL_CLIENT_TRANSACTION_CHECKED", 997 "true").equalsIgnoreCase("true"); 998 super.logStackTraceOnMessageSend = configurationProperties.getProperty( 999 "gov.nist.javax.sip.LOG_STACK_TRACE_ON_MESSAGE_SEND", "false") 1000 .equalsIgnoreCase("true"); 1001 if (isLoggingEnabled()) 1002 getStackLogger().logDebug( 1003 "created Sip stack. Properties = " + configurationProperties); 1004 InputStream in = getClass().getResourceAsStream("/TIMESTAMP"); 1005 if (in != null) { 1006 BufferedReader streamReader = new BufferedReader( 1007 new InputStreamReader(in)); 1008 1009 try { 1010 String buildTimeStamp = streamReader.readLine(); 1011 if (in != null) { 1012 in.close(); 1013 } 1014 getStackLogger().setBuildTimeStamp(buildTimeStamp); 1015 } catch (IOException ex) { 1016 getStackLogger().logError("Could not open build timestamp."); 1017 } 1018 } 1019 1020 String bufferSize = configurationProperties.getProperty( 1021 "gov.nist.javax.sip.RECEIVE_UDP_BUFFER_SIZE", MAX_DATAGRAM_SIZE 1022 .toString()); 1023 int bufferSizeInteger = new Integer(bufferSize).intValue(); 1024 super.setReceiveUdpBufferSize(bufferSizeInteger); 1025 1026 bufferSize = configurationProperties.getProperty( 1027 "gov.nist.javax.sip.SEND_UDP_BUFFER_SIZE", MAX_DATAGRAM_SIZE 1028 .toString()); 1029 bufferSizeInteger = new Integer(bufferSize).intValue(); 1030 super.setSendUdpBufferSize(bufferSizeInteger); 1031 1032 boolean congetstionControlEnabled = Boolean 1033 .parseBoolean(configurationProperties.getProperty( 1034 "gov.nist.javax.sip.CONGESTION_CONTROL_ENABLED", 1035 Boolean.TRUE.toString())); 1036 super.stackDoesCongestionControl = congetstionControlEnabled; 1037 1038 super.isBackToBackUserAgent = Boolean 1039 .parseBoolean(configurationProperties.getProperty( 1040 "gov.nist.javax.sip.IS_BACK_TO_BACK_USER_AGENT", 1041 Boolean.FALSE.toString())); 1042 super.checkBranchId = Boolean.parseBoolean(configurationProperties 1043 .getProperty("gov.nist.javax.sip.REJECT_STRAY_RESPONSES", 1044 Boolean.FALSE.toString())); 1045 1046 super.isDialogTerminatedEventDeliveredForNullDialog = (Boolean.parseBoolean(configurationProperties.getProperty("gov.nist.javax.sip.DELIVER_TERMINATED_EVENT_FOR_NULL_DIALOG", 1047 Boolean.FALSE.toString()))); 1048 1049 1050 super.maxForkTime = Integer.parseInt( 1051 configurationProperties.getProperty("gov.nist.javax.sip.MAX_FORK_TIME_SECONDS","0")); 1052 1053 } 1054 1055 /* 1056 * (non-Javadoc) 1057 * 1058 * @see javax.sip.SipStack#createListeningPoint(java.lang.String, int, 1059 * java.lang.String) 1060 */ 1061 public synchronized ListeningPoint createListeningPoint(String address, 1062 int port, String transport) throws TransportNotSupportedException, 1063 InvalidArgumentException { 1064 if (isLoggingEnabled()) 1065 getStackLogger().logDebug( 1066 "createListeningPoint : address = " + address + " port = " 1067 + port + " transport = " + transport); 1068 1069 if (address == null) 1070 throw new NullPointerException( 1071 "Address for listening point is null!"); 1072 if (transport == null) 1073 throw new NullPointerException("null transport"); 1074 if (port <= 0) 1075 throw new InvalidArgumentException("bad port"); 1076 1077 if (!transport.equalsIgnoreCase("UDP") 1078 && !transport.equalsIgnoreCase("TLS") 1079 && !transport.equalsIgnoreCase("TCP") 1080 && !transport.equalsIgnoreCase("SCTP")) 1081 throw new TransportNotSupportedException("bad transport " 1082 + transport); 1083 1084 /** Reusing an old stack instance */ 1085 if (!this.isAlive()) { 1086 this.toExit = false; 1087 this.reInitialize(); 1088 } 1089 1090 String key = ListeningPointImpl.makeKey(address, port, transport); 1091 1092 ListeningPointImpl lip = (ListeningPointImpl) listeningPoints.get(key); 1093 if (lip != null) { 1094 return lip; 1095 } else { 1096 try { 1097 InetAddress inetAddr = InetAddress.getByName(address); 1098 MessageProcessor messageProcessor = this 1099 .createMessageProcessor(inetAddr, port, transport); 1100 if (this.isLoggingEnabled()) { 1101 this.getStackLogger().logDebug( 1102 "Created Message Processor: " + address 1103 + " port = " + port + " transport = " 1104 + transport); 1105 } 1106 lip = new ListeningPointImpl(this, port, transport); 1107 lip.messageProcessor = messageProcessor; 1108 messageProcessor.setListeningPoint(lip); 1109 this.listeningPoints.put(key, lip); 1110 // start processing messages. 1111 messageProcessor.start(); 1112 return (ListeningPoint) lip; 1113 } catch (java.io.IOException ex) { 1114 if (isLoggingEnabled()) 1115 getStackLogger().logError( 1116 "Invalid argument address = " + address + " port = " 1117 + port + " transport = " + transport); 1118 throw new InvalidArgumentException(ex.getMessage(), ex); 1119 } 1120 } 1121 } 1122 1123 /* 1124 * (non-Javadoc) 1125 * 1126 * @see javax.sip.SipStack#createSipProvider(javax.sip.ListeningPoint) 1127 */ 1128 public SipProvider createSipProvider(ListeningPoint listeningPoint) 1129 throws ObjectInUseException { 1130 if (listeningPoint == null) 1131 throw new NullPointerException("null listeningPoint"); 1132 if (this.isLoggingEnabled()) 1133 this.getStackLogger().logDebug( 1134 "createSipProvider: " + listeningPoint); 1135 ListeningPointImpl listeningPointImpl = (ListeningPointImpl) listeningPoint; 1136 if (listeningPointImpl.sipProvider != null) 1137 throw new ObjectInUseException("Provider already attached!"); 1138 1139 SipProviderImpl provider = new SipProviderImpl(this); 1140 1141 provider.setListeningPoint(listeningPointImpl); 1142 listeningPointImpl.sipProvider = provider; 1143 this.sipProviders.add(provider); 1144 return provider; 1145 } 1146 1147 /* 1148 * (non-Javadoc) 1149 * 1150 * @see javax.sip.SipStack#deleteListeningPoint(javax.sip.ListeningPoint) 1151 */ 1152 public void deleteListeningPoint(ListeningPoint listeningPoint) 1153 throws ObjectInUseException { 1154 if (listeningPoint == null) 1155 throw new NullPointerException("null listeningPoint arg"); 1156 ListeningPointImpl lip = (ListeningPointImpl) listeningPoint; 1157 // Stop the message processing thread in the listening point. 1158 super.removeMessageProcessor(lip.messageProcessor); 1159 String key = lip.getKey(); 1160 this.listeningPoints.remove(key); 1161 1162 } 1163 1164 /* 1165 * (non-Javadoc) 1166 * 1167 * @see javax.sip.SipStack#deleteSipProvider(javax.sip.SipProvider) 1168 */ 1169 public void deleteSipProvider(SipProvider sipProvider) 1170 throws ObjectInUseException { 1171 1172 if (sipProvider == null) 1173 throw new NullPointerException("null provider arg"); 1174 SipProviderImpl sipProviderImpl = (SipProviderImpl) sipProvider; 1175 1176 // JvB: API doc is not clear, but in_use == 1177 // sipProviderImpl.sipListener!=null 1178 // so we should throw if app did not call removeSipListener 1179 // sipProviderImpl.sipListener = null; 1180 if (sipProviderImpl.getSipListener() != null) { 1181 throw new ObjectInUseException( 1182 "SipProvider still has an associated SipListener!"); 1183 } 1184 1185 sipProviderImpl.removeListeningPoints(); 1186 1187 // Bug reported by Rafael Barriuso 1188 sipProviderImpl.stop(); 1189 sipProviders.remove(sipProvider); 1190 if (sipProviders.isEmpty()) { 1191 this.stopStack(); 1192 } 1193 } 1194 1195 /** 1196 * Get the IP Address of the stack. 1197 * 1198 * @see javax.sip.SipStack#getIPAddress() 1199 * @deprecated 1200 */ 1201 public String getIPAddress() { 1202 return super.getHostAddress(); 1203 } 1204 1205 /* 1206 * (non-Javadoc) 1207 * 1208 * @see javax.sip.SipStack#getListeningPoints() 1209 */ 1210 public java.util.Iterator getListeningPoints() { 1211 return this.listeningPoints.values().iterator(); 1212 } 1213 1214 /** 1215 * Return true if retransmission filter is active. 1216 * 1217 * @see javax.sip.SipStack#isRetransmissionFilterActive() 1218 * @deprecated 1219 */ 1220 public boolean isRetransmissionFilterActive() { 1221 return true; 1222 } 1223 1224 /* 1225 * (non-Javadoc) 1226 * 1227 * @see javax.sip.SipStack#getSipProviders() 1228 */ 1229 public java.util.Iterator<SipProviderImpl> getSipProviders() { 1230 return this.sipProviders.iterator(); 1231 } 1232 1233 /* 1234 * (non-Javadoc) 1235 * 1236 * @see javax.sip.SipStack#getStackName() 1237 */ 1238 public String getStackName() { 1239 return this.stackName; 1240 } 1241 1242 /** 1243 * Finalization -- stop the stack on finalization. Exit the transaction 1244 * scanner and release all resources. 1245 * 1246 * @see java.lang.Object#finalize() 1247 */ 1248 protected void finalize() { 1249 this.stopStack(); 1250 } 1251 1252 /** 1253 * This uses the default stack address to create a listening point. 1254 * 1255 * @see javax.sip.SipStack#createListeningPoint(java.lang.String, int, 1256 * java.lang.String) 1257 * @deprecated 1258 */ 1259 public ListeningPoint createListeningPoint(int port, String transport) 1260 throws TransportNotSupportedException, InvalidArgumentException { 1261 if (super.stackAddress == null) 1262 throw new NullPointerException( 1263 "Stack does not have a default IP Address!"); 1264 return this.createListeningPoint(super.stackAddress, port, transport); 1265 } 1266 1267 /* 1268 * (non-Javadoc) 1269 * 1270 * @see javax.sip.SipStack#stop() 1271 */ 1272 public void stop() { 1273 if (isLoggingEnabled()) { 1274 getStackLogger().logDebug("stopStack -- stoppping the stack"); 1275 } 1276 this.stopStack(); 1277 this.sipProviders = new LinkedList<SipProviderImpl>(); 1278 this.listeningPoints = new Hashtable<String, ListeningPointImpl>(); 1279 /* 1280 * Check for presence of an event scanner ( may happen if stack is 1281 * stopped before listener is attached ). 1282 */ 1283 if (this.eventScanner != null) 1284 this.eventScanner.forceStop(); 1285 this.eventScanner = null; 1286 1287 } 1288 1289 /* 1290 * (non-Javadoc) 1291 * 1292 * @see javax.sip.SipStack#start() 1293 */ 1294 public void start() throws ProviderDoesNotExistException, SipException { 1295 // Start a new event scanner if one does not exist. 1296 if (this.eventScanner == null) { 1297 this.eventScanner = new EventScanner(this); 1298 } 1299 1300 } 1301 1302 /** 1303 * Get the listener for the stack. A stack can have only one listener. To 1304 * get an event from a provider, the listener has to be registered with the 1305 * provider. The SipListener is application code. 1306 * 1307 * @return -- the stack SipListener 1308 * 1309 */ 1310 public SipListener getSipListener() { 1311 return this.sipListener; 1312 } 1313 1314 /** 1315 * Get the message log factory registered with the stack. 1316 * 1317 * @return -- the messageLogFactory of the stack. 1318 */ 1319 public LogRecordFactory getLogRecordFactory() { 1320 return super.logRecordFactory; 1321 } 1322 1323 /** 1324 * Set the log appender ( this is useful if you want to specify a particular 1325 * log format or log to something other than a file for example). This method 1326 * is will be removed May 11, 2010 or shortly there after. 1327 * 1328 * @param Appender 1329 * - the log4j appender to add. 1330 * @deprecated TODO: remove this method May 11, 2010. 1331 */ 1332 // BEGIN android-deleted 1333 /* 1334 @Deprecated 1335 public void addLogAppender(org.apache.log4j.Appender appender) { 1336 if (this.getStackLogger() instanceof gov.nist.core.LogWriter) { 1337 ((gov.nist.core.LogWriter) this.getStackLogger()).addAppender(appender); 1338 } 1339 } 1340 */ 1341 // END android-deleted 1342 1343 /** 1344 * Get the log4j logger ( for log stream integration ). 1345 * This method will be removed May 11, 2010 or shortly there after. 1346 * 1347 * @return the log4j logger. 1348 * @deprecated TODO: This method will be removed May 11, 2010. 1349 */ 1350 @Deprecated 1351 // BEGIN andoird-deleted 1352 /* 1353 public org.apache.log4j.Logger getLogger() { 1354 if (this.getStackLogger() instanceof gov.nist.core.LogWriter) { 1355 return ((gov.nist.core.LogWriter) this.getStackLogger()).getLogger(); 1356 } 1357 return null; 1358 } 1359 */ 1360 // END android-deleted 1361 1362 public EventScanner getEventScanner() { 1363 return eventScanner; 1364 } 1365 1366 /* 1367 * (non-Javadoc) 1368 * 1369 * @see 1370 * gov.nist.javax.sip.SipStackExt#getAuthenticationHelper(gov.nist.javax 1371 * .sip.clientauthutils.AccountManager, javax.sip.header.HeaderFactory) 1372 */ 1373 public AuthenticationHelper getAuthenticationHelper( 1374 AccountManager accountManager, HeaderFactory headerFactory) { 1375 return new AuthenticationHelperImpl(this, accountManager, headerFactory); 1376 } 1377 1378 /* 1379 * (non-Javadoc) 1380 * 1381 * @see 1382 * gov.nist.javax.sip.SipStackExt#getAuthenticationHelper(gov.nist.javax 1383 * .sip.clientauthutils.AccountManager, javax.sip.header.HeaderFactory) 1384 */ 1385 public AuthenticationHelper getSecureAuthenticationHelper( 1386 SecureAccountManager accountManager, HeaderFactory headerFactory) { 1387 return new AuthenticationHelperImpl(this, accountManager, headerFactory); 1388 } 1389 1390 /** 1391 * Set the list of cipher suites supported by the stack. A stack can have 1392 * only one set of suites. These are not validated against the supported 1393 * cipher suites of the java runtime, so specifying a cipher here does not 1394 * guarantee that it will work.<br> 1395 * The stack has a default cipher suite of: 1396 * <ul> 1397 * <li>TLS_RSA_WITH_AES_128_CBC_SHA</li> 1398 * <li>SSL_RSA_WITH_3DES_EDE_CBC_SHA</li> 1399 * <li>TLS_DH_anon_WITH_AES_128_CBC_SHA</li> 1400 * <li>SSL_DH_anon_WITH_3DES_EDE_CBC_SHA</li> 1401 * </ul> 1402 * 1403 * <b>NOTE: This function must be called before adding a TLS listener</b> 1404 * 1405 * @param String 1406 * [] The new set of ciphers to support. 1407 * @return 1408 * 1409 */ 1410 public void setEnabledCipherSuites(String[] newCipherSuites) { 1411 cipherSuites = newCipherSuites; 1412 } 1413 1414 /** 1415 * Return the currently enabled cipher suites of the Stack. 1416 * 1417 * @return The currently enabled cipher suites. 1418 */ 1419 public String[] getEnabledCipherSuites() { 1420 return cipherSuites; 1421 } 1422 1423 /** 1424 * Set the list of protocols supported by the stack for outgoing TLS connections. 1425 * A stack can have only one set of protocols. 1426 * These are not validated against the supported 1427 * protocols of the java runtime, so specifying a protocol here does not 1428 * guarantee that it will work.<br> 1429 * The stack has a default protocol suite of: 1430 * <ul> 1431 * <li>SSLv3</li> 1432 * <li>SSLv2Hello</li> 1433 * <li>TLSv1</li> 1434 * </ul> 1435 * 1436 * <b>NOTE: This function must be called before creating a TLSMessageChannel.</b> 1437 * 1438 * @param String 1439 * [] The new set of protocols to use for outgoing TLS connections. 1440 * @return 1441 * 1442 */ 1443 public void setEnabledProtocols(String[] newProtocols) { 1444 enabledProtocols = newProtocols; 1445 } 1446 1447 /** 1448 * Return the currently enabled protocols to use when creating TLS connection. 1449 * 1450 * @return The currently enabled protocols. 1451 */ 1452 public String[] getEnabledProtocols() { 1453 return enabledProtocols; 1454 } 1455 1456 /** 1457 * Set the "back to back User Agent" flag. 1458 * 1459 * @param flag 1460 * - boolean flag to set. 1461 * 1462 */ 1463 public void setIsBackToBackUserAgent(boolean flag) { 1464 super.isBackToBackUserAgent = flag; 1465 } 1466 1467 /** 1468 * Get the "back to back User Agent" flag. 1469 * 1470 * return the value of the flag 1471 * 1472 */ 1473 public boolean isBackToBackUserAgent() { 1474 return super.isBackToBackUserAgent; 1475 } 1476 1477 public boolean isAutomaticDialogErrorHandlingEnabled() { 1478 return super.isAutomaticDialogErrorHandlingEnabled; 1479 } 1480 1481 public boolean acquireSem() { 1482 try { 1483 return this.stackSemaphore.tryAcquire(10, TimeUnit.SECONDS); 1484 } catch ( InterruptedException ex) { 1485 return false; 1486 } 1487 } 1488 1489 public void releaseSem() { 1490 this.stackSemaphore.release(); 1491 } 1492 1493 1494 1495 1496} 1497