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
changes/95/14995/7
Keith Whyte 3 years ago
parent 5f73c2033b
commit bd2d14bd4a
  1. 2
      src/call.c
  2. 13
      src/call.h
  3. 40
      src/sip.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 },
};

@ -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)
{

Loading…
Cancel
Save