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.
kamailio/modules/msrp/msrp_vars.c

463 lines
12 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 "../../trim.h"
#include "../../ut.h"
#include "../../pvapi.h"
#include "msrp_parser.h"
#include "msrp_vars.h"
/**
*
*/
int pv_parse_msrp_name(pv_spec_t *sp, str *in)
{
if(sp==NULL || in==NULL || in->len<=0)
return -1;
switch(in->len)
{
case 3:
if(strncmp(in->s, "buf", 3)==0)
sp->pvp.pvn.u.isname.name.n = 1;
else goto error;
break;
case 4:
if(strncmp(in->s, "body", 4)==0)
sp->pvp.pvn.u.isname.name.n = 2;
else if(strncmp(in->s, "code", 4)==0)
sp->pvp.pvn.u.isname.name.n = 3;
else if(strncmp(in->s, "hdrs", 4)==0)
sp->pvp.pvn.u.isname.name.n = 4;
else goto error;
break;
case 5:
if(strncmp(in->s, "msgid", 5)==0)
sp->pvp.pvn.u.isname.name.n = 5;
else if(strncmp(in->s, "conid", 5)==0)
sp->pvp.pvn.u.isname.name.n = 21;
else goto error;
case 6:
if(strncmp(in->s, "method", 6)==0)
sp->pvp.pvn.u.isname.name.n = 6;
else if(strncmp(in->s, "buflen", 6)==0)
sp->pvp.pvn.u.isname.name.n = 7;
else if(strncmp(in->s, "sessid", 6)==0)
sp->pvp.pvn.u.isname.name.n = 8;
else if(strncmp(in->s, "reason", 6)==0)
sp->pvp.pvn.u.isname.name.n = 9;
else if(strncmp(in->s, "crthop", 6)==0)
sp->pvp.pvn.u.isname.name.n = 12;
else goto error;
break;
case 7:
if(strncmp(in->s, "bodylen", 7)==0)
sp->pvp.pvn.u.isname.name.n = 10;
else if(strncmp(in->s, "transid", 7)==0)
sp->pvp.pvn.u.isname.name.n = 11;
else if(strncmp(in->s, "prevhop", 7)==0)
sp->pvp.pvn.u.isname.name.n = 13;
else if(strncmp(in->s, "nexthop", 7)==0)
sp->pvp.pvn.u.isname.name.n = 14;
else if(strncmp(in->s, "lasthop", 7)==0)
sp->pvp.pvn.u.isname.name.n = 15;
else if(strncmp(in->s, "srcaddr", 7)==0)
sp->pvp.pvn.u.isname.name.n = 19;
else if(strncmp(in->s, "srcsock", 7)==0)
sp->pvp.pvn.u.isname.name.n = 20;
else goto error;
break;
case 8:
if(strncmp(in->s, "firsthop", 8)==0)
sp->pvp.pvn.u.isname.name.n = 16;
else if(strncmp(in->s, "prevhops", 8)==0)
sp->pvp.pvn.u.isname.name.n = 17;
else if(strncmp(in->s, "nexthops", 8)==0)
sp->pvp.pvn.u.isname.name.n = 18;
else goto error;
break;
default:
/* max is 21 */
goto error;
}
sp->pvp.pvn.type = PV_NAME_INTSTR;
sp->pvp.pvn.u.isname.type = 0;
return 0;
error:
LM_ERR("unknown PV msrp name %.*s\n", in->len, in->s);
return -1;
}
/**
*
*/
int pv_get_msrp(sip_msg_t *msg, pv_param_t *param, pv_value_t *res)
{
msrp_frame_t *mf;
msrp_hdr_t *hdr;
str_array_t *sar;
msrp_uri_t uri;
str s;
char *p;
mf = msrp_get_current_frame();
if(mf==NULL || param==NULL)
return -1;
sar = NULL;
hdr = NULL;
switch(param->pvn.u.isname.name.n)
{
case 1:
s.s = mf->buf.s;
s.len = mf->buf.len;
return pv_get_strval(msg, param, res, &s);
case 2:
if(mf->mbody.s==NULL)
return pv_get_null(msg, param, res);
s.s = mf->mbody.s;
s.len = mf->mbody.len;
return pv_get_strval(msg, param, res, &s);
case 3:
if(mf->fline.msgtypeid==MSRP_REQUEST)
return pv_get_null(msg, param, res);
return pv_get_intstrval(msg, param, res, mf->fline.rtypeid,
&mf->fline.rtype);
case 4:
if(mf->hbody.s==NULL)
return pv_get_null(msg, param, res);
s.s = mf->hbody.s;
s.len = mf->hbody.len;
return pv_get_strval(msg, param, res, &s);
case 5:
hdr = msrp_get_hdr_by_id(mf, MSRP_HDR_MESSAGE_ID);
if(hdr==NULL)
return pv_get_null(msg, param, res);
s.s = hdr->body.s;
s.len = hdr->body.len;
trim(&s);
return pv_get_strval(msg, param, res, &s);
case 6:
if(mf->fline.msgtypeid==MSRP_REPLY)
return pv_get_null(msg, param, res);
return pv_get_strintval(msg, param, res, &mf->fline.rtype,
mf->fline.rtypeid);
case 7:
return pv_get_uintval(msg, param, res, mf->buf.len);
case 8:
if(msrp_parse_hdr_to_path(mf)<0)
return pv_get_null(msg, param, res);
hdr = msrp_get_hdr_by_id(mf, MSRP_HDR_TO_PATH);
if(hdr==NULL)
return pv_get_null(msg, param, res);
sar = (str_array_t*)hdr->parsed.data;
s = sar->list[0];
trim(&s);
if(msrp_parse_uri(s.s, s.len, &uri)<0 || uri.session.len<=0)
return pv_get_null(msg, param, res);
s = uri.session;
trim(&s);
return pv_get_strval(msg, param, res, &s);
case 9:
if(mf->fline.msgtypeid==MSRP_REQUEST || mf->fline.rtext.s==NULL)
return pv_get_null(msg, param, res);
return pv_get_strval(msg, param, res, &mf->fline.rtext);
case 10:
return pv_get_uintval(msg, param, res, mf->mbody.len);
case 11:
s = mf->fline.transaction;
trim(&s);
return pv_get_strval(msg, param, res, &s);
case 12:
if(msrp_parse_hdr_to_path(mf)<0)
return pv_get_null(msg, param, res);
hdr = msrp_get_hdr_by_id(mf, MSRP_HDR_TO_PATH);
if(hdr==NULL)
return pv_get_null(msg, param, res);
sar = (str_array_t*)hdr->parsed.data;
s = sar->list[0];
trim(&s);
return pv_get_strval(msg, param, res, &s);
case 13:
if(msrp_parse_hdr_from_path(mf)<0)
return pv_get_null(msg, param, res);
hdr = msrp_get_hdr_by_id(mf, MSRP_HDR_FROM_PATH);
if(hdr==NULL)
return pv_get_null(msg, param, res);
sar = (str_array_t*)hdr->parsed.data;
s = sar->list[0];
trim(&s);
return pv_get_strval(msg, param, res, &s);
case 14:
if(msrp_parse_hdr_to_path(mf)<0)
return pv_get_null(msg, param, res);
hdr = msrp_get_hdr_by_id(mf, MSRP_HDR_TO_PATH);
if(hdr==NULL)
return pv_get_null(msg, param, res);
sar = (str_array_t*)hdr->parsed.data;
if(sar->size<2)
return pv_get_null(msg, param, res);
s = sar->list[1];
trim(&s);
return pv_get_strval(msg, param, res, &s);
case 15:
if(msrp_parse_hdr_to_path(mf)<0)
return pv_get_null(msg, param, res);
hdr = msrp_get_hdr_by_id(mf, MSRP_HDR_TO_PATH);
if(hdr==NULL)
return pv_get_null(msg, param, res);
sar = (str_array_t*)hdr->parsed.data;
s = sar->list[sar->size-1];
trim(&s);
return pv_get_strval(msg, param, res, &s);
case 16:
if(msrp_parse_hdr_from_path(mf)<0)
return pv_get_null(msg, param, res);
hdr = msrp_get_hdr_by_id(mf, MSRP_HDR_FROM_PATH);
if(hdr==NULL)
return pv_get_null(msg, param, res);
sar = (str_array_t*)hdr->parsed.data;
s = sar->list[sar->size-1];
trim(&s);
return pv_get_strval(msg, param, res, &s);
case 17:
if(msrp_parse_hdr_from_path(mf)<0)
return pv_get_null(msg, param, res);
hdr = msrp_get_hdr_by_id(mf, MSRP_HDR_FROM_PATH);
if(hdr==NULL)
return pv_get_null(msg, param, res);
sar = (str_array_t*)hdr->parsed.data;
return pv_get_uintval(msg, param, res, sar->size);
case 18:
if(msrp_parse_hdr_from_path(mf)<0)
return pv_get_null(msg, param, res);
hdr = msrp_get_hdr_by_id(mf, MSRP_HDR_TO_PATH);
if(hdr==NULL)
return pv_get_null(msg, param, res);
sar = (str_array_t*)hdr->parsed.data;
return pv_get_uintval(msg, param, res, sar->size-1);
case 19:
if(pv_get_buffer_size()<100)
return pv_get_null(msg, param, res);
s.s = pv_get_buffer();
p = s.s;
if(mf->tcpinfo->rcv->proto==PROTO_TLS)
{
memcpy(p, "msrps://", 8);
p+=8;
} else {
memcpy(p, "msrp://", 7);
p+=7;
}
strcpy(p, ip_addr2a(&mf->tcpinfo->rcv->src_ip));
strcat(p, ":");
strcat(p, int2str(mf->tcpinfo->rcv->src_port, NULL));
s.len = strlen(s.s);
return pv_get_strval(msg, param, res, &s);
case 20:
return pv_get_strval(msg, param, res,
&mf->tcpinfo->rcv->bind_address->sock_str);
case 21:
if(mf->tcpinfo->con==NULL)
return pv_get_null(msg, param, res);
return pv_get_sintval(msg, param, res, mf->tcpinfo->con->id);
default:
return pv_get_null(msg, param, res);
}
return 0;
}
/**
*
*/
int pv_set_msrp(sip_msg_t *msg, pv_param_t *param, int op,
pv_value_t *val)
{
return 0;
}
enum _tr_msrp_type { TR_MSRP_NONE=0, TR_MSRPURI };
enum _tr_msrpuri_subtype {
TR_MSRPURI_NONE=0, TR_MSRPURI_USER, TR_MSRPURI_HOST, TR_MSRPURI_PORT,
TR_MSRPURI_SESSION, TR_MSRPURI_PROTO, TR_MSRPURI_USERINFO,
TR_MSRPURI_PARAMS, TR_MSRPURI_SCHEME};
static str _tr_empty = { "", 0 };
static str _tr_msrpuri = {0, 0};
static msrp_uri_t _tr_parsed_msrpuri;
/**
*
*/
int tr_msrp_eval_msrpuri(struct sip_msg *msg, tr_param_t *tp, int subtype,
pv_value_t *val)
{
if(val==NULL || (!(val->flags&PV_VAL_STR)) || val->rs.len<=0)
return -1;
if(_tr_msrpuri.len==0 || _tr_msrpuri.len!=val->rs.len ||
strncmp(_tr_msrpuri.s, val->rs.s, val->rs.len)!=0)
{
if(val->rs.len>_tr_msrpuri.len)
{
if(_tr_msrpuri.s) pkg_free(_tr_msrpuri.s);
_tr_msrpuri.s = (char*)pkg_malloc((val->rs.len+1)*sizeof(char));
if(_tr_msrpuri.s==NULL)
{
LM_ERR("no more private memory\n");
memset(&_tr_msrpuri, 0, sizeof(str));
memset(&_tr_parsed_msrpuri, 0, sizeof(msrp_uri_t));
return -1;
}
}
_tr_msrpuri.len = val->rs.len;
memcpy(_tr_msrpuri.s, val->rs.s, val->rs.len);
_tr_msrpuri.s[_tr_msrpuri.len] = '\0';
/* reset old values */
memset(&_tr_parsed_msrpuri, 0, sizeof(msrp_uri_t));
/* parse uri */
if(msrp_parse_uri(_tr_msrpuri.s, _tr_msrpuri.len,
&_tr_parsed_msrpuri)!=0)
{
LM_ERR("invalid uri [%.*s]\n", val->rs.len,
val->rs.s);
pkg_free(_tr_msrpuri.s);
memset(&_tr_msrpuri, 0, sizeof(str));
memset(&_tr_parsed_msrpuri, 0, sizeof(msrp_uri_t));
return -1;
}
}
memset(val, 0, sizeof(pv_value_t));
val->flags = PV_VAL_STR;
switch(subtype)
{
case TR_MSRPURI_USER:
val->rs = (_tr_parsed_msrpuri.user.s)?_tr_parsed_msrpuri.user:_tr_empty;
break;
case TR_MSRPURI_USERINFO:
val->rs = (_tr_parsed_msrpuri.userinfo.s)?_tr_parsed_msrpuri.userinfo:_tr_empty;
break;
case TR_MSRPURI_HOST:
val->rs = (_tr_parsed_msrpuri.host.s)?_tr_parsed_msrpuri.host:_tr_empty;
break;
case TR_MSRPURI_PORT:
val->rs = (_tr_parsed_msrpuri.port.s)?_tr_parsed_msrpuri.port:_tr_empty;
break;
case TR_MSRPURI_SESSION:
val->rs = (_tr_parsed_msrpuri.session.s)?_tr_parsed_msrpuri.session:_tr_empty;
break;
case TR_MSRPURI_PROTO:
val->rs = (_tr_parsed_msrpuri.proto.s)?_tr_parsed_msrpuri.proto:_tr_empty;
break;
case TR_MSRPURI_PARAMS:
val->rs = (_tr_parsed_msrpuri.params.s)?_tr_parsed_msrpuri.params:_tr_empty;
break;
case TR_MSRPURI_SCHEME:
val->rs = (_tr_parsed_msrpuri.scheme.s)?_tr_parsed_msrpuri.scheme:_tr_empty;
break;
default:
LM_ERR("unknown subtype %d\n",
subtype);
return -1;
}
return 0;
}
/**
*
*/
char* tr_parse_msrpuri(str* in, trans_t *t)
{
str name;
char *p;
if(in==NULL || t==NULL)
return NULL;
p = in->s;
name.s = in->s;
t->type = TR_MSRPURI;
t->trf = tr_msrp_eval_msrpuri;
/* find next token */
while(is_in_str(p, in) && *p!=TR_PARAM_MARKER && *p!=TR_RBRACKET) p++;
if(*p=='\0')
{
LM_ERR("invalid transformation: %.*s\n",
in->len, in->s);
goto error;
}
name.len = p - name.s;
trim(&name);
if(name.len==4 && strncasecmp(name.s, "user", 4)==0)
{
t->subtype = TR_MSRPURI_USER;
goto done;
} else if(name.len==4 && strncasecmp(name.s, "host", 4)==0) {
t->subtype = TR_MSRPURI_HOST;
goto done;
} else if(name.len==4 && strncasecmp(name.s, "port", 4)==0) {
t->subtype = TR_MSRPURI_PORT;
goto done;
} else if(name.len==7 && strncasecmp(name.s, "session", 7)==0) {
t->subtype = TR_MSRPURI_SESSION;
goto done;
} else if(name.len==5 && strncasecmp(name.s, "proto", 5)==0) {
t->subtype = TR_MSRPURI_PROTO;
goto done;
} else if(name.len==6 && strncasecmp(name.s, "scheme", 6)==0) {
t->subtype = TR_MSRPURI_SCHEME;
goto done;
} else if(name.len==6 && strncasecmp(name.s, "params", 6)==0) {
t->subtype = TR_MSRPURI_PARAMS;
goto done;
} else if(name.len==8 && strncasecmp(name.s, "userinfo", 8)==0) {
t->subtype = TR_MSRPURI_USERINFO;
goto done;
}
LM_ERR("unknown transformation: %.*s/%.*s/%d!\n", in->len, in->s,
name.len, name.s, name.len);
error:
return NULL;
done:
t->name = name;
return p;
}