Android.bp0100644 0000000 0000000 00000001517 13513104763 011517 0ustar000000000 0000000 // Copyright (C) 2017 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. java_library_static { name: "nist-sip", srcs: ["java/**/*.java"], no_framework_libs: true, errorprone: { javacflags: [ "-Xep:MissingOverride:OFF", // Ignore missing @Override. ], }, } AndroidManifest.xml0100644 0000000 0000000 00000010661 13513104763 013405 0ustar000000000 0000000 CleanSpec.mk0100644 0000000 0000000 00000004263 13513104763 012003 0ustar000000000 0000000 # Copyright (C) 2007 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # If you don't need to do a full clean build but would like to touch # a file or delete some intermediate files, add a clean step to the end # of the list. These steps will only be run once, if they haven't been # run before. # # E.g.: # $(call add-clean-step, touch -c external/sqlite/sqlite3.h) # $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates) # # Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with # files that are missing or have been moved. # # Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory. # Use $(OUT_DIR) to refer to the "out" directory. # # If you need to re-do something that's already mentioned, just copy # the command and add it to the bottom of the list. E.g., if a change # that you made last week required touching a file and a change you # made today requires touching the same file, just copy the old # touch step and add it to the end of the list. # # ************************************************ # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST # ************************************************ # For example: #$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates) #$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates) #$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f) #$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*) # ************************************************ # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST # ************************************************ MODULE_LICENSE_PUBLIC_DOMAIN0100644 0000000 0000000 00000000000 13513104763 013735 0ustar000000000 0000000 NIST-CONDITIONS-OF-USE.txt0100644 0000000 0000000 00000002256 13513104763 013536 0ustar000000000 0000000 /* *********************************************************************** * The following applies to the packages "gov.nist", "test" and * "tools" and all subpackages thereof *********************************************************************** * * Conditions Of Use * * This software was developed by employees of the National Institute of * Standards and Technology (NIST), and others. * This software has been contributed to the public domain. * 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 this software. * * This software is 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 * this software. * * */ NOTICE0100644 0000000 0000000 00000002256 13513104763 010521 0ustar000000000 0000000 /* *********************************************************************** * The following applies to the packages "gov.nist", "test" and * "tools" and all subpackages thereof *********************************************************************** * * Conditions Of Use * * This software was developed by employees of the National Institute of * Standards and Technology (NIST), and others. * This software has been contributed to the public domain. * 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 this software. * * This software is 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 * this software. * * */ TIMESTAMP0100644 0000000 0000000 00000000004 13513104763 011070 0ustar000000000 0000000 140 java/0040755 0000000 0000000 00000000000 13513104763 010534 5ustar000000000 0000000 java/gov/0040755 0000000 0000000 00000000000 13513104763 011327 5ustar000000000 0000000 java/gov/nist/0040755 0000000 0000000 00000000000 13513104763 012304 5ustar000000000 0000000 java/gov/nist/core/0040755 0000000 0000000 00000000000 13513104763 013234 5ustar000000000 0000000 java/gov/nist/core/Debug.java0100644 0000000 0000000 00000004166 13513104763 015131 0ustar000000000 0000000 /* * 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; /** * A class to do debug printfs */ public class Debug { public static boolean debug = false; public static boolean parserDebug = false; static StackLogger stackLogger; public static void setStackLogger(StackLogger stackLogger) { Debug.stackLogger = stackLogger; } public static void println(String s) { if ((parserDebug || debug )&& stackLogger != null ) stackLogger.logDebug(s + "\n"); } public static void printStackTrace(Exception ex) { if ((parserDebug || debug ) && stackLogger != null) { stackLogger.logError("Stack Trace",ex); } } public static void logError(String message, Exception ex) { if ((parserDebug || debug) && stackLogger != null ) { stackLogger.logError(message,ex); } } } java/gov/nist/core/DuplicateNameValueList.java0100644 0000000 0000000 00000016335 13513104763 020450 0ustar000000000 0000000 /* * 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.core; import java.io.Serializable; import java.util.Collection; import java.util.Iterator; import java.util.Map; import java.util.Set; /** * * * This is a Duplicate Name Value List that will allow multiple values map to the same key. * * The parsing and encoding logic for it is the same as that of NameValueList. Only the HashMap * container is different. * * @author aayush.bhatnagar * @since 2.0 * */ 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. * * @return an encoded string containing the objects in this list. * @since v1.0 */ public String encode() { return encode(new StringBuffer()).toString(); } public StringBuffer encode(StringBuffer buffer) { if (!nameValueMap.isEmpty()) { Iterator iterator = nameValueMap.values().iterator(); if (iterator.hasNext()) { while (true) { Object obj = iterator.next(); if (obj instanceof GenericObject) { GenericObject gobj = (GenericObject) obj; gobj.encode(buffer); } else { buffer.append(obj.toString()); } if (iterator.hasNext()) buffer.append(separator); else break; } } } return buffer; } public String toString() { return this.encode(); } /** * Set a namevalue object in this list. */ public void set(NameValue nv) { this.nameValueMap.put(nv.getName().toLowerCase(), nv); } /** * Set a namevalue object in this list. */ public void set(String name, Object value) { NameValue nameValue = new NameValue(name, value); nameValueMap.put(name.toLowerCase(), nameValue); } /** * Compare if two NameValue lists are equal. * * @param otherObject is the object to compare to. * @return true if the two objects compare for equality. */ public boolean equals(Object otherObject) { if ( otherObject == null ) { return false; } if (!otherObject.getClass().equals(this.getClass())) { return false; } DuplicateNameValueList other = (DuplicateNameValueList) otherObject; if (nameValueMap.size() != other.nameValueMap.size()) { return false; } Iterator li = this.nameValueMap.keySet().iterator(); while (li.hasNext()) { String key = (String) li.next(); Collection nv1 = this.getNameValue(key); Collection nv2 = (Collection) other.nameValueMap.get(key); if (nv2 == null) return false; else if (!nv2.equals(nv1)) return false; } return true; } /** * Do a lookup on a given name and return value associated with it. */ public Object getValue(String name) { Collection nv = this.getNameValue(name.toLowerCase()); if (nv != null) return nv; else return null; } /** * Get the NameValue record given a name. * */ public Collection getNameValue(String name) { return (Collection) this.nameValueMap.get(name.toLowerCase()); } /** * Returns a boolean telling if this NameValueList has a record with this name */ public boolean hasNameValue(String name) { return nameValueMap.containsKey(name.toLowerCase()); } /** * Remove the element corresponding to this name. */ public boolean delete(String name) { String lcName = name.toLowerCase(); if (this.nameValueMap.containsKey(lcName)) { this.nameValueMap.remove(lcName); return true; } else { return false; } } public Object clone() { DuplicateNameValueList retval = new DuplicateNameValueList(); retval.setSeparator(this.separator); Iterator it = this.nameValueMap.values().iterator(); while (it.hasNext()) { retval.set((NameValue) ((NameValue) it.next()).clone()); } return retval; } /** * Return an iterator for the name-value pairs of this list. * * @return the iterator. */ public Iterator iterator() { return this.nameValueMap.values().iterator(); } /** * Get a list of parameter names. * * @return a list iterator that has the names of the parameters. */ public Iterator getNames() { return this.nameValueMap.keySet().iterator(); } /** * Get the parameter as a String. * * @return the parameter as a string. */ public String getParameter(String name) { Object val = this.getValue(name); if (val == null) return null; if (val instanceof GenericObject) return ((GenericObject) val).encode(); else return val.toString(); } public void clear() { nameValueMap.clear(); } public boolean isEmpty() { return this.nameValueMap.isEmpty(); } public NameValue put(String key, NameValue value) { return (NameValue) this.nameValueMap.put(key, value); } public NameValue remove(Object key) { return (NameValue) this.nameValueMap.remove(key); } public int size() { return this.nameValueMap.size(); } public Collection values() { return this.nameValueMap.values(); } public int hashCode() { return this.nameValueMap.keySet().hashCode(); } } java/gov/nist/core/GenericObject.java0100644 0000000 0000000 00000067077 13513104763 016620 0ustar000000000 0000000 /* * 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.lang.reflect.*; import java.io.Serializable; import java.util.*; /** * The base class from which all the other classes in the * sipheader, sdpfields and sipmessage packages are extended. * Provides a few utility funcitons such as indentation and * pretty printing that all other classes benifit from. * *@version 1.2 * *@author M. Ranganathan
* * * */ public abstract class GenericObject implements Serializable, Cloneable { // Useful constants. protected static final String SEMICOLON = Separators.SEMICOLON; protected static final String COLON = Separators.COLON; protected static final String COMMA = Separators.COMMA; protected static final String SLASH = Separators.SLASH; protected static final String SP = Separators.SP; protected static final String EQUALS = Separators.EQUALS; protected static final String STAR = Separators.STAR; protected static final String NEWLINE = Separators.NEWLINE; protected static final String RETURN = Separators.RETURN; protected static final String LESS_THAN = Separators.LESS_THAN; protected static final String GREATER_THAN = Separators.GREATER_THAN; protected static final String AT = Separators.AT; protected static final String DOT = Separators.DOT; protected static final String QUESTION = Separators.QUESTION; protected static final String POUND = Separators.POUND; protected static final String AND = Separators.AND; protected static final String LPAREN = Separators.LPAREN; protected static final String RPAREN = Separators.RPAREN; protected static final String DOUBLE_QUOTE = Separators.DOUBLE_QUOTE; protected static final String QUOTE = Separators.QUOTE; protected static final String HT = Separators.HT; protected static final String PERCENT = Separators.PERCENT; protected static final Set> immutableClasses = new HashSet> (10); static final String[] immutableClassNames ={ "String", "Character", "Boolean", "Byte", "Short", "Integer", "Long", "Float", "Double" }; protected int indentation; protected String stringRepresentation; protected Match matchExpression; // Pattern matcher. static { try { for (int i = 0; i < immutableClassNames.length; i++) immutableClasses.add(Class.forName("java.lang." + immutableClassNames [i])); } catch (ClassNotFoundException e) { throw new RuntimeException ("Internal error", e); } } /** Set the pattern matcher. To match on the * field of a sip message, set the match expression in the match template * and invoke the match function. This useful because * SIP headers and parameters may appear in different orders and are not * necessarily in canonical form. This makes it hard to write a pattern * matcher that relies on regular expressions alone. * Thus we rely on the following strategy i.e. To do pattern matching on * an incoming message, first parse it, and then construct a match template, * filling in the fields that you want to * match. The rules for matching are: A null object matches wild card - * that is a match template of null matches any parsed SIP object. * To match with any subfield, set the match template on a template object * of the same type and invoke the match interface. * Regular expressions matching implements the gov.nist.sip.Match interface * that can be done using the Jakarta regexp package for example. * package included herein. This can be used to implement the Match interface * See the APACHE website for documents * */ public void setMatcher(Match matchExpression) { if (matchExpression == null) throw new IllegalArgumentException("null arg!"); this.matchExpression = matchExpression; } /** Return the match expression. *@return the match expression that has previously been set. */ public Match getMatcher() { return matchExpression; } public static Class getClassFromName(String className) { try { return Class.forName(className); } catch (Exception ex) { InternalErrorHandler.handleException(ex); return null; } } public static boolean isMySubclass(Class other) { return GenericObject.class.isAssignableFrom(other); } /** Clones the given object. * If the object is a wrapped type, an array, a GenericObject * or a GenericObjectList, it is cast to the appropriate type * and the clone() method is invoked. Else if the object implements * Cloneable, reflection is used to discover and invoke * clone() method. Otherwise, the original object is returned. */ public static Object makeClone(Object obj) { if (obj == null) throw new NullPointerException("null obj!"); Class c = obj.getClass(); Object clone_obj = obj; if (immutableClasses.contains (c)) return obj; else if (c.isArray ()) { Class ec = c.getComponentType(); if (! ec.isPrimitive()) clone_obj = ((Object []) obj).clone(); else { if (ec == Character.TYPE) clone_obj = ((char []) obj).clone(); else if (ec == Boolean.TYPE) clone_obj = ((boolean []) obj).clone(); if (ec == Byte.TYPE) clone_obj = ((byte []) obj).clone(); else if (ec == Short.TYPE) clone_obj = ((short []) obj).clone(); else if (ec == Integer.TYPE) clone_obj = ((int []) obj).clone(); else if (ec == Long.TYPE) clone_obj = ((long []) obj).clone(); else if (ec == Float.TYPE) clone_obj = ((float []) obj).clone(); else if (ec == Double.TYPE) clone_obj = ((double []) obj).clone(); } } else if (GenericObject.class.isAssignableFrom (c)) clone_obj = ((GenericObject) obj).clone(); else if (GenericObjectList.class.isAssignableFrom (c)) clone_obj = ((GenericObjectList) obj).clone(); else if (Cloneable.class.isAssignableFrom (c)) { // If a clone method exists for the object, then // invoke it try { Method meth = c.getMethod("clone", (Class[]) null); clone_obj = meth.invoke(obj,(Object[]) null); } catch (SecurityException ex) { } catch (IllegalArgumentException ex) { InternalErrorHandler.handleException(ex); } catch (IllegalAccessException ex) { } catch (InvocationTargetException ex) { } catch (NoSuchMethodException ex) { } } return clone_obj; } /** Clones this object. */ public Object clone() { try { return super.clone(); } catch (CloneNotSupportedException e) { throw new RuntimeException("Internal error"); } } /** * Recursively override the fields of this object with the fields * of a new object. This is useful when you want to genrate a template * and override the fields of an incoming SIPMessage with another * SIP message that you have already generated. * * @param mergeObject is the replacement object. The override * obect must be of the same class as this object. * Set any fields that you do not want to override as null in the * mergeOject object. */ public void merge(Object mergeObject) { // Base case. if (mergeObject == null) return; if (!mergeObject.getClass().equals(this.getClass())) throw new IllegalArgumentException("Bad override object"); Class myclass = this.getClass(); while (true) { Field[] fields = myclass.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { Field f = fields[i]; int modifier = f.getModifiers(); if (Modifier.isPrivate(modifier)) { continue; } else if (Modifier.isStatic(modifier)) { continue; } else if (Modifier.isInterface(modifier)) { continue; } Class fieldType = f.getType(); String fname = fieldType.toString(); try { // Primitive fields are printed with type: value if (fieldType.isPrimitive()) { if (fname.compareTo("int") == 0) { int intfield = f.getInt(mergeObject); f.setInt(this, intfield); } else if (fname.compareTo("short") == 0) { short shortField = f.getShort(mergeObject); f.setShort(this, shortField); } else if (fname.compareTo("char") == 0) { char charField = f.getChar(mergeObject); f.setChar(this, charField); } else if (fname.compareTo("long") == 0) { long longField = f.getLong(mergeObject); f.setLong(this, longField); } else if (fname.compareTo("boolean") == 0) { boolean booleanField = f.getBoolean(mergeObject); f.setBoolean(this, booleanField); } else if (fname.compareTo("double") == 0) { double doubleField = f.getDouble(mergeObject); f.setDouble(this, doubleField); } else if (fname.compareTo("float") == 0) { float floatField = f.getFloat(mergeObject); f.setFloat(this, floatField); } } else { Object obj = f.get(this); Object mobj = f.get(mergeObject); if (mobj == null) continue; if (obj == null) { f.set(this, mobj); continue; } if (obj instanceof GenericObject) { GenericObject gobj = (GenericObject) obj; gobj.merge(mobj); } else { f.set(this, mobj); } } } catch (IllegalAccessException ex1) { ex1.printStackTrace(); continue; // we are accessing a private field... } } myclass = myclass.getSuperclass(); if (myclass.equals(GenericObject.class)) break; } } protected GenericObject() { indentation = 0; stringRepresentation = ""; } protected String getIndentation() { char [] chars = new char [indentation]; java.util.Arrays.fill (chars, ' '); return new String (chars); } /** * Add a new string to the accumulated string representation. */ protected void sprint(String a) { if (a == null) { stringRepresentation += getIndentation(); stringRepresentation += "\n"; return; } if (a.compareTo("}") == 0 || a.compareTo("]") == 0) { indentation--; } stringRepresentation += getIndentation(); stringRepresentation += a; stringRepresentation += "\n"; if (a.compareTo("{") == 0 || a.compareTo("[") == 0) { indentation++; } } /** * Pretty printing function accumulator for objects. */ protected void sprint(Object o) { sprint(o.toString()); } /** * Pretty printing accumulator function for ints */ protected void sprint(int intField) { sprint(String.valueOf(intField)); } /** * Pretty printing accumulator function for shorts */ protected void sprint(short shortField) { sprint(String.valueOf(shortField)); } /** * Pretty printing accumulator function for chars */ protected void sprint(char charField) { sprint(String.valueOf(charField)); } /** * Pretty printing accumulator function for longs */ protected void sprint(long longField) { sprint(String.valueOf(longField)); } /** * Pretty printing accumulator function for booleans */ protected void sprint(boolean booleanField) { sprint(String.valueOf(booleanField)); } /** * Pretty printing accumulator function for doubles */ protected void sprint(double doubleField) { sprint(String.valueOf(doubleField)); } /** * Pretty printing accumulator function for floats */ protected void sprint(float floatField) { sprint(String.valueOf(floatField)); } /** * Debug printing function. */ protected void dbgPrint() { Debug.println(debugDump()); } /** * Debug printing function. */ protected void dbgPrint(String s) { Debug.println(s); } /** * An introspection based equality predicate for GenericObjects. *@param that is the other object to test against. *@return true if the objects are euqal and false otherwise */ public boolean equals(Object that) { if ( that == null ) return false; if (!this.getClass().equals(that.getClass())) return false; Class myclass = this.getClass(); Class hisclass = that.getClass(); while (true) { Field[] fields = myclass.getDeclaredFields(); Field[] hisfields = hisclass.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { Field f = fields[i]; Field g = hisfields[i]; // Only print protected and public members. int modifier = f.getModifiers(); if ((modifier & Modifier.PRIVATE) == Modifier.PRIVATE) continue; Class fieldType = f.getType(); String fieldName = f.getName(); if (fieldName.compareTo("stringRepresentation") == 0) { continue; } if (fieldName.compareTo("indentation") == 0) { continue; } try { // Primitive fields are printed with type: value if (fieldType.isPrimitive()) { String fname = fieldType.toString(); if (fname.compareTo("int") == 0) { if (f.getInt(this) != g.getInt(that)) return false; } else if (fname.compareTo("short") == 0) { if (f.getShort(this) != g.getShort(that)) return false; } else if (fname.compareTo("char") == 0) { if (f.getChar(this) != g.getChar(that)) return false; } else if (fname.compareTo("long") == 0) { if (f.getLong(this) != g.getLong(that)) return false; } else if (fname.compareTo("boolean") == 0) { if (f.getBoolean(this) != g.getBoolean(that)) return false; } else if (fname.compareTo("double") == 0) { if (f.getDouble(this) != g.getDouble(that)) return false; } else if (fname.compareTo("float") == 0) { if (f.getFloat(this) != g.getFloat(that)) return false; } } else if (g.get(that) == f.get(this)) return true; else if (f.get(this) == null) return false; else if (g.get(that) == null) return false; else if (g.get(that) == null && f.get(this) != null) return false; else if (!f.get(this).equals(g.get(that))) return false; } catch (IllegalAccessException ex1) { InternalErrorHandler.handleException(ex1); } } if (myclass.equals(GenericObject.class)) break; else { myclass = myclass.getSuperclass(); hisclass = hisclass.getSuperclass(); } } return true; } /** An introspection based predicate matching using a template * object. Allows for partial match of two protocl Objects. *@param other the match pattern to test against. The match object * has to be of the same type (class). Primitive types * and non-sip fields that are non null are matched for equality. * Null in any field matches anything. Some book-keeping fields * are ignored when making the comparison. */ public boolean match(Object other) { if (other == null) return true; if (!this.getClass().equals(other.getClass())) return false; GenericObject that = (GenericObject) other; Class myclass = this.getClass(); Field[] fields = myclass.getDeclaredFields(); Class hisclass = other.getClass(); Field[] hisfields = hisclass.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { Field f = fields[i]; Field g = hisfields[i]; // Only print protected and public members. int modifier = f.getModifiers(); if ((modifier & Modifier.PRIVATE) == Modifier.PRIVATE) continue; Class fieldType = f.getType(); String fieldName = f.getName(); if (fieldName.compareTo("stringRepresentation") == 0) { continue; } if (fieldName.compareTo("indentation") == 0) { continue; } try { // Primitive fields are printed with type: value if (fieldType.isPrimitive()) { String fname = fieldType.toString(); if (fname.compareTo("int") == 0) { if (f.getInt(this) != g.getInt(that)) return false; } else if (fname.compareTo("short") == 0) { if (f.getShort(this) != g.getShort(that)) return false; } else if (fname.compareTo("char") == 0) { if (f.getChar(this) != g.getChar(that)) return false; } else if (fname.compareTo("long") == 0) { if (f.getLong(this) != g.getLong(that)) return false; } else if (fname.compareTo("boolean") == 0) { if (f.getBoolean(this) != g.getBoolean(that)) return false; } else if (fname.compareTo("double") == 0) { if (f.getDouble(this) != g.getDouble(that)) return false; } else if (fname.compareTo("float") == 0) { if (f.getFloat(this) != g.getFloat(that)) return false; } } else { Object myObj = f.get(this); Object hisObj = g.get(that); if (hisObj != null && myObj == null) return false; else if (hisObj == null && myObj != null) continue; else if (hisObj == null && myObj == null) continue; else if ( hisObj instanceof java.lang.String && myObj instanceof java.lang.String) { if ((((String) hisObj).trim()).equals("")) continue; if (((String) myObj) .compareToIgnoreCase((String) hisObj) != 0) return false; } else if ( GenericObject.isMySubclass(myObj.getClass()) && !((GenericObject) myObj).match(hisObj)) return false; else if ( GenericObjectList.isMySubclass(myObj.getClass()) && !((GenericObjectList) myObj).match(hisObj)) return false; } } catch (IllegalAccessException ex1) { InternalErrorHandler.handleException(ex1); } } return true; } /** * Generic print formatting function: * Does depth-first descent of the structure and * recursively prints all non-private objects pointed to * by this object. * * Warning - the following generic string routine will * bomb (go into infinite loop) if there are any circularly linked * structures so if you have these, they had better be private! * * We dont have to worry about such things for our structures *(we never use circular linked structures). */ public String debugDump() { stringRepresentation = ""; Class myclass = getClass(); sprint(myclass.getName()); sprint("{"); Field[] fields = myclass.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { Field f = fields[i]; // Only print protected and public members. int modifier = f.getModifiers(); if ((modifier & Modifier.PRIVATE) == Modifier.PRIVATE) continue; Class fieldType = f.getType(); String fieldName = f.getName(); if (fieldName.compareTo("stringRepresentation") == 0) { // avoid nasty recursions... continue; } if (fieldName.compareTo("indentation") == 0) { // formatting stuff - not relevant here. continue; } sprint(fieldName + ":"); try { // Primitive fields are printed with type: value if (fieldType.isPrimitive()) { String fname = fieldType.toString(); sprint(fname + ":"); if (fname.compareTo("int") == 0) { int intfield = f.getInt(this); sprint(intfield); } else if (fname.compareTo("short") == 0) { short shortField = f.getShort(this); sprint(shortField); } else if (fname.compareTo("char") == 0) { char charField = f.getChar(this); sprint(charField); } else if (fname.compareTo("long") == 0) { long longField = f.getLong(this); sprint(longField); } else if (fname.compareTo("boolean") == 0) { boolean booleanField = f.getBoolean(this); sprint(booleanField); } else if (fname.compareTo("double") == 0) { double doubleField = f.getDouble(this); sprint(doubleField); } else if (fname.compareTo("float") == 0) { float floatField = f.getFloat(this); sprint(floatField); } } else if (GenericObject.class.isAssignableFrom(fieldType)) { if (f.get(this) != null) { sprint( ((GenericObject) f.get(this)).debugDump( indentation + 1)); } else { sprint(""); } } else if ( GenericObjectList.class.isAssignableFrom(fieldType)) { if (f.get(this) != null) { sprint( ((GenericObjectList) f.get(this)).debugDump( indentation + 1)); } else { sprint(""); } } else { // Dont do recursion on things that are not // of our header type... if (f.get(this) != null) { sprint(f.get(this).getClass().getName() + ":"); } else { sprint(fieldType.getName() + ":"); } sprint("{"); if (f.get(this) != null) { sprint(f.get(this).toString()); } else { sprint(""); } sprint("}"); } } catch (IllegalAccessException ex1) { continue; // we are accessing a private field... } catch (Exception ex) { InternalErrorHandler.handleException(ex); } } sprint("}"); return stringRepresentation; } /** * Formatter with a given starting indentation. */ public String debugDump(int indent) { indentation = indent; String retval = this.debugDump(); indentation = 0; return retval; } /** * Get the string encoded version of this object * @since v1.0 */ public abstract String encode(); /** * Put the encoded version of this object in the given StringBuffer. */ public StringBuffer encode(StringBuffer buffer) { return buffer.append(encode()); } } java/gov/nist/core/GenericObjectList.java0100644 0000000 0000000 00000033761 13513104763 017445 0ustar000000000 0000000 /* * 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.util.*; import java.io.Serializable; /** * Implements a homogenous consistent linked list. All the objects in the linked * list must derive from the same root class. This is a useful constraint to * place on our code as this property is invariant.The list is created with the * superclass which can be specified as either a class name or a Class. * * @version 1.2 * * @author M. Ranganathan
* * * */ public abstract class GenericObjectList extends LinkedList implements Serializable, Cloneable{ // Useful constants. protected static final String SEMICOLON = Separators.SEMICOLON; protected static final String COLON = Separators.COLON; protected static final String COMMA = Separators.COMMA; protected static final String SLASH = Separators.SLASH; protected static final String SP = Separators.SP; protected static final String EQUALS = Separators.EQUALS; protected static final String STAR = Separators.STAR; protected static final String NEWLINE = Separators.NEWLINE; protected static final String RETURN = Separators.RETURN; protected static final String LESS_THAN = Separators.LESS_THAN; protected static final String GREATER_THAN = Separators.GREATER_THAN; protected static final String AT = Separators.AT; protected static final String DOT = Separators.DOT; protected static final String QUESTION = Separators.QUESTION; protected static final String POUND = Separators.POUND; protected static final String AND = Separators.AND; protected static final String LPAREN = Separators.LPAREN; protected static final String RPAREN = Separators.RPAREN; protected static final String DOUBLE_QUOTE = Separators.DOUBLE_QUOTE; protected static final String QUOTE = Separators.QUOTE; protected static final String HT = Separators.HT; protected static final String PERCENT = Separators.PERCENT; protected int indentation; protected String listName; // For debugging private ListIterator myListIterator; private String stringRep; protected Class myClass; protected String separator; protected String getIndentation() { char[] chars = new char[indentation]; java.util.Arrays.fill(chars, ' '); return new String(chars); } /** * Return true if this supports reflection based cloning. */ protected static boolean isCloneable(Object obj) { return obj instanceof Cloneable; } public static boolean isMySubclass(Class other) { return GenericObjectList.class.isAssignableFrom(other); } /** * Makes a deep clone of this list. */ public Object clone() { GenericObjectList retval = (GenericObjectList) super.clone(); for (ListIterator iter = retval.listIterator(); iter.hasNext();) { GenericObject obj = (GenericObject) ((GenericObject) iter.next()) .clone(); iter.set(obj); } return retval; } public void setMyClass(Class cl) { myClass = cl; } protected GenericObjectList() { super(); listName = null; stringRep = ""; separator = ";"; } protected GenericObjectList(String lname) { this(); listName = lname; } /** * A Constructor which takes a list name and a class name (for assertion * checking). */ protected GenericObjectList(String lname, String classname) { this(lname); try { myClass = Class.forName(classname); } catch (ClassNotFoundException ex) { InternalErrorHandler.handleException(ex); } } /** * A Constructor which takes a list name and a class (for assertion * checking). */ protected GenericObjectList(String lname, Class objclass) { this(lname); myClass = objclass; } /** * Traverse the list given a list iterator */ protected GenericObject next(ListIterator iterator) { try { return (GenericObject) iterator.next(); } catch (NoSuchElementException ex) { return null; } } /** * This is the default list iterator.This will not handle nested list * traversal. */ protected GenericObject first() { myListIterator = this.listIterator(0); try { return (GenericObject) myListIterator.next(); } catch (NoSuchElementException ex) { return null; } } /** * Fetch the next object from the list based on the default list iterator */ protected GenericObject next() { if (myListIterator == null) { myListIterator = this.listIterator(0); } try { return (GenericObject) myListIterator.next(); } catch (NoSuchElementException ex) { myListIterator = null; return null; } } /** * Concatenate two compatible header lists, adding the argument to the tail * end of this list. * * @param * topFlag set to true to add items to top of list */ protected void concatenate(GenericObjectList objList) { concatenate(objList, false); } /** * Concatenate two compatible header lists, adding the argument either to * the beginning or the tail end of this list. A type check is done before * concatenation. * * @param * topFlag set to true to add items to top of list else * add them to the tail end of the list. */ protected void concatenate(GenericObjectList objList, boolean topFlag) { if (!topFlag) { this.addAll(objList); } else { // add given items to the top end of the list. this.addAll(0, objList); } } /** * string formatting function. */ private void sprint(String s) { if (s == null) { stringRep += getIndentation(); stringRep += "\n"; return; } if (s.compareTo("}") == 0 || s.compareTo("]") == 0) { indentation--; } stringRep += getIndentation(); stringRep += s; stringRep += "\n"; if (s.compareTo("{") == 0 || s.compareTo("[") == 0) { indentation++; } } /** * Convert this list of headers to a formatted string. */ public String debugDump() { stringRep = ""; Object obj = this.first(); if (obj == null) return ""; sprint("listName:"); sprint(listName); sprint("{"); while (obj != null) { sprint("["); sprint(((GenericObject) obj).debugDump(this.indentation)); obj = next(); sprint("]"); } sprint("}"); return stringRep; } /** * Convert this list of headers to a string (for printing) with an * indentation given. */ public String debugDump(int indent) { int save = indentation; indentation = indent; String retval = this.debugDump(); indentation = save; return retval; } public void addFirst(GenericObject objToAdd) { if (myClass == null) { myClass = objToAdd.getClass(); } else { super.addFirst(objToAdd); } } /** * Do a merge of the GenericObjects contained in this list with the * GenericObjects in the mergeList. Note that this does an inplace * modification of the given list. This does an object by object merge of * the given objects. * * @param mergeList * is the list of Generic objects that we want to do an object by * object merge with. Note that no new objects are added to this * list. * */ public void mergeObjects(GenericObjectList mergeList) { if (mergeList == null) return; Iterator it1 = this.listIterator(); Iterator it2 = mergeList.listIterator(); while (it1.hasNext()) { GenericObject outerObj = (GenericObject) it1.next(); while (it2.hasNext()) { Object innerObj = it2.next(); outerObj.merge(innerObj); } } } /** * Encode the list in semicolon separated form. * * @return an encoded string containing the objects in this list. * @since v1.0 */ public String encode() { if (this.isEmpty()) return ""; StringBuffer encoding = new StringBuffer(); ListIterator iterator = this.listIterator(); if (iterator.hasNext()) { while (true) { Object obj = iterator.next(); if (obj instanceof GenericObject) { GenericObject gobj = (GenericObject) obj; encoding.append(gobj.encode()); } else { encoding.append(obj.toString()); } if (iterator.hasNext()) encoding.append(separator); else break; } } return encoding.toString(); } /** * Alias for the encode function above. */ 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. */ public int hashCode() { return 42; } /** * Equality checking predicate. * * @param other * is the object to compare ourselves to. * @return true if the objects are equal. */ public boolean equals(Object other) { if (other == null ) return false; if (!this.getClass().equals(other.getClass())) return false; GenericObjectList that = (GenericObjectList) other; if (this.size() != that.size()) return false; ListIterator myIterator = this.listIterator(); while (myIterator.hasNext()) { Object myobj = myIterator.next(); ListIterator hisIterator = that.listIterator(); try { while (true) { Object hisobj = hisIterator.next(); if (myobj.equals(hisobj)) break; } } catch (NoSuchElementException ex) { return false; } } ListIterator hisIterator = that.listIterator(); while (hisIterator.hasNext()) { Object hisobj = hisIterator.next(); myIterator = this.listIterator(); try { while (true) { Object myobj = myIterator.next(); if (hisobj.equals(myobj)) break; } } catch (NoSuchElementException ex) { return false; } } return true; } /** * Match with a template (return true if we have a superset of the given * template. This can be used for partial match (template matching of SIP * objects). Note -- this implementation is not unnecessarily efficient :-) * * @param other * template object to compare against. */ public boolean match(Object other) { if (!this.getClass().equals(other.getClass())) return false; GenericObjectList that = (GenericObjectList) other; ListIterator hisIterator = that.listIterator(); outer: while (hisIterator.hasNext()) { Object hisobj = hisIterator.next(); Object myobj = null; ListIterator myIterator = this.listIterator(); while (myIterator.hasNext()) { myobj = myIterator.next(); if (myobj instanceof GenericObject) System.out.println("Trying to match = " + ((GenericObject) myobj).encode()); if (GenericObject.isMySubclass(myobj.getClass()) && ((GenericObject) myobj).match(hisobj)) break outer; else if (GenericObjectList.isMySubclass(myobj.getClass()) && ((GenericObjectList) myobj).match(hisobj)) break outer; } System.out.println(((GenericObject) hisobj).encode()); return false; } return true; } } java/gov/nist/core/Host.java0100644 0000000 0000000 00000021011 13513104763 015004 0ustar000000000 0000000 /* * 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.net.*; /* * IPv6 Support added by Emil Ivov (emil_ivov@yahoo.com)
* Network Research Team (http://www-r2.u-strasbg.fr))
* Louis Pasteur University - Strasbourg - France
* * Frank Feif reported a bug. * * */ /** * Stores hostname. * @version 1.2 * * @author M. Ranganathan * @author Emil Ivov IPV6 Support.
* * * * Marc Bednarek (Bugfixes).
* */ public class Host extends GenericObject { /** * Determines whether or not we should tolerate and strip address scope * zones from IPv6 addresses. Address scope zones are sometimes returned * at the end of IPv6 addresses generated by InetAddress.getHostAddress(). * They are however not part of the SIP semantics so basically this method * determines whether or not the parser should be stripping them (as * opposed simply being blunt and throwing an exception). */ 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; /** hostName field */ protected String hostname; /** address field */ protected int addressType; private InetAddress inetAddress; /** default constructor */ 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"); stripAddressScopeZones = Boolean.getBoolean("gov.nist.core.STRIP_ADDR_SCOPES"); setHost(hostName, IPV4ADDRESS); } /** constructor * @param name String to set * @param addrType int to set */ public Host(String name, int addrType) { stripAddressScopeZones = Boolean.getBoolean("gov.nist.core.STRIP_ADDR_SCOPES"); setHost(name, addrType); } /** * Return the host name in encoded form. * @return String */ public String encode() { return encode(new StringBuffer()).toString(); } public StringBuffer encode(StringBuffer buffer) { if (addressType == IPV6ADDRESS && !isIPv6Reference(hostname)) { buffer.append('[').append(hostname).append(']'); } else { buffer.append(hostname); } return buffer; } /** * Compare for equality of hosts. * Host names are compared by textual equality. No dns lookup * is performed. * @param obj Object to set * @return boolean */ public boolean equals(Object obj) { if ( obj == null ) return false; if (!this.getClass().equals(obj.getClass())) { return false; } Host otherHost = (Host) obj; return otherHost.hostname.equals(hostname); } /** get the HostName field * @return String */ public String getHostname() { return hostname; } /** get the Address field * @return String */ public String getAddress() { return hostname; } /** * Convenience function to get the raw IP destination address * of a SIP message as a String. * @return String */ public String getIpAddress() { String rawIpAddress = null; if (hostname == null) return null; if (addressType == HOSTNAME) { try { if (inetAddress == null) inetAddress = InetAddress.getByName(hostname); rawIpAddress = inetAddress.getHostAddress(); } catch (UnknownHostException ex) { dbgPrint("Could not resolve hostname " + ex); } } else { rawIpAddress = hostname; } return rawIpAddress; } /** * Set the hostname member. * @param h String to set */ public void setHostname(String h) { setHost(h, HOSTNAME); } /** Set the IP Address. *@param address is the address string to set. */ public void setHostAddress(String address) { setHost(address, IPV4ADDRESS); } /** * Sets the host address or name of this object. * * @param host that host address/name value * @param type determines whether host is an address or a host name */ private void setHost(String host, int type){ //set inetAddress to null so that it would be reinited //upon next call to getInetAddress() inetAddress = null; if (isIPv6Address(host)) addressType = IPV6ADDRESS; else addressType = type; // Null check bug fix sent in by jpaulo@ipb.pt if (host != null){ hostname = host.trim(); //if this is an FQDN, make it lowercase to simplify processing if(addressType == HOSTNAME) hostname = hostname.toLowerCase(); //remove address scope zones if this is an IPv6 address as they //are not allowed by the RFC int zoneStart = -1; if(addressType == IPV6ADDRESS && stripAddressScopeZones && (zoneStart = hostname.indexOf('%'))!= -1){ hostname = hostname.substring(0, zoneStart); } } } /** * Set the address member * @param address address String to set */ public void setAddress(String address) { this.setHostAddress(address); } /** Return true if the address is a DNS host name * (and not an IPV4 address) *@return true if the hostname is a DNS name */ public boolean isHostname() { return addressType == HOSTNAME; } /** Return true if the address is a DNS host name * (and not an IPV4 address) *@return true if the hostname is host address. */ public boolean isIPAddress() { return addressType != HOSTNAME; } /** Get the inet address from this host. * Caches the inet address returned from dns lookup to avoid * lookup delays. * *@throws UnkownHostexception when the host name cannot be resolved. */ public InetAddress getInetAddress() throws java.net.UnknownHostException { if (hostname == null) return null; if (inetAddress != null) return inetAddress; inetAddress = InetAddress.getByName(hostname); return inetAddress; } //----- IPv6 /** * Verifies whether the address could * be an IPv6 address */ private boolean isIPv6Address(String address) { return (address != null && address.indexOf(':') != -1); } /** * Verifies whether the ipv6reference, i.e. whether it enclosed in * square brackets */ public static boolean isIPv6Reference(String address) { return address.charAt(0) == '[' && address.charAt(address.length() - 1) == ']'; } @Override public int hashCode() { return this.getHostname().hashCode(); } } java/gov/nist/core/HostNameParser.java0100644 0000000 0000000 00000027274 13513104763 017003 0ustar000000000 0000000 /* * 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 * * . * */ /* * * IPv6 Support added by Emil Ivov (emil_ivov@yahoo.com)
* Network Research Team (http://www-r2.u-strasbg.fr))
* Louis Pasteur University - Strasbourg - France
* *Bug fixes for corner cases were contributed by Thomas Froment. */ package gov.nist.core; // BEGIN android-deleted //import gov.nist.javax.sdp.parser.Lexer; // END android-deleted import java.text.ParseException; /** * Parser for host names. * *@version 1.2 * *@author M. Ranganathan */ public class HostNameParser extends ParserCore { // BEGIN android-added private static LexerCore Lexer; // END android-added /** * Determines whether or not we should tolerate and strip address scope * zones from IPv6 addresses. Address scope zones are sometimes returned * at the end of IPv6 addresses generated by InetAddress.getHostAddress(). * They are however not part of the SIP semantics so basically this method * determines whether or not the parser should be stripping them (as * opposed simply being blunt and throwing an exception). */ private boolean stripAddressScopeZones = false; public HostNameParser(String hname) { this.lexer = new LexerCore("charLexer", hname); stripAddressScopeZones = Boolean.getBoolean("gov.nist.core.STRIP_ADDR_SCOPES"); } /** * The lexer is initialized with the buffer. */ 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 = new char[] {LexerCore.ALPHADIGIT_VALID_CHARS, '-', '.'}; protected void consumeDomainLabel() throws ParseException { if (debug) dbg_enter("domainLabel"); try { lexer.consumeValidChars(VALID_DOMAIN_LABEL_CHAR); } finally { if (debug) dbg_leave("domainLabel"); } } protected String ipv6Reference() throws ParseException { StringBuffer retval = new StringBuffer(); if (debug) dbg_enter("ipv6Reference"); try { if(stripAddressScopeZones){ while (lexer.hasMoreChars()) { char la = lexer.lookAhead(0); //'%' is ipv6 address scope zone. see detail at //java.sun.com/j2se/1.5.0/docs/api/java/net/Inet6Address.html if (LexerCore.isHexDigit(la) || la == '.' || la == ':' || la == '[' ) { lexer.consume(1); retval.append(la); } else if (la == ']') { lexer.consume(1); retval.append(la); return retval.toString(); } else if (la == '%'){ //we need to strip the address scope zone. lexer.consume(1); String rest = lexer.getRest(); if(rest == null || rest.length() == 0){ //head for the parse exception break; } //we strip everything until either the end of the string //or a closing square bracket (]) int stripLen = rest.indexOf(']'); if (stripLen == -1){ //no square bracket -> not a valid ipv6 reference break; } lexer.consume(stripLen+1); retval.append("]"); return retval.toString(); } else break; } } else { while (lexer.hasMoreChars()) { char la = lexer.lookAhead(0); if (LexerCore.isHexDigit(la) || la == '.' || la == ':' || la == '[') { lexer.consume(1); retval.append(la); } else if (la == ']') { lexer.consume(1); retval.append(la); return retval.toString(); } else break; } } throw new ParseException( lexer.getBuffer() + ": Illegal Host name ", lexer.getPtr()); } finally { if (debug) dbg_leave("ipv6Reference"); } } public Host host() throws ParseException { if (debug) dbg_enter("host"); try { String hostname; //IPv6 referene if (lexer.lookAhead(0) == '[') { hostname = ipv6Reference(); } //IPv6 address (i.e. missing square brackets) else if( isIPv6Address(lexer.getRest()) ) { int startPtr = lexer.getPtr(); lexer.consumeValidChars( new char[] {LexerCore.ALPHADIGIT_VALID_CHARS, ':'}); hostname = new StringBuffer("[").append( lexer.getBuffer().substring(startPtr, lexer.getPtr())) .append("]").toString(); } //IPv4 address or hostname else { int startPtr = lexer.getPtr(); consumeDomainLabel(); hostname = lexer.getBuffer().substring(startPtr, lexer.getPtr()); } if (hostname.length() == 0) throw new ParseException( lexer.getBuffer() + ": Missing host name", lexer.getPtr()); else return new Host(hostname); } finally { if (debug) dbg_leave("host"); } } /** * Tries to determine whether the address in uriHeader could be * an IPv6 address by counting the number of colons that appear in it. * * @param uriHeader the string (supposedly the value of a URI header) that * we have received for parsing. * * @return true if the host part of uriHeader could be an IPv6 * address (i.e. contains at least two colons) and false otherwise. */ private boolean isIPv6Address(String uriHeader) { // approximately detect the end the host part. //first check if we have an uri param int hostEnd = uriHeader.indexOf(Lexer.QUESTION); //if not or if it appears after a semi-colon then the end of the //address would be a header param. int semiColonIndex = uriHeader.indexOf(Lexer.SEMICOLON); if ( hostEnd == -1 || (semiColonIndex!= -1 && hostEnd > semiColonIndex) ) hostEnd = semiColonIndex; //if there was no header param either the address //continues until the end of the string if ( hostEnd == -1 ) hostEnd = uriHeader.length(); //extract the address String host = uriHeader.substring(0, hostEnd); int firstColonIndex = host.indexOf(Lexer.COLON); if(firstColonIndex == -1) return false; int secondColonIndex = host.indexOf(Lexer.COLON, firstColonIndex + 1); if(secondColonIndex == -1) return false; return true; } /** * Parses a host:port string * * @param allowWS - whether whitespace is allowed around ':', only true for Via headers * @return * @throws ParseException */ public HostPort hostPort( boolean allowWS ) throws ParseException { if (debug) dbg_enter("hostPort"); try { Host host = this.host(); HostPort hp = new HostPort(); hp.setHost(host); // Has a port? if (allowWS) lexer.SPorHT(); // white space before ":port" should be accepted if (lexer.hasMoreChars()) { char la = lexer.lookAhead(0); switch (la) { case ':': lexer.consume(1); if (allowWS) lexer.SPorHT(); // white space before port number should be accepted try { String port = lexer.number(); hp.setPort(Integer.parseInt(port)); } catch (NumberFormatException nfe) { throw new ParseException( lexer.getBuffer() + " :Error parsing port ", lexer.getPtr()); } break; case ',': // allowed in case of multi-headers, e.g. Route // Could check that current header is a multi hdr case ';': // OK, can appear in URIs (parameters) case '?': // same, header parameters case '>': // OK, can appear in headers case ' ': // OK, allow whitespace case '\t': case '\r': case '\n': case '/': // e.g. http://[::1]/xyz.html break; case '%': if(stripAddressScopeZones){ break;//OK,allow IPv6 address scope zone } default: if (!allowWS) { throw new ParseException( lexer.getBuffer() + " Illegal character in hostname:" + lexer.lookAhead(0), lexer.getPtr() ); } } } return hp; } finally { if (debug) dbg_leave("hostPort"); } } public static void main(String args[]) throws ParseException { String hostNames[] = { "foo.bar.com:1234", "proxima.chaplin.bt.co.uk", "129.6.55.181:2345", ":1234", "foo.bar.com: 1234", "foo.bar.com : 1234 ", "MIK_S:1234" }; for (int i = 0; i < hostNames.length; i++) { try { HostNameParser hnp = new HostNameParser(hostNames[i]); HostPort hp = hnp.hostPort(true); System.out.println("["+hp.encode()+"]"); } catch (ParseException ex) { System.out.println("exception text = " + ex.getMessage()); } } } } java/gov/nist/core/HostPort.java0100644 0000000 0000000 00000010507 13513104763 015661 0ustar000000000 0000000 /* * 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.net.*; /** * Holds the hostname:port. * *@version 1.2 * *@author M. Ranganathan * * * */ public final class HostPort extends GenericObject { private static final long serialVersionUID = -7103412227431884523L; // host / ipv4/ ipv6/ /** host field */ protected Host host; /** port field * */ protected int port; /** Default constructor */ public HostPort() { host = null; port = -1; // marker for not set. } /** * Encode this hostport into its string representation. * Note that this could be different from the string that has * been parsed if something has been edited. * @return String */ public String encode() { return encode(new StringBuffer()).toString(); } public StringBuffer encode(StringBuffer buffer) { host.encode(buffer); if (port != -1) buffer.append(COLON).append(port); return buffer; } /** returns true if the two objects are equals, false otherwise. * @param other Object to set * @return boolean */ public boolean equals(Object other) { if (other == null) return false; if (getClass () != other.getClass ()) { return false; } HostPort that = (HostPort) other; return port == that.port && host.equals(that.host); } /** get the Host field * @return host field */ public Host getHost() { return host; } /** get the port field * @return int */ public int getPort() { return port; } /** * Returns boolean value indicating if Header has port * @return boolean value indicating if Header has port */ public boolean hasPort() { return port != -1; } /** remove port. */ public void removePort() { port = -1; } /** * Set the host member * @param h Host to set */ public void setHost(Host h) { host = h; } /** * Set the port member * @param p int to set */ public void setPort(int p) { port = p; } /** Return the internet address corresponding to the host. *@throws java.net.UnkownHostException if host name cannot be resolved. *@return the inet address for the host. */ public InetAddress getInetAddress() throws java.net.UnknownHostException { if (host == null) return null; else return host.getInetAddress(); } public void merge(Object mergeObject) { super.merge (mergeObject); if (port == -1) port = ((HostPort) mergeObject).port; } public Object clone() { HostPort retval = (HostPort) super.clone(); if (this.host != null) retval.host = (Host) this.host.clone(); return retval; } public String toString() { return this.encode(); } @Override public int hashCode() { return this.host.hashCode() + this.port; } } java/gov/nist/core/InternalErrorHandler.java0100644 0000000 0000000 00000005477 13513104763 020175 0ustar000000000 0000000 /* * 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; /** * Handle Internal error failures and print a stack trace (for debugging). * *@version 1.2 * *@author M. Ranganathan
* * * */ public class InternalErrorHandler { public static void handleException(Exception ex) throws RuntimeException { System.err.println ("Unexpected internal error FIXME!! " + ex.getMessage()); ex.printStackTrace(); throw new RuntimeException("Unexpected internal error FIXME!! " + ex.getMessage(), ex); } /** * Handle an unexpected exception. */ public static void handleException(Exception ex, StackLogger stackLogger) { System.err.println ("Unexpected internal error FIXME!! " + ex.getMessage()); stackLogger.logError("UNEXPECTED INTERNAL ERROR FIXME " + ex.getMessage()); ex.printStackTrace(); stackLogger.logException(ex); throw new RuntimeException("Unexpected internal error FIXME!! " + ex.getMessage(), ex); } /** * Handle an unexpected condition (and print the error code). */ public static void handleException(String emsg) { new Exception().printStackTrace(); System.err.println("Unexepcted INTERNAL ERROR FIXME!!"); System.err.println(emsg); throw new RuntimeException(emsg); } public static void handleException(String emsg, StackLogger stackLogger) { stackLogger.logStackTrace(); stackLogger.logError("Unexepcted INTERNAL ERROR FIXME!!"); stackLogger.logFatalError(emsg); throw new RuntimeException(emsg); } } java/gov/nist/core/LexerCore.java0100644 0000000 0000000 00000057611 13513104763 015776 0ustar000000000 0000000 /* * 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.core; import java.text.ParseException; import java.util.Hashtable; /** A lexical analyzer that is used by all parsers in our implementation. * *@version 1.2 *@since 1.1 * *@author M. Ranganathan */ public class LexerCore extends StringTokenizer { // IMPORTANT - All keyword matches should be between START and END public static final int START = 2048; public static final int END = START + 2048; // IMPORTANT -- This should be < END public static final int ID = END - 1; public static final int SAFE = END - 2; // Individial token classes. public static final int WHITESPACE = END + 1; public static final int DIGIT = END + 2; public static final int ALPHA = END + 3; public static final int BACKSLASH = (int) '\\'; public static final int QUOTE = (int) '\''; public static final int AT = (int) '@'; public static final int SP = (int) ' '; public static final int HT = (int) '\t'; public static final int COLON = (int) ':'; public static final int STAR = (int) '*'; public static final int DOLLAR = (int) '$'; public static final int PLUS = (int) '+'; public static final int POUND = (int) '#'; public static final int MINUS = (int) '-'; public static final int DOUBLEQUOTE = (int) '\"'; public static final int TILDE = (int) '~'; public static final int BACK_QUOTE = (int) '`'; public static final int NULL = (int) '\0'; public static final int EQUALS = (int) '='; public static final int SEMICOLON = (int) ';'; public static final int SLASH = (int) '/'; public static final int L_SQUARE_BRACKET = (int) '['; public static final int R_SQUARE_BRACKET = (int) ']'; public static final int R_CURLY = (int) '}'; public static final int L_CURLY = (int) '{'; public static final int HAT = (int) '^'; public static final int BAR = (int) '|'; public static final int DOT = (int) '.'; public static final int EXCLAMATION = (int) '!'; public static final int LPAREN = (int) '('; public static final int RPAREN = (int) ')'; public static final int GREATER_THAN = (int) '>'; public static final int LESS_THAN = (int) '<'; public static final int PERCENT = (int) '%'; public static final int QUESTION = (int) '?'; public static final int AND = (int) '&'; public static final int UNDERSCORE = (int) '_'; protected static final Hashtable globalSymbolTable; protected static final Hashtable lexerTables; protected Hashtable currentLexer; protected String currentLexerName; protected Token currentMatch; static { globalSymbolTable = new Hashtable(); lexerTables = new Hashtable(); } protected void addKeyword(String name, int value) { // System.out.println("addKeyword " + name + " value = " + value); // new Exception().printStackTrace(); Integer val = Integer.valueOf(value); currentLexer.put(name, val); if (!globalSymbolTable.containsKey(val)) globalSymbolTable.put(val, name); } public String lookupToken(int value) { if (value > START) { return (String) globalSymbolTable.get(Integer.valueOf(value)); } else { Character ch = Character.valueOf((char) value); return ch.toString(); } } 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); public void selectLexer(String lexerName) { this.currentLexerName = lexerName; } protected LexerCore() { this.currentLexer = new Hashtable(); this.currentLexerName = "charLexer"; } /** Initialize the lexer with a buffer. */ public LexerCore(String lexerName, String buffer) { super(buffer); this.currentLexerName = lexerName; } /** Peek the next id but dont move the buffer pointer forward. */ public String peekNextId() { int oldPtr = ptr; String retval = ttoken(); savedPtr = ptr; ptr = oldPtr; return retval; } /** Get the next id. */ public String getNextId() { return ttoken(); } // call this after you call match public Token getNextToken() { return this.currentMatch; } /** Look ahead for one token. */ public Token peekNextToken() throws ParseException { return (Token) peekNextToken(1)[0]; } public Token[] peekNextToken(int ntokens) throws ParseException { int old = ptr; Token[] retval = new Token[ntokens]; for (int i = 0; i < ntokens; i++) { Token tok = new Token(); if (startsId()) { String id = ttoken(); tok.tokenValue = id; String idUppercase = id.toUpperCase(); if (currentLexer.containsKey(idUppercase)) { Integer type = (Integer) currentLexer.get(idUppercase); tok.tokenType = type.intValue(); } else tok.tokenType = ID; } else { char nextChar = getNextChar(); tok.tokenValue = String.valueOf(nextChar); if (isAlpha(nextChar)) { tok.tokenType = ALPHA; } else if (isDigit(nextChar)) { tok.tokenType = DIGIT; } else tok.tokenType = (int) nextChar; } retval[i] = tok; } savedPtr = ptr; ptr = old; return retval; } /** Match the given token or throw an exception if no such token * can be matched. */ public Token match(int tok) throws ParseException { if (Debug.parserDebug) { Debug.println("match " + tok); } if (tok > START && tok < END) { if (tok == ID) { // Generic ID sought. if (!startsId()) throw new ParseException(buffer + "\nID expected", ptr); String id = getNextId(); this.currentMatch = new Token(); this.currentMatch.tokenValue = id; this.currentMatch.tokenType = ID; } else if (tok == SAFE) { if (!startsSafeToken()) throw new ParseException(buffer + "\nID expected", ptr); String id = ttokenSafe(); this.currentMatch = new Token(); this.currentMatch.tokenValue = id; this.currentMatch.tokenType = SAFE; } else { String nexttok = getNextId(); Integer cur = (Integer) currentLexer.get(nexttok.toUpperCase()); if (cur == null || cur.intValue() != tok) throw new ParseException( buffer + "\nUnexpected Token : " + nexttok, ptr); this.currentMatch = new Token(); this.currentMatch.tokenValue = nexttok; this.currentMatch.tokenType = tok; } } else if (tok > END) { // Character classes. char next = lookAhead(0); if (tok == DIGIT) { if (!isDigit(next)) throw new ParseException(buffer + "\nExpecting DIGIT", ptr); this.currentMatch = new Token(); this.currentMatch.tokenValue = String.valueOf(next); this.currentMatch.tokenType = tok; consume(1); } else if (tok == ALPHA) { if (!isAlpha(next)) throw new ParseException(buffer + "\nExpecting ALPHA", ptr); this.currentMatch = new Token(); this.currentMatch.tokenValue = String.valueOf(next); this.currentMatch.tokenType = tok; consume(1); } } else { // This is a direct character spec. char ch = (char) tok; char next = lookAhead(0); if (next == ch) { /*this.currentMatch = new Token(); this.currentMatch.tokenValue = String.valueOf(ch); this.currentMatch.tokenType = tok;*/ consume(1); } else throw new ParseException( buffer + "\nExpecting >>>" + ch + "<<< got >>>" + next + "<<<", ptr); } return this.currentMatch; } public void SPorHT() { try { char c = lookAhead(0); while (c == ' ' || c == '\t') { consume(1); c = lookAhead(0); } } catch (ParseException ex) { // Ignore } } /** * JvB: utility function added to validate tokens * * @see RFC3261 section 25.1: * token = 1*(alphanum / "-" / "." / "!" / "%" / "*" / "_" / "+" / "`" / "'" / "~" ) * @param c - character to check * @return true iff character c is a valid token character as per RFC3261 */ public static final boolean isTokenChar( char c ) { if ( isAlphaDigit(c) ) return true; else switch (c) { case '-': case '.': case '!': case '%': case '*': case '_': case '+': case '`': case '\'': case '~': return true; default: return false; } } public boolean startsId() { try { char nextChar = lookAhead(0); return isTokenChar(nextChar); } catch (ParseException ex) { return false; } } public boolean startsSafeToken() { try { char nextChar = lookAhead(0); if (isAlphaDigit(nextChar)) { return true; } else { switch (nextChar) { case '_': case '+': case '-': case '!': case '`': case '\'': case '.': case '/': case '}': case '{': case ']': case '[': case '^': case '|': case '~': case '%': // bug fix by Bruno Konik, JvB copied here case '#': case '@': case '$': case ':': case ';': case '?': case '\"': case '*': case '=': // Issue 155 on java.net return true; default: return false; } } } catch (ParseException ex) { return false; } } public String ttoken() { int startIdx = ptr; try { while (hasMoreChars()) { char nextChar = lookAhead(0); if ( isTokenChar(nextChar) ) { consume(1); } else { break; } } return buffer.substring(startIdx, ptr); } catch (ParseException ex) { return null; } } /* JvB: unreferenced public String ttokenAllowSpace() { int startIdx = ptr; try { while (hasMoreChars()) { char nextChar = lookAhead(0); if (isAlphaDigit(nextChar)) { consume(1); } else { boolean isValidChar = false; switch (nextChar) { case '_': case '+': case '-': case '!': case '`': case '\'': case '~': case '%': // bug fix by Bruno Konik, JvB copied here case '.': case ' ': case '\t': case '*': isValidChar = true; } if (isValidChar) { consume(1); } else { break; } } } return buffer.substring(startIdx, ptr); } catch (ParseException ex) { return null; } }*/ public String ttokenSafe() { int startIdx = ptr; try { while (hasMoreChars()) { char nextChar = lookAhead(0); if (isAlphaDigit(nextChar)) { consume(1); } else { boolean isValidChar = false; switch (nextChar) { case '_': case '+': case '-': case '!': case '`': case '\'': case '.': case '/': case '}': case '{': case ']': case '[': case '^': case '|': case '~': case '%': // bug fix by Bruno Konik, JvB copied here case '#': case '@': case '$': case ':': case ';': case '?': case '\"': case '*': isValidChar = true; } if (isValidChar) { consume(1); } else { break; } } } return buffer.substring(startIdx, ptr); } catch (ParseException ex) { return null; } } static final char ALPHA_VALID_CHARS = Character.MAX_VALUE; static final char DIGIT_VALID_CHARS = Character.MAX_VALUE - 1; static final char ALPHADIGIT_VALID_CHARS = Character.MAX_VALUE - 2; public void consumeValidChars(char[] validChars) { int validCharsLength = validChars.length; try { while (hasMoreChars()) { char nextChar = lookAhead(0); boolean isValid = false; for (int i = 0; i < validCharsLength; i++) { char validChar = validChars[i]; switch(validChar) { case ALPHA_VALID_CHARS: isValid = isAlpha(nextChar); break; case DIGIT_VALID_CHARS: isValid = isDigit(nextChar); break; case ALPHADIGIT_VALID_CHARS: isValid = isAlphaDigit(nextChar); break; default: isValid = nextChar == validChar; } if (isValid) { break; } } if (isValid) { consume(1); } else { break; } } } catch (ParseException ex) { } } /** Parse a comment string cursor is at a ". Leave cursor at closing " *@return the substring containing the quoted string excluding the * closing quote. */ public String quotedString() throws ParseException { int startIdx = ptr + 1; if (lookAhead(0) != '\"') return null; consume(1); while (true) { char next = getNextChar(); if (next == '\"') { // Got to the terminating quote. break; } else if (next == '\0') { throw new ParseException( this.buffer + " :unexpected EOL", this.ptr); } else if (next == '\\') { consume(1); } } return buffer.substring(startIdx, ptr - 1); } /** Parse a comment string cursor is at a "(". Leave cursor at ) *@return the substring containing the comment excluding the * closing brace. */ public String comment() throws ParseException { StringBuffer retval = new StringBuffer(); if (lookAhead(0) != '(') return null; consume(1); while (true) { char next = getNextChar(); if (next == ')') { break; } else if (next == '\0') { throw new ParseException( this.buffer + " :unexpected EOL", this.ptr); } else if (next == '\\') { retval.append(next); next = getNextChar(); if (next == '\0') throw new ParseException( this.buffer + " : unexpected EOL", this.ptr); retval.append(next); } else { retval.append(next); } } return retval.toString(); } /** Return a substring containing no semicolons. *@return a substring containing no semicolons. */ public String byteStringNoSemicolon() { StringBuffer retval = new StringBuffer(); try { while (true) { char next = lookAhead(0); // bug fix from Ben Evans. if (next == '\0' || next == '\n' || next == ';' || next == ',' ) { break; } else { consume(1); retval.append(next); } } } catch (ParseException ex) { return retval.toString(); } return retval.toString(); } /** * Scan until you see a slash or an EOL. * * @return substring containing no slash. */ public String byteStringNoSlash() { StringBuffer retval = new StringBuffer(); try { while (true) { char next = lookAhead(0); // bug fix from Ben Evans. if (next == '\0' || next == '\n' || next == '/' ) { break; } else { consume(1); retval.append(next); } } } catch (ParseException ex) { return retval.toString(); } return retval.toString(); } /** Return a substring containing no commas *@return a substring containing no commas. */ public String byteStringNoComma() { StringBuffer retval = new StringBuffer(); try { while (true) { char next = lookAhead(0); if (next == '\n' || next == ',') { break; } else { consume(1); retval.append(next); } } } catch (ParseException ex) { } return retval.toString(); } public static String charAsString(char ch) { return String.valueOf(ch); } /** Lookahead in the inputBuffer for n chars and return as a string. * Do not consume the input. */ public String charAsString(int nchars) { return buffer.substring(ptr, ptr + nchars); } /** Get and consume the next number. *@return a substring corresponding to a number *(i.e. sequence of digits). */ public String number() throws ParseException { int startIdx = ptr; try { if (!isDigit(lookAhead(0))) { throw new ParseException( buffer + ": Unexpected token at " + lookAhead(0), ptr); } consume(1); while (true) { char next = lookAhead(0); if (isDigit(next)) { consume(1); } else break; } return buffer.substring(startIdx, ptr); } catch (ParseException ex) { return buffer.substring(startIdx, ptr); } } /** Mark the position for backtracking. *@return the current location of the pointer. */ public int markInputPosition() { return ptr; } /** Rewind the input ptr to the marked position. *@param position - the position to rewind the parser to. */ public void rewindInputPosition(int position) { this.ptr = position; } /** Get the rest of the String * @return rest of the buffer. */ public String getRest() { if (ptr >= buffer.length()) return null; else return buffer.substring(ptr); } /** Get the sub-String until the character is encountered * @param c the character to match * @return the substring that matches. */ public String getString(char c) throws ParseException { StringBuffer retval = new StringBuffer(); while (true) { char next = lookAhead(0); //System.out.println(" next = [" + next + ']' + "ptr = " + ptr); //System.out.println(next == '\0'); if (next == '\0') { throw new ParseException( this.buffer + "unexpected EOL", this.ptr); } else if (next == c) { consume(1); break; } else if (next == '\\') { consume(1); char nextchar = lookAhead(0); if (nextchar == '\0') { throw new ParseException( this.buffer + "unexpected EOL", this.ptr); } else { consume(1); retval.append(nextchar); } } else { consume(1); retval.append(next); } } return retval.toString(); } /** Get the read pointer. */ public int getPtr() { return this.ptr; } /** Get the buffer. */ public String getBuffer() { return this.buffer; } /** Create a parse exception. */ public ParseException createParseException() { return new ParseException(this.buffer, this.ptr); } } java/gov/nist/core/LogLevels.java0100644 0000000 0000000 00000001165 13513104763 015773 0ustar000000000 0000000 package gov.nist.core; public interface LogLevels { /* * Each of these levels must be mapped internally to logically equivalent * logging levels in your logger. */ public static final int TRACE_NONE = 0; public static final int TRACE_FATAL = 2; public static final int TRACE_ERROR = 4; public static final int TRACE_WARN = 8; public static final int TRACE_INFO = 16; public static final int TRACE_DEBUG = 32; public static final int TRACE_TRACE = 64; public static final int TRACE_MESSAGES = TRACE_INFO; public static final int TRACE_EXCEPTION = TRACE_ERROR; } java/gov/nist/core/LogWriter.java0100644 0000000 0000000 00000042714 13513104763 016022 0ustar000000000 0000000 /* * 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.*; import java.util.Properties; // BEGIN ANDROID-added // TODO: this class should be replaced by android logging mechanism. public class LogWriter implements StackLogger { private static final String TAG = "SIP_STACK"; private boolean mEnabled = true; public void logStackTrace() { // TODO } public void logStackTrace(int traceLevel) { // TODO } public int getLineCount() { return 0; } public void logException(Throwable ex) { //Log.e(TAG, "", ex); } public void logDebug(String message) { //Log.d(TAG, message); } public void logTrace(String message) { //Log.d(TAG, message); } public void logFatalError(String message) { //Log.e(TAG, message); } public void logError(String message) { //Log.e(TAG, message); } public boolean isLoggingEnabled() { return mEnabled; } public boolean isLoggingEnabled(int logLevel) { // TODO return mEnabled; } public void logError(String message, Exception ex) { //Log.e(TAG, message, ex); } public void logWarning(String string) { //Log.w(TAG, string); } public void logInfo(String string) { //Log.i(TAG, string); } public void disableLogging() { mEnabled = false; } public void enableLogging() { mEnabled = true; } public void setBuildTimeStamp(String buildTimeStamp) { } public void setStackProperties(Properties stackProperties) { } public String getLoggerName() { return "Android SIP Logger"; } } // END android-added // BEGIN android-deleted //import org.apache.log4j.Appender; //import org.apache.log4j.FileAppender; //import org.apache.log4j.Level; //import org.apache.log4j.Logger; //import org.apache.log4j.Priority; //import org.apache.log4j.SimpleLayout; // ///** // * 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.2 // * // * @author M. Ranganathan
// * @author M.Andrews // * @author Jeroen van Bemmel // * @author Jean Deruelle // * // */ // //public class LogWriter implements StackLogger { // // /** // * The logger to which we will write our logging output. // */ // private Logger logger; // // /** // * The stack name. // */ // private String stackName; // // /** // * Name of the log file in which the trace is written out (default is // * /tmp/sipserverlog.txt) // */ // private String logFileName = null; // // /** // * Flag to indicate that logging is enabled. // */ // private volatile boolean needsLogging = false; // // private int lineCount; // // /** // * trace level // */ // // protected int traceLevel = TRACE_NONE; // // private String buildTimeStamp; // // private Properties configurationProperties; // // /** // * log a stack trace. This helps to look at the stack frame. // */ // public void logStackTrace() { // this.logStackTrace(TRACE_DEBUG); // // } // // public void logStackTrace(int traceLevel) { // if (needsLogging) { // 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(); // Level level = this.getLevel(traceLevel); // Priority priority = this.getLogPriority(); // if ( level.isGreaterOrEqual(priority)) { // logger.log(level,stackTrace); // } // // } // } // // /** // * Get the line count in the log stream. // * // * @return // */ // public int getLineCount() { // return lineCount; // } // // /** // * 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) { // // if (needsLogging) { // // this.getLogger().error(ex.getMessage(), ex); // } // } // // // // // /** // * Counts the line number so that the debug log can be correlated to the // * message trace. // * // * @param message -- // * message to count the lines for. // */ // private void countLines(String message) { // char[] chars = message.toCharArray(); // for (int i = 0; i < chars.length; i++) { // if (chars[i] == '\n') // lineCount++; // } // // } // // /** // * Prepend the line and file where this message originated from // * // * @param message // * @return re-written message. // */ // private String enhanceMessage(String message) { // // StackTraceElement[] stackTrace = new Exception().getStackTrace(); // StackTraceElement elem = stackTrace[2]; // String className = elem.getClassName(); // String methodName = elem.getMethodName(); // String fileName = elem.getFileName(); // int lineNumber = elem.getLineNumber(); // String newMessage = className + "." + methodName + "(" + fileName + ":" // + lineNumber + ") [" + message + "]"; // return newMessage; // // } // // /** // * Log a message into the log file. // * // * @param message // * message to log into the log file. // */ // public void logDebug(String message) { // if (needsLogging) { // String newMessage = this.enhanceMessage(message); // if ( this.lineCount == 0) { // getLogger().debug("BUILD TIMESTAMP = " + this.buildTimeStamp); // getLogger().debug("Config Propeties = " + this.configurationProperties); // } // countLines(newMessage); // getLogger().debug(newMessage); // } // // } // // /** // * Log a message into the log file. // * // * @param message // * message to log into the log file. // */ // public void logTrace(String message) { // if (needsLogging) { // String newMessage = this.enhanceMessage(message); // if ( this.lineCount == 0) { // getLogger().debug("BUILD TIMESTAMP = " + this.buildTimeStamp); // getLogger().debug("Config Propeties = " + this.configurationProperties); // } // countLines(newMessage); // getLogger().trace(newMessage); // } // // } // // /** // * Set the trace level for the stack. // */ // private void setTraceLevel(int level) { // traceLevel = level; // } // // /** // * Get the trace level for the stack. // */ // public int getTraceLevel() { // return traceLevel; // } // // /** // * Log an error message. // * // * @param message -- // * error message to log. // */ // public void logFatalError(String message) { // Logger logger = this.getLogger(); // String newMsg = this.enhanceMessage(message); // countLines(newMsg); // logger.fatal(newMsg); // // } // // /** // * Log an error message. // * // * @param message -- // * error message to log. // * // */ // public void logError(String message) { // Logger logger = this.getLogger(); // String newMsg = this.enhanceMessage(message); // countLines(newMsg); // logger.error(newMsg); // // } // // public LogWriter() { // } // // public void setStackProperties(Properties configurationProperties) { // // this.configurationProperties = configurationProperties; // // String logLevel = configurationProperties // .getProperty("gov.nist.javax.sip.TRACE_LEVEL"); // // this.logFileName = configurationProperties // .getProperty("gov.nist.javax.sip.DEBUG_LOG"); // // this.stackName = configurationProperties // .getProperty("javax.sip.STACK_NAME"); // // //check whether a Log4j logger name has been // //specified. if not, use the stack name as the default // //logger name. // String category = configurationProperties // .getProperty("gov.nist.javax.sip.LOG4J_LOGGER_NAME", this.stackName); // // // logger = Logger.getLogger(category); // if (logLevel != null) { // 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.isGreaterOrEqual(Level.DEBUG)) { // this.traceLevel = TRACE_DEBUG; // } else if (level.isGreaterOrEqual(Level.INFO)) { // this.traceLevel = TRACE_INFO; // } else if (level.isGreaterOrEqual(Level.WARN)) { // this.traceLevel = TRACE_ERROR; // } // } // else { // try { // int ll = 0; // if (logLevel.equals("TRACE")) { // ll = TRACE_DEBUG; // Debug.debug = true; // Debug.setStackLogger(this); // } else if (logLevel.equals("DEBUG")) { // ll = TRACE_DEBUG; // } else if ( logLevel.equals("INFO")) { // ll = TRACE_INFO; // } else if (logLevel.equals("ERROR")) { // ll = TRACE_ERROR; // } else if (logLevel.equals("NONE") || logLevel.equals("OFF")) { // ll = TRACE_NONE; // } else { // ll = Integer.parseInt(logLevel); // if ( ll > 32 ) { // Debug.debug = true; // Debug.setStackLogger(this); // } // } // // this.setTraceLevel(ll); // this.needsLogging = true; // if (traceLevel == TRACE_DEBUG) { // logger.setLevel(Level.DEBUG); // } else if (traceLevel == TRACE_INFO) { // logger.setLevel(Level.INFO); // } else if (traceLevel == TRACE_ERROR) { // logger.setLevel(Level.ERROR); // } else if (traceLevel == TRACE_NONE) { // logger.setLevel(Level.OFF); // this.needsLogging = false; // } // // /* // * If user specifies a logging file as part of the startup // * properties then we try to create the appender. // */ // if (this.needsLogging && this.logFileName != null) { // // boolean overwrite = Boolean.valueOf( // configurationProperties.getProperty( // "gov.nist.javax.sip.DEBUG_LOG_OVERWRITE")); // // FileAppender fa = null; // try { // fa = new FileAppender(new SimpleLayout(), // this.logFileName, !overwrite); // } catch (FileNotFoundException fnf) { // // // Likely due to some directoy not existing. Create // // them // File logfile = new File(this.logFileName); // logfile.getParentFile().mkdirs(); // logfile.delete(); // // try { // fa = new FileAppender(new SimpleLayout(), // this.logFileName); // } catch (IOException ioe) { // ioe.printStackTrace(); // give up // } // } catch (IOException ex) { // ex.printStackTrace(); // } // // if (fa != null) // logger.addAppender(fa); // } // // } catch (NumberFormatException ex) { // ex.printStackTrace(); // System.err.println("LogWriter: Bad integer " + logLevel); // System.err.println("logging dislabled "); // needsLogging = false; // } // } // } else { // this.needsLogging = false; // // } // // // } // // /** // * @return flag to indicate if logging is enabled. // */ // public boolean isLoggingEnabled() { // // return this.needsLogging; // } // // /** // * Return true/false if loging is enabled at a given level. // * // * @param logLevel // */ // public boolean isLoggingEnabled(int logLevel) { // return this.needsLogging && logLevel <= traceLevel; // } // // // /** // * 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() { // this.needsLogging = false; // } // // /** // * Enable logging (globally). // */ // public void enableLogging() { // this.needsLogging = true; // // } // // public void setBuildTimeStamp(String buildTimeStamp) { // this.buildTimeStamp = buildTimeStamp; // // } // // public Priority getLogPriority() { // if ( this.traceLevel == TRACE_INFO ) { // return Priority.INFO; // } else if ( this.traceLevel == TRACE_ERROR ) { // return Priority.ERROR; // } else if ( this.traceLevel == TRACE_DEBUG) { // return Priority.DEBUG; // } else if ( this.traceLevel == TRACE_TRACE) { // return Priority.DEBUG; // } else { // return Priority.FATAL; // } // } // // public Level getLevel(int traceLevel) { // if ( traceLevel == TRACE_INFO ) { // return Level.INFO; // } else if ( traceLevel == TRACE_ERROR ) { // return Level.ERROR; // } else if ( traceLevel == TRACE_DEBUG) { // return Level.DEBUG; // } else if (traceLevel == TRACE_TRACE) { // return Level.ALL; // } else { // return Level.OFF; // } // } // // public String getLoggerName() { // if ( this.logger != null ) { // return logger.getName(); // } else { // return null; // } // } // // //} // END android-deleted java/gov/nist/core/Match.java0100644 0000000 0000000 00000003115 13513104763 015130 0ustar000000000 0000000 /* * 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.core; /** Match template for pattern matching. * *@version 1.2 * *@author M. Ranganathan
* * * */ public interface Match { /** Return true if a match occurs for searchString. * This is used for pattern matching in the find and replace and match * functions of the sipheaders and sdpfields packages. We have avoided * picking a specific regexp package to avoid code dependencies. * Use a package such as the jakarta regexp package to implement this. */ public boolean match(String searchString); } java/gov/nist/core/MultiValueMap.java0100644 0000000 0000000 00000000457 13513104763 016627 0ustar000000000 0000000 package gov.nist.core; import java.io.Serializable; import java.util.List; import java.util.Map; public interface MultiValueMap extends Map>, Serializable { // remove(K, V) conflicts with a Map method added in 1.8. http://b/27426743 /*public Object remove( K key, V item );*/ } java/gov/nist/core/MultiValueMapImpl.java0100644 0000000 0000000 00000011041 13513104763 017440 0ustar000000000 0000000 /* * 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.core; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; public class MultiValueMapImpl implements MultiValueMap, Cloneable { private HashMap> map = new HashMap>(); private static final long serialVersionUID = 4275505380960964605L; public MultiValueMapImpl() { super(); } public List put(String key, V value) { ArrayList keyList = map.get(key); if (keyList == null) { keyList = new ArrayList(10); map.put(key, keyList); } keyList.add(value); return keyList; } public boolean containsValue(Object value) { Set pairs = map.entrySet(); if (pairs == null) return false; Iterator pairsIterator = pairs.iterator(); while (pairsIterator.hasNext()) { Map.Entry keyValuePair = (Map.Entry) (pairsIterator.next()); ArrayList list = (ArrayList) (keyValuePair.getValue()); if (list.contains(value)) return true; } return false; } public void 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() { ArrayList returnList = new ArrayList(map.size()); Set pairs = map.entrySet(); Iterator pairsIterator = pairs.iterator(); while (pairsIterator.hasNext()) { Map.Entry keyValuePair = (Map.Entry) (pairsIterator.next()); ArrayList list = (ArrayList) (keyValuePair.getValue()); Object[] values = list.toArray(); for (int ii = 0; ii < values.length; ii++) { returnList.add(values[ii]); } } return returnList; } public Object clone() { MultiValueMapImpl obj = new MultiValueMapImpl(); obj.map = (HashMap>) this.map.clone(); return obj; } public int size() { return this.map.size(); } public boolean containsKey(Object key) { return map.containsKey(key); } public Set entrySet() { return map.entrySet(); } public boolean isEmpty() { return map.isEmpty(); } public Set keySet() { return this.map.keySet(); } // remove(K, V) conflicts with a Map method added in 1.8. http://b/27426743 /*public Object remove(String key, V item) { ArrayList list = this.map.get(key); if (list == null) { return null; } else { return list.remove(item); } }*/ public List get(Object key) { return map.get(key); } public List put(String key, List value) { return this.map.put(key,(ArrayList) value); } public List remove(Object key) { return map.remove(key); } public void putAll(Map< ? extends String, ? extends List> mapToPut) { for (String k : mapToPut.keySet()) { ArrayList al = new ArrayList(); al.addAll(mapToPut.get(k)); this.map.put(k, al); } } } java/gov/nist/core/NameValue.java0100644 0000000 0000000 00000021044 13513104763 015752 0ustar000000000 0000000 /* * 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.util.Map.Entry; /* * Bug reports and fixes: Kirby Kiem, Jeroen van Bemmel. */ /** * Generic structure for storing name-value pairs. * * @version 1.2 * * @author M. Ranganathan
* * * */ public class NameValue extends GenericObject implements Entry { private static final long serialVersionUID = -1857729012596437950L; protected boolean isQuotedString; protected final boolean isFlagParameter; private String separator; private String quotes; private String name; private Object value; public NameValue() { name = null; value = ""; separator = Separators.EQUALS; this.quotes = ""; this.isFlagParameter = false; } /** * New constructor, taking a boolean which is set if the NV pair is a flag * * @param n * @param v * @param isFlag */ public NameValue(String n, Object v, boolean isFlag) { // assert (v != null ); // I dont think this assertion is correct mranga name = n; value = v; separator = Separators.EQUALS; quotes = ""; this.isFlagParameter = isFlag; } /** * Original constructor, sets isFlagParameter to 'false' * * @param n * @param v */ public NameValue(String n, Object v) { this(n, v, false); } /** * Set the separator for the encoding method below. */ public void setSeparator(String sep) { separator = sep; } /** * A flag that indicates that doublequotes should be put around the value * when encoded (for example name=value when value is doublequoted). */ public void setQuotedValue() { isQuotedString = true; this.quotes = Separators.DOUBLE_QUOTE; } /** * Return true if the value is quoted in doublequotes. */ public boolean isValueQuoted() { return isQuotedString; } public String getName() { return name; } public Object getValueAsObject() { return isFlagParameter ? "" : value; // never return null for flag // params } /** * Set the name member */ public void setName(String n) { name = n; } /** * Set the value member */ public void setValueAsObject(Object v) { value = v; } /** * Get the encoded representation of this namevalue object. Added * doublequote for encoding doublequoted values. * * Bug: RFC3261 stipulates that an opaque parameter in authenticate header * has to be: * opaque = "opaque" EQUAL quoted-string * so returning just the name is not acceptable. (e.g. LinkSys phones * are picky about this) * * @since 1.0 * @return an encoded name value (eg. name=value) string. */ public String encode() { return encode(new StringBuffer()).toString(); } public StringBuffer encode(StringBuffer buffer) { if (name != null && value != null && !isFlagParameter) { if (GenericObject.isMySubclass(value.getClass())) { GenericObject gv = (GenericObject) value; buffer.append(name).append(separator).append(quotes); gv.encode(buffer); buffer.append(quotes); return buffer; } else if (GenericObjectList.isMySubclass(value.getClass())) { GenericObjectList gvlist = (GenericObjectList) value; buffer.append(name).append(separator).append(gvlist.encode()); return buffer; } else if ( value.toString().length() == 0) { // opaque="" bug fix - pmusgrave /*if (name.toString().equals(gov.nist.javax.sip.header.ParameterNames.OPAQUE)) return name + separator + quotes + quotes; else return name;*/ if ( this.isQuotedString ) { buffer.append(name).append(separator).append(quotes).append(quotes); return buffer; } else { buffer.append(name).append(separator); // JvB: fix, case: "sip:host?subject=" return buffer; } } else { buffer.append(name).append(separator).append(quotes).append(value.toString()).append(quotes); return buffer; } } else if (name == null && value != null) { if (GenericObject.isMySubclass(value.getClass())) { GenericObject gv = (GenericObject) value; gv.encode(buffer); return buffer; } else if (GenericObjectList.isMySubclass(value.getClass())) { GenericObjectList gvlist = (GenericObjectList) value; buffer.append(gvlist.encode()); return buffer; } else { buffer.append(quotes).append(value.toString()).append(quotes); return buffer; } } else if (name != null && (value == null || isFlagParameter)) { buffer.append(name); return buffer; } else { return buffer; } } public Object clone() { NameValue retval = (NameValue) super.clone(); if (value != null) retval.value = makeClone(value); return retval; } /** * Equality comparison predicate. */ public boolean equals(Object other) { if (other == null ) return false; if (!other.getClass().equals(this.getClass())) return false; NameValue that = (NameValue) other; if (this == that) return true; if (this.name == null && that.name != null || this.name != null && that.name == null) return false; if (this.name != null && that.name != null && this.name.compareToIgnoreCase(that.name) != 0) return false; if (this.value != null && that.value == null || this.value == null && that.value != null) return false; if (this.value == that.value) return true; if (value instanceof String) { // Quoted string comparisions are case sensitive. if (isQuotedString) return this.value.equals(that.value); String val = (String) this.value; String val1 = (String) that.value; return val.compareToIgnoreCase(val1) == 0; } else return this.value.equals(that.value); } /* * (non-Javadoc) * @see java.util.Map$Entry#getKey() */ public String getKey() { return this.name; } /* * (non-Javadoc) * @see java.util.Map$Entry#getValue() */ public String getValue() { return value == null ? null : this.value.toString(); } /* * (non-Javadoc) * @see java.util.Map$Entry#setValue(java.lang.Object) */ public String setValue(String value) { String retval = this.value == null ? null : value; this.value = value; return retval; } @Override public int hashCode() { return this.encode().toLowerCase().hashCode(); } } java/gov/nist/core/NameValueList.java0100644 0000000 0000000 00000022262 13513104763 016611 0ustar000000000 0000000 /* * 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.util.concurrent.*; import java.io.Serializable; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; /** * Implements a simple NameValue association with a quick lookup function (via a * hash map) the default behavior for this class is not thread safe. * specify a constructor with boolean true to make this thread safe. * * @version 1.2 * * @author M. Ranganathan
* * * */ public class NameValueList implements Serializable, Cloneable, Map { private static final long serialVersionUID = -6998271876574260243L; private Map hmap; private String separator; /** * default constructor. */ public NameValueList() { this.separator = ";"; this.hmap = new LinkedHashMap(); } public NameValueList(boolean sync) { this.separator = ";"; if (sync) this.hmap = new ConcurrentHashMap(); else this.hmap = new LinkedHashMap(); } public void setSeparator(String separator) { this.separator = separator; } /** * Encode the list in semicolon separated form. * * @return an encoded string containing the objects in this list. * @since v1.0 */ public String encode() { return encode(new StringBuffer()).toString(); } public StringBuffer encode(StringBuffer buffer) { if (!hmap.isEmpty()) { Iterator iterator = hmap.values().iterator(); if (iterator.hasNext()) { while (true) { Object obj = iterator.next(); if (obj instanceof GenericObject) { GenericObject gobj = (GenericObject) obj; gobj.encode(buffer); } else { buffer.append(obj.toString()); } if (iterator.hasNext()) buffer.append(separator); else break; } } } return buffer; } public String toString() { return this.encode(); } /** * Set a namevalue object in this list. */ public void set(NameValue nv) { this.hmap.put(nv.getName().toLowerCase(), nv); } /** * Set a namevalue object in this list. */ public void set(String name, Object value) { NameValue nameValue = new NameValue(name, value); hmap.put(name.toLowerCase(), nameValue); } /** * Compare if two NameValue lists are equal. * * @param otherObject * is the object to compare to. * @return true if the two objects compare for equality. */ public boolean equals(Object otherObject) { if ( otherObject == null ) { return false; } if (!otherObject.getClass().equals(this.getClass())) { return false; } NameValueList other = (NameValueList) otherObject; if (hmap.size() != other.hmap.size()) { return false; } Iterator li = this.hmap.keySet().iterator(); while (li.hasNext()) { String key = (String) li.next(); NameValue nv1 = this.getNameValue(key); NameValue nv2 = (NameValue) other.hmap.get(key); if (nv2 == null) return false; else if (!nv2.equals(nv1)) return false; } return true; } /** * Do a lookup on a given name and return value associated with it. */ public Object getValue(String name) { NameValue nv = this.getNameValue(name.toLowerCase()); if (nv != null) return nv.getValueAsObject(); else return null; } /** * Get the NameValue record given a name. * * @since 1.0 */ public NameValue getNameValue(String name) { return (NameValue) this.hmap.get(name.toLowerCase()); } /** * Returns a boolean telling if this NameValueList has a record with this * name * * @since 1.0 */ public boolean hasNameValue(String name) { return hmap.containsKey(name.toLowerCase()); } /** * Remove the element corresponding to this name. * * @since 1.0 */ public boolean delete(String name) { String lcName = name.toLowerCase(); if (this.hmap.containsKey(lcName)) { this.hmap.remove(lcName); return true; } else { return false; } } public Object clone() { NameValueList retval = new NameValueList(); retval.setSeparator(this.separator); Iterator it = this.hmap.values().iterator(); while (it.hasNext()) { retval.set((NameValue) ((NameValue) it.next()).clone()); } return retval; } /** * Return the size of the embedded map */ public int size() { return this.hmap.size(); } /** * Return true if empty. */ public boolean isEmpty() { return hmap.isEmpty(); } /** * Return an iterator for the name-value pairs of this list. * * @return the iterator. */ public Iterator iterator() { return this.hmap.values().iterator(); } /** * Get a list of parameter names. * * @return a list iterator that has the names of the parameters. */ public Iterator getNames() { return this.hmap.keySet().iterator(); } /** * Get the parameter as a String. * * @return the parameter as a string. */ public String getParameter(String name) { Object val = this.getValue(name); if (val == null) return null; if (val instanceof GenericObject) return ((GenericObject) val).encode(); else return val.toString(); } /* * (non-Javadoc) * @see java.util.Map#clear() */ public void clear() { this.hmap.clear(); } /* * (non-Javadoc) * @see java.util.Map#containsKey(java.lang.Object) */ public boolean containsKey(Object key) { return this.hmap.containsKey(key.toString().toLowerCase()); } /* * (non-Javadoc) * @see java.util.Map#containsValue(java.lang.Object) */ public boolean containsValue(Object value) { return this.hmap.containsValue(value); } /* * (non-Javadoc) * @see java.util.Map#entrySet() */ public Set> entrySet() { return this.hmap.entrySet(); } /* * (non-Javadoc) * @see java.util.Map#get(java.lang.Object) */ public NameValue get(Object key) { return this.hmap.get(key.toString().toLowerCase()); } /* * (non-Javadoc) * @see java.util.Map#keySet() */ public Set keySet() { return this.hmap.keySet(); } /* * (non-Javadoc) * @see java.util.Map#put(java.lang.Object, java.lang.Object) */ public NameValue put(String name, NameValue nameValue) { return this.hmap.put(name, nameValue); } public void putAll(Map map) { this.hmap.putAll(map); } /* * (non-Javadoc) * @see java.util.Map#remove(java.lang.Object) */ public NameValue remove(Object key) { return this.hmap.remove(key.toString().toLowerCase()); } /* * (non-Javadoc) * @see java.util.Map#values() */ public Collection values() { return this.hmap.values(); } @Override public int hashCode() { return this.hmap.keySet().hashCode(); } } java/gov/nist/core/PackageNames.java0100644 0000000 0000000 00000004370 13513104763 016417 0ustar000000000 0000000 /* * 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; /** * Names for the packages that are referenced herein. * *@version 1.2 * *@author M. Ranganathan
* * * */ public interface PackageNames { public static final String JAIN_HEADER_PACKAGE = "javax.sip.header"; public static final String JAIN_PACKAGE = "javax.sip"; public static final String SIPHEADERS_PACKAGE = "gov.nist.javax.sip.header"; public static final String PARSER_PACKAGE = "gov.nist.javax.sip.parser"; public static final String NET_PACKAGE = "gov.nist.javax.sip.address"; public static final String SIP_PACKAGE = "gov.nist.javax.sip"; public static final String STACK_PACKAGE = "gov.nist.javax.sip.stack"; public static final String CORE_PACKAGE = "gov.nist.core"; public static final String MESSAGE_PACKAGE = "gov.nist.javax.sip.message"; // SDP packages public static final String SDP_PACKAGE = "gov.nist.javax.sdp"; public static final String SDP_PARSER_PACKAGE = SDP_PACKAGE + ".parser"; } java/gov/nist/core/ParserCore.java0100644 0000000 0000000 00000007656 13513104763 016157 0ustar000000000 0000000 /* * 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.core; import java.text.ParseException; /** Generic parser class. * All parsers inherit this class. * *@version 1.2 * *@author M. Ranganathan
* * * */ public abstract class ParserCore { public static final boolean debug = Debug.parserDebug; static int nesting_level; protected LexerCore lexer; protected NameValue nameValue(char separator) throws ParseException { if (debug) dbg_enter("nameValue"); try { lexer.match(LexerCore.ID); Token name = lexer.getNextToken(); // eat white space. lexer.SPorHT(); try { boolean quoted = false; char la = lexer.lookAhead(0); if (la == separator ) { lexer.consume(1); lexer.SPorHT(); String str = null; boolean isFlag = false; if (lexer.lookAhead(0) == '\"') { str = lexer.quotedString(); quoted = true; } else { lexer.match(LexerCore.ID); Token value = lexer.getNextToken(); str = value.tokenValue; // JvB: flag parameters must be empty string! if (str==null) { str = ""; isFlag = true; } } NameValue nv = new NameValue(name.tokenValue,str,isFlag); if (quoted) nv.setQuotedValue(); return nv; } else { // JvB: flag parameters must be empty string! return new NameValue(name.tokenValue,"",true); } } catch (ParseException ex) { return new NameValue(name.tokenValue,null,false); } } finally { if (debug) dbg_leave("nameValue"); } } protected void dbg_enter(String rule) { StringBuffer stringBuffer = new StringBuffer(); for (int i = 0; i < nesting_level ; i++) stringBuffer.append(">"); if (debug) { System.out.println( stringBuffer + rule + "\nlexer buffer = \n" + lexer.getRest()); } nesting_level++; } protected void dbg_leave(String rule) { StringBuffer stringBuffer = new StringBuffer(); for (int i = 0; i < nesting_level ; i++) stringBuffer.append("<"); if (debug) { System.out.println( stringBuffer + rule + "\nlexer buffer = \n" + lexer.getRest()); } nesting_level --; } protected NameValue nameValue() throws ParseException { return nameValue('='); } protected void peekLine(String rule) { if (debug) { Debug.println(rule +" " + lexer.peekLine()); } } } java/gov/nist/core/Separators.java0100644 0000000 0000000 00000004212 13513104763 016216 0ustar000000000 0000000 /* * 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.core; /** Separators. * *@version 1.2 * *@author M. Ranganathan
* * * */ public interface Separators { public static final String SEMICOLON = ";"; public static final String COLON = ":"; public static final String COMMA = ","; public static final String SLASH = "/"; public static final String SP = " "; public static final String EQUALS = "="; public static final String STAR = "*"; public static final String NEWLINE = "\r\n"; public static final String RETURN = "\n"; public static final String LESS_THAN = "<"; public static final String GREATER_THAN = ">"; public static final String AT = "@"; public static final String DOT = "."; public static final String QUESTION = "?"; public static final String POUND = "#"; public static final String AND = "&"; public static final String LPAREN = "("; public static final String RPAREN = ")"; public static final String DOUBLE_QUOTE = "\""; public static final String QUOTE = "\'"; public static final String HT = "\t"; public static final String PERCENT = "%"; } java/gov/nist/core/ServerLogger.java0100644 0000000 0000000 00000002724 13513104763 016507 0ustar000000000 0000000 /* * JBoss, Home of Professional Open Source. * * This code has been contributed to the public domain. * 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.core; import java.util.Properties; import javax.sip.SipStack; import gov.nist.javax.sip.message.SIPMessage; /** * @author jean.deruelle@gmail.com * */ public interface ServerLogger extends LogLevels { void closeLogFile(); void logMessage(SIPMessage message, String from, String to, boolean sender, long time); void logMessage(SIPMessage message, String from, String to, String status, boolean sender, long time); void logMessage(SIPMessage message, String from, String to, String status, boolean sender); void logException(Exception ex); public void setStackProperties(Properties stackProperties); public void setSipStack(SipStack sipStack); } java/gov/nist/core/StackLogger.java0100644 0000000 0000000 00000005250 13513104763 016303 0ustar000000000 0000000 package gov.nist.core; import java.util.Properties; /** * interface that loggers should implement so that the stack can log to various * loggers impl such as log4j, commons logging, sl4j, ... * @author jean.deruelle@gmail.com * */ public interface StackLogger extends LogLevels { /** * log a stack trace. This helps to look at the stack frame. */ public void logStackTrace(); /** * Log a stack trace if the current logging level exceeds * given trace level. * @param traceLevel */ public void logStackTrace(int traceLevel); /** * Get the line count in the log stream. * * @return */ public int getLineCount(); /** * Log an exception. * * @param ex */ public void logException(Throwable ex); /** * Log a message into the log file. * * @param message * message to log into the log file. */ public void logDebug(String message); /** * Log a message into the log file. * * @param message * message to log into the log file. */ public void logTrace(String message); /** * Log an error message. * * @param message -- * error message to log. */ public void logFatalError(String message); /** * Log an error message. * * @param message -- * error message to log. * */ public void logError(String message); /** * @return flag to indicate if logging is enabled. */ public boolean isLoggingEnabled(); /** * Return true/false if loging is enabled at a given level. * * @param logLevel */ public boolean isLoggingEnabled(int logLevel); /** * Log an error message. * * @param message * @param ex */ public void logError(String message, Exception ex); /** * Log a warning mesasge. * * @param string */ public void logWarning(String string); /** * Log an info message. * * @param string */ public void logInfo(String string); /** * Disable logging altogether. * */ public void disableLogging(); /** * Enable logging (globally). */ public void enableLogging(); /** * Set the build time stamp. This is logged into the logging stream. */ public void setBuildTimeStamp(String buildTimeStamp); /** * Stack creation properties. * @param stackProperties */ public void setStackProperties(Properties stackProperties); /** * The category for the logger. * @return */ public String getLoggerName(); } java/gov/nist/core/StringTokenizer.java0100644 0000000 0000000 00000012231 13513104763 017234 0ustar000000000 0000000 /* * 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.core; import java.util.*; import java.text.ParseException; /** Base string token splitter. * *@version 1.2 * *@author M. Ranganathan
* * * */ public class StringTokenizer { protected String buffer; protected int bufferLen; protected int ptr; protected int savedPtr; protected StringTokenizer() { } public StringTokenizer(String buffer) { this.buffer = buffer; bufferLen = buffer.length(); ptr = 0; } public String nextToken() { int startIdx = ptr; while (ptr < bufferLen) { char c = buffer.charAt(ptr); ptr++; if (c == '\n') { break; } } return buffer.substring(startIdx, ptr); } public boolean hasMoreChars() { return ptr < bufferLen; } public static boolean isHexDigit(char ch) { return (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f') || isDigit(ch); } public static boolean isAlpha(char ch) { if (ch <= 127) { return ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')); } else { return Character.isLowerCase(ch) || Character.isUpperCase(ch); } } public static boolean isDigit(char ch) { if (ch <= 127) { return (ch <= '9' && ch >= '0'); } else { return Character.isDigit(ch); } } public static boolean isAlphaDigit(char ch) { if (ch <= 127) { return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch <= '9' && ch >= '0'); } else { return Character.isLowerCase(ch) || Character.isUpperCase(ch) || Character.isDigit(ch); } } public String getLine() { int startIdx = ptr; while (ptr < bufferLen && buffer.charAt(ptr) != '\n') { ptr++; } if (ptr < bufferLen && buffer.charAt(ptr) == '\n') { ptr++; } return buffer.substring(startIdx, ptr); } public String peekLine() { int curPos = ptr; String retval = this.getLine(); ptr = curPos; return retval; } public char lookAhead() throws ParseException { return lookAhead(0); } public char lookAhead(int k) throws ParseException { // Debug.out.println("ptr = " + ptr); try { return buffer.charAt(ptr + k); } catch (IndexOutOfBoundsException e) { return '\0'; } } public char getNextChar() throws ParseException { if (ptr >= bufferLen) throw new ParseException( buffer + " getNextChar: End of buffer", ptr); else return buffer.charAt(ptr++); } public void consume() { ptr = savedPtr; } public void consume(int k) { ptr += k; } /** Get a Vector of the buffer tokenized by lines */ public Vector getLines() { Vector result = new Vector(); while (hasMoreChars()) { String line = getLine(); result.addElement(line); } return result; } /** Get the next token from the buffer. */ public String getNextToken(char delim) throws ParseException { int startIdx = ptr; while (true) { char la = lookAhead(0); if (la == delim) break; else if (la == '\0') throw new ParseException("EOL reached", 0); consume(1); } return buffer.substring(startIdx, ptr); } /** get the SDP field name of the line * @return String */ public static String getSDPFieldName(String line) { if (line == null) return null; String fieldName = null; try { int begin = line.indexOf("="); fieldName = line.substring(0, begin); } catch (IndexOutOfBoundsException e) { return null; } return fieldName; } } java/gov/nist/core/ThreadAuditor.java0100644 0000000 0000000 00000016041 13513104763 016635 0ustar000000000 0000000 package gov.nist.core; import java.util.*; /** * Thread Auditor class: * - Provides a mechanism for applications to check the health of internal threads * - The mechanism is fairly simple: * - Threads register with the auditor at startup and "ping" the auditor every so often. * - The application queries the auditor about the health of the system periodically. The * auditor reports if the threads are healthy or if any of them failed to ping and are * considered dead or stuck. * - The main implication for the monitored threads is that they can no longer block * waiting for an event forever. Any wait() must be implemented with a timeout so that * the thread can periodically ping the auditor. * * This code is in the public domain. * * @author R. Borba (Natural Convergence)
* @version 1.2 */ public class ThreadAuditor { /// Threads being monitored private Map threadHandles = new HashMap(); /// How often are threads supposed to ping private long pingIntervalInMillisecs = 0; /// Internal class, used as a handle by the monitored threads public class ThreadHandle { /// Set to true when the thread pings, periodically reset to false by the auditor private boolean isThreadActive; /// Thread being monitored private Thread thread; /// Thread auditor monitoring this thread private ThreadAuditor threadAuditor; /// Constructor public ThreadHandle(ThreadAuditor aThreadAuditor) { isThreadActive = false; thread = Thread.currentThread(); threadAuditor = aThreadAuditor; } /// Called by the auditor thread to check the ping status of the thread public boolean isThreadActive() { return isThreadActive; } /// Called by the auditor thread to reset the ping status of the thread protected void setThreadActive(boolean value) { isThreadActive = value; } /// Return the thread being monitored public Thread getThread() { return thread; } // Helper function to allow threads to ping using this handle public void ping() { threadAuditor.ping(this); } // Helper function to allow threads to get the ping interval directly from this handle public long getPingIntervalInMillisecs() { return threadAuditor.getPingIntervalInMillisecs(); } /** * Returns a string representation of the object * * @return a string representation of the object */ public String toString() { StringBuffer toString = new StringBuffer() .append("Thread Name: ").append(thread.getName()) .append(", Alive: ").append(thread.isAlive()); return toString.toString(); } } /// Indicates how often monitored threads are supposed to ping (0 = no thread monitoring) public long getPingIntervalInMillisecs() { return pingIntervalInMillisecs; } /// Defines how often monitored threads are supposed to ping public void setPingIntervalInMillisecs(long value) { pingIntervalInMillisecs = value; } /// Indicates if the auditing of threads is enabled public boolean isEnabled() { return (pingIntervalInMillisecs > 0); } /// Called by a thread that wants to be monitored 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); if (isEnabled()) { threadHandles.put(Thread.currentThread(), threadHandle); } return threadHandle; } /// Stops monitoring a given thread public synchronized void removeThread(Thread thread) { threadHandles.remove(thread); } /// Called by a monitored thread reporting that it's alive and well public synchronized void ping(ThreadHandle threadHandle) { threadHandle.setThreadActive(true); } /// Resets the auditor public synchronized void reset() { threadHandles.clear(); } /** * Audits the sanity of all threads * * @return An audit report string (multiple lines), or null if all is well */ public synchronized String auditThreads() { String auditReport = null; // Map stackTraces = null; // Scan all monitored threads looking for non-responsive ones Iterator it = threadHandles.values().iterator(); while (it.hasNext()) { ThreadHandle threadHandle = (ThreadHandle) it.next(); if (!threadHandle.isThreadActive()) { // Get the non-responsive thread Thread thread = threadHandle.getThread(); // Update the audit report if (auditReport == null) { auditReport = "Thread Auditor Report:\n"; } auditReport += " Thread [" + thread.getName() + "] has failed to respond to an audit request.\n"; /* * Stack traces are not available with JDK 1.4. * Feel free to uncomment this block to get a better report if you're using JDK 1.5. */ // // Get stack traces for all live threads (do this only once per audit) // if (stackTraces == null) { // stackTraces = Thread.getAllStackTraces(); // } // // // Get the stack trace for the non-responsive thread // StackTraceElement[] stackTraceElements = (StackTraceElement[])stackTraces.get(thread); // if (stackTraceElements != null && stackTraceElements.length > 0) { // auditReport += " Stack trace:\n"; // // for (int i = 0; i < stackTraceElements.length ; i ++ ) { // StackTraceElement stackTraceElement = stackTraceElements[i]; // auditReport += " " + stackTraceElement.toString() + "\n"; // } // } else { // auditReport += " Stack trace is not available.\n"; // } } // Reset the ping status of the thread threadHandle.setThreadActive(false); } return auditReport; } /** * Returns a string representation of the object * * @return a string representation of the object */ public synchronized String toString() { String toString = "Thread Auditor - List of monitored threads:\n"; Iterator it = threadHandles.values().iterator(); while ( it.hasNext()) { ThreadHandle threadHandle = (ThreadHandle)it.next(); toString += " " + threadHandle.toString() + "\n"; } return toString; } } java/gov/nist/core/Token.java0100644 0000000 0000000 00000002752 13513104763 015162 0ustar000000000 0000000 /* * 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.core; /** * Base token class. * @version 1.2 * * @author M. Ranganathan
* * */ public class Token { protected String tokenValue; protected int tokenType; public String getTokenValue() { return this.tokenValue; } public int getTokenType() { return this.tokenType; } public String toString() { return "tokenValue = " + tokenValue + "/tokenType = " + tokenType; } } java/gov/nist/core/net/0040755 0000000 0000000 00000000000 13513104763 014022 5ustar000000000 0000000 java/gov/nist/core/net/AddressResolver.java0100644 0000000 0000000 00000004467 13513104763 020004 0ustar000000000 0000000 /* * 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.core.net; import java.net.InetAddress; import java.net.UnknownHostException; import javax.sip.address.Hop; /** * An interface that allows you to customize address lookup. * The user can implement this interface to do DNS lookups or other lookup * schemes and register it with the stack. * The default implementation of the address resolver does nothing more than just return back * the Hop that it was passed (fixing up the port if necessary). * However, this behavior can be overriden. To override * implement this interface and register it with the stack using * {@link gov.nist.javax.sip.SipStackExt#setAddressResolver(AddressResolver)}. * This interface will be incorporated into version 2.0 of the JAIN-SIP Specification. * * @since 2.0 * * * @author M. Ranganathan * */ public interface AddressResolver { /** * Do a name lookup and resolve the given IP address. * The default implementation is just an identity mapping * (returns the argument). * * @param hop - an incoming Hop containing a potenitally unresolved address. * @return a new hop ( if the address is recomputed ) or the original hop * if this is just an identity mapping ( the default behavior ). */ public Hop resolveAddress( Hop hop); } java/gov/nist/core/net/DefaultNetworkLayer.java0100644 0000000 0000000 00000013143 13513104763 020617 0ustar000000000 0000000 /* * 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.core.net; import java.io.IOException; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.MulticastSocket; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; /* Added by Daniel J. Martinez Manzano */ import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.SSLServerSocket; import javax.net.ssl.SSLServerSocketFactory; /** * default implementation which passes straight through to java platform * * @author m.andrews * @version 1.2 * @since 1.1 * */ public class DefaultNetworkLayer implements NetworkLayer { private SSLSocketFactory sslSocketFactory; private SSLServerSocketFactory sslServerSocketFactory; /** * single default network layer; for flexibility, it may be better not to * make it a singleton, but singleton seems to make sense currently. */ public static final DefaultNetworkLayer SINGLETON = new DefaultNetworkLayer(); private DefaultNetworkLayer() { sslServerSocketFactory = (SSLServerSocketFactory) SSLServerSocketFactory .getDefault(); sslSocketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault(); } public ServerSocket createServerSocket(int port, int backlog, InetAddress bindAddress) throws IOException { return new ServerSocket(port, backlog, bindAddress); } public Socket createSocket(InetAddress address, int port) throws IOException { return new Socket(address, port); } public DatagramSocket createDatagramSocket() throws SocketException { return new DatagramSocket(); } public DatagramSocket createDatagramSocket(int port, InetAddress laddr) throws SocketException { if ( laddr.isMulticastAddress() ) { try { MulticastSocket ds = new MulticastSocket( port ); ds.joinGroup( laddr ); return ds; } catch (IOException e) { throw new SocketException( e.getLocalizedMessage() ); } } else return new DatagramSocket(port, laddr); } /* Added by Daniel J. Martinez Manzano */ public SSLServerSocket createSSLServerSocket(int port, int backlog, InetAddress bindAddress) throws IOException { return (SSLServerSocket) sslServerSocketFactory.createServerSocket( port, backlog, bindAddress); } /* Added by Daniel J. Martinez Manzano */ public SSLSocket createSSLSocket(InetAddress address, int port) throws IOException { return (SSLSocket) sslSocketFactory.createSocket(address, port); } /* Added by Daniel J. Martinez Manzano */ public SSLSocket createSSLSocket(InetAddress address, int port, InetAddress myAddress) throws IOException { return (SSLSocket) sslSocketFactory.createSocket(address, port, myAddress, 0); } 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); } /** * Creates a new Socket, binds it to myAddress:myPort and connects it to * address:port. * * @param address the InetAddress that we'd like to connect to. * @param port the port that we'd like to connect to * @param myAddress the address that we are supposed to bind on or null * for the "any" address. * @param myPort the port that we are supposed to bind on or 0 for a random * one. * * @return a new Socket, bound on myAddress:myPort and connected to * address:port. * @throws IOException if binding or connecting the socket fail for a reason * (exception relayed from the correspoonding Socket methods) */ public Socket createSocket(InetAddress address, int port, InetAddress myAddress, int myPort) throws IOException { if (myAddress != null) return new Socket(address, port, myAddress, myPort); else if (port != 0) { //myAddress is null (i.e. any) but we have a port number Socket sock = new Socket(); sock.bind(new InetSocketAddress(port)); sock.connect(new InetSocketAddress(address, port)); return sock; } else return new Socket(address, port); } } java/gov/nist/core/net/NetworkLayer.java0100644 0000000 0000000 00000012307 13513104763 017313 0ustar000000000 0000000 /* * 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.core.net; import java.io.IOException; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; // Added by Daniel J. Martinez Manzano import javax.net.ssl.SSLServerSocket; import javax.net.ssl.SSLSocket; /** * basic interface to the network layer * * @author m.andrews * */ public interface NetworkLayer { /** * Creates a server with the specified port, listen backlog, and local IP address to bind to. * comparable to "new java.net.ServerSocket(port,backlog,bindAddress);" * * @param port * @param backlog * @param bindAddress * @return the server socket */ public ServerSocket createServerSocket(int port, int backlog, InetAddress bindAddress) throws IOException; /** * Creates an SSL server with the specified port, listen backlog, and local IP address to bind to. * Added by Daniel J. Martinez Manzano * * @param port * @param backlog * @param bindAddress * @return the server socket */ public SSLServerSocket createSSLServerSocket(int port, int backlog, InetAddress bindAddress) throws IOException; /** * Creates a stream socket and connects it to the specified port number at the specified IP address. * comparable to "new java.net.Socket(address, port);" * * @param address * @param port * @return the socket */ public Socket createSocket(InetAddress address, int port) throws IOException; /** * Creates a stream socket and connects it to the specified port number at the specified IP address. * comparable to "new java.net.Socket(address, port,localaddress);" * * @param address * @param port * @param localAddress * @return the socket */ public Socket createSocket(InetAddress address, int port, InetAddress localAddress) throws IOException; /** * Creates a new Socket, binds it to myAddress:myPort and connects it to * address:port. * * @param address the InetAddress that we'd like to connect to. * @param port the port that we'd like to connect to * @param myAddress the address that we are supposed to bind on or null * for the "any" address. * @param myPort the port that we are supposed to bind on or 0 for a random * one. * * @return a new Socket, bound on myAddress:myPort and connected to * address:port. * @throws IOException if binding or connecting the socket fail for a reason * (exception relayed from the correspoonding Socket methods) */ public Socket createSocket(InetAddress address, int port, InetAddress myAddress, int myPort) throws IOException; /** * Creates a stream SSL socket and connects it to the specified port number at the specified IP address. * Added by Daniel J. Martinez Manzano * * @param address * @param port * @return the socket */ public SSLSocket createSSLSocket(InetAddress address, int port) throws IOException; /** * Creates a stream SSL socket and connects it to the specified port number at the specified IP address. * Added by Daniel J. Martinez Manzano * * @param address * @param port * @param localAddress -- my address. * @return the socket */ public SSLSocket createSSLSocket(InetAddress address, int port, InetAddress localAddress) throws IOException; /** * Constructs a datagram socket and binds it to any available port on the local host machine. * comparable to "new java.net.DatagramSocket();" * * @return the datagram socket */ public DatagramSocket createDatagramSocket() throws SocketException; /** * Creates a datagram socket, bound to the specified local address. * comparable to "new java.net.DatagramSocket(port,laddr);" * * @param port * @param laddr * @return the datagram socket */ public DatagramSocket createDatagramSocket(int port, InetAddress laddr) throws SocketException; } java/gov/nist/core/net/SslNetworkLayer.java0100644 0000000 0000000 00000014660 13513104763 020001 0ustar000000000 0000000 /* * 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.core.net; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; import java.security.GeneralSecurityException; import java.security.KeyStore; import java.security.SecureRandom; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLServerSocket; import javax.net.ssl.SSLServerSocketFactory; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManagerFactory; /** * extended implementation of a network layer that allows to define a private java * keystores/truststores * * @author f.reif * @version 1.2 * @since 1.2 * */ public class SslNetworkLayer implements NetworkLayer { private SSLSocketFactory sslSocketFactory; private SSLServerSocketFactory sslServerSocketFactory; public SslNetworkLayer( String trustStoreFile, String keyStoreFile, char[] keyStorePassword, String keyStoreType) throws GeneralSecurityException, FileNotFoundException, IOException { SSLContext sslContext; sslContext = SSLContext.getInstance("TLS"); String algorithm = KeyManagerFactory.getDefaultAlgorithm(); TrustManagerFactory tmFactory = TrustManagerFactory.getInstance(algorithm); KeyManagerFactory kmFactory = KeyManagerFactory.getInstance(algorithm); SecureRandom secureRandom = new SecureRandom(); secureRandom.nextInt(); KeyStore keyStore = KeyStore.getInstance(keyStoreType); KeyStore trustStore = KeyStore.getInstance(keyStoreType); keyStore.load(new FileInputStream(keyStoreFile), keyStorePassword); trustStore.load(new FileInputStream(trustStoreFile), keyStorePassword); tmFactory.init(trustStore); kmFactory.init(keyStore, keyStorePassword); sslContext.init(kmFactory.getKeyManagers(), tmFactory.getTrustManagers(), secureRandom); sslServerSocketFactory = sslContext.getServerSocketFactory(); sslSocketFactory = sslContext.getSocketFactory(); } public ServerSocket createServerSocket(int port, int backlog, InetAddress bindAddress) throws IOException { return new ServerSocket(port, backlog, bindAddress); } public Socket createSocket(InetAddress address, int port) throws IOException { return new Socket(address, port); } public DatagramSocket createDatagramSocket() throws SocketException { return new DatagramSocket(); } public DatagramSocket createDatagramSocket(int port, InetAddress laddr) throws SocketException { return new DatagramSocket(port, laddr); } /* Added by Daniel J. Martinez Manzano */ public SSLServerSocket createSSLServerSocket(int port, int backlog, InetAddress bindAddress) throws IOException { return (SSLServerSocket) sslServerSocketFactory.createServerSocket( port, backlog, bindAddress); } /* Added by Daniel J. Martinez Manzano */ public SSLSocket createSSLSocket(InetAddress address, int port) throws IOException { return (SSLSocket) sslSocketFactory.createSocket(address, port); } /* Added by Daniel J. Martinez Manzano */ public SSLSocket createSSLSocket(InetAddress address, int port, InetAddress myAddress) throws IOException { return (SSLSocket) sslSocketFactory.createSocket(address, port, myAddress, 0); } 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); } /** * Creates a new Socket, binds it to myAddress:myPort and connects it to * address:port. * * @param address the InetAddress that we'd like to connect to. * @param port the port that we'd like to connect to * @param myAddress the address that we are supposed to bind on or null * for the "any" address. * @param myPort the port that we are supposed to bind on or 0 for a random * one. * * @return a new Socket, bound on myAddress:myPort and connected to * address:port. * @throws IOException if binding or connecting the socket fail for a reason * (exception relayed from the correspoonding Socket methods) */ public Socket createSocket(InetAddress address, int port, InetAddress myAddress, int myPort) throws IOException { if (myAddress != null) return new Socket(address, port, myAddress, myPort); else if (port != 0) { //myAddress is null (i.e. any) but we have a port number Socket sock = new Socket(); sock.bind(new InetSocketAddress(port)); sock.connect(new InetSocketAddress(address, port)); return sock; } else return new Socket(address, port); } } java/gov/nist/core/net/package.html0100644 0000000 0000000 00000000375 13513104763 016305 0ustar000000000 0000000 Contains the Network layer classes and interfaces. The network layer wraps the java.net. Socket classes and allows users low level monitoring and control over these objects. This feature was proposed by Mike Andrews . java/gov/nist/core/package.html0100644 0000000 0000000 00000000263 13513104763 015513 0ustar000000000 0000000 Contains core classes that the rest of the implementation depends upon. These include classes for basic parser and lexer functionality and logging functionality. java/gov/nist/javax/0040755 0000000 0000000 00000000000 13513104763 013415 5ustar000000000 0000000 java/gov/nist/javax/sip/0040755 0000000 0000000 00000000000 13513104763 014210 5ustar000000000 0000000 java/gov/nist/javax/sip/ClientTransactionExt.java0100644 0000000 0000000 00000003370 13513104763 021160 0ustar000000000 0000000 package gov.nist.javax.sip; import java.security.cert.Certificate; import java.security.cert.X509Certificate; import javax.net.ssl.SSLPeerUnverifiedException; import javax.sip.ClientTransaction; import javax.sip.Timeout; import javax.sip.address.Hop; public interface ClientTransactionExt extends ClientTransaction, TransactionExt { /** * Notify on retransmission from the client transaction side. The listener will get a * notification on retransmission when this flag is set. When set the client transaction * listener will get a Timeout.RETRANSMIT event on each retransmission. * * @param flag -- the flag that indicates whether or not notification is desired. * * @since 2.0 */ public void setNotifyOnRetransmit(boolean flag); /** * Send a transaction timeout event to the application if Tx is still in Calling state in the * given time period ( in base timer interval count ) after sending request. The stack will * start a timer and alert the application if the client transaction does not transition out * of the Trying state by the given interval. This is a "one shot" alert. * * @param count -- the number of base timer intervals after which an alert is issued. * * * @since 2.0 */ public void alertIfStillInCallingStateBy(int count); /** * Get the next hop that was computed by the routing layer. * when it sent out the request. This allows you to route requests * to the SAME destination if required ( for example if you get * an authentication challenge ). */ public Hop getNextHop(); /** * Return true if this Ctx is a secure transport. * */ public boolean isSecure(); } java/gov/nist/javax/sip/DefaultAddressResolver.java0100644 0000000 0000000 00000005210 13513104763 021462 0ustar000000000 0000000 /* * 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; import java.net.InetAddress; import java.net.UnknownHostException; import javax.sip.address.Hop; import gov.nist.core.net.AddressResolver; import gov.nist.javax.sip.stack.HopImpl; import gov.nist.javax.sip.stack.MessageProcessor; /** * This is the default implementation of the AddressResolver. The AddressResolver is a NIST-SIP specific * feature. The address resolover is consulted to convert a Hop into a meaningful address. The default * implementation is a passthrough. It only gets involved in setting the default port. However, you * can register your own AddressResolver implementation * Note that * The RI checks incoming via headers for resolving the sentBy field. If you want to set it to * some address that cannot be resolved you should register an AddressResolver with the stack. * This feature is also useful for DNS SRV lookup which is not implemented by the RI at present. * * @version 1.2 * @since 1.2 * @see gov.nist.javax.sip.SipStackImpl#setAddressResolver(AddressResolver) * * @author M. Ranganathan * */ public class DefaultAddressResolver implements AddressResolver { public DefaultAddressResolver() { } /* * (non-Javadoc) * @see gov.nist.core.net.AddressResolver#resolveAddress(javax.sip.address.Hop) */ public Hop resolveAddress(Hop inputAddress) { if (inputAddress.getPort() != -1) return inputAddress; else { return new HopImpl(inputAddress.getHost(), MessageProcessor.getDefaultPort(inputAddress.getTransport()),inputAddress.getTransport()); } } } java/gov/nist/javax/sip/DialogExt.java0100644 0000000 0000000 00000003623 13513104763 016734 0ustar000000000 0000000 package gov.nist.javax.sip; import javax.sip.Dialog; import javax.sip.SipProvider; /** * Extensions for Next specification revision. These interfaces will remain unchanged and be * merged with the next revision of the spec. * * * @author mranga * */ public interface DialogExt extends Dialog { /** * Returns the SipProvider that was used for the first transaction in this Dialog * * @return SipProvider * * @since 2.0 */ public SipProvider getSipProvider(); /** * Sets a flag that indicates that this Dialog is part of a BackToBackUserAgent. If this flag * is set, INVITEs are not allowed to interleave and timed out ACK transmission results in a * BYE being sent to the other side. Setting this flag instructs the stack to automatically * handle dialog errors. Once this flag is set for a dialog, it cannot be changed. * This flag can be set on a stack-wide basis, on a per-provider basis or on a per Dialog basis. * This flag must only be set at the time of Dialog creation. If the flag is set after the first * request or response is seen by the Dialog, the behavior of this flag is undefined. * * @since 2.0 */ public void setBackToBackUserAgent(); /** * Turn off sequence number validation for this dialog. This passes all requests to the * application layer including those that arrive out of order. This is good for testing * purposes. Validation is delegated to the application and the stack will not attempt to * block requests arriving out of sequence from reaching the application. In particular, the * validation of CSeq and the ACK retransmission recognition are delegated to the application. * Your application will be responsible for error handling of these cases. * * @since 2.0 */ public void disableSequenceNumberValidation(); } java/gov/nist/javax/sip/DialogFilter.java0100644 0000000 0000000 00000201477 13513104763 017430 0ustar000000000 0000000 /* * 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.javax.sip; import gov.nist.core.InternalErrorHandler; import gov.nist.javax.sip.address.SipUri; import gov.nist.javax.sip.header.Contact; import gov.nist.javax.sip.header.Event; import gov.nist.javax.sip.header.ReferTo; 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; import gov.nist.javax.sip.stack.MessageChannel; import gov.nist.javax.sip.stack.SIPClientTransaction; import gov.nist.javax.sip.stack.SIPDialog; import gov.nist.javax.sip.stack.SIPServerTransaction; import gov.nist.javax.sip.stack.SIPTransaction; import gov.nist.javax.sip.stack.ServerRequestInterface; 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.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; import javax.sip.message.Request; import javax.sip.message.Response; /* * 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. */ /** * 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.64 $ $Date: 2010/01/14 18:58:30 $ * * @author M. Ranganathan */ class DialogFilter implements ServerRequestInterface, ServerResponseInterface { protected SIPTransaction transactionChannel; protected ListeningPointImpl listeningPoint; private SipStackImpl sipStack; public DialogFilter(SipStackImpl sipStack) { this.sipStack = sipStack; } /** * Send back a Request Pending response. * * @param sipRequest * @param transaction */ private void sendRequestPendingResponse(SIPRequest sipRequest, SIPServerTransaction transaction) { SIPResponse sipResponse = sipRequest.createResponse(Response.REQUEST_PENDING); ServerHeader serverHeader = MessageFactoryImpl.getDefaultServerHeader(); if (serverHeader != null) { sipResponse.setHeader(serverHeader); } try { RetryAfter retryAfter = new RetryAfter(); retryAfter.setRetryAfter(1); sipResponse.setHeader(retryAfter); 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); } } /** * Send a BAD REQUEST response. * * @param sipRequest * @param transaction * @param reasonPhrase */ private void sendBadRequestResponse(SIPRequest sipRequest, SIPServerTransaction transaction, String reasonPhrase) { SIPResponse sipResponse = sipRequest.createResponse(Response.BAD_REQUEST); if (reasonPhrase != null) sipResponse.setReasonPhrase(reasonPhrase); 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) { sipStack.getStackLogger().logError("Problem sending error response", ex); transaction.releaseSem(); sipStack.removeTransaction(transaction); } } /** * Send a CALL OR TRANSACTION DOES NOT EXIST response. * * @param sipRequest * @param transaction */ private void sendCallOrTransactionDoesNotExistResponse(SIPRequest sipRequest, SIPServerTransaction transaction) { SIPResponse sipResponse = sipRequest .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST); 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) { sipStack.getStackLogger().logError("Problem sending error response", ex); transaction.releaseSem(); sipStack.removeTransaction(transaction); } } /** * Send back a LOOP Detected Response. * * @param sipRequest * @param transaction * */ private void sendLoopDetectedResponse(SIPRequest sipRequest, SIPServerTransaction transaction) { SIPResponse sipResponse = sipRequest.createResponse(Response.LOOP_DETECTED); ServerHeader serverHeader = MessageFactoryImpl.getDefaultServerHeader(); if (serverHeader != null) { sipResponse.setHeader(serverHeader); } try { sipStack.addTransactionPendingAck(transaction); transaction.sendResponse(sipResponse); transaction.releaseSem(); } catch (Exception ex) { sipStack.getStackLogger().logError("Problem sending error response", ex); transaction.releaseSem(); sipStack.removeTransaction(transaction); } } /** * Send back an error Response. * * @param sipRequest * @param transaction */ private void sendServerInternalErrorResponse(SIPRequest sipRequest, SIPServerTransaction transaction) { if (sipStack.isLoggingEnabled()) 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(); sipResponse.setHeader(serverHeader); } try { RetryAfter retryAfter = new RetryAfter(); retryAfter.setRetryAfter(10); sipResponse.setHeader(retryAfter); sipStack.addTransactionPendingAck(transaction); transaction.sendResponse(sipResponse); transaction.releaseSem(); } catch (Exception ex) { sipStack.getStackLogger().logError("Problem sending response", ex); transaction.releaseSem(); sipStack.removeTransaction(transaction); } } /** * 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. */ public void processRequest(SIPRequest sipRequest, MessageChannel incomingMessageChannel) { // Generate the wrapper JAIN-SIP object. if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug( "PROCESSING INCOMING REQUEST " + sipRequest + " transactionChannel = " + transactionChannel + " listening point = " + listeningPoint.getIPAddress() + ":" + listeningPoint.getPort()); if (listeningPoint == null) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug( "Dropping message: No listening point registered!"); return; } SipStackImpl sipStack = (SipStackImpl) transactionChannel.getSIPStack(); SipProviderImpl sipProvider = listeningPoint.getProvider(); if (sipProvider == null) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("No provider - dropping !!"); return; } if (sipStack == null) InternalErrorHandler.handleException("Egads! no sip stack!"); // Look for the registered SIPListener for the message channel. SIPServerTransaction transaction = (SIPServerTransaction) this.transactionChannel; if (transaction != null) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug( "transaction state = " + transaction.getState()); } 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 */ if (dialog != null && sipProvider != dialog.getSipProvider()) { Contact contact = dialog.getMyContactHeader(); if (contact != null) { SipUri contactUri = (SipUri) (contact.getAddress().getURI()); String ipAddress = contactUri.getHost(); int contactPort = contactUri.getPort(); String contactTransport = contactUri.getTransportParam(); if (contactTransport == null) contactTransport = "udp"; if (contactPort == -1) { if (contactTransport.equals("udp") || contactTransport.equals("tcp")) contactPort = 5060; else contactPort = 5061; } // Check if the dialog contact is the same as the provider on // which we got the request. Otherwise, dont assign this // dialog to the request. if (ipAddress != null && (!ipAddress.equals(listeningPoint.getIPAddress()) || contactPort != listeningPoint .getPort())) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "nulling dialog -- listening point mismatch! " + contactPort + " lp port = " + listeningPoint.getPort()); } dialog = null; } } } /* * 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.isAutomaticDialogSupportEnabled() && sipProvider.isDialogErrorsAutomaticallyHandled() && sipRequest.getToTag() == null) { SIPServerTransaction sipServerTransaction = sipStack .findMergedTransaction(sipRequest); if (sipServerTransaction != null) { this.sendLoopDetectedResponse(sipRequest, transaction); return; } } if (sipStack.isLoggingEnabled()) { 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 . */ // 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) { RouteList routes = sipRequest.getRouteHeaders(); Route route = (Route) routes.getFirst(); SipUri uri = (SipUri) route.getAddress().getURI(); int port; if (uri.getHostPort().hasPort()) { port = uri.getHostPort().getPort(); } else { if (listeningPoint.getTransport().equalsIgnoreCase("TLS")) port = 5061; else port = 5060; } String host = uri.getHost(); if ((host.equals(listeningPoint.getIPAddress()) || host .equalsIgnoreCase(listeningPoint.getSentBy())) && port == listeningPoint.getPort()) { if (routes.size() == 1) sipRequest.removeHeader(Route.NAME); else routes.removeFirst(); } } 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. */ ReferToHeader sipHeader = (ReferToHeader) sipRequest.getHeader(ReferTo.NAME); if (sipHeader == null) { this .sendBadRequestResponse(sipRequest, transaction, "Refer-To header is missing"); return; } /* * A refer cannot be processed until we have either sent or received an ACK. */ SIPTransaction lastTransaction = ((SIPDialog) dialog).getLastTransaction(); if (lastTransaction != null && sipProvider.isDialogErrorsAutomaticallyHandled()) { SIPRequest lastRequest = (SIPRequest) lastTransaction.getRequest(); if (lastTransaction instanceof SIPServerTransaction) { if (!((SIPDialog) dialog).isAckSeen() && lastRequest.getMethod().equals(Request.INVITE)) { this.sendRequestPendingResponse(sipRequest, transaction); return; } } else if (lastTransaction instanceof SIPClientTransaction) { long cseqno = lastRequest.getCSeqHeader().getSeqNumber(); String method = lastRequest.getMethod(); if (method.equals(Request.INVITE) && !dialog.isAckSent(cseqno)) { this.sendRequestPendingResponse(sipRequest, transaction); return; } } } } 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. * */ if (sipProvider.isAutomaticDialogSupportEnabled() && dialog == null) { this.sendCallOrTransactionDoesNotExistResponse(sipRequest, transaction); return; } } 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 (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("Processing ACK for INVITE Tx "); } else { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("Processing ACK for dialog " + dialog); if (dialog == null) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "Dialog does not exist " + sipRequest.getFirstLine() + " isServerTransaction = " + true); } SIPServerTransaction st = sipStack .getRetransmissionAlertTransaction(dialogId); if (st != null && st.isRetransmissionAlertEnabled()) { st.disableRetransmissionAlerts(); } /* * 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. */ if (ackTransaction != null) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("Found Tx pending ACK"); try { ackTransaction.setAckSeen(); sipStack.removeTransaction(ackTransaction); sipStack.removeTransactionPendingAck(ackTransaction); } catch (Exception ex) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logError( "Problem terminating transaction", ex); } } return; } } else { if (!dialog.handleAck(transaction)) { if (!dialog.isSequnceNumberValidation()) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "Dialog exists with loose dialog validation " + sipRequest.getFirstLine() + " isServerTransaction = " + true + " dialog = " + dialog.getDialogId()); } SIPServerTransaction st = sipStack .getRetransmissionAlertTransaction(dialogId); if (st != null && st.isRetransmissionAlertEnabled()) { st.disableRetransmissionAlerts(); } } else { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "Dropping ACK - cannot find a transaction or dialog"); } SIPServerTransaction ackTransaction = sipStack .findTransactionPendingAck(sipRequest); if (ackTransaction != null) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("Found Tx pending ACK"); try { ackTransaction.setAckSeen(); sipStack.removeTransaction(ackTransaction); sipStack.removeTransactionPendingAck(ackTransaction); } catch (Exception ex) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logError( "Problem terminating transaction", ex); } } } return; } } else { transaction.passToListener(); dialog.addTransaction(transaction); dialog.addRoute(sipRequest); transaction.setDialog(dialog, dialogId); if (sipRequest.getMethod().equals(Request.INVITE) && 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. */ if (sipStack.deliverTerminatedEventForAck) { try { sipStack.addTransaction(transaction); transaction.scheduleAckRemoval(); } catch (IOException ex) { } } else { transaction.setMapped(true); } } } } } 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. */ if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("Processing PRACK for dialog " + dialog); if (dialog == null && sipProvider.isAutomaticDialogSupportEnabled()) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "Dialog does not exist " + sipRequest.getFirstLine() + " isServerTransaction = " + true); } if (sipStack.isLoggingEnabled()) { sipStack .getStackLogger() .logDebug( "Sending 481 for PRACK - automatic dialog support is enabled -- cant find dialog!"); } SIPResponse notExist = sipRequest .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST); try { sipProvider.sendResponse(notExist); } catch (SipException e) { sipStack.getStackLogger().logError("error sending response", e); } if (transaction != null) { sipStack.removeTransaction(transaction); transaction.releaseSem(); } return; } else if (dialog != null) { if (!dialog.handlePrack(sipRequest)) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("Dropping out of sequence PRACK "); if (transaction != null) { sipStack.removeTransaction(transaction); transaction.releaseSem(); } return; } else { try { sipStack.addTransaction(transaction); dialog.addTransaction(transaction); dialog.addRoute(sipRequest); transaction.setDialog(dialog, dialogId); } catch (Exception ex) { InternalErrorHandler.handleException(ex); } } } else { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug( "Processing PRACK without a DIALOG -- this must be a proxy element"); } } else if (sipRequest.getMethod().equals(Request.BYE)) { // Check for correct sequence numbering of the BYE if (dialog != null && !dialog.isRequestConsumable(sipRequest)) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug( "Dropping out of sequence BYE " + dialog.getRemoteSeqNumber() + " " + sipRequest.getCSeq().getSeqNumber()); if (dialog.getRemoteSeqNumber() >= sipRequest.getCSeq().getSeqNumber() && transaction.getState() == TransactionState.TRYING) { this.sendServerInternalErrorResponse(sipRequest, transaction); } // If the stack knows about the tx, then remove it. if (transaction != null) sipStack.removeTransaction(transaction); return; } 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 // No dialog could be found and requests on this // provider. Must act like a user agent -- so drop the request. // NOTE: if Automatic dialog support is not enabled, // then it is the application's responsibility to // take care of this error condition possibly. SIPResponse response = sipRequest .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST); response.setReasonPhrase("Dialog Not Found"); if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug( "dropping request -- automatic dialog " + "support enabled and dialog does not exist!"); try { transaction.sendResponse(response); } catch (SipException ex) { sipStack.getStackLogger().logError("Error in sending response", ex); } // If the stack knows about the tx, then remove it. if (transaction != null) { sipStack.removeTransaction(transaction); transaction.releaseSem(); transaction = null; } return; } // note that the transaction may be null (which // happens when no dialog for the bye was found. // and automatic dialog support is disabled (i.e. the app wants // to manage its own dialog layer. if (transaction != null && dialog != null) { try { if (sipProvider == dialog.getSipProvider()) { sipStack.addTransaction(transaction); dialog.addTransaction(transaction); transaction.setDialog(dialog, dialogId); } } catch (IOException ex) { InternalErrorHandler.handleException(ex); } } if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "BYE Tx = " + transaction + " isMapped =" + transaction.isTransactionMapped()); } } else if (sipRequest.getMethod().equals(Request.CANCEL)) { SIPServerTransaction st = (SIPServerTransaction) sipStack.findCancelTransaction( sipRequest, true); if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "Got a CANCEL, InviteServerTx = " + st + " cancel Server Tx ID = " + transaction + " isMapped = " + transaction.isTransactionMapped()); } // Processing incoming CANCEL. // Check if we can process the CANCEL request. if (sipRequest.getMethod().equals(Request.CANCEL)) { // 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.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 (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("Too late to cancel Transaction"); // send OK and just ignore the CANCEL. try { transaction.sendResponse(sipRequest.createResponse(Response.OK)); } catch (Exception ex) { if (ex.getCause() != null && ex.getCause() instanceof IOException) { st.raiseIOExceptionEvent(); } } return; } if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("Cancel transaction = " + st); } if (transaction != null && st != null && st.getDialog() != null) { // Found an invite tx corresponding to the CANCEL. // 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() && transaction != null) { // Could not find a invite tx corresponding to the CANCEL. // Automatic dialog support is enabled so I must behave like // an endpoint on this provider. // Send the error response for the cancel. SIPResponse response = sipRequest .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST); if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "dropping request -- automatic dialog support " + "enabled and INVITE ST does not exist!"); } try { sipProvider.sendResponse(response); } catch (SipException ex) { InternalErrorHandler.handleException(ex); } if (transaction != null) { sipStack.removeTransaction(transaction); transaction.releaseSem(); } return; } // INVITE was handled statefully so the CANCEL must also be // statefully handled. if (st != null) { try { if (transaction != null) { sipStack.addTransaction(transaction); transaction.setPassToListener(); transaction.setInviteTransaction(st); // Dont let the INVITE and CANCEL be concurrently // processed. st.acquireSem(); } } catch (Exception ex) { InternalErrorHandler.handleException(ex); } } } 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. */ if (dialog != null && transaction != null && lastTransaction != null && sipRequest.getCSeq().getSeqNumber() > dialog.getRemoteSeqNumber() && lastTransaction instanceof SIPServerTransaction && sipProvider.isDialogErrorsAutomaticallyHandled() && dialog.isSequnceNumberValidation() && lastTransaction.isInviteTransaction() && lastTransaction.getState() != TransactionState.COMPLETED && lastTransaction.getState() != TransactionState.TERMINATED && lastTransaction.getState() != TransactionState.CONFIRMED) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "Sending 500 response for out of sequence message"); } this.sendServerInternalErrorResponse(sipRequest, transaction); return; } /* * 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()); if (dialog != null && sipProvider.isDialogErrorsAutomaticallyHandled() && lastTransaction != null && lastTransaction.isInviteTransaction() && lastTransaction instanceof ClientTransaction && lastTransaction.getLastResponse() != null && lastTransaction.getLastResponse().getStatusCode() == 200 && !dialog.isAckSent(lastTransaction.getLastResponse().getCSeq() .getSeqNumber())) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "Sending 491 response for client Dialog ACK not sent."); } this.sendRequestPendingResponse(sipRequest, transaction); return; } if (dialog != null && lastTransaction != null && sipProvider.isDialogErrorsAutomaticallyHandled() && lastTransaction.isInviteTransaction() && lastTransaction instanceof ServerTransaction && !dialog.isAckSeen()) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "Sending 491 response for server Dialog ACK not seen."); } this.sendRequestPendingResponse(sipRequest, transaction); return; } } // Sequence numbers are supposed to be incremented // sequentially within a dialog for RFC 3261 // Note BYE, CANCEL and ACK is handled above - so no check here. if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "CHECK FOR OUT OF SEQ MESSAGE " + dialog + " transaction " + transaction); } 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. */ // Drop the request if (sipStack.isLoggingEnabled()) { 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) if (dialog.getRemoteSeqNumber() >= sipRequest.getCSeq().getSeqNumber() && sipProvider.isDialogErrorsAutomaticallyHandled() && (transaction.getState() == TransactionState.TRYING || transaction .getState() == TransactionState.PROCEEDING)) { this.sendServerInternalErrorResponse(sipRequest, transaction); } return; } try { if (sipProvider == dialog.getSipProvider()) { sipStack.addTransaction(transaction); // This will set the remote sequence number. dialog.addTransaction(transaction); dialog.addRoute(sipRequest); transaction.setDialog(dialog, dialogId); } } catch (IOException ex) { transaction.raiseIOExceptionEvent(); sipStack.removeTransaction(transaction); return; } } RequestEvent sipEvent; if (sipStack.isLoggingEnabled()) { 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. */ if (dialog == null && sipRequest.getMethod().equals(Request.NOTIFY)) { SIPClientTransaction pendingSubscribeClientTx = sipStack.findSubscribeTransaction( sipRequest, listeningPoint); if (sipStack.isLoggingEnabled()) { 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. */ if (sipProvider.isAutomaticDialogSupportEnabled() && pendingSubscribeClientTx == null && !sipStack.deliverUnsolicitedNotify) { /* * 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 (sipStack.isLoggingEnabled()) { 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"); sipProvider.sendResponse(errorResponse); return; } catch (Exception ex) { sipStack.getStackLogger().logError( "Exception while sending error response statelessly", ex); return; } } // If the server transaction cannot be found or if it // aleady has a dialog attached to it then just assign the // notify to this dialog and pass it up. if (pendingSubscribeClientTx != null) { // The response to the pending subscribe tx can try to create // a dialog at the same time that the notify is trying to // create a dialog. Thus we cannot process both at the // same time. transaction.setPendingSubscribe(pendingSubscribeClientTx); // The transaction gets assigned to the dialog from the // outgoing subscribe. First see if anybody claimed the // default Dialog for the outgoing Subscribe request. SIPDialog subscriptionDialog = (SIPDialog) pendingSubscribeClientTx .getDefaultDialog(); // TODO -- refactor this. Can probably be written far cleaner. 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) { subscriptionDialog.setDialogId(dialogId); } else { subscriptionDialog = pendingSubscribeClientTx.getDialog(dialogId); } if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "PROCESSING NOTIFY Subscribe DIALOG " + subscriptionDialog); } // The user could have createed a dialog before sending out // the SUBSCRIBE on the subscribe tx. if (subscriptionDialog == null && (sipProvider.isAutomaticDialogSupportEnabled() || pendingSubscribeClientTx .getDefaultDialog() != null)) { Event event = (Event) sipRequest.getHeader(EventHeader.NAME); if (sipStack.isEventForked(event.getEventType())) { subscriptionDialog = SIPDialog.createFromNOTIFY( pendingSubscribeClientTx, transaction); } } if (subscriptionDialog != null) { transaction.setDialog(subscriptionDialog, dialogId); subscriptionDialog.setState(DialogState.CONFIRMED.getValue()); sipStack.putDialog(subscriptionDialog); pendingSubscribeClientTx.setDialog(subscriptionDialog, dialogId); if (!transaction.isTransactionMapped()) { this.sipStack.mapTransaction(transaction); // Let the listener see it if it just got // created. // otherwise, we have already processed the tx // so // we dont want the listener to see it. transaction.setPassToListener(); try { this.sipStack.addTransaction(transaction); } catch (Exception ex) { } } } } else { // The subscription default dialog is our dialog. // Found a subscrbe dialog for the NOTIFY // So map the tx. transaction.setDialog(subscriptionDialog, dialogId); dialog = subscriptionDialog; if (!transaction.isTransactionMapped()) { this.sipStack.mapTransaction(transaction); // Let the listener see it if it just got created. // otherwise, we have already processed the tx so // we dont want the listener to see it. transaction.setPassToListener(); try { this.sipStack.addTransaction(transaction); } catch (Exception ex) { } } sipStack.putDialog(subscriptionDialog); if (pendingSubscribeClientTx != null) { subscriptionDialog.addTransaction(pendingSubscribeClientTx); pendingSubscribeClientTx.setDialog(subscriptionDialog, dialogId); } } if (transaction != null && ((SIPServerTransaction) transaction).isTransactionMapped()) { // Shadow transaction has been created and the stack // knows // about it. 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 RequestEvent((SipProvider) sipProvider, null, subscriptionDialog, (Request) sipRequest); } } else { if (sipStack.isLoggingEnabled()) { 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 RequestEvent(sipProvider, null, null, (Request) sipRequest); } } else { // 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 RequestEvent(sipProvider, (ServerTransaction) transaction, dialog, (Request) sipRequest); } else { sipEvent = new RequestEvent(sipProvider, null, dialog, (Request) sipRequest); } } sipProvider.handleEvent(sipEvent, transaction); } /** * 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. */ public void processResponse(SIPResponse response, MessageChannel incomingMessageChannel, SIPDialog dialog) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "PROCESSING INCOMING RESPONSE" + response.encodeMessage()); } if (listeningPoint == null) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logError( "Dropping message: No listening point" + " registered!"); return; } if (sipStack.checkBranchId() && !Utils.getInstance().responseBelongsToUs(response)) { if (sipStack.isLoggingEnabled()) { sipStack .getStackLogger() .logError( "Dropping response - topmost VIA header does not originate from this stack"); } return; } SipProviderImpl sipProvider = listeningPoint.getProvider(); if (sipProvider == null) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logError("Dropping message: no provider"); } return; } if (sipProvider.getSipListener() == null) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logError("No listener -- dropping response!"); } return; } SIPClientTransaction transaction = (SIPClientTransaction) this.transactionChannel; SipStackImpl sipStackImpl = sipProvider.sipStack; if (sipStack.isLoggingEnabled()) { sipStackImpl.getStackLogger().logDebug("Transaction = " + transaction); } if (transaction == null) { // Transaction is null but the dialog is not null. This means that // the transaction has been removed by the stack. // If the dialog exists, then it may need to retransmit ACK so // we cannot drop the response. if (dialog != null) { if (response.getStatusCode() / 100 != 2) { if (sipStack.isLoggingEnabled()) { 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 (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "Dialog is terminated -- dropping response!"); } return; } else { boolean ackAlreadySent = false; if (dialog.isAckSeen() && dialog.getLastAckSent() != null) { if (dialog.getLastAckSent().getCSeq().getSeqNumber() == response .getCSeq().getSeqNumber()) { // the last ack sent corresponded to this 200 ackAlreadySent = true; } } // 200 retransmission for the final response. if (ackAlreadySent && response.getCSeq().getMethod().equals(dialog.getMethod())) { try { // Found the dialog - resend the ACK and // dont pass up the null transaction if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "Retransmission of OK detected: Resending last ACK"); } dialog.resendAck(); return; } catch (SipException ex) { // What to do here ?? kill the dialog? sipStack.getStackLogger().logError("could not resend ack", ex); } } } } if (sipStack.isLoggingEnabled()) { 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 (response.getCSeqHeader().getMethod().equals(Request.INVITE)) { SIPClientTransaction forked = this.sipStack.getForkedTransaction(response .getTransactionId()); sipEvent.setOriginalTransaction(forked); } sipProvider.handleEvent(sipEvent, transaction); return; } ResponseEventExt responseEvent = null; // Here if there is an assigned dialog responseEvent = new ResponseEventExt(sipProvider, (ClientTransactionExt) transaction, dialog, (Response) response); if (response.getCSeqHeader().getMethod().equals(Request.INVITE)) { SIPClientTransaction forked = this.sipStack.getForkedTransaction(response .getTransactionId()); responseEvent.setOriginalTransaction(forked); } // Set the Dialog for the response. if (dialog != null && response.getStatusCode() != 100) { // set the last response for the dialog. dialog.setLastResponse(transaction, response); transaction.setDialog(dialog, dialog.getDialogId()); } 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. * * @return auxiliary information that we may have generated during the message processing * which is retrieved by the message logger. */ public String getProcessingInfo() { return null; } /* * (non-Javadoc) * * @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) { String dialogID = sipResponse.getDialogId(false); SIPDialog sipDialog = this.sipStack.getDialog(dialogID); String method = sipResponse.getCSeq().getMethod(); if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "PROCESSING INCOMING RESPONSE: " + sipResponse.encodeMessage()); } if (sipStack.checkBranchId() && !Utils.getInstance().responseBelongsToUs(sipResponse)) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logError("Detected stray response -- dropping"); } return; } if (listeningPoint == null) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug( "Dropping message: No listening point" + " registered!"); return; } SipProviderImpl sipProvider = listeningPoint.getProvider(); if (sipProvider == null) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug("Dropping message: no provider"); } return; } if (sipProvider.getSipListener() == null) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "Dropping message: no sipListener registered!"); } return; } SIPClientTransaction transaction = (SIPClientTransaction) this.transactionChannel; // This may be a dialog creating method for which the ACK has not yet // been sent // but the dialog has already been assigned ( happens this way for // 3PCC). if (sipDialog == null && transaction != null) { sipDialog = transaction.getDialog(dialogID); if (sipDialog != null && sipDialog.getState() == DialogState.TERMINATED) sipDialog = null; } if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug( "Transaction = " + transaction + " sipDialog = " + sipDialog); if (this.transactionChannel != null) { String originalFrom = ((SIPRequest) this.transactionChannel.getRequest()) .getFromTag(); if (originalFrom == null ^ sipResponse.getFrom().getTag() == null) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("From tag mismatch -- dropping response"); return; } if (originalFrom != null && !originalFrom.equalsIgnoreCase(sipResponse.getFrom().getTag())) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("From tag mismatch -- dropping response"); return; } } if (sipStack.isDialogCreated(method) && sipResponse.getStatusCode() != 100 && sipResponse.getFrom().getTag() != null && sipResponse.getTo().getTag() != null && sipDialog == null) { if (sipProvider.isAutomaticDialogSupportEnabled()) { if (this.transactionChannel != null) { if (sipDialog == null) { // There could be an existing dialog for this response. sipDialog = sipStack.createDialog( (SIPClientTransaction) this.transactionChannel, sipResponse); this.transactionChannel.setDialog(sipDialog, sipResponse .getDialogId(false)); } } else { sipDialog = this.sipStack.createDialog(sipProvider, sipResponse); } } } else { // Have a dialog but could not find transaction. if (sipDialog != null && transaction == null && sipDialog.getState() != DialogState.TERMINATED) { if (sipResponse.getStatusCode() / 100 != 2) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug( "status code != 200 ; statusCode = " + sipResponse.getStatusCode()); } else if (sipDialog.getState() == DialogState.TERMINATED) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "Dialog is terminated -- dropping response!"); } // 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)) { try { Request ackRequest = sipDialog.createAck(sipResponse.getCSeq() .getSeqNumber()); sipDialog.sendAck(ackRequest); } catch (Exception ex) { sipStack.getStackLogger().logError("Error creating ack", ex); } } return; } else { boolean ackAlreadySent = false; if (sipDialog.isAckSeen() && sipDialog.getLastAckSent() != null) { if (sipDialog.getLastAckSent().getCSeq().getSeqNumber() == sipResponse .getCSeq().getSeqNumber() && sipResponse.getDialogId(false).equals( 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())) { try { // Found the dialog - resend the ACK and // dont pass up the null transaction if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("resending ACK"); sipDialog.resendAck(); return; } catch (SipException ex) { // What to do here ?? kill the dialog? } } } } // Pass the response up to the application layer to handle // statelessly. } if (sipStack.isLoggingEnabled()) 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); if (sipResponse.getCSeq().getMethod().equals(Request.INVITE)) { ClientTransactionExt originalTx = this.sipStack.getForkedTransaction(sipResponse .getTransactionId()); responseEvent.setOriginalTransaction(originalTx); } sipProvider.handleEvent(responseEvent, transaction); } } java/gov/nist/javax/sip/DialogTimeoutEvent.java0100644 0000000 0000000 00000004257 13513104763 020630 0ustar000000000 0000000 /* * This source code has been contributed to the public domain by Mobicents * * 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; import java.util.EventObject; import javax.sip.Dialog; /** * * DialogAckTimeoutEvent is delivered to the Listener when the * dialog does not receive or send an ACK. * * * @author jean deruelle * @since v2.0 * */ public class DialogTimeoutEvent extends EventObject { private static final long serialVersionUID = -2514000059989311925L; public enum Reason {AckNotReceived, AckNotSent,ReInviteTimeout}; /** * Constructs a DialogTerminatedEvent to indicate a dialog * timeout. * * @param source - the source of TimeoutEvent. * @param dialog - the dialog that timed out. */ public DialogTimeoutEvent(Object source, Dialog dialog, Reason reason) { super(source); m_dialog = dialog; m_reason = reason; } /** * Gets the Dialog associated with the event. This * enables application developers to access the dialog associated to this * event. * * @return the dialog associated with the response event or null if there is no dialog. * @since v1.2 */ public Dialog getDialog() { return m_dialog; } /** * The reason for the Dialog Timeout Event being delivered to the application. * * @return the reason for the timeout event. */ public Reason getReason() { return m_reason; } // internal variables private Dialog m_dialog = null; private Reason m_reason = null; } java/gov/nist/javax/sip/EventScanner.java0100644 0000000 0000000 00000054653 13513104763 017460 0ustar000000000 0000000 /* * 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; import java.util.*; import gov.nist.javax.sip.stack.*; import gov.nist.javax.sip.message.*; import javax.sip.message.*; import javax.sip.*; import gov.nist.core.ThreadAuditor; /* bug fixes SIPQuest communications and Shu-Lin Chen. */ /** * Event Scanner to deliver events to the Listener. * * @version 1.2 $Revision: 1.41 $ $Date: 2009/11/18 02:35:17 $ * * @author M. Ranganathan
* * */ class EventScanner implements Runnable { private boolean isStopped; private int refCount; // SIPquest: Fix for deadlocks private LinkedList pendingEvents = new LinkedList(); private int[] eventMutex = { 0 }; private SipStackImpl sipStack; public void incrementRefcount() { synchronized (eventMutex) { this.refCount++; } } public EventScanner(SipStackImpl sipStackImpl) { this.pendingEvents = new LinkedList(); Thread myThread = new Thread(this); // This needs to be set to false else the // main thread mysteriously exits. myThread.setDaemon(false); this.sipStack = sipStackImpl; myThread.setName("EventScannerThread"); myThread.start(); } public void addEvent(EventWrapper eventWrapper) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("addEvent " + eventWrapper); synchronized (this.eventMutex) { pendingEvents.add(eventWrapper); // Add the event into the pending events list eventMutex.notify(); } } /** * Stop the event scanner. Decrement the reference count and exit the * scanner thread if the ref count goes to 0. */ public void stop() { synchronized (eventMutex) { if (this.refCount > 0) this.refCount--; if (this.refCount == 0) { isStopped = true; eventMutex.notify(); } } } /** * Brutally stop the event scanner. This does not wait for the refcount to * go to 0. * */ public void forceStop() { synchronized (this.eventMutex) { this.isStopped = true; this.refCount = 0; this.eventMutex.notify(); } } public void deliverEvent(EventWrapper eventWrapper) { EventObject sipEvent = eventWrapper.sipEvent; if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug( "sipEvent = " + sipEvent + "source = " + sipEvent.getSource()); SipListener sipListener = null; if (!(sipEvent instanceof IOExceptionEvent)) { sipListener = ((SipProviderImpl) sipEvent.getSource()).getSipListener(); } else { sipListener = sipStack.getSipListener(); } if (sipEvent instanceof RequestEvent) { try { // Check if this request has already created a // transaction SIPRequest sipRequest = (SIPRequest) ((RequestEvent) sipEvent) .getRequest(); if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "deliverEvent : " + sipRequest.getFirstLine() + " transaction " + eventWrapper.transaction + " sipEvent.serverTx = " + ((RequestEvent) sipEvent) .getServerTransaction()); } // Discard the duplicate request if a // transaction already exists. If the listener chose // to handle the request statelessly, then the listener // will see the retransmission. // Note that in both of these two cases, JAIN SIP will allow // you to handle the request statefully or statelessly. // An example of the latter case is REGISTER and an example // of the former case is INVITE. SIPServerTransaction tx = (SIPServerTransaction) sipStack .findTransaction(sipRequest, true); if (tx != null && !tx.passToListener()) { // JvB: make an exception for a very rare case: some // (broken) UACs use // the same branch parameter for an ACK. Such an ACK should // be passed // to the listener (tx == INVITE ST, terminated upon sending // 2xx but // lingering to catch retransmitted INVITEs) if (sipRequest.getMethod().equals(Request.ACK) && tx.isInviteTransaction() && ( tx.getLastResponse().getStatusCode()/100 == 2 || sipStack.isNon2XXAckPassedToListener())) { if (sipStack.isLoggingEnabled()) sipStack .getStackLogger() .logDebug( "Detected broken client sending ACK with same branch! Passing..."); } else { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug( "transaction already exists! " + tx); return; } } else if (sipStack.findPendingTransaction(sipRequest) != null) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug( "transaction already exists!!"); return; } else { // Put it in the pending list so that if a repeat // request comes along it will not get assigned a // new transaction SIPServerTransaction st = (SIPServerTransaction) eventWrapper.transaction; sipStack.putPendingTransaction(st); } // Set up a pointer to the transaction. sipRequest.setTransaction(eventWrapper.transaction); // Change made by SIPquest try { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger() .logDebug( "Calling listener " + sipRequest.getFirstLine()); sipStack.getStackLogger().logDebug( "Calling listener " + eventWrapper.transaction); } if (sipListener != null) sipListener.processRequest((RequestEvent) sipEvent); if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "Done processing Message " + sipRequest.getFirstLine()); } if (eventWrapper.transaction != null) { SIPDialog dialog = (SIPDialog) eventWrapper.transaction .getDialog(); if (dialog != null) dialog.requestConsumed(); } } catch (Exception ex) { // We cannot let this thread die under any // circumstances. Protect ourselves by logging // errors to the console but continue. sipStack.getStackLogger().logException(ex); } } finally { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "Done processing Message " + ((SIPRequest) (((RequestEvent) sipEvent) .getRequest())).getFirstLine()); } if (eventWrapper.transaction != null && ((SIPServerTransaction) eventWrapper.transaction) .passToListener()) { ((SIPServerTransaction) eventWrapper.transaction) .releaseSem(); } if (eventWrapper.transaction != null) sipStack .removePendingTransaction((SIPServerTransaction) eventWrapper.transaction); 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); } } } else if (sipEvent instanceof ResponseEvent) { try { ResponseEvent responseEvent = (ResponseEvent) sipEvent; SIPResponse sipResponse = (SIPResponse) responseEvent .getResponse(); SIPDialog sipDialog = ((SIPDialog) responseEvent.getDialog()); try { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "Calling listener for " + sipResponse.getFirstLine()); } if (sipListener != null) { SIPTransaction tx = eventWrapper.transaction; if (tx != null) { tx.setPassToListener(); } sipListener.processResponse((ResponseEvent) sipEvent); } /* * If the response for a request within a dialog is a 481 * (Call/Transaction Does Not Exist) or a 408 (Request * Timeout), the UAC SHOULD terminate the dialog. */ if ((sipDialog != null && (sipDialog.getState() == null || !sipDialog .getState().equals(DialogState.TERMINATED))) && (sipResponse.getStatusCode() == Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST || sipResponse .getStatusCode() == Response.REQUEST_TIMEOUT)) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "Removing dialog on 408 or 481 response"); } sipDialog.doDeferredDelete(); } /* * The Client tx disappears after the first 2xx response * However, additional 2xx responses may arrive later for * example in the following scenario: * * Multiple 2xx responses may arrive at the UAC for a single * INVITE request due to a forking proxy. Each response is * distinguished by the tag parameter in the To header * field, and each represents a distinct dialog, with a * distinct dialog identifier. * * If the Listener does not ACK the 200 then we assume he * does not care about the dialog and gc the dialog after * some time. However, this is really an application bug. * This garbage collects unacknowledged dialogs. * */ if (sipResponse.getCSeq().getMethod() .equals(Request.INVITE) && sipDialog != null && sipResponse.getStatusCode() == 200) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "Warning! unacknowledged dialog. " + sipDialog.getState()); } /* * If we dont see an ACK in 32 seconds, we want to tear down the dialog. */ sipDialog.doDeferredDeleteIfNoAckSent(sipResponse.getCSeq().getSeqNumber()); } } catch (Exception ex) { // We cannot let this thread die under any // circumstances. Protect ourselves by logging // errors to the console but continue. 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.getState() && ct.getOriginalRequest() != null && !ct.getOriginalRequest().getMethod().equals( Request.INVITE)) { // reduce the state to minimum // This assumes that the application will not need // to access the request once the transaction is // completed. ct.clearState(); } // mark no longer in the event queue. } finally { if (eventWrapper.transaction != null && eventWrapper.transaction.passToListener()) { eventWrapper.transaction.releaseSem(); } } } else if (sipEvent instanceof TimeoutEvent) { // Change made by SIPquest try { // Check for null as listener could be removed. if (sipListener != null) sipListener.processTimeout((TimeoutEvent) sipEvent); } catch (Exception ex) { // We cannot let this thread die under any // circumstances. Protect ourselves by logging // errors to the console but continue. sipStack.getStackLogger().logException(ex); } } else if (sipEvent instanceof DialogTimeoutEvent) { try { // Check for null as listener could be removed. if (sipListener != null && sipListener instanceof SipListenerExt) { ((SipListenerExt)sipListener).processDialogTimeout((DialogTimeoutEvent) sipEvent); } } catch (Exception ex) { // We cannot let this thread die under any // circumstances. Protect ourselves by logging // errors to the console but continue. sipStack.getStackLogger().logException(ex); } } else if (sipEvent instanceof IOExceptionEvent) { try { if (sipListener != null) sipListener.processIOException((IOExceptionEvent) sipEvent); } catch (Exception ex) { sipStack.getStackLogger().logException(ex); } } else if (sipEvent instanceof TransactionTerminatedEvent) { try { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "About to deliver transactionTerminatedEvent"); sipStack.getStackLogger().logDebug( "tx = " + ((TransactionTerminatedEvent) sipEvent) .getClientTransaction()); sipStack.getStackLogger().logDebug( "tx = " + ((TransactionTerminatedEvent) sipEvent) .getServerTransaction()); } if (sipListener != null) sipListener .processTransactionTerminated((TransactionTerminatedEvent) sipEvent); } catch (AbstractMethodError ame) { // JvB: for backwards compatibility, accept this if (sipStack.isLoggingEnabled()) sipStack .getStackLogger() .logWarning( "Unable to call sipListener.processTransactionTerminated"); } catch (Exception ex) { sipStack.getStackLogger().logException(ex); } } else if (sipEvent instanceof DialogTerminatedEvent) { try { if (sipListener != null) sipListener .processDialogTerminated((DialogTerminatedEvent) sipEvent); } catch (AbstractMethodError ame) { // JvB: for backwards compatibility, accept this if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logWarning( "Unable to call sipListener.processDialogTerminated"); } catch (Exception ex) { sipStack.getStackLogger().logException(ex); } } else { sipStack.getStackLogger().logFatalError("bad event" + sipEvent); } } /** * For the non-re-entrant listener this delivers the events to the listener * from a single queue. If the listener is re-entrant, then the stack just * calls the deliverEvent method above. */ public void run() { try { // Ask the auditor to monitor this thread ThreadAuditor.ThreadHandle threadHandle = sipStack.getThreadAuditor().addCurrentThread(); while (true) { EventWrapper eventWrapper = null; LinkedList eventsToDeliver; synchronized (this.eventMutex) { // First, wait for some events to become available. while (pendingEvents.isEmpty()) { // There's nothing in the list, check to make sure we // haven't // been stopped. If we have, then let the thread die. if (this.isStopped) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug( "Stopped event scanner!!"); return; } // We haven't been stopped, and the event list is indeed // rather empty. Wait for some events to come along. try { // Send a heartbeat to the thread auditor threadHandle.ping(); // Wait for events (with a timeout) eventMutex.wait(threadHandle.getPingIntervalInMillisecs()); } catch (InterruptedException ex) { // Let the thread die a normal death if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("Interrupted!"); return; } } // There are events in the 'pending events list' that need // processing. Hold onto the old 'pending Events' list, but // make a new one for the other methods to operate on. This // tap-dancing is to avoid deadlocks and also to ensure that // the list is not modified while we are iterating over it. eventsToDeliver = pendingEvents; pendingEvents = new LinkedList(); } ListIterator iterator = eventsToDeliver.listIterator(); while (iterator.hasNext()) { eventWrapper = (EventWrapper) iterator.next(); if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "Processing " + eventWrapper + "nevents " + eventsToDeliver.size()); } try { deliverEvent(eventWrapper); } catch (Exception e) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logError( "Unexpected exception caught while delivering event -- carrying on bravely", e); } } } } // end While } finally { if (sipStack.isLoggingEnabled()) { if (!this.isStopped) { sipStack.getStackLogger().logFatalError("Event scanner exited abnormally"); } } } } } java/gov/nist/javax/sip/EventWrapper.java0100644 0000000 0000000 00000002677 13513104763 017506 0ustar000000000 0000000 /* * 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; import gov.nist.javax.sip.stack.*; import java.util.*; /** * @version 1.2 $Revision: 1.6 $ $Date: 2009/07/17 18:57:19 $ */ class EventWrapper { protected EventObject sipEvent; protected SIPTransaction transaction; EventWrapper(EventObject sipEvent, SIPTransaction transaction) { this.sipEvent = sipEvent; this.transaction = transaction; } } java/gov/nist/javax/sip/ListeningPointExt.java0100644 0000000 0000000 00000001727 13513104763 020506 0ustar000000000 0000000 package gov.nist.javax.sip; import java.io.IOException; import javax.sip.ListeningPoint; import javax.sip.header.ContactHeader; import javax.sip.header.ViaHeader; public interface ListeningPointExt extends ListeningPoint { /** * Create a contact for this listening point. * * @return a contact header corresponding to this listening point. * * @since 2.0 * */ ContactHeader createContactHeader() ; /** * Send a heartbeat to the specified Ip address and port * via this listening point. This method can be used to send out a period * CR-LF for NAT keepalive. * * @since 2.0 */ public void sendHeartbeat(String ipAddress, int port) throws IOException ; /** * Create a Via header for this listening point. * * @return a via header corresponding to this listening point. Branch ID is set to NULL. * * @since 2.0 */ public ViaHeader createViaHeader(); } java/gov/nist/javax/sip/ListeningPointImpl.java0100644 0000000 0000000 00000016215 13513104763 020645 0ustar000000000 0000000 /* * 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; import java.io.IOException; import java.net.InetAddress; import java.text.ParseException; import javax.sip.*; import javax.sip.address.SipURI; import javax.sip.header.ContactHeader; import javax.sip.header.ViaHeader; import gov.nist.core.Host; import gov.nist.core.HostPort; import gov.nist.core.InternalErrorHandler; import gov.nist.javax.sip.address.AddressImpl; import gov.nist.javax.sip.address.SipUri; import gov.nist.javax.sip.header.Contact; import gov.nist.javax.sip.header.Via; import gov.nist.javax.sip.message.SIPRequest; import gov.nist.javax.sip.stack.*; /** * Implementation of the ListeningPoint interface * * @version 1.2 $Revision: 1.15 $ $Date: 2009/11/19 05:26:58 $ * * @author M. Ranganathan
* * * */ public class ListeningPointImpl implements javax.sip.ListeningPoint, gov.nist.javax.sip.ListeningPointExt { protected String transport; /** My port. (same thing as in the message processor) */ int port; /** * Pointer to the imbedded mesage processor. */ protected MessageProcessor messageProcessor; /** * Provider back pointer */ protected SipProviderImpl sipProvider; /** * Our stack */ protected SipStackImpl sipStack; /** * Construct a key to refer to this structure from the SIP stack * @param host host string * @param port port * @param transport transport * @return a string that is used as a key */ public static String makeKey(String host, int port, String transport) { return new StringBuffer(host) .append(":") .append(port) .append("/") .append(transport) .toString() .toLowerCase(); } /** * Get the key for this strucut * @return get the host */ protected String getKey() { return makeKey(this.getIPAddress(), port, transport); } /** * Set the sip provider for this structure. * @param sipProvider provider to set */ protected void setSipProvider(SipProviderImpl sipProviderImpl) { this.sipProvider = sipProviderImpl; } /** * Remove the sip provider from this listening point. */ protected void removeSipProvider() { this.sipProvider = null; } /** * Constructor * @param sipStack Our sip stack */ protected ListeningPointImpl( SipStack sipStack, int port, String transport) { this.sipStack = (SipStackImpl) sipStack; this.port = port; this.transport = transport; } /** * Clone this listening point. Note that a message Processor is not * started. The transport is set to null. * @return cloned listening point. */ public Object clone() { ListeningPointImpl lip = new ListeningPointImpl(this.sipStack, this.port, null); lip.sipStack = this.sipStack; return lip; } /** * Gets the port of the ListeningPoint. The default port of a ListeningPoint * is dependent on the scheme and transport. For example: *
    *
  • The default port is 5060 if the transport UDP the scheme is sip:. *
  • The default port is 5060 if the transport is TCP the scheme is sip:. *
  • The default port is 5060 if the transport is SCTP the scheme is sip:. *
  • The default port is 5061 if the transport is TLS over TCP the scheme is sip:. *
  • The default port is 5061 if the transport is TCP the scheme is sips:. *
* * @return port of ListeningPoint */ public int getPort() { return messageProcessor.getPort(); } /** * Gets transport of the ListeningPoint. * * @return transport of ListeningPoint */ public String getTransport() { return messageProcessor.getTransport(); } /** * Get the provider. * * @return the provider. */ public SipProviderImpl getProvider() { return this.sipProvider; } /* (non-Javadoc) * @see javax.sip.ListeningPoint#getIPAddress() */ public String getIPAddress() { return this.messageProcessor.getIpAddress().getHostAddress(); } /* (non-Javadoc) * @see javax.sip.ListeningPoint#setSentBy(java.lang.String) */ public void setSentBy(String sentBy) throws ParseException { this.messageProcessor.setSentBy(sentBy); } /* (non-Javadoc) * @see javax.sip.ListeningPoint#getSentBy() */ public String getSentBy() { return this.messageProcessor.getSentBy(); } public boolean isSentBySet() { return this.messageProcessor.isSentBySet(); } public Via getViaHeader() { return this.messageProcessor.getViaHeader(); } public MessageProcessor getMessageProcessor() { return this.messageProcessor; } public ContactHeader createContactHeader() { try { String ipAddress = this.getIPAddress(); int port = this.getPort(); SipURI sipURI = new SipUri(); sipURI.setHost(ipAddress); sipURI.setPort(port); sipURI.setTransportParam(this.transport); Contact contact = new Contact(); AddressImpl address = new AddressImpl(); address.setURI(sipURI); contact.setAddress(address); return contact; } catch (Exception ex) { InternalErrorHandler.handleException("Unexpected exception",sipStack.getStackLogger()); return null; } } public void sendHeartbeat(String ipAddress, int port) throws IOException { HostPort targetHostPort = new HostPort(); targetHostPort.setHost(new Host( ipAddress)); targetHostPort.setPort(port); MessageChannel messageChannel = this.messageProcessor.createMessageChannel(targetHostPort); SIPRequest siprequest = new SIPRequest(); siprequest.setNullRequest(); messageChannel.sendMessage(siprequest); } public ViaHeader createViaHeader() { return this.getViaHeader(); } } java/gov/nist/javax/sip/LogRecord.java0100644 0000000 0000000 00000000613 13513104763 016730 0ustar000000000 0000000 package gov.nist.javax.sip; /** * The interface for a log record. The log records are generated by calling the * LogReocrdFactory instance that is registered with the stack. * * @author M. Ranganathan * */ public interface LogRecord { public abstract boolean equals(Object other); /** * Get an XML String for this message */ public abstract String toString(); } java/gov/nist/javax/sip/LogRecordFactory.java0100644 0000000 0000000 00000002633 13513104763 020264 0ustar000000000 0000000 package gov.nist.javax.sip; /** * The stack calls the message log factory to create logging records. The default implementatation * of this interface can be replaced using the gov.nist.javax.sip.LOG_RECORD_FACTORY property. * This override is provided to allow applications to log axuiliary information (such as environment * conditions etc) when messages are logged in the stack. * * @author M. Ranganathan * */ public interface LogRecordFactory { /** * Create a log record. * * @param message -- the message to be logged. * @param source -- host:port of the source of the message. * @param destination -- host:port of the destination of the message. * @param timeStamp -- The time at which this message was seen by the stack or sent out by * the stack. * @param isSender -- true if we are sending the message false otherwise. * @param firstLine -- the first line of the message to be logged. * @param tid -- the transaction id * @param callId -- the call id * @param timestampVal -- the timestamp header value of the incoming message. * * @return -- a log record with the appropriate fields set. */ public LogRecord createLogRecord(String message, String source, String destination, long timeStamp, boolean isSender, String firstLine, String tid, String callId, long timestampVal); } java/gov/nist/javax/sip/NistSipMessageFactoryImpl.java0100644 0000000 0000000 00000013410 13513104763 022117 0ustar000000000 0000000 /* * 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.javax.sip; import gov.nist.javax.sip.stack.*; import gov.nist.javax.sip.message.*; import javax.sip.*; /** * Implements all the support classes that are necessary for the nist-sip stack * on which the jain-sip stack has been based. This is a mapping class to map * from the NIST-SIP abstractions to the JAIN abstractions. (i.e. It is the glue * code that ties the NIST-SIP event model and the JAIN-SIP event model * together. When a SIP Request or SIP Response is read from the corresponding * messageChannel, the NIST-SIP stack calls the SIPStackMessageFactory * implementation that has been registered with it to process the request.) * * @version 1.2 $Revision: 1.14 $ $Date: 2009/07/29 20:38:17 $ * * @author M. Ranganathan
* * */ class NistSipMessageFactoryImpl implements StackMessageFactory { private SipStackImpl sipStack; /** * Construct a new SIP Server Request. * * @param sipRequest * is the SIPRequest from which the SIPServerRequest is to be * constructed. * @param messageChannel * is the MessageChannel abstraction for this SIPServerRequest. */ public ServerRequestInterface newSIPServerRequest(SIPRequest sipRequest, MessageChannel messageChannel) { if (messageChannel == null || sipRequest == null) { throw new IllegalArgumentException("Null Arg!"); } SipStackImpl theStack = (SipStackImpl) messageChannel.getSIPStack(); DialogFilter retval = new DialogFilter( theStack); if (messageChannel instanceof SIPTransaction) { // If the transaction has already been created // then set the transaction channel. retval.transactionChannel = (SIPTransaction) messageChannel; } retval.listeningPoint = messageChannel.getMessageProcessor() .getListeningPoint(); if (retval.listeningPoint == null) return null; if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug( "Returning request interface for " + sipRequest.getFirstLine() + " " + retval + " messageChannel = " + messageChannel); return retval; } /** * Generate a new server response for the stack. * * @param sipResponse * is the SIPRequest from which the SIPServerRequest is to be * constructed. * @param messageChannel * is the MessageChannel abstraction for this SIPServerResponse */ public ServerResponseInterface newSIPServerResponse( SIPResponse sipResponse, MessageChannel messageChannel) { SIPTransactionStack theStack = (SIPTransactionStack) messageChannel .getSIPStack(); // Tr is null if a transaction is not mapped. SIPTransaction tr = (SIPTransaction) ((SIPTransactionStack) theStack) .findTransaction(sipResponse, false); if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug( "Found Transaction " + tr + " for " + sipResponse); if (tr != null) { // Prune unhealthy responses early if handling statefully. // 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.getState() == null) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug( "Dropping response - null transaction state"); return null; // Ignore 1xx } else if (TransactionState.COMPLETED == tr.getState() && sipResponse.getStatusCode() / 100 == 1) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug( "Dropping response - late arriving " + sipResponse.getStatusCode()); return null; } } DialogFilter retval = new DialogFilter( sipStack); retval.transactionChannel = tr; retval.listeningPoint = messageChannel.getMessageProcessor() .getListeningPoint(); return retval; } public NistSipMessageFactoryImpl(SipStackImpl sipStackImpl) { this.sipStack = sipStackImpl; } }java/gov/nist/javax/sip/ResponseEventExt.java0100644 0000000 0000000 00000003013 13513104763 020326 0ustar000000000 0000000 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. * * @since v2.0 */ public class ResponseEventExt extends ResponseEvent { 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 super.getClientTransaction() == null && m_originalTransaction != null; } /** * Set the original transaction for a forked response. * * @param originalTransaction - the original transaction for which this response event is a fork. */ 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. * * @return the original clientTx for which this is a forked response. */ public ClientTransactionExt getOriginalTransaction() { return this.m_originalTransaction; } } java/gov/nist/javax/sip/SIPConstants.java0100644 0000000 0000000 00000004460 13513104763 017404 0ustar000000000 0000000 /* * 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.javax.sip; import gov.nist.javax.sip.header.*; /** * Default constants for SIP. * @version 1.2 $Revision: 1.9 $ $Date: 2009/07/17 18:57:20 $ */ public interface SIPConstants extends SIPHeaderNames, gov.nist.javax.sip.address.ParameterNames, gov.nist.javax.sip.header.ParameterNames { public static final int DEFAULT_PORT = 5060; // Added by Daniel J. Martinez Manzano public static final int DEFAULT_TLS_PORT = 5061; /** * Prefix for the branch parameter that identifies * BIS 09 compatible branch strings. This indicates * that the branch may be as a global identifier for * identifying transactions. */ public static final String BRANCH_MAGIC_COOKIE = "z9hG4bK"; public static final String BRANCH_MAGIC_COOKIE_LOWER_CASE = "z9hg4bk"; public static final String BRANCH_MAGIC_COOKIE_UPPER_CASE = "Z9HG4BK"; /** * constant SIP_VERSION_STRING */ public static final String SIP_VERSION_STRING = "SIP/2.0"; } java/gov/nist/javax/sip/ServerTransactionExt.java0100644 0000000 0000000 00000000622 13513104763 021205 0ustar000000000 0000000 package gov.nist.javax.sip; import javax.sip.ServerTransaction; public interface ServerTransactionExt extends ServerTransaction, TransactionExt { /** * Return the canceled Invite transaction corresponding to an * incoming CANCEL server transaction. * * @return -- the canceled Invite transaction. * */ public ServerTransaction getCanceledInviteTransaction(); } java/gov/nist/javax/sip/SipListenerExt.java0100644 0000000 0000000 00000004260 13513104763 017774 0ustar000000000 0000000 /* * This source code has been contributed to the public domain by Mobicents * * 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; import javax.sip.Dialog; import javax.sip.SipListener; /** * This interface extends the {@link SipListener} interface and adds the following events to it : *
    *
  • {@link DialogTimeoutEvent}- these are timeout notifications emitted as events by the * SipProvider. Timeout events represent timers expiring in the underlying SipProvider dialog * state machine. These timeout's events notify the application that a dialog has timed out.
  • *
* * @author jean.deruelle@gmail.com * */ public interface SipListenerExt extends SipListener { /** * Processes an expiration Timeout of an underlying {@link Dialog} handled by this * SipListener. This Event notifies the application that a dialog Timer expired in the * Dialog's state machine. Such a condition can occur when the application fails to send an * ACK after receiving an OK response or if an ACK is not received after an OK is sent. The * DialogTimeoutEvent encapsulates the specific timeout type and the dialog identifier. The * type of Timeout can by determined by: * timeoutType = timeoutEvent.getTimeout().getValue(); * * Applications implementing this method should take care of sending the BYE or terminating * the dialog to avoid any dialog leaks. * * @param timeoutEvent - the timeoutEvent received indicating the dialog timed out. */ public void processDialogTimeout(DialogTimeoutEvent timeoutEvent); } java/gov/nist/javax/sip/SipProviderExt.java0100644 0000000 0000000 00000003336 13513104763 020004 0ustar000000000 0000000 package gov.nist.javax.sip; import javax.sip.SipProvider; /** * Extensions to SipProvider under consideration for Version 2.0. * * @since 2.0 */ public interface SipProviderExt extends SipProvider { /** * Sets a flag that indicates that automatic error handling is enabled for this dialog (the * default when automatic dialog support is enabled). This flag is set by default to TRUE when * the Dialog is automatically created by the provider ( automatic dialog support is true) and * set to FALSE by default when the Dialog is created under program control ( automatic dialog * support is false). When this flag is set to true, the stack will automatically send the * following errors : * *
    *
  • 500 Request Out of Order for in-dialog requests that arrive out of order. *
  • 482 Loop Detected When a loop is detected for merged INVITE requests. *
  • 400 Bad request when a REFER is sent without a matching refer-to dialog. *
* If this flag is set to false, the stack will not drop out of sequence ACKs but will pass * these up to the application for handling. * * This flag is automatically set to true if any of the the following conditions is true: *
    *
  • The Back To Back User Agent flag is enabled for the Dialog.
  • *
  • The Automatic Dialog Support flag is enabled for the Dialog
  • *
* * This flag should only be set at the time of Dialog creation ( before the Dialog has seen its first * request or response). If set subsequently, the behavior of the flag is undefined. * * @since 2.0 */ public void setDialogErrorsAutomaticallyHandled(); } java/gov/nist/javax/sip/SipProviderImpl.java0100644 0000000 0000000 00000127045 13513104763 020151 0ustar000000000 0000000 /* * 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.javax.sip; import gov.nist.core.InternalErrorHandler; import gov.nist.javax.sip.DialogTimeoutEvent.Reason; import gov.nist.javax.sip.address.RouterExt; import gov.nist.javax.sip.header.CallID; import gov.nist.javax.sip.header.Via; 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.HopImpl; import gov.nist.javax.sip.stack.MessageChannel; import gov.nist.javax.sip.stack.SIPClientTransaction; import gov.nist.javax.sip.stack.SIPDialog; import gov.nist.javax.sip.stack.SIPDialogErrorEvent; import gov.nist.javax.sip.stack.SIPDialogEventListener; import gov.nist.javax.sip.stack.SIPServerTransaction; import gov.nist.javax.sip.stack.SIPTransaction; import gov.nist.javax.sip.stack.SIPTransactionErrorEvent; import gov.nist.javax.sip.stack.SIPTransactionEventListener; import java.io.IOException; import java.text.ParseException; import java.util.EventObject; import java.util.Iterator; import java.util.TooManyListenersException; import java.util.concurrent.ConcurrentHashMap; import javax.sip.ClientTransaction; import javax.sip.Dialog; import javax.sip.DialogState; import javax.sip.InvalidArgumentException; import javax.sip.ListeningPoint; import javax.sip.ObjectInUseException; import javax.sip.RequestEvent; import javax.sip.ResponseEvent; import javax.sip.ServerTransaction; import javax.sip.SipException; import javax.sip.SipListener; import javax.sip.SipStack; import javax.sip.Timeout; import javax.sip.TimeoutEvent; import javax.sip.Transaction; import javax.sip.TransactionAlreadyExistsException; import javax.sip.TransactionState; import javax.sip.TransactionUnavailableException; import javax.sip.address.Hop; import javax.sip.header.CallIdHeader; import javax.sip.message.Request; import javax.sip.message.Response; /* * Contributions (bug fixes) made by: Daniel J. Martinez Manzano, Hagai Sela. * Bug reports by Shanti Kadiyala, Rhys Ulerich,Victor Hugo */ /** * Implementation of the JAIN-SIP provider interface. * * @version 1.2 $Revision: 1.82 $ $Date: 2009/11/24 17:16:59 $ * * @author M. Ranganathan
* * */ public class SipProviderImpl implements javax.sip.SipProvider, gov.nist.javax.sip.SipProviderExt, SIPTransactionEventListener, SIPDialogEventListener { private SipListener sipListener; protected SipStackImpl sipStack; /* * A set of listening points associated with the provider At most one LP per * transport */ private ConcurrentHashMap listeningPoints; private EventScanner eventScanner; private String address; private int port; private boolean automaticDialogSupportEnabled ; /** * A string containing the 0.0.0.0 IPv4 ANY address. */ private String IN_ADDR_ANY = "0.0.0.0"; /** * A string containing the ::0 IPv6 ANY address. */ private String IN6_ADDR_ANY = "::0"; private boolean dialogErrorsAutomaticallyHandled = true; private SipProviderImpl() { } /** * Stop processing messages for this provider. Post an empty message to our * message processing queue that signals us to quit. */ protected void stop() { // Put an empty event in the queue and post ourselves a message. if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("Exiting provider"); for (Iterator it = listeningPoints.values().iterator(); it.hasNext();) { ListeningPointImpl listeningPoint = (ListeningPointImpl) it.next(); listeningPoint.removeSipProvider(); } this.eventScanner.stop(); } /* * (non-Javadoc) * * @see javax.sip.SipProvider#getListeningPoint(java.lang.String) */ public ListeningPoint getListeningPoint(String transport) { if (transport == null) throw new NullPointerException("Null transport param"); return (ListeningPoint) this.listeningPoints.get(transport .toUpperCase()); } /** * Handle the SIP event - because we have only one listener and we are * already in the context of a separate thread, we dont need to enque the * event and signal another thread. * * @param sipEvent * is the event to process. * */ public void handleEvent(EventObject sipEvent, SIPTransaction transaction) { if (sipStack.isLoggingEnabled()) { 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 ( sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("Dialog = " + dialog); } else if (sipEvent instanceof ResponseEvent) { Dialog dialog = ((ResponseEvent) sipEvent).getDialog(); if (sipStack.isLoggingEnabled() ) sipStack.getStackLogger().logDebug("Dialog = " + dialog); } sipStack.getStackLogger().logStackTrace(); } EventWrapper eventWrapper = new EventWrapper(sipEvent, transaction); if (!sipStack.reEntrantListener) { // Run the event in the context of a single thread. this.eventScanner.addEvent(eventWrapper); } else { // just call the delivery method this.eventScanner.deliverEvent(eventWrapper); } } /** Creates a new instance of SipProviderImpl */ protected SipProviderImpl(SipStackImpl sipStack) { this.eventScanner = sipStack.getEventScanner(); // for quick access. this.sipStack = sipStack; this.eventScanner.incrementRefcount(); this.listeningPoints = new ConcurrentHashMap(); this.automaticDialogSupportEnabled = this.sipStack .isAutomaticDialogSupportEnabled(); this.dialogErrorsAutomaticallyHandled = this.sipStack.isAutomaticDialogErrorHandlingEnabled(); } /* * (non-Javadoc) * * @see java.lang.Object#clone() */ protected Object clone() throws java.lang.CloneNotSupportedException { throw new java.lang.CloneNotSupportedException(); } /* * (non-Javadoc) * * @see javax.sip.SipProvider#addSipListener(javax.sip.SipListener) */ public void addSipListener(SipListener sipListener) throws TooManyListenersException { if (sipStack.sipListener == null) { sipStack.sipListener = sipListener; } else if (sipStack.sipListener != sipListener) { throw new TooManyListenersException( "Stack already has a listener. Only one listener per stack allowed"); } if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("add SipListener " + sipListener); this.sipListener = sipListener; } /* * This method is deprecated (non-Javadoc) * * @see javax.sip.SipProvider#getListeningPoint() */ public ListeningPoint getListeningPoint() { if (this.listeningPoints.size() > 0) return (ListeningPoint) this.listeningPoints.values().iterator() .next(); else return null; } /* * (non-Javadoc) * * @see javax.sip.SipProvider#getNewCallId() */ public CallIdHeader getNewCallId() { String callId = Utils.getInstance().generateCallIdentifier(this.getListeningPoint() .getIPAddress()); CallID callid = new CallID(); try { callid.setCallId(callId); } catch (java.text.ParseException ex) { } return callid; } /* * (non-Javadoc) * * @see javax.sip.SipProvider#getNewClientTransaction(javax.sip.message.Request) */ public ClientTransaction getNewClientTransaction(Request request) throws TransactionUnavailableException { if (request == null) throw new NullPointerException("null request"); if (!sipStack.isAlive()) throw new TransactionUnavailableException("Stack is stopped"); SIPRequest sipRequest = (SIPRequest) request; if (sipRequest.getTransaction() != null) throw new TransactionUnavailableException( "Transaction already assigned to request"); if ( sipRequest.getMethod().equals(Request.ACK)) { throw new TransactionUnavailableException ("Cannot create client transaction for " + Request.ACK); } // Be kind and assign a via header for this provider if the user is // sloppy if (sipRequest.getTopmostVia() == null) { ListeningPointImpl lp = (ListeningPointImpl) this .getListeningPoint("udp"); Via via = lp.getViaHeader(); request.setHeader(via); } // Give the request a quick check to see if all headers are assigned. try { sipRequest.checkHeaders(); } catch (ParseException ex) { throw new TransactionUnavailableException(ex.getMessage(), ex); } /* * User decided to give us his own via header branch. Lets see if it * results in a clash. If so reject the request. */ if (sipRequest.getTopmostVia().getBranch() != null && sipRequest.getTopmostVia().getBranch().startsWith( SIPConstants.BRANCH_MAGIC_COOKIE) && sipStack.findTransaction((SIPRequest) request, false) != null) { throw new TransactionUnavailableException( "Transaction already exists!"); } if (request.getMethod().equalsIgnoreCase(Request.CANCEL)) { SIPClientTransaction ct = (SIPClientTransaction) sipStack .findCancelTransaction((SIPRequest) request, false); if (ct != null) { ClientTransaction retval = sipStack.createClientTransaction( (SIPRequest) request, ct.getMessageChannel()); ((SIPTransaction) retval).addEventListener(this); sipStack.addTransaction((SIPClientTransaction) retval); if (ct.getDialog() != null) { ((SIPClientTransaction) retval).setDialog((SIPDialog) ct .getDialog(), sipRequest.getDialogId(false)); } return retval; } } if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug( "could not find existing transaction for " + ((SIPRequest) request).getFirstLine() + " creating a new one "); // Could not find a dialog or the route is not set in dialog. Hop hop = null; try { hop = sipStack.getNextHop((SIPRequest) request); if (hop == null) throw new TransactionUnavailableException( "Cannot resolve next hop -- transaction unavailable"); } catch (SipException ex) { throw new TransactionUnavailableException( "Cannot resolve next hop -- transaction unavailable", ex); } String transport = hop.getTransport(); ListeningPointImpl listeningPoint = (ListeningPointImpl) this .getListeningPoint(transport); String dialogId = sipRequest.getDialogId(false); SIPDialog dialog = sipStack.getDialog(dialogId); if (dialog != null && dialog.getState() == DialogState.TERMINATED) { // throw new TransactionUnavailableException // ("Found a terminated dialog -- possible re-use of old tag // parameters"); sipStack.removeDialog(dialog); } // An out of dialog route was found. Assign this to the // client transaction. try { // Set the brannch id before you ask for a tx. // If the user has set his own branch Id and the // branch id starts with a valid prefix, then take it. // otherwise, generate one. If branch ID checking has // been requested, set the branch ID. String branchId = null; if (sipRequest.getTopmostVia().getBranch() == null || !sipRequest.getTopmostVia().getBranch().startsWith( SIPConstants.BRANCH_MAGIC_COOKIE) || sipStack.checkBranchId() ) { branchId = Utils.getInstance().generateBranchId(); sipRequest.getTopmostVia().setBranch(branchId); } Via topmostVia = sipRequest.getTopmostVia(); //set port and transport if user hasn't already done this. if(topmostVia.getTransport() == null) topmostVia.setTransport(transport); if(topmostVia.getPort() == -1) topmostVia.setPort(listeningPoint.getPort()); branchId = sipRequest.getTopmostVia().getBranch(); SIPClientTransaction ct = (SIPClientTransaction) sipStack .createMessageChannel(sipRequest, listeningPoint .getMessageProcessor(), hop); if (ct == null) throw new TransactionUnavailableException("Cound not create tx"); ct.setNextHop(hop); ct.setOriginalRequest(sipRequest); ct.setBranch(branchId); // if the stack supports dialogs then if (sipStack.isDialogCreated(request.getMethod())) { // create a new dialog to contain this transaction // provided this is necessary. // This could be a re-invite // in which case the dialog is re-used. // (but noticed by Brad Templeton) if (dialog != null) ct.setDialog(dialog, sipRequest.getDialogId(false)); else if (this.isAutomaticDialogSupportEnabled()) { SIPDialog sipDialog = sipStack.createDialog(ct); ct.setDialog(sipDialog, sipRequest.getDialogId(false)); } } else { if (dialog != null) { ct.setDialog(dialog, sipRequest.getDialogId(false)); } } // The provider is the event listener for all transactions. ct.addEventListener(this); return (ClientTransaction) ct; } catch (IOException ex) { throw new TransactionUnavailableException( "Could not resolve next hop or listening point unavailable! ", ex); } catch (java.text.ParseException ex) { InternalErrorHandler.handleException(ex); throw new TransactionUnavailableException( "Unexpected Exception FIXME! ", ex); } catch (InvalidArgumentException ex) { InternalErrorHandler.handleException(ex); throw new TransactionUnavailableException( "Unexpected Exception FIXME! ", ex); } } /* * (non-Javadoc) * * @see javax.sip.SipProvider#getNewServerTransaction(javax.sip.message.Request) */ public ServerTransaction getNewServerTransaction(Request request) throws TransactionAlreadyExistsException, TransactionUnavailableException { if (!sipStack.isAlive()) throw new TransactionUnavailableException("Stack is stopped"); SIPServerTransaction transaction = null; SIPRequest sipRequest = (SIPRequest) request; try { sipRequest.checkHeaders(); } catch (ParseException ex) { throw new TransactionUnavailableException(ex.getMessage(), ex); } if ( request.getMethod().equals(Request.ACK)) { if ( sipStack.isLoggingEnabled()) sipStack.getStackLogger().logError("Creating server transaction for ACK -- makes no sense!"); throw new TransactionUnavailableException("Cannot create Server transaction for ACK "); } /* * Got a notify. */ if (sipRequest.getMethod().equals(Request.NOTIFY) && sipRequest.getFromTag() != null && sipRequest.getToTag() == null) { SIPClientTransaction ct = sipStack.findSubscribeTransaction( sipRequest, (ListeningPointImpl) this.getListeningPoint()); /* Issue 104 */ if (ct == null && ! sipStack.deliverUnsolicitedNotify) { throw new TransactionUnavailableException( "Cannot find matching Subscription (and gov.nist.javax.sip.DELIVER_UNSOLICITED_NOTIFY not set)"); } } if ( !sipStack.acquireSem()) { throw new TransactionUnavailableException( "Transaction not available -- could not acquire stack lock"); } try { if (sipStack.isDialogCreated(sipRequest.getMethod())) { if (sipStack.findTransaction((SIPRequest) request, true) != null) throw new TransactionAlreadyExistsException( "server transaction already exists!"); transaction = (SIPServerTransaction) ((SIPRequest) request) .getTransaction(); if (transaction == null) throw new TransactionUnavailableException( "Transaction not available"); if (transaction.getOriginalRequest() == null) transaction.setOriginalRequest(sipRequest); try { sipStack.addTransaction(transaction); } catch (IOException ex) { throw new TransactionUnavailableException( "Error sending provisional response"); } // So I can handle timeouts. transaction.addEventListener(this); if (isAutomaticDialogSupportEnabled()) { // If automatic dialog support is enabled then // this tx gets his own dialog. String dialogId = sipRequest.getDialogId(true); SIPDialog dialog = sipStack.getDialog(dialogId); if (dialog == null) { dialog = sipStack.createDialog(transaction); } transaction.setDialog(dialog, sipRequest.getDialogId(true)); if (sipRequest.getMethod().equals(Request.INVITE) && this.isDialogErrorsAutomaticallyHandled()) { sipStack.putInMergeTable(transaction, sipRequest); } dialog.addRoute(sipRequest); if (dialog.getRemoteTag() != null && dialog.getLocalTag() != null) { this.sipStack.putDialog(dialog); } } } else { if (isAutomaticDialogSupportEnabled()) { /* * Under automatic dialog support, dialog is tied into a transaction. You cannot * create a server tx except for dialog creating transactions. After that, all * subsequent transactions are created for you by the stack. */ transaction = (SIPServerTransaction) sipStack.findTransaction( (SIPRequest) request, true); if (transaction != null) throw new TransactionAlreadyExistsException( "Transaction exists! "); transaction = (SIPServerTransaction) ((SIPRequest) request) .getTransaction(); if (transaction == null) throw new TransactionUnavailableException( "Transaction not available!"); if (transaction.getOriginalRequest() == null) transaction.setOriginalRequest(sipRequest); // Map the transaction. try { sipStack.addTransaction(transaction); } catch (IOException ex) { throw new TransactionUnavailableException( "Could not send back provisional response!"); } // If there is a dialog already assigned then just update the // dialog state. String dialogId = sipRequest.getDialogId(true); SIPDialog dialog = sipStack.getDialog(dialogId); if (dialog != null) { dialog.addTransaction(transaction); dialog.addRoute(sipRequest); transaction.setDialog(dialog, sipRequest.getDialogId(true)); } } else { transaction = (SIPServerTransaction) sipStack.findTransaction( (SIPRequest) request, true); if (transaction != null) throw new TransactionAlreadyExistsException( "Transaction exists! "); transaction = (SIPServerTransaction) ((SIPRequest) request) .getTransaction(); if (transaction != null) { if (transaction.getOriginalRequest() == null) transaction.setOriginalRequest(sipRequest); // Map the transaction. sipStack.mapTransaction(transaction); // If there is a dialog already assigned then just // assign the dialog to the transaction. String dialogId = sipRequest.getDialogId(true); SIPDialog dialog = sipStack.getDialog(dialogId); if (dialog != null) { dialog.addTransaction(transaction); dialog.addRoute(sipRequest); transaction.setDialog(dialog, sipRequest .getDialogId(true)); } return transaction; } else { // tx does not exist so create the tx. MessageChannel mc = (MessageChannel) sipRequest .getMessageChannel(); transaction = sipStack.createServerTransaction(mc); if (transaction == null) throw new TransactionUnavailableException( "Transaction unavailable -- too many servrer transactions"); transaction.setOriginalRequest(sipRequest); sipStack.mapTransaction(transaction); // If there is a dialog already assigned then just // assign the dialog to the transaction. String dialogId = sipRequest.getDialogId(true); SIPDialog dialog = sipStack.getDialog(dialogId); if (dialog != null) { dialog.addTransaction(transaction); dialog.addRoute(sipRequest); transaction.setDialog(dialog, sipRequest .getDialogId(true)); } return transaction; } } } return transaction; } finally { sipStack.releaseSem(); } } /* * (non-Javadoc) * * @see javax.sip.SipProvider#getSipStack() */ public SipStack getSipStack() { return (SipStack) this.sipStack; } /* * (non-Javadoc) * * @see javax.sip.SipProvider#removeSipListener(javax.sip.SipListener) */ public void removeSipListener(SipListener sipListener) { if (sipListener == this.getSipListener()) { this.sipListener = null; } boolean found = false; for (Iterator it = sipStack.getSipProviders(); it.hasNext();) { SipProviderImpl nextProvider = (SipProviderImpl) it.next(); if (nextProvider.getSipListener() != null) found = true; } if (!found) { sipStack.sipListener = null; } } /* * (non-Javadoc) * * @see javax.sip.SipProvider#sendRequest(javax.sip.message.Request) */ public void sendRequest(Request request) throws SipException { if (!sipStack.isAlive()) throw new SipException("Stack is stopped."); // mranga: added check to ensure we are not sending empty (keepalive) // message. if (((SIPRequest) request).getRequestLine() != null && request.getMethod().equals(Request.ACK)) { Dialog dialog = sipStack.getDialog(((SIPRequest) request) .getDialogId(false)); if (dialog != null && dialog.getState() != null) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logWarning( "Dialog exists -- you may want to use Dialog.sendAck() " + dialog.getState()); } } Hop hop = sipStack.getRouter((SIPRequest) request).getNextHop(request); if (hop == null) throw new SipException("could not determine next hop!"); SIPRequest sipRequest = (SIPRequest) request; // Check if we have a valid via. // Null request is used to send default proxy keepalive messages. if ((!sipRequest.isNullRequest()) && sipRequest.getTopmostVia() == null) throw new SipException("Invalid SipRequest -- no via header!"); try { /* * JvB: Via branch should already be OK, dont touch it here? Some * apps forward statelessly, and then it's not set. So set only when * not set already, dont overwrite CANCEL branch here.. */ if (!sipRequest.isNullRequest()) { Via via = sipRequest.getTopmostVia(); String branch = via.getBranch(); if (branch == null || branch.length() == 0) { via.setBranch(sipRequest.getTransactionId()); } } MessageChannel messageChannel = null; if (this.listeningPoints.containsKey(hop.getTransport() .toUpperCase())) messageChannel = sipStack.createRawMessageChannel( this.getListeningPoint(hop.getTransport()).getIPAddress(), this.getListeningPoint(hop.getTransport()).getPort(), hop); if (messageChannel != null) { messageChannel.sendMessage((SIPMessage) sipRequest,hop); } else { throw new SipException( "Could not create a message channel for " + hop.toString()); } } catch (IOException ex) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logException(ex); } throw new SipException( "IO Exception occured while Sending Request", ex); } catch (ParseException ex1) { InternalErrorHandler.handleException(ex1); } finally { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug( "done sending " + request.getMethod() + " to hop " + hop); } } /* * (non-Javadoc) * * @see javax.sip.SipProvider#sendResponse(javax.sip.message.Response) */ public void sendResponse(Response response) throws SipException { if (!sipStack.isAlive()) throw new SipException("Stack is stopped"); SIPResponse sipResponse = (SIPResponse) response; Via via = sipResponse.getTopmostVia(); if (via == null) throw new SipException("No via header in response!"); SIPServerTransaction st = (SIPServerTransaction) sipStack.findTransaction((SIPMessage)response, true); if ( st != null && st.getState() != TransactionState.TERMINATED && this.isAutomaticDialogSupportEnabled()) { throw new SipException("Transaction exists -- cannot send response statelessly"); } String transport = via.getTransport(); // check to see if Via has "received paramaeter". If so // set the host to the via parameter. Else set it to the // Via host. String host = via.getReceived(); if (host == null) host = via.getHost(); // Symmetric nat support int port = via.getRPort(); if (port == -1) { port = via.getPort(); if (port == -1) { if (transport.equalsIgnoreCase("TLS")) port = 5061; else port = 5060; } } // for correct management of IPv6 addresses. if (host.indexOf(":") > 0) if (host.indexOf("[") < 0) host = "[" + host + "]"; Hop hop = sipStack.getAddressResolver().resolveAddress( new HopImpl(host, port, transport)); try { ListeningPointImpl listeningPoint = (ListeningPointImpl) this .getListeningPoint(transport); if (listeningPoint == null) throw new SipException( "whoopsa daisy! no listening point found for transport " + transport); MessageChannel messageChannel = sipStack.createRawMessageChannel( this.getListeningPoint(hop.getTransport()).getIPAddress(), listeningPoint.port, hop); messageChannel.sendMessage(sipResponse); } catch (IOException ex) { throw new SipException(ex.getMessage()); } } /* * (non-Javadoc) * * @see javax.sip.SipProvider#setListeningPoint(javax.sip.ListeningPoint) */ public synchronized void setListeningPoint(ListeningPoint listeningPoint) { if (listeningPoint == null) throw new NullPointerException("Null listening point"); ListeningPointImpl lp = (ListeningPointImpl) listeningPoint; lp.sipProvider = this; String transport = lp.getTransport().toUpperCase(); this.address = listeningPoint.getIPAddress(); this.port = listeningPoint.getPort(); // This is the first listening point. this.listeningPoints.clear(); this.listeningPoints.put(transport, listeningPoint); } /* * (non-Javadoc) * * @see javax.sip.SipProvider#getNewDialog(javax.sip.Transaction) */ public Dialog getNewDialog(Transaction transaction) throws SipException { if (transaction == null) throw new NullPointerException("Null transaction!"); if (!sipStack.isAlive()) throw new SipException("Stack is stopped."); if (isAutomaticDialogSupportEnabled()) throw new SipException(" Error - AUTOMATIC_DIALOG_SUPPORT is on"); if (!sipStack.isDialogCreated(transaction.getRequest().getMethod())) throw new SipException("Dialog cannot be created for this method " + transaction.getRequest().getMethod()); SIPDialog dialog = null; SIPTransaction sipTransaction = (SIPTransaction) transaction; if (transaction instanceof ServerTransaction) { SIPServerTransaction st = (SIPServerTransaction) transaction; Response response = st.getLastResponse(); if (response != null) { if (response.getStatusCode() != 100) throw new SipException( "Cannot set dialog after response has been sent"); } SIPRequest sipRequest = (SIPRequest) transaction.getRequest(); String dialogId = sipRequest.getDialogId(true); dialog = sipStack.getDialog(dialogId); if (dialog == null) { dialog = sipStack.createDialog((SIPTransaction) transaction); // create and register the dialog and add the inital route set. dialog.addTransaction(sipTransaction); dialog.addRoute(sipRequest); sipTransaction.setDialog(dialog, null); } else { sipTransaction.setDialog(dialog, sipRequest.getDialogId(true)); } if (sipRequest.getMethod().equals(Request.INVITE) && this.isDialogErrorsAutomaticallyHandled()) { sipStack.putInMergeTable(st, sipRequest); } } else { SIPClientTransaction sipClientTx = (SIPClientTransaction) transaction; SIPResponse response = sipClientTx.getLastResponse(); if (response == null) { // A response has not yet been received, then set this up as the // default dialog. SIPRequest request = (SIPRequest) sipClientTx.getRequest(); String dialogId = request.getDialogId(false); dialog = sipStack.getDialog(dialogId); if (dialog != null) { throw new SipException("Dialog already exists!"); } else { dialog = sipStack.createDialog(sipTransaction); } sipClientTx.setDialog(dialog, null); } else { throw new SipException( "Cannot call this method after response is received!"); } } dialog.addEventListener(this); return dialog; } /** * Invoked when an error has ocurred with a transaction. Propagate up to the * listeners. * * @param transactionErrorEvent * Error event. */ public void transactionErrorEvent( SIPTransactionErrorEvent transactionErrorEvent) { SIPTransaction transaction = (SIPTransaction) transactionErrorEvent .getSource(); if (transactionErrorEvent.getErrorID() == SIPTransactionErrorEvent.TRANSPORT_ERROR) { // There must be a way to inform the TU here!! if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "TransportError occured on " + transaction); } // Treat this like a timeout event. (Suggestion from Christophe). Object errorObject = transactionErrorEvent.getSource(); Timeout timeout = Timeout.TRANSACTION; TimeoutEvent ev = null; if (errorObject instanceof SIPServerTransaction) { ev = new TimeoutEvent(this, (ServerTransaction) errorObject, timeout); } else { SIPClientTransaction clientTx = (SIPClientTransaction) errorObject; Hop hop = clientTx.getNextHop(); if ( sipStack.getRouter() instanceof RouterExt ) { ((RouterExt) sipStack.getRouter()).transactionTimeout(hop); } ev = new TimeoutEvent(this, (ClientTransaction) errorObject, timeout); } // Handling transport error like timeout this.handleEvent(ev, (SIPTransaction) errorObject); } else if (transactionErrorEvent.getErrorID() == SIPTransactionErrorEvent.TIMEOUT_ERROR) { // This is a timeout event. Object errorObject = transactionErrorEvent.getSource(); Timeout timeout = Timeout.TRANSACTION; TimeoutEvent ev = null; if (errorObject instanceof SIPServerTransaction) { ev = new TimeoutEvent(this, (ServerTransaction) errorObject, timeout); } else { SIPClientTransaction clientTx = (SIPClientTransaction) errorObject; Hop hop = clientTx.getNextHop(); if ( sipStack.getRouter() instanceof RouterExt ) { ((RouterExt) sipStack.getRouter()).transactionTimeout(hop); } ev = new TimeoutEvent(this, (ClientTransaction) errorObject, timeout); } this.handleEvent(ev, (SIPTransaction) errorObject); } else if (transactionErrorEvent.getErrorID() == SIPTransactionErrorEvent.TIMEOUT_RETRANSMIT) { // This is a timeout retransmit event. // We should never get this if retransmit filter is // enabled (ie. in that case the stack should handle. // all retransmits. Object errorObject = transactionErrorEvent.getSource(); Transaction tx = (Transaction) errorObject; if (tx.getDialog() != null) InternalErrorHandler.handleException("Unexpected event !", this.sipStack.getStackLogger()); Timeout timeout = Timeout.RETRANSMIT; TimeoutEvent ev = null; if (errorObject instanceof SIPServerTransaction) { ev = new TimeoutEvent(this, (ServerTransaction) errorObject, timeout); } else { ev = new TimeoutEvent(this, (ClientTransaction) errorObject, timeout); } this.handleEvent(ev, (SIPTransaction) errorObject); } } /* * (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(); 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; } if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "Dialog TimeoutError occured on " + sipDialog); } DialogTimeoutEvent ev = new DialogTimeoutEvent(this, sipDialog, reason); // Handling transport error like timeout this.handleEvent(ev, null); } /* * (non-Javadoc) * * @see javax.sip.SipProvider#getListeningPoints() */ public synchronized ListeningPoint[] getListeningPoints() { ListeningPoint[] retval = new ListeningPointImpl[this.listeningPoints .size()]; this.listeningPoints.values().toArray(retval); return retval; } /* * (non-Javadoc) * * @see javax.sip.SipProvider#addListeningPoint(javax.sip.ListeningPoint) */ public synchronized void addListeningPoint(ListeningPoint listeningPoint) throws ObjectInUseException { ListeningPointImpl lp = (ListeningPointImpl) listeningPoint; if (lp.sipProvider != null && lp.sipProvider != this) throw new ObjectInUseException( "Listening point assigned to another provider"); String transport = lp.getTransport().toUpperCase(); if (this.listeningPoints.isEmpty()) { // first one -- record the IP address/port of the LP this.address = listeningPoint.getIPAddress(); this.port = listeningPoint.getPort(); } else { if ((!this.address.equals(listeningPoint.getIPAddress())) || this.port != listeningPoint.getPort()) throw new ObjectInUseException( "Provider already has different IP Address associated"); } if (this.listeningPoints.containsKey(transport) && this.listeningPoints.get(transport) != listeningPoint) throw new ObjectInUseException( "Listening point already assigned for transport!"); // This is for backwards compatibility. lp.sipProvider = this; this.listeningPoints.put(transport, lp); } /* * (non-Javadoc) * * @see javax.sip.SipProvider#removeListeningPoint(javax.sip.ListeningPoint) */ public synchronized void removeListeningPoint(ListeningPoint listeningPoint) throws ObjectInUseException { ListeningPointImpl lp = (ListeningPointImpl) listeningPoint; if (lp.messageProcessor.inUse()) throw new ObjectInUseException("Object is in use"); this.listeningPoints.remove(lp.getTransport().toUpperCase()); } /** * Remove all the listening points for this sip provider. This is called * when the stack removes the Provider */ public synchronized void removeListeningPoints() { for (Iterator it = this.listeningPoints.values().iterator(); it .hasNext();) { ListeningPointImpl lp = (ListeningPointImpl) it.next(); lp.messageProcessor.stop(); it.remove(); } } /* * (non-Javadoc) * * @see javax.sip.SipProvider#setAutomaticDialogSupportEnabled(boolean) */ public void setAutomaticDialogSupportEnabled( boolean automaticDialogSupportEnabled) { this.automaticDialogSupportEnabled = automaticDialogSupportEnabled; if ( this.automaticDialogSupportEnabled ) { this.dialogErrorsAutomaticallyHandled = true; } } /** * @return Returns the automaticDialogSupportEnabled. */ public boolean isAutomaticDialogSupportEnabled() { return automaticDialogSupportEnabled; } /* * (non-Javadoc) * @see gov.nist.javax.sip.SipProviderExt#setDialogErrorsAutomaticallyHandled() */ public void setDialogErrorsAutomaticallyHandled() { this.dialogErrorsAutomaticallyHandled = true; } public boolean isDialogErrorsAutomaticallyHandled() { return this.dialogErrorsAutomaticallyHandled; } /** * @return the sipListener */ public SipListener getSipListener() { return sipListener; } } java/gov/nist/javax/sip/SipStackExt.java0100644 0000000 0000000 00000012123 13513104763 017251 0ustar000000000 0000000 package gov.nist.javax.sip; import gov.nist.core.net.AddressResolver; import gov.nist.javax.sip.clientauthutils.AccountManager; import gov.nist.javax.sip.clientauthutils.AuthenticationHelper; import gov.nist.javax.sip.clientauthutils.SecureAccountManager; import gov.nist.javax.sip.header.extensions.JoinHeader; import gov.nist.javax.sip.header.extensions.ReplacesHeader; import java.io.IOException; import java.net.InetAddress; import java.net.SocketAddress; import java.util.Collection; import javax.sip.Dialog; import javax.sip.SipStack; import javax.sip.header.HeaderFactory; /** * 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 *
* @author M. Ranganathan * */ public interface SipStackExt extends SipStack { /** * Get the collection of dialogs currently in the Dialog table. This is useful for debugging * purposes. * */ public Collection getDialogs(); /** * Get the ReferedTo dialog in the Replaces header. * * @return Dialog object matching the Replaces header, provided it is in an appropriate state * to be replaced, null otherwise * * @since 2.0 */ public Dialog getReplacesDialog(ReplacesHeader replacesHeader); /** * Get the authentication helper. * * * @param accountManager -- account manager (for fetching credentials). * @param headerFactory -- header factory. * * @return - the authentication helper which can be used for generating the appropriate * headers for handling authentication challenges for user agents. * * @since 2.0 */ public AuthenticationHelper getAuthenticationHelper(AccountManager accountManager, HeaderFactory headerFactory); /** * Get the authentication helper. * * * @param accountManager -- account manager (for fetching credentials). * @param headerFactory -- header factory. * * @return - the authentication helper which can be used for generating the appropriate * headers for handling authentication challenges for user agents. * * @since 2.0 */ public AuthenticationHelper getSecureAuthenticationHelper(SecureAccountManager accountManager, HeaderFactory headerFactory); /** * Set the address resolution interface. The address resolver allows you to register custom * lookup schemes ( for example DNS SRV lookup ) that are not directly supported by the JDK. * * @param addressResolver -- the address resolver to set. * * @since 2.0 */ public void setAddressResolver(AddressResolver addressResolver); /** * Get the dialog in the Join header. * * @return Dialog object matching the Join header, provided it is in an appropriate state to * be replaced, null otherwise * * @since 2.0 */ public Dialog getJoinDialog(JoinHeader joinHeader); /** * Set the list of cipher suites supported by the stack. A stack can have only one set of * suites. These are not validated against the supported cipher suites of the java runtime, so * specifying a cipher here does not guarantee that it will work.
* The stack has a default cipher suite of: *
    *
  • TLS_RSA_WITH_AES_128_CBC_SHA
  • *
  • SSL_RSA_WITH_3DES_EDE_CBC_SHA
  • *
  • TLS_DH_anon_WITH_AES_128_CBC_SHA
  • *
  • SSL_DH_anon_WITH_3DES_EDE_CBC_SHA
  • *
* * NOTE: This function must be called before adding a TLS listener * * @since 2.0 * @param newCipherSuites -- The new set of ciphers to support. * */ public void setEnabledCipherSuites(String[] newCipherSuites); /** * Creates and binds, if necessary, a TCP 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; } java/gov/nist/javax/sip/SipStackImpl.java0100644 0000000 0000000 00000161042 13513104763 017417 0ustar000000000 0000000 /* * 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; import gov.nist.core.ServerLogger; import gov.nist.core.StackLogger; import gov.nist.core.net.AddressResolver; import gov.nist.core.net.NetworkLayer; import gov.nist.core.net.SslNetworkLayer; import gov.nist.javax.sip.clientauthutils.AccountManager; import gov.nist.javax.sip.clientauthutils.AuthenticationHelper; import gov.nist.javax.sip.clientauthutils.AuthenticationHelperImpl; import gov.nist.javax.sip.clientauthutils.SecureAccountManager; import gov.nist.javax.sip.parser.StringMsgParser; 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.SIPTransactionStack; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.net.InetAddress; import java.util.Hashtable; import java.util.LinkedList; import java.util.Properties; import java.util.StringTokenizer; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import javax.sip.InvalidArgumentException; import javax.sip.ListeningPoint; import javax.sip.ObjectInUseException; import javax.sip.PeerUnavailableException; import javax.sip.ProviderDoesNotExistException; import javax.sip.SipException; import javax.sip.SipListener; import javax.sip.SipProvider; import javax.sip.SipStack; import javax.sip.TransportNotSupportedException; import javax.sip.address.Router; import javax.sip.header.HeaderFactory; import javax.sip.message.Request; /** * Implementation of SipStack. * * 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} ). 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): *
    * *
  • gov.nist.javax.sip.TRACE_LEVEL = integer
    * Use of this property is still supported but deprecated. Please use * gov.nist.javax.sip.STACK_LOGGER and gov.nist.javax.sip.SERVER_LOGGER for * integration with logging frameworks and for custom formatting of log records. * This property is used by the built in log4j based logger. You can use * the standard log4j level names here (i.e. ERROR, INFO, WARNING, OFF, DEBUG, * TRACE) If this is set to INFO or above, then incoming valid messages are * logged in SERVER_LOG. If you set this to 32 and specify a DEBUG_LOG then vast * amounts of trace information will be dumped in to the specified DEBUG_LOG. * The server log accumulates the signaling trace. This can be viewed using the trace * viewer tool . Please send us both the server log and debug log when * reporting non-obvious problems. You can also use the strings DEBUG or INFO * for level 32 and 16 respectively. If the value of this property is set to * LOG4J, then the effective log levels are determined from the log4j settings * file (e.g. log4j.properties). The logger name for the stack is specified * using the gov.nist.javax.sip.LOG4J_LOGGER_NAME property. By default log4j * logger name for the stack is the same as the stack name. For example, * properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "LOG4J"); * properties.setProperty("gov.nist.javax.sip.LOG4J_LOGGER_NAME", "SIPStackLogger"); * allows you to now control logging in the stack entirely using log4j * facilities.
  • * *
  • gov.nist.javax.sip.LOG_FACTORY = classpath Use of this * property is still supported but deprecated. Please use * gov.nist.javax.sip.STACK_LOGGER and gov.nist.javax.sip.SERVER_LOGGER for * integration with logging frameworks and for custom formatting of log records. *
    * The fully qualified classpath for an implementation of the MessageLogFactory. * The stack calls the MessageLogFactory functions to format the log for * messages that are received or sent. This function allows you to log auxiliary * information related to the application or environmental conditions into the * log stream. The log factory must have a default constructor.
  • * *
  • gov.nist.javax.sip.SERVER_LOG = fileName
    * Use of this property is still supported but deprecated. Please use * gov.nist.javax.sip.STACK_LOGGER and gov.nist.javax.sip.SERVER_LOGGER for * integration with logging frameworks and for custom formatting of log records. * Log valid incoming messages here. If this is left null AND the * TRACE_LEVEL is above INFO (or TRACE) then the messages are printed to stdout. * Otherwise messages are logged in a format that can later be viewed using the * trace viewer application which is located in the tools/tracesviewer * directory. Mail this to us with bug reports.
  • * *
  • gov.nist.javax.sip.DEBUG_LOG = fileName Use of this property * is still supported but deprecated. Please use gov.nist.javax.sip.STACK_LOGGER * and gov.nist.javax.sip.SERVER_LOGGER for integration with logging frameworks * and for custom formatting of log records.
    * Where the debug log goes. Mail this to us with bug reports. *
  • * *
  • gov.nist.javax.sip.LOG_MESSAGE_CONTENT = true|false
    * Set true if you want to capture content into the log. Default is false. A bad * idea to log content if you are using SIP to push a lot of bytes through TCP.
  • * *
  • gov.nist.javax.sip.LOG_STACK_TRACE_ON_MESSAGE_SEND = true|false
    * Set true if you want to to log a stack trace at INFO level for each message * send. This is really handy for debugging.
  • * *
  • gov.nist.javax.sip.STACK_LOGGER = full path name to the class * implementing gov.nist.core.StackLogger interface
    * If this property is defined the sip stack will try to instantiate it through * a no arg constructor. This allows to use different logging implementations * than the ones provided by default to log what happens within the stack while * processing SIP messages. If this property is not defined, the default sip * stack LogWriter will be used for logging
  • * *
  • gov.nist.javax.sip.SERVER_LOGGER = full path name to the class * implementing gov.nist.core.ServerLogger interface
    * If this property is defined the sip stack will try to instantiate it through * a no arg constructor. This allows to use different logging implementations * than the ones provided by default to log sent/received messages by the sip * stack. If this property is not defined, the default sip stack ServerLog will * be used for logging
  • * *
  • gov.nist.javax.sip.AUTOMATIC_DIALOG_ERROR_HANDLING = [true|false] *
    * Default is true. This is also settable on a per-provider basis. This * flag is set to true by default. When set * to false the following behaviors are enabled: * * *
  • Turn off Merged requests Loop Detection: The following behavior is turned off * : 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. * *
* *
  • gov.nist.javax.sip.IS_BACK_TO_BACK_USER_AGENT = [true|false]
    * Default is false This property controls a setting on the Dialog * objects that the stack manages. Pure B2BUA applications should set this flag * to true. This property can also be set on a per-dialog basis. * Setting this to true imposes serialization on re-INVITE and makes * the sending of re-INVITEs asynchronous. The sending of re-INVITE is * controlled as follows : If the previous in-DIALOG request was an invite * ClientTransaction then the next re-INVITEs that uses the dialog will wait * till an ACK has been sent before admitting the new re-INVITE. If the previous * in-DIALOG transaction was a INVITE ServerTransaction then Dialog waits for * ACK before re-INVITE is allowed to be sent. If a dialog is not ACKed within * 32 seconds, then the dialog is torn down and a BYE sent to the peer.
  • *
  • gov.nist.javax.sip.MAX_MESSAGE_SIZE = integer
    * Maximum size of content that a TCP connection can read. Must be at least 4K. * Default is "infinity" -- ie. no limit. This is to prevent DOS attacks * launched by writing to a TCP connection until the server chokes.
  • * *
  • gov.nist.javax.sip.DELIVER_TERMINATED_EVENT_FOR_NULL_DIALOG = [true|false]
    * If set to false (the default), the application does NOT get notified when a Dialog in the * NULL state is terminated. ( Dialogs in the NULL state are not associated with an actual SIP Dialog. * They are a programming convenience. A Dialog is in the NULL state before the first response for the * Dialog forming Transaction). If set to true, the SipListener will get a DialogTerminatedEvent * when a Dialog in the NULL state is terminated. *
  • * *
  • gov.nist.javax.sip.CACHE_SERVER_CONNECTIONS = [true|false]
    * Default value is true. Setting this to false makes the Stack close the server * socket after a Server Transaction goes to the TERMINATED state. This allows a * server to protectect against TCP based Denial of Service attacks launched by * clients (ie. initiate hundreds of client transactions). If true (default * action), the stack will keep the socket open so as to maximize performance at * the expense of Thread and memory resources - leaving itself open to DOS * attacks.
  • * * *
  • gov.nist.javax.sip.CACHE_CLIENT_CONNECTIONS = [true|false]
    * Default value is true. Setting this to false makes the Stack close the server * socket after a Client Transaction goes to the TERMINATED state. This allows a * client release any buffers threads and socket connections associated with a * client transaction after the transaction has terminated at the expense of * performance.
  • * *
  • gov.nist.javax.sip.THREAD_POOL_SIZE = integer
    * Concurrency control for number of simultaneous active threads. If * unspecificed, the default is "infinity". This feature is useful if you are * trying to build a container. *
      *
    • *
    • If this is not specified, and the listener is re-entrant, each * event delivered to the listener is run in the context of a new thread.
    • *
    • If this is specified and the listener is re-entrant, then the stack will * run the listener using a thread from the thread pool. This allows you to * manage the level of concurrency to a fixed maximum. Threads are pre-allocated * when the stack is instantiated.
    • *
    • If this is specified and the listener is not re-entrant, then the stack * will use the thread pool thread from this pool to parse and manage the state * machine but will run the listener in its own thread.
    • *
    * *
  • gov.nist.javax.sip.REENTRANT_LISTENER = true|false
    * Default is false. Set to true if the listener is re-entrant. If the listener * is re-entrant then the stack manages a thread pool and synchronously calls * the listener from the same thread which read the message. Multiple * transactions may concurrently receive messages and this will result in * multiple threads being active in the listener at the same time. The listener * has to be written with this in mind. If you want good performance on a * multithreaded machine write your listener to be re-entrant and set this * property to be true
  • * *
  • gov.nist.javax.sip.MAX_CONNECTIONS = integer
    * Max number of simultaneous TCP connections handled by stack.
  • * *
  • gov.nist.javax.sip.MAX_SERVER_TRANSACTIONS = integer
    * Maximum size of server transaction table. The low water mark is 80% of the * high water mark. Requests are selectively dropped in the lowater mark to * highwater mark range. Requests are unconditionally accepted if the table is * smaller than the low water mark. The default highwater mark is 5000
  • * *
  • gov.nist.javax.sip.MAX_CLIENT_TRANSACTIONS = integer
    * Max number of active client transactions before the caller blocks and waits * for the number to drop below a threshold. Default is unlimited, i.e. the * caller never blocks and waits for a client transaction to become available * (i.e. it does its own resource management in the application).
  • * *
  • gov.nist.javax.sip.PASS_INVITE_NON_2XX_ACK_TO_LISTENER = true|false *
    * If true then the listener will see the ACK for non-2xx responses for server * transactions. This is not standard behavior per RFC 3261 (INVITE server * transaction state machine) but this is a useful flag for testing. The TCK * uses this flag for example.
  • * *
  • gov.nist.javax.sip.MAX_LISTENER_RESPONSE_TIME = Integer
    * Max time (seconds) before sending a response to a server transaction. If a * response is not sent within this time period, the transaction will be deleted * by the stack. Default time is "infinity" - i.e. if the listener never * responds, the stack will hang on to a reference for the transaction and * result in a memory leak. * *
  • gov.nist.javax.sip.DELIVER_TERMINATED_EVENT_FOR_ACK = [true|false] *
    * Default is false. ACK Server Transaction is a Pseuedo-transaction. * If you want termination notification on ACK transactions (so all server * transactions can be handled uniformly in user code during cleanup), then set * this flag to true.
  • * *
  • gov.nist.javax.sip.READ_TIMEOUT = integer
    * This is relevant for incoming TCP connections to prevent starvation at the * server. This defines the timeout in miliseconds between successive reads * after the first byte of a SIP message is read by the stack. All the sip * headers must be delivered in this interval and each successive buffer must be * of the content delivered in this interval. Default value is -1 (ie. the stack * is wide open to starvation attacks) and the client can be as slow as it wants * to be.
  • * *
  • gov.nist.javax.sip.NETWORK_LAYER = classpath
    * This is an EXPERIMENTAL property (still under active devlopment). Defines a * network layer that allows a client to have control over socket allocations * and monitoring of socket activity. A network layer should implement * gov.nist.core.net.NetworkLayer. The default implementation simply acts as a * wrapper for the standard java.net socket layer. This functionality is still * under active development (may be extended to support security and other * features).
  • * *
  • gov.nist.javax.sip.ADDRESS_RESOLVER = classpath
    * The fully qualified class path for an implementation of the AddressResolver * interface. The AddressResolver allows you to support lookup schemes for * addresses that are not directly resolvable to IP adresses using * getHostByName. Specifying your own address resolver allows you to customize * address lookup. The default address resolver is a pass-through address * resolver (i.e. just returns the input string without doing a resolution). See * gov.nist.javax.sip.DefaultAddressResolver.
  • * *
  • gov.nist.javax.sip.AUTO_GENERATE_TIMESTAMP= [true| false]
    * (default is false) Automatically generate a getTimeOfDay timestamp for a * retransmitted request if the original request contained a timestamp. This is * useful for profiling.
  • * *
  • gov.nist.javax.sip.THREAD_AUDIT_INTERVAL_IN_MILLISECS = long
    * Defines how often the application intends to audit the SIP Stack about the * health of its internal threads (the property specifies the time in * miliseconds between successive audits). The audit allows the application to * detect catastrophic failures like an internal thread terminating because of * an exception or getting stuck in a deadlock condition. Events like these will * make the stack inoperable and therefore require immediate action from the * application layer (e.g., alarms, traps, reboot, failover, etc.) Thread audits * are disabled by default. If this property is not specified, audits will * remain disabled. An example of how to use this property is in * src/examples/threadaudit.
  • * * * *
  • gov.nist.javax.sip.COMPUTE_CONTENT_LENGTH_FROM_MESSAGE_BODY = * [true|false]
    * Default is false If set to true, when you are creating a * message from a String, the MessageFactory will compute the content * length from the message content and ignore the provided content length * parameter in the Message. Otherwise, it will use the content length supplied * and generate a parse exception if the content is truncated. * *
  • gov.nist.javax.sip.CANCEL_CLIENT_TRANSACTION_CHECKED = [true|false] *
    * Default is true. This flag is added in support of load balancers or * failover managers where you may want to cancel ongoing transactions from a * different stack than the original stack. If set to false then the * CANCEL client transaction is not checked for the existence of the INVITE or * the state of INVITE when you send the CANCEL request. Hence you can CANCEL an * INVITE from a different stack than the INVITE. You can also create a CANCEL * client transaction late and send it out after the INVITE server transaction * has been Terminated. Clearly this will result in protocol errors. Setting the * flag to true ( default ) enables you to avoid common protocol errors.
  • * *
  • gov.nist.javax.sip.IS_BACK_TO_BACK_USER_AGENT = [true|false]
    * Default is false This property controls a setting on the Dialog * objects that the stack manages. Pure B2BUA applications should set this flag * to true. This property can also be set on a per-dialog basis. * Setting this to true imposes serialization on re-INVITE and makes * the sending of re-INVITEs asynchronous. The sending of re-INVITE is * controlled as follows : If the previous in-DIALOG request was an invite * ClientTransaction then the next re-INVITEs that uses the dialog will wait * till an ACK has been sent before admitting the new re-INVITE. If the previous * in-DIALOG transaction was a INVITE ServerTransaction then Dialog waits for * ACK before re-INVITE is allowed to be sent. If a dialog is not ACKed within * 32 seconds, then the dialog is torn down and a BYE sent to the peer.
  • * * *
  • gov.nist.javax.sip.RECEIVE_UDP_BUFFER_SIZE = int
    * Default is 8*1024. This property control the size of the UDP buffer * used for SIP messages. Under load, if the buffer capacity is overflown the * messages are dropped causing retransmissions, further increasing the load and * causing even more retransmissions. Good values to this property for servers * is a big number in the order of 8*8*1024.
  • * *
  • gov.nist.javax.sip.SEND_UDP_BUFFER_SIZE = int
    * Default is 8*1024. This property control the size of the UDP buffer * used for SIP messages. Under load, if the buffer capacity is overflown the * messages are dropped causing retransmissions, further increasing the load and * causing even more retransmissions. Good values to this property for servers * is a big number in the order of 8*8*1024 or higher.
  • * *
  • gov.nist.javax.sip.CONGESTION_CONTROL_ENABLED = boolean Defailt * is true. If set to true stack will enforce queue length limitation for UDP. * The Max queue size is 5000 messages. The minimum queue size is 2500 messages. *
  • * *
  • gov.nist.javax.sip.DELIVER_UNSOLICITED_NOTIFY = [true|false]
    * Default is false. This flag is added to allow Sip Listeners to * receive all NOTIFY requests including those that are not part of a valid * dialog.
  • * *
  • gov.nist.javax.sip.REJECT_STRAY_RESPONSES = [true|false] Default * is false A flag that checks responses to test whether the response * corresponds to a via header that was previously generated by us. Note that * setting this flag implies that the stack will take control over setting the * VIA header for Sip Requests sent through the stack. The stack will attach a * suffix to the VIA header branch and check any response arriving at the stack * to see if that response suffix is present. If it is not present, then the * stack will silently drop the response.
  • * *
  • gov.nist.javax.sip.MAX_FORK_TIME_SECONDS = integer Maximum time for which the original * transaction for which a forked response is received is tracked. This property * is only relevant to Dialog Stateful applications ( User Agents or B2BUA). * When a forked response is received in this time interval from when the original * INVITE client transaction was sent, the stack will place the original INVITE * 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.TLS_CLIENT_PROTOCOLS = String * Comma-separated list of protocols to use when creating outgoing TLS connections. * The default is "SSLv3, SSLv2Hello, TLSv1". * Some servers do not support SSLv2Hello, so override to "SSLv3, TLSv1". *
  • *
  • 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 * (client and server) will use the key store provided in the fileName. The * trust store will default to the same store file. A password must be provided * to access the keyStore using the following property:
    * * properties.setProperty("javax.net.ssl.keyStorePassword", "<password>"); *
    * The trust store can be changed, to a separate file with the following * setting:
    * * properties.setProperty("javax.net.ssl.trustStore", "<trustStoreFileName location>"); *
    * If the trust store property is provided the password on the trust store must * be the same as the key store.
    *
    * Note that the stack supports the extensions that are defined in * SipStackExt. These will be supported in the next release of JAIN-SIP. You * should only use the extensions that are defined in this class. * * * @version 1.2 $Revision: 1.115 $ $Date: 2010/01/10 00:13:14 $ * * @author M. Ranganathan
    * * * * */ public class SipStackImpl extends SIPTransactionStack implements javax.sip.SipStack, SipStackExt { private EventScanner eventScanner; private Hashtable listeningPoints; private LinkedList sipProviders; /** * Max datagram size. */ 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. boolean reEntrantListener; SipListener sipListener; // If set to true then a transaction terminated event is // delivered for ACK transactions. boolean deliverTerminatedEventForAck = false; // If set to true then the application want to receive // unsolicited NOTIFYs, ie NOTIFYs that don't match any dialog boolean deliverUnsolicitedNotify = false; // Stack semaphore (global lock). private Semaphore stackSemaphore = new Semaphore(1); // RFC3261: TLS_RSA_WITH_AES_128_CBC_SHA MUST be supported // RFC3261: TLS_RSA_WITH_3DES_EDE_CBC_SHA SHOULD be supported for backwards // compat private String[] cipherSuites = { "TLS_RSA_WITH_AES_128_CBC_SHA", // AES difficult to get with // c++/Windows // "TLS_RSA_WITH_3DES_EDE_CBC_SHA", // Unsupported by Sun impl, "SSL_RSA_WITH_3DES_EDE_CBC_SHA", // For backwards comp., C++ // JvB: patch from Sebastien Mazy, issue with mismatching // ciphersuites "TLS_DH_anon_WITH_AES_128_CBC_SHA", "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA", }; // Supported protocols for TLS client: can be overridden by application private String[] enabledProtocols = { "SSLv3", "SSLv2Hello", "TLSv1" }; /** * Creates a new instance of SipStackImpl. */ protected SipStackImpl() { super(); NistSipMessageFactoryImpl msgFactory = new NistSipMessageFactoryImpl( this); super.setMessageFactory(msgFactory); this.eventScanner = new EventScanner(this); this.listeningPoints = new Hashtable(); this.sipProviders = new LinkedList(); } /** * ReInitialize the stack instance. */ private void reInitialize() { super.reInit(); this.eventScanner = new EventScanner(this); this.listeningPoints = new Hashtable(); this.sipProviders = new LinkedList(); this.sipListener = null; } /** * Return true if automatic dialog support is enabled for this stack. * * @return boolean, true if automatic dialog support is enabled for this * stack */ boolean isAutomaticDialogSupportEnabled() { return super.isAutomaticDialogSupportEnabled; } /** * Constructor for the stack. * * @param configurationProperties * -- stack configuration properties including NIST-specific * extensions. * @throws PeerUnavailableException */ public SipStackImpl(Properties configurationProperties) throws PeerUnavailableException { this(); String address = configurationProperties .getProperty("javax.sip.IP_ADDRESS"); try { /** Retrieve the stack IP address */ if (address != null) { // In version 1.2 of the spec the IP address is // associated with the listening point and // is not madatory. super.setHostAddress(address); } } catch (java.net.UnknownHostException ex) { throw new PeerUnavailableException("bad address " + address); } /** Retrieve the stack name */ String name = configurationProperties .getProperty("javax.sip.STACK_NAME"); if (name == null) throw new PeerUnavailableException("stack name is missing"); super.setStackName(name); String stackLoggerClassName = configurationProperties .getProperty("gov.nist.javax.sip.STACK_LOGGER"); // To log debug messages. if (stackLoggerClassName == null) stackLoggerClassName = "gov.nist.core.LogWriter"; try { Class stackLoggerClass = Class.forName(stackLoggerClassName); Class[] constructorArgs = new Class[0]; Constructor cons = stackLoggerClass .getConstructor(constructorArgs); Object[] args = new Object[0]; StackLogger stackLogger = (StackLogger) cons.newInstance(args); stackLogger.setStackProperties(configurationProperties); super.setStackLogger(stackLogger); } catch (InvocationTargetException ex1) { throw new IllegalArgumentException( "Cound not instantiate stack logger " + stackLoggerClassName + "- check that it is present on the classpath and that there is a no-args constructor defined", ex1); } catch (Exception ex) { throw new IllegalArgumentException( "Cound not instantiate stack logger " + stackLoggerClassName + "- check that it is present on the classpath and that there is a no-args constructor defined", ex); } String serverLoggerClassName = configurationProperties .getProperty("gov.nist.javax.sip.SERVER_LOGGER"); // To log debug messages. if (serverLoggerClassName == null) serverLoggerClassName = "gov.nist.javax.sip.stack.ServerLog"; try { Class serverLoggerClass = Class .forName(serverLoggerClassName); Class[] constructorArgs = new Class[0]; Constructor cons = serverLoggerClass .getConstructor(constructorArgs); Object[] args = new Object[0]; this.serverLogger = (ServerLogger) cons.newInstance(args); serverLogger.setSipStack(this); serverLogger.setStackProperties(configurationProperties); } catch (InvocationTargetException ex1) { throw new IllegalArgumentException( "Cound not instantiate server logger " + stackLoggerClassName + "- check that it is present on the classpath and that there is a no-args constructor defined", ex1); } catch (Exception ex) { throw new IllegalArgumentException( "Cound not instantiate server logger " + stackLoggerClassName + "- check that it is present on the classpath and that there is a no-args constructor defined", ex); } // Default router -- use this for routing SIP URIs. // Our router does not do DNS lookups. this.outboundProxy = configurationProperties .getProperty("javax.sip.OUTBOUND_PROXY"); this.defaultRouter = new DefaultRouter(this, outboundProxy); /** Retrieve the router path */ String routerPath = configurationProperties .getProperty("javax.sip.ROUTER_PATH"); if (routerPath == null) routerPath = "gov.nist.javax.sip.stack.DefaultRouter"; try { Class routerClass = Class.forName(routerPath); Class[] constructorArgs = new Class[2]; constructorArgs[0] = javax.sip.SipStack.class; constructorArgs[1] = String.class; Constructor cons = routerClass.getConstructor(constructorArgs); Object[] args = new Object[2]; args[0] = (SipStack) this; args[1] = outboundProxy; Router router = (Router) cons.newInstance(args); super.setRouter(router); } catch (InvocationTargetException ex1) { 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) { getStackLogger().logError("could not instantiate router", (Exception) ex.getCause()); throw new PeerUnavailableException("Could not instantiate router", ex); } // The flag that indicates that the default router is to be ignored. String useRouterForAll = configurationProperties .getProperty("javax.sip.USE_ROUTER_FOR_ALL_URIS"); this.useRouterForAll = true; if (useRouterForAll != null) { this.useRouterForAll = "true".equalsIgnoreCase(useRouterForAll); } /* * Retrieve the EXTENSION Methods. These are used for instantiation of * Dialogs. */ String extensionMethods = configurationProperties .getProperty("javax.sip.EXTENSION_METHODS"); if (extensionMethods != null) { java.util.StringTokenizer st = new java.util.StringTokenizer( extensionMethods); while (st.hasMoreTokens()) { String em = st.nextToken(":"); if (em.equalsIgnoreCase(Request.BYE) || em.equalsIgnoreCase(Request.INVITE) || em.equalsIgnoreCase(Request.SUBSCRIBE) || em.equalsIgnoreCase(Request.NOTIFY) || em.equalsIgnoreCase(Request.ACK) || em.equalsIgnoreCase(Request.OPTIONS)) throw new PeerUnavailableException("Bad extension method " + em); else this.addExtensionMethod(em); } } String keyStoreFile = configurationProperties .getProperty("javax.net.ssl.keyStore"); String trustStoreFile = configurationProperties .getProperty("javax.net.ssl.trustStore"); if (keyStoreFile != null) { if (trustStoreFile == null) { trustStoreFile = keyStoreFile; } String keyStorePassword = configurationProperties .getProperty("javax.net.ssl.keyStorePassword"); try { this.networkLayer = new SslNetworkLayer(trustStoreFile, keyStoreFile, keyStorePassword.toCharArray(), configurationProperties .getProperty("javax.net.ssl.keyStoreType")); } catch (Exception e1) { getStackLogger().logError( "could not instantiate SSL networking", e1); } } // Set the auto dialog support flag. super.isAutomaticDialogSupportEnabled = configurationProperties .getProperty("javax.sip.AUTOMATIC_DIALOG_SUPPORT", "on") .equalsIgnoreCase("on"); super.isAutomaticDialogErrorHandlingEnabled = configurationProperties .getProperty("gov.nist.javax.sip.AUTOMATIC_DIALOG_ERROR_HANDLING","true") .equals(Boolean.TRUE.toString()); if ( super.isAutomaticDialogSupportEnabled ) { super.isAutomaticDialogErrorHandlingEnabled = true; } if (configurationProperties .getProperty("gov.nist.javax.sip.MAX_LISTENER_RESPONSE_TIME") != null) { super.maxListenerResponseTime = Integer .parseInt(configurationProperties .getProperty("gov.nist.javax.sip.MAX_LISTENER_RESPONSE_TIME")); if (super.maxListenerResponseTime <= 0) throw new PeerUnavailableException( "Bad configuration parameter gov.nist.javax.sip.MAX_LISTENER_RESPONSE_TIME : should be positive"); } else { super.maxListenerResponseTime = -1; } this.deliverTerminatedEventForAck = configurationProperties .getProperty( "gov.nist.javax.sip.DELIVER_TERMINATED_EVENT_FOR_ACK", "false").equalsIgnoreCase("true"); this.deliverUnsolicitedNotify = configurationProperties.getProperty( "gov.nist.javax.sip.DELIVER_UNSOLICITED_NOTIFY", "false") .equalsIgnoreCase("true"); String forkedSubscriptions = configurationProperties .getProperty("javax.sip.FORKABLE_EVENTS"); if (forkedSubscriptions != null) { StringTokenizer st = new StringTokenizer(forkedSubscriptions); while (st.hasMoreTokens()) { String nextEvent = st.nextToken(); this.forkedEvents.add(nextEvent); } } // The following features are unique to the NIST implementation. /* * gets the NetworkLayer implementation, if any. Note that this is a * NIST only feature. */ final String NETWORK_LAYER_KEY = "gov.nist.javax.sip.NETWORK_LAYER"; if (configurationProperties.containsKey(NETWORK_LAYER_KEY)) { String path = configurationProperties .getProperty(NETWORK_LAYER_KEY); try { Class clazz = Class.forName(path); Constructor c = clazz.getConstructor(new Class[0]); networkLayer = (NetworkLayer) c.newInstance(new Object[0]); } catch (Exception e) { throw new PeerUnavailableException( "can't find or instantiate NetworkLayer implementation: " + path); } } final String ADDRESS_RESOLVER_KEY = "gov.nist.javax.sip.ADDRESS_RESOLVER"; if (configurationProperties.containsKey(ADDRESS_RESOLVER_KEY)) { String path = configurationProperties .getProperty(ADDRESS_RESOLVER_KEY); try { Class clazz = Class.forName(path); Constructor c = clazz.getConstructor(new Class[0]); this.addressResolver = (AddressResolver) c .newInstance(new Object[0]); } catch (Exception e) { throw new PeerUnavailableException( "can't find or instantiate AddressResolver implementation: " + path); } } String maxConnections = configurationProperties .getProperty("gov.nist.javax.sip.MAX_CONNECTIONS"); if (maxConnections != null) { try { this.maxConnections = new Integer(maxConnections).intValue(); } catch (NumberFormatException ex) { if (isLoggingEnabled()) getStackLogger().logError( "max connections - bad value " + ex.getMessage()); } } String threadPoolSize = configurationProperties .getProperty("gov.nist.javax.sip.THREAD_POOL_SIZE"); if (threadPoolSize != null) { try { this.threadPoolSize = new Integer(threadPoolSize).intValue(); } catch (NumberFormatException ex) { if (isLoggingEnabled()) this.getStackLogger().logError( "thread pool size - bad value " + ex.getMessage()); } } String serverTransactionTableSize = configurationProperties .getProperty("gov.nist.javax.sip.MAX_SERVER_TRANSACTIONS"); if (serverTransactionTableSize != null) { try { this.serverTransactionTableHighwaterMark = new Integer( serverTransactionTableSize).intValue(); this.serverTransactionTableLowaterMark = this.serverTransactionTableHighwaterMark * 80 / 100; // Lowater is 80% of highwater } catch (NumberFormatException ex) { if (isLoggingEnabled()) this.getStackLogger() .logError( "transaction table size - bad value " + ex.getMessage()); } } else { // Issue 256 : consistent with MAX_CLIENT_TRANSACTIONS, if the MAX_SERVER_TRANSACTIONS is not set // we assume the transaction table size can grow unlimited this.unlimitedServerTransactionTableSize = true; } String clientTransactionTableSize = configurationProperties .getProperty("gov.nist.javax.sip.MAX_CLIENT_TRANSACTIONS"); if (clientTransactionTableSize != null) { try { this.clientTransactionTableHiwaterMark = new Integer( clientTransactionTableSize).intValue(); this.clientTransactionTableLowaterMark = this.clientTransactionTableLowaterMark * 80 / 100; // Lowater is 80% of highwater } catch (NumberFormatException ex) { if (isLoggingEnabled()) this.getStackLogger() .logError( "transaction table size - bad value " + ex.getMessage()); } } else { this.unlimitedClientTransactionTableSize = true; } super.cacheServerConnections = true; String flag = configurationProperties .getProperty("gov.nist.javax.sip.CACHE_SERVER_CONNECTIONS"); if (flag != null && "false".equalsIgnoreCase(flag.trim())) { super.cacheServerConnections = false; } super.cacheClientConnections = true; String cacheflag = configurationProperties .getProperty("gov.nist.javax.sip.CACHE_CLIENT_CONNECTIONS"); if (cacheflag != null && "false".equalsIgnoreCase(cacheflag.trim())) { super.cacheClientConnections = false; } String readTimeout = configurationProperties .getProperty("gov.nist.javax.sip.READ_TIMEOUT"); if (readTimeout != null) { try { int rt = Integer.parseInt(readTimeout); if (rt >= 100) { super.readTimeout = rt; } else { System.err.println("Value too low " + readTimeout); } } catch (NumberFormatException nfe) { // Ignore. if (isLoggingEnabled()) getStackLogger().logError("Bad read timeout " + readTimeout); } } // Get the address of the stun server. String stunAddr = configurationProperties .getProperty("gov.nist.javax.sip.STUN_SERVER"); if (stunAddr != null) this.getStackLogger().logWarning( "Ignoring obsolete property " + "gov.nist.javax.sip.STUN_SERVER"); String maxMsgSize = configurationProperties .getProperty("gov.nist.javax.sip.MAX_MESSAGE_SIZE"); try { if (maxMsgSize != null) { super.maxMessageSize = new Integer(maxMsgSize).intValue(); if (super.maxMessageSize < 4096) super.maxMessageSize = 4096; } else { // Allow for "infinite" size of message super.maxMessageSize = 0; } } catch (NumberFormatException ex) { if (isLoggingEnabled()) getStackLogger().logError( "maxMessageSize - bad value " + ex.getMessage()); } String rel = configurationProperties .getProperty("gov.nist.javax.sip.REENTRANT_LISTENER"); this.reEntrantListener = (rel != null && "true".equalsIgnoreCase(rel)); // Check if a thread audit interval is specified String interval = configurationProperties .getProperty("gov.nist.javax.sip.THREAD_AUDIT_INTERVAL_IN_MILLISECS"); if (interval != null) { try { // Make the monitored threads ping the auditor twice as fast as // the audits getThreadAuditor().setPingIntervalInMillisecs( Long.valueOf(interval).longValue() / 2); } catch (NumberFormatException ex) { if (isLoggingEnabled()) getStackLogger().logError( "THREAD_AUDIT_INTERVAL_IN_MILLISECS - bad value [" + interval + "] " + ex.getMessage()); } } // JvB: added property for testing this .setNon2XXAckPassedToListener(Boolean .valueOf( configurationProperties .getProperty( "gov.nist.javax.sip.PASS_INVITE_NON_2XX_ACK_TO_LISTENER", "false")).booleanValue()); this.generateTimeStampHeader = Boolean.valueOf( configurationProperties.getProperty( "gov.nist.javax.sip.AUTO_GENERATE_TIMESTAMP", "false")) .booleanValue(); String messageLogFactoryClasspath = configurationProperties .getProperty("gov.nist.javax.sip.LOG_FACTORY"); if (messageLogFactoryClasspath != null) { try { Class clazz = Class.forName(messageLogFactoryClasspath); Constructor c = clazz.getConstructor(new Class[0]); this.logRecordFactory = (LogRecordFactory) c .newInstance(new Object[0]); } catch (Exception ex) { if (isLoggingEnabled()) getStackLogger() .logError( "Bad configuration value for LOG_FACTORY -- using default logger"); this.logRecordFactory = new DefaultMessageLogFactory(); } } else { this.logRecordFactory = new DefaultMessageLogFactory(); } boolean computeContentLength = configurationProperties.getProperty( "gov.nist.javax.sip.COMPUTE_CONTENT_LENGTH_FROM_MESSAGE_BODY", "false").equalsIgnoreCase("true"); StringMsgParser .setComputeContentLengthFromMessage(computeContentLength); String tlsClientProtocols = configurationProperties.getProperty( "gov.nist.javax.sip.TLS_CLIENT_PROTOCOLS"); if (tlsClientProtocols != null) { StringTokenizer st = new StringTokenizer(tlsClientProtocols, " ,"); String[] protocols = new String[st.countTokens()]; int i=0; while (st.hasMoreTokens()) { protocols[i++] = st.nextToken(); } this.enabledProtocols = protocols; } super.rfc2543Supported = configurationProperties.getProperty( "gov.nist.javax.sip.RFC_2543_SUPPORT_ENABLED", "true") .equalsIgnoreCase("true"); super.cancelClientTransactionChecked = configurationProperties .getProperty( "gov.nist.javax.sip.CANCEL_CLIENT_TRANSACTION_CHECKED", "true").equalsIgnoreCase("true"); super.logStackTraceOnMessageSend = configurationProperties.getProperty( "gov.nist.javax.sip.LOG_STACK_TRACE_ON_MESSAGE_SEND", "false") .equalsIgnoreCase("true"); if (isLoggingEnabled()) getStackLogger().logDebug( "created Sip stack. Properties = " + configurationProperties); InputStream in = getClass().getResourceAsStream("/TIMESTAMP"); if (in != null) { BufferedReader streamReader = new BufferedReader( new InputStreamReader(in)); try { String buildTimeStamp = streamReader.readLine(); if (in != null) { in.close(); } getStackLogger().setBuildTimeStamp(buildTimeStamp); } catch (IOException ex) { getStackLogger().logError("Could not open build timestamp."); } } String bufferSize = configurationProperties.getProperty( "gov.nist.javax.sip.RECEIVE_UDP_BUFFER_SIZE", MAX_DATAGRAM_SIZE .toString()); int bufferSizeInteger = new Integer(bufferSize).intValue(); super.setReceiveUdpBufferSize(bufferSizeInteger); bufferSize = configurationProperties.getProperty( "gov.nist.javax.sip.SEND_UDP_BUFFER_SIZE", MAX_DATAGRAM_SIZE .toString()); bufferSizeInteger = new Integer(bufferSize).intValue(); super.setSendUdpBufferSize(bufferSizeInteger); boolean congetstionControlEnabled = Boolean .parseBoolean(configurationProperties.getProperty( "gov.nist.javax.sip.CONGESTION_CONTROL_ENABLED", Boolean.TRUE.toString())); super.stackDoesCongestionControl = congetstionControlEnabled; super.isBackToBackUserAgent = Boolean .parseBoolean(configurationProperties.getProperty( "gov.nist.javax.sip.IS_BACK_TO_BACK_USER_AGENT", Boolean.FALSE.toString())); super.checkBranchId = Boolean.parseBoolean(configurationProperties .getProperty("gov.nist.javax.sip.REJECT_STRAY_RESPONSES", Boolean.FALSE.toString())); super.isDialogTerminatedEventDeliveredForNullDialog = (Boolean.parseBoolean(configurationProperties.getProperty("gov.nist.javax.sip.DELIVER_TERMINATED_EVENT_FOR_NULL_DIALOG", Boolean.FALSE.toString()))); super.maxForkTime = Integer.parseInt( configurationProperties.getProperty("gov.nist.javax.sip.MAX_FORK_TIME_SECONDS","0")); } /* * (non-Javadoc) * * @see javax.sip.SipStack#createListeningPoint(java.lang.String, int, * java.lang.String) */ public synchronized ListeningPoint createListeningPoint(String address, int port, String transport) throws TransportNotSupportedException, InvalidArgumentException { if (isLoggingEnabled()) getStackLogger().logDebug( "createListeningPoint : address = " + address + " port = " + port + " transport = " + transport); if (address == null) throw new NullPointerException( "Address for listening point is null!"); if (transport == null) throw new NullPointerException("null transport"); if (port <= 0) throw new InvalidArgumentException("bad port"); if (!transport.equalsIgnoreCase("UDP") && !transport.equalsIgnoreCase("TLS") && !transport.equalsIgnoreCase("TCP") && !transport.equalsIgnoreCase("SCTP")) throw new TransportNotSupportedException("bad transport " + transport); /** Reusing an old stack instance */ if (!this.isAlive()) { this.toExit = false; this.reInitialize(); } String key = ListeningPointImpl.makeKey(address, port, transport); ListeningPointImpl lip = (ListeningPointImpl) listeningPoints.get(key); if (lip != null) { return lip; } else { try { InetAddress inetAddr = InetAddress.getByName(address); MessageProcessor messageProcessor = this .createMessageProcessor(inetAddr, port, transport); if (this.isLoggingEnabled()) { this.getStackLogger().logDebug( "Created Message Processor: " + address + " port = " + port + " transport = " + transport); } lip = new ListeningPointImpl(this, port, transport); lip.messageProcessor = messageProcessor; messageProcessor.setListeningPoint(lip); this.listeningPoints.put(key, lip); // start processing messages. messageProcessor.start(); return (ListeningPoint) lip; } catch (java.io.IOException ex) { if (isLoggingEnabled()) getStackLogger().logError( "Invalid argument address = " + address + " port = " + port + " transport = " + transport); throw new InvalidArgumentException(ex.getMessage(), ex); } } } /* * (non-Javadoc) * * @see javax.sip.SipStack#createSipProvider(javax.sip.ListeningPoint) */ public SipProvider createSipProvider(ListeningPoint listeningPoint) throws ObjectInUseException { if (listeningPoint == null) throw new NullPointerException("null listeningPoint"); if (this.isLoggingEnabled()) this.getStackLogger().logDebug( "createSipProvider: " + listeningPoint); ListeningPointImpl listeningPointImpl = (ListeningPointImpl) listeningPoint; if (listeningPointImpl.sipProvider != null) throw new ObjectInUseException("Provider already attached!"); SipProviderImpl provider = new SipProviderImpl(this); provider.setListeningPoint(listeningPointImpl); listeningPointImpl.sipProvider = provider; this.sipProviders.add(provider); return provider; } /* * (non-Javadoc) * * @see javax.sip.SipStack#deleteListeningPoint(javax.sip.ListeningPoint) */ public void deleteListeningPoint(ListeningPoint listeningPoint) throws ObjectInUseException { if (listeningPoint == null) throw new NullPointerException("null listeningPoint arg"); ListeningPointImpl lip = (ListeningPointImpl) listeningPoint; // Stop the message processing thread in the listening point. super.removeMessageProcessor(lip.messageProcessor); String key = lip.getKey(); this.listeningPoints.remove(key); } /* * (non-Javadoc) * * @see javax.sip.SipStack#deleteSipProvider(javax.sip.SipProvider) */ public void deleteSipProvider(SipProvider sipProvider) throws ObjectInUseException { if (sipProvider == null) throw new NullPointerException("null provider arg"); SipProviderImpl sipProviderImpl = (SipProviderImpl) sipProvider; // JvB: API doc is not clear, but in_use == // sipProviderImpl.sipListener!=null // so we should throw if app did not call removeSipListener // sipProviderImpl.sipListener = null; if (sipProviderImpl.getSipListener() != null) { throw new ObjectInUseException( "SipProvider still has an associated SipListener!"); } sipProviderImpl.removeListeningPoints(); // Bug reported by Rafael Barriuso sipProviderImpl.stop(); sipProviders.remove(sipProvider); if (sipProviders.isEmpty()) { this.stopStack(); } } /** * Get the IP Address of the stack. * * @see javax.sip.SipStack#getIPAddress() * @deprecated */ public String getIPAddress() { return super.getHostAddress(); } /* * (non-Javadoc) * * @see javax.sip.SipStack#getListeningPoints() */ public java.util.Iterator getListeningPoints() { return this.listeningPoints.values().iterator(); } /** * Return true if retransmission filter is active. * * @see javax.sip.SipStack#isRetransmissionFilterActive() * @deprecated */ public boolean isRetransmissionFilterActive() { return true; } /* * (non-Javadoc) * * @see javax.sip.SipStack#getSipProviders() */ public java.util.Iterator getSipProviders() { return this.sipProviders.iterator(); } /* * (non-Javadoc) * * @see javax.sip.SipStack#getStackName() */ public String getStackName() { return this.stackName; } /** * Finalization -- stop the stack on finalization. Exit the transaction * scanner and release all resources. * * @see java.lang.Object#finalize() */ protected void finalize() { this.stopStack(); } /** * This uses the default stack address to create a listening point. * * @see javax.sip.SipStack#createListeningPoint(java.lang.String, int, * java.lang.String) * @deprecated */ public ListeningPoint createListeningPoint(int port, String transport) throws TransportNotSupportedException, InvalidArgumentException { if (super.stackAddress == null) throw new NullPointerException( "Stack does not have a default IP Address!"); return this.createListeningPoint(super.stackAddress, port, transport); } /* * (non-Javadoc) * * @see javax.sip.SipStack#stop() */ public void stop() { if (isLoggingEnabled()) { getStackLogger().logDebug("stopStack -- stoppping the stack"); } this.stopStack(); this.sipProviders = new LinkedList(); this.listeningPoints = new Hashtable(); /* * Check for presence of an event scanner ( may happen if stack is * stopped before listener is attached ). */ if (this.eventScanner != null) this.eventScanner.forceStop(); this.eventScanner = null; } /* * (non-Javadoc) * * @see javax.sip.SipStack#start() */ public void start() throws ProviderDoesNotExistException, SipException { // Start a new event scanner if one does not exist. if (this.eventScanner == null) { this.eventScanner = new EventScanner(this); } } /** * Get the listener for the stack. A stack can have only one listener. To * get an event from a provider, the listener has to be registered with the * provider. The SipListener is application code. * * @return -- the stack SipListener * */ public SipListener getSipListener() { return this.sipListener; } /** * Get the message log factory registered with the stack. * * @return -- the messageLogFactory of the stack. */ public LogRecordFactory getLogRecordFactory() { return super.logRecordFactory; } /** * Set the log appender ( this is useful if you want to specify a particular * log format or log to something other than a file for example). This method * is will be removed May 11, 2010 or shortly there after. * * @param Appender * - the log4j appender to add. * @deprecated TODO: remove this method May 11, 2010. */ // BEGIN android-deleted /* @Deprecated public void addLogAppender(org.apache.log4j.Appender appender) { if (this.getStackLogger() instanceof gov.nist.core.LogWriter) { ((gov.nist.core.LogWriter) this.getStackLogger()).addAppender(appender); } } */ // END android-deleted /** * Get the log4j logger ( for log stream integration ). * This method will be removed May 11, 2010 or shortly there after. * * @return the log4j logger. * @deprecated TODO: This method will be removed May 11, 2010. */ @Deprecated // BEGIN andoird-deleted /* public org.apache.log4j.Logger getLogger() { if (this.getStackLogger() instanceof gov.nist.core.LogWriter) { return ((gov.nist.core.LogWriter) this.getStackLogger()).getLogger(); } return null; } */ // END android-deleted public EventScanner getEventScanner() { return eventScanner; } /* * (non-Javadoc) * * @see * gov.nist.javax.sip.SipStackExt#getAuthenticationHelper(gov.nist.javax * .sip.clientauthutils.AccountManager, javax.sip.header.HeaderFactory) */ public AuthenticationHelper getAuthenticationHelper( AccountManager accountManager, HeaderFactory headerFactory) { return new AuthenticationHelperImpl(this, accountManager, headerFactory); } /* * (non-Javadoc) * * @see * gov.nist.javax.sip.SipStackExt#getAuthenticationHelper(gov.nist.javax * .sip.clientauthutils.AccountManager, javax.sip.header.HeaderFactory) */ public AuthenticationHelper getSecureAuthenticationHelper( SecureAccountManager accountManager, HeaderFactory headerFactory) { return new AuthenticationHelperImpl(this, accountManager, headerFactory); } /** * Set the list of cipher suites supported by the stack. A stack can have * only one set of suites. These are not validated against the supported * cipher suites of the java runtime, so specifying a cipher here does not * guarantee that it will work.
    * The stack has a default cipher suite of: *
      *
    • TLS_RSA_WITH_AES_128_CBC_SHA
    • *
    • SSL_RSA_WITH_3DES_EDE_CBC_SHA
    • *
    • TLS_DH_anon_WITH_AES_128_CBC_SHA
    • *
    • SSL_DH_anon_WITH_3DES_EDE_CBC_SHA
    • *
    * * NOTE: This function must be called before adding a TLS listener * * @param String * [] The new set of ciphers to support. * @return * */ public void setEnabledCipherSuites(String[] newCipherSuites) { cipherSuites = newCipherSuites; } /** * Return the currently enabled cipher suites of the Stack. * * @return The currently enabled cipher suites. */ public String[] getEnabledCipherSuites() { return cipherSuites; } /** * Set the list of protocols supported by the stack for outgoing TLS connections. * A stack can have only one set of protocols. * These are not validated against the supported * protocols of the java runtime, so specifying a protocol here does not * guarantee that it will work.
    * The stack has a default protocol suite of: *
      *
    • SSLv3
    • *
    • SSLv2Hello
    • *
    • TLSv1
    • *
    * * NOTE: This function must be called before creating a TLSMessageChannel. * * @param String * [] The new set of protocols to use for outgoing TLS connections. * @return * */ public void setEnabledProtocols(String[] newProtocols) { enabledProtocols = newProtocols; } /** * Return the currently enabled protocols to use when creating TLS connection. * * @return The currently enabled protocols. */ public String[] getEnabledProtocols() { return enabledProtocols; } /** * Set the "back to back User Agent" flag. * * @param flag * - boolean flag to set. * */ public void setIsBackToBackUserAgent(boolean flag) { super.isBackToBackUserAgent = flag; } /** * Get the "back to back User Agent" flag. * * return the value of the flag * */ public boolean isBackToBackUserAgent() { return super.isBackToBackUserAgent; } public boolean isAutomaticDialogErrorHandlingEnabled() { return super.isAutomaticDialogErrorHandlingEnabled; } public boolean acquireSem() { try { return this.stackSemaphore.tryAcquire(10, TimeUnit.SECONDS); } catch ( InterruptedException ex) { return false; } } public void releaseSem() { this.stackSemaphore.release(); } } java/gov/nist/javax/sip/TransactionExt.java0100644 0000000 0000000 00000005000 13513104763 020011 0ustar000000000 0000000 package gov.nist.javax.sip; import java.security.cert.Certificate; import javax.net.ssl.SSLPeerUnverifiedException; import javax.sip.SipProvider; import javax.sip.Transaction; public interface TransactionExt extends Transaction { /** * Get the Sip Provider associated with this transaction */ public SipProvider getSipProvider(); /** * Returns the IP address of the upstream/downstream hop from which this message was initially received * @return the IP address of the upstream/downstream hop from which this message was initially received * @since 2.0 */ public String getPeerAddress(); /** * Returns the port of the upstream/downstream hop from which this message was initially received * @return the port of the upstream/downstream hop from which this message was initially received * @since 2.0 */ public int getPeerPort(); /** * Returns the name of the protocol with which this message was initially received * @return the name of the protocol with which this message was initially received * @since 2.0 */ public String getTransport(); /** * return the ip address on which this message was initially received * @return the ip address on which this message was initially received */ public String getHost(); /** * return the port on which this message was initially received * @return the port on which this message was initially received */ public int getPort(); /** * Return the Cipher Suite that was used for the SSL handshake. * * @return Returns the cipher suite in use by the session which was produced by the handshake. * @throw UnsupportedOperationException if this is not a secure client transaction. */ public String getCipherSuite() throws UnsupportedOperationException; /** * Get the certificate(s) that were sent to the peer during handshaking. *@return the certificate(s) that were sent to the peer during handshaking. *@throw UnsupportedOperationException if this is not a secure client transaction. * */ Certificate[] getLocalCertificates() throws UnsupportedOperationException; /** * @return the identity of the peer which was identified as part of defining the session. * @throws SSLPeerUnverifiedException * @throw UnsupportedOperationException if this is not a secure client transaction. */ Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException; } java/gov/nist/javax/sip/Utils.java0100644 0000000 0000000 00000014637 13513104763 016163 0ustar000000000 0000000 /* * 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.javax.sip; import gov.nist.javax.sip.header.Via; import gov.nist.javax.sip.message.SIPResponse; import java.security.MessageDigest; import java.util.HashSet; /** * A few utilities that are used in various places by the stack. This is used to * convert byte arrays to hex strings etc. Generate tags and branch identifiers * and odds and ends. * * @author mranga * @version 1.2 $Revision: 1.21 $ $Date: 2009/10/18 13:46:37 $ */ public class Utils implements UtilsExt { 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 */ private static final char[] toHex = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; static { try { digester = MessageDigest.getInstance("MD5"); } catch (Exception ex) { throw new RuntimeException("Could not intialize Digester ", ex); } rand = new java.util.Random(); signature = toHexString(Integer.toString(Math.abs( rand.nextInt() % 1000 )).getBytes()); } public static Utils getInstance() { return instance; } /** * convert an array of bytes to an hexadecimal string * * @return a string * @param b * bytes array to convert to a hexadecimal string */ public static String toHexString(byte b[]) { int pos = 0; char[] c = new char[b.length * 2]; for (int i = 0; i < b.length; i++) { c[pos++] = toHex[(b[i] >> 4) & 0x0F]; c[pos++] = toHex[b[i] & 0x0f]; } return new String(c); } /** * Put quotes around a string and return it. * Any " characters appearing in str are escaped * * @return a quoted string * @param str * string to be quoted */ public static String getQuotedString(String str) { return '"' + str.replace( "\"", "\\\"" ) + '"'; } /** * Squeeze out all white space from a string and return the reduced string. * * @param input * input string to sqeeze. * @return String a reduced string. */ protected static String reduceString(String input) { String newString = input.toLowerCase(); int len = newString.length(); String retval = ""; for (int i = 0; i < len; i++) { if (newString.charAt(i) == ' ' || newString.charAt(i) == '\t') continue; else retval += newString.charAt(i); } return retval; } /** * Generate a call identifier. This is useful when we want to generate a * call identifier in advance of generating a message. */ public synchronized String generateCallIdentifier(String address) { String date = Long.toString(System.currentTimeMillis() + callIDCounter++ + rand.nextLong()); byte cid[] = digester.digest(date.getBytes()); String cidString = Utils.toHexString(cid); return cidString + "@" + address; } /** * Generate a tag for a FROM header or TO header. Just return a random 4 * digit integer (should be enough to avoid any clashes!) Tags only need to * be unique within a call. * * @return a string that can be used as a tag parameter. * * synchronized: needed for access to 'rand', else risk to generate same tag * twice */ public synchronized String generateTag() { return Integer.toHexString(rand.nextInt()); } /** * Generate a cryptographically random identifier that can be used to * generate a branch identifier. * * @return a cryptographically random gloablly unique string that can be * used as a branch identifier. */ public synchronized String generateBranchId() { // long num = rand.nextLong() + Utils.counter++ + System.currentTimeMillis(); byte bid[] = digester.digest(Long.toString(num).getBytes()); // prepend with a magic cookie to indicate we are bis09 compatible. return SIPConstants.BRANCH_MAGIC_COOKIE + Utils.toHexString(bid) + this.signature; } public boolean responseBelongsToUs(SIPResponse response) { Via topmostVia = response.getTopmostVia(); String branch = topmostVia.getBranch(); return branch != null && branch.endsWith(this.signature); } public static String getSignature() { return signature; } public static void main(String[] args) { HashSet branchIds = new HashSet(); for (int b = 0; b < 100000; b++) { String bid = Utils.getInstance().generateBranchId(); if (branchIds.contains(bid)) { throw new RuntimeException("Duplicate Branch ID"); } else { branchIds.add(bid); } } System.out.println("Done!!"); } } java/gov/nist/javax/sip/UtilsExt.java0100644 0000000 0000000 00000003437 13513104763 016640 0ustar000000000 0000000 /* * JBoss, Home of Professional Open Source * This code has been contributed to the public domain. * * 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; /** * @author jean.deruelle@gmail.com * */ public interface UtilsExt { /** * Generate a call identifier. This is useful when we want to generate a * call identifier in advance of generating a message. * @since 2.0 */ public String generateCallIdentifier(String address); /** * Generate a tag for a FROM header or TO header. Just return a random 4 * digit integer (should be enough to avoid any clashes!) Tags only need to * be unique within a call. * * @return a string that can be used as a tag parameter. * * synchronized: needed for access to 'rand', else risk to generate same tag * twice * @since 2.0 */ public String generateTag(); /** * Generate a cryptographically random identifier that can be used to * generate a branch identifier. * * @return a cryptographically random gloablly unique string that can be * used as a branch identifier. * @since 2.0 */ public String generateBranchId(); } java/gov/nist/javax/sip/address/0040755 0000000 0000000 00000000000 13513104763 015635 5ustar000000000 0000000 java/gov/nist/javax/sip/address/AddressFactoryImpl.java0100644 0000000 0000000 00000017340 13513104763 022241 0ustar000000000 0000000 /* * 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.address; import gov.nist.javax.sip.parser.*; import java.text.ParseException; import javax.sip.address.*; /** * Implementation of the JAIN-SIP address factory. * @version 1.2 $Revision: 1.9 $ $Date: 2009/10/22 10:25:56 $ * * @author M. Ranganathan
    * * * * IPv6 Support added by Emil Ivov (emil_ivov@yahoo.com)
    * Network Research Team (http://www-r2.u-strasbg.fr))
    * Louis Pasteur University - Strasbourg - France
    * */ public class AddressFactoryImpl implements javax.sip.address.AddressFactory { /** Creates a new instance of AddressFactoryImpl */ public AddressFactoryImpl() { } /** * *Create an empty address object. * *SPEC_REVISION */ public javax.sip.address.Address createAddress() { return new AddressImpl(); } /** * Creates an Address with the new display name and URI attribute * values. * * @param displayName - the new string value of the display name of the * address. A null value does not set the display name. * @param uri - the new URI value of the address. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the displayName value. */ public javax.sip.address.Address createAddress( String displayName, javax.sip.address.URI uri) { if (uri == null) throw new NullPointerException("null URI"); AddressImpl addressImpl = new AddressImpl(); if (displayName != null) addressImpl.setDisplayName(displayName); addressImpl.setURI(uri); return addressImpl; } /** create a sip uri. * *@param uri -- the uri to parse. */ public javax.sip.address.SipURI createSipURI(String uri) // throws java.net.URISyntaxException { throws ParseException { if (uri == null) throw new NullPointerException("null URI"); try { StringMsgParser smp = new StringMsgParser(); 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); } } /** Create a SipURI * *@param user -- the user *@param host -- the host. */ public javax.sip.address.SipURI createSipURI(String user, String host) throws ParseException { if (host == null) throw new NullPointerException("null host"); StringBuffer uriString = new StringBuffer("sip:"); if (user != null) { uriString.append(user); uriString.append("@"); } //if host is an IPv6 string we should enclose it in sq brackets if (host.indexOf(':') != host.lastIndexOf(':') && host.trim().charAt(0) != '[') host = '[' + host + ']'; uriString.append(host); StringMsgParser smp = new StringMsgParser(); try { 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 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. */ public javax.sip.address.TelURL createTelURL(String uri) throws ParseException { if (uri == null) throw new NullPointerException("null url"); String telUrl = "tel:" + uri; try { StringMsgParser smp = new StringMsgParser(); TelURLImpl timp = (TelURLImpl) smp.parseUrl(telUrl); return (TelURL) timp; } catch (ParseException ex) { 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 * returned may or may not be a SipURI or TelURL cast as a URI. * * @param uri - the new string value of the URI. * @throws URISyntaxException if the URI string is malformed. */ public javax.sip.address.URI createURI(String uri) throws ParseException { if (uri == null) throw new NullPointerException("null arg"); try { URLParser urlParser = new URLParser(uri); String scheme = urlParser.peekScheme(); if (scheme == null) throw new ParseException("bad scheme", 0); 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 (javax.sip.address.URI) urlParser.telURL(true); } } catch (ParseException ex) { throw new ParseException(ex.getMessage(), 0); } return new gov.nist.javax.sip.address.GenericURI(uri); } } java/gov/nist/javax/sip/address/AddressImpl.java0100644 0000000 0000000 00000022417 13513104763 020712 0ustar000000000 0000000 /* * 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.javax.sip.address; import gov.nist.core.*; import javax.sip.address.*; /* * BUG Fix from Antonis Kadris. */ /** * Address structure. Imbeds a URI and adds a display name. * *@author M. Ranganathan
    * * * *@version 1.2 $Revision: 1.11 $ $Date: 2009/07/17 18:57:21 $ * */ public final class AddressImpl extends NetObject implements javax.sip.address.Address { private static final long serialVersionUID = 429592779568617259L; /** Constant field. */ public static final int NAME_ADDR = 1; /** constant field. */ public static final int ADDRESS_SPEC = 2; /** Constant field. */ public static final int WILD_CARD = 3; protected int addressType; /** displayName field */ protected String displayName; /** address field */ protected GenericURI address; /** Match on the address only. * Dont care about the display name. */ public boolean match(Object other) { // TODO -- add the matcher; if (other == null) return true; if (!(other instanceof Address)) return false; else { AddressImpl that = (AddressImpl) other; if (that.getMatcher() != null) return that.getMatcher().match(this.encode()); else if (that.displayName != null && this.displayName == null) return false; else if (that.displayName == null) return address.match(that.address); else return displayName.equalsIgnoreCase(that.displayName) && address.match(that.address); } } /** Get the host port portion of the address spec. *@return host:port in a HostPort structure. */ public HostPort getHostPort() { if (!(address instanceof SipUri)) throw new RuntimeException("address is not a SipUri"); SipUri uri = (SipUri) address; return uri.getHostPort(); } /** Get the port from the imbedded URI. This assumes that a SIP URL * is encapsulated in this address object. * *@return the port from the address. * */ public int getPort() { if (!(address instanceof SipUri)) throw new RuntimeException("address is not a SipUri"); SipUri uri = (SipUri) address; return uri.getHostPort().getPort(); } /** Get the user@host:port for the address field. This assumes * that the encapsulated object is a SipUri. * * *@return string containing user@host:port. */ public String getUserAtHostPort() { if (address instanceof SipUri) { SipUri uri = (SipUri) address; return uri.getUserAtHostPort(); } else return address.toString(); } /** Get the host name from the address. * *@return the host name. */ public String getHost() { if (!(address instanceof SipUri)) throw new RuntimeException("address is not a SipUri"); SipUri uri = (SipUri) address; return uri.getHostPort().getHost().getHostname(); } /** Remove a parameter from the address. * *@param parameterName is the name of the parameter to remove. */ public void removeParameter(String parameterName) { if (!(address instanceof SipUri)) throw new RuntimeException("address is not a SipUri"); SipUri uri = (SipUri) address; uri.removeParameter(parameterName); } /** * Encode the address as a string and return it. * @return String canonical encoded version of this address. */ public String encode() { return encode(new StringBuffer()).toString(); } public StringBuffer encode(StringBuffer buffer) { if (this.addressType == WILD_CARD) { buffer.append('*'); } else { if (displayName != null) { buffer.append(DOUBLE_QUOTE) .append(displayName) .append(DOUBLE_QUOTE) .append(SP); } if (address != null) { if (addressType == NAME_ADDR || displayName != null) buffer.append(LESS_THAN); address.encode(buffer); if (addressType == NAME_ADDR || displayName != null) buffer.append(GREATER_THAN); } } return buffer; } public AddressImpl() { this.addressType = NAME_ADDR; } /** * Get the address type; * @return int */ public int getAddressType() { return addressType; } /** * Set the address type. The address can be NAME_ADDR, ADDR_SPEC or * WILD_CARD * * @param atype int to set * */ public void setAddressType(int atype) { addressType = atype; } /** * get the display name * * @return String * */ public String getDisplayName() { return displayName; } /** * Set the displayName member * * @param displayName String to set * */ public void setDisplayName(String displayName) { this.displayName = displayName; this.addressType = NAME_ADDR; } /** * Set the address field * * @param address SipUri to set * */ public void setAddess(javax.sip.address.URI address) { this.address = (GenericURI) address; } /** * hashCode impelmentation * */ public int hashCode() { return this.address.hashCode(); } /** * Compare two address specs for equality. * * @param other Object to compare this this address * * @return boolean * */ public boolean equals(Object other) { if (this==other) return true; if (other instanceof Address) { final Address o = (Address) other; // Don't compare display name (?) return this.getURI().equals( o.getURI() ); } return false; } /** return true if DisplayName exist. * * @return boolean */ public boolean hasDisplayName() { return (displayName != null); } /** remove the displayName field */ public void removeDisplayName() { displayName = null; } /** Return true if the imbedded URI is a sip URI. * * @return true if the imbedded URI is a SIP URI. * */ public boolean isSIPAddress() { return address instanceof SipUri; } /** Returns the URI address of this Address. The type of URI can be * determined by the scheme. * * @return address parmater of the Address object */ public URI getURI() { return this.address; } /** This determines if this address is a wildcard address. That is * Address.getAddress.getUserInfo() == *; * * @return true if this name address is a wildcard, false otherwise. */ public boolean isWildcard() { return this.addressType == WILD_CARD; } /** Sets the URI address of this Address. The URI can be either a * TelURL or a SipURI. * * @param address - the new URI address value of this NameAddress. */ public void setURI(URI address) { this.address = (GenericURI) address; } /** Set the user name for the imbedded URI. * *@param user -- user name to set for the imbedded URI. */ public void setUser(String user) { ((SipUri) this.address).setUser(user); } /** Mark this a wild card address type. * Also set the SIP URI to a special wild card address. */ public void setWildCardFlag() { this.addressType = WILD_CARD; this.address = new SipUri(); ((SipUri)this.address).setUser("*"); } public Object clone() { AddressImpl retval = (AddressImpl) super.clone(); if (this.address != null) retval.address = (GenericURI) this.address.clone(); return retval; } } java/gov/nist/javax/sip/address/Authority.java0100644 0000000 0000000 00000013772 13513104763 020477 0ustar000000000 0000000 /* * 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.javax.sip.address; import gov.nist.core.*; /** * Authority part of a URI structure. Section 3.2.2 RFC2396 * * @version 1.2 $Revision: 1.10 $ $Date: 2009/12/16 14:48:33 $ * * @author M. Ranganathan
    * * * */ public class Authority extends NetObject { private static final long serialVersionUID = -3570349777347017894L; /** hostport field */ protected HostPort hostPort; /** userInfo field */ protected UserInfo userInfo; /** * Return the host name in encoded form. * @return encoded string (does the same thing as toString) */ public String encode() { return encode(new StringBuffer()).toString(); } public StringBuffer encode(StringBuffer buffer) { if (userInfo != null) { userInfo.encode(buffer); buffer.append(AT); hostPort.encode(buffer); } else { hostPort.encode(buffer); } return buffer; } /** retruns true if the two Objects are equals , false otherwise. * @param other Object to test. * @return boolean */ @Override public boolean equals(Object other) { if (other == null) return false; if (other.getClass() != getClass()) { return false; } Authority otherAuth = (Authority) other; if (!this.hostPort.equals(otherAuth.hostPort)) { return false; } if (this.userInfo != null && otherAuth.userInfo != null) { if (!this.userInfo.equals(otherAuth.userInfo)) { return false; } } return true; } /** * get the hostPort member. * @return HostPort */ public HostPort getHostPort() { return hostPort; } /** * get the userInfo memnber. * @return UserInfo */ public UserInfo getUserInfo() { return userInfo; } /** * Get password from the user info. * @return String */ public String getPassword() { if (userInfo == null) return null; else return userInfo.password; } /** * Get the user name if it exists. * @return String user or null if not set. */ public String getUser() { return userInfo != null ? userInfo.user : null; } /** * Get the host name. * @return Host (null if not set) */ public Host getHost() { if (hostPort == null) return null; else return hostPort.getHost(); } /** * Get the port. * @return int port (-1) if port is not set. */ public int getPort() { if (hostPort == null) return -1; else return hostPort.getPort(); } /** remove the port. */ public void removePort() { if (hostPort != null) hostPort.removePort(); } /** * set the password. * @param passwd String to set */ public void setPassword(String passwd) { if (userInfo == null) userInfo = new UserInfo(); userInfo.setPassword(passwd); } /** * Set the user name of the userInfo member. * @param user String to set */ public void setUser(String user) { if (userInfo == null) userInfo = new UserInfo(); this.userInfo.setUser(user); } /** * set the host. * @param host Host to set */ public void setHost(Host host) { if (hostPort == null) hostPort = new HostPort(); hostPort.setHost(host); } /** * Set the port. * @param port int to set */ public void setPort(int port) { if (hostPort == null) hostPort = new HostPort(); hostPort.setPort(port); } /** * Set the hostPort member * @param h HostPort to set */ public void setHostPort(HostPort h) { hostPort = h; } /** * Set the userInfo member * @param u UserInfo to set */ public void setUserInfo(UserInfo u) { userInfo = u; } /** Remove the user Infor. * */ public void removeUserInfo() { this.userInfo = null; } public Object clone() { Authority retval = (Authority) super.clone(); if (this.hostPort != null) retval.hostPort = (HostPort) this.hostPort.clone(); if (this.userInfo != null) retval.userInfo = (UserInfo) this.userInfo.clone(); return retval; } @Override public int hashCode() { if ( this.hostPort == null ) throw new UnsupportedOperationException("Null hostPort cannot compute hashcode"); return this.hostPort.encode().hashCode(); } } java/gov/nist/javax/sip/address/GenericURI.java0100644 0000000 0000000 00000007763 13513104763 020446 0ustar000000000 0000000 /* * 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.address; import java.text.ParseException; import javax.sip.address.URI; /** * Implementation of the URI class. This relies on the 1.4 URI class. * * @author M. Ranganathan
    * @version 1.2 $Revision: 1.10 $ $Date: 2009/11/15 19:50:45 $ * * */ public class GenericURI extends NetObject implements javax.sip.address.URI { /** * */ private static final long serialVersionUID = 3237685256878068790L; public static final String SIP = ParameterNames.SIP_URI_SCHEME; public static final String SIPS = ParameterNames.SIPS_URI_SCHEME; public static final String TEL = ParameterNames.TEL_URI_SCHEME; public static final String POSTDIAL = ParameterNames.POSTDIAL; public static final String PHONE_CONTEXT_TAG = ParameterNames.PHONE_CONTEXT_TAG; public static final String ISUB = ParameterNames.ISUB; public static final String PROVIDER_TAG = ParameterNames.PROVIDER_TAG; /** Imbedded URI */ protected String uriString; /** * The URI Scheme. */ protected String scheme; /** Consturctor */ protected GenericURI() { } /** Constructor given the URI string * @param uriString The imbedded URI string. * @throws java.net.URISyntaxException When there is a syntaz error in the imbedded URI. */ public GenericURI(String uriString) throws ParseException { try { this.uriString = uriString; int i = uriString.indexOf(":"); scheme = uriString.substring(0, i); } catch (Exception e) { throw new ParseException("GenericURI, Bad URI format", 0); } } /** Encode the URI. * @return The encoded URI */ public String encode() { return uriString; } public StringBuffer encode(StringBuffer buffer) { return buffer.append(uriString); } /** Encode this URI. * @return The encoded URI */ public String toString() { return this.encode(); } /** Returns the value of the "scheme" of * this URI, for example "sip", "sips" or "tel". * * @return the scheme paramter of the URI */ public String getScheme() { return scheme; } /** This method determines if this is a URI with a scheme of * "sip" or "sips". * * @return true if the scheme is "sip" or "sips", false otherwise. */ public boolean isSipURI() { return this instanceof SipUri; } // @Override public boolean equals(Object that) { if (this==that) return true; else if (that instanceof URI) { final URI o = (URI) that; // This is not sufficient for equality; revert to String equality... // return this.getScheme().equalsIgnoreCase( o.getScheme() ) return this.toString().equalsIgnoreCase( o.toString() ); } return false; } public int hashCode() { return this.toString().hashCode(); } } java/gov/nist/javax/sip/address/NetObject.java0100644 0000000 0000000 00000041106 13513104763 020354 0ustar000000000 0000000 /* * 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.javax.sip.address; import gov.nist.core.*; import java.lang.reflect.*; /** * Root object for all objects in this package. * * @version 1.2 $Revision: 1.10 $ $Date: 2009/07/17 18:57:22 $ * * @author M. Ranganathan
    * * */ public abstract class NetObject extends GenericObject { // BEGIN android-added protected static final long serialVersionUID = 6149926203633320729L; // END android-added protected static final String CORE_PACKAGE = PackageNames.CORE_PACKAGE; protected static final String NET_PACKAGE = PackageNames.NET_PACKAGE; protected static final String PARSER_PACKAGE = PackageNames.PARSER_PACKAGE; protected static final String UDP = "udp"; protected static final String TCP = "tcp"; protected static final String TRANSPORT = "transport"; protected static final String METHOD = "method"; protected static final String USER = "user"; protected static final String PHONE = "phone"; protected static final String MADDR = "maddr"; protected static final String TTL = "ttl"; protected static final String LR = "lr"; protected static final String SIP = "sip"; protected static final String SIPS = "sips"; // Added by Daniel J. Martinez Manzano protected static final String TLS = "tls"; // Added by Peter Musgrave // params for outbound and gruu drafts protected static final String GRUU = "gr"; /** Default constructor */ public NetObject() { super(); } /** * An introspection based equality predicate for SIPObjects. *@param that is the other object to test against. */ public boolean equals(Object that) { if (!this.getClass().equals(that.getClass())) return false; Class myclass = this.getClass(); Class hisclass = that.getClass(); while (true) { Field[] fields = myclass.getDeclaredFields(); Field[] hisfields = hisclass.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { Field f = fields[i]; Field g = hisfields[i]; // Only print protected and public members. int modifier = f.getModifiers(); if ((modifier & Modifier.PRIVATE) == Modifier.PRIVATE) continue; Class fieldType = f.getType(); String fieldName = f.getName(); if (fieldName.compareTo("stringRepresentation") == 0) { continue; } if (fieldName.compareTo("indentation") == 0) { continue; } try { // Primitive fields are printed with type: value if (fieldType.isPrimitive()) { String fname = fieldType.toString(); if (fname.compareTo("int") == 0) { if (f.getInt(this) != g.getInt(that)) return false; } else if (fname.compareTo("short") == 0) { if (f.getShort(this) != g.getShort(that)) return false; } else if (fname.compareTo("char") == 0) { if (f.getChar(this) != g.getChar(that)) return false; } else if (fname.compareTo("long") == 0) { if (f.getLong(this) != g.getLong(that)) return false; } else if (fname.compareTo("boolean") == 0) { if (f.getBoolean(this) != g.getBoolean(that)) return false; } else if (fname.compareTo("double") == 0) { if (f.getDouble(this) != g.getDouble(that)) return false; } else if (fname.compareTo("float") == 0) { if (f.getFloat(this) != g.getFloat(that)) return false; } } else if (g.get(that) == f.get(this)) continue; else if (f.get(this) == null && g.get(that) != null) return false; else if (g.get(that) == null && f.get(that) != null) return false; else if (!f.get(this).equals(g.get(that))) return false; } catch (IllegalAccessException ex1) { InternalErrorHandler.handleException(ex1); } } if (myclass.equals(NetObject.class)) break; else { myclass = myclass.getSuperclass(); hisclass = hisclass.getSuperclass(); } } return true; } /** An introspection based predicate matching using a template * object. Allows for partial match of two protocl Objects. *@param other the match pattern to test against. The match object * has to be of the same type (class). Primitive types * and non-sip fields that are non null are matched for equality. * Null in any field matches anything. Some book-keeping fields * are ignored when making the comparison. *@return true if match succeeds false otherwise. */ public boolean match(Object other) { if (other == null) return true; if (!this.getClass().equals(other.getClass())) return false; GenericObject that = (GenericObject) other; // System.out.println("Comparing " + that.encode()); // System.out.println("this = " + this.encode()); Class hisclass = other.getClass(); Class myclass = this.getClass(); while (true) { Field[] fields = myclass.getDeclaredFields(); Field[] hisfields = hisclass.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { Field f = fields[i]; Field g = hisfields[i]; // Only print protected and public members. int modifier = f.getModifiers(); if ((modifier & Modifier.PRIVATE) == Modifier.PRIVATE) continue; Class fieldType = f.getType(); String fieldName = f.getName(); if (fieldName.compareTo("stringRepresentation") == 0) { continue; } if (fieldName.compareTo("indentation") == 0) { continue; } try { // Primitive fields are printed with type: value if (fieldType.isPrimitive()) { String fname = fieldType.toString(); if (fname.compareTo("int") == 0) { if (f.getInt(this) != g.getInt(that)) return false; } else if (fname.compareTo("short") == 0) { if (f.getShort(this) != g.getShort(that)) return false; } else if (fname.compareTo("char") == 0) { if (f.getChar(this) != g.getChar(that)) return false; } else if (fname.compareTo("long") == 0) { if (f.getLong(this) != g.getLong(that)) return false; } else if (fname.compareTo("boolean") == 0) { if (f.getBoolean(this) != g.getBoolean(that)) return false; } else if (fname.compareTo("double") == 0) { if (f.getDouble(this) != g.getDouble(that)) return false; } else if (fname.compareTo("float") == 0) { if (f.getFloat(this) != g.getFloat(that)) return false; } } else { Object myObj = f.get(this); Object hisObj = g.get(that); if (hisObj != null && myObj == null) return false; else if (hisObj == null && myObj != null) continue; else if (hisObj == null && myObj == null) continue; else if ( hisObj instanceof java.lang.String && myObj instanceof java.lang.String) { if (((String) hisObj).equals("")) continue; if (((String) myObj) .compareToIgnoreCase((String) hisObj) != 0) return false; } else if ( GenericObject.isMySubclass(myObj.getClass()) && GenericObject.isMySubclass(hisObj.getClass()) && myObj.getClass().equals(hisObj.getClass()) && ((GenericObject) hisObj).getMatcher() != null) { String myObjEncoded = ((GenericObject) myObj).encode(); boolean retval = ((GenericObject) hisObj).getMatcher().match( myObjEncoded); if (!retval) return false; } else if ( GenericObject.isMySubclass(myObj.getClass()) && !((GenericObject) myObj).match(hisObj)) return false; else if ( GenericObjectList.isMySubclass(myObj.getClass()) && !((GenericObjectList) myObj).match(hisObj)) return false; } } catch (IllegalAccessException ex1) { InternalErrorHandler.handleException(ex1); } } if (myclass.equals(NetObject.class)) break; else { myclass = myclass.getSuperclass(); hisclass = hisclass.getSuperclass(); } } return true; } /** * An introspection based string formatting method. We need this because * in this package (although it is an exact duplicate of the one in * the superclass) because it needs to access the protected members * of the other objects in this class. * @return String */ public String debugDump() { stringRepresentation = ""; Class myclass = getClass(); sprint(myclass.getName()); sprint("{"); Field[] fields = myclass.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { Field f = fields[i]; // Only print protected and public members. int modifier = f.getModifiers(); if ((modifier & Modifier.PRIVATE) == Modifier.PRIVATE) continue; Class fieldType = f.getType(); String fieldName = f.getName(); if (fieldName.compareTo("stringRepresentation") == 0) { // avoid nasty recursions... continue; } if (fieldName.compareTo("indentation") == 0) { // formatting stuff - not relevant here. continue; } sprint(fieldName + ":"); try { // Primitive fields are printed with type: value if (fieldType.isPrimitive()) { String fname = fieldType.toString(); sprint(fname + ":"); if (fname.compareTo("int") == 0) { int intfield = f.getInt(this); sprint(intfield); } else if (fname.compareTo("short") == 0) { short shortField = f.getShort(this); sprint(shortField); } else if (fname.compareTo("char") == 0) { char charField = f.getChar(this); sprint(charField); } else if (fname.compareTo("long") == 0) { long longField = f.getLong(this); sprint(longField); } else if (fname.compareTo("boolean") == 0) { boolean booleanField = f.getBoolean(this); sprint(booleanField); } else if (fname.compareTo("double") == 0) { double doubleField = f.getDouble(this); sprint(doubleField); } else if (fname.compareTo("float") == 0) { float floatField = f.getFloat(this); sprint(floatField); } } else if (GenericObject.class.isAssignableFrom(fieldType)) { if (f.get(this) != null) { sprint( ((GenericObject) f.get(this)).debugDump( indentation + 1)); } else { sprint(""); } } else if ( GenericObjectList.class.isAssignableFrom(fieldType)) { if (f.get(this) != null) { sprint( ((GenericObjectList) f.get(this)).debugDump( indentation + 1)); } else { sprint(""); } } else { // Dont do recursion on things that are not // of our header type... if (f.get(this) != null) { sprint(f.get(this).getClass().getName() + ":"); } else { sprint(fieldType.getName() + ":"); } sprint("{"); if (f.get(this) != null) { sprint(f.get(this).toString()); } else { sprint(""); } sprint("}"); } } catch (IllegalAccessException ex1) { continue; // we are accessing a private field... } } sprint("}"); return stringRepresentation; } /** * Formatter with a given starting indentation (for nested structs). * @param indent int to set * @return String */ public String debugDump(int indent) { int save = indentation; indentation = indent; String retval = this.debugDump(); indentation = save; return retval; } /** Encode this to a string. * *@return string representation for this object. */ public String toString() { return this.encode(); } } java/gov/nist/javax/sip/address/NetObjectList.java0100644 0000000 0000000 00000007661 13513104763 021220 0ustar000000000 0000000 /* * 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.javax.sip.address; import gov.nist.core.*; import java.util.ListIterator; import java.util.LinkedList; import java.util.Iterator; import java.lang.reflect.*; /** * Root class for all the collection objects in this list: * a wrapper class on the GenericObjectList class for lists of objects * that can appear in NetObjects. * IMPORTANT NOTE: NetObjectList cannot derive from NetObject as this * will screw up the way in which we attach objects to headers. * *@version 1.2 $Revision: 1.8 $ $Date: 2009/07/17 18:57:22 $ * *@author M. Ranganathan
    * * * */ public class NetObjectList extends GenericObjectList { /** * */ private static final long serialVersionUID = -1551780600806959023L; /** * Construct a NetObject List given a list name. * @param lname String to set */ public NetObjectList(String lname) { super(lname); } /** * Construct a NetObject List given a list name and a class for * the objects that go into the list. * @param lname String to set * @param cname Class to set */ public NetObjectList(String lname, Class cname) { super(lname, cname); } /** * Construct an empty NetObjectList. */ public NetObjectList() { super(); } /** * Add a new object to the list. * @param obj NetObject to set */ public void add(NetObject obj) { super.add(obj); } /** concatenate the two Lists * @param net_obj_list NetObjectList to set */ public void concatenate(NetObjectList net_obj_list) { super.concatenate(net_obj_list); } /** returns the first element * @return GenericObject */ public GenericObject first() { return (NetObject) super.first(); } /** returns the next element * @return GenericObject */ public GenericObject next() { return (NetObject) super.next(); } /** returns the next element * @param li ListIterator to set * @return GenericObject */ public GenericObject next(ListIterator li) { return (NetObject) super.next(li); } /** set the class * @param cl Class to set */ public void setMyClass(Class cl) { super.setMyClass(cl); } /** * Convert to a string given an indentation(for pretty printing). * @param indent int to set * @return String */ public String debugDump(int indent) { return super.debugDump(indent); } /** * Encode this to a string. * *@return a string representation for this object. */ public String toString() { return this.encode(); } } java/gov/nist/javax/sip/address/ParameterNames.java0100644 0000000 0000000 00000010736 13513104763 021410 0ustar000000000 0000000 /* * 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.address; /** * Common parameter names. * * @version 1.2 $Revision: 1.6 $ $Date: 2009/07/17 18:57:22 $ * * @author M. Ranganathan
    * * */ public interface ParameterNames { public static final String SIP_URI_SCHEME = "sip"; public static final String SIPS_URI_SCHEME = "sips"; public static final String TEL_URI_SCHEME = "tel"; public static final String POSTDIAL = "postdial"; public static final String PHONE_CONTEXT_TAG = "context-tag"; public static final String ISUB = "isub"; public static final String PROVIDER_TAG = "provider-tag"; public static final String UDP = GenericURI.UDP; public static final String TCP = GenericURI.TCP; public static final String TLS = GenericURI.TLS; } /* * $Log: ParameterNames.java,v $ * Revision 1.6 2009/07/17 18:57:22 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:02:30 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:26 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:29 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:34 mranga * * Import * * * Revision 1.3 2004/10/28 19:02:49 mranga * Submitted by: Daniel Martinez * Reviewed by: M. Ranganathan * * Added changes for TLS support contributed by Daniel Martinez * * Revision 1.2 2004/01/22 13:26:28 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/address/RFC2396UrlDecoder.java0100644 0000000 0000000 00000010231 13513104763 021401 0ustar000000000 0000000 /* * 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.address; import java.io.UnsupportedEncodingException; /** * Copied from Apache Excalibur project. * Source code available at http://www.google.com/codesearch?hl=en&q=+excalibur+decodePath+show:sK_gDY0W5Rw:OTjCHAiSuF0:th3BdHtpX20&sa=N&cd=1&ct=rc&cs_p=http://apache.edgescape.com/excalibur/excalibur-sourceresolve/source/excalibur-sourceresolve-1.1-src.zip&cs_f=excalibur-sourceresolve-1.1/src/java/org/apache/excalibur/source/SourceUtil.java * @author Jean Deruelle * */ public class RFC2396UrlDecoder { /** * Decode a path. * *

    Interprets %XX (where XX is hexadecimal number) as UTF-8 encoded bytes. *

    The validity of the input path is not checked (i.e. characters that * were not encoded will not be reported as errors). *

    This method differs from URLDecoder.decode in that it always uses UTF-8 * (while URLDecoder uses the platform default encoding, often ISO-8859-1), * and doesn't translate + characters to spaces. * * @param uri the path to decode * @return the decoded path */ public static String decode(String uri) { StringBuffer translatedUri = new StringBuffer(uri.length()); byte[] encodedchars = new byte[uri.length() / 3]; int i = 0; int length = uri.length(); int encodedcharsLength = 0; while (i < length) { if (uri.charAt(i) == '%') { //we must process all consecutive %-encoded characters in one go, because they represent //an UTF-8 encoded string, and in UTF-8 one character can be encoded as multiple bytes while (i < length && uri.charAt(i) == '%') { if (i + 2 < length) { try { byte x = (byte)Integer.parseInt(uri.substring(i + 1, i + 3), 16); encodedchars[encodedcharsLength] = x; } catch (NumberFormatException e) { throw new IllegalArgumentException("Illegal hex characters in pattern %" + uri.substring(i + 1, i + 3)); } encodedcharsLength++; i += 3; } else { throw new IllegalArgumentException("% character should be followed by 2 hexadecimal characters."); } } try { String translatedPart = new String(encodedchars, 0, encodedcharsLength, "UTF-8"); translatedUri.append(translatedPart); } catch (UnsupportedEncodingException e) { //the situation that UTF-8 is not supported is quite theoretical, so throw a runtime exception throw new RuntimeException("Problem in decodePath: UTF-8 encoding not supported."); } encodedcharsLength = 0; } else { //a normal character translatedUri.append(uri.charAt(i)); i++; } } return translatedUri.toString(); } }java/gov/nist/javax/sip/address/RouterExt.java0100644 0000000 0000000 00000002526 13513104763 020443 0ustar000000000 0000000 /* * 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.address; import javax.sip.address.Hop; import javax.sip.address.Router; /** * */ public interface RouterExt extends Router { /** * Record that a transaction failure occured for the given hop. * */ public void transactionTimeout(Hop hop); } java/gov/nist/javax/sip/address/SipURIExt.java0100644 0000000 0000000 00000001574 13513104763 020300 0ustar000000000 0000000 package gov.nist.javax.sip.address; import javax.sip.address.SipURI; /** * URI Interface extensions that will be added to version 2.0 of the JSR 32 spec. * * @author mranga * * @since 2.0 * */ public interface SipURIExt extends SipURI { /** * Strip the headers that are tacked to the URI. * * @since 2.0 */ public void removeHeaders(); /** * Strip a specific header tacked to the URI. * * @param headerName -- the name of the header. * * @since 2.0 */ public void removeHeader(String headerName); /** * Returns whether the gr parameter is set. * * @since 2.0 */ public boolean hasGrParam(); /** * Sets the gr parameter. * * @param value -- the GRUU param value. * * @since 2.0 */ public void setGrParam(String value); } java/gov/nist/javax/sip/address/SipUri.java0100644 0000000 0000000 00000102122 13513104763 017706 0ustar000000000 0000000 /* * 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.javax.sip.address; /* *Bug fix contributions *Daniel J. Martinez Manzano *Stefan Marx. *pmusgrave@newheights.com (Additions for gruu and outbound drafts) *Jeroen van Bemmel ( additions for SCTP transport ) */ import gov.nist.core.*; import java.util.*; import java.text.ParseException; import javax.sip.PeerUnavailableException; import javax.sip.SipFactory; import javax.sip.address.SipURI; import javax.sip.header.Header; import javax.sip.header.HeaderFactory; /** * Implementation of the SipURI interface. * * * @author M. Ranganathan
    * @version 1.2 $Revision: 1.22 $ $Date: 2009/11/15 19:50:45 $ * * * */ public class SipUri extends GenericURI implements javax.sip.address.SipURI , SipURIExt{ private static final long serialVersionUID = 7749781076218987044L; /** Authority for the uri. */ protected Authority authority; /** uriParms list */ protected NameValueList uriParms; /** qheaders list */ protected NameValueList qheaders; /** telephoneSubscriber field */ protected TelephoneNumber telephoneSubscriber; public SipUri() { this.scheme = SIP; this.uriParms = new NameValueList(); this.qheaders = new NameValueList(); this.qheaders.setSeparator("&"); } /** Constructor given the scheme. * The scheme must be either Sip or Sips */ public void setScheme(String scheme) { if (scheme.compareToIgnoreCase(SIP) != 0 && scheme.compareToIgnoreCase(SIPS) != 0) throw new IllegalArgumentException("bad scheme " + scheme); this.scheme = scheme.toLowerCase(); } /** Get the scheme. */ public String getScheme() { return scheme; } /** * clear all URI Parameters. * @since v1.0 */ public void clearUriParms() { uriParms = new NameValueList(); } /** *Clear the password from the user part if it exists. */ public void clearPassword() { if (this.authority != null) { UserInfo userInfo = authority.getUserInfo(); if (userInfo != null) userInfo.clearPassword(); } } /** Get the authority. */ public Authority getAuthority() { return this.authority; } /** * Clear all Qheaders. */ public void clearQheaders() { qheaders = new NameValueList(); } /** * Compare two URIs and return true if they are equal. * @param that the object to compare to. * @return true if the object is equal to this object. * * JvB: Updated to define equality in terms of API methods, according to the rules * in RFC3261 section 19.1.4 * * Jean Deruelle: Updated to define equality of API methods, according to the rules * in RFC3261 section 19.1.4 convert potential ie : * %HEX HEX encoding parts of the URI before comparing them * transport param added in comparison * header equality enforced in comparison * */ @SuppressWarnings("unchecked") @Override public boolean equals(Object that) { // Shortcut for same object if (that==this) return true; if (that instanceof SipURI) { final SipURI a = this; final SipURI b = (SipURI) that; // A SIP and SIPS URI are never equivalent if ( a.isSecure() ^ b.isSecure() ) return false; // For two URIs to be equal, the user, password, host, and port // components must match; comparison of userinfo is case-sensitive if (a.getUser()==null ^ b.getUser()==null) return false; if (a.getUserPassword()==null ^ b.getUserPassword()==null) return false; if (a.getUser()!=null && !RFC2396UrlDecoder.decode(a.getUser()).equals(RFC2396UrlDecoder.decode(b.getUser()))) return false; if (a.getUserPassword()!=null && !RFC2396UrlDecoder.decode(a.getUserPassword()).equals(RFC2396UrlDecoder.decode(b.getUserPassword()))) return false; if (a.getHost() == null ^ b.getHost() == null) return false; if (a.getHost() != null && !a.getHost().equalsIgnoreCase(b.getHost())) return false; if (a.getPort() != b.getPort()) return false; // URI parameters for (Iterator i = a.getParameterNames(); i.hasNext();) { String pname = (String) i.next(); String p1 = a.getParameter(pname); String p2 = b.getParameter(pname); // those present in both must match (case-insensitive) if (p1!=null && p2!=null && !RFC2396UrlDecoder.decode(p1).equalsIgnoreCase(RFC2396UrlDecoder.decode(p2))) return false; } // transport, user, ttl or method must match when present in either if (a.getTransportParam()==null ^ b.getTransportParam()==null) return false; if (a.getUserParam()==null ^ b.getUserParam()==null) return false; if (a.getTTLParam()==-1 ^ b.getTTLParam()==-1) return false; if (a.getMethodParam()==null ^ b.getMethodParam()==null) return false; if (a.getMAddrParam()==null ^ b.getMAddrParam()==null) return false; // Headers: must match according to their definition. if(a.getHeaderNames().hasNext() && !b.getHeaderNames().hasNext()) return false; if(!a.getHeaderNames().hasNext() && b.getHeaderNames().hasNext()) return false; if(a.getHeaderNames().hasNext() && b.getHeaderNames().hasNext()) { HeaderFactory headerFactory = null; try { headerFactory = SipFactory.getInstance().createHeaderFactory(); } catch (PeerUnavailableException e) { Debug.logError("Cannot get the header factory to parse the header of the sip uris to compare", e); return false; } for (Iterator i = a.getHeaderNames(); i.hasNext();) { String hname = (String) i.next(); String h1 = a.getHeader(hname); String h2 = b.getHeader(hname); if(h1 == null && h2 != null) return false; if(h2 == null && h1 != null) return false; // The following check should not be needed but we add it for findbugs. if(h1 == null && h2 == null) continue; try { Header header1 = headerFactory.createHeader(hname, RFC2396UrlDecoder.decode(h1)); Header header2 = headerFactory.createHeader(hname, RFC2396UrlDecoder.decode(h2)); // those present in both must match according to the equals method of the corresponding header if (!header1.equals(header2)) return false; } catch (ParseException e) { Debug.logError("Cannot parse one of the header of the sip uris to compare " + a + " " + b, e); return false; } } } // Finally, we can conclude that they are indeed equal return true; } return false; } /** * Construct a URL from the parsed structure. * @return String */ public String encode() { return encode(new StringBuffer()).toString(); } public StringBuffer encode(StringBuffer buffer) { buffer.append(scheme).append(COLON); if (authority != null) authority.encode(buffer); if (!uriParms.isEmpty()) { buffer.append(SEMICOLON); uriParms.encode(buffer); } if (!qheaders.isEmpty()) { buffer.append(QUESTION); qheaders.encode(buffer); } return buffer; } /** Return a string representation. * *@return the String representation of this URI. * */ public String toString() { return this.encode(); } /** * getUser@host * @return user@host portion of the uri (null if none exists). * * Peter Musgrave - handle null user */ public String getUserAtHost() { String user = ""; if (authority.getUserInfo() != null) user = authority.getUserInfo().getUser(); String host = authority.getHost().encode(); StringBuffer s = null; if (user.equals("")) { s = new StringBuffer(); } else { s = new StringBuffer(user).append(AT); } return s.append(host).toString(); } /** * getUser@host * @return user@host portion of the uri (null if none exists). */ public String getUserAtHostPort() { String user = ""; if (authority.getUserInfo() != null) user = authority.getUserInfo().getUser(); String host = authority.getHost().encode(); int port = authority.getPort(); // If port not set assign the default. StringBuffer s = null; if (user.equals("")) { s = new StringBuffer(); } else { s = new StringBuffer(user).append(AT); } if (port != -1) { return s.append(host).append(COLON).append(port).toString(); } else return s.append(host).toString(); } /** * get the parameter (do a name lookup) and return null if none exists. * @param parmname Name of the parameter to get. * @return Parameter of the given name (null if none exists). */ public Object getParm(String parmname) { Object obj = uriParms.getValue(parmname); return obj; } /** * Get the method parameter. * @return Method parameter. */ public String getMethod() { return (String) getParm(METHOD); } /** * Accessor for URI parameters * @return A name-value list containing the parameters. */ public NameValueList getParameters() { return uriParms; } /** Remove the URI parameters. * */ public void removeParameters() { this.uriParms = new NameValueList(); } /** * Accessor forSIPObjects * @return Get the query headers (that appear after the ? in * the URL) */ public NameValueList getQheaders() { return qheaders; } /** * Get the urse parameter. * @return User parameter (user= phone or user=ip). */ public String getUserType() { return (String) uriParms.getValue(USER); } /** * Get the password of the user. * @return User password when it embedded as part of the uri * ( a very bad idea). */ public String getUserPassword() { if (authority == null) return null; return authority.getPassword(); } /** Set the user password. *@param password - password to set. */ public void setUserPassword(String password) { if (this.authority == null) this.authority = new Authority(); authority.setPassword(password); } /** * Returns the stucture corresponding to the telephone number * provided that the user is a telephone subscriber. * @return TelephoneNumber part of the url (only makes sense * when user = phone is specified) */ public TelephoneNumber getTelephoneSubscriber() { if (telephoneSubscriber == null) { telephoneSubscriber = new TelephoneNumber(); } return telephoneSubscriber; } /** * Get the host and port of the server. * @return get the host:port part of the url parsed into a * structure. */ public HostPort getHostPort() { if (authority == null || authority.getHost() == null ) return null; else { return authority.getHostPort(); } } /** Get the port from the authority field. * *@return the port from the authority field. */ public int getPort() { HostPort hp = this.getHostPort(); if (hp == null) return -1; return hp.getPort(); } /** Get the host protion of the URI. * @return the host portion of the url. */ public String getHost() { if ( authority == null) return null; else if (authority.getHost() == null ) return null; else return authority.getHost().encode(); } /** * returns true if the user is a telephone subscriber. * If the host is an Internet telephony * gateway, a telephone-subscriber field MAY be used instead * of a user field. The telephone-subscriber field uses the * notation of RFC 2806 [19]. Any characters of the un-escaped * "telephone-subscriber" that are not either in the set * "unreserved" or "user-unreserved" MUST be escaped. The set * of characters not reserved in the RFC 2806 description of * telephone-subscriber contains a number of characters in * various syntax elements that need to be escaped when used * in SIP URLs, for example quotation marks (%22), hash (%23), * colon (%3a), at-sign (%40) and the "unwise" characters, * i.e., punctuation of %5b and above. * * The telephone number is a special case of a user name and * cannot be distinguished by a BNF. Thus, a URL parameter, * user, is added to distinguish telephone numbers from user * names. * * The user parameter value "phone" indicates that the user * part contains a telephone number. Even without this * parameter, recipients of SIP URLs MAY interpret the pre-@ * part as a telephone number if local restrictions on the * @return true if the user is a telephone subscriber. */ public boolean isUserTelephoneSubscriber() { String usrtype = (String) uriParms.getValue(USER); if (usrtype == null) return false; return usrtype.equalsIgnoreCase(PHONE); } /** *remove the ttl value from the parameter list if it exists. */ public void removeTTL() { if (uriParms != null) uriParms.delete(TTL); } /** *Remove the maddr param if it exists. */ public void removeMAddr() { if (uriParms != null) uriParms.delete(MADDR); } /** *Delete the transport string. */ public void removeTransport() { if (uriParms != null) uriParms.delete(TRANSPORT); } /** Remove a header given its name (provided it exists). * @param name name of the header to remove. */ public void removeHeader(String name) { if (qheaders != null) qheaders.delete(name); } /** Remove all headers. */ public void removeHeaders() { qheaders = new NameValueList(); } /** * Set the user type. */ public void removeUserType() { if (uriParms != null) uriParms.delete(USER); } /** *remove the port setting. */ public void removePort() { authority.removePort(); } /** * remove the Method. */ public void removeMethod() { if (uriParms != null) uriParms.delete(METHOD); } /** Sets the user of SipURI. The identifier of a particular resource at * the host being addressed. The user and the user password including the * "at" sign make up the user-info. * * @param uname The new String value of the user. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the user value. */ public void setUser(String uname) { if (this.authority == null) { this.authority = new Authority(); } this.authority.setUser(uname); } /** Remove the user. */ public void removeUser() { this.authority.removeUserInfo(); } /** Set the default parameters for this URI. * Do nothing if the parameter is already set to some value. * Otherwise set it to the given value. * @param name Name of the parameter to set. * @param value value of the parameter to set. */ public void setDefaultParm(String name, Object value) { if (uriParms.getValue(name) == null) { NameValue nv = new NameValue(name, value); uriParms.set(nv); } } /** Set the authority member * @param authority Authority to set. */ public void setAuthority(Authority authority) { this.authority = authority; } /** Set the host for this URI. * @param h host to set. */ public void setHost(Host h) { if (this.authority == null) this.authority = new Authority(); this.authority.setHost(h); } /** Set the uriParms member * @param parms URI parameters to set. */ public void setUriParms(NameValueList parms) { uriParms = parms; } /** * Set a given URI parameter. Note - parameter must be properly * encoded before the function is called. * @param name Name of the parameter to set. * @param value value of the parameter to set. */ public void setUriParm(String name, Object value) { NameValue nv = new NameValue(name, value); uriParms.set(nv); } /** Set the qheaders member * @param parms query headers to set. */ public void setQheaders(NameValueList parms) { qheaders = parms; } /** * Set the MADDR parameter . * @param mAddr Host Name to set */ public void setMAddr(String mAddr) { NameValue nameValue = uriParms.getNameValue(MADDR); Host host = new Host(); host.setAddress(mAddr); if (nameValue != null) nameValue.setValueAsObject(host); else { nameValue = new NameValue(MADDR, host); uriParms.set(nameValue); } } /** Sets the value of the user parameter. The user URI parameter exists to * distinguish telephone numbers from user names that happen to look like * telephone numbers. This is equivalent to setParameter("user", user). * * @param usertype New value String value of the method parameter */ public void setUserParam(String usertype) { uriParms.set(USER, usertype); } /** * Set the Method * @param method method parameter */ public void setMethod(String method) { uriParms.set(METHOD, method); } /** * Sets ISDN subaddress of SipURL * @param isdnSubAddress ISDN subaddress */ public void setIsdnSubAddress(String isdnSubAddress) { if (telephoneSubscriber == null) telephoneSubscriber = new TelephoneNumber(); telephoneSubscriber.setIsdnSubaddress(isdnSubAddress); } /** * Set the telephone subscriber field. * @param tel Telephone subscriber field to set. */ public void setTelephoneSubscriber(TelephoneNumber tel) { telephoneSubscriber = tel; } /** set the port to a given value. * @param p Port to set. */ public void setPort(int p) { if (authority == null) authority = new Authority(); authority.setPort(p); } /** * Boolean to check if a parameter of a given name exists. * @param name Name of the parameter to check on. * @return a boolean indicating whether the parameter exists. */ public boolean hasParameter(String name) { return uriParms.getValue(name) != null; } /** * Set the query header when provided as a name-value pair. * @param nameValue qeuery header provided as a name,value pair. */ public void setQHeader(NameValue nameValue) { this.qheaders.set(nameValue); } /** Set the parameter as given. *@param nameValue - parameter to set. */ public void setUriParameter(NameValue nameValue) { this.uriParms.set(nameValue); } /** Return true if the transport parameter is defined. * @return true if transport appears as a parameter and false otherwise. */ public boolean hasTransport() { return hasParameter(TRANSPORT); } /** * Remove a parameter given its name * @param name -- name of the parameter to remove. */ public void removeParameter(String name) { uriParms.delete(name); } /** Set the hostPort field of the imbedded authority field. *@param hostPort is the hostPort to set. */ public void setHostPort(HostPort hostPort) { if (this.authority == null) { this.authority = new Authority(); } authority.setHostPort(hostPort); } /** clone this. */ public Object clone() { SipUri retval = (SipUri) super.clone(); if (this.authority != null) retval.authority = (Authority) this.authority.clone(); if (this.uriParms != null) retval.uriParms = (NameValueList) this.uriParms.clone(); if (this.qheaders != null) retval.qheaders = (NameValueList) this.qheaders.clone(); if (this.telephoneSubscriber != null) retval.telephoneSubscriber = (TelephoneNumber) this.telephoneSubscriber.clone(); return retval; } /** * Returns the value of the named header, or null if it is not set. * SIP/SIPS URIs may specify headers. As an example, the URI * sip:joe@jcp.org?priority=urgent has a header "priority" whose * value is "urgent". * * @param name name of header to retrieve * @return the value of specified header */ public String getHeader(String name) { return this.qheaders.getValue(name) != null ? this.qheaders.getValue(name).toString() : null; } /** * Returns an Iterator over the names (Strings) of all headers present * in this SipURI. * * @return an Iterator over all the header names */ public Iterator getHeaderNames() { return this.qheaders.getNames(); } /** Returns the value of the lr parameter, or null if this * is not set. This is equivalent to getParameter("lr"). * * @return the value of the lr parameter */ public String getLrParam() { boolean haslr = this.hasParameter(LR); return haslr ? "true" : null; } /** Returns the value of the maddr parameter, or null if this * is not set. This is equivalent to getParameter("maddr"). * * @return the value of the maddr parameter */ public String getMAddrParam() { NameValue maddr = uriParms.getNameValue(MADDR); if (maddr == null) return null; String host = (String) maddr.getValueAsObject(); return host; } /** * Returns the value of the method parameter, or null if this * is not set. This is equivalent to getParameter("method"). * * @return the value of the method parameter */ public String getMethodParam() { return this.getParameter(METHOD); } /** * 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) { Object val = uriParms.getValue(name); if (val == null) return null; if (val instanceof GenericObject) return ((GenericObject) val).encode(); else return val.toString(); } /** * Returns an Iterator over the names (Strings) of all parameters present * * in this ParametersHeader. * * * * @return an Iterator over all the parameter names * */ public Iterator getParameterNames() { return this.uriParms.getNames(); } /** Returns the value of the "ttl" parameter, or -1 if this is not set. * This method is equivalent to getParameter("ttl"). * * @return the value of the ttl parameter */ public int getTTLParam() { Integer ttl = (Integer) uriParms.getValue("ttl"); if (ttl != null) return ttl.intValue(); else return -1; } /** Returns the value of the "transport" parameter, or null if this is not * set. This is equivalent to getParameter("transport"). * * @return the transport paramter of the SipURI */ public String getTransportParam() { if (uriParms != null) { return (String) uriParms.getValue(TRANSPORT); } else return null; } /** Returns the value of the userParam, *or null if this is not set. *

    * This is equivalent to getParameter("user"). * * @return the value of the userParam of the SipURI */ public String getUser() { return authority.getUser(); } /** Returns true if this SipURI is secure i.e. if this SipURI represents a * sips URI. A sip URI returns false. * * @return true if this SipURI represents a sips URI, and * false if it represents a sip URI. */ public boolean isSecure() { return this.getScheme().equalsIgnoreCase(SIPS); } /** This method determines if this is a URI with a scheme of "sip" or "sips". * * @return true if the scheme is "sip" or "sips", false otherwise. */ public boolean isSipURI() { return true; } /** Sets the value of the specified header fields to be included in a * request constructed from the URI. If the header already had a value it * will be overwritten. * * @param name - a String specifying the header name * @param value - a String specifying the header value */ public void setHeader(String name, String value) { NameValue nv = new NameValue(name, value); qheaders.set(nv); } /** * Set the host portion of the SipURI * * @param host host to set. */ public void setHost(String host) throws ParseException { Host h = new Host(host); this.setHost(h); } /** Sets the value of the lr parameter of this SipURI. The lr * parameter, when present, indicates that the element responsible for * this resource implements the routing mechanisms specified in RFC 3261. * This parameter will be used in the URIs proxies place in the * Record-Route header field values, and may appear in the URIs in a * pre-existing route set. */ public void setLrParam() { this.uriParms.set("lr",null); // JvB: fixed to not add duplicates } /** * Sets the value of the maddr parameter of this SipURI. The * maddr parameter indicates the server address to be contacted for this * user, overriding any address derived from the host field. This is * equivalent to setParameter("maddr", maddr). * * @param maddr New value of the maddr parameter */ public void setMAddrParam(String maddr) throws ParseException { if (maddr == null) throw new NullPointerException("bad maddr"); setParameter("maddr", maddr); } /** Sets the value of the method parameter. This specifies * which SIP method to use in requests directed at this URI. This is * equivalent to setParameter("method", method). * * @param method - new value String value of the method parameter */ public void setMethodParam(String method) throws ParseException { setParameter("method", method); } /** * Sets the value of the specified parameter. If the parameter already had * * a value it will be overwritten. A zero-length String indicates flag * * parameter. * * * * @param name - a String specifying the parameter name * * @param value - a String specifying the parameter value * * @throws ParseException which signals that an error has been reached * * unexpectedly while parsing the parameter name or value. * */ public void setParameter(String name, String value) throws ParseException { if (name.equalsIgnoreCase("ttl")) { try { Integer.parseInt(value); } catch (NumberFormatException ex) { throw new ParseException("bad parameter " + value, 0); } } uriParms.set(name,value); } /** Sets the scheme of this URI to sip or sips depending on whether the * argument is true or false. The default value is false. * * @param secure - the boolean value indicating if the SipURI is secure. */ public void setSecure(boolean secure) { if (secure) this.scheme = SIPS; else this.scheme = SIP; } /** Sets the value of the ttl parameter. The ttl parameter * specifies the time-to-live value when packets are sent using UDP * multicast. This is equivalent to setParameter("ttl", ttl). * * @param ttl - new value of the ttl parameter */ public void setTTLParam(int ttl) { if (ttl <= 0) throw new IllegalArgumentException("Bad ttl value"); if (uriParms != null) { NameValue nv = new NameValue("ttl", Integer.valueOf(ttl)); uriParms.set(nv); } } /** Sets the value of the "transport" parameter. This parameter specifies * which transport protocol to use for sending requests and responses to * this entity. The following values are defined: "udp", "tcp", "sctp", * "tls", but other values may be used also. This method is equivalent to * setParameter("transport", transport). Transport parameter constants * are defined in the {@link javax.sip.ListeningPoint}. * * @param transport - new value for the "transport" parameter * @see javax.sip.ListeningPoint */ public void setTransportParam(String transport) throws ParseException { if (transport == null) throw new NullPointerException("null arg"); if (transport.compareToIgnoreCase("UDP") == 0 || transport.compareToIgnoreCase("TLS") == 0 || transport.compareToIgnoreCase("TCP") == 0 || transport.compareToIgnoreCase("SCTP") == 0) { NameValue nv = new NameValue(TRANSPORT, transport.toLowerCase()); uriParms.set(nv); } else throw new ParseException("bad transport " + transport, 0); } /** Returns the user part of this SipURI, or null if it is not set. * * @return the user part of this SipURI */ public String getUserParam() { return getParameter("user"); } /** Returns whether the the lr parameter is set. This is * equivalent to hasParameter("lr"). This interface has no getLrParam as * RFC3261 does not specify any values for the "lr" paramater. * * @return true if the "lr" parameter is set, false otherwise. */ public boolean hasLrParam() { return uriParms.getNameValue("lr") != null; } /** * Returns whether the gr parameter is set. * * Not part on the interface since gruu is not part of the base RFC3261. */ public boolean hasGrParam() { return uriParms.getNameValue(GRUU) != null; } /** * Sets the gr parameter. * * Not part on the interface since gruu is not part of the base RFC3261. */ public void setGrParam(String value) { this.uriParms.set(GRUU, value); // JvB: fixed to not add duplicates } /** * Sets the gr parameter. * * Not part on the interface since gruu is not part of the base RFC3261. */ public String getGrParam() { return (String) this.uriParms.getValue(GRUU); // JvB: fixed to not add duplicates } /** *remove the +sip-instance value from the parameter list if it exists. */ } java/gov/nist/javax/sip/address/TelURLImpl.java0100644 0000000 0000000 00000014775 13513104763 020444 0ustar000000000 0000000 /* * 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.address; import gov.nist.core.NameValueList; import java.text.ParseException; import java.util.Iterator; /** * Implementation of the TelURL interface. * * @version 1.2 $Revision: 1.10 $ $Date: 2009/11/15 19:50:45 $ * * @author M. Ranganathan * */ public class TelURLImpl extends GenericURI implements javax.sip.address.TelURL { private static final long serialVersionUID = 5873527320305915954L; protected TelephoneNumber telephoneNumber; /** Creates a new instance of TelURLImpl */ public TelURLImpl() { this.scheme = "tel"; } /** Set the telephone number. *@param telephoneNumber -- telephone number to set. */ public void setTelephoneNumber(TelephoneNumber telephoneNumber) { this.telephoneNumber = telephoneNumber; } /** Returns the value of the isdnSubAddress parameter, or null * if it is not set. * * @return the value of the isdnSubAddress parameter */ public String getIsdnSubAddress() { return telephoneNumber.getIsdnSubaddress(); } /** Returns the value of the postDial parameter, or null if it * is not set. * * @return the value of the postDial parameter */ public String getPostDial() { return telephoneNumber.getPostDial(); } /** Returns the value of the "scheme" of this URI, for example "sip", "sips" * or "tel". * * @return the scheme paramter of the URI */ public String getScheme() { return this.scheme; } /** Returns true if this TelURL is global i.e. if the TelURI * has a global phone user. * * @return true if this TelURL represents a global phone user, * and false otherwise. */ public boolean isGlobal() { return telephoneNumber.isGlobal(); } /** This method determines if this is a URI with a scheme of "sip" or "sips". * * @return true if the scheme is "sip" or "sips", false otherwise. */ public boolean isSipURI() { return false; } /** Sets phone user of this TelURL to be either global or local. The default * value is false, hence the TelURL is defaulted to local. * * @param global - the boolean value indicating if the TelURL has a global * phone user. */ public void setGlobal(boolean global) { this.telephoneNumber.setGlobal(global); } /** Sets ISDN subaddress of this TelURL. If a subaddress is present, it is * appended to the phone number after ";isub=". * * @param isdnSubAddress - new value of the isdnSubAddress * parameter */ public void setIsdnSubAddress(String isdnSubAddress) { this.telephoneNumber.setIsdnSubaddress(isdnSubAddress); } /** Sets post dial of this TelURL. The post-dial sequence describes what and * when the local entity should send to the phone line. * * @param postDial - new value of the postDial parameter */ public void setPostDial(String postDial) { this.telephoneNumber.setPostDial(postDial); } /** * Set the telephone number. * @param telephoneNumber long phone number to set. */ public void setPhoneNumber(String telephoneNumber) { this.telephoneNumber.setPhoneNumber(telephoneNumber); } /** Get the telephone number. * *@return -- the telephone number. */ public String getPhoneNumber() { return this.telephoneNumber.getPhoneNumber(); } /** Return the string encoding. * *@return -- the string encoding. */ public String toString() { return this.scheme + ":" + telephoneNumber.encode(); } public String encode() { return encode(new StringBuffer()).toString(); } public StringBuffer encode(StringBuffer buffer) { buffer.append(this.scheme).append(':'); telephoneNumber.encode(buffer); return buffer; } /** Deep copy clone operation. * *@return -- a cloned version of this telephone number. */ public Object clone() { TelURLImpl retval = (TelURLImpl) super.clone(); if (this.telephoneNumber != null) retval.telephoneNumber = (TelephoneNumber) this.telephoneNumber.clone(); return retval; } public String getParameter(String parameterName) { return telephoneNumber.getParameter(parameterName); } public void setParameter(String name, String value) { telephoneNumber.setParameter(name, value); } public Iterator getParameterNames() { return telephoneNumber.getParameterNames(); } public NameValueList getParameters() { return telephoneNumber.getParameters(); } public void removeParameter(String name) { telephoneNumber.removeParameter(name); } /* (non-Javadoc) * @see javax.sip.address.TelURL#setPhoneContext(java.lang.String) */ public void setPhoneContext(String phoneContext) throws ParseException { // JvB: set (null) should be interpreted as 'remove' if (phoneContext==null) { this.removeParameter("phone-context"); } else { this.setParameter("phone-context",phoneContext); } } /* (non-Javadoc) * @see javax.sip.address.TelURL#getPhoneContext() */ public String getPhoneContext() { return this.getParameter("phone-context"); } } java/gov/nist/javax/sip/address/TelephoneNumber.java0100644 0000000 0000000 00000014430 13513104763 021573 0ustar000000000 0000000 /* * 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.address; import gov.nist.core.*; import java.util.Iterator; /** * Telephone number class. * @version 1.2 * @version 1.2 $Revision: 1.10 $ $Date: 2009/07/17 18:57:23 $ * * @author M. Ranganathan * */ public class TelephoneNumber extends NetObject { public static final String POSTDIAL = ParameterNames.POSTDIAL; public static final String PHONE_CONTEXT_TAG = ParameterNames.PHONE_CONTEXT_TAG; public static final String ISUB = ParameterNames.ISUB; public static final String PROVIDER_TAG = ParameterNames.PROVIDER_TAG; /** isglobal field */ protected boolean isglobal; /** phoneNumber field */ protected String phoneNumber; /** parmeters list */ protected NameValueList parameters; /** Creates new TelephoneNumber */ public TelephoneNumber() { parameters = new NameValueList(); } /** delete the specified parameter. * @param name String to set */ public void deleteParm(String name) { parameters.delete(name); } /** get the PhoneNumber field * @return String */ public String getPhoneNumber() { return phoneNumber; } /** get the PostDial field * @return String */ public String getPostDial() { return (String) parameters.getValue(POSTDIAL); } /** * Get the isdn subaddress for this number. * @return String */ public String getIsdnSubaddress() { return (String) parameters.getValue(ISUB); } /** returns true if th PostDial field exists * @return boolean */ public boolean hasPostDial() { return parameters.getValue(POSTDIAL) != null; } /** return true if this header has parameters. * @param pname String to set * @return boolean */ public boolean hasParm(String pname) { return parameters.hasNameValue(pname); } /** * return true if the isdn subaddress exists. * @return boolean */ public boolean hasIsdnSubaddress() { return hasParm(ISUB); } /** * is a global telephone number. * @return boolean */ public boolean isGlobal() { return isglobal; } /** remove the PostDial field */ public void removePostDial() { parameters.delete(POSTDIAL); } /** * Remove the isdn subaddress (if it exists). */ public void removeIsdnSubaddress() { deleteParm(ISUB); } /** * Set the list of parameters. * @param p NameValueList to set */ public void setParameters(NameValueList p) { parameters = p; } /** set the Global field * @param g boolean to set */ public void setGlobal(boolean g) { isglobal = g; } /** set the PostDial field * @param p String to set */ public void setPostDial(String p) { NameValue nv = new NameValue(POSTDIAL, p); parameters.set(nv); } /** set the specified parameter * @param name String to set * @param value Object to set */ public void setParm(String name, Object value) { NameValue nv = new NameValue(name, value); parameters.set(nv); } /** * set the isdn subaddress for this structure. * @param isub String to set */ public void setIsdnSubaddress(String isub) { setParm(ISUB, isub); } /** set the PhoneNumber field * @param num String to set */ public void setPhoneNumber(String num) { phoneNumber = num; } public String encode() { return encode(new StringBuffer()).toString(); } public StringBuffer encode(StringBuffer buffer) { if (isglobal) buffer.append('+'); buffer.append(phoneNumber); if (!parameters.isEmpty()) { buffer.append(SEMICOLON); parameters.encode(buffer); } return buffer; } /** * 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) { Object val = parameters.getValue(name); if (val == null) return null; if (val instanceof GenericObject) return ((GenericObject) val).encode(); else return val.toString(); } /** * * Returns an Iterator over the names (Strings) of all parameters. * * @return an Iterator over all the parameter names * */ public Iterator getParameterNames() { return this.parameters.getNames(); } public void removeParameter(String parameter) { this.parameters.delete(parameter); } public void setParameter(String name, String value) { NameValue nv = new NameValue(name, value); this.parameters.set(nv); } public Object clone() { TelephoneNumber retval = (TelephoneNumber) super.clone(); if (this.parameters != null) retval.parameters = (NameValueList) this.parameters.clone(); return retval; } public NameValueList getParameters() { return this.parameters; } } java/gov/nist/javax/sip/address/UserInfo.java0100644 0000000 0000000 00000011625 13513104763 020234 0ustar000000000 0000000 /* * 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 * * . * */ /* * Acknowledgement -- Lamine Brahimi * Submitted a bug fix for a this class. */ /******************************************************************************* * Product of NIST/ITL Advanced Networking Technologies Division (ANTD). * *******************************************************************************/ package gov.nist.javax.sip.address; /** * User information part of a URL. * * @version 1.2 $Revision: 1.8 $ $Date: 2009/07/17 18:57:23 $ * @author M. Ranganathan
    * */ public final class UserInfo extends NetObject { private static final long serialVersionUID = 7268593273924256144L; /** user field */ protected String user; /** password field */ protected String password; /** userType field */ protected int userType; /** Constant field */ public final static int TELEPHONE_SUBSCRIBER = 1; /** constant field */ public final static int USER = 2; /** Default constructor */ public UserInfo() { super(); } /** * Compare for equality. * @param obj Object to set * @return true if the two headers are equals, false otherwise. */ public boolean equals(Object obj) { if (getClass() != obj.getClass()) { return false; } UserInfo other = (UserInfo) obj; if (this.userType != other.userType) { return false; } if (!this.user.equalsIgnoreCase(other.user)) { return false; } if (this.password != null && other.password == null) return false; if (other.password != null && this.password == null) return false; if (this.password == other.password) return true; return (this.password.equals(other.password)); } /** * Encode the user information as a string. * @return String */ public String encode() { return encode(new StringBuffer()).toString(); } public StringBuffer encode(StringBuffer buffer) { if (password != null) buffer.append(user).append(COLON).append(password); else buffer.append(user); return buffer; } /** Clear the password field. */ public void clearPassword() { this.password = null; } /** * Gets the user type (which can be set to TELEPHONE_SUBSCRIBER or USER) * @return the type of user. */ public int getUserType() { return userType; } /** get the user field. * @return String */ public String getUser() { return user; } /** get the password field. * @return String */ public String getPassword() { return password; } /** * Set the user member * @param user String to set */ public void setUser(String user) { this.user = user; // BUG Fix submitted by Lamine Brahimi // add this (taken form sip_messageParser) // otherwise comparison of two SipUrl will fail because this // parameter is not set (whereas it is set in sip_messageParser). if (user != null && (user.indexOf(POUND) >= 0 || user.indexOf(SEMICOLON) >= 0)) { setUserType(TELEPHONE_SUBSCRIBER); } else { setUserType(USER); } } /** * Set the password member * @param p String to set */ public void setPassword(String p) { password = p; } /** * Set the user type (to TELEPHONE_SUBSCRIBER or USER). * @param type int to set * @throws IllegalArgumentException if type is not in range. */ public void setUserType(int type) throws IllegalArgumentException { if (type != TELEPHONE_SUBSCRIBER && type != USER) { throw new IllegalArgumentException("Parameter not in range"); } userType = type; } } java/gov/nist/javax/sip/address/package.html0100644 0000000 0000000 00000000113 13513104763 020106 0ustar000000000 0000000 Implementation of the address package of the JAIN SIP API. java/gov/nist/javax/sip/clientauthutils/0040755 0000000 0000000 00000000000 13513104763 017431 5ustar000000000 0000000 java/gov/nist/javax/sip/clientauthutils/AccountManager.java0100644 0000000 0000000 00000001250 13513104763 023156 0ustar000000000 0000000 package gov.nist.javax.sip.clientauthutils; import javax.sip.ClientTransaction; public interface AccountManager { /** * Returns the user credentials for a given SIP Domain. * You can implement any desired method (such as popping up a dialog for example ) * to retrieve the credentials. * * @param challengedTransaction - the transaction that is being challenged. * @param realm - the realm that is being challenged for which a credential should be * returned. * @return -- the user credentials associated with the domain. */ UserCredentials getCredentials(ClientTransaction challengedTransaction, String realm); } java/gov/nist/javax/sip/clientauthutils/AuthenticationHelper.java0100644 0000000 0000000 00000005306 13513104763 024414 0ustar000000000 0000000 package gov.nist.javax.sip.clientauthutils; import java.text.ParseException; import java.util.Collection; import javax.sip.ClientTransaction; import javax.sip.InvalidArgumentException; import javax.sip.SipException; import javax.sip.SipProvider; import javax.sip.header.AuthorizationHeader; import javax.sip.message.Request; import javax.sip.message.Response; /** * A helper interface that provides useful functionality for clients that need to authenticate * with servers. * * @author Emil Ivov * @author Jeroen van Bemmel * @author M. Ranganathan * * @since 2.0 * * */ public interface AuthenticationHelper { /** * Uses securityAuthority to determinie a set of valid user credentials for * the specified Response (Challenge) and appends it to the challenged * request so that it could be retransmitted. * * * * @param challenge * the 401/407 challenge response * @param challengedTransaction * the transaction established by the challenged request * @param transactionCreator * the JAIN SipProvider that we should use to create the new * transaction. * @param cacheTime The amount of time (seconds ) for which the authentication helper * will keep a reference to the generated credentials in a cache. * If you specify -1, then the authentication credentials are cached * until you remove them from the cache. If you choose this option, make sure * you remove the cached headers or you will have a memory leak. * * @return a transaction containing a re-originated request with the * necessary authorization header. * @throws SipException * if we get an exception white creating the new transaction * @throws NullPointerException * if an argument or a header is null. */ public abstract ClientTransaction handleChallenge(Response challenge, ClientTransaction challengedTransaction, SipProvider transactionCreator, int cacheTime ) throws SipException, NullPointerException; /** * Attach authentication headers to the given request. This looks up * the credential cache and picks up any stored authentication headers * for the given call ID and attaches it to the request. * @param request - the request for which we attach the authentication headers. */ public abstract void setAuthenticationHeaders(Request request) ; /** * Remove cached entry. * * @param callId -- the call Id for which we want to remove the cached headers. * */ public abstract void removeCachedAuthenticationHeaders(String callId); } java/gov/nist/javax/sip/clientauthutils/AuthenticationHelperImpl.java0100644 0000000 0000000 00000045325 13513104763 025243 0ustar000000000 0000000 package gov.nist.javax.sip.clientauthutils; /* * * This code has been contributed with permission from: * * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client but has been significantly changed. * It is donated to the JAIN-SIP project as it is common code that many sip clients * need to perform class and others will consitute a set of utility functions * that will implement common operations that ease the life of the developer. * * Acknowledgements: * ---------------- * * Fredrik Wickstrom reported that dialog cseq counters are not incremented * when resending requests. He later uncovered additional problems and * proposed a way to fix them (his proposition was taken into account). */ import gov.nist.javax.sip.SipStackImpl; import gov.nist.javax.sip.address.SipUri; import gov.nist.javax.sip.message.SIPRequest; import gov.nist.javax.sip.stack.SIPClientTransaction; import gov.nist.javax.sip.stack.SIPTransactionStack; import java.text.ParseException; import java.util.Collection; import java.util.Iterator; import java.util.ListIterator; import java.util.Timer; import javax.sip.ClientTransaction; import javax.sip.DialogState; import javax.sip.InvalidArgumentException; import javax.sip.SipException; import javax.sip.SipProvider; import javax.sip.address.Hop; import javax.sip.address.SipURI; import javax.sip.address.URI; import javax.sip.header.AuthorizationHeader; import javax.sip.header.CSeqHeader; import javax.sip.header.Header; import javax.sip.header.HeaderFactory; import javax.sip.header.ProxyAuthenticateHeader; import javax.sip.header.ProxyAuthorizationHeader; import javax.sip.header.ViaHeader; import javax.sip.header.WWWAuthenticateHeader; import javax.sip.message.Request; import javax.sip.message.Response; /** * The class handles authentication challenges, caches user credentials and takes care (through * the SecurityAuthority interface) about retrieving passwords. * * * @author Emil Ivov * @author Jeroen van Bemmel * @author M. Ranganathan * * @since 2.0 */ public class AuthenticationHelperImpl implements AuthenticationHelper { /** * Credentials cached so far. */ private CredentialsCache cachedCredentials; /** * The account manager for the system. Stores user credentials. */ private Object accountManager = null; /* * Header factory for this security manager. */ private HeaderFactory headerFactory; private SipStackImpl sipStack; Timer timer; /** * Default constructor for the security manager. There is one Account manager. There is one * SipSecurity manager for every user name, * * @param sipStack -- our stack. * @param accountManager -- an implementation of the AccountManager interface. * @param headerFactory -- header factory. */ public AuthenticationHelperImpl(SipStackImpl sipStack, AccountManager accountManager, HeaderFactory headerFactory) { this.accountManager = accountManager; this.headerFactory = headerFactory; this.sipStack = sipStack; this.cachedCredentials = new CredentialsCache(((SIPTransactionStack) sipStack).getTimer()); } /** * Default constructor for the security manager. There is one Account manager. There is one * SipSecurity manager for every user name, * * @param sipStack -- our stack. * @param accountManager -- an implementation of the AccountManager interface. * @param headerFactory -- header factory. */ public AuthenticationHelperImpl(SipStackImpl sipStack, SecureAccountManager accountManager, HeaderFactory headerFactory) { this.accountManager = accountManager; this.headerFactory = headerFactory; this.sipStack = sipStack; this.cachedCredentials = new CredentialsCache(((SIPTransactionStack) sipStack).getTimer()); } /* * (non-Javadoc) * * @see gov.nist.javax.sip.clientauthutils.AuthenticationHelper#handleChallenge(javax.sip.message.Response, * javax.sip.ClientTransaction, javax.sip.SipProvider) */ public ClientTransaction handleChallenge(Response challenge, ClientTransaction challengedTransaction, SipProvider transactionCreator, int cacheTime) throws SipException, NullPointerException { try { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug("handleChallenge: " + challenge); } SIPRequest challengedRequest = ((SIPRequest) challengedTransaction.getRequest()); Request reoriginatedRequest = null; /* * If the challenged request is part of a Dialog and the * Dialog is confirmed the re-originated request should be * generated as an in-Dialog request. */ if ( challengedRequest.getToTag() != null || challengedTransaction.getDialog() == null || challengedTransaction.getDialog().getState() != DialogState.CONFIRMED) { reoriginatedRequest = (Request) challengedRequest.clone(); } else { /* * Re-originate the request by consulting the dialog. In particular * the route set could change between the original request and the * in-dialog challenge. */ reoriginatedRequest = challengedTransaction.getDialog().createRequest(challengedRequest.getMethod()); Iterator headerNames = challengedRequest.getHeaderNames(); while (headerNames.hasNext()) { String headerName = headerNames.next(); if ( reoriginatedRequest.getHeader(headerName) != null) { ListIterator

    iterator = reoriginatedRequest.getHeaders(headerName); while (iterator.hasNext()) { reoriginatedRequest.addHeader(iterator.next()); } } } } // remove the branch id so that we could use the request in a new // transaction removeBranchID(reoriginatedRequest); if (challenge == null || reoriginatedRequest == null) { throw new NullPointerException("A null argument was passed to handle challenge."); } ListIterator authHeaders = null; if (challenge.getStatusCode() == Response.UNAUTHORIZED) { authHeaders = challenge.getHeaders(WWWAuthenticateHeader.NAME); } else if (challenge.getStatusCode() == Response.PROXY_AUTHENTICATION_REQUIRED) { authHeaders = challenge.getHeaders(ProxyAuthenticateHeader.NAME); } else { throw new IllegalArgumentException("Unexpected status code "); } if (authHeaders == null) { throw new IllegalArgumentException( "Could not find WWWAuthenticate or ProxyAuthenticate headers"); } // Remove all authorization headers from the request (we'll re-add them // from cache) reoriginatedRequest.removeHeader(AuthorizationHeader.NAME); reoriginatedRequest.removeHeader(ProxyAuthorizationHeader.NAME); // rfc 3261 says that the cseq header should be augmented for the new // request. do it here so that the new dialog (created together with // the new client transaction) takes it into account. // Bug report - Fredrik Wickstrom CSeqHeader cSeq = (CSeqHeader) reoriginatedRequest.getHeader((CSeqHeader.NAME)); try { cSeq.setSeqNumber(cSeq.getSeqNumber() + 1l); } catch (InvalidArgumentException ex) { throw new SipException("Invalid CSeq -- could not increment : " + cSeq.getSeqNumber()); } /* Resolve this to the next hop based on the previous lookup. If we are not using * lose routing (RFC2543) then just attach hop as a maddr param. */ if ( challengedRequest.getRouteHeaders() == null ) { Hop hop = ((SIPClientTransaction) challengedTransaction).getNextHop(); SipURI sipUri = (SipURI) reoriginatedRequest.getRequestURI(); // BEGIN android-added if ( !hop.getHost().equalsIgnoreCase(sipUri.getHost()) && !hop.equals(sipStack.getRouter(challengedRequest).getOutboundProxy()) ) // END android-added sipUri.setMAddrParam(hop.getHost()); if ( hop.getPort() != -1 ) sipUri.setPort(hop.getPort()); } ClientTransaction retryTran = transactionCreator .getNewClientTransaction(reoriginatedRequest); WWWAuthenticateHeader authHeader = null; SipURI requestUri = (SipURI) challengedTransaction.getRequest().getRequestURI(); while (authHeaders.hasNext()) { authHeader = (WWWAuthenticateHeader) authHeaders.next(); String realm = authHeader.getRealm(); AuthorizationHeader authorization = null; String sipDomain; if ( this.accountManager instanceof SecureAccountManager ) { UserCredentialHash credHash = ((SecureAccountManager)this.accountManager).getCredentialHash(challengedTransaction,realm); URI uri = reoriginatedRequest.getRequestURI(); sipDomain = credHash.getSipDomain(); authorization = this.getAuthorization(reoriginatedRequest .getMethod(), uri.toString(), (reoriginatedRequest.getContent() == null) ? "" : new String( reoriginatedRequest.getRawContent()), authHeader, credHash); } else { UserCredentials userCreds = ((AccountManager) this.accountManager).getCredentials(challengedTransaction, realm); sipDomain = userCreds.getSipDomain(); if (userCreds == null) throw new SipException( "Cannot find user creds for the given user name and realm"); // we haven't yet authenticated this realm since we were // started. authorization = this.getAuthorization(reoriginatedRequest .getMethod(), reoriginatedRequest.getRequestURI().toString(), (reoriginatedRequest.getContent() == null) ? "" : new String( reoriginatedRequest.getRawContent()), authHeader, userCreds); } if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug( "Created authorization header: " + authorization.toString()); if (cacheTime != 0) cachedCredentials.cacheAuthorizationHeader(sipDomain, authorization, cacheTime); reoriginatedRequest.addHeader(authorization); } if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "Returning authorization transaction." + retryTran); } return retryTran; } catch (SipException ex) { throw ex; } catch (Exception ex) { sipStack.getStackLogger().logError("Unexpected exception ", ex); throw new SipException("Unexpected exception ", ex); } } /** * Generates an authorisation header in response to wwwAuthHeader. * * @param method method of the request being authenticated * @param uri digest-uri * @param requestBody the body of the request. * @param authHeader the challenge that we should respond to * @param userCredentials username and pass * * @return an authorisation header in response to authHeader. * * @throws OperationFailedException if auth header was malformated. */ private AuthorizationHeader getAuthorization(String method, String uri, String requestBody, WWWAuthenticateHeader authHeader, UserCredentials userCredentials) { String response = null; // JvB: authHeader.getQop() is a quoted _list_ of qop values // (e.g. "auth,auth-int") Client is supposed to pick one String qopList = authHeader.getQop(); String qop = (qopList != null) ? "auth" : null; String nc_value = "00000001"; String cnonce = "xyz"; response = MessageDigestAlgorithm.calculateResponse(authHeader.getAlgorithm(), userCredentials.getUserName(), authHeader.getRealm(), userCredentials .getPassword(), authHeader.getNonce(), nc_value, // JvB added cnonce, // JvB added method, uri, requestBody, qop,sipStack.getStackLogger());// jvb changed AuthorizationHeader authorization = null; try { if (authHeader instanceof ProxyAuthenticateHeader) { authorization = headerFactory.createProxyAuthorizationHeader(authHeader .getScheme()); } else { authorization = headerFactory.createAuthorizationHeader(authHeader.getScheme()); } authorization.setUsername(userCredentials.getUserName()); authorization.setRealm(authHeader.getRealm()); authorization.setNonce(authHeader.getNonce()); authorization.setParameter("uri", uri); authorization.setResponse(response); if (authHeader.getAlgorithm() != null) { authorization.setAlgorithm(authHeader.getAlgorithm()); } if (authHeader.getOpaque() != null) { authorization.setOpaque(authHeader.getOpaque()); } // jvb added if (qop != null) { authorization.setQop(qop); authorization.setCNonce(cnonce); authorization.setNonceCount(Integer.parseInt(nc_value)); } authorization.setResponse(response); } catch (ParseException ex) { throw new RuntimeException("Failed to create an authorization header!"); } return authorization; } /** * Generates an authorisation header in response to wwwAuthHeader. * * @param method method of the request being authenticated * @param uri digest-uri * @param requestBody the body of the request. * @param authHeader the challenge that we should respond to * @param userCredentials username and pass * * @return an authorisation header in response to authHeader. * * @throws OperationFailedException if auth header was malformated. */ private AuthorizationHeader getAuthorization(String method, String uri, String requestBody, WWWAuthenticateHeader authHeader, UserCredentialHash userCredentials) { String response = null; // JvB: authHeader.getQop() is a quoted _list_ of qop values // (e.g. "auth,auth-int") Client is supposed to pick one String qopList = authHeader.getQop(); String qop = (qopList != null) ? "auth" : null; String nc_value = "00000001"; String cnonce = "xyz"; response = MessageDigestAlgorithm.calculateResponse(authHeader.getAlgorithm(), userCredentials.getHashUserDomainPassword(), authHeader.getNonce(), nc_value, // JvB added cnonce, // JvB added method, uri, requestBody, qop,sipStack.getStackLogger());// jvb changed AuthorizationHeader authorization = null; try { if (authHeader instanceof ProxyAuthenticateHeader) { authorization = headerFactory.createProxyAuthorizationHeader(authHeader .getScheme()); } else { authorization = headerFactory.createAuthorizationHeader(authHeader.getScheme()); } authorization.setUsername(userCredentials.getUserName()); authorization.setRealm(authHeader.getRealm()); authorization.setNonce(authHeader.getNonce()); authorization.setParameter("uri", uri); authorization.setResponse(response); if (authHeader.getAlgorithm() != null) { authorization.setAlgorithm(authHeader.getAlgorithm()); } if (authHeader.getOpaque() != null) { authorization.setOpaque(authHeader.getOpaque()); } // jvb added if (qop != null) { authorization.setQop(qop); authorization.setCNonce(cnonce); authorization.setNonceCount(Integer.parseInt(nc_value)); } authorization.setResponse(response); } catch (ParseException ex) { throw new RuntimeException("Failed to create an authorization header!"); } return authorization; } /** * Removes all via headers from request and replaces them with a new one, equal to * the one that was top most. * * @param request the Request whose branchID we'd like to remove. * */ private void removeBranchID(Request request) { ViaHeader viaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME); viaHeader.removeParameter("branch"); } /* * (non-Javadoc) * * @see gov.nist.javax.sip.clientauthutils.AuthenticationHelper#attachAuthenticationHeaders(javax.sip.message.Request) */ public void setAuthenticationHeaders(Request request) { SIPRequest sipRequest = (SIPRequest) request; String callId = sipRequest.getCallId().getCallId(); request.removeHeader(AuthorizationHeader.NAME); Collection authHeaders = this.cachedCredentials .getCachedAuthorizationHeaders(callId); if (authHeaders == null) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug( "Could not find authentication headers for " + callId); return; } for (AuthorizationHeader authHeader : authHeaders) { request.addHeader(authHeader); } } /* * (non-Javadoc) * * @see gov.nist.javax.sip.clientauthutils.AuthenticationHelper#removeCachedAuthenticationHeaders(java.lang.String) */ public void removeCachedAuthenticationHeaders(String callId) { if (callId == null) throw new NullPointerException("Null callId argument "); this.cachedCredentials.removeAuthenticationHeader(callId); } } java/gov/nist/javax/sip/clientauthutils/CredentialsCache.java0100644 0000000 0000000 00000007110 13513104763 023451 0ustar000000000 0000000 package gov.nist.javax.sip.clientauthutils; import java.util.*; import java.util.concurrent.ConcurrentHashMap; 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 * set up calls. We cache credentials on a per proxy domain per user basis. * */ class CredentialsCache { /** * The key for this map is the proxy domain name. A given proxy authorizes a * user for a number of domains. The Hashtable value of the mapping is a * mapping of user names to AuthorizationHeader list for that proxy domain. */ private ConcurrentHashMap> authorizationHeaders = new ConcurrentHashMap>(); private Timer timer; class TimeoutTask extends TimerTask { String callId; String userName; public TimeoutTask(String userName, String proxyDomain) { this.callId = proxyDomain; this.userName = userName; } @Override public void run() { authorizationHeaders.remove(callId); } } CredentialsCache (Timer timer) { this.timer = timer; } /** * Cache the bindings of proxyDomain and authorization header. * * @param callid * the id of the call that the authorization header * belongs to. * @param authorization * the authorization header that we'd like to cache. */ void cacheAuthorizationHeader(String callId, AuthorizationHeader authorization, int cacheTime) { String user = authorization.getUsername(); if ( callId == null) throw new NullPointerException("Call ID is null!"); if ( authorization == null) throw new NullPointerException("Null authorization domain"); List authHeaders = authorizationHeaders.get(callId); if (authHeaders == null) { authHeaders = new LinkedList(); authorizationHeaders.put(callId, authHeaders); } else { String realm = authorization.getRealm(); for (ListIterator li = authHeaders.listIterator(); li.hasNext();) { AuthorizationHeader authHeader = (AuthorizationHeader) li.next(); if ( realm.equals(authHeader.getRealm()) ) { li.remove(); } } } authHeaders.add(authorization); TimeoutTask timeoutTask = new TimeoutTask( callId,user); if ( cacheTime != -1) this.timer.schedule(timeoutTask, cacheTime*1000); } /** * Returns an authorization header cached for the specified call id and null * if no authorization header has been previously cached for this call. * * @param callid * the call id that we'd like to retrive a cached authorization * header for. * * @return authorization header corresponding to that user for the given * proxy domain. */ Collection getCachedAuthorizationHeaders( String callid) { if (callid == null) throw new NullPointerException("Null arg!"); return this.authorizationHeaders.get(callid); } /** * Remove a cached authorization header. * * @param callId */ public void removeAuthenticationHeader(String callId) { this.authorizationHeaders.remove(callId); } } java/gov/nist/javax/sip/clientauthutils/MessageDigestAlgorithm.java0100644 0000000 0000000 00000022244 13513104763 024670 0ustar000000000 0000000 package gov.nist.javax.sip.clientauthutils; import gov.nist.core.StackLogger; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; /** * The class takes standard Http Authentication details and returns a response according to the * MD5 algorithm * * @author Emil Ivov */ public class MessageDigestAlgorithm { /** * Calculates an http authentication response in accordance with rfc2617. *

    * * @param algorithm a string indicating a pair of algorithms (MD5 (default), or MD5-sess) used * to produce the digest and a checksum. * @param hashUserNameRealmPasswd MD5 hash of (username:realm:password) * @param nonce_value A server-specified data string provided in the challenge. * @param cnonce_value an optional client-chosen value whose purpose is to foil chosen * plaintext attacks. * @param method the SIP method of the request being challenged. * @param digest_uri_value the value of the "uri" directive on the Authorization header in the * request. * @param entity_body the entity-body * @param qop_value Indicates what "quality of protection" the client has applied to the * message. * @param nc_value the hexadecimal count of the number of requests (including the current * request) that the client has sent with the nonce value in this request. * @return a digest response as defined in rfc2617 * @throws NullPointerException in case of incorrectly null parameters. */ 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()) { stackLogger.logDebug("trying to authenticate using : " + algorithm + ", "+ hashUserNameRealmPasswd + ", " + nonce_value + ", " + nc_value + ", " + cnonce_value + ", " + method + ", " + digest_uri_value + ", " + entity_body + ", " + qop_value); } if (hashUserNameRealmPasswd == null || method == null || digest_uri_value == null || nonce_value == null) throw new NullPointerException( "Null parameter to MessageDigestAlgorithm.calculateResponse()"); // The following follows closely the algorithm for generating a response // digest as specified by rfc2617 if (cnonce_value == null || cnonce_value.length() == 0) throw new NullPointerException( "cnonce_value may not be absent for MD5-Sess algorithm."); String A2 = null; if (qop_value == null || qop_value.trim().length() == 0 || qop_value.trim().equalsIgnoreCase("auth")) { A2 = method + ":" + digest_uri_value; } else { if (entity_body == null) entity_body = ""; A2 = method + ":" + digest_uri_value + ":" + H(entity_body); } String request_digest = null; if (cnonce_value != null && qop_value != null && nc_value != null && (qop_value.equalsIgnoreCase("auth") || qop_value.equalsIgnoreCase("auth-int"))) { request_digest = KD(hashUserNameRealmPasswd, nonce_value + ":" + nc_value + ":" + cnonce_value + ":" + qop_value + ":" + H(A2)); } else { request_digest = KD(hashUserNameRealmPasswd, nonce_value + ":" + H(A2)); } return request_digest; } /** * Calculates an http authentication response in accordance with rfc2617. *

    * * @param algorithm a string indicating a pair of algorithms (MD5 (default), or MD5-sess) used * to produce the digest and a checksum. * @param username_value username_value (see rfc2617) * @param realm_value A string that has been displayed to the user in order to determine the * context of the username and password to use. * @param passwd the password to encode in the challenge response. * @param nonce_value A server-specified data string provided in the challenge. * @param cnonce_value an optional client-chosen value whose purpose is to foil chosen * plaintext attacks. * @param method the SIP method of the request being challenged. * @param digest_uri_value the value of the "uri" directive on the Authorization header in the * request. * @param entity_body the entity-body * @param qop_value Indicates what "quality of protection" the client has applied to the * message. * @param nc_value the hexadecimal count of the number of requests (including the current * request) that the client has sent with the nonce value in this request. * @return a digest response as defined in rfc2617 * @throws NullPointerException in case of incorrectly null parameters. */ static String calculateResponse(String algorithm, String username_value, String realm_value, 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()) { stackLogger.logDebug("trying to authenticate using : " + algorithm + ", " + username_value + ", " + realm_value + ", " + (passwd != null && passwd.trim().length() > 0) + ", " + nonce_value + ", " + nc_value + ", " + cnonce_value + ", " + method + ", " + digest_uri_value + ", " + entity_body + ", " + qop_value); } if (username_value == null || realm_value == null || passwd == null || method == null || digest_uri_value == null || nonce_value == null) throw new NullPointerException( "Null parameter to MessageDigestAlgorithm.calculateResponse()"); // The following follows closely the algorithm for generating a response // digest as specified by rfc2617 String A1 = null; if (algorithm == null || algorithm.trim().length() == 0 || algorithm.trim().equalsIgnoreCase("MD5")) { A1 = username_value + ":" + realm_value + ":" + passwd; } else { if (cnonce_value == null || cnonce_value.length() == 0) throw new NullPointerException( "cnonce_value may not be absent for MD5-Sess algorithm."); A1 = H(username_value + ":" + realm_value + ":" + passwd) + ":" + nonce_value + ":" + cnonce_value; } String A2 = null; if (qop_value == null || qop_value.trim().length() == 0 || qop_value.trim().equalsIgnoreCase("auth")) { A2 = method + ":" + digest_uri_value; } else { if (entity_body == null) entity_body = ""; A2 = method + ":" + digest_uri_value + ":" + H(entity_body); } String request_digest = null; if (cnonce_value != null && qop_value != null && nc_value != null && (qop_value.equalsIgnoreCase("auth") || qop_value.equalsIgnoreCase("auth-int"))) { request_digest = KD(H(A1), nonce_value + ":" + nc_value + ":" + cnonce_value + ":" + qop_value + ":" + H(A2)); } else { request_digest = KD(H(A1), nonce_value + ":" + H(A2)); } return request_digest; } /** * Defined in rfc 2617 as H(data) = MD5(data); * * @param data data * @return MD5(data) */ private static String H(String data) { try { MessageDigest digest = MessageDigest.getInstance("MD5"); return toHexString(digest.digest(data.getBytes())); } catch (NoSuchAlgorithmException ex) { // shouldn't happen throw new RuntimeException("Failed to instantiate an MD5 algorithm", ex); } } /** * Defined in rfc 2617 as KD(secret, data) = H(concat(secret, ":", data)) * * @param data data * @param secret secret * @return H(concat(secret, ":", data)); */ private static String KD(String secret, String data) { return H(secret + ":" + data); } // the following code was copied from the NIST-SIP instant // messenger (its author is Olivier Deruelle). Thanks for making it public! /** * to hex converter */ private static final char[] toHex = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; /** * Converts b[] to hex string. * * @param b the bte array to convert * @return a Hex representation of b. */ private static String toHexString(byte b[]) { int pos = 0; char[] c = new char[b.length * 2]; for (int i = 0; i < b.length; i++) { c[pos++] = toHex[(b[i] >> 4) & 0x0F]; c[pos++] = toHex[b[i] & 0x0f]; } return new String(c); } } java/gov/nist/javax/sip/clientauthutils/SecureAccountManager.java0100644 0000000 0000000 00000001264 13513104763 024332 0ustar000000000 0000000 package gov.nist.javax.sip.clientauthutils; import javax.sip.ClientTransaction; public interface SecureAccountManager { /** * Returns the user credentials for a given SIP Domain. * You can implement any desired method (such as popping up a dialog for example ) * to retrieve the credentials. * * @param challengedTransaction - the transaction that is being challenged. * @param realm - the realm that is being challenged for which a credential should be * returned. * @return -- the user credentials associated with the domain. */ UserCredentialHash getCredentialHash(ClientTransaction challengedTransaction, String realm); } java/gov/nist/javax/sip/clientauthutils/UserCredentialHash.java0100644 0000000 0000000 00000001535 13513104763 024012 0ustar000000000 0000000 package gov.nist.javax.sip.clientauthutils; /** * Interface for those clients that only supply * hash(user:domain:password). This is more secure than simply supplying * password because the password cannot be extracted. Implementations * tend to prefer to store information in user accounts using such a * hash rather than plain text passwords because it offers better security. * */ public interface UserCredentialHash { /** * Get the user name. * * @return userName */ public String getUserName(); /** * Get the SipDomain. * * @return the SIP Domain. */ public String getSipDomain(); /** * Get the MD5(userName:sipdomain:password) * * @return the MD5 hash of userName:sipDomain:password. */ public String getHashUserDomainPassword(); } java/gov/nist/javax/sip/clientauthutils/UserCredentials.java0100644 0000000 0000000 00000001456 13513104763 023373 0ustar000000000 0000000 package gov.nist.javax.sip.clientauthutils; /** * The class is used whenever user credentials for a particular realm (site * server or service) are necessary * @author Emil Ivov * @author M. Ranganathan * @version 1.0 */ public interface UserCredentials { /** * Returns the name of the user that these credentials relate to. * @return the user name. */ public String getUserName(); /** * Returns a password associated with this set of credentials. * * @return a password associated with this set of credentials. */ public String getPassword(); /** * Returns the SIP Domain for this username password combination. * * @return the sip domain */ public String getSipDomain(); } java/gov/nist/javax/sip/clientauthutils/package.html0100644 0000000 0000000 00000001046 13513104763 021710 0ustar000000000 0000000 This package contains a set of utilities for client side Authentication Challenge handling. It has been adapted from the SIP communicator project and generously dontated to the JAIN-SIP project It is not part of the standard JAIN-SIP implementation at this point but is being considered for addition as this is an operation that is commonly required by all SIP clients; it is hence a good capability to include in a library such as JAIN-SIP.

    Primary authors of this code are Emil Ivov with corrections from Jeroen van Bemmel. java/gov/nist/javax/sip/header/0040755 0000000 0000000 00000000000 13513104763 015440 5ustar000000000 0000000 java/gov/nist/javax/sip/header/Accept.java0100644 0000000 0000000 00000012512 13513104763 017500 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.InvalidArgumentException; /** * Accept header : The top level header is actually AcceptList which is a list of * Accept headers. * * @version 1.2 $Revision: 1.9 $ $Date: 2009/07/17 18:57:24 $ * * @since 1.1 * * @author M. Ranganathan
    * * * */ public final class Accept extends ParametersHeader implements javax.sip.header.AcceptHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -7866187924308658151L; /** mediaRange field */ protected MediaRange mediaRange; /** default constructor */ public Accept() { super(NAME); } /** returns true if this header allows all ContentTypes, * false otherwise. * @return Boolean */ public boolean allowsAllContentTypes() { if (mediaRange == null) return false; else return mediaRange.type.compareTo(STAR) == 0; } /** * returns true if this header allows all ContentSubTypes, * false otherwise. * @return boolean */ public boolean allowsAllContentSubTypes() { if (mediaRange == null) { return false; } else return mediaRange.getSubtype().compareTo(STAR) == 0; } /** Encode the value of this header into cannonical form. *@return encoded value of the header as a string. */ protected String encodeBody() { return encodeBody(new StringBuffer()).toString(); } protected StringBuffer encodeBody(StringBuffer buffer) { if (mediaRange != null) mediaRange.encode(buffer); if (parameters != null && !parameters.isEmpty()) { buffer.append(';'); parameters.encode(buffer); } return buffer; } /** get the MediaRange field * @return MediaRange */ public MediaRange getMediaRange() { return mediaRange; } /** get the contentType field * @return String */ public String getContentType() { if (mediaRange == null) return null; else return mediaRange.getType(); } /** get the ContentSubType fiels * @return String */ public String getContentSubType() { if (mediaRange == null) return null; else return mediaRange.getSubtype(); } /** * Get the q value. * @return float */ public float getQValue() { return getParameterAsFloat(ParameterNames.Q); } /** * Return true if the q value has been set. * @return boolean */ public boolean hasQValue() { return super.hasParameter(ParameterNames.Q); } /** *Remove the q value. */ public void removeQValue() { super.removeParameter(ParameterNames.Q); } /** set the ContentSubType field * @param subtype String to set */ public void setContentSubType(String subtype) { if (mediaRange == null) mediaRange = new MediaRange(); mediaRange.setSubtype(subtype); } /** set the ContentType field * @param type String to set */ public void setContentType(String type) { if (mediaRange == null) mediaRange = new MediaRange(); mediaRange.setType(type); } /** * Set the q value * @param qValue float to set * @throws IllegalArgumentException if qValue is <0.0 or >1.0 */ public void setQValue(float qValue) throws InvalidArgumentException { if (qValue == -1) super.removeParameter(ParameterNames.Q); super.setParameter(ParameterNames.Q, qValue); } /** * Set the mediaRange member * @param m MediaRange field */ public void setMediaRange(MediaRange m) { mediaRange = m; } public Object clone() { Accept retval = (Accept) super.clone(); if (this.mediaRange != null) retval.mediaRange = (MediaRange) this.mediaRange.clone(); return retval; } } java/gov/nist/javax/sip/header/AcceptEncoding.java0100644 0000000 0000000 00000010575 13513104763 021156 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.InvalidArgumentException; import javax.sip.header.*; import java.text.ParseException; /** * Accept-Encoding SIP (HTTP) Header. * * @author M. Ranganathan * @author Olivier Deruelle
    * @version 1.2 $Revision: 1.7 $ $Date: 2009/07/17 18:57:24 $ * @since 1.1 * *

     *  From HTTP RFC 2616
     *
     *
     *    The Accept-Encoding request-header field is similar to Accept, but
     *    restricts the content-codings (section 3.5) that are acceptable in
     *    the response.
     *
     *
     *        Accept-Encoding  = "Accept-Encoding" ":"
     *
     *
     *                           1#( codings [ ";" "q" "=" qvalue ] )
     *        codings          = ( content-coding | "*" )
     *
     *    Examples of its use are:
     *
     *        Accept-Encoding: compress, gzip
     *        Accept-Encoding:
     *        Accept-Encoding: *
     *        Accept-Encoding: compress;q=0.5, gzip;q=1.0
     *        Accept-Encoding: gzip;q=1.0, identity; q=0.5, *;q=0
     * 
    * */ public final class AcceptEncoding extends ParametersHeader implements AcceptEncodingHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -1476807565552873525L; /** * contentEncoding field */ protected String contentCoding; /** * default constructor */ public AcceptEncoding() { super(NAME); } /** * Encode the value of this header. * * @return the value of this header encoded into a string. */ protected String encodeBody() { return encode(new StringBuffer()).toString(); } protected StringBuffer encodeBody(StringBuffer buffer) { if (contentCoding != null) { buffer.append(contentCoding); } if (parameters != null && !parameters.isEmpty()) { buffer.append(SEMICOLON).append(parameters.encode()); } return buffer; } /** * get QValue field * * @return float */ public float getQValue() { return getParameterAsFloat("q"); } /** * get ContentEncoding field * * @return String */ public String getEncoding() { return contentCoding; } /** * Set the qvalue member * * @param q * double to set */ public void setQValue(float q) throws InvalidArgumentException { if (q < 0.0 || q > 1.0) throw new InvalidArgumentException("qvalue out of range!"); super.setParameter("q", q); } /** * Sets the encoding of an EncodingHeader. * * @param encoding - * the new string value defining the encoding. * @throws ParseException * which signals that an error has been reached unexpectedly * while parsing the encoding value. */ public void setEncoding(String encoding) throws ParseException { if (encoding == null) throw new NullPointerException(" encoding parameter is null"); contentCoding = encoding; } } java/gov/nist/javax/sip/header/AcceptEncodingList.java0100644 0000000 0000000 00000003576 13513104763 022015 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.header.*; /** * AcceptEncodingList of AccepEncoding headers. * *@author M. Ranganathan *@version 1.2 $Revision: 1.6 $ $Date: 2009/07/17 18:57:25 $ *@since 1.1 * * */ public class AcceptEncodingList extends SIPHeaderList{ @Override public Object clone() { AcceptEncodingList retval = new AcceptEncodingList(); retval.clonehlist(this.hlist); return retval; } /** default constructor */ public AcceptEncodingList() { super(AcceptEncoding.class, AcceptEncodingHeader.NAME); } } java/gov/nist/javax/sip/header/AcceptLanguage.java0100644 0000000 0000000 00000013101 13513104763 021137 0ustar000000000 0000000 /* * 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.javax.sip.header; import gov.nist.core.*; import javax.sip.header.AcceptLanguageHeader; import javax.sip.InvalidArgumentException; import java.util.Locale; /** * Accept Language body. * * @author M. Ranganathan * @version 1.2 $Revision: 1.8 $ $Date: 2009/10/18 13:46:32 $ * @since 1.1 * * *
     * HTTP RFC 2616 Section 14.4
     * Accept-Language = "Accept-Language" ":"
     *                         1#( language-range [ ";" "q" "=" qvalue ] )
     *       language-range  = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" )
     *
     * 
    * * @see AcceptLanguageList */ public final class AcceptLanguage extends ParametersHeader implements AcceptLanguageHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -4473982069737324919L; /** languageRange field */ protected String languageRange; /** default constructor */ public AcceptLanguage() { super(NAME); } /** Encode the value of this header to a string. *@return encoded header as a string. */ protected String encodeBody() { StringBuffer encoding = new StringBuffer(); if (languageRange != null) { encoding.append(languageRange); } if (!parameters.isEmpty()) { encoding.append(SEMICOLON).append(parameters.encode()); } return encoding.toString(); } /** get the LanguageRange field * @return String */ public String getLanguageRange() { return languageRange; } /** get the QValue field. Return -1 if the parameter has not been * set. * @return float */ public float getQValue() { if (!hasParameter("q")) return -1; return ((Float) parameters.getValue("q")).floatValue(); } /** * Return true if the q value has been set. * @since 1.0 * @return boolean */ public boolean hasQValue() { return hasParameter("q"); } /** * Remove the q value. * @since 1.0 */ public void removeQValue() { removeParameter("q"); } /** * Set the languageRange. * * @param languageRange is the language range to set. * */ public void setLanguageRange(String languageRange) { this.languageRange = languageRange.trim(); } /** * Sets q-value for media-range in AcceptLanguageHeader. Q-values allow the * * user to indicate the relative degree of preference for that media-range, * * using the qvalue scale from 0 to 1. If no q-value is present, the * * media-range should be treated as having a q-value of 1. * * * * @param q The new float value of the q-value, a value of -1 resets * the qValue. * * @throws InvalidArgumentException if the q parameter value is not * * -1 or between 0 and 1. * */ public void setQValue(float q) throws InvalidArgumentException { if (q < 0.0 || q > 1.0) throw new InvalidArgumentException("qvalue out of range!"); if (q == -1) this.removeParameter("q"); else this.setParameter(new NameValue("q", Float.valueOf(q))); } /** * Gets the language value of the AcceptLanguageHeader. * * * * @return the language Locale value of this AcceptLanguageHeader * */ public Locale getAcceptLanguage() { if (this.languageRange == null) return null; else { int dash = languageRange.indexOf('-'); if (dash>=0) { return new Locale( languageRange.substring(0,dash), languageRange.substring(dash+1) ); } else return new Locale( this.languageRange ); } } /** * Sets the language parameter of this AcceptLanguageHeader. * * * * @param language - the new Locale value of the language of * * AcceptLanguageHeader * * */ public void setAcceptLanguage(Locale language) { // JvB: need to take sub-tag into account if ( "".equals(language.getCountry())) { this.languageRange = language.getLanguage(); } else { this.languageRange = language.getLanguage() + '-' + language.getCountry(); } } } java/gov/nist/javax/sip/header/AcceptLanguageList.java0100644 0000000 0000000 00000004575 13513104763 022012 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.header.*; /** * AcceptLanguageList: Strings together a list of AcceptLanguage SIPHeaders. * @author M. Ranganathan * @version 1.2 $Revision: 1.7 $ $Date: 2009/07/17 18:57:25 $ * @since 1.1 * * */ public class AcceptLanguageList extends SIPHeaderList { private static final long serialVersionUID = -3289606805203488840L; @Override public Object clone() { AcceptLanguageList retval = new AcceptLanguageList(); retval.clonehlist(this.hlist); return retval; } public AcceptLanguageList() { super(AcceptLanguage.class, AcceptLanguageHeader.NAME); } public AcceptLanguage getFirst() { AcceptLanguage retval = (AcceptLanguage) super.getFirst(); if (retval != null) return retval; else return new AcceptLanguage(); } public AcceptLanguage getLast() { AcceptLanguage retval = (AcceptLanguage) super.getLast(); if (retval != null) return retval; else return new AcceptLanguage(); } } java/gov/nist/javax/sip/header/AcceptList.java0100644 0000000 0000000 00000003736 13513104763 020344 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.header.*; /** * Accept List of SIP headers. * * @author M. Ranganathan
    * @version 1.2 $Revision: 1.6 $ $Date: 2009/07/17 18:57:25 $ * * @since 1.1 * * @see Accept */ public class AcceptList extends SIPHeaderList { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -1800813338560484831L; @Override public Object clone() { AcceptList retval = new AcceptList(); retval.clonehlist(this.hlist); return retval; } /** * Default constructor */ public AcceptList() { super(Accept.class, AcceptHeader.NAME); } } java/gov/nist/javax/sip/header/AddressParameters.java0100644 0000000 0000000 00000001135 13513104763 021711 0ustar000000000 0000000 package gov.nist.javax.sip.header; import java.util.Map; import java.util.Map.Entry; import javax.sip.address.Address; import javax.sip.header.Parameters; public interface AddressParameters extends Parameters { /** * get the Address field * @return the imbedded Address */ public abstract Address getAddress(); /** * set the Address field * @param address Address to set */ public abstract void setAddress(Address address); /** * Get the parameters map. * */ public abstract Map> getParameters(); } java/gov/nist/javax/sip/header/AddressParametersHeader.java0100644 0000000 0000000 00000006115 13513104763 023025 0ustar000000000 0000000 /* * 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.address.*; import javax.sip.header.FromHeader; import javax.sip.header.HeaderAddress; import javax.sip.header.Parameters; import gov.nist.javax.sip.address.*; /** An abstract class for headers that take an address and parameters. * * @version 1.2 $Revision: 1.11 $ $Date: 2009/07/17 18:57:25 $ * * @since 1.1 * * @author M. Ranganathan
    * * * * */ public abstract class AddressParametersHeader extends ParametersHeader implements Parameters { protected AddressImpl address; /* (non-Javadoc) * @see gov.nist.javax.sip.header.AddressParameters#getAddress() */ public Address getAddress() { return address; } /* (non-Javadoc) * @see gov.nist.javax.sip.header.AddressParameters#setAddress(javax.sip.address.Address) */ public void setAddress(Address address) { this.address = (AddressImpl) address; } /** * Constructor given the name of the header. */ protected AddressParametersHeader(String name) { super(name); } /** * Constructor given a synch flag. * * @param name * @param sync */ protected AddressParametersHeader(String name, boolean sync) { super(name,sync); } /* (non-Javadoc) * @see gov.nist.javax.sip.header.AddressParameters#clone() */ public Object clone() { AddressParametersHeader retval = (AddressParametersHeader) super.clone(); if (this.address != null) retval.address = (AddressImpl) this.address.clone(); return retval; } /* (non-Javadoc) * @see gov.nist.javax.sip.header.AddressParameters#equals(java.lang.Object) */ public boolean equals(Object other) { if (this==other) return true; if (other instanceof HeaderAddress && other instanceof Parameters) { final HeaderAddress o = (HeaderAddress) other; return this.getAddress().equals( o.getAddress() ) && this.equalParameters( (Parameters) o ); } return false; } } java/gov/nist/javax/sip/header/AlertInfo.java0100644 0000000 0000000 00000007206 13513104763 020170 0ustar000000000 0000000 /* * 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.javax.sip.header; import java.text.ParseException; import gov.nist.javax.sip.address.*; import javax.sip.address.*; /** * AlertInfo SIP Header. * * @author M. Ranganathan
    * * @since 1.1 * * @version 1.2 $Revision: 1.8 $ $Date: 2009/07/17 18:57:25 $ * * */ public final class AlertInfo extends ParametersHeader implements javax.sip.header.AlertInfoHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = 4159657362051508719L; /** URI field */ protected GenericURI uri; /** String field */ protected String string; /** Constructor */ public AlertInfo() { super(NAME); } /** * Return value encoding in canonical form. * @return The value of the header in canonical encoding. */ protected String encodeBody() { StringBuffer encoding = new StringBuffer(); if (uri != null) { encoding.append(LESS_THAN).append(uri.encode()).append(GREATER_THAN); } else if (string != null) { encoding.append(string); } if (!parameters.isEmpty()) { encoding.append(SEMICOLON).append(parameters.encode()); } return encoding.toString(); } /** * Set the uri member * @param uri URI to set */ public void setAlertInfo(URI uri) { this.uri = (GenericURI) uri; } /** * Set the string member * @param string String to set */ public void setAlertInfo(String string) { this.string = string; } /** * Returns the AlertInfo value of this AlertInfoHeader. * @return the URI representing the AlertInfo. */ public URI getAlertInfo() { URI alertInfoUri = null; if (this.uri != null) { alertInfoUri = (URI) this.uri; } else { try { alertInfoUri = (URI) new GenericURI(string); } catch (ParseException e) { ; // Eat the exception. } } return alertInfoUri; } public Object clone() { AlertInfo retval = (AlertInfo) super.clone(); if (this.uri != null) { retval.uri = (GenericURI) this.uri.clone(); } else if (this.string != null) { retval.string = this.string; } return retval; } } java/gov/nist/javax/sip/header/AlertInfoList.java0100644 0000000 0000000 00000003527 13513104763 021026 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.header.*; /** * AlertInfo SIPHeader - there can be several AlertInfo headers. * *@author M. Ranganathan
    * * * */ public class AlertInfoList extends SIPHeaderList { private static final long serialVersionUID = 1L; public Object clone() { AlertInfoList retval = new AlertInfoList(); retval.clonehlist(this.hlist); return retval; } /** default constructor */ public AlertInfoList() { super( AlertInfo.class,AlertInfoHeader.NAME); } } java/gov/nist/javax/sip/header/Allow.java0100644 0000000 0000000 00000005165 13513104763 017365 0ustar000000000 0000000 /* * 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.javax.sip.header; import java.text.ParseException; /** * Allow SIPHeader. * * @author M. Ranganathan
    * @version 1.2 $Revision: 1.6 $ $Date: 2009/07/17 18:57:26 $ * @since 1.1 * * */ public final class Allow extends SIPHeader implements javax.sip.header.AllowHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -3105079479020693930L; /** method field */ protected String method; /** default constructor */ public Allow() { super(ALLOW); } /** constructor * @param m String to set */ public Allow(String m) { super(ALLOW); method = m; } /** get the method field * @return String */ public String getMethod() { return method; } /** * Set the method member * @param method method to set. */ public void setMethod(String method) throws ParseException { if (method == null) throw new NullPointerException( "JAIN-SIP Exception" + ", Allow, setMethod(), the method parameter is null."); this.method = method; } /** Return body encoded in canonical form. * @return body encoded as a string. */ protected String encodeBody() { return method; } } java/gov/nist/javax/sip/header/AllowEvents.java0100644 0000000 0000000 00000006151 13513104763 020546 0ustar000000000 0000000 /* * 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.javax.sip.header; import java.text.ParseException; /** * AllowEvents SIPHeader. * * @author M. Ranganathan NIST/ITL ANTD.
    * @author Olivier Deruelle
    * * * @version 1.2 $Revision: 1.7 $ $Date: 2009/07/17 18:57:26 $ * @since 1.1 */ public final class AllowEvents extends SIPHeader implements javax.sip.header.AllowEventsHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = 617962431813193114L; /** method field */ protected String eventType; /** default constructor */ public AllowEvents() { super(ALLOW_EVENTS); } /** constructor * @param m String to set */ public AllowEvents(String m) { super(ALLOW_EVENTS); eventType = m; } /** * Sets the eventType defined in this AllowEventsHeader. * * @param eventType - the String defining the method supported * in this AllowEventsHeader * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the Strings defining the eventType supported */ public void setEventType(String eventType) throws ParseException { if (eventType == null) throw new NullPointerException( "JAIN-SIP Exception," + "AllowEvents, setEventType(), the eventType parameter is null"); this.eventType = eventType; } /** * Gets the eventType of the AllowEventsHeader. * * @return the String object identifing the eventTypes of AllowEventsHeader. */ public String getEventType() { return eventType; } /** Return body encoded in canonical form. * @return body encoded as a string. */ protected String encodeBody() { return eventType; } } java/gov/nist/javax/sip/header/AllowEventsList.java0100644 0000000 0000000 00000006752 13513104763 021411 0ustar000000000 0000000 /* * 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.javax.sip.header; import java.util.*; import java.text.ParseException; import javax.sip.header.*; /** * List of AllowEvents headers. * The sip message can have multiple AllowEvents headers which are strung * together in a list. * * @author M. Ranganathan
    * @author Olivier Deruelle
    * * * @version 1.2 $Revision: 1.7 $ $Date: 2009/07/17 18:57:26 $ * @since 1.1 * */ public class AllowEventsList extends SIPHeaderList { private static final long serialVersionUID = -684763195336212992L; public Object clone() { AllowEventsList retval = new AllowEventsList(); retval.clonehlist(this.hlist); return retval; } /** default constructor */ public AllowEventsList() { super(AllowEvents.class, AllowEventsHeader.NAME); } /** * Gets an Iterator of all the methods of the AllowEventsHeader. Returns an empty * * Iterator if no methods are defined in this AllowEvents Header. * * * * @return Iterator of String objects each identifing the methods of * * AllowEventsHeader. * * */ public ListIterator getMethods() { ListIterator li = super.hlist.listIterator(); LinkedList ll = new LinkedList (); while (li.hasNext()) { AllowEvents allowEvents = (AllowEvents) li.next(); ll.add(allowEvents.getEventType()); } return ll.listIterator(); } /** * Sets the methods supported defined by this AllowEventsHeader. * * * * @param methods - the Iterator of Strings defining the methods supported * * in this AllowEventsHeader * * @throws ParseException which signals that an error has been reached * * unexpectedly while parsing the Strings defining the methods supported. * * */ public void setMethods(List methods) throws ParseException { ListIterator it = methods.listIterator(); while (it.hasNext()) { AllowEvents allowEvents = new AllowEvents(); allowEvents.setEventType((String) it.next()); this.add(allowEvents); } } } java/gov/nist/javax/sip/header/AllowList.java0100644 0000000 0000000 00000006454 13513104763 020223 0ustar000000000 0000000 /* * 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.javax.sip.header; import java.util.*; import java.text.ParseException; import javax.sip.header.*; /** * List of ALLOW headers. The sip message can have multiple Allow headers * * @author M. Ranganathan
    * @version 1.2 $Revision: 1.7 $ $Date: 2009/07/17 18:57:26 $ * @since 1.1 * */ public class AllowList extends SIPHeaderList { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -4699795429662562358L; public Object clone() { AllowList retval = new AllowList(); retval.clonehlist(this.hlist); return retval; } /** default constructor */ public AllowList() { super(Allow.class, AllowHeader.NAME); } /** * Gets an Iterator of all the methods of the AllowHeader. Returns an empty * * Iterator if no methods are defined in this Allow Header. * * * * @return Iterator of String objects each identifing the methods of * * AllowHeader. * * */ public ListIterator getMethods() { LinkedList ll = new LinkedList (); for ( Iterator it = this.hlist.iterator(); it.hasNext();) { Allow a = (Allow)it.next(); ll.add(a.getMethod()); } return ll.listIterator(); } /** * Sets the methods supported defined by this AllowHeader. * * * * @param methods - the Iterator of Strings defining the methods supported * * in this AllowHeader * * @throws ParseException which signals that an error has been reached * * unexpectedly while parsing the Strings defining the methods supported. * * */ public void setMethods(List methods) throws ParseException { ListIterator it = methods.listIterator(); while (it.hasNext()) { Allow allow = new Allow(); allow.setMethod((String) it.next()); this.add(allow); } } } java/gov/nist/javax/sip/header/AuthenticationHeader.java0100644 0000000 0000000 00000043256 13513104763 022402 0ustar000000000 0000000 /* * 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.javax.sip.header; import gov.nist.core.*; import gov.nist.javax.sip.header.ims.ParameterNamesIms; import java.text.ParseException; /* * 2005/06/12: geir.hedemark@telio.no: Changed behaviour of qop parameter in * Authorization header - removed quoting of string according to * RFC3261, BNF element "message-qop" (as opposed to "qop-options", * which is quoted. */ /** * The generic AuthenticationHeader * * @author Olivier Deruelle * @author M. Ranganathan
    * @since 1.1 * @version 1.2 $Revision: 1.13 $ $Date: 2009/10/18 13:46:32 $ * * */ public abstract class AuthenticationHeader extends ParametersHeader { public static final String DOMAIN = ParameterNames.DOMAIN; public static final String REALM = ParameterNames.REALM; public static final String OPAQUE = ParameterNames.OPAQUE; public static final String ALGORITHM = ParameterNames.ALGORITHM; public static final String QOP = ParameterNames.QOP; public static final String STALE = ParameterNames.STALE; public static final String SIGNATURE = ParameterNames.SIGNATURE; public static final String RESPONSE = ParameterNames.RESPONSE; public static final String SIGNED_BY = ParameterNames.SIGNED_BY; public static final String NC = ParameterNames.NC; public static final String URI = ParameterNames.URI; public static final String USERNAME = ParameterNames.USERNAME; public static final String CNONCE = ParameterNames.CNONCE; public static final String NONCE = ParameterNames.NONCE; public static final String IK = ParameterNamesIms.IK; public static final String CK = ParameterNamesIms.CK; public static final String INTEGRITY_PROTECTED = ParameterNamesIms.INTEGRITY_PROTECTED; protected String scheme; public AuthenticationHeader(String name) { super(name); parameters.setSeparator(Separators.COMMA); // oddball this.scheme = ParameterNames.DIGEST; } public AuthenticationHeader() { super(); parameters.setSeparator(Separators.COMMA); } /** * set the specified parameter. Bug reported by Dominic Sparks. * * @param name -- * name of the parameter * @param value -- * value of the parameter. */ public void setParameter(String name, String value) throws ParseException { NameValue nv = super.parameters.getNameValue(name.toLowerCase()); if (nv == null) { nv = new NameValue(name, value); if (name.equalsIgnoreCase(ParameterNames.QOP) || name.equalsIgnoreCase(ParameterNames.REALM) || name.equalsIgnoreCase(ParameterNames.CNONCE) || name.equalsIgnoreCase(ParameterNames.NONCE) || name.equalsIgnoreCase(ParameterNames.USERNAME) || name.equalsIgnoreCase(ParameterNames.DOMAIN) || name.equalsIgnoreCase(ParameterNames.OPAQUE) || name.equalsIgnoreCase(ParameterNames.NEXT_NONCE) || name.equalsIgnoreCase(ParameterNames.URI) || name.equalsIgnoreCase(ParameterNames.RESPONSE ) ||name.equalsIgnoreCase(ParameterNamesIms.IK) || name.equalsIgnoreCase(ParameterNamesIms.CK) || name.equalsIgnoreCase(ParameterNamesIms.INTEGRITY_PROTECTED)) { if (((this instanceof Authorization) || (this instanceof ProxyAuthorization)) && name.equalsIgnoreCase(ParameterNames.QOP)) { // NOP, QOP not quoted in authorization headers } else { nv.setQuotedValue(); } if (value == null) throw new NullPointerException("null value"); if (value.startsWith(Separators.DOUBLE_QUOTE)) throw new ParseException(value + " : Unexpected DOUBLE_QUOTE", 0); } super.setParameter(nv); } else nv.setValueAsObject(value); } /** * This is only used for the parser interface. * * @param challenge -- * the challenge from which the parameters are extracted. */ public void setChallenge(Challenge challenge) { this.scheme = challenge.scheme; super.parameters = challenge.authParams; } /** * Encode in canonical form. * * @return canonical string. */ public String encodeBody() { this.parameters.setSeparator(Separators.COMMA); return this.scheme + SP + parameters.encode(); } /** * Sets the scheme of the challenge information for this * AuthenticationHeaderHeader. For example, Digest. * * @param scheme - * the new string value that identifies the challenge information * scheme. */ public void setScheme(String scheme) { this.scheme = scheme; } /** * Returns the scheme of the challenge information for this * AuthenticationHeaderHeader. * * @return the string value of the challenge information. */ public String getScheme() { return scheme; } /** * Sets the Realm of the WWWAuthenicateHeader to the realm * parameter value. Realm strings MUST be globally unique. It is RECOMMENDED * that a realm string contain a hostname or domain name. Realm strings * SHOULD present a human-readable identifier that can be rendered to a * user. * * @param realm * the new Realm String of this WWWAuthenicateHeader. * @throws ParseException * which signals that an error has been reached unexpectedly * while parsing the realm. */ public void setRealm(String realm) throws ParseException { if (realm == null) throw new NullPointerException( "JAIN-SIP Exception, " + " AuthenticationHeader, setRealm(), The realm parameter is null"); setParameter(ParameterNames.REALM, realm); } /** * Returns the Realm value of this WWWAuthenicateHeader. This convenience * method returns only the realm of the complete Challenge. * * @return the String representing the Realm information, null if value is * not set. * @since v1.1 */ public String getRealm() { return getParameter(ParameterNames.REALM); } /** * Sets the Nonce of the WWWAuthenicateHeader to the nonce * parameter value. * * @param nonce - * the new nonce String of this WWWAuthenicateHeader. * @throws ParseException * which signals that an error has been reached unexpectedly * while parsing the nonce value. * @since v1.1 */ public void setNonce(String nonce) throws ParseException { if (nonce == null) throw new NullPointerException( "JAIN-SIP Exception, " + " AuthenticationHeader, setNonce(), The nonce parameter is null"); setParameter(NONCE, nonce); } /** * Returns the Nonce value of this WWWAuthenicateHeader. * * @return the String representing the nonce information, null if value is * not set. * @since v1.1 */ public String getNonce() { return getParameter(ParameterNames.NONCE); } /** * Sets the URI of the WWWAuthenicateHeader to the uri parameter * value. * * @param uri - * the new URI of this AuthenicationHeader. * @since v1.1 * * Note that since 1.2 this is no longer applicable to the WWW-Authenticate * and Proxy-Authenticate headers */ public void setURI(javax.sip.address.URI uri) { if (uri != null) { NameValue nv = new NameValue(ParameterNames.URI, uri); nv.setQuotedValue(); super.parameters.set(nv); } else { throw new NullPointerException("Null URI"); } } /** * Returns the URI value of this WWWAuthenicateHeader, for example * DigestURI. * * @return the URI representing the URI information, null if value is not * set. * @since v1.1 * * Note that since 1.2 this is no longer applicable to the WWW-Authenticate * and Proxy-Authenticate headers */ public javax.sip.address.URI getURI() { return getParameterAsURI(ParameterNames.URI); } /** * Sets the Algorithm of the WWWAuthenicateHeader to the new algorithm * parameter value. * * @param algorithm - * the new algorithm String of this WWWAuthenicateHeader. * @throws ParseException * which signals that an error has been reached unexpectedly * while parsing the algorithm value. * @since v1.1 */ public void setAlgorithm(String algorithm) throws ParseException { if (algorithm == null) throw new NullPointerException("null arg"); setParameter(ParameterNames.ALGORITHM, algorithm); } /** * Returns the Algorithm value of this WWWAuthenicateHeader. * * @return the String representing the Algorithm information, null if the * value is not set. * @since v1.1 */ public String getAlgorithm() { return getParameter(ParameterNames.ALGORITHM); } /** * Sets the Qop value of the WWWAuthenicateHeader to the new qop * parameter value. * * @param qop - * the new Qop string of this WWWAuthenicateHeader. * @throws ParseException * which signals that an error has been reached unexpectedly * while parsing the Qop value. * @since v1.1 */ public void setQop(String qop) throws ParseException { if (qop == null) throw new NullPointerException("null arg"); setParameter(ParameterNames.QOP, qop); } /** * Returns the Qop value of this WWWAuthenicateHeader. * * @return the string representing the Qop information, null if the value is * not set. * @since v1.1 */ public String getQop() { return getParameter(ParameterNames.QOP); } /** * Sets the Opaque value of the WWWAuthenicateHeader to the new opaque * parameter value. * * @param opaque - * the new Opaque string of this WWWAuthenicateHeader. * @throws ParseException * which signals that an error has been reached unexpectedly * while parsing the opaque value. * @since v1.1 */ public void setOpaque(String opaque) throws ParseException { if (opaque == null) throw new NullPointerException("null arg"); setParameter(ParameterNames.OPAQUE, opaque); } /** * Returns the Opaque value of this WWWAuthenicateHeader. * * @return the String representing the Opaque information, null if the value * is not set. * @since v1.1 */ public String getOpaque() { return getParameter(ParameterNames.OPAQUE); } /** * Sets the Domain of the WWWAuthenicateHeader to the domain * parameter value. * * @param domain - * the new Domain string of this WWWAuthenicateHeader. * @throws ParseException * which signals that an error has been reached unexpectedly * while parsing the domain. * @since v1.1 */ public void setDomain(String domain) throws ParseException { if (domain == null) throw new NullPointerException("null arg"); setParameter(ParameterNames.DOMAIN, domain); } /** * Returns the Domain value of this WWWAuthenicateHeader. * * @return the String representing the Domain information, null if value is * not set. * @since v1.1 */ public String getDomain() { return getParameter(ParameterNames.DOMAIN); } /** * Sets the value of the stale parameter of the WWWAuthenicateHeader to the * stale parameter value. * * @param stale - * the Boolean.valueOf value of the stale parameter. * @since v1.1 */ public void setStale(boolean stale) { setParameter(new NameValue(ParameterNames.STALE, Boolean.valueOf(stale))); } /** * Returns the boolean value of the state paramater of this * WWWAuthenicateHeader. * * @return the boolean representing if the challenge is stale. * @since v1.1 */ public boolean isStale() { return this.getParameterAsBoolean(ParameterNames.STALE); } /** * Set the CNonce. * * @param cnonce -- * a nonce string. */ public void setCNonce(String cnonce) throws ParseException { this.setParameter(ParameterNames.CNONCE, cnonce); } /** * Get the CNonce. * * @return the cnonce value. */ public String getCNonce() { return getParameter(ParameterNames.CNONCE); } public int getNonceCount() { return this.getParameterAsHexInt(ParameterNames.NC); } /** * Set the nonce count pakrameter. Bug fix sent in by Andreas Bystr�m */ public void setNonceCount(int param) throws java.text.ParseException { if (param < 0) throw new ParseException("bad value", 0); String nc = Integer.toHexString(param); String base = "00000000"; nc = base.substring(0, 8 - nc.length()) + nc; this.setParameter(ParameterNames.NC, nc); } /** * Get the RESPONSE value (or null if it does not exist). * * @return String response parameter value. */ public String getResponse() { return (String) getParameterValue(ParameterNames.RESPONSE); } /** * Set the Response. * * @param response * to set. */ public void setResponse(String response) throws ParseException { if (response == null) throw new NullPointerException("Null parameter"); // Bug fix from Andreas Bystr�m this.setParameter(RESPONSE, response); } /** * Returns the Username value of this AuthorizationHeader. This convenience * method returns only the username of the complete Response. * * @return the String representing the Username information, null if value * is not set. * * * */ public String getUsername() { return (String) getParameter(ParameterNames.USERNAME); } /** * Sets the Username of the AuthorizationHeader to the username * parameter value. * * @param username * the new Username String of this AuthorizationHeader. * * @throws ParseException * which signals that an error has been reached * * unexpectedly while parsing the username. * * * */ public void setUsername(String username) throws ParseException { this.setParameter(ParameterNames.USERNAME, username); } public void setIK(String ik) throws ParseException { if (ik == null) throw new NullPointerException( "JAIN-SIP Exception, " + " AuthenticationHeader, setIk(), The auth-param IK parameter is null"); setParameter(IK, ik); } public String getIK() { return getParameter(ParameterNamesIms.IK); } public void setCK(String ck) throws ParseException { if (ck == null) throw new NullPointerException( "JAIN-SIP Exception, " + " AuthenticationHeader, setCk(), The auth-param CK parameter is null"); setParameter(CK, ck); } public String getCK() { return getParameter(ParameterNamesIms.CK); } public void setIntegrityProtected(String integrityProtected) throws ParseException { if (integrityProtected == null) throw new NullPointerException( "JAIN-SIP Exception, " + " AuthenticationHeader, setIntegrityProtected(), The integrity-protected parameter is null"); setParameter(INTEGRITY_PROTECTED, integrityProtected); } public String getIntegrityProtected() { return getParameter(ParameterNamesIms.INTEGRITY_PROTECTED); } } java/gov/nist/javax/sip/header/AuthenticationInfo.java0100644 0000000 0000000 00000017606 13513104763 022105 0ustar000000000 0000000 /* * 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 gov.nist.core.*; import java.text.ParseException; /** * Authentication info SIP Header. * * @author M. Ranganathan NIST/ITL/ANTD * @since 1.1 * @version 1.2 $Revision: 1.9 $ $Date: 2009/07/17 18:57:27 $ * * */ public final class AuthenticationInfo extends ParametersHeader implements javax.sip.header.AuthenticationInfoHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -4371927900917127057L; /** Default contstructor. */ public AuthenticationInfo() { super(NAME); parameters.setSeparator(COMMA); // Odd ball. } public void add(NameValue nv) { parameters.set(nv); } /** Value of header encoded in canonical form. */ protected String encodeBody() { return parameters.encode(); } /** Get the name value pair for a given authentication info parameter. * *@param name is the name for which we want to retrieve the name value * list. */ public NameValue getAuthInfo(String name) { return parameters.getNameValue(name); } /** * Returns the AuthenticationInfo value of this AuthenticationInfoHeader. * * * * @return the String representing the AuthenticationInfo * * * */ public String getAuthenticationInfo() { return this.encodeBody(); } /** Returns the CNonce value of this AuthenticationInfoHeader. * * @return the String representing the cNonce information, null if value is * not set. * @since v1.1 */ public String getCNonce() { return this.getParameter(ParameterNames.CNONCE); } /** Returns the nextNonce value of this AuthenticationInfoHeader. * * @return the String representing the nextNonce * information, null if value is not set. * @since v1.1 */ public String getNextNonce() { return this.getParameter(ParameterNames.NEXT_NONCE); } /** Returns the Nonce Count value of this AuthenticationInfoHeader. * * @return the integer representing the nonceCount information, -1 if value is * not set. * @since v1.1 */ public int getNonceCount() { return this.getParameterAsInt(ParameterNames.NONCE_COUNT); } /** Returns the messageQop value of this AuthenticationInfoHeader. * * @return the string representing the messageQop information, null if the * value is not set. * @since v1.1 */ public String getQop() { return this.getParameter(ParameterNames.QOP); } /** Returns the Response value of this AuthenticationInfoHeader. * * @return the String representing the Response information. * @since v1.1 */ public String getResponse() { return this.getParameter(ParameterNames.RESPONSE_AUTH); } /** Sets the CNonce of the AuthenticationInfoHeader to the cNonce * parameter value. * * @param cNonce - the new cNonce String of this AuthenticationInfoHeader. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the cNonce value. * @since v1.1 */ public void setCNonce(String cNonce) throws ParseException { this.setParameter(ParameterNames.CNONCE, cNonce); } /** Sets the NextNonce of the AuthenticationInfoHeader to the nextNonce * parameter value. * * @param nextNonce - the new nextNonce String of this AuthenticationInfoHeader. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the nextNonce value. * @since v1.1 */ public void setNextNonce(String nextNonce) throws ParseException { this.setParameter(ParameterNames.NEXT_NONCE, nextNonce); } /** Sets the Nonce Count of the AuthenticationInfoHeader to the nonceCount * parameter value. * * @param nonceCount - the new nonceCount integer of this AuthenticationInfoHeader. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the nonceCount value. * @since v1.1 */ public void setNonceCount(int nonceCount) throws ParseException { if (nonceCount < 0) throw new ParseException("bad value", 0); String nc = Integer.toHexString(nonceCount); String base = "00000000"; nc = base.substring(0, 8 - nc.length()) + nc; this.setParameter(ParameterNames.NC, nc); } /** Sets the Qop value of the AuthenticationInfoHeader to the new * qop parameter value. * * @param qop - the new Qop string of this AuthenticationInfoHeader. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the Qop value. * @since v1.1 */ public void setQop(String qop) throws ParseException { this.setParameter(ParameterNames.QOP, qop); } /** Sets the Response of the * AuthenticationInfoHeader to the new response * parameter value. * * @param response - the new response String of this * AuthenticationInfoHeader. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the Response. * @since v1.1 */ public void setResponse(String response) throws ParseException { this.setParameter(ParameterNames.RESPONSE_AUTH, response); } public void setParameter(String name, String value) throws ParseException { if (name == null) throw new NullPointerException("null name"); NameValue nv = super.parameters.getNameValue(name.toLowerCase()); if (nv == null) { nv = new NameValue(name, value); if (name.equalsIgnoreCase(ParameterNames.QOP) || name.equalsIgnoreCase(ParameterNames.NEXT_NONCE) || name.equalsIgnoreCase(ParameterNames.REALM) || name.equalsIgnoreCase(ParameterNames.CNONCE) || name.equalsIgnoreCase(ParameterNames.NONCE) || name.equalsIgnoreCase(ParameterNames.OPAQUE) || name.equalsIgnoreCase(ParameterNames.USERNAME) || name.equalsIgnoreCase(ParameterNames.DOMAIN) || name.equalsIgnoreCase(ParameterNames.NEXT_NONCE) || name.equalsIgnoreCase(ParameterNames.RESPONSE_AUTH)) { if (value == null) throw new NullPointerException("null value"); if (value.startsWith(Separators.DOUBLE_QUOTE)) throw new ParseException( value + " : Unexpected DOUBLE_QUOTE", 0); nv.setQuotedValue(); } super.setParameter(nv); } else nv.setValueAsObject(value); } } java/gov/nist/javax/sip/header/AuthenticationInfoList.java0100644 0000000 0000000 00000003660 13513104763 022734 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.header.*; /** * A list of AuthenticationInfo headers (there can be multiple in a message). * *@author M. Ranganathan
    * */ public class AuthenticationInfoList extends SIPHeaderList { private static final long serialVersionUID = 1L; public Object clone() { AuthenticationInfoList retval = new AuthenticationInfoList(); retval.clonehlist(this.hlist); return retval; } /** Creates a new instance of AuthenticationList */ public AuthenticationInfoList() { super( AuthenticationInfo.class, AuthenticationInfoHeader.NAME); } } java/gov/nist/javax/sip/header/Authorization.java0100644 0000000 0000000 00000003763 13513104763 021151 0ustar000000000 0000000 /* * 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.javax.sip.header; import gov.nist.javax.sip.header.ims.AuthorizationHeaderIms; import javax.sip.header.*; /** * Authorization SIP header. * * @see ProxyAuthorization * * @author M. Ranganathan NIST/ITL/ANTD
    * @version 1.2 $Revision: 1.6 $ $Date: 2009/07/17 18:57:27 $ * * */ public class Authorization extends gov.nist.javax.sip.header.AuthenticationHeader implements javax.sip.header.AuthorizationHeader, AuthorizationHeaderIms { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -8897770321892281348L; /** Default constructor. */ public Authorization() { super(AuthorizationHeader.NAME); } } java/gov/nist/javax/sip/header/AuthorizationList.java0100644 0000000 0000000 00000003723 13513104763 022001 0ustar000000000 0000000 /* * 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.javax.sip.header; /** * WWWAuthenticate SIPHeader (of which there can be several?) * * @version 1.2 $Revision: 1.5 $ $Date: 2009/07/17 18:57:27 $ * * @author M. Ranganathan
    * * * */ public class AuthorizationList extends SIPHeaderList { /** * Comment for serialVersionUID */ private static final long serialVersionUID = 1L; public Object clone() { AuthorizationList retval = new AuthorizationList(); retval.clonehlist(this.hlist); return retval; } /** * constructor. */ public AuthorizationList() { super(Authorization.class, Authorization.NAME); } } java/gov/nist/javax/sip/header/CSeq.java0100644 0000000 0000000 00000012302 13513104763 017131 0ustar000000000 0000000 /* * 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.javax.sip.header; import gov.nist.javax.sip.message.SIPRequest; import javax.sip.InvalidArgumentException; import javax.sip.header.CSeqHeader; import java.text.ParseException; /** * CSeq SIP Header. * * @author M. Ranganathan
    * @version 1.2 $Revision: 1.10 $ $Date: 2009/10/18 13:46:33 $ * @since 1.1 * */ public class CSeq extends SIPHeader implements javax.sip.header.CSeqHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -5405798080040422910L; /** * seqno field */ protected Long seqno; /** * method field */ protected String method; /** * Constructor. */ public CSeq() { super(CSEQ); } /** * Constructor given the sequence number and method. * * @param seqno is the sequence number to assign. * @param method is the method string. */ public CSeq(long seqno, String method) { this(); this.seqno = Long.valueOf(seqno); this.method = SIPRequest.getCannonicalName(method); } /** * Compare two cseq headers for equality. * @param other Object to compare against. * @return true if the two cseq headers are equals, false * otherwise. */ public boolean equals(Object other) { if (other instanceof CSeqHeader) { final CSeqHeader o = (CSeqHeader) other; return this.getSeqNumber() == o.getSeqNumber() && this.getMethod().equals( o.getMethod() ); } return false; } /** * Return canonical encoded header. * @return String with canonical encoded header. */ public String encode() { return headerName + COLON + SP + encodeBody() + NEWLINE; } /** * Return canonical header content. (encoded header except headerName:) * * @return encoded string. */ public String encodeBody() { return encodeBody(new StringBuffer()).toString(); } protected StringBuffer encodeBody(StringBuffer buffer) { return buffer.append(seqno).append(SP).append(method.toUpperCase()); } /** * Get the method. * @return String the method. */ public String getMethod() { return method; } /* * (non-Javadoc) * @see javax.sip.header.CSeqHeader#setSequenceNumber(long) */ public void setSeqNumber(long sequenceNumber) throws InvalidArgumentException { if (sequenceNumber < 0 ) throw new InvalidArgumentException( "JAIN-SIP Exception, CSeq, setSequenceNumber(), " + "the sequence number parameter is < 0 : " + sequenceNumber); else if ( sequenceNumber > ((long)1)<<32 - 1) throw new InvalidArgumentException( "JAIN-SIP Exception, CSeq, setSequenceNumber(), " + "the sequence number parameter is too large : " + sequenceNumber); seqno = Long.valueOf(sequenceNumber); } /** * For backwards compatibility */ public void setSequenceNumber(int sequenceNumber) throws InvalidArgumentException { this.setSeqNumber( (long) sequenceNumber ); } /* * (non-Javadoc) * @see javax.sip.header.CSeqHeader#setMethod(java.lang.String) */ public void setMethod(String meth) throws ParseException { if (meth == null) throw new NullPointerException( "JAIN-SIP Exception, CSeq" + ", setMethod(), the meth parameter is null"); this.method = SIPRequest.getCannonicalName(meth); } /* * (non-Javadoc) * @see javax.sip.header.CSeqHeader#getSequenceNumber() */ public int getSequenceNumber() { if (this.seqno == null) return 0; else return this.seqno.intValue(); } public long getSeqNumber() { return this.seqno.longValue(); } } java/gov/nist/javax/sip/header/CallID.java0100644 0000000 0000000 00000010603 13513104763 017370 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.header.CallIdHeader; import java.text.ParseException; /** * Call ID SIPHeader. * * @author M. Ranganathan
    * @version 1.2 $Revision: 1.7 $ $Date: 2009/07/17 18:57:27 $ * @since 1.1 */ public class CallID extends SIPHeader implements javax.sip.header.CallIdHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -6463630258703731156L; /** * callIdentifier field */ protected CallIdentifier callIdentifier; /** * Default constructor */ public CallID() { super(NAME); } /* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) * * CallIDs are compared case-insensitively */ public boolean equals( Object other ) { if (this==other) return true; if (other instanceof CallIdHeader) { final CallIdHeader o = (CallIdHeader) other; return this.getCallId().equalsIgnoreCase( o.getCallId() ); } return false; } /** * Encode the body part of this header (i.e. leave out the hdrName). *@return String encoded body part of the header. */ public String encodeBody() { return encodeBody(new StringBuffer()).toString(); } protected StringBuffer encodeBody(StringBuffer buffer) { if (callIdentifier != null) callIdentifier.encode(buffer); return buffer; } /** * get the CallId field. This does the same thing as * encodeBody * @return String the encoded body part of the */ public String getCallId() { return encodeBody(); } /** * get the call Identifer member. * @return CallIdentifier */ public CallIdentifier getCallIdentifer() { return callIdentifier; } /** * set the CallId field * @param cid String to set. This is the body part of the Call-Id * header. It must have the form localId@host or localId. * @throws IllegalArgumentException if cid is null, not a token, or is * not a token@token. */ public void setCallId(String cid) throws ParseException { try { callIdentifier = new CallIdentifier(cid); } catch (IllegalArgumentException ex) { throw new ParseException(cid, 0); } } /** * Set the callIdentifier member. * @param cid CallIdentifier to set (localId@host). */ public void setCallIdentifier(CallIdentifier cid) { callIdentifier = cid; } /** Constructor given the call Identifier. *@param callId string call identifier (should be localid@host) *@throws IllegalArgumentException if call identifier is bad. */ public CallID(String callId) throws IllegalArgumentException { super(NAME); this.callIdentifier = new CallIdentifier(callId); } public Object clone() { CallID retval = (CallID) super.clone(); if (this.callIdentifier != null) retval.callIdentifier = (CallIdentifier) this.callIdentifier.clone(); return retval; } } java/gov/nist/javax/sip/header/CallIdentifier.java0100644 0000000 0000000 00000012122 13513104763 021154 0ustar000000000 0000000 /* * 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.javax.sip.header; /** * The call identifer that goes into a callID header and a in-reply-to header. * * @author M. Ranganathan
    * @version 1.2 $Revision: 1.7 $ $Date: 2009/12/16 02:38:35 $ * @see CallID * @see InReplyTo * @since 1.1 */ public final class CallIdentifier extends SIPObject { /** * Comment for serialVersionUID */ private static final long serialVersionUID = 7314773655675451377L; /** * localId field */ protected String localId; /** * host field */ protected String host; /** * Default constructor */ public CallIdentifier() { } /** * Constructor * @param localId id is the local id. * @param host is the host. */ public CallIdentifier(String localId, String host) { this.localId = localId; this.host = host; } /** * constructor * @param cid String to set * @throws IllegalArgumentException if cid is null or is not a token, * or token@token */ public CallIdentifier(String cid) throws IllegalArgumentException { setCallID(cid); } /** * Get the encoded version of this id. * @return String to set */ public String encode() { return encode(new StringBuffer()).toString(); } public StringBuffer encode(StringBuffer buffer) { buffer.append(localId); if (host != null) { buffer.append(AT).append(host); } return buffer; } /** * Compare two call identifiers for equality. * @param other Object to set * @return true if the two call identifiers are equals, false * otherwise */ public boolean equals(Object other) { if (other == null ) return false; if (!other.getClass().equals(this.getClass())) { return false; } CallIdentifier that = (CallIdentifier) other; if (this.localId.compareTo(that.localId) != 0) { return false; } if (this.host == that.host) return true; if ((this.host == null && that.host != null) || (this.host != null && that.host == null)) return false; if (host.compareToIgnoreCase(that.host) != 0) { return false; } return true; } @Override public int hashCode() { if (this.localId == null ) { throw new UnsupportedOperationException("Hash code called before id is set"); } return this.localId.hashCode(); } /** get the LocalId field * @return String */ public String getLocalId() { return localId; } /** get the host field * @return host member String */ public String getHost() { return host; } /** * Set the localId member * @param localId String to set */ public void setLocalId(String localId) { this.localId = localId; } /** set the callId field * @param cid Strimg to set * @throws IllegalArgumentException if cid is null or is not a token or * token@token */ public void setCallID(String cid) throws IllegalArgumentException { if (cid == null) throw new IllegalArgumentException("NULL!"); int index = cid.indexOf('@'); if (index == -1) { localId = cid; host = null; } else { localId = cid.substring(0, index); host = cid.substring(index + 1, cid.length()); if (localId == null || host == null) { throw new IllegalArgumentException("CallID must be token@token or token"); } } } /** * Set the host member * @param host String to set */ public void setHost(String host) { this.host = host; } } java/gov/nist/javax/sip/header/CallInfo.java0100644 0000000 0000000 00000006575 13513104763 020004 0ustar000000000 0000000 /* * 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.javax.sip.header; import gov.nist.javax.sip.address.*; import java.text.ParseException; /** * CallInfo SIPHeader. * * * @author "M. Ranganathan"
    * @version 1.2 $Revision: 1.7 $ $Date: 2009/07/17 18:57:28 $ * @since 1.1 */ public final class CallInfo extends ParametersHeader implements javax.sip.header.CallInfoHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -8179246487696752928L; protected GenericURI info; /** * Default constructor */ public CallInfo() { super(CALL_INFO); } /** * Return canonical representation. * @return String */ public String encodeBody() { return encodeBody(new StringBuffer()).toString(); } protected StringBuffer encodeBody(StringBuffer buffer) { buffer.append(LESS_THAN); info.encode(buffer); buffer.append(GREATER_THAN); if (parameters != null && !parameters.isEmpty()) { buffer.append(SEMICOLON); parameters.encode(buffer); } return buffer; } /** * get the purpose field * @return String */ public String getPurpose() { return this.getParameter("purpose"); } /** * get the URI field * @return URI */ public javax.sip.address.URI getInfo() { return info; } /** * set the purpose field * @param purpose is the purpose field. */ public void setPurpose(String purpose) { if (purpose == null) throw new NullPointerException("null arg"); try { this.setParameter("purpose", purpose); } catch (ParseException ex) { } } /** * set the URI field * @param info is the URI to set. */ public void setInfo(javax.sip.address.URI info) { this.info = (GenericURI) info; } public Object clone() { CallInfo retval = (CallInfo) super.clone(); if (this.info != null) retval.info = (GenericURI) this.info.clone(); return retval; } } java/gov/nist/javax/sip/header/CallInfoList.java0100644 0000000 0000000 00000003765 13513104763 020636 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.header.*; /** * A list of CallInfo headers (there can be multiple in a message). * * @author M. Ranganathan
    * @version 1.2 $Revision: 1.6 $ $Date: 2009/07/17 18:57:28 $ * @since 1.1 * */ public class CallInfoList extends SIPHeaderList { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -4949850334388806423L; public Object clone() { CallInfoList retval = new CallInfoList (); retval.clonehlist(this.hlist); return retval; } /** * Default constructor */ public CallInfoList() { super(CallInfo.class, CallInfoHeader.NAME); } } java/gov/nist/javax/sip/header/Challenge.java0100644 0000000 0000000 00000014541 13513104763 020167 0ustar000000000 0000000 /* * 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.javax.sip.header; import gov.nist.core.*; /** * Challenge part of the Auth header. This is only used by the parser interface * * @author M. Ranganathan
    * @version 1.2 $Revision: 1.7 $ $Date: 2009/07/17 18:57:28 $ * @since 1.1 * */ public class Challenge extends SIPObject { /** * Comment for serialVersionUID */ private static final long serialVersionUID = 5944455875924336L; private static String DOMAIN = ParameterNames.DOMAIN; private static String REALM = ParameterNames.REALM; private static String OPAQUE = ParameterNames.OPAQUE; private static String ALGORITHM = ParameterNames.ALGORITHM; private static String QOP = ParameterNames.QOP; private static String STALE = ParameterNames.STALE; private static String SIGNATURE = ParameterNames.SIGNATURE; private static String RESPONSE = ParameterNames.RESPONSE; private static String SIGNED_BY = ParameterNames.SIGNED_BY; private static String URI = ParameterNames.URI; /** * scheme field */ protected String scheme; /** * authParms list */ protected NameValueList authParams; /** * Default constructor */ public Challenge() { authParams = new NameValueList(); authParams.setSeparator(COMMA); } /** * Encode the challenge in canonical form. * @return String */ public String encode() { return new StringBuffer(scheme) .append(SP) .append(authParams.encode()) .toString(); } /** * get the scheme field * @return String */ public String getScheme() { return scheme; } /** * get AuthParms list. * @return NameValueList */ public NameValueList getAuthParams() { return authParams; } /** * get the domain * @return String */ public String getDomain() { return (String) authParams.getValue(DOMAIN); } /** * get the URI field * @return String */ public String getURI() { return (String) authParams.getValue(URI); } /** * get the Opaque field * @return String */ public String getOpaque() { return (String) authParams.getValue(OPAQUE); } /** * get QOP value * @return String */ public String getQOP() { return (String) authParams.getValue(QOP); } /** * get the Algorithm value. * @return String */ public String getAlgorithm() { return (String) authParams.getValue(ALGORITHM); } /** * get the State value. * @return String */ public String getStale() { return (String) authParams.getValue(STALE); } /** * get the Signature value. * @return String */ public String getSignature() { return (String) authParams.getValue(SIGNATURE); } /** * get the signedBy value. * @return String */ public String getSignedBy() { return (String) authParams.getValue(SIGNED_BY); } /** * get the Response value. * @return String */ public String getResponse() { return (String) authParams.getValue(RESPONSE); } /** * get the realm value. * @return String. */ public String getRealm() { return (String) authParams.getValue(REALM); } /** * get the specified parameter * @param name String to set * @return String to set */ public String getParameter(String name) { return (String) authParams.getValue(name); } /** * boolean function * @param name String to set * @return true if this header has the specified parameter, false otherwise. */ public boolean hasParameter(String name) { return authParams.getNameValue(name) != null; } /** * Boolean function * @return true if this header has some parameters. */ public boolean hasParameters() { return authParams.size() != 0; } /** * delete the specified parameter * @param name String * @return true if the specified parameter has been removed, false * otherwise. */ public boolean removeParameter(String name) { return authParams.delete(name); } /** * remove all parameters */ public void removeParameters() { authParams = new NameValueList(); } /** * set the specified parameter * @param nv NameValue to set */ public void setParameter(NameValue nv) { authParams.set(nv); } /** * Set the scheme member * @param s String to set */ public void setScheme(String s) { scheme = s; } /** * Set the authParams member * @param a NameValueList to set */ public void setAuthParams(NameValueList a) { authParams = a; } public Object clone() { Challenge retval = (Challenge) super.clone(); if (this.authParams != null) retval.authParams = (NameValueList) this.authParams.clone(); return retval; } } java/gov/nist/javax/sip/header/Contact.java0100644 0000000 0000000 00000020403 13513104763 017672 0ustar000000000 0000000 /* * 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 * * . * */ /* * Bug reports contributed by Joao Paulo, Stephen Jones, * John Zeng and Alstair Cole. * */ /******************************************************************************* * Product of NIST/ITL Advanced Networking Technologies Division (ANTD). * *******************************************************************************/ package gov.nist.javax.sip.header; import gov.nist.core.NameValue; import gov.nist.core.NameValueList; import gov.nist.javax.sip.address.AddressImpl; import javax.sip.InvalidArgumentException; import javax.sip.header.ContactHeader; import java.text.ParseException; /** * Contact Item. * * @see gov.nist.javax.sip.header.ContactList * * @author M. Ranganathan
    * @version 1.2 $Revision: 1.13 $ $Date: 2009/10/18 13:46:31 $ * @since 1.1 * * */ public final class Contact extends AddressParametersHeader implements javax.sip.header.ContactHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = 1677294871695706288L; public static final String ACTION = ParameterNames.ACTION; public static final String PROXY = ParameterNames.PROXY; public static final String REDIRECT = ParameterNames.REDIRECT; public static final String EXPIRES = ParameterNames.EXPIRES; public static final String Q = ParameterNames.Q; // This must be private or the toString will go for a loop! private ContactList contactList; /** wildCardFlag field. */ protected boolean wildCardFlag; /** Default constructor. */ public Contact() { super(NAME); } /** Set a parameter. */ public void setParameter(String name, String value) throws ParseException { NameValue nv = parameters.getNameValue(name); if (nv != null) { nv.setValueAsObject(value); } else { nv = new NameValue(name, value); if (name.equalsIgnoreCase("methods")) nv.setQuotedValue(); this.parameters.set(nv); } } /** * Encode body of the header into a cannonical String. * @return string encoding of the header value. */ protected String encodeBody() { return encodeBody(new StringBuffer()).toString(); } protected StringBuffer encodeBody(StringBuffer buffer) { if (wildCardFlag) { buffer.append('*'); } else { // Bug report by Joao Paulo if (address.getAddressType() == AddressImpl.NAME_ADDR) { address.encode(buffer); } else { // Encoding in canonical form must have <> around address. buffer.append('<'); address.encode(buffer); buffer.append('>'); } if (!parameters.isEmpty()) { buffer.append(SEMICOLON); parameters.encode(buffer); } } return buffer; } /** get the Contact list. * @return ContactList */ public ContactList getContactList() { return contactList; } /** get the WildCardFlag field * @return boolean */ public boolean getWildCardFlag() { return wildCardFlag; } /** get the address field. * @return Address */ public javax.sip.address.Address getAddress() { // JAIN-SIP stores the wild card as an address! return address; } /** get the parameters List * @return NameValueList */ public NameValueList getContactParms() { return parameters; } /** get Expires parameter. * @return the Expires parameter. */ public int getExpires() { return getParameterAsInt(EXPIRES); } /** Set the expiry time in seconds. *@param expiryDeltaSeconds exipry time. */ public void setExpires(int expiryDeltaSeconds) { Integer deltaSeconds = Integer.valueOf(expiryDeltaSeconds); this.parameters.set(EXPIRES, deltaSeconds); } /** get the Q-value * @return float */ public float getQValue() { return getParameterAsFloat(Q); } /** set the Contact List * @param cl ContactList to set */ public void setContactList(ContactList cl) { contactList = cl; } /** * Set the wildCardFlag member * @param w boolean to set */ public void setWildCardFlag(boolean w) { this.wildCardFlag = true; this.address = new AddressImpl(); this.address.setWildCardFlag(); } /** * Set the address member * * @param address Address to set */ public void setAddress(javax.sip.address.Address address) { // Canonical form must have <> around the address. if (address == null) throw new NullPointerException("null address"); this.address = (AddressImpl) address; this.wildCardFlag = false; } /** * set the Q-value parameter * @param qValue float to set */ public void setQValue(float qValue) throws InvalidArgumentException { if (qValue != -1 && (qValue < 0 || qValue > 1)) throw new InvalidArgumentException( "JAIN-SIP Exception, Contact, setQValue(), " + "the qValue is not between 0 and 1"); this.parameters.set(Q, Float.valueOf(qValue)); } public Object clone() { Contact retval = (Contact) super.clone(); if (this.contactList != null) retval.contactList = (ContactList) this.contactList.clone(); return retval; } /* (non-Javadoc) * @see javax.sip.header.ContactHeader#setWildCard() */ public void setWildCard() { this.setWildCardFlag(true); } /* (non-Javadoc) * @see javax.sip.header.ContactHeader#isWildCard() */ public boolean isWildCard() { return this.address.isWildcard(); } public boolean equals(Object other) { return (other instanceof ContactHeader) && super.equals(other); } public void removeSipInstanceParam() { if (parameters != null) parameters.delete(ParameterNames.SIP_INSTANCE); } public String getSipInstanceParam() { return (String) parameters.getValue(ParameterNames.SIP_INSTANCE); } public void setSipInstanceParam(String value) { this.parameters.set(ParameterNames.SIP_INSTANCE, value); } /** *remove the pub-gruu value from the parameter list if it exists. */ public void removePubGruuParam() { if (parameters != null) parameters.delete(ParameterNames.PUB_GRUU); } public String getPubGruuParam() { return (String) parameters.getValue(ParameterNames.PUB_GRUU); } public void setPubGruuParam(String value) { this.parameters.set(ParameterNames.PUB_GRUU, value); } /** *remove the pub-gruu value from the parameter list if it exists. */ public void removeTempGruuParam() { if (parameters != null) parameters.delete(ParameterNames.TEMP_GRUU); } public String getTempGruuParam() { return (String) parameters.getValue(ParameterNames.TEMP_GRUU); } public void setTempGruuParam(String value) { this.parameters.set(ParameterNames.TEMP_GRUU, value); } } java/gov/nist/javax/sip/header/ContactList.java0100644 0000000 0000000 00000003740 13513104763 020533 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.header.*; import java.util.ListIterator; /** * List of contact headers.ContactLists are also maintained in a hashtable * for quick lookup. * @author M. Ranganathan
    * @version 1.2 $Revision: 1.7 $ $Date: 2009/07/17 18:57:28 $ * @since 1.1 */ public class ContactList extends SIPHeaderList { private static final long serialVersionUID = 1224806837758986814L; public Object clone() { ContactList retval = new ContactList(); retval.clonehlist(this.hlist); return retval; } /** * Constructor. */ public ContactList() { super(Contact.class, ContactHeader.NAME); } } java/gov/nist/javax/sip/header/ContentDisposition.java0100644 0000000 0000000 00000014412 13513104763 022141 0ustar000000000 0000000 /* * 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.javax.sip.header; import java.text.*; /** * Content Dispositon SIP Header. * * @author M. Ranganathan
    * @version 1.2 $Revision: 1.5 $ $Date: 2009/07/17 18:57:29 $ * @since 1.1 * */ public final class ContentDisposition extends ParametersHeader implements javax.sip.header.ContentDispositionHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = 835596496276127003L; /** * DispositionType field. */ protected String dispositionType; /** * Default constructor. */ public ContentDisposition() { super(NAME); } /** * Encode value of header into canonical string. * @return encoded value of header. * */ public String encodeBody() { StringBuffer encoding = new StringBuffer(dispositionType); if (!this.parameters.isEmpty()) { encoding.append(SEMICOLON).append(parameters.encode()); } return encoding.toString(); } /** * Set the disposition type. * @param dispositionType type. */ public void setDispositionType(String dispositionType) throws ParseException { if (dispositionType == null) throw new NullPointerException( "JAIN-SIP Exception" + ", ContentDisposition, setDispositionType(), the dispositionType parameter is null"); this.dispositionType = dispositionType; } /** * Get the disposition type. * @return Disposition Type */ public String getDispositionType() { return this.dispositionType; } /** * Get the dispositionType field. * @return String */ public String getHandling() { return this.getParameter("handling"); } /** set the dispositionType field. * @param handling String to set. */ public void setHandling(String handling) throws ParseException { if (handling == null) throw new NullPointerException( "JAIN-SIP Exception" + ", ContentDisposition, setHandling(), the handling parameter is null"); this.setParameter("handling", handling); } /** * Gets the interpretation of the message body or message body part of * this ContentDispositionHeader. * * @return interpretation of the message body or message body part */ public String getContentDisposition() { return this.encodeBody(); } } /* * $Log: ContentDisposition.java,v $ * 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: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:26 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:34 mranga * * Import * * * Revision 1.2 2004/01/22 13:26:29 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/header/ContentEncoding.java0100644 0000000 0000000 00000011226 13513104763 021363 0ustar000000000 0000000 /* * 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.javax.sip.header; import java.text.ParseException; /** * Content encoding part of a content encoding header list. * @see ContentEncodingList *
     * From HTTP RFC 2616
     *14.11 Content-Encoding
     *
     *   The Content-Encoding entity-header field is used as a modifier to the
     *   media-type. When present, its value indicates what additional content
     *   codings have been applied to the entity-body, and thus what decoding
     *   mechanisms must be applied in order to obtain the media-type
     *   referenced by the Content-Type header field. Content-Encoding is
     *   primarily used to allow a document to be compressed without losing
     *   the identity of its underlying media type.
     *
     *       Content-Encoding  = "Content-Encoding" ":" 1#content-coding
     *
     *   Content codings are defined in section 3.5. An example of its use is
     *
     *       Content-Encoding: gzip
     *
     *   The content-coding is a characteristic of the entity identified by
     *   the Request-URI. Typically, the entity-body is stored with this
     *   encoding and is only decoded before rendering or analogous usage.
     *   However, a non-transparent proxy MAY modify the content-coding if the
     *   new coding is known to be acceptable to the recipient, unless the
     *   "no-transform" cache-control directive is present in the message.
     *
     *   If the content-coding of an entity is not "identity", then the
     *   response MUST include a Content-Encoding entity-header (section
     *   14.11) that lists the non-identity content-coding(s) used.
     *
     *   If the content-coding of an entity in a request message is not
     *   acceptable to the origin server, the server SHOULD respond with a
     *   status code of 415 (Unsupported Media Type).
     *
     *   If multiple encodings have been applied to an entity, the content
     *   codings MUST be listed in the order in which they were applied.
     *   Additional information about the encoding parameters MAY be provided
     *   by other entity-header fields not defined by this specification.
     *
    * * @author M. Ranganathan
    * @author Olivier Deruelle
    * @version 1.2 $Revision: 1.5 $ $Date: 2009/07/17 18:57:29 $ * @since 1.1 */ public class ContentEncoding extends SIPHeader implements javax.sip.header.ContentEncodingHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = 2034230276579558857L; /** * ContentEncoding field. */ protected String contentEncoding; /** * Default constructor. */ public ContentEncoding() { super(CONTENT_ENCODING); } /** * Constructor. * @param enc String to set. */ public ContentEncoding(String enc) { super(CONTENT_ENCODING); contentEncoding = enc; } /** * Canonical encoding of body of the header. * @return encoded body of the header. */ public String encodeBody() { return contentEncoding; } /** * Get the ContentEncoding field. * @return String */ public String getEncoding() { return contentEncoding; } /** * Set the ConentEncoding field. * @param encoding String to set */ public void setEncoding(String encoding) throws ParseException { if (encoding == null) throw new NullPointerException( "JAIN-SIP Exception, " + " encoding is null"); contentEncoding = encoding; } } java/gov/nist/javax/sip/header/ContentEncodingList.java0100644 0000000 0000000 00000003701 13513104763 022216 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.header.*; /** * Content Encoding SIP header List. Keeps a list of ContentEncoding headers. * *@author M. Rangananthan *@version 1.2 *@since 1.1 */ public final class ContentEncodingList extends SIPHeaderList { private static final long serialVersionUID = 7365216146576273970L; public Object clone() { ContentEncodingList retval = new ContentEncodingList(); retval.clonehlist(this.hlist); return retval; } /** Default constructor. */ public ContentEncodingList () { super( ContentEncoding.class, ContentEncodingHeader.NAME); } } java/gov/nist/javax/sip/header/ContentLanguage.java0100644 0000000 0000000 00000013051 13513104763 021356 0ustar000000000 0000000 /* * 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.javax.sip.header; import java.util.Locale; /** * ContentLanguage header *
    *Fielding, et al.            Standards Track                   [Page 118]
    *RFC 2616                        HTTP/1.1                       June 1999
    *
    *  14.12 Content-Language
    *
    *   The Content-Language entity-header field describes the natural
    *   language(s) of the intended audience for the enclosed entity. Note
    *   that this might not be equivalent to all the languages used within
    *   the entity-body.
    *
    *       Content-Language  = "Content-Language" ":" 1#language-tag
    *
    *   Language tags are defined in section 3.10. The primary purpose of
    *   Content-Language is to allow a user to identify and differentiate
    *   entities according to the user's own preferred language. Thus, if the
    *   body content is intended only for a Danish-literate audience, the
    *   appropriate field is
    *
    *       Content-Language: da
    *
    *   If no Content-Language is specified, the default is that the content
    *   is intended for all language audiences. This might mean that the
    *   sender does not consider it to be specific to any natural language,
    *   or that the sender does not know for which language it is intended.
    *
    *   Multiple languages MAY be listed for content that is intended for
    *   multiple audiences. For example, a rendition of the "Treaty of
    *   Waitangi," presented simultaneously in the original Maori and English
    *   versions, would call for
    *
    *       Content-Language: mi, en
    *
    *   However, just because multiple languages are present within an entity
    *   does not mean that it is intended for multiple linguistic audiences.
    *   An example would be a beginner's language primer, such as "A First
    *   Lesson in Latin," which is clearly intended to be used by an
    *   English-literate audience. In this case, the Content-Language would
    *   properly only include "en".
    *
    *   Content-Language MAY be applied to any media type -- it is not
    *   limited to textual documents.
    *
    * @author M. Ranganathan * @version 1.2 $Revision: 1.8 $ $Date: 2009/07/17 18:57:29 $ * @since 1.1 */ public class ContentLanguage extends SIPHeader implements javax.sip.header.ContentLanguageHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -5195728427134181070L; /** languageTag field. */ protected Locale locale; public ContentLanguage() { super(CONTENT_LANGUAGE); } /** * Default constructor. * @param languageTag String to set */ public ContentLanguage(String languageTag) { super(CONTENT_LANGUAGE); this.setLanguageTag( languageTag ); } /** * Canonical encoding of the value of the header. * @return encoded body of header. */ public String encodeBody() { return this.getLanguageTag(); } /** get the languageTag field. * @return String */ public String getLanguageTag() { // JvB: Need to take sub-tags into account if ( "".equals(locale.getCountry())) { return locale.getLanguage(); } else { return locale.getLanguage() + '-' + locale.getCountry(); } } /** set the languageTag field * @param languageTag -- language tag to set. */ public void setLanguageTag(String languageTag) { final int slash = languageTag.indexOf('-'); if (slash>=0) { this.locale = new Locale(languageTag.substring(0,slash), languageTag.substring(slash+1) ); } else { this.locale = new Locale(languageTag); } } /** * Gets the language value of the ContentLanguageHeader. * * * * @return the Locale value of this ContentLanguageHeader * */ public Locale getContentLanguage() { return locale; } /** * Sets the language parameter of this ContentLanguageHeader. * * @param language - the new Locale value of the language of * * ContentLanguageHeader * */ public void setContentLanguage(Locale language) { this.locale = language; } public Object clone() { ContentLanguage retval = (ContentLanguage) super.clone(); if (this.locale != null) retval.locale = (Locale) this.locale.clone(); return retval; } } java/gov/nist/javax/sip/header/ContentLanguageList.java0100644 0000000 0000000 00000003625 13513104763 022220 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.header.*; /** * ContentLanguage list of headers. * *@since 1.1 *@version 1.2 *@author M. Ranganathan */ public final class ContentLanguageList extends SIPHeaderList { private static final long serialVersionUID = -5302265987802886465L; public Object clone() { ContentLanguageList retval = new ContentLanguageList(); retval.clonehlist(this.hlist); return retval; } /** Default constructor */ public ContentLanguageList () { super(ContentLanguage.class, ContentLanguageHeader.NAME); } } java/gov/nist/javax/sip/header/ContentLength.java0100644 0000000 0000000 00000011634 13513104763 021061 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.*; import javax.sip.header.ContentLengthHeader; /** * ContentLength SIPHeader (of which there can be only one in a SIPMessage). *
    *Fielding, et al.            Standards Track                   [Page 119]
    *RFC 2616                        HTTP/1.1                       June 1999
    *
    *
    *      14.13 Content-Length
    *
    *   The Content-Length entity-header field indicates the size of the
    *   entity-body, in decimal number of OCTETs, sent to the recipient or,
    *   in the case of the HEAD method, the size of the entity-body that
    *   would have been sent had the request been a GET.
    *
    *       Content-Length    = "Content-Length" ":" 1*DIGIT
    *
    *   An example is
    *
    *       Content-Length: 3495
    *
    *   Applications SHOULD use this field to indicate the transfer-length of
    *   the message-body, unless this is prohibited by the rules in section
    *   4.4.
    *
    *   Any Content-Length greater than or equal to zero is a valid value.
    *   Section 4.4 describes how to determine the length of a message-body
    *   if a Content-Length is not given.
    *
    *   Note that the meaning of this field is significantly different from
    *   the corresponding definition in MIME, where it is an optional field
    *   used within the "message/external-body" content-type. In HTTP, it
    *   SHOULD be sent whenever the message's length can be determined prior
    *   to being transferred, unless this is prohibited by the rules in
    *   section 4.4.
    * 
    * *@author M. Ranganathan
    *@author Olivier Deruelle
    *@version 1.2 $Revision: 1.7 $ $Date: 2009/10/18 13:46:34 $ *@since 1.1 */ public class ContentLength extends SIPHeader implements javax.sip.header.ContentLengthHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = 1187190542411037027L; /** * contentLength field. */ protected Integer contentLength; /** * Default constructor. */ public ContentLength() { super(NAME); } /** * Constructor given a length. */ public ContentLength(int length) { super(NAME); this.contentLength = Integer.valueOf(length); } /** * get the ContentLength field. * @return int */ public int getContentLength() { return contentLength.intValue(); } /** * Set the contentLength member * @param contentLength int to set */ public void setContentLength(int contentLength) throws InvalidArgumentException { if (contentLength < 0) throw new InvalidArgumentException( "JAIN-SIP Exception" + ", ContentLength, setContentLength(), the contentLength parameter is <0"); this.contentLength = Integer.valueOf(contentLength); } /** * Encode into a canonical string. * @return String */ public String encodeBody() { return encodeBody(new StringBuffer()).toString(); } protected StringBuffer encodeBody(StringBuffer buffer) { if (contentLength == null) buffer.append("0"); else buffer.append(contentLength.toString()); return buffer; } /** * Pattern matcher ignores content length. */ public boolean match(Object other) { if (other instanceof ContentLength) return true; else return false; } public boolean equals(Object other) { if (other instanceof ContentLengthHeader) { final ContentLengthHeader o = (ContentLengthHeader) other; return this.getContentLength() == o.getContentLength(); } return false; } } java/gov/nist/javax/sip/header/ContentType.java0100644 0000000 0000000 00000014566 13513104763 020570 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.header.ContentTypeHeader; import java.text.ParseException; /** * ContentType SIP Header *
    *14.17 Content-Type
    *
    *   The Content-Type entity-header field indicates the media type of the
    *   entity-body sent to the recipient or, in the case of the HEAD method,
    *   the media type that would have been sent had the request been a GET.
    *
    *   Content-Type   = "Content-Type" ":" media-type
    *
    *   Media types are defined in section 3.7. An example of the field is
    *
    *       Content-Type: text/html; charset=ISO-8859-4
    *
    *   Further discussion of methods for identifying the media type of an
    *   entity is provided in section 7.2.1.
    *
    * From  HTTP RFC 2616
    * 
    * * *@version 1.2 * *@author M. Ranganathan
    *@author Olivier Deruelle
    *@version 1.2 $Revision: 1.7 $ $Date: 2009/07/17 18:57:29 $ *@since 1.1 * */ public class ContentType extends ParametersHeader implements javax.sip.header.ContentTypeHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = 8475682204373446610L; /** mediaRange field. */ protected MediaRange mediaRange; /** Default constructor. */ public ContentType() { super(CONTENT_TYPE); } /** Constructor given a content type and subtype. *@param contentType is the content type. *@param contentSubtype is the content subtype */ public ContentType(String contentType, String contentSubtype) { this(); this.setContentType(contentType, contentSubtype); } /** compare two MediaRange headers. * @param media String to set * @return int. */ public int compareMediaRange(String media) { return ( mediaRange.type + "/" + mediaRange.subtype).compareToIgnoreCase( media); } /** * Encode into a canonical string. * @return String. */ public String encodeBody() { return encodeBody(new StringBuffer()).toString(); } protected StringBuffer encodeBody(StringBuffer buffer) { mediaRange.encode(buffer); if (hasParameters()) { buffer.append(SEMICOLON); parameters.encode(buffer); } return buffer; } /** get the mediaRange field. * @return MediaRange. */ public MediaRange getMediaRange() { return mediaRange; } /** get the Media Type. * @return String. */ public String getMediaType() { return mediaRange.type; } /** get the MediaSubType field. * @return String. */ public String getMediaSubType() { return mediaRange.subtype; } /** Get the content subtype. *@return the content subtype string (or null if not set). */ public String getContentSubType() { return mediaRange == null ? null : mediaRange.getSubtype(); } /** Get the content subtype. *@return the content tyep string (or null if not set). */ public String getContentType() { return mediaRange == null ? null : mediaRange.getType(); } /** Get the charset parameter. */ public String getCharset() { return this.getParameter("charset"); } /** * Set the mediaRange member * @param m mediaRange field. */ public void setMediaRange(MediaRange m) { mediaRange = m; } /** * set the content type and subtype. *@param contentType Content type string. *@param contentSubType content subtype string */ public void setContentType(String contentType, String contentSubType) { if (mediaRange == null) mediaRange = new MediaRange(); mediaRange.setType(contentType); mediaRange.setSubtype(contentSubType); } /** * set the content type. *@param contentType Content type string. */ public void setContentType(String contentType) throws ParseException { if (contentType == null) throw new NullPointerException("null arg"); if (mediaRange == null) mediaRange = new MediaRange(); mediaRange.setType(contentType); } /** Set the content subtype. * @param contentType String to set */ public void setContentSubType(String contentType) throws ParseException { if (contentType == null) throw new NullPointerException("null arg"); if (mediaRange == null) mediaRange = new MediaRange(); mediaRange.setSubtype(contentType); } public Object clone() { ContentType retval = (ContentType) super.clone(); if (this.mediaRange != null) retval.mediaRange = (MediaRange) this.mediaRange.clone(); return retval; } public boolean equals(Object other) { if (other instanceof ContentTypeHeader) { final ContentTypeHeader o = (ContentTypeHeader) other; return this.getContentType().equalsIgnoreCase( o.getContentType() ) && this.getContentSubType().equalsIgnoreCase( o.getContentSubType() ) && equalParameters( o ); } return false; } } java/gov/nist/javax/sip/header/Credentials.java0100644 0000000 0000000 00000010545 13513104763 020542 0ustar000000000 0000000 /* * 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.javax.sip.header; import gov.nist.core.*; /** * Credentials that are used in authentication and authorization headers. * @author M. Ranganathan * @version 1.2 $Revision: 1.7 $ $Date: 2009/07/17 18:57:30 $ * @since 1.1 */ public class Credentials extends SIPObject { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -6335592791505451524L; private static String DOMAIN = ParameterNames.DOMAIN; private static String REALM = ParameterNames.REALM; private static String OPAQUE = ParameterNames.OPAQUE; private static String RESPONSE = ParameterNames.RESPONSE; private static String URI = ParameterNames.URI; private static String NONCE = ParameterNames.NONCE; private static String CNONCE = ParameterNames.CNONCE; private static String USERNAME = ParameterNames.USERNAME; protected String scheme; /** * parameters list. */ protected NameValueList parameters; /** * Default constructor */ public Credentials() { parameters = new NameValueList(); parameters.setSeparator(COMMA); } /** * get the parameters list. * @return NameValueList */ public NameValueList getCredentials() { return parameters; } /** * get the scheme field. * @return String. */ public String getScheme() { return scheme; } /** * Set the scheme member * @param s String to set */ public void setScheme(String s) { scheme = s; } /** * Set the parameters member * @param c NameValueList to set. */ public void setCredentials(NameValueList c) { parameters = c; } public String encode() { String retval = scheme; if (!parameters.isEmpty()) { retval += SP + parameters.encode(); } return retval; } /*public void setCredential(NameValue nameValue) { if (nameValue.getName().compareToIgnoreCase(URI) == 0) nameValue.setQuotedValue(); else if (nameValue.getName().compareToIgnoreCase(NONCE) == 0) nameValue.setQuotedValue(); else if (nameValue.getName().compareToIgnoreCase(REALM) == 0) nameValue.setQuotedValue(); else if (nameValue.getName().compareToIgnoreCase(CNONCE) == 0) nameValue.setQuotedValue(); else if (nameValue.getName().compareToIgnoreCase(RESPONSE) == 0) nameValue.setQuotedValue(); else if (nameValue.getName().compareToIgnoreCase(OPAQUE) == 0) nameValue.setQuotedValue(); else if (nameValue.getName().compareToIgnoreCase(USERNAME) == 0) nameValue.setQuotedValue(); else if (nameValue.getName().compareToIgnoreCase(DOMAIN) == 0) nameValue.setQuotedValue(); parameters.set(nameValue); }*/ public Object clone() { Credentials retval = (Credentials) super.clone(); if (this.parameters != null) retval.parameters = (NameValueList) this.parameters.clone(); return retval; } } java/gov/nist/javax/sip/header/ErrorInfo.java0100644 0000000 0000000 00000010373 13513104763 020211 0ustar000000000 0000000 /* * 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.javax.sip.header; import gov.nist.javax.sip.address.*; import javax.sip.header.*; import javax.sip.address.*; import java.text.ParseException; /** * ErrorInfo SIP Header. * * @version 1.2 $Revision: 1.6 $ $Date: 2009/07/17 18:57:30 $ * @since 1.1 * * @author M. Ranganathan
    * @author Olivier Deruelle
    * */ public final class ErrorInfo extends ParametersHeader implements ErrorInfoHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -6347702901964436362L; protected GenericURI errorInfo; /** * Default constructor. */ public ErrorInfo() { super(NAME); } /** * Constructor given the error info * @param errorInfo -- the error information to set. */ public ErrorInfo(GenericURI errorInfo) { this(); this.errorInfo = errorInfo; } /** * Encode into canonical form. * @return String */ public String encodeBody() { StringBuffer retval = new StringBuffer(LESS_THAN).append(errorInfo.toString()).append( GREATER_THAN); if (!parameters.isEmpty()) { retval.append(SEMICOLON).append(parameters.encode()); } return retval.toString(); } /** * Sets the ErrorInfo of the ErrorInfoHeader to the errorInfo * parameter value. * * @param errorInfo the new ErrorInfo of this ErrorInfoHeader. */ public void setErrorInfo(javax.sip.address.URI errorInfo) { this.errorInfo = (GenericURI) errorInfo; } /** * Returns the ErrorInfo value of this ErrorInfoHeader. This message * may return null if a String message identifies the ErrorInfo. * * @return the URI representing the ErrorInfo. */ public URI getErrorInfo() { return errorInfo; } /** * Sets the Error information message to the new message value * supplied to this method. * * @param message - the new string value that represents the error message. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the error message. */ public void setErrorMessage(String message) throws ParseException { if (message == null) throw new NullPointerException( "JAIN-SIP Exception " + ", ErrorInfoHeader, setErrorMessage(), the message parameter is null"); setParameter("message", message); } /** * Get the Error information message of this ErrorInfoHeader. * * @return the stringified version of the ErrorInfo header. */ public String getErrorMessage() { return getParameter("message"); } public Object clone() { ErrorInfo retval = (ErrorInfo) super.clone(); if (this.errorInfo != null) retval.errorInfo = (GenericURI) this.errorInfo.clone(); return retval; } } java/gov/nist/javax/sip/header/ErrorInfoList.java0100644 0000000 0000000 00000004334 13513104763 021045 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.header.*; /** * Error Info sip header. * *@version 1.2 $Revision: 1.6 $ $Date: 2009/07/17 18:57:30 $ * *@author M. Ranganathan
    *@since 1.1 *@see ErrorInfoList *
    *
    * 6.24 Error-Info
    *
    *   The Error-Info response header provides a pointer to additional
    *   information about the error status response. This header field is
    *   only contained in 3xx, 4xx, 5xx and 6xx responses.
    *
    *
    *
    *       Error-Info  =  "Error-Info" ":" # ( "<" URI ">" *( ";" generic-param ))
    *
    * */ public class ErrorInfoList extends SIPHeaderList{ /** * */ private static final long serialVersionUID = 1L; public Object clone() { ErrorInfoList retval = new ErrorInfoList(); retval.clonehlist(this.hlist); return retval; } /** * Default constructor. */ public ErrorInfoList() { super(ErrorInfo.class, ErrorInfoHeader.NAME); } } java/gov/nist/javax/sip/header/Event.java0100644 0000000 0000000 00000011360 13513104763 017362 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.header.*; import java.text.ParseException; /** * Event SIP Header. * *@version 1.2 $Revision: 1.7 $ $Date: 2007/06/28 15:08:42 $ *@since 1.1 * *@author M. Ranganathan
    *@author Olivier Deruelle
    * * */ public class Event extends ParametersHeader implements EventHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -6458387810431874841L; protected String eventType; /** * Creates a new instance of Event */ public Event() { super(EVENT); } /** * Sets the eventType to the newly supplied eventType string. * * @param eventType - the new string defining the eventType supported * in this EventHeader * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the eventType value. */ public void setEventType(String eventType) throws ParseException { if (eventType == null) throw new NullPointerException(" the eventType is null"); this.eventType = eventType; } /** * Gets the eventType of the EventHeader. * * @return the string object identifing the eventType of EventHeader. */ public String getEventType() { return eventType; } /** * Sets the id to the newly supplied eventId string. * * @param eventId - the new string defining the eventId of this EventHeader * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the eventId value. */ public void setEventId(String eventId) throws ParseException { if (eventId == null) throw new NullPointerException(" the eventId parameter is null"); setParameter(ParameterNames.ID, eventId); } /** * Gets the id of the EventHeader. This method may return null if the * "eventId" is not set. * @return the string object identifing the eventId of EventHeader. */ public String getEventId() { return getParameter(ParameterNames.ID); } /** * Encode in canonical form. * @return String */ public String encodeBody() { return encodeBody(new StringBuffer()).toString(); } protected StringBuffer encodeBody(StringBuffer buffer) { if (eventType != null) buffer.append(eventType); if (!parameters.isEmpty()) { buffer.append(SEMICOLON); this.parameters.encode(buffer); } return buffer; } /** * Return true if the given event header matches the supplied one. * * @param matchTarget -- event header to match against. */ public boolean match(Event matchTarget) { if (matchTarget.eventType == null && this.eventType != null) return false; else if (matchTarget.eventType != null && this.eventType == null) return false; else if (this.eventType == null && matchTarget.eventType == null) return false; else if (getEventId() == null && matchTarget.getEventId() != null) return false; else if (getEventId() != null && matchTarget.getEventId() == null) return false; return matchTarget.eventType.equalsIgnoreCase(this.eventType) && ((this.getEventId() == matchTarget.getEventId()) || this.getEventId().equalsIgnoreCase(matchTarget.getEventId())); } } java/gov/nist/javax/sip/header/Expires.java0100644 0000000 0000000 00000005646 13513104763 017732 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.*; /** * Expires SIP Header. * * @version 1.2 $Revision: 1.6 $ $Date: 2009/07/17 18:57:30 $ * @since 1.1 * * @author M. Ranganathan
    * * */ public class Expires extends SIPHeader implements javax.sip.header.ExpiresHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = 3134344915465784267L; /** expires field */ protected int expires; /** default constructor */ public Expires() { super(NAME); } /** * Return canonical form. * @return String */ public String encodeBody() { return encodeBody(new StringBuffer()).toString(); } protected StringBuffer encodeBody(StringBuffer buffer) { return buffer.append(expires); } /** * Gets the expires value of the ExpiresHeader. This expires value is * * relative time. * * * * @return the expires value of the ExpiresHeader. * * */ public int getExpires() { return expires; } /** * Sets the relative expires value of the ExpiresHeader. * The expires value MUST be greater than zero and MUST be * less than 2**31. * * @param expires - the new expires value of this ExpiresHeader * * @throws InvalidArgumentException if supplied value is less than zero. * * */ public void setExpires(int expires) throws InvalidArgumentException { if (expires < 0) throw new InvalidArgumentException("bad argument " + expires); this.expires = expires; } } java/gov/nist/javax/sip/header/ExtensionHeaderImpl.java0100644 0000000 0000000 00000007112 13513104763 022210 0ustar000000000 0000000 /* * 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.javax.sip.header; /** * A generic extension header for the stack. * The input text of the header gets recorded here. * * @version 1.2 $Revision: 1.5 $ $Date: 2009/07/17 18:57:30 $ * @since 1.1 * * @author M. Ranganathan
    * * */ public class ExtensionHeaderImpl extends SIPHeader implements javax.sip.header.ExtensionHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -8693922839612081849L; protected String value; /** * This was added to allow for automatic cloning of headers. */ public ExtensionHeaderImpl() { } public ExtensionHeaderImpl(String headerName) { super(headerName); } /** * Set the name of the header. * @param headerName is the name of the header to set. */ public void setName(String headerName) { this.headerName = headerName; } /** * Set the value of the header. */ public void setValue(String value) { this.value = value; } /** * Get the value of the extension header. * @return the value of the extension header. */ public String getHeaderValue() { if (this.value != null) { return this.value; } else { String encodedHdr = null; try { // Bug fix submitted by Lamine Brahimi encodedHdr = this.encode(); } catch (Exception ex) { return null; } StringBuffer buffer = new StringBuffer(encodedHdr); while (buffer.length() > 0 && buffer.charAt(0) != ':') { buffer.deleteCharAt(0); } buffer.deleteCharAt(0); this.value = buffer.toString().trim(); return this.value; } } /** * Return the canonical encoding of this header. */ public String encode() { return new StringBuffer(this.headerName) .append(COLON) .append(SP) .append(this.value) .append(NEWLINE) .toString(); } /** * Return just the body of this header encoded (leaving out the * name and the CRLF at the end). */ public String encodeBody() { return this.getHeaderValue(); } } java/gov/nist/javax/sip/header/ExtensionHeaderList.java0100644 0000000 0000000 00000004565 13513104763 022233 0ustar000000000 0000000 /* * 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.javax.sip.header; import java.util.ListIterator; import javax.sip.header.ExtensionHeader; import javax.sip.header.Header; /** * A generic extension header list. * @version 1.2 $Revision: 1.8 $ $Date: 2009/07/17 18:57:30 $ * @since 1.1 */ public class ExtensionHeaderList extends SIPHeaderList { private static final long serialVersionUID = 4681326807149890197L; public Object clone() { ExtensionHeaderList retval = new ExtensionHeaderList(headerName); retval.clonehlist(this.hlist); return retval; } public ExtensionHeaderList(String hName) { super( ExtensionHeaderImpl.class, hName); } public ExtensionHeaderList() { super(ExtensionHeaderImpl.class,null); } public String encode() { StringBuffer retval = new StringBuffer(); ListIterator it = this.listIterator(); while(it.hasNext()) { ExtensionHeaderImpl eh = (ExtensionHeaderImpl) it.next(); retval.append(eh.encode()); } return retval.toString(); } } java/gov/nist/javax/sip/header/From.java0100644 0000000 0000000 00000010735 13513104763 017211 0ustar000000000 0000000 /* * 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.javax.sip.header; import gov.nist.core.HostPort; import gov.nist.javax.sip.address.AddressImpl; import gov.nist.javax.sip.parser.Parser; import javax.sip.header.FromHeader; import java.text.ParseException; /** * From SIP Header. * * @version 1.2 $Revision: 1.9 $ $Date: 2009/07/17 18:57:31 $ * @since 1.1 * * @author M. Ranganathan
    * * */ public final class From extends AddressParametersHeader implements javax.sip.header.FromHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -6312727234330643892L; /** Default constructor */ public From() { super(NAME); } /** Generate a FROM header from a TO header */ public From(To to) { super(NAME); address = to.address; parameters = to.parameters; } /** * Encode the header content into a String. * * @return String */ protected String encodeBody() { return encodeBody(new StringBuffer()).toString(); } protected StringBuffer encodeBody(StringBuffer buffer) { if (address.getAddressType() == AddressImpl.ADDRESS_SPEC) { buffer.append(LESS_THAN); } address.encode(buffer); if (address.getAddressType() == AddressImpl.ADDRESS_SPEC) { buffer.append(GREATER_THAN); } if (!parameters.isEmpty()) { buffer.append(SEMICOLON); parameters.encode(buffer); } return buffer; } /** * Conveniance accessor function to get the hostPort field from the address. * Warning -- this assumes that the embedded URI is a SipURL. * * @return hostport field */ public HostPort getHostPort() { return address.getHostPort(); } /** * Get the display name from the address. * @return Display name */ public String getDisplayName() { return address.getDisplayName(); } /** * Get the tag parameter from the address parm list. * @return tag field */ public String getTag() { if (parameters == null) return null; return getParameter(ParameterNames.TAG); } /** Boolean function * @return true if the Tag exist */ public boolean hasTag() { return hasParameter(ParameterNames.TAG); } /** remove Tag member */ public void removeTag() { parameters.delete(ParameterNames.TAG); } /** * Set the address member * @param address Address to set */ public void setAddress(javax.sip.address.Address address) { this.address = (AddressImpl) address; } /** * Set the tag member * @param t tag to set. From tags are mandatory. */ public void setTag(String t) throws ParseException { // JvB: check that it is a valid token Parser.checkToken(t); this.setParameter(ParameterNames.TAG, t); } /** Get the user@host port string. */ public String getUserAtHostPort() { return address.getUserAtHostPort(); } public boolean equals(Object other) { return (other instanceof FromHeader) && super.equals(other); } } java/gov/nist/javax/sip/header/HeaderExt.java0100644 0000000 0000000 00000002331 13513104763 020150 0ustar000000000 0000000 /* * JBoss, Home of Professional Open Source * This code has been contributed to the public domain by the author. * * 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.Header; /** * Extensions to the Header interface supported by the implementation and * will be included in the next spec release. * * @author jean.deruelle@gmail.com * */ public interface HeaderExt extends Header { /** * Gets the header value (i.e. what follows the name:) as a string * @return the header value (i.e. what follows the name:) * @since 2.0 */ public String getValue(); } java/gov/nist/javax/sip/header/HeaderFactoryExt.java0100644 0000000 0000000 00000020637 13513104763 021511 0ustar000000000 0000000 package gov.nist.javax.sip.header; import java.text.ParseException; import gov.nist.javax.sip.header.extensions.JoinHeader; 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 javax.sip.InvalidArgumentException; import javax.sip.address.Address; import javax.sip.header.Header; import javax.sip.header.HeaderFactory; /** * Header factory extensions. These will be included in the next release of * JAIN-SIP. * * @since 2.0 * */ public interface HeaderFactoryExt extends HeaderFactory { /** * Create a RequestLine from a String * @throws ParseException */ public SipRequestLine createRequestLine(String requestLine) throws ParseException; /** * Create a StatusLine from a String. */ public SipStatusLine createStatusLine(String statusLine) throws ParseException; /** * Create a ReferredBy Header. * * @param address -- * address for the header. * */ public ReferredByHeader createReferredByHeader(Address address); /** * * Create a Replaces header with a call Id, to and from tag. * * @param callId - * the call id to use. * @param toTag - * the to tag to use. * @param fromTag - * the fromTag to use. * */ public ReplacesHeader createReplacesHeader(String callId, String toTag, String fromTag) throws ParseException; /** * creates a P-Access-Network-Info header. * * @return newly created P-Access-Network-Info header */ public PAccessNetworkInfoHeader createPAccessNetworkInfoHeader(); /** * P-Asserted-Identity header * * @param address - * Address * @return newly created P-Asserted-Identity header * @throws ParseException * @throws NullPointerException */ public PAssertedIdentityHeader createPAssertedIdentityHeader(Address address) throws NullPointerException, ParseException; /** * Creates a new P-Associated-URI header based on the supplied address * * @param assocURI - * Address * @return newly created P-Associated-URI header * @throws NullPointerException * if the supplied address is null * @throws ParseException */ public PAssociatedURIHeader createPAssociatedURIHeader(Address assocURI); /** * P-Called-Party-ID header * * @param address - * Address * @return newly created P-Called-Party-ID header * @throws NullPointerException * @throws ParseException */ public PCalledPartyIDHeader createPCalledPartyIDHeader(Address address); /** * P-Charging-Function-Addresses header * * @return newly created P-Charging-Function-Addresses header */ public PChargingFunctionAddressesHeader createPChargingFunctionAddressesHeader(); /** * P-Charging-Vector header * * @param icid - * icid string * @return newly created P-Charging-Vector header * @throws NullPointerException * @throws ParseException */ public PChargingVectorHeader createChargingVectorHeader(String icid) throws ParseException; /** * P-Media-Authorization header * @param token - token string * @return newly created P-Media-Authorizarion header * @throws InvalidArgumentException * @throws ParseException */ public PMediaAuthorizationHeader createPMediaAuthorizationHeader(String token) throws InvalidArgumentException, ParseException; /** * P-Preferred-Identity header * @param address - Address * @return newly created P-Preferred-Identity header * @throws NullPointerException */ public PPreferredIdentityHeader createPPreferredIdentityHeader(Address address); /** * P-Visited-Network-ID header * @return newly created P-Visited-Network-ID header */ public PVisitedNetworkIDHeader createPVisitedNetworkIDHeader(); /** * PATH header * @param address - Address * @return newly created Path header * @throws NullPointerException * @throws ParseException */ public PathHeader createPathHeader(Address address); /** * Privacy header * @param privacyType - privacy type string * @return newly created Privacy header * @throws NullPointerException */ public PrivacyHeader createPrivacyHeader(String privacyType); /** * Service-Route header * @param address - Address * @return newly created Service-Route header * @throws NullPointerException */ public ServiceRouteHeader createServiceRouteHeader(Address address); /** * Security-Server header * @return newly created Security-Server header */ public SecurityServerHeader createSecurityServerHeader(); /** * Security-Client header * @return newly created Security-Client header */ public SecurityClientHeader createSecurityClientHeader(); /** * Security-Verify header * @return newly created Security-Verify header */ public SecurityVerifyHeader createSecurityVerifyHeader(); /** * Creates a new SessionExpiresHeader based on the newly supplied expires value. * * @param expires - the new integer value of the expires. * @throws InvalidArgumentException if supplied expires is less * than zero. * @return the newly created SessionExpiresHeader object. * */ public SessionExpiresHeader createSessionExpiresHeader(int expires) throws InvalidArgumentException ; /** * * Create a Join header with a call Id, to and from tag. * * @param callId - * the call id to use. * @param toTag - * the to tag to use. * @param fromTag - * the fromTag to use. * */ public JoinHeader createJoinHeader(String callId, String toTag, String fromTag) throws ParseException; /** * * @return the newly created P-User-Database header * @param the database name, that may be an IP:port or a domain name. */ public PUserDatabaseHeader createPUserDatabaseHeader(String databaseName); /** * * @param address * @return The newly created P-Profile-Key header */ public PProfileKeyHeader createPProfileKeyHeader(Address address); /** * @param address of the served user. * @return The newly created P-Served-User Header. */ public PServedUserHeader createPServedUserHeader(Address address); /** * * @return The newly created P-Preferred-Service Header. */ public PPreferredServiceHeader createPPreferredServiceHeader(); /** * * @return The newly created P-Asserted-Service Header. */ public PAssertedServiceHeader createPAssertedServiceHeader(); /** * Create a header from a string. The string is assumed to be in the * name:value format. The trailing CRLF (if any ) will be stripped * before parsing this. The header should be a singleton. */ public Header createHeader(String header) throws ParseException; } java/gov/nist/javax/sip/header/HeaderFactoryImpl.java0100644 0000000 0000000 00000157372 13513104763 021661 0ustar000000000 0000000 /* * 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.javax.sip.header; import gov.nist.javax.sip.header.ims.*; /* IMS headers - issued by Miguel Freitas */ import gov.nist.javax.sip.header.extensions.*; // extension headers - pmusgrave import javax.sip.header.*; import gov.nist.javax.sip.parser.*; import gov.nist.javax.sip.parser.extensions.ReferencesParser; import javax.sip.address.*; import java.text.ParseException; import javax.sip.InvalidArgumentException; import java.util.*; import gov.nist.javax.sip.address.*; /* * This file contains enhancements contributed by Alexandre Silva Santos * (PT-Inovacao) and Miguel Freitas */ /** Implementation of the JAIN SIP HeaderFactory * * @version 1.2 $Revision: 1.22 $ $Date: 2010/01/12 18:58:48 $ * @since 1.1 * *@author M. Ranganathan
    *@author Olivier Deruelle
    * * */ public class HeaderFactoryImpl implements HeaderFactory , HeaderFactoryExt { /** * Determines whether or not we should tolerate and strip address scope * zones from IPv6 addresses. Address scope zones are sometimes returned * at the end of IPv6 addresses generated by InetAddress.getHostAddress(). * They are however not part of the SIP semantics so basically this method * determines whether or not the parser should be stripping them (as * opposed simply being blunt and throwing an exception). */ private boolean stripAddressScopeZones = false; /** * Set pretty encoding on / off. * This splits up via headers into multiple lines for readability ( better for * debugging ). * */ public void setPrettyEncoding(boolean flag) { SIPHeaderList.setPrettyEncode(flag); } /** * Creates a new AcceptEncodingHeader based on the newly supplied encoding * value. * * @param encoding - the new string containing the encoding value. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the encoding value. * @return the newly created AcceptEncodingHeader object. */ public AcceptEncodingHeader createAcceptEncodingHeader(String encoding) throws ParseException { if (encoding == null) throw new NullPointerException("the encoding parameter is null"); AcceptEncoding acceptEncoding = new AcceptEncoding(); acceptEncoding.setEncoding(encoding); return acceptEncoding; } /** * Creates a new AcceptHeader based on the newly supplied contentType and * contentSubType values. * * @param contentType The new string content type value. * @param contentSubType The new string content sub-type value. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the content type or content subtype value. * @return the newly created AcceptHeader object. */ public AcceptHeader createAcceptHeader( String contentType, String contentSubType) throws ParseException { if (contentType == null || contentSubType == null) throw new NullPointerException("contentType or subtype is null "); Accept accept = new Accept(); accept.setContentType(contentType); accept.setContentSubType(contentSubType); return accept; } /** * Creates a new AcceptLanguageHeader based on the newly supplied * language value. * * @param language - the new Locale value of the language * @return the newly created AcceptLanguageHeader object. */ public AcceptLanguageHeader createAcceptLanguageHeader(Locale language) { if (language == null) throw new NullPointerException("null arg"); AcceptLanguage acceptLanguage = new AcceptLanguage(); acceptLanguage.setAcceptLanguage(language); return acceptLanguage; } /** * Creates a new AlertInfoHeader based on the newly supplied alertInfo value. * * @param alertInfo - the new URI value of the alertInfo * @return the newly created AlertInfoHeader object. * @since v1.1 */ public AlertInfoHeader createAlertInfoHeader(URI alertInfo) { if (alertInfo == null) throw new NullPointerException("null arg alertInfo"); AlertInfo a = new AlertInfo(); a.setAlertInfo(alertInfo); return a; } /** * Creates a new AllowEventsHeader based on the newly supplied event type * value. * * @param eventType - the new string containing the eventType value. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the eventType value. * @return the newly created AllowEventsHeader object. * @since v1.1 */ public AllowEventsHeader createAllowEventsHeader(String eventType) throws ParseException { if (eventType == null) throw new NullPointerException("null arg eventType"); AllowEvents allowEvents = new AllowEvents(); allowEvents.setEventType(eventType); return allowEvents; } /** * Creates a new AllowHeader based on the newly supplied method value. * * @param method - the new string containing the method value. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the method value. * @return the newly created AllowHeader object. */ public AllowHeader createAllowHeader(String method) throws ParseException { if (method == null) throw new NullPointerException("null arg method"); Allow allow = new Allow(); allow.setMethod(method); return allow; } /** * Creates a new AuthenticationInfoHeader based on the newly supplied * response value. * * @param response - the new string value of the response. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the response value. * @return the newly created AuthenticationInfoHeader object. * @since v1.1 */ public AuthenticationInfoHeader createAuthenticationInfoHeader(String response) throws ParseException { if (response == null) throw new NullPointerException("null arg response"); AuthenticationInfo auth = new AuthenticationInfo(); auth.setResponse(response); return auth; } /** * Creates a new AuthorizationHeader based on the newly supplied * scheme value. * * @param scheme - the new string value of the scheme. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the scheme value. * @return the newly created AuthorizationHeader object. */ public AuthorizationHeader createAuthorizationHeader(String scheme) throws ParseException { if (scheme == null) throw new NullPointerException("null arg scheme "); Authorization auth = new Authorization(); auth.setScheme(scheme); return auth; } /** * Creates a new CSeqHeader based on the newly supplied sequence number and * method values. * * @param sequenceNumber - the new integer value of the sequence number. * @param method - the new string value of the method. * @throws InvalidArgumentException if supplied sequence number is less * than zero. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the method value. * @return the newly created CSeqHeader object. */ public CSeqHeader createCSeqHeader( long sequenceNumber, String method) throws ParseException, InvalidArgumentException { if (sequenceNumber < 0) throw new InvalidArgumentException("bad arg " + sequenceNumber); if (method == null) throw new NullPointerException("null arg method"); CSeq cseq = new CSeq(); cseq.setMethod(method); cseq.setSeqNumber(sequenceNumber); return cseq; } /** * For backwards compatibility, also accept int * @deprecated */ public CSeqHeader createCSeqHeader( int sequenceNumber, String method) throws ParseException, InvalidArgumentException { return this.createCSeqHeader( (long) sequenceNumber, method ); } /** * Creates a new CallIdHeader based on the newly supplied callId value. * * @param callId - the new string value of the call-id. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the callId value. * @return the newly created CallIdHeader object. */ public CallIdHeader createCallIdHeader(String callId) throws ParseException { if (callId == null) throw new NullPointerException("null arg callId"); CallID c = new CallID(); c.setCallId(callId); return c; } /** * Creates a new CallInfoHeader based on the newly supplied callInfo value. * * @param callInfo The new string value of the callInfo. * @return the newly created CallInfoHeader object. */ public CallInfoHeader createCallInfoHeader(URI callInfo) { if (callInfo == null) throw new NullPointerException("null arg callInfo"); CallInfo c = new CallInfo(); c.setInfo(callInfo); return c; } /** * Creates a new ContactHeader based on the newly supplied address value. * * @param address - the new Address value of the address. * @return the newly created ContactHeader object. */ public ContactHeader createContactHeader(Address address) { if (address == null) throw new NullPointerException("null arg address"); Contact contact = new Contact(); contact.setAddress(address); return contact; } /** * Creates a new wildcard ContactHeader. This is used in Register requests * to indicate to the server that it should remove all locations the * at which the user is currently available. This implies that the * following conditions are met: *
      *
    • ContactHeader.getAddress.getAddress.getUserInfo() == *; *
    • ContactHeader.getAddress.getAddress.isWildCard() == true; *
    • ContactHeader.getExpires() == 0; *
    * * @return the newly created wildcard ContactHeader. */ public ContactHeader createContactHeader() { Contact contact = new Contact(); contact.setWildCardFlag(true); contact.setExpires(0); return contact; } /** * Creates a new ContentDispositionHeader based on the newly supplied * contentDisposition value. * * @param contentDisposition - the new string value of the contentDisposition. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the contentDisposition value. * @return the newly created ContentDispositionHeader object. * @since v1.1 */ public ContentDispositionHeader createContentDispositionHeader(String contentDisposition) throws ParseException { if (contentDisposition == null) throw new NullPointerException("null arg contentDisposition"); ContentDisposition c = new ContentDisposition(); c.setDispositionType(contentDisposition); return c; } /** * Creates a new ContentEncodingHeader based on the newly supplied encoding * value. * * @param encoding - the new string containing the encoding value. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the encoding value. * @return the newly created ContentEncodingHeader object. */ public ContentEncodingHeader createContentEncodingHeader(String encoding) throws ParseException { if (encoding == null) throw new NullPointerException("null encoding"); ContentEncoding c = new ContentEncoding(); c.setEncoding(encoding); return c; } /** * Creates a new ContentLanguageHeader based on the newly supplied * contentLanguage value. * * @param contentLanguage - the new Locale value of the contentLanguage. * @return the newly created ContentLanguageHeader object. * @since v1.1 */ public ContentLanguageHeader createContentLanguageHeader(Locale contentLanguage) { if (contentLanguage == null) throw new NullPointerException("null arg contentLanguage"); ContentLanguage c = new ContentLanguage(); c.setContentLanguage(contentLanguage); return c; } /** * Creates a new CSeqHeader based on the newly supplied contentLength value. * * @param contentLength - the new integer value of the contentLength. * @throws InvalidArgumentException if supplied contentLength is less * than zero. * @return the newly created ContentLengthHeader object. */ public ContentLengthHeader createContentLengthHeader(int contentLength) throws InvalidArgumentException { if (contentLength < 0) throw new InvalidArgumentException("bad contentLength"); ContentLength c = new ContentLength(); c.setContentLength(contentLength); return c; } /** * Creates a new ContentTypeHeader based on the newly supplied contentType and * contentSubType values. * * @param contentType - the new string content type value. * @param contentSubType - the new string content sub-type value. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the content type or content subtype value. * @return the newly created ContentTypeHeader object. */ public ContentTypeHeader createContentTypeHeader( String contentType, String contentSubType) throws ParseException { if (contentType == null || contentSubType == null) throw new NullPointerException("null contentType or subType"); ContentType c = new ContentType(); c.setContentType(contentType); c.setContentSubType(contentSubType); return c; } /** * Creates a new DateHeader based on the newly supplied date value. * * @param date - the new Calender value of the date. * @return the newly created DateHeader object. */ public DateHeader createDateHeader(Calendar date) { SIPDateHeader d = new SIPDateHeader(); if (date == null) throw new NullPointerException("null date"); d.setDate(date); return d; } /** * Creates a new EventHeader based on the newly supplied eventType value. * * @param eventType - the new string value of the eventType. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the eventType value. * @return the newly created EventHeader object. * @since v1.1 */ public EventHeader createEventHeader(String eventType) throws ParseException { if (eventType == null) throw new NullPointerException("null eventType"); Event event = new Event(); event.setEventType(eventType); return event; } /** * Creates a new ExpiresHeader based on the newly supplied expires value. * * @param expires - the new integer value of the expires. * @throws InvalidArgumentException if supplied expires is less * than zero. * @return the newly created ExpiresHeader object. */ public ExpiresHeader createExpiresHeader(int expires) throws InvalidArgumentException { if (expires < 0) throw new InvalidArgumentException("bad value " + expires); Expires e = new Expires(); e.setExpires(expires); return e; } /** * Creates a new ExtensionHeader based on the newly supplied name and * value values. * * @param name - the new string name of the ExtensionHeader value. * @param value - the new string value of the ExtensionHeader. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the name or value values. * @return the newly created ExtensionHeader object. */ public javax.sip.header.ExtensionHeader createExtensionHeader( String name, String value) throws ParseException { if (name == null) throw new NullPointerException("bad name"); gov.nist.javax.sip.header.ExtensionHeaderImpl ext = new gov.nist.javax.sip.header.ExtensionHeaderImpl(); ext.setName(name); ext.setValue(value); return ext; } /** * Creates a new FromHeader based on the newly supplied address and * tag values. * * @param address - the new Address object of the address. * @param tag - the new string value of the tag. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the tag value. * @return the newly created FromHeader object. */ public FromHeader createFromHeader(Address address, String tag) throws ParseException { if (address == null) throw new NullPointerException("null address arg"); From from = new From(); from.setAddress(address); if (tag != null) from.setTag(tag); return from; } /** * Creates a new InReplyToHeader based on the newly supplied callId * value. * * @param callId - the new string containing the callId value. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the callId value. * @return the newly created InReplyToHeader object. * @since v1.1 */ public InReplyToHeader createInReplyToHeader(String callId) throws ParseException { if (callId == null) throw new NullPointerException("null callId arg"); InReplyTo inReplyTo = new InReplyTo(); inReplyTo.setCallId(callId); return inReplyTo; } /** * Creates a new MaxForwardsHeader based on the newly * supplied maxForwards value. * * @param maxForwards The new integer value of the maxForwards. * @throws InvalidArgumentException if supplied maxForwards is less * than zero or greater than 255. * @return the newly created MaxForwardsHeader object. */ public MaxForwardsHeader createMaxForwardsHeader(int maxForwards) throws InvalidArgumentException { if (maxForwards < 0 || maxForwards > 255) throw new InvalidArgumentException( "bad maxForwards arg " + maxForwards); MaxForwards m = new MaxForwards(); m.setMaxForwards(maxForwards); return m; } /** * Creates a new MimeVersionHeader based on the newly * supplied mimeVersion value. * * @param majorVersion - the new integer value of the majorVersion. * @param minorVersion - the new integer value of the minorVersion. * @throws InvalidArgumentException if supplied mimeVersion is less * than zero. * @return the newly created MimeVersionHeader object. * @since v1.1 */ public MimeVersionHeader createMimeVersionHeader( int majorVersion, int minorVersion) throws InvalidArgumentException { if (majorVersion < 0 || minorVersion < 0) throw new javax.sip.InvalidArgumentException( "bad major/minor version"); MimeVersion m = new MimeVersion(); m.setMajorVersion(majorVersion); m.setMinorVersion(minorVersion); return m; } /** * Creates a new MinExpiresHeader based on the newly supplied minExpires value. * * @param minExpires - the new integer value of the minExpires. * @throws InvalidArgumentException if supplied minExpires is less * than zero. * @return the newly created MinExpiresHeader object. * @since v1.1 */ public MinExpiresHeader createMinExpiresHeader(int minExpires) throws InvalidArgumentException { if (minExpires < 0) throw new InvalidArgumentException("bad minExpires " + minExpires); MinExpires min = new MinExpires(); min.setExpires(minExpires); return min; } /** * Creates a new MinSEHeader based on the newly supplied expires value. * * @param expires - the new integer value of the expires. * @throws InvalidArgumentException if supplied expires is less * than zero. * @return the newly created ExpiresHeader object. * * TODO: Once interfaces are in javax, change the type to MinSEHeader * and add to HeaderFactory. - pmusgrave * * pmusgrave */ public ExtensionHeader createMinSEHeader(int expires) throws InvalidArgumentException { if (expires < 0) throw new InvalidArgumentException("bad value " + expires); MinSE e = new MinSE(); e.setExpires(expires); return e; } /** * Creates a new OrganizationHeader based on the newly supplied * organization value. * * @param organization - the new string value of the organization. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the organization value. * @return the newly created OrganizationHeader object. */ public OrganizationHeader createOrganizationHeader(String organization) throws ParseException { if (organization == null) throw new NullPointerException("bad organization arg"); Organization o = new Organization(); o.setOrganization(organization); return o; } /** * Creates a new PriorityHeader based on the newly supplied priority value. * * @param priority - the new string value of the priority. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the priority value. * @return the newly created PriorityHeader object. */ public PriorityHeader createPriorityHeader(String priority) throws ParseException { if (priority == null) throw new NullPointerException("bad priority arg"); Priority p = new Priority(); p.setPriority(priority); return p; } /** * Creates a new ProxyAuthenticateHeader based on the newly supplied * scheme value. * * @param scheme - the new string value of the scheme. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the scheme value. * @return the newly created ProxyAuthenticateHeader object. */ public ProxyAuthenticateHeader createProxyAuthenticateHeader(String scheme) throws ParseException { if (scheme == null) throw new NullPointerException("bad scheme arg"); ProxyAuthenticate p = new ProxyAuthenticate(); p.setScheme(scheme); return p; } /** * Creates a new ProxyAuthorizationHeader based on the newly supplied * scheme value. * * @param scheme - the new string value of the scheme. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the scheme value. * @return the newly created ProxyAuthorizationHeader object. */ public ProxyAuthorizationHeader createProxyAuthorizationHeader(String scheme) throws ParseException { if (scheme == null) throw new NullPointerException("bad scheme arg"); ProxyAuthorization p = new ProxyAuthorization(); p.setScheme(scheme); return p; } /** * Creates a new ProxyRequireHeader based on the newly supplied optionTag * value. * * @param optionTag - the new string OptionTag value. * @return the newly created ProxyRequireHeader object. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the optionTag value. */ public ProxyRequireHeader createProxyRequireHeader(String optionTag) throws ParseException { if (optionTag == null) throw new NullPointerException("bad optionTag arg"); ProxyRequire p = new ProxyRequire(); p.setOptionTag(optionTag); return p; } /** * Creates a new RAckHeader based on the newly supplied rSeqNumber, * cSeqNumber and method values. * * @param rSeqNumber - the new integer value of the rSeqNumber. * @param cSeqNumber - the new integer value of the cSeqNumber. * @param method - the new string value of the method. * @throws InvalidArgumentException if supplied rSeqNumber or cSeqNumber is * less than zero or greater than than 2**31-1. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the method value. * @return the newly created RAckHeader object. * @since v1.1 */ public RAckHeader createRAckHeader( long rSeqNumber, long cSeqNumber, String method) throws InvalidArgumentException, ParseException { if (method == null) throw new NullPointerException("Bad method"); if (cSeqNumber < 0 || rSeqNumber < 0) throw new InvalidArgumentException("bad cseq/rseq arg"); RAck rack = new RAck(); rack.setMethod(method); rack.setCSequenceNumber(cSeqNumber); rack.setRSequenceNumber(rSeqNumber); return rack; } /** * @deprecated * @see javax.sip.header.HeaderFactory#createRAckHeader(int, int, java.lang.String) */ public RAckHeader createRAckHeader(int rSeqNumber, int cSeqNumber, String method) throws InvalidArgumentException, ParseException { return createRAckHeader((long)rSeqNumber, (long)cSeqNumber, method); } /** * @deprecated * @see javax.sip.header.HeaderFactory#createRSeqHeader(int) */ public RSeqHeader createRSeqHeader(int sequenceNumber) throws InvalidArgumentException { return createRSeqHeader((long) sequenceNumber) ; } /** * Creates a new RSeqHeader based on the newly supplied sequenceNumber value. * * @param sequenceNumber - the new integer value of the sequenceNumber. * @throws InvalidArgumentException if supplied sequenceNumber is * less than zero or greater than than 2**31-1. * @return the newly created RSeqHeader object. * @since v1.1 */ public RSeqHeader createRSeqHeader(long sequenceNumber) throws InvalidArgumentException { if (sequenceNumber < 0) throw new InvalidArgumentException( "invalid sequenceNumber arg " + sequenceNumber); RSeq rseq = new RSeq(); rseq.setSeqNumber(sequenceNumber); return rseq; } /** * Creates a new ReasonHeader based on the newly supplied reason value. * * @param protocol - the new string value of the protocol. * @param cause - the new integer value of the cause. * @param text - the new string value of the text. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the protocol, cause or text value. * @return the newly created ReasonHeader object. * @since v1.1 */ public ReasonHeader createReasonHeader( String protocol, int cause, String text) throws InvalidArgumentException, ParseException { if (protocol == null) throw new NullPointerException("bad protocol arg"); if (cause < 0) throw new InvalidArgumentException("bad cause"); Reason reason = new Reason(); reason.setProtocol(protocol); reason.setCause(cause); reason.setText(text); return reason; } /** * Creates a new RecordRouteHeader based on the newly supplied address value. * * @param address - the new Address object of the address. * @return the newly created RecordRouteHeader object. */ public RecordRouteHeader createRecordRouteHeader(Address address) { if ( address == null) throw new NullPointerException("Null argument!"); RecordRoute recordRoute = new RecordRoute(); recordRoute.setAddress(address); return recordRoute; } /** * Creates a new ReplyToHeader based on the newly supplied address value. * * @param address - the new Address object of the address. * @return the newly created ReplyToHeader object. * @since v1.1 */ public ReplyToHeader createReplyToHeader(Address address) { if (address == null) throw new NullPointerException("null address"); ReplyTo replyTo = new ReplyTo(); replyTo.setAddress(address); return replyTo; } /** * Creates a new RequireHeader based on the newly supplied optionTag * value. * * @param optionTag - the new string value containing the optionTag value. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the List of optionTag value. * @return the newly created RequireHeader object. */ public RequireHeader createRequireHeader(String optionTag) throws ParseException { if (optionTag == null) throw new NullPointerException("null optionTag"); Require require = new Require(); require.setOptionTag(optionTag); return require; } /** * Creates a new RetryAfterHeader based on the newly supplied retryAfter * value. * * @param retryAfter - the new integer value of the retryAfter. * @throws InvalidArgumentException if supplied retryAfter is less * than zero. * @return the newly created RetryAfterHeader object. */ public RetryAfterHeader createRetryAfterHeader(int retryAfter) throws InvalidArgumentException { if (retryAfter < 0) throw new InvalidArgumentException("bad retryAfter arg"); RetryAfter r = new RetryAfter(); r.setRetryAfter(retryAfter); return r; } /** * Creates a new RouteHeader based on the newly supplied address value. * * @param address - the new Address object of the address. * @return the newly created RouteHeader object. */ public RouteHeader createRouteHeader(Address address) { if (address == null) throw new NullPointerException("null address arg"); Route route = new Route(); route.setAddress(address); return route; } /** * Creates a new ServerHeader based on the newly supplied product value. * * @param product - the new list value of the product. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the product value. * @return the newly created ServerHeader object. */ public ServerHeader createServerHeader(List product) throws ParseException { if (product == null) throw new NullPointerException("null productList arg"); Server server = new Server(); server.setProduct(product); return server; } /** * Creates a new SubjectHeader based on the newly supplied subject value. * * @param subject - the new string value of the subject. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the subject value. * @return the newly created SubjectHeader object. */ public SubjectHeader createSubjectHeader(String subject) throws ParseException { if (subject == null) throw new NullPointerException("null subject arg"); Subject s = new Subject(); s.setSubject(subject); return s; } /** * Creates a new SubscriptionStateHeader based on the newly supplied * subscriptionState value. * * @param subscriptionState - the new string value of the subscriptionState. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the subscriptionState value. * @return the newly created SubscriptionStateHeader object. * @since v1.1 */ public SubscriptionStateHeader createSubscriptionStateHeader(String subscriptionState) throws ParseException { if (subscriptionState == null) throw new NullPointerException("null subscriptionState arg"); SubscriptionState s = new SubscriptionState(); s.setState(subscriptionState); return s; } /** * Creates a new SupportedHeader based on the newly supplied optionTag * value. * * @param optionTag - the new string containing the optionTag value. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the optionTag value. * @return the newly created SupportedHeader object. */ public SupportedHeader createSupportedHeader(String optionTag) throws ParseException { if (optionTag == null) throw new NullPointerException("null optionTag arg"); Supported supported = new Supported(); supported.setOptionTag(optionTag); return supported; } /** * Creates a new TimeStampHeader based on the newly supplied timeStamp value. * * @param timeStamp - the new float value of the timeStamp. * @throws InvalidArgumentException if supplied timeStamp is less * than zero. * @return the newly created TimeStampHeader object. */ public TimeStampHeader createTimeStampHeader(float timeStamp) throws InvalidArgumentException { if (timeStamp < 0) throw new IllegalArgumentException("illegal timeStamp"); TimeStamp t = new TimeStamp(); t.setTimeStamp(timeStamp); return t; } /** * Creates a new ToHeader based on the newly supplied address and * tag values. * * @param address - the new Address object of the address. * @param tag - the new string value of the tag. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the tag value. * @return the newly created ToHeader object. */ public ToHeader createToHeader(Address address, String tag) throws ParseException { if (address == null) throw new NullPointerException("null address"); To to = new To(); to.setAddress(address); if (tag != null) to.setTag(tag); return to; } /** * Creates a new UnsupportedHeader based on the newly supplied optionTag * value. * * @param optionTag - the new string containing the optionTag value. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the List of optionTag value. * @return the newly created UnsupportedHeader object. */ public UnsupportedHeader createUnsupportedHeader(String optionTag) throws ParseException { if (optionTag == null) throw new NullPointerException(optionTag); Unsupported unsupported = new Unsupported(); unsupported.setOptionTag(optionTag); return unsupported; } /** * Creates a new UserAgentHeader based on the newly supplied product value. * * @param product - the new list value of the product. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the product value. * @return the newly created UserAgentHeader object. */ public UserAgentHeader createUserAgentHeader(List product) throws ParseException { if (product == null) throw new NullPointerException("null user agent"); UserAgent userAgent = new UserAgent(); userAgent.setProduct(product); return userAgent; } /** * Creates a new ViaHeader based on the newly supplied uri and branch values. * * @param host the new host value of uri. * @param port the new port value of uri. * @param transport the new transport value of uri. * @param branch the new string value of the branch. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the branch value. * @return the newly created ViaHeader object. */ public ViaHeader createViaHeader( String host, int port, String transport, String branch) throws ParseException, InvalidArgumentException { // This should be changed. if (host == null || transport == null) throw new NullPointerException("null arg"); Via via = new Via(); if (branch != null) via.setBranch(branch); // for supporting IPv6 addresses if(host.indexOf(':') >= 0 && host.indexOf('[') < 0) { //strip address scope zones if any if(stripAddressScopeZones) { int zoneStart = host.indexOf('%'); if(zoneStart != -1) host = host.substring(0, zoneStart); } host = '[' + host + ']'; } via.setHost(host); via.setPort(port); via.setTransport(transport); return via; } /** * Creates a new WWWAuthenticateHeader based on the newly supplied * scheme value. * * @param scheme - the new string value of the scheme. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the scheme values. * @return the newly created WWWAuthenticateHeader object. */ public WWWAuthenticateHeader createWWWAuthenticateHeader(String scheme) throws ParseException { if (scheme == null) throw new NullPointerException("null scheme"); WWWAuthenticate www = new WWWAuthenticate(); www.setScheme(scheme); return www; } /** * Creates a new WarningHeader based on the newly supplied * agent, code and comment values. * * @param agent - the new string value of the agent. * @param code - the new boolean integer of the code. * @param comment - the new string value of the comment. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the agent or comment values. * @throws InvalidArgumentException if an invalid integer code is given for * the WarningHeader. * @return the newly created WarningHeader object. */ public WarningHeader createWarningHeader( String agent, int code, String comment) throws ParseException, InvalidArgumentException { if (agent == null) throw new NullPointerException("null arg"); Warning warning = new Warning(); warning.setAgent(agent); warning.setCode(code); warning.setText(comment); return warning; } /** Creates a new ErrorInfoHeader based on the newly * supplied errorInfo value. * * @param errorInfo - the new URI value of the errorInfo. * @return the newly created ErrorInfoHeader object. */ public ErrorInfoHeader createErrorInfoHeader(URI errorInfo) { if (errorInfo == null) throw new NullPointerException("null arg"); return new ErrorInfo((GenericURI) errorInfo); } /** * Create a header from the given header text. * Header should not have the trailng crlf. * @throws ParseException */ public javax.sip.header.Header createHeader(String headerText) throws ParseException { StringMsgParser smp = new StringMsgParser(); SIPHeader sipHeader = smp.parseSIPHeader(headerText.trim()); if (sipHeader instanceof SIPHeaderList) { if (((SIPHeaderList) sipHeader).size() > 1) { throw new ParseException( "Only singleton allowed " + headerText, 0); } else if (((SIPHeaderList) sipHeader).size() == 0) { try { return (Header) ((SIPHeaderList) sipHeader) .getMyClass() .newInstance(); } catch (InstantiationException ex) { ex.printStackTrace(); return null; } catch (IllegalAccessException ex) { ex.printStackTrace(); return null; } } else { return (Header) ((SIPHeaderList) sipHeader).getFirst(); } } else { return (Header) sipHeader; } } /** Create and parse a header. * * @param headerName -- header name for the header to parse. * @param headerValue -- header value for the header to parse. * @throws ParseException * @return the parsed sip header */ public javax.sip.header.Header createHeader( String headerName, String headerValue) throws java.text.ParseException { if (headerName == null) throw new NullPointerException("header name is null"); String hdrText = new StringBuffer() .append(headerName) .append(":") .append(headerValue) .toString(); return createHeader(hdrText); } /** Create and return a list of headers. *@param headers -- list of headers. *@throws ParseException -- if a parse exception occurs or a List * of that type of header is not alowed. *@return a List containing the headers. */ public java.util.List createHeaders(String headers) throws java.text.ParseException { if (headers == null) throw new NullPointerException("null arg!"); StringMsgParser smp = new StringMsgParser(); SIPHeader shdr = smp.parseSIPHeader(headers); if (shdr instanceof SIPHeaderList) return (SIPHeaderList) shdr; else throw new ParseException( "List of headers of this type is not allowed in a message", 0); } /** Create a ReferTo Header. *@param address -- address for the header. */ public ReferToHeader createReferToHeader(Address address) { if (address == null) throw new NullPointerException("null address!"); ReferTo referTo = new ReferTo(); referTo.setAddress(address); return referTo; } /** Create a ReferredBy Header. * * pmusgrave * *@param address -- address for the header. * * TODO: Once interfaces are in javax, change the type to MinSEHeader * and add to HeaderFactory. - pmusgrave */ public ReferredByHeader createReferredByHeader(Address address) { if (address == null) throw new NullPointerException("null address!"); ReferredBy referredBy = new ReferredBy(); referredBy.setAddress(address); return referredBy; } /** * Create a Replaces header with a call Id, to and from tag. * * TODO: Once interfaces are in javax, change the type to MinSEHeader * and add to HeaderFactory. - pmusgrave * pmusgrave */ public ReplacesHeader createReplacesHeader(String callId, String toTag, String fromTag) throws ParseException { Replaces replaces = new Replaces(); replaces.setCallId(callId); replaces.setFromTag(fromTag); replaces.setToTag(toTag); return replaces; } /** * Create a Join header with a call Id, to and from tag. * */ public JoinHeader createJoinHeader(String callId, String toTag, String fromTag) throws ParseException { Join join = new Join(); join.setCallId(callId); join.setFromTag(fromTag); join.setToTag(toTag); return join; } /* * (non-Javadoc) * @see javax.sip.header.HeaderFactory#createSIPETagHeader(java.lang.String) */ public SIPETagHeader createSIPETagHeader(String etag) throws ParseException { return new SIPETag(etag); } /* * (non-Javadoc) * @see javax.sip.header.HeaderFactory#createSIPIfMatchHeader(java.lang.String) */ public SIPIfMatchHeader createSIPIfMatchHeader(String etag) throws ParseException { return new SIPIfMatch(etag); } ////////////////////////////////////////////////////////////////////////// // The following headers are not part of the JSIP spec. // They are IMS headers // (contributed by Miguel Freitas - PT Inovacao and Telecommunications Institute) /////////////////////////////////////////////////////////////////////////// /** * creates a P-Access-Network-Info header * @return newly created P-Access-Network-Info header */ public PAccessNetworkInfoHeader createPAccessNetworkInfoHeader() { PAccessNetworkInfo accessNetworkInfo = new PAccessNetworkInfo(); return accessNetworkInfo; } /** * P-Asserted-Identity header * @param address - Address * @return newly created P-Asserted-Identity header * @throws ParseException * @throws NullPointerException */ public PAssertedIdentityHeader createPAssertedIdentityHeader(Address address) throws NullPointerException, ParseException { if (address == null) throw new NullPointerException("null address!"); PAssertedIdentity assertedIdentity = new PAssertedIdentity(); assertedIdentity.setAddress(address); return assertedIdentity; } /** * Creates a new P-Associated-URI header based on the supplied address * @param assocURI - Address * @return newly created P-Associated-URI header * @throws NullPointerException if the supplied address is null * @throws ParseException */ public PAssociatedURIHeader createPAssociatedURIHeader(Address assocURI) { if (assocURI == null) throw new NullPointerException("null associatedURI!"); PAssociatedURI associatedURI = new PAssociatedURI(); associatedURI.setAddress(assocURI); return associatedURI; } /** * P-Called-Party-ID header * @param address - Address * @return newly created P-Called-Party-ID header * @throws NullPointerException * @throws ParseException */ public PCalledPartyIDHeader createPCalledPartyIDHeader(Address address) { if (address == null) throw new NullPointerException("null address!"); PCalledPartyID calledPartyID = new PCalledPartyID(); calledPartyID.setAddress(address); return calledPartyID; } /** * P-Charging-Function-Addresses header * @return newly created P-Charging-Function-Addresses header */ public PChargingFunctionAddressesHeader createPChargingFunctionAddressesHeader() { PChargingFunctionAddresses cfa = new PChargingFunctionAddresses(); return cfa; } /** * P-Charging-Vector header * @param icid - icid string * @return newly created P-Charging-Vector header * @throws NullPointerException * @throws ParseException */ public PChargingVectorHeader createChargingVectorHeader(String icid) throws ParseException { if (icid == null) throw new NullPointerException("null icid arg!"); PChargingVector chargingVector = new PChargingVector(); chargingVector.setICID(icid); return chargingVector; } /** * P-Media-Authorization header * @param token - token string * @return newly created P-Media-Authorizarion header * @throws InvalidArgumentException * @throws ParseException */ public PMediaAuthorizationHeader createPMediaAuthorizationHeader(String token) throws InvalidArgumentException, ParseException { if (token == null || token == "") throw new InvalidArgumentException("The Media-Authorization-Token parameter is null or empty"); PMediaAuthorization mediaAuthorization = new PMediaAuthorization(); mediaAuthorization.setMediaAuthorizationToken(token); return mediaAuthorization; } /** * P-Preferred-Identity header * @param address - Address * @return newly created P-Preferred-Identity header * @throws NullPointerException */ public PPreferredIdentityHeader createPPreferredIdentityHeader(Address address) { if (address == null) throw new NullPointerException("null address!"); PPreferredIdentity preferredIdentity = new PPreferredIdentity(); preferredIdentity.setAddress(address); return preferredIdentity; } /** * P-Visited-Network-ID header * @return newly created P-Visited-Network-ID header */ public PVisitedNetworkIDHeader createPVisitedNetworkIDHeader() { PVisitedNetworkID visitedNetworkID = new PVisitedNetworkID(); return visitedNetworkID; } /** * PATH header * @param address - Address * @return newly created Path header * @throws NullPointerException * @throws ParseException */ public PathHeader createPathHeader(Address address) { if (address == null) throw new NullPointerException("null address!"); Path path = new Path(); path.setAddress(address); return path; } /** * Privacy header * @param privacyType - privacy type string * @return newly created Privacy header * @throws NullPointerException */ public PrivacyHeader createPrivacyHeader(String privacyType) { if (privacyType == null) throw new NullPointerException("null privacyType arg"); Privacy privacy = new Privacy(privacyType); return privacy; } /** * Service-Route header * @param address - Address * @return newly created Service-Route header * @throws NullPointerException */ public ServiceRouteHeader createServiceRouteHeader(Address address) { if (address == null) throw new NullPointerException("null address!"); ServiceRoute serviceRoute = new ServiceRoute(); serviceRoute.setAddress(address); return serviceRoute; } /** * Security-Server header * @return newly created Security-Server header */ public SecurityServerHeader createSecurityServerHeader() { SecurityServer secServer = new SecurityServer(); return secServer; } /** * Security-Client header * @return newly created Security-Client header */ public SecurityClientHeader createSecurityClientHeader() { SecurityClient secClient = new SecurityClient(); return secClient; } /** * Security-Verify header * @return newly created Security-Verify header */ public SecurityVerifyHeader createSecurityVerifyHeader() { SecurityVerify secVerify = new SecurityVerify(); return secVerify; } /** * @return the newly create P-User-Database header. * Please note that this is not a SIP/TEL uri. It is a * DIAMETER AAA URI. */ public PUserDatabaseHeader createPUserDatabaseHeader(String databaseName) { if((databaseName ==null)||(databaseName.equals(" "))) throw new NullPointerException("Database name is null"); PUserDatabase pUserDatabase = new PUserDatabase(); pUserDatabase.setDatabaseName(databaseName); return pUserDatabase; } /** * * @return The newly created P-Profile-Key header. * */ public PProfileKeyHeader createPProfileKeyHeader(Address address) { if (address ==null) throw new NullPointerException("Address is null"); PProfileKey pProfileKey = new PProfileKey(); pProfileKey.setAddress(address); return pProfileKey; } /** * * @return The newly created P-Served-User header. */ public PServedUserHeader createPServedUserHeader(Address address) { if(address==null) throw new NullPointerException("Address is null"); PServedUser psu = new PServedUser(); psu.setAddress(address); return psu; } /** * @return The newly created P-Preferred-Service header. */ public PPreferredServiceHeader createPPreferredServiceHeader() { PPreferredService pps = new PPreferredService(); return pps; } /** * * @return The newly created P-Asserted-Service header. */ public PAssertedServiceHeader createPAssertedServiceHeader() { PAssertedService pas = new PAssertedService(); return pas; } /** * Creates a new SessionExpiresHeader based on the newly supplied expires value. * * @param expires - the new integer value of the expires. * @throws InvalidArgumentException if supplied expires is less * than zero. * @return the newly created SessionExpiresHeader object. * */ public SessionExpiresHeader createSessionExpiresHeader(int expires) throws InvalidArgumentException { if (expires < 0) throw new InvalidArgumentException("bad value " + expires); SessionExpires s = new SessionExpires(); s.setExpires(expires); return s; } /** * Create a new Request Line from a String. * */ public SipRequestLine createRequestLine(String requestLine) throws ParseException { RequestLineParser requestLineParser = new RequestLineParser(requestLine); return (SipRequestLine) requestLineParser.parse(); } /** * Create a new StatusLine from a String. */ public SipStatusLine createStatusLine(String statusLine) throws ParseException { StatusLineParser statusLineParser = new StatusLineParser(statusLine); return (SipStatusLine) statusLineParser.parse(); } /** * Create and return a references header. * * @param callId * @param rel * @return * @throws ParseException */ public ReferencesHeader createReferencesHeader(String callId, String rel) throws ParseException { ReferencesHeader retval = new References(); retval.setCallId(callId); retval.setRel(rel); return retval; } ////////////////////////////////////////////////////////// // Constructor ////////////////////////////////////////////////////////// /** * Default constructor. */ public HeaderFactoryImpl() { stripAddressScopeZones = Boolean.getBoolean("gov.nist.core.STRIP_ADDR_SCOPES"); } } java/gov/nist/javax/sip/header/InReplyTo.java0100644 0000000 0000000 00000006542 13513104763 020174 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.header.*; import java.text.ParseException; /** * InReplyTo SIP Header. * * @version 1.2 $Revision: 1.6 $ $Date: 2009/07/17 18:57:31 $ * * @author M. Ranganathan
    * @author Olivier Deruelle
    * * */ public class InReplyTo extends SIPHeader implements InReplyToHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = 1682602905733508890L; protected CallIdentifier callId; /** Default constructor */ public InReplyTo() { super(IN_REPLY_TO); } /** constructor * @param cid CallIdentifier to set */ public InReplyTo(CallIdentifier cid) { super(IN_REPLY_TO); callId = cid; } /** * Sets the Call-Id of the InReplyToHeader. The CallId parameter uniquely * identifies a serious of messages within a dialogue. * * @param callId - the string value of the Call-Id of this InReplyToHeader. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the callId value. */ public void setCallId(String callId) throws ParseException { try { this.callId = new CallIdentifier(callId); } catch (Exception e) { throw new ParseException(e.getMessage(), 0); } } /** * Returns the Call-Id of InReplyToHeader. The CallId parameter uniquely * identifies a series of messages within a dialogue. * * @return the String value of the Call-Id of this InReplyToHeader */ public String getCallId() { if (callId == null) return null; return callId.encode(); } /** * Generate canonical form of the header. * @return String */ public String encodeBody() { return callId.encode(); } public Object clone() { InReplyTo retval = (InReplyTo) super.clone(); if (this.callId != null) retval.callId = (CallIdentifier) this.callId.clone(); return retval; } } java/gov/nist/javax/sip/header/InReplyToList.java0100644 0000000 0000000 00000003661 13513104763 021027 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.header.*; /** * In-Reply-To SIP header. Keeps a list of InReplyToHeader * * @version 1.2 $Revision: 1.6 $ $Date: 2009/07/17 18:57:31 $ * @since 1.1 * *@author M. Ranganathan
    * * * */ public final class InReplyToList extends SIPHeaderList { private static final long serialVersionUID = -7993498496830999237L; public Object clone() { InReplyToList retval = new InReplyToList(); retval.clonehlist(this.hlist); return retval; } /** Default constructor */ public InReplyToList() { super(InReplyTo.class, InReplyToHeader.NAME); } } java/gov/nist/javax/sip/header/Indentation.java0100644 0000000 0000000 00000005216 13513104763 020560 0ustar000000000 0000000 /* * 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.javax.sip.header; /** * Internal utility class for pretty printing and header formatting. * * @author M. Ranganathan * @author O. Deruelle * * @version 1.2 $Revision: 1.6 $ $Date: 2009/07/17 18:57:31 $ */ class Indentation { private int indentation; /** * Default constructor */ protected Indentation() { indentation = 0; } /** * Constructor * * @param initval * int to set */ protected Indentation(int initval) { indentation = initval; } /** * set the indentation field * * @param initval * int to set */ protected void setIndentation(int initval) { indentation = initval; } /** * get the number of indentation. * * @return int */ protected int getCount() { return indentation; } /** * increment the indentation field */ protected void increment() { indentation++; } /** * decrement the indentation field */ protected void decrement() { indentation--; } /** * get the indentation * * @return String */ protected String getIndentation() { char[] chars = new char[indentation]; java.util.Arrays.fill(chars, ' '); return new String(chars); } } java/gov/nist/javax/sip/header/MaxForwards.java0100644 0000000 0000000 00000007133 13513104763 020541 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.header.*; import javax.sip.InvalidArgumentException; /** * MaxForwards SIPHeader * * @version 1.2 $Revision: 1.8 $ $Date: 2009/07/17 18:57:32 $ * * @author M. Ranganathan
    * @author Olivier Deruelle
    * */ public class MaxForwards extends SIPHeader implements MaxForwardsHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -3096874323347175943L; /** maxForwards field. */ protected int maxForwards; /** Default constructor. */ public MaxForwards() { super(NAME); } public MaxForwards( int m ) throws InvalidArgumentException { super(NAME); this.setMaxForwards( m ); } /** get the MaxForwards field. * @return the maxForwards member. */ public int getMaxForwards() { return maxForwards; } /** * Set the maxForwards member * @param maxForwards maxForwards parameter to set */ public void setMaxForwards(int maxForwards) throws InvalidArgumentException { if (maxForwards < 0 || maxForwards > 255) throw new InvalidArgumentException( "bad max forwards value " + maxForwards); this.maxForwards = maxForwards; } /** * Encode into a string. * @return encoded string. * */ public String encodeBody() { return encodeBody(new StringBuffer()).toString(); } protected StringBuffer encodeBody(StringBuffer buffer) { return buffer.append(maxForwards); } /** Boolean function * @return true if MaxForwards field reached zero. */ public boolean hasReachedZero() { return maxForwards == 0; } /** decrement MaxForwards field one by one. */ public void decrementMaxForwards() throws TooManyHopsException { if (maxForwards > 0) maxForwards--; else throw new TooManyHopsException ("has already reached 0!"); } public boolean equals(Object other) { if (this==other) return true; if (other instanceof MaxForwardsHeader) { final MaxForwardsHeader o = (MaxForwardsHeader) other; return this.getMaxForwards() == o.getMaxForwards(); } return false; } } java/gov/nist/javax/sip/header/MediaRange.java0100644 0000000 0000000 00000006264 13513104763 020304 0ustar000000000 0000000 /* * 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). * * See ../../../../doc/uncopyright.html for conditions of use. * * Author: M. Ranganathan (mranga@nist.gov) * * Modified By: O. Deruelle (deruelle@nist.gov) * * Questions/Comments: nist-sip-dev@antd.nist.gov * *******************************************************************************/ package gov.nist.javax.sip.header; /** * Media Range * @see Accept * @since 0.9 * @version 1.2 $Revision: 1.6 $ $Date: 2009/07/17 18:57:32 $ *
    * Revisions:
    *
    * Version 1.0
    *    1. Added encode method.
    *
    * media-range    = ( "STAR/STAR"
    *                        | ( type "/" STAR )
    *                        | ( type "/" subtype )
    *                        ) *( ";" parameter )
    *
    * HTTP RFC 2616 Section 14.1
    * 
    */ public class MediaRange extends SIPObject { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -6297125815438079210L; /** type field */ protected String type; /** subtype field */ protected String subtype; /** Default constructor */ public MediaRange() { } /** get type field * @return String */ public String getType() { return type; } /** get the subType field. * @return String */ public String getSubtype() { return subtype; } /** * Set the type member * @param t String to set */ public void setType(String t) { type = t; } /** * Set the subtype member * @param s String to set */ public void setSubtype(String s) { subtype = s; } /** * Encode the object. * @return String */ public String encode() { return encode(new StringBuffer()).toString(); } public StringBuffer encode(StringBuffer buffer) { return buffer.append(type) .append(SLASH) .append(subtype); } } java/gov/nist/javax/sip/header/MimeVersion.java0100644 0000000 0000000 00000014772 13513104763 020550 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.InvalidArgumentException; import javax.sip.header.*; /** * MimeVersion SIP Header. * * @version 1.2 $Revision: 1.6 $ $Date: 2009/10/18 13:46:35 $ * @since 1.1 * * @author M. Ranganathan
    * @author Olivier Deruelle
    * * */ public class MimeVersion extends SIPHeader implements MimeVersionHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -7951589626435082068L; /** * mimeVersion field */ protected int minorVersion; /** * majorVersion field */ protected int majorVersion; /** * Default constructor */ public MimeVersion() { super(MIME_VERSION); } /** * Gets the Minor version value of this MimeVersionHeader. * * @return the Minor version of this MimeVersionHeader */ public int getMinorVersion() { return minorVersion; } /** * Gets the Major version value of this MimeVersionHeader. * * @return the Major version of this MimeVersionHeader */ public int getMajorVersion() { return majorVersion; } /** * Sets the Minor-Version argument of this MimeVersionHeader to the supplied * minorVersion value. * * @param minorVersion - the new integer Minor version * @throws InvalidArgumentException */ public void setMinorVersion(int minorVersion) throws InvalidArgumentException { if (minorVersion < 0) throw new InvalidArgumentException( "JAIN-SIP Exception" + ", MimeVersion, setMinorVersion(), the minorVersion parameter is null"); this.minorVersion = minorVersion; } /** * Sets the Major-Version argument of this MimeVersionHeader to the supplied * majorVersion value. * * @param majorVersion - the new integer Major version * @throws InvalidArgumentException */ public void setMajorVersion(int majorVersion) throws InvalidArgumentException { if (majorVersion < 0) throw new InvalidArgumentException( "JAIN-SIP Exception" + ", MimeVersion, setMajorVersion(), the majorVersion parameter is null"); this.majorVersion = majorVersion; } /** * Return canonical form. * @return String */ public String encodeBody() { return Integer.toString(majorVersion) + DOT + Integer.toString(minorVersion); } } /* * $Log: MimeVersion.java,v $ * 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. * * Revision 1.4 2006/07/13 09:01:33 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:26 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:34 mranga * * Import * * * Revision 1.2 2004/01/22 13:26:29 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/header/MinExpires.java0100644 0000000 0000000 00000013004 13513104763 020361 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.*; import javax.sip.header.*; /** * MinExpires SIP Header. * * @version 1.2 $Revision: 1.6 $ $Date: 2009/10/18 13:46:35 $ * @since 1.1 * * @author M. Ranganathan
    * @author Olivier Deruelle
    * * * */ public class MinExpires extends SIPHeader implements MinExpiresHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = 7001828209606095801L; /** expires field */ protected int expires; /** default constructor */ public MinExpires() { super(NAME); } /** * Return canonical form. * @return String */ public String encodeBody() { return Integer.toString(expires); } /** * Gets the expires value of the ExpiresHeader. This expires value is * relative time. * * @return the expires value of the ExpiresHeader. * */ public int getExpires() { return expires; } /** * Sets the relative expires value of the ExpiresHeader. * The expires value MUST be greater than zero and MUST be * less than 2**31. * * @param expires - the new expires value of this ExpiresHeader * * @throws InvalidArgumentException if supplied value is less than zero. * * * */ public void setExpires(int expires) throws InvalidArgumentException { if (expires < 0) throw new InvalidArgumentException("bad argument " + expires); this.expires = expires; } } /* * $Log: MinExpires.java,v $ * 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. * * Revision 1.4 2006/07/13 09:01:20 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:26 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:34 mranga * * Import * * * Revision 1.2 2004/01/22 13:26:29 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/header/NameMap.java0100644 0000000 0000000 00000015626 13513104763 017630 0ustar000000000 0000000 /* * 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 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.11 $ $Date: 2009/07/17 18:57:32 $ * @since 1.1 */ public class NameMap implements SIPHeaderNames, PackageNames { static Hashtable nameMap; static { initializeNameMap(); } protected static void putNameMap(String headerName, String className) { nameMap.put( headerName.toLowerCase(), className); } public static Class getClassFromName(String headerName) { String className = (String) nameMap.get(headerName.toLowerCase()); if (className == null) return null; else { try { return Class.forName(className); } catch (ClassNotFoundException ex) { return null; } } } /** add an extension header to this map. *@param headerName is the extension header name. *@param className is the fully qualified class name that implements * the header (does not have to belong to the nist-sip package). * Use this if you want to use the introspection-based methods. */ public static void addExtensionHeader( String headerName, String className) { nameMap.put(headerName.toLowerCase(), className); } private static void initializeNameMap() { nameMap = new Hashtable(); putNameMap(MinExpires.NAME, MinExpires.class.getName()); // 1 putNameMap(ErrorInfo.NAME, ErrorInfo.class.getName()); // 2 putNameMap(MimeVersion.NAME, MimeVersion.class.getName()); // 3 putNameMap(InReplyTo.NAME, InReplyTo.class.getName()); // 4 putNameMap(Allow.NAME, Allow.class.getName()); // 5 putNameMap(ContentLanguage.NAME, ContentLanguage.class.getName()); // 6 putNameMap(CALL_INFO, CallInfo.class.getName()); //7 putNameMap(CSEQ, CSeq.class.getName()); //8 putNameMap(ALERT_INFO, AlertInfo.class.getName()); //9 putNameMap(ACCEPT_ENCODING, AcceptEncoding.class.getName()); //10 putNameMap(ACCEPT, Accept.class.getName()); //11 putNameMap(ACCEPT_LANGUAGE, AcceptLanguage.class.getName()); //12 putNameMap(RECORD_ROUTE, RecordRoute.class.getName()); //13 putNameMap(TIMESTAMP, TimeStamp.class.getName()); //14 putNameMap(TO, To.class.getName()); //15 putNameMap(VIA, Via.class.getName()); //16 putNameMap(FROM, From.class.getName()); //17 putNameMap(CALL_ID, CallID.class.getName()); //18 putNameMap(AUTHORIZATION, Authorization.class.getName()); //19 putNameMap(PROXY_AUTHENTICATE, ProxyAuthenticate.class.getName()); //20 putNameMap(SERVER, Server.class.getName()); //21 putNameMap(UNSUPPORTED, Unsupported.class.getName()); //22 putNameMap(RETRY_AFTER, RetryAfter.class.getName()); //23 putNameMap(CONTENT_TYPE, ContentType.class.getName()); //24 putNameMap(CONTENT_ENCODING, ContentEncoding.class.getName()); //25 putNameMap(CONTENT_LENGTH, ContentLength.class.getName()); //26 putNameMap(ROUTE, Route.class.getName()); //27 putNameMap(CONTACT, Contact.class.getName()); //28 putNameMap(WWW_AUTHENTICATE, WWWAuthenticate.class.getName()); //29 putNameMap(MAX_FORWARDS, MaxForwards.class.getName()); //30 putNameMap(ORGANIZATION, Organization.class.getName()); //31 putNameMap(PROXY_AUTHORIZATION, ProxyAuthorization.class.getName()); //32 putNameMap(PROXY_REQUIRE, ProxyRequire.class.getName()); //33 putNameMap(REQUIRE, Require.class.getName()); //34 putNameMap(CONTENT_DISPOSITION, ContentDisposition.class.getName()); //35 putNameMap(SUBJECT, Subject.class.getName()); //36 putNameMap(USER_AGENT, UserAgent.class.getName()); //37 putNameMap(WARNING, Warning.class.getName()); //38 putNameMap(PRIORITY, Priority.class.getName()); //39 putNameMap(DATE, SIPDateHeader.class.getName()); //40 putNameMap(EXPIRES, Expires.class.getName()); //41 putNameMap(SUPPORTED, Supported.class.getName()); //42 putNameMap(REPLY_TO, ReplyTo.class.getName()); // 43 putNameMap(SUBSCRIPTION_STATE, SubscriptionState.class.getName()); //44 putNameMap(EVENT, Event.class.getName()); //45 putNameMap(ALLOW_EVENTS, AllowEvents.class.getName()); //46 // pmusgrave - extensions putNameMap(REFERRED_BY, "ReferredBy"); putNameMap(SESSION_EXPIRES, "SessionExpires"); putNameMap(MIN_SE, "MinSE"); putNameMap(REPLACES, "Replaces"); // jean deruelle putNameMap(JOIN, "Join"); // IMS Specific headers. putNameMap(PAccessNetworkInfoHeader.NAME, PAccessNetworkInfo.class.getName()); putNameMap(PAssertedIdentityHeader.NAME, PAssertedIdentity.class.getName()); putNameMap(PAssociatedURIHeader.NAME, PAssociatedURI.class.getName()); putNameMap(PCalledPartyIDHeader.NAME, PCalledPartyID.class.getName()); putNameMap(PChargingFunctionAddressesHeader.NAME, PChargingFunctionAddresses.class.getName()); putNameMap(PChargingVectorHeader.NAME,PChargingVector.class.getName()); putNameMap(PMediaAuthorizationHeader.NAME,PMediaAuthorization.class.getName()); putNameMap(Path.NAME, Path.class.getName()); putNameMap(PPreferredIdentity.NAME, PPreferredIdentity.class.getName()); putNameMap(Privacy.NAME,Privacy.class.getName()); putNameMap(ServiceRoute.NAME, ServiceRoute.class.getName()); putNameMap(PVisitedNetworkID.NAME, PVisitedNetworkID.class.getName()); } } java/gov/nist/javax/sip/header/Organization.java0100644 0000000 0000000 00000012165 13513104763 020751 0ustar000000000 0000000 /* * 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.javax.sip.header; import java.text.ParseException; import javax.sip.header.*; /** * Organization SIP Header. * * @version 1.2 $Revision: 1.5 $ $Date: 2009/07/17 18:57:32 $ * @since 1.1 * * @author M. Ranganathan
    * @author Olivier Deruelle
    * * * */ public class Organization extends SIPHeader implements OrganizationHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -2775003113740192712L; /** * Organization field */ protected String organization; /** * Return encoding of value of the header. * @return String */ public String encodeBody() { return organization; } /** * Default constructor */ public Organization() { super(ORGANIZATION); } /** * Get the organization field. * @return String */ public String getOrganization() { return organization; } /** * Set the organization member * @param o String to set */ public void setOrganization(String o) throws ParseException { if (o == null) throw new NullPointerException( "JAIN-SIP Exception," + " Organization, setOrganization(), the organization parameter is null"); organization = o; } } /* * $Log: Organization.java,v $ * 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: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:26 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:34 mranga * * Import * * * Revision 1.2 2004/01/22 13:26:29 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/header/ParameterNames.java0100644 0000000 0000000 00000011036 13513104763 021205 0ustar000000000 0000000 /* * 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; /** * A list of commonly occuring parameter names. These are for conveniance so as * to avoid typo's * * @version 1.2 $Revision: 1.8 $ $Date: 2009/07/17 18:57:33 $ * @since 1.1 * * @author M. Ranganathan
    * * * */ public interface ParameterNames { // Issue reported by larryb public static final String NEXT_NONCE = "nextnonce"; public static final String TAG = "tag"; public static final String USERNAME = "username"; public static final String URI = "uri"; public static final String DOMAIN = "domain"; public static final String CNONCE = "cnonce"; public static final String PASSWORD = "password"; public static final String RESPONSE = "response"; public static final String RESPONSE_AUTH = "rspauth"; public static final String OPAQUE = "opaque"; public static final String ALGORITHM = "algorithm"; public static final String DIGEST = "Digest"; public static final String SIGNED_BY = "signed-by"; public static final String SIGNATURE = "signature"; public static final String NONCE = "nonce"; // Issue reported by larryb public static final String NONCE_COUNT = "nc"; public static final String PUBKEY = "pubkey"; public static final String COOKIE = "cookie"; public static final String REALM = "realm"; public static final String VERSION = "version"; public static final String STALE = "stale"; public static final String QOP = "qop"; public static final String NC = "nc"; public static final String PURPOSE = "purpose"; public static final String CARD = "card"; public static final String INFO = "info"; public static final String ACTION = "action"; public static final String PROXY = "proxy"; public static final String REDIRECT = "redirect"; public static final String EXPIRES = "expires"; public static final String Q = "q"; public static final String RENDER = "render"; public static final String SESSION = "session"; public static final String ICON = "icon"; public static final String ALERT = "alert"; public static final String HANDLING = "handling"; public static final String REQUIRED = "required"; public static final String OPTIONAL = "optional"; public static final String EMERGENCY = "emergency"; public static final String URGENT = "urgent"; public static final String NORMAL = "normal"; public static final String NON_URGENT = "non-urgent"; public static final String DURATION = "duration"; public static final String BRANCH = "branch"; public static final String HIDDEN = "hidden"; public static final String RECEIVED = "received"; public static final String MADDR = "maddr"; public static final String TTL = "ttl"; public static final String TRANSPORT = "transport"; public static final String TEXT = "text"; public static final String CAUSE = "cause"; public static final String ID = "id"; // @@@ hagai public static final String RPORT = "rport"; // Added pmusgrave (Replaces support) public static final String TO_TAG = "to-tag"; public static final String FROM_TAG = "from-tag"; // pmusgrave (outbound and gruu) // draft-sip-outbouund-08 // draft-sip-gruu-12 public static final String SIP_INSTANCE = "+sip.instance"; public static final String PUB_GRUU = "pub-gruu"; public static final String TEMP_GRUU = "temp-gruu"; public static final String GRUU = "gruu"; } java/gov/nist/javax/sip/header/ParametersHeader.java0100644 0000000 0000000 00000045012 13513104763 021516 0ustar000000000 0000000 /* * 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 Advanced Networking Technologies Division */ /**************************************************************************/ package gov.nist.javax.sip.header; import gov.nist.core.DuplicateNameValueList; import gov.nist.core.NameValue; import gov.nist.core.NameValueList; import gov.nist.javax.sip.address.GenericURI; import java.io.Serializable; import java.text.ParseException; import java.util.Iterator; import javax.sip.header.Parameters; /** * Parameters header. Suitable for extension by headers that have parameters. * * @author M. Ranganathan
    * * * @version 1.2 $Revision: 1.15 $ $Date: 2010/01/12 00:05:27 $ * */ public abstract class ParametersHeader extends SIPHeader implements javax.sip.header.Parameters, Serializable { protected NameValueList parameters; protected DuplicateNameValueList duplicates; protected ParametersHeader() { this.parameters = new NameValueList(); this.duplicates = new DuplicateNameValueList(); } protected ParametersHeader(String hdrName) { super(hdrName); this.parameters = new NameValueList(); this.duplicates = new DuplicateNameValueList(); } protected ParametersHeader(String hdrName, boolean sync) { super(hdrName); this.parameters = new NameValueList(sync); this.duplicates = new DuplicateNameValueList(); } /** * 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); } /** * Return the parameter as an object (dont convert to string). * * @param name is the name of the parameter to get. * @return the object associated with the name. */ public Object getParameterValue(String name) { return this.parameters.getValue(name); } /** * Returns an Iterator over the names (Strings) of all parameters present * in this ParametersHeader. * * @return an Iterator over all the parameter names */ public Iterator getParameterNames() { return parameters.getNames(); } /** Return true if you have a parameter and false otherwise. * *@return true if the parameters list is non-empty. */ public boolean hasParameters() { return parameters != null && !parameters.isEmpty(); } /** * Removes the specified parameter from Parameters of this ParametersHeader. * This method returns silently if the parameter is not part of the * ParametersHeader. * * @param name - a String specifying the parameter name */ public void removeParameter(String name) { this.parameters.delete(name); } /** * Sets the value of the specified parameter. If the parameter already had * * a value it will be overwritten. A zero-length String indicates flag * * parameter. * * * * @param name - a String specifying the parameter name * * @param value - a String specifying the parameter value * * @throws ParseException which signals that an error has been reached * * unexpectedly while parsing the parameter name or value. * */ public void setParameter(String name, String value) throws ParseException { NameValue nv = parameters.getNameValue(name); if (nv != null) { nv.setValueAsObject(value); } else { nv = new NameValue(name, value); this.parameters.set(nv); } } /** * Sets the value of the specified parameter. If the parameter already had * * a value it will be overwritten. A zero-length String indicates flag * * parameter. * * * * @param name - a String specifying the parameter name * * @param value - a String specifying the parameter value * * @throws ParseException which signals that an error has been reached * * unexpectedly while parsing the parameter name or value. * */ public void setQuotedParameter(String name, String value) throws ParseException { NameValue nv = parameters.getNameValue(name); if (nv != null) { nv.setValueAsObject(value); nv.setQuotedValue(); } else { nv = new NameValue(name, value); nv.setQuotedValue(); this.parameters.set(nv); } } /** * Sets the value of the specified parameter. If the parameter already had * * a value it will be overwritten. * * * @param name - a String specifying the parameter name * * @param value - an int specifying the parameter value * * @throws ParseException which signals that an error has been reached * * unexpectedly while parsing the parameter name or value. * */ protected void setParameter(String name, int value) { Integer val = Integer.valueOf(value); this.parameters.set(name,val); } /** * Sets the value of the specified parameter. If the parameter already had * * a value it will be overwritten. * * * @param name - a String specifying the parameter name * * @param value - a boolean specifying the parameter value * * @throws ParseException which signals that an error has been reached * * unexpectedly while parsing the parameter name or value. * */ protected void setParameter(String name, boolean value) { Boolean val = Boolean.valueOf(value); this.parameters.set(name,val); } /** * Sets the value of the specified parameter. If the parameter already had * * a value it will be overwritten. * * @param name - a String specifying the parameter name * * @param value - a boolean specifying the parameter value * * @throws ParseException which signals that an error has been reached * * unexpectedly while parsing the parameter name or value. * */ protected void setParameter(String name, float value) { Float val = Float.valueOf(value); NameValue nv = parameters.getNameValue(name); if (nv != null) { nv.setValueAsObject(val); } else { nv = new NameValue(name, val); this.parameters.set(nv); } } /** * Sets the value of the specified parameter. If the parameter already had * * a value it will be overwritten. A zero-length String indicates flag * * parameter. * * * * @param name - a String specifying the parameter name * * @param value - a String specifying the parameter value * * @throws ParseException which signals that an error has been reached * * unexpectedly while parsing the parameter name or value. * */ protected void setParameter(String name, Object value) { this.parameters.set(name,value); } /** * Return true if has a parameter. * * @param parameterName is the name of the parameter. * * @return true if the parameter exists and false if not. */ public boolean hasParameter(String parameterName) { return this.parameters.hasNameValue(parameterName); } /** *Remove all parameters. */ public void removeParameters() { this.parameters = new NameValueList(); } /** * get the parameter list. * @return parameter list */ public NameValueList getParameters() { return parameters; } /** Set the parameter given a name and value. * * @param nameValue - the name value of the parameter to set. */ public void setParameter(NameValue nameValue) { this.parameters.set(nameValue); } /** * Set the parameter list. * * @param parameters The name value list to set as the parameter list. */ public void setParameters(NameValueList parameters) { this.parameters = parameters; } /** * Get the parameter as an integer value. * * @param parameterName -- the parameter name to fetch. * * @return -1 if the parameter is not defined in the header. */ protected int getParameterAsInt(String parameterName) { if (this.getParameterValue(parameterName) != null) { try { if (this.getParameterValue(parameterName) instanceof String) { return Integer.parseInt(this.getParameter(parameterName)); } else { return ((Integer) getParameterValue(parameterName)) .intValue(); } } catch (NumberFormatException ex) { return -1; } } else return -1; } /** Get the parameter as an integer when it is entered as a hex. * *@param parameterName -- The parameter name to fetch. * *@return -1 if the parameter is not defined in the header. */ protected int getParameterAsHexInt(String parameterName) { if (this.getParameterValue(parameterName) != null) { try { if (this.getParameterValue(parameterName) instanceof String) { return Integer.parseInt( this.getParameter(parameterName), 16); } else { return ((Integer) getParameterValue(parameterName)) .intValue(); } } catch (NumberFormatException ex) { return -1; } } else return -1; } /** Get the parameter as a float value. * *@param parameterName -- the parameter name to fetch * *@return -1 if the parameter is not defined or the parameter as a float. */ protected float getParameterAsFloat(String parameterName) { if (this.getParameterValue(parameterName) != null) { try { if (this.getParameterValue(parameterName) instanceof String) { return Float.parseFloat(this.getParameter(parameterName)); } else { return ((Float) getParameterValue(parameterName)) .floatValue(); } } catch (NumberFormatException ex) { return -1; } } else return -1; } /** * Get the parameter as a long value. * * @param parameterName -- the parameter name to fetch. * * @return -1 if the parameter is not defined or the parameter as a long. */ protected long getParameterAsLong(String parameterName) { if (this.getParameterValue(parameterName) != null) { try { if (this.getParameterValue(parameterName) instanceof String) { return Long.parseLong(this.getParameter(parameterName)); } else { return ((Long) getParameterValue(parameterName)) .longValue(); } } catch (NumberFormatException ex) { return -1; } } else return -1; } /** * Get the parameter value as a URI. * * @param parameterName -- the parameter name * * @return value of the parameter as a URI or null if the parameter * not present. */ protected GenericURI getParameterAsURI(String parameterName) { Object val = getParameterValue(parameterName); if (val instanceof GenericURI) return (GenericURI) val; else { try { return new GenericURI((String) val); } catch (ParseException ex) { //catch ( URISyntaxException ex) { return null; } } } /** * Get the parameter value as a boolean. * * @param parameterName -- the parameter name * @return boolean value of the parameter. */ protected boolean getParameterAsBoolean(String parameterName) { Object val = getParameterValue(parameterName); if (val == null) { return false; } else if (val instanceof Boolean) { return ((Boolean) val).booleanValue(); } else if (val instanceof String) { return Boolean.valueOf((String) val).booleanValue(); } else return false; } /** * This is for the benifit of the TCK. * * @return the name value pair for the given parameter name. */ public NameValue getNameValue(String parameterName) { return parameters.getNameValue(parameterName); } public Object clone() { ParametersHeader retval = (ParametersHeader) super.clone(); if (this.parameters != null) retval.parameters = (NameValueList) this.parameters.clone(); return retval; } //------------------------- /** * Introduced specifically for the P-Charging-Function-Addresses Header and * all other headers that may have multiple header parameters of the same name, but * with multiple possible values. * * Example: P-Charging-Function-Addresses: ccf=[5555::b99:c88:d77:e66]; ccf=[5555::a55:b44:c33:d22]; * ecf=[5555::1ff:2ee:3dd:4cc]; ecf=[5555::6aa:7bb:8cc:9dd] * @param name of the parameter * @param value of the parameter */ public void setMultiParameter(String name, String value) { NameValue nv = new NameValue(); nv.setName(name); nv.setValue(value); duplicates.set(nv); } /** Set the parameter given a name and value. * * @param nameValue - the name value of the parameter to set. */ public void setMultiParameter(NameValue nameValue) { this.duplicates.set(nameValue); } /** * Returns the parameter name * @param name * @return */ public String getMultiParameter(String name) { return this.duplicates.getParameter(name); } public DuplicateNameValueList getMultiParameters() { return duplicates; } /** * Return the parameter as an object (dont convert to string). * * @param name is the name of the parameter to get. * @return the object associated with the name. */ public Object getMultiParameterValue(String name) { return this.duplicates.getValue(name); } /** * Returns an Iterator over the names (Strings) of all parameters present * in this ParametersHeader. * * @return an Iterator over all the parameter names */ public Iterator getMultiParameterNames() { return duplicates.getNames(); } /** Return true if you have a parameter and false otherwise. * *@return true if the parameters list is non-empty. */ public boolean hasMultiParameters() { return duplicates != null && !duplicates.isEmpty(); } /** * Removes the specified parameter from Parameters of this ParametersHeader. * This method returns silently if the parameter is not part of the * ParametersHeader. * * @param name - a String specifying the parameter name */ public void removeMultiParameter(String name) { this.duplicates.delete(name); } /** * Return true if has a parameter. * * @param parameterName is the name of the parameter. * * @return true if the parameter exists and false if not. */ public boolean hasMultiParameter(String parameterName) { return this.duplicates.hasNameValue(parameterName); } /** *Remove all parameters. */ public void removeMultiParameters() { this.duplicates = new DuplicateNameValueList(); } //------------------------------- @SuppressWarnings("unchecked") protected final boolean equalParameters( Parameters other ) { if (this==other) return true; for ( Iterator i = this.getParameterNames(); i.hasNext();) { String pname = (String) i.next(); String p1 = this.getParameter( pname ); String p2 = other.getParameter( pname ); // getting them based on this.getParameterNames. Note that p1 may be null // if this is a name-only parameter like rport or lr. if (p1 == null ^ p2 == null) return false; else if (p1 != null && !p1.equalsIgnoreCase(p2) ) return false; } // Also compare other's parameters; some duplicate testing here... for ( Iterator i = other.getParameterNames(); i.hasNext();) { String pname = (String) i.next(); String p1 = other.getParameter( pname ); String p2 = this.getParameter( pname ); // assert( p1 != null ); // if ( p1 == null ) throw new RuntimeException("Assertion check failed!"); // if (p2==null) return false; // getting them based on this.getParameterNames. Note that p1 may be null // if this is a name-only parameter like rport or lr. if (p1 == null ^ p2 == null) return false; else if (p1 != null && !p1.equalsIgnoreCase(p2) ) return false; } return true; } // ----------- Abstract methods -------------- protected abstract String encodeBody(); } java/gov/nist/javax/sip/header/Priority.java0100644 0000000 0000000 00000005612 13513104763 020125 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.header.*; import java.text.ParseException; /** * the Priority header. * * @author Olivier Deruelle
    * @version 1.2 $Revision: 1.6 $ $Date: 2009/07/17 18:57:33 $ * * * */ public class Priority extends SIPHeader implements PriorityHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = 3837543366074322106L; /** constant EMERGENCY field */ public static final String EMERGENCY = ParameterNames.EMERGENCY; /** constant URGENT field */ public static final String URGENT = ParameterNames.URGENT; /** constant NORMAL field */ public static final String NORMAL = ParameterNames.NORMAL; /** constant NON_URGENT field */ public static final String NON_URGENT = ParameterNames.NON_URGENT; /** priority field */ protected String priority; /** Default constructor */ public Priority() { super(NAME); } /** * Encode into canonical form. * @return String */ public String encodeBody() { return priority; } /** * get the priority value. * @return String */ public String getPriority() { return priority; } /** * Set the priority member * @param p String to set */ public void setPriority(String p) throws ParseException { if (p == null) throw new NullPointerException( "JAIN-SIP Exception," + "Priority, setPriority(), the priority parameter is null"); priority = p; } } java/gov/nist/javax/sip/header/Protocol.java0100644 0000000 0000000 00000015460 13513104763 020107 0ustar000000000 0000000 /* * 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.javax.sip.header; import java.text.ParseException; /** * Protocol name and version. * * @version 1.2 $Revision: 1.8 $ $Date: 2009/07/17 18:57:33 $ * * @author M. Ranganathan
    * * * */ public class Protocol extends SIPObject { /** * Comment for serialVersionUID */ private static final long serialVersionUID = 2216758055974073280L; /** protocolName field */ protected String protocolName; /** protocolVersion field */ protected String protocolVersion; /** transport field */ protected String transport; /** * Return canonical form. * @return String */ public String encode() { return encode(new StringBuffer()).toString(); } public StringBuffer encode(StringBuffer buffer) { buffer.append(protocolName.toUpperCase()) .append(SLASH) .append(protocolVersion) .append(SLASH) .append(transport.toUpperCase()); return buffer; } /** get the protocol name * @return String */ public String getProtocolName() { return protocolName; } /** get the protocol version * @return String */ public String getProtocolVersion() { return protocolVersion; } /** * Get the protocol name + version * JvB: This is what is returned in the ViaHeader interface for 'getProtocol()' * * @return String : protocolname + '/' + version */ public String getProtocol() { return protocolName + '/' + protocolVersion; } public void setProtocol( String name_and_version ) throws ParseException { int slash = name_and_version.indexOf('/'); if (slash>0) { this.protocolName = name_and_version.substring(0,slash); this.protocolVersion = name_and_version.substring( slash+1 ); } else throw new ParseException( "Missing '/' in protocol", 0 ); } /** get the transport * @return String */ public String getTransport() { return transport; } /** * Set the protocolName member * @param p String to set */ public void setProtocolName(String p) { protocolName = p; } /** * Set the protocolVersion member * @param p String to set */ public void setProtocolVersion(String p) { protocolVersion = p; } /** * Set the transport member * @param t String to set */ public void setTransport(String t) { transport = t; } /** * Default constructor. */ public Protocol() { protocolName = "SIP"; protocolVersion = "2.0"; transport = "UDP"; } } /* * $Log: Protocol.java,v $ * 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 StringBuffer instance during the encoding phase. * * Revision 1.6 2006/07/13 09:01:24 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.4 2006/06/19 06:47:26 mranga * javadoc fixups * * Revision 1.3 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.2 2005/10/09 18:47:53 jeroen * defined equals() in terms of API calls * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.2 2004/01/22 13:26:29 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/header/ProxyAuthenticate.java0100644 0000000 0000000 00000012263 13513104763 021764 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.address.URI; import javax.sip.header.*; /** * Proxy Authenticate SIP (HTTP ) header. * * @version 1.2 $Revision: 1.5 $ $Date: 2009/07/17 18:57:33 $ * * @author M. Ranganathan
    * @author Olivier Deruelle
    * * * */ public class ProxyAuthenticate extends AuthenticationHeader implements ProxyAuthenticateHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = 3826145955463251116L; /** * Default Constructor */ public ProxyAuthenticate() { super(NAME); } /* (non-Javadoc) * @see gov.nist.javax.sip.header.AuthenticationHeader#getURI() * * @since 1.2 this method is deprecated, uri is not a valid paramter for this header * Fail silently for backwards compatibility */ public URI getURI() { return null; } /* (non-Javadoc) * @see gov.nist.javax.sip.header.AuthenticationHeader#setURI(javax.sip.address.URI) * * @since 1.2 this method is deprecated, uri is not a valid paramter for this header * Fail silently for backwards compatibility */ public void setURI(URI uri) { // empty, fail silently } } /* * $Log: ProxyAuthenticate.java,v $ * Revision 1.5 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.4 2006/07/13 09:01:19 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.4 2006/06/19 06:47:26 mranga * javadoc fixups * * Revision 1.3 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.2 2005/10/09 10:50:06 jeroen * get/setURI is deprecated for WWW-Authenticate and Proxy-Authenticate, * but not for other AAA related headers * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.2 2004/01/22 13:26:29 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/header/ProxyAuthenticateList.java0100644 0000000 0000000 00000003765 13513104763 022627 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.header.*; /** * List of ProxyAuthenticate headers. * @version 1.2 $Revision: 1.6 $ $Date: 2009/07/17 18:57:34 $ * * @author M. Ranganathan
    * * * */ public class ProxyAuthenticateList extends SIPHeaderList { /** * Comment for serialVersionUID */ private static final long serialVersionUID = 1L; public Object clone() { ProxyAuthenticateList retval = new ProxyAuthenticateList(); retval.clonehlist(this.hlist); return retval; } /** Default constructor */ public ProxyAuthenticateList() { super(ProxyAuthenticate.class, ProxyAuthenticateHeader.NAME); } } java/gov/nist/javax/sip/header/ProxyAuthorization.java0100644 0000000 0000000 00000010575 13513104763 022212 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.header.*; /** * ProxyAuthorization Header. * * @version 1.2 $Revision: 1.5 $ $Date: 2009/07/17 18:57:34 $ * * @author M. Ranganathan
    * @author Olivier Deruelle
    * * * */ public class ProxyAuthorization extends AuthenticationHeader implements ProxyAuthorizationHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -6374966905199799098L; /** default constructor */ public ProxyAuthorization() { super(PROXY_AUTHORIZATION); } } /* * $Log: ProxyAuthorization.java,v $ * 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:46 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:26 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.2 2004/01/22 13:26:29 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/header/ProxyAuthorizationList.java0100644 0000000 0000000 00000003774 13513104763 023051 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.header.*; /** * List of ProxyAuthorization headers. * @version 1.2 $Revision: 1.5 $ $Date: 2009/07/17 18:57:34 $ * * @author M. Ranganathan
    * * * */ public class ProxyAuthorizationList extends SIPHeaderList{ /** * Comment for serialVersionUID */ private static final long serialVersionUID = -1L; public Object clone() { ProxyAuthorizationList retval = new ProxyAuthorizationList(); retval.clonehlist(this.hlist); return retval; } /** Default constructor */ public ProxyAuthorizationList() { super(ProxyAuthorization.class, ProxyAuthorizationHeader.NAME); } } java/gov/nist/javax/sip/header/ProxyRequire.java0100644 0000000 0000000 00000012760 13513104763 020764 0ustar000000000 0000000 /* * 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.javax.sip.header; import java.text.ParseException; import javax.sip.header.*; /** * ProxyRequire Header. * * @version 1.2 $Revision: 1.5 $ $Date: 2009/07/17 18:57:34 $ * * @author M. Ranganathan
    * @author Olivier Deruelle
    * * * */ public class ProxyRequire extends SIPHeader implements ProxyRequireHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -3269274234851067893L; /** * Optiontag field */ protected String optionTag; /** * Default Constructor */ public ProxyRequire() { super(PROXY_REQUIRE); } /** Constructor * @param s String to set */ public ProxyRequire(String s) { super(PROXY_REQUIRE); optionTag = s; } /** * Encode in canonical form. * @return String */ public String encodeBody() { return optionTag; } /** * Sets the option tag value to the new supplied optionTag * parameter. * * @param optionTag - the new string value of the option tag. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the optionTag value. */ public void setOptionTag(String optionTag) throws ParseException { if (optionTag == null) throw new NullPointerException("JAIN-SIP Exception, ProxyRequire, setOptionTag(), the optionTag parameter is null"); this.optionTag = optionTag; } /** * Gets the option tag of this OptionTag class. * * @return the string that identifies the option tag value. */ public String getOptionTag() { return optionTag; } } /* * $Log: ProxyRequire.java,v $ * 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: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:26 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.2 2004/01/22 13:26:29 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/header/ProxyRequireList.java0100644 0000000 0000000 00000003765 13513104763 021625 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.header.*; /** * Proxy Require SIPSIPObject (list of option tags) * * @version 1.2 $Revision: 1.6 $ $Date: 2009/07/17 18:57:34 $ * * @author M. Ranganathan
    * * * */ public class ProxyRequireList extends SIPHeaderList { /** * Comment for serialVersionUID */ private static final long serialVersionUID = 5648630649476486042L; public Object clone() { ProxyRequireList retval = new ProxyRequireList(); retval.clonehlist(this.hlist); return retval; } /** Default Constructor */ public ProxyRequireList() { super(ProxyRequire.class, ProxyRequireHeader.NAME); } } java/gov/nist/javax/sip/header/RAck.java0100644 0000000 0000000 00000010663 13513104763 017126 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.InvalidArgumentException; import java.text.ParseException; /** * RAck SIP Header implementation * * @version 1.2 $Revision: 1.7 $ $Date: 2009/07/17 18:57:34 $ * * @author M. Ranganathan
    * * */ public class RAck extends SIPHeader implements javax.sip.header.RAckHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = 743999286077404118L; protected long cSeqNumber; protected long rSeqNumber; protected String method; /** Creates a new instance of RAck */ public RAck() { super(NAME); } /** * Encode the body of this header (the stuff that follows headerName). A.K.A * headerValue. * */ protected String encodeBody() { // Bug reported by Bruno Konik - was encoded in // the wrong order. return new StringBuffer().append(rSeqNumber).append(SP).append( cSeqNumber).append(SP).append(method).toString(); } /** * Gets the CSeq sequence number of this RAckHeader. * * @deprecated * @return the integer value of the cSeq number of the RAckHeader */ public int getCSeqNumber() { return (int) cSeqNumber; } /** * Gets the CSeq sequence number of this RAckHeader. * * @return the integer value of the cSeq number of the RAckHeader */ public long getCSeqNumberLong() { return cSeqNumber; } /** * Gets the method of RAckHeader * * @return method of RAckHeader */ public String getMethod() { return this.method; } /** * Gets the RSeq sequence number of this RAckHeader. * * @deprecated * @return the integer value of the RSeq number of the RAckHeader */ public int getRSeqNumber() { return (int) rSeqNumber; } /** * @deprecated * @see javax.sip.header.RAckHeader#setCSeqNumber(int) */ public void setCSeqNumber(int cSeqNumber) throws InvalidArgumentException { this.setCSequenceNumber(cSeqNumber); } public void setMethod(String method) throws ParseException { this.method = method; } public long getCSequenceNumber() { return this.cSeqNumber; } public long getRSequenceNumber() { return this.rSeqNumber; } public void setCSequenceNumber(long cSeqNumber) throws InvalidArgumentException { if (cSeqNumber <= 0 || cSeqNumber > ((long) 1) << 32 - 1) throw new InvalidArgumentException("Bad CSeq # " + cSeqNumber); this.cSeqNumber = cSeqNumber; } /** *@deprecated * @see javax.sip.header.RAckHeader#setRSeqNumber(int) */ public void setRSeqNumber(int rSeqNumber) throws InvalidArgumentException { this.setRSequenceNumber(rSeqNumber); } public void setRSequenceNumber(long rSeqNumber) throws InvalidArgumentException { if (rSeqNumber <= 0 || cSeqNumber > ((long) 1) << 32 - 1) throw new InvalidArgumentException("Bad rSeq # " + rSeqNumber); this.rSeqNumber = rSeqNumber; } } java/gov/nist/javax/sip/header/RSeq.java0100644 0000000 0000000 00000005173 13513104763 017160 0ustar000000000 0000000 /* * 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.InvalidArgumentException; /** * * @version 1.2 $Revision: 1.7 $ $Date: 2009/10/18 13:46:35 $ * * @author M. Ranganathan
    * * */ public class RSeq extends SIPHeader implements javax.sip.header.RSeqHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = 8765762413224043394L; protected long sequenceNumber; /** Creates a new instance of RSeq */ public RSeq() { super(NAME); } /** Gets the sequence number of this RSeqHeader. * @deprecated * @return the integer value of the Sequence number of the RSeqHeader */ public int getSequenceNumber() { return (int)this.sequenceNumber; } /** Encode the body of this header (the stuff that follows headerName). * A.K.A headerValue. */ protected String encodeBody() { return Long.toString(this.sequenceNumber); } public long getSeqNumber() { return this.sequenceNumber; } public void setSeqNumber(long sequenceNumber) throws InvalidArgumentException { if (sequenceNumber <= 0 ||sequenceNumber > ((long)1)<<32 - 1) throw new InvalidArgumentException( "Bad seq number " + sequenceNumber); this.sequenceNumber = sequenceNumber; } /** * @deprecated * @see javax.sip.header.RSeqHeader#setSequenceNumber(int) */ public void setSequenceNumber(int sequenceNumber) throws InvalidArgumentException { this.setSeqNumber(sequenceNumber); } } java/gov/nist/javax/sip/header/Reason.java0100644 0000000 0000000 00000017417 13513104763 017541 0ustar000000000 0000000 /* * 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 * * . * */ /* * Reason.java * Reason = "Reason" HCOLON reason-value *(COMMA reason-value) * reason-value = protocol *(SEMI reason-params) * protocol = "SIP" / "Q.850" / token * reason-params = protocol-cause / reason-text * / reason-extension * protocol-cause = "cause" EQUAL cause * cause = 1*DIGIT * reason-text = "text" EQUAL quoted-string * reason-extension = generic-param */ package gov.nist.javax.sip.header; import gov.nist.javax.sip.Utils; import java.text.ParseException; /** * Definition of the Reason SIP Header. * * @version 1.2 $Revision: 1.8 $ $Date: 2009/10/18 13:46:34 $ * * @author M. Ranganathan
    * * */ public class Reason extends ParametersHeader implements javax.sip.header.ReasonHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -8903376965568297388L; public final String TEXT = ParameterNames.TEXT; public final String CAUSE = ParameterNames.CAUSE; protected String protocol; /** Get the cause token. *@return the cause code. */ public int getCause() { return getParameterAsInt(CAUSE); } /** * Set the cause. * *@param cause - cause to set. */ public void setCause(int cause) throws javax.sip.InvalidArgumentException { this.parameters.set("cause", Integer.valueOf(cause)); } /** Set the protocol * *@param protocol - protocol to set. */ public void setProtocol(String protocol) throws ParseException { this.protocol = protocol; } /** Return the protocol. * *@return the protocol. */ public String getProtocol() { return this.protocol; } /** Set the text. * *@param text -- string text to set. */ public void setText(String text) throws ParseException { // JvB: MUST be quoted if ( text.charAt(0) != '"' ) { text = Utils.getQuotedString(text); } this.parameters.set("text", text); } /** Get the text. * *@return text parameter. * */ public String getText() { return this.parameters.getParameter("text"); } /** Set the cause. /** Creates a new instance of Reason */ public Reason() { super(NAME); } /** Gets the unique string name of this Header. A name constant is defined in * each individual Header identifying each Header. * * @return the name of this specific Header */ public String getName() { return NAME; } /** * Encode the body of this header (the stuff that follows headerName). * A.K.A headerValue. */ 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: Reason.java,v $ * 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. * * Revision 1.6 2008/11/19 10:56:27 jbemmel * Ensure that reason text is quoted * * Revision 1.5 2006/11/01 02:22:56 mranga * Issue number: 83 * Obtained from: * Submitted by: * Reviewed by: mranga * fix thread safety issue in NameValueList and clean up some mess. * 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.4 2006/07/13 09:01:19 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:26 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.2 2004/01/22 13:26:29 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/header/ReasonList.java0100644 0000000 0000000 00000003612 13513104763 020365 0ustar000000000 0000000 /* * 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.javax.sip.header; import java.util.List; import javax.sip.header.*; /** * List of Reason headers. * @version 1.2 $Revision: 1.6 $ $Date: 2009/07/17 18:57:35 $ * * @author M. Ranganathan
    * * */ public final class ReasonList extends SIPHeaderList { private static final long serialVersionUID = 7459989997463160670L; public Object clone() { ReasonList retval = new ReasonList(); retval.clonehlist(this.hlist); return retval; } /** Default constructor */ public ReasonList() { super(Reason.class, ReasonHeader.NAME); } } java/gov/nist/javax/sip/header/RecordRoute.java0100644 0000000 0000000 00000005467 13513104763 020551 0ustar000000000 0000000 /* * 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.javax.sip.header; import gov.nist.javax.sip.address.*; /** * 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.6 $ $Date: 2009/07/17 18:57:35 $ * *@author M. Ranganathan
    * * * */ public class RecordRoute extends AddressParametersHeader implements javax.sip.header.RecordRouteHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = 2388023364181727205L; /** * constructor * @param address address to set */ public RecordRoute(AddressImpl address) { super(NAME); this.address = address; } /** * default constructor */ public RecordRoute() { super(RECORD_ROUTE); } /** Encode into canonical form. *@return String containing the canonicaly encoded header. */ public String encodeBody() { return encodeBody(new StringBuffer()).toString(); } protected StringBuffer encodeBody(StringBuffer buffer) { if (address.getAddressType() == AddressImpl.ADDRESS_SPEC) { buffer.append(LESS_THAN); } address.encode(buffer); if (address.getAddressType() == AddressImpl.ADDRESS_SPEC) { buffer.append(GREATER_THAN); } if (!parameters.isEmpty()) { buffer.append(SEMICOLON); this.parameters.encode(buffer); } return buffer; } } java/gov/nist/javax/sip/header/RecordRouteList.java0100644 0000000 0000000 00000003665 13513104763 021403 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.header.*; /** * RecordRoute List of SIP headers (a collection of Addresses) * * @version 1.2 $Revision: 1.6 $ $Date: 2009/07/17 18:57:35 $ * * @author M. Ranganathan
    * * * */ public class RecordRouteList extends SIPHeaderList { private static final long serialVersionUID = 1724940469426766691L; public Object clone() { RecordRouteList retval = new RecordRouteList(); retval.clonehlist(this.hlist); return retval; } /** Default constructor */ public RecordRouteList() { super(RecordRoute.class, RecordRouteHeader.NAME); } } java/gov/nist/javax/sip/header/ReferTo.java0100644 0000000 0000000 00000011667 13513104763 017661 0ustar000000000 0000000 /* * 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.javax.sip.header; import gov.nist.javax.sip.address.*; /** * ReferTo SIP Header. * * @version 1.2 $Revision: 1.6 $ $Date: 2009/07/17 18:57:35 $ * * @author M. Ranganathan
    * @author Olivier Deruelle
    * * * */ public final class ReferTo extends AddressParametersHeader implements javax.sip.header.ReferToHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -1666700428440034851L; /** default Constructor. */ public ReferTo() { super(NAME); } /** * Encode the header content into a String. * @return String */ protected String encodeBody() { if (address == null) return null; String retval = ""; if (address.getAddressType() == AddressImpl.ADDRESS_SPEC) { retval += LESS_THAN; } retval += address.encode(); if (address.getAddressType() == AddressImpl.ADDRESS_SPEC) { retval += GREATER_THAN; } if (!parameters.isEmpty()) { retval += SEMICOLON + parameters.encode(); } return retval; } } /* * $Log: ReferTo.java,v $ * 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: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:26 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.3 2004/01/22 13:26:29 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/header/ReplyTo.java0100644 0000000 0000000 00000013227 13513104763 017703 0ustar000000000 0000000 /* * 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.javax.sip.header; import gov.nist.core.*; import gov.nist.javax.sip.address.*; import javax.sip.header.*; /** * ReplyTo Header. * * @version 1.2 $Revision: 1.5 $ $Date: 2009/07/17 18:57:36 $ * * @author M. Ranganathan
    * @author Olivier Deruelle
    * * * */ public final class ReplyTo extends AddressParametersHeader implements ReplyToHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -9103698729465531373L; /** Default constructor */ public ReplyTo() { super(NAME); } /** Default constructor given an address. * *@param address -- address of this header. * */ public ReplyTo(AddressImpl address) { super(NAME); this.address = address; } /** * Encode the header into a String. * @return String */ public String encode() { return headerName + COLON + SP + encodeBody() + NEWLINE; } /** * Encode the header content into a String. * @return String */ public String encodeBody() { String retval = ""; if (address.getAddressType() == AddressImpl.ADDRESS_SPEC) { retval += LESS_THAN; } retval += address.encode(); if (address.getAddressType() == AddressImpl.ADDRESS_SPEC) { retval += GREATER_THAN; } if (!parameters.isEmpty()) { retval += SEMICOLON + parameters.encode(); } return retval; } /** * Conveniance accessor function to get the hostPort field from the address * @return HostPort */ public HostPort getHostPort() { return address.getHostPort(); } /** * Get the display name from the address. * @return String */ public String getDisplayName() { return address.getDisplayName(); } } /* * $Log: ReplyTo.java,v $ * 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: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:26 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.2 2004/01/22 13:26:29 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/header/RequestLine.java0100644 0000000 0000000 00000022135 13513104763 020543 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.address.URI; import gov.nist.javax.sip.address.*; /** * RequestLine of SIP Request. * * @version 1.2 $Revision: 1.8 $ $Date: 2009/09/15 02:55:27 $ * @author M. Ranganathan */ public class RequestLine extends SIPObject implements SipRequestLine { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -3286426172326043129L; /** uri field. Note that this can be a SIP URI or a generic URI * like tel URI. */ protected GenericURI uri; /** method field. */ protected String method; /** sipVersion field */ protected String sipVersion; /** Default constructor */ public RequestLine() { sipVersion = "SIP/2.0"; } /** Encode the request line as a String. * * @return requestLine encoded as a string. */ public String encode() { return encode(new StringBuffer()).toString(); } public StringBuffer encode(StringBuffer buffer) { if (method != null) { buffer.append(method); buffer.append(SP); } if (uri != null) { uri.encode(buffer); buffer.append(SP); } buffer.append(sipVersion); buffer.append(NEWLINE); return buffer; } /* (non-Javadoc) * @see gov.nist.javax.sip.header.SipRequestLine#getUri() */ public GenericURI getUri() { return uri; } /** Constructor given the request URI and the method. */ public RequestLine(GenericURI requestURI, String method) { this.uri = requestURI; this.method = method; this.sipVersion = "SIP/2.0"; } /* (non-Javadoc) * @see gov.nist.javax.sip.header.SipRequestLine#getMethod() */ public String getMethod() { return method; } /* (non-Javadoc) * @see gov.nist.javax.sip.header.SipRequestLine#getSipVersion() */ public String getSipVersion() { return sipVersion; } /* (non-Javadoc) * @see gov.nist.javax.sip.header.SipRequestLine#setUri(gov.nist.javax.sip.address.GenericURI) */ public void setUri(URI uri) { this.uri = (GenericURI)uri; } /* (non-Javadoc) * @see gov.nist.javax.sip.header.SipRequestLine#setMethod(java.lang.String) */ public void setMethod(String method) { this.method = method; } /* (non-Javadoc) * @see gov.nist.javax.sip.header.SipRequestLine#setSipVersion(java.lang.String) */ public void setSipVersion(String version) { this.sipVersion = version; } /* (non-Javadoc) * @see gov.nist.javax.sip.header.SipRequestLine#getVersionMajor() */ public String getVersionMajor() { if (sipVersion == null) return null; String major = null; boolean slash = false; for (int i = 0; i < sipVersion.length(); i++) { if (sipVersion.charAt(i) == '.') break; if (slash) { if (major == null) major = "" + sipVersion.charAt(i); else major += sipVersion.charAt(i); } if (sipVersion.charAt(i) == '/') slash = true; } return major; } /* (non-Javadoc) * @see gov.nist.javax.sip.header.SipRequestLine#getVersionMinor() */ public String getVersionMinor() { if (sipVersion == null) return null; String minor = null; boolean dot = false; for (int i = 0; i < sipVersion.length(); i++) { if (dot) { if (minor == null) minor = "" + sipVersion.charAt(i); else minor += sipVersion.charAt(i); } if (sipVersion.charAt(i) == '.') dot = true; } return minor; } /** * Compare for equality. * *@param other object to compare with. We assume that all fields * are set. */ public boolean equals(Object other) { boolean retval; if (!other.getClass().equals(this.getClass())) { return false; } RequestLine that = (RequestLine) other; try { retval = this.method.equals(that.method) && this.uri.equals(that.uri) && this.sipVersion.equals(that.sipVersion); } catch (NullPointerException ex) { retval = false; } return retval; } public Object clone() { RequestLine retval = (RequestLine) super.clone(); if (this.uri != null) retval.uri = (GenericURI) this.uri.clone(); return retval; } } /* * $Log: RequestLine.java,v $ * 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 StringBuffer instance during the encoding phase. * * Revision 1.5 2006/07/13 09:01:26 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:26 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.3 2005/04/16 20:38:50 dmuresan * Canonical clone() implementations for the GenericObject and GenericObjectList hierarchies * * Revision 1.2 2004/01/22 13:26:29 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/header/Require.java0100644 0000000 0000000 00000012744 13513104763 017724 0ustar000000000 0000000 /* * 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.javax.sip.header; import java.text.ParseException; import javax.sip.header.*; /** * Require SIP Header. * * @version 1.2 $Revision: 1.5 $ $Date: 2009/07/17 18:57:36 $ * * @author M. Ranganathan
    * @author Olivier Deruelle
    * * */ public class Require extends SIPHeader implements RequireHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -3743425404884053281L; /** optionTag field */ protected String optionTag; /** * Default constructor */ public Require() { super(REQUIRE); } /** constructor * @param s String to set */ public Require(String s) { super(REQUIRE); optionTag = s; } /** * Encode in canonical form. * @return String */ public String encodeBody() { return optionTag; } /** * Sets the option tag value to the new supplied optionTag * parameter. * * @param optionTag - the new string value of the option tag. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the optionTag value. */ public void setOptionTag(String optionTag) throws ParseException { if (optionTag == null) throw new NullPointerException( "JAIN-SIP Exception, Require, " + "setOptionTag(), the optionTag parameter is null"); this.optionTag = optionTag; } /** * Gets the option tag of this OptionTag class. * * @return the string that identifies the option tag value. */ public String getOptionTag() { return optionTag; } } /* * $Log: Require.java,v $ * 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: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:26 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.2 2004/01/22 13:26:29 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/header/RequireList.java0100644 0000000 0000000 00000003674 13513104763 020562 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.header.*; /** * List of Require headers. *
     * Require  =  "Require" ":" 1#option-tag
     * 
    * * @version 1.2 $Revision: 1.6 $ $Date: 2009/07/17 18:57:36 $ * * @author M. Ranganathan
    * * */ public final class RequireList extends SIPHeaderList { private static final long serialVersionUID = -1760629092046963213L; public Object clone() { RequireList retval = new RequireList(); retval.clonehlist(this.hlist); return retval; } /** Default constructor */ public RequireList() { super(Require.class, RequireHeader.NAME); } } java/gov/nist/javax/sip/header/RetryAfter.java0100644 0000000 0000000 00000012653 13513104763 020376 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.*; import java.text.ParseException; import javax.sip.header.*; /** * Retry-After SIP Header. * * @version 1.2 $Revision: 1.9 $ $Date: 2009/11/04 17:35:55 $ * * @author M. Ranganathan
    * @author Olivier Deruelle
    * * */ public class RetryAfter extends ParametersHeader implements RetryAfterHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -1029458515616146140L; /** constant DURATION parameter. */ public static final String DURATION = ParameterNames.DURATION; /** duration field */ protected Integer retryAfter = new Integer(0); /** comment field */ protected String comment; /** Default constructor */ public RetryAfter() { super(NAME); } /** Encode body of this into cannonical form. * @return encoded body */ public String encodeBody() { StringBuffer s = new StringBuffer(); if (retryAfter != null) s.append(retryAfter); if (comment != null) s.append(SP + LPAREN + comment + RPAREN); if (!parameters.isEmpty()) { s.append(SEMICOLON + parameters.encode()); } return s.toString(); } /** Boolean function * @return true if comment exist, false otherwise */ public boolean hasComment() { return comment != null; } /** remove comment field */ public void removeComment() { comment = null; } /** remove duration field */ public void removeDuration() { super.removeParameter(DURATION); } /** * Sets the retry after value of the RetryAfterHeader. * The retry after value MUST be greater than zero and * MUST be less than 2**31. * * @param retryAfter - the new retry after value of this RetryAfterHeader * @throws InvalidArgumentException if supplied value is less than zero. * */ public void setRetryAfter(int retryAfter) throws InvalidArgumentException { if (retryAfter < 0) throw new InvalidArgumentException( "invalid parameter " + retryAfter); this.retryAfter = Integer.valueOf(retryAfter); } /** * Gets the retry after value of the RetryAfterHeader. This retry after * value is relative time. * * @return the retry after value of the RetryAfterHeader. * */ public int getRetryAfter() { return retryAfter.intValue(); } /** * Gets the comment of RetryAfterHeader. * * @return the comment of this RetryAfterHeader, return null if no comment * is available. */ public String getComment() { return comment; } /** * Sets the comment value of the RetryAfterHeader. * * @param comment - the new comment string value of the RetryAfterHeader. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the comment. */ public void setComment(String comment) throws ParseException { if (comment == null) throw new NullPointerException("the comment parameter is null"); this.comment = comment; } /** * Sets the duration value of the RetryAfterHeader. The retry after value * MUST be greater than zero and MUST be less than 2**31. * * @param duration - the new duration value of this RetryAfterHeader * @throws InvalidArgumentException if supplied value is less than zero. * */ public void setDuration(int duration) throws InvalidArgumentException { if (duration < 0) throw new InvalidArgumentException("the duration parameter is <0"); this.setParameter(DURATION, duration); } /** * Gets the duration value of the RetryAfterHeader. This duration value * is relative time. * * @return the duration value of the RetryAfterHeader, return zero if not * set. * */ public int getDuration() { if (this.getParameter(DURATION) == null) return -1; else return super.getParameterAsInt(DURATION); } } java/gov/nist/javax/sip/header/Route.java0100644 0000000 0000000 00000006265 13513104763 017407 0ustar000000000 0000000 /* * 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.javax.sip.header; import gov.nist.javax.sip.address.AddressImpl; import javax.sip.header.RouteHeader; /** * Route SIPHeader Object * * @version 1.2 $Revision: 1.6 $ $Date: 2009/07/17 18:57:36 $ * * @author M. Ranganathan
    * * */ public class Route extends AddressParametersHeader implements javax.sip.header.RouteHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = 5683577362998368846L; /** Default constructor */ public Route() { super(NAME); } /** Default constructor given an address. * *@param address -- address of this header. * */ public Route(AddressImpl address) { super(NAME); this.address = address; } /** * Hashcode so this header can be inserted into a set. * *@return the hashcode of the encoded address. */ public int hashCode() { return this.address.getHostPort().encode().toLowerCase().hashCode(); } /** * Encode into canonical form. * Acknowledgement: contains a bug fix for a bug reported by * Laurent Schwizer * *@return a canonical encoding of the header. */ public String encodeBody() { return encodeBody(new StringBuffer()).toString(); } protected StringBuffer encodeBody(StringBuffer buffer) { boolean addrFlag = address.getAddressType() == AddressImpl.NAME_ADDR; if (!addrFlag) { buffer.append('<'); address.encode(buffer); buffer.append('>'); } else { address.encode(buffer); } if (!parameters.isEmpty()) { buffer.append(SEMICOLON); parameters.encode(buffer); } return buffer; } public boolean equals(Object other) { return (other instanceof RouteHeader) && super.equals(other); } } java/gov/nist/javax/sip/header/RouteList.java0100644 0000000 0000000 00000005156 13513104763 020241 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.header.*; import java.util.*; /** * A list of Route Headers. * * @version 1.2 $Revision: 1.8 $ $Date: 2009/07/17 18:57:36 $ * * @author M. Ranganathan
    * * * */ public class RouteList extends SIPHeaderList { private static final long serialVersionUID = 3407603519354809748L; /** default constructor */ public RouteList() { super(Route.class, RouteHeader.NAME); } public Object clone() { RouteList retval = new RouteList(); retval.clonehlist(this.hlist); return retval; } public String encode() { if ( super.hlist.isEmpty()) return ""; else return super.encode(); } /** * Order is important when comparing route lists. */ public boolean equals(Object other) { if (!(other instanceof RouteList)) return false; RouteList that = (RouteList) other; if (this.size() != that.size()) return false; ListIterator it = this.listIterator(); ListIterator it1 = that.listIterator(); while (it.hasNext()) { Route route = (Route) it.next(); Route route1 = (Route) it1.next(); if (!route.equals(route1)) return false; } return true; } } java/gov/nist/javax/sip/header/SIPDate.java0100644 0000000 0000000 00000044217 13513104763 017541 0ustar000000000 0000000 /* * 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.javax.sip.header; import gov.nist.core.*; import java.util.Calendar; import java.util.TimeZone; import java.util.Locale; import java.util.GregorianCalendar; import java.io.Serializable; import java.lang.IllegalArgumentException; /** * Implements a parser class for tracking expiration time * when specified as a Date value. *
    * From the HTTP 1.1 spec
    *14.18 Date
    *
    *   The Date general-header field represents the date and time at which
    *   the message was originated, having the same semantics as orig-date in
    *   RFC 822. The field value is an HTTP-date, as described in section
    *   3.3.1; it MUST be sent in RFC 1123 [8]-date format.
    
    *       Date  = "Date" ":" HTTP-date
    *
    *   An example is
    *
    *       Date: Tue, 15 Nov 1994 08:12:31 GMT
    *
    * *@version 1.2 $Revision: 1.9 $ $Date: 2009/10/18 13:46:33 $ * *@author M. Ranganathan
    * * * * */ public class SIPDate implements Cloneable,Serializable { /** * Comment for serialVersionUID */ private static final long serialVersionUID = 8544101899928346909L; public static final String GMT = "GMT"; public static final String MON = "Mon"; public static final String TUE = "Tue"; public static final String WED = "Wed"; public static final String THU = "Thu"; public static final String FRI = "Fri"; public static final String SAT = "Sat"; public static final String SUN = "Sun"; public static final String JAN = "Jan"; public static final String FEB = "Feb"; public static final String MAR = "Mar"; public static final String APR = "Apr"; public static final String MAY = "May"; public static final String JUN = "Jun"; public static final String JUL = "Jul"; public static final String AUG = "Aug"; public static final String SEP = "Sep"; public static final String OCT = "Oct"; public static final String NOV = "Nov"; public static final String DEC = "Dec"; /** sipWkDay member */ protected String sipWkDay; /** sipMonth member */ protected String sipMonth; /** wkday member */ protected int wkday; /** day member */ protected int day; /** month member */ protected int month; /** year member */ protected int year; /** hour member */ protected int hour; /** minute member */ protected int minute; /** second member */ protected int second; /** javaCal member */ private java.util.Calendar javaCal; /** equality check. * *@return true if the two date fields are equals */ public boolean equals(Object that){ if (that.getClass() != this.getClass())return false; SIPDate other = (SIPDate)that; return this.wkday == other.wkday && this.day == other.day && this.month == other.month && this.year == other.year && this.hour == other.hour && this.minute == other.minute && this.second == other.second; } /** * Initializer, sets all the fields to invalid values. */ public SIPDate() { wkday = -1; day = -1; month = -1; year = -1; hour = -1; minute = -1; second = -1; javaCal = null; } /** * Construct a SIP date from the time offset given in miliseconds * @param timeMillis long to set */ public SIPDate(long timeMillis) { javaCal = new GregorianCalendar( TimeZone.getTimeZone("GMT:0"), Locale.getDefault()); java.util.Date date = new java.util.Date(timeMillis); javaCal.setTime(date); wkday = javaCal.get(Calendar.DAY_OF_WEEK); switch (wkday) { case Calendar.MONDAY : sipWkDay = MON; break; case Calendar.TUESDAY : sipWkDay = TUE; break; case Calendar.WEDNESDAY : sipWkDay = WED; break; case Calendar.THURSDAY : sipWkDay = THU; break; case Calendar.FRIDAY : sipWkDay = FRI; break; case Calendar.SATURDAY : sipWkDay = SAT; break; case Calendar.SUNDAY : sipWkDay = SUN; break; default : InternalErrorHandler.handleException( "No date map for wkday " + wkday); } day = javaCal.get(Calendar.DAY_OF_MONTH); month = javaCal.get(Calendar.MONTH); switch (month) { case Calendar.JANUARY : sipMonth = JAN; break; case Calendar.FEBRUARY : sipMonth = FEB; break; case Calendar.MARCH : sipMonth = MAR; break; case Calendar.APRIL : sipMonth = APR; break; case Calendar.MAY : sipMonth = MAY; break; case Calendar.JUNE : sipMonth = JUN; break; case Calendar.JULY : sipMonth = JUL; break; case Calendar.AUGUST : sipMonth = AUG; break; case Calendar.SEPTEMBER : sipMonth = SEP; break; case Calendar.OCTOBER : sipMonth = OCT; break; case Calendar.NOVEMBER : sipMonth = NOV; break; case Calendar.DECEMBER : sipMonth = DEC; break; default : InternalErrorHandler.handleException( "No date map for month " + month); } year = javaCal.get(Calendar.YEAR); // Bug report by Bruno Konik hour = javaCal.get(Calendar.HOUR_OF_DAY); minute = javaCal.get(Calendar.MINUTE); second = javaCal.get(Calendar.SECOND); } /** * Get canonical string representation. * @return String */ public String encode() { String dayString; if (day < 10) { dayString = "0" + day; } else dayString = "" + day; String hourString; if (hour < 10) { hourString = "0" + hour; } else hourString = "" + hour; String minuteString; if (minute < 10) { minuteString = "0" + minute; } else minuteString = "" + minute; String secondString; if (second < 10) { secondString = "0" + second; } else secondString = "" + second; String encoding = ""; if (sipWkDay != null) encoding += sipWkDay + Separators.COMMA + Separators.SP; encoding += dayString + Separators.SP; if (sipMonth != null) encoding += sipMonth + Separators.SP; encoding += year + Separators.SP + hourString + Separators.COLON + minuteString + Separators.COLON + secondString + Separators.SP + GMT; return encoding; } /** * The only accessor we allow is to the java calendar record. * All other fields are for this package only. * @return Calendar */ public java.util.Calendar getJavaCal() { if (javaCal == null) setJavaCal(); return javaCal; } /** get the WkDay field * @return String */ public String getWkday() { return sipWkDay; } /** get the month * @return String */ public String getMonth() { return sipMonth; } /** get the hour * @return int */ public int getHour() { return hour; } /** get the minute * @return int */ public int getMinute() { return minute; } /** get the second * @return int */ public int getSecond() { return second; } /** * convert the SIP Date of this structure to a Java Date. * SIP Dates are forced to be GMT. Stores the converted time * as a java Calendar class. */ private void setJavaCal() { javaCal = new GregorianCalendar( TimeZone.getTimeZone("GMT:0"), Locale.getDefault()); if (year != -1) javaCal.set(Calendar.YEAR, year); if (day != -1) javaCal.set(Calendar.DAY_OF_MONTH, day); if (month != -1) javaCal.set(Calendar.MONTH, month); if (wkday != -1) javaCal.set(Calendar.DAY_OF_WEEK, wkday); if (hour != -1) javaCal.set(Calendar.HOUR, hour); if (minute != -1) javaCal.set(Calendar.MINUTE, minute); if (second != -1) javaCal.set(Calendar.SECOND, second); } /** * Set the wkday member * @param w String to set * @throws IllegalArgumentException if w is not a valid day. */ public void setWkday(String w) throws IllegalArgumentException { sipWkDay = w; if (sipWkDay.compareToIgnoreCase(MON) == 0) { wkday = Calendar.MONDAY; } else if (sipWkDay.compareToIgnoreCase(TUE) == 0) { wkday = Calendar.TUESDAY; } else if (sipWkDay.compareToIgnoreCase(WED) == 0) { wkday = Calendar.WEDNESDAY; } else if (sipWkDay.compareToIgnoreCase(THU) == 0) { wkday = Calendar.THURSDAY; } else if (sipWkDay.compareToIgnoreCase(FRI) == 0) { wkday = Calendar.FRIDAY; } else if (sipWkDay.compareToIgnoreCase(SAT) == 0) { wkday = Calendar.SATURDAY; } else if (sipWkDay.compareToIgnoreCase(SUN) == 0) { wkday = Calendar.SUNDAY; } else { throw new IllegalArgumentException("Illegal Week day :" + w); } } /** * Set the day member * @param d int to set * @throws IllegalArgumentException if d is not a valid day */ public void setDay(int d) throws IllegalArgumentException { if (d < 1 || d > 31) throw new IllegalArgumentException( "Illegal Day of the month " + Integer.toString(d)); day = d; } /** * Set the month member * @param m String to set. * @throws IllegalArgumentException if m is not a valid month */ public void setMonth(String m) throws IllegalArgumentException { sipMonth = m; if (sipMonth.compareToIgnoreCase(JAN) == 0) { month = Calendar.JANUARY; } else if (sipMonth.compareToIgnoreCase(FEB) == 0) { month = Calendar.FEBRUARY; } else if (sipMonth.compareToIgnoreCase(MAR) == 0) { month = Calendar.MARCH; } else if (sipMonth.compareToIgnoreCase(APR) == 0) { month = Calendar.APRIL; } else if (sipMonth.compareToIgnoreCase(MAY) == 0) { month = Calendar.MAY; } else if (sipMonth.compareToIgnoreCase(JUN) == 0) { month = Calendar.JUNE; } else if (sipMonth.compareToIgnoreCase(JUL) == 0) { month = Calendar.JULY; } else if (sipMonth.compareToIgnoreCase(AUG) == 0) { month = Calendar.AUGUST; } else if (sipMonth.compareToIgnoreCase(SEP) == 0) { month = Calendar.SEPTEMBER; } else if (sipMonth.compareToIgnoreCase(OCT) == 0) { month = Calendar.OCTOBER; } else if (sipMonth.compareToIgnoreCase(NOV) == 0) { month = Calendar.NOVEMBER; } else if (sipMonth.compareToIgnoreCase(DEC) == 0) { month = Calendar.DECEMBER; } else { throw new IllegalArgumentException("Illegal Month :" + m); } } /** * Set the year member * @param y int to set * @throws IllegalArgumentException if y is not a valid year. */ public void setYear(int y) throws IllegalArgumentException { if (y < 0) throw new IllegalArgumentException("Illegal year : " + y); javaCal = null; year = y; } /** * Get the year member. */ public int getYear() { return year; } /** * Set the hour member * @param h int to set * @throws IllegalArgumentException if h is not a valid hour. */ public void setHour(int h) throws IllegalArgumentException { if (h < 0 || h > 24) throw new IllegalArgumentException("Illegal hour : " + h); javaCal = null; hour = h; } /** * Set the minute member * @param m int to set * @throws IllegalArgumentException if m is not a valid minute */ public void setMinute(int m) throws IllegalArgumentException { if (m < 0 || m >= 60) throw new IllegalArgumentException( "Illegal minute : " + (Integer.toString(m))); javaCal = null; minute = m; } /** * Set the second member * @param s int to set * @throws IllegalArgumentException if s is not a valid second */ public void setSecond(int s) throws IllegalArgumentException { if (s < 0 || s >= 60) throw new IllegalArgumentException( "Illegal second : " + Integer.toString(s)); javaCal = null; second = s; } /** Get the time offset from the current time. * *@return offset from the current time. */ public int getDeltaSeconds() { // long ctime = this.getJavaCal().getTimeInMillis(); long ctime = this.getJavaCal().getTime().getTime(); return (int) (ctime - System.currentTimeMillis()) / 1000; } public Object clone() { SIPDate retval; try { retval = (SIPDate) super.clone(); } catch (CloneNotSupportedException e) { throw new RuntimeException("Internal error"); } if (javaCal != null) retval.javaCal = (java.util.Calendar) javaCal.clone(); return retval; } } /* * $Log: SIPDate.java,v $ * 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. * * Revision 1.7 2006/07/13 09:01:16 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:26 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.5 2005/04/16 20:35:10 dmuresan * SIPDate made cloneable. * * Revision 1.4 2004/07/28 14:41:53 mranga * Submitted by: mranga * * fixed equality check for SIPDate. * * Revision 1.3 2004/04/05 21:46:08 mranga * Submitted by: Bruno Konik * Reviewed by: mranga * * Revision 1.2 2004/01/22 13:26:29 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/header/SIPDateHeader.java0100644 0000000 0000000 00000013064 13513104763 020646 0ustar000000000 0000000 /* * 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.javax.sip.header; import java.util.*; import javax.sip.header.*; /** * Date Header. * *@version 1.2 $Revision: 1.6 $ $Date: 2009/07/17 18:57:37 $ * *@author M. Ranganathan
    *@author Olivier Deruelle
    * * */ public class SIPDateHeader extends SIPHeader implements DateHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = 1734186339037274664L; /** date field */ protected SIPDate date; /** Default constructor. */ public SIPDateHeader() { super(DATE); } /** Encode the header into a String. * @return String */ public String encodeBody() { return date.encode(); } /** * Set the date member * @param d SIPDate to set */ public void setDate(SIPDate d) { date = d; } /** * Sets date of DateHeader. The date is repesented by the Calendar object. * * @param dat the Calendar object date of this header. */ public void setDate(Calendar dat) { if (dat != null) date = new SIPDate(dat.getTime().getTime()); } /** * Gets the date of DateHeader. The date is repesented by the Calender * object. * * @return the Calendar object representing the date of DateHeader */ public Calendar getDate() { if (date == null) return null; return date.getJavaCal(); } public Object clone() { SIPDateHeader retval = (SIPDateHeader) super.clone(); if (this.date != null) retval.date = (SIPDate) this.date.clone(); return retval; } } /* * $Log: SIPDateHeader.java,v $ * 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: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:26 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.3 2005/04/16 20:38:50 dmuresan * Canonical clone() implementations for the GenericObject and GenericObjectList hierarchies * * Revision 1.2 2004/01/22 13:26:29 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/header/SIPETag.java0100644 0000000 0000000 00000005646 13513104763 017507 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.header.*; import java.text.ParseException; /** * the SIP-ETag header. * * @author Jeroen van Bemmel
    * @version 1.2 $Revision: 1.3 $ $Date: 2009/07/17 18:57:37 $ * @since 1.2 */ public class SIPETag extends SIPHeader implements SIPETagHeader , ExtensionHeader{ /** * Comment for serialVersionUID */ private static final long serialVersionUID = 3837543366074322107L; /** * entity tag field */ protected String entityTag; /** Default constructor */ public SIPETag() { super(NAME); } public SIPETag( String tag ) throws ParseException { this(); this.setETag( tag ); } /** * Encode into canonical form. * @return String */ public String encodeBody() { return entityTag; } /** * get the priority value. * @return String */ public String getETag() { return entityTag; } /** * Set the priority member * @param etag String to set */ public void setETag(String etag) throws ParseException { if (etag == null) throw new NullPointerException( "JAIN-SIP Exception," + "SIP-ETag, setETag(), the etag parameter is null"); this.entityTag = etag; } /** * This method needs to be added for backwards compatibility to * avoid ClassCast exception on V1.1 applications * * @see javax.sip.header.ExtensionHeader#setValue(java.lang.String) */ public void setValue(String value) throws ParseException { this.setETag(value); } } java/gov/nist/javax/sip/header/SIPHeader.java0100644 0000000 0000000 00000010410 13513104763 020040 0ustar000000000 0000000 /* * 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.javax.sip.header; /** * Root class from which all SIPHeader objects are subclassed. * * @author M. Ranganathan
    * @version 1.2 $Revision: 1.7 $ $Date: 2009/07/17 18:57:37 $ * * */ public abstract class SIPHeader extends SIPObject implements SIPHeaderNames, javax.sip.header.Header, HeaderExt { /** name of this header */ protected String headerName; /** Value of the header. */ /** Constructor * @param hname String to set */ protected SIPHeader(String hname) { headerName = hname; } /** Default constructor */ public SIPHeader() { } /** * Name of the SIPHeader * @return String */ public String getHeaderName() { return headerName; } /** Alias for getHaderName above. * *@return String headerName * */ public String getName() { return this.headerName; } /** * Set the name of the header . * @param hdrname String to set */ public void setHeaderName(String hdrname) { headerName = hdrname; } /** Get the header value (i.e. what follows the name:). * This merely goes through and lops off the portion that follows * the headerName: */ public String getHeaderValue() { String encodedHdr = null; try { encodedHdr = this.encode(); } catch (Exception ex) { return null; } StringBuffer buffer = new StringBuffer(encodedHdr); while (buffer.length() > 0 && buffer.charAt(0) != ':') { buffer.deleteCharAt(0); } if (buffer.length() > 0) buffer.deleteCharAt(0); return buffer.toString().trim(); } /** Return false if this is not a header list * (SIPHeaderList overrrides this method). *@return false */ public boolean isHeaderList() { return false; } /** Encode this header into canonical form. */ public String encode() { return encode(new StringBuffer()).toString(); } public StringBuffer encode(StringBuffer buffer) { buffer.append(this.headerName).append(COLON).append(SP); this.encodeBody(buffer); buffer.append(NEWLINE); return buffer; } /** Encode the body of this header (the stuff that follows headerName). * A.K.A headerValue. */ 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. */ public String getValue() { return this.getHeaderValue(); } /** * This is a pretty simple hashCode but satisfies requirements. * */ public int hashCode() { return this.headerName.hashCode(); } public final String toString() { return this.encode(); } } java/gov/nist/javax/sip/header/SIPHeaderList.java0100644 0000000 0000000 00000043744 13513104763 020714 0ustar000000000 0000000 /* * 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.javax.sip.header; import gov.nist.core.GenericObject; import gov.nist.core.Separators; import gov.nist.javax.sip.header.ims.PrivacyHeader; import javax.sip.header.Header; import java.lang.reflect.Constructor; import java.util.*; /** * * This is the root class for all lists of SIP headers. It imbeds a * SIPObjectList object and extends SIPHeader Lists of ContactSIPObjects etc. * derive from this class. This supports homogeneous lists (all elements in the * 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.15 $ $Date: 2005/10/09 18:47:53 */ public abstract class SIPHeaderList extends SIPHeader implements java.util.List, Header { private static boolean prettyEncode = false; /** * hlist field. */ protected List hlist; private Class myClass; public String getName() { return this.headerName; } private SIPHeaderList() { hlist = new LinkedList(); } /** * Constructor * * @param objclass * Class to set * @param hname * String to set */ protected SIPHeaderList(Class objclass, String hname) { this(); this.headerName = hname; this.myClass = objclass; } /** * Concatenate the list of stuff that we are keeping around and also the * text corresponding to these structures (that we parsed). * * @param objectToAdd */ public boolean add(HDR objectToAdd) { hlist.add((HDR)objectToAdd); return true; } /** * Concatenate the list of stuff that we are keeping around and also the * text corresponding to these structures (that we parsed). * * @param obj * Genericobject to set */ public void addFirst(HDR obj) { hlist.add(0,(HDR) obj); } /** * Add to this list. * * @param sipheader * SIPHeader to add. * @param top * is true if we want to add to the top of the list. */ public void add(HDR sipheader, boolean top) { if (top) this.addFirst(sipheader); else this.add(sipheader); } /** * Concatenate two compatible lists. This appends or prepends the new list * to the end of this list. * * @param other * SIPHeaderList to set * @param topFlag * flag which indicates which end to concatenate * the lists. * @throws IllegalArgumentException * if the two lists are not compatible */ public void concatenate(SIPHeaderList other, boolean topFlag) throws IllegalArgumentException { if (!topFlag) { this.addAll(other); } else { // add given items to the top end of the list. this.addAll(0, other); } } /** * Encode a list of sip headers. Headers are returned in cannonical form. * * @return String encoded string representation of this list of headers. * (Contains string append of each encoded header). */ public String encode() { return encode(new StringBuffer()).toString(); } public StringBuffer encode(StringBuffer buffer) { if (hlist.isEmpty()) { buffer.append(headerName).append(':').append(Separators.NEWLINE); } else { // The following headers do not have comma separated forms for // multiple headers. Thus, they must be encoded separately. if (this.headerName.equals(SIPHeaderNames.WWW_AUTHENTICATE) || this.headerName.equals(SIPHeaderNames.PROXY_AUTHENTICATE) || this.headerName.equals(SIPHeaderNames.AUTHORIZATION) || this.headerName.equals(SIPHeaderNames.PROXY_AUTHORIZATION) || (prettyEncode && (this.headerName.equals(SIPHeaderNames.VIA) || this.headerName.equals(SIPHeaderNames.ROUTE) || this.headerName.equals(SIPHeaderNames.RECORD_ROUTE))) // Less confusing to read || this.getClass().equals( ExtensionHeaderList.class) ) { ListIterator li = hlist.listIterator(); while (li.hasNext()) { HDR sipheader = (HDR) li.next(); sipheader.encode(buffer); } } else { // These can be concatenated together in an comma separated // list. buffer.append(headerName).append(Separators.COLON).append(Separators.SP); this.encodeBody(buffer); buffer.append(Separators.NEWLINE); } } return buffer; } /** * Return a list of encoded strings (one for each sipheader). * * @return LinkedList containing encoded strings in this header list. an * empty list is returned if this header list contains no sip * headers. */ public List getHeadersAsEncodedStrings() { List retval = new LinkedList(); ListIterator li = hlist.listIterator(); while (li.hasNext()) { Header sipheader = li.next(); retval.add(sipheader.toString()); } return retval; } /** * Get the first element of this list. * * @return SIPHeader first element of the list. */ public Header getFirst() { if (hlist == null || hlist.isEmpty()) return null; else return hlist.get(0); } /** * Get the last element of this list. * * @return SIPHeader last element of the list. */ public Header getLast() { if (hlist == null || hlist.isEmpty()) return null; return hlist.get(hlist.size() - 1); } /** * Get the class for the headers of this list. * * @return Class of header supported by this list. */ public Class getMyClass() { return this.myClass; } /** * Empty check * * @return boolean true if list is empty */ public boolean isEmpty() { return hlist.isEmpty(); } /** * Get an initialized iterator for my imbedded list * * @return the generated ListIterator */ public ListIterator listIterator() { return hlist.listIterator(0); } /** * Get the imbedded linked list. * * @return the imedded linked list of SIP headers. */ public List getHeaderList() { return this.hlist; } /** * Get the list iterator for a given position. * * @param position * position for the list iterator to return * @return the generated list iterator */ public ListIterator listIterator(int position) { return hlist.listIterator(position); } /** * Remove the first element of this list. */ public void removeFirst() { if (hlist.size() != 0) hlist.remove(0); } /** * Remove the last element of this list. */ public void removeLast() { if (hlist.size() != 0) hlist.remove(hlist.size() - 1); } /** * Remove a sip header from this list of sip headers. * * @param obj * SIPHeader to remove * @return boolean */ public boolean remove(HDR obj) { if (hlist.size() == 0) return false; else return hlist.remove(obj); } /** * Set the root class for all objects inserted into my list (for assertion * check) * * @param cl * class to set */ protected void setMyClass(Class cl) { this.myClass = cl; } /** * convert to a string representation (for printing). * * @param indentation * int to set * @return String string representation of object (for printing). */ public String debugDump(int indentation) { stringRepresentation = ""; String indent = new Indentation(indentation).getIndentation(); String className = this.getClass().getName(); sprint(indent + className); sprint(indent + "{"); for (Iterator it = hlist.iterator(); it.hasNext();) { HDR sipHeader = (HDR) it.next(); sprint(indent + sipHeader.debugDump()); } sprint(indent + "}"); return stringRepresentation; } /** * convert to a string representation * * @return String */ public String debugDump() { return debugDump(0); } /** * Array conversion. * * @return SIPHeader [] */ public Object[] toArray() { return hlist.toArray(); } /** * index of an element. * * @return index of the given element (-1) if element does not exist. */ public int indexOf(GenericObject gobj) { return hlist.indexOf(gobj); } /** * insert at a location. * * @param index * location where to add the sipHeader. * @param sipHeader * SIPHeader structure to add. */ public void add(int index, HDR sipHeader) throws IndexOutOfBoundsException { hlist.add(index, sipHeader); } /** * Equality comparison operator. * * @param other * the other object to compare with. true is returned iff the * classes match and list of headers herein is equal to the list * of headers in the target (order of the headers is not * important). */ @SuppressWarnings("unchecked") public boolean equals(Object other) { if (other == this) return true; if (other instanceof SIPHeaderList) { SIPHeaderList that = (SIPHeaderList) other; if (this.hlist == that.hlist) return true; else if (this.hlist == null) return that.hlist == null || that.hlist.size() == 0; return this.hlist.equals(that.hlist); } return false; } /** * Template match against a template. null field in template indicates wild * card match. */ public boolean match(SIPHeaderList template) { if (template == null) return true; if (!this.getClass().equals(template.getClass())) return false; SIPHeaderList that = (SIPHeaderList) template; if (this.hlist == that.hlist) return true; else if (this.hlist == null) return false; else { for (Iterator it = that.hlist.iterator(); it.hasNext();) { SIPHeader sipHeader = (SIPHeader) it.next(); boolean found = false; for (Iterator it1 = this.hlist.iterator(); it1.hasNext() && !found;) { SIPHeader sipHeader1 = (SIPHeader) it1.next(); found = sipHeader1.match(sipHeader); } if (!found) return false; } return true; } } /** * make a clone of this header list. * * @return clone of this Header. */ public Object clone() { try { Class clazz = this.getClass(); Constructor cons = clazz.getConstructor((Class[])null); SIPHeaderList retval = (SIPHeaderList) cons.newInstance((Object[])null); retval.headerName = this.headerName; retval.myClass = this.myClass; return retval.clonehlist(this.hlist); } catch (Exception ex) { throw new RuntimeException("Could not clone!", ex); } } protected final SIPHeaderList clonehlist(List hlistToClone) { if (hlistToClone != null) { for (Iterator it = (Iterator) hlistToClone.iterator(); it.hasNext();) { Header h = it.next(); this.hlist.add((HDR)h.clone()); } } return this; } /** * Get the number of headers in the list. */ public int size() { return hlist.size(); } /** * Return true if this is a header list (overrides the base class method * which returns false). * * @return true */ public boolean isHeaderList() { return true; } /** * Encode the body of this header (the stuff that follows headerName). A.K.A * headerValue. This will not give a reasonable result for WWW-Authenticate, * Authorization, Proxy-Authenticate and Proxy-Authorization and hence this * is protected. */ protected String encodeBody() { return encodeBody(new StringBuffer()).toString(); } protected StringBuffer encodeBody(StringBuffer buffer) { ListIterator iterator = this.listIterator(); while (true) { SIPHeader sipHeader = (SIPHeader) iterator.next(); if ( sipHeader == this ) throw new RuntimeException ("Unexpected circularity in SipHeaderList"); sipHeader.encodeBody(buffer); // if (body.equals("")) System.out.println("BODY == "); if (iterator.hasNext()) { if (!this.headerName.equals(PrivacyHeader.NAME)) buffer.append(Separators.COMMA); else buffer.append(Separators.SEMICOLON); continue; } else break; } return buffer; } public boolean addAll(Collection collection) { return this.hlist.addAll(collection); } public boolean addAll(int index, Collection collection) { return this.hlist.addAll(index, collection); } public boolean containsAll(Collection collection) { return this.hlist.containsAll(collection); } public void clear() { this.hlist.clear(); } public boolean contains(Object header) { return this.hlist.contains(header); } /** * Get the object at the specified location. * * @param index -- * location from which to get the object. * */ public HDR get(int index) { return this.hlist.get(index); } /** * Return the index of a given object. * * @param obj -- * object whose index to compute. */ public int indexOf(Object obj) { return this.hlist.indexOf(obj); } /** * Return the iterator to the imbedded list. * * @return iterator to the imbedded list. * */ public java.util.Iterator iterator() { return this.hlist.listIterator(); } /** * Get the last index of the given object. * * @param obj -- * object whose index to find. */ public int lastIndexOf(Object obj) { return this.hlist.lastIndexOf(obj); } /** * Remove the given object. * * @param obj -- * object to remove. * */ public boolean remove(Object obj) { return this.hlist.remove(obj); } /** * Remove the object at a given index. * * @param index -- * index at which to remove the object */ public HDR remove(int index) { return this.hlist.remove(index); } /** * Remove all the elements. * @see List#removeAll(java.util.Collection) */ public boolean removeAll(java.util.Collection collection) { return this.hlist.removeAll(collection); } /** * @see List#retainAll(java.util.Collection) * @param collection */ public boolean retainAll(java.util.Collection collection) { return this.hlist.retainAll(collection); } /** * Get a sublist of the list. * * @see List#subList(int, int) */ public java.util.List subList(int index1, int index2) { return this.hlist.subList(index1, index2); } /** * @see Object#hashCode() * @return -- the computed hashcode. */ public int hashCode() { return this.headerName.hashCode(); } /** * Set a SIPHeader at a particular position in the list. * * @see List#set(int, java.lang.Object) */ public HDR set(int position, HDR sipHeader) { return hlist.set(position, sipHeader); } public static void setPrettyEncode(boolean flag) { prettyEncode = flag; } public T[] toArray(T[] array) { return this.hlist.toArray(array); } } java/gov/nist/javax/sip/header/SIPHeaderNames.java0100644 0000000 0000000 00000013226 13513104763 021034 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.header.*; import gov.nist.javax.sip.header.extensions.*; /** * SIPHeader names that are supported by this parser * * @version 1.2 $Revision: 1.9 $ $Date: 2009/07/17 18:57:37 $ * * @author M. Ranganathan
    * * */ public interface SIPHeaderNames { public static final String MIN_EXPIRES = MinExpiresHeader.NAME; //1 public static final String ERROR_INFO = ErrorInfoHeader.NAME; //2 public static final String MIME_VERSION = MimeVersionHeader.NAME; //3 public static final String IN_REPLY_TO = InReplyToHeader.NAME; //4 public static final String ALLOW = AllowHeader.NAME; //5 public static final String CONTENT_LANGUAGE = ContentLanguageHeader.NAME; //6 public static final String CALL_INFO = CallInfoHeader.NAME; //7 public static final String CSEQ = CSeqHeader.NAME; //8 public static final String ALERT_INFO = AlertInfoHeader.NAME; //9 public static final String ACCEPT_ENCODING = AcceptEncodingHeader.NAME; //10 public static final String ACCEPT = AcceptHeader.NAME; //11 public static final String ACCEPT_LANGUAGE = AcceptLanguageHeader.NAME; //12 public static final String RECORD_ROUTE = RecordRouteHeader.NAME; //13 public static final String TIMESTAMP = TimeStampHeader.NAME; //14 public static final String TO = ToHeader.NAME; //15 public static final String VIA = ViaHeader.NAME; //16 public static final String FROM = FromHeader.NAME; //17 public static final String CALL_ID = CallIdHeader.NAME; //18 public static final String AUTHORIZATION = AuthorizationHeader.NAME; //19 public static final String PROXY_AUTHENTICATE = ProxyAuthenticateHeader.NAME; //20 public static final String SERVER = ServerHeader.NAME; //21 public static final String UNSUPPORTED = UnsupportedHeader.NAME; //22 public static final String RETRY_AFTER = RetryAfterHeader.NAME; //23 public static final String CONTENT_TYPE = ContentTypeHeader.NAME; //24 public static final String CONTENT_ENCODING = ContentEncodingHeader.NAME; //25 public static final String CONTENT_LENGTH = ContentLengthHeader.NAME; //26 public static final String ROUTE = RouteHeader.NAME; //27 public static final String CONTACT = ContactHeader.NAME; //28 public static final String WWW_AUTHENTICATE = WWWAuthenticateHeader.NAME; //29 public static final String MAX_FORWARDS = MaxForwardsHeader.NAME; //30 public static final String ORGANIZATION = OrganizationHeader.NAME; //31 public static final String PROXY_AUTHORIZATION = ProxyAuthorizationHeader.NAME; //32 public static final String PROXY_REQUIRE = ProxyRequireHeader.NAME; //33 public static final String REQUIRE = RequireHeader.NAME; //34 public static final String CONTENT_DISPOSITION = ContentDispositionHeader.NAME; //35 public static final String SUBJECT = SubjectHeader.NAME; //36 public static final String USER_AGENT = UserAgentHeader.NAME; //37 public static final String WARNING = WarningHeader.NAME; //38 public static final String PRIORITY = PriorityHeader.NAME; //39 public static final String DATE = DateHeader.NAME; //40 public static final String EXPIRES = ExpiresHeader.NAME; //41 public static final String SUPPORTED = SupportedHeader.NAME; //42 public static final String AUTHENTICATION_INFO = AuthenticationInfoHeader.NAME; //43 public static final String REPLY_TO = ReplyToHeader.NAME; //44 public static final String RACK = RAckHeader.NAME; //45 public static final String RSEQ = RSeqHeader.NAME; //46 public static final String REASON = ReasonHeader.NAME; //47 public static final String SUBSCRIPTION_STATE = SubscriptionStateHeader.NAME; //48 public static final String EVENT = EventHeader.NAME; //44 public static final String ALLOW_EVENTS = AllowEventsHeader.NAME; //45 public static final String SIP_ETAG = SIPETagHeader.NAME; //46 public static final String SIP_IF_MATCH = SIPIfMatchHeader.NAME; //47 // NewHeights pmusgrave public static final String REFERRED_BY = ReferredByHeader.NAME; //48 public static final String SESSION_EXPIRES = SessionExpiresHeader.NAME; //49 public static final String MIN_SE = MinSEHeader.NAME; //50 public static final String REPLACES = ReplacesHeader.NAME; //51 public static final String JOIN = JoinHeader.NAME; //52 } java/gov/nist/javax/sip/header/SIPHeaderNamesCache.java0100644 0000000 0000000 00000002217 13513104763 021756 0ustar000000000 0000000 package gov.nist.javax.sip.header; import java.util.HashMap; import java.lang.reflect.Field; import java.lang.reflect.Modifier; /** * @author yanick.belanger */ public abstract class SIPHeaderNamesCache { private static final HashMap lowercaseMap = new HashMap(); static { Field[] fields = SIPHeaderNames.class.getFields(); for (int i = 0; i < fields.length; i++) { Field field = fields[i]; if (field.getType().equals(String.class) && Modifier.isStatic(field.getModifiers())) { try { String value = (String) field.get(null); String lowerCase = value.toLowerCase(); lowercaseMap.put(value, lowerCase); lowercaseMap.put(lowerCase, lowerCase); } catch (IllegalAccessException e) { } } } } public static String toLowerCase(String headerName) { String lowerCase = (String) lowercaseMap.get(headerName); if (lowerCase == null) { return headerName.toLowerCase(); } else { return lowerCase; } } } java/gov/nist/javax/sip/header/SIPIfMatch.java0100644 0000000 0000000 00000005525 13513104763 020176 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.header.*; import java.text.ParseException; /** * the SIP-If-Match header. * * @author Jeroen van Bemmel
    * @version 1.2 $Revision: 1.3 $ $Date: 2009/07/17 18:57:38 $ * @since 1.2 */ public class SIPIfMatch extends SIPHeader implements SIPIfMatchHeader,ExtensionHeader { /** * unique serial id */ private static final long serialVersionUID = 3833745477828359730L; /** * entity tag field */ protected String entityTag; /** Default constructor */ public SIPIfMatch() { super(NAME); } public SIPIfMatch(String etag) throws ParseException { this(); this.setETag( etag ); } /** * Encode into canonical form. * @return String */ public String encodeBody() { return entityTag; } /** * get the priority value. * @return String */ public String getETag() { return entityTag; } /** * Set the priority member * @param etag -- the entity tag to set. */ public void setETag(String etag) throws ParseException { if (etag == null) throw new NullPointerException( "JAIN-SIP Exception," + "SIP-If-Match, setETag(), the etag parameter is null"); this.entityTag = etag; } /** * For v 1.1 backwards compatibility. * @see javax.sip.header.ExtensionHeader#setValue(java.lang.String) */ public void setValue(String value) throws ParseException { this.setETag(value); } } java/gov/nist/javax/sip/header/SIPObject.java0100644 0000000 0000000 00000040652 13513104763 020071 0ustar000000000 0000000 /* * 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.javax.sip.header; import gov.nist.core.GenericObject; import gov.nist.core.GenericObjectList; import gov.nist.core.InternalErrorHandler; import java.lang.reflect.Field; import java.lang.reflect.Modifier; /** * Root class for all singleton objects in this package: * specializes the gov.nist.sip.header.GenericObject class for SIPHeader * related objects. * * @version 1.2 $Revision: 1.10 $ $Date: 2009/07/17 18:57:38 $ * * @author M. Ranganathan
    * * * */ public abstract class SIPObject extends GenericObject { /** default Constructor */ protected SIPObject() { super(); } /** Debug function */ public void dbgPrint() { super.dbgPrint(); } /** Encode the header into a String. * @return String */ public abstract String encode(); /** Encode the header into the given StringBuffer. * Default implemation calls encode(). */ public StringBuffer encode(StringBuffer buffer) { return buffer.append(encode()); } /** * An introspection based equality predicate for SIPObjects. *@param other the other object to test against. */ public boolean equals(Object other) { if (!this.getClass().equals(other.getClass())) return false; SIPObject that = (SIPObject) other; Class myclass = this.getClass(); Class hisclass = other.getClass(); while (true) { Field[] fields = myclass.getDeclaredFields(); if (!hisclass.equals(myclass)) return false; Field[] hisfields = hisclass.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { Field f = fields[i]; Field g = hisfields[i]; // Only print protected and public members. int modifier = f.getModifiers(); if ((modifier & Modifier.PRIVATE) == Modifier.PRIVATE) continue; Class fieldType = f.getType(); String fieldName = f.getName(); if (fieldName.compareTo("stringRepresentation") == 0) { continue; } if (fieldName.compareTo("indentation") == 0) { continue; } try { // Primitive fields are printed with type: value if (fieldType.isPrimitive()) { String fname = fieldType.toString(); if (fname.compareTo("int") == 0) { if (f.getInt(this) != g.getInt(that)) return false; } else if (fname.compareTo("short") == 0) { if (f.getShort(this) != g.getShort(that)) return false; } else if (fname.compareTo("char") == 0) { if (f.getChar(this) != g.getChar(that)) return false; } else if (fname.compareTo("long") == 0) { if (f.getLong(this) != g.getLong(that)) return false; } else if (fname.compareTo("boolean") == 0) { if (f.getBoolean(this) != g.getBoolean(that)) return false; } else if (fname.compareTo("double") == 0) { if (f.getDouble(this) != g.getDouble(that)) return false; } else if (fname.compareTo("float") == 0) { if (f.getFloat(this) != g.getFloat(that)) return false; } } else if (g.get(that) == f.get(this)) continue; else if (f.get(this) == null && g.get(that) != null) return false; else if (g.get(that) == null && f.get(this) != null) return false; else if (!f.get(this).equals(g.get(that))) return false; } catch (IllegalAccessException ex1) { System.out.println("accessed field " + fieldName); System.out.println("modifier " + modifier); System.out.println("modifier.private " + Modifier.PRIVATE); InternalErrorHandler.handleException(ex1); } } if (myclass.equals(SIPObject.class)) break; else { myclass = myclass.getSuperclass(); hisclass = hisclass.getSuperclass(); } } return true; } /** An introspection based predicate matching using a template * object. Allows for partial match of two protocl Objects. * You can set a generalized matcher (using regular expressions * for example) by implementing the Match interface and registering * it with the template. *@param other the match pattern to test against. The match object * has to be of the same type (class). Primitive types * and non-sip fields that are non null are matched for equality. * Null in any field matches anything. Some book-keeping fields * are ignored when making the comparison. * */ public boolean match(Object other) { if (other == null) { return true; } if (!this.getClass().equals(other.getClass())) return false; GenericObject that = (GenericObject) other; Class myclass = this.getClass(); Class hisclass = other.getClass(); while (true) { Field[] fields = myclass.getDeclaredFields(); Field[] hisfields = hisclass.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { Field f = fields[i]; Field g = hisfields[i]; // Only print protected and public members. int modifier = f.getModifiers(); if ((modifier & Modifier.PRIVATE) == Modifier.PRIVATE) continue; Class fieldType = f.getType(); String fieldName = f.getName(); if (fieldName.compareTo("stringRepresentation") == 0) { continue; } if (fieldName.compareTo("indentation") == 0) { continue; } try { if (fieldType.isPrimitive()) { String fname = fieldType.toString(); if (fname.compareTo("int") == 0) { if (f.getInt(this) != g.getInt(that)) return false; } else if (fname.compareTo("short") == 0) { if (f.getShort(this) != g.getShort(that)) return false; } else if (fname.compareTo("char") == 0) { if (f.getChar(this) != g.getChar(that)) return false; } else if (fname.compareTo("long") == 0) { if (f.getLong(this) != g.getLong(that)) return false; } else if (fname.compareTo("boolean") == 0) { if (f.getBoolean(this) != g.getBoolean(that)) return false; } else if (fname.compareTo("double") == 0) { if (f.getDouble(this) != g.getDouble(that)) return false; } else if (fname.compareTo("float") == 0) { if (f.getFloat(this) != g.getFloat(that)) return false; } else { InternalErrorHandler.handleException( "unknown type"); } } else { Object myObj = f.get(this); Object hisObj = g.get(that); if (hisObj != null && myObj == null) return false; else if (hisObj == null && myObj != null) continue; else if (hisObj == null && myObj == null) continue; else if ( hisObj instanceof java.lang.String && myObj instanceof java.lang.String) { if ((((String) hisObj).trim()).equals("")) continue; if (((String) myObj) .compareToIgnoreCase((String) hisObj) != 0) return false; } else if ( hisObj != null && GenericObject.isMySubclass(myObj.getClass()) && GenericObject.isMySubclass(hisObj.getClass()) && myObj.getClass().equals(hisObj.getClass()) && ((GenericObject) hisObj).getMatcher() != null) { String myObjEncoded = ((GenericObject) myObj).encode(); boolean retval = ((GenericObject) hisObj).getMatcher().match( myObjEncoded); if (!retval) return false; } else if ( GenericObject.isMySubclass(myObj.getClass()) && !((GenericObject) myObj).match(hisObj)) return false; else if ( GenericObjectList.isMySubclass(myObj.getClass()) && !((GenericObjectList) myObj).match(hisObj)) return false; } } catch (IllegalAccessException ex1) { InternalErrorHandler.handleException(ex1); } } if (myclass.equals(SIPObject.class)) break; else { myclass = myclass.getSuperclass(); hisclass = hisclass.getSuperclass(); } } return true; } /** * An introspection based string formatting method. We need this because * in this package (although it is an exact duplicate of the one in * the superclass) because it needs to access the protected members * of the other objects in this class. * @return String */ public String debugDump() { stringRepresentation = ""; Class myclass = getClass(); sprint(myclass.getName()); sprint("{"); Field[] fields = myclass.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { Field f = fields[i]; // Only print protected and public members. int modifier = f.getModifiers(); if ((modifier & Modifier.PRIVATE) == Modifier.PRIVATE) continue; Class fieldType = f.getType(); String fieldName = f.getName(); if (fieldName.compareTo("stringRepresentation") == 0) { // avoid nasty recursions... continue; } if (fieldName.compareTo("indentation") == 0) { // formatting stuff - not relevant here. continue; } sprint(fieldName + ":"); try { // Primitive fields are printed with type: value if (fieldType.isPrimitive()) { String fname = fieldType.toString(); sprint(fname + ":"); if (fname.compareTo("int") == 0) { int intfield = f.getInt(this); sprint(intfield); } else if (fname.compareTo("short") == 0) { short shortField = f.getShort(this); sprint(shortField); } else if (fname.compareTo("char") == 0) { char charField = f.getChar(this); sprint(charField); } else if (fname.compareTo("long") == 0) { long longField = f.getLong(this); sprint(longField); } else if (fname.compareTo("boolean") == 0) { boolean booleanField = f.getBoolean(this); sprint(booleanField); } else if (fname.compareTo("double") == 0) { double doubleField = f.getDouble(this); sprint(doubleField); } else if (fname.compareTo("float") == 0) { float floatField = f.getFloat(this); sprint(floatField); } } else if (GenericObject.class.isAssignableFrom(fieldType)) { if (f.get(this) != null) { sprint( ((GenericObject) f.get(this)).debugDump( indentation + 1)); } else { sprint(""); } } else if ( GenericObjectList.class.isAssignableFrom(fieldType)) { if (f.get(this) != null) { sprint( ((GenericObjectList) f.get(this)).debugDump( indentation + 1)); } else { sprint(""); } } else { // Dont do recursion on things that are not // of our header type... if (f.get(this) != null) { sprint(f.get(this).getClass().getName() + ":"); } else { sprint(fieldType.getName() + ":"); } sprint("{"); if (f.get(this) != null) { sprint(f.get(this).toString()); } else { sprint(""); } sprint("}"); } } catch (IllegalAccessException ex1) { continue; // we are accessing a private field... } } sprint("}"); return stringRepresentation; } /** * Formatter with a given starting indentation (for nested structs). * @param indent int to set * @return String */ public String debugDump(int indent) { int save = indentation; indentation = indent; String retval = this.debugDump(); indentation = save; return retval; } public String toString() { return this.encode(); } } java/gov/nist/javax/sip/header/SIPObjectList.java0100644 0000000 0000000 00000010374 13513104763 020723 0ustar000000000 0000000 /* * 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.javax.sip.header; import java.util.ListIterator; import java.util.LinkedList; import java.util.Iterator; import java.lang.reflect.*; import gov.nist.core.*; /** * Root class for all the collection objects in this list: * a wrapper class on the GenericObjectList class for lists of objects * that can appear in SIPObjects. * IMPORTANT NOTE: SIPObjectList cannot derive from SIPObject. * * @version 1.2 $Revision: 1.7 $ $Date: 2009/07/17 18:57:38 $ * * @author M. Ranganathan
    * * */ public class SIPObjectList extends GenericObjectList { private static final long serialVersionUID = -3015154738977508905L; /** * Construct a SIPObject List given a list name. * @param lname String to set */ public SIPObjectList(String lname) { super(lname); } /** * Construct an empty SIPObjectList. */ public SIPObjectList() { super(); } /** * Do a merge of the GenericObjects contained in this list with the * GenericObjects in the mergeList. Note that this does an inplace * modification of the given list. This does an object by object * merge of the given objects. * *@param mergeList is the list of Generic objects that we want to do * an object by object merge with. Note that no new objects are * added to this list. * */ public void mergeObjects(GenericObjectList mergeList) { Iterator it1 = this.listIterator(); Iterator it2 = mergeList.listIterator(); while (it1.hasNext()) { GenericObject outerObj = (GenericObject) it1.next(); while (it2.hasNext()) { Object innerObj = it2.next(); outerObj.merge(innerObj); } } } /** * Append a given list to the end of this list. * @param otherList SIPObjectList to set */ public void concatenate(SIPObjectList otherList) { super.concatenate(otherList); } /** * Append or prepend a given list to this list. * @param otherList SIPObjectList to set * @param topFlag boolean to set */ public void concatenate(SIPObjectList otherList, boolean topFlag) { super.concatenate(otherList, topFlag); } /** * Get the first object of this list. * @return GenericObject */ public GenericObject first() { return (SIPObject) super.first(); } /** * Get the next object of this list (assumes that first() has been * called prior to calling this method.) * @return GenericObject */ public GenericObject next() { return (SIPObject) super.next(); } /** * Convert to a string given an indentation(for pretty printing). * This is useful for debugging the system in lieu of a debugger. * * @param indent int to set * @return an indentation */ public String debugDump(int indent) { return super.debugDump(indent); } } java/gov/nist/javax/sip/header/Server.java0100644 0000000 0000000 00000014131 13513104763 017546 0ustar000000000 0000000 /* * 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.javax.sip.header; import java.text.ParseException; import javax.sip.header.*; import java.util.*; /** * Supported SIP Header. * * @version 1.2 $Revision: 1.5 $ $Date: 2009/07/17 18:57:38 $ * * @author M. Ranganathan
    * @author Olivier Deruelle
    * * * */ public class Server extends SIPHeader implements ServerHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -3587764149383342973L; /** Product tokens. */ protected List productTokens; /** * Return canonical form. * @return String */ private String encodeProduct() { StringBuffer tokens = new StringBuffer(); ListIterator it = productTokens.listIterator(); while (it.hasNext()) { tokens.append((String) it.next()); if (it.hasNext()) tokens.append('/'); else break; } return tokens.toString(); } /** set the productToken field * @param pt String to set */ public void addProductToken(String pt) { productTokens.add(pt); } /** * Constructor. */ public Server() { super(NAME); productTokens = new LinkedList(); } /** Encode only the body of this header. *@return encoded value of the header. */ public String encodeBody() { return encodeProduct(); } /** * Returns the list value of the product parameter. * * @return the software of this UserAgentHeader */ public ListIterator getProduct() { if (productTokens == null || productTokens.isEmpty()) return null; else return productTokens.listIterator(); } /** * Sets the product value of the UserAgentHeader. * * @param product - a List specifying the product value * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the product value. */ public void setProduct(List product) throws ParseException { if (product == null) throw new NullPointerException( "JAIN-SIP Exception, UserAgent, " + "setProduct(), the " + " product parameter is null"); productTokens = product; } } /* * $Log: Server.java,v $ * 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: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.2 2004/01/22 13:26:29 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/header/SipRequestLine.java0100644 0000000 0000000 00000002265 13513104763 021221 0ustar000000000 0000000 package gov.nist.javax.sip.header; import javax.sip.address.URI; /** * The SIP Request Line. * * @since 2.0 */ public interface SipRequestLine { /** get the Request-URI. * * @return the request URI */ public abstract URI getUri(); /** * Get the Method * * @return method string. */ public abstract String getMethod(); /** * Get the SIP version. * * @return String */ public abstract String getSipVersion(); /** * Set the URI. * * @param uri URI to set. */ public abstract void setUri(URI uri); /** * Set the method member * * @param method String to set */ public abstract void setMethod(String method); /** * Set the sipVersion member * * @param s String to set */ public abstract void setSipVersion(String version); /** * Get the major verrsion number. * *@return String major version number */ public abstract String getVersionMajor(); /** * Get the minor version number. * *@return String minor version number * */ public abstract String getVersionMinor(); } java/gov/nist/javax/sip/header/SipStatusLine.java0100644 0000000 0000000 00000002244 13513104763 021051 0ustar000000000 0000000 package gov.nist.javax.sip.header; /** * The SIP Status line. * * @since 2.0 */ public interface SipStatusLine { /** get the Sip Version * @return SipVersion */ public abstract String getSipVersion(); /** get the Status Code * @return StatusCode */ public abstract int getStatusCode(); /** get the ReasonPhrase field * @return ReasonPhrase field */ public abstract String getReasonPhrase(); /** * Set the sipVersion member * @param sipVersion String to set */ public abstract void setSipVersion(String sipVersion); /** * Set the statusCode member * @param statusCode int to set */ public abstract void setStatusCode(int statusCode); /** * Set the reasonPhrase member * @param reasonPhrase String to set */ public abstract void setReasonPhrase(String reasonPhrase); /** * Get the major version number. *@return String major version number */ public abstract String getVersionMajor(); /** * Get the minor version number. *@return String minor version number */ public abstract String getVersionMinor(); } java/gov/nist/javax/sip/header/StatusLine.java0100644 0000000 0000000 00000022305 13513104763 020375 0ustar000000000 0000000 /* * 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.javax.sip.header; import gov.nist.javax.sip.SIPConstants; /** * Status Line (for SIPReply) messages. * * @version 1.2 $Revision: 1.7 $ $Date: 2009/10/18 13:46:34 $ * * @author M. Ranganathan
    * * */ public final class StatusLine extends SIPObject implements SipStatusLine { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -4738092215519950414L; protected boolean matchStatusClass; /** sipVersion field */ protected String sipVersion; /** status code field */ protected int statusCode; /** reasonPhrase field */ protected String reasonPhrase; /** Match with a template. * Match only the response class if the last two digits of the * match templates are 0's */ public boolean match(Object matchObj) { if (!(matchObj instanceof StatusLine)) return false; StatusLine sl = (StatusLine) matchObj; // A pattern matcher has been registered. if (sl.matchExpression != null) return sl.matchExpression.match(this.encode()); // no patter matcher has been registered.. if (sl.sipVersion != null && !sl.sipVersion.equals(sipVersion)) return false; if (sl.statusCode != 0) { if (matchStatusClass) { int hiscode = sl.statusCode; String codeString = Integer.toString(sl.statusCode); String mycode = Integer.toString(statusCode); if (codeString.charAt(0) != mycode.charAt(0)) return false; } else { if (statusCode != sl.statusCode) return false; } } if (sl.reasonPhrase == null || reasonPhrase == sl.reasonPhrase) return true; return reasonPhrase.equals(sl.reasonPhrase); } /** set the flag on a match template. *If this set to true, then the whole status code is matched (default * behavior) else only the class of the response is matched. */ public void setMatchStatusClass(boolean flag) { matchStatusClass = flag; } /** Default Constructor */ public StatusLine() { reasonPhrase = null; sipVersion = SIPConstants.SIP_VERSION_STRING; } /** * Encode into a canonical form. * @return String */ public String encode() { String encoding = SIPConstants.SIP_VERSION_STRING + SP + statusCode; if (reasonPhrase != null) encoding += SP + reasonPhrase; encoding += NEWLINE; return encoding; } /* (non-Javadoc) * @see gov.nist.javax.sip.header.SipStatusLine#getSipVersion() */ public String getSipVersion() { return sipVersion; } /* (non-Javadoc) * @see gov.nist.javax.sip.header.SipStatusLine#getStatusCode() */ public int getStatusCode() { return statusCode; } /* (non-Javadoc) * @see gov.nist.javax.sip.header.SipStatusLine#getReasonPhrase() */ public String getReasonPhrase() { return reasonPhrase; } /* (non-Javadoc) * @see gov.nist.javax.sip.header.SipStatusLine#setSipVersion(java.lang.String) */ public void setSipVersion(String s) { sipVersion = s; } /* (non-Javadoc) * @see gov.nist.javax.sip.header.SipStatusLine#setStatusCode(int) */ public void setStatusCode(int statusCode) { this.statusCode = statusCode; } /* (non-Javadoc) * @see gov.nist.javax.sip.header.SipStatusLine#setReasonPhrase(java.lang.String) */ public void setReasonPhrase(String reasonPhrase) { this.reasonPhrase = reasonPhrase; } /* (non-Javadoc) * @see gov.nist.javax.sip.header.SipStatusLine#getVersionMajor() */ public String getVersionMajor() { if (sipVersion == null) return null; String major = null; boolean slash = false; for (int i = 0; i < sipVersion.length(); i++) { if (sipVersion.charAt(i) == '.') slash = false; if (slash) { if (major == null) major = "" + sipVersion.charAt(i); else major += sipVersion.charAt(i); } if (sipVersion.charAt(i) == '/') slash = true; } return major; } /* (non-Javadoc) * @see gov.nist.javax.sip.header.SipStatusLine#getVersionMinor() */ public String getVersionMinor() { if (sipVersion == null) return null; String minor = null; boolean dot = false; for (int i = 0; i < sipVersion.length(); i++) { if (dot) { if (minor == null) minor = "" + sipVersion.charAt(i); else minor += sipVersion.charAt(i); } if (sipVersion.charAt(i) == '.') dot = true; } return minor; } } /* * $Log: StatusLine.java,v $ * Revision 1.7 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.6 2009/09/15 02:55:26 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.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:48 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.2 2004/01/22 13:26:29 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/header/Subject.java0100644 0000000 0000000 00000012572 13513104763 017706 0ustar000000000 0000000 /* * 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.javax.sip.header; import java.text.ParseException; import javax.sip.header.*; /** * Supported SIP Header. * * @version 1.2 $Revision: 1.5 $ $Date: 2009/07/17 18:57:39 $ * * @author M. Ranganathan
    * @author Olivier Deruelle
    * * * */ public class Subject extends SIPHeader implements SubjectHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -6479220126758862528L; /** subject field */ protected String subject; /** Default Constructor. */ public Subject() { super(SUBJECT); } /** * Generate the canonical form. * @return String. */ public String encodeBody() { if (subject != null) { return subject; } else { return ""; } } /** * Sets the subject value of the SubjectHeader to the supplied string * subject value. * * @param subject - the new subject value of this header * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the subject value. */ public void setSubject(String subject) throws ParseException { if (subject == null) throw new NullPointerException( "JAIN-SIP Exception, " + " Subject, setSubject(), the subject parameter is null"); this.subject = subject; } /** * Gets the subject value of SubjectHeader * * @return subject of SubjectHeader */ public String getSubject() { return subject; } } /* * $Log: Subject.java,v $ * 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: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.2 2004/01/22 13:26:29 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/header/SubscriptionState.java0100644 0000000 0000000 00000014403 13513104763 021767 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.InvalidArgumentException; import javax.sip.header.SubscriptionStateHeader; import java.text.ParseException; /** *SubscriptionState header * * @version 1.2 $Revision: 1.7 $ $Date: 2009/07/17 18:57:39 $ * * @author Olivier Deruelle
    * * */ public class SubscriptionState extends ParametersHeader implements SubscriptionStateHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -6673833053927258745L; protected int expires; protected int retryAfter; protected String reasonCode; protected String state; /** Creates a new instance of SubscriptionState */ public SubscriptionState() { super(SIPHeaderNames.SUBSCRIPTION_STATE); expires = -1; retryAfter = -1; } /** * 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. * @throws InvalidArgumentException if supplied value is less than zero. */ public void setExpires(int expires) throws InvalidArgumentException { if (expires < 0) throw new InvalidArgumentException( "JAIN-SIP " + "Exception, SubscriptionState, setExpires(), the expires parameter is < 0"); this.expires = expires; } /** * Gets the expires value of the SubscriptionStateHeader. This expires value is * relative time. * * @return the expires value of the SubscriptionStateHeader. */ public int getExpires() { return expires; } /** * Sets the retry after value of the SubscriptionStateHeader. The retry after value * MUST be greater than zero and MUST be less than 2**31. * * @param retryAfter - the new retry after value of this SubscriptionStateHeader * @throws InvalidArgumentException if supplied value is less than zero. */ public void setRetryAfter(int retryAfter) throws InvalidArgumentException { if (retryAfter <= 0) throw new InvalidArgumentException( "JAIN-SIP " + "Exception, SubscriptionState, setRetryAfter(), the retryAfter parameter is <=0"); this.retryAfter = retryAfter; } /** * Gets the retry after value of the SubscriptionStateHeader. This retry after * value is relative time. * * @return the retry after value of the SubscriptionStateHeader. */ public int getRetryAfter() { return retryAfter; } /** * Gets the reason code of SubscriptionStateHeader. * * @return the comment of this SubscriptionStateHeader, return null if no reason code * is available. */ public String getReasonCode() { return reasonCode; } /** * Sets the reason code value of the SubscriptionStateHeader. * * @param reasonCode - the new reason code string value of the SubscriptionStateHeader. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the reason code. */ public void setReasonCode(String reasonCode) throws ParseException { if (reasonCode == null) throw new NullPointerException( "JAIN-SIP " + "Exception, SubscriptionState, setReasonCode(), the reasonCode parameter is null"); this.reasonCode = reasonCode; } /** * Gets the state of SubscriptionStateHeader. * * @return the state of this SubscriptionStateHeader. */ public String getState() { return state; } /** * Sets the state value of the SubscriptionStateHeader. * * @param state - the new state string value of the SubscriptionStateHeader. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the state. */ public void setState(String state) throws ParseException { if (state == null) throw new NullPointerException( "JAIN-SIP " + "Exception, SubscriptionState, setState(), the state parameter is null"); this.state = state; } /** Just the encoded body of the header. * @return the string encoded header body. */ public String encodeBody() { return encodeBody(new StringBuffer()).toString(); } protected StringBuffer encodeBody(StringBuffer buffer) { if (state != null) buffer.append(state); if (reasonCode != null) buffer.append(";reason=").append(reasonCode); if (expires != -1) buffer.append(";expires=").append(expires); if (retryAfter != -1) buffer.append(";retry-after=").append(retryAfter); if (!parameters.isEmpty()) { buffer.append(SEMICOLON); parameters.encode(buffer); } return buffer; } } java/gov/nist/javax/sip/header/Supported.java0100644 0000000 0000000 00000013663 13513104763 020276 0ustar000000000 0000000 /* * 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.javax.sip.header; import java.text.ParseException; import javax.sip.header.*; /** * Supported SIP Header. * * @version 1.2 $Revision: 1.5 $ $Date: 2009/07/17 18:57:39 $ * * @author M. Ranganathan
    * @author Olivier Deruelle
    * * * */ public class Supported extends SIPHeader implements SupportedHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -7679667592702854542L; /* the Option field */ protected String optionTag; /** * default constructor */ public Supported() { super(SIPHeaderNames.SUPPORTED); optionTag = null; } /** * Constructor * @param option_tag String to set */ public Supported(String option_tag) { super(SIPHeaderNames.SUPPORTED); optionTag = option_tag; } /** * Return canonical form of the header. * @return encoded header. */ public String encode() { String retval = headerName + COLON; if (optionTag != null) retval += SP + optionTag; retval += NEWLINE; return retval; } /** * Just the encoded body of the header. * @return the string encoded header body. */ public String encodeBody() { return optionTag != null ? optionTag : ""; } /** * Sets the option tag value to the new supplied optionTag * parameter. * * @param optionTag - the new string value of the option tag. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the optionTag value. */ public void setOptionTag(String optionTag) throws ParseException { if (optionTag == null) throw new NullPointerException( "JAIN-SIP Exception, Supported, " + "setOptionTag(), the optionTag parameter is null"); this.optionTag = optionTag; } /** * Gets the option tag of this OptionTag class. * * @return the string that identifies the option tag value. */ public String getOptionTag() { return optionTag; } } /* * $Log: Supported.java,v $ * 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: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.2 2004/01/22 13:26:30 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/header/SupportedList.java0100644 0000000 0000000 00000003602 13513104763 021122 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.header.*; /** * A list of supported headers. * @version 1.2 $Revision: 1.6 $ $Date: 2009/07/17 18:57:39 $ * @see Supported */ public class SupportedList extends SIPHeaderList{ /** * */ private static final long serialVersionUID = -4539299544895602367L; public Object clone() { SupportedList retval = new SupportedList(); retval.clonehlist(this.hlist); return retval; } /** Default Constructor */ public SupportedList() { super(Supported.class, SupportedHeader.NAME); } } java/gov/nist/javax/sip/header/TimeStamp.java0100644 0000000 0000000 00000012556 13513104763 020214 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.InvalidArgumentException; import javax.sip.header.*; /** * TimeStamp SIP Header. * * @version 1.2 $Revision: 1.7 $ $Date: 2009/10/18 13:46:31 $ * * @author M. Ranganathan
    * @author Olivier Deruelle
    * * * */ public class TimeStamp extends SIPHeader implements TimeStampHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -3711322366481232720L; /** * timeStamp field */ protected long timeStamp = -1; /** * delay field */ protected int delay = -1; protected float delayFloat = -1; private float timeStampFloat = -1; /** * Default Constructor */ public TimeStamp() { super(TIMESTAMP); delay = -1; } private String getTimeStampAsString() { if (timeStamp == -1 && timeStampFloat == -1) return ""; else if (timeStamp != -1) return Long.toString(timeStamp); else return Float.toString(timeStampFloat); } private String getDelayAsString() { if (delay == -1 && delayFloat == -1) return ""; else if (delay != -1) return Integer.toString(delay); else return Float.toString(delayFloat); } /** * Return canonical form of the header. * * @return String */ public String encodeBody() { StringBuffer retval = new StringBuffer(); String s1 = getTimeStampAsString(); String s2 = getDelayAsString(); if (s1.equals("") && s2.equals("")) return ""; if (!s1.equals("")) retval.append(s1); if (!s2.equals("")) retval.append(" ").append(s2); return retval.toString(); } /** * return true if delay exists * * @return boolean */ public boolean hasDelay() { return delay != -1; } /* * remove the Delay field */ public void removeDelay() { delay = -1; } public void setTimeStamp(float timeStamp) throws InvalidArgumentException { if (timeStamp < 0) throw new InvalidArgumentException( "JAIN-SIP Exception, TimeStamp, " + "setTimeStamp(), the timeStamp parameter is <0"); this.timeStamp = -1; this.timeStampFloat = timeStamp; } public float getTimeStamp() { return this.timeStampFloat == -1 ? Float.valueOf(timeStamp).floatValue() : this.timeStampFloat; } public float getDelay() { return delayFloat == -1 ? Float.valueOf(delay).floatValue() : delayFloat; } /** * Sets the new delay value of the TimestampHeader to the delay paramter * passed to this method * * @param delay - * the Float.valueOf delay value * @throws InvalidArgumentException * if the delay value argumenmt is a negative value other than * -1. */ public void setDelay(float delay) throws InvalidArgumentException { if (delay < 0 && delay != -1) throw new InvalidArgumentException( "JAIN-SIP Exception, TimeStamp, " + "setDelay(), the delay parameter is <0"); this.delayFloat = delay; this.delay = -1; } public long getTime() { return this.timeStamp == -1 ? (long) timeStampFloat : timeStamp; } public int getTimeDelay() { return this.delay == -1 ? (int) delayFloat : delay; } public void setTime(long timeStamp) throws InvalidArgumentException { if (timeStamp < -1) throw new InvalidArgumentException("Illegal timestamp"); this.timeStamp = timeStamp; this.timeStampFloat = -1; } public void setTimeDelay(int delay) throws InvalidArgumentException { if (delay < -1) throw new InvalidArgumentException("Value out of range " + delay); this.delay = delay; this.delayFloat = -1; } } java/gov/nist/javax/sip/header/To.java0100644 0000000 0000000 00000011746 13513104763 016673 0ustar000000000 0000000 /* * 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.javax.sip.header; import gov.nist.core.HostPort; import gov.nist.javax.sip.address.AddressImpl; import gov.nist.javax.sip.parser.Parser; import javax.sip.header.ToHeader; import java.text.ParseException; /** * To SIP Header. * * @version 1.2 $Revision: 1.11 $ $Date: 2009/07/17 18:57:39 $ * * @author M. Ranganathan
    * @author Olivier Deruelle
    * * * */ public final class To extends AddressParametersHeader implements javax.sip.header.ToHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -4057413800584586316L; /** * default Constructor. */ public To() { super(TO,true); } /** * Generate a TO header from a FROM header */ public To(From from) { super(TO); setAddress(from.address); setParameters(from.parameters); } /** * Encode the header into a String. * * @since 1.0 * @return String */ public String encode() { return headerName + COLON + SP + encodeBody() + NEWLINE; } /** * Encode the header content into a String. * * @return String */ protected String encodeBody() { return encodeBody(new StringBuffer()).toString(); } protected StringBuffer encodeBody(StringBuffer buffer) { if (address != null) { if (address.getAddressType() == AddressImpl.ADDRESS_SPEC) { buffer.append(LESS_THAN); } address.encode(buffer); if (address.getAddressType() == AddressImpl.ADDRESS_SPEC) { buffer.append(GREATER_THAN); } if (!parameters.isEmpty()) { buffer.append(SEMICOLON); parameters.encode(buffer); } } return buffer; } /** * Conveniance accessor function to get the hostPort field from the address. * Warning -- this assumes that the embedded URI is a SipURL. * * @return hostport field */ public HostPort getHostPort() { if (address == null) return null; return address.getHostPort(); } /** * Get the display name from the address. * * @return Display name */ public String getDisplayName() { if (address == null) return null; return address.getDisplayName(); } /** * Get the tag parameter from the address parm list. * * @return tag field */ public String getTag() { if (parameters == null) return null; return getParameter(ParameterNames.TAG); } /** * Boolean function * * @return true if the Tag exist */ public boolean hasTag() { if (parameters == null) return false; return hasParameter(ParameterNames.TAG); } /** * remove Tag member */ public void removeTag() { if (parameters != null) parameters.delete(ParameterNames.TAG); } /** * Set the tag member. This should remain empty for the initial request in * a dialog. * * @param t - tag String to set. */ public void setTag(String t) throws ParseException { // JvB: check that it is a valid token Parser.checkToken(t); this.setParameter(ParameterNames.TAG, t); } /** * Get the user@host port string. */ public String getUserAtHostPort() { if (address == null) return null; return address.getUserAtHostPort(); } public boolean equals(Object other) { return (other instanceof ToHeader) && super.equals(other); } } java/gov/nist/javax/sip/header/Unsupported.java0100644 0000000 0000000 00000012215 13513104763 020631 0ustar000000000 0000000 /* * 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.javax.sip.header; import java.text.ParseException; /** * the Unsupported header. * * @version 1.2 $Revision: 1.5 $ $Date: 2009/07/17 18:57:40 $ * @author Olivier Deruelle
    * * * */ public class Unsupported extends SIPHeader implements javax.sip.header.UnsupportedHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -2479414149440236199L; /** option-Tag field. */ protected String optionTag; /** Default Constructor. */ public Unsupported() { super(NAME); } /** Constructor * @param ot String to set */ public Unsupported(String ot) { super(NAME); optionTag = ot; } /** * Return a canonical value. * @return String. */ public String encodeBody() { return optionTag; } /** get the option tag field * @return option Tag field */ public String getOptionTag() { return optionTag; } /** * Set the option member * @param o String to set */ public void setOptionTag(String o) throws ParseException { if (o == null) throw new NullPointerException( "JAIN-SIP Exception, " + " Unsupported, setOptionTag(), The option tag parameter is null"); optionTag = o; } } /* * $Log: Unsupported.java,v $ * 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: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.2 2004/01/22 13:26:30 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/header/UnsupportedList.java0100644 0000000 0000000 00000003620 13513104763 021465 0ustar000000000 0000000 /* * 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.javax.sip.header; import java.util.Iterator; import javax.sip.header.*; /** * List of Unsupported headers. * @version 1.2 $Revision: 1.6 $ $Date: 2009/07/17 18:57:40 $ * @author M. Ranganathan */ public class UnsupportedList extends SIPHeaderList { private static final long serialVersionUID = -4052610269407058661L; /** Default Constructor */ public UnsupportedList() { super(Unsupported.class, UnsupportedHeader.NAME); } public Object clone() { UnsupportedList retval = new UnsupportedList(); return retval.clonehlist(this.hlist); } } java/gov/nist/javax/sip/header/UserAgent.java0100644 0000000 0000000 00000015323 13513104763 020201 0ustar000000000 0000000 /* * 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.javax.sip.header; import java.util.*; import java.text.ParseException; import javax.sip.header.*; /** * the UserAgent SIPObject. * * @author Olivier Deruelle
    * @version 1.2 $Revision: 1.8 $ $Date: 2009/07/17 18:57:40 $ * * * */ public class UserAgent extends SIPHeader implements UserAgentHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = 4561239179796364295L; /** Product tokens. */ protected List productTokens; /** * Return canonical form. * pmusgrave - put a space between products (preserves format of header) * @return String */ private String encodeProduct() { StringBuffer tokens = new StringBuffer(); ListIterator it = productTokens.listIterator(); while (it.hasNext()) { tokens.append((String) it.next()); } return tokens.toString(); } /** set the productToken field * @param pt String to set */ public void addProductToken(String pt) { productTokens.add(pt); } /** * Constructor. */ public UserAgent() { super(NAME); productTokens = new LinkedList(); } /** Encode only the body of this header. *@return encoded value of the header. */ public String encodeBody() { return encodeProduct(); } /** * Returns the list value of the product parameter. * * @return the software of this UserAgentHeader */ public ListIterator getProduct() { if (productTokens == null || productTokens.isEmpty()) return null; else return productTokens.listIterator(); } /** * Sets the product value of the UserAgentHeader. * * @param product - a List specifying the product value * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the product value. */ public void setProduct(List product) throws ParseException { if (product == null) throw new NullPointerException( "JAIN-SIP Exception, UserAgent, " + "setProduct(), the " + " product parameter is null"); productTokens = product; } public Object clone() { UserAgent retval = (UserAgent) super.clone(); if (productTokens != null) retval.productTokens = new LinkedList (productTokens); return retval; } } /* * $Log: UserAgent.java,v $ * 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: * Submitted by: mranga * Reviewed by: mranga * Fix minor issue in encoding of user-agent header. * * Revision 1.6 2006/10/12 11:57:55 pmusgrave * Issue number: 79, 80 * Submitted by: pmusgrave@newheights.com * Reviewed by: mranga * * Revision 1.5 2006/07/13 09:01:48 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.3 2005/04/16 20:38:51 dmuresan * Canonical clone() implementations for the GenericObject and GenericObjectList hierarchies * * Revision 1.2 2004/01/22 13:26:30 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/header/Via.java0100644 0000000 0000000 00000040104 13513104763 017016 0ustar000000000 0000000 /* * 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.javax.sip.header; import gov.nist.core.Host; import gov.nist.core.HostPort; import gov.nist.core.NameValue; import gov.nist.core.NameValueList; import gov.nist.javax.sip.stack.HopImpl; import javax.sip.InvalidArgumentException; import javax.sip.address.Hop; import javax.sip.header.ViaHeader; import java.text.ParseException; /** * Via SIPHeader (these are strung together in a ViaList). * * @see ViaList * * @version 1.2 $Revision: 1.17 $ $Date: 2009/10/18 13:46:33 $ * * @author M. Ranganathan
    * * * */ public class Via extends ParametersHeader implements javax.sip.header.ViaHeader, ViaHeaderExt { /** * Comment for serialVersionUID */ private static final long serialVersionUID = 5281728373401351378L; /** The branch parameter is included by every forking proxy. */ public static final String BRANCH = ParameterNames.BRANCH; /** The "received" parameter is added only for receiver-added Via Fields. */ public static final String RECEIVED = ParameterNames.RECEIVED; /** The "maddr" paramter is designating the multicast address. */ public static final String MADDR = ParameterNames.MADDR; /** The "TTL" parameter is designating the time-to-live value. */ public static final String TTL = ParameterNames.TTL; /** The RPORT parameter. */ public static final String RPORT = ParameterNames.RPORT; /** sentProtocol field. */ protected Protocol sentProtocol; /** sentBy field. */ protected HostPort sentBy; /** * comment field * * JvB note: RFC3261 does not allow a comment to appear in Via headers, and this * is not accessible through the API. Suggest removal */ protected String comment; private boolean rPortFlag = false; /** Default constructor */ public Via() { super(NAME); sentProtocol = new Protocol(); } public boolean equals(Object other) { if (other==this) return true; if (other instanceof ViaHeader) { final ViaHeader o = (ViaHeader) other; return getProtocol().equalsIgnoreCase( o.getProtocol() ) && getTransport().equalsIgnoreCase( o.getTransport() ) && getHost().equalsIgnoreCase( o.getHost() ) && getPort() == o.getPort() && equalParameters( o ); } return false; } /** get the Protocol Version * @return String */ public String getProtocolVersion() { if (sentProtocol == null) return null; else return sentProtocol.getProtocolVersion(); } /** * Accessor for the sentProtocol field. * @return Protocol field */ public Protocol getSentProtocol() { return sentProtocol; } /** * Accessor for the sentBy field *@return SentBy field */ public HostPort getSentBy() { return sentBy; } /** * Get the host, port and transport as a Hop. This is * useful for the stack to avoid duplication of code. * */ public Hop getHop() { HopImpl hop = new HopImpl(sentBy.getHost().getHostname(), sentBy.getPort(),sentProtocol.getTransport()); return hop; } /** * Accessor for the parameters field * @return parameters field */ public NameValueList getViaParms() { return parameters; } /** * Accessor for the comment field. * @return comment field. * @deprecated RFC 2543 support feature. */ public String getComment() { return comment; } /** port of the Via Header. * @return true if Port exists. */ public boolean hasPort() { return (getSentBy()).hasPort(); } /** comment of the Via Header. * * @return false if comment does not exist and true otherwise. */ public boolean hasComment() { return comment != null; } /** remove the port. */ public void removePort() { sentBy.removePort(); } /** remove the comment field. */ public void removeComment() { comment = null; } /** set the Protocol Version * @param protocolVersion String to set */ public void setProtocolVersion(String protocolVersion) { if (sentProtocol == null) sentProtocol = new Protocol(); sentProtocol.setProtocolVersion(protocolVersion); } /** set the Host of the Via Header * @param host String to set */ public void setHost(Host host) { if (sentBy == null) { sentBy = new HostPort(); } sentBy.setHost(host); } /** * Set the sentProtocol member * @param s Protocol to set. */ public void setSentProtocol(Protocol s) { sentProtocol = s; } /** * Set the sentBy member * @param s HostPort to set. */ public void setSentBy(HostPort s) { sentBy = s; } /** * Set the comment member * @param c String to set. * @deprecated This is an RFC 2543 feature. */ public void setComment(String c) { comment = c; } /** Encode the body of this header (the stuff that follows headerName). * A.K.A headerValue. */ protected String encodeBody() { return encodeBody(new StringBuffer()).toString(); } protected StringBuffer encodeBody(StringBuffer buffer) { sentProtocol.encode(buffer); buffer.append(SP); sentBy.encode(buffer); if (!parameters.isEmpty()) { buffer.append(SEMICOLON); parameters.encode(buffer); } if (comment != null) { buffer.append(SP).append(LPAREN).append(comment).append(RPAREN); } if (rPortFlag) buffer.append(";rport"); return buffer; } /** * Set the host part of this ViaHeader to the newly supplied host * parameter. * * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the host value. */ public void setHost(String host) throws ParseException { if (sentBy == null) sentBy = new HostPort(); try { Host h = new Host(host); sentBy.setHost(h); } catch (Exception e) { throw new NullPointerException(" host parameter is null"); } } /** * Returns the host part of this ViaHeader. * * @return the string value of the host */ public String getHost() { if (sentBy == null) return null; else { Host host = sentBy.getHost(); if (host == null) return null; else return host.getHostname(); } } /** * Set the port part of this ViaHeader to the newly supplied port * parameter. * * @param port - the Integer.valueOf value of the port of this ViaHeader */ public void setPort(int port) throws InvalidArgumentException { if ( port!=-1 && (port<1 || port>65535)) { throw new InvalidArgumentException( "Port value out of range -1, [1..65535]" ); } if (sentBy == null) sentBy = new HostPort(); sentBy.setPort(port); } /** * Set the RPort flag parameter */ public void setRPort(){ rPortFlag = true; } /** * Returns the port part of this ViaHeader. * * @return the integer value of the port */ public int getPort() { if (sentBy == null) return -1; return sentBy.getPort(); } /** * Return the rport parameter. * *@return the rport parameter or -1. */ public int getRPort() { String strRport = getParameter(ParameterNames.RPORT); if (strRport != null && ! strRport.equals("")) return Integer.valueOf(strRport).intValue(); else return -1; } /** * Returns the value of the transport parameter. * * @return the string value of the transport paramter of the ViaHeader */ public String getTransport() { if (sentProtocol == null) return null; return sentProtocol.getTransport(); } /** * Sets the value of the transport. This parameter specifies * which transport protocol to use for sending requests and responses to * this entity. The following values are defined: "udp", "tcp", "sctp", * "tls", but other values may be used also. * * @param transport - new value for the transport parameter * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the transport value. */ public void setTransport(String transport) throws ParseException { if (transport == null) throw new NullPointerException( "JAIN-SIP Exception, " + "Via, setTransport(), the transport parameter is null."); if (sentProtocol == null) sentProtocol = new Protocol(); sentProtocol.setTransport(transport); } /** * Returns the value of the protocol used. * * @return the string value of the protocol paramter of the ViaHeader */ public String getProtocol() { if (sentProtocol == null) return null; return sentProtocol.getProtocol();// JvB: Return name ~and~ version } /** * Sets the value of the protocol parameter. This parameter specifies * which protocol is used, for example "SIP/2.0". * * @param protocol - new value for the protocol parameter * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the protocol value. */ public void setProtocol(String protocol) throws ParseException { if (protocol == null) throw new NullPointerException( "JAIN-SIP Exception, " + "Via, setProtocol(), the protocol parameter is null."); if (sentProtocol == null) sentProtocol = new Protocol(); sentProtocol.setProtocol(protocol); } /** * Returns the value of the ttl parameter, or -1 if this is not set. * * @return the integer value of the ttl parameter */ public int getTTL() { int ttl = getParameterAsInt(ParameterNames.TTL); return ttl; } /** * Sets the value of the ttl parameter. The ttl parameter specifies the * time-to-live value when packets are sent using UDP multicast. * * @param ttl - new value of the ttl parameter * @throws InvalidArgumentException if supplied value is less than zero or * greater than 255, excluding -1 the default not set value. */ public void setTTL(int ttl) throws InvalidArgumentException { if (ttl < 0 && ttl != -1) throw new InvalidArgumentException( "JAIN-SIP Exception" + ", Via, setTTL(), the ttl parameter is < 0"); setParameter(new NameValue(ParameterNames.TTL, Integer.valueOf(ttl))); } /** * Returns the value of the maddr parameter, or null if this * is not set. * * @return the string value of the maddr parameter */ public String getMAddr() { return getParameter(ParameterNames.MADDR); } /** * Sets the value of the maddr parameter of this ViaHeader. The * maddr parameter indicates the server address to be contacted for this * user, overriding any address derived from the host field. * * @param mAddr new value of the maddr parameter * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the mAddr value. */ public void setMAddr(String mAddr) throws ParseException { if (mAddr == null) throw new NullPointerException( "JAIN-SIP Exception, " + "Via, setMAddr(), the mAddr parameter is null."); Host host = new Host(); host.setAddress(mAddr); NameValue nameValue = new NameValue(ParameterNames.MADDR, host); setParameter(nameValue); } /** * Gets the received paramater of the ViaHeader. Returns null if received * does not exist. * * @return the string received value of ViaHeader */ public String getReceived() { return getParameter(ParameterNames.RECEIVED); } /** * Sets the received parameter of ViaHeader. * * @param received - the newly supplied received parameter. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the received value. */ public void setReceived(String received) throws ParseException { if (received == null) throw new NullPointerException( "JAIN-SIP Exception, " + "Via, setReceived(), the received parameter is null."); setParameter(ParameterNames.RECEIVED, received); } /** * Gets the branch paramater of the ViaHeader. Returns null if branch * does not exist. * * @return the string branch value of ViaHeader */ public String getBranch() { return getParameter(ParameterNames.BRANCH); } /** * Sets the branch parameter of the ViaHeader to the newly supplied * branch value. * * @param branch - the new string branch parmameter of the ViaHeader. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the branch value. */ public void setBranch(String branch) throws ParseException { if (branch == null || branch.length()==0) throw new NullPointerException( "JAIN-SIP Exception, " + "Via, setBranch(), the branch parameter is null or length 0."); setParameter(ParameterNames.BRANCH, branch); } public Object clone() { Via retval = (Via) super.clone(); if (this.sentProtocol != null) retval.sentProtocol = (Protocol) this.sentProtocol.clone(); if (this.sentBy != null) retval.sentBy = (HostPort) this.sentBy.clone(); if ( this.getRPort() != -1) retval.setParameter(RPORT,this.getRPort()); return retval; } /* * (non-Javadoc) * @see gov.nist.javax.sip.header.ViaHeaderExt#getSentByField() */ public String getSentByField() { if(sentBy != null) return sentBy.encode(); return null; } /* * (non-Javadoc) * @see gov.nist.javax.sip.header.ViaHeaderExt#getSentProtocolField() */ public String getSentProtocolField() { if(sentProtocol != null) return sentProtocol.encode(); return null; } } java/gov/nist/javax/sip/header/ViaHeaderExt.java0100644 0000000 0000000 00000001120 13513104763 020603 0ustar000000000 0000000 /* * This code has been contributed by the authors to the public domain. */ package gov.nist.javax.sip.header; import javax.sip.header.ViaHeader; /** * @author jean.deruelle@gmail.com * */ public interface ViaHeaderExt extends ViaHeader { /** * Returns hostname:port as a string equivalent to the "sent-by" field * @return "sent-by" field * @since 2.0 */ public String getSentByField(); /** * Returns transport to the "sent-protocol" field * @return "sent-protocol" field * @since 2.0 */ public String getSentProtocolField(); } java/gov/nist/javax/sip/header/ViaList.java0100644 0000000 0000000 00000003625 13513104763 017661 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.header.*; import java.util.Iterator; /** * Keeps a list and a hashtable of via header functions. * * @version 1.2 $Revision: 1.7 $ $Date: 2009/07/17 18:57:41 $ * * @author M. Ranganathan
    * * * */ public final class ViaList extends SIPHeaderList { private static final long serialVersionUID = 3899679374556152313L; public Object clone() { ViaList retval = new ViaList(); return retval.clonehlist(this.hlist); } /** * Default Constructor. */ public ViaList() { super(Via.class, ViaHeader.NAME); } } java/gov/nist/javax/sip/header/WWWAuthenticate.java0100644 0000000 0000000 00000005131 13513104763 021323 0ustar000000000 0000000 /* * 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.javax.sip.header; import gov.nist.javax.sip.header.ims.WWWAuthenticateHeaderIms; import javax.sip.address.URI; import javax.sip.header.*; /** * The WWWAuthenticate SIP header. * * @version 1.2 $Revision: 1.6 $ $Date: 2009/07/17 18:57:41 $ * * * * @see WWWAuthenticateList SIPHeader which strings these together. */ public class WWWAuthenticate extends AuthenticationHeader implements WWWAuthenticateHeader, WWWAuthenticateHeaderIms { /** * Comment for serialVersionUID */ private static final long serialVersionUID = 115378648697363486L; /** * Default Constructor. */ public WWWAuthenticate() { super(NAME); } /* (non-Javadoc) * @see gov.nist.javax.sip.header.AuthenticationHeader#getURI() * * @since 1.2 this method is deprecated, uri is not a valid paramter for this header * Fail silently for backwards compatibility */ public URI getURI() { return null; } /* (non-Javadoc) * @see gov.nist.javax.sip.header.AuthenticationHeader#setURI(javax.sip.address.URI) * * @since 1.2 this method is deprecated, uri is not a valid paramter for this header * Fail silently for backwards compatibility */ public void setURI(URI uri) { // empty, fail silently } } java/gov/nist/javax/sip/header/WWWAuthenticateList.java0100644 0000000 0000000 00000003704 13513104763 022163 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.header.*; /** * WWWAuthenticate SIPHeader (of which there can be several?) * * @version 1.2 $Revision: 1.7 $ $Date: 2009/07/17 18:57:41 $ * * @author M. Ranganathan
    * * * */ public class WWWAuthenticateList extends SIPHeaderList { private static final long serialVersionUID = -6978902284285501346L; public Object clone() { WWWAuthenticateList retval = new WWWAuthenticateList(); return retval.clonehlist(this.hlist); } /** * constructor. */ public WWWAuthenticateList() { super(WWWAuthenticate.class, WWWAuthenticateHeader.NAME); } } java/gov/nist/javax/sip/header/Warning.java0100644 0000000 0000000 00000016267 13513104763 017721 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.header.*; import java.text.ParseException; import javax.sip.InvalidArgumentException; /** * the WarningValue SIPObject. * * @author M. Ranganathan
    * @author Olivier Deruelle
    * @version 1.2 $Revision: 1.8 $ $Date: 2009/10/18 13:46:33 $ * * * * @see WarningList SIPHeader which strings these together. */ public class Warning extends SIPHeader implements WarningHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -3433328864230783899L; /** warn code field, the warn code consists of three digits. */ protected int code; /** the name or pseudonym of the server adding * the Warning header, for use in debugging */ protected String agent; /** warn-text field */ protected String text; /** * constructor. */ public Warning() { super(WARNING); } /** Encode the body of the header (return the stuff following name:). *@return the string encoding of the header value. */ public String encodeBody() { return text != null ? Integer.toString(code) + SP + agent + SP + DOUBLE_QUOTE + text + DOUBLE_QUOTE : Integer.toString(code) + SP + agent; } /** * Gets code of WarningHeader * @return code of WarningHeader */ public int getCode() { return code; } /** * Gets agent host of WarningHeader * @return agent host of WarningHeader */ public String getAgent() { return agent; } /** * Gets text of WarningHeader * @return text of WarningHeader */ public String getText() { return text; } /** * Sets code of WarningHeader * @param code int to set * @throws SipParseException if code is not accepted by implementation */ public void setCode(int code) throws InvalidArgumentException { if (code >99 && code < 1000) { // check this is a 3DIGIT code this.code = code; } else throw new InvalidArgumentException( "Code parameter in the Warning header is invalid: code=" + code); } /** * Sets host of WarningHeader * @param host String to set * @throws ParseException if host is not accepted by implementation */ public void setAgent(String host) throws ParseException { if (host == null) throw new NullPointerException("the host parameter in the Warning header is null"); else { this.agent = host; } } /** * Sets text of WarningHeader * @param text String to set * @throws ParseException if text is not accepted by implementation */ public void setText(String text) throws ParseException { if (text == null) { throw new ParseException( "The text parameter in the Warning header is null", 0); } else this.text = text; } } /* * $Log: Warning.java,v $ * 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. * * Revision 1.6 2006/07/13 09:01:44 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.4 2004/04/22 22:51:16 mranga * Submitted by: Thomas Froment * Reviewed by: mranga * * Fixed corner cases. * * Revision 1.2 2004/01/22 13:26:30 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/header/WarningList.java0100644 0000000 0000000 00000003645 13513104763 020551 0ustar000000000 0000000 /* * 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.javax.sip.header; import javax.sip.header.*; /** * A list of Warning headers. * * @version 1.2 $Revision: 1.6 $ $Date: 2009/07/17 18:57:41 $ * * @author M. Ranganathan
    * * * */ public class WarningList extends SIPHeaderList { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -1423278728898430175L; public Object clone() { WarningList retval = new WarningList(); return retval.clonehlist(this.hlist); } /** * Constructor. */ public WarningList() { super(Warning.class, Warning.NAME); } } java/gov/nist/javax/sip/header/extensions/0040755 0000000 0000000 00000000000 13513104763 017637 5ustar000000000 0000000 java/gov/nist/javax/sip/header/extensions/Join.java0100644 0000000 0000000 00000011462 13513104763 021402 0ustar000000000 0000000 /******************************************************************************* * Product of NIST/ITL Advanced Networking Technologies Division (ANTD). * *******************************************************************************/ package gov.nist.javax.sip.header.extensions; import java.text.ParseException; import gov.nist.javax.sip.header.*; import javax.sip.header.ExtensionHeader; /* * This code is in the public domain. */ /** * Join SIPHeader. * * @author jean.deruelle@gmail.com
    * * @version JAIN-SIP-1.2 * * */ public class Join extends ParametersHeader implements ExtensionHeader, JoinHeader { /** * */ private static final long serialVersionUID = -840116548918120056L; public static final String NAME = "Join"; /** * callIdentifier field */ public CallIdentifier callIdentifier; public String callId; /** * Default constructor */ public Join() { super(NAME); } /** Constructor given the call Identifier. *@param callId string call identifier (should be localid@host) *@throws IllegalArgumentException if call identifier is bad. */ public Join(String callId) throws IllegalArgumentException { super(NAME); this.callIdentifier = new CallIdentifier(callId); } /** * Encode the body part of this header (i.e. leave out the hdrName). * @return String encoded body part of the header. */ public String encodeBody() { if (callId == null) return null; else { String retVal = callId; if (!parameters.isEmpty()) { retVal += SEMICOLON + parameters.encode(); } return retVal; } } /** * get the CallId field. This does the same thing as encodeBody * * @return String the encoded body part of the */ public String getCallId() { return callId; } /** * get the call Identifer member. * @return CallIdentifier */ public CallIdentifier getCallIdentifer() { return callIdentifier; } /** * set the CallId field * @param cid String to set. This is the body part of the Call-Id * header. It must have the form localId@host or localId. * @throws IllegalArgumentException if cid is null, not a token, or is * not a token@token. */ public void setCallId(String cid) { callId = cid; } /** * Set the callIdentifier member. * @param cid CallIdentifier to set (localId@host). */ public void setCallIdentifier(CallIdentifier cid) { callIdentifier = cid; } /** * Get the to-tag parameter from the address parm list. * @return tag field */ public String getToTag() { if (parameters == null) return null; return getParameter(ParameterNames.TO_TAG); } /** * Set the to-tag member * @param t tag to set. From tags are mandatory. */ public void setToTag(String t) throws ParseException { if (t == null) throw new NullPointerException("null tag "); else if (t.trim().equals("")) throw new ParseException("bad tag", 0); this.setParameter(ParameterNames.TO_TAG, t); } /** Boolean function * @return true if the Tag exist */ public boolean hasToTag() { return hasParameter(ParameterNames.TO_TAG); } /** remove Tag member */ public void removeToTag() { parameters.delete(ParameterNames.TO_TAG); } /** * Get the from-tag parameter from the address parm list. * @return tag field */ public String getFromTag() { if (parameters == null) return null; return getParameter(ParameterNames.FROM_TAG); } /** * Set the to-tag member * @param t tag to set. From tags are mandatory. */ public void setFromTag(String t) throws ParseException { if (t == null) throw new NullPointerException("null tag "); else if (t.trim().equals("")) throw new ParseException("bad tag", 0); this.setParameter(ParameterNames.FROM_TAG, t); } /** Boolean function * @return true if the Tag exist */ public boolean hasFromTag() { return hasParameter(ParameterNames.FROM_TAG); } /** remove Tag member */ public void removeFromTag() { parameters.delete(ParameterNames.FROM_TAG); } public void setValue(String value) throws ParseException { // not implemented. throw new ParseException(value,0); } // public Object clone() { // CallID retval = (CallID) super.clone(); // if (this.callIdentifier != null) // retval.setCallIdentifier( (CallIdentifier) this.callIdentifier.clone() ); // return retval; // } } java/gov/nist/javax/sip/header/extensions/JoinHeader.java0100644 0000000 0000000 00000014770 13513104763 022520 0ustar000000000 0000000 /* * 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.extensions; import java.text.ParseException; import javax.sip.header.Header; import javax.sip.header.Parameters; /** * The From header field indicates the logical identity of the initiator * of the request, possibly the user's address-of-record. This may be different * from the initiator of the dialog. Requests sent by the callee to the caller * use the callee's address in the From header field. *

    * Like the To header field, it contains a URI and optionally a display name, * encapsulated in a {@link javax.sip.address.Address}. It is used by SIP * elements to determine which processing rules to apply to a request (for * example, automatic call rejection). As such, it is very important that the * From URI not contain IP addresses or the FQDN of the host on which the UA is * running, since these are not logical names. *

    * The From header field allows for a display name. A UAC SHOULD use * the display name "Anonymous", along with a syntactically correct, but * otherwise meaningless URI (like sip:thisis@anonymous.invalid), if the * identity of the client is to remain hidden. *

    * Usually, the value that populates the From header field in requests * generated by a particular UA is pre-provisioned by the user or by the * administrators of the user's local domain. If a particular UA is used by * multiple users, it might have switchable profiles that include a URI * corresponding to the identity of the profiled user. Recipients of requests * can authenticate the originator of a request in order to ascertain that * they are who their From header field claims they are. *

    * Two From header fields are equivalent if their URIs match, and their * parameters match. Extension parameters in one header field, not present in * the other are ignored for the purposes of comparison. This means that the * display name and presence or absence of angle brackets do not affect * matching. *

      *
    • The "Tag" parameter - is used in the To and From header fields of SIP * messages. It serves as a general mechanism to identify a dialog, which is * the combination of the Call-ID along with two tags, one from each * participant in the dialog. When a User Agent sends a request outside of a dialog, * it contains a From tag only, providing "half" of the dialog ID. The dialog * is completed from the response(s), each of which contributes the second half * in the To header field. When a tag is generated by a User Agent for insertion into * a request or response, it MUST be globally unique and cryptographically * random with at least 32 bits of randomness. Besides the requirement for * global uniqueness, the algorithm for generating a tag is implementation * specific. Tags are helpful in fault tolerant systems, where a dialog is to * be recovered on an alternate server after a failure. A UAS can select the * tag in such a way that a backup can recognize a request as part of a dialog * on the failed server, and therefore determine that it should attempt to * recover the dialog and any other state associated with it. *
    * For Example:
    * From: "Bob" sips:bob@biloxi.com ;tag=a48s
    * From: sip:+12125551212@phone2net.com;tag=887s
    * From: Anonymous sip:c8oqz84zk7z@privacy.org;tag=hyh8
    * * @version 1.1 * @author jean.deruelle@gmail.com */ public interface JoinHeader extends Parameters, Header { /** * Sets the tag parameter of the FromHeader. The tag in the From field of a * request identifies the peer of the dialog. When a UA sends a request * outside of a dialog, it contains a From tag only, providing "half" of * the dialog Identifier. *

    * The From Header MUST contain a new "tag" parameter, chosen by the UAC * applicaton. Once the initial From "tag" is assigned it should not be * manipulated by the application. That is on the client side for outbound * requests the application is responsible for Tag assigmennment, after * dialog establishment the stack will take care of Tag assignment. * * @param tag - the new tag of the FromHeader * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the Tag value. */ public void setToTag(String tag) throws ParseException; public void setFromTag(String tag) throws ParseException; /** * Gets the tag of FromHeader. The Tag parameter identified the Peer of the * dialogue and must always be present. * * @return the tag parameter of the FromHeader. */ public String getToTag(); public String getFromTag(); /** * Sets the Call-Id of the CallIdHeader. The CallId parameter uniquely * identifies a serious of messages within a dialogue. * * @param callId - the string value of the Call-Id of this CallIdHeader. * @throws ParseException which signals that an error has been reached * unexpectedly while parsing the callId value. */ public void setCallId(String callId) throws ParseException; /** * Returns the Call-Id of CallIdHeader. The CallId parameter uniquely * identifies a series of messages within a dialogue. * * @return the String value of the Call-Id of this CallIdHeader */ public String getCallId(); /** * Name of JoinHeader */ public final static String NAME = "Join"; } java/gov/nist/javax/sip/header/extensions/MinSE.java0100644 0000000 0000000 00000004766 13513104763 021467 0ustar000000000 0000000 /******************************************************************************* * Product of NIST/ITL Advanced Networking Technologies Division (ANTD). * *******************************************************************************/ /* * This code has been contributed by the author to the public domain. */ package gov.nist.javax.sip.header.extensions; import java.text.ParseException; import gov.nist.javax.sip.header.*; import javax.sip.*; import javax.sip.header.ExtensionHeader; /** * MinSE SIP Header. * * (Created by modifying Expires.java) * * @version JAIN-SIP-1.1 $Revision: 1.4 $ $Date: 2009/10/18 13:46:36 $ * * @author P. Musgrave
    * */ public class MinSE extends ParametersHeader implements ExtensionHeader, MinSEHeader { // TODO: When the MinSEHeader is added to javax - move this there...pmusgrave public static final String NAME = "Min-SE"; /** * Comment for serialVersionUID */ private static final long serialVersionUID = 3134344915465784267L; /** expires field */ public int expires; /** default constructor */ public MinSE() { super(NAME); } /** * Return canonical form. * @return String */ public String encodeBody() { String retval = Integer.toString(expires); // seems overkill - but Expires did this. if (!parameters.isEmpty()) { retval += SEMICOLON + parameters.encode(); } return retval; } public void setValue(String value) throws ParseException { // not implemented. throw new ParseException(value,0); } /** * Gets the expires value of the ExpiresHeader. This expires value is * * relative time. * * * * @return the expires value of the ExpiresHeader. * * @since JAIN SIP v1.1 * */ public int getExpires() { return expires; } /** * Sets the relative expires value of the ExpiresHeader. * The expires value MUST be greater than zero and MUST be * less than 2**31. * * @param expires - the new expires value of this ExpiresHeader * * @throws InvalidArgumentException if supplied value is less than zero. * * @since JAIN SIP v1.2 * */ public void setExpires(int expires) throws InvalidArgumentException { if (expires < 0) throw new InvalidArgumentException("bad argument " + expires); this.expires = expires; } } java/gov/nist/javax/sip/header/extensions/MinSEHeader.java0100644 0000000 0000000 00000000344 13513104763 022564 0ustar000000000 0000000 package gov.nist.javax.sip.header.extensions; import javax.sip.header.Header; import javax.sip.header.Parameters; public interface MinSEHeader extends Parameters, Header { public final static String NAME = "Min-SE"; } java/gov/nist/javax/sip/header/extensions/References.java0100644 0000000 0000000 00000003273 13513104763 022565 0ustar000000000 0000000 package gov.nist.javax.sip.header.extensions; import gov.nist.javax.sip.header.ParametersHeader; import java.text.ParseException; import java.util.Iterator; import javax.sip.header.ExtensionHeader; public class References extends ParametersHeader implements ReferencesHeader,ExtensionHeader { private static final long serialVersionUID = 8536961681006637622L; private String callId; public References() { super(ReferencesHeader.NAME); } public String getCallId() { return callId; } public String getRel() { return this.getParameter(REL); } public void setCallId(String callId) { this.callId = callId; } public void setRel(String rel) throws ParseException{ if ( rel != null ) { this.setParameter(REL,rel); } } public String getParameter(String name) { return super.getParameter(name); } public Iterator getParameterNames() { return super.getParameterNames(); } public void removeParameter(String name) { super.removeParameter(name); } public void setParameter(String name, String value) throws ParseException { super.setParameter(name,value); } public String getName() { return ReferencesHeader.NAME; } protected String encodeBody() { if ( super.parameters.isEmpty()) { return callId ; } else { return callId + ";" + super.parameters.encode(); } } public void setValue(String value) throws ParseException { throw new UnsupportedOperationException("operation not supported"); } } java/gov/nist/javax/sip/header/extensions/ReferencesHeader.java0100644 0000000 0000000 00000001677 13513104763 023704 0ustar000000000 0000000 package gov.nist.javax.sip.header.extensions; import java.text.ParseException; import javax.sip.header.Header; import javax.sip.header.Parameters; /** * References header: See http://tools.ietf.org/html/draft-worley-references-05 */ public interface ReferencesHeader extends Parameters, Header { public static final String NAME = "References"; public static final String CHAIN = "chain"; public static final String INQUIRY = "inquiry"; public static final String REFER = "refer" ; public static final String SEQUEL = "sequel"; public static final String XFER = "xfer"; public static final String REL = "rel"; public static final String SERVICE = "service"; public void setCallId(String callId) throws ParseException; public String getCallId(); public void setRel (String rel) throws ParseException; public String getRel(); } java/gov/nist/javax/sip/header/extensions/ReferredBy.java0100644 0000000 0000000 00000010451 13513104763 022531 0ustar000000000 0000000 /******************************************************************************* * Product of NIST/ITL Advanced Networking Technologies Division (ANTD). * *******************************************************************************/ package gov.nist.javax.sip.header.extensions; import java.text.ParseException; import javax.sip.header.ExtensionHeader; import gov.nist.javax.sip.header.*; import gov.nist.javax.sip.address.*; /* * This code has been contributed by the author to the public domain. */ /** * ReferredBy SIP Header. RFC 3892 * * @version JAIN-SIP-1.2 * * @author Peter Musgrave. * * */ public final class ReferredBy extends AddressParametersHeader implements ExtensionHeader, ReferredByHeader { // TODO: Need a unique UID private static final long serialVersionUID = 3134344915465784267L; // TODO: When the MinSEHeader is added to javax - move this there...pmusgrave public static final String NAME = "Referred-By"; /** default Constructor. */ public ReferredBy() { super(NAME); } public void setValue(String value) throws ParseException { // not implemented. throw new ParseException(value,0); } /** * Encode the header content into a String. * @return String */ protected String encodeBody() { if (address == null) return null; String retval = ""; if (address.getAddressType() == AddressImpl.ADDRESS_SPEC) { retval += LESS_THAN; } retval += address.encode(); if (address.getAddressType() == AddressImpl.ADDRESS_SPEC) { retval += GREATER_THAN; } if (!parameters.isEmpty()) { retval += SEMICOLON + parameters.encode(); } return retval; } } /* * $Log: ReferredBy.java,v $ * 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: * Submitted by: * Reviewed by: mranga * doc fixups * 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.1 2006/10/12 11:57:52 pmusgrave * Issue number: 79, 80 * Submitted by: pmusgrave@newheights.com * Reviewed by: mranga * * Revision 1.2 2006/03/20 20:52:03 pmusgrave * Add RefferedBy to header factory * Correct implements statement in ReferredBy * * Revision 1.1.1.1 2006/03/15 16:00:07 pmusgrave * Source with additions * * Revision 1.3 2004/01/22 13:26:29 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/header/extensions/ReferredByHeader.java0100644 0000000 0000000 00000001572 13513104763 023646 0ustar000000000 0000000 /* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package gov.nist.javax.sip.header.extensions; import javax.sip.header.Header; import javax.sip.header.HeaderAddress; import javax.sip.header.Parameters; public interface ReferredByHeader extends Header, HeaderAddress, Parameters { String NAME = "Referred-By"; } java/gov/nist/javax/sip/header/extensions/Replaces.java0100644 0000000 0000000 00000017317 13513104763 022246 0ustar000000000 0000000 /******************************************************************************* * Product of NIST/ITL Advanced Networking Technologies Division (ANTD). * *******************************************************************************/ package gov.nist.javax.sip.header.extensions; import java.text.ParseException; import gov.nist.javax.sip.header.*; import javax.sip.header.ExtensionHeader; /* * This code is in the public domain. */ /** * Replaces SIPHeader. * ToDo: add support for early-only flag. * * @author P, Musgrave
    * * @version JAIN-SIP-1.2 * * */ public class Replaces extends ParametersHeader implements ExtensionHeader, ReplacesHeader { // TODO: Need a unique UID private static final long serialVersionUID = 8765762413224043300L; // TODO: When the MinSEHeader is added to javax - move this there...pmusgrave public static final String NAME = "Replaces"; /** * callIdentifier field */ public CallIdentifier callIdentifier; public String callId; /** * Default constructor */ public Replaces() { super(NAME); } /** Constructor given the call Identifier. *@param callId string call identifier (should be localid@host) *@throws IllegalArgumentException if call identifier is bad. */ public Replaces(String callId) throws IllegalArgumentException { super(NAME); this.callIdentifier = new CallIdentifier(callId); } /** * Encode the body part of this header (i.e. leave out the hdrName). * @return String encoded body part of the header. */ public String encodeBody() { if (callId == null) return null; else { String retVal = callId; if (!parameters.isEmpty()) { retVal += SEMICOLON + parameters.encode(); } return retVal; } } /** * get the CallId field. This does the same thing as encodeBody * * @return String the encoded body part of the */ public String getCallId() { return callId; } /** * get the call Identifer member. * @return CallIdentifier */ public CallIdentifier getCallIdentifer() { return callIdentifier; } /** * set the CallId field * @param cid String to set. This is the body part of the Call-Id * header. It must have the form localId@host or localId. * @throws IllegalArgumentException if cid is null, not a token, or is * not a token@token. */ public void setCallId(String cid) { callId = cid; } /** * Set the callIdentifier member. * @param cid CallIdentifier to set (localId@host). */ public void setCallIdentifier(CallIdentifier cid) { callIdentifier = cid; } /** * Get the to-tag parameter from the address parm list. * @return tag field */ public String getToTag() { if (parameters == null) return null; return getParameter(ParameterNames.TO_TAG); } /** * Set the to-tag member * @param t tag to set. From tags are mandatory. */ public void setToTag(String t) throws ParseException { if (t == null) throw new NullPointerException("null tag "); else if (t.trim().equals("")) throw new ParseException("bad tag", 0); this.setParameter(ParameterNames.TO_TAG, t); } /** Boolean function * @return true if the Tag exist */ public boolean hasToTag() { return hasParameter(ParameterNames.TO_TAG); } /** remove Tag member */ public void removeToTag() { parameters.delete(ParameterNames.TO_TAG); } /** * Get the from-tag parameter from the address parm list. * @return tag field */ public String getFromTag() { if (parameters == null) return null; return getParameter(ParameterNames.FROM_TAG); } /** * Set the to-tag member * @param t tag to set. From tags are mandatory. */ public void setFromTag(String t) throws ParseException { if (t == null) throw new NullPointerException("null tag "); else if (t.trim().equals("")) throw new ParseException("bad tag", 0); this.setParameter(ParameterNames.FROM_TAG, t); } /** Boolean function * @return true if the Tag exist */ public boolean hasFromTag() { return hasParameter(ParameterNames.FROM_TAG); } /** remove Tag member */ public void removeFromTag() { parameters.delete(ParameterNames.FROM_TAG); } public void setValue(String value) throws ParseException { // not implemented. throw new ParseException(value,0); } // public Object clone() { // CallID retval = (CallID) super.clone(); // if (this.callIdentifier != null) // retval.setCallIdentifier( (CallIdentifier) this.callIdentifier.clone() ); // return retval; // } } /* * $Log: Replaces.java,v $ * 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: * Submitted by: * Reviewed by: mranga * doc fixups * 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.1 2006/10/12 11:57:51 pmusgrave * Issue number: 79, 80 * Submitted by: pmusgrave@newheights.com * Reviewed by: mranga * * Revision 1.3 2006/07/19 15:05:20 pmusgrave * Modify encodeBody so it uses callId and not CallIdentifier * * Revision 1.2 2006/04/17 23:41:31 pmusgrave * Add Session Timer and Replaces headers * * Revision 1.1.1.1 2006/03/15 16:00:07 pmusgrave * Source with additions * * Revision 1.3 2005/04/16 20:38:48 dmuresan * Canonical clone() implementations for the GenericObject and GenericObjectList hierarchies * * Revision 1.2 2004/01/22 13:26:29 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/header/extensions/ReplacesHeader.java0100644 0000000 0000000 00000002114 13513104763 023344 0ustar000000000 0000000 /* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package gov.nist.javax.sip.header.extensions; import java.text.ParseException; import javax.sip.header.Header; import javax.sip.header.Parameters; public interface ReplacesHeader extends Header, Parameters { String NAME = "Replaces"; String getToTag(); void setToTag(String tag) throws ParseException; String getFromTag(); void setFromTag(String tag) throws ParseException; String getCallId(); void setCallId(String callId) throws ParseException; }java/gov/nist/javax/sip/header/extensions/SessionExpires.java0100644 0000000 0000000 00000005132 13513104763 023463 0ustar000000000 0000000 /******************************************************************************* * Product of NIST/ITL Advanced Networking Technologies Division (ANTD). * *******************************************************************************/ package gov.nist.javax.sip.header.extensions; import gov.nist.javax.sip.header.ParametersHeader; import java.text.ParseException; import javax.sip.InvalidArgumentException; import javax.sip.header.ExtensionHeader; /** * ReferredBy SIP Header. * * @version JAIN-SIP-1.1 $Revision: 1.5 $ $Date: 2009/10/18 13:46:36 $ * * @author Peter Musgrave. * */ public final class SessionExpires extends ParametersHeader implements ExtensionHeader, SessionExpiresHeader { // TODO: Need a unique UID private static final long serialVersionUID = 8765762413224043300L; // TODO: When the MinSEHeader is added to javax - move this there...pmusgrave public static final String NAME = "Session-Expires"; public int expires; public static final String REFRESHER = "refresher"; /** default Constructor. */ public SessionExpires() { super(NAME); } /** * Gets the expires value of the SessionExpiresHeader. This expires value is * relative time. * * * * @return the expires value of the ExpiresHeader. * * @since JAIN SIP v1.1 * */ public int getExpires() { return expires; } /** * Sets the relative expires value of the SessionExpiresHeader. * The expires value MUST be greater than zero and MUST be * less than 2**31. * * @param expires - the new expires value * * @throws InvalidArgumentException if supplied value is less than zero. * * @since JAIN SIP v1.1 * */ public void setExpires(int expires) throws InvalidArgumentException { if (expires < 0) throw new InvalidArgumentException("bad argument " + expires); this.expires = expires; } public void setValue(String value) throws ParseException { // not implemented. throw new ParseException(value,0); } /** * Encode the header content into a String. * @return String */ protected String encodeBody() { String retval = Integer.toString(expires); if (!parameters.isEmpty()) { retval += SEMICOLON + parameters.encode(); } return retval; } public String getRefresher() { return parameters.getParameter(REFRESHER); } public void setRefresher(String refresher) { this.parameters.set(REFRESHER,refresher); } } java/gov/nist/javax/sip/header/extensions/SessionExpiresHeader.java0100644 0000000 0000000 00000000773 13513104763 024602 0ustar000000000 0000000 package gov.nist.javax.sip.header.extensions; import javax.sip.InvalidArgumentException; import javax.sip.header.*; /* * Extension for SessionTimer RFC 4028 * * */ public interface SessionExpiresHeader extends Parameters, Header, ExtensionHeader{ public final static String NAME = "Session-Expires"; public int getExpires(); public void setExpires(int expires) throws InvalidArgumentException; public String getRefresher() ; public void setRefresher(String refresher); } java/gov/nist/javax/sip/header/ims/0040755 0000000 0000000 00000000000 13513104763 016230 5ustar000000000 0000000 java/gov/nist/javax/sip/header/ims/AddressHeaderIms.java0100644 0000000 0000000 00000004533 13513104763 022244 0ustar000000000 0000000 /* * Conditions Of Use * * This software was developed by employees of the National Institute of * Standards and Technology (NIST), an agency of the Federal Government * and others. * 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 PT INOVAO - EST DEPARTMENT * *******************************************/ package gov.nist.javax.sip.header.ims; import javax.sip.address.Address; import gov.nist.javax.sip.address.AddressImpl; import gov.nist.javax.sip.header.SIPHeader; /** * AddressHeader base class. * @author ALEXANDRE MIGUEL SILVA SANTOS (PT Innovacau) */ public abstract class AddressHeaderIms extends SIPHeader { protected AddressImpl address; /** * get the Address field * @return the imbedded Address */ public Address getAddress() { return address; } /** * set the Address field * @param address Address to set */ public void setAddress(Address address) { this.address = (AddressImpl) address; } public abstract String encodeBody(); //protected abstract String encodeBody(); /** * Constructor given the name of the header. */ public AddressHeaderIms(String name) { //protected AddressHeader(String name) { super(name); } public Object clone() { AddressHeaderIms retval = (AddressHeaderIms) super.clone(); if (this.address != null) retval.address = (AddressImpl) this.address.clone(); return retval; } } java/gov/nist/javax/sip/header/ims/AuthorizationHeaderIms.java0100644 0000000 0000000 00000004071 13513104763 023514 0ustar000000000 0000000 /* * Conditions Of Use * * This software was developed by employees of the National Institute of * Standards and Technology (NIST), an agency of the Federal Government * and others. * 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 PT INOVACAO - EST DEPARTMENT * *******************************************/ package gov.nist.javax.sip.header.ims; import java.text.ParseException; import javax.sip.InvalidArgumentException; import javax.sip.header.AuthorizationHeader; /** * * Extension to Authorization header (3GPP TS 24299-5d0) * * This extension defines a new auth-param for the Authorization header used * in REGISTER requests. * For more information, see RFC 2617 [21] subclause 3.2.2. * * @author ALEXANDRE MIGUEL SILVA SANTOS */ public interface AuthorizationHeaderIms extends AuthorizationHeader { // issued by Miguel Freitas (IT) PT-Inovacao public static final String YES = "yes"; public static final String NO = "no"; /** * @param integrityProtected * @throws ParseException */ public void setIntegrityProtected(String integrityProtected) throws InvalidArgumentException, ParseException; public String getIntegrityProtected(); } java/gov/nist/javax/sip/header/ims/PAccessNetworkInfo.java0100644 0000000 0000000 00000020171 13513104763 022600 0ustar000000000 0000000 /* * Conditions Of Use * * This software was developed by employees of the National Institute of * Standards and Technology (NIST), an agency of the Federal Government, * and others. * 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 PT INOVACAO - EST DEPARTMENT and Aveiro University - Portugal) * *****************************************************************************/ package gov.nist.javax.sip.header.ims; import java.text.ParseException; import javax.sip.header.ContactHeader; import javax.sip.header.ExtensionHeader; import gov.nist.javax.sip.header.ParametersHeader; /** *

    P-Access-Network-Info SIP Private Header

    * * @author Miguel Freitas (IT) PT-Inovacao * * @since 1.2 */ public class PAccessNetworkInfo extends ParametersHeader implements PAccessNetworkInfoHeader, ExtensionHeader { // TODO: serialVersionUID private String accessType; private Object extendAccessInfo; /** * Public constructor. */ public PAccessNetworkInfo() { super(PAccessNetworkInfoHeader.NAME); parameters.setSeparator(SEMICOLON); } /** * Constructor. */ public PAccessNetworkInfo(String accessTypeVal) { this(); setAccessType(accessTypeVal); } /** * Set the accessTpe * * @param accessTypeVal - access type * @throws NullPointerException */ public void setAccessType(String accessTypeVal) { if (accessTypeVal == null) throw new NullPointerException( "JAIN-SIP Exception, " + "P-Access-Network-Info, setAccessType(), the accessType parameter is null."); this.accessType = accessTypeVal; } /** * @return String access type */ public String getAccessType() { return accessType; } /** * * @param cgi -- String CGI value * @throws NullPointerException -- if null argument passed in * @throws ParseException -- if bad argument passed in. */ public void setCGI3GPP(String cgi) throws ParseException { if (cgi == null) throw new NullPointerException( "JAIN-SIP Exception, " + "P-Access-Network-Info, setCGI3GPP(), the cgi parameter is null."); setParameter(ParameterNamesIms.CGI_3GPP, cgi); } /** * * @return String CGI value */ public String getCGI3GPP() { return getParameter(ParameterNamesIms.CGI_3GPP); } /** * Set the UtranCellID field. * * @param utranCellID -- String UTRAN Cell ID value * @throws NullPointerException * @throws ParseException */ public void setUtranCellID3GPP(String utranCellID) throws ParseException { if (utranCellID == null) throw new NullPointerException( "JAIN-SIP Exception, " + "P-Access-Network-Info, setUtranCellID3GPP(), the utranCellID parameter is null."); setParameter(ParameterNamesIms.UTRAN_CELL_ID_3GPP, utranCellID); } /** * * @return String UTRAN Cell ID value */ public String getUtranCellID3GPP() { return getParameter(ParameterNamesIms.UTRAN_CELL_ID_3GPP); } /** * * @param dslLocation - String with the DSL location value * @throws NullPointerException * @throws ParseException */ public void setDSLLocation(String dslLocation) throws ParseException { if (dslLocation == null) throw new NullPointerException( "JAIN-SIP Exception, " + "P-Access-Network-Info, setDSLLocation(), the dslLocation parameter is null."); setParameter(ParameterNamesIms.DSL_LOCATION, dslLocation); } /** * * @return String DSL location value */ public String getDSLLocation() { return getParameter(ParameterNamesIms.DSL_LOCATION); } /** * * @param ci3Gpp2 -- String CI 3GPP2 value * @throws NullPointerException -- if arg is null * @throws ParseException -- if arg is bad. */ public void setCI3GPP2(String ci3Gpp2) throws ParseException { if (ci3Gpp2 == null) throw new NullPointerException( "JAIN-SIP Exception, " + "P-Access-Network-Info, setCI3GPP2(), the ci3Gpp2 parameter is null."); setParameter(ParameterNamesIms.CI_3GPP2, ci3Gpp2); } /** * * @return String CI 3GPP2 value */ public String getCI3GPP2() { return getParameter(ParameterNamesIms.CI_3GPP2); } /** * * @param name -- * parameter name * @param value -- * value of parameter */ public void setParameter(String name, Object value) { /** * @todo ParametersHeader needs to be fix!? missing "throws * ParseException" in setParameter(String, Object) */ if (name.equalsIgnoreCase(ParameterNamesIms.CGI_3GPP) || name.equalsIgnoreCase(ParameterNamesIms.UTRAN_CELL_ID_3GPP) || name.equalsIgnoreCase(ParameterNamesIms.DSL_LOCATION) || name.equalsIgnoreCase(ParameterNamesIms.CI_3GPP2)) { try { super.setQuotedParameter(name, value.toString()); } catch (ParseException e) { } } else { // value can be token either than a quoted-string super.setParameter(name, value); } } /** * extension-access-info = gen-value gen-value = token / host / * quoted-string * * @param extendAccessInfo - extended Access Information */ public void setExtensionAccessInfo(Object extendAccessInfo) throws ParseException { if (extendAccessInfo == null) throw new NullPointerException( "JAIN-SIP Exception, " + "P-Access-Network-Info, setExtendAccessInfo(), the extendAccessInfo parameter is null."); // or -> setParameter("", extendAccessInfo); this.extendAccessInfo = extendAccessInfo; } public Object getExtensionAccessInfo() { return this.extendAccessInfo; } protected String encodeBody() { StringBuffer encoding = new StringBuffer(); if (getAccessType() != null) encoding.append(getAccessType()); if (!parameters.isEmpty()) { 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 + SP + getExtensionAccessInfo().toString()); } return encoding.toString(); } public void setValue(String value) throws ParseException { throw new ParseException(value, 0); } public boolean equals(Object other) { return (other instanceof PAccessNetworkInfoHeader) && super.equals(other); } /* * Makes a deep clone. (ParametersHeader) */ public Object clone() { PAccessNetworkInfo retval = (PAccessNetworkInfo) super.clone(); return retval; } } java/gov/nist/javax/sip/header/ims/PAccessNetworkInfoHeader.java0100644 0000000 0000000 00000010660 13513104763 023713 0ustar000000000 0000000 /* * Conditions Of Use * * This software was developed by employees of the National Institute of * Standards and Technology (NIST), an agency of the Federal Government * and others. * 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 PT INOVACAO - EST DEPARTMENT * *******************************************/ package gov.nist.javax.sip.header.ims; import java.text.ParseException; import javax.sip.header.Header; import javax.sip.header.Parameters; /** *

    P-Access-Network-Info SIP P-Header

    *

    This header carries information relating to the access network between * the UAC and its serving proxy in the home network.

    * *

    IETF RFC3455 + 3GPP TS 24.229-720 (2005-12)

    *

    Sintax:

    *
     * P-Access-Network-Info  = "P-Access-Network-Info": access-type *(; access-info)
     *
     * access-type    = "IEEE-802.11a" / "IEEE-802.11b" / "3GPP-GERAN" / "3GPP-UTRAN-FDD" /
     *                   "3GPP-UTRAN-TDD" / "ADSL" / "ADSL2" / "ADSL2+" / "RADSL" / "SDSL" /
     *                   "HDSL" / "HDSL2" / "G.SHDSL" / "VDSL" / "IDSL" / "3GPP2-1X" /
     *                   "3GPP2-1XHRPD" /token
     *
     * access-info            = cgi-3gpp / utran-cell-id-3gpp / dsl-location /
     *                          ci-3gpp2 / extension-access-info
     * cgi-3gpp               = "cgi-3gpp" EQUAL (token / quoted-string)
     * utran-cell-id-3gpp     = "utran-cell-id-3gpp" EQUAL (token / quoted-string)
     * dsl-location           = "dsl-location" EQUAL (token / quoted-string)
     * ci-3gpp2               = "ci-3gpp2" EQUAL (token / quoted-string)
     * extension-access-info  = gen-value
     * gen-value              = token / host / quoted-string
     * 
    * * @author Miguel Freitas (IT) PT-Inovacao */ public interface PAccessNetworkInfoHeader extends Parameters, Header { public final static String NAME = "P-Access-Network-Info"; // access type public static final String IEEE_802_11 = "IEEE-802.11"; public static final String IEEE_802_11A = "IEEE-802.11a"; public static final String IEEE_802_11B = "IEEE-802.11b"; public static final String IEEE_802_11G = "IEEE-802.11g"; public static final String GGGPP_GERAN = "3GPP-GERAN"; public static final String GGGPP_UTRAN_FDD = "3GPP-UTRAN-FDD"; public static final String GGGPP_UTRAN_TDD = "3GPP-UTRAN-TDD"; public static final String GGGPP_CDMA2000 = "3GPP-CDMA2000"; public static final String ADSL = "ADSL"; public static final String ADSL2 = "ADSL2"; public static final String ADSL2p = "ADSL2+"; public static final String RADSL = "RADSL"; public static final String SDSL = "SDSL"; public static final String HDSL = "HDSL"; public static final String HDSL2 = "HDSL2"; public static final String GSHDSL = "G.SHDSL"; public static final String VDSL = "VDSL"; public static final String IDSL = "IDSL"; public static final String GGGPP2_1X = "3GPP2-1X"; public static final String GGGPP2_1XHRPD = "3GPP2-1XHRPD"; public void setAccessType(String accessTypeVal) throws ParseException; public String getAccessType(); public void setCGI3GPP(String cgi) throws ParseException; public String getCGI3GPP(); public void setUtranCellID3GPP(String utranCellID) throws ParseException; public String getUtranCellID3GPP(); public void setDSLLocation(String dslLocation) throws ParseException; public String getDSLLocation(); public void setCI3GPP2(String ci2Gpp2) throws ParseException; public String getCI3GPP2(); public void setExtensionAccessInfo(Object extendAccessInfo) throws ParseException; public Object getExtensionAccessInfo(); } java/gov/nist/javax/sip/header/ims/PAssertedIdentity.java0100644 0000000 0000000 00000005522 13513104763 022500 0ustar000000000 0000000 /* * Conditions Of Use * * This software was developed by employees of the National Institute of * Standards and Technology (NIST), an agency of the Federal Government, * and others. * 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 PT INOVAO - EST DEPARTMENT * *******************************************/ package gov.nist.javax.sip.header.ims; import java.text.ParseException; import javax.sip.header.ExtensionHeader; import gov.nist.javax.sip.address.AddressImpl; import gov.nist.javax.sip.header.ims.PAssertedIdentityHeader; import gov.nist.javax.sip.header.AddressParametersHeader; /** * P-Asserted-Identity SIP Private Header. * * @author ALEXANDRE MIGUEL SILVA SANTOS - Nú 10045401 */ public class PAssertedIdentity extends AddressParametersHeader implements PAssertedIdentityHeader, SIPHeaderNamesIms, ExtensionHeader { /** * constructor * @param address address to set */ public PAssertedIdentity(AddressImpl address) { super(NAME); this.address = address; } /** * default constructor */ public PAssertedIdentity() { super(NAME); } /** Encode into canonical form. *@return String containing the canonicaly encoded header. */ 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(COMMA + this.parameters.encode()); return retval.toString(); } public Object clone() { PAssertedIdentity retval = (PAssertedIdentity) super.clone(); return retval; } public void setValue(String value) throws ParseException { throw new ParseException(value,0); } } java/gov/nist/javax/sip/header/ims/PAssertedIdentityHeader.java0100644 0000000 0000000 00000004032 13513104763 023604 0ustar000000000 0000000 /* * Conditions Of Use * * This software was developed by employees of the National Institute of * Standards and Technology (NIST), an agency of the Federal Government, * and others. * 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 PT INOVACAO- EST DEPARTMENT * *******************************************/ package gov.nist.javax.sip.header.ims; import javax.sip.header.Header; import javax.sip.header.HeaderAddress; /* * @author ALEXANDRE MIGUEL SILVA SANTOS - Nú 10045401 */ /** * P-Asserted-Identity header * Private Header: RFC 3455. * Contains a URI (commonly a SIP URI) and an optional display-name * enable a network of trusted SIP servers to assert * the identity of authenticated users, and the application of existing * privacy mechanisms to the identity problem. * The use of this extension is only applicable inside an administrative * domain with previously agreed-upon policies for generation, * transport and usage of such information. * * */ public interface PAssertedIdentityHeader extends HeaderAddress, Header { /** * Name of AssertIdentityHeader */ public final static String NAME = "P-Asserted-Identity"; } java/gov/nist/javax/sip/header/ims/PAssertedIdentityList.java0100644 0000000 0000000 00000003736 13513104763 023341 0ustar000000000 0000000 /* * Conditions Of Use * * This software was developed by employees of the National Institute of * Standards and Technology (NIST), an agency of the Federal Government, * and others. * 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 PT INOVACAO - EST DEPARTMENT * *******************************************/ package gov.nist.javax.sip.header.ims; import gov.nist.javax.sip.header.SIPHeaderList; /** * List of P-Asserted-Identity headers * * @author Miguel Freitas (IT) PT-Inovacao */ /* * PAssertedID = "P-Asserted-Identity" HCOLON PAssertedID-value * *(COMMA PAssertedID-value) * PAssertedID-value = name-addr / addr-spec */ public class PAssertedIdentityList extends SIPHeaderList { private static final long serialVersionUID = -6465152445570308974L; /** * constructor. */ public PAssertedIdentityList() { super(PAssertedIdentity.class, PAssertedIdentityHeader.NAME); } public Object clone() { PAssertedIdentityList retval = new PAssertedIdentityList(); return retval.clonehlist(this.hlist); } } java/gov/nist/javax/sip/header/ims/PAssertedService.java0100644 0000000 0000000 00000006300 13513104763 022302 0ustar000000000 0000000 package gov.nist.javax.sip.header.ims; /* * 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 * * . * */ import java.text.ParseException; import gov.nist.javax.sip.header.SIPHeader; import javax.sip.header.ExtensionHeader; /** * * @author aayush.bhatnagar * Rancore Technologies Pvt Ltd, Mumbai India. * */ public class PAssertedService extends SIPHeader implements PAssertedServiceHeader, SIPHeaderNamesIms, ExtensionHeader{ private String subServiceIds; private String subAppIds; protected PAssertedService(String name) { super(NAME); } public PAssertedService() { super(P_ASSERTED_SERVICE); } @Override protected String encodeBody() { StringBuffer retval = new StringBuffer(); retval.append(ParameterNamesIms.SERVICE_ID); if(this.subServiceIds!=null) { retval.append(ParameterNamesIms.SERVICE_ID_LABEL).append("."); retval.append(this.getSubserviceIdentifiers()); } else if(this.subAppIds!=null) { retval.append(ParameterNamesIms.APPLICATION_ID_LABEL).append("."); retval.append(this.getApplicationIdentifiers()); } return retval.toString(); } public void setValue(String value) throws ParseException { throw new ParseException(value,0); } public String getApplicationIdentifiers() { if(this.subAppIds.charAt(0)=='.') { return this.subAppIds.substring(1); } return this.subAppIds; } public String getSubserviceIdentifiers() { if(this.subServiceIds.charAt(0)=='.') { return this.subServiceIds.substring(1); } return this.subServiceIds; } public void setApplicationIdentifiers(String appids) { this.subAppIds = appids; } public void setSubserviceIdentifiers(String subservices) { this.subServiceIds = subservices; } public boolean equals(Object other) { return (other instanceof PAssertedServiceHeader) && super.equals(other); } public Object clone() { PAssertedService retval = (PAssertedService) super.clone(); return retval; } } java/gov/nist/javax/sip/header/ims/PAssertedServiceHeader.java0100644 0000000 0000000 00000004224 13513104763 023416 0ustar000000000 0000000 package gov.nist.javax.sip.header.ims; /* * 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 * * . * */ import javax.sip.header.Header; /** * * @author aayush.bhatnagar * Rancore Technologies Pvt Ltd, Mumbai India. * * The ABNF for this header is all follows: * * PAssertedService = "P-Asserted-Service" * HCOLON PAssertedService-value * * PAssertedService-value = Service-ID *(COMMA Service-ID) * * where, * * Service-ID = "urn:urn-7:" urn-service-id * urn-service-id = top-level *("." sub-service-id) * top-level = let-dig [ *26let-dig ] * sub-service-id = let-dig [ *let-dig ] * let-dig = ALPHA / DIGIT / "-" * * Egs: P-Asserted-Service: urn:urn-7:3gpp-service.exampletelephony.version1 * P-Asserted-Service: urn:urn-7:3gpp-application.exampletelephony.version1 * */ public interface PAssertedServiceHeader extends Header{ public static final String NAME = "P-Asserted-Service"; public void setSubserviceIdentifiers(String subservices); public String getSubserviceIdentifiers(); public void setApplicationIdentifiers(String appids); public String getApplicationIdentifiers(); } java/gov/nist/javax/sip/header/ims/PAssociatedURI.java0100644 0000000 0000000 00000011104 13513104763 021644 0ustar000000000 0000000 /* * Conditions Of Use * * This software was developed by employees of the National Institute of * Standards and Technology (NIST), an agency of the Federal Government, * and others. * 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 PT INOVACAO - EST DEPARTMENT and Aveiro University (Portugal) * ****************************************************************************/ package gov.nist.javax.sip.header.ims; import java.text.ParseException; import gov.nist.javax.sip.address.AddressImpl; import gov.nist.javax.sip.address.GenericURI; import javax.sip.address.URI; import javax.sip.header.ExtensionHeader; import gov.nist.javax.sip.header.ims.PAssociatedURIHeader; /** *

    P-Associated-URI SIP Private Header.

    *

    An associated URI is a URI that the service provider * has allocated to a user for his own usage (address-of-record).

    * *

    sintax (RFC 3455):

    *
     * P-Associated-URI  = "P-Associated-URI" HCOLON
     *                    (p-aso-uri-spec) *(COMMA p-aso-uri-spec)
     * p-aso-uri-spec    = name-addr *(SEMI ai-param)
     * ai-param          = generic-param
     * name-addr         =   [display-name] angle-addr
     * angle-addr        =   [CFWS] "<" addr-spec ">" [CFWS] / obs-angle-addr
     * 
    * * @author Miguel Freitas (IT) PT-Inovacao */ public class PAssociatedURI extends gov.nist.javax.sip.header.AddressParametersHeader implements PAssociatedURIHeader, SIPHeaderNamesIms, ExtensionHeader { // TODO: Need a unique UID /** * Default Constructor */ public PAssociatedURI() { super(PAssociatedURIHeader.NAME); } /** * Constructor * @param address to be set in the header */ public PAssociatedURI(AddressImpl address) { super(PAssociatedURIHeader.NAME); this.address = address; } /** * Constructor * @param associatedURI - GenericURI to be set in the address of this header */ public PAssociatedURI(GenericURI associatedURI) { super(PAssociatedURIHeader.NAME); this.address = new AddressImpl(); this.address.setURI(associatedURI); } /** * Encode into canonical form. * @return String containing the canonicaly encoded header. */ 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(); } /** *

    Set the URI on this address

    * @param associatedURI - GenericURI to be set in the address of this header * @throws NullPointerException when supplied URI is null */ public void setAssociatedURI(URI associatedURI) throws NullPointerException { if (associatedURI == null) throw new NullPointerException("null URI"); this.address.setURI(associatedURI); } /** *

    Get the address's URI

    * @return URI set in the address of this header */ public URI getAssociatedURI() { return this.address.getURI(); } public Object clone() { PAssociatedURI retval = (PAssociatedURI) super.clone(); if (this.address != null) retval.address = (AddressImpl) this.address.clone(); return retval; } public void setValue(String value) throws ParseException{ // not implemented throw new ParseException(value,0); } } java/gov/nist/javax/sip/header/ims/PAssociatedURIHeader.java0100644 0000000 0000000 00000005431 13513104763 022763 0ustar000000000 0000000 /* * Conditions Of Use * * This software was developed by employees of the National Institute of * Standards and Technology (NIST), an agency of the Federal Government * and others. * 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 PT INOVACAO - EST DEPARTMENT and Aveiro University (Portugal) * ****************************************************************************/ package gov.nist.javax.sip.header.ims; import javax.sip.header.Header; import javax.sip.header.HeaderAddress; import javax.sip.header.Parameters; import javax.sip.address.URI; /** *

    P-Associated-URI SIP Private Header.

    *

    An associated URI is a URI that the service provider * has allocated to a user for his own usage (address-of-record).

    * *

    sintax (RFC 3455):

    *
     * P-Associated-URI  = "P-Associated-URI" HCOLON
     *                    (p-aso-uri-spec) *(COMMA p-aso-uri-spec)
     * p-aso-uri-spec    = name-addr *(SEMI ai-param)
     * ai-param          = generic-param
     * name-addr         =   [display-name] angle-addr
     * angle-addr        =   [CFWS] "<" addr-spec ">" [CFWS] / obs-angle-addr
     * 
    * * @author Miguel Freitas (IT) PT-Inovacao */ /* */ public interface PAssociatedURIHeader extends HeaderAddress, Parameters, Header { /** * Name of PAssociatedURIHeader */ public final static String NAME = "P-Associated-URI"; /** *

    Set the URI on this address

    * @param associatedURI - GenericURI to be set in the address of this header * @throws NullPointerException when supplied URI is null */ public void setAssociatedURI(URI associatedURI) throws NullPointerException; /** *

    Get the address's URI

    * @return URI set in the address of this header */ public URI getAssociatedURI(); //public void setAssociatedURI(AddressImpl associatedURI); //public AddressImpl getAssociatedURI(); } java/gov/nist/javax/sip/header/ims/PAssociatedURIList.java0100644 0000000 0000000 00000003576 13513104763 022516 0ustar000000000 0000000 /* * Conditions Of Use * * This software was developed by employees of the National Institute of * Standards and Technology (NIST), an agency of the Federal Government, * and others. * 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 PT INOVACAO - EST DEPARTMENT * *******************************************/ package gov.nist.javax.sip.header.ims; import gov.nist.javax.sip.header.SIPHeaderList; /** * List of P-Associated-URI headers * * @author Miguel Freitas (IT) PT-Inovacao */ /* * P-Associated-URI = "P-Associated-URI" ":" # ( "<" URI ">" *( ";" generic-param )) */ public class PAssociatedURIList extends SIPHeaderList { private static final long serialVersionUID = 4454306052557362851L; /** * constructor. */ public PAssociatedURIList() { super(PAssociatedURI.class, PAssociatedURI.NAME); } public Object clone() { PAssociatedURIList retval = new PAssociatedURIList(); return retval.clonehlist(this.hlist); } } java/gov/nist/javax/sip/header/ims/PCalledPartyID.java0100644 0000000 0000000 00000005302 13513104763 021631 0ustar000000000 0000000 /* * Conditions Of Use * * This software was developed by employees of the National Institute of * Standards and Technology (NIST), an agency of the Federal Government * and others. * 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 PT INOVACAO - EST DEPARTMENT * *******************************************/ package gov.nist.javax.sip.header.ims; import java.text.ParseException; import javax.sip.header.ExtensionHeader; import gov.nist.javax.sip.address.AddressImpl; import gov.nist.javax.sip.header.ims.PCalledPartyIDHeader; /** * P-Called-Party-ID SIP Private Header. * * @author ALEXANDRE MIGUEL SILVA SANTOS - Nú 10045401 */ public class PCalledPartyID extends gov.nist.javax.sip.header.AddressParametersHeader implements PCalledPartyIDHeader, SIPHeaderNamesIms , ExtensionHeader{ /** * constructor * @param address address to set */ public PCalledPartyID(AddressImpl address) { super(NAME); this.address = address; } /** * default constructor */ public PCalledPartyID() { super(CALLED_PARTY_ID); } /** Encode into canonical form. *@return String containing the canonicaly encoded header. */ 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 { // not implemented. throw new ParseException(value,0); } } java/gov/nist/javax/sip/header/ims/PCalledPartyIDHeader.java0100644 0000000 0000000 00000004566 13513104763 022755 0ustar000000000 0000000 /* * Conditions Of Use * * This software was developed by employees of the National Institute of * Standards and Technology (NIST), an agency of the Federal Government * and others. * 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 PT INOVACAO - EST DEPARTMENT * *******************************************/ package gov.nist.javax.sip.header.ims; import javax.sip.header.Header; import javax.sip.header.HeaderAddress; import javax.sip.header.Parameters; /** * P-Called-Party-ID header - Private Header: RFC 3455. *

    A proxy server inserts a P-Called-Party-ID header, typically in an INVITE request, * en-route to its destination. The header is populated with the Request-URI received * by the proxy in the request.

    *

    Both the business SIP URI and the personal SIP URI are registered in the SIP registrar, * so both URIs can receive invitations to new sessions. When the user receives an invitation * to join a session, he/she should be aware of which of the several registered SIP URIs this * session was sent to.

    * *
     * P-Called-Party-ID    = "P-Called-Party-ID" HCOLON
     *                        called-pty-id-spec
     * called-pty-id-spec   = name-addr *(SEMI cpid-param)
     * cpid-param           = generic-param
     * 
    * * @author ALEXANDRE MIGUEL SILVA SANTOS - Nú 10045401 * */ public interface PCalledPartyIDHeader extends HeaderAddress, Parameters, Header { /** * Name of CalledPartyIDHeader */ public final static String NAME = "P-Called-Party-ID"; } java/gov/nist/javax/sip/header/ims/PChargingFunctionAddresses.java0100644 0000000 0000000 00000022622 13513104763 024302 0ustar000000000 0000000 /* * Conditions Of Use * * This software was developed by employees of the National Institute of * Standards and Technology (NIST), an agency of the Federal Government * and others. * 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 PT INOVACAO - EST DEPARTMENT * *******************************************/ package gov.nist.javax.sip.header.ims; import gov.nist.core.NameValue; import java.text.ParseException; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.ListIterator; import javax.sip.header.ExtensionHeader; import gov.nist.javax.sip.header.ims.PChargingFunctionAddressesHeader; import gov.nist.javax.sip.header.ims.ParameterNamesIms; /** *

    P-Charging-Function-Addresses SIP Private Header.

    * *

    Sintax (RFC 3455):

    *
     * P-Charging-Addr        = "P-Charging-Function-Addresses" HCOLON
     *                           charge-addr-params
     *                           *(SEMI charge-addr-params)
     * charge-addr-params     = ccf / ecf / generic-param
     * ccf                    = "ccf" EQUAL gen-value
     * ecf                    = "ecf" EQUAL gen-value
     * gen-value              = token / host / quoted-string
     * 
    * *

    example:

    *

    P-Charging-Function-Addresses: ccf=192.1.1.1; ccf=192.1.1.2; * ecf=192.1.1.3; ecf=192.1.1.4

    * *

    TODO: add PARSER support for IPv6 address. * eg: P-Charging-Function-Addresses: ccf=[5555.b99.c88.d77.e66]; ecf=[5555.6aa.7bb.8cc.9dd]

    * * @author ALEXANDRE MIGUEL SILVA SANTOS - Nú 10045401 */ public class PChargingFunctionAddresses extends gov.nist.javax.sip.header.ParametersHeader implements PChargingFunctionAddressesHeader, SIPHeaderNamesIms , ExtensionHeader{ // TODO: serialVersionUID /** * Defaul Constructor */ public PChargingFunctionAddresses() { super(P_CHARGING_FUNCTION_ADDRESSES); } /* (non-Javadoc) * @see gov.nist.javax.sip.header.ParametersHeader#encodeBody() */ protected String encodeBody() { StringBuffer encoding = new StringBuffer(); // issued by Miguel Freitas if (!duplicates.isEmpty()) { encoding.append(duplicates.encode()); } return encoding.toString(); } /** *

    Set the Charging Collection Function (CCF) Address

    * * @param ccfAddress - the address to set in the CCF parameter * @throws ParseException */ public void setChargingCollectionFunctionAddress(String ccfAddress) throws ParseException { if (ccfAddress == null) throw new NullPointerException( "JAIN-SIP Exception, " + "P-Charging-Function-Addresses, setChargingCollectionFunctionAddress(), the ccfAddress parameter is null."); // setParameter(ParameterNamesIms.CCF, ccfAddress); setMultiParameter(ParameterNamesIms.CCF, ccfAddress); } /** *

    Add another Charging Collection Function (CCF) Address to this header

    * * @param ccfAddress - the address to set in the CCF parameter * @throws ParseException */ public void addChargingCollectionFunctionAddress(String ccfAddress) throws ParseException { if (ccfAddress == null) throw new NullPointerException( "JAIN-SIP Exception, " + "P-Charging-Function-Addresses, setChargingCollectionFunctionAddress(), the ccfAddress parameter is null."); this.parameters.set(ParameterNamesIms.CCF, ccfAddress); } /** *

    Remove a Charging Collection Function (CCF) Address set in this header

    * * @param ccfAddress - the address in the CCF parameter to remove * @throws ParseException if the address was not removed */ public void removeChargingCollectionFunctionAddress(String ccfAddress) throws ParseException { if (ccfAddress == null) throw new NullPointerException( "JAIN-SIP Exception, " + "P-Charging-Function-Addresses, setChargingCollectionFunctionAddress(), the ccfAddress parameter is null."); if(!this.delete(ccfAddress, ParameterNamesIms.CCF)) { throw new ParseException("CCF Address Not Removed",0); } } /** *

    Get all the Charging Collection Function (CCF) Addresses set in this header

    * * @return ListIterator that constains all CCF addresses of this header */ public ListIterator getChargingCollectionFunctionAddresses() { Iterator li = this.parameters.iterator(); LinkedList ccfLIST = new LinkedList(); NameValue nv; while (li.hasNext()) { nv = (NameValue) li.next(); if (nv.getName().equalsIgnoreCase(ParameterNamesIms.CCF)) { NameValue ccfNV = new NameValue(); ccfNV.setName(nv.getName()); ccfNV.setValueAsObject(nv.getValueAsObject()); ccfLIST.add(ccfNV); } } return ccfLIST.listIterator(); } /** *

    Set the Event Charging Function (ECF) Address

    * * @param ecfAddress - the address to set in the ECF parameter * @throws ParseException */ public void setEventChargingFunctionAddress(String ecfAddress) throws ParseException { if (ecfAddress == null) throw new NullPointerException( "JAIN-SIP Exception, " + "P-Charging-Function-Addresses, setEventChargingFunctionAddress(), the ecfAddress parameter is null."); setMultiParameter(ParameterNamesIms.ECF, ecfAddress); // setParameter(ParameterNamesIms.ECF, ecfAddress); } /** *

    Add another Event Charging Function (ECF) Address to this header

    * * @param ecfAddress - the address to set in the ECF parameter * @throws ParseException */ public void addEventChargingFunctionAddress(String ecfAddress) throws ParseException { if (ecfAddress == null) throw new NullPointerException( "JAIN-SIP Exception, " + "P-Charging-Function-Addresses, setEventChargingFunctionAddress(), the ecfAddress parameter is null."); this.parameters.set(ParameterNamesIms.ECF, ecfAddress); } /** *

    Remove a Event Charging Function (ECF) Address set in this header

    * * @param ecfAddress - the address in the ECF parameter to remove * @throws ParseException if the address was not removed */ public void removeEventChargingFunctionAddress(String ecfAddress) throws ParseException { if (ecfAddress == null) throw new NullPointerException( "JAIN-SIP Exception, " + "P-Charging-Function-Addresses, setEventChargingFunctionAddress(), the ecfAddress parameter is null."); if(!this.delete(ecfAddress, ParameterNamesIms.ECF)) { throw new java.text.ParseException("ECF Address Not Removed",0); } } /** *

    Get all the Event Charging Function (ECF) Addresses set in this header

    * * @return ListIterator that constains all CCF addresses of this header */ public ListIterator getEventChargingFunctionAddresses() { LinkedList listw = new LinkedList(); Iterator li = this.parameters.iterator(); ListIterator ecfLIST = listw.listIterator(); NameValue nv; boolean removed = false; while (li.hasNext()) { nv = (NameValue) li.next(); if (nv.getName().equalsIgnoreCase(ParameterNamesIms.ECF)) { NameValue ecfNV = new NameValue(); ecfNV.setName(nv.getName()); ecfNV.setValueAsObject(nv.getValueAsObject()); ecfLIST.add(ecfNV); } } return ecfLIST; } /** *

    Remove parameter

    * * @param value - of the parameter * @param name - of the parameter * @return true if parameter was removed, and false if not */ public boolean delete(String value, String name) { Iterator li = this.parameters.iterator(); NameValue nv; boolean removed = false; while (li.hasNext()) { nv = (NameValue) li.next(); if (((String) nv.getValueAsObject()).equalsIgnoreCase(value) && nv.getName().equalsIgnoreCase(name)) { li.remove(); removed = true; } } return removed; } public void setValue(String value) throws ParseException { throw new ParseException ( value,0); } } java/gov/nist/javax/sip/header/ims/PChargingFunctionAddressesHeader.java0100644 0000000 0000000 00000012175 13513104763 025415 0ustar000000000 0000000 /* * Conditions Of Use * * This software was developed by employees of the National Institute of * Standards and Technology (NIST), an agency of the Federal Government * and others. * 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 PT INOVACAO - EST DEPARTMENT * *******************************************/ package gov.nist.javax.sip.header.ims; import gov.nist.core.NameValue; import javax.sip.header.Header; import javax.sip.header.Parameters; import java.text.ParseException; import java.util.ArrayList; import java.util.ListIterator; /** * P-Charging-Function-Addresses header - * Private Header: RFC 3455. * * There is a need to inform each SIP proxy involved in a transaction about the common * charging functional entities to receive the generated charging records or charging events. *
      *
    • * - CCF is used for off-line charging (e.g., for postpaid account charging). *
    • * - ECF is used for on-line charging (e.g., for pre-paid account charging). *
    * Only one instance of the header MUST be present in a particular request or response. * *
     * P-Charging-Addr = "P-Charging-Function-Addresses" HCOLON
     *          charge-addr-params
     *          *(SEMI charge-addr-params)
     * charge-addr-params   = ccf / ecf / generic-param
     * ccf              = "ccf" EQUAL gen-value
     * ecf              = "ecf" EQUAL gen-value
     *
     * gen-value    = token / host / quoted-string
     *
     * host             =  hostname / IPv4address / IPv6reference
     * hostname         =  *( domainlabel "." ) toplabel [ "." ]
     * domainlabel      =  alphanum / alphanum *( alphanum / "-" ) alphanum
     * toplabel         =  ALPHA / ALPHA *( alphanum / "-" ) alphanum
     *
     *
     * example:
     *  P-Charging-Function-Addresses: ccf=192.1.1.1; ccf=192.1.1.2;
     *  ecf=192.1.1.3; ecf=192.1.1.4
     * 
    * * @author ALEXANDRE MIGUEL SILVA SANTOS - Nú 10045401 */ public interface PChargingFunctionAddressesHeader extends Parameters, Header { /** * Name of PChargingFunctionAddressesHeader */ public final static String NAME = "P-Charging-Function-Addresses"; /** *

    Set the Charging Collection Function (CCF) Address

    * @param ccfAddress - the address to set in the CCF parameter * @throws ParseException */ public void setChargingCollectionFunctionAddress(String ccfAddress) throws ParseException; /** *

    Add another Charging Collection Function (CCF) Address to this header

    * @param ccfAddress - the address to set in the CCF parameter * @throws ParseException */ public void addChargingCollectionFunctionAddress(String ccfAddress) throws ParseException; /** *

    Remove a Charging Collection Function (CCF) Address set in this header

    * @param ccfAddress - the address in the CCF parameter to remove * @throws ParseException if the address was not removed */ public void removeChargingCollectionFunctionAddress(String ccfAddress) throws ParseException; /** *

    Get all the Charging Collection Function (CCF) Addresses set in this header

    * @return ListIterator that constains all CCF addresses of this header */ public ListIterator getChargingCollectionFunctionAddresses(); /** *

    Set the Event Charging Function (ECF) Address

    * @param ecfAddress - the address to set in the ECF parameter * @throws ParseException */ public void setEventChargingFunctionAddress(String ecfAddress)throws ParseException; /** *

    Add another Event Charging Function (ECF) Address to this header

    * @param ecfAddress - the address to set in the ECF parameter * @throws ParseException */ public void addEventChargingFunctionAddress(String ecfAddress) throws ParseException; /** *

    Remove a Event Charging Function (ECF) Address set in this header

    * @param ecfAddress - the address in the ECF parameter to remove * @throws ParseException if the address was not removed */ public void removeEventChargingFunctionAddress(String ecfAddress) throws ParseException; /** *

    Get all the Event Charging Function (ECF) Addresses set in this header

    * @return ListIterator that constains all CCF addresses of this header */ public ListIterator getEventChargingFunctionAddresses(); } java/gov/nist/javax/sip/header/ims/PChargingVector.java0100644 0000000 0000000 00000014610 13513104763 022117 0ustar000000000 0000000 /* * 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 PT INOVACAO - EST DEPARTMENT * *******************************************/ package gov.nist.javax.sip.header.ims; import java.text.ParseException; import javax.sip.header.ExtensionHeader; import gov.nist.javax.sip.header.ims.PChargingVectorHeader; import gov.nist.javax.sip.header.ims.ParameterNamesIms; /** * P-Charging-Vector header SIP Private Header: RFC 3455. * * @author ALEXANDRE MIGUEL SILVA SANTOS */ public class PChargingVector extends gov.nist.javax.sip.header.ParametersHeader implements PChargingVectorHeader, SIPHeaderNamesIms, ExtensionHeader { /** * Default Constructor */ public PChargingVector() { super(P_CHARGING_VECTOR); } /* * (non-Javadoc) * * @see gov.nist.javax.sip.header.ParametersHeader#encodeBody() */ protected String encodeBody() { 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 * should throw an exception * * JvB 26/5: fix for issue #159, check for quotes around icid value */ gov.nist.core.NameValue nv = getNameValue( ParameterNamesIms.ICID_VALUE ); nv.encode( encoding ); //the remaining parameters are optional. // check for their presence, then add the parameter if it exists. if (parameters.containsKey(ParameterNamesIms.ICID_GENERATED_AT)) encoding.append(SEMICOLON).append( ParameterNamesIms.ICID_GENERATED_AT).append(EQUALS).append( getICIDGeneratedAt()); if (parameters.containsKey(ParameterNamesIms.TERM_IOI)) encoding.append(SEMICOLON).append(ParameterNamesIms.TERM_IOI) .append(EQUALS).append(getTerminatingIOI()); if (parameters.containsKey(ParameterNamesIms.ORIG_IOI)) encoding.append(SEMICOLON).append(ParameterNamesIms.ORIG_IOI) .append(EQUALS).append(getOriginatingIOI()); return encoding.toString(); } /** *

    * Get the icid-value parameter value *

    * * @return the value of the icid-value parameter */ public String getICID() { return getParameter(ParameterNamesIms.ICID_VALUE); } /** *

    * Set the icid-value parameter *

    * * @param icid - * value to set in the icid-value parameter * @throws ParseException */ public void setICID(String icid) throws ParseException { if (icid == null) throw new NullPointerException( "JAIN-SIP Exception, " + "P-Charging-Vector, setICID(), the icid parameter is null."); setParameter(ParameterNamesIms.ICID_VALUE, icid); } /** *

    * Get the icid-generated-at parameter value *

    * * @return the icid-generated-at parameter value */ public String getICIDGeneratedAt() { return getParameter(ParameterNamesIms.ICID_GENERATED_AT); } /** *

    * Set the icid-generated-at parameter *

    * * @param host - * value to set in the icid-generated-at parameter * @throws ParseException */ public void setICIDGeneratedAt(String host) throws ParseException { if (host == null) throw new NullPointerException( "JAIN-SIP Exception, " + "P-Charging-Vector, setICIDGeneratedAt(), the host parameter is null."); setParameter(ParameterNamesIms.ICID_GENERATED_AT, host); } /** *

    * Get the orig-ioi parameter value *

    * * @return the orig-ioi parameter value */ public String getOriginatingIOI() { return getParameter(ParameterNamesIms.ORIG_IOI); } /** *

    * Set the orig-ioi parameter *

    * * @param origIOI - * value to set in the orig-ioi parameter. If value is null or * empty, the parameter is removed * @throws ParseException */ public void setOriginatingIOI(String origIOI) throws ParseException { if (origIOI == null || origIOI.length() == 0) { removeParameter(ParameterNamesIms.ORIG_IOI); } else setParameter(ParameterNamesIms.ORIG_IOI, origIOI); } /** *

    * Get the term-ioi parameter value *

    * * @return the term-ioi parameter value */ public String getTerminatingIOI() { return getParameter(ParameterNamesIms.TERM_IOI); } /** *

    * Set the term-ioi parameter *

    * * @param termIOI - * value to set in the term-ioi parameter. If value is null or * empty, the parameter is removed * @throws ParseException */ public void setTerminatingIOI(String termIOI) throws ParseException { if (termIOI == null || termIOI.length() == 0) { removeParameter(ParameterNamesIms.TERM_IOI); } else setParameter(ParameterNamesIms.TERM_IOI, termIOI); } public void setValue(String value) throws ParseException { throw new ParseException(value, 0); } } java/gov/nist/javax/sip/header/ims/PChargingVectorHeader.java0100644 0000000 0000000 00000012125 13513104763 023227 0ustar000000000 0000000 /* * Conditions Of Use * * This software was developed by employees of the National Institute of * Standards and Technology (NIST), an agency of the Federal Government * and others. * 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 PT INOVACAO - EST DEPARTMENT * *******************************************/ package gov.nist.javax.sip.header.ims; import java.text.ParseException; import javax.sip.header.Header; import javax.sip.header.Parameters; /** *

    P-Charging-Vector header SIP Private Header.

    * *

    Sintax (RFC 3455):

    *
     * P-Charging-Vector   = "P-Charging-Vector" HCOLON icid-value (SEMI charge-params)
     * charge-params        = icid-gen-addr / orig-ioi / term-ioi / generic-param
     * icid-value           = "icid-value" EQUAL gen-value
     * icid-gen-addr        = "icid-generated-at" EQUAL host
     * orig-ioi             = "orig-ioi" EQUAL gen-value
     * term-ioi             = "term-ioi" EQUAL gen-value
     * 
    * *

    Sintax from RFC3261:

    *
     * generic-param       = token [ EQUAL gen-value ]
     * gen-value           = token / host / quoted-string
     * host                = hostname / IPv4address / Ipv6reference
     * 
    * * *

    syntax as in 3GPP TS 24.229-720 (2005-12) : * * The access-network-charging-info parameter is an instance of generic-param * from the current charge-params:

    * *
     * access-network-charging-info   = (gprs-charging-info / i-wlan-charging-info / xdsl-charging-info / generic-param)
     * gprs-charging-info          = ggsn SEMI auth-token [SEMI pdp-info-hierarchy] *(SEMI extension-param)
     * ggsn                        = "ggsn" EQUAL gen-value
     * pdp-info-hierarchy          = "pdp-info" EQUAL LDQUOT pdp-info *(COMMA pdp-info) RDQUOT
     * pdp-info                    = pdp-item SEMI pdp-sig SEMI gcid [SEMI flow-id]
     * pdp-item                    = "pdp-item" EQUAL DIGIT
     * pdp-sig                     = "pdp-sig" EQUAL ("yes" / "no")
     * gcid                        = "gcid" EQUAL 1*HEXDIG
     * auth-token                  = "auth-token" EQUAL 1*HEXDIG
     * flow-id                     = "flow-id" EQUAL "(" "{" 1*DIGIT COMMA 1*DIGIT "}" *(COMMA "{" 1*DIGIT COMMA 1*DIGIT"}")")"
     * extension-param             = token [EQUAL token]
     * i-wlan-charging-info        = "pdg"
     * xdsl-charging-info          = bras SEMI auth-token [SEMI xDSL-bearer-info] *(SEMI extension-param)
     * bras                        = "bras" EQUAL gen-value
     * xDSL-bearer-info            = "dsl-bearer-info" EQUAL LDQUOT dsl-bearer-info *(COMMA dsl-bearer-info) RDQUOT
     * dsl-bearer-info             = dsl-bearer-item SEMI dsl-bearer-sig SEMI dslcid [SEMI flow-id]
     * dsl-bearer-item             = "dsl-bearer-item" EQUAL DIGIT
     * dsl-bearer-sig              = "dsl-bearer-sig"
     * 
    * * *

    example: * P-Charging-Vector: icid-value=1234bc9876e; icid-generated-at=192.0.6.8; orig-ioi=home1.net

    * * *

    TODO: gen-value can be token / host / quoted-string

    *

    TODO: add suport for the new header extensions access-network-charging-info

    * * @author ALEXANDRE MIGUEL SILVA SANTOS */ public interface PChargingVectorHeader extends Header, Parameters { /** * Name of PChargingVectorHeader */ public final static String NAME = "P-Charging-Vector"; /** * @return -- icid value. */ public String getICID(); /** * @param icid * @throws ParseException */ public void setICID(String icid) throws ParseException; /** * @return -- the ICID generatedAt field. */ public String getICIDGeneratedAt(); /** * @param host -- set the icid host value. * * @throws ParseException -- if bad host value. */ public void setICIDGeneratedAt(String host) throws ParseException; /** * * @return the originating IOI */ public String getOriginatingIOI(); /** * @param origIOI * @throws ParseException * */ public void setOriginatingIOI(String origIOI) throws ParseException; /** * @return -- the terminating IOI field */ public String getTerminatingIOI(); /** * @param termIOI -- the terminating IOI field to set. * @throws ParseException */ public void setTerminatingIOI(String termIOI) throws ParseException; } java/gov/nist/javax/sip/header/ims/PMediaAuthorization.java0100644 0000000 0000000 00000007366 13513104763 023024 0ustar000000000 0000000 /* * Conditions Of Use * * This software was developed by employees of the National Institute of * Standards and Technology (NIST), an agency of the Federal Government * and others. * 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 PT INOVACAO - EST DEPARTMENT and Aveiro University - Portugal) * *****************************************************************************/ package gov.nist.javax.sip.header.ims; import java.text.ParseException; import gov.nist.javax.sip.header.SIPHeader; import javax.sip.InvalidArgumentException; import javax.sip.header.ExtensionHeader; import javax.sip.header.HeaderAddress; import javax.sip.header.Parameters; /** * P-Media-Authorization SIP Private Header - RFC 3313. * *

    Sintax:

    *
     * P-Media-Authorization   = "P-Media-Authorization" HCOLON
     *                            P-Media-Authorization-Token
     *                            *(COMMA P-Media-Authorization-Token)
     * P-Media-Authorization-Token = 1*HEXDIG
     * 
    * @author Miguel Freitas (IT) PT-Inovacao */ public class PMediaAuthorization extends SIPHeader implements PMediaAuthorizationHeader, SIPHeaderNamesIms, ExtensionHeader { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -6463630258703731133L; /** * P-Media-Authorization Token */ private String token; /** * Constructor */ public PMediaAuthorization() { super(P_MEDIA_AUTHORIZATION); } /** * Get the media authorization token. * * @return token */ public String getToken() { return token; } /** * Set the media authorization token. * * @param token - media authorization token to set * @throws InvalidArgumentException - if token is null or empty */ public void setMediaAuthorizationToken(String token) throws InvalidArgumentException { if (token == null || token.length() == 0) throw new InvalidArgumentException(" the Media-Authorization-Token parameter is null or empty"); this.token = token; } /** * Encode header * @return the header content */ protected String encodeBody() { return token; } public void setValue(String value) throws ParseException { throw new ParseException (value,0); } public boolean equals(Object other) { if (other instanceof PMediaAuthorizationHeader) { final PMediaAuthorizationHeader o = (PMediaAuthorizationHeader) other; return this.getToken().equals(o.getToken()); } return false; } public Object clone() { PMediaAuthorization retval = (PMediaAuthorization) super.clone(); if (this.token != null) retval.token = this.token; return retval; } } java/gov/nist/javax/sip/header/ims/PMediaAuthorizationHeader.java0100644 0000000 0000000 00000004501 13513104763 024121 0ustar000000000 0000000 /* * 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 PT INOVACAO - EST DEPARTMENT and Aveiro University - Portugal) * *****************************************************************************/ package gov.nist.javax.sip.header.ims; import javax.sip.InvalidArgumentException; import javax.sip.header.Header; /** * The P-Media-Authorization SIP Private Header - RFC 3313. * *

    Sintax:

    *
     * P-Media-Authorization   = "P-Media-Authorization" HCOLON
     *                            P-Media-Authorization-Token
     *                            *(COMMA P-Media-Authorization-Token)
     * P-Media-Authorization-Token = 1*HEXDIG
     * 
    * * @author Miguel Freitas (IT) PT-Inovacao */ public interface PMediaAuthorizationHeader extends Header { /** * Name of PMediaAuthorizationHeader */ public final static String NAME = "P-Media-Authorization"; /** * Set the media authorization token. * @param token - media authorization token to set * @throws InvalidArgumentException - if token is null or empty */ public void setMediaAuthorizationToken(String token) throws InvalidArgumentException; /** * Get the media authorization token. * @return token */ public String getToken(); } java/gov/nist/javax/sip/header/ims/PMediaAuthorizationList.java0100644 0000000 0000000 00000003605 13513104763 023650 0ustar000000000 0000000 /* * 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 PT INOVACAO - EST DEPARTMENT and Aveiro University - Portugal) * *****************************************************************************/ package gov.nist.javax.sip.header.ims; import gov.nist.javax.sip.header.SIPHeaderList; /** * List of P-Media-Authorization headers. * * @author Miguel Freitas (IT) PT-Inovacao */ public class PMediaAuthorizationList extends SIPHeaderList { private static final long serialVersionUID = -8226328073989632317L; public PMediaAuthorizationList() { super(PMediaAuthorization.class, PMediaAuthorizationHeader.NAME); } public Object clone() { PMediaAuthorizationList retval = new PMediaAuthorizationList(); return retval.clonehlist(this.hlist); } } java/gov/nist/javax/sip/header/ims/PPreferredIdentity.java0100644 0000000 0000000 00000005107 13513104763 022643 0ustar000000000 0000000 /* * 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 PT INOVACAO - EST DEPARTMENT * *******************************************/ package gov.nist.javax.sip.header.ims; import java.text.ParseException; import javax.sip.header.ExtensionHeader; import gov.nist.javax.sip.address.AddressImpl; import gov.nist.javax.sip.header.AddressParametersHeader; /** * P-Preferred-Identity SIP Private Header - RFC 3325. * * @author ALEXANDRE MIGUEL SILVA SANTOS - Nú 10045401 */ public class PPreferredIdentity extends AddressParametersHeader implements PPreferredIdentityHeader, SIPHeaderNamesIms , ExtensionHeader { /** * constructor * @param address address to set */ public PPreferredIdentity(AddressImpl address) { super(NAME); this.address = address; } /** * default constructor */ public PPreferredIdentity() { super(P_PREFERRED_IDENTITY); } /** Encode into canonical form. * @return String containing the canonicaly encoded header. */ 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); } return retval.toString(); } public void setValue(String value) throws ParseException { throw new ParseException (value,0); } } java/gov/nist/javax/sip/header/ims/PPreferredIdentityHeader.java0100644 0000000 0000000 00000004210 13513104763 023746 0ustar000000000 0000000 /* * 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 PT INOVACAO - EST DEPARTMENT * *******************************************/ package gov.nist.javax.sip.header.ims; import javax.sip.header.Header; import javax.sip.header.HeaderAddress; /** * P-Preferred-Identity header - * SIP Private Header: RFC 3325 * *
      *
    • * . is used from a user agent to a trusted proxy to carry the identity the * user sending the SIP message wishes to be used for the P-Asserted-Header * field value that the trusted element will insert. *
    • * . If there are two values, one value MUST be a sip or sips URI and the other * MUST be a tel URI. *
    * *

    Sintax:

    *
     * PPreferredID = "P-Preferred-Identity" HCOLON PPreferredID-value
     *                 *(COMMA PPreferredID-value)
     * PPreferredID-value = name-addr / addr-spec
     * 
    * * @author ALEXANDRE MIGUEL SILVA SANTOS - Nú 10045401 */ public interface PPreferredIdentityHeader extends HeaderAddress, Header { /** * Name of PreferredIdentityHeader */ public final static String NAME = "P-Preferred-Identity"; } java/gov/nist/javax/sip/header/ims/PPreferredService.java0100644 0000000 0000000 00000006246 13513104763 022457 0ustar000000000 0000000 package gov.nist.javax.sip.header.ims; /* * 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 * * . * */ import java.text.ParseException; import javax.sip.header.ExtensionHeader; import gov.nist.javax.sip.header.SIPHeader; /** * * @author aayush.bhatnagar * */ public class PPreferredService extends SIPHeader implements PPreferredServiceHeader, SIPHeaderNamesIms, ExtensionHeader{ private String subServiceIds; private String subAppIds; protected PPreferredService(String name) { super(NAME); } public PPreferredService() { super(P_PREFERRED_SERVICE); } @Override protected String encodeBody() { StringBuffer retval = new StringBuffer(); retval.append(ParameterNamesIms.SERVICE_ID); if(this.subServiceIds!=null) { retval.append(ParameterNamesIms.SERVICE_ID_LABEL).append("."); retval.append(this.getSubserviceIdentifiers()); } else if(this.subAppIds!=null) { retval.append(ParameterNamesIms.APPLICATION_ID_LABEL).append("."); retval.append(this.getApplicationIdentifiers()); } return retval.toString(); } public void setValue(String value) throws ParseException { throw new ParseException(value,0); } public String getApplicationIdentifiers() { if(this.subAppIds.charAt(0)=='.') { return this.subAppIds.substring(1); } return this.subAppIds; } public String getSubserviceIdentifiers() { if(this.subServiceIds.charAt(0)=='.') { return this.subServiceIds.substring(1); } return this.subServiceIds; } public void setApplicationIdentifiers(String appids) { this.subAppIds = appids; } public void setSubserviceIdentifiers(String subservices) { this.subServiceIds = ".".concat(subservices); } public boolean equals(Object other) { return (other instanceof PPreferredServiceHeader) && super.equals(other); } public Object clone() { PPreferredService retval = (PPreferredService) super.clone(); return retval; } } java/gov/nist/javax/sip/header/ims/PPreferredServiceHeader.java0100644 0000000 0000000 00000004160 13513104763 023561 0ustar000000000 0000000 package gov.nist.javax.sip.header.ims; /* * 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 * * . * */ import javax.sip.header.Header; /** * * @author aayush.bhatnagar * * The ABNF for this header is all follows: * * PPreferredService = "P-Preferred-Service" * HCOLON PPreferredService-value * * PPreferredService-value = Service-ID *(COMMA Service-ID) * * where, * * Service-ID = "urn:urn-7:" urn-service-id * urn-service-id = top-level *("." sub-service-id) * top-level = let-dig [ *26let-dig ] * sub-service-id = let-dig [ *let-dig ] * let-dig = ALPHA / DIGIT / "-" * * Egs: P-Preferred-Service: urn:urn-7:3gpp-service.exampletelephony.version1 * P-Preferred-Service: urn:urn-7:3gpp-application.exampletelephony.version1 * */ public interface PPreferredServiceHeader extends Header{ public static final String NAME = "P-Preferred-Service"; public void setSubserviceIdentifiers(String subservices); public String getSubserviceIdentifiers(); public void setApplicationIdentifiers(String appids); public String getApplicationIdentifiers(); } java/gov/nist/javax/sip/header/ims/PProfileKey.java0100644 0000000 0000000 00000004765 13513104763 021275 0ustar000000000 0000000 package gov.nist.javax.sip.header.ims; /* * 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 * * . * */ import java.text.ParseException; import gov.nist.javax.sip.address.AddressImpl; import gov.nist.javax.sip.header.AddressParametersHeader; import javax.sip.header.ExtensionHeader; /** * * @author aayush.bhatnagar * Rancore Technologies Pvt Ltd, Mumbai India. * */ public class PProfileKey extends AddressParametersHeader implements PProfileKeyHeader, SIPHeaderNamesIms , ExtensionHeader { public PProfileKey( ) { super(P_PROFILE_KEY); } public PProfileKey(AddressImpl address) { super(NAME); this.address = address; } @Override protected 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); } public boolean equals(Object other) { return (other instanceof PProfileKey) && super.equals(other); } public Object clone() { PProfileKey retval = (PProfileKey) super.clone(); return retval; } } java/gov/nist/javax/sip/header/ims/PProfileKeyHeader.java0100644 0000000 0000000 00000003130 13513104763 022367 0ustar000000000 0000000 package gov.nist.javax.sip.header.ims; /* * 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 * * . * */ import javax.sip.header.Header; import javax.sip.header.HeaderAddress; /** * * @author aayush.bhatnagar * Rancore Technologies Pvt Ltd, Mumbai India. * * The ABNF syntax of this header is as follows: * P-Profile-Key = "P-Profile-Key" HCOLON {name-addr / addr-spec} * *{ SEMI generic-param } * * Eg: P-Profile-Key: * */ public interface PProfileKeyHeader extends HeaderAddress, Header{ public final static String NAME = "P-Profile-Key"; } java/gov/nist/javax/sip/header/ims/PServedUser.java0100644 0000000 0000000 00000011335 13513104763 021302 0ustar000000000 0000000 package gov.nist.javax.sip.header.ims; /* * 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 * * . * */ import java.text.ParseException; import javax.sip.InvalidArgumentException; import javax.sip.header.ExtensionHeader; import gov.nist.javax.sip.address.AddressImpl; import gov.nist.javax.sip.header.AddressParametersHeader; /** * * @author aayush.bhatnagar * Rancore Technologies Pvt Ltd, Mumbai India. * * This is the class used for encoding of the P-Served-User header * * */ public class PServedUser extends AddressParametersHeader implements PServedUserHeader, SIPHeaderNamesIms, ExtensionHeader{ public PServedUser(AddressImpl address) { super(P_SERVED_USER); this.address = address; } public PServedUser() { super(NAME); } public String getRegistrationState() { return getParameter(ParameterNamesIms.REGISTRATION_STATE); } public String getSessionCase() { return getParameter(ParameterNamesIms.SESSION_CASE); } public void setRegistrationState(String registrationState) { if((registrationState!=null)) { if(registrationState.equals("reg")||registrationState.equals("unreg")) { try { setParameter(ParameterNamesIms.REGISTRATION_STATE, registrationState); } catch (ParseException e) { e.printStackTrace(); } } else { try { throw new InvalidArgumentException("Value can be either reg or unreg"); } catch (InvalidArgumentException e) { e.printStackTrace(); } } } else { throw new NullPointerException("regstate Parameter value is null"); } } public void setSessionCase(String sessionCase) { if((sessionCase!=null)) { if((sessionCase.equals("orig"))||(sessionCase.equals("term"))) { try { setParameter(ParameterNamesIms.SESSION_CASE, sessionCase); } catch (ParseException e) { e.printStackTrace(); } } else { try { throw new InvalidArgumentException("Value can be either orig or term"); } catch (InvalidArgumentException e) { e.printStackTrace(); } } } else { throw new NullPointerException("sess-case Parameter value is null"); } } @Override protected String encodeBody() { StringBuffer retval = new StringBuffer(); retval.append(address.encode()); if(parameters.containsKey(ParameterNamesIms.REGISTRATION_STATE)) retval.append(SEMICOLON).append(ParameterNamesIms.REGISTRATION_STATE).append(EQUALS) .append(this.getRegistrationState()); if(parameters.containsKey(ParameterNamesIms.SESSION_CASE)) retval.append(SEMICOLON).append(ParameterNamesIms.SESSION_CASE).append(EQUALS) .append(this.getSessionCase()); return retval.toString(); } public void setValue(String value) throws ParseException { throw new ParseException(value,0); } public boolean equals(Object other) { if(other instanceof PServedUser) { final PServedUserHeader psu = (PServedUserHeader)other; return this.getAddress().equals(((PServedUser) other).getAddress()); } return false; } public Object clone() { PServedUser retval = (PServedUser) super.clone(); return retval; } } java/gov/nist/javax/sip/header/ims/PServedUserHeader.java0100644 0000000 0000000 00000004062 13513104763 022412 0ustar000000000 0000000 package gov.nist.javax.sip.header.ims; /* * 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 * * . * */ /** * * @author aayush.bhatnagar * Rancore Technologies Pvt Ltd, Mumbai India. * * The ABNF of the P-Served-User Header is as follows: * * P-Served-User = "P-Served-User" HCOLON PServedUser-value * *(SEMI served-user-param) * served-user-param = sessioncase-param * / registration-state-param * / generic-param * PServedUser-value = name-addr / addr-spec * sessioncase-param = "sescase" EQUAL "orig" / "term" * registration-state-param = "regstate" EQUAL "unreg" / "reg" * * Eg: P-Served-User: ; sescase=orig; regstate=reg * * */ public interface PServedUserHeader { public static final String NAME = "P-Served-User"; public void setSessionCase(String sessionCase); public String getSessionCase(); public void setRegistrationState(String registrationState); public String getRegistrationState(); } java/gov/nist/javax/sip/header/ims/PUserDatabase.java0100644 0000000 0000000 00000005624 13513104763 021562 0ustar000000000 0000000 package gov.nist.javax.sip.header.ims; /* * 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 * * . * */ import java.text.ParseException; import javax.sip.header.ExtensionHeader; /** * * @author aayush.bhatnagar * Rancore Technologies Pvt Ltd, Mumbai India. * */ public class PUserDatabase extends gov.nist.javax.sip.header.ParametersHeader implements PUserDatabaseHeader,SIPHeaderNamesIms, ExtensionHeader{ private String databaseName; /** * * @param databaseName */ public PUserDatabase(String databaseName) { super(NAME); this.databaseName = databaseName; } /** * Default constructor. */ public PUserDatabase() { super(P_USER_DATABASE); } public String getDatabaseName() { return this.databaseName; } public void setDatabaseName(String databaseName) { if((databaseName==null)||(databaseName.equals(" "))) throw new NullPointerException("Database name is null"); else if(!databaseName.contains("aaa://")) this.databaseName = new StringBuffer().append("aaa://").append(databaseName).toString(); else this.databaseName = databaseName; } protected String encodeBody() { StringBuffer retval = new StringBuffer(); retval.append("<"); if(getDatabaseName()!=null) retval.append(getDatabaseName()); if (!parameters.isEmpty()) retval.append(SEMICOLON + this.parameters.encode()); retval.append(">"); return retval.toString(); } public boolean equals(Object other) { return (other instanceof PUserDatabaseHeader) && super.equals(other); } public Object clone() { PUserDatabase retval = (PUserDatabase) super.clone(); return retval; } public void setValue(String value) throws ParseException { throw new ParseException(value,0); } } java/gov/nist/javax/sip/header/ims/PUserDatabaseHeader.java0100644 0000000 0000000 00000004144 13513104763 022667 0ustar000000000 0000000 package gov.nist.javax.sip.header.ims; /* * 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 * * . * */ import javax.sip.header.Header; import javax.sip.header.Parameters; /** * * @author aayush.bhatnagar * Rancore Technologies Pvt Ltd, Mumbai India. * * This is the interface that exposes the behavior * of the P-User-Database header. We only have one * major value for this header, as per RFC 4457. * This value is the Database name. The DB here refers * to the IMS HSS. The DB name is encoded as a URI, delimited * by the < and > signs. There may be generic parameters for * this header encoded as URI parameters. They also lie between * the < and > delimiters. However, this URI is neither a SIP URI * nor a TEL URI. It is a DIAMETER AAA URI.The value of this AAA URI * is consumed by the S-CSCF. The S-CSCF can cache the value of the * HSS received in this header,thus optimizing the IMS registration * process. * */ public interface PUserDatabaseHeader extends Parameters,Header { public final static String NAME = "P-User-Database"; public String getDatabaseName(); public void setDatabaseName(String name); } java/gov/nist/javax/sip/header/ims/PVisitedNetworkID.java0100644 0000000 0000000 00000010422 13513104763 022405 0ustar000000000 0000000 /* * 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 PT INOVACAO - EST DEPARTMENT * *******************************************/ package gov.nist.javax.sip.header.ims; import java.text.ParseException; import javax.sip.header.ExtensionHeader; import javax.sip.header.Parameters; import gov.nist.core.Token; /** * P-Visited-Network-ID SIP Private Header: RFC 3455. * * * @author ALEXANDRE MIGUEL SILVA SANTOS - Nú 10045401 */ public class PVisitedNetworkID extends gov.nist.javax.sip.header.ParametersHeader implements PVisitedNetworkIDHeader, SIPHeaderNamesIms, ExtensionHeader { /** * visited Network ID */ private String networkID; // issued by Miguel Freitas private boolean isQuoted; public PVisitedNetworkID() { super(P_VISITED_NETWORK_ID); } public PVisitedNetworkID(String networkID) { super(P_VISITED_NETWORK_ID); setVisitedNetworkID(networkID); } public PVisitedNetworkID(Token tok) { super(P_VISITED_NETWORK_ID); setVisitedNetworkID(tok.getTokenValue()); } protected String encodeBody() { StringBuffer retval = new StringBuffer(); if (getVisitedNetworkID() != null) { // issued by Miguel Freitas if (isQuoted) retval.append(DOUBLE_QUOTE + getVisitedNetworkID() + DOUBLE_QUOTE); else retval.append(getVisitedNetworkID()); } if (!parameters.isEmpty()) retval.append(SEMICOLON + this.parameters.encode()); return retval.toString(); } /** * Set the visited network ID as a string. The value will be quoted in the header. * @param networkID - string value */ public void setVisitedNetworkID(String networkID) { if (networkID == null) throw new NullPointerException(" the networkID parameter is null"); this.networkID = networkID; // issued by Miguel Freitas this.isQuoted = true; } /** * Set the visited network ID as a token * @param networkID - token value */ public void setVisitedNetworkID(Token networkID) { if (networkID == null) throw new NullPointerException(" the networkID parameter is null"); this.networkID = networkID.getTokenValue(); // issued by Miguel Freitas this.isQuoted = false; } /** * Get the visited network ID value of this header */ public String getVisitedNetworkID() { return networkID; } public void setValue(String value) throws ParseException { throw new ParseException (value,0); } public boolean equals(Object other) { if (other instanceof PVisitedNetworkIDHeader) { PVisitedNetworkIDHeader o = (PVisitedNetworkIDHeader) other; return (this.getVisitedNetworkID().equals( o.getVisitedNetworkID() ) && this.equalParameters( (Parameters) o )); } return false; } public Object clone() { PVisitedNetworkID retval = (PVisitedNetworkID) super.clone(); if (this.networkID != null) retval.networkID = this.networkID; retval.isQuoted = this.isQuoted; return retval; } } java/gov/nist/javax/sip/header/ims/PVisitedNetworkIDHeader.java0100644 0000000 0000000 00000007016 13513104763 023523 0ustar000000000 0000000 /* * 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 PT INOVACAO - EST DEPARTMENT * *******************************************/ package gov.nist.javax.sip.header.ims; import gov.nist.core.Token; import javax.sip.header.Header; import javax.sip.header.Parameters; /** * P-Visited-Network-ID SIP Private Header: RFC 3455. * *
      *
    • * . One of the conditions for a home network to accept the registration of a UA roaming to a * particular visited network, is the existence of a roaming agreement between the home and * the visited network. There is a need to indicate to the home network which one is the visited * network that is providing services to the roaming UA. *
    • * . user agents always register to the home network. The REGISTER request is proxied by * one or more proxies located in the visited network towards the home network *
    • * . the visited network includes an identification that is known at the home network *
    • * . This identification should be globally unique, and takes the form of a quoted text string or a token *
    • * . In case a REGISTER or other request is traversing different administrative domains * (e.g., different visited networks), a SIP proxy MAY insert a NEW P-Visited-Network-ID header * if the request does not contain a P-Visited-Network-ID header with the same network * identifier as its own network identifier *
    * *

    Sintax:

    * *
     * P-Visited-Network-ID = "P-Visited-Network-ID" HCOLON
     *                         vnetwork-spec
     *                         *(COMMA vnetwork-spec)
     * vnetwork-spec        = (token / quoted-string)
     *                         *(SEMI vnetwork-param)
     * vnetwork-param       = generic-param
     *
     *
     * eg: P-Visited-Network-ID: other.net, "Visited network number 1"
     * 
    * * @author ALEXANDRE MIGUEL SILVA SANTOS - Nú 10045401 */ public interface PVisitedNetworkIDHeader extends Parameters, Header { /** * Name of VisitedNetworkIDHeader */ public final static String NAME = "P-Visited-Network-ID"; /** * Set the visited network ID as a string. The value will be quoted in the header. * @param networkID - string value */ public void setVisitedNetworkID(String networkID); /** * Set the visited network ID as a token * @param networkID - token value */ public void setVisitedNetworkID(Token networkID); /** * Get the visited network ID value of this header */ public String getVisitedNetworkID(); } java/gov/nist/javax/sip/header/ims/PVisitedNetworkIDList.java0100644 0000000 0000000 00000003567 13513104763 023255 0ustar000000000 0000000 /* * 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 PT INOVACAO - EST DEPARTMENT * *******************************************/ package gov.nist.javax.sip.header.ims; import gov.nist.javax.sip.header.SIPHeaderList; import gov.nist.javax.sip.header.ims.PVisitedNetworkIDHeader; /** * List of P-Visited-Network-ID headers. * * @author ALEXANDRE MIGUEL SILVA SANTOS - Nú 10045401 */ public class PVisitedNetworkIDList extends SIPHeaderList { private static final long serialVersionUID = -4346667490341752478L; /** Default constructor */ public PVisitedNetworkIDList() { super(PVisitedNetworkID.class, PVisitedNetworkIDHeader.NAME); } public Object clone() { PVisitedNetworkIDList retval = new PVisitedNetworkIDList(); return retval.clonehlist(this.hlist); } } java/gov/nist/javax/sip/header/ims/ParameterNamesIms.java0100644 0000000 0000000 00000007501 13513104763 022450 0ustar000000000 0000000 /* * 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 PT INOVAO - EST DEPARTMENT * *******************************************/ package gov.nist.javax.sip.header.ims; import gov.nist.javax.sip.address.ParameterNames; /** * @author ALEXANDRE MIGUEL SILVA SANTOS - Nú 10045401 */ public interface ParameterNamesIms extends ParameterNames { public static final String IK = "ik"; public static final String CK = "ck"; public static final String INTEGRITY_PROTECTED = "integrity-protected"; public static final String CCF = "ccf"; public static final String ECF = "ecf"; public static final String ICID_VALUE = "icid-value"; public static final String ICID_GENERATED_AT = "icid-generated-at"; public static final String ORIG_IOI = "orig-ioi"; public static final String TERM_IOI = "term-ioi"; // issued by Miguel Freitas // // P-Access-Network-ID public static final String CGI_3GPP = "cgi-3gpp"; public static final String UTRAN_CELL_ID_3GPP = "utran-cell-id-3gpp"; public static final String DSL_LOCATION = "dsl-location"; public static final String CI_3GPP2 = "ci-3gpp2"; // P-Charging-Vector public static final String GGSN = "ggsn"; public static final String PDP_INFO = "pdp-info"; public static final String PDP_ITEM = "pdp-item"; public static final String PDP_SIG = "pdp-sig"; public static final String GCID = "gcid"; public static final String AUTH_TOKEN = "auth-token"; public static final String FLOW_ID = "flow-id"; public static final String PDG = "pdg"; public static final String BRAS = "bras"; public static final String DSL_BEARER_INFO = "dsl-bearer-info"; public static final String DSL_BEARER_ITEM = "dsl-bearer-item"; public static final String DSL_BEARER_SIG = "dsl-bearer-sig"; // sec-agree (Security-Server, Security-Client, Security-Verify) public static final String ALG = "alg"; public static final String EALG = "ealg"; public static final String Q = "q"; public static final String PROT = "prot"; public static final String MOD = "mod"; public static final String SPI_C = "spi-c"; public static final String SPI_S = "spi-s"; public static final String PORT_C = "port-c"; public static final String PORT_S = "port-s"; public static final String D_VER = "d-ver"; // end // //added by aayush.bhatnagar(Ref: RFC 5502) public static final String SESSION_CASE = "sescase"; public static final String REGISTRATION_STATE = "regstate"; //added by aayush.bhatnagar(Ref: draft-drage-sipping-service-identification-03) public static final String SERVICE_ID = "urn:urn-7:"; public static final String SERVICE_ID_LABEL = "3gpp-service"; public static final String APPLICATION_ID_LABEL = "3gpp-application"; } java/gov/nist/javax/sip/header/ims/Path.java0100644 0000000 0000000 00000005130 13513104763 017763 0ustar000000000 0000000 /* * 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 PT INOVACAO - EST DEPARTMENT * *******************************************/ package gov.nist.javax.sip.header.ims; import java.text.ParseException; import javax.sip.header.ExtensionHeader; import gov.nist.javax.sip.address.AddressImpl; import gov.nist.javax.sip.header.ims.PathHeader; /** * @author ALEXANDRE MIGUEL SILVA SANTOS - Nú 10045401 */ public class Path extends gov.nist.javax.sip.header.AddressParametersHeader implements PathHeader, SIPHeaderNamesIms , ExtensionHeader{ /** * constructor * @param address address to set */ public Path(AddressImpl address) { super(NAME); this.address = address; } /** * default constructor */ public Path() { // issued by Miguel Freitas super(NAME); } /** Encode into canonical form. *@return String containing the canonicaly encoded header. */ 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); } } java/gov/nist/javax/sip/header/ims/PathHeader.java0100644 0000000 0000000 00000003224 13513104763 021076 0ustar000000000 0000000 /* * 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 PT INOVACAO - EST DEPARTMENT * *******************************************/ package gov.nist.javax.sip.header.ims; import javax.sip.header.Header; import javax.sip.header.HeaderAddress; import javax.sip.header.Parameters; /* * @author ALEXANDRE MIGUEL SILVA SANTOS - Nú 10045401 */ /** * PATH header SIP param: RFC 3327. * * @author ALEXANDRE MIGUEL SILVA SANTOS - Nú 10045401 * */ public interface PathHeader extends HeaderAddress, Parameters, Header { /** * Name of PathHeader */ public final static String NAME = "Path"; } java/gov/nist/javax/sip/header/ims/PathList.java0100644 0000000 0000000 00000003147 13513104763 020625 0ustar000000000 0000000 /* * 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 PT INOVAO - EST DEPARTMENT * *******************************************/ package gov.nist.javax.sip.header.ims; import gov.nist.javax.sip.header.SIPHeaderList; /** * @author ALEXANDRE MIGUEL SILVA SANTOS - Nú 10045401 */ public class PathList extends SIPHeaderList { /** Default constructor */ public PathList() { super(Path.class, PathHeader.NAME); } public Object clone() { PathList retval = new PathList(); return retval.clonehlist(this.hlist); } } java/gov/nist/javax/sip/header/ims/Privacy.java0100644 0000000 0000000 00000006524 13513104763 020514 0ustar000000000 0000000 /* * 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 PT INOVACAO - EST DEPARTMENT and Aveiro University - Portugal) * *****************************************************************************/ package gov.nist.javax.sip.header.ims; import java.text.ParseException; import javax.sip.header.ExtensionHeader; import javax.sip.header.Parameters; import gov.nist.core.NameValueList; import gov.nist.javax.sip.header.SIPHeader; /** * Privacy SIP header - RFC 3323. * * @author Miguel Freitas (IT) PT-Inovacao */ public class Privacy extends SIPHeader implements PrivacyHeader, SIPHeaderNamesIms, ExtensionHeader { /** * Privacy type */ private String privacy; /** * Default constructor. */ public Privacy() { super(PRIVACY); } /** * Constructor given a privacy type *@param privacy */ public Privacy(String privacy) { this(); this.privacy = privacy; } /** * Encode into a canonical string. * @return String. */ public String encodeBody() { return this.privacy; } /** * Get privacy type * @return privacy type */ public String getPrivacy() { return privacy; } /** * set the privacy type. * @param privacy -- privacy type to set. */ public void setPrivacy(String privacy) throws ParseException { if (privacy == null || privacy == "") throw new NullPointerException( "JAIN-SIP Exception, " + " Privacy, setPrivacy(), privacy value is null or empty"); this.privacy = privacy; } /** * Suppress direct setting of values. * */ public void setValue(String value) throws ParseException { throw new ParseException(value,0); } public boolean equals(Object other) { if (other instanceof PrivacyHeader) { PrivacyHeader o = (PrivacyHeader) other; return (this.getPrivacy().equals( o.getPrivacy() )); } return false; } public Object clone() { Privacy retval = (Privacy) super.clone(); if (this.privacy != null) retval.privacy = this.privacy; return retval; } } java/gov/nist/javax/sip/header/ims/PrivacyHeader.java0100644 0000000 0000000 00000004232 13513104763 021617 0ustar000000000 0000000 /* * 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 PT INOVACAO - EST DEPARTMENT and Aveiro University - Portugal) * *****************************************************************************/ package gov.nist.javax.sip.header.ims; import java.text.ParseException; import javax.sip.header.Header; import javax.sip.header.Parameters; /** * Privacy Header RFC 3323. * *

    Sintax:

    *
     * Privacy-hdr  = "Privacy" HCOLON priv-value *(";" priv-value)
     * priv-value   = "header" / "session" / "user" /
     *                "id" / "none" / "critical" / token
     * example:
     *           Privacy: id
     * 
    * * @author Miguel Freitas (IT) PT-Inovacao */ public interface PrivacyHeader extends Header { /** * Name of PrivacyHeader */ public final static String NAME = "Privacy"; /** * Set Privacy header value * @param privacy -- privacy type to set. */ public void setPrivacy(String privacy) throws ParseException; /** * Get Privacy header value * @return privacy token name */ public String getPrivacy(); } java/gov/nist/javax/sip/header/ims/PrivacyList.java0100644 0000000 0000000 00000003517 13513104763 021347 0ustar000000000 0000000 /* * 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 PT INOVACAO - EST DEPARTMENT and Aveiro University - Portugal) * *****************************************************************************/ package gov.nist.javax.sip.header.ims; import gov.nist.javax.sip.header.SIPHeaderList; /** * List of Privacy headers. * * @author Miguel Freitas (IT) PT-Inovacao */ public class PrivacyList extends SIPHeaderList { private static final long serialVersionUID = 1798720509806307461L; /** * Default constructor */ public PrivacyList() { super(Privacy.class, PrivacyHeader.NAME); } public Object clone() { PrivacyList retval = new PrivacyList(); return retval.clonehlist(this.hlist); } } java/gov/nist/javax/sip/header/ims/SIPHeaderNamesIms.java0100644 0000000 0000000 00000006035 13513104763 022275 0ustar000000000 0000000 /* * 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 PT INOVACAO - EST DEPARTMENT * *******************************************/ package gov.nist.javax.sip.header.ims; /** * @author ALEXANDRE MIGUEL SILVA SANTOS - Nú 10045401 */ public interface SIPHeaderNamesIms extends gov.nist.javax.sip.header.SIPHeaderNames { public static final String PATH = PathHeader.NAME; public static final String SERVICE_ROUTE = ServiceRouteHeader.NAME; public static final String P_ASSERTED_IDENTITY = PAssertedIdentityHeader.NAME; public static final String P_PREFERRED_IDENTITY = PPreferredIdentityHeader.NAME; public static final String CALLED_PARTY_ID = PCalledPartyIDHeader.NAME; public static final String P_VISITED_NETWORK_ID = PVisitedNetworkIDHeader.NAME; public static final String P_CHARGING_FUNCTION_ADDRESSES = PChargingFunctionAddressesHeader.NAME; public static final String P_CHARGING_VECTOR = PChargingVectorHeader.NAME; // issued by Miguel Freitas public static final String PRIVACY = PrivacyHeader.NAME; public static final String P_ASSOCIATED_URI = PAssociatedURIHeader.NAME; public static final String P_MEDIA_AUTHORIZATION = PMediaAuthorizationHeader.NAME; public static final String P_ACCESS_NETWORK_INFO = PAccessNetworkInfoHeader.NAME; public static final String SECURITY_SERVER = SecurityServerHeader.NAME; public static final String SECURITY_CLIENT = SecurityClientHeader.NAME; public static final String SECURITY_VERIFY = SecurityVerifyHeader.NAME; //added by aayush public static final String P_USER_DATABASE = PUserDatabaseHeader.NAME; //added by aayush public static final String P_PROFILE_KEY = PProfileKeyHeader.NAME; //added by aayush public static final String P_SERVED_USER = PServedUserHeader.NAME; //added by aayush public static final String P_PREFERRED_SERVICE = PPreferredServiceHeader.NAME; //added by aayush public static final String P_ASSERTED_SERVICE = PAssertedServiceHeader.NAME; } java/gov/nist/javax/sip/header/ims/SecurityAgree.java0100644 0000000 0000000 00000025042 13513104763 021646 0ustar000000000 0000000 /* * Conditions Of Use * * This software was developed by employees of the National Institute of * Standards and Technology (NIST), an agency of the Federal Government, * and others. * 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 PT INOVACAO - EST DEPARTMENT and Telecommunications Institute (Aveiro, Portugal) * ************************************************************************************************/ package gov.nist.javax.sip.header.ims; import java.text.ParseException; import javax.sip.InvalidArgumentException; import javax.sip.header.Parameters; import gov.nist.core.NameValue; import gov.nist.core.Separators; import gov.nist.javax.sip.header.ims.ParameterNamesIms; import gov.nist.javax.sip.header.ParametersHeader; /** * "Security Mechanism Agreemet for SIP Sessions" * - sec-agree: RFC 3329 + 3GPP TS33.203 (Annex H). * *

    Headers: Security-Server + Security-Client + Security-Verify

    * * @author Miguel Freitas (IT) PT-Inovacao */ public abstract class SecurityAgree extends ParametersHeader { //TODO serialVersionUID //private static final long serialVersionUID = -6671234553927258745L; //public static final String EALG = ParameterNamesIms.EALG; // ... /** * Security Mechanism value */ private String secMechanism; /** * Constructor * @param name - name of the Security Agree header to create */ public SecurityAgree(String name) { super(name); parameters.setSeparator(Separators.SEMICOLON); } /** * Default constructor */ public SecurityAgree() { super(); parameters.setSeparator(Separators.SEMICOLON); } public void setParameter(String name, String value) throws ParseException { if (value == null) throw new NullPointerException("null value"); NameValue nv = super.parameters.getNameValue(name.toLowerCase()); if (nv == null) { nv = new NameValue(name, value); // quoted values if (name.equalsIgnoreCase(ParameterNamesIms.D_VER)) { nv.setQuotedValue(); if (value.startsWith(Separators.DOUBLE_QUOTE)) throw new ParseException(value + " : Unexpected DOUBLE_QUOTE", 0); } super.setParameter(nv); } else { nv.setValueAsObject(value); } } public String encodeBody() { return this.secMechanism + SEMICOLON + SP + parameters.encode(); } /** * Set security mechanism. *

    eg: Security-Client: ipsec-3gpp

    * @param secMech - security mechanism name */ public void setSecurityMechanism(String secMech) throws ParseException { if (secMech == null) throw new NullPointerException( "JAIN-SIP " + "Exception, SecurityAgree, setSecurityMechanism(), the sec-mechanism parameter is null"); this.secMechanism = secMech; } /** * Set Encryption Algorithm (ealg parameter) * @param ealg - encryption algorithm value * @throws ParseException */ public void setEncryptionAlgorithm(String ealg) throws ParseException { if (ealg == null) throw new NullPointerException( "JAIN-SIP " + "Exception, SecurityClient, setEncryptionAlgorithm(), the encryption-algorithm parameter is null"); setParameter(ParameterNamesIms.EALG, ealg); } /** * Set Algorithm (alg parameter) * @param alg - algorithm value * @throws ParseException */ public void setAlgorithm(String alg) throws ParseException { if (alg == null) throw new NullPointerException( "JAIN-SIP " + "Exception, SecurityClient, setAlgorithm(), the algorithm parameter is null"); setParameter(ParameterNamesIms.ALG, alg); } /** * Set Protocol (prot paramater) * @param prot - protocol value * @throws ParseException */ public void setProtocol(String prot) throws ParseException { if (prot == null) throw new NullPointerException( "JAIN-SIP " + "Exception, SecurityClient, setProtocol(), the protocol parameter is null"); setParameter(ParameterNamesIms.PROT, prot); } /** * Set Mode (mod parameter) * @param mod - mode value * @throws ParseException */ public void setMode(String mod) throws ParseException { if (mod == null) throw new NullPointerException( "JAIN-SIP " + "Exception, SecurityClient, setMode(), the mode parameter is null"); setParameter(ParameterNamesIms.MOD, mod); } /** * Set Client SPI (spi-c parameter) * @param spic - spi-c value * @throws InvalidArgumentException */ public void setSPIClient(int spic) throws InvalidArgumentException { if (spic < 0) throw new InvalidArgumentException( "JAIN-SIP " + "Exception, SecurityClient, setSPIClient(), the spi-c parameter is <0"); setParameter(ParameterNamesIms.SPI_C, spic); } /** * Set Server SPI (spi-s parameter) * @param spis - spi-s value * @throws InvalidArgumentException - when value is not valid */ public void setSPIServer(int spis) throws InvalidArgumentException { if (spis < 0) throw new InvalidArgumentException( "JAIN-SIP " + "Exception, SecurityClient, setSPIServer(), the spi-s parameter is <0"); setParameter(ParameterNamesIms.SPI_S, spis); } /** * Set Client Port (port-c parameter) * @param portC - port-c value * @throws InvalidArgumentException - when value is not valid */ public void setPortClient(int portC) throws InvalidArgumentException { if (portC < 0) throw new InvalidArgumentException( "JAIN-SIP " + "Exception, SecurityClient, setPortClient(), the port-c parameter is <0"); setParameter(ParameterNamesIms.PORT_C, portC); } /** * Set Server Port (port-s parameter) * @param portS - port-s value * @throws InvalidArgumentException - when value is not valid */ public void setPortServer(int portS) throws InvalidArgumentException { if (portS < 0) throw new InvalidArgumentException( "JAIN-SIP " + "Exception, SecurityClient, setPortServer(), the port-s parameter is <0"); setParameter(ParameterNamesIms.PORT_S, portS); } /** *

    Set Preference. * The "q" parameter indicates a relative preference for the particular mechanism. * The higher the value the more preferred the mechanism is. * Range from 0.001 to 0.999.

    * @param q - q parameter value * @throws InvalidArgumentException - when value is not valid */ public void setPreference(float q) throws InvalidArgumentException { if (q < 0.0f) throw new InvalidArgumentException( "JAIN-SIP " + "Exception, SecurityClient, setPreference(), the preference (q) parameter is <0"); setParameter(ParameterNamesIms.Q, q); } // get param /** * Get Security Mechanism * @return security mechanims value */ public String getSecurityMechanism() { return this.secMechanism; } /** * Get Encryption Algorithm * @return ealg parameter value */ public String getEncryptionAlgorithm() { return getParameter(ParameterNamesIms.EALG); } /** * Get Algorithm * @return alg parameter value */ public String getAlgorithm() { return getParameter(ParameterNamesIms.ALG); } /** * Get Protocol * @return prot parameter value */ public String getProtocol() { return getParameter(ParameterNamesIms.PROT); } /** * Get Mode * @return mod parameter value */ public String getMode() { return getParameter(ParameterNamesIms.MOD); } /** * Get Client SPI * @return spi-c parameter value */ public int getSPIClient() { return (Integer.parseInt(getParameter(ParameterNamesIms.SPI_C))); } /** * Get Server SPI * @return spi-s parameter value */ public int getSPIServer() { return (Integer.parseInt(getParameter(ParameterNamesIms.SPI_S))); } /** * Get Client Port * @return port-c parameter value */ public int getPortClient() { return (Integer.parseInt(getParameter(ParameterNamesIms.PORT_C))); } /** * Get Server Port * @return port-s parameter value */ public int getPortServer() { return (Integer.parseInt(getParameter(ParameterNamesIms.PORT_S))); } /** * Get Preference * @return q parameter value */ public float getPreference() { return (Float.parseFloat(getParameter(ParameterNamesIms.Q))); } public boolean equals(Object other) { if(other instanceof SecurityAgreeHeader) { SecurityAgreeHeader o = (SecurityAgreeHeader) other; return (this.getSecurityMechanism().equals( o.getSecurityMechanism() ) && this.equalParameters( (Parameters) o )); } return false; } public Object clone() { SecurityAgree retval = (SecurityAgree) super.clone(); if (this.secMechanism != null) retval.secMechanism = this.secMechanism; return retval; } } java/gov/nist/javax/sip/header/ims/SecurityAgreeHeader.java0100644 0000000 0000000 00000011673 13513104763 022764 0ustar000000000 0000000 /* * Conditions Of Use * * This software was developed by employees of the National Institute of * Standards and Technology (NIST), an agency of the Federal Government * and others. * 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 PT INOVACAO - EST DEPARTMENT and Telecommunications Institute (Aveiro, Portugal) * ************************************************************************************************/ package gov.nist.javax.sip.header.ims; import java.text.ParseException; import javax.sip.InvalidArgumentException; import javax.sip.header.Header; import javax.sip.header.Parameters; /** * "Security Mechanism Agreemet for SIP Sessions" * - sec-agree: RFC 3329 + 3GPP TS33.203 (Annex H). * *

    Headers: Security-Server + Security-Client + Security-Verify

    * * @author Miguel Freitas (IT) PT-Inovacao */ public interface SecurityAgreeHeader extends Parameters, Header { /** * Set security mechanism. *

    eg: Security-Client: ipsec-3gpp

    * @param secMech - security mechanism name */ public void setSecurityMechanism(String secMech) throws ParseException; /** * Set Encryption Algorithm (ealg parameter) * @param ealg - encryption algorithm value * @throws ParseException */ public void setEncryptionAlgorithm(String ealg) throws ParseException; /** * Set Algorithm (alg parameter) * @param alg - algorithm value * @throws ParseException */ public void setAlgorithm(String alg) throws ParseException; /** * Set Protocol (prot paramater) * @param prot - protocol value * @throws ParseException */ public void setProtocol(String prot) throws ParseException; /** * Set Mode (mod parameter) * @param mod - mode value * @throws ParseException */ public void setMode(String mod) throws ParseException; /** * Set Client SPI (spi-c parameter) * @param spic - spi-c value * @throws InvalidArgumentException */ public void setSPIClient(int spic) throws InvalidArgumentException; /** * Set Server SPI (spi-s parameter) * @param spis - spi-s value * @throws InvalidArgumentException - when value is not valid */ public void setSPIServer(int spis) throws InvalidArgumentException; /** * Set Client Port (port-c parameter) * @param portC - port-c value * @throws InvalidArgumentException - when value is not valid */ public void setPortClient(int portC) throws InvalidArgumentException; /** * Set Server Port (port-s parameter) * @param portS - port-s value * @throws InvalidArgumentException - when value is not valid */ public void setPortServer(int portS) throws InvalidArgumentException; /** * Set Preference * @param q - q parameter value * @throws InvalidArgumentException - when value is not valid */ public void setPreference(float q) throws InvalidArgumentException; /** * Get Security Mechanism * @return security mechanims value */ public String getSecurityMechanism(); /** * Get Encryption Algorithm * @return ealg parameter value */ public String getEncryptionAlgorithm(); /** * Get Algorithm * @return alg parameter value */ public String getAlgorithm(); /** * Get Protocol * @return prot parameter value */ public String getProtocol(); /** * Get Mode * @return mod parameter value */ public String getMode(); /** * Get Client SPI * @return spi-c parameter value */ public int getSPIClient(); /** * Get Server SPI * @return spi-s parameter value */ public int getSPIServer(); /** * Get Client Port * @return port-c parameter value */ public int getPortClient(); /** * Get Server Port * @return port-s parameter value */ public int getPortServer(); /** * Get Preference * @return q parameter value */ public float getPreference(); } java/gov/nist/javax/sip/header/ims/SecurityClient.java0100644 0000000 0000000 00000003756 13513104763 022051 0ustar000000000 0000000 /* * Conditions Of Use * * This software was developed by employees of the National Institute of * Standards and Technology (NIST), an agency of the Federal Government, * and others. * 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 PT INOVACAO - EST DEPARTMENT and Telecommunications Institute (Aveiro, Portugal) * ************************************************************************************************/ package gov.nist.javax.sip.header.ims; import java.text.ParseException; import javax.sip.InvalidArgumentException; import javax.sip.header.ExtensionHeader; /** * Security-Client header * - sec-agree: RFC 3329 + 3GPP TS33.203 (Annex H). * *

    * * @author Miguel Freitas (IT) PT-Inovacao */ public class SecurityClient extends SecurityAgree implements SecurityClientHeader, ExtensionHeader { // TODO serialVersionUID public SecurityClient() { super(SecurityClientHeader.NAME); } public void setValue(String value) throws ParseException { throw new ParseException(value,0); } } java/gov/nist/javax/sip/header/ims/SecurityClientHeader.java0100644 0000000 0000000 00000003311 13513104763 023145 0ustar000000000 0000000 /* * Conditions Of Use * * This software was developed by employees of the National Institute of * Standards and Technology (NIST), an agency of the Federal Government * and others. * 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 PT INOVACAO - EST DEPARTMENT and Telecommunications Institute (Aveiro, Portugal) * ************************************************************************************************/ package gov.nist.javax.sip.header.ims; /** * Security-Client header * - sec-agree: RFC 3329 + 3GPP TS33.203 (Annex H). * *

    * * @author Miguel Freitas (IT) PT-Inovacao */ public interface SecurityClientHeader extends SecurityServerHeader { /** * Name of SecurityClientHeader */ public final static String NAME = "Security-Client"; } java/gov/nist/javax/sip/header/ims/SecurityClientList.java0100644 0000000 0000000 00000003736 13513104763 022703 0ustar000000000 0000000 /* * Conditions Of Use * * This software was developed by employees of the National Institute of * Standards and Technology (NIST), an agency of the Federal Government, * and others. * 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 PT INOVACAO - EST DEPARTMENT and Telecommunications Institute (Aveiro, Portugal) * ************************************************************************************************/ package gov.nist.javax.sip.header.ims; import gov.nist.javax.sip.header.SIPHeaderList; import gov.nist.javax.sip.header.ims.SecurityClient; /** * List of Security-Client headers. * * @author Miguel Freitas (IT) PT-Inovacao */ public class SecurityClientList extends SIPHeaderList { private static final long serialVersionUID = 3094231003329176217L; public SecurityClientList() { super(SecurityClient.class, SecurityClientHeader.NAME); } public Object clone() { SecurityClientList retval = new SecurityClientList(); return retval.clonehlist(this.hlist); } } java/gov/nist/javax/sip/header/ims/SecurityServer.java0100644 0000000 0000000 00000003702 13513104763 022070 0ustar000000000 0000000 /* * Conditions Of Use * * This software was developed by employees of the National Institute of * Standards and Technology (NIST), an agency of the Federal Government, * and others. * 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 PT INOVACAO - EST DEPARTMENT and Telecommunications Institute (Aveiro, Portugal) * ************************************************************************************************/ package gov.nist.javax.sip.header.ims; import java.text.ParseException; import javax.sip.header.ExtensionHeader; /** * Security-Server header * - sec-agree: RFC 3329 + 3GPP TS33.203 (Annex H). * *

    * * @author Miguel Freitas (IT) PT-Inovacao */ public class SecurityServer extends SecurityAgree implements SecurityServerHeader, ExtensionHeader { // TODO serialVersionUID public SecurityServer() { super(SecurityServerHeader.NAME); } public void setValue(String value) throws ParseException { throw new ParseException(value,0); } } java/gov/nist/javax/sip/header/ims/SecurityServerHeader.java0100644 0000000 0000000 00000003534 13513104763 023204 0ustar000000000 0000000 /* * Conditions Of Use * * This software was developed by employees of the National Institute of * Standards and Technology (NIST), an agency of the Federal Government * and others. * 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 PT INOVACAO - EST DEPARTMENT and Telecommunications Institute (Aveiro, Portugal) * ************************************************************************************************/ package gov.nist.javax.sip.header.ims; import java.text.ParseException; import javax.sip.InvalidArgumentException; import javax.sip.header.Header; import javax.sip.header.Parameters; /** * Security-Server header * - sec-agree: RFC 3329 + 3GPP TS33.203 (Annex H). * *

    * * @author Miguel Freitas (IT) PT-Inovacao */ public interface SecurityServerHeader extends SecurityAgreeHeader { /** * Name of SecurityServerHeader */ public final static String NAME = "Security-Server"; } java/gov/nist/javax/sip/header/ims/SecurityServerList.java0100644 0000000 0000000 00000003752 13513104763 022731 0ustar000000000 0000000 /* * Conditions Of Use * * This software was developed by employees of the National Institute of * Standards and Technology (NIST), an agency of the Federal Government, * and others. * 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 PT INOVACAO - EST DEPARTMENT and Telecommunications Institute (Aveiro, Portugal) * ************************************************************************************************/ package gov.nist.javax.sip.header.ims; import gov.nist.javax.sip.header.SIPHeaderList; import gov.nist.javax.sip.header.ims.SecurityServer; /** * List of Security-Server headers. * *

    * * @author Miguel Freitas (IT) PT-Inovacao */ public class SecurityServerList extends SIPHeaderList { private static final long serialVersionUID = -1392066520803180238L; public SecurityServerList() { super(SecurityServer.class, SecurityServerHeader.NAME); } public Object clone() { SecurityServerList retval = new SecurityServerList(); return retval.clonehlist(this.hlist); } } java/gov/nist/javax/sip/header/ims/SecurityVerify.java0100644 0000000 0000000 00000003702 13513104763 022066 0ustar000000000 0000000 /* * Conditions Of Use * * This software was developed by employees of the National Institute of * Standards and Technology (NIST), an agency of the Federal Government, * and others. * 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 PT INOVACAO - EST DEPARTMENT and Telecommunications Institute (Aveiro, Portugal) * ************************************************************************************************/ package gov.nist.javax.sip.header.ims; import java.text.ParseException; import javax.sip.header.ExtensionHeader; /** * Security-Verify header * - sec-agree: RFC 3329 + 3GPP TS33.203 (Annex H). * *

    * * @author Miguel Freitas (IT) PT-Inovacao */ public class SecurityVerify extends SecurityAgree implements SecurityVerifyHeader, ExtensionHeader { // TODO serialVersionUID public SecurityVerify() { super(SecurityVerifyHeader.NAME); } public void setValue(String value) throws ParseException { throw new ParseException(value,0); } } java/gov/nist/javax/sip/header/ims/SecurityVerifyHeader.java0100644 0000000 0000000 00000003311 13513104763 023173 0ustar000000000 0000000 /* * Conditions Of Use * * This software was developed by employees of the National Institute of * Standards and Technology (NIST), an agency of the Federal Government * and others. * 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 PT INOVACAO - EST DEPARTMENT and Telecommunications Institute (Aveiro, Portugal) * ************************************************************************************************/ package gov.nist.javax.sip.header.ims; /** * Security-Verify header * - sec-agree: RFC 3329 + 3GPP TS33.203 (Annex H). * *

    * * @author Miguel Freitas (IT) PT-Inovacao */ public interface SecurityVerifyHeader extends SecurityAgreeHeader { /** * Name of SecurityVerifyHeader */ public final static String NAME = "Security-Verify"; } java/gov/nist/javax/sip/header/ims/SecurityVerifyList.java0100644 0000000 0000000 00000003753 13513104763 022730 0ustar000000000 0000000 /* * Conditions Of Use * * This software was developed by employees of the National Institute of * Standards and Technology (NIST), an agency of the Federal Government, * and others. * 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 PT INOVACAO - EST DEPARTMENT and Telecommunications Institute (Aveiro, Portugal) * ************************************************************************************************/ package gov.nist.javax.sip.header.ims; import gov.nist.javax.sip.header.SIPHeaderList; import gov.nist.javax.sip.header.ims.SecurityVerify; /** * List of Security-Verify headers. * *

    * * @author Miguel Freitas (IT) PT-Inovacao */ public class SecurityVerifyList extends SIPHeaderList { private static final long serialVersionUID = 563201040577795125L; public SecurityVerifyList() { super(SecurityVerify.class, SecurityVerifyHeader.NAME); } public Object clone() { SecurityVerifyList retval = new SecurityVerifyList(); return retval.clonehlist(this.hlist); } } java/gov/nist/javax/sip/header/ims/ServiceRoute.java0100644 0000000 0000000 00000005134 13513104763 021512 0ustar000000000 0000000 /* * 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 PT INOVACAO - EST DEPARTMENT * *******************************************/ package gov.nist.javax.sip.header.ims; import java.text.ParseException; import javax.sip.header.ExtensionHeader; import gov.nist.javax.sip.address.AddressImpl; /** * SERVICE-ROUTE header SIP param: RFC 3608. * * @author ALEXANDRE MIGUEL SILVA SANTOS - Nú 10045401 */ public class ServiceRoute extends gov.nist.javax.sip.header.AddressParametersHeader implements ServiceRouteHeader, SIPHeaderNamesIms, ExtensionHeader { /** * constructor * @param address address to set */ public ServiceRoute(AddressImpl address) { super(NAME); this.address = address; } /** * default constructor */ public ServiceRoute() { super(SERVICE_ROUTE); } /** Encode into canonical form. *@return String containing the canonicaly encoded header. */ 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); } } java/gov/nist/javax/sip/header/ims/ServiceRouteHeader.java0100644 0000000 0000000 00000003161 13513104763 022621 0ustar000000000 0000000 /* * 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 PT INOVACAO - EST DEPARTMENT * *******************************************/ package gov.nist.javax.sip.header.ims; import javax.sip.header.Header; import javax.sip.header.HeaderAddress; import javax.sip.header.Parameters; /** * SERVICE-ROUTE header SIP param: RFC 3608. * * @author ALEXANDRE MIGUEL SILVA SANTOS - Nú 10045401 */ public interface ServiceRouteHeader extends HeaderAddress, Parameters, Header { /** * Name of ServiceRouteHeader */ public final static String NAME = "Service-Route"; } java/gov/nist/javax/sip/header/ims/ServiceRouteList.java0100644 0000000 0000000 00000003350 13513104763 022344 0ustar000000000 0000000 /* * 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 PT INOVAO - EST DEPARTMENT * *******************************************/ package gov.nist.javax.sip.header.ims; import gov.nist.javax.sip.header.SIPHeaderList; /** * @author ALEXANDRE MIGUEL SILVA SANTOS - Nú 10045401 */ public class ServiceRouteList extends SIPHeaderList { private static final long serialVersionUID = -4264811439080938519L; /** Default constructor */ public ServiceRouteList() { super(ServiceRoute.class, ServiceRouteHeader.NAME); } public Object clone() { ServiceRouteList retval = new ServiceRouteList(); return retval.clonehlist(this.hlist); } } java/gov/nist/javax/sip/header/ims/WWWAuthenticateHeaderIms.java0100644 0000000 0000000 00000004371 13513104763 023702 0ustar000000000 0000000 /* * 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 PT INOVACAO - EST DEPARTMENT * *******************************************/ package gov.nist.javax.sip.header.ims; import java.text.ParseException; import javax.sip.header.WWWAuthenticateHeader; /** * Extension to WWW-authenticate header (3GPP TS 24229-5d0). * *

    Defines a new authentication parameter (auth-param) for the WWW-Authenticate header * used in a 401 (Unauthorized) response to the REGISTER request. * For more information, see RFC 2617 [21] subclause 3.2.1.

    * *
     *  auth-param = 1#( integrity-key / cipher-key )
     *  integrity-key = "ik" EQUAL ik-value
     *  cipher-key = "ck" EQUAL ck-value
     *  ik-value = LDQUOT *(HEXDIG) RDQUOT
     *  ck-value = LDQUOT *(HEXDIG) RDQUOT
     * 
    * * @author ALEXANDRE MIGUEL SILVA SANTOS - Nú 10045401 */ public interface WWWAuthenticateHeaderIms extends WWWAuthenticateHeader { // issued by Miguel Freitas public static final String IK = ParameterNamesIms.IK; public static final String CK = ParameterNamesIms.CK; public void setIK(String ik) throws ParseException; public String getIK(); public void setCK(String ck) throws ParseException; public String getCK(); } java/gov/nist/javax/sip/header/ims/package.html0100644 0000000 0000000 00000000771 13513104763 020513 0ustar000000000 0000000 NIST-SIP Specific support for IMS headers contributed by Jose Miguel Freitas (Aveiro University, Portugal) and Alexandre Miguel Silva Santos (PT Inovacau, Portugal). It is not part of the JAIN-SIP 1.2 specification. Questions about the IMS Support in NIST-SIP 1.2 can be directed to Miguel Feitas or the NIST-SIP mailing list. To acccess these headers you have to cast the HeaderFactory to HeaderFactoryImpl. This package has been contributed to the public domain. java/gov/nist/javax/sip/header/package.html0100644 0000000 0000000 00000000217 13513104763 017716 0ustar000000000 0000000 Contains implementations of the SIP headers as defined in JAIN-SIP 1.2 and an implementation of the JAIN-SIP header factory. java/gov/nist/javax/sip/message/0040755 0000000 0000000 00000000000 13513104763 015634 5ustar000000000 0000000 java/gov/nist/javax/sip/message/Content.java0100644 0000000 0000000 00000001074 13513104763 020110 0ustar000000000 0000000 package gov.nist.javax.sip.message; import javax.sip.header.ContentDispositionHeader; import javax.sip.header.ContentTypeHeader; public interface Content { public abstract void setContent(Object content); public abstract Object getContent(); public abstract ContentTypeHeader getContentTypeHeader(); public abstract ContentDispositionHeader getContentDispositionHeader(); /** * The default packing method. This packs the content to be appended to the * sip message. * */ public abstract String toString(); } java/gov/nist/javax/sip/message/ContentImpl.java0100644 0000000 0000000 00000004712 13513104763 020734 0ustar000000000 0000000 package gov.nist.javax.sip.message; import java.text.ParseException; import javax.sip.header.ContentDispositionHeader; import javax.sip.header.ContentTypeHeader; public class ContentImpl implements Content { /* * The content type header for this chunk of content. */ private Object content; private String boundary; private ContentTypeHeader contentTypeHeader; private ContentDispositionHeader contentDispositionHeader; public ContentImpl( String content, String boundary ) { this.content = content; this.boundary = boundary; } /* (non-Javadoc) * @see gov.nist.javax.sip.message.ContentExt#setContent(java.lang.String) */ public void setContent(Object content) { this.content = content; } /* (non-Javadoc) * @see gov.nist.javax.sip.message.ContentExt#getContentTypeHeader() */ public ContentTypeHeader getContentTypeHeader() { return contentTypeHeader; } /* * (non-Javadoc) * @see gov.nist.javax.sip.message.Content#getContent() */ public Object getContent() { return this.content; } /* (non-Javadoc) * @see gov.nist.javax.sip.message.ContentExt#toString() */ public String toString() { // This is not part of a multipart message. if (boundary == null) { return content.toString(); } else { if ( this.contentDispositionHeader != null ) { return "--" + boundary + "\r\n" + getContentTypeHeader() + this.getContentDispositionHeader().toString() + "\r\n" + content.toString(); } else { return "--" + boundary + "\r\n" + getContentTypeHeader() + "\r\n" + content.toString(); } } } /** * @param contentDispositionHeader the contentDispositionHeader to set */ public void setContentDispositionHeader(ContentDispositionHeader contentDispositionHeader) { this.contentDispositionHeader = contentDispositionHeader; } /** * @return the contentDispositionHeader */ public ContentDispositionHeader getContentDispositionHeader() { return contentDispositionHeader; } /** * @param contentTypeHeader the contentTypeHeader to set */ public void setContentTypeHeader(ContentTypeHeader contentTypeHeader) { this.contentTypeHeader = contentTypeHeader; } } java/gov/nist/javax/sip/message/HeaderIterator.java0100644 0000000 0000000 00000005710 13513104763 021401 0ustar000000000 0000000 /* * 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.message; import gov.nist.javax.sip.header.*; import java.util.ListIterator; import java.util.NoSuchElementException; /** * Iterator over lists of headers. Allows for uniform removal handling for singleton headers. * @author M. Ranganathan * @version 1.2 $Revision: 1.8 $ $Date: 2009/07/17 18:57:53 $ * @since 1.1 */ public class HeaderIterator implements ListIterator { private boolean toRemove; private int index; private SIPMessage sipMessage; private SIPHeader sipHeader; protected HeaderIterator(SIPMessage sipMessage, SIPHeader sipHeader) { this.sipMessage = sipMessage; this.sipHeader = sipHeader; } public Object next() throws NoSuchElementException { if (sipHeader == null || index == 1) throw new NoSuchElementException(); toRemove = true; index = 1; return (Object) sipHeader; } public Object previous() throws NoSuchElementException { if (sipHeader == null || index == 0) throw new NoSuchElementException(); toRemove = true; index = 0; return (Object) sipHeader; } public int nextIndex() { return 1; } public int previousIndex() { return index == 0 ? -1 : 0; } public void set(Object header) { throw new UnsupportedOperationException(); } public void add(Object header) { throw new UnsupportedOperationException(); } public void remove() throws IllegalStateException { if (this.sipHeader == null) throw new IllegalStateException(); if (toRemove) { this.sipHeader = null; this.sipMessage.removeHeader(sipHeader.getName()); } else { throw new IllegalStateException(); } } public boolean hasNext() { return index == 0; } public boolean hasPrevious() { return index == 1; } } java/gov/nist/javax/sip/message/ListMap.java0100644 0000000 0000000 00000014675 13513104763 020062 0ustar000000000 0000000 /* * 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.javax.sip.message; 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.14 $ $Date: 2009/07/17 18:57:53 $ * @since 1.1 */ class ListMap { // A table that indicates whether a header has a list representation or // not (to catch adding of the non-list form when a list exists.) // Entries in this table allow you to look up the list form of a header // (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 Hashtable,Class> headerListTable; private static boolean initialized; static { initializeListMap(); } static private void initializeListMap() { /* * Build a table mapping between objects that have a list form and the * class of such objects. */ headerListTable = new Hashtable, Class>(); headerListTable.put(ExtensionHeaderImpl.class, ExtensionHeaderList.class); headerListTable.put(Contact.class, ContactList.class); headerListTable.put(ContentEncoding.class, ContentEncodingList.class); headerListTable.put(Via.class, ViaList.class); headerListTable.put(WWWAuthenticate.class, WWWAuthenticateList.class); headerListTable.put(Accept.class, AcceptList.class); headerListTable.put(AcceptEncoding.class, AcceptEncodingList.class); headerListTable.put(AcceptLanguage.class, AcceptLanguageList.class); headerListTable.put(ProxyRequire.class, ProxyRequireList.class); headerListTable.put(Route.class, RouteList.class); headerListTable.put(Require.class, RequireList.class); headerListTable.put(Warning.class, WarningList.class); headerListTable.put(Unsupported.class, UnsupportedList.class); headerListTable.put(AlertInfo.class, AlertInfoList.class); headerListTable.put(CallInfo.class, CallInfoList.class); headerListTable.put(ProxyAuthenticate.class,ProxyAuthenticateList.class); headerListTable.put(ProxyAuthorization.class, ProxyAuthorizationList.class); headerListTable.put(Authorization.class, AuthorizationList.class); headerListTable.put(Allow.class, AllowList.class); headerListTable.put(RecordRoute.class, RecordRouteList.class); headerListTable.put(ContentLanguage.class, ContentLanguageList.class); headerListTable.put(ErrorInfo.class, ErrorInfoList.class); headerListTable.put(Supported.class, SupportedList.class); headerListTable.put(InReplyTo.class,InReplyToList.class); // IMS headers. headerListTable.put(PAssociatedURI.class, PAssociatedURIList.class); headerListTable.put(PMediaAuthorization.class, PMediaAuthorizationList.class); headerListTable.put(Path.class, PathList.class); headerListTable.put(Privacy.class,PrivacyList.class); headerListTable.put(ServiceRoute.class, ServiceRouteList.class); headerListTable.put(PVisitedNetworkID.class, PVisitedNetworkIDList.class); headerListTable.put(SecurityClient.class, SecurityClientList.class); headerListTable.put(SecurityServer.class, SecurityServerList.class); headerListTable.put(SecurityVerify.class, SecurityVerifyList.class); headerListTable.put(PAssertedIdentity.class, PAssertedIdentityList.class); initialized = true; } /** * return true if this has an associated list object. */ static protected boolean hasList(SIPHeader sipHeader) { if (sipHeader instanceof SIPHeaderList) return false; else { Class headerClass = sipHeader.getClass(); return headerListTable.get(headerClass) != null; } } /** * Return true if this has an associated list object. */ static protected boolean hasList(Class sipHdrClass) { if (!initialized) initializeListMap(); return headerListTable.get(sipHdrClass) != null; } /** * Get the associated list class. */ static protected Class getListClass(Class sipHdrClass) { if (!initialized) initializeListMap(); return (Class) headerListTable.get(sipHdrClass); } /** * Return a list object for this header if it has an associated list object. */ @SuppressWarnings("unchecked") static protected SIPHeaderList getList(SIPHeader sipHeader) { if (!initialized) initializeListMap(); try { Class headerClass = sipHeader.getClass(); Class listClass = headerListTable.get(headerClass); SIPHeaderList shl = (SIPHeaderList) listClass.newInstance(); shl.setHeaderName(sipHeader.getName()); return shl; } catch (InstantiationException ex) { ex.printStackTrace(); } catch (IllegalAccessException ex) { ex.printStackTrace(); } return null; } } java/gov/nist/javax/sip/message/MessageExt.java0100644 0000000 0000000 00000006237 13513104763 020551 0ustar000000000 0000000 package gov.nist.javax.sip.message; import java.text.ParseException; import javax.sip.header.CSeqHeader; import javax.sip.header.CallIdHeader; import javax.sip.header.ContentLengthHeader; import javax.sip.header.ContentTypeHeader; import javax.sip.header.FromHeader; import javax.sip.header.ToHeader; import javax.sip.header.ViaHeader; import javax.sip.message.Message; /** * * @author jean.deruelle@gmail.com * */ public interface MessageExt extends Message { /** * This method allows applications to associate application context with * the message. This specification does not define the format of this * data, this the responsibility of the application and is dependent * on the application. * this application data is un-interpreted by the stack. * Beware : when you clone a message, the deepcopy does not apply to the application data * (instead, we would just make a copy of the pointer). * * @param applicationData - un-interpreted application data. * @since v2.0 * */ public void setApplicationData (Object applicationData); /** * Returns the application data associated with the transaction.This * specification does not define the format of this application specific * data. This is the responsibility of the application. * * @return application data associated with the message by the application. * @since v2.0 * */ public Object getApplicationData(); /** * Get the multipart mime content from a message. Builds a wrapper around the * content and breaks it into multiple sections. Returns these sections as * a multipart mime content list. If the content type is not multipart mime * then the list will have a single element in it. * * @since v2.0 * @param Message message * @throws ParseException if the content type is multipart mime but the content * is not properly encoded. * */ public MultipartMimeContent getMultipartMimeContent() throws ParseException; /** * Get the topmost Via header. * * @since v2.0 */ public ViaHeader getTopmostViaHeader(); /** * Get the From header or null if none present. * * @since v2.0 */ public FromHeader getFromHeader(); /** * Get the To header or null if none present. * * @since v2.0 */ public ToHeader getToHeader(); /** * Get the callId header or null if none present. * * @since v2.0 */ public CallIdHeader getCallIdHeader(); /** * Get the CSeq header or null if none present. * * @since v2.0 */ public CSeqHeader getCSeqHeader(); /** * Get the content type header or null if none present. * * @since v2.0 */ public ContentTypeHeader getContentTypeHeader(); /** * Get the content length header or null if none present. * * @since v2.0 */ public ContentLengthHeader getContentLengthHeader(); /** * Get the first line of the request or response. * * @since v2.0 */ public String getFirstLine(); } java/gov/nist/javax/sip/message/MessageFactoryExt.java0100644 0000000 0000000 00000004213 13513104763 022071 0ustar000000000 0000000 package gov.nist.javax.sip.message; import javax.sip.header.ContentTypeHeader; import javax.sip.header.ServerHeader; import javax.sip.header.UserAgentHeader; import javax.sip.message.MessageFactory; /** * Intefaces that will be supported by the next release of JAIN-SIP. * * @author mranga * */ public interface MessageFactoryExt extends MessageFactory { /** * Set the common UserAgent header for all Requests created from this message factory. * This header is applied to all Messages created from this Factory object except those * that take String for an argument and create Message from the given String. * * @param userAgent -- the user agent header to set. * */ public void setDefaultUserAgentHeader(UserAgentHeader userAgent); /** * Set the common Server header for all Responses created from this message factory. * This header is applied to all Messages created from this Factory object except those * that take String for an argument and create Message from the given String. * * @param userAgent -- the user agent header to set. * * @since 2.0 * */ public void setDefaultServerHeader(ServerHeader userAgent); /** * Set default charset used for encoding String content. Note that this * will be applied to all content that is encoded. The default is UTF-8. * * @since 2.0 * * @param charset -- charset to set. * @throws NullPointerException if null arg * @throws IllegalArgumentException if Charset is not a known charset. * */ public void setDefaultContentEncodingCharset(String charset) throws NullPointerException,IllegalArgumentException ; /** * Create a MultipartMime attachment from a list of content type, subtype and content. * * @since 2.0 * * @throws NullPointerException, IllegalArgumentException */ public MultipartMimeContent createMultipartMimeContent(ContentTypeHeader multipartMimeContentTypeHeader, String[] contentType, String[] contentSubtype, String[] contentBody); } java/gov/nist/javax/sip/message/MessageFactoryImpl.java0100644 0000000 0000000 00000103064 13513104763 022236 0ustar000000000 0000000 /* * 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.javax.sip.message; import java.text.ParseException; import javax.sip.header.*; import java.util.LinkedList; import java.util.List; import gov.nist.javax.sip.header.*; import javax.sip.message.*; import javax.sip.address.*; import gov.nist.javax.sip.parser.*; /** * Message Factory implementation * * @version 1.2 $Revision: 1.23 $ $Date: 2009/09/08 01:58:40 $ * @since 1.1 * * @author M. Ranganathan
    * @author Olivier Deruelle
    * */ @SuppressWarnings("unchecked") public class MessageFactoryImpl implements MessageFactory, MessageFactoryExt { private boolean testing = false; private boolean strict = true; private static String defaultContentEncodingCharset = "UTF-8"; /* * The UserAgent header to include for all requests created from this message factory. */ private static UserAgentHeader userAgent; /* * The Server header to include */ private static ServerHeader server; public void setStrict(boolean strict) { this.strict = strict; } /** * This is for testing -- allows you to generate invalid requests */ public void setTest(boolean flag) { this.testing = flag; } /** * Creates a new instance of MessageFactoryImpl */ public MessageFactoryImpl() { } /** * Creates a new Request message of type specified by the method paramater, * containing the URI of the Request, the mandatory headers of the message * with a body in the form of a Java object and the body content type. * * @param requestURI - * the new URI object of the requestURI value of this Message. * @param method - * the new string of the method value of this Message. * @param callId - * the new CallIdHeader object of the callId value of this * Message. * @param cSeq - * the new CSeqHeader object of the cSeq value of this Message. * @param from - * the new FromHeader object of the from value of this Message. * @param to - * the new ToHeader object of the to value of this Message. * @param via - * the new List object of the ViaHeaders of this Message. * @param content - * the new Object of the body content value of this Message. * @param contentType - * the new ContentTypeHeader object of the content type value of * this Message. * @throws ParseException * which signals that an error has been reached unexpectedly * while parsing the method or the body. */ public Request createRequest(javax.sip.address.URI requestURI, String method, CallIdHeader callId, CSeqHeader cSeq, FromHeader from, ToHeader to, List via, MaxForwardsHeader maxForwards, ContentTypeHeader contentType, Object content) throws ParseException { if (requestURI == null || method == null || callId == null || cSeq == null || from == null || to == null || via == null || maxForwards == null || content == null || contentType == null) throw new NullPointerException("Null parameters"); SIPRequest sipRequest = new SIPRequest(); sipRequest.setRequestURI(requestURI); sipRequest.setMethod(method); sipRequest.setCallId(callId); sipRequest.setCSeq(cSeq); sipRequest.setFrom(from); sipRequest.setTo(to); sipRequest.setVia(via); sipRequest.setMaxForwards(maxForwards); sipRequest.setContent(content, contentType); if ( userAgent != null ) { sipRequest.setHeader(userAgent); } return sipRequest; } /** * Creates a new Request message of type specified by the method paramater, * containing the URI of the Request, the mandatory headers of the message * with a body in the form of a byte array and body content type. * * @param requestURI - * the new URI object of the requestURI value of this Message. * @param method - * the new string of the method value of this Message. * @param callId - * the new CallIdHeader object of the callId value of this * Message. * @param cSeq - * the new CSeqHeader object of the cSeq value of this Message. * @param from - * the new FromHeader object of the from value of this Message. * @param to - * the new ToHeader object of the to value of this Message. * @param via - * the new List object of the ViaHeaders of this Message. * @param content - * the new byte array of the body content value of this Message. * @param contentType - * the new ContentTypeHeader object of the content type value of * this Message. * @throws ParseException * which signals that an error has been reached unexpectedly * while parsing the method or the body. */ public Request createRequest(URI requestURI, String method, CallIdHeader callId, CSeqHeader cSeq, FromHeader from, ToHeader to, List via, MaxForwardsHeader maxForwards, byte[] content, ContentTypeHeader contentType) throws ParseException { if (requestURI == null || method == null || callId == null || cSeq == null || from == null || to == null || via == null || maxForwards == null || content == null || contentType == null) throw new ParseException( "JAIN-SIP Exception, some parameters are missing" + ", unable to create the request", 0); SIPRequest sipRequest = new SIPRequest(); sipRequest.setRequestURI(requestURI); sipRequest.setMethod(method); sipRequest.setCallId(callId); sipRequest.setCSeq(cSeq); sipRequest.setFrom(from); sipRequest.setTo(to); sipRequest.setVia(via); sipRequest.setMaxForwards(maxForwards); sipRequest.setHeader((ContentType) contentType); sipRequest.setMessageContent(content); if ( userAgent != null ) { sipRequest.setHeader(userAgent); } return sipRequest; } /** * Creates a new Request message of type specified by the method paramater, * containing the URI of the Request, the mandatory headers of the message. * This new Request does not contain a body. * * @param requestURI - * the new URI object of the requestURI value of this Message. * @param method - * the new string of the method value of this Message. * @param callId - * the new CallIdHeader object of the callId value of this * Message. * @param cSeq - * the new CSeqHeader object of the cSeq value of this Message. * @param from - * the new FromHeader object of the from value of this Message. * @param to - * the new ToHeader object of the to value of this Message. * @param via - * the new List object of the ViaHeaders of this Message. * @throws ParseException * which signals that an error has been reached unexpectedly * while parsing the method. */ public Request createRequest(URI requestURI, String method, CallIdHeader callId, CSeqHeader cSeq, FromHeader from, ToHeader to, List via, MaxForwardsHeader maxForwards) throws ParseException { if (requestURI == null || method == null || callId == null || cSeq == null || from == null || to == null || via == null || maxForwards == null) throw new ParseException( "JAIN-SIP Exception, some parameters are missing" + ", unable to create the request", 0); SIPRequest sipRequest = new SIPRequest(); sipRequest.setRequestURI(requestURI); sipRequest.setMethod(method); sipRequest.setCallId(callId); sipRequest.setCSeq(cSeq); sipRequest.setFrom(from); sipRequest.setTo(to); sipRequest.setVia(via); sipRequest.setMaxForwards(maxForwards); if (userAgent != null) { sipRequest.setHeader(userAgent); } return sipRequest; } // Standard Response Creation methods /** * Creates a new Response message of type specified by the statusCode * paramater, containing the mandatory headers of the message with a body in * the form of a Java object and the body content type. * * @param statusCode - * the new integer of the statusCode value of this Message. * @param callId - * the new CallIdHeader object of the callId value of this * Message. * @param cSeq - * the new CSeqHeader object of the cSeq value of this Message. * @param from - * the new FromHeader object of the from value of this Message. * @param to - * the new ToHeader object of the to value of this Message. * @param via - * the new List object of the ViaHeaders of this Message. * @param content - * the new Object of the body content value of this Message. * @param contentType - * the new ContentTypeHeader object of the content type value of * this Message. * @throws ParseException * which signals that an error has been reached unexpectedly * while parsing the statusCode or the body. */ public Response createResponse(int statusCode, CallIdHeader callId, CSeqHeader cSeq, FromHeader from, ToHeader to, List via, MaxForwardsHeader maxForwards, Object content, ContentTypeHeader contentType) throws ParseException { if (callId == null || cSeq == null || from == null || to == null || via == null || maxForwards == null || content == null || contentType == null) throw new NullPointerException(" unable to create the response"); SIPResponse sipResponse = new SIPResponse(); StatusLine statusLine = new StatusLine(); statusLine.setStatusCode(statusCode); String reasonPhrase = SIPResponse.getReasonPhrase(statusCode); //if (reasonPhrase == null) // throw new ParseException(statusCode + " Unkown ", 0); statusLine.setReasonPhrase(reasonPhrase); sipResponse.setStatusLine(statusLine); sipResponse.setCallId(callId); sipResponse.setCSeq(cSeq); sipResponse.setFrom(from); sipResponse.setTo(to); sipResponse.setVia(via); sipResponse.setMaxForwards(maxForwards); sipResponse.setContent(content, contentType); if (userAgent != null) { sipResponse.setHeader(userAgent); } return sipResponse; } /** * Creates a new Response message of type specified by the statusCode * paramater, containing the mandatory headers of the message with a body in * the form of a byte array and the body content type. * * @param statusCode - * the new integer of the statusCode value of this Message. * @param callId - * the new CallIdHeader object of the callId value of this * Message. * @param cSeq - * the new CSeqHeader object of the cSeq value of this Message. * @param from - * the new FromHeader object of the from value of this Message. * @param to - * the new ToHeader object of the to value of this Message. * @param via - * the new List object of the ViaHeaders of this Message. * @param content - * the new byte array of the body content value of this Message. * @param contentType - * the new ContentTypeHeader object of the content type value of * this Message. * @throws ParseException * which signals that an error has been reached unexpectedly * while parsing the statusCode or the body. */ public Response createResponse(int statusCode, CallIdHeader callId, CSeqHeader cSeq, FromHeader from, ToHeader to, List via, MaxForwardsHeader maxForwards, byte[] content, ContentTypeHeader contentType) throws ParseException { if (callId == null || cSeq == null || from == null || to == null || via == null || maxForwards == null || content == null || contentType == null) throw new NullPointerException("Null params "); SIPResponse sipResponse = new SIPResponse(); sipResponse.setStatusCode(statusCode); sipResponse.setCallId(callId); sipResponse.setCSeq(cSeq); sipResponse.setFrom(from); sipResponse.setTo(to); sipResponse.setVia(via); sipResponse.setMaxForwards(maxForwards); sipResponse.setHeader((ContentType) contentType); sipResponse.setMessageContent(content); if (userAgent != null) { sipResponse.setHeader(userAgent); } return sipResponse; } /** * Creates a new Response message of type specified by the statusCode * paramater, containing the mandatory headers of the message. This new * Response does not contain a body. * * @param statusCode - * the new integer of the statusCode value of this Message. * @param callId - * the new CallIdHeader object of the callId value of this * Message. * @param cSeq - * the new CSeqHeader object of the cSeq value of this Message. * @param from - * the new FromHeader object of the from value of this Message. * @param to - * the new ToHeader object of the to value of this Message. * @param via - * the new List object of the ViaHeaders of this Message. * @throws ParseException * which signals that an error has been reached unexpectedly * while parsing the statusCode. */ public Response createResponse(int statusCode, CallIdHeader callId, CSeqHeader cSeq, FromHeader from, ToHeader to, List via, MaxForwardsHeader maxForwards) throws ParseException { if (callId == null || cSeq == null || from == null || to == null || via == null || maxForwards == null) throw new ParseException( "JAIN-SIP Exception, some parameters are missing" + ", unable to create the response", 0); SIPResponse sipResponse = new SIPResponse(); sipResponse.setStatusCode(statusCode); sipResponse.setCallId(callId); sipResponse.setCSeq(cSeq); sipResponse.setFrom(from); sipResponse.setTo(to); sipResponse.setVia(via); sipResponse.setMaxForwards(maxForwards); if (userAgent != null) { sipResponse.setHeader(userAgent); } return sipResponse; } // Response Creation methods based on a Request /** * Creates a new Response message of type specified by the statusCode * paramater, based on a specific Request with a new body in the form of a * Java object and the body content type. * * @param statusCode - * the new integer of the statusCode value of this Message. * @param request - * the received Reqest object upon which to base the Response. * @param content - * the new Object of the body content value of this Message. * @param contentType - * the new ContentTypeHeader object of the content type value of * this Message. * @throws ParseException * which signals that an error has been reached unexpectedly * while parsing the statusCode or the body. */ public Response createResponse(int statusCode, Request request, ContentTypeHeader contentType, Object content) throws ParseException { if (request == null || content == null || contentType == null) throw new NullPointerException("null parameters"); SIPRequest sipRequest = (SIPRequest) request; SIPResponse sipResponse = sipRequest.createResponse(statusCode); sipResponse.setContent(content, contentType); if (server != null) { sipResponse.setHeader(server); } return sipResponse; } /** * Creates a new Response message of type specified by the statusCode * paramater, based on a specific Request with a new body in the form of a * byte array and the body content type. * * @param statusCode - * the new integer of the statusCode value of this Message. * @param request - * the received Reqest object upon which to base the Response. * @param content - * the new byte array of the body content value of this Message. * @param contentType - * the new ContentTypeHeader object of the content type value of * this Message. * @throws ParseException * which signals that an error has been reached unexpectedly * while parsing the statusCode or the body. */ public Response createResponse(int statusCode, Request request, ContentTypeHeader contentType, byte[] content) throws ParseException { if (request == null || content == null || contentType == null) throw new NullPointerException("null Parameters"); SIPRequest sipRequest = (SIPRequest) request; SIPResponse sipResponse = sipRequest.createResponse(statusCode); sipResponse.setHeader((ContentType) contentType); sipResponse.setMessageContent(content); if (server != null) { sipResponse.setHeader(server); } return sipResponse; } /** * Creates a new Response message of type specified by the statusCode * paramater, based on a specific Request message. This new Response does * not contain a body. * * @param statusCode - * the new integer of the statusCode value of this Message. * @param request - * the received Reqest object upon which to base the Response. * @throws ParseException * which signals that an error has been reached unexpectedly * while parsing the statusCode. */ public Response createResponse(int statusCode, Request request) throws ParseException { if (request == null) throw new NullPointerException("null parameters"); // if (LogWriter.needsLogging) // LogWriter.logMessage("createResponse " + request); SIPRequest sipRequest = (SIPRequest) request; SIPResponse sipResponse = sipRequest.createResponse(statusCode); // Remove the content from the message (Bug report from // Antonis Karydas. sipResponse.removeContent(); sipResponse.removeHeader(ContentTypeHeader.NAME); if (server != null) { sipResponse.setHeader(server); } return sipResponse; } /** * Creates a new Request message of type specified by the method paramater, * containing the URI of the Request, the mandatory headers of the message * with a body in the form of a byte array and body content type. * * @param requestURI - * the new URI object of the requestURI value of this Message. * @param method - * the new string of the method value of this Message. * @param callId - * the new CallIdHeader object of the callId value of this * Message. * @param cSeq - * the new CSeqHeader object of the cSeq value of this Message. * @param from - * the new FromHeader object of the from value of this Message. * @param to - * the new ToHeader object of the to value of this Message. * @param via - * the new List object of the ViaHeaders of this Message. * @param contentType - * the new ContentTypeHeader object of the content type value of * this Message. * @param content - * the new byte array of the body content value of this Message. * @throws ParseException * which signals that an error has been reached unexpectedly * while parsing the method or the body. */ public Request createRequest(javax.sip.address.URI requestURI, String method, CallIdHeader callId, CSeqHeader cSeq, FromHeader from, ToHeader to, List via, MaxForwardsHeader maxForwards, ContentTypeHeader contentType, byte[] content) throws ParseException { if (requestURI == null || method == null || callId == null || cSeq == null || from == null || to == null || via == null || maxForwards == null || content == null || contentType == null) throw new NullPointerException("missing parameters"); SIPRequest sipRequest = new SIPRequest(); sipRequest.setRequestURI(requestURI); sipRequest.setMethod(method); sipRequest.setCallId(callId); sipRequest.setCSeq(cSeq); sipRequest.setFrom(from); sipRequest.setTo(to); sipRequest.setVia(via); sipRequest.setMaxForwards(maxForwards); sipRequest.setContent(content, contentType); if (userAgent != null) { sipRequest.setHeader(userAgent); } return sipRequest; } /** * Creates a new Response message of type specified by the statusCode * paramater, containing the mandatory headers of the message with a body in * the form of a Java object and the body content type. * * @param statusCode * the new integer of the statusCode value of this Message. * @param callId * the new CallIdHeader object of the callId value of this * Message. * @param cSeq * the new CSeqHeader object of the cSeq value of this Message. * @param from * the new FromHeader object of the from value of this Message. * @param to * the new ToHeader object of the to value of this Message. * @param via * the new List object of the ViaHeaders of this Message. * @param contentType * the new ContentTypeHeader object of the content type value of * this Message. * @param content * the new Object of the body content value of this Message. * @throws ParseException * which signals that an error has been reached unexpectedly * while parsing the statusCode or the body. */ public Response createResponse(int statusCode, CallIdHeader callId, CSeqHeader cSeq, FromHeader from, ToHeader to, List via, MaxForwardsHeader maxForwards, ContentTypeHeader contentType, Object content) throws ParseException { if (callId == null || cSeq == null || from == null || to == null || via == null || maxForwards == null || content == null || contentType == null) throw new NullPointerException("missing parameters"); SIPResponse sipResponse = new SIPResponse(); StatusLine statusLine = new StatusLine(); statusLine.setStatusCode(statusCode); String reason = SIPResponse.getReasonPhrase(statusCode); if (reason == null) throw new ParseException(statusCode + " Unknown", 0); statusLine.setReasonPhrase(reason); sipResponse.setStatusLine(statusLine); sipResponse.setCallId(callId); sipResponse.setCSeq(cSeq); sipResponse.setFrom(from); sipResponse.setTo(to); sipResponse.setVia(via); sipResponse.setContent(content, contentType); if ( userAgent != null) { sipResponse.setHeader(userAgent); } return sipResponse; } /** * Creates a new Response message of type specified by the statusCode * paramater, containing the mandatory headers of the message with a body in * the form of a byte array and the body content type. * * @param statusCode * the new integer of the statusCode value of this Message. * @param callId * the new CallIdHeader object of the callId value of this * Message. * @param cSeq * the new CSeqHeader object of the cSeq value of this Message. * @param from * the new FromHeader object of the from value of this Message. * @param to * the new ToHeader object of the to value of this Message. * @param via * the new List object of the ViaHeaders of this Message. * @param contentType * the new ContentTypeHeader object of the content type value of * this Message. * @param content * the new byte array of the body content value of this Message. * @throws ParseException * which signals that an error has been reached unexpectedly * while parsing the statusCode or the body. */ public Response createResponse(int statusCode, CallIdHeader callId, CSeqHeader cSeq, FromHeader from, ToHeader to, List via, MaxForwardsHeader maxForwards, ContentTypeHeader contentType, byte[] content) throws ParseException { if (callId == null || cSeq == null || from == null || to == null || via == null || maxForwards == null || content == null || contentType == null) throw new NullPointerException("missing parameters"); SIPResponse sipResponse = new SIPResponse(); StatusLine statusLine = new StatusLine(); statusLine.setStatusCode(statusCode); String reason = SIPResponse.getReasonPhrase(statusCode); if (reason == null) throw new ParseException(statusCode + " : Unknown", 0); statusLine.setReasonPhrase(reason); sipResponse.setStatusLine(statusLine); sipResponse.setCallId(callId); sipResponse.setCSeq(cSeq); sipResponse.setFrom(from); sipResponse.setTo(to); sipResponse.setVia(via); sipResponse.setContent(content, contentType); if ( userAgent != null) { sipResponse.setHeader(userAgent); } return sipResponse; } /** * Create a request from a string. Conveniance method for UACs that want to * create an outgoing request from a string. Only the headers of the request * should be included in the String that is supplied to this method. * * @param requestString -- * string from which to create the message null string returns an * empty message. */ public javax.sip.message.Request createRequest(String requestString) throws java.text.ParseException { if (requestString == null || requestString.equals("")) { SIPRequest retval = new SIPRequest(); retval.setNullRequest(); return retval; } StringMsgParser smp = new StringMsgParser(); smp.setStrict(this.strict); /* * This allows you to catch parse exceptions and create invalid messages * if you want. */ ParseExceptionListener parseExceptionListener = new ParseExceptionListener() { public void handleException(ParseException ex, SIPMessage sipMessage, Class headerClass, String headerText, String messageText) throws ParseException { // Rethrow the error for the essential headers. Otherwise bad // headers are simply // recorded in the message. if (testing) { if (headerClass == From.class || headerClass == To.class || headerClass == CallID.class || headerClass == MaxForwards.class || headerClass == Via.class || headerClass == RequestLine.class || headerClass == StatusLine.class || headerClass == CSeq.class) throw ex; sipMessage.addUnparsed(headerText); } } }; if (this.testing) smp.setParseExceptionListener(parseExceptionListener); SIPMessage sipMessage = smp.parseSIPMessage(requestString); if (!(sipMessage instanceof SIPRequest)) throw new ParseException(requestString, 0); return (SIPRequest) sipMessage; } /** * Create a response from a string * * @param responseString -- * string from which to create the message null string returns an * empty message. * */ public Response createResponse(String responseString) throws java.text.ParseException { if (responseString == null) return new SIPResponse(); StringMsgParser smp = new StringMsgParser(); SIPMessage sipMessage = smp.parseSIPMessage(responseString); if (!(sipMessage instanceof SIPResponse)) throw new ParseException(responseString, 0); return (SIPResponse) sipMessage; } /** * Set the common UserAgent header for all requests created from this message factory. * This header is applied to all Messages created from this Factory object except those * that take String for an argument and create Message from the given String. * * @param userAgent -- the user agent header to set. * * @since 2.0 */ public void setDefaultUserAgentHeader(UserAgentHeader userAgent) { MessageFactoryImpl.userAgent = userAgent; } /** * Set the common Server header for all responses created from this message factory. * This header is applied to all Messages created from this Factory object except those * that take String for an argument and create Message from the given String. * * @param userAgent -- the user agent header to set. * * @since 2.0 */ public void setDefaultServerHeader(ServerHeader server) { MessageFactoryImpl.server = server; } /** * Get the default common UserAgentHeader. * * @return the user agent header. * * @since 2.0 */ public static UserAgentHeader getDefaultUserAgentHeader() { return userAgent; } /** * Get the default common server header. * * @return the server header. */ public static ServerHeader getDefaultServerHeader() { return server; } /** * Set default charset used for encoding String content. * @param charset */ public void setDefaultContentEncodingCharset(String charset) throws NullPointerException, IllegalArgumentException { if (charset == null ) throw new NullPointerException ("Null argument!"); MessageFactoryImpl.defaultContentEncodingCharset = charset; } public static String getDefaultContentEncodingCharset() { return MessageFactoryImpl.defaultContentEncodingCharset; } public MultipartMimeContent createMultipartMimeContent(ContentTypeHeader multipartMimeCth, String[] contentType, String[] contentSubtype, String[] contentBody) { String boundary = multipartMimeCth.getParameter("boundary"); MultipartMimeContentImpl retval = new MultipartMimeContentImpl(multipartMimeCth); for (int i = 0 ; i < contentType.length; i++ ) { ContentTypeHeader cth = new ContentType(contentType[i],contentSubtype[i]); ContentImpl contentImpl = new ContentImpl(contentBody[i],boundary); contentImpl.setContentTypeHeader(cth); retval.add(contentImpl); } return retval; } } java/gov/nist/javax/sip/message/MessageObject.java0100644 0000000 0000000 00000014516 13513104763 021216 0ustar000000000 0000000 /* * 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.javax.sip.message; import gov.nist.core.*; import java.lang.reflect.*; /** * This is the root object from which all other objects in this package * are derived. This class is never directly instantiated (and hence it * is abstract). * * @version 1.2 $Revision: 1.7 $ $Date: 2009/07/17 18:57:54 $ * @since 1.1 * * @author M. Ranganathan
    * * */ public abstract class MessageObject extends GenericObject { public abstract String encode(); public void dbgPrint() { super.dbgPrint(); } /** * An introspection based string formatting method. We need this because * in this package (although it is an exact duplicate of the one in * the superclass) because it needs to access the protected members * of the other objects in this class. */ public String debugDump() { stringRepresentation = ""; Class myclass = getClass(); sprint(myclass.getName()); sprint("{"); Field[] fields = myclass.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { Field f = fields[i]; // Only print protected and public members. int modifier = f.getModifiers(); if (modifier == Modifier.PRIVATE) continue; Class fieldType = f.getType(); String fieldName = f.getName(); if (fieldName.compareTo("stringRepresentation") == 0) { // avoid nasty recursions... continue; } if (fieldName.compareTo("indentation") == 0) { // formatting stuff - not relevant here. continue; } sprint(fieldName + ":"); try { // Primitive fields are printed with type: value if (fieldType.isPrimitive()) { String fname = fieldType.toString(); sprint(fname + ":"); if (fname.compareTo("int") == 0) { int intfield = f.getInt(this); sprint(intfield); } else if (fname.compareTo("short") == 0) { short shortField = f.getShort(this); sprint(shortField); } else if (fname.compareTo("char") == 0) { char charField = f.getChar(this); sprint(charField); } else if (fname.compareTo("long") == 0) { long longField = f.getLong(this); sprint(longField); } else if (fname.compareTo("boolean") == 0) { boolean booleanField = f.getBoolean(this); sprint(booleanField); } else if (fname.compareTo("double") == 0) { double doubleField = f.getDouble(this); sprint(doubleField); } else if (fname.compareTo("float") == 0) { float floatField = f.getFloat(this); sprint(floatField); } } else if ( GenericObject.class.isAssignableFrom( fieldType)) { if (f.get(this) != null) { sprint( ((GenericObject) f.get(this)).debugDump( this.indentation + 1)); } else { sprint(""); } } else if (GenericObjectList.class.isAssignableFrom( fieldType)) { if (f.get(this) != null) { sprint( ((GenericObjectList) f.get(this)).debugDump( indentation + 1)); } else { sprint(""); } } else { // Dont do recursion on things that are not // of our header type... if (f.get(this) != null) { sprint(f.get(this).getClass().getName() + ":"); } else { sprint(fieldType.getName() + ":"); } sprint("{"); if (f.get(this) != null) { sprint(f.get(this).toString()); } else { sprint(""); } sprint("}"); } } catch (IllegalAccessException ex1) { continue; // we are accessing a private field... } } sprint("}"); return stringRepresentation; } protected MessageObject() { super(); } /** * Formatter with a given starting indentation (for nested structs). */ public String dbgPrint(int indent) { int save = indentation; indentation = indent; String retval = this.toString(); indentation = save; return retval; } } java/gov/nist/javax/sip/message/MultipartMimeContent.java0100644 0000000 0000000 00000001711 13513104763 022620 0ustar000000000 0000000 package gov.nist.javax.sip.message; import java.util.Iterator; import java.util.List; import javax.sip.header.ContentTypeHeader; public interface MultipartMimeContent { public abstract boolean add(Content content); /** * Return the Content type header to assign to the outgoing sip meassage. * * @return */ public abstract ContentTypeHeader getContentTypeHeader(); public abstract String toString(); /** * Set the content by its type. * * @param content */ public abstract void addContent( Content content); /** * Retrieve the list of Content that is part of this MultitypeMime content. * * @return - the content iterator. Returns an empty iterator if no content list present. */ public Iterator getContents(); /** * Get the number of Content parts. * * @return - the content parts. */ public int getContentCount(); } java/gov/nist/javax/sip/message/MultipartMimeContentImpl.java0100644 0000000 0000000 00000014102 13513104763 023440 0ustar000000000 0000000 package gov.nist.javax.sip.message; import gov.nist.javax.sip.header.HeaderFactoryExt; import gov.nist.javax.sip.header.HeaderFactoryImpl; import gov.nist.javax.sip.parser.StringMsgParser; import java.text.ParseException; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import javax.sip.header.ContentDispositionHeader; import javax.sip.header.ContentTypeHeader; import javax.sip.header.Header; import javax.sip.header.HeaderFactory; import javax.sip.message.Message; /** * Content list for multipart mime content type. * * @author M. Ranganathan * */ public class MultipartMimeContentImpl implements MultipartMimeContent { private List contentList = new LinkedList(); private ContentTypeHeader multipartMimeContentTypeHeader; private String boundary; public static String BOUNDARY = "boundary"; /** * Creates a default content list. */ public MultipartMimeContentImpl(ContentTypeHeader contentTypeHeader) { this.multipartMimeContentTypeHeader = contentTypeHeader; this.boundary = contentTypeHeader.getParameter(BOUNDARY); } /* * (non-Javadoc) * * @see gov.nist.javax.sip.message.MultipartMimeContentExt#add(gov.nist.javax.sip.message.Content) */ public boolean add(Content content) { return contentList.add((ContentImpl) content); } /* * (non-Javadoc) * * @see gov.nist.javax.sip.message.MultipartMimeContentExt#getContentTypeHeader() */ public ContentTypeHeader getContentTypeHeader() { return multipartMimeContentTypeHeader; } /* * (non-Javadoc) * * @see gov.nist.javax.sip.message.MultipartMimeContentExt#toString() */ @Override public String toString() { StringBuffer stringBuffer = new StringBuffer(); for (Content content : this.contentList) { stringBuffer.append(content.toString()); } return stringBuffer.toString(); } /** * unpack a multipart mime packet and return a list of content packets. * * @return -- an iterator of Content blocks. * */ public void createContentList(String body) throws ParseException { try { HeaderFactoryExt headerFactory = new HeaderFactoryImpl(); String delimiter = this.getContentTypeHeader().getParameter(BOUNDARY); if (delimiter == null) { this.contentList = new LinkedList(); ContentImpl content = new ContentImpl(body, delimiter); content.setContentTypeHeader(this.getContentTypeHeader()); this.contentList.add(content); return; } String[] fragments = body.split("--" + delimiter + "\r\n"); for (String nextPart : fragments) { // NOTE - we are not hanlding line folding for the sip header here. if (nextPart == null) { return; } StringBuffer strbuf = new StringBuffer(nextPart); while (strbuf.length() > 0 && (strbuf.charAt(0) == '\r' || strbuf.charAt(0) == '\n')) strbuf.deleteCharAt(0); if (strbuf.length() == 0) continue; nextPart = strbuf.toString(); int position = nextPart.indexOf("\r\n\r\n"); int off = 4; if (position == -1) { position = nextPart.indexOf("\n"); off = 2; } if (position == -1) throw new ParseException("no content type header found in " + nextPart, 0); String rest = nextPart.substring(position + off); if (rest == null) throw new ParseException("No content [" + nextPart + "]", 0); // logger.debug("rest = [[" + rest + "]]"); String headers = nextPart.substring(0, position); ContentImpl content = new ContentImpl(rest, boundary); String[] headerArray = headers.split("\r\n"); for (String hdr : headerArray) { Header header = headerFactory.createHeader(hdr); if (header instanceof ContentTypeHeader) { content.setContentTypeHeader((ContentTypeHeader) header); } else if (header instanceof ContentDispositionHeader) { content.setContentDispositionHeader((ContentDispositionHeader) header); } else { throw new ParseException("Unexpected header type " + header.getName(), 0); } contentList.add(content); } } } catch (StringIndexOutOfBoundsException ex) { throw new ParseException("Invalid Multipart mime format", 0); } } /* * (non-Javadoc) * * @see gov.nist.javax.sip.message.MultipartMimeContentExt#getContentByType(java.lang.String, * java.lang.String) */ public Content getContentByType(String contentType, String contentSubtype) { Content retval = null; if (contentList == null) return null; for (Content content : contentList) { if (content.getContentTypeHeader().getContentType().equalsIgnoreCase(contentType) && content.getContentTypeHeader().getContentSubType().equalsIgnoreCase( contentSubtype)) { retval = content; break; } } return retval; } /* * (non-Javadoc) * * @see gov.nist.javax.sip.message.MultipartMimeContentExt#setContent(java.lang.String, * java.lang.String, gov.nist.javax.sip.message.Content) */ public void addContent(Content content) { this.add(content); } public Iterator getContents() { return this.contentList.iterator(); } public int getContentCount() { return this.contentList.size(); } } java/gov/nist/javax/sip/message/RequestExt.java0100644 0000000 0000000 00000000300 13513104763 020576 0ustar000000000 0000000 package gov.nist.javax.sip.message; import javax.sip.message.Request; /** * Extensions for the JAIN-SIP Request interface. */ public interface RequestExt extends Request, MessageExt { } java/gov/nist/javax/sip/message/ResponseExt.java0100644 0000000 0000000 00000000364 13513104763 020756 0ustar000000000 0000000 package gov.nist.javax.sip.message; import javax.sip.message.Response; /** *Extension for the jain-sip Response interface. This is a convenience *interface (placeholder). */ public interface ResponseExt extends Response, MessageExt { } java/gov/nist/javax/sip/message/SIPDuplicateHeaderException.java0100644 0000000 0000000 00000004643 13513104763 023761 0ustar000000000 0000000 /* * 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.javax.sip.message; import gov.nist.javax.sip.header.*; import java.text.ParseException; /** * Duplicate header exception: thrown when there is more * than one header of a type where there should only be one. * The exception handler may choose to : * 1. discard the duplicate by returning null * 2. keep the duplicate by just returning it. * 3. Discard the entire message by throwing an exception. * @version 1.2 $Revision: 1.6 $ $Date: 2009/07/17 18:57:54 $ * @since 1.1 * @author M. Ranganathan */ public class SIPDuplicateHeaderException extends ParseException { private static final long serialVersionUID = 8241107266407879291L; protected SIPHeader sipHeader; protected SIPMessage sipMessage; public SIPDuplicateHeaderException(String msg) { super(msg, 0); } public SIPMessage getSIPMessage() { return sipMessage; } public SIPHeader getSIPHeader() { return sipHeader; } public void setSIPHeader(SIPHeader sipHeader) { this.sipHeader = sipHeader; } public void setSIPMessage(SIPMessage sipMessage) { this.sipMessage = sipMessage; } } java/gov/nist/javax/sip/message/SIPMessage.java0100644 0000000 0000000 00000177201 13513104763 020444 0ustar000000000 0000000 /* * 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.javax.sip.message; import gov.nist.core.InternalErrorHandler; import gov.nist.javax.sip.SIPConstants; import gov.nist.javax.sip.Utils; import gov.nist.javax.sip.header.AlertInfo; import gov.nist.javax.sip.header.Authorization; import gov.nist.javax.sip.header.CSeq; import gov.nist.javax.sip.header.CallID; import gov.nist.javax.sip.header.Contact; 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.ErrorInfo; import gov.nist.javax.sip.header.ErrorInfoList; import gov.nist.javax.sip.header.From; import gov.nist.javax.sip.header.InReplyTo; import gov.nist.javax.sip.header.MaxForwards; import gov.nist.javax.sip.header.Priority; import gov.nist.javax.sip.header.ProxyAuthenticate; import gov.nist.javax.sip.header.ProxyAuthorization; import gov.nist.javax.sip.header.ProxyRequire; import gov.nist.javax.sip.header.ProxyRequireList; import gov.nist.javax.sip.header.RSeq; import gov.nist.javax.sip.header.RecordRouteList; 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.SIPETag; import gov.nist.javax.sip.header.SIPHeader; import gov.nist.javax.sip.header.SIPHeaderList; import gov.nist.javax.sip.header.SIPHeaderNamesCache; import gov.nist.javax.sip.header.SIPIfMatch; import gov.nist.javax.sip.header.Server; import gov.nist.javax.sip.header.Subject; import gov.nist.javax.sip.header.To; import gov.nist.javax.sip.header.Unsupported; import gov.nist.javax.sip.header.UserAgent; 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.Warning; import gov.nist.javax.sip.parser.HeaderParser; import gov.nist.javax.sip.parser.ParserFactory; import gov.nist.javax.sip.parser.PipelinedMsgParser; import gov.nist.javax.sip.parser.StringMsgParser; import java.io.UnsupportedEncodingException; import java.lang.reflect.Field; 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.concurrent.ConcurrentLinkedQueue; import javax.sip.InvalidArgumentException; import javax.sip.SipException; import javax.sip.header.AuthorizationHeader; import javax.sip.header.CSeqHeader; import javax.sip.header.CallIdHeader; 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.ExpiresHeader; import javax.sip.header.FromHeader; import javax.sip.header.Header; import javax.sip.header.MaxForwardsHeader; import javax.sip.header.RecordRouteHeader; import javax.sip.header.RouteHeader; import javax.sip.header.ToHeader; import javax.sip.header.ViaHeader; import javax.sip.message.Request; /* * 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.53 $ $Date: 2009/12/16 14:58:40 $ * @since 1.1 * * @author M. Ranganathan
    * * */ public abstract class SIPMessage extends MessageObject implements javax.sip.message.Message, MessageExt { // JvB: use static here? private String contentEncodingCharset = MessageFactoryImpl.getDefaultContentEncodingCharset(); /* * True if this is a null request. */ protected boolean nullRequest; /** * unparsed headers */ protected LinkedList unrecognizedHeaders; /** * List of parsed headers (in the order they were added) */ protected ConcurrentLinkedQueue headers; /** * Direct accessors for frequently accessed headers */ protected From fromHeader; protected To toHeader; protected CSeq cSeqHeader; protected CallID callIdHeader; protected ContentLength contentLengthHeader; protected MaxForwards maxForwardsHeader; // Cumulative size of all the headers. protected int size; // Payload private String messageContent; private byte[] messageContentBytes; private Object messageContentObject; // Table of headers indexed by name. private Hashtable nameTable; /** * The application data pointer. This is un-interpreted by the stack. This is provided as a * convenient way of keeping book-keeping data for applications. */ protected Object applicationData; /** * Return true if the header belongs only in a Request. * * @param sipHeader is the header to test. */ public static boolean isRequestHeader(SIPHeader sipHeader) { return sipHeader instanceof AlertInfo || sipHeader instanceof InReplyTo || sipHeader instanceof Authorization || sipHeader instanceof MaxForwards || sipHeader instanceof UserAgent || sipHeader instanceof Priority || sipHeader instanceof ProxyAuthorization || sipHeader instanceof ProxyRequire || sipHeader instanceof ProxyRequireList || sipHeader instanceof Route || sipHeader instanceof RouteList || sipHeader instanceof Subject || sipHeader instanceof SIPIfMatch; } /** * Return true if the header belongs only in a response. * * @param sipHeader is the header to test. */ public static boolean isResponseHeader(SIPHeader sipHeader) { return sipHeader instanceof ErrorInfo || sipHeader instanceof ProxyAuthenticate || sipHeader instanceof Server || sipHeader instanceof Unsupported || sipHeader instanceof RetryAfter || sipHeader instanceof Warning || sipHeader instanceof WWWAuthenticate || sipHeader instanceof SIPETag || sipHeader instanceof RSeq; } /** * 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. */ public LinkedList getMessageAsEncodedStrings() { LinkedList retval = new LinkedList(); Iterator li = headers.iterator(); while (li.hasNext()) { SIPHeader sipHeader = (SIPHeader) li.next(); if (sipHeader instanceof SIPHeaderList) { SIPHeaderList< ? > shl = (SIPHeaderList< ? >) sipHeader; retval.addAll(shl.getHeadersAsEncodedStrings()); } else { retval.add(sipHeader.encode()); } } return retval; } /** * Encode only the message and exclude the contents (for debugging); * * @return a string with all the headers encoded. */ protected String encodeSIPHeaders() { StringBuffer encoding = new StringBuffer(); Iterator it = this.headers.iterator(); while (it.hasNext()) { SIPHeader siphdr = (SIPHeader) it.next(); if (!(siphdr instanceof ContentLength)) siphdr.encode(encoding); } return contentLengthHeader.encode(encoding).append(NEWLINE).toString(); } /** * Encode all the headers except the contents. For debug logging. */ 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 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. */ public boolean match(Object other) { if (other == null) return true; if (!other.getClass().equals(this.getClass())) return false; SIPMessage matchObj = (SIPMessage) other; Iterator li = matchObj.getHeaders(); while (li.hasNext()) { SIPHeader hisHeaders = (SIPHeader) li.next(); List myHeaders = this.getHeaderList(hisHeaders.getHeaderName()); // Could not find a header to match his header. if (myHeaders == null || myHeaders.size() == 0) return false; if (hisHeaders instanceof SIPHeaderList) { ListIterator< ? > outerIterator = ((SIPHeaderList< ? >) hisHeaders) .listIterator(); while (outerIterator.hasNext()) { SIPHeader hisHeader = (SIPHeader) outerIterator.next(); if (hisHeader instanceof ContentLength) continue; ListIterator< ? > innerIterator = myHeaders.listIterator(); boolean found = false; while (innerIterator.hasNext()) { SIPHeader myHeader = (SIPHeader) innerIterator.next(); if (myHeader.match(hisHeader)) { found = true; break; } } if (!found) return false; } } else { SIPHeader hisHeader = hisHeaders; ListIterator innerIterator = myHeaders.listIterator(); boolean found = false; while (innerIterator.hasNext()) { SIPHeader myHeader = (SIPHeader) innerIterator.next(); if (myHeader.match(hisHeader)) { found = true; break; } } if (!found) return false; } } return true; } /** * Merge a request with a template * * @param template -- template to merge with. * */ public void merge(Object template) { if (!template.getClass().equals(this.getClass())) throw new IllegalArgumentException("Bad class " + template.getClass()); SIPMessage templateMessage = (SIPMessage) template; Object[] templateHeaders = templateMessage.headers.toArray(); for (int i = 0; i < templateHeaders.length; i++) { SIPHeader hdr = (SIPHeader) templateHeaders[i]; String hdrName = hdr.getHeaderName(); List myHdrs = this.getHeaderList(hdrName); if (myHdrs == null) { this.attachHeader(hdr); } else { ListIterator it = myHdrs.listIterator(); while (it.hasNext()) { SIPHeader sipHdr = (SIPHeader) it.next(); sipHdr.merge(hdr); } } } } /** * 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() { StringBuffer encoding = new StringBuffer(); Iterator it = this.headers.iterator(); while (it.hasNext()) { SIPHeader siphdr = (SIPHeader) it.next(); if (!(siphdr instanceof ContentLength)) encoding.append(siphdr.encode()); } // Append the unrecognized headers. Headers that are not // recognized are passed through unchanged. for (String unrecognized : this.unrecognizedHeaders) { encoding.append(unrecognized).append(NEWLINE); } encoding.append(contentLengthHeader.encode()).append(NEWLINE); if (this.messageContentObject != null) { String mbody = this.getContent().toString(); encoding.append(mbody); } else if (this.messageContent != null || this.messageContentBytes != null) { String content = null; try { if (messageContent != null) content = messageContent; else { // JvB: Check for 'charset' parameter which overrides the default UTF-8 content = new String(messageContentBytes, getCharset() ); } } catch (UnsupportedEncodingException ex) { InternalErrorHandler.handleException(ex); } encoding.append(content); } return encoding.toString(); } /** * 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). */ public byte[] encodeAsBytes(String transport) { if (this instanceof SIPRequest && ((SIPRequest) this).isNullRequest()) { return "\r\n\r\n".getBytes(); } // JvB: added to fix case where application provides the wrong transport // in the topmost Via header ViaHeader topVia = (ViaHeader) this.getHeader(ViaHeader.NAME); try { topVia.setTransport(transport); } catch (ParseException e) { InternalErrorHandler.handleException(e); } StringBuffer encoding = new StringBuffer(); synchronized (this.headers) { Iterator it = this.headers.iterator(); while (it.hasNext()) { SIPHeader siphdr = (SIPHeader) it.next(); if (!(siphdr instanceof ContentLength)) siphdr.encode(encoding); } } contentLengthHeader.encode(encoding); encoding.append(NEWLINE); byte[] retval = null; byte[] content = this.getRawContent(); if (content != null) { // Append the content byte[] msgarray = null; try { msgarray = encoding.toString().getBytes( getCharset() ); } catch (UnsupportedEncodingException ex) { InternalErrorHandler.handleException(ex); } retval = new byte[msgarray.length + content.length]; System.arraycopy(msgarray, 0, retval, 0, msgarray.length); System.arraycopy(content, 0, retval, msgarray.length, content.length); } else { // Message content does not exist. try { retval = encoding.toString().getBytes( getCharset() ); } catch (UnsupportedEncodingException ex) { InternalErrorHandler.handleException(ex); } } return retval; } /** * clone this message (create a new deep physical copy). All headers in the message are * cloned. You can modify the cloned copy without affecting the original. The content is * handled as follows: If the content is a String, or a byte array, a new copy of the content * 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.nameTable = new Hashtable(); retval.fromHeader = null; retval.toHeader = null; retval.cSeqHeader = null; retval.callIdHeader = null; retval.contentLengthHeader = null; retval.maxForwardsHeader = null; if (this.headers != null) { retval.headers = new ConcurrentLinkedQueue(); for (Iterator iter = headers.iterator(); iter.hasNext();) { SIPHeader hdr = (SIPHeader) iter.next(); retval.attachHeader((SIPHeader) hdr.clone()); } } if (this.messageContentBytes != null) retval.messageContentBytes = (byte[]) this.messageContentBytes.clone(); if (this.messageContentObject != null) retval.messageContentObject = makeClone(messageContentObject); retval.unrecognizedHeaders = this.unrecognizedHeaders; 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. */ public String debugDump() { stringRepresentation = ""; sprint("SIPMessage:"); sprint("{"); try { Field[] fields = this.getClass().getDeclaredFields(); for (int i = 0; i < fields.length; i++) { Field f = fields[i]; Class< ? > fieldType = f.getType(); String fieldName = f.getName(); if (f.get(this) != null && SIPHeader.class.isAssignableFrom(fieldType) && fieldName.compareTo("headers") != 0) { sprint(fieldName + "="); sprint(((SIPHeader) f.get(this)).debugDump()); } } } catch (Exception ex) { InternalErrorHandler.handleException(ex); } sprint("List of headers : "); sprint(headers.toString()); sprint("messageContent = "); sprint("{"); sprint(messageContent); sprint("}"); if (this.getContent() != null) { sprint(this.getContent().toString()); } sprint("}"); return stringRepresentation; } /** * Constructor: Initializes lists and list headers. All the headers for which there can be * multiple occurances in a message are derived from the SIPHeaderListClass. All singleton * headers are derived from SIPHeader class. */ public SIPMessage() { this.unrecognizedHeaders = new LinkedList(); this.headers = new ConcurrentLinkedQueue(); nameTable = new Hashtable(); try { this.attachHeader(new ContentLength(0), false); } catch (Exception ex) { } } /** * Attach a header and die if you get a duplicate header exception. * * @param h SIPHeader to attach. */ private void attachHeader(SIPHeader h) { if (h == null) throw new IllegalArgumentException("null header!"); try { if (h instanceof SIPHeaderList) { SIPHeaderList< ? > hl = (SIPHeaderList< ? >) h; if (hl.isEmpty()) { return; } } attachHeader(h, false, false); } catch (SIPDuplicateHeaderException ex) { // InternalErrorHandler.handleException(ex); } } /** * Attach a header (replacing the original header). * * @param sipHeader SIPHeader that replaces a header of the same type. */ public void setHeader(Header sipHeader) { SIPHeader header = (SIPHeader) sipHeader; if (header == null) throw new IllegalArgumentException("null header!"); try { if (header instanceof SIPHeaderList) { SIPHeaderList< ? > hl = (SIPHeaderList< ? >) header; // Ignore empty lists. if (hl.isEmpty()) return; } this.removeHeader(header.getHeaderName()); attachHeader(header, true, false); } catch (SIPDuplicateHeaderException ex) { InternalErrorHandler.handleException(ex); } } /** * Set a header from a linked list of headers. * * @param headers -- a list of headers to set. */ public void setHeaders(java.util.List headers) { ListIterator listIterator = headers.listIterator(); while (listIterator.hasNext()) { SIPHeader sipHeader = (SIPHeader) listIterator.next(); try { this.attachHeader(sipHeader, false); } catch (SIPDuplicateHeaderException ex) { } } } /** * 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 * allowed (fpr example CSeq). */ public void attachHeader(SIPHeader h, boolean replaceflag) throws SIPDuplicateHeaderException { this.attachHeader(h, replaceflag, false); } /** * 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. * @exception SIPDuplicateHeaderException if the header is of a type that cannot tolerate * duplicates and one of this type already exists (e.g. CSeq header). * @throws IndexOutOfBoundsException If the index specified is greater than the number of * headers that are in this message. */ public void attachHeader(SIPHeader header, boolean replaceFlag, boolean top) throws SIPDuplicateHeaderException { if (header == null) { throw new NullPointerException("null header"); } SIPHeader h; if (ListMap.hasList(header) && !SIPHeaderList.class.isAssignableFrom(header.getClass())) { SIPHeaderList hdrList = ListMap.getList(header); hdrList.add(header); h = hdrList; } else { h = header; } String headerNameLowerCase = SIPHeaderNamesCache.toLowerCase(h.getName()); if (replaceFlag) { nameTable.remove(headerNameLowerCase); } else if (nameTable.containsKey(headerNameLowerCase) && !(h instanceof SIPHeaderList)) { if (h instanceof ContentLength) { try { ContentLength cl = (ContentLength) h; contentLengthHeader.setContentLength(cl.getContentLength()); } catch (InvalidArgumentException e) { } } // Just ignore duplicate header. return; } SIPHeader originalHeader = (SIPHeader) getHeader(header.getName()); // Delete the original header from our list structure. if (originalHeader != null) { Iterator li = headers.iterator(); while (li.hasNext()) { SIPHeader next = (SIPHeader) li.next(); if (next.equals(originalHeader)) { li.remove(); } } } if (!nameTable.containsKey(headerNameLowerCase)) { nameTable.put(headerNameLowerCase, h); headers.add(h); } else { if (h instanceof SIPHeaderList) { SIPHeaderList< ? > hdrlist = (SIPHeaderList< ? >) nameTable .get(headerNameLowerCase); if (hdrlist != null) hdrlist.concatenate((SIPHeaderList) h, top); else nameTable.put(headerNameLowerCase, h); } else { nameTable.put(headerNameLowerCase, h); } } // Direct accessor fields for frequently accessed headers. if (h instanceof From) { this.fromHeader = (From) h; } else if (h instanceof ContentLength) { this.contentLengthHeader = (ContentLength) h; } else if (h instanceof To) { this.toHeader = (To) h; } else if (h instanceof CSeq) { this.cSeqHeader = (CSeq) h; } else if (h instanceof CallID) { this.callIdHeader = (CallID) h; } else if (h instanceof MaxForwards) { this.maxForwardsHeader = (MaxForwards) h; } } /** * 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) nameTable.get(headerNameLowerCase); // nothing to do then we are done. if (toRemove == null) return; if (toRemove instanceof SIPHeaderList) { SIPHeaderList< ? > hdrList = (SIPHeaderList< ? >) toRemove; if (top) hdrList.removeFirst(); else hdrList.removeLast(); // Clean up empty list if (hdrList.isEmpty()) { Iterator li = this.headers.iterator(); while (li.hasNext()) { SIPHeader sipHeader = (SIPHeader) li.next(); if (sipHeader.getName().equalsIgnoreCase(headerNameLowerCase)) li.remove(); } // JvB: also remove it from the nameTable! Else NPE in // DefaultRouter nameTable.remove(headerNameLowerCase); } } else { this.nameTable.remove(headerNameLowerCase); if (toRemove instanceof From) { this.fromHeader = null; } else if (toRemove instanceof To) { this.toHeader = null; } else if (toRemove instanceof CSeq) { this.cSeqHeader = null; } else if (toRemove instanceof CallID) { this.callIdHeader = null; } else if (toRemove instanceof MaxForwards) { this.maxForwardsHeader = null; } else if (toRemove instanceof ContentLength) { this.contentLengthHeader = null; } Iterator li = this.headers.iterator(); while (li.hasNext()) { SIPHeader sipHeader = (SIPHeader) li.next(); if (sipHeader.getName().equalsIgnoreCase(headerName)) li.remove(); } } } /** * Remove all headers given its name. * * @param headerName is the name of the header to remove. */ public void removeHeader(String headerName) { if (headerName == null) throw new NullPointerException("null arg"); String headerNameLowerCase = SIPHeaderNamesCache.toLowerCase(headerName); SIPHeader removed = (SIPHeader) nameTable.remove(headerNameLowerCase); // nothing to do then we are done. if (removed == null) return; // Remove the fast accessor fields. if (removed instanceof From) { this.fromHeader = null; } else if (removed instanceof To) { this.toHeader = null; } else if (removed instanceof CSeq) { this.cSeqHeader = null; } else if (removed instanceof CallID) { this.callIdHeader = null; } else if (removed instanceof MaxForwards) { this.maxForwardsHeader = null; } else if (removed instanceof ContentLength) { this.contentLengthHeader = null; } Iterator li = this.headers.iterator(); while (li.hasNext()) { SIPHeader sipHeader = (SIPHeader) li.next(); if (sipHeader.getName().equalsIgnoreCase(headerNameLowerCase)) li.remove(); } } /** * 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 * possible addition of a tag in the To field (section 10.43)). This allows responses * to be matched with requests. Incorporates a bug fix for a bug sent in by Gordon * 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 = 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. if (topVia != null && topVia.getBranch() != null && topVia.getBranch().toUpperCase().startsWith( SIPConstants.BRANCH_MAGIC_COOKIE_UPPER_CASE)) { // Bis 09 compatible branch assignment algorithm. // implies that the branch id can be used as a transaction // identifier. if (this.getCSeq().getMethod().equals(Request.CANCEL)) return (topVia.getBranch() + ":" + this.getCSeq().getMethod()).toLowerCase(); else return topVia.getBranch().toLowerCase(); } else { // Old style client so construct the transaction identifier // from various fields of the request. StringBuffer retval = new StringBuffer(); From from = (From) this.getFrom(); To to = (To) this.getTo(); // String hpFrom = from.getUserAtHostPort(); // retval.append(hpFrom).append(":"); if (from.hasTag()) retval.append(from.getTag()).append("-"); // String hpTo = to.getUserAtHostPort(); // retval.append(hpTo).append(":"); String cid = this.callIdHeader.getCallId(); retval.append(cid).append("-"); retval.append(this.cSeqHeader.getSequenceNumber()).append("-").append( this.cSeqHeader.getMethod()); if (topVia != null) { retval.append("-").append(topVia.getSentBy().encode()); if (!topVia.getSentBy().hasPort()) { retval.append("-").append(5060); } } if (this.getCSeq().getMethod().equals(Request.CANCEL)) { retval.append(Request.CANCEL); } return retval.toString().toLowerCase().replace(":", "-").replace("@", "-") + Utils.getSignature(); } } /** * Override the hashcode method ( see issue # 55 ) Note that if you try to use this method * before you assemble a valid request, you will get a constant ( -1 ). Beware of placing any * half formed requests in a table. */ public int hashCode() { if (this.callIdHeader == null) throw new RuntimeException( "Invalid message! Cannot compute hashcode! call-id header is missing !"); else return this.callIdHeader.getCallId().hashCode(); } /** * Return true if this message has a body. */ public boolean hasContent() { return messageContent != null || messageContentBytes != null; } /** * Return an iterator for the list of headers in this message. * * @return an Iterator for the headers of this message. */ public Iterator getHeaders() { return headers.iterator(); } /** * 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)); } private Header getHeaderLowerCase(String lowerCaseHeaderName) { if (lowerCaseHeaderName == null) throw new NullPointerException("bad name"); SIPHeader sipHeader = (SIPHeader) nameTable.get(lowerCaseHeaderName); if (sipHeader instanceof SIPHeaderList) return (Header) ((SIPHeaderList) sipHeader).getFirst(); else return (Header) sipHeader; } /** * 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. */ public ContentLengthHeader getContentLengthHeader() { return this.getContentLength(); } /** * Get the from header. * * @return -- the from header. */ public FromHeader getFrom() { return (FromHeader) fromHeader; } /** * Get the ErrorInfo list of headers (null if one does not exist). * * @return List containing ErrorInfo headers. */ public ErrorInfoList getErrorInfoHeaders() { return (ErrorInfoList) getSIPHeaderListLowerCase(ERROR_LOWERCASE); } private static final String ERROR_LOWERCASE = SIPHeaderNamesCache.toLowerCase(ErrorInfo.NAME); /** * Get the Contact list of headers (null if one does not exist). * * @return List containing Contact headers. */ public ContactList getContactHeaders() { return (ContactList) this.getSIPHeaderListLowerCase(CONTACT_LOWERCASE); } private static final String CONTACT_LOWERCASE = SIPHeaderNamesCache .toLowerCase(ContactHeader.NAME); /** * Get the contact header ( the first contact header) which is all we need for the most part. * */ public Contact getContactHeader() { ContactList clist = this.getContactHeaders(); if (clist != null) { return (Contact) clist.getFirst(); } else { return null; } } /** * Get the Via list of headers (null if one does not exist). * * @return List containing Via headers. */ public ViaList getViaHeaders() { return (ViaList) getSIPHeaderListLowerCase(VIA_LOWERCASE); } private static final String VIA_LOWERCASE = SIPHeaderNamesCache.toLowerCase(ViaHeader.NAME); /** * Set A list of via headers. * * @param viaList a list of via headers to add. */ public void setVia(java.util.List viaList) { ViaList vList = new ViaList(); ListIterator it = viaList.listIterator(); while (it.hasNext()) { Via via = (Via) it.next(); vList.add(via); } this.setHeader(vList); } /** * Set the header given a list of headers. * * @param sipHeaderList a headerList to set */ public void setHeader(SIPHeaderList sipHeaderList) { this.setHeader((Header) sipHeaderList); } /** * Get the topmost via header. * * @return the top most via header if one exists or null if none exists. */ public Via getTopmostVia() { if (this.getViaHeaders() == null) return null; else return (Via) (getViaHeaders().getFirst()); } /** * Get the CSeq list of header (null if one does not exist). * * @return CSeq header */ public CSeqHeader getCSeq() { return (CSeqHeader) cSeqHeader; } /** * Get the Authorization header (null if one does not exist). * * @return Authorization header. */ public Authorization getAuthorization() { return (Authorization) getHeaderLowerCase(AUTHORIZATION_LOWERCASE); } private static final String AUTHORIZATION_LOWERCASE = SIPHeaderNamesCache .toLowerCase(AuthorizationHeader.NAME); /** * Get the MaxForwards header (null if one does not exist). * * @return Max-Forwards header */ public MaxForwardsHeader getMaxForwards() { return maxForwardsHeader; } /** * Set the max forwards header. * * @param maxForwards is the MaxForwardsHeader to set. */ public void setMaxForwards(MaxForwardsHeader maxForwards) { this.setHeader(maxForwards); } /** * Get the Route List of headers (null if one does not exist). * * @return List containing Route headers */ public RouteList getRouteHeaders() { return (RouteList) getSIPHeaderListLowerCase(ROUTE_LOWERCASE); } private static final String ROUTE_LOWERCASE = SIPHeaderNamesCache .toLowerCase(RouteHeader.NAME); /** * Get the CallID header (null if one does not exist) * * @return Call-ID header . */ public CallIdHeader getCallId() { return callIdHeader; } /** * Set the call id header. * * @param callId call idHeader (what else could it be?) */ public void setCallId(CallIdHeader callId) { this.setHeader(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 { if (callIdHeader == null) { this.setHeader(new CallID()); } callIdHeader.setCallId(callId); } /** * Get the RecordRoute header list (null if one does not exist). * * @return Record-Route header */ public RecordRouteList getRecordRouteHeaders() { return (RecordRouteList) this.getSIPHeaderListLowerCase(RECORDROUTE_LOWERCASE); } private static final String RECORDROUTE_LOWERCASE = SIPHeaderNamesCache .toLowerCase(RecordRouteHeader.NAME); /** * Get the To header (null if one does not exist). * * @return To header */ public ToHeader getTo() { return (ToHeader) toHeader; } public void setTo(ToHeader to) { this.setHeader(to); } public void setFrom(FromHeader from) { this.setHeader(from); } /** * Get the ContentLength header (null if one does not exist). * * @return content-length header. */ public ContentLengthHeader getContentLength() { return this.contentLengthHeader; } /** * 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) return null; else if (this.messageContent == null) { this.messageContent = new String(messageContentBytes, getCharset() ); } return this.messageContent; } /** * 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() { try { if ( this.messageContentBytes != null ) { // return messageContentBytes; } else if (this.messageContentObject != null) { String messageContent = this.messageContentObject.toString(); this.messageContentBytes = messageContent.getBytes( getCharset() ); } else if (this.messageContent != null) { this.messageContentBytes = messageContent.getBytes( getCharset() ); } return this.messageContentBytes; } catch (UnsupportedEncodingException ex) { InternalErrorHandler.handleException(ex); return null; } } /** * 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. */ public void setMessageContent(String type, String subType, String messageContent) { if (messageContent == null) throw new IllegalArgumentException("messgeContent is null"); ContentType ct = new ContentType(type, subType); this.setHeader(ct); this.messageContent = messageContent; this.messageContentBytes = null; this.messageContentObject = null; // Could be double byte so we need to compute length // after converting to byte[] computeContentLength(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. */ public void setContent(Object content, ContentTypeHeader contentTypeHeader) throws ParseException { if (content == null) throw new NullPointerException("null content"); this.setHeader(contentTypeHeader); this.messageContent = null; this.messageContentBytes = null; this.messageContentObject = null; if (content instanceof String) { this.messageContent = (String) content; } else if (content instanceof byte[]) { this.messageContentBytes = (byte[]) content; } else this.messageContentObject = content; computeContentLength(content); } /** * Get the content (body) of the message. * * @return the content of the sip message. */ public Object getContent() { if (this.messageContentObject != null) return messageContentObject; else if (this.messageContent != null) return this.messageContent; else if (this.messageContentBytes != null) return this.messageContentBytes; else return 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. */ public void setMessageContent(String type, String subType, byte[] messageContent) { ContentType ct = new ContentType(type, subType); this.setHeader(ct); this.setMessageContent(messageContent); computeContentLength(messageContent); } /** * Set the message content for this message. * * @param content Message body as a string. */ 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) || this.contentLengthHeader.getContentLength() < givenLength) { throw new ParseException("Invalid content length " + this.contentLengthHeader.getContentLength() + " / " + givenLength, 0); } } 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) { computeContentLength(content); messageContentBytes = content; messageContent = null; messageContentObject = null; } /** * Method to set the content - called by the parser * * @param content * @throws ParseException */ public void setMessageContent(byte[] content, boolean computeContentLength, int givenLength) throws ParseException { computeContentLength(content); if ((!computeContentLength) && this.contentLengthHeader.getContentLength() < givenLength) { // System.out.println("!!!!!!!!!!! MISMATCH !!!!!!!!!!!"); throw new ParseException("Invalid content length " + this.contentLengthHeader.getContentLength() + " / " + givenLength, 0); } messageContentBytes = content; messageContent = null; messageContentObject = null; } /** * 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) { int length = 0; if (content != null) { if (content instanceof String) { try { length = ((String) content).getBytes( getCharset() ).length; } catch (UnsupportedEncodingException ex) { InternalErrorHandler.handleException(ex); } } else if (content instanceof byte[]) { length = ((byte[]) content).length; } else { length = content.toString().length(); } } try { contentLengthHeader.setContentLength(length); } catch (InvalidArgumentException e) { // Cannot happen. } } /** * Remove the message content if it exists. */ public void removeContent() { messageContent = null; messageContentBytes = null; messageContentObject = null; try { this.contentLengthHeader.setContentLength(0); } catch (InvalidArgumentException ex) { } } /** * 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. */ @SuppressWarnings("unchecked") public ListIterator getHeaders(String headerName) { if (headerName == null) throw new NullPointerException("null headerName"); SIPHeader sipHeader = (SIPHeader) nameTable.get(SIPHeaderNamesCache .toLowerCase(headerName)); // empty iterator if (sipHeader == null) return new LinkedList().listIterator(); if (sipHeader instanceof SIPHeaderList) { return ((SIPHeaderList) sipHeader).listIterator(); } else { return new HeaderIterator(this, sipHeader); } } /** * 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 = name.toLowerCase(); if (this.nameTable.containsKey(lowerCaseName)) { return this.nameTable.get(lowerCaseName).toString(); } else { return this.getHeader(name).toString(); } } private 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) nameTable.get(SIPHeaderNamesCache .toLowerCase(headerName)); if (sipHeader == null) return null; else if (sipHeader instanceof SIPHeaderList) return (List) (((SIPHeaderList< ? >) sipHeader).getHeaderList()); else { LinkedList ll = new LinkedList(); ll.add(sipHeader); return ll; } } /** * 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 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() { return fromHeader != null && fromHeader.getTag() != null; } /** * 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() { return toHeader != null && toHeader.getTag() != null; } /** * Return the from tag. * * @return the tag from the from header. * */ public String getFromTag() { return fromHeader == null ? null : fromHeader.getTag(); } /** * Set the From Tag. * * @param tag -- tag to set in the from header. */ public void setFromTag(String tag) { try { fromHeader.setTag(tag); } catch (ParseException e) { } } /** * Set the to tag. * * @param tag -- tag to set. */ public void setToTag(String tag) { try { toHeader.setTag(tag); } catch (ParseException e) { } } /** * Return the to tag. */ public String getToTag() { return toHeader == null ? null : toHeader.getTag(); } /** * Return the encoded first line. */ public abstract String getFirstLine(); /** * Add a SIP header. * * @param sipHeader -- sip header to add. */ public void addHeader(Header sipHeader) { // Content length is never stored. Just computed. SIPHeader sh = (SIPHeader) sipHeader; try { if ((sipHeader instanceof ViaHeader) || (sipHeader instanceof RecordRouteHeader)) { attachHeader(sh, false, true); } else { attachHeader(sh, false, false); } } catch (SIPDuplicateHeaderException ex) { try { if (sipHeader instanceof ContentLength) { ContentLength cl = (ContentLength) sipHeader; contentLengthHeader.setContentLength(cl.getContentLength()); } } catch (InvalidArgumentException e) { } } } /** * Add a header to the unparsed list of headers. * * @param unparsed -- unparsed header to add to the list. */ public void addUnparsed(String unparsed) { this.unrecognizedHeaders.add(unparsed); } /** * Add a SIP header. * * @param sipHeader -- string version of SIP header to add. */ public void addHeader(String sipHeader) { String hdrString = sipHeader.trim() + "\n"; try { HeaderParser parser = ParserFactory.createParser(sipHeader); SIPHeader sh = parser.parse(); this.attachHeader(sh, false); } catch (ParseException ex) { this.unrecognizedHeaders.add(hdrString); } } /** * Get a list containing the unrecognized headers. * * @return a linked list containing unrecongnized headers. */ public ListIterator getUnrecognizedHeaders() { 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. */ public ListIterator getHeaderNames() { Iterator li = this.headers.iterator(); LinkedList retval = new LinkedList(); while (li.hasNext()) { SIPHeader sipHeader = (SIPHeader) li.next(); String name = sipHeader.getName(); retval.add(name); } return retval.listIterator(); } /** * Compare for equality. * * @param other -- the other object to compare with. */ public boolean equals(Object other) { if (!other.getClass().equals(this.getClass())) { return false; } SIPMessage otherMessage = (SIPMessage) other; Collection values = this.nameTable.values(); Iterator it = values.iterator(); if (nameTable.size() != otherMessage.nameTable.size()) { return false; } while (it.hasNext()) { SIPHeader mine = (SIPHeader) it.next(); SIPHeader his = (SIPHeader) (otherMessage.nameTable.get(SIPHeaderNamesCache .toLowerCase(mine.getName()))); if (his == null) { return false; } else if (!his.equals(mine)) { return false; } } return true; } /** * get content disposition header or null if no such header exists. * * @return the contentDisposition header */ public javax.sip.header.ContentDispositionHeader getContentDisposition() { return (ContentDispositionHeader) getHeaderLowerCase(CONTENT_DISPOSITION_LOWERCASE); } private static final String CONTENT_DISPOSITION_LOWERCASE = SIPHeaderNamesCache .toLowerCase(ContentDispositionHeader.NAME); /** * get the content encoding header. * * @return the contentEncoding header. */ public javax.sip.header.ContentEncodingHeader getContentEncoding() { return (ContentEncodingHeader) getHeaderLowerCase(CONTENT_ENCODING_LOWERCASE); } private static final String CONTENT_ENCODING_LOWERCASE = SIPHeaderNamesCache .toLowerCase(ContentEncodingHeader.NAME); /** * Get the contentLanguage header. * * @return the content language header. */ public javax.sip.header.ContentLanguageHeader getContentLanguage() { return (ContentLanguageHeader) getHeaderLowerCase(CONTENT_LANGUAGE_LOWERCASE); } private static final String CONTENT_LANGUAGE_LOWERCASE = SIPHeaderNamesCache .toLowerCase(ContentLanguageHeader.NAME); /** * Get the exipres header. * * @return the expires header or null if one does not exist. */ public javax.sip.header.ExpiresHeader getExpires() { return (ExpiresHeader) getHeaderLowerCase(EXPIRES_LOWERCASE); } private static final String EXPIRES_LOWERCASE = SIPHeaderNamesCache .toLowerCase(ExpiresHeader.NAME); /** * Set the expiresHeader * * @param expiresHeader -- the expires header to set. */ public void setExpires(ExpiresHeader expiresHeader) { this.setHeader(expiresHeader); } /** * Set the content disposition header. * * @param contentDispositionHeader -- content disposition header. */ public void setContentDisposition(ContentDispositionHeader contentDispositionHeader) { this.setHeader(contentDispositionHeader); } public void setContentEncoding(ContentEncodingHeader contentEncodingHeader) { this.setHeader(contentEncodingHeader); } public void setContentLanguage(ContentLanguageHeader contentLanguageHeader) { this.setHeader(contentLanguageHeader); } /** * Set the content length header. * * @param contentLength -- content length header. */ public void setContentLength(ContentLengthHeader contentLength) { try { this.contentLengthHeader.setContentLength(contentLength.getContentLength()); } catch (InvalidArgumentException ex) { } } /** * 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) { this.size = size; } public int getSize() { return this.size; } /* * (non-Javadoc) * * @see javax.sip.message.Message#addLast(javax.sip.header.Header) */ public void addLast(Header header) throws SipException, NullPointerException { if (header == null) throw new NullPointerException("null arg!"); try { this.attachHeader((SIPHeader) header, false, false); } catch (SIPDuplicateHeaderException ex) { throw new SipException("Cannot add header - header already exists"); } } /* * (non-Javadoc) * * @see javax.sip.message.Message#addFirst(javax.sip.header.Header) */ public void addFirst(Header header) throws SipException, NullPointerException { if (header == null) throw new NullPointerException("null arg!"); try { this.attachHeader((SIPHeader) header, false, true); } catch (SIPDuplicateHeaderException ex) { throw new SipException("Cannot add header - header already exists"); } } /* * (non-Javadoc) * * @see javax.sip.message.Message#removeFirst(java.lang.String) */ public void removeFirst(String headerName) throws NullPointerException { if (headerName == null) throw new NullPointerException("Null argument Provided!"); this.removeHeader(headerName, true); } /* * (non-Javadoc) * * @see javax.sip.message.Message#removeLast(java.lang.String) */ public void removeLast(String headerName) { if (headerName == null) throw new NullPointerException("Null argument Provided!"); this.removeHeader(headerName, false); } /** * Set the CSeq header. * * @param cseqHeader -- CSeq Header. */ public void setCSeq(CSeqHeader cseqHeader) { this.setHeader(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. */ public void setApplicationData(Object applicationData) { this.applicationData = applicationData; } /** * Get the application data associated with this message. * * @return stored application data. */ public Object getApplicationData() { return this.applicationData; } /** * Get the multipart MIME content * */ public MultipartMimeContent getMultipartMimeContent() throws ParseException { if (this.contentLengthHeader.getContentLength() == 0) { return null; } 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; } } 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; } /** * 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; } public abstract void setSIPVersion(String sipVersion) throws ParseException; public abstract String getSIPVersion(); public abstract String toString(); } java/gov/nist/javax/sip/message/SIPRequest.java0100644 0000000 0000000 00000131160 13513104763 020502 0ustar000000000 0000000 /* * 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.javax.sip.message; import gov.nist.javax.sip.address.*; import gov.nist.core.*; import java.util.HashSet; import java.util.Hashtable; import java.util.LinkedList; import java.util.Set; import java.io.UnsupportedEncodingException; import java.util.Iterator; import javax.sip.address.URI; 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 * that create responses and generate cancel requests from incoming orignial requests without the * additional overhead of encoding and decoding messages. Bruno Konik noticed an extraneous * newline added to the end of the buffer when encoding it. Incorporates a bug report from Andreas * Bystrom. Szabo Barna noticed a contact in a cancel request - this is a pointless header for * cancel. Antonis Kyardis contributed bug fixes. Jeroen van Bemmel noted that method names are * case sensitive, should use equals() in getting CannonicalName * */ /** * The SIP Request structure. * * @version 1.2 $Revision: 1.52 $ $Date: 2009/12/16 14:58:40 $ * @since 1.1 * * @author M. Ranganathan
    * * * */ public final class SIPRequest extends SIPMessage implements javax.sip.message.Request, RequestExt { private static final long serialVersionUID = 3360720013577322927L; private static final String DEFAULT_USER = "ip"; private static final String DEFAULT_TRANSPORT = "udp"; private transient Object transactionPointer; private RequestLine requestLine; private transient Object messageChannel; private transient Object inviteTransaction; // The original invite request for a // given cancel request /** * Set of target refresh methods, currently: INVITE, UPDATE, SUBSCRIBE, NOTIFY, REFER * * A target refresh request and its response MUST have a Contact */ private static final Set targetRefreshMethods = new HashSet(); /* * 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. */ private static final Hashtable nameTable = new Hashtable(); private static void putName(String name) { nameTable.put(name, name); } static { targetRefreshMethods.add(Request.INVITE); targetRefreshMethods.add(Request.UPDATE); targetRefreshMethods.add(Request.SUBSCRIBE); targetRefreshMethods.add(Request.NOTIFY); targetRefreshMethods.add(Request.REFER); putName(Request.INVITE); putName(Request.BYE); putName(Request.CANCEL); putName(Request.ACK); putName(Request.PRACK); putName(Request.INFO); putName(Request.MESSAGE); putName(Request.NOTIFY); putName(Request.OPTIONS); putName(Request.PRACK); putName(Request.PUBLISH); putName(Request.REFER); putName(Request.REGISTER); putName(Request.SUBSCRIBE); putName(Request.UPDATE); } /** * @return true iff the method is a target refresh */ public static boolean isTargetRefresh(String ucaseMethod) { return targetRefreshMethods.contains(ucaseMethod); } /** * @return true iff the method is a dialog creating method */ public static boolean isDialogCreating(String ucaseMethod) { return SIPTransactionStack.isDialogCreated(ucaseMethod); } /** * Set to standard constants to speed up processing. this makes equals comparisons run much * faster in the stack because then it is just identity comparision. Character by char * comparison is not required. The method returns the String CONSTANT corresponding to the * String name. * */ public static String getCannonicalName(String method) { if (nameTable.containsKey(method)) return (String) nameTable.get(method); else return method; } /** * Get the Request Line of the SIPRequest. * * @return the request line of the SIP Request. */ public RequestLine getRequestLine() { return requestLine; } /** * Set the request line of the SIP Request. * * @param requestLine is the request line to set in the SIP Request. */ public void setRequestLine(RequestLine requestLine) { this.requestLine = requestLine; } /** * Constructor. */ public SIPRequest() { super(); } /** * Convert to a formatted string for pretty printing. Note that the encode method converts * this into a sip message that is suitable for transmission. Note hack here if you want to * convert the nice curly brackets into some grotesque XML tag. * * @return a string which can be used to examine the message contents. * */ public String debugDump() { String superstring = super.debugDump(); stringRepresentation = ""; sprint(SIPRequest.class.getName()); sprint("{"); if (requestLine != null) sprint(requestLine.debugDump()); sprint(superstring); sprint("}"); return stringRepresentation; } /** * Check header for constraints. (1) Invite options and bye requests can only have SIP URIs in * the contact headers. (2) Request must have cseq, to and from and via headers. (3) Method in * request URI must match that in CSEQ. */ public void checkHeaders() throws ParseException { String prefix = "Missing a required header : "; /* Check for required headers */ if (getCSeq() == null) { throw new ParseException(prefix + CSeqHeader.NAME, 0); } if (getTo() == null) { throw new ParseException(prefix + ToHeader.NAME, 0); } if (this.callIdHeader == null || this.callIdHeader.getCallId() == null || callIdHeader.getCallId().equals("")) { throw new ParseException(prefix + CallIdHeader.NAME, 0); } if (getFrom() == null) { throw new ParseException(prefix + FromHeader.NAME, 0); } if (getViaHeaders() == null) { throw new ParseException(prefix + ViaHeader.NAME, 0); } // BEGIN android-deleted /* if (getMaxForwards() == null) { throw new ParseException(prefix + MaxForwardsHeader.NAME, 0); } */ // END android-deleted if (getTopmostVia() == null) throw new ParseException("No via header in request! ", 0); if (getMethod().equals(Request.NOTIFY)) { if (getHeader(SubscriptionStateHeader.NAME) == null) throw new ParseException(prefix + SubscriptionStateHeader.NAME, 0); if (getHeader(EventHeader.NAME) == null) throw new ParseException(prefix + EventHeader.NAME, 0); } else if (getMethod().equals(Request.PUBLISH)) { /* * For determining the type of the published event state, the EPA MUST include a * single Event header field in PUBLISH requests. The value of this header field * indicates the event package for which this request is publishing event state. */ if (getHeader(EventHeader.NAME) == null) throw new ParseException(prefix + EventHeader.NAME, 0); } /* * RFC 3261 8.1.1.8 The Contact header field MUST be present and contain exactly one SIP * or SIPS URI in any request that can result in the establishment of a dialog. For the * methods defined in this specification, that includes only the INVITE request. For these * requests, the scope of the Contact is global. That is, the Contact header field value * contains the URI at which the UA would like to receive requests, and this URI MUST be * valid even if used in subsequent requests outside of any dialogs. * * If the Request-URI or top Route header field value contains a SIPS URI, the Contact * header field MUST contain a SIPS URI as well. */ if (requestLine.getMethod().equals(Request.INVITE) || requestLine.getMethod().equals(Request.SUBSCRIBE) || requestLine.getMethod().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 // contact header is mandatory. if (this.getToTag() == null) throw new ParseException(prefix + ContactHeader.NAME, 0); } if (requestLine.getUri() instanceof SipUri) { String scheme = ((SipUri) requestLine.getUri()).getScheme(); if ("sips".equalsIgnoreCase(scheme)) { SipUri sipUri = (SipUri) this.getContactHeader().getAddress().getURI(); if (!sipUri.getScheme().equals("sips")) { throw new ParseException("Scheme for contact should be sips:" + sipUri, 0); } } } } /* * Contact header is mandatory for a SIP INVITE request. */ 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 && requestLine.getMethod() != null && getCSeq().getMethod() != null && requestLine.getMethod().compareTo(getCSeq().getMethod()) != 0) { throw new ParseException("CSEQ method mismatch with Request-Line ", 0); } } /** * Set the default values in the request URI if necessary. */ protected void setDefaults() { // The request line may be unparseable (set to null by the // exception handler. if (requestLine == null) return; String method = requestLine.getMethod(); // The requestLine may be malformed! if (method == null) return; GenericURI u = requestLine.getUri(); if (u == null) return; if (method.compareTo(Request.REGISTER) == 0 || method.compareTo(Request.INVITE) == 0) { if (u instanceof SipUri) { SipUri sipUri = (SipUri) u; sipUri.setUserParam(DEFAULT_USER); try { sipUri.setTransportParam(DEFAULT_TRANSPORT); } catch (ParseException ex) { } } } } /** * Patch up the request line as necessary. */ protected void setRequestLineDefaults() { String method = requestLine.getMethod(); if (method == null) { CSeq cseq = (CSeq) this.getCSeq(); if (cseq != null) { method = getCannonicalName(cseq.getMethod()); requestLine.setMethod(method); } } } /** * A conveniance function to access the Request URI. * * @return the requestURI if it exists. */ public javax.sip.address.URI getRequestURI() { if (this.requestLine == null) return null; else return (javax.sip.address.URI) this.requestLine.getUri(); } /** * Sets the RequestURI of Request. The Request-URI is a SIP or SIPS URI or a general URI. It * indicates the user or service to which this request is being addressed. SIP elements MAY * support Request-URIs with schemes other than "sip" and "sips", for example the "tel" URI * scheme. SIP elements MAY translate non-SIP URIs using any mechanism at their disposal, * resulting in SIP URI, SIPS URI, or some other scheme. * * @param uri the new Request URI of this request message */ public void setRequestURI(URI uri) { if ( uri == null ) { throw new NullPointerException("Null request URI"); } if (this.requestLine == null) { this.requestLine = new RequestLine(); } this.requestLine.setUri((GenericURI) uri); this.nullRequest = false; } /** * Set the method. * * @param method is the method to set. * @throws IllegalArgumentException if the method is null */ public void setMethod(String method) { if (method == null) throw new IllegalArgumentException("null method"); if (this.requestLine == null) { this.requestLine = new RequestLine(); } // Set to standard constants to speed up processing. // this makes equals compares run much faster in the // stack because then it is just identity comparision String meth = getCannonicalName(method); this.requestLine.setMethod(meth); if (this.cSeqHeader != null) { try { this.cSeqHeader.setMethod(meth); } catch (ParseException e) { } } } /** * Get the method from the request line. * * @return the method from the request line if the method exits and null if the request line * or the method does not exist. */ public String getMethod() { if (requestLine == null) return null; else return requestLine.getMethod(); } /** * Encode the SIP Request as a string. * * @return an encoded String containing the encoded SIP Message. */ public String encode() { String retval; if (requestLine != null) { this.setRequestLineDefaults(); retval = requestLine.encode() + super.encode(); } else if (this.isNullRequest()) { retval = "\r\n\r\n"; } else { retval = super.encode(); } return retval; } /** * Encode only the headers and not the content. */ public String encodeMessage() { String retval; if (requestLine != null) { this.setRequestLineDefaults(); retval = requestLine.encode() + super.encodeSIPHeaders(); } else if (this.isNullRequest()) { retval = "\r\n\r\n"; } else retval = super.encodeSIPHeaders(); return retval; } /** * ALias for encode above. */ public String toString() { return this.encode(); } /** * Make a clone (deep copy) of this object. You can use this if you want to modify a request * while preserving the original * * @return a deep copy of this object. */ public Object clone() { SIPRequest retval = (SIPRequest) super.clone(); // Do not copy over the tx pointer -- this is only for internal // tracking. retval.transactionPointer = null; if (this.requestLine != null) retval.requestLine = (RequestLine) this.requestLine.clone(); return retval; } /** * Compare for equality. * * @param other object to compare ourselves with. */ public boolean equals(Object other) { if (!this.getClass().equals(other.getClass())) return false; SIPRequest that = (SIPRequest) other; return requestLine.equals(that.requestLine) && super.equals(other); } /** * Get the message as a linked list of strings. Use this if you want to iterate through the * message. * * @return a linked list containing the request line and headers encoded as strings. */ public LinkedList getMessageAsEncodedStrings() { LinkedList retval = super.getMessageAsEncodedStrings(); if (requestLine != null) { this.setRequestLineDefaults(); retval.addFirst(requestLine.encode()); } return retval; } /** * Match with a template. You can use this if you want to match incoming messages with a * pattern and do something when you find a match. This is useful for building filters/pattern * matching responders etc. * * @param matchObj object to match ourselves with (null matches wildcard) * */ public boolean match(Object matchObj) { if (matchObj == null) return true; else if (!matchObj.getClass().equals(this.getClass())) return false; else if (matchObj == this) return true; SIPRequest that = (SIPRequest) matchObj; RequestLine rline = that.requestLine; if (this.requestLine == null && rline != null) return false; else if (this.requestLine == rline) return super.match(matchObj); return requestLine.match(that.requestLine) && super.match(matchObj); } /** * 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. * * @return a byte array containing the SIPRequest encoded as a byte array. */ public byte[] encodeAsBytes(String transport) { if (this.isNullRequest()) { // Encoding a null message for keepalive. return "\r\n\r\n".getBytes(); } else if ( this.requestLine == null ) { return new byte[0]; } byte[] rlbytes = null; if (requestLine != null) { try { rlbytes = requestLine.encode().getBytes("UTF-8"); } catch (UnsupportedEncodingException ex) { InternalErrorHandler.handleException(ex); } } byte[] superbytes = super.encodeAsBytes(transport); byte[] retval = new byte[rlbytes.length + superbytes.length]; System.arraycopy(rlbytes, 0, retval, 0, rlbytes.length); System.arraycopy(superbytes, 0, retval, rlbytes.length, superbytes.length); return retval; } /** * Creates a default SIPResponse message for this request. Note You must add the necessary * tags to outgoing responses if need be. For efficiency, this method does not clone the * incoming request. If you want to modify the outgoing response, be sure to clone the * incoming request as the headers are shared and any modification to the headers of the * outgoing response will result in a modification of the incoming request. Tag fields are * just copied from the incoming request. Contact headers are removed from the incoming * request. Added by Jeff Keyser. * * @param statusCode Status code for the response. Reason phrase is generated. * * @return A SIPResponse with the status and reason supplied, and a copy of all the original * headers from this request. */ public SIPResponse createResponse(int statusCode) { String reasonPhrase = SIPResponse.getReasonPhrase(statusCode); return this.createResponse(statusCode, reasonPhrase); } /** * Creates a default SIPResponse message for this request. Note You must add the necessary * tags to outgoing responses if need be. For efficiency, this method does not clone the * incoming request. If you want to modify the outgoing response, be sure to clone the * incoming request as the headers are shared and any modification to the headers of the * outgoing response will result in a modification of the incoming request. Tag fields are * just copied from the incoming request. Contact headers are removed from the incoming * request. Added by Jeff Keyser. Route headers are not added to the response. * * @param statusCode Status code for the response. * @param reasonPhrase Reason phrase for this response. * * @return A SIPResponse with the status and reason supplied, and a copy of all the original * headers from this request except the ones that are not supposed to be part of the * response . */ public SIPResponse createResponse(int statusCode, String reasonPhrase) { SIPResponse newResponse; Iterator headerIterator; SIPHeader nextHeader; newResponse = new SIPResponse(); try { newResponse.setStatusCode(statusCode); } catch (ParseException ex) { throw new IllegalArgumentException("Bad code " + statusCode); } if (reasonPhrase != null) 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(); } } } if (MessageFactoryImpl.getDefaultServerHeader() != null) { newResponse.setHeader(MessageFactoryImpl.getDefaultServerHeader()); } 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); } return newResponse; } // Helper method for createResponse, to avoid copying Record-Route unless needed private final boolean mustCopyRR( int code ) { // Only for 1xx-2xx, not for 100 or errors if ( code>100 && code<300 ) { return isDialogCreating( this.getMethod() ) && getToTag() == null; } else return false; } /** * Creates a default SIPResquest message that would cancel this request. Note that tag * assignment and removal of is left to the caller (we use whatever tags are present in the * original request). * * @return A CANCEL SIPRequest constructed according to RFC3261 section 9.1 * * @throws SipException * @throws ParseException */ public SIPRequest createCancelRequest() throws SipException { // see RFC3261 9.1 // A CANCEL request SHOULD NOT be sent to cancel a request other than // INVITE if (!this.getMethod().equals(Request.INVITE)) throw new SipException("Attempt to create CANCEL for " + this.getMethod()); /* * The following procedures are used to construct a CANCEL request. The Request-URI, * Call-ID, To, the numeric part of CSeq, and From header fields in the CANCEL request * MUST be identical to those in the request being cancelled, including tags. A CANCEL * constructed by a client MUST have only a single Via header field value matching the top * Via value in the request being cancelled. Using the same values for these header fields * allows the CANCEL to be matched with the request it cancels (Section 9.2 indicates how * such matching occurs). However, the method part of the CSeq header field MUST have a * value of CANCEL. This allows it to be identified and processed as a transaction in its * own right (See Section 17). */ SIPRequest cancel = new SIPRequest(); cancel.setRequestLine((RequestLine) this.requestLine.clone()); cancel.setMethod(Request.CANCEL); cancel.setHeader((Header) this.callIdHeader.clone()); cancel.setHeader((Header) this.toHeader.clone()); cancel.setHeader((Header) cSeqHeader.clone()); try { cancel.getCSeq().setMethod(Request.CANCEL); } catch (ParseException e) { e.printStackTrace(); // should not happen } cancel.setHeader((Header) this.fromHeader.clone()); cancel.addFirst((Header) this.getTopmostVia().clone()); cancel.setHeader((Header) this.maxForwardsHeader.clone()); /* * If the request being cancelled contains a Route header field, the CANCEL request MUST * include that Route header field's values. */ if (this.getRouteHeaders() != null) { cancel.setHeader((SIPHeaderList< ? >) this.getRouteHeaders().clone()); } if (MessageFactoryImpl.getDefaultUserAgentHeader() != null) { cancel.setHeader(MessageFactoryImpl.getDefaultUserAgentHeader()); } return cancel; } /** * Creates a default ACK SIPRequest message for this original request. Note that the * defaultACK SIPRequest does not include the content of the original SIPRequest. If * responseToHeader is null then the toHeader of this request is used to construct the ACK. * Note that tag fields are just copied from the original SIP Request. Added by Jeff Keyser. * * @param responseToHeader To header to use for this request. * * @return A SIPRequest with an ACK method. */ public SIPRequest createAckRequest(To responseToHeader) { SIPRequest newRequest; Iterator headerIterator; SIPHeader nextHeader; newRequest = new SIPRequest(); newRequest.setRequestLine((RequestLine) this.requestLine.clone()); newRequest.setMethod(Request.ACK); 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()); } return newRequest; } /** * Creates an ACK for non-2xx responses according to RFC3261 17.1.1.3 * * @return A SIPRequest with an ACK method. * @throws SipException * @throws NullPointerException * @throws ParseException * * @author jvb */ public final SIPRequest createErrorAck(To responseToHeader) throws SipException, ParseException { /* * The ACK request constructed by the client transaction MUST contain values for the * Call-ID, From, and Request-URI that are equal to the values of those header fields in * the request passed to the transport by the client transaction (call this the "original * request"). The To header field in the ACK MUST equal the To header field in the * response being acknowledged, and therefore will usually differ from the To header field * in the original request by the addition of the tag parameter. The ACK MUST contain a * single Via header field, and this MUST be equal to the top Via header field of the * original request. 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". */ SIPRequest newRequest = new SIPRequest(); newRequest.setRequestLine((RequestLine) this.requestLine.clone()); newRequest.setMethod(Request.ACK); newRequest.setHeader((Header) this.callIdHeader.clone()); newRequest.setHeader((Header) this.maxForwardsHeader.clone()); // ISSUE // 130 // fix newRequest.setHeader((Header) this.fromHeader.clone()); newRequest.setHeader((Header) responseToHeader.clone()); newRequest.addFirst((Header) this.getTopmostVia().clone()); newRequest.setHeader((Header) cSeqHeader.clone()); newRequest.getCSeq().setMethod(Request.ACK); /* * If the INVITE request whose response is being acknowledged had Route header fields, * those header fields MUST appear in the ACK. This is to ensure that the ACK can be * routed properly through any downstream stateless proxies. */ if (this.getRouteHeaders() != null) { newRequest.setHeader((SIPHeaderList) this.getRouteHeaders().clone()); } if (MessageFactoryImpl.getDefaultUserAgentHeader() != null) { newRequest.setHeader(MessageFactoryImpl.getDefaultUserAgentHeader()); } 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. */ public String getViaHost() { Via via = (Via) this.getViaHeaders().getFirst(); return via.getHost(); } /** * Get the port from the topmost via header. * * @return the port from the topmost via header (5060 if there is no port indicated). */ public int getViaPort() { Via via = (Via) this.getViaHeaders().getFirst(); if (via.hasPort()) return via.getPort(); else return 5060; } /** * Get the first line encoded. * * @return a string containing the encoded request line. */ public String getFirstLine() { if (requestLine == null) return null; else return this.requestLine.encode(); } /** * Set the sip version. * * @param sipVersion the sip version to set. */ public void setSIPVersion(String sipVersion) throws ParseException { if (sipVersion == null || !sipVersion.equalsIgnoreCase("SIP/2.0")) throw new ParseException("sipVersion", 0); this.requestLine.setSipVersion(sipVersion); } /** * Get the SIP version. * * @return the SIP version from the request line. */ public String getSIPVersion() { return this.requestLine.getSipVersion(); } /** * Book keeping method to return the current tx for the request if one exists. * * @return the assigned tx. */ public Object getTransaction() { // Return an opaque pointer to the transaction object. // This is for consistency checking and quick lookup. return this.transactionPointer; } /** * Book keeping field to set the current tx for the request. * * @param transaction */ public void setTransaction(Object transaction) { this.transactionPointer = transaction; } /** * Book keeping method to get the messasge channel for the request. * * @return the message channel for the request. */ public Object getMessageChannel() { // return opaque ptr to the message chanel on // which the message was recieved. For consistency // checking and lookup. return this.messageChannel; } /** * Set the message channel for the request ( bookkeeping field ). * * @param messageChannel */ public void setMessageChannel(Object messageChannel) { this.messageChannel = messageChannel; } /** * Generates an Id for checking potentially merged requests. * * @return String to check for merged requests */ public String getMergeId() { /* * generate an identifier from the From tag, Call-ID, and CSeq */ String fromTag = this.getFromTag(); String cseq = this.cSeqHeader.toString(); String callId = this.callIdHeader.getCallId(); /* NOTE : The RFC does NOT specify you need to include a Request URI * This is added here for the case of Back to Back User Agents. */ String requestUri = this.getRequestURI().toString(); if (fromTag != null) { return new StringBuffer().append(requestUri).append(":").append(fromTag).append(":").append(cseq).append(":") .append(callId).toString(); } else return null; } /** * @param inviteTransaction the inviteTransaction to set */ public void setInviteTransaction(Object inviteTransaction) { this.inviteTransaction = inviteTransaction; } /** * @return the inviteTransaction */ public Object getInviteTransaction() { return inviteTransaction; } } java/gov/nist/javax/sip/message/SIPResponse.java0100644 0000000 0000000 00000054015 13513104763 020653 0ustar000000000 0000000 /* * 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.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.29 $ $Date: 2009/10/25 03:07:52 $ * @since 1.1 * * @author M. Ranganathan
    * * */ public final class SIPResponse extends SIPMessage implements javax.sip.message.Response, ResponseExt { protected StatusLine statusLine; public static String getReasonPhrase(int rc) { String retval = null; switch (rc) { case TRYING : retval = "Trying"; break; case RINGING : retval = "Ringing"; break; case CALL_IS_BEING_FORWARDED : retval = "Call is being forwarded"; break; case QUEUED : retval = "Queued"; break; case SESSION_PROGRESS : retval = "Session progress"; break; case OK : retval = "OK"; break; case ACCEPTED : retval = "Accepted"; break; case MULTIPLE_CHOICES : retval = "Multiple choices"; break; case MOVED_PERMANENTLY : retval = "Moved permanently"; break; case MOVED_TEMPORARILY : retval = "Moved Temporarily"; break; case USE_PROXY : retval = "Use proxy"; break; case ALTERNATIVE_SERVICE : retval = "Alternative service"; break; case BAD_REQUEST : retval = "Bad request"; break; case UNAUTHORIZED : retval = "Unauthorized"; break; case PAYMENT_REQUIRED : retval = "Payment required"; break; case FORBIDDEN : retval = "Forbidden"; break; case NOT_FOUND : retval = "Not found"; break; case METHOD_NOT_ALLOWED : retval = "Method not allowed"; break; case NOT_ACCEPTABLE : retval = "Not acceptable"; break; case PROXY_AUTHENTICATION_REQUIRED : retval = "Proxy Authentication required"; break; case REQUEST_TIMEOUT : retval = "Request timeout"; break; case GONE : retval = "Gone"; break; case TEMPORARILY_UNAVAILABLE : retval = "Temporarily Unavailable"; break; case REQUEST_ENTITY_TOO_LARGE : retval = "Request entity too large"; break; case REQUEST_URI_TOO_LONG : retval = "Request-URI too large"; break; case UNSUPPORTED_MEDIA_TYPE : retval = "Unsupported media type"; break; case UNSUPPORTED_URI_SCHEME : retval = "Unsupported URI Scheme"; break; case BAD_EXTENSION : retval = "Bad extension"; break; case EXTENSION_REQUIRED : retval = "Etension Required"; break; case INTERVAL_TOO_BRIEF : retval = "Interval too brief"; break; case CALL_OR_TRANSACTION_DOES_NOT_EXIST : retval = "Call leg/Transaction does not exist"; break; case LOOP_DETECTED : retval = "Loop detected"; break; case TOO_MANY_HOPS : retval = "Too many hops"; break; case ADDRESS_INCOMPLETE : retval = "Address incomplete"; break; case AMBIGUOUS : retval = "Ambiguous"; break; case BUSY_HERE : retval = "Busy here"; break; case REQUEST_TERMINATED : retval = "Request Terminated"; break; //Issue 168, Typo fix reported by fre on the retval case NOT_ACCEPTABLE_HERE : retval = "Not Acceptable here"; break; case BAD_EVENT : retval = "Bad Event"; break; case REQUEST_PENDING : retval = "Request Pending"; break; case SERVER_INTERNAL_ERROR : retval = "Server Internal Error"; break; case UNDECIPHERABLE : retval = "Undecipherable"; break; case NOT_IMPLEMENTED : retval = "Not implemented"; break; case BAD_GATEWAY : retval = "Bad gateway"; break; case SERVICE_UNAVAILABLE : retval = "Service unavailable"; break; case SERVER_TIMEOUT : retval = "Gateway timeout"; break; case VERSION_NOT_SUPPORTED : retval = "SIP version not supported"; break; case MESSAGE_TOO_LARGE : retval = "Message Too Large"; break; case BUSY_EVERYWHERE : retval = "Busy everywhere"; break; case DECLINE : retval = "Decline"; break; case DOES_NOT_EXIST_ANYWHERE : retval = "Does not exist anywhere"; break; case SESSION_NOT_ACCEPTABLE : retval = "Session Not acceptable"; break; case CONDITIONAL_REQUEST_FAILED: retval = "Conditional request failed"; break; default : retval = "Unknown Status"; } return retval; } /** set the status code. *@param statusCode is the status code to set. *@throws IlegalArgumentException if invalid status code. */ public void setStatusCode(int statusCode) throws ParseException { // RFC3261 defines statuscode as 3DIGIT, 606 is the highest officially // defined code but extensions may add others (in theory up to 999, // but in practice up to 699 since the 6xx range is defined as 'final error') if (statusCode < 100 || statusCode > 699) throw new ParseException("bad status code", 0); if (this.statusLine == null) this.statusLine = new StatusLine(); this.statusLine.setStatusCode(statusCode); } /** * Get the status line of the response. *@return StatusLine */ public StatusLine getStatusLine() { return statusLine; } /** Get the staus code (conveniance function). *@return the status code of the status line. */ public int getStatusCode() { return statusLine.getStatusCode(); } /** Set the reason phrase. *@param reasonPhrase the reason phrase. *@throws IllegalArgumentException if null string */ public void setReasonPhrase(String reasonPhrase) { if (reasonPhrase == null) throw new IllegalArgumentException("Bad reason phrase"); if (this.statusLine == null) this.statusLine = new StatusLine(); this.statusLine.setReasonPhrase(reasonPhrase); } /** Get the reason phrase. *@return the reason phrase. */ public String getReasonPhrase() { if (statusLine == null || statusLine.getReasonPhrase() == null) return ""; else return statusLine.getReasonPhrase(); } /** Return true if the response is a final response. *@param rc is the return code. *@return true if the parameter is between the range 200 and 700. */ public static boolean isFinalResponse(int rc) { return rc >= 200 && rc < 700; } /** Is this a final response? *@return true if this is a final response. */ public boolean isFinalResponse() { return isFinalResponse(statusLine.getStatusCode()); } /** * Set the status line field. *@param sl Status line to set. */ public void setStatusLine(StatusLine sl) { statusLine = sl; } /** Constructor. */ public SIPResponse() { super(); } /** * Print formatting function. *Indent and parenthesize for pretty printing. * Note -- use the encode method for formatting the message. * Hack here to XMLize. * *@return a string for pretty printing. */ public String debugDump() { String superstring = super.debugDump(); stringRepresentation = ""; sprint(SIPResponse.class.getCanonicalName()); sprint("{"); if (statusLine != null) { sprint(statusLine.debugDump()); } sprint(superstring); sprint("}"); return stringRepresentation; } /** * Check the response structure. Must have from, to CSEQ and VIA * headers. */ public void checkHeaders() throws ParseException { if (getCSeq() == null) { throw new ParseException(CSeq.NAME+ " Is missing ", 0); } if (getTo() == null) { throw new ParseException(To.NAME+ " Is missing ", 0); } if (getFrom() == null) { throw new ParseException(From.NAME+ " Is missing ", 0); } if (getViaHeaders() == null) { throw new ParseException(Via.NAME+ " Is missing ", 0); } if (getCallId() == null) { throw new ParseException(CallID.NAME + " Is missing ", 0); } if (getStatusCode() > 699) { throw new ParseException("Unknown error code!" + getStatusCode(), 0); } } /** * Encode the SIP Request as a string. *@return The string encoded canonical form of the message. */ public String encode() { String retval; if (statusLine != null) retval = statusLine.encode() + super.encode(); else retval = super.encode(); return retval ; } /** Encode the message except for the body. * *@return The string except for the body. */ public String encodeMessage() { String retval; if (statusLine != null) retval = statusLine.encode() + super.encodeSIPHeaders(); else retval = super.encodeSIPHeaders(); return retval ; } /** Get this message as a list of encoded strings. *@return LinkedList containing encoded strings for each header in * the message. */ public LinkedList getMessageAsEncodedStrings() { LinkedList retval = super.getMessageAsEncodedStrings(); if (statusLine != null) retval.addFirst(statusLine.encode()); return retval; } /** * Make a clone (deep copy) of this object. *@return a deep copy of this object. */ public Object clone() { SIPResponse retval = (SIPResponse) super.clone(); if (this.statusLine != null) retval.statusLine = (StatusLine) this.statusLine.clone(); return retval; } /** * Compare for equality. *@param other other object to compare with. */ public boolean equals(Object other) { if (!this.getClass().equals(other.getClass())) return false; SIPResponse that = (SIPResponse) other; return statusLine.equals(that.statusLine) && super.equals(other); } /** * Match with a template. *@param matchObj template object to match ourselves with (null * in any position in the template object matches wildcard) */ public boolean match(Object matchObj) { if (matchObj == null) return true; else if (!matchObj.getClass().equals(this.getClass())) { return false; } else if (matchObj == this) return true; SIPResponse that = (SIPResponse) matchObj; StatusLine rline = that.statusLine; if (this.statusLine == null && rline != null) return false; else if (this.statusLine == rline) return super.match(matchObj); else { return statusLine.match(that.statusLine) && super.match(matchObj); } } /** 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. * *@return a byte array containing the SIPRequest encoded as a byte * array. */ public byte[] encodeAsBytes( String transport ) { byte[] slbytes = null; if (statusLine != null) { try { slbytes = statusLine.encode().getBytes("UTF-8"); } catch (UnsupportedEncodingException ex) { InternalErrorHandler.handleException(ex); } } byte[] superbytes = super.encodeAsBytes( transport ); byte[] retval = new byte[slbytes.length + superbytes.length]; System.arraycopy(slbytes, 0, retval, 0, slbytes.length); System.arraycopy(superbytes, 0, retval, slbytes.length, superbytes.length); 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. * *@return the status line encoded. * */ public String getFirstLine() { if (this.statusLine == null) return null; else return this.statusLine.encode(); } public void setSIPVersion(String sipVersion) { this.statusLine.setSipVersion(sipVersion); } public String getSIPVersion() { return this.statusLine.getSipVersion(); } public String toString() { if (statusLine == null) return ""; else return statusLine.encode() + super.encode(); } /** * 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); 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; } } java/gov/nist/javax/sip/message/package.html0100644 0000000 0000000 00000000110 13513104763 020102 0ustar000000000 0000000 Class definitions for SIP messages and message factory. java/gov/nist/javax/sip/package.html0100644 0000000 0000000 00000003500 13513104763 016464 0ustar000000000 0000000 This is the root of the JAIN implementation of SIP. It contains an implementation of the Provider, Listener and Stack. Implementation of the headers is contained in header and implementation of the parser in the parser subdirectory. The SIP Protocol specific abstractions are implemented in the stack subdirectory.

    The RI contains several additional Features that are not required by the JAIN-SIP spec and that can be enabled by RI-specific properties that are specified when the SipStack is created. The purpose of these additional properties is to enable the following:

    • Message Logging features - permits the application to log messages in a format that are suitable for trace viewing using the trace viewer facility.
    • TCP starvation attack prevention - Limit the size and timeout for tcp connections.
    • UDP Flooding attack prevention -- limit the size of queues and transaction table size.
    • TCP message size limitation -- limit the size of TCP messages to prevent TCP flooding attacks.
    • Connection caching and reuse for TCP connections -- reduce latency by re-using TCP connections on client and server transactions.
    • Address resolution -- resolve addresses that are not direct DNS lookups or IP addresses using a custom address resolver.
    • Network Layer -- allows your application code to have direct access to the Sockets that are used by the stack (use this feature with caution!).
    See the javadoc for gov.nist.javax.sip.SipStackImpl for a detailed explanation of these features.

    The interfaces that are suffixed with Ext in this package will not be altered and will be included in the next specification revision. These are provided here for those who wish to use these extensions and do not want to wait until the next spec revision becomes available. java/gov/nist/javax/sip/parser/0040755 0000000 0000000 00000000000 13513104763 015504 5ustar000000000 0000000 java/gov/nist/javax/sip/parser/AcceptEncodingParser.java0100644 0000000 0000000 00000016521 13513104763 022374 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import gov.nist.core.*; import java.text.ParseException; import javax.sip.*; /** * Accept-Encoding SIP (HTTP) Header parser. * * @version 1.2 $Revision: 1.7 $ $Date: 2009/07/17 18:57:56 $ * * @author Olivier Deruelle * @author M. Ranganathan * * *

     *
     *   The Accept-Encoding request-header field is similar to Accept, but
     *   restricts the content-codings (section 3.5) that are acceptable in
     *   the response.
     *
     *
     *       Accept-Encoding  = "Accept-Encoding" ":"
     *                      ( encoding *( "," encoding) )
     *       encoding         = ( codings *[ ";" "q" "=" qvalue ] )
     *       codings          = ( content-coding | "*" )
     *
     *   Examples of its use are:
     *
     *       Accept-Encoding: compress, gzip
     *       Accept-Encoding:
     *       Accept-Encoding: *
     *       Accept-Encoding: compress;q=0.5, gzip;q=1.0
     *       Accept-Encoding: gzip;q=1.0, identity; q=0.5, *;q=0
     * 
    * */ public class AcceptEncodingParser extends HeaderParser { /** * Constructor * @param acceptEncoding message to parse */ public AcceptEncodingParser(String acceptEncoding) { super(acceptEncoding); } /** * Constructor * @param lexer Lexer to set */ protected AcceptEncodingParser(Lexer lexer) { super(lexer); } /** * parse the String message * @return SIPHeader (AcceptEncoding object) * @throws ParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { AcceptEncodingList acceptEncodingList = new AcceptEncodingList(); if (debug) dbg_enter("AcceptEncodingParser.parse"); try { headerName(TokenTypes.ACCEPT_ENCODING); // empty body is fine for this header. if (lexer.lookAhead(0) == '\n') { AcceptEncoding acceptEncoding = new AcceptEncoding(); acceptEncodingList.add(acceptEncoding); } else { while (lexer.lookAhead(0) != '\n') { AcceptEncoding acceptEncoding = new AcceptEncoding(); if (lexer.lookAhead(0) != ';') { // Content-Coding: lexer.match(TokenTypes.ID); Token value = lexer.getNextToken(); acceptEncoding.setEncoding(value.getTokenValue()); } while (lexer.lookAhead(0) == ';') { this.lexer.match(';'); this.lexer.SPorHT(); this.lexer.match('q'); this.lexer.SPorHT(); this.lexer.match('='); this.lexer.SPorHT(); lexer.match(TokenTypes.ID); Token value = lexer.getNextToken(); try { float qv = Float.parseFloat(value.getTokenValue()); acceptEncoding.setQValue(qv); } catch (NumberFormatException ex) { throw createParseException(ex.getMessage()); } catch (InvalidArgumentException ex) { throw createParseException(ex.getMessage()); } this.lexer.SPorHT(); } acceptEncodingList.add(acceptEncoding); if (lexer.lookAhead(0) == ',') { this.lexer.match(','); this.lexer.SPorHT(); } } } return acceptEncodingList; } finally { if (debug) dbg_leave("AcceptEncodingParser.parse"); } } } /* * $Log: AcceptEncodingParser.java,v $ * Revision 1.7 2009/07/17 18:57:56 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.6 2006/07/13 09:02:03 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.4 2004/01/22 13:26:31 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/AcceptLanguageParser.java0100644 0000000 0000000 00000015751 13513104763 022375 0ustar000000000 0000000 /* * 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 * * . * */ /* * AcceptLanguageParser.java * * Created on June 10, 2002, 3:31 PM */ package gov.nist.javax.sip.parser; import gov.nist.core.*; import gov.nist.javax.sip.header.*; import javax.sip.*; import java.text.ParseException; /** * Parser for Accept Language Headers. * * Accept Language body. *
     *
     * Accept-Language = "Accept-Language" ":"
     *                         1#( language-range [ ";" "q" "=" qvalue ] )
     *       language-range  = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" )
     *
     * HTTP RFC 2616 Section 14.4
     * 
    * * Accept-Language: da, en-gb;q=0.8, en;q=0.7 * * @see AcceptLanguageList * @version 1.2 $Revision: 1.8 $ $Date: 2009/07/17 18:57:56 $ * * @author Olivier Deruelle * */ public class AcceptLanguageParser extends HeaderParser { /** * Constructor * @param acceptLanguage AcceptLanguage message to parse */ public AcceptLanguageParser(String acceptLanguage) { super(acceptLanguage); } /** * Constructor * @param lexer Lexer to set */ protected AcceptLanguageParser(Lexer lexer) { super(lexer); } /** * parse the String message * @return SIPHeader (AcceptLanguage object) * @throws ParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { AcceptLanguageList acceptLanguageList = new AcceptLanguageList(); if (debug) dbg_enter("AcceptLanguageParser.parse"); try { headerName(TokenTypes.ACCEPT_LANGUAGE); while (lexer.lookAhead(0) != '\n') { AcceptLanguage acceptLanguage = new AcceptLanguage(); acceptLanguage.setHeaderName(SIPHeaderNames.ACCEPT_LANGUAGE); if (lexer.lookAhead(0) != ';') { // Content-Coding: lexer.match(TokenTypes.ID); Token value = lexer.getNextToken(); acceptLanguage.setLanguageRange(value.getTokenValue()); } while (lexer.lookAhead(0) == ';') { this.lexer.match(';'); this.lexer.SPorHT(); this.lexer.match('q'); this.lexer.SPorHT(); this.lexer.match('='); this.lexer.SPorHT(); lexer.match(TokenTypes.ID); Token value = lexer.getNextToken(); try { float fl = Float.parseFloat(value.getTokenValue()); acceptLanguage.setQValue(fl); } catch (NumberFormatException ex) { throw createParseException(ex.getMessage()); } catch (InvalidArgumentException ex) { throw createParseException(ex.getMessage()); } this.lexer.SPorHT(); } acceptLanguageList.add(acceptLanguage); if (lexer.lookAhead(0) == ',') { this.lexer.match(','); this.lexer.SPorHT(); } else this.lexer.SPorHT(); } } finally { if (debug) dbg_leave("AcceptLanguageParser.parse"); } return acceptLanguageList; } } /* * $Log: AcceptLanguageParser.java,v $ * Revision 1.8 2009/07/17 18:57:56 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.7 2006/07/13 09:02:11 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.5 2004/07/28 14:13:54 mranga * Submitted by: mranga * * Move out the test code to a separate test/unit class. * Fixed some encode methods. * * Revision 1.4 2004/01/22 13:26:31 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/AcceptParser.java0100644 0000000 0000000 00000013651 13513104763 020726 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import gov.nist.core.*; import java.text.ParseException; /** * Parser for Accept header. * * @version 1.2 $Revision: 1.7 $ $Date: 2009/07/17 18:57:56 $ * * @author Olivier Deruelle * @author M. Ranganathan
    * * */ public class AcceptParser extends ParametersParser { /** * Creates a new instance of Accept Parser * @param accept the header to parse */ public AcceptParser(String accept) { super(accept); } /** * Constructor * @param lexer the lexer to use to parse the header */ protected AcceptParser(Lexer lexer) { super(lexer); } /** * parse the Accept String header * @return SIPHeader (AcceptList object) * @throws SIPParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { if (debug) dbg_enter("AcceptParser.parse"); AcceptList list = new AcceptList(); try { headerName(TokenTypes.ACCEPT); Accept accept = new Accept(); accept.setHeaderName(SIPHeaderNames.ACCEPT); this.lexer.SPorHT(); this.lexer.match(TokenTypes.ID); Token token = lexer.getNextToken(); accept.setContentType(token.getTokenValue()); this.lexer.match('/'); this.lexer.match(TokenTypes.ID); token = lexer.getNextToken(); accept.setContentSubType(token.getTokenValue()); this.lexer.SPorHT(); super.parse(accept); list.add(accept); while (lexer.lookAhead(0) == ',') { this.lexer.match(','); this.lexer.SPorHT(); accept = new Accept(); this.lexer.match(TokenTypes.ID); token = lexer.getNextToken(); accept.setContentType(token.getTokenValue()); this.lexer.match('/'); this.lexer.match(TokenTypes.ID); token = lexer.getNextToken(); accept.setContentSubType(token.getTokenValue()); this.lexer.SPorHT(); super.parse(accept); list.add(accept); } return list; } finally { if (debug) dbg_leave("AcceptParser.parse"); } } } /* * $Log: AcceptParser.java,v $ * Revision 1.7 2009/07/17 18:57:56 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.6 2006/07/13 09:02:16 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.4 2004/01/22 13:26:31 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/AddressParametersParser.java0100644 0000000 0000000 00000004631 13513104763 023136 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import gov.nist.javax.sip.address.*; import java.text.ParseException; /** * Address parameters parser. * * @version 1.2 $Revision: 1.10 $ $Date: 2009/10/22 10:25:57 $ * @author M. Ranganathan * @since 1.1 * */ public class AddressParametersParser extends ParametersParser { protected AddressParametersParser(Lexer lexer) { super(lexer); } protected AddressParametersParser(String buffer) { super(buffer); } protected void parse(AddressParametersHeader addressParametersHeader) throws ParseException { dbg_enter("AddressParametersParser.parse"); try { AddressParser addressParser = new AddressParser(this.getLexer()); AddressImpl addr = addressParser.address(false); addressParametersHeader.setAddress(addr); lexer.SPorHT(); char la = this.lexer.lookAhead(0); if ( this.lexer.hasMoreChars() && la != '\0' && la != '\n' && this.lexer.startsId()) { super.parseNameValueList(addressParametersHeader); } else super.parse(addressParametersHeader); } catch (ParseException ex) { throw ex; } finally { dbg_leave("AddressParametersParser.parse"); } } } java/gov/nist/javax/sip/parser/AddressParser.java0100644 0000000 0000000 00000017377 13513104763 021125 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.address.*; import java.text.ParseException; /** Parser for addresses. * * @version 1.2 $Revision: 1.11 $ $Date: 2009/10/22 10:26:27 $ * @author M. Ranganathan * * */ public class AddressParser extends Parser { public AddressParser(Lexer lexer) { this.lexer = lexer; this.lexer.selectLexer("charLexer"); } public AddressParser(String address) { this.lexer = new Lexer("charLexer", address); } protected AddressImpl nameAddr() throws ParseException { if (debug) dbg_enter("nameAddr"); try { if (this.lexer.lookAhead(0) == '<') { this.lexer.consume(1); this.lexer.selectLexer("sip_urlLexer"); this.lexer.SPorHT(); URLParser uriParser = new URLParser((Lexer) lexer); GenericURI uri = uriParser.uriReference( true ); AddressImpl retval = new AddressImpl(); retval.setAddressType(AddressImpl.NAME_ADDR); retval.setURI(uri); this.lexer.SPorHT(); this.lexer.match('>'); return retval; } else { AddressImpl addr = new AddressImpl(); addr.setAddressType(AddressImpl.NAME_ADDR); String name = null; if (this.lexer.lookAhead(0) == '\"') { name = this.lexer.quotedString(); this.lexer.SPorHT(); } else name = this.lexer.getNextToken('<'); addr.setDisplayName(name.trim()); this.lexer.match('<'); this.lexer.SPorHT(); URLParser uriParser = new URLParser((Lexer) lexer); GenericURI uri = uriParser.uriReference( true ); AddressImpl retval = new AddressImpl(); addr.setAddressType(AddressImpl.NAME_ADDR); addr.setURI(uri); this.lexer.SPorHT(); this.lexer.match('>'); return addr; } } finally { if (debug) dbg_leave("nameAddr"); } } public AddressImpl address( boolean inclParams ) throws ParseException { if (debug) dbg_enter("address"); AddressImpl retval = null; try { int k = 0; while (lexer.hasMoreChars()) { char la = lexer.lookAhead(k); if (la == '<' || la == '\"' || la == ':' || la == '/') break; else if (la == '\0') throw createParseException("unexpected EOL"); else k++; } char la = lexer.lookAhead(k); if (la == '<' || la == '\"') { retval = nameAddr(); } else if (la == ':' || la == '/') { retval = new AddressImpl(); URLParser uriParser = new URLParser((Lexer) lexer); GenericURI uri = uriParser.uriReference( inclParams ); retval.setAddressType(AddressImpl.ADDRESS_SPEC); retval.setURI(uri); } else { throw createParseException("Bad address spec"); } return retval; } finally { if (debug) dbg_leave("address"); } } /* */ } /* * $Log: AddressParser.java,v $ * 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 StringBuffer instance during the encoding phase. * * Revision 1.8 2007/02/06 16:40:02 belangery * Introduced simple code optimizations. * * Revision 1.7 2006/07/13 09:01:57 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.4 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.3 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.2 2006/03/08 23:32:54 mranga * *** empty log message *** * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.5 2004/07/28 14:13:54 mranga * Submitted by: mranga * * Move out the test code to a separate test/unit class. * Fixed some encode methods. * * Revision 1.4 2004/01/22 13:26:31 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/AlertInfoParser.java0100644 0000000 0000000 00000015370 13513104763 021412 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.address.GenericURI; import gov.nist.javax.sip.header.AlertInfo; import gov.nist.javax.sip.header.AlertInfoList; import gov.nist.javax.sip.header.SIPHeader; import gov.nist.javax.sip.header.SIPHeaderNames; import java.text.ParseException; /** * Parser for AlertInfo header. * * @version 1.2 $Revision: 1.10 $ $Date: 2009/11/07 23:35:49 $ * * @author Olivier Deruelle * @author M. Ranganathan * */ public class AlertInfoParser extends ParametersParser { /** * Creates a new instance of AlertInfo Parser * @param alertInfo the header to parse */ public AlertInfoParser(String alertInfo) { super(alertInfo); } /** * Constructor * @param lexer the lexer to use to parse the header */ protected AlertInfoParser(Lexer lexer) { super(lexer); } /** * parse the AlertInfo String header * @return SIPHeader (AlertInfoList object) * @throws SIPParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { if (debug) dbg_enter("AlertInfoParser.parse"); AlertInfoList list = new AlertInfoList(); try { headerName(TokenTypes.ALERT_INFO); while (lexer.lookAhead(0) != '\n') { AlertInfo alertInfo = new AlertInfo(); alertInfo.setHeaderName(SIPHeaderNames.ALERT_INFO); URLParser urlParser; GenericURI uri; do { this.lexer.SPorHT(); if (this.lexer.lookAhead(0) == '<') { this.lexer.match('<'); urlParser = new URLParser((Lexer) this.lexer); uri = urlParser.uriReference( true ); alertInfo.setAlertInfo(uri); this.lexer.match('>'); } else { /* This is non standard for Polycom support. * I know it is bad grammar but please do not remove. mranga */ String alertInfoStr = this.lexer.byteStringNoSemicolon(); alertInfo.setAlertInfo(alertInfoStr); } this.lexer.SPorHT(); super.parse(alertInfo); list.add(alertInfo); if ( lexer.lookAhead(0) == ',' ) { this.lexer.match(','); } else break; } while (true); } return list; } finally { if (debug) dbg_leave("AlertInfoParser.parse"); } } } /* * $Log: AlertInfoParser.java,v $ * Revision 1.10 2009/11/07 23:35:49 mranga * Fix Alert-Info ( loosen up parsing). Define AUTOMATIC_DIALOG_ERROR_HANDLING flag. * * Revision 1.9 2009/10/22 10:27:36 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.8 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.7 2007/10/18 17:48:09 mranga * Issue number: * Obtained from: * Submitted by: mardy * Reviewed by: mranga * Alert info patch to accept non standard alert info headers. * * Revision 1.6 2006/07/13 09:02:19 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.4 2004/01/22 13:26:31 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/AllowEventsParser.java0100644 0000000 0000000 00000013503 13513104763 021766 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import gov.nist.core.*; import java.text.ParseException; /** * Parser for AllowEvents header. * * @version 1.2 $Revision: 1.8 $ $Date: 2009/07/17 18:57:57 $ * * @author Olivier Deruelle * @author M. Ranganathan * * */ public class AllowEventsParser extends HeaderParser { /** * Creates a new instance of AllowEventsParser * @param allowEvents the header to parse */ public AllowEventsParser(String allowEvents) { super(allowEvents); } /** * Constructor * @param lexer the lexer to use to parse the header */ protected AllowEventsParser(Lexer lexer) { super(lexer); } /** * parse the AllowEvents String header * @return SIPHeader (AllowEventsList object) * @throws SIPParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { if (debug) dbg_enter("AllowEventsParser.parse"); AllowEventsList list = new AllowEventsList(); try { headerName(TokenTypes.ALLOW_EVENTS); AllowEvents allowEvents = new AllowEvents(); allowEvents.setHeaderName(SIPHeaderNames.ALLOW_EVENTS); this.lexer.SPorHT(); this.lexer.match(TokenTypes.ID); Token token = lexer.getNextToken(); allowEvents.setEventType(token.getTokenValue()); list.add(allowEvents); this.lexer.SPorHT(); while (lexer.lookAhead(0) == ',') { this.lexer.match(','); this.lexer.SPorHT(); allowEvents = new AllowEvents(); this.lexer.match(TokenTypes.ID); token = lexer.getNextToken(); allowEvents.setEventType(token.getTokenValue()); list.add(allowEvents); this.lexer.SPorHT(); } this.lexer.SPorHT(); this.lexer.match('\n'); return list; } finally { if (debug) dbg_leave("AllowEventsParser.parse"); } } } /* * $Log: AllowEventsParser.java,v $ * Revision 1.8 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.7 2006/07/13 09:02:01 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.5 2004/07/28 14:13:54 mranga * Submitted by: mranga * * Move out the test code to a separate test/unit class. * Fixed some encode methods. * * Revision 1.4 2004/01/22 13:26:31 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/AllowParser.java0100644 0000000 0000000 00000013226 13513104763 020603 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import gov.nist.core.*; import java.text.ParseException; /** * Parser for Allow header. * * @version 1.2 $Revision: 1.8 $ $Date: 2009/07/17 18:57:57 $ * * @author Olivier Deruelle * @author M. Ranganathan * */ public class AllowParser extends HeaderParser { /** * Creates a new instance of AllowParser * @param allow the header to parse */ public AllowParser(String allow) { super(allow); } /** * Constructor * @param lexer the lexer to use to parse the header */ protected AllowParser(Lexer lexer) { super(lexer); } /** * parse the Allow String header * @return SIPHeader (AllowList object) * @throws SIPParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { if (debug) dbg_enter("AllowParser.parse"); AllowList list = new AllowList(); try { headerName(TokenTypes.ALLOW); Allow allow = new Allow(); allow.setHeaderName(SIPHeaderNames.ALLOW); this.lexer.SPorHT(); this.lexer.match(TokenTypes.ID); Token token = lexer.getNextToken(); allow.setMethod(token.getTokenValue()); list.add(allow); this.lexer.SPorHT(); while (lexer.lookAhead(0) == ',') { this.lexer.match(','); this.lexer.SPorHT(); allow = new Allow(); this.lexer.match(TokenTypes.ID); token = lexer.getNextToken(); allow.setMethod(token.getTokenValue()); list.add(allow); this.lexer.SPorHT(); } this.lexer.SPorHT(); this.lexer.match('\n'); return list; } finally { if (debug) dbg_leave("AllowParser.parse"); } } } /* * $Log: AllowParser.java,v $ * Revision 1.8 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.7 2006/07/13 09:01:58 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.5 2004/07/28 14:13:54 mranga * Submitted by: mranga * * Move out the test code to a separate test/unit class. * Fixed some encode methods. * * Revision 1.4 2004/01/22 13:26:31 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/AuthenticationInfoParser.java0100644 0000000 0000000 00000013312 13513104763 023314 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import gov.nist.core.*; import java.text.ParseException; /** * Parser for Authentication-Info header. * * @version 1.2 $Revision: 1.9 $ $Date: 2009/07/17 18:57:57 $ * * @author Olivier Deruelle * @author M. Ranganathan * */ public class AuthenticationInfoParser extends ParametersParser { /** * Creates a new instance of AuthenticationInfoParser * @param authenticationInfo the header to parse */ public AuthenticationInfoParser(String authenticationInfo) { super(authenticationInfo); } /** * Constructor * @param lexer the lexer to use to parse the header */ protected AuthenticationInfoParser(Lexer lexer) { super(lexer); } /** * parse the AuthenticationInfo String header * @return SIPHeader (AuthenticationInfoList object) * @throws SIPParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { if (debug) dbg_enter("AuthenticationInfoParser.parse"); try { headerName(TokenTypes.AUTHENTICATION_INFO); AuthenticationInfo authenticationInfo = new AuthenticationInfo(); authenticationInfo.setHeaderName( SIPHeaderNames.AUTHENTICATION_INFO); this.lexer.SPorHT(); NameValue nv = super.nameValue(); authenticationInfo.setParameter(nv); this.lexer.SPorHT(); while (lexer.lookAhead(0) == ',') { this.lexer.match(','); this.lexer.SPorHT(); nv = super.nameValue(); authenticationInfo.setParameter(nv); this.lexer.SPorHT(); } this.lexer.SPorHT(); //this.lexer.match('\n'); return authenticationInfo; } finally { if (debug) dbg_leave("AuthenticationInfoParser.parse"); } } /* **/ } /* * $Log: AuthenticationInfoParser.java,v $ * Revision 1.9 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.8 2006/07/13 09:02:06 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.6 2004/07/28 14:13:54 mranga * Submitted by: mranga * * Move out the test code to a separate test/unit class. * Fixed some encode methods. * * Revision 1.5 2004/01/22 13:26:31 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/AuthorizationParser.java0100644 0000000 0000000 00000011537 13513104763 022370 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import java.text.ParseException; /** * Parser for authorization headers. * * @version 1.2 $Revision: 1.8 $ $Date: 2009/07/17 18:57:57 $ * * @author Olivier Deruelle * @author M. Ranganathan * * */ public class AuthorizationParser extends ChallengeParser { /** * Constructor * @param authorization Authorization message to parse */ public AuthorizationParser(String authorization) { super(authorization); } /** * Cosntructor * @param lexer Lexer to set */ protected AuthorizationParser(Lexer lexer) { super(lexer); } /** * parse the String message * @return SIPHeader (Authorization object) * @throws SIPParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { dbg_enter("parse"); try { headerName(TokenTypes.AUTHORIZATION); Authorization auth = new Authorization(); super.parse(auth); return auth; } finally { dbg_leave("parse"); } } } /* * $Log: AuthorizationParser.java,v $ * Revision 1.8 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.7 2006/07/13 09:02:22 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.5 2004/07/28 14:13:54 mranga * Submitted by: mranga * * Move out the test code to a separate test/unit class. * Fixed some encode methods. * * Revision 1.4 2004/01/22 13:26:31 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/CSeqParser.java0100644 0000000 0000000 00000016567 13513104763 020373 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import gov.nist.javax.sip.message.SIPRequest; import java.text.ParseException; import javax.sip.*; import gov.nist.core.*; /** * Parser for CSeq headers. * * @version 1.2 $Revision: 1.10 $ $Date: 2006/08/15 21:44:50 $ * * @author M. Ranganathan * @author Olivier Deruelle * */ public class CSeqParser extends HeaderParser { public CSeqParser(String cseq) { super(cseq); } protected CSeqParser(Lexer lexer) { super(lexer); } public SIPHeader parse() throws ParseException { try { CSeq c = new CSeq(); this.lexer.match(TokenTypes.CSEQ); this.lexer.SPorHT(); this.lexer.match(':'); this.lexer.SPorHT(); String number = this.lexer.number(); c.setSeqNumber(Long.parseLong(number)); this.lexer.SPorHT(); String m = SIPRequest.getCannonicalName( method() ); c.setMethod(m); this.lexer.SPorHT(); this.lexer.match('\n'); return c; } catch (NumberFormatException ex) { Debug.printStackTrace(ex); throw createParseException("Number format exception"); } catch (InvalidArgumentException ex) { Debug.printStackTrace(ex); throw createParseException(ex.getMessage()); } } /** * */ } /* * $Log: CSeqParser.java,v $ * 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: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.5 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.4 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.3 2006/05/22 08:16:15 mranga * Added tests for retransmissionAlert flag * Added tests for transaction terminated event * * Revision 1.2 2006/04/17 17:45:01 jeroen * - Using SIPRequest method to canonicalize request name (current code was omitting some) * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.7 2005/04/27 14:12:04 mranga * Submitted by: Mario Mantak * Reviewed by: mranga * * Added a missing "short form" for event header. * * Revision 1.6 2005/04/21 00:01:59 mranga * Issue number: * Obtained from: * Submitted by: mranga * Reviewed by: mranga * * Adjust remote sequence number when sending out a 491 * 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.5 2004/07/28 14:13:54 mranga Submitted * by: mranga * * Move out the test code to a separate test/unit class. Fixed some encode * methods. * * Revision 1.4 2004/01/22 13:26:31 sverker Issue number: Obtained from: * Submitted by: sverker Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and * javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/CallIDParser.java0100644 0000000 0000000 00000012007 13513104763 020611 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import java.text.*; /** Parser for CALL ID header. * * @version 1.2 $Revision: 1.8 $ $Date: 2009/07/17 18:57:58 $ * * @author M. Ranganathan * @author Olivier Deruelle * */ public class CallIDParser extends HeaderParser { /** * Creates new CallIDParser * @param callID message to parse */ public CallIDParser(String callID) { super(callID); } /** * Constructor * @param lexer Lexer to set */ protected CallIDParser(Lexer lexer) { super(lexer); } /** * parse the String message * @return SIPHeader (CallID object) * @throws ParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { if (debug) dbg_enter("parse"); try { this.lexer.match(TokenTypes.CALL_ID); this.lexer.SPorHT(); this.lexer.match(':'); this.lexer.SPorHT(); CallID callID = new CallID(); this.lexer.SPorHT(); String rest = lexer.getRest(); callID.setCallId(rest.trim()); return callID; } finally { if (debug) dbg_leave("parse"); } } /* } */ } /* * $Log: CallIDParser.java,v $ * Revision 1.8 2009/07/17 18:57:58 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.7 2006/07/13 09:02:17 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.5 2004/07/28 14:13:54 mranga * Submitted by: mranga * * Move out the test code to a separate test/unit class. * Fixed some encode methods. * * Revision 1.4 2004/01/22 13:26:31 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/CallInfoParser.java0100644 0000000 0000000 00000014512 13513104763 021213 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import gov.nist.javax.sip.address.*; import java.text.ParseException; /** * Parser for CallInfo header. * * @version 1.2 $Revision: 1.8 $ $Date: 2009/10/22 10:27:36 $ * * @author Olivier Deruelle * @author M. Ranganathan * */ public class CallInfoParser extends ParametersParser{ /** * Creates a new instance of CallInfoParser * @param callInfo the header to parse */ public CallInfoParser(String callInfo) { super(callInfo); } /** * Constructor * @param lexer the lexer to use to parse the header */ protected CallInfoParser(Lexer lexer) { super(lexer); } /** * parse the CallInfo String header * @return SIPHeader (CallInfoList object) * @throws SIPParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { if (debug) dbg_enter("CallInfoParser.parse"); CallInfoList list=new CallInfoList(); try { headerName(TokenTypes.CALL_INFO); while (lexer.lookAhead(0) != '\n') { CallInfo callInfo= new CallInfo(); callInfo.setHeaderName(SIPHeaderNames.CALL_INFO); this.lexer.SPorHT(); this.lexer.match('<'); URLParser urlParser=new URLParser((Lexer)this.lexer); GenericURI uri=urlParser.uriReference(true); callInfo.setInfo(uri); this.lexer.match('>'); this.lexer.SPorHT(); super.parse(callInfo); list.add(callInfo); while (lexer.lookAhead(0) == ',') { this.lexer.match(','); this.lexer.SPorHT(); callInfo= new CallInfo(); this.lexer.SPorHT(); this.lexer.match('<'); urlParser=new URLParser((Lexer)this.lexer); uri=urlParser.uriReference(true); callInfo.setInfo(uri); this.lexer.match('>'); this.lexer.SPorHT(); super.parse(callInfo); list.add(callInfo); } } return list; } finally { if (debug) dbg_leave("CallInfoParser.parse"); } } } /* * $Log: CallInfoParser.java,v $ * Revision 1.8 2009/10/22 10:27:36 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.7 2006/07/13 09:02:15 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.5 2004/07/28 14:13:54 mranga * Submitted by: mranga * * Move out the test code to a separate test/unit class. * Fixed some encode methods. * * Revision 1.4 2004/01/22 13:26:31 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/ChallengeParser.java0100644 0000000 0000000 00000006162 13513104763 021410 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import gov.nist.core.*; import java.text.ParseException; /** * Parser for the challenge portion of the authentication header. * * @version 1.2 $Revision: 1.8 $ $Date: 2009/07/17 18:57:58 $ * @since 1.1 * * @author Olivier Deruelle
    * * */ public abstract class ChallengeParser extends HeaderParser { /** * Constructor * @param String challenge message to parse to set */ protected ChallengeParser(String challenge) { super(challenge); } /** * Constructor * @param String challenge message to parse to set */ protected ChallengeParser(Lexer lexer) { super(lexer); } /** * Get the parameter of the challenge string * @return NameValue containing the parameter */ protected void parseParameter(AuthenticationHeader header) throws ParseException { if (debug) dbg_enter("parseParameter"); try { NameValue nv = this.nameValue('='); header.setParameter(nv); } finally { if (debug) dbg_leave("parseParameter"); } } /** * parser the String message. * @param header - header structure to fill in. * @throws ParseException if the message does not respect the spec. */ public void parse(AuthenticationHeader header) throws ParseException { // the Scheme: this.lexer.SPorHT(); lexer.match(TokenTypes.ID); Token type = lexer.getNextToken(); this.lexer.SPorHT(); header.setScheme(type.getTokenValue()); // The parameters: try { while (lexer.lookAhead(0) != '\n') { this.parseParameter(header); this.lexer.SPorHT(); char la = lexer.lookAhead(0); if (la == '\n' || la == '\0') break; this.lexer.match(','); this.lexer.SPorHT(); } } catch (ParseException ex) { throw ex; } } } java/gov/nist/javax/sip/parser/ContactParser.java0100644 0000000 0000000 00000005542 13513104763 021122 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.address.AddressImpl; import gov.nist.javax.sip.address.SipUri; import gov.nist.javax.sip.header.Contact; import gov.nist.javax.sip.header.ContactList; import gov.nist.javax.sip.header.SIPHeader; import javax.sip.address.URI; import java.text.ParseException; import java.util.HashSet; import java.util.Iterator; /** * A parser for The SIP contact header. * * @version 1.2 $Revision: 1.13 $ $Date: 2009/10/22 10:27:37 $ * @since 1.1 */ public class ContactParser extends AddressParametersParser { public ContactParser(String contact) { super(contact); } protected ContactParser(Lexer lexer) { super(lexer); this.lexer = lexer; } public SIPHeader parse() throws ParseException { // past the header name and the colon. headerName(TokenTypes.CONTACT); ContactList retval = new ContactList(); while (true) { Contact contact = new Contact(); if (lexer.lookAhead(0) == '*') { final char next = lexer.lookAhead(1); if (next == ' ' || next == '\t' || next == '\r' || next == '\n') { this.lexer.match('*'); contact.setWildCardFlag(true); } else { super.parse(contact); } } else { super.parse(contact); } retval.add(contact); this.lexer.SPorHT(); char la = lexer.lookAhead(0); if (la == ',') { this.lexer.match(','); this.lexer.SPorHT(); } else if (la == '\n' || la == '\0') break; else throw createParseException("unexpected char"); } return retval; } } java/gov/nist/javax/sip/parser/ContentDispositionParser.java0100644 0000000 0000000 00000013065 13513104763 023365 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import gov.nist.core.*; import java.text.ParseException; /** * Parser for ContentLanguage header. * * @version 1.2 $Revision: 1.8 $ $Date: 2009/07/17 18:57:58 $ * * @author Olivier Deruelle
    * @author M. Ranganathan
    * * */ public class ContentDispositionParser extends ParametersParser { /** * Creates a new instance of ContentDispositionParser * @param contentDisposition the header to parse */ public ContentDispositionParser(String contentDisposition) { super(contentDisposition); } /** * Constructor * @param lexer the lexer to use to parse the header */ protected ContentDispositionParser(Lexer lexer) { super(lexer); } /** * parse the ContentDispositionHeader String header * @return SIPHeader (ContentDispositionList object) * @throws SIPParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { if (debug) dbg_enter("ContentDispositionParser.parse"); try { headerName(TokenTypes.CONTENT_DISPOSITION); ContentDisposition cd = new ContentDisposition(); cd.setHeaderName(SIPHeaderNames.CONTENT_DISPOSITION); this.lexer.SPorHT(); this.lexer.match(TokenTypes.ID); Token token = lexer.getNextToken(); cd.setDispositionType(token.getTokenValue()); this.lexer.SPorHT(); super.parse(cd); this.lexer.SPorHT(); this.lexer.match('\n'); return cd; } catch (ParseException ex) { throw createParseException(ex.getMessage()); } finally { if (debug) dbg_leave("ContentDispositionParser.parse"); } } } /* * $Log: ContentDispositionParser.java,v $ * Revision 1.8 2009/07/17 18:57:58 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.7 2006/07/13 09:02:15 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.5 2004/07/28 14:13:55 mranga * Submitted by: mranga * * Move out the test code to a separate test/unit class. * Fixed some encode methods. * * Revision 1.4 2004/01/22 13:26:31 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/ContentEncodingParser.java0100644 0000000 0000000 00000014105 13513104763 022603 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import gov.nist.core.*; import java.text.ParseException; /** * Parser for ContentLanguage header. * * @version 1.2 $Revision: 1.8 $ $Date: 2009/07/17 18:57:58 $ * * @author Olivier Deruelle
    * @author M. Ranganathan
    * * * * @version 1.0 */ public class ContentEncodingParser extends HeaderParser { /** * Creates a new instance of ContentEncodingParser * @param contentEncoding the header to parse */ public ContentEncodingParser(String contentEncoding) { super(contentEncoding); } /** * Constructor * @param lexer the lexer to use to parse the header */ protected ContentEncodingParser(Lexer lexer) { super(lexer); } /** * parse the ContentEncodingHeader String header * @return SIPHeader (ContentEncodingList object) * @throws SIPParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { if (debug) dbg_enter("ContentEncodingParser.parse"); ContentEncodingList list = new ContentEncodingList(); try { headerName(TokenTypes.CONTENT_ENCODING); while (lexer.lookAhead(0) != '\n') { ContentEncoding cl = new ContentEncoding(); cl.setHeaderName(SIPHeaderNames.CONTENT_ENCODING); this.lexer.SPorHT(); this.lexer.match(TokenTypes.ID); Token token = lexer.getNextToken(); cl.setEncoding(token.getTokenValue()); this.lexer.SPorHT(); list.add(cl); while (lexer.lookAhead(0) == ',') { cl = new ContentEncoding(); this.lexer.match(','); this.lexer.SPorHT(); this.lexer.match(TokenTypes.ID); this.lexer.SPorHT(); token = lexer.getNextToken(); cl.setEncoding(token.getTokenValue()); this.lexer.SPorHT(); list.add(cl); } } return list; } catch (ParseException ex) { throw createParseException(ex.getMessage()); } finally { if (debug) dbg_leave("ContentEncodingParser.parse"); } } } /* * $Log: ContentEncodingParser.java,v $ * Revision 1.8 2009/07/17 18:57:58 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.7 2006/07/13 09:01:56 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.5 2004/07/28 14:13:55 mranga * Submitted by: mranga * * Move out the test code to a separate test/unit class. * Fixed some encode methods. * * Revision 1.4 2004/01/22 13:26:31 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/ContentLanguageParser.java0100644 0000000 0000000 00000013774 13513104763 022613 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import gov.nist.core.*; import java.text.ParseException; /** * Parser for ContentLanguage header. * * @version 1.2 $Revision: 1.8 $ $Date: 2009/07/17 18:57:58 $ * * @author Olivier Deruelle
    * @author M. Ranganathan
    * * */ public class ContentLanguageParser extends HeaderParser { /** * Creates a new instance of ContentLanguageParser * @param contentLanguage the header to parse */ public ContentLanguageParser(String contentLanguage) { super(contentLanguage); } /** * Constructor * @param lexer the lexer to use to parse the header */ protected ContentLanguageParser(Lexer lexer) { super(lexer); } /** * parse the ContentLanguageHeader String header * @return SIPHeader (ContentLanguageList object) * @throws SIPParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { if (debug) dbg_enter("ContentLanguageParser.parse"); ContentLanguageList list = new ContentLanguageList(); try { headerName(TokenTypes.CONTENT_LANGUAGE); while (lexer.lookAhead(0) != '\n') { this.lexer.SPorHT(); this.lexer.match(TokenTypes.ID); Token token = lexer.getNextToken(); ContentLanguage cl = new ContentLanguage( token.getTokenValue() ); this.lexer.SPorHT(); list.add(cl); while (lexer.lookAhead(0) == ',') { this.lexer.match(','); this.lexer.SPorHT(); this.lexer.match(TokenTypes.ID); this.lexer.SPorHT(); token = lexer.getNextToken(); cl = new ContentLanguage( token.getTokenValue() ); this.lexer.SPorHT(); list.add(cl); } } return list; } catch (ParseException ex) { throw createParseException(ex.getMessage()); } finally { if (debug) dbg_leave("ContentLanguageParser.parse"); } } } /* * $Log: ContentLanguageParser.java,v $ * Revision 1.8 2009/07/17 18:57:58 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.7 2006/07/13 09:02:24 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.4 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.3 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.2 2005/10/16 15:47:41 jeroen * fixed language sub tag handling * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.5 2004/07/28 14:13:55 mranga * Submitted by: mranga * * Move out the test code to a separate test/unit class. * Fixed some encode methods. * * Revision 1.4 2004/01/22 13:26:31 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/ContentLengthParser.java0100644 0000000 0000000 00000012013 13513104763 022272 0ustar000000000 0000000 /* * 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.parser; import javax.sip.*; import gov.nist.javax.sip.header.*; import java.text.ParseException; /** * Parser for Content-Length Header. * @version 1.2 $Revision: 1.8 $ $Date: 2009/07/17 18:57:58 $ * * @author Olivier Deruelle
    * @author M. Ranganathan
    * * * */ public class ContentLengthParser extends HeaderParser { public ContentLengthParser(String contentLength) { super(contentLength); } protected ContentLengthParser(Lexer lexer) { super(lexer); } public SIPHeader parse() throws ParseException { if (debug) dbg_enter("ContentLengthParser.enter"); try { ContentLength contentLength = new ContentLength(); headerName(TokenTypes.CONTENT_LENGTH); String number = this.lexer.number(); contentLength.setContentLength(Integer.parseInt(number)); this.lexer.SPorHT(); this.lexer.match('\n'); return contentLength; } catch (InvalidArgumentException ex) { throw createParseException(ex.getMessage()); } catch (NumberFormatException ex) { throw createParseException(ex.getMessage()); } finally { if (debug) dbg_leave("ContentLengthParser.leave"); } } } /* * $Log: ContentLengthParser.java,v $ * Revision 1.8 2009/07/17 18:57:58 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.7 2006/07/13 09:02:14 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.5 2004/07/28 14:13:55 mranga * Submitted by: mranga * * Move out the test code to a separate test/unit class. * Fixed some encode methods. * * Revision 1.4 2004/01/22 13:26:31 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/ContentTypeParser.java0100644 0000000 0000000 00000005005 13513104763 021775 0ustar000000000 0000000 /* * 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 * * . * */ /* * ContentTypeParser.java * * Created on February 26, 2002, 2:42 PM */ package gov.nist.javax.sip.parser; import gov.nist.core.*; import gov.nist.javax.sip.header.*; import java.text.ParseException; /** * Parser for content type header. * * @version 1.2 $Revision: 1.9 $ $Date: 2009/07/17 18:57:59 $ * * @author M. Ranganathan
    * * */ public class ContentTypeParser extends ParametersParser { public ContentTypeParser(String contentType) { super(contentType); } protected ContentTypeParser(Lexer lexer) { super(lexer); } public SIPHeader parse() throws ParseException { ContentType contentType = new ContentType(); if (debug) dbg_enter("ContentTypeParser.parse"); try { this.headerName(TokenTypes.CONTENT_TYPE); // The type: lexer.match(TokenTypes.ID); Token type = lexer.getNextToken(); this.lexer.SPorHT(); contentType.setContentType(type.getTokenValue()); // The sub-type: lexer.match('/'); lexer.match(TokenTypes.ID); Token subType = lexer.getNextToken(); this.lexer.SPorHT(); contentType.setContentSubType(subType.getTokenValue()); super.parse(contentType); this.lexer.match('\n'); } finally { if (debug) dbg_leave("ContentTypeParser.parse"); } return contentType; } } java/gov/nist/javax/sip/parser/DateParser.java0100644 0000000 0000000 00000004731 13513104763 020403 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import java.util.*; import java.text.ParseException; /** * Parser for SIP Date field. Converts from SIP Date to the * internal storage (Calendar) * * @version 1.2 $Revision: 1.11 $ $Date: 2009/07/17 18:57:59 $ */ public class DateParser extends HeaderParser { /** * Constructor * @param date message to parse to set */ public DateParser(String date) { super(date); } protected DateParser(Lexer lexer) { super(lexer); } /** * Parse method. * @throws ParseException * @return the parsed Date header/ */ public SIPHeader parse() throws ParseException { if (debug) dbg_enter("DateParser.parse"); try { headerName(TokenTypes.DATE); wkday(); lexer.match(','); lexer.match(' '); Calendar cal = date(); lexer.match(' '); time(cal); lexer.match(' '); String tzone = this.lexer.ttoken().toLowerCase(); if (!"gmt".equals(tzone)) throw createParseException("Bad Time Zone " + tzone); this.lexer.match('\n'); SIPDateHeader retval = new SIPDateHeader(); retval.setDate(cal); return retval; } finally { if (debug) dbg_leave("DateParser.parse"); } } } java/gov/nist/javax/sip/parser/ErrorInfoParser.java0100644 0000000 0000000 00000013654 13513104763 021437 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import gov.nist.javax.sip.address.*; import java.text.ParseException; /** * Parser for ErrorInfo header. * * @version 1.2 $Revision: 1.9 $ $Date: 2009/10/22 10:27:37 $ * * @author Olivier Deruelle
    * @author M. Ranganathan
    * * */ public class ErrorInfoParser extends ParametersParser { /** * Creates a new instance of ErrorInfoParser * @param errorInfo the header to parse */ public ErrorInfoParser(String errorInfo) { super(errorInfo); } /** * Constructor * @param lexer the lexer to use to parse the header */ protected ErrorInfoParser(Lexer lexer) { super(lexer); } /** * parse the ErrorInfo String header * @return SIPHeader (ErrorInfoList object) * @throws SIPParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { if (debug) dbg_enter("ErrorInfoParser.parse"); ErrorInfoList list = new ErrorInfoList(); try { headerName(TokenTypes.ERROR_INFO); while (lexer.lookAhead(0) != '\n') { do { ErrorInfo errorInfo = new ErrorInfo(); errorInfo.setHeaderName(SIPHeaderNames.ERROR_INFO); this.lexer.SPorHT(); this.lexer.match('<'); URLParser urlParser = new URLParser((Lexer) this.lexer); GenericURI uri = urlParser.uriReference( true ); errorInfo.setErrorInfo(uri); this.lexer.match('>'); this.lexer.SPorHT(); super.parse(errorInfo); list.add(errorInfo); if ( lexer.lookAhead(0) == ',' ) { this.lexer.match(','); } else break; } while (true); } return list; } finally { if (debug) dbg_leave("ErrorInfoParser.parse"); } } } /* * $Log: ErrorInfoParser.java,v $ * Revision 1.9 2009/10/22 10:27:37 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.8 2009/07/17 18:57:59 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.7 2006/07/13 09:02:17 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.5 2004/08/10 21:35:43 mranga * Reviewed by: mranga * move test cases out to another package * * Revision 1.4 2004/01/22 13:26:31 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/EventParser.java0100644 0000000 0000000 00000012355 13513104763 020610 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import gov.nist.core.*; import java.text.ParseException; /** * Parser for Event header. * * @version 1.2 $Revision: 1.8 $ $Date: 2009/07/17 18:57:59 $ * * @author Olivier Deruelle
    * @author M. Ranganathan
    * * */ public class EventParser extends ParametersParser { /** * Creates a new instance of EventParser * @param event the header to parse */ public EventParser(String event) { super(event); } /** * Cosntructor * @param lexer the lexer to use to parse the header */ protected EventParser(Lexer lexer) { super(lexer); } /** * parse the String message * @return SIPHeader (Event object) * @throws SIPParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { if (debug) dbg_enter("EventParser.parse"); try { headerName(TokenTypes.EVENT); this.lexer.SPorHT(); Event event = new Event(); this.lexer.match(TokenTypes.ID); Token token = lexer.getNextToken(); String value = token.getTokenValue(); event.setEventType(value); super.parse(event); this.lexer.SPorHT(); this.lexer.match('\n'); return event; } catch (ParseException ex) { throw createParseException(ex.getMessage()); } finally { if (debug) dbg_leave("EventParser.parse"); } } } /* * $Log: EventParser.java,v $ * Revision 1.8 2009/07/17 18:57:59 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.7 2006/07/13 09:02:14 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.5 2004/08/10 21:35:43 mranga * Reviewed by: mranga * move test cases out to another package * * Revision 1.4 2004/01/22 13:26:31 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/ExpiresParser.java0100644 0000000 0000000 00000012372 13513104763 021145 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import java.text.ParseException; import javax.sip.*; /** * Parser for SIP Expires Parser. Converts from SIP Date to the * internal storage (Calendar). * * @version 1.2 $Revision: 1.8 $ $Date: 2009/07/17 18:58:00 $ * * @author M. Ranganathan
    * * */ public class ExpiresParser extends HeaderParser { /** * protected constructor. * @param text is the text of the header to parse */ public ExpiresParser(String text) { super(text); } /** * constructor. * @param lexer is the lexer passed in from the enclosing parser. */ protected ExpiresParser(Lexer lexer) { super(lexer); } /** * Parse the header. */ public SIPHeader parse() throws ParseException { Expires expires = new Expires(); if (debug) dbg_enter("parse"); try { lexer.match(TokenTypes.EXPIRES); lexer.SPorHT(); lexer.match(':'); lexer.SPorHT(); String nextId = lexer.getNextId(); lexer.match('\n'); try { int delta = Integer.parseInt(nextId); expires.setExpires(delta); return expires; } catch (NumberFormatException ex) { throw createParseException("bad integer format"); } catch (InvalidArgumentException ex) { throw createParseException(ex.getMessage()); } } finally { if (debug) dbg_leave("parse"); } } } /* * $Log: ExpiresParser.java,v $ * Revision 1.8 2009/07/17 18:58:00 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.7 2006/07/13 09:02:12 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.5 2004/08/10 21:35:44 mranga * Reviewed by: mranga * move test cases out to another package * * Revision 1.4 2004/01/22 13:26:31 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/FromParser.java0100644 0000000 0000000 00000011703 13513104763 020426 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.From; import gov.nist.javax.sip.header.SIPHeader; import java.text.ParseException; /** From header parser. * * @version 1.2 $Revision: 1.12 $ $Date: 2009/10/22 10:27:37 $ * * @author M. Ranganathan
    * * * */ public class FromParser extends AddressParametersParser { public FromParser(String from) { super(from); } protected FromParser(Lexer lexer) { super(lexer); } public SIPHeader parse() throws ParseException { From from = new From(); this.lexer.match(TokenTypes.FROM); this.lexer.SPorHT(); this.lexer.match(':'); this.lexer.SPorHT(); super.parse(from); this.lexer.match('\n'); return from; } } /* * $Log: FromParser.java,v $ * Revision 1.12 2009/10/22 10:27:37 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.11 2009/07/17 18:58:00 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.10 2007/10/23 17:34:55 mranga * Issue number: * Obtained from: * Submitted by: mranga * Reviewed by: mranga * * Refactored header collections. * * Revision 1.9 2006/07/13 09:02:16 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.7 2004/08/10 21:35:44 mranga * Reviewed by: mranga * move test cases out to another package * * Revision 1.6 2004/04/22 22:51:17 mranga * Submitted by: Thomas Froment * Reviewed by: mranga * * Fixed corner cases. * * Revision 1.5 2004/01/22 13:26:31 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/HeaderParser.java0100644 0000000 0000000 00000015012 13513104763 020710 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import java.util.*; import java.text.ParseException; /** * Generic header parser class. The parsers for various headers extend this * class. To create a parser for a new header, extend this class and change * the createParser class. * * @version 1.2 $Revision: 1.9 $ $Date: 2009/07/17 18:58:00 $ * * @author M. Ranganathan
    * * */ public class HeaderParser extends Parser { /** * Parse the weekday field * @return an integer with the calendar content for wkday. */ protected int wkday() throws ParseException { dbg_enter("wkday"); try { String tok = lexer.ttoken(); String id = tok.toLowerCase(); if (TokenNames.MON.equalsIgnoreCase(id)) return Calendar.MONDAY; else if (TokenNames.TUE.equalsIgnoreCase(id)) return Calendar.TUESDAY; else if (TokenNames.WED.equalsIgnoreCase(id)) return Calendar.WEDNESDAY; else if (TokenNames.THU.equalsIgnoreCase(id)) return Calendar.THURSDAY; else if (TokenNames.FRI.equalsIgnoreCase(id)) return Calendar.FRIDAY; else if (TokenNames.SAT.equalsIgnoreCase(id)) return Calendar.SATURDAY; else if (TokenNames.SUN.equalsIgnoreCase(id)) return Calendar.SUNDAY; else throw createParseException("bad wkday"); } finally { dbg_leave("wkday"); } } /** * parse and return a date field. * @return a date structure with the parsed value. */ protected Calendar date() throws ParseException { try { Calendar retval = Calendar.getInstance(TimeZone.getTimeZone("GMT")); String s1 = lexer.number(); int day = Integer.parseInt(s1); if (day <= 0 || day > 31) throw createParseException("Bad day "); retval.set(Calendar.DAY_OF_MONTH, day); lexer.match(' '); String month = lexer.ttoken().toLowerCase(); if (month.equals("jan")) { retval.set(Calendar.MONTH, Calendar.JANUARY); } else if (month.equals("feb")) { retval.set(Calendar.MONTH, Calendar.FEBRUARY); } else if (month.equals("mar")) { retval.set(Calendar.MONTH, Calendar.MARCH); } else if (month.equals("apr")) { retval.set(Calendar.MONTH, Calendar.APRIL); } else if (month.equals("may")) { retval.set(Calendar.MONTH, Calendar.MAY); } else if (month.equals("jun")) { retval.set(Calendar.MONTH, Calendar.JUNE); } else if (month.equals("jul")) { retval.set(Calendar.MONTH, Calendar.JULY); } else if (month.equals("aug")) { retval.set(Calendar.MONTH, Calendar.AUGUST); } else if (month.equals("sep")) { retval.set(Calendar.MONTH, Calendar.SEPTEMBER); } else if (month.equals("oct")) { retval.set(Calendar.MONTH, Calendar.OCTOBER); } else if (month.equals("nov")) { retval.set(Calendar.MONTH, Calendar.NOVEMBER); } else if (month.equals("dec")) { retval.set(Calendar.MONTH, Calendar.DECEMBER); } lexer.match(' '); String s2 = lexer.number(); int yr = Integer.parseInt(s2); retval.set(Calendar.YEAR, yr); return retval; } catch (Exception ex) { throw createParseException("bad date field"); } } /** * Set the time field. This has the format hour:minute:second */ protected void time(Calendar calendar) throws ParseException { try { String s = lexer.number(); int hour = Integer.parseInt(s); calendar.set(Calendar.HOUR_OF_DAY, hour); lexer.match(':'); s = lexer.number(); int min = Integer.parseInt(s); calendar.set(Calendar.MINUTE, min); lexer.match(':'); s = lexer.number(); int sec = Integer.parseInt(s); calendar.set(Calendar.SECOND, sec); } catch (Exception ex) { throw createParseException("error processing time "); } } /** * Creates new HeaderParser * @param String to parse. */ protected HeaderParser(String header) { this.lexer = new Lexer("command_keywordLexer", header); } protected HeaderParser(Lexer lexer) { this.lexer = lexer; this.lexer.selectLexer("command_keywordLexer"); } /** * Parse the SIP header from the buffer and return a parsed * structure. * @throws ParseException if there was an error parsing. */ public SIPHeader parse() throws ParseException { String name = lexer.getNextToken(':'); lexer.consume(1); String body = lexer.getLine().trim(); // we dont set any fields because the header is // ok ExtensionHeaderImpl retval = new ExtensionHeaderImpl(name); retval.setValue(body); return retval; } /** * Parse the header name until the colon and chew WS after that. */ protected void headerName(int tok) throws ParseException { this.lexer.match(tok); this.lexer.SPorHT(); this.lexer.match(':'); this.lexer.SPorHT(); } } java/gov/nist/javax/sip/parser/InReplyToParser.java0100644 0000000 0000000 00000015041 13513104763 021407 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import gov.nist.core.*; import java.text.ParseException; /** * Parser for InReplyTo header. * * @version 1.2 $Revision: 1.8 $ $Date: 2009/07/17 18:58:00 $ * * @author Olivier Deruelle
    * @author M. Ranganathan
    * * */ public class InReplyToParser extends HeaderParser { /** * Creates a new instance of InReplyToParser * @param inReplyTo the header to parse */ public InReplyToParser(String inReplyTo) { super(inReplyTo); } /** * Constructor * @param lexer the lexer to use to parse the header */ protected InReplyToParser(Lexer lexer) { super(lexer); } /** * parse the String message * @return SIPHeader (InReplyToList object) * @throws SIPParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { if (debug) dbg_enter("InReplyToParser.parse"); InReplyToList list = new InReplyToList(); try { headerName(TokenTypes.IN_REPLY_TO); while (lexer.lookAhead(0) != '\n') { InReplyTo inReplyTo = new InReplyTo(); inReplyTo.setHeaderName(SIPHeaderNames.IN_REPLY_TO); this.lexer.match(TokenTypes.ID); Token token = lexer.getNextToken(); if (lexer.lookAhead(0) == '@') { this.lexer.match('@'); this.lexer.match(TokenTypes.ID); Token secToken = lexer.getNextToken(); inReplyTo.setCallId( token.getTokenValue() + "@" + secToken.getTokenValue()); } else { inReplyTo.setCallId(token.getTokenValue()); } this.lexer.SPorHT(); list.add(inReplyTo); while (lexer.lookAhead(0) == ',') { this.lexer.match(','); this.lexer.SPorHT(); inReplyTo = new InReplyTo(); this.lexer.match(TokenTypes.ID); token = lexer.getNextToken(); if (lexer.lookAhead(0) == '@') { this.lexer.match('@'); this.lexer.match(TokenTypes.ID); Token secToken = lexer.getNextToken(); inReplyTo.setCallId( token.getTokenValue() + "@" + secToken.getTokenValue()); } else { inReplyTo.setCallId(token.getTokenValue()); } list.add(inReplyTo); } } return list; } finally { if (debug) dbg_leave("InReplyToParser.parse"); } } } /* * $Log: InReplyToParser.java,v $ * Revision 1.8 2009/07/17 18:58:00 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.7 2006/07/13 09:02:18 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.5 2004/08/10 21:35:44 mranga * Reviewed by: mranga * move test cases out to another package * * Revision 1.4 2004/01/22 13:26:31 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/Lexer.java0100644 0000000 0000000 00000037636 13513104763 017442 0ustar000000000 0000000 /* * 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.parser; import gov.nist.core.*; import gov.nist.javax.sip.header.extensions.*; import gov.nist.javax.sip.header.ims.*; import javax.sip.header.*; import java.util.Hashtable; /** * Lexer class for the parser. * * @version 1.2 * * @author M. Ranganathan
    * * */ public class Lexer extends LexerCore { /** * get the header name of the line * * @return the header name (stuff before the :) bug fix submitted by * zvali@dev.java.net */ public static String getHeaderName(String line) { if (line == null) return null; String headerName = null; try { int begin = line.indexOf(":"); headerName = null; if (begin >= 1) headerName = line.substring(0, begin).trim(); } catch (IndexOutOfBoundsException e) { return null; } return headerName; } public Lexer(String lexerName, String buffer) { super(lexerName, buffer); this.selectLexer(lexerName); } /** * get the header value of the line * * @return String */ public static String getHeaderValue(String line) { if (line == null) return null; String headerValue = null; try { int begin = line.indexOf(":"); headerValue = line.substring(begin + 1); } catch (IndexOutOfBoundsException e) { return null; } return headerValue; } public void selectLexer(String lexerName) { 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); // JvB: added to support RFC3903 addKeyword(TokenNames.PUBLISH, TokenTypes.PUBLISH); } 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: 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); // pmusgrave RFC3891 addKeyword(ReplacesHeader.NAME.toUpperCase(), TokenTypes.REPLACES_TO); //jean deruelle RFC3911 addKeyword(JoinHeader.NAME.toUpperCase(), TokenTypes.JOIN_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); // 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); 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(PUserDatabaseHeader.NAME.toUpperCase(), TokenTypes.P_USER_DATABASE); // added by aayush@rancore addKeyword(PProfileKeyHeader.NAME.toUpperCase(), TokenTypes.P_PROFILE_KEY); // added by aayush@rancore addKeyword(PServedUserHeader.NAME.toUpperCase(), TokenTypes.P_SERVED_USER); // added by aayush@rancore addKeyword(PPreferredServiceHeader.NAME.toUpperCase(), TokenTypes.P_PREFERRED_SERVICE); // 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); } } } } } java/gov/nist/javax/sip/parser/MaxForwardsParser.java0100644 0000000 0000000 00000011642 13513104763 021762 0ustar000000000 0000000 /* * 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.parser; import javax.sip.*; import gov.nist.javax.sip.header.*; import java.text.ParseException; /** * Parser for Max Forwards Header. * * @version 1.2 $Revision: 1.7 $ $Date: 2009/07/17 18:58:00 $ * * @author M. Ranganathan
    * * */ public class MaxForwardsParser extends HeaderParser { public MaxForwardsParser(String contentLength) { super(contentLength); } protected MaxForwardsParser(Lexer lexer) { super(lexer); } public SIPHeader parse() throws ParseException { if (debug) dbg_enter("MaxForwardsParser.enter"); try { MaxForwards contentLength = new MaxForwards(); headerName(TokenTypes.MAX_FORWARDS); String number = this.lexer.number(); contentLength.setMaxForwards(Integer.parseInt(number)); this.lexer.SPorHT(); this.lexer.match('\n'); return contentLength; } catch (InvalidArgumentException ex) { throw createParseException(ex.getMessage()); } catch (NumberFormatException ex) { throw createParseException(ex.getMessage()); } finally { if (debug) dbg_leave("MaxForwardsParser.leave"); } } } /* * $Log: MaxForwardsParser.java,v $ * Revision 1.7 2009/07/17 18:58:00 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.6 2006/07/13 09:02:05 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.4 2004/08/10 21:35:44 mranga * Reviewed by: mranga * move test cases out to another package * * Revision 1.3 2004/01/22 13:26:31 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/MimeVersionParser.java0100644 0000000 0000000 00000012774 13513104763 021771 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import java.text.ParseException; import javax.sip.*; /** * Parser for MimeVersion header. * * @version 1.2 $Revision: 1.8 $ $Date: 2009/07/17 18:58:01 $ * * @author Olivier Deruelle
    * @author M. Ranganathan
    * * */ public class MimeVersionParser extends HeaderParser { /** * Creates a new instance of MimeVersionParser * @param mimeVersion the header to parse */ public MimeVersionParser(String mimeVersion) { super(mimeVersion); } /** * Cosntructor * @param lexer the lexer to use to parse the header */ protected MimeVersionParser(Lexer lexer) { super(lexer); } /** * parse the String message * @return SIPHeader (MimeVersion object) * @throws SIPParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { if (debug) dbg_enter("MimeVersionParser.parse"); MimeVersion mimeVersion = new MimeVersion(); try { headerName(TokenTypes.MIME_VERSION); mimeVersion.setHeaderName(SIPHeaderNames.MIME_VERSION); try { String majorVersion = this.lexer.number(); mimeVersion.setMajorVersion(Integer.parseInt(majorVersion)); this.lexer.match('.'); String minorVersion = this.lexer.number(); mimeVersion.setMinorVersion(Integer.parseInt(minorVersion)); } catch (InvalidArgumentException ex) { throw createParseException(ex.getMessage()); } this.lexer.SPorHT(); this.lexer.match('\n'); return mimeVersion; } finally { if (debug) dbg_leave("MimeVersionParser.parse"); } } } /* * $Log: MimeVersionParser.java,v $ * Revision 1.8 2009/07/17 18:58:01 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.7 2006/07/13 09:02:16 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.5 2004/08/10 21:35:44 mranga * Reviewed by: mranga * move test cases out to another package * * Revision 1.4 2004/01/22 13:26:31 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/MinExpiresParser.java0100644 0000000 0000000 00000012465 13513104763 021614 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import java.text.ParseException; import javax.sip.*; /** * Parser for MinExpires header. * * @version 1.2 $Revision: 1.8 $ $Date: 2009/07/17 18:58:01 $ * * @author Olivier Deruelle
    * @author M. Ranganathan
    * * * * @version 1.0 */ public class MinExpiresParser extends HeaderParser { /** * Creates a new instance of MinExpiresParser * @param minExpires the header to parse */ public MinExpiresParser(String minExpires) { super(minExpires); } /** * Cosntructor * @param lexer the lexer to use to parse the header */ protected MinExpiresParser(Lexer lexer) { super(lexer); } /** * parse the String message * @return SIPHeader (MinExpiresParser) * @throws SIPParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { if (debug) dbg_enter("MinExpiresParser.parse"); MinExpires minExpires = new MinExpires(); try { headerName(TokenTypes.MIN_EXPIRES); minExpires.setHeaderName(SIPHeaderNames.MIN_EXPIRES); String number = this.lexer.number(); try { minExpires.setExpires(Integer.parseInt(number)); } catch (InvalidArgumentException ex) { throw createParseException(ex.getMessage()); } this.lexer.SPorHT(); this.lexer.match('\n'); return minExpires; } finally { if (debug) dbg_leave("MinExpiresParser.parse"); } } } /* * $Log: MinExpiresParser.java,v $ * Revision 1.8 2009/07/17 18:58:01 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.7 2006/07/13 09:02:03 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.5 2004/08/10 21:35:44 mranga * Reviewed by: mranga * move test cases out to another package * * Revision 1.4 2004/01/22 13:26:31 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/OrganizationParser.java0100644 0000000 0000000 00000004772 13513104763 022177 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import java.text.ParseException; /** Parser for Organization header. * * @version 1.2 $Revision: 1.8 $ $Date: 2009/07/17 18:58:01 $ * * @author Olivier Deruelle
    * @author M. Ranganathan
    * * */ public class OrganizationParser extends HeaderParser { /** * Creates a new instance of OrganizationParser * @param organization the header to parse */ public OrganizationParser(String organization) { super(organization); } /** * Constructor * @param lexer the lexer to use to parse the header */ protected OrganizationParser(Lexer lexer) { super(lexer); } /** * parse the String header * @return SIPHeader (Organization object) * @throws SIPParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { if (debug) dbg_enter("OrganizationParser.parse"); Organization organization = new Organization(); try { headerName(TokenTypes.ORGANIZATION); organization.setHeaderName(SIPHeaderNames.ORGANIZATION); this.lexer.SPorHT(); String value = this.lexer.getRest(); organization.setOrganization(value.trim()); return organization; } finally { if (debug) dbg_leave("OrganizationParser.parse"); } } } java/gov/nist/javax/sip/parser/ParametersParser.java0100644 0000000 0000000 00000004705 13513104763 021632 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import gov.nist.core.*; import java.text.ParseException; /** parameters parser header. * * @version 1.2 $Revision: 1.10 $ $Date: 2009/07/17 18:58:01 $ * * @author M. Ranganathan
    * * * */ public abstract class ParametersParser extends HeaderParser { protected ParametersParser(Lexer lexer) { super((Lexer) lexer); } protected ParametersParser(String buffer) { super(buffer); } protected void parse(ParametersHeader parametersHeader) throws ParseException { this.lexer.SPorHT(); while (lexer.lookAhead(0) == ';') { this.lexer.consume(1); // eat white space this.lexer.SPorHT(); NameValue nv = nameValue(); parametersHeader.setParameter(nv); // eat white space this.lexer.SPorHT(); } } protected void parseNameValueList(ParametersHeader parametersHeader) throws ParseException{ parametersHeader.removeParameters(); while (true) { this.lexer.SPorHT(); NameValue nv = nameValue(); parametersHeader.setParameter(nv.getName(), (String) nv.getValueAsObject()); // eat white space this.lexer.SPorHT(); if (lexer.lookAhead(0) != ';') break; else lexer.consume(1); } } } java/gov/nist/javax/sip/parser/ParseExceptionListener.java0100644 0000000 0000000 00000012224 13513104763 023004 0ustar000000000 0000000 /* * 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.javax.sip.parser; import gov.nist.javax.sip.message.*; import java.text.ParseException; /** * A listener interface that enables customization of parse error handling. * An class that implements this interface is registered with the * parser and is called back from the parser handle parse errors. * * @version 1.2 $Revision: 1.7 $ $Date: 2009/07/17 18:58:01 $ */ public interface ParseExceptionListener { /** * This gets called from the parser when a parse error is generated. * The handler is supposed to introspect on the error class and * header name to handle the error appropriately. The error can * be handled by : *
      *
    • 1. Re-throwing an exception and aborting the parse. *
    • 2. Ignoring the header (attach the unparseable header to * the SIPMessage being parsed). *
    • 3. Re-Parsing the bad header and adding it to the sipMessage *
    * * @param ex - parse exception being processed. * @param sipMessage -- sip message being processed. * @param headerText -- header/RL/SL text being parsed. * @param messageText -- message where this header was detected. */ public void handleException( ParseException ex, SIPMessage sipMessage, Class headerClass, String headerText, String messageText) throws ParseException; } /* * $Log: ParseExceptionListener.java,v $ * Revision 1.7 2009/07/17 18:58:01 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.6 2006/07/13 09:01:55 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.4 2004/01/22 13:26:31 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/Parser.java0100644 0000000 0000000 00000020014 13513104763 017575 0ustar000000000 0000000 /* * 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.parser; import gov.nist.core.Debug; import gov.nist.core.LexerCore; import gov.nist.core.ParserCore; import gov.nist.core.Token; import java.text.ParseException; /** * Base parser class. * * @version 1.2 $Revision: 1.10 $ $Date: 2009/07/17 18:58:01 $ * * @author M. Ranganathan
    * * */ public abstract class Parser extends ParserCore implements TokenTypes { protected ParseException createParseException(String exceptionString) { return new ParseException( lexer.getBuffer() + ":" + exceptionString, lexer.getPtr()); } protected Lexer getLexer() { return (Lexer) this.lexer; } protected String sipVersion() throws ParseException { if (debug) dbg_enter("sipVersion"); try { Token tok = lexer.match(SIP); if (!tok.getTokenValue().equalsIgnoreCase("SIP")) createParseException("Expecting SIP"); lexer.match('/'); tok = lexer.match(ID); if (!tok.getTokenValue().equals("2.0")) createParseException("Expecting SIP/2.0"); return "SIP/2.0"; } finally { if (debug) dbg_leave("sipVersion"); } } /** * parses a method. Consumes if a valid method has been found. */ protected String method() throws ParseException { try { if (debug) dbg_enter("method"); Token[] tokens = this.lexer.peekNextToken(1); Token token = (Token) tokens[0]; if (token.getTokenType() == INVITE || token.getTokenType() == ACK || token.getTokenType() == OPTIONS || token.getTokenType() == BYE || token.getTokenType() == REGISTER || token.getTokenType() == CANCEL || token.getTokenType() == SUBSCRIBE || token.getTokenType() == NOTIFY || token.getTokenType() == PUBLISH || token.getTokenType() == MESSAGE || token.getTokenType() == ID) { lexer.consume(); return token.getTokenValue(); } else { throw createParseException("Invalid Method"); } } finally { if (Debug.debug) dbg_leave("method"); } } /** * Verifies that a given string matches the 'token' production in RFC3261 * * @param token * @throws ParseException - if there are invalid characters * * @author JvB */ public static final void checkToken( String token ) throws ParseException { if (token == null || token.length()==0 ) { throw new ParseException("null or empty token", -1 ); } else { // JvB: check that it is a valid token for ( int i=0; i * * * */ public class ParserFactory { private static Hashtable> parserTable; private static Class[] constructorArgs; private static Hashtable parserConstructorCache; static { parserTable = new Hashtable>(); parserConstructorCache = new Hashtable(); constructorArgs = new Class[1]; constructorArgs[0] = String.class; parserTable.put(ReplyToHeader.NAME.toLowerCase(), ReplyToParser.class); parserTable.put( InReplyToHeader.NAME.toLowerCase(), InReplyToParser.class); parserTable.put( AcceptEncodingHeader.NAME.toLowerCase(), AcceptEncodingParser.class); parserTable.put( AcceptLanguageHeader.NAME.toLowerCase(), AcceptLanguageParser.class); parserTable.put("t", ToParser.class); parserTable.put(ToHeader.NAME.toLowerCase(), ToParser.class); parserTable.put(FromHeader.NAME.toLowerCase(), FromParser.class); parserTable.put("f", FromParser.class); parserTable.put(CSeqHeader.NAME.toLowerCase(), CSeqParser.class); parserTable.put(ViaHeader.NAME.toLowerCase(), ViaParser.class); parserTable.put("v", ViaParser.class); parserTable.put(ContactHeader.NAME.toLowerCase(), ContactParser.class); parserTable.put("m", ContactParser.class); parserTable.put( ContentTypeHeader.NAME.toLowerCase(), ContentTypeParser.class); parserTable.put("c", ContentTypeParser.class); parserTable.put( ContentLengthHeader.NAME.toLowerCase(), ContentLengthParser.class); parserTable.put("l", ContentLengthParser.class); parserTable.put( AuthorizationHeader.NAME.toLowerCase(), AuthorizationParser.class); parserTable.put( WWWAuthenticateHeader.NAME.toLowerCase(), WWWAuthenticateParser.class); parserTable.put(CallIdHeader.NAME.toLowerCase(), CallIDParser.class); parserTable.put("i", CallIDParser.class); parserTable.put(RouteHeader.NAME.toLowerCase(), RouteParser.class); parserTable.put( RecordRouteHeader.NAME.toLowerCase(), RecordRouteParser.class); parserTable.put(DateHeader.NAME.toLowerCase(), DateParser.class); parserTable.put( ProxyAuthorizationHeader.NAME.toLowerCase(), ProxyAuthorizationParser.class); parserTable.put( ProxyAuthenticateHeader.NAME.toLowerCase(), ProxyAuthenticateParser.class); parserTable.put( RetryAfterHeader.NAME.toLowerCase(), RetryAfterParser.class); parserTable.put(RequireHeader.NAME.toLowerCase(), RequireParser.class); parserTable.put( ProxyRequireHeader.NAME.toLowerCase(), ProxyRequireParser.class); parserTable.put( TimeStampHeader.NAME.toLowerCase(), TimeStampParser.class); parserTable.put( UnsupportedHeader.NAME.toLowerCase(), UnsupportedParser.class); parserTable.put( UserAgentHeader.NAME.toLowerCase(), UserAgentParser.class); parserTable.put( SupportedHeader.NAME.toLowerCase(), SupportedParser.class); // bug fix by Steve Crosley parserTable.put("k", SupportedParser.class); parserTable.put(ServerHeader.NAME.toLowerCase(), ServerParser.class); parserTable.put(SubjectHeader.NAME.toLowerCase(), SubjectParser.class); parserTable.put( "s", SubjectParser.class); // JvB: added parserTable.put( SubscriptionStateHeader.NAME.toLowerCase(), SubscriptionStateParser.class); parserTable.put( MaxForwardsHeader.NAME.toLowerCase(), MaxForwardsParser.class); parserTable.put( MimeVersionHeader.NAME.toLowerCase(), MimeVersionParser.class); parserTable.put( MinExpiresHeader.NAME.toLowerCase(), MinExpiresParser.class); parserTable.put( OrganizationHeader.NAME.toLowerCase(), OrganizationParser.class); parserTable.put( PriorityHeader.NAME.toLowerCase(), PriorityParser.class); parserTable.put(RAckHeader.NAME.toLowerCase(), RAckParser.class); parserTable.put(RSeqHeader.NAME.toLowerCase(), RSeqParser.class); parserTable.put(ReasonHeader.NAME.toLowerCase(), ReasonParser.class); parserTable.put(WarningHeader.NAME.toLowerCase(), WarningParser.class); parserTable.put(ExpiresHeader.NAME.toLowerCase(), ExpiresParser.class); parserTable.put(EventHeader.NAME.toLowerCase(), EventParser.class); parserTable.put("o", EventParser.class); parserTable.put( ErrorInfoHeader.NAME.toLowerCase(), ErrorInfoParser.class); parserTable.put( ContentLanguageHeader.NAME.toLowerCase(), ContentLanguageParser.class); parserTable.put( ContentEncodingHeader.NAME.toLowerCase(), ContentEncodingParser.class); parserTable.put("e", ContentEncodingParser.class); parserTable.put( ContentDispositionHeader.NAME.toLowerCase(), ContentDispositionParser.class); parserTable.put( CallInfoHeader.NAME.toLowerCase(), CallInfoParser.class); parserTable.put( AuthenticationInfoHeader.NAME.toLowerCase(), AuthenticationInfoParser.class); parserTable.put(AllowHeader.NAME.toLowerCase(), AllowParser.class); parserTable.put( AllowEventsHeader.NAME.toLowerCase(), AllowEventsParser.class); parserTable.put("u", AllowEventsParser.class); parserTable.put( AlertInfoHeader.NAME.toLowerCase(), AlertInfoParser.class); parserTable.put(AcceptHeader.NAME.toLowerCase(), AcceptParser.class); parserTable.put(ReferToHeader.NAME.toLowerCase(), ReferToParser.class); // Was missing (bug noticed by Steve Crossley) parserTable.put("r", ReferToParser.class); // JvB: added to support RFC3903 PUBLISH parserTable.put(SIPETagHeader.NAME.toLowerCase(), SIPETagParser.class); parserTable.put(SIPIfMatchHeader.NAME.toLowerCase(), SIPIfMatchParser.class); //IMS headers parserTable.put(PAccessNetworkInfoHeader.NAME.toLowerCase(), PAccessNetworkInfoParser.class); parserTable.put(PAssertedIdentityHeader.NAME.toLowerCase(), PAssertedIdentityParser.class); parserTable.put(PPreferredIdentityHeader.NAME.toLowerCase(), PPreferredIdentityParser.class); parserTable.put(PChargingVectorHeader.NAME.toLowerCase(), PChargingVectorParser.class); parserTable.put(PChargingFunctionAddressesHeader.NAME.toLowerCase(), PChargingFunctionAddressesParser.class); parserTable.put(PMediaAuthorizationHeader.NAME.toLowerCase(), PMediaAuthorizationParser.class); parserTable.put(PathHeader.NAME.toLowerCase(), PathParser.class); parserTable.put(PrivacyHeader.NAME.toLowerCase(), PrivacyParser.class); parserTable.put(ServiceRouteHeader.NAME.toLowerCase(), ServiceRouteParser.class); parserTable.put(PVisitedNetworkIDHeader.NAME.toLowerCase(), PVisitedNetworkIDParser.class); parserTable.put(PAssociatedURIHeader.NAME.toLowerCase(), PAssociatedURIParser.class); parserTable.put(PCalledPartyIDHeader.NAME.toLowerCase(), PCalledPartyIDParser.class); parserTable.put(SecurityServerHeader.NAME.toLowerCase(), SecurityServerParser.class); parserTable.put(SecurityClientHeader.NAME.toLowerCase(), SecurityClientParser.class); parserTable.put(SecurityVerifyHeader.NAME.toLowerCase(), SecurityVerifyParser.class); // Per RFC 3892 (pmusgrave) parserTable.put(ReferredBy.NAME.toLowerCase(), ReferredByParser.class); parserTable.put("b", ReferToParser.class); // Per RFC4028 Session Timers (pmusgrave) parserTable.put(SessionExpires.NAME.toLowerCase(), SessionExpiresParser.class); parserTable.put("x", SessionExpiresParser.class); parserTable.put(MinSE.NAME.toLowerCase(), MinSEParser.class); // (RFC4028 does not give a short form header for MinSE) // Per RFC3891 (pmusgrave) parserTable.put(Replaces.NAME.toLowerCase(), ReplacesParser.class); // Per RFC3911 (jean deruelle) parserTable.put(Join.NAME.toLowerCase(), JoinParser.class); //http://tools.ietf.org/html/draft-worley-references-05 parserTable.put(References.NAME.toLowerCase(), ReferencesParser.class); } /** * create a parser for a header. This is the parser factory. */ public static HeaderParser createParser(String line) throws ParseException { String headerName = Lexer.getHeaderName(line); String headerValue = Lexer.getHeaderValue(line); if (headerName == null || headerValue == null) throw new ParseException("The header name or value is null", 0); Class parserClass = (Class) parserTable.get(SIPHeaderNamesCache.toLowerCase(headerName)); if (parserClass != null) { try { Constructor cons = (Constructor) parserConstructorCache.get(parserClass); if (cons == null) { cons = parserClass.getConstructor(constructorArgs); parserConstructorCache.put(parserClass, cons); } Object[] args = new Object[1]; args[0] = line; HeaderParser retval = (HeaderParser) cons.newInstance(args); return retval; } catch (Exception ex) { InternalErrorHandler.handleException(ex); return null; // to placate the compiler. } } else { // Just generate a generic SIPHeader. We define // parsers only for the above. return new HeaderParser(line); } } } /* * $Log: ParserFactory.java,v $ * 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. * * Revision 1.15 2009/01/22 19:33:48 deruelle_jean * Add support for JOIN (RFC 3911) * Issue number: 186 * Obtained from: * Submitted by: Jean Deruelle * Reviewed by: Ranga, The high priest and grand poobah of Jain-SIP * * Revision 1.14 2007/03/07 14:29:46 belangery * Yet another bunch of improvements in the parsing code. * * Revision 1.13 2007/02/23 14:56:06 belangery * Added performance improvement around header name lowercase conversion. * * Revision 1.12 2007/01/08 19:24:21 mranga * Issue number: * Obtained from: * Submitted by: Miguel Freitas * Reviewed by: mranga * * Miguel -- please implement a deep clone method for the IMS headers. * * 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.11 2006/10/12 11:57:54 pmusgrave * Issue number: 79, 80 * Submitted by: pmusgrave@newheights.com * Reviewed by: mranga * * Revision 1.10 2006/09/29 19:40:50 jbemmel * fixed missing IMS header parsing plumbing * * Revision 1.9 2006/09/11 18:41:32 mranga * Issue number: * Obtained from: * Submitted by: mranga * Reviewed by: * Tighter integration of IMS headers. * 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.8 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.7 2006/07/13 09:02:06 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.5 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.4 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.3 2005/10/27 20:49:00 jeroen * added support for RFC3903 PUBLISH * * Revision 1.2 2005/10/14 19:59:00 jeroen * bugfix: missing parser for shortform of Subject (s) * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.4 2005/04/04 09:29:03 dmuresan * Replaced new String().getClass() with String.class. * * Revision 1.3 2004/01/22 13:26:31 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/Pipeline.java0100644 0000000 0000000 00000013277 13513104763 020123 0ustar000000000 0000000 /* * 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.parser; import gov.nist.core.InternalErrorHandler; import gov.nist.javax.sip.stack.SIPStackTimerTask; import java.io.*; import java.util.*; /** * Input class for the pipelined parser. Buffer all bytes read from the socket * and make them available to the message parser. * * @author M. Ranganathan (Contains a bug fix contributed by Rob Daugherty ( * Lucent Technologies) ) * */ public class Pipeline extends InputStream { private LinkedList buffList; private Buffer currentBuffer; private boolean isClosed; private Timer timer; private InputStream pipe; private int readTimeout; private TimerTask myTimerTask; class MyTimer extends SIPStackTimerTask { Pipeline pipeline; private boolean isCancelled; protected MyTimer(Pipeline pipeline) { this.pipeline = pipeline; } protected void runTask() { if (this.isCancelled) return; try { pipeline.close(); } catch (IOException ex) { InternalErrorHandler.handleException(ex); } } public boolean cancel() { boolean retval = super.cancel(); this.isCancelled = true; return retval; } } class Buffer { byte[] bytes; int length; int ptr; public Buffer(byte[] bytes, int length) { ptr = 0; this.length = length; this.bytes = bytes; } public int getNextByte() { int retval = bytes[ptr++] & 0xFF; return retval; } } public void startTimer() { if (this.readTimeout == -1) return; // TODO make this a tunable number. For now 4 seconds // between reads seems reasonable upper limit. this.myTimerTask = new MyTimer(this); this.timer.schedule(this.myTimerTask, this.readTimeout); } public void stopTimer() { if (this.readTimeout == -1) return; if (this.myTimerTask != null) this.myTimerTask.cancel(); } public Pipeline(InputStream pipe, int readTimeout, Timer timer) { // pipe is the Socket stream // this is recorded here to implement a timeout. this.timer = timer; this.pipe = pipe; buffList = new LinkedList(); this.readTimeout = readTimeout; } public void write(byte[] bytes, int start, int length) throws IOException { if (this.isClosed) throw new IOException("Closed!!"); Buffer buff = new Buffer(bytes, length); buff.ptr = start; synchronized (this.buffList) { buffList.add(buff); buffList.notifyAll(); } } public void write(byte[] bytes) throws IOException { if (this.isClosed) throw new IOException("Closed!!"); Buffer buff = new Buffer(bytes, bytes.length); synchronized (this.buffList) { buffList.add(buff); buffList.notifyAll(); } } public void close() throws IOException { this.isClosed = true; synchronized (this.buffList) { this.buffList.notifyAll(); } // JvB: added this.pipe.close(); } public int read() throws IOException { // if (this.isClosed) return -1; synchronized (this.buffList) { if (currentBuffer != null && currentBuffer.ptr < currentBuffer.length) { int retval = currentBuffer.getNextByte(); if (currentBuffer.ptr == currentBuffer.length) this.currentBuffer = null; return retval; } // Bug fix contributed by Rob Daugherty. if (this.isClosed && this.buffList.isEmpty()) return -1; try { // wait till something is posted. while (this.buffList.isEmpty()) { this.buffList.wait(); if (this.isClosed) return -1; } currentBuffer = (Buffer) this.buffList.removeFirst(); int retval = currentBuffer.getNextByte(); if (currentBuffer.ptr == currentBuffer.length) this.currentBuffer = null; return retval; } catch (InterruptedException ex) { throw new IOException(ex.getMessage()); } catch (NoSuchElementException ex) { ex.printStackTrace(); throw new IOException(ex.getMessage()); } } } } java/gov/nist/javax/sip/parser/PipelinedMsgParser.java0100644 0000000 0000000 00000046037 13513104763 022113 0ustar000000000 0000000 /* * 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.javax.sip.parser; /* * * Lamine Brahimi and Yann Duponchel (IBM Zurich) noticed that the parser was * blocking so I threw out some cool pipelining which ran fast but only worked * when the phase of the moon matched its mood. Now things are serialized and * life goes slower but more reliably. * */ import gov.nist.core.*; import gov.nist.javax.sip.message.*; import gov.nist.javax.sip.header.*; import java.text.ParseException; import java.io.*; /** * This implements a pipelined message parser suitable for use with a stream - * oriented input such as TCP. The client uses this class by instatiating with * an input stream from which input is read and fed to a message parser. It * keeps reading from the input stream and process messages in a never ending * interpreter loop. The message listener interface gets called for processing * messages or for processing errors. The payload specified by the * content-length header is read directly from the input stream. This can be * accessed from the SIPMessage using the getContent and getContentBytes methods * provided by the SIPMessage class. * * @version 1.2 $Revision: 1.23 $ $Date: 2009/08/16 17:28:28 $ * * @author M. Ranganathan * * @see SIPMessageListener */ public final class PipelinedMsgParser implements Runnable { /** * The message listener that is registered with this parser. (The message * listener has methods that can process correct and erroneous messages.) */ protected SIPMessageListener sipMessageListener; private Thread mythread; // Preprocessor thread //private byte[] messageBody; //private boolean errorFlag; private Pipeline rawInputStream; private int maxMessageSize; private int sizeCounter; //private int messageSize; /** * default constructor. */ protected PipelinedMsgParser() { super(); } private static int uid = 0; private static synchronized int getNewUid() { return uid++; } /** * Constructor when we are given a message listener and an input stream * (could be a TCP connection or a file) * * @param sipMessageListener * Message listener which has methods that get called back from * the parser when a parse is complete * @param in * Input stream from which to read the input. * @param debug * Enable/disable tracing or lexical analyser switch. */ public PipelinedMsgParser(SIPMessageListener sipMessageListener, Pipeline in, boolean debug, int maxMessageSize) { this(); this.sipMessageListener = sipMessageListener; rawInputStream = in; this.maxMessageSize = maxMessageSize; mythread = new Thread(this); mythread.setName("PipelineThread-" + getNewUid()); } /** * This is the constructor for the pipelined parser. * * @param mhandler * a SIPMessageListener implementation that provides the message * handlers to handle correctly and incorrectly parsed messages. * @param in * An input stream to read messages from. */ public PipelinedMsgParser(SIPMessageListener mhandler, Pipeline in, int maxMsgSize) { this(mhandler, in, false, maxMsgSize); } /** * This is the constructor for the pipelined parser. * * @param in - * An input stream to read messages from. */ public PipelinedMsgParser(Pipeline in) { this(null, in, false, 0); } /** * Start reading and processing input. */ public void processInput() { mythread.start(); } /** * Create a new pipelined parser from an existing one. * * @return A new pipelined parser that reads from the same input stream. */ protected Object clone() { PipelinedMsgParser p = new PipelinedMsgParser(); p.rawInputStream = this.rawInputStream; p.sipMessageListener = this.sipMessageListener; Thread mythread = new Thread(p); mythread.setName("PipelineThread"); return p; } /** * Add a class that implements a SIPMessageListener interface whose methods * get called * on successful parse and error conditons. * * @param mlistener * a SIPMessageListener implementation that can react to correct * and incorrect pars. */ public void setMessageListener(SIPMessageListener mlistener) { sipMessageListener = mlistener; } /** * read a line of input (I cannot use buffered reader because we may need to * switch encodings mid-stream! */ private String readLine(InputStream inputStream) throws IOException { StringBuffer retval = new StringBuffer(""); while (true) { char ch; int i = inputStream.read(); if (i == -1) { throw new IOException("End of stream"); } else ch = (char) i; // reduce the available read size by 1 ("size" of a char). if (this.maxMessageSize > 0) { this.sizeCounter--; if (this.sizeCounter <= 0) throw new IOException("Max size exceeded!"); } if (ch != '\r') retval.append(ch); if (ch == '\n') { break; } } return retval.toString(); } /** * This is input reading thread for the pipelined parser. You feed it input * through the input stream (see the constructor) and it calls back an event * listener interface for message processing or error. It cleans up the * input - dealing with things like line continuation */ public void run() { Pipeline inputStream = this.rawInputStream; // inputStream = new MyFilterInputStream(this.rawInputStream); // I cannot use buffered reader here because we may need to switch // encodings to read the message body. try { while (true) { this.sizeCounter = this.maxMessageSize; // this.messageSize = 0; StringBuffer inputBuffer = new StringBuffer(); if (Debug.parserDebug) Debug.println("Starting parse!"); String line1; String line2 = null; while (true) { try { line1 = readLine(inputStream); // ignore blank lines. if (line1.equals("\n")) { if (Debug.parserDebug) { Debug.println("Discarding blank line. "); } continue; } else break; } catch (IOException ex) { Debug.printStackTrace(ex); this.rawInputStream.stopTimer(); return; } } inputBuffer.append(line1); // Guard against bad guys. this.rawInputStream.startTimer(); Debug.println("Reading Input Stream"); while (true) { try { line2 = readLine(inputStream); inputBuffer.append(line2); if (line2.trim().equals("")) break; } catch (IOException ex) { this.rawInputStream.stopTimer(); Debug.printStackTrace(ex); return; } } // Stop the timer that will kill the read. this.rawInputStream.stopTimer(); inputBuffer.append(line2); StringMsgParser smp = new StringMsgParser(sipMessageListener); smp.readBody = false; SIPMessage sipMessage = null; try { if (Debug.debug) { Debug.println("About to parse : " + inputBuffer.toString()); } sipMessage = smp.parseSIPMessage(inputBuffer.toString()); if (sipMessage == null) { this.rawInputStream.stopTimer(); continue; } } catch (ParseException ex) { // Just ignore the parse exception. Debug.logError("Detected a parse error", ex); continue; } if (Debug.debug) { Debug.println("Completed parsing message"); } ContentLength cl = (ContentLength) sipMessage .getContentLength(); int contentLength = 0; if (cl != null) { contentLength = cl.getContentLength(); } else { contentLength = 0; } if (Debug.debug) { Debug.println("contentLength " + contentLength); } if (contentLength == 0) { sipMessage.removeContent(); } else if (maxMessageSize == 0 || contentLength < this.sizeCounter) { byte[] message_body = new byte[contentLength]; int nread = 0; while (nread < contentLength) { // Start my starvation timer. // This ensures that the other end // writes at least some data in // or we will close the pipe from // him. This prevents DOS attack // that takes up all our connections. this.rawInputStream.startTimer(); try { int readlength = inputStream.read(message_body, nread, contentLength - nread); if (readlength > 0) { nread += readlength; } else { break; } } catch (IOException ex) { Debug.logError("Exception Reading Content",ex); break; } finally { // Stop my starvation timer. this.rawInputStream.stopTimer(); } } sipMessage.setMessageContent(message_body); } // Content length too large - process the message and // return error from there. if (sipMessageListener != null) { try { sipMessageListener.processMessage(sipMessage); } catch (Exception ex) { // fatal error in processing - close the // connection. break; } } } } finally { try { inputStream.close(); } catch (IOException e) { InternalErrorHandler.handleException(e); } } } public void close() { try { this.rawInputStream.close(); } catch (IOException ex) { // Ignore. } } } /* * $Log: PipelinedMsgParser.java,v $ * Revision 1.23 2009/08/16 17:28:28 mranga * Issue number: 208 * Obtained from: * Submitted by: * Reviewed by: * * Add authentication mechanism that uses H(username:domain:password) * * Revision 1.22 2009/07/17 18:58:02 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.21 2008/05/24 04:10:01 mranga * * Issue number: 158 * Obtained from: * Submitted by: * Reviewed by: mranga * * Deliver tx timeout for Canceled INVITE. Fix pipeline thread exit. * * Revision 1.20 2008/05/22 19:38:07 jbemmel * Fix for issue 149: the logic wasn't always closing the internal socket pipe, * causing the pipe reader thread to block indefinitely * * Repeatedly starting/stopping the stack then gives hanging threads * Revision 1.19 2007/01/28 13:06:21 mranga * Issue number: 99 Obtained from: Submitted by: Reviewed by: mranga * * Fixed PRACK handling null pointer exception (for proxy case) and cleanup of * unused variables. * * 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.18 2006/07/13 09:02:10 mranga Issue number: Obtained from: * Submitted by: jeroen van bemmel Reviewed by: mranga Moved some changes from * jain-sip-1.2 to java.net * * 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.4 2006/06/19 06:47:27 mranga javadoc fixups * * Revision 1.3 2006/06/17 10:18:14 mranga Added some synchronization to the * sequence number checking. Small javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga Added NIST disclaimer to all public * domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.16 2004/11/30 23:28:14 mranga Issue number: 44 Submitted by: Rob * Daugherty Reviewed by: M. Ranganathan * * TCP Pipelining truncates content when other end of pipe is closed. * * Revision 1.15 2004/05/30 18:55:56 mranga Reviewed by: mranga Move to timers * and eliminate the Transaction scanner Thread to improve scalability and * reduce cpu usage. * * Revision 1.14 2004/05/16 14:13:22 mranga Reviewed by: mranga Fixed the * use-count issue reported by Peter Parnes. Added property to prevent against * content-length dos attacks. * * Revision 1.13 2004/03/19 04:22:22 mranga Reviewed by: mranga Added IO Pacing * for long writes - split write into chunks and flush after each chunk to avoid * socket back pressure. * * Revision 1.12 2004/03/18 22:01:19 mranga Reviewed by: mranga Get rid of the * PipedInputStream from pipelined parser to avoid a copy. * * Revision 1.11 2004/03/07 22:25:23 mranga Reviewed by: mranga Added a new * configuration parameter that instructs the stack to drop a server connection * after server transaction termination set * gov.nist.javax.sip.CACHE_SERVER_CONNECTIONS=false for this Default behavior * is true. * * Revision 1.10 2004/02/29 15:32:58 mranga Reviewed by: mranga bug fixes on * limiting the max message size. * * Revision 1.9 2004/02/29 00:46:34 mranga Reviewed by: mranga Added new * configuration property to limit max message size for TCP transport. The * property is gov.nist.javax.sip.MAX_MESSAGE_SIZE * * Revision 1.8 2004/02/25 21:43:03 mranga Reviewed by: mranga Added a couple of * todo's and removed some debug printlns that could slow code down by a bit. * * Revision 1.7 2004/02/25 20:52:46 mranga Reviewed by: mranga Fix TCP transport * so messages in excess of 8192 bytes are accepted. * * Revision 1.6 2004/01/22 18:39:41 mranga Reviewed by: M. Ranganathan Moved the * ifdef SIMULATION and associated tags to the first column so Prep preprocessor * can deal with them. * * Revision 1.5 2004/01/22 14:23:45 mranga Reviewed by: mranga Fixed some minor * formatting issues. * * Revision 1.4 2004/01/22 13:26:31 sverker Issue number: Obtained from: * Submitted by: sverker Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and * javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/PriorityParser.java0100644 0000000 0000000 00000006163 13513104763 021350 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import gov.nist.core.*; import java.text.ParseException; /** * Parser for Priority header. * * @version 1.2 $Revision: 1.8 $ $Date: 2009/07/17 18:58:02 $ * * @author Olivier Deruelle
    * @author M. Ranganathan
    * * * * @version 1.0 */ public class PriorityParser extends HeaderParser { /** * Creates a new instance of PriorityParser * @param priority the header to parse */ public PriorityParser(String priority) { super(priority); } /** * Constructor * @param lexer the lexer to use to parse the header */ protected PriorityParser(Lexer lexer) { super(lexer); } /** * parse the String header * @return SIPHeader (Priority object) * @throws SIPParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { if (debug) dbg_enter("PriorityParser.parse"); Priority priority = new Priority(); try { headerName(TokenTypes.PRIORITY); priority.setHeaderName(SIPHeaderNames.PRIORITY); this.lexer.SPorHT(); /*this.lexer.match(TokenTypes.ID); Token token = lexer.getNextToken(); priority.setPriority(token.getTokenValue()); */ // This is in violation of the RFC but // let us be generous in what we accept. priority.setPriority(this.lexer.ttokenSafe()); this.lexer.SPorHT(); this.lexer.match('\n'); return priority; } finally { if (debug) dbg_leave("PriorityParser.parse"); } } public static void main(String args[]) throws ParseException { String p[] = { "Priority: 8;a\n" }; for (int i = 0; i < p.length; i++ ) { PriorityParser parser = new PriorityParser(p[i]); Priority prio= (Priority) parser.parse(); System.out.println("encoded = " + prio.encode()); } } } java/gov/nist/javax/sip/parser/ProxyAuthenticateParser.java0100644 0000000 0000000 00000012462 13513104763 023206 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import java.text.ParseException; /** * Parser for ProxyAuthenticate headers. * * @version 1.2 $Revision: 1.7 $ $Date: 2009/07/17 18:58:02 $ * * @author M. Ranganathan
    * * */ public class ProxyAuthenticateParser extends ChallengeParser { /** * Constructor * @param proxyAuthenticate message to parse */ public ProxyAuthenticateParser(String proxyAuthenticate) { super(proxyAuthenticate); } /** * Cosntructor * @param Lexer lexer to set */ protected ProxyAuthenticateParser(Lexer lexer) { super(lexer); } /** * parse the String message * @return SIPHeader (ProxyAuthenticate object) * @throws ParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { headerName(TokenTypes.PROXY_AUTHENTICATE); ProxyAuthenticate proxyAuthenticate = new ProxyAuthenticate(); super.parse(proxyAuthenticate); return proxyAuthenticate; } /** Test program public static void main(String args[]) throws ParseException { String paAuth[] = { "Proxy-Authenticate: Digest realm=\"MCI WorldCom SIP\","+ "domain=\"sip:ss2.wcom.com\", nonce=\"ea9c8e88df84f1cec4341ae6cbe5a359\","+ "opaque=\"\", stale=FALSE, algorithm=MD5\n", "Proxy-Authenticate: Digest realm=\"MCI WorldCom SIP\","+ "qop=\"auth\" , nonce-value=\"oli\"\n" }; for (int i = 0; i < paAuth.length; i++ ) { ProxyAuthenticateParser pap = new ProxyAuthenticateParser(paAuth[i]); ProxyAuthenticate pa= (ProxyAuthenticate) pap.parse(); System.out.println("encoded = " + pa.encode()); } } */ } /* * $Log: ProxyAuthenticateParser.java,v $ * Revision 1.7 2009/07/17 18:58:02 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.6 2006/07/13 09:02:17 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.4 2004/01/22 13:26:31 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/ProxyAuthorizationParser.java0100644 0000000 0000000 00000013144 13513104763 023426 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import java.text.ParseException; /** * Parser for ProxyAuthorization headers. * * @version 1.2 $Revision: 1.7 $ $Date: 2009/07/17 18:58:02 $ * * @author M. Ranganathan
    * * * */ public class ProxyAuthorizationParser extends ChallengeParser { /** * Constructor * @param proxyAuthorization -- header to parse */ public ProxyAuthorizationParser(String proxyAuthorization) { super(proxyAuthorization); } /** * Cosntructor * @param Lexer lexer to set */ protected ProxyAuthorizationParser(Lexer lexer) { super(lexer); } /** * parse the String message * @return SIPHeader (ProxyAuthenticate object) * @throws ParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { headerName(TokenTypes.PROXY_AUTHORIZATION); ProxyAuthorization proxyAuth = new ProxyAuthorization(); super.parse(proxyAuth); return proxyAuth; } /** public static void main(String args[]) throws ParseException { String paAuth[] = { "Proxy-Authorization: Digest realm=\"MCI WorldCom SIP\","+ "domain=\"sip:ss2.wcom.com\",nonce=\"ea9c8e88df84f1cec4341ae6cbe5a359\","+ "opaque=\"\",stale=FALSE,algorithm=MD5\n", "Proxy-Authorization: Digest realm=\"MCI WorldCom SIP\","+ "qop=\"auth\" , nonce-value=\"oli\"\n" }; for (int i = 0; i < paAuth.length; i++ ) { ProxyAuthorizationParser pap = new ProxyAuthorizationParser(paAuth[i]); ProxyAuthorization pa= (ProxyAuthorization) pap.parse(); String encoded = pa.encode(); System.out.println ("original = \n" + paAuth[i]); System.out.println("encoded = \n" + encoded); pap = new ProxyAuthorizationParser(encoded.trim() + "\n"); pap.parse(); } } **/ } /* * $Log: ProxyAuthorizationParser.java,v $ * Revision 1.7 2009/07/17 18:58:02 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.6 2006/07/13 09:02:18 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.4 2005/02/24 16:13:11 mranga * Submitted by: mranga * Reviewed by: mranga * Just some additional testing on the parser. * * Revision 1.3 2004/01/22 13:26:31 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/ProxyRequireParser.java0100644 0000000 0000000 00000014272 13513104763 022205 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import gov.nist.core.*; import java.text.ParseException; /** * Parser for ProxyRequire header. * @version 1.2 $Revision: 1.7 $ $Date: 2009/07/17 18:58:02 $ * * @author Olivier Deruelle
    * @author M. Ranganathan
    * * */ public class ProxyRequireParser extends HeaderParser { /** * Creates a new instance of ProxyRequireParser * @param require the header to parse */ public ProxyRequireParser(String require) { super(require); } /** * Constructor * @param lexer the lexer to use to parse the header */ protected ProxyRequireParser(Lexer lexer) { super(lexer); } /** * parse the String message * @return SIPHeader (ProxyRequireList object) * @throws SIPParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { ProxyRequireList list = new ProxyRequireList(); if (debug) dbg_enter("ProxyRequireParser.parse"); try { headerName(TokenTypes.PROXY_REQUIRE); while (lexer.lookAhead(0) != '\n') { ProxyRequire r = new ProxyRequire(); r.setHeaderName(SIPHeaderNames.PROXY_REQUIRE); // Parsing the option tag this.lexer.match(TokenTypes.ID); Token token = lexer.getNextToken(); r.setOptionTag(token.getTokenValue()); this.lexer.SPorHT(); list.add(r); while (lexer.lookAhead(0) == ',') { this.lexer.match(','); this.lexer.SPorHT(); r = new ProxyRequire(); // Parsing the option tag this.lexer.match(TokenTypes.ID); token = lexer.getNextToken(); r.setOptionTag(token.getTokenValue()); this.lexer.SPorHT(); list.add(r); } } } finally { if (debug) dbg_leave("ProxyRequireParser.parse"); } return list; } /** Test program public static void main(String args[]) throws ParseException { String r[] = { "Proxy-Require: foo \n", "Proxy-Require: foo1, foo2 , 389\n" }; for (int i = 0; i < r.length; i++ ) { ProxyRequireParser parser = new ProxyRequireParser(r[i]); ProxyRequireList rl= (ProxyRequireList) parser.parse(); System.out.println("encoded = " + rl.encode()); } } */ } /* * $Log: ProxyRequireParser.java,v $ * Revision 1.7 2009/07/17 18:58:02 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.6 2006/07/13 09:02:15 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.4 2004/01/22 13:26:31 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/RAckParser.java0100644 0000000 0000000 00000015574 13513104763 020355 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import gov.nist.core.*; import java.text.ParseException; import javax.sip.*; /** * Parser for RAck header. * * @version 1.2 $Revision: 1.8 $ $Date: 2009/07/17 18:58:02 $ * * @author Olivier Deruelle
    * @author M. Ranganathan
    * * * * @version 1.0 */ public class RAckParser extends HeaderParser { /** * Creates a new instance of RAckParser * @param rack the header to parse */ public RAckParser(String rack) { super(rack); } /** * Constructor * @param lexer the lexer to use to parse the header */ protected RAckParser(Lexer lexer) { super(lexer); } /** * parse the String message * @return SIPHeader (RAck object) * @throws SIPParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { if (debug) dbg_enter("RAckParser.parse"); RAck rack = new RAck(); try { headerName(TokenTypes.RACK); rack.setHeaderName(SIPHeaderNames.RACK); try { String number = this.lexer.number(); rack.setRSequenceNumber(Long.parseLong(number)); this.lexer.SPorHT(); number = this.lexer.number(); rack.setCSequenceNumber(Long.parseLong(number)); this.lexer.SPorHT(); this.lexer.match(TokenTypes.ID); Token token = lexer.getNextToken(); rack.setMethod(token.getTokenValue()); } catch (InvalidArgumentException ex) { throw createParseException(ex.getMessage()); } this.lexer.SPorHT(); this.lexer.match('\n'); return rack; } finally { if (debug) dbg_leave("RAckParser.parse"); } } /** Test program public static void main(String args[]) throws ParseException { String r[] = { "RAck: 776656 1 INVITE\n" }; for (int i = 0; i < r.length; i++ ) { RAckParser parser = new RAckParser(r[i]); RAck ra= (RAck) parser.parse(); System.out.println("encoded = " + ra.encode()); } } */ } /* * $Log: RAckParser.java,v $ * Revision 1.8 2009/07/17 18:58:02 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.7 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.6 2006/07/13 09:02:24 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.4 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.3 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.2 2006/05/24 06:21:43 mranga * change to use the long setter * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.4 2004/01/22 13:26:31 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/RSeqParser.java0100644 0000000 0000000 00000014753 13513104763 020405 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import java.text.ParseException; import javax.sip.*; /** * Parser for RSeq header. * * @version 1.2 $Revision: 1.8 $ $Date: 2009/07/17 18:58:03 $ * * @author Olivier Deruelle
    * @author M. Ranganathan
    * * */ public class RSeqParser extends HeaderParser { /** * Creates a new instance of RSeqParser * @param rseq the header to parse */ public RSeqParser(String rseq) { super(rseq); } /** * Constructor * param lexer the lexer to use to parse the header */ protected RSeqParser(Lexer lexer) { super(lexer); } /** * parse the String message * @return SIPHeader ( RSeq object) * @throws SIPParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { if (debug) dbg_enter("RSeqParser.parse"); RSeq rseq = new RSeq(); try { headerName(TokenTypes.RSEQ); rseq.setHeaderName(SIPHeaderNames.RSEQ); String number = this.lexer.number(); try { rseq.setSeqNumber(Long.parseLong(number)); } catch (InvalidArgumentException ex) { throw createParseException(ex.getMessage()); } this.lexer.SPorHT(); this.lexer.match('\n'); return rseq; } finally { if (debug) dbg_leave("RSeqParser.parse"); } } /** Test program public static void main(String args[]) throws ParseException { String r[] = { "RSeq: 988789 \n" }; for (int i = 0; i < r.length; i++ ) { RSeqParser parser = new RSeqParser(r[i]); RSeq rs= (RSeq) parser.parse(); System.out.println("encoded = " + rs.encode()); } } */ } /* * $Log: RSeqParser.java,v $ * Revision 1.8 2009/07/17 18:58:03 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.7 2006/08/15 21:44:49 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.6 2006/07/13 09:01:53 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.4 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.3 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.2 2006/05/24 06:21:43 mranga * change to use the long setter * * Revision 1.1.1.1 2005/10/04 17:12:36 mranga * * Import * * * Revision 1.4 2004/01/22 13:26:31 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/ReasonParser.java0100644 0000000 0000000 00000014161 13513104763 020753 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import gov.nist.core.*; import java.text.ParseException; /** * Parser for Reason header. * * @version 1.2 * * @author Olivier Deruelle
    * @author M. Ranganathan
    * * */ public class ReasonParser extends ParametersParser { /** * Creates a new instance of ReasonParser * @param reason the header to parse */ public ReasonParser(String reason) { super(reason); } /** * Constructor * @param lexer the lexer to use to parse the header */ protected ReasonParser(Lexer lexer) { super(lexer); } /** * parse the String message * @return SIPHeader (ReasonParserList object) * @throws SIPParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { ReasonList reasonList = new ReasonList(); if (debug) dbg_enter("ReasonParser.parse"); try { headerName(TokenTypes.REASON); this.lexer.SPorHT(); while (lexer.lookAhead(0) != '\n') { Reason reason = new Reason(); this.lexer.match(TokenTypes.ID); Token token = lexer.getNextToken(); String value = token.getTokenValue(); reason.setProtocol(value); super.parse(reason); reasonList.add(reason); if (lexer.lookAhead(0) == ',') { this.lexer.match(','); this.lexer.SPorHT(); } else this.lexer.SPorHT(); } } finally { if (debug) dbg_leave("ReasonParser.parse"); } return reasonList; } /** Test program public static void main(String args[]) throws ParseException { String r[] = { "Reason: SIP ;cause=200 ;text=\"Call completed elsewhere\"\n", "Reason: Q.850 ;cause=16 ;text=\"Terminated\"\n", "Reason: SIP ;cause=600 ;text=\"Busy Everywhere\"\n", "Reason: SIP ;cause=580 ;text=\"Precondition Failure\","+ "SIP ;cause=530 ;text=\"Pre Failure\"\n", "Reason: SIP \n" }; for (int i = 0; i < r.length; i++ ) { ReasonParser parser = new ReasonParser(r[i]); ReasonList rl= (ReasonList) parser.parse(); System.out.println("encoded = " + rl.encode()); } } */ } /* * $Log: ReasonParser.java,v $ * Revision 1.8 2009/07/17 18:58:03 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.7 2008/11/19 10:10:50 jbemmel * Don't catch ParseException but throw it * * Revision 1.6 2006/07/13 09:02:12 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.4 2004/01/22 13:26:31 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/RecordRouteParser.java0100644 0000000 0000000 00000005741 13513104763 021765 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.RecordRoute; import gov.nist.javax.sip.header.RecordRouteList; import gov.nist.javax.sip.header.SIPHeader; import java.text.ParseException; /** * Parser for a list of route headers. * * @version 1.2 $Revision: 1.9 $ $Date: 2009/07/17 18:58:03 $ * * @author Olivier Deruelle
    * @author M. Ranganathan
    * */ public class RecordRouteParser extends AddressParametersParser { /** * Constructor * @param recordRoute message to parse to set */ public RecordRouteParser(String recordRoute) { super(recordRoute); } protected RecordRouteParser(Lexer lexer) { super(lexer); } /** * parse the String message and generate the RecordRoute List Object * @return SIPHeader the RecordRoute List object * @throws ParseException if errors occur during the parsing */ public SIPHeader parse() throws ParseException { RecordRouteList recordRouteList = new RecordRouteList(); if (debug) dbg_enter("RecordRouteParser.parse"); try { this.lexer.match(TokenTypes.RECORD_ROUTE); this.lexer.SPorHT(); this.lexer.match(':'); this.lexer.SPorHT(); while (true) { RecordRoute recordRoute = new RecordRoute(); super.parse(recordRoute); recordRouteList.add(recordRoute); this.lexer.SPorHT(); char la = lexer.lookAhead(0); if (la == ',') { this.lexer.match(','); this.lexer.SPorHT(); } else if (la == '\n') break; else throw createParseException("unexpected char"); } return recordRouteList; } finally { if (debug) dbg_leave("RecordRouteParser.parse"); } } } java/gov/nist/javax/sip/parser/ReferToParser.java0100644 0000000 0000000 00000016021 13513104763 021067 0ustar000000000 0000000 /* * 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.parser; import java.text.ParseException; import gov.nist.javax.sip.header.*; /** * To Header parser. * * @version 1.2 $Revision: 1.8 $ $Date: 2009/07/17 18:58:03 $ * * @author Olivier Deruelle
    * * * */ public class ReferToParser extends AddressParametersParser { /** * Creates new ToParser * @param referTo String to set */ public ReferToParser(String referTo) { super(referTo); } protected ReferToParser(Lexer lexer) { super(lexer); } public SIPHeader parse() throws ParseException { headerName(TokenTypes.REFER_TO); ReferTo referTo = new ReferTo(); super.parse(referTo); this.lexer.match('\n'); return referTo; } public static void main(String args[]) throws ParseException { String to[] = { "Refer-To: \n", "Refer-To: ;tag=5617\n", "Refer-To: T. A. Watson \n", "Refer-To: LittleGuy \n", "Refer-To: sip:mranga@120.6.55.9\n", "Refer-To: sip:mranga@129.6.55.9 ; tag=696928473514.129.6.55.9\n" }; for (int i = 0; i < to.length; i++) { ReferToParser tp = new ReferToParser(to[i]); ReferTo t = (ReferTo) tp.parse(); System.out.println("encoded = " + t.encode()); } } } /* * $Log: ReferToParser.java,v $ * Revision 1.8 2009/07/17 18:58:03 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.7 2006/07/13 09:02:21 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.5 2005/03/29 03:50:01 mranga * Issue number: * Obtained from: * Submitted by: mranga * * Remove transaction for early bye. * Reviewed by: * 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.4 2005/03/27 14:00:14 mranga * Issue number: * Obtained from: * Submitted by: mranga * Reviewed by: mranga * * Added example * 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.3 2004/01/22 13:26:31 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/ReplyToParser.java0100644 0000000 0000000 00000012451 13513104763 021122 0ustar000000000 0000000 /* * 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.parser; import java.text.ParseException; import gov.nist.javax.sip.header.*; /** * Parser for a list of RelpyTo headers. * * @version 1.2 $Revision: 1.7 $ $Date: 2009/07/17 18:58:03 $ * * @author Olivier Deruelle
    * @author M. Ranganathan
    * */ public class ReplyToParser extends AddressParametersParser { /** * Creates a new instance of ReplyToParser * @param replyTo the header to parse */ public ReplyToParser(String replyTo) { super(replyTo); } /** * Cosntructor * param lexer the lexer to use to parse the header */ protected ReplyToParser(Lexer lexer) { super(lexer); } /** * parse the String message and generate the ReplyTo List Object * @return SIPHeader the ReplyTo List object * @throws SIPParseException if errors occur during the parsing */ public SIPHeader parse() throws ParseException { ReplyTo replyTo = new ReplyTo(); if (debug) dbg_enter("ReplyTo.parse"); try { headerName(TokenTypes.REPLY_TO); replyTo.setHeaderName(SIPHeaderNames.REPLY_TO); super.parse(replyTo); return replyTo; } finally { if (debug) dbg_leave("ReplyTo.parse"); } } /** public static void main(String args[]) throws ParseException { String r[] = { "Reply-To: Bob \n" }; for (int i = 0; i < r.length; i++ ) { ReplyToParser rt = new ReplyToParser(r[i]); ReplyTo re = (ReplyTo) rt.parse(); System.out.println("encoded = " +re.encode()); } } */ } /* * $Log: ReplyToParser.java,v $ * Revision 1.7 2009/07/17 18:58:03 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.6 2006/07/13 09:02:16 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.4 2004/01/22 13:26:31 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/RequestLineParser.java0100644 0000000 0000000 00000015667 13513104763 022000 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.address.*; import java.text.ParseException; import gov.nist.javax.sip.header.*; /** * Parser for the SIP request line. * * @version 1.2 * * @author M. Ranganathan
    * * */ public class RequestLineParser extends Parser { public RequestLineParser(String requestLine) { this.lexer = new Lexer("method_keywordLexer", requestLine); } public RequestLineParser(Lexer lexer) { this.lexer = lexer; this.lexer.selectLexer("method_keywordLexer"); } public RequestLine parse() throws ParseException { if (debug) dbg_enter("parse"); try { RequestLine retval = new RequestLine(); String m = method(); lexer.SPorHT(); retval.setMethod(m); this.lexer.selectLexer("sip_urlLexer"); URLParser urlParser = new URLParser(this.getLexer()); GenericURI url = urlParser.uriReference(true); lexer.SPorHT(); retval.setUri(url); this.lexer.selectLexer("request_lineLexer"); String v = sipVersion(); retval.setSipVersion(v); lexer.SPorHT(); lexer.match('\n'); return retval; } finally { if (debug) dbg_leave("parse"); } } public static void main(String args[]) throws ParseException { String requestLines[] = { "REGISTER sip:192.168.0.68 SIP/2.0\n", "REGISTER sip:company.com SIP/2.0\n", "INVITE sip:3660@166.35.231.140 SIP/2.0\n", "INVITE sip:user@company.com SIP/2.0\n", "REGISTER sip:[2001::1]:5060;transport=tcp SIP/2.0\n", // Added by Daniel J. Martinez Manzano "REGISTER sip:[2002:800:700:600:30:4:6:1]:5060;transport=udp SIP/2.0\n", // Added by Daniel J. Martinez Manzano "REGISTER sip:[3ffe:800:700::30:4:6:1]:5060;transport=tls SIP/2.0\n", // Added by Daniel J. Martinez Manzano "REGISTER sip:[2001:720:1710:0:201:29ff:fe21:f403]:5060;transport=udp SIP/2.0\n", "OPTIONS sip:135.180.130.133 SIP/2.0\n" }; for (int i = 0; i < requestLines.length; i++ ) { RequestLineParser rlp = new RequestLineParser(requestLines[i]); RequestLine rl = rlp.parse(); System.out.println("encoded = " + rl.encode()); } } } /* * $Log: RequestLineParser.java,v $ * Revision 1.11 2009/10/22 10:27:38 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/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.9 2009/07/17 18:58:03 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.8 2006/07/13 09:02:14 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:35 mranga * * Import * * * Revision 1.6 2004/10/28 19:02:50 mranga * Submitted by: Daniel Martinez * Reviewed by: M. Ranganathan * * Added changes for TLS support contributed by Daniel Martinez * * Revision 1.5 2004/06/27 00:41:51 mranga * Submitted by: Thomas Froment and Pierre De Rop * Reviewed by: mranga * Performance improvements * (auxiliary data structure for fast lookup of transactions). * * Revision 1.4 2004/01/22 13:26:31 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/RequireParser.java0100644 0000000 0000000 00000014171 13513104763 021141 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import gov.nist.core.*; import java.text.ParseException; /** * Parser for Require header. * * @version 1.2 $Revision: 1.7 $ $Date: 2009/07/17 18:58:04 $ * * @author Olivier Deruelle * @author M. Ranganathan
    * * * * @version 1.0 */ public class RequireParser extends HeaderParser { /** * Creates a new instance of RequireParser * @param require the header to parse */ public RequireParser(String require) { super(require); } /** * Constructor * @param lexer the lexer to use to parse the header */ protected RequireParser(Lexer lexer) { super(lexer); } /** * parse the String message * @return SIPHeader (RequireList object) * @throws SIPParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { RequireList requireList = new RequireList(); if (debug) dbg_enter("RequireParser.parse"); try { headerName(TokenTypes.REQUIRE); while (lexer.lookAhead(0) != '\n') { Require r = new Require(); r.setHeaderName(SIPHeaderNames.REQUIRE); // Parsing the option tag this.lexer.match(TokenTypes.ID); Token token = lexer.getNextToken(); r.setOptionTag(token.getTokenValue()); this.lexer.SPorHT(); requireList.add(r); while (lexer.lookAhead(0) == ',') { this.lexer.match(','); this.lexer.SPorHT(); r = new Require(); // Parsing the option tag this.lexer.match(TokenTypes.ID); token = lexer.getNextToken(); r.setOptionTag(token.getTokenValue()); this.lexer.SPorHT(); requireList.add(r); } } } finally { if (debug) dbg_leave("RequireParser.parse"); } return requireList; } /** Test program public static void main(String args[]) throws ParseException { String r[] = { "Require: 100rel \n", "Require: 100rel, 200ok , 389\n" }; for (int i = 0; i < r.length; i++ ) { RequireParser parser = new RequireParser(r[i]); RequireList rl= (RequireList) parser.parse(); System.out.println("encoded = " + rl.encode()); } } */ } /* * $Log: RequireParser.java,v $ * Revision 1.7 2009/07/17 18:58:04 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.6 2006/07/13 09:02:18 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:36 mranga * * Import * * * Revision 1.4 2004/01/22 13:26:31 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/RetryAfterParser.java0100644 0000000 0000000 00000010414 13513104763 021610 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import gov.nist.core.*; import java.text.ParseException; import javax.sip.*; /** * Parser for RetryAfter header. * * @version 1.2 * * @author Olivier Deruelle * @author M. Ranganathan * * * @version 1.2 $Revision: 1.10 $ $Date: 2009/11/04 17:23:00 $ */ public class RetryAfterParser extends HeaderParser { /** * Creates a new instance of RetryAfterParser * @param retryAfter the header to parse */ public RetryAfterParser(String retryAfter) { super(retryAfter); } /** * Constructor * @param lexer the lexer to use to parse the header */ protected RetryAfterParser(Lexer lexer) { super(lexer); } /** * parse the String message * @return SIPHeader (RetryAfter object) * @throws SIPParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { if (debug) dbg_enter("RetryAfterParser.parse"); RetryAfter retryAfter = new RetryAfter(); try { headerName(TokenTypes.RETRY_AFTER); // mandatory delatseconds: String value = lexer.number(); try { int ds = Integer.parseInt(value); retryAfter.setRetryAfter(ds); } catch (NumberFormatException ex) { throw createParseException(ex.getMessage()); } catch (InvalidArgumentException ex) { throw createParseException(ex.getMessage()); } this.lexer.SPorHT(); if (lexer.lookAhead(0) == '(') { String comment = this.lexer.comment(); retryAfter.setComment(comment); } this.lexer.SPorHT(); while (lexer.lookAhead(0) == ';') { this.lexer.match(';'); this.lexer.SPorHT(); lexer.match(TokenTypes.ID); Token token = lexer.getNextToken(); value = token.getTokenValue(); if (value.equalsIgnoreCase("duration")) { this.lexer.match('='); this.lexer.SPorHT(); value = lexer.number(); try { int duration = Integer.parseInt(value); retryAfter.setDuration(duration); } catch (NumberFormatException ex) { throw createParseException(ex.getMessage()); } catch (InvalidArgumentException ex) { throw createParseException(ex.getMessage()); } } else { this.lexer.SPorHT(); this.lexer.match('='); this.lexer.SPorHT(); lexer.match(TokenTypes.ID); Token secondToken = lexer.getNextToken(); String secondValue = secondToken.getTokenValue(); retryAfter.setParameter(value, secondValue); } this.lexer.SPorHT(); } } finally { if (debug) dbg_leave("RetryAfterParser.parse"); } return retryAfter; } } java/gov/nist/javax/sip/parser/RouteParser.java0100644 0000000 0000000 00000013545 13513104763 020627 0ustar000000000 0000000 /* * 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.parser; import java.text.ParseException; import gov.nist.javax.sip.header.*; /** * Parser for a list of route headers. * * @version 1.2 * * @author Olivier Deruelle
    * @author M. Ranganathan
    * * *@version 1.0 */ public class RouteParser extends AddressParametersParser { /** * Constructor * @param route message to parse to set */ public RouteParser(String route) { super(route); } protected RouteParser(Lexer lexer) { super(lexer); } /** parse the String message and generate the Route List Object * @return SIPHeader the Route List object * @throws SIPParseException if errors occur during the parsing */ public SIPHeader parse() throws ParseException { RouteList routeList = new RouteList(); if (debug) dbg_enter("parse"); try { this.lexer.match(TokenTypes.ROUTE); this.lexer.SPorHT(); this.lexer.match(':'); this.lexer.SPorHT(); while (true) { Route route = new Route(); super.parse(route); routeList.add(route); this.lexer.SPorHT(); char la = lexer.lookAhead(0); if (la == ',') { this.lexer.match(','); this.lexer.SPorHT(); } else if (la == '\n') break; else throw createParseException("unexpected char"); } return routeList; } finally { if (debug) dbg_leave("parse"); } } /** public static void main(String args[]) throws ParseException { String rou[] = { "Route: \n", "Route: sip:bob@biloxi.com \n", "Route: sip:alice@atlanta.com, sip:bob@biloxi.com, sip:carol@chicago.com\n" }; for (int i = 0; i < rou.length; i++ ) { RouteParser rp = new RouteParser(rou[i]); RouteList routeList = (RouteList) rp.parse(); System.out.println("encoded = " +routeList.encode()); } } */ } /* * $Log: RouteParser.java,v $ * Revision 1.8 2009/07/17 18:58:04 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.7 2007/02/06 16:40:03 belangery * Introduced simple code optimizations. * * Revision 1.6 2006/07/13 09:02:07 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:36 mranga * * Import * * * Revision 1.4 2004/01/22 13:26:32 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/SIPETagParser.java0100644 0000000 0000000 00000011263 13513104763 020720 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import gov.nist.core.*; import java.text.ParseException; /** * Parser for SIP-ETag header. * * * @author Jeroen van Bemmel
    * * * * @version 1.2 * @since 1.2 */ public class SIPETagParser extends HeaderParser { /** * Creates a new instance of PriorityParser * @param etag the header to parse */ public SIPETagParser(String etag) { super(etag); } /** * Constructor * @param lexer the lexer to use to parse the header */ protected SIPETagParser(Lexer lexer) { super(lexer); } /** * parse the String header * @return SIPHeader (Priority object) * @throws SIPParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { if (debug) dbg_enter("SIPEtag.parse"); SIPETag sipEtag = new SIPETag(); try { headerName(TokenTypes.SIP_ETAG); this.lexer.SPorHT(); this.lexer.match(TokenTypes.ID); Token token = lexer.getNextToken(); sipEtag.setETag(token.getTokenValue()); this.lexer.SPorHT(); this.lexer.match('\n'); return sipEtag; } finally { if (debug) dbg_leave("SIPEtag.parse"); } } } /* * $Log: SIPETagParser.java,v $ * Revision 1.3 2009/07/17 18:58:04 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.2 2006/07/13 09:01:58 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1 2005/10/27 20:49:00 jeroen * added support for RFC3903 PUBLISH * * 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. * */ java/gov/nist/javax/sip/parser/SIPIfMatchParser.java0100644 0000000 0000000 00000011412 13513104763 021407 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import gov.nist.core.*; import java.text.ParseException; /** * Parser for SIP-If-Match header. * * * @author Jeroen van Bemmel
    * * * @version 1.2 $Revision: 1.3 $ $Date: 2009/07/17 18:58:04 $ * * @since 1.2 */ public class SIPIfMatchParser extends HeaderParser { /** * Creates a new instance of PriorityParser * @param etag the header to parse */ public SIPIfMatchParser(String etag) { super(etag); } /** * Constructor * @param lexer the lexer to use to parse the header */ protected SIPIfMatchParser(Lexer lexer) { super(lexer); } /** * parse the String header * @return SIPHeader (Priority object) * @throws SIPParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { if (debug) dbg_enter("SIPIfMatch.parse"); SIPIfMatch sipIfMatch = new SIPIfMatch(); try { headerName(TokenTypes.SIP_IF_MATCH); this.lexer.SPorHT(); this.lexer.match(TokenTypes.ID); Token token = lexer.getNextToken(); sipIfMatch.setETag(token.getTokenValue()); this.lexer.SPorHT(); this.lexer.match('\n'); return sipIfMatch; } finally { if (debug) dbg_leave("SIPIfMatch.parse"); } } } /* * $Log: SIPIfMatchParser.java,v $ * Revision 1.3 2009/07/17 18:58:04 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.2 2006/07/13 09:02:08 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1 2005/10/27 20:49:00 jeroen * added support for RFC3903 PUBLISH * * 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. * */ java/gov/nist/javax/sip/parser/SIPMessageListener.java0100644 0000000 0000000 00000011217 13513104763 022014 0ustar000000000 0000000 /* * 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.javax.sip.parser; import gov.nist.javax.sip.message.*; /** * Interface that provides methods for processing good * and bad messages for the PipelinedMessageParser. * * @version 1.2 $Revision: 1.8 $ $Date: 2009/07/17 18:58:04 $ * @see PipelinedMsgParser */ public interface SIPMessageListener extends ParseExceptionListener { /** * This is called from the parser on successful message processing. * @see ParseExceptionListener for the method that gets called * on parse exception. * @param msg SIP Message structure that is generated by the parser. */ public void processMessage(SIPMessage msg) throws Exception; } /* * $Log: SIPMessageListener.java,v $ * Revision 1.8 2009/07/17 18:58:04 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.7 2006/07/13 09:02:17 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:36 mranga * * Import * * * Revision 1.5 2004/02/29 00:46:34 mranga * Reviewed by: mranga * Added new configuration property to limit max message size for TCP transport. * The property is gov.nist.javax.sip.MAX_MESSAGE_SIZE * * Revision 1.4 2004/01/22 13:26:32 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/ServerParser.java0100644 0000000 0000000 00000015742 13513104763 021000 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import java.text.ParseException; /** * Parser for Server header. * * @version 1.2 $Revision: 1.9 $ $Date: 2009/07/17 18:58:05 $ * * @author Olivier Deruelle
    * @author M. Ranganathan
    * * */ public class ServerParser extends HeaderParser { /** * Creates a new instance of ServerParser * @param server the header to parse */ public ServerParser(String server) { super(server); } /** * Constructor * @param lexer the lexer to use to parse the header */ protected ServerParser(Lexer lexer) { super(lexer); } /** * parse the String server * @return SIPHeader (Server object) * @throws SIPParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { if (debug) dbg_enter("ServerParser.parse"); Server server = new Server(); try { headerName(TokenTypes.SERVER); if (this.lexer.lookAhead(0) == '\n') throw createParseException("empty header"); // mandatory token: product[/product-version] | (comment) while (this.lexer.lookAhead(0) != '\n' && this.lexer.lookAhead(0) != '\0') { if (this.lexer.lookAhead(0) == '(') { String comment = this.lexer.comment(); server.addProductToken('(' + comment + ')'); } else { String tok; int marker = 0; try { marker = this.lexer.markInputPosition(); tok = this.lexer.getString('/'); if (tok.charAt(tok.length() - 1) == '\n') tok = tok.trim(); server.addProductToken(tok); } catch (ParseException ex) { this.lexer.rewindInputPosition(marker); tok = this.lexer.getRest().trim(); server.addProductToken(tok); break; } } } } finally { if (debug) dbg_leave("ServerParser.parse"); } return server; } /* public static void main(String args[]) throws ParseException { String server[] = { "Server: Softphone/Beta1.5 \n", "Server: HomeServer v2\n", "Server: Nist/Beta1 (beta version) \n", "Server: Nist proxy (beta version)\n", "Server: Nist1.0/Beta2 UbiServer/vers.1.0 (new stuff) (Cool) \n", "Server: Sip EXpress router (0.8.11 (sparc64/solaris))\n" }; for (int i = 0; i < server.length; i++ ) { ServerParser parser = new ServerParser(server[i]); Server s= (Server) parser.parse(); System.out.println("encoded = " + s.encode()); } } */ } /* * $Log: ServerParser.java,v $ * Revision 1.9 2009/07/17 18:58:05 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.8 2006/07/13 09:02:16 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.4 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.3 2006/06/17 10:18:14 mranga * Added some synchronization to the sequence number checking. * Small javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:36 mranga * * Import * * * Revision 1.6 2004/01/30 17:10:47 mranga * Reviewed by: mranga * Server and user agent parser leave an extra Linefeed at the end of token. * * Revision 1.5 2004/01/27 13:52:11 mranga * Reviewed by: mranga * Fixed server/user-agent parser. * suppress sending ack to TU when retransFilter is enabled and ack is retransmitted. * * Revision 1.4 2004/01/22 13:26:32 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/StatusLineParser.java0100644 0000000 0000000 00000013756 13513104763 021630 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import java.text.ParseException; /** * Parser for the SIP status line. * * @version 1.2 $Revision: 1.7 $ $Date: 2009/07/17 18:58:05 $ * * @author M. Ranganathan
    * * * */ public class StatusLineParser extends Parser { public StatusLineParser(String statusLine) { this.lexer = new Lexer("status_lineLexer", statusLine); } public StatusLineParser(Lexer lexer) { this.lexer = lexer; this.lexer.selectLexer("status_lineLexer"); } protected int statusCode() throws ParseException { String scode = this.lexer.number(); if (debug) dbg_enter("statusCode"); try { int retval = Integer.parseInt(scode); return retval; } catch (NumberFormatException ex) { throw new ParseException( lexer.getBuffer() + ":" + ex.getMessage(), lexer.getPtr()); } finally { if (debug) dbg_leave("statusCode"); } } protected String reasonPhrase() throws ParseException { return this.lexer.getRest().trim(); } public StatusLine parse() throws ParseException { try { if (debug) dbg_enter("parse"); StatusLine retval = new StatusLine(); String version = this.sipVersion(); retval.setSipVersion(version); lexer.SPorHT(); int scode = statusCode(); retval.setStatusCode(scode); lexer.SPorHT(); String rp = reasonPhrase(); retval.setReasonPhrase(rp); lexer.SPorHT(); return retval; } finally { if (debug) dbg_leave("parse"); } } /** public static void main(String[] args) throws ParseException { String[] statusLines = { "SIP/2.0 200 OK\n", "BOO 200 OK\n", "SIP/2.0 500 OK bad things happened \n" }; for (int i = 0 ; i < statusLines.length; i++) { try { StatusLineParser slp = new StatusLineParser(statusLines[i]); StatusLine sl = slp.parse(); System.out.println("encoded = " + sl.encode()); } catch (ParseException ex) { System.out.println("error message " + ex.getMessage()); } } } */ } /* * $Log: StatusLineParser.java,v $ * Revision 1.7 2009/07/17 18:58:05 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.6 2006/07/13 09:02:20 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:36 mranga * * Import * * * Revision 1.4 2004/01/22 13:26:32 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/StringMsgParser.java0100644 0000000 0000000 00000062650 13513104763 021447 0ustar000000000 0000000 /* * 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.javax.sip.parser; import gov.nist.core.Host; import gov.nist.core.HostNameParser; import gov.nist.javax.sip.SIPConstants; import gov.nist.javax.sip.address.AddressImpl; 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.*; import gov.nist.javax.sip.message.SIPMessage; import gov.nist.javax.sip.message.SIPRequest; import gov.nist.javax.sip.message.SIPResponse; import java.io.UnsupportedEncodingException; import java.text.ParseException; /* * Acknowledgement: 1/12/2007: Yanick Belanger rewrote the parsing loops to make them * simpler and quicker. */ /** * Parse SIP message and parts of SIP messages such as URI's etc from memory and * return a structure. Intended use: UDP message processing. This class is used * when you have an entire SIP message or SIPHeader or SIP URL in memory and you * want to generate a parsed structure from it. For SIP messages, the payload * can be binary or String. If you have a binary payload, use * parseSIPMessage(byte[]) else use parseSIPMessage(String) The payload is * accessible from the parsed message using the getContent and getContentBytes * methods provided by the SIPMessage class. If SDP parsing is enabled using the * parseContent method, then the SDP body is also parsed and can be accessed * from the message using the getSDPAnnounce method. Currently only eager * parsing of the message is supported (i.e. the entire message is parsed in one * feld swoop). * * * @version 1.2 $Revision: 1.26 $ $Date: 2009/10/22 10:27:38 $ * * @author M. Ranganathan
    * * */ public class StringMsgParser { protected boolean readBody; private ParseExceptionListener parseExceptionListener; private String rawStringMessage; private boolean strict; private static boolean computeContentLengthFromMessage = false; /** * @since v0.9 */ 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; } /** * Parse a buffer containing a single SIP Message where the body is an array * of un-interpreted bytes. This is intended for parsing the message from a * memory buffer when the buffer. Incorporates a bug fix for a bug that was * noted by Will Sullin of Callcast * * @param msgBuffer * a byte buffer 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(byte[] msgBuffer) throws ParseException { if (msgBuffer == null || msgBuffer.length == 0) return null; int i = 0; // Squeeze out any leading control character. try { while (msgBuffer[i] < 0x20) i++; } catch (ArrayIndexOutOfBoundsException e) { // Array contains only control char, return null. 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 { while (msgBuffer[i] != '\r' && msgBuffer[i] != '\n') i++; } catch (ArrayIndexOutOfBoundsException e) { // End of the message. break; } int lineLength = i - lineStart; // Make it a String. try { currentLine = new String(msgBuffer, lineStart, lineLength, "UTF-8"); } catch (UnsupportedEncodingException e) { throw new ParseException("Bad message encoding!", 0); } currentLine = trimEndOfLine(currentLine); if (currentLine.length() == 0) { // Last header line, process the previous buffered header. if (currentHeader != null && message != 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 && message != null) { processHeader(currentHeader, message); } currentHeader = currentLine; } } } if (msgBuffer[i] == '\r' && msgBuffer.length > i+1 && msgBuffer[i+1] == '\n') i++; i++; isFirstLine = false; } while (currentLine.length() > 0); // End do - while 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) { 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); } } } return message; } private String trimEndOfLine(String line) { if (line == null) return line; int i = line.length() - 1; while (i >= 0 && line.charAt(i) <= 0x20) i--; if (i == line.length() - 1) return line; if (i == -1) return ""; return line.substring(0, i+1); } private SIPMessage processFirstLine(String firstLine) throws ParseException { SIPMessage message; if (!firstLine.startsWith(SIPConstants.SIP_VERSION_STRING)) { message = new SIPRequest(); try { RequestLine requestLine = new RequestLineParser(firstLine + "\n") .parse(); ((SIPRequest) message).setRequestLine(requestLine); } catch (ParseException ex) { if (this.parseExceptionListener != null) this.parseExceptionListener.handleException(ex, message, RequestLine.class, firstLine, rawStringMessage); else throw ex; } } else { message = new SIPResponse(); try { StatusLine sl = new StatusLineParser(firstLine + "\n").parse(); ((SIPResponse) message).setStatusLine(sl); } catch (ParseException ex) { if (this.parseExceptionListener != null) { this.parseExceptionListener.handleException(ex, message, StatusLine.class, firstLine, rawStringMessage); } else throw ex; } } return message; } private void processHeader(String header, SIPMessage message) throws ParseException { if (header == null || header.length() == 0) return; HeaderParser headerParser = null; try { headerParser = ParserFactory.createParser(header + "\n"); } catch (ParseException ex) { this.parseExceptionListener.handleException(ex, message, null, header, rawStringMessage); return; } try { SIPHeader sipHeader = headerParser.parse(); message.attachHeader(sipHeader, false); } catch (ParseException ex) { if (this.parseExceptionListener != null) { String headerName = Lexer.getHeaderName(header); Class headerClass = NameMap.getClassFromName(headerName); if (headerClass == null) { headerClass = ExtensionHeaderImpl.class; } this.parseExceptionListener.handleException(ex, message, headerClass, header, rawStringMessage); } } } /** * Parse an address (nameaddr or address spec) and return and address * structure. * * @param address * is a String containing the address to be parsed. * @return a parsed address structure. * @since v1.0 * @exception ParseException * when the address is badly formatted. */ public AddressImpl parseAddress(String address) throws ParseException { AddressParser addressParser = new AddressParser(address); return addressParser.address(true); } /** * Parse a host:port and return a parsed structure. * * @param hostport * is a String containing the host:port to be parsed * @return a parsed address structure. * @since v1.0 * @exception throws * a ParseException when the address is badly formatted. * public HostPort parseHostPort(String hostport) throws ParseException { Lexer lexer = new Lexer("charLexer", hostport); return new HostNameParser(lexer).hostPort(); } */ /** * Parse a host name and return a parsed structure. * * @param host * is a String containing the host name to be parsed * @return a parsed address structure. * @since v1.0 * @exception ParseException * a ParseException when the hostname is badly formatted. */ public Host parseHost(String host) throws ParseException { Lexer lexer = new Lexer("charLexer", host); return new HostNameParser(lexer).host(); } /** * Parse a telephone number return a parsed structure. * * @param telephone_number * is a String containing the telephone # to be parsed * @return a parsed address structure. * @since v1.0 * @exception ParseException * a ParseException when the address is badly formatted. */ public TelephoneNumber parseTelephoneNumber(String telephone_number) throws ParseException { // Bug fix contributed by Will Scullin return new URLParser(telephone_number).parseTelephoneNumber(true); } /** * Parse a SIP url from a string and return a URI structure for it. * * @param url * a String containing the URI structure to be parsed. * @return A parsed URI structure * @exception ParseException * if there was an error parsing the message. */ public SipUri parseSIPUrl(String url) throws ParseException { try { return new URLParser(url).sipURL(true); } catch (ClassCastException ex) { throw new ParseException(url + " Not a SIP URL ", 0); } } /** * Parse a uri from a string and return a URI structure for it. * * @param url * a String containing the URI structure to be parsed. * @return A parsed URI structure * @exception ParseException * if there was an error parsing the message. */ public GenericURI parseUrl(String url) throws ParseException { return new URLParser(url).parse(); } /** * Parse an individual SIP message header from a string. * * @param header * String containing the SIP header. * @return a SIPHeader structure. * @exception ParseException * if there was an error parsing the message. */ public SIPHeader parseSIPHeader(String header) throws ParseException { int start = 0; int end = header.length() - 1; try { // Squeeze out any leading control character. while (header.charAt(start) <= 0x20) start++; // Squeeze out any trailing control character. while (header.charAt(end) <= 0x20) end--; } catch (ArrayIndexOutOfBoundsException e) { // Array contains only control char. throw new ParseException("Empty header.", 0); } StringBuffer buffer = new StringBuffer(end + 1); int i = start; int lineStart = start; boolean endOfLine = false; while (i <= end) { char c = header.charAt(i); if (c == '\r' || c == '\n') { if (!endOfLine) { buffer.append(header.substring(lineStart, i)); endOfLine = true; } } else { if (endOfLine) { endOfLine = false; if (c == ' ' || c == '\t') { buffer.append(' '); lineStart = i + 1; } else { lineStart = i; } } } i++; } buffer.append(header.substring(lineStart, i)); buffer.append('\n'); HeaderParser hp = ParserFactory.createParser(buffer.toString()); if (hp == null) throw new ParseException("could not create parser", 0); return hp.parse(); } /** * Parse the SIP Request Line * * @param requestLine * a String containing the request line to be parsed. * @return a RequestLine structure that has the parsed RequestLine * @exception ParseException * if there was an error parsing the requestLine. */ public RequestLine parseSIPRequestLine(String requestLine) throws ParseException { requestLine += "\n"; return new RequestLineParser(requestLine).parse(); } /** * Parse the SIP Response message status line * * @param statusLine * a String containing the Status line to be parsed. * @return StatusLine class corresponding to message * @exception ParseException * if there was an error parsing * @see StatusLine */ public StatusLine parseSIPStatusLine(String statusLine) throws ParseException { statusLine += "\n"; return new StatusLineParser(statusLine).parse(); } public static void setComputeContentLengthFromMessage( boolean computeContentLengthFromMessage) { StringMsgParser.computeContentLengthFromMessage = computeContentLengthFromMessage; } /** * Test code. */ public static void main(String[] args) throws ParseException { String messages[] = { "SIP/2.0 200 OK\r\n" + "To: \"The Little Blister\" ;tag=469bc066\r\n" + "From: \"The Master Blaster\" ;tag=11\r\n" + "Via: SIP/2.0/UDP 139.10.134.246:5060;branch=z9hG4bK8b0a86f6_1030c7d18e0_17;received=139.10.134.246\r\n" + "Call-ID: 1030c7d18ae_a97b0b_b@8b0a86f6\r\n" + "CSeq: 1 SUBSCRIBE\r\n" + "Contact: \r\n" + "Content-Length: 0\r\n\r\n", "SIP/2.0 180 Ringing\r\n" + "Via: SIP/2.0/UDP 172.18.1.29:5060;branch=z9hG4bK43fc10fb4446d55fc5c8f969607991f4\r\n" + "To: \"0440\" ;tag=2600\r\n" + "From: \"Andreas\" ;tag=8524\r\n" + "Call-ID: f51a1851c5f570606140f14c8eb64fd3@172.18.1.29\r\n" + "CSeq: 1 INVITE\r\n" + "Max-Forwards: 70\r\n" + "Record-Route: \r\n" + "Content-Length: 0\r\n\r\n", "REGISTER sip:nist.gov SIP/2.0\r\n" + "Via: SIP/2.0/UDP 129.6.55.182:14826\r\n" + "Max-Forwards: 70\r\n" + "From: ;tag=6fcd5c7ace8b4a45acf0f0cd539b168b;epid=0d4c418ddf\r\n" + "To: \r\n" + "Call-ID: c5679907eb954a8da9f9dceb282d7230@129.6.55.182\r\n" + "CSeq: 1 REGISTER\r\n" + "Contact: ;methods=\"INVITE, MESSAGE, INFO, SUBSCRIBE, OPTIONS, BYE, CANCEL, NOTIFY, ACK, REFER\"\r\n" + "User-Agent: RTC/(Microsoft RTC)\r\n" + "Event: registration\r\n" + "Allow-Events: presence\r\n" + "Content-Length: 0\r\n\r\n" + "INVITE sip:littleguy@there.com:5060 SIP/2.0\r\n" + "Via: SIP/2.0/UDP 65.243.118.100:5050\r\n" + "From: M. Ranganathan ;tag=1234\r\n" + "To: \"littleguy@there.com\" \r\n" + "Call-ID: Q2AboBsaGn9!?x6@sipbakeoff.com \r\n" + "CSeq: 1 INVITE \r\n" + "Content-Length: 247\r\n\r\n" + "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" }; class ParserThread implements Runnable { String[] messages; public ParserThread(String[] messagesToParse) { this.messages = messagesToParse; } public void run() { for (int i = 0; i < messages.length; i++) { StringMsgParser smp = new StringMsgParser(); try { SIPMessage sipMessage = smp .parseSIPMessage(messages[i]); System.out.println(" i = " + i + " branchId = " + sipMessage.getTopmostVia().getBranch()); // System.out.println("encoded " + // sipMessage.toString()); } catch (ParseException ex) { } // System.out.println("dialog id = " + // sipMessage.getDialogId(false)); } } } for (int i = 0; i < 20; i++) { new Thread(new ParserThread(messages)).start(); } } public void setStrict(boolean strict) { this.strict = strict; } } java/gov/nist/javax/sip/parser/SubjectParser.java0100644 0000000 0000000 00000012357 13513104763 021130 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import java.text.ParseException; /** * Parser for Subject header. * * @version 1.2 * * @author Olivier Deruelle
    * @author M. Ranganathan
    * * */ public class SubjectParser extends HeaderParser { /** * Creates a new instance of SubjectParser * @param subject the header to parse */ public SubjectParser(String subject) { super(subject); } /** * Constructor * @param lexer the lexer to use to parse the header */ protected SubjectParser(Lexer lexer) { super(lexer); } /** * parse the String message * @return SIPHeader (Subject object) * @throws SIPParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { Subject subject = new Subject(); if (debug) dbg_enter("SubjectParser.parse"); try { headerName(TokenTypes.SUBJECT); this.lexer.SPorHT(); String s = this.lexer.getRest(); subject.setSubject(s.trim()); } finally { if (debug) dbg_leave("SubjectParser.parse"); } return subject; } /** Test program public static void main(String args[]) throws ParseException { String subject[] = { "Subject: Where is the Moscone?\n", "Subject: Need more boxes\n" }; for (int i = 0; i < subject.length; i++ ) { SubjectParser parser = new SubjectParser(subject[i]); Subject s= (Subject) parser.parse(); System.out.println("encoded = " +s.encode()); } } */ } /* * $Log: SubjectParser.java,v $ * Revision 1.7 2009/07/17 18:58:05 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.6 2006/07/13 09:02:17 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:36 mranga * * Import * * * Revision 1.4 2004/01/22 13:26:32 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/SubscriptionStateParser.java0100644 0000000 0000000 00000020563 13513104763 023214 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import gov.nist.core.*; import java.text.ParseException; import javax.sip.*; /** * Parser for SubscriptionState header. * * @version 1.2 $Revision: 1.7 $ $Date: 2009/07/17 18:58:05 $ * * @author Olivier Deruelle * @author M. Ranganathan * */ public class SubscriptionStateParser extends HeaderParser { /** * Creates a new instance of SubscriptionStateParser * @param subscriptionState the header to parse */ public SubscriptionStateParser(String subscriptionState) { super(subscriptionState); } /** * Constructor * @param lexer the lexer to use to parse the header */ protected SubscriptionStateParser(Lexer lexer) { super(lexer); } /** * parse the String message * @return SIPHeader (SubscriptionState object) * @throws SIPParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { if (debug) dbg_enter("SubscriptionStateParser.parse"); SubscriptionState subscriptionState = new SubscriptionState(); try { headerName(TokenTypes.SUBSCRIPTION_STATE); subscriptionState.setHeaderName(SIPHeaderNames.SUBSCRIPTION_STATE); // State: lexer.match(TokenTypes.ID); Token token = lexer.getNextToken(); subscriptionState.setState(token.getTokenValue()); while (lexer.lookAhead(0) == ';') { this.lexer.match(';'); this.lexer.SPorHT(); lexer.match(TokenTypes.ID); token = lexer.getNextToken(); String value = token.getTokenValue(); if (value.equalsIgnoreCase("reason")) { this.lexer.match('='); this.lexer.SPorHT(); lexer.match(TokenTypes.ID); token = lexer.getNextToken(); value = token.getTokenValue(); subscriptionState.setReasonCode(value); } else if (value.equalsIgnoreCase("expires")) { this.lexer.match('='); this.lexer.SPorHT(); lexer.match(TokenTypes.ID); token = lexer.getNextToken(); value = token.getTokenValue(); try { int expires = Integer.parseInt(value); subscriptionState.setExpires(expires); } catch (NumberFormatException ex) { throw createParseException(ex.getMessage()); } catch (InvalidArgumentException ex) { throw createParseException(ex.getMessage()); } } else if (value.equalsIgnoreCase("retry-after")) { this.lexer.match('='); this.lexer.SPorHT(); lexer.match(TokenTypes.ID); token = lexer.getNextToken(); value = token.getTokenValue(); try { int retryAfter = Integer.parseInt(value); subscriptionState.setRetryAfter(retryAfter); } catch (NumberFormatException ex) { throw createParseException(ex.getMessage()); } catch (InvalidArgumentException ex) { throw createParseException(ex.getMessage()); } } else { this.lexer.match('='); this.lexer.SPorHT(); lexer.match(TokenTypes.ID); Token secondToken = lexer.getNextToken(); String secondValue = secondToken.getTokenValue(); subscriptionState.setParameter(value, secondValue); } this.lexer.SPorHT(); } } finally { if (debug) dbg_leave("SubscriptionStateParser.parse"); } return subscriptionState; } /** Test program public static void main(String args[]) throws ParseException { String subscriptionState[] = { "Subscription-State: active \n", "Subscription-State: terminated;reason=rejected \n", "Subscription-State: pending;reason=probation;expires=36\n", "Subscription-State: pending;retry-after=10;expires=36\n", "Subscription-State: pending;generic=void\n" }; for (int i = 0; i < subscriptionState.length; i++ ) { SubscriptionStateParser parser = new SubscriptionStateParser(subscriptionState[i]); SubscriptionState ss= (SubscriptionState) parser.parse(); System.out.println("encoded = " + ss.encode()); } } */ } /* * $Log: SubscriptionStateParser.java,v $ * Revision 1.7 2009/07/17 18:58:05 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.6 2006/07/13 09:02:25 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:36 mranga * * Import * * * Revision 1.4 2004/01/22 13:26:32 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/SupportedParser.java0100644 0000000 0000000 00000014457 13513104763 021521 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import gov.nist.core.*; import java.text.ParseException; /** * Parser for Supported header. * * @version 1.2 $Revision: 1.7 $ $Date: 2009/07/17 18:58:06 $ * * @author Olivier Deruelle
    * @author M. Ranganathan
    * * * * @version 1.0 */ public class SupportedParser extends HeaderParser { /** * Creates a new instance of SupportedParser * @param supported the header to parse */ public SupportedParser(String supported) { super(supported); } /** * Constructor * @param lexer the lexer to use to parse the header */ protected SupportedParser(Lexer lexer) { super(lexer); } /** * parse the String message * @return SIPHeader (Supported object) * @throws SIPParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { SupportedList supportedList = new SupportedList(); if (debug) dbg_enter("SupportedParser.parse"); try { headerName(TokenTypes.SUPPORTED); while (lexer.lookAhead(0) != '\n') { this.lexer.SPorHT(); Supported supported = new Supported(); supported.setHeaderName(SIPHeaderNames.SUPPORTED); // Parsing the option tag this.lexer.match(TokenTypes.ID); Token token = lexer.getNextToken(); supported.setOptionTag(token.getTokenValue()); this.lexer.SPorHT(); supportedList.add(supported); while (lexer.lookAhead(0) == ',') { this.lexer.match(','); this.lexer.SPorHT(); supported = new Supported(); // Parsing the option tag this.lexer.match(TokenTypes.ID); token = lexer.getNextToken(); supported.setOptionTag(token.getTokenValue()); this.lexer.SPorHT(); supportedList.add(supported); } } } finally { if (debug) dbg_leave("SupportedParser.parse"); } return supportedList; } /** Test program public static void main(String args[]) throws ParseException { String supported[] = { "Supported: 100rel \n", "Supported: foo1, foo2 ,foo3 , foo4 \n" }; for (int i = 0; i < supported.length; i++ ) { SupportedParser parser = new SupportedParser(supported[i]); SupportedList s= (SupportedList) parser.parse(); System.out.println("encoded = " + s.encode()); } } */ } /* * $Log: SupportedParser.java,v $ * Revision 1.7 2009/07/17 18:58:06 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.6 2006/07/13 09:02:02 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:36 mranga * * Import * * * Revision 1.4 2004/01/22 13:26:32 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/TimeStampParser.java0100644 0000000 0000000 00000020040 13513104763 021420 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import java.text.ParseException; import javax.sip.*; /** * Parser for TimeStamp header. * * @version 1.2 $Revision: 1.9 $ $Date: 2009/10/18 13:46:39 $ * * @author Olivier Deruelle
    * @author M. Ranganathan
    * * */ public class TimeStampParser extends HeaderParser { /** * Creates a new instance of TimeStampParser * @param timeStamp the header to parse */ public TimeStampParser(String timeStamp) { super(timeStamp); } /** * Constructor * @param lexer the lexer to use to parse the header */ protected TimeStampParser(Lexer lexer) { super(lexer); } /** * parse the String message * @return SIPHeader (TimeStamp object) * @throws SIPParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { if (debug) dbg_enter("TimeStampParser.parse"); TimeStamp timeStamp = new TimeStamp(); try { headerName(TokenTypes.TIMESTAMP); timeStamp.setHeaderName(SIPHeaderNames.TIMESTAMP); this.lexer.SPorHT(); String firstNumber = this.lexer.number(); try { if (lexer.lookAhead(0) == '.') { this.lexer.match('.'); String secondNumber = this.lexer.number(); String s = firstNumber + "." + secondNumber; float ts = Float.parseFloat(s); timeStamp.setTimeStamp(ts); } else { long ts = Long.parseLong(firstNumber); timeStamp.setTime(ts); } } catch (NumberFormatException ex) { throw createParseException(ex.getMessage()); } catch (InvalidArgumentException ex) { throw createParseException(ex.getMessage()); } this.lexer.SPorHT(); if (lexer.lookAhead(0) != '\n') { firstNumber = this.lexer.number(); try { if (lexer.lookAhead(0) == '.') { this.lexer.match('.'); String secondNumber = this.lexer.number(); String s = firstNumber + "." + secondNumber; float ts = Float.parseFloat(s); timeStamp.setDelay(ts); } else { int ts = Integer.parseInt(firstNumber); timeStamp.setDelay(ts); } } catch (NumberFormatException ex) { throw createParseException(ex.getMessage()); } catch (InvalidArgumentException ex) { throw createParseException(ex.getMessage()); } } } finally { if (debug) dbg_leave("TimeStampParser.parse"); } return timeStamp; } } /* * $Log: TimeStampParser.java,v $ * Revision 1.9 2009/10/18 13:46:39 deruelle_jean * FindBugs Fixes (Category Performance Warnings) * * Issue number: * Obtained from: * Submitted by: Jean Deruelle * Reviewed by: * * Revision 1.8 2009/07/17 18:58:06 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.7 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.6 2006/07/13 09:02:14 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.5 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.4 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.3 2006/05/25 23:46:23 mranga * Added @author NIST to all API files. Moved a package around in the tck directory. * * Ranga. * * Revision 1.2 2006/05/18 10:08:43 mranga * Fixes null pointer in comparison when host is not specified. Add methods to allow longs and ints as args in TimeStamp Header. * * Ranga. * * Revision 1.1.1.1 2005/10/04 17:12:36 mranga * * Import * * * Revision 1.4 2004/01/22 13:26:32 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/ToParser.java0100644 0000000 0000000 00000013453 13513104763 020111 0ustar000000000 0000000 /* * 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.parser; import java.text.ParseException; import gov.nist.javax.sip.address.*; import gov.nist.javax.sip.header.*; import gov.nist.core.*; /** * To Header parser. * * @version 1.2 $Revision: 1.11 $ $Date: 2009/10/22 10:27:38 $ * * @author Olivier Deruelle
    * * */ public class ToParser extends AddressParametersParser { /** * Creates new ToParser * @param to String to set */ public ToParser(String to) { super(to); } protected ToParser(Lexer lexer) { super(lexer); } public SIPHeader parse() throws ParseException { headerName(TokenTypes.TO); To to = new To(); super.parse(to); this.lexer.match('\n'); return to; } /** public static void main(String args[]) throws ParseException { String to[] = { "To: ;tag=5617\n", "To: T. A. Watson \n", "To: LittleGuy ;tag=bar\n", "To: sip:mranga@120.6.55.9\n", "To: sip:mranga@129.6.55.9;tag=696928473514.129.6.55.9\n", "To: sip:mranga@129.6.55.9; tag=696928473514.129.6.55.9\n", "To: sip:mranga@129.6.55.9 ;tag=696928473514.129.6.55.9\n", "To: sip:mranga@129.6.55.9 ; tag=696928473514.129.6.55.9\n" }; for (int i = 0; i < to.length; i++ ) { System.out.println("toParse = " + to[i]); ToParser tp = new ToParser(to[i]); To t = (To) tp.parse(); System.out.println("encoded = " + t.encode()); } } **/ } /* * $Log: ToParser.java,v $ * Revision 1.11 2009/10/22 10:27:38 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:58:06 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.9 2007/10/23 17:34:55 mranga * Issue number: * Obtained from: * Submitted by: mranga * Reviewed by: mranga * * Refactored header collections. * * Revision 1.8 2006/07/13 09:02:00 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:36 mranga * * Import * * * Revision 1.6 2004/04/22 22:51:18 mranga * Submitted by: Thomas Froment * Reviewed by: mranga * * Fixed corner cases. * * Revision 1.5 2004/01/22 13:26:32 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/TokenNames.java0100644 0000000 0000000 00000015374 13513104763 020422 0ustar000000000 0000000 /* * 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.parser; import javax.sip.message.Request; import gov.nist.javax.sip.address.*; import gov.nist.javax.sip.header.*; /** * A grab bag of SIP Token names. * * @version 1.2 $Revision: 1.10 $ $Date: 2009/07/27 20:35:02 $ * * @author M. Ranganathan
    * * */ public interface TokenNames extends gov.nist.javax.sip.header.ParameterNames, gov.nist.javax.sip.address.ParameterNames { // And now dreaded short forms.... public static final String INVITE = Request.INVITE; public static final String ACK = Request.ACK; public static final String BYE = Request.BYE; public static final String SUBSCRIBE = Request.SUBSCRIBE; public static final String NOTIFY = Request.NOTIFY; public static final String OPTIONS = Request.OPTIONS; public static final String REGISTER = Request.REGISTER; public static final String MESSAGE = Request.MESSAGE; public static final String PUBLISH = Request.PUBLISH; public static final String SIP = GenericURI.SIP; public static final String SIPS = GenericURI.SIPS; public static final String TEL = GenericURI.TEL; public static final String GMT = SIPDate.GMT; public static final String MON = SIPDate.MON; public static final String TUE = SIPDate.TUE; public static final String WED = SIPDate.WED; public static final String THU = SIPDate.THU; public static final String FRI = SIPDate.FRI; public static final String SAT = SIPDate.SAT; public static final String SUN = SIPDate.SUN; public static final String JAN = SIPDate.JAN; public static final String FEB = SIPDate.FEB; public static final String MAR = SIPDate.MAR; public static final String APR = SIPDate.APR; public static final String MAY = SIPDate.MAY; public static final String JUN = SIPDate.JUN; public static final String JUL = SIPDate.JUL; public static final String AUG = SIPDate.AUG; public static final String SEP = SIPDate.SEP; public static final String OCT = SIPDate.OCT; public static final String NOV = SIPDate.NOV; public static final String DEC = SIPDate.DEC; public static final String K = "K"; public static final String C = "C"; public static final String E = "E"; public static final String F = "F"; public static final String I = "I"; public static final String M = "M"; public static final String L = "L"; public static final String S = "S"; public static final String T = "T"; public static final String U = "U";// JvB: added public static final String V = "V"; public static final String R = "R"; public static final String O = "O"; public static final String X = "X"; //Jozef Saniga added } /* * $Log: TokenNames.java,v $ * Revision 1.10 2009/07/27 20:35:02 deruelle_jean * Fix for the compact form of SessionExpires Header from RFC 4028 * * Issue number: * Obtained from: Jozef Saniga * Submitted by: Jean Deruelle * Reviewed by: * * Revision 1.9 2009/07/17 18:58:06 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.8 2006/07/13 09:02:13 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.5 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.4 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.3 2005/10/27 20:49:00 jeroen * added support for RFC3903 PUBLISH * * Revision 1.2 2005/10/08 23:13:56 jeroen * added short form for Allow-Events * * Revision 1.1.1.1 2005/10/04 17:12:36 mranga * * Import * * * Revision 1.5 2005/04/27 14:12:05 mranga * Submitted by: Mario Mantak * Reviewed by: mranga * * Added a missing "short form" for event header. * * Revision 1.4 2004/01/22 13:26:32 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/TokenTypes.java0100644 0000000 0000000 00000034102 13513104763 020451 0ustar000000000 0000000 /* * 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.parser; import gov.nist.core.*; /** * @version 1.2 $Revision: 1.13 $ $Date: 2010/01/12 00:05:25 $ */ public interface TokenTypes { public static final int START = LexerCore.START; // Everything under this is reserved public static final int END = LexerCore.END; // End markder. public static final int SIP = START + 3; public static final int REGISTER = START + 4; public static final int INVITE = START + 5; public static final int ACK = START + 6; public static final int BYE = START + 7; public static final int OPTIONS = START + 8; public static final int CANCEL = START + 9; public static final int ERROR_INFO = START + 10; public static final int IN_REPLY_TO = START + 11; public static final int MIME_VERSION = START + 12; public static final int ALERT_INFO = START + 13; public static final int FROM = START + 14; public static final int TO = START + 15; public static final int VIA = START + 16; public static final int USER_AGENT = START + 17; public static final int SERVER = START + 18; public static final int ACCEPT_ENCODING = START + 19; public static final int ACCEPT = START + 20; public static final int ALLOW = START + 21; public static final int ROUTE = START + 22; public static final int AUTHORIZATION = START + 23; public static final int PROXY_AUTHORIZATION = START + 24; public static final int RETRY_AFTER = START + 25; public static final int PROXY_REQUIRE = START + 26; public static final int CONTENT_LANGUAGE = START + 27; public static final int UNSUPPORTED = START + 28; public static final int SUPPORTED = START + 20; public static final int WARNING = START + 30; public static final int MAX_FORWARDS = START + 31; public static final int DATE = START + 32; public static final int PRIORITY = START + 33; public static final int PROXY_AUTHENTICATE = START + 34; public static final int CONTENT_ENCODING = START + 35; public static final int CONTENT_LENGTH = START + 36; public static final int SUBJECT = START + 37; public static final int CONTENT_TYPE = START + 38; public static final int CONTACT = START + 39; public static final int CALL_ID = START + 40; public static final int REQUIRE = START + 41; public static final int EXPIRES = START + 42; public static final int ENCRYPTION = START + 43; public static final int RECORD_ROUTE = START + 44; public static final int ORGANIZATION = START + 45; public static final int CSEQ = START + 46; public static final int ACCEPT_LANGUAGE = START + 47; public static final int WWW_AUTHENTICATE = START + 48; public static final int RESPONSE_KEY = START + 49; public static final int HIDE = START + 50; public static final int CALL_INFO = START + 51; public static final int CONTENT_DISPOSITION = START + 52; public static final int SUBSCRIBE = START + 53; public static final int NOTIFY = START + 54; public static final int TIMESTAMP = START + 55; public static final int SUBSCRIPTION_STATE = START + 56; public static final int TEL = START + 57; public static final int REPLY_TO = START + 58; public static final int REASON = START + 59; public static final int RSEQ = START + 60; public static final int RACK = START + 61; public static final int MIN_EXPIRES = START + 62; public static final int EVENT = START + 63; public static final int AUTHENTICATION_INFO = START + 64; public static final int ALLOW_EVENTS = START + 65; public static final int REFER_TO = START + 66; // JvB: added to support RFC3903 public static final int PUBLISH = START + 67; public static final int SIP_ETAG = START + 68; public static final int SIP_IF_MATCH = START + 69; public static final int MESSAGE = START + 70; // IMS Headers public static final int PATH = START + 71; public static final int SERVICE_ROUTE = START + 72; public static final int P_ASSERTED_IDENTITY = START + 73; public static final int P_PREFERRED_IDENTITY = START + 74; public static final int P_VISITED_NETWORK_ID = START + 75; public static final int P_CHARGING_FUNCTION_ADDRESSES = START + 76; public static final int P_VECTOR_CHARGING = START + 77; // issued by Miguel Freitas - IMS headers public static final int PRIVACY = START + 78; public static final int P_ACCESS_NETWORK_INFO = START + 79; public static final int P_CALLED_PARTY_ID = START + 80; public static final int P_ASSOCIATED_URI = START + 81; public static final int P_MEDIA_AUTHORIZATION = START + 82; public static final int P_MEDIA_AUTHORIZATION_TOKEN = START + 83; // pmusgrave - additions public static final int REFERREDBY_TO = START + 84; // pmusgrave RFC4028 public static final int SESSIONEXPIRES_TO = START + 85; public static final int MINSE_TO = START + 86; // pmusgrave RFC3891 public static final int REPLACES_TO = START + 87; // pmusgrave sips bug fix public static final int SIPS = START + 88; // issued by Miguel Freitas - SIP Security Agreement (RFC3329) public static final int SECURITY_SERVER = START + 89; public static final int SECURITY_CLIENT = START + 90; public static final int SECURITY_VERIFY = START + 91; // jean deruelle RFC3911 public static final int JOIN_TO = START + 92; // aayush.bhatnagar: RFC 4457 support. public static final int P_USER_DATABASE = START + 93; //aayush.bhatnagar: RFC 5002 support. public static final int P_PROFILE_KEY = START + 94; //aayush.bhatnagar: RFC 5502 support. public static final int P_SERVED_USER = START + 95; //aayush.bhatnaagr: P-Preferred-Service Header: public static final int P_PREFERRED_SERVICE = START + 96; //aayush.bhatnagar: P-Asserted-Service Header: public static final int P_ASSERTED_SERVICE = START + 97; //mranga - References header public static final int REFERENCES = START + 98; public static final int ALPHA = LexerCore.ALPHA; public static final int DIGIT = LexerCore.DIGIT; public static final int ID = LexerCore.ID; public static final int WHITESPACE = LexerCore.WHITESPACE; public static final int BACKSLASH = LexerCore.BACKSLASH; public static final int QUOTE = LexerCore.QUOTE; public static final int AT = LexerCore.AT; public static final int SP = LexerCore.SP; public static final int HT = LexerCore.HT; public static final int COLON = LexerCore.COLON; public static final int STAR = LexerCore.STAR; public static final int DOLLAR = LexerCore.DOLLAR; public static final int PLUS = LexerCore.PLUS; public static final int POUND = LexerCore.POUND; public static final int MINUS = LexerCore.MINUS; public static final int DOUBLEQUOTE = LexerCore.DOUBLEQUOTE; public static final int TILDE = LexerCore.TILDE; public static final int BACK_QUOTE = LexerCore.BACK_QUOTE; public static final int NULL = LexerCore.NULL; public static final int EQUALS = (int) '='; public static final int SEMICOLON = (int) ';'; public static final int SLASH = (int) '/'; public static final int L_SQUARE_BRACKET = (int) '['; public static final int R_SQUARE_BRACKET = (int) ']'; public static final int R_CURLY = (int) '}'; public static final int L_CURLY = (int) '{'; public static final int HAT = (int) '^'; public static final int BAR = (int) '|'; public static final int DOT = (int) '.'; public static final int EXCLAMATION = (int) '!'; public static final int LPAREN = (int) '('; public static final int RPAREN = (int) ')'; public static final int GREATER_THAN = (int) '>'; public static final int LESS_THAN = (int) '<'; public static final int PERCENT = (int) '%'; public static final int QUESTION = (int) '?'; public static final int AND = (int) '&'; public static final int UNDERSCORE = (int) '_'; } /* * $Log: TokenTypes.java,v $ * Revision 1.13 2010/01/12 00:05:25 mranga * Add support for References header draft-worley-references-05 * * Revision 1.12 2009/07/17 18:58:06 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.11 2009/05/10 00:29:53 mranga * * Submitted by: Aayush Bhatnagar * Reviewed by: * IMS headers and parsers. * * Revision 1.10 2009/01/22 19:33:47 deruelle_jean * Add support for JOIN (RFC 3911) * Issue number: 186 * Obtained from: * Submitted by: Jean Deruelle * Reviewed by: Ranga, The high priest and grand poobah of Jain-SIP * * Revision 1.9 2007/01/08 19:24:22 mranga * Issue number: * Obtained from: * Submitted by: Miguel Freitas * Reviewed by: mranga * * Miguel -- please implement a deep clone method for the IMS headers. * * 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.8 2006/10/12 11:57:54 pmusgrave * Issue number: 79, 80 * Submitted by: pmusgrave@newheights.com * Reviewed by: mranga * * Revision 1.7 2006/09/11 18:41:32 mranga * Issue number: * Obtained from: * Submitted by: mranga * Reviewed by: * Tighter integration of IMS headers. * 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.6 2006/07/13 09:01:55 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.4 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.3 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.2 2005/10/27 20:49:00 jeroen * added support for RFC3903 PUBLISH * * Revision 1.1.1.1 2005/10/04 17:12:36 mranga * * Import * * * Revision 1.4 2004/01/22 13:26:32 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/URLParser.java0100644 0000000 0000000 00000063460 13513104763 020174 0ustar000000000 0000000 /* * 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.parser; import gov.nist.core.HostNameParser; import gov.nist.core.HostPort; import gov.nist.core.NameValue; import gov.nist.core.NameValueList; import gov.nist.core.Token; import gov.nist.javax.sip.address.GenericURI; import gov.nist.javax.sip.address.SipUri; import gov.nist.javax.sip.address.TelURLImpl; import gov.nist.javax.sip.address.TelephoneNumber; import java.text.ParseException; /** * 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.27 $ $Date: 2009/10/22 10:27:39 $ * * @author M. Ranganathan
    * * */ public class URLParser extends Parser { public URLParser(String url) { this.lexer = new Lexer("sip_urlLexer", url); } // public tag added - issued by Miguel Freitas public URLParser(Lexer lexer) { this.lexer = lexer; this.lexer.selectLexer("sip_urlLexer"); } protected static boolean isMark(char next) { switch (next) { case '-': case '_': case '.': case '!': case '~': case '*': case '\'': case '(': case ')': return true; default: return false; } } protected static boolean isUnreserved(char next) { return Lexer.isAlphaDigit(next) || isMark(next); } protected static boolean isReservedNoSlash(char next) { switch (next) { case ';': case '?': case ':': case '@': case '&': case '+': case '$': case ',': return true; default: return false; } } // Missing '=' bug in character set - discovered by interop testing // at SIPIT 13 by Bob Johnson and Scott Holben. // change . to ; by Bruno Konik protected static boolean isUserUnreserved(char la) { switch (la) { case '&': case '?': case '+': case '$': case '#': case '/': case ',': case ';': case '=': return true; default: return false; } } protected String unreserved() throws ParseException { char next = lexer.lookAhead(0); if (isUnreserved(next)) { lexer.consume(1); return String.valueOf(next); } else throw createParseException("unreserved"); } /** Name or value of a parameter. */ protected String paramNameOrValue() throws ParseException { int startIdx = lexer.getPtr(); while (lexer.hasMoreChars()) { char next = lexer.lookAhead(0); boolean isValidChar = false; switch (next) { case '[': case ']':// JvB: fixed this one case '/': case ':': case '&': case '+': case '$': isValidChar = true; } if (isValidChar || isUnreserved(next)) { lexer.consume(1); } else if (isEscaped()) { lexer.consume(3); } else break; } return lexer.getBuffer().substring(startIdx, lexer.getPtr()); } private NameValue uriParam() throws ParseException { if (debug) dbg_enter("uriParam"); try { String pvalue = ""; String pname = paramNameOrValue(); char next = lexer.lookAhead(0); boolean isFlagParam = true; if (next == '=') { lexer.consume(1); pvalue = paramNameOrValue(); isFlagParam = false; } if (pname.length() == 0 && ( pvalue == null || pvalue.length() == 0)) return null; else return new NameValue(pname, pvalue, isFlagParam); } finally { if (debug) dbg_leave("uriParam"); } } protected static boolean isReserved(char next) { switch (next) { case ';': case '/': case '?': case ':': case '=': // Bug fix by Bruno Konik case '@': case '&': case '+': case '$': case ',': return true; default: return false; } } protected String reserved() throws ParseException { char next = lexer.lookAhead(0); if (isReserved(next)) { lexer.consume(1); return new StringBuffer().append(next).toString(); } else throw createParseException("reserved"); } protected boolean isEscaped() { try { return lexer.lookAhead(0) == '%' && Lexer.isHexDigit(lexer.lookAhead(1)) && Lexer.isHexDigit(lexer.lookAhead(2)); } catch (Exception ex) { return false; } } protected String escaped() throws ParseException { if (debug) dbg_enter("escaped"); try { StringBuffer retval = new StringBuffer(); char next = lexer.lookAhead(0); char next1 = lexer.lookAhead(1); char next2 = lexer.lookAhead(2); if (next == '%' && Lexer.isHexDigit(next1) && Lexer.isHexDigit(next2)) { lexer.consume(3); retval.append(next); retval.append(next1); retval.append(next2); } else throw createParseException("escaped"); return retval.toString(); } finally { if (debug) dbg_leave("escaped"); } } protected String mark() throws ParseException { if (debug) dbg_enter("mark"); try { char next = lexer.lookAhead(0); if (isMark(next)) { lexer.consume(1); return new String( new char[]{next} ); } else throw createParseException("mark"); } finally { if (debug) dbg_leave("mark"); } } protected String uric() { if (debug) dbg_enter("uric"); try { try { char la = lexer.lookAhead(0); if (isUnreserved(la)) { lexer.consume(1); return Lexer.charAsString(la); } else if (isReserved(la)) { lexer.consume(1); return Lexer.charAsString(la); } else if (isEscaped()) { String retval = lexer.charAsString(3); lexer.consume(3); return retval; } else return null; } catch (Exception ex) { return null; } } finally { if (debug) dbg_leave("uric"); } } protected String uricNoSlash() { if (debug) dbg_enter("uricNoSlash"); try { try { char la = lexer.lookAhead(0); if (isEscaped()) { String retval = lexer.charAsString(3); lexer.consume(3); return retval; } else if (isUnreserved(la)) { lexer.consume(1); return Lexer.charAsString(la); } else if (isReservedNoSlash(la)) { lexer.consume(1); return Lexer.charAsString(la); } else return null; } catch (ParseException ex) { return null; } } finally { if (debug) dbg_leave("uricNoSlash"); } } protected String uricString() throws ParseException { StringBuffer retval = new StringBuffer(); while (true) { String next = uric(); if (next == null) { char la = lexer.lookAhead(0); // JvB: allow IPv6 addresses in generic URI strings // e.g. http://[::1] if ( la == '[' ) { HostNameParser hnp = new HostNameParser(this.getLexer()); HostPort hp = hnp.hostPort( false ); retval.append(hp.toString()); continue; } break; } retval.append(next); } return retval.toString(); } /** * Parse and return a structure for a generic URL. * Note that non SIP URLs are just stored as a string (not parsed). * @return URI is a URL structure for a SIP url. * @throws ParseException if there was a problem parsing. */ public GenericURI uriReference( boolean inBrackets ) throws ParseException { if (debug) dbg_enter("uriReference"); GenericURI retval = null; Token[] tokens = lexer.peekNextToken(2); Token t1 = (Token) tokens[0]; Token t2 = (Token) tokens[1]; try { if (t1.getTokenType() == TokenTypes.SIP || t1.getTokenType() == TokenTypes.SIPS) { if (t2.getTokenType() == ':') retval = sipURL( inBrackets ); else throw createParseException("Expecting \':\'"); } else if (t1.getTokenType() == TokenTypes.TEL) { if (t2.getTokenType() == ':') { retval = telURL( inBrackets ); } else throw createParseException("Expecting \':\'"); } else { String urlString = uricString(); try { retval = new GenericURI(urlString); } catch (ParseException ex) { throw createParseException(ex.getMessage()); } } } finally { if (debug) dbg_leave("uriReference"); } return retval; } /** * Parser for the base phone number. */ private String base_phone_number() throws ParseException { StringBuffer s = new StringBuffer(); if (debug) dbg_enter("base_phone_number"); try { int lc = 0; while (lexer.hasMoreChars()) { char w = lexer.lookAhead(0); if (Lexer.isDigit(w) || w == '-' || w == '.' || w == '(' || w == ')') { lexer.consume(1); s.append(w); lc++; } else if (lc > 0) break; else throw createParseException("unexpected " + w); } return s.toString(); } finally { if (debug) dbg_leave("base_phone_number"); } } /** * Parser for the local phone #. */ private String local_number() throws ParseException { StringBuffer s = new StringBuffer(); if (debug) dbg_enter("local_number"); try { int lc = 0; while (lexer.hasMoreChars()) { char la = lexer.lookAhead(0); if (la == '*' || la == '#' || la == '-' || la == '.' || la == '(' || la == ')' // JvB: allow 'A'..'F', should be uppercase || Lexer.isHexDigit(la)) { lexer.consume(1); s.append(la); lc++; } else if (lc > 0) break; else throw createParseException("unexepcted " + la); } return s.toString(); } finally { if (debug) dbg_leave("local_number"); } } /** * Parser for telephone subscriber. * * @return the parsed telephone number. */ public final TelephoneNumber parseTelephoneNumber( boolean inBrackets ) throws ParseException { TelephoneNumber tn; if (debug) dbg_enter("telephone_subscriber"); lexer.selectLexer("charLexer"); try { char c = lexer.lookAhead(0); if (c == '+') tn = global_phone_number( inBrackets ); else if ( Lexer.isHexDigit(c)// see RFC3966 || c == '#' || c == '*' || c == '-' || c == '.' || c == '(' || c == ')' ) { tn = local_phone_number( inBrackets ); } else throw createParseException("unexpected char " + c); return tn; } finally { if (debug) dbg_leave("telephone_subscriber"); } } private final TelephoneNumber global_phone_number( boolean inBrackets ) throws ParseException { if (debug) dbg_enter("global_phone_number"); try { TelephoneNumber tn = new TelephoneNumber(); tn.setGlobal(true); NameValueList nv = null; this.lexer.match(PLUS); String b = base_phone_number(); tn.setPhoneNumber(b); if (lexer.hasMoreChars()) { char tok = lexer.lookAhead(0); if (tok == ';' && inBrackets) { this.lexer.consume(1); nv = tel_parameters(); tn.setParameters(nv); } } return tn; } finally { if (debug) dbg_leave("global_phone_number"); } } private TelephoneNumber local_phone_number( boolean inBrackets ) throws ParseException { if (debug) dbg_enter("local_phone_number"); TelephoneNumber tn = new TelephoneNumber(); tn.setGlobal(false); NameValueList nv = null; String b = null; try { b = local_number(); tn.setPhoneNumber(b); if (lexer.hasMoreChars()) { Token tok = this.lexer.peekNextToken(); switch (tok.getTokenType()) { case SEMICOLON: { if (inBrackets) { this.lexer.consume(1); nv = tel_parameters(); tn.setParameters(nv); } break; } default : { break; } } } } finally { if (debug) dbg_leave("local_phone_number"); } return tn; } private NameValueList tel_parameters() throws ParseException { NameValueList nvList = new NameValueList(); // JvB: Need to handle 'phone-context' specially // 'isub' (or 'ext') MUST appear first, but we accept any order here NameValue nv; while ( true ) { String pname = paramNameOrValue(); // Handle 'phone-context' specially, it may start with '+' if ( pname.equalsIgnoreCase("phone-context")) { nv = phone_context(); } else { if (lexer.lookAhead(0) == '=') { lexer.consume(1); String value = paramNameOrValue(); nv = new NameValue( pname, value, false ); } else { nv = new NameValue( pname, "", true );// flag param } } nvList.set( nv ); if ( lexer.lookAhead(0) == ';' ) { lexer.consume(1); } else { return nvList; } } } /** * Parses the 'phone-context' parameter in tel: URLs * @throws ParseException */ private NameValue phone_context() throws ParseException { lexer.match('='); char la = lexer.lookAhead(0); Object value; if (la=='+') {// global-number-digits lexer.consume(1);// skip '+' value = "+" + base_phone_number(); } else if ( Lexer.isAlphaDigit(la) ) { Token t = lexer.match( Lexer.ID );// more broad than allowed value = t.getTokenValue(); } else { throw new ParseException( "Invalid phone-context:" + la , -1 ); } return new NameValue( "phone-context", value, false ); } /** * Parse and return a structure for a Tel URL. * @return a parsed tel url structure. */ public TelURLImpl telURL( boolean inBrackets ) throws ParseException { lexer.match(TokenTypes.TEL); lexer.match(':'); TelephoneNumber tn = this.parseTelephoneNumber(inBrackets); TelURLImpl telUrl = new TelURLImpl(); telUrl.setTelephoneNumber(tn); return telUrl; } /** * Parse and return a structure for a SIP URL. * @return a URL structure for a SIP url. * @throws ParseException if there was a problem parsing. */ public SipUri sipURL( boolean inBrackets ) throws ParseException { if (debug) dbg_enter("sipURL"); SipUri retval = new SipUri(); // pmusgrave - handle sips case Token nextToken = lexer.peekNextToken(); int sipOrSips = TokenTypes.SIP; String scheme = TokenNames.SIP; if ( nextToken.getTokenType() == TokenTypes.SIPS) { sipOrSips = TokenTypes.SIPS; scheme = TokenNames.SIPS; } try { lexer.match(sipOrSips); lexer.match(':'); retval.setScheme(scheme); int startOfUser = lexer.markInputPosition(); String userOrHost = user();// Note: user may contain ';', host may not... String passOrPort = null; // name:password or host:port if ( lexer.lookAhead() == ':' ) { lexer.consume(1); passOrPort = password(); } // name@hostPort if ( lexer.lookAhead() == '@' ) { lexer.consume(1); retval.setUser( userOrHost ); if (passOrPort!=null) retval.setUserPassword( passOrPort ); } else { // then userOrHost was a host, backtrack just in case a ';' was eaten... lexer.rewindInputPosition( startOfUser ); } HostNameParser hnp = new HostNameParser(this.getLexer()); HostPort hp = hnp.hostPort( false ); retval.setHostPort(hp); lexer.selectLexer("charLexer"); while (lexer.hasMoreChars()) { // If the URI is not enclosed in brackets, parameters belong to header if (lexer.lookAhead(0) != ';' || !inBrackets) break; lexer.consume(1); NameValue parms = uriParam(); if (parms != null) retval.setUriParameter(parms); } if (lexer.hasMoreChars() && lexer.lookAhead(0) == '?') { lexer.consume(1); while (lexer.hasMoreChars()) { NameValue parms = qheader(); retval.setQHeader(parms); if (lexer.hasMoreChars() && lexer.lookAhead(0) != '&') break; else lexer.consume(1); } } return retval; // BEGIN android-added } catch (RuntimeException e) { throw new ParseException("Invalid URL: " + lexer.getBuffer(), -1); // END android-added } finally { if (debug) dbg_leave("sipURL"); } } public String peekScheme() throws ParseException { Token[] tokens = lexer.peekNextToken(1); if (tokens.length == 0) return null; String scheme = ((Token) tokens[0]).getTokenValue(); return scheme; } /** * Get a name value for a given query header (ie one that comes * after the ?). */ protected NameValue qheader() throws ParseException { String name = lexer.getNextToken('='); lexer.consume(1); String value = hvalue(); return new NameValue(name, value, false); } protected String hvalue() throws ParseException { StringBuffer retval = new StringBuffer(); while (lexer.hasMoreChars()) { char la = lexer.lookAhead(0); // Look for a character that can terminate a URL. boolean isValidChar = false; switch (la) { case '+': case '?': case ':': case '[': case ']': case '/': case '$': case '_': case '-': case '"': case '!': case '~': case '*': case '.': case '(': case ')': isValidChar = true; } if (isValidChar || Lexer.isAlphaDigit(la)) { lexer.consume(1); retval.append(la); } else if (la == '%') { retval.append(escaped()); } else break; } return retval.toString(); } /** * Scan forward until you hit a terminating character for a URL. * We do not handle non sip urls in this implementation. * @return the string that takes us to the end of this URL (i.e. to * the next delimiter). */ protected String urlString() throws ParseException { StringBuffer retval = new StringBuffer(); lexer.selectLexer("charLexer"); while (lexer.hasMoreChars()) { char la = lexer.lookAhead(0); // Look for a character that can terminate a URL. if (la == ' ' || la == '\t' || la == '\n' || la == '>' || la == '<') break; lexer.consume(0); retval.append(la); } return retval.toString(); } protected String user() throws ParseException { if (debug) dbg_enter("user"); try { int startIdx = lexer.getPtr(); while (lexer.hasMoreChars()) { char la = lexer.lookAhead(0); if (isUnreserved(la) || isUserUnreserved(la)) { lexer.consume(1); } else if (isEscaped()) { lexer.consume(3); } else break; } return lexer.getBuffer().substring(startIdx, lexer.getPtr()); } finally { if (debug) dbg_leave("user"); } } protected String password() throws ParseException { int startIdx = lexer.getPtr(); while (true) { char la = lexer.lookAhead(0); boolean isValidChar = false; switch (la) { case '&': case '=': case '+': case '$': case ',': isValidChar = true; } if (isValidChar || isUnreserved(la)) { lexer.consume(1); } else if (isEscaped()) { lexer.consume(3); // bug reported by // Jeff Haynie } else break; } return lexer.getBuffer().substring(startIdx, lexer.getPtr()); } /** * Default parse method. This method just calls uriReference. */ public GenericURI parse() throws ParseException { return uriReference( true ); } // quick test routine for debugging type assignment public static void main(String[] args) throws ParseException { // quick test for sips parsing String[] test = { "sip:alice@example.com", "sips:alice@examples.com" , "sip:3Zqkv5dajqaaas0tCjCxT0xH2ZEuEMsFl0xoasip%3A%2B3519116786244%40siplab.domain.com@213.0.115.163:7070"}; for ( int i = 0; i < test.length; i++) { URLParser p = new URLParser(test[i]); GenericURI uri = p.parse(); System.out.println("uri type returned " + uri.getClass().getName()); System.out.println(test[i] + " is SipUri? " + uri.isSipURI() + ">" + uri.encode()); } } /** **/ } java/gov/nist/javax/sip/parser/UnsupportedParser.java0100644 0000000 0000000 00000014516 13513104763 022060 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import gov.nist.core.*; import java.text.ParseException; /** * Parser for Unsupported header. * * @version 1.2 $Revision: 1.7 $ $Date: 2009/07/17 18:58:07 $ * * @author Olivier Deruelle
    * @author M. Ranganathan
    * * */ public class UnsupportedParser extends HeaderParser { /** * Creates a new instance of UnsupportedParser * @param unsupported - Unsupported header to parse */ public UnsupportedParser(String unsupported) { super(unsupported); } /** * Constructor * @param lexer - the lexer to use to parse the header */ protected UnsupportedParser(Lexer lexer) { super(lexer); } /** * parse the String message * @return SIPHeader (Unsupported object) * @throws SIPParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { UnsupportedList unsupportedList = new UnsupportedList(); if (debug) dbg_enter("UnsupportedParser.parse"); try { headerName(TokenTypes.UNSUPPORTED); while (lexer.lookAhead(0) != '\n') { this.lexer.SPorHT(); Unsupported unsupported = new Unsupported(); unsupported.setHeaderName(SIPHeaderNames.UNSUPPORTED); // Parsing the option tag this.lexer.match(TokenTypes.ID); Token token = lexer.getNextToken(); unsupported.setOptionTag(token.getTokenValue()); this.lexer.SPorHT(); unsupportedList.add(unsupported); while (lexer.lookAhead(0) == ',') { this.lexer.match(','); this.lexer.SPorHT(); unsupported = new Unsupported(); // Parsing the option tag this.lexer.match(TokenTypes.ID); token = lexer.getNextToken(); unsupported.setOptionTag(token.getTokenValue()); this.lexer.SPorHT(); unsupportedList.add(unsupported); } } } finally { if (debug) dbg_leave("UnsupportedParser.parse"); } return unsupportedList; } /** public static void main(String args[]) throws ParseException { String unsupported[] = { "Unsupported: foo \n", "Unsupported: foo1, foo2 ,foo3 , foo4\n" }; for (int i = 0; i < unsupported.length; i++ ) { UnsupportedParser parser = new UnsupportedParser(unsupported[i]); UnsupportedList u= (UnsupportedList) parser.parse(); System.out.println("encoded = " + u.encode()); } } */ } /* * $Log: UnsupportedParser.java,v $ * Revision 1.7 2009/07/17 18:58:07 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.6 2006/07/13 09:01:54 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:36 mranga * * Import * * * Revision 1.4 2004/01/22 13:26:32 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/UserAgentParser.java0100644 0000000 0000000 00000012143 13513104763 021417 0ustar000000000 0000000 /* * 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.parser; import gov.nist.core.Token; import gov.nist.javax.sip.header.*; import java.text.ParseException; /** * Parser for UserAgent header. * * @version 1.2 $Revision: 1.15 $ $Date: 2009/07/17 18:58:07 $ * * @author Olivier Deruelle
    * @author M. Ranganathan
    * * */ public class UserAgentParser extends HeaderParser { /** * Constructor * * @param userAgent - * UserAgent header to parse */ public UserAgentParser(String userAgent) { super(userAgent); } /** * Constructor * * @param lexer - * the lexer to use. */ protected UserAgentParser(Lexer lexer) { super(lexer); } /** * parse the message. Note that we have losened up on the parsing quite a bit because * user agents tend to be very bad about specifying the user agent according to RFC. * * @return SIPHeader (UserAgent object) * @throws SIPParseException * if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { if (debug) dbg_enter("UserAgentParser.parse"); UserAgent userAgent = new UserAgent(); try { headerName(TokenTypes.USER_AGENT); if (this.lexer.lookAhead(0) == '\n') throw createParseException("empty header"); /* * BNF User-Agent = "User-Agent" HCOLON server-val *(LWS server-val) * server-val = product / comment product = token [SLASH * product-version] product-version = token */ while (this.lexer.lookAhead(0) != '\n' && this.lexer.lookAhead(0) != '\0') { if (this.lexer.lookAhead(0) == '(') { String comment = this.lexer.comment(); userAgent.addProductToken('(' + comment + ')'); } else { // product = token [SLASHproduct-version] // product-version = token // The RFC Does NOT allow this space but we are generous in what we accept this.getLexer().SPorHT(); String product = this.lexer.byteStringNoSlash(); if ( product == null ) throw createParseException("Expected product string"); StringBuffer productSb = new StringBuffer(product); // do we possibily have the optional product-version? if (this.lexer.peekNextToken().getTokenType() == TokenTypes.SLASH) { // yes this.lexer.match(TokenTypes.SLASH); // product-version // The RFC Does NOT allow this space but we are generous in what we accept this.getLexer().SPorHT(); String productVersion = this.lexer.byteStringNoSlash(); if ( productVersion == null ) throw createParseException("Expected product version"); productSb.append("/"); productSb.append(productVersion); } userAgent.addProductToken(productSb.toString()); } // LWS this.lexer.SPorHT(); } } finally { if (debug) dbg_leave("UserAgentParser.parse"); } return userAgent; } public static void main(String args[]) throws ParseException { String userAgent[] = { "User-Agent: Softphone/Beta1.5 \n", "User-Agent:Nist/Beta1 (beta version) \n", "User-Agent: Nist UA (beta version)\n", "User-Agent: Nist1.0/Beta2 Ubi/vers.1.0 (very cool) \n" , "User-Agent: SJphone/1.60.299a/L (SJ Labs)\n", "User-Agent: sipXecs/3.5.11 sipXecs/sipxbridge (Linux)\n"}; for (int i = 0; i < userAgent.length; i++ ) { UserAgentParser parser = new UserAgentParser(userAgent[i]); UserAgent ua= (UserAgent) parser.parse(); System.out.println("encoded = " + ua.encode()); } } } java/gov/nist/javax/sip/parser/ViaParser.java0100644 0000000 0000000 00000021323 13513104763 020241 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import gov.nist.core.*; import java.text.ParseException; /** * Parser for via headers. * * @version 1.2 $Revision: 1.12 $ $Date: 2009/07/17 18:58:07 $ * @since 1.1 * * @author Olivier Deruelle * @author M. Ranganathan */ public class ViaParser extends HeaderParser { public ViaParser(String via) { super(via); } public ViaParser(Lexer lexer) { super(lexer); } /** * a parser for the essential part of the via header. */ private void parseVia(Via v) throws ParseException { // The protocol lexer.match(TokenTypes.ID); Token protocolName = lexer.getNextToken(); this.lexer.SPorHT(); // consume the "/" lexer.match('/'); this.lexer.SPorHT(); lexer.match(TokenTypes.ID); this.lexer.SPorHT(); Token protocolVersion = lexer.getNextToken(); this.lexer.SPorHT(); // We consume the "/" lexer.match('/'); this.lexer.SPorHT(); lexer.match(TokenTypes.ID); this.lexer.SPorHT(); Token transport = lexer.getNextToken(); this.lexer.SPorHT(); Protocol protocol = new Protocol(); protocol.setProtocolName(protocolName.getTokenValue()); protocol.setProtocolVersion(protocolVersion.getTokenValue()); protocol.setTransport(transport.getTokenValue()); v.setSentProtocol(protocol); // sent-By HostNameParser hnp = new HostNameParser(this.getLexer()); HostPort hostPort = hnp.hostPort( true ); v.setSentBy(hostPort); // Ignore blanks this.lexer.SPorHT(); // parameters while (lexer.lookAhead(0) == ';') { this.lexer.consume(1); this.lexer.SPorHT(); NameValue nameValue = this.nameValue(); String name = nameValue.getName(); if (name.equals(Via.BRANCH)) { String branchId = (String) nameValue.getValueAsObject(); if (branchId == null) throw new ParseException("null branch Id", lexer.getPtr()); } v.setParameter(nameValue); this.lexer.SPorHT(); } // // JvB Note: RFC3261 does not allow a comment in Via headers anymore // if (lexer.lookAhead(0) == '(') { this.lexer.selectLexer("charLexer"); lexer.consume(1); StringBuffer comment = new StringBuffer(); while (true) { char ch = lexer.lookAhead(0); if (ch == ')') { lexer.consume(1); break; } else if (ch == '\\') { // Escaped character Token tok = lexer.getNextToken(); comment.append(tok.getTokenValue()); lexer.consume(1); tok = lexer.getNextToken(); comment.append(tok.getTokenValue()); lexer.consume(1); } else if (ch == '\n') { break; } else { comment.append(ch); lexer.consume(1); } } v.setComment(comment.toString()); } } /** * Overrides the superclass nameValue parser because we have to tolerate * IPV6 addresses in the received parameter. */ protected NameValue nameValue() throws ParseException { if (debug) dbg_enter("nameValue"); try { lexer.match(LexerCore.ID); Token name = lexer.getNextToken(); // eat white space. lexer.SPorHT(); try { boolean quoted = false; char la = lexer.lookAhead(0); if (la == '=') { lexer.consume(1); lexer.SPorHT(); String str = null; if (name.getTokenValue().compareToIgnoreCase(Via.RECEIVED) == 0) { // Allow for IPV6 Addresses. // these could have : in them! str = lexer.byteStringNoSemicolon(); } else { if (lexer.lookAhead(0) == '\"') { str = lexer.quotedString(); quoted = true; } else { lexer.match(LexerCore.ID); Token value = lexer.getNextToken(); str = value.getTokenValue(); } } NameValue nv = new NameValue(name.getTokenValue() .toLowerCase(), str); if (quoted) nv.setQuotedValue(); return nv; } else { return new NameValue(name.getTokenValue().toLowerCase(), null); } } catch (ParseException ex) { return new NameValue(name.getTokenValue(), null); } } finally { if (debug) dbg_leave("nameValue"); } } public SIPHeader parse() throws ParseException { if (debug) dbg_enter("parse"); try { ViaList viaList = new ViaList(); // The first via header. this.lexer.match(TokenTypes.VIA); this.lexer.SPorHT(); // ignore blanks this.lexer.match(':'); // expect a colon. this.lexer.SPorHT(); // ingore blanks. while (true) { Via v = new Via(); parseVia(v); viaList.add(v); this.lexer.SPorHT(); // eat whitespace. if (this.lexer.lookAhead(0) == ',') { this.lexer.consume(1); // Consume the comma this.lexer.SPorHT(); // Ignore space after. } if (this.lexer.lookAhead(0) == '\n') break; } this.lexer.match('\n'); return viaList; } finally { if (debug) dbg_leave("parse"); } } /** * * public static void main(String args[]) throws ParseException { String * via[] = { "Via: SIP/2.0/UDP 135.180.130.133;branch=-12345\n", "Via: * SIP/2.0/UDP 166.34.120.100;branch=0000045d-00000001"+ ",SIP/2.0/UDP * 166.35.224.216:5000\n", "Via: SIP/2.0/UDP sip33.example.com,"+ " * SIP/2.0/UDP sip32.example.com (oli),"+ "SIP/2.0/UDP sip31.example.com\n", * "Via: SIP/2.0/UDP host.example.com;received=::133;"+ " * branch=C1C3344E2710000000E299E568E7potato10potato0potato0\n", "Via: * SIP/2.0/UDP host.example.com;received=135.180.130.133;"+ " * branch=C1C3344E2710000000E299E568E7potato10potato0potato0\n", "Via: * SIP/2.0/UDP company.com:5604 ( Hello )"+ ", SIP / 2.0 / UDP * 135.180.130.133\n", "Via: SIP/2.0/UDP * 129.6.55.9:7060;received=stinkbug.antd.nist.gov\n", * * "Via: SIP/2.0/UDP ss2.wcom.com:5060;branch=721e418c4.1"+ ", SIP/2.0/UDP * ss1.wcom.com:5060;branch=2d4790.1"+ " , SIP/2.0/UDP here.com:5060( Hello * the big world) \n" ,"Via: SIP/2.0/UDP * ss1.wcom.com:5060;branch=2d4790.1\n", "Via: SIP/2.0/UDP * first.example.com:4000;ttl=16"+ ";maddr=224.2.0.1 ;branch=a7c6a8dlze.1 * (Acme server)\n" }; * * for (int i = 0; i < via.length; i++ ) { ViaParser vp = new * ViaParser(via[i]); System.out.println("toParse = " + via[i]); ViaList vl = * (ViaList) vp.parse(); System.out.println("encoded = " + vl.encode()); } * } * */ } java/gov/nist/javax/sip/parser/WWWAuthenticateParser.java0100644 0000000 0000000 00000011456 13513104763 022553 0ustar000000000 0000000 /* * 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.parser; import java.text.ParseException; import gov.nist.javax.sip.header.*; /** * Parser for WWW authenitcate header. * * @version 1.2 $Revision: 1.7 $ $Date: 2009/07/17 18:58:07 $ * * @author Olivier Deruelle
    * @author M. Ranganathan
    * * */ public class WWWAuthenticateParser extends ChallengeParser { /** * Constructor * @param wwwAuthenticate - message to parse */ public WWWAuthenticateParser(String wwwAuthenticate) { super(wwwAuthenticate); } /** * Cosntructor * @param lexer - lexer to use. */ protected WWWAuthenticateParser(Lexer lexer) { super(lexer); } /** * parse the String message * @return SIPHeader (WWWAuthenticate object) * @throws SIPParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { if (debug) dbg_enter("parse"); try { headerName(TokenTypes.WWW_AUTHENTICATE); WWWAuthenticate wwwAuthenticate = new WWWAuthenticate(); super.parse(wwwAuthenticate); return wwwAuthenticate; } finally { if (debug) dbg_leave("parse"); } } } /* * $Log: WWWAuthenticateParser.java,v $ * Revision 1.7 2009/07/17 18:58:07 emcho * Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project. * * Revision 1.6 2006/07/13 09:02:15 mranga * Issue number: * Obtained from: * Submitted by: jeroen van bemmel * Reviewed by: mranga * Moved some changes from jain-sip-1.2 to java.net * * 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.3 2006/06/19 06:47:27 mranga * javadoc fixups * * Revision 1.2 2006/06/16 15:26:28 mranga * Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak * * Revision 1.1.1.1 2005/10/04 17:12:36 mranga * * Import * * * Revision 1.4 2004/01/22 13:26:32 sverker * Issue number: * Obtained from: * Submitted by: sverker * Reviewed by: mranga * * Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags. * * 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. * */ java/gov/nist/javax/sip/parser/WarningParser.java0100644 0000000 0000000 00000014556 13513104763 021141 0ustar000000000 0000000 /* * 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.parser; import gov.nist.javax.sip.header.*; import gov.nist.core.*; import java.text.ParseException; import javax.sip.*; /** * Parser for Warning header. * * @version 1.2 * * @author Olivier Deruelle * @author M. Ranganathan * * * * @version 1.0 */ public class WarningParser extends HeaderParser { /** * Constructor * * @param warning - * Warning header to parse */ public WarningParser(String warning) { super(warning); } /** * Cosntructor * * @param lexer - * the lexer to use. */ protected WarningParser(Lexer lexer) { super(lexer); } /** * parse the String message * * @return SIPHeader (WarningList object) * @throws SIPParseException * if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { WarningList warningList = new WarningList(); if (debug) dbg_enter("WarningParser.parse"); try { headerName(TokenTypes.WARNING); while (lexer.lookAhead(0) != '\n') { Warning warning = new Warning(); warning.setHeaderName(SIPHeaderNames.WARNING); // Parsing the 3digits code this.lexer.match(TokenTypes.ID); Token token = lexer.getNextToken(); try { int code = Integer.parseInt(token.getTokenValue()); warning.setCode(code); } catch (NumberFormatException ex) { throw createParseException(ex.getMessage()); } catch (InvalidArgumentException ex) { throw createParseException(ex.getMessage()); } this.lexer.SPorHT(); // Parsing the agent this.lexer.match(TokenTypes.ID); token = lexer.getNextToken(); // Bug reported by zvali@dev.java.net if (lexer.lookAhead(0) == ':') { this.lexer.match(':'); this.lexer.match(TokenTypes.ID); Token token2 = lexer.getNextToken(); warning.setAgent(token.getTokenValue() + ":" + token2.getTokenValue()); } else { warning.setAgent(token.getTokenValue()); } this.lexer.SPorHT(); // Parsing the text String text = this.lexer.quotedString(); warning.setText(text); this.lexer.SPorHT(); warningList.add(warning); while (lexer.lookAhead(0) == ',') { this.lexer.match(','); this.lexer.SPorHT(); warning = new Warning(); // Parsing the 3digits code this.lexer.match(TokenTypes.ID); Token tok = lexer.getNextToken(); try { int code = Integer.parseInt(tok.getTokenValue()); warning.setCode(code); } catch (NumberFormatException ex) { throw createParseException(ex.getMessage()); } catch (InvalidArgumentException ex) { throw createParseException(ex.getMessage()); } this.lexer.SPorHT(); // Parsing the agent this.lexer.match(TokenTypes.ID); tok = lexer.getNextToken(); // Bug reported by zvali@dev.java.net if (lexer.lookAhead(0) == ':') { this.lexer.match(':'); this.lexer.match(TokenTypes.ID); Token token2 = lexer.getNextToken(); warning.setAgent(tok.getTokenValue() + ":" + token2.getTokenValue()); } else { warning.setAgent(tok.getTokenValue()); } this.lexer.SPorHT(); // Parsing the text text = this.lexer.quotedString(); warning.setText(text); this.lexer.SPorHT(); warningList.add(warning); } } } finally { if (debug) dbg_leave("WarningParser.parse"); } return warningList; } /** * public static void main(String args[]) throws ParseException { String * warning[] = { "Warning: 307 isi.edu \"Session parameter 'foo' not * understood\"\n", "Warning: 301 isi.edu \"Incompatible network address * type 'E.164'\"\n", "Warning: 312 ii.edu \"Soda\", "+ " 351 i.edu \"I * network address 'E.164'\" , 323 ii.edu \"Sodwea\"\n", "Warning: 392 * 192.168.89.71:5060 \"Noisy feedback tells: pid=936 * req_src_ip=192.168.89.20 in_uri=sip:xxx@yyyy.org:5061 * out_uri=sip:xxx@yyyy.org:5061 via_cnt==1\"\n" }; * * for (int i = 0; i < warning.length; i++ ) { WarningParser parser = new * WarningParser(warning[i]); WarningList warningList= (WarningList) * parser.parse(); System.out.println("encoded = " + warningList.encode()); } * } */ } java/gov/nist/javax/sip/parser/extensions/0040755 0000000 0000000 00000000000 13513104763 017703 5ustar000000000 0000000 java/gov/nist/javax/sip/parser/extensions/JoinParser.java0100644 0000000 0000000 00000004126 13513104763 022622 0ustar000000000 0000000 package gov.nist.javax.sip.parser.extensions; import gov.nist.javax.sip.header.*; import gov.nist.javax.sip.header.extensions.*; import gov.nist.javax.sip.parser.*; import java.text.ParseException; // Parser for Join Header (RFC3911) // Extension by jean deruelle // // Join = "Join" HCOLON callid *(SEMI join-param) // join-param = to-tag / from-tag / generic-param // to-tag = "to-tag" EQUAL token // from-tag = "from-tag" EQUAL token // // public class JoinParser extends ParametersParser { /** * Creates new CallIDParser * @param callID message to parse */ public JoinParser(String callID) { super(callID); } /** * Constructor * @param lexer Lexer to set */ protected JoinParser(Lexer lexer) { super(lexer); } /** * parse the String message * @return SIPHeader (CallID object) * @throws ParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { if (debug) dbg_enter("parse"); try { headerName(TokenTypes.JOIN_TO); Join join = new Join(); this.lexer.SPorHT(); String callId = lexer.byteStringNoSemicolon(); this.lexer.SPorHT(); super.parse(join); join.setCallId(callId); return join; } finally { if (debug) dbg_leave("parse"); } } public static void main(String args[]) throws ParseException { String to[] = { "Join: 12345th5z8z\n", "Join: 12345th5z8z;to-tag=tozght6-45;from-tag=fromzght789-337-2\n", }; for (int i = 0; i < to.length; i++) { JoinParser tp = new JoinParser(to[i]); Join t = (Join) tp.parse(); System.out.println("Parsing => " + to[i]); System.out.print("encoded = " + t.encode() + "==> "); System.out.println("callId " + t.getCallId() + " from-tag=" + t.getFromTag() + " to-tag=" + t.getToTag()) ; } } } java/gov/nist/javax/sip/parser/extensions/MinSEParser.java0100644 0000000 0000000 00000004403 13513104763 022674 0ustar000000000 0000000 package gov.nist.javax.sip.parser.extensions; import gov.nist.javax.sip.header.*; import gov.nist.javax.sip.header.extensions.*; import gov.nist.javax.sip.parser.*; import java.text.ParseException; import javax.sip.*; /** * Parser for SIP MinSE Parser. * * Min-SE = "Min-SE" HCOLON delta-seconds *(SEMI generic-param) * * @author P. Musgrave * * This code is in the public domain. */ public class MinSEParser extends ParametersParser { /** * protected constructor. * @param text is the text of the header to parse */ public MinSEParser(String text) { super(text); } /** * constructor. * @param lexer is the lexer passed in from the enclosing parser. */ protected MinSEParser(Lexer lexer) { super(lexer); } /** * Parse the header. */ public SIPHeader parse() throws ParseException { MinSE minse = new MinSE(); if (debug) dbg_enter("parse"); try { headerName(TokenTypes.MINSE_TO); String nextId = lexer.getNextId(); try { int delta = Integer.parseInt(nextId); minse.setExpires(delta); } catch (NumberFormatException ex) { throw createParseException("bad integer format"); } catch (InvalidArgumentException ex) { throw createParseException(ex.getMessage()); } this.lexer.SPorHT(); super.parse(minse); return minse; } finally { if (debug) dbg_leave("parse"); } } public static void main(String args[]) throws ParseException { String to[] = { "Min-SE: 30\n", "Min-SE: 45;some-param=somevalue\n", }; for (int i = 0; i < to.length; i++) { MinSEParser tp = new MinSEParser(to[i]); MinSE t = (MinSE) tp.parse(); System.out.println("encoded = " + t.encode()); System.out.println("\ntime=" + t.getExpires() ); if ( t.getParameter("some-param") != null) System.out.println("some-param=" + t.getParameter("some-param") ); } } } java/gov/nist/javax/sip/parser/extensions/ReferencesParser.java0100644 0000000 0000000 00000003124 13513104763 024001 0ustar000000000 0000000 package gov.nist.javax.sip.parser.extensions; import gov.nist.core.Token; import gov.nist.javax.sip.header.Reason; import gov.nist.javax.sip.header.ReasonList; import gov.nist.javax.sip.header.SIPHeader; import gov.nist.javax.sip.header.extensions.References; import gov.nist.javax.sip.parser.Lexer; import gov.nist.javax.sip.parser.ParametersParser; import gov.nist.javax.sip.parser.TokenTypes; import java.text.ParseException; public class ReferencesParser extends ParametersParser { /** * Creates a new instance of ReferencesParser * @param references the header to parse */ public ReferencesParser(String references) { super(references); } /** * Constructor * @param lexer the lexer to use to parse the header */ protected ReferencesParser(Lexer lexer) { super(lexer); } /** * parse the String message * @return SIPHeader (ReasonParserList object) * @throws SIPParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { if (debug) dbg_enter("ReasonParser.parse"); try { headerName(TokenTypes.REFERENCES); References references= new References(); this.lexer.SPorHT(); String callId = lexer.byteStringNoSemicolon(); references.setCallId(callId); super.parse(references); return references; } finally { if (debug) dbg_leave("ReferencesParser.parse"); } } } java/gov/nist/javax/sip/parser/extensions/ReferredByParser.java0100644 0000000 0000000 00000003367 13513104763 023762 0ustar000000000 0000000 package gov.nist.javax.sip.parser.extensions; import java.text.ParseException; import gov.nist.javax.sip.header.*; import gov.nist.javax.sip.header.extensions.*; import gov.nist.javax.sip.parser.*; /** * ReferredBy Header parser. * * This code is in the public domain. * * Based on JAIN ReferToParser * */ public class ReferredByParser extends AddressParametersParser { /** * Creates new ToParser * @param referBy String to set */ public ReferredByParser(String referBy) { super(referBy); } protected ReferredByParser(Lexer lexer) { super(lexer); } public SIPHeader parse() throws ParseException { headerName(TokenTypes.REFERREDBY_TO); ReferredBy referBy = new ReferredBy(); super.parse(referBy); this.lexer.match('\n'); return referBy; } public static void main(String args[]) throws ParseException { String to[] = { "Referred-By: \n", "Referred-By: ;tag=5617\n", "Referred-By: T. A. Watson \n", "Referred-By: LittleGuy \n", "Referred-By: sip:mranga@120.6.55.9\n", "Referred-By: sip:mranga@129.6.55.9 ; tag=696928473514.129.6.55.9\n" }; for (int i = 0; i < to.length; i++) { ReferredByParser tp = new ReferredByParser(to[i]); ReferredBy t = (ReferredBy) tp.parse(); System.out.println("encoded = " + t.encode()); } } } /* * $Log: * */ java/gov/nist/javax/sip/parser/extensions/ReplacesParser.java0100644 0000000 0000000 00000004402 13513104763 023456 0ustar000000000 0000000 package gov.nist.javax.sip.parser.extensions; import gov.nist.javax.sip.header.*; import gov.nist.javax.sip.header.extensions.*; import gov.nist.javax.sip.parser.*; import java.text.ParseException; // Parser for Replaces Header (RFC3891) // Extension by pmusgrave // // Replaces = "Replaces" HCOLON callid *(SEMI replaces-param) // replaces-param = to-tag / from-tag / early-flag / generic-param // to-tag = "to-tag" EQUAL token // from-tag = "from-tag" EQUAL token // early-flag = "early-only" // // TODO Should run a test case on early-only // public class ReplacesParser extends ParametersParser { /** * Creates new CallIDParser * @param callID message to parse */ public ReplacesParser(String callID) { super(callID); } /** * Constructor * @param lexer Lexer to set */ protected ReplacesParser(Lexer lexer) { super(lexer); } /** * parse the String message * @return SIPHeader (CallID object) * @throws ParseException if the message does not respect the spec. */ public SIPHeader parse() throws ParseException { if (debug) dbg_enter("parse"); try { headerName(TokenTypes.REPLACES_TO); Replaces replaces = new Replaces(); this.lexer.SPorHT(); String callId = lexer.byteStringNoSemicolon(); this.lexer.SPorHT(); super.parse(replaces); replaces.setCallId(callId); return replaces; } finally { if (debug) dbg_leave("parse"); } } public static void main(String args[]) throws ParseException { String to[] = { "Replaces: 12345th5z8z\n", "Replaces: 12345th5z8z;to-tag=tozght6-45;from-tag=fromzght789-337-2\n", }; for (int i = 0; i < to.length; i++) { ReplacesParser tp = new ReplacesParser(to[i]); Replaces t = (Replaces) tp.parse(); System.out.println("Parsing => " + to[i]); System.out.print("encoded = " + t.encode() + "==> "); System.out.println("callId " + t.getCallId() + " from-tag=" + t.getFromTag() + " to-tag=" + t.getToTag()) ; } } } java/gov/nist/javax/sip/parser/extensions/SessionExpiresParser.java0100644 0000000 0000000 00000004277 13513104763 024715 0ustar000000000 0000000 package gov.nist.javax.sip.parser.extensions; import gov.nist.javax.sip.header.*; import gov.nist.javax.sip.header.extensions.*; import gov.nist.javax.sip.parser.*; import java.text.ParseException; import javax.sip.*; /** * Parser for SIP Session Expires Header. * * */ public class SessionExpiresParser extends ParametersParser { /** * protected constructor. * @param text is the text of the header to parse */ public SessionExpiresParser(String text) { super(text); } /** * constructor. * @param lexer is the lexer passed in from the enclosing parser. */ protected SessionExpiresParser(Lexer lexer) { super(lexer); } /** * Parse the header. */ public SIPHeader parse() throws ParseException { SessionExpires se = new SessionExpires(); if (debug) dbg_enter("parse"); try { headerName(TokenTypes.SESSIONEXPIRES_TO); String nextId = lexer.getNextId(); try { int delta = Integer.parseInt(nextId); se.setExpires(delta); } catch (NumberFormatException ex) { throw createParseException("bad integer format"); } catch (InvalidArgumentException ex) { throw createParseException(ex.getMessage()); } // May have parameters... this.lexer.SPorHT(); super.parse(se); return se; } finally { if (debug) dbg_leave("parse"); } } public static void main(String args[]) throws ParseException { String to[] = { "Session-Expires: 30\n", "Session-Expires: 45;refresher=uac\n", }; for (int i = 0; i < to.length; i++) { SessionExpiresParser tp = new SessionExpiresParser(to[i]); SessionExpires t = (SessionExpires) tp.parse(); System.out.println("encoded = " + t.encode()); System.out.println("\ntime=" + t.getExpires() ); if ( t.getParameter("refresher") != null) System.out.println("refresher=" + t.getParameter("refresher") ); } } } java/gov/nist/javax/sip/parser/ims/0040755 0000000 0000000 00000000000 13513104763 016274 5ustar000000000 0000000 java/gov/nist/javax/sip/parser/ims/AddressHeaderParser.java0100644 0000000 0000000 00000004336 13513104763 023015 0ustar000000000 0000000 /* * 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 PT INOVACAO - EST DEPARTMENT * *******************************************/ package gov.nist.javax.sip.parser.ims; import gov.nist.javax.sip.address.AddressImpl; import gov.nist.javax.sip.parser.AddressParser; import gov.nist.javax.sip.parser.HeaderParser; import gov.nist.javax.sip.parser.Lexer; import java.text.ParseException; import gov.nist.javax.sip.header.ims.AddressHeaderIms; /** * @author ALEXANDRE MIGUEL SILVA SANTOS */ abstract class AddressHeaderParser extends HeaderParser { protected AddressHeaderParser(Lexer lexer) { super(lexer); } protected AddressHeaderParser(String buffer) { super(buffer); } protected void parse(AddressHeaderIms addressHeader) throws ParseException { dbg_enter("AddressHeaderParser.parse"); try { AddressParser addressParser = new AddressParser(this.getLexer()); AddressImpl addr = addressParser.address(true); addressHeader.setAddress(addr); } catch (ParseException ex) { throw ex; } finally { dbg_leave("AddressParametersParser.parse"); } } } java/gov/nist/javax/sip/parser/ims/PAccessNetworkInfoParser.java0100644 0000000 0000000 00000010032 13513104763 024014 0ustar000000000 0000000 /* * 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 PT INOVACAO - EST DEPARTMENT and Telecommunications Institute (Aveiro, Portugal) * ************************************************************************************************/ package gov.nist.javax.sip.parser.ims; import java.text.ParseException; import gov.nist.javax.sip.header.ims.PAccessNetworkInfo; import gov.nist.javax.sip.header.ims.SIPHeaderNamesIms; import gov.nist.core.Token; import gov.nist.core.NameValue; import gov.nist.javax.sip.header.SIPHeader; import gov.nist.javax.sip.parser.HeaderParser; import gov.nist.javax.sip.parser.Lexer; import gov.nist.javax.sip.parser.ParametersParser; import gov.nist.javax.sip.parser.TokenTypes; /** * P-Access-Network-Info header parser. * *

    RFC 3455 - Private Header (P-Header) Extensions to the Session Initiation * Protocol (SIP) for the 3rd-Generation Partnership Project (3GPP)

    * *

    Sintax (RFC 3455):

    *
     * P-Access-Network-Info  = "P-Access-Network-Info" HCOLON access-net-spec
     * access-net-spec        = access-type *(SEMI access-info)
     * access-type            = "IEEE-802.11a" / "IEEE-802.11b" /
     *                          "3GPP-GERAN" / "3GPP-UTRAN-FDD" /
     *                          "3GPP-UTRAN-TDD" / "3GPP-CDMA2000" / token
     * access-info            = cgi-3gpp / utran-cell-id-3gpp / extension-access-info
     * extension-access-info  = gen-value
     * cgi-3gpp               = "cgi-3gpp" EQUAL (token / quoted-string)
     * utran-cell-id-3gpp     = "utran-cell-id-3gpp" EQUAL (token / quoted-string)
     * 
    * * @author Miguel Freitas (IT) PT-Inovacao */ public class PAccessNetworkInfoParser extends HeaderParser implements TokenTypes { public PAccessNetworkInfoParser(String accessNetwork) { super(accessNetwork); } protected PAccessNetworkInfoParser(Lexer lexer) { super(lexer); } public SIPHeader parse() throws ParseException { if (debug) dbg_enter("AccessNetworkInfoParser.parse"); try { headerName(TokenTypes.P_ACCESS_NETWORK_INFO); PAccessNetworkInfo accessNetworkInfo = new PAccessNetworkInfo(); accessNetworkInfo.setHeaderName(SIPHeaderNamesIms.P_ACCESS_NETWORK_INFO); this.lexer.SPorHT(); lexer.match(TokenTypes.ID); Token token = lexer.getNextToken(); accessNetworkInfo.setAccessType(token.getTokenValue()); this.lexer.SPorHT(); while (lexer.lookAhead(0) == ';') { this.lexer.match(';'); this.lexer.SPorHT(); NameValue nv = super.nameValue('='); accessNetworkInfo.setParameter(nv); this.lexer.SPorHT(); } this.lexer.SPorHT(); this.lexer.match('\n'); return accessNetworkInfo; } finally { if (debug) dbg_leave("AccessNetworkInfoParser.parse"); } } } java/gov/nist/javax/sip/parser/ims/PAssertedIdentityParser.java0100644 0000000 0000000 00000006066 13513104763 023725 0ustar000000000 0000000 /* * 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 PT INOVACAO - EST DEPARTMENT * *******************************************/ package gov.nist.javax.sip.parser.ims; import gov.nist.javax.sip.parser.Lexer; import gov.nist.javax.sip.parser.TokenTypes; import java.text.ParseException; import gov.nist.javax.sip.header.SIPHeader; import gov.nist.javax.sip.header.ims.PAssertedIdentity; import gov.nist.javax.sip.header.ims.PAssertedIdentityList; import gov.nist.javax.sip.header.ims.SIPHeaderNamesIms; import gov.nist.javax.sip.parser.AddressParametersParser; /** * @author ALEXANDRE MIGUEL SILVA SANTOS */ public class PAssertedIdentityParser extends AddressParametersParser implements TokenTypes{ /** * Constructor * @param assertedIdentity - message to parse to set */ public PAssertedIdentityParser(String assertedIdentity) { super(assertedIdentity); } protected PAssertedIdentityParser(Lexer lexer) { super(lexer); } public SIPHeader parse() throws ParseException { if (debug) dbg_enter("AssertedIdentityParser.parse"); PAssertedIdentityList assertedIdList = new PAssertedIdentityList(); try { headerName(TokenTypes.P_ASSERTED_IDENTITY); PAssertedIdentity pai = new PAssertedIdentity(); pai.setHeaderName(SIPHeaderNamesIms.P_ASSERTED_IDENTITY); super.parse(pai); assertedIdList.add(pai); this.lexer.SPorHT(); while (lexer.lookAhead(0) == ',') { this.lexer.match(','); this.lexer.SPorHT(); pai = new PAssertedIdentity(); super.parse(pai); assertedIdList.add(pai); this.lexer.SPorHT(); } this.lexer.SPorHT(); this.lexer.match('\n'); return assertedIdList; } finally { if (debug) dbg_leave("AssertedIdentityParser.parse"); } } } java/gov/nist/javax/sip/parser/ims/PAssertedServiceParser.java0100644 0000000 0000000 00000007743 13513104763 023537 0ustar000000000 0000000 package gov.nist.javax.sip.parser.ims; /* * 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 * * . * */ import java.text.ParseException; import javax.sip.InvalidArgumentException; import gov.nist.javax.sip.header.SIPHeader; import gov.nist.javax.sip.header.ims.PAssertedService; import gov.nist.javax.sip.header.ims.ParameterNamesIms; import gov.nist.javax.sip.parser.HeaderParser; import gov.nist.javax.sip.parser.Lexer; import gov.nist.javax.sip.parser.TokenTypes; /** * * @author aayush.bhatnagar * Rancore Technologies Pvt Ltd, Mumbai India. * * Parse this: * P-Asserted-Service: urn:urn-7:3gpp-service.exampletelephony.version1 * */ public class PAssertedServiceParser extends HeaderParser implements TokenTypes{ protected PAssertedServiceParser(Lexer lexer) { super(lexer); } public PAssertedServiceParser(String pas) { super(pas); } public SIPHeader parse() throws ParseException { if(debug) dbg_enter("PAssertedServiceParser.parse"); try { this.lexer.match(TokenTypes.P_ASSERTED_SERVICE); this.lexer.SPorHT(); this.lexer.match(':'); this.lexer.SPorHT(); PAssertedService pps = new PAssertedService(); String urn = this.lexer.getBuffer(); if(urn.contains(ParameterNamesIms.SERVICE_ID)){ if(urn.contains(ParameterNamesIms.SERVICE_ID_LABEL)) { String serviceID = urn.split(ParameterNamesIms.SERVICE_ID_LABEL+".")[1]; if(serviceID.trim().equals("")) try { throw new InvalidArgumentException("URN should atleast have one sub-service"); } catch (InvalidArgumentException e) { e.printStackTrace(); } else pps.setSubserviceIdentifiers(urn.split(ParameterNamesIms.SERVICE_ID_LABEL)[1]); } else if(urn.contains(ParameterNamesIms.APPLICATION_ID_LABEL)) { String appID = urn.split(ParameterNamesIms.APPLICATION_ID_LABEL+".")[1]; if(appID.trim().equals("")) try { throw new InvalidArgumentException("URN should atleast have one sub-application"); } catch (InvalidArgumentException e) { e.printStackTrace(); } else pps.setApplicationIdentifiers(urn.split(ParameterNamesIms.APPLICATION_ID_LABEL)[1]); } else { try { throw new InvalidArgumentException("URN is not well formed"); } catch (InvalidArgumentException e) { e.printStackTrace(); } } } super.parse(); return pps; } finally{ if(debug) dbg_enter("PAssertedServiceParser.parse"); } } } java/gov/nist/javax/sip/parser/ims/PAssociatedURIParser.java0100644 0000000 0000000 00000010242 13513104763 023067 0ustar000000000 0000000 /* * 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 PT INOVACAO - EST DEPARTMENT and Aveiro University (Portugal) * ****************************************************************************/ package gov.nist.javax.sip.parser.ims; import java.text.ParseException; import gov.nist.core.Token; import gov.nist.javax.sip.address.GenericURI; import gov.nist.javax.sip.header.ims.PAssociatedURI; import gov.nist.javax.sip.header.ims.PAssociatedURIList; import gov.nist.javax.sip.header.ims.SIPHeaderNamesIms; import gov.nist.javax.sip.header.Allow; import gov.nist.javax.sip.header.ErrorInfo; import gov.nist.javax.sip.header.SIPHeader; import gov.nist.javax.sip.header.SIPHeaderNames; import gov.nist.javax.sip.parser.Lexer; import gov.nist.javax.sip.parser.TokenTypes; import gov.nist.javax.sip.parser.AddressParametersParser; import gov.nist.javax.sip.parser.URLParser; import gov.nist.javax.sip.parser.ParametersParser; import gov.nist.javax.sip.parser.HeaderParser; /** * P-Associated-URI header parser * * @author Miguel Freitas (IT) PT-Inovacao */ public class PAssociatedURIParser extends AddressParametersParser { /** * Constructor * @param associatedURI content to set */ public PAssociatedURIParser(String associatedURI) { super(associatedURI); } protected PAssociatedURIParser(Lexer lexer) { super(lexer); } public SIPHeader parse() throws ParseException { if (debug) dbg_enter("PAssociatedURIParser.parse"); PAssociatedURIList associatedURIList = new PAssociatedURIList(); try { headerName(TokenTypes.P_ASSOCIATED_URI); PAssociatedURI associatedURI = new PAssociatedURI(); associatedURI.setHeaderName(SIPHeaderNamesIms.P_ASSOCIATED_URI); super.parse(associatedURI); associatedURIList.add(associatedURI); this.lexer.SPorHT(); while (lexer.lookAhead(0) == ',') { this.lexer.match(','); this.lexer.SPorHT(); associatedURI = new PAssociatedURI(); super.parse(associatedURI); associatedURIList.add(associatedURI); this.lexer.SPorHT(); } this.lexer.SPorHT(); this.lexer.match('\n'); return associatedURIList; } finally { if (debug) dbg_leave("PAssociatedURIParser.parse"); } } /** Test program public static void main(String args[]) throws ParseException { String rou[] = { "P-Associated-URI: \n", "P-Associated-URI: , " + " \n" }; for (int i = 0; i < rou.length; i++ ) { PAssociatedURIParser rp = new PAssociatedURIParser(rou[i]); PAssociatedURIList list = (PAssociatedURIList) rp.parse(); System.out.println("encoded = " +list.encode()); } } */ } java/gov/nist/javax/sip/parser/ims/PCalledPartyIDParser.java0100644 0000000 0000000 00000006166 13513104763 023063 0ustar000000000 0000000 /* * 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 PT INOVACAO - EST DEPARTMENT and Aveiro University (Portugal) * ****************************************************************************/ package gov.nist.javax.sip.parser.ims; import java.text.ParseException; import gov.nist.javax.sip.header.ims.PCalledPartyID; import gov.nist.javax.sip.header.SIPHeader; import gov.nist.javax.sip.parser.Lexer; import gov.nist.javax.sip.parser.TokenTypes; import gov.nist.javax.sip.parser.AddressParametersParser; /** * P-Called-Party-ID header parser * * @author Miguel Freitas (IT) PT-Inovacao */ public class PCalledPartyIDParser extends AddressParametersParser { /** * Constructor * @param calledPartyID content to set */ public PCalledPartyIDParser(String calledPartyID) { super(calledPartyID); } protected PCalledPartyIDParser(Lexer lexer) { super(lexer); } public SIPHeader parse() throws ParseException { if (debug) dbg_enter("PCalledPartyIDParser.parse"); try { this.lexer.match(TokenTypes.P_CALLED_PARTY_ID); this.lexer.SPorHT(); this.lexer.match(':'); this.lexer.SPorHT(); PCalledPartyID calledPartyID = new PCalledPartyID(); super.parse(calledPartyID); return calledPartyID; } finally { if (debug) dbg_leave("PCalledPartyIDParser.parse"); } } /** Test program public static void main(String args[]) throws ParseException { String rou[] = { "P-Associated-URI: , " + " \n" }; for (int i = 0; i < rou.length; i++ ) { RecordRouteParser rp = new RecordRouteParser(rou[i]); RecordRouteList recordRouteList = (RecordRouteList) rp.parse(); System.out.println("encoded = " +recordRouteList.encode()); } } */ } java/gov/nist/javax/sip/parser/ims/PChargingFunctionAddressesParser.java0100644 0000000 0000000 00000012045 13513104763 025521 0ustar000000000 0000000 /* * 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 PT INOVACAO - EST DEPARTMENT * *******************************************/ package gov.nist.javax.sip.parser.ims; import gov.nist.core.NameValue; import gov.nist.javax.sip.header.SIPHeader; import gov.nist.javax.sip.header.ims.PChargingFunctionAddresses; import gov.nist.javax.sip.parser.Lexer; import gov.nist.javax.sip.parser.ParametersParser; import gov.nist.javax.sip.parser.TokenTypes; import java.text.ParseException; /** * P-Charging-Function-Addresses header parser. * *

    Sintax (RFC 3455):

    *
     * P-Charging-Addr    = "P-Charging-Function-Addresses" HCOLON
     *                      charge-addr-params
     *                      * (SEMI charge-addr-params)
     * charge-addr-params = ccf / ecf / generic-param
     * ccf                = "ccf" EQUAL gen-value
     * ecf                = "ecf" EQUAL gen-value
     * gen-value          = token / host / quoted-string
     * host               = hostname / IPv4address / IPv6reference
     * hostname           = *( domainlabel "." ) toplabel [ "." ]
     * domainlabel        = alphanum / alphanum *( alphanum / "-" ) alphanum
     * toplabel           = ALPHA / ALPHA *( alphanum / "-" ) alphanum
     * ipv6reference      = "[" IPv6address "]"
     *
     * 
    * * @author ALEXANDRE MIGUEL SILVA SANTOS * @author aayush.bhatnagar: proposed change to allow duplicate ecf and ccf header parameters. */ public class PChargingFunctionAddressesParser extends ParametersParser implements TokenTypes { public PChargingFunctionAddressesParser(String charging) { super(charging); } protected PChargingFunctionAddressesParser(Lexer lexer) { super(lexer); } public SIPHeader parse() throws ParseException { if (debug) dbg_enter("parse"); try { headerName(TokenTypes.P_CHARGING_FUNCTION_ADDRESSES); PChargingFunctionAddresses chargingFunctionAddresses = new PChargingFunctionAddresses(); try { while (lexer.lookAhead(0) != '\n') { this.parseParameter(chargingFunctionAddresses); this.lexer.SPorHT(); char la = lexer.lookAhead(0); if (la == '\n' || la == '\0') break; this.lexer.match(';'); this.lexer.SPorHT(); } } catch (ParseException ex) { throw ex; } super.parse(chargingFunctionAddresses); return chargingFunctionAddresses; } finally { if (debug) dbg_leave("parse"); } } protected void parseParameter(PChargingFunctionAddresses chargingFunctionAddresses) throws ParseException { if (debug) dbg_enter("parseParameter"); try { NameValue nv = this.nameValue('='); //chargingFunctionAddresses.setParameter(nv); chargingFunctionAddresses.setMultiParameter(nv); } finally { if (debug) dbg_leave("parseParameter"); } } /** Test program */ public static void main(String args[]) throws ParseException { String r[] = { "P-Charging-Function-Addresses: ccf=\"test str\"; ecf=token\n", "P-Charging-Function-Addresses: ccf=192.1.1.1; ccf=192.1.1.2; ecf=192.1.1.3; ecf=192.1.1.4\n", "P-Charging-Function-Addresses: ccf=[5555::b99:c88:d77:e66]; ccf=[5555::a55:b44:c33:d22]; " + "ecf=[5555::1ff:2ee:3dd:4cc]; ecf=[5555::6aa:7bb:8cc:9dd]\n" }; for (int i = 0; i < r.length; i++ ) { PChargingFunctionAddressesParser parser = new PChargingFunctionAddressesParser(r[i]); System.out.println("original = " + r[i]); PChargingFunctionAddresses chargAddr= (PChargingFunctionAddresses) parser.parse(); System.out.println("encoded = " + chargAddr.encode()); } } } java/gov/nist/javax/sip/parser/ims/PChargingVectorParser.java0100644 0000000 0000000 00000006533 13513104763 023345 0ustar000000000 0000000 /* * 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 PT INOVACAO - EST DEPARTMENT * *******************************************/ package gov.nist.javax.sip.parser.ims; import gov.nist.core.NameValue; import gov.nist.javax.sip.header.SIPHeader; import gov.nist.javax.sip.header.ims.PChargingVector; import gov.nist.javax.sip.header.ims.ParameterNamesIms; import gov.nist.javax.sip.parser.Lexer; import gov.nist.javax.sip.parser.ParametersParser; import gov.nist.javax.sip.parser.TokenTypes; import java.text.ParseException; /** * P-Charging-Vector header parser. * * @author ALEXANDRE MIGUEL SILVA SANTOS */ public class PChargingVectorParser extends ParametersParser implements TokenTypes { public PChargingVectorParser(String chargingVector) { super(chargingVector); } protected PChargingVectorParser(Lexer lexer) { super(lexer); } public SIPHeader parse() throws ParseException { if (debug) dbg_enter("parse"); try { headerName(TokenTypes.P_VECTOR_CHARGING); PChargingVector chargingVector = new PChargingVector(); try { while (lexer.lookAhead(0) != '\n') { this.parseParameter(chargingVector); this.lexer.SPorHT(); char la = lexer.lookAhead(0); if (la == '\n' || la == '\0') break; this.lexer.match(';'); this.lexer.SPorHT(); } } catch (ParseException ex) { throw ex; } super.parse(chargingVector); if ( chargingVector.getParameter(ParameterNamesIms.ICID_VALUE) == null ) throw new ParseException("Missing a required Parameter : " + ParameterNamesIms.ICID_VALUE, 0); return chargingVector; } finally { if (debug) dbg_leave("parse"); } } protected void parseParameter(PChargingVector chargingVector) throws ParseException { if (debug) dbg_enter("parseParameter"); try { NameValue nv = this.nameValue('='); chargingVector.setParameter(nv); } finally { if (debug) dbg_leave("parseParameter"); } } } java/gov/nist/javax/sip/parser/ims/PMediaAuthorizationParser.java0100644 0000000 0000000 00000010247 13513104763 024235 0ustar000000000 0000000 /* * 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 PT INOVACAO - EST DEPARTMENT and Telecommunications Institute (Aveiro, Portugal) * ************************************************************************************************/ package gov.nist.javax.sip.parser.ims; import java.text.ParseException; import javax.sip.InvalidArgumentException; import gov.nist.javax.sip.header.ims.PMediaAuthorizationList; import gov.nist.javax.sip.header.ims.PMediaAuthorization; import gov.nist.javax.sip.header.ims.SIPHeaderNamesIms; import gov.nist.core.Token; import gov.nist.javax.sip.header.SIPHeader; import gov.nist.javax.sip.parser.HeaderParser; import gov.nist.javax.sip.parser.Lexer; import gov.nist.javax.sip.parser.TokenTypes; /** * P-Media-Authorization header parser. * * @author Miguel Freitas (IT) PT-Inovacao */ public class PMediaAuthorizationParser extends HeaderParser implements TokenTypes { public PMediaAuthorizationParser(String mediaAuthorization) { super(mediaAuthorization); } public PMediaAuthorizationParser(Lexer lexer) { super(lexer); } public SIPHeader parse() throws ParseException { PMediaAuthorizationList mediaAuthorizationList = new PMediaAuthorizationList(); if (debug) dbg_enter("MediaAuthorizationParser.parse"); try { headerName(TokenTypes.P_MEDIA_AUTHORIZATION); PMediaAuthorization mediaAuthorization = new PMediaAuthorization(); mediaAuthorization.setHeaderName(SIPHeaderNamesIms.P_MEDIA_AUTHORIZATION); while (lexer.lookAhead(0) != '\n') { this.lexer.match(TokenTypes.ID); Token token = lexer.getNextToken(); try { mediaAuthorization.setMediaAuthorizationToken(token.getTokenValue()); } catch (InvalidArgumentException e) { throw createParseException(e.getMessage()); } mediaAuthorizationList.add(mediaAuthorization); this.lexer.SPorHT(); if (lexer.lookAhead(0) == ',') { this.lexer.match(','); mediaAuthorization = new PMediaAuthorization(); } this.lexer.SPorHT(); } return mediaAuthorizationList; } finally { if (debug) dbg_leave("MediaAuthorizationParser.parse"); } } /* * test * public static void main(String args[]) throws ParseException { String pHeader[] = { "P-Media-Authorization: 0123456789 \n", "P-Media-Authorization: 0123456789, ABCDEF\n" }; for (int i = 0; i < pHeader.length; i++ ) { PMediaAuthorizationParser mParser = new PMediaAuthorizationParser(pHeader[i]); PMediaAuthorizationList mList= (PMediaAuthorizationList) mParser.parse(); System.out.println("encoded = " + mList.encode()); } } */ } java/gov/nist/javax/sip/parser/ims/PPreferredIdentityParser.java0100644 0000000 0000000 00000004670 13513104763 024070 0ustar000000000 0000000 /* * 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 PT INOVACAO - EST DEPARTMENT * *******************************************/ package gov.nist.javax.sip.parser.ims; import java.text.ParseException; import gov.nist.javax.sip.parser.Lexer; import gov.nist.javax.sip.parser.TokenTypes; import gov.nist.javax.sip.header.SIPHeader; import gov.nist.javax.sip.header.ims.PPreferredIdentity; import gov.nist.javax.sip.parser.AddressParametersParser; /** * P-Preferred-Identity header parser. * * @author ALEXANDRE MIGUEL SILVA SANTOS */ public class PPreferredIdentityParser //extends AddressHeaderParser extends AddressParametersParser implements TokenTypes { public PPreferredIdentityParser(String preferredIdentity) { super(preferredIdentity); } protected PPreferredIdentityParser(Lexer lexer) { super(lexer); } public SIPHeader parse() throws ParseException { if (debug) dbg_enter("PreferredIdentityParser.parse"); try { this.lexer.match(TokenTypes.P_PREFERRED_IDENTITY); this.lexer.SPorHT(); this.lexer.match(':'); this.lexer.SPorHT(); PPreferredIdentity p = new PPreferredIdentity(); super.parse( p ); return p; } finally { if (debug) dbg_leave("PreferredIdentityParser.parse"); } } } java/gov/nist/javax/sip/parser/ims/PPreferredServiceParser.java0100644 0000000 0000000 00000014226 13513104763 023675 0ustar000000000 0000000 package gov.nist.javax.sip.parser.ims; /* * 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 * * . * */ import java.text.ParseException; import javax.sip.InvalidArgumentException; import gov.nist.javax.sip.header.SIPHeader; import gov.nist.javax.sip.header.ims.PPreferredService; import gov.nist.javax.sip.header.ims.ParameterNamesIms; import gov.nist.javax.sip.parser.HeaderParser; import gov.nist.javax.sip.parser.Lexer; import gov.nist.javax.sip.parser.TokenTypes; /** * * @author aayush.bhatnagar * Rancore Technologies Pvt Ltd, Mumbai India. * * Parse this: * P-Preferred-Service: urn:urn-7:3gpp-service.exampletelephony.version1 * */ public class PPreferredServiceParser extends HeaderParser implements TokenTypes{ protected PPreferredServiceParser(Lexer lexer) { super(lexer); } public PPreferredServiceParser(String pps) { super(pps); } /** * "The URN consists of a hierarchical service identifier or application * identifier, with a sequence of labels separated by periods.The left-most label is * the most significant one and is called 'top-level service * identifier', while names to the right are called 'sub-services' or * 'sub-applications'. * * For any given service identifier, labels can be removed right-to-left and * the resulting URN is still valid, referring a more generic * service, with the exception of the top-level service identifier * and possibly the first sub-service or sub-application identifier. * * Labels cannot be removed beyond a defined basic service, for * example, the label w.x may define a service, but the label w may * only define an assignment authority for assigning subsequent * values and not define a service in its own right. In other words, * if a service identifier 'w.x.y.z' exists, the URNs 'w.x' and * 'w.x.y' are also valid service identifiers, but w may not be a * valid service identifier if it merely defines who is responsible" * * TODO: PLEASE VALIDATE MY UNDERSTANDING OF THE ABOVE TEXT :) * @ranga: Please validate my understanding of the above text in the draft :) * This last para is a little ambiguous.I will only check that atleast * 1 sub-service or 1 sub-application is present in the URN declaration. * If not, I throw an exception. I thought of not throwing an exception * and returning whatever was encoded..but the resultant encoding wont * make sense. It would be something like--> * urn:urn-7:3gpp-service OR urn:urn-7:3gpp-application alone with no sub-services * or sub-applications. This is bound to cause an error at the recepient later. * * Sub-service and Application identifiers are not maintained by IANA and * are organization/application dependent (Section 8.2). So we cannot gurantee what lies * beyond the first sub-service or sub-application identifier. It should be the responsibility * of the application to make sense of the entire URN holistically. We can only check for the * standardized part as per the ABNF. */ public SIPHeader parse() throws ParseException { if(debug) dbg_enter("PPreferredServiceParser.parse"); try { this.lexer.match(TokenTypes.P_PREFERRED_SERVICE); this.lexer.SPorHT(); this.lexer.match(':'); this.lexer.SPorHT(); PPreferredService pps = new PPreferredService(); String urn = this.lexer.getBuffer(); if(urn.contains(ParameterNamesIms.SERVICE_ID)){ if(urn.contains(ParameterNamesIms.SERVICE_ID_LABEL)) { String serviceID = urn.split(ParameterNamesIms.SERVICE_ID_LABEL+".")[1]; if(serviceID.trim().equals("")) try { throw new InvalidArgumentException("URN should atleast have one sub-service"); } catch (InvalidArgumentException e) { e.printStackTrace(); } else pps.setSubserviceIdentifiers(serviceID); } else if(urn.contains(ParameterNamesIms.APPLICATION_ID_LABEL)) { String appID = urn.split(ParameterNamesIms.APPLICATION_ID_LABEL)[1]; if(appID.trim().equals("")) try { throw new InvalidArgumentException("URN should atleast have one sub-application"); } catch (InvalidArgumentException e) { e.printStackTrace(); } else pps.setApplicationIdentifiers(appID); } else { try { throw new InvalidArgumentException("URN is not well formed"); } catch (InvalidArgumentException e) { e.printStackTrace(); } } } super.parse(); return pps; } finally{ if(debug) dbg_enter("PPreferredServiceParser.parse"); } } } java/gov/nist/javax/sip/parser/ims/PProfileKeyParser.java0100644 0000000 0000000 00000004242 13513104763 022504 0ustar000000000 0000000 package gov.nist.javax.sip.parser.ims; /* * 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 * * . * */ import java.text.ParseException; import gov.nist.javax.sip.header.SIPHeader; import gov.nist.javax.sip.header.ims.PProfileKey; import gov.nist.javax.sip.parser.AddressParametersParser; import gov.nist.javax.sip.parser.Lexer; import gov.nist.javax.sip.parser.TokenTypes; /** * * @author aayush.bhatnagar * Rancore Technologies Pvt Ltd, Mumbai India. * */ public class PProfileKeyParser extends AddressParametersParser implements TokenTypes{ protected PProfileKeyParser(Lexer lexer) { super(lexer); } public PProfileKeyParser(String profilekey){ super(profilekey); } public SIPHeader parse() throws ParseException { if (debug) dbg_enter("PProfileKey.parse"); try { this.lexer.match(TokenTypes.P_PROFILE_KEY); this.lexer.SPorHT(); this.lexer.match(':'); this.lexer.SPorHT(); PProfileKey p = new PProfileKey(); super.parse(p); return p; } finally { if (debug) dbg_leave("PProfileKey.parse"); } } } java/gov/nist/javax/sip/parser/ims/PServedUserParser.java0100644 0000000 0000000 00000004601 13513104763 022521 0ustar000000000 0000000 package gov.nist.javax.sip.parser.ims; /* * 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 * * . * */ import java.text.ParseException; import gov.nist.javax.sip.address.AddressFactoryImpl; import gov.nist.javax.sip.header.SIPHeader; import gov.nist.javax.sip.header.ims.PServedUser; import gov.nist.javax.sip.parser.Lexer; import gov.nist.javax.sip.parser.ParametersParser; import gov.nist.javax.sip.parser.TokenTypes; /** * * @author aayush.bhatnagar * */ public class PServedUserParser extends ParametersParser implements TokenTypes{ protected PServedUserParser(Lexer lexer) { super(lexer); } public PServedUserParser(String servedUser){ super(servedUser); } public SIPHeader parse() throws ParseException { if (debug) dbg_enter("PServedUser.parse"); try{ this.lexer.match(TokenTypes.P_SERVED_USER); this.lexer.SPorHT(); this.lexer.match(':'); this.lexer.SPorHT(); PServedUser servedUser = new PServedUser(); this.lexer.SPorHT(); String servedUsername = lexer.byteStringNoSemicolon(); servedUser.setAddress(new AddressFactoryImpl().createAddress(servedUsername)); super.parse(servedUser); return servedUser; } finally { if (debug) dbg_leave("PServedUser.parse"); } } } java/gov/nist/javax/sip/parser/ims/PUserDatabaseParser.java0100644 0000000 0000000 00000006155 13513104763 023003 0ustar000000000 0000000 package gov.nist.javax.sip.parser.ims; /* * 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 * * . * */ import java.text.ParseException; import gov.nist.javax.sip.header.SIPHeader; import gov.nist.javax.sip.header.ims.PUserDatabase; import gov.nist.javax.sip.parser.Lexer; import gov.nist.javax.sip.parser.ParametersParser; import gov.nist.javax.sip.parser.TokenTypes; /** * * @author aayush.bhatnagar * Rancore Technologies Pvt Ltd, Mumbai India. * * This is the parser for the P-user-database header. * The syntax for the P-user-database header as per * RFC 4457 is given below: * * P-User-Database = "P-User-Database" HCOLON database * *( SEMI generic-param ) * database = LAQUOT DiameterURI RAQUOT * * Eg: P-User-Database: * */ public class PUserDatabaseParser extends ParametersParser implements TokenTypes{ /** * * @param databaseName */ public PUserDatabaseParser(String databaseName) { super(databaseName); } /** * * @param lexer */ public PUserDatabaseParser(Lexer lexer) { super(lexer); } public SIPHeader parse() throws ParseException { if (debug) dbg_enter("PUserDatabase.parse"); try{ this.lexer.match(TokenTypes.P_USER_DATABASE); this.lexer.SPorHT(); this.lexer.match(':'); this.lexer.SPorHT(); PUserDatabase userDatabase = new PUserDatabase(); this.parseheader(userDatabase); return userDatabase; } finally{ if(debug) dbg_leave("PUserDatabase.parse"); } } private void parseheader(PUserDatabase userDatabase) throws ParseException { StringBuffer dbname = new StringBuffer(); this.lexer.match(LESS_THAN); while(this.lexer.hasMoreChars()) { char next = this.lexer.getNextChar(); if (next!='>'&&next!='\n') { dbname.append(next); } } userDatabase.setDatabaseName(dbname.toString()); super.parse(userDatabase); } } java/gov/nist/javax/sip/parser/ims/PVisitedNetworkIDParser.java0100644 0000000 0000000 00000012032 13513104763 023625 0ustar000000000 0000000 /* * 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 PT INOVACAO - EST DEPARTMENT * *******************************************/ package gov.nist.javax.sip.parser.ims; import gov.nist.core.Token; import gov.nist.javax.sip.header.SIPHeader; import gov.nist.javax.sip.header.ims.PVisitedNetworkID; import gov.nist.javax.sip.header.ims.PVisitedNetworkIDList; import gov.nist.javax.sip.parser.Lexer; import gov.nist.javax.sip.parser.ParametersParser; import gov.nist.javax.sip.parser.TokenTypes; import java.text.ParseException; /** * P-Visited-Network-ID header parser. * *
     * P-Visited-Network-ID   = "P-Visited-Network-ID" HCOLON
     *                          vnetwork-spec
     *                          *(COMMA vnetwork-spec)
     * vnetwork-spec          = (token / quoted-string)
     *                          *(SEMI vnetwork-param)
     * vnetwork-param         = generic-param
     * 
    * * @author ALEXANDRE MIGUEL SILVA SANTOS */ /* */ public class PVisitedNetworkIDParser extends ParametersParser implements TokenTypes { /** * Constructor */ public PVisitedNetworkIDParser(String networkID) { super(networkID); } protected PVisitedNetworkIDParser(Lexer lexer) { super(lexer); } public SIPHeader parse() throws ParseException { PVisitedNetworkIDList visitedNetworkIDList = new PVisitedNetworkIDList(); if (debug) dbg_enter("VisitedNetworkIDParser.parse"); try { this.lexer.match(TokenTypes.P_VISITED_NETWORK_ID); this.lexer.SPorHT(); this.lexer.match(':'); this.lexer.SPorHT(); while (true) { PVisitedNetworkID visitedNetworkID = new PVisitedNetworkID(); if (this.lexer.lookAhead(0) == '\"') parseQuotedString(visitedNetworkID); else parseToken(visitedNetworkID); visitedNetworkIDList.add(visitedNetworkID); this.lexer.SPorHT(); char la = lexer.lookAhead(0); if (la == ',') { this.lexer.match(','); this.lexer.SPorHT(); } else if (la == '\n') break; else throw createParseException("unexpected char = " + la); } return visitedNetworkIDList; } finally { if (debug) dbg_leave("VisitedNetworkIDParser.parse"); } } protected void parseQuotedString(PVisitedNetworkID visitedNetworkID) throws ParseException { if (debug) dbg_enter("parseQuotedString"); try { StringBuffer retval = new StringBuffer(); if (this.lexer.lookAhead(0) != '\"') throw createParseException("unexpected char"); this.lexer.consume(1); while (true) { char next = this.lexer.getNextChar(); if (next == '\"') { // Got to the terminating quote. break; } else if (next == '\0') { throw new ParseException("unexpected EOL", 1); } else if (next == '\\') { retval.append(next); next = this.lexer.getNextChar(); retval.append(next); } else { retval.append(next); } } visitedNetworkID.setVisitedNetworkID(retval.toString()); super.parse(visitedNetworkID); }finally { if (debug) dbg_leave("parseQuotedString.parse"); } } protected void parseToken(PVisitedNetworkID visitedNetworkID) throws ParseException { // issued by Miguel Freitas lexer.match(TokenTypes.ID); Token token = lexer.getNextToken(); //String value = token.getTokenValue(); visitedNetworkID.setVisitedNetworkID(token); super.parse(visitedNetworkID); } } java/gov/nist/javax/sip/parser/ims/PathParser.java0100644 0000000 0000000 00000005733 13513104763 021215 0ustar000000000 0000000 /* * 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 PT INOVACAO - EST DEPARTMENT * *******************************************/ package gov.nist.javax.sip.parser.ims; import gov.nist.javax.sip.header.SIPHeader; import gov.nist.javax.sip.header.ims.Path; import gov.nist.javax.sip.header.ims.PathList; import gov.nist.javax.sip.parser.AddressParametersParser; import gov.nist.javax.sip.parser.Lexer; import gov.nist.javax.sip.parser.TokenTypes; import java.text.ParseException; /** * @author ALEXANDRE MIGUEL SILVA SANTOS */ public class PathParser extends AddressParametersParser implements TokenTypes { /** * Constructor */ public PathParser(String path) { super(path); } protected PathParser(Lexer lexer) { super(lexer); } /** * parse the String message and generate the RecordRoute List Object * @return SIPHeader the RecordRoute List object * @throws ParseException if errors occur during the parsing */ public SIPHeader parse() throws ParseException { PathList pathList = new PathList(); if (debug) dbg_enter("PathParser.parse"); try { this.lexer.match(TokenTypes.PATH); this.lexer.SPorHT(); this.lexer.match(':'); this.lexer.SPorHT(); while (true) { Path path = new Path(); super.parse(path); pathList.add(path); this.lexer.SPorHT(); char la = lexer.lookAhead(0); if (la == ',') { this.lexer.match(','); this.lexer.SPorHT(); } else if (la == '\n') break; else throw createParseException("unexpected char"); } return pathList; } finally { if (debug) dbg_leave("PathParser.parse"); } } } java/gov/nist/javax/sip/parser/ims/PrivacyParser.java0100644 0000000 0000000 00000010016 13513104763 021724 0ustar000000000 0000000 /* * 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 PT INOVACAO - EST DEPARTMENT and Telecommunications Institute (Aveiro, Portugal) * ************************************************************************************************/ package gov.nist.javax.sip.parser.ims; /** * Privacy header parser. * * @author Miguel Freitas (IT) PT-Inovacao */ /* * Privacy-hdr = "Privacy" HCOLON priv-value *(";" priv-value) * priv-value = "header" / "session" / "user" / "none" / "critical" / token */ import gov.nist.core.*; import gov.nist.javax.sip.header.SIPHeader; import gov.nist.javax.sip.parser.Lexer; import gov.nist.javax.sip.parser.TokenTypes; import gov.nist.javax.sip.parser.HeaderParser; import java.text.ParseException; import gov.nist.javax.sip.header.ims.Privacy; import gov.nist.javax.sip.header.ims.PrivacyList; import gov.nist.javax.sip.header.ims.SIPHeaderNamesIms; public class PrivacyParser extends HeaderParser implements TokenTypes { public PrivacyParser(String privacyType) { super(privacyType); } protected PrivacyParser(Lexer lexer) { super(lexer); } public SIPHeader parse() throws ParseException { if (debug) dbg_enter("PrivacyParser.parse"); PrivacyList privacyList = new PrivacyList(); try { this.headerName(TokenTypes.PRIVACY); while (lexer.lookAhead(0) != '\n') { this.lexer.SPorHT(); Privacy privacy = new Privacy(); privacy.setHeaderName(SIPHeaderNamesIms.PRIVACY); this.lexer.match(TokenTypes.ID); Token token = lexer.getNextToken(); privacy.setPrivacy(token.getTokenValue()); this.lexer.SPorHT(); privacyList.add(privacy); // Parsing others option-tags while (lexer.lookAhead(0) == ';') { this.lexer.match(';'); this.lexer.SPorHT(); privacy = new Privacy(); this.lexer.match(TokenTypes.ID); token = lexer.getNextToken(); privacy.setPrivacy(token.getTokenValue()); this.lexer.SPorHT(); privacyList.add(privacy); } } return privacyList; } finally { if (debug) dbg_leave("PrivacyParser.parse"); } } /** Test program */ public static void main(String args[]) throws ParseException { String rou[] = { "Privacy: none\n", "Privacy: none;id;user\n" }; for (int i = 0; i < rou.length; i++ ) { PrivacyParser rp = new PrivacyParser(rou[i]); PrivacyList list = (PrivacyList) rp.parse(); System.out.println("encoded = " +list.encode()); } } } java/gov/nist/javax/sip/parser/ims/SecurityAgreeParser.java0100644 0000000 0000000 00000011453 13513104763 023070 0ustar000000000 0000000 /* * 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 PT INOVACAO - EST DEPARTMENT and Telecommunications Institute (Aveiro, Portugal) * ************************************************************************************************/ package gov.nist.javax.sip.parser.ims; /** * Security Agreement for SIP. *

    headers: Security-Client, Security-Server and Security-Verify

    * * @author Miguel Freitas (IT) PT-Inovacao */ import gov.nist.core.NameValue; import gov.nist.core.Token; import gov.nist.javax.sip.header.SIPHeaderList; import gov.nist.javax.sip.header.ims.*; import gov.nist.javax.sip.parser.HeaderParser; import gov.nist.javax.sip.parser.Lexer; import gov.nist.javax.sip.parser.TokenTypes; import java.text.ParseException; public class SecurityAgreeParser extends HeaderParser { public SecurityAgreeParser(String security) { super(security); } protected SecurityAgreeParser(Lexer lexer) { super(lexer); } protected void parseParameter(SecurityAgree header) throws ParseException { if (debug) dbg_enter("parseParameter"); try { NameValue nv = this.nameValue('='); header.setParameter(nv); } finally { if (debug) dbg_leave("parseParameter"); } } public SIPHeaderList parse(SecurityAgree header) throws ParseException { SIPHeaderList list; if (header.getClass().isInstance(new SecurityClient())) { list = new SecurityClientList(); } else if (header.getClass().isInstance(new SecurityServer())) { list = new SecurityServerList(); } else if (header.getClass().isInstance(new SecurityVerify())) { list = new SecurityVerifyList(); } else return null; // the security-mechanism: this.lexer.SPorHT(); lexer.match(TokenTypes.ID); Token type = lexer.getNextToken(); header.setSecurityMechanism(type.getTokenValue()); this.lexer.SPorHT(); char la = lexer.lookAhead(0); if (la == '\n') { list.add(header); return list; } else if (la == ';') this.lexer.match(';'); this.lexer.SPorHT(); // The parameters: try { while (lexer.lookAhead(0) != '\n') { this.parseParameter(header); this.lexer.SPorHT(); char laInLoop = lexer.lookAhead(0); if (laInLoop == '\n' || laInLoop == '\0') break; else if (laInLoop == ',') { list.add(header); if (header.getClass().isInstance(new SecurityClient())) { header = new SecurityClient(); } else if (header.getClass().isInstance(new SecurityServer())) { header = new SecurityServer(); } else if (header.getClass().isInstance(new SecurityVerify())) { header = new SecurityVerify(); } this.lexer.match(','); // the security-mechanism: this.lexer.SPorHT(); lexer.match(TokenTypes.ID); type = lexer.getNextToken(); header.setSecurityMechanism(type.getTokenValue()); } this.lexer.SPorHT(); if (lexer.lookAhead(0) == ';') this.lexer.match(';'); this.lexer.SPorHT(); } list.add(header); return list; } catch (ParseException ex) { throw ex; } } } java/gov/nist/javax/sip/parser/ims/SecurityClientParser.java0100644 0000000 0000000 00000004672 13513104763 023270 0ustar000000000 0000000 /* * 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 PT INOVACAO - EST DEPARTMENT and Telecommunications Institute (Aveiro, Portugal) * ************************************************************************************************/ package gov.nist.javax.sip.parser.ims; /** * Security-Client header parser. * * @author Miguel Freitas (IT) PT-Inovacao */ import gov.nist.core.Token; import gov.nist.javax.sip.header.SIPHeader; import gov.nist.javax.sip.parser.Lexer; import gov.nist.javax.sip.parser.TokenTypes; import java.text.ParseException; import gov.nist.javax.sip.header.ims.SecurityClient; import gov.nist.javax.sip.header.ims.SecurityClientList; public class SecurityClientParser extends SecurityAgreeParser { public SecurityClientParser(String security) { super(security); } protected SecurityClientParser(Lexer lexer) { super(lexer); } public SIPHeader parse() throws ParseException { dbg_enter("SecuriryClient parse"); try { headerName(TokenTypes.SECURITY_CLIENT); SecurityClient secClient = new SecurityClient(); SecurityClientList secClientList = (SecurityClientList) super.parse(secClient); return secClientList; } finally { dbg_leave("SecuriryClient parse"); } } } java/gov/nist/javax/sip/parser/ims/SecurityServerParser.java0100644 0000000 0000000 00000007356 13513104763 023322 0ustar000000000 0000000 /* * 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 PT INOVACAO - EST DEPARTMENT and Telecommunications Institute (Aveiro, Portugal) * ************************************************************************************************/ package gov.nist.javax.sip.parser.ims; /** * Security-Server header parser. * * @author Miguel Freitas (IT) PT-Inovacao */ import gov.nist.javax.sip.header.SIPHeader; import gov.nist.javax.sip.parser.Lexer; import gov.nist.javax.sip.parser.TokenTypes; import java.text.ParseException; import gov.nist.javax.sip.header.ims.SecurityServerList; import gov.nist.javax.sip.header.ims.SecurityServer; public class SecurityServerParser extends SecurityAgreeParser { public SecurityServerParser(String security) { super(security); } protected SecurityServerParser(Lexer lexer) { super(lexer); } public SIPHeader parse() throws ParseException { dbg_enter("SecuriryServer parse"); try { headerName(TokenTypes.SECURITY_SERVER); SecurityServer secServer = new SecurityServer(); SecurityServerList secServerList = (SecurityServerList) super.parse(secServer); return secServerList; } finally { dbg_leave("SecuriryServer parse"); } } /** Test program public static void main(String args[]) throws ParseException { String r[] = { "Security-Server: ipsec-3gpp; ealg=aes-cbc; " + "alg=hmac-md5-96; port-c=5062; port-s=5063; " + "q=0.1\n" }; String r2[] = { "Security-Server: ipsec-3gpp; ealg=aes-cbc; " + "alg=hmac-md5-96; port-c=5062; port-s=5063; " + "q=0.1, " + "digest; d-alg=md5; " + "d-qop=auth-int; d-ver=AEF1D222; " + "q=0.01\n" }; for (int i = 0; i < r.length; i++ ) { SecurityServerParser parser = new SecurityServerParser(r[i]); SecurityServer secServer= (SecurityServer) parser.parse(); System.out.println("encoded = " + secServer.encode()); } for (int i = 0; i < r2.length; i++ ) { SecurityServerParser parser = new SecurityServerParser(r2[i]); java.util.ListIterator list; SecurityServerList secList = (SecurityServerList) parser.parse(); System.out.println("encoded = " + secList.encode()); } } */ } java/gov/nist/javax/sip/parser/ims/SecurityVerifyParser.java0100644 0000000 0000000 00000004635 13513104763 023315 0ustar000000000 0000000 /* * 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 PT INOVACAO - EST DEPARTMENT and Telecommunications Institute (Aveiro, Portugal) * ************************************************************************************************/ package gov.nist.javax.sip.parser.ims; /** * Security-Verify header parser. * * @author Miguel Freitas (IT) PT-Inovacao */ import gov.nist.javax.sip.header.SIPHeader; import gov.nist.javax.sip.parser.Lexer; import gov.nist.javax.sip.parser.TokenTypes; import java.text.ParseException; import gov.nist.javax.sip.header.ims.SecurityVerify; import gov.nist.javax.sip.header.ims.SecurityVerifyList; public class SecurityVerifyParser extends SecurityAgreeParser { public SecurityVerifyParser(String security) { super(security); } protected SecurityVerifyParser(Lexer lexer) { super(lexer); } public SIPHeader parse() throws ParseException { dbg_enter("SecuriryVerify parse"); try { headerName(TokenTypes.SECURITY_VERIFY); SecurityVerify secVerify = new SecurityVerify(); SecurityVerifyList secVerifyList = (SecurityVerifyList) super.parse(secVerify); return secVerifyList; } finally { dbg_leave("SecuriryVerify parse"); } } } java/gov/nist/javax/sip/parser/ims/ServiceRouteParser.java0100644 0000000 0000000 00000006165 13513104763 022740 0ustar000000000 0000000 /* * 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 PT INOVAO - EST DEPARTMENT * *******************************************/ package gov.nist.javax.sip.parser.ims; import java.text.ParseException; import gov.nist.javax.sip.header.ims.ServiceRoute; import gov.nist.javax.sip.header.ims.ServiceRouteList; import gov.nist.javax.sip.header.SIPHeader; import gov.nist.javax.sip.parser.AddressParametersParser; import gov.nist.javax.sip.parser.Lexer; import gov.nist.javax.sip.parser.TokenTypes; /** * Service-Route header parser. * * @author ALEXANDRE MIGUEL SILVA SANTOS */ public class ServiceRouteParser extends AddressParametersParser { /** * Constructor */ public ServiceRouteParser(String serviceRoute) { super(serviceRoute); } protected ServiceRouteParser(Lexer lexer) { super(lexer); } /** * parse the String message and generate the RecordRoute List Object * @return SIPHeader the RecordRoute List object * @throws ParseException if errors occur during the parsing */ public SIPHeader parse() throws ParseException { ServiceRouteList serviceRouteList = new ServiceRouteList(); if (debug) dbg_enter("ServiceRouteParser.parse"); try { this.lexer.match(TokenTypes.SERVICE_ROUTE); this.lexer.SPorHT(); this.lexer.match(':'); this.lexer.SPorHT(); while (true) { ServiceRoute serviceRoute = new ServiceRoute(); super.parse(serviceRoute); serviceRouteList.add(serviceRoute); this.lexer.SPorHT(); if (lexer.lookAhead(0) == ',') { this.lexer.match(','); this.lexer.SPorHT(); } else if (lexer.lookAhead(0) == '\n') break; else throw createParseException("unexpected char"); } return serviceRouteList; } finally { if (debug) dbg_leave("ServiceRouteParser.parse"); } } } java/gov/nist/javax/sip/parser/ims/TokenNamesIms.java0100644 0000000 0000000 00000003604 13513104763 021654 0ustar000000000 0000000 /* * 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 PT INOVACAO - EST DEPARTMENT and Telecommunications Institute (Aveiro, Portugal) * ************************************************************************************************/ package gov.nist.javax.sip.parser.ims; /** * * @author Miguel Freitas (IT) PT-Inovacao */ public interface TokenNamesIms extends gov.nist.javax.sip.parser.TokenNames { public static final String IEEE_802_11A = "IEEE-802.11a"; public static final String IEEE_802_11B = "IEEE-802.11b"; public static final String GGGPP_GERAN = "3GPP-GERAN"; public static final String GGGPP_UTRAN_FDD = "3GPP-UTRAN-FDD"; public static final String GGGPP_UTRAN_TDD = "3GPP-UTRAN-TDD"; public static final String GGGPP_CDMA2000 = "3GPP-CDMA2000"; } java/gov/nist/javax/sip/parser/ims/package.html0100644 0000000 0000000 00000000327 13513104763 020554 0ustar000000000 0000000 Parser for IMS headers. This code was contributed by Jose Miguel Freitas (PT Innovacau) and ALEXANDRE MIGUEL SILVA SANTOS to this project. This package has been contributed to the public domain. java/gov/nist/javax/sip/parser/package.html0100644 0000000 0000000 00000000077 13513104763 017766 0ustar000000000 0000000 Parsers for SIP Headers, URL's and addresses. java/gov/nist/javax/sip/stack/0040755 0000000 0000000 00000000000 13513104763 015315 5ustar000000000 0000000 java/gov/nist/javax/sip/stack/DefaultMessageLogFactory.java0100644 0000000 0000000 00000002016 13513104763 023037 0ustar000000000 0000000 package gov.nist.javax.sip.stack; import gov.nist.javax.sip.LogRecord; import gov.nist.javax.sip.LogRecordFactory; /** * The Default Message log factory. This can be replaced as a stack * configuration parameter. * * @author M. Ranganathan * */ public class DefaultMessageLogFactory implements LogRecordFactory { public LogRecord createLogRecord(String message, String source, String destination, String timeStamp, boolean isSender, String firstLine, String tid, String callId, long tsHeaderValue) { return new MessageLog(message, source, destination, timeStamp, isSender, firstLine, tid, callId, tsHeaderValue); } public LogRecord createLogRecord(String message, String source, String destination, long timeStamp, boolean isSender, String firstLine, String tid, String callId, long timestampVal) { return new MessageLog(message, source, destination, timeStamp, isSender, firstLine, tid, callId, timestampVal); } } java/gov/nist/javax/sip/stack/DefaultRouter.java0100644 0000000 0000000 00000031230 13513104763 020741 0ustar000000000 0000000 /* * 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.javax.sip.stack; import gov.nist.javax.sip.message.*; import gov.nist.javax.sip.address.*; import gov.nist.javax.sip.header.*; import gov.nist.javax.sip.*; import gov.nist.core.*; import gov.nist.core.net.AddressResolver; import javax.sip.*; import java.util.Iterator; import java.util.LinkedList; import java.util.ListIterator; import javax.sip.header.RouteHeader; import javax.sip.header.ViaHeader; import javax.sip.message.*; import javax.sip.address.*; /* * Bug reported by Will Scullin -- maddr was being ignored when routing * requests. Bug reported by Antonis Karydas - the RequestURI can be a non-sip * URI Jiang He - use address in route header. Significant changes to conform to * RFC 3261 made by Jeroen van Bemmel. Hagai Sela contributed a bug fix to the * strict route post processing code. * */ /** * This is the default router. When the implementation wants to forward a * request and had run out of othe options, then it calls this method to figure * out where to send the request. The default router implements a simple * "default routing algorithm" which just forwards to the configured proxy * address. * *

    * When javax.sip.USE_ROUTER_FOR_ALL_URIS is set to * false, the next hop is determined according to the following * algorithm: *

      *
    • If the request contains one or more Route headers, use the URI of the * topmost Route header as next hop, possibly modifying the request in the * process if the topmost Route header contains no lr parameter(*) *
    • Else, if the property javax.sip.OUTBOUND_PROXY is set, * use its value as the next hop *
    • Otherwise, use the request URI as next hop. If the request URI is not a * SIP URI, call {@link javax.sip.address.Router#getNextHop(Request)} provided * by the application. *
    * *

    * (*)Note that in case the topmost Route header contains no 'lr' parameter * (which means the next hop is a strict router), the implementation will * perform 'Route Information Postprocessing' as described in RFC3261 section * 16.6 step 6 (also known as "Route header popping"). That is, the following * modifications will be made to the request: *

      *
    1. The implementation places the Request-URI into the Route header field as * the last value. *
    2. The implementation then places the first Route header field value into * the Request-URI and removes that value from the Route header field. *
    * Subsequently, the request URI will be used as next hop target * * * @version 1.2 $Revision: 1.17 $ $Date: 2009/11/14 20:06:17 $ * * @author M. Ranganathan
    * */ public class DefaultRouter implements Router { private SipStackImpl sipStack; private Hop defaultRoute; private DefaultRouter() { } /** * Constructor. */ public DefaultRouter(SipStack sipStack, String defaultRoute) { this.sipStack = (SipStackImpl) sipStack; if (defaultRoute != null) { try { this.defaultRoute = (Hop) this.sipStack.getAddressResolver() .resolveAddress((Hop) (new HopImpl(defaultRoute))); } catch (IllegalArgumentException ex) { // The outbound proxy is optional. If specified it should be host:port/transport. ((SIPTransactionStack) sipStack) .getStackLogger() .logError( "Invalid default route specification - need host:port/transport"); throw ex; } } } /** * Return addresses for default proxy to forward the request to. The list is * organized in the following priority. If the requestURI refers directly to * a host, the host and port information are extracted from it and made the * next hop on the list. If the default route has been specified, then it is * used to construct the next element of the list. * RouteHeader firstRoute = (RouteHeader) req.getHeader( RouteHeader.NAME ); * if (firstRoute!=null) { * URI uri = firstRoute.getAddress().getURI(); * if (uri.isSIPUri()) { * SipURI nextHop = (SipURI) uri; * if ( nextHop.hasLrParam() ) { * // OK, use it * } else { * nextHop = fixStrictRouting( req ); <--- Here, make the modifications as per RFC3261 * } * } else { * // error: non-SIP URI not allowed in Route headers * throw new SipException( "Request has Route header with non-SIP URI" ); * } * } else if (outboundProxy!=null) { * // use outbound proxy for nextHop * } else if ( req.getRequestURI().isSipURI() ) { * // use request URI for nextHop * } * * * * @param request * is the sip request to route. * */ public Hop getNextHop(Request request) throws SipException { SIPRequest sipRequest = (SIPRequest) request; RequestLine requestLine = sipRequest.getRequestLine(); if (requestLine == null) { return defaultRoute; } javax.sip.address.URI requestURI = requestLine.getUri(); if (requestURI == null) throw new IllegalArgumentException("Bad message: Null requestURI"); RouteList routes = sipRequest.getRouteHeaders(); /* * In case the topmost Route header contains no 'lr' parameter (which * means the next hop is a strict router), the implementation will * perform 'Route Information Postprocessing' as described in RFC3261 * section 16.6 step 6 (also known as "Route header popping"). That is, * the following modifications will be made to the request: * * The implementation places the Request-URI into the Route header field * as the last value. * * The implementation then places the first Route header field value * into the Request-URI and removes that value from the Route header * field. * * Subsequently, the request URI will be used as next hop target */ if (routes != null) { // to send the request through a specified hop the application is // supposed to prepend the appropriate Route header which. Route route = (Route) routes.getFirst(); URI uri = route.getAddress().getURI(); if (uri.isSipURI()) { SipURI sipUri = (SipURI) uri; if (!sipUri.hasLrParam()) { fixStrictRouting(sipRequest); if (sipStack.isLoggingEnabled()) sipStack.getStackLogger() .logDebug("Route post processing fixed strict routing"); } Hop hop = createHop(sipUri,request); if (sipStack.isLoggingEnabled()) sipStack.getStackLogger() .logDebug("NextHop based on Route:" + hop); return hop; } else { throw new SipException("First Route not a SIP URI"); } } else if (requestURI.isSipURI() && ((SipURI) requestURI).getMAddrParam() != null) { Hop hop = createHop((SipURI) requestURI,request); if (sipStack.isLoggingEnabled()) sipStack.getStackLogger() .logDebug("Using request URI maddr to route the request = " + hop.toString()); // JvB: don't remove it! // ((SipURI) requestURI).removeParameter("maddr"); return hop; } else if (defaultRoute != null) { if (sipStack.isLoggingEnabled()) 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 && sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("Used request-URI for nextHop = " + hop.toString()); else if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger() .logDebug("returning null hop -- loop detected"); } return hop; } else { // The internal router should never be consulted for non-sip URIs. InternalErrorHandler.handleException("Unexpected non-sip URI", this.sipStack.getStackLogger()); return null; } } /** * Performs strict router fix according to RFC3261 section 16.6 step 6 * * pre: top route header in request has no 'lr' parameter in URI post: * request-URI added as last route header, new req-URI = top-route-URI */ public void fixStrictRouting(SIPRequest req) { RouteList routes = req.getRouteHeaders(); Route first = (Route) routes.getFirst(); SipUri firstUri = (SipUri) first.getAddress().getURI(); routes.removeFirst(); // Add request-URI as last Route entry AddressImpl addr = new AddressImpl(); addr.setAddess(req.getRequestURI()); // don't clone it Route route = new Route(addr); routes.add(route); // as last one req.setRequestURI(firstUri); if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug("post: fixStrictRouting" + req); } } /** * Utility method to create a hop from a SIP URI * * @param sipUri * @return */ private final Hop createHop(SipURI sipUri, Request request) { // always use TLS when secure String transport = sipUri.isSecure() ? SIPConstants.TLS : sipUri .getTransportParam(); if (transport == null) { //@see issue 131 ViaHeader via = (ViaHeader) request.getHeader(ViaHeader.NAME); transport = via.getTransport(); } // sipUri.removeParameter("transport"); int port; if (sipUri.getPort() != -1) { port = sipUri.getPort(); } else { if (transport.equalsIgnoreCase(SIPConstants.TLS)) port = 5061; else port = 5060; // TCP or UDP } String host = sipUri.getMAddrParam() != null ? sipUri.getMAddrParam() : sipUri.getHost(); AddressResolver addressResolver = this.sipStack.getAddressResolver(); return addressResolver .resolveAddress(new HopImpl(host, port, transport)); } /** * Get the default hop. * * @return defaultRoute is the default route. public java.util.Iterator * getDefaultRoute(Request request) { return * this.getNextHops((SIPRequest)request); } */ public javax.sip.address.Hop getOutboundProxy() { return this.defaultRoute; } /* * (non-Javadoc) * * @see javax.sip.address.Router#getNextHop(javax.sip.message.Request) */ public ListIterator getNextHops(Request request) { try { LinkedList llist = new LinkedList(); llist.add(this.getNextHop(request)); return llist.listIterator(); } catch (SipException ex) { return null; } } } java/gov/nist/javax/sip/stack/HandshakeCompletedListenerImpl.java0100644 0000000 0000000 00000003274 13513104763 024236 0ustar000000000 0000000 /* * This software has been contributed by the author to the public domain. * * 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; import javax.net.ssl.HandshakeCompletedEvent; import javax.net.ssl.HandshakeCompletedListener; public class HandshakeCompletedListenerImpl implements HandshakeCompletedListener { private HandshakeCompletedEvent handshakeCompletedEvent; private TLSMessageChannel tlsMessageChannel; public HandshakeCompletedListenerImpl(TLSMessageChannel tlsMessageChannel) { this.tlsMessageChannel = tlsMessageChannel; tlsMessageChannel.setHandshakeCompletedListener(this); } public void handshakeCompleted(HandshakeCompletedEvent handshakeCompletedEvent) { this.handshakeCompletedEvent = handshakeCompletedEvent; /* try { Thread.sleep(10); } catch (InterruptedException ex) { }*/ } /** * @return the handshakeCompletedEvent */ public HandshakeCompletedEvent getHandshakeCompletedEvent() { return handshakeCompletedEvent; } } java/gov/nist/javax/sip/stack/HopImpl.java0100644 0000000 0000000 00000013020 13513104763 017521 0ustar000000000 0000000 /* * 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.javax.sip.stack; import java.io.Serializable; import java.util.StringTokenizer; /* * IPv6 Support added by Emil Ivov (emil_ivov@yahoo.com)
    * Network Research Team (http://www-r2.u-strasbg.fr))
    * Louis Pasteur University - Strasbourg - France
    * Bug fix for correct handling of IPV6 Address added by * Daniel J. Martinez Manzano */ /** * Routing algorithms return a list of hops to which the request is * routed. * * @version 1.2 $Revision: 1.11 $ $Date: 2009/07/17 18:58:13 $ * * @author M. Ranganathan
    * * * * */ public final class HopImpl extends Object implements javax.sip.address.Hop, Serializable { protected String host; protected int port; protected String transport; protected boolean defaultRoute; // This is generated from the proxy addr protected boolean uriRoute; // This is extracted from the requestURI. /** * Debugging println. */ public String toString() { return host + ":" + port + "/" + transport; } /** * Create new hop given host, port and transport. * @param hostName hostname * @param portNumber port * @param trans transport */ public HopImpl(String hostName, int portNumber, String trans) { host = hostName; // Added by Daniel J. Martinez Manzano // for correct management of IPv6 addresses. if(host.indexOf(":") >= 0) if(host.indexOf("[") < 0) host = "[" + host + "]"; port = portNumber; transport = trans; } /** * Creates new Hop * @param hop is a hop string in the form of host:port/Transport * @throws IllegalArgument exception if string is not properly formatted or null. */ HopImpl(String hop) throws IllegalArgumentException { if (hop == null) throw new IllegalArgumentException("Null arg!"); // System.out.println("hop = " + hop); int brack = hop.indexOf(']'); int colon = hop.indexOf(':',brack); int slash = hop.indexOf('/',colon); if (colon>0) { this.host = hop.substring(0,colon); String portstr; if (slash>0) { portstr = hop.substring(colon+1,slash); this.transport = hop.substring(slash+1); } else { portstr = hop.substring(colon+1); this.transport = "UDP"; } try { port = Integer.parseInt(portstr); } catch (NumberFormatException ex) { throw new IllegalArgumentException("Bad port spec"); } } else { if (slash>0) { this.host = hop.substring(0,slash); this.transport = hop.substring(slash+1); this.port = transport.equalsIgnoreCase("TLS") ? 5061 : 5060; } else { this.host = hop; this.transport = "UDP"; this.port = 5060; } } // Validate it if (host == null || host.length() == 0) throw new IllegalArgumentException("no host!"); // normalize this.host = this.host.trim(); this.transport = this.transport.trim(); if ((brack>0) && host.charAt(0)!='[') { throw new IllegalArgumentException("Bad IPv6 reference spec"); } if (transport.compareToIgnoreCase("UDP") != 0 && transport.compareToIgnoreCase("TLS") != 0 && transport.compareToIgnoreCase("TCP") != 0) { System.err.println("Bad transport string " + transport); throw new IllegalArgumentException(hop); } } /** * Retruns the host string. * @return host String */ public String getHost() { return host; } /** * Returns the port. * @return port integer. */ public int getPort() { return port; } /** returns the transport string. */ public String getTransport() { return transport; } /** Return true if this is uriRoute */ public boolean isURIRoute() { return uriRoute; } /** Set the URIRoute flag. */ public void setURIRouteFlag() { uriRoute = true; } } java/gov/nist/javax/sip/stack/IOHandler.java0100644 0000000 0000000 00000032672 13513104763 017774 0ustar000000000 0000000 /* * 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 United 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.javax.sip.stack; import gov.nist.core.StackLogger; import gov.nist.javax.sip.SipStackImpl; import java.io.*; import java.net.*; import java.util.Enumeration; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import javax.net.ssl.HandshakeCompletedListener; import javax.net.ssl.SSLSocket; /* * 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
    * * */ class IOHandler { private Semaphore ioSemaphore = new Semaphore(1); private SipStackImpl sipStack; private static String TCP = "tcp"; // Added by Daniel J. Martinez Manzano private static String TLS = "tls"; // A cache of client sockets that can be re-used for // sending tcp messages. private ConcurrentHashMap socketTable; protected static String makeKey(InetAddress addr, int port) { return addr.getHostAddress() + ":" + port; } protected IOHandler(SIPTransactionStack sipStack) { this.sipStack = (SipStackImpl) sipStack; this.socketTable = new ConcurrentHashMap(); } protected void putSocket(String key, Socket sock) { socketTable.put(key, sock); } protected Socket getSocket(String key) { return (Socket) socketTable.get(key); } protected void removeSocket(String key) { socketTable.remove(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 */ 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()) { sipStack.getStackLogger().logDebug( "sendBytes " + transport + " inAddr " + receiverAddress.getHostAddress() + " port = " + contactPort + " length = " + length); } if (sipStack.isLoggingEnabled() && 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 ). try { boolean retval = this.ioSemaphore.tryAcquire(10000, TimeUnit.MILLISECONDS); if (!retval) { throw new IOException( "Could not acquire IO Semaphore after 10 seconds -- giving up "); } } catch (InterruptedException ex) { throw new IOException("exception in acquiring sem"); } Socket clientSock = getSocket(key); try { while (retry_count < max_retry) { if (clientSock == null) { if (sipStack.isLoggingEnabled()) { 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. 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 (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug( "IOException occured retryCount " + retry_count); // old connection is bad. // remove from our table. removeSocket(key); try { clientSock.close(); } catch (Exception e) { } clientSock = null; retry_count++; } } } } finally { ioSemaphore.release(); } 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); try { boolean retval = this.ioSemaphore.tryAcquire(10000, TimeUnit.MILLISECONDS); if (!retval) throw new IOException("Timeout acquiring IO SEM"); } catch (InterruptedException ex) { throw new IOException("exception in acquiring sem"); } Socket clientSock = getSocket(key); try { while (retry_count < max_retry) { if (clientSock == null) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug("inaddr = " + receiverAddress); sipStack.getStackLogger().logDebug("port = " + contactPort); } clientSock = sipStack.getNetworkLayer().createSSLSocket(receiverAddress, contactPort, senderAddress); SSLSocket sslsock = (SSLSocket) clientSock; HandshakeCompletedListener listner = new HandshakeCompletedListenerImpl( (TLSMessageChannel) messageChannel); ((TLSMessageChannel) messageChannel) .setHandshakeCompletedListener(listner); sslsock.addHandshakeCompletedListener(listner); sslsock.setEnabledProtocols(sipStack.getEnabledProtocols()); sslsock.startHandshake(); 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++; } } } } finally { ioSemaphore.release(); } 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; } } /** * 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) { } } } } java/gov/nist/javax/sip/stack/MessageChannel.java0100644 0000000 0000000 00000041027 13513104763 021036 0ustar000000000 0000000 /* * 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.javax.sip.stack; import gov.nist.core.Host; import gov.nist.core.HostPort; import gov.nist.core.InternalErrorHandler; import gov.nist.core.ServerLogger; import gov.nist.javax.sip.address.AddressImpl; import gov.nist.javax.sip.header.ContentLength; import gov.nist.javax.sip.header.ContentType; import gov.nist.javax.sip.header.Via; import gov.nist.javax.sip.message.MessageFactoryImpl; import gov.nist.javax.sip.message.SIPMessage; import gov.nist.javax.sip.message.SIPRequest; import gov.nist.javax.sip.message.SIPResponse; import java.io.IOException; import java.net.InetAddress; import java.text.ParseException; import javax.sip.address.Hop; import javax.sip.header.CSeqHeader; import javax.sip.header.CallIdHeader; import javax.sip.header.ContactHeader; import javax.sip.header.ContentLengthHeader; import javax.sip.header.ContentTypeHeader; import javax.sip.header.FromHeader; import javax.sip.header.ServerHeader; import javax.sip.header.ToHeader; import javax.sip.header.ViaHeader; /** * 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.28 $ $Date: 2009/11/14 20:06:18 $ * * */ public abstract class MessageChannel { // 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() {} /** * Message processor to whom I belong (if set). */ protected transient MessageProcessor messageProcessor; /** * Close the message channel. */ public abstract void close(); /** * 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(); /** * Return true if this is a secure channel. */ public abstract boolean isSecure(); /** * 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(); protected abstract InetAddress getPeerInetAddress(); protected abstract String getPeerProtocol(); /** * Get the sender port ( the port of the other end that sent me the message). */ public abstract int getPeerPort(); public abstract int getPeerPacketSourcePort(); public abstract InetAddress getPeerPacketSourceAddress(); /** * Generate a key which identifies the message channel. This allows us to cache the message * channel. */ public abstract String getKey(); /** * Get the host to assign for an outgoing Request via header. */ public abstract String getViaHost(); /** * Get the port to assign for the via header of an outgoing message. */ 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. */ protected abstract void sendMessage(byte[] message, InetAddress receiverAddress, int receiverPort, boolean reconnectFlag) throws IOException; /** * Get the host of this message channel. * * @return host of this messsage channel. */ public String getHost() { return this.getMessageProcessor().getIpAddress().getHostAddress(); } /** * Get port of this message channel. * * @return Port of this message channel. */ public int getPort() { if (this.messageProcessor != null) return messageProcessor.getPort(); else return -1; } /** * 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 */ public void sendMessage(SIPMessage sipMessage, Hop hop) throws IOException { long time = System.currentTimeMillis(); InetAddress hopAddr = InetAddress.getByName(hop.getHost()); try { for (MessageProcessor messageProcessor : getSIPStack().getMessageProcessors()) { if (messageProcessor.getIpAddress().equals(hopAddr) && messageProcessor.getPort() == hop.getPort() && messageProcessor.getTransport().equals(hop.getTransport())) { MessageChannel messageChannel = messageProcessor.createMessageChannel( hopAddr, hop.getPort()); if (messageChannel instanceof RawMessageChannel) { ((RawMessageChannel) messageChannel).processMessage(sipMessage); if (getSIPStack().isLoggingEnabled()) getSIPStack().getStackLogger().logDebug("Self routing message"); return; } } } byte[] msg = sipMessage.encodeAsBytes(this.getTransport()); this.sendMessage(msg, hopAddr, hop.getPort(), sipMessage instanceof SIPRequest); } catch (IOException ioe) { throw ioe; } catch (Exception ex) { 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.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 */ public void sendMessage(SIPMessage sipMessage, InetAddress receiverAddress, int receiverPort) throws IOException { long time = System.currentTimeMillis(); byte[] bytes = sipMessage.encodeAsBytes(this.getTransport()); sendMessage(bytes, receiverAddress, receiverPort, sipMessage instanceof SIPRequest); logMessage(sipMessage, receiverAddress, receiverPort, time); } /** * Convenience function to get the raw IP source address of a SIP message as a String. */ public String getRawIpSourceAddress() { String sourceAddress = getPeerAddress(); String rawIpSourceAddress = null; try { InetAddress sourceInetAddress = InetAddress.getByName(sourceAddress); rawIpSourceAddress = sourceInetAddress.getHostAddress(); } catch (Exception ex) { InternalErrorHandler.handleException(ex); } return rawIpSourceAddress; } /** * generate a key given the inet address port and transport. */ public static String getKey(InetAddress inetAddr, int port, String transport) { return (transport + ":" + inetAddr.getHostAddress() + ":" + port).toLowerCase(); } /** * Generate a key given host and port. */ public static String getKey(HostPort hostPort, String transport) { return (transport + ":" + hostPort.getHost().getHostname() + ":" + hostPort.getPort()) .toLowerCase(); } /** * Get the hostport structure of this message channel. */ public HostPort getHostPort() { HostPort retval = new HostPort(); retval.setHost(new Host(this.getHost())); retval.setPort(this.getPort()); return retval; } /** * Get the peer host and port. * * @return a HostPort structure for the peer. */ public HostPort getPeerHostPort() { HostPort retval = new HostPort(); retval.setHost(new Host(this.getPeerAddress())); retval.setPort(this.getPeerPort()); return retval; } /** * 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() { Via channelViaHeader; channelViaHeader = new Via(); try { channelViaHeader.setTransport(getTransport()); } catch (ParseException ex) { } channelViaHeader.setSentBy(getHostPort()); return channelViaHeader; } /** * 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() { HostPort retval = new HostPort(); retval.setHost(new Host(this.getViaHost())); retval.setPort(this.getViaPort()); return retval; } /** * 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. */ protected void logMessage(SIPMessage sipMessage, InetAddress address, int port, long time) { if (!getSIPStack().getStackLogger().isLoggingEnabled(ServerLogger.TRACE_MESSAGES)) return; // Default port. if (port == -1) port = 5060; getSIPStack().serverLogger.logMessage(sipMessage, this.getHost() + ":" + this.getPort(), address.getHostAddress().toString() + ":" + port, true, time); } /** * 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(); if (peerport == 0 && sipResponse.getContactHeaders() != null) { ContactHeader contact = (ContactHeader) sipResponse.getContactHeaders().getFirst(); peerport = ((AddressImpl) contact.getAddress()).getPort(); } String from = getPeerAddress().toString() + ":" + peerport; String to = this.getHost() + ":" + getPort(); this.getSIPStack().serverLogger.logMessage(sipResponse, from, to, status, false, receptionTime); } /** * 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) { 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 if (!copyViaHeaders(badReq, buf)) return null; if (!copyHeader(CSeqHeader.NAME, badReq, buf)) return null; if (!copyHeader(CallIdHeader.NAME, badReq, buf)) return null; if (!copyHeader(FromHeader.NAME, badReq, buf)) return null; if (!copyHeader(ToHeader.NAME, badReq, buf)) return null; // Should add a to-tag if not already present... int toStart = buf.indexOf(ToHeader.NAME); if (toStart != -1 && buf.indexOf("tag", toStart) == -1) { buf.append(";tag=badreq"); } // Let's add a Server header too.. ServerHeader s = MessageFactoryImpl.getDefaultServerHeader(); if ( s != null ) { buf.append("\r\n" + s.toString()); } int clength = badReq.length(); if (! (this instanceof UDPMessageChannel) || clength + buf.length() + ContentTypeHeader.NAME.length() + ": message/sipfrag\r\n".length() + ContentLengthHeader.NAME.length() < 1300) { /* * Check to see we are within one UDP packet. */ ContentTypeHeader cth = new ContentType("message", "sipfrag"); buf.append("\r\n" + cth.toString()); ContentLength clengthHeader = new ContentLength(clength); buf.append("\r\n" + clengthHeader.toString()); buf.append("\r\n\r\n" + badReq); } else { 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, StringBuffer buf) { int start = fromReq.indexOf(name); if (start != -1) { int end = fromReq.indexOf("\r\n", start); if (end != -1) { // XX Assumes no continuation here... buf.append(fromReq.subSequence(start - 2, end)); // incl CRLF // in front return true; } } return false; } /** * 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, StringBuffer buf) { int start = fromReq.indexOf(ViaHeader.NAME); boolean found = false; while (start != -1) { int end = fromReq.indexOf("\r\n", start); if (end != -1) { // XX Assumes no continuation here... buf.append(fromReq.subSequence(start - 2, end)); // incl CRLF // in front found = true; start = fromReq.indexOf(ViaHeader.NAME, end); } else { return false; } } return found; } /** * Get the message processor. */ public MessageProcessor getMessageProcessor() { return this.messageProcessor; } } java/gov/nist/javax/sip/stack/MessageLog.java0100644 0000000 0000000 00000012005 13513104763 020201 0ustar000000000 0000000 /* * 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.javax.sip.stack; import gov.nist.javax.sip.LogRecord; /** * This class stores a message along with some other informations * Used to log messages. * *@version 1.2 $Revision: 1.9 $ $Date: 2009/07/17 18:58:13 $ * * @author M. Ranganathan
    * @author Marc Bednarek
    * * */ class MessageLog implements LogRecord { private String message; private String source; private String destination; private long timeStamp; private boolean isSender; private String firstLine; private String tid; private String callId; private long timeStampHeaderValue; /* (non-Javadoc) * @see gov.nist.javax.sip.stack.LogRecord#equals(java.lang.Object) */ public boolean equals(Object other) { if (!(other instanceof MessageLog)) { return false; } else { MessageLog otherLog = (MessageLog) other; return otherLog.message.equals(message) && otherLog.timeStamp == timeStamp; } } /** * Constructor */ public MessageLog( String message, String source, String destination, String timeStamp, boolean isSender, String firstLine, String tid, String callId, long timeStampHeaderValue) { if (message == null || message.equals("")) throw new IllegalArgumentException("null msg"); this.message = message; this.source = source; this.destination = destination; try { long ts = Long.parseLong(timeStamp); if (ts < 0) throw new IllegalArgumentException("Bad time stamp "); this.timeStamp = ts; } catch (NumberFormatException ex) { throw new IllegalArgumentException( "Bad number format " + timeStamp); } this.isSender = isSender; this.firstLine = firstLine; this.tid = tid; this.callId = callId; this.timeStampHeaderValue = timeStampHeaderValue; } public MessageLog( String message, String source, String destination, long timeStamp, boolean isSender, String firstLine, String tid, String callId, long timestampVal) { if (message == null || message.equals("")) throw new IllegalArgumentException("null msg"); this.message = message; this.source = source; this.destination = destination; if (timeStamp < 0) throw new IllegalArgumentException("negative ts"); this.timeStamp = timeStamp; this.isSender = isSender; this.firstLine = firstLine; this.tid = tid; this.callId = callId; this.timeStampHeaderValue = timestampVal; } /* (non-Javadoc) * @see gov.nist.javax.sip.stack.LogRecord#toString() */ public String toString() { String log; log = "\n"; log += "\n"; log += "\n"; return log; } } java/gov/nist/javax/sip/stack/MessageProcessor.java0100644 0000000 0000000 00000023772 13513104763 021454 0ustar000000000 0000000 /* * 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; import gov.nist.core.Host; import gov.nist.core.HostPort; import gov.nist.core.InternalErrorHandler; import gov.nist.javax.sip.ListeningPointImpl; import gov.nist.javax.sip.header.Via; import java.io.IOException; import java.net.InetAddress; import java.text.ParseException; import javax.sip.InvalidArgumentException; /** * This is the Stack abstraction for the active object that waits for messages * to appear on the wire and processes these messages by calling the * MessageFactory interface to create a ServerRequest or ServerResponse object. * The main job of the message processor is to instantiate message channels for * the given transport. * * @version 1.2 $Revision: 1.18 $ $Date: 2009/10/16 22:58:41 $ * * @author M. Ranganathan
    * */ public abstract class MessageProcessor implements Runnable { /** * A string containing the 0.0.0.0 IPv4 ANY address. */ protected static final String IN_ADDR_ANY = "0.0.0.0"; /** * A string containing the ::0 IPv6 ANY address. */ protected static final String IN6_ADDR_ANY = "::0"; /** * My Sent by string ( which I use to set the outgoing via header) */ private String sentBy; private HostPort sentByHostPort; /* * The IP Address that was originally assigned ( Can be ANY ) */ private String savedIpAddress; /** * The IP address where I am listening. */ private InetAddress ipAddress; /** * The port where I am listening */ private int port; /** * The transport where I am listening */ protected String transport; /** * The Listening Point to which I am assigned. */ private ListeningPointImpl listeningPoint; private boolean sentBySet; /** * Our stack (that created us). */ protected SIPTransactionStack sipStack; protected MessageProcessor( String transport ) { this.transport = transport; } /** * Constructor * * @param ipAddress -- ip address where I am listening for incoming requests. * @param port -- port where i am listening for incoming requests. * @param transport -- transport to use for the message processor (UDP/TCP/TLS). */ protected MessageProcessor( InetAddress ipAddress, int port, String transport, SIPTransactionStack transactionStack ) { this( transport ); this.initialize(ipAddress, port, transactionStack); } /** * Initializes this MessageProcessor. Needed for extensions * that use classloading * * @param ipAddress2 * @param transactionStack * @param port2 */ public final void initialize( InetAddress ipAddress, int port, SIPTransactionStack transactionStack ) { this.sipStack = transactionStack; this.savedIpAddress = ipAddress.getHostAddress(); this.ipAddress = ipAddress; this.port = port; this.sentByHostPort = new HostPort(); this.sentByHostPort.setHost(new Host(ipAddress.getHostAddress())); this.sentByHostPort.setPort(port); } /** * Get the transport string. * * @return A string that indicates the transport. (i.e. "tcp" or "udp") */ public String getTransport() { return this.transport; } /** * Get the port identifier. * * @return the port for this message processor. This is where you receive * messages. */ public int getPort() { return this.port; } /** * Get the Via header to assign for this message processor. The topmost via * header of the outoging messages use this. * * @return the ViaHeader to be used by the messages sent via this message processor. */ public Via getViaHeader() { try { Via via = new Via(); if (this.sentByHostPort != null) { via.setSentBy(sentByHostPort); via.setTransport(this.getTransport()); } else { Host host = new Host(); host.setHostname(this.getIpAddress().getHostAddress()); via.setHost(host); via.setPort(this.getPort()); via.setTransport(this.getTransport()); } return via; } catch (ParseException ex) { ex.printStackTrace(); return null; } catch (InvalidArgumentException ex) { ex.printStackTrace(); return null; } } public ListeningPointImpl getListeningPoint() { if ( listeningPoint == null ) { if ( this.getSIPStack().isLoggingEnabled()) { this.getSIPStack().getStackLogger().logError("getListeningPoint" + this + " returning null listeningpoint"); } } return listeningPoint; } public void setListeningPoint(ListeningPointImpl lp) { if ( this.getSIPStack().isLoggingEnabled()) { this.getSIPStack().getStackLogger().logDebug("setListeningPoint" + this + " listeningPoint = " + lp); } if ( lp.getPort() != this.getPort()) InternalErrorHandler.handleException ("lp mismatch with provider",getSIPStack().getStackLogger()); this.listeningPoint = lp; } /** * Get the saved IP Address. */ public String getSavedIpAddress() { return this.savedIpAddress; } /** * @return the ip address for this message processor. */ public InetAddress getIpAddress() { return this.ipAddress; } /** * @param ipAddress the ipAddress to set */ protected void setIpAddress(InetAddress ipAddress) { this.sentByHostPort.setHost( new Host(ipAddress.getHostAddress())); this.ipAddress = ipAddress; } /** * Set the sentby string. This is used for stamping outgoing messages sent * from this listening point. * * @param sentBy */ public void setSentBy(String sentBy) throws ParseException { int ind = sentBy.indexOf(":"); if (ind == -1) { this.sentByHostPort = new HostPort(); this.sentByHostPort.setHost(new Host(sentBy)); } else { this.sentByHostPort = new HostPort(); this.sentByHostPort.setHost(new Host(sentBy.substring(0, ind))); String portStr = sentBy.substring(ind + 1); try { int port = Integer.parseInt(portStr); this.sentByHostPort.setPort(port); } catch (NumberFormatException ex) { throw new ParseException("Bad format encountered at ", ind); } } this.sentBySet = true; this.sentBy = sentBy; } /** * Get the sentby string. * */ public String getSentBy() { if ( this.sentBy == null && this.sentByHostPort != null) { this.sentBy = this.sentByHostPort.toString(); } return this.sentBy; } //////////////////////////////////////////////////////////////////////////////////////// // Abstract methods /////////////////////////////////////////////////////////////////////////////////////// /** * Get the SIP Stack. * * @return the sip stack. */ public abstract SIPTransactionStack getSIPStack(); /** * Create a message channel for the specified host/port. * * @return New MessageChannel for this processor. */ public abstract MessageChannel createMessageChannel(HostPort targetHostPort) throws IOException; /** * Create a message channel for the specified host/port. * * @return New MessageChannel for this processor. */ public abstract MessageChannel createMessageChannel(InetAddress targetHost, int port) throws IOException; /** * Start our thread. */ public abstract void start() throws IOException; /** * Stop method. */ public abstract void stop(); /** * Default target port used by this processor. This is 5060 for TCP / UDP */ public abstract int getDefaultTargetPort(); /** * Flags whether this processor is secure or not. */ public abstract boolean isSecure(); /** * Maximum number of bytes that this processor can handle. */ public abstract int getMaximumMessageSize(); /** * Return true if there are pending messages to be processed (which prevents * the message channel from being closed). */ public abstract boolean inUse(); /** * Run method. */ public abstract void run(); /** * @return Returns the sentBySet. */ public boolean isSentBySet() { return sentBySet; } /** * Get the defalt port for the message processor. * * @param transport * @return -- the default port for the message processor. */ public static int getDefaultPort(String transport) { return transport.equalsIgnoreCase("TLS")?5061:5060; } } java/gov/nist/javax/sip/stack/RawMessageChannel.java0100644 0000000 0000000 00000000315 13513104763 021503 0ustar000000000 0000000 package gov.nist.javax.sip.stack; import gov.nist.javax.sip.message.SIPMessage; public interface RawMessageChannel { public abstract void processMessage(SIPMessage sipMessage) throws Exception ; } java/gov/nist/javax/sip/stack/SIPClientTransaction.java0100644 0000000 0000000 00000205706 13513104763 022167 0ustar000000000 0000000 /* * 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; import gov.nist.core.InternalErrorHandler; import gov.nist.core.NameValueList; import gov.nist.javax.sip.SIPConstants; 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.RecordRoute; import gov.nist.javax.sip.header.RecordRouteList; import gov.nist.javax.sip.header.Route; import gov.nist.javax.sip.header.RouteList; 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 java.io.IOException; import java.security.cert.X509Certificate; import java.text.ParseException; import java.util.ListIterator; import java.util.TimerTask; import java.util.concurrent.ConcurrentHashMap; import javax.net.ssl.SSLPeerUnverifiedException; import javax.sip.Dialog; import javax.sip.DialogState; import javax.sip.InvalidArgumentException; import javax.sip.ObjectInUseException; import javax.sip.SipException; import javax.sip.Timeout; import javax.sip.TimeoutEvent; import javax.sip.TransactionState; import javax.sip.address.Hop; import javax.sip.address.SipURI; import javax.sip.header.ExpiresHeader; import javax.sip.header.RouteHeader; import javax.sip.header.TimeStampHeader; import javax.sip.message.Request; /* * Jeff Keyser -- initial. Daniel J. Martinez Manzano --Added support for TLS message channel. * Emil Ivov -- bug fixes. Chris Beardshear -- bug fix. Andreas Bystrom -- bug fixes. Matt Keller * (Motorolla) -- bug fix. */ /** * Represents a client transaction. Implements the following state machines. (From RFC 3261) * *
     *                   
     *                    
     *                     
     *                      
     *                      
     *                      
     *                                                     |INVITE from TU
     *                                   Timer A fires     |INVITE sent
     *                                   Reset A,          V                      Timer B fires
     *                                   INVITE sent +-----------+                or Transport Err.
     *                                     +---------|           |---------------+inform TU
     *                                     |         |  Calling  |               |
     *                                     +-------->|           |-------------->|
     *                                               +-----------+ 2xx           |
     *                                                  |  |       2xx to TU     |
     *                                                  |  |1xx                  |
     *                          300-699 +---------------+  |1xx to TU            |
     *                         ACK sent |                  |                     |
     *                      resp. to TU |  1xx             V                     |
     *                                  |  1xx to TU  -----------+               |
     *                                  |  +---------|           |               |
     *                                  |  |         |Proceeding |-------------->|
     *                                  |  +-------->|           | 2xx           |
     *                                  |            +-----------+ 2xx to TU     |
     *                                  |       300-699    |                     |
     *                                  |       ACK sent,  |                     |
     *                                  |       resp. to TU|                     |
     *                                  |                  |                     |      NOTE:
     *                                  |  300-699         V                     |
     *                                  |  ACK sent  +-----------+Transport Err. |  transitions
     *                                  |  +---------|           |Inform TU      |  labeled with
     *                                  |  |         | Completed |-------------->|  the event
     *                                  |  +-------->|           |               |  over the action
     *                                  |            +-----------+               |  to take
     *                                  |              ˆ   |                     |
     *                                  |              |   | Timer D fires       |
     *                                  +--------------+   | -                   |
     *                                                     |                     |
     *                                                     V                     |
     *                                               +-----------+               |
     *                                               |           |               |
     *                                               | Terminated|<--------------+
     *                                               |           |
     *                                               +-----------+
     *                      
     *                                       Figure 5: INVITE client transaction
     *                      
     *                      
     *                                                         |Request from TU
     *                                                         |send request
     *                                     Timer E             V
     *                                     send request  +-----------+
     *                                         +---------|           |-------------------+
     *                                         |         |  Trying   |  Timer F          |
     *                                         +-------->|           |  or Transport Err.|
     *                                                   +-----------+  inform TU        |
     *                                      200-699         |  |                         |
     *                                      resp. to TU     |  |1xx                      |
     *                                      +---------------+  |resp. to TU              |
     *                                      |                  |                         |
     *                                      |   Timer E        V       Timer F           |
     *                                      |   send req +-----------+ or Transport Err. |
     *                                      |  +---------|           | inform TU         |
     *                                      |  |         |Proceeding |------------------>|
     *                                      |  +-------->|           |-----+             |
     *                                      |            +-----------+     |1xx          |
     *                                      |              |      ˆ        |resp to TU   |
     *                                      | 200-699      |      +--------+             |
     *                                      | resp. to TU  |                             |
     *                                      |              |                             |
     *                                      |              V                             |
     *                                      |            +-----------+                   |
     *                                      |            |           |                   |
     *                                      |            | Completed |                   |
     *                                      |            |           |                   |
     *                                      |            +-----------+                   |
     *                                      |              ˆ   |                         |
     *                                      |              |   | Timer K                 |
     *                                      +--------------+   | -                       |
     *                                                         |                         |
     *                                                         V                         |
     *                                   NOTE:           +-----------+                   |
     *                                                   |           |                   |
     *                               transitions         | Terminated|<------------------+
     *                               labeled with        |           |
     *                               the event           +-----------+
     *                               over the action
     *                               to take
     *                      
     *                                       Figure 6: non-INVITE client transaction
     *                      
     *                      
     *                      
     *                      
     *                     
     *                    
     * 
    * * * @author M. Ranganathan * * @version 1.2 $Revision: 1.122 $ $Date: 2009/12/17 23:33:52 $ */ public class SIPClientTransaction extends SIPTransaction implements ServerResponseInterface, javax.sip.ClientTransaction, gov.nist.javax.sip.ClientTransactionExt { // 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. private ConcurrentHashMap sipDialogs; private SIPRequest lastRequest; private int viaPort; private String viaHost; // Real ResponseInterface to pass messages to private transient ServerResponseInterface respondTo; private SIPDialog defaultDialog; private Hop nextHop; private boolean notifyOnRetransmit; private boolean timeoutIfStillInCallingState; private int callingStateTimeoutCount; public class TransactionTimer extends SIPStackTimerTask { public TransactionTimer() { } protected void runTask() { SIPClientTransaction clientTransaction; SIPTransactionStack sipStack; clientTransaction = SIPClientTransaction.this; sipStack = clientTransaction.sipStack; // If the transaction has terminated, if (clientTransaction.isTerminated()) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "removing = " + clientTransaction + " isReliable " + clientTransaction.isReliable()); } sipStack.removeTransaction(clientTransaction); try { this.cancel(); } catch (IllegalStateException ex) { if (!sipStack.isAlive()) return; } // 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() && clientTransaction.isReliable()) { int useCount = clientTransaction.getMessageChannel().useCount; if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("Client Use Count = " + useCount); } } } else { // If this transaction has not // terminated, // Fire the transaction timer. clientTransaction.fireTimer(); } } } /** * Creates a new client transaction. * * @param newSIPStack Transaction stack this transaction belongs to. * @param newChannelToUse Channel to encapsulate. * @return the created client transaction. */ 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; // 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()) { sipStack.getStackLogger().logDebug("Creating clientTransaction " + this); sipStack.getStackLogger().logStackTrace(); } // this.startTransactionTimer(); this.sipDialogs = new ConcurrentHashMap(); } /** * Sets the real ResponseInterface this transaction encapsulates. * * @param newRespondTo ResponseInterface to send messages to. */ public void setResponseInterface(ServerResponseInterface newRespondTo) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "Setting response interface for " + this + " to " + newRespondTo); if (newRespondTo == null) { sipStack.getStackLogger().logStackTrace(); sipStack.getStackLogger().logDebug("WARNING -- setting to null!"); } } respondTo = newRespondTo; } /** * Returns this transaction. */ public MessageChannel getRequestChannel() { return this; } /** * Deterines if the message is a part of this transaction. * * @param messageToTest Message to check if it is part of this transaction. * * @return true if the message is part of this transaction, false if not. */ public boolean isMessagePartOfTransaction(SIPMessage messageToTest) { // List of Via headers in the message to test ViaList viaHeaders = messageToTest.getViaHeaders(); // Flags whether the select message is part of this transaction boolean transactionMatches; String messageBranch = ((Via) viaHeaders.getFirst()).getBranch(); boolean rfc3261Compliant = getBranch() != null && messageBranch != null && getBranch().toLowerCase().startsWith( SIPConstants.BRANCH_MAGIC_COOKIE_LOWER_CASE) && messageBranch.toLowerCase().startsWith( SIPConstants.BRANCH_MAGIC_COOKIE_LOWER_CASE); transactionMatches = false; if (TransactionState.COMPLETED == this.getState()) { if (rfc3261Compliant) { transactionMatches = getBranch().equalsIgnoreCase( ((Via) viaHeaders.getFirst()).getBranch()) && getMethod().equals(messageToTest.getCSeq().getMethod()); } else { transactionMatches = getBranch().equals(messageToTest.getTransactionId()); } } else if (!isTerminated()) { if (rfc3261Compliant) { if (viaHeaders != null) { // If the branch parameter is the // same as this transaction and the method is the same, if (getBranch().equalsIgnoreCase(((Via) viaHeaders.getFirst()).getBranch())) { transactionMatches = getOriginalRequest().getCSeq().getMethod().equals( messageToTest.getCSeq().getMethod()); } } } else { // not RFC 3261 compliant. if (getBranch() != null) { transactionMatches = getBranch().equalsIgnoreCase( messageToTest.getTransactionId()); } else { transactionMatches = getOriginalRequest().getTransactionId() .equalsIgnoreCase(messageToTest.getTransactionId()); } } } return transactionMatches; } /** * Send a request message through this transaction and onto the client. * * @param messageToSend Request to process and send. */ public void sendMessage(SIPMessage messageToSend) throws IOException { try { // Message typecast as a request SIPRequest transactionRequest; transactionRequest = (SIPRequest) messageToSend; // Set the branch id for the top via header. Via topVia = (Via) transactionRequest.getViaHeaders().getFirst(); // Tack on a branch identifier to match responses. try { topVia.setBranch(getBranch()); } catch (java.text.ParseException ex) { } if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug("Sending Message " + messageToSend); sipStack.getStackLogger().logDebug("TransactionState " + this.getState()); } // If this is the first request for this transaction, if (TransactionState.PROCEEDING == getState() || TransactionState.CALLING == getState()) { // If this is a TU-generated ACK request, if (transactionRequest.getMethod().equals(Request.ACK)) { // Send directly to the underlying // transport and close this transaction if (isReliable()) { this.setState(TransactionState.TERMINATED); } else { this.setState(TransactionState.COMPLETED); } // BUGBUG -- This suppresses sending the ACK uncomment this // to // test 4xx retransmission // if (transactionRequest.getMethod() != Request.ACK) super.sendMessage(transactionRequest); return; } } try { // Send the message to the server lastRequest = transactionRequest; if (getState() == null) { // Save this request as the one this transaction // is handling setOriginalRequest(transactionRequest); // Change to trying/calling state // Set state first to avoid race condition.. if (transactionRequest.getMethod().equals(Request.INVITE)) { this.setState(TransactionState.CALLING); } else if (transactionRequest.getMethod().equals(Request.ACK)) { // Acks are never retransmitted. this.setState(TransactionState.TERMINATED); } else { this.setState(TransactionState.TRYING); } if (!isReliable()) { enableRetransmissionTimer(); } if (isInviteTransaction()) { enableTimeoutTimer(TIMER_B); } else { enableTimeoutTimer(TIMER_F); } } // BUGBUG This supresses sending ACKS -- uncomment to test // 4xx retransmission. // if (transactionRequest.getMethod() != Request.ACK) super.sendMessage(transactionRequest); } catch (IOException e) { this.setState(TransactionState.TERMINATED); throw e; } } finally { this.isMapped = true; this.startTransactionTimer(); } } /** * Process a new response message through this transaction. If necessary, this message will * also be passed onto the TU. * * @param transactionResponse Response to process. * @param sourceChannel Channel that received this message. */ public synchronized void processResponse(SIPResponse transactionResponse, MessageChannel sourceChannel, SIPDialog dialog) { // If the state has not yet been assigned then this is a // spurious response. if (getState() == null) return; // Ignore 1xx if ((TransactionState.COMPLETED == this.getState() || TransactionState.TERMINATED == this .getState()) && transactionResponse.getStatusCode() / 100 == 1) { return; } if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "processing " + transactionResponse.getFirstLine() + "current state = " + getState()); sipStack.getStackLogger().logDebug("dialog = " + dialog); } this.lastResponse = transactionResponse; /* * JvB: this is now duplicate with code in the other processResponse * * if (dialog != null && transactionResponse.getStatusCode() != 100 && * (transactionResponse.getTo().getTag() != null || sipStack .isRfc2543Supported())) { // * add the route before you process the response. dialog.setLastResponse(this, * transactionResponse); this.setDialog(dialog, transactionResponse.getDialogId(false)); } */ try { if (isInviteTransaction()) inviteClientTransaction(transactionResponse, sourceChannel, dialog); else nonInviteClientTransaction(transactionResponse, sourceChannel, dialog); } catch (IOException ex) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logException(ex); this.setState(TransactionState.TERMINATED); raiseErrorEvent(SIPTransactionErrorEvent.TRANSPORT_ERROR); } } /** * Implements the state machine for invite client transactions. * *
         *                   
         *                    
         *                     
         *                      
         *                      
         *                                                         |Request from TU
         *                                                         |send request
         *                                     Timer E             V
         *                                     send request  +-----------+
         *                                         +---------|           |-------------------+
         *                                         |         |  Trying   |  Timer F          |
         *                                         +-------->|           |  or Transport Err.|
         *                                                   +-----------+  inform TU        |
         *                                      200-699         |  |                         |
         *                                      resp. to TU     |  |1xx                      |
         *                                      +---------------+  |resp. to TU              |
         *                                      |                  |                         |
         *                                      |   Timer E        V       Timer F           |
         *                                      |   send req +-----------+ or Transport Err. |
         *                                      |  +---------|           | inform TU         |
         *                                      |  |         |Proceeding |------------------>|
         *                                      |  +-------->|           |-----+             |
         *                                      |            +-----------+     |1xx          |
         *                                      |              |      ˆ        |resp to TU   |
         *                                      | 200-699      |      +--------+             |
         *                                      | resp. to TU  |                             |
         *                                      |              |                             |
         *                                      |              V                             |
         *                                      |            +-----------+                   |
         *                                      |            |           |                   |
         *                                      |            | Completed |                   |
         *                                      |            |           |                   |
         *                                      |            +-----------+                   |
         *                                      |              ˆ   |                         |
         *                                      |              |   | Timer K                 |
         *                                      +--------------+   | -                       |
         *                                                         |                         |
         *                                                         V                         |
         *                                   NOTE:           +-----------+                   |
         *                                                   |           |                   |
         *                               transitions         | Terminated|<------------------+
         *                               labeled with        |           |
         *                               the event           +-----------+
         *                               over the action
         *                               to take
         *                      
         *                                       Figure 6: non-INVITE client transaction
         *                      
         *                      
         *                     
         *                    
         * 
    * * @param transactionResponse -- transaction response received. * @param sourceChannel - source channel on which the response was received. */ private void nonInviteClientTransaction(SIPResponse transactionResponse, MessageChannel sourceChannel, SIPDialog sipDialog) throws IOException { int statusCode = transactionResponse.getStatusCode(); 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 // this transition. if (respondTo != null) { respondTo.processResponse(transactionResponse, this, sipDialog); } else { this.semRelease(); } } else if (200 <= statusCode && statusCode <= 699) { // Send the response up to the TU. if (respondTo != null) { respondTo.processResponse(transactionResponse, this, sipDialog); } else { this.semRelease(); } if (!isReliable()) { this.setState(TransactionState.COMPLETED); enableTimeoutTimer(TIMER_K); } else { this.setState(TransactionState.TERMINATED); } } } else if (TransactionState.PROCEEDING == this.getState()) { if (statusCode / 100 == 1) { if (respondTo != null) { respondTo.processResponse(transactionResponse, this, sipDialog); } else { this.semRelease(); } } else if (200 <= statusCode && statusCode <= 699) { if (respondTo != null) { respondTo.processResponse(transactionResponse, this, sipDialog); } else { this.semRelease(); } disableRetransmissionTimer(); disableTimeoutTimer(); if (!isReliable()) { this.setState(TransactionState.COMPLETED); enableTimeoutTimer(TIMER_K); } else { this.setState(TransactionState.TERMINATED); } } } else { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( " Not sending response to TU! " + getState()); } this.semRelease(); } } /** * Implements the state machine for invite client transactions. * *
         *                   
         *                    
         *                     
         *                      
         *                      
         *                                                     |INVITE from TU
         *                                   Timer A fires     |INVITE sent
         *                                   Reset A,          V                      Timer B fires
         *                                   INVITE sent +-----------+                or Transport Err.
         *                                     +---------|           |---------------+inform TU
         *                                     |         |  Calling  |               |
         *                                     +-------->|           |-------------->|
         *                                               +-----------+ 2xx           |
         *                                                  |  |       2xx to TU     |
         *                                                  |  |1xx                  |
         *                          300-699 +---------------+  |1xx to TU            |
         *                         ACK sent |                  |                     |
         *                      resp. to TU |  1xx             V                     |
         *                                  |  1xx to TU  -----------+               |
         *                                  |  +---------|           |               |
         *                                  |  |         |Proceeding |-------------->|
         *                                  |  +-------->|           | 2xx           |
         *                                  |            +-----------+ 2xx to TU     |
         *                                  |       300-699    |                     |
         *                                  |       ACK sent,  |                     |
         *                                  |       resp. to TU|                     |
         *                                  |                  |                     |      NOTE:
         *                                  |  300-699         V                     |
         *                                  |  ACK sent  +-----------+Transport Err. |  transitions
         *                                  |  +---------|           |Inform TU      |  labeled with
         *                                  |  |         | Completed |-------------->|  the event
         *                                  |  +-------->|           |               |  over the action
         *                                  |            +-----------+               |  to take
         *                                  |              ˆ   |                     |
         *                                  |              |   | Timer D fires       |
         *                                  +--------------+   | -                   |
         *                                                     |                     |
         *                                                     V                     |
         *                                               +-----------+               |
         *                                               |           |               |
         *                                               | Terminated|<--------------+
         *                                               |           |
         *                                               +-----------+
         *                      
         *                      
         *                     
         *                    
         * 
    * * @param transactionResponse -- transaction response received. * @param sourceChannel - source channel on which the response was received. */ private void inviteClientTransaction(SIPResponse transactionResponse, MessageChannel sourceChannel, SIPDialog dialog) throws IOException { int statusCode = transactionResponse.getStatusCode(); if (TransactionState.TERMINATED == this.getState()) { boolean ackAlreadySent = false; if (dialog != null && dialog.isAckSeen() && dialog.getLastAckSent() != null) { if (dialog.getLastAckSent().getCSeq().getSeqNumber() == transactionResponse.getCSeq() .getSeqNumber() && transactionResponse.getFromTag().equals( dialog.getLastAckSent().getFromTag())) { // the last ack sent corresponded to this response ackAlreadySent = true; } } // retransmit the ACK for this response. if (dialog!= null && ackAlreadySent && transactionResponse.getCSeq().getMethod().equals(dialog.getMethod())) { try { // Found the dialog - resend the ACK and // dont pass up the null transaction if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("resending ACK"); dialog.resendAck(); } catch (SipException ex) { // What to do here ?? kill the dialog? } } this.semRelease(); return; } 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); // 200 responses are always seen by TU. if (respondTo != null) respondTo.processResponse(transactionResponse, this, dialog); else { this.semRelease(); } } else if (statusCode / 100 == 1) { disableRetransmissionTimer(); disableTimeoutTimer(); this.setState(TransactionState.PROCEEDING); if (respondTo != null) respondTo.processResponse(transactionResponse, this, dialog); else { this.semRelease(); } } else if (300 <= statusCode && statusCode <= 699) { // Send back an ACK request try { sendMessage((SIPRequest) createErrorAck()); } catch (Exception ex) { sipStack.getStackLogger().logError( "Unexpected Exception sending ACK -- sending error AcK ", ex); } /* * When in either the "Calling" or "Proceeding" states, reception of response with * status code from 300-699 MUST cause the client transaction to transition to * "Completed". The client transaction MUST pass the received response up to the * 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); enableTimeoutTimer(TIMER_D); } else { // Proceed immediately to the TERMINATED state. this.setState(TransactionState.TERMINATED); } } } 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); if (respondTo != null) { respondTo.processResponse(transactionResponse, this, dialog); } else { this.semRelease(); } } else if (300 <= statusCode && statusCode <= 699) { // Send back an ACK request try { sendMessage((SIPRequest) createErrorAck()); } catch (Exception ex) { InternalErrorHandler.handleException(ex); } if (this.getDialog() != null) { ((SIPDialog) this.getDialog()).releaseAckSem(); } // JvB: update state before passing to app if (!isReliable()) { this.setState(TransactionState.COMPLETED); this.enableTimeoutTimer(TIMER_D); } else { this.setState(TransactionState.TERMINATED); } // Pass up to the TU for processing. if (respondTo != null) respondTo.processResponse(transactionResponse, this, dialog); else { this.semRelease(); } // JvB: duplicate with line 874 // if (!isReliable()) { // enableTimeoutTimer(TIMER_D); // } } } else if (TransactionState.COMPLETED == this.getState()) { if (300 <= statusCode && statusCode <= 699) { // Send back an ACK request try { sendMessage((SIPRequest) createErrorAck()); } catch (Exception ex) { InternalErrorHandler.handleException(ex); } finally { this.semRelease(); } } } } /* * (non-Javadoc) * * @see javax.sip.ClientTransaction#sendRequest() */ public void sendRequest() throws SipException { SIPRequest sipRequest = this.getOriginalRequest(); if (this.getState() != null) throw new SipException("Request already sent"); if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug("sendRequest() " + sipRequest); } try { sipRequest.checkHeaders(); } catch (ParseException ex) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logError("missing required header"); throw new SipException(ex.getMessage()); } if (getMethod().equals(Request.SUBSCRIBE) && sipRequest.getHeader(ExpiresHeader.NAME) == null) { /* * If no "Expires" header is present in a SUBSCRIBE request, the implied default is * defined by the event package being used. * */ if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logWarning( "Expires header missing in outgoing subscribe --" + " Notifier will assume implied value on event package"); } try { /* * This check is removed because it causes problems for load balancers ( See issue * 136) reported by Raghav Ramesh ( BT ) * */ if (this.getOriginalRequest().getMethod().equals(Request.CANCEL) && sipStack.isCancelClientTransactionChecked()) { SIPClientTransaction ct = (SIPClientTransaction) sipStack.findCancelTransaction( this.getOriginalRequest(), false); if (ct == null) { /* * If the original request has generated a final response, the CANCEL SHOULD * NOT be sent, as it is an effective no-op, since CANCEL has no effect on * 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.getState() == null) { throw new SipException( "State is null no provisional response yet -- cannot cancel RFC 3261 9.1"); } else if (!ct.getMethod().equals(Request.INVITE)) { throw new SipException("Cannot cancel non-invite requests RFC 3261 9.1"); } } 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 // Dialog if (this.getSipProvider().isAutomaticDialogSupportEnabled() && dialog != null) { throw new SipException( "Dialog is present and AutomaticDialogSupport is enabled for " + " the provider -- Send the Request using the Dialog.sendRequest(transaction)"); } } // Only map this after the fist request is sent out. if (this.getMethod().equals(Request.INVITE)) { SIPDialog dialog = this.getDefaultDialog(); if (dialog != null && dialog.isBackToBackUserAgent()) { // Block sending re-INVITE till we see the ACK. if ( ! dialog.takeAckSem() ) { throw new SipException ("Failed to take ACK semaphore"); } } } this.isMapped = true; this.sendMessage(sipRequest); } catch (IOException ex) { this.setState(TransactionState.TERMINATED); throw new SipException("IO Error sending request", ex); } } /** * Called by the transaction stack when a retransmission timer fires. */ protected void fireRetransmissionTimer() { try { // Resend the last request sent if (this.getState() == null || !this.isMapped) return; boolean inv = isInviteTransaction(); 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 the retransmission filter is disabled then // retransmission of the INVITE is the application // responsibility. if (lastRequest != null) { if (sipStack.generateTimeStampHeader && lastRequest.getHeader(TimeStampHeader.NAME) != null) { long milisec = System.currentTimeMillis(); TimeStamp timeStamp = new TimeStamp(); try { timeStamp.setTimeStamp(milisec); } catch (InvalidArgumentException ex) { InternalErrorHandler.handleException(ex); } lastRequest.setHeader(timeStamp); } super.sendMessage(lastRequest); if (this.notifyOnRetransmit) { TimeoutEvent txTimeout = new TimeoutEvent(this.getSipProvider(), this, Timeout.RETRANSMIT); this.getSipProvider().handleEvent(txTimeout, this); } if (this.timeoutIfStillInCallingState && this.getState() == TransactionState.CALLING) { this.callingStateTimeoutCount--; if (callingStateTimeoutCount == 0) { TimeoutEvent timeoutEvent = new TimeoutEvent(this.getSipProvider(), this, Timeout.RETRANSMIT); this.getSipProvider().handleEvent(timeoutEvent, this); this.timeoutIfStillInCallingState = false; } } } } } catch (IOException e) { this.raiseIOExceptionEvent(); raiseErrorEvent(SIPTransactionErrorEvent.TRANSPORT_ERROR); } } /** * Called by the transaction stack when a timeout timer fires. */ protected void fireTimeoutTimer() { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("fireTimeoutTimer " + this); SIPDialog dialog = (SIPDialog) this.getDialog(); 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) getSIPStack()).isDialogCreated(this .getOriginalRequest().getMethod())) { // If this is a re-invite we do not delete the dialog even // if the // reinvite times out. Else // terminate the enclosing dialog. dialog.delete(); } } else if (dialog != null) { // Guard against the case of BYE time out. if (getOriginalRequest().getMethod().equalsIgnoreCase(Request.BYE) && dialog.isTerminatedOnBye()) { // Terminate the associated dialog on BYE Timeout. dialog.delete(); } } } if (TransactionState.COMPLETED != this.getState()) { raiseErrorEvent(SIPTransactionErrorEvent.TIMEOUT_ERROR); // Got a timeout error on a cancel. if (this.getOriginalRequest().getMethod().equalsIgnoreCase(Request.CANCEL)) { SIPClientTransaction inviteTx = (SIPClientTransaction) this.getOriginalRequest() .getInviteTransaction(); if (inviteTx != null && ((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); } } } else { this.setState(TransactionState.TERMINATED); } } /* * (non-Javadoc) * * @see javax.sip.ClientTransaction#createCancel() */ public Request createCancel() throws SipException { SIPRequest originalRequest = this.getOriginalRequest(); if (originalRequest == null) throw new SipException("Bad state " + getState()); if (!originalRequest.getMethod().equals(Request.INVITE)) throw new SipException("Only INIVTE may be cancelled"); if (originalRequest.getMethod().equalsIgnoreCase(Request.ACK)) throw new SipException("Cannot Cancel ACK!"); else { SIPRequest cancelRequest = originalRequest.createCancelRequest(); cancelRequest.setInviteTransaction(this); return cancelRequest; } } /* * (non-Javadoc) * * @see javax.sip.ClientTransaction#createAck() */ public Request createAck() throws SipException { SIPRequest originalRequest = this.getOriginalRequest(); if (originalRequest == null) throw new SipException("bad state " + getState()); if (getMethod().equalsIgnoreCase(Request.ACK)) { throw new SipException("Cannot ACK an ACK!"); } else if (lastResponse == null) { throw new SipException("bad Transaction state"); } else if (lastResponse.getStatusCode() < 200) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug("lastResponse = " + lastResponse); } throw new SipException("Cannot ACK a provisional response!"); } SIPRequest ackRequest = originalRequest.createAckRequest((To) lastResponse.getTo()); // Pull the record route headers from the last reesponse. RecordRouteList recordRouteList = lastResponse.getRecordRouteHeaders(); if (recordRouteList == null) { // If the record route list is null then we can // construct the ACK from the specified contact header. // Note the 3xx check here because 3xx is a redirect. // The contact header for the 3xx is the redirected // location so we cannot use that to construct the // request URI. if (lastResponse.getContactHeaders() != null && lastResponse.getStatusCode() / 100 != 3) { Contact contact = (Contact) lastResponse.getContactHeaders().getFirst(); javax.sip.address.URI uri = (javax.sip.address.URI) contact.getAddress().getURI() .clone(); ackRequest.setRequestURI(uri); } return ackRequest; } ackRequest.removeHeader(RouteHeader.NAME); RouteList routeList = new RouteList(); // start at the end of the list and walk backwards ListIterator li = recordRouteList.listIterator(recordRouteList.size()); while (li.hasPrevious()) { RecordRoute rr = (RecordRoute) li.previous(); Route route = new Route(); route.setAddress((AddressImpl) ((AddressImpl) rr.getAddress()).clone()); route.setParameters((NameValueList) rr.getParameters().clone()); routeList.add(route); } Contact contact = null; if (lastResponse.getContactHeaders() != null) { contact = (Contact) lastResponse.getContactHeaders().getFirst(); } if (!((SipURI) ((Route) routeList.getFirst()).getAddress().getURI()).hasLrParam()) { // Contact may not yet be there (bug reported by Andreas B). Route route = null; if (contact != null) { route = new Route(); route.setAddress((AddressImpl) ((AddressImpl) (contact.getAddress())).clone()); } Route firstRoute = (Route) routeList.getFirst(); routeList.removeFirst(); javax.sip.address.URI uri = firstRoute.getAddress().getURI(); ackRequest.setRequestURI(uri); if (route != null) routeList.add(route); ackRequest.addHeader(routeList); } else { if (contact != null) { javax.sip.address.URI uri = (javax.sip.address.URI) contact.getAddress().getURI() .clone(); ackRequest.setRequestURI(uri); ackRequest.addHeader(routeList); } } return ackRequest; } /* * Creates an ACK for an error response, according to RFC3261 section 17.1.1.3 * * Note that this is different from an ACK for 2xx */ private final Request createErrorAck() throws SipException, ParseException { SIPRequest originalRequest = this.getOriginalRequest(); if (originalRequest == null) throw new SipException("bad state " + getState()); 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 (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug("lastResponse = " + lastResponse); } throw new SipException("Cannot ACK a provisional response!"); } return originalRequest.createErrorAck((To) lastResponse.getTo()); } /** * Set the port of the recipient. */ protected void setViaPort(int port) { this.viaPort = port; } /** * Set the port of the recipient. */ protected void setViaHost(String host) { this.viaHost = host; } /** * Get the port of the recipient. */ public int getViaPort() { return this.viaPort; } /** * Get the host of the recipient. */ public String getViaHost() { return this.viaHost; } /** * get the via header for an outgoing request. */ public Via getOutgoingViaHeader() { return this.getMessageProcessor().getViaHeader(); } /** * This is called by the stack after a non-invite client transaction goes to completed state. */ public void clearState() { // reduce the state to minimum // This assumes that the application will not need // to access the request once the transaction is // completed. // TODO -- revisit this - results in a null pointer // occuring occasionally. // this.lastRequest = null; // this.originalRequest = null; // this.lastResponse = null; } /** * Sets a timeout after which the connection is closed (provided the server does not use the * connection for outgoing requests in this time period) and calls the superclass to set * state. */ public void setState(TransactionState newState) { // Set this timer for connection caching // of incoming connections. if (newState == TransactionState.TERMINATED && this.isReliable() && (!getSIPStack().cacheClientConnections)) { // Set a time after which the connection // is closed. this.collectionTime = TIMER_J; } if (super.getState() != TransactionState.COMPLETED && (newState == TransactionState.COMPLETED || newState == TransactionState.TERMINATED)) { sipStack.decrementActiveClientTransactionCount(); } super.setState(newState); } /** * Start the timer task. */ protected void startTransactionTimer() { if (this.transactionTimerStarted.compareAndSet(false, true)) { TimerTask myTimer = new TransactionTimer(); if ( sipStack.getTimer() != null ) { sipStack.getTimer().schedule(myTimer, BASE_TIMER_INTERVAL, BASE_TIMER_INTERVAL); } } } /* * Terminate a transaction. This marks the tx as terminated The tx scanner will run and remove * the tx. (non-Javadoc) * * @see javax.sip.Transaction#terminate() */ public void terminate() throws ObjectInUseException { this.setState(TransactionState.TERMINATED); } /** * Check if the From tag of the response matches the from tag of the original message. A * Response with a tag mismatch should be dropped if a Dialog has been created for the * original request. * * @param sipResponse the response to check. * @return true if the check passes. */ public boolean checkFromTag(SIPResponse sipResponse) { String originalFromTag = ((SIPRequest) this.getRequest()).getFromTag(); if (this.defaultDialog != null) { if (originalFromTag == null ^ sipResponse.getFrom().getTag() == null) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("From tag mismatch -- dropping response"); return false; } if (originalFromTag != null && !originalFromTag.equalsIgnoreCase(sipResponse.getFrom().getTag())) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("From tag mismatch -- dropping response"); return false; } } return true; } /* * (non-Javadoc) * * @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) { // If a dialog has already been created for this response, // pass it up. SIPDialog dialog = null; String method = sipResponse.getCSeq().getMethod(); String dialogId = sipResponse.getDialogId(false); if (method.equals(Request.CANCEL) && lastRequest != null) { // JvB for CANCEL: use invite CT in CANCEL request to get dialog // (instead of stripping tag) SIPClientTransaction ict = (SIPClientTransaction) lastRequest.getInviteTransaction(); if (ict != null) { dialog = ict.defaultDialog; } } else { dialog = this.getDialog(dialogId); } // 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()) && sipStack.isDialogCreated(method)) { /* * Dialog cannot be found for the response. This must be a forked response. no * dialog assigned to this response but a default dialog has been assigned. Note * that if automatic dialog support is configured then a default dialog is always * created. */ synchronized (this) { /* * We need synchronization here because two responses may compete for the * default dialog simultaneously */ if (defaultDialog != null) { if (sipResponse.getFromTag() != null) { SIPResponse dialogResponse = defaultDialog.getLastResponse(); String defaultDialogId = defaultDialog.getDialogId(); if (dialogResponse == null || (method.equals(Request.SUBSCRIBE) && dialogResponse.getCSeq().getMethod().equals( Request.NOTIFY) && defaultDialogId .equals(dialogId))) { // The default dialog has not been claimed yet. defaultDialog.setLastResponse(this, sipResponse); dialog = defaultDialog; } else { /* * check if we have created one previously (happens in the case of * REINVITE processing. JvB: should not happen, this.defaultDialog * should then get set in Dialog#sendRequest line 1662 */ dialog = sipStack.getDialog(dialogId); if (dialog == null) { if (defaultDialog.isAssigned()) { /* * Nop we dont have one. so go ahead and allocate a new * one. */ dialog = sipStack.createDialog(this, sipResponse); } } } if ( dialog != null ) { this.setDialog(dialog, dialog.getDialogId()); } else { sipStack.getStackLogger().logError("dialog is unexpectedly null",new NullPointerException()); } } else { throw new RuntimeException("Response without from-tag"); } } else { // Need to create a new Dialog, this becomes default // JvB: not sure if this ever gets executed if (sipStack.isAutomaticDialogSupportEnabled) { dialog = sipStack.createDialog(this, sipResponse); this.setDialog(dialog, dialog.getDialogId()); } } } // synchronized } else { dialog = defaultDialog; } } else { dialog.setLastResponse(this, sipResponse); } this.processResponse(sipResponse, incomingChannel, dialog); } /* * (non-Javadoc) * * @see gov.nist.javax.sip.stack.SIPTransaction#getDialog() */ public Dialog getDialog() { // This is for backwards compatibility. Dialog retval = null; 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.defaultDialog; } if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( " sipDialogs = " + sipDialogs + " default dialog " + this.defaultDialog + " retval " + retval); } return retval; } /* * (non-Javadoc) * * @see gov.nist.javax.sip.stack.SIPTransaction#setDialog(gov.nist.javax.sip.stack.SIPDialog, * gov.nist.javax.sip.message.SIPMessage) */ public SIPDialog getDialog(String dialogId) { SIPDialog retval = (SIPDialog) this.sipDialogs.get(dialogId); return retval; } /* * (non-Javadoc) * * @see gov.nist.javax.sip.stack.SIPTransaction#setDialog(gov.nist.javax.sip.stack.SIPDialog, * gov.nist.javax.sip.message.SIPMessage) */ public void setDialog(SIPDialog sipDialog, String dialogId) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug( "setDialog: " + dialogId + "sipDialog = " + sipDialog); if (sipDialog == null) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logError("NULL DIALOG!!"); throw new NullPointerException("bad dialog null"); } if (this.defaultDialog == null) { this.defaultDialog = sipDialog; if ( this.getMethod().equals(Request.INVITE) && this.getSIPStack().maxForkTime != 0) { this.getSIPStack().addForkedClientTransaction(this); } } if (dialogId != null && sipDialog.getDialogId() != null) { this.sipDialogs.put(dialogId, sipDialog); } } public SIPDialog getDefaultDialog() { return this.defaultDialog; } /** * Set the next hop ( if it has already been computed). * * @param hop -- the hop that has been previously computed. */ public void setNextHop(Hop hop) { this.nextHop = hop; } /** * Reeturn the previously computed next hop (avoid computing it twice). * * @return -- next hop previously computed. */ public Hop getNextHop() { return nextHop; } /** * Set this flag if you want your Listener to get Timeout.RETRANSMIT notifications each time a * retransmission occurs. * * @param notifyOnRetransmit the notifyOnRetransmit to set */ public void setNotifyOnRetransmit(boolean notifyOnRetransmit) { this.notifyOnRetransmit = notifyOnRetransmit; } /** * @return the notifyOnRetransmit */ public boolean isNotifyOnRetransmit() { return notifyOnRetransmit; } public void alertIfStillInCallingStateBy(int count) { this.timeoutIfStillInCallingState = true; this.callingStateTimeoutCount = count; } } java/gov/nist/javax/sip/stack/SIPDialog.java0100644 0000000 0000000 00000374115 13513104763 017743 0ustar000000000 0000000 /* * 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 Advanced Networking Technologies Division */ /**************************************************************************/ package gov.nist.javax.sip.stack; import gov.nist.core.InternalErrorHandler; import gov.nist.core.NameValueList; import gov.nist.javax.sip.DialogExt; import gov.nist.javax.sip.ListeningPointImpl; import gov.nist.javax.sip.SipListenerExt; import gov.nist.javax.sip.SipProviderImpl; import gov.nist.javax.sip.Utils; import gov.nist.javax.sip.address.AddressImpl; import gov.nist.javax.sip.address.SipUri; import gov.nist.javax.sip.header.Authorization; import gov.nist.javax.sip.header.CSeq; import gov.nist.javax.sip.header.Contact; import gov.nist.javax.sip.header.ContactList; import gov.nist.javax.sip.header.From; import gov.nist.javax.sip.header.MaxForwards; import gov.nist.javax.sip.header.RAck; import gov.nist.javax.sip.header.RSeq; import gov.nist.javax.sip.header.Reason; 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.Route; import gov.nist.javax.sip.header.RouteList; import gov.nist.javax.sip.header.SIPHeader; 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.message.MessageFactoryImpl; import gov.nist.javax.sip.message.SIPMessage; import gov.nist.javax.sip.message.SIPRequest; import gov.nist.javax.sip.message.SIPResponse; import java.io.IOException; import java.io.PrintWriter; import java.io.Serializable; import java.io.StringWriter; import java.net.InetAddress; import java.text.ParseException; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import javax.sip.ClientTransaction; import javax.sip.DialogDoesNotExistException; import javax.sip.DialogState; import javax.sip.IOExceptionEvent; import javax.sip.InvalidArgumentException; import javax.sip.ListeningPoint; import javax.sip.ObjectInUseException; import javax.sip.SipException; import javax.sip.Transaction; import javax.sip.TransactionDoesNotExistException; import javax.sip.TransactionState; import javax.sip.address.Address; import javax.sip.address.Hop; import javax.sip.address.SipURI; import javax.sip.header.CallIdHeader; import javax.sip.header.ContactHeader; import javax.sip.header.EventHeader; import javax.sip.header.OptionTag; 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.SupportedHeader; import javax.sip.header.TimeStampHeader; import javax.sip.message.Request; import javax.sip.message.Response; /* * Acknowledgements: * * Bugs in this class were reported by Antonis Karydas, Brad Templeton, Jeff Adams, Alex Rootham , * 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. * */ /** * 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.159 $ $Date: 2010/01/08 15:14:12 $ * * @author M. Ranganathan * * */ public class SIPDialog implements javax.sip.Dialog, DialogExt { private static final long serialVersionUID = -1429794423085204069L; private transient boolean dialogTerminatedEventDelivered; // prevent duplicate private transient String stackTrace; // for semaphore debugging. private String method; // delivery of the event private transient boolean isAssigned; private boolean reInviteFlag; private transient Object applicationData; // Opaque pointer to application data. private transient SIPRequest originalRequest; // Last response (JvB: either sent or received). private 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 private transient SIPTransaction firstTransaction; private transient SIPTransaction lastTransaction; private String dialogId; private transient String earlyDialogId; private long localSequenceNumber; private long remoteSequenceNumber; protected String myTag; protected String hisTag; private RouteList routeList; private transient SIPTransactionStack sipStack; private int dialogState; protected transient boolean ackSeen; private transient SIPRequest lastAckSent; private SIPRequest lastAckReceived; // 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; private transient int retransmissionTicksLeft; private transient int prevRetransmissionTicks; private long originalLocalSequenceNumber; // This is for debugging only. private transient int ackLine; // Audit tag used by the SIP Stack audit public transient long auditTag = 0; // The following fields are extracted from the request that created the // Dialog. protected javax.sip.address.Address localParty; protected javax.sip.address.Address remoteParty; protected CallIdHeader callIdHeader; public final static int NULL_STATE = -1; public final static int EARLY_STATE = DialogState._EARLY; public final static int CONFIRMED_STATE = DialogState._CONFIRMED; public final static int TERMINATED_STATE = DialogState._TERMINATED; // the amount of time to keep this dialog around before the stack GC's it private static final int DIALOG_LINGER_TIME = 8; private boolean serverTransactionFlag; private transient SipProviderImpl sipProvider; private boolean terminateOnBye; private transient boolean byeSent; // Flag set when BYE is sent, to disallow new // requests private Address remoteTarget; private EventHeader eventHeader; // for Subscribe notify // Stores the last OK for the INVITE // Used in createAck. private transient long lastInviteOkReceived; private transient Semaphore ackSem = new Semaphore(1); private transient int reInviteWaitTime = 100; private transient DialogDeleteTask dialogDeleteTask; private transient DialogDeleteIfNoAckSentTask dialogDeleteIfNoAckSentTask; private transient boolean isAcknowledged; private transient long highestSequenceNumberAcknowledged = -1; private boolean isBackToBackUserAgent; private 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; protected String firstTransactionMethod; protected String firstTransactionId; protected boolean firstTransactionIsServerTransaction; protected int firstTransactionPort = 5060; protected Contact contactHeader; // ////////////////////////////////////////////////////// // Inner classes // ////////////////////////////////////////////////////// /** * 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; ClientTransaction ctx; public void terminate() { try { ctx.terminate(); Thread.currentThread().interrupt(); } catch (ObjectInUseException e) { sipStack.getStackLogger().logError("unexpected error", e); } } public ReInviteSender(ClientTransaction ctx) { this.ctx = ctx; } public void run() { try { long timeToWait = 0; long startTime = System.currentTimeMillis(); if (!SIPDialog.this.takeAckSem()) { /* * Could not send re-INVITE fire a timeout on the INVITE. */ if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logError( "Could not send re-INVITE time out ClientTransaction"); ((SIPClientTransaction) ctx).fireTimeoutTimer(); /* * Send BYE to the Dialog. */ 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()); } 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); SIPDialog.this.sendRequest(byeCtx); return; } } if (getState() != DialogState.TERMINATED) { timeToWait = System.currentTimeMillis() - startTime; } /* * 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 (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("Interrupted sleep"); return; } if (SIPDialog.this.getState() != DialogState.TERMINATED) { SIPDialog.this.sendRequest(ctx, true); } if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("re-INVITE successfully sent"); } catch (Exception ex) { sipStack.getStackLogger().logError("Error sending re-INVITE", ex); } finally { this.ctx = null; } } } class LingerTimer extends SIPStackTimerTask implements Serializable { public LingerTimer() { } protected void runTask() { SIPDialog dialog = SIPDialog.this; if(eventListeners != null) { eventListeners.clear(); } timerTaskLock = null; sipStack.removeDialog(dialog); } } class DialogTimerTask extends SIPStackTimerTask implements Serializable { int nRetransmissions; SIPServerTransaction transaction; public DialogTimerTask(SIPServerTransaction transaction) { this.transaction = transaction; this.nRetransmissions = 0; } protected void runTask() { // If I ACK has not been seen on Dialog, // resend last response. SIPDialog dialog = SIPDialog.this; if (sipStack.isLoggingEnabled()) 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 64*T1 * seconds without receiving an ACK, the dialog is confirmed, but the session SHOULD * be terminated. */ if (nRetransmissions > 64 * SIPTransaction.T1) { if (sipProvider.getSipListener() != null && sipProvider.getSipListener() instanceof SipListenerExt ) { raiseErrorEvent(SIPDialogErrorEvent.DIALOG_ACK_NOT_RECEIVED_TIMEOUT); } else { dialog.delete(); } if (transaction != null && transaction.getState() != javax.sip.TransactionState.TERMINATED) { transaction.raiseErrorEvent(SIPTransactionErrorEvent.TIMEOUT_ERROR); } } else if ((!dialog.ackSeen) && (transaction != null)) { // 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.sendMessage(response); } catch (IOException ex) { raiseIOException(transaction.getPeerAddress(), transaction.getPeerPort(), transaction.getPeerProtocol()); } finally { // Need to fire the timer so // transaction will eventually // time out whether or not // the IOException occurs // Note that this firing also // drives Listener timeout. SIPTransactionStack stack = dialog.sipStack; if (stack.isLoggingEnabled()) { stack.getStackLogger().logDebug("resend 200 response from " + dialog); } transaction.fireTimer(); } } } // Stop running this timer if the dialog is in the // confirmed state or ack seen if retransmit filter on. if (dialog.isAckSeen() || dialog.dialogState == TERMINATED_STATE) { this.transaction = null; this.cancel(); } } } /** * This timer task is used to garbage collect the dialog after some time. * */ class DialogDeleteTask extends SIPStackTimerTask implements Serializable { protected void runTask() { delete(); } } /** * This timer task is used to garbage collect the dialog after some time. * */ class DialogDeleteIfNoAckSentTask extends SIPStackTimerTask implements Serializable { private long seqno; public DialogDeleteIfNoAckSentTask(long seqno) { this.seqno = 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? */ dialogDeleteIfNoAckSentTask = null; if ( !SIPDialog.this.isBackToBackUserAgent) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logError("ACK Was not sent. killing dialog"); if ( ((SipProviderImpl)sipProvider).getSipListener() instanceof SipListenerExt ){ raiseErrorEvent(SIPDialogErrorEvent.DIALOG_ACK_NOT_SENT_TIMEOUT); } else { delete(); } } else { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logError("ACK Was not sent. Sending BYE"); 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. */ try { 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"); byeRequest.addHeader(reasonHeader); ClientTransaction byeCtx = SIPDialog.this.getSipProvider().getNewClientTransaction(byeRequest); SIPDialog.this.sendRequest(byeCtx); return; } catch (Exception ex) { SIPDialog.this.delete(); } } } } } } // /////////////////////////////////////////////////////////// // Constructors. // /////////////////////////////////////////////////////////// /** * Protected Dialog constructor. */ private SIPDialog(SipProviderImpl provider) { this.terminateOnBye = true; this.routeList = new RouteList(); this.dialogState = NULL_STATE; // not yet initialized. localSequenceNumber = 0; remoteSequenceNumber = -1; this.sipProvider = provider; eventListeners = new CopyOnWriteArraySet(); } private void recordStackTrace() { 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. */ public SIPDialog(SIPTransaction transaction) { this(transaction.getSipProvider()); SIPRequest sipRequest = (SIPRequest) transaction.getRequest(); this.callIdHeader = sipRequest.getCallId(); this.earlyDialogId = sipRequest.getDialogId(false); if (transaction == null) throw new NullPointerException("Null tx"); this.sipStack = transaction.sipStack; // this.defaultRouter = new DefaultRouter((SipStack) sipStack, // sipStack.outboundProxy); this.sipProvider = (SipProviderImpl) transaction.getSipProvider(); if (sipProvider == null) throw new NullPointerException("Null Provider!"); this.addTransaction(transaction); if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug("Creating a dialog : " + this); sipStack.getStackLogger().logDebug( "provider port = " + this.sipProvider.getListeningPoint().getPort()); sipStack.getStackLogger().logStackTrace(); } this.isBackToBackUserAgent = sipStack.isBackToBackUserAgent; addEventListener(sipStack); } /** * Constructor given a transaction and a response. * * @param transaction -- the transaction ( client/server) * @param sipResponse -- response with the appropriate tags. */ public SIPDialog(SIPClientTransaction transaction, SIPResponse sipResponse) { this(transaction); if (sipResponse == null) throw new NullPointerException("Null SipResponse"); this.setLastResponse(transaction, sipResponse); this.isBackToBackUserAgent = sipStack.isBackToBackUserAgent; } /** * create a sip dialog with a response ( no tx) */ public SIPDialog(SipProviderImpl sipProvider, SIPResponse sipResponse) { this(sipProvider); this.sipStack = (SIPTransactionStack) sipProvider.getSipStack(); this.setLastResponse(null, sipResponse); this.localSequenceNumber = sipResponse.getCSeq().getSeqNumber(); this.originalLocalSequenceNumber = localSequenceNumber; this.myTag = sipResponse.getFrom().getTag(); this.hisTag = sipResponse.getTo().getTag(); this.localParty = sipResponse.getFrom().getAddress(); this.remoteParty = sipResponse.getTo().getAddress(); this.method = sipResponse.getCSeq().getMethod(); this.callIdHeader = sipResponse.getCallId(); this.serverTransactionFlag = false; if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug("Creating a dialog : " + this); sipStack.getStackLogger().logStackTrace(); } this.isBackToBackUserAgent = sipStack.isBackToBackUserAgent; addEventListener(sipStack); } // /////////////////////////////////////////////////////////// // Private methods // /////////////////////////////////////////////////////////// /** * A debugging print routine. */ private void printRouteList() { if (sipStack.isLoggingEnabled()) { 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) */ 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); sipProvider.handleEvent(ioError, null); setState(SIPDialog.TERMINATED_STATE); } /** * Raise a dialog timeout if an ACK has not been sent or received * * @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.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. */ private void setRemoteParty(SIPMessage sipMessage) { if (!isServer()) { this.remoteParty = sipMessage.getTo().getAddress(); } else { this.remoteParty = sipMessage.getFrom().getAddress(); } if (sipStack.isLoggingEnabled()) { 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. * * @param recordRouteList -- the record route list from the incoming message. */ private void addRoute(RecordRouteList recordRouteList) { try { 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()); boolean addRoute = true; while (li.hasPrevious()) { RecordRoute rr = (RecordRoute) li.previous(); if (addRoute) { Route route = new Route(); AddressImpl address = ((AddressImpl) ((AddressImpl) rr.getAddress()) .clone()); route.setAddress(address); route.setParameters((NameValueList) rr.getParameters().clone()); this.routeList.add(route); } } } else { // This is a server dialog. The top most record route // header is the one that is closest to us. We extract the // route list in the same order as the addresses in the // incoming request. this.routeList = new RouteList(); ListIterator li = recordRouteList.listIterator(); boolean addRoute = true; while (li.hasNext()) { RecordRoute rr = (RecordRoute) li.next(); if (addRoute) { Route route = new Route(); AddressImpl address = ((AddressImpl) ((AddressImpl) rr.getAddress()) .clone()); route.setAddress(address); route.setParameters((NameValueList) rr.getParameters().clone()); routeList.add(route); } } } } finally { if (sipStack.getStackLogger().isLoggingEnabled()) { Iterator it = routeList.iterator(); while (it.hasNext()) { 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(); } } } } } } /** * Add a route list extacted from the contact list of the incoming message. * * @param contactList -- contact list extracted from the incoming message. * */ void setRemoteTarget(ContactHeader contact) { this.remoteTarget = contact.getAddress(); if (sipStack.isLoggingEnabled()) { 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. * * @param sipMessage is the SIP message for which we want to add the route. */ private synchronized void addRoute(SIPResponse sipResponse) { try { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "setContact: dialogState: " + this + "state = " + this.getState()); } if (sipResponse.getStatusCode() == 100) { // Do nothing for trying messages. return; } else if (this.dialogState == TERMINATED_STATE) { // Do nothing if the dialog state is terminated. return; } else if (this.dialogState == CONFIRMED_STATE) { // cannot add route list after the dialog is initialized. // Remote target is updated on RE-INVITE but not // the route list. if (sipResponse.getStatusCode() / 100 == 2 && !this.isServer()) { ContactList contactList = sipResponse.getContactHeaders(); if (contactList != null && SIPRequest.isTargetRefresh(sipResponse.getCSeq().getMethod())) { this.setRemoteTarget((ContactHeader) contactList.getFirst()); } } return; } // Update route list on response if I am a client dialog. if (!isServer()) { // only update the route set if the dialog is not in the confirmed state. if (this.getState() != DialogState.CONFIRMED && this.getState() != DialogState.TERMINATED) { RecordRouteList rrlist = sipResponse.getRecordRouteHeaders(); // Add the route set from the incoming response in reverse // order for record route headers. if (rrlist != null) { this.addRoute(rrlist); } else { // Set the rotue list to the last seen route list. this.routeList = new RouteList(); } } ContactList contactList = sipResponse.getContactHeaders(); if (contactList != null) { this.setRemoteTarget((ContactHeader) contactList.getFirst()); } } } finally { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logStackTrace(); } } } /** * Get a cloned copy of route list for the Dialog. * * @return -- a cloned copy of the dialog route list. */ private synchronized RouteList getRouteList() { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("getRouteList " + this); // Find the top via in the route list. ListIterator li; RouteList retval = new RouteList(); retval = new RouteList(); if (this.routeList != null) { li = routeList.listIterator(); while (li.hasNext()) { Route route = (Route) li.next(); retval.add((Route) route.clone()); } } if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug("----- "); sipStack.getStackLogger().logDebug("getRouteList for " + this); if (retval != null) sipStack.getStackLogger().logDebug("RouteList = " + retval.encode()); if (routeList != null) sipStack.getStackLogger().logDebug("myRouteList = " + routeList.encode()); sipStack.getStackLogger().logDebug("----- "); } return retval; } void setRouteList(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 * */ private void sendAck(Request request, boolean throwIOExceptionAsSipException) throws SipException { SIPRequest ackRequest = (SIPRequest) request; if (sipStack.isLoggingEnabled()) 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 (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 (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 (sipStack.isLoggingEnabled()) { 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()); if (this.getRemoteTag() != null) ackRequest.getTo().setTag(this.getRemoteTag()); } catch (ParseException ex) { throw new SipException(ex.getMessage()); } Hop hop = sipStack.getNextHop(ackRequest); // Hop hop = defaultRouter.getNextHop(ackRequest); if (hop == null) throw new SipException("No route!"); try { if (sipStack.isLoggingEnabled()) 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); InetAddress inetAddress = InetAddress.getByName(hop.getHost()); MessageChannel messageChannel = lp.getMessageProcessor().createMessageChannel( inetAddress, hop.getPort()); boolean releaseAckSem = false; long cseqNo = ((SIPRequest)request).getCSeq().getSeqNumber(); if (!this.isAckSent(cseqNo)) { releaseAckSem = true; } this.setLastAckSent(ackRequest); messageChannel.sendMessage(ackRequest); // Sent atleast one ACK. this.isAcknowledged = true; this.highestSequenceNumberAcknowledged = Math.max(this.highestSequenceNumberAcknowledged, ((SIPRequest)ackRequest).getCSeq().getSeqNumber()); if (releaseAckSem && this.isBackToBackUserAgent) { this.releaseAckSem(); } else { if ( sipStack.isLoggingEnabled() ) { 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()); } catch (SipException ex) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logException(ex); throw ex; } catch (Exception ex) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logException(ex); throw new SipException("Could not create message channel", ex); } if (this.dialogDeleteTask != null) { this.dialogDeleteTask.cancel(); this.dialogDeleteTask = null; } this.ackSeen = true; } // ///////////////////////////////////////////////////////////// // Package local methods // ///////////////////////////////////////////////////////////// /** * Set the stack address. Prevent us from routing messages to ourselves. * * @param sipStack the address of the SIP stack. * */ void setStack(SIPTransactionStack sipStack) { this.sipStack = sipStack; } /** * Get the stack . * * @return sipStack the SIP stack of the dialog. * */ SIPTransactionStack getStack() { return sipStack; } /** * Return True if this dialog is terminated on BYE. * */ boolean isTerminatedOnBye() { return this.terminateOnBye; } /** * Mark that the dialog has seen an ACK. */ void ackReceived(SIPRequest sipRequest) { // Suppress retransmission of the final response if (this.ackSeen) return; SIPServerTransaction tr = this.getInviteTransaction(); if (tr != null) { if (tr.getCSeq() == sipRequest.getCSeq().getSeqNumber()) { acquireTimerTaskSem(); try { if (this.timerTask != null) { this.timerTask.cancel(); this.timerTask = null; } } finally { releaseTimerTaskSem(); } this.ackSeen = true; if (this.dialogDeleteTask != null) { this.dialogDeleteTask.cancel(); this.dialogDeleteTask = null; } this.setLastAckReceived(sipRequest); if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "ackReceived for " + ((SIPTransaction) tr).getMethod()); this.ackLine = sipStack.getStackLogger().getLineCount(); this.printDebugInfo(); } if (this.isBackToBackUserAgent) { this.releaseAckSem(); } this.setState(CONFIRMED_STATE); } } } /** * Return true if a terminated event was delivered to the application as a result of the * dialog termination. * */ synchronized boolean testAndSetIsDialogTerminatedEventDelivered() { boolean retval = this.dialogTerminatedEventDelivered; this.dialogTerminatedEventDelivered = true; return retval; } // ///////////////////////////////////////////////////////// // Public methods // ///////////////////////////////////////////////////////// /** * 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() */ public void setApplicationData(Object applicationData) { this.applicationData = applicationData; } /* * (non-Javadoc) * * @see javax.sip.Dialog#getApplicationData() */ public Object getApplicationData() { return this.applicationData; } /** * Updates the next consumable seqno. * */ public synchronized void requestConsumed() { this.nextSeqno = Long.valueOf(this.getRemoteSeqNumber() + 1); if (sipStack.isLoggingEnabled()) { this.sipStack.getStackLogger().logDebug( "Request Consumed -- next consumable Request Seqno = " + this.nextSeqno); } } /** * 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. */ public synchronized boolean isRequestConsumable(SIPRequest dialogRequest) { // have not yet set remote seqno - this is a fresh if (dialogRequest.getMethod().equals(Request.ACK)) throw new RuntimeException("Illegal method"); // For loose validation this function is delegated to the application if (!this.isSequnceNumberValidation()) { return true; } // JvB: Acceptable iff remoteCSeq < cseq. remoteCSeq==-1 // when not defined yet, so that works too return remoteSequenceNumber < dialogRequest.getCSeq().getSeqNumber(); } /** * 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() { if (sipStack.getTimer() == null) this.setState(TERMINATED_STATE); else { this.dialogDeleteTask = new DialogDeleteTask(); // Delete the transaction after the max ack timeout. sipStack.getTimer().schedule(this.dialogDeleteTask, SIPTransaction.TIMER_H * SIPTransactionStack.BASE_TIMER_INTERVAL); } } /** * Set the state for this dialog. * * @param state is the state to set for the dialog. */ public void setState(int state) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "Setting dialog state for " + this + "newState = " + state); sipStack.getStackLogger().logStackTrace(); if (state != NULL_STATE && state != this.dialogState) if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( this + " old dialog state is " + this.getState()); sipStack.getStackLogger().logDebug( this + " New dialog state is " + DialogState.getObject(state)); } } this.dialogState = state; // Dialog is in terminated state set it up for GC. if (state == TERMINATED_STATE) { if (sipStack.getTimer() != null) { // may be null after shutdown sipStack.getTimer().schedule(new LingerTimer(), DIALOG_LINGER_TIME * 1000); } this.stopTimer(); } } /** * Debugging print for the dialog. */ public void printDebugInfo() { if (sipStack.isLoggingEnabled()) { 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); } } /** * Return true if the dialog has already seen the ack. * * @return flag that records if the ack has been seen. */ public boolean isAckSeen() { return this.ackSeen; } /** * Get the last ACK for this transaction. */ public SIPRequest getLastAckSent() { return this.lastAckSent; } /** * 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) return true; if (this.getLastTransaction() instanceof ClientTransaction) { if (this.getLastAckSent() == null) { return false; } else { return cseqNo <=((SIPRequest) this.getLastAckSent()).getCSeq().getSeqNumber(); } } else { return true; } } /** * Get the transaction that created this dialog. */ 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. *

    * 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. * * @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) { return new LinkedList().listIterator(); } else { return this.getRouteList().listIterator(); } } /** * Add a Route list extracted from a SIPRequest to this Dialog. * * @param sipRequest */ public synchronized void addRoute(SIPRequest sipRequest) { if (sipStack.isLoggingEnabled()) { 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) { return; } // Fix for issue #225: mustn't learn Route set from mid-dialog requests 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 // order if (rrlist != null) { this.addRoute(rrlist); } else { // Set the rotue list to the last seen route list. this.routeList = new RouteList(); } // put the contact header from the incoming request into // the route set. JvB: some duplication here, ref. doTargetRefresh ContactList contactList = sipRequest.getContactHeaders(); if (contactList != null) { this.setRemoteTarget((ContactHeader) contactList.getFirst()); } } /** * Set the dialog identifier. */ public void setDialogId(String 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 * * 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. * * */ public static SIPDialog createFromNOTIFY(SIPClientTransaction subscribeTx, SIPTransaction notifyST) { SIPDialog d = new SIPDialog(notifyST); // // The above sets d.firstTransaction to NOTIFY (ST), correct that // d.serverTransactionFlag = false; // they share this one d.lastTransaction = subscribeTx; storeFirstTransactionInfo(d, subscribeTx); d.terminateOnBye = false; d.localSequenceNumber = subscribeTx.getCSeq(); SIPRequest not = (SIPRequest) notifyST.getRequest(); d.remoteSequenceNumber = not.getCSeq().getSeqNumber(); d.setDialogId(not.getDialogId(true)); d.setLocalTag(not.getToTag()); d.setRemoteTag(not.getFromTag()); // to properly create the Dialog object. // If not the stack will throw an exception when creating the response. d.setLastResponse(subscribeTx, subscribeTx.getLastResponse()); // Dont use setLocal / setRemote here, they make other assumptions d.localParty = not.getTo().getAddress(); d.remoteParty = not.getFrom().getAddress(); // initialize d's route set based on the NOTIFY. Any proxies must have // Record-Routed d.addRoute(not); d.setState(CONFIRMED_STATE); // set state, *after* setting route set! return d; } /** * Return true if is server. * * @return true if is server transaction created this dialog. */ public boolean isServer() { if (this.firstTransactionSeen == false) return this.serverTransactionFlag; else return this.firstTransactionIsServerTransaction; } /** * Return true if this is a re-establishment of the dialog. * * @return true if the reInvite flag is set. */ protected boolean isReInvite() { return this.reInviteFlag; } /** * Get the id for this dialog. * * @return the string identifier for this dialog. * */ public String getDialogId() { if (this.dialogId == null && this.lastResponse != null) this.dialogId = this.lastResponse.getDialogId(isServer()); return this.dialogId; } private static 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 (dialog.isServer()) { SIPServerTransaction st = (SIPServerTransaction) transaction; SIPResponse response = st.getLastResponse(); dialog.contactHeader = response != null ? response.getContactHeader() : null; } else { SIPClientTransaction ct = (SIPClientTransaction) transaction; if (ct != null){ SIPRequest sipRequest = ct.getOriginalRequest(); dialog.contactHeader = sipRequest.getContactHeader(); } } } /** * Add a transaction record to the dialog. * * @param transaction is the transaction to add to the dialog. */ public void addTransaction(SIPTransaction transaction) { SIPRequest sipRequest = (SIPRequest) transaction.getOriginalRequest(); // Proessing a re-invite. if (firstTransactionSeen && !firstTransactionId.equals(transaction.getBranchId()) && transaction.getMethod().equals(firstTransactionMethod)) { this.reInviteFlag = true; } 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); if (sipRequest.getMethod().equals(Request.SUBSCRIBE)) this.eventHeader = (EventHeader) sipRequest.getHeader(EventHeader.NAME); this.setLocalParty(sipRequest); this.setRemoteParty(sipRequest); this.setCallId(sipRequest); if (this.originalRequest == null) { this.originalRequest = sipRequest; } if (this.method == null) { this.method = sipRequest.getMethod(); } if (transaction instanceof SIPServerTransaction) { this.hisTag = sipRequest.getFrom().getTag(); // My tag is assigned when sending response } else { setLocalSequenceNumber(sipRequest.getCSeq().getSeqNumber()); this.originalLocalSequenceNumber = localSequenceNumber; this.myTag = sipRequest.getFrom().getTag(); if (myTag == null) 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()) { // 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); this.setLocalParty(sipRequest); this.setRemoteParty(sipRequest); this.setCallId(sipRequest); this.originalRequest = sipRequest; this.method = sipRequest.getMethod(); } if (transaction instanceof SIPServerTransaction) setRemoteSequenceNumber(sipRequest.getCSeq().getSeqNumber()); // If this is a server transaction record the remote // sequence number to avoid re-processing of requests // with the same sequence number directed towards this // dialog. this.lastTransaction = transaction; // set a back ptr in the incoming dialog. // CHECKME -- why is this here? // transaction.setDialog(this,sipRequest); if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger() .logDebug("Transaction Added " + this + myTag + "/" + hisTag); sipStack.getStackLogger().logDebug( "TID = " + transaction.getTransactionId() + "/" + transaction.isServerTransaction()); sipStack.getStackLogger().logStackTrace(); } } /** * Set the remote tag. * * @param hisTag is the remote tag to set. */ private void setRemoteTag(String hisTag) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "setRemoteTag(): " + this + " remoteTag = " + this.hisTag + " new tag = " + hisTag); } if (this.hisTag != null && hisTag != null && !hisTag.equals(this.hisTag)) { if (this.getState() != DialogState.EARLY) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug( "Dialog is already established -- ignoring remote tag re-assignment"); return; } else if (sipStack.isRemoteTagReassignmentAllowed()) { if (sipStack.isLoggingEnabled()) 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); removed = true; } // Force recomputation of Dialog ID; this.dialogId = null; this.hisTag = hisTag; if (removed) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("ReInserting Dialog"); this.sipStack.putDialog(this); } } } else { if (hisTag != null) { this.hisTag = hisTag; } else { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logWarning("setRemoteTag : called with null argument "); } } } /** * Get the last transaction from the dialog. */ public SIPTransaction getLastTransaction() { return this.lastTransaction; } /** * Get the INVITE transaction (null if no invite transaction). */ public SIPServerTransaction getInviteTransaction() { DialogTimerTask t = this.timerTask; if (t != null) return t.transaction; else return null; } /** * Set the local sequece number for the dialog (defaults to 1 when the dialog is created). * * @param lCseq is the local cseq number. * */ private void setLocalSequenceNumber(long lCseq) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug( "setLocalSequenceNumber: original " + this.localSequenceNumber + " new = " + lCseq); if (lCseq <= this.localSequenceNumber) throw new RuntimeException("Sequence number should not decrease !"); this.localSequenceNumber = lCseq; } /** * Set the remote sequence number for the dialog. * * @param rCseq is the remote cseq number. * */ public void setRemoteSequenceNumber(long rCseq) { if (sipStack.isLoggingEnabled()) 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. */ public void incrementLocalSequenceNumber() { ++this.localSequenceNumber; } /** * Get the remote sequence number (for cseq assignment of outgoing requests within this * dialog). * * @deprecated * @return local sequence number. */ public int getRemoteSequenceNumber() { return (int) this.remoteSequenceNumber; } /** * Get the local sequence number (for cseq assignment of outgoing requests within this * dialog). * * @deprecated * @return local sequence number. */ public int getLocalSequenceNumber() { return (int) this.localSequenceNumber; } /** * Get the sequence number for the request that origianlly created the Dialog. * * @return -- the original starting sequence number for this dialog. */ public long getOriginalLocalSequenceNumber() { return this.originalLocalSequenceNumber; } /* * (non-Javadoc) * * @see javax.sip.Dialog#getLocalSequenceNumberLong() */ public long getLocalSeqNumber() { return this.localSequenceNumber; } /* * (non-Javadoc) * * @see javax.sip.Dialog#getRemoteSequenceNumberLong() */ public long getRemoteSeqNumber() { return this.remoteSequenceNumber; } /* * (non-Javadoc) * * @see javax.sip.Dialog#getLocalTag() */ public String getLocalTag() { return this.myTag; } /* * (non-Javadoc) * * @see javax.sip.Dialog#getRemoteTag() */ public String getRemoteTag() { return hisTag; } /** * 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. */ private void setLocalTag(String mytag) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug("set Local tag " + mytag + " " + this.dialogId); sipStack.getStackLogger().logStackTrace(); } this.myTag = mytag; } /* * (non-Javadoc) * * @see javax.sip.Dialog#delete() */ public void delete() { // the reaper will get him later. this.setState(TERMINATED_STATE); } /* * (non-Javadoc) * * @see javax.sip.Dialog#getCallId() */ public CallIdHeader getCallId() { return this.callIdHeader; } /** * set the call id header for this dialog. */ private void setCallId(SIPRequest sipRequest) { this.callIdHeader = sipRequest.getCallId(); } /* * (non-Javadoc) * * @see javax.sip.Dialog#getLocalParty() */ public javax.sip.address.Address getLocalParty() { return this.localParty; } private void setLocalParty(SIPMessage sipMessage) { if (!isServer()) { this.localParty = sipMessage.getFrom().getAddress(); } else { this.localParty = sipMessage.getTo().getAddress(); } } /** * 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. * * @return the address object of the remote party. */ public javax.sip.address.Address getRemoteParty() { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug("gettingRemoteParty " + this.remoteParty); } return this.remoteParty; } /* * (non-Javadoc) * * @see javax.sip.Dialog#getRemoteTarget() */ public javax.sip.address.Address getRemoteTarget() { return this.remoteTarget; } /* * (non-Javadoc) * * @see javax.sip.Dialog#getState() */ public DialogState getState() { if (this.dialogState == NULL_STATE) return null; // not yet initialized return DialogState.getObject(this.dialogState); } /** * 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. */ public boolean isSecure() { return this.firstTransactionSecure; } /* * (non-Javadoc) * * @see javax.sip.Dialog#sendAck(javax.sip.message.Request) */ public void sendAck(Request request) throws SipException { this.sendAck(request, true); } /* * (non-Javadoc) * * @see javax.sip.Dialog#createRequest(java.lang.String) */ 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); } if (lastResponse != null) return this.createRequest(method, this.lastResponse); else throw new SipException("Dialog not yet established -- no response!"); } /** * The method that actually does the work of creating a request. * * @param method * @param response * @return * @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. * * Throw out cancel request. */ if (method == null || sipResponse == null) throw new NullPointerException("null argument"); if (method.equals(Request.CANCEL)) throw new SipException("Dialog.createRequest(): Invalid request"); if (this.getState() == null || (this.getState().getValue() == TERMINATED_STATE && !method .equalsIgnoreCase(Request.BYE)) || (this.isServer() && this.getState().getValue() == EARLY_STATE && method .equalsIgnoreCase(Request.BYE))) throw new SipException("Dialog " + getDialogId() + " not yet established or terminated " + this.getState()); SipUri sipUri = null; if (this.getRemoteTarget() != null) sipUri = (SipUri) this.getRemoteTarget().getURI().clone(); else { sipUri = (SipUri) this.getRemoteParty().getURI().clone(); sipUri.clearUriParms(); } CSeq cseq = new CSeq(); try { cseq.setMethod(method); cseq.setSeqNumber(this.getLocalSeqNumber()); } catch (Exception ex) { 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. */ ListeningPointImpl lp = (ListeningPointImpl) this.sipProvider .getListeningPoint(sipResponse.getTopmostVia().getTransport()); if (lp == null) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logError( "Cannot find listening point for transport " + sipResponse.getTopmostVia().getTransport()); throw new SipException("Cannot find listening point for transport " + sipResponse.getTopmostVia().getTransport()); } Via via = lp.getViaHeader(); From from = new From(); from.setAddress(this.localParty); To to = new 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. * * 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(); ((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 */ cseq = (CSeq) sipRequest.getCSeq(); cseq.setSeqNumber(this.localSequenceNumber + 1); } catch (InvalidArgumentException ex) { InternalErrorHandler.handleException(ex); } if (method.equals(Request.SUBSCRIBE)) { if (eventHeader != null) sipRequest.addHeader(eventHeader); } /* * 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. */ try { if (this.getLocalTag() != null) { from.setTag(this.getLocalTag()); } else { from.removeTag(); } if (this.getRemoteTag() != null) { to.setTag(this.getRemoteTag()); } else { to.removeTag(); } } catch (ParseException ex) { InternalErrorHandler.handleException(ex); } // get the route list from the dialog. this.updateRequest(sipRequest); return sipRequest; } /* * (non-Javadoc) * * @see javax.sip.Dialog#sendRequest(javax.sip.ClientTransaction) */ public void sendRequest(ClientTransaction clientTransactionId) throws TransactionDoesNotExistException, SipException { this.sendRequest(clientTransactionId, !this.isBackToBackUserAgent); } public void sendRequest(ClientTransaction clientTransactionId, boolean allowInterleaving) throws TransactionDoesNotExistException, SipException { if ( (!allowInterleaving) && clientTransactionId.getRequest().getMethod().equals(Request.INVITE)) { new Thread((new ReInviteSender(clientTransactionId))).start(); return; } SIPRequest dialogRequest = ((SIPClientTransaction) clientTransactionId) .getOriginalRequest(); if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug( "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()); // JvB: added, allow re-sending of BYE after challenge 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(); dialogRequest.addHeader(via); } 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); this.addTransaction((SIPTransaction) clientTransactionId); // Enable the retransmission filter for the transaction ((SIPClientTransaction) clientTransactionId).isMapped = true; From from = (From) dialogRequest.getFrom(); To to = (To) dialogRequest.getTo(); // Caller already did the tag assignment -- check to see if the // 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()); if (this.getRemoteTag() != null && to.getTag() != null && !to.getTag().equals(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. */ 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!"); this.setLocalTag(from.getTag()); } try { if (this.getLocalTag() != null) from.setTag(this.getLocalTag()); if (this.getRemoteTag() != null) to.setTag(this.getRemoteTag()); } catch (ParseException ex) { InternalErrorHandler.handleException(ex); } Hop hop = ((SIPClientTransaction) clientTransactionId).getNextHop(); if (sipStack.isLoggingEnabled()) { 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(); // Remove this from the connection cache if it is in the // connection // cache and is not yet active. oldChannel.uncache(); // Not configured to cache client connections. if (!sipStack.cacheClientConnections) { oldChannel.useCount--; if (sipStack.isLoggingEnabled()) 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. * * 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 (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug( "Null message channel using outbound proxy !"); 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(), this.firstTransactionPort, outboundProxy); if (messageChannel != null) ((SIPClientTransaction) clientTransactionId) .setEncapsulatedChannel(messageChannel); } else { ((SIPClientTransaction) clientTransactionId) .setEncapsulatedChannel(messageChannel); if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug("using message channel " + messageChannel); } } 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(); } catch (Exception ex) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logException(ex); throw new SipException("Could not create message channel", ex); } try { // Increment before setting!! localSequenceNumber++; dialogRequest.getCSeq().setSeqNumber(getLocalSeqNumber()); } catch (InvalidArgumentException ex) { sipStack.getStackLogger().logFatalError(ex.getMessage()); } try { ((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. */ if (dialogRequest.getMethod().equals(Request.BYE)) { this.byeSent = true; /* * Dialog goes into TERMINATED state as soon as BYE is sent. ISSUE 182. */ if (isTerminatedOnBye()) { this.setState(DialogState._TERMINATED); } } } catch (IOException ex) { throw new SipException("error sending message", ex); } } /** * Return yes if the last response is to be retransmitted. */ private boolean toRetransmitFinalResponse(int T2) { if (--retransmissionTicksLeft == 0) { if (2 * prevRetransmissionTicks <= T2) this.retransmissionTicksLeft = 2 * prevRetransmissionTicks; else this.retransmissionTicksLeft = prevRetransmissionTicks; this.prevRetransmissionTicks = retransmissionTicksLeft; return true; } else return false; } protected void setRetransmissionTicks() { this.retransmissionTicksLeft = 1; this.prevRetransmissionTicks = 1; } /** * Resend the last ack. */ public void resendAck() throws SipException { // Check for null. if (this.getLastAckSent() != null) { if (getLastAckSent().getHeader(TimeStampHeader.NAME) != null && sipStack.generateTimeStampHeader) { TimeStamp ts = new TimeStamp(); try { ts.setTimeStamp(System.currentTimeMillis()); getLastAckSent().setHeader(ts); } catch (InvalidArgumentException e) { } } this.sendAck(getLastAckSent(), false); } } /** * Get the method of the request/response that resulted in the creation of the Dialog. * * @return -- the method of the dialog. */ public String getMethod() { // Method of the request or response used to create this dialog return this.method; } /** * Start the dialog timer. * * @param transaction */ protected void startTimer(SIPServerTransaction transaction) { if (this.timerTask != null && timerTask.transaction == transaction) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("Timer already running for " + getDialogId()); return; } if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("Starting dialog timer for " + getDialogId()); this.ackSeen = false; 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(); } /** * Stop the dialog timer. This is called when the dialog is terminated. * */ protected void stopTimer() { try { 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. * * @see javax.sip.Dialog#createPrack(javax.sip.message.Response) */ 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 ((RSeq) relResponse.getHeader(RSeqHeader.NAME) == null) { throw new SipException("Missing RSeq Header"); } try { SIPResponse sipResponse = (SIPResponse) relResponse; SIPRequest sipRequest = (SIPRequest) this.createRequest(Request.PRACK, (SIPResponse) relResponse); String toHeaderTag = sipResponse.getTo().getTag(); sipRequest.setToTag(toHeaderTag); RAck rack = new RAck(); RSeq rseq = (RSeq) relResponse.getHeader(RSeqHeader.NAME); rack.setMethod(sipResponse.getCSeq().getMethod()); rack.setCSequenceNumber((int) sipResponse.getCSeq().getSeqNumber()); rack.setRSequenceNumber(rseq.getSeqNumber()); sipRequest.setHeader(rack); return (Request) sipRequest; } catch (Exception ex) { InternalErrorHandler.handleException(ex); return null; } } private void updateRequest(SIPRequest sipRequest) { RouteList rl = this.getRouteList(); if (rl.size() > 0) { sipRequest.setHeader(rl); } else { sipRequest.removeHeader(RouteHeader.NAME); } if (MessageFactoryImpl.getDefaultUserAgentHeader() != null) { 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 * 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. * * @see javax.sip.Dialog#createAck(long) */ 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); 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)); if (this.remoteTarget == null) { throw new SipException("Cannot create ACK - no remote Target!"); } if (this.sipStack.isLoggingEnabled()) { 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 (sipStack.isLoggingEnabled()) { 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 { // JvB: Transport from first entry in route set, or remote Contact // if none // Only used to find correct LP & create correct Via SipURI uri4transport = null; if (this.routeList != null && !this.routeList.isEmpty()) { Route r = (Route) this.routeList.getFirst(); uri4transport = ((SipURI) r.getAddress().getURI()); } else { // should be !=null, checked above uri4transport = ((SipURI) this.remoteTarget.getURI()); } String transport = uri4transport.getTransportParam(); if (transport == null) { // JvB fix: also support TLS transport = uri4transport.isSecure() ? ListeningPoint.TLS : ListeningPoint.UDP; } ListeningPointImpl lp = (ListeningPointImpl) sipProvider.getListeningPoint(transport); if (lp == null) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logError( "remoteTargetURI " + this.remoteTarget.getURI()); sipStack.getStackLogger().logError("uri4transport = " + uri4transport); sipStack.getStackLogger().logError("No LP found for transport=" + transport); } throw new SipException( "Cannot create ACK - no ListeningPoint for transport towards next hop found:" + transport); } SIPRequest sipRequest = new SIPRequest(); sipRequest.setMethod(Request.ACK); 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 // original request 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()); } } via.setBranch(Utils.getInstance().generateBranchId()); // new branch vias.add(via); sipRequest.setVia(vias); From from = new From(); from.setAddress(this.localParty); from.setTag(this.myTag); sipRequest.setFrom(from); To to = new To(); 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(); if (authorization != null) sipRequest.setHeader(authorization); } // ACKs for 2xx responses // use the Route values learned from the Record-Route of the 2xx // responses. this.updateRequest(sipRequest); return sipRequest; } catch (Exception ex) { InternalErrorHandler.handleException(ex); throw new SipException("unexpected exception ", ex); } } /** * Get the provider for this Dialog. * * SPEC_REVISION * * @return -- the SIP Provider associated with this transaction. */ public SipProviderImpl getSipProvider() { return this.sipProvider; } /** * @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. * * @param sipResponse -- the response to check. * */ public void setResponseTags(SIPResponse sipResponse) { if (this.getLocalTag() != null || this.getRemoteTag() != null) { return; } String responseFromTag = sipResponse.getFromTag(); if ( responseFromTag != null ) { if (responseFromTag.equals(this.getLocalTag())) { sipResponse.setToTag(this.getRemoteTag()); } else if (responseFromTag.equals(this.getRemoteTag())) { sipResponse.setToTag(this.getLocalTag()); } } else { 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. * * @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(); int statusCode = sipResponse.getStatusCode(); if (statusCode == 100) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logWarning( "Invalid status code - 100 in setLastResponse - ignoring"); return; } this.lastResponse = sipResponse; this.setAssigned(); // Adjust state of the Dialog state machine. if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "sipDialog: setLastResponse:" + this + " lastResponse = " + this.lastResponse.getFirstLine()); } if (this.getState() == DialogState.TERMINATED) { if (sipStack.isLoggingEnabled()) { 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); } return; } String cseqMethod = sipResponse.getCSeq().getMethod(); if (sipStack.isLoggingEnabled()) { 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 (cseqMethod.equals(getMethod()) && (sipResponse.getToTag() != null || sipStack.rfc2543Supported) && this.getState() != DialogState.CONFIRMED) { setRemoteTag(sipResponse.getToTag()); this.setDialogId(sipResponse.getDialogId(false)); sipStack.putDialog(this); this.addRoute(sipResponse); setState(SIPDialog.CONFIRMED_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 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); } /* * 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())) { routeList.removeFirst(); } else break; } } } } } 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); } 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. 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; if (getLocalTag() == null && sipResponse.getTo().getTag() != null && sipStack.isDialogCreated(cseqMethod) && cseqMethod.equals(getMethod())) { setLocalTag(sipResponse.getTo().getTag()); 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 { /* * 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()) 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); } } } } 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. */ if (!this.takeAckSem()) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "Delete dialog -- cannot acquire ackSem"); } this.delete(); return; } } } } } } /** * Start the retransmit timer. * * @param sipServerTx -- server transaction on which the response was sent * @param response - response that was sent. */ public void startRetransmitTimer(SIPServerTransaction sipServerTx, Response response) { if (sipServerTx.getRequest().getMethod().equals(Request.INVITE) && response.getStatusCode() / 100 == 2) { this.startTimer(sipServerTx); } } /** * @return -- the last response associated with the dialog. */ 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 * 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. */ 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 */ if (contactList != null) { Contact contact = (Contact) contactList.getFirst(); this.setRemoteTarget(contact); } } private static final boolean optionPresent(ListIterator l, String option) { while (l.hasNext()) { OptionTag opt = (OptionTag) l.next(); if (opt != null && option.equalsIgnoreCase(opt.getOptionTag())) return true; } return false; } /* * (non-Javadoc) * * @see javax.sip.Dialog#createReliableProvisionalResponse(int) */ public Response createReliableProvisionalResponse(int statusCode) throws InvalidArgumentException, SipException { if (!(firstTransactionIsServerTransaction)) { throw new SipException("Not a Server Dialog!"); } /* * 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 "); SIPRequest request = this.originalRequest; if (!request.getMethod().equals(Request.INVITE)) throw new SipException("Bad method"); ListIterator list = request.getHeaders(SupportedHeader.NAME); 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"); } } 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 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 { require.setOptionTag("100rel"); } catch (Exception ex) { InternalErrorHandler.handleException(ex); } response.addHeader(require); RSeq rseq = new RSeq(); /* * 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. */ RecordRouteList rrl = request.getRecordRouteHeaders(); if (rrl != null) { RecordRouteList rrlclone = (RecordRouteList) rrl.clone(); response.setHeader(rrlclone); } return response; } /** * 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) */ 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. */ if (!this.isServer()) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("Dropping Prack -- not a server Dialog"); return false; } SIPServerTransaction sipServerTransaction = (SIPServerTransaction) this .getFirstTransaction(); SIPResponse sipResponse = sipServerTransaction.getReliableProvisionalResponse(); if (sipResponse == null) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger() .logDebug("Dropping Prack -- ReliableResponse not found"); return false; } RAck rack = (RAck) prackRequest.getHeader(RAckHeader.NAME); if (rack == null) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("Dropping Prack -- rack header not found"); return false; } CSeq cseq = (CSeq) sipResponse.getCSeq(); if (!rack.getMethod().equals(cseq.getMethod())) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug( "Dropping Prack -- CSeq Header does not match PRACK"); return false; } if (rack.getCSeqNumberLong() != cseq.getSeqNumber()) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug( "Dropping Prack -- CSeq Header does not match PRACK"); return false; } RSeq rseq = (RSeq) sipResponse.getHeader(RSeqHeader.NAME); if (rack.getRSequenceNumber() != rseq.getSeqNumber()) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug( "Dropping Prack -- RSeq Header does not match PRACK"); return false; } return sipServerTransaction.prackRecieved(); } /* * (non-Javadoc) * * @see javax.sip.Dialog#sendReliableProvisionalResponse(javax.sip.message.Response) */ public void sendReliableProvisionalResponse(Response relResponse) throws SipException { if (!this.isServer()) { throw new SipException("Not a Server Dialog"); } SIPResponse sipResponse = (SIPResponse) relResponse; if (relResponse.getStatusCode() == 100) throw new SipException("Cannot send 100 as a reliable provisional response"); if (relResponse.getStatusCode() / 100 > 2) throw new SipException( "Response code is not a 1xx response - should be in the range 101 to 199 "); /* * Do a little checking on the outgoing response. */ if (sipResponse.getToTag() == null) { throw new SipException( "Badly formatted response -- To tag mandatory for Reliable Provisional Response"); } ListIterator requireList = (ListIterator) relResponse.getHeaders(RequireHeader.NAME); boolean found = false; if (requireList != null) { while (requireList.hasNext() && !found) { RequireHeader rh = (RequireHeader) requireList.next(); if (rh.getOptionTag().equalsIgnoreCase("100rel")) { found = true; } } } if (!found) { Require require = new Require("100rel"); relResponse.addHeader(require); if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "Require header with optionTag 100rel is needed -- adding one"); } } SIPServerTransaction serverTransaction = (SIPServerTransaction) this .getFirstTransaction(); /* * put into the dialog table before sending the response so as to avoid race condition * with PRACK */ this.setLastResponse(serverTransaction, sipResponse); this.setDialogId(sipResponse.getDialogId(true)); serverTransaction.sendReliableProvisionalResponse(relResponse); this.startRetransmitTimer(serverTransaction, relResponse); } /* * (non-Javadoc) * * @see javax.sip.Dialog#terminateOnBye(boolean) */ public void terminateOnBye(boolean terminateFlag) throws SipException { this.terminateOnBye = terminateFlag; } /** * Set the "assigned" flag to true. We do this when inserting the dialog into the dialog table * of the stack. * */ public void setAssigned() { this.isAssigned = true; } /** * Return true if the dialog has already been mapped to a transaction. * */ public boolean isAssigned() { return this.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. * * @return contact header belonging to the dialog. */ public Contact getMyContactHeader() { 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. */ public boolean handleAck(SIPServerTransaction ackTransaction) { SIPRequest sipRequest = ackTransaction.getOriginalRequest(); if (isAckSeen() && getRemoteSeqNumber() == sipRequest.getCSeq().getSeqNumber()) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "ACK already seen by dialog -- dropping Ack" + " retransmission"); } acquireTimerTaskSem(); try { if (this.timerTask != null) { this.timerTask.cancel(); this.timerTask = null; } } finally { releaseTimerTaskSem(); } return false; } else if (this.getState() == DialogState.TERMINATED) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("Dialog is terminated -- dropping ACK"); return false; } else { /* * This could be a re-invite processing. check to see if the ack matches with the last * transaction. s */ SIPServerTransaction tr = getInviteTransaction(); 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(sipRequest); if (sipStack.isLoggingEnabled()) 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. */ if (sipStack.isLoggingEnabled()) 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. */ void releaseAckSem() { if (this.isBackToBackUserAgent) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug("releaseAckSem]" + this); } this.ackSem.release(); } } boolean takeAckSem() { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug("[takeAckSem " + this); } try { if (!this.ackSem.tryAcquire(2, TimeUnit.SECONDS)) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logError("Cannot aquire ACK semaphore"); } if ( sipStack.isLoggingEnabled() ) { sipStack.getStackLogger().logDebug("Semaphore previously acquired at " + this.stackTrace); sipStack.getStackLogger().logStackTrace(); } return false; } if ( sipStack.isLoggingEnabled() ) { this.recordStackTrace(); } } catch (InterruptedException ex) { sipStack.getStackLogger().logError("Cannot aquire ACK semaphore"); return false; } return true; } /** * @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; } /** * @return true if an ack was ever sent for this Dialog */ 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); sipStack.getTimer().schedule( dialogDeleteIfNoAckSentTask, SIPTransaction.TIMER_J * 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 */ 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; try { acquired = this.timerTaskLock.tryAcquire(10, TimeUnit.SECONDS); } catch ( InterruptedException ex) { acquired = false; } if(!acquired) { throw new IllegalStateException("Impossible to acquire the dialog timer task lock"); } } public void releaseTimerTaskSem() { this.timerTaskLock.release(); } } java/gov/nist/javax/sip/stack/SIPDialogErrorEvent.java0100644 0000000 0000000 00000003733 13513104763 021752 0ustar000000000 0000000 /* * This source code has been contributed to the public domain by Mobicents * * 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; import java.util.EventObject; /** * An event that indicates that a dialog has encountered an error. * * @author jean deruelle * @since 2.0 */ public class SIPDialogErrorEvent extends EventObject { /** * This event ID indicates that the transaction has timed out. */ public static final int DIALOG_ACK_NOT_RECEIVED_TIMEOUT = 1; /** * This event ID indicates that there was an error sending a message using * the underlying transport. */ public static final int DIALOG_ACK_NOT_SENT_TIMEOUT = 2; /** * This event ID indicates a timeout occured waiting to send re-INVITE ( for B2BUA) */ public static final int DIALOG_REINVITE_TIMEOUT = 3; // ID of this error event private int errorID; /** * Creates a dialog error event. * * @param sourceDialog Dialog which is raising the error. * @param dialogErrorID ID of the error that has ocurred. */ SIPDialogErrorEvent( SIPDialog sourceDialog, int dialogErrorID) { super(sourceDialog); errorID = dialogErrorID; } /** * Returns the ID of the error. * * @return Error ID. */ public int getErrorID() { return errorID; } } java/gov/nist/javax/sip/stack/SIPDialogEventListener.java0100644 0000000 0000000 00000002251 13513104763 022440 0ustar000000000 0000000 /* * This source code has been contributed to the public domain by Mobicents * * 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; import java.util.EventListener; /** * Interface implemented by classes that want to be notified of asynchronous * dialog events. * * @author jean deruelle * @since 2.0 */ public interface SIPDialogEventListener extends EventListener { /** * Invoked when an error has ocurred with a dialog. * * @param dialogErrorEvent Error event. */ public void dialogErrorEvent(SIPDialogErrorEvent dialogErrorEvent); } java/gov/nist/javax/sip/stack/SIPServerTransaction.java0100644 0000000 0000000 00000217774 13513104763 022227 0ustar000000000 0000000 /* * 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; import gov.nist.core.InternalErrorHandler; import gov.nist.javax.sip.SIPConstants; import gov.nist.javax.sip.ServerTransactionExt; import gov.nist.javax.sip.SipProviderImpl; import gov.nist.javax.sip.Utils; import gov.nist.javax.sip.header.Expires; 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 java.io.IOException; import java.text.ParseException; import java.util.TimerTask; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import javax.sip.Dialog; import javax.sip.DialogState; import javax.sip.DialogTerminatedEvent; import javax.sip.ObjectInUseException; import javax.sip.SipException; import javax.sip.Timeout; import javax.sip.TimeoutEvent; import javax.sip.TransactionState; import javax.sip.address.Hop; import javax.sip.header.ContactHeader; import javax.sip.header.ExpiresHeader; import javax.sip.header.RSeqHeader; import javax.sip.message.Request; import javax.sip.message.Response; /* * Bug fixes / enhancements:Emil Ivov, Antonis Karydas, Daniel J. Martinez Manzano, Daniel, Hagai * Sela, Vazques-Illa, Bill Roome, Thomas Froment and Pierre De Rop, Christophe Anzille and Jeroen * van Bemmel, Frank Reif. * Carolyn Beeton ( Avaya ). * */ /** * Represents a server transaction. Implements the following state machines. * *

     *
     *
     *
     *                                                                      |INVITE
     *                                                                      |pass INV to TU
     *                                                   INVITE             V send 100 if TU won't in 200ms
     *                                                   send response+-----------+
     *                                                       +--------|           |--------+101-199 from TU
     *                                                       |        | Proceeding|        |send response
     *                                                       +------->|           |<-------+
     *                                                                |           |          Transport Err.
     *                                                                |           |          Inform TU
     *                                                                |           |--------------->+
     *                                                                +-----------+                |
     *                                                   300-699 from TU |     |2xx from TU        |
     *                                                   send response   |     |send response      |
     *                                                                   |     +------------------>+
     *                                                                   |                         |
     *                                                   INVITE          V          Timer G fires  |
     *                                                   send response+-----------+ send response  |
     *                                                       +--------|           |--------+       |
     *                                                       |        | Completed |        |       |
     *                                                       +------->|           |<-------+       |
     *                                                                +-----------+                |
     *                                                                   |     |                   |
     *                                                               ACK |     |                   |
     *                                                               -   |     +------------------>+
     *                                                                   |        Timer H fires    |
     *                                                                   V        or Transport Err.|
     *                                                                +-----------+  Inform TU     |
     *                                                                |           |                |
     *                                                                | Confirmed |                |
     *                                                                |           |                |
     *                                                                +-----------+                |
     *                                                                      |                      |
     *                                                                      |Timer I fires         |
     *                                                                      |-                     |
     *                                                                      |                      |
     *                                                                      V                      |
     *                                                                +-----------+                |
     *                                                                |           |                |
     *                                                                | Terminated|<---------------+
     *                                                                |           |
     *                                                                +-----------+
     *
     *                                                     Figure 7: INVITE server transaction
     *                                                         Request received
     *                                                                         |pass to TU
     *
     *                                                                         V
     *                                                                   +-----------+
     *                                                                   |           |
     *                                                                   | Trying    |-------------+
     *                                                                   |           |             |
     *                                                                   +-----------+             |200-699 from TU
     *                                                                         |                   |send response
     *                                                                         |1xx from TU        |
     *                                                                         |send response      |
     *                                                                         |                   |
     *                                                      Request            V      1xx from TU  |
     *                                                      send response+-----------+send response|
     *                                                          +--------|           |--------+    |
     *                                                          |        | Proceeding|        |    |
     *                                                          +------->|           |<-------+    |
     *                                                   +<--------------|           |             |
     *                                                   |Trnsprt Err    +-----------+             |
     *                                                   |Inform TU            |                   |
     *                                                   |                     |                   |
     *                                                   |                     |200-699 from TU    |
     *                                                   |                     |send response      |
     *                                                   |  Request            V                   |
     *                                                   |  send response+-----------+             |
     *                                                   |      +--------|           |             |
     *                                                   |      |        | Completed |<------------+
     *                                                   |      +------->|           |
     *                                                   +<--------------|           |
     *                                                   |Trnsprt Err    +-----------+
     *                                                   |Inform TU            |
     *                                                   |                     |Timer J fires
     *                                                   |                     |-
     *                                                   |                     |
     *                                                   |                     V
     *                                                   |               +-----------+
     *                                                   |               |           |
     *                                                   +-------------->| Terminated|
     *                                                                   |           |
     *                                                                   +-----------+
     *
     *
     *
     *
     *
     * 
    * * @version 1.2 $Revision: 1.118 $ $Date: 2010/01/10 00:13:14 $ * @author M. Ranganathan * */ public class SIPServerTransaction extends SIPTransaction implements ServerRequestInterface, javax.sip.ServerTransaction, ServerTransactionExt { // force the listener to see transaction private int rseqNumber; // private LinkedList pendingRequests; // Real RequestInterface to pass messages to private transient ServerRequestInterface requestOf; private SIPDialog dialog; // the unacknowledged SIPResponse private SIPResponse pendingReliableResponse; // The pending reliable Response Timer private ProvisionalResponseTask provisionalResponseTask; private boolean retransmissionAlertEnabled; private RetransmissionAlertTimerTask retransmissionAlertTimerTask; protected boolean isAckSeen; private SIPClientTransaction pendingSubscribeTransaction; private SIPServerTransaction inviteTransaction; private Semaphore provisionalResponseSem = new Semaphore(1); /** * This timer task is used for alerting the application to send retransmission alerts. * * */ class RetransmissionAlertTimerTask extends SIPStackTimerTask { String dialogId; int ticks; int ticksLeft; public RetransmissionAlertTimerTask(String dialogId) { this.ticks = SIPTransaction.T1; this.ticksLeft = this.ticks; } protected void runTask() { SIPServerTransaction serverTransaction = SIPServerTransaction.this; ticksLeft--; if (ticksLeft == -1) { serverTransaction.fireRetransmissionTimer(); this.ticksLeft = 2 * ticks; } } } class ProvisionalResponseTask extends SIPStackTimerTask { int ticks; int ticksLeft; public ProvisionalResponseTask() { this.ticks = SIPTransaction.T1; this.ticksLeft = this.ticks; } protected void runTask() { SIPServerTransaction serverTransaction = SIPServerTransaction.this; /* * The reliable provisional response is passed to the transaction layer periodically * with an interval that starts at T1 seconds and doubles for each retransmission (T1 * is defined in Section 17 of RFC 3261). Once passed to the server transaction, it is * added to an internal list of unacknowledged reliable provisional responses. The * transaction layer will forward each retransmission passed from the UAS core. * * This differs from retransmissions of 2xx responses, whose intervals cap at T2 * seconds. This is because retransmissions of ACK are triggered on receipt of a 2xx, * but retransmissions of PRACK take place independently of reception of 1xx. */ // If the transaction has terminated, if (serverTransaction.isTerminated()) { this.cancel(); } else { ticksLeft--; if (ticksLeft == -1) { serverTransaction.fireReliableResponseRetransmissionTimer(); this.ticksLeft = 2 * ticks; this.ticks = this.ticksLeft; // timer H MUST be set to fire in 64*T1 seconds for all transports. Timer H // determines when the server // transaction abandons retransmitting the response if (this.ticksLeft >= SIPTransaction.TIMER_H) { this.cancel(); setState(TERMINATED_STATE); fireTimeoutTimer(); } } } } } /** * This timer task will terminate the transaction if the listener does not respond in a * pre-determined time period. This helps prevent buggy listeners (who fail to respond) from * causing memory leaks. This allows a container to protect itself from buggy code ( that * fails to respond to a server transaction). * */ class ListenerExecutionMaxTimer extends SIPStackTimerTask { SIPServerTransaction serverTransaction = SIPServerTransaction.this; ListenerExecutionMaxTimer() { } protected void runTask() { try { if (serverTransaction.getState() == null) { serverTransaction.terminate(); SIPTransactionStack sipStack = serverTransaction.getSIPStack(); sipStack.removePendingTransaction(serverTransaction); sipStack.removeTransaction(serverTransaction); } } catch (Exception ex) { sipStack.getStackLogger().logError("unexpected exception", ex); } } } /** * This timer task is for INVITE server transactions. It will send a trying in 200 ms. if the * TU does not do so. * */ class SendTrying extends SIPStackTimerTask { protected SendTrying() { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("scheduled timer for " + SIPServerTransaction.this); } protected void runTask() { SIPServerTransaction serverTransaction = SIPServerTransaction.this; TransactionState realState = serverTransaction.getRealState(); if (realState == null || TransactionState.TRYING == realState) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug(" sending Trying current state = " + serverTransaction.getRealState()); try { serverTransaction.sendMessage(serverTransaction.getOriginalRequest() .createResponse(100, "Trying")); if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug(" trying sent " + serverTransaction.getRealState()); } catch (IOException ex) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logError("IO error sending TRYING"); } } } } class TransactionTimer extends SIPStackTimerTask { public TransactionTimer() { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug("TransactionTimer() : " + getTransactionId()); } } protected void runTask() { // If the transaction has terminated, 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 { this.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 TimerTask myTimer = new LingerTimer(); sipStack.getTimer().schedule(myTimer, SIPTransactionStack.CONNECTION_LINGER_TIME * 1000); } else { // Add to the fire list -- needs to be moved // outside the synchronized block to prevent // deadlock. fireTimer(); } } } /** * Send a response. * * @param transactionResponse -- the response to send * */ 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 // in // order // to determine where to send a response. // It MUST follow the following process: // 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. if (isReliable()) { 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(); String transport = via.getTransport(); if (transport == null) throw new IOException("missing transport!"); // @@@ hagai Symmetric NAT support int port = via.getRPort(); if (port == -1) port = via.getPort(); if (port == -1) { if (transport.equalsIgnoreCase("TLS")) port = 5061; else port = 5060; } // Otherwise, if the Via header field value contains a // "maddr" parameter, the response MUST be forwarded to // the address listed there, using the port indicated in // "sent-by", // or port 5060 if none is present. If the address is a // multicast // address, the response SHOULD be sent using // the TTL indicated in the "ttl" parameter, or with a // TTL of 1 if that parameter is not present. String host = null; if (via.getMAddr() != null) { host = via.getMAddr(); } else { // Otherwise (for unreliable unicast transports), // if the top Via has a "received" parameter, the response // MUST // be sent to the // address in the "received" parameter, using the port // indicated // in the // "sent-by" value, or using port 5060 if none is specified // explicitly. host = via.getParameter(Via.RECEIVED); if (host == null) { // Otherwise, if it is not receiver-tagged, the response // MUST be // sent to the address indicated by the "sent-by" value, // using the procedures in Section 5 // RFC 3263 PROCEDURE TO BE DONE HERE host = via.getHost(); } } Hop hop = sipStack.addressResolver.resolveAddress(new HopImpl(host, port, transport)); MessageChannel messageChannel = ((SIPTransactionStack) getSIPStack()) .createRawMessageChannel(this.getSipProvider().getListeningPoint( hop.getTransport()).getIPAddress(), this.getPort(), hop); if (messageChannel != null) messageChannel.sendMessage(transactionResponse); else throw new IOException("Could not create a message channel for " + hop); } } finally { this.startTransactionTimer(); } } /** * Creates a new server transaction. * * @param sipStack Transaction stack this transaction belongs to. * @param newChannelToUse Channel to encapsulate. */ protected SIPServerTransaction(SIPTransactionStack sipStack, MessageChannel newChannelToUse) { super(sipStack, newChannelToUse); if (sipStack.maxListenerResponseTime != -1) { sipStack.getTimer().schedule(new ListenerExecutionMaxTimer(), sipStack.maxListenerResponseTime * 1000); } this.rseqNumber = (int) (Math.random() * 1000); // Only one outstanding request for a given server tx. if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug("Creating Server Transaction" + this.getBranchId()); sipStack.getStackLogger().logStackTrace(); } } /** * Sets the real RequestInterface this transaction encapsulates. * * @param newRequestOf RequestInterface to send messages to. */ public void setRequestInterface(ServerRequestInterface newRequestOf) { requestOf = newRequestOf; } /** * Returns this transaction. */ public MessageChannel getResponseChannel() { return this; } /** * Determines if the message is a part of this transaction. * * @param messageToTest Message to check if it is part of this transaction. * * @return True if the message is part of this transaction, false if not. */ public boolean isMessagePartOfTransaction(SIPMessage messageToTest) { // List of Via headers in the message to test 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; 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 ((method.equals(Request.INVITE) || !isTerminated())) { // Get the topmost Via header and its branch parameter viaHeaders = messageToTest.getViaHeaders(); if (viaHeaders != null) { topViaHeader = (Via) viaHeaders.getFirst(); messageBranch = topViaHeader.getBranch(); if (messageBranch != null) { // If the branch parameter exists but // does not start with the magic cookie, if (!messageBranch.toLowerCase().startsWith( SIPConstants.BRANCH_MAGIC_COOKIE_LOWER_CASE)) { // Flags this as old // (RFC2543-compatible) client // version messageBranch = null; } } // If a new branch parameter exists, if (messageBranch != null && this.getBranch() != null) { if (method.equals(Request.CANCEL)) { // Cancel is handled as a special case because it // shares the same same branch id of the invite // that it is trying to cancel. transactionMatches = this.getMethod().equals(Request.CANCEL) && getBranch().equalsIgnoreCase(messageBranch) && topViaHeader.getSentBy().equals( ((Via) getOriginalRequest().getViaHeaders().getFirst()) .getSentBy()); } else { // Matching server side transaction with only the // branch parameter. transactionMatches = getBranch().equalsIgnoreCase(messageBranch) && topViaHeader.getSentBy().equals( ((Via) getOriginalRequest().getViaHeaders().getFirst()) .getSentBy()); } } else { // This is an RFC2543-compliant message; this code is here // for backwards compatibility. // It is a weak check. // If RequestURI, To tag, From tag, CallID, CSeq number, and // top Via headers are the same, the // 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 = super.fromTag; String thisFromTag = messageToTest.getFrom().getTag(); boolean skipFrom = (originalFromTag == null || thisFromTag == null); String originalToTag = super.toTag; String thisToTag = messageToTest.getTo().getTag(); boolean skipTo = (originalToTag == null || thisToTag == null); boolean isResponse = (messageToTest instanceof SIPResponse); // Issue #96: special case handling for a CANCEL request - // 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) && !getOriginalRequest().getCSeq().getMethod().equalsIgnoreCase( Request.CANCEL)) { transactionMatches = false; } else if ((isResponse || getOriginalRequest().getRequestURI().equals( ((SIPRequest) messageToTest).getRequestURI())) && (skipFrom || originalFromTag != null && originalFromTag.equalsIgnoreCase(thisFromTag)) && (skipTo || originalToTag != null && originalToTag.equalsIgnoreCase(thisToTag)) && getOriginalRequest().getCallId().getCallId().equalsIgnoreCase( messageToTest.getCallId().getCallId()) && getOriginalRequest().getCSeq().getSeqNumber() == messageToTest .getCSeq().getSeqNumber() && ((!messageToTest.getCSeq().getMethod().equals(Request.CANCEL)) || getOriginalRequest() .getMethod().equals(messageToTest.getCSeq().getMethod())) && topViaHeader.equals(getOriginalRequest().getViaHeaders() .getFirst())) { transactionMatches = true; } } } } return transactionMatches; } /** * Send out a trying response (only happens when the transaction is mapped). Otherwise the * transaction is not known to the stack. */ protected void map() { // note that TRYING is a pseudo-state for invite transactions TransactionState realState = getRealState(); 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. sipStack.getTimer().schedule(new SendTrying(), 200); } else { isMapped = true; } } // Pull it out of the pending transactions list. sipStack.removePendingTransaction(this); } /** * Return true if the transaction is known to stack. */ public boolean isTransactionMapped() { return this.isMapped; } /** * Process a new request message through this transaction. If necessary, this message will * also be passed onto the TU. * * @param transactionRequest Request to process. * @param sourceChannel Channel that received this message. */ public void processRequest(SIPRequest transactionRequest, MessageChannel sourceChannel) { boolean toTu = false; // Can only process a single request directed to the // transaction at a time. For a given server transaction // the listener sees only one event at a time. if (sipStack.isLoggingEnabled()) { 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() == null) { // Save this request as the one this // transaction is handling setOriginalRequest(transactionRequest); this.setState(TransactionState.TRYING); toTu = true; this.setPassToListener(); // Rsends the TRYING on retransmission of the request. if (isInviteTransaction() && this.isMapped) { // JvB: also // proxies need // to do this // Has side-effect of setting // state to "Proceeding" sendMessage(transactionRequest.createResponse(100, "Trying")); } // If an invite transaction is ACK'ed while in // the completed state, } else if (isInviteTransaction() && TransactionState.COMPLETED == getRealState() && transactionRequest.getMethod().equals(Request.ACK)) { // @jvB bug fix this.setState(TransactionState.CONFIRMED); disableRetransmissionTimer(); if (!isReliable()) { enableTimeoutTimer(TIMER_I); } else { this.setState(TransactionState.TERMINATED); } // JvB: For the purpose of testing a TI, added a property to // pass it anyway if (sipStack.isNon2XXAckPassedToListener()) { // This is useful for test applications that want to see // all messages. requestOf.processRequest(transactionRequest, this); } else { // According to RFC3261 Application should not Ack in // CONFIRMED state if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug("ACK received for server Tx " + this.getTransactionId() + " not delivering to application!"); } this.semRelease(); } return; // If we receive a retransmission of the original // request, } else if (transactionRequest.getMethod().equals(getOriginalRequest().getMethod())) { if (TransactionState.PROCEEDING == getRealState() || TransactionState.COMPLETED == getRealState()) { this.semRelease(); // Resend the last response to // the client 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 if (requestOf != null) requestOf.processRequest(transactionRequest, this); else this.semRelease(); } if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("completed processing retransmitted request : " + transactionRequest.getFirstLine() + this + " txState = " + this.getState() + " lastResponse = " + this.getLastResponse()); return; } // Pass message to the TU 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); } else this.semRelease(); } else { if (requestOf != null) requestOf.processRequest(transactionRequest, this); else this.semRelease(); } } else { // This seems like a common bug so I am allowing it through! if (((SIPTransactionStack) getSIPStack()).isDialogCreated(getOriginalRequest() .getMethod()) && getRealState() == TransactionState.TERMINATED && transactionRequest.getMethod().equals(Request.ACK) && requestOf != null) { SIPDialog thisDialog = (SIPDialog) this.dialog; if (thisDialog == null || !thisDialog.ackProcessed) { // Filter out duplicate acks if (thisDialog != null) { thisDialog.ackReceived(transactionRequest); thisDialog.ackProcessed = true; } requestOf.processRequest(transactionRequest, this); } else { this.semRelease(); } } else if (transactionRequest.getMethod().equals(Request.CANCEL)) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("Too late to cancel Transaction"); this.semRelease(); // send OK and just ignore the CANCEL. try { this.sendMessage(transactionRequest.createResponse(Response.OK)); } catch (IOException ex) { // Transaction is already terminated // just ignore the IOException. } } if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("Dropping request " + getRealState()); } } catch (IOException e) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logError("IOException " ,e); this.semRelease(); this.raiseIOExceptionEvent(); } } /** * 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 { 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 (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 (!this.getOriginalRequest().getTopmostVia().hasPort()) transactionResponse.getTopmostVia().removePort(); } catch (ParseException ex) { 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( getOriginalRequest().getMethod())) { sendResponse(transactionResponse); return; } // 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(); } enableTimeoutTimer(TIMER_H); } } } // 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; 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()) { /* * 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(); } 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); } else { this.setState(TransactionState.TERMINATED); } } // 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()) { sipStack.getStackLogger().logDebug( "sendMessage : tx = " + this + " getState = " + this.getState()); } lastResponse = transactionResponse; this.sendResponse(transactionResponse); } catch (IOException e) { this.setState(TransactionState.TERMINATED); this.collectionTime = 0; throw e; } } finally { this.startTransactionTimer(); } } public String getViaHost() { return getMessageChannel().getViaHost(); } public int getViaPort() { return getMessageChannel().getViaPort(); } /** * Called by the transaction stack when a retransmission timer fires. This retransmits the * last response when the retransmission filter is enabled. */ protected void fireRetransmissionTimer() { try { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug("fireRetransmissionTimer() -- "); } // Resend the last response sent by this transaction 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 (lastResponse.getStatusCode() / 100 > 2 && !this.isAckSeen) super.sendMessage(lastResponse); } else { // alert the application to retransmit the last response SipProviderImpl sipProvider = (SipProviderImpl) this.getSipProvider(); TimeoutEvent txTimeout = new TimeoutEvent(sipProvider, this, Timeout.RETRANSMIT); sipProvider.handleEvent(txTimeout, this); } } } catch (IOException e) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logException(e); raiseErrorEvent(SIPTransactionErrorEvent.TRANSPORT_ERROR); } } private void fireReliableResponseRetransmissionTimer() { try { super.sendMessage(this.pendingReliableResponse); } catch (IOException e) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logException(e); this.setState(TransactionState.TERMINATED); raiseErrorEvent(SIPTransactionErrorEvent.TRANSPORT_ERROR); } } /** * Called by the transaction stack when a timeout timer fires. */ protected void fireTimeoutTimer() { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("SIPServerTransaction.fireTimeoutTimer this = " + this + " current state = " + this.getRealState() + " method = " + this.getOriginalRequest().getMethod()); if ( this.getMethod().equals(Request.INVITE) && sipStack.removeTransactionPendingAck(this) ) { if ( sipStack.isLoggingEnabled() ) { sipStack.getStackLogger().logDebug("Found tx pending ACK - returning"); } return; } 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 (getOriginalRequest().getMethod().equals(Request.BYE)) { if (dialog != null && dialog.isTerminatedOnBye()) dialog.setState(SIPDialog.TERMINATED_STATE); } if (TransactionState.COMPLETED == this.getRealState() && isInviteTransaction()) { raiseErrorEvent(SIPTransactionErrorEvent.TIMEOUT_ERROR); this.setState(TransactionState.TERMINATED); sipStack.removeTransaction(this); } else if (TransactionState.COMPLETED == this.getRealState() && !isInviteTransaction()) { this.setState(TransactionState.TERMINATED); sipStack.removeTransaction(this); } 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); sipStack.removeTransaction(this); } else if (!isInviteTransaction() && (TransactionState.COMPLETED == this.getRealState() || TransactionState.CONFIRMED == this .getRealState())) { this.setState(TransactionState.TERMINATED); } else if (isInviteTransaction() && TransactionState.TERMINATED == this.getRealState()) { // This state could be reached when retransmitting raiseErrorEvent(SIPTransactionErrorEvent.TIMEOUT_ERROR); if (dialog != null) dialog.setState(SIPDialog.TERMINATED_STATE); } } /** * Get the last response. */ public SIPResponse getLastResponse() { return this.lastResponse; } /** * Set the original request. */ public void setOriginalRequest(SIPRequest originalRequest) { super.setOriginalRequest(originalRequest); } /* * (non-Javadoc) * * @see javax.sip.ServerTransaction#sendResponse(javax.sip.message.Response) */ public void sendResponse(Response response) throws SipException { SIPResponse sipResponse = (SIPResponse) response; SIPDialog dialog = this.dialog; if (response == null) throw new NullPointerException("null response"); try { sipResponse.checkHeaders(); } catch (ParseException ex) { throw new SipException(ex.getMessage()); } // check for meaningful response. if (!sipResponse.getCSeq().getMethod().equals(this.getMethod())) { throw new SipException( "CSeq method does not match Request method of request that created the tx."); } /* * 200-class responses to SUBSCRIBE requests also MUST contain an "Expires" header. The * period of time in the response MAY be shorter but MUST NOT be longer than specified in * the request. */ if (this.getMethod().equals(Request.SUBSCRIBE) && response.getStatusCode() / 100 == 2) { if (response.getHeader(ExpiresHeader.NAME) == null) { throw new SipException("Expires header is mandatory in 2xx response of SUBSCRIBE"); } else { Expires requestExpires = (Expires) this.getOriginalRequest().getExpires(); Expires responseExpires = (Expires) response.getExpires(); /* * If no "Expires" header is present in a SUBSCRIBE request, the implied default * is defined by the event package being used. */ if (requestExpires != null && responseExpires.getExpires() > requestExpires.getExpires()) { throw new SipException( "Response Expires time exceeds request Expires time : See RFC 3265 3.1.1"); } } } // Check for mandatory header. if (sipResponse.getStatusCode() == 200 && sipResponse.getCSeq().getMethod().equals(Request.INVITE) && sipResponse.getHeader(ContactHeader.NAME) == null) 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."); } // Fix up the response if the dialog has already been established. try { /* * The UAS MAY send a final response to the initial request before * having received PRACKs for all unacknowledged reliable provisional responses, * unless the final response is 2xx and any of the unacknowledged reliable provisional * responses contained a session description. In that case, it MUST NOT send a final * response until those provisional responses are acknowledged. */ 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")) { try { boolean acquired = this.provisionalResponseSem.tryAcquire(1,TimeUnit.SECONDS); if (!acquired ) { throw new SipException("cannot send response -- unacked povisional"); } } catch (Exception ex) { this.sipStack.getStackLogger().logError("Could not acquire PRACK sem ", ex); } } else { // Sending the final response cancels the // pending response task. 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 (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) { sipResponse.setToTag(dialog.getLocalTag()); } else if (dialog.getLocalTag() != null && sipResponse.getToTag() != null && !dialog.getLocalTag().equals(sipResponse.getToTag())) { throw new SipException("Tag mismatch dialogTag is " + dialog.getLocalTag() + " responseTag is " + sipResponse.getToTag()); } } if (!sipResponse.getCallId().getCallId().equals(dialog.getCallId().getCallId())) { throw new SipException("Dialog mismatch!"); } } // Backward compatibility slippery slope.... // Only set the from tag in the response when the // incoming request has a from tag. 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 (sipStack.isLoggingEnabled()) 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 && response.getStatusCode() != 100) { dialog.setResponseTags(sipResponse); DialogState oldState = dialog.getState(); dialog.setLastResponse(this, (SIPResponse) response); if (oldState == null && dialog.getState() == DialogState.TERMINATED) { DialogTerminatedEvent event = new DialogTerminatedEvent(dialog .getSipProvider(), dialog); // Provide notification to the listener that the dialog has // ended. dialog.getSipProvider().handleEvent(event, this); } } else if (dialog == null && this.getMethod().equals(Request.INVITE) && this.retransmissionAlertEnabled && this.retransmissionAlertTimerTask == null && response.getStatusCode() / 100 == 2) { String dialogId = ((SIPResponse) response).getDialogId(true); this.retransmissionAlertTimerTask = new RetransmissionAlertTimerTask(dialogId); sipStack.retransmissionAlertTransactions.put(dialogId, this); sipStack.getTimer().schedule(this.retransmissionAlertTimerTask, 0, SIPTransactionStack.BASE_TIMER_INTERVAL); } // 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 (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logException(ex); this.setState(TransactionState.TERMINATED); raiseErrorEvent(SIPTransactionErrorEvent.TRANSPORT_ERROR); throw new SipException(ex.getMessage()); } catch (java.text.ParseException 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. */ private TransactionState getRealState() { return super.getState(); } /** * Return the current transaction state according to the RFC 3261 transaction state machine. * Invite transactions do not have a trying state. We just use this as a pseudo state for * processing requests. * * @return the state of the transaction. */ public TransactionState getState() { // Trying is a pseudo state for INVITE transactions. if (this.isInviteTransaction() && TransactionState.TRYING == super.getState()) return TransactionState.PROCEEDING; else return super.getState(); } /** * Sets a timeout after which the connection is closed (provided the server does not use the * connection for outgoing requests in this time period) and calls the superclass to set * state. */ public void setState(TransactionState newState) { // Set this timer for connection caching // of incoming connections. if (newState == TransactionState.TERMINATED && this.isReliable() && (!getSIPStack().cacheServerConnections)) { // Set a time after which the connection // is closed. this.collectionTime = TIMER_J; } super.setState(newState); } /** * Start the timer task. */ protected void startTransactionTimer() { 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.getClass().equals(this.getClass())) { return false; } SIPServerTransaction sst = (SIPServerTransaction) other; return this.getBranch().equalsIgnoreCase(sst.getBranch()); } /* * (non-Javadoc) * * @see gov.nist.javax.sip.stack.SIPTransaction#getDialog() */ public Dialog getDialog() { return this.dialog; } /* * (non-Javadoc) * * @see gov.nist.javax.sip.stack.SIPTransaction#setDialog(gov.nist.javax.sip.stack.SIPDialog, * gov.nist.javax.sip.message.SIPMessage) */ public void setDialog(SIPDialog sipDialog, String dialogId) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("setDialog " + this + " dialog = " + sipDialog); this.dialog = sipDialog; if (dialogId != null) this.dialog.setAssigned(); if (this.retransmissionAlertEnabled && this.retransmissionAlertTimerTask != null) { this.retransmissionAlertTimerTask.cancel(); if (this.retransmissionAlertTimerTask.dialogId != null) { sipStack.retransmissionAlertTransactions .remove(this.retransmissionAlertTimerTask.dialogId); } this.retransmissionAlertTimerTask = null; } this.retransmissionAlertEnabled = false; } /* * (non-Javadoc) * * @see javax.sip.Transaction#terminate() */ public void terminate() throws ObjectInUseException { this.setState(TransactionState.TERMINATED); if (this.retransmissionAlertTimerTask != null) { this.retransmissionAlertTimerTask.cancel(); if (retransmissionAlertTimerTask.dialogId != null) { this.sipStack.retransmissionAlertTransactions .remove(retransmissionAlertTimerTask.dialogId); } this.retransmissionAlertTimerTask = null; } } protected void sendReliableProvisionalResponse(Response relResponse) throws SipException { /* * After the first reliable provisional response for a request has been acknowledged, the * UAS MAY send additional reliable provisional responses. The UAS MUST NOT send a second * reliable provisional response until the first is acknowledged. */ if (this.pendingReliableResponse != null) { throw new SipException("Unacknowledged response"); } 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. */ RSeq rseq = (RSeq) relResponse.getHeader(RSeqHeader.NAME); if (relResponse.getHeader(RSeqHeader.NAME) == null) { rseq = new RSeq(); relResponse.setHeader(rseq); } try { this.rseqNumber++; rseq.setSeqNumber(this.rseqNumber); // start the timer task which will retransmit the reliable response // until the PRACK is received this.lastResponse = (SIPResponse) relResponse; if ( this.getDialog() != null ) { boolean acquired = this.provisionalResponseSem.tryAcquire(1, TimeUnit.SECONDS); if (!acquired) { throw new SipException("Unacknowledged response"); } } this.sendMessage((SIPMessage) relResponse); this.provisionalResponseTask = new ProvisionalResponseTask(); this.sipStack.getTimer().schedule(provisionalResponseTask, 0, SIPTransactionStack.BASE_TIMER_INTERVAL); } catch (Exception ex) { InternalErrorHandler.handleException(ex); } } public SIPResponse getReliableProvisionalResponse() { return this.pendingReliableResponse; } /** * Cancel the retransmit timer for the provisional response task. * * @return true if the tx has seen the prack for the first time and false otherwise. * */ public boolean prackRecieved() { if (this.pendingReliableResponse == null) return false; if(provisionalResponseTask != null) this.provisionalResponseTask.cancel(); this.pendingReliableResponse = null; this.provisionalResponseSem.release(); return true; } /* * (non-Javadoc) * * @see javax.sip.ServerTransaction#enableRetransmissionAlerts() */ public void enableRetransmissionAlerts() throws SipException { if (this.getDialog() != null) throw new SipException("Dialog associated with tx"); else if (!this.getMethod().equals(Request.INVITE)) throw new SipException("Request Method must be INVITE"); this.retransmissionAlertEnabled = true; } public boolean isRetransmissionAlertEnabled() { return this.retransmissionAlertEnabled; } /** * Disable retransmission Alerts and cancel associated timers. * */ public void disableRetransmissionAlerts() { if (this.retransmissionAlertTimerTask != null && this.retransmissionAlertEnabled) { this.retransmissionAlertTimerTask.cancel(); this.retransmissionAlertEnabled = false; String dialogId = this.retransmissionAlertTimerTask.dialogId; if (dialogId != null) { sipStack.retransmissionAlertTransactions.remove(dialogId); } this.retransmissionAlertTimerTask = null; } } /** * This is book-keeping for retransmission filter management. */ public void setAckSeen() { this.isAckSeen = true; } /** * This is book-keeping for retransmission filter management. */ public boolean ackSeen() { return this.isAckSeen; } public void setMapped(boolean b) { this.isMapped = true; } public void setPendingSubscribe(SIPClientTransaction pendingSubscribeClientTx) { this.pendingSubscribeTransaction = pendingSubscribeClientTx; } public void releaseSem() { if (this.pendingSubscribeTransaction != null) { /* * When a notify is being processed we take a lock on the subscribe to avoid racing * with the OK of the subscribe. */ pendingSubscribeTransaction.releaseSem(); } else if (this.inviteTransaction != null && this.getMethod().equals(Request.CANCEL)) { /* * When a CANCEL is being processed we take a nested lock on the associated INVITE * server tx. */ this.inviteTransaction.releaseSem(); } super.releaseSem(); } /** * The INVITE Server Transaction corresponding to a CANCEL Server Transaction. * * @param st -- the invite server tx corresponding to the cancel server transaction. */ public void setInviteTransaction(SIPServerTransaction st) { this.inviteTransaction = st; } /** * TODO -- this method has to be added to the api. * * @return */ public SIPServerTransaction getCanceledInviteTransaction() { return this.inviteTransaction; } public void scheduleAckRemoval() throws IllegalStateException { if (this.getMethod() == null || !this.getMethod().equals(Request.ACK)) { throw new IllegalStateException("Method is null[" + (getMethod() == null) + "] or method is not ACK[" + this.getMethod() + "]"); } this.startTransactionTimer(); } } java/gov/nist/javax/sip/stack/SIPStackTimerTask.java0100644 0000000 0000000 00000002041 13513104763 021417 0ustar000000000 0000000 /* * @author: Brett Buckingham * @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 * avoid killing the SIPTransactionStack timer thread. Note: subclasses MUST not * override run(); instead they should override runTask(). * * @author Brett Buckingham * */ public abstract class SIPStackTimerTask extends TimerTask { // / Implements code to be run when the SIPStackTimerTask is executed. protected abstract void runTask(); // / 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(); } } } java/gov/nist/javax/sip/stack/SIPTransaction.java0100644 0000000 0000000 00000122500 13513104763 021016 0ustar000000000 0000000 /* * 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; import gov.nist.core.InternalErrorHandler; import gov.nist.javax.sip.SIPConstants; import gov.nist.javax.sip.SipProviderImpl; 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 java.io.IOException; import java.net.InetAddress; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import javax.net.ssl.SSLPeerUnverifiedException; import javax.sip.Dialog; import javax.sip.IOExceptionEvent; import javax.sip.ServerTransaction; import javax.sip.TransactionState; import javax.sip.message.Request; import javax.sip.message.Response; /* * Modifications for TLS Support added by Daniel J. Martinez Manzano * Bug fixes by Jeroen van Bemmel (JvB) and others. */ /** * Abstract class to support both client and server transactions. Provides an * encapsulation of a message channel, handles timer events, and creation of the * Via header for a message. * * @author Jeff Keyser * @author M. Ranganathan * * * @version 1.2 $Revision: 1.71 $ $Date: 2009/11/29 04:31:29 $ */ public abstract class SIPTransaction extends MessageChannel implements javax.sip.Transaction, gov.nist.javax.sip.TransactionExt { protected boolean toListener; // Flag to indicate that the listener gets // to see the event. protected int BASE_TIMER_INTERVAL = SIPTransactionStack.BASE_TIMER_INTERVAL; /** * 5 sec Maximum duration a message will remain in the network */ protected int T4 = 5000 / BASE_TIMER_INTERVAL; /** * The maximum retransmit interval for non-INVITE requests and INVITE * responses */ protected int T2 = 4000 / BASE_TIMER_INTERVAL; protected int TIMER_I = T4; protected int TIMER_K = T4; protected int TIMER_D = 32000 / BASE_TIMER_INTERVAL; // protected static final int TIMER_C = 3 * 60 * 1000 / BASE_TIMER_INTERVAL; /** * One timer tick. */ protected static final int T1 = 1; /** * INVITE request retransmit interval, for UDP only */ protected static final int TIMER_A = 1; /** * INVITE transaction timeout timer */ protected static final int TIMER_B = 64; protected static final int TIMER_J = 64; protected static final int TIMER_F = 64; protected static final int TIMER_H = 64; // Proposed feature for next release. protected transient Object applicationData; protected SIPResponse lastResponse; // private SIPDialog dialog; protected boolean isMapped; private Semaphore semaphore; protected boolean isSemaphoreAquired; // protected boolean eventPending; // indicate that an event is pending // here. protected String transactionId; // Transaction Id. // Audit tag used by the SIP Stack audit public long auditTag = 0; /** * Initialized but no state assigned. */ public static final TransactionState INITIAL_STATE = null; /** * Trying state. */ public static final TransactionState TRYING_STATE = TransactionState.TRYING; /** * CALLING State. */ public static final TransactionState CALLING_STATE = TransactionState.CALLING; /** * Proceeding state. */ public static final TransactionState PROCEEDING_STATE = TransactionState.PROCEEDING; /** * Completed state. */ public static final TransactionState COMPLETED_STATE = TransactionState.COMPLETED; /** * Confirmed state. */ public static final TransactionState CONFIRMED_STATE = TransactionState.CONFIRMED; /** * Terminated state. */ public static final TransactionState TERMINATED_STATE = TransactionState.TERMINATED; /** * Maximum number of ticks between retransmissions. */ protected static final int MAXIMUM_RETRANSMISSION_TICK_COUNT = 8; // Parent stack for this transaction protected transient SIPTransactionStack sipStack; // Original request that is being handled by this transaction protected SIPRequest originalRequest; // 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 private String branch; // 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 TransactionState currentState; // Number of ticks the retransmission timer was set to last private transient int retransmissionTimerLastTickCount; // Number of ticks before the message is retransmitted private transient int retransmissionTimerTicksLeft; // Number of ticks before the transaction times out protected int timeoutTimerTicksLeft; // 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; protected String toTag; protected String fromTag; private boolean terminatedEventDelivered; public String getBranchId() { return this.branch; } /** * The linger timer is used to remove the transaction from the transaction * table after it goes into terminated state. This allows connection caching * and also takes care of race conditins. * * */ class LingerTimer extends SIPStackTimerTask { public LingerTimer() { SIPTransaction sipTransaction = SIPTransaction.this; if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug("LingerTimer : " + sipTransaction.getTransactionId()); } } protected void runTask() { SIPTransaction transaction = SIPTransaction.this; // release the connection associated with this transaction. SIPTransactionStack sipStack = transaction.getSIPStack(); if (sipStack.isLoggingEnabled()) { 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()) 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() && (!sipStack.cacheServerConnections) && transaction.isReliable()) { int useCount = transaction.encapsulatedChannel.useCount; sipStack.getStackLogger().logDebug("Use Count = " + useCount); } } } } } /** * Transaction constructor. * * @param newParentStack * Parent stack for this transaction. * @param newEncapsulatedChannel * Underlying channel for this transaction. */ protected SIPTransaction(SIPTransactionStack newParentStack, MessageChannel newEncapsulatedChannel) { sipStack = newParentStack; 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 (sipStack.isLoggingEnabled()) sipStack.getStackLogger() .logDebug("use count for encapsulated channel" + this + " " + encapsulatedChannel.useCount ); } this.currentState = null; disableRetransmissionTimer(); disableTimeoutTimer(); eventListeners = Collections.synchronizedSet(new HashSet()); // Always add the parent stack as a listener // of this transaction addEventListener(newParentStack); } /** * Sets the request message that this transaction handles. * * @param newOriginalRequest * Request being handled. */ public void setOriginalRequest(SIPRequest newOriginalRequest) { // Branch value of topmost Via header String newBranch; if (this.originalRequest != null && (!this.originalRequest.getTransactionId().equals( newOriginalRequest.getTransactionId()))) { sipStack.removeTransactionHash(this); } // This will be cleared later. this.originalRequest = newOriginalRequest; // just cache the control information so the // original request can be released later. this.method = newOriginalRequest.getMethod(); 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 = ((Via) newOriginalRequest.getViaHeaders().getFirst()) .getBranch(); if (newBranch != null) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("Setting Branch id : " + newBranch); // Override the default branch with the one // set by the message setBranch(newBranch); } else { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("Branch id is null - compute TID!" + newOriginalRequest.encode()); setBranch(newOriginalRequest.getTransactionId()); } } /** * Gets the request being handled by this transaction. * * @return -- the original Request associated with this transaction. */ public SIPRequest getOriginalRequest() { return originalRequest; } /** * Get the original request but cast to a Request structure. * * @return the request that generated this transaction. */ public Request getRequest() { return (Request) originalRequest; } /** * Returns a flag stating whether this transaction is for an INVITE request * or not. * * @return -- true if this is an INVITE request, false if not. */ public final boolean isInviteTransaction() { return getMethod().equals(Request.INVITE); } /** * Return true if the transaction corresponds to a CANCEL message. * * @return -- true if the transaciton is a CANCEL transaction. */ public final boolean isCancelTransaction() { return getMethod().equals(Request.CANCEL); } /** * Return a flag that states if this is a BYE transaction. * * @return true if the transaciton is a BYE transaction. */ public final boolean isByeTransaction() { return getMethod().equals(Request.BYE); } /** * Returns the message channel used for transmitting/receiving messages for * this transaction. Made public in support of JAIN dual transaction model. * * @return Encapsulated MessageChannel. * */ public MessageChannel getMessageChannel() { return encapsulatedChannel; } /** * Sets the Via header branch parameter used to identify this transaction. * * @param newBranch * New string used as the branch for this transaction. */ public final void setBranch(String newBranch) { branch = newBranch; } /** * Gets the current setting for the branch parameter of this transaction. * * @return Branch parameter for this transaction. */ public final String getBranch() { if (this.branch == null) { this.branch = getOriginalRequest().getTopmostVia().getBranch(); } return branch; } /** * Get the method of the request used to create this transaction. * * @return the method of the request for the transaction. */ public final String getMethod() { return this.method; } /** * Get the Sequence number of the request used to create the transaction. * * @return the cseq of the request used to create the transaction. */ public final long getCSeq() { return this.cSeq; } /** * Changes the state of this transaction. * * @param newState * New state of this transaction. */ 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.CONFIRMED) { if (newState != TransactionState.TERMINATED) newState = TransactionState.CONFIRMED; } if (currentState != TransactionState.TERMINATED) currentState = newState; else newState = currentState; // END OF PATCH if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug("Transaction:setState " + newState + " " + this + " branchID = " + this.getBranch() + " isClient = " + (this instanceof SIPClientTransaction)); sipStack.getStackLogger().logStackTrace(); } } /** * Gets the current state of this transaction. * * @return Current state of this transaction. */ public TransactionState getState() { return this.currentState; } /** * Enables retransmission timer events for this transaction to begin in one * tick. */ protected final void enableRetransmissionTimer() { enableRetransmissionTimer(1); } /** * Enables retransmission timer events for this transaction to begin after * the number of ticks passed to this routine. * * @param tickCount * Number of ticks before the next retransmission timer event * occurs. */ protected final void enableRetransmissionTimer(int tickCount) { // For INVITE Client transactions, double interval each time if (isInviteTransaction() && (this instanceof SIPClientTransaction)) { retransmissionTimerTicksLeft = tickCount; } else { // non-INVITE transactions and 3xx-6xx responses are capped at T2 retransmissionTimerTicksLeft = Math.min(tickCount, MAXIMUM_RETRANSMISSION_TICK_COUNT); } retransmissionTimerLastTickCount = retransmissionTimerTicksLeft; } /** * Turns off retransmission events for this transaction. */ protected final void disableRetransmissionTimer() { retransmissionTimerTicksLeft = -1; } /** * Enables a timeout event to occur for this transaction after the number of * ticks passed to this method. * * @param tickCount * Number of ticks before this transaction times out. */ protected final void enableTimeoutTimer(int tickCount) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("enableTimeoutTimer " + this + " tickCount " + tickCount + " currentTickCount = " + timeoutTimerTicksLeft); timeoutTimerTicksLeft = tickCount; } /** * Disabled the timeout timer. */ protected final void disableTimeoutTimer() { timeoutTimerTicksLeft = -1; } /** * Fired after each timer tick. Checks the retransmission and timeout timers * of this transaction, and fired these events if necessary. */ final void fireTimer() { // If the timeout timer is enabled, if (timeoutTimerTicksLeft != -1) { // Count down the timer, and if it has run out, if (--timeoutTimerTicksLeft == 0) { // Fire the timeout timer fireTimeoutTimer(); } } // If the retransmission timer is enabled, if (retransmissionTimerTicksLeft != -1) { // Count down the timer, and if it has run out, if (--retransmissionTimerTicksLeft == 0) { // Enable this timer to fire again after // twice the original time enableRetransmissionTimer(retransmissionTimerLastTickCount * 2); // Fire the timeout timer fireRetransmissionTimer(); } } } /** * Tests if this transaction has terminated. * * @return Trus if this transaction is terminated, false if not. */ public final boolean isTerminated() { return getState() == TERMINATED_STATE; } public String getHost() { return encapsulatedChannel.getHost(); } public String getKey() { return encapsulatedChannel.getKey(); } public int getPort() { return encapsulatedChannel.getPort(); } public SIPTransactionStack getSIPStack() { return (SIPTransactionStack) sipStack; } public String getPeerAddress() { return this.peerAddress; } public int getPeerPort() { return this.peerPort; } // @@@ hagai public int getPeerPacketSourcePort() { return this.peerPacketSourcePort; } public InetAddress getPeerPacketSourceAddress() { return this.peerPacketSourceAddress; } protected InetAddress getPeerInetAddress() { return this.peerInetAddress; } protected String getPeerProtocol() { return this.peerProtocol; } public String getTransport() { return encapsulatedChannel.getTransport(); } public boolean isReliable() { return encapsulatedChannel.isReliable(); } /** * Returns the Via header for this channel. Gets the Via header of the * underlying message channel, and adds a branch parameter to it for this * transaction. */ public Via getViaHeader() { // Via header of the encapulated channel Via channelViaHeader; // Add the branch parameter to the underlying // channel's Via header channelViaHeader = super.getViaHeader(); try { channelViaHeader.setBranch(branch); } catch (java.text.ParseException ex) { } return channelViaHeader; } /** * Process the message through the transaction and sends it to the SIP peer. * * @param messageToSend * Message to send to the SIP peer. */ public void sendMessage(SIPMessage messageToSend) throws IOException { // Use the peer address, port and transport // that was specified when the transaction was // created. Bug was noted by Bruce Evangelder // soleo communications. try { encapsulatedChannel.sendMessage(messageToSend, this.peerInetAddress, this.peerPort); } finally { this.startTransactionTimer(); } } /** * Parse the byte array as a message, process it through the transaction, * and send it to the SIP peer. This is just a placeholder method -- calling * it will result in an IO exception. * * @param messageBytes * Bytes of the message to send. * @param receiverAddress * Address of the target peer. * @param receiverPort * Network port of the target peer. * * @throws IOException * If called. */ protected void sendMessage(byte[] messageBytes, InetAddress receiverAddress, int receiverPort, boolean retry) throws IOException { throw new IOException( "Cannot send unparsed message through Transaction Channel!"); } /** * Adds a new event listener to this transaction. * * @param newListener * Listener to add. */ public void addEventListener(SIPTransactionEventListener newListener) { eventListeners.add(newListener); } /** * Removed an event listener from this transaction. * * @param oldListener * Listener to remove. */ public void removeEventListener(SIPTransactionEventListener oldListener) { eventListeners.remove(oldListener); } /** * Creates a SIPTransactionErrorEvent and sends it to all of the listeners * of this transaction. This method also flags the transaction as * terminated. * * @param errorEventID * ID of the error to raise. */ protected void raiseErrorEvent(int errorEventID) { // Error event to send to all listeners SIPTransactionErrorEvent newErrorEvent; // Iterator through the list of listeners Iterator listenerIterator; // Next listener in the list SIPTransactionEventListener nextListener; // Create the error event newErrorEvent = new SIPTransactionErrorEvent(this, errorEventID); // Loop through all listeners of this transaction synchronized (eventListeners) { listenerIterator = eventListeners.iterator(); while (listenerIterator.hasNext()) { // Send the event to the next listener nextListener = (SIPTransactionEventListener) listenerIterator .next(); nextListener.transactionErrorEvent(newErrorEvent); } } // Clear the event listeners after propagating the error. // Retransmit notifications are just an alert to the // application (they are not an error). if (errorEventID != SIPTransactionErrorEvent.TIMEOUT_RETRANSMIT) { eventListeners.clear(); // Errors always terminate a transaction this.setState(TransactionState.TERMINATED); if (this instanceof SIPServerTransaction && this.isByeTransaction() && this.getDialog() != null) ((SIPDialog) this.getDialog()) .setState(SIPDialog.TERMINATED_STATE); } } /** * A shortcut way of telling if we are a server transaction. */ protected boolean isServerTransaction() { return this instanceof SIPServerTransaction; } /** * Gets the dialog object of this Transaction object. This object returns * null if no dialog exists. A dialog only exists for a transaction when a * session is setup between a User Agent Client and a User Agent Server, * either by a 1xx Provisional Response for an early dialog or a 200OK * Response for a committed dialog. * * @return the Dialog Object of this Transaction object. * @see Dialog */ public abstract Dialog getDialog(); /** * set the dialog object. * * @param sipDialog -- * the dialog to set. * @param dialogId -- * the dialog id ot associate with the dialog.s */ public abstract void setDialog(SIPDialog sipDialog, String dialogId); /** * Returns the current value of the retransmit timer in milliseconds used to * retransmit messages over unreliable transports. * * @return the integer value of the retransmit timer in milliseconds. */ public int getRetransmitTimer() { return SIPTransactionStack.BASE_TIMER_INTERVAL; } /** * Get the host to assign for an outgoing Request via header. */ public String getViaHost() { return this.getViaHeader().getHost(); } /** * Get the last response. This is used internally by the implementation. * Dont rely on it. * * @return the last response received (for client transactions) or sent (for * server transactions). */ public SIPResponse getLastResponse() { return this.lastResponse; } /** * Get the JAIN interface response */ public Response getResponse() { return (Response) this.lastResponse; } /** * Get the transaction Id. */ public String getTransactionId() { return this.transactionId; } /** * Hashcode method for fast hashtable lookup. */ public int hashCode() { if (this.transactionId == null) return -1; else return this.transactionId.hashCode(); } /** * Get the port to assign for the via header of an outgoing message. */ public int getViaPort() { return this.getViaHeader().getPort(); } /** * A method that can be used to test if an incoming request belongs to this * transction. This does not take the transaction state into account when * doing the check otherwise it is identical to isMessagePartOfTransaction. * This is useful for checking if a CANCEL belongs to this transaction. * * @param requestToTest * is the request to test. * @return true if the the request belongs to the transaction. * */ public boolean doesCancelMatchTransaction(SIPRequest requestToTest) { // List of Via headers in the message to test 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; transactionMatches = false; if (this.getOriginalRequest() == null || this.getOriginalRequest().getMethod().equals(Request.CANCEL)) return false; // Get the topmost Via header and its branch parameter viaHeaders = requestToTest.getViaHeaders(); if (viaHeaders != null) { topViaHeader = (Via) viaHeaders.getFirst(); messageBranch = topViaHeader.getBranch(); if (messageBranch != null) { // If the branch parameter exists but // does not start with the magic cookie, if (!messageBranch.toLowerCase().startsWith(SIPConstants.BRANCH_MAGIC_COOKIE_LOWER_CASE)) { // Flags this as old // (RFC2543-compatible) client // version messageBranch = null; } } // If a new branch parameter exists, if (messageBranch != null && this.getBranch() != null) { // If the branch equals the branch in // this message, if (getBranch().equalsIgnoreCase(messageBranch) && topViaHeader.getSentBy().equals( ((Via) getOriginalRequest().getViaHeaders() .getFirst()).getSentBy())) { transactionMatches = true; if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("returning true"); } } else { // If this is an RFC2543-compliant message, // If RequestURI, To tag, From tag, // CallID, CSeq number, and top Via // headers are the same, if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("testing against " + getOriginalRequest()); if (getOriginalRequest().getRequestURI().equals( requestToTest.getRequestURI()) && getOriginalRequest().getTo().equals( requestToTest.getTo()) && getOriginalRequest().getFrom().equals( requestToTest.getFrom()) && getOriginalRequest().getCallId().getCallId().equals( requestToTest.getCallId().getCallId()) && getOriginalRequest().getCSeq().getSeqNumber() == requestToTest .getCSeq().getSeqNumber() && topViaHeader.equals(getOriginalRequest() .getViaHeaders().getFirst())) { transactionMatches = true; } } } // JvB: Need to pass the CANCEL to the listener! Retransmitted INVITEs // set it to false if (transactionMatches) { this.setPassToListener(); } return transactionMatches; } /** * Sets the value of the retransmit timer to the newly supplied timer value. * The retransmit timer is expressed in milliseconds and its default value * is 500ms. This method allows the application to change the transaction * retransmit behavior for different networks. Take the gateway proxy as an * example. The internal intranet is likely to be reatively uncongested and * the endpoints will be relatively close. The external network is the * general Internet. This functionality allows different retransmit times * for either side. * * @param retransmitTimer - * the new integer value of the retransmit timer in milliseconds. */ public void setRetransmitTimer(int retransmitTimer) { if (retransmitTimer <= 0) throw new IllegalArgumentException( "Retransmit timer must be positive!"); if (this.transactionTimerStarted.get()) throw new IllegalStateException( "Transaction timer is already started"); BASE_TIMER_INTERVAL = retransmitTimer; T4 = 5000 / BASE_TIMER_INTERVAL; T2 = 4000 / BASE_TIMER_INTERVAL; TIMER_I = T4; TIMER_K = T4; TIMER_D = 32000 / BASE_TIMER_INTERVAL; } /** * Close the encapsulated channel. */ public void close() { this.encapsulatedChannel.close(); if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("Closing " + this.encapsulatedChannel); } public boolean isSecure() { return encapsulatedChannel.isSecure(); } public MessageProcessor getMessageProcessor() { return this.encapsulatedChannel.getMessageProcessor(); } /** * Set the application data pointer. This is un-interpreted by the stack. * This is provided as a conveniant way of keeping 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 applicationd * data pointer. * */ public void setApplicationData(Object applicationData) { this.applicationData = applicationData; } /** * Get the application data associated with this transaction. * * @return stored application data. */ public Object getApplicationData() { return this.applicationData; } /** * Set the encapsuated channel. The peer inet address and port are set equal * to the message channel. */ public void setEncapsulatedChannel(MessageChannel messageChannel) { this.encapsulatedChannel = messageChannel; this.peerInetAddress = messageChannel.getPeerInetAddress(); this.peerPort = messageChannel.getPeerPort(); } /** * Return the SipProvider for which the transaction is assigned. * * @return the SipProvider for the transaction. */ public SipProviderImpl getSipProvider() { return this.getMessageProcessor().getListeningPoint().getProvider(); } /** * Raise an IO Exception event - this is used for reporting asynchronous IO * Exceptions that are attributable to this transaction. * */ public void raiseIOExceptionEvent() { setState(TransactionState.TERMINATED); String host = getPeerAddress(); int port = getPeerPort(); String transport = getTransport(); IOExceptionEvent exceptionEvent = new IOExceptionEvent(this, host, port, transport); getSipProvider().handleEvent(exceptionEvent, this); } /** * A given tx can process only a single outstanding event at a time. This * semaphore gaurds re-entrancy to the transaction. * */ public boolean acquireSem() { boolean retval = false; try { if (sipStack.getStackLogger().isLoggingEnabled()) { sipStack.getStackLogger().logDebug("acquireSem [[[[" + this); sipStack.getStackLogger().logStackTrace(); } retval = this.semaphore.tryAcquire(1000, TimeUnit.MILLISECONDS); if ( sipStack.isLoggingEnabled()) 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; } } /** * Release the transaction semaphore. * */ public void releaseSem() { try { this.toListener = false; this.semRelease(); } catch (Exception ex) { sipStack.getStackLogger().logError("Unexpected exception releasing sem", ex); } } protected void semRelease() { try { if (sipStack.isLoggingEnabled()) { 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); } } /** * Set true to pass the request up to the listener. False otherwise. * */ public boolean passToListener() { return toListener; } /** * Set the passToListener flag to true. */ public void setPassToListener() { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug("setPassToListener()"); } this.toListener = true; } /** * Flag to test if the terminated event is delivered. * * @return */ protected synchronized boolean testAndSetTransactionTerminatedEvent() { boolean retval = !this.terminatedEventDelivered; this.terminatedEventDelivered = true; return retval; } public String getCipherSuite() throws UnsupportedOperationException { if (this.getMessageChannel() instanceof TLSMessageChannel ) { if ( ((TLSMessageChannel) this.getMessageChannel()).getHandshakeCompletedListener() == null ) return null; else if ( ((TLSMessageChannel) this.getMessageChannel()).getHandshakeCompletedListener().getHandshakeCompletedEvent() == null) return null; else return ((TLSMessageChannel) this.getMessageChannel()).getHandshakeCompletedListener().getHandshakeCompletedEvent().getCipherSuite(); } else throw new UnsupportedOperationException("Not a TLS channel"); } public java.security.cert.Certificate[] getLocalCertificates() throws UnsupportedOperationException { if (this.getMessageChannel() instanceof TLSMessageChannel ) { if ( ((TLSMessageChannel) this.getMessageChannel()).getHandshakeCompletedListener() == null ) return null; else if ( ((TLSMessageChannel) this.getMessageChannel()).getHandshakeCompletedListener().getHandshakeCompletedEvent() == null) return null; else return ((TLSMessageChannel) this.getMessageChannel()).getHandshakeCompletedListener().getHandshakeCompletedEvent().getLocalCertificates(); } else throw new UnsupportedOperationException("Not a TLS channel"); } public java.security.cert.Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException { if (this.getMessageChannel() instanceof TLSMessageChannel ) { if ( ((TLSMessageChannel) this.getMessageChannel()).getHandshakeCompletedListener() == null ) return null; else if ( ((TLSMessageChannel) this.getMessageChannel()).getHandshakeCompletedListener().getHandshakeCompletedEvent() == null) return null; else return ((TLSMessageChannel) this.getMessageChannel()).getHandshakeCompletedListener().getHandshakeCompletedEvent().getPeerCertificates(); } else throw new UnsupportedOperationException("Not a TLS channel"); } /** * Start the timer that runs the transaction state machine. * */ protected abstract void startTransactionTimer(); /** * Tests a message to see if it is part of this transaction. * * @return True if the message is part of this transaction, false if not. */ public abstract boolean isMessagePartOfTransaction(SIPMessage messageToTest); /** * This method is called when this transaction's retransmission timer has * fired. */ protected abstract void fireRetransmissionTimer(); /** * This method is called when this transaction's timeout timer has fired. */ protected abstract void fireTimeoutTimer(); } java/gov/nist/javax/sip/stack/SIPTransactionErrorEvent.java0100644 0000000 0000000 00000004771 13513104763 023043 0ustar000000000 0000000 /* * 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; import java.util.EventObject; /** * An event that indicates that a transaction has encountered an error. * * * @author Jeff Keyser * @author M. Ranganathan * * * * @version 1.2 $Revision: 1.7 $ $Date: 2009/07/17 18:58:15 $ */ public class SIPTransactionErrorEvent extends EventObject { /** * Comment for serialVersionUID */ private static final long serialVersionUID = -2713188471978065031L; /** * This event ID indicates that the transaction has timed out. */ public static final int TIMEOUT_ERROR = 1; /** * This event ID indicates that there was an error sending a message using * the underlying transport. */ public static final int TRANSPORT_ERROR = 2; /** * Retransmit signal to application layer. */ public static final int TIMEOUT_RETRANSMIT = 3; // ID of this error event private int errorID; /** * Creates a transaction error event. * * @param sourceTransaction Transaction which is raising the error. * @param transactionErrorID ID of the error that has ocurred. */ SIPTransactionErrorEvent( SIPTransaction sourceTransaction, int transactionErrorID) { super(sourceTransaction); errorID = transactionErrorID; } /** * Returns the ID of the error. * * @return Error ID. */ public int getErrorID() { return errorID; } } java/gov/nist/javax/sip/stack/SIPTransactionEventListener.java0100644 0000000 0000000 00000003120 13513104763 023522 0ustar000000000 0000000 /* * 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; import java.util.EventListener; /** * Interface implemented by classes that want to be notified of asynchronous * transacion events. * * @author Jeff Keyser * @version 1.2 $Revision: 1.7 $ $Date: 2009/07/17 18:58:15 $ */ public interface SIPTransactionEventListener extends EventListener { /** * Invoked when an error has ocurred with a transaction. * * @param transactionErrorEvent Error event. */ public void transactionErrorEvent(SIPTransactionErrorEvent transactionErrorEvent); } java/gov/nist/javax/sip/stack/SIPTransactionStack.java0100644 0000000 0000000 00000262571 13513104763 022021 0ustar000000000 0000000 /* * 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; import gov.nist.core.Host; import gov.nist.core.HostPort; import gov.nist.core.ServerLogger; import gov.nist.core.StackLogger; import gov.nist.core.ThreadAuditor; import gov.nist.core.net.AddressResolver; import gov.nist.core.net.DefaultNetworkLayer; import gov.nist.core.net.NetworkLayer; import gov.nist.javax.sip.DefaultAddressResolver; import gov.nist.javax.sip.ListeningPointImpl; import gov.nist.javax.sip.LogRecordFactory; import gov.nist.javax.sip.SIPConstants; import gov.nist.javax.sip.SipListenerExt; import gov.nist.javax.sip.SipProviderImpl; import gov.nist.javax.sip.SipStackImpl; import gov.nist.javax.sip.header.Event; import gov.nist.javax.sip.header.Via; import gov.nist.javax.sip.header.extensions.JoinHeader; import gov.nist.javax.sip.header.extensions.ReplacesHeader; import gov.nist.javax.sip.message.SIPMessage; import gov.nist.javax.sip.message.SIPRequest; import gov.nist.javax.sip.message.SIPResponse; 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.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.atomic.AtomicInteger; import javax.sip.ClientTransaction; import javax.sip.Dialog; import javax.sip.DialogState; import javax.sip.DialogTerminatedEvent; import javax.sip.ServerTransaction; import javax.sip.SipException; import javax.sip.SipListener; import javax.sip.TransactionState; import javax.sip.TransactionTerminatedEvent; import javax.sip.address.Hop; import javax.sip.address.Router; import javax.sip.header.CallIdHeader; import javax.sip.header.EventHeader; import javax.sip.message.Request; import javax.sip.message.Response; /* * Jeff Keyser : architectural suggestions and contributions. Pierre De Rop and Thomas Froment : * Bug reports. Jeyashankher < jai@lucent.com > : bug reports. Jeroen van Bemmel : Bug fixes. * * */ /** * * 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.141 $ $Date: 2009/12/17 23:38:27 $ */ public abstract class SIPTransactionStack implements SIPTransactionEventListener, SIPDialogEventListener { /* * 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; /* * Table of retransmission Alert timers. */ protected ConcurrentHashMap retransmissionAlertTransactions; // Table of early dialogs ( to keep identity mapping ) protected ConcurrentHashMap earlyDialogTable; // Table of dialogs. protected ConcurrentHashMap dialogTable; // A set of methods that result in dialog creations. protected static final Set dialogCreatingMethods = new HashSet(); // Global timer. Use this for all timer tasks. private Timer timer; // List of pending server transactions private ConcurrentHashMap pendingTransactions; // hashtable for fast lookup private ConcurrentHashMap clientTransactionTable; // Set to false if you want hiwat and lowat to be consulted. protected boolean unlimitedServerTransactionTableSize = true; // 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. private ConcurrentHashMap serverTransactionTable; // A table of ongoing transactions indexed by mergeId ( for detecting merged // requests. private ConcurrentHashMap mergeTable; private ConcurrentHashMap terminatedServerTransactionsPendingAck; private ConcurrentHashMap forkedClientTransactionTable; /* * 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; /* * Name of the stack. */ protected String stackName; /* * 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; /* * Outbound proxy String ( to be handed to the outbound proxy class on creation). */ protected String outboundProxy; protected String routerPath; // Flag to indicate whether the stack will provide dialog // support. protected boolean isAutomaticDialogSupportEnabled; // The set of events for which subscriptions can be forked. protected HashSet forkedEvents; // Generate a timestamp header for retransmitted requests. protected boolean generateTimeStampHeader; protected AddressResolver addressResolver; // 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; // 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; // / Provides a mechanism for applications to check the health of threads in // the stack protected ThreadAuditor threadAuditor = new ThreadAuditor(); protected LogRecordFactory logRecordFactory; // Set to true if the client CANCEL transaction should be checked before sending // it out. protected boolean cancelClientTransactionChecked = true; // Is to tag reassignment allowed. protected boolean remoteTagReassignmentAllowed = true; protected boolean logStackTraceOnMessageSend = true; // Receive UDP buffer size protected int receiveUdpBufferSize; // Send UDP buffer size protected int sendUdpBufferSize; protected boolean stackDoesCongestionControl = true; protected boolean isBackToBackUserAgent = false; protected boolean checkBranchId; protected boolean isAutomaticDialogErrorHandlingEnabled = true; protected boolean isDialogTerminatedEventDeliveredForNullDialog = false; // 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; // / Timer to regularly ping the thread auditor (on behalf of the timer // thread) class PingTimer extends SIPStackTimerTask { // / Timer thread handle ThreadAuditor.ThreadHandle threadHandle; // / Constructor public PingTimer(ThreadAuditor.ThreadHandle a_oThreadHandle) { threadHandle = a_oThreadHandle; } 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(); } // 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; public RemoveForkedTransactionTimerTask(SIPClientTransaction sipClientTransaction ) { this.clientTransaction = sipClientTransaction; } @Override protected void runTask() { forkedClientTransactionTable.remove(clientTransaction.getTransactionId()); } } 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(); 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); } } /** * Re Initialize the stack instance. */ protected void reInit() { if (stackLogger.isLoggingEnabled()) 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.terminatedServerTransactionsPendingAck = new ConcurrentHashMap(); this.forkedClientTransactionTable = new ConcurrentHashMap(); this.timer = new Timer(); 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); } /** * For debugging -- allows you to disable logging or enable logging selectively. * * */ public void disableLogging() { this.getStackLogger().disableLogging(); } /** * Globally enable message logging ( for debugging) * */ public void enableLogging() { this.getStackLogger().enableLogging(); } /** * Print the dialog table. * */ public void printDialogTable() { if (isLoggingEnabled()) { this.getStackLogger().logDebug("dialog table = " + this.dialogTable); System.out.println("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); } /** * 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()) stackLogger.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()) { stackLogger.logDebug("putDialog: dialog already exists" + dialogId + " in table = " + dialogTable.get(dialogId)); } return; } if (stackLogger.isLoggingEnabled()) { stackLogger.logDebug("putDialog dialogId=" + dialogId + " dialog = " + dialog); } dialog.setStack(this); if (stackLogger.isLoggingEnabled()) stackLogger.logStackTrace(); dialogTable.put(dialogId, 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 (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 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); } } else { retval = new SIPDialog(transaction, sipResponse); } 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); } /** * Remove the dialog from the dialog table. * * @param dialog -- dialog to remove. */ public void removeDialog(SIPDialog dialog) { String id = dialog.getDialogId(); String earlyId = dialog.getEarlyDialogId(); if (earlyId != null) { this.earlyDialogTable.remove(earlyId); this.dialogTable.remove(earlyId); } if (id != null) { // FHT: Remove dialog from table only if its associated dialog is the same as the one // specified Object old = this.dialogTable.get(id); 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. 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); } } else if ( this.isDialogTerminatedEventDeliveredForNullDialog ) { 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); } } } /** * 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()) { stackLogger.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()) { 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()) 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()) { stackLogger.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.from.getTag(); Event hisEvent = ct.event; // Event header is mandatory but some slopply clients // dont include it. if (hisEvent == null) continue; if (stackLogger.isLoggingEnabled()) { stackLogger.logDebug("ct.fromTag = " + fromTag); stackLogger.logDebug("thisToTag = " + thisToTag); stackLogger.logDebug("hisEvent = " + hisEvent); stackLogger.logDebug("eventHdr " + eventHdr); } if ( fromTag.equalsIgnoreCase(thisToTag) && hisEvent != null && eventHdr.match(hisEvent) && notifyMessage.getCallId().getCallId().equalsIgnoreCase( ct.callId.getCallId())) { if (ct.acquireSem()) retval = ct; return retval; } } return retval; } finally { if (stackLogger.isLoggingEnabled()) 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()); } /** * 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); } /** * 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()) getStackLogger().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 (stackLogger.isLoggingEnabled()) getStackLogger().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 ( this.getStackLogger().isLoggingEnabled()) { this.getStackLogger().logDebug("findTransaction: returning : " + retval); } } 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 (stackLogger.isLoggingEnabled()) { 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(); 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 (stackLogger.isLoggingEnabled()) 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; } /** * 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 (this.stackLogger.isLoggingEnabled()) { this.stackLogger.logDebug("looking for pending tx for :" + requestReceived.getTransactionId()); } return (SIPServerTransaction) pendingTransactions.get(requestReceived.getTransactionId()); } /** * 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 SIPServerTransaction findMergedTransaction(SIPRequest sipRequest) { if (! sipRequest.getMethod().equals(Request.INVITE)) { /* * Dont need to worry about request merging for Non-INVITE transactions. */ return null; } String mergeId = sipRequest.getMergeId(); SIPServerTransaction mergedTransaction = (SIPServerTransaction) this.mergeTable.get(mergeId); if (mergeId == null ) { return null; } else if (mergedTransaction != null && !mergedTransaction.isMessagePartOfTransaction(sipRequest) ) { return mergedTransaction; } else { /* * Check the server transactions that have resulted in dialogs. */ for (Dialog dialog: this.dialogTable.values() ) { SIPDialog sipDialog = (SIPDialog) dialog ; if (sipDialog.getFirstTransaction() != null && sipDialog.getFirstTransaction() instanceof ServerTransaction) { SIPServerTransaction serverTransaction = ((SIPServerTransaction) sipDialog.getFirstTransaction()); SIPRequest transactionRequest = ((SIPServerTransaction) sipDialog.getFirstTransaction()).getOriginalRequest(); if ( (! serverTransaction.isMessagePartOfTransaction(sipRequest)) && sipRequest.getMergeId().equals(transactionRequest.getMergeId())) { return (SIPServerTransaction) sipDialog.getFirstTransaction(); } } } return null; } } /** * 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.stackLogger.isLoggingEnabled()) { this.stackLogger.logDebug("removePendingTx: " + tr.getTransactionId()); } this.pendingTransactions.remove(tr.getTransactionId()); } /** * 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()) { this.stackLogger.logDebug("Removing tx from merge table "); } String key = ((SIPRequest) tr.getRequest()).getMergeId(); if (key != null) { this.mergeTable.remove(key); } } /** * 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; } /** * 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; } } } // 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); } } } // Set ths transaction's encapsulated request // interface from the superclass if (stackLogger.isLoggingEnabled()) { stackLogger.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 (isLoggingEnabled()) stackLogger.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; 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; } } // 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"); } // 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.stackLogger.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.stackLogger.isLoggingEnabled()) { this.stackLogger.logDebug("returning null - serverResponseInterface is null!"); } currentTransaction.releaseSem(); return null; } } else { if (stackLogger.isLoggingEnabled()) this.stackLogger.logDebug("Could not aquire semaphore !!"); } if (acquired) return currentTransaction; else return null; } /** * 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; } /** * 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; } /** * 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); } } } /** * 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(); } /** * 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()) stackLogger.logDebug("added transaction " + clientTransaction); addTransactionHash(clientTransaction); } /** * 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()) { stackLogger.logDebug("Removing Transaction = " + sipTransaction.getTransactionId() + " transaction = " + sipTransaction); } if (sipTransaction instanceof SIPServerTransaction) { if (stackLogger.isLoggingEnabled()) 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); sipProvider.handleEvent(event, sipTransaction); } } else { String key = sipTransaction.getTransactionId(); Object removed = clientTransactionTable.remove(key); if (stackLogger.isLoggingEnabled()) { 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); } } } /** * 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()) stackLogger.logDebug("added transaction " + serverTransaction); serverTransaction.map(); addTransactionHash(serverTransaction); } /** * 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); if (stackLogger.isLoggingEnabled()) { stackLogger.logDebug(" putTransactionHash : " + " key = " + key); } } else { String key = sipRequest.getTransactionId(); if (stackLogger.isLoggingEnabled()) { stackLogger.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() { if (this.activeClientTransactionCount.decrementAndGet() <= this.clientTransactionTableLowaterMark && !this.unlimitedClientTransactionTableSize) { synchronized (this.clientTransactionTable) { clientTransactionTable.notify(); } } } /** * 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()) { stackLogger.logStackTrace(); stackLogger.logDebug("removing client Tx : " + key); } clientTransactionTable.remove(key); } else if (sipTransaction instanceof SIPServerTransaction) { String key = sipTransaction.getTransactionId(); serverTransactionTable.remove(key); if (stackLogger.isLoggingEnabled()) { stackLogger.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(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. } } /* * (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(); } } /** * 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(); } 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. } try { Thread.sleep(1000); } catch (InterruptedException ex) { } this.clientTransactionTable.clear(); this.serverTransactionTable.clear(); this.dialogTable.clear(); this.serverLogger.closeLogFile(); } /** * 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()) stackLogger.logDebug("putPendingTransaction: " + tr); this.pendingTransactions.put(tr.getTransactionId(), tr); } /** * 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; } } /** * 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(); } /** * Get the logger. * * @return --the logger for the sip stack. Each stack has its own logger instance. */ public StackLogger getStackLogger() { return this.stackLogger; } /** * 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; } /** * 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; } /** * 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; } } /** * 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); } /** * 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; } /** * 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; } } } /* * (non-Javadoc) * * @see javax.sip.SipStack#getRouter() */ public Router getRouter() { return this.router; } /** * return the status of the toExit flag. * * @return true if the stack object is alive and false otherwise. */ public boolean isAlive() { return !toExit; } /** * 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); } } /** * Removes a MessageProcessor from this SIPStack. * * @param oldMessageProcessor */ protected void removeMessageProcessor(MessageProcessor oldMessageProcessor) { synchronized (messageProcessors) { if (messageProcessors.remove(oldMessageProcessor)) { oldMessageProcessor.stop(); } } } /** * 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]); } } /** * 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 { if (transport.equalsIgnoreCase("udp")) { UDPMessageProcessor udpMessageProcessor = new UDPMessageProcessor(ipAddress, this, port); this.addMessageProcessor(udpMessageProcessor); this.udpFlag = true; return udpMessageProcessor; } else if (transport.equalsIgnoreCase("tcp")) { TCPMessageProcessor tcpMessageProcessor = new TCPMessageProcessor(ipAddress, this, port); this.addMessageProcessor(tcpMessageProcessor); // this.tcpFlag = true; return tcpMessageProcessor; } else if (transport.equalsIgnoreCase("tls")) { TLSMessageProcessor tlsMessageProcessor = new TLSMessageProcessor(ipAddress, this, port); this.addMessageProcessor(tlsMessageProcessor); // this.tlsFlag = true; return tlsMessageProcessor; } else if (transport.equalsIgnoreCase("sctp")) { // Need Java 7 for this, so these classes are packaged in a separate jar // Try to load it indirectly, if fails report an error try { Class mpc = ClassLoader.getSystemClassLoader().loadClass( "gov.nist.javax.sip.stack.sctp.SCTPMessageProcessor" ); MessageProcessor mp = (MessageProcessor) mpc.newInstance(); mp.initialize( ipAddress, port, this ); this.addMessageProcessor(mp); return mp; } catch (ClassNotFoundException e) { throw new IllegalArgumentException("SCTP not supported (needs Java 7 and SCTP jar in classpath)"); } catch ( InstantiationException ie ) { throw new IllegalArgumentException("Error initializing SCTP", ie); } catch ( IllegalAccessException ie ) { throw new IllegalArgumentException("Error initializing SCTP", ie); } } else { throw new IllegalArgumentException("bad transport"); } } /** * Set the message factory. * * @param messageFactory -- messageFactory to set. */ protected void setMessageFactory(StackMessageFactory messageFactory) { this.sipMessageFactory = messageFactory; } /** * 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 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()) { stackLogger.logDebug("isEventForked: " + ename + " returning " + this.forkedEvents.contains(ename)); } return this.forkedEvents.contains(ename); } /** * get the address resolver interface. * * @return -- the registered address resolver. */ public AddressResolver getAddressResolver() { return this.addressResolver; } /** * Set the address resolution interface * * @param addressResolver -- the address resolver to set. */ public void setAddressResolver(AddressResolver addressResolver) { this.addressResolver = addressResolver; } /** * Set the logger factory. * * @param logRecordFactory -- the log record factory to set. */ public void setLogRecordFactory(LogRecordFactory logRecordFactory) { this.logRecordFactory = logRecordFactory; } /** * 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; } /** * 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 (stackLogger.isLoggingEnabled()) stackLogger.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 (isLoggingEnabled()) stackLogger.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; } public void setNon2XXAckPassedToListener(boolean passToListener) { this.non2XXAckPassedToListener = passToListener; } /** * @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(); } public boolean isRfc2543Supported() { return this.rfc2543Supported; } public boolean isCancelClientTransactionChecked() { return this.cancelClientTransactionChecked; } 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()) 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(clientTransaction.getTransactionId(), clientTransaction ); } public SIPClientTransaction getForkedTransaction(String transactionId) { return this.forkedClientTransactionTable.get(transactionId); } } java/gov/nist/javax/sip/stack/ServerLog.java0100644 0000000 0000000 00000043152 13513104763 020072 0ustar000000000 0000000 /* * 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.javax.sip.stack; import gov.nist.core.ServerLogger; import gov.nist.core.StackLogger; import gov.nist.javax.sip.LogRecord; import gov.nist.javax.sip.header.CallID; import gov.nist.javax.sip.message.SIPMessage; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.util.Properties; import javax.sip.SipStack; import javax.sip.header.TimeStampHeader; // BEGIN android-deleted // import org.apache.log4j.Level; // import org.apache.log4j.Logger; // END android-deleted /** * 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.39 $ $Date: 2009/11/11 14:00:58 $ * * @author M. Ranganathan
    * * */ public class ServerLog implements ServerLogger { private boolean logContent; protected StackLogger stackLogger; /** * Name of the log file in which the trace is written out (default is null) */ private String logFileName; /** * Print writer that is used to write out the log file. */ private PrintWriter printWriter; /** * Set auxililary information to log with this trace. */ private String auxInfo; private String description; private String stackIpAddress; private SIPTransactionStack sipStack; private Properties configurationProperties; public ServerLog() { // Debug log file. Whatever gets logged by us also makes its way into debug log. } private void setProperties(Properties configurationProperties) { this.configurationProperties = configurationProperties; // Set a descriptive name for the message trace logger. this.description = configurationProperties.getProperty("javax.sip.STACK_NAME"); this.stackIpAddress = configurationProperties.getProperty("javax.sip.IP_ADDRESS"); this.logFileName = configurationProperties.getProperty("gov.nist.javax.sip.SERVER_LOG"); String logLevel = configurationProperties.getProperty("gov.nist.javax.sip.TRACE_LEVEL"); String logContent = configurationProperties .getProperty("gov.nist.javax.sip.LOG_MESSAGE_CONTENT"); this.logContent = (logContent != null && logContent.equals("true")); if (logLevel != null) { if (logLevel.equals("LOG4J")) { // 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. // BEGIN android-deleted /* 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); } */ // END android-deleted } else { try { int ll; if (logLevel.equals("DEBUG")) { ll = TRACE_DEBUG; } else if (logLevel.equals("INFO")) { ll = TRACE_MESSAGES; } else if (logLevel.equals("ERROR")) { ll = TRACE_EXCEPTION; } else if (logLevel.equals("NONE") || logLevel.equals("OFF")) { ll = TRACE_NONE; } else { ll = Integer.parseInt(logLevel); } this.setTraceLevel(ll); } catch (NumberFormatException ex) { System.out.println("ServerLog: WARNING Bad integer " + logLevel); System.out.println("logging dislabled "); this.setTraceLevel(0); } } } checkLogFile(); } public void setStackIpAddress(String ipAddress) { this.stackIpAddress = ipAddress; } // public static boolean isWebTesterCatchException=false; // public static String webTesterLogFile=null; /** * default trace level */ protected int traceLevel = TRACE_MESSAGES; public synchronized void closeLogFile() { if (printWriter != null) { printWriter.close(); printWriter = null; } } public void checkLogFile() { if (logFileName == null || traceLevel < TRACE_MESSAGES) { // Dont create a log file if tracing is // disabled. return; } try { File logFile = new File(logFileName); if (!logFile.exists()) { logFile.createNewFile(); printWriter = null; } // Append buffer to the end of the file unless otherwise specified // by the user. if (printWriter == null) { boolean overwrite = Boolean.valueOf( configurationProperties.getProperty( "gov.nist.javax.sip.SERVER_LOG_OVERWRITE")); FileWriter fw = new FileWriter(logFileName, !overwrite); printWriter = new PrintWriter(fw, true); printWriter.println(""); printWriter.println("\n "); if (auxInfo != null) { if (sipStack.isLoggingEnabled()) { stackLogger .logDebug("Here are the stack configuration properties \n" + "javax.sip.IP_ADDRESS= " + configurationProperties .getProperty("javax.sip.IP_ADDRESS") + "\n" + "javax.sip.ROUTER_PATH= " + configurationProperties .getProperty("javax.sip.ROUTER_PATH") + "\n" + "javax.sip.OUTBOUND_PROXY= " + configurationProperties .getProperty("javax.sip.OUTBOUND_PROXY") + "\n" + "gov.nist.javax.sip.CACHE_CLIENT_CONNECTIONS= " + configurationProperties .getProperty("gov.nist.javax.sip.CACHE_CLIENT_CONNECTIONS") + "\n" + "gov.nist.javax.sip.CACHE_SERVER_CONNECTIONS= " + configurationProperties .getProperty("gov.nist.javax.sip.CACHE_SERVER_CONNECTIONS") + "\n" + "gov.nist.javax.sip.REENTRANT_LISTENER= " + configurationProperties .getProperty("gov.nist.javax.sip.REENTRANT_LISTENER") + "gov.nist.javax.sip.THREAD_POOL_SIZE= " + configurationProperties .getProperty("gov.nist.javax.sip.THREAD_POOL_SIZE") + "\n"); stackLogger.logDebug(" ]]> "); stackLogger.logDebug(""); stackLogger.logDebug("\n "); stackLogger.logDebug(""); stackLogger.logDebug(""); stackLogger.logDebug(""); stackLogger.logDebug("\n"); stackLogger.logDebug(""); stackLogger.logDebug("= TRACE_EXCEPTION) { checkLogFile(); ex.printStackTrace(); if (printWriter != null) ex.printStackTrace(printWriter); } } /** * Set the trace level for the stack. * * @param level -- the trace level to set. The following trace levels are supported: *
      *
    • 0 -- no tracing
    • * *
    • 16 -- trace messages only
    • * *
    • 32 Full tracing including debug messages.
    • * *
    */ public void setTraceLevel(int level) { traceLevel = level; } /** * Get the trace level for the stack. * * @return the trace level */ public int getTraceLevel() { return traceLevel; } /** * Set aux information. Auxiliary information may be associated with the log file. This is * useful for remote logs. * * @param auxInfo -- auxiliary information. */ public void setAuxInfo(String auxInfo) { this.auxInfo = auxInfo; } public void setSipStack(SipStack sipStack) { if(sipStack instanceof SIPTransactionStack) { this.sipStack = (SIPTransactionStack)sipStack; this.stackLogger = this.sipStack.getStackLogger(); } else throw new IllegalArgumentException("sipStack must be a SIPTransactionStack"); } public void setStackProperties(Properties stackProperties) { setProperties(stackProperties); } public void setLevel(int jsipLoggingLevel) { } } java/gov/nist/javax/sip/stack/ServerRequestInterface.java0100644 0000000 0000000 00000004521 13513104763 022617 0ustar000000000 0000000 /* * 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.javax.sip.stack; import gov.nist.javax.sip.message.*; /** * An interface for a genereic message processor for SIP Request messages. * This is implemented by the application. The stack calls the message * factory with a pointer to the parsed structure to create one of these * and then calls processRequest on the newly created SIPServerRequest * It is the applications responsibility to take care of what needs to be * done to actually process the request. * * @version 1.2 $Revision: 1.4 $ $Date: 2009/07/17 18:58:15 $ * * @author M. Ranganathan
    * * * */ public interface ServerRequestInterface { /** * Process the message. This incorporates a feature request * by Salvador Rey Calatayud * @param sipRequest is the incoming SIP Request. * @param incomingChannel is the incoming message channel (parameter * added in response to a request by Salvador Rey Calatayud.) */ public void processRequest( SIPRequest sipRequest, MessageChannel incomingChannel); } java/gov/nist/javax/sip/stack/ServerResponseInterface.java0100644 0000000 0000000 00000005150 13513104763 022764 0ustar000000000 0000000 /* * 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.javax.sip.stack; import gov.nist.javax.sip.message.*; /* * Salvador Rey Calatayud suggested adding a parameter to the processRequest/processResponse * methods. */ /** * An interface for a genereic message processor for SIP Response messages. * This is implemented by the application. The stack calls the message * factory with a pointer to the parsed structure to create one of these * and then calls processResponse on the newly created SIPServerResponse * It is the applications responsibility to take care of what needs to be * done to actually process the response. * * @version 1.2 $Revision: 1.4 $ $Date: 2009/07/17 18:58:15 $ * * @author M. Ranganathan
    * * * */ public interface ServerResponseInterface { /** * Process the Response. * @param incomingChannel is the incoming message channel * @param sipResponse is the responseto process. * @param sipDialog -- dialog for this response */ public void processResponse( SIPResponse sipResponse, MessageChannel incomingChannel, SIPDialog sipDialog); /** * This method is called prior to dialog assignment. * @param sipResponse * @param incomingChannel */ public void processResponse( SIPResponse sipResponse, MessageChannel incomingChannel); } java/gov/nist/javax/sip/stack/StackMessageFactory.java0100644 0000000 0000000 00000005124 13513104763 022061 0ustar000000000 0000000 /* * 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.javax.sip.stack; import gov.nist.javax.sip.message.*; /** * An interface for generating new requests and responses. This is implemented * by the application and called by the stack for processing requests * and responses. When a Request comes in off the wire, the stack calls * newSIPServerRequest which is then responsible for processing the request. * When a response comes off the wire, the stack calls newSIPServerResponse * to process the response. * * @version 1.2 $Revision: 1.5 $ $Date: 2009/07/17 18:58:15 $ * * @author M. Ranganathan
    * * * */ public interface StackMessageFactory { /** * Make a new SIPServerResponse given a SIPRequest and a message * channel. * * @param sipRequest is the incoming request. * @param msgChan is the message channel on which this request was * received. */ public ServerRequestInterface newSIPServerRequest( SIPRequest sipRequest, MessageChannel msgChan); /** * Generate a new server response for the stack. * * @param sipResponse is the incoming response. * @param msgChan is the message channel on which the response was * received. */ public ServerResponseInterface newSIPServerResponse( SIPResponse sipResponse, MessageChannel msgChan); } java/gov/nist/javax/sip/stack/TCPMessageChannel.java0100644 0000000 0000000 00000071346 13513104763 021414 0ustar000000000 0000000 /* * 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.javax.sip.stack; 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; /* * Ahmet Uyar sent in a bug report for TCP operation of the JAIN sipStack. * Niklas Uhrberg suggested that a mechanism be added to limit the number of simultaneous open * connections. The TLS Adaptations were contributed by Daniel Martinez. Hagai Sela contributed a * bug fix for symmetric nat. Jeroen van Bemmel added compensation for buggy clients ( Microsoft * RTC clients ). Bug fixes by viswashanti.kadiyala@antepo.com, Joost Yervante Damand */ /** * 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.59 $ $Date: 2009/11/20 04:45:53 $ */ public class TCPMessageChannel extends MessageChannel implements SIPMessageListener, Runnable, RawMessageChannel { private Socket mySock; private PipelinedMsgParser myParser; protected InputStream myClientInputStream; // just to pass to thread. protected OutputStream myClientOutputStream; protected String key; protected boolean isCached; protected boolean isRunning; private Thread mythread; protected SIPTransactionStack sipStack; protected String myAddress; protected int myPort; protected InetAddress peerAddress; protected int peerPort; protected String peerProtocol; // Incremented whenever a transaction gets assigned // to the message channel and decremented when // a transaction gets freed from the message channel. // protected int useCount; private TCPMessageProcessor tcpMessageProcessor; protected TCPMessageChannel(SIPTransactionStack sipStack) { this.sipStack = 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 */ protected TCPMessageChannel(Socket sock, SIPTransactionStack sipStack, TCPMessageProcessor msgProcessor) throws IOException { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug("creating new TCPMessageChannel "); sipStack.getStackLogger().logStackTrace(); } mySock = sock; peerAddress = mySock.getInetAddress(); myAddress = msgProcessor.getIpAddress().getHostAddress(); myClientInputStream = mySock.getInputStream(); myClientOutputStream = mySock.getOutputStream(); mythread = new Thread(this); mythread.setDaemon(true); mythread.setName("TCPMessageChannelThread"); // Stash away a pointer to our sipStack structure. this.sipStack = sipStack; this.peerPort = mySock.getPort(); this.tcpMessageProcessor = msgProcessor; this.myPort = this.tcpMessageProcessor.getPort(); // Bug report by Vishwashanti Raj Kadiayl super.messageProcessor = msgProcessor; // Can drop this after response is sent potentially. mythread.start(); } /** * 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 (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug("creating new TCPMessageChannel "); sipStack.getStackLogger().logStackTrace(); } this.peerAddress = inetAddr; this.peerPort = port; this.myPort = messageProcessor.getPort(); this.peerProtocol = "TCP"; this.sipStack = sipStack; this.tcpMessageProcessor = messageProcessor; this.myAddress = messageProcessor.getIpAddress().getHostAddress(); // Bug report by Vishwashanti Raj Kadiayl this.key = MessageChannel.getKey(peerAddress, peerPort, "TCP"); super.messageProcessor = messageProcessor; } /** * Returns "true" as this is a reliable transport. */ public boolean isReliable() { return true; } /** * Close the message channel. */ public void close() { try { if (mySock != null) { mySock.close(); mySock = null; } if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("Closing message Channel " + this); } catch (IOException ex) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("Error closing socket " + ex); } } /** * Get my SIP Stack. * * @return The SIP Stack for this message channel. */ public SIPTransactionStack getSIPStack() { return sipStack; } /** * get the transport string. * * @return "tcp" in this case. */ public String getTransport() { return "TCP"; } /** * 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. */ public String getPeerAddress() { if (peerAddress != null) { return peerAddress.getHostAddress(); } else return getHost(); } protected InetAddress getPeerInetAddress() { return peerAddress; } public String getPeerProtocol() { return this.peerProtocol; } /** * 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 retry) throws IOException { /* * 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 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. // (could have replied via udp but received via tcp!). // if (mySock == null && s != null) { // this.uncache(); // } else if (sock != mySock && sock != null) { try { if (mySock != null) mySock.close(); } catch (IOException ex) { } mySock = sock; this.myClientInputStream = mySock.getInputStream(); this.myClientOutputStream = mySock.getOutputStream(); Thread thread = new Thread(this); thread.setDaemon(true); thread.setName("TCPMessageChannelThread"); thread.start(); } } /** * 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(SIPMessage sipMessage) throws IOException { 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 */true); 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. */ 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) { if (mySock != null) { /* * Delay the close of the socket for some time in case it is being used. */ sipStack.getTimer().schedule(new TimerTask() { @Override public boolean cancel() { try { mySock.close(); super.cancel(); } catch (IOException ex) { } return true; } @Override public void run() { try { mySock.close(); } catch (IOException ex) { } } }, 8000); } mySock = sock; this.myClientInputStream = mySock.getInputStream(); this.myClientOutputStream = mySock.getOutputStream(); // start a new reader on this end of the pipe. Thread mythread = new Thread(this); mythread.setDaemon(true); mythread.setName("TCPMessageChannelThread"); mythread.start(); } } /** * 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 (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(RequestLine.class) || hdrClass .equals(StatusLine.class))) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "Encountered Bad Message \n" + sipMessage.toString()); } // JvB: send a 400 response for requests (except ACK) // Currently only UDP, @todo also other transports String msgString = sipMessage.toString(); if (!msgString.startsWith("SIP/") && !msgString.startsWith("ACK ")) { String badReqRes = createBadReqRes(msgString, ex); if (badReqRes != null) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug("Sending automatic 400 Bad Request:"); sipStack.getStackLogger().logDebug(badReqRes); } try { this.sendMessage(badReqRes.getBytes(), this.getPeerInetAddress(), this .getPeerPort(), false); } catch (IOException e) { this.sipStack.getStackLogger().logException(e); } } else { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "Could not formulate automatic 400 Bad Request"); } } } throw ex; } else { sipMessage.addUnparsed(header); } } /** * 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) { String badmsg = sipMessage.encode(); if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug(">>> Dropped Bad Msg"); sipStack.getStackLogger().logDebug(badmsg); } return; } ViaList viaList = sipMessage.getViaHeaders(); // For a request // first via header tells where the message is coming from. // For response, this has already been recorded in the outgoing // message. if (sipMessage instanceof SIPRequest) { Via v = (Via) viaList.getFirst(); Hop hop = sipStack.addressResolver.resolveAddress(v.getHop()); this.peerProtocol = v.getTransport(); try { this.peerAddress = mySock.getInetAddress(); // Check to see if the received parameter matches // the peer address and tag it appropriately. // JvB: dont do this. It is both costly and incorrect // Must set received also when it is a FQDN, regardless // whether // it resolves to the correct IP address // 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()); } // @@@ hagai // JvB: technically, may only do this when Via already // contains // rport v.setParameter(Via.RPORT, Integer.toString(this.peerPort)); } catch (java.text.ParseException ex) { InternalErrorHandler.handleException(ex, sipStack.getStackLogger()); } // Use this for outgoing messages as well. if (!this.isCached) { ((TCPMessageProcessor) this.messageProcessor).cacheMessageChannel(this); this.isCached = true; int remotePort = ((java.net.InetSocketAddress) mySock.getRemoteSocketAddress()).getPort(); String key = IOHandler.makeKey(mySock.getInetAddress(), remotePort); sipStack.ioHandler.putSocket(key, mySock); } } // Foreach part of the request header, fetch it and process it long receptionTime = System.currentTimeMillis(); if (sipMessage instanceof SIPRequest) { // This is a request - process the request. SIPRequest sipRequest = (SIPRequest) sipMessage; // Create a new sever side request processor for this // message and let it handle the rest. if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug("----Processing Message---"); } // Check for reasonable size - reject message // if it is too long. 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 .getMaxMessageSize()) { SIPResponse sipResponse = sipRequest .createResponse(SIPResponse.MESSAGE_TOO_LARGE); byte[] resp = sipResponse.encodeAsBytes(this.getTransport()); this.sendMessage(resp, false); throw new Exception("Message size exceeded"); } ServerRequestInterface sipServerRequest = sipStack.newSIPServerRequest( sipRequest, this); if (sipServerRequest != null) { try { sipServerRequest.processRequest(sipRequest, this); } finally { if (sipServerRequest instanceof SIPTransaction) { SIPServerTransaction sipServerTx = (SIPServerTransaction) sipServerRequest; if (!sipServerTx.passToListener()) ((SIPTransaction) sipServerRequest).releaseSem(); } } } else { if (sipStack.isLoggingEnabled()) this.sipStack.getStackLogger() .logWarning("Dropping request -- could not acquire semaphore in 10 sec"); } } else { SIPResponse sipResponse = (SIPResponse) sipMessage; // JvB: dont do this // if (sipResponse.getStatusCode() == 100) // sipResponse.getTo().removeParameter("tag"); try { sipResponse.checkHeaders(); } catch (ParseException ex) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger() .logError("Dropping Badly formatted response message >>> " + sipResponse); return; } // This is a response message - process it. // Check the size of the response. // If it is too large dump it silently. if (sipStack.getMaxMessageSize() > 0 && sipResponse.getSize() + (sipResponse.getContentLength() == null ? 0 : sipResponse .getContentLength().getContentLength()) > sipStack .getMaxMessageSize()) { if (sipStack.isLoggingEnabled()) this.sipStack.getStackLogger().logDebug("Message size exceeded"); return; } ServerResponseInterface sipServerResponse = sipStack.newSIPServerResponse( sipResponse, this); if (sipServerResponse != null) { try { if (sipServerResponse instanceof SIPClientTransaction && !((SIPClientTransaction) sipServerResponse) .checkFromTag(sipResponse)) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger() .logError("Dropping response message with invalid tag >>> " + sipResponse); return; } sipServerResponse.processResponse(sipResponse, this); } finally { if (sipServerResponse instanceof SIPTransaction && !((SIPTransaction) sipServerResponse).passToListener()) ((SIPTransaction) sipServerResponse).releaseSem(); } } else { sipStack .getStackLogger() .logWarning( "Application is blocked -- could not acquire semaphore -- dropping response"); } } } finally { } } /** * 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; // 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(this, hispipe, this.sipStack.getMaxMessageSize()); // Start running the parser thread. myParser.processInput(); // bug fix by Emmanuel Proulx int bufferSize = 4096; this.tcpMessageProcessor.useCount++; this.isRunning = true; try { while (true) { try { byte[] msg = new byte[bufferSize]; int nbytes = myClientInputStream.read(msg, 0, bufferSize); // no more bytes to read... if (nbytes == -1) { hispipe.write("\r\n\r\n".getBytes("UTF-8")); try { if (sipStack.maxConnections != -1) { synchronized (tcpMessageProcessor) { tcpMessageProcessor.nConnections--; tcpMessageProcessor.notify(); } } hispipe.close(); mySock.close(); } catch (IOException ioex) { } return; } hispipe.write(msg, 0, nbytes); } catch (IOException ex) { // Terminate the message. try { hispipe.write("\r\n\r\n".getBytes("UTF-8")); } catch (Exception e) { // InternalErrorHandler.handleException(e); } try { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("IOException closing sock " + ex); try { if (sipStack.maxConnections != -1) { synchronized (tcpMessageProcessor) { tcpMessageProcessor.nConnections--; // System.out.println("Notifying!"); tcpMessageProcessor.notify(); } } mySock.close(); hispipe.close(); } catch (IOException ioex) { } } catch (Exception ex1) { // Do nothing. } return; } catch (Exception ex) { InternalErrorHandler.handleException(ex, sipStack.getStackLogger()); } } } finally { this.isRunning = false; this.tcpMessageProcessor.remove(this); this.tcpMessageProcessor.useCount--; myParser.close(); } } protected void uncache() { if (isCached && !isRunning) { this.tcpMessageProcessor.remove(this); } } /** * Equals predicate. * * @param other is the other object to compare ourselves to for equals */ public boolean equals(Object other) { if (!this.getClass().equals(other.getClass())) return false; else { TCPMessageChannel that = (TCPMessageChannel) other; if (this.mySock != that.mySock) return false; else return true; } } /** * 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"); return this.key; } } /** * Get the host to assign to outgoing messages. * * @return the host to assign to the via header. */ public String getViaHost() { 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 myPort; } /** * Get the port of the peer to whom we are sending messages. * * @return the peer port. */ public int getPeerPort() { return peerPort; } public int getPeerPacketSourcePort() { return this.peerPort; } public InetAddress getPeerPacketSourceAddress() { return this.peerAddress; } /** * TCP Is not a secure protocol. */ public boolean isSecure() { return false; } } java/gov/nist/javax/sip/stack/TCPMessageProcessor.java0100644 0000000 0000000 00000023502 13513104763 022012 0ustar000000000 0000000 /* * 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.javax.sip.stack; import java.net.Socket; import java.net.ServerSocket; import java.io.IOException; import java.net.SocketException; import gov.nist.core.*; import java.net.*; import java.util.*; /* * Acknowledgement: Jeff Keyser suggested that a Stop mechanism be added to this. Niklas Uhrberg * suggested that a means to limit the number of simultaneous active connections should be added. * Mike Andrews suggested that the thread be accessible so as to implement clean stop using * Thread.join(). Roger M. Persson contributed a bug fix for cleanup on stop(). * */ /** * Sit in a loop waiting for incoming tcp connections and start a new thread to handle each new * connection. This is the active object that creates new TCP MessageChannels (one for each new * accept socket). * * @version 1.2 $Revision: 1.31 $ $Date: 2009/08/31 16:18:00 $ * * @author M. Ranganathan
    * * */ public class TCPMessageProcessor extends MessageProcessor { protected int nConnections; private boolean isRunning; private Hashtable tcpMessageChannels; private ArrayList incomingTcpMessageChannels; private ServerSocket sock; protected int useCount; /** * Constructor. * * @param sipStack SIPStack structure. * @param port port where this message processor listens. */ protected TCPMessageProcessor(InetAddress ipAddress, SIPTransactionStack sipStack, int port) { super(ipAddress, port, "tcp",sipStack); this.sipStack = sipStack; this.tcpMessageChannels = new Hashtable(); this.incomingTcpMessageChannels = new ArrayList(); } /** * Start the processor. */ public void start() throws IOException { Thread thread = new Thread(this); thread.setName("TCPMessageProcessorThread"); thread.setPriority(Thread.MAX_PRIORITY); thread.setDaemon(true); this.sock = sipStack.getNetworkLayer().createServerSocket(getPort(), 0, getIpAddress()); if (getIpAddress().getHostAddress().equals(IN_ADDR_ANY) || getIpAddress().getHostAddress().equals(IN6_ADDR_ANY)) { // Store the address to which we are actually bound super.setIpAddress(sock.getInetAddress()); } this.isRunning = true; thread.start(); } /** * Run method for the thread that gets created for each accept socket. */ public void run() { // Accept new connectins on our socket. while (this.isRunning) { try { synchronized (this) { // sipStack.maxConnections == -1 means we are // willing to handle an "infinite" number of // simultaneous connections (no resource limitation). // This is the default behavior. while (sipStack.maxConnections != -1 && this.nConnections >= sipStack.maxConnections) { try { this.wait(); if (!this.isRunning) return; } catch (InterruptedException ex) { break; } } this.nConnections++; } Socket newsock = sock.accept(); if (sipStack.isLoggingEnabled()) { 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)); } catch (SocketException ex) { this.isRunning = false; } catch (IOException ex) { // Problem accepting connection. if (sipStack.isLoggingEnabled()) getSIPStack().getStackLogger().logException(ex); continue; } catch (Exception ex) { InternalErrorHandler.handleException(ex); } } } /** * Return the transport string. * * @return the transport string */ public String getTransport() { return "tcp"; } /** * Returns the stack. * * @return my sip stack. */ public SIPTransactionStack getSIPStack() { return sipStack; } /** * Stop the message processor. Feature suggested by Jeff Keyser. */ public synchronized void stop() { isRunning = false; // this.listeningPoint = null; try { sock.close(); } catch (IOException e) { e.printStackTrace(); } Collection en = tcpMessageChannels.values(); for (Iterator it = en.iterator(); it.hasNext();) { TCPMessageChannel next = (TCPMessageChannel) it.next(); next.close(); } // RRPN: fix for (Iterator incomingMCIterator = incomingTcpMessageChannels.iterator(); incomingMCIterator .hasNext();) { TCPMessageChannel next = (TCPMessageChannel) incomingMCIterator.next(); next.close(); } this.notify(); } protected synchronized void remove(TCPMessageChannel tcpMessageChannel) { String key = tcpMessageChannel.getKey(); if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug(Thread.currentThread() + " removing " + key); } /** May have been removed already */ if (tcpMessageChannels.get(key) == tcpMessageChannel) { this.tcpMessageChannels.remove(key); } incomingTcpMessageChannels.remove(tcpMessageChannel); } public synchronized MessageChannel createMessageChannel(HostPort targetHostPort) throws IOException { String key = MessageChannel.getKey(targetHostPort, "TCP"); if (tcpMessageChannels.get(key) != null) { return (TCPMessageChannel) this.tcpMessageChannels.get(key); } else { TCPMessageChannel retval = new TCPMessageChannel(targetHostPort.getInetAddress(), targetHostPort.getPort(), sipStack, this); this.tcpMessageChannels.put(key, retval); retval.isCached = true; if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug("key " + key); sipStack.getStackLogger().logDebug("Creating " + retval); } return retval; } } protected synchronized void cacheMessageChannel(TCPMessageChannel messageChannel) { String key = messageChannel.getKey(); TCPMessageChannel currentChannel = (TCPMessageChannel) tcpMessageChannels.get(key); if (currentChannel != null) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("Closing " + key); currentChannel.close(); } if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("Caching " + key); this.tcpMessageChannels.put(key, messageChannel); } public synchronized MessageChannel createMessageChannel(InetAddress host, int port) throws IOException { try { String key = MessageChannel.getKey(host, port, "TCP"); if (tcpMessageChannels.get(key) != null) { return (TCPMessageChannel) this.tcpMessageChannels.get(key); } else { TCPMessageChannel retval = new TCPMessageChannel(host, port, sipStack, this); this.tcpMessageChannels.put(key, retval); retval.isCached = true; if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug("key " + key); sipStack.getStackLogger().logDebug("Creating " + retval); } return retval; } } catch (UnknownHostException ex) { throw new IOException(ex.getMessage()); } } /** * TCP can handle an unlimited number of bytes. */ public int getMaximumMessageSize() { return Integer.MAX_VALUE; } public boolean inUse() { return this.useCount != 0; } /** * Default target port for TCP */ public int getDefaultTargetPort() { return 5060; } /** * TCP is not a secure protocol. */ public boolean isSecure() { return false; } } java/gov/nist/javax/sip/stack/TLSMessageChannel.java0100644 0000000 0000000 00000071226 13513104763 021425 0ustar000000000 0000000 /* * 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 * * . * */ /* This class is entirely derived from TCPMessageChannel, * by making some minor changes. Daniel J. Martinez Manzano * made these changes. Ahmet Uyar * sent in a bug report for TCP operation of the * JAIN sipStack. Niklas Uhrberg suggested that a mechanism be added to * limit the number of simultaneous open connections. The TLS * Adaptations were contributed by Daniel Martinez. Hagai Sela * contributed a bug fix for symmetric nat. Jeroen van Bemmel * 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. */ /****************************************************************************** * Product of NIST/ITL Advanced Networking Technologies Division (ANTD). * ******************************************************************************/ package gov.nist.javax.sip.stack; 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 javax.net.ssl.HandshakeCompletedListener; import javax.net.ssl.SSLSocket; import javax.sip.address.Hop; 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. * * @see gov.nist.javax.sip.parser.PipelinedMsgParser * * * @author M. Ranganathan * * * @version 1.2 $Revision: 1.27 $ $Date: 2010/01/10 00:13:14 $ */ public final class TLSMessageChannel extends MessageChannel implements SIPMessageListener, Runnable, RawMessageChannel { private Socket mySock; private PipelinedMsgParser myParser; private InputStream myClientInputStream; // just to pass to thread. private String key; protected boolean isCached; protected boolean isRunning; private Thread mythread; private String myAddress; private int myPort; private InetAddress peerAddress; private int peerPort; private String peerProtocol; // Incremented whenever a transaction gets assigned // to the message channel and decremented when // a transaction gets freed from the message channel. // protected int useCount = 0; private TLSMessageProcessor tlsMessageProcessor; private SIPTransactionStack sipStack; 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. * * @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 msgProcessor -- the message processor that created us. */ protected TLSMessageChannel(Socket sock, SIPTransactionStack sipStack, TLSMessageProcessor msgProcessor) throws IOException { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug("creating new TLSMessageChannel (incoming)"); sipStack.getStackLogger().logStackTrace(); } mySock = (SSLSocket) sock; if ( sock instanceof SSLSocket ) { SSLSocket sslSock = (SSLSocket) sock; sslSock.setNeedClientAuth(true); this.handshakeCompletedListener = new HandshakeCompletedListenerImpl(this); sslSock.addHandshakeCompletedListener(this.handshakeCompletedListener); sslSock.startHandshake(); } peerAddress = mySock.getInetAddress(); myAddress = msgProcessor.getIpAddress().getHostAddress(); myClientInputStream = mySock.getInputStream(); mythread = new Thread(this); mythread.setDaemon(true); 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(); // Bug report by Vishwashanti Raj Kadiayl super.messageProcessor = msgProcessor; // Can drop this after response is sent potentially. mythread.start(); } /** * 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. */ protected TLSMessageChannel(InetAddress inetAddr, int port, SIPTransactionStack sipStack, TLSMessageProcessor messageProcessor) throws IOException { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug("creating new TLSMessageChannel (outgoing)"); sipStack.getStackLogger().logStackTrace(); } this.peerAddress = inetAddr; this.peerPort = port; this.myPort = messageProcessor.getPort(); this.peerProtocol = "TLS"; this.sipStack = sipStack; this.tlsMessageProcessor = messageProcessor; this.myAddress = messageProcessor.getIpAddress().getHostAddress(); this.key = MessageChannel.getKey(peerAddress, peerPort, "TLS"); super.messageProcessor = messageProcessor; } /** * Returns "true" as this is a reliable transport. */ public boolean isReliable() { return true; } /** * Close the message channel. */ public void close() { try { if (mySock != null) mySock.close(); if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("Closing message Channel " + this); } catch (IOException ex) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("Error closing socket " + ex); } } /** * Get my SIP Stack. * * @return The SIP Stack for this message channel. */ public SIPTransactionStack getSIPStack() { return sipStack; } /** * get the transport string. * * @return "tcp" in this case. */ public String getTransport() { return "tls"; } /** * 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. */ public String getPeerAddress() { if (peerAddress != null) { return peerAddress.getHostAddress(); } else return getHost(); } protected InetAddress getPeerInetAddress() { return peerAddress; } public String getPeerProtocol() { return this.peerProtocol; } /** * 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 retry) throws IOException { 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) { try { if (mySock != null) mySock.close(); } catch (IOException ex) { } mySock = sock; this.myClientInputStream = mySock.getInputStream(); Thread thread = new Thread(this); thread.setDaemon(true); thread.setName("TLSMessageChannelThread"); thread.start(); } } /** * 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(SIPMessage sipMessage) throws IOException { byte[] msg = sipMessage.encodeAsBytes(this.getTransport()); long time = System.currentTimeMillis(); this.sendMessage(msg, sipMessage instanceof SIPRequest); 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. */ 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); // // 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) { try { if (mySock != null) mySock.close(); } catch (IOException ex) { /* ignore */ } mySock = sock; this.myClientInputStream = mySock.getInputStream(); // start a new reader on this end of the pipe. Thread mythread = new Thread(this); mythread.setDaemon(true); mythread.setName("TLSMessageChannelThread"); mythread.start(); } } /** * 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 (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(RequestLine.class) || hdrClass .equals(StatusLine.class))) { if (sipStack.isLoggingEnabled()) 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 (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug("Sending automatic 400 Bad Request:"); sipStack.getStackLogger().logDebug(badReqRes); } try { this.sendMessage(badReqRes.getBytes(), this.getPeerInetAddress(), this .getPeerPort(), false); } catch (IOException e) { this.sipStack.getStackLogger().logException(e); } } else { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "Could not formulate automatic 400 Bad Request"); } } } throw ex; } else { sipMessage.addUnparsed(header); } } /** * 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). * * Jvb: note that this code is identical to TCPMessageChannel, refactor some day */ public void processMessage(SIPMessage sipMessage) throws Exception { try { if (sipMessage.getFrom() == null || sipMessage.getTo() == null || sipMessage.getCallId() == null || sipMessage.getCSeq() == null || sipMessage.getViaHeaders() == null) { String badmsg = sipMessage.encode(); if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logError("bad message " + badmsg); sipStack.getStackLogger().logError(">>> Dropped Bad Msg"); } return; } ViaList viaList = sipMessage.getViaHeaders(); // For a request // first via header tells where the message is coming from. // For response, this has already been recorded in the outgoing // message. if (sipMessage instanceof SIPRequest) { Via v = (Via) viaList.getFirst(); // the peer address and tag it appropriately. Hop hop = sipStack.addressResolver.resolveAddress(v.getHop()); this.peerProtocol = v.getTransport(); try { 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 // it resolves to the correct IP address // 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()); } // @@@ hagai // JvB: technically, may only do this when Via already contains // rport v.setParameter(Via.RPORT, Integer.toString(this.peerPort)); } catch (java.text.ParseException ex) { InternalErrorHandler.handleException(ex); } // Use this for outgoing messages as well. if (!this.isCached) { ((TLSMessageProcessor) this.messageProcessor).cacheMessageChannel(this); this.isCached = true; String key = IOHandler.makeKey(mySock.getInetAddress(), this.peerPort); sipStack.ioHandler.putSocket(key, mySock); } } // Foreach part of the request header, fetch it and process it long receptionTime = System.currentTimeMillis(); // if (sipMessage instanceof SIPRequest) { // This is a request - process the request. SIPRequest sipRequest = (SIPRequest) sipMessage; // Create a new sever side request processor for this // message and let it handle the rest. if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug("----Processing Message---"); } if (this.sipStack.getStackLogger().isLoggingEnabled(ServerLogger.TRACE_MESSAGES)) { 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 .getMaxMessageSize()) { SIPResponse sipResponse = sipRequest .createResponse(SIPResponse.MESSAGE_TOO_LARGE); byte[] resp = sipResponse.encodeAsBytes(this.getTransport()); this.sendMessage(resp, false); throw new Exception("Message size exceeded"); } // Stack could not create a new server request interface. // maybe not enough resources. ServerRequestInterface sipServerRequest = sipStack.newSIPServerRequest( sipRequest, this); if (sipServerRequest != null) { try { sipServerRequest.processRequest(sipRequest, this); } finally { if (sipServerRequest instanceof SIPTransaction) { SIPServerTransaction sipServerTx = (SIPServerTransaction) sipServerRequest; if (!sipServerTx.passToListener()) ((SIPTransaction) sipServerRequest).releaseSem(); } } } else { SIPResponse response = sipRequest .createResponse(Response.SERVICE_UNAVAILABLE); RetryAfter retryAfter = new RetryAfter(); // Be a good citizen and send a decent response code back. try { retryAfter.setRetryAfter((int) (10 * (Math.random()))); response.setHeader(retryAfter); this.sendMessage(response); } catch (Exception e) { // IGNore } if (sipStack.isLoggingEnabled()) sipStack.getStackLogger() .logWarning("Dropping message -- could not acquire semaphore"); } } else { SIPResponse sipResponse = (SIPResponse) sipMessage; try { sipResponse.checkHeaders(); } catch (ParseException ex) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger() .logError("Dropping Badly formatted response message >>> " + sipResponse); return; } // This is a response message - process it. // Check the size of the response. // If it is too large dump it silently. if (sipStack.getMaxMessageSize() > 0 && sipResponse.getSize() + (sipResponse.getContentLength() == null ? 0 : sipResponse .getContentLength().getContentLength()) > sipStack .getMaxMessageSize()) { if (sipStack.isLoggingEnabled()) this.sipStack.getStackLogger().logDebug("Message size exceeded"); return; } ServerResponseInterface sipServerResponse = sipStack.newSIPServerResponse( sipResponse, this); if (sipServerResponse != null) { try { if (sipServerResponse instanceof SIPClientTransaction && !((SIPClientTransaction) sipServerResponse) .checkFromTag(sipResponse)) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger() .logError("Dropping response message with invalid tag >>> " + sipResponse); return; } sipServerResponse.processResponse(sipResponse, this); } finally { if (sipServerResponse instanceof SIPTransaction && !((SIPTransaction) sipServerResponse).passToListener()) { // Note that the semaphore is released in event // scanner if the // request is actually processed by the Listener. ((SIPTransaction) sipServerResponse).releaseSem(); } } } else { sipStack.getStackLogger().logWarning("Could not get semaphore... dropping response"); } } } finally { } } /** * 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; // 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(this, hispipe, this.sipStack.getMaxMessageSize()); // Start running the parser thread. myParser.processInput(); // bug fix by Emmanuel Proulx int bufferSize = 4096; this.tlsMessageProcessor.useCount++; this.isRunning = true; try { while (true) { try { byte[] msg = new byte[bufferSize]; int nbytes = myClientInputStream.read(msg, 0, bufferSize); // no more bytes to read... if (nbytes == -1) { hispipe.write("\r\n\r\n".getBytes("UTF-8")); try { if (sipStack.maxConnections != -1) { synchronized (tlsMessageProcessor) { tlsMessageProcessor.nConnections--; tlsMessageProcessor.notify(); } } hispipe.close(); mySock.close(); } catch (IOException ioex) { } return; } hispipe.write(msg, 0, nbytes); } catch (IOException ex) { // Terminate the message. try { hispipe.write("\r\n\r\n".getBytes("UTF-8")); } catch (Exception e) { // InternalErrorHandler.handleException(e); } try { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("IOException closing sock " + ex); try { if (sipStack.maxConnections != -1) { synchronized (tlsMessageProcessor) { tlsMessageProcessor.nConnections--; tlsMessageProcessor.notify(); } } mySock.close(); hispipe.close(); } catch (IOException ioex) { } } catch (Exception ex1) { // Do nothing. } return; } catch (Exception ex) { InternalErrorHandler.handleException(ex); } } } finally { this.isRunning = false; this.tlsMessageProcessor.remove(this); this.tlsMessageProcessor.useCount--; this.myParser.close(); } } protected void uncache() { if (isCached && !isRunning) { this.tlsMessageProcessor.remove(this); } } /** * Equals predicate. * * @param other is the other object to compare ourselves to for equals */ public boolean equals(Object other) { if (!this.getClass().equals(other.getClass())) return false; else { TLSMessageChannel that = (TLSMessageChannel) other; if (this.mySock != that.mySock) return false; else return true; } } /** * 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"); return this.key; } } /** * Get the host to assign to outgoing messages. * * @return the host to assign to the via header. */ public String getViaHost() { 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 myPort; } /** * Get the port of the peer to whom we are sending messages. * * @return the peer port. */ public int getPeerPort() { return peerPort; } public int getPeerPacketSourcePort() { return this.peerPort; } public InetAddress getPeerPacketSourceAddress() { return this.peerAddress; } /** * TLS Is a secure protocol. */ public boolean isSecure() { return true; } public void setHandshakeCompletedListener( HandshakeCompletedListener handshakeCompletedListenerImpl) { this.handshakeCompletedListener = handshakeCompletedListenerImpl; } /** * @return the handshakeCompletedListener */ public HandshakeCompletedListenerImpl getHandshakeCompletedListener() { return (HandshakeCompletedListenerImpl) handshakeCompletedListener; } } java/gov/nist/javax/sip/stack/TLSMessageProcessor.java0100644 0000000 0000000 00000025202 13513104763 022025 0ustar000000000 0000000 /* * 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 * * . * */ /* This class is entirely derived from TCPMessageProcessor, * by making some minor changes. * * Daniel J. Martinez Manzano * Acknowledgement: Jeff Keyser suggested that a * Stop mechanism be added to this. Niklas Uhrberg suggested that * a means to limit the number of simultaneous active connections * should be added. Mike Andrews suggested that the thread be * accessible so as to implement clean stop using Thread.join(). * */ /****************************************************************************** * Product of NIST/ITL Advanced Networking Technologies Division (ANTD). * ******************************************************************************/ package gov.nist.javax.sip.stack; import gov.nist.core.HostPort; 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.*; import java.util.ArrayList; import java.util.Collection; import java.util.Hashtable; import java.util.Iterator; /** * 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.23 $ $Date: 2009/12/06 15:58:39 $ * * @author M. Ranganathan
    * */ public class TLSMessageProcessor extends MessageProcessor { protected int nConnections; private boolean isRunning; private Hashtable tlsMessageChannels; private ServerSocket sock; protected int useCount = 0; private ArrayList incomingTlsMessageChannels; /** * Constructor. * * @param ipAddress -- inet address where I am listening. * @param sipStack SIPStack structure. * @param port port where this message processor listens. */ protected TLSMessageProcessor(InetAddress ipAddress, SIPTransactionStack sipStack, int port) { super(ipAddress, port, "tls",sipStack); this.sipStack = sipStack; this.tlsMessageChannels = new Hashtable(); this.incomingTlsMessageChannels = new ArrayList(); } /** * Start the processor. */ public void start() throws IOException { Thread thread = new Thread(this); thread.setName("TLSMessageProcessorThread"); // ISSUE 184 thread.setPriority(Thread.MAX_PRIORITY); thread.setDaemon(true); this.sock = sipStack.getNetworkLayer().createSSLServerSocket(this.getPort(), 0, this.getIpAddress()); ((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); ((SSLServerSocket)this.sock).setWantClientAuth(true); this.isRunning = true; thread.start(); } /** * Run method for the thread that gets created for each accept socket. */ public void run() { // Accept new connectins on our socket. while (this.isRunning) { try { synchronized (this) { // sipStack.maxConnections == -1 means we are // willing to handle an "infinite" number of // simultaneous connections (no resource limitation). // This is the default behavior. while (sipStack.maxConnections != -1 && this.nConnections >= sipStack.maxConnections) { try { this.wait(); if (!this.isRunning) return; } catch (InterruptedException ex) { break; } } this.nConnections++; } Socket newsock = sock.accept(); if (sipStack.isLoggingEnabled()) 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)); } catch (SocketException ex) { if ( this.isRunning ) { sipStack.getStackLogger().logError( "Fatal - SocketException occured while Accepting connection", ex); this.isRunning = false; break; } } catch (SSLException ex) { this.isRunning = false; sipStack.getStackLogger().logError( "Fatal - SSSLException occured while Accepting connection", ex); break; } catch (IOException ex) { // Problem accepting connection. sipStack.getStackLogger().logError("Problem Accepting Connection", ex); continue; } catch (Exception ex) { sipStack.getStackLogger().logError("Unexpected Exception!", ex); } } } /** * Returns the stack. * * @return my sip stack. */ public SIPTransactionStack getSIPStack() { return sipStack; } /** * Stop the message processor. Feature suggested by Jeff Keyser. */ public synchronized void stop() { if (!isRunning) return; isRunning = false; try { sock.close(); } catch (IOException e) { e.printStackTrace(); } Collection en = tlsMessageChannels.values(); for (Iterator it = en.iterator(); it.hasNext();) { TLSMessageChannel next = (TLSMessageChannel) it.next(); next.close(); } for (Iterator incomingMCIterator = incomingTlsMessageChannels.iterator(); incomingMCIterator .hasNext();) { TLSMessageChannel next = (TLSMessageChannel) incomingMCIterator.next(); next.close(); } this.notify(); } protected synchronized void remove(TLSMessageChannel tlsMessageChannel) { String key = tlsMessageChannel.getKey(); if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug(Thread.currentThread() + " removing " + key); } /** May have been removed already */ if (tlsMessageChannels.get(key) == tlsMessageChannel) this.tlsMessageChannels.remove(key); incomingTlsMessageChannels.remove(tlsMessageChannel); } public synchronized MessageChannel createMessageChannel(HostPort targetHostPort) throws IOException { String key = MessageChannel.getKey(targetHostPort, "TLS"); if (tlsMessageChannels.get(key) != null) { return (TLSMessageChannel) this.tlsMessageChannels.get(key); } else { TLSMessageChannel retval = new TLSMessageChannel(targetHostPort.getInetAddress(), targetHostPort.getPort(), sipStack, this); this.tlsMessageChannels.put(key, retval); retval.isCached = true; if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug("key " + key); sipStack.getStackLogger().logDebug("Creating " + retval); } return retval; } } protected synchronized void cacheMessageChannel(TLSMessageChannel messageChannel) { String key = messageChannel.getKey(); TLSMessageChannel currentChannel = (TLSMessageChannel) tlsMessageChannels.get(key); if (currentChannel != null) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("Closing " + key); currentChannel.close(); } if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("Caching " + key); this.tlsMessageChannels.put(key, messageChannel); } public synchronized MessageChannel createMessageChannel(InetAddress host, int port) throws IOException { try { String key = MessageChannel.getKey(host, port, "TLS"); if (tlsMessageChannels.get(key) != null) { return (TLSMessageChannel) this.tlsMessageChannels.get(key); } else { TLSMessageChannel retval = new TLSMessageChannel(host, port, sipStack, this); this.tlsMessageChannels.put(key, retval); retval.isCached = true; if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug("key " + key); sipStack.getStackLogger().logDebug("Creating " + retval); } return retval; } } catch (UnknownHostException ex) { throw new IOException(ex.getMessage()); } } /** * TLS can handle an unlimited number of bytes. */ public int getMaximumMessageSize() { return Integer.MAX_VALUE; } public boolean inUse() { return this.useCount != 0; } /** * Default target port for TLS */ public int getDefaultTargetPort() { return 5061; } /** * TLS is a secure protocol. */ public boolean isSecure() { return true; } } java/gov/nist/javax/sip/stack/UDPMessageChannel.java0100644 0000000 0000000 00000105370 13513104763 021411 0ustar000000000 0000000 /* * 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.javax.sip.stack; import gov.nist.core.InternalErrorHandler; import gov.nist.core.ServerLogger; import gov.nist.core.StackLogger; import gov.nist.core.ThreadAuditor; 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.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.ParseExceptionListener; import gov.nist.javax.sip.parser.StringMsgParser; import java.io.IOException; import java.io.OutputStream; import java.net.DatagramPacket; import java.net.DatagramSocket; 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; /* * Kim Kirby (Keyvoice) suggested that duplicate checking should be added to the * stack (later removed). Lamine Brahimi suggested a single threaded behavior * flag be added to this. Niklas Uhrberg suggested that thread pooling support * be added to this for performance and resource management. Peter Parnes found * a bug with this code that was sending it into an infinite loop when a bad * incoming message was parsed. Bug fix by viswashanti.kadiyala@antepo.com. * Hagai Sela addded fixes for NAT traversal. Jeroen van Bemmel fixed up for * buggy clients (such as windows messenger) and added code to return * BAD_REQUEST. David Alique fixed an address recording bug. Jeroen van Bemmel * fixed a performance issue where the stack was doing DNS lookups (potentially * unnecessary). Ricardo Bora (Natural Convergence ) added code that prevents * the stack from exitting when an exception is encountered. * */ /** * This is the UDP Message handler that gets created when a UDP message needs to * be processed. The message is processed by creating a String Message parser * and invoking it on the message read from the UDP socket. The parsed structure * is handed off via a SIP stack request for further processing. This stack * structure isolates the message handling logic from the mechanics of sending * and recieving messages (which could be either udp or tcp. * * * @author M. Ranganathan
    * * * * @version 1.2 $Revision: 1.66 $ $Date: 2010/01/14 05:15:49 $ */ public class UDPMessageChannel extends MessageChannel implements ParseExceptionListener, Runnable, RawMessageChannel { /** * SIP Stack structure for this channel. */ protected SIPTransactionStack sipStack; /** * The parser we are using for messages received from this channel. */ protected StringMsgParser myParser; /** * Where we got the stuff from */ private InetAddress peerAddress; private String myAddress; private int peerPacketSourcePort; private InetAddress peerPacketSourceAddress; /** * Reciever port -- port of the destination. */ private int peerPort; /** * Protocol to use when talking to receiver (i.e. when sending replies). */ private String peerProtocol; protected int myPort; private DatagramPacket incomingPacket; private long receptionTime; /* * 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 Hashtable pingBackRecord = new Hashtable(); class PingBackTimerTask extends TimerTask { String ipAddress; int port; public PingBackTimerTask(String ipAddress, int port) { this.ipAddress = ipAddress; this.port = port; pingBackRecord.put(ipAddress + ":" + port, this); } @Override public void run() { pingBackRecord.remove(ipAddress + ":" + port); } @Override public int hashCode() { return (ipAddress + ":" + port).hashCode(); } } /** * Constructor - takes a datagram packet and a stack structure Extracts the * address of the other from the datagram packet and stashes away the * pointer to the passed stack structure. * * @param stack * is the shared SIPStack structure * @param messageProcessor * is the creating message processor. */ protected UDPMessageChannel(SIPTransactionStack stack, UDPMessageProcessor messageProcessor) { super.messageProcessor = messageProcessor; this.sipStack = stack; Thread mythread = new Thread(this); this.myAddress = messageProcessor.getIpAddress().getHostAddress(); this.myPort = messageProcessor.getPort(); mythread.setName("UDPMessageChannelThread"); mythread.setDaemon(true); mythread.start(); } /** * Constructor. We create one of these in order to process an incoming * message. * * @param stack * is the SIP sipStack. * @param messageProcessor * is the creating message processor. * @param packet * is the incoming datagram packet. */ protected UDPMessageChannel(SIPTransactionStack stack, UDPMessageProcessor messageProcessor, DatagramPacket packet) { this.incomingPacket = packet; super.messageProcessor = messageProcessor; this.sipStack = stack; this.myAddress = messageProcessor.getIpAddress().getHostAddress(); this.myPort = messageProcessor.getPort(); Thread mythread = new Thread(this); mythread.setDaemon(true); mythread.setName("UDPMessageChannelThread"); mythread.start(); } /** * Constructor. We create one of these when we send out a message. * * @param targetAddr * INET address of the place where we want to send messages. * @param port * target port (where we want to send the message). * @param sipStack * our SIP Stack. */ protected UDPMessageChannel(InetAddress targetAddr, int port, SIPTransactionStack sipStack, UDPMessageProcessor messageProcessor) { peerAddress = targetAddr; peerPort = port; peerProtocol = "UDP"; super.messageProcessor = messageProcessor; this.myAddress = messageProcessor.getIpAddress().getHostAddress(); this.myPort = messageProcessor.getPort(); this.sipStack = sipStack; if (sipStack.isLoggingEnabled()) { this.sipStack.getStackLogger().logDebug("Creating message channel " + targetAddr.getHostAddress() + "/" + port); } } /** * Run method specified by runnnable. */ public void run() { // Assume no thread pooling (bug fix by spierhj) ThreadAuditor.ThreadHandle threadHandle = null; while (true) { // Create a new string message parser to parse the list of messages. if (myParser == null) { myParser = new StringMsgParser(); myParser.setParseExceptionListener(this); } // messages that we write out to him. 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(); } // 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; } } packet = (DatagramPacket) ((UDPMessageProcessor) messageProcessor).messageQueue .removeFirst(); } this.incomingPacket = packet; } else { packet = this.incomingPacket; } // Process the packet. Catch and log any exception we may throw. try { processIncomingDataPacket(packet); } catch (Exception e) { sipStack.getStackLogger().logError( "Error while processing incoming UDP packet", e); } if (sipStack.threadPoolSize == -1) { return; } } } /** * Process an incoming datagram * * @param packet * is the incoming datagram packet. */ private void processIncomingDataPacket(DatagramPacket packet) throws Exception { this.peerAddress = packet.getAddress(); int packetLength = packet.getLength(); // Read bytes and put it in a eueue. byte[] bytes = packet.getData(); byte[] msgBytes = new byte[packetLength]; System.arraycopy(bytes, 0, msgBytes, 0, packetLength); // Do debug logging. if (sipStack.isLoggingEnabled()) { this.sipStack.getStackLogger() .logDebug("UDPMessageChannel: processIncomingDataPacket : peerAddress = " + peerAddress.getHostAddress() + "/" + packet.getPort() + " Length = " + packetLength); } SIPMessage sipMessage = null; try { this.receptionTime = System.currentTimeMillis(); sipMessage = myParser.parseSIPMessage(msgBytes); myParser = null; } catch (ParseException 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); if (!msgString.startsWith("SIP/") && !msgString.startsWith("ACK ")) { String badReqRes = createBadReqRes(msgString, ex); if (badReqRes != null) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug( "Sending automatic 400 Bad Request:"); sipStack.getStackLogger().logDebug(badReqRes); } try { this.sendMessage(badReqRes.getBytes(), peerAddress, packet.getPort(), "UDP", false); } catch (IOException e) { this.sipStack.getStackLogger().logException(e); } } else { if (sipStack.isLoggingEnabled()) { sipStack .getStackLogger() .logDebug( "Could not formulate automatic 400 Bad Request"); } } } return; } // No parse exception but null message - reject it and // march on (or return). // exit this message processor if the message did not parse. if (sipMessage == null) { if (sipStack.isLoggingEnabled()) { this.sipStack.getStackLogger().logDebug("Rejecting message ! + Null message parsed."); } if (pingBackRecord.get(packet.getAddress().getHostAddress() + ":" + packet.getPort()) == null ) { byte[] retval = "\r\n\r\n".getBytes(); DatagramPacket keepalive = new DatagramPacket(retval,0,retval.length,packet.getAddress(),packet.getPort()); ((UDPMessageProcessor)this.messageProcessor).sock.send(keepalive); this.sipStack.getTimer().schedule(new PingBackTimerTask(packet.getAddress().getHostAddress(), packet.getPort()), 1000); } return; } ViaList viaList = sipMessage.getViaHeaders(); // Check for the required headers. if (sipMessage.getFrom() == null || sipMessage.getTo() == null || sipMessage.getCallId() == null || sipMessage.getCSeq() == null || sipMessage.getViaHeaders() == null) { String badmsg = new String(msgBytes); 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; } // 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) { Via v = (Via) viaList.getFirst(); Hop hop = sipStack.addressResolver.resolveAddress(v.getHop()); this.peerPort = hop.getPort(); this.peerProtocol = v.getTransport(); this.peerPacketSourceAddress = packet.getAddress(); this.peerPacketSourcePort = packet.getPort(); try { this.peerAddress = packet.getAddress(); // Check to see if the received parameter matches // the peer address and tag it appropriately. boolean hasRPort = v.hasParameter(Via.RPORT); if (hasRPort || !hop.getHost().equals( this.peerAddress.getHostAddress())) { v.setParameter(Via.RECEIVED, this.peerAddress .getHostAddress()); } if (hasRPort) { v.setParameter(Via.RPORT, Integer .toString(this.peerPacketSourcePort)); } } catch (java.text.ParseException ex1) { InternalErrorHandler.handleException(ex1); } } else { this.peerPacketSourceAddress = packet.getAddress(); this.peerPacketSourcePort = packet.getPort(); this.peerAddress = packet.getAddress(); this.peerPort = packet.getPort(); this.peerProtocol = ((Via) viaList.getFirst()).getTransport(); } this.processMessage(sipMessage); } /** * Actually proces the parsed message. * * @param sipMessage */ public void processMessage(SIPMessage sipMessage) { 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 (sipStack.getStackLogger().isLoggingEnabled(ServerLogger.TRACE_MESSAGES)) { this.sipStack.serverLogger.logMessage(sipMessage, this .getPeerHostPort().toString(), this.getHost() + ":" + this.myPort, false, receptionTime); } ServerRequestInterface sipServerRequest = sipStack .newSIPServerRequest(sipRequest, this); // Drop it if there is no request returned if (sipServerRequest == null) { if (sipStack.isLoggingEnabled()) { this.sipStack.getStackLogger() .logWarning("Null request interface returned -- dropping request"); } return; } if (sipStack.isLoggingEnabled()) this.sipStack.getStackLogger().logDebug("About to process " + sipRequest.getFirstLine() + "/" + sipServerRequest); try { sipServerRequest.processRequest(sipRequest, this); } finally { if (sipServerRequest instanceof SIPTransaction) { SIPServerTransaction sipServerTx = (SIPServerTransaction) sipServerRequest; if (!sipServerTx.passToListener()) { ((SIPTransaction) sipServerRequest).releaseSem(); } } } if (sipStack.isLoggingEnabled()) this.sipStack.getStackLogger().logDebug("Done processing " + sipRequest.getFirstLine() + "/" + sipServerRequest); // So far so good -- we will commit this message if // all processing is OK. } else { // Handle a SIP Reply message. SIPResponse sipResponse = (SIPResponse) sipMessage; try { sipResponse.checkHeaders(); } catch (ParseException ex) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger() .logError("Dropping Badly formatted response message >>> " + sipResponse); return; } ServerResponseInterface sipServerResponse = sipStack .newSIPServerResponse(sipResponse, this); if (sipServerResponse != null) { try { if (sipServerResponse instanceof SIPClientTransaction && !((SIPClientTransaction) sipServerResponse) .checkFromTag(sipResponse)) { if (sipStack.isLoggingEnabled()) sipStack.getStackLogger() .logError("Dropping response message with invalid tag >>> " + sipResponse); return; } sipServerResponse.processResponse(sipResponse, this); } finally { if (sipServerResponse instanceof SIPTransaction && !((SIPTransaction) sipServerResponse) .passToListener()) ((SIPTransaction) sipServerResponse).releaseSem(); } // Normal processing of message. } else { if (sipStack.isLoggingEnabled()) { this.sipStack.getStackLogger().logDebug("null sipServerResponse!"); } } } } /** * JvB: added method to check for known buggy clients (Windows Messenger) to * fix the port to which responses are sent * * checks for User-Agent: RTC/1.3.5470 (Messenger 5.1.0701) * * JvB 22/7/2006 better to take this out for the moment, it is only a * problem in rare cases (unregister) * * 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" ); } } * return false; } */ /** * Implementation of the ParseExceptionListener interface. * * @param ex * Exception that is given to us by the parser. * @throws ParseException * If we choose to reject the header or message. */ public void handleException(ParseException ex, SIPMessage sipMessage, Class hdrClass, String header, String message) throws ParseException { 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(RequestLine.class) || hdrClass .equals(StatusLine.class))) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logError("BAD MESSAGE!"); sipStack.getStackLogger().logError(message); } throw ex; } else { sipMessage.addUnparsed(header); } } /** * Return a reply from a pre-constructed reply. This sends the message back * to the entity who caused us to create this channel in the first place. * * @param sipMessage * Message string to send. * @throws IOException * If there is a problem with sending the message. */ public void sendMessage(SIPMessage sipMessage) throws IOException { if (sipStack.isLoggingEnabled() && this.sipStack.isLogStackTraceOnMessageSend()) { if ( sipMessage instanceof SIPRequest && ((SIPRequest)sipMessage).getRequestLine() != null) { /* * We dont want to log empty trace messages. */ this.sipStack.getStackLogger().logStackTrace(StackLogger.TRACE_INFO); } else { this.sipStack.getStackLogger().logStackTrace(StackLogger.TRACE_INFO); } } // Test and see where we are going to send the messsage. If the message // is sent back to oursleves, just // shortcircuit processing. long time = System.currentTimeMillis(); try { for (MessageProcessor messageProcessor : sipStack .getMessageProcessors()) { if (messageProcessor.getIpAddress().equals(this.peerAddress) && messageProcessor.getPort() == this.peerPort && messageProcessor.getTransport().equals( this.peerProtocol)) { MessageChannel messageChannel = messageProcessor .createMessageChannel(this.peerAddress, this.peerPort); if (messageChannel instanceof RawMessageChannel) { ((RawMessageChannel) messageChannel) .processMessage(sipMessage); if (sipStack.isLoggingEnabled()) sipStack.getStackLogger().logDebug("Self routing message"); return; } } } byte[] msg = sipMessage.encodeAsBytes( this.getTransport() ); sendMessage(msg, peerAddress, peerPort, peerProtocol, sipMessage instanceof SIPRequest); } catch (IOException ex) { throw ex; } catch (Exception ex) { sipStack.getStackLogger().logError("An exception occured while sending message",ex); throw new IOException( "An exception occured while sending message"); } finally { if (sipStack.getStackLogger().isLoggingEnabled(ServerLogger.TRACE_MESSAGES) && !sipMessage.isNullRequest()) logMessage(sipMessage, peerAddress, peerPort, time); else if (sipStack.getStackLogger().isLoggingEnabled(ServerLogger.TRACE_DEBUG)) sipStack.getStackLogger().logDebug("Sent EMPTY Message"); } } /** * Send a message to a specified receiver address. * * @param msg * string to send. * @param peerAddress * Address of the place to send it to. * @param peerPort * the port to send it to. * @throws IOException * If there is trouble sending this message. */ 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 (sipStack.isLoggingEnabled() && this.sipStack.isLogStackTraceOnMessageSend() ) { this.sipStack.getStackLogger().logStackTrace(StackLogger.TRACE_INFO); } if (peerPort == -1) { if (sipStack.isLoggingEnabled()) { this.sipStack.getStackLogger().logDebug(getClass().getName() + ":sendMessage: Dropping reply!"); } throw new IOException("Receiver port not set "); } else { if (sipStack.isLoggingEnabled()) { this.sipStack.getStackLogger().logDebug("sendMessage " + peerAddress.getHostAddress() + "/" + peerPort + "\n" + "messageSize = " + msg.length + " message = " + new String(msg)) ; this.sipStack.getStackLogger().logDebug("*******************\n"); } } DatagramPacket reply = new DatagramPacket(msg, msg.length, peerAddress, peerPort); try { DatagramSocket sock; boolean created = false; if (sipStack.udpFlag) { // Use the socket from the message processor (for firewall // support use the same socket as the message processor // socket -- feature request # 18 from java.net). This also // makes the whole thing run faster! sock = ((UDPMessageProcessor) messageProcessor).sock; // Bind the socket to the stack address in case there // are multiple interfaces on the machine (feature reqeust // by Will Scullin) 0 binds to an ephemeral port. // sock = new DatagramSocket(0,sipStack.stackInetAddress); } else { // bind to any interface and port. sock = new DatagramSocket(); created = true; } sock.send(reply); if (created) sock.close(); } catch (IOException ex) { throw ex; } catch (Exception ex) { InternalErrorHandler.handleException(ex); } } /** * Send a message to a specified receiver address. * * @param msg * message string to send. * @param peerAddress * Address of the place to send it to. * @param peerPort * the port to send it to. * @param peerProtocol * protocol to use to send. * @throws IOException * If there is trouble sending this message. */ protected void sendMessage(byte[] msg, InetAddress peerAddress, int peerPort, String peerProtocol, boolean retry) throws IOException { // Via is not included in the request so silently drop the reply. if (peerPort == -1) { if (sipStack.isLoggingEnabled()) { this.sipStack.getStackLogger().logDebug(getClass().getName() + ":sendMessage: Dropping reply!"); } throw new IOException("Receiver port not set "); } else { if (sipStack.isLoggingEnabled()) { this.sipStack.getStackLogger().logDebug( ":sendMessage " + peerAddress.getHostAddress() + "/" + peerPort + "\n" + " messageSize = " + msg.length); } } if (peerProtocol.compareToIgnoreCase("UDP") == 0) { DatagramPacket reply = new DatagramPacket(msg, msg.length, peerAddress, peerPort); try { DatagramSocket sock; if (sipStack.udpFlag) { sock = ((UDPMessageProcessor) messageProcessor).sock; } else { // bind to any interface and port. sock = sipStack.getNetworkLayer().createDatagramSocket(); } if (sipStack.isLoggingEnabled()) { this.sipStack.getStackLogger().logDebug("sendMessage " + peerAddress.getHostAddress() + "/" + peerPort + "\n" + new String(msg)); } sock.send(reply); if (!sipStack.udpFlag) sock.close(); } catch (IOException ex) { throw ex; } catch (Exception ex) { InternalErrorHandler.handleException(ex); } } else { // Use TCP to talk back to the sender. Socket outputSocket = sipStack.ioHandler.sendBytes( this.messageProcessor.getIpAddress(), peerAddress, peerPort, "tcp", msg, retry,this); OutputStream myOutputStream = outputSocket.getOutputStream(); myOutputStream.write(msg, 0, msg.length); myOutputStream.flush(); // The socket is cached (dont close it!); } } /** * get the stack pointer. * * @return The sip stack for this channel. */ public SIPTransactionStack getSIPStack() { return sipStack; } /** * Return a transport string. * * @return the string "udp" in this case. */ public String getTransport() { return SIPConstants.UDP; } /** * get the stack address for the stack that received this message. * * @return The stack address for our sipStack. */ public String getHost() { return messageProcessor.getIpAddress().getHostAddress(); } /** * get the port. * * @return Our port (on which we are getting datagram packets). */ public int getPort() { return ((UDPMessageProcessor) messageProcessor).getPort(); } /** * get the name (address) of the host that sent me the message * * @return The name of the sender (from the datagram packet). */ public String getPeerName() { return peerAddress.getHostName(); } /** * get the address of the host that sent me the message * * @return The senders ip address. */ public String getPeerAddress() { return peerAddress.getHostAddress(); } protected InetAddress getPeerInetAddress() { return peerAddress; } /** * Compare two UDP Message channels for equality. * * @param other * The other message channel with which to compare oursleves. */ public boolean equals(Object other) { if (other == null) return false; boolean retval; if (!this.getClass().equals(other.getClass())) { retval = false; } else { UDPMessageChannel that = (UDPMessageChannel) other; retval = this.getKey().equals(that.getKey()); } return retval; } public String getKey() { return getKey(peerAddress, peerPort, "UDP"); } public int getPeerPacketSourcePort() { return peerPacketSourcePort; } public InetAddress getPeerPacketSourceAddress() { return peerPacketSourceAddress; } /** * Get the logical originator of the message (from the top via header). * * @return topmost via header sentby field */ public String getViaHost() { return this.myAddress; } /** * Get the logical port of the message orginator (from the top via hdr). * * @return the via port from the topmost via header. */ public int getViaPort() { return this.myPort; } /** * Returns "false" as this is an unreliable transport. */ public boolean isReliable() { return false; } /** * UDP is not a secure protocol. */ public boolean isSecure() { return false; } public int getPeerPort() { return peerPort; } public String getPeerProtocol() { return this.peerProtocol; } /** * Close the message channel. */ public void close() { } } java/gov/nist/javax/sip/stack/UDPMessageProcessor.java0100644 0000000 0000000 00000027114 13513104763 022017 0ustar000000000 0000000 /* * 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.javax.sip.stack; import java.io.IOException; import java.util.LinkedList; 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.37 $ $Date: 2009/11/14 20:06:16 $ * * @author M. Ranganathan
    * * * * * See the implementation sequence diagram for processing incoming requests. * * * * Acknowledgement: Jeff Keyser contributed ideas on starting and stoppping the * stack that were incorporated into this code. Niklas Uhrberg suggested that * thread pooling be added to limit the number of threads and improve * performance. */ public class UDPMessageProcessor extends MessageProcessor { /** * The Mapped port (in case STUN suport is enabled) */ private int port; /** * Incoming messages are queued here. */ protected LinkedList messageQueue; /** * A list of message channels that we have started. */ protected LinkedList messageChannels; /** * Max # of udp message channels */ protected int threadPoolSize; protected DatagramSocket sock; /** * A flag that is set to false to exit the message processor (suggestion by * Jeff Keyser). */ protected boolean isRunning; private static final int HIGHWAT=5000; private static final int LOWAT=2500; /** * Constructor. * * @param sipStack * pointer to the stack. */ protected UDPMessageProcessor(InetAddress ipAddress, SIPTransactionStack sipStack, int port) throws IOException { super(ipAddress, port, "udp",sipStack); this.sipStack = sipStack; this.messageQueue = new LinkedList(); this.port = port; try { this.sock = sipStack.getNetworkLayer().createDatagramSocket(port, ipAddress); // Create a new datagram socket. sock.setReceiveBufferSize(sipStack.getReceiveUdpBufferSize()); sock.setSendBufferSize(sipStack.getSendUdpBufferSize()); /** * If the thread auditor is enabled, define a socket timeout value in order to * prevent sock.receive() from blocking forever */ if (sipStack.getThreadAuditor().isEnabled()) { sock.setSoTimeout((int) sipStack.getThreadAuditor().getPingIntervalInMillisecs()); } if ( ipAddress.getHostAddress().equals(IN_ADDR_ANY) || ipAddress.getHostAddress().equals(IN6_ADDR_ANY)){ // Store the address to which we are actually bound // Note that on WINDOWS this is actually broken. It will // return IN_ADDR_ANY again. On linux it will return the // address to which the socket was actually bound. super.setIpAddress( sock.getLocalAddress() ); } } catch (SocketException ex) { throw new IOException(ex.getMessage()); } } /** * Get port on which to listen for incoming stuff. * * @return port on which I am listening. */ public int getPort() { return this.port; } /** * Start our processor thread. */ public void start() throws IOException { this.isRunning = true; Thread thread = new Thread(this); thread.setDaemon(true); // Issue #32 on java.net thread.setName("UDPMessageProcessorThread"); // Issue #184 thread.setPriority(Thread.MAX_PRIORITY); thread.start(); } /** * Thread main routine. */ public void run() { // Check for running flag. this.messageChannels = new LinkedList(); // start all our messageChannels (unless the thread pool size is // infinity. if (sipStack.threadPoolSize != -1) { for (int i = 0; i < sipStack.threadPoolSize; i++) { UDPMessageChannel channel = new UDPMessageChannel(sipStack, this); this.messageChannels.add(channel); } } // Ask the auditor to monitor this thread ThreadAuditor.ThreadHandle threadHandle = sipStack.getThreadAuditor().addCurrentThread(); // Somebody asked us to exit. if isRunnning is set to false. while (this.isRunning) { try { // Let the thread auditor know we're up and running threadHandle.ping(); int bufsize = sock.getReceiveBufferSize(); byte message[] = new byte[bufsize]; DatagramPacket packet = new DatagramPacket(message, bufsize); sock.receive(packet); // This is a simplistic congestion control algorithm. // It accepts packets if queuesize is < LOWAT. It drops // requests if the queue size exceeds a HIGHWAT and accepts // requests with probability p proportional to the difference // between current queue size and LOWAT in the range // of queue sizes between HIGHWAT and LOWAT. // TODO -- penalize spammers by looking at the source // port and IP address. if ( sipStack.stackDoesCongestionControl ) { if ( this.messageQueue.size() >= HIGHWAT) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug("Dropping message -- queue length exceeded"); } //System.out.println("HIGHWAT Drop!"); continue; } else if ( this.messageQueue.size() > LOWAT && this .messageQueue.size() < HIGHWAT ) { // Drop the message with a probabilty that is linear in the range 0 to 1 float threshold = ((float)(messageQueue.size() - LOWAT))/ ((float)(HIGHWAT - LOWAT)); boolean decision = Math.random() > 1.0 - threshold; if ( decision ) { if (sipStack.isLoggingEnabled()) { sipStack.getStackLogger().logDebug("Dropping message with probability " + (1.0 - threshold)); } //System.out.println("RED Drop!"); continue; } } } // Count of # of packets in process. // this.useCount++; if (sipStack.threadPoolSize != -1) { // Note: the only condition watched for by threads // synchronizing on the messageQueue member is that it is // not empty. As soon as you introduce some other // condition you will have to call notifyAll instead of // notify below. synchronized (this.messageQueue) { // was addLast this.messageQueue.add(packet); 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 (sipStack.isLoggingEnabled()) 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 (sipStack.isLoggingEnabled()) getSIPStack().getStackLogger() .logDebug("UDPMessageProcessor: Got an IO Exception"); } catch (Exception ex) { if (sipStack.isLoggingEnabled()) getSIPStack().getStackLogger() .logDebug("UDPMessageProcessor: Unexpected Exception - quitting"); InternalErrorHandler.handleException(ex); return; } } } /** * Shut down the message processor. Close the socket for recieving incoming * messages. */ public void stop() { synchronized (this.messageQueue) { this.isRunning = false; this.messageQueue.notifyAll(); sock.close(); } } /** * Return the transport string. * * @return the transport string */ public String getTransport() { return "udp"; } /** * Returns the stack. * * @return my sip stack. */ public SIPTransactionStack getSIPStack() { return sipStack; } /** * Create and return new TCPMessageChannel for the given host/port. */ public MessageChannel createMessageChannel(HostPort targetHostPort) throws UnknownHostException { return new UDPMessageChannel(targetHostPort.getInetAddress(), targetHostPort.getPort(), sipStack, this); } public MessageChannel createMessageChannel(InetAddress host, int port) throws IOException { return new UDPMessageChannel(host, port, sipStack, this); } /** * Default target port for UDP */ public int getDefaultTargetPort() { return 5060; } /** * UDP is not a secure protocol. */ public boolean isSecure() { return false; } /** * UDP can handle a message as large as the MAX_DATAGRAM_SIZE. */ public int getMaximumMessageSize() { return 8*1024; } /** * Return true if there are any messages in use. */ public boolean inUse() { synchronized (messageQueue) { return messageQueue.size() != 0; } } } java/gov/nist/javax/sip/stack/package.html0100644 0000000 0000000 00000001047 13513104763 017575 0ustar000000000 0000000 This package implements the main protocol abstractions that are defined by the SIP RFC 3261. These include the following main ones:
    • SIPServerTransaction -- an implementation of the Server Transaction State Machine (Chapter 17 of RFC 3261).
    • SIPClientTransaction -- an implementation of the Client Transction State Machine (Chapter 17 of RFC 3261).
    • SIPDialog -- an implementation of the SIP Dialog ( Chapter 11 of RFC 3261 ).
    SIPTransactionStack is the container that holds references to these protocol objects. java/javax/0040755 0000000 0000000 00000000000 13513104763 011645 5ustar000000000 0000000 java/javax/sip/0040755 0000000 0000000 00000000000 13513104763 012440 5ustar000000000 0000000 java/javax/sip/ClientTransaction.java0100644 0000000 0000000 00000001106 13513104763 016722 0ustar000000000 0000000 package javax.sip; import javax.sip.address.Hop; import javax.sip.message.Request; public interface ClientTransaction extends Transaction { /** * @deprecated * For 2xx response, use {@link Dialog.createAck(long)}. The application * should not need to handle non-2xx responses. */ Request createAck() throws SipException; Request createCancel() throws SipException; void sendRequest() throws SipException; void alertIfStillInCallingStateBy(int count); Hop getNextHop(); void setNotifyOnRetransmit(boolean notifyOnRetransmit); } java/javax/sip/Dialog.java0100644 0000000 0000000 00000003555 13513104763 014507 0ustar000000000 0000000 package javax.sip; import java.io.Serializable; import java.text.ParseException; import java.util.Iterator; import javax.sip.address.Address; import javax.sip.header.CallIdHeader; import javax.sip.message.Request; import javax.sip.message.Response; public interface Dialog extends Serializable { Object getApplicationData(); void setApplicationData(Object applicationData); CallIdHeader getCallId(); String getDialogId(); /** * @deprecated */ Transaction getFirstTransaction(); Address getLocalParty(); /** * @deprecated * @see #getLocalSeqNumber() */ int getLocalSequenceNumber(); long getLocalSeqNumber(); String getLocalTag(); Address getRemoteParty(); /** * @deprecated * @see #getRemoteSeqNumber() */ int getRemoteSequenceNumber(); long getRemoteSeqNumber(); String getRemoteTag(); Address getRemoteTarget(); Iterator getRouteSet(); SipProvider getSipProvider(); DialogState getState(); boolean isSecure(); boolean isServer(); void delete(); void incrementLocalSequenceNumber(); Request createRequest(String method) throws SipException; Request createAck(long cseq) throws InvalidArgumentException, SipException; Request createPrack(Response relResponse) throws DialogDoesNotExistException, SipException; Response createReliableProvisionalResponse(int statusCode) throws InvalidArgumentException, SipException; void sendRequest(ClientTransaction clientTransaction) throws TransactionDoesNotExistException, SipException; void sendAck(Request ackRequest) throws SipException; void sendReliableProvisionalResponse(Response relResponse) throws SipException; void setBackToBackUserAgent(); void terminateOnBye(boolean terminateFlag) throws SipException; } java/javax/sip/DialogDoesNotExistException.java0100644 0000000 0000000 00000000517 13513104763 020672 0ustar000000000 0000000 package javax.sip; public class DialogDoesNotExistException extends SipException { public DialogDoesNotExistException(){ } public DialogDoesNotExistException(String message) { super(message); } public DialogDoesNotExistException(String message, Throwable cause) { super(message, cause); } } java/javax/sip/DialogState.java0100644 0000000 0000000 00000001133 13513104763 015476 0ustar000000000 0000000 package javax.sip; public enum DialogState { EARLY, CONFIRMED, TERMINATED; public static final int _EARLY = EARLY.ordinal(); public static final int _CONFIRMED = CONFIRMED.ordinal(); public static final int _TERMINATED = TERMINATED.ordinal(); public static DialogState getObject(int state) { try { return values()[state]; } catch (IndexOutOfBoundsException e) { throw new IllegalArgumentException( "Invalid dialog state: " + state); } } public int getValue() { return ordinal(); } } java/javax/sip/DialogTerminatedEvent.java0100644 0000000 0000000 00000000502 13513104763 017513 0ustar000000000 0000000 package javax.sip; import java.util.EventObject; public class DialogTerminatedEvent extends EventObject { private Dialog mDialog; public DialogTerminatedEvent(Object source, Dialog dialog) { super(source); mDialog = dialog; } public Dialog getDialog() { return mDialog; } } java/javax/sip/IOExceptionEvent.java0100644 0000000 0000000 00000001075 13513104763 016473 0ustar000000000 0000000 package javax.sip; import java.util.EventObject; public class IOExceptionEvent extends EventObject { private String mHost; private int mPort; private String mTransport; public IOExceptionEvent(Object source, String host, int port, String transport) { super(source); mHost = host; mPort = port; mTransport = transport; } public String getHost() { return mHost; } public int getPort() { return mPort; } public String getTransport() { return mTransport; } } java/javax/sip/InvalidArgumentException.java0100644 0000000 0000000 00000000503 13513104763 020246 0ustar000000000 0000000 package javax.sip; public class InvalidArgumentException extends SipException { public InvalidArgumentException() { } public InvalidArgumentException(String message) { super(message); } public InvalidArgumentException(String message, Throwable cause) { super(message, cause); } } java/javax/sip/ListeningPoint.java0100644 0000000 0000000 00000001111 13513104763 016240 0ustar000000000 0000000 package javax.sip; import java.io.IOException; import java.text.ParseException; import javax.sip.header.ContactHeader; public interface ListeningPoint extends Cloneable { String TCP = "TCP"; String UDP = "UDP"; String SCTP = "SCTP"; String TLS = "TLS"; int PORT_5060 = 5060; int PORT_5061 = 5061; String getIPAddress(); int getPort(); String getTransport(); String getSentBy(); void setSentBy(String sentBy) throws ParseException; ContactHeader createContactHeader(); void sendHeartbeat(String s, int i) throws IOException; } java/javax/sip/ObjectInUseException.java0100644 0000000 0000000 00000000464 13513104763 017335 0ustar000000000 0000000 package javax.sip; public class ObjectInUseException extends SipException { public ObjectInUseException() { } public ObjectInUseException(String message) { super(message); } public ObjectInUseException(String message, Throwable cause) { super(message, cause); } } java/javax/sip/PeerUnavailableException.java0100644 0000000 0000000 00000000504 13513104763 020215 0ustar000000000 0000000 package javax.sip; public class PeerUnavailableException extends SipException { public PeerUnavailableException() { } public PeerUnavailableException(String message) { super(message); } public PeerUnavailableException(String message, Throwable cause) { super(message, cause); } } java/javax/sip/ProviderDoesNotExistException.java0100644 0000000 0000000 00000000527 13513104763 021266 0ustar000000000 0000000 package javax.sip; public class ProviderDoesNotExistException extends SipException { public ProviderDoesNotExistException(){ } public ProviderDoesNotExistException(String message) { super(message); } public ProviderDoesNotExistException(String message, Throwable cause) { super(message, cause); } } java/javax/sip/RequestEvent.java0100644 0000000 0000000 00000001323 13513104763 015731 0ustar000000000 0000000 package javax.sip; import java.util.EventObject; import javax.sip.message.Request; public class RequestEvent extends EventObject { private Dialog mDialog; private Request mRequest; private ServerTransaction mServerTransaction; public RequestEvent(Object source, ServerTransaction serverTransaction, Dialog dialog, Request request) { super(source); mDialog = dialog; mRequest = request; mServerTransaction = serverTransaction; } public Dialog getDialog() { return mDialog; } public Request getRequest() { return mRequest; } public ServerTransaction getServerTransaction() { return mServerTransaction; } } java/javax/sip/ResponseEvent.java0100644 0000000 0000000 00000001335 13513104763 016102 0ustar000000000 0000000 package javax.sip; import java.util.EventObject; import javax.sip.message.Response; public class ResponseEvent extends EventObject { private Dialog mDialog; private Response mResponse; private ClientTransaction mClientTransaction; public ResponseEvent(Object source, ClientTransaction clientTransaction, Dialog dialog, Response response) { super(source); mDialog = dialog; mResponse = response; mClientTransaction = clientTransaction; } public Dialog getDialog() { return mDialog; } public Response getResponse() { return mResponse; } public ClientTransaction getClientTransaction(){ return mClientTransaction; } } java/javax/sip/ServerTransaction.java0100644 0000000 0000000 00000000512 13513104763 016752 0ustar000000000 0000000 package javax.sip; import javax.sip.message.Response; public interface ServerTransaction extends Transaction { void sendResponse(Response response) throws SipException, InvalidArgumentException; void enableRetransmissionAlerts() throws SipException; ServerTransaction getCanceledInviteTransaction(); } java/javax/sip/SipException.java0100644 0000000 0000000 00000000421 13513104763 015707 0ustar000000000 0000000 package javax.sip; public class SipException extends Exception { public SipException() { } public SipException(String message) { super(message); } public SipException(String message, Throwable cause) { super(message, cause); } } java/javax/sip/SipFactory.java0100644 0000000 0000000 00000007132 13513104763 015366 0ustar000000000 0000000 package javax.sip; import java.lang.reflect.Constructor; import java.util.HashMap; import java.util.Map; import java.util.Properties; import javax.sip.address.AddressFactory; import javax.sip.header.HeaderFactory; import javax.sip.message.MessageFactory; public class SipFactory { private static final String IP_ADDRESS_PROP = "javax.sip.IP_ADDRESS"; private static final String STACK_NAME_PROP = "javax.sip.STACK_NAME"; private static SipFactory sSipFactory = null; public static synchronized SipFactory getInstance() { if (sSipFactory == null) sSipFactory = new SipFactory(); return sSipFactory; } // name-to-SipStack map; name could be IP address for backward compatibility private Map mNameSipStackMap = new HashMap(); private SipFactory() { } public synchronized void resetFactory() { mNameSipStackMap.clear(); } public synchronized SipStack createSipStack(Properties properties) throws PeerUnavailableException { // for backward compatibility, if IP_ADDRESS_PROP exists, use it and // ignore STACK_NAME_PROP. String name = properties.getProperty(IP_ADDRESS_PROP); if (name == null) { name = properties.getProperty(STACK_NAME_PROP); if (name == null ) { throw new PeerUnavailableException( STACK_NAME_PROP + " property not found"); } } SipStack sipStack = mNameSipStackMap.get(name); if (sipStack == null) { String implClassName = "gov.nist." + SipStack.class.getCanonicalName() + "Impl"; try { sipStack = Class.forName(implClassName) .asSubclass(SipStack.class) .getConstructor(new Class[] {Properties.class}) .newInstance(new Object[] {properties}); } catch (Exception e) { throw new PeerUnavailableException( "Failed to initiate " + implClassName, e); } mNameSipStackMap.put(name, sipStack); } return sipStack; } public AddressFactory createAddressFactory() throws PeerUnavailableException { try { return new gov.nist.javax.sip.address.AddressFactoryImpl(); } catch (Exception e) { if (e instanceof PeerUnavailableException) { throw (PeerUnavailableException) e; } else { throw new PeerUnavailableException( "Failed to create AddressFactory", e); } } } public HeaderFactory createHeaderFactory() throws PeerUnavailableException { try { return new gov.nist.javax.sip.header.HeaderFactoryImpl(); } catch (Exception e) { if (e instanceof PeerUnavailableException) { throw (PeerUnavailableException) e; } else { throw new PeerUnavailableException( "Failed to create HeaderFactory", e); } } } public MessageFactory createMessageFactory() throws PeerUnavailableException { try { return new gov.nist.javax.sip.message.MessageFactoryImpl(); } catch (Exception e) { if (e instanceof PeerUnavailableException) { throw (PeerUnavailableException) e; } else { throw new PeerUnavailableException( "Failed to create MessageFactory", e); } } } } java/javax/sip/SipListener.java0100644 0000000 0000000 00000000715 13513104763 015544 0ustar000000000 0000000 package javax.sip; public interface SipListener { void processDialogTerminated(DialogTerminatedEvent dialogTerminatedEvent); void processIOException(IOExceptionEvent exceptionEvent); void processRequest(RequestEvent requestEvent); void processResponse(ResponseEvent responseEvent); void processTimeout(TimeoutEvent timeoutEvent); void processTransactionTerminated( TransactionTerminatedEvent transactionTerminatedEvent); } java/javax/sip/SipProvider.java0100644 0000000 0000000 00000003123 13513104763 015545 0ustar000000000 0000000 package javax.sip; import java.util.TooManyListenersException; import javax.sip.header.CallIdHeader; import javax.sip.message.Request; import javax.sip.message.Response; public interface SipProvider { /** * @deprecated * @see #addListeningPoint(ListeningPoint) */ void setListeningPoint(ListeningPoint listeningPoint) throws ObjectInUseException; void addListeningPoint(ListeningPoint listeningPoint) throws ObjectInUseException; void removeListeningPoint(ListeningPoint listeningPoint) throws ObjectInUseException; void removeListeningPoints(); /** * @deprecated * @see #getListeningPoints() */ ListeningPoint getListeningPoint(); ListeningPoint getListeningPoint(String transport); ListeningPoint[] getListeningPoints(); void addSipListener(SipListener sipListener) throws TooManyListenersException; void removeSipListener(SipListener sipListener); CallIdHeader getNewCallId(); ClientTransaction getNewClientTransaction(Request request) throws TransactionUnavailableException; ServerTransaction getNewServerTransaction(Request request) throws TransactionAlreadyExistsException, TransactionUnavailableException; Dialog getNewDialog(Transaction transaction) throws SipException; boolean isAutomaticDialogSupportEnabled(); void setAutomaticDialogSupportEnabled(boolean flag); SipStack getSipStack(); void sendRequest(Request request) throws SipException; void sendResponse(Response response) throws SipException; } java/javax/sip/SipStack.java0100644 0000000 0000000 00000002441 13513104763 015022 0ustar000000000 0000000 package javax.sip; import java.util.Collection; import java.util.Iterator; import javax.sip.address.Router; public interface SipStack { /** * Deprecated. Use {@link #createListeningPoint(String, int, String)} * instead. */ ListeningPoint createListeningPoint(int port, String transport) throws TransportNotSupportedException, InvalidArgumentException; ListeningPoint createListeningPoint(String ipAddress, int port, String transport) throws TransportNotSupportedException, InvalidArgumentException; void deleteListeningPoint(ListeningPoint listeningPoint) throws ObjectInUseException; SipProvider createSipProvider(ListeningPoint listeningPoint) throws ObjectInUseException; void deleteSipProvider(SipProvider sipProvider) throws ObjectInUseException; Collection getDialogs(); String getIPAddress(); Iterator getListeningPoints(); Router getRouter(); Iterator getSipProviders(); String getStackName(); /** * @deprecated * Use {@link ServerTransaction#enableRetransmissionAlerts()} to enable * retransmission alerts instead. */ boolean isRetransmissionFilterActive(); void start() throws ProviderDoesNotExistException, SipException; void stop(); } java/javax/sip/Timeout.java0100644 0000000 0000000 00000000115 13513104763 014723 0ustar000000000 0000000 package javax.sip; public enum Timeout { RETRANSMIT, TRANSACTION; } java/javax/sip/TimeoutEvent.java0100644 0000000 0000000 00000001045 13513104763 015730 0ustar000000000 0000000 package javax.sip; public class TimeoutEvent extends TransactionTerminatedEvent { private Timeout mTimeout; public TimeoutEvent(Object source, ServerTransaction serverTransaction, Timeout timeout) { super(source, serverTransaction); mTimeout = timeout; } public TimeoutEvent(Object source, ClientTransaction clientTransaction, Timeout timeout) { super(source, clientTransaction); mTimeout = timeout; } public Timeout getTimeout() { return mTimeout; } } java/javax/sip/Transaction.java0100644 0000000 0000000 00000001303 13513104763 015562 0ustar000000000 0000000 package javax.sip; import java.io.Serializable; import javax.sip.message.Request; public interface Transaction extends Serializable { Object getApplicationData(); void setApplicationData (Object applicationData); String getBranchId(); Dialog getDialog(); String getHost(); String getPeerAddress(); int getPeerPort(); int getPort(); Request getRequest(); SipProvider getSipProvider(); TransactionState getState(); String getTransport(); int getRetransmitTimer() throws UnsupportedOperationException; void setRetransmitTimer(int retransmitTimer) throws UnsupportedOperationException; void terminate() throws ObjectInUseException; } java/javax/sip/TransactionAlreadyExistsException.java0100644 0000000 0000000 00000000547 13513104763 022154 0ustar000000000 0000000 package javax.sip; public class TransactionAlreadyExistsException extends SipException { public TransactionAlreadyExistsException(){ } public TransactionAlreadyExistsException(String message) { super(message); } public TransactionAlreadyExistsException(String message, Throwable cause) { super(message, cause); } } java/javax/sip/TransactionDoesNotExistException.java0100644 0000000 0000000 00000000543 13513104763 021757 0ustar000000000 0000000 package javax.sip; public class TransactionDoesNotExistException extends SipException { public TransactionDoesNotExistException(){ } public TransactionDoesNotExistException(String message) { super(message); } public TransactionDoesNotExistException(String message, Throwable cause) { super(message, cause); } } java/javax/sip/TransactionState.java0100644 0000000 0000000 00000000214 13513104763 016563 0ustar000000000 0000000 package javax.sip; public enum TransactionState { CALLING, TRYING, PROCEEDING, COMPLETED, CONFIRMED, TERMINATED; } java/javax/sip/TransactionTerminatedEvent.java0100644 0000000 0000000 00000001723 13513104763 020607 0ustar000000000 0000000 package javax.sip; import java.util.EventObject; public class TransactionTerminatedEvent extends EventObject { private boolean mIsServerTransaction; private ServerTransaction mServerTransaction; private ClientTransaction mClientTransaction; public TransactionTerminatedEvent( Object source, ServerTransaction serverTransaction) { super(source); mServerTransaction = serverTransaction; mIsServerTransaction = true; } public TransactionTerminatedEvent( Object source, ClientTransaction clientTransaction) { super(source); mClientTransaction = clientTransaction; mIsServerTransaction = false; } public boolean isServerTransaction() { return mIsServerTransaction; } public ClientTransaction getClientTransaction() { return mClientTransaction; } public ServerTransaction getServerTransaction() { return mServerTransaction; } } java/javax/sip/TransactionUnavailableException.java0100644 0000000 0000000 00000000540 13513104763 021607 0ustar000000000 0000000 package javax.sip; public class TransactionUnavailableException extends SipException { public TransactionUnavailableException() { } public TransactionUnavailableException(String message) { super(message); } public TransactionUnavailableException(String message, Throwable cause) { super(message, cause); } } java/javax/sip/TransportNotSupportedException.java0100644 0000000 0000000 00000000534 13513104763 021544 0ustar000000000 0000000 package javax.sip; public class TransportNotSupportedException extends SipException { public TransportNotSupportedException() { } public TransportNotSupportedException(String message) { super(message); } public TransportNotSupportedException(String message, Throwable cause) { super(message, cause); } } java/javax/sip/address/0040755 0000000 0000000 00000000000 13513104763 014065 5ustar000000000 0000000 java/javax/sip/address/Address.java0100644 0000000 0000000 00000001053 13513104763 016311 0ustar000000000 0000000 package javax.sip.address; import java.io.Serializable; import java.text.ParseException; public interface Address extends Cloneable, Serializable { String getDisplayName(); void setDisplayName(String displayName) throws ParseException; boolean hasDisplayName(); String getHost(); int getPort(); String getUserAtHostPort(); boolean isSIPAddress(); URI getURI(); void setURI(URI uri); boolean isWildcard(); void setWildCardFlag(); boolean equals(Object obj); int hashCode(); Object clone(); } java/javax/sip/address/AddressFactory.java0100644 0000000 0000000 00000001063 13513104763 017642 0ustar000000000 0000000 package javax.sip.address; import java.text.ParseException; public interface AddressFactory { Address createAddress(); Address createAddress(String address) throws ParseException; Address createAddress(URI uri); Address createAddress(String displayName, URI uri) throws ParseException; SipURI createSipURI(String uri) throws ParseException; SipURI createSipURI(String user, String host) throws ParseException; TelURL createTelURL(String uri) throws ParseException; URI createURI(String uri) throws ParseException; } java/javax/sip/address/Hop.java0100644 0000000 0000000 00000000311 13513104763 015446 0ustar000000000 0000000 package javax.sip.address; public interface Hop { String getHost(); int getPort(); String getTransport(); boolean isURIRoute(); void setURIRouteFlag(); String toString(); } java/javax/sip/address/Router.java0100644 0000000 0000000 00000000436 13513104763 016210 0ustar000000000 0000000 package javax.sip.address; import java.util.ListIterator; import javax.sip.SipException; import javax.sip.message.Request; public interface Router { Hop getNextHop(Request request) throws SipException; ListIterator getNextHops(Request request); Hop getOutboundProxy(); } java/javax/sip/address/SipURI.java0100644 0000000 0000000 00000002456 13513104763 016047 0ustar000000000 0000000 package javax.sip.address; import java.text.ParseException; import java.util.Iterator; import javax.sip.header.Parameters; import javax.sip.InvalidArgumentException; public interface SipURI extends URI, Parameters { boolean isSecure(); void setSecure(boolean secure); String getHeader(String name); void setHeader(String name, String value); Iterator getHeaderNames(); String getHost(); void setHost(String host) throws ParseException; String getLrParam(); void setLrParam(); boolean hasLrParam(); String getMAddrParam(); void setMAddrParam(String mAddrParam) throws ParseException; int getPort(); void setPort(int port) throws InvalidArgumentException; int getTTLParam(); void setTTLParam(int ttlParam); String getTransportParam(); void setTransportParam(String transportParam) throws ParseException; boolean hasTransport(); String getUser(); void setUser(String user); String getUserParam(); void setUserParam(String userParam); String getUserType(); void removeUserType(); String getUserPassword(); void setUserPassword(String userPassword); String getUserAtHost(); String getUserAtHostPort(); String getMethodParam(); void setMethodParam(String methodParam) throws ParseException; } java/javax/sip/address/TelURL.java0100644 0000000 0000000 00000001131 13513104763 016030 0ustar000000000 0000000 package javax.sip.address; import java.text.ParseException; import javax.sip.header.Parameters; public interface TelURL extends URI, Parameters { String getIsdnSubAddress(); void setIsdnSubAddress(String isdnSubAddress) throws ParseException; String getPhoneContext(); void setPhoneContext(String phoneContext) throws ParseException; String getPhoneNumber(); void setPhoneNumber(String phoneNumber) throws ParseException; String getPostDial(); void setPostDial(String postDial) throws ParseException; boolean isGlobal(); void setGlobal(boolean global); } java/javax/sip/address/URI.java0100644 0000000 0000000 00000000320 13513104763 015357 0ustar000000000 0000000 package javax.sip.address; import java.io.Serializable; public interface URI extends Cloneable, Serializable { String getScheme(); boolean isSipURI(); Object clone(); String toString(); } java/javax/sip/header/0040755 0000000 0000000 00000000000 13513104763 013670 5ustar000000000 0000000 java/javax/sip/header/AcceptEncodingHeader.java0100644 0000000 0000000 00000000425 13513104763 020510 0ustar000000000 0000000 package javax.sip.header; import javax.sip.InvalidArgumentException; public interface AcceptEncodingHeader extends Encoding, Header, Parameters { String NAME = "Accept-Encoding"; float getQValue(); void setQValue(float qValue) throws InvalidArgumentException; } java/javax/sip/header/AcceptHeader.java0100644 0000000 0000000 00000000605 13513104763 017041 0ustar000000000 0000000 package javax.sip.header; import javax.sip.InvalidArgumentException; public interface AcceptHeader extends Header, MediaType, Parameters { String NAME = "Accept"; boolean allowsAllContentSubTypes(); boolean allowsAllContentTypes(); float getQValue(); void setQValue(float qValue) throws InvalidArgumentException; boolean hasQValue(); void removeQValue(); } java/javax/sip/header/AcceptLanguageHeader.java0100644 0000000 0000000 00000000733 13513104763 020507 0ustar000000000 0000000 package javax.sip.header; import java.util.Locale; import javax.sip.InvalidArgumentException; public interface AcceptLanguageHeader extends Header, Parameters { String NAME = "Accept-Language"; Locale getAcceptLanguage(); void setAcceptLanguage(Locale acceptLanguage); void setLanguageRange(String languageRange); float getQValue(); void setQValue(float qValue) throws InvalidArgumentException; boolean hasQValue(); void removeQValue(); } java/javax/sip/header/AlertInfoHeader.java0100644 0000000 0000000 00000000402 13513104763 017520 0ustar000000000 0000000 package javax.sip.header; import javax.sip.address.URI; public interface AlertInfoHeader extends Header, Parameters { String NAME = "Alert-Info"; URI getAlertInfo(); void setAlertInfo(URI alertInfo); void setAlertInfo(String alertInfo); } java/javax/sip/header/AllowEventsHeader.java0100644 0000000 0000000 00000000360 13513104763 020103 0ustar000000000 0000000 package javax.sip.header; import java.text.ParseException; public interface AllowEventsHeader extends Header { String NAME = "Allow-Events"; String getEventType(); void setEventType(String eventType) throws ParseException; } java/javax/sip/header/AllowHeader.java0100644 0000000 0000000 00000000332 13513104763 016715 0ustar000000000 0000000 package javax.sip.header; import java.text.ParseException; public interface AllowHeader extends Header { String NAME = "Allow"; String getMethod(); void setMethod(String method) throws ParseException; } java/javax/sip/header/AuthenticationInfoHeader.java0100644 0000000 0000000 00000001125 13513104763 021433 0ustar000000000 0000000 package javax.sip.header; import java.text.ParseException; public interface AuthenticationInfoHeader extends Header, Parameters { String NAME = "Authentication-Info"; String getCNonce(); void setCNonce(String cNonce) throws ParseException; String getNextNonce(); void setNextNonce(String nextNonce) throws ParseException; int getNonceCount(); void setNonceCount(int nonceCount) throws ParseException; String getQop(); void setQop(String qop) throws ParseException; String getResponse(); void setResponse(String response) throws ParseException; } java/javax/sip/header/AuthorizationHeader.java0100644 0000000 0000000 00000002123 13513104763 020477 0ustar000000000 0000000 package javax.sip.header; import java.text.ParseException; import javax.sip.address.URI; public interface AuthorizationHeader extends Header, Parameters { String NAME = "Authorization"; String getAlgorithm(); void setAlgorithm(String algorithm) throws ParseException; String getCNonce(); void setCNonce(String cNonce) throws ParseException; String getNonce(); void setNonce(String nonce) throws ParseException; int getNonceCount(); void setNonceCount(int nonceCount) throws ParseException; String getOpaque(); void setOpaque(String opaque) throws ParseException; String getQop(); void setQop(String qop) throws ParseException; String getRealm(); void setRealm(String realm) throws ParseException; String getResponse(); void setResponse(String response) throws ParseException; String getScheme(); void setScheme(String scheme); boolean isStale(); void setStale(boolean stale); URI getURI(); void setURI(URI uri); String getUsername(); void setUsername(String username) throws ParseException; } java/javax/sip/header/CSeqHeader.java0100644 0000000 0000000 00000000165 13513104763 016476 0ustar000000000 0000000 package javax.sip.header; public interface CSeqHeader extends AllowHeader, RSeqHeader { String NAME = "CSeq"; } java/javax/sip/header/CallIdHeader.java0100644 0000000 0000000 00000000335 13513104763 016772 0ustar000000000 0000000 package javax.sip.header; import java.text.ParseException; public interface CallIdHeader extends Header { String NAME = "Call-ID"; String getCallId(); void setCallId(String callId) throws ParseException; } java/javax/sip/header/CallInfoHeader.java0100644 0000000 0000000 00000000407 13513104763 017331 0ustar000000000 0000000 package javax.sip.header; import javax.sip.address.URI; public interface CallInfoHeader extends Header, Parameters { String NAME = "Call-Info"; URI getInfo(); void setInfo(URI info); String getPurpose(); void setPurpose(String purpose); } java/javax/sip/header/ContactHeader.java0100644 0000000 0000000 00000000707 13513104763 017240 0ustar000000000 0000000 package javax.sip.header; import javax.sip.InvalidArgumentException; public interface ContactHeader extends HeaderAddress, Header, Parameters { String NAME = "Contact"; int getExpires(); void setExpires(int expires) throws InvalidArgumentException; float getQValue(); void setQValue(float qValue) throws InvalidArgumentException; boolean isWildCard(); void setWildCard(); void setWildCardFlag(boolean wildCardFlag); } java/javax/sip/header/ContentDispositionHeader.java0100644 0000000 0000000 00000000751 13513104763 021503 0ustar000000000 0000000 package javax.sip.header; import java.text.ParseException; public interface ContentDispositionHeader extends Header, Parameters { String NAME = "Content-Disposition"; String RENDER = "Render"; String SESSION = "Session"; String ICON = "Icon"; String ALERT = "Alert"; String getDispositionType(); void setDispositionType(String dispositionType) throws ParseException; String getHandling(); void setHandling(String handling) throws ParseException; } java/javax/sip/header/ContentEncodingHeader.java0100644 0000000 0000000 00000000205 13513104763 020717 0ustar000000000 0000000 package javax.sip.header; public interface ContentEncodingHeader extends Encoding, Header { String NAME = "Content-Encoding"; } java/javax/sip/header/ContentLanguageHeader.java0100644 0000000 0000000 00000000460 13513104763 020717 0ustar000000000 0000000 package javax.sip.header; import java.util.Locale; public interface ContentLanguageHeader extends Header { String NAME = "Content-Language"; Locale getContentLanguage(); void setContentLanguage(Locale language); String getLanguageTag(); void setLanguageTag(String languageTag); } java/javax/sip/header/ContentLengthHeader.java0100644 0000000 0000000 00000000416 13513104763 020416 0ustar000000000 0000000 package javax.sip.header; import javax.sip.InvalidArgumentException; public interface ContentLengthHeader extends Header { String NAME = "Content-Length"; int getContentLength(); void setContentLength(int contentLength) throws InvalidArgumentException; } java/javax/sip/header/ContentTypeHeader.java0100644 0000000 0000000 00000000454 13513104763 020120 0ustar000000000 0000000 package javax.sip.header; import java.text.ParseException; public interface ContentTypeHeader extends Header, MediaType, Parameters { String NAME = "Content-Type"; String getCharset(); void setContentType(String contentType, String contentSubType) throws ParseException; } java/javax/sip/header/DateHeader.java0100644 0000000 0000000 00000000272 13513104763 016517 0ustar000000000 0000000 package javax.sip.header; import java.util.Calendar; public interface DateHeader extends Header { String NAME = "Date"; Calendar getDate(); void setDate(Calendar date); } java/javax/sip/header/Encoding.java0100644 0000000 0000000 00000000262 13513104763 016256 0ustar000000000 0000000 package javax.sip.header; import java.text.ParseException; public interface Encoding { String getEncoding(); void setEncoding(String encoding) throws ParseException; } java/javax/sip/header/ErrorInfoHeader.java0100644 0000000 0000000 00000000536 13513104763 017552 0ustar000000000 0000000 package javax.sip.header; import java.text.ParseException; import javax.sip.address.URI; public interface ErrorInfoHeader extends Header, Parameters { String NAME = "Error-Info"; URI getErrorInfo(); void setErrorInfo(URI errorInfo); String getErrorMessage(); void setErrorMessage(String errorMessage) throws ParseException; } java/javax/sip/header/EventHeader.java0100644 0000000 0000000 00000000504 13513104763 016721 0ustar000000000 0000000 package javax.sip.header; import java.text.ParseException; public interface EventHeader extends Header, Parameters { String NAME = "Event"; String getEventId(); void setEventId(String eventId) throws ParseException; String getEventType(); void setEventType(String eventType) throws ParseException; } java/javax/sip/header/ExpiresHeader.java0100644 0000000 0000000 00000000357 13513104763 017265 0ustar000000000 0000000 package javax.sip.header; import javax.sip.InvalidArgumentException; public interface ExpiresHeader extends Header { String NAME = "Expires"; int getExpires(); void setExpires(int expires) throws InvalidArgumentException; } java/javax/sip/header/ExtensionHeader.java0100644 0000000 0000000 00000000277 13513104763 017623 0ustar000000000 0000000 package javax.sip.header; import java.text.ParseException; public interface ExtensionHeader extends Header { String getValue(); void setValue(String value) throws ParseException; } java/javax/sip/header/FromHeader.java0100644 0000000 0000000 00000000524 13513104763 016545 0ustar000000000 0000000 package javax.sip.header; import java.text.ParseException; public interface FromHeader extends HeaderAddress, Header, Parameters { String NAME = "From"; String getTag(); void setTag(String tag) throws ParseException; boolean hasTag(); void removeTag(); String getDisplayName(); String getUserAtHostPort(); } java/javax/sip/header/Header.java0100644 0000000 0000000 00000000353 13513104763 015721 0ustar000000000 0000000 package javax.sip.header; import java.io.Serializable; public interface Header extends Cloneable, Serializable { String getName(); Object clone(); boolean equals(Object obj); int hashCode(); String toString(); } java/javax/sip/header/HeaderAddress.java0100644 0000000 0000000 00000000241 13513104763 017223 0ustar000000000 0000000 package javax.sip.header; import javax.sip.address.Address; public interface HeaderAddress { Address getAddress(); void setAddress(Address address); } java/javax/sip/header/HeaderFactory.java0100644 0000000 0000000 00000014205 13513104763 017252 0ustar000000000 0000000 package javax.sip.header; import java.text.ParseException; import java.util.Calendar; import java.util.List; import java.util.Locale; import javax.sip.InvalidArgumentException; import javax.sip.address.Address; import javax.sip.address.URI; public interface HeaderFactory { void setPrettyEncoding(boolean flag); AcceptEncodingHeader createAcceptEncodingHeader(String encoding) throws ParseException; AcceptHeader createAcceptHeader(String contentType, String contentSubType) throws ParseException; AcceptLanguageHeader createAcceptLanguageHeader(Locale language); AlertInfoHeader createAlertInfoHeader(URI alertInfo); AllowEventsHeader createAllowEventsHeader(String eventType) throws ParseException; AllowHeader createAllowHeader(String method) throws ParseException; AuthenticationInfoHeader createAuthenticationInfoHeader(String response) throws ParseException; AuthorizationHeader createAuthorizationHeader(String scheme) throws ParseException; CallIdHeader createCallIdHeader(String callId) throws ParseException; CallInfoHeader createCallInfoHeader(URI callInfo); ContactHeader createContactHeader(); ContactHeader createContactHeader(Address address); ContentDispositionHeader createContentDispositionHeader( String contentDispositionType) throws ParseException; ContentEncodingHeader createContentEncodingHeader(String encoding) throws ParseException; ContentLanguageHeader createContentLanguageHeader(Locale contentLanguage); ContentLengthHeader createContentLengthHeader(int contentLength) throws InvalidArgumentException; ContentTypeHeader createContentTypeHeader(String contentType, String contentSubType) throws ParseException; /** * @deprecated * @see #createCSeqHeader(long, String) */ CSeqHeader createCSeqHeader(int sequenceNumber, String method) throws ParseException, InvalidArgumentException; CSeqHeader createCSeqHeader(long sequenceNumber, String method) throws ParseException, InvalidArgumentException; DateHeader createDateHeader(Calendar date); ErrorInfoHeader createErrorInfoHeader(URI errorInfo); EventHeader createEventHeader(String eventType) throws ParseException; ExpiresHeader createExpiresHeader(int expires) throws InvalidArgumentException; ExtensionHeader createExtensionHeader(String name, String value) throws ParseException; FromHeader createFromHeader(Address address, String tag) throws ParseException; Header createHeader(String name, String value) throws ParseException; Header createHeader(String headerText) throws ParseException; List createHeaders(String headers) throws ParseException; InReplyToHeader createInReplyToHeader(String callId) throws ParseException; MaxForwardsHeader createMaxForwardsHeader(int maxForwards) throws InvalidArgumentException; MimeVersionHeader createMimeVersionHeader(int majorVersion, int minorVersion) throws InvalidArgumentException; MinExpiresHeader createMinExpiresHeader(int minExpires) throws InvalidArgumentException; OrganizationHeader createOrganizationHeader(String organization) throws ParseException; PriorityHeader createPriorityHeader(String priority) throws ParseException; ProxyAuthenticateHeader createProxyAuthenticateHeader(String scheme) throws ParseException; ProxyAuthorizationHeader createProxyAuthorizationHeader(String scheme) throws ParseException; ProxyRequireHeader createProxyRequireHeader(String optionTag) throws ParseException; RAckHeader createRAckHeader(long rSeqNumber, long cSeqNumber, String method) throws InvalidArgumentException, ParseException; /** * @deprecated * @see #createRAckHeader(long, long, String) */ RAckHeader createRAckHeader(int rSeqNumber, int cSeqNumber, String method) throws InvalidArgumentException, ParseException; ReasonHeader createReasonHeader(String protocol, int cause, String text) throws InvalidArgumentException, ParseException; RecordRouteHeader createRecordRouteHeader(Address address); ReferToHeader createReferToHeader(Address address); ReplyToHeader createReplyToHeader(Address address); RequireHeader createRequireHeader(String optionTag) throws ParseException; RetryAfterHeader createRetryAfterHeader(int retryAfter) throws InvalidArgumentException; RouteHeader createRouteHeader(Address address); RSeqHeader createRSeqHeader(long sequenceNumber) throws InvalidArgumentException; /** * @deprecated * @see #createRSeqHeader(long) */ RSeqHeader createRSeqHeader(int sequenceNumber) throws InvalidArgumentException; ServerHeader createServerHeader(List product) throws ParseException; SIPETagHeader createSIPETagHeader(String etag) throws ParseException; SIPIfMatchHeader createSIPIfMatchHeader(String etag) throws ParseException; SubjectHeader createSubjectHeader(String subject) throws ParseException; SubscriptionStateHeader createSubscriptionStateHeader( String subscriptionState) throws ParseException; SupportedHeader createSupportedHeader(String optionTag) throws ParseException; TimeStampHeader createTimeStampHeader(float timeStamp) throws InvalidArgumentException; ToHeader createToHeader(Address address, String tag) throws ParseException; UnsupportedHeader createUnsupportedHeader(String optionTag) throws ParseException; UserAgentHeader createUserAgentHeader(List product) throws ParseException; ViaHeader createViaHeader(String host, int port, String transport, String branch) throws InvalidArgumentException, ParseException; WarningHeader createWarningHeader(String agent, int code, String comment) throws InvalidArgumentException, ParseException; WWWAuthenticateHeader createWWWAuthenticateHeader(String scheme) throws ParseException; } java/javax/sip/header/InReplyToHeader.java0100644 0000000 0000000 00000000166 13513104763 017531 0ustar000000000 0000000 package javax.sip.header; public interface InReplyToHeader extends CallIdHeader { String NAME = "In-Reply-To"; } java/javax/sip/header/MaxForwardsHeader.java0100644 0000000 0000000 00000000541 13513104763 020076 0ustar000000000 0000000 package javax.sip.header; import javax.sip.InvalidArgumentException; public interface MaxForwardsHeader extends Header { String NAME = "Max-Forwards"; void decrementMaxForwards() throws TooManyHopsException; int getMaxForwards(); void setMaxForwards(int maxForwards) throws InvalidArgumentException; boolean hasReachedZero(); } java/javax/sip/header/MediaType.java0100644 0000000 0000000 00000000446 13513104763 016415 0ustar000000000 0000000 package javax.sip.header; import java.text.ParseException; public interface MediaType { String getContentSubType(); void setContentSubType(String contentSubType) throws ParseException; String getContentType(); void setContentType(String contentType) throws ParseException; } java/javax/sip/header/MimeVersionHeader.java0100644 0000000 0000000 00000000557 13513104763 020105 0ustar000000000 0000000 package javax.sip.header; import javax.sip.InvalidArgumentException; public interface MimeVersionHeader extends Header { String NAME = "MIME-Version"; int getMajorVersion(); void setMajorVersion(int majorVersion) throws InvalidArgumentException; int getMinorVersion(); void setMinorVersion(int minorVersion) throws InvalidArgumentException; } java/javax/sip/header/MinExpiresHeader.java0100644 0000000 0000000 00000000170 13513104763 017722 0ustar000000000 0000000 package javax.sip.header; public interface MinExpiresHeader extends ExpiresHeader { String NAME = "Min-Expires"; } java/javax/sip/header/OptionTag.java0100644 0000000 0000000 00000000266 13513104763 016440 0ustar000000000 0000000 package javax.sip.header; import java.text.ParseException; public interface OptionTag { String getOptionTag(); void setOptionTag(String optionTag) throws ParseException; } java/javax/sip/header/OrganizationHeader.java0100644 0000000 0000000 00000000372 13513104763 020307 0ustar000000000 0000000 package javax.sip.header; import java.text.ParseException; public interface OrganizationHeader extends Header { String NAME = "Organization"; String getOrganization(); void setOrganization(String organization) throws ParseException; } java/javax/sip/header/Parameters.java0100644 0000000 0000000 00000000460 13513104763 016633 0ustar000000000 0000000 package javax.sip.header; import java.text.ParseException; import java.util.Iterator; public interface Parameters { String getParameter(String name); void setParameter(String name, String value) throws ParseException; Iterator getParameterNames(); void removeParameter(String name); } java/javax/sip/header/PriorityHeader.java0100644 0000000 0000000 00000000555 13513104763 017467 0ustar000000000 0000000 package javax.sip.header; import java.text.ParseException; public interface PriorityHeader extends Header { String NAME = "Priority"; String NON_URGENT = "Non-Urgent"; String NORMAL = "Normal"; String URGENT = "Urgent"; String EMERGENCY = "Emergency"; String getPriority(); void setPriority(String priority) throws ParseException; } java/javax/sip/header/ProxyAuthenticateHeader.java0100644 0000000 0000000 00000000216 13513104763 021320 0ustar000000000 0000000 package javax.sip.header; public interface ProxyAuthenticateHeader extends WWWAuthenticateHeader { String NAME = "Proxy-Authenticate"; } java/javax/sip/header/ProxyAuthorizationHeader.java0100644 0000000 0000000 00000000216 13513104763 021542 0ustar000000000 0000000 package javax.sip.header; public interface ProxyAuthorizationHeader extends AuthorizationHeader { String NAME = "Proxy-Authorization"; } java/javax/sip/header/ProxyRequireHeader.java0100644 0000000 0000000 00000000174 13513104763 020321 0ustar000000000 0000000 package javax.sip.header; public interface ProxyRequireHeader extends RequireHeader { String NAME = "Proxy-Require"; } java/javax/sip/header/RAckHeader.java0100644 0000000 0000000 00000001711 13513104763 016461 0ustar000000000 0000000 package javax.sip.header; import java.text.ParseException; import javax.sip.InvalidArgumentException; public interface RAckHeader extends Header { String NAME = "RAck"; String getMethod(); void setMethod(String method) throws ParseException; long getCSequenceNumber(); void setCSequenceNumber(long cSequenceNumber) throws InvalidArgumentException; long getRSequenceNumber(); void setRSequenceNumber(long rSequenceNumber) throws InvalidArgumentException; /** * @deprecated * @see #getCSequenceNumber() */ int getCSeqNumber(); /** * @deprecated * @see #setCSequenceNumber(long) */ void setCSeqNumber(int cSeqNumber) throws InvalidArgumentException; /** * @deprecated * @see #getRSequenceNumber() */ int getRSeqNumber(); /** * @deprecated * @see #setRSequenceNumber(long) */ void setRSeqNumber(int rSeqNumber) throws InvalidArgumentException; } java/javax/sip/header/RSeqHeader.java0100644 0000000 0000000 00000000747 13513104763 016523 0ustar000000000 0000000 package javax.sip.header; import javax.sip.InvalidArgumentException; public interface RSeqHeader extends Header { String NAME = "RSeq"; long getSeqNumber(); void setSeqNumber(long sequenceNumber) throws InvalidArgumentException; /** * @deprecated * @see #getSeqNumber() */ int getSequenceNumber(); /** * @deprecated * @see #setSeqNumber(long) */ void setSequenceNumber(int sequenceNumber) throws InvalidArgumentException; } java/javax/sip/header/ReasonHeader.java0100644 0000000 0000000 00000000670 13513104763 017073 0ustar000000000 0000000 package javax.sip.header; import java.text.ParseException; import javax.sip.InvalidArgumentException; public interface ReasonHeader extends Header, Parameters { String NAME = "Reason"; int getCause(); void setCause(int cause) throws InvalidArgumentException; String getProtocol(); void setProtocol(String protocol) throws ParseException; String getText(); void setText(String text) throws ParseException; } java/javax/sip/header/RecordRouteHeader.java0100644 0000000 0000000 00000000216 13513104763 020075 0ustar000000000 0000000 package javax.sip.header; public interface RecordRouteHeader extends HeaderAddress, Header, Parameters { String NAME = "Record-Route"; } java/javax/sip/header/ReferToHeader.java0100644 0000000 0000000 00000000206 13513104763 017205 0ustar000000000 0000000 package javax.sip.header; public interface ReferToHeader extends HeaderAddress, Header, Parameters { String NAME = "Refer-To"; } java/javax/sip/header/ReplyToHeader.java0100644 0000000 0000000 00000000244 13513104763 017237 0ustar000000000 0000000 package javax.sip.header; public interface ReplyToHeader extends HeaderAddress, Header, Parameters { String NAME = "Reply-To"; String getDisplayName(); } java/javax/sip/header/RequireHeader.java0100644 0000000 0000000 00000000165 13513104763 017257 0ustar000000000 0000000 package javax.sip.header; public interface RequireHeader extends OptionTag, Header { String NAME = "Require"; } java/javax/sip/header/RetryAfterHeader.java0100644 0000000 0000000 00000001054 13513104763 017730 0ustar000000000 0000000 package javax.sip.header; import java.text.ParseException; import javax.sip.InvalidArgumentException; public interface RetryAfterHeader extends Header, Parameters { String NAME = "Retry-After"; String getComment(); void setComment(String comment) throws ParseException; boolean hasComment(); void removeComment(); int getDuration(); void setDuration(int duration) throws InvalidArgumentException; void removeDuration(); int getRetryAfter(); void setRetryAfter(int retryAfter) throws InvalidArgumentException; } java/javax/sip/header/RouteHeader.java0100644 0000000 0000000 00000000201 13513104763 016730 0ustar000000000 0000000 package javax.sip.header; public interface RouteHeader extends HeaderAddress, Header, Parameters { String NAME = "Route"; } java/javax/sip/header/SIPETagHeader.java0100644 0000000 0000000 00000000342 13513104763 017034 0ustar000000000 0000000 package javax.sip.header; import java.text.ParseException; public interface SIPETagHeader extends ExtensionHeader { String NAME = "SIP-ETag"; String getETag(); void setETag(String etag) throws ParseException; } java/javax/sip/header/SIPIfMatchHeader.java0100644 0000000 0000000 00000000171 13513104763 017527 0ustar000000000 0000000 package javax.sip.header; public interface SIPIfMatchHeader extends SIPETagHeader { String NAME = "SIP-If-Match"; } java/javax/sip/header/ServerHeader.java0100644 0000000 0000000 00000000510 13513104763 017103 0ustar000000000 0000000 package javax.sip.header; import java.text.ParseException; import java.util.List; import java.util.ListIterator; public interface ServerHeader extends Header { String NAME = "Server"; ListIterator getProduct(); void setProduct(List product) throws ParseException; void addProductToken(String productToken); } java/javax/sip/header/SubjectHeader.java0100644 0000000 0000000 00000000341 13513104763 017236 0ustar000000000 0000000 package javax.sip.header; import java.text.ParseException; public interface SubjectHeader extends Header { String NAME = "Subject"; String getSubject(); void setSubject(String subject) throws ParseException; } java/javax/sip/header/SubscriptionStateHeader.java0100644 0000000 0000000 00000001512 13513104763 021325 0ustar000000000 0000000 package javax.sip.header; import java.text.ParseException; import javax.sip.InvalidArgumentException; public interface SubscriptionStateHeader extends ExpiresHeader, Parameters { String NAME = "Subscription-State"; String DEACTIVATED = "Deactivated"; String GIVE_UP = "Give-Up"; String NO_RESOURCE = "No-Resource"; String PROBATION = "Probation"; String REJECTED = "Rejected"; String TIMEOUT = "Timeout"; String UNKNOWN = "Unknown"; String ACTIVE = "Active"; String PENDING = "Pending"; String TERMINATED = "Terminated"; String getReasonCode(); void setReasonCode(String reasonCode) throws ParseException; int getRetryAfter(); void setRetryAfter(int retryAfter) throws InvalidArgumentException; String getState(); void setState(String state) throws ParseException; } java/javax/sip/header/SupportedHeader.java0100644 0000000 0000000 00000000171 13513104763 017625 0ustar000000000 0000000 package javax.sip.header; public interface SupportedHeader extends OptionTag, Header { String NAME = "Supported"; } java/javax/sip/header/TimeStampHeader.java0100644 0000000 0000000 00000001066 13513104763 017547 0ustar000000000 0000000 package javax.sip.header; import javax.sip.InvalidArgumentException; public interface TimeStampHeader extends Header { String NAME = "Timestamp"; float getDelay(); void setDelay(float delay) throws InvalidArgumentException; boolean hasDelay(); void removeDelay(); long getTime(); void setTime(long timeStamp) throws InvalidArgumentException; int getTimeDelay(); void setTimeDelay(int delay) throws InvalidArgumentException; float getTimeStamp(); void setTimeStamp(float timeStamp) throws InvalidArgumentException; } java/javax/sip/header/ToHeader.java0100644 0000000 0000000 00000000520 13513104763 016220 0ustar000000000 0000000 package javax.sip.header; import java.text.ParseException; public interface ToHeader extends HeaderAddress, Header, Parameters { String NAME = "To"; String getTag(); void setTag(String tag) throws ParseException; boolean hasTag(); void removeTag(); String getDisplayName(); String getUserAtHostPort(); } java/javax/sip/header/TooManyHopsException.java0100644 0000000 0000000 00000000510 13513104763 020623 0ustar000000000 0000000 package javax.sip.header; public class TooManyHopsException extends Exception { public TooManyHopsException(){ super(); } public TooManyHopsException(String message) { super(message); } public TooManyHopsException(String message, Throwable cause) { super(message, cause); } } java/javax/sip/header/UnsupportedHeader.java0100644 0000000 0000000 00000000175 13513104763 020174 0ustar000000000 0000000 package javax.sip.header; public interface UnsupportedHeader extends OptionTag, Header { String NAME = "Unsupported"; } java/javax/sip/header/UserAgentHeader.java0100644 0000000 0000000 00000000517 13513104763 017541 0ustar000000000 0000000 package javax.sip.header; import java.text.ParseException; import java.util.List; import java.util.ListIterator; public interface UserAgentHeader extends Header { String NAME = "User-Agent"; ListIterator getProduct(); void setProduct(List product) throws ParseException; void addProductToken(String productToken); } java/javax/sip/header/ViaHeader.java0100644 0000000 0000000 00000001733 13513104763 016364 0ustar000000000 0000000 package javax.sip.header; import java.text.ParseException; import javax.sip.InvalidArgumentException; public interface ViaHeader extends Header, Parameters { String NAME = "Via"; String getBranch(); void setBranch(String branch) throws ParseException; String getHost(); void setHost(String host) throws ParseException; String getMAddr(); void setMAddr(String mAddr) throws ParseException; int getPort(); void setPort(int port) throws InvalidArgumentException; String getProtocol(); void setProtocol(String protocol) throws ParseException; String getReceived(); void setReceived(String received) throws ParseException; int getRPort(); void setRPort() throws InvalidArgumentException; String getTransport(); void setTransport(String transport) throws ParseException; int getTTL(); void setTTL(int ttl) throws InvalidArgumentException; String getSentByField(); String getSentProtocolField(); } java/javax/sip/header/WWWAuthenticateHeader.java0100644 0000000 0000000 00000000542 13513104763 020665 0ustar000000000 0000000 package javax.sip.header; import javax.sip.address.URI; public interface WWWAuthenticateHeader extends AuthorizationHeader { String NAME = "WWW-Authenticate"; /** * @deprecated This method should return null. */ URI getURI(); /** * @deprecated This method should return immediately. */ void setURI(URI uri); } java/javax/sip/header/WarningHeader.java0100644 0000000 0000000 00000001637 13513104763 017255 0ustar000000000 0000000 package javax.sip.header; import java.text.ParseException; import javax.sip.InvalidArgumentException; public interface WarningHeader extends Header { String NAME = "Warning"; int ATTRIBUTE_NOT_UNDERSTOOD = 10; int INCOMPATIBLE_BANDWIDTH_UNITS = 20; int INCOMPATIBLE_MEDIA_FORMAT = 21; int INCOMPATIBLE_NETWORK_ADDRESS_FORMATS = 22; int INCOMPATIBLE_NETWORK_PROTOCOL = 23; int INCOMPATIBLE_TRANSPORT_PROTOCOL = 24; int INSUFFICIENT_BANDWIDTH = 30; int MEDIA_TYPE_NOT_AVAILABLE = 40; int MISCELLANEOUS_WARNING = 99; int MULTICAST_NOT_AVAILABLE = 50; int SESSION_DESCRIPTION_PARAMETER_NOT_UNDERSTOOD = 60; int UNICAST_NOT_AVAILABLE = 51; String getAgent(); void setAgent(String agent) throws ParseException; int getCode(); void setCode(int code) throws InvalidArgumentException; String getText(); void setText(String text) throws ParseException; } java/javax/sip/message/0040755 0000000 0000000 00000000000 13513104763 014064 5ustar000000000 0000000 java/javax/sip/message/Message.java0100644 0000000 0000000 00000004067 13513104763 016317 0ustar000000000 0000000 package javax.sip.message; import java.io.Serializable; import java.text.ParseException; import java.util.ListIterator; import javax.sip.SipException; 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.ExpiresHeader; import javax.sip.header.Header; public interface Message extends Cloneable, Serializable { void addFirst(Header header) throws SipException, NullPointerException; void addHeader(Header header); void addLast(Header header) throws SipException, NullPointerException; Header getHeader(String headerName); void setHeader(Header header); void removeFirst(String headerName) throws NullPointerException; void removeLast(String headerName) throws NullPointerException; void removeHeader(String headerName); ListIterator getHeaderNames(); ListIterator getHeaders(String headerName); ListIterator getUnrecognizedHeaders(); Object getApplicationData(); void setApplicationData(Object applicationData); ContentLengthHeader getContentLength(); void setContentLength(ContentLengthHeader contentLength); ContentLanguageHeader getContentLanguage(); void setContentLanguage(ContentLanguageHeader contentLanguage); ContentEncodingHeader getContentEncoding(); void setContentEncoding(ContentEncodingHeader contentEncoding); ContentDispositionHeader getContentDisposition(); void setContentDisposition(ContentDispositionHeader contentDisposition); Object getContent(); byte[] getRawContent(); void setContent(Object content, ContentTypeHeader contentTypeHeader) throws ParseException; void removeContent(); ExpiresHeader getExpires(); void setExpires(ExpiresHeader expires); String getSIPVersion(); void setSIPVersion(String version) throws ParseException; Object clone(); boolean equals(Object object); int hashCode(); String toString(); } java/javax/sip/message/MessageFactory.java0100644 0000000 0000000 00000005330 13513104763 017641 0ustar000000000 0000000 package javax.sip.message; import java.text.ParseException; import java.util.List; import javax.sip.address.URI; import javax.sip.header.CSeqHeader; import javax.sip.header.CallIdHeader; import javax.sip.header.ContentTypeHeader; import javax.sip.header.FromHeader; import javax.sip.header.MaxForwardsHeader; import javax.sip.header.ServerHeader; import javax.sip.header.ToHeader; import javax.sip.header.UserAgentHeader; public interface MessageFactory { Request createRequest(URI requestURI, String method, CallIdHeader callId, CSeqHeader cSeq, FromHeader from, ToHeader to, List via, MaxForwardsHeader maxForwards, ContentTypeHeader contentType, Object content) throws ParseException; Request createRequest(URI requestURI, String method, CallIdHeader callId, CSeqHeader cSeq, FromHeader from, ToHeader to, List via, MaxForwardsHeader maxForwards, ContentTypeHeader contentType, byte[] content) throws ParseException; Request createRequest(URI requestURI, String method, CallIdHeader callId, CSeqHeader cSeq, FromHeader from, ToHeader to, List via, MaxForwardsHeader maxForwards) throws ParseException; Request createRequest(String request) throws ParseException; Response createResponse(int statusCode, CallIdHeader callId, CSeqHeader cSeq, FromHeader from, ToHeader to, List via, MaxForwardsHeader maxForwards, ContentTypeHeader contentType, Object content) throws ParseException; Response createResponse(int statusCode, CallIdHeader callId, CSeqHeader cSeq, FromHeader from, ToHeader to, List via, MaxForwardsHeader maxForwards, ContentTypeHeader contentType, byte[] content) throws ParseException; Response createResponse(int statusCode, CallIdHeader callId, CSeqHeader cSeq, FromHeader from, ToHeader to, List via, MaxForwardsHeader maxForwards) throws ParseException; Response createResponse(int statusCode, Request request, ContentTypeHeader contentType, Object content) throws ParseException; Response createResponse(int statusCode, Request request, ContentTypeHeader contentType, byte[] content) throws ParseException; Response createResponse(int statusCode, Request request) throws ParseException; Response createResponse(String response) throws ParseException; void setDefaultContentEncodingCharset(String defaultContentEncodingCharset) throws NullPointerException, IllegalArgumentException; void setDefaultServerHeader(ServerHeader defaultServerHeader); void setDefaultUserAgentHeader(UserAgentHeader defaultUserAgentHeader); } java/javax/sip/message/Request.java0100644 0000000 0000000 00000001277 13513104763 016363 0ustar000000000 0000000 package javax.sip.message; import java.text.ParseException; import javax.sip.address.URI; public interface Request extends Message { String ACK = "ACK"; String BYE = "BYE"; String CANCEL = "CANCEL"; String INVITE = "INVITE"; String OPTIONS = "OPTIONS"; String REGISTER = "REGISTER"; String INFO = "INFO"; String MESSAGE = "MESSAGE"; String NOTIFY = "NOTIFY"; String PRACK = "PRACK"; String PUBLISH = "PUBLISH"; String REFER = "REFER"; String SUBSCRIBE = "SUBSCRIBE"; String UPDATE = "UPDATE"; String getMethod(); void setMethod(String method) throws ParseException; URI getRequestURI(); void setRequestURI(URI requestURI); } java/javax/sip/message/Response.java0100644 0000000 0000000 00000003661 13513104763 016530 0ustar000000000 0000000 package javax.sip.message; import java.text.ParseException; public interface Response extends Message { int TRYING = 100; int RINGING = 180; int CALL_IS_BEING_FORWARDED = 181; int QUEUED = 182; int SESSION_PROGRESS = 183; int OK = 200; int ACCEPTED = 202; int MULTIPLE_CHOICES = 300; int MOVED_PERMANENTLY = 301; int MOVED_TEMPORARILY = 302; int USE_PROXY = 305; int ALTERNATIVE_SERVICE = 380; int BAD_REQUEST = 400; int UNAUTHORIZED = 401; int PAYMENT_REQUIRED = 402; int FORBIDDEN = 403; int NOT_FOUND = 404; int METHOD_NOT_ALLOWED = 405; int NOT_ACCEPTABLE = 406; int PROXY_AUTHENTICATION_REQUIRED = 407; int REQUEST_TIMEOUT = 408; int GONE = 410; int CONDITIONAL_REQUEST_FAILED = 412; int REQUEST_ENTITY_TOO_LARGE = 413; int REQUEST_URI_TOO_LONG = 414; int UNSUPPORTED_MEDIA_TYPE = 415; int UNSUPPORTED_URI_SCHEME = 416; int BAD_EXTENSION = 420; int EXTENSION_REQUIRED = 421; int INTERVAL_TOO_BRIEF = 423; int TEMPORARILY_UNAVAILABLE = 480; int CALL_OR_TRANSACTION_DOES_NOT_EXIST = 481; int LOOP_DETECTED = 482; int TOO_MANY_HOPS = 483; int ADDRESS_INCOMPLETE = 484; int AMBIGUOUS = 485; int BUSY_HERE = 486; int REQUEST_TERMINATED = 487; int NOT_ACCEPTABLE_HERE = 488; int BAD_EVENT = 489; int REQUEST_PENDING = 491; int UNDECIPHERABLE = 493; int SERVER_INTERNAL_ERROR = 500; int NOT_IMPLEMENTED = 501; int BAD_GATEWAY = 502; int SERVICE_UNAVAILABLE = 503; int SERVER_TIMEOUT = 504; int VERSION_NOT_SUPPORTED = 505; int MESSAGE_TOO_LARGE = 513; int BUSY_EVERYWHERE = 600; int DECLINE = 603; int DOES_NOT_EXIST_ANYWHERE = 604; int SESSION_NOT_ACCEPTABLE = 606; int getStatusCode(); void setStatusCode(int statusCode) throws ParseException; String getReasonPhrase(); void setReasonPhrase(String reasonPhrase) throws ParseException; } licenses/0040755 0000000 0000000 00000000000 13513104763 011420 5ustar000000000 0000000 licenses/README.txt0100644 0000000 0000000 00000000234 13513104763 013112 0ustar000000000 0000000 NIST-CONDITIONS-OF-USE.txt -------------------------- Applies to the classes under the hierarchy "gov.nist" and under the "tools" and "test" hierarchy. version.txt0100644 0000000 0000000 00000000003 13513104763 012027 0ustar000000000 0000000 140