diff --git a/.classpath b/.classpath index 56e467ec1..86191b2b6 100644 --- a/.classpath +++ b/.classpath @@ -1,11 +1,8 @@ - - + - - diff --git a/.project b/.project index 52b600931..8d513c6a5 100644 --- a/.project +++ b/.project @@ -1,6 +1,6 @@ - jain-sip + jsip-stable-branch diff --git a/TIMESTAMP b/TIMESTAMP new file mode 100644 index 000000000..dec7e0aa3 --- /dev/null +++ b/TIMESTAMP @@ -0,0 +1 @@ +Wed Mar 24 14:53:37 GMT-05:00 2010 \ No newline at end of file diff --git a/ant-tasks/src/net/java/jsip/ant/tasks/VersionerTask.java b/ant-tasks/src/net/java/jsip/ant/tasks/VersionerTask.java index 906dfe727..16140dd86 100644 --- a/ant-tasks/src/net/java/jsip/ant/tasks/VersionerTask.java +++ b/ant-tasks/src/net/java/jsip/ant/tasks/VersionerTask.java @@ -24,7 +24,7 @@ public class VersionerTask extends Task { protected File cvsVersionFile = null; - protected int version = 1111; + protected int version = -1; protected File pomFile = null; protected File toVersion = null; protected boolean incrementCVSVersion = false; @@ -34,6 +34,10 @@ public class VersionerTask extends Task { private boolean doPom = false; private boolean doToVersion = false; + private String timeStampFileName = "TIMESTAMP"; + + private String antprops = "ant-version.properties"; + public void setMainVersionParts(int mainVersionParts) { this.mainVersionParts = mainVersionParts; @@ -117,64 +121,70 @@ public void execute() throws BuildException { super.execute(); - int localVersion = 1111; + int localVersion = -1; if (cvsVersionFile != null) { - //ObjectInputStream ois = null; - BufferedReader br=null; - try { - //ois = new ObjectInputStream(new FileInputStream(cvsVersionFile)); - - String versionValue=null; - br=new BufferedReader(new FileReader(cvsVersionFile)); - versionValue=br.readLine(); - localVersion = Math.abs(Integer.valueOf(versionValue)); - - } catch (Exception e) { - log("Failed to fetch version from file!!"); - localVersion = this.version; - } finally { - if (br != null) - try { - - br.close(); - } catch (Exception e) { - localVersion = this.version; - } - } - super.getProject().setProperty("svnversion", Integer.toString(localVersion)); - - - getProject().setProperty("jain-sip-ri-jar", - "jain-sip-ri-1.2." + localVersion + ".jar"); - getProject().setProperty("jain-sip-sdp-jar", - "jain-sip-sdp-1.2." + localVersion + ".jar"); - getProject().setProperty("jain-sip-src-tar", - "jain-sip-src-1.2." + localVersion + ".tar.gz"); - - getProject().setProperty("jain-sip-javadoc-tar", - "jain-sip-javadoc-1.2." + localVersion + ".tar.gz"); - - getProject().setProperty("jain-sip-all-tar", - "jain-sip-1.2." + localVersion + ".tar.gz"); - getProject().setProperty("jain-sip-tck-jar", - "jain-sip-tck-1.2." + localVersion + ".jar"); - getProject().setProperty("sdp_jar", - "jain-sdp-1.0." + localVersion + ".jar"); - getProject().setProperty("sdp-src-jar", - "jain-sdp-src-1.0." + localVersion + ".jar"); - getProject().setProperty("jain-sip-src-jar", - "jain-sip-src-1.2." + localVersion + ".jar"); - - getProject().setProperty("jain-sip-sctp-jar", - "jain-sip-sctp-1.2." + localVersion + ".jar"); - getProject().setProperty("unit_test_jar", - "jain-sip-unit-test-1.2." + localVersion + ".jar"); - - String cwd = System.getProperty("user.dir"); - getProject().setProperty("top",new File(cwd).getName()); - - - + //ObjectInputStream ois = null; + BufferedReader br=null; + try { + //ois = new ObjectInputStream(new FileInputStream(cvsVersionFile)); + + String versionValue=null; + br=new BufferedReader(new FileReader(cvsVersionFile)); + versionValue=br.readLine(); + localVersion = Math.abs(Integer.valueOf(versionValue)); + + } catch (Exception e) { + log("Failed to fetch version from file!!"); + throw new BuildException(e); + } finally { + if (br != null) + try { + + br.close(); + } catch (Exception e) { + throw new BuildException(e); + } + } + + if (incrementCVSVersion) { + cvsVersionFile.delete(); + try { + cvsVersionFile.createNewFile(); + //ObjectOutputStream oos = new ObjectOutputStream( + // new FileOutputStream(cvsVersionFile)); + //oos.writeUTF(""+localVersion + 1); + BufferedWriter bw=new BufferedWriter(new FileWriter(cvsVersionFile)); + bw.write(""+(localVersion + 1)); + bw.flush(); + bw.close(); + File antPropertiesFile = new File( this.antprops); + antPropertiesFile.createNewFile(); + bw=new BufferedWriter(new FileWriter(antPropertiesFile)); + bw.write("jain-sip-ri-jar=jain-sip-ri-1.2."+(localVersion + 1) + ".jar\n"); + bw.write("jain-sip-sdp-jar=jain-sip-sdp-1.2."+(localVersion + 1) + ".jar\n"); + bw.write("jain-sip-src-tar=jain-sip-src-1.2."+(localVersion + 1) + ".tar.gz\n"); + bw.write("jain-sip-javadoc-tar=jain-sip-javadoc-1.2."+(localVersion + 1) + ".tar.gz\n"); + + bw.write("jain-sip-all-tar=jain-sip-1.2." +(localVersion + 1) + ".tar.gz\n"); + bw.write("jain-sip-tck-jar=jain-sip-tck-1.2."+(localVersion + 1) + ".jar\n"); + bw.write("sdp_jar=jain-sdp-1.0."+(localVersion + 1) + ".jar\n"); + bw.write("sdp-src-jar=jain-sdp-src-1.0."+(localVersion + 1) + ".jar\n"); + + bw.write("jain-sip-sctp-jar=jain-sip-sctp-1.2."+(localVersion + 1) + ".jar\n"); + bw.write("unit_test_jar=jain-sip-unit-test-1.2." + (localVersion+1) + ".jar\n"); + bw.flush(); + bw.close(); + bw=new BufferedWriter(new FileWriter(this.timeStampFileName)); + Date date = new Date ( System.currentTimeMillis()); + bw.write(date.toString()); + bw.close(); + } catch (IOException e) { + log("Failed to increment version in file. See stack trace:",e,0); + e.printStackTrace(); + } + + } + } else { localVersion = this.version; } diff --git a/ant-version.properties b/ant-version.properties new file mode 100644 index 000000000..a04864c15 --- /dev/null +++ b/ant-version.properties @@ -0,0 +1,10 @@ +jain-sip-ri-jar=jain-sip-ri-1.2.148.jar +jain-sip-sdp-jar=jain-sip-sdp-1.2.148.jar +jain-sip-src-tar=jain-sip-src-1.2.148.tar.gz +jain-sip-javadoc-tar=jain-sip-javadoc-1.2.148.tar.gz +jain-sip-all-tar=jain-sip-1.2.148.tar.gz +jain-sip-tck-jar=jain-sip-tck-1.2.148.jar +sdp_jar=jain-sdp-1.0.148.jar +sdp-src-jar=jain-sdp-src-1.0.148.jar +jain-sip-sctp-jar=jain-sip-sctp-1.2.148.jar +unit_test_jar=jain-sip-unit-test-1.2.148.jar diff --git a/build.xml b/build.xml index acfc98af1..de1991b21 100755 --- a/build.xml +++ b/build.xml @@ -73,6 +73,7 @@ c:/jakarta-ant/bin/ant all + @@ -110,7 +111,7 @@ c:/jakarta-ant/bin/ant all - + @@ -130,20 +131,19 @@ c:/jakarta-ant/bin/ant all - + - - + @@ -153,7 +153,7 @@ c:/jakarta-ant/bin/ant all - + @@ -250,8 +250,7 @@ c:/jakarta-ant/bin/ant all - - + @@ -260,7 +259,7 @@ c:/jakarta-ant/bin/ant all - + @@ -275,11 +274,11 @@ c:/jakarta-ant/bin/ant all value="${jain-sip-ri-jar}"/> - + value="${jain-sip-ri-src-jar}"/> @@ -332,10 +331,9 @@ c:/jakarta-ant/bin/ant all - + - - + @@ -357,7 +355,7 @@ c:/jakarta-ant/bin/ant all - + @@ -635,27 +633,31 @@ c:/jakarta-ant/bin/ant all + + + + + - + + includes="jain-sip/**/*/" + excludes="jain-sip/www/**/*,jain-sip/javax/**/*,jain-sip/repo/**/*,jain-sip/ant-tasks/lib/**/*,jain-sip/test-reports/**/*,jain-sip/classes/**/*,jain-sip/javadoc/**/*,jain-sip/*.jar,jain-sip/lib/**/*,jain-sip/tckoutput.txt,jain-sip/*.gz,jain-sip/poms/**/*" /> - - + + includes="jain-sip/javadoc/**/*" /> - + + includes="jain-sip/**/*/" + excludes="jain-sip/*.tar.gz" /> - + @@ -665,21 +667,21 @@ c:/jakarta-ant/bin/ant all - - + - + - + @@ -781,16 +783,10 @@ c:/jakarta-ant/bin/ant all - - - - - - - - - - + + + + @@ -805,11 +801,4 @@ c:/jakarta-ant/bin/ant all - - - - - - - - + diff --git a/m2/jain-sip-ri/pom.xml b/m2/jain-sip-ri/pom.xml index 36b811dac..eb7a227bd 100644 --- a/m2/jain-sip-ri/pom.xml +++ b/m2/jain-sip-ri/pom.xml @@ -1,89 +1,28 @@ - + - 4.0.0 - - javax.sip - 1.2 - jain-sip - + 4.0.0 + + javax.sip + 1.2 + jain-sip + - jain-sip-ri - 1.2.X-SNAPSHOT - - jar - jain-sip-ri - http://jain-sip.dev.java.net - - ../../src - - - org.apache.maven.plugins - maven-compiler-plugin - - 1.5 - 1.5 - - gov/nist/javax/sip/** - gov/nist/javax/sdp/** - gov/nist/core/** - javax/sdp/** - - - gov/nist/javax/sip/stack/sctp/** - - - - - org.apache.maven.plugins - maven-source-plugin - - - attach-sources - verify - - jar - - - - - - org.codehaus.mojo - buildnumber-maven-plugin - 1.0-beta-4 - - - validate - - create - - - - - false - false - - - - org.apache.maven.plugins - maven-jar-plugin - 2.1 - - - - true - - - ${buildNumber} - - - - - - - - target + jain-sip-ri + 1.2.148.9 + + jar + jain-sip-ri + http://jain-sip.dev.java.net + + ../../src + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.5 + 1.5 gov/nist/javax/sip/** gov/nist/javax/sdp/** @@ -91,25 +30,54 @@ javax/sdp/** - **/*.java gov/nist/javax/sip/stack/sctp/** - - - - - - log4j - log4j - 1.2.14 - provided - - - javax.sip - jain-sip-api - 1.2 - provided - - + + + + org.apache.maven.plugins + maven-source-plugin + + + attach-sources + verify + + jar + + + + + + + + target + + gov/nist/javax/sip/** + gov/nist/javax/sdp/** + gov/nist/core/** + javax/sdp/** + + + **/*.java + gov/nist/javax/sip/stack/sctp/** + + + + + + + + log4j + log4j + 1.2.14 + provided + + + javax.sip + jain-sip-api + 1.2 + provided + + diff --git a/m2/jain-sip-sctp/pom.xml b/m2/jain-sip-sctp/pom.xml index f2b002bcd..6a0987871 100644 --- a/m2/jain-sip-sctp/pom.xml +++ b/m2/jain-sip-sctp/pom.xml @@ -9,7 +9,7 @@ jain-sip-sctp - 1.2.X-SNAPSHOT + 1.2.122-SNAPSHOT jar jain-sip-sctp @@ -41,38 +41,6 @@ - - org.codehaus.mojo - buildnumber-maven-plugin - 1.0-beta-4 - - - validate - - create - - - - - false - false - - - - org.apache.maven.plugins - maven-jar-plugin - 2.1 - - - - true - - - ${buildNumber} - - - - diff --git a/m2/pom.xml b/m2/pom.xml index d0d2b8f68..efbccaae6 100644 --- a/m2/pom.xml +++ b/m2/pom.xml @@ -1,6 +1,5 @@ - + 4.0.0 @@ -17,16 +16,39 @@ - - - 1.7 - - - jain-sip-sctp - - + + + 1.7 + + + jain-sip-sctp + + + + + @@ -36,51 +58,65 @@ default - jboss-public-repository-group - JBoss Public Maven Repository Group - https://repository.jboss.org/nexus/content/groups/public/ - default - - true - never - - - true - never - - + jboss-public-repository-group + JBoss Public Maven Repository Group + https://repository.jboss.org/nexus/content/groups/public/ + default + + true + never + + + true + never + + - backup.repository.jboss.org - JBoss Repository Backup - http://anonsvn.jboss.org/repos/repository.jboss.org/maven2/ + backup.repository.jboss.org + JBoss Repository Backup + http://anonsvn.jboss.org/repos/repository.jboss.org/maven2/ true true - + - - - jboss-releases-repository - JBoss Releases Repository - https://repository.jboss.org/nexus/service/local/staging/deploy/maven2/ - - - jboss-snapshots-repository - JBoss Snapshots Repository - https://repository.jboss.org/nexus/content/repositories/snapshots/ - - + + + + + + + jboss-releases-repository + JBoss Releases Repository + https://repository.jboss.org/nexus/service/local/staging/deploy/maven2/ + + + jboss-snapshots-repository + JBoss Snapshots Repository + https://repository.jboss.org/nexus/content/repositories/snapshots/ + + + + diff --git a/src/examples/nistgoodies/configlogger/LogRecordImpl.java b/src/examples/nistgoodies/configlogger/LogRecordImpl.java index b6f7b8827..c6d4c0a3f 100644 --- a/src/examples/nistgoodies/configlogger/LogRecordImpl.java +++ b/src/examples/nistgoodies/configlogger/LogRecordImpl.java @@ -61,7 +61,7 @@ public boolean equals(Object other) { public String toString() { - StringBuilder sbuf = new StringBuilder(); + StringBuffer sbuf = new StringBuffer(); sbuf.append("------------ Message BEGIN ----------- \n"); sbuf.append("timeStamp = " + this.timeStamp + "\n"); sbuf.append(this.message); diff --git a/src/examples/nistgoodies/messagevalve/README.txt b/src/examples/nistgoodies/messagevalve/README.txt deleted file mode 100644 index 60379e9cf..000000000 --- a/src/examples/nistgoodies/messagevalve/README.txt +++ /dev/null @@ -1,23 +0,0 @@ -This example demonstrates the use of gov.nist.javax.sip.SIP_MESSAGE_VALVE property. - -In summary the property specifies a class name that will be instantiated when the SIP stack is -started. Then for every request and response that arrive at the stack this instance will be called -giving you a chance to manipulate or drop the message. - -In the example you can see that the regular processRequest and processResponse callbacks from -SipListener are not invoked because we are dropping them from the SipMessageValve's callbacks. - -Additionally, we send error response 603 to all requests directly from the valve. This way we -avoid any of the overhead associated with transactions, dialogs, validation, etc. You can use -this feature to implement congestion control or DoS attack security. - -In summary here are potential uses of the valve: -1. Congestion control - silent drop or error response -2. DoS attack prevention - because the valve is very early in the pipeline, no significant resources -are allocated for these messages. -3. Manipulate SIP message headers before reaching the application -4. Acquire locks in the early stage of the pipeline, so you can avoid race conditions or message - re-ordering. Implementing message serialization/queuing based on locks. -5. Implement SIP logic that doesn't require statefulness. For example, you might have a full SIP -service, but some requests are simply a keepalive protocol. They don't really need strict transactions -or dialogs, thus you can make the response to the keepalives in the valve. \ No newline at end of file diff --git a/src/examples/nistgoodies/messagevalve/SipMessageValve.java b/src/examples/nistgoodies/messagevalve/SipMessageValve.java deleted file mode 100644 index d9e103de6..000000000 --- a/src/examples/nistgoodies/messagevalve/SipMessageValve.java +++ /dev/null @@ -1,149 +0,0 @@ -package examples.nistgoodies.messagevalve; - -import examples.nistgoodies.threadaudit.ThreadAudit; -import gov.nist.javax.sip.SipStackImpl; -import gov.nist.javax.sip.message.SIPRequest; -import gov.nist.javax.sip.stack.MessageChannel; -import gov.nist.javax.sip.stack.SIPMessageValve; -import gov.nist.javax.sip.stack.SIPTransactionStack; - -import java.io.IOException; -import java.util.Properties; - -import javax.sip.DialogTerminatedEvent; -import javax.sip.IOExceptionEvent; -import javax.sip.ListeningPoint; -import javax.sip.PeerUnavailableException; -import javax.sip.RequestEvent; -import javax.sip.ResponseEvent; -import javax.sip.SipFactory; -import javax.sip.SipListener; -import javax.sip.SipProvider; -import javax.sip.SipStack; -import javax.sip.TransactionTerminatedEvent; -import javax.sip.message.Response; - - -public class SipMessageValve implements SIPMessageValve { - public static class Shootme implements SipListener { - - - private SipStack sipStack; - - private SipProvider sipProvider; - - private static final int myPort = 5070; - public void processRequest(RequestEvent requestEvent) { - System.out.println("This method will never be called because we handle the messages in " + - "the SipMessageValve only!"); - } - - public void processResponse(ResponseEvent responseEvent) { - System.out.println("This method will never be called because we handle the messages in " + - "the SipMessageValve only!"); - } - - public void processTimeout(javax.sip.TimeoutEvent timeoutEvent) { - - } - - public void init() { - SipFactory sipFactory = null; - sipStack = null; - sipFactory = SipFactory.getInstance(); - sipFactory.setPathName("gov.nist"); - Properties properties = new Properties(); - properties.setProperty("javax.sip.STACK_NAME", "shootme"); - // You need 16 for logging traces. 32 for debug + traces. - // Your code will limp at 32 but it is best for debugging. - properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "32"); - properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", - "shootmedebug.txt"); - properties.setProperty("gov.nist.javax.sip.SERVER_LOG", - "shootmelog.txt"); - properties.setProperty("gov.nist.javax.sip.AUTOMATIC_DIALOG_ERROR_HANDLING", "false"); - properties.setProperty("javax.sip.AUTOMATIC_DIALOG_SUPPORT", "off"); - properties.setProperty("gov.nist.javax.sip.SIP_MESSAGE_VALVE", SipMessageValve.class.getCanonicalName()); - - try { - // Create SipStack object - sipStack = sipFactory.createSipStack(properties); - System.out.println("sipStack = " + sipStack); - } catch (PeerUnavailableException e) { - // could not find - // gov.nist.jain.protocol.ip.sip.SipStackImpl - // in the classpath - e.printStackTrace(); - System.err.println(e.getMessage()); - if (e.getCause() != null) - e.getCause().printStackTrace(); - System.exit(0); - } - - try { - ListeningPoint lp = sipStack.createListeningPoint("127.0.0.1", - myPort, "udp"); - - Shootme listener = this; - - sipProvider = sipStack.createSipProvider(lp); - System.out.println("udp provider " + sipProvider); - sipProvider.addSipListener(listener); - - } catch (Exception ex) { - ex.printStackTrace(); - } - - } - - public void processTransactionTerminated( - TransactionTerminatedEvent transactionTerminatedEvent) { - - } - - public void processDialogTerminated( - DialogTerminatedEvent dialogTerminatedEvent) { - - } - - public void processIOException(IOExceptionEvent exceptionEvent) { - - } - - } - - public boolean processRequest(SIPRequest request, - MessageChannel messageChannel) { - try { - messageChannel.sendMessage(request.createResponse(603)); - } catch (IOException e) { - e.printStackTrace(); - } - return false; - } - - public boolean processResponse(Response response, - MessageChannel messageChannel) { - // Just drop the all responses - return false; - } - - public static void main(String[] args) throws Exception { - Shootme shootme = new Shootme(); - shootme.init(); - System.out.println("SIP stack started."); - Thread.sleep(10000); - System.out.println("Stopped."); - } - - public void destroy() { - // TODO Auto-generated method stub - - } - - public void init(SipStack stack) { - SipStackImpl s = (SipStackImpl) stack; - s.getConfigurationProperties(); - System.out.println("SIP Message Valve initialized"); - } -} diff --git a/src/examples/nistgoodies/pluggablelogger/LogRecordImpl.java b/src/examples/nistgoodies/pluggablelogger/LogRecordImpl.java index 2b218ecc9..8d35a13a9 100644 --- a/src/examples/nistgoodies/pluggablelogger/LogRecordImpl.java +++ b/src/examples/nistgoodies/pluggablelogger/LogRecordImpl.java @@ -61,7 +61,7 @@ public boolean equals(Object other) { public String toString() { - StringBuilder sbuf = new StringBuilder(); + StringBuffer sbuf = new StringBuffer(); sbuf.append("------------ Message BEGIN ----------- \n"); sbuf.append("timeStamp = " + this.timeStamp + "\n"); sbuf.append(this.message); diff --git a/src/examples/nistgoodies/pluggablelogger/StackLoggerImpl.java b/src/examples/nistgoodies/pluggablelogger/StackLoggerImpl.java index 69348d1bf..9328ec90c 100644 --- a/src/examples/nistgoodies/pluggablelogger/StackLoggerImpl.java +++ b/src/examples/nistgoodies/pluggablelogger/StackLoggerImpl.java @@ -98,7 +98,7 @@ public void logInfo(String string) { } public void logStackTrace() { - if (this.isLoggingEnabled(TRACE_DEBUG)) { + if (enabled) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); StackTraceElement[] ste = new Exception().getStackTrace(); diff --git a/src/gov/nist/core/CommonLogger.java b/src/gov/nist/core/CommonLogger.java deleted file mode 100644 index 269d53175..000000000 --- a/src/gov/nist/core/CommonLogger.java +++ /dev/null @@ -1,135 +0,0 @@ -package gov.nist.core; - -import java.util.Properties; - -import org.apache.log4j.Logger; -/** - * This class abstracts away single-instanct and multi0instance loggers - * legacyLogger is the old-school one logger per stack reference - * otherLogger is multiinstance logger - * - * @author Vladimir Ralev - * - */ -public class CommonLogger implements StackLogger{ - private String name; - private StackLogger otherLogger; - - public static boolean useLegacyLogger = true; - public static StackLogger legacyLogger; - - public CommonLogger(String name) { - this.name = name; - } - - private StackLogger logger() { - if(useLegacyLogger) { - return legacyLogger; - } else { - if(otherLogger == null) { - otherLogger = new CommonLoggerLog4j(Logger.getLogger(name)); - } - return otherLogger; - } - } - - public static StackLogger getLogger(String name) { - return new CommonLogger(name); - } - public static StackLogger getLogger(Class clazz) { - return getLogger(clazz.getName()); - } - - public static void init(Properties p) { - - } - - public void disableLogging() { - logger().disableLogging(); - } - - public void enableLogging() { - logger().enableLogging(); - - } - - public int getLineCount() { - - return logger().getLineCount(); - } - - public String getLoggerName() { - - return logger().getLoggerName(); - } - - public boolean isLoggingEnabled() { - - return logger().isLoggingEnabled(); - } - - public boolean isLoggingEnabled(int logLevel) { - - return logger().isLoggingEnabled(logLevel); - } - - public void logDebug(String message) { - - logger().logDebug(message); - } - - public void logError(String message) { - - logger().logError(message); - } - - public void logError(String message, Exception ex) { - - logger().logError(message, ex); - } - - public void logException(Throwable ex) { - - logger().logException(ex); - } - - public void logFatalError(String message) { - - logger().logFatalError(message); - } - - public void logInfo(String string) { - - logger().logInfo(string); - } - - public void logStackTrace() { - - logger().logStackTrace(); - } - - public void logStackTrace(int traceLevel) { - - logger().logStackTrace(traceLevel); - } - - public void logTrace(String message) { - - logger().logTrace(message); - } - - public void logWarning(String string) { - - logger().logWarning(string); - } - - public void setBuildTimeStamp(String buildTimeStamp) { - - logger().setBuildTimeStamp(buildTimeStamp); - } - - public void setStackProperties(Properties stackProperties) { - - legacyLogger.setStackProperties(stackProperties); - } -} diff --git a/src/gov/nist/core/CommonLoggerLog4j.java b/src/gov/nist/core/CommonLoggerLog4j.java deleted file mode 100644 index 524db67ca..000000000 --- a/src/gov/nist/core/CommonLoggerLog4j.java +++ /dev/null @@ -1,298 +0,0 @@ -/* - * Conditions Of Use - * - * This software was developed by employees of the National Institute of - * Standards and Technology (NIST), an agency of the Federal Government. - * Pursuant to title 15 Untied States Code Section 105, works of NIST - * employees are not subject to copyright protection in the United States - * and are considered to be in the public domain. As a result, a formal - * license is not needed to use the software. - * - * This software is provided by NIST as a service and is expressly - * provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED - * OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT - * AND DATA ACCURACY. NIST does not warrant or make any representations - * regarding the use of the software or the results thereof, including but - * not limited to the correctness, accuracy, reliability or usefulness of - * the software. - * - * Permission to use this software is contingent upon your acceptance - * of the terms of this agreement. - * - */ -/*************************************************************************** - * Product of NIST/ITL Advanced Networking Technologies Division (ANTD). * - ***************************************************************************/ - -package gov.nist.core; - -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.Properties; - -import org.apache.log4j.Appender; -import org.apache.log4j.Level; -import org.apache.log4j.Logger; - -/** - * A wrapper around log4j that is used for logging debug and errors. You can - * replace this file if you want to change the way in which messages are logged. - * - * @version 1.0 - * - * @author Vladimir Ralev - * - */ - -public class CommonLoggerLog4j implements StackLogger { - - /** - * The logger to which we will write our logging output. - */ - private Logger logger; - - /** - * log a stack trace. This helps to look at the stack frame. - */ - public void logStackTrace() { - this.logStackTrace(TRACE_DEBUG); - - } - - public void logStackTrace(int traceLevel) { - - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - StackTraceElement[] ste = new Exception().getStackTrace(); - // Skip the log writer frame and log all the other stack frames. - for (int i = 1; i < ste.length; i++) { - String callFrame = "[" + ste[i].getFileName() + ":" - + ste[i].getLineNumber() + "]"; - pw.print(callFrame); - } - pw.close(); - String stackTrace = sw.getBuffer().toString(); - logger.debug(stackTrace); - - } - - /** - * Get the line count in the log stream. - * - * @return - */ - public int getLineCount() { - return 0; - } - - /** - * Get the logger. - * - * @return - */ - public Logger getLogger() { - return logger; - } - - - /** - * This method allows you to add an external appender. - * This is useful for the case when you want to log to - * a different log stream than a file. - * - * @param appender - */ - public void addAppender(Appender appender) { - - this.logger.addAppender(appender); - - } - - /** - * Log an exception. - * - * @param ex - */ - public void logException(Throwable ex) { - - logger.error("Error", ex); - } - - /** - * Log a message into the log file. - * - * @param message - * message to log into the log file. - */ - public void logDebug(String message) { - logger.debug(message); - - } - - /** - * Log a message into the log file. - * - * @param message - * message to log into the log file. - */ - public void logTrace(String message) { - logger.debug(message); - } - - /** - * Set the trace level for the stack. - */ - private void setTraceLevel(int level) { - // Nothing - } - - /** - * Get the trace level for the stack. - */ - public int getTraceLevel() { - return levelToInt(logger.getLevel()); - } - - /** - * Log an error message. - * - * @param message -- - * error message to log. - */ - public void logFatalError(String message) { - logger.fatal(message); - - } - - /** - * Log an error message. - * - * @param message -- - * error message to log. - * - */ - public void logError(String message) { - logger.error(message); - - } - - public CommonLoggerLog4j(Logger logger) { - this.logger = logger; - } - - public void setStackProperties(Properties configurationProperties) { - - // Do nothing (can't do anything here, this method is called only for legacy) - - } - - /** - * @return flag to indicate if logging is enabled. - */ - public boolean isLoggingEnabled() { - - return logger.isInfoEnabled(); - } - - /** - * Return true/false if loging is enabled at a given level. - * - * @param logLevel - */ - public boolean isLoggingEnabled(int logLevel) { - return logger.isEnabledFor(intToLevel(logLevel)); - } - - - /** - * Log an error message. - * - * @param message - * @param ex - */ - public void logError(String message, Exception ex) { - Logger logger = this.getLogger(); - logger.error(message, ex); - - } - - /** - * Log a warning mesasge. - * - * @param string - */ - public void logWarning(String string) { - getLogger().warn(string); - - } - - /** - * Log an info message. - * - * @param string - */ - public void logInfo(String string) { - getLogger().info(string); - } - - /** - * Disable logging altogether. - * - */ - public void disableLogging() { - // Do nothing - } - - /** - * Enable logging (globally). - */ - public void enableLogging() { - // Do nothing - - } - - public static Level intToLevel(int intLevel) { - switch(intLevel) { - case TRACE_INFO: return Level.INFO; - case TRACE_DEBUG: return Level.DEBUG; - case TRACE_ERROR: return Level.ERROR; - case TRACE_WARN: return Level.WARN; - case TRACE_TRACE: return Level.TRACE; - case TRACE_FATAL: return Level.FATAL; - } - return Level.OFF; - } - - public static int levelToInt(Level level) { - - if(level.equals(Level.INFO)) { - return TRACE_INFO; - } else if(level.equals(Level.ERROR)) { - return TRACE_ERROR; - } else if(level.equals(Level.DEBUG)) { - return TRACE_DEBUG; - } else if(level.equals(Level.WARN)) { - return TRACE_WARN; - } else if(level.equals(Level.TRACE)) { - return TRACE_TRACE; - } else if(level.equals(Level.FATAL)) { - return TRACE_FATAL; - } - return 0; - } - - public String getLoggerName() { - if ( this.logger != null ) { - return logger.getName(); - } else { - return null; - } - } - - public void setBuildTimeStamp(String buildTimeStamp) { - logger.info("Build timestamp: " + buildTimeStamp); - } - - -} diff --git a/src/gov/nist/core/Debug.java b/src/gov/nist/core/Debug.java index e414017f8..aae49d30f 100755 --- a/src/gov/nist/core/Debug.java +++ b/src/gov/nist/core/Debug.java @@ -45,8 +45,7 @@ public static void setStackLogger(StackLogger stackLogger) { public static void println(String s) { if ((parserDebug || debug )&& stackLogger != null ) - if ( stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - stackLogger.logDebug(s + "\n"); + stackLogger.logDebug(s + "\n"); } public static void printStackTrace(Exception ex) { if ((parserDebug || debug ) && stackLogger != null) { @@ -56,8 +55,7 @@ public static void printStackTrace(Exception ex) { public static void logError(String message, Exception ex) { if ((parserDebug || debug) && stackLogger != null ) { - if ( stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - stackLogger.logError(message,ex); + stackLogger.logError(message,ex); } } diff --git a/src/gov/nist/core/DuplicateNameValueList.java b/src/gov/nist/core/DuplicateNameValueList.java index f522b02c2..53450afcd 100644 --- a/src/gov/nist/core/DuplicateNameValueList.java +++ b/src/gov/nist/core/DuplicateNameValueList.java @@ -44,16 +44,22 @@ public class DuplicateNameValueList implements Serializable, Cloneable { private MultiValueMapImpl nameValueMap = new MultiValueMapImpl(); + private String separator; private static final long serialVersionUID = -5611332957903796952L; public DuplicateNameValueList() { + this.separator = ";"; } // ------------------ + public void setSeparator(String separator) { + this.separator = separator; + } + /** * Encode the list in semicolon separated form. * @@ -61,10 +67,10 @@ public DuplicateNameValueList() * @since v1.0 */ public String encode() { - return encode(new StringBuilder()).toString(); + return encode(new StringBuffer()).toString(); } - public StringBuilder encode(StringBuilder buffer) { + public StringBuffer encode(StringBuffer buffer) { if (!nameValueMap.isEmpty()) { Iterator iterator = nameValueMap.values().iterator(); if (iterator.hasNext()) { @@ -77,7 +83,7 @@ public StringBuilder encode(StringBuilder buffer) { buffer.append(obj.toString()); } if (iterator.hasNext()) - buffer.append(Separators.SEMICOLON); + buffer.append(separator); else break; } @@ -180,7 +186,8 @@ public boolean delete(String name) { } public Object clone() { - DuplicateNameValueList retval = new DuplicateNameValueList(); + DuplicateNameValueList retval = new DuplicateNameValueList(); + retval.setSeparator(this.separator); Iterator it = this.nameValueMap.values().iterator(); while (it.hasNext()) { retval.set((NameValue) ((NameValue) it.next()).clone()); diff --git a/src/gov/nist/core/GenericObject.java b/src/gov/nist/core/GenericObject.java index 0e759c3ef..53eea6b59 100755 --- a/src/gov/nist/core/GenericObject.java +++ b/src/gov/nist/core/GenericObject.java @@ -704,9 +704,9 @@ public String debugDump(int indent) { public abstract String encode(); /** - * Put the encoded version of this object in the given StringBuilder. + * Put the encoded version of this object in the given StringBuffer. */ - public StringBuilder encode(StringBuilder buffer) { + public StringBuffer encode(StringBuffer buffer) { return buffer.append(encode()); } } diff --git a/src/gov/nist/core/GenericObjectList.java b/src/gov/nist/core/GenericObjectList.java index ab06513ae..30c12e2ca 100755 --- a/src/gov/nist/core/GenericObjectList.java +++ b/src/gov/nist/core/GenericObjectList.java @@ -101,6 +101,8 @@ public abstract class GenericObjectList extends LinkedList implem protected Class myClass; + protected String separator; + protected String getIndentation() { char[] chars = new char[indentation]; java.util.Arrays.fill(chars, ' '); @@ -142,6 +144,7 @@ protected GenericObjectList() { super(); listName = null; stringRep = ""; + separator = ";"; } protected GenericObjectList(String lname) { @@ -344,7 +347,7 @@ public void mergeObjects(GenericObjectList mergeList) { public String encode() { if (this.isEmpty()) return ""; - StringBuilder encoding = new StringBuilder(); + StringBuffer encoding = new StringBuffer(); ListIterator iterator = this.listIterator(); if (iterator.hasNext()) { while (true) { @@ -356,7 +359,7 @@ public String encode() { encoding.append(obj.toString()); } if (iterator.hasNext()) - encoding.append(Separators.SEMICOLON); + encoding.append(separator); else break; } @@ -369,7 +372,18 @@ public String encode() { */ public String toString() { return this.encode(); - } + } + + /** + * Set the separator (for encoding the list) + * + * @since v1.0 + * @param sep + * is the new seperator (default is semicolon) + */ + public void setSeparator(String sep) { + separator = sep; + } /** * Hash code. We never expect to put this in a hash table so return a constant. diff --git a/src/gov/nist/core/Host.java b/src/gov/nist/core/Host.java index 938ce6985..022d3091e 100755 --- a/src/gov/nist/core/Host.java +++ b/src/gov/nist/core/Host.java @@ -62,17 +62,13 @@ public class Host extends GenericObject { * determines whether or not the parser should be stripping them (as * opposed simply being blunt and throwing an exception). */ - private static boolean stripAddressScopeZones = false; + private boolean stripAddressScopeZones = false; private static final long serialVersionUID = -7233564517978323344L; protected static final int HOSTNAME = 1; protected static final int IPV4ADDRESS = 2; protected static final int IPV6ADDRESS = 3; - static { - stripAddressScopeZones = Boolean.getBoolean("gov.nist.core.STRIP_ADDR_SCOPES"); - } - /** hostName field */ protected String hostname; @@ -88,13 +84,19 @@ public class Host extends GenericObject { */ public Host() { addressType = HOSTNAME; + + stripAddressScopeZones + = Boolean.getBoolean("gov.nist.core.STRIP_ADDR_SCOPES"); } /** Constructor given host name or IP address. */ public Host(String hostName) throws IllegalArgumentException { if (hostName == null) - throw new IllegalArgumentException("null host name"); + throw new IllegalArgumentException("null host name"); + + stripAddressScopeZones + = Boolean.getBoolean("gov.nist.core.STRIP_ADDR_SCOPES"); setHost(hostName, IPV4ADDRESS); } @@ -104,6 +106,9 @@ public Host(String hostName) throws IllegalArgumentException { * @param addrType int to set */ public Host(String name, int addrType) { + stripAddressScopeZones + = Boolean.getBoolean("gov.nist.core.STRIP_ADDR_SCOPES"); + setHost(name, addrType); } @@ -112,10 +117,10 @@ public Host(String name, int addrType) { * @return String */ public String encode() { - return encode(new StringBuilder()).toString(); + return encode(new StringBuffer()).toString(); } - public StringBuilder encode(StringBuilder buffer) { + public StringBuffer encode(StringBuffer buffer) { if (addressType == IPV6ADDRESS && !isIPv6Reference(hostname)) { buffer.append('[').append(hostname).append(']'); } else { diff --git a/src/gov/nist/core/HostNameParser.java b/src/gov/nist/core/HostNameParser.java index 7adfe7803..aaf26d3fa 100755 --- a/src/gov/nist/core/HostNameParser.java +++ b/src/gov/nist/core/HostNameParser.java @@ -46,7 +46,7 @@ */ public class HostNameParser extends ParserCore { - + /** * Determines whether or not we should tolerate and strip address scope * zones from IPv6 addresses. Address scope zones are sometimes returned @@ -55,14 +55,13 @@ public class HostNameParser extends ParserCore { * determines whether or not the parser should be stripping them (as * opposed simply being blunt and throwing an exception). */ - private static boolean stripAddressScopeZones = false; - - static { - stripAddressScopeZones = Boolean.getBoolean("gov.nist.core.STRIP_ADDR_SCOPES"); - } + private boolean stripAddressScopeZones = false; public HostNameParser(String hname) { this.lexer = new LexerCore("charLexer", hname); + + stripAddressScopeZones + = Boolean.getBoolean("gov.nist.core.STRIP_ADDR_SCOPES"); } /** @@ -71,6 +70,9 @@ public HostNameParser(String hname) { public HostNameParser(LexerCore lexer) { this.lexer = lexer; lexer.selectLexer("charLexer"); + + stripAddressScopeZones + = Boolean.getBoolean("gov.nist.core.STRIP_ADDR_SCOPES"); } private static final char[] VALID_DOMAIN_LABEL_CHAR = @@ -87,7 +89,7 @@ protected void consumeDomainLabel() throws ParseException { } protected String ipv6Reference() throws ParseException { - StringBuilder retval = new StringBuilder(); + StringBuffer retval = new StringBuffer(); if (debug) dbg_enter("ipv6Reference"); @@ -178,7 +180,7 @@ else if( isIPv6Address(lexer.getRest()) ) lexer.consumeValidChars( new char[] {LexerCore.ALPHADIGIT_VALID_CHARS, ':'}); hostname - = new StringBuilder("[").append( + = new StringBuffer("[").append( lexer.getBuffer().substring(startPtr, lexer.getPtr())) .append("]").toString(); } diff --git a/src/gov/nist/core/HostPort.java b/src/gov/nist/core/HostPort.java index 8dec69f1e..b9be09805 100755 --- a/src/gov/nist/core/HostPort.java +++ b/src/gov/nist/core/HostPort.java @@ -69,10 +69,10 @@ public HostPort() { * @return String */ public String encode() { - return encode(new StringBuilder()).toString(); + return encode(new StringBuffer()).toString(); } - public StringBuilder encode(StringBuilder buffer) { + public StringBuffer encode(StringBuffer buffer) { host.encode(buffer); if (port != -1) buffer.append(COLON).append(port); diff --git a/src/gov/nist/core/LexerCore.java b/src/gov/nist/core/LexerCore.java index 2ee5a969f..a05381fc1 100755 --- a/src/gov/nist/core/LexerCore.java +++ b/src/gov/nist/core/LexerCore.java @@ -26,8 +26,7 @@ package gov.nist.core; import java.text.ParseException; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; +import java.util.Hashtable; /** A lexical analyzer that is used by all parsers in our implementation. * @@ -83,16 +82,15 @@ public class LexerCore extends StringTokenizer { public static final int AND = (int) '&'; public static final int UNDERSCORE = (int) '_'; - // jeand : using concurrent data structure to avoid excessive blocking witnessed during profiling - protected static final ConcurrentHashMap globalSymbolTable; - protected static final ConcurrentHashMap> lexerTables; - protected Map currentLexer; + protected static final Hashtable globalSymbolTable; + protected static final Hashtable lexerTables; + protected Hashtable currentLexer; protected String currentLexerName; protected Token currentMatch; static { - globalSymbolTable = new ConcurrentHashMap(); - lexerTables = new ConcurrentHashMap>(); + globalSymbolTable = new Hashtable(); + lexerTables = new Hashtable(); } protected void addKeyword(String name, int value) { @@ -100,8 +98,8 @@ protected void addKeyword(String name, int value) { // new Exception().printStackTrace(); Integer val = Integer.valueOf(value); currentLexer.put(name, val); -// if (!globalSymbolTable.containsKey(val)) - globalSymbolTable.putIfAbsent(val, name); + if (!globalSymbolTable.containsKey(val)) + globalSymbolTable.put(val, name); } public String lookupToken(int value) { @@ -113,14 +111,14 @@ public String lookupToken(int value) { } } -// protected Map addLexer(String lexerName) { -// currentLexer = (Map) lexerTables.get(lexerName); -// if (currentLexer == null) { -// currentLexer = new Hashtable(); -// lexerTables.put(lexerName, currentLexer); -// } -// return currentLexer; -// } + protected Hashtable addLexer(String lexerName) { + currentLexer = (Hashtable) lexerTables.get(lexerName); + if (currentLexer == null) { + currentLexer = new Hashtable(); + lexerTables.put(lexerName, currentLexer); + } + return currentLexer; + } //public abstract void selectLexer(String lexerName); @@ -129,7 +127,7 @@ public void selectLexer(String lexerName) { } protected LexerCore() { - this.currentLexer = new ConcurrentHashMap(); + this.currentLexer = new Hashtable(); this.currentLexerName = "charLexer"; } @@ -382,7 +380,7 @@ public String ttoken() { break; } } - return String.valueOf(buffer, startIdx, ptr - startIdx); + return buffer.substring(startIdx, ptr); } catch (ParseException ex) { return null; } @@ -474,7 +472,7 @@ public String ttokenSafe() { } } } - return String.valueOf(buffer, startIdx, ptr - startIdx); + return buffer.substring(startIdx, ptr); } catch (ParseException ex) { return null; } @@ -536,13 +534,13 @@ public String quotedString() throws ParseException { break; } else if (next == '\0') { throw new ParseException( - String.valueOf(this.buffer) + " :unexpected EOL", + this.buffer + " :unexpected EOL", this.ptr); } else if (next == '\\') { consume(1); } } - return String.valueOf(buffer, startIdx, ptr - startIdx - 1); + return buffer.substring(startIdx, ptr - 1); } /** Parse a comment string cursor is at a "(". Leave cursor at ) @@ -550,7 +548,7 @@ public String quotedString() throws ParseException { * closing brace. */ public String comment() throws ParseException { - StringBuilder retval = new StringBuilder(); + StringBuffer retval = new StringBuffer(); if (lookAhead(0) != '(') return null; consume(1); @@ -581,7 +579,7 @@ public String comment() throws ParseException { *@return a substring containing no semicolons. */ public String byteStringNoSemicolon() { - StringBuilder retval = new StringBuilder(); + StringBuffer retval = new StringBuffer(); try { while (true) { char next = lookAhead(0); @@ -605,7 +603,7 @@ public String byteStringNoSemicolon() { * @return substring containing no slash. */ public String byteStringNoSlash() { - StringBuilder retval = new StringBuilder(); + StringBuffer retval = new StringBuffer(); try { while (true) { char next = lookAhead(0); @@ -628,7 +626,7 @@ public String byteStringNoSlash() { */ public String byteStringNoComma() { - StringBuilder retval = new StringBuilder(); + StringBuffer retval = new StringBuffer(); try { while (true) { char next = lookAhead(0); @@ -652,7 +650,7 @@ public static String charAsString(char ch) { * Do not consume the input. */ public String charAsString(int nchars) { - return String.valueOf(buffer, ptr, nchars -1); + return buffer.substring(ptr, ptr + nchars); } /** Get and consume the next number. @@ -676,9 +674,9 @@ public String number() throws ParseException { } else break; } - return String.valueOf(buffer, startIdx, ptr - startIdx); + return buffer.substring(startIdx, ptr); } catch (ParseException ex) { - return String.valueOf(buffer, startIdx, ptr - startIdx); + return buffer.substring(startIdx, ptr); } } @@ -700,10 +698,10 @@ public void rewindInputPosition(int position) { * @return rest of the buffer. */ public String getRest() { - if (ptr > bufferLen) + if (ptr >= buffer.length()) return null; - else if ( ptr == bufferLen ) return ""; - else return String.valueOf(buffer, ptr, bufferLen - ptr); + else + return buffer.substring(ptr); } /** Get the sub-String until the character is encountered @@ -711,7 +709,7 @@ public String getRest() { * @return the substring that matches. */ public String getString(char c) throws ParseException { - StringBuilder retval = new StringBuilder(); + StringBuffer retval = new StringBuffer(); while (true) { char next = lookAhead(0); //System.out.println(" next = [" + next + ']' + "ptr = " + ptr); @@ -752,12 +750,12 @@ public int getPtr() { /** Get the buffer. */ public String getBuffer() { - return String.valueOf(buffer); + return this.buffer; } /** Create a parse exception. */ public ParseException createParseException() { - return new ParseException(getBuffer(), this.ptr); + return new ParseException(this.buffer, this.ptr); } } diff --git a/src/gov/nist/core/LogWriter.java b/src/gov/nist/core/LogWriter.java index 34d494c68..515f9669c 100755 --- a/src/gov/nist/core/LogWriter.java +++ b/src/gov/nist/core/LogWriter.java @@ -188,7 +188,7 @@ private void countLines(String message) { private String enhanceMessage(String message) { StackTraceElement[] stackTrace = new Exception().getStackTrace(); - StackTraceElement elem = stackTrace[3]; + StackTraceElement elem = stackTrace[2]; String className = elem.getClassName(); String methodName = elem.getMethodName(); String fileName = elem.getFileName(); @@ -305,8 +305,29 @@ public void setStackProperties(Properties configurationProperties) { logger = Logger.getLogger(category); if (logLevel != null) { - if (logLevel.equals("LOG4J")) { - CommonLogger.useLegacyLogger = false; + if (logLevel.equals("LOG4J")) { + //if TRACE_LEVEL property is specified as + //"LOG4J" then, set the traceLevel based on + //the log4j effective log level. + Level level = logger.getEffectiveLevel(); + this.needsLogging = true; + if (level == Level.OFF) { + this.needsLogging = false; + } + this.traceLevel = TRACE_NONE; + if (level.equals(Level.TRACE)) { + this.traceLevel = TRACE_TRACE; + } else if (level.equals(Level.DEBUG)) { + this.traceLevel = TRACE_DEBUG; + } else if (level.equals(Level.INFO)) { + this.traceLevel = TRACE_INFO; + } else if (level.equals(Level.ERROR)) { + this.traceLevel = TRACE_ERROR; + } else if (level.equals(Level.WARN)) { + this.traceLevel = TRACE_WARN; + } else if (level.equals(Level.FATAL)) { + this.traceLevel = TRACE_FATAL; + } } else { diff --git a/src/gov/nist/core/MultiValueMapImpl.java b/src/gov/nist/core/MultiValueMapImpl.java index c4c7a602d..04368e8ce 100644 --- a/src/gov/nist/core/MultiValueMapImpl.java +++ b/src/gov/nist/core/MultiValueMapImpl.java @@ -26,30 +26,26 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; public class MultiValueMapImpl implements MultiValueMap, Cloneable { - // jeand : lazy init of the map to reduce mem consumption - private HashMap> map = null; + private HashMap> map = new HashMap>(); private static final long serialVersionUID = 4275505380960964605L; public MultiValueMapImpl() { super(); + } - public List put(String key, V value) { - ArrayList keyList = null; - if(map != null) { - keyList = map.get(key); - } + public List put(String key, V value) { + ArrayList keyList = map.get(key); if (keyList == null) { - keyList = new ArrayList(); - getMap().put(key, keyList); + keyList = new ArrayList(10); + map.put(key, keyList); } keyList.add(value); @@ -57,10 +53,8 @@ public List put(String key, V value) { } public boolean containsValue(Object value) { - Set pairs = null; - if(map != null) { - pairs = map.entrySet(); - } + Set pairs = map.entrySet(); + if (pairs == null) return false; @@ -75,22 +69,17 @@ public boolean containsValue(Object value) { } public void clear() { - if(map != null) { - Set pairs = map.entrySet(); - Iterator pairsIterator = pairs.iterator(); - while (pairsIterator.hasNext()) { - Map.Entry keyValuePair = (Map.Entry) (pairsIterator.next()); - ArrayList list = (ArrayList) (keyValuePair.getValue()); - list.clear(); - } - map.clear(); - } + Set pairs = map.entrySet(); + Iterator pairsIterator = pairs.iterator(); + while (pairsIterator.hasNext()) { + Map.Entry keyValuePair = (Map.Entry) (pairsIterator.next()); + ArrayList list = (ArrayList) (keyValuePair.getValue()); + list.clear(); + } + map.clear(); } public Collection values() { - if(map == null) { - return new ArrayList(); - } ArrayList returnList = new ArrayList(map.size()); Set pairs = map.entrySet(); @@ -109,51 +98,31 @@ public Collection values() { public Object clone() { MultiValueMapImpl obj = new MultiValueMapImpl(); - if(map != null) { - obj.map = (HashMap>) this.map.clone(); - } + obj.map = (HashMap>) this.map.clone(); return obj; } public int size() { - if(map == null) { - return 0; - } return this.map.size(); } public boolean containsKey(Object key) { - if(map == null) { - return false; - } return map.containsKey(key); } public Set entrySet() { - if(map == null) { - return new HashSet(); - } return map.entrySet(); } public boolean isEmpty() { - if(map == null) { - return true; - } return map.isEmpty(); } public Set keySet() { - if(map == null) { - return new HashSet(); - } return this.map.keySet(); } public Object remove(String key, V item) { - if(map == null) { - return null; - } ArrayList list = this.map.get(key); if (list == null) { return null; @@ -163,20 +132,14 @@ public Object remove(String key, V item) { } public List get(Object key) { - if(map == null) { - return null; - } return map.get(key); } public List put(String key, List value) { - return this.getMap().put(key,(ArrayList) value); + return this.map.put(key,(ArrayList) value); } public List remove(Object key) { - if(map == null) { - return null; - } return map.remove(key); } @@ -184,19 +147,8 @@ public void putAll(Map< ? extends String, ? extends List> mapToPut) { for (String k : mapToPut.keySet()) { ArrayList al = new ArrayList(); al.addAll(mapToPut.get(k)); - getMap().put(k, al); + this.map.put(k, al); } } - - /** - * @return the map - */ - public HashMap> getMap() { - if(map == null) { - map = new HashMap>(0); - } - return map; - } - } diff --git a/src/gov/nist/core/NameValue.java b/src/gov/nist/core/NameValue.java index cd6ca6e2d..c3c339870 100755 --- a/src/gov/nist/core/NameValue.java +++ b/src/gov/nist/core/NameValue.java @@ -124,17 +124,8 @@ public String getName() { } public Object getValueAsObject() { - return getValueAsObject(true); - } - - public Object getValueAsObject(boolean stripQuotes) { if(isFlagParameter) return ""; // never return null for flag params - - // Issue 315 : (https://jain-sip.dev.java.net/issues/show_bug.cgi?id=315) - // header.getParameter() doesn't return quoted value - if(!stripQuotes && isQuotedString) - return quotes + value.toString() + quotes; // add the quotes for quoted string return value; } @@ -167,10 +158,10 @@ public void setValueAsObject(Object v) { * @return an encoded name value (eg. name=value) string. */ public String encode() { - return encode(new StringBuilder()).toString(); + return encode(new StringBuffer()).toString(); } - public StringBuilder encode(StringBuilder buffer) { + public StringBuffer encode(StringBuffer buffer) { if (name != null && value != null && !isFlagParameter) { if (GenericObject.isMySubclass(value.getClass())) { GenericObject gv = (GenericObject) value; @@ -275,7 +266,7 @@ public String getKey() { public String getValue() { if(value == null) - return null; + return null; return value.toString(); } @@ -295,4 +286,5 @@ public String setValue(String value) { public int hashCode() { return this.encode().toLowerCase().hashCode(); } + } diff --git a/src/gov/nist/core/NameValueList.java b/src/gov/nist/core/NameValueList.java index 1d11c8ae9..b30f69481 100755 --- a/src/gov/nist/core/NameValueList.java +++ b/src/gov/nist/core/NameValueList.java @@ -28,14 +28,15 @@ *******************************************************************************/ package gov.nist.core; +import java.util.concurrent.*; + import java.io.Serializable; import java.util.Collection; -import java.util.HashSet; +import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; /** * Implements a simple NameValue association with a quick lookup function (via a @@ -58,26 +59,21 @@ public class NameValueList implements Serializable, Cloneable, Map hmap; private String separator; - - private boolean sync = false; /** * default constructor. */ public NameValueList() { - this.separator = Separators.SEMICOLON; - //jeand : lazy loading of the map to save on mem consumption -// this.hmap = new LinkedHashMap(0); + this.separator = ";"; + this.hmap = new LinkedHashMap(); } public NameValueList(boolean sync) { - this.separator = Separators.SEMICOLON; - this.sync = sync; - //jeand : lazy loading of the map to save on mem consumption -// if (sync) -// this.hmap = new ConcurrentHashMap(0); -// else -// this.hmap = new LinkedHashMap(0); + this.separator = ";"; + if (sync) + this.hmap = new ConcurrentHashMap(); + else + this.hmap = new LinkedHashMap(); } public void setSeparator(String separator) { @@ -91,12 +87,12 @@ public void setSeparator(String separator) { * @since v1.0 */ public String encode() { - return encode(new StringBuilder()).toString(); + return encode(new StringBuffer()).toString(); } - public StringBuilder encode(StringBuilder buffer) { - if (!this.isEmpty()) { - Iterator iterator = this.iterator(); + public StringBuffer encode(StringBuffer buffer) { + if (!hmap.isEmpty()) { + Iterator iterator = hmap.values().iterator(); if (iterator.hasNext()) { while (true) { Object obj = iterator.next(); @@ -125,7 +121,7 @@ public String toString() { */ public void set(NameValue nv) { - this.put(nv.getName().toLowerCase(), nv); + this.hmap.put(nv.getName().toLowerCase(), nv); } /** @@ -133,7 +129,7 @@ public void set(NameValue nv) { */ public void set(String name, Object value) { NameValue nameValue = new NameValue(name, value); - this.put(name.toLowerCase(), nameValue); + hmap.put(name.toLowerCase(), nameValue); } @@ -153,15 +149,15 @@ public boolean equals(Object otherObject) { } NameValueList other = (NameValueList) otherObject; - if (this.size() != this.size()) { + if (hmap.size() != other.hmap.size()) { return false; } - Iterator li = this.getNames(); - + Iterator li = this.hmap.keySet().iterator(); + while (li.hasNext()) { String key = (String) li.next(); NameValue nv1 = this.getNameValue(key); - NameValue nv2 = (NameValue) other.get(key); + NameValue nv2 = (NameValue) other.hmap.get(key); if (nv2 == null) return false; else if (!nv2.equals(nv1)) @@ -174,16 +170,9 @@ else if (!nv2.equals(nv1)) * Do a lookup on a given name and return value associated with it. */ public Object getValue(String name) { - return getValue(name, true); - } - - /** - * Do a lookup on a given name and return value associated with it. - */ - public Object getValue(String name, boolean stripQuotes) { NameValue nv = this.getNameValue(name.toLowerCase()); if (nv != null) - return nv.getValueAsObject(stripQuotes); + return nv.getValueAsObject(); else return null; } @@ -194,10 +183,7 @@ public Object getValue(String name, boolean stripQuotes) { * @since 1.0 */ public NameValue getNameValue(String name) { - if(hmap == null) { - return null; - } - return (NameValue) hmap.get(name.toLowerCase()); + return (NameValue) this.hmap.get(name.toLowerCase()); } /** @@ -207,7 +193,7 @@ public NameValue getNameValue(String name) { * @since 1.0 */ public boolean hasNameValue(String name) { - return this.containsKey(name.toLowerCase()); + return hmap.containsKey(name.toLowerCase()); } /** @@ -217,8 +203,8 @@ public boolean hasNameValue(String name) { */ public boolean delete(String name) { String lcName = name.toLowerCase(); - if (this.containsKey(lcName)) { - this.remove(lcName); + if (this.hmap.containsKey(lcName)) { + this.hmap.remove(lcName); return true; } else { return false; @@ -229,11 +215,9 @@ public boolean delete(String name) { public Object clone() { NameValueList retval = new NameValueList(); retval.setSeparator(this.separator); - if(hmap != null) { - Iterator it = this.iterator(); - while (it.hasNext()) { - retval.set((NameValue) ((NameValue) it.next()).clone()); - } + Iterator it = this.hmap.values().iterator(); + while (it.hasNext()) { + retval.set((NameValue) ((NameValue) it.next()).clone()); } return retval; } @@ -242,19 +226,13 @@ public Object clone() { * Return the size of the embedded map */ public int size() { - if(hmap == null) { - return 0; - } - return hmap.size(); + return this.hmap.size(); } /** * Return true if empty. */ public boolean isEmpty() { - if(hmap == null) { - return true; - } return hmap.isEmpty(); } @@ -264,7 +242,7 @@ public boolean isEmpty() { * @return the iterator. */ public Iterator iterator() { - return this.getMap().values().iterator(); + return this.hmap.values().iterator(); } /** @@ -273,7 +251,7 @@ public Iterator iterator() { * @return a list iterator that has the names of the parameters. */ public Iterator getNames() { - return this.getMap().keySet().iterator(); + return this.hmap.keySet().iterator(); } @@ -283,16 +261,7 @@ public Iterator getNames() { * @return the parameter as a string. */ public String getParameter(String name) { - return getParameter(name, true); - } - - /** - * Get the parameter as a String. - * - * @return the parameter as a string. - */ - public String getParameter(String name, boolean stripQuotes) { - Object val = this.getValue(name, stripQuotes); + Object val = this.getValue(name); if (val == null) return null; if (val instanceof GenericObject) @@ -307,9 +276,7 @@ public String getParameter(String name, boolean stripQuotes) { */ public void clear() { - if(hmap != null) { - hmap.clear(); - } + this.hmap.clear(); } /* @@ -317,10 +284,7 @@ public void clear() { * @see java.util.Map#containsKey(java.lang.Object) */ public boolean containsKey(Object key) { - if(hmap == null) { - return false; - } - return hmap.containsKey(key.toString().toLowerCase()); + return this.hmap.containsKey(key.toString().toLowerCase()); } /* @@ -328,10 +292,7 @@ public boolean containsKey(Object key) { * @see java.util.Map#containsValue(java.lang.Object) */ public boolean containsValue(Object value) { - if(hmap == null) { - return false; - } - return hmap.containsValue(value); + return this.hmap.containsValue(value); } /* @@ -339,10 +300,7 @@ public boolean containsValue(Object value) { * @see java.util.Map#entrySet() */ public Set> entrySet() { - if(hmap == null) { - return new HashSet>(); - } - return hmap.entrySet(); + return this.hmap.entrySet(); } /* @@ -350,10 +308,7 @@ public Set> entrySet() { * @see java.util.Map#get(java.lang.Object) */ public NameValue get(Object key) { - if(hmap == null) { - return null; - } - return hmap.get(key.toString().toLowerCase()); + return this.hmap.get(key.toString().toLowerCase()); } /* @@ -361,10 +316,7 @@ public NameValue get(Object key) { * @see java.util.Map#keySet() */ public Set keySet() { - if(hmap == null) { - return new HashSet(); - } - return hmap.keySet(); + return this.hmap.keySet(); } /* @@ -372,11 +324,11 @@ public Set keySet() { * @see java.util.Map#put(java.lang.Object, java.lang.Object) */ public NameValue put(String name, NameValue nameValue) { - return this.getMap().put(name, nameValue); + return this.hmap.put(name, nameValue); } public void putAll(Map map) { - this.getMap().putAll(map); + this.hmap.putAll(map); } /* @@ -384,36 +336,19 @@ public void putAll(Map map) { * @see java.util.Map#remove(java.lang.Object) */ public NameValue remove(Object key) { - if(hmap == null) { - return null; - } - return this.getMap().remove(key.toString().toLowerCase()); + return this.hmap.remove(key.toString().toLowerCase()); } /* * (non-Javadoc) * @see java.util.Map#values() */ - public Collection values() { - return this.getMap().values(); + public Collection values() { + return this.hmap.values(); } @Override public int hashCode() { - return this.getMap().keySet().hashCode(); + return this.hmap.keySet().hashCode(); } - - /** - * @return the hmap - */ - protected Map getMap() { - if(this.hmap == null) { - if (sync) { - this.hmap = new ConcurrentHashMap(0); - } else { - this.hmap = new LinkedHashMap(0); - } - } - return hmap; - } } diff --git a/src/gov/nist/core/ParserCore.java b/src/gov/nist/core/ParserCore.java index 1d2a298fd..956221dd2 100755 --- a/src/gov/nist/core/ParserCore.java +++ b/src/gov/nist/core/ParserCore.java @@ -98,13 +98,13 @@ protected NameValue nameValue(char separator) throws ParseException { } protected void dbg_enter(String rule) { - StringBuilder stringBuilder = new StringBuilder(); + StringBuffer stringBuffer = new StringBuffer(); for (int i = 0; i < nesting_level ; i++) - stringBuilder.append(">"); + stringBuffer.append(">"); if (debug) { System.out.println( - stringBuilder + rule + + stringBuffer + rule + "\nlexer buffer = \n" + lexer.getRest()); } @@ -112,13 +112,13 @@ protected void dbg_enter(String rule) { } protected void dbg_leave(String rule) { - StringBuilder stringBuilder = new StringBuilder(); + StringBuffer stringBuffer = new StringBuffer(); for (int i = 0; i < nesting_level ; i++) - stringBuilder.append("<"); + stringBuffer.append("<"); if (debug) { System.out.println( - stringBuilder + + stringBuffer + rule + "\nlexer buffer = \n" + lexer.getRest()); diff --git a/src/gov/nist/core/StringTokenizer.java b/src/gov/nist/core/StringTokenizer.java index 2b8067054..ea779f5f7 100755 --- a/src/gov/nist/core/StringTokenizer.java +++ b/src/gov/nist/core/StringTokenizer.java @@ -40,8 +40,7 @@ public class StringTokenizer { - // jeand : moving to char array instead of string, more efficient CPU and mem wise - protected char[] buffer; + protected String buffer; protected int bufferLen; protected int ptr; protected int savedPtr; @@ -50,23 +49,23 @@ protected StringTokenizer() { } public StringTokenizer(String buffer) { - this.buffer = buffer.toCharArray(); + this.buffer = buffer; bufferLen = buffer.length(); ptr = 0; } public String nextToken() { int startIdx = ptr; - + while (ptr < bufferLen) { - char c = buffer[ptr]; + char c = buffer.charAt(ptr); ptr++; if (c == '\n') { break; } } - return String.valueOf(buffer, startIdx, ptr - startIdx); + return buffer.substring(startIdx, ptr); } public boolean hasMoreChars() { @@ -112,13 +111,13 @@ public static boolean isAlphaDigit(char ch) { public String getLine() { int startIdx = ptr; - while (ptr < bufferLen && buffer[ptr] != '\n') { + while (ptr < bufferLen && buffer.charAt(ptr) != '\n') { ptr++; } - if (ptr < bufferLen && buffer[ptr] == '\n') { + if (ptr < bufferLen && buffer.charAt(ptr) == '\n') { ptr++; } - return String.valueOf(buffer,startIdx, ptr - startIdx); + return buffer.substring(startIdx, ptr); } public String peekLine() { @@ -135,7 +134,7 @@ public char lookAhead() throws ParseException { public char lookAhead(int k) throws ParseException { // Debug.out.println("ptr = " + ptr); try { - return buffer[ptr + k]; + return buffer.charAt(ptr + k); } catch (IndexOutOfBoundsException e) { return '\0'; @@ -148,7 +147,7 @@ public char getNextChar() throws ParseException { buffer + " getNextChar: End of buffer", ptr); else - return buffer[ptr++]; + return buffer.charAt(ptr++); } public void consume() { @@ -182,7 +181,7 @@ else if (la == '\0') throw new ParseException("EOL reached", 0); consume(1); } - return String.valueOf(buffer, startIdx, ptr - startIdx); + return buffer.substring(startIdx, ptr); } /** get the SDP field name of the line @@ -193,7 +192,7 @@ public static String getSDPFieldName(String line) { return null; String fieldName = null; try { - int begin = line.indexOf(Separators.EQUALS); + int begin = line.indexOf("="); fieldName = line.substring(0, begin); } catch (IndexOutOfBoundsException e) { return null; @@ -202,3 +201,4 @@ public static String getSDPFieldName(String line) { } } + diff --git a/src/gov/nist/core/ThreadAuditor.java b/src/gov/nist/core/ThreadAuditor.java index 76c67feed..830e5ffb5 100644 --- a/src/gov/nist/core/ThreadAuditor.java +++ b/src/gov/nist/core/ThreadAuditor.java @@ -1,7 +1,6 @@ package gov.nist.core; import java.util.*; -import java.util.concurrent.ConcurrentHashMap; /** * Thread Auditor class: @@ -23,8 +22,7 @@ public class ThreadAuditor { /// Threads being monitored - //jeand : moved to concurrent to avoid blocking witnessed by profiler - private Map threadHandles = new ConcurrentHashMap(); + private Map threadHandles = new HashMap(); /// How often are threads supposed to ping private long pingIntervalInMillisecs = 0; @@ -78,7 +76,7 @@ public long getPingIntervalInMillisecs() { * @return a string representation of the object */ public String toString() { - StringBuilder toString = new StringBuilder() + StringBuffer toString = new StringBuffer() .append("Thread Name: ").append(thread.getName()) .append(", Alive: ").append(thread.isAlive()); return toString.toString(); @@ -101,7 +99,7 @@ public boolean isEnabled() { } /// Called by a thread that wants to be monitored - public ThreadHandle addCurrentThread() { + public synchronized ThreadHandle addCurrentThread() { // Create and return a thread handle but only add it // to the list of monitored threads if the auditor is enabled ThreadHandle threadHandle = new ThreadHandle(this); @@ -112,17 +110,17 @@ public ThreadHandle addCurrentThread() { } /// Stops monitoring a given thread - public void removeThread(Thread thread) { + public synchronized void removeThread(Thread thread) { threadHandles.remove(thread); } /// Called by a monitored thread reporting that it's alive and well - public void ping(ThreadHandle threadHandle) { + public synchronized void ping(ThreadHandle threadHandle) { threadHandle.setThreadActive(true); } /// Resets the auditor - public void reset() { + public synchronized void reset() { threadHandles.clear(); } @@ -131,7 +129,7 @@ public void reset() { * * @return An audit report string (multiple lines), or null if all is well */ - public String auditThreads() { + public synchronized String auditThreads() { String auditReport = null; // Map stackTraces = null; diff --git a/src/gov/nist/core/net/DefaultNetworkLayer.java b/src/gov/nist/core/net/DefaultNetworkLayer.java index e06a4cf23..8c5090068 100644 --- a/src/gov/nist/core/net/DefaultNetworkLayer.java +++ b/src/gov/nist/core/net/DefaultNetworkLayer.java @@ -26,6 +26,7 @@ package gov.nist.core.net; import java.io.IOException; +import java.net.ConnectException; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.InetSocketAddress; @@ -33,6 +34,7 @@ import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; +import java.net.SocketTimeoutException; /* Added by Daniel J. Martinez Manzano */ import javax.net.ssl.SSLSocket; @@ -116,10 +118,24 @@ public SSLSocket createSSLSocket(InetAddress address, int port, public Socket createSocket(InetAddress address, int port, InetAddress myAddress) throws IOException { - if (myAddress != null) - return new Socket(address, port, myAddress, 0); - else - return new Socket(address, port); + if (myAddress != null) { + Socket sock = new Socket(); + try { + sock.connect(new InetSocketAddress(address, port), 8000); + } catch (SocketTimeoutException e) { + throw new ConnectException("Socket timeout error (8sec)" + address + ":" + port); + } + return sock; + } + else { + Socket sock = new Socket(); + try { + sock.connect(new InetSocketAddress(address, port), 8000); + } catch (SocketTimeoutException e) { + throw new ConnectException("Socket timeout error (8sec)" + address + ":" + port); + } + return sock; + } } /** diff --git a/src/gov/nist/javax/sdp/MediaDescriptionImpl.java b/src/gov/nist/javax/sdp/MediaDescriptionImpl.java index 6cdebe179..da92b6e83 100755 --- a/src/gov/nist/javax/sdp/MediaDescriptionImpl.java +++ b/src/gov/nist/javax/sdp/MediaDescriptionImpl.java @@ -65,7 +65,7 @@ public class MediaDescriptionImpl implements javax.sdp.MediaDescription { * @since v1.0 */ public String encode() { - StringBuilder retval = new StringBuilder(); + StringBuffer retval = new StringBuffer(); if (mediaField != null) retval.append(mediaField.encode()); diff --git a/src/gov/nist/javax/sdp/SessionDescriptionImpl.java b/src/gov/nist/javax/sdp/SessionDescriptionImpl.java index 10c1f6006..9c92eebcd 100755 --- a/src/gov/nist/javax/sdp/SessionDescriptionImpl.java +++ b/src/gov/nist/javax/sdp/SessionDescriptionImpl.java @@ -1033,7 +1033,7 @@ public void setMediaDescriptions(Vector mediaDescriptions) } private String encodeVector(Vector vector) { - StringBuilder encBuff = new StringBuilder(); + StringBuffer encBuff = new StringBuffer(); for (int i = 0; i < vector.size(); i++) encBuff.append(vector.elementAt(i)); @@ -1051,7 +1051,7 @@ private String encodeVector(Vector vector) { */ public String toString() { - StringBuilder encBuff = new StringBuilder(); + StringBuffer encBuff = new StringBuffer(); // Encode single attributes encBuff.append(getVersion() == null ? "" : getVersion().toString()); diff --git a/src/gov/nist/javax/sdp/fields/MediaField.java b/src/gov/nist/javax/sdp/fields/MediaField.java index ca2ba5887..a3b3a944d 100755 --- a/src/gov/nist/javax/sdp/fields/MediaField.java +++ b/src/gov/nist/javax/sdp/fields/MediaField.java @@ -202,7 +202,7 @@ public void setMediaFormats(Vector mediaFormats) throws SdpException { } private String encodeFormats() { - StringBuilder retval = new StringBuilder(3 * formats.size ()); + StringBuffer retval = new StringBuffer(3 * formats.size ()); for (int i = 0; i < formats.size(); i++) { retval.append(formats.elementAt(i)); if (i < formats.size() - 1) diff --git a/src/gov/nist/javax/sdp/fields/PreconditionFields.java b/src/gov/nist/javax/sdp/fields/PreconditionFields.java index 0ae9d3974..3a528a932 100644 --- a/src/gov/nist/javax/sdp/fields/PreconditionFields.java +++ b/src/gov/nist/javax/sdp/fields/PreconditionFields.java @@ -31,7 +31,6 @@ package gov.nist.javax.sdp.fields; -import java.io.Serializable; import java.util.Vector; import javax.sdp.SdpException; import javax.sdp.SdpParseException; @@ -48,11 +47,11 @@ *

3GPP TS 24.299,

* IETF RFC3312 + RFC4032 (Precondition Mechanism). * - * Serialization fix contributed by aregr@dev.java.net - * * @author Miguel Freitas (IT) PT-Inovacao */ -public class PreconditionFields implements Serializable + + +public class PreconditionFields { // Media Description attributes for precondition diff --git a/src/gov/nist/javax/sdp/fields/RepeatField.java b/src/gov/nist/javax/sdp/fields/RepeatField.java index a42bff9f0..8c5f1a4b1 100755 --- a/src/gov/nist/javax/sdp/fields/RepeatField.java +++ b/src/gov/nist/javax/sdp/fields/RepeatField.java @@ -188,7 +188,7 @@ public void setTypedTime(boolean typedTime) { } public String encode() { - StringBuilder retval = new StringBuilder(); + StringBuffer retval = new StringBuffer(); retval.append(REPEAT_FIELD) .append(repeatInterval.encode()) .append(Separators.SP) diff --git a/src/gov/nist/javax/sdp/fields/SDPFieldList.java b/src/gov/nist/javax/sdp/fields/SDPFieldList.java index 6190a6717..c25e405d1 100755 --- a/src/gov/nist/javax/sdp/fields/SDPFieldList.java +++ b/src/gov/nist/javax/sdp/fields/SDPFieldList.java @@ -82,7 +82,7 @@ public SDPObject next() { * Encode into a canonical string. */ public String encode() { - StringBuilder retval = new StringBuilder(); + StringBuffer retval = new StringBuffer(); ListIterator li = sdpFields.listIterator(); while (li.hasNext()) { SDPField sdphdr = (SDPField) li.next(); diff --git a/src/gov/nist/javax/sdp/fields/SDPObjectList.java b/src/gov/nist/javax/sdp/fields/SDPObjectList.java index 8417acd1b..782640c1c 100755 --- a/src/gov/nist/javax/sdp/fields/SDPObjectList.java +++ b/src/gov/nist/javax/sdp/fields/SDPObjectList.java @@ -97,7 +97,7 @@ public GenericObject next() { public String encode() { - StringBuilder retval = new StringBuilder(); + StringBuffer retval = new StringBuffer(); SDPObject sdpObject; for (sdpObject = (SDPObject) this.first(); sdpObject != null; diff --git a/src/gov/nist/javax/sdp/fields/TimeField.java b/src/gov/nist/javax/sdp/fields/TimeField.java index 426e07221..b88cca00e 100755 --- a/src/gov/nist/javax/sdp/fields/TimeField.java +++ b/src/gov/nist/javax/sdp/fields/TimeField.java @@ -162,7 +162,7 @@ public void setZero() { * @since v1.0 */ public String encode() { - return new StringBuilder() + return new StringBuffer() .append(TIME_FIELD) .append(startTime) .append(Separators.SP) diff --git a/src/gov/nist/javax/sdp/fields/ZoneField.java b/src/gov/nist/javax/sdp/fields/ZoneField.java index 85ddfd466..c67f63e00 100755 --- a/src/gov/nist/javax/sdp/fields/ZoneField.java +++ b/src/gov/nist/javax/sdp/fields/ZoneField.java @@ -78,7 +78,7 @@ public SDPObjectList getZoneAdjustments() { * Encode this structure into a canonical form. */ public String encode() { - StringBuilder retval = new StringBuilder(ZONE_FIELD); + StringBuffer retval = new StringBuffer(ZONE_FIELD); ListIterator li = zoneAdjustments.listIterator(); int num = 0; while (li.hasNext()) { diff --git a/src/gov/nist/javax/sdp/parser/Lexer.java b/src/gov/nist/javax/sdp/parser/Lexer.java index c4588a1cd..9b0c6c551 100755 --- a/src/gov/nist/javax/sdp/parser/Lexer.java +++ b/src/gov/nist/javax/sdp/parser/Lexer.java @@ -36,7 +36,7 @@ public void selectLexer(String lexerName) { } public static String getFieldName(String line) { - int i = line.indexOf(Separators.EQUALS); + int i = line.indexOf("="); if (i == -1) return null; else @@ -45,9 +45,6 @@ public static String getFieldName(String line) { } /* * $Log: not supported by cvs2svn $ - * Revision 1.5 2009/07/17 18:57:16 emcho - * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. - * * Revision 1.4 2006/07/13 09:02:41 mranga * Issue number: * Obtained from: diff --git a/src/gov/nist/javax/sip/DialogExt.java b/src/gov/nist/javax/sip/DialogExt.java index 4173c164d..ede39cd4a 100644 --- a/src/gov/nist/javax/sip/DialogExt.java +++ b/src/gov/nist/javax/sip/DialogExt.java @@ -48,31 +48,8 @@ public interface DialogExt extends Dialog { */ public void disableSequenceNumberValidation(); - /** - * retrieve the value of release references to know if the stack performs optimizations - * on cleanup to save on memory - * @return release references value - * - * @since 2.0 - */ - public boolean isReleaseReferences(); + - /** - * If set to true it will release all references that it no longer needs. This will include the reference to the - * Request, Transactions, Any unused timers etc. This will significantly reduce memory - * consumption under high load - * @param releaseReferences - * - * @since 2.0 - */ - public void setReleaseReferences(boolean releaseReferences); - /** - * Sets the early dialog timeout period. Overrides the value set by the stack configuration property - * EARLY_DIALOG_TIMEOUT_SECONDS. - * A dialog may remain in early state indefinitely. UACs may kill a dialog in early state of periodic - * provisional responses are not seen for 3 minutes. This allows you to override the RFC - * specified value of 3 minutes hence allowing for fast fail over from unresponsive servers. - */ - public void setEarlyDialogTimeoutSeconds(int timeoutValue); + } diff --git a/src/gov/nist/javax/sip/DialogFilter.java b/src/gov/nist/javax/sip/DialogFilter.java index 2d7b2905e..abe842c02 100644 --- a/src/gov/nist/javax/sip/DialogFilter.java +++ b/src/gov/nist/javax/sip/DialogFilter.java @@ -28,12 +28,8 @@ ******************************************************************************/ package gov.nist.javax.sip; -import gov.nist.core.CommonLogger; -import gov.nist.core.HostPort; import gov.nist.core.InternalErrorHandler; -import gov.nist.core.LogLevels; import gov.nist.core.LogWriter; -import gov.nist.core.StackLogger; import gov.nist.javax.sip.address.SipUri; import gov.nist.javax.sip.header.Contact; import gov.nist.javax.sip.header.Event; @@ -41,6 +37,7 @@ import gov.nist.javax.sip.header.RetryAfter; import gov.nist.javax.sip.header.Route; import gov.nist.javax.sip.header.RouteList; +import gov.nist.javax.sip.header.Server; import gov.nist.javax.sip.message.MessageFactoryImpl; import gov.nist.javax.sip.message.SIPRequest; import gov.nist.javax.sip.message.SIPResponse; @@ -54,16 +51,19 @@ import gov.nist.javax.sip.stack.ServerResponseInterface; import java.io.IOException; +import java.util.TimerTask; import javax.sip.ClientTransaction; import javax.sip.DialogState; -import javax.sip.ListeningPoint; +import javax.sip.InvalidArgumentException; import javax.sip.ObjectInUseException; import javax.sip.RequestEvent; +import javax.sip.ResponseEvent; import javax.sip.ServerTransaction; import javax.sip.SipException; import javax.sip.SipProvider; import javax.sip.TransactionState; +import javax.sip.header.CSeqHeader; import javax.sip.header.EventHeader; import javax.sip.header.ReferToHeader; import javax.sip.header.ServerHeader; @@ -71,28 +71,24 @@ import javax.sip.message.Response; /* - * Bug fixes and Contributions by Lamine Brahimi, Andreas Bystrom, Bill Roome, John Martin, Daniel + * Bug fix Contributions by Lamine Brahimi, Andreas Bystrom, Bill Roome, John Martin, Daniel * Machin Vasquez-Illa, Antonis Karydas, Joe Provino, Bruce Evangelder, Jeroen van Bemmel, Robert - * S. Rosen, Vladimir Ralev + * S. Rosen. */ /** - * An adapter class from the JAIN implementation objects to the NIST-SIP stack. - * The primary purpose of this class is to do early rejection of bad messages - * and deliver meaningful messages to the application. This class is essentially - * a Dialog filter. It is a helper for the UAC Core. It checks for and rejects - * requests and responses which may be filtered out because of sequence number, - * Dialog not found, etc. Note that this is not part of the JAIN-SIP spec (it - * does not implement a JAIN-SIP interface). This is part of the glue that ties - * together the NIST-SIP stack and event model with the JAIN-SIP stack. This is - * strictly an implementation class. + * An adapter class from the JAIN implementation objects to the NIST-SIP stack. The primary + * purpose of this class is to do early rejection of bad messages and deliver meaningful messages + * to the application. This class is essentially a Dialog filter. It is a helper for the UAC Core. + * It checks for and rejects requests and responses which may be filtered out because of sequence + * number, Dialog not found, etc. Note that this is not part of the JAIN-SIP spec (it does not + * implement a JAIN-SIP interface). This is part of the glue that ties together the NIST-SIP stack + * and event model with the JAIN-SIP stack. This is strictly an implementation class. * - * @version 1.2 $Revision: 1.97 $ $Date: 2010-12-02 22:04:18 $ + * @version 1.2 $Revision: 1.75.2.4 $ $Date: 2010-11-23 19:23:10 $ * * @author M. Ranganathan */ class DialogFilter implements ServerRequestInterface, ServerResponseInterface { - - private static StackLogger logger = CommonLogger.getLogger(DialogFilter.class); protected SIPTransaction transactionChannel; @@ -113,11 +109,9 @@ public DialogFilter(SIPTransactionStack sipStack) { */ private void sendRequestPendingResponse(SIPRequest sipRequest, SIPServerTransaction transaction) { - if (transaction.getState() != TransactionState.TERMINATED) { - SIPResponse sipResponse = sipRequest - .createResponse(Response.REQUEST_PENDING); - ServerHeader serverHeader = MessageFactoryImpl - .getDefaultServerHeader(); + if ( transaction.getState() != TransactionState.TERMINATED ) { + SIPResponse sipResponse = sipRequest.createResponse(Response.REQUEST_PENDING); + ServerHeader serverHeader = MessageFactoryImpl.getDefaultServerHeader(); if (serverHeader != null) { sipResponse.setHeader(serverHeader); } @@ -131,8 +125,7 @@ private void sendRequestPendingResponse(SIPRequest sipRequest, transaction.sendResponse(sipResponse); transaction.releaseSem(); } catch (Exception ex) { - logger.logError( - "Problem sending error response", ex); + sipStack.getStackLogger().logError("Problem sending error response", ex); transaction.releaseSem(); sipStack.removeTransaction(transaction); } @@ -147,16 +140,14 @@ private void sendRequestPendingResponse(SIPRequest sipRequest, * @param reasonPhrase */ - private void sendBadRequestResponse(SIPRequest sipRequest, - SIPServerTransaction transaction, String reasonPhrase) { - if (transaction.getState() != TransactionState.TERMINATED) { - - SIPResponse sipResponse = sipRequest - .createResponse(Response.BAD_REQUEST); + private void sendBadRequestResponse(SIPRequest sipRequest, SIPServerTransaction transaction, + String reasonPhrase) { + + if ( transaction.getState() != TransactionState.TERMINATED ) { + SIPResponse sipResponse = sipRequest.createResponse(Response.BAD_REQUEST); if (reasonPhrase != null) sipResponse.setReasonPhrase(reasonPhrase); - ServerHeader serverHeader = MessageFactoryImpl - .getDefaultServerHeader(); + ServerHeader serverHeader = MessageFactoryImpl.getDefaultServerHeader(); if (serverHeader != null) { sipResponse.setHeader(serverHeader); } @@ -167,8 +158,7 @@ private void sendBadRequestResponse(SIPRequest sipRequest, transaction.sendResponse(sipResponse); transaction.releaseSem(); } catch (Exception ex) { - logger.logError( - "Problem sending error response", ex); + sipStack.getStackLogger().logError("Problem sending error response", ex); transaction.releaseSem(); sipStack.removeTransaction(transaction); @@ -183,33 +173,33 @@ private void sendBadRequestResponse(SIPRequest sipRequest, * @param transaction */ - private void sendCallOrTransactionDoesNotExistResponse( - SIPRequest sipRequest, SIPServerTransaction transaction) { + private void sendCallOrTransactionDoesNotExistResponse(SIPRequest sipRequest, + SIPServerTransaction transaction) { - if (transaction.getState() != TransactionState.TERMINATED) { + if ( transaction.getState() != TransactionState.TERMINATED ) { SIPResponse sipResponse = sipRequest - .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST); + .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST); - ServerHeader serverHeader = MessageFactoryImpl - .getDefaultServerHeader(); + ServerHeader serverHeader = MessageFactoryImpl.getDefaultServerHeader(); if (serverHeader != null) { sipResponse.setHeader(serverHeader); } - try { - if (sipRequest.getMethod().equals(Request.INVITE)) { - sipStack.addTransactionPendingAck(transaction); - } - transaction.sendResponse(sipResponse); - transaction.releaseSem(); - } catch (Exception ex) { - logger.logError( - "Problem sending error response", ex); - transaction.releaseSem(); - sipStack.removeTransaction(transaction); + if (transaction.getState() != TransactionState.TERMINATED) { + try { + if (sipRequest.getMethod().equals(Request.INVITE)) { + sipStack.addTransactionPendingAck(transaction); + } + transaction.sendResponse(sipResponse); + transaction.releaseSem(); + } catch (Exception ex) { + sipStack.getStackLogger().logError("Problem sending error response", ex); + transaction.releaseSem(); + sipStack.removeTransaction(transaction); + } } - } + } /** @@ -219,14 +209,11 @@ private void sendCallOrTransactionDoesNotExistResponse( * @param transaction * */ - private void sendLoopDetectedResponse(SIPRequest sipRequest, - SIPServerTransaction transaction) { - SIPResponse sipResponse = sipRequest - .createResponse(Response.LOOP_DETECTED); + private void sendLoopDetectedResponse(SIPRequest sipRequest, SIPServerTransaction transaction) { if (transaction.getState() != TransactionState.TERMINATED) { + SIPResponse sipResponse = sipRequest.createResponse(Response.LOOP_DETECTED); - ServerHeader serverHeader = MessageFactoryImpl - .getDefaultServerHeader(); + ServerHeader serverHeader = MessageFactoryImpl.getDefaultServerHeader(); if (serverHeader != null) { sipResponse.setHeader(serverHeader); } @@ -235,8 +222,7 @@ private void sendLoopDetectedResponse(SIPRequest sipRequest, transaction.sendResponse(sipResponse); transaction.releaseSem(); } catch (Exception ex) { - logger.logError( - "Problem sending error response", ex); + sipStack.getStackLogger().logError("Problem sending error response", ex); transaction.releaseSem(); sipStack.removeTransaction(transaction); @@ -254,16 +240,14 @@ private void sendLoopDetectedResponse(SIPRequest sipRequest, private void sendServerInternalErrorResponse(SIPRequest sipRequest, SIPServerTransaction transaction) { - if (transaction.getState() != TransactionState.TERMINATED) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug( - "Sending 500 response for out of sequence message"); - SIPResponse sipResponse = sipRequest - .createResponse(Response.SERVER_INTERNAL_ERROR); + if (transaction.getState() != TransactionState.TERMINATED ) { + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger() + .logDebug("Sending 500 response for out of sequence message"); + SIPResponse sipResponse = sipRequest.createResponse(Response.SERVER_INTERNAL_ERROR); sipResponse.setReasonPhrase("Request out of order"); if (MessageFactoryImpl.getDefaultServerHeader() != null) { - ServerHeader serverHeader = MessageFactoryImpl - .getDefaultServerHeader(); + ServerHeader serverHeader = MessageFactoryImpl.getDefaultServerHeader(); sipResponse.setHeader(serverHeader); } @@ -275,8 +259,7 @@ private void sendServerInternalErrorResponse(SIPRequest sipRequest, transaction.sendResponse(sipResponse); transaction.releaseSem(); } catch (Exception ex) { - logger.logError("Problem sending response", - ex); + sipStack.getStackLogger().logError("Problem sending response", ex); transaction.releaseSem(); sipStack.removeTransaction(transaction); } @@ -284,38 +267,31 @@ private void sendServerInternalErrorResponse(SIPRequest sipRequest, } /** - * Process a request. Check for various conditions in the dialog that can - * result in the message being dropped. Possibly return errors for these - * conditions. + * Process a request. Check for various conditions in the dialog that can result in the + * message being dropped. Possibly return errors for these conditions. * - * @exception SIPServerException - * is thrown when there is an error processing the request. + * @exception SIPServerException is thrown when there is an error processing the request. */ - public void processRequest(SIPRequest sipRequest, - MessageChannel incomingMessageChannel) { + public void processRequest(SIPRequest sipRequest, MessageChannel incomingMessageChannel) { // Generate the wrapper JAIN-SIP object. - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG) - && listeningPoint != null) - logger.logDebug( - "PROCESSING INCOMING REQUEST " + sipRequest - + " transactionChannel = " + transactionChannel - + " listening point = " - + listeningPoint.getIPAddress() + ":" - + listeningPoint.getPort()); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug( + "PROCESSING INCOMING REQUEST " + sipRequest + " transactionChannel = " + + transactionChannel + " listening point = " + + listeningPoint.getIPAddress() + ":" + listeningPoint.getPort()); if (listeningPoint == null) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug( + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug( "Dropping message: No listening point registered!"); return; } - SIPTransactionStack sipStack = (SIPTransactionStack) transactionChannel - .getSIPStack(); + SIPTransactionStack sipStack = (SIPTransactionStack) transactionChannel.getSIPStack(); SipProviderImpl sipProvider = listeningPoint.getProvider(); if (sipProvider == null) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug("No provider - dropping !!"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("No provider - dropping !!"); return; } @@ -326,20 +302,19 @@ public void processRequest(SIPRequest sipRequest, SIPServerTransaction transaction = (SIPServerTransaction) this.transactionChannel; if (transaction != null) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug( + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug( "transaction state = " + transaction.getState()); } - final String dialogId = sipRequest.getDialogId(true); + String dialogId = sipRequest.getDialogId(true); SIPDialog dialog = sipStack.getDialog(dialogId); /* - * Check if we got this request on the contact address of the dialog If - * not the dialog does not belong to this request. We check this - * condition if a contact address has been assigned to the dialog. - * Forgive the sins of B2BUA's that like to record route ACK's + * Check if we got this request on the contact address of the dialog If not the dialog + * does not belong to this request. We check this condition if a contact address has been + * assigned to the dialog. Forgive the sins of B2BUA's that like to record route ACK's */ if (dialog != null && sipProvider != dialog.getSipProvider()) { - final Contact contact = dialog.getMyContactHeader(); + Contact contact = dialog.getMyContactHeader(); if (contact != null) { SipUri contactUri = (SipUri) (contact.getAddress().getURI()); String ipAddress = contactUri.getHost(); @@ -348,8 +323,7 @@ public void processRequest(SIPRequest sipRequest, if (contactTransport == null) contactTransport = "udp"; if (contactPort == -1) { - if (contactTransport.equals("udp") - || contactTransport.equals("tcp")) + if (contactTransport.equals("udp") || contactTransport.equals("tcp")) contactPort = 5060; else contactPort = 5061; @@ -360,11 +334,10 @@ public void processRequest(SIPRequest sipRequest, if (ipAddress != null && (!ipAddress.equals(listeningPoint.getIPAddress()) || contactPort != listeningPoint .getPort())) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( - "nulling dialog -- listening point mismatch! " - + contactPort + " lp port = " - + listeningPoint.getPort()); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( + "nulling dialog -- listening point mismatch! " + contactPort + + " lp port = " + listeningPoint.getPort()); } dialog = null; @@ -374,56 +347,51 @@ public void processRequest(SIPRequest sipRequest, } /* - * RFC 3261 8.2.2.2 Merged requests: If the request has no tag in the To - * header field, the UAS core MUST check the request against ongoing - * transactions. If the From tag, Call-ID, and CSeq exactly match those - * associated with an ongoing transaction, but the request does not - * match that transaction (based on the matching rules in Section - * 17.2.3), the UAS core SHOULD generate a 482 (Loop Detected) response - * and pass it to the server transaction. This support is only enabled - * when the stack has been instructed to function with Automatic Dialog - * Support. + * RFC 3261 8.2.2.2 Merged requests: If the request has no tag in the To header field, the + * UAS core MUST check the request against ongoing transactions. If the From tag, Call-ID, + * and CSeq exactly match those associated with an ongoing transaction, but the request + * does not match that transaction (based on the matching rules in Section 17.2.3), the + * UAS core SHOULD generate a 482 (Loop Detected) response and pass it to the server + * transaction. This support is only enabled when the stack has been instructed to + * function with Automatic Dialog Support. */ - if (sipProvider.isDialogErrorsAutomaticallyHandled() + if ( sipProvider.isDialogErrorsAutomaticallyHandled() && sipRequest.getToTag() == null) { - if (sipStack.findMergedTransaction(sipRequest)) { + if ( sipStack + .findMergedTransaction(sipRequest)) { this.sendLoopDetectedResponse(sipRequest, transaction); return; } } - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug("dialogId = " + dialogId); - logger.logDebug("dialog = " + dialog); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("dialogId = " + dialogId); + sipStack.getStackLogger().logDebug("dialog = " + dialog); } /* - * RFC 3261 Section 16.4 If the first value in the Route header field - * indicates this proxy,the proxy MUST remove that value from the - * request . + * RFC 3261 Section 16.4 If the first value in the Route header field indicates this + * proxy,the proxy MUST remove that value from the request . */ // If the message is being processed // by a Proxy, then the proxy will take care of stripping the // Route header. If the request is being processed by an // endpoint, then the stack strips off the route header. - if (sipRequest.getHeader(Route.NAME) != null - && transaction.getDialog() != null) { - final RouteList routes = sipRequest.getRouteHeaders(); - final Route route = (Route) routes.getFirst(); - final SipUri uri = (SipUri) route.getAddress().getURI(); - final HostPort hostPort = uri.getHostPort(); + if (sipRequest.getHeader(Route.NAME) != null && transaction.getDialog() != null) { + RouteList routes = sipRequest.getRouteHeaders(); + Route route = (Route) routes.getFirst(); + SipUri uri = (SipUri) route.getAddress().getURI(); int port; - if (hostPort.hasPort()) { - port = hostPort.getPort(); + if (uri.getHostPort().hasPort()) { + port = uri.getHostPort().getPort(); } else { - if (listeningPoint.getTransport().equalsIgnoreCase( - ListeningPoint.TLS)) + if (listeningPoint.getTransport().equalsIgnoreCase("TLS")) port = 5061; else port = 5060; } - String host = hostPort.getHost().encode(); + String host = uri.getHost(); if ((host.equals(listeningPoint.getIPAddress()) || host .equalsIgnoreCase(listeningPoint.getSentBy())) && port == listeningPoint.getPort()) { @@ -433,84 +401,72 @@ public void processRequest(SIPRequest sipRequest, routes.removeFirst(); } } - final String sipRequestMethod = sipRequest.getMethod(); - if (sipRequestMethod.equals(Request.REFER) && dialog != null + + if (sipRequest.getMethod().equals(Request.REFER) && dialog != null && sipProvider.isDialogErrorsAutomaticallyHandled()) { /* - * An agent responding to a REFER method MUST return a 400 (Bad - * Request) if the request contained zero or more than one Refer-To - * header field values. + * An agent responding to a REFER method MUST return a 400 (Bad Request) if the + * request contained zero or more than one Refer-To header field values. */ - ReferToHeader sipHeader = (ReferToHeader) sipRequest - .getHeader(ReferTo.NAME); + ReferToHeader sipHeader = (ReferToHeader) sipRequest.getHeader(ReferTo.NAME); if (sipHeader == null) { - this.sendBadRequestResponse(sipRequest, transaction, - "Refer-To header is missing"); + this + .sendBadRequestResponse(sipRequest, transaction, + "Refer-To header is missing"); return; } /* - * A refer cannot be processed until previous transaction has been - * completed. + * A refer cannot be processed until previous transaction has been completed. */ - SIPTransaction lastTransaction = ((SIPDialog) dialog) - .getLastTransaction(); - if (lastTransaction != null - && sipProvider.isDialogErrorsAutomaticallyHandled()) { - final String lastTransactionMethod = lastTransaction.getMethod(); + SIPTransaction lastTransaction = ((SIPDialog) dialog).getLastTransaction(); + if (lastTransaction != null && sipProvider.isDialogErrorsAutomaticallyHandled()) { + SIPRequest lastRequest = (SIPRequest) lastTransaction.getRequest(); if (lastTransaction instanceof SIPServerTransaction) { - // Handle Pseudo State Trying on Server Transaction - if ((lastTransaction.getInternalState() == TransactionState._PROCEEDING - || lastTransaction.getInternalState() == TransactionState._TRYING) - && lastTransactionMethod.equals(Request.INVITE)) { - this - .sendRequestPendingResponse(sipRequest, - transaction); + if (lastTransaction.getState() == TransactionState.PROCEEDING + && lastRequest.getMethod().equals(Request.INVITE)) { + this.sendRequestPendingResponse(sipRequest, transaction); return; } - } else if (lastTransaction != null - && lastTransaction instanceof SIPClientTransaction) { - if (lastTransactionMethod.equals(Request.INVITE) - && lastTransaction.getInternalState() != TransactionState._TERMINATED - && lastTransaction.getInternalState() != TransactionState._COMPLETED) { - this - .sendRequestPendingResponse(sipRequest, - transaction); + } else if (lastTransaction != null && lastTransaction instanceof SIPClientTransaction) { + long cseqno = lastRequest.getCSeqHeader().getSeqNumber(); + String method = lastRequest.getMethod(); + if (method.equals(Request.INVITE) && lastTransaction.getState() != TransactionState.TERMINATED && + lastTransaction.getState() != TransactionState.COMPLETED ) { + this.sendRequestPendingResponse(sipRequest, transaction); return; } } } - } else if (sipRequestMethod.equals(Request.UPDATE)) { + } else if (sipRequest.getMethod().equals(Request.UPDATE)) { /* - * Got an UPDATE method and the user dialog does not exist and the - * user wants to be a User agent. + * Got an UPDATE method and the user dialog does not exist and the user wants to be a + * User agent. + * */ if (sipProvider.isAutomaticDialogSupportEnabled() && dialog == null) { - this.sendCallOrTransactionDoesNotExistResponse(sipRequest, - transaction); + this.sendCallOrTransactionDoesNotExistResponse(sipRequest, transaction); return; } - } else if (sipRequestMethod.equals(Request.ACK)) { + } else if (sipRequest.getMethod().equals(Request.ACK)) { if (transaction != null && transaction.isInviteTransaction()) { // This is an ack for a 3xx-6xx response. Just let the tx laer // take care of it. - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug( - "Processing ACK for INVITE Tx "); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Processing ACK for INVITE Tx "); + } else { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug( - "Processing ACK for dialog " + dialog); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Processing ACK for dialog " + dialog); if (dialog == null) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( - "Dialog does not exist " - + sipRequest.getFirstLine() + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( + "Dialog does not exist " + sipRequest.getFirstLine() + " isServerTransaction = " + true); } @@ -521,27 +477,26 @@ public void processRequest(SIPRequest sipRequest, } /* - * JvB: must never drop ACKs that dont match a transaction! - * One cannot be sure if it isn't an ACK for a 2xx response + * JvB: must never drop ACKs that dont match a transaction! One cannot be sure + * if it isn't an ACK for a 2xx response + * */ SIPServerTransaction ackTransaction = sipStack .findTransactionPendingAck(sipRequest); /* - * Found a transaction ( that we generated ) which is - * waiting for ACK. So ACK it and return. + * Found a transaction ( that we generated ) which is waiting for ACK. So ACK + * it and return. */ if (ackTransaction != null) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug( - "Found Tx pending ACK"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Found Tx pending ACK"); try { ackTransaction.setAckSeen(); sipStack.removeTransaction(ackTransaction); - sipStack - .removeTransactionPendingAck(ackTransaction); + sipStack.removeTransactionPendingAck(ackTransaction); } catch (Exception ex) { - if (logger.isLoggingEnabled()) { - logger.logError( + if (sipStack.isLoggingEnabled()) { + sipStack.getStackLogger().logError( "Problem terminating transaction", ex); } } @@ -551,100 +506,63 @@ public void processRequest(SIPRequest sipRequest, } else { if (!dialog.handleAck(transaction)) { if (!dialog.isSequnceNumberValidation()) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( "Dialog exists with loose dialog validation " + sipRequest.getFirstLine() - + " isServerTransaction = " - + true + " dialog = " + + " isServerTransaction = " + true + " dialog = " + dialog.getDialogId()); } SIPServerTransaction st = sipStack - .getRetransmissionAlertTransaction(dialogId); + .getRetransmissionAlertTransaction(dialogId); if (st != null && st.isRetransmissionAlertEnabled()) { - st.disableRetransmissionAlerts(); + st.disableRetransmissionAlerts(); } - // Issue 319 : https://jain-sip.dev.java.net/issues/show_bug.cgi?id=319 - // remove the pending ack to stop the transaction timer for transaction - // where the stack replied with a final error response. - SIPServerTransaction ackTransaction = sipStack - .findTransactionPendingAck(sipRequest); - /* - * Found a transaction ( that we generated ) which is - * waiting for ACK. So ACK it and return. - */ - if (ackTransaction != null) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug( - "Found Tx pending ACK"); - try { - ackTransaction.setAckSeen(); - sipStack.removeTransaction(ackTransaction); - sipStack - .removeTransactionPendingAck(ackTransaction); - } catch (Exception ex) { - if (logger.isLoggingEnabled()) { - logger.logError( - "Problem terminating transaction", ex); - } - } - } } else { - if (logger - .isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger - .logDebug( - "Dropping ACK - cannot find a transaction or dialog"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( + "Dropping ACK - cannot find a transaction or dialog"); } SIPServerTransaction ackTransaction = sipStack .findTransactionPendingAck(sipRequest); if (ackTransaction != null) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug( - "Found Tx pending ACK"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Found Tx pending ACK"); try { ackTransaction.setAckSeen(); sipStack.removeTransaction(ackTransaction); - sipStack - .removeTransactionPendingAck(ackTransaction); + sipStack.removeTransactionPendingAck(ackTransaction); } catch (Exception ex) { - if (logger.isLoggingEnabled()) { - logger - .logError( - "Problem terminating transaction", - ex); + if (sipStack.isLoggingEnabled()) { + sipStack.getStackLogger().logError( + "Problem terminating transaction", ex); } } } /* - * For test only we support a flag that will deliver - * retransmitted ACK for 200 OK responses to the - * listener. + * For test only we support a flag that will deliver retransmitted + * ACK for 200 OK responses to the listener. */ - if ((!sipStack - .isDeliverRetransmittedAckToListener()) - || (ackTransaction != null && !sipStack - .isNon2XXAckPassedToListener())) { - return; + if ( (! sipStack.isDeliverRetransmittedAckToListener() ) || ( ackTransaction != null && + !sipStack.isNon2XXAckPassedToListener() ) ) { + return; } } } else { - + dialog.addTransaction(transaction); transaction.passToListener(); dialog.addRoute(sipRequest); transaction.setDialog(dialog, dialogId); if (sipRequest.getMethod().equals(Request.INVITE) - && sipProvider - .isDialogErrorsAutomaticallyHandled()) { + && sipProvider.isDialogErrorsAutomaticallyHandled()) { sipStack.putInMergeTable(transaction, sipRequest); } /* - * Note that ACK is a pseudo transaction. It is never - * added to the stack and you do not get transaction - * terminated events on ACK. + * Note that ACK is a pseudo transaction. It is never added to the stack + * and you do not get transaction terminated events on ACK. */ if (sipStack.isDeliverTerminatedEventForAck()) { @@ -661,31 +579,28 @@ public void processRequest(SIPRequest sipRequest, } } } - } else if (sipRequestMethod.equals(Request.PRACK)) { + } else if (sipRequest.getMethod().equals(Request.PRACK)) { /* - * RFC 3262: A matching PRACK is defined as one within the same - * dialog as the response, and whose method, CSeq-num, and - * response-num in the RAck header field match, respectively, the - * method from the CSeq, the sequence number from the CSeq, and the - * sequence number from the RSeq of the reliable provisional - * response. + * RFC 3262: A matching PRACK is defined as one within the same dialog as the + * response, and whose method, CSeq-num, and response-num in the RAck header field + * match, respectively, the method from the CSeq, the sequence number from the CSeq, + * and the sequence number from the RSeq of the reliable provisional response. */ - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug( - "Processing PRACK for dialog " + dialog); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Processing PRACK for dialog " + dialog); if (dialog == null && sipProvider.isAutomaticDialogSupportEnabled()) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( - "Dialog does not exist " - + sipRequest.getFirstLine() + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( + "Dialog does not exist " + sipRequest.getFirstLine() + " isServerTransaction = " + true); } - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack + .getStackLogger() .logDebug( "Sending 481 for PRACK - automatic dialog support is enabled -- cant find dialog!"); } @@ -695,8 +610,7 @@ public void processRequest(SIPRequest sipRequest, try { sipProvider.sendResponse(notExist); } catch (SipException e) { - logger.logError( - "error sending response", e); + sipStack.getStackLogger().logError("error sending response", e); } if (transaction != null) { sipStack.removeTransaction(transaction); @@ -706,9 +620,8 @@ public void processRequest(SIPRequest sipRequest, } else if (dialog != null) { if (!dialog.handlePrack(sipRequest)) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug( - "Dropping out of sequence PRACK "); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Dropping out of sequence PRACK "); if (transaction != null) { sipStack.removeTransaction(transaction); transaction.releaseSem(); @@ -725,27 +638,23 @@ public void processRequest(SIPRequest sipRequest, } } } else { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger - .logDebug( - "Processing PRACK without a DIALOG -- this must be a proxy element"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug( + "Processing PRACK without a DIALOG -- this must be a proxy element"); } - } else if (sipRequestMethod.equals(Request.BYE)) { + } else if (sipRequest.getMethod().equals(Request.BYE)) { // Check for correct sequence numbering of the BYE if (dialog != null && !dialog.isRequestConsumable(sipRequest)) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug( - "Dropping out of sequence BYE " - + dialog.getRemoteSeqNumber() + " " + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug( + "Dropping out of sequence BYE " + dialog.getRemoteSeqNumber() + " " + sipRequest.getCSeq().getSeqNumber()); - if (dialog.getRemoteSeqNumber() >= sipRequest.getCSeq() - .getSeqNumber() - && transaction.getInternalState() == TransactionState._TRYING) { + if (dialog.getRemoteSeqNumber() >= sipRequest.getCSeq().getSeqNumber() + && transaction.getState() == TransactionState.TRYING) { - this.sendServerInternalErrorResponse(sipRequest, - transaction); + this.sendServerInternalErrorResponse(sipRequest, transaction); } // If the stack knows about the tx, then remove it. @@ -753,8 +662,7 @@ public void processRequest(SIPRequest sipRequest, sipStack.removeTransaction(transaction); return; - } else if (dialog == null - && sipProvider.isAutomaticDialogSupportEnabled()) { + } else if (dialog == null && sipProvider.isAutomaticDialogSupportEnabled()) { // Drop bye's with 481 if dialog does not exist. // If dialog support is enabled then // there must be a dialog associated with the bye @@ -768,16 +676,14 @@ public void processRequest(SIPRequest sipRequest, .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST); response.setReasonPhrase("Dialog Not Found"); - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger - .logDebug( - "dropping request -- automatic dialog " - + "support enabled and dialog does not exist!"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug( + "dropping request -- automatic dialog " + + "support enabled and dialog does not exist!"); try { transaction.sendResponse(response); } catch (SipException ex) { - logger.logError( - "Error in sending response", ex); + sipStack.getStackLogger().logError("Error in sending response", ex); } // If the stack knows about the tx, then remove it. if (transaction != null) { @@ -805,21 +711,20 @@ public void processRequest(SIPRequest sipRequest, InternalErrorHandler.handleException(ex); } } - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( "BYE Tx = " + transaction + " isMapped =" + transaction.isTransactionMapped()); } - } else if (sipRequestMethod.equals(Request.CANCEL)) { + } else if (sipRequest.getMethod().equals(Request.CANCEL)) { - SIPServerTransaction st = (SIPServerTransaction) sipStack - .findCancelTransaction(sipRequest, true); - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( - "Got a CANCEL, InviteServerTx = " + st - + " cancel Server Tx ID = " + transaction - + " isMapped = " + SIPServerTransaction st = (SIPServerTransaction) sipStack.findCancelTransaction( + sipRequest, true); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( + "Got a CANCEL, InviteServerTx = " + st + " cancel Server Tx ID = " + + transaction + " isMapped = " + transaction.isTransactionMapped()); } @@ -829,30 +734,25 @@ public void processRequest(SIPRequest sipRequest, // If the CANCEL comes in too late, there's not // much that the Listener can do so just do the // default action and avoid bothering the listener. - if (st != null - && st.getInternalState() == TransactionState._TERMINATED) { + if (st != null && st.getState() == SIPTransaction.TERMINATED_STATE) { // If transaction already exists but it is // too late to cancel the transaction then // just respond OK to the CANCEL and bail. - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug( - "Too late to cancel Transaction"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Too late to cancel Transaction"); // send OK and just ignore the CANCEL. try { - transaction.sendResponse(sipRequest - .createResponse(Response.OK)); + transaction.sendResponse(sipRequest.createResponse(Response.OK)); } catch (Exception ex) { - if (ex.getCause() != null - && ex.getCause() instanceof IOException) { + if (ex.getCause() != null && ex.getCause() instanceof IOException) { st.raiseIOExceptionEvent(); } } return; } - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug( - "Cancel transaction = " + st); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Cancel transaction = " + st); } if (transaction != null && st != null && st.getDialog() != null) { @@ -860,8 +760,7 @@ public void processRequest(SIPRequest sipRequest, // Set up the client tx and pass up to listener. transaction.setDialog((SIPDialog) st.getDialog(), dialogId); dialog = (SIPDialog) st.getDialog(); - } else if (st == null - && sipProvider.isAutomaticDialogSupportEnabled() + } else if (st == null && sipProvider.isAutomaticDialogSupportEnabled() && transaction != null) { // Could not find a invite tx corresponding to the CANCEL. // Automatic dialog support is enabled so I must behave like @@ -870,8 +769,8 @@ public void processRequest(SIPRequest sipRequest, SIPResponse response = sipRequest .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST); - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( "dropping request -- automatic dialog support " + "enabled and INVITE ST does not exist!"); } @@ -906,34 +805,30 @@ public void processRequest(SIPRequest sipRequest, InternalErrorHandler.handleException(ex); } } - } else if (sipRequestMethod.equals(Request.INVITE)) { + } else if (sipRequest.getMethod().equals(Request.INVITE)) { SIPTransaction lastTransaction = dialog == null ? null : dialog .getInviteTransaction(); /* - * RFC 3261 Chapter 14. A UAS that receives a second INVITE before - * it sends the final response to a first INVITE with a lower CSeq - * sequence number on the same dialog MUST return a 500 (Server - * Internal Error) response to the second INVITE and MUST include a - * Retry-After header field with a randomly chosen value of between - * 0 and 10 seconds. + * RFC 3261 Chapter 14. A UAS that receives a second INVITE before it sends the final + * response to a first INVITE with a lower CSeq sequence number on the same dialog + * MUST return a 500 (Server Internal Error) response to the second INVITE and MUST + * include a Retry-After header field with a randomly chosen value of between 0 and 10 + * seconds. */ - if (dialog != null - && transaction != null - && lastTransaction != null - && sipRequest.getCSeq().getSeqNumber() > dialog - .getRemoteSeqNumber() + if (dialog != null && transaction != null && lastTransaction != null + && sipRequest.getCSeq().getSeqNumber() > dialog.getRemoteSeqNumber() && lastTransaction instanceof SIPServerTransaction && sipProvider.isDialogErrorsAutomaticallyHandled() && dialog.isSequnceNumberValidation() && lastTransaction.isInviteTransaction() - && lastTransaction.getInternalState() != TransactionState._COMPLETED - && lastTransaction.getInternalState() != TransactionState._TERMINATED - && lastTransaction.getInternalState() != TransactionState._CONFIRMED) { + && lastTransaction.getState() != TransactionState.COMPLETED + && lastTransaction.getState() != TransactionState.TERMINATED + && lastTransaction.getState() != TransactionState.CONFIRMED) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( "Sending 500 response for out of sequence message"); } this.sendServerInternalErrorResponse(sipRequest, transaction); @@ -942,13 +837,11 @@ public void processRequest(SIPRequest sipRequest, } /* - * Saw an interleaved invite before ACK was sent. RFC 3261 Chapter - * 14. A UAS that receives an INVITE on a dialog while an INVITE it - * had sent on that dialog is in progress MUST return a 491 (Request - * Pending) response to the received INVITE. + * Saw an interleaved invite before ACK was sent. RFC 3261 Chapter 14. A UAS that + * receives an INVITE on a dialog while an INVITE it had sent on that dialog is in + * progress MUST return a 491 (Request Pending) response to the received INVITE. */ - lastTransaction = (dialog == null ? null : dialog - .getLastTransaction()); + lastTransaction = (dialog == null ? null : dialog.getLastTransaction()); if (dialog != null && sipProvider.isDialogErrorsAutomaticallyHandled() @@ -957,37 +850,32 @@ public void processRequest(SIPRequest sipRequest, && lastTransaction instanceof ClientTransaction && lastTransaction.getLastResponse() != null && lastTransaction.getLastResponse().getStatusCode() == 200 - && !dialog.isAckSent(lastTransaction.getLastResponse() - .getCSeq().getSeqNumber())) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger - .logDebug( - "Sending 491 response for client Dialog ACK not sent."); + && !dialog.isAckSent(lastTransaction.getLastResponse().getCSeq() + .getSeqNumber())) { + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( + "Sending 491 response for client Dialog ACK not sent."); } this.sendRequestPendingResponse(sipRequest, transaction); return; } - if (dialog != null - && lastTransaction != null + if (dialog != null && lastTransaction != null && sipProvider.isDialogErrorsAutomaticallyHandled() && lastTransaction.isInviteTransaction() - && lastTransaction instanceof ServerTransaction - // Handle Pseudo State Trying on Server Transaction - && (lastTransaction.getInternalState() == TransactionState._PROCEEDING - || lastTransaction.getInternalState() == TransactionState._TRYING)) { - // Note that the completed state will be reached when we have - // sent an error - // response and the terminated state will be reached when we - // have sent an OK - // response. We do not need to wait till the ACK to be seen. - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger - .logDebug( - "Sending 491 response. Last transaction is in PROCEEDING state."); - logger.logDebug( - "last Transaction state = " + lastTransaction - + " state " + lastTransaction.getState()); + && lastTransaction instanceof ServerTransaction + /* && !dialog.isAckSeen() */ + && lastTransaction.getState().equals(TransactionState.PROCEEDING) + ) { + // Note that the completed state will be reached when we have sent an error + // response and the terminated state will be reached when we have sent an OK + // response. We do not need to wait till the ACK to be seen. + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( + "Sending 491 response for server Dialog ACK not seen."); + sipStack.getStackLogger().logDebug("Last SipResponse sent " + dialog.getLastResponse()); + + sipStack.getStackLogger().logDebug("last Transaction state = " + lastTransaction + " state "+ lastTransaction.getState()); } this.sendRequestPendingResponse(sipRequest, transaction); return; @@ -999,57 +887,48 @@ public void processRequest(SIPRequest sipRequest, // sequentially within a dialog for RFC 3261 // Note BYE, CANCEL and ACK is handled above - so no check here. - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( - "CHECK FOR OUT OF SEQ MESSAGE " + dialog + " transaction " - + transaction); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( + "CHECK FOR OUT OF SEQ MESSAGE " + dialog + " transaction " + transaction); } - if (dialog != null && transaction != null - && !sipRequestMethod.equals(Request.BYE) - && !sipRequestMethod.equals(Request.CANCEL) - && !sipRequestMethod.equals(Request.ACK) - && !sipRequestMethod.equals(Request.PRACK)) { + if (dialog != null && transaction != null && !sipRequest.getMethod().equals(Request.BYE) + && !sipRequest.getMethod().equals(Request.CANCEL) + && !sipRequest.getMethod().equals(Request.ACK) + && !sipRequest.getMethod().equals(Request.PRACK)) { if (!dialog.isRequestConsumable(sipRequest)) { /* - * RFC 3261: "UAS Behavior" section (12.2.2): If the remote - * sequence number was not empty, but the sequence number of the - * request is lower than the remote sequence number, the request - * is out of order and MUST be rejected with a 500 (Server - * Internal Error) response. + * RFC 3261: "UAS Behavior" section (12.2.2): If the remote sequence number was + * not empty, but the sequence number of the request is lower than the remote + * sequence number, the request is out of order and MUST be rejected with a 500 + * (Server Internal Error) response. */ // Drop the request - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( - "Dropping out of sequence message " - + dialog.getRemoteSeqNumber() + " " - + sipRequest.getCSeq()); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( + "Dropping out of sequence message " + dialog.getRemoteSeqNumber() + + " " + sipRequest.getCSeq()); } // send error when stricly higher, ignore when == // (likely still processing, error would interrupt that) - /* - * && (transaction.getState() == TransactionState.TRYING || - * transaction .getState() == TransactionState.PROCEEDING) - */ + /* && (transaction.getState() == TransactionState.TRYING || transaction + .getState() == TransactionState.PROCEEDING) */ - if (dialog.getRemoteSeqNumber() > sipRequest.getCSeq() - .getSeqNumber() - && sipProvider.isDialogErrorsAutomaticallyHandled()) { - this.sendServerInternalErrorResponse(sipRequest, - transaction); + if (dialog.getRemoteSeqNumber() > sipRequest.getCSeq().getSeqNumber() + && sipProvider.isDialogErrorsAutomaticallyHandled() ) { + this.sendServerInternalErrorResponse(sipRequest, transaction); } else { - try { - transaction.terminate(); - } catch (ObjectInUseException e) { - if (logger.isLoggingEnabled()) { - logger.logError( - "Unexpected exception", e); - } - } + try { + transaction.terminate(); + } catch (ObjectInUseException e) { + if ( sipStack.isLoggingEnabled() ) { + sipStack.getStackLogger().logError("Unexpected exception",e); + } + } } return; } @@ -1058,8 +937,8 @@ public void processRequest(SIPRequest sipRequest, if (sipProvider == dialog.getSipProvider()) { sipStack.addTransaction(transaction); // This will set the remote sequence number. - if (!dialog.addTransaction(transaction)) { - return; + if ( ! dialog.addTransaction(transaction) ) { + return; } dialog.addRoute(sipRequest); transaction.setDialog(dialog, dialogId); @@ -1075,70 +954,62 @@ public void processRequest(SIPRequest sipRequest, RequestEvent sipEvent; - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( sipRequest.getMethod() + " transaction.isMapped = " + transaction.isTransactionMapped()); } /* - * RFC 3265: Each event package MUST specify whether forked SUBSCRIBE - * requests are allowed to install multiple subscriptions. If such - * behavior is not allowed, the first potential dialog- establishing - * message will create a dialog. All subsequent NOTIFY messages which - * correspond to the SUBSCRIBE message (i.e., match "To", "From", "From" - * header "tag" parameter, "Call-ID", "CSeq", "Event", and "Event" - * header "id" parameter) but which do not match the dialog would be - * rejected with a 481 response. Note that the 200-class response to the - * SUBSCRIBE can arrive after a matching NOTIFY has been received; such - * responses might not correlate to the same dialog established by the - * NOTIFY. Except as required to complete the SUBSCRIBE transaction, - * such non-matching 200-class responses are ignored. + * RFC 3265: Each event package MUST specify whether forked SUBSCRIBE requests are allowed + * to install multiple subscriptions. If such behavior is not allowed, the first potential + * dialog- establishing message will create a dialog. All subsequent NOTIFY messages which + * correspond to the SUBSCRIBE message (i.e., match "To", "From", "From" header "tag" + * parameter, "Call-ID", "CSeq", "Event", and "Event" header "id" parameter) but which do + * not match the dialog would be rejected with a 481 response. Note that the 200-class + * response to the SUBSCRIBE can arrive after a matching NOTIFY has been received; such + * responses might not correlate to the same dialog established by the NOTIFY. Except as + * required to complete the SUBSCRIBE transaction, such non-matching 200-class responses + * are ignored. */ - if (dialog == null && sipRequestMethod.equals(Request.NOTIFY)) { + if (dialog == null && sipRequest.getMethod().equals(Request.NOTIFY)) { - SIPClientTransaction pendingSubscribeClientTx = sipStack - .findSubscribeTransaction(sipRequest, listeningPoint); + SIPClientTransaction pendingSubscribeClientTx = sipStack.findSubscribeTransaction( + sipRequest, listeningPoint); - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( - "PROCESSING NOTIFY DIALOG == null " - + pendingSubscribeClientTx); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( + "PROCESSING NOTIFY DIALOG == null " + pendingSubscribeClientTx); } /* - * RFC 3265: Upon receiving a NOTIFY request, the subscriber should - * check that it matches at least one of its outstanding - * subscriptions; if not, it MUST return a - * "481 Subscription does not exist" response unless another 400- or - * -class response is more appropriate. + * RFC 3265: Upon receiving a NOTIFY request, the subscriber should check that it + * matches at least one of its outstanding subscriptions; if not, it MUST return a + * "481 Subscription does not exist" response unless another 400- or -class response + * is more appropriate. */ - if (sipProvider.isAutomaticDialogSupportEnabled() - && pendingSubscribeClientTx == null + if (sipProvider.isAutomaticDialogSupportEnabled() && pendingSubscribeClientTx == null && !sipStack.isDeliverUnsolicitedNotify()) { /* - * This is the case of the UAC receiving a Stray NOTIFY for - * which it has not previously sent out a SUBSCRIBE and for - * which it does not have an established dialog. + * This is the case of the UAC receiving a Stray NOTIFY for which it has not + * previously sent out a SUBSCRIBE and for which it does not have an established + * dialog. */ try { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( "Could not find Subscription for Notify Tx."); } Response errorResponse = sipRequest .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST); - errorResponse - .setReasonPhrase("Subscription does not exist"); + errorResponse.setReasonPhrase("Subscription does not exist"); sipProvider.sendResponse(errorResponse); return; } catch (Exception ex) { - logger - .logError( - "Exception while sending error response statelessly", - ex); + sipStack.getStackLogger().logError( + "Exception while sending error response statelessly", ex); return; } @@ -1161,25 +1032,21 @@ public void processRequest(SIPRequest sipRequest, .getDefaultDialog(); // TODO -- refactor this. Can probably be written far cleaner. - if (subscriptionDialog == null - || subscriptionDialog.getDialogId() == null + if (subscriptionDialog == null || subscriptionDialog.getDialogId() == null || !subscriptionDialog.getDialogId().equals(dialogId)) { // Notify came in before you could assign a response to // the subscribe. // grab the default dialog and assign it to the tags in // the notify. - if (subscriptionDialog != null - && subscriptionDialog.getDialogId() == null) { + if (subscriptionDialog != null && subscriptionDialog.getDialogId() == null) { subscriptionDialog.setDialogId(dialogId); } else { - subscriptionDialog = pendingSubscribeClientTx - .getDialog(dialogId); + subscriptionDialog = pendingSubscribeClientTx.getDialog(dialogId); } - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( - "PROCESSING NOTIFY Subscribe DIALOG " - + subscriptionDialog); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( + "PROCESSING NOTIFY Subscribe DIALOG " + subscriptionDialog); } // The user could have createed a dialog before sending out @@ -1187,8 +1054,7 @@ public void processRequest(SIPRequest sipRequest, if (subscriptionDialog == null && (sipProvider.isAutomaticDialogSupportEnabled() || pendingSubscribeClientTx .getDefaultDialog() != null)) { - Event event = (Event) sipRequest - .getHeader(EventHeader.NAME); + Event event = (Event) sipRequest.getHeader(EventHeader.NAME); if (sipStack.isEventForked(event.getEventType())) { subscriptionDialog = SIPDialog.createFromNOTIFY( @@ -1199,16 +1065,13 @@ public void processRequest(SIPRequest sipRequest, } if (subscriptionDialog != null) { transaction.setDialog(subscriptionDialog, dialogId); - if (subscriptionDialog.getState() != DialogState.CONFIRMED) { - subscriptionDialog - .setPendingRouteUpdateOn202Response(sipRequest); - + if ( subscriptionDialog.getState() != DialogState.CONFIRMED ) { + subscriptionDialog.setPendingRouteUpdateOn202Response(sipRequest); + } - subscriptionDialog.setState(DialogState.CONFIRMED - .getValue()); + subscriptionDialog.setState(DialogState.CONFIRMED.getValue()); sipStack.putDialog(subscriptionDialog); - pendingSubscribeClientTx.setDialog(subscriptionDialog, - dialogId); + pendingSubscribeClientTx.setDialog(subscriptionDialog, dialogId); if (!transaction.isTransactionMapped()) { this.sipStack.mapTransaction(transaction); // Let the listener see it if it just got @@ -1242,43 +1105,36 @@ public void processRequest(SIPRequest sipRequest, } sipStack.putDialog(subscriptionDialog); if (pendingSubscribeClientTx != null) { - subscriptionDialog - .addTransaction(pendingSubscribeClientTx); - pendingSubscribeClientTx.setDialog(subscriptionDialog, - dialogId); + subscriptionDialog.addTransaction(pendingSubscribeClientTx); + pendingSubscribeClientTx.setDialog(subscriptionDialog, dialogId); } } if (transaction != null - && ((SIPServerTransaction) transaction) - .isTransactionMapped()) { + && ((SIPServerTransaction) transaction).isTransactionMapped()) { // Shadow transaction has been created and the stack // knows // about it. - sipEvent = new RequestEventExt((SipProvider) sipProvider, - (ServerTransaction) transaction, - subscriptionDialog, (Request) sipRequest); - + sipEvent = new RequestEvent((SipProvider) sipProvider, + (ServerTransaction) transaction, subscriptionDialog, + (Request) sipRequest); } else { - /* - * Shadow transaction has been created but the stack does - * not know about it. - */ - sipEvent = new RequestEventExt((SipProvider) sipProvider, - null, subscriptionDialog, (Request) sipRequest); - + // Shadow transaction has been created but the stack + // does + // not know + // about it. + sipEvent = new RequestEvent((SipProvider) sipProvider, null, + subscriptionDialog, (Request) sipRequest); } } else { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( - "could not find subscribe tx"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("could not find subscribe tx"); } // Got a notify out of the blue - just pass it up // for stateless handling by the application. - sipEvent = new RequestEventExt(sipProvider, null, null, - (Request) sipRequest); + sipEvent = new RequestEvent(sipProvider, null, null, (Request) sipRequest); } } else { @@ -1286,20 +1142,13 @@ public void processRequest(SIPRequest sipRequest, // For a dialog creating event - set the transaction to null. // The listener can create the dialog if needed. if (transaction != null - && (((SIPServerTransaction) transaction) - .isTransactionMapped())) { - sipEvent = new RequestEventExt(sipProvider, - (ServerTransaction) transaction, dialog, + && (((SIPServerTransaction) transaction).isTransactionMapped())) { + sipEvent = new RequestEvent(sipProvider, (ServerTransaction) transaction, dialog, (Request) sipRequest); } else { - sipEvent = new RequestEventExt(sipProvider, null, dialog, - (Request) sipRequest); - + sipEvent = new RequestEvent(sipProvider, null, dialog, (Request) sipRequest); } - } - ((RequestEventExt) sipEvent).setRemoteIpAddress(sipRequest.getRemoteAddress().getHostAddress()); - ((RequestEventExt)sipEvent).setRemotePort(sipRequest.getRemotePort()); sipProvider.handleEvent(sipEvent, transaction); } @@ -1307,31 +1156,26 @@ public void processRequest(SIPRequest sipRequest, /** * Process the response. * - * @exception SIPServerException - * is thrown when there is an error processing the response - * @param incomingMessageChannel - * -- message channel on which the response is received. + * @exception SIPServerException is thrown when there is an error processing the response + * @param incomingMessageChannel -- message channel on which the response is received. */ - public void processResponse(SIPResponse response, - MessageChannel incomingMessageChannel, SIPDialog dialog) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( - "PROCESSING INCOMING RESPONSE" - + response.encodeMessage(new StringBuilder())); + public void processResponse(SIPResponse response, MessageChannel incomingMessageChannel, + SIPDialog dialog) { + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( + "PROCESSING INCOMING RESPONSE" + response.encodeMessage()); } if (listeningPoint == null) { - if (logger.isLoggingEnabled()) - logger - .logError( - "Dropping message: No listening point" - + " registered!"); + if (sipStack.isLoggingEnabled()) + sipStack.getStackLogger().logError( + "Dropping message: No listening point" + " registered!"); return; } - if (sipStack.checkBranchId() - && !Utils.getInstance().responseBelongsToUs(response)) { - if (logger.isLoggingEnabled()) { - logger + if (sipStack.checkBranchId() && !Utils.getInstance().responseBelongsToUs(response)) { + if (sipStack.isLoggingEnabled()) { + sipStack + .getStackLogger() .logError( "Dropping response - topmost VIA header does not originate from this stack"); } @@ -1340,16 +1184,14 @@ public void processResponse(SIPResponse response, SipProviderImpl sipProvider = listeningPoint.getProvider(); if (sipProvider == null) { - if (logger.isLoggingEnabled()) { - logger.logError( - "Dropping message: no provider"); + if (sipStack.isLoggingEnabled()) { + sipStack.getStackLogger().logError("Dropping message: no provider"); } return; } if (sipProvider.getSipListener() == null) { - if (logger.isLoggingEnabled()) { - logger.logError( - "No listener -- dropping response!"); + if (sipStack.isLoggingEnabled()) { + sipStack.getStackLogger().logError("No listener -- dropping response!"); } return; } @@ -1357,9 +1199,8 @@ public void processResponse(SIPResponse response, SIPClientTransaction transaction = (SIPClientTransaction) this.transactionChannel; SIPTransactionStack sipStackImpl = sipProvider.sipStack; - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( - "Transaction = " + transaction); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStackImpl.getStackLogger().logDebug("Transaction = " + transaction); } if (transaction == null) { @@ -1369,21 +1210,22 @@ public void processResponse(SIPResponse response, // we cannot drop the response. if (dialog != null) { if (response.getStatusCode() / 100 != 2) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack + .getStackLogger() .logDebug( "Response is not a final response and dialog is found for response -- dropping response!"); } return; } else if (dialog.getState() == DialogState.TERMINATED) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( "Dialog is terminated -- dropping response!"); } return; } else { boolean ackAlreadySent = false; - if (dialog.isAckSeen() && dialog.getLastAckSent() != null) { + if ( dialog.isAckSeen() && dialog.getLastAckSent() != null) { if (dialog.getLastAckSent().getCSeq().getSeqNumber() == response .getCSeq().getSeqNumber()) { // the last ack sent corresponded to this 200 @@ -1392,80 +1234,52 @@ public void processResponse(SIPResponse response, } // 200 retransmission for the final response. if (ackAlreadySent - && response.getCSeq().getMethod().equals( - dialog.getMethod())) { + && response.getCSeq().getMethod().equals(dialog.getMethod())) { try { // Found the dialog - resend the ACK and // dont pass up the null transaction - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger - .logDebug( - "Retransmission of OK detected: Resending last ACK"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( + "Retransmission of OK detected: Resending last ACK"); } dialog.resendAck(); return; } catch (SipException ex) { // What to do here ?? kill the dialog? - logger.logError( - "could not resend ack", ex); + sipStack.getStackLogger().logError("could not resend ack", ex); } } } } - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( - "could not find tx, handling statelessly Dialog = " - + dialog); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( + "could not find tx, handling statelessly Dialog = " + dialog); } // Pass the response up to the application layer to handle // statelessly. - ResponseEventExt sipEvent = new ResponseEventExt(sipProvider, - transaction, dialog, (Response) response); - - if (sipStack.getMaxForkTime() != 0 - && SIPTransactionStack.isDialogCreated(response.getCSeqHeader().getMethod())) { - SIPClientTransaction forked = this.sipStack - .getForkedTransaction(response.getForkId()); - if(dialog != null && forked != null) { - dialog.checkRetransmissionForForking(response); - if(forked.getDefaultDialog() != null && !dialog.equals(forked.getDefaultDialog())) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( - "forked dialog " + dialog + " original tx " + forked + " original dialog " + forked.getDefaultDialog()); - } - sipEvent.setOriginalTransaction(forked); - sipEvent.setForkedResponse(true); - } - } + ResponseEventExt sipEvent = new ResponseEventExt(sipProvider, transaction, dialog, + (Response) response); + + if (sipStack.getMaxForkTime() != 0 && response.getCSeqHeader().getMethod().equals(Request.INVITE) ) { + SIPClientTransaction forked = this.sipStack.getForkedTransaction(response.getForkId()); + sipEvent.setOriginalTransaction(forked); } - sipEvent.setRetransmission(response.isRetransmission()); - - sipEvent.setRemoteIpAddress(response.getRemoteAddress().getHostAddress()); - sipEvent.setRemotePort(response.getRemotePort()); + sipProvider.handleEvent(sipEvent, transaction); return; } + ResponseEventExt responseEvent = null; + // Here if there is an assigned dialog - ResponseEventExt responseEvent = new ResponseEventExt(sipProvider, - (ClientTransactionExt) transaction, dialog, (Response) response); - if (sipStack.getMaxForkTime() != 0 - && SIPTransactionStack.isDialogCreated(response.getCSeqHeader().getMethod())) { - SIPClientTransaction forked = this.sipStack - .getForkedTransaction(response.getForkId()); - if(dialog != null && forked != null) { - dialog.checkRetransmissionForForking(response); - if(forked.getDefaultDialog() != null && !dialog.equals(forked.getDefaultDialog())) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( - "forked dialog " + dialog + " original tx " + forked + " original dialog " + forked.getDefaultDialog()); - } - responseEvent.setOriginalTransaction(forked); - responseEvent.setForkedResponse(true); - } - } + responseEvent = new ResponseEventExt(sipProvider, (ClientTransactionExt) transaction, + dialog, (Response) response); + if (sipStack.getMaxForkTime() != 0 && response.getCSeqHeader().getMethod().equals(Request.INVITE)) { + SIPClientTransaction forked = this.sipStack.getForkedTransaction(response + .getForkId()); + responseEvent.setOriginalTransaction(forked); } // Set the Dialog for the response. @@ -1474,19 +1288,17 @@ public void processResponse(SIPResponse response, dialog.setLastResponse(transaction, response); transaction.setDialog(dialog, dialog.getDialogId()); } - responseEvent.setRetransmission(response.isRetransmission()); - responseEvent.setRemoteIpAddress(response.getRemoteAddress().getHostAddress()); - responseEvent.setRemotePort(response.getRemotePort()); + sipProvider.handleEvent(responseEvent, transaction); + } /** - * Just a placeholder. This is called from the stack for message logging. - * Auxiliary processing information can be passed back to be written into - * the log file. + * Just a placeholder. This is called from the stack for message logging. Auxiliary processing + * information can be passed back to be written into the log file. * - * @return auxiliary information that we may have generated during the - * message processing which is retrieved by the message logger. + * @return auxiliary information that we may have generated during the message processing + * which is retrieved by the message logger. */ public String getProcessingInfo() { return null; @@ -1495,53 +1307,44 @@ public String getProcessingInfo() { /* * (non-Javadoc) * - * @see - * gov.nist.javax.sip.stack.ServerResponseInterface#processResponse(gov. - * nist.javax.sip.message.SIPResponse, - * gov.nist.javax.sip.stack.MessageChannel) + * @see gov.nist.javax.sip.stack.ServerResponseInterface#processResponse(gov.nist.javax.sip.message.SIPResponse, + * gov.nist.javax.sip.stack.MessageChannel) */ - public void processResponse(SIPResponse sipResponse, - MessageChannel incomingChannel) { + public void processResponse(SIPResponse sipResponse, MessageChannel incomingChannel) { String dialogID = sipResponse.getDialogId(false); SIPDialog sipDialog = this.sipStack.getDialog(dialogID); String method = sipResponse.getCSeq().getMethod(); - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( - "PROCESSING INCOMING RESPONSE: " - + sipResponse.encodeMessage(new StringBuilder())); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( + "PROCESSING INCOMING RESPONSE: " + sipResponse.encodeMessage()); } - if (sipStack.checkBranchId() - && !Utils.getInstance().responseBelongsToUs(sipResponse)) { - if (logger.isLoggingEnabled()) { - logger.logError( - "Detected stray response -- dropping"); + if (sipStack.checkBranchId() && !Utils.getInstance().responseBelongsToUs(sipResponse)) { + if (sipStack.isLoggingEnabled()) { + sipStack.getStackLogger().logError("Detected stray response -- dropping"); } return; } if (listeningPoint == null) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger - .logDebug( - "Dropping message: No listening point" - + " registered!"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug( + "Dropping message: No listening point" + " registered!"); return; } SipProviderImpl sipProvider = listeningPoint.getProvider(); if (sipProvider == null) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( - "Dropping message: no provider"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("Dropping message: no provider"); } return; } if (sipProvider.getSipListener() == null) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( "Dropping message: no sipListener registered!"); } return; @@ -1554,78 +1357,58 @@ public void processResponse(SIPResponse sipResponse, // 3PCC). if (sipDialog == null && transaction != null) { sipDialog = transaction.getDialog(dialogID); - if (sipDialog != null - && sipDialog.getState() == DialogState.TERMINATED) + if (sipDialog != null && sipDialog.getState() == DialogState.TERMINATED) sipDialog = null; } - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug( - "Transaction = " + transaction + " sipDialog = " - + sipDialog); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug( + "Transaction = " + transaction + " sipDialog = " + sipDialog); if (this.transactionChannel != null) { - String originalFrom = ((SIPRequest) this.transactionChannel - .getRequest()).getFromTag(); + String originalFrom = ((SIPRequest) this.transactionChannel.getRequest()) + .getFromTag(); if (originalFrom == null ^ sipResponse.getFrom().getTag() == null) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug( - "From tag mismatch -- dropping response"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("From tag mismatch -- dropping response"); return; } if (originalFrom != null - && !originalFrom.equalsIgnoreCase(sipResponse.getFrom() - .getTag())) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug( - "From tag mismatch -- dropping response"); + && !originalFrom.equalsIgnoreCase(sipResponse.getFrom().getTag())) { + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("From tag mismatch -- dropping response"); return; } } - boolean createDialog = false; - if (SIPTransactionStack.isDialogCreated(method) - && sipResponse.getStatusCode() != 100 - && sipResponse.getFrom().getTag() != null - && sipResponse.getTo().getTag() != null && sipDialog == null) { - // Issue 317 : for forked response even if automatic dialog support is not enabled + if (sipStack.isDialogCreated(method) && sipResponse.getStatusCode() != 100 + && sipResponse.getFrom().getTag() != null && sipResponse.getTo().getTag() != null + && sipDialog == null) { + // Issue 317 : for forked response even if automatic dialog support is not enabled // a dialog should be created in the case where the original Tx already have a default dialog - // and the current dialog is null. This is also avoiding creating dialog automatically if the flag is not set + // and the current dialog is null. This is also avoiding creating dialog automatically if the flag is not set + boolean createDialog = false; if (sipProvider.isAutomaticDialogSupportEnabled()) { createDialog = true; - } - else { + } else if(!sipProvider.isAutomaticDialogSupportEnabled() && sipResponse.getCSeq().getMethod().equals(Request.INVITE) && sipStack.getMaxForkTime() > 0 && sipDialog == null) { ClientTransactionExt originalTx = this.sipStack .getForkedTransaction(sipResponse.getForkId()); if(originalTx != null && originalTx.getDefaultDialog() != null) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug( - "Need to create dialog for response = " + sipResponse); createDialog = true; } } - if (createDialog) { + if(createDialog) { if (this.transactionChannel != null) { if (sipDialog == null) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( - "Creating dialog for forked response " + sipResponse); - } // There could be an existing dialog for this response. sipDialog = sipStack.createDialog( - (SIPClientTransaction) this.transactionChannel, - sipResponse); + (SIPClientTransaction) this.transactionChannel, sipResponse); - this.transactionChannel.setDialog(sipDialog, - sipResponse.getDialogId(false)); + this.transactionChannel.setDialog(sipDialog, sipResponse + .getDialogId(false)); } } else { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( - "Creating dialog for forked response " + sipResponse); - } - sipDialog = this.sipStack.createDialog(sipProvider, - sipResponse); + sipDialog = this.sipStack.createDialog(sipProvider, sipResponse); } } @@ -1634,55 +1417,47 @@ public void processResponse(SIPResponse sipResponse, if (sipDialog != null && transaction == null && sipDialog.getState() != DialogState.TERMINATED) { if (sipResponse.getStatusCode() / 100 != 2) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug( + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug( "status code != 200 ; statusCode = " + sipResponse.getStatusCode()); } else if (sipDialog.getState() == DialogState.TERMINATED) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( "Dialog is terminated -- dropping response!"); } - // Dialog exists but was terminated - just create and send - // an ACK for the OK. + // Dialog exists but was terminated - just create and send an ACK for the OK. // It could be late arriving. if (sipResponse.getStatusCode() / 100 == 2 - && sipResponse.getCSeq().getMethod().equals( - Request.INVITE)) { + && sipResponse.getCSeq().getMethod().equals(Request.INVITE)) { try { - Request ackRequest = sipDialog - .createAck(sipResponse.getCSeq() - .getSeqNumber()); + Request ackRequest = sipDialog.createAck(sipResponse.getCSeq() + .getSeqNumber()); sipDialog.sendAck(ackRequest); } catch (Exception ex) { - logger.logError( - "Error creating ack", ex); + sipStack.getStackLogger().logError("Error creating ack", ex); } } return; } else { boolean ackAlreadySent = false; - if (/* sipDialog.isAckSeen() - && */ sipDialog.getLastAckSent() != null) { + if (sipDialog.isAckSeen() && sipDialog.getLastAckSent() != null) { if (sipDialog.getLastAckSent().getCSeq().getSeqNumber() == sipResponse .getCSeq().getSeqNumber() && sipResponse.getDialogId(false).equals( - sipDialog.getLastAckSent().getDialogId( - false))) { + sipDialog.getLastAckSent().getDialogId(false))) { // the last ack sent corresponded to this 200 ackAlreadySent = true; } } // 200 retransmission for the final response. if (ackAlreadySent - && sipResponse.getCSeq().getMethod().equals( - sipDialog.getMethod())) { + && sipResponse.getCSeq().getMethod().equals(sipDialog.getMethod())) { try { // Found the dialog - resend the ACK and // dont pass up the null transaction - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug( - "resending ACK"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("resending ACK"); sipDialog.resendAck(); return; @@ -1696,39 +1471,23 @@ public void processResponse(SIPResponse sipResponse, // statelessly. } - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug( - "sending response to TU for processing "); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("sending response to TU for processing "); + + if (sipDialog != null && sipResponse.getStatusCode() != 100 + && sipResponse.getTo().getTag() != null) { + sipDialog.setLastResponse(transaction, sipResponse); + } ResponseEventExt responseEvent = new ResponseEventExt(sipProvider, - (ClientTransactionExt) transaction, sipDialog, - (Response) sipResponse); - - responseEvent.setRemoteIpAddress(sipResponse.getRemoteAddress().getHostAddress()); - responseEvent.setRemotePort(sipResponse.getRemotePort()); + (ClientTransactionExt) transaction, sipDialog, (Response) sipResponse); - if (sipStack.getMaxForkTime() != 0 - && SIPTransactionStack.isDialogCreated(sipResponse.getCSeqHeader().getMethod())) { - ClientTransactionExt originalTx = this.sipStack - .getForkedTransaction(sipResponse.getForkId()); - if(sipDialog != null && originalTx != null) { - sipDialog.checkRetransmissionForForking(sipResponse); - if(originalTx.getDefaultDialog() != null && !sipDialog.equals(originalTx.getDefaultDialog())) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( - "forked dialog " + sipDialog + " original tx " + originalTx + " original dialog " + originalTx.getDefaultDialog()); - } - responseEvent.setOriginalTransaction(originalTx); - responseEvent.setForkedResponse(true); - } - } - } - - if(sipDialog != null && sipResponse.getStatusCode() != 100 && sipResponse.getTo().getTag() != null) { - sipDialog.setLastResponse(transaction, sipResponse); + if (sipStack.getMaxForkTime() != 0 && sipResponse.getCSeq().getMethod().equals(Request.INVITE)) { + ClientTransactionExt originalTx = this.sipStack.getForkedTransaction(sipResponse + .getForkId()); + responseEvent.setOriginalTransaction(originalTx); } - responseEvent.setRetransmission(sipResponse.isRetransmission()); - responseEvent.setRemoteIpAddress(sipResponse.getRemoteAddress().getHostAddress()); + sipProvider.handleEvent(responseEvent, transaction); } diff --git a/src/gov/nist/javax/sip/DialogTimeoutEvent.java b/src/gov/nist/javax/sip/DialogTimeoutEvent.java index b14aa5497..f41416fff 100644 --- a/src/gov/nist/javax/sip/DialogTimeoutEvent.java +++ b/src/gov/nist/javax/sip/DialogTimeoutEvent.java @@ -33,7 +33,7 @@ */ public class DialogTimeoutEvent extends EventObject { private static final long serialVersionUID = -2514000059989311925L; - public enum Reason {AckNotReceived, AckNotSent,ReInviteTimeout,EarlyStateTimeout,CannotAcquireAckSemaphoreForOk}; + public enum Reason {AckNotReceived, AckNotSent,ReInviteTimeout,CannotAcquireAckSemaphoreForOk}; /** * Constructs a DialogTerminatedEvent to indicate a dialog * timeout. diff --git a/src/gov/nist/javax/sip/EventScanner.java b/src/gov/nist/javax/sip/EventScanner.java index 27135ec16..523eac939 100755 --- a/src/gov/nist/javax/sip/EventScanner.java +++ b/src/gov/nist/javax/sip/EventScanner.java @@ -31,10 +31,7 @@ import javax.sip.message.*; import javax.sip.*; -import gov.nist.core.CommonLogger; -import gov.nist.core.LogLevels; import gov.nist.core.LogWriter; -import gov.nist.core.StackLogger; import gov.nist.core.ThreadAuditor; /* bug fixes SIPQuest communications and Shu-Lin Chen. */ @@ -42,22 +39,20 @@ /** * Event Scanner to deliver events to the Listener. * - * @version 1.2 $Revision: 1.47 $ $Date: 2010-12-02 22:04:18 $ + * @version 1.2 $Revision: 1.41.2.1 $ $Date: 2010-11-23 19:23:11 $ * * @author M. Ranganathan
* * */ class EventScanner implements Runnable { - - private static StackLogger logger = CommonLogger.getLogger(EventScanner.class); private boolean isStopped; private int refCount; // SIPquest: Fix for deadlocks - private LinkedList pendingEvents; + private LinkedList pendingEvents = new LinkedList(); private int[] eventMutex = { 0 }; @@ -85,8 +80,8 @@ public EventScanner(SipStackImpl sipStackImpl) { } public void addEvent(EventWrapper eventWrapper) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug("addEvent " + eventWrapper); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("addEvent " + eventWrapper); synchronized (this.eventMutex) { pendingEvents.add(eventWrapper); @@ -133,8 +128,8 @@ public void forceStop() { public void deliverEvent(EventWrapper eventWrapper) { EventObject sipEvent = eventWrapper.sipEvent; - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug( + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug( "sipEvent = " + sipEvent + "source = " + sipEvent.getSource()); SipListener sipListener = null; @@ -152,8 +147,8 @@ public void deliverEvent(EventWrapper eventWrapper) { SIPRequest sipRequest = (SIPRequest) ((RequestEvent) sipEvent) .getRequest(); - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( "deliverEvent : " + sipRequest.getFirstLine() + " transaction " @@ -186,22 +181,23 @@ public void deliverEvent(EventWrapper eventWrapper) { // lingering to catch retransmitted INVITEs) if (sipRequest.getMethod().equals(Request.ACK) && tx.isInviteTransaction() && - ( tx.getLastResponseStatusCode() / 100 == 2 || + (tx.getLastResponse() != null && tx.getLastResponse().getStatusCode()/100 == 2 || sipStack.isNon2XXAckPassedToListener())) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack + .getStackLogger() .logDebug( "Detected broken client sending ACK with same branch! Passing..."); } else { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug( + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug( "transaction already exists! " + tx); return; } - } else if (sipStack.findPendingTransaction(sipRequest.getTransactionId()) != null) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug( + } else if (sipStack.findPendingTransaction(sipRequest) != null) { + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug( "transaction already exists!!"); return; @@ -218,19 +214,19 @@ public void deliverEvent(EventWrapper eventWrapper) { // Change made by SIPquest try { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger() .logDebug( "Calling listener " + sipRequest.getFirstLine()); - logger.logDebug( + sipStack.getStackLogger().logDebug( "Calling listener " + eventWrapper.transaction); } if (sipListener != null) sipListener.processRequest((RequestEvent) sipEvent); - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( "Done processing Message " + sipRequest.getFirstLine()); } @@ -246,11 +242,11 @@ public void deliverEvent(EventWrapper eventWrapper) { // We cannot let this thread die under any // circumstances. Protect ourselves by logging // errors to the console but continue. - logger.logException(ex); + sipStack.getStackLogger().logException(ex); } } finally { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( "Done processing Message " + ((SIPRequest) (((RequestEvent) sipEvent) .getRequest())).getFirstLine()); @@ -265,14 +261,14 @@ public void deliverEvent(EventWrapper eventWrapper) { if (eventWrapper.transaction != null) sipStack .removePendingTransaction((SIPServerTransaction) eventWrapper.transaction); - if (eventWrapper.transaction.getMethod() + if (eventWrapper.transaction.getOriginalRequest().getMethod() .equals(Request.ACK)) { // Set the tx state to terminated so it is removed from the // stack // if the user configured to get notification on ACK // termination eventWrapper.transaction - .setState(TransactionState._TERMINATED); + .setState(TransactionState.TERMINATED); } } @@ -283,9 +279,10 @@ public void deliverEvent(EventWrapper eventWrapper) { .getResponse(); SIPDialog sipDialog = ((SIPDialog) responseEvent.getDialog()); try { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( - "Calling listener " + sipListener + " for " + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + + sipStack.getStackLogger().logDebug( + "Calling listener for " + sipResponse.getFirstLine()); } if (sipListener != null) { @@ -305,8 +302,8 @@ public void deliverEvent(EventWrapper eventWrapper) { .getState().equals(DialogState.TERMINATED))) && (sipResponse.getStatusCode() == Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST || sipResponse .getStatusCode() == Response.REQUEST_TIMEOUT)) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( "Removing dialog on 408 or 481 response"); } sipDialog.doDeferredDelete(); @@ -333,8 +330,8 @@ public void deliverEvent(EventWrapper eventWrapper) { .equals(Request.INVITE) && sipDialog != null && sipResponse.getStatusCode() == 200) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( "Warning! unacknowledged dialog. " + sipDialog.getState()); } /* @@ -346,16 +343,16 @@ public void deliverEvent(EventWrapper eventWrapper) { // We cannot let this thread die under any // circumstances. Protect ourselves by logging // errors to the console but continue. - logger.logException(ex); + sipStack.getStackLogger().logException(ex); } // The original request is not needed except for INVITE // transactions -- null the pointers to the transactions so // that state may be released. SIPClientTransaction ct = (SIPClientTransaction) eventWrapper.transaction; if (ct != null - && TransactionState._COMPLETED == ct.getInternalState() -// && ct.getOriginalRequest() != null - && !ct.getMethod().equals( + && TransactionState.COMPLETED == ct.getState() + && ct.getOriginalRequest() != null + && !ct.getOriginalRequest().getMethod().equals( Request.INVITE)) { // reduce the state to minimum // This assumes that the application will not need @@ -381,7 +378,7 @@ public void deliverEvent(EventWrapper eventWrapper) { // We cannot let this thread die under any // circumstances. Protect ourselves by logging // errors to the console but continue. - logger.logException(ex); + sipStack.getStackLogger().logException(ex); } } else if (sipEvent instanceof DialogTimeoutEvent) { @@ -389,16 +386,12 @@ public void deliverEvent(EventWrapper eventWrapper) { // Check for null as listener could be removed. if (sipListener != null && sipListener instanceof SipListenerExt) { ((SipListenerExt)sipListener).processDialogTimeout((DialogTimeoutEvent) sipEvent); - } else { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("DialogTimeoutEvent not delivered" ); - } } } catch (Exception ex) { // We cannot let this thread die under any // circumstances. Protect ourselves by logging // errors to the console but continue. - logger.logException(ex); + sipStack.getStackLogger().logException(ex); } } else if (sipEvent instanceof IOExceptionEvent) { @@ -406,18 +399,18 @@ public void deliverEvent(EventWrapper eventWrapper) { if (sipListener != null) sipListener.processIOException((IOExceptionEvent) sipEvent); } catch (Exception ex) { - logger.logException(ex); + sipStack.getStackLogger().logException(ex); } } else if (sipEvent instanceof TransactionTerminatedEvent) { try { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( "About to deliver transactionTerminatedEvent"); - logger.logDebug( + sipStack.getStackLogger().logDebug( "tx = " + ((TransactionTerminatedEvent) sipEvent) .getClientTransaction()); - logger.logDebug( + sipStack.getStackLogger().logDebug( "tx = " + ((TransactionTerminatedEvent) sipEvent) .getServerTransaction()); @@ -428,12 +421,13 @@ public void deliverEvent(EventWrapper eventWrapper) { .processTransactionTerminated((TransactionTerminatedEvent) sipEvent); } catch (AbstractMethodError ame) { // JvB: for backwards compatibility, accept this - if (logger.isLoggingEnabled()) - logger + if (sipStack.isLoggingEnabled()) + sipStack + .getStackLogger() .logWarning( "Unable to call sipListener.processTransactionTerminated"); } catch (Exception ex) { - logger.logException(ex); + sipStack.getStackLogger().logException(ex); } } else if (sipEvent instanceof DialogTerminatedEvent) { try { @@ -442,15 +436,15 @@ public void deliverEvent(EventWrapper eventWrapper) { .processDialogTerminated((DialogTerminatedEvent) sipEvent); } catch (AbstractMethodError ame) { // JvB: for backwards compatibility, accept this - if (logger.isLoggingEnabled()) - logger.logWarning( + if (sipStack.isLoggingEnabled()) + sipStack.getStackLogger().logWarning( "Unable to call sipListener.processDialogTerminated"); } catch (Exception ex) { - logger.logException(ex); + sipStack.getStackLogger().logException(ex); } } else { - logger.logFatalError("bad event" + sipEvent); + sipStack.getStackLogger().logFatalError("bad event" + sipEvent); } } @@ -477,8 +471,8 @@ public void run() { // haven't // been stopped. If we have, then let the thread die. if (this.isStopped) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug( + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug( "Stopped event scanner!!"); return; } @@ -493,8 +487,8 @@ public void run() { eventMutex.wait(threadHandle.getPingIntervalInMillisecs()); } catch (InterruptedException ex) { // Let the thread die a normal death - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug("Interrupted!"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Interrupted!"); return; } } @@ -510,25 +504,25 @@ public void run() { ListIterator iterator = eventsToDeliver.listIterator(); while (iterator.hasNext()) { eventWrapper = (EventWrapper) iterator.next(); - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( "Processing " + eventWrapper + "nevents " + eventsToDeliver.size()); } try { deliverEvent(eventWrapper); } catch (Exception e) { - if (logger.isLoggingEnabled()) { - logger.logError( + if (sipStack.isLoggingEnabled()) { + sipStack.getStackLogger().logError( "Unexpected exception caught while delivering event -- carrying on bravely", e); } } } } // end While } finally { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { + if (sipStack.isLoggingEnabled()) { if (!this.isStopped) { - logger.logFatalError("Event scanner exited abnormally"); + sipStack.getStackLogger().logFatalError("Event scanner exited abnormally"); } } } diff --git a/src/gov/nist/javax/sip/ListeningPointImpl.java b/src/gov/nist/javax/sip/ListeningPointImpl.java index 79b575a0d..5428d467e 100755 --- a/src/gov/nist/javax/sip/ListeningPointImpl.java +++ b/src/gov/nist/javax/sip/ListeningPointImpl.java @@ -34,11 +34,9 @@ import javax.sip.header.ContactHeader; import javax.sip.header.ViaHeader; -import gov.nist.core.CommonLogger; import gov.nist.core.Host; import gov.nist.core.HostPort; import gov.nist.core.InternalErrorHandler; -import gov.nist.core.StackLogger; import gov.nist.javax.sip.address.AddressImpl; import gov.nist.javax.sip.address.SipUri; import gov.nist.javax.sip.header.Contact; @@ -49,7 +47,7 @@ /** * Implementation of the ListeningPoint interface * - * @version 1.2 $Revision: 1.18 $ $Date: 2010-12-02 22:04:18 $ + * @version 1.2 $Revision: 1.15 $ $Date: 2009-11-19 05:26:58 $ * * @author M. Ranganathan
* @@ -57,7 +55,7 @@ * */ public class ListeningPointImpl implements javax.sip.ListeningPoint, gov.nist.javax.sip.ListeningPointExt { - private static StackLogger logger = CommonLogger.getLogger(ListeningPointImpl.class); + protected String transport; @@ -91,7 +89,7 @@ public class ListeningPointImpl implements javax.sip.ListeningPoint, gov.nist.ja * @return a string that is used as a key */ public static String makeKey(String host, int port, String transport) { - return new StringBuilder(host) + return new StringBuffer(host) .append(":") .append(port) .append("/") @@ -112,14 +110,14 @@ protected String getKey() { * Set the sip provider for this structure. * @param sipProvider provider to set */ - public void setSipProvider(SipProviderImpl sipProviderImpl) { + protected void setSipProvider(SipProviderImpl sipProviderImpl) { this.sipProvider = sipProviderImpl; } /** * Remove the sip provider from this listening point. */ - public void removeSipProvider() { + protected void removeSipProvider() { this.sipProvider = null; } @@ -239,7 +237,7 @@ public ContactHeader createContactHeader() { return contact; } catch (Exception ex) { - InternalErrorHandler.handleException("Unexpected exception",logger); + InternalErrorHandler.handleException("Unexpected exception",sipStack.getStackLogger()); return null; } } diff --git a/src/gov/nist/javax/sip/MergedSystemProperties.java b/src/gov/nist/javax/sip/MergedSystemProperties.java deleted file mode 100644 index a98d6993b..000000000 --- a/src/gov/nist/javax/sip/MergedSystemProperties.java +++ /dev/null @@ -1,135 +0,0 @@ -package gov.nist.javax.sip; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PrintStream; -import java.io.PrintWriter; -import java.io.Reader; -import java.io.Writer; -import java.util.Enumeration; -import java.util.InvalidPropertiesFormatException; -import java.util.Properties; -import java.util.Set; - -public class MergedSystemProperties extends Properties { - - private Properties parent; - - public MergedSystemProperties(Properties props) { - parent = props; - } - - public void list(PrintStream out) { - parent.list(out); - } - - - public void list(PrintWriter out) { - parent.list(out); - } - - - public synchronized void load(InputStream inStream) throws IOException { - - parent.load(inStream); - } - - - public synchronized void load(Reader reader) throws IOException { - - throw new RuntimeException("Not implemented for Java 5 compatibility"); - } - - - public synchronized void loadFromXML(InputStream in) throws IOException, - InvalidPropertiesFormatException { - - parent.loadFromXML(in); - } - - - public Enumeration propertyNames() { - - return parent.propertyNames(); - } - - - public synchronized void save(OutputStream out, String comments) { - - parent.save(out, comments); - } - - - public synchronized Object setProperty(String key, String value) { - - return parent.setProperty(key, value); - } - - - public void store(OutputStream out, String comments) throws IOException { - - parent.store(out, comments); - } - - - public void store(Writer writer, String comments) throws IOException { - - throw new RuntimeException("Not implemented for Java 5 compatibility"); - } - - - public synchronized void storeToXML(OutputStream os, String comment, - String encoding) throws IOException { - - parent.storeToXML(os, comment, encoding); - } - - - public synchronized void storeToXML(OutputStream os, String comment) - throws IOException { - - parent.storeToXML(os, comment); - } - - - public Set stringPropertyNames() { - - throw new RuntimeException("Not implemented for Java 5 compatibility"); - } - - public String getProperty(String key, String defaultValue) { - if(System.getProperty(key) != null) - return System.getProperty(key); - return parent.getProperty(key, defaultValue); - } - - public String getProperty(String key) { - if(System.getProperty(key) != null) - return System.getProperty(key); - return parent.getProperty(key); - } - - /** - * - */ - private static final long serialVersionUID = -7922854860297151103L; - - - /** - * Determines whether key is already present here. . - * - * @param key the key that we are looking for. - * - * @return true key is a known property and false - * otherwise. - */ - @Override - public boolean containsKey(Object key){ - return parent.containsKey(key); - } - - public String toString() { - return super.toString() + parent.toString(); - } -} diff --git a/src/gov/nist/javax/sip/NistSipMessageFactoryImpl.java b/src/gov/nist/javax/sip/NistSipMessageFactoryImpl.java index 386cd310b..02406800c 100755 --- a/src/gov/nist/javax/sip/NistSipMessageFactoryImpl.java +++ b/src/gov/nist/javax/sip/NistSipMessageFactoryImpl.java @@ -29,9 +29,7 @@ package gov.nist.javax.sip; -import gov.nist.core.CommonLogger; -import gov.nist.core.LogLevels; -import gov.nist.core.StackLogger; +import gov.nist.core.LogWriter; import gov.nist.javax.sip.stack.*; import gov.nist.javax.sip.message.*; import javax.sip.*; @@ -45,14 +43,14 @@ * messageChannel, the NIST-SIP stack calls the SIPStackMessageFactory * implementation that has been registered with it to process the request.) * - * @version 1.2 $Revision: 1.18 $ $Date: 2010-12-02 22:04:19 $ + * @version 1.2 $Revision: 1.15.2.1 $ $Date: 2010-11-23 19:23:11 $ * * @author M. Ranganathan
* * */ class NistSipMessageFactoryImpl implements StackMessageFactory { - private static StackLogger logger = CommonLogger.getLogger(NistSipMessageFactoryImpl.class); + private SIPTransactionStack sipStack; /** @@ -83,8 +81,8 @@ public ServerRequestInterface newSIPServerRequest(SIPRequest sipRequest, .getListeningPoint(); if (retval.listeningPoint == null) return null; - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug( + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug( "Returning request interface for " + sipRequest.getFirstLine() + " " + retval + " messageChannel = " + messageChannel); @@ -107,8 +105,8 @@ public ServerResponseInterface newSIPServerResponse( // Tr is null if a transaction is not mapped. SIPTransaction tr = (SIPTransaction) ((SIPTransactionStack) theStack) .findTransaction(sipResponse, false); - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug( + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug( "Found Transaction " + tr + " for " + sipResponse); if (tr != null) { @@ -116,16 +114,16 @@ public ServerResponseInterface newSIPServerResponse( // If the state has not yet been assigned then this is a // spurious response. This was moved up from the transaction // layer for efficiency. - if (tr.getInternalState() < 0) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug( + if (tr.getState() == null) { + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug( "Dropping response - null transaction state"); return null; // Ignore 1xx - } else if (TransactionState._COMPLETED == tr.getInternalState() + } else if (TransactionState.COMPLETED == tr.getState() && sipResponse.getStatusCode() / 100 == 1) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug( + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug( "Dropping response - late arriving " + sipResponse.getStatusCode()); return null; diff --git a/src/gov/nist/javax/sip/RequestEventExt.java b/src/gov/nist/javax/sip/RequestEventExt.java deleted file mode 100644 index c3fa98633..000000000 --- a/src/gov/nist/javax/sip/RequestEventExt.java +++ /dev/null @@ -1,40 +0,0 @@ -package gov.nist.javax.sip; - -import javax.sip.Dialog; -import javax.sip.RequestEvent; -import javax.sip.ServerTransaction; -import javax.sip.message.Request; - - -/** - * Extension of the RequestEvent. - * - * - */ - - -public class RequestEventExt extends RequestEvent { - private String remoteIpAddress; - - private int remotePort; - - public RequestEventExt(Object source, ServerTransaction serverTransaction, Dialog dialog, Request request) { - super(source,serverTransaction,dialog,request); - } - - public void setRemoteIpAddress(String remoteIpAddress) { - this.remoteIpAddress = remoteIpAddress; - } - - public String getRemoteIpAddress() { - return remoteIpAddress; - } - - public void setRemotePort(int remotePort) { - this.remotePort = remotePort; - } - - public int getRemotePort() { - return remotePort; - } -} diff --git a/src/gov/nist/javax/sip/ResponseEventExt.java b/src/gov/nist/javax/sip/ResponseEventExt.java index 54d8f3151..1b175c65c 100644 --- a/src/gov/nist/javax/sip/ResponseEventExt.java +++ b/src/gov/nist/javax/sip/ResponseEventExt.java @@ -1,113 +1,50 @@ package gov.nist.javax.sip; +import javax.sip.ClientTransaction; import javax.sip.Dialog; import javax.sip.ResponseEvent; import javax.sip.message.Response; /** - * Extension for ResponseEvent. + * Extension for ResponseEvent. * * @since v2.0 */ public class ResponseEventExt extends ResponseEvent { - private ClientTransactionExt m_originalTransaction; - private boolean isForked; - private boolean isRetransmission; - private String remoteIpAddress; - private int remotePort; - - public ResponseEventExt(Object source, ClientTransactionExt clientTransaction, Dialog dialog, Response response) { - super(source, clientTransaction, dialog, response); + private ClientTransactionExt m_originalTransaction; + public ResponseEventExt(Object source, ClientTransactionExt clientTransaction, + Dialog dialog, Response response) { + super(source,clientTransaction,dialog,response); m_originalTransaction = clientTransaction; } - + /** * Return true if this is a forked response. * * @return true if the response event is for a forked response. */ public boolean isForkedResponse() { - return isForked; + return super.getClientTransaction() == null && m_originalTransaction != null; } - - /** - * Set true if this is a forked response. - * - * @return true if the response event is for a forked response. - */ - public void setForkedResponse(boolean forked) { - this.isForked = forked; - } - + /** * Set the original transaction for a forked response. * - * @param originalTransaction - the original transaction for which this response event is a - * fork. + * @param originalTransaction - the original transaction for which this response event is a fork. */ - public void setOriginalTransaction(ClientTransactionExt originalTransaction) { + public void setOriginalTransaction(ClientTransactionExt originalTransaction ) { m_originalTransaction = originalTransaction; } - + /** - * Get the original transaction for which this is a forked response. Note that this - * transaction can be in a TERMINATED state. + * Get the original transaction for which this is a forked response. + * Note that this transaction can be in a TERMINATED state. * * @return the original clientTx for which this is a forked response. */ public ClientTransactionExt getOriginalTransaction() { return this.m_originalTransaction; } - - /** - * Return true if this is a forked response. - * - * @return true if the response event is for a forked response. - */ - public boolean isRetransmission() { - return isRetransmission; - } - - /** - * @param isRetransmission the isRetransmission to set - */ - public void setRetransmission(boolean isRetransmission) { - this.isRetransmission = isRetransmission; - } - - /** - * Set the remote port from which response was received. - * - * @param remotePort -- the remote port from where the response was received. - */ - public void setRemotePort(int remotePort) { - this.remotePort = remotePort; - } - - /** - * Get the remote port from which response was received. - * - */ - public int getRemotePort() { - return remotePort; - } - - /** - * Get the remote IP addr. from which request was received. - * - */ - public String getRemoteIpAddress() { - return remoteIpAddress; - } - - /** - * Get the remote IP addr. from which request was received. - * - * @return remoteIp address from where request was received. - */ - - public void setRemoteIpAddress(String remoteIpAddress) { - this.remoteIpAddress = remoteIpAddress; - } - + + } diff --git a/src/gov/nist/javax/sip/SipProviderImpl.java b/src/gov/nist/javax/sip/SipProviderImpl.java index 24db79f85..c1b32f1b1 100755 --- a/src/gov/nist/javax/sip/SipProviderImpl.java +++ b/src/gov/nist/javax/sip/SipProviderImpl.java @@ -28,10 +28,8 @@ ******************************************************************************/ package gov.nist.javax.sip; -import gov.nist.core.CommonLogger; import gov.nist.core.InternalErrorHandler; -import gov.nist.core.LogLevels; -import gov.nist.core.StackLogger; +import gov.nist.core.LogWriter; import gov.nist.javax.sip.DialogTimeoutEvent.Reason; import gov.nist.javax.sip.address.RouterExt; import gov.nist.javax.sip.header.CallID; @@ -49,7 +47,6 @@ import gov.nist.javax.sip.stack.SIPTransaction; import gov.nist.javax.sip.stack.SIPTransactionErrorEvent; import gov.nist.javax.sip.stack.SIPTransactionEventListener; -import gov.nist.javax.sip.stack.SIPTransactionStack; import java.io.IOException; import java.text.ParseException; @@ -88,7 +85,7 @@ /** * Implementation of the JAIN-SIP provider interface. * - * @version 1.2 $Revision: 1.89 $ $Date: 2010-12-02 22:04:19 $ + * @version 1.2 $Revision: 1.83.2.1 $ $Date: 2010-11-23 19:23:10 $ * * @author M. Ranganathan
* @@ -97,7 +94,7 @@ public class SipProviderImpl implements javax.sip.SipProvider, gov.nist.javax.sip.SipProviderExt, SIPTransactionEventListener, SIPDialogEventListener { - private static StackLogger logger = CommonLogger.getLogger(SipProviderImpl.class); + private SipListener sipListener; protected SipStackImpl sipStack; @@ -137,8 +134,8 @@ private SipProviderImpl() { */ protected void stop() { // Put an empty event in the queue and post ourselves a message. - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug("Exiting provider"); + if (sipStack.isLoggingEnabled()) + sipStack.getStackLogger().logDebug("Exiting provider"); for (Iterator it = listeningPoints.values().iterator(); it.hasNext();) { ListeningPointImpl listeningPoint = (ListeningPointImpl) it.next(); listeningPoint.removeSipProvider(); @@ -170,25 +167,25 @@ public ListeningPoint getListeningPoint(String transport) { */ public void handleEvent(EventObject sipEvent, SIPTransaction transaction) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( "handleEvent " + sipEvent + "currentTransaction = " + transaction + "this.sipListener = " + this.getSipListener() + "sipEvent.source = " + sipEvent.getSource()); if (sipEvent instanceof RequestEvent) { Dialog dialog = ((RequestEvent) sipEvent).getDialog(); - if ( logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) logger.logDebug("Dialog = " + dialog); + if ( sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) sipStack.getStackLogger().logDebug("Dialog = " + dialog); } else if (sipEvent instanceof ResponseEvent) { Dialog dialog = ((ResponseEvent) sipEvent).getDialog(); - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG) ) logger.logDebug("Dialog = " + dialog); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG) ) sipStack.getStackLogger().logDebug("Dialog = " + dialog); } - logger.logStackTrace(); + sipStack.getStackLogger().logStackTrace(); } EventWrapper eventWrapper = new EventWrapper(sipEvent, transaction); - if (!sipStack.isReEntrantListener()) { + if (!sipStack.reEntrantListener) { // Run the event in the context of a single thread. this.eventScanner.addEvent(eventWrapper); } else { @@ -233,8 +230,8 @@ public void addSipListener(SipListener sipListener) "Stack already has a listener. Only one listener per stack allowed"); } - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug("add SipListener " + sipListener); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("add SipListener " + sipListener); this.sipListener = sipListener; } @@ -337,8 +334,8 @@ public ClientTransaction getNewClientTransaction(Request request) } } - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug( + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug( "could not find existing transaction for " + ((SIPRequest) request).getFirstLine() + " creating a new one "); @@ -407,7 +404,7 @@ public ClientTransaction getNewClientTransaction(Request request) ct.setOriginalRequest(sipRequest); ct.setBranch(branchId); // if the stack supports dialogs then - if (SIPTransactionStack.isDialogCreated(request.getMethod())) { + if (sipStack.isDialogCreated(request.getMethod())) { // create a new dialog to contain this transaction // provided this is necessary. // This could be a re-invite @@ -467,8 +464,8 @@ public ServerTransaction getNewServerTransaction(Request request) } if ( request.getMethod().equals(Request.ACK)) { - if ( logger.isLoggingEnabled()) - logger.logError("Creating server transaction for ACK -- makes no sense!"); + if ( sipStack.isLoggingEnabled()) + sipStack.getStackLogger().logError("Creating server transaction for ACK -- makes no sense!"); throw new TransactionUnavailableException("Cannot create Server transaction for ACK "); } /* @@ -491,7 +488,7 @@ public ServerTransaction getNewServerTransaction(Request request) "Transaction not available -- could not acquire stack lock"); } try { - if (SIPTransactionStack.isDialogCreated(sipRequest.getMethod())) { + if (sipStack.isDialogCreated(sipRequest.getMethod())) { if (sipStack.findTransaction((SIPRequest) request, true) != null) throw new TransactionAlreadyExistsException( "server transaction already exists!"); @@ -677,8 +674,8 @@ public void sendRequest(Request request) throws SipException { Dialog dialog = sipStack.getDialog(((SIPRequest) request) .getDialogId(false)); if (dialog != null && dialog.getState() != null) { - if (logger.isLoggingEnabled()) - logger.logWarning( + if (sipStack.isLoggingEnabled()) + sipStack.getStackLogger().logWarning( "Dialog exists -- you may want to use Dialog.sendAck() " + dialog.getState()); } @@ -719,8 +716,8 @@ public void sendRequest(Request request) throws SipException { + hop.toString()); } } catch (IOException ex) { - if (logger.isLoggingEnabled()) { - logger.logException(ex); + if (sipStack.isLoggingEnabled()) { + sipStack.getStackLogger().logException(ex); } throw new SipException( @@ -729,8 +726,8 @@ public void sendRequest(Request request) throws SipException { } catch (ParseException ex1) { InternalErrorHandler.handleException(ex1); } finally { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug( + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug( "done sending " + request.getMethod() + " to hop " + hop); } @@ -749,7 +746,7 @@ public void sendResponse(Response response) throws SipException { if (via == null) throw new SipException("No via header in response!"); SIPServerTransaction st = (SIPServerTransaction) sipStack.findTransaction((SIPMessage)response, true); - if ( st != null && st.getInternalState() != TransactionState._TERMINATED && this.isAutomaticDialogSupportEnabled()) { + if ( st != null && st.getState() != TransactionState.TERMINATED && this.isAutomaticDialogSupportEnabled()) { throw new SipException("Transaction exists -- cannot send response statelessly"); } String transport = via.getTransport(); @@ -833,7 +830,7 @@ public Dialog getNewDialog(Transaction transaction) throws SipException { if (isAutomaticDialogSupportEnabled()) throw new SipException(" Error - AUTOMATIC_DIALOG_SUPPORT is on"); - if (!SIPTransactionStack.isDialogCreated(transaction.getRequest().getMethod())) + if (!sipStack.isDialogCreated(transaction.getRequest().getMethod())) throw new SipException("Dialog cannot be created for this method " + transaction.getRequest().getMethod()); @@ -908,8 +905,8 @@ public void transactionErrorEvent( if (transactionErrorEvent.getErrorID() == SIPTransactionErrorEvent.TRANSPORT_ERROR) { // There must be a way to inform the TU here!! - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( "TransportError occured on " + transaction); } // Treat this like a timeout event. (Suggestion from Christophe). @@ -962,7 +959,7 @@ public void transactionErrorEvent( if (tx.getDialog() != null) InternalErrorHandler.handleException("Unexpected event !", - this.logger); + this.sipStack.getStackLogger()); Timeout timeout = Timeout.RETRANSMIT; TimeoutEvent ev = null; @@ -982,18 +979,16 @@ public void transactionErrorEvent( * (non-Javadoc) * @see gov.nist.javax.sip.stack.SIPDialogEventListener#dialogErrorEvent(gov.nist.javax.sip.stack.SIPDialogErrorEvent) */ - public void dialogErrorEvent(SIPDialogErrorEvent dialogErrorEvent) { + public synchronized void dialogErrorEvent(SIPDialogErrorEvent dialogErrorEvent) { SIPDialog sipDialog = (SIPDialog) dialogErrorEvent.getSource(); Reason reason = Reason.AckNotReceived; if (dialogErrorEvent.getErrorID() == SIPDialogErrorEvent.DIALOG_ACK_NOT_SENT_TIMEOUT) { reason= Reason.AckNotSent; } else if (dialogErrorEvent.getErrorID() == SIPDialogErrorEvent.DIALOG_REINVITE_TIMEOUT) { reason = Reason.ReInviteTimeout; - } else if (dialogErrorEvent.getErrorID() == SIPDialogErrorEvent.EARLY_STATE_TIMEOUT) { - reason = Reason.EarlyStateTimeout; } - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug( + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( "Dialog TimeoutError occured on " + sipDialog); } DialogTimeoutEvent ev = new DialogTimeoutEvent(this, sipDialog, reason); diff --git a/src/gov/nist/javax/sip/SipStackExt.java b/src/gov/nist/javax/sip/SipStackExt.java index 6fa975e4c..46842f363 100644 --- a/src/gov/nist/javax/sip/SipStackExt.java +++ b/src/gov/nist/javax/sip/SipStackExt.java @@ -19,18 +19,18 @@ /** * SIP Stack extensions to be added to the next spec revision. Only these may be safely used in * the interim between now and the next release. SipStackImpl implements this interface. - * + * * The following new stack initialization flags are defined (not the gov.nist prefix will be * dropped when the spec is updated): - * + * *
    *
  • gov.nist.javax.sip.AUTOMATIC_DIALOG_ERROR_HANDLING *
  • gov.nist.javax.sip.IS_BACK_TO_BACK_USER_AGENT *
  • gov.nist.javax.sip.DELIVER_TERMINATED_EVENT_FOR_NULL_DIALOG - *
  • gov.nist.javax.sip.MAX_FORK_TIME_SECONDS + *
  • gov.nist.javax.sip.MAX_FORK_TIME_SECONDS *
* @author M. Ranganathan - * + * */ public interface SipStackExt extends SipStack { @@ -65,7 +65,7 @@ public interface SipStackExt extends SipStack { */ public AuthenticationHelper getAuthenticationHelper(AccountManager accountManager, HeaderFactory headerFactory); - + /** * Get the authentication helper. * @@ -126,7 +126,7 @@ public AuthenticationHelper getSecureAuthenticationHelper(SecureAccountManager a * destination address and port and then returns its local address. * * @param dst the destination address that the socket would need to connect - * to. + * to. * @param dstPort the port number that the connection would be established * with. * @param localAddress the address that we would like to bind on @@ -134,37 +134,13 @@ public AuthenticationHelper getSecureAuthenticationHelper(SecureAccountManager a * @param localPort the port that we'd like our socket to bind to (0 for a * random port). * - * @return the local SocketAddress that this handler would use when - * connecting to the specified destination address and port. - * - * @throws IOException if we fail binding the socket + * @return the SocketAddress that this handler would use when connecting to + * the specified destination address and port. * - * @since 2.0 + * @throws IOException */ - public SocketAddress getLocalAddressForTcpDst(InetAddress dst, int dstPort, + public SocketAddress obtainLocalAddress(InetAddress dst, int dstPort, InetAddress localAddress, int localPort) throws IOException; - /** - * Creates and binds, if necessary, a TLS socket connected to the specified - * destination address and port and then returns its local address. - * - * @param dst the destination address that the socket would need to connect - * to. - * @param dstPort the port number that the connection would be established - * with. - * @param localAddress the address that we would like to bind on - * (null for the "any" address). - * - * @return the local SocketAddress that this handler would use when - * connecting to the specified destination address and port. - * - * @throws IOException if we fail binding the socket - * - * @since 2.0 - */ - public SocketAddress getLocalAddressForTlsDst(InetAddress dst, int dstPort, - InetAddress localAddress) - throws IOException; - } diff --git a/src/gov/nist/javax/sip/SipStackImpl.java b/src/gov/nist/javax/sip/SipStackImpl.java index 94e4d6e7a..f708cca7d 100755 --- a/src/gov/nist/javax/sip/SipStackImpl.java +++ b/src/gov/nist/javax/sip/SipStackImpl.java @@ -25,8 +25,7 @@ */ package gov.nist.javax.sip; -import gov.nist.core.CommonLogger; -import gov.nist.core.LogLevels; +import gov.nist.core.LogWriter; import gov.nist.core.ServerLogger; import gov.nist.core.StackLogger; import gov.nist.core.net.AddressResolver; @@ -40,17 +39,13 @@ import gov.nist.javax.sip.parser.PipelinedMsgParser; import gov.nist.javax.sip.parser.StringMsgParser; import gov.nist.javax.sip.parser.StringMsgParserFactory; -import gov.nist.javax.sip.stack.ClientAuthType; import gov.nist.javax.sip.stack.DefaultMessageLogFactory; import gov.nist.javax.sip.stack.DefaultRouter; import gov.nist.javax.sip.stack.MessageProcessor; import gov.nist.javax.sip.stack.MessageProcessorFactory; import gov.nist.javax.sip.stack.OIOMessageProcessorFactory; import gov.nist.javax.sip.stack.SIPEventInterceptor; -import gov.nist.javax.sip.stack.SIPMessageValve; import gov.nist.javax.sip.stack.SIPTransactionStack; -import gov.nist.javax.sip.stack.timers.DefaultSipTimer; -import gov.nist.javax.sip.stack.timers.SipTimer; import java.io.BufferedReader; import java.io.IOException; @@ -59,10 +54,8 @@ import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.net.InetAddress; -import java.util.Collections; import java.util.Hashtable; import java.util.LinkedList; -import java.util.List; import java.util.Properties; import java.util.StringTokenizer; import java.util.concurrent.Semaphore; @@ -87,12 +80,7 @@ * * The JAIN-SIP stack is initialized by a set of properties (see the JAIN SIP * documentation for an explanation of these properties - * {@link javax.sip.SipStack} ). - * - * For NIST SIP stack all properties can also be passed as JVM system properties - * from the command line as -D arguments. - * - * In addition to these, the following are + * {@link javax.sip.SipStack} ). In addition to these, the following are * meaningful properties for the NIST SIP stack (specify these in the property * array when you create the JAIN-SIP statck): *
    @@ -451,10 +439,6 @@ * client transction in the ResponseEventExt and deliver that to the application. * The event handler can get the original transaction from this event. * - *
  • gov.nist.javax.sip.EARLY_DIALOG_TIMEOUT_SECONDS=integer Maximum time for which a dialog - * can remain in early state. This is defaulted to 3 minutes ( 180 seconds). - *
  • - * *
  • gov.nist.javax.sip.MESSAGE_PARSER_FACTORY = name of the class implementing gov.nist.javax.sip.parser.MessageParserFactory * This factory allows pluggable implementations of the MessageParser that will take care of parsing the incoming messages. * By example one could plug a lazy parser through this factory.
  • @@ -463,19 +447,11 @@ * This factory allows pluggable implementations of the MessageProcessor that will take care of incoming messages. * By example one could plug a NIO Processor through this factory. * - *
  • gov.nist.javax.sip.TIMER_CLASS_NAME = name of the class implementing gov.nist.javax.sip.stack.timers.SipTimer interface - * This allows pluggable implementations of the Timer that will take care of scheduling the various SIP Timers. - * By example one could plug a regular timer, a scheduled thread pool executor.
  • * *
  • gov.nist.javax.sip.DELIVER_RETRANSMITTED_ACK_TO_LISTENER=boolean A testing property * that allows application to see the ACK for retransmitted 200 OK requests. Note that this is for test * purposes only
  • * - * *
  • gov.nist.javax.sip.AGGRESSIVE_CLEANUP=boolean A property that will cleanup Dialog, and Transaction structures - * agrressively to improve memroy usage and performance (up to 50% gain). However one needs to be careful in its code - * on how and when it accesses transaction and dialog data since it cleans up aggressively when transactions changes state - * to COMPLETED or TERMINATED and for Dialog once the ACK is received/sent
  • - * *
  • gov.nist.javax.sip.MIN_KEEPALIVE_TIME_SECONDS = integer Minimum time between keep alive * pings (CRLF CRLF) from clients. If pings arrive with less than this frequency they will be replied * with CRLF CRLF if greater they will be rejected. The default is -1 (i.e. do not respond to CRLF CRLF). @@ -486,14 +462,6 @@ * if the registered SipListener is of type SipListenerExt *
  • * - *
  • gov.nist.javax.sip.SIP_MESSAGE_VALVE= String Default to null. The class name of your custom valve component. - * An instance of this class will be created and the SIPMessageValve.processRequest/Response() methods will be called for every message - * before any long-lived SIP Stack resources are allocated (no transactions, no dialogs). From within the processRequest callback - * implementation you can drop messages, send a response statelessly or otherwise transform/pre-process the message before it reaches - * the next steps of the pipeline. Similarly from processResponse() you can manipulate a response or drop it silently, but dropping - * responses is not recommended, because the transaction already exists when the request for the response was sent. - *
  • - * *
  • gov.nist.javax.sip.SIP_EVENT_INTERCEPTOR Default to null. The class name of your custom interceptor object. * An instance of this object will be created at initialization of the stack. You must implement the interface * gov.nist.javax.sip.stack.SIPEventInterceptor and handle the lifecycle callbacks. This interface is the solution for @@ -517,12 +485,6 @@ * of outbund TLS connections. *
  • * - *
  • gov.nist.javax.sip.TLS_CLIENT_AUTH_TYPE = String Valid values are Default (backward compatible with previous versions) - * , Enabled, Want or Disabled. Set to Enabled if you want the SSL stack to require a valid certificate chain from the client before - * accepting a connection. Set to Want if you want the SSL stack to request a client Certificate, but not fail if one isn't presented. - * A Disabled value will not require a certificate chain. - *
  • - * *
  • javax.net.ssl.keyStore = fileName
    * Default is NULL. If left undefined the keyStore and trustStore will * be left to the java runtime defaults. If defined, any TLS sockets created @@ -546,7 +508,7 @@ * should only use the extensions that are defined in this class. * * - * @version 1.2 $Revision: 1.143 $ $Date: 2010-12-02 22:04:18 $ + * @version 1.2 $Revision: 1.125.2.4 $ $Date: 2010-12-02 01:41:37 $ * * @author M. Ranganathan
    * @@ -556,21 +518,21 @@ */ public class SipStackImpl extends SIPTransactionStack implements javax.sip.SipStack, SipStackExt { - private static StackLogger logger = CommonLogger.getLogger(SipStackImpl.class); + private EventScanner eventScanner; - protected Hashtable listeningPoints; + private Hashtable listeningPoints; - protected List sipProviders; + private LinkedList sipProviders; /** * Max datagram size. */ - public static final Integer MAX_DATAGRAM_SIZE = 64 * 1024; + public static final Integer MAX_DATAGRAM_SIZE = 8 * 1024; // Flag to indicate that the listener is re-entrant and hence // Use this flag with caution. - private boolean reEntrantListener; + boolean reEntrantListener; SipListener sipListener; TlsSecurityPolicy tlsSecurityPolicy; @@ -598,8 +560,9 @@ public class SipStackImpl extends SIPTransactionStack implements "SSLv2Hello", "TLSv1" }; - + private Properties configurationProperties; + /** * Creates a new instance of SipStackImpl. */ @@ -611,7 +574,7 @@ protected SipStackImpl() { super.setMessageFactory(msgFactory); this.eventScanner = new EventScanner(this); this.listeningPoints = new Hashtable(); - this.sipProviders = Collections.synchronizedList(new LinkedList()); + this.sipProviders = new LinkedList(); } @@ -622,23 +585,9 @@ private void reInitialize() { super.reInit(); this.eventScanner = new EventScanner(this); this.listeningPoints = new Hashtable(); - this.sipProviders = Collections.synchronizedList(new LinkedList()); + this.sipProviders = new LinkedList(); this.sipListener = null; - if(!getTimer().isStarted()) { - String defaultTimerName = configurationProperties.getProperty("gov.nist.javax.sip.TIMER_CLASS_NAME",DefaultSipTimer.class.getName()); - try { - setTimer((SipTimer)Class.forName(defaultTimerName).newInstance()); - getTimer().start(this, configurationProperties); - if (getThreadAuditor().isEnabled()) { - // Start monitoring the timer thread - getTimer().schedule(new PingTimer(null), 0); - } - } catch (Exception e) { - logger - .logError( - "Bad configuration value for gov.nist.javax.sip.TIMER_CLASS_NAME", e); - } - } + } /** @@ -662,7 +611,6 @@ boolean isAutomaticDialogSupportEnabled() { public SipStackImpl(Properties configurationProperties) throws PeerUnavailableException { this(); - configurationProperties = new MergedSystemProperties(configurationProperties); this.configurationProperties = configurationProperties; String address = configurationProperties .getProperty("javax.sip.IP_ADDRESS"); @@ -697,8 +645,8 @@ public SipStackImpl(Properties configurationProperties) .getConstructor(constructorArgs); Object[] args = new Object[0]; StackLogger stackLogger = (StackLogger) cons.newInstance(args); - CommonLogger.legacyLogger = stackLogger; stackLogger.setStackProperties(configurationProperties); + super.setStackLogger(stackLogger); } catch (InvocationTargetException ex1) { throw new IllegalArgumentException( "Cound not instantiate stack logger " @@ -767,14 +715,14 @@ public SipStackImpl(Properties configurationProperties) Router router = (Router) cons.newInstance(args); super.setRouter(router); } catch (InvocationTargetException ex1) { - logger + getStackLogger() .logError( "could not instantiate router -- invocation target problem", (Exception) ex1.getCause()); throw new PeerUnavailableException( "Cound not instantiate router - check constructor", ex1); } catch (Exception ex) { - logger.logError("could not instantiate router", + getStackLogger().logError("could not instantiate router", (Exception) ex.getCause()); throw new PeerUnavailableException("Could not instantiate router", ex); @@ -830,7 +778,7 @@ public SipStackImpl(Properties configurationProperties) configurationProperties .getProperty("javax.net.ssl.keyStoreType")); } catch (Exception e1) { - logger.logError( + getStackLogger().logError( "could not instantiate SSL networking", e1); } } @@ -884,7 +832,7 @@ public SipStackImpl(Properties configurationProperties) String tlsPolicyPath = configurationProperties.getProperty("gov.nist.javax.sip.TLS_SECURITY_POLICY"); if (tlsPolicyPath == null) { tlsPolicyPath = "gov.nist.javax.sip.stack.DefaultTlsSecurityPolicy"; - logger.logWarning("using default tls security policy"); + getStackLogger().logWarning("using default tls security policy"); } try { Class< ? > tlsPolicyClass = Class.forName(tlsPolicyPath); @@ -901,13 +849,6 @@ public SipStackImpl(Properties configurationProperties) + "- check that it is present on the classpath and that there is a no-args constructor defined", ex); } - - // Allow application to choose the tls client auth policy on the socket - String clientAuthType = configurationProperties.getProperty("gov.nist.javax.sip.TLS_CLIENT_AUTH_TYPE"); - if (clientAuthType != null) { - super.clientAuth = ClientAuthType.valueOf(clientAuthType); - logger.logInfo("using " + clientAuthType + " tls auth policy"); - } // The following features are unique to the NIST implementation. @@ -928,7 +869,7 @@ public SipStackImpl(Properties configurationProperties) } catch (Exception e) { throw new PeerUnavailableException( "can't find or instantiate NetworkLayer implementation: " - + path, e); + + path); } } @@ -945,7 +886,7 @@ public SipStackImpl(Properties configurationProperties) } catch (Exception e) { throw new PeerUnavailableException( "can't find or instantiate AddressResolver implementation: " - + path, e); + + path); } } @@ -955,8 +896,8 @@ public SipStackImpl(Properties configurationProperties) try { this.maxConnections = new Integer(maxConnections).intValue(); } catch (NumberFormatException ex) { - if (logger.isLoggingEnabled()) - logger.logError( + if (isLoggingEnabled()) + getStackLogger().logError( "max connections - bad value " + ex.getMessage()); } } @@ -967,28 +908,29 @@ public SipStackImpl(Properties configurationProperties) try { this.threadPoolSize = new Integer(threadPoolSize).intValue(); } catch (NumberFormatException ex) { - if (logger.isLoggingEnabled()) - this.logger.logError( + if (isLoggingEnabled()) + this.getStackLogger().logError( "thread pool size - bad value " + ex.getMessage()); } } + - int congetstionControlTimeout = Integer - .parseInt(configurationProperties.getProperty( - "gov.nist.javax.sip.CONGESTION_CONTROL_TIMEOUT", - "8000")); - super.stackCongenstionControlTimeout = congetstionControlTimeout; - + int stackCongestionControlTimeout = Integer + .parseInt(configurationProperties.getProperty( + "gov.nist.javax.sip.CONGESTION_CONTROL_TIMEOUT", + "8000")); + super.stackCongestionControlTimeout = stackCongestionControlTimeout; + String tcpTreadPoolSize = configurationProperties .getProperty("gov.nist.javax.sip.TCP_POST_PARSING_THREAD_POOL_SIZE"); if (tcpTreadPoolSize != null) { try { int threads = new Integer(tcpTreadPoolSize).intValue(); super.setTcpPostParsingThreadPoolSize(threads); - PipelinedMsgParser.setPostParseExcutorSize(threads, congetstionControlTimeout); + PipelinedMsgParser.setPostParseExcutorSize(threads, stackCongestionControlTimeout); } catch (NumberFormatException ex) { - if (logger.isLoggingEnabled()) - this.logger.logError( + if (isLoggingEnabled()) + this.getStackLogger().logError( "TCP post-parse thread pool size - bad value " + tcpTreadPoolSize + " : " + ex.getMessage()); } } @@ -1002,8 +944,8 @@ public SipStackImpl(Properties configurationProperties) this.serverTransactionTableLowaterMark = this.serverTransactionTableHighwaterMark * 80 / 100; // Lowater is 80% of highwater } catch (NumberFormatException ex) { - if (logger.isLoggingEnabled()) - this.logger + if (isLoggingEnabled()) + this.getStackLogger() .logError( "transaction table size - bad value " + ex.getMessage()); @@ -1023,8 +965,8 @@ public SipStackImpl(Properties configurationProperties) this.clientTransactionTableLowaterMark = this.clientTransactionTableLowaterMark * 80 / 100; // Lowater is 80% of highwater } catch (NumberFormatException ex) { - if (logger.isLoggingEnabled()) - this.logger + if (isLoggingEnabled()) + this.getStackLogger() .logError( "transaction table size - bad value " + ex.getMessage()); @@ -1062,8 +1004,8 @@ public SipStackImpl(Properties configurationProperties) } } catch (NumberFormatException nfe) { // Ignore. - if (logger.isLoggingEnabled()) - logger.logError("Bad read timeout " + readTimeout); + if (isLoggingEnabled()) + getStackLogger().logError("Bad read timeout " + readTimeout); } } @@ -1073,7 +1015,7 @@ public SipStackImpl(Properties configurationProperties) .getProperty("gov.nist.javax.sip.STUN_SERVER"); if (stunAddr != null) - this.logger.logWarning( + this.getStackLogger().logWarning( "Ignoring obsolete property " + "gov.nist.javax.sip.STUN_SERVER"); @@ -1090,8 +1032,8 @@ public SipStackImpl(Properties configurationProperties) super.maxMessageSize = 0; } } catch (NumberFormatException ex) { - if (logger.isLoggingEnabled()) - logger.logError( + if (isLoggingEnabled()) + getStackLogger().logError( "maxMessageSize - bad value " + ex.getMessage()); } @@ -1109,8 +1051,8 @@ public SipStackImpl(Properties configurationProperties) getThreadAuditor().setPingIntervalInMillisecs( Long.valueOf(interval).longValue() / 2); } catch (NumberFormatException ex) { - if (logger.isLoggingEnabled()) - logger.logError( + if (isLoggingEnabled()) + getStackLogger().logError( "THREAD_AUDIT_INTERVAL_IN_MILLISECS - bad value [" + interval + "] " + ex.getMessage()); } @@ -1139,8 +1081,8 @@ public SipStackImpl(Properties configurationProperties) this.logRecordFactory = (LogRecordFactory) c .newInstance(new Object[0]); } catch (Exception ex) { - if (logger.isLoggingEnabled()) - logger + if (isLoggingEnabled()) + getStackLogger() .logError( "Bad configuration value for LOG_FACTORY -- using default logger"); this.logRecordFactory = new DefaultMessageLogFactory(); @@ -1181,8 +1123,8 @@ public SipStackImpl(Properties configurationProperties) super.logStackTraceOnMessageSend = configurationProperties.getProperty( "gov.nist.javax.sip.LOG_STACK_TRACE_ON_MESSAGE_SEND", "false") .equalsIgnoreCase("true"); - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug( + if (isLoggingEnabled(LogWriter.TRACE_DEBUG)) + getStackLogger().logDebug( "created Sip stack. Properties = " + configurationProperties); InputStream in = getClass().getResourceAsStream("/TIMESTAMP"); if (in != null) { @@ -1194,9 +1136,9 @@ public SipStackImpl(Properties configurationProperties) if (in != null) { in.close(); } - logger.setBuildTimeStamp(buildTimeStamp); + getStackLogger().setBuildTimeStamp(buildTimeStamp); } catch (IOException ex) { - logger.logError("Could not open build timestamp."); + getStackLogger().logError("Could not open build timestamp."); } } @@ -1227,9 +1169,6 @@ public SipStackImpl(Properties configurationProperties) super.maxForkTime = Integer.parseInt( configurationProperties.getProperty("gov.nist.javax.sip.MAX_FORK_TIME_SECONDS","0")); - super.earlyDialogTimeout = Integer.parseInt( - configurationProperties.getProperty("gov.nist.javax.sip.EARLY_DIALOG_TIMEOUT_SECONDS","180")); - super.minKeepAliveInterval = Integer.parseInt(configurationProperties.getProperty("gov.nist.javax.sip.MIN_KEEPALIVE_TIME_SECONDS","-1")); @@ -1242,7 +1181,7 @@ public SipStackImpl(Properties configurationProperties) try { super.messageParserFactory = (MessageParserFactory) Class.forName(messageParserFactoryName).newInstance(); } catch (Exception e) { - logger + getStackLogger() .logError( "Bad configuration value for gov.nist.javax.sip.MESSAGE_PARSER_FACTORY", e); } @@ -1251,73 +1190,28 @@ public SipStackImpl(Properties configurationProperties) try { super.messageProcessorFactory = (MessageProcessorFactory) Class.forName(messageProcessorFactoryName).newInstance(); } catch (Exception e) { - logger + getStackLogger() .logError( "Bad configuration value for gov.nist.javax.sip.MESSAGE_PROCESSOR_FACTORY", e); } - - String defaultTimerName = configurationProperties.getProperty("gov.nist.javax.sip.TIMER_CLASS_NAME",DefaultSipTimer.class.getName()); - try { - setTimer((SipTimer)Class.forName(defaultTimerName).newInstance()); - getTimer().start(this, configurationProperties); - if (getThreadAuditor().isEnabled()) { - // Start monitoring the timer thread - getTimer().schedule(new PingTimer(null), 0); - } - } catch (Exception e) { - logger - .logError( - "Bad configuration value for gov.nist.javax.sip.TIMER_CLASS_NAME", e); - } - super.aggressiveCleanup = Boolean.parseBoolean(configurationProperties - .getProperty("gov.nist.javax.sip.AGGRESSIVE_CLEANUP", - Boolean.FALSE.toString())); - - String valveClassName = configurationProperties.getProperty("gov.nist.javax.sip.SIP_MESSAGE_VALVE", null); - if(valveClassName != null && !valveClassName.equals("")) { - try { - super.sipMessageValve = (SIPMessageValve) Class.forName(valveClassName).newInstance(); - final SipStack thisStack = this; - - try { - Thread.sleep(100); - sipMessageValve.init(thisStack); - } catch (Exception e) { - logger - .logError("Error intializing SIPMessageValve", e); - } - - } catch (Exception e) { - logger - .logError( - "Bad configuration value for gov.nist.javax.sip.SIP_MESSAGE_VALVE", e); - } - } - String interceptorClassName = configurationProperties.getProperty("gov.nist.javax.sip.SIP_EVENT_INTERCEPTOR", null); if(interceptorClassName != null && !interceptorClassName.equals("")) { try { super.sipEventInterceptor = (SIPEventInterceptor) Class.forName(interceptorClassName).newInstance(); final SipStack thisStack = this; - new Thread() { - public void run() { - try { - Thread.sleep(100); - sipEventInterceptor.init(thisStack); - } catch (Exception e) { - logger - .logError("Error intializing SIPEventInterceptor", e); - } - - } - }.start(); + + try { + sipEventInterceptor.init(thisStack); + } catch (Exception e) { + getStackLogger() + .logError("Error intializing SIPEventInterceptor", e); + } } catch (Exception e) { - logger + getStackLogger() .logError( "Bad configuration value for gov.nist.javax.sip.SIP_EVENT_INTERCEPTOR", e); } } - } /* @@ -1329,8 +1223,8 @@ public void run() { public synchronized ListeningPoint createListeningPoint(String address, int port, String transport) throws TransportNotSupportedException, InvalidArgumentException { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug( + if (isLoggingEnabled(LogWriter.TRACE_DEBUG)) + getStackLogger().logDebug( "createListeningPoint : address = " + address + " port = " + port + " transport = " + transport); @@ -1365,8 +1259,8 @@ public synchronized ListeningPoint createListeningPoint(String address, InetAddress inetAddr = InetAddress.getByName(address); MessageProcessor messageProcessor = this .createMessageProcessor(inetAddr, port, transport); - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - this.logger.logDebug( + if (this.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + this.getStackLogger().logDebug( "Created Message Processor: " + address + " port = " + port + " transport = " + transport); @@ -1379,8 +1273,8 @@ public synchronized ListeningPoint createListeningPoint(String address, messageProcessor.start(); return (ListeningPoint) lip; } catch (java.io.IOException ex) { - if (logger.isLoggingEnabled()) - logger.logError( + if (isLoggingEnabled()) + getStackLogger().logError( "Invalid argument address = " + address + " port = " + port + " transport = " + transport); throw new InvalidArgumentException(ex.getMessage(), ex); @@ -1397,8 +1291,8 @@ public SipProvider createSipProvider(ListeningPoint listeningPoint) throws ObjectInUseException { if (listeningPoint == null) throw new NullPointerException("null listeningPoint"); - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - this.logger.logDebug( + if (this.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + this.getStackLogger().logDebug( "createSipProvider: " + listeningPoint); ListeningPointImpl listeningPointImpl = (ListeningPointImpl) listeningPoint; if (listeningPointImpl.sipProvider != null) @@ -1538,16 +1432,12 @@ public ListeningPoint createListeningPoint(int port, String transport) * @see javax.sip.SipStack#stop() */ public void stop() { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug("stopStack -- stoppping the stack"); - logger.logStackTrace(); + if (isLoggingEnabled()) { + getStackLogger().logDebug("stopStack -- stoppping the stack"); + getStackLogger().logStackTrace(); } this.stopStack(); - if(super.sipMessageValve != null) - super.sipMessageValve.destroy(); - if(super.sipEventInterceptor != null) - super.sipEventInterceptor.destroy(); - this.sipProviders = Collections.synchronizedList(new LinkedList()); + this.sipProviders = new LinkedList(); this.listeningPoints = new Hashtable(); /* * Check for presence of an event scanner ( may happen if stack is @@ -1615,8 +1505,8 @@ public LogRecordFactory getLogRecordFactory() { */ @Deprecated public void addLogAppender(org.apache.log4j.Appender appender) { - if (this.logger instanceof gov.nist.core.LogWriter) { - ((gov.nist.core.LogWriter) this.logger).addAppender(appender); + if (this.getStackLogger() instanceof gov.nist.core.LogWriter) { + ((gov.nist.core.LogWriter) this.getStackLogger()).addAppender(appender); } } @@ -1629,8 +1519,8 @@ public void addLogAppender(org.apache.log4j.Appender appender) { */ @Deprecated public org.apache.log4j.Logger getLogger() { - if (this.logger instanceof gov.nist.core.LogWriter) { - return ((gov.nist.core.LogWriter) this.logger).getLogger(); + if (this.getStackLogger() instanceof gov.nist.core.LogWriter) { + return ((gov.nist.core.LogWriter) this.getStackLogger()).getLogger(); } return null; } @@ -1771,21 +1661,12 @@ public void releaseSem() { this.stackSemaphore.release(); } - /** + + /** * @return the configurationProperties */ public Properties getConfigurationProperties() { return configurationProperties; } - - /** - * @return the reEntrantListener - */ - public boolean isReEntrantListener() { - return reEntrantListener; - } - - - } diff --git a/src/gov/nist/javax/sip/TransactionExt.java b/src/gov/nist/javax/sip/TransactionExt.java index f0a77bb7e..b7258af0b 100644 --- a/src/gov/nist/javax/sip/TransactionExt.java +++ b/src/gov/nist/javax/sip/TransactionExt.java @@ -75,25 +75,6 @@ public interface TransactionExt extends Transaction { */ public List extractCertIdentities() throws SSLPeerUnverifiedException; - /** - * retrieve the value of release references to know if the stack performs optimizations - * on cleanup to save on memory - * @return release references value - * - * @since 2.0 - */ - public boolean isReleaseReferences(); - - /** - * If set to true it will release all references that it no longer needs. This will include the reference to the - * Request, Response, Dialogs, Any unused timers etc. This will significantly reduce memory - * consumption under high load - * @param releaseReferences - * - * @since 2.0 - */ - public void setReleaseReferences(boolean releaseReferences); - /** * Retrieve the value of Timer T2 (in ms) * @return T2 value (in ms) @@ -137,4 +118,5 @@ public interface TransactionExt extends Transaction { * @since 2.0 */ public void setTimerD(int interval); + } diff --git a/src/gov/nist/javax/sip/Utils.java b/src/gov/nist/javax/sip/Utils.java index 4bd39a583..5c039e12b 100755 --- a/src/gov/nist/javax/sip/Utils.java +++ b/src/gov/nist/javax/sip/Utils.java @@ -20,14 +20,12 @@ * Permission to use this software is contingent upon your acceptance * of the terms of this agreement * + * . * */ /******************************************************************************* * Product of NIST/ITL Advanced Networking Technologies Division (ANTD). * *******************************************************************************/ -/* - * Contributions and bug fixes by Vladimir Ralev - */ package gov.nist.javax.sip; import gov.nist.javax.sip.header.Via; @@ -35,8 +33,6 @@ import java.security.MessageDigest; import java.util.HashSet; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; /** * A few utilities that are used in various places by the stack. This is used to @@ -44,25 +40,23 @@ * and odds and ends. * * @author mranga - * @version 1.2 $Revision: 1.24 $ $Date: 2010-10-28 03:20:31 $ + * @version 1.2 $Revision: 1.21 $ $Date: 2009-10-18 13:46:37 $ */ public class Utils implements UtilsExt { - - private static int digesterPoolsSize = 20; - - private static MessageDigest[] digesterPool = new MessageDigest[digesterPoolsSize]; + private static MessageDigest digester; + private static java.util.Random rand; - + private static long counter = 0; private static int callIDCounter; private static String signature ; - + private static Utils instance = new Utils(); - + /** * to hex converter */ @@ -71,20 +65,19 @@ public class Utils implements UtilsExt { static { try { - for(int q=0; q:username@host[:port]. NOTE: in case of IPV6, host must be - * enclosed within []. - * @throws ParseException if the URI string is malformed. - */ - public javax.sip.address.SipURI createSipURI(String sipUri) throws ParseException; - -} diff --git a/src/gov/nist/javax/sip/address/AddressFactoryImpl.java b/src/gov/nist/javax/sip/address/AddressFactoryImpl.java index c28addc95..0adca4478 100755 --- a/src/gov/nist/javax/sip/address/AddressFactoryImpl.java +++ b/src/gov/nist/javax/sip/address/AddressFactoryImpl.java @@ -34,7 +34,7 @@ /** * Implementation of the JAIN-SIP address factory. - * @version 1.2 $Revision: 1.11 $ $Date: 2010-07-27 10:55:29 $ + * @version 1.2 $Revision: 1.9.2.1 $ $Date: 2010-07-27 10:55:22 $ * * @author M. Ranganathan
    * @@ -45,9 +45,9 @@ * Louis Pasteur University - Strasbourg - France
    * */ -public class AddressFactoryImpl implements AddressFactoryEx { - public static final Pattern SCHEME_PATTERN = Pattern.compile("\\p{Alpha}[[{\\p{Alpha}][\\p{Digit}][\\+][-][\\.]]*"); - +public class AddressFactoryImpl implements javax.sip.address.AddressFactory { + public static final Pattern SCHEME_PATTERN = Pattern.compile("\\p{Alpha}[[{\\p{Alpha}][\\p{Digit}][\\+][-][\\.]]*"); + /** Creates a new instance of AddressFactoryImpl */ public AddressFactoryImpl() { @@ -87,50 +87,13 @@ public javax.sip.address.Address createAddress( } - - public javax.sip.address.Address createAddress(javax.sip.address.URI uri) { - if (uri == null) - throw new NullPointerException("null address"); - AddressImpl addressImpl = new AddressImpl(); - addressImpl.setURI(uri); - return addressImpl; - } - - /** - * Creates an Address with the new address string value. The address - * string is parsed in order to create the new Address instance. Create - * with a String value of "*" creates a wildcard address. The wildcard - * can be determined if - * ((SipURI)Address.getURI).getUser() == *;. - * - * @param address - the new string value of the address. - * @throws ParseException which signals that an error has been reached - * unexpectedly while parsing the address value. - */ - public javax.sip.address.Address createAddress(String address) - throws java.text.ParseException { - if (address == null) - throw new NullPointerException("null address"); - - if (address.equals("*")) { - AddressImpl addressImpl = new AddressImpl(); - addressImpl.setAddressType(AddressImpl.WILD_CARD); - SipURI uri = new SipUri(); - uri.setUser("*"); - addressImpl.setURI( uri ); - return addressImpl; - } else { - StringMsgParser smp = new StringMsgParser(); - return smp.parseAddress(address); - } - } - - /** create a sip uri. * *@param uri -- the uri to parse. */ - public javax.sip.address.SipURI createSipURI(String uri) throws ParseException { + public javax.sip.address.SipURI createSipURI(String uri) + // throws java.net.URISyntaxException { + throws ParseException { if (uri == null) throw new NullPointerException("null URI"); try { @@ -138,6 +101,7 @@ public javax.sip.address.SipURI createSipURI(String uri) throws ParseException { SipUri sipUri = smp.parseSIPUrl(uri); return (SipURI) sipUri; } catch (ParseException ex) { + // throw new java.net.URISyntaxException(uri, ex.getMessage()); throw new ParseException(ex.getMessage(), 0); } @@ -148,11 +112,12 @@ public javax.sip.address.SipURI createSipURI(String uri) throws ParseException { *@param user -- the user *@param host -- the host. */ - public javax.sip.address.SipURI createSipURI(String user, String host) throws ParseException { + public javax.sip.address.SipURI createSipURI(String user, String host) + throws ParseException { if (host == null) throw new NullPointerException("null host"); - StringBuilder uriString = new StringBuilder("sip:"); + StringBuffer uriString = new StringBuffer("sip:"); if (user != null) { uriString.append(user); uriString.append("@"); @@ -165,18 +130,19 @@ public javax.sip.address.SipURI createSipURI(String user, String host) throws Pa uriString.append(host); - + StringMsgParser smp = new StringMsgParser(); try { - return this.createSipURI(uriString.toString()); + SipUri sipUri = smp.parseSIPUrl(uriString.toString()); + return sipUri; } catch (ParseException ex) { throw new ParseException(ex.getMessage(), 0); } } /** - * Creates a TelURL based on given URI string. The '+' should - * not be included in the phoneNumber string argument. If scheme is not present, it will be added. + * Creates a TelURL based on given URI string. The scheme or '+' should + * not be included in the phoneNumber string argument. * * @param uri - the new string value of the phoneNumber. * @throws URISyntaxException if the URI string is malformed. @@ -185,14 +151,7 @@ public javax.sip.address.TelURL createTelURL(String uri) throws ParseException { if (uri == null) throw new NullPointerException("null url"); - String telUrl = null; - if(uri.startsWith("tel:")) - { - telUrl = uri; - }else - { - telUrl = "tel:" + uri; - } + String telUrl = "tel:" + uri; try { StringMsgParser smp = new StringMsgParser(); TelURLImpl timp = (TelURLImpl) smp.parseUrl(telUrl); @@ -201,8 +160,44 @@ public javax.sip.address.TelURL createTelURL(String uri) throw new ParseException(ex.getMessage(), 0); } } - - + + public javax.sip.address.Address createAddress(javax.sip.address.URI uri) { + if (uri == null) + throw new NullPointerException("null address"); + AddressImpl addressImpl = new AddressImpl(); + addressImpl.setURI(uri); + return addressImpl; + } + + /** + * Creates an Address with the new address string value. The address + * string is parsed in order to create the new Address instance. Create + * with a String value of "*" creates a wildcard address. The wildcard + * can be determined if + * ((SipURI)Address.getURI).getUser() == *;. + * + * @param address - the new string value of the address. + * @throws ParseException which signals that an error has been reached + * unexpectedly while parsing the address value. + */ + public javax.sip.address.Address createAddress(String address) + throws java.text.ParseException { + if (address == null) + throw new NullPointerException("null address"); + + if (address.equals("*")) { + AddressImpl addressImpl = new AddressImpl(); + addressImpl.setAddressType(AddressImpl.WILD_CARD); + SipURI uri = new SipUri(); + uri.setUser("*"); + addressImpl.setURI( uri ); + return addressImpl; + } else { + StringMsgParser smp = new StringMsgParser(); + return smp.parseAddress(address); + } + } + /** * Creates a URI based on given URI string. The URI string is parsed in * order to create the new URI instance. Depending on the scheme the @@ -220,10 +215,12 @@ public javax.sip.address.URI createURI(String uri) throws ParseException { String scheme = urlParser.peekScheme(); if (scheme == null) throw new ParseException("bad scheme", 0); - if (scheme.equalsIgnoreCase("sip") || scheme.equalsIgnoreCase("sips")) { - return this.createSipURI(uri); + if (scheme.equalsIgnoreCase("sip")) { + return (javax.sip.address.URI) urlParser.sipURL(true); + } else if (scheme.equalsIgnoreCase("sips")) { + return (javax.sip.address.URI) urlParser.sipURL(true); } else if (scheme.equalsIgnoreCase("tel")) { - return this.createTelURL(uri); + return (javax.sip.address.URI) urlParser.telURL(true); } // Issue 316 : the scheme should match ALPHA *(ALPHA / DIGIT / "+" / "-" / "." ) if(!SCHEME_PATTERN.matcher(scheme).matches()) { @@ -231,7 +228,7 @@ public javax.sip.address.URI createURI(String uri) throws ParseException { } } catch (ParseException ex) { throw new ParseException(ex.getMessage(), 0); - } + } return new gov.nist.javax.sip.address.GenericURI(uri); } diff --git a/src/gov/nist/javax/sip/address/AddressImpl.java b/src/gov/nist/javax/sip/address/AddressImpl.java index a0eeea92f..92c3555cf 100755 --- a/src/gov/nist/javax/sip/address/AddressImpl.java +++ b/src/gov/nist/javax/sip/address/AddressImpl.java @@ -40,7 +40,7 @@ * * * - *@version 1.2 $Revision: 1.14 $ $Date: 2010-07-27 10:55:29 $ + *@version 1.2 $Revision: 1.11.2.2 $ $Date: 2010-07-27 10:55:23 $ * */ public final class AddressImpl @@ -161,11 +161,11 @@ public void removeParameter(String parameterName) { * @return String canonical encoded version of this address. */ public String encode() { - return encode(new StringBuilder()).toString(); + return encode(new StringBuffer()).toString(); } - public StringBuilder encode(StringBuilder buffer) { - if (this.addressType == WILD_CARD) { + public StringBuffer encode(StringBuffer buffer) { + if (this.addressType == WILD_CARD) { buffer.append('*'); } else { @@ -175,7 +175,7 @@ public StringBuilder encode(StringBuilder buffer) { .append(DOUBLE_QUOTE) .append(SP); } - if (address != null) { + if (address != null) { if (addressType == NAME_ADDR || displayName != null) buffer.append(LESS_THAN); address.encode(buffer); diff --git a/src/gov/nist/javax/sip/address/Authority.java b/src/gov/nist/javax/sip/address/Authority.java index ff1629705..dedb0b034 100755 --- a/src/gov/nist/javax/sip/address/Authority.java +++ b/src/gov/nist/javax/sip/address/Authority.java @@ -32,7 +32,7 @@ /** * Authority part of a URI structure. Section 3.2.2 RFC2396 * - * @version 1.2 $Revision: 1.11 $ $Date: 2010-05-06 14:08:06 $ + * @version 1.2 $Revision: 1.10 $ $Date: 2009-12-16 14:48:33 $ * * @author M. Ranganathan
    * @@ -56,10 +56,10 @@ public class Authority extends NetObject { * @return encoded string (does the same thing as toString) */ public String encode() { - return encode(new StringBuilder()).toString(); + return encode(new StringBuffer()).toString(); } - public StringBuilder encode(StringBuilder buffer) { + public StringBuffer encode(StringBuffer buffer) { if (userInfo != null) { userInfo.encode(buffer); buffer.append(AT); diff --git a/src/gov/nist/javax/sip/address/GenericURI.java b/src/gov/nist/javax/sip/address/GenericURI.java index 8e90f093e..31cf8822d 100755 --- a/src/gov/nist/javax/sip/address/GenericURI.java +++ b/src/gov/nist/javax/sip/address/GenericURI.java @@ -32,7 +32,7 @@ * Implementation of the URI class. This relies on the 1.4 URI class. * * @author M. Ranganathan
    - * @version 1.2 $Revision: 1.11 $ $Date: 2010-05-06 14:08:06 $ + * @version 1.2 $Revision: 1.10 $ $Date: 2009-11-15 19:50:45 $ * * */ @@ -85,7 +85,7 @@ public String encode() { return uriString; } - public StringBuilder encode(StringBuilder buffer) { + public StringBuffer encode(StringBuffer buffer) { return buffer.append(uriString); } diff --git a/src/gov/nist/javax/sip/address/SipUri.java b/src/gov/nist/javax/sip/address/SipUri.java index 77ee359b3..f09a67dc5 100755 --- a/src/gov/nist/javax/sip/address/SipUri.java +++ b/src/gov/nist/javax/sip/address/SipUri.java @@ -51,7 +51,7 @@ * * * @author M. Ranganathan
    - * @version 1.2 $Revision: 1.24 $ $Date: 2010-05-06 14:08:05 $ + * @version 1.2 $Revision: 1.23 $ $Date: 2010-01-20 10:12:03 $ * * * @@ -235,10 +235,10 @@ public boolean equals(Object that) { * @return String */ public String encode() { - return encode(new StringBuilder()).toString(); + return encode(new StringBuffer()).toString(); } - public StringBuilder encode(StringBuilder buffer) { + public StringBuffer encode(StringBuffer buffer) { buffer.append(scheme).append(COLON); if (authority != null) authority.encode(buffer); @@ -274,11 +274,11 @@ public String getUserAtHost() { user = authority.getUserInfo().getUser(); String host = authority.getHost().encode(); - StringBuilder s = null; + StringBuffer s = null; if (user.equals("")) { - s = new StringBuilder(); + s = new StringBuffer(); } else { - s = new StringBuilder(user).append(AT); + s = new StringBuffer(user).append(AT); } return s.append(host).toString(); } @@ -295,11 +295,11 @@ public String getUserAtHostPort() { String host = authority.getHost().encode(); int port = authority.getPort(); // If port not set assign the default. - StringBuilder s = null; + StringBuffer s = null; if (user.equals("")) { - s = new StringBuilder(); + s = new StringBuffer(); } else { - s = new StringBuilder(user).append(AT); + s = new StringBuffer(user).append(AT); } if (port != -1) { return s.append(host).append(COLON).append(port).toString(); diff --git a/src/gov/nist/javax/sip/address/TelURLImpl.java b/src/gov/nist/javax/sip/address/TelURLImpl.java index ddd23c774..20ecb03ab 100755 --- a/src/gov/nist/javax/sip/address/TelURLImpl.java +++ b/src/gov/nist/javax/sip/address/TelURLImpl.java @@ -33,7 +33,7 @@ /** * Implementation of the TelURL interface. * - * @version 1.2 $Revision: 1.11 $ $Date: 2010-05-06 14:08:06 $ + * @version 1.2 $Revision: 1.10 $ $Date: 2009-11-15 19:50:45 $ * * @author M. Ranganathan * @@ -159,10 +159,10 @@ public String toString() { } public String encode() { - return encode(new StringBuilder()).toString(); + return encode(new StringBuffer()).toString(); } - public StringBuilder encode(StringBuilder buffer) { + public StringBuffer encode(StringBuffer buffer) { buffer.append(this.scheme).append(':'); telephoneNumber.encode(buffer); return buffer; diff --git a/src/gov/nist/javax/sip/address/TelephoneNumber.java b/src/gov/nist/javax/sip/address/TelephoneNumber.java index 604dceb1d..72dc3e4de 100755 --- a/src/gov/nist/javax/sip/address/TelephoneNumber.java +++ b/src/gov/nist/javax/sip/address/TelephoneNumber.java @@ -32,7 +32,7 @@ /** * Telephone number class. * @version 1.2 - * @version 1.2 $Revision: 1.11 $ $Date: 2010-05-06 14:08:05 $ + * @version 1.2 $Revision: 1.10 $ $Date: 2009-07-17 18:57:23 $ * * @author M. Ranganathan * @@ -182,10 +182,10 @@ public void setPhoneNumber(String num) { } public String encode() { - return encode(new StringBuilder()).toString(); + return encode(new StringBuffer()).toString(); } - public StringBuilder encode(StringBuilder buffer) { + public StringBuffer encode(StringBuffer buffer) { if (isglobal) buffer.append('+'); buffer.append(phoneNumber); diff --git a/src/gov/nist/javax/sip/address/UriDecoder.java b/src/gov/nist/javax/sip/address/UriDecoder.java index a2175964a..cdeef4441 100644 --- a/src/gov/nist/javax/sip/address/UriDecoder.java +++ b/src/gov/nist/javax/sip/address/UriDecoder.java @@ -58,7 +58,7 @@ public static String decode(String uri) { // if there is no % we just return the same uri String uriToWorkOn = uri; int indexOfNextPercent = uriToWorkOn.indexOf("%"); - StringBuilder decodedUri = new StringBuilder(); + StringBuffer decodedUri = new StringBuffer(); while(indexOfNextPercent != -1) { decodedUri.append(uriToWorkOn.substring(0, indexOfNextPercent)); diff --git a/src/gov/nist/javax/sip/address/UserInfo.java b/src/gov/nist/javax/sip/address/UserInfo.java index f7a75a21b..9581de34c 100755 --- a/src/gov/nist/javax/sip/address/UserInfo.java +++ b/src/gov/nist/javax/sip/address/UserInfo.java @@ -35,7 +35,7 @@ /** * User information part of a URL. * - * @version 1.2 $Revision: 1.9 $ $Date: 2010-05-06 14:08:06 $ + * @version 1.2 $Revision: 1.8 $ $Date: 2009-07-17 18:57:23 $ * @author M. Ranganathan
    * */ @@ -103,10 +103,10 @@ public boolean equals(Object obj) { * @return String */ public String encode() { - return encode(new StringBuilder()).toString(); + return encode(new StringBuffer()).toString(); } - public StringBuilder encode(StringBuilder buffer) { + public StringBuffer encode(StringBuffer buffer) { if (password != null) buffer.append(user).append(COLON).append(password); else diff --git a/src/gov/nist/javax/sip/clientauthutils/AuthenticationHelperImpl.java b/src/gov/nist/javax/sip/clientauthutils/AuthenticationHelperImpl.java index 5748f6a01..885486e5d 100644 --- a/src/gov/nist/javax/sip/clientauthutils/AuthenticationHelperImpl.java +++ b/src/gov/nist/javax/sip/clientauthutils/AuthenticationHelperImpl.java @@ -17,9 +17,6 @@ * proposed a way to fix them (his proposition was taken into account). */ -import gov.nist.core.CommonLogger; -import gov.nist.core.LogWriter; -import gov.nist.core.StackLogger; import gov.nist.javax.sip.address.SipUri; import gov.nist.javax.sip.message.SIPRequest; import gov.nist.javax.sip.stack.SIPClientTransaction; @@ -63,7 +60,7 @@ */ public class AuthenticationHelperImpl implements AuthenticationHelper { - private static StackLogger logger = CommonLogger.getLogger(AuthenticationHelperImpl.class); + /** * Credentials cached so far. */ @@ -128,10 +125,9 @@ public ClientTransaction handleChallenge(Response challenge, ClientTransaction challengedTransaction, SipProvider transactionCreator, int cacheTime) throws SipException, NullPointerException { try { - - if ( logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("handleChallenge: " + challenge); - + if (sipStack.isLoggingEnabled()) { + sipStack.getStackLogger().logDebug("handleChallenge: " + challenge); + } SIPRequest challengedRequest = ((SIPRequest) challengedTransaction.getRequest()); @@ -230,11 +226,6 @@ public ClientTransaction handleChallenge(Response challenge, if ( this.accountManager instanceof SecureAccountManager ) { UserCredentialHash credHash = ((SecureAccountManager)this.accountManager).getCredentialHash(challengedTransaction,realm); - if ( credHash == null ) { - logger.logDebug("Could not find creds"); - throw new SipException( - "Cannot find user creds for the given user name and realm"); - } URI uri = reoriginatedRequest.getRequestURI(); sipDomain = credHash.getSipDomain(); authorization = this.getAuthorization(reoriginatedRequest @@ -243,13 +234,11 @@ public ClientTransaction handleChallenge(Response challenge, reoriginatedRequest.getRawContent()), authHeader, credHash); } else { UserCredentials userCreds = ((AccountManager) this.accountManager).getCredentials(challengedTransaction, realm); - - if (userCreds == null) { + sipDomain = userCreds.getSipDomain(); + if (userCreds == null) throw new SipException( "Cannot find user creds for the given user name and realm"); - } - sipDomain = userCreds.getSipDomain(); - + // we haven't yet authenticated this realm since we were // started. @@ -258,32 +247,26 @@ public ClientTransaction handleChallenge(Response challenge, (reoriginatedRequest.getContent() == null) ? "" : new String( reoriginatedRequest.getRawContent()), authHeader, userCreds); } - - if ( logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( - "Created authorization header: " + authorization.toString()); - } - + if (sipStack.isLoggingEnabled()) + sipStack.getStackLogger().logDebug( + "Created authorization header: " + authorization.toString()); - if (cacheTime != 0) { - String callId = challengedRequest.getCallId().getCallId(); - cachedCredentials.cacheAuthorizationHeader(callId, + if (cacheTime != 0) + cachedCredentials.cacheAuthorizationHeader(sipDomain, authorization, cacheTime); - } + reoriginatedRequest.addHeader(authorization); } - - if ( logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( + if (sipStack.isLoggingEnabled()) { + sipStack.getStackLogger().logDebug( "Returning authorization transaction." + retryTran); } - return retryTran; } catch (SipException ex) { throw ex; } catch (Exception ex) { - logger.logError("Unexpected exception ", ex); + sipStack.getStackLogger().logError("Unexpected exception ", ex); throw new SipException("Unexpected exception ", ex); } } @@ -319,7 +302,7 @@ private AuthorizationHeader getAuthorization(String method, String uri, String r userCredentials.getUserName(), authHeader.getRealm(), userCredentials .getPassword(), authHeader.getNonce(), nc_value, // JvB added cnonce, // JvB added - method, uri, requestBody, qop,logger);// jvb changed + method, uri, requestBody, qop,sipStack.getStackLogger());// jvb changed AuthorizationHeader authorization = null; try { @@ -385,7 +368,7 @@ private AuthorizationHeader getAuthorization(String method, String uri, String r response = MessageDigestAlgorithm.calculateResponse(authHeader.getAlgorithm(), userCredentials.getHashUserDomainPassword(), authHeader.getNonce(), nc_value, // JvB added cnonce, // JvB added - method, uri, requestBody, qop,logger);// jvb changed + method, uri, requestBody, qop,sipStack.getStackLogger());// jvb changed AuthorizationHeader authorization = null; try { @@ -453,8 +436,8 @@ public void setAuthenticationHeaders(Request request) { Collection authHeaders = this.cachedCredentials .getCachedAuthorizationHeaders(callId); if (authHeaders == null) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug( + if (sipStack.isLoggingEnabled()) + sipStack.getStackLogger().logDebug( "Could not find authentication headers for " + callId); return; } diff --git a/src/gov/nist/javax/sip/clientauthutils/CredentialsCache.java b/src/gov/nist/javax/sip/clientauthutils/CredentialsCache.java index 4b7c1c2c1..2a84f28f8 100644 --- a/src/gov/nist/javax/sip/clientauthutils/CredentialsCache.java +++ b/src/gov/nist/javax/sip/clientauthutils/CredentialsCache.java @@ -1,16 +1,12 @@ package gov.nist.javax.sip.clientauthutils; -import gov.nist.javax.sip.stack.SIPStackTimerTask; -import gov.nist.javax.sip.stack.timers.SipTimer; - -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; -import java.util.ListIterator; -import java.util.TimerTask; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; -import javax.sip.header.AuthorizationHeader; +import javax.sip.*; +import javax.sip.header.*; +import javax.sip.address.*; +import javax.sip.message.*; /** * A cache of authorization headers to be used for subsequent processing when we @@ -28,18 +24,19 @@ class CredentialsCache { */ private ConcurrentHashMap> authorizationHeaders = new ConcurrentHashMap>(); - private SipTimer timer; + private Timer timer; - class TimeoutTask extends SIPStackTimerTask { + class TimeoutTask extends TimerTask { String callId; String userName; - public TimeoutTask(String userName, String callId) { - this.callId = callId; + public TimeoutTask(String userName, String proxyDomain) { + this.callId = proxyDomain; this.userName = userName; } - public void runTask() { + @Override + public void run() { authorizationHeaders.remove(callId); } @@ -48,7 +45,7 @@ public void runTask() { - CredentialsCache (SipTimer timer) { + CredentialsCache (Timer timer) { this.timer = timer; } diff --git a/src/gov/nist/javax/sip/clientauthutils/MessageDigestAlgorithm.java b/src/gov/nist/javax/sip/clientauthutils/MessageDigestAlgorithm.java index aef83df11..8c1752d3d 100644 --- a/src/gov/nist/javax/sip/clientauthutils/MessageDigestAlgorithm.java +++ b/src/gov/nist/javax/sip/clientauthutils/MessageDigestAlgorithm.java @@ -1,6 +1,5 @@ package gov.nist.javax.sip.clientauthutils; -import gov.nist.core.LogWriter; import gov.nist.core.StackLogger; import java.security.MessageDigest; @@ -40,7 +39,7 @@ static String calculateResponse(String algorithm, String hashUserNameRealmPasswd String nonce_value, String nc_value, String cnonce_value, String method, String digest_uri_value, String entity_body, String qop_value, StackLogger stackLogger) { - if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + if (stackLogger.isLoggingEnabled()) { stackLogger.logDebug("trying to authenticate using : " + algorithm + ", "+ hashUserNameRealmPasswd + ", " + nonce_value + ", " + nc_value + ", " + cnonce_value + ", " + method + ", " + digest_uri_value @@ -116,7 +115,7 @@ static String calculateResponse(String algorithm, String username_value, String String passwd, String nonce_value, String nc_value, String cnonce_value, String method, String digest_uri_value, String entity_body, String qop_value, StackLogger stackLogger) { - if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + if (stackLogger.isLoggingEnabled()) { stackLogger.logDebug("trying to authenticate using : " + algorithm + ", " + username_value + ", " + realm_value + ", " + (passwd != null && passwd.trim().length() > 0) + ", " + nonce_value + ", " diff --git a/src/gov/nist/javax/sip/header/Accept.java b/src/gov/nist/javax/sip/header/Accept.java index 376008848..29ba55427 100755 --- a/src/gov/nist/javax/sip/header/Accept.java +++ b/src/gov/nist/javax/sip/header/Accept.java @@ -34,7 +34,7 @@ * Accept header : The top level header is actually AcceptList which is a list of * Accept headers. * - * @version 1.2 $Revision: 1.10 $ $Date: 2010-05-06 14:07:54 $ + * @version 1.2 $Revision: 1.9 $ $Date: 2009-07-17 18:57:24 $ * * @since 1.1 * @@ -89,10 +89,10 @@ public boolean allowsAllContentSubTypes() { *@return encoded value of the header as a string. */ protected String encodeBody() { - return encodeBody(new StringBuilder()).toString(); + return encodeBody(new StringBuffer()).toString(); } - protected StringBuilder encodeBody(StringBuilder buffer) { + protected StringBuffer encodeBody(StringBuffer buffer) { if (mediaRange != null) mediaRange.encode(buffer); if (parameters != null && !parameters.isEmpty()) { diff --git a/src/gov/nist/javax/sip/header/AcceptEncoding.java b/src/gov/nist/javax/sip/header/AcceptEncoding.java index ee7daf914..09a570199 100755 --- a/src/gov/nist/javax/sip/header/AcceptEncoding.java +++ b/src/gov/nist/javax/sip/header/AcceptEncoding.java @@ -37,7 +37,7 @@ * * @author M. Ranganathan * @author Olivier Deruelle
    - * @version 1.2 $Revision: 1.8 $ $Date: 2010-05-06 14:07:54 $ + * @version 1.2 $Revision: 1.7 $ $Date: 2009-07-17 18:57:24 $ * @since 1.1 * *
    @@ -91,10 +91,10 @@ public AcceptEncoding() {
          * @return the value of this header encoded into a string.
          */
         protected String encodeBody() {
    -        return encode(new StringBuilder()).toString();
    +        return encode(new StringBuffer()).toString();
         }
     
    -    protected StringBuilder encodeBody(StringBuilder buffer) {
    +    protected StringBuffer encodeBody(StringBuffer buffer) {
             if (contentCoding != null) {
                 buffer.append(contentCoding);
             }
    diff --git a/src/gov/nist/javax/sip/header/AcceptLanguage.java b/src/gov/nist/javax/sip/header/AcceptLanguage.java
    index 7051ce707..70e917989 100755
    --- a/src/gov/nist/javax/sip/header/AcceptLanguage.java
    +++ b/src/gov/nist/javax/sip/header/AcceptLanguage.java
    @@ -36,7 +36,7 @@
      * Accept Language body.
      *
      * @author M. Ranganathan
    - * @version 1.2 $Revision: 1.9 $ $Date: 2010-05-06 14:07:52 $
    + * @version 1.2 $Revision: 1.8 $ $Date: 2009-10-18 13:46:32 $
      * @since 1.1
      *
      *
    @@ -71,16 +71,15 @@ public AcceptLanguage() {
         /** Encode the value of this header to a string.
          *@return  encoded header as a string.
          */
    -    @Override
    -    protected StringBuilder encodeBody(StringBuilder encoding) {
    -//        StringBuilder encoding = new StringBuilder();
    +    protected String encodeBody() {
    +        StringBuffer encoding = new StringBuffer();
             if (languageRange != null) {
                 encoding.append(languageRange);
             }
             if (!parameters.isEmpty()) {
                 encoding.append(SEMICOLON).append(parameters.encode());
             }
    -        return encoding;
    +        return encoding.toString();
         }
     
         /** get the LanguageRange field
    diff --git a/src/gov/nist/javax/sip/header/AlertInfo.java b/src/gov/nist/javax/sip/header/AlertInfo.java
    index f7c00bc2d..184d18845 100755
    --- a/src/gov/nist/javax/sip/header/AlertInfo.java
    +++ b/src/gov/nist/javax/sip/header/AlertInfo.java
    @@ -38,7 +38,7 @@
      *
      * @since 1.1
      *
    - * @version 1.2 $Revision: 1.9 $ $Date: 2010-05-06 14:07:50 $
    + * @version 1.2 $Revision: 1.8 $ $Date: 2009-07-17 18:57:25 $
      *
      *
      */
    @@ -67,9 +67,8 @@ public AlertInfo() {
          * Return value encoding in canonical form.
          * @return The value of the header in canonical encoding.
          */
    -    @Override
    -    protected StringBuilder encodeBody(StringBuilder encoding) {
    -//        StringBuilder encoding = new StringBuilder();
    +    protected String encodeBody() {
    +        StringBuffer encoding = new StringBuffer();
             if (uri != null) {
                 encoding.append(LESS_THAN).append(uri.encode()).append(GREATER_THAN);
             } else if (string != null) {
    @@ -78,7 +77,7 @@ protected StringBuilder encodeBody(StringBuilder encoding) {
             if (!parameters.isEmpty()) {
                 encoding.append(SEMICOLON).append(parameters.encode());
             }
    -        return encoding;
    +        return encoding.toString();
         }
     
         /**
    diff --git a/src/gov/nist/javax/sip/header/Allow.java b/src/gov/nist/javax/sip/header/Allow.java
    index 714d3ee7e..0fb71b8bc 100644
    --- a/src/gov/nist/javax/sip/header/Allow.java
    +++ b/src/gov/nist/javax/sip/header/Allow.java
    @@ -32,7 +32,7 @@
      * Allow SIPHeader.
      *
      * @author M. Ranganathan   
    - * @version 1.2 $Revision: 1.7 $ $Date: 2010-05-06 14:07:47 $ + * @version 1.2 $Revision: 1.6 $ $Date: 2009-07-17 18:57:26 $ * @since 1.1 * * @@ -84,8 +84,7 @@ public void setMethod(String method) throws ParseException { /** Return body encoded in canonical form. * @return body encoded as a string. */ - @Override - protected StringBuilder encodeBody(StringBuilder buffer) { - return buffer.append(method); + protected String encodeBody() { + return method; } } diff --git a/src/gov/nist/javax/sip/header/AllowEvents.java b/src/gov/nist/javax/sip/header/AllowEvents.java index a0fde11c4..5386f7cc2 100755 --- a/src/gov/nist/javax/sip/header/AllowEvents.java +++ b/src/gov/nist/javax/sip/header/AllowEvents.java @@ -37,7 +37,7 @@ * @author Olivier Deruelle
    * * - * @version 1.2 $Revision: 1.8 $ $Date: 2010-05-06 14:07:48 $ + * @version 1.2 $Revision: 1.7 $ $Date: 2009-07-17 18:57:26 $ * @since 1.1 */ public final class AllowEvents @@ -94,8 +94,7 @@ public String getEventType() { /** Return body encoded in canonical form. * @return body encoded as a string. */ - @Override - protected StringBuilder encodeBody(StringBuilder buffer) { - return buffer.append(eventType); + protected String encodeBody() { + return eventType; } } diff --git a/src/gov/nist/javax/sip/header/AuthenticationHeader.java b/src/gov/nist/javax/sip/header/AuthenticationHeader.java index aa238db3e..24bbfbe77 100755 --- a/src/gov/nist/javax/sip/header/AuthenticationHeader.java +++ b/src/gov/nist/javax/sip/header/AuthenticationHeader.java @@ -43,7 +43,7 @@ * @author Olivier Deruelle * @author M. Ranganathan
    * @since 1.1 - * @version 1.2 $Revision: 1.14 $ $Date: 2010-05-06 14:07:47 $ + * @version 1.2 $Revision: 1.13 $ $Date: 2009-10-18 13:46:32 $ * * */ @@ -153,10 +153,9 @@ public void setChallenge(Challenge challenge) { * * @return canonical string. */ - public StringBuilder encodeBody(StringBuilder buffer) { + public String encodeBody() { this.parameters.setSeparator(Separators.COMMA); - buffer = buffer.append(this.scheme).append(SP); - return parameters.encode(buffer); + return this.scheme + SP + parameters.encode(); } /** diff --git a/src/gov/nist/javax/sip/header/AuthenticationInfo.java b/src/gov/nist/javax/sip/header/AuthenticationInfo.java index 76610a077..86aeb0463 100755 --- a/src/gov/nist/javax/sip/header/AuthenticationInfo.java +++ b/src/gov/nist/javax/sip/header/AuthenticationInfo.java @@ -31,7 +31,7 @@ * * @author M. Ranganathan NIST/ITL/ANTD * @since 1.1 - * @version 1.2 $Revision: 1.10 $ $Date: 2010-05-06 14:07:50 $ + * @version 1.2 $Revision: 1.9 $ $Date: 2009-07-17 18:57:27 $ * * */ @@ -58,8 +58,8 @@ public void add(NameValue nv) { /** Value of header encoded in canonical form. */ - protected StringBuilder encodeBody(StringBuilder buffer) { - return parameters.encode(buffer); + protected String encodeBody() { + return parameters.encode(); } @@ -84,7 +84,7 @@ public NameValue getAuthInfo(String name) { * */ public String getAuthenticationInfo() { - return this.encodeBody(new StringBuilder()).toString(); + return this.encodeBody(); } /** Returns the CNonce value of this AuthenticationInfoHeader. diff --git a/src/gov/nist/javax/sip/header/CSeq.java b/src/gov/nist/javax/sip/header/CSeq.java index 2af520842..4cb090eaa 100755 --- a/src/gov/nist/javax/sip/header/CSeq.java +++ b/src/gov/nist/javax/sip/header/CSeq.java @@ -38,7 +38,7 @@ * CSeq SIP Header. * * @author M. Ranganathan
    - * @version 1.2 $Revision: 1.11 $ $Date: 2010-05-06 14:07:48 $ + * @version 1.2 $Revision: 1.10 $ $Date: 2009-10-18 13:46:33 $ * @since 1.1 * */ @@ -109,10 +109,10 @@ public String encode() { * @return encoded string. */ public String encodeBody() { - return encodeBody(new StringBuilder()).toString(); + return encodeBody(new StringBuffer()).toString(); } - protected StringBuilder encodeBody(StringBuilder buffer) { + protected StringBuffer encodeBody(StringBuffer buffer) { return buffer.append(seqno).append(SP).append(method.toUpperCase()); } diff --git a/src/gov/nist/javax/sip/header/CallID.java b/src/gov/nist/javax/sip/header/CallID.java index 0637a74ab..3af00af10 100644 --- a/src/gov/nist/javax/sip/header/CallID.java +++ b/src/gov/nist/javax/sip/header/CallID.java @@ -34,7 +34,7 @@ * Call ID SIPHeader. * * @author M. Ranganathan
    - * @version 1.2 $Revision: 1.8 $ $Date: 2010-05-06 14:07:54 $ + * @version 1.2 $Revision: 1.7 $ $Date: 2009-07-17 18:57:27 $ * @since 1.1 */ public class CallID @@ -79,10 +79,10 @@ public boolean equals( Object other ) { *@return String encoded body part of the header. */ public String encodeBody() { - return encodeBody(new StringBuilder()).toString(); + return encodeBody(new StringBuffer()).toString(); } - protected StringBuilder encodeBody(StringBuilder buffer) { + protected StringBuffer encodeBody(StringBuffer buffer) { if (callIdentifier != null) callIdentifier.encode(buffer); diff --git a/src/gov/nist/javax/sip/header/CallIdentifier.java b/src/gov/nist/javax/sip/header/CallIdentifier.java index ff097645d..3c3f5d839 100755 --- a/src/gov/nist/javax/sip/header/CallIdentifier.java +++ b/src/gov/nist/javax/sip/header/CallIdentifier.java @@ -32,7 +32,7 @@ * The call identifer that goes into a callID header and a in-reply-to header. * * @author M. Ranganathan
    - * @version 1.2 $Revision: 1.8 $ $Date: 2010-05-06 14:07:46 $ + * @version 1.2 $Revision: 1.7 $ $Date: 2009-12-16 02:38:35 $ * @see CallID * @see InReplyTo * @since 1.1 @@ -85,10 +85,10 @@ public CallIdentifier(String cid) throws IllegalArgumentException { * @return String to set */ public String encode() { - return encode(new StringBuilder()).toString(); + return encode(new StringBuffer()).toString(); } - public StringBuilder encode(StringBuilder buffer) { + public StringBuffer encode(StringBuffer buffer) { buffer.append(localId); if (host != null) { buffer.append(AT).append(host); diff --git a/src/gov/nist/javax/sip/header/CallInfo.java b/src/gov/nist/javax/sip/header/CallInfo.java index 844ee3c05..25af57459 100755 --- a/src/gov/nist/javax/sip/header/CallInfo.java +++ b/src/gov/nist/javax/sip/header/CallInfo.java @@ -35,7 +35,7 @@ * * * @author "M. Ranganathan"
    - * @version 1.2 $Revision: 1.8 $ $Date: 2010-05-06 14:07:48 $ + * @version 1.2 $Revision: 1.7 $ $Date: 2009-07-17 18:57:28 $ * @since 1.1 */ public final class CallInfo @@ -61,10 +61,10 @@ public CallInfo() { * @return String */ public String encodeBody() { - return encodeBody(new StringBuilder()).toString(); + return encodeBody(new StringBuffer()).toString(); } - protected StringBuilder encodeBody(StringBuilder buffer) { + protected StringBuffer encodeBody(StringBuffer buffer) { buffer.append(LESS_THAN); info.encode(buffer); buffer.append(GREATER_THAN); diff --git a/src/gov/nist/javax/sip/header/Challenge.java b/src/gov/nist/javax/sip/header/Challenge.java index b6cc11e13..8005c4873 100755 --- a/src/gov/nist/javax/sip/header/Challenge.java +++ b/src/gov/nist/javax/sip/header/Challenge.java @@ -34,7 +34,7 @@ * Challenge part of the Auth header. This is only used by the parser interface * * @author M. Ranganathan
    - * @version 1.2 $Revision: 1.8 $ $Date: 2010-05-06 14:07:54 $ + * @version 1.2 $Revision: 1.7 $ $Date: 2009-07-17 18:57:28 $ * @since 1.1 * */ @@ -79,7 +79,7 @@ public Challenge() { * @return String */ public String encode() { - return new StringBuilder(scheme) + return new StringBuffer(scheme) .append(SP) .append(authParams.encode()) .toString(); diff --git a/src/gov/nist/javax/sip/header/Contact.java b/src/gov/nist/javax/sip/header/Contact.java index f68a82505..55bd100b9 100755 --- a/src/gov/nist/javax/sip/header/Contact.java +++ b/src/gov/nist/javax/sip/header/Contact.java @@ -47,7 +47,7 @@ * @see gov.nist.javax.sip.header.ContactList * * @author M. Ranganathan
    - * @version 1.2 $Revision: 1.14 $ $Date: 2010-05-06 14:07:50 $ + * @version 1.2 $Revision: 1.13 $ $Date: 2009-10-18 13:46:31 $ * @since 1.1 * * @@ -97,10 +97,10 @@ public void setParameter(String name, String value) throws ParseException { * @return string encoding of the header value. */ protected String encodeBody() { - return encodeBody(new StringBuilder()).toString(); + return encodeBody(new StringBuffer()).toString(); } - protected StringBuilder encodeBody(StringBuilder buffer) { + protected StringBuffer encodeBody(StringBuffer buffer) { if (wildCardFlag) { buffer.append('*'); } diff --git a/src/gov/nist/javax/sip/header/ContentDisposition.java b/src/gov/nist/javax/sip/header/ContentDisposition.java index 7a8f6a398..6dc3580e3 100644 --- a/src/gov/nist/javax/sip/header/ContentDisposition.java +++ b/src/gov/nist/javax/sip/header/ContentDisposition.java @@ -34,7 +34,7 @@ * Content Dispositon SIP Header. * * @author M. Ranganathan
    - * @version 1.2 $Revision: 1.6 $ $Date: 2010-05-06 14:07:47 $ + * @version 1.2 $Revision: 1.5 $ $Date: 2009-07-17 18:57:29 $ * @since 1.1 * */ @@ -63,13 +63,12 @@ public ContentDisposition() { * @return encoded value of header. * */ - public StringBuilder encodeBody(StringBuilder encoding) { -// StringBuilder encoding = new StringBuilder(dispositionType); - encoding.append(dispositionType); + public String encodeBody() { + StringBuffer encoding = new StringBuffer(dispositionType); if (!this.parameters.isEmpty()) { encoding.append(SEMICOLON).append(parameters.encode()); } - return encoding; + return encoding.toString(); } /** @@ -119,14 +118,11 @@ public void setHandling(String handling) throws ParseException { * @return interpretation of the message body or message body part */ public String getContentDisposition() { - return this.encodeBody(new StringBuilder()).toString(); + return this.encodeBody(); } } /* * $Log: not supported by cvs2svn $ - * Revision 1.5 2009/07/17 18:57:29 emcho - * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. - * * Revision 1.4 2006/07/13 09:01:06 mranga * Issue number: * Obtained from: diff --git a/src/gov/nist/javax/sip/header/ContentEncoding.java b/src/gov/nist/javax/sip/header/ContentEncoding.java index 94cd39368..462971bc2 100644 --- a/src/gov/nist/javax/sip/header/ContentEncoding.java +++ b/src/gov/nist/javax/sip/header/ContentEncoding.java @@ -74,7 +74,7 @@ * * @author M. Ranganathan
    * @author Olivier Deruelle
    - * @version 1.2 $Revision: 1.6 $ $Date: 2010-05-06 14:07:53 $ + * @version 1.2 $Revision: 1.5 $ $Date: 2009-07-17 18:57:29 $ * @since 1.1 */ public class ContentEncoding @@ -110,8 +110,8 @@ public ContentEncoding(String enc) { * Canonical encoding of body of the header. * @return encoded body of the header. */ - public StringBuilder encodeBody(StringBuilder buffer) { - return buffer.append(contentEncoding); + public String encodeBody() { + return contentEncoding; } /** diff --git a/src/gov/nist/javax/sip/header/ContentLanguage.java b/src/gov/nist/javax/sip/header/ContentLanguage.java index 952dc8215..1ca3264d2 100755 --- a/src/gov/nist/javax/sip/header/ContentLanguage.java +++ b/src/gov/nist/javax/sip/header/ContentLanguage.java @@ -76,7 +76,7 @@ * limited to textual documents. *
    * @author M. Ranganathan -* @version 1.2 $Revision: 1.9 $ $Date: 2010-05-06 14:07:51 $ +* @version 1.2 $Revision: 1.8 $ $Date: 2009-07-17 18:57:29 $ * @since 1.1 */ public class ContentLanguage @@ -108,8 +108,8 @@ public ContentLanguage(String languageTag) { * Canonical encoding of the value of the header. * @return encoded body of header. */ - public StringBuilder encodeBody(StringBuilder buffer) { - return buffer.append(getLanguageTag()); + public String encodeBody() { + return this.getLanguageTag(); } /** get the languageTag field. diff --git a/src/gov/nist/javax/sip/header/ContentLength.java b/src/gov/nist/javax/sip/header/ContentLength.java index 94cd9f284..6dbc7bd3f 100644 --- a/src/gov/nist/javax/sip/header/ContentLength.java +++ b/src/gov/nist/javax/sip/header/ContentLength.java @@ -69,7 +69,7 @@ * *@author M. Ranganathan
    *@author Olivier Deruelle
    -*@version 1.2 $Revision: 1.8 $ $Date: 2010-05-06 14:07:46 $ +*@version 1.2 $Revision: 1.7 $ $Date: 2009-10-18 13:46:34 $ *@since 1.1 */ public class ContentLength @@ -83,7 +83,7 @@ public class ContentLength /** * contentLength field. */ - protected int contentLength = -1; + protected Integer contentLength; /** * Default constructor. @@ -97,7 +97,7 @@ public ContentLength() { */ public ContentLength(int length) { super(NAME); - this.contentLength = length; + this.contentLength = Integer.valueOf(length); } /** @@ -105,7 +105,7 @@ public ContentLength(int length) { * @return int */ public int getContentLength() { - return contentLength; + return contentLength.intValue(); } /** @@ -126,14 +126,14 @@ public void setContentLength(int contentLength) * @return String */ public String encodeBody() { - return encodeBody(new StringBuilder()).toString(); + return encodeBody(new StringBuffer()).toString(); } - protected StringBuilder encodeBody(StringBuilder buffer) { - if (contentLength < 0) + protected StringBuffer encodeBody(StringBuffer buffer) { + if (contentLength == null) buffer.append("0"); else - buffer.append(contentLength); + buffer.append(contentLength.toString()); return buffer; } diff --git a/src/gov/nist/javax/sip/header/ContentType.java b/src/gov/nist/javax/sip/header/ContentType.java index 6c19cbe42..4913e183a 100644 --- a/src/gov/nist/javax/sip/header/ContentType.java +++ b/src/gov/nist/javax/sip/header/ContentType.java @@ -57,7 +57,7 @@ * *@author M. Ranganathan
    *@author Olivier Deruelle
    -*@version 1.2 $Revision: 1.8 $ $Date: 2010-05-06 14:07:47 $ +*@version 1.2 $Revision: 1.7 $ $Date: 2009-07-17 18:57:29 $ *@since 1.1 * */ @@ -103,10 +103,10 @@ public int compareMediaRange(String media) { * @return String. */ public String encodeBody() { - return encodeBody(new StringBuilder()).toString(); + return encodeBody(new StringBuffer()).toString(); } - protected StringBuilder encodeBody(StringBuilder buffer) { + protected StringBuffer encodeBody(StringBuffer buffer) { mediaRange.encode(buffer); if (hasParameters()) { buffer.append(SEMICOLON); diff --git a/src/gov/nist/javax/sip/header/ErrorInfo.java b/src/gov/nist/javax/sip/header/ErrorInfo.java index 5c8a7d1e6..ca4d788d0 100755 --- a/src/gov/nist/javax/sip/header/ErrorInfo.java +++ b/src/gov/nist/javax/sip/header/ErrorInfo.java @@ -36,7 +36,7 @@ /** * ErrorInfo SIP Header. * - * @version 1.2 $Revision: 1.7 $ $Date: 2010-05-06 14:07:50 $ + * @version 1.2 $Revision: 1.6 $ $Date: 2009-07-17 18:57:30 $ * @since 1.1 * * @author M. Ranganathan
    @@ -74,16 +74,14 @@ public ErrorInfo(GenericURI errorInfo) { * Encode into canonical form. * @return String */ - public StringBuilder encodeBody(StringBuilder retval) { -// StringBuilder retval = - retval.append(LESS_THAN); - errorInfo.encode(retval); - retval.append(GREATER_THAN); + public String encodeBody() { + StringBuffer retval = + new StringBuffer(LESS_THAN).append(errorInfo.toString()).append( + GREATER_THAN); if (!parameters.isEmpty()) { - retval.append(SEMICOLON); - parameters.encode(retval); + retval.append(SEMICOLON).append(parameters.encode()); } - return retval; + return retval.toString(); } /** diff --git a/src/gov/nist/javax/sip/header/Event.java b/src/gov/nist/javax/sip/header/Event.java index 174c5bdd5..b2ebed40b 100755 --- a/src/gov/nist/javax/sip/header/Event.java +++ b/src/gov/nist/javax/sip/header/Event.java @@ -34,7 +34,7 @@ /** * Event SIP Header. * -*@version 1.2 $Revision: 1.8 $ $Date: 2010-05-06 14:07:48 $ +*@version 1.2 $Revision: 1.7 $ $Date: 2007-06-28 15:08:42 $ *@since 1.1 * *@author M. Ranganathan
    @@ -108,10 +108,10 @@ public String getEventId() { * @return String */ public String encodeBody() { - return encodeBody(new StringBuilder()).toString(); + return encodeBody(new StringBuffer()).toString(); } - protected StringBuilder encodeBody(StringBuilder buffer) { + protected StringBuffer encodeBody(StringBuffer buffer) { if (eventType != null) buffer.append(eventType); diff --git a/src/gov/nist/javax/sip/header/Expires.java b/src/gov/nist/javax/sip/header/Expires.java index f7fec3af2..1ae9f85cb 100644 --- a/src/gov/nist/javax/sip/header/Expires.java +++ b/src/gov/nist/javax/sip/header/Expires.java @@ -33,7 +33,7 @@ /** * Expires SIP Header. * - * @version 1.2 $Revision: 1.7 $ $Date: 2010-05-06 14:07:46 $ + * @version 1.2 $Revision: 1.6 $ $Date: 2009-07-17 18:57:30 $ * @since 1.1 * * @author M. Ranganathan
    @@ -64,10 +64,10 @@ public Expires() { * @return String */ public String encodeBody() { - return encodeBody(new StringBuilder()).toString(); + return encodeBody(new StringBuffer()).toString(); } - protected StringBuilder encodeBody(StringBuilder buffer) { + protected StringBuffer encodeBody(StringBuffer buffer) { return buffer.append(expires); } diff --git a/src/gov/nist/javax/sip/header/ExtensionHeaderImpl.java b/src/gov/nist/javax/sip/header/ExtensionHeaderImpl.java index a902b6a2a..d2b82a683 100755 --- a/src/gov/nist/javax/sip/header/ExtensionHeaderImpl.java +++ b/src/gov/nist/javax/sip/header/ExtensionHeaderImpl.java @@ -32,7 +32,7 @@ * A generic extension header for the stack. * The input text of the header gets recorded here. * - * @version 1.2 $Revision: 1.6 $ $Date: 2010-05-06 14:07:46 $ + * @version 1.2 $Revision: 1.5 $ $Date: 2009-07-17 18:57:30 $ * @since 1.1 * * @author M. Ranganathan
    @@ -91,7 +91,7 @@ public String getHeaderValue() { } catch (Exception ex) { return null; } - StringBuilder buffer = new StringBuilder(encodedHdr); + StringBuffer buffer = new StringBuffer(encodedHdr); while (buffer.length() > 0 && buffer.charAt(0) != ':') { buffer.deleteCharAt(0); } @@ -112,13 +112,6 @@ public String encode() { .append(NEWLINE) .toString(); } - - /** - * Return the canonical encoding of this header. - */ - public StringBuilder encodeBody(StringBuilder buffer) { - return buffer.append(this.encodeBody()); - } /** * Return just the body of this header encoded (leaving out the diff --git a/src/gov/nist/javax/sip/header/ExtensionHeaderList.java b/src/gov/nist/javax/sip/header/ExtensionHeaderList.java index 95cdbd391..c0c1b430f 100755 --- a/src/gov/nist/javax/sip/header/ExtensionHeaderList.java +++ b/src/gov/nist/javax/sip/header/ExtensionHeaderList.java @@ -35,7 +35,7 @@ /** * A generic extension header list. - * @version 1.2 $Revision: 1.9 $ $Date: 2010-05-06 14:07:49 $ + * @version 1.2 $Revision: 1.8 $ $Date: 2009-07-17 18:57:30 $ * @since 1.1 */ public class ExtensionHeaderList extends SIPHeaderList { @@ -60,7 +60,7 @@ public ExtensionHeaderList() { public String encode() { - StringBuilder retval = new StringBuilder(); + StringBuffer retval = new StringBuffer(); ListIterator it = this.listIterator(); while(it.hasNext()) { ExtensionHeaderImpl eh = (ExtensionHeaderImpl) it.next(); diff --git a/src/gov/nist/javax/sip/header/From.java b/src/gov/nist/javax/sip/header/From.java index dfddcaee8..99739af63 100755 --- a/src/gov/nist/javax/sip/header/From.java +++ b/src/gov/nist/javax/sip/header/From.java @@ -38,7 +38,7 @@ /** * From SIP Header. * - * @version 1.2 $Revision: 1.10 $ $Date: 2010-05-06 14:07:53 $ + * @version 1.2 $Revision: 1.9 $ $Date: 2009-07-17 18:57:31 $ * @since 1.1 * * @author M. Ranganathan
    @@ -74,10 +74,10 @@ public From(To to) { * @return String */ protected String encodeBody() { - return encodeBody(new StringBuilder()).toString(); + return encodeBody(new StringBuffer()).toString(); } - protected StringBuilder encodeBody(StringBuilder buffer) { + protected StringBuffer encodeBody(StringBuffer buffer) { if (address.getAddressType() == AddressImpl.ADDRESS_SPEC) { buffer.append(LESS_THAN); } diff --git a/src/gov/nist/javax/sip/header/HeaderFactoryImpl.java b/src/gov/nist/javax/sip/header/HeaderFactoryImpl.java index 601389c42..891a6c8d9 100755 --- a/src/gov/nist/javax/sip/header/HeaderFactoryImpl.java +++ b/src/gov/nist/javax/sip/header/HeaderFactoryImpl.java @@ -45,7 +45,7 @@ /** Implementation of the JAIN SIP HeaderFactory * -* @version 1.2 $Revision: 1.23 $ $Date: 2010-05-06 14:07:51 $ +* @version 1.2 $Revision: 1.22 $ $Date: 2010-01-12 18:58:48 $ * @since 1.1 * *@author M. Ranganathan
    @@ -1205,7 +1205,7 @@ public javax.sip.header.Header createHeader( if (headerName == null) throw new NullPointerException("header name is null"); String hdrText = - new StringBuilder() + new StringBuffer() .append(headerName) .append(":") .append(headerValue) @@ -1701,4 +1701,6 @@ public HeaderFactoryImpl() { + + } diff --git a/src/gov/nist/javax/sip/header/InReplyTo.java b/src/gov/nist/javax/sip/header/InReplyTo.java index 6231826de..ea241b32d 100644 --- a/src/gov/nist/javax/sip/header/InReplyTo.java +++ b/src/gov/nist/javax/sip/header/InReplyTo.java @@ -34,7 +34,7 @@ /** * InReplyTo SIP Header. * - * @version 1.2 $Revision: 1.7 $ $Date: 2010-05-06 14:07:54 $ + * @version 1.2 $Revision: 1.6 $ $Date: 2009-07-17 18:57:31 $ * * @author M. Ranganathan
    * @author Olivier Deruelle
    @@ -96,8 +96,8 @@ public String getCallId() { * Generate canonical form of the header. * @return String */ - public StringBuilder encodeBody(StringBuilder retval) { - return callId.encode(retval); + public String encodeBody() { + return callId.encode(); } public Object clone() { diff --git a/src/gov/nist/javax/sip/header/MaxForwards.java b/src/gov/nist/javax/sip/header/MaxForwards.java index bd321acb2..4c50e783e 100644 --- a/src/gov/nist/javax/sip/header/MaxForwards.java +++ b/src/gov/nist/javax/sip/header/MaxForwards.java @@ -33,7 +33,7 @@ /** * MaxForwards SIPHeader * - * @version 1.2 $Revision: 1.9 $ $Date: 2010-05-06 14:07:50 $ + * @version 1.2 $Revision: 1.8 $ $Date: 2009-07-17 18:57:32 $ * * @author M. Ranganathan
    * @author Olivier Deruelle
    @@ -85,10 +85,10 @@ public void setMaxForwards(int maxForwards) * */ public String encodeBody() { - return encodeBody(new StringBuilder()).toString(); + return encodeBody(new StringBuffer()).toString(); } - protected StringBuilder encodeBody(StringBuilder buffer) { + protected StringBuffer encodeBody(StringBuffer buffer) { return buffer.append(maxForwards); } diff --git a/src/gov/nist/javax/sip/header/MediaRange.java b/src/gov/nist/javax/sip/header/MediaRange.java index 5901b106c..0027bd0e3 100755 --- a/src/gov/nist/javax/sip/header/MediaRange.java +++ b/src/gov/nist/javax/sip/header/MediaRange.java @@ -36,7 +36,7 @@ * Media Range * @see Accept * @since 0.9 -* @version 1.2 $Revision: 1.7 $ $Date: 2010-05-06 14:07:55 $ +* @version 1.2 $Revision: 1.6 $ $Date: 2009-07-17 18:57:32 $ *
     * Revisions:
     *
    @@ -106,10 +106,10 @@ public void setSubtype(String s) {
          * @return String
          */
         public String encode() {
    -        return encode(new StringBuilder()).toString();
    +        return encode(new StringBuffer()).toString();
         }
     
    -    public StringBuilder encode(StringBuilder buffer) {
    +    public StringBuffer encode(StringBuffer buffer) {
             return buffer.append(type)
                     .append(SLASH)
                     .append(subtype);
    diff --git a/src/gov/nist/javax/sip/header/MimeVersion.java b/src/gov/nist/javax/sip/header/MimeVersion.java
    index bc5baf344..1191280a0 100644
    --- a/src/gov/nist/javax/sip/header/MimeVersion.java
    +++ b/src/gov/nist/javax/sip/header/MimeVersion.java
    @@ -34,7 +34,7 @@
     /**
      * MimeVersion SIP Header.
      *
    - * @version 1.2 $Revision: 1.7 $ $Date: 2010-05-06 14:07:52 $
    + * @version 1.2 $Revision: 1.6 $ $Date: 2009-10-18 13:46:35 $
      * @since 1.1
      *
      * @author M. Ranganathan   
    @@ -120,23 +120,15 @@ public void setMajorVersion(int majorVersion) * Return canonical form. * @return String */ - public StringBuilder encodeBody(StringBuilder buffer) { - return buffer.append(Integer.toString(majorVersion)) - .append(DOT) - .append(Integer.toString(minorVersion)); + public String encodeBody() { + return Integer.toString(majorVersion) + + DOT + + Integer.toString(minorVersion); } } /* * $Log: not supported by cvs2svn $ - * Revision 1.6 2009/10/18 13:46:35 deruelle_jean - * FindBugs Fixes (Category Performance Warnings) - * - * Issue number: - * Obtained from: - * Submitted by: Jean Deruelle - * Reviewed by: - * * Revision 1.5 2009/07/17 18:57:32 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * diff --git a/src/gov/nist/javax/sip/header/MinExpires.java b/src/gov/nist/javax/sip/header/MinExpires.java index 3371a3a13..fa035fe4e 100644 --- a/src/gov/nist/javax/sip/header/MinExpires.java +++ b/src/gov/nist/javax/sip/header/MinExpires.java @@ -34,7 +34,7 @@ /** * MinExpires SIP Header. * - * @version 1.2 $Revision: 1.7 $ $Date: 2010-05-06 14:07:55 $ + * @version 1.2 $Revision: 1.6 $ $Date: 2009-10-18 13:46:35 $ * @since 1.1 * * @author M. Ranganathan
    @@ -63,8 +63,8 @@ public MinExpires() { * Return canonical form. * @return String */ - public StringBuilder encodeBody(StringBuilder retval) { - return retval.append(Integer.toString(expires)); + public String encodeBody() { + return Integer.toString(expires); } /** @@ -99,14 +99,6 @@ public void setExpires(int expires) throws InvalidArgumentException { } /* * $Log: not supported by cvs2svn $ - * Revision 1.6 2009/10/18 13:46:35 deruelle_jean - * FindBugs Fixes (Category Performance Warnings) - * - * Issue number: - * Obtained from: - * Submitted by: Jean Deruelle - * Reviewed by: - * * Revision 1.5 2009/07/17 18:57:32 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * diff --git a/src/gov/nist/javax/sip/header/NameMap.java b/src/gov/nist/javax/sip/header/NameMap.java index 5d8815247..ce109197b 100755 --- a/src/gov/nist/javax/sip/header/NameMap.java +++ b/src/gov/nist/javax/sip/header/NameMap.java @@ -24,39 +24,20 @@ * */ package gov.nist.javax.sip.header; -import gov.nist.core.PackageNames; -import gov.nist.javax.sip.header.ims.PAccessNetworkInfo; -import gov.nist.javax.sip.header.ims.PAccessNetworkInfoHeader; -import gov.nist.javax.sip.header.ims.PAssertedIdentity; -import gov.nist.javax.sip.header.ims.PAssertedIdentityHeader; -import gov.nist.javax.sip.header.ims.PAssociatedURI; -import gov.nist.javax.sip.header.ims.PAssociatedURIHeader; -import gov.nist.javax.sip.header.ims.PCalledPartyID; -import gov.nist.javax.sip.header.ims.PCalledPartyIDHeader; -import gov.nist.javax.sip.header.ims.PChargingFunctionAddresses; -import gov.nist.javax.sip.header.ims.PChargingFunctionAddressesHeader; -import gov.nist.javax.sip.header.ims.PChargingVector; -import gov.nist.javax.sip.header.ims.PChargingVectorHeader; -import gov.nist.javax.sip.header.ims.PMediaAuthorization; -import gov.nist.javax.sip.header.ims.PMediaAuthorizationHeader; -import gov.nist.javax.sip.header.ims.PPreferredIdentity; -import gov.nist.javax.sip.header.ims.PVisitedNetworkID; -import gov.nist.javax.sip.header.ims.Path; -import gov.nist.javax.sip.header.ims.Privacy; -import gov.nist.javax.sip.header.ims.ServiceRoute; - -import java.util.HashMap; -import java.util.Map; +import gov.nist.core.*; +import gov.nist.javax.sip.header.ims.*; + +import java.util.Hashtable; /** * A mapping class that returns the SIPHeader for a given header name. * Add new classes to this map if you are implementing new header types if * you want some of the introspection based methods to work. - * @version 1.2 $Revision: 1.12 $ $Date: 2010-05-06 14:07:52 $ + * @version 1.2 $Revision: 1.11 $ $Date: 2009-07-17 18:57:32 $ * @since 1.1 */ public class NameMap implements SIPHeaderNames, PackageNames { - static Map nameMap; + static Hashtable nameMap; static { initializeNameMap(); } @@ -94,7 +75,7 @@ public static void addExtensionHeader( } private static void initializeNameMap() { - nameMap = new HashMap(63); + nameMap = new Hashtable(); putNameMap(MinExpires.NAME, MinExpires.class.getName()); // 1 putNameMap(ErrorInfo.NAME, ErrorInfo.class.getName()); // 2 diff --git a/src/gov/nist/javax/sip/header/Organization.java b/src/gov/nist/javax/sip/header/Organization.java index 8675dee19..0ee12973f 100644 --- a/src/gov/nist/javax/sip/header/Organization.java +++ b/src/gov/nist/javax/sip/header/Organization.java @@ -35,7 +35,7 @@ /** * Organization SIP Header. * - * @version 1.2 $Revision: 1.6 $ $Date: 2010-05-06 14:07:49 $ + * @version 1.2 $Revision: 1.5 $ $Date: 2009-07-17 18:57:32 $ * @since 1.1 * * @author M. Ranganathan
    @@ -59,8 +59,8 @@ public class Organization extends SIPHeader implements OrganizationHeader { * Return encoding of value of the header. * @return String */ - public StringBuilder encodeBody(StringBuilder buffer) { - return buffer.append(organization); + public String encodeBody() { + return organization; } /** @@ -92,9 +92,6 @@ public void setOrganization(String o) throws ParseException { } /* * $Log: not supported by cvs2svn $ - * Revision 1.5 2009/07/17 18:57:32 emcho - * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. - * * Revision 1.4 2006/07/13 09:01:15 mranga * Issue number: * Obtained from: diff --git a/src/gov/nist/javax/sip/header/ParametersExt.java b/src/gov/nist/javax/sip/header/ParametersExt.java deleted file mode 100644 index 6e6120fba..000000000 --- a/src/gov/nist/javax/sip/header/ParametersExt.java +++ /dev/null @@ -1,50 +0,0 @@ -/* -* Conditions Of Use -* -* This software was developed by employees of the National Institute of -* Standards and Technology (NIST), an agency of the Federal Government. -* Pursuant to title 15 Untied States Code Section 105, works of NIST -* employees are not subject to copyright protection in the United States -* and are considered to be in the public domain. As a result, a formal -* license is not needed to use the software. -* -* This software is provided by NIST as a service and is expressly -* provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED -* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT -* AND DATA ACCURACY. NIST does not warrant or make any representations -* regarding the use of the software or the results thereof, including but -* not limited to the correctness, accuracy, reliability or usefulness of -* the software. -* -* Permission to use this software is contingent upon your acceptance -* of the terms of this agreement. -* -*/ -package gov.nist.javax.sip.header; - -import javax.sip.header.Parameters; - -/** - * Extensions to the {@link Parameters} interface supported by the implementation and - * will be included in the next spec release. - * - * @author jean.deruelle@gmail.com - * @ since 2.0 - */ -public interface ParametersExt extends Parameters { - /** - * Returns the value of the named parameter, or null if it is not set. A - * zero-length String indicates flag parameter. - * - * The stack remove the undeeded quotes that are imposed by SIP encoding rules to ensure unambiguous parsing.
    - * The stripQuotes parameter can be used to get the original value as it has been received by the stack ie with the quotes - * - * @param name name of parameter to retrieve - * @param stripQuotes will return the value of the parameter as it has been received when the message came into the stack - * @return the value of specified parameter - * @since 2.0 - */ - public String getParameter(String name, boolean stripQuotes); - -} diff --git a/src/gov/nist/javax/sip/header/ParametersHeader.java b/src/gov/nist/javax/sip/header/ParametersHeader.java index b5b8d6576..1f8057fbe 100755 --- a/src/gov/nist/javax/sip/header/ParametersHeader.java +++ b/src/gov/nist/javax/sip/header/ParametersHeader.java @@ -45,12 +45,12 @@ * @author M. Ranganathan
    * * - * @version 1.2 $Revision: 1.17 $ $Date: 2010-07-28 08:39:26 $ + * @version 1.2 $Revision: 1.15 $ $Date: 2010-01-12 00:05:27 $ * */ public abstract class ParametersHeader extends SIPHeader - implements javax.sip.header.Parameters, ParametersExt, Serializable { + implements javax.sip.header.Parameters, Serializable { protected NameValueList parameters; protected DuplicateNameValueList duplicates; @@ -72,23 +72,18 @@ protected ParametersHeader(String hdrName, boolean sync) { this.duplicates = new DuplicateNameValueList(); } - /* - * (non-Javadoc) - * @see javax.sip.header.Parameters#getParameter(java.lang.String) + /** + * Returns the value of the named parameter, or null if it is not set. A + * zero-length String indicates flag parameter. + * + * @param name name of parameter to retrieve + * @return the value of specified parameter */ + public String getParameter(String name) { return this.parameters.getParameter(name); } - - /* - * (non-Javadoc) - * @see gov.nist.javax.sip.header.ParametersExt#getParameter(java.lang.String, boolean) - */ - public String getParameter(String name, boolean stripQuotes) { - return this.parameters.getParameter(name, stripQuotes); - - } /** * Return the parameter as an object (dont convert to string). @@ -616,6 +611,6 @@ protected final boolean equalParameters( Parameters other ) { // ----------- Abstract methods -------------- - protected abstract StringBuilder encodeBody(StringBuilder buffer); + protected abstract String encodeBody(); } diff --git a/src/gov/nist/javax/sip/header/Priority.java b/src/gov/nist/javax/sip/header/Priority.java index 3c0b0a530..24a608ce1 100644 --- a/src/gov/nist/javax/sip/header/Priority.java +++ b/src/gov/nist/javax/sip/header/Priority.java @@ -29,15 +29,13 @@ package gov.nist.javax.sip.header; import javax.sip.header.*; - -import java.nio.Buffer; import java.text.ParseException; /** * the Priority header. * * @author Olivier Deruelle
    - * @version 1.2 $Revision: 1.7 $ $Date: 2010-05-06 14:07:53 $ + * @version 1.2 $Revision: 1.6 $ $Date: 2009-07-17 18:57:33 $ * * * @@ -78,8 +76,8 @@ public Priority() { * Encode into canonical form. * @return String */ - public StringBuilder encodeBody(StringBuilder buffer) { - return buffer.append(priority); + public String encodeBody() { + return priority; } /** diff --git a/src/gov/nist/javax/sip/header/Protocol.java b/src/gov/nist/javax/sip/header/Protocol.java index 60f1cd75c..f46e8a139 100755 --- a/src/gov/nist/javax/sip/header/Protocol.java +++ b/src/gov/nist/javax/sip/header/Protocol.java @@ -33,7 +33,7 @@ /** * Protocol name and version. * - * @version 1.2 $Revision: 1.9 $ $Date: 2010-05-06 14:07:52 $ + * @version 1.2 $Revision: 1.8 $ $Date: 2009-07-17 18:57:33 $ * * @author M. Ranganathan
    * @@ -64,10 +64,10 @@ public class Protocol extends SIPObject { * @return String */ public String encode() { - return encode(new StringBuilder()).toString(); + return encode(new StringBuffer()).toString(); } - public StringBuilder encode(StringBuilder buffer) { + public StringBuffer encode(StringBuffer buffer) { buffer.append(protocolName.toUpperCase()) .append(SLASH) .append(protocolVersion) @@ -151,11 +151,8 @@ public Protocol() { } /* * $Log: not supported by cvs2svn $ - * Revision 1.8 2009/07/17 18:57:33 emcho - * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. - * * Revision 1.7 2007/02/12 15:19:23 belangery - * Changed the encode() and encodeBody() methods of SIP headers and basic classes to make them use the same StringBuilder instance during the encoding phase. + * Changed the encode() and encodeBody() methods of SIP headers and basic classes to make them use the same StringBuffer instance during the encoding phase. * * Revision 1.6 2006/07/13 09:01:24 mranga * Issue number: diff --git a/src/gov/nist/javax/sip/header/ProxyRequire.java b/src/gov/nist/javax/sip/header/ProxyRequire.java index e6388f09a..dfbee86bf 100644 --- a/src/gov/nist/javax/sip/header/ProxyRequire.java +++ b/src/gov/nist/javax/sip/header/ProxyRequire.java @@ -34,7 +34,7 @@ /** * ProxyRequire Header. * - * @version 1.2 $Revision: 1.6 $ $Date: 2010-05-06 14:07:47 $ + * @version 1.2 $Revision: 1.5 $ $Date: 2009-07-17 18:57:34 $ * * @author M. Ranganathan
    * @author Olivier Deruelle
    @@ -72,8 +72,8 @@ public ProxyRequire(String s) { * Encode in canonical form. * @return String */ - public StringBuilder encodeBody(StringBuilder buffer) { - return buffer.append(optionTag); + public String encodeBody() { + return optionTag; } /** @@ -101,9 +101,6 @@ public String getOptionTag() { } /* * $Log: not supported by cvs2svn $ - * Revision 1.5 2009/07/17 18:57:34 emcho - * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. - * * Revision 1.4 2006/07/13 09:01:26 mranga * Issue number: * Obtained from: diff --git a/src/gov/nist/javax/sip/header/RAck.java b/src/gov/nist/javax/sip/header/RAck.java index 5f8657d74..5e087503b 100755 --- a/src/gov/nist/javax/sip/header/RAck.java +++ b/src/gov/nist/javax/sip/header/RAck.java @@ -34,7 +34,7 @@ /** * RAck SIP Header implementation * - * @version 1.2 $Revision: 1.8 $ $Date: 2010-05-06 14:07:54 $ + * @version 1.2 $Revision: 1.7 $ $Date: 2009-07-17 18:57:34 $ * * @author M. Ranganathan
    * @@ -63,11 +63,11 @@ public RAck() { * headerValue. * */ - public StringBuilder encodeBody(StringBuilder buffer) { + protected String encodeBody() { // Bug reported by Bruno Konik - was encoded in // the wrong order. - return buffer.append(rSeqNumber).append(SP).append( - cSeqNumber).append(SP).append(method); + return new StringBuffer().append(rSeqNumber).append(SP).append( + cSeqNumber).append(SP).append(method).toString(); } diff --git a/src/gov/nist/javax/sip/header/RSeq.java b/src/gov/nist/javax/sip/header/RSeq.java index 4077b6ebc..53dc13589 100755 --- a/src/gov/nist/javax/sip/header/RSeq.java +++ b/src/gov/nist/javax/sip/header/RSeq.java @@ -29,7 +29,7 @@ /** * - * @version 1.2 $Revision: 1.8 $ $Date: 2010-05-06 14:07:55 $ + * @version 1.2 $Revision: 1.7 $ $Date: 2009-10-18 13:46:35 $ * * @author M. Ranganathan
    * @@ -59,8 +59,8 @@ public int getSequenceNumber() { /** Encode the body of this header (the stuff that follows headerName). * A.K.A headerValue. */ - public StringBuilder encodeBody(StringBuilder retval) { - return retval.append(Long.toString(this.sequenceNumber)); + protected String encodeBody() { + return Long.toString(this.sequenceNumber); } public long getSeqNumber() { diff --git a/src/gov/nist/javax/sip/header/Reason.java b/src/gov/nist/javax/sip/header/Reason.java index 7d4273f08..efe0dc42c 100755 --- a/src/gov/nist/javax/sip/header/Reason.java +++ b/src/gov/nist/javax/sip/header/Reason.java @@ -45,7 +45,7 @@ /** * Definition of the Reason SIP Header. * - * @version 1.2 $Revision: 1.9 $ $Date: 2010-05-06 14:07:53 $ + * @version 1.2 $Revision: 1.8 $ $Date: 2009-10-18 13:46:34 $ * * @author M. Ranganathan
    * @@ -139,26 +139,17 @@ public String getName() { * Encode the body of this header (the stuff that follows headerName). * A.K.A headerValue. */ - public StringBuilder encodeBody(StringBuilder buffer) { - buffer.append(protocol); - if (parameters != null && !parameters.isEmpty()) { - buffer = buffer.append(SEMICOLON); - buffer = parameters.encode(buffer); - } - return buffer; + protected String encodeBody() { + StringBuffer s = new StringBuffer(); + s.append(protocol); + if (parameters != null && !parameters.isEmpty()) + s.append(SEMICOLON).append(parameters.encode()); + return s.toString(); } } /* * $Log: not supported by cvs2svn $ - * Revision 1.8 2009/10/18 13:46:34 deruelle_jean - * FindBugs Fixes (Category Performance Warnings) - * - * Issue number: - * Obtained from: - * Submitted by: Jean Deruelle - * Reviewed by: - * * Revision 1.7 2009/07/17 18:57:35 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * diff --git a/src/gov/nist/javax/sip/header/RecordRoute.java b/src/gov/nist/javax/sip/header/RecordRoute.java index 700b77bb8..4b969bcc8 100644 --- a/src/gov/nist/javax/sip/header/RecordRoute.java +++ b/src/gov/nist/javax/sip/header/RecordRoute.java @@ -34,7 +34,7 @@ * The Request-Route header is added to a request by any proxy that insists on * being in the path of subsequent requests for the same call leg. * - *@version 1.2 $Revision: 1.7 $ $Date: 2010-05-06 14:07:48 $ + *@version 1.2 $Revision: 1.6 $ $Date: 2009-07-17 18:57:35 $ * *@author M. Ranganathan
    * @@ -71,10 +71,10 @@ public RecordRoute() { *@return String containing the canonicaly encoded header. */ public String encodeBody() { - return encodeBody(new StringBuilder()).toString(); + return encodeBody(new StringBuffer()).toString(); } - protected StringBuilder encodeBody(StringBuilder buffer) { + protected StringBuffer encodeBody(StringBuffer buffer) { if (address.getAddressType() == AddressImpl.ADDRESS_SPEC) { buffer.append(LESS_THAN); } diff --git a/src/gov/nist/javax/sip/header/ReferTo.java b/src/gov/nist/javax/sip/header/ReferTo.java index f7dd032c1..10ba6b793 100755 --- a/src/gov/nist/javax/sip/header/ReferTo.java +++ b/src/gov/nist/javax/sip/header/ReferTo.java @@ -35,7 +35,7 @@ /** * ReferTo SIP Header. * - * @version 1.2 $Revision: 1.7 $ $Date: 2010-05-06 14:07:50 $ + * @version 1.2 $Revision: 1.6 $ $Date: 2009-07-17 18:57:35 $ * * @author M. Ranganathan
    * @author Olivier Deruelle
    @@ -62,29 +62,26 @@ public ReferTo() { * Encode the header content into a String. * @return String */ - public StringBuilder encodeBody(StringBuilder retval) { + protected String encodeBody() { if (address == null) - return null; + return null; + String retval = ""; if (address.getAddressType() == AddressImpl.ADDRESS_SPEC) { - retval.append(LESS_THAN); + retval += LESS_THAN; } - address.encode(retval); + retval += address.encode(); if (address.getAddressType() == AddressImpl.ADDRESS_SPEC) { - retval.append(GREATER_THAN); + retval += GREATER_THAN; } if (!parameters.isEmpty()) { - retval.append(SEMICOLON); - parameters.encode(retval); + retval += SEMICOLON + parameters.encode(); } return retval; } } /* * $Log: not supported by cvs2svn $ - * Revision 1.6 2009/07/17 18:57:35 emcho - * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. - * * Revision 1.5 2006/07/13 09:01:40 mranga * Issue number: * Obtained from: diff --git a/src/gov/nist/javax/sip/header/ReplyTo.java b/src/gov/nist/javax/sip/header/ReplyTo.java index 7b02749fc..0d1a11ed3 100644 --- a/src/gov/nist/javax/sip/header/ReplyTo.java +++ b/src/gov/nist/javax/sip/header/ReplyTo.java @@ -30,13 +30,12 @@ import gov.nist.core.*; import gov.nist.javax.sip.address.*; - import javax.sip.header.*; /** * ReplyTo Header. * - * @version 1.2 $Revision: 1.6 $ $Date: 2010-05-06 14:07:51 $ + * @version 1.2 $Revision: 1.5 $ $Date: 2009-07-17 18:57:36 $ * * @author M. Ranganathan
    * @author Olivier Deruelle
    @@ -74,28 +73,26 @@ public ReplyTo(AddressImpl address) { * @return String */ public String encode() { - return headerName + COLON + SP + encodeBody(new StringBuilder()).toString() + NEWLINE; + return headerName + COLON + SP + encodeBody() + NEWLINE; } /** * Encode the header content into a String. * @return String */ - public StringBuilder encodeBody(StringBuilder retval) { -// String retval = ""; - if (address.getAddressType() == AddressImpl.ADDRESS_SPEC) { - retval.append(LESS_THAN); + public String encodeBody() { + String retval = ""; + if (address.getAddressType() == AddressImpl.ADDRESS_SPEC) { + retval += LESS_THAN; } - address.encode(retval); + retval += address.encode(); if (address.getAddressType() == AddressImpl.ADDRESS_SPEC) { - retval.append(GREATER_THAN); + retval += GREATER_THAN; } - if (!parameters.isEmpty()) { - retval.append(SEMICOLON); - parameters.encode(retval); + retval += SEMICOLON + parameters.encode(); } - return retval; + return retval; } /** @@ -116,9 +113,6 @@ public String getDisplayName() { } /* * $Log: not supported by cvs2svn $ - * Revision 1.5 2009/07/17 18:57:36 emcho - * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. - * * Revision 1.4 2006/07/13 09:01:31 mranga * Issue number: * Obtained from: diff --git a/src/gov/nist/javax/sip/header/RequestLine.java b/src/gov/nist/javax/sip/header/RequestLine.java index a723ab0fa..e641d4c19 100755 --- a/src/gov/nist/javax/sip/header/RequestLine.java +++ b/src/gov/nist/javax/sip/header/RequestLine.java @@ -35,7 +35,7 @@ /** * RequestLine of SIP Request. * - * @version 1.2 $Revision: 1.9 $ $Date: 2010-05-06 14:07:49 $ + * @version 1.2 $Revision: 1.8 $ $Date: 2009-09-15 02:55:27 $ * @author M. Ranganathan */ public class RequestLine extends SIPObject implements SipRequestLine { @@ -70,10 +70,10 @@ public RequestLine() { * @return requestLine encoded as a string. */ public String encode() { - return encode(new StringBuilder()).toString(); + return encode(new StringBuffer()).toString(); } - public StringBuilder encode(StringBuilder buffer) { + public StringBuffer encode(StringBuffer buffer) { if (method != null) { buffer.append(method); buffer.append(SP); @@ -213,17 +213,11 @@ public Object clone() { } /* * $Log: not supported by cvs2svn $ - * Revision 1.8 2009/09/15 02:55:27 mranga - * Issue number: 222 - * Add HeaderFactoryExt.createStatusLine(String) and HeaderFactoryExt.createRequestLine(String) - * Allows users to easily parse SipFrag bodies (for example NOTIFY bodies - * during call transfer). - * * Revision 1.7 2009/07/17 18:57:36 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.6 2007/02/12 15:19:23 belangery - * Changed the encode() and encodeBody() methods of SIP headers and basic classes to make them use the same StringBuilder instance during the encoding phase. + * Changed the encode() and encodeBody() methods of SIP headers and basic classes to make them use the same StringBuffer instance during the encoding phase. * * Revision 1.5 2006/07/13 09:01:26 mranga * Issue number: diff --git a/src/gov/nist/javax/sip/header/Require.java b/src/gov/nist/javax/sip/header/Require.java index 3727afcba..cd8be1f91 100644 --- a/src/gov/nist/javax/sip/header/Require.java +++ b/src/gov/nist/javax/sip/header/Require.java @@ -34,7 +34,7 @@ /** * Require SIP Header. * - * @version 1.2 $Revision: 1.6 $ $Date: 2010-05-06 14:07:48 $ + * @version 1.2 $Revision: 1.5 $ $Date: 2009-07-17 18:57:36 $ * * @author M. Ranganathan
    * @author Olivier Deruelle
    @@ -70,8 +70,8 @@ public Require(String s) { * Encode in canonical form. * @return String */ - public StringBuilder encodeBody(StringBuilder retval) { - return retval.append(optionTag); + public String encodeBody() { + return optionTag; } /** @@ -101,9 +101,6 @@ public String getOptionTag() { } /* * $Log: not supported by cvs2svn $ - * Revision 1.5 2009/07/17 18:57:36 emcho - * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. - * * Revision 1.4 2006/07/13 09:01:22 mranga * Issue number: * Obtained from: diff --git a/src/gov/nist/javax/sip/header/RetryAfter.java b/src/gov/nist/javax/sip/header/RetryAfter.java index 009c8a6a6..09f365d65 100755 --- a/src/gov/nist/javax/sip/header/RetryAfter.java +++ b/src/gov/nist/javax/sip/header/RetryAfter.java @@ -36,7 +36,7 @@ /** * Retry-After SIP Header. * - * @version 1.2 $Revision: 1.10 $ $Date: 2010-05-06 14:07:47 $ + * @version 1.2 $Revision: 1.9 $ $Date: 2009-11-04 17:35:55 $ * * @author M. Ranganathan
    * @author Olivier Deruelle
    @@ -71,21 +71,20 @@ public RetryAfter() { /** Encode body of this into cannonical form. * @return encoded body */ - public StringBuilder encodeBody(StringBuilder retval) { -// StringBuilder s = new StringBuilder(); + public String encodeBody() { + StringBuffer s = new StringBuffer(); if (retryAfter != null) - retval.append(retryAfter); + s.append(retryAfter); if (comment != null) - retval.append(SP + LPAREN + comment + RPAREN); + s.append(SP + LPAREN + comment + RPAREN); if (!parameters.isEmpty()) { - retval.append(SEMICOLON); - parameters.encode(retval); + s.append(SEMICOLON + parameters.encode()); } - return retval; + return s.toString(); } /** Boolean function diff --git a/src/gov/nist/javax/sip/header/Route.java b/src/gov/nist/javax/sip/header/Route.java index 194cead96..2f4301671 100755 --- a/src/gov/nist/javax/sip/header/Route.java +++ b/src/gov/nist/javax/sip/header/Route.java @@ -35,7 +35,7 @@ /** * Route SIPHeader Object * - * @version 1.2 $Revision: 1.7 $ $Date: 2010-05-06 14:07:52 $ + * @version 1.2 $Revision: 1.6 $ $Date: 2009-07-17 18:57:36 $ * * @author M. Ranganathan
    * @@ -84,10 +84,10 @@ public int hashCode() { *@return a canonical encoding of the header. */ public String encodeBody() { - return encodeBody(new StringBuilder()).toString(); + return encodeBody(new StringBuffer()).toString(); } - protected StringBuilder encodeBody(StringBuilder buffer) { + protected StringBuffer encodeBody(StringBuffer buffer) { boolean addrFlag = address.getAddressType() == AddressImpl.NAME_ADDR; if (!addrFlag) { buffer.append('<'); diff --git a/src/gov/nist/javax/sip/header/SIPDate.java b/src/gov/nist/javax/sip/header/SIPDate.java index 625ff928e..c47f80c19 100755 --- a/src/gov/nist/javax/sip/header/SIPDate.java +++ b/src/gov/nist/javax/sip/header/SIPDate.java @@ -54,7 +54,7 @@ * Date: Tue, 15 Nov 1994 08:12:31 GMT *
    * -*@version 1.2 $Revision: 1.10 $ $Date: 2010-05-06 14:07:53 $ +*@version 1.2 $Revision: 1.9 $ $Date: 2009-10-18 13:46:33 $ * *@author M. Ranganathan
    * @@ -252,7 +252,7 @@ public SIPDate(long timeMillis) { * Get canonical string representation. * @return String */ - public StringBuilder encode(StringBuilder encoding) { + public String encode() { String dayString; if (day < 10) { @@ -277,24 +277,28 @@ public StringBuilder encode(StringBuilder encoding) { secondString = "0" + second; } else secondString = "" + second; - + + String encoding = ""; + if (sipWkDay != null) - encoding .append(sipWkDay).append(Separators.COMMA).append(Separators.SP); + encoding += sipWkDay + Separators.COMMA + Separators.SP; - encoding.append(dayString).append(Separators.SP); + encoding += dayString + Separators.SP; if (sipMonth != null) - encoding.append(sipMonth).append(Separators.SP); - - return encoding.append(year) - .append(Separators.SP) - .append(hourString) - .append(Separators.COLON) - .append(minuteString) - .append(Separators.COLON) - .append(secondString) - .append(Separators.SP) - .append(GMT); + encoding += sipMonth + Separators.SP; + + encoding += year + + Separators.SP + + hourString + + Separators.COLON + + minuteString + + Separators.COLON + + secondString + + Separators.SP + + GMT; + + return encoding; } /** @@ -524,14 +528,6 @@ public Object clone() { } /* * $Log: not supported by cvs2svn $ - * Revision 1.9 2009/10/18 13:46:33 deruelle_jean - * FindBugs Fixes (Category Performance Warnings) - * - * Issue number: - * Obtained from: - * Submitted by: Jean Deruelle - * Reviewed by: - * * Revision 1.8 2009/07/17 18:57:37 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * diff --git a/src/gov/nist/javax/sip/header/SIPDateHeader.java b/src/gov/nist/javax/sip/header/SIPDateHeader.java index 4a9d262b5..45a15eab6 100644 --- a/src/gov/nist/javax/sip/header/SIPDateHeader.java +++ b/src/gov/nist/javax/sip/header/SIPDateHeader.java @@ -34,7 +34,7 @@ /** * Date Header. * -*@version 1.2 $Revision: 1.7 $ $Date: 2010-05-06 14:07:46 $ +*@version 1.2 $Revision: 1.6 $ $Date: 2009-07-17 18:57:37 $ * *@author M. Ranganathan
    *@author Olivier Deruelle
    @@ -60,8 +60,8 @@ public SIPDateHeader() { /** Encode the header into a String. * @return String */ - public StringBuilder encodeBody(StringBuilder retval) { - return date.encode(retval); + public String encodeBody() { + return date.encode(); } /** @@ -104,9 +104,6 @@ public Object clone() { } /* * $Log: not supported by cvs2svn $ - * Revision 1.6 2009/07/17 18:57:37 emcho - * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. - * * Revision 1.5 2006/07/13 09:01:23 mranga * Issue number: * Obtained from: diff --git a/src/gov/nist/javax/sip/header/SIPETag.java b/src/gov/nist/javax/sip/header/SIPETag.java index 64d7a404e..881cb932f 100644 --- a/src/gov/nist/javax/sip/header/SIPETag.java +++ b/src/gov/nist/javax/sip/header/SIPETag.java @@ -33,7 +33,7 @@ * the SIP-ETag header. * * @author Jeroen van Bemmel
    - * @version 1.2 $Revision: 1.4 $ $Date: 2010-05-06 14:07:46 $ + * @version 1.2 $Revision: 1.3 $ $Date: 2009-07-17 18:57:37 $ * @since 1.2 */ public class SIPETag extends SIPHeader implements SIPETagHeader , ExtensionHeader{ @@ -64,8 +64,8 @@ public SIPETag( String tag ) throws ParseException { * Encode into canonical form. * @return String */ - public StringBuilder encodeBody(StringBuilder retval) { - return retval.append(entityTag); + public String encodeBody() { + return entityTag; } /** diff --git a/src/gov/nist/javax/sip/header/SIPHeader.java b/src/gov/nist/javax/sip/header/SIPHeader.java index 789b17a62..3ce052f52 100755 --- a/src/gov/nist/javax/sip/header/SIPHeader.java +++ b/src/gov/nist/javax/sip/header/SIPHeader.java @@ -32,7 +32,7 @@ * Root class from which all SIPHeader objects are subclassed. * * @author M. Ranganathan
    - * @version 1.2 $Revision: 1.9 $ $Date: 2010-05-06 14:07:52 $ + * @version 1.2 $Revision: 1.8 $ $Date: 2010-03-06 04:12:11 $ * * */ @@ -51,7 +51,7 @@ public abstract class SIPHeader * @param hname String to set */ protected SIPHeader(String hname) { - headerName = hname.intern(); + headerName = hname; } /** Default constructor @@ -89,7 +89,7 @@ public void setHeaderName(String hdrname) { * the headerName: */ public String getHeaderValue() { - return encodeBody(new StringBuilder()).toString(); + return encodeBody(); } /** Return false if this is not a header list @@ -103,10 +103,10 @@ public boolean isHeaderList() { /** Encode this header into canonical form. */ public String encode() { - return encode(new StringBuilder()).toString(); + return encode(new StringBuffer()).toString(); } - public StringBuilder encode(StringBuilder buffer) { + public StringBuffer encode(StringBuffer buffer) { buffer.append(this.headerName).append(COLON).append(SP); this.encodeBody(buffer); buffer.append(NEWLINE); @@ -116,15 +116,14 @@ public StringBuilder encode(StringBuilder buffer) { /** Encode the body of this header (the stuff that follows headerName). * A.K.A headerValue. */ - protected abstract StringBuilder encodeBody(StringBuilder buffer); - - -// /** Encode the body of this header in the given buffer. -// * Default implementation calls encodeBody(); -// */ -// protected StringBuilder encodeBody(StringBuilder buffer) { -// return buffer.append(encodeBody()); -// } + protected abstract String encodeBody(); + + /** Encode the body of this header in the given buffer. + * Default implementation calls encodeBody(); + */ + protected StringBuffer encodeBody(StringBuffer buffer) { + return buffer.append(encodeBody()); + } /** Alias for getHeaderValue. */ diff --git a/src/gov/nist/javax/sip/header/SIPHeaderList.java b/src/gov/nist/javax/sip/header/SIPHeaderList.java index edab701a8..d11506ac1 100755 --- a/src/gov/nist/javax/sip/header/SIPHeaderList.java +++ b/src/gov/nist/javax/sip/header/SIPHeaderList.java @@ -44,7 +44,7 @@ * list are of the same class). We use this for building type homogeneous lists * of SIPObjects that appear in SIPHeaders * - * @version 1.2 $Revision: 1.16 $ $Date: 2005/10/09 18:47:53 + * @version 1.2 $Revision: 1.15 $ $Date: 2005/10/09 18:47:53 */ public abstract class SIPHeaderList extends SIPHeader implements java.util.List, Header { @@ -148,10 +148,10 @@ public void concatenate(SIPHeaderList other, boolean topFlag) * (Contains string append of each encoded header). */ public String encode() { - return encode(new StringBuilder()).toString(); + return encode(new StringBuffer()).toString(); } - public StringBuilder encode(StringBuilder buffer) { + public StringBuffer encode(StringBuffer buffer) { if (hlist.isEmpty()) { buffer.append(headerName).append(':').append(Separators.NEWLINE); } @@ -493,10 +493,10 @@ public boolean isHeaderList() { * is protected. */ protected String encodeBody() { - return encodeBody(new StringBuilder()).toString(); + return encodeBody(new StringBuffer()).toString(); } - protected StringBuilder encodeBody(StringBuilder buffer) { + protected StringBuffer encodeBody(StringBuffer buffer) { ListIterator iterator = this.listIterator(); while (true) { SIPHeader sipHeader = (SIPHeader) iterator.next(); diff --git a/src/gov/nist/javax/sip/header/SIPHeaderNamesCache.java b/src/gov/nist/javax/sip/header/SIPHeaderNamesCache.java index 05061fb1d..19d33b338 100644 --- a/src/gov/nist/javax/sip/header/SIPHeaderNamesCache.java +++ b/src/gov/nist/javax/sip/header/SIPHeaderNamesCache.java @@ -30,7 +30,7 @@ public abstract class SIPHeaderNamesCache public static String toLowerCase(String headerName) { String lowerCase = (String) lowercaseMap.get(headerName); if (lowerCase == null) { - return headerName.toLowerCase().intern(); + return headerName.toLowerCase(); } else { return lowerCase; diff --git a/src/gov/nist/javax/sip/header/SIPIfMatch.java b/src/gov/nist/javax/sip/header/SIPIfMatch.java index 472b9ad71..523dae3b1 100644 --- a/src/gov/nist/javax/sip/header/SIPIfMatch.java +++ b/src/gov/nist/javax/sip/header/SIPIfMatch.java @@ -33,7 +33,7 @@ * the SIP-If-Match header. * * @author Jeroen van Bemmel
    - * @version 1.2 $Revision: 1.4 $ $Date: 2010-05-06 14:07:50 $ + * @version 1.2 $Revision: 1.3 $ $Date: 2009-07-17 18:57:38 $ * @since 1.2 */ public class SIPIfMatch extends SIPHeader implements SIPIfMatchHeader,ExtensionHeader { @@ -63,8 +63,8 @@ public SIPIfMatch(String etag) throws ParseException { * Encode into canonical form. * @return String */ - public StringBuilder encodeBody(StringBuilder retval) { - return retval.append(entityTag); + public String encodeBody() { + return entityTag; } /** diff --git a/src/gov/nist/javax/sip/header/SIPObject.java b/src/gov/nist/javax/sip/header/SIPObject.java index bbe415dfe..49af81baf 100755 --- a/src/gov/nist/javax/sip/header/SIPObject.java +++ b/src/gov/nist/javax/sip/header/SIPObject.java @@ -39,7 +39,7 @@ * specializes the gov.nist.sip.header.GenericObject class for SIPHeader * related objects. * - * @version 1.2 $Revision: 1.11 $ $Date: 2010-05-06 14:07:48 $ + * @version 1.2 $Revision: 1.10 $ $Date: 2009-07-17 18:57:38 $ * * @author M. Ranganathan
    * @@ -68,10 +68,10 @@ public void dbgPrint() { */ public abstract String encode(); - /** Encode the header into the given StringBuilder. + /** Encode the header into the given StringBuffer. * Default implemation calls encode(). */ - public StringBuilder encode(StringBuilder buffer) { + public StringBuffer encode(StringBuffer buffer) { return buffer.append(encode()); } diff --git a/src/gov/nist/javax/sip/header/Server.java b/src/gov/nist/javax/sip/header/Server.java index d6ca1409c..d04fd3bf5 100644 --- a/src/gov/nist/javax/sip/header/Server.java +++ b/src/gov/nist/javax/sip/header/Server.java @@ -36,7 +36,7 @@ /** * Supported SIP Header. * - * @version 1.2 $Revision: 1.6 $ $Date: 2010-05-06 14:07:49 $ + * @version 1.2 $Revision: 1.5 $ $Date: 2009-07-17 18:57:38 $ * * @author M. Ranganathan
    * @author Olivier Deruelle
    @@ -58,8 +58,8 @@ public class Server extends SIPHeader implements ServerHeader { * Return canonical form. * @return String */ - private StringBuilder encodeProduct(StringBuilder tokens) { -// StringBuilder tokens = new StringBuilder(); + private String encodeProduct() { + StringBuffer tokens = new StringBuffer(); ListIterator it = productTokens.listIterator(); while (it.hasNext()) { @@ -69,7 +69,7 @@ private StringBuilder encodeProduct(StringBuilder tokens) { else break; } - return tokens; + return tokens.toString(); } /** set the productToken field @@ -90,8 +90,8 @@ public Server() { /** Encode only the body of this header. *@return encoded value of the header. */ - public StringBuilder encodeBody(StringBuilder retval) { - return encodeProduct(retval); + public String encodeBody() { + return encodeProduct(); } /** @@ -124,9 +124,6 @@ public void setProduct(List product) throws ParseException { } /* * $Log: not supported by cvs2svn $ - * Revision 1.5 2009/07/17 18:57:38 emcho - * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. - * * Revision 1.4 2006/07/13 09:01:04 mranga * Issue number: * Obtained from: diff --git a/src/gov/nist/javax/sip/header/Subject.java b/src/gov/nist/javax/sip/header/Subject.java index caa80e893..f62ea06c3 100644 --- a/src/gov/nist/javax/sip/header/Subject.java +++ b/src/gov/nist/javax/sip/header/Subject.java @@ -37,7 +37,7 @@ /** * Supported SIP Header. * - * @version 1.2 $Revision: 1.6 $ $Date: 2010-05-06 14:07:52 $ + * @version 1.2 $Revision: 1.5 $ $Date: 2009-07-17 18:57:39 $ * * @author M. Ranganathan
    * @author Olivier Deruelle
    @@ -65,11 +65,11 @@ public Subject() { * Generate the canonical form. * @return String. */ - public StringBuilder encodeBody(StringBuilder retval) { + public String encodeBody() { if (subject != null) { - return retval.append(subject); + return subject; } else { - return retval.append(""); + return ""; } } @@ -101,9 +101,6 @@ public String getSubject() { } /* * $Log: not supported by cvs2svn $ - * Revision 1.5 2009/07/17 18:57:39 emcho - * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. - * * Revision 1.4 2006/07/13 09:01:21 mranga * Issue number: * Obtained from: diff --git a/src/gov/nist/javax/sip/header/SubscriptionState.java b/src/gov/nist/javax/sip/header/SubscriptionState.java index 75155e2d9..cae54fb84 100644 --- a/src/gov/nist/javax/sip/header/SubscriptionState.java +++ b/src/gov/nist/javax/sip/header/SubscriptionState.java @@ -35,7 +35,7 @@ /** *SubscriptionState header * - * @version 1.2 $Revision: 1.8 $ $Date: 2010-05-06 14:07:47 $ + * @version 1.2 $Revision: 1.7 $ $Date: 2009-07-17 18:57:39 $ * * @author Olivier Deruelle
    * @@ -164,10 +164,10 @@ public void setState(String state) throws ParseException { * @return the string encoded header body. */ public String encodeBody() { - return encodeBody(new StringBuilder()).toString(); + return encodeBody(new StringBuffer()).toString(); } - protected StringBuilder encodeBody(StringBuilder buffer) { + protected StringBuffer encodeBody(StringBuffer buffer) { if (state != null) buffer.append(state); if (reasonCode != null) diff --git a/src/gov/nist/javax/sip/header/Supported.java b/src/gov/nist/javax/sip/header/Supported.java index d4998f395..ea1187b87 100644 --- a/src/gov/nist/javax/sip/header/Supported.java +++ b/src/gov/nist/javax/sip/header/Supported.java @@ -34,7 +34,7 @@ /** * Supported SIP Header. * - * @version 1.2 $Revision: 1.6 $ $Date: 2010-05-06 14:07:51 $ + * @version 1.2 $Revision: 1.5 $ $Date: 2009-07-17 18:57:39 $ * * @author M. Ranganathan
    * @author Olivier Deruelle
    @@ -85,8 +85,8 @@ public String encode() { * Just the encoded body of the header. * @return the string encoded header body. */ - public StringBuilder encodeBody(StringBuilder retval) { - return optionTag != null ? retval.append(optionTag) : retval.append(""); + public String encodeBody() { + return optionTag != null ? optionTag : ""; } /** @@ -116,9 +116,6 @@ public String getOptionTag() { } /* * $Log: not supported by cvs2svn $ - * Revision 1.5 2009/07/17 18:57:39 emcho - * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. - * * Revision 1.4 2006/07/13 09:01:27 mranga * Issue number: * Obtained from: diff --git a/src/gov/nist/javax/sip/header/TimeStamp.java b/src/gov/nist/javax/sip/header/TimeStamp.java index dcb782e61..8053d12a8 100644 --- a/src/gov/nist/javax/sip/header/TimeStamp.java +++ b/src/gov/nist/javax/sip/header/TimeStamp.java @@ -35,7 +35,7 @@ /** * TimeStamp SIP Header. * - * @version 1.2 $Revision: 1.8 $ $Date: 2010-05-06 14:07:46 $ + * @version 1.2 $Revision: 1.7 $ $Date: 2009-10-18 13:46:31 $ * * @author M. Ranganathan
    * @author Olivier Deruelle
    @@ -95,17 +95,17 @@ else if (delay != -1) * * @return String */ - public StringBuilder encodeBody(StringBuilder retval) { -// StringBuilder retval = new StringBuilder(); + public String encodeBody() { + StringBuffer retval = new StringBuffer(); String s1 = getTimeStampAsString(); String s2 = getDelayAsString(); if (s1.equals("") && s2.equals("")) - return retval.append(""); + return ""; if (!s1.equals("")) retval.append(s1); if (!s2.equals("")) retval.append(" ").append(s2); - return retval; + return retval.toString(); } diff --git a/src/gov/nist/javax/sip/header/To.java b/src/gov/nist/javax/sip/header/To.java index ea98575c3..4837d996f 100755 --- a/src/gov/nist/javax/sip/header/To.java +++ b/src/gov/nist/javax/sip/header/To.java @@ -38,7 +38,7 @@ /** * To SIP Header. * - * @version 1.2 $Revision: 1.12 $ $Date: 2010-05-06 14:07:51 $ + * @version 1.2 $Revision: 1.11 $ $Date: 2009-07-17 18:57:39 $ * * @author M. Ranganathan
    * @author Olivier Deruelle
    @@ -87,10 +87,10 @@ public String encode() { * @return String */ protected String encodeBody() { - return encodeBody(new StringBuilder()).toString(); + return encodeBody(new StringBuffer()).toString(); } - protected StringBuilder encodeBody(StringBuilder buffer) { + protected StringBuffer encodeBody(StringBuffer buffer) { if (address != null) { if (address.getAddressType() == AddressImpl.ADDRESS_SPEC) { buffer.append(LESS_THAN); diff --git a/src/gov/nist/javax/sip/header/Unsupported.java b/src/gov/nist/javax/sip/header/Unsupported.java index c7f83546c..997cddfbb 100755 --- a/src/gov/nist/javax/sip/header/Unsupported.java +++ b/src/gov/nist/javax/sip/header/Unsupported.java @@ -33,7 +33,7 @@ /** * the Unsupported header. * - * @version 1.2 $Revision: 1.6 $ $Date: 2010-05-06 14:07:49 $ + * @version 1.2 $Revision: 1.5 $ $Date: 2009-07-17 18:57:40 $ * @author Olivier Deruelle
    * * @@ -69,8 +69,8 @@ public Unsupported(String ot) { * Return a canonical value. * @return String. */ - public StringBuilder encodeBody(StringBuilder retval) { - return retval.append(optionTag); + public String encodeBody() { + return optionTag; } /** get the option tag field @@ -94,9 +94,6 @@ public void setOptionTag(String o) throws ParseException { } /* * $Log: not supported by cvs2svn $ - * Revision 1.5 2009/07/17 18:57:40 emcho - * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. - * * Revision 1.4 2006/07/13 09:01:34 mranga * Issue number: * Obtained from: diff --git a/src/gov/nist/javax/sip/header/UserAgent.java b/src/gov/nist/javax/sip/header/UserAgent.java index 71ce64603..de02a8b96 100644 --- a/src/gov/nist/javax/sip/header/UserAgent.java +++ b/src/gov/nist/javax/sip/header/UserAgent.java @@ -36,7 +36,7 @@ * the UserAgent SIPObject. * * @author Olivier Deruelle
    - * @version 1.2 $Revision: 1.9 $ $Date: 2010-05-06 14:07:53 $ + * @version 1.2 $Revision: 1.8 $ $Date: 2009-07-17 18:57:40 $ * * * @@ -56,15 +56,15 @@ public class UserAgent extends SIPHeader implements UserAgentHeader { * pmusgrave - put a space between products (preserves format of header) * @return String */ - private StringBuilder encodeProduct(StringBuilder tokens) { -// StringBuilder tokens = new StringBuilder(); + private String encodeProduct() { + StringBuffer tokens = new StringBuffer(); ListIterator it = productTokens.listIterator(); while (it.hasNext()) { tokens.append((String) it.next()); } - return tokens; + return tokens.toString(); } /** set the productToken field @@ -85,8 +85,8 @@ public UserAgent() { /** Encode only the body of this header. *@return encoded value of the header. */ - public StringBuilder encodeBody(StringBuilder buffer) { - return encodeProduct(buffer); + public String encodeBody() { + return encodeProduct(); } /** @@ -127,9 +127,6 @@ public Object clone() { } /* * $Log: not supported by cvs2svn $ - * Revision 1.8 2009/07/17 18:57:40 emcho - * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. - * * Revision 1.7 2008/07/30 14:36:06 mranga * Issue number: * Obtained from: diff --git a/src/gov/nist/javax/sip/header/Via.java b/src/gov/nist/javax/sip/header/Via.java index e18f73b7d..1bc148b57 100755 --- a/src/gov/nist/javax/sip/header/Via.java +++ b/src/gov/nist/javax/sip/header/Via.java @@ -44,7 +44,7 @@ * * @see ViaList * - * @version 1.2 $Revision: 1.19 $ $Date: 2010-08-13 10:31:54 $ + * @version 1.2 $Revision: 1.17 $ $Date: 2009-10-18 13:46:33 $ * * @author M. Ranganathan
    * @@ -251,10 +251,10 @@ public void setComment(String c) { * A.K.A headerValue. */ protected String encodeBody() { - return encodeBody(new StringBuilder()).toString(); + return encodeBody(new StringBuffer()).toString(); } - protected StringBuilder encodeBody(StringBuilder buffer) { + protected StringBuffer encodeBody(StringBuffer buffer) { sentProtocol.encode(buffer); buffer.append(SP); sentBy.encode(buffer); @@ -324,9 +324,8 @@ public void setPort(int port) throws InvalidArgumentException { * Set the RPort flag parameter */ public void setRPort(){ - // Fix for Issue 309 by jorabin try { - this.setParameter(Via.RPORT,null); + this.setParameter(Via.RPORT,""); } catch (ParseException e) { e.printStackTrace(); // should not occur } diff --git a/src/gov/nist/javax/sip/header/Warning.java b/src/gov/nist/javax/sip/header/Warning.java index 2b36884de..ab508d096 100755 --- a/src/gov/nist/javax/sip/header/Warning.java +++ b/src/gov/nist/javax/sip/header/Warning.java @@ -36,7 +36,7 @@ * * @author M. Ranganathan
    * @author Olivier Deruelle
    - * @version 1.2 $Revision: 1.9 $ $Date: 2010-05-06 14:07:55 $ + * @version 1.2 $Revision: 1.8 $ $Date: 2009-10-18 13:46:33 $ * * * @@ -72,16 +72,16 @@ public Warning() { /** Encode the body of the header (return the stuff following name:). *@return the string encoding of the header value. */ - public StringBuilder encodeBody(StringBuilder buffer) { + public String encodeBody() { return text != null - ? buffer.append(Integer.toString(code)) - .append(SP) - .append(agent) - .append(SP) - .append(DOUBLE_QUOTE) - .append(text) - .append(DOUBLE_QUOTE) - : buffer.append(Integer.toString(code)).append(SP).append(agent); + ? Integer.toString(code) + + SP + + agent + + SP + + DOUBLE_QUOTE + + text + + DOUBLE_QUOTE + : Integer.toString(code) + SP + agent; } /** @@ -151,14 +151,6 @@ public void setText(String text) throws ParseException { } /* * $Log: not supported by cvs2svn $ - * Revision 1.8 2009/10/18 13:46:33 deruelle_jean - * FindBugs Fixes (Category Performance Warnings) - * - * Issue number: - * Obtained from: - * Submitted by: Jean Deruelle - * Reviewed by: - * * Revision 1.7 2009/07/17 18:57:41 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * diff --git a/src/gov/nist/javax/sip/header/extensions/Join.java b/src/gov/nist/javax/sip/header/extensions/Join.java index 756470819..73a82524b 100644 --- a/src/gov/nist/javax/sip/header/extensions/Join.java +++ b/src/gov/nist/javax/sip/header/extensions/Join.java @@ -56,16 +56,15 @@ public Join(String callId) throws IllegalArgumentException { * Encode the body part of this header (i.e. leave out the hdrName). * @return String encoded body part of the header. */ - public StringBuilder encodeBody(StringBuilder retval) { + public String encodeBody() { if (callId == null) - return retval; + return null; else { - retval.append(callId); + String retVal = callId; if (!parameters.isEmpty()) { - retval.append(SEMICOLON); - parameters.encode(retval); + retVal += SEMICOLON + parameters.encode(); } - return retval; + return retVal; } } diff --git a/src/gov/nist/javax/sip/header/extensions/MinSE.java b/src/gov/nist/javax/sip/header/extensions/MinSE.java index 2c4360510..9e842f97f 100644 --- a/src/gov/nist/javax/sip/header/extensions/MinSE.java +++ b/src/gov/nist/javax/sip/header/extensions/MinSE.java @@ -17,7 +17,7 @@ * * (Created by modifying Expires.java) * - * @version JAIN-SIP-1.1 $Revision: 1.5 $ $Date: 2010-05-06 14:07:56 $ + * @version JAIN-SIP-1.1 $Revision: 1.4 $ $Date: 2009-10-18 13:46:36 $ * * @author P. Musgrave
    * @@ -47,12 +47,11 @@ public MinSE() { * Return canonical form. * @return String */ - public StringBuilder encodeBody(StringBuilder retval) { - retval.append(Integer.toString(expires)); // seems overkill - but Expires did this. + public String encodeBody() { + String retval = Integer.toString(expires); // seems overkill - but Expires did this. if (!parameters.isEmpty()) { - retval.append(SEMICOLON); - parameters.encode(retval); + retval += SEMICOLON + parameters.encode(); } return retval; } diff --git a/src/gov/nist/javax/sip/header/extensions/References.java b/src/gov/nist/javax/sip/header/extensions/References.java index bc6090afd..43a72a8a3 100644 --- a/src/gov/nist/javax/sip/header/extensions/References.java +++ b/src/gov/nist/javax/sip/header/extensions/References.java @@ -1,6 +1,5 @@ package gov.nist.javax.sip.header.extensions; -import gov.nist.core.Separators; import gov.nist.javax.sip.header.ParametersHeader; import java.text.ParseException; @@ -72,13 +71,11 @@ public String getName() { } - public StringBuilder encodeBody(StringBuilder buffer) { + protected String encodeBody() { if ( super.parameters.isEmpty()) { - return buffer.append(callId); + return callId ; } else { - buffer = buffer.append(callId).append(Separators.SEMICOLON); - buffer = super.parameters.encode(buffer); - return buffer; + return callId + ";" + super.parameters.encode(); } } diff --git a/src/gov/nist/javax/sip/header/extensions/ReferredBy.java b/src/gov/nist/javax/sip/header/extensions/ReferredBy.java index f1dfe9a01..ad5669392 100644 --- a/src/gov/nist/javax/sip/header/extensions/ReferredBy.java +++ b/src/gov/nist/javax/sip/header/extensions/ReferredBy.java @@ -49,30 +49,26 @@ public void setValue(String value) throws ParseException { * Encode the header content into a String. * @return String */ - public StringBuilder encodeBody(StringBuilder retval) { + protected String encodeBody() { if (address == null) return null; -// String retval = ""; + String retval = ""; if (address.getAddressType() == AddressImpl.ADDRESS_SPEC) { - retval.append(LESS_THAN); + retval += LESS_THAN; } - address.encode(retval); + retval += address.encode(); if (address.getAddressType() == AddressImpl.ADDRESS_SPEC) { - retval.append(GREATER_THAN); + retval += GREATER_THAN; } if (!parameters.isEmpty()) { - retval.append(SEMICOLON); - parameters.encode(retval); + retval += SEMICOLON + parameters.encode(); } return retval; } } /* * $Log: not supported by cvs2svn $ - * Revision 1.3 2009/07/17 18:57:42 emcho - * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. - * * Revision 1.2 2006/10/27 20:58:31 mranga * Issue number: * Obtained from: diff --git a/src/gov/nist/javax/sip/header/extensions/Replaces.java b/src/gov/nist/javax/sip/header/extensions/Replaces.java index 2b5214c05..02d05edbb 100644 --- a/src/gov/nist/javax/sip/header/extensions/Replaces.java +++ b/src/gov/nist/javax/sip/header/extensions/Replaces.java @@ -2,7 +2,6 @@ * Product of NIST/ITL Advanced Networking Technologies Division (ANTD). * *******************************************************************************/ package gov.nist.javax.sip.header.extensions; -import java.nio.Buffer; import java.text.ParseException; import gov.nist.javax.sip.header.*; @@ -57,16 +56,15 @@ public Replaces(String callId) throws IllegalArgumentException { * Encode the body part of this header (i.e. leave out the hdrName). * @return String encoded body part of the header. */ - public StringBuilder encodeBody(StringBuilder retval) { + public String encodeBody() { if (callId == null) - return retval; + return null; else { - retval.append(callId); + String retVal = callId; if (!parameters.isEmpty()) { - retval.append(SEMICOLON); - parameters.encode(retval); + retVal += SEMICOLON + parameters.encode(); } - return retval; + return retVal; } } @@ -188,9 +186,6 @@ public void setValue(String value) throws ParseException { } /* * $Log: not supported by cvs2svn $ - * Revision 1.3 2009/07/17 18:57:42 emcho - * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. - * * Revision 1.2 2006/10/27 20:58:31 mranga * Issue number: * Obtained from: diff --git a/src/gov/nist/javax/sip/header/extensions/SessionExpires.java b/src/gov/nist/javax/sip/header/extensions/SessionExpires.java index 65a73f4af..1209325ed 100644 --- a/src/gov/nist/javax/sip/header/extensions/SessionExpires.java +++ b/src/gov/nist/javax/sip/header/extensions/SessionExpires.java @@ -15,7 +15,7 @@ /** * ReferredBy SIP Header. * - * @version JAIN-SIP-1.1 $Revision: 1.6 $ $Date: 2010-05-06 14:07:56 $ + * @version JAIN-SIP-1.1 $Revision: 1.5 $ $Date: 2009-10-18 13:46:36 $ * * @author Peter Musgrave. * @@ -81,14 +81,13 @@ public void setValue(String value) throws ParseException { * Encode the header content into a String. * @return String */ - protected StringBuilder encodeBody(StringBuilder retval) { + protected String encodeBody() { - retval.append(Integer.toString(expires)); + String retval = Integer.toString(expires); if (!parameters.isEmpty()) { - retval.append(SEMICOLON); - parameters.encode(retval); - } + retval += SEMICOLON + parameters.encode(); + } return retval; } diff --git a/src/gov/nist/javax/sip/header/ims/PAccessNetworkInfo.java b/src/gov/nist/javax/sip/header/ims/PAccessNetworkInfo.java index a0a1db250..c220c78d2 100644 --- a/src/gov/nist/javax/sip/header/ims/PAccessNetworkInfo.java +++ b/src/gov/nist/javax/sip/header/ims/PAccessNetworkInfo.java @@ -245,24 +245,24 @@ public Object getExtensionAccessInfo() { return this.extendAccessInfo; } - public StringBuilder encodeBody(StringBuilder encoding) { + protected String encodeBody() { -// StringBuilder encoding = new StringBuilder(); + StringBuffer encoding = new StringBuffer(); if (getAccessType() != null) encoding.append(getAccessType()); if (!parameters.isEmpty()) { - encoding = encoding.append(SEMICOLON).append(SP); - encoding = this.parameters.encode(encoding); + encoding.append(SEMICOLON + SP + this.parameters.encode()); } // else if (getExtendAccessInfo() != null) // stack deve limitar, de // acordo com a especificação ? if (getExtensionAccessInfo() != null) { - encoding.append(SEMICOLON).append(SP).append(getExtensionAccessInfo().toString()); + encoding.append(SEMICOLON + SP + + getExtensionAccessInfo().toString()); } - return encoding; + return encoding.toString(); } diff --git a/src/gov/nist/javax/sip/header/ims/PAssertedIdentity.java b/src/gov/nist/javax/sip/header/ims/PAssertedIdentity.java index 7f01bd79a..6991247e8 100644 --- a/src/gov/nist/javax/sip/header/ims/PAssertedIdentity.java +++ b/src/gov/nist/javax/sip/header/ims/PAssertedIdentity.java @@ -72,22 +72,20 @@ public PAssertedIdentity() /** Encode into canonical form. *@return String containing the canonicaly encoded header. */ - public StringBuilder encodeBody(StringBuilder retval) { -// StringBuilder retval = new StringBuilder(); + public String encodeBody() { + StringBuffer retval = new StringBuffer(); if (address.getAddressType() == AddressImpl.ADDRESS_SPEC) { retval.append(LESS_THAN); } - address.encode(retval); + retval.append(address.encode()); if (address.getAddressType() == AddressImpl.ADDRESS_SPEC) { retval.append(GREATER_THAN); } - if (!parameters.isEmpty()) { - retval= retval.append(COMMA); - retval= this.parameters.encode(retval); - } - return retval; + if (!parameters.isEmpty()) + retval.append(COMMA + this.parameters.encode()); + return retval.toString(); } diff --git a/src/gov/nist/javax/sip/header/ims/PAssertedService.java b/src/gov/nist/javax/sip/header/ims/PAssertedService.java index 4cfcb525c..2f8bea0bd 100644 --- a/src/gov/nist/javax/sip/header/ims/PAssertedService.java +++ b/src/gov/nist/javax/sip/header/ims/PAssertedService.java @@ -48,8 +48,8 @@ public PAssertedService() } @Override - protected StringBuilder encodeBody(StringBuilder retval) { -// StringBuilder retval = new StringBuilder(); + protected String encodeBody() { + StringBuffer retval = new StringBuffer(); retval.append(ParameterNamesIms.SERVICE_ID); @@ -66,7 +66,7 @@ else if(this.subAppIds!=null) retval.append(this.getApplicationIdentifiers()); } - return retval; + return retval.toString(); } public void setValue(String value) throws ParseException { diff --git a/src/gov/nist/javax/sip/header/ims/PAssociatedURI.java b/src/gov/nist/javax/sip/header/ims/PAssociatedURI.java index 6ccac230e..b62100204 100644 --- a/src/gov/nist/javax/sip/header/ims/PAssociatedURI.java +++ b/src/gov/nist/javax/sip/header/ims/PAssociatedURI.java @@ -104,22 +104,21 @@ public PAssociatedURI(GenericURI associatedURI) * Encode into canonical form. * @return String containing the canonicaly encoded header. */ - public StringBuilder encodeBody(StringBuilder retval) { -// StringBuilder retval = new StringBuilder(); + public String encodeBody() + { + StringBuffer retval = new StringBuffer(); if (address.getAddressType() == AddressImpl.ADDRESS_SPEC) { retval.append(LESS_THAN); } - address.encode(retval); + retval.append(address.encode()); if (address.getAddressType() == AddressImpl.ADDRESS_SPEC) { retval.append(GREATER_THAN); } - if (!parameters.isEmpty()) { - retval= retval.append(SEMICOLON); - retval= this.parameters.encode(retval); - } - return retval; + if (!parameters.isEmpty()) + retval.append(SEMICOLON + this.parameters.encode()); + return retval.toString(); } diff --git a/src/gov/nist/javax/sip/header/ims/PCalledPartyID.java b/src/gov/nist/javax/sip/header/ims/PCalledPartyID.java index e622eb954..48ea4bb58 100644 --- a/src/gov/nist/javax/sip/header/ims/PCalledPartyID.java +++ b/src/gov/nist/javax/sip/header/ims/PCalledPartyID.java @@ -67,21 +67,19 @@ public PCalledPartyID() { /** Encode into canonical form. *@return String containing the canonicaly encoded header. */ - public StringBuilder encodeBody(StringBuilder retval) { -// StringBuilder retval = new StringBuilder(); + public String encodeBody() { + StringBuffer retval = new StringBuffer(); if (address.getAddressType() == AddressImpl.ADDRESS_SPEC) { retval.append(LESS_THAN); } - address.encode(retval); + retval.append(address.encode()); if (address.getAddressType() == AddressImpl.ADDRESS_SPEC) { retval.append(GREATER_THAN); } - if (!parameters.isEmpty()) { - retval= retval.append(SEMICOLON); - retval= this.parameters.encode(retval); - } - return retval; + if (!parameters.isEmpty()) + retval.append(SEMICOLON + this.parameters.encode()); + return retval.toString(); } public void setValue(String value) throws ParseException { diff --git a/src/gov/nist/javax/sip/header/ims/PChargingFunctionAddresses.java b/src/gov/nist/javax/sip/header/ims/PChargingFunctionAddresses.java index 4e521045c..94570d494 100644 --- a/src/gov/nist/javax/sip/header/ims/PChargingFunctionAddresses.java +++ b/src/gov/nist/javax/sip/header/ims/PChargingFunctionAddresses.java @@ -86,17 +86,17 @@ public PChargingFunctionAddresses() { /* (non-Javadoc) * @see gov.nist.javax.sip.header.ParametersHeader#encodeBody() */ - public StringBuilder encodeBody(StringBuilder encoding) { + protected String encodeBody() { -// StringBuilder encoding = new StringBuilder(); + StringBuffer encoding = new StringBuffer(); // issued by Miguel Freitas if (!duplicates.isEmpty()) { - duplicates.encode(encoding); + encoding.append(duplicates.encode()); } - return encoding; + return encoding.toString(); } diff --git a/src/gov/nist/javax/sip/header/ims/PChargingVector.java b/src/gov/nist/javax/sip/header/ims/PChargingVector.java index 9315730c0..069661e66 100644 --- a/src/gov/nist/javax/sip/header/ims/PChargingVector.java +++ b/src/gov/nist/javax/sip/header/ims/PChargingVector.java @@ -58,9 +58,9 @@ public PChargingVector() { * * @see gov.nist.javax.sip.header.ParametersHeader#encodeBody() */ - public StringBuilder encodeBody(StringBuilder encoding) { + protected String encodeBody() { -// StringBuilder encoding = new StringBuilder(); + StringBuffer encoding = new StringBuffer(); /* * no need to check for the presence of icid-value. According to the * spec above this is a mandatory field. if it does not exist, then we @@ -88,7 +88,7 @@ public StringBuilder encodeBody(StringBuilder encoding) { encoding.append(SEMICOLON).append(ParameterNamesIms.ORIG_IOI) .append(EQUALS).append(getOriginatingIOI()); - return encoding; + return encoding.toString(); } /** diff --git a/src/gov/nist/javax/sip/header/ims/PMediaAuthorization.java b/src/gov/nist/javax/sip/header/ims/PMediaAuthorization.java index b121364db..6ac82d1fd 100644 --- a/src/gov/nist/javax/sip/header/ims/PMediaAuthorization.java +++ b/src/gov/nist/javax/sip/header/ims/PMediaAuthorization.java @@ -110,8 +110,9 @@ public void setMediaAuthorizationToken(String token) throws InvalidArgumentExcep * Encode header * @return the header content */ - public StringBuilder encodeBody(StringBuilder encoding) { - return encoding.append(token); + protected String encodeBody() + { + return token; } diff --git a/src/gov/nist/javax/sip/header/ims/PPreferredIdentity.java b/src/gov/nist/javax/sip/header/ims/PPreferredIdentity.java index 50a34360d..3b9ab139b 100644 --- a/src/gov/nist/javax/sip/header/ims/PPreferredIdentity.java +++ b/src/gov/nist/javax/sip/header/ims/PPreferredIdentity.java @@ -71,18 +71,18 @@ public PPreferredIdentity() { /** Encode into canonical form. * @return String containing the canonicaly encoded header. */ - public StringBuilder encodeBody(StringBuilder retval) { -// StringBuilder retval = new StringBuilder(); + public String encodeBody() { + StringBuffer retval = new StringBuffer(); if (address.getAddressType() == AddressImpl.ADDRESS_SPEC) { retval.append(LESS_THAN); } - address.encode(retval); + retval.append(address.encode()); if (address.getAddressType() == AddressImpl.ADDRESS_SPEC) { retval.append(GREATER_THAN); } - return retval; + return retval.toString(); } public void setValue(String value) throws ParseException { diff --git a/src/gov/nist/javax/sip/header/ims/PPreferredService.java b/src/gov/nist/javax/sip/header/ims/PPreferredService.java index 71ae569a2..4a5640776 100644 --- a/src/gov/nist/javax/sip/header/ims/PPreferredService.java +++ b/src/gov/nist/javax/sip/header/ims/PPreferredService.java @@ -47,8 +47,8 @@ public PPreferredService() } @Override - protected StringBuilder encodeBody(StringBuilder retval) { -// StringBuilder retval = new StringBuilder(); + protected String encodeBody() { + StringBuffer retval = new StringBuffer(); retval.append(ParameterNamesIms.SERVICE_ID); @@ -66,7 +66,7 @@ else if(this.subAppIds!=null) retval.append(this.getApplicationIdentifiers()); } - return retval; + return retval.toString(); } public void setValue(String value) throws ParseException { diff --git a/src/gov/nist/javax/sip/header/ims/PProfileKey.java b/src/gov/nist/javax/sip/header/ims/PProfileKey.java index d1db2a8a5..8c08060b8 100644 --- a/src/gov/nist/javax/sip/header/ims/PProfileKey.java +++ b/src/gov/nist/javax/sip/header/ims/PProfileKey.java @@ -50,9 +50,9 @@ public PProfileKey(AddressImpl address) } @Override - protected StringBuilder encodeBody(StringBuilder retval) { + protected String encodeBody() { -// StringBuilder retval = new StringBuilder(); + StringBuffer retval = new StringBuffer(); if (address.getAddressType() == AddressImpl.ADDRESS_SPEC) { retval.append(LESS_THAN); @@ -64,7 +64,7 @@ protected StringBuilder encodeBody(StringBuilder retval) { if (!parameters.isEmpty()) retval.append(SEMICOLON + this.parameters.encode()); - return retval; + return retval.toString(); } public void setValue(String value) throws ParseException { diff --git a/src/gov/nist/javax/sip/header/ims/PServedUser.java b/src/gov/nist/javax/sip/header/ims/PServedUser.java index 484bb4b63..e951bcfdb 100644 --- a/src/gov/nist/javax/sip/header/ims/PServedUser.java +++ b/src/gov/nist/javax/sip/header/ims/PServedUser.java @@ -123,9 +123,9 @@ public void setSessionCase(String sessionCase) { } @Override - protected StringBuilder encodeBody(StringBuilder retval) { + protected String encodeBody() { -// StringBuilder retval = new StringBuilder(); + StringBuffer retval = new StringBuffer(); retval.append(address.encode()); @@ -137,7 +137,7 @@ protected StringBuilder encodeBody(StringBuilder retval) { retval.append(SEMICOLON).append(ParameterNamesIms.SESSION_CASE).append(EQUALS) .append(this.getSessionCase()); - return retval; + return retval.toString(); } public void setValue(String value) throws ParseException { diff --git a/src/gov/nist/javax/sip/header/ims/PUserDatabase.java b/src/gov/nist/javax/sip/header/ims/PUserDatabase.java index 2f2806382..83d3b1049 100644 --- a/src/gov/nist/javax/sip/header/ims/PUserDatabase.java +++ b/src/gov/nist/javax/sip/header/ims/PUserDatabase.java @@ -65,26 +65,24 @@ public void setDatabaseName(String databaseName) { throw new NullPointerException("Database name is null"); else if(!databaseName.contains("aaa://")) - this.databaseName = new StringBuilder().append("aaa://").append(databaseName).toString(); + this.databaseName = new StringBuffer().append("aaa://").append(databaseName).toString(); else this.databaseName = databaseName; } - public StringBuilder encodeBody(StringBuilder retval) { + protected String encodeBody() { -// StringBuilder retval = new StringBuilder(); + StringBuffer retval = new StringBuffer(); retval.append("<"); if(getDatabaseName()!=null) retval.append(getDatabaseName()); - if (!parameters.isEmpty()) { - retval.append(SEMICOLON); - this.parameters.encode(retval); - } + if (!parameters.isEmpty()) + retval.append(SEMICOLON + this.parameters.encode()); retval.append(">"); - return retval; + return retval.toString(); } public boolean equals(Object other) diff --git a/src/gov/nist/javax/sip/header/ims/PVisitedNetworkID.java b/src/gov/nist/javax/sip/header/ims/PVisitedNetworkID.java index c901eab50..2f65db080 100644 --- a/src/gov/nist/javax/sip/header/ims/PVisitedNetworkID.java +++ b/src/gov/nist/javax/sip/header/ims/PVisitedNetworkID.java @@ -78,25 +78,23 @@ public PVisitedNetworkID(Token tok) { } - public StringBuilder encodeBody(StringBuilder retval) { + protected String encodeBody() { -// StringBuilder retval = new StringBuilder(); + StringBuffer retval = new StringBuffer(); if (getVisitedNetworkID() != null) { // issued by Miguel Freitas if (isQuoted) - retval.append(DOUBLE_QUOTE).append(getVisitedNetworkID()).append(DOUBLE_QUOTE); + retval.append(DOUBLE_QUOTE + getVisitedNetworkID() + DOUBLE_QUOTE); else retval.append(getVisitedNetworkID()); } - if (!parameters.isEmpty()) { - retval.append(SEMICOLON); - this.parameters.encode(retval); - } + if (!parameters.isEmpty()) + retval.append(SEMICOLON + this.parameters.encode()); - return retval; + return retval.toString(); } diff --git a/src/gov/nist/javax/sip/header/ims/Path.java b/src/gov/nist/javax/sip/header/ims/Path.java index c00a3e65d..ce6ce1fcf 100644 --- a/src/gov/nist/javax/sip/header/ims/Path.java +++ b/src/gov/nist/javax/sip/header/ims/Path.java @@ -66,21 +66,19 @@ public Path() /** Encode into canonical form. *@return String containing the canonicaly encoded header. */ - public StringBuilder encodeBody(StringBuilder retval) { -// StringBuilder retval = new StringBuilder(); + public String encodeBody() { + StringBuffer retval = new StringBuffer(); if (address.getAddressType() == AddressImpl.ADDRESS_SPEC) { retval.append(LESS_THAN); } - address.encode(retval); + retval.append(address.encode()); if (address.getAddressType() == AddressImpl.ADDRESS_SPEC) { retval.append(GREATER_THAN); } - if (!parameters.isEmpty()) { - retval= retval.append(SEMICOLON); - retval= this.parameters.encode(retval); - } - return retval; + if (!parameters.isEmpty()) + retval.append(SEMICOLON + this.parameters.encode()); + return retval.toString(); } public void setValue(String value) throws ParseException { diff --git a/src/gov/nist/javax/sip/header/ims/Privacy.java b/src/gov/nist/javax/sip/header/ims/Privacy.java index f5fc7cc4d..7b291fdd8 100644 --- a/src/gov/nist/javax/sip/header/ims/Privacy.java +++ b/src/gov/nist/javax/sip/header/ims/Privacy.java @@ -81,8 +81,9 @@ public Privacy(String privacy) * Encode into a canonical string. * @return String. */ - public StringBuilder encodeBody(StringBuilder buffer) { - return buffer.append(this.privacy); + public String encodeBody() + { + return this.privacy; } diff --git a/src/gov/nist/javax/sip/header/ims/SecurityAgree.java b/src/gov/nist/javax/sip/header/ims/SecurityAgree.java index 0906f5ace..6c172c820 100644 --- a/src/gov/nist/javax/sip/header/ims/SecurityAgree.java +++ b/src/gov/nist/javax/sip/header/ims/SecurityAgree.java @@ -117,9 +117,9 @@ public void setParameter(String name, String value) throws ParseException } - public StringBuilder encodeBody(StringBuilder retval) { - retval.append(this.secMechanism).append(SEMICOLON).append(SP); - return parameters.encode(retval); + public String encodeBody() + { + return this.secMechanism + SEMICOLON + SP + parameters.encode(); } diff --git a/src/gov/nist/javax/sip/header/ims/ServiceRoute.java b/src/gov/nist/javax/sip/header/ims/ServiceRoute.java index 929c35cc4..bb77bfab6 100644 --- a/src/gov/nist/javax/sip/header/ims/ServiceRoute.java +++ b/src/gov/nist/javax/sip/header/ims/ServiceRoute.java @@ -67,24 +67,21 @@ public ServiceRoute() { /** Encode into canonical form. *@return String containing the canonicaly encoded header. */ - public StringBuilder encodeBody(StringBuilder retval) { -// String retval = ""; - if (address.getAddressType() == AddressImpl.ADDRESS_SPEC) { - retval.append(LESS_THAN); - } - address.encode(retval); - if (address.getAddressType() == AddressImpl.ADDRESS_SPEC) { - retval.append(GREATER_THAN); - } - - if (!parameters.isEmpty()) { - retval.append(SEMICOLON); - parameters.encode(retval); - } - return retval; + public String encodeBody() { + StringBuffer retval = new StringBuffer(); + if (address.getAddressType() == AddressImpl.ADDRESS_SPEC) { + retval.append(LESS_THAN); + } + retval.append(address.encode()); + if (address.getAddressType() == AddressImpl.ADDRESS_SPEC) { + retval.append(GREATER_THAN); + } + + if (!parameters.isEmpty()) + retval.append(SEMICOLON + this.parameters.encode()); + return retval.toString(); } - public void setValue(String value) throws ParseException { throw new ParseException (value,0); diff --git a/src/gov/nist/javax/sip/message/ListMap.java b/src/gov/nist/javax/sip/message/ListMap.java index 95c742db4..784887161 100755 --- a/src/gov/nist/javax/sip/message/ListMap.java +++ b/src/gov/nist/javax/sip/message/ListMap.java @@ -28,84 +28,14 @@ *******************************************************************************/ package gov.nist.javax.sip.message; -import gov.nist.javax.sip.header.Accept; -import gov.nist.javax.sip.header.AcceptEncoding; -import gov.nist.javax.sip.header.AcceptEncodingList; -import gov.nist.javax.sip.header.AcceptLanguage; -import gov.nist.javax.sip.header.AcceptLanguageList; -import gov.nist.javax.sip.header.AcceptList; -import gov.nist.javax.sip.header.AlertInfo; -import gov.nist.javax.sip.header.AlertInfoList; -import gov.nist.javax.sip.header.Allow; -import gov.nist.javax.sip.header.AllowList; -import gov.nist.javax.sip.header.Authorization; -import gov.nist.javax.sip.header.AuthorizationList; -import gov.nist.javax.sip.header.CallInfo; -import gov.nist.javax.sip.header.CallInfoList; -import gov.nist.javax.sip.header.Contact; -import gov.nist.javax.sip.header.ContactList; -import gov.nist.javax.sip.header.ContentEncoding; -import gov.nist.javax.sip.header.ContentEncodingList; -import gov.nist.javax.sip.header.ContentLanguage; -import gov.nist.javax.sip.header.ContentLanguageList; -import gov.nist.javax.sip.header.ErrorInfo; -import gov.nist.javax.sip.header.ErrorInfoList; -import gov.nist.javax.sip.header.ExtensionHeaderImpl; -import gov.nist.javax.sip.header.ExtensionHeaderList; -import gov.nist.javax.sip.header.InReplyTo; -import gov.nist.javax.sip.header.InReplyToList; -import gov.nist.javax.sip.header.ProxyAuthenticate; -import gov.nist.javax.sip.header.ProxyAuthenticateList; -import gov.nist.javax.sip.header.ProxyAuthorization; -import gov.nist.javax.sip.header.ProxyAuthorizationList; -import gov.nist.javax.sip.header.ProxyRequire; -import gov.nist.javax.sip.header.ProxyRequireList; -import gov.nist.javax.sip.header.RecordRoute; -import gov.nist.javax.sip.header.RecordRouteList; -import gov.nist.javax.sip.header.Require; -import gov.nist.javax.sip.header.RequireList; -import gov.nist.javax.sip.header.Route; -import gov.nist.javax.sip.header.RouteList; -import gov.nist.javax.sip.header.SIPHeader; -import gov.nist.javax.sip.header.SIPHeaderList; -import gov.nist.javax.sip.header.Supported; -import gov.nist.javax.sip.header.SupportedList; -import gov.nist.javax.sip.header.Unsupported; -import gov.nist.javax.sip.header.UnsupportedList; -import gov.nist.javax.sip.header.Via; -import gov.nist.javax.sip.header.ViaList; -import gov.nist.javax.sip.header.WWWAuthenticate; -import gov.nist.javax.sip.header.WWWAuthenticateList; -import gov.nist.javax.sip.header.Warning; -import gov.nist.javax.sip.header.WarningList; -import gov.nist.javax.sip.header.ims.PAssertedIdentity; -import gov.nist.javax.sip.header.ims.PAssertedIdentityList; -import gov.nist.javax.sip.header.ims.PAssociatedURI; -import gov.nist.javax.sip.header.ims.PAssociatedURIList; -import gov.nist.javax.sip.header.ims.PMediaAuthorization; -import gov.nist.javax.sip.header.ims.PMediaAuthorizationList; -import gov.nist.javax.sip.header.ims.PVisitedNetworkID; -import gov.nist.javax.sip.header.ims.PVisitedNetworkIDList; -import gov.nist.javax.sip.header.ims.Path; -import gov.nist.javax.sip.header.ims.PathList; -import gov.nist.javax.sip.header.ims.Privacy; -import gov.nist.javax.sip.header.ims.PrivacyList; -import gov.nist.javax.sip.header.ims.SecurityClient; -import gov.nist.javax.sip.header.ims.SecurityClientList; -import gov.nist.javax.sip.header.ims.SecurityServer; -import gov.nist.javax.sip.header.ims.SecurityServerList; -import gov.nist.javax.sip.header.ims.SecurityVerify; -import gov.nist.javax.sip.header.ims.SecurityVerifyList; -import gov.nist.javax.sip.header.ims.ServiceRoute; -import gov.nist.javax.sip.header.ims.ServiceRouteList; - -import java.util.HashMap; -import java.util.Map; +import gov.nist.javax.sip.header.*; +import gov.nist.javax.sip.header.ims.*; +import java.util.Hashtable; /** * A map of which of the standard headers may appear as a list * - * @version 1.2 $Revision: 1.16 $ $Date: 2010-05-06 14:08:04 $ + * @version 1.2 $Revision: 1.15 $ $Date: 2010-03-15 17:01:23 $ * @since 1.1 */ public class ListMap { @@ -115,7 +45,7 @@ public class ListMap { // (provided it has a list form). Note that under JAVA-5 we have // typed collections which would render such a list obsolete. However, // we are not using java 5. - private static Map,Class> headerListTable; + private static Hashtable,Class> headerListTable; private static boolean initialized; static { @@ -127,8 +57,7 @@ static private void initializeListMap() { * Build a table mapping between objects that have a list form and the * class of such objects. */ - // jeand : using concurrent data structure to avoid excessive blocking - headerListTable = new HashMap, Class>(34); + headerListTable = new Hashtable, Class>(); headerListTable.put(ExtensionHeaderImpl.class, ExtensionHeaderList.class); headerListTable.put(Contact.class, ContactList.class); diff --git a/src/gov/nist/javax/sip/message/MessageFactoryImpl.java b/src/gov/nist/javax/sip/message/MessageFactoryImpl.java index cd5828f58..158ee7036 100755 --- a/src/gov/nist/javax/sip/message/MessageFactoryImpl.java +++ b/src/gov/nist/javax/sip/message/MessageFactoryImpl.java @@ -42,7 +42,7 @@ /** * Message Factory implementation * - * @version 1.2 $Revision: 1.24 $ $Date: 2010-05-06 14:08:03 $ + * @version 1.2 $Revision: 1.23 $ $Date: 2009-09-08 01:58:40 $ * @since 1.1 * * @author M. Ranganathan
    @@ -697,7 +697,7 @@ public javax.sip.message.Request createRequest(String requestString) } StringMsgParser smp = new StringMsgParser(); -// smp.setStrict(this.strict); + smp.setStrict(this.strict); /* * This allows you to catch parse exceptions and create invalid messages @@ -729,11 +729,10 @@ public void handleException(ParseException ex, }; - ParseExceptionListener exHandler = null; if (this.testing) - exHandler = parseExceptionListener; + smp.setParseExceptionListener(parseExceptionListener); - SIPMessage sipMessage = smp.parseSIPMessage(requestString.getBytes(), true, this.strict, exHandler); + SIPMessage sipMessage = smp.parseSIPMessage(requestString); if (!(sipMessage instanceof SIPRequest)) throw new ParseException(requestString, 0); @@ -756,7 +755,7 @@ public Response createResponse(String responseString) StringMsgParser smp = new StringMsgParser(); - SIPMessage sipMessage = smp.parseSIPMessage(responseString.getBytes(), true, false, null); + SIPMessage sipMessage = smp.parseSIPMessage(responseString); if (!(sipMessage instanceof SIPResponse)) throw new ParseException(responseString, 0); diff --git a/src/gov/nist/javax/sip/message/MultipartMimeContentImpl.java b/src/gov/nist/javax/sip/message/MultipartMimeContentImpl.java index 93ff8349b..6c89eb252 100644 --- a/src/gov/nist/javax/sip/message/MultipartMimeContentImpl.java +++ b/src/gov/nist/javax/sip/message/MultipartMimeContentImpl.java @@ -66,12 +66,12 @@ public ContentTypeHeader getContentTypeHeader() { */ @Override public String toString() { - StringBuilder StringBuilder = new StringBuilder(); + StringBuffer stringBuffer = new StringBuffer(); for (Content content : this.contentList) { - StringBuilder.append(content.toString()); + stringBuffer.append(content.toString()); } - return StringBuilder.toString(); + return stringBuffer.toString(); } @@ -103,7 +103,7 @@ public void createContentList(String body) throws ParseException { if (nextPart == null) { return; } - StringBuilder strbuf = new StringBuilder(nextPart); + StringBuffer strbuf = new StringBuffer(nextPart); while (strbuf.length() > 0 && (strbuf.charAt(0) == '\r' || strbuf.charAt(0) == '\n')) strbuf.deleteCharAt(0); diff --git a/src/gov/nist/javax/sip/message/SIPMessage.java b/src/gov/nist/javax/sip/message/SIPMessage.java index 79b2abe27..20f835496 100755 --- a/src/gov/nist/javax/sip/message/SIPMessage.java +++ b/src/gov/nist/javax/sip/message/SIPMessage.java @@ -29,7 +29,6 @@ package gov.nist.javax.sip.message; import gov.nist.core.InternalErrorHandler; -import gov.nist.core.Separators; import gov.nist.javax.sip.SIPConstants; import gov.nist.javax.sip.Utils; import gov.nist.javax.sip.header.AlertInfo; @@ -76,15 +75,13 @@ import java.io.UnsupportedEncodingException; import java.lang.reflect.Field; -import java.net.InetAddress; import java.text.ParseException; import java.util.Collection; +import java.util.Hashtable; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import javax.sip.InvalidArgumentException; @@ -111,32 +108,32 @@ /* * Acknowledgements: Yanick Belanger sent in a patch for the right content length when the content * is a String. Bill Mccormick from Nortel Networks sent in a bug fix for setContent. - * + * */ /** * This is the main SIP Message structure. - * + * * @see StringMsgParser * @see PipelinedMsgParser - * - * @version 1.2 $Revision: 1.59 $ $Date: 2010-12-02 22:44:52 $ + * + * @version 1.2 $Revision: 1.55 $ $Date: 2010-03-15 17:01:23 $ * @since 1.1 - * + * * @author M. Ranganathan
    - * - * + * + * */ public abstract class SIPMessage extends MessageObject implements javax.sip.message.Message, MessageExt { - // JvB: use static here? + // JvB: use static here? private String contentEncodingCharset = MessageFactoryImpl.getDefaultContentEncodingCharset(); - + /* * True if this is a null request. */ protected boolean nullRequest; - + /** * unparsed headers */ @@ -173,7 +170,7 @@ public abstract class SIPMessage extends MessageObject implements javax.sip.mess protected Object messageContentObject; // Table of headers indexed by name. - protected Map headerTable; + private Hashtable nameTable; /** * The application data pointer. This is un-interpreted by the stack. This is provided as a @@ -181,33 +178,11 @@ public abstract class SIPMessage extends MessageObject implements javax.sip.mess */ protected Object applicationData; - protected String forkId; - - /** - * The remote address that this message is bound to or received from. - */ - private InetAddress remoteAddress; - - /** - * The remote port that this message is bound to or received from. - */ - private int remotePort; - - /** - * The local address that we will send the message from or that we received - * it on. - */ - private InetAddress localAddress; - - /** - * The local port that we will send the message from or that we received - * it on. - */ - private int localPort; + private String forkId; /** * Return true if the header belongs only in a Request. - * + * * @param sipHeader is the header to test. */ public static boolean isRequestHeader(SIPHeader sipHeader) { @@ -222,7 +197,7 @@ public static boolean isRequestHeader(SIPHeader sipHeader) { /** * Return true if the header belongs only in a response. - * + * * @param sipHeader is the header to test. */ public static boolean isResponseHeader(SIPHeader sipHeader) { @@ -236,7 +211,7 @@ public static boolean isResponseHeader(SIPHeader sipHeader) { /** * Get the headers as a linked list of encoded Strings - * + * * @return a linked list with each element of the list containing a string encoded header in * canonical form. */ @@ -258,11 +233,11 @@ public LinkedList getMessageAsEncodedStrings() { /** * Encode only the message and exclude the contents (for debugging); - * + * * @return a string with all the headers encoded. */ - protected StringBuilder encodeSIPHeaders(StringBuilder encoding) { -// StringBuilder encoding = new StringBuilder(); + protected String encodeSIPHeaders() { + StringBuffer encoding = new StringBuffer(); Iterator it = this.headers.iterator(); while (it.hasNext()) { @@ -271,63 +246,27 @@ protected StringBuilder encodeSIPHeaders(StringBuilder encoding) { siphdr.encode(encoding); } - return contentLengthHeader.encode(encoding).append(NEWLINE); + return contentLengthHeader.encode(encoding).append(NEWLINE).toString(); } /** * Encode all the headers except the contents. For debug logging. */ - public abstract StringBuilder encodeMessage(StringBuilder retval); + public abstract String encodeMessage(); /** * Get A dialog identifier constructed from this messsage. This is an id that can be used to * identify dialogs. - * + * * @param isServerTransaction is a flag that indicates whether this is a server transaction. */ - public final String getDialogId(boolean isServer) { - To to = (To) this.getTo(); - return this.getDialogId( isServer, to.getTag() ); - } - - /** - * Get a dialog id given the remote tag. - */ - public final String getDialogId(boolean isServer, String toTag) { - From from = (From) this.getFrom(); - CallID cid = (CallID) this.getCallId(); - StringBuffer retval = new StringBuffer(cid.getCallId()); - if (!isServer) { - // retval.append(COLON).append(from.getUserAtHostPort()); - if (from.getTag() != null) { - retval.append(COLON); - retval.append(from.getTag()); - } - // retval.append(COLON).append(to.getUserAtHostPort()); - if (toTag != null) { - retval.append(COLON); - retval.append(toTag); - } - } else { - // retval.append(COLON).append(to.getUserAtHostPort()); - if (toTag != null) { - retval.append(COLON); - retval.append(toTag); - } - // retval.append(COLON).append(from.getUserAtHostPort()); - if (from.getTag() != null) { - retval.append(COLON); - retval.append(from.getTag()); - } - } - return retval.toString().toLowerCase(); - } + public abstract String getDialogId(boolean isServerTransaction); /** * Template match for SIP messages. The matchObj is a SIPMessage template to match against. * This method allows you to do pattern matching with incoming SIP messages. Null matches wild * card. - * + * * @param other is the match template to match against. * @return true if a match occured and false otherwise. */ @@ -386,9 +325,9 @@ public boolean match(Object other) { /** * Merge a request with a template - * + * * @param template -- template to merge with. - * + * */ public void merge(Object template) { if (!template.getClass().equals(this.getClass())) @@ -416,28 +355,26 @@ public void merge(Object template) { * Encode this message as a string. This is more efficient when the payload is a string * (rather than a binary array of bytes). If the payload cannot be encoded as a UTF-8 string * then it is simply ignored (will not appear in the encoded message). - * + * * @return The Canonical String representation of the message (including the canonical string * representation of the SDP payload if it exists). */ public String encode() { - StringBuilder encoding = new StringBuilder(); + StringBuffer encoding = new StringBuffer(); Iterator it = this.headers.iterator(); while (it.hasNext()) { SIPHeader siphdr = (SIPHeader) it.next(); if (!(siphdr instanceof ContentLength)) - siphdr.encode(encoding); + encoding.append(siphdr.encode()); } // Append the unrecognized headers. Headers that are not // recognized are passed through unchanged. - if(unrecognizedHeaders != null) { - for (String unrecognized : unrecognizedHeaders) { - encoding.append(unrecognized).append(NEWLINE); - } + for (String unrecognized : this.unrecognizedHeaders) { + encoding.append(unrecognized).append(NEWLINE); } - contentLengthHeader.encode(encoding).append(NEWLINE); + encoding.append(contentLengthHeader.encode()).append(NEWLINE); if (this.messageContentObject != null) { String mbody = this.getContent().toString(); @@ -450,11 +387,11 @@ public String encode() { if (messageContent != null) content = messageContent; else { - // JvB: Check for 'charset' parameter which overrides the default UTF-8 + // JvB: Check for 'charset' parameter which overrides the default UTF-8 content = new String(messageContentBytes, getCharset() ); } } catch (UnsupportedEncodingException ex) { - InternalErrorHandler.handleException(ex); + InternalErrorHandler.handleException(ex); } encoding.append(content); @@ -465,7 +402,7 @@ public String encode() { /** * Encode the message as a byte array. Use this when the message payload is a binary byte * array. - * + * * @return The Canonical byte array representation of the message (including the canonical * byte array representation of the SDP payload if it exists all in one contiguous * byte array). @@ -483,7 +420,7 @@ public byte[] encodeAsBytes(String transport) { InternalErrorHandler.handleException(e); } - StringBuilder encoding = new StringBuilder(); + StringBuffer encoding = new StringBuffer(); synchronized (this.headers) { Iterator it = this.headers.iterator(); @@ -531,12 +468,12 @@ public byte[] encodeAsBytes(String transport) { * is allocated and copied over. If the content is an Object that supports the clone method, * then the clone method is invoked and the cloned content is the new content. Otherwise, the * content of the new message is set equal to the old one. - * + * * @return A cloned copy of this object. */ public Object clone() { SIPMessage retval = (SIPMessage) super.clone(); - retval.headerTable = new ConcurrentHashMap(); + retval.nameTable = new Hashtable(); retval.fromHeader = null; retval.toHeader = null; retval.cSeqHeader = null; @@ -556,14 +493,12 @@ public Object clone() { if (this.messageContentObject != null) retval.messageContentObject = makeClone(messageContentObject); retval.unrecognizedHeaders = this.unrecognizedHeaders; - retval.remoteAddress = this.remoteAddress; - retval.remotePort = this.remotePort; return retval; } /** * Get the string representation of this header (for pretty printing the generated structure). - * + * * @return Formatted string representation of the object. Note that this is NOT the same as * encode(). This is used mainly for debugging purposes. */ @@ -580,7 +515,7 @@ public String debugDump() { String fieldName = f.getName(); if (f.get(this) != null && SIPHeader.class.isAssignableFrom(fieldType) && fieldName.compareTo("headers") != 0) { - sprint(fieldName + Separators.EQUALS); + sprint(fieldName + "="); sprint(((SIPHeader) f.get(this)).debugDump()); } } @@ -609,7 +544,7 @@ public String debugDump() { public SIPMessage() { this.unrecognizedHeaders = new LinkedList(); this.headers = new ConcurrentLinkedQueue(); - headerTable = new ConcurrentHashMap(); + nameTable = new Hashtable(); try { this.attachHeader(new ContentLength(0), false); } catch (Exception ex) { @@ -618,7 +553,7 @@ public SIPMessage() { /** * Attach a header and die if you get a duplicate header exception. - * + * * @param h SIPHeader to attach. */ private void attachHeader(SIPHeader h) { @@ -639,7 +574,7 @@ private void attachHeader(SIPHeader h) { /** * Attach a header (replacing the original header). - * + * * @param sipHeader SIPHeader that replaces a header of the same type. */ public void setHeader(Header sipHeader) { @@ -662,7 +597,7 @@ public void setHeader(Header sipHeader) { /** * Set a header from a linked list of headers. - * + * * @param headers -- a list of headers to set. */ public void setHeaders(java.util.List headers) { @@ -680,7 +615,7 @@ public void setHeaders(java.util.List headers) { * Attach a header to the end of the existing headers in this SIPMessage structure. This is * equivalent to the attachHeader(SIPHeader,replaceflag,false); which is the normal way in * which headers are attached. This was added in support of JAIN-SIP. - * + * * @param h header to attach. * @param replaceflag if true then replace a header if it exists. * @throws SIPDuplicateHeaderException If replaceFlag is false and only a singleton header is @@ -693,7 +628,7 @@ public void attachHeader(SIPHeader h, boolean replaceflag) throws SIPDuplicateHe /** * Attach the header to the SIP Message structure at a specified position in its list of * headers. - * + * * @param header Header to attach. * @param replaceFlag If true then replace the existing header. * @param top Location in the header list to insert the header. @@ -721,8 +656,8 @@ public void attachHeader(SIPHeader header, boolean replaceFlag, boolean top) String headerNameLowerCase = SIPHeaderNamesCache.toLowerCase(h.getName()); if (replaceFlag) { - headerTable.remove(headerNameLowerCase); - } else if (headerTable.containsKey(headerNameLowerCase) && !(h instanceof SIPHeaderList)) { + nameTable.remove(headerNameLowerCase); + } else if (nameTable.containsKey(headerNameLowerCase) && !(h instanceof SIPHeaderList)) { if (h instanceof ContentLength) { try { ContentLength cl = (ContentLength) h; @@ -747,19 +682,19 @@ public void attachHeader(SIPHeader header, boolean replaceFlag, boolean top) } } - if (!headerTable.containsKey(headerNameLowerCase)) { - headerTable.put(headerNameLowerCase, h); + if (!nameTable.containsKey(headerNameLowerCase)) { + nameTable.put(headerNameLowerCase, h); headers.add(h); } else { if (h instanceof SIPHeaderList) { - SIPHeaderList< ? > hdrlist = (SIPHeaderList< ? >) headerTable + SIPHeaderList< ? > hdrlist = (SIPHeaderList< ? >) nameTable .get(headerNameLowerCase); if (hdrlist != null) hdrlist.concatenate((SIPHeaderList) h, top); else - headerTable.put(headerNameLowerCase, h); + nameTable.put(headerNameLowerCase, h); } else { - headerTable.put(headerNameLowerCase, h); + nameTable.put(headerNameLowerCase, h); } } @@ -783,14 +718,14 @@ public void attachHeader(SIPHeader header, boolean replaceFlag, boolean top) /** * Remove a header given its name. If multiple headers of a given name are present then the * top flag determines which end to remove headers from. - * + * * @param headerName is the name of the header to remove. * @param top -- flag that indicates which end of header list to process. */ public void removeHeader(String headerName, boolean top) { String headerNameLowerCase = SIPHeaderNamesCache.toLowerCase(headerName); - SIPHeader toRemove = (SIPHeader) headerTable.get(headerNameLowerCase); + SIPHeader toRemove = (SIPHeader) nameTable.get(headerNameLowerCase); // nothing to do then we are done. if (toRemove == null) return; @@ -811,10 +746,10 @@ public void removeHeader(String headerName, boolean top) { // JvB: also remove it from the nameTable! Else NPE in // DefaultRouter - headerTable.remove(headerNameLowerCase); + nameTable.remove(headerNameLowerCase); } } else { - this.headerTable.remove(headerNameLowerCase); + this.nameTable.remove(headerNameLowerCase); if (toRemove instanceof From) { this.fromHeader = null; } else if (toRemove instanceof To) { @@ -840,7 +775,7 @@ public void removeHeader(String headerName, boolean top) { /** * Remove all headers given its name. - * + * * @param headerName is the name of the header to remove. */ public void removeHeader(String headerName) { @@ -848,7 +783,7 @@ public void removeHeader(String headerName) { if (headerName == null) throw new NullPointerException("null arg"); String headerNameLowerCase = SIPHeaderNamesCache.toLowerCase(headerName); - SIPHeader removed = (SIPHeader) headerTable.remove(headerNameLowerCase); + SIPHeader removed = (SIPHeader) nameTable.remove(headerNameLowerCase); // nothing to do then we are done. if (removed == null) return; @@ -879,7 +814,7 @@ public void removeHeader(String headerName) { /** * Generate (compute) a transaction ID for this SIP message. - * + * * @return A string containing the concatenation of various portions of the From,To,Via and * RequestURI portions of this message as specified in RFC 2543: All responses to a * request contain the same values in the Call-ID, CSeq, To, and From fields (with the @@ -888,16 +823,16 @@ public void removeHeader(String headerName) { * Ledgard of IPera for generating transactionIDs when no port is present in the via * header. Incorporates a bug fix for a bug report sent in by Chris Mills of Nortel * Networks (converts to lower case when returning the transaction identifier). - * + * * @return a string that can be used as a transaction identifier for this message. This can be * used for matching responses and requests (i.e. an outgoing request and its matching * response have the same computed transaction identifier). */ public String getTransactionId() { - Via topVia = getTopmostVia(); -// if (!this.getViaHeaders().isEmpty()) { -// topVia = (Via) this.getViaHeaders().getFirst(); -// } + Via topVia = null; + if (!this.getViaHeaders().isEmpty()) { + topVia = (Via) this.getViaHeaders().getFirst(); + } // Have specified a branch Identifier so we can use it to identify // the transaction. BranchId is not case sensitive. // Branch Id prefix is not case sensitive. @@ -915,7 +850,7 @@ public String getTransactionId() { } else { // Old style client so construct the transaction identifier // from various fields of the request. - StringBuilder retval = new StringBuilder(); + StringBuffer retval = new StringBuffer(); From from = (From) this.getFrom(); To to = (To) this.getTo(); // String hpFrom = from.getUserAtHostPort(); @@ -964,7 +899,7 @@ public boolean hasContent() { /** * Return an iterator for the list of headers in this message. - * + * * @return an Iterator for the headers of this message. */ public Iterator getHeaders() { @@ -973,17 +908,17 @@ public Iterator getHeaders() { /** * Get the first header of the given name. - * + * * @return header -- the first header of the given name. */ public Header getHeader(String headerName) { return getHeaderLowerCase(SIPHeaderNamesCache.toLowerCase(headerName)); } - protected Header getHeaderLowerCase(String lowerCaseHeaderName) { + private Header getHeaderLowerCase(String lowerCaseHeaderName) { if (lowerCaseHeaderName == null) throw new NullPointerException("bad name"); - SIPHeader sipHeader = (SIPHeader) headerTable.get(lowerCaseHeaderName); + SIPHeader sipHeader = (SIPHeader) nameTable.get(lowerCaseHeaderName); if (sipHeader instanceof SIPHeaderList) return (Header) ((SIPHeaderList) sipHeader).getFirst(); else @@ -992,18 +927,18 @@ protected Header getHeaderLowerCase(String lowerCaseHeaderName) { /** * Get the contentType header (null if one does not exist). - * + * * @return contentType header */ - + public ContentType getContentTypeHeader() { return (ContentType) getHeaderLowerCase(CONTENT_TYPE_LOWERCASE); } - + private static final String CONTENT_TYPE_LOWERCASE = SIPHeaderNamesCache .toLowerCase(ContentTypeHeader.NAME); - + /** * Get the contentLength header. */ @@ -1011,10 +946,10 @@ public ContentLengthHeader getContentLengthHeader() { return this.getContentLength(); } - + /** * Get the from header. - * + * * @return -- the from header. */ public FromHeader getFrom() { @@ -1023,7 +958,7 @@ public FromHeader getFrom() { /** * Get the ErrorInfo list of headers (null if one does not exist). - * + * * @return List containing ErrorInfo headers. */ public ErrorInfoList getErrorInfoHeaders() { @@ -1034,7 +969,7 @@ public ErrorInfoList getErrorInfoHeaders() { /** * Get the Contact list of headers (null if one does not exist). - * + * * @return List containing Contact headers. */ public ContactList getContactHeaders() { @@ -1046,7 +981,7 @@ public ContactList getContactHeaders() { /** * Get the contact header ( the first contact header) which is all we need for the most part. - * + * */ public Contact getContactHeader() { ContactList clist = this.getContactHeaders(); @@ -1060,7 +995,7 @@ public Contact getContactHeader() { /** * Get the Via list of headers (null if one does not exist). - * + * * @return List containing Via headers. */ public ViaList getViaHeaders() { @@ -1071,7 +1006,7 @@ public ViaList getViaHeaders() { /** * Set A list of via headers. - * + * * @param viaList a list of via headers to add. */ public void setVia(java.util.List viaList) { @@ -1086,7 +1021,7 @@ public void setVia(java.util.List viaList) { /** * Set the header given a list of headers. - * + * * @param sipHeaderList a headerList to set */ @@ -1096,7 +1031,7 @@ public void setHeader(SIPHeaderList sipHeaderList) { /** * Get the topmost via header. - * + * * @return the top most via header if one exists or null if none exists. */ public Via getTopmostVia() { @@ -1108,7 +1043,7 @@ public Via getTopmostVia() { /** * Get the CSeq list of header (null if one does not exist). - * + * * @return CSeq header */ public CSeqHeader getCSeq() { @@ -1117,7 +1052,7 @@ public CSeqHeader getCSeq() { /** * Get the Authorization header (null if one does not exist). - * + * * @return Authorization header. */ public Authorization getAuthorization() { @@ -1129,7 +1064,7 @@ public Authorization getAuthorization() { /** * Get the MaxForwards header (null if one does not exist). - * + * * @return Max-Forwards header */ @@ -1139,7 +1074,7 @@ public MaxForwardsHeader getMaxForwards() { /** * Set the max forwards header. - * + * * @param maxForwards is the MaxForwardsHeader to set. */ public void setMaxForwards(MaxForwardsHeader maxForwards) { @@ -1148,7 +1083,7 @@ public void setMaxForwards(MaxForwardsHeader maxForwards) { /** * Get the Route List of headers (null if one does not exist). - * + * * @return List containing Route headers */ public RouteList getRouteHeaders() { @@ -1160,7 +1095,7 @@ public RouteList getRouteHeaders() { /** * Get the CallID header (null if one does not exist) - * + * * @return Call-ID header . */ public CallIdHeader getCallId() { @@ -1169,7 +1104,7 @@ public CallIdHeader getCallId() { /** * Set the call id header. - * + * * @param callId call idHeader (what else could it be?) */ public void setCallId(CallIdHeader callId) { @@ -1178,7 +1113,7 @@ public void setCallId(CallIdHeader callId) { /** * Get the CallID header (null if one does not exist) - * + * * @param callId -- the call identifier to be assigned to the call id header */ public void setCallId(String callId) throws java.text.ParseException { @@ -1190,7 +1125,7 @@ public void setCallId(String callId) throws java.text.ParseException { /** * Get the RecordRoute header list (null if one does not exist). - * + * * @return Record-Route header */ public RecordRouteList getRecordRouteHeaders() { @@ -1202,7 +1137,7 @@ public RecordRouteList getRecordRouteHeaders() { /** * Get the To header (null if one does not exist). - * + * * @return To header */ public ToHeader getTo() { @@ -1220,7 +1155,7 @@ public void setFrom(FromHeader from) { /** * Get the ContentLength header (null if one does not exist). - * + * * @return content-length header. */ public ContentLengthHeader getContentLength() { @@ -1231,11 +1166,11 @@ public ContentLengthHeader getContentLength() { * Get the message body as a string. If the message contains a content type header with a * specified charset, and if the payload has been read as a byte array, then it is returned * encoded into this charset. - * + * * @return Message body (as a string) * @throws UnsupportedEncodingException if the platform does not support the charset specified * in the content type header. - * + * */ public String getMessageContent() throws UnsupportedEncodingException { if (this.messageContent == null && this.messageContentBytes == null) @@ -1250,7 +1185,7 @@ else if (this.messageContent == null) { * Get the message content as an array of bytes. If the payload has been read as a String then * it is decoded using the charset specified in the content type header if it exists. * Otherwise, it is encoded using the default encoding which is UTF-8. - * + * * @return an array of bytes that is the message payload. */ public byte[] getRawContent() { @@ -1261,7 +1196,7 @@ public byte[] getRawContent() { String messageContent = this.messageContentObject.toString(); this.messageContentBytes = messageContent.getBytes( getCharset() ); } else if (this.messageContent != null) { - this.messageContentBytes = messageContent.getBytes( getCharset() ); + this.messageContentBytes = messageContent.getBytes( getCharset() ); } return this.messageContentBytes; } catch (UnsupportedEncodingException ex) { @@ -1272,7 +1207,7 @@ public byte[] getRawContent() { /** * Set the message content given type and subtype. - * + * * @param type is the message type (eg. application) * @param subType is the message sybtype (eg. sdp) * @param messageContent is the messge content as a string. @@ -1292,7 +1227,7 @@ public void setMessageContent(String type, String subType, String messageContent /** * Set the message content after converting the given object to a String. - * + * * @param content -- content to set. * @param contentTypeHeader -- content type header corresponding to content. */ @@ -1318,7 +1253,7 @@ public void setContent(Object content, ContentTypeHeader contentTypeHeader) /** * Get the content (body) of the message. - * + * * @return the content of the sip message. */ public Object getContent() { @@ -1334,7 +1269,7 @@ else if (this.messageContentBytes != null) /** * Set the message content for a given type and subtype. - * + * * @param type is the messge type. * @param subType is the message subType. * @param messageContent is the message content as a byte array. @@ -1349,30 +1284,30 @@ public void setMessageContent(String type, String subType, byte[] messageContent /** * Set the message content for this message. - * + * * @param content Message body as a string. */ - public void setMessageContent(byte[] content, boolean strict, boolean computeContentLength, int givenLength) + public void setMessageContent(String content, boolean strict, boolean computeContentLength, int givenLength) throws ParseException { // Note that that this could be a double byte character // set - bug report by Masafumi Watanabe computeContentLength(content); if ((!computeContentLength)) { - if ( (!strict && this.contentLengthHeader.getContentLength() != givenLength) + if ( (!strict && this.contentLengthHeader.getContentLength() != givenLength) || this.contentLengthHeader.getContentLength() < givenLength) { throw new ParseException("Invalid content length " + this.contentLengthHeader.getContentLength() + " / " + givenLength, 0); } } - messageContent = null; - messageContentBytes = content; + messageContent = content; + messageContentBytes = null; messageContentObject = null; } /** * Set the message content as an array of bytes. - * + * * @param content is the content of the message as an array of bytes. */ public void setMessageContent(byte[] content) { @@ -1385,7 +1320,7 @@ public void setMessageContent(byte[] content) { /** * Method to set the content - called by the parser - * + * * @param content * @throws ParseException */ @@ -1404,7 +1339,7 @@ public void setMessageContent(byte[] content, boolean computeContentLength, int /** * Compute and set the Content-length header based on the given content object. - * + * * @param content is the content, as String, array of bytes, or other object. */ private void computeContentLength(Object content) { @@ -1445,7 +1380,7 @@ public void removeContent() { /** * Get a SIP header or Header list given its name. - * + * * @param headerName is the name of the header to get. * @return a header or header list that contians the retrieved header. */ @@ -1453,7 +1388,7 @@ public void removeContent() { public ListIterator getHeaders(String headerName) { if (headerName == null) throw new NullPointerException("null headerName"); - SIPHeader sipHeader = (SIPHeader) headerTable.get(SIPHeaderNamesCache + SIPHeader sipHeader = (SIPHeader) nameTable.get(SIPHeaderNamesCache .toLowerCase(headerName)); // empty iterator if (sipHeader == null) @@ -1468,32 +1403,32 @@ public ListIterator getHeaders(String headerName) { /** * Get a header of the given name as a string. This concatenates the headers of a given type * as a comma separted list. This is useful for formatting and printing headers. - * + * * @param name * @return the header as a formatted string */ public String getHeaderAsFormattedString(String name) { - String lowerCaseName = SIPHeaderNamesCache.toLowerCase(name); - if (this.headerTable.containsKey(lowerCaseName)) { - return this.headerTable.get(lowerCaseName).toString(); + String lowerCaseName = name.toLowerCase(); + if (this.nameTable.containsKey(lowerCaseName)) { + return this.nameTable.get(lowerCaseName).toString(); } else { return this.getHeader(name).toString(); } } - public SIPHeader getSIPHeaderListLowerCase(String lowerCaseHeaderName) { - return headerTable.get(lowerCaseHeaderName); + protected SIPHeader getSIPHeaderListLowerCase(String lowerCaseHeaderName) { + return nameTable.get(lowerCaseHeaderName); } /** * Get a list of headers of the given name ( or null if no such header exists ). - * + * * @param headerName -- a header name from which to retrieve the list. * @return -- a list of headers with that name. */ @SuppressWarnings("unchecked") private List getHeaderList(String headerName) { - SIPHeader sipHeader = (SIPHeader) headerTable.get(SIPHeaderNamesCache + SIPHeader sipHeader = (SIPHeader) nameTable.get(SIPHeaderNamesCache .toLowerCase(headerName)); if (sipHeader == null) return null; @@ -1508,17 +1443,17 @@ else if (sipHeader instanceof SIPHeaderList) /** * Return true if the SIPMessage has a header of the given name. - * + * * @param headerName is the header name for which we are testing. * @return true if the header is present in the message */ public boolean hasHeader(String headerName) { - return headerTable.containsKey(SIPHeaderNamesCache.toLowerCase(headerName)); + return nameTable.containsKey(SIPHeaderNamesCache.toLowerCase(headerName)); } /** * Return true if the message has a From header tag. - * + * * @return true if the message has a from header and that header has a tag. */ public boolean hasFromTag() { @@ -1527,7 +1462,7 @@ public boolean hasFromTag() { /** * Return true if the message has a To header tag. - * + * * @return true if the message has a to header and that header has a tag. */ public boolean hasToTag() { @@ -1536,9 +1471,9 @@ public boolean hasToTag() { /** * Return the from tag. - * + * * @return the tag from the from header. - * + * */ public String getFromTag() { return fromHeader == null ? null : fromHeader.getTag(); @@ -1546,7 +1481,7 @@ public String getFromTag() { /** * Set the From Tag. - * + * * @param tag -- tag to set in the from header. */ public void setFromTag(String tag) { @@ -1558,7 +1493,7 @@ public void setFromTag(String tag) { /** * Set the to tag. - * + * * @param tag -- tag to set. */ public void setToTag(String tag) { @@ -1582,7 +1517,7 @@ public String getToTag() { /** * Add a SIP header. - * + * * @param sipHeader -- sip header to add. */ public void addHeader(Header sipHeader) { @@ -1607,16 +1542,16 @@ public void addHeader(Header sipHeader) { /** * Add a header to the unparsed list of headers. - * + * * @param unparsed -- unparsed header to add to the list. */ public void addUnparsed(String unparsed) { - this.getUnrecognizedHeadersList().add(unparsed); + this.unrecognizedHeaders.add(unparsed); } /** * Add a SIP header. - * + * * @param sipHeader -- string version of SIP header to add. */ @@ -1627,22 +1562,22 @@ public void addHeader(String sipHeader) { SIPHeader sh = parser.parse(); this.attachHeader(sh, false); } catch (ParseException ex) { - this.getUnrecognizedHeadersList().add(hdrString); + this.unrecognizedHeaders.add(hdrString); } } /** * Get a list containing the unrecognized headers. - * + * * @return a linked list containing unrecongnized headers. */ public ListIterator getUnrecognizedHeaders() { - return this.getUnrecognizedHeadersList().listIterator(); + return this.unrecognizedHeaders.listIterator(); } /** * Get the header names. - * + * * @return a list iterator to a list of header names. These are ordered in the same order as * are present in the message. */ @@ -1659,7 +1594,7 @@ public ListIterator getHeaderNames() { /** * Compare for equality. - * + * * @param other -- the other object to compare with. */ public boolean equals(Object other) { @@ -1667,15 +1602,15 @@ public boolean equals(Object other) { return false; } SIPMessage otherMessage = (SIPMessage) other; - Collection values = this.headerTable.values(); + Collection values = this.nameTable.values(); Iterator it = values.iterator(); - if (headerTable.size() != otherMessage.headerTable.size()) { + if (nameTable.size() != otherMessage.nameTable.size()) { return false; } while (it.hasNext()) { SIPHeader mine = (SIPHeader) it.next(); - SIPHeader his = (SIPHeader) (otherMessage.headerTable.get(SIPHeaderNamesCache + SIPHeader his = (SIPHeader) (otherMessage.nameTable.get(SIPHeaderNamesCache .toLowerCase(mine.getName()))); if (his == null) { return false; @@ -1688,7 +1623,7 @@ public boolean equals(Object other) { /** * get content disposition header or null if no such header exists. - * + * * @return the contentDisposition header */ public javax.sip.header.ContentDispositionHeader getContentDisposition() { @@ -1700,7 +1635,7 @@ public javax.sip.header.ContentDispositionHeader getContentDisposition() { /** * get the content encoding header. - * + * * @return the contentEncoding header. */ public javax.sip.header.ContentEncodingHeader getContentEncoding() { @@ -1712,7 +1647,7 @@ public javax.sip.header.ContentEncodingHeader getContentEncoding() { /** * Get the contentLanguage header. - * + * * @return the content language header. */ public javax.sip.header.ContentLanguageHeader getContentLanguage() { @@ -1724,7 +1659,7 @@ public javax.sip.header.ContentLanguageHeader getContentLanguage() { /** * Get the exipres header. - * + * * @return the expires header or null if one does not exist. */ public javax.sip.header.ExpiresHeader getExpires() { @@ -1736,7 +1671,7 @@ public javax.sip.header.ExpiresHeader getExpires() { /** * Set the expiresHeader - * + * * @param expiresHeader -- the expires header to set. */ @@ -1746,7 +1681,7 @@ public void setExpires(ExpiresHeader expiresHeader) { /** * Set the content disposition header. - * + * * @param contentDispositionHeader -- content disposition header. */ @@ -1766,7 +1701,7 @@ public void setContentLanguage(ContentLanguageHeader contentLanguageHeader) { /** * Set the content length header. - * + * * @param contentLength -- content length header. */ public void setContentLength(ContentLengthHeader contentLength) { @@ -1779,7 +1714,7 @@ public void setContentLength(ContentLengthHeader contentLength) { /** * Set the size of all the headers. This is for book keeping. Called by the parser. - * + * * @param size -- size of the headers. */ public void setSize(int size) { @@ -1792,7 +1727,7 @@ public int getSize() { /* * (non-Javadoc) - * + * * @see javax.sip.message.Message#addLast(javax.sip.header.Header) */ public void addLast(Header header) throws SipException, NullPointerException { @@ -1809,7 +1744,7 @@ public void addLast(Header header) throws SipException, NullPointerException { /* * (non-Javadoc) - * + * * @see javax.sip.message.Message#addFirst(javax.sip.header.Header) */ public void addFirst(Header header) throws SipException, NullPointerException { @@ -1827,7 +1762,7 @@ public void addFirst(Header header) throws SipException, NullPointerException { /* * (non-Javadoc) - * + * * @see javax.sip.message.Message#removeFirst(java.lang.String) */ public void removeFirst(String headerName) throws NullPointerException { @@ -1839,7 +1774,7 @@ public void removeFirst(String headerName) throws NullPointerException { /* * (non-Javadoc) - * + * * @see javax.sip.message.Message#removeLast(java.lang.String) */ public void removeLast(String headerName) { @@ -1851,7 +1786,7 @@ public void removeLast(String headerName) { /** * Set the CSeq header. - * + * * @param cseqHeader -- CSeq Header. */ @@ -1863,7 +1798,7 @@ public void setCSeq(CSeqHeader cseqHeader) { * Set the application data pointer. This method is not used the stack. It is provided as a * convenient way of storing book-keeping data for applications. Note that null clears the * application data pointer (releases it). - * + * * @param applicationData -- application data pointer to set. null clears the application data * pointer. */ @@ -1873,7 +1808,7 @@ public void setApplicationData(Object applicationData) { /** * Get the application data associated with this message. - * + * * @return stored application data. */ public Object getApplicationData() { @@ -1882,7 +1817,7 @@ public Object getApplicationData() { /** * Get the multipart MIME content - * + * */ public MultipartMimeContent getMultipartMimeContent() throws ParseException { if (this.contentLengthHeader.getContentLength() == 0) { @@ -1891,62 +1826,62 @@ public MultipartMimeContent getMultipartMimeContent() throws ParseException { MultipartMimeContentImpl retval = new MultipartMimeContentImpl(this .getContentTypeHeader()); byte[] rawContent = getRawContent(); - try { - String body = new String( rawContent, getCharset() ); - retval.createContentList(body); - return retval; - } catch (UnsupportedEncodingException e) { - InternalErrorHandler.handleException(e); - return null; - } - } - + try { + String body = new String( rawContent, getCharset() ); + retval.createContentList(body); + return retval; + } catch (UnsupportedEncodingException e) { + InternalErrorHandler.handleException(e); + return null; + } + } + public CallIdHeader getCallIdHeader() { return this.callIdHeader; } - + public FromHeader getFromHeader() { return this.fromHeader; } - + public ToHeader getToHeader() { return this.toHeader; } - + public ViaHeader getTopmostViaHeader() { return this.getTopmostVia(); } - + public CSeqHeader getCSeqHeader() { return this.cSeqHeader; } - + /** * Returns the charset to use for encoding/decoding the body of this message */ protected final String getCharset() { - ContentType ct = getContentTypeHeader(); - if (ct!=null) { - String c = ct.getCharset(); - return c!=null ? c : contentEncodingCharset; - } else return contentEncodingCharset; + ContentType ct = getContentTypeHeader(); + if (ct!=null) { + String c = ct.getCharset(); + return c!=null ? c : contentEncodingCharset; + } else return contentEncodingCharset; } - + /** * Return true if this is a null request (i.e. does not have a request line ). - * + * * @return true if null request. */ public boolean isNullRequest() { return this.nullRequest; } - + /** * Set a flag to indiate this is a special message ( encoded with CRLFCRLF ). - * + * */ public void setNullRequest() { this.nullRequest = true; @@ -1964,87 +1899,11 @@ public String getForkId() { return this.forkId; } } - + public abstract void setSIPVersion(String sipVersion) throws ParseException; public abstract String getSIPVersion(); public abstract String toString(); - public void cleanUp() { -// callIdHeader = null; -// contentEncodingCharset = null; -// contentLengthHeader = null; -// cSeqHeader = null; -// forkId = null; -// fromHeader = null; -// if(headers != null) { -// headers.clear(); -// headers = null; -// } -// matchExpression = null; -// maxForwardsHeader = null; -// messageContent = null; -// messageContentBytes = null; -// messageContentObject = null; -// if(nameTable != null) { -// nameTable.clear(); -// nameTable = null; -// } -// stringRepresentation = null; -// toHeader = null; -// if(unrecognizedHeaders != null) { -// unrecognizedHeaders.clear(); -// unrecognizedHeaders = null; -// } - } - - /** - * @param unrecognizedHeaders the unrecognizedHeaders to set - */ - protected void setUnrecognizedHeadersList(LinkedList unrecognizedHeaders) { - this.unrecognizedHeaders = unrecognizedHeaders; - } - - /** - * @return the unrecognizedHeaders - */ - protected LinkedList getUnrecognizedHeadersList() { - if(unrecognizedHeaders == null) { - unrecognizedHeaders = new LinkedList(); - } - return unrecognizedHeaders; - } - - public void setRemoteAddress(InetAddress remoteAddress) { - this.remoteAddress = remoteAddress; - } - - public InetAddress getRemoteAddress() { - return remoteAddress; - } - - public void setRemotePort(int remotePort) { - this.remotePort = remotePort; - } - - public int getRemotePort() { - return remotePort; - } - - public void setLocalAddress(InetAddress localAddress) { - this.localAddress = localAddress; - } - - public InetAddress getLocalAddress() { - return localAddress; - } - - public void setLocalPort(int localPort) { - this.localPort = localPort; - } - - public int getLocalPort() { - return localPort; - } } diff --git a/src/gov/nist/javax/sip/message/SIPRequest.java b/src/gov/nist/javax/sip/message/SIPRequest.java index 2ba3eb614..3da180bbe 100755 --- a/src/gov/nist/javax/sip/message/SIPRequest.java +++ b/src/gov/nist/javax/sip/message/SIPRequest.java @@ -28,47 +28,24 @@ *******************************************************************************/ package gov.nist.javax.sip.message; -import gov.nist.core.InternalErrorHandler; -import gov.nist.javax.sip.address.GenericURI; -import gov.nist.javax.sip.address.SipUri; -import gov.nist.javax.sip.header.CSeq; -import gov.nist.javax.sip.header.RecordRouteList; -import gov.nist.javax.sip.header.RequestLine; -import gov.nist.javax.sip.header.SIPHeader; -import gov.nist.javax.sip.header.SIPHeaderList; -import gov.nist.javax.sip.header.To; -import gov.nist.javax.sip.header.Via; -import gov.nist.javax.sip.header.ViaList; -import gov.nist.javax.sip.stack.SIPTransactionStack; +import gov.nist.javax.sip.address.*; +import gov.nist.core.*; -import java.io.UnsupportedEncodingException; -import java.text.ParseException; import java.util.HashSet; +import java.util.Hashtable; import java.util.LinkedList; -import java.util.Map; import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -import javax.sip.SipException; +import java.io.UnsupportedEncodingException; +import java.util.Iterator; import javax.sip.address.URI; -import javax.sip.header.CSeqHeader; -import javax.sip.header.CallIdHeader; -import javax.sip.header.ContactHeader; -import javax.sip.header.ContentTypeHeader; -import javax.sip.header.EventHeader; -import javax.sip.header.ExpiresHeader; -import javax.sip.header.FromHeader; -import javax.sip.header.Header; -import javax.sip.header.MaxForwardsHeader; -import javax.sip.header.ProxyAuthorizationHeader; -import javax.sip.header.RecordRouteHeader; -import javax.sip.header.RouteHeader; -import javax.sip.header.ServerHeader; -import javax.sip.header.SubscriptionStateHeader; -import javax.sip.header.TimeStampHeader; -import javax.sip.header.ToHeader; -import javax.sip.header.ViaHeader; -import javax.sip.message.Request; +import javax.sip.message.*; + +import java.text.ParseException; +import javax.sip.*; +import javax.sip.header.*; + +import gov.nist.javax.sip.header.*; +import gov.nist.javax.sip.stack.SIPTransactionStack; /* * Acknowledgements: Mark Bednarek made a few fixes to this code. Jeff Keyser added two methods @@ -84,7 +61,7 @@ /** * The SIP Request structure. * - * @version 1.2 $Revision: 1.57 $ $Date: 2010-09-17 20:06:57 $ + * @version 1.2 $Revision: 1.53 $ $Date: 2010-03-15 17:01:24 $ * @since 1.1 * * @author M. Ranganathan
    @@ -103,7 +80,7 @@ public class SIPRequest extends SIPMessage implements javax.sip.message.Request, private transient Object transactionPointer; - protected RequestLine requestLine; + private RequestLine requestLine; private transient Object messageChannel; @@ -122,12 +99,8 @@ public class SIPRequest extends SIPMessage implements javax.sip.message.Request, /* * A table that maps a name string to its cannonical constant. This is used to speed up * parsing of messages .equals reduces to == if we use the constant value. - * - * jeand : Setting the capacity to save on memory since the capacity here will never change */ - private static final Map nameTable = new ConcurrentHashMap(15); - - protected static final Set headersToIncludeInResponse = new HashSet(0); + private static final Hashtable nameTable = new Hashtable(); private static void putName(String name) { nameTable.put(name, name); @@ -156,13 +129,6 @@ private static void putName(String name) { putName(Request.SUBSCRIBE); putName(Request.UPDATE); - headersToIncludeInResponse.add(FromHeader.NAME.toLowerCase()); - headersToIncludeInResponse.add(ToHeader.NAME.toLowerCase()); - headersToIncludeInResponse.add(ViaHeader.NAME.toLowerCase()); - headersToIncludeInResponse.add(RecordRouteHeader.NAME.toLowerCase()); - headersToIncludeInResponse.add(CallIdHeader.NAME.toLowerCase()); - headersToIncludeInResponse.add(CSeqHeader.NAME.toLowerCase()); - headersToIncludeInResponse.add(TimeStampHeader.NAME.toLowerCase()); } /** @@ -304,7 +270,9 @@ public void checkHeaders() throws ParseException { * header field MUST contain a SIPS URI as well. */ final String method = requestLine.getMethod(); - if (SIPTransactionStack.isDialogCreated(method)) { + if (method.equals(Request.INVITE) + || method.equals(Request.SUBSCRIBE) + || method.equals(Request.REFER)) { if (this.getContactHeader() == null) { // Make sure this is not a target refresh. If this is a target // refresh its ok not to have a contact header. Otherwise @@ -327,11 +295,12 @@ public void checkHeaders() throws ParseException { /* * Contact header is mandatory for a SIP INVITE request. */ - /* emmartins: dupe logic, see above - if (this.getContactHeader() == null - && SIPTransactionStack.isDialogCreated(method)) { + if (this.getContactHeader() == null + && (this.getMethod().equals(Request.INVITE) + || this.getMethod().equals(Request.REFER) || this.getMethod().equals( + Request.SUBSCRIBE))) { throw new ParseException("Contact Header is Mandatory for a SIP INVITE", 0); - }*/ + } if (requestLine != null && method != null && getCSeq().getMethod() != null @@ -478,15 +447,15 @@ public String encode() { /** * Encode only the headers and not the content. */ - public StringBuilder encodeMessage(StringBuilder retval) { + public String encodeMessage() { + String retval; if (requestLine != null) { this.setRequestLineDefaults(); - requestLine.encode(retval); - encodeSIPHeaders(retval); + retval = requestLine.encode() + super.encodeSIPHeaders(); } else if (this.isNullRequest()) { - retval.append("\r\n\r\n"); + retval = "\r\n\r\n"; } else - retval = encodeSIPHeaders(retval); + retval = super.encodeSIPHeaders(); return retval; } @@ -570,6 +539,76 @@ else if (this.requestLine == rline) } + /** + * Get a dialog identifier. Generates a string that can be used as a dialog identifier. + * + * @param isServer is set to true if this is the UAS and set to false if this is the UAC + */ + public String getDialogId(boolean isServer) { + CallID cid = (CallID) this.getCallId(); + StringBuffer retval = new StringBuffer(cid.getCallId()); + From from = (From) this.getFrom(); + To to = (To) this.getTo(); + if (!isServer) { + // retval.append(COLON).append(from.getUserAtHostPort()); + if (from.getTag() != null) { + retval.append(COLON); + retval.append(from.getTag()); + } + // retval.append(COLON).append(to.getUserAtHostPort()); + if (to.getTag() != null) { + retval.append(COLON); + retval.append(to.getTag()); + } + } else { + // retval.append(COLON).append(to.getUserAtHostPort()); + if (to.getTag() != null) { + retval.append(COLON); + retval.append(to.getTag()); + } + // retval.append(COLON).append(from.getUserAtHostPort()); + if (from.getTag() != null) { + retval.append(COLON); + retval.append(from.getTag()); + } + } + return retval.toString().toLowerCase(); + + } + + /** + * Get a dialog id given the remote tag. + */ + public String getDialogId(boolean isServer, String toTag) { + From from = (From) this.getFrom(); + CallID cid = (CallID) this.getCallId(); + StringBuffer retval = new StringBuffer(cid.getCallId()); + if (!isServer) { + // retval.append(COLON).append(from.getUserAtHostPort()); + if (from.getTag() != null) { + retval.append(COLON); + retval.append(from.getTag()); + } + // retval.append(COLON).append(to.getUserAtHostPort()); + if (toTag != null) { + retval.append(COLON); + retval.append(toTag); + } + } else { + // retval.append(COLON).append(to.getUserAtHostPort()); + if (toTag != null) { + retval.append(COLON); + retval.append(toTag); + } + // retval.append(COLON).append(from.getUserAtHostPort()); + if (from.getTag() != null) { + retval.append(COLON); + retval.append(from.getTag()); + } + } + return retval.toString().toLowerCase(); + } + /** * Encode this into a byte array. This is used when the body has been set as a binary array * and you want to encode the body as a byte array for transmission. @@ -641,8 +680,8 @@ public SIPResponse createResponse(int statusCode) { public SIPResponse createResponse(int statusCode, String reasonPhrase) { SIPResponse newResponse; -// Iterator headerIterator; -// SIPHeader nextHeader; + Iterator headerIterator; + SIPHeader nextHeader; newResponse = new SIPResponse(); try { @@ -654,55 +693,35 @@ public SIPResponse createResponse(int statusCode, String reasonPhrase) { newResponse.setReasonPhrase(reasonPhrase); else newResponse.setReasonPhrase(SIPResponse.getReasonPhrase(statusCode)); - -// headerIterator = getHeaders(); -// while (headerIterator.hasNext()) { -// nextHeader = (SIPHeader) headerIterator.next(); -// if (nextHeader instanceof From -// || nextHeader instanceof To -// || nextHeader instanceof ViaList -// || nextHeader instanceof CallID -// || (nextHeader instanceof RecordRouteList && mustCopyRR(statusCode)) -// || nextHeader instanceof CSeq -// // We just copy TimeStamp for all headers (not just 100). -// || nextHeader instanceof TimeStamp) { -// -// try { -// -// newResponse.attachHeader((SIPHeader) nextHeader.clone(), false); -// } catch (SIPDuplicateHeaderException e) { -// e.printStackTrace(); -// } -// } -// } - - // no need to iterate through all headers to create the response since we know which headers - // we only want to keep and helps the lazy parsing to avoid going through all headers - for(String headerName : headersToIncludeInResponse) { - SIPHeader nextHeader = headerTable.get(headerName); - if(nextHeader != null) { - if(!(nextHeader instanceof RecordRouteList) || (nextHeader instanceof RecordRouteList && mustCopyRR(statusCode))) { - try { - newResponse.attachHeader((SIPHeader) nextHeader.clone(), false); - } catch (SIPDuplicateHeaderException e) { - e.printStackTrace(); - } - } - } + headerIterator = getHeaders(); + while (headerIterator.hasNext()) { + nextHeader = (SIPHeader) headerIterator.next(); + if (nextHeader instanceof From + || nextHeader instanceof To + || nextHeader instanceof ViaList + || nextHeader instanceof CallID + || (nextHeader instanceof RecordRouteList && mustCopyRR(statusCode)) + || nextHeader instanceof CSeq + // We just copy TimeStamp for all headers (not just 100). + || nextHeader instanceof TimeStamp) { + + try { + + newResponse.attachHeader((SIPHeader) nextHeader.clone(), false); + } catch (SIPDuplicateHeaderException e) { + e.printStackTrace(); + } + } } - if (MessageFactoryImpl.getDefaultServerHeader() != null) { newResponse.setHeader(MessageFactoryImpl.getDefaultServerHeader()); } - // Commented out for Issue 305 : - // tag parameter in the To header in 100 Trying response for re-INVITE - // is needed - // Fix by Tomasz Zieleniewski -// if (newResponse.getStatusCode() == 100) { -// // Trying is never supposed to have the tag parameter set. -// newResponse.getTo().removeParameter("tag"); -// } + if (newResponse.getStatusCode() == 100) { + // Trying is never supposed to have the tag parameter set. + newResponse.getTo().removeParameter("tag"); + + } ServerHeader server = MessageFactoryImpl.getDefaultServerHeader(); if (server != null) { newResponse.setHeader(server); @@ -790,55 +809,75 @@ public SIPRequest createCancelRequest() throws SipException { * @return A SIPRequest with an ACK method. */ public SIPRequest createAckRequest(To responseToHeader) { -// SIPRequest newRequest; -// Iterator headerIterator; -// SIPHeader nextHeader; - - // cloning instead of iterating through headers so that lazy parsers don't have to parse the messages fully - // to create ACK requests - SIPRequest newRequest = (SIPRequest) this.clone(); -// newRequest = new SIPRequest(); -// newRequest.setRequestLine((RequestLine) this.requestLine.clone()); + SIPRequest newRequest; + Iterator headerIterator; + SIPHeader nextHeader; + + newRequest = new SIPRequest(); + newRequest.setRequestLine((RequestLine) this.requestLine.clone()); newRequest.setMethod(Request.ACK); - // Ack and cancel do not get ROUTE headers. - // Route header for ACK is assigned by the - // Dialog if necessary. - newRequest.removeHeader(RouteHeader.NAME); - // Remove proxy auth header. - // Assigned by the Dialog if necessary. - newRequest.removeHeader(ProxyAuthorizationHeader.NAME); - // Adding content is responsibility of user. - newRequest.removeContent(); - // Content type header is removed since - // content length is 0. - newRequest.removeHeader(ContentTypeHeader.NAME); - // The CSeq header field in the - // ACK MUST contain the same value for the - // sequence number as was present in the - // original request, but the method parameter - // MUST be equal to "ACK". - try{ - newRequest.getCSeq().setMethod(Request.ACK); - } catch (ParseException e) { - } - if (responseToHeader != null) { - newRequest.setTo(responseToHeader); - } - // CONTACT header does not apply for ACK requests. - newRequest.removeHeader(ContactHeader.NAME); - newRequest.removeHeader(ExpiresHeader.NAME); - ViaList via = newRequest.getViaHeaders(); - // Bug reported by Gianluca Martinello - // The ACK MUST contain a single Via header field, - // and this MUST be equal to the top Via header - // field of the original - // request. - if(via != null && via.size() > 1) { - for(int i = 2; i < via.size(); i++) { - via.remove(i); - } + headerIterator = getHeaders(); + while (headerIterator.hasNext()) { + nextHeader = (SIPHeader) headerIterator.next(); + if (nextHeader instanceof RouteList) { + // Ack and cancel do not get ROUTE headers. + // Route header for ACK is assigned by the + // Dialog if necessary. + continue; + } else if (nextHeader instanceof ProxyAuthorization) { + // Remove proxy auth header. + // Assigned by the Dialog if necessary. + continue; + } else if (nextHeader instanceof ContentLength) { + // Adding content is responsibility of user. + nextHeader = (SIPHeader) nextHeader.clone(); + try { + ((ContentLength) nextHeader).setContentLength(0); + } catch (InvalidArgumentException e) { + } + } else if (nextHeader instanceof ContentType) { + // Content type header is removed since + // content length is 0. + continue; + } else if (nextHeader instanceof CSeq) { + // The CSeq header field in the + // ACK MUST contain the same value for the + // sequence number as was present in the + // original request, but the method parameter + // MUST be equal to "ACK". + CSeq cseq = (CSeq) nextHeader.clone(); + try { + cseq.setMethod(Request.ACK); + } catch (ParseException e) { + } + nextHeader = cseq; + } else if (nextHeader instanceof To) { + if (responseToHeader != null) { + nextHeader = responseToHeader; + } else { + nextHeader = (SIPHeader) nextHeader.clone(); + } + } else if (nextHeader instanceof ContactList || nextHeader instanceof Expires) { + // CONTACT header does not apply for ACK requests. + continue; + } else if (nextHeader instanceof ViaList) { + // Bug reported by Gianluca Martinello + // The ACK MUST contain a single Via header field, + // and this MUST be equal to the top Via header + // field of the original + // request. + + nextHeader = (SIPHeader) ((ViaList) nextHeader).getFirst().clone(); + } else { + nextHeader = (SIPHeader) nextHeader.clone(); + } + + try { + newRequest.attachHeader(nextHeader, false); + } catch (SIPDuplicateHeaderException e) { + e.printStackTrace(); + } } - if (MessageFactoryImpl.getDefaultUserAgentHeader() != null) { newRequest.setHeader(MessageFactoryImpl.getDefaultUserAgentHeader()); @@ -899,7 +938,132 @@ public final SIPRequest createErrorAck(To responseToHeader) throws SipException, return newRequest; } - /** + /** + * Create a new default SIPRequest from the original request. Warning: the newly created + * SIPRequest, shares the headers of this request but we generate any new headers that we need + * to modify so the original request is umodified. However, if you modify the shared headers + * after this request is created, then the newly created request will also be modified. If you + * want to modify the original request without affecting the returned Request make sure you + * clone it before calling this method. + * + * Only required headers are copied. + *
      + *
    • Contact headers are not included in the newly created request. Setting the appropriate + * sequence number is the responsibility of the caller.
    • + *
    • RouteList is not copied for ACK and CANCEL
    • + *
    • Note that we DO NOT copy the body of the argument into the returned header. We do not + * copy the content type header from the original request either. These have to be added + * seperately and the content length has to be correctly set if necessary the content length + * is set to 0 in the returned header.
    • + *
    • Contact List is not copied from the original request.
    • + *
    • RecordRoute List is not included from original request.
    • + *
    • Via header is not included from the original request.
    • + *
    + * + * @param requestLine is the new request line. + * + * @param switchHeaders is a boolean flag that causes to and from headers to switch (set this + * to true if you are the server of the transaction and are generating a BYE request). + * If the headers are switched, we generate new From and To headers otherwise we just + * use the incoming headers. + * + * @return a new Default SIP Request which has the requestLine specified. + * + */ + public SIPRequest createSIPRequest(RequestLine requestLine, boolean switchHeaders) { + SIPRequest newRequest = new SIPRequest(); + newRequest.requestLine = requestLine; + Iterator headerIterator = this.getHeaders(); + while (headerIterator.hasNext()) { + SIPHeader nextHeader = (SIPHeader) headerIterator.next(); + // For BYE and cancel set the CSeq header to the + // appropriate method. + if (nextHeader instanceof CSeq) { + CSeq newCseq = (CSeq) nextHeader.clone(); + nextHeader = newCseq; + try { + newCseq.setMethod(requestLine.getMethod()); + } catch (ParseException e) { + } + } else if (nextHeader instanceof ViaList) { + Via via = (Via) (((ViaList) nextHeader).getFirst().clone()); + via.removeParameter("branch"); + nextHeader = via; + // Cancel and ACK preserve the branch ID. + } else if (nextHeader instanceof To) { + To to = (To) nextHeader; + if (switchHeaders) { + nextHeader = new From(to); + ((From) nextHeader).removeTag(); + } else { + nextHeader = (SIPHeader) to.clone(); + ((To) nextHeader).removeTag(); + } + } else if (nextHeader instanceof From) { + From from = (From) nextHeader; + if (switchHeaders) { + nextHeader = new To(from); + ((To) nextHeader).removeTag(); + } else { + nextHeader = (SIPHeader) from.clone(); + ((From) nextHeader).removeTag(); + } + } else if (nextHeader instanceof ContentLength) { + ContentLength cl = (ContentLength) nextHeader.clone(); + try { + cl.setContentLength(0); + } catch (InvalidArgumentException e) { + } + nextHeader = cl; + } else if (!(nextHeader instanceof CallID) && !(nextHeader instanceof MaxForwards)) { + // Route is kept by dialog. + // RR is added by the caller. + // Contact is added by the Caller + // Any extension headers must be added + // by the caller. + continue; + } + try { + newRequest.attachHeader(nextHeader, false); + } catch (SIPDuplicateHeaderException e) { + e.printStackTrace(); + } + } + if (MessageFactoryImpl.getDefaultUserAgentHeader() != null) { + newRequest.setHeader(MessageFactoryImpl.getDefaultUserAgentHeader()); + + } + return newRequest; + + } + + /** + * Create a BYE request from this request. + * + * @param switchHeaders is a boolean flag that causes from and isServerTransaction to headers + * to be swapped. Set this to true if you are the server of the dialog and are + * generating a BYE request for the dialog. + * @return a new default BYE request. + */ + public SIPRequest createBYERequest(boolean switchHeaders) { + RequestLine requestLine = (RequestLine) this.requestLine.clone(); + requestLine.setMethod("BYE"); + return this.createSIPRequest(requestLine, switchHeaders); + } + + /** + * Create an ACK request from this request. This is suitable for generating an ACK for an + * INVITE client transaction. + * + * @return an ACK request that is generated from this request. + */ + public SIPRequest createACKRequest() { + RequestLine requestLine = (RequestLine) this.requestLine.clone(); + requestLine.setMethod(Request.ACK); + return this.createSIPRequest(requestLine, false); + } + + /** * Get the host from the topmost via header. * * @return the string representation of the host from the topmost via header. @@ -1016,7 +1180,7 @@ public String getMergeId() { String requestUri = this.getRequestURI().toString(); if (fromTag != null) { - return new StringBuilder().append(requestUri).append(":").append(fromTag).append(":").append(cseq).append(":") + return new StringBuffer().append(requestUri).append(":").append(fromTag).append(":").append(cseq).append(":") .append(callId).toString(); } else return null; @@ -1036,9 +1200,9 @@ public void setInviteTransaction(Object inviteTransaction) { public Object getInviteTransaction() { return inviteTransaction; } + + + - @Override - public void cleanUp() { - super.cleanUp(); - } + } diff --git a/src/gov/nist/javax/sip/message/SIPResponse.java b/src/gov/nist/javax/sip/message/SIPResponse.java index b841612b2..2a0a71edc 100755 --- a/src/gov/nist/javax/sip/message/SIPResponse.java +++ b/src/gov/nist/javax/sip/message/SIPResponse.java @@ -29,22 +29,39 @@ package gov.nist.javax.sip.message; import gov.nist.core.InternalErrorHandler; +import gov.nist.javax.sip.Utils; +import gov.nist.javax.sip.address.SipUri; import gov.nist.javax.sip.header.CSeq; import gov.nist.javax.sip.header.CallID; +import gov.nist.javax.sip.header.ContactList; +import gov.nist.javax.sip.header.ContentLength; +import gov.nist.javax.sip.header.ContentType; import gov.nist.javax.sip.header.From; +import gov.nist.javax.sip.header.MaxForwards; +import gov.nist.javax.sip.header.ReasonList; +import gov.nist.javax.sip.header.RecordRouteList; +import gov.nist.javax.sip.header.RequireList; +import gov.nist.javax.sip.header.SIPHeader; import gov.nist.javax.sip.header.StatusLine; import gov.nist.javax.sip.header.To; import gov.nist.javax.sip.header.Via; +import gov.nist.javax.sip.header.ViaList; +import gov.nist.javax.sip.header.extensions.SessionExpires; import java.io.UnsupportedEncodingException; import java.text.ParseException; +import java.util.Iterator; import java.util.LinkedList; +import javax.sip.header.ReasonHeader; +import javax.sip.header.ServerHeader; +import javax.sip.message.Request; + /** * SIP Response structure. * - * @version 1.2 $Revision: 1.35 $ $Date: 2010-09-14 14:39:39 $ + * @version 1.2 $Revision: 1.31 $ $Date: 2010-03-15 17:01:22 $ * @since 1.1 * * @author M. Ranganathan
    @@ -55,7 +72,6 @@ public class SIPResponse extends SIPMessage implements javax.sip.message.Response, ResponseExt { protected StatusLine statusLine; - private boolean isRetransmission = true; public static String getReasonPhrase(int rc) { String retval = null; @@ -431,15 +447,13 @@ public String encode() { *@return The string except for the body. */ - public StringBuilder encodeMessage(StringBuilder retval) { -// String retval; - if (statusLine != null) { - statusLine.encode(retval); - super.encodeSIPHeaders(retval); - } else { - retval = super.encodeSIPHeaders(retval); - } - return retval; + public String encodeMessage() { + String retval; + if (statusLine != null) + retval = statusLine.encode() + super.encodeSIPHeaders(); + else + retval = super.encodeSIPHeaders(); + return retval ; } @@ -533,6 +547,102 @@ public byte[] encodeAsBytes( String transport ) { return retval; } + + + /** Get a dialog identifier. + * Generates a string that can be used as a dialog identifier. + * + * @param isServer is set to true if this is the UAS + * and set to false if this is the UAC + */ + public String getDialogId(boolean isServer) { + CallID cid = (CallID) this.getCallId(); + From from = (From) this.getFrom(); + To to = (To) this.getTo(); + StringBuffer retval = new StringBuffer(cid.getCallId()); + if (!isServer) { + //retval.append(COLON).append(from.getUserAtHostPort()); + if (from.getTag() != null) { + retval.append(COLON); + retval.append(from.getTag()); + } + //retval.append(COLON).append(to.getUserAtHostPort()); + if (to.getTag() != null) { + retval.append(COLON); + retval.append(to.getTag()); + } + } else { + //retval.append(COLON).append(to.getUserAtHostPort()); + if (to.getTag() != null) { + retval.append(COLON); + retval.append(to.getTag()); + } + //retval.append(COLON).append(from.getUserAtHostPort()); + if (from.getTag() != null) { + retval.append(COLON); + retval.append(from.getTag()); + } + } + return retval.toString().toLowerCase(); + } + + public String getDialogId(boolean isServer, String toTag) { + CallID cid = (CallID) this.getCallId(); + From from = (From) this.getFrom(); + StringBuffer retval = new StringBuffer(cid.getCallId()); + if (!isServer) { + //retval.append(COLON).append(from.getUserAtHostPort()); + if (from.getTag() != null) { + retval.append(COLON); + retval.append(from.getTag()); + } + //retval.append(COLON).append(to.getUserAtHostPort()); + if (toTag != null) { + retval.append(COLON); + retval.append(toTag); + } + } else { + //retval.append(COLON).append(to.getUserAtHostPort()); + if (toTag != null) { + retval.append(COLON); + retval.append(toTag); + } + //retval.append(COLON).append(from.getUserAtHostPort()); + if (from.getTag() != null) { + retval.append(COLON); + retval.append(from.getTag()); + } + } + return retval.toString().toLowerCase(); + } + + /** + * Sets the Via branch for CANCEL or ACK requests + * + * @param via + * @param method + * @throws ParseException + */ + private final void setBranch( Via via, String method ) { + String branch; + if (method.equals( Request.ACK ) ) { + if (statusLine.getStatusCode() >= 300 ) { + branch = getTopmostVia().getBranch(); // non-2xx ACK uses same branch + } else { + branch = Utils.getInstance().generateBranchId(); // 2xx ACK gets new branch + } + } else if (method.equals( Request.CANCEL )) { + branch = getTopmostVia().getBranch(); // CANCEL uses same branch + } else return; + + try { + via.setBranch( branch ); + } catch (ParseException e) { + e.printStackTrace(); + } + } + + /** * Get the encoded first line. * @@ -558,25 +668,70 @@ public String toString() { if (statusLine == null) return ""; else return statusLine.encode() + super.encode(); } - - @Override - public void cleanUp() { -// statusLine = null; - super.cleanUp(); - } /** - * @param isRetransmission the isRetransmission to set + * Generate a request from a response. + * + * @param requestURI -- the request URI to assign to the request. + * @param via -- the Via header to assign to the request + * @param cseq -- the CSeq header to assign to the request + * @param from -- the From header to assign to the request + * @param to -- the To header to assign to the request + * @return -- the newly generated sip request. */ - public void setRetransmission(boolean isRetransmission) { - - this.isRetransmission = isRetransmission; - } + public SIPRequest createRequest(SipUri requestURI, Via via, CSeq cseq, From from, To to) { + SIPRequest newRequest = new SIPRequest(); + String method = cseq.getMethod(); + + newRequest.setMethod(method); + newRequest.setRequestURI(requestURI); + this.setBranch( via, method ); + newRequest.setHeader(via); + newRequest.setHeader(cseq); + Iterator headerIterator = getHeaders(); + while (headerIterator.hasNext()) { + SIPHeader nextHeader = (SIPHeader) headerIterator.next(); + // Some headers do not belong in a Request .... + if (SIPMessage.isResponseHeader(nextHeader) + || nextHeader instanceof ViaList + || nextHeader instanceof CSeq + || nextHeader instanceof ContentType + || nextHeader instanceof ContentLength + || nextHeader instanceof RecordRouteList + || nextHeader instanceof RequireList + || nextHeader instanceof ContactList // JvB: added + || nextHeader instanceof ContentLength + || nextHeader instanceof ServerHeader + || nextHeader instanceof ReasonHeader + || nextHeader instanceof SessionExpires + || nextHeader instanceof ReasonList) { + continue; + } + if (nextHeader instanceof To) + nextHeader = (SIPHeader) to; + else if (nextHeader instanceof From) + nextHeader = (SIPHeader) from; + try { + newRequest.attachHeader(nextHeader, false); + } catch (SIPDuplicateHeaderException e) { + //Should not happen! + e.printStackTrace(); + } + } + + try { + // JvB: all requests need a Max-Forwards + newRequest.attachHeader( new MaxForwards(70), false); + } catch (Exception d) { + + } + + if (MessageFactoryImpl.getDefaultUserAgentHeader() != null ) { + newRequest.setHeader(MessageFactoryImpl.getDefaultUserAgentHeader()); + } + return newRequest; - /** - * @return the isRetransmission - */ - public boolean isRetransmission() { - return isRetransmission; } + + } diff --git a/src/gov/nist/javax/sip/parser/AddressParser.java b/src/gov/nist/javax/sip/parser/AddressParser.java index 2fb70aa40..642f8b6da 100755 --- a/src/gov/nist/javax/sip/parser/AddressParser.java +++ b/src/gov/nist/javax/sip/parser/AddressParser.java @@ -30,7 +30,7 @@ /** Parser for addresses. * - * @version 1.2 $Revision: 1.12 $ $Date: 2010-05-06 14:07:44 $ + * @version 1.2 $Revision: 1.11 $ $Date: 2009-10-22 10:26:27 $ * @author M. Ranganathan * * @@ -133,15 +133,11 @@ else if (la == '\0') } /* * $Log: not supported by cvs2svn $ - * Revision 1.11 2009/10/22 10:26:27 jbemmel - * Fix for issue #230, restructured the code such that parsing for any address appearing without '<' '>' - * stops at ';', then parameters are assigned to the header as expected - * * Revision 1.10 2009/07/17 18:57:57 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.9 2007/02/12 15:19:26 belangery - * Changed the encode() and encodeBody() methods of SIP headers and basic classes to make them use the same StringBuilder instance during the encoding phase. + * Changed the encode() and encodeBody() methods of SIP headers and basic classes to make them use the same StringBuffer instance during the encoding phase. * * Revision 1.8 2007/02/06 16:40:02 belangery * Introduced simple code optimizations. diff --git a/src/gov/nist/javax/sip/parser/CSeqParser.java b/src/gov/nist/javax/sip/parser/CSeqParser.java index efac3ee50..ff1830632 100755 --- a/src/gov/nist/javax/sip/parser/CSeqParser.java +++ b/src/gov/nist/javax/sip/parser/CSeqParser.java @@ -36,7 +36,7 @@ /** * Parser for CSeq headers. * - * @version 1.2 $Revision: 1.11 $ $Date: 2010-05-06 14:07:45 $ + * @version 1.2 $Revision: 1.10 $ $Date: 2006-08-15 21:44:50 $ * * @author M. Ranganathan * @author Olivier Deruelle @@ -63,7 +63,7 @@ public SIPHeader parse() throws ParseException { String number = this.lexer.number(); c.setSeqNumber(Long.parseLong(number)); this.lexer.SPorHT(); - String m = SIPRequest.getCannonicalName( method() ).intern(); + String m = SIPRequest.getCannonicalName( method() ); @@ -86,28 +86,6 @@ public SIPHeader parse() throws ParseException { } /* * $Log: not supported by cvs2svn $ - * Revision 1.10 2006/08/15 21:44:50 mranga - * Issue number: - * Obtained from: - * Submitted by: mranga - * Reviewed by: mranga - * Incorporating the latest API changes from Phelim - * CVS: ---------------------------------------------------------------------- - * CVS: Issue number: - * CVS: If this change addresses one or more issues, - * CVS: then enter the issue number(s) here. - * CVS: Obtained from: - * CVS: If this change has been taken from another system, - * CVS: then name the system in this line, otherwise delete it. - * CVS: Submitted by: - * CVS: If this code has been contributed to the project by someone else; i.e., - * CVS: they sent us a patch or a set of diffs, then include their name/email - * CVS: address here. If this is your work then delete this line. - * CVS: Reviewed by: - * CVS: If we are doing pre-commit code reviews and someone else has - * CVS: reviewed your changes, include their name(s) here. - * CVS: If you have not had it reviewed then delete this line. - * * Revision 1.9 2006/07/13 09:02:17 mranga * Issue number: * Obtained from: diff --git a/src/gov/nist/javax/sip/parser/Lexer.java b/src/gov/nist/javax/sip/parser/Lexer.java index bf1d08571..628d858ee 100755 --- a/src/gov/nist/javax/sip/parser/Lexer.java +++ b/src/gov/nist/javax/sip/parser/Lexer.java @@ -25,89 +25,14 @@ */ package gov.nist.javax.sip.parser; -import gov.nist.core.LexerCore; -import gov.nist.javax.sip.header.extensions.JoinHeader; -import gov.nist.javax.sip.header.extensions.MinSEHeader; -import gov.nist.javax.sip.header.extensions.ReferencesHeader; -import gov.nist.javax.sip.header.extensions.ReferredByHeader; -import gov.nist.javax.sip.header.extensions.ReplacesHeader; -import gov.nist.javax.sip.header.extensions.SessionExpiresHeader; -import gov.nist.javax.sip.header.ims.PAccessNetworkInfoHeader; -import gov.nist.javax.sip.header.ims.PAssertedIdentityHeader; -import gov.nist.javax.sip.header.ims.PAssertedServiceHeader; -import gov.nist.javax.sip.header.ims.PAssociatedURIHeader; -import gov.nist.javax.sip.header.ims.PCalledPartyIDHeader; -import gov.nist.javax.sip.header.ims.PChargingFunctionAddressesHeader; -import gov.nist.javax.sip.header.ims.PChargingVectorHeader; -import gov.nist.javax.sip.header.ims.PMediaAuthorizationHeader; -import gov.nist.javax.sip.header.ims.PPreferredIdentityHeader; -import gov.nist.javax.sip.header.ims.PPreferredServiceHeader; -import gov.nist.javax.sip.header.ims.PProfileKeyHeader; -import gov.nist.javax.sip.header.ims.PServedUserHeader; -import gov.nist.javax.sip.header.ims.PUserDatabaseHeader; -import gov.nist.javax.sip.header.ims.PVisitedNetworkIDHeader; -import gov.nist.javax.sip.header.ims.PathHeader; -import gov.nist.javax.sip.header.ims.PrivacyHeader; -import gov.nist.javax.sip.header.ims.SecurityClientHeader; -import gov.nist.javax.sip.header.ims.SecurityServerHeader; -import gov.nist.javax.sip.header.ims.SecurityVerifyHeader; -import gov.nist.javax.sip.header.ims.ServiceRouteHeader; +import gov.nist.core.*; -import java.util.concurrent.ConcurrentHashMap; +import gov.nist.javax.sip.header.extensions.*; -import javax.sip.header.AcceptEncodingHeader; -import javax.sip.header.AcceptHeader; -import javax.sip.header.AcceptLanguageHeader; -import javax.sip.header.AlertInfoHeader; -import javax.sip.header.AllowEventsHeader; -import javax.sip.header.AllowHeader; -import javax.sip.header.AuthenticationInfoHeader; -import javax.sip.header.AuthorizationHeader; -import javax.sip.header.CSeqHeader; -import javax.sip.header.CallIdHeader; -import javax.sip.header.CallInfoHeader; -import javax.sip.header.ContactHeader; -import javax.sip.header.ContentDispositionHeader; -import javax.sip.header.ContentEncodingHeader; -import javax.sip.header.ContentLanguageHeader; -import javax.sip.header.ContentLengthHeader; -import javax.sip.header.ContentTypeHeader; -import javax.sip.header.DateHeader; -import javax.sip.header.ErrorInfoHeader; -import javax.sip.header.EventHeader; -import javax.sip.header.ExpiresHeader; -import javax.sip.header.FromHeader; -import javax.sip.header.InReplyToHeader; -import javax.sip.header.MaxForwardsHeader; -import javax.sip.header.MimeVersionHeader; -import javax.sip.header.MinExpiresHeader; -import javax.sip.header.OrganizationHeader; -import javax.sip.header.PriorityHeader; -import javax.sip.header.ProxyAuthenticateHeader; -import javax.sip.header.ProxyAuthorizationHeader; -import javax.sip.header.ProxyRequireHeader; -import javax.sip.header.RAckHeader; -import javax.sip.header.RSeqHeader; -import javax.sip.header.ReasonHeader; -import javax.sip.header.RecordRouteHeader; -import javax.sip.header.ReferToHeader; -import javax.sip.header.ReplyToHeader; -import javax.sip.header.RequireHeader; -import javax.sip.header.RetryAfterHeader; -import javax.sip.header.RouteHeader; -import javax.sip.header.SIPETagHeader; -import javax.sip.header.SIPIfMatchHeader; -import javax.sip.header.ServerHeader; -import javax.sip.header.SubjectHeader; -import javax.sip.header.SubscriptionStateHeader; -import javax.sip.header.SupportedHeader; -import javax.sip.header.TimeStampHeader; -import javax.sip.header.ToHeader; -import javax.sip.header.UnsupportedHeader; -import javax.sip.header.UserAgentHeader; -import javax.sip.header.ViaHeader; -import javax.sip.header.WWWAuthenticateHeader; -import javax.sip.header.WarningHeader; +import gov.nist.javax.sip.header.ims.*; + +import javax.sip.header.*; +import java.util.Hashtable; /** * Lexer class for the parser. @@ -164,248 +89,236 @@ public static String getHeaderValue(String line) { } public void selectLexer(String lexerName) { - // Synchronization Bug fix by Robert Rosen. - ConcurrentHashMap lexer = lexerTables.get(lexerName); - this.currentLexerName = lexerName; - if (lexer == null) { - ConcurrentHashMap newLexer = new ConcurrentHashMap(); - // Temporarily set newLexer as current, so addKeyword populate it - currentLexer = newLexer; -// addLexer(lexerName); - if (lexerName.equals("method_keywordLexer")) { - addKeyword(TokenNames.REGISTER, TokenTypes.REGISTER); - addKeyword(TokenNames.ACK, TokenTypes.ACK); - addKeyword(TokenNames.OPTIONS, TokenTypes.OPTIONS); - addKeyword(TokenNames.BYE, TokenTypes.BYE); - addKeyword(TokenNames.INVITE, TokenTypes.INVITE); - addKeyword(TokenNames.SIP.toUpperCase(), TokenTypes.SIP); - addKeyword(TokenNames.SIPS.toUpperCase(), TokenTypes.SIPS); - addKeyword(TokenNames.SUBSCRIBE, TokenTypes.SUBSCRIBE); - addKeyword(TokenNames.NOTIFY, TokenTypes.NOTIFY); - addKeyword(TokenNames.MESSAGE, TokenTypes.MESSAGE); - - // JvB: added to support RFC3903 - addKeyword(TokenNames.PUBLISH, TokenTypes.PUBLISH); + synchronized (lexerTables) { + // Synchronization Bug fix by Robert Rosen. + currentLexer = (Hashtable) lexerTables.get(lexerName); + this.currentLexerName = lexerName; + if (currentLexer == null) { + addLexer(lexerName); + if (lexerName.equals("method_keywordLexer")) { + addKeyword(TokenNames.REGISTER, TokenTypes.REGISTER); + addKeyword(TokenNames.ACK, TokenTypes.ACK); + addKeyword(TokenNames.OPTIONS, TokenTypes.OPTIONS); + addKeyword(TokenNames.BYE, TokenTypes.BYE); + addKeyword(TokenNames.INVITE, TokenTypes.INVITE); + addKeyword(TokenNames.SIP.toUpperCase(), TokenTypes.SIP); + addKeyword(TokenNames.SIPS.toUpperCase(), TokenTypes.SIPS); + addKeyword(TokenNames.SUBSCRIBE, TokenTypes.SUBSCRIBE); + addKeyword(TokenNames.NOTIFY, TokenTypes.NOTIFY); + addKeyword(TokenNames.MESSAGE, TokenTypes.MESSAGE); - } else if (lexerName.equals("command_keywordLexer")) { - addKeyword(ErrorInfoHeader.NAME.toUpperCase(), - TokenTypes.ERROR_INFO); - addKeyword(AllowEventsHeader.NAME.toUpperCase(), - TokenTypes.ALLOW_EVENTS); - addKeyword(AuthenticationInfoHeader.NAME.toUpperCase(), - TokenTypes.AUTHENTICATION_INFO); - addKeyword(EventHeader.NAME.toUpperCase(), TokenTypes.EVENT); - addKeyword(MinExpiresHeader.NAME.toUpperCase(), - TokenTypes.MIN_EXPIRES); - addKeyword(RSeqHeader.NAME.toUpperCase(), TokenTypes.RSEQ); - addKeyword(RAckHeader.NAME.toUpperCase(), TokenTypes.RACK); - addKeyword(ReasonHeader.NAME.toUpperCase(), - TokenTypes.REASON); - addKeyword(ReplyToHeader.NAME.toUpperCase(), - TokenTypes.REPLY_TO); - addKeyword(SubscriptionStateHeader.NAME.toUpperCase(), - TokenTypes.SUBSCRIPTION_STATE); - addKeyword(TimeStampHeader.NAME.toUpperCase(), - TokenTypes.TIMESTAMP); - addKeyword(InReplyToHeader.NAME.toUpperCase(), - TokenTypes.IN_REPLY_TO); - addKeyword(MimeVersionHeader.NAME.toUpperCase(), - TokenTypes.MIME_VERSION); - addKeyword(AlertInfoHeader.NAME.toUpperCase(), - TokenTypes.ALERT_INFO); - addKeyword(FromHeader.NAME.toUpperCase(), TokenTypes.FROM); - addKeyword(ToHeader.NAME.toUpperCase(), TokenTypes.TO); - addKeyword(ReferToHeader.NAME.toUpperCase(), - TokenTypes.REFER_TO); - addKeyword(ViaHeader.NAME.toUpperCase(), TokenTypes.VIA); - addKeyword(UserAgentHeader.NAME.toUpperCase(), - TokenTypes.USER_AGENT); - addKeyword(ServerHeader.NAME.toUpperCase(), - TokenTypes.SERVER); - addKeyword(AcceptEncodingHeader.NAME.toUpperCase(), - TokenTypes.ACCEPT_ENCODING); - addKeyword(AcceptHeader.NAME.toUpperCase(), - TokenTypes.ACCEPT); - addKeyword(AllowHeader.NAME.toUpperCase(), TokenTypes.ALLOW); - addKeyword(RouteHeader.NAME.toUpperCase(), TokenTypes.ROUTE); - addKeyword(AuthorizationHeader.NAME.toUpperCase(), - TokenTypes.AUTHORIZATION); - addKeyword(ProxyAuthorizationHeader.NAME.toUpperCase(), - TokenTypes.PROXY_AUTHORIZATION); - addKeyword(RetryAfterHeader.NAME.toUpperCase(), - TokenTypes.RETRY_AFTER); - addKeyword(ProxyRequireHeader.NAME.toUpperCase(), - TokenTypes.PROXY_REQUIRE); - addKeyword(ContentLanguageHeader.NAME.toUpperCase(), - TokenTypes.CONTENT_LANGUAGE); - addKeyword(UnsupportedHeader.NAME.toUpperCase(), - TokenTypes.UNSUPPORTED); - addKeyword(SupportedHeader.NAME.toUpperCase(), - TokenTypes.SUPPORTED); - addKeyword(WarningHeader.NAME.toUpperCase(), - TokenTypes.WARNING); - addKeyword(MaxForwardsHeader.NAME.toUpperCase(), - TokenTypes.MAX_FORWARDS); - addKeyword(DateHeader.NAME.toUpperCase(), TokenTypes.DATE); - addKeyword(PriorityHeader.NAME.toUpperCase(), - TokenTypes.PRIORITY); - addKeyword(ProxyAuthenticateHeader.NAME.toUpperCase(), - TokenTypes.PROXY_AUTHENTICATE); - addKeyword(ContentEncodingHeader.NAME.toUpperCase(), - TokenTypes.CONTENT_ENCODING); - addKeyword(ContentLengthHeader.NAME.toUpperCase(), - TokenTypes.CONTENT_LENGTH); - addKeyword(SubjectHeader.NAME.toUpperCase(), - TokenTypes.SUBJECT); - addKeyword(ContentTypeHeader.NAME.toUpperCase(), - TokenTypes.CONTENT_TYPE); - addKeyword(ContactHeader.NAME.toUpperCase(), - TokenTypes.CONTACT); - addKeyword(CallIdHeader.NAME.toUpperCase(), - TokenTypes.CALL_ID); - addKeyword(RequireHeader.NAME.toUpperCase(), - TokenTypes.REQUIRE); - addKeyword(ExpiresHeader.NAME.toUpperCase(), - TokenTypes.EXPIRES); - addKeyword(RecordRouteHeader.NAME.toUpperCase(), - TokenTypes.RECORD_ROUTE); - addKeyword(OrganizationHeader.NAME.toUpperCase(), - TokenTypes.ORGANIZATION); - addKeyword(CSeqHeader.NAME.toUpperCase(), TokenTypes.CSEQ); - addKeyword(AcceptLanguageHeader.NAME.toUpperCase(), - TokenTypes.ACCEPT_LANGUAGE); - addKeyword(WWWAuthenticateHeader.NAME.toUpperCase(), - TokenTypes.WWW_AUTHENTICATE); - addKeyword(CallInfoHeader.NAME.toUpperCase(), - TokenTypes.CALL_INFO); - addKeyword(ContentDispositionHeader.NAME.toUpperCase(), - TokenTypes.CONTENT_DISPOSITION); - // And now the dreaded short forms.... - addKeyword(TokenNames.K.toUpperCase(), TokenTypes.SUPPORTED); - addKeyword(TokenNames.C.toUpperCase(), - TokenTypes.CONTENT_TYPE); - addKeyword(TokenNames.E.toUpperCase(), - TokenTypes.CONTENT_ENCODING); - addKeyword(TokenNames.F.toUpperCase(), TokenTypes.FROM); - addKeyword(TokenNames.I.toUpperCase(), TokenTypes.CALL_ID); - addKeyword(TokenNames.M.toUpperCase(), TokenTypes.CONTACT); - addKeyword(TokenNames.L.toUpperCase(), - TokenTypes.CONTENT_LENGTH); - addKeyword(TokenNames.S.toUpperCase(), TokenTypes.SUBJECT); - addKeyword(TokenNames.T.toUpperCase(), TokenTypes.TO); - addKeyword(TokenNames.U.toUpperCase(), - TokenTypes.ALLOW_EVENTS); // JvB: added - addKeyword(TokenNames.V.toUpperCase(), TokenTypes.VIA); - addKeyword(TokenNames.R.toUpperCase(), TokenTypes.REFER_TO); - addKeyword(TokenNames.O.toUpperCase(), TokenTypes.EVENT); // Bug - // fix - // by - // Mario - // Mantak - addKeyword(TokenNames.X.toUpperCase(), TokenTypes.SESSIONEXPIRES_TO); // Bug fix by Jozef Saniga - - // JvB: added to support RFC3903 - addKeyword(SIPETagHeader.NAME.toUpperCase(), - TokenTypes.SIP_ETAG); - addKeyword(SIPIfMatchHeader.NAME.toUpperCase(), - TokenTypes.SIP_IF_MATCH); + // JvB: added to support RFC3903 + addKeyword(TokenNames.PUBLISH, TokenTypes.PUBLISH); - // pmusgrave: Add RFC4028 and ReferredBy - addKeyword(SessionExpiresHeader.NAME.toUpperCase(), - TokenTypes.SESSIONEXPIRES_TO); - addKeyword(MinSEHeader.NAME.toUpperCase(), - TokenTypes.MINSE_TO); - addKeyword(ReferredByHeader.NAME.toUpperCase(), - TokenTypes.REFERREDBY_TO); + } else if (lexerName.equals("command_keywordLexer")) { + addKeyword(ErrorInfoHeader.NAME.toUpperCase(), + TokenTypes.ERROR_INFO); + addKeyword(AllowEventsHeader.NAME.toUpperCase(), + TokenTypes.ALLOW_EVENTS); + addKeyword(AuthenticationInfoHeader.NAME.toUpperCase(), + TokenTypes.AUTHENTICATION_INFO); + addKeyword(EventHeader.NAME.toUpperCase(), TokenTypes.EVENT); + addKeyword(MinExpiresHeader.NAME.toUpperCase(), + TokenTypes.MIN_EXPIRES); + addKeyword(RSeqHeader.NAME.toUpperCase(), TokenTypes.RSEQ); + addKeyword(RAckHeader.NAME.toUpperCase(), TokenTypes.RACK); + addKeyword(ReasonHeader.NAME.toUpperCase(), + TokenTypes.REASON); + addKeyword(ReplyToHeader.NAME.toUpperCase(), + TokenTypes.REPLY_TO); + addKeyword(SubscriptionStateHeader.NAME.toUpperCase(), + TokenTypes.SUBSCRIPTION_STATE); + addKeyword(TimeStampHeader.NAME.toUpperCase(), + TokenTypes.TIMESTAMP); + addKeyword(InReplyToHeader.NAME.toUpperCase(), + TokenTypes.IN_REPLY_TO); + addKeyword(MimeVersionHeader.NAME.toUpperCase(), + TokenTypes.MIME_VERSION); + addKeyword(AlertInfoHeader.NAME.toUpperCase(), + TokenTypes.ALERT_INFO); + addKeyword(FromHeader.NAME.toUpperCase(), TokenTypes.FROM); + addKeyword(ToHeader.NAME.toUpperCase(), TokenTypes.TO); + addKeyword(ReferToHeader.NAME.toUpperCase(), + TokenTypes.REFER_TO); + addKeyword(ViaHeader.NAME.toUpperCase(), TokenTypes.VIA); + addKeyword(UserAgentHeader.NAME.toUpperCase(), + TokenTypes.USER_AGENT); + addKeyword(ServerHeader.NAME.toUpperCase(), + TokenTypes.SERVER); + addKeyword(AcceptEncodingHeader.NAME.toUpperCase(), + TokenTypes.ACCEPT_ENCODING); + addKeyword(AcceptHeader.NAME.toUpperCase(), + TokenTypes.ACCEPT); + addKeyword(AllowHeader.NAME.toUpperCase(), TokenTypes.ALLOW); + addKeyword(RouteHeader.NAME.toUpperCase(), TokenTypes.ROUTE); + addKeyword(AuthorizationHeader.NAME.toUpperCase(), + TokenTypes.AUTHORIZATION); + addKeyword(ProxyAuthorizationHeader.NAME.toUpperCase(), + TokenTypes.PROXY_AUTHORIZATION); + addKeyword(RetryAfterHeader.NAME.toUpperCase(), + TokenTypes.RETRY_AFTER); + addKeyword(ProxyRequireHeader.NAME.toUpperCase(), + TokenTypes.PROXY_REQUIRE); + addKeyword(ContentLanguageHeader.NAME.toUpperCase(), + TokenTypes.CONTENT_LANGUAGE); + addKeyword(UnsupportedHeader.NAME.toUpperCase(), + TokenTypes.UNSUPPORTED); + addKeyword(SupportedHeader.NAME.toUpperCase(), + TokenTypes.SUPPORTED); + addKeyword(WarningHeader.NAME.toUpperCase(), + TokenTypes.WARNING); + addKeyword(MaxForwardsHeader.NAME.toUpperCase(), + TokenTypes.MAX_FORWARDS); + addKeyword(DateHeader.NAME.toUpperCase(), TokenTypes.DATE); + addKeyword(PriorityHeader.NAME.toUpperCase(), + TokenTypes.PRIORITY); + addKeyword(ProxyAuthenticateHeader.NAME.toUpperCase(), + TokenTypes.PROXY_AUTHENTICATE); + addKeyword(ContentEncodingHeader.NAME.toUpperCase(), + TokenTypes.CONTENT_ENCODING); + addKeyword(ContentLengthHeader.NAME.toUpperCase(), + TokenTypes.CONTENT_LENGTH); + addKeyword(SubjectHeader.NAME.toUpperCase(), + TokenTypes.SUBJECT); + addKeyword(ContentTypeHeader.NAME.toUpperCase(), + TokenTypes.CONTENT_TYPE); + addKeyword(ContactHeader.NAME.toUpperCase(), + TokenTypes.CONTACT); + addKeyword(CallIdHeader.NAME.toUpperCase(), + TokenTypes.CALL_ID); + addKeyword(RequireHeader.NAME.toUpperCase(), + TokenTypes.REQUIRE); + addKeyword(ExpiresHeader.NAME.toUpperCase(), + TokenTypes.EXPIRES); + addKeyword(RecordRouteHeader.NAME.toUpperCase(), + TokenTypes.RECORD_ROUTE); + addKeyword(OrganizationHeader.NAME.toUpperCase(), + TokenTypes.ORGANIZATION); + addKeyword(CSeqHeader.NAME.toUpperCase(), TokenTypes.CSEQ); + addKeyword(AcceptLanguageHeader.NAME.toUpperCase(), + TokenTypes.ACCEPT_LANGUAGE); + addKeyword(WWWAuthenticateHeader.NAME.toUpperCase(), + TokenTypes.WWW_AUTHENTICATE); + addKeyword(CallInfoHeader.NAME.toUpperCase(), + TokenTypes.CALL_INFO); + addKeyword(ContentDispositionHeader.NAME.toUpperCase(), + TokenTypes.CONTENT_DISPOSITION); + // And now the dreaded short forms.... + addKeyword(TokenNames.K.toUpperCase(), TokenTypes.SUPPORTED); + addKeyword(TokenNames.C.toUpperCase(), + TokenTypes.CONTENT_TYPE); + addKeyword(TokenNames.E.toUpperCase(), + TokenTypes.CONTENT_ENCODING); + addKeyword(TokenNames.F.toUpperCase(), TokenTypes.FROM); + addKeyword(TokenNames.I.toUpperCase(), TokenTypes.CALL_ID); + addKeyword(TokenNames.M.toUpperCase(), TokenTypes.CONTACT); + addKeyword(TokenNames.L.toUpperCase(), + TokenTypes.CONTENT_LENGTH); + addKeyword(TokenNames.S.toUpperCase(), TokenTypes.SUBJECT); + addKeyword(TokenNames.T.toUpperCase(), TokenTypes.TO); + addKeyword(TokenNames.U.toUpperCase(), + TokenTypes.ALLOW_EVENTS); // JvB: added + addKeyword(TokenNames.V.toUpperCase(), TokenTypes.VIA); + addKeyword(TokenNames.R.toUpperCase(), TokenTypes.REFER_TO); + addKeyword(TokenNames.O.toUpperCase(), TokenTypes.EVENT); // Bug + // fix + // by + // Mario + // Mantak + addKeyword(TokenNames.X.toUpperCase(), TokenTypes.SESSIONEXPIRES_TO); // Bug fix by Jozef Saniga + + // JvB: added to support RFC3903 + addKeyword(SIPETagHeader.NAME.toUpperCase(), + TokenTypes.SIP_ETAG); + addKeyword(SIPIfMatchHeader.NAME.toUpperCase(), + TokenTypes.SIP_IF_MATCH); - // pmusgrave RFC3891 - addKeyword(ReplacesHeader.NAME.toUpperCase(), - TokenTypes.REPLACES_TO); - //jean deruelle RFC3911 - addKeyword(JoinHeader.NAME.toUpperCase(), - TokenTypes.JOIN_TO); + // pmusgrave: Add RFC4028 and ReferredBy + addKeyword(SessionExpiresHeader.NAME.toUpperCase(), + TokenTypes.SESSIONEXPIRES_TO); + addKeyword(MinSEHeader.NAME.toUpperCase(), + TokenTypes.MINSE_TO); + addKeyword(ReferredByHeader.NAME.toUpperCase(), + TokenTypes.REFERREDBY_TO); - // IMS Headers - addKeyword(PathHeader.NAME.toUpperCase(), TokenTypes.PATH); - addKeyword(ServiceRouteHeader.NAME.toUpperCase(), - TokenTypes.SERVICE_ROUTE); - addKeyword(PAssertedIdentityHeader.NAME.toUpperCase(), - TokenTypes.P_ASSERTED_IDENTITY); - addKeyword(PPreferredIdentityHeader.NAME.toUpperCase(), - TokenTypes.P_PREFERRED_IDENTITY); - addKeyword(PrivacyHeader.NAME.toUpperCase(), - TokenTypes.PRIVACY); + // pmusgrave RFC3891 + addKeyword(ReplacesHeader.NAME.toUpperCase(), + TokenTypes.REPLACES_TO); + //jean deruelle RFC3911 + addKeyword(JoinHeader.NAME.toUpperCase(), + TokenTypes.JOIN_TO); - // issued by Miguel Freitas - addKeyword(PCalledPartyIDHeader.NAME.toUpperCase(), - TokenTypes.P_CALLED_PARTY_ID); - addKeyword(PAssociatedURIHeader.NAME.toUpperCase(), - TokenTypes.P_ASSOCIATED_URI); - addKeyword(PVisitedNetworkIDHeader.NAME.toUpperCase(), - TokenTypes.P_VISITED_NETWORK_ID); - addKeyword(PChargingFunctionAddressesHeader.NAME - .toUpperCase(), - TokenTypes.P_CHARGING_FUNCTION_ADDRESSES); - addKeyword(PChargingVectorHeader.NAME.toUpperCase(), - TokenTypes.P_VECTOR_CHARGING); - addKeyword(PAccessNetworkInfoHeader.NAME.toUpperCase(), - TokenTypes.P_ACCESS_NETWORK_INFO); - addKeyword(PMediaAuthorizationHeader.NAME.toUpperCase(), - TokenTypes.P_MEDIA_AUTHORIZATION); + // IMS Headers + addKeyword(PathHeader.NAME.toUpperCase(), TokenTypes.PATH); + addKeyword(ServiceRouteHeader.NAME.toUpperCase(), + TokenTypes.SERVICE_ROUTE); + addKeyword(PAssertedIdentityHeader.NAME.toUpperCase(), + TokenTypes.P_ASSERTED_IDENTITY); + addKeyword(PPreferredIdentityHeader.NAME.toUpperCase(), + TokenTypes.P_PREFERRED_IDENTITY); + addKeyword(PrivacyHeader.NAME.toUpperCase(), + TokenTypes.PRIVACY); - addKeyword(SecurityServerHeader.NAME.toUpperCase(), - TokenTypes.SECURITY_SERVER); - addKeyword(SecurityVerifyHeader.NAME.toUpperCase(), - TokenTypes.SECURITY_VERIFY); - addKeyword(SecurityClientHeader.NAME.toUpperCase(), - TokenTypes.SECURITY_CLIENT); + // issued by Miguel Freitas + addKeyword(PCalledPartyIDHeader.NAME.toUpperCase(), + TokenTypes.P_CALLED_PARTY_ID); + addKeyword(PAssociatedURIHeader.NAME.toUpperCase(), + TokenTypes.P_ASSOCIATED_URI); + addKeyword(PVisitedNetworkIDHeader.NAME.toUpperCase(), + TokenTypes.P_VISITED_NETWORK_ID); + addKeyword(PChargingFunctionAddressesHeader.NAME + .toUpperCase(), + TokenTypes.P_CHARGING_FUNCTION_ADDRESSES); + addKeyword(PChargingVectorHeader.NAME.toUpperCase(), + TokenTypes.P_VECTOR_CHARGING); + addKeyword(PAccessNetworkInfoHeader.NAME.toUpperCase(), + TokenTypes.P_ACCESS_NETWORK_INFO); + addKeyword(PMediaAuthorizationHeader.NAME.toUpperCase(), + TokenTypes.P_MEDIA_AUTHORIZATION); - // added by aayush@rancore - addKeyword(PUserDatabaseHeader.NAME.toUpperCase(), - TokenTypes.P_USER_DATABASE); + addKeyword(SecurityServerHeader.NAME.toUpperCase(), + TokenTypes.SECURITY_SERVER); + addKeyword(SecurityVerifyHeader.NAME.toUpperCase(), + TokenTypes.SECURITY_VERIFY); + addKeyword(SecurityClientHeader.NAME.toUpperCase(), + TokenTypes.SECURITY_CLIENT); - // added by aayush@rancore - addKeyword(PProfileKeyHeader.NAME.toUpperCase(), - TokenTypes.P_PROFILE_KEY); + // added by aayush@rancore + addKeyword(PUserDatabaseHeader.NAME.toUpperCase(), + TokenTypes.P_USER_DATABASE); - // added by aayush@rancore - addKeyword(PServedUserHeader.NAME.toUpperCase(), - TokenTypes.P_SERVED_USER); + // added by aayush@rancore + addKeyword(PProfileKeyHeader.NAME.toUpperCase(), + TokenTypes.P_PROFILE_KEY); - // added by aayush@rancore - addKeyword(PPreferredServiceHeader.NAME.toUpperCase(), - TokenTypes.P_PREFERRED_SERVICE); + // added by aayush@rancore + addKeyword(PServedUserHeader.NAME.toUpperCase(), + TokenTypes.P_SERVED_USER); - // added by aayush@rancore - addKeyword(PAssertedServiceHeader.NAME.toUpperCase(), - TokenTypes.P_ASSERTED_SERVICE); - - // added References header - addKeyword(ReferencesHeader.NAME.toUpperCase(),TokenTypes.REFERENCES); + // added by aayush@rancore + addKeyword(PPreferredServiceHeader.NAME.toUpperCase(), + TokenTypes.P_PREFERRED_SERVICE); - // end // + // added by aayush@rancore + addKeyword(PAssertedServiceHeader.NAME.toUpperCase(), + TokenTypes.P_ASSERTED_SERVICE); + + // added References header + addKeyword(ReferencesHeader.NAME.toUpperCase(),TokenTypes.REFERENCES); + // end // - } else if (lexerName.equals("status_lineLexer")) { - addKeyword(TokenNames.SIP.toUpperCase(), TokenTypes.SIP); - } else if (lexerName.equals("request_lineLexer")) { - addKeyword(TokenNames.SIP.toUpperCase(), TokenTypes.SIP); - } else if (lexerName.equals("sip_urlLexer")) { - addKeyword(TokenNames.TEL.toUpperCase(), TokenTypes.TEL); - addKeyword(TokenNames.SIP.toUpperCase(), TokenTypes.SIP); - addKeyword(TokenNames.SIPS.toUpperCase(), TokenTypes.SIPS); - } - // Now newLexer is completely initialized, let's check if somebody - // have put lexer in table - lexer = lexerTables.putIfAbsent(lexerName, newLexer); - if (lexer == null) { - // put succeeded, use new value - lexer = newLexer; + } else if (lexerName.equals("status_lineLexer")) { + addKeyword(TokenNames.SIP.toUpperCase(), TokenTypes.SIP); + } else if (lexerName.equals("request_lineLexer")) { + addKeyword(TokenNames.SIP.toUpperCase(), TokenTypes.SIP); + } else if (lexerName.equals("sip_urlLexer")) { + addKeyword(TokenNames.TEL.toUpperCase(), TokenTypes.TEL); + addKeyword(TokenNames.SIP.toUpperCase(), TokenTypes.SIP); + addKeyword(TokenNames.SIPS.toUpperCase(), TokenTypes.SIPS); + } } - currentLexer = lexer; - } else { - currentLexer = lexer; } } } diff --git a/src/gov/nist/javax/sip/parser/MessageParser.java b/src/gov/nist/javax/sip/parser/MessageParser.java index 56c27f5be..86dd0cb4a 100644 --- a/src/gov/nist/javax/sip/parser/MessageParser.java +++ b/src/gov/nist/javax/sip/parser/MessageParser.java @@ -37,14 +37,25 @@ */ public interface MessageParser { + /** + * Callback if an exception occurs during the parsing to notify back the stack + * @param parseExceptionListener + */ + void setParseExceptionListener(ParseExceptionListener parseExceptionListener); + + /** + * If the content body should be read or not + * + * @param readBody + */ + void setReadBody(boolean readBody); + /** * parse a byte array containing the SIP Message into a SIPMessage object * @param msgBytes the SIP Message received from the network - * @param readBody If the content body should be read or not - * @param exhandler Callback if an exception occurs during the parsing to notify back the stack * @return a SIPMessage object that the stack can interact with * @throws ParseException if a parseexception occurs */ - SIPMessage parseSIPMessage(byte[] msgBytes, boolean readBody, boolean strict, ParseExceptionListener exhandler) throws ParseException; + SIPMessage parseSIPMessage(byte[] msgBytes) throws ParseException; } diff --git a/src/gov/nist/javax/sip/parser/ParserFactory.java b/src/gov/nist/javax/sip/parser/ParserFactory.java index 03d688234..99d2fdfb6 100755 --- a/src/gov/nist/javax/sip/parser/ParserFactory.java +++ b/src/gov/nist/javax/sip/parser/ParserFactory.java @@ -24,115 +24,22 @@ * */ package gov.nist.javax.sip.parser; -import gov.nist.core.InternalErrorHandler; -import gov.nist.javax.sip.header.SIPHeaderNamesCache; -import gov.nist.javax.sip.header.extensions.Join; -import gov.nist.javax.sip.header.extensions.MinSE; -import gov.nist.javax.sip.header.extensions.References; -import gov.nist.javax.sip.header.extensions.ReferredBy; -import gov.nist.javax.sip.header.extensions.Replaces; -import gov.nist.javax.sip.header.extensions.SessionExpires; -import gov.nist.javax.sip.header.ims.PAccessNetworkInfoHeader; -import gov.nist.javax.sip.header.ims.PAssertedIdentityHeader; -import gov.nist.javax.sip.header.ims.PAssociatedURIHeader; -import gov.nist.javax.sip.header.ims.PCalledPartyIDHeader; -import gov.nist.javax.sip.header.ims.PChargingFunctionAddressesHeader; -import gov.nist.javax.sip.header.ims.PChargingVectorHeader; -import gov.nist.javax.sip.header.ims.PMediaAuthorizationHeader; -import gov.nist.javax.sip.header.ims.PPreferredIdentityHeader; -import gov.nist.javax.sip.header.ims.PVisitedNetworkIDHeader; -import gov.nist.javax.sip.header.ims.PathHeader; -import gov.nist.javax.sip.header.ims.PrivacyHeader; -import gov.nist.javax.sip.header.ims.SecurityClientHeader; -import gov.nist.javax.sip.header.ims.SecurityServerHeader; -import gov.nist.javax.sip.header.ims.SecurityVerifyHeader; -import gov.nist.javax.sip.header.ims.ServiceRouteHeader; -import gov.nist.javax.sip.parser.extensions.JoinParser; -import gov.nist.javax.sip.parser.extensions.MinSEParser; -import gov.nist.javax.sip.parser.extensions.ReferencesParser; -import gov.nist.javax.sip.parser.extensions.ReferredByParser; -import gov.nist.javax.sip.parser.extensions.ReplacesParser; -import gov.nist.javax.sip.parser.extensions.SessionExpiresParser; -import gov.nist.javax.sip.parser.ims.PAccessNetworkInfoParser; -import gov.nist.javax.sip.parser.ims.PAssertedIdentityParser; -import gov.nist.javax.sip.parser.ims.PAssociatedURIParser; -import gov.nist.javax.sip.parser.ims.PCalledPartyIDParser; -import gov.nist.javax.sip.parser.ims.PChargingFunctionAddressesParser; -import gov.nist.javax.sip.parser.ims.PChargingVectorParser; -import gov.nist.javax.sip.parser.ims.PMediaAuthorizationParser; -import gov.nist.javax.sip.parser.ims.PPreferredIdentityParser; -import gov.nist.javax.sip.parser.ims.PVisitedNetworkIDParser; -import gov.nist.javax.sip.parser.ims.PathParser; -import gov.nist.javax.sip.parser.ims.PrivacyParser; -import gov.nist.javax.sip.parser.ims.SecurityClientParser; -import gov.nist.javax.sip.parser.ims.SecurityServerParser; -import gov.nist.javax.sip.parser.ims.SecurityVerifyParser; -import gov.nist.javax.sip.parser.ims.ServiceRouteParser; - -import java.lang.reflect.Constructor; +import gov.nist.javax.sip.parser.ims.*; +import gov.nist.javax.sip.header.ims.*; +import java.util.Hashtable; +import java.lang.reflect.*; +import javax.sip.header.*; import java.text.ParseException; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import javax.sip.header.AcceptEncodingHeader; -import javax.sip.header.AcceptHeader; -import javax.sip.header.AcceptLanguageHeader; -import javax.sip.header.AlertInfoHeader; -import javax.sip.header.AllowEventsHeader; -import javax.sip.header.AllowHeader; -import javax.sip.header.AuthenticationInfoHeader; -import javax.sip.header.AuthorizationHeader; -import javax.sip.header.CSeqHeader; -import javax.sip.header.CallIdHeader; -import javax.sip.header.CallInfoHeader; -import javax.sip.header.ContactHeader; -import javax.sip.header.ContentDispositionHeader; -import javax.sip.header.ContentEncodingHeader; -import javax.sip.header.ContentLanguageHeader; -import javax.sip.header.ContentLengthHeader; -import javax.sip.header.ContentTypeHeader; -import javax.sip.header.DateHeader; -import javax.sip.header.ErrorInfoHeader; -import javax.sip.header.EventHeader; -import javax.sip.header.ExpiresHeader; -import javax.sip.header.FromHeader; -import javax.sip.header.InReplyToHeader; -import javax.sip.header.MaxForwardsHeader; -import javax.sip.header.MimeVersionHeader; -import javax.sip.header.MinExpiresHeader; -import javax.sip.header.OrganizationHeader; -import javax.sip.header.PriorityHeader; -import javax.sip.header.ProxyAuthenticateHeader; -import javax.sip.header.ProxyAuthorizationHeader; -import javax.sip.header.ProxyRequireHeader; -import javax.sip.header.RAckHeader; -import javax.sip.header.RSeqHeader; -import javax.sip.header.ReasonHeader; -import javax.sip.header.RecordRouteHeader; -import javax.sip.header.ReferToHeader; -import javax.sip.header.ReplyToHeader; -import javax.sip.header.RequireHeader; -import javax.sip.header.RetryAfterHeader; -import javax.sip.header.RouteHeader; -import javax.sip.header.SIPETagHeader; -import javax.sip.header.SIPIfMatchHeader; -import javax.sip.header.ServerHeader; -import javax.sip.header.SubjectHeader; -import javax.sip.header.SubscriptionStateHeader; -import javax.sip.header.SupportedHeader; -import javax.sip.header.TimeStampHeader; -import javax.sip.header.ToHeader; -import javax.sip.header.UnsupportedHeader; -import javax.sip.header.UserAgentHeader; -import javax.sip.header.ViaHeader; -import javax.sip.header.WWWAuthenticateHeader; -import javax.sip.header.WarningHeader; +import gov.nist.core.*; +import gov.nist.javax.sip.header.extensions.*; +import gov.nist.javax.sip.header.SIPHeaderNamesCache; +import gov.nist.javax.sip.parser.extensions.*; /** * A factory class that does a name lookup on a registered parser and * returns a header parser for the given name. * - * @version 1.2 $Revision: 1.18 $ $Date: 2010-05-06 14:07:44 $ + * @version 1.2 $Revision: 1.17 $ $Date: 2010-01-12 00:05:25 $ * * @author M. Ranganathan
    * @@ -140,14 +47,14 @@ * */ public class ParserFactory { - //jeand : moving to concurrent structures to avoid blocking witnessed during profiling - private static Map> parserTable; + + private static Hashtable> parserTable; private static Class[] constructorArgs; - private static ConcurrentHashMap parserConstructorCache; + private static Hashtable parserConstructorCache; static { - parserTable = new ConcurrentHashMap>(90); - parserConstructorCache = new ConcurrentHashMap(); + parserTable = new Hashtable>(); + parserConstructorCache = new Hashtable(); constructorArgs = new Class[1]; constructorArgs[0] = String.class; parserTable.put(ReplyToHeader.NAME.toLowerCase(), ReplyToParser.class); @@ -387,7 +294,7 @@ public static HeaderParser createParser(String line) Constructor cons = (Constructor) parserConstructorCache.get(parserClass); if (cons == null) { cons = parserClass.getConstructor(constructorArgs); - parserConstructorCache.putIfAbsent(parserClass, cons); + parserConstructorCache.put(parserClass, cons); } Object[] args = new Object[1]; args[0] = line; @@ -408,9 +315,6 @@ public static HeaderParser createParser(String line) } /* * $Log: not supported by cvs2svn $ - * Revision 1.17 2010/01/12 00:05:25 mranga - * Add support for References header draft-worley-references-05 - * * Revision 1.16 2009/07/17 18:58:01 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * diff --git a/src/gov/nist/javax/sip/parser/Pipeline.java b/src/gov/nist/javax/sip/parser/Pipeline.java index b55891c98..30e3bc3be 100755 --- a/src/gov/nist/javax/sip/parser/Pipeline.java +++ b/src/gov/nist/javax/sip/parser/Pipeline.java @@ -27,12 +27,9 @@ import gov.nist.core.InternalErrorHandler; import gov.nist.javax.sip.stack.SIPStackTimerTask; -import gov.nist.javax.sip.stack.timers.SipTimer; -import java.io.IOException; -import java.io.InputStream; -import java.util.LinkedList; -import java.util.NoSuchElementException; +import java.io.*; +import java.util.*; /** * Input class for the pipelined parser. Buffer all bytes read from the socket @@ -50,13 +47,13 @@ public class Pipeline extends InputStream { private boolean isClosed; - private SipTimer timer; + private Timer timer; private InputStream pipe; private int readTimeout; - private SIPStackTimerTask myTimerTask; + private TimerTask myTimerTask; class MyTimer extends SIPStackTimerTask { Pipeline pipeline; @@ -67,11 +64,9 @@ protected MyTimer(Pipeline pipeline) { this.pipeline = pipeline; } - public void runTask() { - if (this.isCancelled) { - this.pipeline = null; + protected void runTask() { + if (this.isCancelled) return; - } try { pipeline.close(); @@ -80,13 +75,12 @@ public void runTask() { } } - @Override - public void cleanUpBeforeCancel() { - this.isCancelled = true; - this.pipeline = null; - super.cleanUpBeforeCancel(); + public boolean cancel() { + boolean retval = super.cancel(); + this.isCancelled = true; + return retval; } - + } class Buffer { @@ -121,10 +115,10 @@ public void stopTimer() { if (this.readTimeout == -1) return; if (this.myTimerTask != null) - this.timer.cancel(myTimerTask); + this.myTimerTask.cancel(); } - public Pipeline(InputStream pipe, int readTimeout, SipTimer timer) { + public Pipeline(InputStream pipe, int readTimeout, Timer timer) { // pipe is the Socket stream // this is recorded here to implement a timeout. this.timer = timer; @@ -181,7 +175,7 @@ public int read() throws IOException { // wait till something is posted. while (this.buffList.isEmpty()) { this.buffList.wait(); - // jeand : Issue 314 : return -1 only is the buffer is empty + // jeand : Issue 314 : return -1 only if the buffer is empty if (this.buffList.isEmpty() && this.isClosed) return -1; } diff --git a/src/gov/nist/javax/sip/parser/PipelinedMsgParser.java b/src/gov/nist/javax/sip/parser/PipelinedMsgParser.java index 38f24bf71..0912f97f1 100755 --- a/src/gov/nist/javax/sip/parser/PipelinedMsgParser.java +++ b/src/gov/nist/javax/sip/parser/PipelinedMsgParser.java @@ -36,9 +36,8 @@ * life goes slower but more reliably. * */ -import gov.nist.core.CommonLogger; +import gov.nist.core.Debug; import gov.nist.core.InternalErrorHandler; -import gov.nist.core.LogLevels; import gov.nist.core.LogWriter; import gov.nist.core.StackLogger; import gov.nist.javax.sip.header.ContentLength; @@ -72,16 +71,15 @@ * accessed from the SIPMessage using the getContent and getContentBytes methods * provided by the SIPMessage class. * - * @version 1.2 $Revision: 1.39 $ $Date: 2010-12-02 22:04:22 $ + * @version 1.2 $Revision: 1.28.2.9 $ $Date: 2010-12-02 08:19:52 $ * * @author M. Ranganathan * * @see SIPMessageListener */ public final class PipelinedMsgParser implements Runnable { - private static StackLogger logger = CommonLogger.getLogger(PipelinedMsgParser.class); - private static final String CRLF = "\r\n"; + /** * The message listener that is registered with this parser. (The message @@ -95,7 +93,6 @@ public final class PipelinedMsgParser implements Runnable { private int maxMessageSize; private int sizeCounter; private SIPTransactionStack sipStack; - private MessageParser smp = null; private ConcurrentHashMap messagesOrderingMap = new ConcurrentHashMap(); boolean isRunning = false; @@ -103,13 +100,14 @@ public final class PipelinedMsgParser implements Runnable { * default constructor. */ protected PipelinedMsgParser() { - super(); + super(); + } private static int uid = 0; private static synchronized int getNewUid() { - return uid++; + return uid++%99999999; } /** @@ -128,7 +126,9 @@ public PipelinedMsgParser(SIPTransactionStack sipStack, SIPMessageListener sipMe Pipeline in, boolean debug, int maxMessageSize) { this(); this.sipStack = sipStack; - smp = sipStack.getMessageParserFactory().createMessageParser(sipStack); + if(staticQueueAuditor != null) { + staticQueueAuditor.setLogger(sipStack.getStackLogger()); + } this.sipMessageListener = sipMessageListener; rawInputStream = in; this.maxMessageSize = maxMessageSize; @@ -159,9 +159,6 @@ public PipelinedMsgParser(SIPTransactionStack sipStack, SIPMessageListener mhand * An input stream to read messages from. */ - public PipelinedMsgParser(SIPTransactionStack sipStack, Pipeline in) { - this(sipStack, null, in, false, 0); - } /** * Start reading and processing input. @@ -181,7 +178,7 @@ protected Object clone() { p.rawInputStream = this.rawInputStream; p.sipMessageListener = this.sipMessageListener; Thread mythread = new Thread(p); - mythread.setName("PipelineThread"); + mythread.setName(this.mythread.getName()); return p; } @@ -208,9 +205,6 @@ private String readLine(InputStream inputStream) throws IOException { int increment = 1024; int bufferSize = increment; byte[] lineBuffer = new byte[bufferSize]; - // handles RFC 5626 CRLF keepalive mechanism - byte[] crlfBuffer = new byte[2]; - int crlfCounter = 0; while (true) { char ch; int i = inputStream.read(); @@ -226,30 +220,20 @@ private String readLine(InputStream inputStream) throws IOException { } if (ch != '\r') lineBuffer[counter++] = (byte) (i&0xFF); - else if (counter == 0) - crlfBuffer[crlfCounter++] = (byte) '\r'; - + if (ch == '\n') { - if(counter == 1 && crlfCounter > 0) { - crlfBuffer[crlfCounter++] = (byte) '\n'; - } - break; + break; } if( counter == bufferSize ) { - byte[] tempBuffer = new byte[bufferSize + increment]; + byte[] tempBuffer = new byte[bufferSize + increment]; System.arraycopy((Object)lineBuffer,0, (Object)tempBuffer, 0, bufferSize); - bufferSize = bufferSize + increment; - lineBuffer = tempBuffer; + bufferSize = bufferSize + increment; + lineBuffer = tempBuffer; } } - if(counter == 1 && crlfCounter > 0) { - return new String(crlfBuffer,0,crlfCounter,"UTF-8"); - } else { - return new String(lineBuffer,0,counter,"UTF-8"); - } - + return new String(lineBuffer,0,counter,"UTF-8"); } public class Dispatch implements Runnable, QueuedMessageDispatchBase{ @@ -273,28 +257,28 @@ public void run() { try { semaphore.acquire(); } catch (InterruptedException e) { - logger.logError("Semaphore acquisition for callId " + callId + " interrupted", e); + sipStack.getStackLogger().logError("Semaphore acquisition for callId " + callId + " interrupted", e); } // once acquired we get the first message to process SIPMessage message = messagesForCallID.poll(); - if (logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) { - logger.logDebug("semaphore acquired for message " + message); + if (sipStack.getStackLogger().isLoggingEnabled(StackLogger.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("semaphore acquired for message " + message + " threadname " + mythread.getName()); } try { sipMessageListener.processMessage(message); } catch (Exception e) { - logger.logError("Error occured processing message", e); + sipStack.getStackLogger().logError("Error occured processing message", e); // We do not break the TCP connection because other calls use the same socket here } finally { - if(messagesForCallID.size() <= 0) { + if(messagesForCallID.isEmpty()) { messagesOrderingMap.remove(callId); - if (logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) { - logger.logDebug("CallIDOrderingStructure removed for message " + callId); + if (sipStack.getStackLogger().isLoggingEnabled(StackLogger.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("CallIDOrderingStructure removed for message " + callId); } } - if (logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) { - logger.logDebug("releasing semaphore for message " + message); + if (sipStack.getStackLogger().isLoggingEnabled(StackLogger.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("releasing semaphore for message " + message + " threadname " + mythread.getName()); } //release the semaphore so that another thread can process another message from the call id queue in the correct order // or a new message from another call id queue @@ -308,8 +292,8 @@ public void run() { sipStack.sipEventInterceptor.afterMessage(message); } } - if (logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) { - logger.logDebug("dispatch task done on " + message + " threadname " + mythread.getName()); + if (sipStack.getStackLogger().isLoggingEnabled(StackLogger.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("dispatch task done on " + message + " threadname " + mythread.getName()); } } public long getReceptionTime() { @@ -325,76 +309,53 @@ public long getReceptionTime() { public void run() { Pipeline inputStream = this.rawInputStream; - final StackLogger stackLogger = logger; + final StackLogger stackLogger = sipStack.getStackLogger(); // inputStream = new MyFilterInputStream(this.rawInputStream); // I cannot use buffered reader here because we may need to switch // encodings to read the message body. try { - isRunning = true; + isRunning = true; while (isRunning) { this.sizeCounter = this.maxMessageSize; // this.messageSize = 0; - StringBuilder inputBuffer = new StringBuilder(); + StringBuffer inputBuffer = new StringBuffer(); - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug("Starting to parse."); - } + if (Debug.parserDebug) + Debug.println("Starting parse!"); String line1; String line2 = null; - boolean isPreviousLineCRLF = false; + while (true) { try { line1 = readLine(inputStream); // ignore blank lines. if (line1.equals("\n")) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug("Discarding blank line"); + if (Debug.parserDebug) { + Debug.println("Discarding blank line. "); } continue; - } else if(CRLF.equals(line1)) { - if(isPreviousLineCRLF) { - // Handling keepalive ping (double CRLF) as defined per RFC 5626 Section 4.4.1 - // sending pong (single CRLF) - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("KeepAlive Double CRLF received, sending single CRLF as defined per RFC 5626 Section 4.4.1"); - } - try { - sipMessageListener.sendSingleCLRF(); - } catch (Exception e) { - logger.logError("A problem occured while trying to send a single CLRF in response to a double CLRF", e); - } - continue; - } else { - isPreviousLineCRLF = true; - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug("Received CRLF"); - } - } - continue; - } else + } else break; } catch (IOException ex) { - // we only wait if the thread is still in a running state and hasn't been close from somewhere else + // we only wait if the thread is still in a running state and hasn't been close from somewhere else // or we are leaking because the thread is waiting forever if(postParseExecutor != null && isRunning){ - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("waiting for messagesOrderingMap " + this + " threadname " + mythread.getName()); - synchronized (messagesOrderingMap) { + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("waiting for messagesOrderingMap " + this + " threadname " + mythread.getName()); + synchronized (messagesOrderingMap) { try { messagesOrderingMap.wait(64000); } catch (InterruptedException e) {} - } - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("got notified for messagesOrderingMap " + this + " threadname " + mythread.getName()); + } + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("got notified or the wait timed out after 64s for messagesOrderingMap " + this + " threadname " + mythread.getName()); } - this.rawInputStream.stopTimer(); - if (logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) { - logger.logDebug("thread ending for threadname " + mythread.getName()); + this.rawInputStream.stopTimer(); + if (sipStack.getStackLogger().isLoggingEnabled(StackLogger.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("thread ending for threadname " + mythread.getName()); } - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logStackTrace(LogLevels.TRACE_DEBUG); - } + Debug.printStackTrace(ex); return; } } @@ -403,9 +364,7 @@ public void run() { // Guard against bad guys. this.rawInputStream.startTimer(); - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug("Reading Input stream."); - } + Debug.println("Reading Input Stream"); while (true) { try { line2 = readLine(inputStream); @@ -413,54 +372,53 @@ public void run() { if (line2.trim().equals("")) break; } catch (IOException ex) { - // we only wait if the thread is still in a running state and hasn't been close from somewhere else + // we only wait if the thread is still in a running state and hasn't been close from somewhere else // or we are leaking because the thread is waiting forever - if(postParseExecutor != null && isRunning){ - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("waiting for messagesOrderingMap " + this + " threadname " + mythread.getName()); + if(postParseExecutor != null && isRunning) { + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("waiting for messagesOrderingMap " + this + " threadname " + mythread.getName()); synchronized (messagesOrderingMap) { try { messagesOrderingMap.wait(64000); } catch (InterruptedException e) {} - } - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("got notified for messagesOrderingMap " + this + " threadname " + mythread.getName()); - } + } + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("got notified or the wait timed out after 64s for messagesOrderingMap " + this + " threadname " + mythread.getName()); + } this.rawInputStream.stopTimer(); - if (logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) { - logger.logDebug("thread ending for threadname " + mythread.getName()); + if (sipStack.getStackLogger().isLoggingEnabled(StackLogger.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("thread ending for threadname " + mythread.getName()); } - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logStackTrace(LogLevels.TRACE_DEBUG); - } + Debug.printStackTrace(ex); return; } } // Stop the timer that will kill the read. this.rawInputStream.stopTimer(); - inputBuffer.append(line2); -// smp.setParseExceptionListener(sipMessageListener); -// smp.setReadBody(false); + inputBuffer.append(line2); + MessageParser smp = sipStack.getMessageParserFactory().createMessageParser(sipStack); + smp.setParseExceptionListener(sipMessageListener); + smp.setReadBody(false); SIPMessage sipMessage = null; try { if (stackLogger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) { - stackLogger.logDebug("About to parse : " + inputBuffer.toString()); + stackLogger.logDebug("About to parse : " + inputBuffer.toString()); } - sipMessage = smp.parseSIPMessage(inputBuffer.toString().getBytes(), false, false, sipMessageListener); + sipMessage = smp.parseSIPMessage(inputBuffer.toString().getBytes()); if (sipMessage == null) { this.rawInputStream.stopTimer(); continue; } } catch (ParseException ex) { // Just ignore the parse exception. - stackLogger.logError("Detected a parse error", ex); + stackLogger.logError("Detected a parse error", ex); continue; } - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug("Completed parsing message"); + if (Debug.debug) { + Debug.println("Completed parsing message"); } ContentLength cl = (ContentLength) sipMessage .getContentLength(); @@ -471,8 +429,8 @@ public void run() { contentLength = 0; } - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug("Content length = " + contentLength); + if (Debug.debug) { + Debug.println("contentLength " + contentLength); } if (contentLength == 0) { @@ -513,7 +471,6 @@ public void run() { if (sipMessageListener != null) { try { if(postParseExecutor == null) { - /** * If gov.nist.javax.sip.TCP_POST_PARSING_THREAD_POOL_SIZE is disabled * we continue with the old logic here. @@ -551,10 +508,12 @@ public void run() { // to avoid blocking other messages with a different call id // that could be processed in parallel callIDOrderingStructure.getMessagesForCallID().offer(sipMessage); - - postParseExecutor.execute(new Dispatch(callIDOrderingStructure, callId)); // run in executor thread + + postParseExecutor.execute(new Dispatch(callIDOrderingStructure, callId)); } } catch (Exception ex) { + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("error on processing... breaking " + this + " threadname " + mythread.getName()); // fatal error in processing - close the // connection. break; @@ -563,17 +522,22 @@ public void run() { } } finally { try { - cleanMessageOrderingMap(); - if(!inputStream.isClosed()) { + cleanMessageOrderingMap(); + if(!inputStream.isClosed()) { inputStream.close(); } } catch (IOException e) { + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("ioexception on cleaning up " + this + " threadname " + mythread.getName()); InternalErrorHandler.handleException(e); } } + if (sipStack.getStackLogger().isLoggingEnabled(StackLogger.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("thread ending for threadname " + mythread.getName()); + } } - private static ExecutorService postParseExecutor = null; + private static ExecutorService postParseExecutor = null; public static class NamedThreadFactory implements ThreadFactory { static long threadNumber = 0; @@ -584,10 +548,10 @@ public Thread newThread(Runnable arg0) { } } - + public static BlockingQueue staticQueue; public static BlockingQueueDispatchAuditor staticQueueAuditor; - public static void setPostParseExcutorSize(int threads, int queueTimeout){ + public static void setPostParseExcutorSize(int threads, int timeout){ if(postParseExecutor != null) { postParseExecutor.shutdownNow(); } @@ -598,21 +562,27 @@ public static void setPostParseExcutorSize(int threads, int queueTimeout){ } } - if(threads<=0) { - postParseExecutor = null; - } else { - staticQueue = new LinkedBlockingQueue(); - postParseExecutor = new ThreadPoolExecutor(threads, threads, - 0, TimeUnit.SECONDS, staticQueue, - new NamedThreadFactory()); - - staticQueueAuditor = new BlockingQueueDispatchAuditor(staticQueue); - staticQueueAuditor.setTimeout(queueTimeout); - staticQueueAuditor.start(2000); + if(postParseExecutor == null) { + if(threads<=0) { + postParseExecutor = null; + } else { + if(staticQueueAuditor != null) { + staticQueueAuditor.stop(); + } + staticQueue = new LinkedBlockingQueue(); + postParseExecutor = new ThreadPoolExecutor(threads, threads, + 0, TimeUnit.SECONDS, staticQueue, + new NamedThreadFactory()); + if(timeout>0) { + staticQueueAuditor = new BlockingQueueDispatchAuditor(staticQueue); + staticQueueAuditor.setTimeout(timeout); + staticQueueAuditor.start(2000); + } + } } - } + /** * Data structure to make sure ordering of Messages is guaranteed under TCP when the post parsing thread pool is used * @author jean.deruelle@gmail.com @@ -643,14 +613,14 @@ public Queue getMessagesForCallID() { } public void close() { - isRunning = false; - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("Closing pipelinedmsgparser " + this + " threadname " + mythread.getName()); + isRunning = false; + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Closing pipelinedmsgparser " + this + " threadname " + mythread.getName()); try { this.rawInputStream.close(); } catch (IOException ex) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("Couldn't close the rawInputStream " + this + " threadname " + mythread.getName() + " already closed ? " + rawInputStream.isClosed()); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Couldn't close the rawInputStream " + this + " threadname " + mythread.getName() + " already closed ? " + rawInputStream.isClosed()); // Ignore. } if(postParseExecutor != null){ @@ -661,7 +631,7 @@ public void close() { // eventually leads to thread leaking and OutOfMemory mythread.interrupt(); } - } + } } public static void shutdownTcpThreadpool() { @@ -669,42 +639,37 @@ public static void shutdownTcpThreadpool() { postParseExecutor.shutdown(); postParseExecutor = null; } - if(staticQueueAuditor != null) { - try { - staticQueueAuditor.stop(); - } catch (Exception e) { - - } - } } - private void cleanMessageOrderingMap() { + private void cleanMessageOrderingMap() { // not needed and can cause NPE on close if race condition // for (CallIDOrderingStructure callIDOrderingStructure: messagesOrderingMap.values()) { // callIDOrderingStructure.getSemaphore().release(); // callIDOrderingStructure.getMessagesForCallID().clear(); // } - messagesOrderingMap.clear(); - synchronized (messagesOrderingMap) { + messagesOrderingMap.clear(); + synchronized (messagesOrderingMap) { messagesOrderingMap.notifyAll(); } - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("cleaned the messagesOrderingMap " + this + " threadname " + mythread.getName()); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("cleaned the messagesOrderingMap " + this + " threadname " + mythread.getName()); } } /* * $Log: not supported by cvs2svn $ - * Revision 1.38 2010/12/02 11:44:16 vralev + * Revision 1.28.2.8 2010/12/02 08:06:37 vralev * Issue number: 346 * Obtained from: vralev * - * Congestion control. Patch + Tests for HEAD + * Fix JDK 1.5 compatibility * - * Revision 1.37 2010/10/26 23:49:12 vralev - * Issue number: 337 + * Revision 1.28.2.7 2010/12/02 01:41:36 vralev + * Issue number: 346 * Obtained from: vralev * - * Revision 1.36 2010/10/13 15:26:59 deruelle_jean + * Patch + Tests for sipx branch + * + * Revision 1.28.2.6 2010/10/13 15:26:52 deruelle_jean * Fix for TCP calls under load freeze JAIN SIP with TCP_POST_PARSING_THREAD_POOL_SIZE > 0 * * Issue number: @@ -712,7 +677,7 @@ private void cleanMessageOrderingMap() { * Submitted by: Jean Deruelle * Reviewed by: * - * Revision 1.35 2010/10/12 18:47:16 deruelle_jean + * Revision 1.28.2.5 2010/10/12 18:47:22 deruelle_jean * Fix for restarting the stack when the gov.nist.javax.sip.TCP_POST_PARSING_THREAD_POOL_SIZE option is used * * Issue number: @@ -720,8 +685,8 @@ private void cleanMessageOrderingMap() { * Submitted by: Jean Deruelle * Reviewed by: * - * Revision 1.34 2010/10/07 15:40:25 deruelle_jean - * Adding some cleaning up to POST_PARSING_THREAD_POOL option + * Revision 1.28.2.4 2010/10/07 15:38:52 deruelle_jean + * Backporting POST_PARSING_THREAD_POOL fixes to the stable branch * * Issue number: * Obtained from: diff --git a/src/gov/nist/javax/sip/parser/SIPMessageListener.java b/src/gov/nist/javax/sip/parser/SIPMessageListener.java index 6cb6b2e23..ebfe84872 100755 --- a/src/gov/nist/javax/sip/parser/SIPMessageListener.java +++ b/src/gov/nist/javax/sip/parser/SIPMessageListener.java @@ -44,8 +44,6 @@ public interface SIPMessageListener extends ParseExceptionListener { * @param msg SIP Message structure that is generated by the parser. */ public void processMessage(SIPMessage msg) throws Exception; - - public void sendSingleCLRF() throws Exception; } /* * $Log: not supported by cvs2svn $ diff --git a/src/gov/nist/javax/sip/parser/StringMsgParser.java b/src/gov/nist/javax/sip/parser/StringMsgParser.java index 0269b189c..9b208f4db 100755 --- a/src/gov/nist/javax/sip/parser/StringMsgParser.java +++ b/src/gov/nist/javax/sip/parser/StringMsgParser.java @@ -37,11 +37,7 @@ import gov.nist.javax.sip.address.GenericURI; import gov.nist.javax.sip.address.SipUri; import gov.nist.javax.sip.address.TelephoneNumber; -import gov.nist.javax.sip.header.ExtensionHeaderImpl; -import gov.nist.javax.sip.header.NameMap; -import gov.nist.javax.sip.header.RequestLine; -import gov.nist.javax.sip.header.SIPHeader; -import gov.nist.javax.sip.header.StatusLine; +import gov.nist.javax.sip.header.*; import gov.nist.javax.sip.message.SIPMessage; import gov.nist.javax.sip.message.SIPRequest; import gov.nist.javax.sip.message.SIPResponse; @@ -68,7 +64,7 @@ * feld swoop). * * - * @version 1.2 $Revision: 1.28 $ $Date: 2010-05-06 14:07:44 $ + * @version 1.2 $Revision: 1.27 $ $Date: 2010-03-15 17:01:21 $ * * @author M. Ranganathan
    * @@ -76,6 +72,11 @@ */ public class StringMsgParser implements MessageParser { + protected boolean readBody; + protected ParseExceptionListener parseExceptionListener; + protected String rawStringMessage; + private boolean strict; + protected static boolean computeContentLengthFromMessage = false; /** @@ -83,6 +84,30 @@ public class StringMsgParser implements MessageParser { */ public StringMsgParser() { super(); + readBody = true; + } + + /** + * Constructor (given a parse exception handler). + * + * @since 1.0 + * @param exhandler + * is the parse exception listener for the message parser. + */ + public StringMsgParser(ParseExceptionListener exhandler) { + this(); + parseExceptionListener = exhandler; + } + + /** + * Add a handler for header parsing errors. + * + * @param pexhandler + * is a class that implements the ParseExceptionListener + * interface. + */ + public void setParseExceptionListener(ParseExceptionListener pexhandler) { + parseExceptionListener = pexhandler; } /** @@ -101,7 +126,7 @@ public StringMsgParser() { * (and the rest of the buffer is discarded). * @see ParseExceptionListener */ - public SIPMessage parseSIPMessage(byte[] msgBuffer, boolean readBody, boolean strict, ParseExceptionListener parseExceptionListener) throws ParseException { + public SIPMessage parseSIPMessage(byte[] msgBuffer) throws ParseException { if (msgBuffer == null || msgBuffer.length == 0) return null; @@ -149,13 +174,13 @@ public SIPMessage parseSIPMessage(byte[] msgBuffer, boolean readBody, boolean st if (currentLine.length() == 0) { // Last header line, process the previous buffered header. if (currentHeader != null && message != null) { - processHeader(currentHeader, message, parseExceptionListener, msgBuffer); + processHeader(currentHeader, message); } } else { if (isFirstLine) { - message = processFirstLine(currentLine, parseExceptionListener, msgBuffer); + message = processFirstLine(currentLine); } else { char firstChar = currentLine.charAt(0); if (firstChar == '\t' || firstChar == ' ') { @@ -167,7 +192,7 @@ public SIPMessage parseSIPMessage(byte[] msgBuffer, boolean readBody, boolean st } else { if (currentHeader != null && message != null) { - processHeader(currentHeader, message, parseExceptionListener, msgBuffer); + processHeader(currentHeader, message); } currentHeader = currentLine; } @@ -185,20 +210,127 @@ public SIPMessage parseSIPMessage(byte[] msgBuffer, boolean readBody, boolean st if (message == null) throw new ParseException("Bad message", 0); message.setSize(i); + if (readBody && message.getContentLength() != null && + message.getContentLength().getContentLength() != 0) { + + int bodyLength = msgBuffer.length - i; + + byte[] body = new byte[bodyLength]; + System.arraycopy(msgBuffer, i, body, 0, bodyLength); + message.setMessageContent(body,computeContentLengthFromMessage ,message.getContentLength().getContentLength() ); + } + + return message; + } + + /** + * Parse a buffer containing one or more SIP Messages and return an array of + * SIPMessage parsed structures. + * + * @param msgString + * a String containing the messages to be parsed. This can + * consist of multiple SIP Messages concatenated together. + * @return a SIPMessage structure (request or response) containing the + * parsed SIP message. + * @exception ParseException + * is thrown when an illegal message has been encountered + * (and the rest of the buffer is discarded). + * @see ParseExceptionListener + */ + public SIPMessage parseSIPMessage(String msgString) throws ParseException { + if (msgString == null || msgString.length() == 0) + return null; + + rawStringMessage = msgString; + + int i = 0; + + // Squeeze out any leading control character. + try { + while (msgString.charAt(i) < 0x20) + i++; + } + catch (ArrayIndexOutOfBoundsException e) { + // Array contains only control char, return null. + return null; + } catch (StringIndexOutOfBoundsException ex) { + return null; + } + + // Iterate thru the request/status line and headers. + String currentLine = null; + String currentHeader = null; + boolean isFirstLine = true; + SIPMessage message = null; + do + { + int lineStart = i; + + // Find the length of the line. + try { + char c = msgString.charAt(i); + while (c != '\r' && c != '\n') + c = msgString.charAt(++i); + } + catch (ArrayIndexOutOfBoundsException e) { + // End of the message. + break; + } catch ( StringIndexOutOfBoundsException ex) { + break; + } + + // Make it a String. + currentLine = msgString.substring(lineStart, i); + currentLine = trimEndOfLine(currentLine); + + if (currentLine.length() == 0) { + // Last header line, process the previous buffered header. + if (currentHeader != null) { + processHeader(currentHeader, message); + } + } + else { + if (isFirstLine) { + message = processFirstLine(currentLine); + } else { + char firstChar = currentLine.charAt(0); + if (firstChar == '\t' || firstChar == ' ') { + if (currentHeader == null) + throw new ParseException("Bad header continuation.", 0); + + // This is a continuation, append it to the previous line. + currentHeader += currentLine.substring(1); + } + else { + if (currentHeader != null) { + processHeader(currentHeader, message); + } + currentHeader = currentLine; + } + } + } + + if (msgString.charAt(i) == '\r' && msgString.length() > i+1 && msgString.charAt(i+1) == '\n') + i++; + + i++; + + isFirstLine = false; + } + while (currentLine.length() > 0); + + message.setSize(i); + // Check for content legth header if (readBody && message.getContentLength() != null ) { - if ( message.getContentLength().getContentLength() != 0) { - int bodyLength = msgBuffer.length - i; - - byte[] body = new byte[bodyLength]; - System.arraycopy(msgBuffer, i, body, 0, bodyLength); - message.setMessageContent(body,!strict,computeContentLengthFromMessage,message.getContentLength().getContentLength()); - } else if (!computeContentLengthFromMessage && message.getContentLength().getContentLength() == 0 & strict) { - String last4Chars = new String(msgBuffer, msgBuffer.length - 4, 4); - if(!"\r\n\r\n".equals(last4Chars)) { - throw new ParseException("Extraneous characters at the end of the message ",i); - } - } + if ( message.getContentLength().getContentLength() != 0) { + String body = msgString.substring(i); + message.setMessageContent(body,this.strict,computeContentLengthFromMessage,message.getContentLength().getContentLength()); + } else if (!computeContentLengthFromMessage && message.getContentLength().getContentLength() == 0 && !msgString.endsWith("\r\n\r\n") ){ + if ( strict ) { + throw new ParseException("Extraneous characters at the end of the message ",i); + } + } } @@ -222,7 +354,7 @@ protected static String trimEndOfLine(String line) { return line.substring(0, i+1); } - protected SIPMessage processFirstLine(String firstLine, ParseExceptionListener parseExceptionListener, byte[] msgBuffer) throws ParseException { + private SIPMessage processFirstLine(String firstLine) throws ParseException { SIPMessage message; if (!firstLine.startsWith(SIPConstants.SIP_VERSION_STRING)) { message = new SIPRequest(); @@ -231,14 +363,10 @@ protected SIPMessage processFirstLine(String firstLine, ParseExceptionListener p .parse(); ((SIPRequest) message).setRequestLine(requestLine); } catch (ParseException ex) { - if (parseExceptionListener != null) - try { - parseExceptionListener.handleException(ex, message, - RequestLine.class, firstLine, new String(msgBuffer, "UTF-8")); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } - else + if (this.parseExceptionListener != null) + this.parseExceptionListener.handleException(ex, message, + RequestLine.class, firstLine, rawStringMessage); + else throw ex; } @@ -248,13 +376,9 @@ protected SIPMessage processFirstLine(String firstLine, ParseExceptionListener p StatusLine sl = new StatusLineParser(firstLine + "\n").parse(); ((SIPResponse) message).setStatusLine(sl); } catch (ParseException ex) { - if (parseExceptionListener != null) { - try { - parseExceptionListener.handleException(ex, message, - StatusLine.class, firstLine, new String(msgBuffer, "UTF-8")); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } + if (this.parseExceptionListener != null) { + this.parseExceptionListener.handleException(ex, message, + StatusLine.class, firstLine, rawStringMessage); } else throw ex; @@ -263,7 +387,7 @@ protected SIPMessage processFirstLine(String firstLine, ParseExceptionListener p return message; } - protected void processHeader(String header, SIPMessage message, ParseExceptionListener parseExceptionListener, byte[] rawMessage) throws ParseException { + protected void processHeader(String header, SIPMessage message) throws ParseException { if (header == null || header.length() == 0) return; @@ -271,8 +395,8 @@ protected void processHeader(String header, SIPMessage message, ParseExceptionLi try { headerParser = ParserFactory.createParser(header + "\n"); } catch (ParseException ex) { - parseExceptionListener.handleException(ex, message, null, - header, null); + this.parseExceptionListener.handleException(ex, message, null, + header, rawStringMessage); return; } @@ -280,19 +404,15 @@ protected void processHeader(String header, SIPMessage message, ParseExceptionLi SIPHeader sipHeader = headerParser.parse(); message.attachHeader(sipHeader, false); } catch (ParseException ex) { - if (parseExceptionListener != null) { + if (this.parseExceptionListener != null) { String headerName = Lexer.getHeaderName(header); Class headerClass = NameMap.getClassFromName(headerName); if (headerClass == null) { headerClass = ExtensionHeaderImpl.class; } - try { - parseExceptionListener.handleException(ex, message, - headerClass, header, new String(rawMessage, "UTF-8")); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } + this.parseExceptionListener.handleException(ex, message, + headerClass, header, rawStringMessage); } } @@ -405,7 +525,7 @@ public GenericURI parseUrl(String url) throws ParseException { * @exception ParseException * if there was an error parsing the message. */ - public static SIPHeader parseSIPHeader(String header) throws ParseException { + public SIPHeader parseSIPHeader(String header) throws ParseException { int start = 0; int end = header.length() - 1; try { @@ -422,7 +542,7 @@ public static SIPHeader parseSIPHeader(String header) throws ParseException { throw new ParseException("Empty header.", 0); } - StringBuilder buffer = new StringBuilder(end + 1); + StringBuffer buffer = new StringBuffer(end + 1); int i = start; int lineStart = start; boolean endOfLine = false; @@ -560,7 +680,7 @@ public void run() { StringMsgParser smp = new StringMsgParser(); try { SIPMessage sipMessage = smp - .parseSIPMessage(messages[i].getBytes(), true, false, null); + .parseSIPMessage(messages[i]); System.out.println(" i = " + i + " branchId = " + sipMessage.getTopmostVia().getBranch()); // System.out.println("encoded " + @@ -581,4 +701,13 @@ public void run() { } + public void setStrict(boolean strict) { + this.strict = strict; + + } + + public void setReadBody(boolean readBody) { + this.readBody = readBody; + } + } diff --git a/src/gov/nist/javax/sip/parser/URLParser.java b/src/gov/nist/javax/sip/parser/URLParser.java index 402c00130..1d715e2f7 100755 --- a/src/gov/nist/javax/sip/parser/URLParser.java +++ b/src/gov/nist/javax/sip/parser/URLParser.java @@ -38,7 +38,7 @@ /** * Parser For SIP and Tel URLs. Other kinds of URL's are handled by the * J2SE 1.4 URL class. - * @version 1.2 $Revision: 1.28 $ $Date: 2010-05-06 14:07:44 $ + * @version 1.2 $Revision: 1.27 $ $Date: 2009-10-22 10:27:39 $ * * @author M. Ranganathan
    * @@ -195,7 +195,7 @@ protected String reserved() throws ParseException { char next = lexer.lookAhead(0); if (isReserved(next)) { lexer.consume(1); - return new StringBuilder().append(next).toString(); + return new StringBuffer().append(next).toString(); } else throw createParseException("reserved"); } @@ -214,7 +214,7 @@ protected String escaped() throws ParseException { if (debug) dbg_enter("escaped"); try { - StringBuilder retval = new StringBuilder(); + StringBuffer retval = new StringBuffer(); char next = lexer.lookAhead(0); char next1 = lexer.lookAhead(1); char next2 = lexer.lookAhead(2); @@ -306,7 +306,7 @@ protected String uricNoSlash() { } protected String uricString() throws ParseException { - StringBuilder retval = new StringBuilder(); + StringBuffer retval = new StringBuffer(); while (true) { String next = uric(); if (next == null) { @@ -371,7 +371,7 @@ public GenericURI uriReference( boolean inBrackets ) throws ParseException { * Parser for the base phone number. */ private String base_phone_number() throws ParseException { - StringBuilder s = new StringBuilder(); + StringBuffer s = new StringBuffer(); if (debug) dbg_enter("base_phone_number"); @@ -404,7 +404,7 @@ private String base_phone_number() throws ParseException { * Parser for the local phone #. */ private String local_number() throws ParseException { - StringBuilder s = new StringBuilder(); + StringBuffer s = new StringBuffer(); if (debug) dbg_enter("local_number"); try { @@ -673,7 +673,11 @@ public SipUri sipURL( boolean inBrackets ) throws ParseException { } public String peekScheme() throws ParseException { - return lexer.getString(':'); + Token[] tokens = lexer.peekNextToken(1); + if (tokens.length == 0) + return null; + String scheme = ((Token) tokens[0]).getTokenValue(); + return scheme; } /** @@ -689,7 +693,7 @@ protected NameValue qheader() throws ParseException { } protected String hvalue() throws ParseException { - StringBuilder retval = new StringBuilder(); + StringBuffer retval = new StringBuffer(); while (lexer.hasMoreChars()) { char la = lexer.lookAhead(0); // Look for a character that can terminate a URL. @@ -731,7 +735,7 @@ protected String hvalue() throws ParseException { * the next delimiter). */ protected String urlString() throws ParseException { - StringBuilder retval = new StringBuilder(); + StringBuffer retval = new StringBuffer(); lexer.selectLexer("charLexer"); while (lexer.hasMoreChars()) { diff --git a/src/gov/nist/javax/sip/parser/UserAgentParser.java b/src/gov/nist/javax/sip/parser/UserAgentParser.java index bd0b05394..cf080367c 100755 --- a/src/gov/nist/javax/sip/parser/UserAgentParser.java +++ b/src/gov/nist/javax/sip/parser/UserAgentParser.java @@ -32,7 +32,7 @@ /** * Parser for UserAgent header. * - * @version 1.2 $Revision: 1.16 $ $Date: 2010-05-06 14:07:44 $ + * @version 1.2 $Revision: 1.15 $ $Date: 2009-07-17 18:58:07 $ * * @author Olivier Deruelle
    * @author M. Ranganathan
    @@ -100,7 +100,7 @@ public SIPHeader parse() throws ParseException { String product = this.lexer.byteStringNoSlash(); if ( product == null ) throw createParseException("Expected product string"); - StringBuilder productSb = new StringBuilder(product); + StringBuffer productSb = new StringBuffer(product); // do we possibily have the optional product-version? if (this.lexer.peekNextToken().getTokenType() == TokenTypes.SLASH) { // yes diff --git a/src/gov/nist/javax/sip/parser/ViaParser.java b/src/gov/nist/javax/sip/parser/ViaParser.java index e580b112d..22df76c5e 100755 --- a/src/gov/nist/javax/sip/parser/ViaParser.java +++ b/src/gov/nist/javax/sip/parser/ViaParser.java @@ -32,7 +32,7 @@ /** * Parser for via headers. * - * @version 1.2 $Revision: 1.13 $ $Date: 2010-05-06 14:07:45 $ + * @version 1.2 $Revision: 1.12 $ $Date: 2009-07-17 18:58:07 $ * @since 1.1 * * @author Olivier Deruelle @@ -111,7 +111,7 @@ private void parseVia(Via v) throws ParseException { if (lexer.lookAhead(0) == '(') { this.lexer.selectLexer("charLexer"); lexer.consume(1); - StringBuilder comment = new StringBuilder(); + StringBuffer comment = new StringBuffer(); while (true) { char ch = lexer.lookAhead(0); if (ch == ')') { diff --git a/src/gov/nist/javax/sip/parser/ims/PUserDatabaseParser.java b/src/gov/nist/javax/sip/parser/ims/PUserDatabaseParser.java index 140ea885c..c89aec7ca 100644 --- a/src/gov/nist/javax/sip/parser/ims/PUserDatabaseParser.java +++ b/src/gov/nist/javax/sip/parser/ims/PUserDatabaseParser.java @@ -92,7 +92,7 @@ public SIPHeader parse() throws ParseException { private void parseheader(PUserDatabase userDatabase) throws ParseException { - StringBuilder dbname = new StringBuilder(); + StringBuffer dbname = new StringBuffer(); this.lexer.match(LESS_THAN); while(this.lexer.hasMoreChars()) diff --git a/src/gov/nist/javax/sip/parser/ims/PVisitedNetworkIDParser.java b/src/gov/nist/javax/sip/parser/ims/PVisitedNetworkIDParser.java index 9a77e712c..c2f910f70 100644 --- a/src/gov/nist/javax/sip/parser/ims/PVisitedNetworkIDParser.java +++ b/src/gov/nist/javax/sip/parser/ims/PVisitedNetworkIDParser.java @@ -125,7 +125,7 @@ protected void parseQuotedString(PVisitedNetworkID visitedNetworkID) throws Pars try { - StringBuilder retval = new StringBuilder(); + StringBuffer retval = new StringBuffer(); if (this.lexer.lookAhead(0) != '\"') throw createParseException("unexpected char"); diff --git a/src/gov/nist/javax/sip/stack/BlockingQueueDispatchAuditor.java b/src/gov/nist/javax/sip/stack/BlockingQueueDispatchAuditor.java index e5512ae79..4c867e96d 100644 --- a/src/gov/nist/javax/sip/stack/BlockingQueueDispatchAuditor.java +++ b/src/gov/nist/javax/sip/stack/BlockingQueueDispatchAuditor.java @@ -1,6 +1,5 @@ package gov.nist.javax.sip.stack; -import gov.nist.core.CommonLogger; import gov.nist.core.LogLevels; import gov.nist.core.StackLogger; @@ -10,20 +9,18 @@ public class BlockingQueueDispatchAuditor extends TimerTask { private Timer timer = new Timer(); - private static StackLogger logger = CommonLogger.getLogger(BlockingQueueDispatchAuditor.class); - private long totalReject = 0; - private boolean started = false; - private Queue queue; - private int timeout = 8000; - public BlockingQueueDispatchAuditor(Queue queue) { + private StackLogger logger; + private long totalReject = 0; + private boolean started = false; + private Queue queue; + private int timeout = 8000; + + public BlockingQueueDispatchAuditor(Queue queue) { this.queue = queue; } - public void start(int interval) { - if(started) stop(); - started = true; - timer = new Timer(); - timer.scheduleAtFixedRate(this, interval, interval); + public void setLogger(StackLogger logger) { + this.logger = logger; } public int getTimeout() { @@ -33,11 +30,23 @@ public int getTimeout() { public void setTimeout(int timeout) { this.timeout = timeout; } + + public void start(int interval) { + if(started) stop(); + started = true; + timer = new Timer(); + timer.scheduleAtFixedRate(this, interval, interval); + } public void stop() { try { - timer.cancel(); + try { + if(timer != null) timer.cancel(); + } catch (Exception e) { + + } timer = null; + queue = null; } catch (Exception e) { //not important } finally { @@ -45,31 +54,31 @@ public void stop() { } } - public void run() { - try { - int removed = 0; - synchronized(this.queue) { - QueuedMessageDispatchBase runnable =(QueuedMessageDispatchBase) this.queue.peek(); - while(runnable != null) { - QueuedMessageDispatchBase d = (QueuedMessageDispatchBase) runnable; - if(System.currentTimeMillis() - d.getReceptionTime() > timeout) { - queue.poll(); - runnable = (QueuedMessageDispatchBase) this.queue.peek(); - removed ++; - } else { - runnable = null; - } - } - } - if(removed>0) { - totalReject+=removed; - if(logger != null && logger.isLoggingEnabled(LogLevels.TRACE_WARN)) - logger.logWarning("Removed stuck messages=" + removed + - " total rejected=" + totalReject + " stil in queue=" + this.queue.size()); - } + public void run() { + try { + int removed = 0; + synchronized(this.queue) { // We can afford to lock here because it will either run very quickly or the server is congested anyway + QueuedMessageDispatchBase runnable =(QueuedMessageDispatchBase) this.queue.peek(); + while(runnable != null) { + QueuedMessageDispatchBase d = (QueuedMessageDispatchBase) runnable; + if(System.currentTimeMillis() - d.getReceptionTime() > timeout) { + queue.poll(); + runnable = (QueuedMessageDispatchBase) this.queue.peek(); + removed ++; + } else { + runnable = null; + } + } + } + if(removed>0) { + totalReject+=removed; + if(logger != null && logger.isLoggingEnabled(LogLevels.TRACE_WARN)) + logger.logWarning("Removed stuck messages=" + removed + + " total rejected=" + totalReject + " stil in queue=" + this.queue.size()); + } - } catch (Exception e) { - if(logger != null && logger.isLoggingEnabled(LogLevels.TRACE_WARN)) { + } catch (Exception e) { + if(logger != null && logger.isLoggingEnabled(LogLevels.TRACE_WARN)) { logger.logWarning("Problem reaping old requests. This is not a fatal error." + e); } } diff --git a/src/gov/nist/javax/sip/stack/CallAnalyzer.java b/src/gov/nist/javax/sip/stack/CallAnalyzer.java index c70f80754..287e9f454 100644 --- a/src/gov/nist/javax/sip/stack/CallAnalyzer.java +++ b/src/gov/nist/javax/sip/stack/CallAnalyzer.java @@ -1,5 +1,4 @@ package gov.nist.javax.sip.stack; -import gov.nist.core.CommonLogger; import gov.nist.core.StackLogger; import gov.nist.javax.sip.SipStackImpl; @@ -28,7 +27,7 @@ * */ public class CallAnalyzer { - private static StackLogger logger = CommonLogger.getLogger(CallAnalyzer.class); + private static StackLogger logger; /* * This is a Thread -> Hashmap association, each hashmap can contain multiple metricts for the thread @@ -46,6 +45,7 @@ public class CallAnalyzer { public CallAnalyzer(SipStackImpl stack) { this.stack = stack; + logger = stack.getStackLogger(); } public static class TImeMetricInfo { diff --git a/src/gov/nist/javax/sip/stack/ClientAuthType.java b/src/gov/nist/javax/sip/stack/ClientAuthType.java deleted file mode 100644 index b99dc6bc1..000000000 --- a/src/gov/nist/javax/sip/stack/ClientAuthType.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Conditions Of Use - * - * This software was developed by employees of the National Institute of - * Standards and Technology (NIST), an agency of the Federal Government. - * Pursuant to title 15 Untied States Code Section 105, works of NIST - * employees are not subject to copyright protection in the United States - * and are considered to be in the public domain. As a result, a formal - * license is not needed to use the software. - * - * This software is provided by NIST as a service and is expressly - * provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED - * OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT - * AND DATA ACCURACY. NIST does not warrant or make any representations - * regarding the use of the software or the results thereof, including but - * not limited to the correctness, accuracy, reliability or usefulness of - * the software. - * - * Permission to use this software is contingent upon your acceptance - * of the terms of this agreement - * - * . - * - */ -package gov.nist.javax.sip.stack; - -/** - * @author jean.deruelle@gmail.com - * - */ -public enum ClientAuthType { - Enabled, Disabled, Want, Default; -} diff --git a/src/gov/nist/javax/sip/stack/CongestionControlMessageValve.java b/src/gov/nist/javax/sip/stack/CongestionControlMessageValve.java deleted file mode 100644 index 343563de9..000000000 --- a/src/gov/nist/javax/sip/stack/CongestionControlMessageValve.java +++ /dev/null @@ -1,85 +0,0 @@ -package gov.nist.javax.sip.stack; - -import java.io.IOException; - -import gov.nist.core.CommonLogger; -import gov.nist.core.StackLogger; -import gov.nist.javax.sip.SipStackImpl; -import gov.nist.javax.sip.message.SIPRequest; -import gov.nist.javax.sip.message.SIPResponse; - -import javax.sip.SipStack; -import javax.sip.message.Request; -import javax.sip.message.Response; - -/** - * This is just a simple reusable congestion control valve JSIP apps can use to stop traffic when the number of - * server transactions reaches the limit specified in gov.nist.javax.sip.MAX_SERVER_TRANSACTIONS without breaking - * existing dialogs. - * - * The drop policy is specified in DROP_RESPONSE_STATUS where "0" means silent drop and any positive number will be - * interpreted as the status code of the error response that will be generated. - * - * To enable this in your application you must specify this property: - * gov.nist.javax.sip.SIP_MESSAGE_VALVE=gov.nist.javax.sip.stack.CongestionControlMessageValve - * - * It is advised to extend this class to add your application-specific control conditions - * - * @author vladimirralev - * - */ -public class CongestionControlMessageValve implements SIPMessageValve{ - private static StackLogger logger = CommonLogger.getLogger(CongestionControlMessageValve.class); - protected SipStackImpl sipStack; - // High water mark for ServerTransaction Table - // after which requests are dropped. - protected int serverTransactionTableHighwaterMark; - protected int dropResponseStatus; - - public boolean processRequest(SIPRequest request, - MessageChannel messageChannel) { - String requestMethod = request.getMethod(); - - // We should not attempt to drop these requests because they actually free resources - // which is our goal in congested mode - boolean undropableMethod = requestMethod.equals(Request.BYE) - || requestMethod.equals(Request.ACK) - || requestMethod.equals(Request.PRACK) - || requestMethod.equals(Request.CANCEL); - - if(!undropableMethod) { - if(serverTransactionTableHighwaterMark <= sipStack.getServerTransactionTableSize()) { - if(dropResponseStatus>0) { - SIPResponse response = request.createResponse(dropResponseStatus); - try { - messageChannel.sendMessage(response); - } catch (IOException e) { - logger.logError("Failed to send congestion control error response" + response, e); - } - } - return false; // Do not pass this request to the pipeline - } - } - return true; // OK, the processing of the request can continue - } - - public boolean processResponse(Response response, - MessageChannel messageChannel) { - return true; - } - - public void destroy() { - logger.logInfo("Destorying the congestion control valve " + this); - - } - - public void init(SipStack stack) { - sipStack = (SipStackImpl) stack; - logger.logInfo("Initializing congestion control valve"); - String serverTransactionsString = sipStack.getConfigurationProperties().getProperty("gov.nist.javax.sip.MAX_SERVER_TRANSACTIONS", "10000"); - serverTransactionTableHighwaterMark = new Integer(serverTransactionsString); - String dropResponseStatusString = sipStack.getConfigurationProperties().getProperty("DROP_RESPONSE_STATUS", "503"); - dropResponseStatus = new Integer(dropResponseStatusString); - } - -} diff --git a/src/gov/nist/javax/sip/stack/DefaultRouter.java b/src/gov/nist/javax/sip/stack/DefaultRouter.java index 11f79d84e..3bc590fa4 100755 --- a/src/gov/nist/javax/sip/stack/DefaultRouter.java +++ b/src/gov/nist/javax/sip/stack/DefaultRouter.java @@ -91,14 +91,12 @@ * Subsequently, the request URI will be used as next hop target * * - * @version 1.2 $Revision: 1.20 $ $Date: 2010-12-02 22:04:12 $ + * @version 1.2 $Revision: 1.18.2.1 $ $Date: 2010-11-23 19:23:11 $ * * @author M. Ranganathan
    * */ public class DefaultRouter implements Router { - - private static StackLogger logger = CommonLogger.getLogger(DefaultRouter.class); private SIPTransactionStack sipStack; @@ -119,7 +117,8 @@ public DefaultRouter(SipStack sipStack, String defaultRoute) { .resolveAddress((Hop) (new HopImpl(defaultRoute))); } catch (IllegalArgumentException ex) { // The outbound proxy is optional. If specified it should be host:port/transport. - logger + ((SIPTransactionStack) sipStack) + .getStackLogger() .logError( "Invalid default route specification - need host:port/transport"); throw ex; @@ -201,14 +200,14 @@ public Hop getNextHop(Request request) throws SipException { if (!sipUri.hasLrParam()) { fixStrictRouting(sipRequest); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger() .logDebug("Route post processing fixed strict routing"); } Hop hop = createHop(sipUri,request); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger() .logDebug("NextHop based on Route:" + hop); return hop; } else { @@ -218,8 +217,8 @@ public Hop getNextHop(Request request) throws SipException { } else if (requestURI.isSipURI() && ((SipURI) requestURI).getMAddrParam() != null) { Hop hop = createHop((SipURI) requestURI,request); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger() .logDebug("Using request URI maddr to route the request = " + hop.toString()); @@ -229,18 +228,18 @@ public Hop getNextHop(Request request) throws SipException { return hop; } else if (defaultRoute != null) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger() .logDebug("Using outbound proxy to route the request = " + defaultRoute.toString()); return defaultRoute; } else if (requestURI.isSipURI()) { Hop hop = createHop((SipURI) requestURI,request); - if (hop != null && logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("Used request-URI for nextHop = " + if (hop != null && sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Used request-URI for nextHop = " + hop.toString()); - else if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger + else if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger() .logDebug("returning null hop -- loop detected"); } return hop; @@ -248,7 +247,7 @@ else if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { } else { // The internal router should never be consulted for non-sip URIs. InternalErrorHandler.handleException("Unexpected non-sip URI", - this.logger); + this.sipStack.getStackLogger()); return null; } @@ -274,8 +273,8 @@ public void fixStrictRouting(SIPRequest req) { routes.add(route); // as last one req.setRequestURI(firstUri); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("post: fixStrictRouting" + req); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("post: fixStrictRouting" + req); } } @@ -287,7 +286,7 @@ public void fixStrictRouting(SIPRequest req) { */ - protected final Hop createHop(SipURI sipUri, Request request) { + private final Hop createHop(SipURI sipUri, Request request) { // always use TLS when secure String transport = sipUri.isSecure() ? SIPConstants.TLS : sipUri .getTransportParam(); diff --git a/src/gov/nist/javax/sip/stack/HandshakeCompletedListenerImpl.java b/src/gov/nist/javax/sip/stack/HandshakeCompletedListenerImpl.java index 8c4b3768c..bd7524632 100644 --- a/src/gov/nist/javax/sip/stack/HandshakeCompletedListenerImpl.java +++ b/src/gov/nist/javax/sip/stack/HandshakeCompletedListenerImpl.java @@ -24,36 +24,25 @@ public class HandshakeCompletedListenerImpl implements HandshakeCompletedListener { private HandshakeCompletedEvent handshakeCompletedEvent; - private Object eventWaitObject = new Object(); - + private TLSMessageChannel tlsMessageChannel; + + public HandshakeCompletedListenerImpl(TLSMessageChannel tlsMessageChannel) { + this.tlsMessageChannel = tlsMessageChannel; tlsMessageChannel.setHandshakeCompletedListener(this); } + public void handshakeCompleted(HandshakeCompletedEvent handshakeCompletedEvent) { - this.handshakeCompletedEvent = handshakeCompletedEvent; - synchronized (eventWaitObject) { - eventWaitObject.notify(); - } + this.handshakeCompletedEvent = handshakeCompletedEvent; } /** - * Gets the event indicating that the SSL handshake has completed. The - * method waits until the event has been obtained by the listener or a - * timeout of 5 seconds has elapsed. - * - * @return the handshakeCompletedEvent or null when the timeout elapsed + * @return the handshakeCompletedEvent */ public HandshakeCompletedEvent getHandshakeCompletedEvent() { - try { - synchronized (eventWaitObject) { - if (handshakeCompletedEvent == null) - eventWaitObject.wait(5000); - } - } - catch (InterruptedException e) { - // we don't care - } return handshakeCompletedEvent; } + + } diff --git a/src/gov/nist/javax/sip/stack/IOHandler.java b/src/gov/nist/javax/sip/stack/IOHandler.java index 53c6708cb..45ed62272 100755 --- a/src/gov/nist/javax/sip/stack/IOHandler.java +++ b/src/gov/nist/javax/sip/stack/IOHandler.java @@ -28,20 +28,21 @@ *******************************************************************************/ package gov.nist.javax.sip.stack; -import gov.nist.core.CommonLogger; -import gov.nist.core.LogLevels; import gov.nist.core.LogWriter; import gov.nist.core.StackLogger; import gov.nist.javax.sip.SipStackImpl; import java.io.IOException; import java.io.OutputStream; +import java.net.ConnectException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.Socket; import java.net.SocketAddress; +import java.net.SocketException; import java.util.Enumeration; +import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; @@ -52,291 +53,217 @@ /* * TLS support Added by Daniel J.Martinez Manzano - * + * */ /** * Low level Input output to a socket. Caches TCP connections and takes care of * re-connecting to the remote party if the other end drops the connection - * + * * @version 1.2 - * + * * @author M. Ranganathan
    - * - * + * + * */ public class IOHandler { - - private static StackLogger logger = CommonLogger.getLogger(IOHandler.class); - - private SipStackImpl sipStack; - - private static final String TCP = "tcp"; - - // Added by Daniel J. Martinez Manzano - private static final String TLS = "tls"; - - // A cache of client sockets that can be re-used for - // sending tcp messages. - private final ConcurrentHashMap socketTable = new ConcurrentHashMap(); - - private final ConcurrentHashMap socketCreationMap = new ConcurrentHashMap(); - - // private Semaphore ioSemaphore = new Semaphore(1); - - protected static String makeKey(InetAddress addr, int port) { - return addr.getHostAddress() + ":" + port; - - } - - protected static String makeKey(String addr, int port) { - return addr + ":" + port; - } - - protected IOHandler(SIPTransactionStack sipStack) { - this.sipStack = (SipStackImpl) sipStack; - } - - protected void putSocket(String key, Socket sock) { - if (logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) { - logger.logDebug("adding socket for key " + key); - } - socketTable.put(key, sock); - } - - protected Socket getSocket(String key) { - return (Socket) socketTable.get(key); - - } - - protected void removeSocket(String key) { - socketTable.remove(key); - socketCreationMap.remove(key); - if (logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) { - logger.logDebug("removed Socket and Semaphore for key " + key); - } - } - - /** - * A private function to write things out. This needs to be synchronized as - * writes can occur from multiple threads. We write in chunks to allow the - * other side to synchronize for large sized writes. - */ - private void writeChunks(OutputStream outputStream, byte[] bytes, int length) - throws IOException { - // Chunk size is 16K - this hack is for large - // writes over slow connections. - synchronized (outputStream) { - // outputStream.write(bytes,0,length); - int chunksize = 8 * 1024; - for (int p = 0; p < length; p += chunksize) { - int chunk = p + chunksize < length ? chunksize : length - p; - outputStream.write(bytes, p, chunk); - } - } - outputStream.flush(); - } - - /** - * Creates and binds, if necessary, a socket connected to the specified - * destination address and port and then returns its local address. - * - * @param dst - * the destination address that the socket would need to connect - * to. - * @param dstPort - * the port number that the connection would be established with. - * @param localAddress - * the address that we would like to bind on (null for the "any" - * address). - * @param localPort - * the port that we'd like our socket to bind to (0 for a random - * port). - * - * @return the SocketAddress that this handler would use when connecting to - * the specified destination address and port. - * - * @throws IOException if we fail binding the socket - */ - public SocketAddress getLocalAddressForTcpDst(InetAddress dst, int dstPort, - InetAddress localAddress, int localPort) throws IOException { - String key = makeKey(dst, dstPort); - - Socket clientSock = getSocket(key); - - if (clientSock == null) { - clientSock = sipStack.getNetworkLayer().createSocket(dst, dstPort, - localAddress, localPort); - putSocket(key, clientSock); - } - - return clientSock.getLocalSocketAddress(); - - } - /** - * Creates and binds, if necessary, a socket connected to the specified - * destination address and port and then returns its local address. - * - * @param dst the destination address that the socket would need to connect - * to. - * @param dstPort the port number that the connection would be established - * with. - * @param localAddress the address that we would like to bind on (null for - * the "any" address). - * - * @param channel the message channel that will be servicing the socket - * - * @return the SocketAddress that this handler would use when connecting to - * the specified destination address and port. - * - * @throws IOException if we fail binding the socket - */ - public SocketAddress getLocalAddressForTlsDst(InetAddress dst, int dstPort, - InetAddress localAddress, TLSMessageChannel channel) - throws IOException { - String key = makeKey(dst, dstPort); - - Socket clientSock = getSocket(key); - - if (clientSock == null) { - - clientSock = sipStack.getNetworkLayer() - .createSSLSocket(dst, dstPort, localAddress); - - SSLSocket sslsock = (SSLSocket) clientSock; - - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( - "inaddr = " + dst); - logger.logDebug( - "port = " + dstPort); - } + + private SipStackImpl sipStack; - HandshakeCompletedListener listner - = new HandshakeCompletedListenerImpl(channel); + private static final String TCP = "tcp"; - channel.setHandshakeCompletedListener(listner); - sslsock.addHandshakeCompletedListener(listner); - sslsock.setEnabledProtocols(sipStack.getEnabledProtocols()); - sslsock.startHandshake(); + // Added by Daniel J. Martinez Manzano + private static final String TLS = "tls"; - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - this.logger.logDebug( - "Handshake passed"); - } - - // allow application to enforce policy by validating the - // certificate - try { - sipStack.getTlsSecurityPolicy().enforceTlsPolicy( - channel.getEncapsulatedClientTransaction()); - } - catch (SecurityException ex) { - throw new IOException(ex.getMessage()); - } + // A cache of client sockets that can be re-used for + // sending tcp messages. + private final ConcurrentHashMap socketTable = new ConcurrentHashMap(); + + private final ConcurrentHashMap socketCreationMap = new ConcurrentHashMap(); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - this.logger.logDebug( - "TLS Security policy passed"); - } + + //private Semaphore ioSemaphore = new Semaphore(1); - putSocket(key, clientSock); - } + protected static String makeKey(InetAddress addr, int port) { + return addr.getHostAddress() + ":" + port; - return clientSock.getLocalSocketAddress(); - } + } - /** - * Send an array of bytes. - * - * @param receiverAddress - * -- inet address - * @param contactPort - * -- port to connect to. - * @param transport - * -- tcp or udp. - * @param isClient - * -- retry to connect if the other end closed connection - * @throws IOException - * -- if there is an IO exception sending message. - */ - - public Socket sendBytes(InetAddress senderAddress, - InetAddress receiverAddress, int contactPort, String transport, - byte[] bytes, boolean isClient, MessageChannel messageChannel) - throws IOException { - int retry_count = 0; - int max_retry = isClient ? 2 : 1; - // Server uses TCP transport. TCP client sockets are cached - int length = bytes.length; - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( - "sendBytes " + transport + " inAddr " - + receiverAddress.getHostAddress() + " port = " - + contactPort + " length = " + length + " isClient " + isClient ); + protected IOHandler(SIPTransactionStack sipStack) { + this.sipStack = (SipStackImpl) sipStack; + } + protected void putSocket(String key, Socket sock) { + if (sipStack.getStackLogger().isLoggingEnabled(StackLogger.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("adding socket for key " + key); } - if (logger.isLoggingEnabled(LogLevels.TRACE_INFO) - && sipStack.isLogStackTraceOnMessageSend()) { - logger.logStackTrace(StackLogger.TRACE_INFO); + socketTable.put(key, sock); + } + + protected Socket getSocket(String key) { + return (Socket) socketTable.get(key); + + } + + protected void removeSocket(String key) { + socketTable.remove(key); + socketCreationMap.remove(key); + if (sipStack.getStackLogger().isLoggingEnabled(StackLogger.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("removed Socket and Semaphore for key " + key); } - if (transport.compareToIgnoreCase(TCP) == 0) { - String key = makeKey(receiverAddress, contactPort); - // This should be in a synchronized block ( reported by - // Jayashenkhar ( lucent ). - - Socket clientSock = null; - enterIOCriticalSection(key); - - try { - clientSock = getSocket(key); - while (retry_count < max_retry) { - if (clientSock == null) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( - "inaddr = " + receiverAddress); - logger.logDebug( - "port = " + contactPort); - } - // note that the IP Address for stack may not be - // assigned. - // sender address is the address of the listening point. - // in version 1.1 all listening points have the same IP - // address (i.e. that of the stack). In version 1.2 - // the IP address is on a per listening point basis. - clientSock = sipStack.getNetworkLayer().createSocket( - receiverAddress, contactPort, senderAddress); - OutputStream outputStream = clientSock - .getOutputStream(); - writeChunks(outputStream, bytes, length); - putSocket(key, clientSock); - break; - } else { - try { - OutputStream outputStream = clientSock - .getOutputStream(); - writeChunks(outputStream, bytes, length); - break; - } catch (IOException ex) { - if (logger - .isLoggingEnabled(LogWriter.TRACE_ERROR)) - logger.logInfo( - "IOException occured retryCount " - + retry_count); - try { - clientSock.close(); - } catch (Exception e) { - } - clientSock = null; - retry_count++; - // This is a server tx trying to send a response. - if ( !isClient ) { - removeSocket(key); - throw ex; - } - if(retry_count >= max_retry) { + } + + /** + * A private function to write things out. This needs to be synchronized as + * writes can occur from multiple threads. We write in chunks to allow the + * other side to synchronize for large sized writes. + */ + private void writeChunks(OutputStream outputStream, byte[] bytes, int length) + throws IOException { + // Chunk size is 16K - this hack is for large + // writes over slow connections. + synchronized (outputStream) { + // outputStream.write(bytes,0,length); + int chunksize = 8 * 1024; + for (int p = 0; p < length; p += chunksize) { + int chunk = p + chunksize < length ? chunksize : length - p; + outputStream.write(bytes, p, chunk); + } + } + outputStream.flush(); + } + + /** + * Creates and binds, if necessary, a socket connected to the specified + * destination address and port and then returns its local address. + * + * @param dst + * the destination address that the socket would need to connect + * to. + * @param dstPort + * the port number that the connection would be established with. + * @param localAddress + * the address that we would like to bind on (null for the "any" + * address). + * @param localPort + * the port that we'd like our socket to bind to (0 for a random + * port). + * + * @return the SocketAddress that this handler would use when connecting to + * the specified destination address and port. + * + * @throws IOException + */ + public SocketAddress obtainLocalAddress(InetAddress dst, int dstPort, + InetAddress localAddress, int localPort) throws IOException { + String key = makeKey(dst, dstPort); + + Socket clientSock = getSocket(key); + + if (clientSock == null) { + clientSock = sipStack.getNetworkLayer().createSocket(dst, dstPort, + localAddress, localPort); + putSocket(key, clientSock); + } + + return clientSock.getLocalSocketAddress(); + + } + + /** + * Send an array of bytes. + * + * @param receiverAddress + * -- inet address + * @param contactPort + * -- port to connect to. + * @param transport + * -- tcp or udp. + * @param retry + * -- retry to connect if the other end closed connection + * @throws IOException + * -- if there is an IO exception sending message. + */ + + public Socket sendBytes(InetAddress senderAddress, + InetAddress receiverAddress, int contactPort, String transport, + byte[] bytes, boolean retry, MessageChannel messageChannel) + throws IOException { + int retry_count = 0; + int max_retry = retry ? 2 : 1; + // Server uses TCP transport. TCP client sockets are cached + int length = bytes.length; + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( + "sendBytes " + transport + " inAddr " + + receiverAddress.getHostAddress() + " port = " + + contactPort + " length = " + length); + + } + if (sipStack.isLoggingEnabled(LogWriter.TRACE_INFO) + && sipStack.isLogStackTraceOnMessageSend()) { + sipStack.getStackLogger().logStackTrace(StackLogger.TRACE_INFO); + } + if (transport.compareToIgnoreCase(TCP) == 0) { + String key = makeKey(receiverAddress, contactPort); + // This should be in a synchronized block ( reported by + // Jayashenkhar ( lucent ). + + Socket clientSock = null; + enterIOCriticalSection(key); + + try { + clientSock = getSocket(key); + while (retry_count < max_retry) { + if (clientSock == null) { + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( + "inaddr = " + receiverAddress); + sipStack.getStackLogger().logDebug( + "port = " + contactPort); + } + // note that the IP Address for stack may not be + // assigned. + // sender address is the address of the listening point. + // in version 1.1 all listening points have the same IP + // address (i.e. that of the stack). In version 1.2 + // the IP address is on a per listening point basis. + try{ + clientSock = sipStack.getNetworkLayer().createSocket( + receiverAddress, contactPort, senderAddress); + } catch (SocketException e) { // We must catch the timeout exceptions here, any SocketException not just ConnectException + sipStack.getStackLogger().logError("Problem connecting " + + receiverAddress + " " + contactPort + " " + senderAddress + " for message " + new String(bytes, "UTF-8")); + // new connection is bad. + // remove from our table the socket and its semaphore + removeSocket(key); + throw new SocketException(e.getClass() + " " + e.getMessage() + " " + e.getCause()); + } + OutputStream outputStream = clientSock + .getOutputStream(); + writeChunks(outputStream, bytes, length); + putSocket(key, clientSock); + break; + } else { + try { + OutputStream outputStream = clientSock + .getOutputStream(); + writeChunks(outputStream, bytes, length); + break; + } catch (IOException ex) { + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug( + "IOException occured retryCount " + + retry_count); + try { + clientSock.close(); + } catch (Exception e) { + } + clientSock = null; + retry_count++; + if(retry_count >= max_retry) { // old connection is bad. // remove from our table the socket and its semaphore removeSocket(key); @@ -344,312 +271,157 @@ public Socket sendBytes(InetAddress senderAddress, // don't remove the semaphore on retry socketTable.remove(key); } - } - } - } - } catch (IOException ex) { - if (logger.isLoggingEnabled(LogWriter.TRACE_ERROR)) { - logger.logError( - "Problem sending: sendBytes " + transport - + " inAddr " - + receiverAddress.getHostAddress() - + " port = " + contactPort + - " remoteHost " + messageChannel.getPeerAddress() + - " remotePort " + messageChannel.getPeerPort() + - " peerPacketPort " - + messageChannel.getPeerPacketSourcePort() + " isClient " + isClient); - } - - removeSocket(key); - - /* - * For TCP responses, the transmission of responses is - * controlled by RFC 3261, section 18.2.2 : - * - * o If the "sent-protocol" is a reliable transport protocol - * such as TCP or SCTP, or TLS over those, the response MUST be - * sent using the existing connection to the source of the - * original request that created the transaction, if that - * connection is still open. This requires the server transport - * to maintain an association between server transactions and - * transport connections. If that connection is no longer open, - * the server SHOULD open a connection to the IP address in the - * "received" parameter, if present, using the port in the - * "sent-by" value, or the default port for that transport, if - * no port is specified. If that connection attempt fails, the - * server SHOULD use the procedures in [4] for servers in order - * to determine the IP address and port to open the connection - * and send the response to. - */ - if (!isClient) { - receiverAddress = InetAddress.getByName(messageChannel - .getViaHost()); - contactPort = messageChannel.getViaPort(); - if (contactPort == -1) - contactPort = 5060; - - key = makeKey(receiverAddress, messageChannel - .getViaPort()); - clientSock = this.getSocket(key); - if (clientSock == null) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( - "inaddr = " + receiverAddress + - " port = " + contactPort); - } - clientSock = sipStack.getNetworkLayer().createSocket( - receiverAddress, contactPort, senderAddress); - OutputStream outputStream = clientSock - .getOutputStream(); - writeChunks(outputStream, bytes, length); - putSocket(key, clientSock); - return clientSock; - } else { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( - "sending to " + key ); - } - try { - OutputStream outputStream = clientSock - .getOutputStream(); - writeChunks(outputStream, bytes, length); - return clientSock; - } catch (IOException ioe) { - if (logger - .isLoggingEnabled(LogWriter.TRACE_ERROR)) - logger.logError( - "IOException occured ", ioe); - if (logger - .isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug( - "Removing and Closing socket"); - // old connection is bad. - // remove from our table. - removeSocket(key); - try { - clientSock.close(); - } catch (Exception e) { - } - clientSock = null; - throw ioe; - } - } - } else { - logger.logError("IOException occured at " , ex); - throw ex; - } - } finally { - leaveIOCriticalSection(key); - } - - if (clientSock == null) { - - if (logger.isLoggingEnabled(LogWriter.TRACE_ERROR)) { - logger.logError( - this.socketTable.toString()); - logger.logError( - "Could not connect to " + receiverAddress + ":" - + contactPort); - } - - throw new IOException("Could not connect to " + receiverAddress - + ":" + contactPort); - } else { - return clientSock; - } - - // Added by Daniel J. Martinez Manzano - // Copied and modified from the former section for TCP - } else if (transport.compareToIgnoreCase(TLS) == 0) { - String key = makeKey(receiverAddress, contactPort); - Socket clientSock = null; - enterIOCriticalSection(key); - - try { - clientSock = getSocket(key); - - while (retry_count < max_retry) { - if (clientSock == null) { - - clientSock = sipStack.getNetworkLayer() - .createSSLSocket(receiverAddress, contactPort, - senderAddress); - SSLSocket sslsock = (SSLSocket) clientSock; - - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( - "inaddr = " + receiverAddress); - logger.logDebug( - "port = " + contactPort); - } - HandshakeCompletedListener listner = new HandshakeCompletedListenerImpl( - (TLSMessageChannel) messageChannel); - ((TLSMessageChannel) messageChannel) - .setHandshakeCompletedListener(listner); - sslsock.addHandshakeCompletedListener(listner); - sslsock.setEnabledProtocols(sipStack - .getEnabledProtocols()); - sslsock.startHandshake(); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - this.logger.logDebug( - "Handshake passed"); - } - // allow application to enforce policy by validating the - // certificate - - try { - sipStack - .getTlsSecurityPolicy() - .enforceTlsPolicy( - messageChannel - .getEncapsulatedClientTransaction()); - } catch (SecurityException ex) { - throw new IOException(ex.getMessage()); - } - - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - this.logger.logDebug( - "TLS Security policy passed"); - } - OutputStream outputStream = clientSock - .getOutputStream(); - writeChunks(outputStream, bytes, length); - putSocket(key, clientSock); - break; - } else { - try { - OutputStream outputStream = clientSock - .getOutputStream(); - writeChunks(outputStream, bytes, length); - break; - } catch (IOException ex) { - if (logger.isLoggingEnabled()) - logger.logException(ex); - // old connection is bad. - // remove from our table. - removeSocket(key); - - try { - logger.logDebug( - "Closing socket"); - clientSock.close(); - } catch (Exception e) { - } - clientSock = null; - retry_count++; - } - } - } - } catch (SSLHandshakeException ex) { - removeSocket(key); - throw ex; - } catch (IOException ex) { - removeSocket(key); - - if (!isClient) { - receiverAddress = InetAddress.getByName(messageChannel - .getViaHost()); - contactPort = messageChannel.getViaPort(); - if (contactPort == -1) - contactPort = 5060; - - key = makeKey(receiverAddress, messageChannel - .getViaPort()); - clientSock = this.getSocket(key); - if (clientSock == null) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( - "inaddr = " + receiverAddress + - " port = " + contactPort); - } - SSLSocket sslsock = sipStack.getNetworkLayer().createSSLSocket( - receiverAddress, contactPort, senderAddress); - OutputStream outputStream = sslsock - .getOutputStream(); - HandshakeCompletedListener listner = new HandshakeCompletedListenerImpl( - (TLSMessageChannel) messageChannel); - ((TLSMessageChannel) messageChannel) - .setHandshakeCompletedListener(listner); - sslsock.addHandshakeCompletedListener(listner); - sslsock.setEnabledProtocols(sipStack - .getEnabledProtocols()); - sslsock.startHandshake(); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - this.logger.logDebug( - "Handshake passed"); - } - writeChunks(outputStream, bytes, length); - putSocket(key, clientSock); - return sslsock; - } else { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( - "sending to " + key ); - } - try { - OutputStream outputStream = clientSock - .getOutputStream(); - writeChunks(outputStream, bytes, length); - return clientSock; - } catch (IOException ioe) { - if (logger - .isLoggingEnabled(LogWriter.TRACE_ERROR)) - logger.logError( - "IOException occured ", ioe); - if (logger - .isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug( - "Removing and Closing socket"); - // old connection is bad. - // remove from our table. - removeSocket(key); - try { - clientSock.close(); - } catch (Exception e) { - } - clientSock = null; - throw ioe; - } - } - } else { - throw ex; - } - } finally { - leaveIOCriticalSection(key); - } - if (clientSock == null) { - throw new IOException("Could not connect to " + receiverAddress - + ":" + contactPort); - } else - return clientSock; - - } else { - // This is a UDP transport... - DatagramSocket datagramSock = sipStack.getNetworkLayer() - .createDatagramSocket(); - datagramSock.connect(receiverAddress, contactPort); - DatagramPacket dgPacket = new DatagramPacket(bytes, 0, length, - receiverAddress, contactPort); - datagramSock.send(dgPacket); - datagramSock.close(); - return null; - } - - } + } + } + } + } catch (IOException ex) { + removeSocket(key); + throw ex; + } finally { + leaveIOCriticalSection(key); + } + + if (clientSock == null) { + + if (sipStack.isLoggingEnabled()) { + sipStack.getStackLogger().logDebug( + this.socketTable.toString()); + sipStack.getStackLogger().logError( + "Could not connect to " + receiverAddress + ":" + + contactPort); + } + + throw new IOException("Could not connect to " + receiverAddress + + ":" + contactPort); + } else + return clientSock; + + // Added by Daniel J. Martinez Manzano + // Copied and modified from the former section for TCP + } else if (transport.compareToIgnoreCase(TLS) == 0) { + String key = makeKey(receiverAddress, contactPort); + Socket clientSock = null; + enterIOCriticalSection(key); + + try { + clientSock = getSocket(key); + + while (retry_count < max_retry) { + if (clientSock == null) { + + clientSock = sipStack.getNetworkLayer() + .createSSLSocket(receiverAddress, contactPort, + senderAddress); + SSLSocket sslsock = (SSLSocket) clientSock; + + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( + "inaddr = " + receiverAddress); + sipStack.getStackLogger().logDebug( + "port = " + contactPort); + } + HandshakeCompletedListener listner = new HandshakeCompletedListenerImpl( + (TLSMessageChannel) messageChannel); + ((TLSMessageChannel) messageChannel) + .setHandshakeCompletedListener(listner); + sslsock.addHandshakeCompletedListener(listner); + sslsock.setEnabledProtocols(sipStack + .getEnabledProtocols()); + sslsock.startHandshake(); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + this.sipStack.getStackLogger().logDebug( + "Handshake passed"); + } + // allow application to enforce policy by validating the + // certificate + + try { + sipStack + .getTlsSecurityPolicy() + .enforceTlsPolicy( + messageChannel + .getEncapsulatedClientTransaction()); + } catch (SecurityException ex) { + throw new IOException(ex.getMessage()); + } + + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + this.sipStack.getStackLogger().logDebug( + "TLS Security policy passed"); + } + OutputStream outputStream = clientSock + .getOutputStream(); + writeChunks(outputStream, bytes, length); + putSocket(key, clientSock); + break; + } else { + try { + OutputStream outputStream = clientSock + .getOutputStream(); + writeChunks(outputStream, bytes, length); + break; + } catch (IOException ex) { + if (sipStack.isLoggingEnabled()) + sipStack.getStackLogger().logException(ex); + // old connection is bad. + // remove from our table. + removeSocket(key); + try { + clientSock.close(); + } catch (Exception e) { + } + clientSock = null; + retry_count++; + } + } + } + } catch (SSLHandshakeException ex) { + removeSocket(key); + throw ex; + } catch (IOException ex) { + removeSocket(key); + throw ex; + } finally { + leaveIOCriticalSection(key); + } + if (clientSock == null) { + throw new IOException("Could not connect to " + receiverAddress + + ":" + contactPort); + } else + return clientSock; + + } else { + // This is a UDP transport... + DatagramSocket datagramSock = sipStack.getNetworkLayer() + .createDatagramSocket(); + datagramSock.connect(receiverAddress, contactPort); + DatagramPacket dgPacket = new DatagramPacket(bytes, 0, length, + receiverAddress, contactPort); + datagramSock.send(dgPacket); + datagramSock.close(); + return null; + } + + } + + /* + private void enterIOCriticalSection(String key) throws IOException { + try { + if ( ! this.ioSemaphore.tryAcquire(10,TimeUnit.SECONDS) ) { + throw new IOException("Could not acquire semaphore"); + } + } catch (InterruptedException e) { + throw new IOException("exception in acquiring sem"); + } + } + + + private void leaveIOCriticalSection(String key) { + this.ioSemaphore.release(); + } + */ - /* - * private void enterIOCriticalSection(String key) throws IOException { try - * { if ( ! this.ioSemaphore.tryAcquire(10,TimeUnit.SECONDS) ) { throw new - * IOException("Could not acquire semaphore"); } } catch - * (InterruptedException e) { throw new - * IOException("exception in acquiring sem"); } } - * - * - * private void leaveIOCriticalSection(String key) { - * this.ioSemaphore.release(); } - */ - - private void leaveIOCriticalSection(String key) { + private void leaveIOCriticalSection(String key) { Semaphore creationSemaphore = socketCreationMap.get(key); if (creationSemaphore != null) { creationSemaphore.release(); @@ -664,8 +436,8 @@ private void enterIOCriticalSection(String key) throws IOException { creationSemaphore = socketCreationMap.putIfAbsent(key, newCreationSemaphore); if(creationSemaphore == null) { creationSemaphore = newCreationSemaphore; - if (logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) { - logger.logDebug("new Semaphore added for key " + key); + if (sipStack.getStackLogger().isLoggingEnabled(StackLogger.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("new Semaphore added for key " + key); } } } @@ -673,7 +445,7 @@ private void enterIOCriticalSection(String key) throws IOException { try { boolean retval = creationSemaphore.tryAcquire(10, TimeUnit.SECONDS); if (!retval) { - throw new IOException("Could not acquire IO Semaphore'" + key + throw new IOException("Could not acquire IO Semaphore'" + key + "' after 10 seconds -- giving up "); } } catch (InterruptedException e) { @@ -681,24 +453,20 @@ private void enterIOCriticalSection(String key) throws IOException { } } - /** - * Close all the cached connections. - */ - public void closeAll() { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger - .logDebug( - "Closing " + socketTable.size() - + " sockets from IOHandler"); - for (Enumeration values = socketTable.elements(); values - .hasMoreElements();) { - Socket s = (Socket) values.nextElement(); - try { - s.close(); - } catch (IOException ex) { - } - } - } + /** + * Close all the cached connections. + */ + public void closeAll() { + for (Enumeration values = socketTable.elements(); values + .hasMoreElements();) { + Socket s = (Socket) values.nextElement(); + try { + s.close(); + } catch (IOException ex) { + } + } + + } } diff --git a/src/gov/nist/javax/sip/stack/IllegalTransactionStateException.java b/src/gov/nist/javax/sip/stack/IllegalTransactionStateException.java deleted file mode 100644 index 858dc1678..000000000 --- a/src/gov/nist/javax/sip/stack/IllegalTransactionStateException.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * JBoss, Home of Professional Open Source - * Copyright 2008, Red Hat Middleware LLC, and individual contributors - * by the @authors tag. See the copyright.txt in the distribution for a - * full listing of individual contributors. - * - * This is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this software; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA, or see the FSF site: http://www.fsf.org. - */ -package gov.nist.javax.sip.stack; - -import javax.sip.SipException; - -/** - * @author jean.deruelle@gmail.com - * - */ -public class IllegalTransactionStateException extends SipException { - - Reason reason = Reason.GenericReason; - - public enum Reason { - RequestAlreadySent, MissingRequiredHeader, UnmatchingCSeq, ExpiresHeaderMandatory, ContactHeaderMandatory, GenericReason - } - - /** - * Constructs a new IllegalTransactionStateException - */ - public IllegalTransactionStateException(Reason reason) { - super(); - this.reason = reason; - } - - - - /** - * Constructs a new IllegalTransactionStateException with the specified error - * message. - * - * @param message the error message of this Exception. - */ - public IllegalTransactionStateException(String message, Reason reason) { - super(message); - this.reason = reason; - } - - /** - * Constructs a new IllegalTransactionStateException with the specified error - * message and specialized cause that triggered this error condition. - * - * @param message the detail of the error message - * @param cause the specialized cause that triggered this exception - */ - public IllegalTransactionStateException(String message, Throwable cause, Reason reason) { - super(message, cause); - this.reason = reason; - } - - - /** - * Returns the reason of this exception - * - * @return the reason of this exception - */ - public Reason getReason() { - return(reason); - } - -} diff --git a/src/gov/nist/javax/sip/stack/MessageChannel.java b/src/gov/nist/javax/sip/stack/MessageChannel.java index 6c6044fa6..8745ef8a9 100755 --- a/src/gov/nist/javax/sip/stack/MessageChannel.java +++ b/src/gov/nist/javax/sip/stack/MessageChannel.java @@ -1,13 +1,13 @@ /* - * Conditions Of Use - * + * Conditions Of Use + * * This software was developed by employees of the National Institute of * Standards and Technology (NIST), an agency of the Federal Government. * Pursuant to title 15 Untied States Code Section 105, works of NIST * employees are not subject to copyright protection in the United States * and are considered to be in the public domain. As a result, a formal * license is not needed to use the software. - * + * * This software is provided by NIST as a service and is expressly * provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED * OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF @@ -16,12 +16,12 @@ * regarding the use of the software or the results thereof, including but * not limited to the correctness, accuracy, reliability or usefulness of * the software. - * + * * Permission to use this software is contingent upon your acceptance * of the terms of this agreement - * + * * . - * + * */ /****************************************************************************** * Product of NIST/ITL Advanced Networking Technologies Division (ANTD). * @@ -29,13 +29,11 @@ package gov.nist.javax.sip.stack; -import gov.nist.core.CommonLogger; import gov.nist.core.Host; import gov.nist.core.HostPort; import gov.nist.core.InternalErrorHandler; import gov.nist.core.LogWriter; import gov.nist.core.ServerLogger; -import gov.nist.core.StackLogger; import gov.nist.javax.sip.address.AddressImpl; import gov.nist.javax.sip.header.ContentLength; import gov.nist.javax.sip.header.ContentType; @@ -62,37 +60,35 @@ /** * Message channel abstraction for the SIP stack. - * + * * @author M. Ranganathan
    Contains additions for support of symmetric NAT contributed by * Hagai. - * - * @version 1.2 $Revision: 1.40 $ $Date: 2010-12-02 22:44:53 $ - * - * + * + * @version 1.2 $Revision: 1.29.2.5 $ $Date: 2010-11-23 19:23:14 $ + * + * */ public abstract class MessageChannel { - private static StackLogger logger = CommonLogger.getLogger(MessageChannel.class); - // Incremented whenever a transaction gets assigned // to the message channel and decremented when // a transaction gets freed from the message channel. - protected int useCount; - - /** - * Hook method, overridden by subclasses - */ - protected void uncache() {} - + protected int useCount; + + /** + * Hook method, overridden by subclasses + */ + protected void uncache() {} + /** * Message processor to whom I belong (if set). */ protected transient MessageProcessor messageProcessor; - + /** * The client transaction that this message channel points to. */ - private SIPClientTransaction encapsulatedClientTransaction; + private SIPClientTransaction encapsulatedClientTransaction; /** * Close the message channel. @@ -101,21 +97,21 @@ protected void uncache() {} /** * Get the SIPStack object from this message channel. - * + * * @return SIPStack object of this message channel */ public abstract SIPTransactionStack getSIPStack(); /** * Get transport string of this message channel. - * + * * @return Transport string of this message channel. */ public abstract String getTransport(); /** * Get whether this channel is reliable or not. - * + * * @return True if reliable, false if not. */ public abstract boolean isReliable(); @@ -127,14 +123,14 @@ protected void uncache() {} /** * Send the message (after it has been formatted) - * + * * @param sipMessage Message to send. */ public abstract void sendMessage(SIPMessage sipMessage) throws IOException; /** * Get the peer address of the machine that sent us this message. - * + * * @return a string contianing the ip address or host name of the sender of the message. */ public abstract String getPeerAddress(); @@ -159,7 +155,7 @@ protected void uncache() {} public abstract String getKey(); /** - * Get the host for a viaHeader. + * Get the host to assign for an outgoing Request via header. */ public abstract String getViaHost(); @@ -168,10 +164,9 @@ protected void uncache() {} */ public abstract int getViaPort(); - /** * Send the message (after it has been formatted), to a specified address and a specified port - * + * * @param message Message to send. * @param receiverAddress Address of the receiver. * @param receiverPort Port of the receiver. @@ -181,7 +176,7 @@ protected abstract void sendMessage(byte[] message, InetAddress receiverAddress, /** * Get the host of this message channel. - * + * * @return host of this messsage channel. */ public String getHost() { @@ -190,7 +185,7 @@ public String getHost() { /** * Get port of this message channel. - * + * * @return Port of this message channel. */ public int getPort() { @@ -202,7 +197,7 @@ public int getPort() { /** * Send a formatted message to the specified target. - * + * * @param sipMessage Message to send. * @param hop hop to send it to. * @throws IOException If there is an error sending the message @@ -220,23 +215,23 @@ public void sendMessage(final SIPMessage sipMessage, Hop hop) throws IOException MessageChannel messageChannel = messageProcessor.createMessageChannel( hopAddr, hop.getPort()); if (messageChannel instanceof RawMessageChannel) { - final RawMessageChannel channel = (RawMessageChannel) messageChannel; - Runnable processMessageTask = new Runnable() { - - public void run() { - try { - ((RawMessageChannel) channel).processMessage((SIPMessage) sipMessage.clone()); - } catch (Exception ex) { - if (logger.isLoggingEnabled(ServerLogger.TRACE_ERROR)) { - logger.logError("Error self routing message cause by: ", ex); - } - } - } - }; - getSIPStack().getSelfRoutingThreadpoolExecutor().execute(processMessageTask); - - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("Self routing message"); + final RawMessageChannel channel = (RawMessageChannel) messageChannel; + Runnable processMessageTask = new Runnable() { + + public void run() { + try { + ((RawMessageChannel) channel).processMessage((SIPMessage) sipMessage.clone()); + } catch (Exception ex) { + if (getSIPStack().getStackLogger().isLoggingEnabled(ServerLogger.TRACE_ERROR)) { + getSIPStack().getStackLogger().logError("Error self routing message cause by: ", ex); + } + } + } + }; + getSIPStack().getSelfRoutingThreadpoolExecutor().execute(processMessageTask); + + if (getSIPStack().isLoggingEnabled(LogWriter.TRACE_DEBUG)) + getSIPStack().getStackLogger().logDebug("Self routing message"); return; } @@ -246,30 +241,24 @@ public void run() { this.sendMessage(msg, hopAddr, hop.getPort(), sipMessage instanceof SIPRequest); - // we successfully sent the message without an exception so let's - // now set port and address - sipMessage.setRemoteAddress(hopAddr); - sipMessage.setRemotePort(hop.getPort()); - sipMessage.setLocalPort(this.getPort()); - sipMessage.setLocalAddress(this.getMessageProcessor().getIpAddress()); } catch (IOException ioe) { throw ioe; } catch (Exception ex) { - if (this.logger.isLoggingEnabled(ServerLogger.TRACE_ERROR)) { - this.logger.logError("Error self routing message cause by: ", ex); - } - // TODO: When moving to Java 6, use the IOExcpetion(message, exception) constructor + if (this.getSIPStack().getStackLogger().isLoggingEnabled(ServerLogger.TRACE_ERROR)) { + this.getSIPStack().getStackLogger().logError("Error self routing message cause by: ", ex); + } + // TODO: When moving to Java 6, use the IOExcpetion(message, exception) constructor throw new IOException("Error self routing message"); } finally { - if (this.logger.isLoggingEnabled(ServerLogger.TRACE_MESSAGES)) + if (this.getSIPStack().getStackLogger().isLoggingEnabled(ServerLogger.TRACE_MESSAGES)) logMessage(sipMessage, hopAddr, hop.getPort(), time); } } /** * Send a message given SIP message. - * + * * @param sipMessage is the messge to send. * @param receiverAddress is the address to which we want to send * @param receiverPort is the port to which we want to send @@ -279,15 +268,6 @@ public void sendMessage(SIPMessage sipMessage, InetAddress receiverAddress, int long time = System.currentTimeMillis(); byte[] bytes = sipMessage.encodeAsBytes(this.getTransport()); sendMessage(bytes, receiverAddress, receiverPort, sipMessage instanceof SIPRequest); - - // we successfully sent the message without an exception so let's - // set port and address before we feed it to the logger. - sipMessage.setRemoteAddress(receiverAddress); - sipMessage.setRemotePort(receiverPort); - sipMessage.setLocalPort(this.getPort()); - sipMessage.setLocalAddress(this.getMessageProcessor().getIpAddress()); - - //ready to log logMessage(sipMessage, receiverAddress, receiverPort, time); } @@ -333,7 +313,7 @@ public HostPort getHostPort() { /** * Get the peer host and port. - * + * * @return a HostPort structure for the peer. */ public HostPort getPeerHostPort() { @@ -345,7 +325,7 @@ public HostPort getPeerHostPort() { /** * Get the Via header for this transport. Note that this does not set a branch identifier. - * + * * @return a via header for outgoing messages sent from this channel. */ public Via getViaHeader() { @@ -363,7 +343,7 @@ public Via getViaHeader() { /** * Get the via header host:port structure. This is extracted from the topmost via header of * the request. - * + * * @return a host:port structure */ public HostPort getViaHostPort() { @@ -375,13 +355,13 @@ public HostPort getViaHostPort() { /** * Log a message sent to an address and port via the default interface. - * + * * @param sipMessage is the message to log. * @param address is the inet address to which the message is sent. * @param port is the port to which the message is directed. */ - public void logMessage(SIPMessage sipMessage, InetAddress address, int port, long time) { - if (!logger.isLoggingEnabled(ServerLogger.TRACE_MESSAGES)) + protected void logMessage(SIPMessage sipMessage, InetAddress address, int port, long time) { + if (!getSIPStack().getStackLogger().isLoggingEnabled(ServerLogger.TRACE_MESSAGES)) return; // Default port. @@ -394,10 +374,10 @@ public void logMessage(SIPMessage sipMessage, InetAddress address, int port, lon /** * Log a response received at this message channel. This is used for processing incoming * responses to a client transaction. - * + * * @param receptionTime is the time at which the response was received. * @param status is the processing status of the message. - * + * */ public void logResponse(SIPResponse sipResponse, long receptionTime, String status) { int peerport = getPeerPort(); @@ -414,13 +394,13 @@ public void logResponse(SIPResponse sipResponse, long receptionTime, String stat /** * Creates a response to a bad request (ie one that causes a ParseException) - * + * * @param badReq * @return message bytes, null if unable to formulate response */ protected final String createBadReqRes(String badReq, ParseException pe) { - StringBuilder buf = new StringBuilder(512); + StringBuffer buf = new StringBuffer(512); buf.append("SIP/2.0 400 Bad Request (" + pe.getLocalizedMessage() + ')'); // We need the following headers: all Vias, CSeq, Call-ID, From, To @@ -450,8 +430,8 @@ protected final String createBadReqRes(String badReq, ParseException pe) { if (! (this instanceof UDPMessageChannel) || clength + buf.length() + ContentTypeHeader.NAME.length() + ": message/sipfrag\r\n".length() + - ContentLengthHeader.NAME.length() < 1300) { - + ContentLengthHeader.NAME.length() < 1300) { + /* * Check to see we are within one UDP packet. */ @@ -464,22 +444,22 @@ protected final String createBadReqRes(String badReq, ParseException pe) { ContentLength clengthHeader = new ContentLength(0); buf.append("\r\n" + clengthHeader.toString()); } - + return buf.toString(); } /** * Copies a header from a request - * + * * @param name * @param fromReq * @param buf * @return - * + * * Note: some limitations here: does not work for short forms of headers, or continuations; * problems when header names appear in other parts of the request */ - private static final boolean copyHeader(String name, String fromReq, StringBuilder buf) { + private static final boolean copyHeader(String name, String fromReq, StringBuffer buf) { int start = fromReq.indexOf(name); if (start != -1) { int end = fromReq.indexOf("\r\n", start); @@ -495,14 +475,14 @@ private static final boolean copyHeader(String name, String fromReq, StringBuild /** * Copies all via headers from a request - * + * * @param fromReq * @param buf * @return - * + * * Note: some limitations here: does not work for short forms of headers, or continuations */ - private static final boolean copyViaHeaders(String fromReq, StringBuilder buf) { + private static final boolean copyViaHeaders(String fromReq, StringBuffer buf) { int start = fromReq.indexOf(ViaHeader.NAME); boolean found = false; while (start != -1) { @@ -526,12 +506,12 @@ private static final boolean copyViaHeaders(String fromReq, StringBuilder buf) { public MessageProcessor getMessageProcessor() { return this.messageProcessor; } - + public SIPClientTransaction getEncapsulatedClientTransaction() { - return this.encapsulatedClientTransaction; + return this.encapsulatedClientTransaction; } - public void setEncapsulatedClientTransaction(SIPClientTransaction transaction) { - this.encapsulatedClientTransaction = transaction; - } + public void setEncapsulatedClientTransaction(SIPClientTransaction transaction) { + this.encapsulatedClientTransaction = transaction; + } } diff --git a/src/gov/nist/javax/sip/stack/MessageProcessor.java b/src/gov/nist/javax/sip/stack/MessageProcessor.java index 21b5f70de..65d3cdbc7 100755 --- a/src/gov/nist/javax/sip/stack/MessageProcessor.java +++ b/src/gov/nist/javax/sip/stack/MessageProcessor.java @@ -25,12 +25,10 @@ */ package gov.nist.javax.sip.stack; -import gov.nist.core.CommonLogger; import gov.nist.core.Host; import gov.nist.core.HostPort; import gov.nist.core.InternalErrorHandler; import gov.nist.core.LogWriter; -import gov.nist.core.StackLogger; import gov.nist.javax.sip.ListeningPointImpl; import gov.nist.javax.sip.header.Via; @@ -47,13 +45,12 @@ * The main job of the message processor is to instantiate message channels for * the given transport. * - * @version 1.2 $Revision: 1.20 $ $Date: 2010-12-02 22:04:15 $ + * @version 1.2 $Revision: 1.18.2.1 $ $Date: 2010-11-23 19:23:12 $ * * @author M. Ranganathan
    * */ public abstract class MessageProcessor implements Runnable { - private static StackLogger logger = CommonLogger.getLogger(MessageProcessor.class); /** * A string containing the 0.0.0.0 IPv4 ANY address. */ @@ -189,8 +186,8 @@ public Via getViaHeader() { } public ListeningPointImpl getListeningPoint() { if ( listeningPoint == null ) { - if ( logger.isLoggingEnabled()) { - this.logger.logError("getListeningPoint" + this + + if ( this.getSIPStack().isLoggingEnabled()) { + this.getSIPStack().getStackLogger().logError("getListeningPoint" + this + " returning null listeningpoint"); } @@ -199,14 +196,14 @@ public ListeningPointImpl getListeningPoint() { } public void setListeningPoint(ListeningPointImpl lp) { - if ( logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - this.logger.logDebug("setListeningPoint" + this + + if ( this.getSIPStack().isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + this.getSIPStack().getStackLogger().logDebug("setListeningPoint" + this + " listeningPoint = " + lp); } if ( lp.getPort() != this.getPort()) InternalErrorHandler.handleException - ("lp mismatch with provider",logger); + ("lp mismatch with provider",getSIPStack().getStackLogger()); this.listeningPoint = lp; } diff --git a/src/gov/nist/javax/sip/stack/SIPClientTransaction.java b/src/gov/nist/javax/sip/stack/SIPClientTransaction.java index fc9f2a7f5..038e5617f 100755 --- a/src/gov/nist/javax/sip/stack/SIPClientTransaction.java +++ b/src/gov/nist/javax/sip/stack/SIPClientTransaction.java @@ -25,18 +25,14 @@ */ package gov.nist.javax.sip.stack; -import gov.nist.core.CommonLogger; import gov.nist.core.InternalErrorHandler; import gov.nist.core.LogWriter; import gov.nist.core.NameValueList; -import gov.nist.core.StackLogger; import gov.nist.javax.sip.SIPConstants; import gov.nist.javax.sip.SipProviderImpl; -import gov.nist.javax.sip.SipStackImpl; import gov.nist.javax.sip.Utils; import gov.nist.javax.sip.address.AddressImpl; import gov.nist.javax.sip.header.Contact; -import gov.nist.javax.sip.header.Event; import gov.nist.javax.sip.header.Expires; import gov.nist.javax.sip.header.RecordRoute; import gov.nist.javax.sip.header.RecordRouteList; @@ -45,18 +41,16 @@ import gov.nist.javax.sip.header.TimeStamp; import gov.nist.javax.sip.header.To; import gov.nist.javax.sip.header.Via; +import gov.nist.javax.sip.header.ViaList; import gov.nist.javax.sip.message.SIPMessage; import gov.nist.javax.sip.message.SIPRequest; import gov.nist.javax.sip.message.SIPResponse; -import gov.nist.javax.sip.stack.IllegalTransactionStateException.Reason; import java.io.IOException; import java.text.ParseException; -import java.util.HashSet; import java.util.ListIterator; -import java.util.Set; -import java.util.concurrent.CopyOnWriteArraySet; -import java.util.concurrent.atomic.AtomicBoolean; +import java.util.TimerTask; +import java.util.concurrent.ConcurrentHashMap; import javax.sip.Dialog; import javax.sip.DialogState; @@ -68,7 +62,6 @@ import javax.sip.TransactionState; import javax.sip.address.Hop; import javax.sip.address.SipURI; -import javax.sip.header.EventHeader; import javax.sip.header.ExpiresHeader; import javax.sip.header.RouteHeader; import javax.sip.header.TimeStampHeader; @@ -185,17 +178,16 @@ * * @author M. Ranganathan * - * @version 1.2 $Revision: 1.144 $ $Date: 2010-12-02 22:04:16 $ + * @version 1.2 $Revision: 1.125.2.2 $ $Date: 2010-11-23 19:23:13 $ */ public class SIPClientTransaction extends SIPTransaction implements ServerResponseInterface, javax.sip.ClientTransaction, gov.nist.javax.sip.ClientTransactionExt { - private static StackLogger logger = CommonLogger.getLogger(SIPClientTransaction.class); + // a SIP Client transaction may belong simultaneously to multiple // dialogs in the early state. These dialogs all have // the same call ID and same From tag but different to tags. - - //jeand : we don't keep the ref to the dialogs but only to their id to save on memory - private Set sipDialogs; + + private ConcurrentHashMap sipDialogs; private SIPRequest lastRequest; @@ -206,9 +198,6 @@ public class SIPClientTransaction extends SIPTransaction implements ServerRespon // Real ResponseInterface to pass messages to private transient ServerResponseInterface respondTo; - // jeand: ref to the default dialog id to allow nullying the ref to the dialog quickly - // and thus saving on mem - private String defaultDialogId; private SIPDialog defaultDialog; private Hop nextHop; @@ -218,21 +207,8 @@ public class SIPClientTransaction extends SIPTransaction implements ServerRespon private boolean timeoutIfStillInCallingState; private int callingStateTimeoutCount; - - private SIPStackTimerTask transactionTimer; - - // jeand/ avoid keeping the full Original Request in memory - private String originalRequestFromTag; - private String originalRequestCallId; - private Event originalRequestEventHeader; - private Contact originalRequestContact; - private String originalRequestScheme; - - private Object transactionTimerLock = new Object(); - private AtomicBoolean timerKStarted = new AtomicBoolean(false); - private boolean transactionTimerCancelled = false; - private Set responsesReceived = new HashSet(2); - + + private ExpiresTimerTask expiresTimerTask; public class TransactionTimer extends SIPStackTimerTask { @@ -240,31 +216,63 @@ public TransactionTimer() { } - public void runTask() { + protected void runTask() { SIPClientTransaction clientTransaction; SIPTransactionStack sipStack; clientTransaction = SIPClientTransaction.this; sipStack = clientTransaction.sipStack; // If the transaction has terminated, - if (clientTransaction.isTerminated()) { + if (clientTransaction.isTerminated()) { + + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( + "removing = " + clientTransaction + " isReliable " + + clientTransaction.isReliable()); + } + + sipStack.removeTransaction(clientTransaction); try { - sipStack.getTimer().cancel(this); + this.cancel(); } catch (IllegalStateException ex) { if (!sipStack.isAlive()) return; } - cleanUpOnTerminated(); + // Client transaction terminated. Kill connection if + // this is a TCP after the linger timer has expired. + // The linger timer is needed to allow any pending requests to + // return responses. + if ((!sipStack.cacheClientConnections) && clientTransaction.isReliable()) { + + int newUseCount = --clientTransaction.getMessageChannel().useCount; + if (newUseCount <= 0) { + // Let the connection linger for a while and then close + // it. + TimerTask myTimer = new LingerTimer(); + sipStack.getTimer().schedule(myTimer, + SIPTransactionStack.CONNECTION_LINGER_TIME * 1000); + } + + } else { + // Cache the client connections so dont close the + // connection. This keeps the connection open permanently + // until the client disconnects. + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG) && clientTransaction.isReliable()) { + int useCount = clientTransaction.getMessageChannel().useCount; + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Client Use Count = " + useCount); + } + } } else { // If this transaction has not // terminated, // Fire the transaction timer. clientTransaction.fireTimer(); - + } } @@ -287,8 +295,8 @@ public void runTask() { SIPClientTransaction.this, Timeout.TRANSACTION); provider.handleEvent(tte, ct); } else { - if ( SIPClientTransaction.this.logger.isLoggingEnabled(LogWriter.TRACE_DEBUG) ) { - SIPClientTransaction.this.logger.logDebug("state = " + ct.getState()); + if ( SIPClientTransaction.this.getSIPStack().getStackLogger().isLoggingEnabled(LogWriter.TRACE_DEBUG) ) { + SIPClientTransaction.this.getSIPStack().getStackLogger().logDebug("state = " + ct.getState()); } } } @@ -305,18 +313,25 @@ public void runTask() { protected SIPClientTransaction(SIPTransactionStack newSIPStack, MessageChannel newChannelToUse) { super(newSIPStack, newChannelToUse); // Create a random branch parameter for this transaction + // setBranch( SIPConstants.BRANCH_MAGIC_COOKIE + + // Integer.toHexString( hashCode( ) ) ); setBranch(Utils.getInstance().generateBranchId()); this.messageProcessor = newChannelToUse.messageProcessor; this.setEncapsulatedChannel(newChannelToUse); this.notifyOnRetransmit = false; this.timeoutIfStillInCallingState = false; - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("Creating clientTransaction " + this); - logger.logStackTrace(); + // This semaphore guards the listener from being + // re-entered for this transaction. That is + // for a give tx, the listener is called at most + // once with an outstanding request. + + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("Creating clientTransaction " + this); + sipStack.getStackLogger().logStackTrace(); } // this.startTransactionTimer(); - this.sipDialogs = new CopyOnWriteArraySet(); + this.sipDialogs = new ConcurrentHashMap(); } /** @@ -325,12 +340,12 @@ protected SIPClientTransaction(SIPTransactionStack newSIPStack, MessageChannel n * @param newRespondTo ResponseInterface to send messages to. */ public void setResponseInterface(ServerResponseInterface newRespondTo) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( "Setting response interface for " + this + " to " + newRespondTo); if (newRespondTo == null) { - logger.logStackTrace(); - logger.logDebug("WARNING -- setting to null!"); + sipStack.getStackLogger().logStackTrace(); + sipStack.getStackLogger().logDebug("WARNING -- setting to null!"); } } @@ -357,10 +372,10 @@ public MessageChannel getRequestChannel() { public boolean isMessagePartOfTransaction(SIPMessage messageToTest) { // List of Via headers in the message to test - Via topMostViaHeader = messageToTest.getTopmostVia(); + ViaList viaHeaders = messageToTest.getViaHeaders(); // Flags whether the select message is part of this transaction boolean transactionMatches; - String messageBranch = topMostViaHeader.getBranch(); + String messageBranch = ((Via) viaHeaders.getFirst()).getBranch(); boolean rfc3261Compliant = getBranch() != null && messageBranch != null && getBranch().toLowerCase().startsWith( @@ -369,21 +384,21 @@ && getBranch().toLowerCase().startsWith( SIPConstants.BRANCH_MAGIC_COOKIE_LOWER_CASE); transactionMatches = false; - if (TransactionState._COMPLETED == this.getInternalState()) { + if (TransactionState.COMPLETED == this.getState()) { if (rfc3261Compliant) { transactionMatches = getBranch().equalsIgnoreCase( - topMostViaHeader.getBranch()) + ((Via) viaHeaders.getFirst()).getBranch()) && getMethod().equals(messageToTest.getCSeq().getMethod()); } else { transactionMatches = getBranch().equals(messageToTest.getTransactionId()); } } else if (!isTerminated()) { if (rfc3261Compliant) { - if (topMostViaHeader != null) { + if (viaHeaders != null) { // If the branch parameter is the // same as this transaction and the method is the same, - if (getBranch().equalsIgnoreCase(topMostViaHeader.getBranch())) { - transactionMatches = getMethod().equals( + if (getBranch().equalsIgnoreCase(((Via) viaHeaders.getFirst()).getBranch())) { + transactionMatches = getOriginalRequest().getCSeq().getMethod().equals( messageToTest.getCSeq().getMethod()); } @@ -394,7 +409,7 @@ && getBranch().toLowerCase().startsWith( transactionMatches = getBranch().equalsIgnoreCase( messageToTest.getTransactionId()); } else { - transactionMatches = ((SIPRequest)getRequest()).getTransactionId() + transactionMatches = getOriginalRequest().getTransactionId() .equalsIgnoreCase(messageToTest.getTransactionId()); } @@ -419,20 +434,20 @@ public void sendMessage(SIPMessage messageToSend) throws IOException { transactionRequest = (SIPRequest) messageToSend; // Set the branch id for the top via header. - Via topVia = (Via) transactionRequest.getTopmostVia(); + Via topVia = (Via) transactionRequest.getViaHeaders().getFirst(); // Tack on a branch identifier to match responses. try { topVia.setBranch(getBranch()); } catch (java.text.ParseException ex) { } - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("Sending Message " + messageToSend); - logger.logDebug("TransactionState " + this.getState()); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("Sending Message " + messageToSend); + sipStack.getStackLogger().logDebug("TransactionState " + this.getState()); } // If this is the first request for this transaction, - if (TransactionState._PROCEEDING == getInternalState() - || TransactionState._CALLING == getInternalState()) { + if (TransactionState.PROCEEDING == getState() + || TransactionState.CALLING == getState()) { // If this is a TU-generated ACK request, if (transactionRequest.getMethod().equals(Request.ACK)) { @@ -440,11 +455,10 @@ public void sendMessage(SIPMessage messageToSend) throws IOException { // Send directly to the underlying // transport and close this transaction if (isReliable()) { - this.setState(TransactionState._TERMINATED); + this.setState(TransactionState.TERMINATED); } else { - this.setState(TransactionState._COMPLETED); + this.setState(TransactionState.COMPLETED); } - cleanUpOnTimer(); // BUGBUG -- This suppresses sending the ACK uncomment this // to // test 4xx retransmission @@ -459,7 +473,7 @@ public void sendMessage(SIPMessage messageToSend) throws IOException { // Send the message to the server lastRequest = transactionRequest; - if (getInternalState() < 0) { + if (getState() == null) { // Save this request as the one this transaction // is handling setOriginalRequest(transactionRequest); @@ -467,13 +481,12 @@ public void sendMessage(SIPMessage messageToSend) throws IOException { // Set state first to avoid race condition.. if (transactionRequest.getMethod().equals(Request.INVITE)) { - this.setState(TransactionState._CALLING); + this.setState(TransactionState.CALLING); } else if (transactionRequest.getMethod().equals(Request.ACK)) { // Acks are never retransmitted. - this.setState(TransactionState._TERMINATED); - cleanUpOnTimer(); + this.setState(TransactionState.TERMINATED); } else { - this.setState(TransactionState._TRYING); + this.setState(TransactionState.TRYING); } if (!isReliable()) { enableRetransmissionTimer(); @@ -491,7 +504,7 @@ public void sendMessage(SIPMessage messageToSend) throws IOException { } catch (IOException e) { - this.setState(TransactionState._TERMINATED); + this.setState(TransactionState.TERMINATED); throw e; } @@ -516,21 +529,21 @@ public synchronized void processResponse(SIPResponse transactionResponse, // If the state has not yet been assigned then this is a // spurious response. - if (getInternalState() < 0) + if (getState() == null) return; // Ignore 1xx - if ((TransactionState._COMPLETED == this.getInternalState() || TransactionState._TERMINATED == this - .getInternalState()) + if ((TransactionState.COMPLETED == this.getState() || TransactionState.TERMINATED == this + .getState()) && transactionResponse.getStatusCode() / 100 == 1) { return; } - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( "processing " + transactionResponse.getFirstLine() + "current state = " + getState()); - logger.logDebug("dialog = " + dialog); + sipStack.getStackLogger().logDebug("dialog = " + dialog); } this.lastResponse = transactionResponse; @@ -550,9 +563,9 @@ public synchronized void processResponse(SIPResponse transactionResponse, else nonInviteClientTransaction(transactionResponse, sourceChannel, dialog); } catch (IOException ex) { - if (logger.isLoggingEnabled()) - logger.logException(ex); - this.setState(TransactionState._TERMINATED); + if (sipStack.isLoggingEnabled()) + sipStack.getStackLogger().logException(ex); + this.setState(TransactionState.TERMINATED); raiseErrorEvent(SIPTransactionErrorEvent.TRANSPORT_ERROR); } } @@ -620,9 +633,9 @@ public synchronized void processResponse(SIPResponse transactionResponse, private void nonInviteClientTransaction(SIPResponse transactionResponse, MessageChannel sourceChannel, SIPDialog sipDialog) throws IOException { int statusCode = transactionResponse.getStatusCode(); - if (TransactionState._TRYING == this.getInternalState()) { - if (statusCode / 100 == 1) { - this.setState(TransactionState._PROCEEDING); + if (TransactionState.TRYING == this.getState()) { + if (statusCode / 100 == 1) { + this.setState(TransactionState.PROCEEDING); enableRetransmissionTimer(MAXIMUM_RETRANSMISSION_TICK_COUNT); enableTimeoutTimer(TIMER_F); // According to RFC, the TU has to be informed on @@ -633,25 +646,20 @@ private void nonInviteClientTransaction(SIPResponse transactionResponse, this.semRelease(); } } else if (200 <= statusCode && statusCode <= 699) { - if (!isReliable()) { - this.setState(TransactionState._COMPLETED); - scheduleTimerK(TIMER_K); - } else { - this.setState(TransactionState._TERMINATED); - } // Send the response up to the TU. if (respondTo != null) { respondTo.processResponse(transactionResponse, this, sipDialog); } else { this.semRelease(); } - if (isReliable() - && TransactionState._TERMINATED == getInternalState()) { - cleanUpOnTerminated(); + if (!isReliable()) { + this.setState(TransactionState.COMPLETED); + enableTimeoutTimer(TIMER_K); + } else { + this.setState(TransactionState.TERMINATED); } - cleanUpOnTimer(); } - } else if (TransactionState._PROCEEDING == this.getInternalState()) { + } else if (TransactionState.PROCEEDING == this.getState()) { if (statusCode / 100 == 1) { if (respondTo != null) { respondTo.processResponse(transactionResponse, this, sipDialog); @@ -659,66 +667,30 @@ private void nonInviteClientTransaction(SIPResponse transactionResponse, this.semRelease(); } } else if (200 <= statusCode && statusCode <= 699) { - disableRetransmissionTimer(); - disableTimeoutTimer(); - if (!isReliable()) { - this.setState(TransactionState._COMPLETED); - scheduleTimerK(TIMER_K); - } else { - this.setState(TransactionState._TERMINATED); - } if (respondTo != null) { respondTo.processResponse(transactionResponse, this, sipDialog); } else { this.semRelease(); } - if (isReliable() - && TransactionState._TERMINATED == getInternalState()) { - cleanUpOnTerminated(); + disableRetransmissionTimer(); + disableTimeoutTimer(); + if (!isReliable()) { + this.setState(TransactionState.COMPLETED); + enableTimeoutTimer(TIMER_K); + } else { + this.setState(TransactionState.TERMINATED); } - cleanUpOnTimer(); } } else { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( " Not sending response to TU! " + getState()); } this.semRelease(); } - } - - // avoid re-scheduling the transaction timer every 500ms while we know we have to wait for TIMER_K * 500 ms - private void scheduleTimerK(long time) { - if(transactionTimer != null && timerKStarted.compareAndSet(false, true)) { - synchronized (transactionTimerLock) { - if(!transactionTimerCancelled) { - sipStack.getTimer().cancel(transactionTimer); - transactionTimer = null; - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("starting TransactionTimerK() : " + getTransactionId() + " time " + time); - } - SIPStackTimerTask task = new SIPStackTimerTask () { - - public void runTask() { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("executing TransactionTimerJ() : " + getTransactionId()); - } - fireTimeoutTimer(); - cleanUpOnTerminated(); - } - }; - if(time > 0) { - sipStack.getTimer().schedule(task, time * BASE_TIMER_INTERVAL); - } else { - task.runTask(); - } - transactionTimerCancelled =true; - } - } - } - } + } - /** + /** * Implements the state machine for invite client transactions. * *
    @@ -779,7 +751,7 @@ private void inviteClientTransaction(SIPResponse transactionResponse,
                 MessageChannel sourceChannel, SIPDialog dialog) throws IOException {
             int statusCode = transactionResponse.getStatusCode();
            
    -        if (TransactionState._TERMINATED == this.getInternalState()) {
    +        if (TransactionState.TERMINATED == this.getState()) {
                 boolean ackAlreadySent = false;
                // if (dialog != null  && dialog.isAckSeen() && dialog.getLastAckSent() != null) 
                 if ( dialog!= null && dialog.isAckSent(transactionResponse.getCSeq().getSeqNumber())) {
    @@ -797,8 +769,8 @@ private void inviteClientTransaction(SIPResponse transactionResponse,
                     try {
                         // Found the dialog - resend the ACK and
                         // dont pass up the null transaction
    -                    if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG))
    -                        logger.logDebug("resending ACK");
    +                    if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG))
    +                        sipStack.getStackLogger().logDebug("resending ACK");
     
                         dialog.resendAck();
                     } catch (SipException ex) {
    @@ -808,15 +780,15 @@ private void inviteClientTransaction(SIPResponse transactionResponse,
     
                 this.semRelease();
                 return;
    -        } else if (TransactionState._CALLING == this.getInternalState()) {
    +        } else if (TransactionState.CALLING == this.getState()) {
                 if (statusCode / 100 == 2) {
     
                     // JvB: do this ~before~ calling the application, to avoid
                     // retransmissions
                     // of the INVITE after app sends ACK
                     disableRetransmissionTimer();
    -                disableTimeoutTimer();                
    -                this.setState(TransactionState._TERMINATED);
    +                disableTimeoutTimer();
    +                this.setState(TransactionState.TERMINATED);
     
                     // 200 responses are always seen by TU.
                     if (respondTo != null)
    @@ -827,8 +799,8 @@ private void inviteClientTransaction(SIPResponse transactionResponse,
     
                 } else if (statusCode / 100 == 1) {
                     disableRetransmissionTimer();
    -                disableTimeoutTimer();                
    -                this.setState(TransactionState._PROCEEDING);
    +                disableTimeoutTimer();
    +                this.setState(TransactionState.PROCEEDING);
     
                     if (respondTo != null)
                         respondTo.processResponse(transactionResponse, this, dialog);
    @@ -843,7 +815,7 @@ private void inviteClientTransaction(SIPResponse transactionResponse,
                         sendMessage((SIPRequest) createErrorAck());
     
                     } catch (Exception ex) {
    -                    logger.logError(
    +                    sipStack.getStackLogger().logError(
                                 "Unexpected Exception sending ACK -- sending error AcK ", ex);
     
                     }
    @@ -855,33 +827,33 @@ private void inviteClientTransaction(SIPResponse transactionResponse,
                      * TU, and the client transaction MUST generate an ACK request.
                      */
     
    +                if (respondTo != null) {
    +                    respondTo.processResponse(transactionResponse, this, dialog);
    +                } else {
    +                    this.semRelease();
    +                }
    +
                     if (this.getDialog() != null &&  ((SIPDialog)this.getDialog()).isBackToBackUserAgent()) {
                         ((SIPDialog) this.getDialog()).releaseAckSem();
                     }
     
    -                if (!isReliable()) {                    
    -                    this.setState(TransactionState._COMPLETED);
    +                if (!isReliable()) {
    +                    this.setState(TransactionState.COMPLETED);
                         enableTimeoutTimer(TIMER_D);
    -                } else {                    
    -                    // Proceed immediately to the TERMINATED state.
    -                    this.setState(TransactionState._TERMINATED);
    -                }
    -                if (respondTo != null) {
    -                    respondTo.processResponse(transactionResponse, this, dialog);
                     } else {
    -                    this.semRelease();
    +                    // Proceed immediately to the TERMINATED state.
    +                    this.setState(TransactionState.TERMINATED);
                     }
    -                cleanUpOnTimer();
                 }
    -        } else if (TransactionState._PROCEEDING == this.getInternalState()) {
    +        } else if (TransactionState.PROCEEDING == this.getState()) {
                 if (statusCode / 100 == 1) {
                     if (respondTo != null) {
                         respondTo.processResponse(transactionResponse, this, dialog);
                     } else {
                         this.semRelease();
                     }
    -            } else if (statusCode / 100 == 2) {                
    -                this.setState(TransactionState._TERMINATED);
    +            } else if (statusCode / 100 == 2) {
    +                this.setState(TransactionState.TERMINATED);
                     if (respondTo != null) {
                         respondTo.processResponse(transactionResponse, this, dialog);
                     } else {
    @@ -900,13 +872,12 @@ private void inviteClientTransaction(SIPResponse transactionResponse,
                         ((SIPDialog) this.getDialog()).releaseAckSem();
                     }
                     // JvB: update state before passing to app
    -                if (!isReliable()) {                    
    -                    this.setState(TransactionState._COMPLETED);
    +                if (!isReliable()) {
    +                    this.setState(TransactionState.COMPLETED);
                         this.enableTimeoutTimer(TIMER_D);
    -                } else {                    
    -                    this.setState(TransactionState._TERMINATED);
    +                } else {
    +                    this.setState(TransactionState.TERMINATED);
                     }
    -                cleanUpOnTimer();
     
                     // Pass up to the TU for processing.
                     if (respondTo != null)
    @@ -920,7 +891,7 @@ private void inviteClientTransaction(SIPResponse transactionResponse,
                     // enableTimeoutTimer(TIMER_D);
                     // }
                 }
    -        } else if (TransactionState._COMPLETED == this.getInternalState()) {
    +        } else if (TransactionState.COMPLETED == this.getState()) {
                 if (300 <= statusCode && statusCode <= 699) {
                     // Send back an ACK request
                     try {
    @@ -944,19 +915,19 @@ private void inviteClientTransaction(SIPResponse transactionResponse,
         public void sendRequest() throws SipException {
             SIPRequest sipRequest = this.getOriginalRequest();
     
    -        if (this.getInternalState() >= 0)
    -            throw new IllegalTransactionStateException("Request already sent", Reason.RequestAlreadySent);
    +        if (this.getState() != null)
    +            throw new SipException("Request already sent");
     
    -        if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    -            logger.logDebug("sendRequest() " + sipRequest);
    +        if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    +            sipStack.getStackLogger().logDebug("sendRequest() " + sipRequest);
             }
     
             try {
                 sipRequest.checkHeaders();
             } catch (ParseException ex) {
    -        	if (logger.isLoggingEnabled())
    -        		logger.logError("missing required header");
    -        	throw new IllegalTransactionStateException(ex.getMessage(), Reason.MissingRequiredHeader);
    +        	if (sipStack.isLoggingEnabled())
    +        		sipStack.getStackLogger().logError("missing required header");
    +            throw new SipException(ex.getMessage());
             }
     
             if (getMethod().equals(Request.SUBSCRIBE)
    @@ -966,8 +937,8 @@ public void sendRequest() throws SipException {
                  * defined by the event package being used.
                  * 
                  */
    -        	if (logger.isLoggingEnabled())
    -        		logger.logWarning(
    +        	if (sipStack.isLoggingEnabled())
    +        		sipStack.getStackLogger().logWarning(
                         "Expires header missing in outgoing subscribe --"
                                 + " Notifier will assume implied value on event package");
             }
    @@ -977,7 +948,7 @@ public void sendRequest() throws SipException {
                  * 136) reported by Raghav Ramesh ( BT )
                  * 
                  */
    -            if (this.getMethod().equals(Request.CANCEL)
    +            if (this.getOriginalRequest().getMethod().equals(Request.CANCEL)
                         && sipStack.isCancelClientTransactionChecked()) {
                     SIPClientTransaction ct = (SIPClientTransaction) sipStack.findCancelTransaction(
                             this.getOriginalRequest(), false);
    @@ -988,14 +959,16 @@ public void sendRequest() throws SipException {
                          * requests that have already generated a final response.
                          */
                         throw new SipException("Could not find original tx to cancel. RFC 3261 9.1");
    -                } else if (ct.getInternalState() < 0) {
    +                } else if (ct.getState() == null) {
                         throw new SipException(
                                 "State is null no provisional response yet -- cannot cancel RFC 3261 9.1");
    -                } else if (!ct.isInviteTransaction()) {
    +                } else if (!ct.getMethod().equals(Request.INVITE)) {
                         throw new SipException("Cannot cancel non-invite requests RFC 3261 9.1");
                     }
    -            } else if (this.getMethod().equals(Request.BYE)
    -                    || this.getMethod().equals(Request.NOTIFY)) {
    +            } else
    +
    +            if (this.getOriginalRequest().getMethod().equals(Request.BYE)
    +                    || this.getOriginalRequest().getMethod().equals(Request.NOTIFY)) {
                     SIPDialog dialog = sipStack.getDialog(this.getOriginalRequest()
                             .getDialogId(false));
                     // I want to behave like a user agent so send the BYE using the
    @@ -1007,7 +980,7 @@ public void sendRequest() throws SipException {
                     }
                 }
                 // Only map this after the fist request is sent out.
    -            if (isInviteTransaction()) {
    +            if (this.getMethod().equals(Request.INVITE)) {
                     SIPDialog dialog = this.getDefaultDialog();
     
                     if (dialog != null && dialog.isBackToBackUserAgent()) {
    @@ -1019,29 +992,23 @@ public void sendRequest() throws SipException {
                     }
                 }
                 this.isMapped = true;
    -         // Time extracted from the Expires header.
                 int expiresTime = -1;
    -
    -           if ( sipRequest.getHeader(ExpiresHeader.NAME) != null ) {
    +            if ( sipRequest.getHeader(ExpiresHeader.NAME) != null ) {
                     Expires expires = (Expires) sipRequest.getHeader(ExpiresHeader.NAME);
                     expiresTime = expires.getExpires();
                 } 
                 // This is a User Agent. The user has specified an Expires time. Start a timer
                 // which will check if the tx is terminated by that time.
    -            if ( this.getDefaultDialog() != null  &&  isInviteTransaction() &&
    +            if ( this.getDefaultDialog() != null  &&  getMethod().equals(Request.INVITE) &&
                         expiresTime != -1 && expiresTimerTask == null ) {
                     this.expiresTimerTask = new ExpiresTimerTask();
                     sipStack.getTimer().schedule(expiresTimerTask, expiresTime * 1000);
                     
                 }
                 this.sendMessage(sipRequest);
    -            
     
             } catch (IOException ex) {
    -            this.setState(TransactionState._TERMINATED);
    -            if ( this.expiresTimerTask != null ) {
    -                sipStack.getTimer().cancel(this.expiresTimerTask);
    -            }
    +            this.setState(TransactionState.TERMINATED);
                 throw new SipException(
                         ex.getMessage() == null ? "IO Error sending request" : ex.getMessage(),
                         ex);
    @@ -1057,17 +1024,17 @@ protected void fireRetransmissionTimer() {
             try {
     
                 // Resend the last request sent
    -            if (this.getInternalState() < 0 || !this.isMapped)
    +            if (this.getState() == null || !this.isMapped)
                     return;
     
                 boolean inv = isInviteTransaction();
    -            int s = this.getInternalState();
    +            TransactionState s = this.getState();
     
                 // JvB: INVITE CTs only retransmit in CALLING, non-INVITE in both TRYING and
                 // PROCEEDING
                 // Bug-fix for non-INVITE transactions not retransmitted when 1xx response received
    -            if ((inv && TransactionState._CALLING == s)
    -                    || (!inv && (TransactionState._TRYING == s || TransactionState._PROCEEDING == s))) {
    +            if ((inv && TransactionState.CALLING == s)
    +                    || (!inv && (TransactionState.TRYING == s || TransactionState.PROCEEDING == s))) {
                     // If the retransmission filter is disabled then
                     // retransmission of the INVITE is the application
                     // responsibility.
    @@ -1091,7 +1058,7 @@ protected void fireRetransmissionTimer() {
                             this.getSipProvider().handleEvent(txTimeout, this);
                         }
                         if (this.timeoutIfStillInCallingState
    -                            && this.getInternalState() == TransactionState._CALLING) {
    +                            && this.getState() == TransactionState.CALLING) {
                             this.callingStateTimeoutCount--;
                             if (callingStateTimeoutCount == 0) {
                                 TimeoutEvent timeoutEvent = new TimeoutEvent(this.getSipProvider(),
    @@ -1116,18 +1083,19 @@ protected void fireRetransmissionTimer() {
          */
         protected void fireTimeoutTimer() {
     
    -        if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG))
    -            logger.logDebug("fireTimeoutTimer " + this);
    +        if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG))
    +            sipStack.getStackLogger().logDebug("fireTimeoutTimer " + this);
     
             SIPDialog dialog = (SIPDialog) this.getDialog();
    -        if (TransactionState._CALLING == this.getInternalState()
    -                || TransactionState._TRYING == this.getInternalState()
    -                || TransactionState._PROCEEDING == this.getInternalState()) {
    +        if (TransactionState.CALLING == this.getState()
    +                || TransactionState.TRYING == this.getState()
    +                || TransactionState.PROCEEDING == this.getState()) {
                 // Timeout occured. If this is asociated with a transaction
                 // creation then kill the dialog.
                 if (dialog != null
                         && (dialog.getState() == null || dialog.getState() == DialogState.EARLY)) {
    -                if (SIPTransactionStack.isDialogCreated(this.getMethod())) {
    +                if (((SIPTransactionStack) getSIPStack()).isDialogCreated(this
    +                        .getOriginalRequest().getMethod())) {
                         // If this is a re-invite we do not delete the dialog even
                         // if the
                         // reinvite times out. Else
    @@ -1137,35 +1105,35 @@ protected void fireTimeoutTimer() {
                 } else if (dialog != null) {
                     // Guard against the case of BYE time out.
     
    -                if (this.getMethod().equalsIgnoreCase(Request.BYE)
    +                if (getOriginalRequest().getMethod().equalsIgnoreCase(Request.BYE)
                             && dialog.isTerminatedOnBye()) {
                         // Terminate the associated dialog on BYE Timeout.
                         dialog.delete();
                     }
                 }
             }
    -        if (TransactionState._COMPLETED != this.getInternalState() && TransactionState._TERMINATED != this.getInternalState()) {
    +        if (TransactionState.COMPLETED != this.getState()) {
                 raiseErrorEvent(SIPTransactionErrorEvent.TIMEOUT_ERROR);
                 // Got a timeout error on a cancel.
    -            if (this.getMethod().equalsIgnoreCase(Request.CANCEL)) {
    +            if (this.getOriginalRequest().getMethod().equalsIgnoreCase(Request.CANCEL)) {
                     SIPClientTransaction inviteTx = (SIPClientTransaction) this.getOriginalRequest()
                             .getInviteTransaction();
                     if (inviteTx != null
    -                        && ((inviteTx.getInternalState() == TransactionState._CALLING || inviteTx
    -                                .getInternalState() == TransactionState._PROCEEDING))
    +                        && ((inviteTx.getState() == TransactionState.CALLING || inviteTx
    +                                .getState() == TransactionState.PROCEEDING))
                             && inviteTx.getDialog() != null) {
                         /*
                          * A proxy server should have started TIMER C and take care of the Termination
                          * using transaction.terminate() by itself (i.e. this is not the job of the
                          * stack at this point but we do it to be nice.
                          */
    -                    inviteTx.setState(TransactionState._TERMINATED);
    +                    inviteTx.setState(TransactionState.TERMINATED);
     
                     }
                 }
     
             } else {
    -            this.setState(TransactionState._TERMINATED);
    +            this.setState(TransactionState.TERMINATED);
             }
     
         }
    @@ -1205,8 +1173,8 @@ public Request createAck() throws SipException {
             } else if (lastResponse == null) {
                 throw new SipException("bad Transaction state");
             } else if (lastResponse.getStatusCode() < 200) {
    -            if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    -                logger.logDebug("lastResponse = " + lastResponse);
    +            if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    +                sipStack.getStackLogger().logDebug("lastResponse = " + lastResponse);
                 }
                 throw new SipException("Cannot ACK a provisional response!");
             }
    @@ -1288,13 +1256,13 @@ private final Request createErrorAck() throws SipException, ParseException {
             SIPRequest originalRequest = this.getOriginalRequest();
             if (originalRequest == null)
                 throw new SipException("bad state " + getState());
    -        if (!isInviteTransaction()) {
    +        if (!getMethod().equals(Request.INVITE)) {
                 throw new SipException("Can only ACK an INVITE!");
             } else if (lastResponse == null) {
                 throw new SipException("bad Transaction state");
             } else if (lastResponse.getStatusCode() < 200) {
    -            if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    -                logger.logDebug("lastResponse = " + lastResponse);
    +            if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    +                sipStack.getStackLogger().logDebug("lastResponse = " + lastResponse);
                 }
                 throw new SipException("Cannot ACK a provisional response!");
             }
    @@ -1304,14 +1272,14 @@ private final Request createErrorAck() throws SipException, ParseException {
         /**
          * Set the port of the recipient.
          */
    -    public void setViaPort(int port) {
    +    protected void setViaPort(int port) {
             this.viaPort = port;
         }
     
         /**
          * Set the port of the recipient.
          */
    -    public void setViaHost(String host) {
    +    protected void setViaHost(String host) {
             this.viaHost = host;
         }
     
    @@ -1356,18 +1324,18 @@ public void clearState() {
          * connection for outgoing requests in this time period) and calls the superclass to set
          * state.
          */
    -    public void setState(int newState) {
    +    public void setState(TransactionState newState) {
             // Set this timer for connection caching
             // of incoming connections.
    -        if (newState == TransactionState._TERMINATED && this.isReliable()
    +        if (newState == TransactionState.TERMINATED && this.isReliable()
                     && (!getSIPStack().cacheClientConnections)) {
                 // Set a time after which the connection
                 // is closed.
                 this.collectionTime = TIMER_J;
     
             }
    -        if (super.getInternalState() != TransactionState._COMPLETED
    -                && (newState == TransactionState._COMPLETED || newState == TransactionState._TERMINATED)) {
    +        if (super.getState() != TransactionState.COMPLETED
    +                && (newState == TransactionState.COMPLETED || newState == TransactionState.TERMINATED)) {
                 sipStack.decrementActiveClientTransactionCount();
             }
             super.setState(newState);
    @@ -1377,14 +1345,10 @@ public void setState(int newState) {
          * Start the timer task.
          */
         protected  void startTransactionTimer() {
    -        if (this.transactionTimerStarted.compareAndSet(false, true)) {        	
    +        if (this.transactionTimerStarted.compareAndSet(false, true)) {
    +	        TimerTask myTimer = new TransactionTimer();
     	        if ( sipStack.getTimer() != null ) {
    -	        	synchronized (transactionTimerLock) {
    -	        		if(!transactionTimerCancelled) {
    -	        			transactionTimer = new TransactionTimer();
    -	        			sipStack.getTimer().scheduleWithFixedDelay(transactionTimer, BASE_TIMER_INTERVAL, BASE_TIMER_INTERVAL);
    -	        		}
    -				}	        	
    +	            sipStack.getTimer().schedule(myTimer, BASE_TIMER_INTERVAL, BASE_TIMER_INTERVAL);
     	        }
             }
         }
    @@ -1396,22 +1360,13 @@ protected  void startTransactionTimer() {
          * @see javax.sip.Transaction#terminate()
          */
         public void terminate() throws ObjectInUseException {
    -        this.setState(TransactionState._TERMINATED);
    +        this.setState(TransactionState.TERMINATED);
             if(!transactionTimerStarted.get()) {
         		// if no transaction timer was started just remove the tx without firing a transaction terminated event
             	testAndSetTransactionTerminatedEvent();
             	sipStack.removeTransaction(this);
             }
    -    }
    -    
    -    /**
    -     * Stop the ExPIRES timer if it is running.
    -     */
    -    public void stopExpiresTimer() {
    -        if ( this.expiresTimerTask != null ) {
    -            sipStack.getTimer().cancel(this.expiresTimerTask);
    -            this.expiresTimerTask = null;
    -        }
    +
         }
     
         /**
    @@ -1423,17 +1378,17 @@ public void stopExpiresTimer() {
          * @return true if the check passes.
          */
         public boolean checkFromTag(SIPResponse sipResponse) {
    -        String originalFromTag = getOriginalRequestFromTag();
    +        String originalFromTag = ((SIPRequest) this.getRequest()).getFromTag();
             if (this.defaultDialog != null) {
                 if (originalFromTag == null ^ sipResponse.getFrom().getTag() == null) {
    -            	if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG))
    -            		logger.logDebug("From tag mismatch -- dropping response");
    +            	if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG))
    +            		sipStack.getStackLogger().logDebug("From tag mismatch -- dropping response");
                     return false;
                 }
                 if (originalFromTag != null
                         && !originalFromTag.equalsIgnoreCase(sipResponse.getFrom().getTag())) {
    -            	if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG))
    -            		logger.logDebug("From tag mismatch -- dropping response");
    +            	if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG))
    +            		sipStack.getStackLogger().logDebug("From tag mismatch -- dropping response");
                     return false;
                 }
             }
    @@ -1448,21 +1403,7 @@ public boolean checkFromTag(SIPResponse sipResponse) {
          *      gov.nist.javax.sip.stack.MessageChannel)
          */
         public void processResponse(SIPResponse sipResponse, MessageChannel incomingChannel) {
    -                
    -        int code = sipResponse.getStatusCode();
    -		boolean isRetransmission = !responsesReceived.add(Integer.valueOf(code));
    -        if(code == 183 && isRetransmission) {
    -        	if(lastResponse != null && !sipResponse.toString().equals(lastResponse.toString())) {
    -        		isRetransmission = false;
    -        	}
    -        }
    -        
    -        if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    -            logger.logDebug(
    -                    "marking response as retransmission " + isRetransmission + " for ctx " + this);
    -        }
    -        sipResponse.setRetransmission(isRetransmission);
    -                
    +
             // If a dialog has already been created for this response,
             // pass it up.
             SIPDialog dialog = null;
    @@ -1481,10 +1422,11 @@ public void processResponse(SIPResponse sipResponse, MessageChannel incomingChan
     
             // JvB: Check all conditions required for creating a new Dialog
             if (dialog == null) {
    +            int code = sipResponse.getStatusCode();
                 if ((code > 100 && code < 300)
                 /* skip 100 (may have a to tag */
                 && (sipResponse.getToTag() != null || sipStack.isRfc2543Supported())
    -                    && SIPTransactionStack.isDialogCreated(method)) {
    +                    && sipStack.isDialogCreated(method)) {
     
                     /*
                      * Dialog cannot be found for the response. This must be a forked response. no
    @@ -1500,10 +1442,11 @@ public void processResponse(SIPResponse sipResponse, MessageChannel incomingChan
                          */
                         if (defaultDialog != null) {
                             if (sipResponse.getFromTag() != null) {
    +                            SIPResponse dialogResponse = defaultDialog.getLastResponse();
                                 String defaultDialogId = defaultDialog.getDialogId();
    -                            if (defaultDialog.getLastResponseMethod() == null
    +                            if (dialogResponse == null
                                         || (method.equals(Request.SUBSCRIBE)
    -                                            && defaultDialog.getLastResponseMethod().equals(
    +                                            && dialogResponse.getCSeq().getMethod().equals(
                                                         Request.NOTIFY) && defaultDialogId
                                                 .equals(dialogId))) {
                                     // The default dialog has not been claimed yet.
    @@ -1532,7 +1475,7 @@ public void processResponse(SIPResponse sipResponse, MessageChannel incomingChan
                                 if ( dialog != null ) {
                                     this.setDialog(dialog, dialog.getDialogId());
                                 } else {
    -                                logger.logError("dialog is unexpectedly null",new NullPointerException());
    +                                sipStack.getStackLogger().logError("dialog is unexpectedly null",new NullPointerException());
                                 }
                             } else {
                                 throw new RuntimeException("Response without from-tag");
    @@ -1550,12 +1493,7 @@ public void processResponse(SIPResponse sipResponse, MessageChannel incomingChan
                     dialog = defaultDialog;
                 }
             } else {
    -            // Test added to make sure the retrans flag is correct on forked responses
    -            // this will avoid setting the last response on the dialog and chnage its state
    -            // before it is passed to the dialogfilter layer where it is done as well
    -            if(TransactionState._TERMINATED != getInternalState()) {
    -                dialog.setLastResponse(this, sipResponse);
    -            }
    +            dialog.setLastResponse(this, sipResponse);
             }
             this.processResponse(sipResponse, incomingChannel, dialog);
         }
    @@ -1568,23 +1506,20 @@ public void processResponse(SIPResponse sipResponse, MessageChannel incomingChan
         public  Dialog getDialog() {
             // This is for backwards compatibility.
             Dialog retval = null;
    -        // get it in a local variable because the last response can be nullified and the if condition
    -        // can throw NPE
    -        SIPResponse localLastResponse = this.lastResponse;
    -        if(localLastResponse != null && localLastResponse.getFromTag() != null
    -                && localLastResponse.getToTag() != null
    -                && localLastResponse.getStatusCode() != 100) {
    -            String dialogId = localLastResponse.getDialogId(false);
    +        if (this.lastResponse != null && this.lastResponse.getFromTag() != null
    +                && this.lastResponse.getToTag() != null
    +                && this.lastResponse.getStatusCode() != 100) {
    +            String dialogId = this.lastResponse.getDialogId(false);
                 retval = (Dialog) getDialog(dialogId);
             }
     
             if (retval == null) {
    -            retval = (Dialog) this.getDefaultDialog();
    +            retval = (Dialog) this.defaultDialog;
     
             }
    -        if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    -            logger.logDebug(
    -                    " sipDialogs =  " + sipDialogs + " default dialog " + this.getDefaultDialog()
    +        if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    +            sipStack.getStackLogger().logDebug(
    +                    " sipDialogs =  " + sipDialogs + " default dialog " + this.defaultDialog
                                 + " retval " + retval);
             }
             return retval;
    @@ -1598,13 +1533,7 @@ public  Dialog getDialog() {
          *      gov.nist.javax.sip.message.SIPMessage)
          */
         public SIPDialog getDialog(String dialogId) {
    -    	SIPDialog retval = null;
    -    	if(sipDialogs != null && sipDialogs.contains(dialogId)) {
    -    		retval = this.sipStack.getDialog(dialogId);
    -    		if(retval == null) {
    -    			retval = this.sipStack.getEarlyDialog(dialogId);
    -    		}
    -    	}
    +        SIPDialog retval = (SIPDialog) this.sipDialogs.get(dialogId);
             return retval;
     
         }
    @@ -1616,35 +1545,30 @@ public SIPDialog getDialog(String dialogId) {
          *      gov.nist.javax.sip.message.SIPMessage)
          */
         public void setDialog(SIPDialog sipDialog, String dialogId) {
    -        if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG))
    -            logger.logDebug(
    -                    "setDialog: " + dialogId + " sipDialog = " + sipDialog);
    +        if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG))
    +            sipStack.getStackLogger().logDebug(
    +                    "setDialog: " + dialogId + "sipDialog = " + sipDialog);
     
             if (sipDialog == null) {
    -        	if (logger.isLoggingEnabled(LogWriter.TRACE_ERROR))
    -        		logger.logError("NULL DIALOG!!");
    +        	if (sipStack.isLoggingEnabled())
    +        		sipStack.getStackLogger().logError("NULL DIALOG!!");
                 throw new NullPointerException("bad dialog null");
             }
    -        if (this.defaultDialog == null && defaultDialogId == null) {
    +        if (this.defaultDialog == null) {
                 this.defaultDialog = sipDialog;
    -            // We only deal with Forked INVITEs.
    -            if (isInviteTransaction() && this.getSIPStack().getMaxForkTime() != 0) {
    +            if ( this.getMethod().equals(Request.INVITE) && this.getSIPStack().getMaxForkTime() != 0) {
                     this.getSIPStack().addForkedClientTransaction(this);
                 }
             }
    -        if (dialogId != null && sipDialog.getDialogId() != null && sipDialogs != null) {
    -            this.sipDialogs.add(dialogId);
    +        if (dialogId != null && sipDialog.getDialogId() != null) {
    +            this.sipDialogs.put(dialogId, sipDialog);
    +
             }
     
         }
     
         public SIPDialog getDefaultDialog() {
    -    	SIPDialog dialog = defaultDialog;
    -    	// jeand if the dialog has been nullified then get the dialog from the saved dialog id
    -    	if(dialog == null && defaultDialogId != null) {
    -    		dialog = this.sipStack.getDialog(defaultDialogId);    		
    -    	}
    -    	return dialog;
    +        return this.defaultDialog;
         }
     
         /**
    @@ -1688,201 +1612,14 @@ public void alertIfStillInCallingStateBy(int count) {
             this.callingStateTimeoutCount = count;
         }
     
    -    // jeand method use to cleanup eagerly all structures that won't be needed anymore once the tx passed in the COMPLETED state
    -    protected void cleanUpOnTimer() {
    -    	if(isReleaseReferences()) {
    -	    	if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    -	            logger.logDebug("cleanupOnTimer: "
    -	                    + getTransactionId());
    -	        }       
    -	    	// we release the ref to the dialog asap and just keep the id of the dialog to look it up in the dialog table
    -	    	if(defaultDialog != null) {
    -		    	String dialogId = defaultDialog.getDialogId();
    -		    	// we nullify the ref only if it can be find in the dialog table (not always true if the dialog is in null state, check challenge unittest of the testsuite)
    -		    	if(dialogId != null && sipStack.getDialog(dialogId) != null) {
    -		    		defaultDialogId = dialogId;
    -		    		defaultDialog = null;	    		
    -		    	}
    -	    	}
    -	    	if(originalRequest != null) {
    -		    	originalRequest.setTransaction(null);
    -		    	originalRequest.setInviteTransaction(null);
    -		    	originalRequest.cleanUp();
    -		    	// we keep the request in a byte array to be able to recreate it
    -		    	// no matter what to keep API backward compatibility
    -		    	if(originalRequestBytes == null) {
    -		    	    originalRequestBytes = originalRequest.encodeAsBytes(this.getTransport());   
    -		    	}		    	
    -		    	if(!getMethod().equalsIgnoreCase(Request.INVITE) && !getMethod().equalsIgnoreCase(Request.CANCEL)) {	    			
    -	    			originalRequestFromTag = originalRequest.getFromTag();
    -	    			originalRequestCallId = originalRequest.getCallId().getCallId();
    -	    			originalRequestEventHeader = (Event) originalRequest.getHeader("Event");
    -	    			originalRequestContact = originalRequest.getContactHeader();
    -	    			originalRequestScheme = originalRequest.getRequestURI().getScheme();
    -	    			originalRequest = null;    			
    -	    		}  
    -	    	}
    -	    	// for subscribe Tx we need to keep the last response longer to be able to create notify from dialog
    -	    	if(!getMethod().equalsIgnoreCase(Request.SUBSCRIBE)) {
    -	    		lastResponse = null;
    -	    	}    	 
    -	    	lastRequest = null;
    -    	}
    -	}
    -    
    -    //jeand : cleanup method to clear the state of the tx once it has been removed from the stack
    -    @Override    
    -    public void cleanUp() {
    -    	if(isReleaseReferences()) {
    -	    	// release the connection associated with this transaction.
    -	        if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    -	            logger.logDebug("cleanup : "
    -	                    + getTransactionId());
    -	        }        
    -	    	if(defaultDialog != null) {
    -	    		defaultDialogId = defaultDialog.getDialogId();
    -	    		defaultDialog = null;
    -	    	}
    -	    	// we keep the request in a byte array to be able to recreate it
    -            // no matter what to keep API backward compatibility
    -	    	if(originalRequest != null && originalRequestBytes == null) {
    -	    	    originalRequestBytes = originalRequest.encodeAsBytes(this.getTransport());
    -	    	}
    -		    originalRequest = null;		    
    -	    	cleanUpOnTimer();
    -	    	// commented out because the application can hold on a ref to the tx
    -	    	// after it has been removed from the stack
    -	    	// and want to get the request or branch from it
    -//			originalRequestBytes = null;
    -//		    originalRequestBranch = null;
    -		    originalRequestCallId = null;
    -		    originalRequestEventHeader = null;
    -		    originalRequestFromTag = null;
    -		    originalRequestContact = null;
    -		    originalRequestScheme = null;
    -	    	if(sipDialogs != null) {
    -		    	sipDialogs.clear();	    	
    -	    	}
    -	    	responsesReceived.clear();
    -	    	respondTo = null;
    -	    	transactionTimer = null;
    -	    	lastResponse = null;
    -	    	transactionTimerLock = null; 
    -//	    	transactionTimerStarted = null;
    -	    	timerKStarted = null;    	
    -    	}
    +    public void stopExpiresTimer() {
    +        if ( this.expiresTimerTask != null ) {
    +            this.expiresTimerTask.cancel();
    +            this.expiresTimerTask = null;
    +        }
         }
    -    
    -    // jeand cleanup called after the ctx timer or the timer k has fired
    -    protected void cleanUpOnTerminated() {
    -    	if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    -            logger.logDebug(
    -                    "removing  = " + this + " isReliable "
    -                            + isReliable());
    -        }  
    -    	if(isReleaseReferences()) {
    -			
    -			if(originalRequest == null && originalRequestBytes != null) {
    -	        	try {
    -					originalRequest = (SIPRequest) sipStack.getMessageParserFactory().createMessageParser(sipStack).parseSIPMessage(originalRequestBytes, true, false, null);
    -//					originalRequestBytes = null;
    -				} catch (ParseException e) {
    -					logger.logError("message " + originalRequestBytes + " could not be reparsed !");
    -				}
    -			}   
    -    	}
    -	       
    -    	sipStack.removeTransaction(this);           
    -	
    -        // Client transaction terminated. Kill connection if
    -        // this is a TCP after the linger timer has expired.
    -        // The linger timer is needed to allow any pending requests to
    -        // return responses.                
    -        if ((!sipStack.cacheClientConnections) && isReliable()) {
    -
    -            int newUseCount = --getMessageChannel().useCount;
    -            if (newUseCount <= 0) {
    -                // Let the connection linger for a while and then close
    -                // it.
    -            	SIPStackTimerTask myTimer = new LingerTimer();
    -                sipStack.getTimer().schedule(myTimer,
    -                        SIPTransactionStack.CONNECTION_LINGER_TIME * 1000);
    -            }
     
    -        } else {
    -            // Cache the client connections so dont close the
    -            // connection. This keeps the connection open permanently
    -            // until the client disconnects.
    -            if (logger.isLoggingEnabled() && isReliable()) {
    -               	int useCount = getMessageChannel().useCount;
    -               	if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG))
    -               		logger.logDebug("Client Use Count = " + useCount);
    -            }                    
    -            // Let the connection linger for a while and then close
    -            // it.
    -            if(((SipStackImpl)getSIPStack()).isReEntrantListener() && isReleaseReferences()) {
    -            	cleanUp();     
    -            } 
    -            // Commented out for Issue 298 : not to break backward compatibility
    -            // this piece of code was not present before aggressive optimizations
    -            // see sipx-stable-420 branch
    -//            else {
    -//            	SIPStackTimerTask myTimer = new LingerTimer();
    -//                sipStack.getTimer().schedule(myTimer,
    -//                        SIPTransactionStack.CONNECTION_LINGER_TIME * 1000);
    -//            }
    -        }
    -    	
    -	}
    -
    -	/**
    -	 * @return the originalRequestFromTag
    -	 */
    -	public String getOriginalRequestFromTag() {
    -		if(originalRequest == null) {
    -			return originalRequestFromTag;
    -		}
    -		return originalRequest.getFromTag();
    -	}
    -	
    -	/**
    -	 * @return the originalRequestFromTag
    -	 */
    -	public String getOriginalRequestCallId() {
    -		if(originalRequest == null) {
    -			return originalRequestCallId;
    -		}
    -		return originalRequest.getCallId().getCallId();
    -	}
    -	
    -	/**
    -	 * @return the originalRequestFromTag
    -	 */
    -	public Event getOriginalRequestEvent() {
    -		if(originalRequest == null) {
    -			return originalRequestEventHeader;
    -		}
    -		return (Event) originalRequest.getHeader(EventHeader.NAME);
    -	}
    -	
    -	/**
    -	 * @return the originalRequestFromTag
    -	 */
    -	public Contact getOriginalRequestContact() {
    -		if(originalRequest == null) {
    -			return originalRequestContact;
    -		}
    -		return originalRequest.getContactHeader();
    -	}
    -	
    -	/**
    -	 * @return the originalRequestFromTag
    -	 */
    -	public String getOriginalRequestScheme() {
    -		if(originalRequest == null) {
    -			return originalRequestScheme;
    -		}
    -		return originalRequest.getRequestURI().getScheme();
    -	}
    +    
    +    
        
     }
    diff --git a/src/gov/nist/javax/sip/stack/SIPDialog.java b/src/gov/nist/javax/sip/stack/SIPDialog.java
    index 9dc0a9a83..d2722427d 100755
    --- a/src/gov/nist/javax/sip/stack/SIPDialog.java
    +++ b/src/gov/nist/javax/sip/stack/SIPDialog.java
    @@ -28,13 +28,11 @@
     /**************************************************************************/
     package gov.nist.javax.sip.stack;
     
    -import gov.nist.core.CommonLogger;
     import gov.nist.core.InternalErrorHandler;
    -import gov.nist.core.LogLevels;
     import gov.nist.core.LogWriter;
     import gov.nist.core.NameValueList;
    -import gov.nist.core.StackLogger;
     import gov.nist.javax.sip.DialogExt;
    +import gov.nist.javax.sip.DialogTimeoutEvent;
     import gov.nist.javax.sip.ListeningPointImpl;
     import gov.nist.javax.sip.SipListenerExt;
     import gov.nist.javax.sip.SipProviderImpl;
    @@ -54,6 +52,7 @@
     import gov.nist.javax.sip.header.RecordRoute;
     import gov.nist.javax.sip.header.RecordRouteList;
     import gov.nist.javax.sip.header.Require;
    +import gov.nist.javax.sip.header.RetryAfter;
     import gov.nist.javax.sip.header.Route;
     import gov.nist.javax.sip.header.RouteList;
     import gov.nist.javax.sip.header.SIPHeader;
    @@ -64,10 +63,6 @@
     import gov.nist.javax.sip.message.SIPMessage;
     import gov.nist.javax.sip.message.SIPRequest;
     import gov.nist.javax.sip.message.SIPResponse;
    -import gov.nist.javax.sip.parser.AddressParser;
    -import gov.nist.javax.sip.parser.CallIDParser;
    -import gov.nist.javax.sip.parser.ContactParser;
    -import gov.nist.javax.sip.parser.RecordRouteParser;
     
     import java.io.IOException;
     import java.io.PrintWriter;
    @@ -76,14 +71,14 @@
     import java.net.InetAddress;
     import java.text.ParseException;
     import java.util.ArrayList;
    -import java.util.HashSet;
     import java.util.Iterator;
     import java.util.LinkedList;
     import java.util.List;
     import java.util.ListIterator;
    -import java.util.Random;
     import java.util.Set;
     import java.util.concurrent.CopyOnWriteArraySet;
    +import java.util.concurrent.ExecutorService;
    +import java.util.concurrent.Executors;
     import java.util.concurrent.Semaphore;
     import java.util.concurrent.TimeUnit;
     
    @@ -105,12 +100,12 @@
     import javax.sip.header.ContactHeader;
     import javax.sip.header.EventHeader;
     import javax.sip.header.OptionTag;
    -import javax.sip.header.ProxyAuthorizationHeader;
     import javax.sip.header.RAckHeader;
     import javax.sip.header.RSeqHeader;
     import javax.sip.header.ReasonHeader;
     import javax.sip.header.RequireHeader;
     import javax.sip.header.RouteHeader;
    +import javax.sip.header.ServerHeader;
     import javax.sip.header.SupportedHeader;
     import javax.sip.header.TimeStampHeader;
     import javax.sip.message.Request;
    @@ -123,19 +118,17 @@
      * Martin Le Clerk, Christophe Anzille, Andreas Bystrom, Lebing Xie, Jeroen van Bemmel. Hagai Sela
      * reported a bug in updating the route set (on RE-INVITE). Jens Tinfors submitted a bug fix and
      * the .equals method. Jan Schaumloeffel contributed a buf fix ( memory leak was happening when
    - * 180 contained a To tag. Bug fixes by Vladimir Ralev (Redhat).
    - * Performance enhancements and memory reduction enhancements by Jean Deruelle.
    + * 180 contained a To tag.
      * 
      */
     
     /**
    - * Tracks dialogs. A dialog is a peer to peer association of communicating SIP
    - * entities. For INVITE transactions, a Dialog is created when a success message
    - * is received (i.e. a response that has a To tag). The SIP Protocol stores
    - * enough state in the message structure to extract a dialog identifier that can
    - * be used to retrieve this structure from the SipStack.
    + * Tracks dialogs. A dialog is a peer to peer association of communicating SIP entities. For
    + * INVITE transactions, a Dialog is created when a success message is received (i.e. a response
    + * that has a To tag). The SIP Protocol stores enough state in the message structure to extract a
    + * dialog identifier that can be used to retrieve this structure from the SipStack.
      * 
    - * @version 1.2 $Revision: 1.207 $ $Date: 2010-12-02 22:04:14 $
    + * @version 1.2 $Revision: 1.172.2.4 $ $Date: 2010-11-23 19:23:12 $
      * 
      * @author M. Ranganathan
      * 
    @@ -143,48 +136,33 @@
      */
     
     public class SIPDialog implements javax.sip.Dialog, DialogExt {
    -	private static StackLogger logger = CommonLogger.getLogger(SIPDialog.class);
     
         private static final long serialVersionUID = -1429794423085204069L;
     
    -    private transient boolean dialogTerminatedEventDelivered; // prevent
    -    // duplicate
    -
    +    private transient boolean dialogTerminatedEventDelivered; // prevent duplicate
    +    
         private transient String stackTrace; // for semaphore debugging.
     
         protected String method;
     
         // delivery of the event
    -    protected transient boolean isAssigned;
    +    private transient boolean isAssigned;
     
    -    protected boolean reInviteFlag;
    +    private boolean reInviteFlag;
     
    -    private transient Object applicationData; // Opaque pointer to application
    -    // data.
    +    private transient Object applicationData; // Opaque pointer to application data.
     
         private transient SIPRequest originalRequest;
    -    // jeand : avoid keeping the original request ref above for too long (mem
    -    // saving)
    -    protected transient String originalRequestRecordRouteHeadersString;
    -    protected transient RecordRouteList originalRequestRecordRouteHeaders;
     
         // Last response (JvB: either sent or received).
    -    // jeand replaced the last response with only the data from it needed to
    -    // save on mem
    -    protected String lastResponseDialogId;
    -    private Via lastResponseTopMostVia;
    -    protected Integer lastResponseStatusCode;
    -    protected long lastResponseCSeqNumber;
    -    protected String lastResponseMethod;
    -    protected String lastResponseFromTag;
    -    protected String lastResponseToTag;
    -
    -    // jeand: needed for reliable response sending but nullifyed right after the
    -    // ACK has been received or sent to let go of the ref ASAP
    -    protected SIPTransaction firstTransaction;
    -    // jeand needed for checking 491 but nullifyed right after the ACK has been
    -    // received or sent to let go of the ref ASAP
    -    protected SIPTransaction lastTransaction;
    +    protected SIPResponse lastResponse;
    +
    +    // Should be transient, in case the dialog is serialized it will be null
    +    // so when a subsequent request will be sent it will be set and a new message channel can be
    +    // created
    +    protected transient SIPTransaction firstTransaction;
    +
    +    protected transient SIPTransaction lastTransaction;
     
         protected String dialogId;
     
    @@ -203,20 +181,17 @@ public class SIPDialog implements javax.sip.Dialog, DialogExt {
         private transient SIPTransactionStack sipStack;
     
         private int dialogState;
    -
    +    
         protected transient SIPRequest lastAckSent;
     
    -    // jeand : replaced the lastAckReceived message with only the data needed to
    -    // save on mem
    -    protected Long lastAckReceivedCSeqNumber;
    +    protected SIPRequest lastAckReceived;
     
    -    // could be set on recovery by examining the method looks like a duplicate
    -    // of ackSeen
    +    // could be set on recovery by examining the method looks like a duplicate of ackSeen
         protected transient boolean ackProcessed;
     
         protected transient DialogTimerTask timerTask;
     
    -    protected transient long nextSeqno;
    +    protected transient Long nextSeqno;
     
         private transient int retransmissionTicksLeft;
     
    @@ -234,13 +209,10 @@ public class SIPDialog implements javax.sip.Dialog, DialogExt {
         // Dialog.
     
         protected javax.sip.address.Address localParty;
    -    protected String localPartyStringified;
     
         protected javax.sip.address.Address remoteParty;
    -    protected String remotePartyStringified;
     
         protected CallIdHeader callIdHeader;
    -    protected String callIdHeaderString;
     
         public final static int NULL_STATE = -1;
     
    @@ -260,13 +232,11 @@ public class SIPDialog implements javax.sip.Dialog, DialogExt {
     
         protected boolean terminateOnBye;
     
    -    protected transient boolean byeSent; // Flag set when BYE is sent, to
    -    // disallow new
    +    protected transient boolean byeSent; // Flag set when BYE is sent, to disallow new
     
         // requests
     
         protected Address remoteTarget;
    -    protected String remoteTargetStringified;
     
         protected EventHeader eventHeader; // for Subscribe notify
     
    @@ -276,97 +246,52 @@ public class SIPDialog implements javax.sip.Dialog, DialogExt {
     
         private transient Semaphore ackSem = new Semaphore(1);
     
    -    protected transient int reInviteWaitTime = 100;
    +    private transient int reInviteWaitTime = 100;
     
         private transient DialogDeleteTask dialogDeleteTask;
     
    -    private transient DialogDeleteIfNoAckSentTask dialogDeleteIfNoAckSentTask;
    -
    -    protected transient boolean isAcknowledged;
    -
    +	private transient DialogDeleteIfNoAckSentTask dialogDeleteIfNoAckSentTask;
    +    
    +    private transient boolean isAcknowledged;
    +    
         private transient long highestSequenceNumberAcknowledged = -1;
    -
    +    
         protected boolean isBackToBackUserAgent;
     
         protected boolean sequenceNumberValidation = true;
     
         // List of event listeners for this dialog
    -    private transient Set eventListeners;
    -    // added for Issue 248 :
    -    // https://jain-sip.dev.java.net/issues/show_bug.cgi?id=248
    -    private Semaphore timerTaskLock = new Semaphore(1);
    -
    -    // We store here the useful data from the first transaction without having
    -    // to
    -    // keep the whole transaction object for the duration of the dialog. It also
    -    // contains the non-transient information used in the replication of
    -    // dialogs.
    -    protected boolean firstTransactionSecure;
    -    protected boolean firstTransactionSeen;
    +	private transient Set eventListeners;
    +	// added for Issue 248 : https://jain-sip.dev.java.net/issues/show_bug.cgi?id=248
    +	private Semaphore timerTaskLock = new Semaphore(1);
    +	
    +	// We store here the useful data from the first transaction without having to
    +	// keep the whole transaction object for the duration of the dialog. It also
    +	// contains the non-transient information used in the replication of dialogs.
    +	protected boolean firstTransactionSecure;
    +	protected boolean firstTransactionSeen;
         protected String firstTransactionMethod;
         protected String firstTransactionId;
         protected boolean firstTransactionIsServerTransaction;
         protected String firstTransactionMergeId;
    -    protected int firstTransactionPort = 5060;
    +    protected int firstTransactionPort = 5060;   
         protected Contact contactHeader;
    -    protected String contactHeaderStringified;
    -
    -    private boolean pendingRouteUpdateOn202Response;
     
    -    protected ProxyAuthorizationHeader proxyAuthorizationHeader; // For
    -                                                                 // subequent
    -                                                                 // requests.
    +	private boolean pendingRouteUpdateOn202Response;
     
    -    // aggressive flag to optimize eagerly
    -    private boolean releaseReferences;
    -
    -    private EarlyStateTimerTask earlyStateTimerTask;
    -
    -    private int earlyDialogTimeout = 180;
    -
    -	private int ackSemTakenFor;
    -	private Set responsesReceivedInForkingCase = new HashSet(0);
     
         // //////////////////////////////////////////////////////
         // Inner classes
         // //////////////////////////////////////////////////////
     
    -    class EarlyStateTimerTask extends SIPStackTimerTask implements Serializable {
    -
    -        public EarlyStateTimerTask() {
    -
    -        }
    -
    -        @Override
    -        public void runTask() {
    -            try {
    -                if (SIPDialog.this.getState().equals(DialogState.EARLY)) {
    -                    
    -                    SIPDialog.this
    -                            .raiseErrorEvent(SIPDialogErrorEvent.EARLY_STATE_TIMEOUT);
    -                } else {
    -                    if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    -                        logger.logDebug("EarlyStateTimerTask : Dialog state is " + SIPDialog.this.getState());
    -                    }
    -                }
    -            } catch (Exception ex) {
    -                logger.logError(
    -                        "Unexpected exception delivering event", ex);
    -            }
    -        }
    -
    -    }
    -
         /**
    -     * This task waits till a pending ACK has been recorded and then sends out a
    -     * re-INVITE. This is to prevent interleaving INVITEs ( which will result in
    -     * a 493 from the UA that receives the out of order INVITE). This is
    -     * primarily for B2BUA support. A B2BUA may send a delayed ACK while it does
    -     * mid call codec renegotiation. In the meanwhile, it cannot send an
    -     * intervening re-INVITE otherwise the othr end will respond with a
    -     * REQUEST_PENDING. We want to avoid this condition. Hence we wait till the
    -     * ACK for the previous re-INVITE has been sent before sending the next
    -     * re-INVITE.
    +     * This task waits till a pending ACK has been recorded and then sends out a re-INVITE. This
    +     * is to prevent interleaving INVITEs ( which will result in a 493 from the UA that receives
    +     * the out of order INVITE). This is primarily for B2BUA support. A B2BUA may send a delayed
    +     * ACK while it does mid call codec renegotiation. In the meanwhile, it cannot send an intervening
    +     * re-INVITE otherwise the othr end will respond with a REQUEST_PENDING. We want to avoid this
    +     * condition. Hence we wait till the ACK for the previous re-INVITE has been sent before 
    +     * sending the next re-INVITE. 
          */
         public class ReInviteSender implements Runnable, Serializable {
             private static final long serialVersionUID = 1019346148741070635L;
    @@ -374,81 +299,45 @@ public class ReInviteSender implements Runnable, Serializable {
     
             public void terminate() {
                 try {
    -            	if ( logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    -            		logger.logDebug("ReInviteSender::terminate: ctx = " + ctx);
    -            	}
    -            	
                     ctx.terminate();
                     Thread.currentThread().interrupt();
                 } catch (ObjectInUseException e) {
    -                logger.logError("unexpected error", e);
    +                sipStack.getStackLogger().logError("unexpected error", e);
                 }
             }
     
             public ReInviteSender(ClientTransaction ctx) {
                 this.ctx = ctx;
    -            if ( logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    -            	logger.logDebug("ReInviteSender::ReInviteSender: ctx = " + ctx );
    -            	logger.logStackTrace();
    -            }
             }
     
             public void run() {
                 try {
                     long timeToWait = 0;
                     long startTime = System.currentTimeMillis();
    -                boolean dialogTimedOut = false;
    -                boolean busyWait = false;
    -
    -                // If we have an INVITE transaction, make sure that it is TERMINATED
    -                // before sending a re-INVITE.. Not the cleanest solution but it works.
    -                if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    -                	logger.logDebug("SIPDialog::reInviteSender: dialog = " + ctx.getDialog()  + " lastTransaction = " + lastTransaction + " lastTransactionState " + lastTransaction.getState());
    -                }
    -                while (SIPDialog.this.lastTransaction != null &&
    -                			SIPDialog.this.lastTransaction instanceof SIPServerTransaction && 
    -                			SIPDialog.this.lastTransaction.isInviteTransaction() &&
    -                		    SIPDialog.this.lastTransaction.getState() != TransactionState.TERMINATED)
    -                {
    -                	Thread.sleep(50);
    -                	busyWait = true;
    -                }
    -                
    -                // Wait a bit to grab the ack semaphore just in case the OK got sent.
    -                if (busyWait) {
    -                	Thread.sleep(50);
    -                }
     
                     if (!SIPDialog.this.takeAckSem()) {
                         /*
                          * Could not send re-INVITE fire a timeout on the INVITE.
                          */
    -                    if (logger.isLoggingEnabled())
    -                        logger
    -                                .logError(
    -                                        "Could not send re-INVITE time out ClientTransaction");
    +                	if (sipStack.isLoggingEnabled())
    +                		sipStack.getStackLogger().logError(
    +                            "Could not send re-INVITE time out ClientTransaction");
                         ((SIPClientTransaction) ctx).fireTimeoutTimer();
                         /*
    -                     * Send BYE to the Dialog.
    +                     * Send BYE to the Dialog. 
                          */
    -                    if (sipProvider.getSipListener() != null
    -                            && sipProvider.getSipListener() instanceof SipListenerExt) {
    -                        dialogTimedOut = true;
    +                    if ( sipProvider.getSipListener() != null && sipProvider.getSipListener() instanceof SipListenerExt ) {
                             raiseErrorEvent(SIPDialogErrorEvent.DIALOG_REINVITE_TIMEOUT);
                         } else {
    -                        Request byeRequest = SIPDialog.this
    -                                .createRequest(Request.BYE);
    -                        if (MessageFactoryImpl.getDefaultUserAgentHeader() != null) {
    -                            byeRequest.addHeader(MessageFactoryImpl
    -                                    .getDefaultUserAgentHeader());
    +                        Request byeRequest = SIPDialog.this.createRequest(Request.BYE);
    +                        if ( MessageFactoryImpl.getDefaultUserAgentHeader() != null ) {
    +                            byeRequest.addHeader(MessageFactoryImpl.getDefaultUserAgentHeader());
                             }
                             ReasonHeader reasonHeader = new Reason();
                             reasonHeader.setCause(1024);
                             reasonHeader.setText("Timed out waiting to re-INVITE");
                             byeRequest.addHeader(reasonHeader);
    -                        ClientTransaction byeCtx = SIPDialog.this
    -                                .getSipProvider().getNewClientTransaction(
    -                                        byeRequest);
    +                        ClientTransaction byeCtx = SIPDialog.this.getSipProvider().getNewClientTransaction(byeRequest);
                             SIPDialog.this.sendRequest(byeCtx);
                             return;
                         }
    @@ -459,50 +348,46 @@ public void run() {
                     }
     
                     /*
    -                 * If we had to wait for ACK then wait for the ACK to actually
    -                 * get to the other side. Wait for any ACK retransmissions to
    -                 * finish. Then send out the request. This is a hack in support
    -                 * of some UA that want re-INVITEs to be spaced out in time (
    -                 * else they return a 400 error code ).
    +                 * If we had to wait for ACK then wait for the ACK to actually get to the other
    +                 * side. Wait for any ACK retransmissions to finish. Then send out the request.
    +                 * This is a hack in support of some UA that want re-INVITEs to be spaced out in
    +                 * time ( else they return a 400 error code ).
                      */
                     try {
                         if (timeToWait != 0) {
                             Thread.sleep(SIPDialog.this.reInviteWaitTime);
                         }
                     } catch (InterruptedException ex) {
    -                    if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG))
    -                        logger.logDebug("Interrupted sleep");
    +                	if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG))
    +                		sipStack.getStackLogger().logDebug("Interrupted sleep");
                         return;
                     }
    -                if (SIPDialog.this.getState() != DialogState.TERMINATED && !dialogTimedOut && ctx.getState() != TransactionState.TERMINATED ) {
    +                if (SIPDialog.this.getState() != DialogState.TERMINATED) {
                         SIPDialog.this.sendRequest(ctx, true);
    -                    if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) 
    -                        logger.logDebug(
    -                                "re-INVITE successfully sent");
                     }
    -               
    +                if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG))
    +                	sipStack.getStackLogger().logDebug("re-INVITE successfully sent");
                 } catch (Exception ex) {
    -                logger.logError("Error sending re-INVITE",
    -                        ex);
    +                sipStack.getStackLogger().logError("Error sending re-INVITE", ex);
                 } finally {
                     this.ctx = null;
                 }
             }
         }
     
    -    class LingerTimer extends SIPStackTimerTask implements Serializable {
    +	class LingerTimer extends SIPStackTimerTask implements Serializable {
    +
    +        public LingerTimer() {
     
    -        public void runTask() {
    +        }
    +
    +        protected void runTask() {
                 SIPDialog dialog = SIPDialog.this;
    -            sipStack.removeDialog(dialog);
    -            // Issue 279 :
    -            // https://jain-sip.dev.java.net/issues/show_bug.cgi?id=279
    -            // if non reentrant listener is used the event delivery of
    -            // DialogTerminated
    -            // can happen after the clean
    -            if (((SipStackImpl) getStack()).isReEntrantListener()) {
    -                cleanUp();
    +            if(eventListeners != null) {
    +            	eventListeners.clear();
                 }
    +            timerTaskLock = null;
    +            sipStack.removeDialog(dialog);
             }
     
         }
    @@ -511,58 +396,54 @@ class DialogTimerTask extends SIPStackTimerTask implements Serializable {
             int nRetransmissions;
     
             SIPServerTransaction transaction;
    -
    -        // long cseqNumber;
    +        long cseqNumber;
     
             public DialogTimerTask(SIPServerTransaction transaction) {
                 this.transaction = transaction;
                 this.nRetransmissions = 0;
    -         }
    +            this.cseqNumber = transaction.getLastResponse().getCSeq().getSeqNumber();
    +        }
     
    -        public void runTask() {
    +        protected void runTask() {
                 // If I ACK has not been seen on Dialog,
                 // resend last response.
                 SIPDialog dialog = SIPDialog.this;
    -            if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG))
    -                logger.logDebug("Running dialog timer");
    +            if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG))
    +                sipStack.getStackLogger().logDebug("Running dialog timer");
                 nRetransmissions++;
                 SIPServerTransaction transaction = this.transaction;
                 /*
    -             * Issue 106. Section 13.3.1.4 RFC 3261 The 2xx response is passed
    -             * to the transport with an interval that starts at T1 seconds and
    -             * doubles for each retransmission until it reaches T2 seconds If
    -             * the server retransmits the 2xx response for 64T1 seconds without
    -             * receiving an ACK, the dialog is confirmed, but the session SHOULD
    +             * Issue 106. Section 13.3.1.4 RFC 3261 The 2xx response is passed to the transport
    +             * with an interval that starts at T1 seconds and doubles for each retransmission
    +             * until it reaches T2 seconds If the server retransmits the 2xx response for 64*T1
    +             * seconds without receiving an ACK, the dialog is confirmed, but the session SHOULD
                  * be terminated.
                  */
     
    -            if (nRetransmissions > sipStack.getAckTimeoutFactor()
    -                    * SIPTransaction.T1) {
    -                if (SIPDialog.this.getSipProvider().getSipListener() != null
    -                        && SIPDialog.this.getSipProvider().getSipListener() instanceof SipListenerExt) {
    -                    raiseErrorEvent(SIPDialogErrorEvent.DIALOG_ACK_NOT_RECEIVED_TIMEOUT);
    -                } else {
    -                    SIPDialog.this.delete();
    -                }
    +            if (nRetransmissions > sipStack.getAckTimeoutFactor()* SIPTransaction.T1) {
    +            	if (SIPDialog.this.getSipProvider().getSipListener() != null && SIPDialog.this.getSipProvider().getSipListener() instanceof SipListenerExt ) {
    +            		raiseErrorEvent(SIPDialogErrorEvent.DIALOG_ACK_NOT_RECEIVED_TIMEOUT); 
    +            	} else {
    +            		SIPDialog.this.delete();
    +            	}
                     if (transaction != null
                             && transaction.getState() != javax.sip.TransactionState.TERMINATED) {
    -                    transaction
    -                            .raiseErrorEvent(SIPTransactionErrorEvent.TIMEOUT_ERROR);
    +                    transaction.raiseErrorEvent(SIPTransactionErrorEvent.TIMEOUT_ERROR);  
                     }
    -            } else if ((transaction != null) && (!dialog.isAckSeen())) {
    -                // Retransmit to 2xx until ack receivedialog.
    -                if (lastResponseStatusCode.intValue() / 100 == 2) {
    +            } else if ( (transaction != null)&& (!dialog.isAckSeen()) ) {
    +                // Retransmit to 200 until ack receivedialog.
    +                SIPResponse response = transaction.getLastResponse();
    +                if (response.getStatusCode() == 200) {
                         try {
     
                             // resend the last response.
    -                        if (dialog.toRetransmitFinalResponse(transaction.T2)) {
    -                            transaction.resendLastResponseAsBytes();
    -                        }
    +                        if (dialog.toRetransmitFinalResponse(transaction.T2))
    +                            transaction.sendMessage(response);
    +
                         } catch (IOException ex) {
     
    -                        raiseIOException(transaction.getPeerAddress(),
    -                                transaction.getPeerPort(), transaction
    -                                        .getPeerProtocol());
    +                        raiseIOException(transaction.getPeerAddress(), transaction.getPeerPort(),
    +                                transaction.getPeerProtocol());
     
                         } finally {
                             // Need to fire the timer so
    @@ -572,9 +453,8 @@ public void runTask() {
                             // Note that this firing also
                             // drives Listener timeout.
                             SIPTransactionStack stack = dialog.sipStack;
    -                        if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    -                            logger.logDebug(
    -                                    "resend 200 response from " + dialog);
    +                        if (stack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    +                            stack.getStackLogger().logDebug("resend 200 response from " + dialog);
                             }
                             transaction.fireTimer();
                         }
    @@ -585,20 +465,12 @@ public void runTask() {
                 // confirmed state or ack seen if retransmit filter on.
                 if (dialog.isAckSeen() || dialog.dialogState == TERMINATED_STATE) {
                     this.transaction = null;
    -                getStack().getTimer().cancel(this);
    +                this.cancel();
     
                 }
     
             }
     
    -        @Override
    -        public void cleanUpBeforeCancel() {
    -            transaction = null;
    -           // lastAckSent = null;
    -            cleanUpOnAck();
    -            super.cleanUpBeforeCancel();
    -        }
    -
         }
     
         /**
    @@ -608,70 +480,62 @@ public void cleanUpBeforeCancel() {
     
         class DialogDeleteTask extends SIPStackTimerTask implements Serializable {
     
    -        public void runTask() {
    +        protected void runTask() {
                 delete();
             }
     
         }
    -
    +    
         /**
          * This timer task is used to garbage collect the dialog after some time.
          * 
          */
     
    -    class DialogDeleteIfNoAckSentTask extends SIPStackTimerTask implements
    -            Serializable {
    +    class DialogDeleteIfNoAckSentTask extends SIPStackTimerTask implements Serializable {
             private long seqno;
    -
    +   
             public DialogDeleteIfNoAckSentTask(long seqno) {
                 this.seqno = seqno;
             }
     
    -        public void runTask() {
    -            if (SIPDialog.this.highestSequenceNumberAcknowledged < seqno) {
    +        protected void runTask() {
    +            if (SIPDialog.this.highestSequenceNumberAcknowledged < seqno) {  
                     /*
    -                 * Did not send ACK so we need to delete the dialog. B2BUA NOTE:
    -                 * we may want to send BYE to the Dialog at this point. Do we
    -                 * want to make this behavior tailorable?
    +                 * Did not send ACK so we need to delete the dialog.
    +                 * B2BUA NOTE: we may want to send BYE to the Dialog at this 
    +                 * point. Do we want to make this behavior tailorable?
                      */
    -                dialogDeleteIfNoAckSentTask = null;
    -                if (!SIPDialog.this.isBackToBackUserAgent) {
    -                    if (logger.isLoggingEnabled())
    -                        logger.logError(
    -                                "ACK Was not sent. killing dialog " + dialogId);
    -                    if (((SipProviderImpl) sipProvider).getSipListener() instanceof SipListenerExt) {
    -                        raiseErrorEvent(SIPDialogErrorEvent.DIALOG_ACK_NOT_SENT_TIMEOUT);
    -                    } else {
    -                        delete();
    -                    }
    +            	dialogDeleteIfNoAckSentTask = null;
    +                if ( !SIPDialog.this.isBackToBackUserAgent) {
    +                	if (sipStack.isLoggingEnabled())
    +                		sipStack.getStackLogger().logError("ACK Was not sent. killing dialog " + dialogId);
    +                	if ( ((SipProviderImpl)sipProvider).getSipListener() instanceof SipListenerExt ){
    +                	    raiseErrorEvent(SIPDialogErrorEvent.DIALOG_ACK_NOT_SENT_TIMEOUT);
    +                	} else {
    +                	    delete();
    +                	}
                     } else {
    -                    if (logger.isLoggingEnabled())
    -                        logger.logError(
    -                                "ACK Was not sent. Sending BYE " + dialogId);
    -                    if (((SipProviderImpl) sipProvider).getSipListener() instanceof SipListenerExt) {
    -                        raiseErrorEvent(SIPDialogErrorEvent.DIALOG_ACK_NOT_SENT_TIMEOUT);
    -                    } else {
    +                	if (sipStack.isLoggingEnabled()) 
    +                		sipStack.getStackLogger().logError("ACK Was not sent. Sending BYE for dialog " + dialogId);
    +                	   if ( ((SipProviderImpl)sipProvider).getSipListener() instanceof SipListenerExt ){    
    +                	       raiseErrorEvent(SIPDialogErrorEvent.DIALOG_ACK_NOT_SENT_TIMEOUT);
    +                	   } else {
     
                             /*
    -                         * Send BYE to the Dialog. This will be removed for the
    -                         * next spec revision.
    +                         * Send BYE to the Dialog. 
    +                         * This will be removed for the next spec revision.
                              */
                             try {
    -                            Request byeRequest = SIPDialog.this
    -                                    .createRequest(Request.BYE);
    -                            if (MessageFactoryImpl.getDefaultUserAgentHeader() != null) {
    -                                byeRequest.addHeader(MessageFactoryImpl
    -                                        .getDefaultUserAgentHeader());
    +                            Request byeRequest = SIPDialog.this.createRequest(Request.BYE);
    +                            if ( MessageFactoryImpl.getDefaultUserAgentHeader() != null ) {
    +                                byeRequest.addHeader(MessageFactoryImpl.getDefaultUserAgentHeader());
                                 }
                                 ReasonHeader reasonHeader = new Reason();
                                 reasonHeader.setProtocol("SIP");
                                 reasonHeader.setCause(1025);
    -                            reasonHeader
    -                                    .setText("Timed out waiting to send ACK " + dialogId);
    +                            reasonHeader.setText("Timed out waiting to send ACK for dialog " + dialogId);
                                 byeRequest.addHeader(reasonHeader);
    -                            ClientTransaction byeCtx = SIPDialog.this
    -                                    .getSipProvider().getNewClientTransaction(
    -                                            byeRequest);
    +                            ClientTransaction byeCtx = SIPDialog.this.getSipProvider().getNewClientTransaction(byeRequest);
                                 SIPDialog.this.sendRequest(byeCtx);
                                 return;
                             } catch (Exception ex) {
    @@ -698,28 +562,23 @@ private SIPDialog(SipProviderImpl provider) {
             remoteSequenceNumber = -1;
             this.sipProvider = provider;
             eventListeners = new CopyOnWriteArraySet();
    -        this.earlyDialogTimeout = ((SIPTransactionStack) provider.getSipStack())
    -                .getEarlyDialogTimeout();
         }
    -
    +    
         private void recordStackTrace() {
    -        StringWriter stringWriter = new StringWriter();
    -        PrintWriter writer = new PrintWriter(stringWriter);
    -        new Exception().printStackTrace(writer);
    -        String stackTraceSignature = Integer.toString(Math.abs(new Random().nextInt()));
    -        logger.logDebug("TraceRecord = " + stackTraceSignature);
    -        this.stackTrace = "TraceRecord = " + stackTraceSignature + ":" +  stringWriter.getBuffer().toString();
    +      StringWriter stringWriter = new StringWriter();
    +      PrintWriter writer = new PrintWriter(stringWriter);
    +      new Exception().printStackTrace(writer);
    +       this.stackTrace = stringWriter.getBuffer().toString();
         }
     
         /**
          * Constructor given the first transaction.
          * 
    -     * @param transaction
    -     *            is the first transaction.
    +     * @param transaction is the first transaction.
          */
         public SIPDialog(SIPTransaction transaction) {
             this(transaction.getSipProvider());
    -
    +       
             SIPRequest sipRequest = (SIPRequest) transaction.getRequest();
             this.callIdHeader = sipRequest.getCallId();
             this.earlyDialogId = sipRequest.getDialogId(false);
    @@ -734,26 +593,22 @@ public SIPDialog(SIPTransaction transaction) {
             if (sipProvider == null)
                 throw new NullPointerException("Null Provider!");
             this.isBackToBackUserAgent = sipStack.isBackToBackUserAgent;
    -
    +        
             this.addTransaction(transaction);
    -        if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    -            logger.logDebug("Creating a dialog : " + this);
    -            logger.logDebug(
    -                    "provider port = "
    -                            + this.sipProvider.getListeningPoint().getPort());
    -            logger.logStackTrace();
    +        if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    +            sipStack.getStackLogger().logDebug("Creating a dialog : " + this);
    +            sipStack.getStackLogger().logDebug(
    +                    "provider port = " + this.sipProvider.getListeningPoint().getPort());
    +            sipStack.getStackLogger().logStackTrace();
             }
             addEventListener(sipStack);
    -        releaseReferences = sipStack.isAggressiveCleanup();
         }
     
         /**
          * Constructor given a transaction and a response.
          * 
    -     * @param transaction
    -     *            -- the transaction ( client/server)
    -     * @param sipResponse
    -     *            -- response with the appropriate tags.
    +     * @param transaction -- the transaction ( client/server)
    +     * @param sipResponse -- response with the appropriate tags.
          */
         public SIPDialog(SIPClientTransaction transaction, SIPResponse sipResponse) {
             this(transaction);
    @@ -779,13 +634,12 @@ public SIPDialog(SipProviderImpl sipProvider, SIPResponse sipResponse) {
             this.method = sipResponse.getCSeq().getMethod();
             this.callIdHeader = sipResponse.getCallId();
             this.serverTransactionFlag = false;
    -        if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    -            logger.logDebug("Creating a dialog : " + this);
    -            logger.logStackTrace();
    +        if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    +            sipStack.getStackLogger().logDebug("Creating a dialog : " + this);
    +            sipStack.getStackLogger().logStackTrace();
             }
             this.isBackToBackUserAgent = sipStack.isBackToBackUserAgent;
             addEventListener(sipStack);
    -        releaseReferences = sipStack.isAggressiveCleanup();
         }
     
         // ///////////////////////////////////////////////////////////
    @@ -795,86 +649,86 @@ public SIPDialog(SipProviderImpl sipProvider, SIPResponse sipResponse) {
          * A debugging print routine.
          */
         private void printRouteList() {
    -        if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    -            logger.logDebug("this : " + this);
    -            logger.logDebug(
    -                    "printRouteList : " + this.routeList.encode());
    +        if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    +            sipStack.getStackLogger().logDebug("this : " + this);
    +            sipStack.getStackLogger().logDebug("printRouteList : " + this.routeList.encode());
             }
         }
     
    +    /**
    +     * Return true if this is a client dialog.
    +     * 
    +     * @return true if the transaction that created this dialog is a client transaction and false
    +     *         otherwise.
    +     */
    +    private boolean isClientDialog() {
    +        SIPTransaction transaction = (SIPTransaction) this.getFirstTransaction();
    +        return transaction instanceof SIPClientTransaction;
    +    }
    +
         /**
          * Raise an io exception for asyncrhonous retransmission of responses
          * 
    -     * @param host
    -     *            -- host to where the io was headed
    -     * @param port
    -     *            -- remote port
    -     * @param protocol
    -     *            -- protocol (udp/tcp/tls)
    +     * @param host -- host to where the io was headed
    +     * @param port -- remote port
    +     * @param protocol -- protocol (udp/tcp/tls)
          */
         private void raiseIOException(String host, int port, String protocol) {
             // Error occured in retransmitting response.
             // Deliver the error event to the listener
             // Kill the dialog.
     
    -        IOExceptionEvent ioError = new IOExceptionEvent(this, host, port,
    -                protocol);
    +        IOExceptionEvent ioError = new IOExceptionEvent(this, host, port, protocol);
             sipProvider.handleEvent(ioError, null);
     
             setState(SIPDialog.TERMINATED_STATE);
         }
    -
    +    
         /**
          * Raise a dialog timeout if an ACK has not been sent or received
          * 
    -     * @param dialogTimeoutError
    +     * @param dialogTimeoutError 
          */
         private void raiseErrorEvent(int dialogTimeoutError) {
    -        // Error event to send to all listeners
    -        SIPDialogErrorEvent newErrorEvent;
    -        // Iterator through the list of listeners
    -        Iterator listenerIterator;
    -        // Next listener in the list
    -        SIPDialogEventListener nextListener;
    -
    -        // Create the error event
    -        newErrorEvent = new SIPDialogErrorEvent(this, dialogTimeoutError);
    -
    -        // Loop through all listeners of this transaction
    -        synchronized (eventListeners) {
    -            
    -            listenerIterator = eventListeners.iterator();
    -            while (listenerIterator.hasNext()) {
    -                // Send the event to the next listener
    -                nextListener = (SIPDialogEventListener) listenerIterator.next();
    -                nextListener.dialogErrorEvent(newErrorEvent);
    -            }
    -        }
    -        // Clear the event listeners after propagating the error.
    -        eventListeners.clear();
    -        // Errors always terminate a dialog except if a timeout has occured
    -        // because an ACK was not sent or received, then it is the
    -        // responsibility of the app to terminate
    -        // the dialog, either by sending a BYE or by calling delete() on the
    -        // dialog
    -        if (dialogTimeoutError != SIPDialogErrorEvent.DIALOG_ACK_NOT_SENT_TIMEOUT
    -                && dialogTimeoutError != SIPDialogErrorEvent.DIALOG_ACK_NOT_RECEIVED_TIMEOUT
    -                && dialogTimeoutError != SIPDialogErrorEvent.EARLY_STATE_TIMEOUT
    -                && dialogTimeoutError != SIPDialogErrorEvent.DIALOG_REINVITE_TIMEOUT) {
    -            delete();
    -        }
    -
    -        // we stop the timer in any case
    -        stopTimer();
    -    }
    +		// Error event to send to all listeners
    +		SIPDialogErrorEvent newErrorEvent;
    +		// Iterator through the list of listeners
    +		Iterator listenerIterator;
    +		// Next listener in the list
    +		SIPDialogEventListener nextListener;
    +
    +		// Create the error event
    +		newErrorEvent = new SIPDialogErrorEvent(this, dialogTimeoutError);
    +
    +		// Loop through all listeners of this transaction
    +		synchronized (eventListeners) {
    +			listenerIterator = eventListeners.iterator();
    +			while (listenerIterator.hasNext()) {
    +				// Send the event to the next listener
    +				nextListener = (SIPDialogEventListener) listenerIterator.next();
    +				nextListener.dialogErrorEvent(newErrorEvent);
    +			}
    +		}
    +		// Clear the event listeners after propagating the error.
    +		eventListeners.clear();
    +		// Errors always terminate a dialog except if a timeout has occured because an ACK was not sent or received, then it is the responsibility of the app to terminate
    +		// the dialog, either by sending a BYE or by calling delete() on the dialog		
    +		if( dialogTimeoutError != SIPDialogErrorEvent.DIALOG_ACK_NOT_SENT_TIMEOUT  &&
    +		        dialogTimeoutError != SIPDialogErrorEvent.DIALOG_ACK_NOT_RECEIVED_TIMEOUT  &&
    +		        dialogTimeoutError != SIPDialogErrorEvent.DIALOG_REINVITE_TIMEOUT ) {
    +			delete();
    +		}
    +		
    +		// we stop the timer in any case
    +		stopTimer();
    +	}
     
         /**
          * Set the remote party for this Dialog.
          * 
    -     * @param sipMessage
    -     *            -- SIP Message to extract the relevant information from.
    +     * @param sipMessage -- SIP Message to extract the relevant information from.
          */
    -    protected void setRemoteParty(SIPMessage sipMessage) {
    +    private void setRemoteParty(SIPMessage sipMessage) {
     
             if (!isServer()) {
     
    @@ -883,45 +737,41 @@ protected void setRemoteParty(SIPMessage sipMessage) {
                 this.remoteParty = sipMessage.getFrom().getAddress();
     
             }
    -        if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    -            logger.logDebug(
    -                    "settingRemoteParty " + this.remoteParty);
    +        if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    +            sipStack.getStackLogger().logDebug("settingRemoteParty " + this.remoteParty);
             }
         }
     
         /**
    -     * Add a route list extracted from a record route list. If this is a server
    -     * dialog then we assume that the record are added to the route list IN
    -     * order. If this is a client dialog then we assume that the record route
    -     * headers give us the route list to add in reverse order.
    +     * Add a route list extracted from a record route list. If this is a server dialog then we
    +     * assume that the record are added to the route list IN order. If this is a client dialog
    +     * then we assume that the record route headers give us the route list to add in reverse
    +     * order.
          * 
    -     * @param recordRouteList
    -     *            -- the record route list from the incoming message.
    +     * @param recordRouteList -- the record route list from the incoming message.
          */
     
         private void addRoute(RecordRouteList recordRouteList) {
             try {
    -            if (!this.isServer()) {
    +            if (this.isClientDialog()) {
                     // This is a client dialog so we extract the record
                     // route from the response and reverse its order to
                     // careate a route list.
                     this.routeList = new RouteList();
                     // start at the end of the list and walk backwards
     
    -                ListIterator li = recordRouteList.listIterator(recordRouteList
    -                        .size());
    +                ListIterator li = recordRouteList.listIterator(recordRouteList.size());
                     boolean addRoute = true;
                     while (li.hasPrevious()) {
                         RecordRoute rr = (RecordRoute) li.previous();
     
                         if (addRoute) {
                             Route route = new Route();
    -                        AddressImpl address = ((AddressImpl) ((AddressImpl) rr
    -                                .getAddress()).clone());
    +                        AddressImpl address = ((AddressImpl) ((AddressImpl) rr.getAddress())
    +                                .clone());
     
                             route.setAddress(address);
    -                        route.setParameters((NameValueList) rr.getParameters()
    -                                .clone());
    +                        route.setParameters((NameValueList) rr.getParameters().clone());
     
                             this.routeList.add(route);
                         }
    @@ -939,34 +789,30 @@ private void addRoute(RecordRouteList recordRouteList) {
     
                         if (addRoute) {
                             Route route = new Route();
    -                        AddressImpl address = ((AddressImpl) ((AddressImpl) rr
    -                                .getAddress()).clone());
    -                        route.setAddress(address);
    -                        route.setParameters((NameValueList) rr.getParameters()
    +                        AddressImpl address = ((AddressImpl) ((AddressImpl) rr.getAddress())
                                     .clone());
    +                        route.setAddress(address);
    +                        route.setParameters((NameValueList) rr.getParameters().clone());
                             routeList.add(route);
                         }
                     }
                 }
             } finally {
    -            if (logger.isLoggingEnabled()) {
    +            if (sipStack.getStackLogger().isLoggingEnabled()) {
                     Iterator it = routeList.iterator();
     
                     while (it.hasNext()) {
    -                    SipURI sipUri = (SipURI) (((Route) it.next()).getAddress()
    -                            .getURI());
    -                    if (!sipUri.hasLrParam()) {
    -                        if (logger.isLoggingEnabled()) {
    -                            logger.logWarning(
    -                                    "NON LR route in Route set detected for dialog : "
    -                                            + this);
    -                            logger.logStackTrace();
    -                        }
    +                    SipURI sipUri = (SipURI) (((Route) it.next()).getAddress().getURI());
    +                    if (!sipUri.hasLrParam()) {                     
    +                    	if (sipStack.isLoggingEnabled()) {
    +                    		sipStack.getStackLogger().logWarning(
    +                                "NON LR route in Route set detected for dialog : " + this);
    +                        	sipStack.getStackLogger().logStackTrace();
    +                    	}	
                         } else {
    -                        if (logger.isLoggingEnabled(
    -                                LogWriter.TRACE_DEBUG))
    -                            logger.logDebug(
    -                                    "route = " + sipUri);
    +                    	if(sipStack.getStackLogger().isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    +                    		sipStack.getStackLogger().logDebug("route = " + sipUri);
    +                    	}
                         }
                     }
                 }
    @@ -976,35 +822,31 @@ private void addRoute(RecordRouteList recordRouteList) {
         /**
          * Add a route list extacted from the contact list of the incoming message.
          * 
    -     * @param contactList
    -     *            -- contact list extracted from the incoming message.
    +     * @param contactList -- contact list extracted from the incoming message.
          * 
          */
     
    -    protected void setRemoteTarget(ContactHeader contact) {
    +    void setRemoteTarget(ContactHeader contact) {
             this.remoteTarget = contact.getAddress();
    -        if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    -            logger.logDebug(
    -                    "Dialog.setRemoteTarget: " + this.remoteTarget);
    -            logger.logStackTrace();
    +        if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    +            sipStack.getStackLogger().logDebug("Dialog.setRemoteTarget: " + this.remoteTarget);
    +            sipStack.getStackLogger().logStackTrace();
             }
     
         }
     
         /**
    -     * Extract the route information from this SIP Message and add the relevant
    -     * information to the route set.
    +     * Extract the route information from this SIP Message and add the relevant information to the
    +     * route set.
          * 
    -     * @param sipMessage
    -     *            is the SIP message for which we want to add the route.
    +     * @param sipMessage is the SIP message for which we want to add the route.
          */
         private synchronized void addRoute(SIPResponse sipResponse) {
     
             try {
    -            if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    -                logger.logDebug(
    -                        "setContact: dialogState: " + this + "state = "
    -                                + this.getState());
    +            if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    +                sipStack.getStackLogger().logDebug(
    +                        "setContact: dialogState: " + this + "state = " + this.getState());
                 }
                 if (sipResponse.getStatusCode() == 100) {
                     // Do nothing for trying messages.
    @@ -1019,26 +861,21 @@ private synchronized void addRoute(SIPResponse sipResponse) {
                     if (sipResponse.getStatusCode() / 100 == 2 && !this.isServer()) {
                         ContactList contactList = sipResponse.getContactHeaders();
                         if (contactList != null
    -                            && SIPRequest.isTargetRefresh(sipResponse.getCSeq()
    -                                    .getMethod())) {
    -                        this.setRemoteTarget((ContactHeader) contactList
    -                                .getFirst());
    +                            && SIPRequest.isTargetRefresh(sipResponse.getCSeq().getMethod())) {
    +                        this.setRemoteTarget((ContactHeader) contactList.getFirst());
                         }
                     }
    -                if (!this.pendingRouteUpdateOn202Response)
    -                    return;
    +                if (! this.pendingRouteUpdateOn202Response ) return;
                 }
     
                 // Update route list on response if I am a client dialog.
                 if (!isServer() || this.pendingRouteUpdateOn202Response) {
     
    -                // only update the route set if the dialog is not in the
    -                // confirmed state.
    -                if ((this.getState() != DialogState.CONFIRMED && this
    -                        .getState() != DialogState.TERMINATED)
    -                        || this.pendingRouteUpdateOn202Response) {
    -                    RecordRouteList rrlist = sipResponse
    -                            .getRecordRouteHeaders();
    +                // only update the route set if the dialog is not in the confirmed state.
    +                if ((this.getState() != DialogState.CONFIRMED
    +                        && this.getState() != DialogState.TERMINATED) || 
    +                        this.pendingRouteUpdateOn202Response ) {
    +                    RecordRouteList rrlist = sipResponse.getRecordRouteHeaders();
                         // Add the route set from the incoming response in reverse
                         // order for record route headers.
                         if (rrlist != null) {
    @@ -1051,15 +888,13 @@ private synchronized void addRoute(SIPResponse sipResponse) {
     
                     ContactList contactList = sipResponse.getContactHeaders();
                     if (contactList != null) {
    -                    this
    -                            .setRemoteTarget((ContactHeader) contactList
    -                                    .getFirst());
    +                    this.setRemoteTarget((ContactHeader) contactList.getFirst());
                     }
                 }
     
             } finally {
    -            if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) {
    -                logger.logStackTrace();
    +            if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    +                sipStack.getStackLogger().logStackTrace();
                 }
             }
         }
    @@ -1070,8 +905,8 @@ private synchronized void addRoute(SIPResponse sipResponse) {
          * @return -- a cloned copy of the dialog route list.
          */
         private synchronized RouteList getRouteList() {
    -        if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG))
    -            logger.logDebug("getRouteList " + this);
    +        if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG))
    +            sipStack.getStackLogger().logDebug("getRouteList " + this);
             // Find the top via in the route list.
             ListIterator li;
             RouteList retval = new RouteList();
    @@ -1085,81 +920,65 @@ private synchronized RouteList getRouteList() {
                 }
             }
     
    -        if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    -            logger.logDebug("----- ");
    -            logger.logDebug("getRouteList for " + this);
    +        if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    +            sipStack.getStackLogger().logDebug("----- ");
    +            sipStack.getStackLogger().logDebug("getRouteList for " + this);
                 if (retval != null)
    -                logger.logDebug(
    -                        "RouteList = " + retval.encode());
    +                sipStack.getStackLogger().logDebug("RouteList = " + retval.encode());
                 if (routeList != null)
    -                logger.logDebug(
    -                        "myRouteList = " + routeList.encode());
    -            logger.logDebug("----- ");
    +                sipStack.getStackLogger().logDebug("myRouteList = " + routeList.encode());
    +            sipStack.getStackLogger().logDebug("----- ");
             }
             return retval;
         }
    -
    +    
         void setRouteList(RouteList routeList) {
    -        this.routeList = routeList;
    +    	this.routeList = routeList;
         }
     
         /**
          * Sends ACK Request to the remote party of this Dialogue.
          * 
          * 
    -     * @param request
    -     *            the new ACK Request message to send.
    -     * @param throwIOExceptionAsSipException
    -     *            - throws SipException if IOEx encountered. Otherwise, no
    -     *            exception is propagated.
    -     * @param releaseAckSem
    -     *            - release ack semaphore.
    -     * @throws SipException
    -     *             if implementation cannot send the ACK Request for any other
    -     *             reason
    +     * @param request the new ACK Request message to send.
    +     * @param throwIOExceptionAsSipException - throws SipException if IOEx encountered. Otherwise,
    +     *        no exception is propagated.
    +     * @param releaseAckSem - release ack semaphore.
    +     * @throws SipException if implementation cannot send the ACK Request for any other reason
          * 
          */
         private void sendAck(Request request, boolean throwIOExceptionAsSipException)
                 throws SipException {
    -
             SIPRequest ackRequest = (SIPRequest) request;
    -        if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG))
    -            logger.logDebug("sendAck" + this);
    -        
    +        if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG))
    +            sipStack.getStackLogger().logDebug("sendAck" + this);
    +
             if (!ackRequest.getMethod().equals(Request.ACK))
                 throw new SipException("Bad request method -- should be ACK");
    -        if (this.getState() == null
    -                || this.getState().getValue() == EARLY_STATE) {
    -            if (logger.isLoggingEnabled(LogWriter.TRACE_ERROR)) {
    -                logger.logError(
    -                        "Bad Dialog State for " + this + " dialogID = "
    -                                + this.getDialogId());
    +        if (this.getState() == null || this.getState().getValue() == EARLY_STATE) {
    +            if (sipStack.isLoggingEnabled()) {
    +                sipStack.getStackLogger().logError(
    +                        "Bad Dialog State for " + this + " dialogID = " + this.getDialogId());
                 }
                 throw new SipException("Bad dialog state " + this.getState());
             }
     
    -        if (!this.getCallId().getCallId().equals(
    -                ((SIPRequest) request).getCallId().getCallId())) {
    -            if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    -                logger
    -                        .logError("CallID " + this.getCallId());
    -                logger
    -                        .logError(
    -                                "RequestCallID = "
    -                                        + ackRequest.getCallId().getCallId());
    -                logger.logError("dialog =  " + this);
    +        if (!this.getCallId().getCallId().equals(((SIPRequest) request).getCallId().getCallId())) {
    +            if (sipStack.isLoggingEnabled()) {
    +                sipStack.getStackLogger().logError("CallID " + this.getCallId());
    +                sipStack.getStackLogger().logError(
    +                        "RequestCallID = " + ackRequest.getCallId().getCallId());
    +                sipStack.getStackLogger().logError("dialog =  " + this);
                 }
                 throw new SipException("Bad call ID in request");
             }
             try {
    -            if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    -                logger.logDebug(
    -                        "setting from tag For outgoing ACK= "
    -                                + this.getLocalTag());
    -                logger.logDebug(
    -                        "setting To tag for outgoing ACK = "
    -                                + this.getRemoteTag());
    -                logger.logDebug("ack = " + ackRequest);
    +            if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    +                sipStack.getStackLogger().logDebug(
    +                        "setting from tag For outgoing ACK= " + this.getLocalTag());
    +                sipStack.getStackLogger().logDebug(
    +                        "setting To tag for outgoing ACK = " + this.getRemoteTag());
    +                sipStack.getStackLogger().logDebug("ack = " + ackRequest);
                 }
                 if (this.getLocalTag() != null)
                     ackRequest.getFrom().setTag(this.getLocalTag());
    @@ -1174,19 +993,18 @@ private void sendAck(Request request, boolean throwIOExceptionAsSipException)
             if (hop == null)
                 throw new SipException("No route!");
             try {
    -            if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG))
    -                logger.logDebug("hop = " + hop);
    -            ListeningPointImpl lp = (ListeningPointImpl) this.sipProvider
    -                    .getListeningPoint(hop.getTransport());
    +            if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG))
    +                sipStack.getStackLogger().logDebug("hop = " + hop);
    +            ListeningPointImpl lp = (ListeningPointImpl) this.sipProvider.getListeningPoint(hop
    +                    .getTransport());
                 if (lp == null)
    -                throw new SipException(
    -                        "No listening point for this provider registered at "
    -                                + hop);
    +                throw new SipException("No listening point for this provider registered at "
    +                        + hop);
                 InetAddress inetAddress = InetAddress.getByName(hop.getHost());
    -            MessageChannel messageChannel = lp.getMessageProcessor()
    -                    .createMessageChannel(inetAddress, hop.getPort());
    +            MessageChannel messageChannel = lp.getMessageProcessor().createMessageChannel(
    +                    inetAddress, hop.getPort());
                 boolean releaseAckSem = false;
    -            long cseqNo = ((SIPRequest) request).getCSeq().getSeqNumber();
    +            long cseqNo = ((SIPRequest)request).getCSeq().getSeqNumber();
                 if (!this.isAckSent(cseqNo)) {
                     releaseAckSem = true;
                 }
    @@ -1195,37 +1013,33 @@ private void sendAck(Request request, boolean throwIOExceptionAsSipException)
                 messageChannel.sendMessage(ackRequest);
                 // Sent atleast one ACK.
                 this.isAcknowledged = true;
    -            this.highestSequenceNumberAcknowledged = Math.max(
    -                    this.highestSequenceNumberAcknowledged,
    -                    ((SIPRequest) ackRequest).getCSeq().getSeqNumber());
    +            this.highestSequenceNumberAcknowledged = Math.max(this.highestSequenceNumberAcknowledged,
    +                    ((SIPRequest)ackRequest).getCSeq().getSeqNumber());
                 if (releaseAckSem && this.isBackToBackUserAgent) {
                     this.releaseAckSem();
                 } else {
    -                if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    -                    logger.logDebug(
    -                            "Not releasing ack sem for " + this + " isAckSent "
    -                                    + releaseAckSem);
    +                if ( sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG) ) {
    +                    sipStack.getStackLogger().logDebug("Not releasing ack sem for " + this + " isAckSent " + releaseAckSem );
                     }
                 }
             } catch (IOException ex) {
                 if (throwIOExceptionAsSipException)
                     throw new SipException("Could not send ack", ex);
    -            this.raiseIOException(hop.getHost(), hop.getPort(), hop
    -                    .getTransport());
    +            this.raiseIOException(hop.getHost(), hop.getPort(), hop.getTransport());
             } catch (SipException ex) {
    -            if (logger.isLoggingEnabled())
    -                logger.logException(ex);
    +            if (sipStack.isLoggingEnabled())
    +                sipStack.getStackLogger().logException(ex);
                 throw ex;
             } catch (Exception ex) {
    -            if (logger.isLoggingEnabled())
    -                logger.logException(ex);
    +            if (sipStack.isLoggingEnabled())
    +                sipStack.getStackLogger().logException(ex);
                 throw new SipException("Could not create message channel", ex);
             }
             if (this.dialogDeleteTask != null) {
    -            this.getStack().getTimer().cancel(dialogDeleteTask);
    +            this.dialogDeleteTask.cancel();
                 this.dialogDeleteTask = null;
             }
    -
    +      
         }
     
         // /////////////////////////////////////////////////////////////
    @@ -1235,8 +1049,7 @@ private void sendAck(Request request, boolean throwIOExceptionAsSipException)
         /**
          * Set the stack address. Prevent us from routing messages to ourselves.
          * 
    -     * @param sipStack
    -     *            the address of the SIP stack.
    +     * @param sipStack the address of the SIP stack.
          * 
          */
         void setStack(SIPTransactionStack sipStack) {
    @@ -1266,37 +1079,34 @@ boolean isTerminatedOnBye() {
         /**
          * Mark that the dialog has seen an ACK.
          */
    -    void ackReceived(long cseqNumber) {
    +    void ackReceived(SIPRequest sipRequest) {
    +
             // Suppress retransmission of the final response
             if (this.isAckSeen()) {
    -            if (logger.isLoggingEnabled(
    -                    LogWriter.TRACE_DEBUG))
    -                logger.logDebug(
    -                        "Ack already seen for response -- dropping");
    +        	sipStack.getStackLogger().logDebug("Ack already seen for response -- dropping");
                 return;
             }
             SIPServerTransaction tr = this.getInviteTransaction();
             if (tr != null) {
    -            if (tr.getCSeq() == cseqNumber) {
    -                acquireTimerTaskSem();
    -                try {
    -                    if (this.timerTask != null) {
    -                        this.getStack().getTimer().cancel(timerTask);
    -                        this.timerTask = null;
    -                    }
    -                } finally {
    -                    releaseTimerTaskSem();
    -                }
    +            if (tr.getCSeq() == sipRequest.getCSeq().getSeqNumber()) {
    +            	acquireTimerTaskSem();
    +            	try {
    +	                if (this.timerTask != null) {                	                	
    +	                	this.timerTask.cancel();
    +		                this.timerTask = null;                	
    +	                }
    +            	} finally {
    +            		releaseTimerTaskSem();
    +            	}
                     if (this.dialogDeleteTask != null) {
    -                    this.getStack().getTimer().cancel(dialogDeleteTask);
    +                    this.dialogDeleteTask.cancel();
                         this.dialogDeleteTask = null;
                     }
    -                lastAckReceivedCSeqNumber = Long.valueOf(cseqNumber);
    -                if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    -                    logger.logDebug(
    -                            "ackReceived for "
    -                                    + ((SIPTransaction) tr).getMethod());
    -                    this.ackLine = logger.getLineCount();
    +                this.setLastAckReceived(sipRequest);
    +                if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    +                    sipStack.getStackLogger().logDebug(
    +                            "ackReceived for " + ((SIPTransaction) tr).getMethod());
    +                    this.ackLine = sipStack.getStackLogger().getLineCount();
                         this.printDebugInfo();
                     }
                     if (this.isBackToBackUserAgent) {
    @@ -1305,16 +1115,13 @@ void ackReceived(long cseqNumber) {
                     this.setState(CONFIRMED_STATE);
                 }
             } else {
    -            if (logger.isLoggingEnabled(
    -                    LogWriter.TRACE_DEBUG))
    -                logger.logDebug(
    -                        "tr is null -- not updating the ack state");
    +        	sipStack.getStackLogger().logDebug("tr is null -- not updating the ack state" );
             }
         }
     
         /**
    -     * Return true if a terminated event was delivered to the application as a
    -     * result of the dialog termination.
    +     * Return true if a terminated event was delivered to the application as a result of the
    +     * dialog termination.
          * 
          */
         synchronized boolean testAndSetIsDialogTerminatedEventDelivered() {
    @@ -1328,25 +1135,25 @@ synchronized boolean testAndSetIsDialogTerminatedEventDelivered() {
         // /////////////////////////////////////////////////////////
     
         /**
    -     * Adds a new event listener to this dialog.
    -     * 
    -     * @param newListener
    -     *            Listener to add.
    -     */
    -    public void addEventListener(SIPDialogEventListener newListener) {
    -        eventListeners.add(newListener);
    -    }
    -
    -    /**
    -     * Removed an event listener from this dialog.
    -     * 
    -     * @param oldListener
    -     *            Listener to remove.
    -     */
    -    public void removeEventListener(SIPDialogEventListener oldListener) {
    -        eventListeners.remove(oldListener);
    -    }
    -
    +	 * Adds a new event listener to this dialog.
    +	 * 
    +	 * @param newListener
    +	 *            Listener to add.
    +	 */
    +	public void addEventListener(SIPDialogEventListener newListener) {
    +		eventListeners.add(newListener);
    +	}
    +
    +	/**
    +	 * Removed an event listener from this dialog.
    +	 * 
    +	 * @param oldListener
    +	 *            Listener to remove.
    +	 */
    +	public void removeEventListener(SIPDialogEventListener oldListener) {
    +		eventListeners.remove(oldListener);
    +	}
    +    
         /*
          * @see javax.sip.Dialog#setApplicationData()
          */
    @@ -1368,12 +1175,11 @@ public Object getApplicationData() {
          * 
          */
         public synchronized void requestConsumed() {
    -        this.nextSeqno = this.getRemoteSeqNumber() + 1;
    +        this.nextSeqno = Long.valueOf(this.getRemoteSeqNumber() + 1);
     
    -        if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    -            this.logger.logDebug(
    -                    "Request Consumed -- next consumable Request Seqno = "
    -                            + this.nextSeqno);
    +        if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    +            this.sipStack.getStackLogger().logDebug(
    +                    "Request Consumed -- next consumable Request Seqno = " + this.nextSeqno);
             }
     
         }
    @@ -1381,10 +1187,8 @@ public synchronized void requestConsumed() {
         /**
          * Return true if this request can be consumed by the dialog.
          * 
    -     * @param dialogRequest
    -     *            is the request to check with the dialog.
    -     * @return true if the dialogRequest sequence number matches the next
    -     *         consumable seqno.
    +     * @param dialogRequest is the request to check with the dialog.
    +     * @return true if the dialogRequest sequence number matches the next consumable seqno.
          */
         public synchronized boolean isRequestConsumable(SIPRequest dialogRequest) {
             // have not yet set remote seqno - this is a fresh
    @@ -1402,9 +1206,9 @@ public synchronized boolean isRequestConsumable(SIPRequest dialogRequest) {
         }
     
         /**
    -     * This method is called when a forked dialog is created from the client
    -     * side. It starts a timer task. If the timer task expires before an ACK is
    -     * sent then the dialog is cancelled (i.e. garbage collected ).
    +     * This method is called when a forked dialog is created from the client side. It starts a
    +     * timer task. If the timer task expires before an ACK is sent then the dialog is cancelled
    +     * (i.e. garbage collected ).
          * 
          */
         public void doDeferredDelete() {
    @@ -1413,14 +1217,8 @@ public void doDeferredDelete() {
             else {
                 this.dialogDeleteTask = new DialogDeleteTask();
                 // Delete the transaction after the max ack timeout.
    -            if (sipStack.getTimer() != null && sipStack.getTimer().isStarted()) {
    -            	sipStack.getTimer().schedule(
    -                    this.dialogDeleteTask,
    -                    SIPTransaction.TIMER_H
    -                            * SIPTransactionStack.BASE_TIMER_INTERVAL);
    -            } else {
    -            	this.delete();
    -            }
    +            sipStack.getTimer().schedule(this.dialogDeleteTask,
    +                    SIPTransaction.TIMER_H * SIPTransactionStack.BASE_TIMER_INTERVAL);
             }
     
         }
    @@ -1428,36 +1226,28 @@ public void doDeferredDelete() {
         /**
          * Set the state for this dialog.
          * 
    -     * @param state
    -     *            is the state to set for the dialog.
    +     * @param state is the state to set for the dialog.
          */
     
         public void setState(int state) {
    -        if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    -            logger.logDebug(
    -                    "SIPDialog::setState:Setting dialog state for " + this + "newState = " + state);
    -            logger.logStackTrace();
    +        if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    +            sipStack.getStackLogger().logDebug(
    +                    "Setting dialog state for " + this + "newState = " + state);
    +            sipStack.getStackLogger().logStackTrace();
                 if (state != NULL_STATE && state != this.dialogState)
    -                if (logger.isLoggingEnabled()) {
    -                    logger.logDebug("SIPDialog::setState:" +	
    +                if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    +                    sipStack.getStackLogger().logDebug(
                                 this + "  old dialog state is " + this.getState());
    -                    logger.logDebug("SIPDialog::setState:" +
    -                            this + "  New dialog state is "
    -                                    + DialogState.getObject(state));
    +                    sipStack.getStackLogger().logDebug(
    +                            this + "  New dialog state is " + DialogState.getObject(state));
                     }
     
             }
    -        if ( state == EARLY_STATE ) {
    -            this.addEventListener(this.getSipProvider());
    -        }
    -
             this.dialogState = state;
             // Dialog is in terminated state set it up for GC.
             if (state == TERMINATED_STATE) {
    -            this.removeEventListener(this.getSipProvider());
    -            if (sipStack.getTimer() != null && sipStack.getTimer().isStarted() ) { // may be null after shutdown
    -                sipStack.getTimer().schedule(new LingerTimer(),
    -                        DIALOG_LINGER_TIME * 1000);
    +            if (sipStack.getTimer() != null) { // may be null after shutdown
    +                sipStack.getTimer().schedule(new LingerTimer(), DIALOG_LINGER_TIME * 1000);
                 }
                 this.stopTimer();
     
    @@ -1468,16 +1258,13 @@ public void setState(int state) {
          * Debugging print for the dialog.
          */
         public void printDebugInfo() {
    -        if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    -            logger.logDebug("isServer = " + isServer());
    -            logger.logDebug("localTag = " + getLocalTag());
    -            logger.logDebug("remoteTag = " + getRemoteTag());
    -            logger.logDebug(
    -                    "localSequenceNumer = " + getLocalSeqNumber());
    -            logger.logDebug(
    -                    "remoteSequenceNumer = " + getRemoteSeqNumber());
    -            logger.logDebug(
    -                    "ackLine:" + this.getRemoteTag() + " " + ackLine);
    +        if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
    +            sipStack.getStackLogger().logDebug("isServer = " + isServer());
    +            sipStack.getStackLogger().logDebug("localTag = " + getLocalTag());
    +            sipStack.getStackLogger().logDebug("remoteTag = " + getRemoteTag());
    +            sipStack.getStackLogger().logDebug("localSequenceNumer = " + getLocalSeqNumber());
    +            sipStack.getStackLogger().logDebug("remoteSequenceNumer = " + getRemoteSeqNumber());
    +            sipStack.getStackLogger().logDebug("ackLine:" + this.getRemoteTag() + " " + ackLine);
             }
         }
     
    @@ -1487,37 +1274,27 @@ public void printDebugInfo() {
          * @return flag that records if the ack has been seen.
          */
         public boolean isAckSeen() {
    -
    -        if (lastAckReceivedCSeqNumber == null
    -                && lastResponseStatusCode == Response.OK) {
    -            if (logger.isLoggingEnabled(
    -                    LogWriter.TRACE_DEBUG)) {
    -                logger.logDebug(
    -                        this + "lastAckReceived is null -- returning false");
    -            }
    -            return false;
    -        } else if (lastResponseMethod == null) {
    -            if (logger.isLoggingEnabled(
    -                    LogWriter.TRACE_DEBUG)) {
    -                logger.logDebug(
    -                        this + "lastResponse is null -- returning false");
    -            }
    -            return false;
    -        } else if (lastAckReceivedCSeqNumber == null
    -                && lastResponseStatusCode / 100 > 2) {
    -            if (logger.isLoggingEnabled(
    -                    LogWriter.TRACE_DEBUG)) {
    -                logger.logDebug(
    -                        this + "lastResponse statusCode "
    -                                + lastResponseStatusCode);
    -            }
    -            return true;
    -        } else {
    -
    -            return this.lastAckReceivedCSeqNumber != null
    -                    && this.lastAckReceivedCSeqNumber >= this
    -                            .getRemoteSeqNumber();
    -        }
    +    	
    +    	if (lastAckReceived == null && lastResponse.getStatusCode() == Response.OK ) {
    +    		if ( sipStack.getStackLogger().isLoggingEnabled(LogWriter.TRACE_DEBUG) ) {
    +    			sipStack.getStackLogger().logDebug(this + "lastAckReceived is null -- returning false");
    +    		}
    +    		return false;
    +    	} else if (lastResponse == null ) {
    +    		if ( sipStack.getStackLogger().isLoggingEnabled(LogWriter.TRACE_DEBUG) ) {
    +    			sipStack.getStackLogger().logDebug(this + "lastResponse is null -- returning false");
    +    		}
    +    		return false;
    +    	} else if ( lastAckReceived == null  && lastResponse.getStatusCode() / 100 > 2 ) {
    +    		if ( sipStack.getStackLogger().isLoggingEnabled(LogWriter.TRACE_DEBUG) ) {
    +    			sipStack.getStackLogger().logDebug(this + "lastResponse statusCode " + lastResponse.getStatusCode());
    +    		}
    +    		return true;
    +    	} else {
    +    		
    +    		return this.lastAckReceived != null &&
    +    			this.lastAckReceived.getCSeq().getSeqNumber() >= this.getRemoteSeqNumber();
    +    	}
         }
     
         /**
    @@ -1528,8 +1305,8 @@ public SIPRequest getLastAckSent() {
         }
     
         /**
    -     * Return true if ACK was sent ( for client tx ). For server tx, this is a
    -     * NO-OP ( we dont send ACK).
    +     * Return true if ACK was sent ( for client tx ). For server tx, this is a NO-OP ( we dont
    +     * send ACK).
          */
         public boolean isAckSent(long cseqNo) {
             if (this.getLastTransaction() == null)
    @@ -1538,55 +1315,39 @@ public boolean isAckSent(long cseqNo) {
                 if (this.getLastAckSent() == null) {
                     return false;
                 } else {
    -                return cseqNo <= ((SIPRequest) this.getLastAckSent()).getCSeq()
    -                        .getSeqNumber();
    +                return cseqNo <=((SIPRequest) this.getLastAckSent()).getCSeq().getSeqNumber();
                 }
             } else {
                 return true;
             }
         }
     
    -    @Deprecated
    -    public Transaction getFirstTransaction() {
    -        throw new UnsupportedOperationException(
    -                "This method has been deprecated and is no longer supported");
    -    }
    -
         /**
    -     * This is for internal use only.
    -     * 
    +     * Get the transaction that created this dialog.
          */
    -    public Transaction getFirstTransactionInt() {
    -        // jeand : we try to avoid keeping the ref around for too long to help
    -        // the GC
    -        if (firstTransaction != null) {
    -            return firstTransaction;
    -        }
    -        return this.sipStack.findTransaction(firstTransactionId,
    -                firstTransactionIsServerTransaction);
    +    public Transaction getFirstTransaction() {
    +        return this.firstTransaction;
         }
     
    +
         /**
    -     * Gets the route set for the dialog. When acting as an User Agent Server
    -     * the route set MUST be set to the list of URIs in the Record-Route header
    -     * field from the request, taken in order and preserving all URI parameters.
    -     * When acting as an User Agent Client the route set MUST be set to the list
    -     * of URIs in the Record-Route header field from the response, taken in
    -     * reverse order and preserving all URI parameters. If no Record-Route
    -     * header field is present in the request or response, the route set MUST be
    -     * set to the empty set. This route set, even if empty, overrides any
    -     * pre-existing route set for future requests in this dialog.
    +     * Gets the route set for the dialog. When acting as an User Agent Server the route set MUST
    +     * be set to the list of URIs in the Record-Route header field from the request, taken in
    +     * order and preserving all URI parameters. When acting as an User Agent Client the route set
    +     * MUST be set to the list of URIs in the Record-Route header field from the response, taken
    +     * in reverse order and preserving all URI parameters. If no Record-Route header field is
    +     * present in the request or response, the route set MUST be set to the empty set. This route
    +     * set, even if empty, overrides any pre-existing route set for future requests in this
    +     * dialog.
          * 

    - * Requests within a dialog MAY contain Record-Route and Contact header - * fields. However, these requests do not cause the dialog's route set to be - * modified. + * Requests within a dialog MAY contain Record-Route and Contact header fields. However, these + * requests do not cause the dialog's route set to be modified. *

    - * The User Agent Client uses the remote target and route set to build the - * Request-URI and Route header field of the request. + * The User Agent Client uses the remote target and route set to build the Request-URI and + * Route header field of the request. * - * @return an Iterator containing a list of route headers to be used for - * forwarding. Empty iterator is returned if route has not been - * established. + * @return an Iterator containing a list of route headers to be used for forwarding. Empty + * iterator is returned if route has not been established. */ public Iterator getRouteSet() { if (this.routeList == null) { @@ -1602,25 +1363,22 @@ public Iterator getRouteSet() { * @param sipRequest */ public synchronized void addRoute(SIPRequest sipRequest) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( - "setContact: dialogState: " + this + "state = " - + this.getState()); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( + "setContact: dialogState: " + this + "state = " + this.getState()); } if (this.dialogState == CONFIRMED_STATE && SIPRequest.isTargetRefresh(sipRequest.getMethod())) { this.doTargetRefresh(sipRequest); } - if (this.dialogState == CONFIRMED_STATE - || this.dialogState == TERMINATED_STATE) { + if (this.dialogState == CONFIRMED_STATE || this.dialogState == TERMINATED_STATE) { return; } - + // Fix for issue #225: mustn't learn Route set from mid-dialog requests - if (sipRequest.getToTag() != null) - return; - + if ( sipRequest.getToTag()!=null ) return; + // Incoming Request has the route list RecordRouteList rrlist = sipRequest.getRecordRouteHeaders(); // Add the route set from the incoming response in reverse @@ -1644,25 +1402,19 @@ public synchronized void addRoute(SIPRequest sipRequest) { * Set the dialog identifier. */ public void setDialogId(String dialogId) { - if (firstTransaction != null) { - firstTransaction.setDialog(this, dialogId); - } this.dialogId = dialogId; } /** - * Creates a new dialog based on a received NOTIFY. The dialog state is - * initialized appropriately. The NOTIFY differs in the From tag + * Creates a new dialog based on a received NOTIFY. The dialog state is initialized + * appropriately. The NOTIFY differs in the From tag * - * Made this a separate method to clearly distinguish what's happening here - * - this is a non-trivial case + * Made this a separate method to clearly distinguish what's happening here - this is a + * non-trivial case * - * @param subscribeTx - * - the transaction started with the SUBSCRIBE that we sent - * @param notifyST - * - the ServerTransaction created for an incoming NOTIFY - * @return -- a new dialog created from the subscribe original SUBSCRIBE - * transaction. + * @param subscribeTx - the transaction started with the SUBSCRIBE that we sent + * @param notifyST - the ServerTransaction created for an incoming NOTIFY + * @return -- a new dialog created from the subscribe original SUBSCRIBE transaction. * * */ @@ -1728,99 +1480,71 @@ protected boolean isReInvite() { */ public String getDialogId() { - if (this.dialogId == null && this.lastResponseDialogId != null) - this.dialogId = this.lastResponseDialogId; + if (this.dialogId == null && this.lastResponse != null) + this.dialogId = this.lastResponse.getDialogId(isServer()); return this.dialogId; } - protected void storeFirstTransactionInfo(SIPDialog dialog, - SIPTransaction transaction) { - - dialog.firstTransactionSeen = true; - dialog.firstTransaction = transaction; - dialog.firstTransactionIsServerTransaction = transaction - .isServerTransaction(); - if (dialog.firstTransactionIsServerTransaction) { - dialog.firstTransactionSecure = transaction.getRequest() - .getRequestURI().getScheme().equalsIgnoreCase("sips"); - } else { - dialog.firstTransactionSecure = ((SIPClientTransaction) transaction) - .getOriginalRequestScheme().equalsIgnoreCase("sips"); - } - dialog.firstTransactionPort = transaction.getPort(); - dialog.firstTransactionId = transaction.getBranchId(); - dialog.firstTransactionMethod = transaction.getMethod(); - if (transaction instanceof SIPServerTransaction - && dialog.firstTransactionMethod.equals(Request.INVITE)) { - sipStack.removeMergeDialog(firstTransactionMergeId); + protected void storeFirstTransactionInfo(SIPDialog dialog, SIPTransaction transaction) { + dialog.firstTransaction = transaction; + dialog.firstTransactionSeen = true; + dialog.firstTransactionIsServerTransaction = transaction.isServerTransaction(); + dialog.firstTransactionSecure = transaction.getRequest().getRequestURI().getScheme() + .equalsIgnoreCase("sips"); + dialog.firstTransactionPort = transaction.getPort(); + dialog.firstTransactionId = transaction.getBranchId(); + dialog.firstTransactionMethod = transaction.getMethod(); + if ( transaction instanceof SIPServerTransaction && dialog.firstTransactionMethod.equals(Request.INVITE) ) { + sipStack.removeMergeDialog(firstTransactionMergeId); dialog.firstTransactionMergeId = ((SIPRequest) transaction.getRequest()).getMergeId(); - sipStack.putMergeDialog(this); - } - - if (transaction.isServerTransaction()) { + sipStack.putMergeDialog(this); + } + + if (dialog.isServer()) { SIPServerTransaction st = (SIPServerTransaction) transaction; SIPResponse response = st.getLastResponse(); - dialog.contactHeader = response != null ? response - .getContactHeader() : null; + dialog.contactHeader = response != null ? response.getContactHeader() : null; } else { SIPClientTransaction ct = (SIPClientTransaction) transaction; - if (ct != null) { - dialog.contactHeader = ct.getOriginalRequestContact(); + if (ct != null){ + SIPRequest sipRequest = ct.getOriginalRequest(); + dialog.contactHeader = sipRequest.getContactHeader(); } } - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("firstTransaction = " + dialog.firstTransaction); - logger.logDebug("firstTransactionIsServerTransaction = " + firstTransactionIsServerTransaction); - logger.logDebug("firstTransactionSecure = " + firstTransactionSecure); - logger.logDebug("firstTransactionPort = " + firstTransactionPort); - logger.logDebug("firstTransactionId = " + firstTransactionId); - logger.logDebug("firstTransactionMethod = " + firstTransactionMethod); - logger.logDebug("firstTransactionMergeId = " + firstTransactionMergeId); - } } - /** * Add a transaction record to the dialog. * - * @param transaction - * is the transaction to add to the dialog. + * @param transaction is the transaction to add to the dialog. */ - public boolean addTransaction(SIPTransaction transaction) { + public boolean addTransaction(SIPTransaction transaction) { SIPRequest sipRequest = (SIPRequest) transaction.getOriginalRequest(); // Proessing a re-invite. - if (firstTransactionSeen - && !firstTransactionId.equals(transaction.getBranchId()) + if (firstTransactionSeen && !firstTransactionId.equals(transaction.getBranchId()) && transaction.getMethod().equals(firstTransactionMethod)) { setReInviteFlag(true); } - - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( - "SipDialog.addTransaction() " + this + " transaction = " - + transaction); + + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("SipDialog.addTransaction() " + this + " transaction = " + transaction); } if (firstTransactionSeen == false) { // Record the local and remote sequenc // numbers and the from and to tags for future // use on this dialog. - storeFirstTransactionInfo(this, transaction); + storeFirstTransactionInfo(this, transaction); if (sipRequest.getMethod().equals(Request.SUBSCRIBE)) - this.eventHeader = (EventHeader) sipRequest - .getHeader(EventHeader.NAME); + this.eventHeader = (EventHeader) sipRequest.getHeader(EventHeader.NAME); this.setLocalParty(sipRequest); this.setRemoteParty(sipRequest); this.setCallId(sipRequest); - if (this.originalRequest == null - && transaction.isInviteTransaction()) { + if (this.originalRequest == null) { this.originalRequest = sipRequest; - } else if (originalRequest != null) { - originalRequestRecordRouteHeaders = sipRequest - .getRecordRouteHeaders(); } if (this.method == null) { this.method = sipRequest.getMethod(); @@ -1834,35 +1558,24 @@ public boolean addTransaction(SIPTransaction transaction) { this.originalLocalSequenceNumber = localSequenceNumber; this.setLocalTag(sipRequest.getFrom().getTag()); if (myTag == null) - if (logger.isLoggingEnabled()) - logger - .logError( - "The request's From header is missing the required Tag parameter."); + if (sipStack.isLoggingEnabled()) + sipStack.getStackLogger().logError( + "The request's From header is missing the required Tag parameter."); } } else if (transaction.getMethod().equals(firstTransactionMethod) - && firstTransactionIsServerTransaction != transaction - .isServerTransaction()) { + && firstTransactionIsServerTransaction != transaction.isServerTransaction()) { // This case occurs when you are processing a re-invite. // Switch from client side to server side for re-invite // (put the other side on hold). - - storeFirstTransactionInfo(this, transaction); - + + storeFirstTransactionInfo(this, transaction); + this.setLocalParty(sipRequest); this.setRemoteParty(sipRequest); this.setCallId(sipRequest); - if (transaction.isInviteTransaction()) { - this.originalRequest = sipRequest; - } else { - originalRequestRecordRouteHeaders = sipRequest - .getRecordRouteHeaders(); - } + this.originalRequest = sipRequest; this.method = sipRequest.getMethod(); - } else if (firstTransaction == null - && transaction.isInviteTransaction()) { - // jeand needed for reinvite reliable processing - firstTransaction = transaction; } if (transaction instanceof SIPServerTransaction) { setRemoteSequenceNumber(sipRequest.getCSeq().getSeqNumber()); @@ -1872,25 +1585,22 @@ public boolean addTransaction(SIPTransaction transaction) { // sequence number to avoid re-processing of requests // with the same sequence number directed towards this // dialog. - - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( - "isBackToBackUserAgent = " + this.isBackToBackUserAgent); - } - if (transaction.isInviteTransaction()) { - if ( logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("SIPDialog::setLastTransaction:dialog= " + SIPDialog.this + " lastTransaction = " + transaction); - } - this.lastTransaction = transaction; + + if ( sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG) ) { + sipStack.getStackLogger().logDebug("isBackToBackUserAgent = " + this.isBackToBackUserAgent ); } - - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( - "Transaction Added " + this + myTag + "/" + hisTag); - logger.logDebug( + + + + this.lastTransaction = transaction; + + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger() + .logDebug("Transaction Added " + this + myTag + "/" + hisTag); + sipStack.getStackLogger().logDebug( "TID = " + transaction.getTransactionId() + "/" + transaction.isServerTransaction()); - logger.logStackTrace(); + sipStack.getStackLogger().logStackTrace(); } return true; } @@ -1898,31 +1608,26 @@ public boolean addTransaction(SIPTransaction transaction) { /** * Set the remote tag. * - * @param hisTag - * is the remote tag to set. + * @param hisTag is the remote tag to set. */ - protected void setRemoteTag(String hisTag) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( - "setRemoteTag(): " + this + " remoteTag = " + this.hisTag - + " new tag = " + hisTag); + private void setRemoteTag(String hisTag) { + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( + "setRemoteTag(): " + this + " remoteTag = " + this.hisTag + " new tag = " + + hisTag); } - if (this.hisTag != null && hisTag != null - && !hisTag.equals(this.hisTag)) { + if (this.hisTag != null && hisTag != null && !hisTag.equals(this.hisTag)) { if (this.getState() != DialogState.EARLY) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger - .logDebug( - "Dialog is already established -- ignoring remote tag re-assignment"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug( + "Dialog is already established -- ignoring remote tag re-assignment"); return; } else if (sipStack.isRemoteTagReassignmentAllowed()) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger - .logDebug( - "UNSAFE OPERATION ! tag re-assignment " - + this.hisTag - + " trying to set to " + hisTag - + " can cause unexpected effects "); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug( + "UNSAFE OPERATION ! tag re-assignment " + this.hisTag + + " trying to set to " + hisTag + + " can cause unexpected effects "); boolean removed = false; if (this.sipStack.getDialog(dialogId) == this) { this.sipStack.removeDialog(dialogId); @@ -1933,9 +1638,8 @@ protected void setRemoteTag(String hisTag) { this.dialogId = null; this.hisTag = hisTag; if (removed) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger - .logDebug("ReInserting Dialog"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("ReInserting Dialog"); this.sipStack.putDialog(this); } } @@ -1943,9 +1647,8 @@ protected void setRemoteTag(String hisTag) { if (hisTag != null) { this.hisTag = hisTag; } else { - if (logger.isLoggingEnabled()) - logger.logWarning( - "setRemoteTag : called with null argument "); + if (sipStack.isLoggingEnabled()) + sipStack.getStackLogger().logWarning("setRemoteTag : called with null argument "); } } } @@ -1969,18 +1672,16 @@ public SIPServerTransaction getInviteTransaction() { } /** - * Set the local sequece number for the dialog (defaults to 1 when the - * dialog is created). + * Set the local sequece number for the dialog (defaults to 1 when the dialog is created). * - * @param lCseq - * is the local cseq number. + * @param lCseq is the local cseq number. * */ private void setLocalSequenceNumber(long lCseq) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug( - "setLocalSequenceNumber: original " - + this.localSequenceNumber + " new = " + lCseq); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug( + "setLocalSequenceNumber: original " + this.localSequenceNumber + " new = " + + lCseq); if (lCseq <= this.localSequenceNumber) throw new RuntimeException("Sequence number should not decrease !"); this.localSequenceNumber = lCseq; @@ -1989,29 +1690,27 @@ private void setLocalSequenceNumber(long lCseq) { /** * Set the remote sequence number for the dialog. * - * @param rCseq - * is the remote cseq number. + * @param rCseq is the remote cseq number. * */ public void setRemoteSequenceNumber(long rCseq) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug( - "setRemoteSeqno " + this + "/" + rCseq); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("setRemoteSeqno " + this + "/" + rCseq); this.remoteSequenceNumber = rCseq; } /** - * Increment the local CSeq # for the dialog. This is useful for if you want - * to create a hole in the sequence number i.e. route a request outside the - * dialog and then resume within the dialog. + * Increment the local CSeq # for the dialog. This is useful for if you want to create a hole + * in the sequence number i.e. route a request outside the dialog and then resume within the + * dialog. */ public void incrementLocalSequenceNumber() { ++this.localSequenceNumber; } /** - * Get the remote sequence number (for cseq assignment of outgoing requests - * within this dialog). + * Get the remote sequence number (for cseq assignment of outgoing requests within this + * dialog). * * @deprecated * @return local sequence number. @@ -2022,8 +1721,8 @@ public int getRemoteSequenceNumber() { } /** - * Get the local sequence number (for cseq assignment of outgoing requests - * within this dialog). + * Get the local sequence number (for cseq assignment of outgoing requests within this + * dialog). * * @deprecated * @return local sequence number. @@ -2034,8 +1733,7 @@ public int getLocalSequenceNumber() { } /** - * Get the sequence number for the request that origianlly created the - * Dialog. + * Get the sequence number for the request that origianlly created the Dialog. * * @return -- the original starting sequence number for this dialog. */ @@ -2083,16 +1781,14 @@ public String getRemoteTag() { /** * Set local tag for the transaction. * - * @param mytag - * is the tag to use in From headers client transactions that - * belong to this dialog and for generating To tags for Server - * transaction requests that belong to this dialog. + * @param mytag is the tag to use in From headers client transactions that belong to this + * dialog and for generating To tags for Server transaction requests that belong to + * this dialog. */ - protected void setLocalTag(String mytag) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( - "set Local tag " + mytag + " dialog = " + this); - logger.logStackTrace(); + private void setLocalTag(String mytag) { + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("set Local tag " + mytag + " dialog = " + this ); + sipStack.getStackLogger().logStackTrace(); } this.myTag = mytag; @@ -2116,17 +1812,6 @@ public void delete() { * @see javax.sip.Dialog#getCallId() */ public CallIdHeader getCallId() { - // jeand : we save the header in a string form and reparse it, help GC - // for dialogs updated not too often - if (callIdHeader == null && callIdHeaderString != null) { - try { - this.callIdHeader = (CallIdHeader) new CallIDParser( - callIdHeaderString).parse(); - } catch (ParseException e) { - logger.logError( - "error reparsing the call id header", e); - } - } return this.callIdHeader; } @@ -2144,21 +1829,10 @@ private void setCallId(SIPRequest sipRequest) { */ public javax.sip.address.Address getLocalParty() { - // jeand : we save the address in a string form and reparse it, help GC - // for dialogs updated not too often - if (localParty == null && localPartyStringified != null) { - try { - this.localParty = (Address) new AddressParser( - localPartyStringified).address(true); - } catch (ParseException e) { - logger.logError( - "error reparsing the localParty", e); - } - } return this.localParty; } - protected void setLocalParty(SIPMessage sipMessage) { + private void setLocalParty(SIPMessage sipMessage) { if (!isServer()) { this.localParty = sipMessage.getFrom().getAddress(); } else { @@ -2167,30 +1841,18 @@ protected void setLocalParty(SIPMessage sipMessage) { } /** - * Returns the Address identifying the remote party. This is the value of - * the To header of locally initiated requests in this dialogue when acting - * as an User Agent Client. + * Returns the Address identifying the remote party. This is the value of the To header of + * locally initiated requests in this dialogue when acting as an User Agent Client. *

    - * This is the value of the From header of recieved responses in this - * dialogue when acting as an User Agent Server. + * This is the value of the From header of recieved responses in this dialogue when acting as + * an User Agent Server. * * @return the address object of the remote party. */ public javax.sip.address.Address getRemoteParty() { - // jeand : we save the address in a string form and reparse it, help GC - // for dialogs updated not too often - if (remoteParty == null && remotePartyStringified != null) { - try { - this.remoteParty = (Address) new AddressParser( - remotePartyStringified).address(true); - } catch (ParseException e) { - logger.logError( - "error reparsing the remoteParty", e); - } - } - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( - "gettingRemoteParty " + this.remoteParty); + + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("gettingRemoteParty " + this.remoteParty); } return this.remoteParty; @@ -2202,17 +1864,7 @@ public javax.sip.address.Address getRemoteParty() { * @see javax.sip.Dialog#getRemoteTarget() */ public javax.sip.address.Address getRemoteTarget() { - // jeand : we save the address in a string form and reparse it, help GC - // for dialogs updated not too often - if (remoteTarget == null && remoteTargetStringified != null) { - try { - this.remoteTarget = (Address) new AddressParser( - remoteTargetStringified).address(true); - } catch (ParseException e) { - logger.logError( - "error reparsing the remoteTarget", e); - } - } + return this.remoteTarget; } @@ -2228,12 +1880,11 @@ public DialogState getState() { } /** - * Returns true if this Dialog is secure i.e. if the request arrived over - * TLS, and the Request-URI contained a SIPS URI, the "secure" flag is set - * to TRUE. + * Returns true if this Dialog is secure i.e. if the request arrived over TLS, and the + * Request-URI contained a SIPS URI, the "secure" flag is set to TRUE. * - * @return true if this dialogue was established using a sips - * URI over TLS, and false otherwise. + * @return true if this dialogue was established using a sips URI over TLS, and + * false otherwise. */ public boolean isSecure() { return this.firstTransactionSecure; @@ -2256,12 +1907,10 @@ public void sendAck(Request request) throws SipException { public Request createRequest(String method) throws SipException { if (method.equals(Request.ACK) || method.equals(Request.PRACK)) { - throw new SipException( - "Invalid method specified for createRequest:" + method); + throw new SipException("Invalid method specified for createRequest:" + method); } - if (lastResponseTopMostVia != null) - return this.createRequest(method, this.lastResponseTopMostVia - .getTransport()); + if (lastResponse != null) + return this.createRequest(method, this.lastResponse); else throw new SipException("Dialog not yet established -- no response!"); } @@ -2274,18 +1923,16 @@ public Request createRequest(String method) throws SipException { * @return * @throws SipException */ - private SIPRequest createRequest(String method, String topMostViaTransport) - throws SipException { + private Request createRequest(String method, SIPResponse sipResponse) throws SipException { /* - * Check if the dialog is in the right state (RFC 3261 section 15). The - * caller's UA MAY send a BYE for either CONFIRMED or EARLY dialogs, and - * the callee's UA MAY send a BYE on CONFIRMED dialogs, but MUST NOT - * send a BYE on EARLY dialogs. + * Check if the dialog is in the right state (RFC 3261 section 15). The caller's UA MAY + * send a BYE for either CONFIRMED or EARLY dialogs, and the callee's UA MAY send a BYE on + * CONFIRMED dialogs, but MUST NOT send a BYE on EARLY dialogs. * * Throw out cancel request. */ - if (method == null || topMostViaTransport == null) + if (method == null || sipResponse == null) throw new NullPointerException("null argument"); if (method.equals(Request.CANCEL)) @@ -2294,8 +1941,7 @@ private SIPRequest createRequest(String method, String topMostViaTransport) if (this.getState() == null || (this.getState().getValue() == TERMINATED_STATE && !method .equalsIgnoreCase(Request.BYE)) - || (this.isServer() - && this.getState().getValue() == EARLY_STATE && method + || (this.isServer() && this.getState().getValue() == EARLY_STATE && method .equalsIgnoreCase(Request.BYE))) throw new SipException("Dialog " + getDialogId() + " not yet established or terminated " + this.getState()); @@ -2313,55 +1959,52 @@ private SIPRequest createRequest(String method, String topMostViaTransport) cseq.setMethod(method); cseq.setSeqNumber(this.getLocalSeqNumber()); } catch (Exception ex) { - if (logger.isLoggingEnabled()) - logger.logError("Unexpected error"); + if (sipStack.isLoggingEnabled()) + sipStack.getStackLogger().logError("Unexpected error"); InternalErrorHandler.handleException(ex); } /* - * Add a via header for the outbound request based on the transport of - * the message processor. + * Add a via header for the outbound request based on the transport of the message + * processor. */ ListeningPointImpl lp = (ListeningPointImpl) this.sipProvider - .getListeningPoint(topMostViaTransport); + .getListeningPoint(sipResponse.getTopmostVia().getTransport()); if (lp == null) { - if (logger.isLoggingEnabled()) - logger.logError( + if (sipStack.isLoggingEnabled()) + sipStack.getStackLogger().logError( "Cannot find listening point for transport " - + topMostViaTransport); + + sipResponse.getTopmostVia().getTransport()); throw new SipException("Cannot find listening point for transport " - + topMostViaTransport); + + sipResponse.getTopmostVia().getTransport()); } Via via = lp.getViaHeader(); From from = new From(); - from.setAddress(this.getLocalParty()); + from.setAddress(this.localParty); To to = new To(); - to.setAddress(this.getRemoteParty()); - SIPRequest sipRequest = createRequest(sipUri, via, cseq, from, to); + to.setAddress(this.remoteParty); + SIPRequest sipRequest = sipResponse.createRequest(sipUri, via, cseq, from, to); /* - * The default contact header is obtained from the provider. The - * application can override this. + * The default contact header is obtained from the provider. The application can override + * this. * - * JvB: Should only do this for target refresh requests, ie not for BYE, - * PRACK, etc + * JvB: Should only do this for target refresh requests, ie not for BYE, PRACK, etc */ if (SIPRequest.isTargetRefresh(method)) { ContactHeader contactHeader = ((ListeningPointImpl) this.sipProvider - .getListeningPoint(lp.getTransport())) - .createContactHeader(); + .getListeningPoint(lp.getTransport())).createContactHeader(); - ((SipURI) contactHeader.getAddress().getURI()).setSecure(this - .isSecure()); + ((SipURI) contactHeader.getAddress().getURI()).setSecure(this.isSecure()); sipRequest.setHeader(contactHeader); } try { /* - * Guess of local sequence number - this is being re-set when the - * request is actually dispatched + * Guess of local sequence number - this is being re-set when the request is actually + * dispatched */ cseq = (CSeq) sipRequest.getCSeq(); cseq.setSeqNumber(this.localSequenceNumber + 1); @@ -2380,14 +2023,12 @@ private SIPRequest createRequest(String method, String topMostViaTransport) /* * RFC3261, section 12.2.1.1: * - * The URI in the To field of the request MUST be set to the remote URI - * from the dialog state. The tag in the To header field of the request - * MUST be set to the remote tag of the dialog ID. The From URI of the - * request MUST be set to the local URI from the dialog state. The tag - * in the From header field of the request MUST be set to the local tag - * of the dialog ID. If the value of the remote or local tags is null, - * the tag parameter MUST be omitted from the To or From header fields, - * respectively. + * The URI in the To field of the request MUST be set to the remote URI from the dialog + * state. The tag in the To header field of the request MUST be set to the remote tag of + * the dialog ID. The From URI of the request MUST be set to the local URI from the dialog + * state. The tag in the From header field of the request MUST be set to the local tag of + * the dialog ID. If the value of the remote or local tags is null, the tag parameter MUST + * be omitted from the To or From header fields, respectively. */ try { @@ -2412,80 +2053,6 @@ private SIPRequest createRequest(String method, String topMostViaTransport) } - /** - * Generate a request from a response. - * - * @param requestURI - * -- the request URI to assign to the request. - * @param via - * -- the Via header to assign to the request - * @param cseq - * -- the CSeq header to assign to the request - * @param from - * -- the From header to assign to the request - * @param to - * -- the To header to assign to the request - * @return -- the newly generated sip request. - */ - public SIPRequest createRequest(SipUri requestURI, Via via, CSeq cseq, - From from, To to) { - SIPRequest newRequest = new SIPRequest(); - String method = cseq.getMethod(); - - newRequest.setMethod(method); - newRequest.setRequestURI(requestURI); - this.setBranch(via, method); - newRequest.setHeader(via); - newRequest.setHeader(cseq); - newRequest.setHeader(from); - newRequest.setHeader(to); - newRequest.setHeader(getCallId()); - - try { - // JvB: all requests need a Max-Forwards - newRequest.attachHeader(new MaxForwards(70), false); - } catch (Exception d) { - - } - - if (MessageFactoryImpl.getDefaultUserAgentHeader() != null) { - newRequest - .setHeader(MessageFactoryImpl.getDefaultUserAgentHeader()); - } - return newRequest; - - } - - /** - * Sets the Via branch for CANCEL or ACK requests - * - * @param via - * @param method - * @throws ParseException - */ - private final void setBranch(Via via, String method) { - String branch; - if (method.equals(Request.ACK)) { - if (getLastResponseStatusCode().intValue() >= 300) { - branch = lastResponseTopMostVia.getBranch(); // non-2xx ACK uses - // same branch - } else { - branch = Utils.getInstance().generateBranchId(); // 2xx ACK gets - // new branch - } - } else if (method.equals(Request.CANCEL)) { - branch = lastResponseTopMostVia.getBranch(); // CANCEL uses same - // branch - } else - return; - - try { - via.setBranch(branch); - } catch (ParseException e) { - e.printStackTrace(); - } - } - /* * (non-Javadoc) * @@ -2497,72 +2064,55 @@ public void sendRequest(ClientTransaction clientTransactionId) this.sendRequest(clientTransactionId, !this.isBackToBackUserAgent); } - public void sendRequest(ClientTransaction clientTransactionId, - boolean allowInterleaving) throws TransactionDoesNotExistException, - SipException { + public void sendRequest(ClientTransaction clientTransactionId, boolean allowInterleaving) + throws TransactionDoesNotExistException, SipException { - if (clientTransactionId == null) - throw new NullPointerException("null parameter"); - - - if ((!allowInterleaving) - && clientTransactionId.getRequest().getMethod().equals( - Request.INVITE)) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("SIPDialog::sendRequest " + this + " clientTransaction = " + clientTransactionId); - } - sipStack.getReinviteExecutor().execute( - (new ReInviteSender(clientTransactionId))); - return; - } + if ((!allowInterleaving) + && clientTransactionId.getRequest().getMethod().equals(Request.INVITE)) + { + sipStack.getReinviteExecutor().execute((new ReInviteSender(clientTransactionId))); + return; + } SIPRequest dialogRequest = ((SIPClientTransaction) clientTransactionId) .getOriginalRequest(); - this.proxyAuthorizationHeader = (ProxyAuthorizationHeader) dialogRequest - .getHeader(ProxyAuthorizationHeader.NAME); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug( + "dialog.sendRequest " + " dialog = " + this + "\ndialogRequest = \n" + + dialogRequest); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug( - "SIPDialog::sendRequest:dialog.sendRequest " + " dialog = " + this - + "\ndialogRequest = \n" + dialogRequest); + if (clientTransactionId == null) + throw new NullPointerException("null parameter"); if (dialogRequest.getMethod().equals(Request.ACK) || dialogRequest.getMethod().equals(Request.CANCEL)) - throw new SipException("Bad Request Method. " - + dialogRequest.getMethod()); + throw new SipException("Bad Request Method. " + dialogRequest.getMethod()); // JvB: added, allow re-sending of BYE after challenge - if (byeSent && isTerminatedOnBye() - && !dialogRequest.getMethod().equals(Request.BYE)) { - if (logger.isLoggingEnabled()) - logger.logError( - "BYE already sent for " + this); + if (byeSent && isTerminatedOnBye() && !dialogRequest.getMethod().equals(Request.BYE)) { + if (sipStack.isLoggingEnabled()) + sipStack.getStackLogger().logError("BYE already sent for " + this); throw new SipException("Cannot send request; BYE already sent"); } if (dialogRequest.getTopmostVia() == null) { - Via via = ((SIPClientTransaction) clientTransactionId) - .getOutgoingViaHeader(); + Via via = ((SIPClientTransaction) clientTransactionId).getOutgoingViaHeader(); dialogRequest.addHeader(via); } - if (!this.getCallId().getCallId().equalsIgnoreCase( - dialogRequest.getCallId().getCallId())) { - - if (logger.isLoggingEnabled()) { - logger - .logError("CallID " + this.getCallId()); - logger.logError( - "SIPDialog::sendRequest:RequestCallID = " - + dialogRequest.getCallId().getCallId()); - logger.logError("dialog = " + this); + if (!this.getCallId().getCallId().equalsIgnoreCase(dialogRequest.getCallId().getCallId())) { + + if (sipStack.isLoggingEnabled()) { + sipStack.getStackLogger().logError("CallID " + this.getCallId()); + sipStack.getStackLogger().logError( + "RequestCallID = " + dialogRequest.getCallId().getCallId()); + sipStack.getStackLogger().logError("dialog = " + this); } throw new SipException("Bad call ID in request"); } // Set the dialog back pointer. - ((SIPClientTransaction) clientTransactionId).setDialog(this, - this.dialogId); + ((SIPClientTransaction) clientTransactionId).setDialog(this, this.dialogId); this.addTransaction((SIPTransaction) clientTransactionId); // Enable the retransmission filter for the transaction @@ -2576,25 +2126,20 @@ public void sendRequest(ClientTransaction clientTransactionId, // tag assignment is OK. if (this.getLocalTag() != null && from.getTag() != null && !from.getTag().equals(this.getLocalTag())) - throw new SipException("From tag mismatch expecting " - + this.getLocalTag()); + throw new SipException("From tag mismatch expecting " + this.getLocalTag()); if (this.getRemoteTag() != null && to.getTag() != null && !to.getTag().equals(this.getRemoteTag())) { - if (logger.isLoggingEnabled()) - this.logger.logWarning( - "SIPDialog::sendRequest:To header tag mismatch expecting " - + this.getRemoteTag()); + if (sipStack.isLoggingEnabled()) + this.sipStack.getStackLogger().logWarning( + "To header tag mismatch expecting " + this.getRemoteTag()); } /* - * The application is sending a NOTIFY before sending the response of - * the dialog. + * The application is sending a NOTIFY before sending the response of the dialog. */ - if (this.getLocalTag() == null - && dialogRequest.getMethod().equals(Request.NOTIFY)) { + if (this.getLocalTag() == null && dialogRequest.getMethod().equals(Request.NOTIFY)) { if (!this.getMethod().equals(Request.SUBSCRIBE)) - throw new SipException( - "Trying to send NOTIFY without SUBSCRIBE Dialog!"); + throw new SipException("Trying to send NOTIFY without SUBSCRIBE Dialog!"); this.setLocalTag(from.getTag()); } @@ -2612,18 +2157,18 @@ public void sendRequest(ClientTransaction clientTransactionId, } Hop hop = ((SIPClientTransaction) clientTransactionId).getNextHop(); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( - "SIPDialog::sendRequest:Using hop = " + hop.getHost() + " : " + hop.getPort()); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( + "Using hop = " + hop.getHost() + " : " + hop.getPort()); } try { - MessageChannel messageChannel = sipStack.createRawMessageChannel( - this.getSipProvider().getListeningPoint(hop.getTransport()) - .getIPAddress(), this.firstTransactionPort, hop); - - MessageChannel oldChannel = ((SIPClientTransaction) clientTransactionId) - .getMessageChannel(); + MessageChannel messageChannel = sipStack.createRawMessageChannel(this + .getSipProvider().getListeningPoint(hop.getTransport()).getIPAddress(), + this.firstTransactionPort, hop); + + MessageChannel oldChannel = ((SIPClientTransaction) + clientTransactionId).getMessageChannel(); // Remove this from the connection cache if it is in the // connection @@ -2633,40 +2178,34 @@ public void sendRequest(ClientTransaction clientTransactionId, // Not configured to cache client connections. if (!sipStack.cacheClientConnections) { oldChannel.useCount--; - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug( - "SIPDialog::sendRequest:oldChannel: useCount " + oldChannel.useCount); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug( + "oldChannel: useCount " + oldChannel.useCount); } if (messageChannel == null) { /* - * At this point the procedures of 8.1.2 and 12.2.1.1 of RFC3261 - * have been tried but the resulting next hop cannot be resolved - * (recall that the exception thrown is caught and ignored in - * SIPStack.createMessageChannel() so we end up here with a null - * messageChannel instead of the exception handler below). All - * else failing, try the outbound proxy in accordance with - * 8.1.2, in particular: This ensures that outbound proxies that - * do not add Record-Route header field values will drop out of - * the path of subsequent requests. It allows endpoints that - * cannot resolve the first Route URI to delegate that task to - * an outbound proxy. + * At this point the procedures of 8.1.2 and 12.2.1.1 of RFC3261 have been tried + * but the resulting next hop cannot be resolved (recall that the exception thrown + * is caught and ignored in SIPStack.createMessageChannel() so we end up here with + * a null messageChannel instead of the exception handler below). All else + * failing, try the outbound proxy in accordance with 8.1.2, in particular: This + * ensures that outbound proxies that do not add Record-Route header field values + * will drop out of the path of subsequent requests. It allows endpoints that + * cannot resolve the first Route URI to delegate that task to an outbound proxy. * - * if one considers the 'first Route URI' of a request - * constructed according to 12.2.1.1 to be the request URI when - * the route set is empty. + * if one considers the 'first Route URI' of a request constructed according to + * 12.2.1.1 to be the request URI when the route set is empty. */ - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug( + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug( "Null message channel using outbound proxy !"); - Hop outboundProxy = sipStack.getRouter(dialogRequest) - .getOutboundProxy(); + Hop outboundProxy = sipStack.getRouter(dialogRequest).getOutboundProxy(); if (outboundProxy == null) throw new SipException("No route found! hop=" + hop); - messageChannel = sipStack.createRawMessageChannel(this - .getSipProvider().getListeningPoint( - outboundProxy.getTransport()).getIPAddress(), + messageChannel = sipStack.createRawMessageChannel(this.getSipProvider() + .getListeningPoint(outboundProxy.getTransport()).getIPAddress(), this.firstTransactionPort, outboundProxy); if (messageChannel != null) ((SIPClientTransaction) clientTransactionId) @@ -2675,24 +2214,22 @@ public void sendRequest(ClientTransaction clientTransactionId, ((SIPClientTransaction) clientTransactionId) .setEncapsulatedChannel(messageChannel); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( - "SIPDialog::sendRequest:using message channel " + messageChannel); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("using message channel " + messageChannel); } } - if (messageChannel != null) - messageChannel.useCount++; - + if (messageChannel != null) messageChannel.useCount++; + // See if we need to release the previously mapped channel. if ((!sipStack.cacheClientConnections) && oldChannel != null && oldChannel.useCount <= 0) - oldChannel.close(); + oldChannel.close(); } catch (Exception ex) { - if (logger.isLoggingEnabled()) - logger.logException(ex); + if (sipStack.isLoggingEnabled()) + sipStack.getStackLogger().logException(ex); throw new SipException("Could not create message channel", ex); } @@ -2701,22 +2238,19 @@ public void sendRequest(ClientTransaction clientTransactionId, localSequenceNumber++; dialogRequest.getCSeq().setSeqNumber(getLocalSeqNumber()); } catch (InvalidArgumentException ex) { - logger.logFatalError(ex.getMessage()); + sipStack.getStackLogger().logFatalError(ex.getMessage()); } try { - ((SIPClientTransaction) clientTransactionId) - .sendMessage(dialogRequest); + ((SIPClientTransaction) clientTransactionId).sendMessage(dialogRequest); /* - * Note that if the BYE is rejected then the Dialog should bo back - * to the ESTABLISHED state so we only set state after successful - * send. + * Note that if the BYE is rejected then the Dialog should bo back to the ESTABLISHED + * state so we only set state after successful send. */ if (dialogRequest.getMethod().equals(Request.BYE)) { this.byeSent = true; /* - * Dialog goes into TERMINATED state as soon as BYE is sent. - * ISSUE 182. + * Dialog goes into TERMINATED state as soon as BYE is sent. ISSUE 182. */ if (isTerminatedOnBye()) { this.setState(DialogState._TERMINATED); @@ -2767,17 +2301,12 @@ public void resendAck() throws SipException { } } this.sendAck(getLastAckSent(), false); - } else { - if(logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)){ - logger.logDebug("SIPDialog::resendAck:lastAck sent is NULL hence not resending ACK"); - } } } /** - * Get the method of the request/response that resulted in the creation of - * the Dialog. + * Get the method of the request/response that resulted in the creation of the Dialog. * * @return -- the method of the dialog. */ @@ -2794,31 +2323,26 @@ public String getMethod() { protected void startTimer(SIPServerTransaction transaction) { if (this.timerTask != null && timerTask.transaction == transaction) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug( - "Timer already running for " + getDialogId()); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Timer already running for " + getDialogId()); return; } - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug( - "Starting dialog timer for " + getDialogId()); - - acquireTimerTaskSem(); - try { - if (this.timerTask != null) { - this.timerTask.transaction = transaction; - } else { - this.timerTask = new DialogTimerTask(transaction); - if ( sipStack.getTimer() != null && sipStack.getTimer().isStarted()) { - sipStack.getTimer().scheduleWithFixedDelay(timerTask, - SIPTransactionStack.BASE_TIMER_INTERVAL, - SIPTransactionStack.BASE_TIMER_INTERVAL); - } - } - } finally { - releaseTimerTaskSem(); - } - + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Starting dialog timer for " + getDialogId()); + + acquireTimerTaskSem(); + try { + if (this.timerTask != null) { + this.timerTask.transaction = transaction; + } else { + this.timerTask = new DialogTimerTask(transaction); + sipStack.getTimer().schedule(timerTask, SIPTransactionStack.BASE_TIMER_INTERVAL, + SIPTransactionStack.BASE_TIMER_INTERVAL); + } + } finally { + releaseTimerTaskSem(); + } + this.setRetransmissionTicks(); } @@ -2828,42 +2352,35 @@ protected void startTimer(SIPServerTransaction transaction) { */ protected void stopTimer() { try { - acquireTimerTaskSem(); - try { - if (this.timerTask != null) { - this.getStack().getTimer().cancel(timerTask); - this.timerTask = null; - } - if (this.earlyStateTimerTask != null) { - this.getStack().getTimer().cancel(this.earlyStateTimerTask); - this.earlyStateTimerTask = null; - } - } finally { - releaseTimerTaskSem(); - } + acquireTimerTaskSem(); + try { + if (this.timerTask != null) { + this.timerTask.cancel(); + this.timerTask = null; + } + } finally { + releaseTimerTaskSem(); + } } catch (Exception ex) { } } /* - * (non-Javadoc) Retransmissions of the reliable provisional response cease - * when a matching PRACK is received by the UA core. PRACK is like any other - * request within a dialog, and the UAS core processes it according to the - * procedures of Sections 8.2 and 12.2.2 of RFC 3261. A matching PRACK is - * defined as one within the same dialog as the response, and whose method, - * CSeq-num, and response-num in the RAck header field match, respectively, - * the method from the CSeq, the sequence number from the CSeq, and the - * sequence number from the RSeq of the reliable provisional response. + * (non-Javadoc) Retransmissions of the reliable provisional response cease when a matching + * PRACK is received by the UA core. PRACK is like any other request within a dialog, and the + * UAS core processes it according to the procedures of Sections 8.2 and 12.2.2 of RFC 3261. A + * matching PRACK is defined as one within the same dialog as the response, and whose method, + * CSeq-num, and response-num in the RAck header field match, respectively, the method from + * the CSeq, the sequence number from the CSeq, and the sequence number from the RSeq of the + * reliable provisional response. * * @see javax.sip.Dialog#createPrack(javax.sip.message.Response) */ - public Request createPrack(Response relResponse) - throws DialogDoesNotExistException, SipException { + public Request createPrack(Response relResponse) throws DialogDoesNotExistException, + SipException { - if (this.getState() == null - || this.getState().equals(DialogState.TERMINATED)) - throw new DialogDoesNotExistException( - "Dialog not initialized or terminated"); + if (this.getState() == null || this.getState().equals(DialogState.TERMINATED)) + throw new DialogDoesNotExistException("Dialog not initialized or terminated"); if ((RSeq) relResponse.getHeader(RSeqHeader.NAME) == null) { throw new SipException("Missing RSeq Header"); @@ -2871,8 +2388,8 @@ public Request createPrack(Response relResponse) try { SIPResponse sipResponse = (SIPResponse) relResponse; - SIPRequest sipRequest = this.createRequest(Request.PRACK, - sipResponse.getTopmostVia().getTransport()); + SIPRequest sipRequest = (SIPRequest) this.createRequest(Request.PRACK, + (SIPResponse) relResponse); String toHeaderTag = sipResponse.getTo().getTag(); sipRequest.setToTag(toHeaderTag); RAck rack = new RAck(); @@ -2881,9 +2398,6 @@ public Request createPrack(Response relResponse) rack.setCSequenceNumber((int) sipResponse.getCSeq().getSeqNumber()); rack.setRSequenceNumber(rseq.getSeqNumber()); sipRequest.setHeader(rack); - if (this.proxyAuthorizationHeader != null) { - sipRequest.addHeader(proxyAuthorizationHeader); - } return (Request) sipRequest; } catch (Exception ex) { InternalErrorHandler.handleException(ex); @@ -2901,75 +2415,57 @@ private void updateRequest(SIPRequest sipRequest) { sipRequest.removeHeader(RouteHeader.NAME); } if (MessageFactoryImpl.getDefaultUserAgentHeader() != null) { - sipRequest - .setHeader(MessageFactoryImpl.getDefaultUserAgentHeader()); - } - - /* - * Update the request with Proxy auth header if one has been cached. - */ - if (this.proxyAuthorizationHeader != null - && sipRequest.getHeader(ProxyAuthorizationHeader.NAME) == null) { - sipRequest.setHeader(proxyAuthorizationHeader); + sipRequest.setHeader(MessageFactoryImpl.getDefaultUserAgentHeader()); } } /* - * (non-Javadoc) The UAC core MUST generate an ACK request for each 2xx - * received from the transaction layer. The header fields of the ACK are - * constructed in the same way as for any request sent within a dialog (see - * Section 12) with the exception of the CSeq and the header fields related - * to authentication. The sequence number of the CSeq header field MUST be - * the same as the INVITE being acknowledged, but the CSeq method MUST be - * ACK. The ACK MUST contain the same credentials as the INVITE. If the 2xx - * contains an offer (based on the rules above), the ACK MUST carry an - * answer in its body. If the offer in the 2xx response is not acceptable, - * the UAC core MUST generate a valid answer in the ACK and then send a BYE + * (non-Javadoc) The UAC core MUST generate an ACK request for each 2xx received from the + * transaction layer. The header fields of the ACK are constructed in the same way as for any + * request sent within a dialog (see Section 12) with the exception of the CSeq and the header + * fields related to authentication. The sequence number of the CSeq header field MUST be the + * same as the INVITE being acknowledged, but the CSeq method MUST be ACK. The ACK MUST + * contain the same credentials as the INVITE. If the 2xx contains an offer (based on the + * rules above), the ACK MUST carry an answer in its body. If the offer in the 2xx response is + * not acceptable, the UAC core MUST generate a valid answer in the ACK and then send a BYE * immediately. * - * Note that for the case of forked requests, you can create multiple - * outgoing invites each with a different cseq and hence you need to supply - * the invite. + * Note that for the case of forked requests, you can create multiple outgoing invites each + * with a different cseq and hence you need to supply the invite. * * @see javax.sip.Dialog#createAck(long) */ - public Request createAck(long cseqno) throws InvalidArgumentException, - SipException { + public Request createAck(long cseqno) throws InvalidArgumentException, SipException { // JvB: strictly speaking it is allowed to start a dialog with // SUBSCRIBE, // then send INVITE+ACK later on if (!method.equals(Request.INVITE)) - throw new SipException("Dialog was not created with an INVITE" - + method); + throw new SipException("Dialog was not created with an INVITE" + method); if (cseqno <= 0) throw new InvalidArgumentException("bad cseq <= 0 "); else if (cseqno > ((((long) 1) << 32) - 1)) - throw new InvalidArgumentException("bad cseq > " - + ((((long) 1) << 32) - 1)); + throw new InvalidArgumentException("bad cseq > " + ((((long) 1) << 32) - 1)); - if (this.getRemoteTarget() == null) { + if (this.remoteTarget == null) { throw new SipException("Cannot create ACK - no remote Target!"); } - if (this.logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - this.logger.logDebug( - "createAck " + this + " cseqno " + cseqno); + if (this.sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + this.sipStack.getStackLogger().logDebug("createAck " + this + " cseqno " + cseqno); } // MUST ack in the same order that the OKs were received. This traps // out of order ACK sending. Old ACKs seqno's can always be ACKed. if (lastInviteOkReceived < cseqno) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - this.logger.logDebug( - "WARNING : Attempt to crete ACK without OK " + this); - this.logger.logDebug( - "LAST RESPONSE = " + this.getLastResponseStatusCode()); - } - throw new SipException( - "Dialog not yet established -- no OK response!"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + this.sipStack.getStackLogger().logDebug( + "WARNING : Attempt to crete ACK without OK " + this); + this.sipStack.getStackLogger().logDebug("LAST RESPONSE = " + this.lastResponse); + } + throw new SipException("Dialog not yet established -- no OK response!"); } try { @@ -2983,7 +2479,7 @@ else if (cseqno > ((((long) 1) << 32) - 1)) Route r = (Route) this.routeList.getFirst(); uri4transport = ((SipURI) r.getAddress().getURI()); } else { // should be !=null, checked above - uri4transport = ((SipURI) this.getRemoteTarget().getURI()); + uri4transport = ((SipURI) this.remoteTarget.getURI()); } String transport = uri4transport.getTransportParam(); @@ -3005,13 +2501,13 @@ else if (cseqno > ((((long) 1) << 32) - 1)) } } if (lp == null) { - if (logger.isLoggingEnabled()) { - logger.logError( + if (sipStack.isLoggingEnabled()) { + sipStack.getStackLogger().logError( "remoteTargetURI " + this.getRemoteTarget().getURI()); - logger.logError( + sipStack.getStackLogger().logError( "uri4transport = " + uri4transport); - logger.logError( + sipStack.getStackLogger().logError( "No LP found for transport=" + transport); } throw new SipException( @@ -3020,55 +2516,43 @@ else if (cseqno > ((((long) 1) << 32) - 1)) } SIPRequest sipRequest = new SIPRequest(); sipRequest.setMethod(Request.ACK); - sipRequest.setRequestURI((SipUri) getRemoteTarget().getURI() - .clone()); - sipRequest.setCallId(this.getCallId()); + sipRequest.setRequestURI((SipUri) getRemoteTarget().getURI().clone()); + sipRequest.setCallId(this.callIdHeader); sipRequest.setCSeq(new CSeq(cseqno, Request.ACK)); List vias = new ArrayList(); // Via via = lp.getViaHeader(); // The user may have touched the sentby for the response. // so use the via header extracted from the response for the ACK => // https://jain-sip.dev.java.net/issues/show_bug.cgi?id=205 - // strip the params from the via of the response and use the params - // from the + // strip the params from the via of the response and use the params from the // original request - Via via = this.lastResponseTopMostVia; + Via via = this.lastResponse.getTopmostVia(); via.removeParameters(); - if (originalRequest != null - && originalRequest.getTopmostVia() != null) { - NameValueList originalRequestParameters = originalRequest - .getTopmostVia().getParameters(); - if (originalRequestParameters != null - && originalRequestParameters.size() > 0) { - via.setParameters((NameValueList) originalRequestParameters - .clone()); + if (originalRequest != null && originalRequest.getTopmostVia() != null) { + NameValueList originalRequestParameters = originalRequest.getTopmostVia() + .getParameters(); + if (originalRequestParameters != null && originalRequestParameters.size() > 0) { + via.setParameters((NameValueList) originalRequestParameters.clone()); } } via.setBranch(Utils.getInstance().generateBranchId()); // new branch vias.add(via); sipRequest.setVia(vias); From from = new From(); - from.setAddress(this.getLocalParty()); + from.setAddress(this.localParty); from.setTag(this.myTag); sipRequest.setFrom(from); To to = new To(); - to.setAddress(this.getRemoteParty()); + to.setAddress(this.remoteParty); if (hisTag != null) to.setTag(this.hisTag); sipRequest.setTo(to); sipRequest.setMaxForwards(new MaxForwards(70)); if (this.originalRequest != null) { - Authorization authorization = this.originalRequest - .getAuthorization(); + Authorization authorization = this.originalRequest.getAuthorization(); if (authorization != null) sipRequest.setHeader(authorization); - // jeand : setting back the original Request to null to avoid - // keeping references around for too long - // since it is used only in the dialog setup - originalRequestRecordRouteHeaders = originalRequest - .getRecordRouteHeaders(); - originalRequest = null; } // ACKs for 2xx responses @@ -3096,20 +2580,17 @@ public SipProviderImpl getSipProvider() { } /** - * @param sipProvider - * the sipProvider to set + * @param sipProvider the sipProvider to set */ public void setSipProvider(SipProviderImpl sipProvider) { this.sipProvider = sipProvider; } /** - * Check the tags of the response against the tags of the Dialog. Return - * true if the respnse matches the tags of the dialog. We do this check wehn - * sending out a response. + * Check the tags of the response against the tags of the Dialog. Return true if the respnse + * matches the tags of the dialog. We do this check wehn sending out a response. * - * @param sipResponse - * -- the response to check. + * @param sipResponse -- the response to check. * */ public void setResponseTags(SIPResponse sipResponse) { @@ -3117,410 +2598,305 @@ public void setResponseTags(SIPResponse sipResponse) { return; } String responseFromTag = sipResponse.getFromTag(); - if (responseFromTag != null) { + if ( responseFromTag != null ) { if (responseFromTag.equals(this.getLocalTag())) { sipResponse.setToTag(this.getRemoteTag()); } else if (responseFromTag.equals(this.getRemoteTag())) { sipResponse.setToTag(this.getLocalTag()); } } else { - if (logger.isLoggingEnabled()) - logger.logWarning( - "No from tag in response! Not RFC 3261 compatible."); + if (sipStack.isLoggingEnabled()) + sipStack.getStackLogger().logWarning("No from tag in response! Not RFC 3261 compatible."); } } /** - * Set the last response for this dialog. This method is called for updating - * the dialog state when a response is either sent or received from within a - * Dialog. + * Set the last response for this dialog. This method is called for updating the dialog state + * when a response is either sent or received from within a Dialog. * - * @param transaction - * -- the transaction associated with the response - * @param sipResponse - * -- the last response to set. + * @param transaction -- the transaction associated with the response + * @param sipResponse -- the last response to set. */ - public void setLastResponse(SIPTransaction transaction, - SIPResponse sipResponse) { - this.callIdHeader = sipResponse.getCallId(); - final int statusCode = sipResponse.getStatusCode(); + public void setLastResponse(SIPTransaction transaction, SIPResponse sipResponse) { + this.callIdHeader = sipResponse.getCallId(); + int statusCode = sipResponse.getStatusCode(); if (statusCode == 100) { - if (logger.isLoggingEnabled()) - logger - .logWarning( - "Invalid status code - 100 in setLastResponse - ignoring"); + if (sipStack.isLoggingEnabled()) + sipStack.getStackLogger().logWarning( + "Invalid status code - 100 in setLastResponse - ignoring"); return; } - - if ( logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logStackTrace(); - } - // this.lastResponse = sipResponse; - try { - this.lastResponseStatusCode = Integer.valueOf(statusCode); - this.lastResponseTopMostVia = sipResponse.getTopmostVia(); - this.lastResponseMethod = sipResponse.getCSeqHeader().getMethod(); - this.lastResponseCSeqNumber = sipResponse.getCSeq().getSeqNumber(); - if (sipResponse.getToTag() != null ) { - this.lastResponseToTag = sipResponse.getToTag(); - } - if ( sipResponse.getFromTag() != null ) { - this.lastResponseFromTag = sipResponse.getFromTag(); - } - if (transaction != null) { - this.lastResponseDialogId = sipResponse.getDialogId(transaction - .isServerTransaction()); - } - this.setAssigned(); - // Adjust state of the Dialog state machine. - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( - "sipDialog: setLastResponse:" + this - + " lastResponse = " - + this.lastResponseStatusCode); - } - if (this.getState() == DialogState.TERMINATED) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger - .logDebug( - "sipDialog: setLastResponse -- dialog is terminated - ignoring "); - } - // Capture the OK response for later use in createAck - // This is handy for late arriving OK's that we want to ACK. - if (lastResponseMethod.equals(Request.INVITE) - && statusCode == 200) { - - this.lastInviteOkReceived = Math.max( - lastResponseCSeqNumber, this.lastInviteOkReceived); - } - return; - } - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logStackTrace(); - logger.logDebug( - "cseqMethod = " + lastResponseMethod); - logger.logDebug( - "dialogState = " + this.getState()); - logger.logDebug( - "method = " + this.getMethod()); - logger - .logDebug("statusCode = " + statusCode); - logger.logDebug( - "transaction = " + transaction); + + this.lastResponse = sipResponse; + this.setAssigned(); + // Adjust state of the Dialog state machine. + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( + "sipDialog: setLastResponse:" + this + " lastResponse = " + + this.lastResponse.getFirstLine()); + } + if (this.getState() == DialogState.TERMINATED) { + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( + "sipDialog: setLastResponse -- dialog is terminated - ignoring "); + } + // Capture the OK response for later use in createAck + // This is handy for late arriving OK's that we want to ACK. + if (sipResponse.getCSeq().getMethod().equals(Request.INVITE) && statusCode == 200) { + + this.lastInviteOkReceived = Math.max(sipResponse.getCSeq().getSeqNumber(), + this.lastInviteOkReceived); } - - // JvB: don't use "!this.isServer" here - // note that the transaction can be null for forked - // responses. - if (transaction == null || transaction instanceof ClientTransaction) { - if (SIPTransactionStack.isDialogCreated(lastResponseMethod)) { - // Make a final tag assignment. - if (getState() == null && (statusCode / 100 == 1)) { - /* - * Guard aginst slipping back into early state from - * confirmed state. - */ - // Was (sipResponse.getToTag() != null || - // sipStack.rfc2543Supported) - setState(SIPDialog.EARLY_STATE); - if ((sipResponse.getToTag() != null || sipStack.rfc2543Supported) - && this.getRemoteTag() == null) { - setRemoteTag(sipResponse.getToTag()); - this.setDialogId(sipResponse.getDialogId(false)); - sipStack.putDialog(this); - this.addRoute(sipResponse); - } - } else if (getState() != null - && getState().equals(DialogState.EARLY) - && statusCode / 100 == 1) { + return; + } + String cseqMethod = sipResponse.getCSeq().getMethod(); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logStackTrace(); + sipStack.getStackLogger().logDebug("cseqMethod = " + cseqMethod); + sipStack.getStackLogger().logDebug("dialogState = " + this.getState()); + sipStack.getStackLogger().logDebug("method = " + this.getMethod()); + sipStack.getStackLogger().logDebug("statusCode = " + statusCode); + sipStack.getStackLogger().logDebug("transaction = " + transaction); + } + + // JvB: don't use "!this.isServer" here + // note that the transaction can be null for forked + // responses. + if (transaction == null || transaction instanceof ClientTransaction) { + if (sipStack.isDialogCreated(cseqMethod)) { + // Make a final tag assignment. + if (getState() == null && (statusCode / 100 == 1)) { + /* + * Guard aginst slipping back into early state from confirmed state. + */ + // Was (sipResponse.getToTag() != null || sipStack.rfc2543Supported) + setState(SIPDialog.EARLY_STATE); + if ((sipResponse.getToTag() != null || sipStack.rfc2543Supported) + && this.getRemoteTag() == null) { + setRemoteTag(sipResponse.getToTag()); + this.setDialogId(sipResponse.getDialogId(false)); + sipStack.putDialog(this); + this.addRoute(sipResponse); + } + } else if (getState() != null && getState().equals(DialogState.EARLY) + && statusCode / 100 == 1) { + /* + * This case occurs for forked dialog responses. The To tag can change as a + * result of the forking. The remote target can also change as a result of the + * forking. + */ + if (cseqMethod.equals(getMethod()) && transaction != null + && (sipResponse.getToTag() != null || sipStack.rfc2543Supported)) { + setRemoteTag(sipResponse.getToTag()); + this.setDialogId(sipResponse.getDialogId(false)); + sipStack.putDialog(this); + this.addRoute(sipResponse); + } + } else if (statusCode / 100 == 2) { + // This is a dialog creating method (such as INVITE). + // 2xx response -- set the state to the confirmed + // state. To tag is MANDATORY for the response. + + // Only do this if method equals initial request! + if(sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("pendingRouteUpdateOn202Response : " + this.pendingRouteUpdateOn202Response); + } + if (cseqMethod.equals(getMethod()) + && (sipResponse.getToTag() != null || sipStack.rfc2543Supported) + && (this.getState() != DialogState.CONFIRMED || + (this.getState() == DialogState.CONFIRMED + && cseqMethod.equals(Request.SUBSCRIBE) + && this.pendingRouteUpdateOn202Response + && sipResponse.getStatusCode() == Response.ACCEPTED))) { + if (this.getState() != DialogState.CONFIRMED) { + setRemoteTag(sipResponse.getToTag()); + this.setDialogId(sipResponse.getDialogId(false)); + sipStack.putDialog(this); + this.addRoute(sipResponse); + this.setState(CONFIRMED_STATE); + } + /* - * This case occurs for forked dialog responses. The To - * tag can change as a result of the forking. The remote - * target can also change as a result of the forking. + * Note: Subscribe NOTIFY processing. The route set is computed + * only after we get the 202 response but the NOTIFY may come in before + * we get the 202 response. So we need to update the route set after + * we see the 202 despite the fact that the dialog is in the CONFIRMED + * state. We do this only on the dialog forming SUBSCRIBE an not a + * resubscribe. */ - if (lastResponseMethod.equals(getMethod()) - && transaction != null - && (sipResponse.getToTag() != null || sipStack.rfc2543Supported)) { - setRemoteTag(sipResponse.getToTag()); - this.setDialogId(sipResponse.getDialogId(false)); - sipStack.putDialog(this); - this.addRoute(sipResponse); - } - } else if (statusCode / 100 == 2) { - // This is a dialog creating method (such as INVITE). - // 2xx response -- set the state to the confirmed - // state. To tag is MANDATORY for the response. - - // Only do this if method equals initial request! - if (logger.isLoggingEnabled( - LogWriter.TRACE_DEBUG)) { - logger - .logDebug( - "pendingRouteUpdateOn202Response : " - + this.pendingRouteUpdateOn202Response); - } - if (lastResponseMethod.equals(getMethod()) - && (sipResponse.getToTag() != null || sipStack.rfc2543Supported) - && (this.getState() != DialogState.CONFIRMED || (this - .getState() == DialogState.CONFIRMED - && lastResponseMethod - .equals(Request.SUBSCRIBE) - && this.pendingRouteUpdateOn202Response && sipResponse - .getStatusCode() == Response.ACCEPTED))) { - if (this.getState() != DialogState.CONFIRMED) { - setRemoteTag(sipResponse.getToTag()); - this - .setDialogId(sipResponse - .getDialogId(false)); - sipStack.putDialog(this); - this.addRoute(sipResponse); - this.setState(CONFIRMED_STATE); - } - - /* - * Note: Subscribe NOTIFY processing. The route set - * is computed only after we get the 202 response - * but the NOTIFY may come in before we get the 202 - * response. So we need to update the route set - * after we see the 202 despite the fact that the - * dialog is in the CONFIRMED state. We do this only - * on the dialog forming SUBSCRIBE an not a - * resubscribe. - */ - - if (lastResponseMethod.equals(Request.SUBSCRIBE) - && sipResponse.getStatusCode() == Response.ACCEPTED - && this.pendingRouteUpdateOn202Response) { - setRemoteTag(sipResponse.getToTag()); - this.addRoute(sipResponse); - this.pendingRouteUpdateOn202Response = false; - } - } - - // Capture the OK response for later use in createAck - if (lastResponseMethod.equals(Request.INVITE)) { - this.lastInviteOkReceived = Math.max(sipResponse - .getCSeq().getSeqNumber(), - this.lastInviteOkReceived); + + if ( cseqMethod.equals(Request.SUBSCRIBE) + && sipResponse.getStatusCode() == Response.ACCEPTED + && this.pendingRouteUpdateOn202Response) { + setRemoteTag(sipResponse.getToTag()); + this.addRoute(sipResponse); + this.pendingRouteUpdateOn202Response = false; } + } - } else if (statusCode >= 300 - && statusCode <= 699 - && (getState() == null || (lastResponseMethod - .equals(getMethod()) && getState() - .getValue() == SIPDialog.EARLY_STATE))) { - /* - * This case handles 3xx, 4xx, 5xx and 6xx responses. - * RFC 3261 Section 12.3 - dialog termination. - * Independent of the method, if a request outside of a - * dialog generates a non-2xx final response, any early - * dialogs created through provisional responses to that - * request are terminated. - */ - setState(SIPDialog.TERMINATED_STATE); + // Capture the OK response for later use in createAck + if (cseqMethod.equals(Request.INVITE)) { + this.lastInviteOkReceived = Math.max(sipResponse.getCSeq().getSeqNumber(), + this.lastInviteOkReceived); } + } else if (statusCode >= 300 + && statusCode <= 699 + && (getState() == null || (cseqMethod.equals(getMethod()) && getState() + .getValue() == SIPDialog.EARLY_STATE))) { /* - * This code is in support of "proxy" servers that are - * constructed as back to back user agents. This could be a - * dialog in the middle of the call setup path somewhere. - * Hence the incoming invite has record route headers in it. - * The response will have additional record route headers. - * However, for this dialog only the downstream record route - * headers matter. Ideally proxy servers should not be - * constructed as Back to Back User Agents. Remove all the - * record routes that are present in the incoming INVITE so - * you only have the downstream Route headers present in the - * dialog. Note that for an endpoint - you will have no - * record route headers present in the original request so - * the loop will not execute. + * This case handles 3xx, 4xx, 5xx and 6xx responses. RFC 3261 Section 12.3 - + * dialog termination. Independent of the method, if a request outside of a + * dialog generates a non-2xx final response, any early dialogs created + * through provisional responses to that request are terminated. */ - if (this.getState() != DialogState.CONFIRMED - && this.getState() != DialogState.TERMINATED) { - if (getOriginalRequestRecordRouteHeaders() != null) { - ListIterator it = getOriginalRequestRecordRouteHeaders() - .listIterator( - getOriginalRequestRecordRouteHeaders() - .size()); + setState(SIPDialog.TERMINATED_STATE); + } + + /* + * This code is in support of "proxy" servers that are constructed as back to back + * user agents. This could be a dialog in the middle of the call setup path + * somewhere. Hence the incoming invite has record route headers in it. The + * response will have additional record route headers. However, for this dialog + * only the downstream record route headers matter. Ideally proxy servers should + * not be constructed as Back to Back User Agents. Remove all the record routes + * that are present in the incoming INVITE so you only have the downstream Route + * headers present in the dialog. Note that for an endpoint - you will have no + * record route headers present in the original request so the loop will not + * execute. + */ + if ( this.getState() != DialogState.CONFIRMED && this.getState() != DialogState.TERMINATED ) { + if (originalRequest != null) { + RecordRouteList rrList = originalRequest.getRecordRouteHeaders(); + if (rrList != null) { + ListIterator it = rrList.listIterator(rrList.size()); while (it.hasPrevious()) { RecordRoute rr = (RecordRoute) it.previous(); Route route = (Route) routeList.getFirst(); - if (route != null - && rr.getAddress().equals( - route.getAddress())) { + if (route != null && rr.getAddress().equals(route.getAddress())) { routeList.removeFirst(); } else break; } } } - - } else if (lastResponseMethod.equals(Request.NOTIFY) - && (this.getMethod().equals(Request.SUBSCRIBE) || this - .getMethod().equals(Request.REFER)) - && sipResponse.getStatusCode() / 100 == 2 - && this.getState() == null) { - // This is a notify response. - this.setDialogId(sipResponse.getDialogId(true)); - sipStack.putDialog(this); - this.setState(SIPDialog.CONFIRMED_STATE); - - } else if (lastResponseMethod.equals(Request.BYE) - && statusCode / 100 == 2 && isTerminatedOnBye()) { - // Dialog will be terminated when the transction is - // terminated. - setState(SIPDialog.TERMINATED_STATE); } - } else { - // Processing Server Dialog. - if (lastResponseMethod.equals(Request.BYE) - && statusCode / 100 == 2 && this.isTerminatedOnBye()) { - /* - * Only transition to terminated state when 200 OK is - * returned for the BYE. Other status codes just result in - * leaving the state in COMPLETED state. - */ - this.setState(SIPDialog.TERMINATED_STATE); - } else { - boolean doPutDialog = false; - - if (getLocalTag() == null - && sipResponse.getTo().getTag() != null - && SIPTransactionStack.isDialogCreated(lastResponseMethod) - && lastResponseMethod.equals(getMethod())) { - setLocalTag(sipResponse.getTo().getTag()); - doPutDialog = true; - } + } else if (cseqMethod.equals(Request.NOTIFY) + && (this.getMethod().equals(Request.SUBSCRIBE) || this.getMethod().equals( + Request.REFER)) && sipResponse.getStatusCode() / 100 == 2 + && this.getState() == null) { + // This is a notify response. + this.setDialogId(sipResponse.getDialogId(true)); + sipStack.putDialog(this); + this.setState(SIPDialog.CONFIRMED_STATE); - if (statusCode / 100 != 2) { - if (statusCode / 100 == 1) { - if (doPutDialog) { + } else if (cseqMethod.equals(Request.BYE) && statusCode / 100 == 2 + && isTerminatedOnBye()) { + // Dialog will be terminated when the transction is terminated. + setState(SIPDialog.TERMINATED_STATE); + } + } else { + // Processing Server Dialog. - setState(SIPDialog.EARLY_STATE); - this.setDialogId(sipResponse.getDialogId(true)); - sipStack.putDialog(this); - } - } else { - /* - * RFC 3265 chapter 3.1.4.1 "Non-200 class final - * responses indicate that no subscription or dialog - * has been created, and no subsequent NOTIFY - * message will be sent. All non-200 class" + - * responses (with the exception of "489", described - * herein) have the same meanings and handling as - * described in SIP" - */ - // Bug Fix by Jens tinfors - // see - // https://jain-sip.dev.java.net/servlets/ReadMsg?list=users&msgNo=797 - if (statusCode == 489 - && (lastResponseMethod - .equals(Request.NOTIFY) || lastResponseMethod - .equals(Request.SUBSCRIBE))) { - if (logger - .isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger - .logDebug( - "RFC 3265 : Not setting dialog to TERMINATED for 489"); - } else { - // baranowb: simplest fix to - // https://jain-sip.dev.java.net/issues/show_bug.cgi?id=175 - // application is responsible for terminating in - // this case - // see rfc 5057 for better explanation - if (!this.isReInvite() - && getState() != DialogState.CONFIRMED) { - this.setState(SIPDialog.TERMINATED_STATE); - } - } - } + if (cseqMethod.equals(Request.BYE) && statusCode / 100 == 2 + && this.isTerminatedOnBye()) { + /* + * Only transition to terminated state when 200 OK is returned for the BYE. Other + * status codes just result in leaving the state in COMPLETED state. + */ + this.setState(SIPDialog.TERMINATED_STATE); + } else { + boolean doPutDialog = false; - } else { + if (getLocalTag() == null && sipResponse.getTo().getTag() != null + && sipStack.isDialogCreated(cseqMethod) && cseqMethod.equals(getMethod())) { + setLocalTag(sipResponse.getTo().getTag()); - /* - * JvB: RFC4235 says that when sending 2xx on UAS side, - * state should move to CONFIRMED - */ - if (this.dialogState <= SIPDialog.EARLY_STATE - && (lastResponseMethod.equals(Request.INVITE) - || lastResponseMethod - .equals(Request.SUBSCRIBE) || lastResponseMethod - .equals(Request.REFER))) { - this.setState(SIPDialog.CONFIRMED_STATE); - } + doPutDialog = true; + } + if (statusCode / 100 != 2) { + if (statusCode / 100 == 1) { if (doPutDialog) { + + setState(SIPDialog.EARLY_STATE); this.setDialogId(sipResponse.getDialogId(true)); sipStack.putDialog(this); } + } else { /* - * We put the dialog into the table. We must wait for - * ACK before re-INVITE is sent. + * RFC 3265 chapter 3.1.4.1 "Non-200 class final responses indicate that + * no subscription or dialog has been created, and no subsequent NOTIFY + * message will be sent. All non-200 class" + responses (with the + * exception of "489", described herein) have the same meanings and + * handling as described in SIP" */ + // Bug Fix by Jens tinfors + // see https://jain-sip.dev.java.net/servlets/ReadMsg?list=users&msgNo=797 + if (statusCode == 489 + && (cseqMethod.equals(Request.NOTIFY) || cseqMethod + .equals(Request.SUBSCRIBE))) { + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug( + "RFC 3265 : Not setting dialog to TERMINATED for 489"); + } else { + // baranowb: simplest fix to + // https://jain-sip.dev.java.net/issues/show_bug.cgi?id=175 + // application is responsible for terminating in this case + // see rfc 5057 for better explanation + if (!this.isReInvite() && getState() != DialogState.CONFIRMED) { + this.setState(SIPDialog.TERMINATED_STATE); + } + } + } - if (transaction.getInternalState() != TransactionState._TERMINATED - && sipResponse.getStatusCode() == Response.OK - && lastResponseMethod.equals(Request.INVITE) - && this.isBackToBackUserAgent) { + } else { + + /* + * JvB: RFC4235 says that when sending 2xx on UAS side, state should move to + * CONFIRMED + */ + if (this.dialogState <= SIPDialog.EARLY_STATE + && (cseqMethod.equals(Request.INVITE) + || cseqMethod.equals(Request.SUBSCRIBE) || cseqMethod + .equals(Request.REFER))) { + this.setState(SIPDialog.CONFIRMED_STATE); + } + + if (doPutDialog) { + this.setDialogId(sipResponse.getDialogId(true)); + sipStack.putDialog(this); + } + /* + * We put the dialog into the table. We must wait for ACK before re-INVITE is + * sent. + */ + + if (transaction.getState() != TransactionState.TERMINATED + && sipResponse.getStatusCode() == Response.OK + && cseqMethod.equals(Request.INVITE) + && this.isBackToBackUserAgent) { // - // Acquire the flag for re-INVITE so that we cannot - // re-INVITE before - // ACK is received. + // Acquire the flag for re-INVITE so that we cannot re-INVITE before + // ACK is received. // if (!this.takeAckSem()) { - if (logger - .isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger - .logDebug( - "Delete dialog -- cannot acquire ackSem"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( + "Delete dialog -- cannot acquire ackSem"); } - this - .raiseErrorEvent(SIPDialogErrorEvent.DIALOG_ERROR_INTERNAL_COULD_NOT_TAKE_ACK_SEM); - logger - .logError( - "IntenalError : Ack Sem already acquired "); + this.raiseErrorEvent(SIPDialogErrorEvent.DIALOG_ERROR_INTERNAL_COULD_NOT_TAKE_ACK_SEM); + this.sipStack.getStackLogger().logError("IntenalError : Ack Sem already acquired "); return; } - - } - - + } + } - } - } finally { - if (sipResponse.getCSeq().getMethod().equals(Request.INVITE) - && transaction instanceof ClientTransaction && this.getState() != DialogState.TERMINATED) { - this.acquireTimerTaskSem(); - try { - if (this.getState() == DialogState.EARLY) { - if (this.earlyStateTimerTask != null) { - sipStack.getTimer() - .cancel(this.earlyStateTimerTask); - } - logger.logDebug( - "EarlyStateTimerTask craeted " - + this.earlyDialogTimeout * 1000); - this.earlyStateTimerTask = new EarlyStateTimerTask(); - if (sipStack.getTimer() != null && sipStack.getTimer().isStarted() ) { - sipStack.getTimer().schedule(this.earlyStateTimerTask, - this.earlyDialogTimeout * 1000); - } - } else { - if (this.earlyStateTimerTask != null) { - sipStack.getTimer() - .cancel(this.earlyStateTimerTask); - this.earlyStateTimerTask = null; - } - } - } finally { - this.releaseTimerTaskSem(); - } - } } } @@ -3528,19 +2904,14 @@ && getState() != DialogState.CONFIRMED) { /** * Start the retransmit timer. * - * @param sipServerTx - * -- server transaction on which the response was sent - * @param response - * - response that was sent. + * @param sipServerTx -- server transaction on which the response was sent + * @param response - response that was sent. */ - public void startRetransmitTimer(SIPServerTransaction sipServerTx, - Response response) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( - "startRetransmitTimer() " + response.getStatusCode() - + " method " + sipServerTx.getMethod()); - } - if (sipServerTx.isInviteTransaction() + public void startRetransmitTimer(SIPServerTransaction sipServerTx, Response response) { + if (sipStack.getStackLogger().isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("startRetransmitTimer() "+ response.getStatusCode() + " method " + sipServerTx.getRequest().getMethod() ); + } + if (sipServerTx.getRequest().getMethod().equals(Request.INVITE) && response.getStatusCode() / 100 == 2) { this.startTimer(sipServerTx); } @@ -3549,32 +2920,31 @@ public void startRetransmitTimer(SIPServerTransaction sipServerTx, /** * @return -- the last response associated with the dialog. */ - // public SIPResponse getLastResponse() { - // - // return lastResponse; - // } + public SIPResponse getLastResponse() { + + return lastResponse; + } + /** * Do taget refresh dialog state updates. * - * RFC 3261: Requests within a dialog MAY contain Record-Route and Contact - * header fields. However, these requests do not cause the dialog's route - * set to be modified, although they may modify the remote target URI. - * Specifically, requests that are not target refresh requests do not modify - * the dialog's remote target URI, and requests that are target refresh + * RFC 3261: Requests within a dialog MAY contain Record-Route and Contact header fields. + * However, these requests do not cause the dialog's route set to be modified, although they + * may modify the remote target URI. Specifically, requests that are not target refresh + * requests do not modify the dialog's remote target URI, and requests that are target refresh * requests do. For dialogs that have been established with an * - * INVITE, the only target refresh request defined is re-INVITE (see Section - * 14). Other extensions may define different target refresh requests for - * dialogs established in other ways. + * INVITE, the only target refresh request defined is re-INVITE (see Section 14). Other + * extensions may define different target refresh requests for dialogs established in other + * ways. */ private void doTargetRefresh(SIPMessage sipMessage) { ContactList contactList = sipMessage.getContactHeaders(); /* - * INVITE is the target refresh for INVITE dialogs. SUBSCRIBE is the - * target refresh for subscribe dialogs from the client side. This - * modifies the remote target URI potentially + * INVITE is the target refresh for INVITE dialogs. SUBSCRIBE is the target refresh for + * subscribe dialogs from the client side. This modifies the remote target URI potentially */ if (contactList != null) { @@ -3607,11 +2977,10 @@ public Response createReliableProvisionalResponse(int statusCode) } /* - * A UAS MUST NOT attempt to send a 100 (Trying) response reliably. Only - * provisional responses numbered 101 to 199 may be sent reliably. If - * the request did not include either a Supported or Require header - * field indicating this feature, the UAS MUST NOT send the provisional - * response reliably. + * A UAS MUST NOT attempt to send a 100 (Trying) response reliably. Only provisional + * responses numbered 101 to 199 may be sent reliably. If the request did not include + * either a Supported or Require header field indicating this feature, the UAS MUST NOT + * send the provisional response reliably. */ if (statusCode <= 100 || statusCode > 199) throw new InvalidArgumentException("Bad status code "); @@ -3623,22 +2992,20 @@ public Response createReliableProvisionalResponse(int statusCode) if (list == null || !optionPresent(list, "100rel")) { list = request.getHeaders(RequireHeader.NAME); if (list == null || !optionPresent(list, "100rel")) { - throw new SipException( - "No Supported/Require 100rel header in the request"); + throw new SipException("No Supported/Require 100rel header in the request"); } } SIPResponse response = request.createResponse(statusCode); /* - * The provisional response to be sent reliably is constructed by the - * UAS core according to the procedures of Section 8.2.6 of RFC 3261. In - * addition, it MUST contain a Require header field containing the - * option tag 100rel, and MUST include an RSeq header field. The value - * of the header field for the first reliable provisional response in a - * transaction MUST be between 1 and 231 - 1. It is RECOMMENDED that it - * be chosen uniformly in this range. The RSeq numbering space is within - * a single transaction. This means that provisional responses for - * different requests MAY use the same values for the RSeq number. + * The provisional response to be sent reliably is constructed by the UAS core according + * to the procedures of Section 8.2.6 of RFC 3261. In addition, it MUST contain a Require + * header field containing the option tag 100rel, and MUST include an RSeq header field. + * The value of the header field for the first reliable provisional response in a + * transaction MUST be between 1 and 2**31 - 1. It is RECOMMENDED that it be chosen + * uniformly in this range. The RSeq numbering space is within a single transaction. This + * means that provisional responses for different requests MAY use the same values for the + * RSeq number. */ Require require = new Require(); try { @@ -3649,15 +3016,13 @@ public Response createReliableProvisionalResponse(int statusCode) response.addHeader(require); RSeq rseq = new RSeq(); /* - * set an arbitrary sequence number. This is actually set when the - * response is sent out + * set an arbitrary sequence number. This is actually set when the response is sent out */ rseq.setSeqNumber(1L); /* - * Copy the record route headers from the request to the response ( - * Issue 160 ). Note that other 1xx headers do not get their Record - * Route headers copied over but reliable provisional responses do. See - * RFC 3262 Table 2. + * Copy the record route headers from the request to the response ( Issue 160 ). Note that + * other 1xx headers do not get their Record Route headers copied over but reliable + * provisional responses do. See RFC 3262 Table 2. */ RecordRouteList rrl = request.getRecordRouteHeaders(); if (rrl != null) { @@ -3672,65 +3037,61 @@ public Response createReliableProvisionalResponse(int statusCode) * Do the processing necessary for the PRACK * * @param prackRequest - * @return true if this is the first time the tx has seen the prack ( and - * hence needs to be passed up to the TU) + * @return true if this is the first time the tx has seen the prack ( and hence needs to be + * passed up to the TU) */ public boolean handlePrack(SIPRequest prackRequest) { /* - * The RAck header is sent in a PRACK request to support reliability of - * provisional responses. It contains two numbers and a method tag. The - * first number is the value from the RSeq header in the provisional - * response that is being acknowledged. The next number, and the method, - * are copied from the CSeq in the response that is being acknowledged. - * The method name in the RAck header is case sensitive. + * The RAck header is sent in a PRACK request to support reliability of provisional + * responses. It contains two numbers and a method tag. The first number is the value from + * the RSeq header in the provisional response that is being acknowledged. The next + * number, and the method, are copied from the CSeq in the response that is being + * acknowledged. The method name in the RAck header is case sensitive. */ if (!this.isServer()) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug( - "Dropping Prack -- not a server Dialog"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Dropping Prack -- not a server Dialog"); return false; } SIPServerTransaction sipServerTransaction = (SIPServerTransaction) this - .getFirstTransactionInt(); - byte[] sipResponse = sipServerTransaction - .getReliableProvisionalResponse(); + .getFirstTransaction(); + SIPResponse sipResponse = sipServerTransaction.getReliableProvisionalResponse(); if (sipResponse == null) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug( - "Dropping Prack -- ReliableResponse not found"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger() + .logDebug("Dropping Prack -- ReliableResponse not found"); return false; } RAck rack = (RAck) prackRequest.getHeader(RAckHeader.NAME); if (rack == null) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug( - "Dropping Prack -- rack header not found"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Dropping Prack -- rack header not found"); return false; } + CSeq cseq = (CSeq) sipResponse.getCSeq(); - if (!rack.getMethod().equals( - sipServerTransaction.getPendingReliableResponseMethod())) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug( + if (!rack.getMethod().equals(cseq.getMethod())) { + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug( "Dropping Prack -- CSeq Header does not match PRACK"); return false; } - if (rack.getCSeqNumberLong() != sipServerTransaction - .getPendingReliableCSeqNumber()) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug( + if (rack.getCSeqNumberLong() != cseq.getSeqNumber()) { + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug( "Dropping Prack -- CSeq Header does not match PRACK"); return false; } - if (rack.getRSequenceNumber() != sipServerTransaction - .getPendingReliableRSeqNumber()) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug( + RSeq rseq = (RSeq) sipResponse.getHeader(RSeqHeader.NAME); + + if (rack.getRSequenceNumber() != rseq.getSeqNumber()) { + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug( "Dropping Prack -- RSeq Header does not match PRACK"); return false; } @@ -3741,12 +3102,9 @@ public boolean handlePrack(SIPRequest prackRequest) { /* * (non-Javadoc) * - * @see - * javax.sip.Dialog#sendReliableProvisionalResponse(javax.sip.message.Response - * ) + * @see javax.sip.Dialog#sendReliableProvisionalResponse(javax.sip.message.Response) */ - public void sendReliableProvisionalResponse(Response relResponse) - throws SipException { + public void sendReliableProvisionalResponse(Response relResponse) throws SipException { if (!this.isServer()) { throw new SipException("Not a Server Dialog"); } @@ -3754,8 +3112,7 @@ public void sendReliableProvisionalResponse(Response relResponse) SIPResponse sipResponse = (SIPResponse) relResponse; if (relResponse.getStatusCode() == 100) - throw new SipException( - "Cannot send 100 as a reliable provisional response"); + throw new SipException("Cannot send 100 as a reliable provisional response"); if (relResponse.getStatusCode() / 100 > 2) throw new SipException( @@ -3768,8 +3125,7 @@ public void sendReliableProvisionalResponse(Response relResponse) throw new SipException( "Badly formatted response -- To tag mandatory for Reliable Provisional Response"); } - ListIterator requireList = (ListIterator) relResponse - .getHeaders(RequireHeader.NAME); + ListIterator requireList = (ListIterator) relResponse.getHeaders(RequireHeader.NAME); boolean found = false; if (requireList != null) { @@ -3785,19 +3141,18 @@ public void sendReliableProvisionalResponse(Response relResponse) if (!found) { Require require = new Require("100rel"); relResponse.addHeader(require); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger - .logDebug( - "Require header with optionTag 100rel is needed -- adding one"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( + "Require header with optionTag 100rel is needed -- adding one"); } } SIPServerTransaction serverTransaction = (SIPServerTransaction) this - .getFirstTransactionInt(); + .getFirstTransaction(); /* - * put into the dialog table before sending the response so as to avoid - * race condition with PRACK + * put into the dialog table before sending the response so as to avoid race condition + * with PRACK */ this.setLastResponse(serverTransaction, sipResponse); @@ -3820,8 +3175,8 @@ public void terminateOnBye(boolean terminateFlag) throws SipException { } /** - * Set the "assigned" flag to true. We do this when inserting the dialog - * into the dialog table of the stack. + * Set the "assigned" flag to true. We do this when inserting the dialog into the dialog table + * of the stack. * */ public void setAssigned() { @@ -3838,154 +3193,136 @@ public boolean isAssigned() { } /** - * Get the contact header that the owner of this dialog assigned. Subsequent - * Requests are considered to belong to the dialog if the dialog identifier - * matches and the contact header matches the ip address and port on which - * the request is received. + * Get the contact header that the owner of this dialog assigned. Subsequent Requests are + * considered to belong to the dialog if the dialog identifier matches and the contact header + * matches the ip address and port on which the request is received. * * @return contact header belonging to the dialog. */ public Contact getMyContactHeader() { - if (contactHeader == null && contactHeaderStringified != null) { - try { - this.contactHeader = (Contact) new ContactParser( - contactHeaderStringified).parse(); - } catch (ParseException e) { - logger.logError( - "error reparsing the contact header", e); - } - } - return contactHeader; + return contactHeader; } /** * Do the necessary processing to handle an ACK directed at this Dialog. * - * @param ackTransaction - * -- the ACK transaction that was directed at this dialog. - * @return -- true if the ACK was successfully consumed by the Dialog and - * resulted in the dialog state being changed. + * @param ackTransaction -- the ACK transaction that was directed at this dialog. + * @return -- true if the ACK was successfully consumed by the Dialog and resulted in the + * dialog state being changed. */ public boolean handleAck(SIPServerTransaction ackTransaction) { - // SIPRequest sipRequest = ackTransaction.getOriginalRequest(); + SIPRequest sipRequest = ackTransaction.getOriginalRequest(); - if (isAckSeen() && getRemoteSeqNumber() == ackTransaction.getCSeq()) { + if (isAckSeen() && getRemoteSeqNumber() == sipRequest.getCSeq().getSeqNumber()) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( - "ACK already seen by dialog -- dropping Ack" - + " retransmission"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( + "ACK already seen by dialog -- dropping Ack" + " retransmission"); } acquireTimerTaskSem(); try { - if (this.timerTask != null) { - this.getStack().getTimer().cancel(timerTask); - this.timerTask = null; - } + if (this.timerTask != null) { + this.timerTask.cancel(); + this.timerTask = null; + } } finally { - releaseTimerTaskSem(); - } + releaseTimerTaskSem(); + } return false; } else if (this.getState() == DialogState.TERMINATED) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug( - "Dialog is terminated -- dropping ACK"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Dialog is terminated -- dropping ACK"); return false; } else { - if (lastResponseStatusCode != null - && lastResponseStatusCode.intValue() / 100 == 2 - && lastResponseMethod.equals(Request.INVITE) - && lastResponseCSeqNumber == ackTransaction.getCSeq()) { + /* + * This could be a re-invite processing. check to see if the ack matches with the last + * transaction. s + */ + + SIPServerTransaction tr = getInviteTransaction(); - ackTransaction.setDialog(this, lastResponseDialogId); + SIPResponse sipResponse = (tr != null ? tr.getLastResponse() : null); + + // Idiot check for sending ACK from the wrong side! + if (tr != null + && sipResponse != null + && sipResponse.getStatusCode() / 100 == 2 + && sipResponse.getCSeq().getMethod().equals(Request.INVITE) + && sipResponse.getCSeq().getSeqNumber() == sipRequest.getCSeq() + .getSeqNumber()) { + + ackTransaction.setDialog(this, sipResponse.getDialogId(false)); /* * record that we already saw an ACK for this dialog. */ - ackReceived(ackTransaction.getCSeq()); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug( - "ACK for 2XX response --- sending to TU "); + + ackReceived(sipRequest); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("ACK for 2XX response --- sending to TU "); return true; } else { - /* - * This happens when the ACK is re-transmitted and arrives too - * late to be processed. + /* + * This happens when the ACK is re-transmitted and arrives too late to be + * processed. */ - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug( - " INVITE transaction not found"); - if ( this.isBackToBackUserAgent() ) { - this.releaseAckSem(); - } - return true; - + + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug( + " INVITE transaction not found -- Discarding ACK"); + return false; } } } + void setEarlyDialogId(String earlyDialogId) { + this.earlyDialogId = earlyDialogId; + } + String getEarlyDialogId() { return earlyDialogId; } /** - * Release the semaphore for ACK processing so the next re-INVITE may - * proceed. + * Release the semaphore for ACK processing so the next re-INVITE may proceed. */ void releaseAckSem() { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger - .logDebug("releaseAckSem-enter]]" + this + " sem=" + this.ackSem + " b2bua=" + this.isBackToBackUserAgent); - logger.logStackTrace(); - } if (this.isBackToBackUserAgent) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger - .logDebug("releaseAckSem]]" + this + " sem=" + this.ackSem); - logger.logStackTrace(); - } - if (this.ackSem.availablePermits() == 0 ) { - this.ackSem.release(); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger - .logDebug("releaseAckSem]]" + this + " sem=" + this.ackSem); - } + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("releaseAckSem]" + this); } + this.ackSem.release(); } + } boolean takeAckSem() { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("[takeAckSem " + this + " sem=" + this.ackSem); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("[takeAckSem " + this); } try { - if (!this.ackSem.tryAcquire(2, TimeUnit.SECONDS)) { - if (logger.isLoggingEnabled()) { - logger.logError( - "Cannot aquire ACK semaphore "); + if (sipStack.isLoggingEnabled()) { + sipStack.getStackLogger().logError("Cannot aquire ACK semaphore"); } - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( - "Semaphore previously acquired at " - + this.stackTrace + " sem=" + this.ackSem); - logger.logStackTrace(); - + if ( sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG) ) { + sipStack.getStackLogger().logDebug("Semaphore previously acquired at " + this.stackTrace); + sipStack.getStackLogger().logStackTrace(); + } return false; } - - if (logger.isLoggingEnabled( - StackLogger.TRACE_DEBUG)) { - + + if ( sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG) ) { + this.recordStackTrace(); } - + } catch (InterruptedException ex) { - logger.logError("Cannot aquire ACK semaphore"); + sipStack.getStackLogger().logError("Cannot aquire ACK semaphore"); return false; } @@ -3994,14 +3331,26 @@ boolean takeAckSem() { } /** - * @param lastAckSent - * the lastAckSent to set + * @param lastAckReceived the lastAckReceived to set + */ + private void setLastAckReceived(SIPRequest lastAckReceived) { + this.lastAckReceived = lastAckReceived; + } + + /** + * @return the lastAckReceived + */ + protected SIPRequest getLastAckReceived() { + return lastAckReceived; + } + + /** + * @param lastAckSent the lastAckSent to set */ private void setLastAckSent(SIPRequest lastAckSent) { this.lastAckSent = lastAckSent; - this.lastAckSent.setTransaction(null); // null out the associated Tx (release memory) } - + /** * @return true if an ack was ever sent for this Dialog */ @@ -4009,264 +3358,109 @@ public boolean isAtleastOneAckSent() { return this.isAcknowledged; } + + public boolean isBackToBackUserAgent() { return this.isBackToBackUserAgent; } - + public synchronized void doDeferredDeleteIfNoAckSent(long seqno) { - if (sipStack.getTimer() == null) { - this.setState(TERMINATED_STATE); - } else if (dialogDeleteIfNoAckSentTask == null) { - // Delete the transaction after the max ack timeout. - dialogDeleteIfNoAckSentTask = new DialogDeleteIfNoAckSentTask(seqno); - if (sipStack.getTimer() != null && sipStack.getTimer().isStarted()) { - sipStack.getTimer().schedule( - dialogDeleteIfNoAckSentTask, - sipStack.getAckTimeoutFactor() - * SIPTransactionStack.BASE_TIMER_INTERVAL); - } - } - } + if (sipStack.getTimer() == null) { + this.setState(TERMINATED_STATE); + } else if(dialogDeleteIfNoAckSentTask == null){ + // Delete the transaction after the max ack timeout. + dialogDeleteIfNoAckSentTask = new DialogDeleteIfNoAckSentTask(seqno); + sipStack.getTimer().schedule( + dialogDeleteIfNoAckSentTask, + sipStack.getAckTimeoutFactor() + * SIPTransactionStack.BASE_TIMER_INTERVAL); + } + } /* * (non-Javadoc) - * * @see gov.nist.javax.sip.DialogExt#setBackToBackUserAgent(boolean) */ public void setBackToBackUserAgent() { - this.isBackToBackUserAgent = true; - } - - /** - * @return the eventHeader - */ - EventHeader getEventHeader() { - return eventHeader; - } - - /** - * @param eventHeader - * the eventHeader to set - */ - void setEventHeader(EventHeader eventHeader) { - this.eventHeader = eventHeader; - } - - /** - * @param serverTransactionFlag - * the serverTransactionFlag to set - */ - void setServerTransactionFlag(boolean serverTransactionFlag) { - this.serverTransactionFlag = serverTransactionFlag; - } - - /** - * @param reInviteFlag - * the reinviteFlag to set - */ - protected void setReInviteFlag(boolean reInviteFlag) { - this.reInviteFlag = reInviteFlag; - } - - public boolean isSequnceNumberValidation() { - return this.sequenceNumberValidation; - } - + this.isBackToBackUserAgent = true; + } + + /** + * @return the eventHeader + */ + EventHeader getEventHeader() { + return eventHeader; + } + + /** + * @param eventHeader the eventHeader to set + */ + void setEventHeader(EventHeader eventHeader) { + this.eventHeader = eventHeader; + } + + /** + * @param serverTransactionFlag the serverTransactionFlag to set + */ + void setServerTransactionFlag(boolean serverTransactionFlag) { + this.serverTransactionFlag = serverTransactionFlag; + } + + /** + * @param reInviteFlag the reinviteFlag to set + */ + void setReInviteFlag(boolean reInviteFlag) { + this.reInviteFlag = reInviteFlag; + } + + + public boolean isSequnceNumberValidation() { + return this.sequenceNumberValidation; + } + public void disableSequenceNumberValidation() { this.sequenceNumberValidation = false; } - + + public void acquireTimerTaskSem() { - boolean acquired = false; + boolean acquired = false; try { acquired = this.timerTaskLock.tryAcquire(10, TimeUnit.SECONDS); - } catch (InterruptedException ex) { + } catch ( InterruptedException ex) { acquired = false; } - if (!acquired) { - throw new IllegalStateException( - "Impossible to acquire the dialog timer task lock"); + if(!acquired) { + throw new IllegalStateException("Impossible to acquire the dialog timer task lock"); } } - + public void releaseTimerTaskSem() { this.timerTaskLock.release(); } - public String getMergeId() { - return this.firstTransactionMergeId; - } - - public void setPendingRouteUpdateOn202Response(SIPRequest sipRequest) { - this.pendingRouteUpdateOn202Response = true; - String toTag = sipRequest.getToHeader().getTag(); - if (toTag != null) { - this.setRemoteTag(toTag); - } - - } - - public String getLastResponseMethod() { - return lastResponseMethod; - } - - public Integer getLastResponseStatusCode() { - return lastResponseStatusCode; - } - - public long getLastResponseCSeqNumber() { - return lastResponseCSeqNumber; - } - - // jeand cleanup the dialog from the data not needed anymore upon receiving - // or sending an ACK - // to save on mem - protected void cleanUpOnAck() { - if (isReleaseReferences()) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( - "cleanupOnAck : " + getDialogId()); - } - if (originalRequest != null) { - if (originalRequestRecordRouteHeaders != null) { - originalRequestRecordRouteHeadersString = originalRequestRecordRouteHeaders - .toString(); - } - originalRequestRecordRouteHeaders = null; - originalRequest = null; - } - if (firstTransaction != null) { - if (firstTransaction.getOriginalRequest() != null) { - firstTransaction.getOriginalRequest().cleanUp(); - } - firstTransaction = null; - } - if (lastTransaction != null) { - if (lastTransaction.getOriginalRequest() != null) { - lastTransaction.getOriginalRequest().cleanUp(); - } - lastTransaction = null; - } - if (callIdHeader != null) { - callIdHeaderString = callIdHeader.toString(); - callIdHeader = null; - } - if (contactHeader != null) { - contactHeaderStringified = contactHeader.toString(); - contactHeader = null; - } - if (remoteTarget != null) { - remoteTargetStringified = remoteTarget.toString(); - remoteTarget = null; - } - if (remoteParty != null) { - remotePartyStringified = remoteParty.toString(); - remoteParty = null; - } - if (localParty != null) { - localPartyStringified = localParty.toString(); - localParty = null; - } - } - } - - /** - * Release references so the GC can clean up dialog state. - * - */ - protected void cleanUp() { - if (isReleaseReferences()) { - cleanUpOnAck(); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger - .logDebug("dialog cleanup : " + getDialogId()); - } - if (eventListeners != null) { - eventListeners.clear(); - } - timerTaskLock = null; - ackSem = null; - contactHeader = null; - eventHeader = null; - firstTransactionId = null; - firstTransactionMethod = null; - // Cannot clear up the last Ack Sent. until DIALOG is terminated. - - // lastAckReceivedCSeqNumber = null; - lastResponseDialogId = null; - lastResponseMethod = null; - lastResponseTopMostVia = null; - if (originalRequestRecordRouteHeaders != null) { - originalRequestRecordRouteHeaders.clear(); - originalRequestRecordRouteHeaders = null; - originalRequestRecordRouteHeadersString = null; - } - if (routeList != null) { - routeList.clear(); - routeList = null; - } - responsesReceivedInForkingCase.clear(); - } - } - - protected RecordRouteList getOriginalRequestRecordRouteHeaders() { - if (originalRequestRecordRouteHeaders == null - && originalRequestRecordRouteHeadersString != null) { - try { - originalRequestRecordRouteHeaders = (RecordRouteList) new RecordRouteParser( - originalRequestRecordRouteHeadersString).parse(); - } catch (ParseException e) { - logger - .logError( - "error reparsing the originalRequest RecordRoute Headers", - e); - } - originalRequestRecordRouteHeadersString = null; - } - return originalRequestRecordRouteHeaders; - } - - /** - * @return the lastResponseTopMostVia - */ - public Via getLastResponseTopMostVia() { - return lastResponseTopMostVia; - } - - /* - * (non-Javadoc) - * - * @see gov.nist.javax.sip.DialogExt#isReleaseReferences() - */ - public boolean isReleaseReferences() { - return releaseReferences; - } - - /* - * (non-Javadoc) - * - * @see gov.nist.javax.sip.DialogExt#setReleaseReferences(boolean) - */ - public void setReleaseReferences(boolean releaseReferences) { - this.releaseReferences = releaseReferences; - } - - public void setEarlyDialogTimeoutSeconds(int seconds) { - if (seconds <= 0) { - throw new IllegalArgumentException("Invalid value " + seconds); - } - this.earlyDialogTimeout = seconds; - } - - public void checkRetransmissionForForking(SIPResponse response) { - final int statusCode = response.getStatusCode(); - final String responseMethod = response.getCSeqHeader().getMethod(); - final long responseCSeqNumber = response.getCSeq().getSeqNumber(); - boolean isRetransmission = !responsesReceivedInForkingCase.add(statusCode + "/" + responseCSeqNumber + "/" + responseMethod); - response.setRetransmission(isRetransmission); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( - "marking response as retransmission " + isRetransmission + " for dialog " + this); - } - } + + + public String getMergeId( ) { + return this.firstTransactionMergeId; + } + + public void setPendingRouteUpdateOn202Response(SIPRequest sipRequest) { + this.pendingRouteUpdateOn202Response = true; + String toTag = sipRequest.getToHeader().getTag(); + if ( toTag != null ) { + this.setRemoteTag(toTag); + } + + } + + /** + * @return the lastResponseTopMostVia + */ + public Via getLastResponseTopMostVia() { + if(lastResponse == null) + return null; + return lastResponse.getTopmostVia(); + } + } diff --git a/src/gov/nist/javax/sip/stack/SIPDialogErrorEvent.java b/src/gov/nist/javax/sip/stack/SIPDialogErrorEvent.java index d9846c727..5379cd439 100644 --- a/src/gov/nist/javax/sip/stack/SIPDialogErrorEvent.java +++ b/src/gov/nist/javax/sip/stack/SIPDialogErrorEvent.java @@ -45,15 +45,10 @@ public class SIPDialogErrorEvent extends EventObject { */ public static final int DIALOG_REINVITE_TIMEOUT = 3; - /* - * Dialog in early state for too long. - */ - public static final int EARLY_STATE_TIMEOUT = 4; - /* * This event Id indicates that some internal error happened and the ACK semaphore could not be acquired. */ - public static final int DIALOG_ERROR_INTERNAL_COULD_NOT_TAKE_ACK_SEM = 5; + public static final int DIALOG_ERROR_INTERNAL_COULD_NOT_TAKE_ACK_SEM = 4; // ID of this error event @@ -84,8 +79,6 @@ public SIPDialogErrorEvent (SIPDialog sourceDialog, DialogTimeoutEvent.Reason re this.errorID = DIALOG_REINVITE_TIMEOUT; } else if (reason == DialogTimeoutEvent.Reason.CannotAcquireAckSemaphoreForOk) { this.errorID = DIALOG_ERROR_INTERNAL_COULD_NOT_TAKE_ACK_SEM; - } else if ( reason == DialogTimeoutEvent.Reason.EarlyStateTimeout) { - this.errorID = EARLY_STATE_TIMEOUT; } } diff --git a/src/gov/nist/javax/sip/stack/SIPMessageValve.java b/src/gov/nist/javax/sip/stack/SIPMessageValve.java deleted file mode 100644 index b5e6d9a3b..000000000 --- a/src/gov/nist/javax/sip/stack/SIPMessageValve.java +++ /dev/null @@ -1,52 +0,0 @@ -package gov.nist.javax.sip.stack; - -import javax.sip.SipStack; -import javax.sip.message.Request; -import javax.sip.message.Response; - -import gov.nist.javax.sip.message.SIPRequest; - -/** - * This interface has callbacks that are notified for every SIP message arriving at the container. - * The callbacks occurs before any significant long-lived resources are allocated for this call, thus - * it gives a chance to the application to pre-process the message and filter based on some - * application-specific algorithm. Creating and sending a stateless response is also allowed. - * - * It is useful for congestion control or header re-writing. - * - * @author Vladimir Ralev - * - */ -public interface SIPMessageValve { - /** - * The callback method that is called for every request before any transaction/dialog mapping - * or allocation occur. - * - * @param request - * @param messageChannel - * @return - */ - public boolean processRequest(SIPRequest request, MessageChannel messageChannel); - - /** - * The callback method that is called for every response before any transaction/dialog mapping - * or allocation occur. - * - * @param response - * @param messageChannel - * @return - */ - public boolean processResponse(Response response, MessageChannel messageChannel); - - /** - * This method is called when the valve is initialized. You can perform any initialization here. - * - * @param stack - */ - public void init(SipStack stack); - - /** - * This method is called when the valve is about to be destroyed. You can perform any cleanup here. - */ - public void destroy(); -} diff --git a/src/gov/nist/javax/sip/stack/SIPServerTransaction.java b/src/gov/nist/javax/sip/stack/SIPServerTransaction.java index c9e32a121..8a22efffe 100755 --- a/src/gov/nist/javax/sip/stack/SIPServerTransaction.java +++ b/src/gov/nist/javax/sip/stack/SIPServerTransaction.java @@ -25,12 +25,8 @@ */ package gov.nist.javax.sip.stack; -import gov.nist.core.CommonLogger; -import gov.nist.core.HostPort; import gov.nist.core.InternalErrorHandler; import gov.nist.core.LogWriter; -import gov.nist.core.ServerLogger; -import gov.nist.core.StackLogger; import gov.nist.javax.sip.SIPConstants; import gov.nist.javax.sip.ServerTransactionExt; import gov.nist.javax.sip.SipProviderImpl; @@ -39,14 +35,15 @@ import gov.nist.javax.sip.header.ParameterNames; import gov.nist.javax.sip.header.RSeq; import gov.nist.javax.sip.header.Via; +import gov.nist.javax.sip.header.ViaList; import gov.nist.javax.sip.message.SIPMessage; import gov.nist.javax.sip.message.SIPRequest; import gov.nist.javax.sip.message.SIPResponse; -import gov.nist.javax.sip.stack.IllegalTransactionStateException.Reason; +import gov.nist.javax.sip.stack.SIPTransaction.LingerTimer; import java.io.IOException; -import java.net.InetAddress; import java.text.ParseException; +import java.util.TimerTask; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; @@ -60,7 +57,6 @@ import javax.sip.TransactionState; import javax.sip.address.Hop; import javax.sip.header.ContactHeader; -import javax.sip.header.ContentTypeHeader; import javax.sip.header.ExpiresHeader; import javax.sip.header.RSeqHeader; import javax.sip.message.Request; @@ -172,18 +168,16 @@ * *

    * - * @version 1.2 $Revision: 1.150 $ $Date: 2010-12-02 22:04:15 $ + * @version 1.2 $Revision: 1.124.2.2 $ $Date: 2010-11-23 19:23:13 $ * @author M. Ranganathan * */ public class SIPServerTransaction extends SIPTransaction implements ServerRequestInterface, javax.sip.ServerTransaction, ServerTransactionExt { - private static StackLogger logger = CommonLogger.getLogger(SIPServerTransaction.class); - public static final String CONTENT_TYPE_APPLICATION = "application"; - public static final String CONTENT_SUBTYPE_SDP = "sdp"; + // force the listener to see transaction - private int rseqNumber = -1; + private int rseqNumber; // private LinkedList pendingRequests; @@ -191,17 +185,10 @@ public class SIPServerTransaction extends SIPTransaction implements ServerReques private transient ServerRequestInterface requestOf; private SIPDialog dialog; - // jeand needed because we nullify the dialog ref early and keep only the dialogId to save on mem and help GC - protected String dialogId; // the unacknowledged SIPResponse -// private SIPResponse pendingReliableResponse; - // wondering if the pendingReliableResponseAsBytes could be put into the lastResponseAsBytes - private byte[] pendingReliableResponseAsBytes; - private String pendingReliableResponseMethod; - private long pendingReliableCSeqNumber; - private long pendingReliableRSeqNumber; + private SIPResponse pendingReliableResponse; // The pending reliable Response Timer private ProvisionalResponseTask provisionalResponseTask; @@ -217,23 +204,12 @@ public class SIPServerTransaction extends SIPTransaction implements ServerReques private SIPClientTransaction pendingSubscribeTransaction; private SIPServerTransaction inviteTransaction; - + // Experimental. private static boolean interlockProvisionalResponses = true; - + private Semaphore provisionalResponseSem = new Semaphore(1); - // jeand we nullify the last response fast to save on mem and help GC, but we keep only the information needed - private byte[] lastResponseAsBytes; - private String lastResponseHost; - private int lastResponsePort; - private String lastResponseTransport; - - private int lastResponseStatusCode; - - private HostPort originalRequestSentBy; - private String originalRequestFromTag; - /** * This timer task is used for alerting the application to send retransmission alerts. * @@ -253,7 +229,7 @@ public RetransmissionAlertTimerTask(String dialogId) { this.ticksLeft = this.ticks; } - public void runTask() { + protected void runTask() { SIPServerTransaction serverTransaction = SIPServerTransaction.this; ticksLeft--; if (ticksLeft == -1) { @@ -276,7 +252,7 @@ public ProvisionalResponseTask() { this.ticksLeft = this.ticks; } - public void runTask() { + protected void runTask() { SIPServerTransaction serverTransaction = SIPServerTransaction.this; /* * The reliable provisional response is passed to the transaction layer periodically @@ -292,7 +268,7 @@ public void runTask() { // If the transaction has terminated, if (serverTransaction.isTerminated()) { - sipStack.getTimer().cancel(this); + this.cancel(); } else { ticksLeft--; @@ -304,8 +280,8 @@ public void runTask() { // determines when the server // transaction abandons retransmitting the response if (this.ticksLeft >= SIPTransaction.TIMER_H) { - sipStack.getTimer().cancel(this); - setState(TransactionState._TERMINATED); + this.cancel(); + setState(TERMINATED_STATE); fireTimeoutTimer(); } } @@ -329,23 +305,26 @@ class ListenerExecutionMaxTimer extends SIPStackTimerTask { ListenerExecutionMaxTimer() { } - public void runTask() { + protected void runTask() { try { - listenerExecutionMaxTimer = null; - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("Fired ListenerExecutionMaxTimer for stx " + serverTransaction.getTransactionId() + " state " + serverTransaction.getState()); - if (serverTransaction.getInternalState() <= 1 || + listenerExecutionMaxTimer = null; + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Fired ListenerExecutionMaxTimer for stx " + serverTransaction.getTransactionId() + " state " + serverTransaction.getState()); + if (serverTransaction.getState() == null || + serverTransaction.getState().equals(TransactionState.CALLING) || + serverTransaction.getState().equals(TransactionState.TRYING) || // may have been forcefully TERMINATED through terminate() method but if the tx timer never got scheduled // it wouldn't be reaped - serverTransaction.getInternalState() >= 5) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("ListenerExecutionMaxTimer : terminating and removing stx " + serverTransaction.getTransactionId()); + serverTransaction.getState().equals(TransactionState.TERMINATED)) { + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("ListenerExecutionMaxTimer : terminating and removing stx " + serverTransaction.getTransactionId()); serverTransaction.terminate(); SIPTransactionStack sipStack = serverTransaction.getSIPStack(); sipStack.removeTransaction(serverTransaction); } + } catch (Exception ex) { - logger.logError("unexpected exception", ex); + sipStack.getStackLogger().logError("unexpected exception", ex); } } } @@ -358,29 +337,29 @@ public void runTask() { class SendTrying extends SIPStackTimerTask { protected SendTrying() { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("scheduled timer for " + SIPServerTransaction.this); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("scheduled timer for " + SIPServerTransaction.this); } - public void runTask() { + protected void runTask() { SIPServerTransaction serverTransaction = SIPServerTransaction.this; - int realState = serverTransaction.getRealState(); + TransactionState realState = serverTransaction.getRealState(); - if (realState < 0 || TransactionState._TRYING == realState) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug(" sending Trying current state = " + if (realState == null || TransactionState.TRYING == realState) { + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug(" sending Trying current state = " + serverTransaction.getRealState()); try { serverTransaction.sendMessage(serverTransaction.getOriginalRequest() .createResponse(100, "Trying")); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug(" trying sent " + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug(" trying sent " + serverTransaction.getRealState()); } catch (IOException ex) { - if (logger.isLoggingEnabled()) - logger.logError("IO error sending TRYING"); + if (sipStack.isLoggingEnabled()) + sipStack.getStackLogger().logError("IO error sending TRYING"); } } @@ -390,47 +369,45 @@ public void runTask() { class TransactionTimer extends SIPStackTimerTask { public TransactionTimer() { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("TransactionTimer() : " + getTransactionId()); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("TransactionTimer() : " + getTransactionId()); } } - public void runTask() { + protected void runTask() { // If the transaction has terminated, - if (isTerminated()) { + if (isTerminated()) { // Keep the transaction hanging around in the transaction table // to catch the incoming ACK -- this is needed for tcp only. // Note that the transaction record is actually removed in // the connection linger timer. try { - sipStack.getTimer().cancel(this); - if(listenerExecutionMaxTimer != null) { - sipStack.getTimer().cancel(listenerExecutionMaxTimer); - } + this.cancel(); + if(listenerExecutionMaxTimer != null) { + listenerExecutionMaxTimer.cancel(); + } } catch (IllegalStateException ex) { if (!sipStack.isAlive()) return; } - // Oneshot timer that garbage collects the SeverTransaction // after a scheduled amount of time. The linger timer allows // the client side of the tx to use the same connection to // send an ACK and prevents a race condition for creation // of new server tx - SIPStackTimerTask myTimer = new LingerTimer(); + TimerTask myTimer = new LingerTimer(); sipStack.getTimer().schedule(myTimer, - SIPTransactionStack.CONNECTION_LINGER_TIME * 1000); + SIPTransactionStack.CONNECTION_LINGER_TIME * 1000); + } else { // Add to the fire list -- needs to be moved // outside the synchronized block to prevent // deadlock. fireTimer(); - } - if(originalRequest != null) { - originalRequest.cleanUp(); + } } @@ -443,10 +420,8 @@ public void runTask() { * */ - protected void sendResponse(SIPResponse transactionResponse) throws IOException { - if ( logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("sipServerTransaction::sendResponse " + transactionResponse.getFirstLine()); - } + private void sendResponse(SIPResponse transactionResponse) throws IOException { + try { // RFC18.2.2. Sending Responses // The server transport uses the value of the top Via header field @@ -464,6 +439,10 @@ protected void sendResponse(SIPResponse transactionResponse) throws IOException getMessageChannel().sendMessage(transactionResponse); + // TODO If that connection attempt fails, the server SHOULD + // use SRV 3263 procedures + // for servers in order to determine the IP address + // and port to open the connection and send the response to. } else { Via via = transactionResponse.getTopmostVia(); @@ -522,18 +501,13 @@ protected void sendResponse(SIPResponse transactionResponse) throws IOException hop.getTransport()).getIPAddress(), this.getPort(), hop); if (messageChannel != null) { messageChannel.sendMessage(transactionResponse); - lastResponseHost = host; - lastResponsePort = port; - lastResponseTransport = transport; } else { throw new IOException("Could not create a message channel for " + hop + " with source IP:Port "+ - this.getSipProvider().getListeningPoint( + this.getSipProvider().getListeningPoint( hop.getTransport()).getIPAddress() + ":" + this.getPort()); } } - lastResponseAsBytes = transactionResponse.encodeAsBytes(this.getTransport()); - lastResponse = null; } finally { this.startTransactionTimer(); } @@ -550,14 +524,17 @@ protected SIPServerTransaction(SIPTransactionStack sipStack, MessageChannel newC super(sipStack, newChannelToUse); if (sipStack.maxListenerResponseTime != -1) { - sipStack.getTimer().schedule(new ListenerExecutionMaxTimer(), + listenerExecutionMaxTimer = new ListenerExecutionMaxTimer(); + sipStack.getTimer().schedule(listenerExecutionMaxTimer, sipStack.maxListenerResponseTime * 1000); } + + this.rseqNumber = (int) (Math.random() * 1000); // Only one outstanding request for a given server tx. - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("Creating Server Transaction" + this.getBranchId()); - logger.logStackTrace(); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("Creating Server Transaction" + this.getBranchId()); + sipStack.getStackLogger().logStackTrace(); } } @@ -582,8 +559,8 @@ public MessageChannel getResponseChannel() { } - - + + /** * Determines if the message is a part of this transaction. * @@ -594,25 +571,29 @@ public MessageChannel getResponseChannel() { public boolean isMessagePartOfTransaction(SIPMessage messageToTest) { // List of Via headers in the message to test -// ViaList viaHeaders; - + ViaList viaHeaders; + // Topmost Via header in the list + Via topViaHeader; + // Branch code in the topmost Via header + String messageBranch; // Flags whether the select message is part of this transaction - boolean transactionMatches = false; - final String method = messageToTest.getCSeq().getMethod(); - SIPRequest origRequest = getOriginalRequest(); + boolean transactionMatches; + + transactionMatches = false; + + String method = messageToTest.getCSeq().getMethod(); // Invite Server transactions linger in the terminated state in the // transaction // table and are matched to compensate for // http://bugs.sipit.net/show_bug.cgi?id=769 - if (isInviteTransaction() || !isTerminated()) { + if ((method.equals(Request.INVITE) || !isTerminated())) { // Get the topmost Via header and its branch parameter - final Via topViaHeader = messageToTest.getTopmostVia(); - if (topViaHeader != null) { + viaHeaders = messageToTest.getViaHeaders(); + if (viaHeaders != null) { -// topViaHeader = (Via) viaHeaders.getFirst(); - // Branch code in the topmost Via header - String messageBranch = topViaHeader.getBranch(); + topViaHeader = (Via) viaHeaders.getFirst(); + messageBranch = topViaHeader.getBranch(); if (messageBranch != null) { // If the branch parameter exists but @@ -638,28 +619,20 @@ public boolean isMessagePartOfTransaction(SIPMessage messageToTest) { transactionMatches = this.getMethod().equals(Request.CANCEL) && getBranch().equalsIgnoreCase(messageBranch) && topViaHeader.getSentBy().equals( - origRequest.getTopmostVia() + ((Via) getOriginalRequest().getViaHeaders().getFirst()) .getSentBy()); } else { // Matching server side transaction with only the // branch parameter. - if(origRequest != null) { - transactionMatches = getBranch().equalsIgnoreCase(messageBranch) + transactionMatches = getBranch().equalsIgnoreCase(messageBranch) && topViaHeader.getSentBy().equals( - origRequest.getTopmostVia() + ((Via) getOriginalRequest().getViaHeaders().getFirst()) .getSentBy()); - } else { - transactionMatches = getBranch().equalsIgnoreCase(messageBranch) - && topViaHeader.getSentBy().equals(originalRequestSentBy); - } } } else { - // force the reparsing only on non RFC 3261 messages - origRequest = (SIPRequest) getRequest(); - // This is an RFC2543-compliant message; this code is here // for backwards compatibility. // It is a weak check. @@ -668,13 +641,13 @@ && getBranch().equalsIgnoreCase(messageBranch) // SIPMessage matches this transaction. An exception is for // a CANCEL request, which is not deemed // to be part of an otherwise-matching INVITE transaction. - String originalFromTag = origRequest.getFromTag(); + String originalFromTag = super.fromTag; String thisFromTag = messageToTest.getFrom().getTag(); boolean skipFrom = (originalFromTag == null || thisFromTag == null); - String originalToTag = origRequest.getToTag(); + String originalToTag = super.toTag; String thisToTag = messageToTest.getTo().getTag(); @@ -684,20 +657,21 @@ && getBranch().equalsIgnoreCase(messageBranch) // the CSeq method of the original request must // be CANCEL for it to have a chance at matching. if (messageToTest.getCSeq().getMethod().equalsIgnoreCase(Request.CANCEL) - && !origRequest.getCSeq().getMethod().equalsIgnoreCase( + && !getOriginalRequest().getCSeq().getMethod().equalsIgnoreCase( Request.CANCEL)) { transactionMatches = false; - } else if ((isResponse || origRequest.getRequestURI().equals( + } else if ((isResponse || getOriginalRequest().getRequestURI().equals( ((SIPRequest) messageToTest).getRequestURI())) && (skipFrom || originalFromTag != null && originalFromTag.equalsIgnoreCase(thisFromTag)) && (skipTo || originalToTag != null && originalToTag.equalsIgnoreCase(thisToTag)) - && origRequest.getCallId().getCallId().equalsIgnoreCase( + && getOriginalRequest().getCallId().getCallId().equalsIgnoreCase( messageToTest.getCallId().getCallId()) - && origRequest.getCSeq().getSeqNumber() == messageToTest + && getOriginalRequest().getCSeq().getSeqNumber() == messageToTest .getCSeq().getSeqNumber() - && ((!messageToTest.getCSeq().getMethod().equals(Request.CANCEL)) || - getMethod().equals(messageToTest.getCSeq().getMethod())) - && topViaHeader.equals(origRequest.getTopmostVia())) { + && ((!messageToTest.getCSeq().getMethod().equals(Request.CANCEL)) || getOriginalRequest() + .getMethod().equals(messageToTest.getCSeq().getMethod())) + && topViaHeader.equals(getOriginalRequest().getViaHeaders() + .getFirst())) { transactionMatches = true; } @@ -718,12 +692,14 @@ && getBranch().equalsIgnoreCase(messageBranch) protected void map() { // note that TRYING is a pseudo-state for invite transactions - int realState = getRealState(); + TransactionState realState = getRealState(); - if (realState < 0 || realState == TransactionState._TRYING) { - // Also sent by intermediate proxies. - // null check added as the stack may be stopped. TRYING is not sent by reliable transports. - if (isInviteTransaction() && !this.isMapped && sipStack.getTimer() != null ) { + if (realState == null || realState == TransactionState.TRYING) { + // JvB: Removed the condition 'dialog!=null'. Trying should also + // be + // sent by intermediate proxies. This fixes some TCK tests + // null check added as the stack may be stopped. + if (isInviteTransaction() && !this.isMapped && sipStack.getTimer() != null) { this.isMapped = true; // Schedule a timer to fire in 200 ms if the // TU did not send a trying in that time. @@ -759,19 +735,19 @@ public void processRequest(SIPRequest transactionRequest, MessageChannel sourceC // transaction at a time. For a given server transaction // the listener sees only one event at a time. - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("processRequest: " + transactionRequest.getFirstLine()); - logger.logDebug("tx state = " + this.getRealState()); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("processRequest: " + transactionRequest.getFirstLine()); + sipStack.getStackLogger().logDebug("tx state = " + this.getRealState()); } try { // If this is the first request for this transaction, - if (getRealState() < 0) { + if (getRealState() == null) { // Save this request as the one this // transaction is handling setOriginalRequest(transactionRequest); - this.setState(TransactionState._TRYING); + this.setState(TransactionState.TRYING); toTu = true; this.setPassToListener(); @@ -788,22 +764,22 @@ public void processRequest(SIPRequest transactionRequest, MessageChannel sourceC } // If an invite transaction is ACK'ed while in // the completed state, - } else if (isInviteTransaction() && TransactionState._COMPLETED == getRealState() + } else if (isInviteTransaction() && TransactionState.COMPLETED == getRealState() && transactionRequest.getMethod().equals(Request.ACK)) { // @jvB bug fix - this.setState(TransactionState._CONFIRMED); + this.setState(TransactionState.CONFIRMED); disableRetransmissionTimer(); if (!isReliable()) { enableTimeoutTimer(TIMER_I); } else { - this.setState(TransactionState._TERMINATED); + this.setState(TransactionState.TERMINATED); } - + // JvB: For the purpose of testing a TI, added a property to // pass it anyway if (sipStack.isNon2XXAckPassedToListener()) { @@ -813,8 +789,8 @@ public void processRequest(SIPRequest transactionRequest, MessageChannel sourceC } else { // According to RFC3261 Application should not Ack in // CONFIRMED state - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("ACK received for server Tx " + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("ACK received for server Tx " + this.getTransactionId() + " not delivering to application!"); } @@ -825,15 +801,19 @@ public void processRequest(SIPRequest transactionRequest, MessageChannel sourceC // If we receive a retransmission of the original // request, - } else if (transactionRequest.getMethod().equals(getMethod())) { + } else if (transactionRequest.getMethod().equals(getOriginalRequest().getMethod())) { - if (TransactionState._PROCEEDING == getRealState() - || TransactionState._COMPLETED == getRealState()) { + if (TransactionState.PROCEEDING == getRealState() + || TransactionState.COMPLETED == getRealState()) { this.semRelease(); // Resend the last response to // the client - // Send the message to the client - resendLastResponseAsBytes(); + if (lastResponse != null) { + + // Send the message to the client + super.sendMessage(lastResponse); + + } } else if (transactionRequest.getMethod().equals(Request.ACK)) { // This is passed up to the TU to suppress // retransmission of OK @@ -842,18 +822,18 @@ public void processRequest(SIPRequest transactionRequest, MessageChannel sourceC else this.semRelease(); } - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("completed processing retransmitted request : " + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("completed processing retransmitted request : " + transactionRequest.getFirstLine() + this + " txState = " - + this.getState() + " lastResponse = " + this.lastResponseAsBytes); + + this.getState() + " lastResponse = " + this.getLastResponse()); return; } // Pass message to the TU - if (TransactionState._COMPLETED != getRealState() - && TransactionState._TERMINATED != getRealState() && requestOf != null) { - if (getMethod().equals(transactionRequest.getMethod())) { + if (TransactionState.COMPLETED != getRealState() + && TransactionState.TERMINATED != getRealState() && requestOf != null) { + if (getOriginalRequest().getMethod().equals(transactionRequest.getMethod())) { // Only send original request to TU once! if (toTu) { requestOf.processRequest(transactionRequest, this); @@ -867,16 +847,17 @@ public void processRequest(SIPRequest transactionRequest, MessageChannel sourceC } } else { // This seems like a common bug so I am allowing it through! - if (SIPTransactionStack.isDialogCreated(getMethod()) - && getRealState() == TransactionState._TERMINATED + if (((SIPTransactionStack) getSIPStack()).isDialogCreated(getOriginalRequest() + .getMethod()) + && getRealState() == TransactionState.TERMINATED && transactionRequest.getMethod().equals(Request.ACK) && requestOf != null) { - SIPDialog thisDialog = (SIPDialog) getDialog(); + SIPDialog thisDialog = (SIPDialog) this.dialog; if (thisDialog == null || !thisDialog.ackProcessed) { // Filter out duplicate acks if (thisDialog != null) { - thisDialog.ackReceived(transactionRequest.getCSeq().getSeqNumber()); + thisDialog.ackReceived(transactionRequest); thisDialog.ackProcessed = true; } requestOf.processRequest(transactionRequest, this); @@ -885,8 +866,8 @@ && getRealState() == TransactionState._TERMINATED } } else if (transactionRequest.getMethod().equals(Request.CANCEL)) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("Too late to cancel Transaction"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Too late to cancel Transaction"); this.semRelease(); // send OK and just ignore the CANCEL. try { @@ -896,13 +877,13 @@ && getRealState() == TransactionState._TERMINATED // just ignore the IOException. } } - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("Dropping request " + getRealState()); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Dropping request " + getRealState()); } } catch (IOException e) { - if (logger.isLoggingEnabled()) - logger.logError("IOException " ,e); + if (sipStack.isLoggingEnabled()) + sipStack.getStackLogger().logError("IOException " ,e); this.semRelease(); this.raiseIOExceptionEvent(); } @@ -910,248 +891,240 @@ && getRealState() == TransactionState._TERMINATED } /** - * Send a response message through this transaction and onto the client. The response drives + * Send a response message through this transactionand onto the client. The response drives * the state machine. * * @param messageToSend Response to process and send. */ public void sendMessage(SIPMessage messageToSend) throws IOException { - if ( logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("sipServerTransaction::sendMessage " + messageToSend.getFirstLine()); - } - // Message typecast as a response - final SIPResponse transactionResponse = (SIPResponse) messageToSend; - // Status code of the response being sent to the client - final int statusCode = transactionResponse.getStatusCode(); try { + // Message typecast as a response + SIPResponse transactionResponse; + // Status code of the response being sent to the client + int statusCode; + + // Get the status code from the response + transactionResponse = (SIPResponse) messageToSend; + statusCode = transactionResponse.getStatusCode(); try { // Provided we have set the banch id for this we set the BID for // the // outgoing via. - if (originalRequestBranch != null) + if (this.getOriginalRequest().getTopmostVia().getBranch() != null) transactionResponse.getTopmostVia().setBranch(this.getBranch()); else transactionResponse.getTopmostVia().removeParameter(ParameterNames.BRANCH); // Make the topmost via headers match identically for the // transaction rsponse. - if (!originalRequestHasPort) + if (!this.getOriginalRequest().getTopmostVia().hasPort()) transactionResponse.getTopmostVia().removePort(); } catch (ParseException ex) { - logger.logError("UnexpectedException",ex); - throw new IOException("Unexpected exception"); + ex.printStackTrace(); } // Method of the response does not match the request used to // create the transaction - transaction state does not change. if (!transactionResponse.getCSeq().getMethod().equals( - getMethod())) { + getOriginalRequest().getMethod())) { sendResponse(transactionResponse); return; } - if(!checkStateTimers(statusCode)) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("checkStateTimers returned false -- not sending message"); - } - return; - } - - try { - // Send the message to the client. - // Record the last message sent out. - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( - "sendMessage : tx = " + this + " getState = " + this.getState()); - } - lastResponse = transactionResponse; - lastResponseStatusCode = transactionResponse.getStatusCode(); - - this.sendResponse(transactionResponse); - - } catch (IOException e) { + // If the TU sends a provisional response while in the + // trying state, + + if (getRealState() == TransactionState.TRYING) { + if (statusCode / 100 == 1) { + this.setState(TransactionState.PROCEEDING); + } else if (200 <= statusCode && statusCode <= 699) { + // INVITE ST has TRYING as a Pseudo state + // (See issue 76). We are using the TRYING + // pseudo state invite Transactions + // to signal if the application + // has sent trying or not and hence this + // check is necessary. + if (!isInviteTransaction()) { + if (!isReliable()) { + // Linger in the completed state to catch + // retransmissions if the transport is not + // reliable. + this.setState(TransactionState.COMPLETED); + // Note that Timer J is only set for Unreliable + // transports -- see Issue 75. + /* + * From RFC 3261 Section 17.2.2 (non-invite server transaction) + * + * When the server transaction enters the "Completed" state, it MUST + * set Timer J to fire in 64*T1 seconds for unreliable transports, and + * zero seconds for reliable transports. While in the "Completed" + * state, the server transaction MUST pass the final response to the + * transport layer for retransmission whenever a retransmission of the + * request is received. Any other final responses passed by the TU to + * the server transaction MUST be discarded while in the "Completed" + * state. The server transaction remains in this state until Timer J + * fires, at which point it MUST transition to the "Terminated" state. + */ + enableTimeoutTimer(TIMER_J); + } else { + this.setState(TransactionState.TERMINATED); + } + } else { + // This is the case for INVITE server transactions. + // essentially, it duplicates the code in the + // PROCEEDING case below. There is no TRYING state for INVITE + // transactions in the RFC. We are using it to signal whether the + // application has sent a provisional response or not. Hence + // this is treated the same as as Proceeding. + if (statusCode / 100 == 2) { + // Status code is 2xx means that the + // transaction transitions to TERMINATED + // for both Reliable as well as unreliable + // transports. Note that the dialog layer + // takes care of retransmitting 2xx final + // responses. + /* + * RFC 3261 Section 13.3.1.4 Note, however, that the INVITE server + * transaction will be destroyed as soon as it receives this final + * response and passes it to the transport. Therefore, it is necessary + * to periodically pass the response directly to the transport until + * the ACK arrives. The 2xx response is passed to the transport with + * an interval that starts at T1 seconds and doubles for each + * retransmission until it reaches T2 seconds (T1 and T2 are defined + * in Section 17). Response retransmissions cease when an ACK request + * for the response is received. This is independent of whatever + * transport protocols are used to send the response. + */ + this.disableRetransmissionTimer(); + this.disableTimeoutTimer(); + this.collectionTime = TIMER_J; + this.setState(TransactionState.TERMINATED); + if (this.dialog != null) + this.dialog.setRetransmissionTicks(); + } else { + // This an error final response. + this.setState(TransactionState.COMPLETED); + if (!isReliable()) { + /* + * RFC 3261 + * + * While in the "Proceeding" state, if the TU passes a response + * with status code from 300 to 699 to the server transaction, the + * response MUST be passed to the transport layer for + * transmission, and the state machine MUST enter the "Completed" + * state. For unreliable transports, timer G is set to fire in T1 + * seconds, and is not set to fire for reliable transports. + */ + + enableRetransmissionTimer(); - this.setState(TransactionState._TERMINATED); - this.collectionTime = 0; - throw e; + } + enableTimeoutTimer(TIMER_H); + } + } - } - } finally { - this.startTransactionTimer(); - } + } - } + // If the transaction is in the proceeding state, + } else if (getRealState() == TransactionState.PROCEEDING) { + if (isInviteTransaction()) { - private boolean checkStateTimers(int statusCode) { - // If the TU sends a provisional response while in the - // trying state, - - if (getRealState() == TransactionState._TRYING) { - if (statusCode / 100 == 1) { - this.setState(TransactionState._PROCEEDING); - } else if (200 <= statusCode && statusCode <= 699) { - // INVITE ST has TRYING as a Pseudo state - // (See issue 76). We are using the TRYING - // pseudo state invite Transactions - // to signal if the application - // has sent trying or not and hence this - // check is necessary. - if (!isInviteTransaction()) { - if (!isReliable() && getInternalState() != TransactionState._COMPLETED) { - // Linger in the completed state to catch - // retransmissions if the transport is not - // reliable. - this.setState(TransactionState._COMPLETED); - // Note that Timer J is only set for Unreliable - // transports -- see Issue 75. - /* - * From RFC 3261 Section 17.2.2 (non-invite server transaction) - * - * When the server transaction enters the "Completed" state, it MUST - * set Timer J to fire in 64*T1 seconds for unreliable transports, and - * zero seconds for reliable transports. While in the "Completed" - * state, the server transaction MUST pass the final response to the - * transport layer for retransmission whenever a retransmission of the - * request is received. Any other final responses passed by the TU to - * the server transaction MUST be discarded while in the "Completed" - * state. The server transaction remains in this state until Timer J - * fires, at which point it MUST transition to the "Terminated" state. - */ - startTransactionTimerJ(TIMER_J); - cleanUpOnTimer(); - } else { - cleanUpOnTimer(); - this.setState(TransactionState._TERMINATED); - startTransactionTimerJ(0); - } - } else { - // This is the case for INVITE server transactions. - // essentially, it duplicates the code in the - // PROCEEDING case below. There is no TRYING state for INVITE - // transactions in the RFC. We are using it to signal whether the - // application has sent a provisional response or not. Hence - // this is treated the same as as Proceeding. + // If the response is a failure message, if (statusCode / 100 == 2) { - // Status code is 2xx means that the - // transaction transitions to TERMINATED - // for both Reliable as well as unreliable - // transports. Note that the dialog layer - // takes care of retransmitting 2xx final - // responses. - /* - * RFC 3261 Section 13.3.1.4 Note, however, that the INVITE server - * transaction will be destroyed as soon as it receives this final - * response and passes it to the transport. Therefore, it is necessary - * to periodically pass the response directly to the transport until - * the ACK arrives. The 2xx response is passed to the transport with - * an interval that starts at T1 seconds and doubles for each - * retransmission until it reaches T2 seconds (T1 and T2 are defined - * in Section 17). Response retransmissions cease when an ACK request - * for the response is received. This is independent of whatever - * transport protocols are used to send the response. - */ + // Set up to catch returning ACKs + // The transaction lingers in the + // terminated state for some time + // to catch retransmitted INVITEs this.disableRetransmissionTimer(); this.disableTimeoutTimer(); this.collectionTime = TIMER_J; - cleanUpOnTimer(); - this.setState(TransactionState._TERMINATED); - if (this.getDialog() != null) - ((SIPDialog) this.getDialog()).setRetransmissionTicks(); - } else { - // This an error final response. - this.setState(TransactionState._COMPLETED); + this.setState(TransactionState.TERMINATED); + if (this.dialog != null) + this.dialog.setRetransmissionTicks(); + + } else if (300 <= statusCode && statusCode <= 699) { + + // Set up to catch returning ACKs + this.setState(TransactionState.COMPLETED); if (!isReliable()) { /* - * RFC 3261 - * - * While in the "Proceeding" state, if the TU passes a response - * with status code from 300 to 699 to the server transaction, the - * response MUST be passed to the transport layer for - * transmission, and the state machine MUST enter the "Completed" - * state. For unreliable transports, timer G is set to fire in T1 - * seconds, and is not set to fire for reliable transports. + * While in the "Proceeding" state, if the TU passes a response with + * status code from 300 to 699 to the server transaction, the response + * MUST be passed to the transport layer for transmission, and the + * state machine MUST enter the "Completed" state. For unreliable + * transports, timer G is set to fire in T1 seconds, and is not set to + * fire for reliable transports. */ enableRetransmissionTimer(); } - cleanUpOnTimer(); enableTimeoutTimer(TIMER_H); + } - } - } + // If the transaction is not an invite transaction + // and this is a final response, + } else if (200 <= statusCode && statusCode <= 699) { + // This is for Non-invite server transactions. - // If the transaction is in the proceeding state, - } else if (getRealState() == TransactionState._PROCEEDING) { - - if (isInviteTransaction()) { - - // If the response is a failure message, - if (statusCode / 100 == 2) { - // Set up to catch returning ACKs - // The transaction lingers in the - // terminated state for some time - // to catch retransmitted INVITEs - this.disableRetransmissionTimer(); - this.disableTimeoutTimer(); - this.collectionTime = TIMER_J; - cleanUpOnTimer(); - this.setState(TransactionState._TERMINATED); - if (this.getDialog() != null) - ((SIPDialog) this.getDialog()).setRetransmissionTicks(); - - } else if (300 <= statusCode && statusCode <= 699) { - - // Set up to catch returning ACKs - this.setState(TransactionState._COMPLETED); + // Set up to retransmit this response, + // or terminate the transaction + this.setState(TransactionState.COMPLETED); if (!isReliable()) { - /* - * While in the "Proceeding" state, if the TU passes a response with - * status code from 300 to 699 to the server transaction, the response - * MUST be passed to the transport layer for transmission, and the - * state machine MUST enter the "Completed" state. For unreliable - * transports, timer G is set to fire in T1 seconds, and is not set to - * fire for reliable transports. - */ - enableRetransmissionTimer(); + + disableRetransmissionTimer(); + enableTimeoutTimer(TIMER_J); + + } else { + + this.setState(TransactionState.TERMINATED); + } - cleanUpOnTimer(); - enableTimeoutTimer(TIMER_H); + } - // If the transaction is not an invite transaction - // and this is a final response, - } else if (200 <= statusCode && statusCode <= 699) { - // This is for Non-invite server transactions. - // Set up to retransmit this response, - // or terminate the transaction - this.setState(TransactionState._COMPLETED); - if (!isReliable()) { - disableRetransmissionTimer(); -// enableTimeoutTimer(TIMER_J); - startTransactionTimerJ(TIMER_J); - } else { - this.setState(TransactionState._TERMINATED); - startTransactionTimerJ(0); + // If the transaction has already completed, + } else if (TransactionState.COMPLETED == this.getRealState()) { + + return; + } + + try { + // Send the message to the client. + // Record the last message sent out. + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( + "sendMessage : tx = " + this + " getState = " + this.getState()); } - cleanUpOnTimer(); + lastResponse = transactionResponse; + this.sendResponse(transactionResponse); + + } catch (IOException e) { + + this.setState(TransactionState.TERMINATED); + this.collectionTime = 0; + throw e; + } - // If the transaction has already completed, - } else if (TransactionState._COMPLETED == this.getRealState()) { - return false; + } finally { + this.startTransactionTimer(); } - return true; + } public String getViaHost() { - return super.getViaHost(); + + return getMessageChannel().getViaHost(); + } public int getViaPort() { - return super.getViaPort(); + + return getMessageChannel().getViaPort(); + } /** @@ -1161,17 +1134,16 @@ public int getViaPort() { protected void fireRetransmissionTimer() { try { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("fireRetransmissionTimer() -- " + this + " state " + getState()); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("fireRetransmissionTimer() -- "); } // Resend the last response sent by this transaction - if (isInviteTransaction() && (lastResponse != null || lastResponseAsBytes != null)) { + if (isInviteTransaction() && lastResponse != null) { // null can happen if this is terminating when the timer fires. if (!this.retransmissionAlertEnabled || sipStack.isTransactionPendingAck(this) ) { // Retransmit last response until ack. - if (lastResponseStatusCode / 100 >= 2 && !this.isAckSeen) { - resendLastResponseAsBytes(); - } + if (lastResponse.getStatusCode() / 100 > 2 && !this.isAckSeen) + super.sendMessage(lastResponse); } else { // alert the application to retransmit the last response SipProviderImpl sipProvider = (SipProviderImpl) this.getSipProvider(); @@ -1182,102 +1154,23 @@ protected void fireRetransmissionTimer() { } } catch (IOException e) { - if (logger.isLoggingEnabled()) - logger.logException(e); + if (sipStack.isLoggingEnabled()) + sipStack.getStackLogger().logException(e); raiseErrorEvent(SIPTransactionErrorEvent.TRANSPORT_ERROR); } } - // jeand we nullify the last response very fast to save on mem and help GC but we keep it as byte array - // so this method is used to resend the last response either as a response or byte array depending on if it has been nullified - public void resendLastResponseAsBytes() throws IOException { - - if(lastResponse != null) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("resend last response " + lastResponse); - } - sendMessage(lastResponse); - } else if (lastResponseAsBytes != null) { - // Send the message to the client -// if(!checkStateTimers(lastResponseStatusCode)) { -// return; -// } - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("resend last response " + new String(lastResponseAsBytes)); - } - - if(isReliable()) { - if (logger.isLoggingEnabled(ServerLogger.TRACE_MESSAGES)) { - // Issue 343 : we have to log the retransmission - try { - SIPResponse lastReparsedResponse = (SIPResponse) sipStack.getMessageParserFactory().createMessageParser(sipStack).parseSIPMessage(lastResponseAsBytes, true, false, null); - - lastReparsedResponse.setRemoteAddress( - this.getPeerInetAddress()); - lastReparsedResponse.setRemotePort(this.getPeerPort()); - lastReparsedResponse.setLocalPort( - getMessageChannel().getPort()); - lastReparsedResponse.setLocalAddress( - getMessageChannel() - .getMessageProcessor().getIpAddress()); - - getMessageChannel().logMessage(lastReparsedResponse, this.getPeerInetAddress(), this.getPeerPort(), System.currentTimeMillis()); - } catch (ParseException e) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("couldn't reparse last response " + new String(lastResponseAsBytes)); - } - } - } - getMessageChannel().sendMessage(lastResponseAsBytes, this.getPeerInetAddress(), this.getPeerPort(), false); - } else { - Hop hop = sipStack.addressResolver.resolveAddress(new HopImpl(lastResponseHost, lastResponsePort, - lastResponseTransport)); - - MessageChannel messageChannel = ((SIPTransactionStack) getSIPStack()) - .createRawMessageChannel(this.getSipProvider().getListeningPoint( - hop.getTransport()).getIPAddress(), this.getPort(), hop); - if (messageChannel != null) { - if (logger.isLoggingEnabled(ServerLogger.TRACE_MESSAGES)) { - // Issue 343 : we have to log the retransmission - try { - SIPResponse lastReparsedResponse = (SIPResponse) sipStack.getMessageParserFactory().createMessageParser(sipStack).parseSIPMessage(lastResponseAsBytes, true, false, null); - - lastReparsedResponse.setRemoteAddress( - this.getPeerInetAddress()); - lastReparsedResponse.setRemotePort - (this.getPeerPort()); - lastReparsedResponse.setLocalPort( - getMessageChannel().getPort()); - lastReparsedResponse.setLocalAddress( - getMessageChannel() - .getMessageProcessor().getIpAddress()); - - getMessageChannel().logMessage(lastReparsedResponse, this.getPeerInetAddress(), this.getPeerPort(), System.currentTimeMillis()); - } catch (ParseException e) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("couldn't reparse last response " + new String(lastResponseAsBytes)); - } - } - } - messageChannel.sendMessage(lastResponseAsBytes, InetAddress.getByName(hop.getHost()), hop.getPort(), false); - } else { - throw new IOException("Could not create a message channel for " + hop + " with source IP:Port "+ - this.getSipProvider().getListeningPoint( - hop.getTransport()).getIPAddress() + ":" + this.getPort()); - } - } - } - } - private void fireReliableResponseRetransmissionTimer() { try { - resendLastResponseAsBytes(); + + super.sendMessage(this.pendingReliableResponse); + } catch (IOException e) { - if (logger.isLoggingEnabled()) - logger.logException(e); - this.setState(TransactionState._TERMINATED); + if (sipStack.isLoggingEnabled()) + sipStack.getStackLogger().logException(e); + this.setState(TransactionState.TERMINATED); raiseErrorEvent(SIPTransactionErrorEvent.TRANSPORT_ERROR); } @@ -1288,55 +1181,52 @@ private void fireReliableResponseRetransmissionTimer() { */ protected void fireTimeoutTimer() { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("SIPServerTransaction.fireTimeoutTimer this = " + this + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("SIPServerTransaction.fireTimeoutTimer this = " + this + " current state = " + this.getRealState() + " method = " - + this.getMethod()); + + this.getOriginalRequest().getMethod()); - if (isInviteTransaction() && sipStack.removeTransactionPendingAck(this) ) { - if ( logger.isLoggingEnabled(LogWriter.TRACE_DEBUG) ) { - logger.logDebug("Found tx pending ACK - returning"); + if ( this.getMethod().equals(Request.INVITE) && sipStack.removeTransactionPendingAck(this) ) { + if ( sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG) ) { + sipStack.getStackLogger().logDebug("Found tx pending ACK - returning"); } return; - + } - SIPDialog dialog = (SIPDialog) getDialog(); - - - if (SIPTransactionStack.isDialogCreated(getMethod()) - && (TransactionState._CALLING == this.getRealState() || TransactionState._TRYING == this + SIPDialog dialog = (SIPDialog) this.dialog; + + + if (((SIPTransactionStack) getSIPStack()).isDialogCreated(this.getOriginalRequest() + .getMethod()) + && (TransactionState.CALLING == this.getRealState() || TransactionState.TRYING == this .getRealState())) { dialog.setState(SIPDialog.TERMINATED_STATE); - } else if (getMethod().equals(Request.BYE)) { + } else if (getOriginalRequest().getMethod().equals(Request.BYE)) { if (dialog != null && dialog.isTerminatedOnBye()) dialog.setState(SIPDialog.TERMINATED_STATE); } - if (TransactionState._COMPLETED == this.getRealState() && isInviteTransaction()) { + if (TransactionState.COMPLETED == this.getRealState() && isInviteTransaction()) { raiseErrorEvent(SIPTransactionErrorEvent.TIMEOUT_ERROR); - this.setState(TransactionState._TERMINATED); + this.setState(TransactionState.TERMINATED); sipStack.removeTransaction(this); - } else if (TransactionState._COMPLETED == this.getRealState() && !isInviteTransaction()) { - this.setState(TransactionState._TERMINATED); - if(!getMethod().equals(Request.CANCEL)) { - cleanUp(); - } else { - sipStack.removeTransaction(this); - } + } else if (TransactionState.COMPLETED == this.getRealState() && !isInviteTransaction()) { + this.setState(TransactionState.TERMINATED); + sipStack.removeTransaction(this); - } else if (TransactionState._CONFIRMED == this.getRealState() && isInviteTransaction()) { + } else if (TransactionState.CONFIRMED == this.getRealState() && isInviteTransaction()) { // TIMER_I should not generate a timeout // exception to the application when the // Invite transaction is in Confirmed state. // Just transition to Terminated state. - this.setState(TransactionState._TERMINATED); + this.setState(TransactionState.TERMINATED); sipStack.removeTransaction(this); } else if (!isInviteTransaction() - && (TransactionState._COMPLETED == this.getRealState() || TransactionState._CONFIRMED == this + && (TransactionState.COMPLETED == this.getRealState() || TransactionState.CONFIRMED == this .getRealState())) { - this.setState(TransactionState._TERMINATED); - } else if (isInviteTransaction() && TransactionState._TERMINATED == this.getRealState()) { + this.setState(TransactionState.TERMINATED); + } else if (isInviteTransaction() && TransactionState.TERMINATED == this.getRealState()) { // This state could be reached when retransmitting raiseErrorEvent(SIPTransactionErrorEvent.TIMEOUT_ERROR); @@ -1348,10 +1238,10 @@ protected void fireTimeoutTimer() { } /** - * Get the last response status code. + * Get the last response. */ - public int getLastResponseStatusCode() { - return this.lastResponseStatusCode; + public SIPResponse getLastResponse() { + return this.lastResponse; } /** @@ -1370,21 +1260,20 @@ public void setOriginalRequest(SIPRequest originalRequest) { public void sendResponse(Response response) throws SipException { SIPResponse sipResponse = (SIPResponse) response; - SIPDialog dialog = (SIPDialog) getDialog(); + SIPDialog dialog = this.dialog; if (response == null) throw new NullPointerException("null response"); try { sipResponse.checkHeaders(); } catch (ParseException ex) { - throw new IllegalTransactionStateException(ex.getMessage(), Reason.MissingRequiredHeader); + throw new SipException(ex.getMessage()); } // check for meaningful response. - final String responseMethod = sipResponse.getCSeq().getMethod(); - if (!responseMethod.equals(this.getMethod())) { - throw new IllegalTransactionStateException( - "CSeq method does not match Request method of request that created the tx.", Reason.UnmatchingCSeq); + if (!sipResponse.getCSeq().getMethod().equals(this.getMethod())) { + throw new SipException( + "CSeq method does not match Request method of request that created the tx."); } /* @@ -1392,11 +1281,10 @@ public void sendResponse(Response response) throws SipException { * period of time in the response MAY be shorter but MUST NOT be longer than specified in * the request. */ - final int statusCode = response.getStatusCode(); - if (this.getMethod().equals(Request.SUBSCRIBE) && statusCode / 100 == 2) { + if (this.getMethod().equals(Request.SUBSCRIBE) && response.getStatusCode() / 100 == 2) { if (response.getHeader(ExpiresHeader.NAME) == null) { - throw new IllegalTransactionStateException("Expires header is mandatory in 2xx response of SUBSCRIBE", Reason.ExpiresHeaderMandatory); + throw new SipException("Expires header is mandatory in 2xx response of SUBSCRIBE"); } else { Expires requestExpires = (Expires) this.getOriginalRequest().getExpires(); Expires responseExpires = (Expires) response.getExpires(); @@ -1414,10 +1302,10 @@ public void sendResponse(Response response) throws SipException { } // Check for mandatory header. - if (statusCode == 200 - && responseMethod.equals(Request.INVITE) + if (sipResponse.getStatusCode() == 200 + && sipResponse.getCSeq().getMethod().equals(Request.INVITE) && sipResponse.getHeader(ContactHeader.NAME) == null) - throw new IllegalTransactionStateException("Contact Header is mandatory for the OK to the INVITE", Reason.ContactHeaderMandatory); + throw new SipException("Contact Header is mandatory for the OK to the INVITE"); if (!this.isMessagePartOfTransaction((SIPMessage) response)) { throw new SipException("Response does not belong to this transaction."); @@ -1432,55 +1320,54 @@ public void sendResponse(Response response) throws SipException { * responses contained a session description. In that case, it MUST NOT send a final * response until those provisional responses are acknowledged. */ - final ContentTypeHeader contentTypeHeader = ((SIPResponse)response).getContentTypeHeader(); - if (this.pendingReliableResponseAsBytes != null - && this.getDialog() != null - && this.getInternalState() != TransactionState._TERMINATED - && statusCode / 100 == 2 - && contentTypeHeader != null - && contentTypeHeader.getContentType() - .equalsIgnoreCase(CONTENT_TYPE_APPLICATION) - && contentTypeHeader.getContentSubType() - .equalsIgnoreCase(CONTENT_SUBTYPE_SDP)) { + if (this.pendingReliableResponse != null + && this.getDialog() != null + && this.getState() != TransactionState.TERMINATED + && ((SIPResponse)response).getContentTypeHeader() != null + && response.getStatusCode() / 100 == 2 + && ((SIPResponse)response).getContentTypeHeader().getContentType() + .equalsIgnoreCase("application") + && ((SIPResponse)response).getContentTypeHeader().getContentSubType() + .equalsIgnoreCase("sdp")) { if (!interlockProvisionalResponses ) { - throw new SipException("cannot send response -- unacked provisional"); - } else { + throw new SipException("cannot send response -- unacked povisional"); + } else { try { boolean acquired = this.provisionalResponseSem.tryAcquire(1,TimeUnit.SECONDS); if (!acquired ) { - throw new SipException("cannot send response -- unacked provisional"); + throw new SipException("cannot send response -- unacked povisional"); } } catch (InterruptedException ex) { - logger.logError ("Interrupted acuqiring PRACK sem"); + sipStack.getStackLogger().logError ("Interrupted acuqiring PRACK sem"); throw new SipException("Cannot aquire PRACK sem"); } - + } } else { // Sending the final response cancels the // pending response task. - if (this.pendingReliableResponseAsBytes != null && sipResponse.isFinalResponse()) { - sipStack.getTimer().cancel(provisionalResponseTask); + if (this.pendingReliableResponse != null && sipResponse.isFinalResponse()) { + this.provisionalResponseTask.cancel(); this.provisionalResponseTask = null; - } + } } // Dialog checks. These make sure that the response // being sent makes sense. if (dialog != null) { - if (statusCode / 100 == 2 - && SIPTransactionStack.isDialogCreated(responseMethod)) { - if (dialog.getLocalTag() == null && sipResponse.getToTag() == null) { + if (sipResponse.getStatusCode() / 100 == 2 + && sipStack.isDialogCreated(sipResponse.getCSeq().getMethod())) { + if (dialog.getLocalTag() == null && sipResponse.getTo().getTag() == null) { // Trying to send final response and user forgot to set // to // tag on the response -- be nice and assign the tag for // the user. sipResponse.getTo().setTag(Utils.getInstance().generateTag()); } else if (dialog.getLocalTag() != null && sipResponse.getToTag() == null) { - if ( logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("assigning toTag : serverTransaction = " + this + " dialog " - + dialog + " tag = " + dialog.getLocalTag()); - } + if ( sipStack.getStackLogger().isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("assigning toTag : serverTransaction = " + this + " dialog " + + dialog + " tag = " + dialog.getLocalTag()); + } sipResponse.setToTag(dialog.getLocalTag()); } else if (dialog.getLocalTag() != null && sipResponse.getToTag() != null && !dialog.getLocalTag().equals(sipResponse.getToTag())) { @@ -1500,22 +1387,22 @@ public void sendResponse(Response response) throws SipException { // Backward compatibility slippery slope.... // Only set the from tag in the response when the // incoming request has a from tag. - String fromTag = originalRequestFromTag; - if(getRequest() != null) { - fromTag = ((SIPRequest) this.getRequest()).getFromTag(); - } + String fromTag = ((SIPRequest) this.getRequest()).getFrom().getTag(); if (fromTag != null && sipResponse.getFromTag() != null && !sipResponse.getFromTag().equals(fromTag)) { throw new SipException("From tag of request does not match response from tag"); } else if (fromTag != null) { sipResponse.getFrom().setTag(fromTag); } else { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("WARNING -- Null From tag in request!!"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("WARNING -- Null From tag in request!!"); } + + + // See if the dialog needs to be inserted into the dialog table // or if the state of the dialog needs to be changed. - if (dialog != null && statusCode != 100) { + if (dialog != null && response.getStatusCode() != 100) { dialog.setResponseTags(sipResponse); DialogState oldState = dialog.getState(); dialog.setLastResponse(this, (SIPResponse) response); @@ -1529,7 +1416,7 @@ public void sendResponse(Response response) throws SipException { } - } else if (dialog == null && isInviteTransaction() + } else if (dialog == null && this.getMethod().equals(Request.INVITE) && this.retransmissionAlertEnabled && this.retransmissionAlertTimerTask == null && response.getStatusCode() / 100 == 2) { @@ -1537,7 +1424,7 @@ public void sendResponse(Response response) throws SipException { this.retransmissionAlertTimerTask = new RetransmissionAlertTimerTask(dialogId); sipStack.retransmissionAlertTransactions.put(dialogId, this); - sipStack.getTimer().scheduleWithFixedDelay(this.retransmissionAlertTimerTask, 0, + sipStack.getTimer().schedule(this.retransmissionAlertTimerTask, 0, SIPTransactionStack.BASE_TIMER_INTERVAL); } @@ -1545,34 +1432,31 @@ public void sendResponse(Response response) throws SipException { // Send message after possibly inserting the Dialog // into the dialog table to avoid a possible race condition. - this.sendMessage((SIPResponse) response); - - - + if ( dialog != null ) { dialog.startRetransmitTimer(this, (SIPResponse)response); } } catch (IOException ex) { - if (logger.isLoggingEnabled()) - logger.logException(ex); - this.setState(TransactionState._TERMINATED); + if (sipStack.isLoggingEnabled()) + sipStack.getStackLogger().logException(ex); + this.setState(TransactionState.TERMINATED); raiseErrorEvent(SIPTransactionErrorEvent.TRANSPORT_ERROR); - throw new SipException(ex.getMessage(), ex); + throw new SipException(ex.getMessage()); } catch (java.text.ParseException ex1) { - if (logger.isLoggingEnabled()) - logger.logException(ex1); - this.setState(TransactionState._TERMINATED); - throw new SipException(ex1.getMessage(), ex1); + if (sipStack.isLoggingEnabled()) + sipStack.getStackLogger().logException(ex1); + this.setState(TransactionState.TERMINATED); + throw new SipException(ex1.getMessage()); } } /** * Return the book-keeping information that we actually use. */ - protected int getRealState() { - return super.getInternalState(); + private TransactionState getRealState() { + return super.getState(); } /** @@ -1584,7 +1468,7 @@ protected int getRealState() { */ public TransactionState getState() { // Trying is a pseudo state for INVITE transactions. - if (this.isInviteTransaction() && TransactionState._TRYING == super.getInternalState()) + if (this.isInviteTransaction() && TransactionState.TRYING == super.getState()) return TransactionState.PROCEEDING; else return super.getState(); @@ -1595,10 +1479,10 @@ public TransactionState getState() { * connection for outgoing requests in this time period) and calls the superclass to set * state. */ - public void setState(int newState) { + public void setState(TransactionState newState) { // Set this timer for connection caching // of incoming connections. - if (newState == TransactionState._TERMINATED && this.isReliable() + if (newState == TransactionState.TERMINATED && this.isReliable() && (!getSIPStack().cacheServerConnections)) { // Set a time after which the connection // is closed. @@ -1613,57 +1497,18 @@ public void setState(int newState) { * Start the timer task. */ protected void startTransactionTimer() { - if(getMethod().equalsIgnoreCase(Request.INVITE) || getMethod().equalsIgnoreCase(Request.CANCEL) || getMethod().equalsIgnoreCase(Request.ACK)) { - if (this.transactionTimerStarted.compareAndSet(false, true)) { - if (sipStack.getTimer() != null && sipStack.getTimer().isStarted() ) { - // The timer is set to null when the Stack is - // shutting down. - SIPStackTimerTask myTimer = new TransactionTimer(); - // Do not schedule when the stack is not alive. - if (sipStack.getTimer() != null && sipStack.getTimer().isStarted() ) { - sipStack.getTimer().scheduleWithFixedDelay(myTimer, BASE_TIMER_INTERVAL, BASE_TIMER_INTERVAL); - } - myTimer = null; - } - } - } - } - - /** - * Start the timer task. - */ - protected void startTransactionTimerJ(long time) { - if (this.transactionTimerStarted.compareAndSet(false, true)) { - if (sipStack.getTimer() != null && sipStack.getTimer().isStarted() ) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("starting TransactionTimerJ() : " + getTransactionId() + " time " + time); - } - // The timer is set to null when the Stack is - // shutting down. - SIPStackTimerTask task = new SIPStackTimerTask () { - - public void runTask() { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("executing TransactionTimerJ() : " + getTransactionId()); - } - fireTimeoutTimer(); - cleanUp(); - if(originalRequest != null) { - originalRequest.cleanUp(); - } - } - }; - if(time > 0) { - sipStack.getTimer().schedule(task, time * T1 * BASE_TIMER_INTERVAL); - } else { - task.runTask(); - } - } + if (this.transactionTimerStarted.compareAndSet(false, true)) { + if (sipStack.getTimer() != null) { + // The timer is set to null when the Stack is + // shutting down. + TimerTask myTimer = new TransactionTimer(); + sipStack.getTimer().schedule(myTimer, BASE_TIMER_INTERVAL, BASE_TIMER_INTERVAL); } + } } public boolean equals(Object other) { - if(other == null) return false; + if(other == null) return false; if (!other.getClass().equals(this.getClass())) { return false; } @@ -1677,10 +1522,8 @@ public boolean equals(Object other) { * @see gov.nist.javax.sip.stack.SIPTransaction#getDialog() */ public Dialog getDialog() { - if(dialog == null && dialogId != null) { - return sipStack.getDialog(dialogId); - } - return dialog; + + return this.dialog; } /* @@ -1690,14 +1533,13 @@ public Dialog getDialog() { * gov.nist.javax.sip.message.SIPMessage) */ public void setDialog(SIPDialog sipDialog, String dialogId) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("setDialog " + this + " dialog = " + sipDialog); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("setDialog " + this + " dialog = " + sipDialog); this.dialog = sipDialog; - this.dialogId = dialogId; if (dialogId != null) - sipDialog.setAssigned(); + this.dialog.setAssigned(); if (this.retransmissionAlertEnabled && this.retransmissionAlertTimerTask != null) { - sipStack.getTimer().cancel(retransmissionAlertTimerTask); + this.retransmissionAlertTimerTask.cancel(); if (this.retransmissionAlertTimerTask.dialogId != null) { sipStack.retransmissionAlertTransactions .remove(this.retransmissionAlertTimerTask.dialogId); @@ -1714,10 +1556,10 @@ public void setDialog(SIPDialog sipDialog, String dialogId) { * * @see javax.sip.Transaction#terminate() */ - public void terminate() throws ObjectInUseException { - this.setState(TransactionState._TERMINATED); + public void terminate() throws ObjectInUseException { + this.setState(TransactionState.TERMINATED); if (this.retransmissionAlertTimerTask != null) { - sipStack.getTimer().cancel(retransmissionAlertTimerTask); + this.retransmissionAlertTimerTask.cancel(); if (retransmissionAlertTimerTask.dialogId != null) { this.sipStack.retransmissionAlertTransactions .remove(retransmissionAlertTimerTask.dialogId); @@ -1730,6 +1572,7 @@ public void terminate() throws ObjectInUseException { testAndSetTransactionTerminatedEvent(); sipStack.removeTransaction(this); } + } protected void sendReliableProvisionalResponse(Response relResponse) throws SipException { @@ -1739,15 +1582,11 @@ protected void sendReliableProvisionalResponse(Response relResponse) throws SipE * UAS MAY send additional reliable provisional responses. The UAS MUST NOT send a second * reliable provisional response until the first is acknowledged. */ - if (this.pendingReliableResponseAsBytes != null) { + if (this.pendingReliableResponse != null) { throw new SipException("Unacknowledged response"); - } else { - SIPResponse reliableResponse = (SIPResponse) relResponse; - this.pendingReliableResponseAsBytes = reliableResponse.encodeAsBytes(this.getTransport()); - this.pendingReliableResponseMethod = reliableResponse.getCSeq().getMethod(); - this.pendingReliableCSeqNumber = reliableResponse.getCSeq().getSeqNumber(); - } + } else + this.pendingReliableResponse = (SIPResponse) relResponse; /* * In addition, it MUST contain a Require header field containing the option tag 100rel, * and MUST include an RSeq header field. @@ -1759,15 +1598,11 @@ protected void sendReliableProvisionalResponse(Response relResponse) throws SipE } try { - if(rseqNumber < 0) { - this.rseqNumber = (int) (Math.random() * 1000); - } this.rseqNumber++; rseq.setSeqNumber(this.rseqNumber); - this.pendingReliableRSeqNumber = rseq.getSeqNumber(); // start the timer task which will retransmit the reliable response - // until the PRACK is received. Cannot send a second provisional. + // until the PRACK is received. Cannot send a second provisional. this.lastResponse = (SIPResponse) relResponse; if ( this.getDialog() != null && interlockProvisionalResponses ) { boolean acquired = this.provisionalResponseSem.tryAcquire(1, TimeUnit.SECONDS); @@ -1775,10 +1610,10 @@ protected void sendReliableProvisionalResponse(Response relResponse) throws SipE throw new SipException("Unacknowledged reliable response"); } } - //moved the task scheduling before the sending of the message to overcome + //moved the task scheduling before the sending of the message to overcome // Issue 265 : https://jain-sip.dev.java.net/issues/show_bug.cgi?id=265 this.provisionalResponseTask = new ProvisionalResponseTask(); - this.sipStack.getTimer().scheduleWithFixedDelay(provisionalResponseTask, 0, + this.sipStack.getTimer().schedule(provisionalResponseTask, 0, SIPTransactionStack.BASE_TIMER_INTERVAL); this.sendMessage((SIPMessage) relResponse); } catch (Exception ex) { @@ -1787,9 +1622,9 @@ protected void sendReliableProvisionalResponse(Response relResponse) throws SipE } - public byte[] getReliableProvisionalResponse() { + public SIPResponse getReliableProvisionalResponse() { - return this.pendingReliableResponseAsBytes; + return this.pendingReliableResponse; } /** @@ -1800,15 +1635,15 @@ public byte[] getReliableProvisionalResponse() { */ public boolean prackRecieved() { - if (this.pendingReliableResponseAsBytes == null) + if (this.pendingReliableResponse == null) return false; - if(provisionalResponseTask != null) { - sipStack.getTimer().cancel(provisionalResponseTask); - this.provisionalResponseTask = null; - } - - this.pendingReliableResponseAsBytes = null; - if ( interlockProvisionalResponses && getDialog() != null ) { + if(provisionalResponseTask != null) { + this.provisionalResponseTask.cancel(); + this.provisionalResponseTask = null; + } + + this.pendingReliableResponse = null; + if ( interlockProvisionalResponses && this.dialog != null ) { this.provisionalResponseSem.release(); } return true; @@ -1824,7 +1659,7 @@ public void enableRetransmissionAlerts() throws SipException { if (this.getDialog() != null) throw new SipException("Dialog associated with tx"); - else if (!isInviteTransaction()) + else if (!this.getMethod().equals(Request.INVITE)) throw new SipException("Request Method must be INVITE"); this.retransmissionAlertEnabled = true; @@ -1841,7 +1676,7 @@ public boolean isRetransmissionAlertEnabled() { */ public void disableRetransmissionAlerts() { if (this.retransmissionAlertTimerTask != null && this.retransmissionAlertEnabled) { - sipStack.getTimer().cancel(retransmissionAlertTimerTask); + this.retransmissionAlertTimerTask.cancel(); this.retransmissionAlertEnabled = false; String dialogId = this.retransmissionAlertTimerTask.dialogId; @@ -1868,6 +1703,7 @@ public boolean ackSeen() { public void setMapped(boolean b) { this.isMapped = true; + } public void setPendingSubscribe(SIPClientTransaction pendingSubscribeClientTx) { @@ -1921,154 +1757,5 @@ public void scheduleAckRemoval() throws IllegalStateException { this.startTransactionTimer(); } - - // jeand cleanup the state of the stx to help GC - public void cleanUp() { - // Remove it from the set - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("removing" + this); - - if(isReleaseReferences()) { - - // release the connection associated with this transaction. - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("cleanup : " - + getTransactionId()); - } - // we keep the request in a byte array to be able to recreate it - // no matter what to keep API backward compatibility - if(originalRequest == null && originalRequestBytes != null) { - try { - originalRequest = (SIPRequest) sipStack.getMessageParserFactory().createMessageParser(sipStack).parseSIPMessage(originalRequestBytes, true, false, null); -// originalRequestBytes = null; - } catch (ParseException e) { - logger.logError("message " + originalRequestBytes + "could not be reparsed !"); - } - } else if (originalRequest != null && originalRequestBytes == null) { - originalRequestBytes = originalRequest.encodeAsBytes(this.getTransport()); - } - sipStack.removeTransaction(this); - cleanUpOnTimer(); - // commented out because the application can hold on a ref to the tx - // after it has been removed from the stack - // and want to get the request or branch from it -// originalRequestBytes = null; -// originalRequestBranch = null; - originalRequestFromTag = null; - originalRequestSentBy = null; - // it should be available in the processTxTerminatedEvent, so we can nullify it only here - if(originalRequest != null) { - // originalRequestSentBy = originalRequest.getTopmostVia().getSentBy(); - // originalRequestFromTag = originalRequest.getFromTag(); - originalRequest = null; - } - if(!isReliable() && inviteTransaction != null) { - inviteTransaction = null; - } - // Application Data has to be cleared by the application - // applicationData = null; - lastResponse = null; - // Issue 318 : (https://jain-sip.dev.java.net/issues/show_bug.cgi?id=318) - // Re-transmission of 200 to INVITE terminates prematurely : - // don't nullify since the transaction may be terminated - // but the ack not received so the 200 retransmissions should continue -// lastResponseAsBytes = null; - - // don't clean up because on sending 200 OK to CANCEL otherwise we try to start the transaction timer - // but due to timer J it has already been cleaned up -// transactionTimerStarted = null; - } else { - sipStack.removeTransaction(this); - } - - // Uncache the server tx - if ((!sipStack.cacheServerConnections) - && --getMessageChannel().useCount <= 0) { - // Close the encapsulated socket if stack is configured - close(); - } else { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG) - && (!sipStack.cacheServerConnections) - && isReliable()) { - int useCount = getMessageChannel().useCount; - logger.logDebug("Use Count = " + useCount); - } - } - - } - - // clean up the state of the stx when it goes to completed or terminated to help GC - protected void cleanUpOnTimer() { - if(isReleaseReferences()) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("cleanup on timer : " - + getTransactionId()); - } - if(dialog != null && getMethod().equals(Request.CANCEL)) { - // used to deal with getting the dialog on cancel tx after the 200 OK to CANCEL has been sent - dialogId = dialog.getDialogId(); - } - dialog = null; - // we don't nullify the inviteTx for CANCEL since the app can get it from getCanceledInviteTransaction - if(inviteTransaction != null && !getMethod().equals(Request.CANCEL)) { - // we release the semaphore for Cancel processing - inviteTransaction.releaseSem(); - inviteTransaction = null; - } - if(originalRequest != null) { - originalRequest.setTransaction(null); - originalRequest.setInviteTransaction(null); - if(!getMethod().equalsIgnoreCase(Request.INVITE)) { - if(originalRequestSentBy == null) { - originalRequestSentBy = originalRequest.getTopmostVia().getSentBy(); - } - if(originalRequestFromTag == null) { - originalRequestFromTag = originalRequest.getFromTag(); - } - } - // we keep the request in a byte array to be able to recreate it - // no matter what to keep API backward compatibility - if(originalRequestBytes == null) { - originalRequestBytes = originalRequest.encodeAsBytes(this.getTransport()); - } - if(!getMethod().equalsIgnoreCase(Request.INVITE) && !getMethod().equalsIgnoreCase(Request.CANCEL)) { - originalRequest = null; - } - } - if(lastResponse != null) { - lastResponseAsBytes = lastResponse.encodeAsBytes(this.getTransport()); - lastResponse = null; - } - pendingReliableResponseAsBytes = null; - pendingReliableResponseMethod = null; - pendingSubscribeTransaction = null; - provisionalResponseSem = null; - retransmissionAlertTimerTask = null; - requestOf = null; - messageProcessor = null; - } - } - - /** - * @return the pendingReliableResponseMethod - */ - public String getPendingReliableResponseMethod() { - return pendingReliableResponseMethod; - } - - /** - * @return the pendingReliableCSeqNumber - */ - public long getPendingReliableCSeqNumber() { - return pendingReliableCSeqNumber; - } - - /** - * @return the pendingReliableRSeqNumber - */ - public long getPendingReliableRSeqNumber() { - return pendingReliableRSeqNumber; - } - - + } diff --git a/src/gov/nist/javax/sip/stack/SIPStackTimerTask.java b/src/gov/nist/javax/sip/stack/SIPStackTimerTask.java index 8e593faba..d74dad42d 100644 --- a/src/gov/nist/javax/sip/stack/SIPStackTimerTask.java +++ b/src/gov/nist/javax/sip/stack/SIPStackTimerTask.java @@ -1,13 +1,14 @@ /* * @author: Brett Buckingham - * @author: Last modified by: $Author: deruelle_jean $ - * @version: $Date: 2010-05-06 14:08:11 $ $Revision: 1.4 $ + * @author: Last modified by: $Author: emcho $ + * @version: $Date: 2009-07-17 18:58:14 $ $Revision: 1.3 $ * * This source code has been contributed to the public domain. */ package gov.nist.javax.sip.stack; +import java.util.TimerTask; /** * A subclass of TimerTask which runs TimerTask code within a try/catch block to @@ -17,21 +18,18 @@ * @author Brett Buckingham * */ -public abstract class SIPStackTimerTask { - // the underlying timer task that was scheduled in the Stack SIP timer - Object timerTask = null; - // Implements code to be run when the SIPStackTimerTask is executed. - public abstract void runTask(); - - public void cleanUpBeforeCancel() { - - } - - public void setSipTimerTask(Object timer) { - timerTask = timer; - } +public abstract class SIPStackTimerTask extends TimerTask { + // / Implements code to be run when the SIPStackTimerTask is executed. + protected abstract void runTask(); - public Object getSipTimerTask() { - return timerTask; - } + // / The run() method is final to ensure that all subclasses inherit the + // exception handling. + public final void run() { + try { + runTask(); + } catch (Throwable e) { + System.out.println("SIP stack timer task failed due to exception:"); + e.printStackTrace(); + } + } } diff --git a/src/gov/nist/javax/sip/stack/SIPTransaction.java b/src/gov/nist/javax/sip/stack/SIPTransaction.java index 92fdae2b6..fd5efb80c 100755 --- a/src/gov/nist/javax/sip/stack/SIPTransaction.java +++ b/src/gov/nist/javax/sip/stack/SIPTransaction.java @@ -25,21 +25,21 @@ */ package gov.nist.javax.sip.stack; -import gov.nist.core.CommonLogger; import gov.nist.core.InternalErrorHandler; -import gov.nist.core.LogLevels; import gov.nist.core.LogWriter; +import gov.nist.javax.sip.address.AddressFactoryImpl; import gov.nist.core.ServerLogger; -import gov.nist.core.StackLogger; import gov.nist.javax.sip.SIPConstants; import gov.nist.javax.sip.SipProviderImpl; -import gov.nist.javax.sip.SipStackImpl; -import gov.nist.javax.sip.address.AddressFactoryImpl; +import gov.nist.javax.sip.header.CallID; +import gov.nist.javax.sip.header.Event; +import gov.nist.javax.sip.header.From; +import gov.nist.javax.sip.header.To; import gov.nist.javax.sip.header.Via; +import gov.nist.javax.sip.header.ViaList; import gov.nist.javax.sip.message.SIPMessage; import gov.nist.javax.sip.message.SIPRequest; import gov.nist.javax.sip.message.SIPResponse; -import gov.nist.javax.sip.stack.SIPClientTransaction.ExpiresTimerTask; import java.io.IOException; import java.net.InetAddress; @@ -49,20 +49,21 @@ import java.text.ParseException; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; -import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.locks.ReentrantLock; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.net.ssl.SSLPeerUnverifiedException; import javax.sip.Dialog; import javax.sip.IOExceptionEvent; +import javax.sip.ServerTransaction; import javax.sip.TransactionState; import javax.sip.address.SipURI; import javax.sip.message.Request; @@ -82,11 +83,11 @@ * @author M. Ranganathan * * - * @version 1.2 $Revision: 1.100 $ $Date: 2010-12-02 22:04:13 $ + * @version 1.2 $Revision: 1.75.2.7 $ $Date: 2010-11-23 19:23:14 $ */ public abstract class SIPTransaction extends MessageChannel implements javax.sip.Transaction, gov.nist.javax.sip.TransactionExt { - private static StackLogger logger = CommonLogger.getLogger(SIPTransaction.class); + protected boolean toListener; // Flag to indicate that the listener gets // to see the event. @@ -140,7 +141,9 @@ public abstract class SIPTransaction extends MessageChannel implements protected boolean isMapped; - private TransactionSemaphore semaphore; + private Semaphore semaphore; + + protected boolean isSemaphoreAquired; // protected boolean eventPending; // indicate that an event is pending // here. @@ -195,17 +198,28 @@ public abstract class SIPTransaction extends MessageChannel implements // Original request that is being handled by this transaction protected SIPRequest originalRequest; - //jeand we nullify the originalRequest fast to save on mem and help GC - // so we keep only those data instead - protected byte[] originalRequestBytes; - protected long originalRequestCSeqNumber; - protected String originalRequestBranch; - protected boolean originalRequestHasPort; - - + // Underlying channel being used to send messages for this transaction private transient MessageChannel encapsulatedChannel; + // Port of peer + protected int peerPort; + + // Address of peer + protected InetAddress peerInetAddress; + + // Address of peer as a string + protected String peerAddress; + + // Protocol of peer + protected String peerProtocol; + + // @@@ hagai - NAT changes + // Source port extracted from peer packet + protected int peerPacketSourcePort; + + protected InetAddress peerPacketSourceAddress; + protected AtomicBoolean transactionTimerStarted = new AtomicBoolean(false); // Transaction branch ID @@ -214,8 +228,11 @@ public abstract class SIPTransaction extends MessageChannel implements // Method of the Request used to create the transaction. private String method; + // Sequence number of request used to create the transaction + private long cSeq; + // Current transaction state - private int currentState = -1; + private TransactionState currentState; // Number of ticks the retransmission timer was set to last private transient int retransmissionTimerLastTickCount; @@ -229,96 +246,36 @@ public abstract class SIPTransaction extends MessageChannel implements // List of event listeners for this transaction private transient Set eventListeners; + // Hang on to these - we clear out the request URI after + // transaction goes to final state. Pointers to these are kept around + // for transaction matching as long as the transaction is in + // the transaction table. + protected From from; + + protected To to; + + protected Event event; + + protected CallID callId; + + // Back ptr to the JAIN layer. + // private Object wrapper; // Counter for caching of connections. // Connection lingers for collectionTime // after the Transaction goes to terminated state. protected int collectionTime; - private boolean terminatedEventDelivered; - - // aggressive flag to optimize eagerly - private boolean releaseReferences; - - // caching flags - private Boolean inviteTransaction = null; - private Boolean dialogCreatingTransaction = null; - - // caching fork id - private String forkId = null; - - public ExpiresTimerTask expiresTimerTask; + protected String toTag; + + protected String fromTag; + + private boolean terminatedEventDelivered; public String getBranchId() { return this.branch; } - // [Issue 284] https://jain-sip.dev.java.net/issues/show_bug.cgi?id=284 - // JAIN SIP drops 200 OK due to race condition - // Wrapper that uses a semaphore for non reentrant listener - // and a lock for reetrant listener to avoid race conditions - // when 2 responses 180/200 OK arrives at the same time - class TransactionSemaphore { - - private static final long serialVersionUID = -1634100711669020804L; - Semaphore sem = null; - ReentrantLock lock = null; - - public TransactionSemaphore() { - if(((SipStackImpl)getSIPStack()).isReEntrantListener()) { - lock = new ReentrantLock(); - } else { - sem = new Semaphore(1, true); - } - } - - public boolean acquire() { - try { - if(((SipStackImpl)getSIPStack()).isReEntrantListener()) { - lock.lock(); - } else { - sem.acquire(); - } - return true; - } catch (Exception ex) { - logger.logError("Unexpected exception acquiring sem", - ex); - InternalErrorHandler.handleException(ex); - return false; - } - } - - public boolean tryAcquire() { - try { - if(((SipStackImpl)getSIPStack()).isReEntrantListener()) { - return lock.tryLock(sipStack.maxListenerResponseTime, TimeUnit.SECONDS); - } else { - return sem.tryAcquire(sipStack.maxListenerResponseTime, TimeUnit.SECONDS); - } - } catch (Exception ex) { - logger.logError("Unexpected exception trying acquiring sem", - ex); - InternalErrorHandler.handleException(ex); - return false; - } - } - - public void release() { - try { - if(((SipStackImpl)getSIPStack()).isReEntrantListener()) { - if(lock.isHeldByCurrentThread()) { - lock.unlock(); - } - } else { - sem.release(); - } - } catch (Exception ex) { - logger.logError("Unexpected exception releasing sem", - ex); - } - } - } - /** * The linger timer is used to remove the transaction from the transaction * table after it goes into terminated state. This allows connection caching @@ -328,17 +285,48 @@ public void release() { */ class LingerTimer extends SIPStackTimerTask { - public LingerTimer() { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - SIPTransaction sipTransaction = SIPTransaction.this; - logger.logDebug("LingerTimer : " + public LingerTimer() { + SIPTransaction sipTransaction = SIPTransaction.this; + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("LingerTimer : " + sipTransaction.getTransactionId()); } } - public void runTask() { - cleanUp(); + protected void runTask() { + SIPTransaction transaction = SIPTransaction.this; + // release the connection associated with this transaction. + SIPTransactionStack sipStack = transaction.getSIPStack(); + + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("LingerTimer: run() : " + + getTransactionId()); + } + + if (transaction instanceof SIPClientTransaction) { + sipStack.removeTransaction(transaction); + transaction.close(); + + } else if (transaction instanceof ServerTransaction) { + // Remove it from the set + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("removing" + transaction); + sipStack.removeTransaction(transaction); + if ((!sipStack.cacheServerConnections) + && --transaction.encapsulatedChannel.useCount <= 0) { + // Close the encapsulated socket if stack is configured + transaction.close(); + } else { + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG) + && (!sipStack.cacheServerConnections) + && transaction.isReliable()) { + int useCount = transaction.encapsulatedChannel.useCount; + sipStack.getStackLogger().logDebug("Use Count = " + useCount); + } + } + } + } } @@ -354,36 +342,43 @@ protected SIPTransaction(SIPTransactionStack newParentStack, MessageChannel newEncapsulatedChannel) { sipStack = newParentStack; - this.semaphore = new TransactionSemaphore(); + this.semaphore = new Semaphore(1,true); encapsulatedChannel = newEncapsulatedChannel; - + // Record this to check if the address has changed before sending + // message to avoid possible race condition. + this.peerPort = newEncapsulatedChannel.getPeerPort(); + this.peerAddress = newEncapsulatedChannel.getPeerAddress(); + this.peerInetAddress = newEncapsulatedChannel.getPeerInetAddress(); + // @@@ hagai + this.peerPacketSourcePort = newEncapsulatedChannel + .getPeerPacketSourcePort(); + this.peerPacketSourceAddress = newEncapsulatedChannel + .getPeerPacketSourceAddress(); + this.peerProtocol = newEncapsulatedChannel.getPeerProtocol(); if (this.isReliable()) { encapsulatedChannel.useCount++; - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger() .logDebug("use count for encapsulated channel" + this + " " + encapsulatedChannel.useCount ); } - this.currentState = -1; + this.currentState = null; disableRetransmissionTimer(); disableTimeoutTimer(); - eventListeners = new CopyOnWriteArraySet(); + eventListeners = Collections.synchronizedSet(new HashSet()); // Always add the parent stack as a listener // of this transaction addEventListener(newParentStack); - releaseReferences = sipStack.isAggressiveCleanup(); } - public abstract void cleanUp(); - - /** + /** * Sets the request message that this transaction handles. * * @param newOriginalRequest @@ -394,52 +389,46 @@ public void setOriginalRequest(SIPRequest newOriginalRequest) { // Branch value of topmost Via header String newBranch; - final String newTransactionId = newOriginalRequest.getTransactionId(); if (this.originalRequest != null && (!this.originalRequest.getTransactionId().equals( - newTransactionId))) { + newOriginalRequest.getTransactionId()))) { sipStack.removeTransactionHash(this); } // This will be cleared later. this.originalRequest = newOriginalRequest; - this.originalRequestCSeqNumber = newOriginalRequest.getCSeq().getSeqNumber(); - final Via topmostVia = newOriginalRequest.getTopmostVia(); - this.originalRequestBranch = topmostVia.getBranch(); - this.originalRequestHasPort = topmostVia.hasPort(); - int originalRequestViaPort = topmostVia.getPort(); - - if ( originalRequestViaPort == -1 ) { - if (topmostVia.getTransport().equalsIgnoreCase("TLS") ) { - originalRequestViaPort = 5061; - } else { - originalRequestViaPort = 5060; - } - } - + // just cache the control information so the // original request can be released later. this.method = newOriginalRequest.getMethod(); - - this.transactionId = newTransactionId; + this.from = (From) newOriginalRequest.getFrom(); + this.to = (To) newOriginalRequest.getTo(); + // Save these to avoid concurrent modification exceptions! + this.toTag = this.to.getTag(); + this.fromTag = this.from.getTag(); + this.callId = (CallID) newOriginalRequest.getCallId(); + this.cSeq = newOriginalRequest.getCSeq().getSeqNumber(); + this.event = (Event) newOriginalRequest.getHeader("Event"); + this.transactionId = newOriginalRequest.getTransactionId(); originalRequest.setTransaction(this); // If the message has an explicit branch value set, - newBranch = topmostVia.getBranch(); + newBranch = ((Via) newOriginalRequest.getViaHeaders().getFirst()) + .getBranch(); if (newBranch != null) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("Setting Branch id : " + newBranch); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Setting Branch id : " + newBranch); // Override the default branch with the one // set by the message setBranch(newBranch); } else { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("Branch id is null - compute TID!" + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Branch id is null - compute TID!" + newOriginalRequest.encode()); - setBranch(newTransactionId); + setBranch(newOriginalRequest.getTransactionId()); } } @@ -449,7 +438,7 @@ public void setOriginalRequest(SIPRequest newOriginalRequest) { * @return -- the original Request associated with this transaction. */ public SIPRequest getOriginalRequest() { - return this.originalRequest; + return originalRequest; } /** @@ -458,32 +447,9 @@ public SIPRequest getOriginalRequest() { * @return the request that generated this transaction. */ public Request getRequest() { - if(isReleaseReferences() && originalRequest == null && originalRequestBytes != null) { - if(logger.isLoggingEnabled(StackLogger.TRACE_WARN)) { - logger.logWarning("reparsing original request " + originalRequestBytes + " since it was eagerly cleaned up, but beware this is not efficient with the aggressive flag set !"); - } - try { - originalRequest = (SIPRequest) sipStack.getMessageParserFactory().createMessageParser(sipStack).parseSIPMessage(originalRequestBytes, true, false, null); -// originalRequestBytes = null; - } catch (ParseException e) { - logger.logError("message " + originalRequestBytes + " could not be reparsed !"); - } - } return (Request) originalRequest; } - /** - * Returns a flag stating whether this transaction is for a request that creates a dialog. - * - * @return -- true if this is a request that creates a dialog, false if not. - */ - public final boolean isDialogCreatingTransaction() { - if (dialogCreatingTransaction == null) { - dialogCreatingTransaction = Boolean.valueOf(isInviteTransaction() || getMethod().equals(Request.SUBSCRIBE) || getMethod().equals(Request.REFER)); - } - return dialogCreatingTransaction.booleanValue(); - } - /** * Returns a flag stating whether this transaction is for an INVITE request * or not. @@ -491,10 +457,7 @@ public final boolean isDialogCreatingTransaction() { * @return -- true if this is an INVITE request, false if not. */ public final boolean isInviteTransaction() { - if (inviteTransaction == null) { - inviteTransaction = Boolean.valueOf(getMethod().equals(Request.INVITE)); - } - return inviteTransaction.booleanValue(); + return getMethod().equals(Request.INVITE); } /** @@ -543,7 +506,7 @@ public final void setBranch(String newBranch) { */ public final String getBranch() { if (this.branch == null) { - this.branch = originalRequestBranch; + this.branch = getOriginalRequest().getTopmostVia().getBranch(); } return branch; } @@ -563,7 +526,7 @@ public final String getMethod() { * @return the cseq of the request used to create the transaction. */ public final long getCSeq() { - return this.originalRequestCSeqNumber; + return this.cSeq; } /** @@ -572,49 +535,37 @@ public final long getCSeq() { * @param newState * New state of this transaction. */ - public void setState(int newState) { + public void setState(TransactionState newState) { // PATCH submitted by sribeyron - if (currentState == TransactionState._COMPLETED) { - if (newState != TransactionState._TERMINATED - && newState != TransactionState._CONFIRMED) - newState = TransactionState._COMPLETED; + if (currentState == TransactionState.COMPLETED) { + if (newState != TransactionState.TERMINATED + && newState != TransactionState.CONFIRMED) + newState = TransactionState.COMPLETED; } - if (currentState == TransactionState._CONFIRMED) { - if (newState != TransactionState._TERMINATED) - newState = TransactionState._CONFIRMED; + if (currentState == TransactionState.CONFIRMED) { + if (newState != TransactionState.TERMINATED) + newState = TransactionState.CONFIRMED; } - if (currentState != TransactionState._TERMINATED) + if (currentState != TransactionState.TERMINATED) currentState = newState; else newState = currentState; // END OF PATCH - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("Transaction:setState " + newState + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("Transaction:setState " + newState + " " + this + " branchID = " + this.getBranch() + " isClient = " + (this instanceof SIPClientTransaction)); - logger.logStackTrace(); + sipStack.getStackLogger().logStackTrace(); } } - /** - * Gets the current state of this transaction. - * - * @return Current state of this transaction. - */ - public int getInternalState() { - return this.currentState; - } - /** * Gets the current state of this transaction. * * @return Current state of this transaction. */ public TransactionState getState() { - if(currentState < 0) { - return null; - } - return TransactionState.getObject(this.currentState); + return this.currentState; } /** @@ -660,8 +611,8 @@ protected final void disableRetransmissionTimer() { * Number of ticks before this transaction times out. */ protected final void enableTimeoutTimer(int tickCount) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("enableTimeoutTimer " + this + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("enableTimeoutTimer " + this + " tickCount " + tickCount + " currentTickCount = " + timeoutTimerTicksLeft); @@ -709,7 +660,7 @@ final void fireTimer() { * @return Trus if this transaction is terminated, false if not. */ public final boolean isTerminated() { - return currentState == TransactionState._TERMINATED; + return getState() == TERMINATED_STATE; } public String getHost() { @@ -729,28 +680,28 @@ public SIPTransactionStack getSIPStack() { } public String getPeerAddress() { - return this.encapsulatedChannel.getPeerAddress(); + return this.peerAddress; } public int getPeerPort() { - return this.encapsulatedChannel.getPeerPort(); + return this.peerPort; } // @@@ hagai public int getPeerPacketSourcePort() { - return this.encapsulatedChannel.getPeerPacketSourcePort(); + return this.peerPacketSourcePort; } public InetAddress getPeerPacketSourceAddress() { - return this.encapsulatedChannel.getPeerPacketSourceAddress(); + return this.peerPacketSourceAddress; } protected InetAddress getPeerInetAddress() { - return this.encapsulatedChannel.getPeerInetAddress(); + return this.peerInetAddress; } protected String getPeerProtocol() { - return this.encapsulatedChannel.getPeerProtocol(); + return this.peerProtocol; } public String getTransport() { @@ -811,8 +762,8 @@ public void run() { ((TCPMessageChannel) channel) .processMessage((SIPMessage) messageToSend.clone(), getPeerInetAddress()); } catch (Exception ex) { - if (logger.isLoggingEnabled(ServerLogger.TRACE_ERROR)) { - logger.logError("Error self routing message cause by: ", ex); + if (getSIPStack().getStackLogger().isLoggingEnabled(ServerLogger.TRACE_ERROR)) { + getSIPStack().getStackLogger().logError("Error self routing message cause by: ", ex); } } } @@ -820,10 +771,10 @@ public void run() { getSIPStack().getSelfRoutingThreadpoolExecutor().execute(processMessageTask); } catch (Exception e) { - logger.logError("Error passing message in self routing", e); + sipStack.getStackLogger().logError("Error passing message in self routing", e); } - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug("Self routing message"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Self routing message"); return; } if (channel instanceof RawMessageChannel) { @@ -835,25 +786,25 @@ public void run() { try { ((RawMessageChannel) channel).processMessage((SIPMessage) messageToSend.clone()); } catch (Exception ex) { - if (logger.isLoggingEnabled(ServerLogger.TRACE_ERROR)) { - logger.logError("Error self routing message cause by: ", ex); + if (getSIPStack().getStackLogger().isLoggingEnabled(ServerLogger.TRACE_ERROR)) { + getSIPStack().getStackLogger().logError("Error self routing message cause by: ", ex); } } } }; getSIPStack().getSelfRoutingThreadpoolExecutor().execute(processMessageTask); } catch (Exception e) { - logger.logError("Error passing message in self routing", e); + sipStack.getStackLogger().logError("Error passing message in self routing", e); } - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug("Self routing message"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Self routing message"); return; } } } encapsulatedChannel.sendMessage(messageToSend, - this.getPeerInetAddress(), this.getPeerPort()); + this.peerInetAddress, this.peerPort); } finally { this.startTransactionTimer(); } @@ -938,7 +889,7 @@ protected void raiseErrorEvent(int errorEventID) { eventListeners.clear(); // Errors always terminate a transaction - this.setState(TransactionState._TERMINATED); + this.setState(TransactionState.TERMINATED); if (this instanceof SIPServerTransaction && this.isByeTransaction() && this.getDialog() != null) @@ -1050,7 +1001,7 @@ public int getViaPort() { public boolean doesCancelMatchTransaction(SIPRequest requestToTest) { // List of Via headers in the message to test -// ViaList viaHeaders; + ViaList viaHeaders; // Topmost Via header in the list Via topViaHeader; // Branch code in the topmost Via header @@ -1059,15 +1010,15 @@ public boolean doesCancelMatchTransaction(SIPRequest requestToTest) { boolean transactionMatches; transactionMatches = false; - final SIPRequest origRequest = getOriginalRequest(); - if (origRequest == null - || this.getMethod().equals(Request.CANCEL)) + + if (this.getOriginalRequest() == null + || this.getOriginalRequest().getMethod().equals(Request.CANCEL)) return false; // Get the topmost Via header and its branch parameter - topViaHeader = requestToTest.getTopmostVia(); - if (topViaHeader != null) { + viaHeaders = requestToTest.getViaHeaders(); + if (viaHeaders != null) { -// topViaHeader = (Via) viaHeaders.getFirst(); + topViaHeader = (Via) viaHeaders.getFirst(); messageBranch = topViaHeader.getBranch(); if (messageBranch != null) { @@ -1091,10 +1042,11 @@ public boolean doesCancelMatchTransaction(SIPRequest requestToTest) { // this message, if (getBranch().equalsIgnoreCase(messageBranch) && topViaHeader.getSentBy().equals( - origRequest.getTopmostVia().getSentBy())) { + ((Via) getOriginalRequest().getViaHeaders() + .getFirst()).getSentBy())) { transactionMatches = true; - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("returning true"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("returning true"); } } else { @@ -1102,21 +1054,22 @@ public boolean doesCancelMatchTransaction(SIPRequest requestToTest) { // If RequestURI, To tag, From tag, // CallID, CSeq number, and top Via // headers are the same, - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("testing against " - + origRequest); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("testing against " + + getOriginalRequest()); - if (origRequest.getRequestURI().equals( + if (getOriginalRequest().getRequestURI().equals( requestToTest.getRequestURI()) - && origRequest.getTo().equals( + && getOriginalRequest().getTo().equals( requestToTest.getTo()) - && origRequest.getFrom().equals( + && getOriginalRequest().getFrom().equals( requestToTest.getFrom()) - && origRequest.getCallId().getCallId().equals( + && getOriginalRequest().getCallId().getCallId().equals( requestToTest.getCallId().getCallId()) - && origRequest.getCSeq().getSeqNumber() == requestToTest + && getOriginalRequest().getCSeq().getSeqNumber() == requestToTest .getCSeq().getSeqNumber() - && topViaHeader.equals(origRequest.getTopmostVia())) { + && topViaHeader.equals(getOriginalRequest() + .getViaHeaders().getFirst())) { transactionMatches = true; } @@ -1167,8 +1120,8 @@ public void setRetransmitTimer(int retransmitTimer) { */ public void close() { this.encapsulatedChannel.close(); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("Closing " + this.encapsulatedChannel); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Closing " + this.encapsulatedChannel); } @@ -1213,7 +1166,9 @@ public void setEncapsulatedChannel(MessageChannel messageChannel) { this.encapsulatedChannel = messageChannel; if ( this instanceof SIPClientTransaction ) { this.encapsulatedChannel.setEncapsulatedClientTransaction((SIPClientTransaction) this); - } + } + this.peerInetAddress = messageChannel.getPeerInetAddress(); + this.peerPort = messageChannel.getPeerPort(); } /** @@ -1232,7 +1187,7 @@ public SipProviderImpl getSipProvider() { * */ public void raiseIOExceptionEvent() { - setState(TransactionState._TERMINATED); + setState(TransactionState.TERMINATED); String host = getPeerAddress(); int port = getPeerPort(); String transport = getTransport(); @@ -1248,21 +1203,31 @@ public void raiseIOExceptionEvent() { */ public boolean acquireSem() { boolean retval = false; - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("acquireSem [[[[" + this); - logger.logStackTrace(); - } - if ( this.sipStack.maxListenerResponseTime == -1 ) { - retval = this.semaphore.acquire(); - } else { - retval = this.semaphore.tryAcquire(); + try { + if (sipStack.getStackLogger().isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("acquireSem [[[[" + this); + sipStack.getStackLogger().logStackTrace(); + } + if ( this.sipStack.maxListenerResponseTime == -1 ) { + this.semaphore.acquire(); + retval = true; + } else { + retval = this.semaphore.tryAcquire(this.sipStack.maxListenerResponseTime, TimeUnit.SECONDS); + } + if ( sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug( + "acquireSem() returning : " + retval); + return retval; + } catch (Exception ex) { + sipStack.getStackLogger().logError("Unexpected exception acquiring sem", + ex); + InternalErrorHandler.handleException(ex); + return false; + } finally { + this.isSemaphoreAquired = retval; } - if ( logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug( - "acquireSem() returning : " + retval); - return retval; + } - /** * Release the transaction semaphore. @@ -1275,7 +1240,7 @@ public void releaseSem() { this.semRelease(); } catch (Exception ex) { - logger.logError("Unexpected exception releasing sem", + sipStack.getStackLogger().logError("Unexpected exception releasing sem", ex); } @@ -1283,11 +1248,19 @@ public void releaseSem() { } protected void semRelease() { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("semRelease ]]]]" + this); - logger.logStackTrace(); + try { + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("semRelease ]]]]" + this); + sipStack.getStackLogger().logStackTrace(); + } + this.isSemaphoreAquired = false; + this.semaphore.release(); + + } catch (Exception ex) { + sipStack.getStackLogger().logError("Unexpected exception releasing sem", + ex); + } - this.semaphore.release(); } /** @@ -1303,8 +1276,8 @@ public boolean passToListener() { * Set the passToListener flag to true. */ public void setPassToListener() { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("setPassToListener()"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("setPassToListener()"); } this.toListener = true; @@ -1365,8 +1338,8 @@ public List extractCertIdentities() throws SSLPeerUnverifiedException { List certIdentities = new ArrayList(); Certificate[] certs = getPeerCertificates(); if (certs == null) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("No certificates available"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("No certificates available"); } return certIdentities; } @@ -1376,16 +1349,16 @@ public List extractCertIdentities() throws SSLPeerUnverifiedException { try { subjAltNames = x509cert.getSubjectAlternativeNames(); } catch (CertificateParsingException ex) { - if (logger.isLoggingEnabled()) { - logger.logError("Error parsing TLS certificate", ex); + if (sipStack.isLoggingEnabled()) { + sipStack.getStackLogger().logError("Error parsing TLS certificate", ex); } } // subjAltName types are defined in rfc2459 final Integer dnsNameType = 2; final Integer uriNameType = 6; if (subjAltNames != null) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("found subjAltNames: " + subjAltNames); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("found subjAltNames: " + subjAltNames); } // First look for a URI in the subjectAltName field // as per draft-ietf-sip-domain-certs-04 @@ -1397,14 +1370,14 @@ public List extractCertIdentities() throws SSLPeerUnverifiedException { try { altNameUri = new AddressFactoryImpl().createSipURI((String) altName.get(1)); String altHostName = altNameUri.getHost(); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( "found uri " + altName.get(1) + ", hostName " + altHostName); } certIdentities.add(altHostName); } catch (ParseException e) { - if (logger.isLoggingEnabled()) { - logger.logError( + if (sipStack.isLoggingEnabled()) { + sipStack.getStackLogger().logError( "certificate contains invalid uri: " + altName.get(1)); } } @@ -1418,8 +1391,8 @@ public List extractCertIdentities() throws SSLPeerUnverifiedException { if (certIdentities.isEmpty()) { for (List< ? > altName : subjAltNames) { if (altName.get(0).equals(dnsNameType)) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("found dns " + altName.get(1)); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("found dns " + altName.get(1)); } certIdentities.add(altName.get(1).toString()); } @@ -1437,14 +1410,14 @@ public List extractCertIdentities() throws SSLPeerUnverifiedException { Matcher matcher = EXTRACT_CN.matcher(dname); if (matcher.matches()) { cname = matcher.group(1); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("found CN: " + cname + " from DN: " + dname); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("found CN: " + cname + " from DN: " + dname); } certIdentities.add(cname); } } catch (Exception ex) { - if (logger.isLoggingEnabled()) { - logger.logError("exception while extracting CN", ex); + if (sipStack.isLoggingEnabled()) { + sipStack.getStackLogger().logError("exception while extracting CN", ex); } } } @@ -1454,6 +1427,7 @@ public List extractCertIdentities() throws SSLPeerUnverifiedException { throw new UnsupportedOperationException("Not a TLS channel"); } + /** * Start the timer that runs the transaction state machine. * @@ -1479,22 +1453,7 @@ public List extractCertIdentities() throws SSLPeerUnverifiedException { */ protected abstract void fireTimeoutTimer(); - /* - * (non-Javadoc) - * @see gov.nist.javax.sip.DialogExt#isReleaseReferences() - */ - public boolean isReleaseReferences() { - return releaseReferences; - } - /* - * (non-Javadoc) - * @see gov.nist.javax.sip.DialogExt#setReleaseReferences(boolean) - */ - public void setReleaseReferences(boolean releaseReferences) { - this.releaseReferences = releaseReferences; - } - /* * (non-Javadoc) * @see gov.nist.javax.sip.TransactionExt#getTimerD() @@ -1524,9 +1483,9 @@ public int getTimerT4() { * @see gov.nist.javax.sip.TransactionExt#setTimerD(int) */ public void setTimerD(int interval) { - if(interval < 32000) { - throw new IllegalArgumentException("To be RFC 3261 compliant, the value of Timer D should be at least 32s"); - } + if(interval < 32000) { + throw new IllegalArgumentException("To be RFC 3261 compliant, the value of Timer D should be at least 32s"); + } TIMER_D = interval / BASE_TIMER_INTERVAL; } @@ -1547,21 +1506,4 @@ public void setTimerT4(int interval) { TIMER_I = T4; TIMER_K = T4; } - - - /** - * Sets the fork id for the transaction. - * @param forkId - */ - public void setForkId(String forkId) { - this.forkId = forkId; - } - - /** - * Retrieves the fork id for the transaction. - * @return - */ - public String getForkId() { - return forkId; - } } diff --git a/src/gov/nist/javax/sip/stack/SIPTransactionStack.java b/src/gov/nist/javax/sip/stack/SIPTransactionStack.java index 0aa6f4e2f..8bd93fd9d 100755 --- a/src/gov/nist/javax/sip/stack/SIPTransactionStack.java +++ b/src/gov/nist/javax/sip/stack/SIPTransactionStack.java @@ -25,10 +25,8 @@ */ package gov.nist.javax.sip.stack; -import gov.nist.core.CommonLogger; import gov.nist.core.Host; import gov.nist.core.HostPort; -import gov.nist.core.LogLevels; import gov.nist.core.LogWriter; import gov.nist.core.ServerLogger; import gov.nist.core.StackLogger; @@ -51,19 +49,20 @@ import gov.nist.javax.sip.message.SIPRequest; import gov.nist.javax.sip.message.SIPResponse; import gov.nist.javax.sip.parser.MessageParserFactory; -import gov.nist.javax.sip.stack.timers.SipTimer; import java.io.IOException; import java.net.InetAddress; import java.net.SocketAddress; import java.net.UnknownHostException; +import java.util.ArrayList; import java.util.Collection; +import java.util.Date; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.Set; +import java.util.Timer; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -94,844 +93,765 @@ */ /** - * + * * This is the sip stack. It is essentially a management interface. It manages * the resources for the JAIN-SIP implementation. This is the structure that is * wrapped by the SipStackImpl. - * + * * @see gov.nist.javax.sip.SipStackImpl - * + * * @author M. Ranganathan
    - * - * @version 1.2 $Revision: 1.180 $ $Date: 2010-12-02 22:04:15 $ + * + * @version 1.2 $Revision: 1.152.2.6 $ $Date: 2010-12-02 01:41:35 $ */ public abstract class SIPTransactionStack implements - SIPTransactionEventListener, SIPDialogEventListener { - private static StackLogger logger = CommonLogger.getLogger(SIPTransactionStack.class); - /* - * Number of milliseconds between timer ticks (500). - */ - public static final int BASE_TIMER_INTERVAL = 500; - - /* - * Connection linger time (seconds) this is the time (in seconds) for which - * we linger the TCP connection before closing it. - */ - public static final int CONNECTION_LINGER_TIME = 8; - - /* - * Dialog Early state timeout duration. - */ - protected int earlyDialogTimeout = 180; - + SIPTransactionEventListener, SIPDialogEventListener { - /* - * Table of retransmission Alert timers. - */ - protected ConcurrentHashMap retransmissionAlertTransactions; + /* + * Number of milliseconds between timer ticks (500). + */ + public static final int BASE_TIMER_INTERVAL = 500; - // Table of early dialogs ( to keep identity mapping ) - protected ConcurrentHashMap earlyDialogTable; + /* + * Connection linger time (seconds) this is the time (in seconds) for which + * we linger the TCP connection before closing it. + */ + public static final int CONNECTION_LINGER_TIME = 8; - // Table of dialogs. - protected ConcurrentHashMap dialogTable; + /* + * Table of retransmission Alert timers. + */ + protected ConcurrentHashMap retransmissionAlertTransactions; - // Table of server dialogs ( for loop detection) - protected ConcurrentHashMap serverDialogMergeTestTable; + // Table of early dialogs ( to keep identity mapping ) + protected ConcurrentHashMap earlyDialogTable; - // A set of methods that result in dialog creations. - protected static final Set dialogCreatingMethods = new HashSet(); + // Table of dialogs. + protected ConcurrentHashMap dialogTable; - // Global timer. Use this for all timer tasks. + // Table of server dialogs ( for loop detection) + protected ConcurrentHashMap serverDialogMergeTestTable; - private SipTimer timer; + // A set of methods that result in dialog creations. + protected static final Set dialogCreatingMethods = new HashSet(); - // List of pending server transactions - private ConcurrentHashMap pendingTransactions; + // Global timer. Use this for all timer tasks. - // hashtable for fast lookup - protected ConcurrentHashMap clientTransactionTable; + private Timer timer; - // Set to false if you want hiwat and lowat to be consulted. - protected boolean unlimitedServerTransactionTableSize = true; + // List of pending server transactions + private ConcurrentHashMap pendingTransactions; - // Set to false if you want unlimited size of client trnansactin table. - protected boolean unlimitedClientTransactionTableSize = true; - - // High water mark for ServerTransaction Table - // after which requests are dropped. - protected int serverTransactionTableHighwaterMark = 5000; - - // Low water mark for Server Tx table size after which - // requests are selectively dropped - protected int serverTransactionTableLowaterMark = 4000; - - // Hiwater mark for client transaction table. These defaults can be - // overriden by stack - // configuration. - protected int clientTransactionTableHiwaterMark = 1000; - - // Low water mark for client tx table. - protected int clientTransactionTableLowaterMark = 800; - - private AtomicInteger activeClientTransactionCount = new AtomicInteger(0); - - // Hashtable for server transactions. - protected ConcurrentHashMap serverTransactionTable; - - // A table of ongoing transactions indexed by mergeId ( for detecting merged - // requests. - private ConcurrentHashMap mergeTable; - - private ConcurrentHashMap terminatedServerTransactionsPendingAck; - - private ConcurrentHashMap forkedClientTransactionTable; - - protected boolean deliverRetransmittedAckToListener = false; - - /* - * ServerLog is used just for logging stack message tracecs. - */ - protected ServerLogger serverLogger; - - /* - * We support UDP on this stack. - */ - boolean udpFlag; - - /* - * Internal router. Use this for all sip: request routing. - */ - protected DefaultRouter defaultRouter; - - /* - * Global flag that turns logging off - */ - protected boolean needsLogging; - - /* - * Flag used for testing TI, bypasses filtering of ACK to non-2xx - */ - private boolean non2XXAckPassedToListener; - - /* - * Class that handles caching of TCP/TLS connections. - */ - protected IOHandler ioHandler; + // hashtable for fast lookup + private ConcurrentHashMap clientTransactionTable; - /* - * Flag that indicates that the stack is active. - */ - protected boolean toExit; + // Set to false if you want hiwat and lowat to be consulted. + protected boolean unlimitedServerTransactionTableSize = true; - /* - * Name of the stack. - */ - protected String stackName; + // Set to false if you want unlimited size of client trnansactin table. + protected boolean unlimitedClientTransactionTableSize = true; - /* - * IP address of stack -- this can be re-written by stun. - * - * @deprecated - */ - protected String stackAddress; + // High water mark for ServerTransaction Table + // after which requests are dropped. + protected int serverTransactionTableHighwaterMark = 5000; - /* - * INET address of stack (cached to avoid repeated lookup) - * - * @deprecated - */ - protected InetAddress stackInetAddress; - - /* - * Request factory interface (to be provided by the application) - */ - protected StackMessageFactory sipMessageFactory; - - /* - * Router to determine where to forward the request. - */ - protected javax.sip.address.Router router; - - /* - * Number of pre-allocated threads for processing udp messages. -1 means no - * preallocated threads ( dynamically allocated threads). - */ - protected int threadPoolSize; - - /* - * max number of simultaneous connections. - */ - protected int maxConnections; - - /* - * Close accept socket on completion. - */ - protected boolean cacheServerConnections; + // Low water mark for Server Tx table size after which + // requests are selectively dropped + protected int serverTransactionTableLowaterMark = 4000; - /* - * Close connect socket on Tx termination. - */ - protected boolean cacheClientConnections; + // Hiwater mark for client transaction table. These defaults can be + // overriden by stack + // configuration. + protected int clientTransactionTableHiwaterMark = 1000; - /* - * Use the user supplied router for all out of dialog requests. - */ - protected boolean useRouterForAll; - - /* - * Max size of message that can be read from a TCP connection. - */ - protected int maxContentLength; + // Low water mark for client tx table. + protected int clientTransactionTableLowaterMark = 800; + + private AtomicInteger activeClientTransactionCount = new AtomicInteger(0); + + // Hashtable for server transactions. + private ConcurrentHashMap serverTransactionTable; + + // A table of ongoing transactions indexed by mergeId ( for detecting merged + // requests. + private ConcurrentHashMap mergeTable; + + private ConcurrentHashMap terminatedServerTransactionsPendingAck; + + private ConcurrentHashMap forkedClientTransactionTable; + + protected boolean deliverRetransmittedAckToListener = false; + + /* + * A wrapper around differnt logging implementations (log4j, commons + * logging, slf4j, ...) to help log debug. + */ + private StackLogger stackLogger; + + /* + * ServerLog is used just for logging stack message tracecs. + */ + protected ServerLogger serverLogger; + + /* + * We support UDP on this stack. + */ + boolean udpFlag; + + /* + * Internal router. Use this for all sip: request routing. + */ + protected DefaultRouter defaultRouter; + + /* + * Global flag that turns logging off + */ + protected boolean needsLogging; + + /* + * Flag used for testing TI, bypasses filtering of ACK to non-2xx + */ + private boolean non2XXAckPassedToListener; + + /* + * Class that handles caching of TCP/TLS connections. + */ + protected IOHandler ioHandler; + + /* + * Flag that indicates that the stack is active. + */ + protected boolean toExit; - /* - * Max # of headers that a SIP message can contain. - */ - protected int maxMessageSize; - - /* - * A collection of message processors. - */ - private Collection messageProcessors; - - /* - * Read timeout on TCP incoming sockets -- defines the time between reads - * for after delivery of first byte of message. - */ - protected int readTimeout; - - /* - * The socket factory. Can be overriden by applications that want direct - * access to the underlying socket. - */ - - protected NetworkLayer networkLayer; + /* + * Name of the stack. + */ + protected String stackName; - /* - * Outbound proxy String ( to be handed to the outbound proxy class on - * creation). - */ - protected String outboundProxy; + /* + * IP address of stack -- this can be re-written by stun. + * + * @deprecated + */ + protected String stackAddress; + + /* + * INET address of stack (cached to avoid repeated lookup) + * + * @deprecated + */ + protected InetAddress stackInetAddress; + + /* + * Request factory interface (to be provided by the application) + */ + protected StackMessageFactory sipMessageFactory; + + /* + * Router to determine where to forward the request. + */ + protected javax.sip.address.Router router; + + /* + * Number of pre-allocated threads for processing udp messages. -1 means no + * preallocated threads ( dynamically allocated threads). + */ + protected int threadPoolSize; + + /* + * max number of simultaneous connections. + */ + protected int maxConnections; + + /* + * Close accept socket on completion. + */ + protected boolean cacheServerConnections; + + /* + * Close connect socket on Tx termination. + */ + protected boolean cacheClientConnections; + + /* + * Use the user supplied router for all out of dialog requests. + */ + protected boolean useRouterForAll; + + /* + * Max size of message that can be read from a TCP connection. + */ + protected int maxContentLength; + + /* + * Max # of headers that a SIP message can contain. + */ + protected int maxMessageSize; + + /* + * A collection of message processors. + */ + private Collection messageProcessors; + + /* + * Read timeout on TCP incoming sockets -- defines the time between reads + * for after delivery of first byte of message. + */ + protected int readTimeout; + + /* + * The socket factory. Can be overriden by applications that want direct + * access to the underlying socket. + */ + + protected NetworkLayer networkLayer; - protected String routerPath; + /* + * Outbound proxy String ( to be handed to the outbound proxy class on + * creation). + */ + protected String outboundProxy; - // Flag to indicate whether the stack will provide dialog - // support. - protected boolean isAutomaticDialogSupportEnabled; + protected String routerPath; - // The set of events for which subscriptions can be forked. + // Flag to indicate whether the stack will provide dialog + // support. + protected boolean isAutomaticDialogSupportEnabled; - protected HashSet forkedEvents; + // The set of events for which subscriptions can be forked. - // Generate a timestamp header for retransmitted requests. - protected boolean generateTimeStampHeader; + protected HashSet forkedEvents; - protected AddressResolver addressResolver; + // Generate a timestamp header for retransmitted requests. + protected boolean generateTimeStampHeader; - // Max time that the listener is allowed to take to respond to a - // request. Default is "infinity". This property allows - // containers to defend against buggy clients (that do not - // want to respond to requests). - protected int maxListenerResponseTime; + protected AddressResolver addressResolver; - // A flag that indicates whether or not RFC 2543 clients are fully - // supported. - // If this is set to true, then To tag checking on the Dialog layer is - // disabled in a few places - resulting in possible breakage of forked - // dialogs. - protected boolean rfc2543Supported = true; + // Max time that the listener is allowed to take to respond to a + // request. Default is "infinity". This property allows + // containers to defend against buggy clients (that do not + // want to respond to requests). + protected int maxListenerResponseTime; - // / Provides a mechanism for applications to check the health of threads in - // the stack - protected ThreadAuditor threadAuditor = new ThreadAuditor(); + // A flag that indicates whether or not RFC 2543 clients are fully + // supported. + // If this is set to true, then To tag checking on the Dialog layer is + // disabled in a few places - resulting in possible breakage of forked + // dialogs. + protected boolean rfc2543Supported = true; - protected LogRecordFactory logRecordFactory; + // / Provides a mechanism for applications to check the health of threads in + // the stack + protected ThreadAuditor threadAuditor = new ThreadAuditor(); - // Set to true if the client CANCEL transaction should be checked before - // sending - // it out. - protected boolean cancelClientTransactionChecked = true; + protected LogRecordFactory logRecordFactory; - // Is to tag reassignment allowed. - protected boolean remoteTagReassignmentAllowed = true; + // Set to true if the client CANCEL transaction should be checked before + // sending + // it out. + protected boolean cancelClientTransactionChecked = true; - protected boolean logStackTraceOnMessageSend = true; + // Is to tag reassignment allowed. + protected boolean remoteTagReassignmentAllowed = true; - // Receive UDP buffer size - protected int receiveUdpBufferSize; + protected boolean logStackTraceOnMessageSend = true; - // Send UDP buffer size - protected int sendUdpBufferSize; + // Receive UDP buffer size + protected int receiveUdpBufferSize; - protected int stackCongenstionControlTimeout = 0; + // Send UDP buffer size + protected int sendUdpBufferSize; - protected boolean isBackToBackUserAgent = false; + protected int stackCongestionControlTimeout = 0; - protected boolean checkBranchId; + protected boolean isBackToBackUserAgent = false; - protected boolean isAutomaticDialogErrorHandlingEnabled = true; + protected boolean checkBranchId; - protected boolean isDialogTerminatedEventDeliveredForNullDialog = false; + protected boolean isAutomaticDialogErrorHandlingEnabled = true; - // Max time for a forked response to arrive. After this time, the original - // dialog - // is not tracked. If you want to track the original transaction you need to - // specify - // the max fork time with a stack init property. - protected int maxForkTime = 0; + protected boolean isDialogTerminatedEventDeliveredForNullDialog = false; - // Whether or not to deliver unsolicited NOTIFY + // Max time for a forked response to arrive. After this time, the original + // dialog + // is not tracked. If you want to track the original transaction you need to + // specify + // the max fork time with a stack init property. + protected int maxForkTime = 0; - private boolean deliverUnsolicitedNotify = false; + // Whether or not to deliver unsolicited NOTIFY - private boolean deliverTerminatedEventForAck = false; + private boolean deliverUnsolicitedNotify = false; - protected ClientAuthType clientAuth = ClientAuthType.Default; - - // ThreadPool when parsed SIP messages are processed. Affects the case when many TCP calls use single socket. - private int tcpPostParsingThreadPoolSize = 0; - - // Minimum time between NAT kee alive pings from clients. - // Any ping that exceeds this time will result in CRLF CRLF going - // from the UDP message channel. - protected long minKeepAliveInterval = -1L; - - // The time after which a "dialog timeout event" is delivered to a listener. - protected int dialogTimeoutFactor = 64; - - // factory used to create MessageParser objects - public MessageParserFactory messageParserFactory; - // factory used to create MessageProcessor objects - public MessageProcessorFactory messageProcessorFactory; + private boolean deliverTerminatedEventForAck = false; + + // ThreadPool when parsed SIP messages are processed. Affects the case when many TCP calls use single socket. + private int tcpPostParsingThreadPoolSize = 0; + + // Minimum time between NAT kee alive pings from clients. + // Any ping that exceeds this time will result in CRLF CRLF going + // from the UDP message channel. + protected long minKeepAliveInterval = -1L; + + // The time after which a "dialog timeout event" is delivered to a listener. + protected int dialogTimeoutFactor = 64; + public SIPEventInterceptor sipEventInterceptor; + + // factory used to create MessageParser objects + protected MessageParserFactory messageParserFactory; + // factory used to create MessageProcessor objects + protected MessageProcessorFactory messageProcessorFactory; + + /** + * Executor used to optimise the ReinviteSender Runnable in the sendRequest + * of the SipDialog + */ + protected static Executor selfRoutingThreadpoolExecutor; + + private static class SameThreadExecutor implements Executor { - protected boolean aggressiveCleanup = false; + public void execute(Runnable command) { + command.run(); // Just run the command is the same thread + } + + } + + public Executor getSelfRoutingThreadpoolExecutor() { + if(selfRoutingThreadpoolExecutor == null) { + if(this.threadPoolSize<=0) { + selfRoutingThreadpoolExecutor = new SameThreadExecutor(); + } else { + selfRoutingThreadpoolExecutor = Executors.newFixedThreadPool(this.threadPoolSize); + } + } + return selfRoutingThreadpoolExecutor; + } + + /** + * Executor used to optimise the ReinviteSender Runnable in the sendRequest + * of the SipDialog + */ + private ExecutorService reinviteExecutor = Executors + .newCachedThreadPool(new ThreadFactory() { + private int threadCount = 0; + + public Thread newThread(Runnable pRunnable) { + return new Thread(pRunnable, String.format("%s-%d", + "ReInviteSender", threadCount++)); + } + }); - public SIPMessageValve sipMessageValve; - - public SIPEventInterceptor sipEventInterceptor; + // / Timer to regularly ping the thread auditor (on behalf of the timer + // thread) + class PingTimer extends SIPStackTimerTask { + // / Timer thread handle + ThreadAuditor.ThreadHandle threadHandle; - protected static Executor selfRoutingThreadpoolExecutor; + // / Constructor + public PingTimer(ThreadAuditor.ThreadHandle a_oThreadHandle) { + threadHandle = a_oThreadHandle; + } - private static class SameThreadExecutor implements Executor { + protected void runTask() { + // Check if we still have a timer (it may be null after shutdown) + if (getTimer() != null) { + // Register the timer task if we haven't done so + if (threadHandle == null) { + // This happens only once since the thread handle is passed + // to the next scheduled ping timer + threadHandle = getThreadAuditor().addCurrentThread(); + } - public void execute(Runnable command) { - command.run(); // Just run the command is the same thread - } + // Let the thread auditor know that the timer task is alive + threadHandle.ping(); - } + // Schedule the next ping + getTimer().schedule(new PingTimer(threadHandle), + threadHandle.getPingIntervalInMillisecs()); + } + } - public Executor getSelfRoutingThreadpoolExecutor() { - if(selfRoutingThreadpoolExecutor == null) { - if(this.threadPoolSize<=0) { - selfRoutingThreadpoolExecutor = new SameThreadExecutor(); - } else { - selfRoutingThreadpoolExecutor = Executors.newFixedThreadPool(this.threadPoolSize); - } - } - return selfRoutingThreadpoolExecutor; - } - /** - * Executor used to optimise the ReinviteSender Runnable in the sendRequest - * of the SipDialog - */ - private ExecutorService reinviteExecutor = Executors - .newCachedThreadPool(new ThreadFactory() { - private int threadCount = 0; - - public Thread newThread(Runnable pRunnable) { - return new Thread(pRunnable, String.format("%s-%d", - "ReInviteSender", threadCount++)); - } - }); - - // / Timer to regularly ping the thread auditor (on behalf of the timer - // thread) - protected class PingTimer extends SIPStackTimerTask { - // / Timer thread handle - ThreadAuditor.ThreadHandle threadHandle; - - // / Constructor - public PingTimer(ThreadAuditor.ThreadHandle a_oThreadHandle) { - threadHandle = a_oThreadHandle; - } - - public void runTask() { - // Check if we still have a timer (it may be null after shutdown) - if (getTimer() != null) { - // Register the timer task if we haven't done so - if (threadHandle == null) { - // This happens only once since the thread handle is passed - // to the next scheduled ping timer - threadHandle = getThreadAuditor().addCurrentThread(); - } - - // Let the thread auditor know that the timer task is alive - threadHandle.ping(); - - // Schedule the next ping - getTimer().schedule(new PingTimer(threadHandle), - threadHandle.getPingIntervalInMillisecs()); - } - } + } - } + class RemoveForkedTransactionTimerTask extends SIPStackTimerTask { + private SIPClientTransaction clientTransaction; - class RemoveForkedTransactionTimerTask extends SIPStackTimerTask { + public RemoveForkedTransactionTimerTask( + SIPClientTransaction sipClientTransaction) { + this.clientTransaction = sipClientTransaction; + } - private final String forkId; + @Override + protected void runTask() { + forkedClientTransactionTable.remove(((SIPRequest) clientTransaction + .getRequest()).getForkId()); + } - public RemoveForkedTransactionTimerTask(String forkId) { - this.forkId = forkId; - } + } - @Override - public void runTask() { - forkedClientTransactionTable.remove(forkId); - } + static { + // Standard set of methods that create dialogs. + dialogCreatingMethods.add(Request.REFER); + dialogCreatingMethods.add(Request.INVITE); + dialogCreatingMethods.add(Request.SUBSCRIBE); + } - } + /** + * Default constructor. + */ + protected SIPTransactionStack() { + this.toExit = false; + this.forkedEvents = new HashSet(); + // set of events for which subscriptions can be forked. + // Set an infinite thread pool size. + this.threadPoolSize = -1; + // Close response socket after infinte time. + // for max performance + this.cacheServerConnections = true; + // Close the request socket after infinite time. + // for max performance + this.cacheClientConnections = true; + // Max number of simultaneous connections. + this.maxConnections = -1; + // Array of message processors. + messageProcessors = new ArrayList(); + // Handle IO for this process. + this.ioHandler = new IOHandler(this); + + // The read time out is infinite. + this.readTimeout = -1; + + this.maxListenerResponseTime = -1; + + // The default (identity) address lookup scheme + + this.addressResolver = new DefaultAddressResolver(); + + // Notify may or may not create a dialog. This is handled in + // the code. + // Create the transaction collections + + // Dialog dable. + this.dialogTable = new ConcurrentHashMap(); + this.earlyDialogTable = new ConcurrentHashMap(); + this.serverDialogMergeTestTable = new ConcurrentHashMap(); + + clientTransactionTable = new ConcurrentHashMap(); + serverTransactionTable = new ConcurrentHashMap(); + this.terminatedServerTransactionsPendingAck = new ConcurrentHashMap(); + mergeTable = new ConcurrentHashMap(); + retransmissionAlertTransactions = new ConcurrentHashMap(); + + // Start the timer event thread. + + this.timer = new Timer(); + this.pendingTransactions = new ConcurrentHashMap(); + + this.forkedClientTransactionTable = new ConcurrentHashMap(); + + if (getThreadAuditor().isEnabled()) { + // Start monitoring the timer thread + timer.schedule(new PingTimer(null), 0); + } + } - static { - // Standard set of methods that create dialogs. - dialogCreatingMethods.add(Request.REFER); - dialogCreatingMethods.add(Request.INVITE); - dialogCreatingMethods.add(Request.SUBSCRIBE); - } + /** + * Re Initialize the stack instance. + */ + protected void reInit() { + if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + stackLogger.logDebug("Re-initializing !"); + + // Array of message processors. + messageProcessors = new ArrayList(); + // Handle IO for this process. + this.ioHandler = new IOHandler(this); + // clientTransactions = new ConcurrentLinkedQueue(); + // serverTransactions = new ConcurrentLinkedQueue(); + pendingTransactions = new ConcurrentHashMap(); + clientTransactionTable = new ConcurrentHashMap(); + serverTransactionTable = new ConcurrentHashMap(); + retransmissionAlertTransactions = new ConcurrentHashMap(); + mergeTable = new ConcurrentHashMap(); + // Dialog dable. + this.dialogTable = new ConcurrentHashMap(); + this.earlyDialogTable = new ConcurrentHashMap(); + this.serverDialogMergeTestTable = new ConcurrentHashMap(); + this.terminatedServerTransactionsPendingAck = new ConcurrentHashMap(); + this.forkedClientTransactionTable = new ConcurrentHashMap(); + + this.timer = new Timer(); + + this.activeClientTransactionCount = new AtomicInteger(0); - /** - * Default constructor. - */ - protected SIPTransactionStack() { - this.toExit = false; - this.forkedEvents = new HashSet(); - // set of events for which subscriptions can be forked. - // Set an infinite thread pool size. - this.threadPoolSize = -1; - // Close response socket after infinte time. - // for max performance - this.cacheServerConnections = true; - // Close the request socket after infinite time. - // for max performance - this.cacheClientConnections = true; - // Max number of simultaneous connections. - this.maxConnections = -1; - // Array of message processors. - // jeand : using concurrent data structure to avoid excessive blocking - messageProcessors = new CopyOnWriteArrayList(); - // Handle IO for this process. - this.ioHandler = new IOHandler(this); - - // The read time out is infinite. - this.readTimeout = -1; - - this.maxListenerResponseTime = -1; - - // The default (identity) address lookup scheme - - this.addressResolver = new DefaultAddressResolver(); - - // Notify may or may not create a dialog. This is handled in - // the code. - // Create the transaction collections - - // Dialog dable. - this.dialogTable = new ConcurrentHashMap(); - this.earlyDialogTable = new ConcurrentHashMap(); - this.serverDialogMergeTestTable = new ConcurrentHashMap(); - - clientTransactionTable = new ConcurrentHashMap(); - serverTransactionTable = new ConcurrentHashMap(); - this.terminatedServerTransactionsPendingAck = new ConcurrentHashMap(); - mergeTable = new ConcurrentHashMap(); - retransmissionAlertTransactions = new ConcurrentHashMap(); - - // Start the timer event thread. - -// this.timer = new DefaultTimer(); - this.pendingTransactions = new ConcurrentHashMap(); - - - this.forkedClientTransactionTable = new ConcurrentHashMap(); - } + } - /** - * Re Initialize the stack instance. - */ - protected void reInit() { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("Re-initializing !"); - - // Array of message processors. - messageProcessors = new CopyOnWriteArrayList(); - // Handle IO for this process. - this.ioHandler = new IOHandler(this); - pendingTransactions = new ConcurrentHashMap(); - clientTransactionTable = new ConcurrentHashMap(); - serverTransactionTable = new ConcurrentHashMap(); - retransmissionAlertTransactions = new ConcurrentHashMap(); - mergeTable = new ConcurrentHashMap(); - // Dialog dable. - this.dialogTable = new ConcurrentHashMap(); - this.earlyDialogTable = new ConcurrentHashMap(); - this.serverDialogMergeTestTable = new ConcurrentHashMap(); - this.terminatedServerTransactionsPendingAck = new ConcurrentHashMap(); - this.forkedClientTransactionTable = new ConcurrentHashMap(); - -// this.timer = new DefaultTimer(); - - this.activeClientTransactionCount = new AtomicInteger(0); + /** + * Creates and binds, if necessary, a socket connected to the specified + * destination address and port and then returns its local address. + * + * @param dst + * the destination address that the socket would need to connect + * to. + * @param dstPort + * the port number that the connection would be established with. + * @param localAddress + * the address that we would like to bind on (null for the "any" + * address). + * @param localPort + * the port that we'd like our socket to bind to (0 for a random + * port). + * + * @return the SocketAddress that this handler would use when connecting to + * the specified destination address and port. + * + * @throws IOException + */ + public SocketAddress obtainLocalAddress(InetAddress dst, int dstPort, + InetAddress localAddress, int localPort) throws IOException { + return this.ioHandler.obtainLocalAddress(dst, dstPort, localAddress, + localPort); - } + } - /** - * Creates and binds, if necessary, a socket connected to the specified - * destination address and port and then returns its local address. - * - * @param dst the destination address that the socket would need to connect - * to. - * @param dstPort the port number that the connection would be established - * with. - * @param localAddress the address that we would like to bind on (null for - * the "any" address). - * @param localPort the port that we'd like our socket to bind to (0 for a - * random port). - * - * @return the SocketAddress that this handler would use when connecting to - * the specified destination address and port. - * - * @throws IOException if binding the socket fails - */ - public SocketAddress getLocalAddressForTcpDst(InetAddress dst, int dstPort, - InetAddress localAddress, int localPort) throws IOException { - return this.ioHandler.getLocalAddressForTcpDst( - dst, dstPort, localAddress, localPort); - } + /** + * For debugging -- allows you to disable logging or enable logging + * selectively. + * + * + */ + public void disableLogging() { + this.getStackLogger().disableLogging(); + } - /** - * Creates and binds, if necessary, a TCP SSL socket connected to the - * specified destination address and port and then returns its local - * address. - * - * @param dst the destination address that the socket would need to connect - * to. - * @param dstPort the port number that the connection would be established - * with. - * @param localAddress the address that we would like to bind on - * (null for the "any" address). - * - * @return the SocketAddress that this handler would use when connecting to - * the specified destination address and port. - * - * @throws IOException if binding the socket fails - */ - public SocketAddress getLocalAddressForTlsDst( InetAddress dst, - int dstPort, InetAddress localAddress) throws IOException { - - // First find the TLS message processor - TLSMessageProcessor tlsProcessor = null; - MessageProcessor[] processors = getMessageProcessors(); - for (MessageProcessor processor : processors){ - if(processor instanceof TLSMessageProcessor){ - tlsProcessor = (TLSMessageProcessor)processor; - break; - } - } - - if(tlsProcessor == null) - return null; - - // Here we don't create the channel but if the channel is already - // existing will be returned - TLSMessageChannel msgChannel = - (TLSMessageChannel)tlsProcessor.createMessageChannel(dst, dstPort); - - return this.ioHandler.getLocalAddressForTlsDst( - dst, dstPort, localAddress, msgChannel); - } - - /** - * For debugging -- allows you to disable logging or enable logging - * selectively. - * - * - */ - public void disableLogging() { - this.logger.disableLogging(); - } + /** + * Globally enable message logging ( for debugging) + * + */ + public void enableLogging() { + this.getStackLogger().enableLogging(); + } - /** - * Globally enable message logging ( for debugging) - * - */ - public void enableLogging() { - this.logger.enableLogging(); - } + /** + * Print the dialog table. + * + */ + public void printDialogTable() { + if (isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + this.getStackLogger().logDebug( + "dialog table = " + this.dialogTable); + } + } - /** - * Print the dialog table. - * - */ - public void printDialogTable() { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - this.logger.logDebug( - "dialog table = " + this.dialogTable); - } - } + /** + * Retrieve a transaction from our table of transactions with pending + * retransmission alerts. + * + * @param dialogId + * @return -- the RetransmissionAlert enabled transaction corresponding to + * the given dialog ID. + */ + public SIPServerTransaction getRetransmissionAlertTransaction( + String dialogId) { + return (SIPServerTransaction) this.retransmissionAlertTransactions + .get(dialogId); + } - /** - * Retrieve a transaction from our table of transactions with pending - * retransmission alerts. - * - * @param dialogId - * @return -- the RetransmissionAlert enabled transaction corresponding to - * the given dialog ID. - */ - public SIPServerTransaction getRetransmissionAlertTransaction( - String dialogId) { - return (SIPServerTransaction) this.retransmissionAlertTransactions - .get(dialogId); - } + /** + * Return true if extension is supported. + * + * @return true if extension is supported and false otherwise. + */ + public static boolean isDialogCreated(String method) { + return dialogCreatingMethods.contains(method); + } - /** - * Return true if extension is supported. - * - * @return true if extension is supported and false otherwise. - */ - public static boolean isDialogCreated(String method) { - return dialogCreatingMethods.contains(method); - } + /** + * Add an extension method. + * + * @param extensionMethod + * -- extension method to support for dialog creation + */ + public void addExtensionMethod(String extensionMethod) { + if (extensionMethod.equals(Request.NOTIFY)) { + if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + stackLogger.logDebug("NOTIFY Supported Natively"); + } else { + dialogCreatingMethods.add(extensionMethod.trim().toUpperCase()); + } + } - /** - * Add an extension method. - * - * @param extensionMethod - * -- extension method to support for dialog creation - */ - public void addExtensionMethod(String extensionMethod) { - if (extensionMethod.equals(Request.NOTIFY)) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("NOTIFY Supported Natively"); - } else { - dialogCreatingMethods.add(extensionMethod.trim().toUpperCase()); - } - } + /** + * Put a dialog into the dialog table. + * + * @param dialog + * -- dialog to put into the dialog table. + * + */ + public void putDialog(SIPDialog dialog) { + String dialogId = dialog.getDialogId(); + if (dialogTable.containsKey(dialogId)) { + if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + stackLogger + .logDebug("putDialog: dialog already exists" + dialogId + + " in table = " + dialogTable.get(dialogId)); + } + return; + } + if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + stackLogger.logDebug("putDialog dialogId=" + dialogId + + " dialog = " + dialog); + } + dialog.setStack(this); + if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + stackLogger.logStackTrace(); + dialogTable.put(dialogId, dialog); + putMergeDialog(dialog); - /** - * Put a dialog into the dialog table. - * - * @param dialog - * -- dialog to put into the dialog table. - * - */ - public SIPDialog putDialog(SIPDialog dialog) { - String dialogId = dialog.getDialogId(); - if (dialogTable.containsKey(dialogId)) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger - .logDebug("putDialog: dialog already exists" + dialogId - + " in table = " + dialogTable.get(dialogId)); - } - return dialogTable.get(dialogId); - } - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("putDialog dialogId=" + dialogId - + " dialog = " + dialog); - } - dialog.setStack(this); - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logStackTrace(); - dialogTable.put(dialogId, dialog); - putMergeDialog(dialog); - - return dialog; - } + } - /** - * Create a dialog and add this transaction to it. - * - * @param transaction - * -- tx to add to the dialog. - * @return the newly created Dialog. - */ - /** - * Create a dialog and add this transaction to it. - * - * @param transaction - * -- tx to add to the dialog. - * @return the newly created Dialog. - */ - public SIPDialog createDialog(SIPTransaction transaction) { - - SIPDialog retval = null; - - if (transaction instanceof SIPClientTransaction) { - String dialogId = ((SIPRequest) transaction.getRequest()) - .getDialogId(false); - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug("createDialog dialogId=" + dialogId); - } - if (this.earlyDialogTable.get(dialogId) != null) { - SIPDialog dialog = this.earlyDialogTable.get(dialogId); - if (dialog.getState() == null - || dialog.getState() == DialogState.EARLY) { - retval = dialog; - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug("createDialog early Dialog found : earlyDialogId=" - + dialogId + " earlyDialog= " + dialog); - } - } else { - retval = new SIPDialog(transaction); - this.earlyDialogTable.put(dialogId, retval); - } - } else { - retval = new SIPDialog(transaction); - this.earlyDialogTable.put(dialogId, retval); - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug("createDialog early Dialog not found : earlyDialogId=" - + dialogId + " created one " + retval); - } - } - } else { - retval = new SIPDialog(transaction); - } - - return retval; + /** + * Create a dialog and add this transaction to it. + * + * @param transaction + * -- tx to add to the dialog. + * @return the newly created Dialog. + */ + public SIPDialog createDialog(SIPTransaction transaction) { + + SIPDialog retval = null; + + if (transaction instanceof SIPClientTransaction) { + String dialogId = ((SIPRequest) transaction.getRequest()) + .getDialogId(false); + if (this.earlyDialogTable.get(dialogId) != null) { + SIPDialog dialog = this.earlyDialogTable.get(dialogId); + if (dialog.getState() == null + || dialog.getState() == DialogState.EARLY) { + retval = dialog; + } else { + retval = new SIPDialog(transaction); + this.earlyDialogTable.put(dialogId, retval); + } + } else { + retval = new SIPDialog(transaction); + this.earlyDialogTable.put(dialogId, retval); + } + } else { + retval = new SIPDialog(transaction); + } - } + return retval; - /** - * Create a Dialog given a client tx and response. - * - * @param transaction - * @param sipResponse - * @return - */ - - public SIPDialog createDialog(SIPClientTransaction transaction, - SIPResponse sipResponse) { - String originalDialogId = ((SIPRequest)transaction.getRequest()).getDialogId(false); - String earlyDialogId = sipResponse.getDialogId(false); - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug("createDialog originalDialogId=" + originalDialogId); - logger.logDebug("createDialog earlyDialogId=" + earlyDialogId); - logger.logDebug("createDialog default Dialog=" + transaction.getDefaultDialog()); - if(transaction.getDefaultDialog() != null) { - logger.logDebug("createDialog default Dialog Id=" + transaction.getDefaultDialog().getDialogId()); - } - } - SIPDialog retval = null; - SIPDialog earlyDialog = this.earlyDialogTable.get(originalDialogId); - if (earlyDialog != null && transaction != null && (transaction.getDefaultDialog() == null || transaction.getDefaultDialog().getDialogId().equals(originalDialogId))) { - retval = earlyDialog; - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug("createDialog early Dialog found : earlyDialogId=" - + originalDialogId + " earlyDialog= " + retval); - } - if (sipResponse.isFinalResponse()) { - this.earlyDialogTable.remove(originalDialogId); - } - - } else { - retval = new SIPDialog(transaction, sipResponse); - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logDebug("createDialog early Dialog not found : earlyDialogId=" - + earlyDialogId + " created one " + retval); - } - } - return retval; + } - } - /** - * Create a Dialog given a sip provider and response. - * - * @param sipProvider - * @param sipResponse - * @return - */ - public SIPDialog createDialog(SipProviderImpl sipProvider, - SIPResponse sipResponse) { - return new SIPDialog(sipProvider, sipResponse); - } + /** + * Create a Dialog given a client tx and response. + * + * @param transaction + * @param sipResponse + * @return + */ + + public SIPDialog createDialog(SIPClientTransaction transaction, + SIPResponse sipResponse) { + String dialogId = ((SIPRequest) transaction.getRequest()) + .getDialogId(false); + SIPDialog retval = null; + if (this.earlyDialogTable.get(dialogId) != null) { + retval = this.earlyDialogTable.get(dialogId); + if (sipResponse.isFinalResponse()) { + this.earlyDialogTable.remove(dialogId); + } - /** - * Remove the dialog from the dialog table. - * - * @param dialog - * -- dialog to remove. - */ - public void removeDialog(SIPDialog dialog) { + } else { + retval = new SIPDialog(transaction, sipResponse); + } + return retval; - String id = dialog.getDialogId(); + } - String earlyId = dialog.getEarlyDialogId(); + /** + * Create a Dialog given a sip provider and response. + * + * @param sipProvider + * @param sipResponse + * @return + */ + public SIPDialog createDialog(SipProviderImpl sipProvider, + SIPResponse sipResponse) { + return new SIPDialog(sipProvider, sipResponse); + } - if (earlyId != null) { - this.earlyDialogTable.remove(earlyId); - this.dialogTable.remove(earlyId); - } + /** + * Remove the dialog from the dialog table. + * + * @param dialog + * -- dialog to remove. + */ + public void removeDialog(SIPDialog dialog) { - removeMergeDialog(dialog.getMergeId()); + String id = dialog.getDialogId(); - if (id != null) { + String earlyId = dialog.getEarlyDialogId(); - // FHT: Remove dialog from table only if its associated dialog is - // the same as the one - // specified + if (earlyId != null) { + this.earlyDialogTable.remove(earlyId); + this.dialogTable.remove(earlyId); + } - Object old = this.dialogTable.get(id); + removeMergeDialog(dialog.getMergeId()); - if (old == dialog) { - this.dialogTable.remove(id); - } + if (id != null) { - // We now deliver DTE even when the dialog is not originally present - // in the Dialog - // Table - // This happens before the dialog state is assigned. + // FHT: Remove dialog from table only if its associated dialog is + // the same as the one + // specified - if (!dialog.testAndSetIsDialogTerminatedEventDelivered()) { - DialogTerminatedEvent event = new DialogTerminatedEvent(dialog - .getSipProvider(), dialog); + Object old = this.dialogTable.get(id); - // Provide notification to the listener that the dialog has - // ended. - dialog.getSipProvider().handleEvent(event, null); + if (old == dialog) { + this.dialogTable.remove(id); + } - } + // We now deliver DTE even when the dialog is not originally present + // in the Dialog + // Table + // This happens before the dialog state is assigned. - } else if ( this.isDialogTerminatedEventDeliveredForNullDialog ) { - if (!dialog.testAndSetIsDialogTerminatedEventDelivered()) { - DialogTerminatedEvent event = new DialogTerminatedEvent(dialog - .getSipProvider(), dialog); + if (!dialog.testAndSetIsDialogTerminatedEventDelivered()) { + DialogTerminatedEvent event = new DialogTerminatedEvent(dialog + .getSipProvider(), dialog); - // Provide notification to the listener that the dialog has - // ended. - dialog.getSipProvider().handleEvent(event, null); + // Provide notification to the listener that the dialog has + // ended. + dialog.getSipProvider().handleEvent(event, null); - } - } + } - } + } else if (this.isDialogTerminatedEventDeliveredForNullDialog) { + if (!dialog.testAndSetIsDialogTerminatedEventDelivered()) { + DialogTerminatedEvent event = new DialogTerminatedEvent(dialog + .getSipProvider(), dialog); - public SIPDialog getEarlyDialog(String dialogId) { + // Provide notification to the listener that the dialog has + // ended. + dialog.getSipProvider().handleEvent(event, null); - SIPDialog sipDialog = (SIPDialog) earlyDialogTable.get(dialogId); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("getEarlyDialog(" + dialogId + ") : returning " + sipDialog); - } - return sipDialog; + } + } - } + } - protected void removeMergeDialog(String mergeId) { + protected void removeMergeDialog(String mergeId) { if(mergeId != null) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("Tyring to remove Dialog from serverDialogMerge table with Merge Dialog Id " + mergeId); + if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + stackLogger.logDebug("Tyring to remove Dialog from serverDialogMerge table with Merge Dialog Id " + mergeId); } SIPDialog sipDialog = serverDialogMergeTestTable.remove(mergeId); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG) && sipDialog != null) { - logger.logDebug("removed Dialog " + sipDialog + " from serverDialogMerge table with Merge Dialog Id " + mergeId); + if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG) && sipDialog != null) { + stackLogger.logDebug("removed Dialog " + sipDialog + " from serverDialogMerge table with Merge Dialog Id " + mergeId); } } } @@ -941,2139 +861,2039 @@ protected void putMergeDialog(SIPDialog sipDialog) { String mergeId = sipDialog.getMergeId(); if(mergeId != null) { serverDialogMergeTestTable.put(mergeId, sipDialog); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("put Dialog " + sipDialog + " in serverDialogMerge table with Merge Dialog Id " + mergeId); + if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + stackLogger.logDebug("put Dialog " + sipDialog + " in serverDialogMerge table with Merge Dialog Id " + mergeId); } } } } - - /** - * Return the dialog for a given dialog ID. If compatibility is enabled then - * we do not assume the presence of tags and hence need to add a flag to - * indicate whether this is a server or client transaction. - * - * @param dialogId - * is the dialog id to check. - */ + + /** + * Return the dialog for a given dialog ID. If compatibility is enabled then + * we do not assume the presence of tags and hence need to add a flag to + * indicate whether this is a server or client transaction. + * + * @param dialogId + * is the dialog id to check. + */ + + public SIPDialog getDialog(String dialogId) { + + SIPDialog sipDialog = (SIPDialog) dialogTable.get(dialogId); + if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + stackLogger.logDebug("getDialog(" + dialogId + ") : returning " + + sipDialog); + } + return sipDialog; - public SIPDialog getDialog(String dialogId) { + } - SIPDialog sipDialog = (SIPDialog) dialogTable.get(dialogId); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("getDialog(" + dialogId + ") : returning " - + sipDialog); - } - return sipDialog; + /** + * Remove the dialog given its dialog id. This is used for dialog id + * re-assignment only. + * + * @param dialogId + * is the dialog Id to remove. + */ + public void removeDialog(String dialogId) { + if (stackLogger.isLoggingEnabled(LogWriter.TRACE_WARN)) { + stackLogger.logWarning("Silently removing dialog from table"); + } + dialogTable.remove(dialogId); + } - } + /** + * Find a matching client SUBSCRIBE to the incoming notify. NOTIFY requests + * are matched to such SUBSCRIBE requests if they contain the same + * "Call-ID", a "To" header "tag" parameter which matches the "From" header + * "tag" parameter of the SUBSCRIBE, and the same "Event" header field. + * Rules for comparisons of the "Event" headers are described in section + * 7.2.1. If a matching NOTIFY request contains a "Subscription-State" of + * "active" or "pending", it creates a new subscription and a new dialog + * (unless they have already been created by a matching response, as + * described above). + * + * @param notifyMessage + * @return -- the matching ClientTransaction with semaphore aquired or null + * if no such client transaction can be found. + */ + public SIPClientTransaction findSubscribeTransaction( + SIPRequest notifyMessage, ListeningPointImpl listeningPoint) { + SIPClientTransaction retval = null; + try { + Iterator it = clientTransactionTable.values().iterator(); + if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + stackLogger.logDebug("ct table size = " + + clientTransactionTable.size()); + String thisToTag = notifyMessage.getTo().getTag(); + if (thisToTag == null) { + return retval; + } + Event eventHdr = (Event) notifyMessage.getHeader(EventHeader.NAME); + if (eventHdr == null) { + if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + stackLogger + .logDebug("event Header is null -- returning null"); + } - /** - * Remove the dialog given its dialog id. This is used for dialog id - * re-assignment only. - * - * @param dialogId - * is the dialog Id to remove. - */ - public void removeDialog(String dialogId) { - if (logger.isLoggingEnabled()) { - logger.logWarning("Silently removing dialog from table"); - } - dialogTable.remove(dialogId); - } + return retval; + } + while (it.hasNext()) { + SIPClientTransaction ct = (SIPClientTransaction) it.next(); + if (!ct.getMethod().equals(Request.SUBSCRIBE)) + continue; + + // if ( sipProvider.getListeningPoint(transport) == null) + String fromTag = ct.from.getTag(); + Event hisEvent = ct.event; + // Event header is mandatory but some slopply clients + // dont include it. + if (hisEvent == null) + continue; + if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + stackLogger.logDebug("ct.fromTag = " + fromTag); + stackLogger.logDebug("thisToTag = " + thisToTag); + stackLogger.logDebug("hisEvent = " + hisEvent); + stackLogger.logDebug("eventHdr " + eventHdr); + } - /** - * Find a matching client SUBSCRIBE to the incoming notify. NOTIFY requests - * are matched to such SUBSCRIBE requests if they contain the same - * "Call-ID", a "To" header "tag" parameter which matches the "From" header - * "tag" parameter of the SUBSCRIBE, and the same "Event" header field. - * Rules for comparisons of the "Event" headers are described in section - * 7.2.1. If a matching NOTIFY request contains a "Subscription-State" of - * "active" or "pending", it creates a new subscription and a new dialog - * (unless they have already been created by a matching response, as - * described above). - * - * @param notifyMessage - * @return -- the matching ClientTransaction with semaphore aquired or null - * if no such client transaction can be found. - */ - public SIPClientTransaction findSubscribeTransaction( - SIPRequest notifyMessage, ListeningPointImpl listeningPoint) { - SIPClientTransaction retval = null; - try { - Iterator it = clientTransactionTable.values().iterator(); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("ct table size = " - + clientTransactionTable.size()); - String thisToTag = notifyMessage.getTo().getTag(); - if (thisToTag == null) { - return retval; - } - Event eventHdr = (Event) notifyMessage.getHeader(EventHeader.NAME); - if (eventHdr == null) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger - .logDebug("event Header is null -- returning null"); - } - - return retval; - } - while (it.hasNext()) { - SIPClientTransaction ct = (SIPClientTransaction) it.next(); - if (!ct.getMethod().equals(Request.SUBSCRIBE)) - continue; - - // if ( sipProvider.getListeningPoint(transport) == null) - String fromTag = ct.getOriginalRequestFromTag(); - Event hisEvent = (Event) ct.getOriginalRequestEvent(); - // Event header is mandatory but some slopply clients - // dont include it. - if (hisEvent == null) - continue; - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("ct.fromTag = " + fromTag); - logger.logDebug("thisToTag = " + thisToTag); - logger.logDebug("hisEvent = " + hisEvent); - logger.logDebug("eventHdr " + eventHdr); - } - - if ( fromTag.equalsIgnoreCase(thisToTag) - && hisEvent != null - && eventHdr.match(hisEvent) - && notifyMessage.getCallId().getCallId().equalsIgnoreCase( - ct.getOriginalRequestCallId())) { - if (!this.isDeliverUnsolicitedNotify() ) { - ct.acquireSem(); - } - retval = ct; - return ct; - } - } - - return retval; - } finally { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("findSubscribeTransaction : returning " - + retval); - - } + if (fromTag.equalsIgnoreCase(thisToTag) + && hisEvent != null + && eventHdr.match(hisEvent) + && notifyMessage.getCallId().getCallId() + .equalsIgnoreCase(ct.callId.getCallId())) { + if (!this.isDeliverUnsolicitedNotify()) { + ct.acquireSem(); + } + retval = ct; + return ct; + } + } - } + return retval; + } finally { + if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + stackLogger.logDebug("findSubscribeTransaction : returning " + + retval); - /** - * Add entry to "Transaction Pending ACK" table. - * - * @param serverTransaction - */ - public void addTransactionPendingAck(SIPServerTransaction serverTransaction) { - String branchId = ((SIPRequest) serverTransaction.getRequest()) - .getTopmostVia().getBranch(); - if ( branchId != null ) { - this.terminatedServerTransactionsPendingAck.put(branchId, - serverTransaction); - } + } - } + } - /** - * Get entry in the server transaction pending ACK table corresponding to an - * ACK. - * - * @param ackMessage - * @return - */ - public SIPServerTransaction findTransactionPendingAck(SIPRequest ackMessage) { - return this.terminatedServerTransactionsPendingAck.get(ackMessage - .getTopmostVia().getBranch()); - } + /** + * Add entry to "Transaction Pending ACK" table. + * + * @param serverTransaction + */ + public void addTransactionPendingAck(SIPServerTransaction serverTransaction) { + String branchId = ((SIPRequest) serverTransaction.getRequest()) + .getTopmostVia().getBranch(); + if (branchId != null) { + this.terminatedServerTransactionsPendingAck.put(branchId, + serverTransaction); + } - /** - * Remove entry from "Transaction Pending ACK" table. - * - * @param serverTransaction - * @return - */ - - public boolean removeTransactionPendingAck(SIPServerTransaction serverTransaction) { -// String branchId = ((SIPRequest)serverTransaction.getRequest()).getTopmostVia().getBranch(); - String branchId = serverTransaction.getBranchId(); - if ( branchId != null - && this.terminatedServerTransactionsPendingAck. - containsKey(branchId) ) { - this.terminatedServerTransactionsPendingAck.remove(branchId); - return true; - } else { - return false; - } - } + } - /** - * Check if this entry exists in the "Transaction Pending ACK" table. - * - * @param serverTransaction - * @return - */ - public boolean isTransactionPendingAck( - SIPServerTransaction serverTransaction) { - String branchId = ((SIPRequest) serverTransaction.getRequest()) - .getTopmostVia().getBranch(); - return this.terminatedServerTransactionsPendingAck.contains(branchId); - } + /** + * Get entry in the server transaction pending ACK table corresponding to an + * ACK. + * + * @param ackMessage + * @return + */ + public SIPServerTransaction findTransactionPendingAck(SIPRequest ackMessage) { + return this.terminatedServerTransactionsPendingAck.get(ackMessage + .getTopmostVia().getBranch()); + } - /** - * Find the transaction corresponding to a given request. - * - * @param sipMessage - * request for which to retrieve the transaction. - * - * @param isServer - * search the server transaction table if true. - * - * @return the transaction object corresponding to the request or null if no - * such mapping exists. - */ - public SIPTransaction findTransaction(SIPMessage sipMessage, - boolean isServer) { - SIPTransaction retval = null; - try { - if (isServer) { - Via via = sipMessage.getTopmostVia(); - if (via.getBranch() != null) { - String key = sipMessage.getTransactionId(); - - retval = (SIPTransaction) serverTransactionTable.get(key); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger - .logDebug( - "serverTx: looking for key " + key - + " existing=" - + serverTransactionTable); - if (key - .startsWith(SIPConstants.BRANCH_MAGIC_COOKIE_LOWER_CASE)) { - return retval; - } - - } - // Need to scan the table for old style transactions (RFC 2543 - // style) - Iterator it = serverTransactionTable - .values().iterator(); - while (it.hasNext()) { - SIPServerTransaction sipServerTransaction = (SIPServerTransaction) it - .next(); - if (sipServerTransaction - .isMessagePartOfTransaction(sipMessage)) { - retval = sipServerTransaction; - return retval; - } - } - - } else { - Via via = sipMessage.getTopmostVia(); - if (via.getBranch() != null) { - String key = sipMessage.getTransactionId(); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug( - "clientTx: looking for key " + key); - retval = (SIPTransaction) clientTransactionTable.get(key); - if (key - .startsWith(SIPConstants.BRANCH_MAGIC_COOKIE_LOWER_CASE)) { - return retval; - } - - } - // Need to scan the table for old style transactions (RFC 2543 - // style). This is terribly slow but we need to do this - // for backasswords compatibility. - Iterator it = clientTransactionTable - .values().iterator(); - while (it.hasNext()) { - SIPClientTransaction clientTransaction = (SIPClientTransaction) it - .next(); - if (clientTransaction - .isMessagePartOfTransaction(sipMessage)) { - retval = clientTransaction; - return retval; - } - } - - } - } finally { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( - "findTransaction: returning : " + retval); - } - } - return retval; + /** + * Remove entry from "Transaction Pending ACK" table. + * + * @param serverTransaction + * @return + */ + + public boolean removeTransactionPendingAck( + SIPServerTransaction serverTransaction) { + String branchId = ((SIPRequest) serverTransaction.getRequest()) + .getTopmostVia().getBranch(); + if (branchId != null + && this.terminatedServerTransactionsPendingAck + .containsKey(branchId)) { + this.terminatedServerTransactionsPendingAck.remove(branchId); + return true; + } else { + return false; + } + } - } + /** + * Check if this entry exists in the "Transaction Pending ACK" table. + * + * @param serverTransaction + * @return + */ + public boolean isTransactionPendingAck( + SIPServerTransaction serverTransaction) { + String branchId = ((SIPRequest) serverTransaction.getRequest()) + .getTopmostVia().getBranch(); + return this.terminatedServerTransactionsPendingAck.contains(branchId); + } - public SIPTransaction findTransaction(String transactionId, boolean isServer) { - if(isServer) { - return serverTransactionTable.get(transactionId); - } else { - return clientTransactionTable.get(transactionId); - } - } + /** + * Find the transaction corresponding to a given request. + * + * @param sipMessage + * request for which to retrieve the transaction. + * + * @param isServer + * search the server transaction table if true. + * + * @return the transaction object corresponding to the request or null if no + * such mapping exists. + */ + public SIPTransaction findTransaction(SIPMessage sipMessage, + boolean isServer) { + SIPTransaction retval = null; + try { + if (isServer) { + Via via = sipMessage.getTopmostVia(); + if (via.getBranch() != null) { + String key = sipMessage.getTransactionId(); + + retval = (SIPTransaction) serverTransactionTable.get(key); + if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + getStackLogger() + .logDebug( + "serverTx: looking for key " + key + + " existing=" + + serverTransactionTable); + if (key + .startsWith(SIPConstants.BRANCH_MAGIC_COOKIE_LOWER_CASE)) { + return retval; + } - /** - * Get the transaction to cancel. Search the server transaction table for a - * transaction that matches the given transaction. - */ - public SIPTransaction findCancelTransaction(SIPRequest cancelRequest, - boolean isServer) { - - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("findCancelTransaction request= \n" - + cancelRequest + "\nfindCancelRequest isServer=" - + isServer); - } - - if (isServer) { - Iterator li = this.serverTransactionTable - .values().iterator(); - while (li.hasNext()) { - SIPTransaction transaction = (SIPTransaction) li.next(); - - SIPServerTransaction sipServerTransaction = (SIPServerTransaction) transaction; - if (sipServerTransaction - .doesCancelMatchTransaction(cancelRequest)) - return sipServerTransaction; - } - - } else { - Iterator li = this.clientTransactionTable - .values().iterator(); - while (li.hasNext()) { - SIPTransaction transaction = (SIPTransaction) li.next(); - - SIPClientTransaction sipClientTransaction = (SIPClientTransaction) transaction; - if (sipClientTransaction - .doesCancelMatchTransaction(cancelRequest)) - return sipClientTransaction; - - } - - } - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger - .logDebug("Could not find transaction for cancel request"); - return null; - } + } + // Need to scan the table for old style transactions (RFC 2543 + // style) + Iterator it = serverTransactionTable + .values().iterator(); + while (it.hasNext()) { + SIPServerTransaction sipServerTransaction = (SIPServerTransaction) it + .next(); + if (sipServerTransaction + .isMessagePartOfTransaction(sipMessage)) { + retval = sipServerTransaction; + return retval; + } + } - /** - * Construcor for the stack. Registers the request and response factories - * for the stack. - * - * @param messageFactory - * User-implemented factory for processing messages. - */ - protected SIPTransactionStack(StackMessageFactory messageFactory) { - this(); - this.sipMessageFactory = messageFactory; - } + } else { + Via via = sipMessage.getTopmostVia(); + if (via.getBranch() != null) { + String key = sipMessage.getTransactionId(); + if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + getStackLogger().logDebug( + "clientTx: looking for key " + key); + retval = (SIPTransaction) clientTransactionTable.get(key); + if (key + .startsWith(SIPConstants.BRANCH_MAGIC_COOKIE_LOWER_CASE)) { + return retval; + } - /** - * Finds a pending server transaction. Since each request may be handled - * either statefully or statelessly, we keep a map of pending transactions - * so that a duplicate transaction is not created if a second request is - * recieved while the first one is being processed. - * - * @param requestReceived - * @return -- the pending transaction or null if no such transaction exists. - */ - public SIPServerTransaction findPendingTransaction( - String transactionId) { - if (this.logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - this.logger.logDebug("looking for pending tx for :" - + transactionId); - } - return (SIPServerTransaction) pendingTransactions.get(transactionId); + } + // Need to scan the table for old style transactions (RFC 2543 + // style). This is terribly slow but we need to do this + // for backasswords compatibility. + Iterator it = clientTransactionTable + .values().iterator(); + while (it.hasNext()) { + SIPClientTransaction clientTransaction = (SIPClientTransaction) it + .next(); + if (clientTransaction + .isMessagePartOfTransaction(sipMessage)) { + retval = clientTransaction; + return retval; + } + } - } + } + } finally { + if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + this.getStackLogger().logDebug( + "findTransaction: returning : " + retval); + } + } + return retval; - /** - * See if there is a pending transaction with the same Merge ID as the Merge - * ID obtained from the SIP Request. The Merge table is for handling the - * following condition: If the request has no tag in the To header field, - * the UAS core MUST check the request against ongoing transactions. If the - * From tag, Call-ID, and CSeq exactly match those associated with an - * ongoing transaction, but the request does not match that transaction - * (based on the matching rules in Section 17.2.3), the UAS core SHOULD - * generate a 482 (Loop Detected) response and pass it to the server - * transaction. - */ - public boolean findMergedTransaction(SIPRequest sipRequest) { - if (!sipRequest.getMethod().equals(Request.INVITE)) { - /* - * Dont need to worry about request merging for Non-INVITE - * transactions. - */ - return false; - } - String mergeId = sipRequest.getMergeId(); - if (mergeId != null) { - SIPServerTransaction mergedTransaction = (SIPServerTransaction) this.mergeTable - .get(mergeId); - if (mergedTransaction != null - && !mergedTransaction - .isMessagePartOfTransaction(sipRequest)) { - return true; - }else { - /* - * Check for loop detection for really late arriving - * requests - */ - SIPDialog serverDialog = this.serverDialogMergeTestTable - .get(mergeId); - if (serverDialog != null && serverDialog.firstTransactionIsServerTransaction - && serverDialog.getState() == DialogState.CONFIRMED) { - return true; - } - } - } - - return false; - } + } - /** - * Remove a pending Server transaction from the stack. This is called after - * the user code has completed execution in the listener. - * - * @param tr - * -- pending transaction to remove. - */ - public void removePendingTransaction(SIPServerTransaction tr) { - if (this.logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - this.logger.logDebug("removePendingTx: " - + tr.getTransactionId()); - } - this.pendingTransactions.remove(tr.getTransactionId()); + /** + * Get the transaction to cancel. Search the server transaction table for a + * transaction that matches the given transaction. + */ + public SIPTransaction findCancelTransaction(SIPRequest cancelRequest, + boolean isServer) { + + if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + stackLogger.logDebug("findCancelTransaction request= \n" + + cancelRequest + "\nfindCancelRequest isServer=" + + isServer); + } - } + if (isServer) { + Iterator li = this.serverTransactionTable + .values().iterator(); + while (li.hasNext()) { + SIPTransaction transaction = (SIPTransaction) li.next(); - /** - * Remove a transaction from the merge table. - * - * @param tr - * -- the server transaction to remove from the merge table. - * - */ - public void removeFromMergeTable(SIPServerTransaction tr) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - this.logger.logDebug("Removing tx from merge table "); - } - String key = ((SIPRequest) tr.getRequest()).getMergeId(); - if (key != null) { - this.mergeTable.remove(key); - } - } + SIPServerTransaction sipServerTransaction = (SIPServerTransaction) transaction; + if (sipServerTransaction + .doesCancelMatchTransaction(cancelRequest)) + return sipServerTransaction; + } - /** - * Put this into the merge request table. - * - * @param sipTransaction - * -- transaction to put into the merge table. - * - */ - public void putInMergeTable(SIPServerTransaction sipTransaction, - SIPRequest sipRequest) { - String mergeKey = sipRequest.getMergeId(); - if (mergeKey != null) { - this.mergeTable.put(mergeKey, sipTransaction); - } - } + } else { + Iterator li = this.clientTransactionTable + .values().iterator(); + while (li.hasNext()) { + SIPTransaction transaction = (SIPTransaction) li.next(); - /** - * Map a Server transaction (possibly sending out a 100 if the server tx is - * an INVITE). This actually places it in the hash table and makes it known - * to the stack. - * - * @param transaction - * -- the server transaction to map. - */ - public void mapTransaction(SIPServerTransaction transaction) { - if (transaction.isMapped) - return; - addTransactionHash(transaction); - // transaction.startTransactionTimer(); - transaction.isMapped = true; - } + SIPClientTransaction sipClientTransaction = (SIPClientTransaction) transaction; + if (sipClientTransaction + .doesCancelMatchTransaction(cancelRequest)) + return sipClientTransaction; - /** - * Handles a new SIP request. It finds a server transaction to handle this - * message. If none exists, it creates a new transaction. - * - * @param requestReceived - * Request to handle. - * @param requestMessageChannel - * Channel that received message. - * - * @return A server transaction. - */ - public ServerRequestInterface newSIPServerRequest( - SIPRequest requestReceived, MessageChannel requestMessageChannel) { - // Next transaction in the set - SIPServerTransaction nextTransaction; - - final String key = requestReceived.getTransactionId(); - - requestReceived.setMessageChannel(requestMessageChannel); - - if(sipMessageValve != null) { - if(!sipMessageValve.processRequest( - requestReceived, requestMessageChannel)) { - if(logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( - "Request dropped by the SIP message valve. Request = " + requestReceived); - } - return null; - } - } - - // Transaction to handle this request - SIPServerTransaction currentTransaction = (SIPServerTransaction) findTransaction(key, true); - - // Got to do this for bacasswards compatibility. - if (currentTransaction == null - || !currentTransaction - .isMessagePartOfTransaction(requestReceived)) { - - // Loop through all server transactions - currentTransaction = null; - if (!key.toLowerCase().startsWith( - SIPConstants.BRANCH_MAGIC_COOKIE_LOWER_CASE)) { - Iterator transactionIterator = serverTransactionTable.values().iterator(); - while (transactionIterator.hasNext() - && currentTransaction == null) { - - nextTransaction = (SIPServerTransaction) transactionIterator - .next(); - - // If this transaction should handle this request, - if (nextTransaction - .isMessagePartOfTransaction(requestReceived)) { - // Mark this transaction as the one - // to handle this message - currentTransaction = nextTransaction; - } - } - } - - // If no transaction exists to handle this message - if (currentTransaction == null) { - currentTransaction = findPendingTransaction(key); - if (currentTransaction != null) { - // Associate the tx with the received request. - requestReceived.setTransaction(currentTransaction); - if (currentTransaction != null - && currentTransaction.acquireSem()) - return currentTransaction; - else - return null; - - } - // Creating a new server tx. May fail under heavy load. - currentTransaction = createServerTransaction(requestMessageChannel); - if (currentTransaction != null) { - // currentTransaction.setPassToListener(); - currentTransaction.setOriginalRequest(requestReceived); - // Associate the tx with the received request. - requestReceived.setTransaction(currentTransaction); - } - - } - - } - - // Set ths transaction's encapsulated request - // interface from the superclass - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("newSIPServerRequest( " - + requestReceived.getMethod() + ":" - + requestReceived.getTopmostVia().getBranch() + "):" - + currentTransaction); - } - - if (currentTransaction != null) - currentTransaction.setRequestInterface(sipMessageFactory - .newSIPServerRequest(requestReceived, currentTransaction)); - - if (currentTransaction != null && currentTransaction.acquireSem()) { - return currentTransaction; - } else if (currentTransaction != null) { - try { - /* - * Already processing a message for this transaction. SEND a - * trying ( message already being processed ). - */ - if (currentTransaction - .isMessagePartOfTransaction(requestReceived) - && currentTransaction.getMethod().equals( - requestReceived.getMethod())) { - SIPResponse trying = requestReceived - .createResponse(Response.TRYING); - trying.removeContent(); - currentTransaction.getMessageChannel().sendMessage(trying); - } - } catch (Exception ex) { - if (logger.isLoggingEnabled()) - logger.logError("Exception occured sending TRYING"); - } - return null; - } else { - return null; - } - } + } - /** - * Handles a new SIP response. It finds a client transaction to handle this - * message. If none exists, it sends the message directly to the superclass. - * - * @param responseReceived - * Response to handle. - * @param responseMessageChannel - * Channel that received message. - * - * @return A client transaction. - */ - public ServerResponseInterface newSIPServerResponse( - SIPResponse responseReceived, MessageChannel responseMessageChannel) { - - // Iterator through all client transactions - Iterator transactionIterator; - // Next transaction in the set - SIPClientTransaction nextTransaction; - // Transaction to handle this request - SIPClientTransaction currentTransaction; - - if(sipMessageValve != null) { - if(!sipMessageValve.processResponse( - responseReceived, responseMessageChannel)) { - if(logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( - "Response dropped by the SIP message valve. Response = " + responseReceived); - } - return null; - } - } - - String key = responseReceived.getTransactionId(); - - // Note that for RFC 3261 compliant operation, this lookup will - // return a tx if one exists and hence no need to search through - // the table. - currentTransaction = (SIPClientTransaction) findTransaction(key, false); - - if (currentTransaction == null - || (!currentTransaction - .isMessagePartOfTransaction(responseReceived) && !key - .startsWith(SIPConstants.BRANCH_MAGIC_COOKIE_LOWER_CASE))) { - // Loop through all client transactions - - transactionIterator = clientTransactionTable.values().iterator(); - currentTransaction = null; - while (transactionIterator.hasNext() && currentTransaction == null) { - - nextTransaction = (SIPClientTransaction) transactionIterator - .next(); - - // If this transaction should handle this request, - if (nextTransaction - .isMessagePartOfTransaction(responseReceived)) { - - // Mark this transaction as the one to - // handle this message - currentTransaction = nextTransaction; - - } - - } - - // If no transaction exists to handle this message, - if (currentTransaction == null) { - // JvB: Need to log before passing the response to the client - // app, it - // gets modified! - if (this.logger.isLoggingEnabled(StackLogger.TRACE_INFO)) { - responseMessageChannel.logResponse(responseReceived, System - .currentTimeMillis(), "before processing"); - } - - // Pass the message directly to the TU - return sipMessageFactory.newSIPServerResponse(responseReceived, - responseMessageChannel); - - } - } - - // Aquire the sem -- previous request may still be processing. - boolean acquired = currentTransaction.acquireSem(); - // Set ths transaction's encapsulated response interface - // from the superclass - if (this.logger.isLoggingEnabled(StackLogger.TRACE_INFO)) { - currentTransaction.logResponse(responseReceived, System - .currentTimeMillis(), "before processing"); - } - - if (acquired) { - ServerResponseInterface sri = sipMessageFactory - .newSIPServerResponse(responseReceived, currentTransaction); - if (sri != null) { - currentTransaction.setResponseInterface(sri); - } else { - if (this.logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - this.logger - .logDebug("returning null - serverResponseInterface is null!"); - } - currentTransaction.releaseSem(); - return null; - } - } else { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - this.logger.logDebug("Could not aquire semaphore !!"); - } - - if (acquired) - return currentTransaction; - else - return null; + } + if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + stackLogger + .logDebug("Could not find transaction for cancel request"); + return null; + } - } + /** + * Construcor for the stack. Registers the request and response factories + * for the stack. + * + * @param messageFactory + * User-implemented factory for processing messages. + */ + protected SIPTransactionStack(StackMessageFactory messageFactory) { + this(); + this.sipMessageFactory = messageFactory; + } - /** - * Creates a client transaction to handle a new request. Gets the real - * message channel from the superclass, and then creates a new client - * transaction wrapped around this channel. - * - * @param nextHop - * Hop to create a channel to contact. - */ - public MessageChannel createMessageChannel(SIPRequest request, - MessageProcessor mp, Hop nextHop) throws IOException { - // New client transaction to return - SIPTransaction returnChannel; - - // Create a new client transaction around the - // superclass' message channel - // Create the host/port of the target hop - Host targetHost = new Host(); - targetHost.setHostname(nextHop.getHost()); - HostPort targetHostPort = new HostPort(); - targetHostPort.setHost(targetHost); - targetHostPort.setPort(nextHop.getPort()); - MessageChannel mc = mp.createMessageChannel(targetHostPort); - - // Superclass will return null if no message processor - // available for the transport. - if (mc == null) - return null; - - returnChannel = createClientTransaction(request, mc); - - ((SIPClientTransaction) returnChannel).setViaPort(nextHop.getPort()); - ((SIPClientTransaction) returnChannel).setViaHost(nextHop.getHost()); - addTransactionHash(returnChannel); - // clientTransactionTable.put(returnChannel.getTransactionId(), - // returnChannel); - // Add the transaction timer for the state machine. - // returnChannel.startTransactionTimer(); - return returnChannel; + /** + * Finds a pending server transaction. Since each request may be handled + * either statefully or statelessly, we keep a map of pending transactions + * so that a duplicate transaction is not created if a second request is + * recieved while the first one is being processed. + * + * @param requestReceived + * @return -- the pending transaction or null if no such transaction exists. + */ + public SIPServerTransaction findPendingTransaction( + SIPRequest requestReceived) { + if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + this.stackLogger.logDebug("looking for pending tx for :" + + requestReceived.getTransactionId()); + } + return (SIPServerTransaction) pendingTransactions.get(requestReceived + .getTransactionId()); - } + } - /** - * Creates a client transaction that encapsulates a MessageChannel. Useful - * for implementations that want to subclass the standard - * - * @param encapsulatedMessageChannel - * Message channel of the transport layer. - */ - public SIPClientTransaction createClientTransaction(SIPRequest sipRequest, - MessageChannel encapsulatedMessageChannel) { - SIPClientTransaction ct = new SIPClientTransaction(this, - encapsulatedMessageChannel); - ct.setOriginalRequest(sipRequest); - return ct; - } + /** + * See if there is a pending transaction with the same Merge ID as the Merge + * ID obtained from the SIP Request. The Merge table is for handling the + * following condition: If the request has no tag in the To header field, + * the UAS core MUST check the request against ongoing transactions. If the + * From tag, Call-ID, and CSeq exactly match those associated with an + * ongoing transaction, but the request does not match that transaction + * (based on the matching rules in Section 17.2.3), the UAS core SHOULD + * generate a 482 (Loop Detected) response and pass it to the server + * transaction. + */ + public boolean findMergedTransaction(SIPRequest sipRequest) { + if (!sipRequest.getMethod().equals(Request.INVITE)) { + /* + * Dont need to worry about request merging for Non-INVITE + * transactions. + */ + return false; + } + String mergeId = sipRequest.getMergeId(); + if (mergeId != null) { + SIPServerTransaction mergedTransaction = (SIPServerTransaction) this.mergeTable + .get(mergeId); + if (mergedTransaction != null + && !mergedTransaction + .isMessagePartOfTransaction(sipRequest)) { + return true; + }else { + /* + * Check for loop detection for really late arriving + * requests + */ + SIPDialog serverDialog = this.serverDialogMergeTestTable + .get(mergeId); + if (serverDialog != null && serverDialog.firstTransactionIsServerTransaction + && serverDialog.getState() == DialogState.CONFIRMED) { + return true; + } + } + } - /** - * Creates a server transaction that encapsulates a MessageChannel. Useful - * for implementations that want to subclass the standard - * - * @param encapsulatedMessageChannel - * Message channel of the transport layer. - */ - public SIPServerTransaction createServerTransaction( - MessageChannel encapsulatedMessageChannel) { - // Issue 256 : be consistent with createClientTransaction, if - // unlimitedServerTransactionTableSize is true, - // a new Server Transaction is created no matter what - if (unlimitedServerTransactionTableSize) { - return new SIPServerTransaction(this, encapsulatedMessageChannel); - } else { - float threshold = ((float) (serverTransactionTable.size() - serverTransactionTableLowaterMark)) - / ((float) (serverTransactionTableHighwaterMark - serverTransactionTableLowaterMark)); - boolean decision = Math.random() > 1.0 - threshold; - if (decision) { - return null; - } else { - return new SIPServerTransaction(this, - encapsulatedMessageChannel); - } - - } + return false; + } - } + /** + * Remove a pending Server transaction from the stack. This is called after + * the user code has completed execution in the listener. + * + * @param tr + * -- pending transaction to remove. + */ + public void removePendingTransaction(SIPServerTransaction tr) { + if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + this.stackLogger.logDebug("removePendingTx: " + + tr.getTransactionId()); + } + this.pendingTransactions.remove(tr.getTransactionId()); - /** - * Get the size of the client transaction table. - * - * @return -- size of the ct table. - */ - public int getClientTransactionTableSize() { - return this.clientTransactionTable.size(); - } + } - /** - * Get the size of the server transaction table. - * - * @return -- size of the server table. - */ - public int getServerTransactionTableSize() { - return this.serverTransactionTable.size(); - } + /** + * Remove a transaction from the merge table. + * + * @param tr + * -- the server transaction to remove from the merge table. + * + */ + public void removeFromMergeTable(SIPServerTransaction tr) { + if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + this.stackLogger.logDebug("Removing tx from merge table "); + } + String key = ((SIPRequest) tr.getRequest()).getMergeId(); + if (key != null) { + this.mergeTable.remove(key); + } + } - /** - * Add a new client transaction to the set of existing transactions. Add it - * to the top of the list so an incoming response has less work to do in - * order to find the transaction. - * - * @param clientTransaction - * -- client transaction to add to the set. - */ - public void addTransaction(SIPClientTransaction clientTransaction) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("added transaction " + clientTransaction); - addTransactionHash(clientTransaction); + /** + * Put this into the merge request table. + * + * @param sipTransaction + * -- transaction to put into the merge table. + * + */ + public void putInMergeTable(SIPServerTransaction sipTransaction, + SIPRequest sipRequest) { + String mergeKey = sipRequest.getMergeId(); + if (mergeKey != null) { + this.mergeTable.put(mergeKey, sipTransaction); + } + } - } + /** + * Map a Server transaction (possibly sending out a 100 if the server tx is + * an INVITE). This actually places it in the hash table and makes it known + * to the stack. + * + * @param transaction + * -- the server transaction to map. + */ + public void mapTransaction(SIPServerTransaction transaction) { + if (transaction.isMapped) + return; + addTransactionHash(transaction); + // transaction.startTransactionTimer(); + transaction.isMapped = true; + } - /** - * Remove transaction. This actually gets the tx out of the search - * structures which the stack keeps around. When the tx - */ - public void removeTransaction(SIPTransaction sipTransaction) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("removeTransaction: Removing Transaction = " - + sipTransaction.getTransactionId() + " transaction = " - + sipTransaction); - } - try { - if (sipTransaction instanceof SIPServerTransaction) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) { - logger.logStackTrace(); - } - String key = sipTransaction.getTransactionId(); - Object removed = serverTransactionTable.remove(key); - String method = sipTransaction.getMethod(); - this - .removePendingTransaction((SIPServerTransaction) sipTransaction); - this - .removeTransactionPendingAck((SIPServerTransaction) sipTransaction); - if (method.equalsIgnoreCase(Request.INVITE)) { - this - .removeFromMergeTable((SIPServerTransaction) sipTransaction); - } - // Send a notification to the listener. - SipProviderImpl sipProvider = (SipProviderImpl) sipTransaction - .getSipProvider(); - if (removed != null - && sipTransaction.testAndSetTransactionTerminatedEvent()) { - TransactionTerminatedEvent event = new TransactionTerminatedEvent( - sipProvider, (ServerTransaction) sipTransaction); - - sipProvider.handleEvent(event, sipTransaction); - - } - } else { - - String key = sipTransaction.getTransactionId(); - Object removed = clientTransactionTable.remove(key); - - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("REMOVED client tx " + removed + " KEY = " - + key); - - - } - if ( removed != null ) { - SIPClientTransaction clientTx = (SIPClientTransaction)removed; - final String forkId = clientTx.getForkId(); - if (forkId != null && clientTx.isInviteTransaction() - && this.maxForkTime != 0) { - this.timer.schedule(new RemoveForkedTransactionTimerTask( - forkId), this.maxForkTime * 1000); - clientTx.stopExpiresTimer(); - } - } - - // Send a notification to the listener. - if (removed != null - && sipTransaction.testAndSetTransactionTerminatedEvent()) { - SipProviderImpl sipProvider = (SipProviderImpl) sipTransaction - .getSipProvider(); - TransactionTerminatedEvent event = new TransactionTerminatedEvent( - sipProvider, (ClientTransaction) sipTransaction); - - sipProvider.handleEvent(event, sipTransaction); - } - - } - } finally { - if ( logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug(String.format("removeTransaction: Table size : " + - " clientTransactionTable %d " + - " mergetTable %d " + - " terminatedServerTransactionsPendingAck %d " + - " forkedClientTransactionTable %d " + - " pendingTransactions %d " , - clientTransactionTable.size(), mergeTable.size(), - terminatedServerTransactionsPendingAck.size(), - forkedClientTransactionTable.size(), - pendingTransactions.size() - )); - } - } + /** + * Handles a new SIP request. It finds a server transaction to handle this + * message. If none exists, it creates a new transaction. + * + * @param requestReceived + * Request to handle. + * @param requestMessageChannel + * Channel that received message. + * + * @return A server transaction. + */ + public ServerRequestInterface newSIPServerRequest( + SIPRequest requestReceived, MessageChannel requestMessageChannel) { + // Iterator through all server transactions + Iterator transactionIterator; + // Next transaction in the set + SIPServerTransaction nextTransaction; + // Transaction to handle this request + SIPServerTransaction currentTransaction; + + String key = requestReceived.getTransactionId(); + + requestReceived.setMessageChannel(requestMessageChannel); + + currentTransaction = (SIPServerTransaction) serverTransactionTable + .get(key); + + // Got to do this for bacasswards compatibility. + if (currentTransaction == null + || !currentTransaction + .isMessagePartOfTransaction(requestReceived)) { + + // Loop through all server transactions + transactionIterator = serverTransactionTable.values().iterator(); + currentTransaction = null; + if (!key.toLowerCase().startsWith( + SIPConstants.BRANCH_MAGIC_COOKIE_LOWER_CASE)) { + while (transactionIterator.hasNext() + && currentTransaction == null) { + + nextTransaction = (SIPServerTransaction) transactionIterator + .next(); + + // If this transaction should handle this request, + if (nextTransaction + .isMessagePartOfTransaction(requestReceived)) { + // Mark this transaction as the one + // to handle this message + currentTransaction = nextTransaction; + } + } + } - /** - * Add a new server transaction to the set of existing transactions. Add it - * to the top of the list so an incoming ack has less work to do in order to - * find the transaction. - * - * @param serverTransaction - * -- server transaction to add to the set. - */ - public void addTransaction(SIPServerTransaction serverTransaction) - throws IOException { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("added transaction " + serverTransaction); - serverTransaction.map(); - - addTransactionHash(serverTransaction); + // If no transaction exists to handle this message + if (currentTransaction == null) { + currentTransaction = findPendingTransaction(requestReceived); + if (currentTransaction != null) { + // Associate the tx with the received request. + requestReceived.setTransaction(currentTransaction); + if (currentTransaction != null + && currentTransaction.acquireSem()) + return currentTransaction; + else + return null; - } + } + // Creating a new server tx. May fail under heavy load. + currentTransaction = createServerTransaction(requestMessageChannel); + if (currentTransaction != null) { + // currentTransaction.setPassToListener(); + currentTransaction.setOriginalRequest(requestReceived); + // Associate the tx with the received request. + requestReceived.setTransaction(currentTransaction); + } - /** - * Hash table for quick lookup of transactions. Here we wait for room if - * needed. - */ - private void addTransactionHash(SIPTransaction sipTransaction) { - SIPRequest sipRequest = sipTransaction.getOriginalRequest(); - if (sipTransaction instanceof SIPClientTransaction) { - if (!this.unlimitedClientTransactionTableSize) { - if (this.activeClientTransactionCount.get() > clientTransactionTableHiwaterMark) { - try { - synchronized (this.clientTransactionTable) { - this.clientTransactionTable.wait(); - this.activeClientTransactionCount.incrementAndGet(); - } - - } catch (Exception ex) { - if (logger.isLoggingEnabled()) { - logger.logError( - "Exception occured while waiting for room", - ex); - } - - } - } - } else { - this.activeClientTransactionCount.incrementAndGet(); - } - String key = sipRequest.getTransactionId(); - clientTransactionTable.put(key, - (SIPClientTransaction) sipTransaction); - - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger - .logDebug(" putTransactionHash : " + " key = " + key); - } - } else { - String key = sipRequest.getTransactionId(); - - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger - .logDebug(" putTransactionHash : " + " key = " + key); - } - serverTransactionTable.put(key, - (SIPServerTransaction) sipTransaction); - - } + } - } + } - /** - * This method is called when a client tx transitions to the Completed or - * Terminated state. - * - */ - protected void decrementActiveClientTransactionCount() { + // Set ths transaction's encapsulated request + // interface from the superclass + if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + stackLogger.logDebug("newSIPServerRequest( " + + requestReceived.getMethod() + ":" + + requestReceived.getTopmostVia().getBranch() + "):" + + currentTransaction); + } - if (this.activeClientTransactionCount.decrementAndGet() <= this.clientTransactionTableLowaterMark - && !this.unlimitedClientTransactionTableSize) { - synchronized (this.clientTransactionTable) { + if (currentTransaction != null) + currentTransaction.setRequestInterface(sipMessageFactory + .newSIPServerRequest(requestReceived, currentTransaction)); + + if (currentTransaction != null && currentTransaction.acquireSem()) { + return currentTransaction; + } else if (currentTransaction != null) { + try { + /* + * Already processing a message for this transaction. SEND a + * trying ( message already being processed ). + */ + if (currentTransaction + .isMessagePartOfTransaction(requestReceived) + && currentTransaction.getMethod().equals( + requestReceived.getMethod())) { + SIPResponse trying = requestReceived + .createResponse(Response.TRYING); + trying.removeContent(); + currentTransaction.getMessageChannel().sendMessage(trying); + } + } catch (Exception ex) { + if (isLoggingEnabled()) + stackLogger.logError("Exception occured sending TRYING"); + } + return null; + } else { + return null; + } + } - clientTransactionTable.notify(); + /** + * Handles a new SIP response. It finds a client transaction to handle this + * message. If none exists, it sends the message directly to the superclass. + * + * @param responseReceived + * Response to handle. + * @param responseMessageChannel + * Channel that received message. + * + * @return A client transaction. + */ + public ServerResponseInterface newSIPServerResponse( + SIPResponse responseReceived, MessageChannel responseMessageChannel) { + + // Iterator through all client transactions + Iterator transactionIterator; + // Next transaction in the set + SIPClientTransaction nextTransaction; + // Transaction to handle this request + SIPClientTransaction currentTransaction; + + String key = responseReceived.getTransactionId(); + + // Note that for RFC 3261 compliant operation, this lookup will + // return a tx if one exists and hence no need to search through + // the table. + currentTransaction = (SIPClientTransaction) clientTransactionTable + .get(key); + + if (currentTransaction == null + || (!currentTransaction + .isMessagePartOfTransaction(responseReceived) && !key + .startsWith(SIPConstants.BRANCH_MAGIC_COOKIE_LOWER_CASE))) { + // Loop through all client transactions + + transactionIterator = clientTransactionTable.values().iterator(); + currentTransaction = null; + while (transactionIterator.hasNext() && currentTransaction == null) { + + nextTransaction = (SIPClientTransaction) transactionIterator + .next(); + + // If this transaction should handle this request, + if (nextTransaction + .isMessagePartOfTransaction(responseReceived)) { + + // Mark this transaction as the one to + // handle this message + currentTransaction = nextTransaction; - } - } - } + } - /** - * Remove the transaction from transaction hash. - */ - protected void removeTransactionHash(SIPTransaction sipTransaction) { - SIPRequest sipRequest = sipTransaction.getOriginalRequest(); - if (sipRequest == null) - return; - if (sipTransaction instanceof SIPClientTransaction) { - String key = sipTransaction.getTransactionId(); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logStackTrace(); - logger.logDebug("removing client Tx : " + key); - } - clientTransactionTable.remove(key); - - } else if (sipTransaction instanceof SIPServerTransaction) { - String key = sipTransaction.getTransactionId(); - serverTransactionTable.remove(key); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("removing server Tx : " + key); - } - } - } + } - /** - * Invoked when an error has ocurred with a transaction. - * - * @param transactionErrorEvent - * Error event. - */ - public synchronized void transactionErrorEvent( - SIPTransactionErrorEvent transactionErrorEvent) { - SIPTransaction transaction = (SIPTransaction) transactionErrorEvent - .getSource(); - - if (transactionErrorEvent.getErrorID() == SIPTransactionErrorEvent.TRANSPORT_ERROR) { - // Kill scanning of this transaction. - transaction.setState(TransactionState._TERMINATED); - if (transaction instanceof SIPServerTransaction) { - // let the reaper get him - ((SIPServerTransaction) transaction).collectionTime = 0; - } - transaction.disableTimeoutTimer(); - transaction.disableRetransmissionTimer(); - // Send a IO Exception to the Listener. - } - } + // If no transaction exists to handle this message, + if (currentTransaction == null) { + // JvB: Need to log before passing the response to the client + // app, it + // gets modified! + if (this.stackLogger.isLoggingEnabled(StackLogger.TRACE_INFO)) { + responseMessageChannel.logResponse(responseReceived, System + .currentTimeMillis(), "before processing"); + } - /* - * (non-Javadoc) - * - * @see - * gov.nist.javax.sip.stack.SIPDialogEventListener#dialogErrorEvent(gov. - * nist.javax.sip.stack.SIPDialogErrorEvent) - */ - public synchronized void dialogErrorEvent( - SIPDialogErrorEvent dialogErrorEvent) { - SIPDialog sipDialog = (SIPDialog) dialogErrorEvent.getSource(); - SipListener sipListener = ((SipStackImpl)this).getSipListener(); - // if the app is not implementing the SipListenerExt interface we delete - // the dialog to avoid leaks - if(sipDialog != null && !(sipListener instanceof SipListenerExt)) { - sipDialog.delete(); - } - } + // Pass the message directly to the TU + return sipMessageFactory.newSIPServerResponse(responseReceived, + responseMessageChannel); - /** - * Stop stack. Clear all the timer stuff. Make the stack close all accept - * connections and return. This is useful if you want to start/stop the - * stack several times from your application. Caution : use of this function - * could cause peculiar bugs as messages are prcessed asynchronously by the - * stack. - */ - public void stopStack() { - // Prevent NPE on two concurrent stops - this.toExit = true; - - // JvB: set it to null, SIPDialog tries to schedule things after stop - this.pendingTransactions.clear(); - synchronized (this) { - this.notifyAll(); - } - synchronized (this.clientTransactionTable) { - clientTransactionTable.notifyAll(); - } - - // Threads must periodically check this flag. - MessageProcessor[] processorList; - processorList = getMessageProcessors(); - for (int processorIndex = 0; processorIndex < processorList.length; processorIndex++) { - removeMessageProcessor(processorList[processorIndex]); - } - this.ioHandler.closeAll(); - // Let the processing complete. - - if (this.timer != null) - this.timer.stop(); - try { - Thread.sleep(1000); - } catch (InterruptedException ex) { - } - this.clientTransactionTable.clear(); - this.serverTransactionTable.clear(); - - this.dialogTable.clear(); - this.serverLogger.closeLogFile(); + } + } - } + // Aquire the sem -- previous request may still be processing. + boolean acquired = currentTransaction.acquireSem(); + // Set ths transaction's encapsulated response interface + // from the superclass + if (this.stackLogger.isLoggingEnabled(StackLogger.TRACE_INFO)) { + currentTransaction.logResponse(responseReceived, System + .currentTimeMillis(), "before processing"); + } - /** - * Put a transaction in the pending transaction list. This is to avoid a - * race condition when a duplicate may arrive when the application is - * deciding whether to create a transaction or not. - */ - public void putPendingTransaction(SIPServerTransaction tr) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("putPendingTransaction: " + tr); + if (acquired) { + ServerResponseInterface sri = sipMessageFactory + .newSIPServerResponse(responseReceived, currentTransaction); + if (sri != null) { + currentTransaction.setResponseInterface(sri); + } else { + if (this.stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + this.stackLogger + .logDebug("returning null - serverResponseInterface is null!"); + } + currentTransaction.releaseSem(); + return null; + } + } else { + if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + this.stackLogger.logDebug("Could not aquire semaphore !!"); + } - this.pendingTransactions.put(tr.getTransactionId(), tr); + if (acquired) + return currentTransaction; + else + return null; - } + } - /** - * Return the network layer (i.e. the interface for socket creation or the - * socket factory for the stack). - * - * @return -- the registered Network Layer. - */ - public NetworkLayer getNetworkLayer() { - if (networkLayer == null) { - return DefaultNetworkLayer.SINGLETON; - } else { - return networkLayer; - } - } + /** + * Creates a client transaction to handle a new request. Gets the real + * message channel from the superclass, and then creates a new client + * transaction wrapped around this channel. + * + * @param nextHop + * Hop to create a channel to contact. + */ + public MessageChannel createMessageChannel(SIPRequest request, + MessageProcessor mp, Hop nextHop) throws IOException { + // New client transaction to return + SIPTransaction returnChannel; + + // Create a new client transaction around the + // superclass' message channel + // Create the host/port of the target hop + Host targetHost = new Host(); + targetHost.setHostname(nextHop.getHost()); + HostPort targetHostPort = new HostPort(); + targetHostPort.setHost(targetHost); + targetHostPort.setPort(nextHop.getPort()); + MessageChannel mc = mp.createMessageChannel(targetHostPort); + + // Superclass will return null if no message processor + // available for the transport. + if (mc == null) + return null; + + returnChannel = createClientTransaction(request, mc); + + ((SIPClientTransaction) returnChannel).setViaPort(nextHop.getPort()); + ((SIPClientTransaction) returnChannel).setViaHost(nextHop.getHost()); + addTransactionHash(returnChannel); + // clientTransactionTable.put(returnChannel.getTransactionId(), + // returnChannel); + // Add the transaction timer for the state machine. + // returnChannel.startTransactionTimer(); + return returnChannel; - /** - * Return true if logging is enabled for this stack. - * Deprecated. Use StackLogger.isLoggingEnabled instead - * - * @return true if logging is enabled for this stack instance. - */ - @Deprecated - public boolean isLoggingEnabled() { - return logger == null ? false : logger - .isLoggingEnabled(); - } + } - /** - * Deprecated. Use StackLogger.isLoggingEnabled instead - * @param level - * @return - */ - @Deprecated - public boolean isLoggingEnabled( int level ) { - return logger == null ? false - : logger.isLoggingEnabled( level ); - } + /** + * Creates a client transaction that encapsulates a MessageChannel. Useful + * for implementations that want to subclass the standard + * + * @param encapsulatedMessageChannel + * Message channel of the transport layer. + */ + public SIPClientTransaction createClientTransaction(SIPRequest sipRequest, + MessageChannel encapsulatedMessageChannel) { + SIPClientTransaction ct = new SIPClientTransaction(this, + encapsulatedMessageChannel); + ct.setOriginalRequest(sipRequest); + return ct; + } - /** - * Get the logger. This method should be deprected. - * Use static logger = CommonLogger.getLogger() instead - * - * @return --the logger for the sip stack. Each stack has its own logger - * instance. - */ - @Deprecated - public StackLogger getStackLogger() { - return logger; - } + /** + * Creates a server transaction that encapsulates a MessageChannel. Useful + * for implementations that want to subclass the standard + * + * @param encapsulatedMessageChannel + * Message channel of the transport layer. + */ + public SIPServerTransaction createServerTransaction( + MessageChannel encapsulatedMessageChannel) { + // Issue 256 : be consistent with createClientTransaction, if + // unlimitedServerTransactionTableSize is true, + // a new Server Transaction is created no matter what + if (unlimitedServerTransactionTableSize) { + return new SIPServerTransaction(this, encapsulatedMessageChannel); + } else { + float threshold = ((float) (serverTransactionTable.size() - serverTransactionTableLowaterMark)) + / ((float) (serverTransactionTableHighwaterMark - serverTransactionTableLowaterMark)); + boolean decision = Math.random() > 1.0 - threshold; + if (decision) { + return null; + } else { + return new SIPServerTransaction(this, + encapsulatedMessageChannel); + } - /** - * Server log is the place where we log messages for the signaling trace - * viewer. - * - * @return -- the log file where messages are logged for viewing by the - * trace viewer. - */ - public ServerLogger getServerLogger() { - return this.serverLogger; - } + } - /** - * Maximum size of a single TCP message. Limiting the size of a single TCP - * message prevents flooding attacks. - * - * @return the size of a single TCP message. - */ - public int getMaxMessageSize() { - return this.maxMessageSize; - } + } - /** - * Set the flag that instructs the stack to only start a single thread for - * sequentially processing incoming udp messages (thus serializing the - * processing). Same as setting thread pool size to 1. - */ - public void setSingleThreaded() { - this.threadPoolSize = 1; - } + /** + * Get the size of the client transaction table. + * + * @return -- size of the ct table. + */ + public int getClientTransactionTableSize() { + return this.clientTransactionTable.size(); + } - /** - * If all calls are occurring on a single TCP socket then the stack would process them in single thread. - * This property allows immediately after parsing to split the load into many threads which increases - * the performance significantly. If set to 0 then we just use the old model with single thread. - * - * @return - */ - public int getTcpPostParsingThreadPoolSize() { - return tcpPostParsingThreadPoolSize; - } + /** + * Get the size of the server transaction table. + * + * @return -- size of the server table. + */ + public int getServerTransactionTableSize() { + return this.serverTransactionTable.size(); + } - /** - * If all calls are occurring on a single TCP socket then the stack would process them in single thread. - * This property allows immediately after parsing to split the load into many threads which increases - * the performance significantly. If set to 0 then we just use the old model with single thread. - * - * @param tcpPostParsingThreadPoolSize - */ - public void setTcpPostParsingThreadPoolSize(int tcpPostParsingThreadPoolSize) { - this.tcpPostParsingThreadPoolSize = tcpPostParsingThreadPoolSize; - } + /** + * Add a new client transaction to the set of existing transactions. Add it + * to the top of the list so an incoming response has less work to do in + * order to find the transaction. + * + * @param clientTransaction + * -- client transaction to add to the set. + */ + public void addTransaction(SIPClientTransaction clientTransaction) { + if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + stackLogger.logDebug("added transaction " + clientTransaction); + addTransactionHash(clientTransaction); - /** - * Set the thread pool size for processing incoming UDP messages. Limit the - * total number of threads for processing udp messages. - * - * @param size - * -- the thread pool size. - * - */ - public void setThreadPoolSize(int size) { - this.threadPoolSize = size; - } + } - /** - * Set the max # of simultaneously handled TCP connections. - * - * @param nconnections - * -- the number of connections to handle. - */ - public void setMaxConnections(int nconnections) { - this.maxConnections = nconnections; - } + /** + * Remove transaction. This actually gets the tx out of the search + * structures which the stack keeps around. When the tx + */ + public void removeTransaction(SIPTransaction sipTransaction) { + if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + stackLogger.logDebug("Removing Transaction = " + + sipTransaction.getTransactionId() + " transaction = " + + sipTransaction); + } + if (sipTransaction instanceof SIPServerTransaction) { + if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + stackLogger.logStackTrace(); + String key = sipTransaction.getTransactionId(); + Object removed = serverTransactionTable.remove(key); + String method = sipTransaction.getMethod(); + this + .removePendingTransaction((SIPServerTransaction) sipTransaction); + this + .removeTransactionPendingAck((SIPServerTransaction) sipTransaction); + if (method.equalsIgnoreCase(Request.INVITE)) { + this + .removeFromMergeTable((SIPServerTransaction) sipTransaction); + } + // Send a notification to the listener. + SipProviderImpl sipProvider = (SipProviderImpl) sipTransaction + .getSipProvider(); + if (removed != null + && sipTransaction.testAndSetTransactionTerminatedEvent()) { + TransactionTerminatedEvent event = new TransactionTerminatedEvent( + sipProvider, (ServerTransaction) sipTransaction); - /** - * Get the default route string. - * - * @param sipRequest - * is the request for which we want to compute the next hop. - * @throws SipException - */ - public Hop getNextHop(SIPRequest sipRequest) throws SipException { - if (this.useRouterForAll) { - // Use custom router to route all messages. - if (router != null) - return router.getNextHop(sipRequest); - else - return null; - } else { - // Also non-SIP request containing Route headers goes to the default - // router - if (sipRequest.getRequestURI().isSipURI() - || sipRequest.getRouteHeaders() != null) { - return defaultRouter.getNextHop(sipRequest); - } else if (router != null) { - return router.getNextHop(sipRequest); - } else - return null; - } - } + sipProvider.handleEvent(event, sipTransaction); - /** - * Set the descriptive name of the stack. - * - * @param stackName - * -- descriptive name of the stack. - */ - public void setStackName(String stackName) { - this.stackName = stackName; - } + } + } else { + + String key = sipTransaction.getTransactionId(); + Object removed = clientTransactionTable.remove(key); + + if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + stackLogger.logDebug("REMOVED client tx " + removed + " KEY = " + + key); + if (removed != null) { + SIPClientTransaction clientTx = (SIPClientTransaction) removed; + if (clientTx.getMethod().equals(Request.INVITE) + && this.maxForkTime != 0) { + RemoveForkedTransactionTimerTask ttask = new RemoveForkedTransactionTimerTask( + clientTx); + this.timer.schedule(ttask, this.maxForkTime * 1000); + } + } + } + // Send a notification to the listener. + if (removed != null + && sipTransaction.testAndSetTransactionTerminatedEvent()) { + SipProviderImpl sipProvider = (SipProviderImpl) sipTransaction + .getSipProvider(); + TransactionTerminatedEvent event = new TransactionTerminatedEvent( + sipProvider, (ClientTransaction) sipTransaction); + sipProvider.handleEvent(event, sipTransaction); + } + ((SIPClientTransaction)sipTransaction).stopExpiresTimer(); - /** - * Set my address. - * - * @param stackAddress - * -- A string containing the stack address. - */ - protected void setHostAddress(String stackAddress) - throws UnknownHostException { - if (stackAddress.indexOf(':') != stackAddress.lastIndexOf(':') - && stackAddress.trim().charAt(0) != '[') - this.stackAddress = '[' + stackAddress + ']'; - else - this.stackAddress = stackAddress; - this.stackInetAddress = InetAddress.getByName(stackAddress); - } + } + } - /** - * Get my address. - * - * @return hostAddress - my host address or null if no host address is - * defined. - * @deprecated - */ - public String getHostAddress() { - - // JvB: for 1.2 this may return null... - return this.stackAddress; - } + /** + * Add a new server transaction to the set of existing transactions. Add it + * to the top of the list so an incoming ack has less work to do in order to + * find the transaction. + * + * @param serverTransaction + * -- server transaction to add to the set. + */ + public void addTransaction(SIPServerTransaction serverTransaction) + throws IOException { + if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + stackLogger.logDebug("added transaction " + serverTransaction); + serverTransaction.map(); + + addTransactionHash(serverTransaction); - /** - * Set the router algorithm. This is meant for routing messages out of - * dialog or for non-sip uri's. - * - * @param router - * A class that implements the Router interface. - */ - protected void setRouter(Router router) { - this.router = router; - } + } - /** - * Get the router algorithm. - * - * @return Router router - */ - public Router getRouter(SIPRequest request) { - if (request.getRequestLine() == null) { - return this.defaultRouter; - } else if (this.useRouterForAll) { - return this.router; - } else { - if (request.getRequestURI().getScheme().equals("sip") - || request.getRequestURI().getScheme().equals("sips")) { - return this.defaultRouter; - } else { - if (this.router != null) - return this.router; - else - return defaultRouter; - } - } - } + /** + * Hash table for quick lookup of transactions. Here we wait for room if + * needed. + */ + private void addTransactionHash(SIPTransaction sipTransaction) { + SIPRequest sipRequest = sipTransaction.getOriginalRequest(); + if (sipTransaction instanceof SIPClientTransaction) { + if (!this.unlimitedClientTransactionTableSize) { + if (this.activeClientTransactionCount.get() > clientTransactionTableHiwaterMark) { + try { + synchronized (this.clientTransactionTable) { + this.clientTransactionTable.wait(); + this.activeClientTransactionCount.incrementAndGet(); + } + + } catch (Exception ex) { + if (stackLogger.isLoggingEnabled()) { + stackLogger.logError( + "Exception occured while waiting for room", + ex); + } + + } + } + } else { + this.activeClientTransactionCount.incrementAndGet(); + } + String key = sipRequest.getTransactionId(); + clientTransactionTable.put(key, + (SIPClientTransaction) sipTransaction); - /* - * (non-Javadoc) - * - * @see javax.sip.SipStack#getRouter() - */ - public Router getRouter() { - return this.router; - } + if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + stackLogger + .logDebug(" putTransactionHash : " + " key = " + key); + } + } else { + String key = sipRequest.getTransactionId(); - /** - * return the status of the toExit flag. - * - * @return true if the stack object is alive and false otherwise. - */ - public boolean isAlive() { - return !toExit; - } + if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + stackLogger + .logDebug(" putTransactionHash : " + " key = " + key); + } + serverTransactionTable.put(key, + (SIPServerTransaction) sipTransaction); - /** - * Adds a new MessageProcessor to the list of running processors for this - * SIPStack and starts it. You can use this method for dynamic stack - * configuration. - */ - protected void addMessageProcessor(MessageProcessor newMessageProcessor) - throws IOException { - // Suggested changes by Jeyashankher, jai@lucent.com - // newMessageProcessor.start() can fail - // because a local port is not available - // This throws an IOException. - // We should not add the message processor to the - // local list of processors unless the start() - // call is successful. - // newMessageProcessor.start(); - messageProcessors.add(newMessageProcessor); + } + } - } + /** + * This method is called when a client tx transitions to the Completed or + * Terminated state. + * + */ + protected void decrementActiveClientTransactionCount() { - /** - * Removes a MessageProcessor from this SIPStack. - * - * @param oldMessageProcessor - */ - protected void removeMessageProcessor(MessageProcessor oldMessageProcessor) { - if (messageProcessors.remove(oldMessageProcessor)) { - oldMessageProcessor.stop(); - } + if (this.activeClientTransactionCount.decrementAndGet() <= this.clientTransactionTableLowaterMark + && !this.unlimitedClientTransactionTableSize) { + synchronized (this.clientTransactionTable) { - } + clientTransactionTable.notify(); - /** - * Gets an array of running MessageProcessors on this SIPStack. - * Acknowledgement: Jeff Keyser suggested that applications should have - * access to the running message processors and contributed this code. - * - * @return an array of running message processors. - */ - protected MessageProcessor[] getMessageProcessors() { - return (MessageProcessor[]) messageProcessors - .toArray(new MessageProcessor[0]); + } + } + } - } + /** + * Remove the transaction from transaction hash. + */ + protected void removeTransactionHash(SIPTransaction sipTransaction) { + SIPRequest sipRequest = sipTransaction.getOriginalRequest(); + if (sipRequest == null) + return; + if (sipTransaction instanceof SIPClientTransaction) { + String key = sipTransaction.getTransactionId(); + if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + stackLogger.logStackTrace(); + stackLogger.logDebug("removing client Tx : " + key); + } + clientTransactionTable.remove(key); - /** - * Creates the equivalent of a JAIN listening point and attaches to the - * stack. - * - * @param ipAddress - * -- ip address for the listening point. - * @param port - * -- port for the listening point. - * @param transport - * -- transport for the listening point. - */ - protected MessageProcessor createMessageProcessor(InetAddress ipAddress, - int port, String transport) throws java.io.IOException { - MessageProcessor newMessageProcessor = messageProcessorFactory.createMessageProcessor(this, ipAddress, port, transport); - this.addMessageProcessor(newMessageProcessor); - return newMessageProcessor; - } + } else if (sipTransaction instanceof SIPServerTransaction) { + String key = sipTransaction.getTransactionId(); + serverTransactionTable.remove(key); + if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + stackLogger.logDebug("removing server Tx : " + key); + } + } + } - /** - * Set the message factory. - * - * @param messageFactory - * -- messageFactory to set. - */ - protected void setMessageFactory(StackMessageFactory messageFactory) { - this.sipMessageFactory = messageFactory; - } + /** + * Invoked when an error has ocurred with a transaction. + * + * @param transactionErrorEvent + * Error event. + */ + public synchronized void transactionErrorEvent( + SIPTransactionErrorEvent transactionErrorEvent) { + SIPTransaction transaction = (SIPTransaction) transactionErrorEvent + .getSource(); + + if (transactionErrorEvent.getErrorID() == SIPTransactionErrorEvent.TRANSPORT_ERROR) { + // Kill scanning of this transaction. + transaction.setState(SIPTransaction.TERMINATED_STATE); + if (transaction instanceof SIPServerTransaction) { + // let the reaper get him + ((SIPServerTransaction) transaction).collectionTime = 0; + } + transaction.disableTimeoutTimer(); + transaction.disableRetransmissionTimer(); + // Send a IO Exception to the Listener. + } + } - /** - * Creates a new MessageChannel for a given Hop. - * - * @param sourceIpAddress - * - Ip address of the source of this message. - * - * @param sourcePort - * - source port of the message channel to be created. - * - * @param nextHop - * Hop to create a MessageChannel to. - * - * @return A MessageChannel to the specified Hop, or null if no - * MessageProcessors support contacting that Hop. - * - * @throws UnknownHostException - * If the host in the Hop doesn't exist. - */ - public MessageChannel createRawMessageChannel(String sourceIpAddress, - int sourcePort, Hop nextHop) throws UnknownHostException { - Host targetHost; - HostPort targetHostPort; - Iterator processorIterator; - MessageProcessor nextProcessor; - MessageChannel newChannel; - - // Create the host/port of the target hop - targetHost = new Host(); - targetHost.setHostname(nextHop.getHost()); - targetHostPort = new HostPort(); - targetHostPort.setHost(targetHost); - targetHostPort.setPort(nextHop.getPort()); - - // Search each processor for the correct transport - newChannel = null; - processorIterator = messageProcessors.iterator(); - while (processorIterator.hasNext() && newChannel == null) { - nextProcessor = (MessageProcessor) processorIterator.next(); - // If a processor that supports the correct - // transport is found, - if (nextHop.getTransport().equalsIgnoreCase( - nextProcessor.getTransport()) - && sourceIpAddress.equals(nextProcessor.getIpAddress() - .getHostAddress()) - && sourcePort == nextProcessor.getPort()) { - try { - // Create a channel to the target - // host/port - newChannel = nextProcessor - .createMessageChannel(targetHostPort); - } catch (UnknownHostException ex) { - if (logger.isLoggingEnabled()) - logger.logException(ex); - throw ex; - } catch (IOException e) { - if (logger.isLoggingEnabled()) - logger.logException(e); - // Ignore channel creation error - - // try next processor - } - } - } - - if(newChannel == null) { - if(logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("newChanne is null, messageProcessors.size = " + messageProcessors.size()); - processorIterator = messageProcessors.iterator(); - while (processorIterator.hasNext() && newChannel == null) { - nextProcessor = (MessageProcessor) processorIterator.next(); - logger.logDebug("nextProcessor:" + nextProcessor + "| transport = " + - nextProcessor.getTransport() + " ipAddress=" + - nextProcessor.getIpAddress() + " port=" + - nextProcessor.getPort()); - } - logger.logDebug("More info on newChannel=null"); - logger.logDebug("nextHop=" + nextHop + " sourceIp=" + sourceIpAddress + - " sourcePort=" + sourcePort + " targetHostPort=" + targetHostPort); - } - } - // Return the newly-created channel - return newChannel; - } + /* + * (non-Javadoc) + * + * @see + * gov.nist.javax.sip.stack.SIPDialogEventListener#dialogErrorEvent(gov. + * nist.javax.sip.stack.SIPDialogErrorEvent) + */ + public synchronized void dialogErrorEvent( + SIPDialogErrorEvent dialogErrorEvent) { + SIPDialog sipDialog = (SIPDialog) dialogErrorEvent.getSource(); + SipListener sipListener = ((SipStackImpl) this).getSipListener(); + // if the app is not implementing the SipListenerExt interface we delete + // the dialog to avoid leaks + if (sipDialog != null && !(sipListener instanceof SipListenerExt)) { + sipDialog.delete(); + } + } - /** - * Return true if a given event can result in a forked subscription. The - * stack is configured with a set of event names that can result in forked - * subscriptions. - * - * @param ename - * -- event name to check. - * - */ - public boolean isEventForked(String ename) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("isEventForked: " + ename + " returning " - + this.forkedEvents.contains(ename)); - } - return this.forkedEvents.contains(ename); - } + /** + * Stop stack. Clear all the timer stuff. Make the stack close all accept + * connections and return. This is useful if you want to start/stop the + * stack several times from your application. Caution : use of this function + * could cause peculiar bugs as messages are prcessed asynchronously by the + * stack. + */ + public void stopStack() { + // Prevent NPE on two concurrent stops + if (this.timer != null) + this.timer.cancel(); + + // JvB: set it to null, SIPDialog tries to schedule things after stop + timer = null; + this.pendingTransactions.clear(); + this.toExit = true; + synchronized (this) { + this.notifyAll(); + } + synchronized (this.clientTransactionTable) { + clientTransactionTable.notifyAll(); + } - /** - * get the address resolver interface. - * - * @return -- the registered address resolver. - */ - public AddressResolver getAddressResolver() { - return this.addressResolver; - } + synchronized (this.messageProcessors) { + // Threads must periodically check this flag. + MessageProcessor[] processorList; + processorList = getMessageProcessors(); + for (int processorIndex = 0; processorIndex < processorList.length; processorIndex++) { + removeMessageProcessor(processorList[processorIndex]); + } + this.ioHandler.closeAll(); + // Let the processing complete. - /** - * Set the address resolution interface - * - * @param addressResolver - * -- the address resolver to set. - */ - public void setAddressResolver(AddressResolver addressResolver) { - this.addressResolver = addressResolver; - } + } + try { - /** - * Set the logger factory. - * - * @param logRecordFactory - * -- the log record factory to set. - */ - public void setLogRecordFactory(LogRecordFactory logRecordFactory) { - this.logRecordFactory = logRecordFactory; - } + Thread.sleep(1000); - /** - * get the thread auditor object - * - * @return -- the thread auditor of the stack - */ - public ThreadAuditor getThreadAuditor() { - return this.threadAuditor; - } + } catch (InterruptedException ex) { + } + this.clientTransactionTable.clear(); + this.serverTransactionTable.clear(); - // / - // / Stack Audit methods - // / - - /** - * Audits the SIP Stack for leaks - * - * @return Audit report, null if no leaks were found - */ - public String auditStack(Set activeCallIDs, long leakedDialogTimer, - long leakedTransactionTimer) { - String auditReport = null; - String leakedDialogs = auditDialogs(activeCallIDs, leakedDialogTimer); - String leakedServerTransactions = auditTransactions( - serverTransactionTable, leakedTransactionTimer); - String leakedClientTransactions = auditTransactions( - clientTransactionTable, leakedTransactionTimer); - if (leakedDialogs != null || leakedServerTransactions != null - || leakedClientTransactions != null) { - auditReport = "SIP Stack Audit:\n" - + (leakedDialogs != null ? leakedDialogs : "") - + (leakedServerTransactions != null ? leakedServerTransactions - : "") - + (leakedClientTransactions != null ? leakedClientTransactions - : ""); - } - return auditReport; - } + this.dialogTable.clear(); + this.serverLogger.closeLogFile(); - /** - * Audits SIP dialogs for leaks - Compares the dialogs in the dialogTable - * with a list of Call IDs passed by the application. - Dialogs that are not - * known by the application are leak suspects. - Kill the dialogs that are - * still around after the timer specified. - * - * @return Audit report, null if no dialog leaks were found - */ - private String auditDialogs(Set activeCallIDs, long leakedDialogTimer) { - String auditReport = " Leaked dialogs:\n"; - int leakedDialogs = 0; - long currentTime = System.currentTimeMillis(); - - // Make a shallow copy of the dialog list. - // This copy will remain intact as leaked dialogs are removed by the - // stack. - LinkedList dialogs; - synchronized (dialogTable) { - dialogs = new LinkedList(dialogTable.values()); - } - - // Iterate through the dialogDialog, get the callID of each dialog and - // check if it's in the - // list of active calls passed by the application. If it isn't, start - // the timer on it. - // If the timer has expired, kill the dialog. - Iterator it = dialogs.iterator(); - while (it.hasNext()) { - // Get the next dialog - SIPDialog itDialog = (SIPDialog) it.next(); - - // Get the call id associated with this dialog - CallIdHeader callIdHeader = (itDialog != null ? itDialog - .getCallId() : null); - String callID = (callIdHeader != null ? callIdHeader.getCallId() - : null); - - // Check if the application knows about this call id - if (itDialog != null && callID != null - && !activeCallIDs.contains(callID)) { - // Application doesn't know anything about this dialog... - if (itDialog.auditTag == 0) { - // Mark this dialog as suspect - itDialog.auditTag = currentTime; - } else { - // We already audited this dialog before. Check if his - // time's up. - if (currentTime - itDialog.auditTag >= leakedDialogTimer) { - // Leaked dialog found - leakedDialogs++; - - // Generate report - DialogState dialogState = itDialog.getState(); - String dialogReport = "dialog id: " - + itDialog.getDialogId() - + ", dialog state: " - + (dialogState != null ? dialogState.toString() - : "null"); - auditReport += " " + dialogReport + "\n"; - - // Kill it - itDialog.setState(SIPDialog.TERMINATED_STATE); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("auditDialogs: leaked " - + dialogReport); - } - } - } - } - - // Return final report - if (leakedDialogs > 0) { - auditReport += " Total: " + Integer.toString(leakedDialogs) - + " leaked dialogs detected and removed.\n"; - } else { - auditReport = null; - } - return auditReport; - } + } - /** - * Audits SIP transactions for leaks - * - * @return Audit report, null if no transaction leaks were found - */ - private String auditTransactions(ConcurrentHashMap transactionsMap, - long a_nLeakedTransactionTimer) { - String auditReport = " Leaked transactions:\n"; - int leakedTransactions = 0; - long currentTime = System.currentTimeMillis(); - - // Make a shallow copy of the transaction list. - // This copy will remain intact as leaked transactions are removed by - // the stack. - LinkedList transactionsList = new LinkedList(transactionsMap.values()); - - // Iterate through our copy - Iterator it = transactionsList.iterator(); - while (it.hasNext()) { - SIPTransaction sipTransaction = (SIPTransaction) it.next(); - if (sipTransaction != null) { - if (sipTransaction.auditTag == 0) { - // First time we see this transaction. Mark it as audited. - sipTransaction.auditTag = currentTime; - } else { - // We've seen this transaction before. Check if his time's - // up. - if (currentTime - sipTransaction.auditTag >= a_nLeakedTransactionTimer) { - // Leaked transaction found - leakedTransactions++; - - // Generate some report - TransactionState transactionState = sipTransaction - .getState(); - SIPRequest origRequest = sipTransaction - .getOriginalRequest(); - String origRequestMethod = (origRequest != null ? origRequest - .getMethod() - : null); - String transactionReport = sipTransaction.getClass() - .getName() - + ", state: " - + (transactionState != null ? transactionState - .toString() : "null") - + ", OR: " - + (origRequestMethod != null ? origRequestMethod - : "null"); - auditReport += " " + transactionReport + "\n"; - - // Kill it - removeTransaction(sipTransaction); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("auditTransactions: leaked " - + transactionReport); - } - } - } - } - - // Return final report - if (leakedTransactions > 0) { - auditReport += " Total: " + Integer.toString(leakedTransactions) - + " leaked transactions detected and removed.\n"; - } else { - auditReport = null; - } - return auditReport; - } + /** + * Put a transaction in the pending transaction list. This is to avoid a + * race condition when a duplicate may arrive when the application is + * deciding whether to create a transaction or not. + */ + public void putPendingTransaction(SIPServerTransaction tr) { + if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + stackLogger.logDebug("putPendingTransaction: " + tr); - public void setNon2XXAckPassedToListener(boolean passToListener) { - this.non2XXAckPassedToListener = passToListener; - } + this.pendingTransactions.put(tr.getTransactionId(), tr); - /** - * @return the non2XXAckPassedToListener - */ - public boolean isNon2XXAckPassedToListener() { - return non2XXAckPassedToListener; - } + } - /** - * Get the count of client transactions that is not in the completed or - * terminated state. - * - * @return the activeClientTransactionCount - */ - public int getActiveClientTransactionCount() { - return activeClientTransactionCount.get(); - } + /** + * Return the network layer (i.e. the interface for socket creation or the + * socket factory for the stack). + * + * @return -- the registered Network Layer. + */ + public NetworkLayer getNetworkLayer() { + if (networkLayer == null) { + return DefaultNetworkLayer.SINGLETON; + } else { + return networkLayer; + } + } - public boolean isRfc2543Supported() { + /** + * Return true if logging is enabled for this stack. + * + * @return true if logging is enabled for this stack instance. + */ + public boolean isLoggingEnabled() { + return this.stackLogger == null ? false : this.stackLogger + .isLoggingEnabled(); + } + + public boolean isLoggingEnabled( int level ) { + return this.stackLogger == null ? false + : this.stackLogger.isLoggingEnabled( level ); + } + + /** + * Get the logger. + * + * @return --the logger for the sip stack. Each stack has its own logger + * instance. + */ + public StackLogger getStackLogger() { + return this.stackLogger; + } - return this.rfc2543Supported; - } + /** + * Server log is the place where we log messages for the signaling trace + * viewer. + * + * @return -- the log file where messages are logged for viewing by the + * trace viewer. + */ + public ServerLogger getServerLogger() { + return this.serverLogger; + } - public boolean isCancelClientTransactionChecked() { - return this.cancelClientTransactionChecked; - } + /** + * Maximum size of a single TCP message. Limiting the size of a single TCP + * message prevents flooding attacks. + * + * @return the size of a single TCP message. + */ + public int getMaxMessageSize() { + return this.maxMessageSize; + } - public boolean isRemoteTagReassignmentAllowed() { - return this.remoteTagReassignmentAllowed; - } + /** + * Set the flag that instructs the stack to only start a single thread for + * sequentially processing incoming udp messages (thus serializing the + * processing). Same as setting thread pool size to 1. + */ + public void setSingleThreaded() { + this.threadPoolSize = 1; + } - /** - * This method is slated for addition to the next spec revision. - * - * - * @return -- the collection of dialogs that is being managed by the stack. - */ - public Collection getDialogs() { - HashSet dialogs = new HashSet(); - dialogs.addAll(this.dialogTable.values()); - dialogs.addAll(this.earlyDialogTable.values()); - return dialogs; - } + /** + * Set the thread pool size for processing incoming UDP messages. Limit the + * total number of threads for processing udp messages. + * + * @param size + * -- the thread pool size. + * + */ + public void setThreadPoolSize(int size) { + this.threadPoolSize = size; + } - /** - * - * @return -- the collection of dialogs matching the state that is being - * managed by the stack. - */ - public Collection getDialogs(DialogState state) { - HashSet matchingDialogs = new HashSet(); - if (DialogState.EARLY.equals(state)) { - matchingDialogs.addAll(this.earlyDialogTable.values()); - } else { - Collection dialogs = dialogTable.values(); - for (SIPDialog dialog : dialogs) { - if (dialog.getState() != null - && dialog.getState().equals(state)) { - matchingDialogs.add(dialog); - } - } - } - return matchingDialogs; - } + /** + * If all calls are occurring on a single TCP socket then the stack would process them in single thread. + * This property allows immediately after parsing to split the load into many threads which increases + * the performance significantly. If set to 0 then we just use the old model with single thread. + * + * @return + */ + public int getTcpPostParsingThreadPoolSize() { + return tcpPostParsingThreadPoolSize; + } - /** - * Get the Replaced Dialog from the stack. - * - * @param replacesHeader - * -- the header that references the dialog being replaced. - */ - public Dialog getReplacesDialog(ReplacesHeader replacesHeader) { - String cid = replacesHeader.getCallId(); - String fromTag = replacesHeader.getFromTag(); - String toTag = replacesHeader.getToTag(); - - for ( SIPDialog dialog : this.dialogTable.values() ) { - if ( dialog.getCallId().getCallId().equals(cid) - && fromTag.equalsIgnoreCase(dialog.lastResponseFromTag) - && toTag.equalsIgnoreCase(dialog.lastResponseToTag)) { - return dialog; - } - } - - StringBuilder dialogId = new StringBuilder(cid); - - // retval.append(COLON).append(to.getUserAtHostPort()); - if (toTag != null) { - dialogId.append(":"); - dialogId.append(toTag); - } - // retval.append(COLON).append(from.getUserAtHostPort()); - if (fromTag != null) { - dialogId.append(":"); - dialogId.append(fromTag); - } - String did = dialogId.toString().toLowerCase(); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("Looking for dialog " + did); - /* - * Check if we can find this dialog in our dialog table. - */ - Dialog replacesDialog = this.dialogTable.get(did); - /* - * This could be a forked dialog. Search for it. - */ - if ( replacesDialog == null ) { - for (SIPClientTransaction ctx : this.clientTransactionTable - .values()) { - if ( ctx.getDialog(did) != null ) { - replacesDialog = ctx.getDialog(did); - break; - } - } - } - - return replacesDialog; - } + /** + * If all calls are occurring on a single TCP socket then the stack would process them in single thread. + * This property allows immediately after parsing to split the load into many threads which increases + * the performance significantly. If set to 0 then we just use the old model with single thread. + * + * @param tcpPostParsingThreadPoolSize + */ + public void setTcpPostParsingThreadPoolSize(int tcpPostParsingThreadPoolSize) { + this.tcpPostParsingThreadPoolSize = tcpPostParsingThreadPoolSize; + } - /** - * Get the Join Dialog from the stack. - * - * @param joinHeader - * -- the header that references the dialog being joined. - */ - public Dialog getJoinDialog(JoinHeader joinHeader) { - String cid = joinHeader.getCallId(); - String fromTag = joinHeader.getFromTag(); - String toTag = joinHeader.getToTag(); - - StringBuilder retval = new StringBuilder(cid); - - // retval.append(COLON).append(to.getUserAtHostPort()); - if (toTag != null) { - retval.append(":"); - retval.append(toTag); - } - // retval.append(COLON).append(from.getUserAtHostPort()); - if (fromTag != null) { - retval.append(":"); - retval.append(fromTag); - } - return this.dialogTable.get(retval.toString().toLowerCase()); - } + /** + * Set the max # of simultaneously handled TCP connections. + * + * @param nconnections + * -- the number of connections to handle. + */ + public void setMaxConnections(int nconnections) { + this.maxConnections = nconnections; + } - /** - * @param timer - * the timer to set - */ - public void setTimer(SipTimer timer) { - this.timer = timer; - } + /** + * Get the default route string. + * + * @param sipRequest + * is the request for which we want to compute the next hop. + * @throws SipException + */ + public Hop getNextHop(SIPRequest sipRequest) throws SipException { + if (this.useRouterForAll) { + // Use custom router to route all messages. + if (router != null) + return router.getNextHop(sipRequest); + else + return null; + } else { + // Also non-SIP request containing Route headers goes to the default + // router + if (sipRequest.getRequestURI().isSipURI() + || sipRequest.getRouteHeaders() != null) { + return defaultRouter.getNextHop(sipRequest); + } else if (router != null) { + return router.getNextHop(sipRequest); + } else + return null; + } + } - /** - * @return the timer - */ - public SipTimer getTimer() throws IllegalStateException { -// if(timer == null) -// throw new IllegalStateException("Stack has been stopped, no further tasks can be scheduled."); - return timer; - } + /** + * Set the descriptive name of the stack. + * + * @param stackName + * -- descriptive name of the stack. + */ + public void setStackName(String stackName) { + this.stackName = stackName; + } + /** + * Set my address. + * + * @param stackAddress + * -- A string containing the stack address. + */ + protected void setHostAddress(String stackAddress) + throws UnknownHostException { + if (stackAddress.indexOf(':') != stackAddress.lastIndexOf(':') + && stackAddress.trim().charAt(0) != '[') + this.stackAddress = '[' + stackAddress + ']'; + else + this.stackAddress = stackAddress; + this.stackInetAddress = InetAddress.getByName(stackAddress); + } - /** - * Size of the receive UDP buffer. This property affects performance under - * load. Bigger buffer is better under load. - * - * @return - */ - public int getReceiveUdpBufferSize() { - return receiveUdpBufferSize; - } + /** + * Get my address. + * + * @return hostAddress - my host address or null if no host address is + * defined. + * @deprecated + */ + public String getHostAddress() { + + // JvB: for 1.2 this may return null... + return this.stackAddress; + } - /** - * Size of the receive UDP buffer. This property affects performance under - * load. Bigger buffer is better under load. - * - * @return - */ - public void setReceiveUdpBufferSize(int receiveUdpBufferSize) { - this.receiveUdpBufferSize = receiveUdpBufferSize; - } + /** + * Set the router algorithm. This is meant for routing messages out of + * dialog or for non-sip uri's. + * + * @param router + * A class that implements the Router interface. + */ + protected void setRouter(Router router) { + this.router = router; + } - /** - * Size of the send UDP buffer. This property affects performance under - * load. Bigger buffer is better under load. - * - * @return - */ - public int getSendUdpBufferSize() { - return sendUdpBufferSize; - } + /** + * Get the router algorithm. + * + * @return Router router + */ + public Router getRouter(SIPRequest request) { + if (request.getRequestLine() == null) { + return this.defaultRouter; + } else if (this.useRouterForAll) { + return this.router; + } else { + if (request.getRequestURI().getScheme().equals("sip") + || request.getRequestURI().getScheme().equals("sips")) { + return this.defaultRouter; + } else { + if (this.router != null) + return this.router; + else + return defaultRouter; + } + } + } - /** - * Size of the send UDP buffer. This property affects performance under - * load. Bigger buffer is better under load. - * - * @return - */ - public void setSendUdpBufferSize(int sendUdpBufferSize) { - this.sendUdpBufferSize = sendUdpBufferSize; - } + /* + * (non-Javadoc) + * + * @see javax.sip.SipStack#getRouter() + */ + public Router getRouter() { + return this.router; + } - /** - * Flag that reqests checking of branch IDs on responses. - * - * @return - */ - public boolean checkBranchId() { - return this.checkBranchId; - } - - /** - * @param logStackTraceOnMessageSend - * the logStackTraceOnMessageSend to set - */ - public void setLogStackTraceOnMessageSend(boolean logStackTraceOnMessageSend) { - this.logStackTraceOnMessageSend = logStackTraceOnMessageSend; - } + /** + * return the status of the toExit flag. + * + * @return true if the stack object is alive and false otherwise. + */ + public boolean isAlive() { + return !toExit; + } - /** - * @return the logStackTraceOnMessageSend - */ - public boolean isLogStackTraceOnMessageSend() { - return logStackTraceOnMessageSend; - } + /** + * Adds a new MessageProcessor to the list of running processors for this + * SIPStack and starts it. You can use this method for dynamic stack + * configuration. + */ + protected void addMessageProcessor(MessageProcessor newMessageProcessor) + throws IOException { + synchronized (messageProcessors) { + // Suggested changes by Jeyashankher, jai@lucent.com + // newMessageProcessor.start() can fail + // because a local port is not available + // This throws an IOException. + // We should not add the message processor to the + // local list of processors unless the start() + // call is successful. + // newMessageProcessor.start(); + messageProcessors.add(newMessageProcessor); - public void setDeliverDialogTerminatedEventForNullDialog() { - this.isDialogTerminatedEventDeliveredForNullDialog = true; - } + } + } - public void addForkedClientTransaction( - SIPClientTransaction clientTransaction) { - String forkId = ((SIPRequest)clientTransaction.getRequest()).getForkId(); - clientTransaction.setForkId(forkId); - this.forkedClientTransactionTable.put(forkId, clientTransaction); - } + /** + * Removes a MessageProcessor from this SIPStack. + * + * @param oldMessageProcessor + */ + protected void removeMessageProcessor(MessageProcessor oldMessageProcessor) { + synchronized (messageProcessors) { + if (messageProcessors.remove(oldMessageProcessor)) { + oldMessageProcessor.stop(); + } + } + } - public SIPClientTransaction getForkedTransaction(String transactionId) { - return this.forkedClientTransactionTable.get(transactionId); - } + /** + * Gets an array of running MessageProcessors on this SIPStack. + * Acknowledgement: Jeff Keyser suggested that applications should have + * access to the running message processors and contributed this code. + * + * @return an array of running message processors. + */ + protected MessageProcessor[] getMessageProcessors() { + synchronized (messageProcessors) { + return (MessageProcessor[]) messageProcessors + .toArray(new MessageProcessor[0]); + } + } - /** - * @param deliverUnsolicitedNotify - * the deliverUnsolicitedNotify to set - */ - public void setDeliverUnsolicitedNotify(boolean deliverUnsolicitedNotify) { - this.deliverUnsolicitedNotify = deliverUnsolicitedNotify; - } + /** + * Creates the equivalent of a JAIN listening point and attaches to the + * stack. + * + * @param ipAddress + * -- ip address for the listening point. + * @param port + * -- port for the listening point. + * @param transport + * -- transport for the listening point. + */ + protected MessageProcessor createMessageProcessor(InetAddress ipAddress, + int port, String transport) throws java.io.IOException { + MessageProcessor newMessageProcessor = messageProcessorFactory.createMessageProcessor(this, ipAddress, port, transport); + this.addMessageProcessor(newMessageProcessor); + return newMessageProcessor; + } - /** - * @return the deliverUnsolicitedNotify - */ - public boolean isDeliverUnsolicitedNotify() { - return deliverUnsolicitedNotify; - } + /** + * Set the message factory. + * + * @param messageFactory + * -- messageFactory to set. + */ + protected void setMessageFactory(StackMessageFactory messageFactory) { + this.sipMessageFactory = messageFactory; + } - /** - * @param deliverTerminatedEventForAck - * the deliverTerminatedEventForAck to set - */ - public void setDeliverTerminatedEventForAck( - boolean deliverTerminatedEventForAck) { - this.deliverTerminatedEventForAck = deliverTerminatedEventForAck; - } + /** + * Creates a new MessageChannel for a given Hop. + * + * @param sourceIpAddress + * - Ip address of the source of this message. + * + * @param sourcePort + * - source port of the message channel to be created. + * + * @param nextHop + * Hop to create a MessageChannel to. + * + * @return A MessageChannel to the specified Hop, or null if no + * MessageProcessors support contacting that Hop. + * + * @throws UnknownHostException + * If the host in the Hop doesn't exist. + */ + public MessageChannel createRawMessageChannel(String sourceIpAddress, + int sourcePort, Hop nextHop) throws UnknownHostException { + Host targetHost; + HostPort targetHostPort; + Iterator processorIterator; + MessageProcessor nextProcessor; + MessageChannel newChannel; + + // Create the host/port of the target hop + targetHost = new Host(); + targetHost.setHostname(nextHop.getHost()); + targetHostPort = new HostPort(); + targetHostPort.setHost(targetHost); + targetHostPort.setPort(nextHop.getPort()); + + // Search each processor for the correct transport + newChannel = null; + processorIterator = messageProcessors.iterator(); + while (processorIterator.hasNext() && newChannel == null) { + nextProcessor = (MessageProcessor) processorIterator.next(); + // If a processor that supports the correct + // transport is found, + if (nextHop.getTransport().equalsIgnoreCase( + nextProcessor.getTransport()) + && sourceIpAddress.equals(nextProcessor.getIpAddress() + .getHostAddress()) + && sourcePort == nextProcessor.getPort()) { + try { + // Create a channel to the target + // host/port + newChannel = nextProcessor + .createMessageChannel(targetHostPort); + } catch (UnknownHostException ex) { + if (stackLogger.isLoggingEnabled()) + stackLogger.logException(ex); + throw ex; + } catch (IOException e) { + if (stackLogger.isLoggingEnabled()) + stackLogger.logException(e); + // Ignore channel creation error - + // try next processor + } + } + } + // Return the newly-created channel + return newChannel; + } - /** - * @return the deliverTerminatedEventForAck - */ - public boolean isDeliverTerminatedEventForAck() { - return deliverTerminatedEventForAck; - } + /** + * Return true if a given event can result in a forked subscription. The + * stack is configured with a set of event names that can result in forked + * subscriptions. + * + * @param ename + * -- event name to check. + * + */ + public boolean isEventForked(String ename) { + if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + stackLogger.logDebug("isEventForked: " + ename + " returning " + + this.forkedEvents.contains(ename)); + } + return this.forkedEvents.contains(ename); + } - public long getMinKeepAliveInterval() { - return this.minKeepAliveInterval; - } + /** + * get the address resolver interface. + * + * @return -- the registered address resolver. + */ + public AddressResolver getAddressResolver() { + return this.addressResolver; + } - /** - * @param maxForkTime - * the maxForkTime to set - */ - public void setMaxForkTime(int maxForkTime) { - this.maxForkTime = maxForkTime; - } + /** + * Set the address resolution interface + * + * @param addressResolver + * -- the address resolver to set. + */ + public void setAddressResolver(AddressResolver addressResolver) { + this.addressResolver = addressResolver; + } - /** - * @return the maxForkTime - */ - public int getMaxForkTime() { - return maxForkTime; - } + /** + * Set the logger factory. + * + * @param logRecordFactory + * -- the log record factory to set. + */ + public void setLogRecordFactory(LogRecordFactory logRecordFactory) { + this.logRecordFactory = logRecordFactory; + } - /** - * This is a testing interface. Normally the application does not see - * retransmitted ACK for 200 OK retransmissions. - * - * @return - */ - public boolean isDeliverRetransmittedAckToListener() { - return this.deliverRetransmittedAckToListener; - } + /** + * get the thread auditor object + * + * @return -- the thread auditor of the stack + */ + public ThreadAuditor getThreadAuditor() { + return this.threadAuditor; + } + // / + // / Stack Audit methods + // / + + /** + * Audits the SIP Stack for leaks + * + * @return Audit report, null if no leaks were found + */ + public String auditStack(Set activeCallIDs, long leakedDialogTimer, + long leakedTransactionTimer) { + String auditReport = null; + String leakedDialogs = auditDialogs(activeCallIDs, leakedDialogTimer); + String leakedServerTransactions = auditTransactions( + serverTransactionTable, leakedTransactionTimer); + String leakedClientTransactions = auditTransactions( + clientTransactionTable, leakedTransactionTimer); + if (leakedDialogs != null || leakedServerTransactions != null + || leakedClientTransactions != null) { + auditReport = "SIP Stack Audit:\n" + + (leakedDialogs != null ? leakedDialogs : "") + + (leakedServerTransactions != null ? leakedServerTransactions + : "") + + (leakedClientTransactions != null ? leakedClientTransactions + : ""); + } + return auditReport; + } - /** - * Get the dialog timeout counter. - * - * @return - */ + /** + * Audits SIP dialogs for leaks - Compares the dialogs in the dialogTable + * with a list of Call IDs passed by the application. - Dialogs that are not + * known by the application are leak suspects. - Kill the dialogs that are + * still around after the timer specified. + * + * @return Audit report, null if no dialog leaks were found + */ + private String auditDialogs(Set activeCallIDs, long leakedDialogTimer) { + String auditReport = " Leaked dialogs:\n"; + int leakedDialogs = 0; + long currentTime = System.currentTimeMillis(); + + // Make a shallow copy of the dialog list. + // This copy will remain intact as leaked dialogs are removed by the + // stack. + LinkedList dialogs; + synchronized (dialogTable) { + dialogs = new LinkedList(dialogTable.values()); + } - public int getAckTimeoutFactor() { - if (getSipListener() != null - && getSipListener() instanceof SipListenerExt) { - return dialogTimeoutFactor; - } else { - return 64; - } - } + // Iterate through the dialogDialog, get the callID of each dialog and + // check if it's in the + // list of active calls passed by the application. If it isn't, start + // the timer on it. + // If the timer has expired, kill the dialog. + Iterator it = dialogs.iterator(); + while (it.hasNext()) { + // Get the next dialog + SIPDialog itDialog = (SIPDialog) it.next(); + + // Get the call id associated with this dialog + CallIdHeader callIdHeader = (itDialog != null ? itDialog + .getCallId() : null); + String callID = (callIdHeader != null ? callIdHeader.getCallId() + : null); + + // Check if the application knows about this call id + if (itDialog != null && callID != null + && !activeCallIDs.contains(callID)) { + // Application doesn't know anything about this dialog... + if (itDialog.auditTag == 0) { + // Mark this dialog as suspect + itDialog.auditTag = currentTime; + } else { + // We already audited this dialog before. Check if his + // time's up. + if (currentTime - itDialog.auditTag >= leakedDialogTimer) { + // Leaked dialog found + leakedDialogs++; + + // Generate report + DialogState dialogState = itDialog.getState(); + String dialogReport = "dialog id: " + + itDialog.getDialogId() + + ", dialog state: " + + (dialogState != null ? dialogState.toString() + : "null"); + auditReport += " " + dialogReport + "\n"; + + // Kill it + itDialog.setState(SIPDialog.TERMINATED_STATE); + if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + stackLogger.logDebug("auditDialogs: leaked " + + dialogReport); + } + } + } + } - public abstract SipListener getSipListener(); - - /** - * Executor used to optimize the ReinviteSender Runnable in the sendRequest - * of the SipDialog - */ - public ExecutorService getReinviteExecutor() { - return reinviteExecutor; - } - - /** - * @param messageParserFactory the messageParserFactory to set - */ - public void setMessageParserFactory(MessageParserFactory messageParserFactory) { - this.messageParserFactory = messageParserFactory; - } + // Return final report + if (leakedDialogs > 0) { + auditReport += " Total: " + Integer.toString(leakedDialogs) + + " leaked dialogs detected and removed.\n"; + } else { + auditReport = null; + } + return auditReport; + } - /** - * @return the messageParserFactory - */ - public MessageParserFactory getMessageParserFactory() { - return messageParserFactory; - } + /** + * Audits SIP transactions for leaks + * + * @return Audit report, null if no transaction leaks were found + */ + private String auditTransactions(ConcurrentHashMap transactionsMap, + long a_nLeakedTransactionTimer) { + String auditReport = " Leaked transactions:\n"; + int leakedTransactions = 0; + long currentTime = System.currentTimeMillis(); + + // Make a shallow copy of the transaction list. + // This copy will remain intact as leaked transactions are removed by + // the stack. + LinkedList transactionsList = new LinkedList(transactionsMap.values()); + + // Iterate through our copy + Iterator it = transactionsList.iterator(); + while (it.hasNext()) { + SIPTransaction sipTransaction = (SIPTransaction) it.next(); + if (sipTransaction != null) { + if (sipTransaction.auditTag == 0) { + // First time we see this transaction. Mark it as audited. + sipTransaction.auditTag = currentTime; + } else { + // We've seen this transaction before. Check if his time's + // up. + if (currentTime - sipTransaction.auditTag >= a_nLeakedTransactionTimer) { + // Leaked transaction found + leakedTransactions++; + + // Generate some report + TransactionState transactionState = sipTransaction + .getState(); + SIPRequest origRequest = sipTransaction + .getOriginalRequest(); + String origRequestMethod = (origRequest != null ? origRequest + .getMethod() + : null); + String transactionReport = sipTransaction.getClass() + .getName() + + ", state: " + + (transactionState != null ? transactionState + .toString() : "null") + + ", OR: " + + (origRequestMethod != null ? origRequestMethod + : "null"); + auditReport += " " + transactionReport + "\n"; + + // Kill it + removeTransaction(sipTransaction); + if (isLoggingEnabled(LogWriter.TRACE_DEBUG)) + stackLogger.logDebug("auditTransactions: leaked " + + transactionReport); + } + } + } + } - /** - * @param messageProcessorFactory the messageProcessorFactory to set - */ - public void setMessageProcessorFactory(MessageProcessorFactory messageProcessorFactory) { - this.messageProcessorFactory = messageProcessorFactory; - } + // Return final report + if (leakedTransactions > 0) { + auditReport += " Total: " + Integer.toString(leakedTransactions) + + " leaked transactions detected and removed.\n"; + } else { + auditReport = null; + } + return auditReport; + } - /** - * @return the messageProcessorFactory - */ - public MessageProcessorFactory getMessageProcessorFactory() { - return messageProcessorFactory; - } + public void setNon2XXAckPassedToListener(boolean passToListener) { + this.non2XXAckPassedToListener = passToListener; + } - /** - * @param aggressiveCleanup the aggressiveCleanup to set - */ - public void setAggressiveCleanup(boolean aggressiveCleanup) { - this.aggressiveCleanup = aggressiveCleanup; - } + /** + * @return the non2XXAckPassedToListener + */ + public boolean isNon2XXAckPassedToListener() { + return non2XXAckPassedToListener; + } - /** - * @return the aggressiveCleanup - */ - public boolean isAggressiveCleanup() { - return aggressiveCleanup; - } + /** + * Get the count of client transactions that is not in the completed or + * terminated state. + * + * @return the activeClientTransactionCount + */ + public int getActiveClientTransactionCount() { + return activeClientTransactionCount.get(); + } + public boolean isRfc2543Supported() { + return this.rfc2543Supported; + } - public int getEarlyDialogTimeout() { - return this.earlyDialogTimeout; - } + public boolean isCancelClientTransactionChecked() { + return this.cancelClientTransactionChecked; + } - /** - * @param clientAuth the clientAuth to set - */ - public void setClientAuth(ClientAuthType clientAuth) { - this.clientAuth = clientAuth; - } + public boolean isRemoteTagReassignmentAllowed() { + return this.remoteTagReassignmentAllowed; + } + + /** + * This method is slated for addition to the next spec revision. + * + * + * @return -- the collection of dialogs that is being managed by the stack. + */ + public Collection getDialogs() { + HashSet dialogs = new HashSet(); + dialogs.addAll(this.dialogTable.values()); + dialogs.addAll(this.earlyDialogTable.values()); + return dialogs; + } + + /** + * + * @return -- the collection of dialogs matching the state that is being + * managed by the stack. + */ + public Collection getDialogs(DialogState state) { + HashSet matchingDialogs = new HashSet(); + if (DialogState.EARLY.equals(state)) { + matchingDialogs.addAll(this.earlyDialogTable.values()); + } else { + Collection dialogs = dialogTable.values(); + for (SIPDialog dialog : dialogs) { + if (dialog.getState() != null + && dialog.getState().equals(state)) { + matchingDialogs.add(dialog); + } + } + } + return matchingDialogs; + } + + /** + * Get the Replaced Dialog from the stack. + * + * @param replacesHeader + * -- the header that references the dialog being replaced. + */ + public Dialog getReplacesDialog(ReplacesHeader replacesHeader) { + String cid = replacesHeader.getCallId(); + String fromTag = replacesHeader.getFromTag(); + String toTag = replacesHeader.getToTag(); + + StringBuffer dialogId = new StringBuffer(cid); + + // retval.append(COLON).append(to.getUserAtHostPort()); + if (toTag != null) { + dialogId.append(":"); + dialogId.append(toTag); + } + // retval.append(COLON).append(from.getUserAtHostPort()); + if (fromTag != null) { + dialogId.append(":"); + dialogId.append(fromTag); + } + String did = dialogId.toString().toLowerCase(); + if (stackLogger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + stackLogger.logDebug("Looking for dialog " + did); + /* + * Check if we can find this dialog in our dialog table. + */ + Dialog replacesDialog = this.dialogTable.get(did); + /* + * This could be a forked dialog. Search for it. + */ + if (replacesDialog == null) { + for (SIPClientTransaction ctx : this.clientTransactionTable + .values()) { + if (ctx.getDialog(did) != null) { + replacesDialog = ctx.getDialog(did); + break; + } + } + } + + return replacesDialog; + } + + /** + * Get the Join Dialog from the stack. + * + * @param joinHeader + * -- the header that references the dialog being joined. + */ + public Dialog getJoinDialog(JoinHeader joinHeader) { + String cid = joinHeader.getCallId(); + String fromTag = joinHeader.getFromTag(); + String toTag = joinHeader.getToTag(); + + StringBuffer retval = new StringBuffer(cid); + + // retval.append(COLON).append(to.getUserAtHostPort()); + if (toTag != null) { + retval.append(":"); + retval.append(toTag); + } + // retval.append(COLON).append(from.getUserAtHostPort()); + if (fromTag != null) { + retval.append(":"); + retval.append(fromTag); + } + return this.dialogTable.get(retval.toString().toLowerCase()); + } + + /** + * @param timer + * the timer to set + */ + public void setTimer(Timer timer) { + this.timer = timer; + } + + /** + * @return the timer + */ + public Timer getTimer() { + return timer; + } + + /** + * Size of the receive UDP buffer. This property affects performance under + * load. Bigger buffer is better under load. + * + * @return + */ + public int getReceiveUdpBufferSize() { + return receiveUdpBufferSize; + } + + /** + * Size of the receive UDP buffer. This property affects performance under + * load. Bigger buffer is better under load. + * + * @return + */ + public void setReceiveUdpBufferSize(int receiveUdpBufferSize) { + this.receiveUdpBufferSize = receiveUdpBufferSize; + } + + /** + * Size of the send UDP buffer. This property affects performance under + * load. Bigger buffer is better under load. + * + * @return + */ + public int getSendUdpBufferSize() { + return sendUdpBufferSize; + } + + /** + * Size of the send UDP buffer. This property affects performance under + * load. Bigger buffer is better under load. + * + * @return + */ + public void setSendUdpBufferSize(int sendUdpBufferSize) { + this.sendUdpBufferSize = sendUdpBufferSize; + } + + /** + * @param stackLogger + * the stackLogger to set + */ + public void setStackLogger(StackLogger stackLogger) { + this.stackLogger = stackLogger; + } + + /** + * Flag that reqests checking of branch IDs on responses. + * + * @return + */ + public boolean checkBranchId() { + return this.checkBranchId; + } + + /** + * @param logStackTraceOnMessageSend + * the logStackTraceOnMessageSend to set + */ + public void setLogStackTraceOnMessageSend(boolean logStackTraceOnMessageSend) { + this.logStackTraceOnMessageSend = logStackTraceOnMessageSend; + } + + /** + * @return the logStackTraceOnMessageSend + */ + public boolean isLogStackTraceOnMessageSend() { + return logStackTraceOnMessageSend; + } + + public void setDeliverDialogTerminatedEventForNullDialog() { + this.isDialogTerminatedEventDeliveredForNullDialog = true; + } + + public void addForkedClientTransaction( + SIPClientTransaction clientTransaction) { + this.forkedClientTransactionTable.put(((SIPRequest) clientTransaction + .getRequest()).getForkId(), clientTransaction); + } + + public SIPClientTransaction getForkedTransaction(String transactionId) { + return this.forkedClientTransactionTable.get(transactionId); + } + + /** + * @param deliverUnsolicitedNotify + * the deliverUnsolicitedNotify to set + */ + public void setDeliverUnsolicitedNotify(boolean deliverUnsolicitedNotify) { + this.deliverUnsolicitedNotify = deliverUnsolicitedNotify; + } + + /** + * @return the deliverUnsolicitedNotify + */ + public boolean isDeliverUnsolicitedNotify() { + return deliverUnsolicitedNotify; + } + + /** + * @param deliverTerminatedEventForAck + * the deliverTerminatedEventForAck to set + */ + public void setDeliverTerminatedEventForAck( + boolean deliverTerminatedEventForAck) { + this.deliverTerminatedEventForAck = deliverTerminatedEventForAck; + } + + /** + * @return the deliverTerminatedEventForAck + */ + public boolean isDeliverTerminatedEventForAck() { + return deliverTerminatedEventForAck; + } + + public long getMinKeepAliveInterval() { + return this.minKeepAliveInterval; + } + + /** + * @param maxForkTime + * the maxForkTime to set + */ + public void setMaxForkTime(int maxForkTime) { + this.maxForkTime = maxForkTime; + } + + /** + * @return the maxForkTime + */ + public int getMaxForkTime() { + return maxForkTime; + } + + /** + * This is a testing interface. Normally the application does not see + * retransmitted ACK for 200 OK retransmissions. + * + * @return + */ + public boolean isDeliverRetransmittedAckToListener() { + return this.deliverRetransmittedAckToListener; + } + + /** + * Get the dialog timeout counter. + * + * @return + */ + + public int getAckTimeoutFactor() { + if (getSipListener() != null + && getSipListener() instanceof SipListenerExt) { + return dialogTimeoutFactor; + } else { + return 64; + } + } + + public abstract SipListener getSipListener(); + + /** + * Executor used to optimize the ReinviteSender Runnable in the sendRequest + * of the SipDialog + */ + public ExecutorService getReinviteExecutor() { + return reinviteExecutor; + } + + /** + * @param messageParserFactory the messageParserFactory to set + */ + public void setMessageParserFactory(MessageParserFactory messageParserFactory) { + this.messageParserFactory = messageParserFactory; + } + + /** + * @return the messageParserFactory + */ + public MessageParserFactory getMessageParserFactory() { + return messageParserFactory; + } + + /** + * @param messageProcessorFactory the messageProcessorFactory to set + */ + public void setMessageProcessorFactory(MessageProcessorFactory messageProcessorFactory) { + this.messageProcessorFactory = messageProcessorFactory; + } + + /** + * @return the messageProcessorFactory + */ + public MessageProcessorFactory getMessageProcessorFactory() { + return messageProcessorFactory; + } - /** - * @return the clientAuth - */ - public ClientAuthType getClientAuth() { - return clientAuth; - } } diff --git a/src/gov/nist/javax/sip/stack/ServerLog.java b/src/gov/nist/javax/sip/stack/ServerLog.java index 76a99ce06..8f6831a57 100755 --- a/src/gov/nist/javax/sip/stack/ServerLog.java +++ b/src/gov/nist/javax/sip/stack/ServerLog.java @@ -29,7 +29,6 @@ package gov.nist.javax.sip.stack; -import gov.nist.core.CommonLogger; import gov.nist.core.LogWriter; import gov.nist.core.ServerLogger; import gov.nist.core.StackLogger; @@ -46,12 +45,15 @@ import javax.sip.SipStack; import javax.sip.header.TimeStampHeader; +import org.apache.log4j.Level; +import org.apache.log4j.Logger; + /** * Log file wrapper class. Log messages into the message trace file and also write the log into * the debug file if needed. This class keeps an XML formatted trace around for later access via * RMI. The trace can be viewed with a trace viewer (see tools.traceviewerapp). * - * @version 1.2 $Revision: 1.42 $ $Date: 2010-12-15 11:43:02 $ + * @version 1.2 $Revision: 1.39.2.1 $ $Date: 2010-11-23 19:23:12 $ * * @author M. Ranganathan
    * @@ -104,7 +106,26 @@ private void setProperties(Properties configurationProperties) { if (logLevel != null) { if (logLevel.equals("LOG4J")) { - CommonLogger.useLegacyLogger = false; + // if TRACE_LEVEL property is specified as + // "LOG4J" then, set the traceLevel based on + // the log4j effective log level. + + // check whether a Log4j logger name has been + // specified. if not, use the stack name as the default + // logger name. + Logger logger = Logger.getLogger(configurationProperties.getProperty( + "gov.nist.javax.sip.LOG4J_LOGGER_NAME", this.description)); + Level level = logger.getEffectiveLevel(); + + if (level == Level.OFF) { + this.setTraceLevel(0); + } else if (level.isGreaterOrEqual(Level.DEBUG)) { + this.setTraceLevel(TRACE_DEBUG); + } else if (level.isGreaterOrEqual(Level.INFO)) { + this.setTraceLevel(TRACE_MESSAGES); + } else if (level.isGreaterOrEqual(Level.WARN)) { + this.setTraceLevel(TRACE_EXCEPTION); + } } else { try { int ll; @@ -287,7 +308,7 @@ private void logMessage(String message) { if (printWriter != null) { printWriter.println(logInfo); } - if (sipStack.isLoggingEnabled()) { + if (sipStack.isLoggingEnabled(LogWriter.TRACE_INFO)) { stackLogger.logInfo(logInfo); } @@ -321,7 +342,7 @@ public void logMessage(SIPMessage message, String from, String to, boolean sende if (cid != null) callId = cid.getCallId(); String firstLine = message.getFirstLine().trim(); - String inputText = (logContent ? message.encode() : message.encodeMessage(new StringBuilder()).toString()); + String inputText = (logContent ? message.encode() : message.encodeMessage()); String tid = message.getTransactionId(); TimeStampHeader tsHdr = (TimeStampHeader) message.getHeader(TimeStampHeader.NAME); long tsval = tsHdr == null ? 0 : tsHdr.getTime(); @@ -346,7 +367,7 @@ public void logMessage(SIPMessage message, String from, String to, String status if (cid != null) callId = cid.getCallId(); String firstLine = message.getFirstLine().trim(); - String encoded = (logContent ? message.encode() : message.encodeMessage(new StringBuilder()).toString()); + String encoded = (logContent ? message.encode() : message.encodeMessage()); String tid = message.getTransactionId(); TimeStampHeader tshdr = (TimeStampHeader) message.getHeader(TimeStampHeader.NAME); long tsval = tshdr == null ? 0 : tshdr.getTime(); diff --git a/src/gov/nist/javax/sip/stack/TCPMessageChannel.java b/src/gov/nist/javax/sip/stack/TCPMessageChannel.java index 9214ded27..2a69089bb 100755 --- a/src/gov/nist/javax/sip/stack/TCPMessageChannel.java +++ b/src/gov/nist/javax/sip/stack/TCPMessageChannel.java @@ -1,13 +1,13 @@ /* - * Conditions Of Use - * + * Conditions Of Use + * * This software was developed by employees of the National Institute of * Standards and Technology (NIST), an agency of the Federal Government. * Pursuant to title 15 Untied States Code Section 105, works of NIST * employees are not subject to copyright protection in the United States * and are considered to be in the public domain. As a result, a formal * license is not needed to use the software. - * + * * This software is provided by NIST as a service and is expressly * provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED * OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF @@ -16,48 +16,30 @@ * regarding the use of the software or the results thereof, including but * not limited to the correctness, accuracy, reliability or usefulness of * the software. - * + * * Permission to use this software is contingent upon your acceptance * of the terms of this agreement - * + * * . - * + * */ /****************************************************************************** * Product of NIST/ITL Advanced Networking Technologies Division (ANTD). * ******************************************************************************/ package gov.nist.javax.sip.stack; -import gov.nist.core.CommonLogger; -import gov.nist.core.InternalErrorHandler; -import gov.nist.core.LogWriter; -import gov.nist.core.ServerLogger; -import gov.nist.core.StackLogger; -import gov.nist.javax.sip.header.CSeq; -import gov.nist.javax.sip.header.CallID; -import gov.nist.javax.sip.header.ContentLength; -import gov.nist.javax.sip.header.From; -import gov.nist.javax.sip.header.RequestLine; -import gov.nist.javax.sip.header.StatusLine; -import gov.nist.javax.sip.header.To; -import gov.nist.javax.sip.header.Via; -import gov.nist.javax.sip.header.ViaList; -import gov.nist.javax.sip.message.SIPMessage; -import gov.nist.javax.sip.message.SIPRequest; -import gov.nist.javax.sip.message.SIPResponse; -import gov.nist.javax.sip.parser.Pipeline; -import gov.nist.javax.sip.parser.PipelinedMsgParser; -import gov.nist.javax.sip.parser.SIPMessageListener; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.InetAddress; -import java.net.Socket; +import gov.nist.javax.sip.SipStackImpl; +import gov.nist.javax.sip.header.*; +import gov.nist.javax.sip.message.*; +import gov.nist.javax.sip.parser.*; +import gov.nist.core.*; + +import java.net.*; +import java.io.*; import java.text.ParseException; +import java.util.TimerTask; import javax.sip.address.Hop; -import javax.sip.message.Response; /* * Ahmet Uyar sent in a bug report for TCP operation of the JAIN sipStack. @@ -68,23 +50,22 @@ */ /** - * This is a stack abstraction for TCP connections. This abstracts a stream of - * parsed messages. The SIP sipStack starts this from the main SIPStack class - * for each connection that it accepts. It starts a message parser in its own - * thread and talks to the message parser via a pipe. The message parser calls - * back via the parseError or processMessage functions that are defined as part - * of the SIPMessageListener interface. - * + * This is a stack abstraction for TCP connections. This abstracts a stream of parsed messages. + * The SIP sipStack starts this from the main SIPStack class for each connection that it accepts. + * It starts a message parser in its own thread and talks to the message parser via a pipe. The + * message parser calls back via the parseError or processMessage functions that are defined as + * part of the SIPMessageListener interface. + * * @see gov.nist.javax.sip.parser.PipelinedMsgParser - * - * + * + * * @author M. Ranganathan
    - * - * @version 1.2 $Revision: 1.83 $ $Date: 2010-12-02 22:44:53 $ + * + * @version 1.2 $Revision: 1.65.2.9 $ $Date: 2010-12-02 08:06:38 $ */ -public class TCPMessageChannel extends MessageChannel implements - SIPMessageListener, Runnable, RawMessageChannel { - private static StackLogger logger = CommonLogger.getLogger(TCPMessageChannel.class); +public class TCPMessageChannel extends MessageChannel implements SIPMessageListener, Runnable, + RawMessageChannel { + private Socket mySock; private PipelinedMsgParser myParser; @@ -110,8 +91,9 @@ public class TCPMessageChannel extends MessageChannel implements protected InetAddress peerAddress; + // This is the TCP source port that the peer actually used the first time he connected to us protected int peerPort; - + protected String peerProtocol; // Incremented whenever a transaction gets assigned @@ -127,27 +109,23 @@ protected TCPMessageChannel(SIPTransactionStack sipStack) { } /** - * Constructor - gets called from the SIPStack class with a socket on - * accepting a new client. All the processing of the message is done here - * with the sipStack being freed up to handle new connections. The sock - * input is the socket that is returned from the accept. Global data that is - * shared by all threads is accessible in the Server structure. - * - * @param sock - * Socket from which to read and write messages. The socket is - * already connected (was created as a result of an accept). - * - * @param sipStack - * Ptr to SIP Stack + * Constructor - gets called from the SIPStack class with a socket on accepting a new client. + * All the processing of the message is done here with the sipStack being freed up to handle + * new connections. The sock input is the socket that is returned from the accept. Global data + * that is shared by all threads is accessible in the Server structure. + * + * @param sock Socket from which to read and write messages. The socket is already connected + * (was created as a result of an accept). + * + * @param sipStack Ptr to SIP Stack */ protected TCPMessageChannel(Socket sock, SIPTransactionStack sipStack, - TCPMessageProcessor msgProcessor, String threadName) throws IOException { + TCPMessageProcessor msgProcessor) throws IOException { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( - "creating new TCPMessageChannel "); - logger.logStackTrace(); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("creating new TCPMessageChannel "); + sipStack.getStackLogger().logStackTrace(); } mySock = sock; peerAddress = mySock.getInetAddress(); @@ -156,12 +134,12 @@ protected TCPMessageChannel(Socket sock, SIPTransactionStack sipStack, myClientOutputStream = mySock.getOutputStream(); mythread = new Thread(this); mythread.setDaemon(true); - mythread.setName(threadName); + mythread.setName("TCPMessageChannelThread"); // Stash away a pointer to our sipStack structure. this.sipStack = sipStack; this.peerPort = mySock.getPort(); this.key = MessageChannel.getKey(peerAddress, peerPort, "TCP"); - + this.tcpMessageProcessor = msgProcessor; this.myPort = this.tcpMessageProcessor.getPort(); // Bug report by Vishwashanti Raj Kadiayl @@ -171,24 +149,18 @@ protected TCPMessageChannel(Socket sock, SIPTransactionStack sipStack, } /** - * Constructor - connects to the given inet address. Acknowledgement -- - * Lamine Brahimi (IBM Zurich) sent in a bug fix for this method. A thread - * was being uncessarily created. - * - * @param inetAddr - * inet address to connect to. - * @param sipStack - * is the sip sipStack from which we are created. - * @throws IOException - * if we cannot connect. + * Constructor - connects to the given inet address. Acknowledgement -- Lamine Brahimi (IBM + * Zurich) sent in a bug fix for this method. A thread was being uncessarily created. + * + * @param inetAddr inet address to connect to. + * @param sipStack is the sip sipStack from which we are created. + * @throws IOException if we cannot connect. */ - protected TCPMessageChannel(InetAddress inetAddr, int port, - SIPTransactionStack sipStack, TCPMessageProcessor messageProcessor) - throws IOException { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( - "creating new TCPMessageChannel "); - logger.logStackTrace(); + protected TCPMessageChannel(InetAddress inetAddr, int port, SIPTransactionStack sipStack, + TCPMessageProcessor messageProcessor) throws IOException { + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("creating new TCPMessageChannel "); + sipStack.getStackLogger().logStackTrace(); } this.peerAddress = inetAddr; this.peerPort = port; @@ -203,14 +175,13 @@ protected TCPMessageChannel(InetAddress inetAddr, int port, } - /** * Returns "true" as this is a reliable transport. */ public boolean isReliable() { return true; } - + /** * Close the message channel. */ @@ -221,58 +192,56 @@ public void close() { /** * Close the message channel. */ - public void close(boolean removeSocket) { - isRunning = false; + public void close(boolean removeSocket) { + isRunning = false; // we need to close everything because the socket may be closed by the other end // like in LB scenarios sending OPTIONS and killing the socket after it gets the response - if (mySock != null) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("Closing socket " + key); - try { - mySock.close(); - mySock = null; - } catch (IOException ex) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("Error closing socket " + ex); - } - } - if(myParser != null) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("Closing my parser " + myParser); - myParser.close(); - } - // no need to close myClientInputStream since myParser.close() above will do it - if(myClientOutputStream != null) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("Closing client output stream " + myClientOutputStream); - try { - myClientOutputStream.close(); - } catch (IOException ex) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("Error closing client output stream" + ex); - } - } - if(removeSocket) { - // remove the "tcp:" part of the key to cleanup the ioHandler hashmap - String ioHandlerKey = key.substring(4); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("Closing TCP socket " + ioHandlerKey); - // Issue 358 : remove socket and semaphore on close to avoid leaking - sipStack.ioHandler.removeSocket(ioHandlerKey); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("Closing message Channel " + this); - } else { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + if (mySock != null) { + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Closing socket " + key); + try { + mySock.close(); + } catch (IOException ex) { + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Error closing socket " + ex); + } + } + if(myParser != null) { + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Closing my parser " + myParser); + myParser.close(); + } + // no need to close myClientInputStream since myParser.close() above will do it + if(myClientOutputStream != null) { + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Closing client output stream " + myClientOutputStream); + try { + myClientOutputStream.close(); + } catch (IOException ex) { + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Error closing client output stream" + ex); + } + } + if(removeSocket) { + // remove the "tcp:" part of the key to cleanup the ioHandler hashmap + String ioHandlerKey = key.substring(4); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Closing TCP socket " + ioHandlerKey); + // Issue 358 : remove socket and semaphore on close to avoid leaking + sipStack.ioHandler.removeSocket(ioHandlerKey); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Closing message Channel " + this); + } else { + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { String ioHandlerKey = key.substring(4); - logger.logDebug("not removing socket key from the cached map since it has already been updated by the iohandler.sendBytes " + ioHandlerKey); + sipStack.getStackLogger().logDebug("not removing socket key from the cached map since it has already been updated by the iohandler.sendBytes " + ioHandlerKey); } } - } /** * Get my SIP Stack. - * + * * @return The SIP Stack for this message channel. */ public SIPTransactionStack getSIPStack() { @@ -281,7 +250,7 @@ public SIPTransactionStack getSIPStack() { /** * get the transport string. - * + * * @return "tcp" in this case. */ public String getTransport() { @@ -290,9 +259,9 @@ public String getTransport() { /** * get the address of the client that sent the data to us. - * - * @return Address of the client that sent us data that resulted in this - * channel being created. + * + * @return Address of the client that sent us data that resulted in this channel being + * created. */ public String getPeerAddress() { if (peerAddress != null) { @@ -310,29 +279,23 @@ public String getPeerProtocol() { } /** - * Send message to whoever is connected to us. Uses the topmost via address - * to send to. - * - * @param msg - * is the message to send. - * @param isClient + * Send message to whoever is connected to us. Uses the topmost via address to send to. + * + * @param msg is the message to send. + * @param retry */ - private void sendMessage(byte[] msg, boolean isClient) throws IOException { + private void sendMessage(byte[] msg, boolean retry) throws IOException { - if ( logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("sendMessage isClient = " + isClient); - } /* - * Patch from kircuv@dev.java.net (Issue 119 ) This patch avoids the - * case where two TCPMessageChannels are now pointing to the same - * socket.getInputStream(). - * + * Patch from kircuv@dev.java.net (Issue 119 ) This patch avoids the case where two + * TCPMessageChannels are now pointing to the same socket.getInputStream(). + * * JvB 22/5 removed */ - - Socket sock = this.sipStack.ioHandler.sendBytes(this.messageProcessor - .getIpAddress(), this.peerAddress, this.peerPort, - this.peerProtocol, msg, isClient, this); + // Socket s = this.sipStack.ioHandler.getSocket(IOHandler.makeKey( + // this.peerAddress, this.peerPort)); + Socket sock = this.sipStack.ioHandler.sendBytes(this.messageProcessor.getIpAddress(), + this.peerAddress, this.peerPort, this.peerProtocol, msg, retry, this); // Created a new socket so close the old one and stick the new // one in its place but dont do this if it is a datagram socket. @@ -341,18 +304,17 @@ private void sendMessage(byte[] msg, boolean isClient) throws IOException { // this.uncache(); // } else if (sock != mySock && sock != null) { - if(mySock != null && logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( + if (mySock != null && sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( "Old socket different than new socket"); - logger.logStackTrace(); - - logger.logDebug( - "Old socket local ip address " + mySock.getLocalSocketAddress()); - logger.logDebug( - "Old socket remote ip address " + mySock.getRemoteSocketAddress()); - logger.logDebug( + sipStack.getStackLogger().logStackTrace(); + sipStack.getStackLogger().logDebug( + "Old socket local ip address " + mySock.getLocalSocketAddress()); + sipStack.getStackLogger().logDebug( + "Old socket remote ip address " + mySock.getRemoteSocketAddress()); + sipStack.getStackLogger().logDebug( "New socket local ip address " + sock.getLocalSocketAddress()); - logger.logDebug( + sipStack.getStackLogger().logDebug( "New socket remote ip address " + sock.getRemoteSocketAddress()); } close(false); @@ -368,121 +330,101 @@ private void sendMessage(byte[] msg, boolean isClient) throws IOException { } /** - * Return a formatted message to the client. We try to re-connect with the - * peer on the other end if possible. - * - * @param sipMessage - * Message to send. - * @throws IOException - * If there is an error sending the message + * Return a formatted message to the client. We try to re-connect with the peer on the other + * end if possible. + * + * @param sipMessage Message to send. + * @throws IOException If there is an error sending the message */ public void sendMessage(final SIPMessage sipMessage) throws IOException { - - if ( logger.isLoggingEnabled(LogWriter.TRACE_DEBUG) && !sipMessage.isNullRequest() ) { - logger.logDebug("sendMessage:: " + sipMessage.getFirstLine() + " cseq method = " + sipMessage.getCSeq().getMethod()); - } - - for (MessageProcessor messageProcessor : getSIPStack() - .getMessageProcessors()) { - if (messageProcessor.getIpAddress().getHostAddress().equals( - this.getPeerAddress()) + + for (MessageProcessor messageProcessor : getSIPStack().getMessageProcessors()) { + if (getSIPStack().getStackLogger().isLoggingEnabled(LogWriter.TRACE_DEBUG)){ + getSIPStack().getStackLogger().logDebug("messageProcessor=" + messageProcessor + + ", addr=" + messageProcessor.getIpAddress().getHostAddress() + + ", peeraddr= " + this.getPeerAddress() + + ", mpTransport=" + messageProcessor.getTransport() + + ", mpPort=" + messageProcessor.getPort() + + ", peerport=" + this.getPeerPort() + + ", peertrnsport=" + this.getPeerProtocol() + " EL\n"); + } + + if (messageProcessor.getIpAddress().getHostAddress().equals(this.getPeerAddress()) && messageProcessor.getPort() == this.getPeerPort() - && messageProcessor.getTransport().equalsIgnoreCase( - this.getPeerProtocol())) { - Runnable processMessageTask = new Runnable() { + && messageProcessor.getTransport().equalsIgnoreCase(this.getPeerProtocol())) { + Runnable processMessageTask = new Runnable() { + + public void run() { + try { + processMessage((SIPMessage) sipMessage.clone()); + } catch (Exception ex) { + if (getSIPStack().getStackLogger().isLoggingEnabled(ServerLogger.TRACE_ERROR)) { + getSIPStack().getStackLogger().logError("Error self routing message cause by: ", ex); + } + } + } + }; + getSIPStack().getSelfRoutingThreadpoolExecutor().execute(processMessageTask); + + if (getSIPStack().getStackLogger().isLoggingEnabled(LogWriter.TRACE_DEBUG)) + getSIPStack().getStackLogger().logDebug("Self routing message"); + return; + } - public void run() { - try { - processMessage((SIPMessage) sipMessage.clone()); - } catch (Exception ex) { - if (logger - .isLoggingEnabled(ServerLogger.TRACE_ERROR)) { - logger - .logError( - "Error self routing message cause by: ", - ex); - } - } - } - }; - getSIPStack().getSelfRoutingThreadpoolExecutor().execute( - processMessageTask); - - if (logger.isLoggingEnabled( - LogWriter.TRACE_DEBUG)) - logger.logDebug( - "Self routing message"); - return; } - - } - byte[] msg = sipMessage.encodeAsBytes(this.getTransport()); long time = System.currentTimeMillis(); // JvB: also retry for responses, if the connection is gone we should // try to reconnect - this.sendMessage(msg, sipMessage instanceof SIPRequest ); + this.sendMessage(msg, /* sipMessage instanceof SIPRequest */true); - // message was sent without any exception so let's set set port and - // address before we feed it to the logger - sipMessage.setRemoteAddress(this.peerAddress); - sipMessage.setRemotePort(this.peerPort); - sipMessage.setLocalAddress(this.getMessageProcessor().getIpAddress()); - sipMessage.setLocalPort(this.getPort()); - - if (logger.isLoggingEnabled( - ServerLogger.TRACE_MESSAGES)) + if (this.sipStack.getStackLogger().isLoggingEnabled(ServerLogger.TRACE_MESSAGES)) logMessage(sipMessage, peerAddress, peerPort, time); } /** * Send a message to a specified address. - * - * @param message - * Pre-formatted message to send. - * @param receiverAddress - * Address to send it to. - * @param receiverPort - * Receiver port. - * @throws IOException - * If there is a problem connecting or sending. + * + * @param message Pre-formatted message to send. + * @param receiverAddress Address to send it to. + * @param receiverPort Receiver port. + * @throws IOException If there is a problem connecting or sending. */ - public void sendMessage(byte message[], InetAddress receiverAddress, - int receiverPort, boolean retry) throws IOException { + public void sendMessage(byte message[], InetAddress receiverAddress, int receiverPort, + boolean retry) throws IOException { if (message == null || receiverAddress == null) throw new IllegalArgumentException("Null argument"); - Socket sock = this.sipStack.ioHandler.sendBytes(this.messageProcessor - .getIpAddress(), receiverAddress, receiverPort, "TCP", message, - retry, this); - if (sock != mySock && sock != null) { + Socket sock = this.sipStack.ioHandler.sendBytes(this.messageProcessor.getIpAddress(), + receiverAddress, receiverPort, "TCP", message, retry, this); + if (sock != mySock && sock != null) { if (mySock != null) { - if(logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( + if(sipStack.getStackLogger().isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( "Old socket different than new socket"); - logger.logStackTrace(); - - logger.logDebug( - "Old socket local ip address " + mySock.getLocalSocketAddress()); - logger.logDebug( - "Old socket remote ip address " + mySock.getRemoteSocketAddress()); - logger.logDebug( + sipStack.getStackLogger().logStackTrace(); + sipStack.getStackLogger().logDebug( + "Old socket local ip address " + mySock.getLocalSocketAddress()); + sipStack.getStackLogger().logDebug( + "Old socket remote ip address " + mySock.getRemoteSocketAddress()); + sipStack.getStackLogger().logDebug( "New socket local ip address " + sock.getLocalSocketAddress()); - logger.logDebug( + sipStack.getStackLogger().logDebug( "New socket remote ip address " + sock.getRemoteSocketAddress()); } /* - * Delay the close of the socket for some time in case it is - * being used. + * Delay the close of the socket for some time in case it is being used. */ - sipStack.getTimer().schedule(new SIPStackTimerTask() { + sipStack.getTimer().schedule(new TimerTask() { @Override - public void cleanUpBeforeCancel() { - close(false); + public boolean cancel() { + close(false); + return true; } - public void runTask() { + @Override + public void run() { close(false); } }, 8000); @@ -501,34 +443,26 @@ public void runTask() { } /** - * Exception processor for exceptions detected from the parser. (This is - * invoked by the parser when an error is detected). - * - * @param sipMessage - * -- the message that incurred the error. - * @param ex - * -- parse exception detected by the parser. - * @param header - * -- header that caused the error. - * @throws ParseException - * Thrown if we want to reject the message. + * Exception processor for exceptions detected from the parser. (This is invoked by the parser + * when an error is detected). + * + * @param sipMessage -- the message that incurred the error. + * @param ex -- parse exception detected by the parser. + * @param header -- header that caused the error. + * @throws ParseException Thrown if we want to reject the message. */ - public void handleException(ParseException ex, SIPMessage sipMessage, - Class hdrClass, String header, String message) - throws ParseException { - if (logger.isLoggingEnabled()) - logger.logException(ex); + public void handleException(ParseException ex, SIPMessage sipMessage, Class hdrClass, + String header, String message) throws ParseException { + if (sipStack.isLoggingEnabled()) + sipStack.getStackLogger().logException(ex); // Log the bad message for later reference. if ((hdrClass != null) && (hdrClass.equals(From.class) || hdrClass.equals(To.class) - || hdrClass.equals(CSeq.class) - || hdrClass.equals(Via.class) - || hdrClass.equals(CallID.class) - || hdrClass.equals(ContentLength.class) - || hdrClass.equals(RequestLine.class) || hdrClass + || hdrClass.equals(CSeq.class) || hdrClass.equals(Via.class) + || hdrClass.equals(CallID.class) || hdrClass.equals(RequestLine.class) || hdrClass .equals(StatusLine.class))) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( "Encountered Bad Message \n" + sipMessage.toString()); } @@ -539,23 +473,20 @@ public void handleException(ParseException ex, SIPMessage sipMessage, String badReqRes = createBadReqRes(msgString, ex); if (badReqRes != null) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( - "Sending automatic 400 Bad Request:"); - logger.logDebug(badReqRes); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("Sending automatic 400 Bad Request:"); + sipStack.getStackLogger().logDebug(badReqRes); } try { - this.sendMessage(badReqRes.getBytes(), this - .getPeerInetAddress(), this.getPeerPort(), - false); + this.sendMessage(badReqRes.getBytes(), this.getPeerInetAddress(), this + .getPeerPort(), false); } catch (IOException e) { - logger.logException(e); + this.sipStack.getStackLogger().logException(e); } } else { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger - .logDebug( - "Could not formulate automatic 400 Bad Request"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( + "Could not formulate automatic 400 Bad Request"); } } } @@ -565,49 +496,40 @@ public void handleException(ParseException ex, SIPMessage sipMessage, sipMessage.addUnparsed(header); } } - + public void processMessage(SIPMessage sipMessage, InetAddress address) { - this.peerAddress = address; - try { - processMessage(sipMessage); - } catch (Exception e) { - if (logger.isLoggingEnabled( - ServerLog.TRACE_ERROR)) { - logger.logError( - "ERROR processing self routing", e); - } - } + this.peerAddress = address; + try { + processMessage(sipMessage); + } catch (Exception e) { + if(sipStack.getStackLogger().isLoggingEnabled(ServerLog.TRACE_ERROR)) { + sipStack.getStackLogger().logError("ERROR processing self routing", e); + } + } } /** - * Gets invoked by the parser as a callback on successful message parsing - * (i.e. no parser errors). - * - * @param sipMessage - * Mesage to process (this calls the application for processing - * the message). + * Gets invoked by the parser as a callback on successful message parsing (i.e. no parser + * errors). + * + * @param sipMessage Mesage to process (this calls the application for processing the + * message). */ public void processMessage(SIPMessage sipMessage) throws Exception { try { if (sipMessage.getFrom() == null || // sipMessage.getFrom().getTag() // == null || - sipMessage.getTo() == null - || sipMessage.getCallId() == null - || sipMessage.getCSeq() == null - || sipMessage.getViaHeaders() == null) { + sipMessage.getTo() == null || sipMessage.getCallId() == null + || sipMessage.getCSeq() == null || sipMessage.getViaHeaders() == null) { String badmsg = sipMessage.encode(); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug(">>> Dropped Bad Msg"); - logger.logDebug(badmsg); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug(">>> Dropped Bad Msg"); + sipStack.getStackLogger().logDebug(badmsg); } return; } - sipMessage.setRemoteAddress(this.peerAddress); - sipMessage.setRemotePort(this.getPeerPort()); - sipMessage.setLocalAddress(this.getMessageProcessor().getIpAddress()); - sipMessage.setLocalPort(this.getPort()); ViaList viaList = sipMessage.getViaHeaders(); // For a request @@ -619,10 +541,9 @@ public void processMessage(SIPMessage sipMessage) throws Exception { Hop hop = sipStack.addressResolver.resolveAddress(v.getHop()); this.peerProtocol = v.getTransport(); try { - if (mySock != null) { // selfrouting makes socket = null - // https://jain-sip.dev.java.net/issues/show_bug.cgi?id=297 - this.peerAddress = mySock.getInetAddress(); - } + if(mySock != null) { // selfrouting makes socket = null + this.peerAddress = mySock.getInetAddress(); + } // Check to see if the received parameter matches // the peer address and tag it appropriately. @@ -634,10 +555,8 @@ public void processMessage(SIPMessage sipMessage) throws Exception { // InetAddress.getByName(hop.getHost()); // JvB: if sender added 'rport', must always set received if (v.hasParameter(Via.RPORT) - || !hop.getHost().equals( - this.peerAddress.getHostAddress())) { - v.setParameter(Via.RECEIVED, this.peerAddress - .getHostAddress()); + || !hop.getHost().equals(this.peerAddress.getHostAddress())) { + v.setParameter(Via.RECEIVED, this.peerAddress.getHostAddress()); } // @@@ hagai // JvB: technically, may only do this when Via already @@ -645,17 +564,13 @@ public void processMessage(SIPMessage sipMessage) throws Exception { // rport v.setParameter(Via.RPORT, Integer.toString(this.peerPort)); } catch (java.text.ParseException ex) { - InternalErrorHandler.handleException(ex, logger); + InternalErrorHandler.handleException(ex, sipStack.getStackLogger()); } // Use this for outgoing messages as well. - if (!this.isCached && mySock != null) { // self routing makes - // mySock=null - // https://jain-sip.dev.java.net/issues/show_bug.cgi?id=297 + if (!this.isCached && mySock != null) { this.isCached = true; - int remotePort = ((java.net.InetSocketAddress) mySock - .getRemoteSocketAddress()).getPort(); - String key = IOHandler.makeKey(mySock.getInetAddress(), - remotePort); + int remotePort = ((java.net.InetSocketAddress) mySock.getRemoteSocketAddress()).getPort(); + String key = IOHandler.makeKey(mySock.getInetAddress(), remotePort); sipStack.ioHandler.putSocket(key, mySock); // since it can close the socket it needs to be after the mySock usage otherwise // it the socket will be disconnected and NPE will be thrown in some edge cases @@ -664,6 +579,7 @@ public void processMessage(SIPMessage sipMessage) throws Exception { } } + // Foreach part of the request header, fetch it and process it long receptionTime = System.currentTimeMillis(); @@ -674,65 +590,33 @@ public void processMessage(SIPMessage sipMessage) throws Exception { // Create a new sever side request processor for this // message and let it handle the rest. - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( - "----Processing Message---"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("----Processing Message---"); } // Check for reasonable size - reject message // if it is too long. - if (logger.isLoggingEnabled( - ServerLogger.TRACE_MESSAGES)) { - sipStack.serverLogger.logMessage(sipMessage, this - .getPeerHostPort().toString(), this - .getMessageProcessor().getIpAddress() - .getHostAddress() - + ":" + this.getMessageProcessor().getPort(), - false, receptionTime); + if (this.sipStack.getStackLogger().isLoggingEnabled(ServerLogger.TRACE_MESSAGES)) { + sipStack.serverLogger.logMessage(sipMessage, this.getPeerHostPort().toString(), + this.getMessageProcessor().getIpAddress().getHostAddress() + ":" + + this.getMessageProcessor().getPort(), false, receptionTime); } if (sipStack.getMaxMessageSize() > 0 && sipRequest.getSize() - + (sipRequest.getContentLength() == null ? 0 - : sipRequest.getContentLength() - .getContentLength()) > sipStack + + (sipRequest.getContentLength() == null ? 0 : sipRequest + .getContentLength().getContentLength()) > sipStack .getMaxMessageSize()) { SIPResponse sipResponse = sipRequest .createResponse(SIPResponse.MESSAGE_TOO_LARGE); - byte[] resp = sipResponse - .encodeAsBytes(this.getTransport()); + byte[] resp = sipResponse.encodeAsBytes(this.getTransport()); this.sendMessage(resp, false); throw new Exception("Message size exceeded"); } - /* @see Issue 292 */ - String sipVersion = ((SIPRequest) sipMessage).getRequestLine() - .getSipVersion(); - if (!sipVersion.equals("SIP/2.0")) { - SIPResponse versionNotSupported = ((SIPRequest) sipMessage) - .createResponse(Response.VERSION_NOT_SUPPORTED, - "Bad version " + sipVersion); - this.sendMessage(versionNotSupported.encodeAsBytes(this - .getTransport()), false); - throw new Exception("Bad sip version"); - } - - String method = ((SIPRequest) sipMessage).getMethod(); - String cseqMethod = ((SIPRequest) sipMessage).getCSeqHeader() - .getMethod(); - - if (!method.equalsIgnoreCase(cseqMethod)) { - SIPResponse sipResponse = sipRequest - .createResponse(SIPResponse.BAD_REQUEST); - byte[] resp = sipResponse - .encodeAsBytes(this.getTransport()); - this.sendMessage(resp, false); - throw new Exception("Bad CSeq method"); - } - - ServerRequestInterface sipServerRequest = sipStack - .newSIPServerRequest(sipRequest, this); + ServerRequestInterface sipServerRequest = sipStack.newSIPServerRequest( + sipRequest, this); if (sipServerRequest != null) { try { @@ -741,15 +625,13 @@ public void processMessage(SIPMessage sipMessage) throws Exception { if (sipServerRequest instanceof SIPTransaction) { SIPServerTransaction sipServerTx = (SIPServerTransaction) sipServerRequest; if (!sipServerTx.passToListener()) - ((SIPTransaction) sipServerRequest) - .releaseSem(); + ((SIPTransaction) sipServerRequest).releaseSem(); } } } else { - if (logger.isLoggingEnabled()) - logger - .logWarning( - "Dropping request -- could not acquire semaphore in 10 sec"); + if (sipStack.isLoggingEnabled()) + this.sipStack.getStackLogger() + .logWarning("Dropping request -- could not acquire semaphore in 10 sec"); } } else { @@ -760,9 +642,9 @@ public void processMessage(SIPMessage sipMessage) throws Exception { try { sipResponse.checkHeaders(); } catch (ParseException ex) { - if (logger.isLoggingEnabled()) - logger.logError( - "Dropping Badly formatted response message >>> " + if (sipStack.isLoggingEnabled()) + sipStack.getStackLogger() + .logError("Dropping Badly formatted response message >>> " + sipResponse); return; } @@ -771,26 +653,24 @@ public void processMessage(SIPMessage sipMessage) throws Exception { // If it is too large dump it silently. if (sipStack.getMaxMessageSize() > 0 && sipResponse.getSize() - + (sipResponse.getContentLength() == null ? 0 - : sipResponse.getContentLength() - .getContentLength()) > sipStack + + (sipResponse.getContentLength() == null ? 0 : sipResponse + .getContentLength().getContentLength()) > sipStack .getMaxMessageSize()) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug( - "Message size exceeded"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + this.sipStack.getStackLogger().logDebug("Message size exceeded"); return; } - ServerResponseInterface sipServerResponse = sipStack - .newSIPServerResponse(sipResponse, this); + ServerResponseInterface sipServerResponse = sipStack.newSIPServerResponse( + sipResponse, this); if (sipServerResponse != null) { try { if (sipServerResponse instanceof SIPClientTransaction && !((SIPClientTransaction) sipServerResponse) .checkFromTag(sipResponse)) { - if (logger.isLoggingEnabled()) - logger.logError( - "Dropping response message with invalid tag >>> " + if (sipStack.isLoggingEnabled()) + sipStack.getStackLogger() + .logError("Dropping response message with invalid tag >>> " + sipResponse); return; } @@ -798,12 +678,12 @@ public void processMessage(SIPMessage sipMessage) throws Exception { sipServerResponse.processResponse(sipResponse, this); } finally { if (sipServerResponse instanceof SIPTransaction - && !((SIPTransaction) sipServerResponse) - .passToListener()) + && !((SIPTransaction) sipServerResponse).passToListener()) ((SIPTransaction) sipServerResponse).releaseSem(); } } else { - logger + sipStack + .getStackLogger() .logWarning( "Application is blocked -- could not acquire semaphore -- dropping response"); } @@ -813,21 +693,18 @@ public void processMessage(SIPMessage sipMessage) throws Exception { } /** - * This gets invoked when thread.start is called from the constructor. - * Implements a message loop - reading the tcp connection and processing - * messages until we are done or the other end has closed. + * This gets invoked when thread.start is called from the constructor. Implements a message + * loop - reading the tcp connection and processing messages until we are done or the other + * end has closed. */ - - - public void run() { + public void run() { Pipeline hispipe = null; // Create a pipeline to connect to our message parser. hispipe = new Pipeline(myClientInputStream, sipStack.readTimeout, ((SIPTransactionStack) sipStack).getTimer()); // Create a pipelined message parser to read and parse - // messages that we write out to him. - myParser = new PipelinedMsgParser(sipStack, this, hispipe, - this.sipStack.getMaxMessageSize()); + // messages that we write out to him. + myParser = new PipelinedMsgParser(sipStack, this, hispipe, this.sipStack.getMaxMessageSize()); // Start running the parser thread. myParser.processInput(); // bug fix by Emmanuel Proulx @@ -854,8 +731,7 @@ public void run() { } catch (IOException ioex) { } return; - } - + } hispipe.write(msg, 0, nbytes); } catch (IOException ex) { @@ -867,9 +743,8 @@ public void run() { } try { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug( - "IOException closing sock " + ex); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("IOException closing sock " + ex); try { if (sipStack.maxConnections != -1) { synchronized (tcpMessageProcessor) { @@ -887,7 +762,7 @@ public void run() { } return; } catch (Exception ex) { - InternalErrorHandler.handleException(ex, logger); + InternalErrorHandler.handleException(ex, sipStack.getStackLogger()); } } } finally { @@ -903,20 +778,19 @@ public void run() { } protected void uncache() { - if (isCached && !isRunning) { - this.tcpMessageProcessor.remove(this); - } + if (isCached && !isRunning ) { + this.tcpMessageProcessor.remove(this); + } } /** * Equals predicate. - * - * @param other - * is the other object to compare ourselves to for equals + * + * @param other is the other object to compare ourselves to for equals */ public boolean equals(Object other) { - + if(other==null) return false; if (!this.getClass().equals(other.getClass())) return false; else { @@ -929,40 +803,39 @@ public boolean equals(Object other) { } /** - * Get an identifying key. This key is used to cache the connection and - * re-use it if necessary. + * Get an identifying key. This key is used to cache the connection and re-use it if + * necessary. */ public String getKey() { if (this.key != null) { return this.key; } else { - this.key = MessageChannel.getKey(this.peerAddress, this.peerPort, - "TCP"); + this.key = MessageChannel.getKey(this.peerAddress, this.peerPort, "TCP"); return this.key; } } /** * Get the host to assign to outgoing messages. - * + * * @return the host to assign to the via header. */ public String getViaHost() { - return this.myAddress; + return myAddress; } /** * Get the port for outgoing messages sent from the channel. - * + * * @return the port to assign to the via header. */ public int getViaPort() { - return this.myPort; + return myPort; } /** * Get the port of the peer to whom we are sending messages. - * + * * @return the peer port. */ public int getPeerPort() { @@ -983,14 +856,4 @@ public InetAddress getPeerPacketSourceAddress() { public boolean isSecure() { return false; } - - /* - * (non-Javadoc) - * @see gov.nist.javax.sip.parser.SIPMessageListener#sendSingleCLRF() - */ - public void sendSingleCLRF() throws Exception { - if(mySock != null && !mySock.isClosed()) { - mySock.getOutputStream().write("\r\n".getBytes("UTF-8")); - } - } } diff --git a/src/gov/nist/javax/sip/stack/TCPMessageProcessor.java b/src/gov/nist/javax/sip/stack/TCPMessageProcessor.java index b4c1b4a9f..a2cffdc38 100755 --- a/src/gov/nist/javax/sip/stack/TCPMessageProcessor.java +++ b/src/gov/nist/javax/sip/stack/TCPMessageProcessor.java @@ -50,15 +50,13 @@ * connection. This is the active object that creates new TCP MessageChannels (one for each new * accept socket). * - * @version 1.2 $Revision: 1.35 $ $Date: 2010-12-02 22:04:13 $ + * @version 1.2 $Revision: 1.31.2.1 $ $Date: 2010-11-23 19:23:14 $ * * @author M. Ranganathan
    * * */ public class TCPMessageProcessor extends MessageProcessor { - - private static StackLogger logger = CommonLogger.getLogger(TCPMessageProcessor.class); protected int nConnections; @@ -134,19 +132,19 @@ public void run() { } Socket newsock = sock.accept(); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("Accepting new connection!"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + getSIPStack().getStackLogger().logDebug("Accepting new connection!"); } // Note that for an incoming message channel, the // thread is already running - incomingTcpMessageChannels.add(new TCPMessageChannel(newsock, sipStack, this, "TCPMessageChannelThread-" + nConnections)); + incomingTcpMessageChannels.add(new TCPMessageChannel(newsock, sipStack, this)); } catch (SocketException ex) { this.isRunning = false; } catch (IOException ex) { // Problem accepting connection. - if (logger.isLoggingEnabled()) - logger.logException(ex); + if (sipStack.isLoggingEnabled()) + getSIPStack().getStackLogger().logException(ex); continue; } catch (Exception ex) { InternalErrorHandler.handleException(ex); @@ -202,8 +200,8 @@ public synchronized void stop() { protected synchronized void remove(TCPMessageChannel tcpMessageChannel) { String key = tcpMessageChannel.getKey(); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug(Thread.currentThread() + " removing " + key); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug(Thread.currentThread() + " removing " + key); } /** May have been removed already */ @@ -224,9 +222,9 @@ public synchronized MessageChannel createMessageChannel(HostPort targetHostPort) targetHostPort.getPort(), sipStack, this); this.tcpMessageChannels.put(key, retval); retval.isCached = true; - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("key " + key); - logger.logDebug("Creating " + retval); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("key " + key); + sipStack.getStackLogger().logDebug("Creating " + retval); } return retval; } @@ -236,12 +234,12 @@ protected synchronized void cacheMessageChannel(TCPMessageChannel messageChannel String key = messageChannel.getKey(); TCPMessageChannel currentChannel = (TCPMessageChannel) tcpMessageChannels.get(key); if (currentChannel != null) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug("Closing " + key); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Closing " + key); currentChannel.close(); } - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("Caching " + key); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Caching " + key); this.tcpMessageChannels.put(key, messageChannel); } @@ -256,9 +254,9 @@ public synchronized MessageChannel createMessageChannel(InetAddress host, int po TCPMessageChannel retval = new TCPMessageChannel(host, port, sipStack, this); this.tcpMessageChannels.put(key, retval); retval.isCached = true; - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("key " + key); - logger.logDebug("Creating " + retval); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("key " + key); + sipStack.getStackLogger().logDebug("Creating " + retval); } return retval; } diff --git a/src/gov/nist/javax/sip/stack/TLSMessageChannel.java b/src/gov/nist/javax/sip/stack/TLSMessageChannel.java index 207dddfd7..8bf0e578a 100755 --- a/src/gov/nist/javax/sip/stack/TLSMessageChannel.java +++ b/src/gov/nist/javax/sip/stack/TLSMessageChannel.java @@ -34,7 +34,6 @@ * added compensation for buggy clients ( Microsoft RTC clients ). * Bug fixes by viswashanti.kadiyala@antepo.com, Joost Yervante Damand * Lamine Brahimi (IBM Zurich) sent in a bug fix - a thread was being uncessarily created. - * Carolyn Beeton (Avaya) bug fix for ssl handshake exception. */ /****************************************************************************** @@ -42,33 +41,15 @@ ******************************************************************************/ package gov.nist.javax.sip.stack; -import gov.nist.core.CommonLogger; -import gov.nist.core.InternalErrorHandler; -import gov.nist.core.LogWriter; -import gov.nist.core.ServerLogger; -import gov.nist.core.StackLogger; -import gov.nist.javax.sip.header.CSeq; -import gov.nist.javax.sip.header.CallID; -import gov.nist.javax.sip.header.ContentLength; -import gov.nist.javax.sip.header.From; -import gov.nist.javax.sip.header.RequestLine; -import gov.nist.javax.sip.header.RetryAfter; -import gov.nist.javax.sip.header.StatusLine; -import gov.nist.javax.sip.header.To; -import gov.nist.javax.sip.header.Via; -import gov.nist.javax.sip.header.ViaList; -import gov.nist.javax.sip.message.SIPMessage; -import gov.nist.javax.sip.message.SIPRequest; -import gov.nist.javax.sip.message.SIPResponse; -import gov.nist.javax.sip.parser.Pipeline; -import gov.nist.javax.sip.parser.PipelinedMsgParser; -import gov.nist.javax.sip.parser.SIPMessageListener; - -import java.io.IOException; -import java.io.InputStream; -import java.net.InetAddress; -import java.net.Socket; +import gov.nist.javax.sip.header.*; +import gov.nist.javax.sip.message.*; +import gov.nist.javax.sip.parser.*; +import gov.nist.core.*; + +import java.net.*; +import java.io.*; import java.text.ParseException; +import java.util.TimerTask; import javax.net.ssl.HandshakeCompletedListener; import javax.net.ssl.SSLHandshakeException; @@ -77,12 +58,11 @@ import javax.sip.message.Response; /** - * This is sipStack for TLS connections. This abstracts a stream of parsed - * messages. The SIP sipStack starts this from the main SIPStack class for each - * connection that it accepts. It starts a message parser in its own thread and - * talks to the message parser via a pipe. The message parser calls back via the - * parseError or processMessage functions that are defined as part of the - * SIPMessageListener interface. + * This is sipStack for TLS connections. This abstracts a stream of parsed messages. The SIP + * sipStack starts this from the main SIPStack class for each connection that it accepts. It + * starts a message parser in its own thread and talks to the message parser via a pipe. The + * message parser calls back via the parseError or processMessage functions that are defined as + * part of the SIPMessageListener interface. * * @see gov.nist.javax.sip.parser.PipelinedMsgParser * @@ -90,11 +70,11 @@ * @author M. Ranganathan * * - * @version 1.2 $Revision: 1.43 $ $Date: 2010-12-02 22:44:53 $ + * @version 1.2 $Revision: 1.33.2.2 $ $Date: 2010-11-23 19:23:14 $ */ -public final class TLSMessageChannel extends MessageChannel implements - SIPMessageListener, Runnable, RawMessageChannel { - private static StackLogger logger = CommonLogger.getLogger(TLSMessageChannel.class); +public final class TLSMessageChannel extends MessageChannel implements SIPMessageListener, + Runnable, RawMessageChannel { + private Socket mySock; private PipelinedMsgParser myParser; @@ -131,65 +111,52 @@ public final class TLSMessageChannel extends MessageChannel implements private HandshakeCompletedListener handshakeCompletedListener; /** - * Constructor - gets called from the SIPStack class with a socket on - * accepting a new client. All the processing of the message is done here - * with the sipStack being freed up to handle new connections. The sock - * input is the socket that is returned from the accept. Global data that is - * shared by all threads is accessible in the Server structure. + * Constructor - gets called from the SIPStack class with a socket on accepting a new client. + * All the processing of the message is done here with the sipStack being freed up to handle + * new connections. The sock input is the socket that is returned from the accept. Global data + * that is shared by all threads is accessible in the Server structure. * - * @param sock - * Socket from which to read and write messages. The socket is - * already connected (was created as a result of an accept). + * @param sock Socket from which to read and write messages. The socket is already connected + * (was created as a result of an accept). * - * @param sipStack - * Ptr to SIP Stack + * @param sipStack Ptr to SIP Stack * - * @param msgProcessor - * -- the message processor that created us. + * @param msgProcessor -- the message processor that created us. */ protected TLSMessageChannel(Socket sock, SIPTransactionStack sipStack, - TLSMessageProcessor msgProcessor, String threadName) throws IOException { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( - "creating new TLSMessageChannel (incoming)"); - logger.logStackTrace(); + TLSMessageProcessor msgProcessor) throws IOException { + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("creating new TLSMessageChannel (incoming)"); + sipStack.getStackLogger().logStackTrace(); } mySock = (SSLSocket) sock; if (sock instanceof SSLSocket) { try { SSLSocket sslSock = (SSLSocket) sock; - if(sipStack.getClientAuth() != ClientAuthType.Want && sipStack.getClientAuth() != ClientAuthType.Disabled) { - sslSock.setNeedClientAuth(true); - } - if(logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) { - logger.logDebug("SSLServerSocket need client auth " + sslSock.getNeedClientAuth()); - } - this.handshakeCompletedListener = new HandshakeCompletedListenerImpl( - this); - sslSock - .addHandshakeCompletedListener(this.handshakeCompletedListener); + sslSock.setNeedClientAuth(true); + this.handshakeCompletedListener = new HandshakeCompletedListenerImpl(this); + sslSock.addHandshakeCompletedListener(this.handshakeCompletedListener); sslSock.startHandshake(); } catch (SSLHandshakeException ex) { throw new IOException(ex.getMessage()); } } - + peerAddress = mySock.getInetAddress(); myAddress = msgProcessor.getIpAddress().getHostAddress(); myClientInputStream = mySock.getInputStream(); mythread = new Thread(this); mythread.setDaemon(true); - mythread.setName(threadName); + mythread.setName("TLSMessageChannelThread"); // Stash away a pointer to our sipStack structure. this.sipStack = sipStack; this.tlsMessageProcessor = msgProcessor; this.myPort = this.tlsMessageProcessor.getPort(); this.peerPort = mySock.getPort(); - this.key = MessageChannel.getKey(peerAddress, peerPort, "TLS"); // Bug report by Vishwashanti Raj Kadiayl super.messageProcessor = msgProcessor; // Can drop this after response is sent potentially. @@ -199,22 +166,16 @@ protected TLSMessageChannel(Socket sock, SIPTransactionStack sipStack, /** * Constructor - connects to the given inet address. * - * @param inetAddr - * inet address to connect to. - * @param sipStack - * is the sip sipStack from which we are created. - * @param messageProcessor - * -- the message processor that created us. - * @throws IOException - * if we cannot connect. + * @param inetAddr inet address to connect to. + * @param sipStack is the sip sipStack from which we are created. + * @param messageProcessor -- the message processor that created us. + * @throws IOException if we cannot connect. */ - protected TLSMessageChannel(InetAddress inetAddr, int port, - SIPTransactionStack sipStack, TLSMessageProcessor messageProcessor) - throws IOException { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( - "creating new TLSMessageChannel (outgoing)"); - logger.logStackTrace(); + protected TLSMessageChannel(InetAddress inetAddr, int port, SIPTransactionStack sipStack, + TLSMessageProcessor messageProcessor) throws IOException { + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("creating new TLSMessageChannel (outgoing)"); + sipStack.getStackLogger().logStackTrace(); } this.peerAddress = inetAddr; this.peerPort = port; @@ -245,42 +206,40 @@ public void close() { /** * Close the message channel. */ - public void close(boolean removeSocket) { - - isRunning = false; + public void close(boolean removeSocket) { + isRunning = false; // we need to close everything because the socket may be closed by the other end // like in LB scenarios sending OPTIONS and killing the socket after it gets the response if (mySock != null) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("Closing socket " + key); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Closing socket " + key); try { mySock.close(); } catch (IOException ex) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("Error closing socket " + ex); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Error closing socket " + ex); } - } + } if(myParser != null) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("Closing my parser " + myParser); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Closing my parser " + myParser); myParser.close(); - } - if(removeSocket) { + } + if(removeSocket) { // remove the "tls:" part of the key to cleanup the ioHandler hashmap String ioHandlerKey = key.substring(4); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("Closing TLS socket " + ioHandlerKey); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Closing TLS socket " + ioHandlerKey); // Issue 358 : remove socket and semaphore on close to avoid leaking sipStack.ioHandler.removeSocket(ioHandlerKey); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("Closing message Channel " + this); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Closing message Channel " + this); } else { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { String ioHandlerKey = key.substring(4); - logger.logDebug("not removing socket key from the cached map since it has already been updated by the iohandler.sendBytes " + ioHandlerKey); + sipStack.getStackLogger().logDebug("not removing socket key from the cached map since it has already been updated by the iohandler.sendBytes " + ioHandlerKey); } - } - + } } /** @@ -304,8 +263,8 @@ public String getTransport() { /** * get the address of the client that sent the data to us. * - * @return Address of the client that sent us data that resulted in this - * channel being created. + * @return Address of the client that sent us data that resulted in this channel being + * created. */ public String getPeerAddress() { if (peerAddress != null) { @@ -323,35 +282,32 @@ public String getPeerProtocol() { } /** - * Send message to whoever is connected to us. Uses the topmost via address - * to send to. + * Send message to whoever is connected to us. Uses the topmost via address to send to. * - * @param msg - * is the message to send. + * @param msg is the message to send. * @param retry */ private void sendMessage(byte[] msg, boolean retry) throws IOException { - Socket sock = this.sipStack.ioHandler.sendBytes(this - .getMessageProcessor().getIpAddress(), this.peerAddress, - this.peerPort, this.peerProtocol, msg, retry, this); + Socket sock = this.sipStack.ioHandler.sendBytes( + this.getMessageProcessor().getIpAddress(), this.peerAddress, this.peerPort, + this.peerProtocol, msg, retry,this); // Created a new socket so close the old one and stick the new // one in its place but dont do this if it is a datagram socket. // (could have replied via udp but received via tcp!). if (sock != mySock && sock != null) { - if(mySock != null && logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( + if (mySock != null && sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logError( "Old socket different than new socket"); - logger.logStackTrace(); - - logger.logDebug( - "Old socket local ip address " + mySock.getLocalSocketAddress()); - logger.logDebug( - "Old socket remote ip address " + mySock.getRemoteSocketAddress()); - logger.logDebug( + sipStack.getStackLogger().logStackTrace(); + sipStack.getStackLogger().logDebug( + "Old socket local ip address " + mySock.getLocalSocketAddress()); + sipStack.getStackLogger().logDebug( + "Old socket remote ip address " + mySock.getRemoteSocketAddress()); + sipStack.getStackLogger().logDebug( "New socket local ip address " + sock.getLocalSocketAddress()); - logger.logDebug( + sipStack.getStackLogger().logDebug( "New socket remote ip address " + sock.getRemoteSocketAddress()); - } + } close(false); mySock = sock; this.myClientInputStream = mySock.getInputStream(); @@ -365,13 +321,11 @@ private void sendMessage(byte[] msg, boolean retry) throws IOException { } /** - * Return a formatted message to the client. We try to re-connect with the - * peer on the other end if possible. + * Return a formatted message to the client. We try to re-connect with the peer on the other + * end if possible. * - * @param sipMessage - * Message to send. - * @throws IOException - * If there is an error sending the message + * @param sipMessage Message to send. + * @throws IOException If there is an error sending the message */ public void sendMessage(SIPMessage sipMessage) throws IOException { byte[] msg = sipMessage.encodeAsBytes(this.getTransport()); @@ -380,73 +334,58 @@ public void sendMessage(SIPMessage sipMessage) throws IOException { this.sendMessage(msg, sipMessage instanceof SIPRequest); - // we didn't run into any problems while sending the message so let's - // now set ports and addresses before feeding it to the logger. - sipMessage.setRemoteAddress(this.peerAddress); - sipMessage.setRemotePort(this.peerPort); - sipMessage.setLocalAddress(this.getMessageProcessor().getIpAddress()); - sipMessage.setLocalPort(this.getPort()); - - if (this.logger.isLoggingEnabled( - ServerLogger.TRACE_MESSAGES)) + if (this.sipStack.getStackLogger().isLoggingEnabled(ServerLogger.TRACE_MESSAGES)) logMessage(sipMessage, peerAddress, peerPort, time); } /** * Send a message to a specified address. * - * @param message - * Pre-formatted message to send. - * @param receiverAddress - * Address to send it to. - * @param receiverPort - * Receiver port. - * @throws IOException - * If there is a problem connecting or sending. + * @param message Pre-formatted message to send. + * @param receiverAddress Address to send it to. + * @param receiverPort Receiver port. + * @throws IOException If there is a problem connecting or sending. */ - public void sendMessage(byte message[], InetAddress receiverAddress, - int receiverPort, boolean retry) throws IOException { + public void sendMessage(byte message[], InetAddress receiverAddress, int receiverPort, + boolean retry) throws IOException { if (message == null || receiverAddress == null) throw new IllegalArgumentException("Null argument"); - Socket sock = this.sipStack.ioHandler.sendBytes(this.messageProcessor - .getIpAddress(), receiverAddress, receiverPort, "TLS", message, - retry, this); + Socket sock = this.sipStack.ioHandler.sendBytes(this.messageProcessor.getIpAddress(), + receiverAddress, receiverPort, "TLS", message, retry, this); // // Created a new socket so close the old one and s // Check for null (bug fix sent in by Christophe) - if (sock != mySock && sock != null) { - if (mySock != null) { - if(logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( - "Old socket different than new socket"); - logger.logStackTrace(); - - logger.logDebug( - "Old socket local ip address " + mySock.getLocalSocketAddress()); - logger.logDebug( - "Old socket remote ip address " + mySock.getRemoteSocketAddress()); - logger.logDebug( - "New socket local ip address " + sock.getLocalSocketAddress()); - logger.logDebug( - "New socket remote ip address " + sock.getRemoteSocketAddress()); - } + if (sock != mySock && sock != null) { + if (mySock != null) { + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( + "Old socket different than new socket"); + sipStack.getStackLogger().logStackTrace(); + sipStack.getStackLogger().logDebug( + "Old socket local ip address " + mySock.getLocalSocketAddress()); + sipStack.getStackLogger().logDebug( + "Old socket remote ip address " + mySock.getRemoteSocketAddress()); + sipStack.getStackLogger().logDebug( + "New socket local ip address " + sock.getLocalSocketAddress()); + sipStack.getStackLogger().logDebug( + "New socket remote ip address " + sock.getRemoteSocketAddress()); + } /* * Delay the close of the socket for some time in case it is being used. */ - sipStack.getTimer().schedule(new SIPStackTimerTask() { - - @Override - public void cleanUpBeforeCancel() { - close(false); - super.cleanUpBeforeCancel(); - } + sipStack.getTimer().schedule(new TimerTask() { + @Override + public boolean cancel() { + close(false); + return true; + } @Override - public void runTask() { + public void run() { close(false); } }, 8000); - } + } mySock = sock; this.myClientInputStream = mySock.getInputStream(); @@ -460,58 +399,46 @@ public void runTask() { } /** - * Exception processor for exceptions detected from the parser. (This is - * invoked by the parser when an error is detected). + * Exception processor for exceptions detected from the parser. (This is invoked by the parser + * when an error is detected). * - * @param sipMessage - * -- the message that incurred the error. - * @param ex - * -- parse exception detected by the parser. - * @param header - * -- header that caused the error. - * @throws ParseException - * Thrown if we want to reject the message. + * @param sipMessage -- the message that incurred the error. + * @param ex -- parse exception detected by the parser. + * @param header -- header that caused the error. + * @throws ParseException Thrown if we want to reject the message. */ - public void handleException(ParseException ex, SIPMessage sipMessage, - Class hdrClass, String header, String message) - throws ParseException { - if (logger.isLoggingEnabled()) - logger.logException(ex); + public void handleException(ParseException ex, SIPMessage sipMessage, Class hdrClass, + String header, String message) throws ParseException { + if (sipStack.isLoggingEnabled()) + sipStack.getStackLogger().logException(ex); // Log the bad message for later reference. if ((hdrClass != null) && (hdrClass.equals(From.class) || hdrClass.equals(To.class) - || hdrClass.equals(CSeq.class) - || hdrClass.equals(Via.class) - || hdrClass.equals(CallID.class) - || hdrClass.equals(ContentLength.class) - || hdrClass.equals(RequestLine.class) || hdrClass + || hdrClass.equals(CSeq.class) || hdrClass.equals(Via.class) + || hdrClass.equals(CallID.class) || hdrClass.equals(RequestLine.class) || hdrClass .equals(StatusLine.class))) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug( - "Encountered bad message \n" + message); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Encountered bad message \n" + message); // JvB: send a 400 response for requests (except ACK) String msgString = sipMessage.toString(); if (!msgString.startsWith("SIP/") && !msgString.startsWith("ACK ")) { String badReqRes = createBadReqRes(msgString, ex); if (badReqRes != null) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( - "Sending automatic 400 Bad Request:"); - logger.logDebug(badReqRes); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("Sending automatic 400 Bad Request:"); + sipStack.getStackLogger().logDebug(badReqRes); } try { - this.sendMessage(badReqRes.getBytes(), this - .getPeerInetAddress(), this.getPeerPort(), - false); + this.sendMessage(badReqRes.getBytes(), this.getPeerInetAddress(), this + .getPeerPort(), false); } catch (IOException e) { - logger.logException(e); + this.sipStack.getStackLogger().logException(e); } } else { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger - .logDebug( - "Could not formulate automatic 400 Bad Request"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( + "Could not formulate automatic 400 Bad Request"); } } } @@ -522,31 +449,23 @@ public void handleException(ParseException ex, SIPMessage sipMessage, } /** - * Gets invoked by the parser as a callback on successful message parsing - * (i.e. no parser errors). + * Gets invoked by the parser as a callback on successful message parsing (i.e. no parser + * errors). * - * @param sipMessage - * Message to process (this calls the application for processing - * the message). + * @param sipMessage Message to process (this calls the application for processing the + * message). * - * Jvb: note that this code is identical to TCPMessageChannel, - * refactor some day + * Jvb: note that this code is identical to TCPMessageChannel, refactor some day */ public void processMessage(SIPMessage sipMessage) throws Exception { try { - sipMessage.setRemoteAddress(this.peerAddress); - sipMessage.setRemotePort(this.getPeerPort()); - sipMessage.setLocalAddress(this.getMessageProcessor().getIpAddress()); - sipMessage.setLocalPort(this.getPort()); - if (sipMessage.getFrom() == null || sipMessage.getTo() == null - || sipMessage.getCallId() == null - || sipMessage.getCSeq() == null + || sipMessage.getCallId() == null || sipMessage.getCSeq() == null || sipMessage.getViaHeaders() == null) { String badmsg = sipMessage.encode(); - if (logger.isLoggingEnabled()) { - logger.logError("bad message " + badmsg); - logger.logError(">>> Dropped Bad Msg"); + if (sipStack.isLoggingEnabled()) { + sipStack.getStackLogger().logError("bad message " + badmsg); + sipStack.getStackLogger().logError(">>> Dropped Bad Msg"); } return; } @@ -566,21 +485,16 @@ public void processMessage(SIPMessage sipMessage) throws Exception { this.peerAddress = mySock.getInetAddress(); // Check to see if the received parameter matches // JvB: dont do this. It is both costly and incorrect - // Must set received also when it is a FQDN, regardless - // whether + // Must set received also when it is a FQDN, regardless whether // it resolves to the correct IP address - // InetAddress sentByAddress = - // InetAddress.getByName(hop.getHost()); + // InetAddress sentByAddress = InetAddress.getByName(hop.getHost()); // JvB: if sender added 'rport', must always set received if (v.hasParameter(Via.RPORT) - || !hop.getHost().equals( - this.peerAddress.getHostAddress())) { - v.setParameter(Via.RECEIVED, this.peerAddress - .getHostAddress()); + || !hop.getHost().equals(this.peerAddress.getHostAddress())) { + v.setParameter(Via.RECEIVED, this.peerAddress.getHostAddress()); } // @@@ hagai - // JvB: technically, may only do this when Via already - // contains + // JvB: technically, may only do this when Via already contains // rport v.setParameter(Via.RPORT, Integer.toString(this.peerPort)); } catch (java.text.ParseException ex) { @@ -588,11 +502,9 @@ public void processMessage(SIPMessage sipMessage) throws Exception { } // Use this for outgoing messages as well. if (!this.isCached) { - ((TLSMessageProcessor) this.messageProcessor) - .cacheMessageChannel(this); + ((TLSMessageProcessor) this.messageProcessor).cacheMessageChannel(this); this.isCached = true; - String key = IOHandler.makeKey(mySock.getInetAddress(), - this.peerPort); + String key = IOHandler.makeKey(mySock.getInetAddress(), this.peerPort); sipStack.ioHandler.putSocket(key, mySock); } } @@ -608,65 +520,34 @@ public void processMessage(SIPMessage sipMessage) throws Exception { // Create a new sever side request processor for this // message and let it handle the rest. - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( - "----Processing Message---"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("----Processing Message---"); } - if (logger.isLoggingEnabled( - ServerLogger.TRACE_MESSAGES)) { + if (this.sipStack.getStackLogger().isLoggingEnabled(ServerLogger.TRACE_MESSAGES)) { - sipStack.serverLogger.logMessage(sipMessage, this - .getPeerHostPort().toString(), - this.messageProcessor.getIpAddress() - .getHostAddress() - + ":" + this.messageProcessor.getPort(), - false, receptionTime); + sipStack.serverLogger.logMessage(sipMessage, this.getPeerHostPort().toString(), + this.messageProcessor.getIpAddress().getHostAddress() + ":" + + this.messageProcessor.getPort(), false, receptionTime); } // Check for reasonable size - reject message // if it is too long. if (sipStack.getMaxMessageSize() > 0 && sipRequest.getSize() - + (sipRequest.getContentLength() == null ? 0 - : sipRequest.getContentLength() - .getContentLength()) > sipStack + + (sipRequest.getContentLength() == null ? 0 : sipRequest + .getContentLength().getContentLength()) > sipStack .getMaxMessageSize()) { SIPResponse sipResponse = sipRequest .createResponse(SIPResponse.MESSAGE_TOO_LARGE); - byte[] resp = sipResponse - .encodeAsBytes(this.getTransport()); + byte[] resp = sipResponse.encodeAsBytes(this.getTransport()); this.sendMessage(resp, false); throw new Exception("Message size exceeded"); } - String sipVersion = ((SIPRequest) sipMessage).getRequestLine() - .getSipVersion(); - if (!sipVersion.equals("SIP/2.0")) { - SIPResponse versionNotSupported = ((SIPRequest) sipMessage) - .createResponse(Response.VERSION_NOT_SUPPORTED, - "Bad SIP version " + sipVersion); - this.sendMessage(versionNotSupported.encodeAsBytes(this - .getTransport()), false); - throw new Exception("Bad version "); - } - - String method = ((SIPRequest) sipMessage).getMethod(); - String cseqMethod = ((SIPRequest) sipMessage).getCSeqHeader() - .getMethod(); - - if (!method.equalsIgnoreCase(cseqMethod)) { - SIPResponse sipResponse = sipRequest - .createResponse(SIPResponse.BAD_REQUEST); - byte[] resp = sipResponse - .encodeAsBytes(this.getTransport()); - this.sendMessage(resp, false); - throw new Exception("Bad CSeq method"); - } - // Stack could not create a new server request interface. // maybe not enough resources. - ServerRequestInterface sipServerRequest = sipStack - .newSIPServerRequest(sipRequest, this); + ServerRequestInterface sipServerRequest = sipStack.newSIPServerRequest( + sipRequest, this); if (sipServerRequest != null) { try { sipServerRequest.processRequest(sipRequest, this); @@ -674,8 +555,7 @@ public void processMessage(SIPMessage sipMessage) throws Exception { if (sipServerRequest instanceof SIPTransaction) { SIPServerTransaction sipServerTx = (SIPServerTransaction) sipServerRequest; if (!sipServerTx.passToListener()) - ((SIPTransaction) sipServerRequest) - .releaseSem(); + ((SIPTransaction) sipServerRequest).releaseSem(); } } } else { @@ -692,19 +572,18 @@ public void processMessage(SIPMessage sipMessage) throws Exception { } catch (Exception e) { // IGNore } - if (logger.isLoggingEnabled()) - logger - .logWarning( - "Dropping message -- could not acquire semaphore"); + if (sipStack.isLoggingEnabled()) + sipStack.getStackLogger() + .logWarning("Dropping message -- could not acquire semaphore"); } } else { SIPResponse sipResponse = (SIPResponse) sipMessage; try { sipResponse.checkHeaders(); } catch (ParseException ex) { - if (logger.isLoggingEnabled()) - logger.logError( - "Dropping Badly formatted response message >>> " + if (sipStack.isLoggingEnabled()) + sipStack.getStackLogger() + .logError("Dropping Badly formatted response message >>> " + sipResponse); return; } @@ -713,27 +592,24 @@ public void processMessage(SIPMessage sipMessage) throws Exception { // If it is too large dump it silently. if (sipStack.getMaxMessageSize() > 0 && sipResponse.getSize() - + (sipResponse.getContentLength() == null ? 0 - : sipResponse.getContentLength() - .getContentLength()) > sipStack + + (sipResponse.getContentLength() == null ? 0 : sipResponse + .getContentLength().getContentLength()) > sipStack .getMaxMessageSize()) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug( - "Message size exceeded"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + this.sipStack.getStackLogger().logDebug("Message size exceeded"); return; } - - ServerResponseInterface sipServerResponse = sipStack - .newSIPServerResponse(sipResponse, this); + ServerResponseInterface sipServerResponse = sipStack.newSIPServerResponse( + sipResponse, this); if (sipServerResponse != null) { try { if (sipServerResponse instanceof SIPClientTransaction && !((SIPClientTransaction) sipServerResponse) .checkFromTag(sipResponse)) { - if (logger.isLoggingEnabled()) - logger.logError( - "Dropping response message with invalid tag >>> " + if (sipStack.isLoggingEnabled()) + sipStack.getStackLogger() + .logError("Dropping response message with invalid tag >>> " + sipResponse); return; } @@ -741,8 +617,7 @@ public void processMessage(SIPMessage sipMessage) throws Exception { sipServerResponse.processResponse(sipResponse, this); } finally { if (sipServerResponse instanceof SIPTransaction - && !((SIPTransaction) sipServerResponse) - .passToListener()) { + && !((SIPTransaction) sipServerResponse).passToListener()) { // Note that the semaphore is released in event // scanner if the // request is actually processed by the Listener. @@ -750,8 +625,7 @@ public void processMessage(SIPMessage sipMessage) throws Exception { } } } else { - logger.logWarning( - "Could not get semaphore... dropping response"); + sipStack.getStackLogger().logWarning("Could not get semaphore... dropping response"); } } } finally { @@ -759,9 +633,9 @@ public void processMessage(SIPMessage sipMessage) throws Exception { } /** - * This gets invoked when thread.start is called from the constructor. - * Implements a message loop - reading the tcp connection and processing - * messages until we are done or the other end has closed. + * This gets invoked when thread.start is called from the constructor. Implements a message + * loop - reading the tcp connection and processing messages until we are done or the other + * end has closed. */ public void run() { Pipeline hispipe = null; @@ -770,8 +644,7 @@ public void run() { ((SIPTransactionStack) sipStack).getTimer()); // Create a pipelined message parser to read and parse // messages that we write out to him. - myParser = new PipelinedMsgParser(sipStack, this, hispipe, - this.sipStack.getMaxMessageSize()); + myParser = new PipelinedMsgParser(sipStack, this, hispipe, this.sipStack.getMaxMessageSize()); // Start running the parser thread. myParser.processInput(); // bug fix by Emmanuel Proulx @@ -798,7 +671,7 @@ public void run() { } catch (IOException ioex) { } return; - } + } hispipe.write(msg, 0, nbytes); } catch (IOException ex) { @@ -810,9 +683,8 @@ public void run() { } try { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug( - "IOException closing sock " + ex); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("IOException closing sock " + ex); try { if (sipStack.maxConnections != -1) { synchronized (tlsMessageProcessor) { @@ -838,23 +710,22 @@ public void run() { this.tlsMessageProcessor.useCount--; // parser could be null if the socket was closed by the remote end already if(myParser != null) { - this.myParser.close(); + myParser.close(); } } } protected void uncache() { - if (isCached && !isRunning) { - this.tlsMessageProcessor.remove(this); - } + if (isCached && !isRunning ) { + this.tlsMessageProcessor.remove(this); + } } /** * Equals predicate. * - * @param other - * is the other object to compare ourselves to for equals + * @param other is the other object to compare ourselves to for equals */ public boolean equals(Object other) { @@ -871,15 +742,14 @@ public boolean equals(Object other) { } /** - * Get an identifying key. This key is used to cache the connection and - * re-use it if necessary. + * Get an identifying key. This key is used to cache the connection and re-use it if + * necessary. */ public String getKey() { if (this.key != null) { return this.key; } else { - this.key = MessageChannel.getKey(this.peerAddress, this.peerPort, - "TLS"); + this.key = MessageChannel.getKey(this.peerAddress, this.peerPort, "TLS"); return this.key; } } @@ -937,14 +807,4 @@ public void setHandshakeCompletedListener( public HandshakeCompletedListenerImpl getHandshakeCompletedListener() { return (HandshakeCompletedListenerImpl) handshakeCompletedListener; } - - /* - * (non-Javadoc) - * @see gov.nist.javax.sip.parser.SIPMessageListener#sendSingleCLRF() - */ - public void sendSingleCLRF() throws Exception { - if(mySock != null && !mySock.isClosed()) { - mySock.getOutputStream().write("\r\n".getBytes("UTF-8")); - } - } } diff --git a/src/gov/nist/javax/sip/stack/TLSMessageProcessor.java b/src/gov/nist/javax/sip/stack/TLSMessageProcessor.java index ae7204c94..a57f61da1 100755 --- a/src/gov/nist/javax/sip/stack/TLSMessageProcessor.java +++ b/src/gov/nist/javax/sip/stack/TLSMessageProcessor.java @@ -40,39 +40,33 @@ ******************************************************************************/ package gov.nist.javax.sip.stack; -import gov.nist.core.CommonLogger; import gov.nist.core.HostPort; -import gov.nist.core.LogLevels; import gov.nist.core.LogWriter; -import gov.nist.core.StackLogger; import gov.nist.javax.sip.SipStackImpl; +import javax.net.ssl.SSLException; +import javax.net.ssl.SSLServerSocket; +import javax.net.ssl.SSLSocket; + import java.io.IOException; -import java.net.InetAddress; -import java.net.ServerSocket; -import java.net.Socket; -import java.net.SocketException; -import java.net.UnknownHostException; +import java.net.*; import java.util.ArrayList; import java.util.Collection; import java.util.Hashtable; import java.util.Iterator; -import javax.net.ssl.SSLException; -import javax.net.ssl.SSLServerSocket; - /** * Sit in a loop waiting for incoming tls connections and start a new thread to handle each new * connection. This is the active object that creates new TLS MessageChannels (one for each new * accept socket). * - * @version 1.2 $Revision: 1.29 $ $Date: 2010-12-02 22:04:13 $ + * @version 1.2 $Revision: 1.25.2.2 $ $Date: 2010-11-23 19:23:14 $ * * @author M. Ranganathan
    * */ public class TLSMessageProcessor extends MessageProcessor { - private static StackLogger logger = CommonLogger.getLogger(TLSMessageProcessor.class); + protected int nConnections; private boolean isRunning; @@ -112,32 +106,14 @@ public void start() throws IOException { this.sock = sipStack.getNetworkLayer().createSSLServerSocket(this.getPort(), 0, this.getIpAddress()); - if(sipStack.getClientAuth() == ClientAuthType.Want || sipStack.getClientAuth() == ClientAuthType.Default) { - // we set it to true in Default case as well to keep backward compatibility and default behavior - ((SSLServerSocket) this.sock).setWantClientAuth(true); - } else { - ((SSLServerSocket) this.sock).setWantClientAuth(false); - } - if(sipStack.getClientAuth() == ClientAuthType.Enabled) { - ((SSLServerSocket) this.sock).setNeedClientAuth(true); - } else { - ((SSLServerSocket) this.sock).setNeedClientAuth(false); - } + ((SSLServerSocket) this.sock).setNeedClientAuth(false); ((SSLServerSocket) this.sock).setUseClientMode(false); + ((SSLServerSocket) this.sock).setWantClientAuth(true); String []enabledCiphers = ((SipStackImpl)sipStack).getEnabledCipherSuites(); - ((SSLServerSocket) this.sock).setEnabledCipherSuites(enabledCiphers); - if(sipStack.getClientAuth() == ClientAuthType.Want || sipStack.getClientAuth() == ClientAuthType.Default) { - // we set it to true in Default case as well to keep backward compatibility and default behavior - ((SSLServerSocket) this.sock).setWantClientAuth(true); - } else { - ((SSLServerSocket) this.sock).setWantClientAuth(false); - } + ((SSLServerSocket) this.sock).setEnabledCipherSuites(enabledCiphers); + ((SSLServerSocket)this.sock).setWantClientAuth(true); + - if(logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) { - logger.logDebug("SSLServerSocket want client auth " + ((SSLServerSocket) this.sock).getWantClientAuth()); - logger.logDebug("SSLServerSocket need client auth " + ((SSLServerSocket) this.sock).getNeedClientAuth()); - } - this.isRunning = true; thread.start(); @@ -147,7 +123,7 @@ public void start() throws IOException { * Run method for the thread that gets created for each accept socket. */ public void run() { - // Accept new connectins on our socket. + // Accept new connections on our socket. while (this.isRunning) { try { @@ -170,39 +146,39 @@ public void run() { } this.nConnections++; } - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug(" waiting to accept new connection!"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug(" waiting to accept new connection!"); } Socket newsock = sock.accept(); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("Accepting new connection!"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("Accepting new connection!"); } // Note that for an incoming message channel, the // thread is already running - incomingTlsMessageChannels.add(new TLSMessageChannel(newsock, sipStack, this, "TLSMessageChannelThread-" + nConnections)); + incomingTlsMessageChannels.add(new TLSMessageChannel(newsock, sipStack, this)); } catch (SocketException ex) { if ( this.isRunning ) { - logger.logError( + sipStack.getStackLogger().logError( "Fatal - SocketException occured while Accepting connection", ex); this.isRunning = false; break; } } catch (SSLException ex) { this.isRunning = false; - logger.logError( - "Fatal - SSSLException occured while Accepting connection", ex); + sipStack.getStackLogger().logError( + "Fatal - SSLException occured while Accepting connection", ex); break; } catch (IOException ex) { // Problem accepting connection. - logger.logError("Problem Accepting Connection", ex); + sipStack.getStackLogger().logError("Problem Accepting Connection", ex); continue; } catch (Exception ex) { - logger.logError("Unexpected Exception!", ex); + sipStack.getStackLogger().logError("Unexpected Exception!", ex); } } } @@ -247,8 +223,8 @@ public synchronized void stop() { protected synchronized void remove(TLSMessageChannel tlsMessageChannel) { String key = tlsMessageChannel.getKey(); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug(Thread.currentThread() + " removing " + key); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug(Thread.currentThread() + " removing " + key); } /** May have been removed already */ @@ -268,9 +244,9 @@ public synchronized MessageChannel createMessageChannel(HostPort targetHostPort) targetHostPort.getPort(), sipStack, this); this.tlsMessageChannels.put(key, retval); retval.isCached = true; - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("key " + key); - logger.logDebug("Creating " + retval); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("key " + key); + sipStack.getStackLogger().logDebug("Creating " + retval); } return retval; } @@ -280,12 +256,12 @@ protected synchronized void cacheMessageChannel(TLSMessageChannel messageChannel String key = messageChannel.getKey(); TLSMessageChannel currentChannel = (TLSMessageChannel) tlsMessageChannels.get(key); if (currentChannel != null) { - if (logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) - logger.logDebug("Closing " + key); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Closing " + key); currentChannel.close(); } - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("Caching " + key); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Caching " + key); this.tlsMessageChannels.put(key, messageChannel); } @@ -300,9 +276,9 @@ public synchronized MessageChannel createMessageChannel(InetAddress host, int po TLSMessageChannel retval = new TLSMessageChannel(host, port, sipStack, this); this.tlsMessageChannels.put(key, retval); retval.isCached = true; - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("key " + key); - logger.logDebug("Creating " + retval); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug("key " + key); + sipStack.getStackLogger().logDebug("Creating " + retval); } return retval; } diff --git a/src/gov/nist/javax/sip/stack/UDPMessageChannel.java b/src/gov/nist/javax/sip/stack/UDPMessageChannel.java index a7e33a66a..f75cc2f10 100755 --- a/src/gov/nist/javax/sip/stack/UDPMessageChannel.java +++ b/src/gov/nist/javax/sip/stack/UDPMessageChannel.java @@ -29,9 +29,7 @@ package gov.nist.javax.sip.stack; -import gov.nist.core.CommonLogger; import gov.nist.core.InternalErrorHandler; -import gov.nist.core.LogLevels; import gov.nist.core.LogWriter; import gov.nist.core.ServerLogger; import gov.nist.core.StackLogger; @@ -39,12 +37,12 @@ import gov.nist.javax.sip.SIPConstants; import gov.nist.javax.sip.header.CSeq; import gov.nist.javax.sip.header.CallID; -import gov.nist.javax.sip.header.ContentLength; import gov.nist.javax.sip.header.From; import gov.nist.javax.sip.header.RequestLine; import gov.nist.javax.sip.header.StatusLine; import gov.nist.javax.sip.header.To; import gov.nist.javax.sip.header.Via; +import gov.nist.javax.sip.header.ViaList; import gov.nist.javax.sip.message.SIPMessage; import gov.nist.javax.sip.message.SIPRequest; import gov.nist.javax.sip.message.SIPResponse; @@ -58,10 +56,11 @@ import java.net.InetAddress; import java.net.Socket; import java.text.ParseException; +import java.util.HashSet; import java.util.Hashtable; +import java.util.TimerTask; import javax.sip.address.Hop; -import javax.sip.message.Response; /* * Kim Kirby (Keyvoice) suggested that duplicate checking should be added to the @@ -92,11 +91,12 @@ * * * - * @version 1.2 $Revision: 1.87 $ $Date: 2010-12-02 22:44:53 $ + * @version 1.2 $Revision: 1.70.2.6 $ $Date: 2010-12-02 01:41:35 $ */ public class UDPMessageChannel extends MessageChannel implements ParseExceptionListener, Runnable, RawMessageChannel { - private static StackLogger logger = CommonLogger.getLogger(UDPMessageChannel.class); + + /** * SIP Stack structure for this channel. */ @@ -133,30 +133,26 @@ public class UDPMessageChannel extends MessageChannel implements private DatagramPacket incomingPacket; private long receptionTime; - - private Thread mythread = null; - + /* - * A table that keeps track of when the last pingback was sent to a given - * remote IP address and port. This is for NAT compensation. This stays in - * the table for 1 seconds and prevents infinite loop. If a second pingback - * happens in that period of time, it will be dropped. + * A table that keeps track of when the last pingback was sent to a given remote IP address + * and port. This is for NAT compensation. This stays in the table for 1 seconds and prevents + * infinite loop. If a second pingback happens in that period of time, it will be dropped. */ - private static Hashtable pingBackRecord = new Hashtable(); - - class PingBackTimerTask extends SIPStackTimerTask { + private static Hashtable pingBackRecord = new Hashtable(); + + class PingBackTimerTask extends TimerTask { String ipAddress; int port; - + public PingBackTimerTask(String ipAddress, int port) { this.ipAddress = ipAddress; this.port = port; } - - public void runTask() { - pingBackRecord.remove(ipAddress + ":" + port); + @Override + public void run() { + pingBackRecord.remove(ipAddress + ":" + port); } - @Override public int hashCode() { return (ipAddress + ":" + port).hashCode(); @@ -172,25 +168,18 @@ public int hashCode() { * is the shared SIPStack structure * @param messageProcessor * is the creating message processor. - * @param threadName - * name that will be affected to the underlying thread */ protected UDPMessageChannel(SIPTransactionStack stack, - UDPMessageProcessor messageProcessor, String threadName) { + UDPMessageProcessor messageProcessor) { super.messageProcessor = messageProcessor; this.sipStack = stack; - // jeand : Create a new string message parser to parse the list of - // messages. - myParser = sipStack.getMessageParserFactory().createMessageParser( - sipStack); - - mythread = new Thread(this); + Thread mythread = new Thread(this); this.myAddress = messageProcessor.getIpAddress().getHostAddress(); this.myPort = messageProcessor.getPort(); - mythread.setName(threadName); + mythread.setName("UDPMessageChannelThread"); mythread.setDaemon(true); mythread.start(); @@ -214,14 +203,9 @@ protected UDPMessageChannel(SIPTransactionStack stack, super.messageProcessor = messageProcessor; this.sipStack = stack; - // jeand : Create a new string message parser to parse the list of - // messages. - myParser = sipStack.getMessageParserFactory().createMessageParser( - sipStack); - this.myAddress = messageProcessor.getIpAddress().getHostAddress(); this.myPort = messageProcessor.getPort(); - mythread = new Thread(this); + Thread mythread = new Thread(this); mythread.setDaemon(true); mythread.start(); @@ -247,15 +231,9 @@ protected UDPMessageChannel(InetAddress targetAddr, int port, this.myAddress = messageProcessor.getIpAddress().getHostAddress(); this.myPort = messageProcessor.getPort(); this.sipStack = sipStack; - // jeand : Create a new string message parser to parse the list of - // messages. - myParser = sipStack.getMessageParserFactory().createMessageParser( - sipStack); - - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - this.logger.logDebug( - "Creating message channel " + targetAddr.getHostAddress() - + "/" + port); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + this.sipStack.getStackLogger().logDebug("Creating message channel " + + targetAddr.getHostAddress() + "/" + port); } } @@ -266,26 +244,56 @@ public void run() { // Assume no thread pooling (bug fix by spierhj) ThreadAuditor.ThreadHandle threadHandle = null; - final UDPMessageProcessor udpMessageProcessor = (UDPMessageProcessor) messageProcessor; - while (true) { + // Create a new string message parser to parse the list of messages. + if (myParser == null) { + myParser = sipStack.getMessageParserFactory().createMessageParser(sipStack); + myParser.setParseExceptionListener(this); + } // messages that we write out to him. - DatagramPacket packet = null; + DatagramPacket packet; if (sipStack.threadPoolSize != -1) { + synchronized (((UDPMessageProcessor) messageProcessor).messageQueue) { + while (((UDPMessageProcessor) messageProcessor).messageQueue + .isEmpty()) { + // Check to see if we need to exit. + if (!((UDPMessageProcessor) messageProcessor).isRunning) + return; + try { + // We're part of a thread pool. Ask the auditor to + // monitor this thread. + if (threadHandle == null) { + threadHandle = sipStack.getThreadAuditor() + .addCurrentThread(); + } - if (threadHandle == null) { - threadHandle = sipStack.getThreadAuditor() - .addCurrentThread(); - } + // Send a heartbeat to the thread auditor + threadHandle.ping(); + + // Wait for packets + // Note: getPingInterval returns 0 (infinite) if the + // thread auditor is disabled. + ((UDPMessageProcessor) messageProcessor).messageQueue + .wait(threadHandle + .getPingIntervalInMillisecs()); + } catch (InterruptedException ex) { + if (!((UDPMessageProcessor) messageProcessor).isRunning) + return; + } + } + DatagramQueuedMessageDispatch dispatch = null; + try { + dispatch = (DatagramQueuedMessageDispatch) ((UDPMessageProcessor) messageProcessor).messageQueue + .poll(); + } catch (Exception e) { + if(sipStack.getStackLogger().isLoggingEnabled(LogWriter.TRACE_WARN)) { + sipStack.getStackLogger().logWarning("Error in polling the queue in dispath task, will continue with next message " + e); + } + } + if(dispatch == null) continue; + packet = dispatch.packet; - // Send a heartbeat to the thread auditor - threadHandle.ping(); - try { - packet = udpMessageProcessor.messageQueue.take().packet; - } catch (InterruptedException ex) { - if (!udpMessageProcessor.isRunning) - return; } this.incomingPacket = packet; } else { @@ -297,7 +305,7 @@ public void run() { processIncomingDataPacket(packet); } catch (Exception e) { - logger.logError( + sipStack.getStackLogger().logError( "Error while processing incoming UDP packet", e); } @@ -323,9 +331,9 @@ private void processIncomingDataPacket(DatagramPacket packet) System.arraycopy(bytes, 0, msgBytes, 0, packetLength); // Do debug logging. - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - this.logger.logDebug( - "UDPMessageChannel: processIncomingDataPacket : peerAddress = " + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + this.sipStack.getStackLogger() + .logDebug("UDPMessageChannel: processIncomingDataPacket : peerAddress = " + peerAddress.getHostAddress() + "/" + packet.getPort() + " Length = " + packetLength); @@ -334,40 +342,19 @@ private void processIncomingDataPacket(DatagramPacket packet) SIPMessage sipMessage = null; try { this.receptionTime = System.currentTimeMillis(); - sipMessage = myParser.parseSIPMessage(msgBytes, true, false, this); - /*@see Issue 292 */ - if (sipMessage instanceof SIPRequest) { - String sipVersion = ((SIPRequest)sipMessage).getRequestLine().getSipVersion(); - if (! sipVersion.equals("SIP/2.0")) { - Response versionNotSupported = ((SIPRequest) sipMessage).createResponse(Response.VERSION_NOT_SUPPORTED, "Bad version " + sipVersion); - this.sendMessage(versionNotSupported.toString().getBytes(),peerAddress,packet.getPort(),"UDP",false); - return; - } - String method = ((SIPRequest) sipMessage).getMethod(); - String cseqMethod = ((SIPRequest) sipMessage).getCSeqHeader() - .getMethod(); - - if (!method.equalsIgnoreCase(cseqMethod)) { - SIPResponse sipResponse = ((SIPRequest) sipMessage) - .createResponse(SIPResponse.BAD_REQUEST); - byte[] resp = sipResponse - .encodeAsBytes(this.getTransport()); - this.sendMessage(resp,peerAddress,packet.getPort(),"UDP",false); - return; - - } - } - + sipMessage = myParser.parseSIPMessage(msgBytes); + myParser = null; } catch (ParseException ex) { - // myParser = null; // let go of the parser reference. - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - this.logger.logDebug( - "Rejecting message ! " + new String(msgBytes)); - this.logger.logDebug( - "error message " + ex.getMessage()); - this.logger.logException(ex); + myParser = null; // let go of the parser reference. + if (sipStack.isLoggingEnabled()) { + this.sipStack.getStackLogger().logDebug("Rejecting message ! " + + new String(msgBytes)); + this.sipStack.getStackLogger().logDebug("error message " + + ex.getMessage()); + this.sipStack.getStackLogger().logException(ex); } + // JvB: send a 400 response for requests (except ACK) // Currently only UDP, @todo also other transports String msgString = new String(msgBytes, 0, packetLength); @@ -375,20 +362,21 @@ private void processIncomingDataPacket(DatagramPacket packet) String badReqRes = createBadReqRes(msgString, ex); if (badReqRes != null) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug( + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack.getStackLogger().logDebug( "Sending automatic 400 Bad Request:"); - logger.logDebug(badReqRes); + sipStack.getStackLogger().logDebug(badReqRes); } try { this.sendMessage(badReqRes.getBytes(), peerAddress, packet.getPort(), "UDP", false); } catch (IOException e) { - this.logger.logException(e); + this.sipStack.getStackLogger().logException(e); } } else { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + sipStack + .getStackLogger() .logDebug( "Could not formulate automatic 400 Bad Request"); } @@ -402,26 +390,20 @@ private void processIncomingDataPacket(DatagramPacket packet) // exit this message processor if the message did not parse. if (sipMessage == null) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - this.logger.logDebug( - "Rejecting message ! + Null message parsed."); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + this.sipStack.getStackLogger().logDebug("Rejecting message ! + Null message parsed."); } - String key = packet.getAddress().getHostAddress() + ":" - + packet.getPort(); - if (pingBackRecord.get(key) == null - && sipStack.getMinKeepAliveInterval() > 0) { + String key = packet.getAddress().getHostAddress() + ":" + packet.getPort(); + if (pingBackRecord.get(key) == null && sipStack.getMinKeepAliveInterval() > 0) { byte[] retval = "\r\n\r\n".getBytes(); - DatagramPacket keepalive = new DatagramPacket(retval, 0, - retval.length, packet.getAddress(), packet.getPort()); - PingBackTimerTask task = new PingBackTimerTask(packet - .getAddress().getHostAddress(), packet.getPort()); + DatagramPacket keepalive = new DatagramPacket(retval,0,retval.length,packet.getAddress(),packet.getPort()); + PingBackTimerTask task = new PingBackTimerTask(packet.getAddress().getHostAddress(), + packet.getPort()); this.pingBackRecord.put(key, task); - this.sipStack.getTimer().schedule(task, - sipStack.getMinKeepAliveInterval() * 1000); - ((UDPMessageProcessor) this.messageProcessor).sock - .send(keepalive); + this.sipStack.getTimer().schedule(task, sipStack.getMinKeepAliveInterval() * 1000); + ((UDPMessageProcessor)this.messageProcessor).sock.send(keepalive); } else { - logger.logDebug("Not sending ping back"); + sipStack.getStackLogger().logDebug("Not sending ping back"); } return; } @@ -429,31 +411,29 @@ private void processIncomingDataPacket(DatagramPacket packet) // Check for the required headers. if (sipMessage.getFrom() == null || sipMessage.getTo() == null || sipMessage.getCallId() == null - || sipMessage.getCSeq() == null || topMostVia == null) { + || sipMessage.getCSeq() == null + || topMostVia == null) { String badmsg = new String(msgBytes); - if (logger.isLoggingEnabled()) { - this.logger - .logError("bad message " + badmsg); - this.logger.logError( - ">>> Dropped Bad Msg " + "From = " - + sipMessage.getFrom() + "To = " - + sipMessage.getTo() + "CallId = " - + sipMessage.getCallId() + "CSeq = " - + sipMessage.getCSeq() + "Via = " - + sipMessage.getViaHeaders()); + if (sipStack.isLoggingEnabled()) { + this.sipStack.getStackLogger().logError("bad message " + badmsg); + this.sipStack.getStackLogger().logError(">>> Dropped Bad Msg " + + "From = " + sipMessage.getFrom() + "To = " + + sipMessage.getTo() + "CallId = " + + sipMessage.getCallId() + "CSeq = " + + sipMessage.getCSeq() + "Via = " + + sipMessage.getViaHeaders()); } return; } - + if(sipStack.sipEventInterceptor != null) { sipStack.sipEventInterceptor.beforeMessage(sipMessage); } // For a request first via header tells where the message // is coming from. // For response, just get the port from the packet. - if (sipMessage instanceof SIPRequest) { - Hop hop = sipStack.addressResolver.resolveAddress(topMostVia - .getHop()); + if (sipMessage instanceof SIPRequest) { + Hop hop = sipStack.addressResolver.resolveAddress(topMostVia.getHop()); this.peerPort = hop.getPort(); this.peerProtocol = topMostVia.getTransport(); @@ -464,16 +444,17 @@ private void processIncomingDataPacket(DatagramPacket packet) // Check to see if the received parameter matches // the peer address and tag it appropriately. + boolean hasRPort = topMostVia.hasParameter(Via.RPORT); if (hasRPort || !hop.getHost().equals( this.peerAddress.getHostAddress())) { - topMostVia.setParameter(Via.RECEIVED, this.peerAddress + topMostVia.setParameter(Via.RECEIVED, this.peerAddress .getHostAddress()); } if (hasRPort) { - topMostVia.setParameter(Via.RPORT, Integer + topMostVia.setParameter(Via.RPORT, Integer .toString(this.peerPacketSourcePort)); } } catch (java.text.ParseException ex1) { @@ -501,10 +482,6 @@ private void processIncomingDataPacket(DatagramPacket packet) * @param sipMessage */ public void processMessage(SIPMessage sipMessage) { - sipMessage.setRemoteAddress(this.peerAddress); - sipMessage.setRemotePort(this.getPeerPort()); - sipMessage.setLocalPort(this.getPort()); - sipMessage.setLocalAddress(this.getMessageProcessor().getIpAddress()); if (sipMessage instanceof SIPRequest) { SIPRequest sipRequest = (SIPRequest) sipMessage; @@ -512,30 +489,28 @@ public void processMessage(SIPMessage sipMessage) { // This is a request - process it. // So far so good -- we will commit this message if // all processing is OK. - if (logger.isLoggingEnabled( - ServerLogger.TRACE_MESSAGES)) { + if (sipStack.getStackLogger().isLoggingEnabled(ServerLogger.TRACE_MESSAGES)) { this.sipStack.serverLogger.logMessage(sipMessage, this .getPeerHostPort().toString(), this.getHost() + ":" + this.myPort, false, receptionTime); } - final ServerRequestInterface sipServerRequest = sipStack + ServerRequestInterface sipServerRequest = sipStack .newSIPServerRequest(sipRequest, this); // Drop it if there is no request returned if (sipServerRequest == null) { - if (logger.isLoggingEnabled()) { - logger - .logWarning( - "Null request interface returned -- dropping request"); + if (sipStack.isLoggingEnabled()) { + this.sipStack.getStackLogger() + .logWarning("Null request interface returned -- dropping request"); } + return; } - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - this.logger.logDebug( - "About to process " + sipRequest.getFirstLine() + "/" - + sipServerRequest); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + this.sipStack.getStackLogger().logDebug("About to process " + + sipRequest.getFirstLine() + "/" + sipServerRequest); try { sipServerRequest.processRequest(sipRequest, this); } finally { @@ -546,10 +521,9 @@ public void processMessage(SIPMessage sipMessage) { } } } - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - this.logger.logDebug( - "Done processing " + sipRequest.getFirstLine() + "/" - + sipServerRequest); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + this.sipStack.getStackLogger().logDebug("Done processing " + + sipRequest.getFirstLine() + "/" + sipServerRequest); // So far so good -- we will commit this message if // all processing is OK. @@ -560,9 +534,9 @@ public void processMessage(SIPMessage sipMessage) { try { sipResponse.checkHeaders(); } catch (ParseException ex) { - if (logger.isLoggingEnabled()) - logger.logError( - "Dropping Badly formatted response message >>> " + if (sipStack.isLoggingEnabled()) + sipStack.getStackLogger() + .logError("Dropping Badly formatted response message >>> " + sipResponse); return; } @@ -573,9 +547,9 @@ public void processMessage(SIPMessage sipMessage) { if (sipServerResponse instanceof SIPClientTransaction && !((SIPClientTransaction) sipServerResponse) .checkFromTag(sipResponse)) { - if (logger.isLoggingEnabled()) - logger.logError( - "Dropping response message with invalid tag >>> " + if (sipStack.isLoggingEnabled()) + sipStack.getStackLogger() + .logError("Dropping response message with invalid tag >>> " + sipResponse); return; } @@ -590,9 +564,8 @@ public void processMessage(SIPMessage sipMessage) { // Normal processing of message. } else { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - this.logger.logDebug( - "null sipServerResponse!"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + this.sipStack.getStackLogger().logDebug("null sipServerResponse!"); } } @@ -610,8 +583,8 @@ public void processMessage(SIPMessage sipMessage) { * * private final boolean isBuggyClient( SIPRequest r ) { UserAgent uah = * (UserAgent) r.getHeader( UserAgent.NAME ); if (uah!=null) { - * java.util.ListIterator i = uah.getProduct(); if (i.hasNext()) { String p - * = (String) uah.getProduct().next(); return p.startsWith( "RTC" ); } } + * java.util.ListIterator i = uah.getProduct(); if (i.hasNext()) { String p = + * (String) uah.getProduct().next(); return p.startsWith( "RTC" ); } } * return false; } */ @@ -626,21 +599,20 @@ public void processMessage(SIPMessage sipMessage) { public void handleException(ParseException ex, SIPMessage sipMessage, Class hdrClass, String header, String message) throws ParseException { - if (logger.isLoggingEnabled()) - this.logger.logException(ex); + if (sipStack.isLoggingEnabled()) + this.sipStack.getStackLogger().logException(ex); // Log the bad message for later reference. if ((hdrClass != null) && (hdrClass.equals(From.class) || hdrClass.equals(To.class) || hdrClass.equals(CSeq.class) || hdrClass.equals(Via.class) || hdrClass.equals(CallID.class) - || hdrClass.equals(ContentLength.class) || hdrClass.equals(RequestLine.class) || hdrClass .equals(StatusLine.class))) { - if (logger.isLoggingEnabled()) { - logger.logError("BAD MESSAGE!"); - logger.logError(message); - } + if (sipStack.isLoggingEnabled()) { + sipStack.getStackLogger().logError("BAD MESSAGE!"); + sipStack.getStackLogger().logError(message); + } throw ex; } else { sipMessage.addUnparsed(header); @@ -657,18 +629,15 @@ public void handleException(ParseException ex, SIPMessage sipMessage, * If there is a problem with sending the message. */ public void sendMessage(final SIPMessage sipMessage) throws IOException { - if (logger.isLoggingEnabled(LogLevels.TRACE_INFO) - && this.sipStack.isLogStackTraceOnMessageSend()) { - if (sipMessage instanceof SIPRequest - && ((SIPRequest) sipMessage).getRequestLine() != null) { + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG) && this.sipStack.isLogStackTraceOnMessageSend()) { + if ( sipMessage instanceof SIPRequest && + ((SIPRequest)sipMessage).getRequestLine() != null) { /* * We dont want to log empty trace messages. */ - this.logger.logStackTrace( - StackLogger.TRACE_INFO); + this.sipStack.getStackLogger().logStackTrace(StackLogger.TRACE_INFO); } else { - this.logger.logStackTrace( - StackLogger.TRACE_INFO); + this.sipStack.getStackLogger().logStackTrace(StackLogger.TRACE_INFO); } } @@ -685,63 +654,48 @@ public void sendMessage(final SIPMessage sipMessage) throws IOException { this.peerProtocol)) { MessageChannel messageChannel = messageProcessor .createMessageChannel(this.peerAddress, - this.peerPort); + this.peerPort); if (messageChannel instanceof RawMessageChannel) { - - final RawMessageChannel channel = (RawMessageChannel) messageChannel; - Runnable processMessageTask = new Runnable() { - public void run() { - try { - ((RawMessageChannel) channel) - .processMessage((SIPMessage) sipMessage.clone()); - } catch (Exception ex) { - if (logger - .isLoggingEnabled( - ServerLogger.TRACE_ERROR)) { - logger - .logError( - "Error self routing message cause by: ", - ex); - } - } - } - }; - getSIPStack().getSelfRoutingThreadpoolExecutor() - .execute(processMessageTask); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug( - "Self routing message"); - return; + final RawMessageChannel channel = (RawMessageChannel) messageChannel; + Runnable processMessageTask = new Runnable() { + + public void run() { + try { + ((RawMessageChannel) channel) + .processMessage((SIPMessage) sipMessage.clone()); + } catch (Exception ex) { + if (getSIPStack().getStackLogger().isLoggingEnabled(ServerLogger.TRACE_ERROR)) { + getSIPStack().getStackLogger().logError("Error self routing message cause by: ", ex); + } + } + } + }; + getSIPStack().getSelfRoutingThreadpoolExecutor().execute(processMessageTask); + + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Self routing message"); + return; } + } } - byte[] msg = sipMessage.encodeAsBytes(this.getTransport()); + byte[] msg = sipMessage.encodeAsBytes( this.getTransport() ); sendMessage(msg, peerAddress, peerPort, peerProtocol, sipMessage instanceof SIPRequest); - // we didn't run into problems while sending so let's set ports and - // addresses before feeding the message to the loggers. - sipMessage.setRemoteAddress(peerAddress); - sipMessage.setRemotePort(peerPort); - sipMessage.setLocalPort(this.getPort()); - sipMessage.setLocalAddress(this.getMessageProcessor().getIpAddress()); - } catch (IOException ex) { throw ex; } catch (Exception ex) { - logger.logError( - "An exception occured while sending message", ex); - throw new IOException("An exception occured while sending message"); + sipStack.getStackLogger().logError("An exception occured while sending message",ex); + throw new IOException( + "An exception occured while sending message"); } finally { - if (logger.isLoggingEnabled( - ServerLogger.TRACE_MESSAGES) - && !sipMessage.isNullRequest()) + if (sipStack.getStackLogger().isLoggingEnabled(ServerLogger.TRACE_MESSAGES) && !sipMessage.isNullRequest()) logMessage(sipMessage, peerAddress, peerPort, time); - else if (logger.isLoggingEnabled( - ServerLogger.TRACE_DEBUG)) - logger.logDebug("Sent EMPTY Message"); + else if (sipStack.getStackLogger().isLoggingEnabled(ServerLogger.TRACE_DEBUG)) + sipStack.getStackLogger().logDebug("Sent EMPTY Message"); } } @@ -760,25 +714,20 @@ else if (logger.isLoggingEnabled( protected void sendMessage(byte[] msg, InetAddress peerAddress, int peerPort, boolean reConnect) throws IOException { // Via is not included in the request so silently drop the reply. - if (logger.isLoggingEnabled(LogLevels.TRACE_INFO) - && this.sipStack.isLogStackTraceOnMessageSend()) { - this.logger - .logStackTrace(StackLogger.TRACE_INFO); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_INFO) && this.sipStack.isLogStackTraceOnMessageSend() ) { + this.sipStack.getStackLogger().logStackTrace(StackLogger.TRACE_INFO); } if (peerPort == -1) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - this.logger.logDebug( - getClass().getName() + ":sendMessage: Dropping reply!"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + this.sipStack.getStackLogger().logDebug(getClass().getName() + + ":sendMessage: Dropping reply!"); } throw new IOException("Receiver port not set "); } else { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - this.logger.logDebug( - "sendMessage " + peerAddress.getHostAddress() + "/" - + peerPort + "\n" + "messageSize = " - + msg.length + " message = " + new String(msg)); - this.logger - .logDebug("*******************\n"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + this.sipStack.getStackLogger().logDebug("sendMessage " + peerAddress.getHostAddress() + "/" + + peerPort + "\n" + "messageSize = " + msg.length + " message = " + new String(msg)) ; + this.sipStack.getStackLogger().logDebug("*******************\n"); } } @@ -833,17 +782,15 @@ protected void sendMessage(byte[] msg, InetAddress peerAddress, throws IOException { // Via is not included in the request so silently drop the reply. if (peerPort == -1) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - this.logger.logDebug( - getClass().getName() + ":sendMessage: Dropping reply!"); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + this.sipStack.getStackLogger().logDebug(getClass().getName() + + ":sendMessage: Dropping reply!"); } throw new IOException("Receiver port not set "); } else { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - this.logger.logDebug( - ":sendMessage " + peerAddress.getHostAddress() + "/" - + peerPort + "\n" + " messageSize = " - + msg.length); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + this.sipStack.getStackLogger().logDebug( ":sendMessage " + peerAddress.getHostAddress() + "/" + + peerPort + "\n" + " messageSize = " + msg.length); } } if (peerProtocol.compareToIgnoreCase("UDP") == 0) { @@ -859,10 +806,10 @@ protected void sendMessage(byte[] msg, InetAddress peerAddress, // bind to any interface and port. sock = sipStack.getNetworkLayer().createDatagramSocket(); } - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - this.logger.logDebug( - "sendMessage " + peerAddress.getHostAddress() + "/" - + peerPort + "\n" + new String(msg)); + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { + this.sipStack.getStackLogger().logDebug("sendMessage " + + peerAddress.getHostAddress() + "/" + peerPort + + "\n" + new String(msg)); } sock.send(reply); if (!sipStack.udpFlag) @@ -877,7 +824,7 @@ protected void sendMessage(byte[] msg, InetAddress peerAddress, // Use TCP to talk back to the sender. Socket outputSocket = sipStack.ioHandler.sendBytes( this.messageProcessor.getIpAddress(), peerAddress, - peerPort, "tcp", msg, retry, this); + peerPort, "tcp", msg, retry,this); OutputStream myOutputStream = outputSocket.getOutputStream(); myOutputStream.write(msg, 0, msg.length); myOutputStream.flush(); @@ -1020,12 +967,7 @@ public String getPeerProtocol() { * Close the message channel. */ public void close() { - if (mythread != null) { - // jeand stop the thread waiting on the queue if the processor is - // stopped - mythread.interrupt(); - mythread = null; - } } + } diff --git a/src/gov/nist/javax/sip/stack/UDPMessageProcessor.java b/src/gov/nist/javax/sip/stack/UDPMessageProcessor.java index 351189b80..e2e24c226 100755 --- a/src/gov/nist/javax/sip/stack/UDPMessageProcessor.java +++ b/src/gov/nist/javax/sip/stack/UDPMessageProcessor.java @@ -28,31 +28,18 @@ *******************************************************************************/ package gov.nist.javax.sip.stack; -import gov.nist.core.CommonLogger; -import gov.nist.core.HostPort; -import gov.nist.core.InternalErrorHandler; -import gov.nist.core.LogWriter; -import gov.nist.core.StackLogger; -import gov.nist.core.ThreadAuditor; -import gov.nist.javax.sip.SipStackImpl; - import java.io.IOException; -import java.net.DatagramPacket; -import java.net.DatagramSocket; -import java.net.InetAddress; -import java.net.SocketException; -import java.net.SocketTimeoutException; -import java.net.UnknownHostException; import java.util.LinkedList; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; +import java.net.*; + +import gov.nist.core.*; /** * Sit in a loop and handle incoming udp datagram messages. For each Datagram * packet, a new UDPMessageChannel is created (upto the max thread pool size). * Each UDP message is processed in its own thread). * - * @version 1.2 $Revision: 1.46 $ $Date: 2010-12-02 22:04:12 $ + * @version 1.2 $Revision: 1.37.2.2 $ $Date: 2010-12-02 01:41:35 $ * * @author M. Ranganathan
    * @@ -69,8 +56,6 @@ * performance. */ public class UDPMessageProcessor extends MessageProcessor { - - private static StackLogger logger = CommonLogger.getLogger(UDPMessageProcessor.class); /** * The Mapped port (in case STUN suport is enabled) */ @@ -79,12 +64,7 @@ public class UDPMessageProcessor extends MessageProcessor { /** * Incoming messages are queued here. */ - protected BlockingQueue messageQueue; - - /** - * Auditing taks that checks for outdated requests in the queue - */ - BlockingQueueDispatchAuditor congestionAuditor; + protected LinkedList messageQueue; /** * A list of message channels that we have started. @@ -108,8 +88,6 @@ public class UDPMessageProcessor extends MessageProcessor { private static final int LOWAT=2500; - private int maxMessageSize = SipStackImpl.MAX_DATAGRAM_SIZE; - /** * Constructor. * @@ -121,18 +99,8 @@ protected UDPMessageProcessor(InetAddress ipAddress, super(ipAddress, port, "udp",sipStack); this.sipStack = sipStack; - if(sipStack.getMaxMessageSize() < SipStackImpl.MAX_DATAGRAM_SIZE && sipStack.getMaxMessageSize() > 0) { - this.maxMessageSize = sipStack.getMaxMessageSize(); - } - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("Max Message size is " + maxMessageSize); - } - this.messageQueue = new LinkedBlockingQueue(); - if(sipStack.stackCongenstionControlTimeout>0) { - this.congestionAuditor = new BlockingQueueDispatchAuditor(this.messageQueue); - this.congestionAuditor.setTimeout(sipStack.stackCongenstionControlTimeout); - this.congestionAuditor.start(2000); - } + + this.messageQueue = new LinkedList(); this.port = port; try { @@ -163,7 +131,7 @@ protected UDPMessageProcessor(InetAddress ipAddress, } } - + BlockingQueueDispatchAuditor audit; /** * Get port on which to listen for incoming stuff. @@ -180,9 +148,15 @@ public int getPort() { public void start() throws IOException { - this.isRunning = true; - Thread thread = new Thread(this); - thread.setDaemon(true); + this.isRunning = true; + if(getSIPStack().stackCongestionControlTimeout>0) { + this.audit = new BlockingQueueDispatchAuditor(this.messageQueue); + this.audit.setLogger(getSIPStack().getStackLogger()); + this.audit.setTimeout(getSIPStack().stackCongestionControlTimeout); + this.audit.start(2000); + } + Thread thread = new Thread(this); + thread.setDaemon(true); // Issue #32 on java.net thread.setName("UDPMessageProcessorThread"); // Issue #184 @@ -201,7 +175,7 @@ public void run() { if (sipStack.threadPoolSize != -1) { for (int i = 0; i < sipStack.threadPoolSize; i++) { UDPMessageChannel channel = new UDPMessageChannel(sipStack, - this, ((SipStackImpl)sipStack).getStackName() + "-UDPMessageChannelThread-" + i); + this); this.messageChannels.add(channel); } @@ -217,11 +191,11 @@ public void run() { // Let the thread auditor know we're up and running threadHandle.ping(); - int bufsize = this.maxMessageSize; + int bufsize = sock.getReceiveBufferSize(); byte message[] = new byte[bufsize]; DatagramPacket packet = new DatagramPacket(message, bufsize); sock.receive(packet); - + // Count of # of packets in process. // this.useCount++; if (sipStack.threadPoolSize != -1) { @@ -231,27 +205,35 @@ public void run() { // condition you will have to call notifyAll instead of // notify below. - this.messageQueue.offer(new DatagramQueuedMessageDispatch(packet, System.currentTimeMillis())); - + synchronized (this.messageQueue) { + // was addLast + this.messageQueue.add(new DatagramQueuedMessageDispatch(packet, System.currentTimeMillis())); + this.messageQueue.notify(); + } } else { new UDPMessageChannel(sipStack, this, packet); } } catch (SocketTimeoutException ex) { // This socket timeout alows us to ping the thread auditor periodically } catch (SocketException ex) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + getSIPStack().getStackLogger() .logDebug("UDPMessageProcessor: Stopping"); isRunning = false; + // The notifyAll should be in a synchronized block. + // ( bug report by Niklas Uhrberg ). + synchronized (this.messageQueue) { + this.messageQueue.notifyAll(); + } } catch (IOException ex) { isRunning = false; ex.printStackTrace(); - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + getSIPStack().getStackLogger() .logDebug("UDPMessageProcessor: Got an IO Exception"); } catch (Exception ex) { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger + if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) + getSIPStack().getStackLogger() .logDebug("UDPMessageProcessor: Unexpected Exception - quitting"); InternalErrorHandler.handleException(ex); return; @@ -264,15 +246,15 @@ public void run() { * messages. */ public void stop() { + synchronized (this.messageQueue) { this.isRunning = false; - sock.close(); - // closing the channels - for (Object messageChannel : messageChannels) { - ((MessageChannel)messageChannel).close(); - } - if(sipStack.stackCongenstionControlTimeout > 0 && congestionAuditor != null) { - this.congestionAuditor.stop(); - } + this.messageQueue.notifyAll(); + sock.close(); + if(this.audit != null) { + this.audit.stop(); + } + + } } /** @@ -325,14 +307,16 @@ public boolean isSecure() { * UDP can handle a message as large as the MAX_DATAGRAM_SIZE. */ public int getMaximumMessageSize() { - return sipStack.getReceiveUdpBufferSize(); + return 8*1024; } /** * Return true if there are any messages in use. */ public boolean inUse() { - return !messageQueue.isEmpty(); + synchronized (messageQueue) { + return messageQueue.size() != 0; + } } } diff --git a/src/gov/nist/javax/sip/stack/sctp/SCTPMessageChannel.java b/src/gov/nist/javax/sip/stack/sctp/SCTPMessageChannel.java index c7933b980..91693900e 100644 --- a/src/gov/nist/javax/sip/stack/sctp/SCTPMessageChannel.java +++ b/src/gov/nist/javax/sip/stack/sctp/SCTPMessageChannel.java @@ -1,9 +1,6 @@ package gov.nist.javax.sip.stack.sctp; -import gov.nist.core.CommonLogger; -import gov.nist.core.LogWriter; import gov.nist.core.ServerLogger; -import gov.nist.core.StackLogger; import gov.nist.javax.sip.header.CSeq; import gov.nist.javax.sip.header.CallID; import gov.nist.javax.sip.header.From; @@ -37,234 +34,228 @@ /** * SCTP message channel - * + * * @author Jeroen van Bemmel */ -final class SCTPMessageChannel extends MessageChannel - implements ParseExceptionListener, Comparable { - private static StackLogger logger = CommonLogger.getLogger(SCTPMessageChannel.class); - - private final SCTPMessageProcessor processor; - private InetSocketAddress peerAddress; // destination address - private InetSocketAddress peerSrcAddress; - - private final SctpChannel channel; - private final SelectionKey key; - - private final MessageInfo messageInfo; // outgoing SCTP options, cached - private long rxTime; //< Time first byte of message was received - - // XXX Hardcoded, enough? TODO make stack property - private final ByteBuffer rxBuffer = ByteBuffer.allocateDirect( 10000 ); - - private final StringMsgParser parser = new StringMsgParser(); // Parser instance - - // for outgoing connections - SCTPMessageChannel( SCTPMessageProcessor p, InetSocketAddress dest ) throws IOException { - this.processor = p; - this.messageProcessor = p; // super class - this.peerAddress = dest; - this.peerSrcAddress = dest; // assume the same, override upon packet - - this.messageInfo = MessageInfo.createOutgoing( dest, 0 ); - messageInfo.unordered( true ); - - this.channel = SctpChannel.open( dest, 1, 1 ); - channel.configureBlocking( false ); - this.key = processor.registerChannel( this, channel ); - } - - // For incoming connections - SCTPMessageChannel( SCTPMessageProcessor p, SctpChannel c ) throws IOException { - this.processor = p; - this.messageProcessor = p; // super class - SocketAddress a = c.getRemoteAddresses().iterator().next(); - this.peerAddress = (InetSocketAddress) a; - this.peerSrcAddress = (InetSocketAddress) a; - this.messageInfo = MessageInfo.createOutgoing( a, 0 ); - messageInfo.unordered( true ); - - this.channel = c; - channel.configureBlocking( false ); - this.key = processor.registerChannel( this, channel ); - } - - @Override - public void close() { - try { - this.key.cancel(); - channel.close(); - } catch (IOException e) { - e.printStackTrace(); - } finally { - processor.removeChannel( this ); - } - } - - void closeNoRemove() { - try { - this.key.cancel(); - channel.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - @Override - public String getKey() { - // Note: could put this in super class - return getKey( this.getPeerInetAddress(), this.getPeerPort(), this.getTransport() ); - } - - @Override - public String getPeerAddress() { - return peerAddress.getHostString(); - } - - @Override - protected InetAddress getPeerInetAddress() { - return peerAddress.getAddress(); - } - - @Override - public InetAddress getPeerPacketSourceAddress() { - return peerSrcAddress.getAddress(); - } - - @Override - public int getPeerPacketSourcePort() { - return peerSrcAddress.getPort(); - } - - @Override - public int getPeerPort() { - return peerAddress.getPort(); - } - - @Override - protected String getPeerProtocol() { - return "sctp"; // else something really is weird ;) - } - - @Override - public SIPTransactionStack getSIPStack() { - return processor.getSIPStack(); - } - - @Override - public String getTransport() { - return "sctp"; - } - - @Override - public String getViaHost() { - return processor.getSavedIpAddress(); - } - - @Override - public int getViaPort() { - return processor.getPort(); - } - - @Override - public boolean isReliable() { - return true; - } - - @Override - public boolean isSecure() { - return false; - } - - @Override - public void sendMessage(SIPMessage sipMessage) throws IOException { - byte[] msg = sipMessage.encodeAsBytes( this.getTransport() ); - this.sendMessage( msg, this.getPeerInetAddress(), this.getPeerPort(), false ); - } - - @Override - protected void sendMessage(byte[] message, InetAddress receiverAddress, - int receiverPort, boolean reconnectFlag) throws IOException { - - assert( receiverAddress.equals( peerAddress.getAddress() ) ); - assert( receiverPort == peerAddress.getPort() ); - - // XX ignoring 'reconnect' for now - int nBytes = channel.send( ByteBuffer.wrap(message), messageInfo ); - if ( logger.isLoggingEnabled( LogWriter.TRACE_DEBUG ) ) { - logger.logDebug( "SCTP bytes sent:" + nBytes ); - } - } - - /** - * Called by SCTPMessageProcessor when one or more bytes are available for reading - * @throws IOException - */ - void readMessages() throws IOException { - if (rxTime==0) { - rxTime = System.currentTimeMillis(); - } - MessageInfo info = channel.receive( rxBuffer, null, null ); - if (info==null) { - // happens a lot, some sort of keep-alive? - if ( logger.isLoggingEnabled( LogWriter.TRACE_DEBUG ) ) { - logger.logDebug( "SCTP read-event but no message" ); - } - return; - } else if (info.bytes()==-1) { - logger.logWarning( "SCTP peer closed, closing too..." ); - this.close(); - return; - } else if ( !info.isComplete() ) { - if ( logger.isLoggingEnabled( LogWriter.TRACE_DEBUG ) ) { - logger.logDebug( "SCTP incomplete message; bytes=" + info.bytes() ); - } - return; - } else { - if ( logger.isLoggingEnabled( LogWriter.TRACE_DEBUG ) ) { - logger.logDebug( "SCTP message now complete; bytes=" + info.bytes() ); - } - } - - // Assume it is 1 full message, not multiple messages - byte[] msg = new byte[ rxBuffer.position() ]; - rxBuffer.flip(); - rxBuffer.get( msg ); - rxBuffer.compact(); - try { - SIPMessage m = parser.parseSIPMessage( msg, true, true, this ); - this.processMessage( m, rxTime ); - rxTime = 0; // reset for next message - } catch (ParseException e) { - logger.logException( e ); - if ( logger.isLoggingEnabled( LogWriter.TRACE_DEBUG ) ) { - logger.logDebug( "Invalid message bytes=" + msg.length + ":" + new String(msg) ); - } - this.close(); - throw new IOException( "Error parsing incoming SCTP message", e ); - } - } - - /** +final class SCTPMessageChannel extends MessageChannel + implements ParseExceptionListener, Comparable { + + private final SCTPMessageProcessor processor; + private InetSocketAddress peerAddress; // destination address + private InetSocketAddress peerSrcAddress; + + private final SctpChannel channel; + private final SelectionKey key; + + private final MessageInfo messageInfo; // outgoing SCTP options, cached + private long rxTime; //< Time first byte of message was received + + // XXX Hardcoded, enough? TODO make stack property + private final ByteBuffer rxBuffer = ByteBuffer.allocateDirect( 10000 ); + + private final StringMsgParser parser = new StringMsgParser( this ); // Parser instance + + // for outgoing connections + SCTPMessageChannel( SCTPMessageProcessor p, InetSocketAddress dest ) throws IOException { + this.processor = p; + this.messageProcessor = p; // super class + this.peerAddress = dest; + this.peerSrcAddress = dest; // assume the same, override upon packet + + this.messageInfo = MessageInfo.createOutgoing( dest, 0 ); + messageInfo.unordered( true ); + + this.channel = SctpChannel.open( dest, 1, 1 ); + channel.configureBlocking( false ); + this.key = processor.registerChannel( this, channel ); + } + + // For incoming connections + SCTPMessageChannel( SCTPMessageProcessor p, SctpChannel c ) throws IOException { + this.processor = p; + this.messageProcessor = p; // super class + SocketAddress a = c.getRemoteAddresses().iterator().next(); + this.peerAddress = (InetSocketAddress) a; + this.peerSrcAddress = (InetSocketAddress) a; + this.messageInfo = MessageInfo.createOutgoing( a, 0 ); + messageInfo.unordered( true ); + + this.channel = c; + channel.configureBlocking( false ); + this.key = processor.registerChannel( this, channel ); + } + + @Override + public void close() { + try { + this.key.cancel(); + channel.close(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + processor.removeChannel( this ); + } + } + + void closeNoRemove() { + try { + this.key.cancel(); + channel.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public String getKey() { + // Note: could put this in super class + return getKey( this.getPeerInetAddress(), this.getPeerPort(), this.getTransport() ); + } + + @Override + public String getPeerAddress() { + return peerAddress.getHostString(); + } + + @Override + protected InetAddress getPeerInetAddress() { + return peerAddress.getAddress(); + } + + @Override + public InetAddress getPeerPacketSourceAddress() { + return peerSrcAddress.getAddress(); + } + + @Override + public int getPeerPacketSourcePort() { + return peerSrcAddress.getPort(); + } + + @Override + public int getPeerPort() { + return peerAddress.getPort(); + } + + @Override + protected String getPeerProtocol() { + return "sctp"; // else something really is weird ;) + } + + @Override + public SIPTransactionStack getSIPStack() { + return processor.getSIPStack(); + } + + @Override + public String getTransport() { + return "sctp"; + } + + @Override + public String getViaHost() { + return processor.getSavedIpAddress(); + } + + @Override + public int getViaPort() { + return processor.getPort(); + } + + @Override + public boolean isReliable() { + return true; + } + + @Override + public boolean isSecure() { + return false; + } + + @Override + public void sendMessage(SIPMessage sipMessage) throws IOException { + byte[] msg = sipMessage.encodeAsBytes( this.getTransport() ); + this.sendMessage( msg, this.getPeerInetAddress(), this.getPeerPort(), false ); + } + + @Override + protected void sendMessage(byte[] message, InetAddress receiverAddress, + int receiverPort, boolean reconnectFlag) throws IOException { + + assert( receiverAddress.equals( peerAddress.getAddress() ) ); + assert( receiverPort == peerAddress.getPort() ); + + // XX ignoring 'reconnect' for now + int nBytes = channel.send( ByteBuffer.wrap(message), messageInfo ); + if ( getSIPStack().getStackLogger().isLoggingEnabled( ServerLogger.TRACE_DEBUG ) ) { + getSIPStack().getStackLogger().logDebug( "SCTP bytes sent:" + nBytes ); + } + } + + /** + * Called by SCTPMessageProcessor when one or more bytes are available for reading + * @throws IOException + */ + void readMessages() throws IOException { + if (rxTime==0) { + rxTime = System.currentTimeMillis(); + } + MessageInfo info = channel.receive( rxBuffer, null, null ); + if (info==null) { + // happens a lot, some sort of keep-alive? + if ( getSIPStack().getStackLogger().isLoggingEnabled( ServerLogger.TRACE_DEBUG ) ) { + getSIPStack().getStackLogger().logDebug( "SCTP read-event but no message" ); + } + return; + } else if (info.bytes()==-1) { + getSIPStack().getStackLogger().logWarning( "SCTP peer closed, closing too..." ); + this.close(); + return; + } else if ( !info.isComplete() ) { + if ( getSIPStack().getStackLogger().isLoggingEnabled( ServerLogger.TRACE_DEBUG ) ) { + getSIPStack().getStackLogger().logDebug( "SCTP incomplete message; bytes=" + info.bytes() ); + } + return; + } else { + if ( getSIPStack().getStackLogger().isLoggingEnabled( ServerLogger.TRACE_DEBUG ) ) { + getSIPStack().getStackLogger().logDebug( "SCTP message now complete; bytes=" + info.bytes() ); + } + } + + // Assume it is 1 full message, not multiple messages + byte[] msg = new byte[ rxBuffer.position() ]; + rxBuffer.flip(); + rxBuffer.get( msg ); + rxBuffer.compact(); + try { + SIPMessage m = parser.parseSIPMessage( msg ); + this.processMessage( m, rxTime ); + rxTime = 0; // reset for next message + } catch (ParseException e) { + getSIPStack().getStackLogger().logException( e ); + if ( getSIPStack().getStackLogger().isLoggingEnabled( ServerLogger.TRACE_DEBUG ) ) { + getSIPStack().getStackLogger().logDebug( "Invalid message bytes=" + msg.length + ":" + new String(msg) ); + } + this.close(); + throw new IOException( "Error parsing incoming SCTP message", e ); + } + } + + /** * Actually proces the parsed message. * @param sipMessage - * + * * JvB: copied from UDPMessageChannel, TODO restructure */ private void processMessage( SIPMessage sipMessage, long rxTime ) { - SIPTransactionStack sipStack = processor.getSIPStack(); - sipMessage.setRemoteAddress(this.peerAddress.getAddress()); - sipMessage.setRemotePort(this.getPeerPort()); - sipMessage.setLocalPort(this.getPort()); - sipMessage.setLocalAddress(this.getMessageProcessor().getIpAddress()); - + SIPTransactionStack sipStack = processor.getSIPStack(); if (sipMessage instanceof SIPRequest) { SIPRequest sipRequest = (SIPRequest) sipMessage; // This is a request - process it. // So far so good -- we will commit this message if // all processing is OK. - if (logger.isLoggingEnabled(ServerLogger.TRACE_MESSAGES)) { + if (sipStack.getStackLogger().isLoggingEnabled(ServerLogger.TRACE_MESSAGES)) { sipStack.getServerLogger().logMessage(sipMessage, this .getPeerHostPort().toString(), this.getHost() + ":" + this.getPort(), false, rxTime); @@ -273,18 +264,17 @@ private void processMessage( SIPMessage sipMessage, long rxTime ) { .newSIPServerRequest(sipRequest, this); // Drop it if there is no request returned if (sipServerRequest == null) { - if (logger.isLoggingEnabled()) { - logger + if (sipStack.isLoggingEnabled()) { + sipStack.getStackLogger() .logWarning("Null request interface returned -- dropping request"); } return; } - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("About to process " + if (sipStack.isLoggingEnabled()) + sipStack.getStackLogger().logDebug("About to process " + sipRequest.getFirstLine() + "/" + sipServerRequest); - } try { sipServerRequest.processRequest(sipRequest, this); } finally { @@ -295,8 +285,8 @@ private void processMessage( SIPMessage sipMessage, long rxTime ) { } } } - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) - logger.logDebug("Done processing " + if (sipStack.isLoggingEnabled()) + sipStack.getStackLogger().logDebug("Done processing " + sipRequest.getFirstLine() + "/" + sipServerRequest); // So far so good -- we will commit this message if @@ -308,8 +298,8 @@ private void processMessage( SIPMessage sipMessage, long rxTime ) { try { sipResponse.checkHeaders(); } catch (ParseException ex) { - if (logger.isLoggingEnabled()) - logger + if (sipStack.isLoggingEnabled()) + sipStack.getStackLogger() .logError("Dropping Badly formatted response message >>> " + sipResponse); return; @@ -321,8 +311,8 @@ private void processMessage( SIPMessage sipMessage, long rxTime ) { if (sipServerResponse instanceof SIPClientTransaction && !((SIPClientTransaction) sipServerResponse) .checkFromTag(sipResponse)) { - if (logger.isLoggingEnabled()) - logger + if (sipStack.isLoggingEnabled()) + sipStack.getStackLogger() .logError("Dropping response message with invalid tag >>> " + sipResponse); return; @@ -338,14 +328,14 @@ private void processMessage( SIPMessage sipMessage, long rxTime ) { // Normal processing of message. } else { - if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) { - logger.logDebug("null sipServerResponse!"); + if (sipStack.isLoggingEnabled()) { + sipStack.getStackLogger().logDebug("null sipServerResponse!"); } } } } - + /** * Implementation of the ParseExceptionListener interface. * @@ -353,14 +343,14 @@ private void processMessage( SIPMessage sipMessage, long rxTime ) { * Exception that is given to us by the parser. * @throws ParseException * If we choose to reject the header or message. - * + * * JvB: copied from UDPMessageChannel, TODO restructure! */ public void handleException(ParseException ex, SIPMessage sipMessage, Class hdrClass, String header, String message) throws ParseException { if (getSIPStack().isLoggingEnabled()) - this.logger.logException(ex); + this.getSIPStack().getStackLogger().logException(ex); // Log the bad message for later reference. if ((hdrClass != null) && (hdrClass.equals(From.class) || hdrClass.equals(To.class) @@ -369,21 +359,20 @@ public void handleException(ParseException ex, SIPMessage sipMessage, || hdrClass.equals(CallID.class) || hdrClass.equals(RequestLine.class) || hdrClass .equals(StatusLine.class))) { - logger.logError("BAD MESSAGE!"); - logger.logError(message); + getSIPStack().getStackLogger().logError("BAD MESSAGE!"); + getSIPStack().getStackLogger().logError(message); throw ex; } else { sipMessage.addUnparsed(header); } } - + public int compareTo(SCTPMessageChannel o) { - return this.hashCode() - o.hashCode(); + return this.hashCode() - o.hashCode(); } - + @Override protected void uncache() { - processor.removeChannel( this ); + // TODO Auto-generated method stub } - } diff --git a/src/gov/nist/javax/sip/stack/timers/DefaultSipTimer.java b/src/gov/nist/javax/sip/stack/timers/DefaultSipTimer.java deleted file mode 100644 index 70cc573a5..000000000 --- a/src/gov/nist/javax/sip/stack/timers/DefaultSipTimer.java +++ /dev/null @@ -1,148 +0,0 @@ -/* -* Conditions Of Use -* -* This software was developed by employees of the National Institute of -* Standards and Technology (NIST), an agency of the Federal Government. -* Pursuant to title 15 Untied States Code Section 105, works of NIST -* employees are not subject to copyright protection in the United States -* and are considered to be in the public domain. As a result, a formal -* license is not needed to use the software. -* -* This software is provided by NIST as a service and is expressly -* provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED -* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT -* AND DATA ACCURACY. NIST does not warrant or make any representations -* regarding the use of the software or the results thereof, including but -* not limited to the correctness, accuracy, reliability or usefulness of -* the software. -* -* Permission to use this software is contingent upon your acceptance -* of the terms of this agreement -* -* . -* -*/ -package gov.nist.javax.sip.stack.timers; - -import gov.nist.core.CommonLogger; -import gov.nist.core.StackLogger; -import gov.nist.javax.sip.SipStackImpl; -import gov.nist.javax.sip.stack.SIPStackTimerTask; -import gov.nist.javax.sip.stack.SIPTransactionStack; - -import java.util.Properties; -import java.util.Timer; -import java.util.TimerTask; -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * Default SIP Timer implementation based on java.util.Timer - * - * @author jean.deruelle@gmail.com - * - */ -public class DefaultSipTimer extends Timer implements SipTimer { - private static StackLogger logger = CommonLogger.getLogger(DefaultSipTimer.class); - - protected AtomicBoolean started = new AtomicBoolean(false); - protected SipStackImpl sipStackImpl; - - private class DefaultTimerTask extends TimerTask { - private SIPStackTimerTask task; - - public DefaultTimerTask(SIPStackTimerTask task) { - this.task= task; - task.setSipTimerTask(this); - } - - public void run() { - try { - // task can be null if it has been cancelled - if(task != null) { - task.runTask(); - } - } catch (Throwable e) { - System.out.println("SIP stack timer task failed due to exception:"); - e.printStackTrace(); - } - } - - public boolean cancel() { - if(task != null) { - task.cleanUpBeforeCancel(); - task = null; - } - return super.cancel(); - } - } - - /* - * (non-Javadoc) - * @see gov.nist.javax.sip.stack.timers.SipTimer#schedule(gov.nist.javax.sip.stack.SIPStackTimerTask, long) - */ - public boolean schedule(SIPStackTimerTask task, long delay) { - if(!started.get()) { - throw new IllegalStateException("The SIP Stack Timer has been stopped, no new tasks can be scheduled !"); - } - super.schedule(new DefaultTimerTask(task), delay); - return true; - } - - /* - * (non-Javadoc) - * @see gov.nist.javax.sip.stack.timers.SipTimer#scheduleWithFixedDelay(gov.nist.javax.sip.stack.SIPStackTimerTask, long, long) - */ - public boolean scheduleWithFixedDelay(SIPStackTimerTask task, long delay, - long period) { - if(!started.get()) { - throw new IllegalStateException("The SIP Stack Timer has been stopped, no new tasks can be scheduled !"); - } - super.schedule(new DefaultTimerTask(task), delay, period); - return true; - } - - /* - * (non-Javadoc) - * @see gov.nist.javax.sip.stack.timers.SipTimer#cancel(gov.nist.javax.sip.stack.SIPStackTimerTask) - */ - public boolean cancel(SIPStackTimerTask task) { - return ((TimerTask)task.getSipTimerTask()).cancel(); - } - - /* - * (non-Javadoc) - * @see gov.nist.javax.sip.stack.timers.SipTimer#start(gov.nist.javax.sip.SipStackImpl, java.util.Properties) - */ - public void start(SipStackImpl sipStack, Properties configurationProperties) { - sipStackImpl= sipStack; - // don't need the properties so nothing to see here - started.set(true); - if(logger.isLoggingEnabled(StackLogger.TRACE_INFO)) { - logger.logInfo("the sip stack timer " + this.getClass().getName() + " has been started"); - } - } - - /* - * (non-Javadoc) - * @see gov.nist.javax.sip.stack.timers.SipTimer#stop() - */ - public void stop() { - started.set(false); - cancel(); - logger.logStackTrace(StackLogger.TRACE_DEBUG); - if(logger.isLoggingEnabled(StackLogger.TRACE_INFO)) { - logger.logInfo("the sip stack timer " + this.getClass().getName() + " has been stopped"); - } - } - - /* - * (non-Javadoc) - * @see gov.nist.javax.sip.stack.timers.SipTimer#isStarted() - */ - public boolean isStarted() { - return started.get(); - } - - -} diff --git a/src/gov/nist/javax/sip/stack/timers/ScheduledExecutorSipTimer.java b/src/gov/nist/javax/sip/stack/timers/ScheduledExecutorSipTimer.java deleted file mode 100644 index 64cd2adbc..000000000 --- a/src/gov/nist/javax/sip/stack/timers/ScheduledExecutorSipTimer.java +++ /dev/null @@ -1,156 +0,0 @@ -/* -* Conditions Of Use -* -* This software was developed by employees of the National Institute of -* Standards and Technology (NIST), an agency of the Federal Government. -* Pursuant to title 15 Untied States Code Section 105, works of NIST -* employees are not subject to copyright protection in the United States -* and are considered to be in the public domain. As a result, a formal -* license is not needed to use the software. -* -* This software is provided by NIST as a service and is expressly -* provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED -* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT -* AND DATA ACCURACY. NIST does not warrant or make any representations -* regarding the use of the software or the results thereof, including but -* not limited to the correctness, accuracy, reliability or usefulness of -* the software. -* -* Permission to use this software is contingent upon your acceptance -* of the terms of this agreement -* -* . -* -*/ -package gov.nist.javax.sip.stack.timers; - -import gov.nist.core.CommonLogger; -import gov.nist.core.StackLogger; -import gov.nist.javax.sip.SipStackImpl; -import gov.nist.javax.sip.stack.SIPStackTimerTask; - -import java.util.Properties; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -/** - * Implementation of the SIP Timer based on java.util.concurrent.ScheduledThreadPoolExecutor - * Seems to perform - * - * @author jean.deruelle@gmail.com - * - */ -public class ScheduledExecutorSipTimer implements SipTimer { - private static StackLogger logger = CommonLogger.getLogger(ScheduledExecutorSipTimer.class); - protected SipStackImpl sipStackImpl; - ScheduledThreadPoolExecutor threadPoolExecutor; - // Counts the number of cancelled tasks - private volatile int numCancelled = 0; - - public ScheduledExecutorSipTimer() { - threadPoolExecutor = new ScheduledThreadPoolExecutor(1); - } - - /* (non-Javadoc) - * @see gov.nist.javax.sip.stack.timers.SipTimer#stop() - */ - public void stop() { - threadPoolExecutor.shutdown(); - logger.logStackTrace(StackLogger.TRACE_DEBUG); - if(logger.isLoggingEnabled(StackLogger.TRACE_INFO)) { - logger.logInfo("the sip stack timer " + this.getClass().getName() + " has been stopped"); - } - } - - /* (non-Javadoc) - * @see gov.nist.javax.sip.stack.timers.SipTimer#schedule(gov.nist.javax.sip.stack.SIPStackTimerTask, long) - */ - public boolean schedule(SIPStackTimerTask task, long delay) { - if(threadPoolExecutor.isShutdown()) { - throw new IllegalStateException("The SIP Stack Timer has been stopped, no new tasks can be scheduled !"); - } - ScheduledFuture future = threadPoolExecutor.schedule(new ScheduledSipTimerTask(task), delay, TimeUnit.MILLISECONDS); - task.setSipTimerTask(future); - return true; - } - - /* - * (non-Javadoc) - * @see gov.nist.javax.sip.stack.timers.SipTimer#scheduleWithFixedDelay(gov.nist.javax.sip.stack.SIPStackTimerTask, long, long) - */ - public boolean scheduleWithFixedDelay(SIPStackTimerTask task, long delay, - long period) { - if(threadPoolExecutor.isShutdown()) { - throw new IllegalStateException("The SIP Stack Timer has been stopped, no new tasks can be scheduled !"); - } - ScheduledFuture future = threadPoolExecutor.scheduleWithFixedDelay(new ScheduledSipTimerTask(task), delay, period, TimeUnit.MILLISECONDS); - task.setSipTimerTask(future); - return true; - } - - /* - * (non-Javadoc) - * @see gov.nist.javax.sip.stack.timers.SipTimer#start(gov.nist.javax.sip.SipStackImpl, java.util.Properties) - */ - public void start(SipStackImpl sipStack, Properties configurationProperties) { - sipStackImpl= sipStack; - // TODO have a param in the stack properties to set the number of thread for the timer executor - threadPoolExecutor.prestartAllCoreThreads(); - if(logger.isLoggingEnabled(StackLogger.TRACE_INFO)) { - logger.logInfo("the sip stack timer " + this.getClass().getName() + " has been started"); - } - } - /* - * (non-Javadoc) - * @see gov.nist.javax.sip.stack.timers.SipTimer#cancel(gov.nist.javax.sip.stack.SIPStackTimerTask) - */ - public boolean cancel(SIPStackTimerTask task) { - boolean cancelled = false; - ScheduledFuture sipTimerTask = (ScheduledFuture) task.getSipTimerTask(); - if(sipTimerTask != null) { - task.cleanUpBeforeCancel(); - task.setSipTimerTask(null); - threadPoolExecutor.remove((Runnable)sipTimerTask); - cancelled = sipTimerTask.cancel(false); - } - // Purge is expensive when called frequently, only call it every now and then. - // We do not sync the numCancelled variable. We dont care about correctness of - // the number, and we will still call purge rought once on every 100 cancels. - numCancelled++; - if(numCancelled % 50 == 0) { - threadPoolExecutor.purge(); - } - return cancelled; - } - - private class ScheduledSipTimerTask implements Runnable { - private SIPStackTimerTask task; - - public ScheduledSipTimerTask(SIPStackTimerTask task) { - this.task= task; - } - - public void run() { - try { - // task can be null if it has been cancelled - if(task != null) { - task.runTask(); - } - } catch (Throwable e) { - System.out.println("SIP stack timer task failed due to exception:"); - e.printStackTrace(); - } - } - } - - /* - * (non-Javadoc) - * @see gov.nist.javax.sip.stack.timers.SipTimer#isStarted() - */ - public boolean isStarted() { - return threadPoolExecutor.isTerminated(); - } - -} diff --git a/src/gov/nist/javax/sip/stack/timers/SipTimer.java b/src/gov/nist/javax/sip/stack/timers/SipTimer.java deleted file mode 100644 index f6534b9bc..000000000 --- a/src/gov/nist/javax/sip/stack/timers/SipTimer.java +++ /dev/null @@ -1,84 +0,0 @@ -/* -* Conditions Of Use -* -* This software was developed by employees of the National Institute of -* Standards and Technology (NIST), an agency of the Federal Government. -* Pursuant to title 15 Untied States Code Section 105, works of NIST -* employees are not subject to copyright protection in the United States -* and are considered to be in the public domain. As a result, a formal -* license is not needed to use the software. -* -* This software is provided by NIST as a service and is expressly -* provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED -* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT -* AND DATA ACCURACY. NIST does not warrant or make any representations -* regarding the use of the software or the results thereof, including but -* not limited to the correctness, accuracy, reliability or usefulness of -* the software. -* -* Permission to use this software is contingent upon your acceptance -* of the terms of this agreement -* -* . -* -*/ -package gov.nist.javax.sip.stack.timers; - -import gov.nist.javax.sip.SipStackImpl; -import gov.nist.javax.sip.stack.SIPStackTimerTask; - -import java.util.Properties; - -/** - * Interface to implement to plug a new Timer implementation. currently the ones provided with the stack are based on java.util.Timer - * or java.util.concurrent.ScheduledThreadPoolExecutor - * - * @author jean.deruelle@gmail.com - * - */ -public interface SipTimer { - - /** - * Schedule a new SIPStackTimerTask after the specified delay - * @param task the task to schedule - * @param delay the delay in milliseconds to schedule the task - * @return true if the task was correctly scheduled, false otherwise - */ - boolean schedule(SIPStackTimerTask task, long delay); - - /** - * Schedule a new SIPStackTimerTask after the specified delay - * @param task the task to schedule - * @param delay the delay in milliseconds to schedule the task - * @param period the period to run the task after it has been first scheduled - * @return true if the task was correctly scheduled, false otherwise - */ - boolean scheduleWithFixedDelay(SIPStackTimerTask task, long delay, long period); - - /** - * Stop the Timer (called when the stack is stop or reinitialized) - */ - void stop(); - - /** - * cancel a previously scheduled task - * @param task task to cancel - * @return true if the task was cancelled, false otherwise - */ - boolean cancel(SIPStackTimerTask task); - - /** - * Start the SIP Timer, called when the stack is created. The stack configuration is passed - * so that different implementations can use specific config properties to configure themselves - * @param sipStack TODO - * @param configurationProperties the stack properties - */ - void start(SipStackImpl sipStack, Properties configurationProperties); - - /** - * Check if the timer is started or stopped - * @return true is the timer is started false otherwise - */ - boolean isStarted(); -} diff --git a/src/javax/sdp/SdpException.java b/src/javax/sdp/SdpException.java index 631f37211..39e912874 100644 --- a/src/javax/sdp/SdpException.java +++ b/src/javax/sdp/SdpException.java @@ -6,8 +6,6 @@ package javax.sdp; -import gov.nist.core.Separators; - /** The SdpException defines a general exception for the SDP classes to throw when they encounter a difficulty. * * @author deruelle @@ -38,7 +36,7 @@ public SdpException(String message){ */ public SdpException(String message, Throwable rootCause){ - super(rootCause.getMessage()+ Separators.SEMICOLON +message); + super(rootCause.getMessage()+";"+message); } /** Constructs a new SdpException as a result of a system exception and uses diff --git a/src/javax/sip/Transaction.java b/src/javax/sip/Transaction.java index d6f527aa4..2edce13d3 100755 --- a/src/javax/sip/Transaction.java +++ b/src/javax/sip/Transaction.java @@ -1,8 +1,8 @@ /** * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Unpublished - rights reserved under the Copyright Laws of the United States. - * Copyright � 2003 Sun Microsystems, Inc. All rights reserved. - * Copyright � 2005 BEA Systems, Inc. All rights reserved. + * Copyright © 2003 Sun Microsystems, Inc. All rights reserved. + * Copyright © 2005 BEA Systems, Inc. All rights reserved. * * Use is subject to license terms. * @@ -147,7 +147,6 @@ public void setRetransmitTimer(int retransmitTimer) * a final Response has been received by one branch. * * @return the Request message that created this transaction. - * */ public Request getRequest(); diff --git a/src/javax/sip/header/SubscriptionStateHeader.java b/src/javax/sip/header/SubscriptionStateHeader.java index 51e61a60c..9b8d40ff8 100644 --- a/src/javax/sip/header/SubscriptionStateHeader.java +++ b/src/javax/sip/header/SubscriptionStateHeader.java @@ -6,7 +6,7 @@ * * Use is subject to license terms. * - * This distribution may include materials developed by third parties. + * This distribution may include materials developed by third parties. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * @@ -16,7 +16,7 @@ * * HISTORY * Version Date Author Comments - * 1.1 13/12/2002 Phelim O'Doherty Initial version, extension header to + * 1.1 13/12/2002 Phelim O'Doherty Initial version, extension header to * support RFC3265 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ @@ -26,33 +26,33 @@ import java.text.ParseException; /** - * This interface represents the Subscription State header, as - * defined by RFC3265, this + * This interface represents the Subscription State header, as + * defined by RFC3265, this * header is not part of RFC3261. - *

    - * NOTIFY requests MUST contain SubscriptionState headers which indicate the + *

    + * NOTIFY requests MUST contain SubscriptionState headers which indicate the * status of the subscription. The subscription states are: *

      - *
    • active - If the SubscriptionState header value is "active", it means - * that the subscription has been accepted and (in general) has been authorized. - * If the header also contains an "expires" parameter, the subscriber SHOULD - * take it as the authoritative subscription duration and adjust accordingly. + *
    • active - If the SubscriptionState header value is "active", it means + * that the subscription has been accepted and (in general) has been authorized. + * If the header also contains an "expires" parameter, the subscriber SHOULD + * take it as the authoritative subscription duration and adjust accordingly. * The "retry-after" and "reason" parameters have no semantics for "active". - *
    • pending - If the SubscriptionState value is "pending", the - * subscription has been received by the notifier, but there is insufficient - * policy information to grant or deny the subscription yet. If the header also - * contains an "expires" parameter, the subscriber SHOULD take it as the - * authoritative subscription duration and adjust accordingly. No further - * action is necessary on the part of the subscriber. The "retry-after" and + *
    • pending - If the SubscriptionState value is "pending", the + * subscription has been received by the notifier, but there is insufficient + * policy information to grant or deny the subscription yet. If the header also + * contains an "expires" parameter, the subscriber SHOULD take it as the + * authoritative subscription duration and adjust accordingly. No further + * action is necessary on the part of the subscriber. The "retry-after" and * "reason" parameters have no semantics for "pending". - *
    • terminated - If the SubscriptionState value is "terminated", the - * subscriber should consider the subscription terminated. The "expires" + *
    • terminated - If the SubscriptionState value is "terminated", the + * subscriber should consider the subscription terminated. The "expires" * parameter has no semantics for "terminated". If a reason code is present, the - * client should behave as described in the reason code defined in this Header. - * If no reason code or an unknown reason code is present, the client MAY - * attempt to re-subscribe at any time (unless a "retry-after" parameter is + * client should behave as described in the reason code defined in this Header. + * If no reason code or an unknown reason code is present, the client MAY + * attempt to re-subscribe at any time (unless a "retry-after" parameter is * present, in which case the client SHOULD NOT attempt re-subscription until - * after the number of seconds specified by the "retry-after" parameter). + * after the number of seconds specified by the "retry-after" parameter). *
    * * @author BEA Systems, NIST @@ -60,9 +60,9 @@ */ public interface SubscriptionStateHeader extends Parameters, Header { - + /** - * Sets the relative expires value of the SubscriptionStateHeader. The + * Sets the relative expires value of the SubscriptionStateHeader. The * expires value MUST be greater than zero and MUST be less than 2**31. * * @param expires - the new expires value of this SubscriptionStateHeader. @@ -76,8 +76,8 @@ public interface SubscriptionStateHeader extends Parameters, Header { * * @return the expires value of the SubscriptionStateHeader. */ - public int getExpires(); - + public int getExpires(); + /** * Sets the retry after value of the SubscriptionStateHeader. The retry after value * MUST be greater than zero and MUST be less than 2**31. @@ -111,7 +111,7 @@ public interface SubscriptionStateHeader extends Parameters, Header { * unexpectedly while parsing the reason code. */ public void setReasonCode(String reasonCode) throws ParseException; - + /** * Gets the state of SubscriptionStateHeader. * @@ -126,87 +126,87 @@ public interface SubscriptionStateHeader extends Parameters, Header { * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the state. */ - public void setState(String state) throws ParseException; - + public void setState(String state) throws ParseException; + /** * Name of SubscriptionStateHeader */ public final static String NAME = "Subscription-State"; -//Reason Code Constants - +//Reason Code Constants + /** * Reason Code: The reason why the subscription was terminated is Unknown. */ - public final static String UNKNOWN = "unknown"; - + public final static String UNKNOWN = "Unknown"; + /** - * Reason Code: The subscription has been terminated, but the subscriber SHOULD retry - * immediately with a new subscription. One primary use of such a status - * code is to allow migration of subscriptions between nodes. The + * Reason Code: The subscription has been terminated, but the subscriber SHOULD retry + * immediately with a new subscription. One primary use of such a status + * code is to allow migration of subscriptions between nodes. The * "retry-after" parameter has no semantics for "deactivated". */ - public final static String DEACTIVATED = "deactivated"; - + public final static String DEACTIVATED = "Deactivated"; + /** - * Reason Code: The subscription has been terminated, but the client SHOULD retry at - * some later time. If a "retry-after" parameter is also present, the client - * SHOULD wait at least the number of seconds specified by that parameter + * Reason Code: The subscription has been terminated, but the client SHOULD retry at + * some later time. If a "retry-after" parameter is also present, the client + * SHOULD wait at least the number of seconds specified by that parameter * before attempting to re-subscribe. */ - public final static String PROBATION = "probation"; - + public final static String PROBATION = "Probation"; + /** - * Reason Code: The subscription has been terminated due to change in authorization - * policy. Clients SHOULD NOT attempt to re-subscribe. The "retry-after" + * Reason Code: The subscription has been terminated due to change in authorization + * policy. Clients SHOULD NOT attempt to re-subscribe. The "retry-after" * parameter has no semantics for "rejected". */ - public final static String REJECTED = "rejected"; - + public final static String REJECTED = "Rejected"; + /** - * Reason Code: The subscription has been terminated because it was not refreshed before - * it expired. Clients MAY re-subscribe immediately. The "retry-after" + * Reason Code: The subscription has been terminated because it was not refreshed before + * it expired. Clients MAY re-subscribe immediately. The "retry-after" * parameter has no semantics for "timeout". */ - public final static String TIMEOUT = "timeout"; - + public final static String TIMEOUT = "Timeout"; + /** - * Reason Code: The subscription has been terminated because the notifier could not - * obtain authorization in a timely fashion. If a "retry-after" parameter - * is also present, the client SHOULD wait at least the number of seconds - * specified by that parameter before attempting to re-subscribe; otherwise, - * the client MAY retry immediately, but will likely get put back into + * Reason Code: The subscription has been terminated because the notifier could not + * obtain authorization in a timely fashion. If a "retry-after" parameter + * is also present, the client SHOULD wait at least the number of seconds + * specified by that parameter before attempting to re-subscribe; otherwise, + * the client MAY retry immediately, but will likely get put back into * pending state. */ - public final static String GIVE_UP = "giveup"; - + public final static String GIVE_UP = "Give-Up"; + /** - * Reason Code: The subscription has been terminated because the resource state which was - * being monitored no longer exists. Clients SHOULD NOT attempt to + * Reason Code: The subscription has been terminated because the resource state which was + * being monitored no longer exists. Clients SHOULD NOT attempt to * re-subscribe. The "retry-after" parameter has no semantics for "noresource". */ - public final static String NO_RESOURCE = "noresource"; - -// State constants - + public final static String NO_RESOURCE = "No-Resource"; + +// State constants + /** - * State: The subscription has been accepted and (in general) has been + * State: The subscription has been accepted and (in general) has been * authorized. */ - public final static String ACTIVE = "active"; - + public final static String ACTIVE = "Active"; + /** - * State: The subscription has been terminated, if a reason code is present, + * State: The subscription has been terminated, if a reason code is present, * the client should behave as described in the reason code. */ - public final static String TERMINATED = "terminated"; - + public final static String TERMINATED = "Terminated"; + /** - * State: The subscription has been received by the notifier, but there is + * State: The subscription has been received by the notifier, but there is * insufficient policy information to grant or deny the subscription yet. */ - public final static String PENDING = "pending"; - + public final static String PENDING = "Pending"; + } diff --git a/src/performance/b2bua/run_uac_DIALOG.sh b/src/performance/b2bua/run_uac_DIALOG.sh index 3ab9d5812..42498b241 100755 --- a/src/performance/b2bua/run_uac_DIALOG.sh +++ b/src/performance/b2bua/run_uac_DIALOG.sh @@ -1,2 +1 @@ sipp 127.0.0.1:5060 -trace_err -sf uac_DIALOG.xml -i 127.0.0.1 -p 5050 -r 1 -m 1000000 -l 1000000 -#sipp 127.0.0.1:5060 -trace_err -sf uac_DIALOG.xml -i 127.0.0.1 -p 5050 -r 1 -m 1 -l 1000000 diff --git a/src/performance/uas/.ant-targets-build.xml b/src/performance/uas/.ant-targets-build.xml deleted file mode 100644 index 61364bca7..000000000 --- a/src/performance/uas/.ant-targets-build.xml +++ /dev/null @@ -1,5 +0,0 @@ -clean -shootme -shootme-no-dialog -shootme-no-dialog-no-tx -shootmelog diff --git a/src/performance/uas/Shootme.java b/src/performance/uas/Shootme.java index 5b52d087d..dde1ea763 100644 --- a/src/performance/uas/Shootme.java +++ b/src/performance/uas/Shootme.java @@ -1,12 +1,7 @@ package performance.uas; -import gov.nist.javax.sip.message.RequestExt; - import java.util.Properties; -import java.util.Timer; -import java.util.TimerTask; -import javax.sip.ClientTransaction; import javax.sip.Dialog; import javax.sip.DialogTerminatedEvent; import javax.sip.IOExceptionEvent; @@ -22,7 +17,6 @@ import javax.sip.TransactionTerminatedEvent; import javax.sip.address.Address; import javax.sip.address.AddressFactory; -import javax.sip.address.SipURI; import javax.sip.header.ContactHeader; import javax.sip.header.HeaderFactory; import javax.sip.header.ToHeader; @@ -44,52 +38,25 @@ public class Shootme implements SipListener { private static HeaderFactory headerFactory; private static SipStack sipStack; - - private static SipFactory sipFactory; - - private static SipProvider sipProvider; - - private static Timer timer = new Timer(); private static final String myAddress = "127.0.0.1"; private static final int myPort = 5080; + protected static final String usageString = "java " + Shootme.class.getCanonicalName() + " \n" + ">>>> is your class path set to the root?"; - private static final long BYE_DELAY = 60000; - - private static final String TIMER_USER = "sipp-timer"; - private static void usage() { System.out.println(usageString); System.exit(0); - } - class ByeTask extends TimerTask { - Dialog dialog; - - public ByeTask(Dialog dialog) { - this.dialog = dialog; - } - public void run () { - try { - Request byeRequest = this.dialog.createRequest(Request.BYE); - ClientTransaction ct = sipProvider.getNewClientTransaction(byeRequest); - dialog.sendRequest(ct); - dialog = null; - } catch (Exception ex) { - ex.printStackTrace(); - } - - } } - + public void processRequest(RequestEvent requestEvent) { final Request request = requestEvent.getRequest(); - final ServerTransaction serverTransactionId = requestEvent.getServerTransaction(); + final ServerTransaction serverTransactionId = requestEvent.getServerTransaction(); if (request.getMethod().equals(Request.INVITE)) { processInvite(requestEvent, serverTransactionId); @@ -111,11 +78,7 @@ public void processResponse(ResponseEvent responseEvent) { */ public void processAck(RequestEvent requestEvent, ServerTransaction serverTransaction) { - final Dialog dialog = requestEvent.getDialog(); - final RequestExt request = (RequestExt) requestEvent.getRequest(); - if(((SipURI)request.getFromHeader().getAddress().getURI()).getUser().equalsIgnoreCase(TIMER_USER)) { - timer.schedule(new ByeTask(dialog), BYE_DELAY) ; - } + } /** @@ -131,12 +94,12 @@ public void processInvite(RequestEvent requestEvent, if (st == null) { st = sipProvider.getNewServerTransaction(request); } - sipProvider.getNewDialog(st); final String toTag = ""+System.nanoTime(); Response response = messageFactory.createResponse(Response.RINGING, request); ToHeader toHeader = (ToHeader) response.getHeader(ToHeader.NAME); - toHeader.setTag(toTag); // Application is supposed to set. + toHeader.setTag(toTag); // Application is supposed to set. + sipProvider.getNewDialog(st); // Creates a dialog only for non trying responses st.sendResponse(response); @@ -163,13 +126,10 @@ public void processInvite(RequestEvent requestEvent, public void processBye(RequestEvent requestEvent, ServerTransaction serverTransactionId) { final Request request = requestEvent.getRequest(); - final Dialog dialog = requestEvent.getDialog(); try { final Response response = messageFactory.createResponse(200, request); - if(serverTransactionId == null) { - serverTransactionId = ((SipProvider)requestEvent.getSource()).getNewServerTransaction(request); - } serverTransactionId.sendResponse(response); + } catch (Exception ex) { ex.printStackTrace(); //System.exit(0); @@ -183,16 +143,10 @@ public void processCancel(RequestEvent requestEvent, } public void processTimeout(javax.sip.TimeoutEvent timeoutEvent) { - Request request = null; - if(timeoutEvent.getClientTransaction() == null) { - request = timeoutEvent.getServerTransaction().getRequest(); - } else { - request = timeoutEvent.getClientTransaction().getRequest(); - } - //System.out.println(request); } - public void init() { + public void init() { + SipFactory sipFactory = null; sipStack = null; sipFactory = SipFactory.getInstance(); sipFactory.setPathName("gov.nist"); @@ -207,15 +161,16 @@ public void init() { "shootmedebug.txt"); properties.setProperty("gov.nist.javax.sip.SERVER_LOG", "shootmelog.txt"); + properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", + "shootmedebug.txt"); + properties.setProperty("gov.nist.javax.sip.SERVER_LOG", + "shootmelog.txt"); properties.setProperty("gov.nist.javax.sip.REENTRANT_LISTENER", "true"); - properties.setProperty("gov.nist.javax.sip.THREAD_POOL_SIZE", "4"); + properties.setProperty("gov.nist.javax.sip.THREAD_POOL_SIZE", "64"); properties.setProperty("gov.nist.javax.sip.RECEIVE_UDP_BUFFER_SIZE", "65536"); properties.setProperty("gov.nist.javax.sip.SEND_UDP_BUFFER_SIZE", "65536"); properties.setProperty("gov.nist.javax.sip.CONGESTION_CONTROL_ENABLED", "false"); -// properties.setProperty("gov.nist.javax.sip.MESSAGE_PARSER_FACTORY", CharsMsgParserFactory.class.getName()); -// properties.setProperty("gov.nist.javax.sip.TIMER_CLASS_NAME", ScheduledExecutorSipTimer.class.getName()); -// properties.setProperty("gov.nist.javax.sip.TIMER_CLASS_NAME", HashWheelSipTimer.class.getName()); try { // Create SipStack object sipStack = sipFactory.createSipStack(properties); @@ -239,7 +194,7 @@ public void init() { Shootme listener = this; - sipProvider = sipStack.createSipProvider(lp); + SipProvider sipProvider = sipStack.createSipProvider(lp); sipProvider.addSipListener(listener); } catch (Exception ex) { @@ -259,19 +214,12 @@ public void processIOException(IOExceptionEvent exceptionEvent) { public void processTransactionTerminated( TransactionTerminatedEvent transactionTerminatedEvent) { - Request request = null; - if(transactionTerminatedEvent.getClientTransaction() == null) { - request = transactionTerminatedEvent.getServerTransaction().getRequest(); - } else { - request = transactionTerminatedEvent.getClientTransaction().getRequest(); - } - //System.out.println(request); + } public void processDialogTerminated( DialogTerminatedEvent dialogTerminatedEvent) { - Dialog dialog = dialogTerminatedEvent.getDialog(); - //System.out.println(dialog); + } } diff --git a/src/performance/uas/ShootmeDialogAndTxStateless.java b/src/performance/uas/ShootmeDialogAndTxStateless.java deleted file mode 100644 index b333d09de..000000000 --- a/src/performance/uas/ShootmeDialogAndTxStateless.java +++ /dev/null @@ -1,226 +0,0 @@ -package performance.uas; - -import java.util.Properties; - -import javax.sip.DialogTerminatedEvent; -import javax.sip.IOExceptionEvent; -import javax.sip.ListeningPoint; -import javax.sip.PeerUnavailableException; -import javax.sip.RequestEvent; -import javax.sip.ResponseEvent; -import javax.sip.ServerTransaction; -import javax.sip.SipFactory; -import javax.sip.SipListener; -import javax.sip.SipProvider; -import javax.sip.SipStack; -import javax.sip.TransactionTerminatedEvent; -import javax.sip.address.Address; -import javax.sip.address.AddressFactory; -import javax.sip.header.ContactHeader; -import javax.sip.header.HeaderFactory; -import javax.sip.header.ToHeader; -import javax.sip.message.MessageFactory; -import javax.sip.message.Request; -import javax.sip.message.Response; - -/** - * This is the UAS application for performance testing - * - * @author Vladimir Ralev - */ -public class ShootmeDialogAndTxStateless implements SipListener { - - private static AddressFactory addressFactory; - - private static MessageFactory messageFactory; - - private static HeaderFactory headerFactory; - - private static SipStack sipStack; - - private static final String myAddress = "127.0.0.1"; - - private static final int myPort = 5080; - - - protected static final String usageString = "java " - + ShootmeDialogAndTxStateless.class.getCanonicalName() + " \n" - + ">>>> is your class path set to the root?"; - - private static void usage() { - System.out.println(usageString); - System.exit(0); - - } - - public void processRequest(RequestEvent requestEvent) { - final Request request = requestEvent.getRequest(); - final ServerTransaction serverTransactionId = requestEvent.getServerTransaction(); - - if (request.getMethod().equals(Request.INVITE)) { - processInvite(requestEvent, serverTransactionId); - } else if (request.getMethod().equals(Request.ACK)) { - processAck(requestEvent, serverTransactionId); - } else if (request.getMethod().equals(Request.BYE)) { - processBye(requestEvent, serverTransactionId); - } else if (request.getMethod().equals(Request.CANCEL)) { - processCancel(requestEvent, serverTransactionId); - } - - } - - public void processResponse(ResponseEvent responseEvent) { - } - - /** - * Process the ACK request. - */ - public void processAck(RequestEvent requestEvent, - ServerTransaction serverTransaction) { - - } - - /** - * Process the invite request. - */ - public void processInvite(RequestEvent requestEvent, - ServerTransaction serverTransaction) { - - final Request request = requestEvent.getRequest(); - final SipProvider sipProvider = (SipProvider) requestEvent.getSource(); -// ServerTransaction st = serverTransaction; - try { -// if (st == null) { -// st = sipProvider.getNewServerTransaction(request); -// } - final String toTag = ""+System.nanoTime(); - Response response = messageFactory.createResponse(Response.RINGING, - request); - ToHeader toHeader = (ToHeader) response.getHeader(ToHeader.NAME); - toHeader.setTag(toTag); // Application is supposed to set. - sipProvider.sendResponse(response); - - response = messageFactory.createResponse(Response.OK, - request); - final Address address = addressFactory.createAddress("Shootme "); - final ContactHeader contactHeader = headerFactory - .createContactHeader(address); - response.addHeader(contactHeader); - toHeader = (ToHeader) response.getHeader(ToHeader.NAME); - toHeader.setTag(toTag); // Application is supposed to set. - response.addHeader(contactHeader); - sipProvider.sendResponse(response); - } catch (Exception ex) { - ex.printStackTrace(); - //System.exit(0); - } - } - - - /** - * Process the bye request. - */ - public void processBye(RequestEvent requestEvent, - ServerTransaction serverTransactionId) { - final Request request = requestEvent.getRequest(); - try { - final Response response = messageFactory.createResponse(200, request); - ((SipProvider)requestEvent.getSource()).sendResponse(response); - - } catch (Exception ex) { - ex.printStackTrace(); - //System.exit(0); - - } - } - - public void processCancel(RequestEvent requestEvent, - ServerTransaction serverTransactionId) { - - } - - public void processTimeout(javax.sip.TimeoutEvent timeoutEvent) { - } - - public void init() { - SipFactory sipFactory = null; - sipStack = null; - sipFactory = SipFactory.getInstance(); - sipFactory.setPathName("gov.nist"); - Properties properties = new Properties(); - properties.setProperty("javax.sip.STACK_NAME", "shootme"); - // You need 16 for logging traces. 32 for debug + traces. - // Your code will limp at 32 but it is best for debugging. - properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "0"); - properties.setProperty("gov.nist.javax.sip.LOG_MESSAGE_CONTENT", "false"); - properties.setProperty("javax.sip.AUTOMATIC_DIALOG_SUPPORT", "off"); - properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", - "./shootmedebug.txt"); - properties.setProperty("gov.nist.javax.sip.SERVER_LOG", - "./shootmelog.txt"); - properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", - "./shootmedebug.txt"); - properties.setProperty("gov.nist.javax.sip.SERVER_LOG", - "./shootmelog.txt"); - properties.setProperty("gov.nist.javax.sip.REENTRANT_LISTENER", - "true"); - properties.setProperty("gov.nist.javax.sip.THREAD_POOL_SIZE", "4"); - properties.setProperty("gov.nist.javax.sip.RECEIVE_UDP_BUFFER_SIZE", "65536"); - properties.setProperty("gov.nist.javax.sip.SEND_UDP_BUFFER_SIZE", "65536"); - //properties.setProperty("gov.nist.javax.sip.RECEIVE_UDP_BUFFER_SIZE", "120000"); - //properties.setProperty("gov.nist.javax.sip.SEND_UDP_BUFFER_SIZE", "120000"); - - properties.setProperty("gov.nist.javax.sip.CONGESTION_CONTROL_ENABLED", "false"); - try { - // Create SipStack object - sipStack = sipFactory.createSipStack(properties); - } catch (PeerUnavailableException e) { - // could not find - // gov.nist.jain.protocol.ip.sip.SipStackImpl - // in the classpath - e.printStackTrace(); - System.err.println(e.getMessage()); - if (e.getCause() != null) - e.getCause().printStackTrace(); - System.exit(0); - } - - try { - headerFactory = sipFactory.createHeaderFactory(); - addressFactory = sipFactory.createAddressFactory(); - messageFactory = sipFactory.createMessageFactory(); - ListeningPoint lp = sipStack.createListeningPoint("127.0.0.1", - myPort, "udp"); - - ShootmeDialogAndTxStateless listener = this; - - SipProvider sipProvider = sipStack.createSipProvider(lp); - sipProvider.addSipListener(listener); - - } catch (Exception ex) { - ex.printStackTrace(); - usage(); - } - - } - - public static void main(String args[]) { - new ShootmeDialogAndTxStateless().init(); - } - - public void processIOException(IOExceptionEvent exceptionEvent) { - - } - - public void processTransactionTerminated( - TransactionTerminatedEvent transactionTerminatedEvent) { - - } - - public void processDialogTerminated( - DialogTerminatedEvent dialogTerminatedEvent) { - - } - -} diff --git a/src/performance/uas/ShootmeDialogStateless.java b/src/performance/uas/ShootmeDialogStateless.java deleted file mode 100644 index 6db417c50..000000000 --- a/src/performance/uas/ShootmeDialogStateless.java +++ /dev/null @@ -1,247 +0,0 @@ -package performance.uas; - -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.Date; -import java.util.Properties; - -import javax.sip.DialogTerminatedEvent; -import javax.sip.IOExceptionEvent; -import javax.sip.ListeningPoint; -import javax.sip.PeerUnavailableException; -import javax.sip.RequestEvent; -import javax.sip.ResponseEvent; -import javax.sip.ServerTransaction; -import javax.sip.SipFactory; -import javax.sip.SipListener; -import javax.sip.SipProvider; -import javax.sip.SipStack; -import javax.sip.TransactionAlreadyExistsException; -import javax.sip.TransactionTerminatedEvent; -import javax.sip.TransactionUnavailableException; -import javax.sip.address.Address; -import javax.sip.address.AddressFactory; -import javax.sip.header.ContactHeader; -import javax.sip.header.HeaderFactory; -import javax.sip.header.ToHeader; -import javax.sip.message.MessageFactory; -import javax.sip.message.Request; -import javax.sip.message.Response; - -/** - * This is the UAS application for performance testing - * - * @author Vladimir Ralev - */ -public class ShootmeDialogStateless implements SipListener { - - private static AddressFactory addressFactory; - - private static MessageFactory messageFactory; - - private static HeaderFactory headerFactory; - - private static SipStack sipStack; - - private static final String myAddress = "127.0.0.1"; - - private static final int myPort = 5080; - - - protected static final String usageString = "java " - + ShootmeDialogStateless.class.getCanonicalName() + " \n" - + ">>>> is your class path set to the root?"; - - private static void usage() { - System.out.println(usageString); - System.exit(0); - - } - - public void processRequest(RequestEvent requestEvent) { - final Request request = requestEvent.getRequest(); - final ServerTransaction serverTransactionId = requestEvent.getServerTransaction(); - - if (request.getMethod().equals(Request.INVITE)) { - processInvite(requestEvent, serverTransactionId); - } else if (request.getMethod().equals(Request.ACK)) { - processAck(requestEvent, serverTransactionId); - } else if (request.getMethod().equals(Request.BYE)) { - processBye(requestEvent, serverTransactionId); - } else if (request.getMethod().equals(Request.CANCEL)) { - processCancel(requestEvent, serverTransactionId); - } - - } - - public void processResponse(ResponseEvent responseEvent) { - } - - /** - * Process the ACK request. - */ - public void processAck(RequestEvent requestEvent, - ServerTransaction serverTransaction) { - - } - - /** - * Process the invite request. - */ - public void processInvite(RequestEvent requestEvent, - ServerTransaction serverTransaction) { - - final Request request = requestEvent.getRequest(); - final SipProvider sipProvider = (SipProvider) requestEvent.getSource(); - ServerTransaction st = serverTransaction; - try { - if (st == null) { - try { - st = sipProvider.getNewServerTransaction(request); - } catch ( TransactionUnavailableException tae) { - tae.printStackTrace(); - return; - } catch ( TransactionAlreadyExistsException taex ) { - // This is a retransmission so just return. - return; - } - } - final String toTag = ""+System.nanoTime(); - Response response = messageFactory.createResponse(Response.RINGING, - request); - ToHeader toHeader = (ToHeader) response.getHeader(ToHeader.NAME); - toHeader.setTag(toTag); // Application is supposed to set. - st.sendResponse(response); - - response = messageFactory.createResponse(Response.OK, - request); - final Address address = addressFactory.createAddress("Shootme "); - final ContactHeader contactHeader = headerFactory - .createContactHeader(address); - response.addHeader(contactHeader); - toHeader = (ToHeader) response.getHeader(ToHeader.NAME); - toHeader.setTag(toTag); // Application is supposed to set. - st.sendResponse(response); - } catch (Exception ex) { - ex.printStackTrace(); - //System.exit(0); - } - } - - - /** - * Process the bye request. - */ - public void processBye(RequestEvent requestEvent, - ServerTransaction serverTransactionId) { - final Request request = requestEvent.getRequest(); - - try { - if (serverTransactionId == null) { - try { - serverTransactionId = ((SipProvider)requestEvent.getSource()).getNewServerTransaction(request); - } catch ( TransactionUnavailableException tae) { - tae.printStackTrace(); - return; - } catch ( TransactionAlreadyExistsException taex ) { - // This is a retransmission so just return. - return; - } - } - final Response response = messageFactory.createResponse(200, request); - serverTransactionId.sendResponse(response); - - } catch (Exception ex) { - ex.printStackTrace(); - //System.exit(0); - - } - } - - public void processCancel(RequestEvent requestEvent, - ServerTransaction serverTransactionId) { - - } - - public void processTimeout(javax.sip.TimeoutEvent timeoutEvent) { - } - - public void init() { - SipFactory sipFactory = null; - sipStack = null; - sipFactory = SipFactory.getInstance(); - sipFactory.setPathName("gov.nist"); - Properties properties = new Properties(); - properties.setProperty("javax.sip.STACK_NAME", "shootme"); - // You need 16 for logging traces. 32 for debug + traces. - // Your code will limp at 32 but it is best for debugging. - properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "0"); - properties.setProperty("gov.nist.javax.sip.LOG_MESSAGE_CONTENT", "false"); - properties.setProperty("javax.sip.AUTOMATIC_DIALOG_SUPPORT", "off"); - properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", - "shootmedebug.txt"); - properties.setProperty("gov.nist.javax.sip.SERVER_LOG", - "shootmelog.txt"); - properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", - "shootmedebug.txt"); - properties.setProperty("gov.nist.javax.sip.SERVER_LOG", - "shootmelog.txt"); - properties.setProperty("gov.nist.javax.sip.REENTRANT_LISTENER", - "true"); - properties.setProperty("gov.nist.javax.sip.THREAD_POOL_SIZE", "4"); - properties.setProperty("gov.nist.javax.sip.RECEIVE_UDP_BUFFER_SIZE", "65536"); - properties.setProperty("gov.nist.javax.sip.SEND_UDP_BUFFER_SIZE", "65536"); - properties.setProperty("gov.nist.javax.sip.CONGESTION_CONTROL_ENABLED", "false"); - try { - // Create SipStack object - sipStack = sipFactory.createSipStack(properties); - } catch (PeerUnavailableException e) { - // could not find - // gov.nist.jain.protocol.ip.sip.SipStackImpl - // in the classpath - e.printStackTrace(); - System.err.println(e.getMessage()); - if (e.getCause() != null) - e.getCause().printStackTrace(); - System.exit(0); - } - - try { - headerFactory = sipFactory.createHeaderFactory(); - addressFactory = sipFactory.createAddressFactory(); - messageFactory = sipFactory.createMessageFactory(); - ListeningPoint lp = sipStack.createListeningPoint("127.0.0.1", - myPort, "udp"); - - ShootmeDialogStateless listener = this; - - SipProvider sipProvider = sipStack.createSipProvider(lp); - sipProvider.addSipListener(listener); - - } catch (Exception ex) { - ex.printStackTrace(); - usage(); - } - - } - - public static void main(String args[]) { - new ShootmeDialogStateless().init(); - } - - public void processIOException(IOExceptionEvent exceptionEvent) { - - } - - public void processTransactionTerminated( - TransactionTerminatedEvent transactionTerminatedEvent) { -// System.out.println("Tx Term Event : " + new SimpleDateFormat("hh:mm:ss").format(new Date(Calendar.getInstance().getTimeInMillis())) + " \n" + transactionTerminatedEvent.getServerTransaction().getRequest()); - } - - public void processDialogTerminated( - DialogTerminatedEvent dialogTerminatedEvent) { - - } - -} diff --git a/src/performance/uas/build.xml b/src/performance/uas/build.xml index 12e7550d1..ca6a54b8d 100644 --- a/src/performance/uas/build.xml +++ b/src/performance/uas/build.xml @@ -5,12 +5,10 @@ - - @@ -20,47 +18,12 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/performance/uas/diff.txt b/src/performance/uas/diff.txt deleted file mode 100644 index 9fec5de20..000000000 --- a/src/performance/uas/diff.txt +++ /dev/null @@ -1,701 +0,0 @@ -diff --git a/src/gov/nist/javax/sip/message/SIPMessage.java b/src/gov/nist/javax/sip/message/SIPMessage.java -index 3ab19f1..6ed47ee 100755 ---- a/src/gov/nist/javax/sip/message/SIPMessage.java -+++ b/src/gov/nist/javax/sip/message/SIPMessage.java -@@ -138,7 +138,7 @@ public abstract class SIPMessage extends MessageObject implements javax.sip.mess - /** - * unparsed headers - */ -- private LinkedList unrecognizedHeaders; -+ protected LinkedList unrecognizedHeaders; - - /** - * List of parsed headers (in the order they were added) -@@ -171,7 +171,7 @@ public abstract class SIPMessage extends MessageObject implements javax.sip.mess - protected Object messageContentObject; - - // Table of headers indexed by name. -- private Map nameTable; -+ protected Map headerTable; - - /** - * The application data pointer. This is un-interpreted by the stack. This is provided as a -@@ -179,7 +179,7 @@ public abstract class SIPMessage extends MessageObject implements javax.sip.mess - */ - protected Object applicationData; - -- private String forkId; -+ protected String forkId; - - /** - * Return true if the header belongs only in a Request. -@@ -476,7 +476,7 @@ public abstract class SIPMessage extends MessageObject implements javax.sip.mess - */ - public Object clone() { - SIPMessage retval = (SIPMessage) super.clone(); -- retval.nameTable = new ConcurrentHashMap(); -+ retval.headerTable = new ConcurrentHashMap(); - retval.fromHeader = null; - retval.toHeader = null; - retval.cSeqHeader = null; -@@ -546,7 +546,7 @@ public abstract class SIPMessage extends MessageObject implements javax.sip.mess - */ - public SIPMessage() { - this.headers = new ConcurrentLinkedQueue(); -- nameTable = new ConcurrentHashMap(); -+ headerTable = new ConcurrentHashMap(); - try { - this.attachHeader(new ContentLength(0), false); - } catch (Exception ex) { -@@ -658,8 +658,8 @@ public abstract class SIPMessage extends MessageObject implements javax.sip.mess - - String headerNameLowerCase = SIPHeaderNamesCache.toLowerCase(h.getName()); - if (replaceFlag) { -- nameTable.remove(headerNameLowerCase); -- } else if (nameTable.containsKey(headerNameLowerCase) && !(h instanceof SIPHeaderList)) { -+ headerTable.remove(headerNameLowerCase); -+ } else if (headerTable.containsKey(headerNameLowerCase) && !(h instanceof SIPHeaderList)) { - if (h instanceof ContentLength) { - try { - ContentLength cl = (ContentLength) h; -@@ -684,19 +684,19 @@ public abstract class SIPMessage extends MessageObject implements javax.sip.mess - } - } - -- if (!nameTable.containsKey(headerNameLowerCase)) { -- nameTable.put(headerNameLowerCase, h); -+ if (!headerTable.containsKey(headerNameLowerCase)) { -+ headerTable.put(headerNameLowerCase, h); - headers.add(h); - } else { - if (h instanceof SIPHeaderList) { -- SIPHeaderList< ? > hdrlist = (SIPHeaderList< ? >) nameTable -+ SIPHeaderList< ? > hdrlist = (SIPHeaderList< ? >) headerTable - .get(headerNameLowerCase); - if (hdrlist != null) - hdrlist.concatenate((SIPHeaderList) h, top); - else -- nameTable.put(headerNameLowerCase, h); -+ headerTable.put(headerNameLowerCase, h); - } else { -- nameTable.put(headerNameLowerCase, h); -+ headerTable.put(headerNameLowerCase, h); - } - } - -@@ -727,7 +727,7 @@ public abstract class SIPMessage extends MessageObject implements javax.sip.mess - public void removeHeader(String headerName, boolean top) { - - String headerNameLowerCase = SIPHeaderNamesCache.toLowerCase(headerName); -- SIPHeader toRemove = (SIPHeader) nameTable.get(headerNameLowerCase); -+ SIPHeader toRemove = (SIPHeader) headerTable.get(headerNameLowerCase); - // nothing to do then we are done. - if (toRemove == null) - return; -@@ -748,10 +748,10 @@ public abstract class SIPMessage extends MessageObject implements javax.sip.mess - - // JvB: also remove it from the nameTable! Else NPE in - // DefaultRouter -- nameTable.remove(headerNameLowerCase); -+ headerTable.remove(headerNameLowerCase); - } - } else { -- this.nameTable.remove(headerNameLowerCase); -+ this.headerTable.remove(headerNameLowerCase); - if (toRemove instanceof From) { - this.fromHeader = null; - } else if (toRemove instanceof To) { -@@ -785,7 +785,7 @@ public abstract class SIPMessage extends MessageObject implements javax.sip.mess - if (headerName == null) - throw new NullPointerException("null arg"); - String headerNameLowerCase = SIPHeaderNamesCache.toLowerCase(headerName); -- SIPHeader removed = (SIPHeader) nameTable.remove(headerNameLowerCase); -+ SIPHeader removed = (SIPHeader) headerTable.remove(headerNameLowerCase); - // nothing to do then we are done. - if (removed == null) - return; -@@ -929,7 +929,7 @@ public abstract class SIPMessage extends MessageObject implements javax.sip.mess - private Header getHeaderLowerCase(String lowerCaseHeaderName) { - if (lowerCaseHeaderName == null) - throw new NullPointerException("bad name"); -- SIPHeader sipHeader = (SIPHeader) nameTable.get(lowerCaseHeaderName); -+ SIPHeader sipHeader = (SIPHeader) headerTable.get(lowerCaseHeaderName); - if (sipHeader instanceof SIPHeaderList) - return (Header) ((SIPHeaderList) sipHeader).getFirst(); - else -@@ -1399,7 +1399,7 @@ public abstract class SIPMessage extends MessageObject implements javax.sip.mess - public ListIterator getHeaders(String headerName) { - if (headerName == null) - throw new NullPointerException("null headerName"); -- SIPHeader sipHeader = (SIPHeader) nameTable.get(SIPHeaderNamesCache -+ SIPHeader sipHeader = (SIPHeader) headerTable.get(SIPHeaderNamesCache - .toLowerCase(headerName)); - // empty iterator - if (sipHeader == null) -@@ -1420,15 +1420,15 @@ public abstract class SIPMessage extends MessageObject implements javax.sip.mess - */ - public String getHeaderAsFormattedString(String name) { - String lowerCaseName = name.toLowerCase(); -- if (this.nameTable.containsKey(lowerCaseName)) { -- return this.nameTable.get(lowerCaseName).toString(); -+ if (this.headerTable.containsKey(lowerCaseName)) { -+ return this.headerTable.get(lowerCaseName).toString(); - } else { - return this.getHeader(name).toString(); - } - } - - protected SIPHeader getSIPHeaderListLowerCase(String lowerCaseHeaderName) { -- return nameTable.get(lowerCaseHeaderName); -+ return headerTable.get(lowerCaseHeaderName); - } - - /** -@@ -1439,7 +1439,7 @@ public abstract class SIPMessage extends MessageObject implements javax.sip.mess - */ - @SuppressWarnings("unchecked") - private List getHeaderList(String headerName) { -- SIPHeader sipHeader = (SIPHeader) nameTable.get(SIPHeaderNamesCache -+ SIPHeader sipHeader = (SIPHeader) headerTable.get(SIPHeaderNamesCache - .toLowerCase(headerName)); - if (sipHeader == null) - return null; -@@ -1459,7 +1459,7 @@ public abstract class SIPMessage extends MessageObject implements javax.sip.mess - * @return true if the header is present in the message - */ - public boolean hasHeader(String headerName) { -- return nameTable.containsKey(SIPHeaderNamesCache.toLowerCase(headerName)); -+ return headerTable.containsKey(SIPHeaderNamesCache.toLowerCase(headerName)); - } - - /** -@@ -1613,15 +1613,15 @@ public abstract class SIPMessage extends MessageObject implements javax.sip.mess - return false; - } - SIPMessage otherMessage = (SIPMessage) other; -- Collection values = this.nameTable.values(); -+ Collection values = this.headerTable.values(); - Iterator it = values.iterator(); -- if (nameTable.size() != otherMessage.nameTable.size()) { -+ if (headerTable.size() != otherMessage.headerTable.size()) { - return false; - } - - while (it.hasNext()) { - SIPHeader mine = (SIPHeader) it.next(); -- SIPHeader his = (SIPHeader) (otherMessage.nameTable.get(SIPHeaderNamesCache -+ SIPHeader his = (SIPHeader) (otherMessage.headerTable.get(SIPHeaderNamesCache - .toLowerCase(mine.getName()))); - if (his == null) { - return false; -@@ -1918,32 +1918,32 @@ public abstract class SIPMessage extends MessageObject implements javax.sip.mess - public abstract String toString(); - - public void cleanUp() { -- applicationData = null; -- callIdHeader = null; -- contentEncodingCharset = null; -- contentLengthHeader = null; -- cSeqHeader = null; -- forkId = null; -- fromHeader = null; -- if(headers != null) { -- headers.clear(); -- headers = null; -- } -- matchExpression = null; -- maxForwardsHeader = null; -- messageContent = null; -- messageContentBytes = null; -- messageContentObject = null; -- if(nameTable != null) { -- nameTable.clear(); -- nameTable = null; -- } -- stringRepresentation = null; -- toHeader = null; -- if(unrecognizedHeaders != null) { -- unrecognizedHeaders.clear(); -- unrecognizedHeaders = null; -- } -+// applicationData = null; -+// callIdHeader = null; -+// contentEncodingCharset = null; -+// contentLengthHeader = null; -+// cSeqHeader = null; -+// forkId = null; -+// fromHeader = null; -+// if(headers != null) { -+// headers.clear(); -+// headers = null; -+// } -+// matchExpression = null; -+// maxForwardsHeader = null; -+// messageContent = null; -+// messageContentBytes = null; -+// messageContentObject = null; -+// if(nameTable != null) { -+// nameTable.clear(); -+// nameTable = null; -+// } -+// stringRepresentation = null; -+// toHeader = null; -+// if(unrecognizedHeaders != null) { -+// unrecognizedHeaders.clear(); -+// unrecognizedHeaders = null; -+// } - } - - /** -diff --git a/src/gov/nist/javax/sip/message/SIPRequest.java b/src/gov/nist/javax/sip/message/SIPRequest.java -index 9f2f092..300e96c 100755 ---- a/src/gov/nist/javax/sip/message/SIPRequest.java -+++ b/src/gov/nist/javax/sip/message/SIPRequest.java -@@ -1231,4 +1231,9 @@ public class SIPRequest extends SIPMessage implements javax.sip.message.Request, - public Object getInviteTransaction() { - return inviteTransaction; - } -+ -+ @Override -+ public void cleanUp() { -+ super.cleanUp(); -+ } - } -diff --git a/src/gov/nist/javax/sip/message/SIPResponse.java b/src/gov/nist/javax/sip/message/SIPResponse.java -index 7100459..bc47c02 100755 ---- a/src/gov/nist/javax/sip/message/SIPResponse.java -+++ b/src/gov/nist/javax/sip/message/SIPResponse.java -@@ -646,7 +646,7 @@ public class SIPResponse - - @Override - public void cleanUp() { -- statusLine = null; -+// statusLine = null; - super.cleanUp(); - } - } -diff --git a/src/gov/nist/javax/sip/parser/StringMsgParser.java b/src/gov/nist/javax/sip/parser/StringMsgParser.java -index 3f00e3f..c15abfd 100755 ---- a/src/gov/nist/javax/sip/parser/StringMsgParser.java -+++ b/src/gov/nist/javax/sip/parser/StringMsgParser.java -@@ -75,7 +75,7 @@ public class StringMsgParser implements MessageParser { - protected boolean readBody; - protected ParseExceptionListener parseExceptionListener; - protected String rawStringMessage; -- private boolean strict; -+ protected boolean strict; - - protected static boolean computeContentLengthFromMessage = false; - -diff --git a/src/gov/nist/javax/sip/stack/SIPClientTransaction.java b/src/gov/nist/javax/sip/stack/SIPClientTransaction.java -index 5d12325..ca7a2c3 100755 ---- a/src/gov/nist/javax/sip/stack/SIPClientTransaction.java -+++ b/src/gov/nist/javax/sip/stack/SIPClientTransaction.java -@@ -1587,7 +1587,7 @@ public class SIPClientTransaction extends SIPTransaction implements ServerRespon - // we release the ref to the dialog asap and just keep the id of the dialog to look it up in the dialog table - if(defaultDialog != null) { - String dialogId = defaultDialog.getDialogId(); -- // we nullify the ref only if it can be find in the dialog table (not always true, check challenge unittest of the testsuite) -+ // we nullify the ref only if it can be find in the dialog table (not always true if the dialog is in null state, check challenge unittest of the testsuite) - if(dialogId != null && sipStack.getDialog(dialogId) != null) { - defaultDialogId = dialogId; - defaultDialog = null; -diff --git a/src/gov/nist/javax/sip/stack/SIPDialog.java b/src/gov/nist/javax/sip/stack/SIPDialog.java -index 3057675..0f7ec92 100755 ---- a/src/gov/nist/javax/sip/stack/SIPDialog.java -+++ b/src/gov/nist/javax/sip/stack/SIPDialog.java -@@ -45,6 +45,7 @@ import gov.nist.javax.sip.header.ContactList; - import gov.nist.javax.sip.header.ContentLength; - import gov.nist.javax.sip.header.ContentType; - import gov.nist.javax.sip.header.From; -+import gov.nist.javax.sip.header.HeaderFactoryImpl; - import gov.nist.javax.sip.header.MaxForwards; - import gov.nist.javax.sip.header.RAck; - import gov.nist.javax.sip.header.RSeq; -@@ -67,6 +68,12 @@ import gov.nist.javax.sip.message.SIPDuplicateHeaderException; - import gov.nist.javax.sip.message.SIPMessage; - import gov.nist.javax.sip.message.SIPRequest; - import gov.nist.javax.sip.message.SIPResponse; -+import gov.nist.javax.sip.parser.AddressParser; -+import gov.nist.javax.sip.parser.CallIDParser; -+import gov.nist.javax.sip.parser.ContactParser; -+import gov.nist.javax.sip.parser.HeaderParser; -+import gov.nist.javax.sip.parser.ParserFactory; -+import gov.nist.javax.sip.parser.RecordRouteParser; - - import java.io.IOException; - import java.io.PrintWriter; -@@ -157,11 +164,12 @@ public class SIPDialog implements javax.sip.Dialog, DialogExt { - private transient Object applicationData; // Opaque pointer to application data. - - private transient SIPRequest originalRequest; -+ private transient String originalRequestRecordRouteHeadersString; - private transient RecordRouteList originalRequestRecordRouteHeaders; - - // Last response (JvB: either sent or received). - // private SIPResponse lastResponse; -- protected Collection lastResponseHeaders; -+ protected Collection lastResponseHeaders; - protected String lastResponseDialogId; - protected Via lastResponseTopMostVia; - protected Integer lastResponseStatusCode; -@@ -213,10 +221,13 @@ public class SIPDialog implements javax.sip.Dialog, DialogExt { - // Dialog. - - protected javax.sip.address.Address localParty; -+ protected String localPartyStringified; - - protected javax.sip.address.Address remoteParty; -+ private String remotePartyStringified; - - protected CallIdHeader callIdHeader; -+ protected String callIdHeaderString; - - public final static int NULL_STATE = -1; - -@@ -241,6 +252,7 @@ public class SIPDialog implements javax.sip.Dialog, DialogExt { - // requests - - private Address remoteTarget; -+ private String remoteTargetStringified; - - private EventHeader eventHeader; // for Subscribe notify - -@@ -284,7 +296,7 @@ public class SIPDialog implements javax.sip.Dialog, DialogExt { - protected String firstTransactionMergeId; - protected int firstTransactionPort = 5060; - protected Contact contactHeader; -- -+ protected String contactHeaderStringified; - - // ////////////////////////////////////////////////////// - // Inner classes -@@ -570,7 +582,46 @@ public class SIPDialog implements javax.sip.Dialog, DialogExt { - eventListeners = new CopyOnWriteArraySet(); - } - -- public void cleanUp() { -+ protected void cleanUpOnAck() { -+ if(originalRequest != null) { -+// originalRequestRecordRouteHeaders = originalRequest.getRecordRouteHeaders(); -+ if(originalRequestRecordRouteHeaders != null) { -+ originalRequestRecordRouteHeadersString = originalRequestRecordRouteHeaders.toString(); -+ } -+ originalRequestRecordRouteHeaders = null; -+ originalRequest = null; -+ } -+ if(firstTransaction != null) { -+ firstTransaction.getOriginalRequest().cleanUp(); -+ firstTransaction = null; -+ } -+ if(lastTransaction != null) { -+ lastTransaction.getOriginalRequest().cleanUp(); -+ lastTransaction = null; -+ } -+ if(callIdHeader != null) { -+ callIdHeaderString = callIdHeader.toString(); -+ callIdHeader = null; -+ } -+ if(contactHeader != null) { -+ contactHeaderStringified = contactHeader.toString(); -+ contactHeader = null; -+ } -+ if(remoteTarget != null) { -+ remoteTargetStringified = remoteTarget.toString(); -+ remoteTarget = null; -+ } -+ if(remoteParty != null) { -+ remotePartyStringified = remoteParty.toString(); -+ remoteParty = null; -+ } -+ if(localParty != null) { -+ localPartyStringified = localParty.toString(); -+ localParty = null; -+ } -+ } -+ -+ protected void cleanUp() { - if(eventListeners != null) { - eventListeners.clear(); - } -@@ -602,6 +653,7 @@ public class SIPDialog implements javax.sip.Dialog, DialogExt { - if(originalRequestRecordRouteHeaders != null) { - originalRequestRecordRouteHeaders.clear(); - originalRequestRecordRouteHeaders = null; -+ originalRequestRecordRouteHeadersString = null; - } - remoteTarget = null; - if(routeList != null) { -@@ -610,6 +662,18 @@ public class SIPDialog implements javax.sip.Dialog, DialogExt { - } - } - -+ protected RecordRouteList getOriginalRequestRecordRouteHeaders() { -+ if(originalRequestRecordRouteHeaders == null && originalRequestRecordRouteHeadersString != null) { -+ try { -+ originalRequestRecordRouteHeaders = (RecordRouteList) new RecordRouteParser(originalRequestRecordRouteHeadersString).parse(); -+ } catch (ParseException e) { -+ sipStack.getStackLogger().logError("error reparsing the originalRequest RecordRoute Headers", e); -+ } -+ originalRequestRecordRouteHeadersString = null; -+ } -+ return originalRequestRecordRouteHeaders; -+ } -+ - private void recordStackTrace() { - StringWriter stringWriter = new StringWriter(); - PrintWriter writer = new PrintWriter(stringWriter); -@@ -980,10 +1044,7 @@ public class SIPDialog implements javax.sip.Dialog, DialogExt { - */ - private void sendAck(Request request, boolean throwIOExceptionAsSipException) - throws SipException { -- if(originalRequest != null) { -- originalRequestRecordRouteHeaders = originalRequest.getRecordRouteHeaders(); -- originalRequest = null; -- } -+ - SIPRequest ackRequest = (SIPRequest) request; - if (sipStack.isLoggingEnabled()) - sipStack.getStackLogger().logDebug("sendAck" + this); -@@ -1046,9 +1107,7 @@ public class SIPDialog implements javax.sip.Dialog, DialogExt { - - this.setLastAckSent(ackRequest); - messageChannel.sendMessage(ackRequest); -- // Sent atleast one ACK. -- firstTransaction = null; -- lastTransaction = null; -+ cleanUpOnAck(); - this.isAcknowledged = true; - this.highestSequenceNumberAcknowledged = Math.max(this.highestSequenceNumberAcknowledged, - ((SIPRequest)ackRequest).getCSeq().getSeqNumber()); -@@ -1117,10 +1176,6 @@ public class SIPDialog implements javax.sip.Dialog, DialogExt { - * Mark that the dialog has seen an ACK. - */ - void ackReceived(long cseqNumber) { -- if(originalRequest != null) { -- originalRequestRecordRouteHeaders = originalRequest.getRecordRouteHeaders(); -- originalRequest = null; -- } - // Suppress retransmission of the final response - if (this.isAckSeen()) { - sipStack.getStackLogger().logDebug("Ack already seen for response -- dropping"); -@@ -1157,8 +1212,7 @@ public class SIPDialog implements javax.sip.Dialog, DialogExt { - } else { - sipStack.getStackLogger().logDebug("tr is null -- not updating the ack state" ); - } -- firstTransaction = null; -- lastTransaction = null; -+ cleanUpOnAck(); - } - - /** -@@ -1890,6 +1944,14 @@ public class SIPDialog implements javax.sip.Dialog, DialogExt { - * @see javax.sip.Dialog#getCallId() - */ - public CallIdHeader getCallId() { -+ if(callIdHeader == null && callIdHeaderString != null) { -+ try { -+ this.callIdHeader = (CallIdHeader) new CallIDParser(callIdHeaderString).parse(); -+ } catch (ParseException e) { -+ sipStack.getStackLogger().logError("error reparsing the call id header", e); -+ } -+ callIdHeaderString = null; -+ } - return this.callIdHeader; - } - -@@ -1907,6 +1969,14 @@ public class SIPDialog implements javax.sip.Dialog, DialogExt { - */ - - public javax.sip.address.Address getLocalParty() { -+ if(localParty == null && localPartyStringified != null) { -+ try { -+ this.localParty = (Address) new AddressParser(localPartyStringified).address(true); -+ } catch (ParseException e) { -+ sipStack.getStackLogger().logError("error reparsing the localParty", e); -+ } -+ localPartyStringified = null; -+ } - return this.localParty; - } - -@@ -1929,6 +1999,14 @@ public class SIPDialog implements javax.sip.Dialog, DialogExt { - */ - public javax.sip.address.Address getRemoteParty() { - -+ if(remoteParty == null && remotePartyStringified != null) { -+ try { -+ this.remoteParty = (Address) new AddressParser(remotePartyStringified).address(true); -+ } catch (ParseException e) { -+ sipStack.getStackLogger().logError("error reparsing the remoteParty", e); -+ } -+ remotePartyStringified = null; -+ } - if (sipStack.isLoggingEnabled()) { - sipStack.getStackLogger().logDebug("gettingRemoteParty " + this.remoteParty); - } -@@ -1942,7 +2020,14 @@ public class SIPDialog implements javax.sip.Dialog, DialogExt { - * @see javax.sip.Dialog#getRemoteTarget() - */ - public javax.sip.address.Address getRemoteTarget() { -- -+ if(remoteTarget == null && remoteTargetStringified != null) { -+ try { -+ this.remoteTarget = (Address) new AddressParser(remoteTargetStringified).address(true); -+ } catch (ParseException e) { -+ sipStack.getStackLogger().logError("error reparsing the remoteTarget", e); -+ } -+ remoteTargetStringified = null; -+ } - return this.remoteTarget; - } - -@@ -2152,9 +2237,17 @@ public class SIPDialog implements javax.sip.Dialog, DialogExt { - newRequest.setHeader(cseq); - newRequest.setHeader(from); - newRequest.setHeader(to); -- Iterator headerIterator = lastResponseHeaders.iterator(); -+ Iterator headerIterator = lastResponseHeaders.iterator(); - while (headerIterator.hasNext()) { -- SIPHeader nextHeader = (SIPHeader) headerIterator.next(); -+ String nextHeaderString = (String) headerIterator.next(); -+ SIPHeader nextHeader = null; -+ try { -+ HeaderParser headerParser = ParserFactory.createParser(nextHeaderString + "\n"); -+ nextHeader = headerParser.parse(); -+ } catch (ParseException ex) { -+ throw new IllegalArgumentException("error reparsing the call id header", ex); -+ } -+ - // // Some headers do not belong in a Request .... - // if (SIPMessage.isResponseHeader(nextHeader) - // || nextHeader instanceof ViaList -@@ -2794,7 +2887,7 @@ public class SIPDialog implements javax.sip.Dialog, DialogExt { - if(lastResponseHeaders != null) { - lastResponseHeaders.clear(); - } -- this.lastResponseHeaders = new CopyOnWriteArrayList(); -+ this.lastResponseHeaders = new CopyOnWriteArrayList(); - Iterator headerIterator = sipResponse.getHeaders(); - while (headerIterator.hasNext()) { - SIPHeader nextHeader = headerIterator.next(); -@@ -2816,7 +2909,7 @@ public class SIPDialog implements javax.sip.Dialog, DialogExt { - || nextHeader instanceof To) { - continue; - } -- lastResponseHeaders.add(nextHeader); -+ lastResponseHeaders.add(nextHeader.toString()); - } - this.setAssigned(); - // Adjust state of the Dialog state machine. -@@ -2931,9 +3024,9 @@ public class SIPDialog implements javax.sip.Dialog, DialogExt { - * execute. - */ - if ( this.getState() != DialogState.CONFIRMED && this.getState() != DialogState.TERMINATED ) { -- if (originalRequestRecordRouteHeaders != null) { -- if (originalRequestRecordRouteHeaders != null) { -- ListIterator it = originalRequestRecordRouteHeaders.listIterator(originalRequestRecordRouteHeaders.size()); -+ if (getOriginalRequestRecordRouteHeaders() != null) { -+// if (originalRequestRecordRouteHeaders != null) { -+ ListIterator it = getOriginalRequestRecordRouteHeaders().listIterator(getOriginalRequestRecordRouteHeaders().size()); - while (it.hasPrevious()) { - RecordRoute rr = (RecordRoute) it.previous(); - Route route = (Route) routeList.getFirst(); -@@ -2942,7 +3035,7 @@ public class SIPDialog implements javax.sip.Dialog, DialogExt { - } else - break; - } -- } -+// } - } - } - -@@ -3362,6 +3455,14 @@ public class SIPDialog implements javax.sip.Dialog, DialogExt { - * @return contact header belonging to the dialog. - */ - public Contact getMyContactHeader() { -+ if(contactHeader == null && contactHeaderStringified != null) { -+ try { -+ this.contactHeader = (Contact) new ContactParser(contactHeaderStringified).parse(); -+ } catch (ParseException e) { -+ sipStack.getStackLogger().logError("error reparsing the contact header", e); -+ } -+ contactHeaderStringified = null; -+ } - return contactHeader; - } - -diff --git a/src/gov/nist/javax/sip/stack/SIPServerTransaction.java b/src/gov/nist/javax/sip/stack/SIPServerTransaction.java -index c971b08..b345d0a 100755 ---- a/src/gov/nist/javax/sip/stack/SIPServerTransaction.java -+++ b/src/gov/nist/javax/sip/stack/SIPServerTransaction.java -@@ -1840,8 +1840,8 @@ public class SIPServerTransaction extends SIPTransaction implements ServerReques - cleanUpOnTimer(); - // it should be available in the processTxTerminatedEvent, so we can nullify it only here - if(originalRequest != null) { -- originalRequestSentBy = originalRequest.getTopmostVia().getSentBy(); -- originalRequestFromTag = originalRequest.getFromTag(); -+// originalRequestSentBy = originalRequest.getTopmostVia().getSentBy(); -+// originalRequestFromTag = originalRequest.getFromTag(); - originalRequest = null; - } - if(inviteTransaction != null) { -@@ -1881,9 +1881,18 @@ public class SIPServerTransaction extends SIPTransaction implements ServerReques - inviteTransaction.releaseSem(); - inviteTransaction = null; - } -- if(originalRequest !=null) { -+ if(originalRequest != null) { - originalRequest.setTransaction(null); - originalRequest.setInviteTransaction(null); -+ if(!originalRequest.getMethod().equalsIgnoreCase(Request.INVITE)) { -+ if(originalRequestSentBy == null) { -+ originalRequestSentBy = originalRequest.getTopmostVia().getSentBy(); -+ } -+ if(originalRequestFromTag == null) { -+ originalRequestFromTag = originalRequest.getFromTag(); -+ } -+ originalRequest.cleanUp(); -+ } - } - if(lastResponse != null) { - lastResponseAsBytes = lastResponse.encodeAsBytes(this.getTransport()); -diff --git a/src/performance/uas/Shootme.java b/src/performance/uas/Shootme.java -index b899593..cbe8de6 100644 ---- a/src/performance/uas/Shootme.java -+++ b/src/performance/uas/Shootme.java -@@ -1,6 +1,7 @@ - package performance.uas; - - import gov.nist.javax.sip.message.RequestExt; -+import gov.nist.javax.sip.parser.selective.SelectiveParserFactory; - - import java.util.Properties; - import java.util.Timer; -@@ -170,7 +171,6 @@ public class Shootme implements SipListener { - serverTransactionId = ((SipProvider)requestEvent.getSource()).getNewServerTransaction(request); - } - serverTransactionId.sendResponse(response); -- - } catch (Exception ex) { - ex.printStackTrace(); - //System.exit(0); -@@ -207,7 +207,7 @@ public class Shootme implements SipListener { - properties.setProperty("gov.nist.javax.sip.RECEIVE_UDP_BUFFER_SIZE", "65536"); - properties.setProperty("gov.nist.javax.sip.SEND_UDP_BUFFER_SIZE", "65536"); - properties.setProperty("gov.nist.javax.sip.CONGESTION_CONTROL_ENABLED", "false"); --// properties.setProperty("gov.nist.javax.sip.MESSAGE_PARSER_FACTORY", LazyMessageParserFactory.class.getName()); -+ properties.setProperty("gov.nist.javax.sip.MESSAGE_PARSER_FACTORY", SelectiveParserFactory.class.getName()); - try { - // Create SipStack object - sipStack = sipFactory.createSipStack(properties); -@@ -251,7 +251,8 @@ public class Shootme implements SipListener { - - public void processTransactionTerminated( - TransactionTerminatedEvent transactionTerminatedEvent) { -- -+ Request request = transactionTerminatedEvent.getServerTransaction().getRequest(); -+// System.out.println(request); - } - - public void processDialogTerminated( diff --git a/src/performance/uas/performance-test-timer.sh b/src/performance/uas/performance-test-timer.sh deleted file mode 100755 index 073b33c5f..000000000 --- a/src/performance/uas/performance-test-timer.sh +++ /dev/null @@ -1,9 +0,0 @@ -killall sipp -rm *.log -export TEST_IP=127.0.0.1 -echo "IP Address for the test is $TEST_IP" - -echo "Attempting to start sipp script"; -#sipp $TEST_IP:5080 -sf performance-uac-timer.xml -trace_err -i $TEST_IP -p 5055 -r 200 -m 10000000 -sipp $TEST_IP:5080 -sf performance-uac-timer.xml -trace_err -i $TEST_IP -p 5055 -r 500 -m 1 - diff --git a/src/performance/uas/performance-test.sh b/src/performance/uas/performance-test.sh index 289eb9c2c..92dce7ec3 100755 --- a/src/performance/uas/performance-test.sh +++ b/src/performance/uas/performance-test.sh @@ -4,6 +4,5 @@ export TEST_IP=127.0.0.1 echo "IP Address for the test is $TEST_IP" echo "Attempting to start sipp script"; -sipp $TEST_IP:5080 -sf performance-uac.xml -trace_err -i $TEST_IP -p 5055 -r 200 -m 10000000 -#sipp $TEST_IP:5080 -sf performance-uac.xml -trace_err -i $TEST_IP -p 5055 -r 200 -m 1 +sipp $TEST_IP:5080 -sf performance-uac.xml -trace_err -i $TEST_IP -p 5055 -r 1 -m 50000000000 diff --git a/src/performance/uas/performance-uac-timer.xml b/src/performance/uas/performance-uac-timer.xml deleted file mode 100644 index 8dee7a44e..000000000 --- a/src/performance/uas/performance-uac-timer.xml +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - ;tag=[call_number] - To: sut - Call-ID: [call_id] - CSeq: 1 INVITE - Contact: sip:sipp@[local_ip]:[local_port] - Max-Forwards: 70 - Subject: Performance Test - Content-Type: application/sdp - Content-Length: [len] - - v=0 - o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip] - s=- - c=IN IP[media_ip_type] [media_ip] - t=0 0 - m=audio [media_port] RTP/AVP 0 - a=rtpmap:0 PCMU/8000 - - ]]> - - - - - - - - - - - - - - - - - - - - ;tag=[call_number] - To: sut [peer_tag_param] - Call-ID: [call_id] - CSeq: 1 ACK - Contact: sip:sipp@[local_ip]:[local_port] - Max-Forwards: 70 - [routes] - Subject: Performance Test - Content-Length: 0 - - ]]> - - - - - - - - - - - - - - diff --git a/src/test/gov/nist/javax/sdp/parser/SdpParserTest.java b/src/test/gov/nist/javax/sdp/parser/SdpParserTest.java index 42e167a84..60eef833b 100644 --- a/src/test/gov/nist/javax/sdp/parser/SdpParserTest.java +++ b/src/test/gov/nist/javax/sdp/parser/SdpParserTest.java @@ -1,16 +1,13 @@ package test.gov.nist.javax.sdp.parser; -import gov.nist.javax.sdp.SessionDescriptionImpl; -import gov.nist.javax.sdp.parser.SDPAnnounceParser; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.ObjectOutputStream; import java.util.Vector; import javax.sdp.Attribute; import javax.sdp.MediaDescription; +import gov.nist.javax.sdp.SessionDescriptionImpl; +import gov.nist.javax.sdp.fields.AttributeField; +import gov.nist.javax.sdp.parser.SDPAnnounceParser; import junit.framework.TestCase; public class SdpParserTest extends TestCase { @@ -66,12 +63,6 @@ public void testSdpParser() throws Exception { // Unfortunately equals is not yet implemented. // assertEquals("Equality check", // sessiondescription,sessiondescription1); - - // Check if SDP is serializable - File outFile = File.createTempFile("sdpObj",".dat"); - outFile.deleteOnExit(); - ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(outFile, false)); - os.writeObject(sessiondescription1); } } diff --git a/src/test/tck/TestHarness.java b/src/test/tck/TestHarness.java index 8ace98da0..2b4c7893b 100755 --- a/src/test/tck/TestHarness.java +++ b/src/test/tck/TestHarness.java @@ -300,9 +300,9 @@ public static void assertEquals(String reason, Object me, Object him) { if (me == him) { logSuccess("assertEquals : " + reason); } else if (me == null && him != null) { - logFailure("assertEquals failed:" + reason ); + logFailure("assertEquals failed"); } else if (me != null && him == null) { - logFailure("assertEquals failed:" + reason ); + logFailure("assertEquals failed"); } else if (!me.equals(him)) { logFailure(reason); } @@ -443,13 +443,14 @@ static void getRIFactories(boolean autoDialog) { } public void logTestCompleted() { - TestCase.assertTrue( testPassed ); + logger.info(this.getName() + " Completed"); + } public void logTestCompleted(String info) { - TestCase.assertTrue( testPassed ); logger.info(this.getName() + ":" + info +" Completed"); + } diff --git a/src/test/tck/msgflow/InviteServerTransactionsStateMachineTest.java b/src/test/tck/msgflow/InviteServerTransactionsStateMachineTest.java index 98e0e666c..5f1617750 100755 --- a/src/test/tck/msgflow/InviteServerTransactionsStateMachineTest.java +++ b/src/test/tck/msgflow/InviteServerTransactionsStateMachineTest.java @@ -647,10 +647,11 @@ public void testCanceledInvite() { ex.printStackTrace(); fail("The TI failed to send a REQUEST_TERMINATED response"); } - //The Transaction should now be COMPLETED or CONFIRMED. Could be CONFIRMED if it gets an ACK very fast. - assertTrue( + //The Transaction should now be COMPLETED + assertEquals( "The Transaction did not remain COMPLETED after transmitting a REQUEST_TERMINATED response", - tran.getState() == TransactionState.COMPLETED || tran.getState() == TransactionState.CONFIRMED); + TransactionState.COMPLETED, + tran.getState()); //Check whether the BUSY_HERE is received by the RI. waitForMessage(); responseEvent = responseCollector.extractCollectedResponseEvent(); diff --git a/src/test/tck/msgflow/callflows/ProtocolObjects.java b/src/test/tck/msgflow/callflows/ProtocolObjects.java index 77508cd84..59a0d0181 100644 --- a/src/test/tck/msgflow/callflows/ProtocolObjects.java +++ b/src/test/tck/msgflow/callflows/ProtocolObjects.java @@ -38,7 +38,7 @@ public class ProtocolObjects { public ProtocolObjects(String stackname, String pathname, String transport, - boolean autoDialog, boolean isBackToBackUserAgent, boolean isReentrant) { + boolean autoDialog, boolean isBackToBackUserAgent) { this.autoDialog = autoDialog; this.transport = transport; @@ -74,7 +74,8 @@ public ProtocolObjects(String stackname, String pathname, String transport, properties.setProperty("gov.nist.javax.sip.IS_BACK_TO_BACK_USER_AGENT", Boolean.toString(isBackToBackUserAgent)); properties.setProperty("gov.nist.javax.sip.DELIVER_RETRANSMITTED_ACK_TO_LISTENER", "true"); - properties.setProperty("gov.nist.javax.sip.REENTRANT_LISTENER", "" + isReentrant); + + // Set to 0 in your production code for max speed. // You need 16 for logging traces. 32 for debug + traces. diff --git a/src/test/tck/msgflow/callflows/ScenarioHarness.java b/src/test/tck/msgflow/callflows/ScenarioHarness.java index ba51eb106..e5d6a0835 100644 --- a/src/test/tck/msgflow/callflows/ScenarioHarness.java +++ b/src/test/tck/msgflow/callflows/ScenarioHarness.java @@ -32,10 +32,10 @@ public abstract class ScenarioHarness extends TestHarness { public void setUp() throws Exception { if (testedImplFlag) { this.tiProtocolObjects.add(new ProtocolObjects("ti" + super.getName(), "gov.nist", - transport, true,false, false)); + transport, true,false)); this.addRiProtocolObjects(new ProtocolObjects("ri" + super.getName(), super - .getImplementationPath(), transport, true,false, false)); + .getImplementationPath(), transport, true,false)); /* * if (!getImplementationPath().equals("gov.nist")) this.riProtocolObjects = new * ProtocolObjects( super.getName(), super.getImplementationPath(), transport, true); @@ -44,9 +44,9 @@ public void setUp() throws Exception { } else { this.tiProtocolObjects.add(new ProtocolObjects("ti" + super.getName(), - getImplementationPath(), transport, true,false, false)); + getImplementationPath(), transport, true,false)); this.addRiProtocolObjects(new ProtocolObjects("ri" + super.getName(), "gov.nist", - transport, true,false, false)); + transport, true,false)); /* * if (!getImplementationPath().equals("gov.nist")) this.riProtocolObjects = new @@ -61,12 +61,12 @@ public void setUp(int nri, int nti) throws Exception { if (testedImplFlag) { for (int i = 0; i < nti; i++) { this.tiProtocolObjects.add(new ProtocolObjects("ti" + super.getName() + i, - "gov.nist", transport, true,false, false)); + "gov.nist", transport, true,false)); } for (int i = 0; i < nri; i++) { this.addRiProtocolObjects(new ProtocolObjects("ri" + super.getName() + i, super - .getImplementationPath(), transport, true,false, false)); + .getImplementationPath(), transport, true,false)); } /* * if (!getImplementationPath().equals("gov.nist")) this.riProtocolObjects = new @@ -77,11 +77,11 @@ public void setUp(int nri, int nti) throws Exception { } else { for (int i = 0; i < nti; i++) { this.tiProtocolObjects.add(new ProtocolObjects("ti" + super.getName() + i, - getImplementationPath(), transport, true,false, false)); + getImplementationPath(), transport, true,false)); } for (int i = 0; i < nri; i++) { this.addRiProtocolObjects(new ProtocolObjects("ri" + super.getName() + i, - "gov.nist", transport, true,false, false)); + "gov.nist", transport, true,false)); } /* @@ -96,10 +96,10 @@ public void setUp(int nri, int nti) throws Exception { public void setUp(boolean riAutoDialog) throws Exception { if (testedImplFlag) { this.tiProtocolObjects.add(new ProtocolObjects("ti" + super.getName(), "gov.nist", - transport, true, false, false)); + transport, true, false)); this.addRiProtocolObjects(new ProtocolObjects("ri" + super.getName(), super - .getImplementationPath(), transport, riAutoDialog,false, false)); + .getImplementationPath(), transport, riAutoDialog,false)); /* * if (!getImplementationPath().equals("gov.nist")) this.riProtocolObjects = new * ProtocolObjects( super.getName(), super.getImplementationPath(), transport, true); @@ -108,9 +108,9 @@ public void setUp(boolean riAutoDialog) throws Exception { } else { this.tiProtocolObjects.add(new ProtocolObjects("ti" + super.getName(), - getImplementationPath(), transport, true,false, false)); + getImplementationPath(), transport, true,false)); this.addRiProtocolObjects(new ProtocolObjects("ri" + super.getName(), "gov.nist", - transport, riAutoDialog,false, false)); + transport, riAutoDialog,false)); /* * if (!getImplementationPath().equals("gov.nist")) this.riProtocolObjects = new @@ -125,22 +125,22 @@ public void setUp(boolean riAutoDialog, int nri, int nti) { if (testedImplFlag) { for (int i = 0; i < nti; i++) { this.tiProtocolObjects.add(new ProtocolObjects("ti" + super.getName() + i, - "gov.nist", transport, true,false, false)); + "gov.nist", transport, true,false)); } for (int i = 0; i < nri; i++) { this.addRiProtocolObjects(new ProtocolObjects("ri" + super.getName(), super - .getImplementationPath(), transport, riAutoDialog,false, false)); + .getImplementationPath(), transport, riAutoDialog,false)); } } else { for (int i = 0; i < nti; i++) { this.tiProtocolObjects.add(new ProtocolObjects("ti" + super.getName() + i, - getImplementationPath(), transport, true,false, false)); + getImplementationPath(), transport, true,false)); } for (int i = 0; i < nri; i++) { this.addRiProtocolObjects(new ProtocolObjects("ri" + super.getName(), "gov.nist", - transport, riAutoDialog,false, false)); + transport, riAutoDialog,false)); } } diff --git a/src/test/tck/msgflow/callflows/refer/AbstractReferTestCase.java b/src/test/tck/msgflow/callflows/refer/AbstractReferTestCase.java index f212b35ae..3b4d0a6f8 100644 --- a/src/test/tck/msgflow/callflows/refer/AbstractReferTestCase.java +++ b/src/test/tck/msgflow/callflows/refer/AbstractReferTestCase.java @@ -89,7 +89,7 @@ public void tearDown() throws Exception { Thread.sleep(1000); this.providerTable.clear(); - super.assertTrue(" Should have at least 3 NOTIFY", referrer.count >= 3); // Should have 3 NOTIFYs + assertEquals( 3, referrer.count ); // Should have 3 NOTIFYs logTestCompleted(); } catch (Exception ex) { diff --git a/src/test/tck/msgflow/callflows/refer/Referee.java b/src/test/tck/msgflow/callflows/refer/Referee.java index b35b720a1..5d2a6734c 100644 --- a/src/test/tck/msgflow/callflows/refer/Referee.java +++ b/src/test/tck/msgflow/callflows/refer/Referee.java @@ -282,17 +282,10 @@ public void processResponse(ResponseEvent responseReceivedEvent) { Response response = (Response) responseReceivedEvent.getResponse(); Transaction tid = responseReceivedEvent.getClientTransaction(); - if(tid != null) { - logger.info("Response received with client transaction id " - + tid + ":\n" + response.getStatusCode() + - " cseq = " + response.getHeader(CSeqHeader.NAME) + - " dialog " + tid.getDialog()); - } else { - logger.info("Response received with client transaction id " - + tid + ":\n" + response.getStatusCode() + - " cseq = " + response.getHeader(CSeqHeader.NAME) + - " dialog " + responseReceivedEvent.getDialog()); - } + logger.info("Response received with client transaction id " + + tid + ":\n" + response.getStatusCode() + + " cseq = " + response.getHeader(CSeqHeader.NAME) + + " dialog " + tid.getDialog()); CSeqHeader cseq = (CSeqHeader) response.getHeader( CSeqHeader.NAME ); if (cseq.getMethod().equals(Request.INVITE)) { @@ -303,7 +296,7 @@ public void processResponse(ResponseEvent responseReceivedEvent) { TestHarness.fail("Failed to send notify, because of " + e1.getMessage()); } - if (response.getStatusCode() == 200 ) { + if (response.getStatusCode() >= 200 && response.getStatusCode() < 300) { try { Request ack = tid.getDialog().createAck( cseq.getSeqNumber() ); tid.getDialog().sendAck( ack ); diff --git a/src/test/tck/msgflow/callflows/reinvite/Shootme.java b/src/test/tck/msgflow/callflows/reinvite/Shootme.java index 1bf09cb89..398c71d99 100644 --- a/src/test/tck/msgflow/callflows/reinvite/Shootme.java +++ b/src/test/tck/msgflow/callflows/reinvite/Shootme.java @@ -286,7 +286,7 @@ public SipProvider createSipProvider() throws Exception { public static void main(String args[]) throws Exception { logger.addAppender( new ConsoleAppender(new SimpleLayout())); - ProtocolObjects protocolObjects = new ProtocolObjects("shootme", "gov.nist","udp",true,false, false); + ProtocolObjects protocolObjects = new ProtocolObjects("shootme", "gov.nist","udp",true,false); Shootme shootme = new Shootme(protocolObjects); shootme.createSipProvider().addSipListener(shootme); diff --git a/src/test/tck/msgflow/callflows/sctp/Shootme.java b/src/test/tck/msgflow/callflows/sctp/Shootme.java index cf22665e7..249d368ae 100644 --- a/src/test/tck/msgflow/callflows/sctp/Shootme.java +++ b/src/test/tck/msgflow/callflows/sctp/Shootme.java @@ -280,7 +280,7 @@ public SipProvider createSipProvider() throws Exception { public static void main(String args[]) throws Exception { logger.addAppender( new ConsoleAppender(new SimpleLayout())); - ProtocolObjects protocolObjects = new ProtocolObjects("shootme", "gov.nist","udp",true,false, false); + ProtocolObjects protocolObjects = new ProtocolObjects("shootme", "gov.nist","udp",true,false); Shootme shootme = new Shootme(protocolObjects); shootme.createSipProvider().addSipListener(shootme); diff --git a/src/test/tck/msgflow/callflows/tls/Shootme.java b/src/test/tck/msgflow/callflows/tls/Shootme.java index 117b59cf6..445814e4e 100644 --- a/src/test/tck/msgflow/callflows/tls/Shootme.java +++ b/src/test/tck/msgflow/callflows/tls/Shootme.java @@ -280,7 +280,7 @@ public SipProvider createSipProvider() throws Exception { public static void main(String args[]) throws Exception { logger.addAppender( new ConsoleAppender(new SimpleLayout())); - ProtocolObjects protocolObjects = new ProtocolObjects("shootme", "gov.nist","udp",true,false, false); + ProtocolObjects protocolObjects = new ProtocolObjects("shootme", "gov.nist","udp",true,false); Shootme shootme = new Shootme(protocolObjects); shootme.createSipProvider().addSipListener(shootme); diff --git a/src/test/torture/Torture.java b/src/test/torture/Torture.java index 0bec853a4..9f82ca7c2 100755 --- a/src/test/torture/Torture.java +++ b/src/test/torture/Torture.java @@ -356,13 +356,13 @@ public void endElement(String namespaceURI, String local, String name) stringParser = new StringMsgParser(); // stringParser.disableInputTracking(); -// stringParser.setParseExceptionListener(this); + stringParser.setParseExceptionListener(this); SIPMessage sipMessage = null; SIPHeader sipHeader = null; SipUri sipURL = null; try { if (testMessageType.equals(MESSAGE)) { - sipMessage = stringParser.parseSIPMessage(testMessage.getBytes(), true, false, (ParseExceptionListener) this); + sipMessage = stringParser.parseSIPMessage(testMessage); encodedMessage = sipMessage.encode(); } else if (testMessageType.equals(SIP_HEADER)) { sipHeader = stringParser.parseSIPHeader(testMessage); diff --git a/src/test/unit/gov/nist/javax/sip/address/JainSipUriTest.java b/src/test/unit/gov/nist/javax/sip/address/JainSipUriTest.java index 92c22e79d..0bf5e345d 100644 --- a/src/test/unit/gov/nist/javax/sip/address/JainSipUriTest.java +++ b/src/test/unit/gov/nist/javax/sip/address/JainSipUriTest.java @@ -1,9 +1,6 @@ package test.unit.gov.nist.javax.sip.address; -import java.text.ParseException; - import javax.sip.address.SipURI; -import javax.sip.address.URI; /** * Tests from RFC3261 §19.1.4 URI Comparison @@ -31,12 +28,6 @@ public class JainSipUriTest extends junit.framework.TestCase { {"sip:carol@chicago.com", "sip:carol@chicago.com?Subject=next%20meeting"}, {"sip:carol@chicago.com;security=off", "sip:carol@chicago.com;security=on"} }; - - static String[] goodURIs = {"sip:darth-vader@darkstar.org", "tel:+122222222", "sips:yoda@dark-star.org", "urn:service:sos", - "ftp://ftp.is.co.za/rfc/rfc1808.txt","http://www.ietf.org/rfc/rfc2396.txt","ldap://[2001:db8::7]/c=GB?objectClass?one","mailto:John.Doe@example.com", - "news:comp.infosystems.www.servers.unix","tel:+1-816-555-1212","telnet://192.0.2.16:80/","urn:oasis:names:specification:docbook:dtd:xml:4.1.2"}; - - static String[] badURIs = {"darth-vader@darkstar.org", "tel@:+122222222", "darth-vader@127.0.0.1:5080" }; private javax.sip.SipFactory sipFactory; @@ -46,15 +37,9 @@ public void setUp() { } private SipURI sipUri(String uri) throws Exception { - return (SipURI) uri(uri); - } - - - private URI uri(String uri) throws Exception { - return sipFactory.createAddressFactory().createURI(uri); + return (SipURI) sipFactory.createAddressFactory().createURI(uri); } - public void testEqual() throws Exception { for (int i = 0; i < equal.length; i++) { SipURI uri1 = sipUri(equal[i][0]); @@ -72,21 +57,4 @@ public void testDifferent() throws Exception { assertFalse(uri2 + " is the same as " + uri1, uri2.equals(uri1)); } } - - public void testGoodURIs() throws Exception { - for (int i = 0; i < goodURIs.length; i++) { - URI uri = uri(goodURIs[i]); - } - } - - public void testBadURIs() throws Exception { - for (int i = 0; i < badURIs.length; i++) { - try { - URI uri = uri(badURIs[i]); - fail(uri + " should throw parse exception"); - } catch (ParseException e) { - // ok - } - } - } } diff --git a/src/test/unit/gov/nist/javax/sip/parser/AddressParserTest.java b/src/test/unit/gov/nist/javax/sip/parser/AddressParserTest.java index ecc76155f..052cf5800 100755 --- a/src/test/unit/gov/nist/javax/sip/parser/AddressParserTest.java +++ b/src/test/unit/gov/nist/javax/sip/parser/AddressParserTest.java @@ -28,13 +28,11 @@ import gov.nist.javax.sip.parser.AddressParser; import java.text.ParseException; -import java.util.regex.Pattern; import javax.sip.PeerUnavailableException; import javax.sip.SipFactory; import javax.sip.address.Address; import javax.sip.address.AddressFactory; -import javax.sip.address.URI; /** * @@ -78,6 +76,5 @@ public void testParser() { e.printStackTrace(); fail(this.getClass().getName()); } - } } diff --git a/src/test/unit/gov/nist/javax/sip/parser/ContactParserTest.java b/src/test/unit/gov/nist/javax/sip/parser/ContactParserTest.java index 11e383d75..a1de19528 100755 --- a/src/test/unit/gov/nist/javax/sip/parser/ContactParserTest.java +++ b/src/test/unit/gov/nist/javax/sip/parser/ContactParserTest.java @@ -24,16 +24,15 @@ */ package test.unit.gov.nist.javax.sip.parser; +import java.text.ParseException; + +import javax.sip.header.Parameters; + import gov.nist.javax.sip.header.ContactList; -import gov.nist.javax.sip.header.ParametersExt; import gov.nist.javax.sip.header.SIPHeader; import gov.nist.javax.sip.parser.ContactParser; import gov.nist.javax.sip.parser.HeaderParser; -import java.text.ParseException; - -import javax.sip.header.Parameters; - /** * Test case for contact parser * @@ -67,14 +66,14 @@ public void testParser() { // Issue 315 : (https://jain-sip.dev.java.net/issues/show_bug.cgi?id=315) // header.getParameter() doesn't return quoted value - try { - String parameters = "Contact: ;+sip.instance=\"\""; - HeaderParser hp = createParser(ContactParser.class, parameters); - SIPHeader hdr = (SIPHeader) hp.parse(); - assertEquals("\"\"", ((ParametersExt)((ContactList)hdr).getFirst()).getParameter("+sip.instance", false)); - } catch (ParseException ex) { - fail(this.getClass().getName()); - } +// try { +// String parameters = "Contact: ;+sip.instance=\"\""; +// HeaderParser hp = createParser(ContactParser.class, parameters); +// SIPHeader hdr = (SIPHeader) hp.parse(); +// assertEquals("\"\"", ((Parameters)((ContactList)hdr).getFirst()).getParameter("+sip.instance")); +// } catch (ParseException ex) { +// fail(this.getClass().getName()); +// } } } diff --git a/src/test/unit/gov/nist/javax/sip/parser/RussianDisplayNameTest.java b/src/test/unit/gov/nist/javax/sip/parser/RussianDisplayNameTest.java index 6834ab182..10ad1ecbd 100644 --- a/src/test/unit/gov/nist/javax/sip/parser/RussianDisplayNameTest.java +++ b/src/test/unit/gov/nist/javax/sip/parser/RussianDisplayNameTest.java @@ -63,7 +63,7 @@ public void testParseMessage () { StringMsgParser smp = new StringMsgParser(); - SIPMessage message = smp.parseSIPMessage(messageToParse.getBytes("UTF-8"), true, false, null); + SIPMessage message = smp.parseSIPMessage(messageToParse.getBytes("UTF-8")); System.out.println("Message = " + message); @@ -71,7 +71,7 @@ public void testParseMessage () { smp = new StringMsgParser(); - message = smp.parseSIPMessage(bytes, true, false, null); + message = smp.parseSIPMessage(bytes); System.out.println("Message = " + message); char[] mybytes = new char[2]; byte[] sipMessageBytes = new byte[binaryMessage.length()]; @@ -85,13 +85,13 @@ public void testParseMessage () { } smp = new StringMsgParser(); - SIPMessage reparsed = smp.parseSIPMessage(sipMessageBytes, true, false, null); + SIPMessage reparsed = smp.parseSIPMessage(sipMessageBytes); System.out.println("Reparsed = " + reparsed); bytes = message.encodeAsBytes("UDP"); smp = new StringMsgParser(); - reparsed = smp.parseSIPMessage(bytes, true, false, null); + reparsed = smp.parseSIPMessage(bytes); System.out.println("Reparsed = " + reparsed); diff --git a/src/test/unit/gov/nist/javax/sip/stack/CancelEventTest.java b/src/test/unit/gov/nist/javax/sip/stack/CancelEventTest.java index 8a106fc8e..47b7e246b 100644 --- a/src/test/unit/gov/nist/javax/sip/stack/CancelEventTest.java +++ b/src/test/unit/gov/nist/javax/sip/stack/CancelEventTest.java @@ -217,7 +217,7 @@ public void processTimeout(javax.sip.TimeoutEvent timeoutEvent) { logger.info("dialog = " + transaction.getDialog()); logger.info("dialogState = " + transaction.getDialog().getState()); logger.info("Transaction Time out"); - fail("Timeout Shouldnt happen on UAC side!!!"); + fail("Timeout Shouldnt happen on UAS side!!!"); } private void sendCancel() { @@ -431,8 +431,6 @@ class Shootme implements SipListener { HeaderFactory headerFactory; - private boolean dialogOnCancelTx = true; - Shootme () { SipFactory sipFactory = null; String stackname = "shootme"; @@ -572,9 +570,6 @@ public void processCancel(RequestEvent requestEvent, inviteTid.sendResponse(response); } cancelOk = true; - if(serverTransactionId.getDialog() == null) { - dialogOnCancelTx = false; - } } catch (Exception ex) { // logger.error(ex); ex.printStackTrace(); @@ -647,13 +642,8 @@ public void processDialogTerminated( } public boolean conditionMet() { - System.out.println("cancelOK = " + cancelOk); - System.out.println("cancelTerm = " + cancelTxTerm); - System.out.println("inviteTxTerm = " + inviteTxTerm); - System.out.println("dialogTerminated = " + dialogTerminated); - System.out.println("dialogOnCancelTx = " + dialogOnCancelTx); - return cancelOk && cancelTxTerm && inviteTxTerm && dialogTerminated && dialogOnCancelTx; + return cancelOk && cancelTxTerm && inviteTxTerm && dialogTerminated; } public String[] conditionsState() { @@ -695,7 +685,6 @@ public void testCancelEvent() throws Exception { shootist.sendInvite(); Thread.sleep(40000); assertTrue ( shootist.conditionMet()); - assertTrue ( shootme.conditionMet()); } public void tearDown() { diff --git a/src/test/unit/gov/nist/javax/sip/stack/CtxExpiredTest.java b/src/test/unit/gov/nist/javax/sip/stack/CtxExpiredTest.java deleted file mode 100644 index cccd078c7..000000000 --- a/src/test/unit/gov/nist/javax/sip/stack/CtxExpiredTest.java +++ /dev/null @@ -1,441 +0,0 @@ -package test.unit.gov.nist.javax.sip.stack; - -import java.util.ArrayList; -import java.util.Properties; - -import gov.nist.javax.sip.ServerTransactionExt; -import gov.nist.javax.sip.SipProviderExt; -import gov.nist.javax.sip.SipStackExt; -import gov.nist.javax.sip.header.HeaderFactoryExt; -import gov.nist.javax.sip.message.MessageFactoryExt; - -import javax.sip.ClientTransaction; -import javax.sip.Dialog; -import javax.sip.DialogTerminatedEvent; -import javax.sip.IOExceptionEvent; -import javax.sip.ListeningPoint; -import javax.sip.PeerUnavailableException; -import javax.sip.RequestEvent; -import javax.sip.ResponseEvent; -import javax.sip.ServerTransaction; -import javax.sip.SipFactory; -import javax.sip.SipListener; -import javax.sip.TimeoutEvent; -import javax.sip.TransactionState; -import javax.sip.TransactionTerminatedEvent; -import javax.sip.address.Address; -import javax.sip.address.AddressFactory; -import javax.sip.address.SipURI; -import javax.sip.header.CSeqHeader; -import javax.sip.header.CallIdHeader; -import javax.sip.header.ContactHeader; -import javax.sip.header.ContentTypeHeader; -import javax.sip.header.ExpiresHeader; -import javax.sip.header.FromHeader; -import javax.sip.header.Header; -import javax.sip.header.MaxForwardsHeader; -import javax.sip.header.RouteHeader; -import javax.sip.header.ToHeader; -import javax.sip.header.ViaHeader; -import javax.sip.message.Request; -import javax.sip.message.Response; - -import org.apache.log4j.ConsoleAppender; -import org.apache.log4j.Logger; - -import junit.framework.TestCase; - -public class CtxExpiredTest extends TestCase { - - AddressFactory addressFactory; - - HeaderFactoryExt headerFactory; - - MessageFactoryExt messageFactory; - - private Shootist shootist; - - private Shootme shootme; - - private SipStackExt shootistStack; - - private SipStackExt shootmeStack; - - private static String PEER_ADDRESS = Shootme.myAddress; - - private static int PEER_PORT = Shootme.myPort; - - private static String peerHostPort = PEER_ADDRESS + ":" + PEER_PORT; - - private static Logger logger = Logger.getLogger(CtxExpiredTest.class); - static { - logger.addAppender(new ConsoleAppender()); - } - - class Shootist implements SipListener { - - protected static final String myAddress = "127.0.0.1"; - - protected static final int myPort = 6050; - - private SipProviderExt provider; - - private boolean saw1xx; - - private ClientTransaction inviteTid; - - private Dialog dialog; - - private boolean timeoutSeen; - - public void checkState() { - assertTrue("Should see timeout ", timeoutSeen); - assertTrue("Should see 1xx ", saw1xx); - } - - public Shootist(SipStackExt sipStack) throws Exception { - ListeningPoint lp = sipStack.createListeningPoint("127.0.0.1", - myPort, "udp"); - this.provider = (SipProviderExt) sipStack.createSipProvider(lp); - provider.addSipListener(this); - } - - public void sendInvite() { - - try { - - // Note that a provider has multiple listening points. - // all the listening points must have the same IP address - // and port but differ in their transport parameters. - - String fromName = "BigGuy"; - String fromSipAddress = "here.com"; - String fromDisplayName = "The Master Blaster"; - - String toSipAddress = "there.com"; - String toUser = "LittleGuy"; - String toDisplayName = "The Little Blister"; - - // create >From Header - SipURI fromAddress = addressFactory.createSipURI(fromName, - fromSipAddress); - - Address fromNameAddress = addressFactory - .createAddress(fromAddress); - fromNameAddress.setDisplayName(fromDisplayName); - FromHeader fromHeader = headerFactory.createFromHeader( - fromNameAddress, new Integer( - (int) (Math.random() * Integer.MAX_VALUE)) - .toString()); - - // create To Header - SipURI toAddress = addressFactory.createSipURI(toUser, - toSipAddress); - Address toNameAddress = addressFactory.createAddress(toAddress); - toNameAddress.setDisplayName(toDisplayName); - ToHeader toHeader = headerFactory.createToHeader(toNameAddress, - null); - - // create Request URI - SipURI requestURI = addressFactory.createSipURI(toUser, - peerHostPort); - - // Create ViaHeaders - - ArrayList viaHeaders = new ArrayList(); - int port = provider.getListeningPoint("udp").getPort(); - - ViaHeader viaHeader = headerFactory.createViaHeader(myAddress, - port, "udp", null); - - // add via headers - viaHeaders.add(viaHeader); - - // Create ContentTypeHeader - ContentTypeHeader contentTypeHeader = headerFactory - .createContentTypeHeader("application", "sdp"); - - // Create a new CallId header - CallIdHeader callIdHeader = provider.getNewCallId(); - // JvB: Make sure that the implementation matches the - // messagefactory - callIdHeader = headerFactory.createCallIdHeader(callIdHeader - .getCallId()); - - // Create a new Cseq header - CSeqHeader cSeqHeader = headerFactory.createCSeqHeader(1L, - Request.INVITE); - - // Create a new MaxForwardsHeader - MaxForwardsHeader maxForwards = headerFactory - .createMaxForwardsHeader(70); - - // Create the request. - Request request = messageFactory.createRequest(requestURI, - Request.INVITE, callIdHeader, cSeqHeader, fromHeader, - toHeader, viaHeaders, maxForwards); - // Create contact headers - - // Create the contact name address. - SipURI contactURI = addressFactory.createSipURI(fromName, - myAddress); - contactURI.setPort(provider.getListeningPoint("udp").getPort()); - - Address contactAddress = addressFactory - .createAddress(contactURI); - - // Add the contact address. - contactAddress.setDisplayName(fromName); - - ContactHeader contactHeader = headerFactory - .createContactHeader(contactAddress); - request.addHeader(contactHeader); - - ExpiresHeader expires = headerFactory.createExpiresHeader(20); - - request.setHeader(expires); - - String sdpData = "v=0\r\n" - + "o=4855 13760799956958020 13760799956958020" - + " IN IP4 129.6.55.78\r\n" - + "s=mysession session\r\n" + "p=+46 8 52018010\r\n" - + "c=IN IP4 129.6.55.78\r\n" + "t=0 0\r\n" - + "m=audio 6022 RTP/AVP 0 4 18\r\n" - + "a=rtpmap:0 PCMU/8000\r\n" - + "a=rtpmap:4 G723/8000\r\n" - + "a=rtpmap:18 G729A/8000\r\n" + "a=ptime:20\r\n"; - - request.setContent(sdpData, contentTypeHeader); - - // The following is the preferred method to route requests - // to the peer. Create a route header and set the "lr" - // parameter for the router header. - - Address address = addressFactory.createAddress(""); - // SipUri sipUri = (SipUri) address.getURI(); - // sipUri.setPort(PEER_PORT); - - RouteHeader routeHeader = headerFactory - .createRouteHeader(address); - ((SipURI) address.getURI()).setLrParam(); - request.addHeader(routeHeader); - - // Create the client transaction. - this.inviteTid = provider.getNewClientTransaction(request); - this.dialog = this.inviteTid.getDialog(); - // Note that the response may have arrived right away so - // we cannot check after the message is sent. - TestCase - .assertTrue(this.dialog.getState() == null); - - // send the request out. - this.inviteTid.sendRequest(); - - } catch (Exception ex) { - logger.error("Unexpected exception", ex); - TestCase.fail("unexpected exception"); - } - } - - - public void processDialogTerminated( - DialogTerminatedEvent dialogTerminatedEvent) { - - } - - - public void processIOException(IOExceptionEvent exceptionEvent) { - TestCase.fail("Unexpected event"); - } - - - public void processRequest(RequestEvent requestEvent) { - TestCase.fail("Unexpected event : processRequest"); - - } - - - public void processResponse(ResponseEvent responseEvent) { - - if (responseEvent.getResponse().getStatusCode() == 100) { - this.saw1xx = true; - } - } - - - public void processTimeout(TimeoutEvent timeoutEvent) { - this.timeoutSeen = true; - ClientTransaction ctx = timeoutEvent.getClientTransaction(); - TestCase.assertSame("Should see a timeout for INVITE", ctx, - this.inviteTid); - TestCase.assertEquals("Should be in proceeding state", - TransactionState.PROCEEDING, ctx.getState()); - try { - Request cancelRequest = timeoutEvent.getClientTransaction() - .createCancel(); - ClientTransaction cancelTx = this.provider - .getNewClientTransaction(cancelRequest); - cancelTx.sendRequest(); - } catch (Exception ex) { - logger.error("Unexpected exception", ex); - TestCase.fail("Unexpected exception"); - } - - } - - - public void processTransactionTerminated( - TransactionTerminatedEvent transactionTerminatedEvent) { - logger.debug("Transaction Terminated Event seen"); - - } - - } - - public class Shootme implements SipListener { - - public static final int myPort = 6060; - public static final String myAddress = "127.0.0.1"; - private SipProviderExt provider; - - public Shootme(SipStackExt sipStack) throws Exception { - ListeningPoint lp = sipStack.createListeningPoint("127.0.0.1", - myPort, "udp"); - this.provider = (SipProviderExt) sipStack.createSipProvider(lp); - provider.addSipListener(this); - } - - - public void processDialogTerminated( - DialogTerminatedEvent dialogTerminatedEvent) { - // TODO Auto-generated method stub - - } - - - public void processIOException(IOExceptionEvent exceptionEvent) { - // TODO Auto-generated method stub - - } - - - public void processRequest(RequestEvent requestEvent) { - try { - Request request = requestEvent.getRequest(); - - if (request.getMethod().equals(Request.INVITE)) { - if (requestEvent.getServerTransaction() == null) { - - ServerTransactionExt serverTransaction = (ServerTransactionExt) this.provider - .getNewServerTransaction(request); - - Response tryingResponse = messageFactory - .createResponse(100, request); - serverTransaction.sendResponse(tryingResponse); - - } - } else if (request.getMethod().equals(Request.CANCEL)) { - ServerTransaction stx = requestEvent.getServerTransaction(); - Response okResponse = messageFactory.createResponse(200, - request); - stx.sendResponse(okResponse); - - } - } catch (Exception ex) { - logger.error("Unexpected exception", ex); - TestCase.fail("Unexpected exception"); - } - } - - - public void processResponse(ResponseEvent responseEvent) { - // TODO Auto-generated method stub - - } - - - public void processTimeout(TimeoutEvent timeoutEvent) { - // TODO Auto-generated method stub - - } - - - public void processTransactionTerminated( - TransactionTerminatedEvent transactionTerminatedEvent) { - // TODO Auto-generated method stub - - } - - } - - - public void setUp() throws Exception { - SipFactory sipFactory = null; - - sipFactory = SipFactory.getInstance(); - sipFactory.setPathName("gov.nist"); - Properties properties; - - try { - headerFactory = (HeaderFactoryExt) sipFactory.createHeaderFactory(); - addressFactory = sipFactory.createAddressFactory(); - messageFactory = (MessageFactoryExt) sipFactory - .createMessageFactory(); - - } catch (Exception ex) { - ex.printStackTrace(); - fail("Unexpected exception"); - } - try { - // Create SipStack object - properties = new Properties(); - properties.setProperty("javax.sip.STACK_NAME", "shootist"); - // You need 16 for logging traces. 32 for debug + traces. - // Your code will limp at 32 but it is best for debugging. - properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "32"); - properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", - "shootistdebug.txt"); - - - this.shootistStack = (SipStackExt) sipFactory - .createSipStack(properties); - this.shootist = new Shootist(shootistStack); - - // ----------------------------- - properties = new Properties(); - properties.setProperty("javax.sip.STACK_NAME", "shootme"); - // You need 16 for logging traces. 32 for debug + traces. - // Your code will limp at 32 but it is best for debugging. - properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "32"); - properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", - "shootmedebug.txt"); - this.shootmeStack = (SipStackExt) sipFactory - .createSipStack(properties); - this.shootme = new Shootme(shootmeStack); - - } catch (PeerUnavailableException e) { - // could not find - // gov.nist.jain.protocol.ip.sip.SipStackImpl - // in the classpath - e.printStackTrace(); - System.err.println(e.getMessage()); - if (e.getCause() != null) - e.getCause().printStackTrace(); - TestCase.fail("Unexpected exception"); - } - - } - - - public void tearDown() throws Exception { - Thread.sleep(30000); - this.shootist.checkState(); - this.shootistStack.stop(); - this.shootmeStack.stop(); - } - - public void testSendInviteExpectTimeout() { - this.shootist.sendInvite(); - } -} diff --git a/src/test/unit/gov/nist/javax/sip/stack/DialogEarlyStateTimeoutTest.java b/src/test/unit/gov/nist/javax/sip/stack/DialogEarlyStateTimeoutTest.java deleted file mode 100644 index 6105c8e3e..000000000 --- a/src/test/unit/gov/nist/javax/sip/stack/DialogEarlyStateTimeoutTest.java +++ /dev/null @@ -1,471 +0,0 @@ -package test.unit.gov.nist.javax.sip.stack; - -import gov.nist.javax.sip.DialogTimeoutEvent; -import gov.nist.javax.sip.ServerTransactionExt; -import gov.nist.javax.sip.SipListenerExt; -import gov.nist.javax.sip.SipProviderExt; -import gov.nist.javax.sip.SipStackExt; -import gov.nist.javax.sip.header.HeaderFactoryExt; -import gov.nist.javax.sip.message.MessageFactoryExt; - -import java.util.ArrayList; -import java.util.Properties; - -import javax.sip.ClientTransaction; -import javax.sip.Dialog; -import javax.sip.DialogTerminatedEvent; -import javax.sip.IOExceptionEvent; -import javax.sip.ListeningPoint; -import javax.sip.PeerUnavailableException; -import javax.sip.RequestEvent; -import javax.sip.ResponseEvent; -import javax.sip.ServerTransaction; -import javax.sip.SipFactory; -import javax.sip.SipListener; -import javax.sip.TimeoutEvent; -import javax.sip.TransactionState; -import javax.sip.TransactionTerminatedEvent; -import javax.sip.address.Address; -import javax.sip.address.AddressFactory; -import javax.sip.address.SipURI; -import javax.sip.header.CSeqHeader; -import javax.sip.header.CallIdHeader; -import javax.sip.header.ContactHeader; -import javax.sip.header.ContentTypeHeader; -import javax.sip.header.ExpiresHeader; -import javax.sip.header.FromHeader; -import javax.sip.header.MaxForwardsHeader; -import javax.sip.header.RouteHeader; -import javax.sip.header.ToHeader; -import javax.sip.header.ViaHeader; -import javax.sip.message.Request; -import javax.sip.message.Response; - -import org.apache.log4j.ConsoleAppender; -import org.apache.log4j.Logger; - -import test.unit.gov.nist.javax.sip.stack.CtxExpiredTest.Shootist; -import test.unit.gov.nist.javax.sip.stack.CtxExpiredTest.Shootme; -import junit.framework.TestCase; - -public class DialogEarlyStateTimeoutTest extends TestCase { - AddressFactory addressFactory; - - HeaderFactoryExt headerFactory; - - MessageFactoryExt messageFactory; - - private Shootist shootist; - - private Shootme shootme; - - private SipStackExt shootistStack; - - private SipStackExt shootmeStack; - - private static String PEER_ADDRESS = Shootme.myAddress; - - private static int PEER_PORT = Shootme.myPort; - - private static String peerHostPort = PEER_ADDRESS + ":" + PEER_PORT; - - private static Logger logger = Logger.getLogger(CtxExpiredTest.class); - static { - logger.addAppender(new ConsoleAppender()); - } - - class Shootist implements SipListenerExt { - - protected static final String myAddress = "127.0.0.1"; - - protected static final int myPort = 6050; - - private SipProviderExt provider; - - private boolean saw1xx; - - private ClientTransaction inviteTid; - - private Dialog dialog; - - private boolean timeoutSeen; - - private Dialog timeoutDialog; - - public void checkState() { - assertTrue("Should see timeout ", timeoutSeen); - assertTrue("Should see 1xx ", saw1xx); - assertEquals("Dialog must be inviteDIalog", this.dialog, - timeoutDialog); - } - - public Shootist(SipStackExt sipStack) throws Exception { - ListeningPoint lp = sipStack.createListeningPoint("127.0.0.1", - myPort, "udp"); - this.provider = (SipProviderExt) sipStack.createSipProvider(lp); - provider.addSipListener(this); - } - - public void sendInvite() { - - try { - - // Note that a provider has multiple listening points. - // all the listening points must have the same IP address - // and port but differ in their transport parameters. - - String fromName = "BigGuy"; - String fromSipAddress = "here.com"; - String fromDisplayName = "The Master Blaster"; - - String toSipAddress = "there.com"; - String toUser = "LittleGuy"; - String toDisplayName = "The Little Blister"; - - // create >From Header - SipURI fromAddress = addressFactory.createSipURI(fromName, - fromSipAddress); - - Address fromNameAddress = addressFactory - .createAddress(fromAddress); - fromNameAddress.setDisplayName(fromDisplayName); - FromHeader fromHeader = headerFactory.createFromHeader( - fromNameAddress, new Integer( - (int) (Math.random() * Integer.MAX_VALUE)) - .toString()); - - // create To Header - SipURI toAddress = addressFactory.createSipURI(toUser, - toSipAddress); - Address toNameAddress = addressFactory.createAddress(toAddress); - toNameAddress.setDisplayName(toDisplayName); - ToHeader toHeader = headerFactory.createToHeader(toNameAddress, - null); - - // create Request URI - SipURI requestURI = addressFactory.createSipURI(toUser, - peerHostPort); - - // Create ViaHeaders - - ArrayList viaHeaders = new ArrayList(); - int port = provider.getListeningPoint("udp").getPort(); - - ViaHeader viaHeader = headerFactory.createViaHeader(myAddress, - port, "udp", null); - - // add via headers - viaHeaders.add(viaHeader); - - // Create ContentTypeHeader - ContentTypeHeader contentTypeHeader = headerFactory - .createContentTypeHeader("application", "sdp"); - - // Create a new CallId header - CallIdHeader callIdHeader = provider.getNewCallId(); - // JvB: Make sure that the implementation matches the - // messagefactory - callIdHeader = headerFactory.createCallIdHeader(callIdHeader - .getCallId()); - - // Create a new Cseq header - CSeqHeader cSeqHeader = headerFactory.createCSeqHeader(1L, - Request.INVITE); - - // Create a new MaxForwardsHeader - MaxForwardsHeader maxForwards = headerFactory - .createMaxForwardsHeader(70); - - // Create the request. - Request request = messageFactory.createRequest(requestURI, - Request.INVITE, callIdHeader, cSeqHeader, fromHeader, - toHeader, viaHeaders, maxForwards); - // Create contact headers - - // Create the contact name address. - SipURI contactURI = addressFactory.createSipURI(fromName, - myAddress); - contactURI.setPort(provider.getListeningPoint("udp").getPort()); - - Address contactAddress = addressFactory - .createAddress(contactURI); - - // Add the contact address. - contactAddress.setDisplayName(fromName); - - ContactHeader contactHeader = headerFactory - .createContactHeader(contactAddress); - request.addHeader(contactHeader); - - String sdpData = "v=0\r\n" - + "o=4855 13760799956958020 13760799956958020" - + " IN IP4 129.6.55.78\r\n" - + "s=mysession session\r\n" + "p=+46 8 52018010\r\n" - + "c=IN IP4 129.6.55.78\r\n" + "t=0 0\r\n" - + "m=audio 6022 RTP/AVP 0 4 18\r\n" - + "a=rtpmap:0 PCMU/8000\r\n" - + "a=rtpmap:4 G723/8000\r\n" - + "a=rtpmap:18 G729A/8000\r\n" + "a=ptime:20\r\n"; - - request.setContent(sdpData, contentTypeHeader); - - // The following is the preferred method to route requests - // to the peer. Create a route header and set the "lr" - // parameter for the router header. - - Address address = addressFactory.createAddress(""); - // SipUri sipUri = (SipUri) address.getURI(); - // sipUri.setPort(PEER_PORT); - - RouteHeader routeHeader = headerFactory - .createRouteHeader(address); - ((SipURI) address.getURI()).setLrParam(); - request.addHeader(routeHeader); - - // Create the client transaction. - this.inviteTid = provider.getNewClientTransaction(request); - this.dialog = this.inviteTid.getDialog(); - // Note that the response may have arrived right away so - // we cannot check after the message is sent. - TestCase.assertTrue(this.dialog.getState() == null); - - // send the request out. - - this.inviteTid.sendRequest(); - - } catch (Exception ex) { - logger.error("Unexpected exception", ex); - TestCase.fail("unexpected exception"); - } - } - - - public void processDialogTerminated( - DialogTerminatedEvent dialogTerminatedEvent) { - - } - - - public void processIOException(IOExceptionEvent exceptionEvent) { - TestCase.fail("Unexpected event"); - } - - - public void processRequest(RequestEvent requestEvent) { - TestCase.fail("Unexpected event : processRequest"); - - } - - - public void processResponse(ResponseEvent responseEvent) { - - if (responseEvent.getResponse().getStatusCode() == 100) { - this.saw1xx = true; - } - } - - - public void processTimeout(TimeoutEvent timeoutEvent) { - TestCase.fail("No timeout should be seen here"); - - } - - - public void processTransactionTerminated( - TransactionTerminatedEvent transactionTerminatedEvent) { - logger.debug("Transaction Terminated Event seen"); - - } - - - public void processDialogTimeout(DialogTimeoutEvent timeoutEvent) { - try { - this.timeoutSeen = true; - this.timeoutDialog = timeoutEvent.getDialog(); - Dialog dialog = timeoutEvent.getDialog(); - dialog.delete(); - Request cancelRequest = inviteTid.createCancel(); - ClientTransaction cancelTx = this.provider - .getNewClientTransaction(cancelRequest); - cancelTx.sendRequest(); - } catch (Exception exception) { - exception.printStackTrace(); - logger.error("Unexpected exception", exception); - TestCase.fail("unexpected exception"); - } - - } - - } - - public class Shootme implements SipListener { - - public static final int myPort = 6060; - public static final String myAddress = "127.0.0.1"; - private SipProviderExt provider; - private boolean cancelSeen; - private boolean byeSeen; - - public void checkState() { - TestCase.assertTrue("Should see cancel", cancelSeen); - } - - public Shootme(SipStackExt sipStack) throws Exception { - ListeningPoint lp = sipStack.createListeningPoint("127.0.0.1", - myPort, "udp"); - this.provider = (SipProviderExt) sipStack.createSipProvider(lp); - provider.addSipListener(this); - } - - - public void processDialogTerminated( - DialogTerminatedEvent dialogTerminatedEvent) { - // TODO Auto-generated method stub - - } - - - public void processIOException(IOExceptionEvent exceptionEvent) { - // TODO Auto-generated method stub - - } - - - public void processRequest(RequestEvent requestEvent) { - try { - Request request = requestEvent.getRequest(); - - if (request.getMethod().equals(Request.INVITE)) { - if (requestEvent.getServerTransaction() == null) { - - ServerTransactionExt serverTransaction = (ServerTransactionExt) this.provider - .getNewServerTransaction(request); - - Response tryingResponse = messageFactory - .createResponse(100, request); - serverTransaction.sendResponse(tryingResponse); - Thread.sleep(1000); - Response ringingResponse = messageFactory - .createResponse(Response.RINGING, request); - - serverTransaction.sendResponse(ringingResponse); - - } - } else if (request.getMethod().equals(Request.CANCEL)) { - ServerTransaction stx = requestEvent.getServerTransaction(); - Response okResponse = messageFactory.createResponse(200, - request); - stx.sendResponse(okResponse); - this.cancelSeen = true; - - } else if (request.getMethod().equals(Request.BYE)) { - ServerTransaction stx = requestEvent.getServerTransaction(); - Response okResponse = messageFactory.createResponse(200, - request); - stx.sendResponse(okResponse); - this.byeSeen = true; - - } - } catch (Exception ex) { - logger.error("Unexpected exception", ex); - TestCase.fail("Unexpected exception"); - } - } - - - public void processResponse(ResponseEvent responseEvent) { - // TODO Auto-generated method stub - - } - - - public void processTimeout(TimeoutEvent timeoutEvent) { - // TODO Auto-generated method stub - - } - - - public void processTransactionTerminated( - TransactionTerminatedEvent transactionTerminatedEvent) { - // TODO Auto-generated method stub - - } - - } - - - public void setUp() throws Exception { - SipFactory sipFactory = null; - - sipFactory = SipFactory.getInstance(); - sipFactory.setPathName("gov.nist"); - Properties properties; - - try { - headerFactory = (HeaderFactoryExt) sipFactory.createHeaderFactory(); - addressFactory = sipFactory.createAddressFactory(); - messageFactory = (MessageFactoryExt) sipFactory - .createMessageFactory(); - - } catch (Exception ex) { - ex.printStackTrace(); - fail("Unexpected exception"); - } - try { - // Create SipStack object - properties = new Properties(); - properties.setProperty("javax.sip.STACK_NAME", "shootist"); - // You need 16 for logging traces. 32 for debug + traces. - // Your code will limp at 32 but it is best for debugging. - properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "32"); - properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", - "shootistdebug.txt"); - - properties.setProperty( - "gov.nist.javax.sip.EARLY_DIALOG_TIMEOUT_SECONDS", "30"); - - this.shootistStack = (SipStackExt) sipFactory - .createSipStack(properties); - this.shootist = new Shootist(shootistStack); - - // ----------------------------- - properties = new Properties(); - properties.setProperty("javax.sip.STACK_NAME", "shootme"); - // You need 16 for logging traces. 32 for debug + traces. - // Your code will limp at 32 but it is best for debugging. - properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "32"); - properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", - "shootmedebug.txt"); - properties.setProperty( - "gov.nist.javax.sip.EARLY_DIALOG_TIMEOUT_SECONDS", "30"); - this.shootmeStack = (SipStackExt) sipFactory - .createSipStack(properties); - this.shootme = new Shootme(shootmeStack); - - } catch (PeerUnavailableException e) { - // could not find - // gov.nist.jain.protocol.ip.sip.SipStackImpl - // in the classpath - e.printStackTrace(); - System.err.println(e.getMessage()); - if (e.getCause() != null) - e.getCause().printStackTrace(); - TestCase.fail("Unexpected exception"); - } - - } - - - public void tearDown() throws Exception { - Thread.sleep(50000); - this.shootist.checkState(); - this.shootme.checkState(); - this.shootistStack.stop(); - this.shootmeStack.stop(); - } - - public void testSendInviteExpectTimeout() { - this.shootist.sendInvite(); - } -} diff --git a/src/test/unit/gov/nist/javax/sip/stack/DialogIdentityTest.java b/src/test/unit/gov/nist/javax/sip/stack/DialogIdentityTest.java index 31b4ed318..e0f0738cc 100644 --- a/src/test/unit/gov/nist/javax/sip/stack/DialogIdentityTest.java +++ b/src/test/unit/gov/nist/javax/sip/stack/DialogIdentityTest.java @@ -70,8 +70,6 @@ class Shootme implements SipListener { private Dialog dialog; - private boolean setToTagOn180; - public static final boolean callerSendsBye = true; class MyTimerTask extends TimerTask { @@ -94,10 +92,6 @@ public void run() { - public Shootme(boolean b) { - this.setToTagOn180 = b; - } - public void processRequest(RequestEvent requestEvent) { Request request = requestEvent.getRequest(); ServerTransaction serverTransactionId = requestEvent @@ -174,10 +168,6 @@ public void processInvite(RequestEvent requestEvent, // System.out.println("shootme: " + request); Response response = messageFactory.createResponse(Response.RINGING, request); - if(setToTagOn180) { - ToHeader toHeader = (ToHeader) response.getHeader(ToHeader.NAME); - toHeader.setTag("4321"); // Application is supposed to set. - } ServerTransaction st = requestEvent.getServerTransaction(); if (st == null) { @@ -744,7 +734,7 @@ public void testDialogIdentity() throws Exception { Shootist shootist = new Shootist(); - Shootme shootme = new Shootme(false); + Shootme shootme = new Shootme(); shootme.init(); shootist.init(); @@ -753,20 +743,8 @@ public void testDialogIdentity() throws Exception { shootist.stop(); shootme.stop(); - } - - public void testDialogIdentity180HasToTag() throws Exception { - Shootist shootist = new Shootist(); - Shootme shootme = new Shootme(true); - shootme.init(); - shootist.init(); - - Thread.sleep(10000); - - shootist.stop(); - shootme.stop(); -} + } } diff --git a/src/test/unit/gov/nist/javax/sip/stack/LooseDialogValidationTest.java b/src/test/unit/gov/nist/javax/sip/stack/LooseDialogValidationTest.java index f7330a0ca..141bbfd0d 100644 --- a/src/test/unit/gov/nist/javax/sip/stack/LooseDialogValidationTest.java +++ b/src/test/unit/gov/nist/javax/sip/stack/LooseDialogValidationTest.java @@ -614,7 +614,7 @@ public void testCSeqValidationIsOff() { this.shootme.init(); this.shootist.init(); try { - Thread.sleep(10000); + Thread.sleep(7000); } catch (Exception ex) { } diff --git a/src/test/unit/gov/nist/javax/sip/stack/ReInviteBusyTest.java b/src/test/unit/gov/nist/javax/sip/stack/ReInviteBusyTest.java index 4e39d3e2f..121c4f4f4 100644 --- a/src/test/unit/gov/nist/javax/sip/stack/ReInviteBusyTest.java +++ b/src/test/unit/gov/nist/javax/sip/stack/ReInviteBusyTest.java @@ -24,12 +24,14 @@ -import gov.nist.javax.sip.message.ResponseExt; - import java.util.ArrayList; +import java.util.EventObject; import java.util.HashSet; +import java.util.Hashtable; import java.util.Iterator; import java.util.Properties; +import java.util.Timer; +import java.util.TimerTask; import javax.sip.ClientTransaction; import javax.sip.Dialog; @@ -46,6 +48,7 @@ import javax.sip.SipListener; import javax.sip.SipProvider; import javax.sip.SipStack; +import javax.sip.TimeoutEvent; import javax.sip.Transaction; import javax.sip.TransactionTerminatedEvent; import javax.sip.address.Address; @@ -66,14 +69,19 @@ import javax.sip.message.Request; import javax.sip.message.Response; -import junit.framework.TestCase; - import org.apache.log4j.Appender; import org.apache.log4j.ConsoleAppender; +import org.apache.log4j.FileAppender; import org.apache.log4j.Logger; +import org.apache.log4j.PropertyConfigurator; import org.apache.log4j.SimpleLayout; +import org.apache.log4j.helpers.NullEnumeration; import test.tck.msgflow.callflows.NonSipUriRouter; +import test.tck.msgflow.callflows.ProtocolObjects; +import test.tck.msgflow.callflows.ScenarioHarness; + +import junit.framework.TestCase; /** * @author M. Ranganathan @@ -262,8 +270,6 @@ public class Shootme implements SipListener { private int reInviteCount; - private boolean isToTagInTryingReInvitePresent = false; - class ApplicationData { protected int ackCount; } @@ -321,7 +327,6 @@ public void processInvite(RequestEvent requestEvent, ServerTransaction serverTra ServerTransaction st = requestEvent.getServerTransaction(); int finalResponse; logger.info("Got an INVITE " + request + " serverTx = " + st); - Thread.sleep(300); if (st == null) { st = sipProvider.getNewServerTransaction(request); @@ -448,11 +453,6 @@ public void processResponse(ResponseEvent responseReceivedEvent) { if (tid != null) { Dialog dialog = tid.getDialog(); logger.info("Dalog State = " + dialog.getState()); - String toTag = ((ResponseExt)response).getToHeader().getTag(); - if(DialogState.CONFIRMED.equals(dialog.getState()) && toTag != null && response.getStatusCode() == Response.TRYING) { - this.isToTagInTryingReInvitePresent = true; - logger.info("to tag for trying in re INVITE is present " + toTag); - } } } catch (Exception ex) { @@ -486,8 +486,7 @@ public SipProvider createSipProvider() throws Exception { } public void checkState() { - assertTrue("should see a re-INVITE", this.reInviteCount >=2 ); - assertTrue("To tag in trying for re-INVITE shoulnd't be null", isToTagInTryingReInvitePresent); + assertEquals("should see a re-INVITE", 2, this.reInviteCount); } @@ -580,9 +579,6 @@ public void processInvite(Request request, ServerTransaction st) { Dialog dialog = st.getDialog(); logger.info("shootist received RE INVITE. Sending BUSY_HERE"); assertEquals("Dialog state must in confirmed state ",DialogState.CONFIRMED,dialog.getState()); - - Thread.sleep(300); - Response response = protocolObjects.messageFactory.createResponse(Response.BUSY_HERE, request); ((ToHeader) response.getHeader(ToHeader.NAME)).setTag(((ToHeader) request diff --git a/src/test/unit/gov/nist/javax/sip/stack/SIPEventInterceptorTest.java b/src/test/unit/gov/nist/javax/sip/stack/SIPEventInterceptorTest.java deleted file mode 100644 index f02189fee..000000000 --- a/src/test/unit/gov/nist/javax/sip/stack/SIPEventInterceptorTest.java +++ /dev/null @@ -1,660 +0,0 @@ -package test.unit.gov.nist.javax.sip.stack; - -import gov.nist.javax.sip.DialogExt; -import gov.nist.javax.sip.stack.CallAnalysisInterceptor; -import gov.nist.javax.sip.stack.CallAnalyzer; -import gov.nist.javax.sip.stack.CallAnalyzer.MetricAnalysisConfiguration; -import gov.nist.javax.sip.stack.CallAnalyzer.MetricReference; - -import java.util.ArrayList; -import java.util.Properties; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; - -import javax.sip.ClientTransaction; -import javax.sip.Dialog; -import javax.sip.DialogTerminatedEvent; -import javax.sip.IOExceptionEvent; -import javax.sip.ListeningPoint; -import javax.sip.PeerUnavailableException; -import javax.sip.RequestEvent; -import javax.sip.ResponseEvent; -import javax.sip.ServerTransaction; -import javax.sip.SipException; -import javax.sip.SipFactory; -import javax.sip.SipListener; -import javax.sip.SipProvider; -import javax.sip.SipStack; -import javax.sip.Transaction; -import javax.sip.TransactionTerminatedEvent; -import javax.sip.address.Address; -import javax.sip.address.AddressFactory; -import javax.sip.address.SipURI; -import javax.sip.header.CSeqHeader; -import javax.sip.header.CallIdHeader; -import javax.sip.header.ContactHeader; -import javax.sip.header.ContentTypeHeader; -import javax.sip.header.FromHeader; -import javax.sip.header.Header; -import javax.sip.header.HeaderFactory; -import javax.sip.header.MaxForwardsHeader; -import javax.sip.header.ToHeader; -import javax.sip.header.ViaHeader; -import javax.sip.message.MessageFactory; -import javax.sip.message.Request; -import javax.sip.message.Response; - - -import junit.framework.TestCase; - -public class SIPEventInterceptorTest extends TestCase{ - static int count; - static int stuck = 50; - public void testCallAnalyzerConcurrencyAndLeaks() throws Exception { - ExecutorService ex = Executors.newFixedThreadPool(400); - final CallAnalyzer tp = new CallAnalyzer(); - final MetricReference sec = new MetricReference("sec"); - MetricReference se1c = new MetricReference("se111c"); - tp.configure(sec, new MetricAnalysisConfiguration(10,500,500)); - tp.startAnalysis(sec); - tp.startAnalysis(se1c); - Runnable r = new Runnable() { - - public void run() { - tp.enter(sec); - try { - if(++count % 10000==0) { - System.out.println("Avg " + tp.getMetricStats(sec).averageTime); - Thread.sleep(1000); - } - - Thread.sleep(stuck); - - } catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - tp.leave(sec); - } - }; - for(int q=0; q<200000; q++) { - ex.execute(r); - } - - System.out.println("size:" + tp.getNumberOfThreads()); - //Thread.sleep(5000); - ex.shutdown(); - ex.awaitTermination(60, TimeUnit.SECONDS); - ex.shutdownNow(); - ex = null; - System.gc(); - System.gc();Thread.sleep(1000); - System.out.println("size:" + tp.getNumberOfThreads()); - - assertTrue(Math.abs(tp.getMetricStats(sec).averageTime - stuck)<10); // wrong avg time - assertEquals(0, tp.getNumberOfThreads()); // Memory leaking - } - - public class Shootme implements SipListener { - - private AddressFactory addressFactory; - - private MessageFactory messageFactory; - - private HeaderFactory headerFactory; - - private SipStack sipStack; - - private SipProvider sipProvider; - - private static final String myAddress = "127.0.0.1"; - - private static final int myPort = 5070; - - - - private DialogExt dialog; - - public static final boolean callerSendsBye = true; - - - - - public void processRequest(RequestEvent requestEvent) { - Request request = requestEvent.getRequest(); - ServerTransaction serverTransactionId = requestEvent - .getServerTransaction(); - - System.out.println("\n\nRequest " + request.getMethod() - + " received at " + sipStack.getStackName() - + " with server transaction id " + serverTransactionId); - - if (request.getMethod().equals(Request.INVITE)) { - processInvite(requestEvent, serverTransactionId); - } else if(request.getMethod().equals(Request.ACK)) { - processAck(requestEvent, serverTransactionId); - } - - } - - private int num = 0; - - public void processResponse(ResponseEvent responseEvent) { - num++; - if(num<5) { - try { - System.out.println("shootme: got an OK response! "); - System.out.println("Dialog State = " + dialog.getState()); - SipProvider provider = (SipProvider) responseEvent.getSource(); - - Request messageRequest = dialog.createRequest(Request.MESSAGE); - CSeqHeader cseq = (CSeqHeader)messageRequest.getHeader(CSeqHeader.NAME); - - // We will test if the CSEq validation is off by sending CSeq 1 again - cseq.setSeqNumber(1); - ClientTransaction ct = provider - .getNewClientTransaction(messageRequest); - dialog.sendRequest(ct); - - } catch (Exception ex) { - ex.printStackTrace(); - } - } else if (num == 5){ - try { - System.out.println("shootme: got an OK response! "); - System.out.println("Dialog State = " + dialog.getState()); - SipProvider provider = (SipProvider) responseEvent.getSource(); - - Request messageRequest = dialog.createRequest(Request.BYE); - - ClientTransaction ct = provider - .getNewClientTransaction(messageRequest); - dialog.sendRequest(ct); - - } catch (Exception ex) { - ex.printStackTrace(); - } - } - if(responseEvent.getResponse().getStatusCode() == 500) { - fail("We received some error. It should not happen with loose dialog validation. We should not receive error on cseq out of order"); - } - } - - int acks = 0; - /** - * Process the ACK request. Send the bye and complete the call flow. - */ - public void processAck(RequestEvent requestEvent, - ServerTransaction serverTransaction) { - acks++; - // We will wait for 5 acks to test if retransmissions are filtered. With loose dialog - // validation the ACK retransmissions are not filtered by the stack. - if(acks == 5) - { - try { - System.out.println("shootme: got an ACK! "); - System.out.println("Dialog State = " + dialog.getState()); - SipProvider provider = (SipProvider) requestEvent.getSource(); - - Request messageRequest = dialog.createRequest(Request.MESSAGE); - CSeqHeader cseq = (CSeqHeader)messageRequest.getHeader(CSeqHeader.NAME); - - // We will test if the CSEq validation is off by sending CSeq 1 again - - ClientTransaction ct = provider - .getNewClientTransaction(messageRequest); - cseq.setSeqNumber(1); - ct.sendRequest(); - - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - } - - /** - * Process the invite request. - */ - public void processInvite(RequestEvent requestEvent, - ServerTransaction serverTransaction) { - - SipProvider sipProvider = (SipProvider) requestEvent.getSource(); - - Request request = requestEvent.getRequest(); - try { - serverTransaction = sipProvider.getNewServerTransaction(request); - dialog = (DialogExt) sipProvider.getNewDialog(serverTransaction); - dialog.disableSequenceNumberValidation(); - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - try { - - - Response okResponse = messageFactory.createResponse(Response.OK, - request); - FromHeader from = (FromHeader) okResponse.getHeader(FromHeader.NAME); - from.removeParameter("tag"); - Address address = addressFactory.createAddress("Shootme "); - ContactHeader contactHeader = headerFactory - .createContactHeader(address); - ToHeader toHeader = (ToHeader) okResponse.getHeader(ToHeader.NAME); - toHeader.setTag("4321"); // Application is supposed to set. - - FromHeader fromHeader = (FromHeader)okResponse.getHeader(FromHeader.NAME); - fromHeader.setTag("12345"); - okResponse.addHeader(contactHeader); - serverTransaction.sendResponse(okResponse); - - - } catch (Exception ex) { - ex.printStackTrace(); - System.exit(0); - } - } - - - - - - - public void processTimeout(javax.sip.TimeoutEvent timeoutEvent) { - Transaction transaction; - if (timeoutEvent.isServerTransaction()) { - transaction = timeoutEvent.getServerTransaction(); - } else { - transaction = timeoutEvent.getClientTransaction(); - } - System.out.println("state = " + transaction.getState()); - System.out.println("dialog = " + transaction.getDialog()); - System.out.println("dialogState = " - + transaction.getDialog().getState()); - System.out.println("Transaction Time out"); - } - - public void init() { - SipFactory sipFactory = null; - sipStack = null; - sipFactory = SipFactory.getInstance(); - sipFactory.setPathName("gov.nist"); - Properties properties = new Properties(); - properties.setProperty("javax.sip.STACK_NAME", "shootme"); - // You need 16 for logging traces. 32 for debug + traces. - // Your code will limp at 32 but it is best for debugging. - properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "32"); - properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", - "shootmedebug.txt"); - properties.setProperty("gov.nist.javax.sip.SERVER_LOG", - "shootmelog.txt"); - properties.setProperty("gov.nist.javax.sip.AUTOMATIC_DIALOG_ERROR_HANDLING", "false"); - properties.setProperty("javax.sip.AUTOMATIC_DIALOG_SUPPORT", "off"); - properties.setProperty("gov.nist.javax.sip.SIP_EVENT_INTERCEPTOR", CallAnalysisInterceptor.class.getName()); - - try { - // Create SipStack object - sipStack = sipFactory.createSipStack(properties); - System.out.println("sipStack = " + sipStack); - } catch (PeerUnavailableException e) { - // could not find - // gov.nist.jain.protocol.ip.sip.SipStackImpl - // in the classpath - e.printStackTrace(); - System.err.println(e.getMessage()); - if (e.getCause() != null) - e.getCause().printStackTrace(); - System.exit(0); - } - - try { - headerFactory = sipFactory.createHeaderFactory(); - addressFactory = sipFactory.createAddressFactory(); - messageFactory = sipFactory.createMessageFactory(); - ListeningPoint lp = sipStack.createListeningPoint("127.0.0.1", - myPort, "udp"); - - Shootme listener = this; - - sipProvider = sipStack.createSipProvider(lp); - System.out.println("udp provider " + sipProvider); - sipProvider.addSipListener(listener); - - } catch (Exception ex) { - ex.printStackTrace(); - fail("Unexpected exception"); - } - - } - - - - public void processIOException(IOExceptionEvent exceptionEvent) { - fail("IOException"); - - } - - public void processTransactionTerminated( - TransactionTerminatedEvent transactionTerminatedEvent) { - if (transactionTerminatedEvent.isServerTransaction()) - System.out.println("Transaction terminated event recieved" - + transactionTerminatedEvent.getServerTransaction()); - else - System.out.println("Transaction terminated " - + transactionTerminatedEvent.getClientTransaction()); - - } - - public void processDialogTerminated( - DialogTerminatedEvent dialogTerminatedEvent) { - Dialog d = dialogTerminatedEvent.getDialog(); - System.out.println("Local Party = " + d.getLocalParty()); - - } - - public void terminate() { - this.sipStack.stop(); - } - - } - - - - public class Shootist implements SipListener { - - private SipProvider sipProvider; - - private AddressFactory addressFactory; - - private MessageFactory messageFactory; - - private HeaderFactory headerFactory; - - private SipStack sipStack; - - private ContactHeader contactHeader; - - private ListeningPoint udpListeningPoint; - - - private Dialog dialog; - - - private boolean timeoutRecieved; - - boolean messageSeen = false; - - - - - - public void processRequest(RequestEvent requestReceivedEvent) { - Request request = requestReceivedEvent.getRequest(); - if(request.getMethod().equalsIgnoreCase("message")) { - messageSeen = true; - } - try { - Response response = messageFactory.createResponse(200, request); - requestReceivedEvent.getServerTransaction().sendResponse(response); - } catch (Exception e) { - e.printStackTrace();fail("Error"); - } - - - } - - public int lastResponseCode; - - public void processResponse(ResponseEvent responseReceivedEvent) { - lastResponseCode = responseReceivedEvent.getResponse().getStatusCode(); - try { - if(responseReceivedEvent.getResponse().getStatusCode() == 200) { - Request r = responseReceivedEvent.getClientTransaction().createAck(); - sipProvider.sendRequest(r); - } - //responseReceivedEvent.getClientTransaction().sendRequest(r); - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - public void processTimeout(javax.sip.TimeoutEvent timeoutEvent) { - - System.out.println("Got a timeout " + timeoutEvent.getClientTransaction()); - - this.timeoutRecieved = true; - } - - - - public void init() { - SipFactory sipFactory = null; - sipStack = null; - sipFactory = SipFactory.getInstance(); - sipFactory.setPathName("gov.nist"); - Properties properties = new Properties(); - // If you want to try TCP transport change the following to - String transport = "udp"; - String peerHostPort = "127.0.0.1:5070"; - properties.setProperty("javax.sip.OUTBOUND_PROXY", peerHostPort + "/" - + transport); - // If you want to use UDP then uncomment this. - properties.setProperty("javax.sip.STACK_NAME", "shootist"); - - // The following properties are specific to nist-sip - // and are not necessarily part of any other jain-sip - // implementation. - // You can set a max message size for tcp transport to - // guard against denial of service attack. - properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", - "shootistdebug.txt"); - properties.setProperty("gov.nist.javax.sip.SERVER_LOG", - "shootistlog.txt"); - - // Drop the client connection after we are done with the transaction. - properties.setProperty("gov.nist.javax.sip.CACHE_CLIENT_CONNECTIONS", - "false"); - // Set to 0 (or NONE) in your production code for max speed. - // You need 16 (or TRACE) for logging traces. 32 (or DEBUG) for debug + traces. - // Your code will limp at 32 but it is best for debugging. - properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "DEBUG"); - properties.setProperty("javax.sip.AUTOMATIC_DIALOG_SUPPORT", "off"); - properties.setProperty("gov.nist.javax.sip.AUTOMATIC_DIALOG_ERROR_HANDLING","false"); - properties.setProperty("gov.nist.javax.sip.SIP_EVENT_INTERCEPTOR", CallAnalysisInterceptor.class.getName()); - - try { - // Create SipStack object - sipStack = sipFactory.createSipStack(properties); - System.out.println("createSipStack " + sipStack); - } catch (PeerUnavailableException e) { - // could not find - // gov.nist.jain.protocol.ip.sip.SipStackImpl - // in the classpath - e.printStackTrace(); - System.err.println(e.getMessage()); - fail("Problem with setup"); - } - - try { - headerFactory = sipFactory.createHeaderFactory(); - addressFactory = sipFactory.createAddressFactory(); - messageFactory = sipFactory.createMessageFactory(); - udpListeningPoint = sipStack.createListeningPoint("127.0.0.1", 5060, "udp"); - sipProvider = sipStack.createSipProvider(udpListeningPoint); - Shootist listener = this; - sipProvider.addSipListener(listener); - - String fromName = "BigGuy"; - String fromSipAddress = "here.com"; - String fromDisplayName = "The Master Blaster"; - - String toSipAddress = "there.com"; - String toUser = "LittleGuy"; - String toDisplayName = "The Little Blister"; - - // create >From Header - SipURI fromAddress = addressFactory.createSipURI(fromName, - fromSipAddress); - - Address fromNameAddress = addressFactory.createAddress(fromAddress); - fromNameAddress.setDisplayName(fromDisplayName); - FromHeader fromHeader = headerFactory.createFromHeader( - fromNameAddress, "12345"); - - // create To Header - SipURI toAddress = addressFactory - .createSipURI(toUser, toSipAddress); - Address toNameAddress = addressFactory.createAddress(toAddress); - toNameAddress.setDisplayName(toDisplayName); - ToHeader toHeader = headerFactory.createToHeader(toNameAddress, - null); - - // create Request URI - SipURI requestURI = addressFactory.createSipURI(toUser, - peerHostPort); - - // Create ViaHeaders - - ArrayList viaHeaders = new ArrayList(); - String ipAddress = udpListeningPoint.getIPAddress(); - ViaHeader viaHeader = headerFactory.createViaHeader(ipAddress, - sipProvider.getListeningPoint(transport).getPort(), - transport, null); - - // add via headers - viaHeaders.add(viaHeader); - - // Create ContentTypeHeader - ContentTypeHeader contentTypeHeader = headerFactory - .createContentTypeHeader("application", "sdp"); - - // Create a new CallId header - CallIdHeader callIdHeader = sipProvider.getNewCallId(); - - // Create a new Cseq header - CSeqHeader cSeqHeader = headerFactory.createCSeqHeader(1L, - Request.INVITE); - - // Create a new MaxForwardsHeader - MaxForwardsHeader maxForwards = headerFactory - .createMaxForwardsHeader(70); - - // Create the request. - Request request = messageFactory.createRequest(requestURI, - Request.INVITE, callIdHeader, cSeqHeader, fromHeader, - toHeader, viaHeaders, maxForwards); - // Create contact headers - String host = "127.0.0.1"; - - SipURI contactUrl = addressFactory.createSipURI(fromName, host); - contactUrl.setPort(udpListeningPoint.getPort()); - contactUrl.setLrParam(); - - // Create the contact name address. - SipURI contactURI = addressFactory.createSipURI(fromName, host); - contactURI.setPort(sipProvider.getListeningPoint(transport) - .getPort()); - - Address contactAddress = addressFactory.createAddress(contactURI); - - // Add the contact address. - contactAddress.setDisplayName(fromName); - - contactHeader = headerFactory.createContactHeader(contactAddress); - request.addHeader(contactHeader); - - // You can add extension headers of your own making - // to the outgoing SIP request. - // Add the extension header. - Header extensionHeader = headerFactory.createHeader("My-Header", - "my header value"); - request.addHeader(extensionHeader); - - String sdpData = "v=0\r\n" - + "o=4855 13760799956958020 13760799956958020" - + " IN IP4 129.6.55.78\r\n" + "s=mysession session\r\n" - + "p=+46 8 52018010\r\n" + "c=IN IP4 129.6.55.78\r\n" - + "t=0 0\r\n" + "m=audio 6022 RTP/AVP 0 4 18\r\n" - + "a=rtpmap:0 PCMU/8000\r\n" + "a=rtpmap:4 G723/8000\r\n" - + "a=rtpmap:18 G729A/8000\r\n" + "a=ptime:20\r\n"; - byte[] contents = sdpData.getBytes(); - - request.setContent(contents, contentTypeHeader); - // You can add as many extension headers as you - // want. - - extensionHeader = headerFactory.createHeader("My-Other-Header", - "my new header value "); - request.addHeader(extensionHeader); - - Header callInfoHeader = headerFactory.createHeader("Call-Info", - ""); - request.addHeader(callInfoHeader); - - // Create the client transaction. - ClientTransaction inviteTid = sipProvider.getNewClientTransaction(request); - Dialog d = null; - try { - d = sipProvider.getNewDialog(inviteTid); - } catch (SipException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } - - // send the request out. - inviteTid.sendRequest(); - - dialog = inviteTid.getDialog(); - - } catch (Exception ex) { - fail("cannot create or send initial invite"); - } - } - - - - public void processIOException(IOExceptionEvent exceptionEvent) { - System.out.println("IOException happened for " - + exceptionEvent.getHost() + " port = " - + exceptionEvent.getPort()); - - } - - public void processTransactionTerminated( - TransactionTerminatedEvent transactionTerminatedEvent) { - System.out.println("Transaction terminated event recieved"); - } - - public void processDialogTerminated( - DialogTerminatedEvent dialogTerminatedEvent) { - System.out.println("dialogTerminatedEvent"); - - } - public void terminate() { - this.sipStack.stop(); - } - } - - private Shootme shootme; - private Shootist shootist; - - public void testInterceptor() { - this.shootme = new Shootme(); - this.shootist = new Shootist(); - this.shootme.init(); - this.shootist.init(); - try { - Thread.sleep(10000); - } catch (Exception ex) { - - } - assertTrue(shootme.acks>0); - shootist.terminate(); - shootme.terminate(); - } - -} diff --git a/src/test/unit/gov/nist/javax/sip/stack/SIPMessageValveImpl.java b/src/test/unit/gov/nist/javax/sip/stack/SIPMessageValveImpl.java deleted file mode 100644 index 78349c6b9..000000000 --- a/src/test/unit/gov/nist/javax/sip/stack/SIPMessageValveImpl.java +++ /dev/null @@ -1,61 +0,0 @@ -package test.unit.gov.nist.javax.sip.stack; -import gov.nist.javax.sip.SipStackImpl; -import gov.nist.javax.sip.message.SIPMessage; -import gov.nist.javax.sip.message.SIPRequest; -import gov.nist.javax.sip.stack.MessageChannel; -import gov.nist.javax.sip.stack.SIPMessageValve; - -import java.io.IOException; - -import javax.sip.SipStack; -import javax.sip.message.Response; - - public class SIPMessageValveImpl implements SIPMessageValve { - public static int lastResponseCode; - public static boolean inited; - public static boolean destroyed; - - public boolean processRequest(SIPRequest request, MessageChannel messageChannel) { - try { - sendResponse(messageChannel, createErrorResponse(request, 603)); - return false; - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - return false; - } - - /** - * Demonstrating how stateless response is created and sent - * @param request - * @param code - * @return - */ - public SIPMessage createErrorResponse(SIPRequest request, int code) { - return request.createResponse(code); - } - - public void sendResponse(MessageChannel channel, SIPMessage response) throws IOException { - channel.sendMessage(response); - } - - public boolean processResponse(Response response, - MessageChannel messageChannel) { - lastResponseCode = response.getStatusCode(); - return true; - } - - public void destroy() { - destroyed = true; - } - - public void init(SipStack stack) { - SipStackImpl impl = (SipStackImpl) stack; - impl.getConfigurationProperties().getProperty("keee"); - impl.getActiveClientTransactionCount(); - inited = true; - } - - - } \ No newline at end of file diff --git a/src/test/unit/gov/nist/javax/sip/stack/SIPMessageValveTest.java b/src/test/unit/gov/nist/javax/sip/stack/SIPMessageValveTest.java deleted file mode 100644 index 2431009a7..000000000 --- a/src/test/unit/gov/nist/javax/sip/stack/SIPMessageValveTest.java +++ /dev/null @@ -1,623 +0,0 @@ -package test.unit.gov.nist.javax.sip.stack; - -import gov.nist.javax.sip.DialogExt; -import gov.nist.javax.sip.SipProviderExt; -import gov.nist.javax.sip.message.SIPMessage; -import gov.nist.javax.sip.message.SIPRequest; -import gov.nist.javax.sip.stack.MessageChannel; -import gov.nist.javax.sip.stack.SIPMessageValve; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Properties; - -import javax.sip.ClientTransaction; -import javax.sip.Dialog; -import javax.sip.DialogTerminatedEvent; -import javax.sip.IOExceptionEvent; -import javax.sip.ListeningPoint; -import javax.sip.PeerUnavailableException; -import javax.sip.RequestEvent; -import javax.sip.ResponseEvent; -import javax.sip.ServerTransaction; -import javax.sip.SipException; -import javax.sip.SipFactory; -import javax.sip.SipListener; -import javax.sip.SipProvider; -import javax.sip.SipStack; -import javax.sip.Transaction; -import javax.sip.TransactionTerminatedEvent; -import javax.sip.address.Address; -import javax.sip.address.AddressFactory; -import javax.sip.address.SipURI; -import javax.sip.header.CSeqHeader; -import javax.sip.header.CallIdHeader; -import javax.sip.header.ContactHeader; -import javax.sip.header.ContentTypeHeader; -import javax.sip.header.FromHeader; -import javax.sip.header.Header; -import javax.sip.header.HeaderFactory; -import javax.sip.header.MaxForwardsHeader; -import javax.sip.header.ToHeader; -import javax.sip.header.ViaHeader; -import javax.sip.message.MessageFactory; -import javax.sip.message.Request; -import javax.sip.message.Response; - -import junit.framework.TestCase; - -/** - * Test for SIP_MESSAGE_VALVE callback - * - * @author Vladimir Ralev - * - */ -public class SIPMessageValveTest extends TestCase { - - public class Shootme implements SipListener { - - private AddressFactory addressFactory; - - private MessageFactory messageFactory; - - private HeaderFactory headerFactory; - - private SipStack sipStack; - - private SipProvider sipProvider; - - private static final String myAddress = "127.0.0.1"; - - private static final int myPort = 5070; - - - - private DialogExt dialog; - - public static final boolean callerSendsBye = true; - - - - - public void processRequest(RequestEvent requestEvent) { - Request request = requestEvent.getRequest(); - ServerTransaction serverTransactionId = requestEvent - .getServerTransaction(); - - System.out.println("\n\nRequest " + request.getMethod() - + " received at " + sipStack.getStackName() - + " with server transaction id " + serverTransactionId); - - if (request.getMethod().equals(Request.INVITE)) { - processInvite(requestEvent, serverTransactionId); - } else if(request.getMethod().equals(Request.ACK)) { - processAck(requestEvent, serverTransactionId); - } - - } - - private int num = 0; - - public void processResponse(ResponseEvent responseEvent) { - num++; - if(num<5) { - try { - System.out.println("shootme: got an OK response! "); - System.out.println("Dialog State = " + dialog.getState()); - SipProvider provider = (SipProvider) responseEvent.getSource(); - - Request messageRequest = dialog.createRequest(Request.MESSAGE); - CSeqHeader cseq = (CSeqHeader)messageRequest.getHeader(CSeqHeader.NAME); - - // We will test if the CSEq validation is off by sending CSeq 1 again - cseq.setSeqNumber(1); - ClientTransaction ct = provider - .getNewClientTransaction(messageRequest); - dialog.sendRequest(ct); - - } catch (Exception ex) { - ex.printStackTrace(); - } - } else if (num == 5){ - try { - System.out.println("shootme: got an OK response! "); - System.out.println("Dialog State = " + dialog.getState()); - SipProvider provider = (SipProvider) responseEvent.getSource(); - - Request messageRequest = dialog.createRequest(Request.BYE); - - ClientTransaction ct = provider - .getNewClientTransaction(messageRequest); - dialog.sendRequest(ct); - - } catch (Exception ex) { - ex.printStackTrace(); - } - } - if(responseEvent.getResponse().getStatusCode() == 500) { - fail("We received some error. It should not happen with loose dialog validation. We should not receive error on cseq out of order"); - } - } - - int acks = 0; - /** - * Process the ACK request. Send the bye and complete the call flow. - */ - public void processAck(RequestEvent requestEvent, - ServerTransaction serverTransaction) { - acks++; - // We will wait for 5 acks to test if retransmissions are filtered. With loose dialog - // validation the ACK retransmissions are not filtered by the stack. - if(acks == 5) - { - try { - System.out.println("shootme: got an ACK! "); - System.out.println("Dialog State = " + dialog.getState()); - SipProvider provider = (SipProvider) requestEvent.getSource(); - - Request messageRequest = dialog.createRequest(Request.MESSAGE); - CSeqHeader cseq = (CSeqHeader)messageRequest.getHeader(CSeqHeader.NAME); - - // We will test if the CSEq validation is off by sending CSeq 1 again - - ClientTransaction ct = provider - .getNewClientTransaction(messageRequest); - cseq.setSeqNumber(1); - ct.sendRequest(); - - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - } - - /** - * Process the invite request. - */ - public void processInvite(RequestEvent requestEvent, - ServerTransaction serverTransaction) { - - SipProvider sipProvider = (SipProvider) requestEvent.getSource(); - - Request request = requestEvent.getRequest(); - try { - serverTransaction = sipProvider.getNewServerTransaction(request); - dialog = (DialogExt) sipProvider.getNewDialog(serverTransaction); - dialog.disableSequenceNumberValidation(); - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - try { - - - Response okResponse = messageFactory.createResponse(Response.OK, - request); - FromHeader from = (FromHeader) okResponse.getHeader(FromHeader.NAME); - from.removeParameter("tag"); - Address address = addressFactory.createAddress("Shootme "); - ContactHeader contactHeader = headerFactory - .createContactHeader(address); - ToHeader toHeader = (ToHeader) okResponse.getHeader(ToHeader.NAME); - toHeader.setTag("4321"); // Application is supposed to set. - - FromHeader fromHeader = (FromHeader)okResponse.getHeader(FromHeader.NAME); - fromHeader.setTag("12345"); - okResponse.addHeader(contactHeader); - serverTransaction.sendResponse(okResponse); - - - } catch (Exception ex) { - ex.printStackTrace(); - System.exit(0); - } - } - - - - - - - public void processTimeout(javax.sip.TimeoutEvent timeoutEvent) { - Transaction transaction; - if (timeoutEvent.isServerTransaction()) { - transaction = timeoutEvent.getServerTransaction(); - } else { - transaction = timeoutEvent.getClientTransaction(); - } - System.out.println("state = " + transaction.getState()); - System.out.println("dialog = " + transaction.getDialog()); - System.out.println("dialogState = " - + transaction.getDialog().getState()); - System.out.println("Transaction Time out"); - } - - public void init() { - SipFactory sipFactory = null; - sipStack = null; - sipFactory = SipFactory.getInstance(); - sipFactory.setPathName("gov.nist"); - Properties properties = new Properties(); - properties.setProperty("javax.sip.STACK_NAME", "shootme"); - // You need 16 for logging traces. 32 for debug + traces. - // Your code will limp at 32 but it is best for debugging. - properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "32"); - properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", - "shootmedebug.txt"); - properties.setProperty("gov.nist.javax.sip.SERVER_LOG", - "shootmelog.txt"); - properties.setProperty("gov.nist.javax.sip.AUTOMATIC_DIALOG_ERROR_HANDLING", "false"); - properties.setProperty("javax.sip.AUTOMATIC_DIALOG_SUPPORT", "off"); - properties.setProperty("gov.nist.javax.sip.SIP_MESSAGE_VALVE", SIPMessageValveImpl.class.getCanonicalName()); - - try { - // Create SipStack object - sipStack = sipFactory.createSipStack(properties); - System.out.println("sipStack = " + sipStack); - } catch (PeerUnavailableException e) { - // could not find - // gov.nist.jain.protocol.ip.sip.SipStackImpl - // in the classpath - e.printStackTrace(); - System.err.println(e.getMessage()); - if (e.getCause() != null) - e.getCause().printStackTrace(); - System.exit(0); - } - - try { - headerFactory = sipFactory.createHeaderFactory(); - addressFactory = sipFactory.createAddressFactory(); - messageFactory = sipFactory.createMessageFactory(); - ListeningPoint lp = sipStack.createListeningPoint("127.0.0.1", - myPort, "udp"); - - Shootme listener = this; - - sipProvider = sipStack.createSipProvider(lp); - System.out.println("udp provider " + sipProvider); - sipProvider.addSipListener(listener); - - } catch (Exception ex) { - ex.printStackTrace(); - fail("Unexpected exception"); - } - - } - - - - public void processIOException(IOExceptionEvent exceptionEvent) { - fail("IOException"); - - } - - public void processTransactionTerminated( - TransactionTerminatedEvent transactionTerminatedEvent) { - if (transactionTerminatedEvent.isServerTransaction()) - System.out.println("Transaction terminated event recieved" - + transactionTerminatedEvent.getServerTransaction()); - else - System.out.println("Transaction terminated " - + transactionTerminatedEvent.getClientTransaction()); - - } - - public void processDialogTerminated( - DialogTerminatedEvent dialogTerminatedEvent) { - Dialog d = dialogTerminatedEvent.getDialog(); - System.out.println("Local Party = " + d.getLocalParty()); - - } - - public void terminate() { - this.sipStack.stop(); - } - - } - - - - public class Shootist implements SipListener { - - private SipProvider sipProvider; - - private AddressFactory addressFactory; - - private MessageFactory messageFactory; - - private HeaderFactory headerFactory; - - private SipStack sipStack; - - private ContactHeader contactHeader; - - private ListeningPoint udpListeningPoint; - - - private Dialog dialog; - - - private boolean timeoutRecieved; - - boolean messageSeen = false; - - - - - - public void processRequest(RequestEvent requestReceivedEvent) { - Request request = requestReceivedEvent.getRequest(); - if(request.getMethod().equalsIgnoreCase("message")) { - messageSeen = true; - } - try { - Response response = messageFactory.createResponse(200, request); - requestReceivedEvent.getServerTransaction().sendResponse(response); - } catch (Exception e) { - e.printStackTrace();fail("Error"); - } - - - } - - public int lastResponseCode; - - public void processResponse(ResponseEvent responseReceivedEvent) { - lastResponseCode = responseReceivedEvent.getResponse().getStatusCode(); - if ( responseReceivedEvent.getResponse().getStatusCode() != 603) { - - fail("Expected 603 here from the valve. Got " + responseReceivedEvent.getResponse()); - } - - } - - public void processTimeout(javax.sip.TimeoutEvent timeoutEvent) { - - System.out.println("Got a timeout " + timeoutEvent.getClientTransaction()); - - this.timeoutRecieved = true; - } - - - - public void init() { - SipFactory sipFactory = null; - sipStack = null; - sipFactory = SipFactory.getInstance(); - sipFactory.setPathName("gov.nist"); - Properties properties = new Properties(); - // If you want to try TCP transport change the following to - String transport = "udp"; - String peerHostPort = "127.0.0.1:5070"; - properties.setProperty("javax.sip.OUTBOUND_PROXY", peerHostPort + "/" - + transport); - // If you want to use UDP then uncomment this. - properties.setProperty("javax.sip.STACK_NAME", "shootist"); - - // The following properties are specific to nist-sip - // and are not necessarily part of any other jain-sip - // implementation. - // You can set a max message size for tcp transport to - // guard against denial of service attack. - properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", - "shootistdebug.txt"); - properties.setProperty("gov.nist.javax.sip.SERVER_LOG", - "shootistlog.txt"); - - // Drop the client connection after we are done with the transaction. - properties.setProperty("gov.nist.javax.sip.CACHE_CLIENT_CONNECTIONS", - "false"); - // Set to 0 (or NONE) in your production code for max speed. - // You need 16 (or TRACE) for logging traces. 32 (or DEBUG) for debug + traces. - // Your code will limp at 32 but it is best for debugging. - properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "DEBUG"); - properties.setProperty("javax.sip.AUTOMATIC_DIALOG_SUPPORT", "off"); - properties.setProperty("gov.nist.javax.sip.AUTOMATIC_DIALOG_ERROR_HANDLING","false"); - properties.setProperty("gov.nist.javax.sip.SIP_MESSAGE_VALVE", SIPMessageValveImpl.class.getCanonicalName()); - - try { - // Create SipStack object - sipStack = sipFactory.createSipStack(properties); - System.out.println("createSipStack " + sipStack); - } catch (PeerUnavailableException e) { - // could not find - // gov.nist.jain.protocol.ip.sip.SipStackImpl - // in the classpath - e.printStackTrace(); - System.err.println(e.getMessage()); - fail("Problem with setup"); - } - - try { - headerFactory = sipFactory.createHeaderFactory(); - addressFactory = sipFactory.createAddressFactory(); - messageFactory = sipFactory.createMessageFactory(); - udpListeningPoint = sipStack.createListeningPoint("127.0.0.1", 5060, "udp"); - sipProvider = sipStack.createSipProvider(udpListeningPoint); - Shootist listener = this; - sipProvider.addSipListener(listener); - - String fromName = "BigGuy"; - String fromSipAddress = "here.com"; - String fromDisplayName = "The Master Blaster"; - - String toSipAddress = "there.com"; - String toUser = "LittleGuy"; - String toDisplayName = "The Little Blister"; - - // create >From Header - SipURI fromAddress = addressFactory.createSipURI(fromName, - fromSipAddress); - - Address fromNameAddress = addressFactory.createAddress(fromAddress); - fromNameAddress.setDisplayName(fromDisplayName); - FromHeader fromHeader = headerFactory.createFromHeader( - fromNameAddress, "12345"); - - // create To Header - SipURI toAddress = addressFactory - .createSipURI(toUser, toSipAddress); - Address toNameAddress = addressFactory.createAddress(toAddress); - toNameAddress.setDisplayName(toDisplayName); - ToHeader toHeader = headerFactory.createToHeader(toNameAddress, - null); - - // create Request URI - SipURI requestURI = addressFactory.createSipURI(toUser, - peerHostPort); - - // Create ViaHeaders - - ArrayList viaHeaders = new ArrayList(); - String ipAddress = udpListeningPoint.getIPAddress(); - ViaHeader viaHeader = headerFactory.createViaHeader(ipAddress, - sipProvider.getListeningPoint(transport).getPort(), - transport, null); - - // add via headers - viaHeaders.add(viaHeader); - - // Create ContentTypeHeader - ContentTypeHeader contentTypeHeader = headerFactory - .createContentTypeHeader("application", "sdp"); - - // Create a new CallId header - CallIdHeader callIdHeader = sipProvider.getNewCallId(); - - // Create a new Cseq header - CSeqHeader cSeqHeader = headerFactory.createCSeqHeader(1L, - Request.INVITE); - - // Create a new MaxForwardsHeader - MaxForwardsHeader maxForwards = headerFactory - .createMaxForwardsHeader(70); - - // Create the request. - Request request = messageFactory.createRequest(requestURI, - Request.INVITE, callIdHeader, cSeqHeader, fromHeader, - toHeader, viaHeaders, maxForwards); - // Create contact headers - String host = "127.0.0.1"; - - SipURI contactUrl = addressFactory.createSipURI(fromName, host); - contactUrl.setPort(udpListeningPoint.getPort()); - contactUrl.setLrParam(); - - // Create the contact name address. - SipURI contactURI = addressFactory.createSipURI(fromName, host); - contactURI.setPort(sipProvider.getListeningPoint(transport) - .getPort()); - - Address contactAddress = addressFactory.createAddress(contactURI); - - // Add the contact address. - contactAddress.setDisplayName(fromName); - - contactHeader = headerFactory.createContactHeader(contactAddress); - request.addHeader(contactHeader); - - // You can add extension headers of your own making - // to the outgoing SIP request. - // Add the extension header. - Header extensionHeader = headerFactory.createHeader("My-Header", - "my header value"); - request.addHeader(extensionHeader); - - String sdpData = "v=0\r\n" - + "o=4855 13760799956958020 13760799956958020" - + " IN IP4 129.6.55.78\r\n" + "s=mysession session\r\n" - + "p=+46 8 52018010\r\n" + "c=IN IP4 129.6.55.78\r\n" - + "t=0 0\r\n" + "m=audio 6022 RTP/AVP 0 4 18\r\n" - + "a=rtpmap:0 PCMU/8000\r\n" + "a=rtpmap:4 G723/8000\r\n" - + "a=rtpmap:18 G729A/8000\r\n" + "a=ptime:20\r\n"; - byte[] contents = sdpData.getBytes(); - - request.setContent(contents, contentTypeHeader); - // You can add as many extension headers as you - // want. - - extensionHeader = headerFactory.createHeader("My-Other-Header", - "my new header value "); - request.addHeader(extensionHeader); - - Header callInfoHeader = headerFactory.createHeader("Call-Info", - ""); - request.addHeader(callInfoHeader); - - // Create the client transaction. - ClientTransaction inviteTid = sipProvider.getNewClientTransaction(request); - Dialog d = null; - try { - d = sipProvider.getNewDialog(inviteTid); - } catch (SipException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } - - // send the request out. - inviteTid.sendRequest(); - - dialog = inviteTid.getDialog(); - - } catch (Exception ex) { - fail("cannot create or send initial invite"); - } - } - - - - public void processIOException(IOExceptionEvent exceptionEvent) { - System.out.println("IOException happened for " - + exceptionEvent.getHost() + " port = " - + exceptionEvent.getPort()); - - } - - public void processTransactionTerminated( - TransactionTerminatedEvent transactionTerminatedEvent) { - System.out.println("Transaction terminated event recieved"); - } - - public void processDialogTerminated( - DialogTerminatedEvent dialogTerminatedEvent) { - System.out.println("dialogTerminatedEvent"); - - } - public void terminate() { - this.sipStack.stop(); - } - } - - private test.unit.gov.nist.javax.sip.stack.SIPMessageValveTest.Shootme shootme; - private test.unit.gov.nist.javax.sip.stack.SIPMessageValveTest.Shootist shootist; - - public void setUp() { - this.shootme = new Shootme(); - this.shootist = new Shootist(); - - - } - public void tearDown() { - shootist.terminate(); - shootme.terminate(); - } - - public void testSipMessageValve() { - this.shootme.init(); - this.shootist.init(); - try { - Thread.sleep(10000); - } catch (Exception ex) { - - } - if(this.shootist.lastResponseCode != 603) fail("We expected 603"); - if(SIPMessageValveImpl.lastResponseCode != 603) fail("We expected 603"); - assertTrue(SIPMessageValveImpl.inited); - } - - -} diff --git a/src/test/unit/gov/nist/javax/sip/stack/SelfroutingTest.java b/src/test/unit/gov/nist/javax/sip/stack/SelfroutingTest.java deleted file mode 100644 index 7935b520f..000000000 --- a/src/test/unit/gov/nist/javax/sip/stack/SelfroutingTest.java +++ /dev/null @@ -1,479 +0,0 @@ -package test.unit.gov.nist.javax.sip.stack; - -import gov.nist.javax.sip.SipStackImpl; - -import java.util.ArrayList; -import java.util.EventObject; - -import javax.sip.ClientTransaction; -import javax.sip.Dialog; -import javax.sip.DialogTerminatedEvent; -import javax.sip.IOExceptionEvent; -import javax.sip.ListeningPoint; -import javax.sip.RequestEvent; -import javax.sip.ResponseEvent; -import javax.sip.ServerTransaction; -import javax.sip.SipListener; -import javax.sip.SipProvider; -import javax.sip.TimeoutEvent; -import javax.sip.Transaction; -import javax.sip.TransactionTerminatedEvent; -import javax.sip.address.Address; -import javax.sip.address.SipURI; -import javax.sip.header.CSeqHeader; -import javax.sip.header.CallIdHeader; -import javax.sip.header.ContactHeader; -import javax.sip.header.ContentTypeHeader; -import javax.sip.header.FromHeader; -import javax.sip.header.Header; -import javax.sip.header.MaxForwardsHeader; -import javax.sip.header.RouteHeader; -import javax.sip.header.ToHeader; -import javax.sip.header.ViaHeader; -import javax.sip.message.Request; -import javax.sip.message.Response; - -import org.apache.log4j.Logger; - -import test.tck.msgflow.callflows.ProtocolObjects; -import test.tck.msgflow.callflows.ScenarioHarness; - -public class SelfroutingTest extends ScenarioHarness { - - protected Shootist shootist; - - private static Logger logger = Logger.getLogger("test.tck"); - - static { - if (!logger.isAttached(console)) - logger.addAppender(console); - } - - class Shootist implements SipListener { - - private SipProvider provider; - - - private ContactHeader contactHeader; - - private ListeningPoint listeningPoint; - - // To run on two machines change these to suit. - public static final String myAddress = "127.0.0.1"; - - private static final int myPort = 5060; - - protected ClientTransaction inviteTid; - - - - - private ProtocolObjects protocolObjects; - - private Dialog dialog; - - - - - - public Shootist(ProtocolObjects protocolObjects) { - super(); - this.protocolObjects = protocolObjects; - - } - - - - public void processRequest(RequestEvent requestReceivedEvent) { - Request request = requestReceivedEvent.getRequest(); - ServerTransaction serverTransactionId = requestReceivedEvent - .getServerTransaction(); - - logger.info("\n\nRequest " + request.getMethod() + " received at " - + protocolObjects.sipStack.getStackName() - + " with server transaction id " + serverTransactionId); - - if (request.getMethod().equals(Request.BYE)) - processBye(request, serverTransactionId); - else if (request.getMethod().equals(Request.ACK)) - processAck(request, serverTransactionId); - else if (request.getMethod().equals(Request.INVITE)) - processInvite(request, serverTransactionId); - } - - public void processBye(Request request, - ServerTransaction serverTransactionId) { - try { - logger.info("shootist: got a bye ."); - if (serverTransactionId == null) { - logger.info("shootist: null TID."); - return; - } - Response response = protocolObjects.messageFactory.createResponse( - 200, request); - serverTransactionId.sendResponse(response); - } catch (Exception ex) { - logger.error("unexpected exception",ex); - fail("unexpected exception"); - - } - } - - public void processInvite(Request request, - ServerTransaction serverTransactionId) { - try { - Response response = protocolObjects.messageFactory.createResponse( - 200, request); - provider.sendResponse(response); - } catch (Exception ex) { - logger.error("unexpected exception",ex); - fail("unexpected exception"); - - } - } - - public void processAck(Request request, - ServerTransaction serverTransactionId) { - try { - logger.info("shootist: got ACK ."); - if (serverTransactionId == null) { - logger.info("shootist: null TID."); - return; - } - Request bye = dialog.createRequest(Request.BYE); - ClientTransaction ctx = provider.getNewClientTransaction(bye); - ctx.sendRequest(); - } catch (Exception ex) { - logger.error("unexpected exception",ex); - fail("unexpected exception"); - - } - } - - public boolean okToInviteReceived; - - public void processResponse(ResponseEvent responseReceivedEvent) { - logger.info("Got a response"); - - Response response = (Response) responseReceivedEvent.getResponse(); - Transaction tid = responseReceivedEvent.getClientTransaction(); - - logger.info("Response received with client transaction id " + tid - + ":\n" + response.getStatusCode()); - if (tid != null) { - logger.info("Dialog = " + responseReceivedEvent.getDialog()); - logger.info("Dialog State is " - + responseReceivedEvent.getDialog().getState()); - } - SipProvider provider = (SipProvider) responseReceivedEvent.getSource(); - - try { - if (response.getStatusCode() == Response.OK) { - if(((CSeqHeader) response.getHeader(CSeqHeader.NAME)) - .getMethod().equals(Request.INVITE)) { - okToInviteReceived = true; - } - } - } catch (Exception ex) { - logger.error(ex); - ex.printStackTrace(); - fail("unexpected exception"); - } - - } - - public void processTimeout(javax.sip.TimeoutEvent timeoutEvent) { - - logger.info("Transaction Time out"); - logger.info("TimeoutEvent " + timeoutEvent.getTimeout()); - } - - public SipProvider createSipProvider() { - try { - listeningPoint = protocolObjects.sipStack.createListeningPoint( - myAddress, myPort, protocolObjects.transport); - - provider = protocolObjects.sipStack - .createSipProvider(listeningPoint); - return provider; - } catch (Exception ex) { - logger.error(ex); - fail("unable to create provider"); - return null; - } - } - - public void sendInvite() { - - try { - - // Note that a provider has multiple listening points. - // all the listening points must have the same IP address - // and port but differ in their transport parameters. - - String fromName = "BigGuy"; - String fromSipAddress = "here.com"; - String fromDisplayName = "The Master Blaster"; - - String toSipAddress = "there.com"; - String toUser = "LittleGuy"; - String toDisplayName = "The Little Blister"; - - // create >From Header - SipURI fromAddress = protocolObjects.addressFactory.createSipURI( - fromName, fromSipAddress); - - Address fromNameAddress = protocolObjects.addressFactory - .createAddress(fromAddress); - fromNameAddress.setDisplayName(fromDisplayName); - FromHeader fromHeader = protocolObjects.headerFactory - .createFromHeader(fromNameAddress, new Integer((int) (Math - .random() * Integer.MAX_VALUE)).toString()); - - // create To Header - SipURI toAddress = protocolObjects.addressFactory.createSipURI( - toUser, toSipAddress); - Address toNameAddress = protocolObjects.addressFactory - .createAddress(toAddress); - toNameAddress.setDisplayName(toDisplayName); - ToHeader toHeader = protocolObjects.headerFactory.createToHeader( - toNameAddress, null); - - // create Request URI addressed to me - SipURI requestURI = protocolObjects.addressFactory.createSipURI( - toUser, myAddress + ":" + myPort); - - // Create ViaHeaders - - ArrayList viaHeaders = new ArrayList(); - int port = provider.getListeningPoint(protocolObjects.transport) - .getPort(); - - ViaHeader viaHeader = protocolObjects.headerFactory - .createViaHeader(myAddress, port, - protocolObjects.transport, null); - - // add via headers - viaHeaders.add(viaHeader); - - // Create ContentTypeHeader - ContentTypeHeader contentTypeHeader = protocolObjects.headerFactory - .createContentTypeHeader("application", "sdp"); - - // Create a new CallId header - CallIdHeader callIdHeader = provider.getNewCallId(); - // JvB: Make sure that the implementation matches the messagefactory - callIdHeader = protocolObjects.headerFactory.createCallIdHeader( callIdHeader.getCallId() ); - - - // Create a new Cseq header - CSeqHeader cSeqHeader = protocolObjects.headerFactory - .createCSeqHeader(1L, Request.INVITE); - - // Create a new MaxForwardsHeader - MaxForwardsHeader maxForwards = protocolObjects.headerFactory - .createMaxForwardsHeader(70); - - // Create the request. - Request request = protocolObjects.messageFactory.createRequest( - requestURI, Request.INVITE, callIdHeader, cSeqHeader, - fromHeader, toHeader, viaHeaders, maxForwards); - // Create contact headers - - // Create the contact name address. - SipURI contactURI = protocolObjects.addressFactory.createSipURI( - fromName, myAddress); - contactURI.setPort(provider.getListeningPoint( - protocolObjects.transport).getPort()); - - Address contactAddress = protocolObjects.addressFactory - .createAddress(contactURI); - - // Add the contact address. - contactAddress.setDisplayName(fromName); - - contactHeader = protocolObjects.headerFactory - .createContactHeader(contactAddress); - request.addHeader(contactHeader); - - // Add the extension header. - Header extensionHeader = protocolObjects.headerFactory - .createHeader("My-Header", "my header value"); - request.addHeader(extensionHeader); - - String sdpData = "v=0\r\n" - + "o=4855 13760799956958020 13760799956958020" - + " IN IP4 129.6.55.78\r\n" + "s=mysession session\r\n" - + "p=+46 8 52018010\r\n" + "c=IN IP4 129.6.55.78\r\n" - + "t=0 0\r\n" + "m=audio 6022 RTP/AVP 0 4 18\r\n" - + "a=rtpmap:0 PCMU/8000\r\n" + "a=rtpmap:4 G723/8000\r\n" - + "a=rtpmap:18 G729A/8000\r\n" + "a=ptime:20\r\n"; - - request.setContent(sdpData, contentTypeHeader); - - // The following is the preferred method to route requests - // to the peer. Create a route header and set the "lr" - // parameter for the router header. - - Address address = protocolObjects.addressFactory - .createAddress(""); - // SipUri sipUri = (SipUri) address.getURI(); - // sipUri.setPort(PEER_PORT); - - RouteHeader routeHeader = protocolObjects.headerFactory - .createRouteHeader(address); - ((SipURI)address.getURI()).setLrParam(); - request.addHeader(routeHeader); - extensionHeader = protocolObjects.headerFactory.createHeader( - "My-Other-Header", "my new header value "); - request.addHeader(extensionHeader); - - Header callInfoHeader = protocolObjects.headerFactory.createHeader( - "Call-Info", ""); - request.addHeader(callInfoHeader); - - // Create the client transaction. - this.inviteTid = provider.getNewClientTransaction(request); - this.dialog = this.inviteTid.getDialog(); - // Note that the response may have arrived right away so - // we cannot check after the message is sent. - assertTrue(this.dialog.getState() == null); - - // send the request out. - this.inviteTid.sendRequest(); - - - } catch (Exception ex) { - logger.error("Unexpected exception", ex); - fail("unexpected exception"); - } - } - - - - /* - * (non-Javadoc) - * - * @see javax.sip.SipListener#processIOException(javax.sip.IOExceptionEvent) - */ - public void processIOException(IOExceptionEvent exceptionEvent) { - logger.error("IO Exception!"); - fail("Unexpected exception"); - - } - - /* - * (non-Javadoc) - * - * @see javax.sip.SipListener#processTransactionTerminated(javax.sip.TransactionTerminatedEvent) - */ - public void processTransactionTerminated( - TransactionTerminatedEvent transactionTerminatedEvent) { - - logger.info("Transaction Terminated Event!"); - } - - /* - * (non-Javadoc) - * - * @see javax.sip.SipListener#processDialogTerminated(javax.sip.DialogTerminatedEvent) - */ - public void processDialogTerminated( - DialogTerminatedEvent dialogTerminatedEvent) { - logger.info("Dialog Terminated Event!"); - - } - } - - - public SelfroutingTest() - { - super("Selfrouting", true); - } - - public void setUp() { - - - } - - public void testSelfroutingUDP() { - try { - this.transport = "udp"; - - super.setUp(); - shootist = new Shootist(getRiProtocolObjects()); - SipProvider shootistProvider = shootist.createSipProvider(); - shootistProvider.addSipListener(shootist); - SipStackImpl ss = (SipStackImpl) shootistProvider.getSipStack(); - - getRiProtocolObjects().start(); - if (getTiProtocolObjects() != getRiProtocolObjects()) - getTiProtocolObjects().start(); - } catch (Exception ex) { - ex.printStackTrace(); - fail("unexpected exception "); - } - new Thread() { - @Override - public void run() { - shootist.sendInvite(); - super.run(); - } - }.start(); - - try { - Thread.sleep(4000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - assertTrue(this.shootist.okToInviteReceived); - } - - public void testSelfroutingTCP() { - try { - this.transport = "tcp"; - - super.setUp(); - shootist = new Shootist(getRiProtocolObjects()); - SipProvider shootistProvider = shootist.createSipProvider(); - shootistProvider.addSipListener(shootist); - - getRiProtocolObjects().start(); - if (getTiProtocolObjects() != getRiProtocolObjects()) - getTiProtocolObjects().start(); - } catch (Exception ex) { - ex.printStackTrace(); - fail("unexpected exception "); - } - new Thread() { - @Override - public void run() { - shootist.sendInvite(); - super.run(); - } - }.start(); - - try { - Thread.sleep(4000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - assertTrue(this.shootist.okToInviteReceived); - } - - public void tearDown() { - try { - Thread.sleep(1000); - getTiProtocolObjects().destroy(); - if (getTiProtocolObjects() != getRiProtocolObjects()) - getRiProtocolObjects().destroy(); - Thread.sleep(1000); - this.providerTable.clear(); - logTestCompleted(); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - -} diff --git a/src/test/unit/gov/nist/javax/sip/stack/ServerTransactionRetransmissionTimerTest.java b/src/test/unit/gov/nist/javax/sip/stack/ServerTransactionRetransmissionTimerTest.java index b276d2aeb..ed83cdcc2 100644 --- a/src/test/unit/gov/nist/javax/sip/stack/ServerTransactionRetransmissionTimerTest.java +++ b/src/test/unit/gov/nist/javax/sip/stack/ServerTransactionRetransmissionTimerTest.java @@ -1,7 +1,5 @@ package test.unit.gov.nist.javax.sip.stack; -import gov.nist.javax.sip.ResponseEventExt; - import javax.sip.*; import javax.sip.address.*; import javax.sip.header.*; @@ -47,8 +45,6 @@ class Shootist implements SipListener { private long startTime = System.currentTimeMillis(); private boolean byeTaskRunning; - - public boolean sendAck = true; class ByeTask extends TimerTask { Dialog dialog; @@ -138,7 +134,7 @@ public void processResponse(ResponseEvent responseReceivedEvent) { + response.getStatusCode() + " " + cseq); if (tid == null) { - TestCase.assertTrue("retrans flag should be true", ((ResponseEventExt)responseReceivedEvent).isRetransmission()); + // RFC3261: MUST respond to every 2xx if (ackRequest != null && dialog != null) { logger.info("re-sending ACK"); @@ -171,22 +167,19 @@ public void processResponse(ResponseEvent responseReceivedEvent) { if (response.getStatusCode() == Response.OK) { if (cseq.getMethod().equals(Request.INVITE)) { - if (sendAck) { - TestCase.assertFalse("retrans flag should be false", ((ResponseEventExt)responseReceivedEvent).isRetransmission()); - // ***************************************************************** - // BEGIN - // Frank Reif: delayed-ack after 6s - logger.info("Sending ACK after 15s ..."); - new Timer().schedule(new AckTimerTask(dialog,cseq.getSeqNumber()), 15000); - - // JvB: test REFER, reported bug in tag handling - // dialog.sendRequest( - // sipProvider.getNewClientTransaction( - // dialog.createRequest("REFER") )); - - // ***************************************************************** - // END - } + // ***************************************************************** + // BEGIN + // Frank Reif: delayed-ack after 6s + logger.info("Sending ACK after 15s ..."); + new Timer().schedule(new AckTimerTask(dialog,cseq.getSeqNumber()), 15000); + + // JvB: test REFER, reported bug in tag handling + // dialog.sendRequest( + // sipProvider.getNewClientTransaction( + // dialog.createRequest("REFER") )); + + // ***************************************************************** + // END } else if (cseq.getMethod().equals(Request.CANCEL)) { if (dialog.getState() == DialogState.CONFIRMED) { @@ -276,7 +269,7 @@ public void init() { // You need 16 (or TRACE) for logging traces. 32 (or DEBUG) for // debug + traces. // Your code will limp at 32 but it is best for debugging. - properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "32"); + properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "0"); try { // Create SipStack object @@ -684,7 +677,7 @@ public void init() { properties.setProperty("javax.sip.STACK_NAME", "shootme"); // You need 16 for logging traces. 32 for debug + traces. // Your code will limp at 32 but it is best for debugging. - properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "32"); + properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "0"); properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", "shootmedebug.txt"); properties.setProperty("gov.nist.javax.sip.SERVER_LOG", @@ -778,16 +771,5 @@ public void testRetransmit() { } } - - public void testRetransmitNoAckSent() { - this.shootme.init(); - this.shootist.sendAck = false; - this.shootist.init(); - try { - Thread.sleep(60000); - } catch (Exception ex) { - - } - } } diff --git a/src/test/unit/gov/nist/javax/sip/stack/SetRetransmissionTimerTest.java b/src/test/unit/gov/nist/javax/sip/stack/SetRetransmissionTimerTest.java index b893e3562..79714627c 100644 --- a/src/test/unit/gov/nist/javax/sip/stack/SetRetransmissionTimerTest.java +++ b/src/test/unit/gov/nist/javax/sip/stack/SetRetransmissionTimerTest.java @@ -1,23 +1,53 @@ package test.unit.gov.nist.javax.sip.stack; -import gov.nist.javax.sip.ResponseEventExt; import gov.nist.javax.sip.TransactionExt; -import junit.framework.TestCase; -import javax.sip.*; -import javax.sip.address.*; -import javax.sip.header.*; -import javax.sip.message.*; +import java.util.ArrayList; +import java.util.Properties; +import java.util.Timer; +import java.util.TimerTask; + +import javax.sip.ClientTransaction; +import javax.sip.Dialog; +import javax.sip.DialogState; +import javax.sip.DialogTerminatedEvent; +import javax.sip.IOExceptionEvent; +import javax.sip.ListeningPoint; +import javax.sip.PeerUnavailableException; +import javax.sip.RequestEvent; +import javax.sip.ResponseEvent; +import javax.sip.ServerTransaction; +import javax.sip.SipException; +import javax.sip.SipFactory; +import javax.sip.SipListener; +import javax.sip.SipProvider; +import javax.sip.SipStack; +import javax.sip.Transaction; +import javax.sip.TransactionState; +import javax.sip.TransactionTerminatedEvent; +import javax.sip.address.Address; +import javax.sip.address.AddressFactory; +import javax.sip.address.SipURI; +import javax.sip.header.CSeqHeader; +import javax.sip.header.CallIdHeader; +import javax.sip.header.ContactHeader; +import javax.sip.header.ContentTypeHeader; +import javax.sip.header.FromHeader; +import javax.sip.header.Header; +import javax.sip.header.HeaderFactory; +import javax.sip.header.MaxForwardsHeader; +import javax.sip.header.ToHeader; +import javax.sip.header.ViaHeader; +import javax.sip.message.MessageFactory; +import javax.sip.message.Request; +import javax.sip.message.Response; + +import junit.framework.TestCase; import org.apache.log4j.ConsoleAppender; import org.apache.log4j.Logger; import org.apache.log4j.SimpleLayout; -import java.text.ParseException; -import java.util.*; - -import junit.framework.TestCase; - public class SetRetransmissionTimerTest extends TestCase { public static final boolean callerSendsBye = true; @@ -138,7 +168,7 @@ public void processResponse(ResponseEvent responseReceivedEvent) { + response.getStatusCode() + " " + cseq); if (tid == null) { - TestCase.assertTrue("retrans flag should be true", ((ResponseEventExt)responseReceivedEvent).isRetransmission()); + // RFC3261: MUST respond to every 2xx if (ackRequest != null && dialog != null) { logger.info("re-sending ACK"); @@ -163,7 +193,6 @@ public void processResponse(ResponseEvent responseReceivedEvent) { try { if (response.getStatusCode() == Response.OK) { if (cseq.getMethod().equals(Request.INVITE)) { - TestCase.assertFalse("retrans flag should be false", ((ResponseEventExt)responseReceivedEvent).isRetransmission()); logger.info("Sending ACK after 15s ..."); new Timer().schedule(new AckTimerTask(dialog,cseq.getSeqNumber()), 15000); } else if (cseq.getMethod().equals(Request.CANCEL)) { @@ -394,6 +423,7 @@ public void init() { ((TransactionExt)inviteTid).setTimerD(64000); ((TransactionExt)inviteTid).setTimerT2(800); ((TransactionExt)inviteTid).setTimerT4(1000); + // send the request out. inviteTid.sendRequest(); diff --git a/src/test/unit/gov/nist/javax/sip/stack/StackQueueCongestionControlTest.java b/src/test/unit/gov/nist/javax/sip/stack/StackQueueCongestionControlTest.java index a1712c7eb..79ab97ad4 100644 --- a/src/test/unit/gov/nist/javax/sip/stack/StackQueueCongestionControlTest.java +++ b/src/test/unit/gov/nist/javax/sip/stack/StackQueueCongestionControlTest.java @@ -273,7 +273,7 @@ public void init(String transport, int volume) { properties.setProperty("javax.sip.STACK_NAME", "shootme"); // You need 16 for logging traces. 32 for debug + traces. // Your code will limp at 32 but it is best for debugging. - properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "0"); + properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "32"); properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", "shootmedebug.txt"); properties.setProperty("gov.nist.javax.sip.SERVER_LOG", @@ -425,7 +425,6 @@ public void processResponse(ResponseEvent responseReceivedEvent) { } } - public void processTimeout(javax.sip.TimeoutEvent timeoutEvent) { @@ -461,12 +460,12 @@ public void init(String threads, String timeout, int sleep, String transport) { "shootistlog.txt"); // Drop the client connection after we are done with the transaction. - properties.setProperty("gov.nist.javax.sip.CACHE_CLIENT_CONNECTIONS", - "false"); +// properties.setProperty("gov.nist.javax.sip.CACHE_CLIENT_CONNECTIONS", +// "false"); // Set to 0 (or NONE) in your production code for max speed. // You need 16 (or TRACE) for logging traces. 32 (or DEBUG) for debug + traces. // Your code will limp at 32 but it is best for debugging. - properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "0"); + properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "32"); if(threads!=null) { properties.setProperty("gov.nist.javax.sip.THREAD_POOL_SIZE", threads); properties.setProperty("gov.nist.javax.sip.TCP_POST_PARSING_THREAD_POOL_SIZE", threads); @@ -729,7 +728,7 @@ public void testUDPNoThreadpool() { } public void testTCPNoThreadpool() { - this.shootme.init("tcp",100); + this.shootme.init("tcp",1000); this.shootist.init(null, "1", 1, "tcp"); try { Thread.sleep(4000); @@ -756,7 +755,9 @@ public void testTCPCongestionControlOff() { fail("We excpeted more than 0" + this.shootist.receivedResponses); } assertEquals(shootist.receivedResponses, shootme.sentResponses); - + if(this.shootme.acks != 5) { + fail("We expect 5 ACKs because retransmissions are not filtered in loose dialog validation."); + } } public void testTCPHugeLoss() { this.shootme.init("tcp",1000); @@ -772,10 +773,5 @@ public void testTCPHugeLoss() { assertTrue(shootist.receivedResponses0) a+=a; - System.out.println(a); - } } diff --git a/src/test/unit/gov/nist/javax/sip/stack/TcpSingleThreadDeadlockTest.java b/src/test/unit/gov/nist/javax/sip/stack/TcpSingleThreadDeadlockTest.java deleted file mode 100644 index 09a324966..000000000 --- a/src/test/unit/gov/nist/javax/sip/stack/TcpSingleThreadDeadlockTest.java +++ /dev/null @@ -1,672 +0,0 @@ -package test.unit.gov.nist.javax.sip.stack; - -import gov.nist.javax.sip.DialogExt; -import gov.nist.javax.sip.SipProviderExt; - -import java.util.ArrayList; -import java.util.Properties; - -import javax.sip.ClientTransaction; -import javax.sip.Dialog; -import javax.sip.DialogTerminatedEvent; -import javax.sip.IOExceptionEvent; -import javax.sip.ListeningPoint; -import javax.sip.PeerUnavailableException; -import javax.sip.RequestEvent; -import javax.sip.ResponseEvent; -import javax.sip.ServerTransaction; -import javax.sip.SipException; -import javax.sip.SipFactory; -import javax.sip.SipListener; -import javax.sip.SipProvider; -import javax.sip.SipStack; -import javax.sip.Transaction; -import javax.sip.TransactionTerminatedEvent; -import javax.sip.address.Address; -import javax.sip.address.AddressFactory; -import javax.sip.address.SipURI; -import javax.sip.header.CSeqHeader; -import javax.sip.header.CallIdHeader; -import javax.sip.header.ContactHeader; -import javax.sip.header.ContentTypeHeader; -import javax.sip.header.FromHeader; -import javax.sip.header.Header; -import javax.sip.header.HeaderFactory; -import javax.sip.header.MaxForwardsHeader; -import javax.sip.header.ToHeader; -import javax.sip.header.ViaHeader; -import javax.sip.message.MessageFactory; -import javax.sip.message.Request; -import javax.sip.message.Response; - -import junit.framework.TestCase; - -/** - * Testing for deadlock under massive load on the same call. - * This testcase reproduces deadlock that occurs most frequently with TCP thread pool size set to 1 - * from this issue https://jain-sip.dev.java.net/issues/show_bug.cgi?id=301 - * - * Other related issue is here http://code.google.com/p/mobicents/issues/detail?id=1810 - * - * The test sends couple of thousands 180 Ringing responses in order to stall the UAC thread. - * - * The issue is more easily reproducible without debug logs - 300 vs 1000 messages on average - * - * @author vralev - * - */ -public class TcpSingleThreadDeadlockTest extends TestCase { - - public class Shootme implements SipListener { - - private AddressFactory addressFactory; - - private MessageFactory messageFactory; - - private HeaderFactory headerFactory; - - private SipStack sipStack; - - private SipProvider sipProvider; - - private static final String myAddress = "127.0.0.1"; - - private static final int myPort = 5070; - - - - private DialogExt dialog; - - public static final boolean callerSendsBye = true; - - - - - public void processRequest(RequestEvent requestEvent) { - Request request = requestEvent.getRequest(); - ServerTransaction serverTransactionId = requestEvent - .getServerTransaction(); - - System.out.println("\n\nRequest " + request.getMethod() - + " received at " + sipStack.getStackName() - + " with server transaction id " + serverTransactionId); - - if (request.getMethod().equals(Request.INVITE)) { - processInvite(requestEvent, serverTransactionId); - } else if(request.getMethod().equals(Request.ACK)) { - processAck(requestEvent, serverTransactionId); - } - - } - - private int num = 0; - - public void processResponse(ResponseEvent responseEvent) { - num++; - if(num<5) { - try { - System.out.println("shootme: got an OK response! "); - System.out.println("Dialog State = " + dialog.getState()); - SipProvider provider = (SipProvider) responseEvent.getSource(); - - Request messageRequest = dialog.createRequest(Request.MESSAGE); - CSeqHeader cseq = (CSeqHeader)messageRequest.getHeader(CSeqHeader.NAME); - - // We will test if the CSEq validation is off by sending CSeq 1 again - cseq.setSeqNumber(1); - ClientTransaction ct = provider - .getNewClientTransaction(messageRequest); - dialog.sendRequest(ct); - - } catch (Exception ex) { - ex.printStackTrace(); - } - } else if (num == 5){ - try { - System.out.println("shootme: got an OK response! "); - System.out.println("Dialog State = " + dialog.getState()); - SipProvider provider = (SipProvider) responseEvent.getSource(); - - Request messageRequest = dialog.createRequest(Request.BYE); - - ClientTransaction ct = provider - .getNewClientTransaction(messageRequest); - dialog.sendRequest(ct); - - } catch (Exception ex) { - ex.printStackTrace(); - } - } - if(responseEvent.getResponse().getStatusCode() == 500) { - fail("We received some error. It should not happen with loose dialog validation. We should not receive error on cseq out of order"); - } - } - - int acks = 0; - /** - * Process the ACK request. Send the bye and complete the call flow. - */ - public void processAck(RequestEvent requestEvent, - ServerTransaction serverTransaction) { - acks++; - // We will wait for 5 acks to test if retransmissions are filtered. With loose dialog - // validation the ACK retransmissions are not filtered by the stack. - if(acks == 5) - { - try { - System.out.println("shootme: got an ACK! "); - System.out.println("Dialog State = " + dialog.getState()); - SipProvider provider = (SipProvider) requestEvent.getSource(); - - Request messageRequest = dialog.createRequest(Request.MESSAGE); - CSeqHeader cseq = (CSeqHeader)messageRequest.getHeader(CSeqHeader.NAME); - - // We will test if the CSEq validation is off by sending CSeq 1 again - - ClientTransaction ct = provider - .getNewClientTransaction(messageRequest); - cseq.setSeqNumber(1); - ct.sendRequest(); - - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - } - - /** - * Process the invite request. - */ - public void processInvite(RequestEvent requestEvent, - ServerTransaction serverTransaction) { - - SipProvider sipProvider = (SipProvider) requestEvent.getSource(); - - Request request = requestEvent.getRequest(); - try { - serverTransaction = sipProvider.getNewServerTransaction(request); - dialog = (DialogExt) sipProvider.getNewDialog(serverTransaction); - dialog.disableSequenceNumberValidation(); - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - for(int q = 0; q<6000; q++) { - try { - Response okResponse = messageFactory.createResponse(180, - request); - FromHeader from = (FromHeader) okResponse.getHeader(FromHeader.NAME); - from.removeParameter("tag"); - Address address = addressFactory.createAddress("Shootme "); - ContactHeader contactHeader = headerFactory - .createContactHeader(address); - ToHeader toHeader = (ToHeader) okResponse.getHeader(ToHeader.NAME); - toHeader.setTag("4321"); // Application is supposed to set. - - FromHeader fromHeader = (FromHeader)okResponse.getHeader(FromHeader.NAME); - fromHeader.setTag("12345"); - okResponse.addHeader(contactHeader); - serverTransaction.sendResponse(okResponse); - - - } catch (Exception ex) { - ex.printStackTrace(); - //System.exit(0); - } - if(q%100==0) System.out.println("Send " + q); - } - try { - Response okResponse = messageFactory.createResponse(200, - request); - FromHeader from = (FromHeader) okResponse.getHeader(FromHeader.NAME); - from.removeParameter("tag"); - Address address = addressFactory.createAddress("Shootme "); - ContactHeader contactHeader = headerFactory - .createContactHeader(address); - ToHeader toHeader = (ToHeader) okResponse.getHeader(ToHeader.NAME); - toHeader.setTag("4321"); // Application is supposed to set. - - FromHeader fromHeader = (FromHeader)okResponse.getHeader(FromHeader.NAME); - fromHeader.setTag("12345"); - okResponse.addHeader(contactHeader); - serverTransaction.sendResponse(okResponse); - - - } catch (Exception ex) { - ex.printStackTrace(); - //System.exit(0); - } - } - - - - - - - public void processTimeout(javax.sip.TimeoutEvent timeoutEvent) { - Transaction transaction; - if (timeoutEvent.isServerTransaction()) { - transaction = timeoutEvent.getServerTransaction(); - } else { - transaction = timeoutEvent.getClientTransaction(); - } - System.out.println("state = " + transaction.getState()); - System.out.println("dialog = " + transaction.getDialog()); - System.out.println("dialogState = " - + transaction.getDialog().getState()); - System.out.println("Transaction Time out"); - } - - public void init() { - SipFactory sipFactory = null; - sipStack = null; - sipFactory = SipFactory.getInstance(); - sipFactory.setPathName("gov.nist"); - Properties properties = new Properties(); - properties.setProperty("javax.sip.STACK_NAME", "shootme"); - // You need 16 for logging traces. 32 for debug + traces. - // Your code will limp at 32 but it is best for debugging. - properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "0"); - properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", - "shootmedebug.txt"); - properties.setProperty("gov.nist.javax.sip.SERVER_LOG", - "shootmelog.txt"); - properties.setProperty("gov.nist.javax.sip.AUTOMATIC_DIALOG_ERROR_HANDLING", "false"); - properties.setProperty("javax.sip.AUTOMATIC_DIALOG_SUPPORT", "off"); - - try { - // Create SipStack object - sipStack = sipFactory.createSipStack(properties); - System.out.println("sipStack = " + sipStack); - } catch (PeerUnavailableException e) { - // could not find - // gov.nist.jain.protocol.ip.sip.SipStackImpl - // in the classpath - e.printStackTrace(); - System.err.println(e.getMessage()); - if (e.getCause() != null) - e.getCause().printStackTrace(); - //System.exit(0); - } - - try { - headerFactory = sipFactory.createHeaderFactory(); - addressFactory = sipFactory.createAddressFactory(); - messageFactory = sipFactory.createMessageFactory(); - ListeningPoint lp = sipStack.createListeningPoint("127.0.0.1", - myPort, "tcp"); - - Shootme listener = this; - - sipProvider = sipStack.createSipProvider(lp); - System.out.println("udp provider " + sipProvider); - sipProvider.addSipListener(listener); - - } catch (Exception ex) { - ex.printStackTrace(); - fail("Unexpected exception"); - } - - } - - - - public void processIOException(IOExceptionEvent exceptionEvent) { - fail("IOException"); - - } - - public void processTransactionTerminated( - TransactionTerminatedEvent transactionTerminatedEvent) { - if (transactionTerminatedEvent.isServerTransaction()) - System.out.println("Transaction terminated event recieved" - + transactionTerminatedEvent.getServerTransaction()); - else - System.out.println("Transaction terminated " - + transactionTerminatedEvent.getClientTransaction()); - - } - - public void processDialogTerminated( - DialogTerminatedEvent dialogTerminatedEvent) { - Dialog d = dialogTerminatedEvent.getDialog(); - System.out.println("Local Party = " + d.getLocalParty()); - - } - - public void terminate() { - this.sipStack.stop(); - } - - } - - public class Shootist implements SipListener { - - private SipProvider sipProvider; - - private AddressFactory addressFactory; - - private MessageFactory messageFactory; - - private HeaderFactory headerFactory; - - private SipStack sipStack; - - private ContactHeader contactHeader; - - private ListeningPoint udpListeningPoint; - - - private Dialog dialog; - - - private boolean timeoutRecieved; - - boolean messageSeen = false; - - - - - - public void processRequest(RequestEvent requestReceivedEvent) { - Request request = requestReceivedEvent.getRequest(); - if(request.getMethod().equalsIgnoreCase("message")) { - messageSeen = true; - } - try { - Response response = messageFactory.createResponse(200, request); - requestReceivedEvent.getServerTransaction().sendResponse(response); - } catch (Exception e) { - e.printStackTrace();fail("Error"); - } - - - } - - - -int q=0; -boolean inUse = false; - public void processResponse(ResponseEvent responseReceivedEvent) { - try { - if(inUse!=false) { - fail("Concurrent responses should not happen"); - throw new RuntimeException(); - } - inUse = true; - if(q%100==0) System.out.println("Receive " + q); - q++; - if ( responseReceivedEvent.getResponse().getStatusCode() == Response.OK) { - - Dialog d = responseReceivedEvent.getDialog(); - try { - Request ack = d.createAck(1); - sipProvider.sendRequest(ack); - sipProvider.sendRequest(ack); - sipProvider.sendRequest(ack); - sipProvider.sendRequest(ack); - sipProvider.sendRequest(ack); - } catch (Exception e) { - e.printStackTrace(); - fail("Error sending ACK"); - } - } - }finally { - inUse = false; - } - - } - - public void processTimeout(javax.sip.TimeoutEvent timeoutEvent) { - - System.out.println("Got a timeout " + timeoutEvent.getClientTransaction()); - - this.timeoutRecieved = true; - } - - - - public void init() { - SipFactory sipFactory = null; - sipStack = null; - sipFactory = SipFactory.getInstance(); - sipFactory.setPathName("gov.nist"); - Properties properties = new Properties(); - // If you want to try TCP transport change the following to - String transport = "tcp"; - String peerHostPort = "127.0.0.1:5070"; - //properties.setProperty("javax.sip.OUTBOUND_PROXY", peerHostPort + "/" - // + transport); - // If you want to use UDP then uncomment this. - properties.setProperty("javax.sip.STACK_NAME", "shootist"); - - // The following properties are specific to nist-sip - // and are not necessarily part of any other jain-sip - // implementation. - // You can set a max message size for tcp transport to - // guard against denial of service attack. - properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", - "shootistdebug.txt"); - properties.setProperty("gov.nist.javax.sip.SERVER_LOG", - "shootistlog.txt"); - - // Drop the client connection after we are done with the transaction. - properties.setProperty("gov.nist.javax.sip.CACHE_CLIENT_CONNECTIONS", - "false"); - // Set to 0 (or NONE) in your production code for max speed. - // You need 16 (or TRACE) for logging traces. 32 (or DEBUG) for debug + traces. - // Your code will limp at 32 but it is best for debugging. - properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "0"); - properties.setProperty("gov.nist.javax.sip.TCP_POST_PARSING_THREAD_POOL_SIZE", "1"); - properties.setProperty("javax.sip.AUTOMATIC_DIALOG_SUPPORT", "off"); - properties.setProperty("gov.nist.javax.sip.AUTOMATIC_DIALOG_ERROR_HANDLING","false"); - - try { - // Create SipStack object - sipStack = sipFactory.createSipStack(properties); - System.out.println("createSipStack " + sipStack); - } catch (PeerUnavailableException e) { - // could not find - // gov.nist.jain.protocol.ip.sip.SipStackImpl - // in the classpath - e.printStackTrace(); - System.err.println(e.getMessage()); - fail("Problem with setup"); - } - - try { - headerFactory = sipFactory.createHeaderFactory(); - addressFactory = sipFactory.createAddressFactory(); - messageFactory = sipFactory.createMessageFactory(); - udpListeningPoint = sipStack.createListeningPoint("127.0.0.1", 5060, "tcp"); - sipProvider = sipStack.createSipProvider(udpListeningPoint); - Shootist listener = this; - sipProvider.addSipListener(listener); - - String fromName = "BigGuy"; - String fromSipAddress = "here.com"; - String fromDisplayName = "The Master Blaster"; - - String toSipAddress = "there.com"; - String toUser = "LittleGuy"; - String toDisplayName = "The Little Blister"; - - // create >From Header - SipURI fromAddress = addressFactory.createSipURI(fromName, - fromSipAddress); - - Address fromNameAddress = addressFactory.createAddress(fromAddress); - fromNameAddress.setDisplayName(fromDisplayName); - FromHeader fromHeader = headerFactory.createFromHeader( - fromNameAddress, "12345"); - - // create To Header - SipURI toAddress = addressFactory - .createSipURI(toUser, toSipAddress); - Address toNameAddress = addressFactory.createAddress(toAddress); - toNameAddress.setDisplayName(toDisplayName); - ToHeader toHeader = headerFactory.createToHeader(toNameAddress, - null); - - // create Request URI - SipURI requestURI = addressFactory.createSipURI(toUser, - peerHostPort); - - // Create ViaHeaders - - ArrayList viaHeaders = new ArrayList(); - String ipAddress = udpListeningPoint.getIPAddress(); - ViaHeader viaHeader = headerFactory.createViaHeader(ipAddress, - sipProvider.getListeningPoint(transport).getPort(), - transport, null); - - // add via headers - viaHeaders.add(viaHeader); - - // Create ContentTypeHeader - ContentTypeHeader contentTypeHeader = headerFactory - .createContentTypeHeader("application", "sdp"); - - // Create a new CallId header - CallIdHeader callIdHeader = sipProvider.getNewCallId(); - - // Create a new Cseq header - CSeqHeader cSeqHeader = headerFactory.createCSeqHeader(1L, - Request.INVITE); - - // Create a new MaxForwardsHeader - MaxForwardsHeader maxForwards = headerFactory - .createMaxForwardsHeader(70); - - // Create the request. - Request request = messageFactory.createRequest(requestURI, - Request.INVITE, callIdHeader, cSeqHeader, fromHeader, - toHeader, viaHeaders, maxForwards); - // Create contact headers - String host = "127.0.0.1"; - - SipURI contactUrl = addressFactory.createSipURI(fromName, host); - contactUrl.setPort(udpListeningPoint.getPort()); - contactUrl.setLrParam(); - - // Create the contact name address. - SipURI contactURI = addressFactory.createSipURI(fromName, host); - contactURI.setPort(sipProvider.getListeningPoint(transport) - .getPort()); - - Address contactAddress = addressFactory.createAddress(contactURI); - - // Add the contact address. - contactAddress.setDisplayName(fromName); - - contactHeader = headerFactory.createContactHeader(contactAddress); - request.addHeader(contactHeader); - - // You can add extension headers of your own making - // to the outgoing SIP request. - // Add the extension header. - Header extensionHeader = headerFactory.createHeader("My-Header", - "my header value"); - request.addHeader(extensionHeader); - - String sdpData = "v=0\r\n" - + "o=4855 13760799956958020 13760799956958020" - + " IN IP4 129.6.55.78\r\n" + "s=mysession session\r\n" - + "p=+46 8 52018010\r\n" + "c=IN IP4 129.6.55.78\r\n" - + "t=0 0\r\n" + "m=audio 6022 RTP/AVP 0 4 18\r\n" - + "a=rtpmap:0 PCMU/8000\r\n" + "a=rtpmap:4 G723/8000\r\n" - + "a=rtpmap:18 G729A/8000\r\n" + "a=ptime:20\r\n"; - byte[] contents = sdpData.getBytes(); - - request.setContent(contents, contentTypeHeader); - // You can add as many extension headers as you - // want. - - extensionHeader = headerFactory.createHeader("My-Other-Header", - "my new header value "); - request.addHeader(extensionHeader); - - Header callInfoHeader = headerFactory.createHeader("Call-Info", - ""); - request.addHeader(callInfoHeader); - - // Create the client transaction. - ClientTransaction inviteTid = sipProvider.getNewClientTransaction(request); - Dialog d = null; - try { - d = sipProvider.getNewDialog(inviteTid); - } catch (SipException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } - - // send the request out. - inviteTid.sendRequest(); - - dialog = inviteTid.getDialog(); - - } catch (Exception ex) { - ex.printStackTrace(); - fail("cannot create or send initial invite"); - } - } - - - - public void processIOException(IOExceptionEvent exceptionEvent) { - System.out.println("IOException happened for " - + exceptionEvent.getHost() + " port = " - + exceptionEvent.getPort()); - - } - - public void processTransactionTerminated( - TransactionTerminatedEvent transactionTerminatedEvent) { - System.out.println("Transaction terminated event recieved"); - } - - public void processDialogTerminated( - DialogTerminatedEvent dialogTerminatedEvent) { - System.out.println("dialogTerminatedEvent"); - - } - public void terminate() { - this.sipStack.stop(); - } - } - - private test.unit.gov.nist.javax.sip.stack.TcpSingleThreadDeadlockTest.Shootme shootme; - private test.unit.gov.nist.javax.sip.stack.TcpSingleThreadDeadlockTest.Shootist shootist; - - public void setUp() { - this.shootme = new Shootme(); - this.shootist = new Shootist(); - - - } - public void tearDown() { - shootist.terminate(); - shootme.terminate(); - } - - public void testStressMessageSerialization() { - this.shootme.init(); - this.shootist.init(); - try { - Thread.sleep(12000); - } catch (Exception ex) { - - } - if(!this.shootist.messageSeen) { - fail("Something went wrong. We expected the MESSAGE requests. Why are they not sent?"); - } - if(this.shootme.acks != 5) { - fail("We expect 5 ACKs because retransmissions are not filtered in loose dialog validation."); - } - } - - -} diff --git a/src/test/unit/gov/nist/javax/sip/stack/ViaRPortTest.java b/src/test/unit/gov/nist/javax/sip/stack/ViaRPortTest.java deleted file mode 100644 index 75382825b..000000000 --- a/src/test/unit/gov/nist/javax/sip/stack/ViaRPortTest.java +++ /dev/null @@ -1,215 +0,0 @@ -package test.unit.gov.nist.javax.sip.stack; - - - -import gov.nist.javax.sip.ListeningPointImpl; - -import java.util.Arrays; -import java.util.List; -import java.util.ListIterator; -import java.util.Properties; - -import javax.sip.ClientTransaction; -import javax.sip.DialogTerminatedEvent; -import javax.sip.IOExceptionEvent; -import javax.sip.ListeningPoint; -import javax.sip.RequestEvent; -import javax.sip.ResponseEvent; -import javax.sip.SipFactory; -import javax.sip.SipListener; -import javax.sip.SipProvider; -import javax.sip.SipStack; -import javax.sip.TimeoutEvent; -import javax.sip.TransactionTerminatedEvent; -import javax.sip.address.Address; -import javax.sip.address.AddressFactory; -import javax.sip.address.URI; -import javax.sip.header.CSeqHeader; -import javax.sip.header.CallIdHeader; -import javax.sip.header.ContactHeader; -import javax.sip.header.FromHeader; -import javax.sip.header.HeaderFactory; -import javax.sip.header.MaxForwardsHeader; -import javax.sip.header.ToHeader; -import javax.sip.header.ViaHeader; -import javax.sip.message.MessageFactory; -import javax.sip.message.Request; - -import test.tck.msgflow.callflows.ScenarioHarness; - -import junit.framework.Assert; -/** - * Test Issue 309 Via.setRPort() creates malformed rport parameter - * @author jean.deruelle@gmail.com - * - */ -public class ViaRPortTest extends ScenarioHarness { - - - public ViaRPortTest() { - super("ViaRPortTest",true); - } - - - public final int SERVER_PORT = 5600; - - public final int CLIENT_PORT = 6500; - - protected String testProtocol = "udp"; - - public HeaderFactory headerFactory; - - public MessageFactory messageFactory; - - public AddressFactory addressFactory; - - public String host; - - public void setUp() throws Exception { - - } - - public void testRPort() throws Exception { - Server server = new Server(); - Client client = new Client(); - - client.sendInviteWithRPort(); - Thread.sleep(1000); - - Request serverLastRequestReceived = server.getLastRequestReceived(); - assertNotNull(serverLastRequestReceived); - - ListIterator iterator = serverLastRequestReceived.getHeaders(ViaHeader.NAME); - assertTrue(iterator.hasNext()); - int rport = iterator.next().getRPort(); - - assertEquals(6500, rport); - } - - - public class Server extends SipAdapter { - protected SipStack sipStack; - - protected SipFactory sipFactory = null; - - protected SipProvider provider = null; - - private Request lastRequestReceived; - - public Server() { - try { - final Properties defaultProperties = new Properties(); - host = "127.0.0.1"; - - defaultProperties.setProperty("javax.sip.STACK_NAME", "server"); - defaultProperties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "DEBUG"); - defaultProperties.setProperty("gov.nist.javax.sip.DEBUG_LOG", "server_debug_ViaRPortTest.txt"); - defaultProperties.setProperty("gov.nist.javax.sip.SERVER_LOG", "server_log_ViaRPortTest.txt"); - defaultProperties.setProperty("gov.nist.javax.sip.READ_TIMEOUT", "1000"); - defaultProperties.setProperty("gov.nist.javax.sip.CACHE_SERVER_CONNECTIONS", - "false"); - this.sipFactory = SipFactory.getInstance(); - this.sipFactory.setPathName("gov.nist"); - this.sipStack = this.sipFactory.createSipStack(defaultProperties); - this.sipStack.start(); - ListeningPoint lp = this.sipStack.createListeningPoint(host, SERVER_PORT, testProtocol); - this.provider = this.sipStack.createSipProvider(lp);; - this.provider.addSipListener(this); - } catch (Exception e) { - e.printStackTrace(); - Assert.fail("unexpected exception "); - } - - } - - public void stop() { - this.sipStack.stop(); - } - - public void processRequest(RequestEvent requestEvent) { - lastRequestReceived = requestEvent.getRequest(); - } - - public Request getLastRequestReceived() { - return lastRequestReceived; - } - } - - public class Client extends SipAdapter { - - private SipFactory sipFactory; - private SipStack sipStack; - private SipProvider provider; - private boolean o_sentInvite, o_received180, o_sentCancel, o_receiver200Cancel, - o_inviteTxTerm, o_dialogTerinated; - - public Client() { - try { - final Properties defaultProperties = new Properties(); - String host = "127.0.0.1"; - defaultProperties.setProperty("javax.sip.STACK_NAME", "client"); - defaultProperties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "DEBUG"); - defaultProperties.setProperty("gov.nist.javax.sip.DEBUG_LOG", "client_debug.txt"); - defaultProperties.setProperty("gov.nist.javax.sip.SERVER_LOG", "client_log.txt"); - defaultProperties.setProperty("gov.nist.javax.sip.READ_TIMEOUT", "1000"); - defaultProperties.setProperty("gov.nist.javax.sip.CACHE_SERVER_CONNECTIONS","false"); - this.sipFactory = SipFactory.getInstance(); - this.sipFactory.setPathName("gov.nist"); - this.sipStack = this.sipFactory.createSipStack(defaultProperties); - this.sipStack.start(); - ListeningPoint lp = this.sipStack.createListeningPoint(host, CLIENT_PORT, testProtocol); - this.provider = this.sipStack.createSipProvider(lp); - headerFactory = this.sipFactory.createHeaderFactory(); - messageFactory = this.sipFactory.createMessageFactory(); - addressFactory = this.sipFactory.createAddressFactory(); - this.provider.addSipListener(this); - } catch (Exception e) { - e.printStackTrace(); - Assert.fail("unexpected exception "); - } - } - - public void sendInviteWithRPort() throws Exception { - Address fromAddress = addressFactory.createAddress("here@somewhere:5070"); - ContactHeader contactHeader1 = headerFactory.createContactHeader(addressFactory.createAddress("sip:here@somewhere:5070")); - ContactHeader contactHeader2 = headerFactory.createContactHeader(addressFactory.createAddress("sip:here@somewhereelse:5080")); - - - CallIdHeader callId = provider.getNewCallId(); - CSeqHeader cSeq = headerFactory.createCSeqHeader(1l, Request.INVITE); - FromHeader from = headerFactory.createFromHeader(fromAddress, "1234"); - ToHeader to = headerFactory.createToHeader(addressFactory.createAddress("server@"+host+":"+SERVER_PORT), null); - ViaHeader via = ((ListeningPointImpl)provider.getListeningPoint(testProtocol)).getViaHeader(); - via.setRPort(); - List vias = Arrays.asList(via); - MaxForwardsHeader maxForwards = headerFactory.createMaxForwardsHeader(10); - - URI requestURI = addressFactory.createURI("sip:test@"+host+":"+SERVER_PORT); - Request request = messageFactory.createRequest(requestURI, Request.INVITE, callId, cSeq, from, to, vias, maxForwards); - System.out.println(request); - assertTrue(request.toString().indexOf("rport=") == -1); - - request.setRequestURI(requestURI); - request.addHeader(contactHeader1); - request.addHeader(contactHeader2); - ClientTransaction ctx = this.provider.getNewClientTransaction(request); - ctx.sendRequest(); - } - } - - - private static class SipAdapter implements SipListener { - - public void processDialogTerminated(DialogTerminatedEvent arg0) {} - - public void processIOException(IOExceptionEvent arg0) {} - - public void processRequest(RequestEvent arg0) {} - - public void processResponse(ResponseEvent arg0) {} - - public void processTimeout(TimeoutEvent arg0) {} - - public void processTransactionTerminated(TransactionTerminatedEvent arg0) {} - } -} diff --git a/src/test/unit/gov/nist/javax/sip/stack/challenge/Shootme.java b/src/test/unit/gov/nist/javax/sip/stack/challenge/Shootme.java index 8c0c1a083..dadf4cc42 100644 --- a/src/test/unit/gov/nist/javax/sip/stack/challenge/Shootme.java +++ b/src/test/unit/gov/nist/javax/sip/stack/challenge/Shootme.java @@ -297,7 +297,7 @@ public SipProvider createSipProvider() throws Exception { public static void main(String args[]) throws Exception { logger.addAppender(new ConsoleAppender(new SimpleLayout())); ProtocolObjects protocolObjects = new ProtocolObjects("shootme", - "gov.nist", "udp", true,false, false); + "gov.nist", "udp", true,false); Shootme shootme = new Shootme(protocolObjects); shootme.createSipProvider().addSipListener(shootme); diff --git a/src/test/unit/gov/nist/javax/sip/stack/ctx491/ReInviteTest.java b/src/test/unit/gov/nist/javax/sip/stack/ctx491/ReInviteTest.java index cd8a2334e..a94002c8c 100644 --- a/src/test/unit/gov/nist/javax/sip/stack/ctx491/ReInviteTest.java +++ b/src/test/unit/gov/nist/javax/sip/stack/ctx491/ReInviteTest.java @@ -135,9 +135,7 @@ public void processRequest(RequestEvent requestEvent) { } public void processResponse(ResponseEvent responseEvent) { - if ( getSipListener(responseEvent) != null ) { - getSipListener(responseEvent).processResponse(responseEvent); - } + getSipListener(responseEvent).processResponse(responseEvent); } diff --git a/src/test/unit/gov/nist/javax/sip/stack/ctx491/Shootme.java b/src/test/unit/gov/nist/javax/sip/stack/ctx491/Shootme.java index 9c3181baa..ec63a28bb 100644 --- a/src/test/unit/gov/nist/javax/sip/stack/ctx491/Shootme.java +++ b/src/test/unit/gov/nist/javax/sip/stack/ctx491/Shootme.java @@ -155,8 +155,6 @@ public void processInvite(RequestEvent requestEvent, logger.info("Dialog state " + dialog.getState()); } st.sendResponse(response); - - Thread.sleep(500); response = protocolObjects.messageFactory.createResponse(200, request); toHeader = (ToHeader) response.getHeader(ToHeader.NAME); toHeader.setTag("4321"); @@ -264,7 +262,7 @@ public SipProvider createSipProvider() throws Exception { public static void main(String args[]) throws Exception { logger.addAppender( new ConsoleAppender(new SimpleLayout())); - ProtocolObjects protocolObjects = new ProtocolObjects("shootme", "gov.nist","udp",true,false, false); + ProtocolObjects protocolObjects = new ProtocolObjects("shootme", "gov.nist","udp",true,false); Shootme shootme = new Shootme(protocolObjects); shootme.createSipProvider().addSipListener(shootme); diff --git a/src/test/unit/gov/nist/javax/sip/stack/dialog/b2bua/BackToBackUserAgent.java b/src/test/unit/gov/nist/javax/sip/stack/dialog/b2bua/BackToBackUserAgent.java index 53d339dcb..6d6cb8215 100644 --- a/src/test/unit/gov/nist/javax/sip/stack/dialog/b2bua/BackToBackUserAgent.java +++ b/src/test/unit/gov/nist/javax/sip/stack/dialog/b2bua/BackToBackUserAgent.java @@ -205,7 +205,7 @@ public BackToBackUserAgent(int port1, int port2) { sipFactory = SipFactory.getInstance(); sipFactory.setPathName("gov.nist"); Properties properties = new Properties(); - this.protocolObjects = new ProtocolObjects("backtobackua","gov.nist","udp",true,true, false); + this.protocolObjects = new ProtocolObjects("backtobackua","gov.nist","udp",true,true); try { diff --git a/src/test/unit/gov/nist/javax/sip/stack/dialog/b2bua/Shootist.java b/src/test/unit/gov/nist/javax/sip/stack/dialog/b2bua/Shootist.java index 3b2a49c3e..693aaa5fe 100644 --- a/src/test/unit/gov/nist/javax/sip/stack/dialog/b2bua/Shootist.java +++ b/src/test/unit/gov/nist/javax/sip/stack/dialog/b2bua/Shootist.java @@ -143,7 +143,7 @@ public Shootist(int myPort, int proxyPort) throws Exception { this.port = myPort; - ProtocolObjects sipObjects = new ProtocolObjects("shootist","gov.nist","udp",true,false, false); + ProtocolObjects sipObjects = new ProtocolObjects("shootist","gov.nist","udp",true,false); addressFactory = sipObjects.addressFactory; messageFactory = sipObjects.messageFactory; headerFactory = sipObjects.headerFactory; diff --git a/src/test/unit/gov/nist/javax/sip/stack/dialog/b2bua/Shootme.java b/src/test/unit/gov/nist/javax/sip/stack/dialog/b2bua/Shootme.java index 67d4e6c10..861771650 100644 --- a/src/test/unit/gov/nist/javax/sip/stack/dialog/b2bua/Shootme.java +++ b/src/test/unit/gov/nist/javax/sip/stack/dialog/b2bua/Shootme.java @@ -342,7 +342,7 @@ public Shootme( int myPort, boolean sendRinging, int delay ) throws TooManyListe this.delay = delay; this.sendRinging = sendRinging; - ProtocolObjects sipObjects = new ProtocolObjects("shootme","gov.nist","udp",true,false, false); + ProtocolObjects sipObjects = new ProtocolObjects("shootme","gov.nist","udp",true,false); addressFactory = sipObjects.addressFactory; messageFactory = sipObjects.messageFactory; headerFactory = sipObjects.headerFactory; diff --git a/src/test/unit/gov/nist/javax/sip/stack/dialog/b2bua/reinvite/BackToBackUserAgent.java b/src/test/unit/gov/nist/javax/sip/stack/dialog/b2bua/reinvite/BackToBackUserAgent.java index 49ba81a6f..e263913f3 100644 --- a/src/test/unit/gov/nist/javax/sip/stack/dialog/b2bua/reinvite/BackToBackUserAgent.java +++ b/src/test/unit/gov/nist/javax/sip/stack/dialog/b2bua/reinvite/BackToBackUserAgent.java @@ -233,7 +233,7 @@ public BackToBackUserAgent(int port1, int port2) { sipFactory = SipFactory.getInstance(); sipFactory.setPathName("gov.nist"); Properties properties = new Properties(); - this.protocolObjects = new ProtocolObjects("backtobackua","gov.nist","udp",true,true, false); + this.protocolObjects = new ProtocolObjects("backtobackua","gov.nist","udp",true,true); try { diff --git a/src/test/unit/gov/nist/javax/sip/stack/dialog/b2bua/reinvite/Shootist.java b/src/test/unit/gov/nist/javax/sip/stack/dialog/b2bua/reinvite/Shootist.java index 07db85aaa..7d911a156 100644 --- a/src/test/unit/gov/nist/javax/sip/stack/dialog/b2bua/reinvite/Shootist.java +++ b/src/test/unit/gov/nist/javax/sip/stack/dialog/b2bua/reinvite/Shootist.java @@ -143,7 +143,7 @@ public Shootist(int myPort, int proxyPort) throws Exception { this.port = myPort; - ProtocolObjects sipObjects = new ProtocolObjects("shootist","gov.nist","udp",true,false, false); + ProtocolObjects sipObjects = new ProtocolObjects("shootist","gov.nist","udp",true,false); addressFactory = sipObjects.addressFactory; messageFactory = sipObjects.messageFactory; headerFactory = sipObjects.headerFactory; diff --git a/src/test/unit/gov/nist/javax/sip/stack/dialog/b2bua/reinvite/Shootme.java b/src/test/unit/gov/nist/javax/sip/stack/dialog/b2bua/reinvite/Shootme.java index ab54cbf81..ccdb8559a 100644 --- a/src/test/unit/gov/nist/javax/sip/stack/dialog/b2bua/reinvite/Shootme.java +++ b/src/test/unit/gov/nist/javax/sip/stack/dialog/b2bua/reinvite/Shootme.java @@ -348,7 +348,7 @@ public Shootme( int myPort, boolean sendRinging, int delay ) throws TooManyListe this.delay = delay; this.sendRinging = sendRinging; - ProtocolObjects sipObjects = new ProtocolObjects("shootme","gov.nist","udp",true,false, false); + ProtocolObjects sipObjects = new ProtocolObjects("shootme","gov.nist","udp",true,false); addressFactory = sipObjects.addressFactory; messageFactory = sipObjects.messageFactory; headerFactory = sipObjects.headerFactory; diff --git a/src/test/unit/gov/nist/javax/sip/stack/dialog/termination/DialogTerminationOn50XTest.java b/src/test/unit/gov/nist/javax/sip/stack/dialog/termination/DialogTerminationOn50XTest.java index 7d82dbfe4..b17c984c1 100644 --- a/src/test/unit/gov/nist/javax/sip/stack/dialog/termination/DialogTerminationOn50XTest.java +++ b/src/test/unit/gov/nist/javax/sip/stack/dialog/termination/DialogTerminationOn50XTest.java @@ -89,8 +89,8 @@ public void testSendInviteShouldNotTerminatedOnINFO() { return; } if (i != 600) { -// doTearDown(false); -// doSetUp(); + doTearDown(false); + doSetUp(); } } diff --git a/src/test/unit/gov/nist/javax/sip/stack/dialog/timeout/DialogTimeoutTest.java b/src/test/unit/gov/nist/javax/sip/stack/dialog/timeout/DialogTimeoutTest.java index 1327fd783..e93534173 100644 --- a/src/test/unit/gov/nist/javax/sip/stack/dialog/timeout/DialogTimeoutTest.java +++ b/src/test/unit/gov/nist/javax/sip/stack/dialog/timeout/DialogTimeoutTest.java @@ -15,9 +15,20 @@ */ package test.unit.gov.nist.javax.sip.stack.dialog.timeout; +import gov.nist.javax.sip.DialogTimeoutEvent; +import gov.nist.javax.sip.SipListenerExt; import gov.nist.javax.sip.SipStackImpl; +import java.util.EventObject; + +import javax.sip.DialogTerminatedEvent; +import javax.sip.IOExceptionEvent; +import javax.sip.RequestEvent; +import javax.sip.ResponseEvent; +import javax.sip.SipListener; import javax.sip.SipProvider; +import javax.sip.TimeoutEvent; +import javax.sip.TransactionTerminatedEvent; import org.apache.log4j.Logger; @@ -31,7 +42,7 @@ * @author jean deruelle * */ -public class DialogTimeoutTest extends ScenarioHarness { +public class DialogTimeoutTest extends ScenarioHarness implements SipListenerExt { private ProtocolObjects shootistProtocolObjs; @@ -47,13 +58,20 @@ public class DialogTimeoutTest extends ScenarioHarness { private ShootmeNotImplementingListener shootmeNotImplementingListener; private static final Logger logger = Logger.getLogger("test.tck"); - private static final int TIMEOUT = 60000; + private static final int TIMEOUT = 45000; static { if (!logger.isAttached(console)) logger.addAppender(console); } + private SipListener getSipListener(EventObject sipEvent) { + SipProvider source = (SipProvider) sipEvent.getSource(); + SipListener listener = (SipListener) providerTable.get(source); + assertTrue(listener != null); + return listener; + } + public DialogTimeoutTest() { super("DialogTerminationOn500Test", true); @@ -77,12 +95,11 @@ private void doSetUp() { public void testDialogTimeoutSipListenerExt() { try { - this.shootistProtocolObjs = new ProtocolObjects("shootist", "gov.nist", "udp", false,false, true); + this.shootistProtocolObjs = new ProtocolObjects("shootist", "gov.nist", "udp", false,false); shootist = new Shootist(shootistProtocolObjs); SipProvider shootistProvider = shootist.createSipProvider(); - this.shootmeProtocolObjs = new ProtocolObjects("shootme", "gov.nist", "udp", false,false, true); - ((SipStackImpl)shootmeProtocolObjs.sipStack).setAggressiveCleanup(true); + this.shootmeProtocolObjs = new ProtocolObjects("shootme", "gov.nist", "udp", false,false); shootme = new Shootme(shootmeProtocolObjs); SipProvider shootmeProvider = shootme.createSipProvider(); @@ -91,8 +108,8 @@ public void testDialogTimeoutSipListenerExt() { shootme.init(); providerTable.put(shootmeProvider, shootme); - shootistProvider.addSipListener(shootist); - shootmeProvider.addSipListener(shootme); + shootistProvider.addSipListener(this); + shootmeProvider.addSipListener(this); getRiProtocolObjects().start(); if (getTiProtocolObjects() != getRiProtocolObjects()) @@ -120,13 +137,12 @@ public void testDialogTimeoutSipListenerExt() { public void testDialogTimeoutAndTerminatedSipListenerExt() { try { - this.shootistProtocolObjs = new ProtocolObjects("shootist", "gov.nist", "udp", false,false, true); + this.shootistProtocolObjs = new ProtocolObjects("shootist", "gov.nist", "udp", false,false); shootist = new Shootist(shootistProtocolObjs); shootist.setSendByeOnDialogTimeout(true); SipProvider shootistProvider = shootist.createSipProvider(); - this.shootmeProtocolObjs = new ProtocolObjects("shootme", "gov.nist", "udp", false,false, true); - ((SipStackImpl)shootmeProtocolObjs.sipStack).setAggressiveCleanup(true); + this.shootmeProtocolObjs = new ProtocolObjects("shootme", "gov.nist", "udp", false,false); shootme = new Shootme(shootmeProtocolObjs); shootme.setReceiveBye(true); SipProvider shootmeProvider = shootme.createSipProvider(); @@ -136,8 +152,8 @@ public void testDialogTimeoutAndTerminatedSipListenerExt() { shootme.init(); providerTable.put(shootmeProvider, shootme); - shootistProvider.addSipListener(shootist); - shootmeProvider.addSipListener(shootme); + shootistProvider.addSipListener(this); + shootmeProvider.addSipListener(this); getRiProtocolObjects().start(); if (getTiProtocolObjects() != getRiProtocolObjects()) @@ -164,12 +180,11 @@ public void testDialogTimeoutAndTerminatedSipListenerExt() { public void testDialogTimeoutDialogDeletedNotImplementedSipListenerExt() { try { - this.shootistProtocolObjs = new ProtocolObjects("shootist", "gov.nist", "udp", false,false, true); + this.shootistProtocolObjs = new ProtocolObjects("shootist", "gov.nist", "udp", false,false); shootistNotImplementingSipListenerExt = new ShootistNotImplementingSipListenerExt(shootistProtocolObjs); SipProvider shootistProvider = shootistNotImplementingSipListenerExt.createSipProvider(); - this.shootmeProtocolObjs = new ProtocolObjects("shootme", "gov.nist", "udp", false,false, true); - ((SipStackImpl)shootmeProtocolObjs.sipStack).setAggressiveCleanup(true); + this.shootmeProtocolObjs = new ProtocolObjects("shootme", "gov.nist", "udp", false,false); shootme = new Shootme(shootmeProtocolObjs); SipProvider shootmeProvider = shootme.createSipProvider(); @@ -179,7 +194,7 @@ public void testDialogTimeoutDialogDeletedNotImplementedSipListenerExt() { shootme.init(); providerTable.put(shootmeProvider, shootme); shootistProvider.addSipListener(shootistNotImplementingSipListenerExt); - shootmeProvider.addSipListener(shootme); + shootmeProvider.addSipListener(this); getRiProtocolObjects().start(); if (getTiProtocolObjects() != getRiProtocolObjects()) @@ -206,12 +221,11 @@ public void testDialogTimeoutDialogDeletedNotImplementedSipListenerExt() { public void testDialogTimeoutAutoDialog() { try { - this.shootistProtocolObjs = new ProtocolObjects("shootist", "gov.nist", "udp", true,false, true); + this.shootistProtocolObjs = new ProtocolObjects("shootist", "gov.nist", "udp", true,false); shootist = new Shootist(shootistProtocolObjs); SipProvider shootistProvider = shootist.createSipProvider(); - this.shootmeProtocolObjs = new ProtocolObjects("shootme", "gov.nist", "udp", true,false, true); - ((SipStackImpl)shootmeProtocolObjs.sipStack).setAggressiveCleanup(true); + this.shootmeProtocolObjs = new ProtocolObjects("shootme", "gov.nist", "udp", true,false); shootme = new Shootme(shootmeProtocolObjs); SipProvider shootmeProvider = shootme.createSipProvider(); @@ -220,8 +234,8 @@ public void testDialogTimeoutAutoDialog() { shootme.init(); providerTable.put(shootmeProvider, shootme); - shootistProvider.addSipListener(shootist); - shootmeProvider.addSipListener(shootme); + shootistProvider.addSipListener(this); + shootmeProvider.addSipListener(this); getRiProtocolObjects().start(); if (getTiProtocolObjects() != getRiProtocolObjects()) @@ -248,12 +262,11 @@ public void testDialogTimeoutAutoDialog() { public void testDialogTimeoutB2BUABothCalled() { try { - this.shootistProtocolObjs = new ProtocolObjects("shootist", "gov.nist", "udp", false,true, true); + this.shootistProtocolObjs = new ProtocolObjects("shootist", "gov.nist", "udp", false,true); shootist = new Shootist(shootistProtocolObjs); SipProvider shootistProvider = shootist.createSipProvider(); - this.shootmeProtocolObjs = new ProtocolObjects("shootme", "gov.nist", "udp", false,false, true); - ((SipStackImpl)shootmeProtocolObjs.sipStack).setAggressiveCleanup(true); + this.shootmeProtocolObjs = new ProtocolObjects("shootme", "gov.nist", "udp", false,false); shootmeNotImplementingListener = new ShootmeNotImplementingListener(shootmeProtocolObjs); shootmeNotImplementingListener.setStateIsOk(true); SipProvider shootmeProvider = shootmeNotImplementingListener.createSipProvider(); @@ -263,8 +276,8 @@ public void testDialogTimeoutB2BUABothCalled() { shootmeNotImplementingListener.init(); providerTable.put(shootmeProvider, shootmeNotImplementingListener); - shootistProvider.addSipListener(shootist); - shootmeProvider.addSipListener(shootmeNotImplementingListener); + shootistProvider.addSipListener(this); + shootmeProvider.addSipListener(this); getRiProtocolObjects().start(); if (getTiProtocolObjects() != getRiProtocolObjects()) @@ -298,7 +311,7 @@ public void tearDown() { private void doTearDown(boolean definetly) { try { - Thread.sleep(3000); + Thread.sleep(2000); // this.shootist.checkState(); // this.shootme.checkState(); shootmeProtocolObjs.destroy(); @@ -311,4 +324,40 @@ private void doTearDown(boolean definetly) { ex.printStackTrace(); } } + + public void processRequest(RequestEvent requestEvent) { + getSipListener(requestEvent).processRequest(requestEvent); + + } + + public void processResponse(ResponseEvent responseEvent) { + getSipListener(responseEvent).processResponse(responseEvent); + + } + + public void processTimeout(TimeoutEvent timeoutEvent) { + getSipListener(timeoutEvent).processTimeout(timeoutEvent); + } + + public void processDialogTimeout(DialogTimeoutEvent timeoutEvent) { + if(getSipListener(timeoutEvent) instanceof SipListenerExt) { + ((SipListenerExt)getSipListener(timeoutEvent)).processDialogTimeout(timeoutEvent); + } + } + + public void processIOException(IOExceptionEvent exceptionEvent) { + fail("unexpected exception"); + + } + + public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) { + getSipListener(transactionTerminatedEvent).processTransactionTerminated(transactionTerminatedEvent); + + } + + public void processDialogTerminated(DialogTerminatedEvent dialogTerminatedEvent) { + getSipListener(dialogTerminatedEvent).processDialogTerminated(dialogTerminatedEvent); + + } + } diff --git a/src/test/unit/gov/nist/javax/sip/stack/dialog/timeout/Shootme.java b/src/test/unit/gov/nist/javax/sip/stack/dialog/timeout/Shootme.java index 50e18f42e..d2b3063da 100644 --- a/src/test/unit/gov/nist/javax/sip/stack/dialog/timeout/Shootme.java +++ b/src/test/unit/gov/nist/javax/sip/stack/dialog/timeout/Shootme.java @@ -18,7 +18,6 @@ import gov.nist.javax.sip.DialogTimeoutEvent; import gov.nist.javax.sip.SipListenerExt; import gov.nist.javax.sip.DialogTimeoutEvent.Reason; -import gov.nist.javax.sip.stack.SIPDialog; import java.util.Timer; import java.util.TimerTask; @@ -83,7 +82,6 @@ public void run() { if(!protocolObjects.autoDialog) { ((SipProvider)requestEvent.getSource()).getNewDialog(st); } - st.getDialog().setApplicationData("some junk"); // System.out.println("got a server tranasaction " + st); st.sendResponse(response); // send 180(RING) @@ -184,15 +182,13 @@ public void processAck(RequestEvent requestEvent, ServerTransaction serverTransa } } - public void processDialogTerminated(DialogTerminatedEvent dialogTerminatedEvent) { + public void processDialogTerminated(DialogTerminatedEvent dialogTerminatedEvent) { if(!protocolObjects.autoDialog && !receiveBye) { stateIsOk = false; DialogTimeoutTest.fail("This shouldn't be called since a dialogtimeout event should be passed to the application instead!"); } else { stateIsOk = true; } - TimerTask timerTask = new CheckAppData(dialogTerminatedEvent.getDialog()); - new Timer().schedule(timerTask, 15000); } public void processInfo(RequestEvent requestEvent) { @@ -290,7 +286,6 @@ public void processResponse(ResponseEvent responseReceivedEvent) { if (response.getStatusCode() == Response.OK && ((CSeqHeader) response.getHeader(CSeqHeader.NAME)).getMethod().equals(Request.INVITE)) { Dialog dialog = tid.getDialog(); - Request request = tid.getRequest(); dialog.sendAck(request); } @@ -321,21 +316,15 @@ public void processTimeout(javax.sip.TimeoutEvent timeoutEvent) { } public void processDialogTimeout(DialogTimeoutEvent timeoutEvent) { - System.out.println("processDialogTerminated " + timeoutEvent.getDialog()); - - DialogTimeoutEvent dialogAckTimeoutEvent = (DialogTimeoutEvent)timeoutEvent; - Dialog timeoutDialog = dialogAckTimeoutEvent.getDialog(); - if(timeoutDialog == null){ - DialogTimeoutTest.fail( + DialogTimeoutEvent dialogAckTimeoutEvent = (DialogTimeoutEvent)timeoutEvent; + Dialog timeoutDialog = dialogAckTimeoutEvent.getDialog(); + if(timeoutDialog == null){ + DialogTimeoutTest.fail( "Shootist: Exception on timeout, dialog shouldn't be null"); - stateIsOk = false; - return; - } - if(dialogAckTimeoutEvent.getReason() == Reason.AckNotReceived) { - stateIsOk = true; - } - TimerTask timerTask = new CheckAppData(timeoutDialog); - new Timer().schedule(timerTask, 9000); + } + if(dialogAckTimeoutEvent.getReason() == Reason.AckNotReceived) { + stateIsOk = true; + } } public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) { @@ -361,19 +350,4 @@ public boolean isReceiveBye() { return receiveBye; } - class CheckAppData extends TimerTask { - Dialog dialog; - - public CheckAppData(Dialog dialog) { - this.dialog = dialog; - } - - public void run() { - System.out.println("Checking app data " + dialog.getApplicationData()); - if(dialog.getApplicationData() == null || !dialog.getApplicationData().equals("some junk")) { - stateIsOk = false; - DialogTimeoutTest.fail("application data should never be null except if nullified by the application !"); - } - } - } } diff --git a/src/test/unit/gov/nist/javax/sip/stack/dialog/timeout/ShootmeNotImplementingListener.java b/src/test/unit/gov/nist/javax/sip/stack/dialog/timeout/ShootmeNotImplementingListener.java index 39288d0b5..49240e65b 100644 --- a/src/test/unit/gov/nist/javax/sip/stack/dialog/timeout/ShootmeNotImplementingListener.java +++ b/src/test/unit/gov/nist/javax/sip/stack/dialog/timeout/ShootmeNotImplementingListener.java @@ -16,7 +16,6 @@ package test.unit.gov.nist.javax.sip.stack.dialog.timeout; import gov.nist.javax.sip.DialogTimeoutEvent; -import gov.nist.javax.sip.stack.SIPDialog; import java.util.Timer; import java.util.TimerTask; @@ -82,8 +81,6 @@ public void run() { if(!protocolObjects.autoDialog) { ((SipProvider)requestEvent.getSource()).getNewDialog(st); } - st.getDialog().setApplicationData("some junk"); - // System.out.println("got a server tranasaction " + st); st.sendResponse(response); // send 180(RING) response = messageFactory.createResponse(200, request); @@ -183,8 +180,6 @@ public void processAck(RequestEvent requestEvent, ServerTransaction serverTransa } public void processDialogTerminated(DialogTerminatedEvent dialogTerminatedEvent) { - TimerTask timerTask = new CheckAppData(dialogTerminatedEvent.getDialog()); - new Timer().schedule(timerTask, 9000); // Dialog dialog = dialogTerminatedEvent.getDialog(); // // System.out.println("Dialog Terminated Event " + dialog.getDialogId()); @@ -348,19 +343,4 @@ public boolean isStateIsOk() { return stateIsOk; } - class CheckAppData extends TimerTask { - Dialog dialog; - - public CheckAppData(Dialog dialog) { - this.dialog = dialog; - } - - public void run() { - System.out.println("Checking app data " + dialog.getApplicationData()); - if(dialog.getApplicationData() == null || !dialog.getApplicationData().equals("some junk")) { - stateIsOk = false; - DialogTimeoutTest.fail("application data should never be null except if nullified by the application !"); - } - } - } } diff --git a/src/test/unit/gov/nist/javax/sip/stack/forkedinvite/InviteTest.java b/src/test/unit/gov/nist/javax/sip/stack/forkedinvite/InviteTest.java index 935e16cb0..7050fbdd1 100644 --- a/src/test/unit/gov/nist/javax/sip/stack/forkedinvite/InviteTest.java +++ b/src/test/unit/gov/nist/javax/sip/stack/forkedinvite/InviteTest.java @@ -67,160 +67,78 @@ public void tearDown() { } public void testInvite() throws Exception { - try { - shootist = new Shootist(6050, 5070, "on", true); - SipProvider shootistProvider = shootist.createSipProvider(); - shootistProvider.addSipListener(shootist); - boolean sendRinging = true; - for (int i = 0 ; i < forkCount ; i ++ ) { - - Shootme shootme = new Shootme(5080 + i,sendRinging,4000 + (500 *i), 4000 + (500 *i)); - sendRinging = true; - SipProvider shootmeProvider = shootme.createProvider(); - shootmeProvider.addSipListener(shootme); - this.shootme.add(shootme); - } - - - - this.proxy = new Proxy(5070,forkCount); - SipProvider provider = proxy.createSipProvider(); - provider.addSipListener(proxy); - logger.debug("setup completed"); + shootist = new Shootist(6050, 5070, "on"); + SipProvider shootistProvider = shootist.createSipProvider(); + shootistProvider.addSipListener(shootist); + boolean sendRinging = true; + for (int i = 0 ; i < forkCount ; i ++ ) { - this.shootist.sendInvite(forkCount); - - Thread.sleep(35000); - this.shootist.checkState(); - int ackCount = 0; - for ( Shootme shootme: this.shootme) { - shootme.checkState(); - if ( shootme.isAckSeen()) { - ackCount ++; - } - } - assertEquals("ACK count must be exactly 2", 2,ackCount); - } finally { - this.shootist.stop(); - for ( Shootme shootme: this.shootme) { - shootme.stop(); - } - this.proxy.stop(); + Shootme shootme = new Shootme(5080 + i,sendRinging,400*forkCount - 200*i); + sendRinging = false; + SipProvider shootmeProvider = shootme.createProvider(); + shootmeProvider.addSipListener(shootme); + this.shootme.add(shootme); + } + + + + this.proxy = new Proxy(5070,forkCount); + SipProvider provider = proxy.createSipProvider(); + provider.addSipListener(proxy); + logger.debug("setup completed"); + + this.shootist.sendInvite(forkCount); + + Thread.sleep(12000); + this.shootist.checkState(); + int ackCount = 0; + for ( Shootme shootme: this.shootme) { + shootme.checkState(); + if ( shootme.isAckSeen()) { + ackCount ++; + } } + assertEquals("ACK count must be exactly 2", 2,ackCount); + this.shootist.stop(); + for ( Shootme shootme: this.shootme) { + shootme.stop(); + } + this.proxy.stop(); } public void testInviteAutomaticDialogNonEnabled() throws Exception { - try { - shootist = new Shootist(6050, 5070, "off", true); - SipProvider shootistProvider = shootist.createSipProvider(); - shootistProvider.addSipListener(shootist); - boolean sendRinging = true; - for (int i = 0 ; i < forkCount ; i ++ ) { - Shootme shootme = new Shootme(5080 + i,sendRinging, 4000 + (100 *i), 4000 + (100 *i)); - sendRinging = true; - SipProvider shootmeProvider = shootme.createProvider(); - shootmeProvider.addSipListener(shootme); - this.shootme.add(shootme); - } - this.proxy = new Proxy(5070,forkCount); - SipProvider provider = proxy.createSipProvider(); - provider.addSipListener(proxy); - logger.debug("setup completed"); - - this.shootist.sendInvite(forkCount); - Thread.sleep(35000); - this.shootist.checkState(); - int ackCount = 0; - for ( Shootme shootme: this.shootme) { - shootme.checkState(); - if ( shootme.isAckSeen()) { - ackCount ++; - } - } - assertEquals("ACK count must be exactly 2", 2,ackCount); - } finally { - this.shootist.stop(); - for ( Shootme shootme: this.shootme) { - shootme.stop(); - } - this.proxy.stop(); + shootist = new Shootist(6050, 5070, "off"); + SipProvider shootistProvider = shootist.createSipProvider(); + shootistProvider.addSipListener(shootist); + boolean sendRinging = true; + for (int i = 0 ; i < forkCount ; i ++ ) { + Shootme shootme = new Shootme(5080 + i,sendRinging,400*forkCount - 200*i); + sendRinging = false; + SipProvider shootmeProvider = shootme.createProvider(); + shootmeProvider.addSipListener(shootme); + this.shootme.add(shootme); } - } - - public void testInviteAutomaticDialogNonEnabledForkSecond() throws Exception { - try { - shootist = new Shootist(6050, 5070, "off", false); - SipProvider shootistProvider = shootist.createSipProvider(); - shootistProvider.addSipListener(shootist); - boolean sendRinging = true; - for (int i = 0 ; i < forkCount ; i ++ ) { - Shootme shootme = new Shootme(5080 + i,sendRinging, 4000 - (100 *i), 4000 - (100 *i)); - sendRinging = true; - SipProvider shootmeProvider = shootme.createProvider(); - shootmeProvider.addSipListener(shootme); - this.shootme.add(shootme); - } - this.proxy = new Proxy(5070,forkCount); - SipProvider provider = proxy.createSipProvider(); - provider.addSipListener(proxy); - logger.debug("setup completed"); - - this.shootist.sendInvite(forkCount); - Thread.sleep(35000); - this.shootist.checkState(); - int ackCount = 0; - for ( Shootme shootme: this.shootme) { - shootme.checkState(); - if ( shootme.isAckSeen()) { - ackCount ++; - } - } - assertEquals("ACK count must be exactly 2", 2,ackCount); - } finally { - this.shootist.stop(); - for ( Shootme shootme: this.shootme) { - shootme.stop(); - } - this.proxy.stop(); + this.proxy = new Proxy(5070,forkCount); + SipProvider provider = proxy.createSipProvider(); + provider.addSipListener(proxy); + logger.debug("setup completed"); + + this.shootist.sendInvite(forkCount); + Thread.sleep(12000); + this.shootist.checkState(); + int ackCount = 0; + for ( Shootme shootme: this.shootme) { + shootme.checkState(); + if ( shootme.isAckSeen()) { + ackCount ++; + } } - } - - public void testInviteAutomaticDialogNonEnabledOKFromSecondForkFirst() throws Exception { - try { - shootist = new Shootist(6050, 5070, "off", true); - SipProvider shootistProvider = shootist.createSipProvider(); - shootistProvider.addSipListener(shootist); - boolean sendRinging = true; - for (int i = 0 ; i < forkCount ; i ++ ) { - Shootme shootme = new Shootme(5080 + i,sendRinging, 4000 + (100 *i), 4000 - (100 *i)); - sendRinging = true; - SipProvider shootmeProvider = shootme.createProvider(); - shootmeProvider.addSipListener(shootme); - this.shootme.add(shootme); - } - this.proxy = new Proxy(5070,forkCount); - SipProvider provider = proxy.createSipProvider(); - provider.addSipListener(proxy); - logger.debug("setup completed"); - - this.shootist.sendInvite(forkCount); - Thread.sleep(35000); - this.shootist.checkState(); - int ackCount = 0; - for ( Shootme shootme: this.shootme) { - shootme.checkState(); - if ( shootme.isAckSeen()) { - ackCount ++; - } - } - assertEquals("ACK count must be exactly 2", 2,ackCount); - } finally { - this.shootist.stop(); - for ( Shootme shootme: this.shootme) { - shootme.stop(); - } - this.proxy.stop(); + assertEquals("ACK count must be exactly 2", 2,ackCount); + this.shootist.stop(); + for ( Shootme shootme: this.shootme) { + shootme.stop(); } + this.proxy.stop(); } /** @@ -228,42 +146,39 @@ public void testInviteAutomaticDialogNonEnabledOKFromSecondForkFirst() throws Ex * the app code has called createNewDialog doesn't create a dialog */ public void testAutomaticDialogNonEnabledRaceCondition() throws Exception { - try { - shootist = new Shootist(6050, 5070, "off", false); - shootist.setCreateDialogAfterRequest(true); - SipProvider shootistProvider = shootist.createSipProvider(); - shootistProvider.addSipListener(shootist); - boolean sendRinging = true; - forkCount = 1; - for (int i = 0 ; i < forkCount ; i ++ ) { - Shootme shootme = new Shootme(5080 + i,sendRinging, 4000 + (500 *i), 4000 + (500 *i)); - sendRinging = true; - SipProvider shootmeProvider = shootme.createProvider(); - shootmeProvider.addSipListener(shootme); - this.shootme.add(shootme); - } - this.proxy = new Proxy(5070,forkCount); - SipProvider provider = proxy.createSipProvider(); - provider.addSipListener(proxy); - logger.debug("setup completed"); - - this.shootist.sendInvite(0); - Thread.sleep(35000); - this.shootist.checkState(); - int ackCount = 0; - for ( Shootme shootme: this.shootme) { - if ( shootme.isAckSeen()) { - ackCount ++; - } - } - assertEquals("ACK count must be exactly 0", 0,ackCount); - } finally { - this.shootist.stop(); - for ( Shootme shootme: this.shootme) { - shootme.stop(); - } - this.proxy.stop(); + shootist = new Shootist(6050, 5070, "off"); + shootist.setCreateDialogAfterRequest(true); + SipProvider shootistProvider = shootist.createSipProvider(); + shootistProvider.addSipListener(shootist); + boolean sendRinging = true; + forkCount = 1; + for (int i = 0 ; i < forkCount ; i ++ ) { + Shootme shootme = new Shootme(5080 + i,sendRinging,400*forkCount - 200*i); + sendRinging = false; + SipProvider shootmeProvider = shootme.createProvider(); + shootmeProvider.addSipListener(shootme); + this.shootme.add(shootme); + } + this.proxy = new Proxy(5070,forkCount); + SipProvider provider = proxy.createSipProvider(); + provider.addSipListener(proxy); + logger.debug("setup completed"); + + this.shootist.sendInvite(0); + Thread.sleep(12000); + this.shootist.checkState(); + int ackCount = 0; + for ( Shootme shootme: this.shootme) { + if ( shootme.isAckSeen()) { + ackCount ++; + } + } + assertEquals("ACK count must be exactly 0", 0,ackCount); + this.shootist.stop(); + for ( Shootme shootme: this.shootme) { + shootme.stop(); } + this.proxy.stop(); } diff --git a/src/test/unit/gov/nist/javax/sip/stack/forkedinvite/Shootist.java b/src/test/unit/gov/nist/javax/sip/stack/forkedinvite/Shootist.java index a35d53b75..a1c5622f9 100644 --- a/src/test/unit/gov/nist/javax/sip/stack/forkedinvite/Shootist.java +++ b/src/test/unit/gov/nist/javax/sip/stack/forkedinvite/Shootist.java @@ -1,8 +1,6 @@ package test.unit.gov.nist.javax.sip.stack.forkedinvite; import gov.nist.javax.sip.ResponseEventExt; -import gov.nist.javax.sip.SipStackImpl; -import gov.nist.javax.sip.message.ResponseExt; import java.util.ArrayList; import java.util.HashSet; @@ -43,10 +41,7 @@ import junit.framework.TestCase; -import org.apache.log4j.ConsoleAppender; import org.apache.log4j.Logger; -import org.apache.log4j.SimpleLayout; -import org.apache.log4j.helpers.NullEnumeration; /** @@ -79,21 +74,11 @@ public class Shootist implements SipListener { private static Logger logger = Logger.getLogger(Shootist.class); - static { - if (logger.getAllAppenders().equals(NullEnumeration.getInstance())) { - logger.addAppender(new ConsoleAppender(new SimpleLayout())); - } - } - private Dialog originalDialog; - - private Dialog earlyDialog; private HashSet forkedDialogs = new HashSet(); - - private HashSet forkedEarlyDialogs = new HashSet(); private Dialog ackedDialog; @@ -126,10 +111,6 @@ public class Shootist implements SipListener { private boolean createDialogAfterRequest = false; - private boolean terminatedDialogWasOneOfCancelled; - - private boolean forkFirst; - class SendBye extends TimerTask { private Dialog dialog; @@ -142,6 +123,8 @@ public void run() { TestCase.assertEquals ("Dialog state must be confirmed", DialogState.CONFIRMED,dialog.getState()); + + Request byeRequest = dialog.createRequest(Request.BYE); ClientTransaction ctx = sipProvider.getNewClientTransaction(byeRequest); dialog.sendRequest(ctx); @@ -150,23 +133,27 @@ public void run() { } } + } - public Shootist(int myPort, int proxyPort, String createDialogAuto, boolean forkFirst) { + + + public Shootist(int myPort, int proxyPort, String createDialogAuto) { + + this.port = myPort; - this.peerPort = proxyPort; - this.forkFirst = forkFirst; - + SipObjects sipObjects = new SipObjects(myPort, "shootist", createDialogAuto); addressFactory = sipObjects.addressFactory; messageFactory = sipObjects.messageFactory; headerFactory = sipObjects.headerFactory; this.sipStack = sipObjects.sipStack; - + + this.peerPort = proxyPort; if(!createDialogAuto.equalsIgnoreCase("on")) { isAutomaticDialogSupportEnabled = false; } - } + } public void processRequest(RequestEvent requestReceivedEvent) { Request request = requestReceivedEvent.getRequest(); @@ -209,112 +196,87 @@ public void processBye(Request request, } public synchronized void processResponse(ResponseEvent responseReceived) { - try { - ResponseEventExt responseReceivedEvent = (ResponseEventExt) responseReceived; - Response response = (Response) responseReceivedEvent.getResponse(); - ClientTransaction tid = responseReceivedEvent.getClientTransaction(); - CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME); - - logger.info("Response received : Status Code = " - + response.getStatusCode() + " " + cseq); - logger.info("Response = " + response + " class=" + response.getClass() ); - - Dialog dialog = responseReceivedEvent.getDialog(); - if(createDialogAfterRequest) { - TestCase.assertNull( dialog ); - return; - } else { - TestCase.assertNotNull( dialog ); - } - System.out.println("original Tx " + responseReceivedEvent.getOriginalTransaction()); - if (tid != null) - logger.info("transaction state is " + tid.getState()); - else - logger.info("transaction = " + tid); - - logger.info("Dialog = " + dialog); - logger.info("Dialog state is " + dialog.getState()); + logger.info("Got a response"); + ResponseEventExt responseReceivedEvent = (ResponseEventExt) responseReceived; + Response response = (Response) responseReceivedEvent.getResponse(); + ClientTransaction tid = responseReceivedEvent.getClientTransaction(); + CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME); + + logger.info("Response received : Status Code = " + + response.getStatusCode() + " " + cseq); + logger.info("Response = " + response + " class=" + response.getClass() ); + - String toTag = ((ResponseExt)response).getToHeader().getTag(); - boolean isFromFork = false; - if(forkFirst) { - isFromFork = toTag != null && !toTag.contains("shootme-5080"); - } else { - isFromFork = toTag != null && !toTag.contains("shootme-5081"); - } - logger.info("isRetransmission = " + responseReceivedEvent.isRetransmission() + " isFromForked = " + isFromFork + " isForked = " + responseReceivedEvent.isForkedResponse() + " response "+ response); - + Dialog dialog = responseReceivedEvent.getDialog(); + if(createDialogAfterRequest) { + TestCase.assertNull( dialog ); + return; + } else { + TestCase.assertNotNull( dialog ); + } + + System.out.println("original Tx " + responseReceivedEvent.getOriginalTransaction()); + if ( cseq.getMethod().equals(Request.INVITE)) { + TestCase.assertSame("Must preserve original dialog", + this.originalDialog,responseReceivedEvent.getOriginalTransaction().getDefaultDialog()); + } + + if (tid != null) + logger.info("transaction state is " + tid.getState()); + else + logger.info("transaction = " + tid); + + logger.info("Dialog = " + dialog); + + logger.info("Dialog state is " + dialog.getState()); + + try { if (response.getStatusCode() == Response.OK) { if (cseq.getMethod().equals(Request.INVITE)) { + TestCase.assertEquals( DialogState.CONFIRMED, dialog.getState() ); + Request ackRequest = dialog.createAck(cseq + .getSeqNumber()); + + TestCase.assertNotNull( ackRequest.getHeader( MaxForwardsHeader.NAME ) ); + + dialog.sendAck(ackRequest); // Proxy will fork. I will accept the first dialog. this.forkedDialogs.add(dialog); - if (!isFromFork) { - TestCase.assertFalse("non forked event must not set flag",responseReceivedEvent.isForkedResponse()); - - if(ackedDialog == null) { - TestCase.assertFalse("retransmission flag should be false",responseReceivedEvent.isRetransmission()); - TestCase.assertTrue( - "Dialog state should be CONFIRMED", dialog - .getState() == DialogState.CONFIRMED); - - TestCase.assertTrue(this.ackedDialog == null || - this.ackedDialog == dialog); - this.ackedDialog = dialog; - - Request ackRequest = dialog.createAck(cseq - .getSeqNumber()); - - TestCase.assertNotNull( ackRequest.getHeader( MaxForwardsHeader.NAME ) ); - // sleeping to see how it reacts with retrans - logger.info("Waiting to Send ACK"); - Thread.sleep(1000); - logger.info("Sending " + ackRequest); - dialog.sendAck(ackRequest); - - if ( callerSendsBye ) { - timer.schedule( new SendBye(ackedDialog), 2000 ); - } - } else { - TestCase.assertTrue("retransmission flag should be true",responseReceivedEvent.isRetransmission()); + if ( responseReceivedEvent.getClientTransaction() != null ) { + this.originalTransaction = responseReceivedEvent.getClientTransaction(); + logger.info("Sending ACK"); + TestCase.assertTrue( + "Dialog state should be CONFIRMED", dialog + .getState() == DialogState.CONFIRMED); + + TestCase.assertTrue(this.ackedDialog == null || + this.ackedDialog == dialog); + this.ackedDialog = dialog; + + if ( callerSendsBye ) { + timer.schedule( new SendBye(ackedDialog), 4000 ); } + } else { - TestCase.assertTrue("forked event must set flag",responseReceivedEvent.isForkedResponse()); - TestCase.assertSame("original ctx must match " , this.originalTransaction, - responseReceivedEvent.getOriginalTransaction()); - if ( cseq.getMethod().equals(Request.INVITE)) { - TestCase.assertSame("Must preserve original dialog", - this.originalDialog,responseReceivedEvent.getOriginalTransaction().getDefaultDialog()); - } - - if(canceledDialog.isEmpty()) { - TestCase.assertFalse("retransmission flag should be false",responseReceivedEvent.isRetransmission()); - TestCase.assertEquals( DialogState.CONFIRMED, dialog.getState() ); - this.canceledDialog.add(dialog); - Request ackRequest = dialog.createAck(cseq - .getSeqNumber()); + ResponseEventExt responseEventExt = (ResponseEventExt) responseReceivedEvent; + TestCase.assertTrue("forked event must set flag",responseEventExt.isForkedResponse()); + this.canceledDialog.add(dialog); + SipProvider sipProvider = (SipProvider) responseReceivedEvent + .getSource(); - TestCase.assertNotNull( ackRequest.getHeader( MaxForwardsHeader.NAME ) ); - // sleeping to see how it reacts with retrans - logger.info("Waiting to Send ACK"); - Thread.sleep(1000); - logger.info("Sending " + ackRequest); - dialog.sendAck(ackRequest); - - Thread.sleep(2000); - - Request byeRequest = dialog.createRequest(Request.BYE); - ClientTransaction ct = sipProvider - .getNewClientTransaction(byeRequest); - dialog.sendRequest(ct); - } else { - TestCase.assertTrue("retransmission flag should be true",responseReceivedEvent.isRetransmission()); - } + TestCase.assertSame("original ctx must match " , + responseEventExt.getOriginalTransaction(),this.originalTransaction); + + Request byeRequest = dialog.createRequest(Request.BYE); + ClientTransaction ct = sipProvider + .getNewClientTransaction(byeRequest); + dialog.sendRequest(ct); } } else if ( cseq.getMethod().equals(Request.BYE)) { - TestCase.assertFalse("retransmission flag should be false",responseReceivedEvent.isRetransmission()); + if ( dialog == this.ackedDialog) { this.byeResponseSeen = true; } @@ -322,21 +284,7 @@ public synchronized void processResponse(ResponseEvent responseReceived) { logger.info("Response method = " + cseq.getMethod()); } } else if ( response.getStatusCode() == Response.RINGING ) { - TestCase.assertEquals( DialogState.EARLY, dialog.getState() ); - this.forkedEarlyDialogs.add(dialog); - // Proxy will fork. This make sure the forked early dialog is not the same as the first one. - if(isFromFork) { - logger.info("forked early dialog= " + dialog + " for response " + response); - ResponseEventExt responseEventExt = (ResponseEventExt) responseReceivedEvent; - TestCase.assertTrue("forked event must set flag",responseEventExt.isForkedResponse()); - TestCase.assertNotSame(dialog, earlyDialog); - TestCase.assertSame(earlyDialog, responseEventExt.getOriginalTransaction().getDefaultDialog()); - } else { - earlyDialog = dialog; - logger.info("original early dialog= " + dialog + " for response " + response); - ResponseEventExt responseEventExt = (ResponseEventExt) responseReceivedEvent; - TestCase.assertFalse("non forked event must not set flag",responseEventExt.isForkedResponse()); - } + //TestHarness.assertEquals( DialogState.EARLY, dialog.getState() ); } } catch (Throwable ex) { ex.printStackTrace(); @@ -364,8 +312,6 @@ public SipProvider createSipProvider() { } public void checkState() { - TestCase.assertEquals("Should see " + this.counter + " distinct early dialogs", - counter, this.forkedEarlyDialogs.size()); TestCase.assertEquals("Should see " + this.counter + " distinct dialogs", counter,this.forkedDialogs.size()); if(!createDialogAfterRequest) { @@ -376,10 +322,8 @@ public void checkState() { } else { TestCase.assertTrue(originalDialog == null); } - TestCase.assertTrue(((SipStackImpl)sipStack).getDialogs(DialogState.EARLY).isEmpty()); - if(this.counter > 0) { - TestCase.assertTrue("DTE dialog must be one of those we canceled", terminatedDialogWasOneOfCancelled); - } + + // cleanup forkedDialogs.clear(); } @@ -520,7 +464,6 @@ public void sendInvite(int forkCount) { // Create the client transaction. inviteTid = sipProvider.getNewClientTransaction(request); - this.originalTransaction = inviteTid; Dialog dialog = null; if(isAutomaticDialogSupportEnabled) { dialog = inviteTid.getDialog(); @@ -563,10 +506,8 @@ public void processTransactionTerminated( public void processDialogTerminated( DialogTerminatedEvent dialogTerminatedEvent) { - logger.info("dialog Id " + dialogTerminatedEvent.getDialog().getDialogId()); - if(this.canceledDialog.contains((Dialog)dialogTerminatedEvent.getDialog() )) { - terminatedDialogWasOneOfCancelled= true; - } + TestCase.assertTrue("DTE dialog must be one of those we canceled", + this.canceledDialog.contains((Dialog)dialogTerminatedEvent.getDialog() )); } @@ -594,9 +535,10 @@ class DialogCreationDelayTask extends TimerTask { public void run() { try { originalDialog = sipProvider.getNewDialog(inviteTid); - TestCase.fail("Should not be able to create Dialog after request sent"); + TestCase.assertTrue("Initial dialog state should be null", + originalDialog.getState() == null); } catch (SipException e) { - logger.info("Got the expected SIP Exception"); + e.printStackTrace(); } } } diff --git a/src/test/unit/gov/nist/javax/sip/stack/forkedinvite/Shootme.java b/src/test/unit/gov/nist/javax/sip/stack/forkedinvite/Shootme.java index 64af31678..cac3536be 100644 --- a/src/test/unit/gov/nist/javax/sip/stack/forkedinvite/Shootme.java +++ b/src/test/unit/gov/nist/javax/sip/stack/forkedinvite/Shootme.java @@ -74,9 +74,9 @@ public class Shootme implements SipListener { private SipStack sipStack; - private int ringingDelay; + private int delay; - private int okDelay; + private int ringingDelay; private boolean sendRinging; @@ -172,32 +172,31 @@ public void processInvite(RequestEvent requestEvent, this.serverTxTable.put(txId, st); // Create the 100 Trying response. -// Response response = messageFactory.createResponse(Response.TRYING, -// request); -// ListeningPoint lp = sipProvider.getListeningPoint(transport); -// int myPort = lp.getPort(); -// + Response response = messageFactory.createResponse(Response.TRYING, + request); + ListeningPoint lp = sipProvider.getListeningPoint(transport); + int myPort = lp.getPort(); + Address address = addressFactory.createAddress("Shootme "); -// -// // Add a random sleep to stagger the two OK's for the benifit of implementations -// // that may not be too good about handling re-entrancy. -// int timeToSleep = (int) ( Math.random() * 1000); -// -// Thread.sleep(timeToSleep); -// -// st.sendResponse(response); + + // Add a random sleep to stagger the two OK's for the benifit of implementations + // that may not be too good about handling re-entrancy. + int timeToSleep = (int) ( Math.random() * 1000); + + Thread.sleep(timeToSleep); + + st.sendResponse(response); Response ringingResponse = messageFactory.createResponse(Response.RINGING, request); ContactHeader contactHeader = headerFactory.createContactHeader(address); - ringingResponse.addHeader(contactHeader); + response.addHeader(contactHeader); ToHeader toHeader = (ToHeader) ringingResponse.getHeader(ToHeader.NAME); - String toTag = "shootme-" + myPort + "-" + new Integer(new Random().nextInt()).toString(); + String toTag = new Integer(new Random().nextInt()).toString(); toHeader.setTag(toTag); if ( sendRinging ) { ringingResponse.addHeader(contactHeader); - Thread.sleep(this.ringingDelay / 2); st.sendResponse(ringingResponse); } Dialog dialog = st.getDialog(); @@ -205,7 +204,7 @@ public void processInvite(RequestEvent requestEvent, this.inviteSeen = true; - timer.schedule(new MyTimerTask(requestEvent,st,toTag), this.okDelay); + timer.schedule(new MyTimerTask(requestEvent,st,toTag), this.delay); } catch (Exception ex) { ex.printStackTrace(); System.exit(0); @@ -335,10 +334,9 @@ public SipProvider createProvider() { } - public Shootme( int myPort, boolean sendRinging, int ringingDelay, int okDelay ) { + public Shootme( int myPort, boolean sendRinging, int delay ) { this.myPort = myPort; - this.ringingDelay = ringingDelay; - this.okDelay = okDelay; + this.delay = delay; this.sendRinging = sendRinging; SipObjects sipObjects = new SipObjects(myPort, "shootme","on"); diff --git a/src/test/unit/gov/nist/javax/sip/stack/forkedinvite/SipObjects.java b/src/test/unit/gov/nist/javax/sip/stack/forkedinvite/SipObjects.java index f276638f3..aaa792b30 100644 --- a/src/test/unit/gov/nist/javax/sip/stack/forkedinvite/SipObjects.java +++ b/src/test/unit/gov/nist/javax/sip/stack/forkedinvite/SipObjects.java @@ -44,7 +44,7 @@ public SipObjects(int myPort, String stackName, String automaticDialog) { properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "32"); String logFile = "logs/" + stackname + ".txt"; - properties.setProperty("gov.nist.javax.sip.MAX_FORK_TIME_SECONDS", "12"); + properties.setProperty("gov.nist.javax.sip.MAX_FORK_TIME_SECONDS", "32"); properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", logFile); diff --git a/src/test/unit/gov/nist/javax/sip/stack/no491/ReInviteTCPPostParserThreadPoolTest.java b/src/test/unit/gov/nist/javax/sip/stack/no491/ReInviteTCPPostParserThreadPoolTest.java index ca05c1d43..515a944b1 100644 --- a/src/test/unit/gov/nist/javax/sip/stack/no491/ReInviteTCPPostParserThreadPoolTest.java +++ b/src/test/unit/gov/nist/javax/sip/stack/no491/ReInviteTCPPostParserThreadPoolTest.java @@ -101,22 +101,39 @@ public void testSendInvite() throws Exception { PipelinedMsgParser.setPostParseExcutorSize(threads, 10000); ((SipStackImpl)getRiProtocolObjects().sipStack).setTcpPostParsingThreadPoolSize(threads); ((SipStackImpl)getTiProtocolObjects().sipStack).setTcpPostParsingThreadPoolSize(threads); - getRiProtocolObjects().start(); - getTiProtocolObjects().start(); + getRiProtocolObjects().start(); + if (getTiProtocolObjects() != getRiProtocolObjects()) + getTiProtocolObjects().start(); this.shootist.sendInvite(); try { - Thread.sleep(20000); + Thread.sleep(15000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + public void testSendInvite1Thread() throws Exception { + int threads = 1; + PipelinedMsgParser.setPostParseExcutorSize(threads, 10000); + ((SipStackImpl)getRiProtocolObjects().sipStack).setTcpPostParsingThreadPoolSize(threads); + ((SipStackImpl)getTiProtocolObjects().sipStack).setTcpPostParsingThreadPoolSize(threads); + getRiProtocolObjects().start(); + if (getTiProtocolObjects() != getRiProtocolObjects()) + getTiProtocolObjects().start(); + + this.shootist.sendInvite(); + try { + Thread.sleep(15000); } catch (InterruptedException e) { e.printStackTrace(); } - this.shootist.checkState(); - this.shootme.checkState(); } public void tearDown() { try { - + this.shootist.checkState(); + this.shootme.checkState(); super.tearDown(); Thread.sleep(1000); this.providerTable.clear(); diff --git a/src/test/unit/gov/nist/javax/sip/stack/no491/Shootme.java b/src/test/unit/gov/nist/javax/sip/stack/no491/Shootme.java index 85eee21a3..53acf6498 100644 --- a/src/test/unit/gov/nist/javax/sip/stack/no491/Shootme.java +++ b/src/test/unit/gov/nist/javax/sip/stack/no491/Shootme.java @@ -283,7 +283,7 @@ public SipProvider createSipProvider() throws Exception { public static void main(String args[]) throws Exception { logger.addAppender( new ConsoleAppender(new SimpleLayout())); - ProtocolObjects protocolObjects = new ProtocolObjects("shootme", "gov.nist","udp",true,false, false); + ProtocolObjects protocolObjects = new ProtocolObjects("shootme", "gov.nist","udp",true,false); Shootme shootme = new Shootme(protocolObjects); shootme.createSipProvider().addSipListener(shootme); diff --git a/src/test/unit/gov/nist/javax/sip/stack/reInvite/ReInviteTest.java b/src/test/unit/gov/nist/javax/sip/stack/reInvite/ReInviteTest.java index c95284e02..f7368ab04 100644 --- a/src/test/unit/gov/nist/javax/sip/stack/reInvite/ReInviteTest.java +++ b/src/test/unit/gov/nist/javax/sip/stack/reInvite/ReInviteTest.java @@ -22,9 +22,13 @@ */ package test.unit.gov.nist.javax.sip.stack.reInvite; +import gov.nist.javax.sip.SipProviderImpl; import gov.nist.javax.sip.SipStackImpl; import java.util.EventObject; +import java.util.Hashtable; +import java.util.Timer; +import java.util.TimerTask; import javax.sip.DialogTerminatedEvent; import javax.sip.IOExceptionEvent; @@ -35,9 +39,19 @@ import javax.sip.TimeoutEvent; import javax.sip.TransactionTerminatedEvent; +import org.apache.log4j.Appender; +import org.apache.log4j.ConsoleAppender; +import org.apache.log4j.FileAppender; import org.apache.log4j.Logger; +import org.apache.log4j.PropertyConfigurator; +import org.apache.log4j.SimpleLayout; +import org.apache.log4j.helpers.NullEnumeration; +import test.tck.msgflow.callflows.ProtocolObjects; import test.tck.msgflow.callflows.ScenarioHarness; +import test.tck.TestHarness; + +import junit.framework.TestCase; /** * @author M. Ranganathan diff --git a/src/test/unit/gov/nist/javax/sip/stack/reInvite/Shootme.java b/src/test/unit/gov/nist/javax/sip/stack/reInvite/Shootme.java index a14e2fc9d..69796ad8a 100644 --- a/src/test/unit/gov/nist/javax/sip/stack/reInvite/Shootme.java +++ b/src/test/unit/gov/nist/javax/sip/stack/reInvite/Shootme.java @@ -242,7 +242,7 @@ public void processResponse(ResponseEvent responseReceivedEvent) { logger.info("Response received with client transaction id " + tid + ":\n" + response); - try { + try { if (response.getStatusCode() == Response.OK && ((CSeqHeader) response.getHeader(CSeqHeader.NAME)) .getMethod().equals(Request.INVITE)) { @@ -295,7 +295,7 @@ public SipProvider createSipProvider() throws Exception { public static void main(String args[]) throws Exception { logger.addAppender( new ConsoleAppender(new SimpleLayout())); - ProtocolObjects protocolObjects = new ProtocolObjects("shootme", "gov.nist","udp",true,false, false); + ProtocolObjects protocolObjects = new ProtocolObjects("shootme", "gov.nist","udp",true,false); Shootme shootme = new Shootme(protocolObjects); shootme.createSipProvider().addSipListener(shootme); diff --git a/src/test/unit/gov/nist/javax/sip/stack/reinvitechallenge/Shootme.java b/src/test/unit/gov/nist/javax/sip/stack/reinvitechallenge/Shootme.java index be668c61c..188bed78b 100644 --- a/src/test/unit/gov/nist/javax/sip/stack/reinvitechallenge/Shootme.java +++ b/src/test/unit/gov/nist/javax/sip/stack/reinvitechallenge/Shootme.java @@ -318,7 +318,7 @@ public SipProvider createSipProvider() throws Exception { public static void main(String args[]) throws Exception { logger.addAppender( new ConsoleAppender(new SimpleLayout())); - ProtocolObjects protocolObjects = new ProtocolObjects("shootme", "gov.nist","udp",true,false, false); + ProtocolObjects protocolObjects = new ProtocolObjects("shootme", "gov.nist","udp",true,false); Shootme shootme = new Shootme(protocolObjects); shootme.createSipProvider().addSipListener(shootme); diff --git a/src/test/unit/gov/nist/javax/sip/stack/stx491/Shootme.java b/src/test/unit/gov/nist/javax/sip/stack/stx491/Shootme.java index 7251fa0f6..a378f3ebc 100644 --- a/src/test/unit/gov/nist/javax/sip/stack/stx491/Shootme.java +++ b/src/test/unit/gov/nist/javax/sip/stack/stx491/Shootme.java @@ -276,7 +276,7 @@ public SipProvider createSipProvider() throws Exception { public static void main(String args[]) throws Exception { logger.addAppender( new ConsoleAppender(new SimpleLayout())); - ProtocolObjects protocolObjects = new ProtocolObjects("shootme", "gov.nist","udp",true,false, false); + ProtocolObjects protocolObjects = new ProtocolObjects("shootme", "gov.nist","udp",true,false); Shootme shootme = new Shootme(protocolObjects); shootme.createSipProvider().addSipListener(shootme); diff --git a/src/test/unit/gov/nist/javax/sip/stack/subsnotify/Notifier.java b/src/test/unit/gov/nist/javax/sip/stack/subsnotify/Notifier.java index bc0d478f8..89577814c 100755 --- a/src/test/unit/gov/nist/javax/sip/stack/subsnotify/Notifier.java +++ b/src/test/unit/gov/nist/javax/sip/stack/subsnotify/Notifier.java @@ -1,6 +1,5 @@ package test.unit.gov.nist.javax.sip.stack.subsnotify; -import gov.nist.javax.sip.ResponseEventExt; import gov.nist.javax.sip.message.ResponseExt; import javax.sip.*; @@ -10,8 +9,6 @@ import java.util.*; -import junit.framework.TestCase; - import org.apache.log4j.*; /** @@ -43,8 +40,6 @@ public class Notifier implements SipListener { protected int notifyCount = 0; - private boolean handleSubscribe = true; - @@ -84,113 +79,114 @@ public void processSubscribe(RequestEvent requestEvent, try { logger.info("notifier: " + request); logger.info("notifier : dialog = " + requestEvent.getDialog()); - if(handleSubscribe) { - EventHeader eventHeader = (EventHeader) request.getHeader(EventHeader.NAME); - if ( eventHeader == null) { - logger.info("Cannot find event header.... dropping request."); - return; - } - - // Always create a ServerTransaction, best as early as possible in the code - Response response = null; - ServerTransaction st = requestEvent.getServerTransaction(); - if (st == null) { - st = sipProvider.getNewServerTransaction(request); - } - - // Check if it is an initial SUBSCRIBE or a refresh / unsubscribe - toTag = Integer.toHexString( (int) (Math.random() * Integer.MAX_VALUE) ); - response = messageFactory.createResponse(202, request); - ToHeader toHeader = (ToHeader) response.getHeader(ToHeader.NAME); - toHeader.setTag(toTag); - // Sanity check: to header should not ahve a tag. Else the dialog - - - - - // Both 2xx response to SUBSCRIBE and NOTIFY need a Contact - Address address = addressFactory.createAddress("Notifier "); - ((SipURI)address.getURI()).setPort( udpProvider.getListeningPoint("udp").getPort() ); - ContactHeader contactHeader = headerFactory.createContactHeader(address); - response.addHeader(contactHeader); - - // Expires header is mandatory in 2xx responses to SUBSCRIBE - ExpiresHeader expires = (ExpiresHeader) request.getHeader( ExpiresHeader.NAME ); - if (expires==null) { - expires = headerFactory.createExpiresHeader(30);// rather short - } - response.addHeader( expires ); - - - /* - * NOTIFY requests MUST contain a "Subscription-State" header with a - * value of "active", "pending", or "terminated". The "active" value - * indicates that the subscription has been accepted and has been - * authorized (in most cases; see section 5.2.). The "pending" value - * indicates that the subscription has been received, but that - * policy information is insufficient to accept or deny the - * subscription at this time. The "terminated" value indicates that - * the subscription is not active. - */ - - Dialog dialog = sipProvider.getNewDialog(st); - - Address toAddress = ((ResponseExt)response).getFromHeader().getAddress(); - String toTag = ((ResponseExt)response).getFromHeader().getTag(); - Address fromAddress = ((ResponseExt) response).getToHeader().getAddress(); - String fromTag = ((ResponseExt) response).getToHeader().getTag(); - FromHeader fromHeader = headerFactory.createFromHeader(fromAddress, fromTag); - toHeader = headerFactory.createToHeader(toAddress, toTag); - // Create a new Cseq header - CSeqHeader cSeqHeader = headerFactory.createCSeqHeader(1L, - Request.NOTIFY); - ArrayList viaHeaders = new ArrayList(); - String transport = "udp"; - int port = sipProvider.getListeningPoint(transport).getPort(); - ViaHeader viaHeader = headerFactory.createViaHeader("127.0.0.1", - port, transport, null); - - // add via headers - viaHeaders.add(viaHeader); - - MaxForwardsHeader maxForwards = headerFactory.createMaxForwardsHeader(70); - SipURI requestURI = addressFactory.createSipURI(null, "127.0.0.1"); - requestURI.setPort(5060); - - CallIdHeader callIdHeader = ((ResponseExt)response).getCallIdHeader(); - - // Create the request. - Request notifyRequest = messageFactory.createRequest(requestURI, - Request.NOTIFY, callIdHeader, cSeqHeader, fromHeader, - toHeader, viaHeaders, maxForwards); + EventHeader eventHeader = (EventHeader) request.getHeader(EventHeader.NAME); + if ( eventHeader == null) { + logger.info("Cannot find event header.... dropping request."); + return; + } + + // Always create a ServerTransaction, best as early as possible in the code + Response response = null; + ServerTransaction st = requestEvent.getServerTransaction(); + if (st == null) { + st = sipProvider.getNewServerTransaction(request); + } + + // Check if it is an initial SUBSCRIBE or a refresh / unsubscribe + toTag = Integer.toHexString( (int) (Math.random() * Integer.MAX_VALUE) ); + response = messageFactory.createResponse(202, request); + ToHeader toHeader = (ToHeader) response.getHeader(ToHeader.NAME); + toHeader.setTag(toTag); + // Sanity check: to header should not ahve a tag. Else the dialog + + + + + // Both 2xx response to SUBSCRIBE and NOTIFY need a Contact + Address address = addressFactory.createAddress("Notifier "); + ((SipURI)address.getURI()).setPort( udpProvider.getListeningPoint("udp").getPort() ); + ContactHeader contactHeader = headerFactory.createContactHeader(address); + response.addHeader(contactHeader); + + // Expires header is mandatory in 2xx responses to SUBSCRIBE + ExpiresHeader expires = (ExpiresHeader) request.getHeader( ExpiresHeader.NAME ); + if (expires==null) { + expires = headerFactory.createExpiresHeader(30);// rather short + } + response.addHeader( expires ); + + + /* + * NOTIFY requests MUST contain a "Subscription-State" header with a + * value of "active", "pending", or "terminated". The "active" value + * indicates that the subscription has been accepted and has been + * authorized (in most cases; see section 5.2.). The "pending" value + * indicates that the subscription has been received, but that + * policy information is insufficient to accept or deny the + * subscription at this time. The "terminated" value indicates that + * the subscription is not active. + */ + + Dialog dialog = sipProvider.getNewDialog(st); + + Address toAddress = ((ResponseExt)response).getFromHeader().getAddress(); + String toTag = ((ResponseExt)response).getFromHeader().getTag(); + Address fromAddress = ((ResponseExt) response).getToHeader().getAddress(); + String fromTag = ((ResponseExt) response).getToHeader().getTag(); + FromHeader fromHeader = headerFactory.createFromHeader(fromAddress, fromTag); + toHeader = headerFactory.createToHeader(toAddress, toTag); + // Create a new Cseq header + CSeqHeader cSeqHeader = headerFactory.createCSeqHeader(1L, + Request.NOTIFY); + ArrayList viaHeaders = new ArrayList(); + String transport = "udp"; + int port = sipProvider.getListeningPoint(transport).getPort(); + ViaHeader viaHeader = headerFactory.createViaHeader("127.0.0.1", + port, transport, null); + + // add via headers + viaHeaders.add(viaHeader); + + MaxForwardsHeader maxForwards = headerFactory.createMaxForwardsHeader(70); + SipURI requestURI = addressFactory.createSipURI(null, "127.0.0.1"); + requestURI.setPort(5060); + + CallIdHeader callIdHeader = ((ResponseExt)response).getCallIdHeader(); + + // Create the request. + Request notifyRequest = messageFactory.createRequest(requestURI, + Request.NOTIFY, callIdHeader, cSeqHeader, fromHeader, + toHeader, viaHeaders, maxForwards); + + - - - // Mark the contact header, to check that the remote contact is updated - ((SipURI)contactHeader.getAddress().getURI()).setParameter("id","not"); - - // Initial state is pending, second time we assume terminated (Expires==0) - SubscriptionStateHeader sstate = headerFactory.createSubscriptionStateHeader( - SubscriptionStateHeader.PENDING ); - - // Need a reason for terminated - if ( sstate.getState().equalsIgnoreCase("terminated") ) { - sstate.setReasonCode( "deactivated" ); - } - - notifyRequest.addHeader(sstate); - notifyRequest.setHeader(eventHeader); - notifyRequest.setHeader(contactHeader); - // notifyRequest.setHeader(routeHeader); - ClientTransaction ct = udpProvider.getNewClientTransaction(notifyRequest); - - ct.sendRequest(); - logger.info("NOTIFY Branch ID " + - ((ViaHeader)request.getHeader(ViaHeader.NAME)).getParameter("branch")); - logger.info("notifier: got an Subscribe sending OK"); - - st.sendResponse(response); + // Mark the contact header, to check that the remote contact is updated + ((SipURI)contactHeader.getAddress().getURI()).setParameter("id","not"); + + // Initial state is pending, second time we assume terminated (Expires==0) + SubscriptionStateHeader sstate = headerFactory.createSubscriptionStateHeader( + SubscriptionStateHeader.PENDING ); + + // Need a reason for terminated + if ( sstate.getState().equalsIgnoreCase("terminated") ) { + sstate.setReasonCode( "deactivated" ); } + + notifyRequest.addHeader(sstate); + notifyRequest.setHeader(eventHeader); + notifyRequest.setHeader(contactHeader); + // notifyRequest.setHeader(routeHeader); + ClientTransaction ct = udpProvider.getNewClientTransaction(notifyRequest); + + ct.sendRequest(); + logger.info("NOTIFY Branch ID " + + ((ViaHeader)request.getHeader(ViaHeader.NAME)).getParameter("branch")); + logger.info("notifier: got an Subscribe sending OK"); + + st.sendResponse(response); + + + } catch (Throwable ex) { ex.printStackTrace(); // System.exit(0); @@ -201,12 +197,6 @@ public synchronized void processResponse(ResponseEvent responseReceivedEvent) { Response response = (Response) responseReceivedEvent.getResponse(); Transaction tid = responseReceivedEvent.getClientTransaction(); - if(tid == null) { - TestCase.assertTrue("retrans flag should be true", ((ResponseEventExt)responseReceivedEvent).isRetransmission()); - } else { - TestCase.assertFalse("retrans flag should be false", ((ResponseEventExt)responseReceivedEvent).isRetransmission()); - } - if ( response.getStatusCode() != 200 ) { this.notifyCount --; } else { @@ -329,8 +319,4 @@ public void tearDown() { } - public void setHandleSubscribe(boolean b) { - handleSubscribe = b; - } - } diff --git a/src/test/unit/gov/nist/javax/sip/stack/subsnotify/Subscriber.java b/src/test/unit/gov/nist/javax/sip/stack/subsnotify/Subscriber.java index fa97a01ef..9dea261e3 100755 --- a/src/test/unit/gov/nist/javax/sip/stack/subsnotify/Subscriber.java +++ b/src/test/unit/gov/nist/javax/sip/stack/subsnotify/Subscriber.java @@ -1,6 +1,5 @@ package test.unit.gov.nist.javax.sip.stack.subsnotify; -import gov.nist.javax.sip.ResponseEventExt; import gov.nist.javax.sip.stack.SIPTransactionStack; import javax.sip.*; @@ -155,11 +154,9 @@ public void processResponse(ResponseEvent responseReceivedEvent) { logger.info("Response received with client transaction id " + tid + ":\n" + response.getStatusCode() ); if (tid == null) { - TestCase.assertTrue("retrans flag should be true", ((ResponseEventExt)responseReceivedEvent).isRetransmission()); logger.info("Stray response -- dropping "); return; } - TestCase.assertFalse("retrans flag should be false", ((ResponseEventExt)responseReceivedEvent).isRetransmission()); logger.info("transaction state is " + tid.getState()); logger.info("Dialog = " + tid.getDialog()); if ( tid.getDialog () != null ) @@ -299,8 +296,6 @@ public static Subscriber createSubcriber() throws Exception { Properties properties = new Properties(); properties.setProperty("javax.sip.USE_ROUTER_FOR_ALL_URIS", "false"); - - properties.setProperty("gov.nist.javax.sip.AGGRESSIVE_CLEANUP", "true"); properties.setProperty("javax.sip.STACK_NAME", "subscriber"); properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", @@ -345,15 +340,6 @@ public void processDialogTerminated( public void processTimeout(javax.sip.TimeoutEvent timeoutEvent) { logger.info("Transaction Time out"); - logger.info("before sleep Transaction request " + timeoutEvent.getClientTransaction().getRequest()); - try { - Thread.sleep(10000); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - logger.info("After sleep Transaction request " + timeoutEvent.getClientTransaction().getRequest()); - } public void tearDown() { diff --git a/src/test/unit/gov/nist/javax/sip/stack/subsnotify/SubscriberTimeoutAggressiveTest.java b/src/test/unit/gov/nist/javax/sip/stack/subsnotify/SubscriberTimeoutAggressiveTest.java deleted file mode 100644 index 3e34d2c36..000000000 --- a/src/test/unit/gov/nist/javax/sip/stack/subsnotify/SubscriberTimeoutAggressiveTest.java +++ /dev/null @@ -1,28 +0,0 @@ -package test.unit.gov.nist.javax.sip.stack.subsnotify; - -import junit.framework.TestCase; - -public class SubscriberTimeoutAggressiveTest extends TestCase { - Subscriber subscriber; - Notifier notifier; - - - public void setUp() throws Exception { - subscriber = Subscriber.createSubcriber(); - notifier = Notifier.createNotifier(); - } - - - public void testSendSubscribe() { - notifier.setHandleSubscribe(false); - subscriber.sendSubscribe(); - - } - - public void tearDown() throws Exception { - Thread.sleep(50000); - subscriber.tearDown(); - notifier.tearDown(); - } - -} diff --git a/src/test/unit/gov/nist/javax/sip/stack/uasreinvite/Shootme.java b/src/test/unit/gov/nist/javax/sip/stack/uasreinvite/Shootme.java index 050f94111..781677b3b 100644 --- a/src/test/unit/gov/nist/javax/sip/stack/uasreinvite/Shootme.java +++ b/src/test/unit/gov/nist/javax/sip/stack/uasreinvite/Shootme.java @@ -294,7 +294,7 @@ public SipProvider createSipProvider() throws Exception { public static void main(String args[]) throws Exception { logger.addAppender( new ConsoleAppender(new SimpleLayout())); - ProtocolObjects protocolObjects = new ProtocolObjects("shootme", "gov.nist","udp",true,false, false); + ProtocolObjects protocolObjects = new ProtocolObjects("shootme", "gov.nist","udp",true,false); Shootme shootme = new Shootme(protocolObjects); shootme.createSipProvider().addSipListener(shootme); diff --git a/src/tools/sniffer/SniffMessage.java b/src/tools/sniffer/SniffMessage.java index f496625eb..449235842 100755 --- a/src/tools/sniffer/SniffMessage.java +++ b/src/tools/sniffer/SniffMessage.java @@ -140,7 +140,8 @@ private void getSipMessage(ArrayList sniffMsgList) throws ParseException { //parse SIP message StringMsgParser parser = new StringMsgParser(); - sipMessage = parser.parseSIPMessage(msgBuffer.getBytes(), true, false, new SniffMessage()); + parser.setParseExceptionListener(new SniffMessage()); + sipMessage = parser.parseSIPMessage(msgBuffer); } public String getCallID() { diff --git a/version.txt b/version.txt new file mode 100644 index 000000000..4b9bce482 --- /dev/null +++ b/version.txt @@ -0,0 +1 @@ +148 \ No newline at end of file diff --git a/www/index.html b/www/index.html index 098b7ad80..f85d31f63 100644 --- a/www/index.html +++ b/www/index.html @@ -49,6 +49,7 @@

    Artifacts and Downloads

    • CVS address is dev.java.net
    • CVS Path is /cvs +
    • Module name is jain-sip
    • CVS login and passsword is the same as your java.net login
    • Or if you prefer the command line:
      @@ -58,11 +59,11 @@ 

      Artifacts and Downloads

+ -

This project includes an extensive test suite that is run when ever a change is made to the CVS repository. Visit the download link above to see the tests run by cruise control for each commit. JAIN-SIP has been leak tested under both error conditions and error @@ -70,6 +71,15 @@

Performance and Stability

testing (Pascal Maugeri: "Genaker VoIP API using JAIN-SIP v1.2.85"):
  • See Stability testing results. +

    The stack performance measures in at 476 CAPS on a P5 dual core, +3.2 GHZ using TCP for transport. Using P4 3.2 GHZ single core with +hyperthreading and 2GB of RAM, a thruput of 267 CAPS has been reported. +On a dual core 3.4 Mhz P5 with 1 Gig RAM a thruput of 476 CAPS has been +reported. Using UDP for transport, on a P4 single core, 2 GHZ machine +with 1 Gb of RAM and with no hyperthreading a a performance of 82 CAPS +was observed. Using TCP for the same scenario, we measure in at 200 +CAPS. Load tests were performed using test in test/load/concurrency. No +memory leaks were seen after 1000000 calls.