diff options
Diffstat (limited to 'channels/iax2-parser.c')
-rw-r--r-- | channels/iax2-parser.c | 65 |
1 files changed, 60 insertions, 5 deletions
diff --git a/channels/iax2-parser.c b/channels/iax2-parser.c index 24c3c57bb..9a105168c 100644 --- a/channels/iax2-parser.c +++ b/channels/iax2-parser.c @@ -214,6 +214,21 @@ static void dump_samprate(char *output, int maxlen, void *value, int len) } +static void dump_versioned_codec(char *output, int maxlen, void *value, int len) +{ + char *version = (char *) value; + if (version[0] == 0) { + if (len == (int) (sizeof(format_t) + sizeof(char))) { + format_t codec = ntohll(get_unaligned_uint64(value + 1)); + ast_copy_string(output, ast_getformatname(codec), maxlen); + } else { + ast_copy_string(output, "Invalid length!", maxlen); + } + } else { + ast_copy_string(output, "Unknown version!", maxlen); + } +} + static void dump_prov_ies(char *output, int maxlen, unsigned char *iedata, int len); static void dump_prov(char *output, int maxlen, void *value, int len) { @@ -233,7 +248,9 @@ static struct iax2_ie { { IAX_IE_USERNAME, "USERNAME", dump_string }, { IAX_IE_PASSWORD, "PASSWORD", dump_string }, { IAX_IE_CAPABILITY, "CAPABILITY", dump_int }, + { IAX_IE_CAPABILITY2, "CAPABILITY2", dump_versioned_codec }, { IAX_IE_FORMAT, "FORMAT", dump_int }, + { IAX_IE_FORMAT2, "FORMAT2", dump_versioned_codec }, { IAX_IE_LANGUAGE, "LANGUAGE", dump_string }, { IAX_IE_VERSION, "VERSION", dump_short }, { IAX_IE_ADSICPE, "ADSICPE", dump_short }, @@ -679,6 +696,16 @@ int iax_ie_append_addr(struct iax_ie_data *ied, unsigned char ie, const struct s return iax_ie_append_raw(ied, ie, sin, (int)sizeof(struct sockaddr_in)); } +int iax_ie_append_versioned_uint64(struct iax_ie_data *ied, unsigned char ie, unsigned char version, uint64_t value) +{ + struct _local { + unsigned char version; + uint64_t value; + } __attribute__((packed)) newval = { version, }; + put_unaligned_uint64(&newval.value, htonll(value)); + 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) { unsigned int newval; @@ -769,15 +796,43 @@ int iax_parse_ies(struct iax_ies *ies, unsigned char *data, int datalen) if (len != (int)sizeof(unsigned int)) { snprintf(tmp, (int)sizeof(tmp), "Expecting capability to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len); errorf(tmp); - } else - ies->capability = ntohl(get_unaligned_uint32(data + 2)); + } else if (ies->capability == 0) { /* Don't overwrite capability2, if specified */ + ies->capability = ntohll(get_unaligned_uint32(data + 2)); + } + break; + case IAX_IE_CAPABILITY2: + { + int version = data[2]; + if (version == 0) { + if (len != (int)sizeof(char) + sizeof(format_t)) { + snprintf(tmp, (int)sizeof(tmp), "Expecting capability to be %d bytes long but was %d\n", (int) (sizeof(format_t) + sizeof(char)), len); + errorf(tmp); + } else { + ies->capability = (format_t) ntohll(get_unaligned_uint64(data + 3)); + } + } /* else unknown version */ + } break; case IAX_IE_FORMAT: if (len != (int)sizeof(unsigned int)) { snprintf(tmp, (int)sizeof(tmp), "Expecting format to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len); errorf(tmp); - } else + } else if (ies->format == 0) { /* Don't overwrite format2, if specified */ ies->format = ntohl(get_unaligned_uint32(data + 2)); + } + break; + case IAX_IE_FORMAT2: + { + int version = data[2]; + if (version == 0) { + if (len != (int)sizeof(char) + sizeof(format_t)) { + snprintf(tmp, (int)sizeof(tmp), "Expecting format to be %d bytes long but was %d\n", (int) (sizeof(format_t) + sizeof(char)), len); + errorf(tmp); + } else { + ies->format = (format_t) ntohll(get_unaligned_uint64(data + 3)); + } + } /* else unknown version */ + } break; case IAX_IE_LANGUAGE: ies->language = (char *)data + 2; @@ -1083,7 +1138,7 @@ 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; - fr->af.subclass = f->subclass; + fr->af.subclass.codec = f->subclass.codec; fr->af.mallocd = 0; /* Our frame is static relative to the container */ fr->af.datalen = f->datalen; fr->af.samples = f->samples; @@ -1102,7 +1157,7 @@ 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 == AST_FORMAT_SLINEAR)) { + if ((fr->af.frametype == AST_FRAME_VOICE) && (fr->af.subclass.codec == AST_FORMAT_SLINEAR)) { /* 2 bytes / sample for SLINEAR */ ast_swapcopy_samples(fr->af.data.ptr, f->data.ptr, copy_len / 2); } else |