Home > Java, SIP, Telecom > Application of HTTP parsers to SIP

Application of HTTP parsers to SIP

SIP was intentionally designed to have same syntax as HTTP. Except of familiarity for network engineers, it allows using same parser for both protocols. However, I never saw any case of “common” parser. So I decided to try myself. I’ve took open source HTTP servlet containers, located their HTTP parsers, and tried to apply those parsers to SIP messages.

Jetty

First container was Jetty. I’ve used version 6.1.11. Parser functionality is easily located, because it is encapsulated in class org.mortbay.jetty.HttpParser. This class accepts some buffers for internal use, an EndPoint which is the source of data to parse, and EventHandler which is notified when some message component was parsed. Main method is parseNext(), which tries to parse as much data as available. Reaching end of available data, this method remembers last “state” and last position before returning, so next time it will continue from a place it has stopped. I will call such parser “stateful non-blocking stream-oriented”.

Applying Jetty parser to SIP messages is pretty easy. First, an unparsed message should be wrapped either in ByteArrayEndPoint (if message is in form of byte array) or in StringEndPoint (if message is in form of character sequence). Second, an EventHandler should be implemented, which will store parsed data in object which represents SIP message. At last, an instance of HttpParser should be created and parse() method invoked.

Parser of Jetty is not “complete” and not “strict”. For example, it doesn’t distinguish between requests and responses, it just parses three components of start line. Detailed parsing and validation of all specific headers could be done later.

Code of parser itself is quite complex. Parser works at byte level. It even provides message components as instances of org.mortbay.io.Buffer, which is very similar to java.nio.ByteBuffer. This buffer could be decoded into character format.

Tomcat

Second container was Tomcat. I’ve used version 6.0.16. HTTP parser here is located in component called “coyote”. Class which performes parsing is called org.apache.coyote.http11.InternalInputBuffer. Tomcat uses this class from method process() of class org.apache.coyote.http11.Http11Processor, which accepts Socket as input parameter. Using Http11Processor is not convenient, so I’ve used InternalInputBuffer directly, which is quite simple. Constructor accepts instance of org.apache.coyote.Request which will store parsed data. As a source of data InternalInputBuffer accepts any java.io.InputStream, so I’ve just used ByteArrayInputStream containing whole SIP message. After invoking methods parseRequestLine() and parseHeaders() it is possible to extract all nesessary data from Request, such as method, and headers, then put those data into any suitable form.

When used from Http11Processor, a parser is provided with InputStream of Socket, so read() operation used by parser will block if there are no data. I will call such parser “blocking stream-oriented”. A big drawback of Tomcat is that it isn’t able to parse SIP responses. Parser works on byte level, and all message components are stored in Request class as instances of MessageBytes class. This class performes byte-to-char conversion on demand.

Resin open-source

And finally, Resin open-source version 3.1.6. It is quite simple to locate HTTP parser here. Class is called com.caucho.server.http.HttpRequest, and a particular method is handleRequest(). Constructor of HttpRequest requires an implementation of Connection which is used as source of data. I’ve created a fake connection and assigned a readStream with StringReader which took SIP message in String format. Another option was to use ReaderStream which obtains data through any java.io.Reader (like InputStreamReader). Parser doesn’t do real UTF-8 decoding. Instead, it takes a byte, simply extends it to character, does all parsing using this character, then stores it into object field.

However, it seems to me that parser is not re-usable, because constructor of HttpRequest accepts object of Server class as argument, and I cannot fake this Server.

Conclusion

It is quite possible to use some HTTP parsers for SIP. Jetty is a winner here: you don’t need to modify it (just put a jar file into classpath), it will work perfectly with NIO and amount of code to write is small. The only drawback is that code of parser is quite complex. Parser of Tomcat is simpler, but works only for requests and only with synchronious I/O. Resin is not re-usable without modifications.

Advertisements
Categories: Java, SIP, Telecom Tags: , , , ,
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: