Fields Summary |
---|
protected boolean | readBodyFlag indicating body read requested. |
private String | rawMessageUnprocessed message part 1 (for error reporting). |
private String | rawMessage1Unprocessed message part 2 (for error reporting). |
private String | currentMessageCurrent message. |
private ParseExceptionListener | parseExceptionListenerParsing exeception listener. |
private Vector | messageHeadersMessage headers. |
private int | bufferPointerCurrent buffer pointer. |
private boolean | bodyIsStringFlag indicating bodyis a text string. |
private byte[] | currentMessageBytesCurrent message contents as an arrayof bytes. |
protected int | contentLengthLengthg of current message body. |
private boolean | debugFlagDebugging enabled flag. |
private int | currentLineCurrent line being parsed. |
private String | currentHeaderCurrent header being processed. |
Methods Summary |
---|
protected byte[] | getBodyAsBytes()Gets the message body as a byte array.
if (this.contentLength == 0) {
return null;
} else {
int endIndex = bufferPointer + this.contentLength;
// guard against bad specifications.
if (endIndex > currentMessageBytes.length) {
endIndex = currentMessageBytes.length;
}
byte[] body = new byte[endIndex - bufferPointer];
System.arraycopy
(currentMessageBytes, bufferPointer, body, 0, body.length);
bufferPointer = endIndex;
this.contentLength = 0;
return body;
}
|
public java.lang.String | getCurrentHeader()Gets the current header.
return currentHeader;
|
public int | getCurrentLineNumber()Gets the current line number.
return currentLine;
|
protected java.lang.String | getMessageBody()Gets the message body.
if (this.contentLength == 0) {
return null;
} else {
int endIndex = bufferPointer + this.contentLength;
String body;
// guard against bad specifications.
if (endIndex > currentMessage.length()) {
endIndex = currentMessage.length();
body = currentMessage.substring(bufferPointer, endIndex);
bufferPointer = endIndex;
} else {
body = currentMessage.substring(bufferPointer, endIndex);
bufferPointer = endIndex + 1;
}
this.contentLength = 0;
return body;
}
|
protected boolean | isBodyString()Returns true if the body is encoded as a string.
If the parseMessage(String) method is invoked then the body
is assumed to be a string.
return bodyIsString;
|
private java.lang.StringBuffer | normalizeMessage(java.lang.StringBuffer srcMsg)Normalize message string, i.e. remove whitespace
StringBuffer normalizedMessage = new StringBuffer(srcMsg.length());
String message1 = srcMsg.toString();
int length = message1.indexOf("\n\n") + 2;
int k = 0;
while (k < length - 1) {
final char thisChar = srcMsg.charAt(k);
final char thatChar = srcMsg.charAt(k+1);
// is it a continuation line?
if (thisChar == '\n" && (thatChar == '\t" || thatChar == ' ")) {
normalizedMessage.append(' ");
k++; // skipping \n
// now remove whitespace
char nextChar;
do {
k++; // skipping \t or space
if (k == length) {
break;
}
nextChar = srcMsg.charAt(k);
} while (nextChar == ' " || nextChar == '\t");
} else {
normalizedMessage.append(thisChar);
k++;
}
}
return normalizedMessage;
|
public Address | parseAddress(java.lang.String address)Parses an address (nameaddr or address spec) and return and address
structure.
AddressParser addressParser = new AddressParser(address);
return addressParser.address();
|
public Header | parseHeader(java.lang.String header)Parses an individual SIP message header from a string.
// It's not clear why "\n\n" was added to the header.
// header += "\n\n";
// Handle line folding.
String nmessage = StringTokenizer.convertNewLines(header);
nmessage += "\n"; /* why not Separators.NEWLINE ? */
// System.out.println(">>> '" + nmessage + "'");
HeaderParser hp = ParserFactory.createParser(nmessage);
if (hp == null)
throw new ParseException("could not create parser", 0);
return hp.parse();
|
public Host | parseHost(java.lang.String host)Parse a host name and return a parsed structure.
Lexer lexer = new Lexer("charLexer", host);
HostNameParser hp = new HostNameParser(lexer);
return new Host(hp.hostName());
|
public HostPort | parseHostPort(java.lang.String hostport)Parses a host:port and return a parsed structure.
Lexer lexer = new Lexer("charLexer", hostport);
return new HostNameParser(lexer).hostPort();
|
private Message | parseMessage(java.lang.String currentMessage)This is called repeatedly by parseMessage to parse
the contents of a message buffer. This assumes the message
already has continuations etc. taken care of.
prior to its being called.
// position line counter at the end of the
// sip messages.
//
// System.out.println("parsing <<" + currentMessage+">>");
Message sipmsg = null;
StringTokenizer tokenizer = new StringTokenizer(currentMessage, '\n");
messageHeaders = new Vector(); // A list of headers for error reporting
while (tokenizer.hasMoreChars()) {
String nexttok = tokenizer.nextToken();
if (nexttok.equals("\n")) {
String nextnexttok = tokenizer.nextToken();
if (nextnexttok.equals("\n")) {
break;
} else messageHeaders.addElement(nextnexttok);
} else messageHeaders.addElement(nexttok);
}
currentLine = 0;
currentHeader = (String) messageHeaders.elementAt(currentLine);
String firstLine = currentHeader;
// System.out.println("first Line " + firstLine);
if (!firstLine.startsWith(SIPConstants.SIP_VERSION_STRING)) {
sipmsg = new Request();
try {
RequestLine rl =
new RequestLineParser(firstLine+ "\n").parse();
((Request) sipmsg).setRequestLine(rl);
} catch (ParseException ex) {
if (this.parseExceptionListener != null)
this.parseExceptionListener.handleException
(ex, sipmsg, new RequestLine().getClass(),
firstLine, currentMessage);
else throw ex;
}
} else {
sipmsg = new Response();
try {
StatusLine sl = new StatusLineParser(firstLine + "\n").parse();
((Response) sipmsg).setStatusLine(sl);
} catch (ParseException ex) {
if (this.parseExceptionListener != null) {
this.parseExceptionListener.handleException
(ex, sipmsg,
new StatusLine().getClass(),
firstLine, currentMessage);
} else throw ex;
}
}
for (int i = 1; i < messageHeaders.size(); i++) {
String hdrstring = (String) messageHeaders.elementAt(i);
if (hdrstring == null || hdrstring.trim().equals("")) {
continue;
}
HeaderParser hdrParser = null;
try {
// System.out.println("'" + hdrstring + "'");
hdrParser = ParserFactory.createParser(hdrstring + "\n");
} catch (ParseException ex) {
parseExceptionListener.handleException(
ex, sipmsg, null, hdrstring, currentMessage);
continue;
}
Header sipHeader = null;
try {
sipHeader = hdrParser.parse();
sipmsg.attachHeader(sipHeader, false);
} catch (ParseException ex) {
// ex.printStackTrace();
if (parseExceptionListener != null) {
String hdrName = Lexer.getHeaderName(hdrstring);
Class hdrClass = NameMap.getClassFromName(hdrName);
if (hdrClass == null) {
hdrClass = ExtensionHeader.clazz;
}
parseExceptionListener.handleException(
ex, sipmsg, hdrClass, hdrstring, currentMessage);
} else { // use generic parser
hdrParser = new ExtensionParser(hdrstring + "\n");
sipHeader = hdrParser.parse();
try {
sipmsg.attachHeader(sipHeader, false);
} catch (SipException exc) {
throw new ParseException(sipHeader.toString(), 0);
}
}
} catch (SipException ex) {
// Invalid header.
throw new ParseException(sipHeader.toString(), 0);
}
}
return sipmsg;
|
public RequestLine | parseRequestLine(java.lang.String requestLine)Parses the SIP Request Line
requestLine += "\n";
return new RequestLineParser(requestLine).parse();
|
public Message | parseSIPMessage(java.lang.String sipMessages)Parses a buffer containing one or more SIP Messages and return
an array of
Message parsed structures. Note that the current limitation is that
this does not handle content encoding properly. The message content is
just assumed to be encoded using the same encoding as the sip message
itself (i.e. binary encodings such as gzip are not supported).
// Handle line folding and evil DOS CR-LF sequences
rawMessage = sipMessages;
Vector retval = new Vector();
String pmessage = sipMessages;
bodyIsString = true;
this.contentLength = 0;
if (pmessage.trim().equals(""))
return null;
pmessage += "\n\n";
StringBuffer message = new StringBuffer(pmessage);
// squeeze out the leading crlf sequences.
while (message.charAt(0) == '\r" || message.charAt(0) == '\n") {
bufferPointer ++;
message.deleteCharAt(0);
}
// squeeze out the crlf sequences and make them uniformly CR
String message1 = message.toString();
int length;
length = message1.indexOf("\r\n\r\n");
if (length > 0) length += 4;
if (length == -1) {
length = message1.indexOf("\n\n");
if (length == -1)
throw new ParseException("no trailing crlf", 0);
} else length += 2;
// Get rid of CR to make it uniform.
for (int k = 0; k < length; k++) {
if (message.charAt(k) == '\r") {
message.deleteCharAt(k);
length --;
}
}
if (debugFlag) {
for (int k = 0; k < length; k++) {
rawMessage1 = rawMessage1 + "[" + message.charAt(k) +"]";
}
}
// The following can be written more efficiently in a single pass
// but it is somewhat complex.
StringTokenizer tokenizer = new StringTokenizer
(message.toString(), '\n");
StringBuffer cooked_message = new StringBuffer();
while (tokenizer.hasMoreChars()) {
String nexttok = tokenizer.nextToken();
// Ignore blank lines with leading spaces or tabs.
if (nexttok.trim().equals("")) cooked_message.append("\n");
else cooked_message.append(nexttok);
}
cooked_message = normalizeMessage(cooked_message);
cooked_message.append("\n\n");
// Separate the string out into substrings for
// error reporting.
currentMessage = cooked_message.toString();
if (Parser.debug) {
Logging.report(Logging.ERROR, LogChannels.LC_JSR180,
currentMessage);
}
bufferPointer = currentMessage.indexOf("\n\n") + 3;
Message sipmsg = this.parseMessage(currentMessage);
if (readBody && sipmsg.getContentLengthHeader() != null &&
sipmsg.getContentLengthHeader().getContentLength() != 0) {
this.contentLength =
sipmsg.getContentLengthHeader().getContentLength();
String body = this.getMessageBody();
sipmsg.setMessageContent(body);
}
return sipmsg;
|
public Message | parseSIPMessage(byte[] msgBuffer)Parses a buffer containing a single SIP Message where the body
is an array of un-interpreted bytes. This is intended for parsing
the message from a memory buffer when the buffer.
Incorporates a bug fix for a bug that was noted by Will Sullin of
Callcast
bufferPointer = 0;
bodyIsString = false;
currentMessageBytes = msgBuffer;
int start;
// Squeeze out leading CRLF
// Squeeze out the leading nulls (otherwise the parser will crash)
for (start = bufferPointer; start < msgBuffer.length; start++) {
final char chr = (char)msgBuffer[start];
if (chr != '\r"
&& chr != '\n"
&& chr != '\0") break;
}
if (start == msgBuffer.length)
return null;
// Find the end of the SIP message.
int fin;
for (fin = start; fin < msgBuffer.length -4; fin ++) {
if ((char) msgBuffer[fin] == '\r"
&& (char) msgBuffer[fin+1] == '\n"
&& (char) msgBuffer[fin+2] == '\r"
&& (char) msgBuffer[fin+3] == '\n") {
break;
}
}
if (fin < msgBuffer.length) {
// we do not handle the (theoretically possible) case that the
// headers end with LFLF but there *is* CRLFCRLF in the body
fin += 4;
} else {
// Could not find CRLFCRLF end of message so look for LFLF
for (fin = start; fin < msgBuffer.length -2; fin++) {
if ((char)msgBuffer[fin] == '\n"
&& (char)msgBuffer[fin+1] == '\n") break;
}
if (fin < msgBuffer.length) fin += 2;
else throw new ParseException("Message not terminated", 0);
}
// Encode the body as a UTF-8 string.
String messageString = null;
try {
messageString = new String(msgBuffer, start, fin - start, "UTF-8");
} catch (UnsupportedEncodingException ex) {
throw new ParseException("Bad message encoding!", 0);
}
bufferPointer = fin;
int length = messageString.length();
StringBuffer message = new StringBuffer(length);
// Get rid of CR to make it uniform for the parser.
for (int k = 0; k < length; k++) {
final char currChar = messageString.charAt(k);
if (currChar != '\r") {
message.append(currChar);
}
}
length = message.length();
if (Parser.debug) {
for (int k = 0; k < length; k++) {
rawMessage1 = rawMessage1 + "[" + message.charAt(k) +"]";
}
}
// The following can be written more efficiently in a single pass
// but it is somewhat complex.
StringTokenizer tokenizer = new StringTokenizer
(message.toString(), '\n");
StringBuffer cooked_message = new StringBuffer();
while (tokenizer.hasMoreChars()) {
String nexttok = tokenizer.nextToken();
// Ignore blank lines with leading spaces or tabs.
if (nexttok.trim().equals("")) cooked_message.append("\n");
else cooked_message.append(nexttok);
}
cooked_message = normalizeMessage(cooked_message);
cooked_message.append("\n\n");
// Separate the string out into substrings for
// error reporting.
currentMessage = cooked_message.toString();
Message sipmsg = parseMessage(currentMessage);
if (readBody && sipmsg.getContentLengthHeader() != null
&& sipmsg.getContentLengthHeader().getContentLength() != 0) {
contentLength = sipmsg.getContentLengthHeader().getContentLength();
byte body[] = getBodyAsBytes();
sipmsg.setMessageContent(body);
}
// System.out.println("Parsed = [" + sipmsg + "]");
return sipmsg;
|
public StatusLine | parseSIPStatusLine(java.lang.String statusLine)Parses the SIP Response message status line
statusLine += "\n";
return new StatusLineParser(statusLine).parse();
|
public SipURI | parseSIPUrl(java.lang.String url)Parses a SIP url from a string and return a URI structure for it.
try {
URLParser parser = new URLParser(url);
SipURI uri = (SipURI)parser.parse();
// whole string has to be consumed
// otherwise it is wrong URL or not URL only
if (parser.getLexer().hasMoreChars()) {
throw new ParseException(url + " Not a URL string",
parser.getLexer().getPtr());
}
return uri;
} catch (ClassCastException ex) {
throw new ParseException(url + " Not a SIP URL ", 0);
}
|
public TelephoneNumber | parseTelephoneNumber(java.lang.String telephone_number)Parses a telephone number return a parsed structure.
return new URLParser(telephone_number).parseTelephoneNumber();
|
public URI | parseUrl(java.lang.String url)Parses a uri from a string and return a URI structure for it.
return new URLParser(url).parse();
|
protected byte[] | readBytesToEnd()Returns the bytes to the end of the message.
This is invoked when the parser is invoked with an array of bytes
rather than with a string.
byte[] body = new byte[currentMessageBytes.length - bufferPointer];
int endIndex = currentMessageBytes.length;
for (int i = bufferPointer, k = 0; i < endIndex; i++, k++) {
body[k] = currentMessageBytes[i];
}
bufferPointer = endIndex;
this.contentLength = 0;
return body;
|
protected java.lang.String | readToEnd()Returns the contents till the end of the buffer (this is useful when
you encounter an error.
String body = currentMessage.substring(bufferPointer);
bufferPointer += body.length();
return body;
|
public void | setParseExceptionListener(ParseExceptionListener pexhandler)Adds a handler for header parsing errors.
parseExceptionListener = pexhandler;
|