1600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/* 2600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Conditions Of Use 3600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 4600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * This software was developed by employees of the National Institute of 5600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Standards and Technology (NIST), an agency of the Federal Government. 6600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Pursuant to title 15 Untied States Code Section 105, works of NIST 7600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * employees are not subject to copyright protection in the United States 8600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * and are considered to be in the public domain. As a result, a formal 9600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * license is not needed to use the software. 10600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 11600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * This software is provided by NIST as a service and is expressly 12600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED 13600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF 14600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT 15600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * AND DATA ACCURACY. NIST does not warrant or make any representations 16600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * regarding the use of the software or the results thereof, including but 17600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * not limited to the correctness, accuracy, reliability or usefulness of 18600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * the software. 19600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 20600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Permission to use this software is contingent upon your acceptance 21600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * of the terms of this agreement 22600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 23600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * . 24600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 25600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 26600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/******************************************************************************* 27600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Product of NIST/ITL Advanced Networking Technologies Division (ANTD) * 28600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *******************************************************************************/ 29600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangpackage gov.nist.javax.sip.message; 30600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 31600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.address.*; 32600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.core.*; 33600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 34600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.HashSet; 35600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.Hashtable; 36600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.LinkedList; 37600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.Set; 38600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.io.UnsupportedEncodingException; 39600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.Iterator; 40600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.address.URI; 41600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.message.*; 42600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 43600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.text.ParseException; 44600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.*; 45600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.*; 46600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 47600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.*; 48600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.stack.SIPTransactionStack; 49600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 50600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/* 51600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Acknowledgements: Mark Bednarek made a few fixes to this code. Jeff Keyser added two methods 52600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * that create responses and generate cancel requests from incoming orignial requests without the 53600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * additional overhead of encoding and decoding messages. Bruno Konik noticed an extraneous 54600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * newline added to the end of the buffer when encoding it. Incorporates a bug report from Andreas 55600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Bystrom. Szabo Barna noticed a contact in a cancel request - this is a pointless header for 56600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * cancel. Antonis Kyardis contributed bug fixes. Jeroen van Bemmel noted that method names are 57600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * case sensitive, should use equals() in getting CannonicalName 58600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 59600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 60600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 61600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/** 62600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * The SIP Request structure. 63600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 64600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @version 1.2 $Revision: 1.52 $ $Date: 2009/12/16 14:58:40 $ 65600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @since 1.1 66600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 67600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @author M. Ranganathan <br/> 68600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 69600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 70600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 71600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 72600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 73600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangpublic final class SIPRequest extends SIPMessage implements javax.sip.message.Request, RequestExt { 74600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 75600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private static final long serialVersionUID = 3360720013577322927L; 76600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 77600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private static final String DEFAULT_USER = "ip"; 78600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 79600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private static final String DEFAULT_TRANSPORT = "udp"; 80600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 81600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private transient Object transactionPointer; 82600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 83600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private RequestLine requestLine; 84600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 85600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private transient Object messageChannel; 86600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 87600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 88600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 89600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private transient Object inviteTransaction; // The original invite request for a 90600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // given cancel request 91600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 92600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 93600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Set of target refresh methods, currently: INVITE, UPDATE, SUBSCRIBE, NOTIFY, REFER 94600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 95600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * A target refresh request and its response MUST have a Contact 96600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 97600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private static final Set<String> targetRefreshMethods = new HashSet<String>(); 98600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 99600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 100600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * A table that maps a name string to its cannonical constant. This is used to speed up 101600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * parsing of messages .equals reduces to == if we use the constant value. 102600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 103600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private static final Hashtable<String, String> nameTable = new Hashtable<String, String>(); 104600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 105600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private static void putName(String name) { 106600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang nameTable.put(name, name); 107600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 108600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 109600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang static { 110600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang targetRefreshMethods.add(Request.INVITE); 111600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang targetRefreshMethods.add(Request.UPDATE); 112600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang targetRefreshMethods.add(Request.SUBSCRIBE); 113600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang targetRefreshMethods.add(Request.NOTIFY); 114600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang targetRefreshMethods.add(Request.REFER); 115600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 116600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang putName(Request.INVITE); 117600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang putName(Request.BYE); 118600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang putName(Request.CANCEL); 119600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang putName(Request.ACK); 120600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang putName(Request.PRACK); 121600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang putName(Request.INFO); 122600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang putName(Request.MESSAGE); 123600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang putName(Request.NOTIFY); 124600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang putName(Request.OPTIONS); 125600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang putName(Request.PRACK); 126600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang putName(Request.PUBLISH); 127600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang putName(Request.REFER); 128600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang putName(Request.REGISTER); 129600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang putName(Request.SUBSCRIBE); 130600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang putName(Request.UPDATE); 131600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 132600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 133600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 134600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 135600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return true iff the method is a target refresh 136600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 137600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public static boolean isTargetRefresh(String ucaseMethod) { 138600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return targetRefreshMethods.contains(ucaseMethod); 139600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 140600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 141600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 142600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return true iff the method is a dialog creating method 143600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 144600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public static boolean isDialogCreating(String ucaseMethod) { 145600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return SIPTransactionStack.isDialogCreated(ucaseMethod); 146600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 147600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 148600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 149600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Set to standard constants to speed up processing. this makes equals comparisons run much 150600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * faster in the stack because then it is just identity comparision. Character by char 151600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * comparison is not required. The method returns the String CONSTANT corresponding to the 152600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * String name. 153600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 154600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 155600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public static String getCannonicalName(String method) { 156600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 157600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (nameTable.containsKey(method)) 158600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return (String) nameTable.get(method); 159600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else 160600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return method; 161600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 162600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 163600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 164600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the Request Line of the SIPRequest. 165600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 166600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return the request line of the SIP Request. 167600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 168600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 169600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public RequestLine getRequestLine() { 170600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return requestLine; 171600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 172600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 173600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 174600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Set the request line of the SIP Request. 175600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 176600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param requestLine is the request line to set in the SIP Request. 177600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 178600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 179600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void setRequestLine(RequestLine requestLine) { 180600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.requestLine = requestLine; 181600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 182600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 183600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 184600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Constructor. 185600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 186600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public SIPRequest() { 187600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang super(); 188600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 189600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 190600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 191600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Convert to a formatted string for pretty printing. Note that the encode method converts 192600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * this into a sip message that is suitable for transmission. Note hack here if you want to 193600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * convert the nice curly brackets into some grotesque XML tag. 194600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 195600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return a string which can be used to examine the message contents. 196600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 197600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 198600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public String debugDump() { 199600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String superstring = super.debugDump(); 200600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang stringRepresentation = ""; 201600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sprint(SIPRequest.class.getName()); 202600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sprint("{"); 203600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (requestLine != null) 204600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sprint(requestLine.debugDump()); 205600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sprint(superstring); 206600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sprint("}"); 207600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return stringRepresentation; 208600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 209600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 210600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 211600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Check header for constraints. (1) Invite options and bye requests can only have SIP URIs in 212600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * the contact headers. (2) Request must have cseq, to and from and via headers. (3) Method in 213600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * request URI must match that in CSEQ. 214600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 215600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void checkHeaders() throws ParseException { 216600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String prefix = "Missing a required header : "; 217600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 218600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* Check for required headers */ 219600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 220600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (getCSeq() == null) { 221600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new ParseException(prefix + CSeqHeader.NAME, 0); 222600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 223600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (getTo() == null) { 224600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new ParseException(prefix + ToHeader.NAME, 0); 225600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 226600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 227600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.callIdHeader == null || this.callIdHeader.getCallId() == null 228600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || callIdHeader.getCallId().equals("")) { 229600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new ParseException(prefix + CallIdHeader.NAME, 0); 230600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 231600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (getFrom() == null) { 232600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new ParseException(prefix + FromHeader.NAME, 0); 233600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 234600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (getViaHeaders() == null) { 235600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new ParseException(prefix + ViaHeader.NAME, 0); 236600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 2374842dc6980fb830a4eef822e7d85beaab79ce2d2Chia-chi Yeh // BEGIN android-deleted 2384842dc6980fb830a4eef822e7d85beaab79ce2d2Chia-chi Yeh /* 239600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (getMaxForwards() == null) { 240600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new ParseException(prefix + MaxForwardsHeader.NAME, 0); 241600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 2424842dc6980fb830a4eef822e7d85beaab79ce2d2Chia-chi Yeh */ 2434842dc6980fb830a4eef822e7d85beaab79ce2d2Chia-chi Yeh // END android-deleted 244600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 245600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (getTopmostVia() == null) 246600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new ParseException("No via header in request! ", 0); 247600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 248600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (getMethod().equals(Request.NOTIFY)) { 249600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (getHeader(SubscriptionStateHeader.NAME) == null) 250600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new ParseException(prefix + SubscriptionStateHeader.NAME, 0); 251600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 252600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (getHeader(EventHeader.NAME) == null) 253600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new ParseException(prefix + EventHeader.NAME, 0); 254600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 255600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (getMethod().equals(Request.PUBLISH)) { 256600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 257600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * For determining the type of the published event state, the EPA MUST include a 258600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * single Event header field in PUBLISH requests. The value of this header field 259600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * indicates the event package for which this request is publishing event state. 260600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 261600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (getHeader(EventHeader.NAME) == null) 262600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new ParseException(prefix + EventHeader.NAME, 0); 263600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 264600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 265600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 266600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * RFC 3261 8.1.1.8 The Contact header field MUST be present and contain exactly one SIP 267600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * or SIPS URI in any request that can result in the establishment of a dialog. For the 268600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * methods defined in this specification, that includes only the INVITE request. For these 269600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * requests, the scope of the Contact is global. That is, the Contact header field value 270600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * contains the URI at which the UA would like to receive requests, and this URI MUST be 271600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * valid even if used in subsequent requests outside of any dialogs. 272600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 273600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * If the Request-URI or top Route header field value contains a SIPS URI, the Contact 274600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * header field MUST contain a SIPS URI as well. 275600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 276600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (requestLine.getMethod().equals(Request.INVITE) 277600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || requestLine.getMethod().equals(Request.SUBSCRIBE) 278600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || requestLine.getMethod().equals(Request.REFER)) { 279600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.getContactHeader() == null) { 280600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Make sure this is not a target refresh. If this is a target 281600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // refresh its ok not to have a contact header. Otherwise 282600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // contact header is mandatory. 283600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.getToTag() == null) 284600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new ParseException(prefix + ContactHeader.NAME, 0); 285600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 286600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 287600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (requestLine.getUri() instanceof SipUri) { 288600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String scheme = ((SipUri) requestLine.getUri()).getScheme(); 289600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if ("sips".equalsIgnoreCase(scheme)) { 290600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SipUri sipUri = (SipUri) this.getContactHeader().getAddress().getURI(); 291600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!sipUri.getScheme().equals("sips")) { 292600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new ParseException("Scheme for contact should be sips:" + sipUri, 0); 293600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 294600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 295600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 296600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 297600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 298600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 299600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Contact header is mandatory for a SIP INVITE request. 300600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 301600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.getContactHeader() == null 302600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && (this.getMethod().equals(Request.INVITE) 303600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || this.getMethod().equals(Request.REFER) || this.getMethod().equals( 304600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Request.SUBSCRIBE))) { 305600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new ParseException("Contact Header is Mandatory for a SIP INVITE", 0); 306600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 307600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 308600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (requestLine != null && requestLine.getMethod() != null 309600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && getCSeq().getMethod() != null 310600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && requestLine.getMethod().compareTo(getCSeq().getMethod()) != 0) { 311600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new ParseException("CSEQ method mismatch with Request-Line ", 0); 312600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 313600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 314600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 315600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 316600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 317600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 318600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Set the default values in the request URI if necessary. 319600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 320600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected void setDefaults() { 321600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // The request line may be unparseable (set to null by the 322600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // exception handler. 323600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (requestLine == null) 324600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 325600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String method = requestLine.getMethod(); 326600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // The requestLine may be malformed! 327600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (method == null) 328600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 329600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang GenericURI u = requestLine.getUri(); 330600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (u == null) 331600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 332600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (method.compareTo(Request.REGISTER) == 0 || method.compareTo(Request.INVITE) == 0) { 333600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (u instanceof SipUri) { 334600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SipUri sipUri = (SipUri) u; 335600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipUri.setUserParam(DEFAULT_USER); 336600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 337600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipUri.setTransportParam(DEFAULT_TRANSPORT); 338600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (ParseException ex) { 339600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 340600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 341600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 342600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 343600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 344600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 345600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Patch up the request line as necessary. 346600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 347600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected void setRequestLineDefaults() { 348600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String method = requestLine.getMethod(); 349600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (method == null) { 350600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang CSeq cseq = (CSeq) this.getCSeq(); 351600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (cseq != null) { 352600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang method = getCannonicalName(cseq.getMethod()); 353600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang requestLine.setMethod(method); 354600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 355600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 356600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 357600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 358600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 359600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * A conveniance function to access the Request URI. 360600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 361600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return the requestURI if it exists. 362600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 363600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public javax.sip.address.URI getRequestURI() { 364600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.requestLine == null) 365600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return null; 366600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else 367600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return (javax.sip.address.URI) this.requestLine.getUri(); 368600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 369600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 370600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 371600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Sets the RequestURI of Request. The Request-URI is a SIP or SIPS URI or a general URI. It 372600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * indicates the user or service to which this request is being addressed. SIP elements MAY 373600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * support Request-URIs with schemes other than "sip" and "sips", for example the "tel" URI 374600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * scheme. SIP elements MAY translate non-SIP URIs using any mechanism at their disposal, 375600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * resulting in SIP URI, SIPS URI, or some other scheme. 376600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 377600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param uri the new Request URI of this request message 378600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 379600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void setRequestURI(URI uri) { 380600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if ( uri == null ) { 381600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new NullPointerException("Null request URI"); 382600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 383600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.requestLine == null) { 384600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.requestLine = new RequestLine(); 385600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 386600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.requestLine.setUri((GenericURI) uri); 387600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.nullRequest = false; 388600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 389600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 390600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 391600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Set the method. 392600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 393600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param method is the method to set. 394600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @throws IllegalArgumentException if the method is null 395600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 396600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void setMethod(String method) { 397600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (method == null) 398600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new IllegalArgumentException("null method"); 399600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.requestLine == null) { 400600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.requestLine = new RequestLine(); 401600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 402600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 403600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Set to standard constants to speed up processing. 404600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // this makes equals compares run much faster in the 405600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // stack because then it is just identity comparision 406600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 407600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String meth = getCannonicalName(method); 408600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.requestLine.setMethod(meth); 409600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 410600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.cSeqHeader != null) { 411600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 412600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.cSeqHeader.setMethod(meth); 413600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (ParseException e) { 414600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 415600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 416600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 417600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 418600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 419600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the method from the request line. 420600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 421600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return the method from the request line if the method exits and null if the request line 422600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * or the method does not exist. 423600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 424600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public String getMethod() { 425600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (requestLine == null) 426600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return null; 427600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else 428600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return requestLine.getMethod(); 429600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 430600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 431600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 432600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Encode the SIP Request as a string. 433600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 434600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return an encoded String containing the encoded SIP Message. 435600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 436600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 437600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public String encode() { 438600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String retval; 439600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (requestLine != null) { 440600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.setRequestLineDefaults(); 441600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval = requestLine.encode() + super.encode(); 442600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (this.isNullRequest()) { 443600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval = "\r\n\r\n"; 444600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 445600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval = super.encode(); 446600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 447600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return retval; 448600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 449600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 450600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 451600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Encode only the headers and not the content. 452600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 453600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public String encodeMessage() { 454600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String retval; 455600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (requestLine != null) { 456600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.setRequestLineDefaults(); 457600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval = requestLine.encode() + super.encodeSIPHeaders(); 458600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (this.isNullRequest()) { 459600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval = "\r\n\r\n"; 460600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else 461600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval = super.encodeSIPHeaders(); 462600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return retval; 463600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 464600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 465600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 466600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 467600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * ALias for encode above. 468600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 469600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public String toString() { 470600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.encode(); 471600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 472600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 473600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 474600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Make a clone (deep copy) of this object. You can use this if you want to modify a request 475600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * while preserving the original 476600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 477600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return a deep copy of this object. 478600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 479600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 480600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public Object clone() { 481600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPRequest retval = (SIPRequest) super.clone(); 482600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Do not copy over the tx pointer -- this is only for internal 483600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // tracking. 484600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.transactionPointer = null; 485600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.requestLine != null) 486600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.requestLine = (RequestLine) this.requestLine.clone(); 487600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 488600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return retval; 489600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 490600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 491600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 492600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Compare for equality. 493600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 494600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param other object to compare ourselves with. 495600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 496600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public boolean equals(Object other) { 497600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!this.getClass().equals(other.getClass())) 498600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return false; 499600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPRequest that = (SIPRequest) other; 500600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 501600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return requestLine.equals(that.requestLine) && super.equals(other); 502600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 503600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 504600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 505600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the message as a linked list of strings. Use this if you want to iterate through the 506600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * message. 507600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 508600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return a linked list containing the request line and headers encoded as strings. 509600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 510600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public LinkedList getMessageAsEncodedStrings() { 511600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang LinkedList retval = super.getMessageAsEncodedStrings(); 512600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (requestLine != null) { 513600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.setRequestLineDefaults(); 514600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.addFirst(requestLine.encode()); 515600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 516600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return retval; 517600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 518600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 519600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 520600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 521600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Match with a template. You can use this if you want to match incoming messages with a 522600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * pattern and do something when you find a match. This is useful for building filters/pattern 523600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * matching responders etc. 524600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 525600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param matchObj object to match ourselves with (null matches wildcard) 526600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 527600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 528600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public boolean match(Object matchObj) { 529600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (matchObj == null) 530600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return true; 531600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else if (!matchObj.getClass().equals(this.getClass())) 532600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return false; 533600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else if (matchObj == this) 534600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return true; 535600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPRequest that = (SIPRequest) matchObj; 536600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang RequestLine rline = that.requestLine; 537600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.requestLine == null && rline != null) 538600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return false; 539600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else if (this.requestLine == rline) 540600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return super.match(matchObj); 541600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return requestLine.match(that.requestLine) && super.match(matchObj); 542600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 543600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 544600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 545600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 546600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get a dialog identifier. Generates a string that can be used as a dialog identifier. 547600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 548600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param isServer is set to true if this is the UAS and set to false if this is the UAC 549600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 550600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public String getDialogId(boolean isServer) { 551600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang CallID cid = (CallID) this.getCallId(); 552600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang StringBuffer retval = new StringBuffer(cid.getCallId()); 553600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang From from = (From) this.getFrom(); 554600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang To to = (To) this.getTo(); 555600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!isServer) { 556600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // retval.append(COLON).append(from.getUserAtHostPort()); 557600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (from.getTag() != null) { 558600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.append(COLON); 559600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.append(from.getTag()); 560600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 561600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // retval.append(COLON).append(to.getUserAtHostPort()); 562600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (to.getTag() != null) { 563600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.append(COLON); 564600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.append(to.getTag()); 565600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 566600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 567600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // retval.append(COLON).append(to.getUserAtHostPort()); 568600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (to.getTag() != null) { 569600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.append(COLON); 570600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.append(to.getTag()); 571600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 572600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // retval.append(COLON).append(from.getUserAtHostPort()); 573600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (from.getTag() != null) { 574600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.append(COLON); 575600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.append(from.getTag()); 576600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 577600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 578600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return retval.toString().toLowerCase(); 579600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 580600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 581600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 582600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 583600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get a dialog id given the remote tag. 584600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 585600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public String getDialogId(boolean isServer, String toTag) { 586600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang From from = (From) this.getFrom(); 587600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang CallID cid = (CallID) this.getCallId(); 588600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang StringBuffer retval = new StringBuffer(cid.getCallId()); 589600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!isServer) { 590600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // retval.append(COLON).append(from.getUserAtHostPort()); 591600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (from.getTag() != null) { 592600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.append(COLON); 593600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.append(from.getTag()); 594600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 595600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // retval.append(COLON).append(to.getUserAtHostPort()); 596600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (toTag != null) { 597600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.append(COLON); 598600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.append(toTag); 599600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 600600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 601600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // retval.append(COLON).append(to.getUserAtHostPort()); 602600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (toTag != null) { 603600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.append(COLON); 604600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.append(toTag); 605600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 606600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // retval.append(COLON).append(from.getUserAtHostPort()); 607600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (from.getTag() != null) { 608600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.append(COLON); 609600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.append(from.getTag()); 610600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 611600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 612600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return retval.toString().toLowerCase(); 613600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 614600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 615600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 616600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Encode this into a byte array. This is used when the body has been set as a binary array 617600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * and you want to encode the body as a byte array for transmission. 618600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 619600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return a byte array containing the SIPRequest encoded as a byte array. 620600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 621600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 622600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public byte[] encodeAsBytes(String transport) { 623600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.isNullRequest()) { 624600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Encoding a null message for keepalive. 625600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return "\r\n\r\n".getBytes(); 626600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if ( this.requestLine == null ) { 627600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return new byte[0]; 628600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 629600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 630600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang byte[] rlbytes = null; 631600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (requestLine != null) { 632600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 633600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang rlbytes = requestLine.encode().getBytes("UTF-8"); 634600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (UnsupportedEncodingException ex) { 635600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang InternalErrorHandler.handleException(ex); 636600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 637600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 638600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang byte[] superbytes = super.encodeAsBytes(transport); 639600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang byte[] retval = new byte[rlbytes.length + superbytes.length]; 640600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang System.arraycopy(rlbytes, 0, retval, 0, rlbytes.length); 641600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang System.arraycopy(superbytes, 0, retval, rlbytes.length, superbytes.length); 642600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return retval; 643600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 644600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 645600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 646600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Creates a default SIPResponse message for this request. Note You must add the necessary 647600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * tags to outgoing responses if need be. For efficiency, this method does not clone the 648600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * incoming request. If you want to modify the outgoing response, be sure to clone the 649600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * incoming request as the headers are shared and any modification to the headers of the 650600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * outgoing response will result in a modification of the incoming request. Tag fields are 651600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * just copied from the incoming request. Contact headers are removed from the incoming 652600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * request. Added by Jeff Keyser. 653600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 654600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param statusCode Status code for the response. Reason phrase is generated. 655600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 656600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return A SIPResponse with the status and reason supplied, and a copy of all the original 657600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * headers from this request. 658600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 659600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 660600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public SIPResponse createResponse(int statusCode) { 661600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 662600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String reasonPhrase = SIPResponse.getReasonPhrase(statusCode); 663600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.createResponse(statusCode, reasonPhrase); 664600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 665600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 666600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 667600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 668600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Creates a default SIPResponse message for this request. Note You must add the necessary 669600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * tags to outgoing responses if need be. For efficiency, this method does not clone the 670600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * incoming request. If you want to modify the outgoing response, be sure to clone the 671600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * incoming request as the headers are shared and any modification to the headers of the 672600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * outgoing response will result in a modification of the incoming request. Tag fields are 673600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * just copied from the incoming request. Contact headers are removed from the incoming 674600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * request. Added by Jeff Keyser. Route headers are not added to the response. 675600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 676600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param statusCode Status code for the response. 677600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param reasonPhrase Reason phrase for this response. 678600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 679600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return A SIPResponse with the status and reason supplied, and a copy of all the original 680600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * headers from this request except the ones that are not supposed to be part of the 681600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * response . 682600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 683600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 684600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public SIPResponse createResponse(int statusCode, String reasonPhrase) { 685600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPResponse newResponse; 686600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Iterator headerIterator; 687600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeader nextHeader; 688600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 689600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang newResponse = new SIPResponse(); 690600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 691600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang newResponse.setStatusCode(statusCode); 692600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (ParseException ex) { 693600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new IllegalArgumentException("Bad code " + statusCode); 694600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 695600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (reasonPhrase != null) 696600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang newResponse.setReasonPhrase(reasonPhrase); 697600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else 698600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang newResponse.setReasonPhrase(SIPResponse.getReasonPhrase(statusCode)); 699600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang headerIterator = getHeaders(); 700600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (headerIterator.hasNext()) { 701600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang nextHeader = (SIPHeader) headerIterator.next(); 702600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (nextHeader instanceof From 703600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || nextHeader instanceof To 704600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || nextHeader instanceof ViaList 705600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || nextHeader instanceof CallID 706600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || (nextHeader instanceof RecordRouteList && mustCopyRR(statusCode)) 707600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || nextHeader instanceof CSeq 708600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // We just copy TimeStamp for all headers (not just 100). 709600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || nextHeader instanceof TimeStamp) { 710600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 711600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 712600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 713600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang newResponse.attachHeader((SIPHeader) nextHeader.clone(), false); 714600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (SIPDuplicateHeaderException e) { 715600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang e.printStackTrace(); 716600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 717600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 718600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 719600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (MessageFactoryImpl.getDefaultServerHeader() != null) { 720600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang newResponse.setHeader(MessageFactoryImpl.getDefaultServerHeader()); 721600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 722600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 723600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (newResponse.getStatusCode() == 100) { 724600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Trying is never supposed to have the tag parameter set. 725600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang newResponse.getTo().removeParameter("tag"); 726600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 727600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 728600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ServerHeader server = MessageFactoryImpl.getDefaultServerHeader(); 729600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (server != null) { 730600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang newResponse.setHeader(server); 731600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 732600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return newResponse; 733600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 734600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 735600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Helper method for createResponse, to avoid copying Record-Route unless needed 736600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private final boolean mustCopyRR( int code ) { 737600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Only for 1xx-2xx, not for 100 or errors 738600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if ( code>100 && code<300 ) { 739600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return isDialogCreating( this.getMethod() ) && getToTag() == null; 740600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else return false; 741600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 742600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 743600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 744600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Creates a default SIPResquest message that would cancel this request. Note that tag 745600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * assignment and removal of is left to the caller (we use whatever tags are present in the 746600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * original request). 747600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 748600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return A CANCEL SIPRequest constructed according to RFC3261 section 9.1 749600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 750600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @throws SipException 751600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @throws ParseException 752600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 753600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public SIPRequest createCancelRequest() throws SipException { 754600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 755600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // see RFC3261 9.1 756600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 757600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // A CANCEL request SHOULD NOT be sent to cancel a request other than 758600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // INVITE 759600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 760600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!this.getMethod().equals(Request.INVITE)) 761600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new SipException("Attempt to create CANCEL for " + this.getMethod()); 762600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 763600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 764600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * The following procedures are used to construct a CANCEL request. The Request-URI, 765600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Call-ID, To, the numeric part of CSeq, and From header fields in the CANCEL request 766600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * MUST be identical to those in the request being cancelled, including tags. A CANCEL 767600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * constructed by a client MUST have only a single Via header field value matching the top 768600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Via value in the request being cancelled. Using the same values for these header fields 769600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * allows the CANCEL to be matched with the request it cancels (Section 9.2 indicates how 770600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * such matching occurs). However, the method part of the CSeq header field MUST have a 771600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * value of CANCEL. This allows it to be identified and processed as a transaction in its 772600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * own right (See Section 17). 773600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 774600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPRequest cancel = new SIPRequest(); 775600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang cancel.setRequestLine((RequestLine) this.requestLine.clone()); 776600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang cancel.setMethod(Request.CANCEL); 777600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang cancel.setHeader((Header) this.callIdHeader.clone()); 778600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang cancel.setHeader((Header) this.toHeader.clone()); 779600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang cancel.setHeader((Header) cSeqHeader.clone()); 780600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 781600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang cancel.getCSeq().setMethod(Request.CANCEL); 782600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (ParseException e) { 783600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang e.printStackTrace(); // should not happen 784600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 785600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang cancel.setHeader((Header) this.fromHeader.clone()); 786600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 787600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang cancel.addFirst((Header) this.getTopmostVia().clone()); 788600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang cancel.setHeader((Header) this.maxForwardsHeader.clone()); 789600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 790600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 791600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * If the request being cancelled contains a Route header field, the CANCEL request MUST 792600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * include that Route header field's values. 793600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 794600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.getRouteHeaders() != null) { 795600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang cancel.setHeader((SIPHeaderList< ? >) this.getRouteHeaders().clone()); 796600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 797600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (MessageFactoryImpl.getDefaultUserAgentHeader() != null) { 798600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang cancel.setHeader(MessageFactoryImpl.getDefaultUserAgentHeader()); 799600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 800600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 801600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return cancel; 802600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 803600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 804600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 805600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Creates a default ACK SIPRequest message for this original request. Note that the 806600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * defaultACK SIPRequest does not include the content of the original SIPRequest. If 807600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * responseToHeader is null then the toHeader of this request is used to construct the ACK. 808600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Note that tag fields are just copied from the original SIP Request. Added by Jeff Keyser. 809600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 810600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param responseToHeader To header to use for this request. 811600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 812600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return A SIPRequest with an ACK method. 813600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 814600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public SIPRequest createAckRequest(To responseToHeader) { 815600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPRequest newRequest; 816600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Iterator headerIterator; 817600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeader nextHeader; 818600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 819600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang newRequest = new SIPRequest(); 820600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang newRequest.setRequestLine((RequestLine) this.requestLine.clone()); 821600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang newRequest.setMethod(Request.ACK); 822600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang headerIterator = getHeaders(); 823600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (headerIterator.hasNext()) { 824600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang nextHeader = (SIPHeader) headerIterator.next(); 825600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (nextHeader instanceof RouteList) { 826600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Ack and cancel do not get ROUTE headers. 827600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Route header for ACK is assigned by the 828600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Dialog if necessary. 829600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang continue; 830600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (nextHeader instanceof ProxyAuthorization) { 831600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Remove proxy auth header. 832600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Assigned by the Dialog if necessary. 833600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang continue; 834600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (nextHeader instanceof ContentLength) { 835600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Adding content is responsibility of user. 836600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang nextHeader = (SIPHeader) nextHeader.clone(); 837600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 838600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ((ContentLength) nextHeader).setContentLength(0); 839600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (InvalidArgumentException e) { 840600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 841600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (nextHeader instanceof ContentType) { 842600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Content type header is removed since 843600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // content length is 0. 844600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang continue; 845600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (nextHeader instanceof CSeq) { 846600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // The CSeq header field in the 847600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // ACK MUST contain the same value for the 848600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // sequence number as was present in the 849600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // original request, but the method parameter 850600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // MUST be equal to "ACK". 851600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang CSeq cseq = (CSeq) nextHeader.clone(); 852600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 853600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang cseq.setMethod(Request.ACK); 854600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (ParseException e) { 855600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 856600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang nextHeader = cseq; 857600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (nextHeader instanceof To) { 858600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (responseToHeader != null) { 859600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang nextHeader = responseToHeader; 860600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 861600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang nextHeader = (SIPHeader) nextHeader.clone(); 862600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 863600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (nextHeader instanceof ContactList || nextHeader instanceof Expires) { 864600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // CONTACT header does not apply for ACK requests. 865600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang continue; 866600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (nextHeader instanceof ViaList) { 867600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Bug reported by Gianluca Martinello 868600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // The ACK MUST contain a single Via header field, 869600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // and this MUST be equal to the top Via header 870600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // field of the original 871600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // request. 872600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 873600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang nextHeader = (SIPHeader) ((ViaList) nextHeader).getFirst().clone(); 874600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 875600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang nextHeader = (SIPHeader) nextHeader.clone(); 876600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 877600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 878600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 879600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang newRequest.attachHeader(nextHeader, false); 880600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (SIPDuplicateHeaderException e) { 881600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang e.printStackTrace(); 882600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 883600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 884600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (MessageFactoryImpl.getDefaultUserAgentHeader() != null) { 885600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang newRequest.setHeader(MessageFactoryImpl.getDefaultUserAgentHeader()); 886600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 887600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 888600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return newRequest; 889600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 890600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 891600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 892600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Creates an ACK for non-2xx responses according to RFC3261 17.1.1.3 893600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 894600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return A SIPRequest with an ACK method. 895600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @throws SipException 896600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @throws NullPointerException 897600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @throws ParseException 898600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 899600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @author jvb 900600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 901600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public final SIPRequest createErrorAck(To responseToHeader) throws SipException, 902600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ParseException { 903600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 904600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 905600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * The ACK request constructed by the client transaction MUST contain values for the 906600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Call-ID, From, and Request-URI that are equal to the values of those header fields in 907600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * the request passed to the transport by the client transaction (call this the "original 908600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * request"). The To header field in the ACK MUST equal the To header field in the 909600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * response being acknowledged, and therefore will usually differ from the To header field 910600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * in the original request by the addition of the tag parameter. The ACK MUST contain a 911600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * single Via header field, and this MUST be equal to the top Via header field of the 912600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * original request. The CSeq header field in the ACK MUST contain the same value for the 913600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * sequence number as was present in the original request, but the method parameter MUST 914600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * be equal to "ACK". 915600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 916600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPRequest newRequest = new SIPRequest(); 917600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang newRequest.setRequestLine((RequestLine) this.requestLine.clone()); 918600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang newRequest.setMethod(Request.ACK); 919600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang newRequest.setHeader((Header) this.callIdHeader.clone()); 920600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang newRequest.setHeader((Header) this.maxForwardsHeader.clone()); // ISSUE 921600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // 130 922600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // fix 923600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang newRequest.setHeader((Header) this.fromHeader.clone()); 924600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang newRequest.setHeader((Header) responseToHeader.clone()); 925600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang newRequest.addFirst((Header) this.getTopmostVia().clone()); 926600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang newRequest.setHeader((Header) cSeqHeader.clone()); 927600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang newRequest.getCSeq().setMethod(Request.ACK); 928600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 929600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 930600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * If the INVITE request whose response is being acknowledged had Route header fields, 931600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * those header fields MUST appear in the ACK. This is to ensure that the ACK can be 932600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * routed properly through any downstream stateless proxies. 933600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 934600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.getRouteHeaders() != null) { 935600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang newRequest.setHeader((SIPHeaderList) this.getRouteHeaders().clone()); 936600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 937600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (MessageFactoryImpl.getDefaultUserAgentHeader() != null) { 938600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang newRequest.setHeader(MessageFactoryImpl.getDefaultUserAgentHeader()); 939600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 940600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 941600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return newRequest; 942600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 943600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 944600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 945600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Create a new default SIPRequest from the original request. Warning: the newly created 946600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * SIPRequest, shares the headers of this request but we generate any new headers that we need 947600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * to modify so the original request is umodified. However, if you modify the shared headers 948600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * after this request is created, then the newly created request will also be modified. If you 949600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * want to modify the original request without affecting the returned Request make sure you 950600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * clone it before calling this method. 951600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 952600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Only required headers are copied. 953600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <ul> 954600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li> Contact headers are not included in the newly created request. Setting the appropriate 955600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * sequence number is the responsibility of the caller. </li> 956600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li> RouteList is not copied for ACK and CANCEL </li> 957600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li> Note that we DO NOT copy the body of the argument into the returned header. We do not 958600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * copy the content type header from the original request either. These have to be added 959600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * seperately and the content length has to be correctly set if necessary the content length 960600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * is set to 0 in the returned header. </li> 961600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li>Contact List is not copied from the original request.</li> 962600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li>RecordRoute List is not included from original request. </li> 963600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <li>Via header is not included from the original request. </li> 964600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * </ul> 965600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 966600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param requestLine is the new request line. 967600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 968600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param switchHeaders is a boolean flag that causes to and from headers to switch (set this 969600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * to true if you are the server of the transaction and are generating a BYE request). 970600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * If the headers are switched, we generate new From and To headers otherwise we just 971600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * use the incoming headers. 972600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 973600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return a new Default SIP Request which has the requestLine specified. 974600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 975600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 976600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public SIPRequest createSIPRequest(RequestLine requestLine, boolean switchHeaders) { 977600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPRequest newRequest = new SIPRequest(); 978600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang newRequest.requestLine = requestLine; 979600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Iterator<SIPHeader> headerIterator = this.getHeaders(); 980600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (headerIterator.hasNext()) { 981600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeader nextHeader = (SIPHeader) headerIterator.next(); 982600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // For BYE and cancel set the CSeq header to the 983600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // appropriate method. 984600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (nextHeader instanceof CSeq) { 985600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang CSeq newCseq = (CSeq) nextHeader.clone(); 986600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang nextHeader = newCseq; 987600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 988600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang newCseq.setMethod(requestLine.getMethod()); 989600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (ParseException e) { 990600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 991600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (nextHeader instanceof ViaList) { 992600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Via via = (Via) (((ViaList) nextHeader).getFirst().clone()); 993600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang via.removeParameter("branch"); 994600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang nextHeader = via; 995600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Cancel and ACK preserve the branch ID. 996600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (nextHeader instanceof To) { 997600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang To to = (To) nextHeader; 998600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (switchHeaders) { 999600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang nextHeader = new From(to); 1000600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ((From) nextHeader).removeTag(); 1001600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 1002600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang nextHeader = (SIPHeader) to.clone(); 1003600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ((To) nextHeader).removeTag(); 1004600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1005600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (nextHeader instanceof From) { 1006600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang From from = (From) nextHeader; 1007600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (switchHeaders) { 1008600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang nextHeader = new To(from); 1009600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ((To) nextHeader).removeTag(); 1010600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 1011600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang nextHeader = (SIPHeader) from.clone(); 1012600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ((From) nextHeader).removeTag(); 1013600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1014600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (nextHeader instanceof ContentLength) { 1015600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ContentLength cl = (ContentLength) nextHeader.clone(); 1016600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 1017600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang cl.setContentLength(0); 1018600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (InvalidArgumentException e) { 1019600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1020600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang nextHeader = cl; 1021600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (!(nextHeader instanceof CallID) && !(nextHeader instanceof MaxForwards)) { 1022600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Route is kept by dialog. 1023600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // RR is added by the caller. 1024600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Contact is added by the Caller 1025600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Any extension headers must be added 1026600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // by the caller. 1027600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang continue; 1028600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1029600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 1030600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang newRequest.attachHeader(nextHeader, false); 1031600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (SIPDuplicateHeaderException e) { 1032600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang e.printStackTrace(); 1033600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1034600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1035600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (MessageFactoryImpl.getDefaultUserAgentHeader() != null) { 1036600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang newRequest.setHeader(MessageFactoryImpl.getDefaultUserAgentHeader()); 1037600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1038600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1039600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return newRequest; 1040600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1041600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1042600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1043600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1044600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Create a BYE request from this request. 1045600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1046600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param switchHeaders is a boolean flag that causes from and isServerTransaction to headers 1047600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * to be swapped. Set this to true if you are the server of the dialog and are 1048600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * generating a BYE request for the dialog. 1049600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return a new default BYE request. 1050600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1051600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public SIPRequest createBYERequest(boolean switchHeaders) { 1052600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang RequestLine requestLine = (RequestLine) this.requestLine.clone(); 1053600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang requestLine.setMethod("BYE"); 1054600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.createSIPRequest(requestLine, switchHeaders); 1055600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1056600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1057600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1058600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Create an ACK request from this request. This is suitable for generating an ACK for an 1059600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * INVITE client transaction. 1060600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1061600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return an ACK request that is generated from this request. 1062600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1063600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public SIPRequest createACKRequest() { 1064600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang RequestLine requestLine = (RequestLine) this.requestLine.clone(); 1065600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang requestLine.setMethod(Request.ACK); 1066600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.createSIPRequest(requestLine, false); 1067600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1068600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1069600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1070600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the host from the topmost via header. 1071600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1072600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return the string representation of the host from the topmost via header. 1073600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1074600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public String getViaHost() { 1075600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Via via = (Via) this.getViaHeaders().getFirst(); 1076600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return via.getHost(); 1077600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1078600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1079600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1080600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1081600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the port from the topmost via header. 1082600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1083600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return the port from the topmost via header (5060 if there is no port indicated). 1084600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1085600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public int getViaPort() { 1086600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Via via = (Via) this.getViaHeaders().getFirst(); 1087600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (via.hasPort()) 1088600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return via.getPort(); 1089600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else 1090600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return 5060; 1091600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1092600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1093600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1094600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the first line encoded. 1095600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1096600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return a string containing the encoded request line. 1097600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1098600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public String getFirstLine() { 1099600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (requestLine == null) 1100600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return null; 1101600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else 1102600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.requestLine.encode(); 1103600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1104600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1105600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1106600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Set the sip version. 1107600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1108600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param sipVersion the sip version to set. 1109600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1110600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void setSIPVersion(String sipVersion) throws ParseException { 1111600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipVersion == null || !sipVersion.equalsIgnoreCase("SIP/2.0")) 1112600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new ParseException("sipVersion", 0); 1113600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.requestLine.setSipVersion(sipVersion); 1114600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1115600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1116600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1117600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the SIP version. 1118600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1119600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return the SIP version from the request line. 1120600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1121600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public String getSIPVersion() { 1122600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.requestLine.getSipVersion(); 1123600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1124600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1125600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1126600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Book keeping method to return the current tx for the request if one exists. 1127600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1128600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return the assigned tx. 1129600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1130600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public Object getTransaction() { 1131600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Return an opaque pointer to the transaction object. 1132600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // This is for consistency checking and quick lookup. 1133600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.transactionPointer; 1134600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1135600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1136600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1137600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Book keeping field to set the current tx for the request. 1138600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1139600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param transaction 1140600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1141600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void setTransaction(Object transaction) { 1142600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.transactionPointer = transaction; 1143600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1144600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1145600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1146600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Book keeping method to get the messasge channel for the request. 1147600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1148600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return the message channel for the request. 1149600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1150600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1151600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public Object getMessageChannel() { 1152600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // return opaque ptr to the message chanel on 1153600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // which the message was recieved. For consistency 1154600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // checking and lookup. 1155600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.messageChannel; 1156600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1157600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1158600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1159600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Set the message channel for the request ( bookkeeping field ). 1160600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1161600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param messageChannel 1162600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1163600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1164600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void setMessageChannel(Object messageChannel) { 1165600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.messageChannel = messageChannel; 1166600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1167600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1168600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1169600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Generates an Id for checking potentially merged requests. 1170600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1171600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return String to check for merged requests 1172600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1173600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public String getMergeId() { 1174600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 1175600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * generate an identifier from the From tag, Call-ID, and CSeq 1176600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1177600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String fromTag = this.getFromTag(); 1178600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String cseq = this.cSeqHeader.toString(); 1179600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String callId = this.callIdHeader.getCallId(); 1180600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* NOTE : The RFC does NOT specify you need to include a Request URI 1181600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * This is added here for the case of Back to Back User Agents. 1182600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1183600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String requestUri = this.getRequestURI().toString(); 1184600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1185600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (fromTag != null) { 1186600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return new StringBuffer().append(requestUri).append(":").append(fromTag).append(":").append(cseq).append(":") 1187600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .append(callId).toString(); 1188600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else 1189600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return null; 1190600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1191600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1192600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1193600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1194600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param inviteTransaction the inviteTransaction to set 1195600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1196600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void setInviteTransaction(Object inviteTransaction) { 1197600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.inviteTransaction = inviteTransaction; 1198600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1199600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1200600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1201600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return the inviteTransaction 1202600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1203600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public Object getInviteTransaction() { 1204600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return inviteTransaction; 1205600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1206600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1207600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1208600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1209600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1210600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1211600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang} 1212