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.
1325 lines
33 KiB
1325 lines
33 KiB
/*
|
|
* lost module functions
|
|
*
|
|
* Copyright (C) 2022 Wolfgang Kampichler
|
|
* DEC112, FREQUENTIS AG
|
|
*
|
|
* This file is part of Kamailio, a free SIP server.
|
|
*
|
|
* Kamailio 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
|
|
*
|
|
* Kamailio 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
*/
|
|
|
|
/*!
|
|
* \file
|
|
* \brief Kamailio lost :: functions
|
|
* \ingroup lost
|
|
* Module: \ref lost
|
|
*/
|
|
/*****************/
|
|
|
|
#include "../../modules/http_client/curl_api.h"
|
|
|
|
#include "../../core/mod_fix.h"
|
|
#include "../../core/pvar.h"
|
|
#include "../../core/route_struct.h"
|
|
#include "../../core/ut.h"
|
|
#include "../../core/trim.h"
|
|
#include "../../core/mem/mem.h"
|
|
#include "../../core/parser/msg_parser.h"
|
|
#include "../../core/parser/parse_body.h"
|
|
#include "../../core/lvalue.h"
|
|
|
|
#include "pidf.h"
|
|
#include "utilities.h"
|
|
#include "response.h"
|
|
#include "naptr.h"
|
|
|
|
#define LOST_SUCCESS 200
|
|
#define LOST_CLIENT_ERROR 400
|
|
#define LOST_SERVER_ERROR 500
|
|
|
|
#define HELD_DEFAULT_TYPE "geodetic locationURI"
|
|
#define HELD_DEFAULT_TYPE_LEN (sizeof(HELD_DEFAULT_TYPE) - 1)
|
|
|
|
#define NAPTR_LOST_SERVICE_HTTP "LoST:http"
|
|
#define NAPTR_LOST_SERVICE_HTTPS "LoST:https"
|
|
#define NAPTR_LIS_SERVICE_HELD "LIS:HELD"
|
|
|
|
#define ACCEPT_HDR \
|
|
"Accept: " \
|
|
"application/pidf+xml,application/" \
|
|
"held+xml;q=0.5"
|
|
|
|
extern httpc_api_t httpapi;
|
|
|
|
extern int lost_geoloc_type;
|
|
extern int lost_geoloc_order;
|
|
extern int lost_verbose;
|
|
extern int held_resp_time;
|
|
extern int held_exact_type;
|
|
extern int held_post_req;
|
|
extern str held_loc_type;
|
|
|
|
char mtheld[] = "application/held+xml;charset=utf-8";
|
|
char mtlost[] = "application/lost+xml;charset=utf-8";
|
|
|
|
char uri_element[] = "uri";
|
|
char name_element[] = "displayName";
|
|
char errors_element[] = "errors";
|
|
|
|
/*
|
|
* lost_held_type(type, exact, lgth)
|
|
* verifies module params and returns valid HELD loaction type
|
|
* allocated in private memory
|
|
*/
|
|
char *lost_held_type(char *type, int *exact, int *lgth)
|
|
{
|
|
char *ret = NULL;
|
|
char *tmp = NULL;
|
|
int len = 0;
|
|
|
|
ret = (char *)pkg_malloc(1);
|
|
if(ret == NULL)
|
|
goto err;
|
|
|
|
memset(ret, 0, 1);
|
|
*lgth = 0;
|
|
|
|
if(strstr(type, HELD_TYPE_ANY)) {
|
|
len = strlen(ret) + strlen(HELD_TYPE_ANY) + 1;
|
|
tmp = pkg_realloc(ret, len);
|
|
if(tmp == NULL)
|
|
goto err;
|
|
ret = tmp;
|
|
strcat(ret, HELD_TYPE_ANY);
|
|
*exact = 0;
|
|
} else {
|
|
if(strstr(type, HELD_TYPE_CIV)) {
|
|
len = strlen(ret) + strlen(HELD_TYPE_CIV) + 1;
|
|
tmp = pkg_realloc(ret, len);
|
|
if(tmp == NULL)
|
|
goto err;
|
|
ret = tmp;
|
|
strcat(ret, HELD_TYPE_CIV);
|
|
}
|
|
if(strstr(type, HELD_TYPE_GEO)) {
|
|
if(strlen(ret) > 1) {
|
|
len = strlen(ret) + strlen(HELD_TYPE_SEP) + 1;
|
|
tmp = pkg_realloc(ret, len);
|
|
if(tmp == NULL)
|
|
goto err;
|
|
ret = tmp;
|
|
strcat(ret, HELD_TYPE_SEP);
|
|
}
|
|
len = strlen(ret) + strlen(HELD_TYPE_GEO) + 1;
|
|
tmp = pkg_realloc(ret, len);
|
|
if(tmp == NULL)
|
|
goto err;
|
|
ret = tmp;
|
|
strcat(ret, HELD_TYPE_GEO);
|
|
}
|
|
if(strstr(type, HELD_TYPE_URI)) {
|
|
if(strlen(ret) > 1) {
|
|
len = strlen(ret) + strlen(HELD_TYPE_SEP) + 1;
|
|
tmp = pkg_realloc(ret, len);
|
|
if(tmp == NULL)
|
|
goto err;
|
|
ret = tmp;
|
|
strcat(ret, HELD_TYPE_SEP);
|
|
}
|
|
len = strlen(ret) + strlen(HELD_TYPE_URI) + 1;
|
|
tmp = pkg_realloc(ret, len);
|
|
if(tmp == NULL)
|
|
goto err;
|
|
ret = tmp;
|
|
strcat(ret, HELD_TYPE_URI);
|
|
}
|
|
}
|
|
|
|
*lgth = strlen(ret);
|
|
return ret;
|
|
|
|
err:
|
|
PKG_MEM_ERROR;
|
|
/* clean up */
|
|
if(ret != NULL) {
|
|
pkg_free(ret);
|
|
ret = NULL;
|
|
}
|
|
*lgth = 0;
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* lost_function_held(msg, con, pidf, url, err, id)
|
|
* assembles and runs HELD locationRequest, parses results
|
|
*/
|
|
int lost_held_function(struct sip_msg *_m, char *_con, char *_pidf, char *_url,
|
|
char *_err, char *_id)
|
|
{
|
|
pv_spec_t *pspidf;
|
|
pv_spec_t *psurl;
|
|
pv_spec_t *pserr;
|
|
|
|
pv_value_t pvpidf;
|
|
pv_value_t pvurl;
|
|
pv_value_t pverr;
|
|
|
|
p_lost_held_t held = NULL;
|
|
|
|
xmlDocPtr doc = NULL;
|
|
xmlNodePtr root = NULL;
|
|
xmlNodePtr cur_node = NULL;
|
|
|
|
str geo = STR_NULL; /* return value geolocation uri */
|
|
str res = STR_NULL; /* return value pidf */
|
|
str err = STR_NULL; /* return value error */
|
|
|
|
str url = STR_NULL;
|
|
str did = STR_NULL;
|
|
str que = STR_NULL;
|
|
str con = STR_NULL;
|
|
str host = STR_NULL;
|
|
str name = STR_NULL;
|
|
str idhdr = STR_NULL;
|
|
str pidfurl = STR_NULL;
|
|
|
|
static str rtype = STR_STATIC_INIT(HELD_DEFAULT_TYPE);
|
|
static str sheld = STR_STATIC_INIT(NAPTR_LIS_SERVICE_HELD);
|
|
|
|
char ustr[MAX_URI_SIZE];
|
|
char istr[NI_MAXHOST];
|
|
char *ipstr = NULL;
|
|
char *lisurl = NULL;
|
|
char *heldreq = NULL;
|
|
|
|
int len = 0;
|
|
int curl = 0;
|
|
int flag = 0;
|
|
int naptr = 0;
|
|
int presence = 0;
|
|
int res_error = 0;
|
|
|
|
if(_pidf == NULL || _url == NULL || _err == NULL) {
|
|
LM_ERR("invalid parameter\n");
|
|
goto err;
|
|
}
|
|
|
|
/* module parameter */
|
|
if(held_loc_type.len > 0) {
|
|
rtype.s = held_loc_type.s;
|
|
rtype.len = held_loc_type.len;
|
|
}
|
|
/* connection from parameter */
|
|
if(_con) {
|
|
if(get_str_fparam(&con, _m, (gparam_p)_con) != 0) {
|
|
LM_ERR("cannot get connection string\n");
|
|
goto err;
|
|
}
|
|
/* check if connection exists */
|
|
if(con.s != NULL && con.len > 0) {
|
|
if(httpapi.http_connection_exists(&con) == 0) {
|
|
LM_ERR("connection: [%s] does not exist\n", con.s);
|
|
goto err;
|
|
}
|
|
}
|
|
}
|
|
/* id from parameter */
|
|
if(_id) {
|
|
if(get_str_fparam(&did, _m, (gparam_p)_id) != 0) {
|
|
LM_ERR("cannot get device id\n");
|
|
goto err;
|
|
}
|
|
if(did.len == 0) {
|
|
LM_ERR("no device id found\n");
|
|
goto err;
|
|
}
|
|
} else {
|
|
|
|
LM_DBG("parsing P-A-I header\n");
|
|
|
|
/* id from P-A-I header */
|
|
idhdr.s = lost_get_pai_header(_m, &idhdr.len);
|
|
if(idhdr.len == 0) {
|
|
LM_WARN("P-A-I header not found, trying From header ...\n");
|
|
|
|
LM_DBG("parsing From header\n");
|
|
|
|
/* id from From header */
|
|
idhdr.s = lost_get_from_header(_m, &idhdr.len);
|
|
if(idhdr.len == 0) {
|
|
LM_ERR("no device id found\n");
|
|
goto err;
|
|
}
|
|
}
|
|
did.s = idhdr.s;
|
|
did.len = idhdr.len;
|
|
}
|
|
LM_INFO("### HELD id [%.*s]\n", did.len, did.s);
|
|
/* assemble locationRequest */
|
|
held = lost_new_held(did, rtype, held_resp_time, held_exact_type);
|
|
if(held == NULL) {
|
|
LM_ERR("held object allocation failed\n");
|
|
goto err;
|
|
}
|
|
que.s = lost_held_location_request(held, &que.len);
|
|
lost_free_held(&held); /* clean up */
|
|
if(que.len == 0) {
|
|
LM_ERR("held request document error\n");
|
|
que.s = NULL;
|
|
goto err;
|
|
}
|
|
|
|
LM_DBG("held location request: [%s]\n", que.s);
|
|
|
|
/* send locationRequest to location server - HTTP POST */
|
|
if(con.s != NULL && con.len > 0) {
|
|
|
|
LM_DBG("using connection [%.*s]\n", con.len, con.s);
|
|
|
|
/* send via connection */
|
|
curl = httpapi.http_connect(_m, &con, NULL, &res, mtheld, &que);
|
|
} else {
|
|
/* we have no connection ... do a NAPTR lookup */
|
|
if(lost_parse_host(did.s, &host, &flag) > 0) {
|
|
|
|
LM_DBG("no conn. trying NATPR lookup [%.*s]\n", host.len, host.s);
|
|
|
|
/* remove '[' and ']' from string (IPv6) */
|
|
if(flag == AF_INET6) {
|
|
host.s++;
|
|
host.len = host.len - 2;
|
|
}
|
|
/* is it a name or ip ... check nameinfo (reverse lookup) */
|
|
len = 0;
|
|
ipstr = lost_copy_string(host, &len);
|
|
if(ipstr != NULL) {
|
|
name.s = &(istr[0]);
|
|
name.len = NI_MAXHOST;
|
|
if(lost_get_nameinfo(ipstr, &name, flag) > 0) {
|
|
|
|
LM_DBG("ip [%s] to name [%.*s]\n", ipstr, name.len, name.s);
|
|
|
|
/* change ip string to name */
|
|
host.s = name.s;
|
|
host.len = name.len;
|
|
} else {
|
|
|
|
/* keep string */
|
|
LM_DBG("no nameinfo for [%s]\n", ipstr);
|
|
}
|
|
pkg_free(ipstr); /* clean up */
|
|
ipstr = NULL;
|
|
} else {
|
|
LM_ERR("could not copy host info\n");
|
|
}
|
|
url.s = &(ustr[0]);
|
|
url.len = MAX_URI_SIZE;
|
|
if((naptr = lost_naptr_lookup(host, &sheld, &url)) == 0) {
|
|
LM_ERR("NAPTR failed on [%.*s]\n", host.len, host.s);
|
|
goto err;
|
|
}
|
|
} else {
|
|
LM_ERR("failed to get location service for [%.*s]\n", did.len,
|
|
did.s);
|
|
goto err;
|
|
}
|
|
|
|
LM_DBG("NATPR lookup returned [%.*s]\n", url.len, url.s);
|
|
|
|
/* curl doesn't like str */
|
|
len = 0;
|
|
lisurl = lost_copy_string(url, &len);
|
|
if(lisurl == NULL) {
|
|
LM_ERR("could not copy POST url\n");
|
|
goto err;
|
|
}
|
|
/* send to service */
|
|
curl = httpapi.http_client_query_c(
|
|
_m, lisurl, &res, que.s, mtheld, ACCEPT_HDR);
|
|
pkg_free(lisurl); /*clean up */
|
|
lisurl = NULL;
|
|
}
|
|
/* only HTTP 2xx responses are accepted */
|
|
if(curl >= 300 || curl < 100) {
|
|
if(con.s != NULL && con.len > 0) {
|
|
LM_ERR("[%.*s] failed with error: %d\n", con.len, con.s, curl);
|
|
} else {
|
|
LM_ERR("POST [%.*s] failed with error: %d\n", url.len, url.s, curl);
|
|
}
|
|
goto err;
|
|
}
|
|
if(con.s != NULL && con.len > 0) {
|
|
|
|
LM_DBG("[%.*s] returned: %d\n", con.len, con.s, curl);
|
|
|
|
} else {
|
|
|
|
LM_DBG("[%.*s] returned: %d\n", url.len, url.s, curl);
|
|
}
|
|
did.s = NULL;
|
|
did.len = 0;
|
|
/* clean up */
|
|
lost_free_string(&idhdr);
|
|
lost_free_string(&que);
|
|
/* read and parse the returned xml */
|
|
doc = xmlReadMemory(res.s, res.len, 0, NULL,
|
|
XML_PARSE_NOBLANKS | XML_PARSE_NONET | XML_PARSE_NOCDATA);
|
|
if(doc == NULL) {
|
|
LM_WARN("invalid xml document: [%.*s]\n", res.len, res.s);
|
|
doc = xmlRecoverMemory(res.s, res.len);
|
|
if(doc == NULL) {
|
|
LM_ERR("xml document recovery failed on: [%.*s]\n", res.len, res.s);
|
|
goto err;
|
|
}
|
|
|
|
LM_DBG("xml document recovered\n");
|
|
}
|
|
root = xmlDocGetRootElement(doc);
|
|
if(root == NULL) {
|
|
LM_ERR("empty xml document\n");
|
|
goto err;
|
|
}
|
|
/* check the root element ... shall be locationResponse, or error */
|
|
if(xmlStrcmp(root->name, (const xmlChar *)"locationResponse") == 0) {
|
|
|
|
LM_DBG("HELD location response [%.*s]\n", res.len, res.s);
|
|
|
|
for(cur_node = root->children; cur_node; cur_node = cur_node->next) {
|
|
if(cur_node->type == XML_ELEMENT_NODE) {
|
|
if(xmlStrcmp(cur_node->name, (const xmlChar *)"locationUriSet")
|
|
== 0) {
|
|
|
|
LM_DBG("*** node '%s' found\n", cur_node->name);
|
|
|
|
/* get the locationUri element */
|
|
geo.s = lost_get_content(
|
|
root, (char *)HELD_TYPE_URI, &geo.len);
|
|
if(geo.len == 0) {
|
|
LM_WARN("%s element not found\n", HELD_TYPE_URI);
|
|
geo.s = NULL;
|
|
} else {
|
|
geo.s = lost_trim_content(geo.s, &geo.len);
|
|
}
|
|
}
|
|
if(xmlStrcmp(cur_node->name, (const xmlChar *)"presence")
|
|
== 0) {
|
|
|
|
LM_DBG("*** node '%s' found\n", cur_node->name);
|
|
|
|
/* response contains presence node */
|
|
presence = 1;
|
|
}
|
|
}
|
|
}
|
|
/* if we do not have a presence node but a location URI */
|
|
/* dereference pidf.lo at location server via HTTP GET */
|
|
if((presence == 0) && (geo.s != NULL && geo.len > 0)) {
|
|
LM_INFO("presence node not found in HELD response, trying URI "
|
|
"...\n");
|
|
if(held_post_req == 0) {
|
|
curl = httpapi.http_client_query_c(
|
|
_m, geo.s, &pidfurl, NULL, mtheld, ACCEPT_HDR);
|
|
} else {
|
|
len = 0;
|
|
heldreq = lost_held_post_request(&len, 0, NULL);
|
|
if(heldreq == NULL) {
|
|
LM_ERR("could not create POST request\n");
|
|
goto err;
|
|
}
|
|
|
|
LM_DBG("held POST request: [%.*s]\n", len, heldreq);
|
|
|
|
curl = httpapi.http_client_query_c(
|
|
_m, geo.s, &pidfurl, heldreq, mtheld, ACCEPT_HDR);
|
|
pkg_free(heldreq); /* clean up */
|
|
heldreq = NULL;
|
|
}
|
|
/* only HTTP 2xx responses are accepted */
|
|
if(curl >= 300 || curl < 100) {
|
|
LM_ERR("GET [%.*s] failed with error: %d\n", pidfurl.len,
|
|
pidfurl.s, curl);
|
|
goto err;
|
|
}
|
|
if(pidfurl.len == 0) {
|
|
LM_WARN("HELD location request failed [%.*s]\n", geo.len,
|
|
geo.s);
|
|
} else {
|
|
|
|
LM_DBG("HELD location response [%.*s]\n", pidfurl.len,
|
|
pidfurl.s);
|
|
|
|
res.s = pidfurl.s;
|
|
res.len = pidfurl.len;
|
|
}
|
|
}
|
|
/* error received */
|
|
} else if(xmlStrcmp(root->name, (const xmlChar *)"error") == 0) {
|
|
|
|
LM_DBG("HELD error response [%.*s]\n", res.len, res.s);
|
|
|
|
/* get the error property */
|
|
err.s = lost_get_property(root, (char *)"code", &err.len);
|
|
if(err.len == 0) {
|
|
LM_ERR("error - property not found: [%.*s]\n", res.len, res.s);
|
|
goto err;
|
|
}
|
|
LM_WARN("locationRequest error response: [%.*s]\n", err.len, err.s);
|
|
} else {
|
|
LM_ERR("root element is not valid: [%.*s]\n", res.len, res.s);
|
|
goto err;
|
|
}
|
|
|
|
/* clean up */
|
|
xmlFreeDoc(doc);
|
|
doc = NULL;
|
|
|
|
/* set writeable pvars */
|
|
pvpidf.rs = res;
|
|
pvpidf.rs.s = res.s;
|
|
pvpidf.rs.len = res.len;
|
|
|
|
pvpidf.flags = PV_VAL_STR;
|
|
pspidf = (pv_spec_t *)_pidf;
|
|
pspidf->setf(_m, &pspidf->pvp, (int)EQ_T, &pvpidf);
|
|
lost_free_string(&res); /* clean up */
|
|
|
|
pvurl.rs = geo;
|
|
pvurl.rs.s = geo.s;
|
|
pvurl.rs.len = geo.len;
|
|
|
|
pvurl.flags = PV_VAL_STR;
|
|
psurl = (pv_spec_t *)_url;
|
|
psurl->setf(_m, &psurl->pvp, (int)EQ_T, &pvurl);
|
|
lost_free_string(&geo); /* clean up */
|
|
|
|
/* return error code in case of response error */
|
|
if(err.len > 0) {
|
|
res_error = 1;
|
|
}
|
|
pverr.rs = err;
|
|
pverr.rs.s = err.s;
|
|
pverr.rs.len = err.len;
|
|
|
|
pverr.flags = PV_VAL_STR;
|
|
pserr = (pv_spec_t *)_err;
|
|
pserr->setf(_m, &pserr->pvp, (int)EQ_T, &pverr);
|
|
lost_free_string(&err); /* clean up */
|
|
|
|
return (res_error > 0) ? LOST_SERVER_ERROR : LOST_SUCCESS;
|
|
|
|
err:
|
|
/* clean up pointer */
|
|
lost_free_string(&que);
|
|
lost_free_string(&idhdr);
|
|
lost_free_string(&pidfurl);
|
|
/* clean up xml */
|
|
if(doc != NULL) {
|
|
xmlFreeDoc(doc);
|
|
}
|
|
/* clean up string */
|
|
if(res.s != NULL && res.len > 0) {
|
|
lost_free_string(&res);
|
|
}
|
|
if(geo.s != NULL && geo.len > 0) {
|
|
lost_free_string(&geo);
|
|
}
|
|
if(err.s != NULL && err.len > 0) {
|
|
lost_free_string(&err);
|
|
}
|
|
|
|
return LOST_CLIENT_ERROR;
|
|
}
|
|
|
|
|
|
/*
|
|
* lost_held_dereference(msg, url, pidf, err, rtime, rtype)
|
|
* assembles and runs HELD locationRequest (POST), returns result as pidf
|
|
*/
|
|
int lost_held_dereference(struct sip_msg *_m, char *_url, char *_pidf,
|
|
char *_err, char *_rtime, char *_rtype)
|
|
{
|
|
pv_spec_t *pspidf;
|
|
pv_spec_t *pserr;
|
|
|
|
pv_value_t pvpidf;
|
|
pv_value_t pverr;
|
|
|
|
xmlDocPtr doc = NULL;
|
|
xmlNodePtr root = NULL;
|
|
|
|
str url = STR_NULL;
|
|
str rtm = STR_NULL;
|
|
str rtp = STR_NULL;
|
|
|
|
str res = STR_NULL; /* return value location response */
|
|
str err = STR_NULL; /* return value error */
|
|
|
|
char *ptr = NULL;
|
|
char *lisurl = NULL;
|
|
char *heldreq = NULL;
|
|
char *rtype = NULL;
|
|
|
|
long ltime = 0;
|
|
long rtime = 0;
|
|
|
|
int len = 0;
|
|
int curl = 0;
|
|
int exact = 0;
|
|
int ret = LOST_SUCCESS;
|
|
|
|
if(_url == NULL || _rtime == NULL || _pidf == NULL || _rtype == NULL
|
|
|| _err == NULL) {
|
|
LM_ERR("invalid parameter\n");
|
|
goto err;
|
|
}
|
|
|
|
/* dereference url from parameter */
|
|
if(_url) {
|
|
if(get_str_fparam(&url, _m, (gparam_p)_url) != 0) {
|
|
LM_ERR("cannot get dereference url\n");
|
|
goto err;
|
|
}
|
|
if(url.len == 0) {
|
|
LM_ERR("no dereference url found\n");
|
|
goto err;
|
|
}
|
|
}
|
|
|
|
/* response time from parameter */
|
|
if(_rtime) {
|
|
if(get_str_fparam(&rtm, _m, (gparam_p)_rtime) != 0) {
|
|
LM_ERR("cannot get response time\n");
|
|
goto err;
|
|
}
|
|
if(rtm.len == 0) {
|
|
/* default: rtime = 0 */
|
|
LM_WARN("no response time found\n");
|
|
} else {
|
|
ltime = strtol(rtm.s, &ptr, 10);
|
|
/* look for a number ... */
|
|
if((ltime > 0) && (strlen(ptr) == 0)) {
|
|
/* responseTime: milliseconds */
|
|
rtime = ltime;
|
|
/* or a string */
|
|
} else if((ltime == 0) && (strlen(ptr) > 0)) {
|
|
if(strncasecmp(ptr, HELD_ED, strlen(HELD_ED)) == 0) {
|
|
/* responseTime: emergencyDispatch */
|
|
rtime = -1;
|
|
} else if(strncasecmp(ptr, HELD_ER, strlen(HELD_ER)) == 0) {
|
|
/* responseTime: emergencyRouting */
|
|
rtime = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* response type from parameter */
|
|
if(_rtype) {
|
|
if(get_str_fparam(&rtp, _m, (gparam_p)_rtype) != 0) {
|
|
LM_ERR("cannot get response type\n");
|
|
goto err;
|
|
}
|
|
if(rtp.len == 0) {
|
|
LM_WARN("no response type found\n");
|
|
rtype = NULL;
|
|
} else {
|
|
len = 0;
|
|
/* response type string sanity check */
|
|
rtype = lost_held_type(rtp.s, &exact, &len);
|
|
/* default value will be used if nothing was returned */
|
|
if(rtype == NULL) {
|
|
LM_WARN("cannot normalize [%.*s]\n", rtp.len, rtp.s);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* get the HELD request body */
|
|
heldreq = lost_held_post_request(&len, rtime, rtype);
|
|
|
|
/* clean up */
|
|
if(rtype != NULL) {
|
|
pkg_free(rtype);
|
|
rtype = NULL;
|
|
}
|
|
|
|
if(heldreq == NULL) {
|
|
LM_ERR("could not create POST request\n");
|
|
goto err;
|
|
}
|
|
|
|
LM_DBG("POST request: [%.*s]\n", len, heldreq);
|
|
|
|
/* curl doesn't like str */
|
|
len = 0;
|
|
lisurl = lost_copy_string(url, &len);
|
|
if(lisurl == NULL) {
|
|
LM_ERR("could not copy POST url\n");
|
|
pkg_free(heldreq); /* clean up */
|
|
heldreq = NULL;
|
|
goto err;
|
|
}
|
|
|
|
LM_DBG("POST url: [%.*s]\n", len, lisurl);
|
|
|
|
curl = httpapi.http_client_query_c(
|
|
_m, lisurl, &res, heldreq, mtheld, ACCEPT_HDR);
|
|
pkg_free(lisurl); /* clean up */
|
|
lisurl = NULL;
|
|
pkg_free(heldreq);
|
|
heldreq = NULL;
|
|
|
|
/* only HTTP 2xx responses are accepted */
|
|
if(curl >= 300 || curl < 100) {
|
|
LM_ERR("POST [%.*s] failed with error: %d\n", url.len, url.s, curl);
|
|
goto err;
|
|
}
|
|
if(res.s != NULL && res.len > 0) {
|
|
|
|
LM_DBG("LbR pidf-lo: [%.*s]\n", res.len, res.s);
|
|
|
|
} else {
|
|
LM_ERR("dereferencing location failed\n");
|
|
goto err;
|
|
}
|
|
|
|
/* read and parse the returned xml */
|
|
doc = xmlReadMemory(res.s, res.len, 0, NULL,
|
|
XML_PARSE_NOBLANKS | XML_PARSE_NONET | XML_PARSE_NOCDATA);
|
|
if(doc == NULL) {
|
|
LM_WARN("invalid xml document: [%.*s]\n", res.len, res.s);
|
|
doc = xmlRecoverMemory(res.s, res.len);
|
|
if(doc == NULL) {
|
|
LM_ERR("xml document recovery failed on: [%.*s]\n", res.len, res.s);
|
|
goto err;
|
|
}
|
|
|
|
LM_DBG("xml document recovered\n");
|
|
}
|
|
root = xmlDocGetRootElement(doc);
|
|
if(root == NULL) {
|
|
LM_ERR("empty xml document\n");
|
|
goto err;
|
|
}
|
|
|
|
/* check root element ... shall be presence|locationResponse, or error */
|
|
if((!xmlStrcmp(root->name, (const xmlChar *)"presence"))
|
|
|| (!xmlStrcmp(root->name, (const xmlChar *)"locationResponse"))) {
|
|
|
|
LM_DBG("HELD location response [%.*s]\n", res.len, res.s);
|
|
|
|
/* check content and set response code
|
|
* + 0 nothing found: return 200
|
|
* + 1 reference found: return 201
|
|
* + 2 value found: return 202
|
|
* + 3 value and reference found: return 203
|
|
*/
|
|
ret += lost_check_HeldResponse(root);
|
|
/* error received */
|
|
} else if(xmlStrcmp(root->name, (const xmlChar *)"error") == 0) {
|
|
|
|
LM_DBG("HELD error response [%.*s]\n", res.len, res.s);
|
|
|
|
/* get the error property */
|
|
err.s = lost_get_property(root, (char *)"code", &err.len);
|
|
if(err.len == 0) {
|
|
LM_ERR("error - property not found: [%.*s]\n", res.len, res.s);
|
|
goto err;
|
|
}
|
|
LM_WARN("locationRequest error response: [%.*s]\n", err.len, err.s);
|
|
} else {
|
|
LM_ERR("root element is not valid: [%.*s]\n", res.len, res.s);
|
|
goto err;
|
|
}
|
|
|
|
/* clean up */
|
|
xmlFreeDoc(doc);
|
|
doc = NULL;
|
|
|
|
/* set writeable pvars */
|
|
pvpidf.rs = res;
|
|
pvpidf.rs.s = res.s;
|
|
pvpidf.rs.len = res.len;
|
|
|
|
pvpidf.flags = PV_VAL_STR;
|
|
pspidf = (pv_spec_t *)_pidf;
|
|
pspidf->setf(_m, &pspidf->pvp, (int)EQ_T, &pvpidf);
|
|
lost_free_string(&res); /* clean up */
|
|
|
|
/* return error code in case of response error */
|
|
if(err.len > 0) {
|
|
ret = LOST_SERVER_ERROR;
|
|
}
|
|
pverr.rs = err;
|
|
pverr.rs.s = err.s;
|
|
pverr.rs.len = err.len;
|
|
|
|
pverr.flags = PV_VAL_STR;
|
|
pserr = (pv_spec_t *)_err;
|
|
pserr->setf(_m, &pserr->pvp, (int)EQ_T, &pverr);
|
|
lost_free_string(&err); /* clean up */
|
|
|
|
return ret;
|
|
|
|
err:
|
|
/* clean up xml */
|
|
if(doc != NULL) {
|
|
xmlFreeDoc(doc);
|
|
}
|
|
/* clean up string */
|
|
if(res.s != NULL && res.len > 0) {
|
|
lost_free_string(&res);
|
|
}
|
|
if(err.s != NULL && err.len > 0) {
|
|
lost_free_string(&err);
|
|
}
|
|
|
|
return LOST_CLIENT_ERROR;
|
|
}
|
|
|
|
/*
|
|
* lost_function(msg, con, pidf, uri, name, err, pidf, urn)
|
|
* assembles and runs LOST findService request, parses results
|
|
*/
|
|
int lost_function(struct sip_msg *_m, char *_con, char *_uri, char *_name,
|
|
char *_err, char *_pidf, char *_urn)
|
|
{
|
|
pv_spec_t *psname;
|
|
pv_spec_t *psuri;
|
|
pv_spec_t *pserr;
|
|
|
|
pv_value_t pvname;
|
|
pv_value_t pvuri;
|
|
pv_value_t pverr;
|
|
|
|
p_lost_loc_t loc = NULL;
|
|
p_lost_geolist_t geolist = NULL;
|
|
p_lost_fsr_t fsrdata = NULL;
|
|
|
|
str name = STR_NULL; /* return value displayName */
|
|
str uri = STR_NULL; /* return value uri */
|
|
str err = STR_NULL; /* return value error */
|
|
|
|
str tmp = STR_NULL;
|
|
str url = STR_NULL;
|
|
str urn = STR_NULL;
|
|
str req = STR_NULL;
|
|
str con = STR_NULL;
|
|
str ret = STR_NULL;
|
|
str pidf = STR_NULL;
|
|
str oldurl = STR_NULL;
|
|
str losturl = STR_NULL;
|
|
|
|
static str shttp = STR_STATIC_INIT(NAPTR_LOST_SERVICE_HTTP);
|
|
static str shttps = STR_STATIC_INIT(NAPTR_LOST_SERVICE_HTTPS);
|
|
|
|
struct msg_start *fl;
|
|
|
|
char ustr[MAX_URI_SIZE];
|
|
char *search = NULL;
|
|
char *geoval = NULL;
|
|
char *urlrep = NULL;
|
|
char *heldreq = NULL;
|
|
|
|
int geotype = 0;
|
|
int redirect = 0;
|
|
int curl = 0;
|
|
int len = 0;
|
|
int naptr = 0;
|
|
int geoitems = 0;
|
|
int res_error = 0;
|
|
|
|
if(_con == NULL || _uri == NULL || _name == NULL || _err == NULL) {
|
|
LM_ERR("invalid parameter\n");
|
|
goto err;
|
|
}
|
|
/* connection from parameter */
|
|
if(_con) {
|
|
if(get_str_fparam(&con, _m, (gparam_p)_con) != 0) {
|
|
LM_ERR("cannot get connection string\n");
|
|
goto err;
|
|
}
|
|
/* check if connection exists */
|
|
if(con.s != NULL && con.len > 0) {
|
|
if(httpapi.http_connection_exists(&con) == 0) {
|
|
LM_WARN("connection: [%.*s] does not exist\n", con.len, con.s);
|
|
/* check if NAPTR lookup works with connection parameter */
|
|
losturl.s = &(ustr[0]);
|
|
losturl.len = MAX_URI_SIZE;
|
|
if((naptr = lost_naptr_lookup(con, &shttps, &losturl)) == 0) {
|
|
naptr = lost_naptr_lookup(con, &shttp, &losturl);
|
|
}
|
|
if(naptr == 0) {
|
|
LM_ERR("NAPTR failed on [%.*s]\n", con.len, con.s);
|
|
goto err;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/* urn from parameter */
|
|
if(_urn) {
|
|
if(get_str_fparam(&urn, _m, (gparam_p)_urn) != 0) {
|
|
LM_ERR("cannot get service urn parameter\n");
|
|
goto err;
|
|
}
|
|
}
|
|
/* urn from request line */
|
|
if(urn.len == 0) {
|
|
|
|
LM_DBG("no service urn parameter, trying request line ...\n");
|
|
|
|
fl = &(_m->first_line);
|
|
urn.len = fl->u.request.uri.len;
|
|
urn.s = fl->u.request.uri.s;
|
|
}
|
|
/* check urn scheme */
|
|
search = urn.s;
|
|
if(is_urn(search) > 0) {
|
|
LM_INFO("### LOST urn\t[%.*s]\n", urn.len, urn.s);
|
|
} else {
|
|
LM_ERR("service urn not found\n");
|
|
goto err;
|
|
}
|
|
/* pidf from parameter */
|
|
if(_pidf) {
|
|
if(get_str_fparam(&pidf, _m, (gparam_p)_pidf) != 0) {
|
|
LM_ERR("cannot get pidf parameter\n");
|
|
} else {
|
|
|
|
LM_DBG("parsing pidf parameter ...\n");
|
|
|
|
if(pidf.s != NULL && pidf.len > 0) {
|
|
|
|
LM_DBG("pidf: [%.*s]\n", pidf.len, pidf.s);
|
|
|
|
/* parse the pidf and get loc object */
|
|
loc = lost_parse_pidf(pidf, urn);
|
|
}
|
|
}
|
|
}
|
|
/* neither valid pidf parameter nor loc ... check geolocation header */
|
|
if(loc == NULL) {
|
|
|
|
/* parse Geolocation header */
|
|
|
|
LM_DBG("parsing geolocation header ...\n");
|
|
|
|
geolist = lost_get_geolocation_header(_m, &geoitems);
|
|
|
|
if(geoitems == 0) {
|
|
LM_ERR("geolocation header not found\n");
|
|
goto err;
|
|
}
|
|
|
|
LM_DBG("number of location URIs: %d\n", geoitems);
|
|
|
|
if(lost_geoloc_order == 0) {
|
|
|
|
LM_DBG("reversing location URI sequence\n");
|
|
|
|
lost_reverse_geoheader_list(&geolist);
|
|
}
|
|
switch(lost_geoloc_type) {
|
|
case ANY: /* type: 0 */
|
|
geoval = lost_get_geoheader_value(geolist, ANY, &geotype);
|
|
|
|
LM_DBG("geolocation header field (any): %s\n", geoval);
|
|
|
|
break;
|
|
case CID: /* type: 1 */
|
|
geoval = lost_get_geoheader_value(geolist, CID, &geotype);
|
|
|
|
LM_DBG("geolocation header field (LbV): %s\n", geoval);
|
|
|
|
break;
|
|
case HTTP: /* type: 2 */
|
|
geoval = lost_get_geoheader_value(geolist, HTTP, &geotype);
|
|
/* fallback to https */
|
|
if(geoval == NULL) {
|
|
LM_WARN("no valid http URL ... trying https\n");
|
|
geoval = lost_get_geoheader_value(geolist, HTTPS, &geotype);
|
|
}
|
|
|
|
LM_DBG("geolocation header field (LbR): %s\n", geoval);
|
|
|
|
break;
|
|
case HTTPS: /* type: 3 */
|
|
/* prefer https */
|
|
geoval = lost_get_geoheader_value(geolist, HTTPS, &geotype);
|
|
/* fallback to http */
|
|
if(geoval == NULL) {
|
|
LM_WARN("no valid https URL ... trying http\n");
|
|
geoval = lost_get_geoheader_value(geolist, HTTP, &geotype);
|
|
}
|
|
|
|
LM_DBG("geolocation header field (LbR): %s\n", geoval);
|
|
|
|
break;
|
|
default:
|
|
LM_WARN("unknown module parameter value\n");
|
|
geoval = lost_get_geoheader_value(geolist, UNKNOWN, &geotype);
|
|
|
|
LM_DBG("geolocation header field (any): %s\n", geoval);
|
|
|
|
break;
|
|
}
|
|
if(geoval == NULL) {
|
|
LM_ERR("invalid geolocation header\n");
|
|
goto err;
|
|
}
|
|
LM_INFO("### LOST loc\t[%s]\n", geoval);
|
|
/* clean up */
|
|
pidf.s = NULL;
|
|
pidf.len = 0;
|
|
/* use location by value */
|
|
if(geotype == CID) {
|
|
/* get body part - filter=>content-indirection */
|
|
pidf.s = get_body_part_by_filter(_m, 0, 0, geoval, NULL, &pidf.len);
|
|
if(pidf.s != NULL && pidf.len > 0) {
|
|
|
|
LM_DBG("LbV pidf-lo: [%.*s]\n", pidf.len, pidf.s);
|
|
|
|
} else {
|
|
LM_WARN("no multipart body found\n");
|
|
}
|
|
}
|
|
/* use location by reference */
|
|
if((geotype == HTTPS) || (geotype == HTTP)) {
|
|
url.s = geoval;
|
|
url.len = strlen(geoval);
|
|
/* ! dereference pidf.lo at location server - HTTP GET */
|
|
/* ! requires hack in http_client module */
|
|
/* ! functions.c => http_client_query => query_params.oneline = 0; */
|
|
if(held_post_req == 0) {
|
|
curl = httpapi.http_client_query_c(
|
|
_m, url.s, &ret, NULL, mtheld, ACCEPT_HDR);
|
|
} else {
|
|
len = 0;
|
|
heldreq = lost_held_post_request(&len, 0, NULL);
|
|
if(heldreq == NULL) {
|
|
LM_ERR("could not create POST request\n");
|
|
goto err;
|
|
}
|
|
|
|
LM_DBG("POST request: [%.*s]\n", len, heldreq);
|
|
|
|
curl = httpapi.http_client_query_c(
|
|
_m, url.s, &ret, heldreq, mtheld, ACCEPT_HDR);
|
|
pkg_free(heldreq); /* clean up */
|
|
heldreq = NULL;
|
|
}
|
|
/* only HTTP 2xx responses are accepted */
|
|
if(curl >= 300 || curl < 100) {
|
|
if(held_post_req == 0) {
|
|
LM_ERR("GET [%.*s] failed with error: %d\n", url.len, url.s,
|
|
curl);
|
|
} else {
|
|
LM_ERR("POST [%.*s] failed with error: %d\n", url.len,
|
|
url.s, curl);
|
|
}
|
|
/* clean up */
|
|
lost_free_string(&ret);
|
|
goto err;
|
|
}
|
|
url.s = NULL;
|
|
url.len = 0;
|
|
pidf.s = ret.s;
|
|
pidf.len = ret.len;
|
|
if(pidf.s != NULL && pidf.len > 0) {
|
|
|
|
LM_DBG("LbR pidf-lo: [%.*s]\n", pidf.len, pidf.s);
|
|
|
|
} else {
|
|
LM_WARN("dereferencing location failed\n");
|
|
}
|
|
}
|
|
/* clean up */
|
|
lost_free_geoheader_list(&geolist);
|
|
lost_free_string(&ret);
|
|
|
|
if(pidf.s == NULL && pidf.len == 0) {
|
|
LM_ERR("location object not found\n");
|
|
goto err;
|
|
}
|
|
/* parse the pidf and get loc object */
|
|
loc = lost_parse_pidf(pidf, urn);
|
|
}
|
|
/* pidf parsing failed ... return */
|
|
if(loc == NULL) {
|
|
LM_ERR("parsing pidf failed\n");
|
|
goto err;
|
|
}
|
|
/* assemble findService request */
|
|
req.s = lost_find_service_request(loc, &req.len);
|
|
lost_free_loc(&loc); /* clean up */
|
|
|
|
if(req.s == NULL && req.len == 0) {
|
|
LM_ERR("lost request failed\n");
|
|
goto err;
|
|
}
|
|
|
|
LM_DBG("findService request: [%.*s]\n", req.len, req.s);
|
|
|
|
/* send findService request to mapping server - HTTP POST */
|
|
if(naptr) {
|
|
/* copy url */
|
|
len = 0;
|
|
urlrep = lost_copy_string(url, &len);
|
|
if(urlrep == NULL) {
|
|
LM_ERR("could not copy POST url\n");
|
|
goto err;
|
|
}
|
|
/* send request */
|
|
curl = httpapi.http_client_query(_m, urlrep, &ret, req.s, mtlost);
|
|
pkg_free(urlrep); /* clean up */
|
|
urlrep = NULL;
|
|
} else {
|
|
curl = httpapi.http_connect(_m, &con, NULL, &ret, mtlost, &req);
|
|
}
|
|
/* only HTTP 2xx responses are accepted */
|
|
if(curl >= 300 || curl < 100) {
|
|
if(naptr) {
|
|
LM_ERR("POST [%.*s] failed with error: %d\n", url.len, url.s, curl);
|
|
} else {
|
|
LM_ERR("[%.*s] failed with error: %d\n", con.len, con.s, curl);
|
|
}
|
|
lost_free_string(&ret);
|
|
goto err;
|
|
}
|
|
|
|
if(naptr) {
|
|
LM_DBG("[%.*s] returned: %d\n", url.len, url.s, curl);
|
|
} else {
|
|
LM_DBG("[%.*s] returned: %d\n", con.len, con.s, curl);
|
|
}
|
|
|
|
if(ret.len == 0) {
|
|
LM_ERR("findService request failed\n");
|
|
goto err;
|
|
}
|
|
|
|
LM_DBG("findService response: [%.*s]\n", ret.len, ret.s);
|
|
|
|
/* at least parse one request */
|
|
redirect = 1;
|
|
while(redirect) {
|
|
fsrdata = lost_parse_findServiceResponse(ret);
|
|
if (lost_verbose == 1) {
|
|
lost_print_findServiceResponse(fsrdata);
|
|
}
|
|
switch(fsrdata->category) {
|
|
case RESPONSE:
|
|
if(fsrdata->uri != NULL) {
|
|
/* get the first sips uri element ... */
|
|
if(lost_search_response_list(&fsrdata->uri, &tmp.s, SIPS_S) > 0) {
|
|
tmp.len = strlen(tmp.s);
|
|
/* or the first sip uri element ... */
|
|
} else if(lost_search_response_list(&fsrdata->uri, &tmp.s, SIP_S) > 0) {
|
|
tmp.len = strlen(tmp.s);
|
|
/* or return error if nothing found */
|
|
} else {
|
|
LM_ERR("sip/sips uri not found: [%.*s]\n", ret.len, ret.s);
|
|
goto err;
|
|
}
|
|
/* copy uri string */
|
|
if(pkg_str_dup(&uri, &tmp) < 0) {
|
|
LM_ERR("could not copy: [%.*s]\n", tmp.len, tmp.s);
|
|
goto err;
|
|
}
|
|
} else {
|
|
LM_ERR("uri element not found: [%.*s]\n", ret.len, ret.s);
|
|
goto err;
|
|
}
|
|
if(fsrdata->mapping != NULL) {
|
|
/* get the displayName element */
|
|
if((tmp.s = fsrdata->mapping->name->text) != NULL) {
|
|
tmp.len = strlen(fsrdata->mapping->name->text);
|
|
if(pkg_str_dup(&name, &tmp) < 0) {
|
|
LM_ERR("could not copy: [%.*s]\n", tmp.len, tmp.s);
|
|
goto err;
|
|
}
|
|
}
|
|
} else {
|
|
LM_ERR("name not found: [%.*s]\n", ret.len, ret.s);
|
|
goto err;
|
|
}
|
|
/* we are done */
|
|
redirect = 0;
|
|
break;
|
|
case ERROR:
|
|
/* get the errors element */
|
|
if(fsrdata->errors != NULL) {
|
|
if((tmp.s = fsrdata->errors->issue->type) != NULL) {
|
|
tmp.len = strlen(fsrdata->errors->issue->type);
|
|
if(pkg_str_dup(&err, &tmp) < 0) {
|
|
LM_ERR("could not copy: [%.*s]\n", tmp.len, tmp.s);
|
|
goto err;
|
|
}
|
|
}
|
|
/* clean up */
|
|
tmp.s = NULL;
|
|
tmp.len = 0;
|
|
} else {
|
|
LM_ERR("errors not found: [%.*s]\n", ret.len, ret.s);
|
|
goto err;
|
|
}
|
|
/* we are done */
|
|
redirect = 0;
|
|
break;
|
|
case REDIRECT:
|
|
/* get the target element */
|
|
if(fsrdata->redirect != NULL) {
|
|
if((tmp.s = fsrdata->redirect->target) != NULL) {
|
|
tmp.len = strlen(fsrdata->redirect->target);
|
|
url.s = &(ustr[0]);
|
|
url.len = MAX_URI_SIZE;
|
|
/* get url string via NAPTR */
|
|
naptr = lost_naptr_lookup(tmp, &shttps, &url);
|
|
if(naptr == 0) {
|
|
/* fallback to http */
|
|
naptr = lost_naptr_lookup(tmp, &shttp, &url);
|
|
}
|
|
/* nothing found ... return */
|
|
if(naptr == 0) {
|
|
LM_ERR("NAPTR failed on [%.*s]\n", tmp.len, tmp.s);
|
|
goto err;
|
|
}
|
|
/* clean up */
|
|
tmp.s = NULL;
|
|
tmp.len = 0;
|
|
/* check loop */
|
|
if(oldurl.s != NULL && oldurl.len > 0) {
|
|
if(str_strcasecmp(&url, &oldurl) == 0) {
|
|
LM_ERR("loop detected: "
|
|
"[%.*s]<-->[%.*s]\n",
|
|
oldurl.len, oldurl.s, url.len, url.s);
|
|
goto err;
|
|
}
|
|
}
|
|
/* remember the redirect target */
|
|
if(pkg_str_dup(&oldurl, &url) < 0) {
|
|
LM_ERR("could not copy: [%.*s]\n", url.len, url.s);
|
|
goto err;
|
|
}
|
|
/* clean up */
|
|
lost_free_findServiceResponse(&fsrdata);
|
|
lost_free_string(&ret);
|
|
/* copy url */
|
|
len = 0;
|
|
urlrep = lost_copy_string(url, &len);
|
|
if(urlrep == NULL) {
|
|
LM_ERR("could not copy POST url\n");
|
|
goto err;
|
|
}
|
|
/* send request */
|
|
curl = httpapi.http_client_query(
|
|
_m, urlrep, &ret, req.s, mtlost);
|
|
pkg_free(urlrep); /*clean up */
|
|
urlrep = NULL;
|
|
/* only HTTP 2xx responses are accepted */
|
|
if(curl >= 300 || curl < 100) {
|
|
LM_ERR("POST [%.*s] failed with error: %d\n",
|
|
url.len, url.s, curl);
|
|
goto err;
|
|
}
|
|
/* reset url string */
|
|
url.s = NULL;
|
|
url.len = 0;
|
|
/* once more ... we got a redirect */
|
|
redirect = 1;
|
|
}
|
|
} else {
|
|
LM_ERR("redirect element not found: [%.*s]\n", ret.len,
|
|
ret.s);
|
|
goto err;
|
|
}
|
|
break;
|
|
case OTHER:
|
|
default:
|
|
LM_ERR("pidf is not valid: [%.*s]\n", ret.len, ret.s);
|
|
goto err;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* clean up */
|
|
lost_free_findServiceResponse(&fsrdata);
|
|
lost_free_string(&ret);
|
|
lost_free_string(&req);
|
|
lost_free_string(&oldurl);
|
|
|
|
/* set writable pvars */
|
|
pvname.rs = name;
|
|
pvname.rs.s = name.s;
|
|
pvname.rs.len = name.len;
|
|
|
|
pvname.flags = PV_VAL_STR;
|
|
psname = (pv_spec_t *)_name;
|
|
psname->setf(_m, &psname->pvp, (int)EQ_T, &pvname);
|
|
lost_free_string(&name); /* clean up */
|
|
|
|
pvuri.rs = uri;
|
|
pvuri.rs.s = uri.s;
|
|
pvuri.rs.len = uri.len;
|
|
|
|
pvuri.flags = PV_VAL_STR;
|
|
psuri = (pv_spec_t *)_uri;
|
|
psuri->setf(_m, &psuri->pvp, (int)EQ_T, &pvuri);
|
|
lost_free_string(&uri); /* clean up */
|
|
|
|
/* return error code in case of response error */
|
|
if(err.len > 0) {
|
|
res_error = 1;
|
|
}
|
|
pverr.rs = err;
|
|
pverr.rs.s = err.s;
|
|
pverr.rs.len = err.len;
|
|
|
|
pverr.flags = PV_VAL_STR;
|
|
pserr = (pv_spec_t *)_err;
|
|
pserr->setf(_m, &pserr->pvp, (int)EQ_T, &pverr);
|
|
lost_free_string(&err); /* clean up */
|
|
|
|
return (res_error > 0) ? LOST_SERVER_ERROR : LOST_SUCCESS;
|
|
|
|
err:
|
|
/* clean up */
|
|
lost_free_findServiceResponse(&fsrdata);
|
|
lost_free_geoheader_list(&geolist);
|
|
lost_free_loc(&loc);
|
|
/* clean up string */
|
|
if(oldurl.s != NULL && oldurl.len > 0) {
|
|
lost_free_string(&oldurl);
|
|
}
|
|
if(ret.s != NULL && ret.len > 0) {
|
|
lost_free_string(&ret);
|
|
}
|
|
if(req.s != NULL && req.len > 0) {
|
|
lost_free_string(&req);
|
|
}
|
|
if(name.s != NULL && name.len > 0) {
|
|
lost_free_string(&name);
|
|
}
|
|
if(uri.s != NULL && uri.len > 0) {
|
|
lost_free_string(&uri);
|
|
}
|
|
if(err.s != NULL && err.len > 0) {
|
|
lost_free_string(&err);
|
|
}
|
|
|
|
return LOST_CLIENT_ERROR;
|
|
}
|