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 Wangpackage gov.nist.javax.sip;
27600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
28600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.core.ServerLogger;
29600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.core.StackLogger;
30600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.core.net.AddressResolver;
31600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.core.net.NetworkLayer;
32600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.core.net.SslNetworkLayer;
33600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.clientauthutils.AccountManager;
34600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.clientauthutils.AuthenticationHelper;
35600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.clientauthutils.AuthenticationHelperImpl;
36600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.clientauthutils.SecureAccountManager;
37600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.parser.StringMsgParser;
38600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.stack.DefaultMessageLogFactory;
39600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.stack.DefaultRouter;
40600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.stack.MessageProcessor;
41600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.stack.SIPTransactionStack;
42600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
43600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.io.BufferedReader;
44600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.io.IOException;
45600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.io.InputStream;
46600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.io.InputStreamReader;
47600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.lang.reflect.Constructor;
48600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.lang.reflect.InvocationTargetException;
49600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.net.InetAddress;
50600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.Hashtable;
51600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.LinkedList;
52600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.Properties;
53600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.StringTokenizer;
54600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.concurrent.Semaphore;
55600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.concurrent.TimeUnit;
56600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
57600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.InvalidArgumentException;
58600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.ListeningPoint;
59600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.ObjectInUseException;
60600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.PeerUnavailableException;
61600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.ProviderDoesNotExistException;
62600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.SipException;
63600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.SipListener;
64600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.SipProvider;
65600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.SipStack;
66600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.TransportNotSupportedException;
67600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.address.Router;
68600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.HeaderFactory;
69600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.message.Request;
70600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
71600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/**
72600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Implementation of SipStack.
73600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
74600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * The JAIN-SIP stack is initialized by a set of properties (see the JAIN SIP
75600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * documentation for an explanation of these properties
76600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * {@link javax.sip.SipStack} ). In addition to these, the following are
77600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * meaningful properties for the NIST SIP stack (specify these in the property
78600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * array when you create the JAIN-SIP statck):
79600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <ul>
80600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
81600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li><b>gov.nist.javax.sip.TRACE_LEVEL = integer </b><br/>
82600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <b> Use of this property is still supported but deprecated. Please use
83600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * gov.nist.javax.sip.STACK_LOGGER and gov.nist.javax.sip.SERVER_LOGGER for
84600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * integration with logging frameworks and for custom formatting of log records.
85600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * </b> This property is used by the built in log4j based logger. You can use
86600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * the standard log4j level names here (i.e. ERROR, INFO, WARNING, OFF, DEBUG,
87600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * TRACE) If this is set to INFO or above, then incoming valid messages are
88600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * logged in SERVER_LOG. If you set this to 32 and specify a DEBUG_LOG then vast
89600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * amounts of trace information will be dumped in to the specified DEBUG_LOG.
90600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * The server log accumulates the signaling trace. <a href="{@docRoot}
91600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * /tools/tracesviewer/tracesviewer.html"> This can be viewed using the trace
92600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * viewer tool .</a> Please send us both the server log and debug log when
93600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * reporting non-obvious problems. You can also use the strings DEBUG or INFO
94600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * for level 32 and 16 respectively. If the value of this property is set to
95600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * LOG4J, then the effective log levels are determined from the log4j settings
96600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * file (e.g. log4j.properties). The logger name for the stack is specified
97600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * using the gov.nist.javax.sip.LOG4J_LOGGER_NAME property. By default log4j
98600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * logger name for the stack is the same as the stack name. For example, <code>
99600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "LOG4J");
100600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * properties.setProperty("gov.nist.javax.sip.LOG4J_LOGGER_NAME", "SIPStackLogger");
101600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * </code> allows you to now control logging in the stack entirely using log4j
102600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * facilities.</li>
103600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
104600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li><b>gov.nist.javax.sip.LOG_FACTORY = classpath </b> <b> Use of this
105600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * property is still supported but deprecated. Please use
106600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * gov.nist.javax.sip.STACK_LOGGER and gov.nist.javax.sip.SERVER_LOGGER for
107600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * integration with logging frameworks and for custom formatting of log records.
108600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * </b> <br/>
109600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * The fully qualified classpath for an implementation of the MessageLogFactory.
110600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * The stack calls the MessageLogFactory functions to format the log for
111600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * messages that are received or sent. This function allows you to log auxiliary
112600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * information related to the application or environmental conditions into the
113600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * log stream. The log factory must have a default constructor.</li>
114600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
115600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li><b>gov.nist.javax.sip.SERVER_LOG = fileName </b><br/>
116600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <b> Use of this property is still supported but deprecated. Please use
117600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * gov.nist.javax.sip.STACK_LOGGER and gov.nist.javax.sip.SERVER_LOGGER for
118600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * integration with logging frameworks and for custom formatting of log records.
119600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * </b> Log valid incoming messages here. If this is left null AND the
120600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * TRACE_LEVEL is above INFO (or TRACE) then the messages are printed to stdout.
121600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Otherwise messages are logged in a format that can later be viewed using the
122600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * trace viewer application which is located in the tools/tracesviewer
123600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * directory. <font color=red> Mail this to us with bug reports. </font></li>
124600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
125600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li><b>gov.nist.javax.sip.DEBUG_LOG = fileName </b> <b> Use of this property
126600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * is still supported but deprecated. Please use gov.nist.javax.sip.STACK_LOGGER
127600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * and gov.nist.javax.sip.SERVER_LOGGER for integration with logging frameworks
128600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * and for custom formatting of log records. </b> <br/>
129600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Where the debug log goes. <font color=red> Mail this to us with bug reports.
130600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * </font></li>
131600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
132600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li><b>gov.nist.javax.sip.LOG_MESSAGE_CONTENT = true|false </b><br/>
133600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Set true if you want to capture content into the log. Default is false. A bad
134600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * idea to log content if you are using SIP to push a lot of bytes through TCP.</li>
135600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
136600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li><b>gov.nist.javax.sip.LOG_STACK_TRACE_ON_MESSAGE_SEND = true|false </b><br/>
137600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Set true if you want to to log a stack trace at INFO level for each message
138600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * send. This is really handy for debugging.</li>
139600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
140600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li><b>gov.nist.javax.sip.STACK_LOGGER = full path name to the class
141600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * implementing gov.nist.core.StackLogger interface</b><br/>
142600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * If this property is defined the sip stack will try to instantiate it through
143600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * a no arg constructor. This allows to use different logging implementations
144600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * than the ones provided by default to log what happens within the stack while
145600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * processing SIP messages. If this property is not defined, the default sip
146600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * stack LogWriter will be used for logging</li>
147600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
148600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li><b>gov.nist.javax.sip.SERVER_LOGGER = full path name to the class
149600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * implementing gov.nist.core.ServerLogger interface</b><br/>
150600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * If this property is defined the sip stack will try to instantiate it through
151600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * a no arg constructor. This allows to use different logging implementations
152600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * than the ones provided by default to log sent/received messages by the sip
153600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * stack. If this property is not defined, the default sip stack ServerLog will
154600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * be used for logging</li>
155600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
156600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li><b>gov.nist.javax.sip.AUTOMATIC_DIALOG_ERROR_HANDLING = [true|false] </b>
157600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <br/>
158600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Default is <it>true</it>. This is also settable on a per-provider basis. This
159600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * flag is set to true by default. When set
160600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * to <it>false</it> the following behaviors are enabled:
161600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
162600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
163600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li>Turn off Merged requests Loop Detection: The following behavior is turned off
164600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * : If the request has no tag in the To header field, the UAS core MUST check
165600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * the request against ongoing transactions. If the From tag, Call-ID, and CSeq
166600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * exactly match those associated with an ongoing transaction, but the request
167600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * does not match that transaction (based on the matching rules in Section
168600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 17.2.3), the UAS core SHOULD generate a 482 (Loop Detected) response and pass
169600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * it to the server transaction.
170600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
171600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * </ul>
172600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
173600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li><b>gov.nist.javax.sip.IS_BACK_TO_BACK_USER_AGENT = [true|false] </b> <br/>
174600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Default is <it>false</it> This property controls a setting on the Dialog
175600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * objects that the stack manages. Pure B2BUA applications should set this flag
176600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * to <it>true</it>. This property can also be set on a per-dialog basis.
177600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Setting this to <it>true</it> imposes serialization on re-INVITE and makes
178600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * the sending of re-INVITEs asynchronous. The sending of re-INVITE is
179600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * controlled as follows : If the previous in-DIALOG request was an invite
180600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * ClientTransaction then the next re-INVITEs that uses the dialog will wait
181600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * till an ACK has been sent before admitting the new re-INVITE. If the previous
182600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * in-DIALOG transaction was a INVITE ServerTransaction then Dialog waits for
183600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * ACK before re-INVITE is allowed to be sent. If a dialog is not ACKed within
184600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 32 seconds, then the dialog is torn down and a BYE sent to the peer.</li>
185600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li><b>gov.nist.javax.sip.MAX_MESSAGE_SIZE = integer</b> <br/>
186600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Maximum size of content that a TCP connection can read. Must be at least 4K.
187600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Default is "infinity" -- ie. no limit. This is to prevent DOS attacks
188600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * launched by writing to a TCP connection until the server chokes.</li>
189600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
190600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li><b>gov.nist.javax.sip.DELIVER_TERMINATED_EVENT_FOR_NULL_DIALOG = [true|false] </b><br/>
191600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * If set to false (the default), the application does NOT get notified when a Dialog in the
192600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * NULL state is terminated. ( Dialogs in the NULL state are not associated with an actual SIP Dialog.
193600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * They are a programming convenience. A Dialog is in the NULL state before the first response for the
194600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Dialog forming Transaction). If set to true, the SipListener will get a DialogTerminatedEvent
195600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * when a Dialog in the NULL state is terminated.
196600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * </li>
197600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
198600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li><b>gov.nist.javax.sip.CACHE_SERVER_CONNECTIONS = [true|false] </b> <br/>
199600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Default value is true. Setting this to false makes the Stack close the server
200600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * socket after a Server Transaction goes to the TERMINATED state. This allows a
201600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * server to protectect against TCP based Denial of Service attacks launched by
202600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * clients (ie. initiate hundreds of client transactions). If true (default
203600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * action), the stack will keep the socket open so as to maximize performance at
204600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * the expense of Thread and memory resources - leaving itself open to DOS
205600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * attacks.</li>
206600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
207600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
208600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li><b>gov.nist.javax.sip.CACHE_CLIENT_CONNECTIONS = [true|false] </b> <br/>
209600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Default value is true. Setting this to false makes the Stack close the server
210600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * socket after a Client Transaction goes to the TERMINATED state. This allows a
211600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * client release any buffers threads and socket connections associated with a
212600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * client transaction after the transaction has terminated at the expense of
213600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * performance.</li>
214600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
215600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li><b>gov.nist.javax.sip.THREAD_POOL_SIZE = integer </b> <br/>
216600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Concurrency control for number of simultaneous active threads. If
217600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * unspecificed, the default is "infinity". This feature is useful if you are
218600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * trying to build a container.
219600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <ul>
220600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li>
221600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li>If this is not specified, <b> and the listener is re-entrant</b>, each
222600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * event delivered to the listener is run in the context of a new thread.</li>
223600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li>If this is specified and the listener is re-entrant, then the stack will
224600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * run the listener using a thread from the thread pool. This allows you to
225600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * manage the level of concurrency to a fixed maximum. Threads are pre-allocated
226600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * when the stack is instantiated.</li>
227600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li>If this is specified and the listener is not re-entrant, then the stack
228600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * will use the thread pool thread from this pool to parse and manage the state
229600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * machine but will run the listener in its own thread.</li>
230600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * </ul>
231600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
232600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li><b>gov.nist.javax.sip.REENTRANT_LISTENER = true|false </b> <br/>
233600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Default is false. Set to true if the listener is re-entrant. If the listener
234600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * is re-entrant then the stack manages a thread pool and synchronously calls
235600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * the listener from the same thread which read the message. Multiple
236600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * transactions may concurrently receive messages and this will result in
237600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * multiple threads being active in the listener at the same time. The listener
238600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * has to be written with this in mind. <b> If you want good performance on a
239600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * multithreaded machine write your listener to be re-entrant and set this
240600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * property to be true </b></li>
241600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
242600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li><b>gov.nist.javax.sip.MAX_CONNECTIONS = integer </b> <br/>
243600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Max number of simultaneous TCP connections handled by stack.</li>
244600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
245600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li><b>gov.nist.javax.sip.MAX_SERVER_TRANSACTIONS = integer </b> <br/>
246600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Maximum size of server transaction table. The low water mark is 80% of the
247600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * high water mark. Requests are selectively dropped in the lowater mark to
248600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * highwater mark range. Requests are unconditionally accepted if the table is
249600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * smaller than the low water mark. The default highwater mark is 5000</li>
250600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
251600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li><b>gov.nist.javax.sip.MAX_CLIENT_TRANSACTIONS = integer </b> <br/>
252600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Max number of active client transactions before the caller blocks and waits
253600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * for the number to drop below a threshold. Default is unlimited, i.e. the
254600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * caller never blocks and waits for a client transaction to become available
255600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * (i.e. it does its own resource management in the application).</li>
256600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
257600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li><b>gov.nist.javax.sip.PASS_INVITE_NON_2XX_ACK_TO_LISTENER = true|false
258600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * </b> <br/>
259600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * If true then the listener will see the ACK for non-2xx responses for server
260600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * transactions. This is not standard behavior per RFC 3261 (INVITE server
261600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * transaction state machine) but this is a useful flag for testing. The TCK
262600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * uses this flag for example.</li>
263600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
264600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li><b>gov.nist.javax.sip.MAX_LISTENER_RESPONSE_TIME = Integer </b> <br/>
265600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Max time (seconds) before sending a response to a server transaction. If a
266600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * response is not sent within this time period, the transaction will be deleted
267600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * by the stack. Default time is "infinity" - i.e. if the listener never
268600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * responds, the stack will hang on to a reference for the transaction and
269600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * result in a memory leak.
270600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
271600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li><b>gov.nist.javax.sip.DELIVER_TERMINATED_EVENT_FOR_ACK = [true|false]</b>
272600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <br/>
273600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Default is <it>false</it>. ACK Server Transaction is a Pseuedo-transaction.
274600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * If you want termination notification on ACK transactions (so all server
275600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * transactions can be handled uniformly in user code during cleanup), then set
276600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * this flag to <it>true</it>.</li>
277600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
278600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li><b>gov.nist.javax.sip.READ_TIMEOUT = integer </b> <br/>
279600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * This is relevant for incoming TCP connections to prevent starvation at the
280600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * server. This defines the timeout in miliseconds between successive reads
281600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * after the first byte of a SIP message is read by the stack. All the sip
282600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * headers must be delivered in this interval and each successive buffer must be
283600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * of the content delivered in this interval. Default value is -1 (ie. the stack
284600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * is wide open to starvation attacks) and the client can be as slow as it wants
285600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * to be.</li>
286600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
287600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li><b>gov.nist.javax.sip.NETWORK_LAYER = classpath </b> <br/>
288600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * This is an EXPERIMENTAL property (still under active devlopment). Defines a
289600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * network layer that allows a client to have control over socket allocations
290600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * and monitoring of socket activity. A network layer should implement
291600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * gov.nist.core.net.NetworkLayer. The default implementation simply acts as a
292600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * wrapper for the standard java.net socket layer. This functionality is still
293600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * under active development (may be extended to support security and other
294600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * features).</li>
295600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
296600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li><b>gov.nist.javax.sip.ADDRESS_RESOLVER = classpath </b><br/>
297600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * The fully qualified class path for an implementation of the AddressResolver
298600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * interface. The AddressResolver allows you to support lookup schemes for
299600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * addresses that are not directly resolvable to IP adresses using
300600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * getHostByName. Specifying your own address resolver allows you to customize
301600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * address lookup. The default address resolver is a pass-through address
302600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * resolver (i.e. just returns the input string without doing a resolution). See
303600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * gov.nist.javax.sip.DefaultAddressResolver.</li>
304600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
305600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li><b>gov.nist.javax.sip.AUTO_GENERATE_TIMESTAMP= [true| false] </b><br/>
306600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * (default is false) Automatically generate a getTimeOfDay timestamp for a
307600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * retransmitted request if the original request contained a timestamp. This is
308600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * useful for profiling.</li>
309600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
310600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li><b>gov.nist.javax.sip.THREAD_AUDIT_INTERVAL_IN_MILLISECS = long </b> <br/>
311600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Defines how often the application intends to audit the SIP Stack about the
312600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * health of its internal threads (the property specifies the time in
313600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * miliseconds between successive audits). The audit allows the application to
314600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * detect catastrophic failures like an internal thread terminating because of
315600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * an exception or getting stuck in a deadlock condition. Events like these will
316600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * make the stack inoperable and therefore require immediate action from the
317600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * application layer (e.g., alarms, traps, reboot, failover, etc.) Thread audits
318600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * are disabled by default. If this property is not specified, audits will
319600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * remain disabled. An example of how to use this property is in
320600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * src/examples/threadaudit.</li>
321600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
322600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
323600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
324600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li><b>gov.nist.javax.sip.COMPUTE_CONTENT_LENGTH_FROM_MESSAGE_BODY =
325600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * [true|false] </b> <br/>
326600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Default is <it>false</it> If set to <it>true</it>, when you are creating a
327600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * message from a <it>String</it>, the MessageFactory will compute the content
328600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * length from the message content and ignore the provided content length
329600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * parameter in the Message. Otherwise, it will use the content length supplied
330600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * and generate a parse exception if the content is truncated.
331600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
332600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li><b>gov.nist.javax.sip.CANCEL_CLIENT_TRANSACTION_CHECKED = [true|false]
333600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * </b> <br/>
334600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Default is <it>true</it>. This flag is added in support of load balancers or
335600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * failover managers where you may want to cancel ongoing transactions from a
336600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * different stack than the original stack. If set to <it>false</it> then the
337600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * CANCEL client transaction is not checked for the existence of the INVITE or
338600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * the state of INVITE when you send the CANCEL request. Hence you can CANCEL an
339600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * INVITE from a different stack than the INVITE. You can also create a CANCEL
340600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * client transaction late and send it out after the INVITE server transaction
341600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * has been Terminated. Clearly this will result in protocol errors. Setting the
342600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * flag to true ( default ) enables you to avoid common protocol errors.</li>
343600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
344600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li><b>gov.nist.javax.sip.IS_BACK_TO_BACK_USER_AGENT = [true|false] </b> <br/>
345600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Default is <it>false</it> This property controls a setting on the Dialog
346600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * objects that the stack manages. Pure B2BUA applications should set this flag
347600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * to <it>true</it>. This property can also be set on a per-dialog basis.
348600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Setting this to <it>true</it> imposes serialization on re-INVITE and makes
349600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * the sending of re-INVITEs asynchronous. The sending of re-INVITE is
350600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * controlled as follows : If the previous in-DIALOG request was an invite
351600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * ClientTransaction then the next re-INVITEs that uses the dialog will wait
352600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * till an ACK has been sent before admitting the new re-INVITE. If the previous
353600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * in-DIALOG transaction was a INVITE ServerTransaction then Dialog waits for
354600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * ACK before re-INVITE is allowed to be sent. If a dialog is not ACKed within
355600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 32 seconds, then the dialog is torn down and a BYE sent to the peer.</li>
356600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
357600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
358600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li><b>gov.nist.javax.sip.RECEIVE_UDP_BUFFER_SIZE = int </b> <br/>
359600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Default is <it>8*1024</it>. This property control the size of the UDP buffer
360600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * used for SIP messages. Under load, if the buffer capacity is overflown the
361600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * messages are dropped causing retransmissions, further increasing the load and
362600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * causing even more retransmissions. Good values to this property for servers
363600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * is a big number in the order of 8*8*1024.</li>
364600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
365600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li><b>gov.nist.javax.sip.SEND_UDP_BUFFER_SIZE = int </b> <br/>
366600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Default is <it>8*1024</it>. This property control the size of the UDP buffer
367600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * used for SIP messages. Under load, if the buffer capacity is overflown the
368600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * messages are dropped causing retransmissions, further increasing the load and
369600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * causing even more retransmissions. Good values to this property for servers
370600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * is a big number in the order of 8*8*1024 or higher.</li>
371600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
372600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li><b>gov.nist.javax.sip.CONGESTION_CONTROL_ENABLED = boolean </b> Defailt
373600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * is true. If set to true stack will enforce queue length limitation for UDP.
374600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * The Max queue size is 5000 messages. The minimum queue size is 2500 messages.
375600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * </li>
376600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
377600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li><b>gov.nist.javax.sip.DELIVER_UNSOLICITED_NOTIFY = [true|false] </b> <br/>
378600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Default is <it>false</it>. This flag is added to allow Sip Listeners to
379600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * receive all NOTIFY requests including those that are not part of a valid
380600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * dialog.</li>
381600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
382600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li><b>gov.nist.javax.sip.REJECT_STRAY_RESPONSES = [true|false] </b> Default
383600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * is <it>false</it> A flag that checks responses to test whether the response
384600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * corresponds to a via header that was previously generated by us. Note that
385600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * setting this flag implies that the stack will take control over setting the
386600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * VIA header for Sip Requests sent through the stack. The stack will attach a
387600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * suffix to the VIA header branch and check any response arriving at the stack
388600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * to see if that response suffix is present. If it is not present, then the
389600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * stack will silently drop the response.</li>
390600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
391600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li><b>gov.nist.javax.sip.MAX_FORK_TIME_SECONDS = integer </b> Maximum time for which the original
392600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * transaction for which a forked response is received is tracked. This property
393600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * is only relevant to Dialog Stateful applications ( User Agents or B2BUA).
394600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * When a forked response is received in this time interval from when the original
395600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * INVITE client transaction was sent, the stack will place the original INVITE
396600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * client transction in the ResponseEventExt and deliver that to the application.
397600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * The event handler can get the original transaction from this event. </li>
398600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
399600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *  * <li><b>gov.nist.javax.sip.TLS_CLIENT_PROTOCOLS = String </b>
400600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *  Comma-separated list of protocols to use when creating outgoing TLS connections.
401600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *  The default is "SSLv3, SSLv2Hello, TLSv1".
402600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *  Some servers do not support SSLv2Hello, so override to "SSLv3, TLSv1".
403600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * </li>
404600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
405600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li><b>javax.net.ssl.keyStore = fileName </b> <br/>
406600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Default is <it>NULL</it>. If left undefined the keyStore and trustStore will
407600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * be left to the java runtime defaults. If defined, any TLS sockets created
408600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * (client and server) will use the key store provided in the fileName. The
409600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * trust store will default to the same store file. A password must be provided
410600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * to access the keyStore using the following property: <br>
411600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <code>
412600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * properties.setProperty("javax.net.ssl.keyStorePassword", "&lt;password&gt;");
413600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * </code> <br>
414600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * The trust store can be changed, to a separate file with the following
415600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * setting: <br>
416600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <code>
417600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * properties.setProperty("javax.net.ssl.trustStore", "&lt;trustStoreFileName location&gt;");
418600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * </code> <br>
419600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * If the trust store property is provided the password on the trust store must
420600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * be the same as the key store. <br>
421600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <br>
422600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <b> Note that the stack supports the extensions that are defined in
423600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * SipStackExt. These will be supported in the next release of JAIN-SIP. You
424600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * should only use the extensions that are defined in this class. </b>
425600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
426600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
427600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @version 1.2 $Revision: 1.115 $ $Date: 2010/01/10 00:13:14 $
428600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
429600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @author M. Ranganathan <br/>
430600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
431600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
432600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
433600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
434600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */
435600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangpublic class SipStackImpl extends SIPTransactionStack implements
436600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		javax.sip.SipStack, SipStackExt {
437600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
438600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	private EventScanner eventScanner;
439600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
440600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	private Hashtable<String, ListeningPointImpl> listeningPoints;
441600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
442600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	private LinkedList<SipProviderImpl> sipProviders;
443600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
444600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	/**
445600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * Max datagram size.
446600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 */
447600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	public static final Integer MAX_DATAGRAM_SIZE = 8 * 1024;
448600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
449600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	// Flag to indicate that the listener is re-entrant and hence
450600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	// Use this flag with caution.
451600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	boolean reEntrantListener;
452600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
453600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	SipListener sipListener;
454600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
455600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	// If set to true then a transaction terminated event is
456600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	// delivered for ACK transactions.
457600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	boolean deliverTerminatedEventForAck = false;
458600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
459600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	// If set to true then the application want to receive
460600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	// unsolicited NOTIFYs, ie NOTIFYs that don't match any dialog
461600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	boolean deliverUnsolicitedNotify = false;
462600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
463600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	// Stack semaphore (global lock).
464600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	private Semaphore stackSemaphore = new Semaphore(1);
465600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
466600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	// RFC3261: TLS_RSA_WITH_AES_128_CBC_SHA MUST be supported
467600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	// RFC3261: TLS_RSA_WITH_3DES_EDE_CBC_SHA SHOULD be supported for backwards
468600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	// compat
469600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	private String[] cipherSuites = {
470600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			"TLS_RSA_WITH_AES_128_CBC_SHA", // AES difficult to get with
471600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang											// c++/Windows
472600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			// "TLS_RSA_WITH_3DES_EDE_CBC_SHA", // Unsupported by Sun impl,
473600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			"SSL_RSA_WITH_3DES_EDE_CBC_SHA", // For backwards comp., C++
474600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
475600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			// JvB: patch from Sebastien Mazy, issue with mismatching
476600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			// ciphersuites
477600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			"TLS_DH_anon_WITH_AES_128_CBC_SHA",
478600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			"SSL_DH_anon_WITH_3DES_EDE_CBC_SHA", };
479600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
480600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	// Supported protocols for TLS client: can be overridden by application
481600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	private String[] enabledProtocols = {
482600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			"SSLv3",
483600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			"SSLv2Hello",
484600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			"TLSv1"
485600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	};
486600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
487600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	/**
488600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * Creates a new instance of SipStackImpl.
489600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 */
490600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
491600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	protected SipStackImpl() {
492600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		super();
493600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		NistSipMessageFactoryImpl msgFactory = new NistSipMessageFactoryImpl(
494600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				this);
495600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		super.setMessageFactory(msgFactory);
496600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		this.eventScanner = new EventScanner(this);
497600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		this.listeningPoints = new Hashtable<String, ListeningPointImpl>();
498600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		this.sipProviders = new LinkedList<SipProviderImpl>();
499600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
500600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	}
501600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
502600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	/**
503600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * ReInitialize the stack instance.
504600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 */
505600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	private void reInitialize() {
506600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		super.reInit();
507600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		this.eventScanner = new EventScanner(this);
508600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		this.listeningPoints = new Hashtable<String, ListeningPointImpl>();
509600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		this.sipProviders = new LinkedList<SipProviderImpl>();
510600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		this.sipListener = null;
511600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
512600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	}
513600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
514600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	/**
515600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * Return true if automatic dialog support is enabled for this stack.
516600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *
517600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * @return boolean, true if automatic dialog support is enabled for this
518600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *         stack
519600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 */
520600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	boolean isAutomaticDialogSupportEnabled() {
521600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		return super.isAutomaticDialogSupportEnabled;
522600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	}
523600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
524600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	/**
525600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * Constructor for the stack.
526600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *
527600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * @param configurationProperties
528600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *            -- stack configuration properties including NIST-specific
529600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *            extensions.
530600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * @throws PeerUnavailableException
531600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 */
532600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	public SipStackImpl(Properties configurationProperties)
533600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			throws PeerUnavailableException {
534600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		this();
535600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		String address = configurationProperties
536600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				.getProperty("javax.sip.IP_ADDRESS");
537600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		try {
538600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			/** Retrieve the stack IP address */
539600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			if (address != null) {
540600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				// In version 1.2 of the spec the IP address is
541600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				// associated with the listening point and
542600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				// is not madatory.
543600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				super.setHostAddress(address);
544600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
545600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			}
546600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		} catch (java.net.UnknownHostException ex) {
547600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			throw new PeerUnavailableException("bad address " + address);
548600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		}
549600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
550600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		/** Retrieve the stack name */
551600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		String name = configurationProperties
552600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				.getProperty("javax.sip.STACK_NAME");
553600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (name == null)
554600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			throw new PeerUnavailableException("stack name is missing");
555600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		super.setStackName(name);
556600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		String stackLoggerClassName = configurationProperties
557600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				.getProperty("gov.nist.javax.sip.STACK_LOGGER");
558600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		// To log debug messages.
559600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (stackLoggerClassName == null)
560600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			stackLoggerClassName = "gov.nist.core.LogWriter";
561600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			try {
562600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				Class<?> stackLoggerClass = Class.forName(stackLoggerClassName);
563600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				Class<?>[] constructorArgs = new Class[0];
564600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				Constructor<?> cons = stackLoggerClass
565600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						.getConstructor(constructorArgs);
566600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				Object[] args = new Object[0];
567600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				StackLogger stackLogger = (StackLogger) cons.newInstance(args);
568600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				stackLogger.setStackProperties(configurationProperties);
569600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				super.setStackLogger(stackLogger);
570600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			} catch (InvocationTargetException ex1) {
571600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				throw new IllegalArgumentException(
572600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						"Cound not instantiate stack logger "
573600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang								+ stackLoggerClassName
574600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang								+ "- check that it is present on the classpath and that there is a no-args constructor defined",
575600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						ex1);
576600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			} catch (Exception ex) {
577600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				throw new IllegalArgumentException(
578600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						"Cound not instantiate stack logger "
579600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang								+ stackLoggerClassName
580600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang								+ "- check that it is present on the classpath and that there is a no-args constructor defined",
581600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						ex);
582600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			}
583600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
584600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		String serverLoggerClassName = configurationProperties
585600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				.getProperty("gov.nist.javax.sip.SERVER_LOGGER");
586600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		// To log debug messages.
587600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (serverLoggerClassName == null)
588600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			serverLoggerClassName = "gov.nist.javax.sip.stack.ServerLog";
589600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			try {
590600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				Class<?> serverLoggerClass = Class
591600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						.forName(serverLoggerClassName);
592600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				Class<?>[] constructorArgs = new Class[0];
593600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				Constructor<?> cons = serverLoggerClass
594600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						.getConstructor(constructorArgs);
595600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				Object[] args = new Object[0];
596600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				this.serverLogger = (ServerLogger) cons.newInstance(args);
597600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				serverLogger.setSipStack(this);
598600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				serverLogger.setStackProperties(configurationProperties);
599600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			} catch (InvocationTargetException ex1) {
600600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				throw new IllegalArgumentException(
601600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						"Cound not instantiate server logger "
602600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang								+ stackLoggerClassName
603600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang								+ "- check that it is present on the classpath and that there is a no-args constructor defined",
604600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						ex1);
605600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			} catch (Exception ex) {
606600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				throw new IllegalArgumentException(
607600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						"Cound not instantiate server logger "
608600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang								+ stackLoggerClassName
609600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang								+ "- check that it is present on the classpath and that there is a no-args constructor defined",
610600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						ex);
611600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			}
612600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
613600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		// Default router -- use this for routing SIP URIs.
614600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		// Our router does not do DNS lookups.
615600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		this.outboundProxy = configurationProperties
616600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				.getProperty("javax.sip.OUTBOUND_PROXY");
617600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
618600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		this.defaultRouter = new DefaultRouter(this, outboundProxy);
619600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
620600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		/** Retrieve the router path */
621600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		String routerPath = configurationProperties
622600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				.getProperty("javax.sip.ROUTER_PATH");
623600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (routerPath == null)
624600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			routerPath = "gov.nist.javax.sip.stack.DefaultRouter";
625600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
626600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		try {
627600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			Class<?> routerClass = Class.forName(routerPath);
628600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			Class<?>[] constructorArgs = new Class[2];
629600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			constructorArgs[0] = javax.sip.SipStack.class;
630600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			constructorArgs[1] = String.class;
631600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			Constructor<?> cons = routerClass.getConstructor(constructorArgs);
632600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			Object[] args = new Object[2];
633600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			args[0] = (SipStack) this;
634600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			args[1] = outboundProxy;
635600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			Router router = (Router) cons.newInstance(args);
636600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			super.setRouter(router);
637600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		} catch (InvocationTargetException ex1) {
638600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			getStackLogger()
639600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang					.logError(
640600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang							"could not instantiate router -- invocation target problem",
641600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang							(Exception) ex1.getCause());
642600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			throw new PeerUnavailableException(
643600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang					"Cound not instantiate router - check constructor", ex1);
644600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		} catch (Exception ex) {
645600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			getStackLogger().logError("could not instantiate router",
646600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang					(Exception) ex.getCause());
647600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			throw new PeerUnavailableException("Could not instantiate router",
648600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang					ex);
649600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		}
650600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
651600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		// The flag that indicates that the default router is to be ignored.
652600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		String useRouterForAll = configurationProperties
653600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				.getProperty("javax.sip.USE_ROUTER_FOR_ALL_URIS");
654600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		this.useRouterForAll = true;
655600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (useRouterForAll != null) {
656600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			this.useRouterForAll = "true".equalsIgnoreCase(useRouterForAll);
657600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		}
658600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
659600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		/*
660600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		 * Retrieve the EXTENSION Methods. These are used for instantiation of
661600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		 * Dialogs.
662600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		 */
663600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		String extensionMethods = configurationProperties
664600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				.getProperty("javax.sip.EXTENSION_METHODS");
665600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
666600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (extensionMethods != null) {
667600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			java.util.StringTokenizer st = new java.util.StringTokenizer(
668600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang					extensionMethods);
669600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			while (st.hasMoreTokens()) {
670600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				String em = st.nextToken(":");
671600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				if (em.equalsIgnoreCase(Request.BYE)
672600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						|| em.equalsIgnoreCase(Request.INVITE)
673600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						|| em.equalsIgnoreCase(Request.SUBSCRIBE)
674600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						|| em.equalsIgnoreCase(Request.NOTIFY)
675600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						|| em.equalsIgnoreCase(Request.ACK)
676600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						|| em.equalsIgnoreCase(Request.OPTIONS))
677600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang					throw new PeerUnavailableException("Bad extension method "
678600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang							+ em);
679600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				else
680600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang					this.addExtensionMethod(em);
681600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			}
682600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		}
683600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		String keyStoreFile = configurationProperties
684600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				.getProperty("javax.net.ssl.keyStore");
685600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		String trustStoreFile = configurationProperties
686600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				.getProperty("javax.net.ssl.trustStore");
687600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (keyStoreFile != null) {
688600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			if (trustStoreFile == null) {
689600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				trustStoreFile = keyStoreFile;
690600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			}
691600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			String keyStorePassword = configurationProperties
692600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang					.getProperty("javax.net.ssl.keyStorePassword");
693600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			try {
694600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				this.networkLayer = new SslNetworkLayer(trustStoreFile,
695600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						keyStoreFile, keyStorePassword.toCharArray(),
696600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						configurationProperties
697600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang								.getProperty("javax.net.ssl.keyStoreType"));
698600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			} catch (Exception e1) {
699600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				getStackLogger().logError(
700600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						"could not instantiate SSL networking", e1);
701600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			}
702600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		}
703600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
704600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		// Set the auto dialog support flag.
705600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		super.isAutomaticDialogSupportEnabled = configurationProperties
706600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				.getProperty("javax.sip.AUTOMATIC_DIALOG_SUPPORT", "on")
707600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				.equalsIgnoreCase("on");
708600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
709600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		super.isAutomaticDialogErrorHandlingEnabled = configurationProperties
710600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang					.getProperty("gov.nist.javax.sip.AUTOMATIC_DIALOG_ERROR_HANDLING","true")
711600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang					.equals(Boolean.TRUE.toString());
712600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if ( super.isAutomaticDialogSupportEnabled ) {
713600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			super.isAutomaticDialogErrorHandlingEnabled = true;
714600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		}
715600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
716600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (configurationProperties
717600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				.getProperty("gov.nist.javax.sip.MAX_LISTENER_RESPONSE_TIME") != null) {
718600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			super.maxListenerResponseTime = Integer
719600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang					.parseInt(configurationProperties
720600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang							.getProperty("gov.nist.javax.sip.MAX_LISTENER_RESPONSE_TIME"));
721600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			if (super.maxListenerResponseTime <= 0)
722600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				throw new PeerUnavailableException(
723600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						"Bad configuration parameter gov.nist.javax.sip.MAX_LISTENER_RESPONSE_TIME : should be positive");
724600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		} else {
725600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			super.maxListenerResponseTime = -1;
726600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		}
727600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
728600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
729600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
730600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		this.deliverTerminatedEventForAck = configurationProperties
731600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				.getProperty(
732600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						"gov.nist.javax.sip.DELIVER_TERMINATED_EVENT_FOR_ACK",
733600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						"false").equalsIgnoreCase("true");
734600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
735600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		this.deliverUnsolicitedNotify = configurationProperties.getProperty(
736600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				"gov.nist.javax.sip.DELIVER_UNSOLICITED_NOTIFY", "false")
737600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				.equalsIgnoreCase("true");
738600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
739600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		String forkedSubscriptions = configurationProperties
740600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				.getProperty("javax.sip.FORKABLE_EVENTS");
741600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (forkedSubscriptions != null) {
742600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			StringTokenizer st = new StringTokenizer(forkedSubscriptions);
743600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			while (st.hasMoreTokens()) {
744600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				String nextEvent = st.nextToken();
745600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				this.forkedEvents.add(nextEvent);
746600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			}
747600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		}
748600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
749600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		// The following features are unique to the NIST implementation.
750600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
751600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		/*
752600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		 * gets the NetworkLayer implementation, if any. Note that this is a
753600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		 * NIST only feature.
754600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		 */
755600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
756600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		final String NETWORK_LAYER_KEY = "gov.nist.javax.sip.NETWORK_LAYER";
757600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
758600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (configurationProperties.containsKey(NETWORK_LAYER_KEY)) {
759600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			String path = configurationProperties
760600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang					.getProperty(NETWORK_LAYER_KEY);
761600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			try {
762600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				Class<?> clazz = Class.forName(path);
763600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				Constructor<?> c = clazz.getConstructor(new Class[0]);
764600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				networkLayer = (NetworkLayer) c.newInstance(new Object[0]);
765600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			} catch (Exception e) {
766600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				throw new PeerUnavailableException(
767600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						"can't find or instantiate NetworkLayer implementation: "
768600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang								+ path);
769600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			}
770600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		}
771600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
772600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		final String ADDRESS_RESOLVER_KEY = "gov.nist.javax.sip.ADDRESS_RESOLVER";
773600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
774600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (configurationProperties.containsKey(ADDRESS_RESOLVER_KEY)) {
775600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			String path = configurationProperties
776600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang					.getProperty(ADDRESS_RESOLVER_KEY);
777600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			try {
778600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				Class<?> clazz = Class.forName(path);
779600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				Constructor<?> c = clazz.getConstructor(new Class[0]);
780600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				this.addressResolver = (AddressResolver) c
781600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						.newInstance(new Object[0]);
782600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			} catch (Exception e) {
783600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				throw new PeerUnavailableException(
784600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						"can't find or instantiate AddressResolver implementation: "
785600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang								+ path);
786600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			}
787600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		}
788600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
789600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		String maxConnections = configurationProperties
790600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				.getProperty("gov.nist.javax.sip.MAX_CONNECTIONS");
791600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (maxConnections != null) {
792600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			try {
793600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				this.maxConnections = new Integer(maxConnections).intValue();
794600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			} catch (NumberFormatException ex) {
795600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				if (isLoggingEnabled())
796600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang					getStackLogger().logError(
797600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						"max connections - bad value " + ex.getMessage());
798600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			}
799600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		}
800600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
801600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		String threadPoolSize = configurationProperties
802600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				.getProperty("gov.nist.javax.sip.THREAD_POOL_SIZE");
803600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (threadPoolSize != null) {
804600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			try {
805600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				this.threadPoolSize = new Integer(threadPoolSize).intValue();
806600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			} catch (NumberFormatException ex) {
807600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				if (isLoggingEnabled())
808600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang					this.getStackLogger().logError(
809600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						"thread pool size - bad value " + ex.getMessage());
810600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			}
811600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		}
812600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
813600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		String serverTransactionTableSize = configurationProperties
814600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				.getProperty("gov.nist.javax.sip.MAX_SERVER_TRANSACTIONS");
815600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (serverTransactionTableSize != null) {
816600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			try {
817600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				this.serverTransactionTableHighwaterMark = new Integer(
818600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						serverTransactionTableSize).intValue();
819600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				this.serverTransactionTableLowaterMark = this.serverTransactionTableHighwaterMark * 80 / 100;
820600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				// Lowater is 80% of highwater
821600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			} catch (NumberFormatException ex) {
822600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				if (isLoggingEnabled())
823600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang					this.getStackLogger()
824600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						.logError(
825600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang								"transaction table size - bad value "
826600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang										+ ex.getMessage());
827600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			}
828600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		} else {
829600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			// Issue 256 : consistent with MAX_CLIENT_TRANSACTIONS, if the MAX_SERVER_TRANSACTIONS is not set
830600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			// we assume the transaction table size can grow unlimited
831600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			this.unlimitedServerTransactionTableSize = true;
832600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		}
833600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
834600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		String clientTransactionTableSize = configurationProperties
835600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				.getProperty("gov.nist.javax.sip.MAX_CLIENT_TRANSACTIONS");
836600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (clientTransactionTableSize != null) {
837600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			try {
838600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				this.clientTransactionTableHiwaterMark = new Integer(
839600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						clientTransactionTableSize).intValue();
840600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				this.clientTransactionTableLowaterMark = this.clientTransactionTableLowaterMark * 80 / 100;
841600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				// Lowater is 80% of highwater
842600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			} catch (NumberFormatException ex) {
843600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				if (isLoggingEnabled())
844600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang					this.getStackLogger()
845600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						.logError(
846600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang								"transaction table size - bad value "
847600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang										+ ex.getMessage());
848600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			}
849600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		} else {
850600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			this.unlimitedClientTransactionTableSize = true;
851600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		}
852600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
853600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		super.cacheServerConnections = true;
854600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		String flag = configurationProperties
855600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				.getProperty("gov.nist.javax.sip.CACHE_SERVER_CONNECTIONS");
856600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
857600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (flag != null && "false".equalsIgnoreCase(flag.trim())) {
858600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			super.cacheServerConnections = false;
859600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		}
860600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
861600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		super.cacheClientConnections = true;
862600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		String cacheflag = configurationProperties
863600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				.getProperty("gov.nist.javax.sip.CACHE_CLIENT_CONNECTIONS");
864600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
865600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (cacheflag != null && "false".equalsIgnoreCase(cacheflag.trim())) {
866600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			super.cacheClientConnections = false;
867600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		}
868600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
869600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		String readTimeout = configurationProperties
870600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				.getProperty("gov.nist.javax.sip.READ_TIMEOUT");
871600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (readTimeout != null) {
872600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			try {
873600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
874600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				int rt = Integer.parseInt(readTimeout);
875600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				if (rt >= 100) {
876600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang					super.readTimeout = rt;
877600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				} else {
878600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang					System.err.println("Value too low " + readTimeout);
879600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				}
880600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			} catch (NumberFormatException nfe) {
881600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				// Ignore.
882600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				if (isLoggingEnabled())
883600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang					getStackLogger().logError("Bad read timeout " + readTimeout);
884600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			}
885600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		}
886600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
887600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		// Get the address of the stun server.
888600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
889600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		String stunAddr = configurationProperties
890600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				.getProperty("gov.nist.javax.sip.STUN_SERVER");
891600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
892600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (stunAddr != null)
893600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			this.getStackLogger().logWarning(
894600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang					"Ignoring obsolete property "
895600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang							+ "gov.nist.javax.sip.STUN_SERVER");
896600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
897600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		String maxMsgSize = configurationProperties
898600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				.getProperty("gov.nist.javax.sip.MAX_MESSAGE_SIZE");
899600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
900600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		try {
901600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			if (maxMsgSize != null) {
902600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				super.maxMessageSize = new Integer(maxMsgSize).intValue();
903600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				if (super.maxMessageSize < 4096)
904600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang					super.maxMessageSize = 4096;
905600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			} else {
906600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				// Allow for "infinite" size of message
907600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				super.maxMessageSize = 0;
908600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			}
909600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		} catch (NumberFormatException ex) {
910600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			if (isLoggingEnabled())
911600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				getStackLogger().logError(
912600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang					"maxMessageSize - bad value " + ex.getMessage());
913600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		}
914600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
915600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		String rel = configurationProperties
916600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				.getProperty("gov.nist.javax.sip.REENTRANT_LISTENER");
917600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		this.reEntrantListener = (rel != null && "true".equalsIgnoreCase(rel));
918600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
919600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		// Check if a thread audit interval is specified
920600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		String interval = configurationProperties
921600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				.getProperty("gov.nist.javax.sip.THREAD_AUDIT_INTERVAL_IN_MILLISECS");
922600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (interval != null) {
923600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			try {
924600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				// Make the monitored threads ping the auditor twice as fast as
925600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				// the audits
926600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				getThreadAuditor().setPingIntervalInMillisecs(
927600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						Long.valueOf(interval).longValue() / 2);
928600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			} catch (NumberFormatException ex) {
929600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				if (isLoggingEnabled())
930600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang					getStackLogger().logError(
931600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						"THREAD_AUDIT_INTERVAL_IN_MILLISECS - bad value ["
932600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang								+ interval + "] " + ex.getMessage());
933600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			}
934600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		}
935600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
936600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		// JvB: added property for testing
937600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		this
938600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				.setNon2XXAckPassedToListener(Boolean
939600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						.valueOf(
940600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang								configurationProperties
941600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang										.getProperty(
942600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang												"gov.nist.javax.sip.PASS_INVITE_NON_2XX_ACK_TO_LISTENER",
943600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang												"false")).booleanValue());
944600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
945600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		this.generateTimeStampHeader = Boolean.valueOf(
946600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				configurationProperties.getProperty(
947600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						"gov.nist.javax.sip.AUTO_GENERATE_TIMESTAMP", "false"))
948600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				.booleanValue();
949600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
950600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		String messageLogFactoryClasspath = configurationProperties
951600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				.getProperty("gov.nist.javax.sip.LOG_FACTORY");
952600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (messageLogFactoryClasspath != null) {
953600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			try {
954600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				Class<?> clazz = Class.forName(messageLogFactoryClasspath);
955600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				Constructor<?> c = clazz.getConstructor(new Class[0]);
956600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				this.logRecordFactory = (LogRecordFactory) c
957600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						.newInstance(new Object[0]);
958600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			} catch (Exception ex) {
959600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				if (isLoggingEnabled())
960600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang					getStackLogger()
961600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						.logError(
962600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang								"Bad configuration value for LOG_FACTORY -- using default logger");
963600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				this.logRecordFactory = new DefaultMessageLogFactory();
964600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			}
965600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
966600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		} else {
967600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			this.logRecordFactory = new DefaultMessageLogFactory();
968600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		}
969600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
970600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		boolean computeContentLength = configurationProperties.getProperty(
971600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				"gov.nist.javax.sip.COMPUTE_CONTENT_LENGTH_FROM_MESSAGE_BODY",
972600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				"false").equalsIgnoreCase("true");
973600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		StringMsgParser
974600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				.setComputeContentLengthFromMessage(computeContentLength);
975600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
976600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		String tlsClientProtocols = configurationProperties.getProperty(
977600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				"gov.nist.javax.sip.TLS_CLIENT_PROTOCOLS");
978600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (tlsClientProtocols != null)
979600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		{
980600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			StringTokenizer st = new StringTokenizer(tlsClientProtocols, " ,");
981600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			String[] protocols = new String[st.countTokens()];
982600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
983600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			int i=0;
984600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			while (st.hasMoreTokens()) {
985600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				protocols[i++] = st.nextToken();
986600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			}
987600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			this.enabledProtocols = protocols;
988600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		}
989600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
990600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		super.rfc2543Supported = configurationProperties.getProperty(
991600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				"gov.nist.javax.sip.RFC_2543_SUPPORT_ENABLED", "true")
992600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				.equalsIgnoreCase("true");
993600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
994600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		super.cancelClientTransactionChecked = configurationProperties
995600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				.getProperty(
996600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						"gov.nist.javax.sip.CANCEL_CLIENT_TRANSACTION_CHECKED",
997600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						"true").equalsIgnoreCase("true");
998600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		super.logStackTraceOnMessageSend = configurationProperties.getProperty(
999600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				"gov.nist.javax.sip.LOG_STACK_TRACE_ON_MESSAGE_SEND", "false")
1000600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				.equalsIgnoreCase("true");
1001600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (isLoggingEnabled())
1002600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			getStackLogger().logDebug(
1003600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				"created Sip stack. Properties = " + configurationProperties);
1004600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		InputStream in = getClass().getResourceAsStream("/TIMESTAMP");
1005600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (in != null) {
1006600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			BufferedReader streamReader = new BufferedReader(
1007600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang					new InputStreamReader(in));
1008600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1009600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			try {
1010600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				String buildTimeStamp = streamReader.readLine();
1011600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				if (in != null) {
1012600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang					in.close();
1013600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				}
1014600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				getStackLogger().setBuildTimeStamp(buildTimeStamp);
1015600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			} catch (IOException ex) {
1016600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				getStackLogger().logError("Could not open build timestamp.");
1017600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			}
1018600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		}
1019600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1020600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		String bufferSize = configurationProperties.getProperty(
1021600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				"gov.nist.javax.sip.RECEIVE_UDP_BUFFER_SIZE", MAX_DATAGRAM_SIZE
1022600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						.toString());
1023600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		int bufferSizeInteger = new Integer(bufferSize).intValue();
1024600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		super.setReceiveUdpBufferSize(bufferSizeInteger);
1025600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1026600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		bufferSize = configurationProperties.getProperty(
1027600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				"gov.nist.javax.sip.SEND_UDP_BUFFER_SIZE", MAX_DATAGRAM_SIZE
1028600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						.toString());
1029600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		bufferSizeInteger = new Integer(bufferSize).intValue();
1030600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		super.setSendUdpBufferSize(bufferSizeInteger);
1031600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1032600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		boolean congetstionControlEnabled = Boolean
1033600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				.parseBoolean(configurationProperties.getProperty(
1034600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						"gov.nist.javax.sip.CONGESTION_CONTROL_ENABLED",
1035600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						Boolean.TRUE.toString()));
1036600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		super.stackDoesCongestionControl = congetstionControlEnabled;
1037600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1038600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		super.isBackToBackUserAgent = Boolean
1039600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				.parseBoolean(configurationProperties.getProperty(
1040600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						"gov.nist.javax.sip.IS_BACK_TO_BACK_USER_AGENT",
1041600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						Boolean.FALSE.toString()));
1042600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		super.checkBranchId = Boolean.parseBoolean(configurationProperties
1043600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				.getProperty("gov.nist.javax.sip.REJECT_STRAY_RESPONSES",
1044600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						Boolean.FALSE.toString()));
1045600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1046600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		super.isDialogTerminatedEventDeliveredForNullDialog = (Boolean.parseBoolean(configurationProperties.getProperty("gov.nist.javax.sip.DELIVER_TERMINATED_EVENT_FOR_NULL_DIALOG",
1047600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		        Boolean.FALSE.toString())));
1048600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1049600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1050600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		super.maxForkTime = Integer.parseInt(
1051600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		        configurationProperties.getProperty("gov.nist.javax.sip.MAX_FORK_TIME_SECONDS","0"));
1052600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1053600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	}
1054600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1055600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	/*
1056600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * (non-Javadoc)
1057600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *
1058600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * @see javax.sip.SipStack#createListeningPoint(java.lang.String, int,
1059600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * java.lang.String)
1060600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 */
1061600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	public synchronized ListeningPoint createListeningPoint(String address,
1062600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			int port, String transport) throws TransportNotSupportedException,
1063600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			InvalidArgumentException {
1064600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (isLoggingEnabled())
1065600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			getStackLogger().logDebug(
1066600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				"createListeningPoint : address = " + address + " port = "
1067600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						+ port + " transport = " + transport);
1068600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1069600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (address == null)
1070600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			throw new NullPointerException(
1071600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang					"Address for listening point is null!");
1072600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (transport == null)
1073600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			throw new NullPointerException("null transport");
1074600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (port <= 0)
1075600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			throw new InvalidArgumentException("bad port");
1076600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1077600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (!transport.equalsIgnoreCase("UDP")
1078600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				&& !transport.equalsIgnoreCase("TLS")
1079600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				&& !transport.equalsIgnoreCase("TCP")
1080600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				&& !transport.equalsIgnoreCase("SCTP"))
1081600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			throw new TransportNotSupportedException("bad transport "
1082600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang					+ transport);
1083600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1084600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		/** Reusing an old stack instance */
1085600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (!this.isAlive()) {
1086600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			this.toExit = false;
1087600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			this.reInitialize();
1088600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		}
1089600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1090600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		String key = ListeningPointImpl.makeKey(address, port, transport);
1091600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1092600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		ListeningPointImpl lip = (ListeningPointImpl) listeningPoints.get(key);
1093600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (lip != null) {
1094600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			return lip;
1095600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		} else {
1096600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			try {
1097600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				InetAddress inetAddr = InetAddress.getByName(address);
1098600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				MessageProcessor messageProcessor = this
1099600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						.createMessageProcessor(inetAddr, port, transport);
1100600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				if (this.isLoggingEnabled()) {
1101600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang					this.getStackLogger().logDebug(
1102600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang							"Created Message Processor: " + address
1103600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang									+ " port = " + port + " transport = "
1104600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang									+ transport);
1105600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				}
1106600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				lip = new ListeningPointImpl(this, port, transport);
1107600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				lip.messageProcessor = messageProcessor;
1108600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				messageProcessor.setListeningPoint(lip);
1109600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				this.listeningPoints.put(key, lip);
1110600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				// start processing messages.
1111600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				messageProcessor.start();
1112600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				return (ListeningPoint) lip;
1113600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			} catch (java.io.IOException ex) {
1114600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				if (isLoggingEnabled())
1115600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang					getStackLogger().logError(
1116600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang						"Invalid argument address = " + address + " port = "
1117600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang								+ port + " transport = " + transport);
1118600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang				throw new InvalidArgumentException(ex.getMessage(), ex);
1119600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			}
1120600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		}
1121600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	}
1122600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1123600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	/*
1124600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * (non-Javadoc)
1125600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *
1126600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * @see javax.sip.SipStack#createSipProvider(javax.sip.ListeningPoint)
1127600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 */
1128600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	public SipProvider createSipProvider(ListeningPoint listeningPoint)
1129600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			throws ObjectInUseException {
1130600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (listeningPoint == null)
1131600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			throw new NullPointerException("null listeningPoint");
1132600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (this.isLoggingEnabled())
1133600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			this.getStackLogger().logDebug(
1134600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang					"createSipProvider: " + listeningPoint);
1135600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		ListeningPointImpl listeningPointImpl = (ListeningPointImpl) listeningPoint;
1136600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (listeningPointImpl.sipProvider != null)
1137600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			throw new ObjectInUseException("Provider already attached!");
1138600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1139600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		SipProviderImpl provider = new SipProviderImpl(this);
1140600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1141600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		provider.setListeningPoint(listeningPointImpl);
1142600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		listeningPointImpl.sipProvider = provider;
1143600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		this.sipProviders.add(provider);
1144600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		return provider;
1145600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	}
1146600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1147600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	/*
1148600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * (non-Javadoc)
1149600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *
1150600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * @see javax.sip.SipStack#deleteListeningPoint(javax.sip.ListeningPoint)
1151600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 */
1152600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	public void deleteListeningPoint(ListeningPoint listeningPoint)
1153600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			throws ObjectInUseException {
1154600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (listeningPoint == null)
1155600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			throw new NullPointerException("null listeningPoint arg");
1156600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		ListeningPointImpl lip = (ListeningPointImpl) listeningPoint;
1157600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		// Stop the message processing thread in the listening point.
1158600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		super.removeMessageProcessor(lip.messageProcessor);
1159600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		String key = lip.getKey();
1160600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		this.listeningPoints.remove(key);
1161600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1162600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	}
1163600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1164600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	/*
1165600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * (non-Javadoc)
1166600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *
1167600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * @see javax.sip.SipStack#deleteSipProvider(javax.sip.SipProvider)
1168600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 */
1169600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	public void deleteSipProvider(SipProvider sipProvider)
1170600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			throws ObjectInUseException {
1171600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1172600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (sipProvider == null)
1173600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			throw new NullPointerException("null provider arg");
1174600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		SipProviderImpl sipProviderImpl = (SipProviderImpl) sipProvider;
1175600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1176600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		// JvB: API doc is not clear, but in_use ==
1177600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		// sipProviderImpl.sipListener!=null
1178600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		// so we should throw if app did not call removeSipListener
1179600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		// sipProviderImpl.sipListener = null;
1180600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (sipProviderImpl.getSipListener() != null) {
1181600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			throw new ObjectInUseException(
1182600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang					"SipProvider still has an associated SipListener!");
1183600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		}
1184600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1185600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		sipProviderImpl.removeListeningPoints();
1186600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1187600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		// Bug reported by Rafael Barriuso
1188600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		sipProviderImpl.stop();
1189600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		sipProviders.remove(sipProvider);
1190600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (sipProviders.isEmpty()) {
1191600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			this.stopStack();
1192600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		}
1193600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	}
1194600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1195600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	/**
1196600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * Get the IP Address of the stack.
1197600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *
1198600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * @see javax.sip.SipStack#getIPAddress()
1199600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * @deprecated
1200600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 */
1201600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	public String getIPAddress() {
1202600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		return super.getHostAddress();
1203600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	}
1204600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1205600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	/*
1206600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * (non-Javadoc)
1207600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *
1208600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * @see javax.sip.SipStack#getListeningPoints()
1209600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 */
1210600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	public java.util.Iterator getListeningPoints() {
1211600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		return this.listeningPoints.values().iterator();
1212600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	}
1213600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1214600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	/**
1215600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * Return true if retransmission filter is active.
1216600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *
1217600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * @see javax.sip.SipStack#isRetransmissionFilterActive()
1218600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * @deprecated
1219600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 */
1220600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	public boolean isRetransmissionFilterActive() {
1221600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		return true;
1222600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	}
1223600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1224600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	/*
1225600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * (non-Javadoc)
1226600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *
1227600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * @see javax.sip.SipStack#getSipProviders()
1228600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 */
1229600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	public java.util.Iterator<SipProviderImpl> getSipProviders() {
1230600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		return this.sipProviders.iterator();
1231600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	}
1232600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1233600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	/*
1234600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * (non-Javadoc)
1235600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *
1236600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * @see javax.sip.SipStack#getStackName()
1237600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 */
1238600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	public String getStackName() {
1239600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		return this.stackName;
1240600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	}
1241600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1242600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	/**
1243600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * Finalization -- stop the stack on finalization. Exit the transaction
1244600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * scanner and release all resources.
1245600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *
1246600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * @see java.lang.Object#finalize()
1247600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 */
1248600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	protected void finalize() {
1249600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		this.stopStack();
1250600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	}
1251600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1252600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	/**
1253600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * This uses the default stack address to create a listening point.
1254600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *
1255600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * @see javax.sip.SipStack#createListeningPoint(java.lang.String, int,
1256600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *      java.lang.String)
1257600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * @deprecated
1258600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 */
1259600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	public ListeningPoint createListeningPoint(int port, String transport)
1260600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			throws TransportNotSupportedException, InvalidArgumentException {
1261600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (super.stackAddress == null)
1262600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			throw new NullPointerException(
1263600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang					"Stack does not have a default IP Address!");
1264600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		return this.createListeningPoint(super.stackAddress, port, transport);
1265600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	}
1266600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1267600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	/*
1268600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * (non-Javadoc)
1269600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *
1270600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * @see javax.sip.SipStack#stop()
1271600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 */
1272600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	public void stop() {
1273600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (isLoggingEnabled()) {
1274600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			getStackLogger().logDebug("stopStack -- stoppping the stack");
1275600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		}
1276600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		this.stopStack();
1277600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		this.sipProviders = new LinkedList<SipProviderImpl>();
1278600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		this.listeningPoints = new Hashtable<String, ListeningPointImpl>();
1279600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		/*
1280600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		 * Check for presence of an event scanner ( may happen if stack is
1281600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		 * stopped before listener is attached ).
1282600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		 */
1283600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (this.eventScanner != null)
1284600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			this.eventScanner.forceStop();
1285600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		this.eventScanner = null;
1286600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1287600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	}
1288600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1289600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	/*
1290600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * (non-Javadoc)
1291600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *
1292600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * @see javax.sip.SipStack#start()
1293600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 */
1294600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	public void start() throws ProviderDoesNotExistException, SipException {
1295600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		// Start a new event scanner if one does not exist.
1296600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (this.eventScanner == null) {
1297600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			this.eventScanner = new EventScanner(this);
1298600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		}
1299600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1300600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	}
1301600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1302600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	/**
1303600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * Get the listener for the stack. A stack can have only one listener. To
1304600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * get an event from a provider, the listener has to be registered with the
1305600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * provider. The SipListener is application code.
1306600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *
1307600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * @return -- the stack SipListener
1308600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *
1309600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 */
1310600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	public SipListener getSipListener() {
1311600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		return this.sipListener;
1312600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	}
1313600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1314600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	/**
1315600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * Get the message log factory registered with the stack.
1316600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *
1317600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * @return -- the messageLogFactory of the stack.
1318600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 */
1319600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	public LogRecordFactory getLogRecordFactory() {
1320600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		return super.logRecordFactory;
1321600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	}
1322600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1323600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	/**
1324600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * Set the log appender ( this is useful if you want to specify a particular
1325600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * log format or log to something other than a file for example). This method
1326600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * is will be removed May 11, 2010 or shortly there after.
1327600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *
1328600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * @param Appender
1329600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *            - the log4j appender to add.
1330600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * @deprecated TODO: remove this method May 11, 2010.
1331600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 */
1332600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // BEGIN android-deleted
1333600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	/*
1334600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        @Deprecated
1335600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	public void addLogAppender(org.apache.log4j.Appender appender) {
1336600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (this.getStackLogger() instanceof gov.nist.core.LogWriter) {
1337600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			((gov.nist.core.LogWriter) this.getStackLogger()).addAppender(appender);
1338600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		}
1339600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	}
1340600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        */
1341600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // END android-deleted
1342600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1343600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	/**
1344600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * Get the log4j logger ( for log stream integration ).
1345600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * This method will be removed May 11, 2010 or shortly there after.
1346600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *
1347600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * @return  the log4j logger.
1348600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * @deprecated TODO: This method will be removed May 11, 2010.
1349600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 */
1350600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	@Deprecated
1351600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // BEGIN andoird-deleted
1352600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        /*
1353600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	public org.apache.log4j.Logger getLogger() {
1354600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		if (this.getStackLogger() instanceof gov.nist.core.LogWriter) {
1355600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			return ((gov.nist.core.LogWriter) this.getStackLogger()).getLogger();
1356600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		}
1357600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		return null;
1358600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	}
1359600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        */
1360600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // END android-deleted
1361600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1362600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	public EventScanner getEventScanner() {
1363600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		return eventScanner;
1364600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	}
1365600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1366600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	/*
1367600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * (non-Javadoc)
1368600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *
1369600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * @see
1370600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * gov.nist.javax.sip.SipStackExt#getAuthenticationHelper(gov.nist.javax
1371600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * .sip.clientauthutils.AccountManager, javax.sip.header.HeaderFactory)
1372600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 */
1373600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	public AuthenticationHelper getAuthenticationHelper(
1374600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			AccountManager accountManager, HeaderFactory headerFactory) {
1375600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		return new AuthenticationHelperImpl(this, accountManager, headerFactory);
1376600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	}
1377600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1378600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	/*
1379600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * (non-Javadoc)
1380600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *
1381600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * @see
1382600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * gov.nist.javax.sip.SipStackExt#getAuthenticationHelper(gov.nist.javax
1383600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * .sip.clientauthutils.AccountManager, javax.sip.header.HeaderFactory)
1384600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 */
1385600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	public AuthenticationHelper getSecureAuthenticationHelper(
1386600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang			SecureAccountManager accountManager, HeaderFactory headerFactory) {
1387600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		return new AuthenticationHelperImpl(this, accountManager, headerFactory);
1388600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	}
1389600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1390600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	/**
1391600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * Set the list of cipher suites supported by the stack. A stack can have
1392600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * only one set of suites. These are not validated against the supported
1393600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * cipher suites of the java runtime, so specifying a cipher here does not
1394600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * guarantee that it will work.<br>
1395600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * The stack has a default cipher suite of:
1396600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * <ul>
1397600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * <li>TLS_RSA_WITH_AES_128_CBC_SHA</li>
1398600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * <li>SSL_RSA_WITH_3DES_EDE_CBC_SHA</li>
1399600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * <li>TLS_DH_anon_WITH_AES_128_CBC_SHA</li>
1400600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * <li>SSL_DH_anon_WITH_3DES_EDE_CBC_SHA</li>
1401600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * </ul>
1402600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *
1403600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * <b>NOTE: This function must be called before adding a TLS listener</b>
1404600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *
1405600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * @param String
1406600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *            [] The new set of ciphers to support.
1407600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * @return
1408600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *
1409600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 */
1410600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	public void setEnabledCipherSuites(String[] newCipherSuites) {
1411600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		cipherSuites = newCipherSuites;
1412600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	}
1413600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1414600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	/**
1415600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * Return the currently enabled cipher suites of the Stack.
1416600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *
1417600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * @return The currently enabled cipher suites.
1418600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 */
1419600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	public String[] getEnabledCipherSuites() {
1420600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		return cipherSuites;
1421600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	}
1422600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1423600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	/**
1424600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * Set the list of protocols supported by the stack for outgoing TLS connections.
1425600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * A stack can have only one set of protocols.
1426600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * These are not validated against the supported
1427600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * protocols of the java runtime, so specifying a protocol here does not
1428600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * guarantee that it will work.<br>
1429600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * The stack has a default protocol suite of:
1430600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * <ul>
1431600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * <li>SSLv3</li>
1432600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * <li>SSLv2Hello</li>
1433600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * <li>TLSv1</li>
1434600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * </ul>
1435600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *
1436600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * <b>NOTE: This function must be called before creating a TLSMessageChannel.</b>
1437600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *
1438600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * @param String
1439600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *            [] The new set of protocols to use for outgoing TLS connections.
1440600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * @return
1441600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *
1442600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 */
1443600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	public void setEnabledProtocols(String[] newProtocols) {
1444600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		enabledProtocols = newProtocols;
1445600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	}
1446600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1447600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	/**
1448600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * Return the currently enabled protocols to use when creating TLS connection.
1449600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *
1450600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * @return The currently enabled protocols.
1451600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 */
1452600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	public String[] getEnabledProtocols() {
1453600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		return enabledProtocols;
1454600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	}
1455600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1456600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	/**
1457600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * Set the "back to back User Agent" flag.
1458600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *
1459600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * @param flag
1460600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *            - boolean flag to set.
1461600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *
1462600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 */
1463600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	public void setIsBackToBackUserAgent(boolean flag) {
1464600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		super.isBackToBackUserAgent = flag;
1465600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	}
1466600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1467600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	/**
1468600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * Get the "back to back User Agent" flag.
1469600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *
1470600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 * return the value of the flag
1471600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 *
1472600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	 */
1473600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	public boolean isBackToBackUserAgent() {
1474600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		return super.isBackToBackUserAgent;
1475600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	}
1476600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1477600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	public boolean isAutomaticDialogErrorHandlingEnabled() {
1478600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang		return super.isAutomaticDialogErrorHandlingEnabled;
1479600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang	}
1480600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1481600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public boolean acquireSem() {
1482600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        try {
1483600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return this.stackSemaphore.tryAcquire(10, TimeUnit.SECONDS);
1484600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } catch ( InterruptedException ex) {
1485600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return false;
1486600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
1487600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
1488600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1489600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public void releaseSem() {
1490600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.stackSemaphore.release();
1491600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
1492600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1493600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1494600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1495600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1496600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang}
1497