sip: use osmo_{enc,dec}_gcr() from libosmocore
Change-Id: I46fa46fc79494d337f2f4657215b91c39207eea4 Depends: I06babb959fdc82f4e82d92260131d60c98b0abd2 Fixes: Id40d7e0fed9356f801b3627c118150055e7232b1 Related: OS#5164
This commit is contained in:
parent
5e178d2c55
commit
f3eb44f54b
|
@ -5,6 +5,7 @@
|
|||
#include <osmocom/core/linuxlist.h>
|
||||
#include <osmocom/core/timer.h>
|
||||
#include <osmocom/core/utils.h>
|
||||
#include <osmocom/gsm/gsm29205.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <netinet/in.h>
|
||||
|
@ -31,7 +32,10 @@ struct call {
|
|||
|
||||
const char *source;
|
||||
const char *dest;
|
||||
|
||||
/* Global Call Reference */
|
||||
struct osmo_gcr_parsed gcr;
|
||||
bool gcr_present;
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
|
@ -544,6 +544,7 @@ static void check_setup(struct mncc_connection *conn, const char *buf, int rc)
|
|||
leg->state = MNCC_CC_INITIAL;
|
||||
leg->dir = MNCC_DIR_MO;
|
||||
leg->base.call->gcr = data->gcr;
|
||||
leg->base.call->gcr_present = true;
|
||||
memcpy(&leg->called, called, sizeof(leg->called));
|
||||
memcpy(&leg->calling, &data->calling, sizeof(leg->calling));
|
||||
memcpy(&leg->imsi, data->imsi, sizeof(leg->imsi));
|
||||
|
@ -899,7 +900,8 @@ int mncc_create_remote_leg(struct mncc_connection *conn, struct call *call)
|
|||
|
||||
mncc.fields |= MNCC_F_CALLING;
|
||||
mncc.calling.plan = GSM48_NPI_ISDN_E164;
|
||||
mncc.gcr = call->gcr;
|
||||
if (call->gcr_present)
|
||||
mncc.gcr = call->gcr;
|
||||
|
||||
if (call->source && call->source[0] == '+') {
|
||||
mncc.calling.type = GSM48_TON_INTERNATIONAL;
|
||||
|
|
89
src/sip.c
89
src/sip.c
|
@ -107,34 +107,6 @@ static void call_connect(struct sip_call_leg *leg, const sip_t *sip)
|
|||
nua_ack(leg->nua_handle, TAG_END());
|
||||
}
|
||||
|
||||
int _osmo_dec_gcr(struct osmo_gcr_parsed *gcr, const uint8_t *elem, uint8_t len)
|
||||
{
|
||||
uint16_t parsed = 1; /* account for length byte right away */
|
||||
|
||||
if (len < 13)
|
||||
return -EBADMSG;
|
||||
|
||||
gcr->net_len = elem[0];
|
||||
if (gcr->net_len < 3 || gcr->net_len > 5)
|
||||
return -EINVAL;
|
||||
|
||||
memcpy(gcr->net, elem + parsed, gcr->net_len);
|
||||
/* +1 for ignored Node ID length field */
|
||||
parsed += (gcr->net_len + 1);
|
||||
|
||||
gcr->node = osmo_load16be(elem + parsed);
|
||||
parsed += 2;
|
||||
|
||||
if (elem[parsed] != 5) /* see Table B 2.1.9.2 */
|
||||
return -ENOENT;
|
||||
|
||||
parsed++;
|
||||
|
||||
memcpy(gcr->cr, elem + parsed, 5);
|
||||
|
||||
return parsed + 5;
|
||||
}
|
||||
|
||||
static void new_call(struct sip_agent *agent, nua_handle_t *nh,
|
||||
const sip_t *sip)
|
||||
{
|
||||
|
@ -142,15 +114,16 @@ static void new_call(struct sip_agent *agent, nua_handle_t *nh,
|
|||
struct sip_call_leg *leg;
|
||||
const char *from = NULL, *to = NULL;
|
||||
char ip_addr[INET6_ADDRSTRLEN];
|
||||
uint8_t gcr_back[28] = { 0 };
|
||||
|
||||
bool xgcr_hdr_present = false;
|
||||
uint8_t xgcr_hdr[28] = { 0 };
|
||||
|
||||
LOGP(DSIP, LOGL_INFO, "Incoming call(%s) handle(%p)\n", sip->sip_call_id->i_id, nh);
|
||||
|
||||
sip_unknown_t *unknown_header = sip->sip_unknown;
|
||||
while (unknown_header != NULL) {
|
||||
if (!strcmp("X-Global-Call-Ref", unknown_header->un_name)) {
|
||||
osmo_hexparse(unknown_header->un_value, gcr_back, sizeof(gcr_back));
|
||||
osmo_hexparse(unknown_header->un_value, xgcr_hdr, sizeof(xgcr_hdr));
|
||||
xgcr_hdr_present = true;
|
||||
break;
|
||||
}
|
||||
unknown_header = unknown_header->un_next;
|
||||
|
@ -171,7 +144,16 @@ static void new_call(struct sip_agent *agent, nua_handle_t *nh,
|
|||
return;
|
||||
}
|
||||
|
||||
_osmo_dec_gcr(&call->gcr, gcr_back, sizeof(gcr_back));
|
||||
/* Decode Decode the Global Call Reference (if present) */
|
||||
if (xgcr_hdr_present) {
|
||||
if (osmo_dec_gcr(&call->gcr, xgcr_hdr, sizeof(xgcr_hdr)) < 0) {
|
||||
LOGP(DSIP, LOGL_ERROR, "Failed to parse X-Global-Call-Ref.\n");
|
||||
nua_respond(nh, SIP_406_NOT_ACCEPTABLE, TAG_END());
|
||||
nua_handle_destroy(nh);
|
||||
return;
|
||||
}
|
||||
call->gcr_present = true;
|
||||
}
|
||||
|
||||
if (sip->sip_to)
|
||||
to = sip->sip_to->a_url->url_user;
|
||||
|
@ -632,38 +614,10 @@ static void sip_retrieve_call(struct call_leg *_leg)
|
|||
leg->state = SIP_CC_CONNECTED;
|
||||
}
|
||||
|
||||
/*! Encode Global Call Reference. */
|
||||
uint8_t _osmo_enc_gcr(uint8_t *buf, const struct osmo_gcr_parsed *g)
|
||||
{
|
||||
uint8_t tmp[2];
|
||||
|
||||
if (!g)
|
||||
return 0;
|
||||
|
||||
if (g->net_len < 3 || g->net_len > 5)
|
||||
return 0;
|
||||
|
||||
buf = lv_put(buf, g->net_len, g->net);
|
||||
osmo_store16be(g->node, &tmp);
|
||||
buf = lv_put(buf, 2, tmp);
|
||||
buf = lv_put(buf, 5, g->cr);
|
||||
|
||||
/* Length: LV(Net) + LV(Node) + LV(CRef) - see 3GPP TS §3.2.2.115 */
|
||||
return (g->net_len + 1) + (2 + 1) + (5 + 1);
|
||||
}
|
||||
|
||||
static int send_invite(struct sip_agent *agent, struct sip_call_leg *leg,
|
||||
const char *calling_num, const char *called_num)
|
||||
{
|
||||
struct call_leg *other = leg->base.call->initial;
|
||||
char gcr_hex[30];
|
||||
uint8_t data[15];
|
||||
|
||||
gcr_hex[0] = '\0';
|
||||
data[0] = '\0';
|
||||
uint8_t len = _osmo_enc_gcr(data, &leg->base.call->gcr);
|
||||
if (len)
|
||||
osmo_strlcpy(gcr_hex, osmo_hexdump_nospc(data, len*2+1), len*2+1);
|
||||
|
||||
char *from = talloc_asprintf(leg, "sip:%s@%s:%d",
|
||||
calling_num,
|
||||
|
@ -675,7 +629,18 @@ static int send_invite(struct sip_agent *agent, struct sip_call_leg *leg,
|
|||
agent->app->sip.remote_port);
|
||||
char *sdp = sdp_create_file(leg, other, sdp_sendrecv);
|
||||
|
||||
char *x_gcr = talloc_asprintf(leg, "X-Global-Call-Ref: %s", gcr_hex);
|
||||
/* Encode the Global Call Reference (if present) */
|
||||
char *x_gcr = NULL;
|
||||
|
||||
if (leg->base.call->gcr_present) {
|
||||
struct msgb *msg = msgb_alloc(16, "SIP GCR");
|
||||
|
||||
if (msg != NULL && osmo_enc_gcr(msg, &leg->base.call->gcr) > 0)
|
||||
x_gcr = talloc_asprintf(leg, "X-Global-Call-Ref: %s", msgb_hexdump(msg));
|
||||
else
|
||||
LOGP(DSIP, LOGL_ERROR, "Failed to encode GCR for leg(%p)\n", leg);
|
||||
msgb_free(msg);
|
||||
}
|
||||
|
||||
leg->state = SIP_CC_INITIAL;
|
||||
leg->dir = SIP_DIR_MT;
|
||||
|
@ -684,7 +649,7 @@ static int send_invite(struct sip_agent *agent, struct sip_call_leg *leg,
|
|||
SIPTAG_TO_STR(to),
|
||||
NUTAG_MEDIA_ENABLE(0),
|
||||
SIPTAG_CONTENT_TYPE_STR("application/sdp"),
|
||||
SIPTAG_HEADER_STR(x_gcr),
|
||||
TAG_IF(x_gcr, SIPTAG_HEADER_STR(x_gcr)),
|
||||
SIPTAG_PAYLOAD_STR(sdp),
|
||||
TAG_END());
|
||||
|
||||
|
|
Loading…
Reference in New Issue