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/******************************************************************************* 28600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Product of NIST/ITL Advanced Networking Technologies Division (ANTD) * 29600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ******************************************************************************/ 30600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 31600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangpackage gov.nist.javax.sip.parser; 32600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 33600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.core.Host; 34600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.core.HostNameParser; 35600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.SIPConstants; 36600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.address.AddressImpl; 37600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.address.GenericURI; 38600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.address.SipUri; 39600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.address.TelephoneNumber; 40600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.*; 41600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.message.SIPMessage; 42600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.message.SIPRequest; 43600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.message.SIPResponse; 44600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 45600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.io.UnsupportedEncodingException; 46600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.text.ParseException; 47600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/* 48600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Acknowledgement: 1/12/2007: Yanick Belanger rewrote the parsing loops to make them 49600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * simpler and quicker. 50600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 51600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 52600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/** 53600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Parse SIP message and parts of SIP messages such as URI's etc from memory and 54600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * return a structure. Intended use: UDP message processing. This class is used 55600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * when you have an entire SIP message or SIPHeader or SIP URL in memory and you 56600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * want to generate a parsed structure from it. For SIP messages, the payload 57600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * can be binary or String. If you have a binary payload, use 58600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * parseSIPMessage(byte[]) else use parseSIPMessage(String) The payload is 59600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * accessible from the parsed message using the getContent and getContentBytes 60600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * methods provided by the SIPMessage class. If SDP parsing is enabled using the 61600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * parseContent method, then the SDP body is also parsed and can be accessed 62600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * from the message using the getSDPAnnounce method. Currently only eager 63600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * parsing of the message is supported (i.e. the entire message is parsed in one 64600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * feld swoop). 65600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 66600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 67600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @version 1.2 $Revision: 1.26 $ $Date: 2009/10/22 10:27:38 $ 68600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 69600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @author M. Ranganathan <br/> 70600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 71600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 72600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 73600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangpublic class StringMsgParser { 74600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 75600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected boolean readBody; 76600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private ParseExceptionListener parseExceptionListener; 77600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private String rawStringMessage; 78600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private boolean strict; 79600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 80600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private static boolean computeContentLengthFromMessage = false; 81600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 82600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 83600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @since v0.9 84600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 85600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public StringMsgParser() { 86600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang super(); 87600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang readBody = true; 88600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 89600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 90600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 91600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Constructor (given a parse exception handler). 92600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 93600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @since 1.0 94600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param exhandler 95600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * is the parse exception listener for the message parser. 96600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 97600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public StringMsgParser(ParseExceptionListener exhandler) { 98600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this(); 99600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang parseExceptionListener = exhandler; 100600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 101600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 102600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 103600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Add a handler for header parsing errors. 104600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 105600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param pexhandler 106600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * is a class that implements the ParseExceptionListener 107600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * interface. 108600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 109600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void setParseExceptionListener(ParseExceptionListener pexhandler) { 110600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang parseExceptionListener = pexhandler; 111600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 112600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 113600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 114600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Parse a buffer containing a single SIP Message where the body is an array 115600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * of un-interpreted bytes. This is intended for parsing the message from a 116600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * memory buffer when the buffer. Incorporates a bug fix for a bug that was 117600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * noted by Will Sullin of Callcast 118600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 119600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param msgBuffer 120600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * a byte buffer containing the messages to be parsed. This can 121600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * consist of multiple SIP Messages concatenated together. 122600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return a SIPMessage[] structure (request or response) containing the 123600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * parsed SIP message. 124600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @exception ParseException 125600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * is thrown when an illegal message has been encountered 126600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * (and the rest of the buffer is discarded). 127600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @see ParseExceptionListener 128600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 129600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public SIPMessage parseSIPMessage(byte[] msgBuffer) throws ParseException { 130600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (msgBuffer == null || msgBuffer.length == 0) 131600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return null; 132600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 133600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int i = 0; 134600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 135600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Squeeze out any leading control character. 136600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 137600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (msgBuffer[i] < 0x20) 138600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang i++; 139600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 140600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang catch (ArrayIndexOutOfBoundsException e) { 141600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Array contains only control char, return null. 142600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return null; 143600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 144600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 145600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Iterate thru the request/status line and headers. 146600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String currentLine = null; 147600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String currentHeader = null; 148600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang boolean isFirstLine = true; 149600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPMessage message = null; 150600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang do 151600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang { 152600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int lineStart = i; 153600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 154600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Find the length of the line. 155600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 156600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (msgBuffer[i] != '\r' && msgBuffer[i] != '\n') 157600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang i++; 158600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 159600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang catch (ArrayIndexOutOfBoundsException e) { 160600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // End of the message. 161600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang break; 162600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 163600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int lineLength = i - lineStart; 164600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 165600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Make it a String. 166600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 167600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang currentLine = new String(msgBuffer, lineStart, lineLength, "UTF-8"); 168600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (UnsupportedEncodingException e) { 169600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new ParseException("Bad message encoding!", 0); 170600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 171600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 172600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang currentLine = trimEndOfLine(currentLine); 173600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 174600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (currentLine.length() == 0) { 175600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Last header line, process the previous buffered header. 176600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (currentHeader != null && message != null) { 177600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang processHeader(currentHeader, message); 178600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 179600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 180600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 181600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else { 182600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (isFirstLine) { 183600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang message = processFirstLine(currentLine); 184600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 185600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang char firstChar = currentLine.charAt(0); 186600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (firstChar == '\t' || firstChar == ' ') { 187600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (currentHeader == null) 188600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new ParseException("Bad header continuation.", 0); 189600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 190600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // This is a continuation, append it to the previous line. 191600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang currentHeader += currentLine.substring(1); 192600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 193600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else { 194600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (currentHeader != null && message != null) { 195600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang processHeader(currentHeader, message); 196600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 197600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang currentHeader = currentLine; 198600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 199600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 200600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 201600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 202600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (msgBuffer[i] == '\r' && msgBuffer.length > i+1 && msgBuffer[i+1] == '\n') 203600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang i++; 204600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 205600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang i++; 206600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 207600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang isFirstLine = false; 208600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } while (currentLine.length() > 0); // End do - while 209600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 210600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (message == null) throw new ParseException("Bad message", 0); 211600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang message.setSize(i); 212600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 213600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (readBody && message.getContentLength() != null && 214600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang message.getContentLength().getContentLength() != 0) { 215600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 216600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int bodyLength = msgBuffer.length - i; 217600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 218600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang byte[] body = new byte[bodyLength]; 219600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang System.arraycopy(msgBuffer, i, body, 0, bodyLength); 220600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang message.setMessageContent(body,computeContentLengthFromMessage ,message.getContentLength().getContentLength() ); 221600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 222600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 223600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return message; 224600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 225600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 226600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 227600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Parse a buffer containing one or more SIP Messages and return an array of 228600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * SIPMessage parsed structures. 229600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 230600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param msgString 231600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * a String containing the messages to be parsed. This can 232600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * consist of multiple SIP Messages concatenated together. 233600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return a SIPMessage structure (request or response) containing the 234600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * parsed SIP message. 235600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @exception ParseException 236600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * is thrown when an illegal message has been encountered 237600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * (and the rest of the buffer is discarded). 238600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @see ParseExceptionListener 239600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 240600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public SIPMessage parseSIPMessage(String msgString) throws ParseException { 241600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (msgString == null || msgString.length() == 0) 242600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return null; 243600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 244600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang rawStringMessage = msgString; 245600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 246600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int i = 0; 247600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 248600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Squeeze out any leading control character. 249600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 250600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (msgString.charAt(i) < 0x20) 251600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang i++; 252600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 253600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang catch (ArrayIndexOutOfBoundsException e) { 254600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Array contains only control char, return null. 255600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return null; 256600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (StringIndexOutOfBoundsException ex) { 257600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return null; 258600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 259600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 260600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Iterate thru the request/status line and headers. 261600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String currentLine = null; 262600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String currentHeader = null; 263600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang boolean isFirstLine = true; 264600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPMessage message = null; 265600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang do 266600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang { 267600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int lineStart = i; 268600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 269600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Find the length of the line. 270600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 271600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang char c = msgString.charAt(i); 272600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (c != '\r' && c != '\n') 273600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang c = msgString.charAt(++i); 274600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 275600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang catch (ArrayIndexOutOfBoundsException e) { 276600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // End of the message. 277600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang break; 278600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch ( StringIndexOutOfBoundsException ex) { 279600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang break; 280600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 281600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 282600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Make it a String. 283600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang currentLine = msgString.substring(lineStart, i); 284600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang currentLine = trimEndOfLine(currentLine); 285600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 286600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (currentLine.length() == 0) { 287600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Last header line, process the previous buffered header. 288600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (currentHeader != null) { 289600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang processHeader(currentHeader, message); 290600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 291600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 292600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else { 293600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (isFirstLine) { 294600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang message = processFirstLine(currentLine); 295600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 296600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang char firstChar = currentLine.charAt(0); 297600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (firstChar == '\t' || firstChar == ' ') { 298600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (currentHeader == null) 299600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new ParseException("Bad header continuation.", 0); 300600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 301600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // This is a continuation, append it to the previous line. 302600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang currentHeader += currentLine.substring(1); 303600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 304600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else { 305600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (currentHeader != null) { 306600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang processHeader(currentHeader, message); 307600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 308600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang currentHeader = currentLine; 309600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 310600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 311600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 312600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 313600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (msgString.charAt(i) == '\r' && msgString.length() > i+1 && msgString.charAt(i+1) == '\n') 314600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang i++; 315600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 316600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang i++; 317600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 318600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang isFirstLine = false; 319600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 320600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (currentLine.length() > 0); 321600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 322600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang message.setSize(i); 323600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 324600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Check for content legth header 325600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (readBody && message.getContentLength() != null ) { 326600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if ( message.getContentLength().getContentLength() != 0) { 327600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String body = msgString.substring(i); 328600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang message.setMessageContent(body,this.strict,computeContentLengthFromMessage,message.getContentLength().getContentLength()); 329600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (!computeContentLengthFromMessage && message.getContentLength().getContentLength() == 0 && !msgString.endsWith("\r\n\r\n") ){ 330600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if ( strict ) { 331600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new ParseException("Extraneous characters at the end of the message ",i); 332600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 333600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 334600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 335600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 336600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 337600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return message; 338600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 339600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 340600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private String trimEndOfLine(String line) { 341600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (line == null) 342600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return line; 343600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 344600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int i = line.length() - 1; 345600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (i >= 0 && line.charAt(i) <= 0x20) 346600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang i--; 347600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 348600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (i == line.length() - 1) 349600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return line; 350600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 351600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (i == -1) 352600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return ""; 353600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 354600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return line.substring(0, i+1); 355600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 356600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 357600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private SIPMessage processFirstLine(String firstLine) throws ParseException { 358600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPMessage message; 359600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!firstLine.startsWith(SIPConstants.SIP_VERSION_STRING)) { 360600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang message = new SIPRequest(); 361600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 362600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang RequestLine requestLine = new RequestLineParser(firstLine + "\n") 363600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .parse(); 364600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ((SIPRequest) message).setRequestLine(requestLine); 365600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (ParseException ex) { 366600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.parseExceptionListener != null) 367600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.parseExceptionListener.handleException(ex, message, 368600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang RequestLine.class, firstLine, rawStringMessage); 369600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else 370600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw ex; 371600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 372600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 373600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 374600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang message = new SIPResponse(); 375600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 376600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang StatusLine sl = new StatusLineParser(firstLine + "\n").parse(); 377600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ((SIPResponse) message).setStatusLine(sl); 378600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (ParseException ex) { 379600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.parseExceptionListener != null) { 380600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.parseExceptionListener.handleException(ex, message, 381600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang StatusLine.class, firstLine, rawStringMessage); 382600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else 383600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw ex; 384600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 385600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 386600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 387600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return message; 388600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 389600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 390600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private void processHeader(String header, SIPMessage message) throws ParseException { 391600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (header == null || header.length() == 0) 392600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 393600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 394600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang HeaderParser headerParser = null; 395600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 396600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang headerParser = ParserFactory.createParser(header + "\n"); 397600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (ParseException ex) { 398600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.parseExceptionListener.handleException(ex, message, null, 399600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang header, rawStringMessage); 400600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 401600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 402600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 403600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 404600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPHeader sipHeader = headerParser.parse(); 405600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang message.attachHeader(sipHeader, false); 406600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (ParseException ex) { 407600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.parseExceptionListener != null) { 408600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String headerName = Lexer.getHeaderName(header); 409600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Class headerClass = NameMap.getClassFromName(headerName); 410600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (headerClass == null) { 411600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang headerClass = ExtensionHeaderImpl.class; 412600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 413600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 414600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.parseExceptionListener.handleException(ex, message, 415600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang headerClass, header, rawStringMessage); 416600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 417600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 418600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 419600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 420600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 421600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 422600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Parse an address (nameaddr or address spec) and return and address 423600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * structure. 424600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 425600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param address 426600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * is a String containing the address to be parsed. 427600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return a parsed address structure. 428600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @since v1.0 429600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @exception ParseException 430600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * when the address is badly formatted. 431600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 432600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public AddressImpl parseAddress(String address) throws ParseException { 433600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang AddressParser addressParser = new AddressParser(address); 434600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return addressParser.address(true); 435600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 436600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 437600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 438600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Parse a host:port and return a parsed structure. 439600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 440600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param hostport 441600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * is a String containing the host:port to be parsed 442600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return a parsed address structure. 443600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @since v1.0 444600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @exception throws 445600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * a ParseException when the address is badly formatted. 446600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 447600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public HostPort parseHostPort(String hostport) throws ParseException { 448600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Lexer lexer = new Lexer("charLexer", hostport); 449600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return new HostNameParser(lexer).hostPort(); 450600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 451600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 452600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 453600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 454600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 455600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Parse a host name and return a parsed structure. 456600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 457600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param host 458600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * is a String containing the host name to be parsed 459600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return a parsed address structure. 460600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @since v1.0 461600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @exception ParseException 462600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * a ParseException when the hostname is badly formatted. 463600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 464600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public Host parseHost(String host) throws ParseException { 465600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Lexer lexer = new Lexer("charLexer", host); 466600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return new HostNameParser(lexer).host(); 467600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 468600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 469600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 470600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 471600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Parse a telephone number return a parsed structure. 472600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 473600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param telephone_number 474600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * is a String containing the telephone # to be parsed 475600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return a parsed address structure. 476600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @since v1.0 477600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @exception ParseException 478600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * a ParseException when the address is badly formatted. 479600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 480600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public TelephoneNumber parseTelephoneNumber(String telephone_number) 481600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throws ParseException { 482600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Bug fix contributed by Will Scullin 483600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return new URLParser(telephone_number).parseTelephoneNumber(true); 484600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 485600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 486600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 487600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 488600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Parse a SIP url from a string and return a URI structure for it. 489600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 490600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param url 491600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * a String containing the URI structure to be parsed. 492600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return A parsed URI structure 493600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @exception ParseException 494600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * if there was an error parsing the message. 495600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 496600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 497600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public SipUri parseSIPUrl(String url) throws ParseException { 498600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 499600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return new URLParser(url).sipURL(true); 500600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (ClassCastException ex) { 501600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new ParseException(url + " Not a SIP URL ", 0); 502600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 503600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 504600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 505600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 506600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Parse a uri from a string and return a URI structure for it. 507600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 508600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param url 509600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * a String containing the URI structure to be parsed. 510600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return A parsed URI structure 511600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @exception ParseException 512600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * if there was an error parsing the message. 513600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 514600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 515600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public GenericURI parseUrl(String url) throws ParseException { 516600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return new URLParser(url).parse(); 517600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 518600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 519600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 520600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Parse an individual SIP message header from a string. 521600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 522600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param header 523600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * String containing the SIP header. 524600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return a SIPHeader structure. 525600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @exception ParseException 526600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * if there was an error parsing the message. 527600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 528600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public SIPHeader parseSIPHeader(String header) throws ParseException { 529600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int start = 0; 530600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int end = header.length() - 1; 531600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 532600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Squeeze out any leading control character. 533600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (header.charAt(start) <= 0x20) 534600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang start++; 535600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 536600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Squeeze out any trailing control character. 537600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (header.charAt(end) <= 0x20) 538600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang end--; 539600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 540600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang catch (ArrayIndexOutOfBoundsException e) { 541600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Array contains only control char. 542600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new ParseException("Empty header.", 0); 543600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 544600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 545600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang StringBuffer buffer = new StringBuffer(end + 1); 546600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int i = start; 547600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int lineStart = start; 548600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang boolean endOfLine = false; 549600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (i <= end) { 550600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang char c = header.charAt(i); 551600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (c == '\r' || c == '\n') { 552600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!endOfLine) { 553600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang buffer.append(header.substring(lineStart, i)); 554600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang endOfLine = true; 555600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 556600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 557600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else { 558600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (endOfLine) { 559600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang endOfLine = false; 560600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (c == ' ' || c == '\t') { 561600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang buffer.append(' '); 562600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang lineStart = i + 1; 563600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 564600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else { 565600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang lineStart = i; 566600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 567600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 568600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 569600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 570600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang i++; 571600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 572600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang buffer.append(header.substring(lineStart, i)); 573600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang buffer.append('\n'); 574600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 575600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang HeaderParser hp = ParserFactory.createParser(buffer.toString()); 576600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (hp == null) 577600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new ParseException("could not create parser", 0); 578600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return hp.parse(); 579600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 580600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 581600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 582600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Parse the SIP Request Line 583600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 584600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param requestLine 585600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * a String containing the request line to be parsed. 586600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return a RequestLine structure that has the parsed RequestLine 587600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @exception ParseException 588600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * if there was an error parsing the requestLine. 589600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 590600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 591600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public RequestLine parseSIPRequestLine(String requestLine) 592600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throws ParseException { 593600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang requestLine += "\n"; 594600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return new RequestLineParser(requestLine).parse(); 595600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 596600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 597600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 598600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Parse the SIP Response message status line 599600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 600600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param statusLine 601600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * a String containing the Status line to be parsed. 602600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return StatusLine class corresponding to message 603600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @exception ParseException 604600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * if there was an error parsing 605600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @see StatusLine 606600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 607600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 608600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public StatusLine parseSIPStatusLine(String statusLine) 609600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throws ParseException { 610600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang statusLine += "\n"; 611600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return new StatusLineParser(statusLine).parse(); 612600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 613600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 614600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public static void setComputeContentLengthFromMessage( 615600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang boolean computeContentLengthFromMessage) { 616600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang StringMsgParser.computeContentLengthFromMessage = computeContentLengthFromMessage; 617600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 618600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 619600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 620600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 621600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 622600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Test code. 623600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 624600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public static void main(String[] args) throws ParseException { 625600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String messages[] = { 626600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "SIP/2.0 200 OK\r\n" 627600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "To: \"The Little Blister\" <sip:LittleGuy@there.com>;tag=469bc066\r\n" 628600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "From: \"The Master Blaster\" <sip:BigGuy@here.com>;tag=11\r\n" 629600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "Via: SIP/2.0/UDP 139.10.134.246:5060;branch=z9hG4bK8b0a86f6_1030c7d18e0_17;received=139.10.134.246\r\n" 630600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "Call-ID: 1030c7d18ae_a97b0b_b@8b0a86f6\r\n" 631600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "CSeq: 1 SUBSCRIBE\r\n" 632600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "Contact: <sip:172.16.11.162:5070>\r\n" 633600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "Content-Length: 0\r\n\r\n", 634600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 635600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "SIP/2.0 180 Ringing\r\n" 636600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "Via: SIP/2.0/UDP 172.18.1.29:5060;branch=z9hG4bK43fc10fb4446d55fc5c8f969607991f4\r\n" 637600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "To: \"0440\" <sip:0440@212.209.220.131>;tag=2600\r\n" 638600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "From: \"Andreas\" <sip:andreas@e-horizon.se>;tag=8524\r\n" 639600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "Call-ID: f51a1851c5f570606140f14c8eb64fd3@172.18.1.29\r\n" 640600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "CSeq: 1 INVITE\r\n" + "Max-Forwards: 70\r\n" 641600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "Record-Route: <sip:212.209.220.131:5060>\r\n" 642600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "Content-Length: 0\r\n\r\n", 643600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "REGISTER sip:nist.gov SIP/2.0\r\n" 644600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "Via: SIP/2.0/UDP 129.6.55.182:14826\r\n" 645600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "Max-Forwards: 70\r\n" 646600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "From: <sip:mranga@nist.gov>;tag=6fcd5c7ace8b4a45acf0f0cd539b168b;epid=0d4c418ddf\r\n" 647600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "To: <sip:mranga@nist.gov>\r\n" 648600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "Call-ID: c5679907eb954a8da9f9dceb282d7230@129.6.55.182\r\n" 649600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "CSeq: 1 REGISTER\r\n" 650600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "Contact: <sip:129.6.55.182:14826>;methods=\"INVITE, MESSAGE, INFO, SUBSCRIBE, OPTIONS, BYE, CANCEL, NOTIFY, ACK, REFER\"\r\n" 651600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "User-Agent: RTC/(Microsoft RTC)\r\n" 652600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "Event: registration\r\n" 653600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "Allow-Events: presence\r\n" 654600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "Content-Length: 0\r\n\r\n" 655600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "INVITE sip:littleguy@there.com:5060 SIP/2.0\r\n" 656600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "Via: SIP/2.0/UDP 65.243.118.100:5050\r\n" 657600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "From: M. Ranganathan <sip:M.Ranganathan@sipbakeoff.com>;tag=1234\r\n" 658600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "To: \"littleguy@there.com\" <sip:littleguy@there.com:5060> \r\n" 659600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "Call-ID: Q2AboBsaGn9!?x6@sipbakeoff.com \r\n" 660600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "CSeq: 1 INVITE \r\n" 661600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "Content-Length: 247\r\n\r\n" 662600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "v=0\r\n" 663600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "o=4855 13760799956958020 13760799956958020 IN IP4 129.6.55.78\r\n" 664600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "s=mysession session\r\n" + "p=+46 8 52018010\r\n" 665600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "c=IN IP4 129.6.55.78\r\n" + "t=0 0\r\n" 666600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "m=audio 6022 RTP/AVP 0 4 18\r\n" 667600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "a=rtpmap:0 PCMU/8000\r\n" 668600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "a=rtpmap:4 G723/8000\r\n" 669600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "a=rtpmap:18 G729A/8000\r\n" + "a=ptime:20\r\n" }; 670600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 671600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang class ParserThread implements Runnable { 672600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String[] messages; 673600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 674600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public ParserThread(String[] messagesToParse) { 675600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.messages = messagesToParse; 676600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 677600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 678600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void run() { 679600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang for (int i = 0; i < messages.length; i++) { 680600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang StringMsgParser smp = new StringMsgParser(); 681600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 682600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPMessage sipMessage = smp 683600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .parseSIPMessage(messages[i]); 684600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang System.out.println(" i = " + i + " branchId = " 685600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + sipMessage.getTopmostVia().getBranch()); 686600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // System.out.println("encoded " + 687600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // sipMessage.toString()); 688600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (ParseException ex) { 689600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 690600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 691600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 692600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // System.out.println("dialog id = " + 693600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // sipMessage.getDialogId(false)); 694600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 695600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 696600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 697600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 698600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang for (int i = 0; i < 20; i++) { 699600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang new Thread(new ParserThread(messages)).start(); 700600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 701600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 702600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 703600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 704600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void setStrict(boolean strict) { 705600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.strict = strict; 706600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 707600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 708600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 709600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang} 710