sdp_helpr_funcs.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815
  1. /*
  2. * SDP parser helpers
  3. *
  4. * Copyright (C) 2008-2009 SOMA Networks, INC.
  5. * Copyright (C) 2010 VoIP Embedded, Inc
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright notice,
  11. * this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT ``AS IS'' AND ANY EXPRESS OR
  17. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  18. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
  19. * EVENT SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  20. * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  21. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  22. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  23. * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  24. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  25. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. *
  27. */
  28. #include <stdlib.h>
  29. #include "../../ut.h"
  30. #include "../msg_parser.h"
  31. #include "../parser_f.h"
  32. #include "../parse_hname2.h"
  33. #include "sdp.h"
  34. static struct {
  35. const char *s;
  36. int len;
  37. int is_rtp;
  38. } sup_ptypes[] = {
  39. {.s = "rtp/avp", .len = 7, .is_rtp = 1},
  40. {.s = "udptl", .len = 5, .is_rtp = 0},
  41. {.s = "rtp/avpf", .len = 8, .is_rtp = 1},
  42. {.s = "rtp/savp", .len = 8, .is_rtp = 1},
  43. {.s = "rtp/savpf", .len = 9, .is_rtp = 1},
  44. {.s = "udp", .len = 3, .is_rtp = 0},
  45. {.s = "udp/bfcp", .len = 8, .is_rtp = 0},
  46. {.s = NULL, .len = 0, .is_rtp = 0}
  47. };
  48. #define READ(val) \
  49. (*(val + 0) + (*(val + 1) << 8) + (*(val + 2) << 16) + (*(val + 3) << 24))
  50. #define advance(_ptr,_n,_str,_error) \
  51. do{\
  52. if ((_ptr)+(_n)>(_str).s+(_str).len)\
  53. goto _error;\
  54. (_ptr) = (_ptr) + (_n);\
  55. }while(0);
  56. #define one_of_16( _x , _t ) \
  57. (_x==_t[0]||_x==_t[15]||_x==_t[8]||_x==_t[2]||_x==_t[3]||_x==_t[4]\
  58. ||_x==_t[5]||_x==_t[6]||_x==_t[7]||_x==_t[1]||_x==_t[9]||_x==_t[10]\
  59. ||_x==_t[11]||_x==_t[12]||_x==_t[13]||_x==_t[14])
  60. #define one_of_8( _x , _t ) \
  61. (_x==_t[0]||_x==_t[7]||_x==_t[1]||_x==_t[2]||_x==_t[3]||_x==_t[4]\
  62. ||_x==_t[5]||_x==_t[6])
  63. /*
  64. * ser_memmem() returns the location of the first occurrence of data
  65. * pattern b2 of size len2 in memory block b1 of size len1 or
  66. * NULL if none is found. Obtained from NetBSD.
  67. */
  68. static void * ser_memmem(const void *b1, const void *b2, size_t len1, size_t len2)
  69. {
  70. /* Initialize search pointer */
  71. char *sp = (char *) b1;
  72. /* Initialize pattern pointer */
  73. char *pp = (char *) b2;
  74. /* Initialize end of search address space pointer */
  75. char *eos = sp + len1 - len2;
  76. /* Sanity check */
  77. if(!(b1 && b2 && len1 && len2))
  78. return NULL;
  79. while (sp <= eos) {
  80. if (*sp == *pp)
  81. if (memcmp(sp, pp, len2) == 0)
  82. return sp;
  83. sp++;
  84. }
  85. return NULL;
  86. }
  87. /*
  88. * ser_memrmem() returns the location of the last occurrence of data
  89. * pattern b2 of size len2 in memory block b1 of size len1 or
  90. * NULL if none is found.
  91. */
  92. static void * ser_memrmem(const void *b1, const void *b2, size_t len1, size_t len2)
  93. {
  94. /* Initialize search pointer */
  95. char *sp = (char *) b1 + len1 - len2;
  96. /* Initialize pattern pointer */
  97. char *pp = (char *) b2;
  98. /* Initialize end of search address space pointer */
  99. char *eos = (char *) b1;
  100. /* Sanity check */
  101. if(!(b1 && b2 && len1 && len2))
  102. return NULL;
  103. while (sp >= eos) {
  104. if (*sp == *pp)
  105. if (memcmp(sp, pp, len2) == 0)
  106. return sp;
  107. sp--;
  108. }
  109. return NULL;
  110. }
  111. int get_mixed_part_delimiter(str* body, str *mp_delimiter)
  112. {
  113. static unsigned int boun[16] = {
  114. 0x6e756f62,0x4e756f62,0x6e556f62,0x4e556f62,
  115. 0x6e754f62,0x4e754f62,0x6e554f62,0x4e554f62,
  116. 0x6e756f42,0x4e756f42,0x6e556f42,0x4e556f42,
  117. 0x6e754f42,0x4e754f42,0x6e554f42,0x4e554f42};
  118. static unsigned int dary[16] = {
  119. 0x79726164,0x59726164,0x79526164,0x59526164,
  120. 0x79724164,0x59724164,0x79524164,0x59524164,
  121. 0x79726144,0x59726144,0x79526144,0x59526144,
  122. 0x79724144,0x59724144,0x79524144,0x59524144};
  123. str str_type;
  124. unsigned int x;
  125. char *p;
  126. /* LM_DBG("<%.*s>\n",body->len,body->s); */
  127. p = str_type.s = body->s;
  128. str_type.len = body->len;
  129. while (*p!=';' && p<(body->s+body->len))
  130. advance(p,1,str_type,error);
  131. p++;
  132. str_type.s = p;
  133. str_type.len = body->len - (p - body->s);
  134. /* LM_DBG("string to parse: <%.*s>\n",str_type.len,str_type.s); */
  135. /* skip spaces and tabs if any */
  136. while (*p==' ' || *p=='\t')
  137. advance(p,1,str_type,error);
  138. advance(p,4,str_type,error);
  139. x = READ(p-4);
  140. if (!one_of_16(x,boun))
  141. goto other;
  142. advance(p,4,str_type,error);
  143. x = READ(p-4);
  144. if (!one_of_16(x,dary))
  145. goto other;
  146. /* skip spaces and tabs if any */
  147. while (*p==' ' || *p=='\t')
  148. advance(p,1,str_type,error);
  149. if (*p!='=') {
  150. LM_ERR("parse error: no = found after boundary field\n");
  151. goto error;
  152. }
  153. advance(p,1,str_type,error);
  154. while ((*p==' ' || *p=='\t') && p+1<str_type.s+str_type.len)
  155. advance(p,1,str_type,error);
  156. mp_delimiter->len = str_type.len - (int)(p-str_type.s);
  157. mp_delimiter->s = p;
  158. /* check if the boundary value is enclosed in quotes */
  159. if(*p=='"' || *p=='\'') {
  160. if(mp_delimiter->s[mp_delimiter->len-1]==*p) {
  161. mp_delimiter->s = p+1;
  162. mp_delimiter->len -= 2;
  163. if(mp_delimiter->len<=0) {
  164. LM_ERR("invalid boundary field value\n");
  165. goto error;
  166. }
  167. } else {
  168. LM_ERR("missing closing quote in boundary field value\n");
  169. goto error;
  170. }
  171. }
  172. return 1;
  173. error:
  174. return -1;
  175. other:
  176. LM_DBG("'boundary' parsing error\n");
  177. return -1;
  178. }
  179. /**
  180. * rfc4566:
  181. * a=rtpmap:<payload type> <encoding name>/<clock rate> [/<encoding parameters>]
  182. */
  183. int extract_rtpmap(str *body,
  184. str *rtpmap_payload, str *rtpmap_encoding, str *rtpmap_clockrate, str *rtpmap_parmas)
  185. {
  186. char *cp, *cp1;
  187. int len;
  188. if (strncasecmp(body->s, "a=rtpmap:", 9) !=0) {
  189. /*LM_DBG("We are not pointing to an a=rtpmap: attribute =>`%.*s'\n", body->len, body->s); */
  190. return -1;
  191. }
  192. cp1 = body->s;
  193. rtpmap_payload->s = cp1 + 9; /* skip `a=rtpmap:' */
  194. rtpmap_payload->len = eat_line(rtpmap_payload->s, body->s + body->len -
  195. rtpmap_payload->s) - rtpmap_payload->s;
  196. trim_len(rtpmap_payload->len, rtpmap_payload->s, *rtpmap_payload);
  197. len = rtpmap_payload->len;
  198. /* */
  199. cp = eat_token_end(rtpmap_payload->s, rtpmap_payload->s + rtpmap_payload->len);
  200. rtpmap_payload->len = cp - rtpmap_payload->s;
  201. if (rtpmap_payload->len <= 0 || cp == rtpmap_payload->s) {
  202. LM_ERR("no encoding in `a=rtpmap'\n");
  203. return -1;
  204. }
  205. len -= rtpmap_payload->len;
  206. rtpmap_encoding->s = cp;
  207. cp = eat_space_end(rtpmap_encoding->s, rtpmap_encoding->s + len);
  208. len -= cp - rtpmap_encoding->s;
  209. if (len <= 0 || cp == rtpmap_encoding->s) {
  210. LM_ERR("no encoding in `a=rtpmap:'\n");
  211. return -1;
  212. }
  213. rtpmap_encoding->s = cp;
  214. cp1 = (char*)ser_memmem(cp, "/", len, 1);
  215. if(cp1==NULL) {
  216. LM_ERR("invalid encoding in `a=rtpmap' at [%.*s]\n", len, cp);
  217. return -1;
  218. }
  219. len -= cp1 - cp;
  220. rtpmap_encoding->len = cp1 - cp;
  221. cp = cp1+1; /* skip '/' */
  222. len--;
  223. rtpmap_clockrate->s = cp;
  224. cp1 = (char*)ser_memmem(cp, "/", len, 1);
  225. if(cp1==NULL) {
  226. /* no encoding parameters */
  227. rtpmap_clockrate->len = len;
  228. rtpmap_parmas->s = NULL;
  229. rtpmap_parmas->len = 0;
  230. return 0;
  231. }
  232. rtpmap_clockrate->len = cp1 - cp;
  233. len -= cp1 - cp;
  234. rtpmap_parmas->s = cp1 + 1; /* skip '/' */
  235. rtpmap_parmas->len = len - 1;
  236. return 0;
  237. }
  238. int extract_fmtp( str *body, str *fmtp_payload, str *fmtp_string )
  239. {
  240. char *cp, *cp1;
  241. int len;
  242. if (strncasecmp(body->s, "a=fmtp:", 7) !=0) {
  243. /*LM_DBG("We are not pointing to an a=fmtp: attribute =>`%.*s'\n", body->len, body->s); */
  244. return -1;
  245. }
  246. cp1 = body->s;
  247. fmtp_payload->s = cp1 + 7; /* skip `a=fmtp:' */
  248. fmtp_payload->len = eat_line(fmtp_payload->s, body->s + body->len -
  249. fmtp_payload->s) - fmtp_payload->s;
  250. trim_len(fmtp_payload->len, fmtp_payload->s, *fmtp_payload);
  251. len = fmtp_payload->len;
  252. /* */
  253. cp = eat_token_end(fmtp_payload->s, fmtp_payload->s + fmtp_payload->len);
  254. fmtp_payload->len = cp - fmtp_payload->s;
  255. if (fmtp_payload->len <= 0 || cp == fmtp_payload->s) {
  256. LM_ERR("no encoding in `a=fmtp:'\n");
  257. return -1;
  258. }
  259. len -= fmtp_payload->len;
  260. fmtp_string->s = cp;
  261. cp = eat_space_end(fmtp_string->s, fmtp_string->s + len);
  262. len -= cp - fmtp_string->s;
  263. if (len <= 0 || cp == fmtp_string->s) {
  264. LM_ERR("no encoding in `a=fmtp:'\n");
  265. return -1;
  266. }
  267. fmtp_string->s = cp;
  268. fmtp_string->len = eat_line(fmtp_string->s, body->s + body->len -
  269. fmtp_string->s) - fmtp_string->s;
  270. trim_len(fmtp_string->len, fmtp_string->s, *fmtp_string);
  271. return 0;
  272. }
  273. /**
  274. * Allocate a new ice attribute
  275. */
  276. static inline sdp_ice_attr_t *add_sdp_ice(sdp_stream_cell_t* _stream)
  277. {
  278. sdp_ice_attr_t *ice_attr;
  279. int len;
  280. len = sizeof(sdp_ice_attr_t);
  281. ice_attr = (sdp_ice_attr_t *)pkg_malloc(len);
  282. if (ice_attr == NULL) {
  283. LM_ERR("No memory left\n");
  284. return NULL;
  285. }
  286. memset( ice_attr, 0, len);
  287. /* Insert the new ice attribute */
  288. ice_attr->next = _stream->ice_attr;
  289. _stream->ice_attr = ice_attr;
  290. _stream->ice_attrs_num++;
  291. return ice_attr;
  292. }
  293. int extract_candidate(str *body, sdp_stream_cell_t *stream)
  294. {
  295. char *space, *start;
  296. int len, fl;
  297. sdp_ice_attr_t *ice_attr;
  298. if ((body->len < 12) || (strncasecmp(body->s, "a=candidate:", 12) != 0)) {
  299. /*LM_DBG("We are not pointing to an a=candidate: attribute =>`%.*s'\n", body->len, body->s); */
  300. return -1;
  301. }
  302. start = body->s + 12;
  303. len = body->len - 12;
  304. space = memchr(start, 32, len);
  305. if ((space == NULL) || (space - start + 3 > len) || !isdigit(*(space + 1))) {
  306. LM_ERR("no component in `a=candidate'\n");
  307. return -1;
  308. }
  309. fl = space - start;
  310. start = space + 1;
  311. len = len - (space - start + 1);
  312. space = memchr(start, 32, len);
  313. if (space == NULL) {
  314. LM_ERR("no component in `a=candidate'\n");
  315. return -1;
  316. }
  317. ice_attr = add_sdp_ice(stream);
  318. if (ice_attr == NULL) {
  319. LM_ERR("failed to add ice attribute\n");
  320. return -1;
  321. }
  322. /* currently only foundation and component-id are parsed */
  323. /* if needed, parse more */
  324. ice_attr->foundation.s = body->s + 12;
  325. ice_attr->foundation.len = fl;
  326. ice_attr->component_id = strtol(start, (char **)NULL, 10);
  327. return 0;
  328. }
  329. /* generic method for attribute extraction
  330. * field must has format "a=attrname:" */
  331. int extract_field(str *body, str *value, str field)
  332. {
  333. if (strncmp(body->s, field.s, field.len < body->len ? field.len : body->len) !=0) {
  334. /*LM_DBG("We are not pointing to an %.* attribute =>`%.*s'\n", field.len, field.s, body->len, body->s); */
  335. return -1;
  336. }
  337. value->s = body->s + field.len; /* skip `a=attrname:' */
  338. value->len = eat_line(value->s, body->s + body->len -
  339. value->s) - value->s;
  340. trim_len(value->len, value->s, *value);
  341. return 0;
  342. }
  343. int extract_ptime(str *body, str *ptime)
  344. {
  345. static const str field = str_init("a=ptime:");
  346. return extract_field(body, ptime, field);
  347. }
  348. int extract_accept_types(str *body, str *accept_types)
  349. {
  350. static const str field = str_init("a=accept-types:");
  351. return extract_field(body, accept_types, field);
  352. }
  353. int extract_accept_wrapped_types(str *body, str *accept_wrapped_types)
  354. {
  355. static const str field = str_init("a=accept-wrapped-types:");
  356. return extract_field(body, accept_wrapped_types, field);
  357. }
  358. int extract_max_size(str *body, str *max_size)
  359. {
  360. static const str field = str_init("a=max-size:");
  361. return extract_field(body, max_size, field);
  362. }
  363. int extract_path(str *body, str *path)
  364. {
  365. static const str field = str_init("a=path:");
  366. return extract_field(body, path, field);
  367. }
  368. int extract_rtcp(str *body, str *rtcp)
  369. {
  370. static const str field = str_init("a=rtcp:");
  371. return extract_field(body, rtcp, field);
  372. }
  373. int extract_sendrecv_mode(str *body, str *sendrecv_mode, int *is_on_hold)
  374. {
  375. char *cp1;
  376. cp1 = body->s;
  377. if ( !( (strncasecmp(cp1, "a=sendrecv", 10) == 0) ||
  378. (strncasecmp(cp1, "a=recvonly", 10) == 0))) {
  379. if ((strncasecmp(cp1, "a=inactive", 10) == 0) ||
  380. (strncasecmp(cp1, "a=sendonly", 10) == 0) ) {
  381. *is_on_hold = 1;
  382. } else {
  383. return -1;
  384. }
  385. }
  386. sendrecv_mode->s = body->s + 2; /* skip `a=' */
  387. sendrecv_mode->len = 8; /* we know the length and therefore we don't need to overkill */
  388. /*
  389. sendrecv_mode->len = eat_line(sendrecv_mode->s, body->s + body->len -
  390. sendrecv_mode->s) - sendrecv_mode->s;
  391. trim_len(sendrecv_mode->len, sendrecv_mode->s, *sendrecv_mode);
  392. */
  393. return 0;
  394. }
  395. int extract_bwidth(str *body, str *bwtype, str *bwwitdth)
  396. {
  397. char *cp, *cp1;
  398. int len;
  399. cp1 = NULL;
  400. for (cp = body->s; (len = body->s + body->len - cp) > 0;) {
  401. cp1 = (char*)ser_memmem(cp, "b=", len, 2);
  402. if (cp1 == NULL || cp1[-1] == '\n' || cp1[-1] == '\r')
  403. break;
  404. cp = cp1 + 2;
  405. }
  406. if (cp1 == NULL)
  407. return -1;
  408. bwtype->s = cp1 + 2;
  409. bwtype->len = eat_line(bwtype->s, body->s + body->len - bwtype->s) - bwtype->s;
  410. trim_len(bwtype->len, bwtype->s, *bwtype);
  411. cp = bwtype->s;
  412. len = bwtype->len;
  413. cp1 = (char*)ser_memmem(cp, ":", len, 1);
  414. len -= cp1 - cp;
  415. if (len <= 0) {
  416. LM_ERR("invalid encoding in `b=%.*s'\n", bwtype->len, bwtype->s);
  417. return -1;
  418. }
  419. bwtype->len = cp1 - cp;
  420. /* skip ':' */
  421. bwwitdth->s = cp1 + 1;
  422. bwwitdth->len = len - 1;
  423. return 0;
  424. }
  425. int extract_mediaip(str *body, str *mediaip, int *pf, char *line)
  426. {
  427. char *cp, *cp1;
  428. int len;
  429. cp1 = NULL;
  430. for (cp = body->s; (len = body->s + body->len - cp) > 0;) {
  431. cp1 = (char*)ser_memmem(cp, line, len, 2);
  432. if (cp1 == NULL || cp1[-1] == '\n' || cp1[-1] == '\r')
  433. break;
  434. cp = cp1 + 2;
  435. }
  436. if (cp1 == NULL)
  437. return -1;
  438. mediaip->s = cp1 + 2;
  439. mediaip->len = eat_line(mediaip->s, body->s + body->len - mediaip->s) - mediaip->s;
  440. trim_len(mediaip->len, mediaip->s, *mediaip);
  441. if (mediaip->len == 0) {
  442. LM_ERR("no [%s] line in SDP\n",line);
  443. return -1;
  444. }
  445. /* search reverse for IP[4|6] in c=/o= line */
  446. cp = (char*)ser_memrmem(mediaip->s, " IP", mediaip->len, 3);
  447. if (cp == NULL) {
  448. LM_ERR("no `IP[4|6]' in `%s' field\n",line);
  449. return -1;
  450. }
  451. /* safety checks:
  452. * - for lenght, at least 6: ' IP[4|6] x...'
  453. * - white space after
  454. */
  455. if(cp + 6 > mediaip->s + mediaip->len && cp[4]!=' ') {
  456. LM_ERR("invalid content for `%s' line\n",line);
  457. return -1;
  458. }
  459. switch(cp[3]) {
  460. case '4':
  461. *pf = AF_INET;
  462. break;
  463. case '6':
  464. *pf = AF_INET6;
  465. break;
  466. default:
  467. LM_ERR("invalid addrtype IPx for `%s' line\n",line);
  468. return -1;
  469. }
  470. cp += 5;
  471. /* next token is the IP address */
  472. cp = eat_space_end(cp, mediaip->s + mediaip->len);
  473. len = eat_token_end(cp, mediaip->s + mediaip->len) - cp;
  474. mediaip->s = cp;
  475. mediaip->len = len;
  476. if (mediaip->len == 0) {
  477. LM_ERR("no `IP[4|6]' address in `%s' field\n",line);
  478. return -1;
  479. }
  480. LM_DBG("located IP address [%.*s] in `%s' field\n",
  481. mediaip->len, mediaip->s, line);
  482. return 1;
  483. }
  484. int extract_media_attr(str *body, str *mediamedia, str *mediaport, str *mediatransport, str *mediapayload, int *is_rtp)
  485. {
  486. char *cp, *cp1;
  487. int len, i;
  488. cp1 = NULL;
  489. for (cp = body->s; (len = body->s + body->len - cp) > 0;) {
  490. cp1 = (char*)ser_memmem(cp, "m=", len, 2);
  491. if (cp1 == NULL || cp1[-1] == '\n' || cp1[-1] == '\r')
  492. break;
  493. cp = cp1 + 2;
  494. }
  495. if (cp1 == NULL) {
  496. LM_ERR("no `m=' in SDP\n");
  497. return -1;
  498. }
  499. mediaport->s = cp1 + 2; /* skip `m=' */
  500. mediaport->len = eat_line(mediaport->s, body->s + body->len -
  501. mediaport->s) - mediaport->s;
  502. trim_len(mediaport->len, mediaport->s, *mediaport);
  503. mediapayload->len = mediaport->len;
  504. mediamedia->s = mediaport->s;
  505. /* Skip media supertype and spaces after it */
  506. cp = eat_token_end(mediaport->s, mediaport->s + mediaport->len);
  507. mediaport->len -= cp - mediaport->s;
  508. mediamedia->len = mediapayload->len - mediaport->len;
  509. if (mediaport->len <= 0 || cp == mediaport->s) {
  510. LM_ERR("no port in `m='\n");
  511. return -1;
  512. }
  513. mediaport->s = cp;
  514. cp = eat_space_end(mediaport->s, mediaport->s + mediaport->len);
  515. mediaport->len -= cp - mediaport->s;
  516. if (mediaport->len <= 0 || cp == mediaport->s) {
  517. LM_ERR("no port in `m='\n");
  518. return -1;
  519. }
  520. /* Extract port */
  521. mediaport->s = cp;
  522. cp = eat_token_end(mediaport->s, mediaport->s + mediaport->len);
  523. mediatransport->len = mediaport->len - (cp - mediaport->s);
  524. if (mediatransport->len <= 0 || cp == mediaport->s) {
  525. LM_ERR("no port in `m='\n");
  526. return -1;
  527. }
  528. mediatransport->s = cp;
  529. mediaport->len = cp - mediaport->s;
  530. /* Skip spaces after port */
  531. cp = eat_space_end(mediatransport->s, mediatransport->s + mediatransport->len);
  532. mediatransport->len -= cp - mediatransport->s;
  533. if (mediatransport->len <= 0 || cp == mediatransport->s) {
  534. LM_ERR("no protocol type in `m='\n");
  535. return -1;
  536. }
  537. /* Extract protocol type */
  538. mediatransport->s = cp;
  539. cp = eat_token_end(mediatransport->s, mediatransport->s + mediatransport->len);
  540. if (cp == mediatransport->s) {
  541. LM_ERR("no protocol type in `m='\n");
  542. return -1;
  543. }
  544. mediatransport->len = cp - mediatransport->s;
  545. mediapayload->s = mediatransport->s + mediatransport->len;
  546. mediapayload->len -= mediapayload->s - mediamedia->s;
  547. cp = eat_space_end(mediapayload->s, mediapayload->s + mediapayload->len);
  548. mediapayload->len -= cp - mediapayload->s;
  549. mediapayload->s = cp;
  550. for (i = 0; sup_ptypes[i].s != NULL; i++)
  551. if (mediatransport->len == sup_ptypes[i].len &&
  552. strncasecmp(mediatransport->s, sup_ptypes[i].s, mediatransport->len) == 0) {
  553. *is_rtp = sup_ptypes[i].is_rtp;
  554. return 0;
  555. }
  556. /* Unproxyable protocol type. Generally it isn't error. */
  557. return 0;
  558. }
  559. /*
  560. * Auxiliary for some functions.
  561. * Returns pointer to first character of found line, or NULL if no such line.
  562. */
  563. char *find_sdp_line(char* p, char* plimit, char linechar)
  564. {
  565. static char linehead[3] = "x=";
  566. char *cp, *cp1;
  567. linehead[0] = linechar;
  568. /* Iterate through body */
  569. cp = p;
  570. for (;;) {
  571. if (cp >= plimit)
  572. return NULL;
  573. cp1 = ser_memmem(cp, linehead, plimit-cp, 2);
  574. if (cp1 == NULL)
  575. return NULL;
  576. /*
  577. * As it is body, we assume it has previous line and we can
  578. * lookup previous character.
  579. */
  580. if (cp1[-1] == '\n' || cp1[-1] == '\r')
  581. return cp1;
  582. /*
  583. * Having such data, but not at line beginning.
  584. * Skip them and reiterate. ser_memmem() will find next
  585. * occurence.
  586. */
  587. if (plimit - cp1 < 2)
  588. return NULL;
  589. cp = cp1 + 2;
  590. }
  591. }
  592. /* This function assumes p points to a line of requested type. */
  593. char * find_next_sdp_line(char* p, char* plimit, char linechar, char* defptr)
  594. {
  595. char *t;
  596. if (p >= plimit || plimit - p < 3)
  597. return defptr;
  598. t = find_sdp_line(p + 2, plimit, linechar);
  599. return t ? t : defptr;
  600. }
  601. /* Find first SDP line starting with linechar. Return defptr if not found */
  602. char * find_first_sdp_line(char* pstart, char* plimit, char linechar,
  603. char* defptr)
  604. {
  605. char *t;
  606. if (pstart >= plimit || plimit - pstart < 3)
  607. return defptr;
  608. t = find_sdp_line(pstart, plimit, linechar);
  609. return t ? t : defptr;
  610. }
  611. /* returns pointer to next header line, and fill hdr_f ;
  612. * if at end of header returns pointer to the last crlf (always buf)*/
  613. char* get_sdp_hdr_field(char* buf, char* end, struct hdr_field* hdr)
  614. {
  615. char* tmp;
  616. char *match;
  617. if ((*buf)=='\n' || (*buf)=='\r'){
  618. /* double crlf or lflf or crcr */
  619. hdr->type=HDR_EOH_T;
  620. return buf;
  621. }
  622. tmp=parse_hname2(buf, end, hdr);
  623. if (hdr->type==HDR_ERROR_T){
  624. LM_ERR("bad header\n");
  625. goto error;
  626. }
  627. /* eliminate leading whitespace */
  628. tmp=eat_lws_end(tmp, end);
  629. if (tmp>=end) {
  630. LM_ERR("hf empty\n");
  631. goto error;
  632. }
  633. /* just skip over it */
  634. hdr->body.s=tmp;
  635. /* find end of header */
  636. /* find lf */
  637. do{
  638. match=memchr(tmp, '\n', end-tmp);
  639. if (match){
  640. match++;
  641. }else {
  642. LM_ERR("bad body for <%s>(%d)\n", hdr->name.s, hdr->type);
  643. tmp=end;
  644. goto error;
  645. }
  646. tmp=match;
  647. }while( match<end &&( (*match==' ')||(*match=='\t') ) );
  648. tmp=match;
  649. hdr->body.len=match-hdr->body.s;
  650. /* jku: if \r covered by current length, shrink it */
  651. trim_r( hdr->body );
  652. hdr->len=tmp-hdr->name.s;
  653. return tmp;
  654. error:
  655. LM_DBG("error exit\n");
  656. hdr->type=HDR_ERROR_T;
  657. hdr->len=tmp-hdr->name.s;
  658. return tmp;
  659. }
  660. char *find_sdp_line_delimiter(char* p, char* plimit, str delimiter)
  661. {
  662. static char delimiterhead[3] = "--";
  663. char *cp, *cp1;
  664. /* Iterate through body */
  665. cp = p;
  666. for (;;) {
  667. if (cp >= plimit)
  668. return NULL;
  669. for(;;) {
  670. cp1 = ser_memmem(cp, delimiterhead, plimit-cp, 2);
  671. if (cp1 == NULL)
  672. return NULL;
  673. /* We matched '--',
  674. * now let's match the boundary delimiter */
  675. if (strncmp(cp1+2, delimiter.s, delimiter.len) == 0)
  676. break;
  677. else
  678. cp = cp1 + 2 + delimiter.len;
  679. if (cp >= plimit)
  680. return NULL;
  681. }
  682. if (cp1[-1] == '\n' || cp1[-1] == '\r')
  683. return cp1;
  684. if (plimit - cp1 < 2 + delimiter.len)
  685. return NULL;
  686. cp = cp1 + 2 + delimiter.len;
  687. }
  688. }
  689. /*
  690. * This function assumes p points to a delimiter type line.
  691. */
  692. char *find_next_sdp_line_delimiter(char* p, char* plimit, str delimiter, char* defptr)
  693. {
  694. char *t;
  695. if (p >= plimit || plimit - p < 3)
  696. return defptr;
  697. t = find_sdp_line_delimiter(p + 2, plimit, delimiter);
  698. return t ? t : defptr;
  699. }