aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeith <keith@rhizomatica.org>2019-07-30 16:26:03 +0200
committerKeith <keith@rhizomatica.org>2019-08-05 19:05:43 +0200
commitbd2d14bd4af592c2694217d84aaf81d759d2ca10 (patch)
treeb29b3f7d68c1e5fe33e078f0be9d81a5794098d0
parent5f73c2033b6b4e690f30292020d7361f48b5f2c2 (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.c2
-rw-r--r--src/call.h13
-rw-r--r--src/sip.c40
3 files changed, 55 insertions, 0 deletions
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)
{