CHANGES: Change md file extension to txt.
[asterisk/asterisk.git] / channels / iax2 / parser.c
index 5d1a8ca..8683938 100644 (file)
@@ -20,7 +20,7 @@
  *
  * \brief Implementation of Inter-Asterisk eXchange Protocol, v 2
  *
- * \author Mark Spencer <markster@digium.com> 
+ * \author Mark Spencer <markster@digium.com>
  */
 
 /*** MODULEINFO
@@ -29,8 +29,6 @@
 
 #include "asterisk.h"
 
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
@@ -41,16 +39,24 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/config.h"
 #include "asterisk/lock.h"
 #include "asterisk/threadstorage.h"
+#include "asterisk/netsock2.h"
+#include "asterisk/format_cache.h"
+#include "asterisk/format_compatibility.h"
 
 #include "include/iax2.h"
 #include "include/parser.h"
 #include "include/provision.h"
+#include "include/codec_pref.h"
 
 static int frames = 0;
 static int iframes = 0;
 static int oframes = 0;
 
-#if !defined(LOW_MEMORY)
+#if (defined(LOW_MEMORY) || defined(MALLOC_DEBUG)) && !defined(NO_FRAME_CACHE)
+#define NO_FRAME_CACHE
+#endif
+
+#if !defined(NO_FRAME_CACHE)
 static void frame_cache_cleanup(void *data);
 
 /*! \brief A per-thread cache of iax_frame structures */
@@ -83,13 +89,23 @@ static void (*errorf)(const char *str) = internalerror;
 
 static void dump_addr(char *output, int maxlen, void *value, int len)
 {
-       struct sockaddr_in sin;
-       if (len == (int)sizeof(sin)) {
-               memcpy(&sin, value, len);
-               snprintf(output, maxlen, "IPV4 %s:%d", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
+       struct ast_sockaddr addr;
+
+       if (len == (int)sizeof(struct sockaddr_in)) {
+               addr.ss.ss_family = AF_INET;
+       } else if (len == (int) sizeof(struct sockaddr_in6)) {
+               addr.ss.ss_family = AF_INET6;
        } else {
                ast_copy_string(output, "Invalid Address", maxlen);
+               return;
        }
+
+       memcpy(&addr, value, len);
+       addr.len = len;
+
+       snprintf(output, maxlen, "%s %s",
+                               ast_sockaddr_is_ipv4(&addr) || ast_sockaddr_is_ipv4_mapped(&addr) ? "IPV4" : "IPV6",
+                               ast_sockaddr_stringify(&addr));
 }
 
 static void dump_string_hex(char *output, int maxlen, void *value, int len)
@@ -97,7 +113,7 @@ static void dump_string_hex(char *output, int maxlen, void *value, int len)
        int i = 0;
 
        while (len-- && (i + 1) * 4 < maxlen) {
-               sprintf(output + (4 * i), "\\x%2.2x", *((unsigned char *)value + i));
+               sprintf(output + (4 * i), "\\x%02hhx", *((unsigned char *)value + i));
                i++;
        }
 }
@@ -113,7 +129,7 @@ static void dump_string(char *output, int maxlen, void *value, int len)
 
 static void dump_prefs(char *output, int maxlen, void *value, int len)
 {
-       struct ast_codec_pref pref;
+       struct iax2_codec_pref pref;
        int total_len = 0;
 
        maxlen--;
@@ -124,10 +140,10 @@ static void dump_prefs(char *output, int maxlen, void *value, int len)
 
        strncpy(output, value, maxlen);
        output[maxlen] = '\0';
-       
-       ast_codec_pref_convert(&pref, output, total_len, 0);
+
+       iax2_codec_pref_convert(&pref, output, total_len, 0);
        memset(output,0,total_len);
-       ast_codec_pref_string(&pref, output, total_len);
+       iax2_codec_pref_string(&pref, output, total_len);
 }
 
 static void dump_int(char *output, int maxlen, void *value, int len)
@@ -135,7 +151,7 @@ static void dump_int(char *output, int maxlen, void *value, int len)
        if (len == (int)sizeof(unsigned int))
                snprintf(output, maxlen, "%lu", (unsigned long)ntohl(get_unaligned_uint32(value)));
        else
-               ast_copy_string(output, "Invalid INT", maxlen); 
+               ast_copy_string(output, "Invalid INT", maxlen);
 }
 
 static void dump_short(char *output, int maxlen, void *value, int len)
@@ -165,19 +181,30 @@ static void dump_datetime(char *output, int maxlen, void *value, int len)
                tm.tm_mday = (val >> 16) & 0x1f;
                tm.tm_mon  = ((val >> 21) & 0x0f) - 1;
                tm.tm_year = ((val >> 25) & 0x7f) + 100;
-               ast_strftime(output, maxlen, "%Y-%m-%d  %T", &tm); 
+               ast_strftime(output, maxlen, "%Y-%m-%d  %T", &tm);
        } else
                ast_copy_string(output, "Invalid DATETIME format!", maxlen);
 }
 
 static void dump_ipaddr(char *output, int maxlen, void *value, int len)
 {
-       struct sockaddr_in sin;
-       if (len == (int)sizeof(unsigned int)) {
-               memcpy(&sin.sin_addr, value, len);
-               snprintf(output, maxlen, "%s", ast_inet_ntoa(sin.sin_addr));
-       } else
+       struct ast_sockaddr addr;
+       char *str_addr;
+
+       if (len == (int)sizeof(struct sockaddr_in)) {
+               addr.ss.ss_family = AF_INET;
+       } else if (len == (int)sizeof(struct sockaddr_in6)) {
+               addr.ss.ss_family = AF_INET6;
+       } else {
                ast_copy_string(output, "Invalid IPADDR", maxlen);
+               return;
+       }
+
+       memcpy(&addr, value, len);
+       addr.len = len;
+
+       str_addr = ast_sockaddr_stringify(&addr);
+       ast_copy_string(output, str_addr, maxlen);
 }
 
 
@@ -239,11 +266,12 @@ static void dump_prov(char *output, int maxlen, void *value, int len)
        dump_prov_ies(output, maxlen, value, len);
 }
 
-static struct iax2_ie {
+struct iax2_ie {
        int ie;
        char *name;
        void (*dump)(char *output, int maxlen, void *value, int len);
-} infoelts[] = {
+};
+static struct iax2_ie infoelts[] = {
        { IAX_IE_CALLED_NUMBER, "CALLED NUMBER", dump_string },
        { IAX_IE_CALLING_NUMBER, "CALLING NUMBER", dump_string },
        { IAX_IE_CALLING_ANI, "ANI", dump_string },
@@ -342,7 +370,7 @@ static void dump_prov_ies(char *output, int maxlen, unsigned char *iedata, int l
        char tmp[256];
        if (len < 2)
                return;
-       strcpy(output, "\n"); 
+       strcpy(output, "\n");
        maxlen -= strlen(output); output += strlen(output);
        while(len > 2) {
                ie = iedata[0];
@@ -391,7 +419,8 @@ static void dump_ies(unsigned char *iedata, int len)
        int x;
        int found;
        char interp[1024];
-       char tmp[1024];
+       char tmp[1046];
+
        if (len < 2)
                return;
        while(len > 2) {
@@ -562,7 +591,7 @@ void iax_frame_subclass2str(enum iax_frame_subclass subclass, char *str, size_t
        ast_copy_string(str, cmd, len);
 }
 
-void iax_showframe(struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, struct sockaddr_in *sin, int datalen)
+void iax_showframe(struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, struct ast_sockaddr *addr, int datalen)
 {
        const char *framelist[] = {
                "(0?)",
@@ -605,7 +634,7 @@ void iax_showframe(struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, s
                "CNLINE ",
                "REDIR  ",
                "T38PARM",
-               "CONTRCC",
+               "CC ERR!",/* This must never go across an IAX link. */
                "SRCCHG ",
                "READACT",
                "AOC    ",
@@ -675,19 +704,22 @@ void iax_showframe(struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, s
                snprintf(subclass2, sizeof(subclass2), "%d", fh->csub);
                subclass = subclass2;
        }
-       snprintf(tmp, sizeof(tmp), 
-                "%s-Frame Retry[%s] -- OSeqno: %3.3d ISeqno: %3.3d Type: %s Subclass: %s\n",
+
+       snprintf(tmp, sizeof(tmp),
+               "%s-Frame Retry[%s] -- OSeqno: %3.3d ISeqno: %3.3d Type: %s Subclass: %s\n",
                 dir,
                 retries, fh->oseqno, fh->iseqno, class, subclass);
        outputf(tmp);
-       snprintf(tmp, sizeof(tmp), 
-                "   Timestamp: %05lums  SCall: %5.5d  DCall: %5.5d [%s:%d]\n",
-                (unsigned long)ntohl(fh->ts),
-                ntohs(fh->scallno) & ~IAX_FLAG_FULL, ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS,
-                ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
+       snprintf(tmp, sizeof(tmp), "   Timestamp: %05lums  SCall: %5.5d  DCall: %5.5d %s\n",
+                       (unsigned long)ntohl(fh->ts),
+                       ntohs(fh->scallno) & ~IAX_FLAG_FULL,
+                       ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS,
+                       ast_sockaddr_stringify(addr));
+
        outputf(tmp);
        if (fh->type == AST_FRAME_IAX)
                dump_ies(fh->iedata, datalen);
+
 }
 
 int iax_ie_append_raw(struct iax_ie_data *ied, unsigned char ie, const void *data, int datalen)
@@ -705,9 +737,9 @@ int iax_ie_append_raw(struct iax_ie_data *ied, unsigned char ie, const void *dat
        return 0;
 }
 
-int iax_ie_append_addr(struct iax_ie_data *ied, unsigned char ie, const struct sockaddr_in *sin)
+int iax_ie_append_addr(struct iax_ie_data *ied, unsigned char ie, const struct ast_sockaddr *addr)
 {
-       return iax_ie_append_raw(ied, ie, sin, (int)sizeof(struct sockaddr_in));
+       return iax_ie_append_raw(ied, ie, addr, addr->len);
 }
 
 int iax_ie_append_versioned_uint64(struct iax_ie_data *ied, unsigned char ie, unsigned char version, uint64_t value)
@@ -720,14 +752,14 @@ int iax_ie_append_versioned_uint64(struct iax_ie_data *ied, unsigned char ie, un
        return iax_ie_append_raw(ied, ie, &newval, (int) sizeof(newval));
 }
 
-int iax_ie_append_int(struct iax_ie_data *ied, unsigned char ie, unsigned int value) 
+int iax_ie_append_int(struct iax_ie_data *ied, unsigned char ie, unsigned int value)
 {
        unsigned int newval;
        newval = htonl(value);
        return iax_ie_append_raw(ied, ie, &newval, (int)sizeof(newval));
 }
 
-int iax_ie_append_short(struct iax_ie_data *ied, unsigned char ie, unsigned short value) 
+int iax_ie_append_short(struct iax_ie_data *ied, unsigned char ie, unsigned short value)
 {
        unsigned short newval;
        newval = htons(value);
@@ -744,7 +776,7 @@ int iax_ie_append_byte(struct iax_ie_data *ied, unsigned char ie, unsigned char
        return iax_ie_append_raw(ied, ie, &dat, 1);
 }
 
-int iax_ie_append(struct iax_ie_data *ied, unsigned char ie) 
+int iax_ie_append(struct iax_ie_data *ied, unsigned char ie)
 {
        return iax_ie_append_raw(ied, ie, NULL, 0);
 }
@@ -902,7 +934,8 @@ int iax_parse_ies(struct iax_ies *ies, unsigned char *data, int datalen)
                        ies->rsa_result = (char *)data + 2;
                        break;
                case IAX_IE_APPARENT_ADDR:
-                       ies->apparent_addr = ((struct sockaddr_in *)(data + 2));
+                       memcpy(&ies->apparent_addr , (struct ast_sockaddr *) (data + 2), len);
+                       ies->apparent_addr.len = len;
                        break;
                case IAX_IE_REFRESH:
                        if (len != (int)sizeof(unsigned short)) {
@@ -949,7 +982,7 @@ int iax_parse_ies(struct iax_ies *ies, unsigned char *data, int datalen)
                                snprintf(tmp, (int)sizeof(tmp), "Expecting msgcount to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
                                errorf(tmp);
                        } else
-                               ies->msgcount = ntohs(get_unaligned_uint16(data + 2));  
+                               ies->msgcount = ntohs(get_unaligned_uint16(data + 2));
                        break;
                case IAX_IE_AUTOANSWER:
                        ies->autoanswer = 1;
@@ -976,7 +1009,7 @@ int iax_parse_ies(struct iax_ies *ies, unsigned char *data, int datalen)
                                snprintf(tmp, (int)sizeof(tmp), "Expecting firmwarever to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
                                errorf(tmp);
                        } else
-                               ies->firmwarever = ntohs(get_unaligned_uint16(data + 2));       
+                               ies->firmwarever = ntohs(get_unaligned_uint16(data + 2));
                        break;
                case IAX_IE_DEVICETYPE:
                        ies->devicetype = (char *)data + 2;
@@ -1029,7 +1062,7 @@ int iax_parse_ies(struct iax_ies *ies, unsigned char *data, int datalen)
                                snprintf(tmp, (int)sizeof(tmp), "Expecting callingtns to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
                                errorf(tmp);
                        } else
-                               ies->calling_tns = ntohs(get_unaligned_uint16(data + 2));       
+                               ies->calling_tns = ntohs(get_unaligned_uint16(data + 2));
                        break;
                case IAX_IE_RR_JITTER:
                        if (len != (int)sizeof(unsigned int)) {
@@ -1121,7 +1154,7 @@ int iax_parse_ies(struct iax_ies *ies, unsigned char *data, int datalen)
                                ies->osptokenblock[count] = (char *)data + 2 + 1;
                                ies->ospblocklength[count] = len - 1;
                        } else {
-                               snprintf(tmp, (int)sizeof(tmp), "Expected OSP token block index to be 0~%d but was %d\n", IAX_MAX_OSPBLOCK_NUM - 1, count);
+                               snprintf(tmp, (int)sizeof(tmp), "Expected OSP token block index to be 0~%d but was %u\n", IAX_MAX_OSPBLOCK_NUM - 1, count);
                                errorf(tmp);
                        }
                        break;
@@ -1152,7 +1185,8 @@ int iax_parse_ies(struct iax_ies *ies, unsigned char *data, int datalen)
 void iax_frame_wrap(struct iax_frame *fr, struct ast_frame *f)
 {
        fr->af.frametype = f->frametype;
-       ast_format_copy(&fr->af.subclass.format, &f->subclass.format);
+       fr->af.subclass.format = f->subclass.format;
+       fr->af.subclass.integer = f->subclass.integer;
        fr->af.mallocd = 0;                             /* Our frame is static relative to the container */
        fr->af.datalen = f->datalen;
        fr->af.samples = f->samples;
@@ -1171,7 +1205,8 @@ void iax_frame_wrap(struct iax_frame *fr, struct ast_frame *f)
                }
 #if __BYTE_ORDER == __LITTLE_ENDIAN
                /* We need to byte-swap slinear samples from network byte order */
-               if ((fr->af.frametype == AST_FRAME_VOICE) && (fr->af.subclass.format.id == AST_FORMAT_SLINEAR)) {
+               if ((fr->af.frametype == AST_FRAME_VOICE) &&
+                       (ast_format_cmp(fr->af.subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL)) {
                        /* 2 bytes / sample for SLINEAR */
                        ast_swapcopy_samples(fr->af.data.ptr, f->data.ptr, copy_len / 2);
                } else
@@ -1184,7 +1219,7 @@ struct iax_frame *iax_frame_new(int direction, int datalen, unsigned int cacheab
 {
        struct iax_frame *fr;
 
-#if !defined(LOW_MEMORY)
+#if !defined(NO_FRAME_CACHE)
        if (cacheable) {
                struct iax_frames *iax_frames;
                struct iax_frame *smallest;
@@ -1212,13 +1247,13 @@ struct iax_frame *iax_frame_new(int direction, int datalen, unsigned int cacheab
                                        iax_frames->size--;
                                        ast_free(smallest);
                                }
-                               if (!(fr = ast_calloc_cache(1, sizeof(*fr) + datalen))) {
+                               if (!(fr = ast_calloc(1, sizeof(*fr) + datalen))) {
                                        return NULL;
                                }
                                fr->afdatalen = datalen;
                        }
                } else {
-                       if (!(fr = ast_calloc_cache(1, sizeof(*fr) + datalen))) {
+                       if (!(fr = ast_calloc(1, sizeof(*fr) + datalen))) {
                                return NULL;
                        }
                        fr->afdatalen = datalen;
@@ -1236,12 +1271,12 @@ struct iax_frame *iax_frame_new(int direction, int datalen, unsigned int cacheab
 
        fr->direction = direction;
        fr->retrans = -1;
-       
+
        if (fr->direction == DIRECTION_INGRESS)
                ast_atomic_fetchadd_int(&iframes, 1);
        else
                ast_atomic_fetchadd_int(&oframes, 1);
-       
+
        ast_atomic_fetchadd_int(&frames, 1);
 
        return fr;
@@ -1249,7 +1284,7 @@ struct iax_frame *iax_frame_new(int direction, int datalen, unsigned int cacheab
 
 void iax_frame_free(struct iax_frame *fr)
 {
-#if !defined(LOW_MEMORY)
+#if !defined(NO_FRAME_CACHE)
        struct iax_frames *iax_frames = NULL;
 #endif
 
@@ -1264,8 +1299,10 @@ void iax_frame_free(struct iax_frame *fr)
        }
        ast_atomic_fetchadd_int(&frames, -1);
 
-#if !defined(LOW_MEMORY)
-       if (!fr->cacheable || !(iax_frames = ast_threadstorage_get(&frame_cache, sizeof(*iax_frames)))) {
+#if !defined(NO_FRAME_CACHE)
+       if (!fr->cacheable
+               || !ast_opt_cache_media_frames
+               || !(iax_frames = ast_threadstorage_get(&frame_cache, sizeof(*iax_frames)))) {
                ast_free(fr);
                return;
        }
@@ -1286,7 +1323,7 @@ void iax_frame_free(struct iax_frame *fr)
        ast_free(fr);
 }
 
-#if !defined(LOW_MEMORY)
+#if !defined(NO_FRAME_CACHE)
 static void frame_cache_cleanup(void *data)
 {
        struct iax_frames *framelist = data;