summaryrefslogtreecommitdiff
path: root/channels/iax2-parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'channels/iax2-parser.c')
-rw-r--r--channels/iax2-parser.c65
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