Bug #6109: Fix unprotected list in RTP, implement AST_LIST macros, update doxygen docs

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@7730 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.4
Olle Johansson 20 years ago
parent 9b315771d4
commit 715a220850

@ -26,12 +26,13 @@
#ifndef _ASTERISK_RTP_H #ifndef _ASTERISK_RTP_H
#define _ASTERISK_RTP_H #define _ASTERISK_RTP_H
#include <netinet/in.h>
#include "asterisk/frame.h" #include "asterisk/frame.h"
#include "asterisk/io.h" #include "asterisk/io.h"
#include "asterisk/sched.h" #include "asterisk/sched.h"
#include "asterisk/channel.h" #include "asterisk/channel.h"
#include "asterisk/linkedlists.h"
#include <netinet/in.h>
#if defined(__cplusplus) || defined(c_plusplus) #if defined(__cplusplus) || defined(c_plusplus)
extern "C" { extern "C" {
@ -48,15 +49,15 @@ extern "C" {
#define AST_RTP_MAX AST_RTP_CISCO_DTMF #define AST_RTP_MAX AST_RTP_CISCO_DTMF
struct ast_rtp_protocol { struct ast_rtp_protocol {
/* Get RTP struct, or NULL if unwilling to transfer */ /*! Get RTP struct, or NULL if unwilling to transfer */
struct ast_rtp *(* const get_rtp_info)(struct ast_channel *chan); struct ast_rtp *(* const get_rtp_info)(struct ast_channel *chan);
/* Get RTP struct, or NULL if unwilling to transfer */ /*! Get RTP struct, or NULL if unwilling to transfer */
struct ast_rtp *(* const get_vrtp_info)(struct ast_channel *chan); struct ast_rtp *(* const get_vrtp_info)(struct ast_channel *chan);
/* Set RTP peer */ /*! Set RTP peer */
int (* const set_rtp_peer)(struct ast_channel *chan, struct ast_rtp *peer, struct ast_rtp *vpeer, int codecs, int nat_active); int (* const set_rtp_peer)(struct ast_channel *chan, struct ast_rtp *peer, struct ast_rtp *vpeer, int codecs, int nat_active);
int (* const get_codec)(struct ast_channel *chan); int (* const get_codec)(struct ast_channel *chan);
const char * const type; const char * const type;
struct ast_rtp_protocol *next; AST_LIST_ENTRY(ast_rtp_protocol) list;
}; };
/*! /*!
@ -124,25 +125,25 @@ int ast_rtp_sendcng(struct ast_rtp *rtp, int level);
int ast_rtp_settos(struct ast_rtp *rtp, int tos); int ast_rtp_settos(struct ast_rtp *rtp, int tos);
/* Setting RTP payload types from lines in a SDP description: */ /*! \brief Setting RTP payload types from lines in a SDP description: */
void ast_rtp_pt_clear(struct ast_rtp* rtp); void ast_rtp_pt_clear(struct ast_rtp* rtp);
/* Set payload types to defaults */ /*! \brief Set payload types to defaults */
void ast_rtp_pt_default(struct ast_rtp* rtp); void ast_rtp_pt_default(struct ast_rtp* rtp);
void ast_rtp_set_m_type(struct ast_rtp* rtp, int pt); void ast_rtp_set_m_type(struct ast_rtp* rtp, int pt);
void ast_rtp_set_rtpmap_type(struct ast_rtp* rtp, int pt, void ast_rtp_set_rtpmap_type(struct ast_rtp* rtp, int pt,
char* mimeType, char* mimeSubtype); char* mimeType, char* mimeSubtype);
/* Mapping between RTP payload format codes and Asterisk codes: */ /*! \brief Mapping between RTP payload format codes and Asterisk codes: */
struct rtpPayloadType ast_rtp_lookup_pt(struct ast_rtp* rtp, int pt); struct rtpPayloadType ast_rtp_lookup_pt(struct ast_rtp* rtp, int pt);
int ast_rtp_lookup_code(struct ast_rtp* rtp, int isAstFormat, int code); int ast_rtp_lookup_code(struct ast_rtp* rtp, int isAstFormat, int code);
void ast_rtp_get_current_formats(struct ast_rtp* rtp, void ast_rtp_get_current_formats(struct ast_rtp* rtp,
int* astFormats, int* nonAstFormats); int* astFormats, int* nonAstFormats);
/* Mapping an Asterisk code into a MIME subtype (string): */ /*! \brief Mapping an Asterisk code into a MIME subtype (string): */
char* ast_rtp_lookup_mime_subtype(int isAstFormat, int code); char* ast_rtp_lookup_mime_subtype(int isAstFormat, int code);
/* Build a string of MIME subtype names from a capability list */ /*! \brief Build a string of MIME subtype names from a capability list */
char *ast_rtp_lookup_mime_multiple(char *buf, int size, const int capability, const int isAstFormat); char *ast_rtp_lookup_mime_multiple(char *buf, int size, const int capability, const int isAstFormat);
void ast_rtp_setnat(struct ast_rtp *rtp, int nat); void ast_rtp_setnat(struct ast_rtp *rtp, int nat);

221
rtp.c

@ -61,38 +61,38 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#define RTP_MTU 1200 #define RTP_MTU 1200
#define DEFAULT_DTMF_TIMEOUT 3000 /* samples */ #define DEFAULT_DTMF_TIMEOUT 3000 /*!< samples */
static int dtmftimeout = DEFAULT_DTMF_TIMEOUT; static int dtmftimeout = DEFAULT_DTMF_TIMEOUT;
static int rtpstart = 0; static int rtpstart = 0; /*!< First port for RTP sessions (set in rtp.conf) */
static int rtpend = 0; static int rtpend = 0; /*!< Last port for RTP sessions (set in rtp.conf) */
static int rtpdebug = 0; /* Are we debugging? */ static int rtpdebug = 0; /*!< Are we debugging? */
static struct sockaddr_in rtpdebugaddr; /* Debug packets to/from this host */ static struct sockaddr_in rtpdebugaddr; /*!< Debug packets to/from this host */
#ifdef SO_NO_CHECK #ifdef SO_NO_CHECK
static int nochecksums = 0; static int nochecksums = 0;
#endif #endif
/* The value of each payload format mapping: */ /*! \brief The value of each payload format mapping: */
struct rtpPayloadType { struct rtpPayloadType {
int isAstFormat; /* whether the following code is an AST_FORMAT */ int isAstFormat; /*!< whether the following code is an AST_FORMAT */
int code; int code;
}; };
#define MAX_RTP_PT 256 #define MAX_RTP_PT 256
#define FLAG_3389_WARNING (1 << 0) #define FLAG_3389_WARNING (1 << 0)
#define FLAG_NAT_ACTIVE (3 << 1) #define FLAG_NAT_ACTIVE (3 << 1)
#define FLAG_NAT_INACTIVE (0 << 1) #define FLAG_NAT_INACTIVE (0 << 1)
#define FLAG_NAT_INACTIVE_NOWARN (1 << 1) #define FLAG_NAT_INACTIVE_NOWARN (1 << 1)
/*! \brief RTP session description */
struct ast_rtp { struct ast_rtp {
int s; int s;
char resp; char resp;
struct ast_frame f; struct ast_frame f;
unsigned char rawdata[8192 + AST_FRIENDLY_OFFSET]; unsigned char rawdata[8192 + AST_FRIENDLY_OFFSET];
/*! Synchronization source, RFC 3550, page 10. */ unsigned int ssrc; /*!< Synchronization source, RFC 3550, page 10. */
unsigned int ssrc;
unsigned int lastts; unsigned int lastts;
unsigned int lastdigitts; unsigned int lastdigitts;
unsigned int lastrxts; unsigned int lastrxts;
@ -106,25 +106,21 @@ struct ast_rtp {
unsigned int dtmfduration; unsigned int dtmfduration;
int nat; int nat;
unsigned int flags; unsigned int flags;
/*! Socket representation of the local endpoint. */ struct sockaddr_in us; /*!< Socket representation of the local endpoint. */
struct sockaddr_in us; struct sockaddr_in them; /*!< Socket representation of the remote endpoint. */
/*! Socket representation of the remote endpoint. */
struct sockaddr_in them;
struct timeval rxcore; struct timeval rxcore;
struct timeval txcore; struct timeval txcore;
struct timeval dtmfmute; struct timeval dtmfmute;
struct ast_smoother *smoother; struct ast_smoother *smoother;
int *ioid; int *ioid;
/*! Sequence number, RFC 3550, page 13. */ unsigned short seqno; /*!< Sequence number, RFC 3550, page 13. */
unsigned short seqno;
unsigned short rxseqno; unsigned short rxseqno;
struct sched_context *sched; struct sched_context *sched;
struct io_context *io; struct io_context *io;
void *data; void *data;
ast_rtp_callback callback; ast_rtp_callback callback;
struct rtpPayloadType current_RTP_PT[MAX_RTP_PT]; struct rtpPayloadType current_RTP_PT[MAX_RTP_PT];
/*! a cache for the result of rtp_lookup_code(): */ int rtp_lookup_code_cache_isAstFormat; /*!< a cache for the result of rtp_lookup_code(): */
int rtp_lookup_code_cache_isAstFormat;
int rtp_lookup_code_cache_code; int rtp_lookup_code_cache_code;
int rtp_lookup_code_cache_result; int rtp_lookup_code_cache_result;
struct ast_rtcp *rtcp; struct ast_rtcp *rtcp;
@ -141,15 +137,13 @@ struct ast_rtp {
* *
*/ */
struct ast_rtcp { struct ast_rtcp {
/*! Socket */ int s; /*!< Socket */
int s; struct sockaddr_in us; /*!< Socket representation of the local endpoint. */
/*! Socket representation of the local endpoint. */ struct sockaddr_in them; /*!< Socket representation of the remote endpoint. */
struct sockaddr_in us;
/*! Socket representation of the remote endpoint. */
struct sockaddr_in them;
}; };
static struct ast_rtp_protocol *protos = NULL; /*! \brief List of current sessions */
static AST_LIST_HEAD_STATIC(protos, ast_rtp_protocol);
int ast_rtp_fd(struct ast_rtp *rtp) int ast_rtp_fd(struct ast_rtp *rtp)
{ {
@ -229,9 +223,8 @@ static struct ast_frame *process_cisco_dtmf(struct ast_rtp *rtp, unsigned char *
struct ast_frame *f = NULL; struct ast_frame *f = NULL;
event = ntohl(*((unsigned int *)(data))); event = ntohl(*((unsigned int *)(data)));
event &= 0x001F; event &= 0x001F;
#if 0 if (option_debug > 2 || rtpdebug)
printf("Cisco Digit: %08x (len = %d)\n", event, len); ast_log(LOG_DEBUG, "Cisco DTMF Digit: %08x (len = %d)\n", event, len);
#endif
if (event < 10) { if (event < 10) {
resp = '0' + event; resp = '0' + event;
} else if (event < 11) { } else if (event < 11) {
@ -269,6 +262,7 @@ static struct ast_frame *process_rfc2833(struct ast_rtp *rtp, unsigned char *dat
unsigned int duration; unsigned int duration;
char resp = 0; char resp = 0;
struct ast_frame *f = NULL; struct ast_frame *f = NULL;
event = ntohl(*((unsigned int *)(data))); event = ntohl(*((unsigned int *)(data)));
event >>= 24; event >>= 24;
event_end = ntohl(*((unsigned int *)(data))); event_end = ntohl(*((unsigned int *)(data)));
@ -276,7 +270,7 @@ static struct ast_frame *process_rfc2833(struct ast_rtp *rtp, unsigned char *dat
event_end >>= 24; event_end >>= 24;
duration = ntohl(*((unsigned int *)(data))); duration = ntohl(*((unsigned int *)(data)));
duration &= 0xFFFF; duration &= 0xFFFF;
if (rtpdebug) if (rtpdebug || option_debug > 2)
ast_log(LOG_DEBUG, "- RTP 2833 Event: %08x (len = %d)\n", event, len); ast_log(LOG_DEBUG, "- RTP 2833 Event: %08x (len = %d)\n", event, len);
if (event < 10) { if (event < 10) {
resp = '0' + event; resp = '0' + event;
@ -638,61 +632,61 @@ struct ast_frame *ast_rtp_read(struct ast_rtp *rtp)
/* The following array defines the MIME Media type (and subtype) for each /* The following array defines the MIME Media type (and subtype) for each
of our codecs, or RTP-specific data type. */ of our codecs, or RTP-specific data type. */
static struct { static struct {
struct rtpPayloadType payloadType; struct rtpPayloadType payloadType;
char* type; char* type;
char* subtype; char* subtype;
} mimeTypes[] = { } mimeTypes[] = {
{{1, AST_FORMAT_G723_1}, "audio", "G723"}, {{1, AST_FORMAT_G723_1}, "audio", "G723"},
{{1, AST_FORMAT_GSM}, "audio", "GSM"}, {{1, AST_FORMAT_GSM}, "audio", "GSM"},
{{1, AST_FORMAT_ULAW}, "audio", "PCMU"}, {{1, AST_FORMAT_ULAW}, "audio", "PCMU"},
{{1, AST_FORMAT_ALAW}, "audio", "PCMA"}, {{1, AST_FORMAT_ALAW}, "audio", "PCMA"},
{{1, AST_FORMAT_G726}, "audio", "G726-32"}, {{1, AST_FORMAT_G726}, "audio", "G726-32"},
{{1, AST_FORMAT_ADPCM}, "audio", "DVI4"}, {{1, AST_FORMAT_ADPCM}, "audio", "DVI4"},
{{1, AST_FORMAT_SLINEAR}, "audio", "L16"}, {{1, AST_FORMAT_SLINEAR}, "audio", "L16"},
{{1, AST_FORMAT_LPC10}, "audio", "LPC"}, {{1, AST_FORMAT_LPC10}, "audio", "LPC"},
{{1, AST_FORMAT_G729A}, "audio", "G729"}, {{1, AST_FORMAT_G729A}, "audio", "G729"},
{{1, AST_FORMAT_SPEEX}, "audio", "speex"}, {{1, AST_FORMAT_SPEEX}, "audio", "speex"},
{{1, AST_FORMAT_ILBC}, "audio", "iLBC"}, {{1, AST_FORMAT_ILBC}, "audio", "iLBC"},
{{0, AST_RTP_DTMF}, "audio", "telephone-event"}, {{0, AST_RTP_DTMF}, "audio", "telephone-event"},
{{0, AST_RTP_CISCO_DTMF}, "audio", "cisco-telephone-event"}, {{0, AST_RTP_CISCO_DTMF}, "audio", "cisco-telephone-event"},
{{0, AST_RTP_CN}, "audio", "CN"}, {{0, AST_RTP_CN}, "audio", "CN"},
{{1, AST_FORMAT_JPEG}, "video", "JPEG"}, {{1, AST_FORMAT_JPEG}, "video", "JPEG"},
{{1, AST_FORMAT_PNG}, "video", "PNG"}, {{1, AST_FORMAT_PNG}, "video", "PNG"},
{{1, AST_FORMAT_H261}, "video", "H261"}, {{1, AST_FORMAT_H261}, "video", "H261"},
{{1, AST_FORMAT_H263}, "video", "H263"}, {{1, AST_FORMAT_H263}, "video", "H263"},
{{1, AST_FORMAT_H263_PLUS}, "video", "h263-1998"}, {{1, AST_FORMAT_H263_PLUS}, "video", "h263-1998"},
}; };
/* Static (i.e., well-known) RTP payload types for our "AST_FORMAT..."s: /* Static (i.e., well-known) RTP payload types for our "AST_FORMAT..."s:
also, our own choices for dynamic payload types. This is our master also, our own choices for dynamic payload types. This is our master
table for transmission */ table for transmission */
static struct rtpPayloadType static_RTP_PT[MAX_RTP_PT] = { static struct rtpPayloadType static_RTP_PT[MAX_RTP_PT] = {
[0] = {1, AST_FORMAT_ULAW}, [0] = {1, AST_FORMAT_ULAW},
#ifdef USE_DEPRECATED_G726 #ifdef USE_DEPRECATED_G726
[2] = {1, AST_FORMAT_G726}, /* Technically this is G.721, but if Cisco can do it, so can we... */ [2] = {1, AST_FORMAT_G726}, /* Technically this is G.721, but if Cisco can do it, so can we... */
#endif #endif
[3] = {1, AST_FORMAT_GSM}, [3] = {1, AST_FORMAT_GSM},
[4] = {1, AST_FORMAT_G723_1}, [4] = {1, AST_FORMAT_G723_1},
[5] = {1, AST_FORMAT_ADPCM}, /* 8 kHz */ [5] = {1, AST_FORMAT_ADPCM}, /* 8 kHz */
[6] = {1, AST_FORMAT_ADPCM}, /* 16 kHz */ [6] = {1, AST_FORMAT_ADPCM}, /* 16 kHz */
[7] = {1, AST_FORMAT_LPC10}, [7] = {1, AST_FORMAT_LPC10},
[8] = {1, AST_FORMAT_ALAW}, [8] = {1, AST_FORMAT_ALAW},
[10] = {1, AST_FORMAT_SLINEAR}, /* 2 channels */ [10] = {1, AST_FORMAT_SLINEAR}, /* 2 channels */
[11] = {1, AST_FORMAT_SLINEAR}, /* 1 channel */ [11] = {1, AST_FORMAT_SLINEAR}, /* 1 channel */
[13] = {0, AST_RTP_CN}, [13] = {0, AST_RTP_CN},
[16] = {1, AST_FORMAT_ADPCM}, /* 11.025 kHz */ [16] = {1, AST_FORMAT_ADPCM}, /* 11.025 kHz */
[17] = {1, AST_FORMAT_ADPCM}, /* 22.050 kHz */ [17] = {1, AST_FORMAT_ADPCM}, /* 22.050 kHz */
[18] = {1, AST_FORMAT_G729A}, [18] = {1, AST_FORMAT_G729A},
[19] = {0, AST_RTP_CN}, /* Also used for CN */ [19] = {0, AST_RTP_CN}, /* Also used for CN */
[26] = {1, AST_FORMAT_JPEG}, [26] = {1, AST_FORMAT_JPEG},
[31] = {1, AST_FORMAT_H261}, [31] = {1, AST_FORMAT_H261},
[34] = {1, AST_FORMAT_H263}, [34] = {1, AST_FORMAT_H263},
[103] = {1, AST_FORMAT_H263_PLUS}, [103] = {1, AST_FORMAT_H263_PLUS},
[97] = {1, AST_FORMAT_ILBC}, [97] = {1, AST_FORMAT_ILBC},
[101] = {0, AST_RTP_DTMF}, [101] = {0, AST_RTP_DTMF},
[110] = {1, AST_FORMAT_SPEEX}, [110] = {1, AST_FORMAT_SPEEX},
[111] = {1, AST_FORMAT_G726}, [111] = {1, AST_FORMAT_G726},
[121] = {0, AST_RTP_CISCO_DTMF}, /* Must be type 121 */ [121] = {0, AST_RTP_CISCO_DTMF}, /* Must be type 121 */
}; };
void ast_rtp_pt_clear(struct ast_rtp* rtp) void ast_rtp_pt_clear(struct ast_rtp* rtp)
@ -741,18 +735,18 @@ static void ast_rtp_pt_copy(struct ast_rtp *dest, struct ast_rtp *src)
dest->rtp_lookup_code_cache_result = 0; dest->rtp_lookup_code_cache_result = 0;
} }
/*--- get_proto: Get channel driver interface structure */ /*! \brief Get channel driver interface structure */
static struct ast_rtp_protocol *get_proto(struct ast_channel *chan) static struct ast_rtp_protocol *get_proto(struct ast_channel *chan)
{ {
struct ast_rtp_protocol *cur; struct ast_rtp_protocol *cur;
cur = protos; AST_LIST_LOCK(&protos);
while(cur) { AST_LIST_TRAVERSE(&protos, cur, list) {
if (cur->type == chan->type) { if (cur->type == chan->type)
return cur; return cur;
}
cur = cur->next;
} }
AST_LIST_UNLOCK(&protos);
return NULL; return NULL;
} }
@ -773,13 +767,15 @@ int ast_rtp_make_compatible(struct ast_channel *dest, struct ast_channel *src)
destpr = get_proto(dest); destpr = get_proto(dest);
srcpr = get_proto(src); srcpr = get_proto(src);
if (!destpr) { if (!destpr) {
ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name); if (option_debug)
ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name);
ast_mutex_unlock(&dest->lock); ast_mutex_unlock(&dest->lock);
ast_mutex_unlock(&src->lock); ast_mutex_unlock(&src->lock);
return 0; return 0;
} }
if (!srcpr) { if (!srcpr) {
ast_log(LOG_WARNING, "Channel '%s' has no RTP, not doing anything\n", src->name); if (option_debug)
ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src->name);
ast_mutex_unlock(&dest->lock); ast_mutex_unlock(&dest->lock);
ast_mutex_unlock(&src->lock); ast_mutex_unlock(&src->lock);
return 0; return 0;
@ -809,13 +805,15 @@ int ast_rtp_make_compatible(struct ast_channel *dest, struct ast_channel *src)
ast_rtp_pt_copy(vdestp, vsrcp); ast_rtp_pt_copy(vdestp, vsrcp);
ast_mutex_unlock(&dest->lock); ast_mutex_unlock(&dest->lock);
ast_mutex_unlock(&src->lock); ast_mutex_unlock(&src->lock);
ast_log(LOG_DEBUG, "Seeded SDP of '%s' with that of '%s'\n", dest->name, src->name); if (option_debug)
ast_log(LOG_DEBUG, "Seeded SDP of '%s' with that of '%s'\n", dest->name, src->name);
return 1; return 1;
} }
/* Make a note of a RTP paymoad type that was seen in a SDP "m=" line. */ /*! \brief Make a note of a RTP paymoad type that was seen in a SDP "m=" line.
/* By default, use the well-known value for this type (although it may */ * By default, use the well-known value for this type (although it may
/* still be set to a different value by a subsequent "a=rtpmap:" line): */ * still be set to a different value by a subsequent "a=rtpmap:" line)
*/
void ast_rtp_set_m_type(struct ast_rtp* rtp, int pt) void ast_rtp_set_m_type(struct ast_rtp* rtp, int pt)
{ {
if (pt < 0 || pt > MAX_RTP_PT) if (pt < 0 || pt > MAX_RTP_PT)
@ -826,11 +824,10 @@ void ast_rtp_set_m_type(struct ast_rtp* rtp, int pt)
} }
} }
/* Make a note of a RTP payload type (with MIME type) that was seen in */ /*! \brief Make a note of a RTP payload type (with MIME type) that was seen in
/* a SDP "a=rtpmap:" line. */ a SDP "a=rtpmap:" line. */
void ast_rtp_set_rtpmap_type(struct ast_rtp* rtp, int pt, void ast_rtp_set_rtpmap_type(struct ast_rtp* rtp, int pt,
char* mimeType, char* mimeSubtype) char* mimeType, char* mimeSubtype)
{ {
int i; int i;
@ -846,8 +843,8 @@ void ast_rtp_set_rtpmap_type(struct ast_rtp* rtp, int pt,
} }
} }
/* Return the union of all of the codecs that were set by rtp_set...() calls */ /*! \brief Return the union of all of the codecs that were set by rtp_set...() calls
/* They're returned as two distinct sets: AST_FORMATs, and AST_RTPs */ * They're returned as two distinct sets: AST_FORMATs, and AST_RTPs */
void ast_rtp_get_current_formats(struct ast_rtp* rtp, void ast_rtp_get_current_formats(struct ast_rtp* rtp,
int* astFormats, int* nonAstFormats) { int* astFormats, int* nonAstFormats) {
int pt; int pt;
@ -879,7 +876,7 @@ struct rtpPayloadType ast_rtp_lookup_pt(struct ast_rtp* rtp, int pt)
return result; return result;
} }
/* Looks up an RTP code out of our *static* outbound list */ /*! \brief Looks up an RTP code out of our *static* outbound list */
int ast_rtp_lookup_code(struct ast_rtp* rtp, const int isAstFormat, const int code) { int ast_rtp_lookup_code(struct ast_rtp* rtp, const int isAstFormat, const int code) {
int pt; int pt;
@ -1533,44 +1530,42 @@ int ast_rtp_write(struct ast_rtp *rtp, struct ast_frame *_f)
return 0; return 0;
} }
/*--- ast_rtp_proto_unregister: Unregister interface to channel driver */ /*! \brief Unregister interface to channel driver */
void ast_rtp_proto_unregister(struct ast_rtp_protocol *proto) void ast_rtp_proto_unregister(struct ast_rtp_protocol *proto)
{ {
struct ast_rtp_protocol *cur, *prev; struct ast_rtp_protocol *cur;
cur = protos; AST_LIST_LOCK(&protos);
prev = NULL; AST_LIST_TRAVERSE_SAFE_BEGIN(&protos, cur, list) {
while(cur) {
if (cur == proto) { if (cur == proto) {
if (prev) AST_LIST_REMOVE_CURRENT(&protos, list);
prev->next = proto->next; break;
else
protos = proto->next;
return;
} }
prev = cur;
cur = cur->next;
} }
AST_LIST_TRAVERSE_SAFE_END
AST_LIST_UNLOCK(&protos);
} }
/*--- ast_rtp_proto_register: Register interface to channel driver */ /*! \brief Register interface to channel driver */
int ast_rtp_proto_register(struct ast_rtp_protocol *proto) int ast_rtp_proto_register(struct ast_rtp_protocol *proto)
{ {
struct ast_rtp_protocol *cur; struct ast_rtp_protocol *cur;
cur = protos;
while(cur) { AST_LIST_LOCK(&protos);
AST_LIST_TRAVERSE(&protos, cur, list) {
if (cur->type == proto->type) { if (cur->type == proto->type) {
ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type); ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
AST_LIST_UNLOCK(&protos);
return -1; return -1;
} }
cur = cur->next;
} }
proto->next = protos; AST_LIST_INSERT_HEAD(&protos, proto, list);
protos = proto; AST_LIST_UNLOCK(&protos);
return 0; return 0;
} }
/* ast_rtp_bridge: Bridge calls. If possible and allowed, initiate /*! \brief Bridge calls. If possible and allowed, initiate
re-invite so the peers exchange media directly outside re-invite so the peers exchange media directly outside
of Asterisk. */ of Asterisk. */
enum ast_bridge_result ast_rtp_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms) enum ast_bridge_result ast_rtp_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
@ -1935,7 +1930,7 @@ void ast_rtp_reload(void)
} }
/*--- ast_rtp_init: Initialize the RTP system in Asterisk */ /*! \brief Initialize the RTP system in Asterisk */
void ast_rtp_init(void) void ast_rtp_init(void)
{ {
ast_cli_register(&cli_debug); ast_cli_register(&cli_debug);

Loading…
Cancel
Save