Browse code

core:sdp parser: gracefully handle \n-terminated SDP

Stefan Sayer authored on 24/07/2014 16:23:40
Showing 4 changed files
... ...
@@ -33,14 +33,19 @@ using std::map;
33 33
 #include "strings.h"
34 34
 #endif
35 35
 
36
+#define CR   '\r'
37
+#define LF   '\n'
38
+#define CRLF "\r\n"
39
+
36 40
 static void parse_session_attr(AmSdp* sdp_msg, char* s, char** next);
37 41
 static bool parse_sdp_line_ex(AmSdp* sdp_msg, char*& s);
38
-static void parse_sdp_connection(AmSdp* sdp_msg, char* s, char t);
42
+static char* parse_sdp_connection(AmSdp* sdp_msg, char* s, char t);
39 43
 static void parse_sdp_media(AmSdp* sdp_msg, char* s);
40
-static void parse_sdp_attr(AmSdp* sdp_msg, char* s);
44
+static char* parse_sdp_attr(AmSdp* sdp_msg, char* s);
41 45
 static void parse_sdp_origin(AmSdp* sdp_masg, char* s);
42 46
 
43 47
 inline char* get_next_line(char* s);
48
+inline char* skip_till_next_line(char* s, size_t& line_len);
44 49
 static char* is_eql_next(char* s);
45 50
 static char* parse_until(char* s, char end);
46 51
 static char* parse_until(char* s, char* end, char c);
... ...
@@ -555,7 +560,7 @@ static bool parse_sdp_line_ex(AmSdp* sdp_msg, char*& s)
555 560
 {
556 561
   if (!s) return true; // SDP can't be empty, return error (true really used for failure?)
557 562
 
558
-  char* next=0;
563
+  char* next=0; size_t line_len = 0;
559 564
   register parse_st state;
560 565
   //default state
561 566
   state=SDP_DESCR;
... ...
@@ -568,11 +573,13 @@ static bool parse_sdp_line_ex(AmSdp* sdp_msg, char*& s)
568 573
       case 'v':
569 574
 	{
570 575
 	  s = is_eql_next(s);
571
-	  next = get_next_line(s);
572
-	  if (int(next-s)-2 >= 0) {
573
-	    string version(s, int(next-s)-2);
576
+	  next = skip_till_next_line(s, line_len);
577
+	  if (line_len) {
578
+	    string version(s, line_len);
574 579
 	    str2i(version, sdp_msg->version);
575
-	    //DBG("parse_sdp_line_ex: found version\n");
580
+	    //	    DBG("parse_sdp_line_ex: found version '%s'\n", version.c_str());
581
+	  } else {
582
+	    sdp_msg->version = 0;
576 583
 	  }
577 584
 	  s = next;
578 585
 	  state = SDP_DESCR;
... ...
@@ -588,23 +595,24 @@ static bool parse_sdp_line_ex(AmSdp* sdp_msg, char*& s)
588 595
 	break;
589 596
       case 's':
590 597
 	{
591
-	  //DBG("parse_sdp_line_ex: found session\n");
592 598
 	  s = is_eql_next(s);
593
-	  next = get_next_line(s);
594
-	  if (int(next-s)-2 >= 0) {
595
-	    string sessionName(s, int(next-s)-2);
596
-	    sdp_msg->sessionName = sessionName;
599
+	  next = skip_till_next_line(s, line_len);
600
+	  if (line_len) {
601
+	    sdp_msg->sessionName = string(s, line_len);
602
+	  } else {
603
+	    sdp_msg->sessionName.clear();
597 604
 	  }
598 605
 	  s = next;
599 606
 	  break;
600 607
 	}
601 608
 
602 609
       case 'u': {
603
-	//DBG("parse_sdp_line_ex: found uri\n");
604 610
 	  s = is_eql_next(s);
605
-	  next = get_next_line(s);
606
-	  if (int(next-s)-2 >= 0) {
607
-	    sdp_msg->uri = string(s, int(next-s)-2);
611
+	  next = skip_till_next_line(s, line_len);
612
+	  if (line_len) {
613
+	    sdp_msg->uri = string(s, line_len);
614
+	  } else {
615
+	    sdp_msg->uri.clear();
608 616
 	  }
609 617
 	  s = next;
610 618
       } break;
... ...
@@ -615,14 +623,11 @@ static bool parse_sdp_line_ex(AmSdp* sdp_msg, char*& s)
615 623
       case 'b':
616 624
       case 't':
617 625
       case 'k':
618
-	//DBG("parse_sdp_line_ex: found unknown line '%c'\n", *s);
619 626
 	s = is_eql_next(s);
620
-	next = get_next_line(s);
621
-	s = next;
627
+	s = skip_till_next_line(s, line_len);
622 628
 	state = SDP_DESCR;
623 629
 	break;
624 630
       case 'a':
625
-	//DBG("parse_sdp_line_ex: found attributes\n");
626 631
 	s = is_eql_next(s);
627 632
 	parse_session_attr(sdp_msg, s, &next);
628 633
 	// next = get_next_line(s);
... ...
@@ -631,11 +636,9 @@ static bool parse_sdp_line_ex(AmSdp* sdp_msg, char*& s)
631 636
 	state = SDP_DESCR;
632 637
 	break;
633 638
       case 'c':
634
-	//DBG("parse_sdp_line_ex: found connection\n");
635 639
 	s = is_eql_next(s);
636
-	parse_sdp_connection(sdp_msg, s, 'd');
637
-	s = get_next_line(s);
638
-	state = SDP_DESCR;	
640
+	s = parse_sdp_connection(sdp_msg, s, 'd');
641
+	state = SDP_DESCR;
639 642
 	break;
640 643
       case 'm':
641 644
 	//DBG("parse_sdp_line_ex: found media\n");
... ...
@@ -644,11 +647,17 @@ static bool parse_sdp_line_ex(AmSdp* sdp_msg, char*& s)
644 647
 
645 648
       default:
646 649
 	{
647
-	  next = get_next_line(s);
648
-	  if (int(next-s)-2 >= 0) {
649
-	    string line(s, int(next-s)-2);
650
+	  next = skip_till_next_line(s, line_len);
651
+	  if (line_len) {
652
+	    sdp_msg->uri = string(s, line_len);
653
+	  } else {
654
+	    sdp_msg->uri.clear();
655
+	  }
656
+
657
+	  next = skip_till_next_line(s, line_len);
658
+	  if (line_len) {
650 659
 	    DBG("parse_sdp_line: skipping unknown Session description %s=\n",
651
-		(char*)line.c_str());
660
+		string(s, line_len).c_str());
652 661
 	  }
653 662
 	  s = next;
654 663
 	  break;
... ...
@@ -661,45 +670,42 @@ static bool parse_sdp_line_ex(AmSdp* sdp_msg, char*& s)
661 670
       case 'm':
662 671
 	s = is_eql_next(s);
663 672
 	parse_sdp_media(sdp_msg, s);
664
-	s = get_next_line(s);
673
+	s = skip_till_next_line(s, line_len);
665 674
 	state = SDP_MEDIA;
666 675
 	break;
667 676
       case 'i':
668 677
 	s = is_eql_next(s);
669
-	s = get_next_line(s);
678
+	s = skip_till_next_line(s, line_len);
670 679
 	state = SDP_MEDIA;
671 680
 	break;
672 681
       case 'c':
673 682
 	s = is_eql_next(s);
674 683
 	//DBG("parse_sdp_line: found media connection\n");
675
-	parse_sdp_connection(sdp_msg, s, 'm');
676
-	s = get_next_line(s);
684
+	s = parse_sdp_connection(sdp_msg, s, 'm');
677 685
 	state = SDP_MEDIA;
678 686
 	break;
679 687
       case 'b':
680 688
 	s = is_eql_next(s);
681
-	s = get_next_line(s);
689
+	s = skip_till_next_line(s, line_len);
682 690
 	state = SDP_MEDIA;
683 691
 	break;
684 692
       case 'k':
685 693
 	s = is_eql_next(s);
686
-	s = get_next_line(s);
694
+	s = skip_till_next_line(s, line_len);
687 695
 	state = SDP_MEDIA;
688 696
 	break;
689 697
       case 'a':
690 698
 	s = is_eql_next(s);
691
-	parse_sdp_attr(sdp_msg, s);
692
-	s = get_next_line(s);
699
+	s = parse_sdp_attr(sdp_msg, s);
693 700
 	state = SDP_MEDIA;
694 701
 	break;
695 702
 	
696 703
       default :
697 704
 	{
698
-	  next = get_next_line(s);
699
-	  if (int(next-s)-2 >= 0) {
700
-	    string line(s, int(next-s)-2);
701
-	    DBG("parse_sdp_line: skipping unknown Media description '%s'\n",
702
-		(char*)line.c_str());
705
+	  next = skip_till_next_line(s, line_len);
706
+	  if (line_len) {
707
+	    DBG("parse_sdp_line: skipping unknown Media description '%.*s'\n",
708
+		(int)line_len, s);
703 709
 	  }
704 710
 	  s = next;
705 711
 	  break;
... ...
@@ -713,17 +719,23 @@ static bool parse_sdp_line_ex(AmSdp* sdp_msg, char*& s)
713 719
 }
714 720
 
715 721
 
716
-static void parse_sdp_connection(AmSdp* sdp_msg, char* s, char t)
722
+static char* parse_sdp_connection(AmSdp* sdp_msg, char* s, char t)
717 723
 {
718 724
   
719 725
   char* connection_line=s;
720 726
   char* next=0;
721
-  char* line_end=0;
727
+  char* next_line=0;
728
+  size_t line_len = 0;
722 729
   int parsing=1;
723 730
 
724 731
   SdpConnection c;
725 732
 
726
-  line_end = get_next_line(s);
733
+  next_line = skip_till_next_line(s, line_len);
734
+  if (line_len <= 7) { // should be at least c=IN IP4 ...
735
+    DBG("short connection line '%.*s'\n", (int)line_len, s);
736
+    return next_line;
737
+  }
738
+
727 739
   register sdp_connection_st state;
728 740
   state = NET_TYPE;
729 741
 
... ...
@@ -732,34 +744,35 @@ static void parse_sdp_connection(AmSdp* sdp_msg, char* s, char t)
732 744
   while(parsing){
733 745
     switch(state){
734 746
     case NET_TYPE:
735
-      //Ignore NET_TYPE since it is always IN 
736
-      connection_line +=3;
747
+      //Ignore NET_TYPE since it is always IN, fixme
748
+      c.network = NT_IN; // fixme
749
+      connection_line +=3; // fixme
737 750
       state = ADDR_TYPE;
738 751
       break;
739 752
     case ADDR_TYPE:
740 753
       {
741 754
 	string addr_type(connection_line,3);
742
-	connection_line +=4;
755
+	connection_line +=4; // fixme
743 756
 	if(addr_type == "IP4"){
744
-	  c.addrType = 1;
757
+	  c.addrType = AT_V4;
745 758
 	  state = IP4;
746 759
 	}else if(addr_type == "IP6"){
747
-	  c.addrType = 2;
760
+	  c.addrType = AT_V6;
748 761
 	  state = IP6;
749 762
 	}else{
750
-	  ERROR("parse_sdp_connection: Unknown addr_type in c=\n");
751
-	  c.addrType = 0;
752
-	  parsing = 0;
763
+	  DBG("parse_sdp_connection: Unknown addr_type in c-line: '%s'\n", addr_type.c_str());
764
+	  c.addrType = AT_NONE;
765
+	  parsing = 0; // ???
753 766
 	}
754 767
 	break;
755 768
       }
756 769
     case IP4:
757 770
       {
758
-	  if(contains(connection_line, line_end, '/')){
771
+	  if(contains(connection_line, next_line, '/')){
759 772
 	      next = parse_until(s, '/');
760 773
 	      c.address = string(connection_line,int(next-connection_line)-2);
761 774
 	  }else{
762
-	      c.address = string(connection_line, int(line_end-connection_line)-2);
775
+	    c.address = string(connection_line, line_len-7);
763 776
 	  }
764 777
 	  parsing = 0;
765 778
 	  break;
... ...
@@ -767,11 +780,11 @@ static void parse_sdp_connection(AmSdp* sdp_msg, char* s, char t)
767 780
       
768 781
     case IP6:
769 782
       { 
770
-	  if(contains(connection_line, line_end, '/')){
783
+	  if(contains(connection_line, next_line, '/')){
771 784
 	      next = parse_until(s, '/');
772 785
 	      c.address = string(connection_line, int(next-connection_line)-2);
773 786
 	  }else{
774
-	      c.address = string(connection_line, int(line_end-connection_line)-2);
787
+	      c.address = string(connection_line, line_len-7);
775 788
 	  }
776 789
 	  parsing = 0;
777 790
 	  break;
... ...
@@ -788,7 +801,7 @@ static void parse_sdp_connection(AmSdp* sdp_msg, char* s, char t)
788 801
   }
789 802
 
790 803
   //DBG("parse_sdp_line_ex: parse_sdp_connection: done parsing sdp connection\n");
791
-  return;
804
+  return next_line;
792 805
 }
793 806
 
794 807
 
... ...
@@ -930,7 +943,8 @@ static void parse_sdp_media(AmSdp* sdp_msg, char* s)
930 943
 
931 944
 // session level attribute
932 945
 static void parse_session_attr(AmSdp* sdp_msg, char* s, char** next) {
933
-  *next = get_next_line(s);
946
+  size_t line_len = 0;
947
+  *next = skip_till_next_line(s, line_len);
934 948
   if (*next == s) {
935 949
     WARN("premature end of SDP in session attr\n");
936 950
     while (**next != '\0') (*next)++;
... ...
@@ -938,7 +952,7 @@ static void parse_session_attr(AmSdp* sdp_msg, char* s, char** next) {
938 952
   }
939 953
   char* attr_end = *next-1;
940 954
   while (attr_end >= s &&
941
-	 ((*attr_end == 10) || (*attr_end == 13)))
955
+	 ((*attr_end == LF) || (*attr_end == CR)))
942 956
     attr_end--;
943 957
 
944 958
   if (*attr_end == ':') {
... ...
@@ -959,15 +973,14 @@ static void parse_session_attr(AmSdp* sdp_msg, char* s, char** next) {
959 973
 					       string(col, attr_end-col+1)));
960 974
     // DBG("got session attribute '%.*s:%.*s'\n", (int)(col-s-1), s, (int)(attr_end-col+1), col);
961 975
   }
962
-
963 976
 }
964 977
 
965 978
 // media level attribute
966
-static void parse_sdp_attr(AmSdp* sdp_msg, char* s)
979
+static char* parse_sdp_attr(AmSdp* sdp_msg, char* s)
967 980
 {
968 981
   if(sdp_msg->media.empty()){
969 982
     ERROR("While parsing media options: no actual media !\n");
970
-    return;
983
+    return s;
971 984
   }
972 985
   
973 986
   SdpMedia& media = sdp_msg->media.back();
... ...
@@ -981,20 +994,16 @@ static void parse_sdp_attr(AmSdp* sdp_msg, char* s)
981 994
   char* attr_line=s;
982 995
   char* next=0;
983 996
   char* line_end=0;
997
+  size_t line_len = 0;
984 998
   int parsing = 1;
985
-  line_end = get_next_line(attr_line);
999
+  line_end = skip_till_next_line(attr_line, line_len);
986 1000
   
987 1001
   unsigned int payload_type, clock_rate, encoding_param = 0;
988 1002
   string encoding_name, params;
989 1003
 
990 1004
   string attr;
991 1005
   if (!contains(attr_line, line_end, ':')) {
992
-    next = parse_until(attr_line, '\r');
993
-    if (next >= line_end) {
994
-      DBG("found attribute line '%s', which is not followed by cr\n", attr_line);
995
-      next = line_end;
996
-    }
997
-    attr = string(attr_line, int(next-attr_line)-1);
1006
+    attr = string(attr_line, line_len);
998 1007
     attr_check(attr);
999 1008
     parsing = 0;
1000 1009
   } else {
... ...
@@ -1089,10 +1098,10 @@ static void parse_sdp_attr(AmSdp* sdp_msg, char* s)
1089 1098
 
1090 1099
   } else if(attr == "fmtp"){
1091 1100
     while(parsing){
1092
-      switch(fmtp_st){
1101
+      switch(fmtp_st){ // fixme
1093 1102
       case FORMAT:
1094 1103
 	{
1095
-	  next = parse_until(attr_line, ' ');
1104
+	  next = parse_until(attr_line, line_end, ' ');
1096 1105
 	  string fmtp_format(attr_line, int(next-attr_line)-1);
1097 1106
 	  str2i(fmtp_format, payload_type);
1098 1107
 	  attr_line = next;
... ...
@@ -1100,12 +1109,12 @@ static void parse_sdp_attr(AmSdp* sdp_msg, char* s)
1100 1109
 	  break;
1101 1110
 	}
1102 1111
       case FORMAT_PARAM:
1103
-	{ 
1104
-	  line_end--;
1105
-	  while (is_wsp(*line_end))
1106
-	    line_end--;
1112
+	{
1113
+	  char* param_end = line_end-1;
1114
+	  while (is_wsp(*param_end))
1115
+	    param_end--;
1107 1116
 
1108
-	  params = string(attr_line, line_end-attr_line+1);
1117
+	  params = string(attr_line, param_end-attr_line+1);
1109 1118
 	  parsing = 0;
1110 1119
 	}
1111 1120
 	break;
... ...
@@ -1127,21 +1136,20 @@ static void parse_sdp_attr(AmSdp* sdp_msg, char* s)
1127 1136
 
1128 1137
   } else if (attr == "direction") {
1129 1138
     if (parsing) {
1130
-      next = parse_until(attr_line, '\r');
1131
-      if(next < line_end){
1132
-	string value(attr_line, int(next-attr_line)-1);
1133
-	if (value == "active") {
1134
-	  media.dir=SdpMedia::DirActive;
1135
-	  // DBG("found media attr 'direction' value '%s'\n", (char*)value.c_str());
1136
-	} else if (value == "passive") {
1137
-	  media.dir=SdpMedia::DirPassive;
1138
-	  //DBG("found media attr 'direction' value '%s'\n", (char*)value.c_str());
1139
-	} else if (attr == "both") {
1140
-	  media.dir=SdpMedia::DirBoth;
1141
-	  //DBG("found media attr 'direction' value '%s'\n", (char*)value.c_str());
1142
-	} 
1139
+      size_t dir_len = 0;
1140
+      next = skip_till_next_line(attr_line, dir_len);
1141
+      string value(attr_line, dir_len);
1142
+      if (value == "active") {
1143
+	media.dir=SdpMedia::DirActive;
1144
+	// DBG("found media attr 'direction' value '%s'\n", (char*)value.c_str());
1145
+      } else if (value == "passive") {
1146
+	media.dir=SdpMedia::DirPassive;
1147
+	//DBG("found media attr 'direction' value '%s'\n", (char*)value.c_str());
1148
+      } else if (attr == "both") {
1149
+	media.dir=SdpMedia::DirBoth;
1150
+	//DBG("found media attr 'direction' value '%s'\n", (char*)value.c_str());
1143 1151
       } else {
1144
-	DBG("found media attribute 'direction', but value is not followed by cr\n");
1152
+	DBG("found unknown value for media attribute 'direction'\n");
1145 1153
       }
1146 1154
     } else {
1147 1155
       DBG("ignoring direction attribute without value\n");
... ...
@@ -1162,12 +1170,9 @@ static void parse_sdp_attr(AmSdp* sdp_msg, char* s)
1162 1170
     attr_check(attr);
1163 1171
     string value;
1164 1172
     if (parsing) {
1165
-      next = parse_until(attr_line, '\r');
1166
-      if(next >= line_end){
1167
-	DBG("found media attribute '%s', but value is not followed by cr\n",
1168
-	    (char *)attr.c_str());
1169
-      }
1170
-      value = string (attr_line, int(next-attr_line)-1);
1173
+      size_t attr_len = 0;
1174
+      next = skip_till_next_line(attr_line, attr_len);
1175
+      value = string (attr_line, attr_len);
1171 1176
     }
1172 1177
 
1173 1178
     // if (value.empty()) {
... ...
@@ -1177,6 +1182,7 @@ static void parse_sdp_attr(AmSdp* sdp_msg, char* s)
1177 1182
     // }
1178 1183
     media.attributes.push_back(SdpAttribute(attr, value));
1179 1184
   }
1185
+  return line_end;
1180 1186
 }
1181 1187
 
1182 1188
 static void parse_sdp_origin(AmSdp* sdp_msg, char* s)
... ...
@@ -1184,7 +1190,8 @@ static void parse_sdp_origin(AmSdp* sdp_msg, char* s)
1184 1190
   char* origin_line = s;
1185 1191
   char* next=0;
1186 1192
   char* line_end=0;
1187
-  line_end = get_next_line(s);
1193
+  size_t line_len=0;
1194
+  line_end = skip_till_next_line(s, line_len);
1188 1195
   
1189 1196
   register sdp_origin_st origin_st;
1190 1197
   origin_st = USER;
... ...
@@ -1248,6 +1255,7 @@ static void parse_sdp_origin(AmSdp* sdp_msg, char* s)
1248 1255
 	    break;
1249 1256
 	  }
1250 1257
 	  string net_type(origin_line, int(next-origin_line)-1);
1258
+	  origin.conn.network = NT_IN; // fixme
1251 1259
 	  origin_line = next;
1252 1260
 	  origin_st = ADDR;
1253 1261
 	  break;
... ...
@@ -1260,7 +1268,17 @@ static void parse_sdp_origin(AmSdp* sdp_msg, char* s)
1260 1268
 	    origin_st = UNICAST_ADDR;
1261 1269
 	    break;
1262 1270
 	  }
1271
+
1263 1272
 	  string addr_type(origin_line, int(next-origin_line)-1);
1273
+	  if(addr_type == "IP4"){
1274
+	    origin.conn.addrType = AT_V4;
1275
+	  }else if(addr_type == "IP6"){
1276
+	    origin.conn.addrType = AT_V6;
1277
+	  }else{
1278
+	    DBG("parse_sdp_connection: Unknown addr_type in o line: '%s'\n", addr_type.c_str());
1279
+	    origin.conn.addrType = AT_NONE;
1280
+	  }
1281
+
1264 1282
 	  origin_line = next;
1265 1283
 	  origin_st = UNICAST_ADDR;
1266 1284
 	  break;
... ...
@@ -1268,12 +1286,18 @@ static void parse_sdp_origin(AmSdp* sdp_msg, char* s)
1268 1286
       case UNICAST_ADDR:
1269 1287
 	{
1270 1288
 	  next = parse_until(origin_line, ' ');
1271
-	  //check if line contains more values than allowed
1272
-	  if(next > line_end){
1273
-	    origin.conn.address = string(origin_line, int(line_end-origin_line)-2);
1274
-	  }else{
1275
-	    DBG("parse_sdp_origin: 'o=' contains more values than allowed; these values will be ignored\n");  
1276
-	    origin.conn.address = string(origin_line, int(next-origin_line)-1);
1289
+	  if (next != origin_line) {
1290
+	    //check if line contains more values than allowed
1291
+	    if(next > line_end){
1292
+	      size_t addr_len = 0;
1293
+	      skip_till_next_line(origin_line, addr_len);
1294
+	      origin.conn.address = string(origin_line, addr_len);
1295
+	    }else{
1296
+	      DBG("parse_sdp_origin: 'o=' contains more values than allowed; these values will be ignored\n");  
1297
+	      origin.conn.address = string(origin_line, int(next-origin_line)-1);
1298
+	    }
1299
+	  } else {
1300
+	    origin.conn.address = "";
1277 1301
 	  }
1278 1302
 	  parsing = 0;
1279 1303
 	  break;
... ...
@@ -1328,6 +1352,28 @@ static char* parse_until(char* s, char* end, char c)
1328 1352
   return line;
1329 1353
 }
1330 1354
 
1355
+static size_t len_till_eol(char* s, char* end)
1356
+{
1357
+  size_t res=0;
1358
+  char* line=s;
1359
+  while(line<end && *line && *line != '\r' && *line != '\n'){
1360
+    line++;
1361
+    res++;
1362
+  }
1363
+  return res;
1364
+}
1365
+
1366
+static size_t len_till_char_or_eol(char* s, char* end, char c)
1367
+{
1368
+  size_t res=0;
1369
+  char* line=s;
1370
+  while(line<end && *line && *line !=  c && *line != '\r' && *line != '\n'){
1371
+    line++;
1372
+    res++;
1373
+  }
1374
+  return res;
1375
+}
1376
+
1331 1377
 static char* is_eql_next(char* s)
1332 1378
 {
1333 1379
   char* current_line=s;
... ...
@@ -1343,20 +1389,53 @@ inline char* get_next_line(char* s)
1343 1389
   char* next_line=s;
1344 1390
   //search for next line
1345 1391
  while( *next_line != '\0') {
1346
-    if(*next_line == 13){
1347
-      next_line +=2;
1392
+    if(*next_line == CR){
1393
+      next_line++;
1394
+      if (*next_line == LF) {
1395
+	next_line++;
1396
+	break;
1397
+      } else {
1398
+	continue;
1399
+      }
1400
+    } else if (*next_line == LF){	
1401
+      next_line++;
1348 1402
       break;
1349 1403
     }
1350
-    else if(*next_line == 10){	
1351
-      next_line +=1;
1352
-      break;
1353
-    }  
1354 1404
     next_line++;
1355 1405
  }
1356 1406
 
1357 1407
   return next_line; 
1358 1408
 }
1359 1409
 
1410
+/* skip to 0, CRLF or LF;
1411
+   @return line_len length of current line
1412
+   @return start of next line 
1413
+*/
1414
+inline char* skip_till_next_line(char* s, size_t& line_len)
1415
+{
1416
+  char* next_line=s;
1417
+  line_len = 0;
1418
+
1419
+  //search for next line
1420
+  while( *next_line != '\0') {
1421
+    if (*next_line == CR) {
1422
+      next_line++;
1423
+      if (*next_line == LF) {
1424
+	next_line++;
1425
+	break;
1426
+      } else {
1427
+	continue;
1428
+      }
1429
+    } else if (*next_line == LF){	
1430
+      next_line++;
1431
+      break;
1432
+    }
1433
+    line_len++;
1434
+    next_line++;
1435
+ }
1436
+
1437
+  return next_line; 
1438
+}
1360 1439
 
1361 1440
 /*
1362 1441
  *Check if known media type is used
... ...
@@ -22,6 +22,7 @@ FCT_BGN() {
22 22
   log_stderr=true;
23 23
   log_level=3;
24 24
 
25
+  FCTMF_SUITE_CALL(test_sdp);
25 26
   FCTMF_SUITE_CALL(test_auth);
26 27
   FCTMF_SUITE_CALL(test_headers);
27 28
   FCTMF_SUITE_CALL(test_uriparser);
28 29
new file mode 100644
... ...
@@ -0,0 +1,90 @@
1
+#include "fct.h"
2
+
3
+#include "log.h"
4
+
5
+#include "AmSdp.h"
6
+
7
+#define CRLF "\r\n"
8
+#define LF "\n"
9
+
10
+FCTMF_SUITE_BGN(test_sdp) {
11
+
12
+    FCT_TEST_BGN(normal_sdp_ok) {
13
+      AmSdp s;
14
+      string sdp = 
15
+	"v=0" CRLF
16
+	"o=- 3615077380 3615077398 IN IP4 178.66.14.5" CRLF
17
+	"s=-" CRLF
18
+	"c=IN IP4 178.66.14.5" CRLF
19
+	"t=0 0" CRLF
20
+	"m=audio 21964 RTP/AVP 0 101" CRLF
21
+	"a=sendrecv" CRLF
22
+	"a=ptime:20" CRLF
23
+	"a=rtpmap:0 PCMU/8000" CRLF
24
+	"a=rtpmap:101 telephone-event/8000" CRLF
25
+	"a=fmtp:101 0-15" CRLF ;
26
+
27
+      fct_chk(!s.parse(sdp.c_str()));
28
+      fct_chk(s.version==0);
29
+      fct_chk(s.origin.user == "-");
30
+      fct_chk(s.origin.sessId == 3615077380);
31
+      fct_chk(s.origin.sessV == 3615077398);
32
+      fct_chk(s.origin.conn.address == "178.66.14.5");
33
+      fct_chk(s.origin.conn.network == NT_IN);
34
+      fct_chk(s.origin.conn.addrType == AT_V4);
35
+
36
+      fct_chk(s.conn.address == "178.66.14.5");
37
+      fct_chk(s.conn.network == NT_IN);
38
+      fct_chk(s.conn.addrType == AT_V4);
39
+
40
+      fct_chk(s.media.size() == 1);
41
+      fct_chk(s.media[0].type == MT_AUDIO);
42
+      fct_chk(s.media[0].port == 21964);
43
+      fct_chk(s.media[0].transport == TP_RTPAVP);
44
+      fct_chk(s.media[0].payloads.size()==2);
45
+      fct_chk(s.media[0].payloads[0].payload_type==0);
46
+      fct_chk(s.media[0].payloads[1].payload_type==101);
47
+      fct_chk(s.media[0].payloads[0].encoding_name=="PCMU");
48
+      fct_chk(s.media[0].payloads[1].encoding_name=="telephone-event");
49
+    } FCT_TEST_END();
50
+
51
+    FCT_TEST_BGN(sdp_LF_no_CRLF) {
52
+      AmSdp s;
53
+      string sdp = 
54
+	"v=0" LF
55
+	"o=- 3615077380 3615077398 IN IP4 178.66.14.5" LF
56
+	"s=-" LF
57
+	"c=IN IP4 178.66.14.5" LF
58
+	"t=0 0" LF
59
+	"m=audio 21964 RTP/AVP 0 101" LF
60
+	"a=sendrecv" LF
61
+	"a=ptime:20" LF
62
+	"a=rtpmap:0 PCMU/8000" LF
63
+	"a=rtpmap:101 telephone-event/8000" LF
64
+	"a=fmtp:101 0-15" LF ;
65
+
66
+      fct_chk(!s.parse(sdp.c_str()));
67
+      fct_chk(s.version==0);
68
+      fct_chk(s.origin.user == "-");
69
+      fct_chk(s.origin.sessId == 3615077380);
70
+      fct_chk(s.origin.sessV == 3615077398);
71
+      fct_chk(s.origin.conn.address == "178.66.14.5");
72
+      fct_chk(s.origin.conn.network == NT_IN);
73
+      fct_chk(s.origin.conn.addrType == AT_V4);
74
+
75
+      fct_chk(s.conn.address == "178.66.14.5");
76
+      fct_chk(s.conn.network == NT_IN);
77
+      fct_chk(s.conn.addrType == AT_V4);
78
+
79
+      fct_chk(s.media.size() == 1);
80
+      fct_chk(s.media[0].type == MT_AUDIO);
81
+      fct_chk(s.media[0].port == 21964);
82
+      fct_chk(s.media[0].transport == TP_RTPAVP);
83
+      fct_chk(s.media[0].payloads.size()==2);
84
+      fct_chk(s.media[0].payloads[0].payload_type==0);
85
+      fct_chk(s.media[0].payloads[1].payload_type==101);
86
+      fct_chk(s.media[0].payloads[0].encoding_name=="PCMU");
87
+      fct_chk(s.media[0].payloads[1].encoding_name=="telephone-event");
88
+    } FCT_TEST_END();
89
+
90
+} FCTMF_SUITE_END();
0 91
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+