diff options
author | Keith <keith@rhizomatica.org> | 2019-07-30 16:26:03 +0200 |
---|---|---|
committer | Keith <keith@rhizomatica.org> | 2019-08-05 19:05:43 +0200 |
commit | bd2d14bd4af592c2694217d84aaf81d759d2ca10 (patch) | |
tree | b29b3f7d68c1e5fe33e078f0be9d81a5794098d0 | |
parent | 5f73c2033b6b4e690f30292020d7361f48b5f2c2 (diff) |
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
-rw-r--r-- | src/call.c | 2 | ||||
-rw-r--r-- | src/call.h | 13 | ||||
-rw-r--r-- | src/sip.c | 40 |
3 files changed, 55 insertions, 0 deletions
@@ -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 }, }; @@ -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 { @@ -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) { |