diff --git a/src/channels/chan_voicemngr.c b/src/channels/chan_voicemngr.c index 8385295190e61ba9db8769d83250ded6b3b32598..edc2005de3cb571158824fc7a6be0b69b9552ba2 100644 --- a/src/channels/chan_voicemngr.c +++ b/src/channels/chan_voicemngr.c @@ -39,7 +39,8 @@ #include <signal.h> #include <semaphore.h> #include <sys/types.h> -#include <sys/stat.h> // mkfifo() +#include <sys/stat.h> // mkfifo() + #include "asterisk/lock.h" #include "asterisk/channel.h" #include "asterisk/options.h" @@ -78,7 +79,7 @@ static int cwtimeout_cb(const void *data); static int cwbeep_cb(const void *data); static int r4hanguptimeout_cb(const void *data); static void brcm_generate_rtp_packet(struct brcm_subchannel *p, uint8_t *packet_buf, int type, int marker, int dtmf_timestamp, int seqno); -static void brcm_interpret_rtcp_packet(struct brcm_subchannel *p, uint8_t *rtcp_frame, uint32_t rtcp_size); +static void brcm_process_rtcp_packet(struct brcm_subchannel *p, uint8_t *rtcp_frame, uint32_t rtcp_size); static int brcm_mute_connection(struct brcm_subchannel *p); static int brcm_unmute_connection(struct brcm_subchannel *p); static int brcm_close_connection(struct brcm_subchannel *p); @@ -134,6 +135,16 @@ static int endpt_get_rtp_stats(int line); static int is_call_waiting_enabled(const char *sip_account); static int has_call_in_sip_client(const char *sip_account); +/* Global jitter buffer configuration - by default, jb is disabled */ +static struct ast_jb_conf default_jbconf = +{ + .flags = 0, + .max_size = -1, + .resync_threshold = -1, + .impl = "", + .target_extra = -1, +}; + /* Global brcm channel parameters */ static const char tdesc[] = "Broadcom SLIC Driver"; static const char config[] = "chan_telephony.conf"; @@ -1572,7 +1583,7 @@ static int brcm_write(struct ast_channel *ast, struct ast_frame *frame) /* copy frame data to audio packet */ memcpy(ap->rtp, frame->data.ptr, frame->datalen); - brcm_interpret_rtcp_packet(sub, ap->rtp, ap->rtp_size); + brcm_process_rtcp_packet(sub, ap->rtp, ap->rtp_size); pe_bus_send(audio_tx_bus, (uint8_t *)ap, packet_size); free(ap); @@ -5123,9 +5134,9 @@ static int brcm_close_connection(struct brcm_subchannel *sub) return 0; } - /* Generate rtp payload, 12 bytes of header and 160 bytes of ulaw payload */ -static void brcm_generate_rtp_packet(struct brcm_subchannel *sub, uint8_t *packet_buf, int type, int marker, int dtmf_timestamp, int seqno) { +static void brcm_generate_rtp_packet(struct brcm_subchannel *sub, uint8_t *packet_buf, int type, int marker, int dtmf_timestamp, int seqno) +{ unsigned short* packet_buf16 = (unsigned short*)packet_buf; unsigned int* packet_buf32 = (unsigned int*)packet_buf; @@ -5137,35 +5148,44 @@ static void brcm_generate_rtp_packet(struct brcm_subchannel *sub, uint8_t *packe packet_buf[1] = type; packet_buf[1] |= marker?0x80:0x00; packet_buf16[1] = htons(seqno ? seqno : sub->sequence_number++); //Add sequence number - packet_buf32[1] = htonl(sub->time_stamp); //Add timestamp + packet_buf32[1] = htonl(sub->time_stamp); //Add timestamp sub->time_stamp += sub->period*8; - packet_buf32[2] = sub->ssrc; //Random SSRC + packet_buf32[2] = sub->ssrc; } -static void brcm_interpret_rtcp_packet(struct brcm_subchannel *p, uint8_t *rtcp_frame, uint32_t rtcp_size) { - unsigned int *rtcp_word = (unsigned int *)(rtcp_frame); // 32 bits packet - unsigned int packetwords = rtcp_size / 4; // number of packets - unsigned int position = 0; - unsigned int pt; +/* + * This function does the followings. + * - Replace SSRC with the value from the sub-channel, which is also used by the corresponding RTP packets within + * the same session. Both RTP and RTCP packets in the same session must have the same SSRC value. + * - Accumulate "Interarrival jitter" for farEndInterrivalJitter and jitter_count which are used to calculate + * averageFarEndInterarrivalJitter. + */ +static void brcm_process_rtcp_packet(struct brcm_subchannel *p, uint8_t *rtcp_frame, uint32_t rtcp_size) +{ + struct rtcp_header_t *rtcp_hdr = (struct rtcp_header_t *)rtcp_frame; + uint8_t *packet_end = rtcp_frame + rtcp_size; - while (position < packetwords) { - unsigned int temp_word = ntohl(rtcp_word[position]); - pt = (temp_word >> 16) & 0xFF; - switch (pt) { + while ((uint8_t *)rtcp_hdr + sizeof(struct rtcp_header_t) <= packet_end && // Minimum RTCP packet size validation + RTCP_GET_VERSION(rtcp_hdr) == RTP_VERSION && // RTP version validation + RTCP_PKT_END(rtcp_hdr) <= packet_end) { // Packet length validation + switch (rtcp_hdr->pt) { case RTCP_SR: p->jitter_count++; - p->farEndInterrivalJitter += ntohl(rtcp_word[position+10]); + p->farEndInterrivalJitter += RTCP_SR_GET_INTERARRIVAL_JITTER(rtcp_hdr); /* Intentional fall through */ case RTCP_RR: case RTCP_SDES: case RTCP_XR: - //replacing ssrc - rtcp_word[position + 1] = p->ssrc; + // Replace SSRC for all types of RTCP packets above + rtcp_hdr->ssrc = p->ssrc; break; + default: + ast_log(LOG_ERROR, "Unknown RTCP packet type:%hhu\n", rtcp_hdr->pt); break; - } - position++; + } + // Move to the next RTCP header for a compound RTCP packet which contains more than one packet types + rtcp_hdr = (struct rtcp_header_t *)RTCP_PKT_END(rtcp_hdr); } } @@ -5276,4 +5296,13 @@ static int feature_access_code_match(char *sequence) return retval; } -AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Broadcom SLIC channel"); +/* + * To avoid the following loading error. + * + * module_load_error: Module 'chan_voicemngr.so' was not compiled with the same compile-time options as this version of Asterisk. + * module_load_error: Module 'chan_voicemngr.so' will not be initialized as it may cause instability. + */ +#undef AST_BUILDOPT_SUM +#define AST_BUILDOPT_SUM "" + +AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "IOPSYS voicemngr channel"); diff --git a/src/channels/chan_voicemngr.h b/src/channels/chan_voicemngr.h index a4cd44db272b2de1b268e16dbd4460372ace6a2e..173c2b796146f1c81a6f1958f8aa7afd8f3f7aaf 100644 --- a/src/channels/chan_voicemngr.h +++ b/src/channels/chan_voicemngr.h @@ -5,15 +5,11 @@ #ifndef CHAN_VOICEMNGR_H #define CHAN_VOICEMNGR_H -/* Change this value when needed */ -#define CHANNEL_VERSION "1.2" +#define CHANNEL_VERSION "1.2" -#define DEFAULT_CALLER_ID "Unknown" -#define PHONE_MAX_BUF 480 +#define PHONE_MAX_BUF 480 #define CALL_STATUS_MAX_LEN 14 -#define TIMEMSEC 1000 - // RTP payload type #define RTP_PT_PCMU 0 #define RTP_PT_G726 2 @@ -24,25 +20,24 @@ #define RTP_PT_G729 18 #define RTP_PT_DTMF 101 -// Marker bit -#define RTP_MARKER_BIT (1<<7) - -// RTCP packet type -#define RTCP_SR 200 -#define RTCP_RR 201 -#define RTCP_SDES 202 -#define RTCP_XR 207 - -#define NOT_INITIALIZED -1 -//#define EPSTATUS_DRIVER_ERROR -1 -#define MAX_NUM_LINEID 30 +#define NOT_INITIALIZED -1 +#define MAX_NUM_LINEID 30 #define PACKET_BUFFER_SIZE 1024 -#define NUM_SUBCHANNELS 2 +#define NUM_SUBCHANNELS 2 #define BEGIN 0 #define CONT 1 #define END 2 +#define DEFAULT_CALL_WAITING_TIMEOUT 20 // In seconds +#define DEFAULT_CALL_WAITING_BEEP_FREQ 5 // In seconds +#define DEFAULT_R4_HANGUP_TIMEOUT 5000 // In milliseconds +#define DEFAULT_ONHOLD_HANGUP_TIMEOUT 20 // In seconds + +// RTP header info +#define RTP_VERSION 2 +#define RTP_MARKER_BIT (1<<7) + enum brcm_channel_state { ONHOOK, OFFHOOK, @@ -60,7 +55,7 @@ enum brcm_channel_state { ALLOCATED, }; -enum LINE_EVENT { // Events from low level line (endpoint etc.) +enum LINE_EVENT { // Events from low level line (endpoint etc.) EVENT_DTMF0, EVENT_DTMF1, EVENT_DTMF2, @@ -117,6 +112,26 @@ typedef enum callid_state { CALLID_ESTABLISHED = 1 } callid_state; +/* + * Common part of RTCP header according to https://datatracker.ietf.org/doc/html/rfc1889#section-6.3.1 + */ +#define RTCP_SR 200 +#define RTCP_RR 201 +#define RTCP_SDES 202 +#define RTCP_XR 207 +struct __attribute__((packed)) rtcp_header_t { + uint8_t v_p_rc; // Version, padding and reception report count + uint8_t pt; // Packet type + /* The length of RTCP packet in 32-bit words minus 1, including the header and padding if any. + * For a compound RTCP packet which contains more than one payload type, e.g. SR + SDES + XR, length is + * just for one single RTCP packet instead of all packets. */ + uint16_t length; + uint32_t ssrc; // Synchronization source identifier for the originator +}; +#define RTCP_PKT_END(header) ((uint8_t *)(header) + (ntohs((header)->length) + 1) * 4) +#define RTCP_GET_VERSION(header) ((header)->v_p_rc >> 6) +#define RTCP_SR_GET_INTERARRIVAL_JITTER(header) ntohl(*((uint32_t *)(header) + 10)) + struct brcm_subchannel { int id; int call_id; /* The call_id of connection assigned by pjsip */ @@ -145,7 +160,6 @@ struct brcm_subchannel { char blind_xfer_target[32]; /* Transfer target for unattended call transfer */ }; - struct brcm_channel_tech { int (* signal_ringing)(struct brcm_pvt *p); int (* signal_ringing_callerid_pending)(struct brcm_pvt *p); @@ -155,7 +169,6 @@ struct brcm_channel_tech { int (* release)(struct brcm_pvt *p); }; - struct brcm_pvt { ast_mutex_t lock; int fd; /* Raw file descriptor for this device */ @@ -195,8 +208,6 @@ enum rtp_type { BRCM_RTCP_RR }; - - /* Mapping of DTMF to char/name/intval */ typedef struct DTMF_CHARNAME_MAP { @@ -242,9 +253,9 @@ typedef struct { int autodial_timeoutmsec; int ringsignal; int timeoutmsec; - int interdigitopenmsec; - int minimumnumberdigits; - char terminationdigit; + int interdigitopenmsec; + int minimumnumberdigits; + char terminationdigit; int period; int hangup_xfer; int dialtone_timeoutmsec; @@ -252,13 +263,12 @@ typedef struct { int offhook_silence_timeoutmsec; int do_not_disturb; int anonymouscallenable; - int calleridenable; - int calleridnameenable; + int calleridenable; + int calleridnameenable; flash_spec flashSpec; int mwi_enabled; } channel_settings; - /* Caller ID */ #define CLID_MAX_DATE 10 #define CLID_MAX_NUMBER 21 @@ -269,23 +279,4 @@ typedef struct CLID_STRING char number_name[CLID_MAX_NUMBER + CLID_MAX_NAME + 4]; // 4 = comma, quotation marks and null terminator } CLID_STRING; - -/* Global jitterbuffer configuration - by default, jb is disabled */ -static struct ast_jb_conf default_jbconf = -{ - .flags = 0, - .max_size = -1, - .resync_threshold = -1, - .impl = "", - .target_extra = -1, -}; - - -#define DEFAULT_CALL_WAITING_TIMEOUT 20 // In seconds -#define DEFAULT_CALL_WAITING_BEEP_FREQ 5 // In seconds - -#define DEFAULT_R4_HANGUP_TIMEOUT 5000 // In milliseconds -#define DEFAULT_ONHOLD_HANGUP_TIMEOUT 20 // In seconds - - #endif /* CHAN_VOICEMNGR_H */