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.

  • 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.

  • Compile it by running make. You will get an executable abnfgen.
  • Copy/move/link the executable abnfgen to a directory into your PATH environment 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.8 installed in your computer:
    ~$ ruby -v
    ruby 1.8.6 (2007-09-24 patchlevel 111) [i486-linux]
    
  • Install it by running ruby setup.rb as root.
  • Check the installation:
    ~$ gem1.8 -v
    1.3.1
    
  • Install term-ansicolor gem (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-Parser and make sure that sip_parser.sh has 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 3966
  • TEXT : Text to match enclosed with ' or "
~$ ./sip_parser.sh KEYWORD -f FILE
  • KEYWORD : Any BNF keyword in RFC 3261 or RFC 3966
  • FILE : 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).

An included command called 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.

Also available in: HTML TXT