Ragel SIP parser¶
A SIP parser based on Ragel State Machine Compiler. It's 100% strict and implements BNF grammar in RFC 3261 and 3966.
Installation¶
Install Ragel¶
The first step is installing the last stable version of Ragel.
- Download Ragel from http://www.complang.org/ragel/ragel-6.6.tar.gz.
- Install it by running
./configure,make,make install.
- Check the installacion:
~$ ragel -v Ragel State Machine Compiler version X.X NNNNN YYYY Copyright (c) 2001-2009 by Adrian Thurston
Install ABNF Generator¶
ABFN Generator parses ABNF definitions from source file and generates output as state machine definition for Ragel.
- Download the version 0.2 from http://www.2p.cz/files/2p.cz/downloads/abnfgen-src.0.2.tgz.
- Compile it by running
make. You will get an executableabnfgen.
- Copy/move/link the executable
abnfgento a directory into yourPATHenvironment variable (ie:/usr/local/bin). Make sure it has execution permissions for your user.
- Check the installation:
~$ abnfgen -V abnfgen - ABNF generator, v0.1
Install Ruby 1.8 and RubyGems¶
- Make sure you have
Ruby 1.8installed in your computer:~$ ruby -v ruby 1.8.6 (2007-09-24 patchlevel 111) [i486-linux]
- Download
RubyGemsfrom http://rubyforge.org/frs/download.php/45905/rubygems-1.3.1.tgz.
- Install it by running
ruby setup.rbas root.
- Check the installation:
~$ gem1.8 -v 1.3.1
- Install
term-ansicolorgem (as root):~# gem1.8 install term-ansicolor
Download Ragel SIP Parser¶
- Get it using Subversion:
~$ svn co svn://dev.sipdoc.net/Ragel-SIP-Parser Ragel-SIP-Parser
- Enter into the directory
Ragel-SIP-Parserand make sure thatsip_parser.shhas running permissions. If not add them by running:~$ chmod +x sip_parser.sh
Usage¶
~$ ./sip_parser.sh KEYWORD 'TEXT'
KEYWORD: Any BNF keyword in RFC 3261 or RFC 3966TEXT: Text to match enclosed with ' or "
~$ ./sip_parser.sh KEYWORD -f FILE
KEYWORD: Any BNF keyword in RFC 3261 or RFC 3966FILE: File containing the text to match, don't add newline (<CRLF> string is replaced with "\r\n")
After running the above command, the script will compile the Ragel machine according to the KEYWORD parameter and show a colorized output. In case the text is invalid, the first wrong character will be pointed by a red arrow.
Examples¶
- Checking a valid 'Request-Line':
~$ ./sip_parser.sh Request-Line 'INVITE sip:ibc@aliax.net;transport=TcP SIP/2.0' Compiling 'sip_parser.rl' ... OK Parsing 'Request_Line': INVITE sip:ibc@aliax.net;transport=TcP SIP/2.0 ... -------------------------------- Finished: cs: 387 p: 47 pe: 47 Time: 0.000954 -------------------------------- OK
- Checking an invalid 'SIP-URI' (host part contains illegal character '
_'):~$ ./sip_parser.sh SIP-URI 'SIp:alice:mypassword@invalid_hostpart.com:5070;param=xxx' Compiling 'sip_parser.rl' ... OK Parsing 'SIP_URI': SIp:alice:mypassword@invalid_hostpart.com:5070;param=xxx ... -------------------------------- Finished: cs: 0 p: 28 pe: 57 Error parsing the data in character 28: SIp:alice:mypassword@invalid_hostpart.com:5070;param=xxx ^ Time: 0.001084 -------------------------------- ERROR
- Checking a valid 'From' header:
./sip_parser.sh From 'f: "Iñaki B.C." <sips:ibc@aliax.net;cool=yes>;hparam1=on;hparam2;hparam3=xxx' Compiling 'sip_parser.rl' ... OK Parsing 'From': f: "Iñaki B.C." <sips:ibc@aliax.net;cool=yes>;hparam1=on;hparam2;hparam3=xxx ... -------------------------------- Finished: cs: 858 p: 78 pe: 78 Time: 0.001584 -------------------------------- OK
- Checking an invalid 'Contact' multi-value header (the third URI is in 'addr-spec' form containing an invalid question mark '
?' symbol):~$ ./sip_parser.sh Contact 'ConTACT: Alice <sip:alice?VALID-QUESTION-MARK@domain.org>;hparam=1 , tel:+1234;param=asd, sips:user?INVALID-QUESTION-MARK@mydomain.org' Compiling 'sip_parser.rl' ... OK Parsing 'Contact': ConTACT: Alice <sip:alice?VALID-QUESTION-MARK@domain.org>;hparam=1 , tel:+1234;param=asd, sips:user?INVALID-QUESTION-MARK@mydomain.org ... -------------------------------- Finished: cs: 0 p: 102 pe: 138 Error parsing the data in character 102: ConTACT: Alice <sip:alice?VALID-QUESTION-MARK@domain.org>;hparam=1 , tel:+1234;param=asd, sips:user?INVALID-QUESTION-MARK@mydomain.org ^ Time: 0.001813 -------------------------------- ERROR
- Checking an invalid 'telephone-uri' (it's a 'local number' so it needs the param
phone-context):~$ ./sip_parser.sh telephone-uri 'tel:1234' Compiling 'sip_parser.rl' ... OK Parsing 'telephone_uri': tel:1234 ... -------------------------------- Finished: cs: 0 p: 8 pe: 9 Error parsing the data in character 8: tel:1234 ^ Time: 0.000826 -------------------------------- ERROR
- Checking a valid IPv6:
~$ ./sip_parser.sh IPv6address '2001:0db8:85a3:08d3:1319:8a2e:0370:7334' Compiling 'sip_parser.rl' ... OK Parsing 'IPv6address': 2001:0db8:85a3:08d3:1319:8a2e:0370:7334 ... -------------------------------- Finished: cs: 152 p: 40 pe: 40 Time: 0.00083 -------------------------------- OK
Examples using grammar written in a file¶
Some SIP grammars cannot be written as Bash command line argument since they include invalid characters as ! or '. We can write the grammar in a file and test it. Also we can simulate a CRLF by writting "<CRLF>" in the file.
For example let check a valid 'Request-Line' appearing in RFC 4475 (SIP Torture Messages):
- First create a file called 'FILE' (note there must not be a new line at the end):
!interesting-Method0123456789_*+`.%indeed'~ sip:1_unusual.URI~(to-be!sure)&isn't+it$/crazy?,/;;*:&it+has=1,weird!*pas$wo~d_too.(doesn't-it)@example.com SIP/2.0
- Check it:
~$ ./sip_parser.sh Request-Line -f FILE Compiling 'sip_parser.rl' ... OK Parsing 'Request_Line': !interesting-Method0123456789_*+`.0ndeed'~ sip:1_unusual.URI~(to-be!sure)&isn't+it$/crazy?,/;;*:&it+has=1,weird!*pas$wo~d_too.(doesn't-it)@example.com SIP/2.0 ... -------------------------------- Finished: cs: 387 p: 160 pe: 160 Time: 0.001961 -------------------------------- OK
Now, let insert a valid CRLF into a 'Via' header:
- Create a file called 'FILE2':
Via: SIP / 2.0 / UDP<CRLF> first.example.com: 4000;ttl=16;maddr=224.2.0.1 ;branch=z9hG4bKa7c6a8dlze.1
- Let's check it:
$ ./sip_parser.sh Via -f FILE Compiling 'sip_parser.rl' ... OK Parsing 'Via': Via: SIP / 2.0 / UDP first.example.com: 4000;ttl=16;maddr=224.2.0.1 ;branch=z9hG4bKa7c6a8dlze.1 ... -------------------------------- Finished: cs: 624 p: 98 pe: 98 Time: 0.001065 -------------------------------- OK
Issues¶
svn update¶
Some files are generated or modified each time 'sip_parser.sh' is executed (for example 'main.rl'). But these files are also included in the Subversion repository so when doing a svn update you will get some conflicts, ie:
~$/Ragel-SIP-Parser$ svn update A FILE C main.rl U sip_parser.sh C sip_parser.rb Updated to revision 47.
In order to avoid it, delete the files in conflict and perform the svn update (this is a really dirty workaround, perhaps it's possible to force an update of the trunk version replacing our local modifed files instead of creating "conflict" files).
svn_update.sh will perform these steps for us:
- It deletes 'main.rl' and 'sip_parser.rb' files.
- It executes
svn update.
Example:
~$ ./svn_update.sh Deleting 'main.rl' and 'sip_parser.rb' ... svn update ... Se restituyó 'main.rl' Se restituyó 'sip_parser.rb' In revision 48. OK
UTF-8 in Ruby output¶
UTF-8 symbols are wrongly displayed in the Ruby output so the error pointer (^) could point to incorrect position.