mirror of https://github.com/sipwise/kamailio.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
699 lines
14 KiB
699 lines
14 KiB
/**
|
|
* $Id$
|
|
*
|
|
* Copyright (C) 2012 Daniel-Constantin Mierla (asipto.com)
|
|
*
|
|
* This file is part of Kamailio, a free SIP server.
|
|
*
|
|
* This file is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version
|
|
*
|
|
*
|
|
* This file is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "../../dprint.h"
|
|
#include "../../ut.h"
|
|
#include "../../trim.h"
|
|
#include "../../mem/mem.h"
|
|
|
|
#include "msrp_parser.h"
|
|
|
|
typedef struct msrp_str_id {
|
|
str sval;
|
|
int ival;
|
|
} msrp_str_id_t;
|
|
|
|
|
|
static msrp_str_id_t _msrp_rtypes[] = {
|
|
{ str_init("SEND"), MSRP_REQ_SEND },
|
|
{ str_init("AUTH"), MSRP_REQ_AUTH },
|
|
{ str_init("REPORT"), MSRP_REQ_REPORT },
|
|
{ {0, 0}, 0}
|
|
};
|
|
|
|
|
|
static msrp_str_id_t _msrp_htypes[] = {
|
|
{ str_init("From-Path"), MSRP_HDR_FROM_PATH },
|
|
{ str_init("To-Path"), MSRP_HDR_TO_PATH },
|
|
{ str_init("Use-Path"), MSRP_HDR_USE_PATH },
|
|
{ str_init("Message-ID"), MSRP_HDR_MESSAGE_ID },
|
|
{ str_init("Byte-Range"), MSRP_HDR_BYTE_RANGE },
|
|
{ str_init("Status"), MSRP_HDR_STATUS },
|
|
{ str_init("Success-Report"), MSRP_HDR_SUCCESS_REPORT },
|
|
{ str_init("Content-Type"), MSRP_HDR_CONTENT_TYPE },
|
|
{ str_init("Authorization"), MSRP_HDR_AUTH },
|
|
{ str_init("WWW-Authenticate"), MSRP_HDR_WWWAUTH },
|
|
{ str_init("Authentication-Info"), MSRP_HDR_AUTHINFO },
|
|
{ {0, 0}, 0}
|
|
};
|
|
|
|
|
|
/* */
|
|
int msrp_fline_set_rtypeid(msrp_frame_t *mf);
|
|
int msrp_hdr_set_type(msrp_hdr_t *hdr);
|
|
|
|
/**
|
|
*
|
|
*/
|
|
int msrp_parse_frame(msrp_frame_t *mf)
|
|
{
|
|
if(msrp_parse_fline(mf)<0)
|
|
{
|
|
LM_ERR("unable to parse first line\n");
|
|
return -1;
|
|
}
|
|
if(msrp_parse_headers(mf)<0)
|
|
{
|
|
LM_ERR("unable to parse first line\n");
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
int msrp_parse_fline(msrp_frame_t *mf)
|
|
{
|
|
char *p;
|
|
char *s;
|
|
|
|
mf->fline.buf.s = mf->buf.s;
|
|
s = mf->buf.s;
|
|
p = q_memchr(mf->fline.buf.s, '\n', mf->buf.len);
|
|
if(p==NULL) {
|
|
LM_ERR("no end of line\n");
|
|
return -1;
|
|
}
|
|
mf->fline.buf.len = p - mf->fline.buf.s + 1;
|
|
|
|
if(mf->fline.buf.len<10) {
|
|
LM_ERR("too short for a valid first line [%.*s] (%d)\n",
|
|
mf->fline.buf.len, mf->fline.buf.s, mf->fline.buf.len);
|
|
return -1;
|
|
}
|
|
if(memcmp(mf->fline.buf.s, "MSRP ", 5)!=0) {
|
|
LM_ERR("first line does not start with MSRP [%.*s] (%d)\n",
|
|
mf->fline.buf.len, mf->fline.buf.s, mf->fline.buf.len);
|
|
return -1;
|
|
}
|
|
mf->fline.protocol.s = mf->fline.buf.s;
|
|
mf->fline.protocol.len = 4;
|
|
s += 5;
|
|
p = q_memchr(s, ' ', mf->fline.buf.s + mf->fline.buf.len - s);
|
|
/* eat whitespaces */
|
|
while (p!=NULL && p==s) {
|
|
s++;
|
|
p = q_memchr(s, ' ', mf->fline.buf.s + mf->fline.buf.len - s);
|
|
}
|
|
if(p==NULL) {
|
|
LM_ERR("cannot find transaction id in first line [%.*s] (%d)\n",
|
|
mf->fline.buf.len, mf->fline.buf.s, mf->fline.buf.len);
|
|
return -1;
|
|
}
|
|
mf->fline.transaction.s = s;
|
|
mf->fline.transaction.len = p - s;
|
|
s = p+1;
|
|
p = q_memchr(s, ' ', mf->fline.buf.s + mf->fline.buf.len - s);
|
|
/* eat whitespaces */
|
|
while (p!=NULL && p==s) {
|
|
s++;
|
|
p = q_memchr(s, ' ', mf->fline.buf.s + mf->fline.buf.len - s);
|
|
}
|
|
if(p==NULL) {
|
|
if(s>=mf->fline.buf.s + mf->fline.buf.len - 2) {
|
|
LM_ERR("cannot method in first line [%.*s] (%d)\n",
|
|
mf->fline.buf.len, mf->fline.buf.s, mf->fline.buf.len);
|
|
return -1;
|
|
}
|
|
mf->fline.rtype.s = s;
|
|
mf->fline.rtype.len = mf->fline.buf.s + mf->fline.buf.len - s;
|
|
trim(&mf->fline.rtype);
|
|
mf->fline.msgtypeid = MSRP_REQUEST;
|
|
goto done;
|
|
}
|
|
mf->fline.rtype.s = s;
|
|
mf->fline.rtype.len = p - s;
|
|
s = p+1;
|
|
mf->fline.rtext.s = s;
|
|
mf->fline.rtext.len = mf->fline.buf.s + mf->fline.buf.len - s;
|
|
trim(&mf->fline.rtext);
|
|
mf->fline.msgtypeid = MSRP_REPLY;
|
|
|
|
done:
|
|
if(msrp_fline_set_rtypeid(mf)<0)
|
|
{
|
|
LM_ERR("cannot set rtype-id in first line [%.*s] (%d)\n",
|
|
mf->fline.buf.len, mf->fline.buf.s, mf->fline.buf.len);
|
|
return -1;
|
|
}
|
|
LM_DBG("MSRP FLine: [%d] [%.*s] [%.*s] [%.*s] [%d] [%.*s]\n",
|
|
mf->fline.msgtypeid,
|
|
mf->fline.protocol.len, mf->fline.protocol.s,
|
|
mf->fline.transaction.len, mf->fline.transaction.s,
|
|
mf->fline.rtype.len, mf->fline.rtype.s,
|
|
mf->fline.rtypeid,
|
|
mf->fline.rtext.len, mf->fline.rtext.s);
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
int msrp_fline_set_rtypeid(msrp_frame_t *mf)
|
|
{
|
|
unsigned int i;
|
|
if(mf->fline.msgtypeid==MSRP_REPLY)
|
|
{
|
|
if(str2int(&mf->fline.rtype, &i)<0)
|
|
{
|
|
LM_ERR("invalid status code [%.*s]\n",
|
|
mf->fline.rtype.len, mf->fline.rtype.s);
|
|
return -1;
|
|
}
|
|
mf->fline.rtypeid = MSRP_REQ_RPLSTART + i;
|
|
return 0;
|
|
}
|
|
if(mf->fline.msgtypeid==MSRP_REQUEST)
|
|
{
|
|
for(i=0; _msrp_rtypes[i].sval.s!=NULL; i++)
|
|
{
|
|
if(mf->fline.rtype.len==_msrp_rtypes[i].sval.len
|
|
&& strncmp(_msrp_rtypes[i].sval.s,
|
|
mf->fline.rtype.s,
|
|
_msrp_rtypes[i].sval.len)==0)
|
|
{
|
|
mf->fline.rtypeid = _msrp_rtypes[i].ival;
|
|
return 0;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
int msrp_parse_headers(msrp_frame_t *mf)
|
|
{
|
|
char *e; /* end of message */
|
|
char *l; /* end of line */
|
|
char *p; /* searched location */
|
|
char *s; /* start for search */
|
|
msrp_hdr_t *hdr;
|
|
msrp_hdr_t *last;
|
|
|
|
/* already parsed?!? */
|
|
if(mf->headers != NULL)
|
|
return 0;
|
|
|
|
last = NULL;
|
|
mf->hbody.s = mf->fline.buf.s + mf->fline.buf.len;
|
|
e = mf->buf.s + mf->buf.len;
|
|
s = mf->hbody.s;
|
|
p = s;
|
|
while(p!=NULL)
|
|
{
|
|
l = q_memchr(s, '\n', e - s);
|
|
if(l==NULL) {
|
|
LM_ERR("broken msrp frame message\n");
|
|
return -1;
|
|
}
|
|
p = q_memchr(s, ':', l - s);
|
|
if(p==NULL)
|
|
{
|
|
/* line without ':' - end of headers */
|
|
if(s[0]=='-')
|
|
{
|
|
mf->endline.len = 7 + mf->fline.transaction.len + 1 + 2;
|
|
/* check if it is end-line (i.e., no msg body) */
|
|
if((l-s+1 == mf->endline.len)
|
|
&& strncmp(s, "-------", 7)==0
|
|
&& strncmp(s+7, mf->fline.transaction.s,
|
|
mf->fline.transaction.len)==0)
|
|
{
|
|
mf->hbody.len = s - mf->hbody.s;
|
|
mf->endline.s = s;
|
|
goto ateoh;
|
|
}
|
|
mf->endline.len = 0;
|
|
LM_ERR("mismatch msrp frame message eoh endline\n");
|
|
return -1;
|
|
} else if (s[0]=='\r' || s[0]=='\n') {
|
|
mf->hbody.len = s - mf->hbody.s;
|
|
mf->mbody.s = l + 1;
|
|
goto ateoh;
|
|
}
|
|
LM_ERR("broken msrp frame message eoh\n");
|
|
return -1;
|
|
}
|
|
/* new header */
|
|
hdr = (msrp_hdr_t*)pkg_malloc(sizeof(msrp_hdr_t));
|
|
if(hdr==NULL)
|
|
{
|
|
LM_ERR("no more pkg\n");
|
|
return -1;
|
|
}
|
|
memset(hdr, 0, sizeof(msrp_hdr_t));
|
|
hdr->buf.s = s;
|
|
hdr->buf.len = l - s + 1;
|
|
hdr->name.s = s;
|
|
hdr->name.len = p - s;
|
|
hdr->body.s = p + 1;
|
|
hdr->body.len = l - p - 1;
|
|
trim(&hdr->body);
|
|
|
|
if(last==NULL)
|
|
{
|
|
mf->headers = hdr;
|
|
last = hdr;
|
|
} else {
|
|
last->next = hdr;
|
|
last = hdr;
|
|
}
|
|
msrp_hdr_set_type(hdr);
|
|
|
|
LM_DBG("MSRP Header: (%p) [%.*s] [%d] [%.*s]\n",
|
|
hdr, hdr->name.len, hdr->name.s, hdr->htype,
|
|
hdr->body.len, hdr->body.s);
|
|
s = l + 1;
|
|
}
|
|
|
|
ateoh:
|
|
if(mf->mbody.s!=NULL)
|
|
{
|
|
/* last header must be Content-Type */
|
|
|
|
/* get now body.len and endline */
|
|
mf->endline.len = 7 + mf->fline.transaction.len + 1 + 2;
|
|
mf->endline.s = e - mf->endline.len;
|
|
s = mf->endline.s;
|
|
if(s[-1]!='\n')
|
|
{
|
|
LM_ERR("broken msrp frame message body endline\n");
|
|
return -1;
|
|
}
|
|
if(strncmp(s, "-------", 7)==0
|
|
&& strncmp(s+7, mf->fline.transaction.s,
|
|
mf->fline.transaction.len)==0)
|
|
{
|
|
mf->mbody.len = s - mf->mbody.s;
|
|
LM_DBG("MSRP Body: [%d] [[\n%.*s\n]]\n",
|
|
mf->mbody.len, mf->mbody.len, mf->mbody.s);
|
|
return 0;
|
|
}
|
|
LM_ERR("mismatch msrp frame message body endline\n");
|
|
return -1;
|
|
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
int msrp_hdr_set_type(msrp_hdr_t *hdr)
|
|
{
|
|
int i;
|
|
if(hdr==NULL)
|
|
return -1;
|
|
|
|
for(i=0; _msrp_htypes[i].sval.s!=NULL; i++)
|
|
{
|
|
if(hdr->name.len==_msrp_htypes[i].sval.len
|
|
&& strncmp(_msrp_htypes[i].sval.s,
|
|
hdr->name.s,
|
|
_msrp_htypes[i].sval.len)==0)
|
|
{
|
|
hdr->htype = _msrp_htypes[i].ival;
|
|
return 0;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
void msrp_destroy_frame(msrp_frame_t *mf)
|
|
{
|
|
msrp_hdr_t *hdr;
|
|
msrp_hdr_t *nxt;
|
|
|
|
if(mf==NULL || mf->headers==NULL)
|
|
return;
|
|
|
|
hdr = mf->headers;
|
|
while(hdr!=NULL)
|
|
{
|
|
nxt = hdr->next;
|
|
if(hdr->parsed.flags&MSRP_DATA_SET)
|
|
{
|
|
if(hdr->parsed.free_fn)
|
|
{
|
|
hdr->parsed.free_fn(hdr->parsed.data);
|
|
}
|
|
}
|
|
pkg_free(hdr);
|
|
hdr = NULL;
|
|
hdr = nxt;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
void msrp_free_frame(msrp_frame_t *mf)
|
|
{
|
|
msrp_destroy_frame(mf);
|
|
pkg_free(mf);
|
|
return;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
int msrp_parse_uri(char *start, int len, msrp_uri_t *uri)
|
|
{
|
|
char *e;
|
|
char *l;
|
|
char *p;
|
|
char *s;
|
|
str *hook;
|
|
|
|
if(start==NULL || uri==NULL || len<8)
|
|
{
|
|
LM_ERR("invalid parameters\n");
|
|
return -1;
|
|
}
|
|
|
|
memset(uri, 0, sizeof(msrp_uri_t));
|
|
e = start + len;
|
|
s = start;
|
|
uri->buf.s = s;
|
|
uri->scheme.s = s;
|
|
|
|
if(strncasecmp(s, "msrp://", 7)==0) {
|
|
uri->scheme.len = 4;
|
|
uri->scheme_no = MSRP_SCHEME_MSRP;
|
|
s += 7;
|
|
} else if(strncasecmp(s, "msrps://", 8)==0) {
|
|
uri->scheme.len = 5;
|
|
uri->scheme_no = MSRP_SCHEME_MSRPS;
|
|
s += 8;
|
|
} else {
|
|
LM_ERR("invalid scheme in [%.*s]\n", len, start);
|
|
goto error;
|
|
}
|
|
|
|
p = q_memchr(s, '@', e - s);
|
|
if(p!=NULL)
|
|
{
|
|
l = q_memchr(s, ';', e - s);
|
|
if(l==NULL || p<l)
|
|
{
|
|
/* user info part */
|
|
uri->userinfo.s = s;
|
|
uri->userinfo.len = p - s;
|
|
uri->user.s = s;
|
|
l = q_memchr(uri->userinfo.s, ';', uri->userinfo.len);
|
|
if(l!=NULL)
|
|
{
|
|
uri->user.len = l - uri->user.s;
|
|
} else {
|
|
l = q_memchr(uri->userinfo.s, ':', uri->userinfo.len);
|
|
if(l!=NULL)
|
|
{
|
|
uri->user.len = l - uri->user.s;
|
|
} else {
|
|
uri->user.len = uri->userinfo.len;
|
|
}
|
|
}
|
|
}
|
|
s = p + 1;
|
|
if(s>=e) goto error;
|
|
}
|
|
hook = &uri->host;
|
|
hook->s = s;
|
|
p = q_memchr(s, ':', e - s);
|
|
if(p!=NULL)
|
|
{
|
|
hook->len = p - hook->s;
|
|
hook = &uri->port;
|
|
s = p+1;
|
|
if(s>=e) goto error;
|
|
}
|
|
hook->s = s;
|
|
p = q_memchr(s, '/', e - s);
|
|
if(p!=NULL)
|
|
{
|
|
hook->len = p - hook->s;
|
|
hook = &uri->session;
|
|
s = p+1;
|
|
if(s>=e) goto error;
|
|
}
|
|
hook->s = s;
|
|
p = q_memchr(s, ';', e - s);
|
|
if(p!=NULL)
|
|
{
|
|
hook->len = p - hook->s;
|
|
hook = &uri->params;
|
|
s = p+1;
|
|
if(s>=e) goto error;
|
|
}
|
|
hook->s = s;
|
|
hook->len = e - hook->s;
|
|
trim(hook);
|
|
|
|
if(uri->host.len<=0)
|
|
{
|
|
LM_ERR("bad host part in [%.*s] at [%ld]\n",
|
|
len, start, s - start);
|
|
goto error;
|
|
}
|
|
if(uri->port.len <= 0)
|
|
{
|
|
uri->port_no = 0;
|
|
} else {
|
|
str2sint(&uri->port, &uri->port_no);
|
|
if(uri->port_no<1 || uri->port_no > ((1<<16)-1))
|
|
{
|
|
LM_ERR("bad port part in [%.*s] at [%ld]\n",
|
|
len, start, s - start);
|
|
goto error;
|
|
}
|
|
}
|
|
if(uri->params.len > 0)
|
|
{
|
|
uri->proto.s = uri->params.s;
|
|
if(uri->params.len > 3 && strncasecmp(uri->params.s, "tcp", 3)==0)
|
|
{
|
|
uri->proto.len = 3;
|
|
uri->proto_no = MSRP_PROTO_TCP;
|
|
} else {
|
|
p = q_memchr(uri->params.s, ';', uri->params.len);
|
|
if(p!=NULL) {
|
|
uri->proto.len = p - uri->proto.s;
|
|
uri->params.len = uri->params.s + uri->params.len - p - 1;
|
|
uri->params.s = p + 1;
|
|
} else {
|
|
uri->proto.len = uri->params.len;
|
|
uri->params.s = NULL;
|
|
uri->params.len = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
LM_DBG("MSRP URI: [%.*s] [%.*s] [%.*s] [%.*s] [%.*s] [%.*s] [%.*s]\n",
|
|
uri->scheme.len, uri->scheme.s,
|
|
uri->user.len, (uri->user.s)?uri->user.s:"",
|
|
uri->host.len, uri->host.s,
|
|
uri->port.len, (uri->port.s)?uri->port.s:"",
|
|
uri->session.len, (uri->session.s)?uri->session.s:"",
|
|
uri->proto.len, (uri->proto.s)?uri->proto.s:"",
|
|
uri->params.len, (uri->params.s)?uri->params.s:"");
|
|
return 0;
|
|
|
|
error:
|
|
LM_ERR("parsing error in [%.*s] at [%ld]\n",
|
|
len, start, s - start);
|
|
memset(uri, 0, sizeof(msrp_uri_t));
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
msrp_hdr_t *msrp_get_hdr_by_id(msrp_frame_t *mf, int hdrid)
|
|
{
|
|
msrp_hdr_t *hdr;
|
|
for(hdr=mf->headers; hdr; hdr=hdr->next)
|
|
if(hdr->htype==hdrid)
|
|
return hdr;
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/**
|
|
*
|
|
*/
|
|
int msrp_explode_str(str **arr, str *in, str *del)
|
|
{
|
|
str *larr;
|
|
int i;
|
|
int j;
|
|
int k;
|
|
int n;
|
|
|
|
/* Find number of strings */
|
|
n = 0;
|
|
for(i=0; i<in->len; i++)
|
|
{
|
|
for(j=0; j<del->len; j++)
|
|
{
|
|
if(in->s[i]==del->s[j])
|
|
{
|
|
n++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
n++;
|
|
|
|
larr = pkg_malloc(n * sizeof(str));
|
|
if(larr==NULL)
|
|
{
|
|
LM_ERR("no more pkg\n");
|
|
return -1;
|
|
}
|
|
memset(larr, 0, n * sizeof(str));
|
|
|
|
k = 0;
|
|
if(n==1)
|
|
{
|
|
larr[k].s = in->s;
|
|
larr[k].len = in->len;
|
|
*arr = larr;
|
|
return n;
|
|
}
|
|
|
|
larr[k].s = in->s;
|
|
for(i=0; i<in->len; i++)
|
|
{
|
|
for(j=0; j<del->len; j++)
|
|
{
|
|
if(in->s[i]==del->s[j])
|
|
{
|
|
larr[k].len = in->s + i - larr[k].s;
|
|
k++;
|
|
if(k<n)
|
|
larr[k].s = in->s + i + 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
larr[k].len = in->s + i - larr[k].s;
|
|
|
|
*arr = larr;
|
|
|
|
return n;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
int msrp_explode_strz(str **arr, str *in, char *del)
|
|
{
|
|
str s;
|
|
|
|
s.s = del;
|
|
s.len = strlen(s.s);
|
|
return msrp_explode_str(arr, in, &s);
|
|
}
|
|
|
|
void msrp_str_array_destroy(void *data)
|
|
{
|
|
str_array_t *arr;
|
|
if(data==NULL)
|
|
return;
|
|
arr = (str_array_t*)data;
|
|
if(arr->list!=NULL)
|
|
pkg_free(arr->list);
|
|
pkg_free(arr);
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
int msrp_parse_hdr_uri_list(msrp_hdr_t *hdr)
|
|
{
|
|
str_array_t *arr;
|
|
str s;
|
|
|
|
arr = pkg_malloc(sizeof(str_array_t));
|
|
if(arr==NULL)
|
|
{
|
|
LM_ERR("no more pkg\n");
|
|
return -1;
|
|
}
|
|
memset(arr, 0, sizeof(str_array_t));
|
|
|
|
s = hdr->body;
|
|
trim(&s);
|
|
arr->size = msrp_explode_strz(&arr->list, &s, " ");
|
|
hdr->parsed.flags |= MSRP_DATA_SET;
|
|
hdr->parsed.free_fn = msrp_str_array_destroy;
|
|
hdr->parsed.data = arr;
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
int msrp_parse_hdr_from_path(msrp_frame_t *mf)
|
|
{
|
|
msrp_hdr_t *hdr;
|
|
|
|
hdr = msrp_get_hdr_by_id(mf, MSRP_HDR_FROM_PATH);
|
|
if(hdr==NULL)
|
|
return -1;
|
|
if(hdr->parsed.flags&MSRP_DATA_SET)
|
|
return 0;
|
|
return msrp_parse_hdr_uri_list(hdr);
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
int msrp_parse_hdr_to_path(msrp_frame_t *mf)
|
|
{
|
|
msrp_hdr_t *hdr;
|
|
|
|
hdr = msrp_get_hdr_by_id(mf, MSRP_HDR_TO_PATH);
|
|
if(hdr==NULL)
|
|
return -1;
|
|
if(hdr->parsed.flags&MSRP_DATA_SET)
|
|
return 0;
|
|
return msrp_parse_hdr_uri_list(hdr);
|
|
}
|
|
|