Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SipPlugin read rfc2833 dtmf and convert to sip info event #3280

Merged
merged 7 commits into from
Nov 20, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 56 additions & 1 deletion src/plugins/janus_sip.c
Original file line number Diff line number Diff line change
Expand Up @@ -868,6 +868,7 @@ static int dscp_video_rtp = 0;
static char *sips_certs_dir = NULL;
#define JANUS_DEFAULT_SIP_TIMER_T1X64 32000
static int sip_timer_t1x64 = JANUS_DEFAULT_SIP_TIMER_T1X64;
static uint16_t dtmf_keys[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '*', '#', 'A', 'B', 'C', 'D'};

static gboolean query_contact_header = FALSE;

Expand Down Expand Up @@ -1047,6 +1048,11 @@ typedef struct janus_sip_media {
int audio_level_extension_id;
} janus_sip_media;

typedef struct janus_sip_dtmf {
uint16_t dtmf_event_id;
uint32_t timestamp;
} janus_sip_dtmf;

typedef struct janus_sip_session {
janus_plugin_session *handle;
ssip_t *stack;
Expand Down Expand Up @@ -1079,7 +1085,9 @@ typedef struct janus_sip_session {
GList *incoming_header_prefixes;
GList *active_calls;
janus_refcount ref;
janus_sip_dtmf latest_dtmf;
} janus_sip_session;

static GHashTable *sessions;
static GHashTable *identities;
static GHashTable *callids;
Expand Down Expand Up @@ -1512,7 +1520,7 @@ char *janus_sip_sdp_manipulate(janus_sip_session *session, janus_sdp *sdp, gbool
static int janus_sip_allocate_local_ports(janus_sip_session *session, gboolean update);
static void *janus_sip_relay_thread(void *data);
static void janus_sip_media_cleanup(janus_sip_session *session);

static void janus_sip_check_rfc2833(janus_sip_session *session, char *buffer, int len);

/* URI parsing utilies */

Expand Down Expand Up @@ -7140,6 +7148,7 @@ static void *janus_sip_relay_thread(void *data) {
continue;
}
janus_rtp_header *header = (janus_rtp_header *)buffer;
janus_sip_check_rfc2833(session, buffer, bytes);
if(session->media.audio_ssrc_peer == 0) {
session->media.audio_ssrc_peer = ntohl(header->ssrc);
JANUS_LOG(LOG_VERB, "Got SIP peer audio SSRC: %"SCNu32"\n", session->media.audio_ssrc_peer);
Expand Down Expand Up @@ -7392,6 +7401,52 @@ gpointer janus_sip_sofia_thread(gpointer user_data) {
return NULL;
}

/* Check peer RTP has RFC2833 and push event */
static void janus_sip_check_rfc2833(janus_sip_session *session, char *buffer, int len) {
janus_rtp_header *rtp_header = (janus_rtp_header *)buffer;
if(rtp_header->type != JANUS_RTP_RFC2833_DEFAULT_PAYLOAD_TYPE)
return;
int plen = 0;
char *payload_buffer = janus_rtp_payload(buffer, len, &plen);
if(plen < sizeof(janus_rtp_rfc2833_payload))
ywmoyue marked this conversation as resolved.
Show resolved Hide resolved
return;
janus_rtp_rfc2833_payload *rfc2833_payload = (janus_rtp_rfc2833_payload *)payload_buffer;
ywmoyue marked this conversation as resolved.
Show resolved Hide resolved
uint16_t duration = ntohs(rfc2833_payload->duration);
if(rfc2833_payload->end == 0)
return;

/* Set up last dtmf to avoid duplication */
if(session->latest_dtmf.dtmf_event_id == rfc2833_payload->event && session->latest_dtmf.timestamp == rtp_header->timestamp)
return;
session->latest_dtmf.dtmf_event_id = rfc2833_payload->event;
session->latest_dtmf.timestamp = rtp_header->timestamp;

/* Parse dtmf key */
uint16_t dtmf_key;
if(rfc2833_payload->event < 0 || rfc2833_payload->event > 15)
ywmoyue marked this conversation as resolved.
Show resolved Hide resolved
return;
dtmf_key = dtmf_keys[rfc2833_payload->event];
char dtmf_key_str[2];
dtmf_key_str[0] = dtmf_key;
dtmf_key_str[1] = '\0';

/* Notify the application */
json_t *info = json_object();
json_object_set_new(info, "sip", json_string("event"));
json_t *result = json_object();
json_object_set_new(result, "event", json_string("dtmf"));
json_object_set_new(result, "sender", json_string(session->callee));
json_object_set_new(result, "signal", json_string(dtmf_key_str));
json_object_set_new(result, "duration", json_integer(duration));
if(session->callid)
json_object_set_new(info, "call_id", json_string(session->callid));
json_object_set_new(info, "result", result);
ywmoyue marked this conversation as resolved.
Show resolved Hide resolved
int ret = gateway->push_event(session->handle, &janus_sip_plugin, session->transaction, info, NULL);
JANUS_LOG(LOG_VERB, " >> Pushing event to peer: %d (%s)\n", ret, janus_get_api_error(ret));
json_decref(info);
return;
}

/* Helper method to send an RTCP PLI to the SIP peer */
static void janus_sip_rtcp_pli_send(janus_sip_session *session) {
if(!session || g_atomic_int_get(&session->destroyed)) {
Expand Down
19 changes: 19 additions & 0 deletions src/rtp.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,25 @@ typedef struct janus_rtp_header_extension {
uint16_t length;
} janus_rtp_header_extension;

/*! \brief RTP RFC2833 payload */
typedef struct janus_rtp_rfc2833_payload {
#if __BYTE_ORDER == __BIG_ENDIAN
uint8_t event;
uint8_t end:1;
uint8_t reserved:1;
uint8_t volume:6;
uint16_t duration;
#elif __BYTE_ORDER == __LITTLE_ENDIAN
uint8_t event;
uint8_t volume:6;
uint8_t reserved:1;
uint8_t end:1;
uint16_t duration;
#endif
} janus_rtp_rfc2833_payload;

#define JANUS_RTP_RFC2833_DEFAULT_PAYLOAD_TYPE 101

/*! \brief a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level */
#define JANUS_RTP_EXTMAP_AUDIO_LEVEL "urn:ietf:params:rtp-hdrext:ssrc-audio-level"
/*! \brief a=extmap:2 urn:ietf:params:rtp-hdrext:toffset */
Expand Down