Bug #6109: Fix unprotected list in RTP, implement AST_LIST macros, update doxygen...
authorOlle Johansson <oej@edvina.net>
Tue, 3 Jan 2006 09:30:19 +0000 (09:30 +0000)
committerOlle Johansson <oej@edvina.net>
Tue, 3 Jan 2006 09:30:19 +0000 (09:30 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@7730 65c4cc65-6c06-0410-ace0-fbb531ad65f3

include/asterisk/rtp.h
rtp.c

index 9654806..27e979a 100644 (file)
 #ifndef _ASTERISK_RTP_H
 #define _ASTERISK_RTP_H
 
+#include <netinet/in.h>
+
 #include "asterisk/frame.h"
 #include "asterisk/io.h"
 #include "asterisk/sched.h"
 #include "asterisk/channel.h"
-
-#include <netinet/in.h>
+#include "asterisk/linkedlists.h"
 
 #if defined(__cplusplus) || defined(c_plusplus)
 extern "C" {
@@ -48,15 +49,15 @@ extern "C" {
 #define AST_RTP_MAX             AST_RTP_CISCO_DTMF
 
 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);
-       /* 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);
-       /* 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 get_codec)(struct ast_channel *chan);
        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);
 
-/*  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);
-/* Set payload types to defaults */
+/*! \brief Set payload types to defaults */
 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_rtpmap_type(struct ast_rtp* rtp, int pt,
                         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);
 int ast_rtp_lookup_code(struct ast_rtp* rtp, int isAstFormat, int code);
 
 void ast_rtp_get_current_formats(struct ast_rtp* rtp,
                             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);
 
-/* 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);
 
 void ast_rtp_setnat(struct ast_rtp *rtp, int nat);
diff --git a/rtp.c b/rtp.c
index afdd6d1..3f0f745 100644 (file)
--- a/rtp.c
+++ b/rtp.c
@@ -61,38 +61,38 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
 #define RTP_MTU                1200
 
-#define DEFAULT_DTMF_TIMEOUT 3000 /* samples */
+#define DEFAULT_DTMF_TIMEOUT 3000      /*!< samples */
 
 static int dtmftimeout = DEFAULT_DTMF_TIMEOUT;
 
-static int rtpstart = 0;
-static int rtpend = 0;
-static int rtpdebug = 0;               /* Are we debugging? */
-static struct sockaddr_in rtpdebugaddr;        /* Debug packets to/from this host */
+static int rtpstart = 0;               /*!< First port for RTP sessions (set in rtp.conf) */
+static int rtpend = 0;                 /*!< Last port for RTP sessions (set in rtp.conf) */
+static int rtpdebug = 0;               /*!< Are we debugging? */
+static struct sockaddr_in rtpdebugaddr;        /*!< Debug packets to/from this host */
 #ifdef SO_NO_CHECK
 static int nochecksums = 0;
 #endif
 
-/* The value of each payload format mapping: */
+/*! \brief The value of each payload format mapping: */
 struct rtpPayloadType {
-       int isAstFormat;        /* whether the following code is an AST_FORMAT */
+       int isAstFormat;        /*!< whether the following code is an AST_FORMAT */
        int code;
 };
 
-#define MAX_RTP_PT 256
+#define MAX_RTP_PT                     256
 
 #define FLAG_3389_WARNING              (1 << 0)
 #define FLAG_NAT_ACTIVE                        (3 << 1)
 #define FLAG_NAT_INACTIVE              (0 << 1)
 #define FLAG_NAT_INACTIVE_NOWARN       (1 << 1)
 
+/*! \brief RTP session description */
 struct ast_rtp {
        int s;
        char resp;
        struct ast_frame f;
        unsigned char rawdata[8192 + AST_FRIENDLY_OFFSET];
-       /*! Synchronization source, RFC 3550, page 10. */
-       unsigned int ssrc;
+       unsigned int ssrc;              /*!< Synchronization source, RFC 3550, page 10. */
        unsigned int lastts;
        unsigned int lastdigitts;
        unsigned int lastrxts;
@@ -106,25 +106,21 @@ struct ast_rtp {
        unsigned int dtmfduration;
        int nat;
        unsigned int flags;
-       /*! Socket representation of the local endpoint. */
-       struct sockaddr_in us;
-       /*! Socket representation of the remote endpoint. */
-       struct sockaddr_in them;
+       struct sockaddr_in us;          /*!< Socket representation of the local endpoint. */
+       struct sockaddr_in them;        /*!< Socket representation of the remote endpoint. */
        struct timeval rxcore;
        struct timeval txcore;
        struct timeval dtmfmute;
        struct ast_smoother *smoother;
        int *ioid;
-       /*! Sequence number, RFC 3550, page 13. */
-       unsigned short seqno;
+       unsigned short seqno;           /*!< Sequence number, RFC 3550, page 13. */
        unsigned short rxseqno;
        struct sched_context *sched;
        struct io_context *io;
        void *data;
        ast_rtp_callback callback;
        struct rtpPayloadType current_RTP_PT[MAX_RTP_PT];
-       /*! a cache for the result of rtp_lookup_code(): */
-       int rtp_lookup_code_cache_isAstFormat;
+       int rtp_lookup_code_cache_isAstFormat; /*!< a cache for the result of rtp_lookup_code(): */
        int rtp_lookup_code_cache_code;
        int rtp_lookup_code_cache_result;
        struct ast_rtcp *rtcp;
@@ -141,15 +137,13 @@ struct ast_rtp {
  * 
  */
 struct ast_rtcp {
-       /*! Socket */
-       int s;
-       /*! Socket representation of the local endpoint. */
-       struct sockaddr_in us;
-       /*! Socket representation of the remote endpoint. */
-       struct sockaddr_in them;
+       int s;                          /*!< Socket */
+       struct sockaddr_in us;          /*!< Socket representation of the local endpoint. */
+       struct sockaddr_in them;        /*!< Socket representation of the remote endpoint. */
 };
 
-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)
 {
@@ -229,9 +223,8 @@ static struct ast_frame *process_cisco_dtmf(struct ast_rtp *rtp, unsigned char *
        struct ast_frame *f = NULL;
        event = ntohl(*((unsigned int *)(data)));
        event &= 0x001F;
-#if 0
-       printf("Cisco Digit: %08x (len = %d)\n", event, len);
-#endif 
+       if (option_debug > 2 || rtpdebug)
+               ast_log(LOG_DEBUG, "Cisco DTMF Digit: %08x (len = %d)\n", event, len);
        if (event < 10) {
                resp = '0' + event;
        } else if (event < 11) {
@@ -269,6 +262,7 @@ static struct ast_frame *process_rfc2833(struct ast_rtp *rtp, unsigned char *dat
        unsigned int duration;
        char resp = 0;
        struct ast_frame *f = NULL;
+
        event = ntohl(*((unsigned int *)(data)));
        event >>= 24;
        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;
        duration = ntohl(*((unsigned int *)(data)));
        duration &= 0xFFFF;
-       if (rtpdebug)
+       if (rtpdebug || option_debug > 2)
                ast_log(LOG_DEBUG, "- RTP 2833 Event: %08x (len = %d)\n", event, len);
        if (event < 10) {
                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
    of our codecs, or RTP-specific data type. */
 static struct {
-  struct rtpPayloadType payloadType;
-  char* type;
-  char* subtype;
+       struct rtpPayloadType payloadType;
+       char* type;
+       char* subtype;
 } mimeTypes[] = {
-  {{1, AST_FORMAT_G723_1}, "audio", "G723"},
-  {{1, AST_FORMAT_GSM}, "audio", "GSM"},
-  {{1, AST_FORMAT_ULAW}, "audio", "PCMU"},
-  {{1, AST_FORMAT_ALAW}, "audio", "PCMA"},
-  {{1, AST_FORMAT_G726}, "audio", "G726-32"},
-  {{1, AST_FORMAT_ADPCM}, "audio", "DVI4"},
-  {{1, AST_FORMAT_SLINEAR}, "audio", "L16"},
-  {{1, AST_FORMAT_LPC10}, "audio", "LPC"},
-  {{1, AST_FORMAT_G729A}, "audio", "G729"},
-  {{1, AST_FORMAT_SPEEX}, "audio", "speex"},
-  {{1, AST_FORMAT_ILBC}, "audio", "iLBC"},
-  {{0, AST_RTP_DTMF}, "audio", "telephone-event"},
-  {{0, AST_RTP_CISCO_DTMF}, "audio", "cisco-telephone-event"},
-  {{0, AST_RTP_CN}, "audio", "CN"},
-  {{1, AST_FORMAT_JPEG}, "video", "JPEG"},
-  {{1, AST_FORMAT_PNG}, "video", "PNG"},
-  {{1, AST_FORMAT_H261}, "video", "H261"},
-  {{1, AST_FORMAT_H263}, "video", "H263"},
-  {{1, AST_FORMAT_H263_PLUS}, "video", "h263-1998"},
+       {{1, AST_FORMAT_G723_1}, "audio", "G723"},
+       {{1, AST_FORMAT_GSM}, "audio", "GSM"},
+       {{1, AST_FORMAT_ULAW}, "audio", "PCMU"},
+       {{1, AST_FORMAT_ALAW}, "audio", "PCMA"},
+       {{1, AST_FORMAT_G726}, "audio", "G726-32"},
+       {{1, AST_FORMAT_ADPCM}, "audio", "DVI4"},
+       {{1, AST_FORMAT_SLINEAR}, "audio", "L16"},
+       {{1, AST_FORMAT_LPC10}, "audio", "LPC"},
+       {{1, AST_FORMAT_G729A}, "audio", "G729"},
+       {{1, AST_FORMAT_SPEEX}, "audio", "speex"},
+       {{1, AST_FORMAT_ILBC}, "audio", "iLBC"},
+       {{0, AST_RTP_DTMF}, "audio", "telephone-event"},
+       {{0, AST_RTP_CISCO_DTMF}, "audio", "cisco-telephone-event"},
+       {{0, AST_RTP_CN}, "audio", "CN"},
+       {{1, AST_FORMAT_JPEG}, "video", "JPEG"},
+       {{1, AST_FORMAT_PNG}, "video", "PNG"},
+       {{1, AST_FORMAT_H261}, "video", "H261"},
+       {{1, AST_FORMAT_H263}, "video", "H263"},
+       {{1, AST_FORMAT_H263_PLUS}, "video", "h263-1998"},
 };
 
 /* 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
    table for transmission */
 static struct rtpPayloadType static_RTP_PT[MAX_RTP_PT] = {
-  [0] = {1, AST_FORMAT_ULAW},
+       [0] = {1, AST_FORMAT_ULAW},
 #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
-  [3] = {1, AST_FORMAT_GSM},
-  [4] = {1, AST_FORMAT_G723_1},
-  [5] = {1, AST_FORMAT_ADPCM}, /* 8 kHz */
-  [6] = {1, AST_FORMAT_ADPCM}, /* 16 kHz */
-  [7] = {1, AST_FORMAT_LPC10},
-  [8] = {1, AST_FORMAT_ALAW},
-  [10] = {1, AST_FORMAT_SLINEAR}, /* 2 channels */
-  [11] = {1, AST_FORMAT_SLINEAR}, /* 1 channel */
-  [13] = {0, AST_RTP_CN},
-  [16] = {1, AST_FORMAT_ADPCM}, /* 11.025 kHz */
-  [17] = {1, AST_FORMAT_ADPCM}, /* 22.050 kHz */
-  [18] = {1, AST_FORMAT_G729A},
-  [19] = {0, AST_RTP_CN},              /* Also used for CN */
-  [26] = {1, AST_FORMAT_JPEG},
-  [31] = {1, AST_FORMAT_H261},
-  [34] = {1, AST_FORMAT_H263},
-  [103] = {1, AST_FORMAT_H263_PLUS},
-  [97] = {1, AST_FORMAT_ILBC},
-  [101] = {0, AST_RTP_DTMF},
-  [110] = {1, AST_FORMAT_SPEEX},
-  [111] = {1, AST_FORMAT_G726},
-  [121] = {0, AST_RTP_CISCO_DTMF}, /* Must be type 121 */
+       [3] = {1, AST_FORMAT_GSM},
+       [4] = {1, AST_FORMAT_G723_1},
+       [5] = {1, AST_FORMAT_ADPCM}, /* 8 kHz */
+       [6] = {1, AST_FORMAT_ADPCM}, /* 16 kHz */
+       [7] = {1, AST_FORMAT_LPC10},
+       [8] = {1, AST_FORMAT_ALAW},
+       [10] = {1, AST_FORMAT_SLINEAR}, /* 2 channels */
+       [11] = {1, AST_FORMAT_SLINEAR}, /* 1 channel */
+       [13] = {0, AST_RTP_CN},
+       [16] = {1, AST_FORMAT_ADPCM}, /* 11.025 kHz */
+       [17] = {1, AST_FORMAT_ADPCM}, /* 22.050 kHz */
+       [18] = {1, AST_FORMAT_G729A},
+       [19] = {0, AST_RTP_CN},         /* Also used for CN */
+       [26] = {1, AST_FORMAT_JPEG},
+       [31] = {1, AST_FORMAT_H261},
+       [34] = {1, AST_FORMAT_H263},
+       [103] = {1, AST_FORMAT_H263_PLUS},
+       [97] = {1, AST_FORMAT_ILBC},
+       [101] = {0, AST_RTP_DTMF},
+       [110] = {1, AST_FORMAT_SPEEX},
+       [111] = {1, AST_FORMAT_G726},
+       [121] = {0, AST_RTP_CISCO_DTMF}, /* Must be type 121 */
 };
 
 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;
 }
 
-/*--- get_proto: Get channel driver interface structure */
+/*! \brief Get channel driver interface structure */
 static struct ast_rtp_protocol *get_proto(struct ast_channel *chan)
 {
        struct ast_rtp_protocol *cur;
 
-       cur = protos;
-       while(cur) {
-               if (cur->type == chan->type) {
+       AST_LIST_LOCK(&protos);
+       AST_LIST_TRAVERSE(&protos, cur, list) {
+               if (cur->type == chan->type)
                        return cur;
-               }
-               cur = cur->next;
        }
+       AST_LIST_UNLOCK(&protos);
+
        return NULL;
 }
 
@@ -773,13 +767,15 @@ int ast_rtp_make_compatible(struct ast_channel *dest, struct ast_channel *src)
        destpr = get_proto(dest);
        srcpr = get_proto(src);
        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(&src->lock);
                return 0;
        }
        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(&src->lock);
                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_mutex_unlock(&dest->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;
 }
 
-/* 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 */
-/* still be set to a different value by a subsequent "a=rtpmap:" 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 
+ * 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) 
 {
        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 */
-/* a SDP "a=rtpmap:" line. */
+/*! \brief Make a note of a RTP payload type (with MIME type) that was seen in
+       a SDP "a=rtpmap:" line. */
 void ast_rtp_set_rtpmap_type(struct ast_rtp* rtp, int pt,
                         char* mimeType, char* mimeSubtype) 
-                        
 {
        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 */
-/* They're returned as two distinct sets: AST_FORMATs, and AST_RTPs */
+/*! \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 */
 void ast_rtp_get_current_formats(struct ast_rtp* rtp,
                             int* astFormats, int* nonAstFormats) {
        int pt;
@@ -879,7 +876,7 @@ struct rtpPayloadType ast_rtp_lookup_pt(struct ast_rtp* rtp, int pt)
        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 pt;
@@ -1533,44 +1530,42 @@ int ast_rtp_write(struct ast_rtp *rtp, struct ast_frame *_f)
        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)
 {
-       struct ast_rtp_protocol *cur, *prev;
+       struct ast_rtp_protocol *cur;
 
-       cur = protos;
-       prev = NULL;
-       while(cur) {
+       AST_LIST_LOCK(&protos);
+       AST_LIST_TRAVERSE_SAFE_BEGIN(&protos, cur, list) {      
                if (cur == proto) {
-                       if (prev)
-                               prev->next = proto->next;
-                       else
-                               protos = proto->next;
-                       return;
+                       AST_LIST_REMOVE_CURRENT(&protos, list);
+                       break;
                }
-               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)
 {
        struct ast_rtp_protocol *cur;
-       cur = protos;
-       while(cur) {
+
+       AST_LIST_LOCK(&protos);
+       AST_LIST_TRAVERSE(&protos, cur, list) { 
                if (cur->type == proto->type) {
                        ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
+                       AST_LIST_UNLOCK(&protos);
                        return -1;
                }
-               cur = cur->next;
        }
-       proto->next = protos;
-       protos = proto;
+       AST_LIST_INSERT_HEAD(&protos, proto, list);
+       AST_LIST_UNLOCK(&protos);
+       
        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 
        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)
@@ -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)
 {
        ast_cli_register(&cli_debug);