diff --git a/src/app.c b/src/app.c index 36e7cb0..0fe149b 100644 --- a/src/app.c +++ b/src/app.c @@ -63,15 +63,19 @@ static void route_to_sip(struct call *call, const char *source, const char *dest call->initial->release_call(call->initial); } +static void route_to_mncc(struct call *call, const char *source, + const char *dest) +{ + if (mncc_create_remote_leg(&g_app.mncc.conn, call, source, dest) != 0) + call->initial->release_call(call->initial); +} + void app_route_call(struct call *call, const char *source, const char *dest) { if (call->initial->type == CALL_TYPE_MNCC) route_to_sip(call, source, dest); - else { - LOGP(DAPP, LOGL_ERROR, "Can not route call(%u) to MNCC yet\n", - call->id); - call->initial->release_call(call->initial); - } + else + route_to_mncc(call, source, dest); } const char *app_media_name(int ptmsg) diff --git a/src/mncc.c b/src/mncc.c index 2e0e01d..92ce189 100644 --- a/src/mncc.c +++ b/src/mncc.c @@ -489,6 +489,63 @@ static void check_hello(struct mncc_connection *conn, char *buf, int rc) conn->state = MNCC_READY; } +int mncc_create_remote_leg(struct mncc_connection *conn, struct call *call, + const char *calling, const char *called) +{ + struct mncc_call_leg *leg; + struct gsm_mncc mncc = { 0, }; + int rc; + + leg = talloc_zero(call, struct mncc_call_leg); + if (!leg) { + LOGP(DMNCC, LOGL_ERROR, "Failed to allocate leg call(%u)\n", + call->id); + return -1; + } + + leg->base.type = CALL_TYPE_MNCC; + leg->base.connect_call = mncc_call_leg_connect; + leg->base.ring_call = mncc_call_leg_ring; + leg->base.release_call = mncc_call_leg_release; + leg->base.call = call; + + leg->callref = call->id; + + leg->conn = conn; + leg->state = MNCC_CC_INITIAL; + + mncc.msg_type = MNCC_SETUP_REQ; + mncc.callref = leg->callref; + + mncc.fields |= MNCC_F_CALLING; + mncc.calling.plan = 1; + mncc.calling.type = 0x0; + memcpy(&mncc.calling.number, calling, sizeof(mncc.calling.number)); + + mncc.fields |= MNCC_F_CALLED; + mncc.called.plan = 1; + mncc.called.type = 0x0; + memcpy(&mncc.called.number, called, sizeof(mncc.called.number)); + + /* + * TODO/FIXME: + * - Determine/request channel based on offered audio codecs + * - Screening, redirect? + * - Synth. the bearer caps based on codecs? + */ + rc = write(conn->fd.fd, &mncc, sizeof(mncc)); + if (rc != sizeof(mncc)) { + LOGP(DMNCC, LOGL_ERROR, "Failed to send message leg(%u)\n", + leg->callref); + close_connection(conn); + talloc_free(leg); + return -1; + } + + call->remote = &leg->base; + return 0; +} + static void mncc_reconnect(void *data) { int rc; diff --git a/src/mncc.h b/src/mncc.h index 5944a1b..7078283 100644 --- a/src/mncc.h +++ b/src/mncc.h @@ -6,6 +6,7 @@ #include struct app_config; +struct call; enum { MNCC_DISCONNECTED, @@ -28,3 +29,6 @@ struct mncc_connection { void mncc_connection_init(struct mncc_connection *conn, struct app_config *cfg); void mncc_connection_start(struct mncc_connection *conn); + +int mncc_create_remote_leg(struct mncc_connection *conn, struct call *call, + const char *calling, const char *called);