ussd_proxy: properly set To and From SIP headers

This commit is contained in:
Sergey Kostanbaev
2015-10-26 13:35:48 +03:00
committed by Ivan Kluchnikov
parent be9419881c
commit 70e6f2ec74

View File

@@ -7,6 +7,7 @@
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <assert.h> #include <assert.h>
#include <unistd.h>
typedef struct context_s context_t; typedef struct context_s context_t;
#define NTA_OUTGOING_MAGIC_T context_t #define NTA_OUTGOING_MAGIC_T context_t
@@ -25,6 +26,7 @@ typedef struct operation operation_t;
#include <sofia-sip/sip_util.h> #include <sofia-sip/sip_util.h>
#include <sofia-sip/auth_client.h> #include <sofia-sip/auth_client.h>
#include <sofia-sip/tport_tag.h> #include <sofia-sip/tport_tag.h>
#include <sofia-sip/url.h>
#include <osmocom/abis/ipa.h> #include <osmocom/abis/ipa.h>
#include <osmocom/core/application.h> #include <osmocom/core/application.h>
@@ -183,7 +185,8 @@ struct context_s {
nua_t *nua; nua_t *nua;
const char *to_str; url_t *to_url;
url_t *self_url;
/* Array of isup connections */ /* Array of isup connections */
struct isup_connection isup[1]; struct isup_connection isup[1];
@@ -299,6 +302,18 @@ static int ussd_parse_xml(const char *xml,
return 1; return 1;
} }
static void operetion_destroy(operation_t* op)
{
/* release operation handle */
nua_handle_destroy(op->handle);
op->handle = NULL;
/* FIXME replace by list removal */
op->ctx->operations = NULL;
/* release operation context information */
su_free(op->ctx->home, op);
}
void proxy_r_invite(int status, void proxy_r_invite(int status,
char const *phrase, char const *phrase,
nua_t *nua, nua_t *nua,
@@ -308,10 +323,14 @@ void proxy_r_invite(int status,
sip_t const *sip, sip_t const *sip,
tagi_t tags[]) tagi_t tags[])
{ {
fprintf(stderr, "*** Got reply %d for INVITE\n", status);
if (status == 200) { if (status == 200) {
nua_ack(nh, TAG_END()); nua_ack(nh, TAG_END());
} else { } else {
printf("response to INVITE: %03d %s\n", status, phrase); printf("response to INVITE: %03d %s\n", status, phrase);
ussd_send_data(hmagic, 1, "en", 2, NULL, 0);
operetion_destroy(hmagic);
} }
} }
@@ -356,13 +375,7 @@ void proxy_r_bye(int status,
} }
} }
/* release operation handle */ operetion_destroy(hmagic);
nua_handle_destroy(hmagic->handle);
hmagic->handle = NULL;
/* release operation context information */
su_free(hmagic->ctx->home, hmagic);
} }
int ussd_create_xml_ascii(char *content, size_t max_len, const char* language, const char* msg, int msg_len) int ussd_create_xml_ascii(char *content, size_t max_len, const char* language, const char* msg, int msg_len)
@@ -382,14 +395,22 @@ int ussd_create_xml_ascii(char *content, size_t max_len, const char* language, c
return 1; return 1;
} }
/* URL_RESERVED_CHARS in sofia is not strict enough as in RFC3986 */
#define RFC3986_RESERVED_CHARS "!*'();:@&=+$,/?#[]"
operation_t *open_ussd_session_mo(context_t* ctx, operation_t *open_ussd_session_mo(context_t* ctx,
isup_connection_t *conn, isup_connection_t *conn,
struct ss_request* ss, struct ss_request* ss,
const char* extention) const char* extention)
{ {
char content[1024]; char content[1024];
char escaped_to[512];
operation_t *op; operation_t *op;
sip_to_t *to; sip_to_t *to = NULL;
sip_to_t *from = NULL;
url_t to_url, from_url;
char* to_url_str;
char* from_url_str;
/* create operation context information */ /* create operation context information */
op = su_zalloc(ctx->home, (sizeof *op)); op = su_zalloc(ctx->home, (sizeof *op));
@@ -397,22 +418,6 @@ operation_t *open_ussd_session_mo(context_t* ctx,
goto failed_alloc; goto failed_alloc;
} }
/* Destination address */
to = sip_to_create(ctx->home, (url_string_t *)ctx->to_str);
if (!to) {
goto failed_create;
}
//to->a_display = name;
/* create operation handle */
op->handle = nua_handle(ctx->nua,
op,
SIPTAG_TO(to),
TAG_END());
if (op->handle == NULL) {
goto failed_sip_addr;
}
op->ctx = ctx; op->ctx = ctx;
op->ussd.conn = conn; op->ussd.conn = conn;
op->ussd.ms_originated = 1; op->ussd.ms_originated = 1;
@@ -421,12 +426,60 @@ operation_t *open_ussd_session_mo(context_t* ctx,
/* TODO add language support !!! */ /* TODO add language support !!! */
if (!ussd_create_xml_ascii(content, sizeof(content), "en", if (!ussd_create_xml_ascii(content, sizeof(content),
"en",
(const char* )op->ussd.rigester_msg.ussd_text, (const char* )op->ussd.rigester_msg.ussd_text,
op->ussd.rigester_msg.ussd_text_len)) { op->ussd.rigester_msg.ussd_text_len)) {
goto failed_nua; goto failed_to_parse_xml;
} }
/* Destination address */
url_escape(escaped_to, ss->ussd_text, RFC3986_RESERVED_CHARS);
to_url = *ctx->to_url;
to_url.url_user = escaped_to;
to_url_str = url_as_string(ctx->home, &to_url);
if (to_url_str == NULL) {
goto failed_create_handle;
}
to = sip_to_create(ctx->home, (url_string_t *)to_url_str);
su_free(ctx->home, to_url_str);
if (!to) {
goto failed_create_handle;
}
/* Source address */
from_url = *ctx->self_url;
from_url.url_user = extention;
from_url_str = url_as_string(ctx->home, &from_url);
if (from_url_str == NULL) {
goto failed_create_handle;
}
from = sip_from_create(ctx->home, (url_string_t *)from_url_str);
su_free(ctx->home, from_url_str);
if (!to) {
goto failed_create_handle;
}
/* create operation handle */
op->handle = nua_handle(ctx->nua,
op,
SIPTAG_TO(to),
SIPTAG_FROM(from),
TAG_END());
su_free(ctx->home, from);
su_free(ctx->home, to);
from = NULL;
to = NULL;
if (op->handle == NULL) {
goto failed_create_handle;
}
nua_invite(op->handle, nua_invite(op->handle,
/* other tags as needed ... */ /* other tags as needed ... */
SIPTAG_CONTENT_TYPE_STR("application/vnd.3gpp.ussd+xml"), SIPTAG_CONTENT_TYPE_STR("application/vnd.3gpp.ussd+xml"),
@@ -435,11 +488,14 @@ operation_t *open_ussd_session_mo(context_t* ctx,
return op; return op;
failed_nua: //failed_nua:
nua_handle_destroy(op->handle); // nua_handle_destroy(op->handle);
failed_sip_addr: failed_create_handle:
su_free(ctx->home, to); if (from != NULL)
failed_create: su_free(ctx->home, from);
if (to != NULL)
su_free(ctx->home, to);
failed_to_parse_xml:
su_free(ctx->home, op); su_free(ctx->home, op);
failed_alloc: failed_alloc:
fprintf(stderr, "*** open_ussd_session failed!\n"); fprintf(stderr, "*** open_ussd_session failed!\n");
@@ -539,8 +595,10 @@ int ussd_send_data(operation_t *op, int last, const char* lang, unsigned lang_le
memset(&ss, 0, sizeof(ss)); memset(&ss, 0, sizeof(ss));
// TODO handle language // TODO handle language
if (msg == NULL) {
if (last) { ss.message_type = GSM0480_MTYPE_RELEASE_COMPLETE;
ss.component_type = GSM0480_CTYPE_REJECT;
} else if (last) {
ss.message_type = GSM0480_MTYPE_RELEASE_COMPLETE; ss.message_type = GSM0480_MTYPE_RELEASE_COMPLETE;
ss.component_type = GSM0480_CTYPE_RETURN_RESULT; ss.component_type = GSM0480_CTYPE_RETURN_RESULT;
} else { } else {
@@ -552,12 +610,17 @@ int ussd_send_data(operation_t *op, int last, const char* lang, unsigned lang_le
ss.opcode = op->ussd.rigester_msg.opcode; ss.opcode = op->ussd.rigester_msg.opcode;
ss.invoke_id = op->ussd.rigester_msg.invoke_id; ss.invoke_id = op->ussd.rigester_msg.invoke_id;
if (msg_len > MAX_LEN_USSD_STRING) { if (msg) {
msg_len = MAX_LEN_USSD_STRING; if (msg_len > MAX_LEN_USSD_STRING) {
} msg_len = MAX_LEN_USSD_STRING;
}
ss.ussd_text_len = msg_len; ss.ussd_text_len = msg_len;
strncpy(ss.ussd_text, msg, msg_len); strncpy(ss.ussd_text, msg, msg_len);
} else {
ss.ussd_text_len = 0;
ss.ussd_text[0] = 0;
}
struct msgb *outmsg = msgb_alloc_headroom(4000, 64, __func__); struct msgb *outmsg = msgb_alloc_headroom(4000, 64, __func__);
subscr_uss_message(outmsg, subscr_uss_message(outmsg,
@@ -723,8 +786,36 @@ int main(int argc, char *argv[])
context_t context[1] = {{{SU_HOME_INIT(context)}}}; context_t context[1] = {{{SU_HOME_INIT(context)}}};
su_sockaddr_t listen_addr; su_sockaddr_t listen_addr;
int rc; int rc;
int port = 8184; int sup_port = 8184;
const char* to_str = "sip:ussd@127.0.0.1:5060"; const char* to_str = "sip:127.0.0.1:5060";
const char* url_str = "sip:127.0.0.1:5090";
int force_tcp = 0;
int c;
while ((c = getopt (argc, argv, "p:t:u:T?")) != -1) {
switch (c)
{
case 'p':
sup_port = atoi(optarg);
break;
case 't':
to_str = optarg;
break;
case 'u':
url_str = optarg;
break;
case 'T':
force_tcp = 1;
break;
case '?':
default:
fprintf(stderr, "Usage:\n"
"%s [-p sup_port] [-t to_url] [-u agent_url] [-T]\n",
argv[0]);
return 2;
}
}
osmo_init_logging(&ipa_proxy_test_log_info); osmo_init_logging(&ipa_proxy_test_log_info);
@@ -756,7 +847,7 @@ int main(int argc, char *argv[])
memset(&listen_addr, 0, sizeof(listen_addr)); memset(&listen_addr, 0, sizeof(listen_addr));
listen_addr.su_sin.sin_family = AF_INET; listen_addr.su_sin.sin_family = AF_INET;
listen_addr.su_sin.sin_addr.s_addr = INADDR_ANY; listen_addr.su_sin.sin_addr.s_addr = INADDR_ANY;
listen_addr.su_sin.sin_port = htons(port); listen_addr.su_sin.sin_port = htons(sup_port);
rc = bind(context->isup_acc_socket, &listen_addr.su_sa, sizeof(listen_addr.su_sin)); rc = bind(context->isup_acc_socket, &listen_addr.su_sa, sizeof(listen_addr.su_sin));
if (rc < 0) { if (rc < 0) {
@@ -778,11 +869,22 @@ int main(int argc, char *argv[])
NULL, NULL,
0); 0);
context->to_str = to_str; context->to_url = url_make(home, to_str);
context->self_url = url_make(home, url_str);
if (context->to_url == NULL) {
fprintf(stderr, "Unable to parse destination URL\n");
return 1;
}
if (context->self_url == NULL) {
fprintf(stderr, "Unable to parse our (source) URL\n");
return 1;
}
context->nua = nua_create(context->root, context->nua = nua_create(context->root,
context_callback, context_callback,
context, context,
NUTAG_URL ("sip:ussd_proxy@127.0.0.1:5090"), NUTAG_URL (url_str),
/* tags as necessary ...*/ /* tags as necessary ...*/
TAG_NULL()); TAG_NULL());
if (context->nua == NULL) { if (context->nua == NULL) {
@@ -796,9 +898,14 @@ int main(int argc, char *argv[])
NUTAG_SESSION_TIMER(0), NUTAG_SESSION_TIMER(0),
NUTAG_AUTOANSWER(0), NUTAG_AUTOANSWER(0),
NUTAG_MEDIA_ENABLE(0), NUTAG_MEDIA_ENABLE(0),
//NTATAG_UDP_MTU(100), //////////////// FORCE TCP
TAG_NULL()); TAG_NULL());
if (force_tcp) {
nua_set_params(context->nua,
NTATAG_UDP_MTU(10),
TAG_NULL());
}
context->operations = NULL; context->operations = NULL;
// TEST only // TEST only