123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815 |
- /*
- * SDP parser helpers
- *
- * Copyright (C) 2008-2009 SOMA Networks, INC.
- * Copyright (C) 2010 VoIP Embedded, Inc
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
- #include <stdlib.h>
- #include "../../ut.h"
- #include "../msg_parser.h"
- #include "../parser_f.h"
- #include "../parse_hname2.h"
- #include "sdp.h"
- static struct {
- const char *s;
- int len;
- int is_rtp;
- } sup_ptypes[] = {
- {.s = "rtp/avp", .len = 7, .is_rtp = 1},
- {.s = "udptl", .len = 5, .is_rtp = 0},
- {.s = "rtp/avpf", .len = 8, .is_rtp = 1},
- {.s = "rtp/savp", .len = 8, .is_rtp = 1},
- {.s = "rtp/savpf", .len = 9, .is_rtp = 1},
- {.s = "udp", .len = 3, .is_rtp = 0},
- {.s = "udp/bfcp", .len = 8, .is_rtp = 0},
- {.s = NULL, .len = 0, .is_rtp = 0}
- };
- #define READ(val) \
- (*(val + 0) + (*(val + 1) << 8) + (*(val + 2) << 16) + (*(val + 3) << 24))
- #define advance(_ptr,_n,_str,_error) \
- do{\
- if ((_ptr)+(_n)>(_str).s+(_str).len)\
- goto _error;\
- (_ptr) = (_ptr) + (_n);\
- }while(0);
- #define one_of_16( _x , _t ) \
- (_x==_t[0]||_x==_t[15]||_x==_t[8]||_x==_t[2]||_x==_t[3]||_x==_t[4]\
- ||_x==_t[5]||_x==_t[6]||_x==_t[7]||_x==_t[1]||_x==_t[9]||_x==_t[10]\
- ||_x==_t[11]||_x==_t[12]||_x==_t[13]||_x==_t[14])
- #define one_of_8( _x , _t ) \
- (_x==_t[0]||_x==_t[7]||_x==_t[1]||_x==_t[2]||_x==_t[3]||_x==_t[4]\
- ||_x==_t[5]||_x==_t[6])
- /*
- * ser_memmem() returns the location of the first occurrence of data
- * pattern b2 of size len2 in memory block b1 of size len1 or
- * NULL if none is found. Obtained from NetBSD.
- */
- static void * ser_memmem(const void *b1, const void *b2, size_t len1, size_t len2)
- {
- /* Initialize search pointer */
- char *sp = (char *) b1;
- /* Initialize pattern pointer */
- char *pp = (char *) b2;
- /* Initialize end of search address space pointer */
- char *eos = sp + len1 - len2;
- /* Sanity check */
- if(!(b1 && b2 && len1 && len2))
- return NULL;
- while (sp <= eos) {
- if (*sp == *pp)
- if (memcmp(sp, pp, len2) == 0)
- return sp;
- sp++;
- }
- return NULL;
- }
- /*
- * ser_memrmem() returns the location of the last occurrence of data
- * pattern b2 of size len2 in memory block b1 of size len1 or
- * NULL if none is found.
- */
- static void * ser_memrmem(const void *b1, const void *b2, size_t len1, size_t len2)
- {
- /* Initialize search pointer */
- char *sp = (char *) b1 + len1 - len2;
- /* Initialize pattern pointer */
- char *pp = (char *) b2;
- /* Initialize end of search address space pointer */
- char *eos = (char *) b1;
- /* Sanity check */
- if(!(b1 && b2 && len1 && len2))
- return NULL;
- while (sp >= eos) {
- if (*sp == *pp)
- if (memcmp(sp, pp, len2) == 0)
- return sp;
- sp--;
- }
- return NULL;
- }
- int get_mixed_part_delimiter(str* body, str *mp_delimiter)
- {
- static unsigned int boun[16] = {
- 0x6e756f62,0x4e756f62,0x6e556f62,0x4e556f62,
- 0x6e754f62,0x4e754f62,0x6e554f62,0x4e554f62,
- 0x6e756f42,0x4e756f42,0x6e556f42,0x4e556f42,
- 0x6e754f42,0x4e754f42,0x6e554f42,0x4e554f42};
- static unsigned int dary[16] = {
- 0x79726164,0x59726164,0x79526164,0x59526164,
- 0x79724164,0x59724164,0x79524164,0x59524164,
- 0x79726144,0x59726144,0x79526144,0x59526144,
- 0x79724144,0x59724144,0x79524144,0x59524144};
- str str_type;
- unsigned int x;
- char *p;
- /* LM_DBG("<%.*s>\n",body->len,body->s); */
- p = str_type.s = body->s;
- str_type.len = body->len;
- while (*p!=';' && p<(body->s+body->len))
- advance(p,1,str_type,error);
- p++;
- str_type.s = p;
- str_type.len = body->len - (p - body->s);
- /* LM_DBG("string to parse: <%.*s>\n",str_type.len,str_type.s); */
- /* skip spaces and tabs if any */
- while (*p==' ' || *p=='\t')
- advance(p,1,str_type,error);
- advance(p,4,str_type,error);
- x = READ(p-4);
- if (!one_of_16(x,boun))
- goto other;
- advance(p,4,str_type,error);
- x = READ(p-4);
- if (!one_of_16(x,dary))
- goto other;
-
- /* skip spaces and tabs if any */
- while (*p==' ' || *p=='\t')
- advance(p,1,str_type,error);
- if (*p!='=') {
- LM_ERR("parse error: no = found after boundary field\n");
- goto error;
- }
- advance(p,1,str_type,error);
- while ((*p==' ' || *p=='\t') && p+1<str_type.s+str_type.len)
- advance(p,1,str_type,error);
- mp_delimiter->len = str_type.len - (int)(p-str_type.s);
- mp_delimiter->s = p;
- /* check if the boundary value is enclosed in quotes */
- if(*p=='"' || *p=='\'') {
- if(mp_delimiter->s[mp_delimiter->len-1]==*p) {
- mp_delimiter->s = p+1;
- mp_delimiter->len -= 2;
- if(mp_delimiter->len<=0) {
- LM_ERR("invalid boundary field value\n");
- goto error;
- }
- } else {
- LM_ERR("missing closing quote in boundary field value\n");
- goto error;
- }
- }
- return 1;
- error:
- return -1;
- other:
- LM_DBG("'boundary' parsing error\n");
- return -1;
- }
- /**
- * rfc4566:
- * a=rtpmap:<payload type> <encoding name>/<clock rate> [/<encoding parameters>]
- */
- int extract_rtpmap(str *body,
- str *rtpmap_payload, str *rtpmap_encoding, str *rtpmap_clockrate, str *rtpmap_parmas)
- {
- char *cp, *cp1;
- int len;
- if (strncasecmp(body->s, "a=rtpmap:", 9) !=0) {
- /*LM_DBG("We are not pointing to an a=rtpmap: attribute =>`%.*s'\n", body->len, body->s); */
- return -1;
- }
- cp1 = body->s;
- rtpmap_payload->s = cp1 + 9; /* skip `a=rtpmap:' */
- rtpmap_payload->len = eat_line(rtpmap_payload->s, body->s + body->len -
- rtpmap_payload->s) - rtpmap_payload->s;
- trim_len(rtpmap_payload->len, rtpmap_payload->s, *rtpmap_payload);
- len = rtpmap_payload->len;
- /* */
- cp = eat_token_end(rtpmap_payload->s, rtpmap_payload->s + rtpmap_payload->len);
- rtpmap_payload->len = cp - rtpmap_payload->s;
- if (rtpmap_payload->len <= 0 || cp == rtpmap_payload->s) {
- LM_ERR("no encoding in `a=rtpmap'\n");
- return -1;
- }
- len -= rtpmap_payload->len;
- rtpmap_encoding->s = cp;
- cp = eat_space_end(rtpmap_encoding->s, rtpmap_encoding->s + len);
- len -= cp - rtpmap_encoding->s;
- if (len <= 0 || cp == rtpmap_encoding->s) {
- LM_ERR("no encoding in `a=rtpmap:'\n");
- return -1;
- }
- rtpmap_encoding->s = cp;
- cp1 = (char*)ser_memmem(cp, "/", len, 1);
- if(cp1==NULL) {
- LM_ERR("invalid encoding in `a=rtpmap' at [%.*s]\n", len, cp);
- return -1;
- }
- len -= cp1 - cp;
- rtpmap_encoding->len = cp1 - cp;
- cp = cp1+1; /* skip '/' */
- len--;
- rtpmap_clockrate->s = cp;
- cp1 = (char*)ser_memmem(cp, "/", len, 1);
- if(cp1==NULL) {
- /* no encoding parameters */
- rtpmap_clockrate->len = len;
- rtpmap_parmas->s = NULL;
- rtpmap_parmas->len = 0;
- return 0;
- }
- rtpmap_clockrate->len = cp1 - cp;
- len -= cp1 - cp;
- rtpmap_parmas->s = cp1 + 1; /* skip '/' */
- rtpmap_parmas->len = len - 1;
- return 0;
- }
- int extract_fmtp( str *body, str *fmtp_payload, str *fmtp_string )
- {
- char *cp, *cp1;
- int len;
- if (strncasecmp(body->s, "a=fmtp:", 7) !=0) {
- /*LM_DBG("We are not pointing to an a=fmtp: attribute =>`%.*s'\n", body->len, body->s); */
- return -1;
- }
- cp1 = body->s;
- fmtp_payload->s = cp1 + 7; /* skip `a=fmtp:' */
- fmtp_payload->len = eat_line(fmtp_payload->s, body->s + body->len -
- fmtp_payload->s) - fmtp_payload->s;
- trim_len(fmtp_payload->len, fmtp_payload->s, *fmtp_payload);
- len = fmtp_payload->len;
- /* */
- cp = eat_token_end(fmtp_payload->s, fmtp_payload->s + fmtp_payload->len);
- fmtp_payload->len = cp - fmtp_payload->s;
- if (fmtp_payload->len <= 0 || cp == fmtp_payload->s) {
- LM_ERR("no encoding in `a=fmtp:'\n");
- return -1;
- }
- len -= fmtp_payload->len;
- fmtp_string->s = cp;
- cp = eat_space_end(fmtp_string->s, fmtp_string->s + len);
- len -= cp - fmtp_string->s;
- if (len <= 0 || cp == fmtp_string->s) {
- LM_ERR("no encoding in `a=fmtp:'\n");
- return -1;
- }
- fmtp_string->s = cp;
- fmtp_string->len = eat_line(fmtp_string->s, body->s + body->len -
- fmtp_string->s) - fmtp_string->s;
- trim_len(fmtp_string->len, fmtp_string->s, *fmtp_string);
- return 0;
- }
- /**
- * Allocate a new ice attribute
- */
- static inline sdp_ice_attr_t *add_sdp_ice(sdp_stream_cell_t* _stream)
- {
- sdp_ice_attr_t *ice_attr;
- int len;
- len = sizeof(sdp_ice_attr_t);
- ice_attr = (sdp_ice_attr_t *)pkg_malloc(len);
- if (ice_attr == NULL) {
- LM_ERR("No memory left\n");
- return NULL;
- }
- memset( ice_attr, 0, len);
- /* Insert the new ice attribute */
- ice_attr->next = _stream->ice_attr;
- _stream->ice_attr = ice_attr;
- _stream->ice_attrs_num++;
- return ice_attr;
- }
- int extract_candidate(str *body, sdp_stream_cell_t *stream)
- {
- char *space, *start;
- int len, fl;
- sdp_ice_attr_t *ice_attr;
- if ((body->len < 12) || (strncasecmp(body->s, "a=candidate:", 12) != 0)) {
- /*LM_DBG("We are not pointing to an a=candidate: attribute =>`%.*s'\n", body->len, body->s); */
- return -1;
- }
-
- start = body->s + 12;
- len = body->len - 12;
- space = memchr(start, 32, len);
- if ((space == NULL) || (space - start + 3 > len) || !isdigit(*(space + 1))) {
- LM_ERR("no component in `a=candidate'\n");
- return -1;
- }
- fl = space - start;
-
- start = space + 1;
- len = len - (space - start + 1);
- space = memchr(start, 32, len);
- if (space == NULL) {
- LM_ERR("no component in `a=candidate'\n");
- return -1;
- }
- ice_attr = add_sdp_ice(stream);
- if (ice_attr == NULL) {
- LM_ERR("failed to add ice attribute\n");
- return -1;
- }
- /* currently only foundation and component-id are parsed */
- /* if needed, parse more */
- ice_attr->foundation.s = body->s + 12;
- ice_attr->foundation.len = fl;
- ice_attr->component_id = strtol(start, (char **)NULL, 10);
- return 0;
- }
- /* generic method for attribute extraction
- * field must has format "a=attrname:" */
- int extract_field(str *body, str *value, str field)
- {
- if (strncmp(body->s, field.s, field.len < body->len ? field.len : body->len) !=0) {
- /*LM_DBG("We are not pointing to an %.* attribute =>`%.*s'\n", field.len, field.s, body->len, body->s); */
- return -1;
- }
- value->s = body->s + field.len; /* skip `a=attrname:' */
- value->len = eat_line(value->s, body->s + body->len -
- value->s) - value->s;
- trim_len(value->len, value->s, *value);
- return 0;
- }
- int extract_ptime(str *body, str *ptime)
- {
- static const str field = str_init("a=ptime:");
- return extract_field(body, ptime, field);
- }
- int extract_accept_types(str *body, str *accept_types)
- {
- static const str field = str_init("a=accept-types:");
- return extract_field(body, accept_types, field);
- }
- int extract_accept_wrapped_types(str *body, str *accept_wrapped_types)
- {
- static const str field = str_init("a=accept-wrapped-types:");
- return extract_field(body, accept_wrapped_types, field);
- }
- int extract_max_size(str *body, str *max_size)
- {
- static const str field = str_init("a=max-size:");
- return extract_field(body, max_size, field);
- }
- int extract_path(str *body, str *path)
- {
- static const str field = str_init("a=path:");
- return extract_field(body, path, field);
- }
- int extract_rtcp(str *body, str *rtcp)
- {
- static const str field = str_init("a=rtcp:");
- return extract_field(body, rtcp, field);
- }
- int extract_sendrecv_mode(str *body, str *sendrecv_mode, int *is_on_hold)
- {
- char *cp1;
- cp1 = body->s;
- if ( !( (strncasecmp(cp1, "a=sendrecv", 10) == 0) ||
- (strncasecmp(cp1, "a=recvonly", 10) == 0))) {
- if ((strncasecmp(cp1, "a=inactive", 10) == 0) ||
- (strncasecmp(cp1, "a=sendonly", 10) == 0) ) {
- *is_on_hold = 1;
- } else {
- return -1;
- }
- }
- sendrecv_mode->s = body->s + 2; /* skip `a=' */
- sendrecv_mode->len = 8; /* we know the length and therefore we don't need to overkill */
- /*
- sendrecv_mode->len = eat_line(sendrecv_mode->s, body->s + body->len -
- sendrecv_mode->s) - sendrecv_mode->s;
- trim_len(sendrecv_mode->len, sendrecv_mode->s, *sendrecv_mode);
- */
- return 0;
- }
- int extract_bwidth(str *body, str *bwtype, str *bwwitdth)
- {
- char *cp, *cp1;
- int len;
- cp1 = NULL;
- for (cp = body->s; (len = body->s + body->len - cp) > 0;) {
- cp1 = (char*)ser_memmem(cp, "b=", len, 2);
- if (cp1 == NULL || cp1[-1] == '\n' || cp1[-1] == '\r')
- break;
- cp = cp1 + 2;
- }
- if (cp1 == NULL)
- return -1;
- bwtype->s = cp1 + 2;
- bwtype->len = eat_line(bwtype->s, body->s + body->len - bwtype->s) - bwtype->s;
- trim_len(bwtype->len, bwtype->s, *bwtype);
- cp = bwtype->s;
- len = bwtype->len;
- cp1 = (char*)ser_memmem(cp, ":", len, 1);
- len -= cp1 - cp;
- if (len <= 0) {
- LM_ERR("invalid encoding in `b=%.*s'\n", bwtype->len, bwtype->s);
- return -1;
- }
- bwtype->len = cp1 - cp;
- /* skip ':' */
- bwwitdth->s = cp1 + 1;
- bwwitdth->len = len - 1;
-
- return 0;
- }
- int extract_mediaip(str *body, str *mediaip, int *pf, char *line)
- {
- char *cp, *cp1;
- int len;
- cp1 = NULL;
- for (cp = body->s; (len = body->s + body->len - cp) > 0;) {
- cp1 = (char*)ser_memmem(cp, line, len, 2);
- if (cp1 == NULL || cp1[-1] == '\n' || cp1[-1] == '\r')
- break;
- cp = cp1 + 2;
- }
- if (cp1 == NULL)
- return -1;
- mediaip->s = cp1 + 2;
- mediaip->len = eat_line(mediaip->s, body->s + body->len - mediaip->s) - mediaip->s;
- trim_len(mediaip->len, mediaip->s, *mediaip);
- if (mediaip->len == 0) {
- LM_ERR("no [%s] line in SDP\n",line);
- return -1;
- }
- /* search reverse for IP[4|6] in c=/o= line */
- cp = (char*)ser_memrmem(mediaip->s, " IP", mediaip->len, 3);
- if (cp == NULL) {
- LM_ERR("no `IP[4|6]' in `%s' field\n",line);
- return -1;
- }
- /* safety checks:
- * - for lenght, at least 6: ' IP[4|6] x...'
- * - white space after
- */
- if(cp + 6 > mediaip->s + mediaip->len && cp[4]!=' ') {
- LM_ERR("invalid content for `%s' line\n",line);
- return -1;
- }
- switch(cp[3]) {
- case '4':
- *pf = AF_INET;
- break;
- case '6':
- *pf = AF_INET6;
- break;
- default:
- LM_ERR("invalid addrtype IPx for `%s' line\n",line);
- return -1;
- }
- cp += 5;
- /* next token is the IP address */
- cp = eat_space_end(cp, mediaip->s + mediaip->len);
- len = eat_token_end(cp, mediaip->s + mediaip->len) - cp;
- mediaip->s = cp;
- mediaip->len = len;
- if (mediaip->len == 0) {
- LM_ERR("no `IP[4|6]' address in `%s' field\n",line);
- return -1;
- }
- LM_DBG("located IP address [%.*s] in `%s' field\n",
- mediaip->len, mediaip->s, line);
- return 1;
- }
- int extract_media_attr(str *body, str *mediamedia, str *mediaport, str *mediatransport, str *mediapayload, int *is_rtp)
- {
- char *cp, *cp1;
- int len, i;
- cp1 = NULL;
- for (cp = body->s; (len = body->s + body->len - cp) > 0;) {
- cp1 = (char*)ser_memmem(cp, "m=", len, 2);
- if (cp1 == NULL || cp1[-1] == '\n' || cp1[-1] == '\r')
- break;
- cp = cp1 + 2;
- }
- if (cp1 == NULL) {
- LM_ERR("no `m=' in SDP\n");
- return -1;
- }
- mediaport->s = cp1 + 2; /* skip `m=' */
- mediaport->len = eat_line(mediaport->s, body->s + body->len -
- mediaport->s) - mediaport->s;
- trim_len(mediaport->len, mediaport->s, *mediaport);
- mediapayload->len = mediaport->len;
- mediamedia->s = mediaport->s;
- /* Skip media supertype and spaces after it */
- cp = eat_token_end(mediaport->s, mediaport->s + mediaport->len);
- mediaport->len -= cp - mediaport->s;
- mediamedia->len = mediapayload->len - mediaport->len;
- if (mediaport->len <= 0 || cp == mediaport->s) {
- LM_ERR("no port in `m='\n");
- return -1;
- }
- mediaport->s = cp;
- cp = eat_space_end(mediaport->s, mediaport->s + mediaport->len);
- mediaport->len -= cp - mediaport->s;
- if (mediaport->len <= 0 || cp == mediaport->s) {
- LM_ERR("no port in `m='\n");
- return -1;
- }
- /* Extract port */
- mediaport->s = cp;
- cp = eat_token_end(mediaport->s, mediaport->s + mediaport->len);
- mediatransport->len = mediaport->len - (cp - mediaport->s);
- if (mediatransport->len <= 0 || cp == mediaport->s) {
- LM_ERR("no port in `m='\n");
- return -1;
- }
- mediatransport->s = cp;
- mediaport->len = cp - mediaport->s;
- /* Skip spaces after port */
- cp = eat_space_end(mediatransport->s, mediatransport->s + mediatransport->len);
- mediatransport->len -= cp - mediatransport->s;
- if (mediatransport->len <= 0 || cp == mediatransport->s) {
- LM_ERR("no protocol type in `m='\n");
- return -1;
- }
- /* Extract protocol type */
- mediatransport->s = cp;
- cp = eat_token_end(mediatransport->s, mediatransport->s + mediatransport->len);
- if (cp == mediatransport->s) {
- LM_ERR("no protocol type in `m='\n");
- return -1;
- }
- mediatransport->len = cp - mediatransport->s;
- mediapayload->s = mediatransport->s + mediatransport->len;
- mediapayload->len -= mediapayload->s - mediamedia->s;
- cp = eat_space_end(mediapayload->s, mediapayload->s + mediapayload->len);
- mediapayload->len -= cp - mediapayload->s;
- mediapayload->s = cp;
- for (i = 0; sup_ptypes[i].s != NULL; i++)
- if (mediatransport->len == sup_ptypes[i].len &&
- strncasecmp(mediatransport->s, sup_ptypes[i].s, mediatransport->len) == 0) {
- *is_rtp = sup_ptypes[i].is_rtp;
- return 0;
- }
- /* Unproxyable protocol type. Generally it isn't error. */
- return 0;
- }
- /*
- * Auxiliary for some functions.
- * Returns pointer to first character of found line, or NULL if no such line.
- */
- char *find_sdp_line(char* p, char* plimit, char linechar)
- {
- static char linehead[3] = "x=";
- char *cp, *cp1;
- linehead[0] = linechar;
- /* Iterate through body */
- cp = p;
- for (;;) {
- if (cp >= plimit)
- return NULL;
- cp1 = ser_memmem(cp, linehead, plimit-cp, 2);
- if (cp1 == NULL)
- return NULL;
- /*
- * As it is body, we assume it has previous line and we can
- * lookup previous character.
- */
- if (cp1[-1] == '\n' || cp1[-1] == '\r')
- return cp1;
- /*
- * Having such data, but not at line beginning.
- * Skip them and reiterate. ser_memmem() will find next
- * occurence.
- */
- if (plimit - cp1 < 2)
- return NULL;
- cp = cp1 + 2;
- }
- }
- /* This function assumes p points to a line of requested type. */
- char * find_next_sdp_line(char* p, char* plimit, char linechar, char* defptr)
- {
- char *t;
- if (p >= plimit || plimit - p < 3)
- return defptr;
- t = find_sdp_line(p + 2, plimit, linechar);
- return t ? t : defptr;
- }
- /* Find first SDP line starting with linechar. Return defptr if not found */
- char * find_first_sdp_line(char* pstart, char* plimit, char linechar,
- char* defptr)
- {
- char *t;
- if (pstart >= plimit || plimit - pstart < 3)
- return defptr;
- t = find_sdp_line(pstart, plimit, linechar);
- return t ? t : defptr;
- }
- /* returns pointer to next header line, and fill hdr_f ;
- * if at end of header returns pointer to the last crlf (always buf)*/
- char* get_sdp_hdr_field(char* buf, char* end, struct hdr_field* hdr)
- {
- char* tmp;
- char *match;
- if ((*buf)=='\n' || (*buf)=='\r'){
- /* double crlf or lflf or crcr */
- hdr->type=HDR_EOH_T;
- return buf;
- }
- tmp=parse_hname2(buf, end, hdr);
- if (hdr->type==HDR_ERROR_T){
- LM_ERR("bad header\n");
- goto error;
- }
- /* eliminate leading whitespace */
- tmp=eat_lws_end(tmp, end);
- if (tmp>=end) {
- LM_ERR("hf empty\n");
- goto error;
- }
- /* just skip over it */
- hdr->body.s=tmp;
- /* find end of header */
- /* find lf */
- do{
- match=memchr(tmp, '\n', end-tmp);
- if (match){
- match++;
- }else {
- LM_ERR("bad body for <%s>(%d)\n", hdr->name.s, hdr->type);
- tmp=end;
- goto error;
- }
- tmp=match;
- }while( match<end &&( (*match==' ')||(*match=='\t') ) );
- tmp=match;
- hdr->body.len=match-hdr->body.s;
- /* jku: if \r covered by current length, shrink it */
- trim_r( hdr->body );
- hdr->len=tmp-hdr->name.s;
- return tmp;
- error:
- LM_DBG("error exit\n");
- hdr->type=HDR_ERROR_T;
- hdr->len=tmp-hdr->name.s;
- return tmp;
- }
- char *find_sdp_line_delimiter(char* p, char* plimit, str delimiter)
- {
- static char delimiterhead[3] = "--";
- char *cp, *cp1;
- /* Iterate through body */
- cp = p;
- for (;;) {
- if (cp >= plimit)
- return NULL;
- for(;;) {
- cp1 = ser_memmem(cp, delimiterhead, plimit-cp, 2);
- if (cp1 == NULL)
- return NULL;
- /* We matched '--',
- * now let's match the boundary delimiter */
- if (strncmp(cp1+2, delimiter.s, delimiter.len) == 0)
- break;
- else
- cp = cp1 + 2 + delimiter.len;
- if (cp >= plimit)
- return NULL;
- }
- if (cp1[-1] == '\n' || cp1[-1] == '\r')
- return cp1;
- if (plimit - cp1 < 2 + delimiter.len)
- return NULL;
- cp = cp1 + 2 + delimiter.len;
- }
- }
- /*
- * This function assumes p points to a delimiter type line.
- */
- char *find_next_sdp_line_delimiter(char* p, char* plimit, str delimiter, char* defptr)
- {
- char *t;
- if (p >= plimit || plimit - p < 3)
- return defptr;
- t = find_sdp_line_delimiter(p + 2, plimit, delimiter);
- return t ? t : defptr;
- }
|