mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-mgw.git
synced 2025-11-03 05:23:43 +00:00
ussd_proxy: properly set To and From SIP headers
This commit is contained in:
committed by
Ivan Kluchnikov
parent
be9419881c
commit
70e6f2ec74
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user