From bd2d14bd4af592c2694217d84aaf81d759d2ca10 Mon Sep 17 00:00:00 2001 From: Keith Date: Tue, 30 Jul 2019 16:26:03 +0200 Subject: [PATCH] Prepare to support MO Call HOLD Add function pointers to the call_leg struct for call hold and retrieve. Add function to send re-INVITE to SIP side when MNCC side puts call on HOLD/RETRIEVES. Add MNCC/SIP CC_HOLD to call states. Change-Id: I2595626dfa50eb2f8e29a02540b708c9c1dce88c --- src/call.c | 2 ++ src/call.h | 13 +++++++++++++ src/sip.c | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+) diff --git a/src/call.c b/src/call.c index 9be6b4d..67207e5 100644 --- a/src/call.c +++ b/src/call.c @@ -40,6 +40,7 @@ const struct value_string mncc_state_vals[] = { { MNCC_CC_INITIAL, "INITIAL" }, { MNCC_CC_PROCEEDING, "PROCEEDING" }, { MNCC_CC_CONNECTED, "CONNECTED" }, + { MNCC_CC_HOLD, "ON HOLD" }, { 0, NULL }, }; @@ -53,6 +54,7 @@ const struct value_string sip_state_vals[] = { { SIP_CC_INITIAL, "INITIAL" }, { SIP_CC_DLG_CNFD, "CONFIRMED" }, { SIP_CC_CONNECTED, "CONNECTED" }, + { SIP_CC_HOLD, "ON HOLD" }, { 0, NULL }, }; diff --git a/src/call.h b/src/call.h index 5076c01..bc772a4 100644 --- a/src/call.h +++ b/src/call.h @@ -75,6 +75,17 @@ struct call_leg { */ void (*dtmf)(struct call_leg *, int keypad); + /** + * Call HOLD requested + */ + void (*hold_call)(struct call_leg *); + + /** + * Call HOLD ended + */ + void (*retrieve_call)(struct call_leg *); + + void (*update_rtp)(struct call_leg *); }; @@ -83,6 +94,7 @@ enum sip_cc_state { SIP_CC_INITIAL, SIP_CC_DLG_CNFD, SIP_CC_CONNECTED, + SIP_CC_HOLD, }; enum sip_dir { @@ -113,6 +125,7 @@ enum mncc_cc_state { MNCC_CC_INITIAL, MNCC_CC_PROCEEDING, /* skip delivered state */ MNCC_CC_CONNECTED, + MNCC_CC_HOLD, }; enum mncc_dir { diff --git a/src/sip.c b/src/sip.c index be0d24a..8a96bed 100644 --- a/src/sip.c +++ b/src/sip.c @@ -40,6 +40,9 @@ static void sip_release_call(struct call_leg *_leg); static void sip_ring_call(struct call_leg *_leg); static void sip_connect_call(struct call_leg *_leg); static void sip_dtmf_call(struct call_leg *_leg, int keypad); +static void sip_hold_call(struct call_leg *_leg); +static void sip_retrieve_call(struct call_leg *_leg); + /* Find a SIP Call leg by given nua_handle */ static struct sip_call_leg *sip_find_leg(nua_handle_t *nh) @@ -160,6 +163,8 @@ static void new_call(struct sip_agent *agent, nua_handle_t *nh, leg->base.ring_call = sip_ring_call; leg->base.connect_call = sip_connect_call; leg->base.dtmf = sip_dtmf_call; + leg->base.hold_call = sip_hold_call; + leg->base.retrieve_call = sip_retrieve_call; leg->agent = agent; leg->nua_handle = nh; nua_handle_bind(nh, leg); @@ -441,6 +446,7 @@ static void sip_release_call(struct call_leg *_leg) } break; case SIP_CC_CONNECTED: + case SIP_CC_HOLD: LOGP(DSIP, LOGL_NOTICE, "Ending leg(%p) in con\n", leg); nua_bye(leg->nua_handle, TAG_END()); break; @@ -503,6 +509,40 @@ static void sip_dtmf_call(struct call_leg *_leg, int keypad) talloc_free(buf); } +static void sip_hold_call(struct call_leg *_leg) +{ + struct sip_call_leg *leg; + struct call_leg *other_leg; + OSMO_ASSERT(_leg->type == CALL_TYPE_SIP); + leg = (struct sip_call_leg *) _leg; + other_leg = call_leg_other(&leg->base); + char *sdp = sdp_create_file(leg, other_leg, sdp_sendonly); + nua_invite(leg->nua_handle, + NUTAG_MEDIA_ENABLE(0), + SIPTAG_CONTENT_TYPE_STR("application/sdp"), + SIPTAG_PAYLOAD_STR(sdp), + TAG_END()); + talloc_free(sdp); + leg->state = SIP_CC_HOLD; +} + +static void sip_retrieve_call(struct call_leg *_leg) +{ + struct sip_call_leg *leg; + struct call_leg *other_leg; + OSMO_ASSERT(_leg->type == CALL_TYPE_SIP); + leg = (struct sip_call_leg *) _leg; + other_leg = call_leg_other(&leg->base); + char *sdp = sdp_create_file(leg, other_leg, sdp_sendrecv); + nua_invite(leg->nua_handle, + NUTAG_MEDIA_ENABLE(0), + SIPTAG_CONTENT_TYPE_STR("application/sdp"), + SIPTAG_PAYLOAD_STR(sdp), + TAG_END()); + talloc_free(sdp); + leg->state = SIP_CC_CONNECTED; +} + static int send_invite(struct sip_agent *agent, struct sip_call_leg *leg, const char *calling_num, const char *called_num) {