From c2474dc0beffc67478383410aa09846cbf6b44dd Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Thu, 31 Mar 2016 16:06:04 +0200 Subject: [PATCH] mncc: Add handling to connect a MNCC MT call This will go through the stage of: * MNCC_CALL_CONF_IND (to which we create a RTP socket) * then we might receive a MNCC_ALERT_IND * and finally the MNCC_SETUP_CNF For the last two we inform the other leg about the progress. --- src/mncc.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 116 insertions(+), 10 deletions(-) diff --git a/src/mncc.c b/src/mncc.c index 1895254..c25672d 100644 --- a/src/mncc.c +++ b/src/mncc.c @@ -130,18 +130,11 @@ static void mncc_rtp_send(struct mncc_connection *conn, uint32_t msg_type, uint3 } } -static void mncc_call_leg_connect(struct call_leg *_leg) +static bool send_rtp_connect(struct mncc_call_leg *leg, struct call_leg *other) { struct gsm_mncc_rtp mncc = { 0, }; - struct mncc_call_leg *leg; - struct call_leg *other; int rc; - OSMO_ASSERT(_leg->type == CALL_TYPE_MNCC); - leg = (struct mncc_call_leg *) _leg; - - other = call_leg_other(_leg); - /* * Send RTP CONNECT and we handle the general failure of it by * tearing down the call. @@ -160,8 +153,23 @@ static void mncc_call_leg_connect(struct call_leg *_leg) LOGP(DMNCC, LOGL_ERROR, "Failed to send message leg(%u)\n", leg->callref); close_connection(leg->conn); - return; + return false; } + return true; +} + +static void mncc_call_leg_connect(struct call_leg *_leg) +{ + struct mncc_call_leg *leg; + struct call_leg *other; + + OSMO_ASSERT(_leg->type == CALL_TYPE_MNCC); + leg = (struct mncc_call_leg *) _leg; + + other = call_leg_other(_leg); + + if (!send_rtp_connect(leg, other)) + return; start_cmd_timer(leg, MNCC_SETUP_COMPL_IND); mncc_send(leg->conn, MNCC_SETUP_RSP, leg->callref); @@ -230,7 +238,7 @@ static void close_connection(struct mncc_connection *conn) conn->on_disconnect(conn); } -static void continue_call(struct mncc_call_leg *leg) +static void continue_mo_call(struct mncc_call_leg *leg) { char *dest, *source; @@ -249,6 +257,26 @@ static void continue_call(struct mncc_call_leg *leg) talloc_free(dest); } +static void continue_mt_call(struct mncc_call_leg *leg) +{ + struct call_leg *other_leg; + + /* TODO.. check codec selection */ + other_leg = call_leg_other(&leg->base); + if (!other_leg) + return; + + /* assume the type is compatible */ + other_leg->payload_type = leg->base.payload_type; +} + +static void continue_call(struct mncc_call_leg *leg) +{ + if (leg->dir == MNCC_DIR_MO) + return continue_mo_call(leg); + return continue_mt_call(leg); +} + static void check_rtp_connect(struct mncc_connection *conn, char *buf, int rc) { struct gsm_mncc_rtp *rtp; @@ -497,6 +525,75 @@ static void check_rej_ind(struct mncc_connection *conn, char *buf, int rc) call_leg_release(&leg->base); } +static void check_cnf_ind(struct mncc_connection *conn, char *buf, int rc) +{ + struct gsm_mncc *data; + struct mncc_call_leg *leg; + + leg = find_leg(conn, buf, rc, &data); + if (!leg) + return; + + LOGP(DMNCC, LOGL_DEBUG, + "leg(%u) confirmend. creating RTP socket.\n", + leg->callref); + + start_cmd_timer(leg, MNCC_RTP_CREATE); + mncc_rtp_send(conn, MNCC_RTP_CREATE, data->callref); +} + +static void check_alrt_ind(struct mncc_connection *conn, char *buf, int rc) +{ + struct gsm_mncc *data; + struct mncc_call_leg *leg; + struct call_leg *other_leg; + + leg = find_leg(conn, buf, rc, &data); + if (!leg) + return; + + LOGP(DMNCC, LOGL_DEBUG, + "leg(%u) is alerting.\n", leg->callref); + + other_leg = call_leg_other(&leg->base); + if (!other_leg) { + LOGP(DMNCC, LOGL_ERROR, "leg(%u) other leg gone!\n", + leg->callref); + mncc_call_leg_release(&leg->base); + return; + } + + other_leg->ring_call(other_leg); +} + +static void check_stp_cnf(struct mncc_connection *conn, char *buf, int rc) +{ + struct gsm_mncc *data; + struct mncc_call_leg *leg; + struct call_leg *other_leg; + + leg = find_leg(conn, buf, rc, &data); + if (!leg) + return; + + LOGP(DMNCC, LOGL_DEBUG, "leg(%u) setup completed\n", leg->callref); + + other_leg = call_leg_other(&leg->base); + if (!other_leg) { + LOGP(DMNCC, LOGL_ERROR, "leg(%u) other leg gone!\n", + leg->callref); + mncc_call_leg_release(&leg->base); + return; + } + + if (!send_rtp_connect(leg, other_leg)) + return; + leg->state = MNCC_CC_CONNECTED; + mncc_send(leg->conn, MNCC_SETUP_COMPL_REQ, leg->callref); + + other_leg->connect_call(other_leg); +} + static void check_hello(struct mncc_connection *conn, char *buf, int rc) { struct gsm_mncc_hello *hello; @@ -643,6 +740,15 @@ static int mncc_data(struct osmo_fd *fd, unsigned int what) case MNCC_SETUP_COMPL_IND: check_stp_cmpl_ind(conn, buf, rc); break; + case MNCC_SETUP_CNF: + check_stp_cnf(conn, buf, rc); + break; + case MNCC_CALL_CONF_IND: + check_cnf_ind(conn, buf, rc); + break; + case MNCC_ALERT_IND: + check_alrt_ind(conn, buf, rc); + break; default: LOGP(DMNCC, LOGL_ERROR, "Unhandled message type %d/0x%x\n", msg_type, msg_type);