Source

ocaml-sip / src / Sip_parser.ml

(*********************************************************************************************************************
 *
 *)
open Batteries

open Sip_utils
open Sip_types

(********************************************************************************************************************
 * Parsed request 
 *)

class parsed_sip_request _reqmethod _uri _version mime : sip_request =

        (* compute and extract required informations *)

        let reqmethod      = sip_request_method_of_string _reqmethod in

        let content_length = int_of_string (Hashtbl.find mime "content-length") in

        let addr_from      = SipUri (Hashtbl.find mime "from") in

        let addr_to        = SipUri (Hashtbl.find mime "to") in

        let call_id        = SipCallId (Hashtbl.find mime "call-id") in

        let cseq           = SipCseq (Hashtbl.find mime "cseq") in

        let vias           = Hashtbl.find_all mime "via" in

        let version        = sip_version_of_string _version in

        let uri            = SipUri _uri in

        let sip_contact    = SipContact (Hashtbl.find mime "contact") in

        let max_forwards   = int_of_string (Hashtbl.find mime "max-forwards") in

        (* construct object *)

    object

        val mime                = mime

        method sip_method       = reqmethod

        method sip_version      = version

        method uri              = uri

        method content_length   = content_length

        method addr_to          = addr_to

        method addr_from        = addr_from

        method vias             = vias

        method call_id          = call_id

        method cseq             = cseq

        method max_forwards     = max_forwards

        method contact          = sip_contact

        method header name      = Hashtbl.find mime name

        method headers name     = Hashtbl.find_all mime name

    end

(********************************************************************************************************************
 * Parser for request 
 *)

exception Invalid_sip_message

let parse_request_method buffer = 
    let (strmethod, last) = find_word 0 buffer in
    (sip_request_method_of_string strmethod, last)

let parse_request_line buffer =
    let (reqmethod, last) = find_word 0    buffer in
    let (uri,       last) = find_word last buffer in
    let (ver,       last) = find_word last buffer in
    let (_,         last) = find_endline last buffer in
    (reqmethod, uri, ver, last)

let parse_mime buffer =
    let htable = Hashtbl.create 27 in

    let parse_entry first =
        let seps          = [' '; '\r'; '\n'; ':'] in
        let (name,  last) = find_sep seps first buffer in
        let (       last) = skip_seps seps buffer last in
        let (value, last) = find_endline last buffer in
        (name, value, last)
        in

    let rec parse_lines last =
        let (line, _) = find_endline last buffer in
        if String.length line == 0 
        then
            (htable, last + 2)
        else
            let (name, value, last) = parse_entry last in
            Hashtbl.add htable (String.lowercase name) value;
            parse_lines last
        in

    parse_lines

let early_parse_request buffer =
    try 
        let (reqmethod, uri, sipver, last) = parse_request_line buffer in
        let (mime, last)                   = parse_mime buffer last in
        (reqmethod, uri, sipver, mime, last)
    with
        Not_found | Invalid_argument _ ->
            raise Invalid_sip_message

let parse_request buffer : sip_request =
    let (reqmethod, uri, sipver, mime, last) = early_parse_request buffer in
    try
        new parsed_sip_request reqmethod uri sipver mime
    with
        Not_found | Failure _ ->
            raise Invalid_sip_message

let test1 = 
    "INVITE sip2 SIP/2.0\r\n" ^
    "A: 20\r\n" ^
    "B: 30\r\n" ^
    "C: 40\r\n" ^
    "\r\n" ^
    "Content" 


let test2 =
      "INVITE sip:bob@biloxi.com SIP/2.0" ^ eol_sep ^
      "Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bK776asdhds" ^ eol_sep ^
      "Max-Forwards: 70" ^ eol_sep ^
      "To: Bob <sip:bob@biloxi.com>" ^ eol_sep ^
      "From: Alice <sip:alice@atlanta.com>;tag=1928301774" ^ eol_sep ^
      "Call-ID: a84b4c76e66710@pc33.atlanta.com" ^ eol_sep ^
      "CSeq: 314159 INVITE" ^ eol_sep ^
      "Contact: <sip:alice@pc33.atlanta.com>" ^ eol_sep ^
      "Content-Type: application/sdp" ^ eol_sep ^
      "Content-Length: 142" ^ eol_sep ^
      eol_sep ^
      "blaa"