Commits

Paweł Wieczorek committed b5a1524 Draft Merge

merge

Comments (0)

Files changed (5)

src/Sip_parser.ml

 
         let content_length = int_of_string (Hashtbl.find mime "content-length") in
 
-        let addr_from      = SipUri (Hashtbl.find mime "from") in
+        let addr_from      = sip_address_of_string (Hashtbl.find mime "from") in
 
-        let addr_to        = SipUri (Hashtbl.find mime "to") in
+        let addr_to        = sip_address_of_string (Hashtbl.find mime "to") in
 
-        let call_id        = SipCallId (Hashtbl.find mime "call-id") in
+        let call_id        = sip_call_id_of_string (Hashtbl.find mime "call-id") in
 
-        let cseq           = SipCseq (Hashtbl.find mime "cseq") in
+        let cseq           = sip_cseq_of_string (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 uri            = sip_uri_of_string _uri in
 
-(*
-        let sip_contact    = SipContact (Hashtbl.find mime "contact") in
-*)
+        let sip_contact    = Option.map sip_address_of_string (Hashtbl.find_option mime "contact") in
 
         let max_forwards   = int_of_string (Hashtbl.find mime "max-forwards") in
 
 
         method addr_from        = addr_from
 
-        method vias             = vias
+        method vias             = List.map sip_via_of_string vias
 
         method call_id          = call_id
 
 
         method max_forwards     = max_forwards
 
-(*
         method contact          = sip_contact
-*)
 
         method header name      = Hashtbl.find mime name
 
+        method header_option name = Hashtbl.find_option mime name
+
         method header_all name  = Hashtbl.find_all mime name
 
     end
 
 (********************************************************************************************************************
  * Parser for request 
+ *
+ * I hope it is very fast, but I am not sure if it is safe.
+ * TODO: encode an monadic forward-parser and benchmark against this code
  *)
 
 exception Invalid_sip_message
 let parse_mime buffer =
     let htable = Hashtbl.create 27 in
 
+    let rec parse_multiline index =
+        let (value, index)   = find_endline index buffer in
+        if index < String.length buffer && String.get buffer index = ' '
+        then
+            let (value2, index2) = parse_multiline (succ index) in
+            (value ^ value2 , index2)
+        else
+            (value, index)
+        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
+        let (value, last) = parse_multiline last in
+        (*
+        print_endline ("KEY " ^ name);
+        print_endline ("VAL " ^ value);
+        *)
         (name, value, last)
         in
 
             parse_lines last
         in
 
-    parse_lines
+    parse_lines 
 
 let early_parse_request buffer =
     try 
         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"
-
-
     SipUri of string
 
 type sip_address =
-    SipAddress of string * sip_uri
+    SipAddress of string
 
 type sip_call_id =
     SipCallId of string
 type sip_cseq =
     SipCseq of string
 
-type sip_contact =
-    SipContact of string
-
 type sip_version =
     | SIP_1_0
     | SIP_2_0
     | UnknownSipVersion of string
 
-type sip_transport =
-    | UDP
-    | TCP
-    | SCTP
-    | TLS
-    | UnknownTransport of string
 
 type sip_via =
-    | SipVia of sip_version * sip_transport
+    | SipVia of string
 
 class type sip_request =
     object
 
         method content_length   : int
 
-        method addr_to          : sip_uri
+        method addr_to          : sip_address
 
-        method addr_from        : sip_uri
+        method addr_from        : sip_address
 
-        method vias             : string list
+        method vias             : sip_via list
 
         method call_id          : sip_call_id
 
 
         method max_forwards     : int
 
-(*
-        method contact          : sip_contact
-*)
+        method contact          : sip_address option
 
         method header           : string -> string
 
+        method header_option    : string -> string option
+
         method header_all       : string -> string list
 
+
     end
 
 (*********************************************************************************************************************
 
 let sip_cseq_of_string = function
     | s -> SipCseq s
+
+let sip_call_id_of_string = function
+    | s -> SipCallId s
+
+let string_of_sip_call_id = function
+    | SipCallId s -> s
+
+let sip_via_of_string = function
+    | s -> SipVia s
+
+let string_of_sip_via = function
+    | SipVia s -> s
+
+let sip_address_of_string = function
+    | s -> SipAddress s
+
+let string_of_sip_address = function
+    | SipAddress s -> s
+
 
 
 let test_suite = "SIP" >:::
-    [ Test_monadic_parser.test_suite
-    ; Test_parser.test_suite
+    [ Test_parser.test_suite
+    ; Test_monadic_parser.test_suite
     ]
 ;;
 

tests/Test_parser.ml

 let assert_strs_equal msg a b =
     assert_equal ~msg:msg ~printer:(fun x -> "[" ^ String.concat "," (List.map String.quote x) ^ "]") a b
 
-let validate_extracted_field request conv field extracted expected =
-    let actual_mime      = request#header (String.lowercase field) in
-    assert_equal ~msg:("mime field " ^ field) expected (conv actual_mime);
-    assert_equal ~msg:("extracted field" ^ field) expected extracted
+let _validate_field printer actual request revconv field extracted expected =
+    assert_equal
+        ~msg:("mime field " ^ field)
+        ~printer:printer
+        expected actual;
+
+    assert_equal
+        ~msg:("extracted field " ^ field)
+        ~printer:printer
+        expected extracted
+
+let validate_extracted_field request conv revconv field extracted expected =
+    let actual_mime      = conv (request#header (String.lowercase field)) in
+    let printer = String.quote -| revconv in
+    _validate_field printer actual_mime request revconv field extracted expected
+
+let validate_extracted_field_option request conv revconv field extracted expected =
+    let actual_mime      = Option.map conv (request#header_option (String.lowercase field)) in
+    let printer          = Option.map_default (String.quote -| revconv) "None" in
+    _validate_field printer actual_mime request revconv field extracted expected
+
+let validate_extracted_field_all request conv revconv field extracted expected =
+    let actual_mime      = List.map conv (request#header_all (String.lowercase field)) in
+    let printer          = String.concat "," -| List.map (String.quote -| revconv) in
+    _validate_field printer actual_mime request revconv field extracted expected
 
 let validate_message request = function
     | DescrMimeField (field, expected) ->
 
     | DescrContentLength expected ->
         let extracted = request#content_length in
-        validate_extracted_field request int_of_string "content-length" extracted expected
+        validate_extracted_field request
+            int_of_string string_of_int
+            "content-length" extracted expected
 
     | DescrMaxForwards expected ->
         let extracted = request#max_forwards in
-        validate_extracted_field request int_of_string "max-forwards" extracted expected
+        validate_extracted_field request
+            int_of_string string_of_int
+            "max-forwards" extracted expected
 
     | DescrSipVersion expected ->
         let extracted = request#sip_version in
 
     | DescrCseq expected ->
         let extracted = request#cseq in
-        validate_extracted_field request (fun s -> SipCseq s) "cseq" extracted expected
+        validate_extracted_field request
+            sip_cseq_of_string string_of_sip_cseq
+            "cseq" extracted expected
 
     | DescrCallId expected ->
         let extracted = request#call_id in
-        validate_extracted_field request (fun s -> SipCallId s) "call-id" extracted expected
+        validate_extracted_field request
+            sip_call_id_of_string string_of_sip_call_id
+            "call-id" extracted expected
+
+    | DescrTo expected ->
+        let extracted = request#addr_to in
+        validate_extracted_field request
+            sip_address_of_string string_of_sip_address
+            "to" extracted expected
+
+    | DescrFrom expected ->
+        let extracted = request#addr_from in
+        validate_extracted_field request
+            sip_address_of_string string_of_sip_address
+            "from" extracted expected
+
+    | DescrVia expected ->
+        let extracted = request#vias in
+        validate_extracted_field_all request
+            sip_via_of_string string_of_sip_via
+            "via" extracted expected
+
+    | DescrContact expected ->
+        let extracted = request#contact in
+        validate_extracted_field_option request
+            sip_address_of_string string_of_sip_address
+            "contact" extracted expected
 
 let valid_message_parse_test (title, buffer, descr) = 
     "valid message -- " ^ title >::

tests/data/Testdata_messages.ml

         | DescrUri of sip_uri
         | DescrCallId of sip_call_id
         | DescrSipMethod of sip_request_method
+        | DescrTo of sip_address
+        | DescrFrom of sip_address
+        | DescrVia of sip_via list
+        | DescrContact of sip_address option
 
     let descr_content_length i = DescrContentLength i
     let descr_sip_version i    = DescrSipVersion i
     let descr_uri c            = DescrUri c
     let descr_sip_method c     = DescrSipMethod c
     let descr_call_id c        = DescrCallId c
+    let descr_to c             = DescrTo c
+    let descr_from c           = DescrFrom c
+    let descr_via c            = DescrVia (List.rev c)
+
+    let descr_no_contact       = DescrContact None
+    let descr_contact c        = DescrContact (Some c)
 end
 
 module Valid_messages = struct
                 INVITE
 
             ; descr_uri
-                (SipUri "sip:bob@biloxi.com")
+                (sip_uri_of_string "sip:bob@biloxi.com")
 
             ; descr_sip_version
                 SIP_2_0
 
+            ; descr_contact
+                (sip_address_of_string "<sip:alice@pc33.atlanta.com>")
+
             ; descr_cseq
-                (SipCseq "314159 INVITE")
+                (sip_cseq_of_string "314159 INVITE")
 
             ; descr_call_id
-                (SipCallId "a84b4c76e66710@pc33.atlanta.com")
+                (sip_call_id_of_string "a84b4c76e66710@pc33.atlanta.com")
 
             ; descr_max_forwards
                 70
 
+            ; descr_to
+                (sip_address_of_string "Bob <sip:bob@biloxi.com>")
+
+            ; descr_from
+                (sip_address_of_string "Alice <sip:alice@atlanta.com>;tag=1928301774")
+
             ; descr_content_length
                 142
 
+            ; descr_mime_field "Content-type"
+                "application/sdp"
+
             ; descr_mime_fields
                 "Via"
                 [ "SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bK776asdhds" 
                 ]
+
+            ; descr_via
+                [ sip_via_of_string "SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bK776asdhds" 
+                ]
             ]
 
         ; prepare_valid_message "basic invite RFC3261.4, multiline header"
                 INVITE
 
             ; descr_uri
-                (SipUri "sip:bob@biloxi.com")
+                (sip_uri_of_string "sip:bob@biloxi.com")
 
             ; descr_sip_version
                 SIP_2_0
 
+            ; descr_to
+                (sip_address_of_string "Bob <sip:bob@biloxi.com>")
+
+            ; descr_from
+                (sip_address_of_string "Alice <sip:alice@atlanta.com>;tag=1928301774")
+
             ; descr_call_id
-                (SipCallId "a84b4c76e66710")
+                (sip_call_id_of_string "a84b4c76e66710")
 
             ; descr_cseq
-                (SipCseq "314159 INVITE")
+                (sip_cseq_of_string "314159 INVITE")
 
             ; descr_max_forwards 70
 
 
             ; descr_content_length
                 568
+
+            ; descr_via
+                [ sip_via_of_string
+                    "SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8"
+                ]
             ]
 
         ; prepare_valid_message "basic invite RFC3261.4, but as SIP/1.0"
                 OPTIONS
 
             ; descr_uri
-                (SipUri "sip:carol@chicago.com")
+                (sip_uri_of_string "sip:carol@chicago.com")
 
             ; descr_sip_version
                 SIP_2_0
 
             ; descr_max_forwards
                 70
+
+            ; descr_to
+                (sip_address_of_string "<sip:carol@chicago.com>")
+
+            ; descr_from
+                (sip_address_of_string "Alice <sip:alice@atlanta.com>;tag=1928301774")
+
+            ; descr_via
+                [ sip_via_of_string
+                    "SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKhjhs8ass877"
+                ]
             ]
 
         ; prepare_valid_message "register from RFC3261.24.1"
                 REGISTER
 
             ; descr_uri
-                (SipUri "sip:registrar.biloxi.com")
+                (sip_uri_of_string "sip:registrar.biloxi.com")
 
             ; descr_sip_version
                 SIP_2_0
 
+            ; descr_to
+                (sip_address_of_string "Bob <sip:bob@biloxi.com>")
+
+            ; descr_from
+                (sip_address_of_string "Bob <sip:bob@biloxi.com>;tag=456248")
+
             ; descr_max_forwards
                 70
 
             ; descr_call_id
-                (SipCallId "843817637684230@998sdasdh09")
+                (sip_call_id_of_string "843817637684230@998sdasdh09")
 
             ; descr_cseq
-                (SipCseq "1826 REGISTER")
+                (sip_cseq_of_string "1826 REGISTER")
 
             ; descr_content_length
                 0
+
+            ; descr_via
+                [ sip_via_of_string
+                    "SIP/2.0/UDP bobspc.biloxi.com:5060;branch=z9hG4bKnashds7"
+                ]
             ]
 
         ; prepare_valid_message "sip message from RFC3261.24.2 (Alice -> atlanta.com proxy)"
 
             ; descr_sip_version
                 SIP_2_0
+
+            ; descr_to
+                (sip_address_of_string "Bob <sip:bob@biloxi.com>")
+
+            ; descr_from
+                (sip_address_of_string "Alice <sip:alice@atlanta.com>;tag=1928301774")
+
+            ; descr_via
+                [ sip_via_of_string
+                    "SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8"
+                ]
+
             ]
 
         ; prepare_valid_message "sip message from RFC3261.24.2 (atlanta.com proxy -> biloxi.com proxy)"
 
             ; descr_sip_version
                 SIP_2_0
+
+            ; descr_to
+                (sip_address_of_string "Bob <sip:bob@biloxi.com>")
+
+            ; descr_from
+                (sip_address_of_string "Alice <sip:alice@atlanta.com>;tag=1928301774")
+
+            ; descr_via
+                [ sip_via_of_string
+                    "SIP/2.0/UDP bigbox3.site3.atlanta.com;branch=z9hG4bK77ef4c2312983.1"
+                ; sip_via_of_string
+                    "SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8;received=192.0.2.1"
+                ]
             ]
 
         ; prepare_valid_message "sip message from RFC3261.24.2 (biloxi.com proxy -> Bob)"
 
             ; descr_sip_version
                 SIP_2_0
+
+            ; descr_to
+                (sip_address_of_string "Bob <sip:bob@biloxi.com>")
+
+            ; descr_from
+                (sip_address_of_string "Alice <sip:alice@atlanta.com>;tag=1928301774")
+
+            ; descr_via
+                [ sip_via_of_string
+                    "SIP/2.0/UDP server10.biloxi.com;branch=z9hG4bK4b43c2ff8.1"
+                ; sip_via_of_string
+                    "SIP/2.0/UDP bigbox3.site3.atlanta.com;branch=z9hG4bK77ef4c2312983.1;received=192.0.2.2"
+                ; sip_via_of_string
+                    "SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8;received=192.0.2.1"
+                ]
             ]
 
         ; prepare_valid_message "sip message ACK from RFC3261.24.2 (Alice -> Bob)"
 
             ; descr_sip_version
                 SIP_2_0
+
+            ; descr_to
+                (sip_address_of_string "Bob <sip:bob@biloxi.com>;tag=a6c85cf")
+
+            ; descr_from
+                (sip_address_of_string "Alice <sip:alice@atlanta.com>;tag=1928301774")
+
+            ; descr_via
+                [ sip_via_of_string
+                    "SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds9"
+                ]
             ]
 
         ; prepare_valid_message "sip message BYE from RFC3261.24.2 (Bob -> Alice)"
 
             ; descr_sip_version
                 SIP_2_0
+
+            ; descr_to
+                (sip_address_of_string "Alice <sip:alice@atlanta.com>;tag=1928301774")
+
+            ; descr_from
+                (sip_address_of_string "Bob <sip:bob@biloxi.com>;tag=a6c85cf")
+
+            ; descr_via
+                [ sip_via_of_string
+                    "SIP/2.0/UDP 192.0.2.4;branch=z9hG4bKnashds10"
+                ]
             ]
 
-    ]
+        ; prepare_valid_message "sip message with unknown method SOMEMETHOD"
+            [ "SOMEMETHOD sip:alice@pc33.atlanta.com SIP/2.0"
+            ; "Via: SIP/2.0/UDP 192.0.2.4;branch=z9hG4bKnashds10"
+            ; "Max-Forwards: 70"
+            ; "From: Bob <sip:bob@biloxi.com>;tag=a6c85cf"
+            ; "To: Alice <sip:alice@atlanta.com>;tag=1928301774"
+            ; "Call-ID: a84b4c76e66710"
+            ; "CSeq: 231 BYE"
+            ; "Content-Length: 0"
+            ; ""
+            ; ""
+            ]
+
+            [ descr_sip_method
+                (UnknownRequestMethod "SOMEMETHOD")
+
+            ; descr_sip_version
+                SIP_2_0
+
+            ; descr_to
+                (sip_address_of_string "Alice <sip:alice@atlanta.com>;tag=1928301774")
+
+            ; descr_from
+                (sip_address_of_string "Bob <sip:bob@biloxi.com>;tag=a6c85cf")
+
+            ; descr_via
+                [ sip_via_of_string
+                    "SIP/2.0/UDP 192.0.2.4;branch=z9hG4bKnashds10"
+                ]
+            ]
+
+        ]
+
+
+    let response =
+        [ prepare_valid_message "sip response from RFC3261.4"
+            [ "SIP/2.0 200 OK"
+            ; "Via: SIP/2.0/UDP server10.biloxi.com"
+            ; "   ;branch=z9hG4bKnashds8;received=192.0.2.3"
+            ; "Via: SIP/2.0/UDP bigbox3.site3.atlanta.com"
+            ; "   ;branch=z9hG4bK77ef4c2312983.1;received=192.0.2.2"
+            ; "Via: SIP/2.0/UDP pc33.atlanta.com"
+            ; "   ;branch=z9hG4bK776asdhds ;received=192.0.2.1"
+            ; "To: Bob <sip:bob@biloxi.com>;tag=a6c85cf"
+            ; "From: Alice <sip:alice@atlanta.com>;tag=1928301774"
+            ; "Call-ID: a84b4c76e66710@pc33.atlanta.com"
+            ; "CSeq: 314159 INVITE"
+            ; "Contact: <sip:bob@192.0.2.4>"
+            ; "Content-Type: application/sdp"
+            ; "Content-Length: 131"
+            ; ""
+            ; String.repeat "a" 131
+            ]
+
+            [
+            ]
+
+         ; prepare_valid_message "sip response from RFC3261.11"
+            [ "SIP/2.0 200 OK"
+            ; "Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKhjhs8ass877"
+            ; " ;received=192.0.2.4"
+            ; "To: <sip:carol@chicago.com>;tag=93810874"
+            ; "From: Alice <sip:alice@atlanta.com>;tag=1928301774"
+            ; "Call-ID: a84b4c76e66710"
+            ; "CSeq: 63104 OPTIONS"
+            ; "Contact: <sip:carol@chicago.com>"
+            ; "Contact: <mailto:carol@chicago.com>"
+            ; "Allow: INVITE, ACK, CANCEL, OPTIONS, BYE"
+            ; "Accept: application/sdp"
+            ; "Accept-Encoding: gzip"
+            ; "Accept-Language: en"
+            ; "Supported: foo"
+            ; "Content-Type: application/sdp"
+            ; "Content-Length: 274"
+            ; ""
+            ; String.repeat "a" 274
+            ]
+
+            [
+            ]
+]
 
 end
 
             ; ""
             ; String.repeat "a" 142
             ]
+
+        ; prepare_invalid_message "basic invite RFC3261.4"
+            [ "INVITE invalid:bob@biloxi.com SIP/2.0" 
+            ; "Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bK776asdhds" 
+            ; "Max-Forwards: 70" 
+            ; "To: Bob <sip:bob@biloxi.com>" 
+            ; "From: Alice <sip:alice@atlanta.com>;tag=1928301774" 
+            ; "Call-ID: a84b4c76e66710@pc33.atlanta.com" 
+            ; "CSeq: 314159 INVITE"
+            ; "Contact: <sip:alice@pc33.atlanta.com>"
+            ; "Content-Type: application/sdp"
+            ; "Content-Length: 142"
+            ; ""
+            ; String.repeat "a" 142
+            ]
+
         ]
 
-
 end