summaryrefslogtreecommitdiff
path: root/res
diff options
context:
space:
mode:
Diffstat (limited to 'res')
-rw-r--r--res/res.xml6
-rw-r--r--res/res_ari.c16
-rw-r--r--res/res_ari_applications.c6
-rw-r--r--res/res_ari_asterisk.c26
-rw-r--r--res/res_ari_bridges.c16
-rw-r--r--res/res_ari_channels.c34
-rw-r--r--res/res_ari_device_states.c4
-rw-r--r--res/res_ari_endpoints.c10
-rw-r--r--res/res_ari_events.c6
-rw-r--r--res/res_ari_mailboxes.c4
-rw-r--r--res/res_ari_playbacks.c6
-rw-r--r--res/res_ari_recordings.c18
-rw-r--r--res/res_ari_sounds.c4
-rw-r--r--res/res_fax.c109
-rw-r--r--res/res_format_attr_g729.c76
-rw-r--r--res/res_odbc.c1
-rw-r--r--res/res_odbc_transaction.c2
-rw-r--r--res/res_pjsip.c26
-rw-r--r--res/res_pjsip/config_global.c43
-rw-r--r--res/res_pjsip/pjsip_configuration.c37
-rw-r--r--res/res_pjsip/pjsip_options.c41
-rw-r--r--res/res_pjsip_refer.c7
-rw-r--r--res/res_pjsip_registrar.c14
-rw-r--r--res/res_pjsip_t38.c14
-rw-r--r--res/res_rtp_multicast.c7
25 files changed, 405 insertions, 128 deletions
diff --git a/res/res.xml b/res/res.xml
new file mode 100644
index 000000000..e9cb5f962
--- /dev/null
+++ b/res/res.xml
@@ -0,0 +1,6 @@
+<member name="res_digium_phone" displayname="Download the Digium Phone Module for Asterisk. See http://downloads.digium.com/pub/telephony/res_digium_phone/README.">
+ <support_level>external</support_level>
+ <depend>xmlstarlet</depend>
+ <depend>bash</depend>
+ <defaultenabled>no</defaultenabled>
+</member>
diff --git a/res/res_ari.c b/res/res_ari.c
index 4a0a22d79..4ff98ce96 100644
--- a/res/res_ari.c
+++ b/res/res_ari.c
@@ -579,7 +579,7 @@ void ast_ari_invoke(struct ast_tcptls_session_instance *ser,
}
}
-void ast_ari_get_docs(const char *uri, struct ast_variable *headers,
+void ast_ari_get_docs(const char *uri, const char *prefix, struct ast_variable *headers,
struct ast_ari_response *response)
{
RAII_VAR(struct ast_str *, absolute_path_builder, NULL, ast_free);
@@ -685,9 +685,15 @@ void ast_ari_get_docs(const char *uri, struct ast_variable *headers,
}
}
if (host != NULL) {
- ast_json_object_set(
- obj, "basePath",
- ast_json_stringf("http://%s/ari", host->value));
+ if (prefix != NULL && strlen(prefix) > 0) {
+ ast_json_object_set(
+ obj, "basePath",
+ ast_json_stringf("http://%s%s/ari", host->value,prefix));
+ } else {
+ ast_json_object_set(
+ obj, "basePath",
+ ast_json_stringf("http://%s/ari", host->value));
+ }
} else {
/* Without the host, we don't have the basePath */
ast_json_object_del(obj, "basePath");
@@ -969,7 +975,7 @@ static int ast_ari_callback(struct ast_tcptls_session_instance *ser,
ast_ari_response_error(&response, 405, "Method Not Allowed", "Unsupported method");
} else {
/* Skip the api-docs prefix */
- ast_ari_get_docs(strchr(uri, '/') + 1, headers, &response);
+ ast_ari_get_docs(strchr(uri, '/') + 1, urih->prefix, headers, &response);
}
} else {
/* Other RESTful resources */
diff --git a/res/res_ari_applications.c b/res/res_ari_applications.c
index e81d16498..dd868a602 100644
--- a/res/res_ari_applications.c
+++ b/res/res_ari_applications.c
@@ -496,7 +496,7 @@ fin: __attribute__((unused))
return;
}
-/*! \brief REST handler for /api-docs/applications.{format} */
+/*! \brief REST handler for /api-docs/applications.json */
static struct stasis_rest_handlers applications_applicationName_subscription = {
.path_segment = "subscription",
.callbacks = {
@@ -506,7 +506,7 @@ static struct stasis_rest_handlers applications_applicationName_subscription = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/applications.{format} */
+/*! \brief REST handler for /api-docs/applications.json */
static struct stasis_rest_handlers applications_applicationName = {
.path_segment = "applicationName",
.is_wildcard = 1,
@@ -516,7 +516,7 @@ static struct stasis_rest_handlers applications_applicationName = {
.num_children = 1,
.children = { &applications_applicationName_subscription, }
};
-/*! \brief REST handler for /api-docs/applications.{format} */
+/*! \brief REST handler for /api-docs/applications.json */
static struct stasis_rest_handlers applications = {
.path_segment = "applications",
.callbacks = {
diff --git a/res/res_ari_asterisk.c b/res/res_ari_asterisk.c
index fe6e3d363..b52a2a722 100644
--- a/res/res_ari_asterisk.c
+++ b/res/res_ari_asterisk.c
@@ -1178,7 +1178,7 @@ fin: __attribute__((unused))
return;
}
-/*! \brief REST handler for /api-docs/asterisk.{format} */
+/*! \brief REST handler for /api-docs/asterisk.json */
static struct stasis_rest_handlers asterisk_config_dynamic_configClass_objectType_id = {
.path_segment = "id",
.is_wildcard = 1,
@@ -1190,7 +1190,7 @@ static struct stasis_rest_handlers asterisk_config_dynamic_configClass_objectTyp
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/asterisk.{format} */
+/*! \brief REST handler for /api-docs/asterisk.json */
static struct stasis_rest_handlers asterisk_config_dynamic_configClass_objectType = {
.path_segment = "objectType",
.is_wildcard = 1,
@@ -1199,7 +1199,7 @@ static struct stasis_rest_handlers asterisk_config_dynamic_configClass_objectTyp
.num_children = 1,
.children = { &asterisk_config_dynamic_configClass_objectType_id, }
};
-/*! \brief REST handler for /api-docs/asterisk.{format} */
+/*! \brief REST handler for /api-docs/asterisk.json */
static struct stasis_rest_handlers asterisk_config_dynamic_configClass = {
.path_segment = "configClass",
.is_wildcard = 1,
@@ -1208,7 +1208,7 @@ static struct stasis_rest_handlers asterisk_config_dynamic_configClass = {
.num_children = 1,
.children = { &asterisk_config_dynamic_configClass_objectType, }
};
-/*! \brief REST handler for /api-docs/asterisk.{format} */
+/*! \brief REST handler for /api-docs/asterisk.json */
static struct stasis_rest_handlers asterisk_config_dynamic = {
.path_segment = "dynamic",
.callbacks = {
@@ -1216,7 +1216,7 @@ static struct stasis_rest_handlers asterisk_config_dynamic = {
.num_children = 1,
.children = { &asterisk_config_dynamic_configClass, }
};
-/*! \brief REST handler for /api-docs/asterisk.{format} */
+/*! \brief REST handler for /api-docs/asterisk.json */
static struct stasis_rest_handlers asterisk_config = {
.path_segment = "config",
.callbacks = {
@@ -1224,7 +1224,7 @@ static struct stasis_rest_handlers asterisk_config = {
.num_children = 1,
.children = { &asterisk_config_dynamic, }
};
-/*! \brief REST handler for /api-docs/asterisk.{format} */
+/*! \brief REST handler for /api-docs/asterisk.json */
static struct stasis_rest_handlers asterisk_info = {
.path_segment = "info",
.callbacks = {
@@ -1233,7 +1233,7 @@ static struct stasis_rest_handlers asterisk_info = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/asterisk.{format} */
+/*! \brief REST handler for /api-docs/asterisk.json */
static struct stasis_rest_handlers asterisk_modules_moduleName = {
.path_segment = "moduleName",
.is_wildcard = 1,
@@ -1246,7 +1246,7 @@ static struct stasis_rest_handlers asterisk_modules_moduleName = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/asterisk.{format} */
+/*! \brief REST handler for /api-docs/asterisk.json */
static struct stasis_rest_handlers asterisk_modules = {
.path_segment = "modules",
.callbacks = {
@@ -1255,7 +1255,7 @@ static struct stasis_rest_handlers asterisk_modules = {
.num_children = 1,
.children = { &asterisk_modules_moduleName, }
};
-/*! \brief REST handler for /api-docs/asterisk.{format} */
+/*! \brief REST handler for /api-docs/asterisk.json */
static struct stasis_rest_handlers asterisk_logging_logChannelName_rotate = {
.path_segment = "rotate",
.callbacks = {
@@ -1264,7 +1264,7 @@ static struct stasis_rest_handlers asterisk_logging_logChannelName_rotate = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/asterisk.{format} */
+/*! \brief REST handler for /api-docs/asterisk.json */
static struct stasis_rest_handlers asterisk_logging_logChannelName = {
.path_segment = "logChannelName",
.is_wildcard = 1,
@@ -1275,7 +1275,7 @@ static struct stasis_rest_handlers asterisk_logging_logChannelName = {
.num_children = 1,
.children = { &asterisk_logging_logChannelName_rotate, }
};
-/*! \brief REST handler for /api-docs/asterisk.{format} */
+/*! \brief REST handler for /api-docs/asterisk.json */
static struct stasis_rest_handlers asterisk_logging = {
.path_segment = "logging",
.callbacks = {
@@ -1284,7 +1284,7 @@ static struct stasis_rest_handlers asterisk_logging = {
.num_children = 1,
.children = { &asterisk_logging_logChannelName, }
};
-/*! \brief REST handler for /api-docs/asterisk.{format} */
+/*! \brief REST handler for /api-docs/asterisk.json */
static struct stasis_rest_handlers asterisk_variable = {
.path_segment = "variable",
.callbacks = {
@@ -1294,7 +1294,7 @@ static struct stasis_rest_handlers asterisk_variable = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/asterisk.{format} */
+/*! \brief REST handler for /api-docs/asterisk.json */
static struct stasis_rest_handlers asterisk = {
.path_segment = "asterisk",
.callbacks = {
diff --git a/res/res_ari_bridges.c b/res/res_ari_bridges.c
index 860ff1dc0..889d42213 100644
--- a/res/res_ari_bridges.c
+++ b/res/res_ari_bridges.c
@@ -1318,7 +1318,7 @@ fin: __attribute__((unused))
return;
}
-/*! \brief REST handler for /api-docs/bridges.{format} */
+/*! \brief REST handler for /api-docs/bridges.json */
static struct stasis_rest_handlers bridges_bridgeId_addChannel = {
.path_segment = "addChannel",
.callbacks = {
@@ -1327,7 +1327,7 @@ static struct stasis_rest_handlers bridges_bridgeId_addChannel = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/bridges.{format} */
+/*! \brief REST handler for /api-docs/bridges.json */
static struct stasis_rest_handlers bridges_bridgeId_removeChannel = {
.path_segment = "removeChannel",
.callbacks = {
@@ -1336,7 +1336,7 @@ static struct stasis_rest_handlers bridges_bridgeId_removeChannel = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/bridges.{format} */
+/*! \brief REST handler for /api-docs/bridges.json */
static struct stasis_rest_handlers bridges_bridgeId_moh = {
.path_segment = "moh",
.callbacks = {
@@ -1346,7 +1346,7 @@ static struct stasis_rest_handlers bridges_bridgeId_moh = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/bridges.{format} */
+/*! \brief REST handler for /api-docs/bridges.json */
static struct stasis_rest_handlers bridges_bridgeId_play_playbackId = {
.path_segment = "playbackId",
.is_wildcard = 1,
@@ -1356,7 +1356,7 @@ static struct stasis_rest_handlers bridges_bridgeId_play_playbackId = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/bridges.{format} */
+/*! \brief REST handler for /api-docs/bridges.json */
static struct stasis_rest_handlers bridges_bridgeId_play = {
.path_segment = "play",
.callbacks = {
@@ -1365,7 +1365,7 @@ static struct stasis_rest_handlers bridges_bridgeId_play = {
.num_children = 1,
.children = { &bridges_bridgeId_play_playbackId, }
};
-/*! \brief REST handler for /api-docs/bridges.{format} */
+/*! \brief REST handler for /api-docs/bridges.json */
static struct stasis_rest_handlers bridges_bridgeId_record = {
.path_segment = "record",
.callbacks = {
@@ -1374,7 +1374,7 @@ static struct stasis_rest_handlers bridges_bridgeId_record = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/bridges.{format} */
+/*! \brief REST handler for /api-docs/bridges.json */
static struct stasis_rest_handlers bridges_bridgeId = {
.path_segment = "bridgeId",
.is_wildcard = 1,
@@ -1386,7 +1386,7 @@ static struct stasis_rest_handlers bridges_bridgeId = {
.num_children = 5,
.children = { &bridges_bridgeId_addChannel,&bridges_bridgeId_removeChannel,&bridges_bridgeId_moh,&bridges_bridgeId_play,&bridges_bridgeId_record, }
};
-/*! \brief REST handler for /api-docs/bridges.{format} */
+/*! \brief REST handler for /api-docs/bridges.json */
static struct stasis_rest_handlers bridges = {
.path_segment = "bridges",
.callbacks = {
diff --git a/res/res_ari_channels.c b/res/res_ari_channels.c
index a14a9c8cb..9dc19cc86 100644
--- a/res/res_ari_channels.c
+++ b/res/res_ari_channels.c
@@ -2567,7 +2567,7 @@ fin: __attribute__((unused))
return;
}
-/*! \brief REST handler for /api-docs/channels.{format} */
+/*! \brief REST handler for /api-docs/channels.json */
static struct stasis_rest_handlers channels_channelId_continue = {
.path_segment = "continue",
.callbacks = {
@@ -2576,7 +2576,7 @@ static struct stasis_rest_handlers channels_channelId_continue = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/channels.{format} */
+/*! \brief REST handler for /api-docs/channels.json */
static struct stasis_rest_handlers channels_channelId_redirect = {
.path_segment = "redirect",
.callbacks = {
@@ -2585,7 +2585,7 @@ static struct stasis_rest_handlers channels_channelId_redirect = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/channels.{format} */
+/*! \brief REST handler for /api-docs/channels.json */
static struct stasis_rest_handlers channels_channelId_answer = {
.path_segment = "answer",
.callbacks = {
@@ -2594,7 +2594,7 @@ static struct stasis_rest_handlers channels_channelId_answer = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/channels.{format} */
+/*! \brief REST handler for /api-docs/channels.json */
static struct stasis_rest_handlers channels_channelId_ring = {
.path_segment = "ring",
.callbacks = {
@@ -2604,7 +2604,7 @@ static struct stasis_rest_handlers channels_channelId_ring = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/channels.{format} */
+/*! \brief REST handler for /api-docs/channels.json */
static struct stasis_rest_handlers channels_channelId_dtmf = {
.path_segment = "dtmf",
.callbacks = {
@@ -2613,7 +2613,7 @@ static struct stasis_rest_handlers channels_channelId_dtmf = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/channels.{format} */
+/*! \brief REST handler for /api-docs/channels.json */
static struct stasis_rest_handlers channels_channelId_mute = {
.path_segment = "mute",
.callbacks = {
@@ -2623,7 +2623,7 @@ static struct stasis_rest_handlers channels_channelId_mute = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/channels.{format} */
+/*! \brief REST handler for /api-docs/channels.json */
static struct stasis_rest_handlers channels_channelId_hold = {
.path_segment = "hold",
.callbacks = {
@@ -2633,7 +2633,7 @@ static struct stasis_rest_handlers channels_channelId_hold = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/channels.{format} */
+/*! \brief REST handler for /api-docs/channels.json */
static struct stasis_rest_handlers channels_channelId_moh = {
.path_segment = "moh",
.callbacks = {
@@ -2643,7 +2643,7 @@ static struct stasis_rest_handlers channels_channelId_moh = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/channels.{format} */
+/*! \brief REST handler for /api-docs/channels.json */
static struct stasis_rest_handlers channels_channelId_silence = {
.path_segment = "silence",
.callbacks = {
@@ -2653,7 +2653,7 @@ static struct stasis_rest_handlers channels_channelId_silence = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/channels.{format} */
+/*! \brief REST handler for /api-docs/channels.json */
static struct stasis_rest_handlers channels_channelId_play_playbackId = {
.path_segment = "playbackId",
.is_wildcard = 1,
@@ -2663,7 +2663,7 @@ static struct stasis_rest_handlers channels_channelId_play_playbackId = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/channels.{format} */
+/*! \brief REST handler for /api-docs/channels.json */
static struct stasis_rest_handlers channels_channelId_play = {
.path_segment = "play",
.callbacks = {
@@ -2672,7 +2672,7 @@ static struct stasis_rest_handlers channels_channelId_play = {
.num_children = 1,
.children = { &channels_channelId_play_playbackId, }
};
-/*! \brief REST handler for /api-docs/channels.{format} */
+/*! \brief REST handler for /api-docs/channels.json */
static struct stasis_rest_handlers channels_channelId_record = {
.path_segment = "record",
.callbacks = {
@@ -2681,7 +2681,7 @@ static struct stasis_rest_handlers channels_channelId_record = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/channels.{format} */
+/*! \brief REST handler for /api-docs/channels.json */
static struct stasis_rest_handlers channels_channelId_variable = {
.path_segment = "variable",
.callbacks = {
@@ -2691,7 +2691,7 @@ static struct stasis_rest_handlers channels_channelId_variable = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/channels.{format} */
+/*! \brief REST handler for /api-docs/channels.json */
static struct stasis_rest_handlers channels_channelId_snoop_snoopId = {
.path_segment = "snoopId",
.is_wildcard = 1,
@@ -2701,7 +2701,7 @@ static struct stasis_rest_handlers channels_channelId_snoop_snoopId = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/channels.{format} */
+/*! \brief REST handler for /api-docs/channels.json */
static struct stasis_rest_handlers channels_channelId_snoop = {
.path_segment = "snoop",
.callbacks = {
@@ -2710,7 +2710,7 @@ static struct stasis_rest_handlers channels_channelId_snoop = {
.num_children = 1,
.children = { &channels_channelId_snoop_snoopId, }
};
-/*! \brief REST handler for /api-docs/channels.{format} */
+/*! \brief REST handler for /api-docs/channels.json */
static struct stasis_rest_handlers channels_channelId = {
.path_segment = "channelId",
.is_wildcard = 1,
@@ -2722,7 +2722,7 @@ static struct stasis_rest_handlers channels_channelId = {
.num_children = 13,
.children = { &channels_channelId_continue,&channels_channelId_redirect,&channels_channelId_answer,&channels_channelId_ring,&channels_channelId_dtmf,&channels_channelId_mute,&channels_channelId_hold,&channels_channelId_moh,&channels_channelId_silence,&channels_channelId_play,&channels_channelId_record,&channels_channelId_variable,&channels_channelId_snoop, }
};
-/*! \brief REST handler for /api-docs/channels.{format} */
+/*! \brief REST handler for /api-docs/channels.json */
static struct stasis_rest_handlers channels = {
.path_segment = "channels",
.callbacks = {
diff --git a/res/res_ari_device_states.c b/res/res_ari_device_states.c
index f15e3da78..6d5d19f58 100644
--- a/res/res_ari_device_states.c
+++ b/res/res_ari_device_states.c
@@ -320,7 +320,7 @@ fin: __attribute__((unused))
return;
}
-/*! \brief REST handler for /api-docs/deviceStates.{format} */
+/*! \brief REST handler for /api-docs/deviceStates.json */
static struct stasis_rest_handlers deviceStates_deviceName = {
.path_segment = "deviceName",
.is_wildcard = 1,
@@ -332,7 +332,7 @@ static struct stasis_rest_handlers deviceStates_deviceName = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/deviceStates.{format} */
+/*! \brief REST handler for /api-docs/deviceStates.json */
static struct stasis_rest_handlers deviceStates = {
.path_segment = "deviceStates",
.callbacks = {
diff --git a/res/res_ari_endpoints.c b/res/res_ari_endpoints.c
index 4d54ff3bd..e3ade435d 100644
--- a/res/res_ari_endpoints.c
+++ b/res/res_ari_endpoints.c
@@ -434,7 +434,7 @@ fin: __attribute__((unused))
return;
}
-/*! \brief REST handler for /api-docs/endpoints.{format} */
+/*! \brief REST handler for /api-docs/endpoints.json */
static struct stasis_rest_handlers endpoints_sendMessage = {
.path_segment = "sendMessage",
.callbacks = {
@@ -443,7 +443,7 @@ static struct stasis_rest_handlers endpoints_sendMessage = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/endpoints.{format} */
+/*! \brief REST handler for /api-docs/endpoints.json */
static struct stasis_rest_handlers endpoints_tech_resource_sendMessage = {
.path_segment = "sendMessage",
.callbacks = {
@@ -452,7 +452,7 @@ static struct stasis_rest_handlers endpoints_tech_resource_sendMessage = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/endpoints.{format} */
+/*! \brief REST handler for /api-docs/endpoints.json */
static struct stasis_rest_handlers endpoints_tech_resource = {
.path_segment = "resource",
.is_wildcard = 1,
@@ -462,7 +462,7 @@ static struct stasis_rest_handlers endpoints_tech_resource = {
.num_children = 1,
.children = { &endpoints_tech_resource_sendMessage, }
};
-/*! \brief REST handler for /api-docs/endpoints.{format} */
+/*! \brief REST handler for /api-docs/endpoints.json */
static struct stasis_rest_handlers endpoints_tech = {
.path_segment = "tech",
.is_wildcard = 1,
@@ -472,7 +472,7 @@ static struct stasis_rest_handlers endpoints_tech = {
.num_children = 1,
.children = { &endpoints_tech_resource, }
};
-/*! \brief REST handler for /api-docs/endpoints.{format} */
+/*! \brief REST handler for /api-docs/endpoints.json */
static struct stasis_rest_handlers endpoints = {
.path_segment = "endpoints",
.callbacks = {
diff --git a/res/res_ari_events.c b/res/res_ari_events.c
index 65bd38d5b..e85db4c45 100644
--- a/res/res_ari_events.c
+++ b/res/res_ari_events.c
@@ -407,7 +407,7 @@ fin: __attribute__((unused))
return;
}
-/*! \brief REST handler for /api-docs/events.{format} */
+/*! \brief REST handler for /api-docs/events.json */
static struct stasis_rest_handlers events_user_eventName = {
.path_segment = "eventName",
.is_wildcard = 1,
@@ -417,7 +417,7 @@ static struct stasis_rest_handlers events_user_eventName = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/events.{format} */
+/*! \brief REST handler for /api-docs/events.json */
static struct stasis_rest_handlers events_user = {
.path_segment = "user",
.callbacks = {
@@ -425,7 +425,7 @@ static struct stasis_rest_handlers events_user = {
.num_children = 1,
.children = { &events_user_eventName, }
};
-/*! \brief REST handler for /api-docs/events.{format} */
+/*! \brief REST handler for /api-docs/events.json */
static struct stasis_rest_handlers events = {
.path_segment = "events",
.callbacks = {
diff --git a/res/res_ari_mailboxes.c b/res/res_ari_mailboxes.c
index 2b3404f2b..6ed16a84e 100644
--- a/res/res_ari_mailboxes.c
+++ b/res/res_ari_mailboxes.c
@@ -326,7 +326,7 @@ fin: __attribute__((unused))
return;
}
-/*! \brief REST handler for /api-docs/mailboxes.{format} */
+/*! \brief REST handler for /api-docs/mailboxes.json */
static struct stasis_rest_handlers mailboxes_mailboxName = {
.path_segment = "mailboxName",
.is_wildcard = 1,
@@ -338,7 +338,7 @@ static struct stasis_rest_handlers mailboxes_mailboxName = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/mailboxes.{format} */
+/*! \brief REST handler for /api-docs/mailboxes.json */
static struct stasis_rest_handlers mailboxes = {
.path_segment = "mailboxes",
.callbacks = {
diff --git a/res/res_ari_playbacks.c b/res/res_ari_playbacks.c
index de38ad86d..233603303 100644
--- a/res/res_ari_playbacks.c
+++ b/res/res_ari_playbacks.c
@@ -270,7 +270,7 @@ fin: __attribute__((unused))
return;
}
-/*! \brief REST handler for /api-docs/playbacks.{format} */
+/*! \brief REST handler for /api-docs/playbacks.json */
static struct stasis_rest_handlers playbacks_playbackId_control = {
.path_segment = "control",
.callbacks = {
@@ -279,7 +279,7 @@ static struct stasis_rest_handlers playbacks_playbackId_control = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/playbacks.{format} */
+/*! \brief REST handler for /api-docs/playbacks.json */
static struct stasis_rest_handlers playbacks_playbackId = {
.path_segment = "playbackId",
.is_wildcard = 1,
@@ -290,7 +290,7 @@ static struct stasis_rest_handlers playbacks_playbackId = {
.num_children = 1,
.children = { &playbacks_playbackId_control, }
};
-/*! \brief REST handler for /api-docs/playbacks.{format} */
+/*! \brief REST handler for /api-docs/playbacks.json */
static struct stasis_rest_handlers playbacks = {
.path_segment = "playbacks",
.callbacks = {
diff --git a/res/res_ari_recordings.c b/res/res_ari_recordings.c
index dede53c48..04ce0ac97 100644
--- a/res/res_ari_recordings.c
+++ b/res/res_ari_recordings.c
@@ -737,7 +737,7 @@ fin: __attribute__((unused))
return;
}
-/*! \brief REST handler for /api-docs/recordings.{format} */
+/*! \brief REST handler for /api-docs/recordings.json */
static struct stasis_rest_handlers recordings_stored_recordingName_copy = {
.path_segment = "copy",
.callbacks = {
@@ -746,7 +746,7 @@ static struct stasis_rest_handlers recordings_stored_recordingName_copy = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/recordings.{format} */
+/*! \brief REST handler for /api-docs/recordings.json */
static struct stasis_rest_handlers recordings_stored_recordingName = {
.path_segment = "recordingName",
.is_wildcard = 1,
@@ -757,7 +757,7 @@ static struct stasis_rest_handlers recordings_stored_recordingName = {
.num_children = 1,
.children = { &recordings_stored_recordingName_copy, }
};
-/*! \brief REST handler for /api-docs/recordings.{format} */
+/*! \brief REST handler for /api-docs/recordings.json */
static struct stasis_rest_handlers recordings_stored = {
.path_segment = "stored",
.callbacks = {
@@ -766,7 +766,7 @@ static struct stasis_rest_handlers recordings_stored = {
.num_children = 1,
.children = { &recordings_stored_recordingName, }
};
-/*! \brief REST handler for /api-docs/recordings.{format} */
+/*! \brief REST handler for /api-docs/recordings.json */
static struct stasis_rest_handlers recordings_live_recordingName_stop = {
.path_segment = "stop",
.callbacks = {
@@ -775,7 +775,7 @@ static struct stasis_rest_handlers recordings_live_recordingName_stop = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/recordings.{format} */
+/*! \brief REST handler for /api-docs/recordings.json */
static struct stasis_rest_handlers recordings_live_recordingName_pause = {
.path_segment = "pause",
.callbacks = {
@@ -785,7 +785,7 @@ static struct stasis_rest_handlers recordings_live_recordingName_pause = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/recordings.{format} */
+/*! \brief REST handler for /api-docs/recordings.json */
static struct stasis_rest_handlers recordings_live_recordingName_mute = {
.path_segment = "mute",
.callbacks = {
@@ -795,7 +795,7 @@ static struct stasis_rest_handlers recordings_live_recordingName_mute = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/recordings.{format} */
+/*! \brief REST handler for /api-docs/recordings.json */
static struct stasis_rest_handlers recordings_live_recordingName = {
.path_segment = "recordingName",
.is_wildcard = 1,
@@ -806,7 +806,7 @@ static struct stasis_rest_handlers recordings_live_recordingName = {
.num_children = 3,
.children = { &recordings_live_recordingName_stop,&recordings_live_recordingName_pause,&recordings_live_recordingName_mute, }
};
-/*! \brief REST handler for /api-docs/recordings.{format} */
+/*! \brief REST handler for /api-docs/recordings.json */
static struct stasis_rest_handlers recordings_live = {
.path_segment = "live",
.callbacks = {
@@ -814,7 +814,7 @@ static struct stasis_rest_handlers recordings_live = {
.num_children = 1,
.children = { &recordings_live_recordingName, }
};
-/*! \brief REST handler for /api-docs/recordings.{format} */
+/*! \brief REST handler for /api-docs/recordings.json */
static struct stasis_rest_handlers recordings = {
.path_segment = "recordings",
.callbacks = {
diff --git a/res/res_ari_sounds.c b/res/res_ari_sounds.c
index c53330d54..935025dec 100644
--- a/res/res_ari_sounds.c
+++ b/res/res_ari_sounds.c
@@ -208,7 +208,7 @@ fin: __attribute__((unused))
return;
}
-/*! \brief REST handler for /api-docs/sounds.{format} */
+/*! \brief REST handler for /api-docs/sounds.json */
static struct stasis_rest_handlers sounds_soundId = {
.path_segment = "soundId",
.is_wildcard = 1,
@@ -218,7 +218,7 @@ static struct stasis_rest_handlers sounds_soundId = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/sounds.{format} */
+/*! \brief REST handler for /api-docs/sounds.json */
static struct stasis_rest_handlers sounds = {
.path_segment = "sounds",
.callbacks = {
diff --git a/res/res_fax.c b/res/res_fax.c
index 86260d10e..e37091b31 100644
--- a/res/res_fax.c
+++ b/res/res_fax.c
@@ -641,6 +641,7 @@ static void fixup_callback(void *data, struct ast_channel *old_chan, struct ast_
struct ast_fax_session_details *new_details = find_or_create_details(new_chan);
ast_framehook_detach(old_chan, old_details->gateway_id);
+ new_details->is_t38_negotiated = old_details->is_t38_negotiated;
fax_gateway_attach(new_chan, new_details);
ao2_cleanup(new_details);
}
@@ -1439,6 +1440,7 @@ static int report_fax_status(struct ast_channel *chan, struct ast_fax_session_de
static void set_channel_variables(struct ast_channel *chan, struct ast_fax_session_details *details)
{
char buf[10];
+
pbx_builtin_setvar_helper(chan, "FAXSTATUS", S_OR(details->result, NULL));
pbx_builtin_setvar_helper(chan, "FAXERROR", S_OR(details->error, NULL));
pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", S_OR(details->resultstr, NULL));
@@ -1447,7 +1449,7 @@ static void set_channel_variables(struct ast_channel *chan, struct ast_fax_sessi
pbx_builtin_setvar_helper(chan, "FAXBITRATE", S_OR(details->transfer_rate, NULL));
pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", S_OR(details->resolution, NULL));
- if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
+ if (details->is_t38_negotiated) {
pbx_builtin_setvar_helper(chan, "FAXMODE", "T38");
} else {
pbx_builtin_setvar_helper(chan, "FAXMODE", "audio");
@@ -1656,6 +1658,7 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det
ast_string_field_set(details, result, "");
ast_string_field_set(details, resultstr, "");
ast_string_field_set(details, error, "");
+ details->is_t38_negotiated = t38negotiated;
set_channel_variables(chan, details);
if (fax->tech->start_session(fax) < 0) {
@@ -1706,12 +1709,18 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det
* do T.38 as well
*/
t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
- t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
+ if (details->caps & AST_FAX_TECH_T38) {
+ details->is_t38_negotiated = 1;
+ t38_parameters.request_response = AST_T38_NEGOTIATED;
+ } else {
+ t38_parameters.request_response = AST_T38_REFUSED;
+ }
ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
break;
case AST_T38_NEGOTIATED:
t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
t38negotiated = 1;
+ details->is_t38_negotiated = 1;
break;
default:
break;
@@ -2880,11 +2889,17 @@ static struct fax_gateway *fax_gateway_new(struct ast_channel *chan, struct ast_
return gateway;
}
-/*! \brief Create a fax session and start T.30<->T.38 gateway mode
+/*!
+ * \brief Create a fax session and start T.30<->T.38 gateway mode
+ *
* \param gateway a fax gateway object
* \param details fax session details
* \param chan active channel
- * \return 0 on error 1 on success*/
+ *
+ * \pre chan is locked on entry
+ *
+ * \return 0 on error 1 on success
+ */
static int fax_gateway_start(struct fax_gateway *gateway, struct ast_fax_session_details *details, struct ast_channel *chan)
{
struct ast_fax_session *s;
@@ -2896,6 +2911,7 @@ static int fax_gateway_start(struct fax_gateway *gateway, struct ast_fax_session
ast_string_field_set(details, result, "FAILED");
ast_string_field_set(details, resultstr, "error starting gateway session");
ast_string_field_set(details, error, "INIT_ERROR");
+ details->is_t38_negotiated = 0;
set_channel_variables(chan, details);
report_fax_status(chan, details, "No Available Resource");
ast_log(LOG_ERROR, "Can't create a FAX session, gateway attempt failed.\n");
@@ -2916,6 +2932,7 @@ static int fax_gateway_start(struct fax_gateway *gateway, struct ast_fax_session
ast_string_field_set(details, result, "FAILED");
ast_string_field_set(details, resultstr, "error starting gateway session");
ast_string_field_set(details, error, "INIT_ERROR");
+ details->is_t38_negotiated = 0;
set_channel_variables(chan, details);
return -1;
}
@@ -2928,6 +2945,7 @@ static int fax_gateway_start(struct fax_gateway *gateway, struct ast_fax_session
return 0;
}
+/*! \pre chan is locked on entry */
static struct ast_frame *fax_gateway_request_t38(struct fax_gateway *gateway, struct ast_channel *chan, struct ast_frame *f)
{
struct ast_frame *fp;
@@ -2960,12 +2978,14 @@ static struct ast_frame *fax_gateway_request_t38(struct fax_gateway *gateway, st
gateway->t38_state = T38_STATE_NEGOTIATING;
gateway->timeout_start = ast_tvnow();
+ details->is_t38_negotiated = 0;
details->gateway_timeout = FAX_GATEWAY_TIMEOUT;
ast_debug(1, "requesting T.38 for gateway session for %s\n", ast_channel_name(chan));
return fp;
}
+/*! \pre chan is locked on entry */
static struct ast_frame *fax_gateway_detect_v21(struct fax_gateway *gateway, struct ast_channel *chan, struct ast_channel *peer, struct ast_channel *active, struct ast_frame *f)
{
struct ast_channel *other = (active == chan) ? peer : chan;
@@ -2981,8 +3001,14 @@ static struct ast_frame *fax_gateway_detect_v21(struct fax_gateway *gateway, str
}
if (gateway->detected_v21) {
+ enum ast_t38_state state_other;
+
destroy_v21_sessions(gateway);
- if (ast_channel_get_t38_state(other) == T38_STATE_UNKNOWN) {
+
+ ast_channel_unlock(chan);
+ state_other = ast_channel_get_t38_state(other);
+ ast_channel_lock(chan);
+ if (state_other == T38_STATE_UNKNOWN) {
ast_debug(1, "detected v21 preamble from %s\n", ast_channel_name(active));
return fax_gateway_request_t38(gateway, chan, f);
} else {
@@ -2993,21 +3019,29 @@ static struct ast_frame *fax_gateway_detect_v21(struct fax_gateway *gateway, str
return f;
}
-static int fax_gateway_indicate_t38(struct ast_channel *chan, struct ast_channel *active, struct ast_control_t38_parameters *control_params)
+/*! \pre chan is locked on entry */
+static void fax_gateway_indicate_t38(struct ast_channel *chan, struct ast_channel *active, struct ast_control_t38_parameters *control_params)
{
if (active == chan) {
- return ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, control_params, sizeof(*control_params));
+ ast_channel_unlock(chan);
+ ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, control_params, sizeof(*control_params));
+ ast_channel_lock(chan);
} else {
- return ast_queue_control_data(chan, AST_CONTROL_T38_PARAMETERS, control_params, sizeof(*control_params));
+ ast_queue_control_data(chan, AST_CONTROL_T38_PARAMETERS, control_params, sizeof(*control_params));
}
}
-/*! \brief T38 Gateway Negotiate t38 parameters
+/*!
+ * \brief T38 Gateway Negotiate t38 parameters
+ *
* \param gateway gateway object
* \param chan channel running the gateway
* \param peer channel im bridged too
* \param active channel the frame originated on
* \param f the control frame to process
+ *
+ * \pre chan is locked on entry
+ *
* \return processed control frame or null frame
*/
static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, struct ast_channel *chan, struct ast_channel *peer, struct ast_channel *active, struct ast_frame *f)
@@ -3015,6 +3049,7 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
struct ast_control_t38_parameters *control_params = f->data.ptr;
struct ast_channel *other = (active == chan) ? peer : chan;
struct ast_fax_session_details *details;
+ enum ast_t38_state state_other;
if (f->datalen != sizeof(struct ast_control_t38_parameters)) {
/* invalaid AST_CONTROL_T38_PARAMETERS frame, we can't
@@ -3037,9 +3072,11 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
}
if (control_params->request_response == AST_T38_REQUEST_NEGOTIATE) {
- enum ast_t38_state state = ast_channel_get_t38_state(other);
+ ast_channel_unlock(chan);
+ state_other = ast_channel_get_t38_state(other);
+ ast_channel_lock(chan);
- if (state == T38_STATE_UNKNOWN) {
+ if (state_other == T38_STATE_UNKNOWN) {
/* we detected a request to negotiate T.38 and the
* other channel appears to support T.38, we'll pass
* the request through and only step in if the other
@@ -3048,10 +3085,11 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
t38_parameters_ast_to_fax(&details->their_t38_parameters, control_params);
gateway->t38_state = T38_STATE_UNKNOWN;
gateway->timeout_start = ast_tvnow();
+ details->is_t38_negotiated = 0;
details->gateway_timeout = FAX_GATEWAY_TIMEOUT;
ao2_ref(details, -1);
return f;
- } else if (state == T38_STATE_UNAVAILABLE || state == T38_STATE_REJECTED) {
+ } else if (state_other == T38_STATE_UNAVAILABLE || state_other == T38_STATE_REJECTED) {
/* the other channel does not support T.38, we need to
* step in here */
ast_debug(1, "%s is attempting to negotiate T.38 but %s does not support it\n", ast_channel_name(active), ast_channel_name(other));
@@ -3063,12 +3101,14 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
if (fax_gateway_start(gateway, details, chan)) {
ast_log(LOG_ERROR, "error starting T.38 gateway for T.38 channel %s and G.711 channel %s\n", ast_channel_name(active), ast_channel_name(other));
gateway->t38_state = T38_STATE_REJECTED;
+ details->is_t38_negotiated = 0;
control_params->request_response = AST_T38_REFUSED;
ast_framehook_detach(chan, details->gateway_id);
details->gateway_id = -1;
} else {
gateway->t38_state = T38_STATE_NEGOTIATED;
+ details->is_t38_negotiated = chan == active;
control_params->request_response = AST_T38_NEGOTIATED;
report_fax_status(chan, details, "T.38 Negotiated");
}
@@ -3086,6 +3126,7 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
t38_parameters_ast_to_fax(&details->their_t38_parameters, control_params);
gateway->t38_state = T38_STATE_UNKNOWN;
gateway->timeout_start = ast_tvnow();
+ details->is_t38_negotiated = 0;
details->gateway_timeout = FAX_GATEWAY_TIMEOUT;
ast_debug(1, "%s is attempting to negotiate T.38 after we already sent a negotiation request based on v21 preamble detection\n", ast_channel_name(active));
@@ -3108,6 +3149,7 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
ast_string_field_set(details, result, "SUCCESS");
ast_string_field_set(details, resultstr, "no gateway necessary");
ast_string_field_set(details, error, "NATIVE_T38");
+ details->is_t38_negotiated = 1;
set_channel_variables(chan, details);
ast_debug(1, "%s is attempting to negotiate T.38 after we already negotiated T.38 with %s, disabling the gateway\n", ast_channel_name(active), ast_channel_name(other));
@@ -3122,11 +3164,15 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
&& control_params->request_response == AST_T38_REFUSED) {
ast_debug(1, "unable to negotiate T.38 on %s for fax gateway\n", ast_channel_name(active));
+ details->is_t38_negotiated = 0;
/* our request to negotiate T.38 was refused, if the other
* channel supports T.38, they might still reinvite and save
* the day. Otherwise disable the gateway. */
- if (ast_channel_get_t38_state(other) == T38_STATE_UNKNOWN) {
+ ast_channel_unlock(chan);
+ state_other = ast_channel_get_t38_state(other);
+ ast_channel_lock(chan);
+ if (state_other == T38_STATE_UNKNOWN) {
gateway->t38_state = T38_STATE_UNAVAILABLE;
} else {
ast_framehook_detach(chan, details->gateway_id);
@@ -3150,11 +3196,13 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
if (fax_gateway_start(gateway, details, chan)) {
ast_log(LOG_ERROR, "error starting T.38 gateway for T.38 channel %s and G.711 channel %s\n", ast_channel_name(active), ast_channel_name(other));
gateway->t38_state = T38_STATE_NEGOTIATING;
+ details->is_t38_negotiated = 0;
control_params->request_response = AST_T38_REQUEST_TERMINATE;
fax_gateway_indicate_t38(chan, active, control_params);
} else {
gateway->t38_state = T38_STATE_NEGOTIATED;
+ details->is_t38_negotiated = chan == active;
report_fax_status(chan, details, "T.38 Negotiated");
}
@@ -3170,14 +3218,16 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
t38_parameters_fax_to_ast(control_params, &details->our_t38_parameters);
if (fax_gateway_start(gateway, details, chan)) {
- ast_log(LOG_ERROR, "error starting T.38 gateway for T.38 channel %s and G.711 channel %s\n", ast_channel_name(active), ast_channel_name(other));
+ ast_log(LOG_ERROR, "error starting T.38 gateway for T.38 channel %s and G.711 channel %s\n", ast_channel_name(other), ast_channel_name(active));
gateway->t38_state = T38_STATE_REJECTED;
+ details->is_t38_negotiated = 0;
control_params->request_response = AST_T38_REFUSED;
ast_framehook_detach(chan, details->gateway_id);
details->gateway_id = -1;
} else {
gateway->t38_state = T38_STATE_NEGOTIATED;
+ details->is_t38_negotiated = chan == other;
control_params->request_response = AST_T38_NEGOTIATED;
}
@@ -3193,6 +3243,7 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
details->gateway_id = -1;
gateway->t38_state = T38_STATE_REJECTED;
+ details->is_t38_negotiated = 0;
control_params->request_response = AST_T38_TERMINATED;
fax_gateway_indicate_t38(chan, active, control_params);
@@ -3208,6 +3259,7 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
ast_string_field_set(details, result, "SUCCESS");
ast_string_field_set(details, resultstr, "no gateway necessary");
ast_string_field_set(details, error, "NATIVE_T38");
+ details->is_t38_negotiated = 1;
set_channel_variables(chan, details);
ao2_ref(details, -1);
@@ -3250,7 +3302,8 @@ static void fax_gateway_framehook_destroy(void *data)
ao2_ref(gateway, -1);
}
-/*! \brief T.30<->T.38 gateway framehook.
+/*!
+ * \brief T.30<->T.38 gateway framehook.
*
* Intercept packets on bridged channels and determine if a T.38 gateway is
* required. If a gateway is required, start a gateway and handle T.38
@@ -3261,6 +3314,8 @@ static void fax_gateway_framehook_destroy(void *data)
* \param event framehook event
* \param data framehook data (struct fax_gateway *)
*
+ * \pre chan is locked on entry
+ *
* \return processed frame or NULL when f is NULL or a null frame
*/
static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data)
@@ -3323,8 +3378,16 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct
}
if (!gateway->bridged) {
+ enum ast_t38_state state_chan;
+ enum ast_t38_state state_peer;
+
+ ast_channel_unlock(chan);
+ state_chan = ast_channel_get_t38_state(chan);
+ state_peer = ast_channel_get_t38_state(peer);
+ ast_channel_lock(chan);
+
/* don't start a gateway if neither channel can handle T.38 */
- if (ast_channel_get_t38_state(chan) == T38_STATE_UNAVAILABLE && ast_channel_get_t38_state(peer) == T38_STATE_UNAVAILABLE) {
+ if (state_chan == T38_STATE_UNAVAILABLE && state_peer == T38_STATE_UNAVAILABLE) {
ast_debug(1, "not starting gateway for %s and %s; neither channel supports T.38\n", ast_channel_name(chan), ast_channel_name(peer));
ast_framehook_detach(chan, gateway->framehook);
details->gateway_id = -1;
@@ -3332,6 +3395,7 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct
ast_string_field_set(details, result, "FAILED");
ast_string_field_set(details, resultstr, "neither channel supports T.38");
ast_string_field_set(details, error, "T38_NEG_ERROR");
+ details->is_t38_negotiated = 0;
set_channel_variables(chan, details);
return f;
}
@@ -3376,6 +3440,7 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct
ast_string_field_set(details, result, "FAILED");
ast_string_field_build(details, resultstr, "no fax activity after %d ms", details->gateway_timeout);
ast_string_field_set(details, error, "TIMEOUT");
+ details->is_t38_negotiated = 0;
set_channel_variables(chan, details);
return f;
}
@@ -3491,9 +3556,9 @@ static int fax_gateway_attach(struct ast_channel *chan, struct ast_fax_session_d
.disable_inheritance = 1, /* Masquerade inheritance is handled through the datastore fixup */
};
- if (global_fax_debug) {
- details->option.debug = AST_FAX_OPTFLAG_TRUE;
- }
+ if (global_fax_debug) {
+ details->option.debug = AST_FAX_OPTFLAG_TRUE;
+ }
ast_string_field_set(details, result, "SUCCESS");
ast_string_field_set(details, resultstr, "gateway operation started successfully");
@@ -3506,6 +3571,7 @@ static int fax_gateway_attach(struct ast_channel *chan, struct ast_fax_session_d
ast_string_field_set(details, result, "FAILED");
ast_string_field_set(details, resultstr, "error initializing gateway session");
ast_string_field_set(details, error, "INIT_ERROR");
+ details->is_t38_negotiated = 0;
set_channel_variables(chan, details);
report_fax_status(chan, details, "No Available Resource");
return -1;
@@ -3521,6 +3587,7 @@ static int fax_gateway_attach(struct ast_channel *chan, struct ast_fax_session_d
ast_string_field_set(details, result, "FAILED");
ast_string_field_set(details, resultstr, "error attaching gateway to channel");
ast_string_field_set(details, error, "INIT_ERROR");
+ details->is_t38_negotiated = 0;
set_channel_variables(chan, details);
return -1;
}
@@ -4509,7 +4576,9 @@ static int acf_faxopt_write(struct ast_channel *chan, const char *cmd, char *dat
ast_log(LOG_WARNING, "Attempt to attach a T.38 gateway on channel (%s) with gateway already running.\n", ast_channel_name(chan));
}
} else if (ast_false(val)) {
+ ast_channel_lock(chan);
ast_framehook_detach(chan, details->gateway_id);
+ ast_channel_unlock(chan);
details->gateway_id = -1;
} else {
ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(%s).\n", value, data);
@@ -4561,7 +4630,9 @@ static int acf_faxopt_write(struct ast_channel *chan, const char *cmd, char *dat
ast_log(LOG_WARNING, "Attempt to attach a FAX detect on channel (%s) with FAX detect already running.\n", ast_channel_name(chan));
}
} else if (ast_false(val)) {
+ ast_channel_lock(chan);
ast_framehook_detach(chan, details->faxdetect_id);
+ ast_channel_unlock(chan);
details->faxdetect_id = -1;
} else {
ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(%s).\n", value, data);
diff --git a/res/res_format_attr_g729.c b/res/res_format_attr_g729.c
new file mode 100644
index 000000000..5ba4920d9
--- /dev/null
+++ b/res/res_format_attr_g729.c
@@ -0,0 +1,76 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2016, Digium, Inc.
+ *
+ * Jason Parker <jparker@sangoma.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*** MODULEINFO
+ <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_REGISTER_FILE()
+
+#include "asterisk/module.h"
+#include "asterisk/format.h"
+
+/* Destroy is a required callback and must exist */
+static void g729_destroy(struct ast_format *format)
+{
+}
+
+/* Clone is a required callback and must exist */
+static int g729_clone(const struct ast_format *src, struct ast_format *dst)
+{
+ return 0;
+}
+
+static void g729_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str)
+{
+ /*
+ * According to the rfc the joint annexb format parameter should be set to 'yes'
+ * or 'no' based on the answerer (rfc7261 - 3.3). However, Asterisk being a B2BUA
+ * makes things tricky. So for now Asterisk will set annexb=no.
+ */
+ ast_str_append(str, 0, "a=fmtp:%u annexb=no\r\n", payload);
+}
+
+static struct ast_format_interface g729_interface = {
+ .format_destroy = g729_destroy,
+ .format_clone = g729_clone,
+ .format_generate_sdp_fmtp = g729_generate_sdp_fmtp,
+};
+
+static int load_module(void)
+{
+ if (ast_format_interface_register("g729", &g729_interface)) {
+ return AST_MODULE_LOAD_DECLINE;
+ }
+
+ return AST_MODULE_LOAD_SUCCESS;
+}
+
+static int unload_module(void)
+{
+ return 0;
+}
+
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "G.729 Format Attribute Module",
+ .support_level = AST_MODULE_SUPPORT_CORE,
+ .load = load_module,
+ .unload = unload_module,
+ .load_pri = AST_MODPRI_CHANNEL_DEPEND,
+);
diff --git a/res/res_odbc.c b/res/res_odbc.c
index 31ea29b03..2477def5b 100644
--- a/res/res_odbc.c
+++ b/res/res_odbc.c
@@ -41,6 +41,7 @@
/*** MODULEINFO
<depend>generic_odbc</depend>
+ <depend>res_odbc_transaction</depend>
<depend>ltdl</depend>
<support_level>core</support_level>
***/
diff --git a/res/res_odbc_transaction.c b/res/res_odbc_transaction.c
index 33800c3ce..7e48b72cf 100644
--- a/res/res_odbc_transaction.c
+++ b/res/res_odbc_transaction.c
@@ -26,7 +26,7 @@
#include "asterisk/module.h"
/*** MODULEINFO
- <depend>res_odbc</depend>
+ <depend>generic_odbc</depend>
<support_level>core</support_level>
***/
diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index aafb3a211..96c07d501 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -913,6 +913,12 @@
then the <replaceable>context</replaceable> setting is used.
</para></description>
</configOption>
+ <configOption name="contact_user" default="">
+ <synopsis>Force the user on the outgoing Contact header to this value.</synopsis>
+ <description><para>
+ On outbound requests, force the user portion of the Contact header to this value.
+ </para></description>
+ </configOption>
</configObject>
<configObject name="auth">
<synopsis>Authentication type</synopsis>
@@ -2869,8 +2875,16 @@ pjsip_dialog *ast_sip_create_dialog_uac(const struct ast_sip_endpoint *endpoint,
/* Update the dialog with the new local URI, we do it afterwards so we can use the dialog pool for construction */
pj_strdup_with_null(dlg->pool, &dlg->local.info_str, &local_uri);
dlg->local.info->uri = pjsip_parse_uri(dlg->pool, dlg->local.info_str.ptr, dlg->local.info_str.slen, 0);
+
dlg->local.contact = pjsip_parse_hdr(dlg->pool, &HCONTACT, local_uri.ptr, local_uri.slen, NULL);
+ if (!ast_strlen_zero(endpoint->contact_user)) {
+ pjsip_sip_uri *sip_uri;
+
+ sip_uri = pjsip_uri_get_uri(dlg->local.contact->uri);
+ pj_strdup2(dlg->pool, &sip_uri->user, endpoint->contact_user);
+ }
+
/* If a request user has been specified and we are permitted to change it, do so */
if (!ast_strlen_zero(request_user)) {
pjsip_sip_uri *sip_uri;
@@ -3172,6 +3186,18 @@ static int create_out_of_dialog_request(const pjsip_method *method, struct ast_s
return -1;
}
+ if (endpoint && !ast_strlen_zero(endpoint->contact_user)){
+ pjsip_contact_hdr *contact_hdr;
+ pjsip_sip_uri *contact_uri;
+ static const pj_str_t HCONTACT = { "Contact", 7 };
+
+ contact_hdr = pjsip_msg_find_hdr_by_name((*tdata)->msg, &HCONTACT, NULL);
+ if (contact_hdr) {
+ contact_uri = pjsip_uri_get_uri(contact_hdr->uri);
+ pj_strdup2(pool, &contact_uri->user, endpoint->contact_user);
+ }
+ }
+
/* Add the user=phone parameter if applicable */
ast_sip_add_usereqphone(endpoint, (*tdata)->pool, (*tdata)->msg->line.req.uri);
diff --git a/res/res_pjsip/config_global.c b/res/res_pjsip/config_global.c
index 975c5eefe..281630ae4 100644
--- a/res/res_pjsip/config_global.c
+++ b/res/res_pjsip/config_global.c
@@ -48,6 +48,15 @@
#define DEFAULT_MWI_TPS_QUEUE_LOW -1
#define DEFAULT_MWI_DISABLE_INITIAL_UNSOLICITED 0
+/*!
+ * \brief Cached global config object
+ *
+ * \details
+ * Cached so we don't have to keep asking sorcery for the config.
+ * We could ask for it hundreds of times a second if not more.
+ */
+static AO2_GLOBAL_OBJ_STATIC(global_cfg);
+
static char default_useragent[256];
struct global_config {
@@ -67,21 +76,21 @@ struct global_config {
/*! Realm to use in challenges before an endpoint is identified */
AST_STRING_FIELD(default_realm);
);
- /* Value to put in Max-Forwards header */
+ /*! Value to put in Max-Forwards header */
unsigned int max_forwards;
- /* The interval at which to send keep alive messages to active connection-oriented transports */
+ /*! The interval at which to send keep alive messages to active connection-oriented transports */
unsigned int keep_alive_interval;
- /* The maximum time for all contacts to be qualified at startup */
+ /*! The maximum time for all contacts to be qualified at startup */
unsigned int max_initial_qualify_time;
- /* The interval at which to check for expired contacts */
+ /*! The interval at which to check for expired contacts */
unsigned int contact_expiration_check_interval;
/*! Nonzero to disable multi domain support */
unsigned int disable_multi_domain;
- /* The maximum number of unidentified requests per source IP address before a security event is logged */
+ /*! The maximum number of unidentified requests per source IP address before a security event is logged */
unsigned int unidentified_request_count;
- /* The period during which unidentified requests are accumulated */
+ /*! The period during which unidentified requests are accumulated */
unsigned int unidentified_request_period;
- /* Interval at which expired unidentifed requests will be pruned */
+ /*! Interval at which expired unidentifed requests will be pruned */
unsigned int unidentified_request_prune_interval;
struct {
/*! Taskprocessor high water alert trigger level */
@@ -135,23 +144,14 @@ static int global_apply(const struct ast_sorcery *sorcery, void *obj)
ast_sip_add_global_request_header("Max-Forwards", max_forwards, 1);
ast_sip_add_global_request_header("User-Agent", cfg->useragent, 1);
ast_sip_add_global_response_header("Server", cfg->useragent, 1);
+
+ ao2_t_global_obj_replace_unref(global_cfg, cfg, "Applying global settings");
return 0;
}
static struct global_config *get_global_cfg(void)
{
- struct global_config *cfg;
- struct ao2_container *globals;
-
- globals = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "global",
- AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
- if (!globals) {
- return NULL;
- }
-
- cfg = ao2_find(globals, NULL, 0);
- ao2_ref(globals, -1);
- return cfg;
+ return ao2_global_obj_ref(global_cfg);
}
char *ast_sip_global_default_outbound_endpoint(void)
@@ -462,6 +462,8 @@ int ast_sip_destroy_sorcery_global(void)
ast_sorcery_instance_observer_remove(sorcery, &observer_callbacks_global);
+ ao2_t_global_obj_release(global_cfg, "Module is unloading");
+
return 0;
}
@@ -508,7 +510,8 @@ int ast_sip_initialize_sorcery_global(void)
ast_sorcery_object_field_register(sorcery, "global", "contact_expiration_check_interval",
__stringify(DEFAULT_CONTACT_EXPIRATION_CHECK_INTERVAL),
OPT_UINT_T, 0, FLDSET(struct global_config, contact_expiration_check_interval));
- ast_sorcery_object_field_register(sorcery, "global", "disable_multi_domain", "no",
+ ast_sorcery_object_field_register(sorcery, "global", "disable_multi_domain",
+ DEFAULT_DISABLE_MULTI_DOMAIN ? "yes" : "no",
OPT_BOOL_T, 1, FLDSET(struct global_config, disable_multi_domain));
ast_sorcery_object_field_register(sorcery, "global", "unidentified_request_count",
__stringify(DEFAULT_UNIDENTIFIED_REQUEST_COUNT),
diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c
index 9e757e230..478e5c7d7 100644
--- a/res/res_pjsip/pjsip_configuration.c
+++ b/res/res_pjsip/pjsip_configuration.c
@@ -606,6 +606,10 @@ static int ident_handler(const struct aco_option *opt, struct ast_variable *var,
endpoint->ident_method = 0;
return -1;
}
+ if (endpoint->ident_method & method) {
+ /* We are already indentifying by this method. No need to do it again. */
+ continue;
+ }
endpoint->ident_method |= method;
AST_VECTOR_APPEND(&endpoint->ident_method_order, method);
@@ -966,7 +970,9 @@ static int dtls_handler(const struct aco_option *opt,
{
struct ast_sip_endpoint *endpoint = obj;
char *name = ast_strdupa(var->name);
- char *front, *back, *buf = name;
+ char *front = NULL;
+ char *back = NULL;
+ char *buf = name;
/* strip out underscores in the name */
front = strtok_r(buf, "_", &back);
@@ -1211,6 +1217,31 @@ static int voicemail_extension_to_str(const void *obj, const intptr_t *args, cha
return 0;
}
+static int contact_user_handler(const struct aco_option *opt,
+ struct ast_variable *var, void *obj)
+{
+ struct ast_sip_endpoint *endpoint = obj;
+
+ endpoint->contact_user = ast_strdup(var->value);
+ if (!endpoint->contact_user) {
+ return -1;
+ }
+
+ return 0;
+}
+
+static int contact_user_to_str(const void *obj, const intptr_t *args, char **buf)
+{
+ const struct ast_sip_endpoint *endpoint = obj;
+
+ *buf = ast_strdup(endpoint->contact_user);
+ if (!(*buf)) {
+ return -1;
+ }
+
+ return 0;
+}
+
static void *sip_nat_hook_alloc(const char *name)
{
return ast_sorcery_generic_alloc(sizeof(struct ast_sip_nat_hook), NULL);
@@ -1265,7 +1296,7 @@ static struct ast_endpoint *persistent_endpoint_find_or_create(const struct ast_
return NULL;
}
- ast_endpoint_set_state(persistent->endpoint, AST_ENDPOINT_UNKNOWN);
+ ast_endpoint_set_state(persistent->endpoint, AST_ENDPOINT_OFFLINE);
ao2_link_flags(persistent_endpoints, persistent, OBJ_NOLOCK);
}
@@ -1907,6 +1938,7 @@ int ast_res_pjsip_initialize_configuration(const struct ast_module_info *ast_mod
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "contact_permit", "", endpoint_acl_handler, NULL, NULL, 0, 0);
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "contact_acl", "", endpoint_acl_handler, contact_acl_to_str, NULL, 0, 0);
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "subscribe_context", "", OPT_CHAR_ARRAY_T, 0, CHARFLDSET(struct ast_sip_endpoint, subscription.context));
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "contact_user", "", contact_user_handler, contact_user_to_str, NULL, 0, 0);
if (ast_sip_initialize_sorcery_transport()) {
ast_log(LOG_ERROR, "Failed to register SIP transport support with sorcery\n");
@@ -2038,6 +2070,7 @@ static void endpoint_destructor(void* obj)
ao2_cleanup(endpoint->persistent);
ast_variables_destroy(endpoint->channel_vars);
AST_VECTOR_FREE(&endpoint->ident_method_order);
+ ast_free(endpoint->contact_user);
}
static int init_subscription_configuration(struct ast_sip_endpoint_subscription_configuration *subscription)
diff --git a/res/res_pjsip/pjsip_options.c b/res/res_pjsip/pjsip_options.c
index 6f7455d50..d87188363 100644
--- a/res/res_pjsip/pjsip_options.c
+++ b/res/res_pjsip/pjsip_options.c
@@ -53,6 +53,9 @@ static const char *short_status_map [] = {
[REMOVED] = "Removed",
};
+static void contact_deleted(const void *obj);
+static void qualify_and_schedule(struct ast_sip_contact *contact);
+
const char *ast_sip_get_contact_status_label(const enum ast_sip_contact_status_type status)
{
return status_map[status];
@@ -106,6 +109,29 @@ static void *contact_status_alloc(const char *name)
return status;
}
+static int qualify_and_schedule_aor_contact(void *obj)
+{
+ struct ast_sip_contact *contact = obj;
+ struct ast_sip_aor *aor;
+
+ if (!contact || ast_strlen_zero(contact->aor) ||
+ !(aor = ast_sip_location_retrieve_aor(contact->aor))) {
+ ao2_ref(contact, -1);
+ return -1;
+ }
+
+ contact->qualify_frequency = aor->qualify_frequency;
+ contact->qualify_timeout = aor->qualify_timeout;
+ contact->authenticate_qualify = aor->authenticate_qualify;
+
+ ao2_ref(aor, -1);
+
+ qualify_and_schedule(contact);
+ ao2_ref(contact, -1);
+
+ return 0;
+}
+
AST_MUTEX_DEFINE_STATIC(creation_lock);
/*!
@@ -147,6 +173,18 @@ struct ast_sip_contact_status *ast_res_pjsip_find_or_create_contact_status(const
return NULL;
}
+ /* The permanent contact added after asterisk start should be qualified. */
+ if (ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED) && ast_tvzero(contact->expiration_time)) {
+ /*
+ * The FULLY_BOOTED to filter out contacts that already existed when asterisk started.
+ * The zero expiration_time to select only permanent contacts.
+ */
+ ao2_ref((struct ast_sip_contact *) contact, +1);
+ if (ast_sip_push_task(NULL, qualify_and_schedule_aor_contact, (struct ast_sip_contact *) contact)) {
+ ao2_ref((struct ast_sip_contact *) contact, -1);
+ }
+ }
+
ast_statsd_log_string_va("PJSIP.contacts.states.%s", AST_STATSD_GAUGE,
"+1", 1.0, ast_sip_get_contact_status_label(status->status));
@@ -378,8 +416,9 @@ static int qualify_contact(struct ast_sip_endpoint *endpoint, struct ast_sip_con
endpoint_local = find_an_endpoint(contact);
}
if (!endpoint_local) {
- ast_log(LOG_ERROR, "Unable to find an endpoint to qualify contact %s\n",
+ ast_log(LOG_WARNING, "Unable to find an endpoint to qualify contact %s. Deleting this contact\n",
contact->uri);
+ contact_deleted(contact);
return -1;
}
}
diff --git a/res/res_pjsip_refer.c b/res/res_pjsip_refer.c
index e5bb90e5c..8fe4e8477 100644
--- a/res/res_pjsip_refer.c
+++ b/res/res_pjsip_refer.c
@@ -607,7 +607,10 @@ static void refer_blind_callback(struct ast_channel *chan, struct transfer_chann
ao2_ref(refer->progress, +1);
/* If we can't attach a frame hook for whatever reason send a notification of success immediately */
- if ((refer->progress->framehook = ast_framehook_attach(chan, &hook)) < 0) {
+ ast_channel_lock(chan);
+ refer->progress->framehook = ast_framehook_attach(chan, &hook);
+ ast_channel_unlock(chan);
+ if (refer->progress->framehook < 0) {
struct refer_progress_notification *notification = refer_progress_notification_alloc(refer->progress, 200,
PJSIP_EVSUB_STATE_TERMINATED);
@@ -638,7 +641,9 @@ static void refer_blind_callback(struct ast_channel *chan, struct transfer_chann
refer_progress_notify(notification);
}
+ ast_channel_lock(chan);
ast_framehook_detach(chan, refer->progress->framehook);
+ ast_channel_unlock(chan);
ao2_cleanup(refer->progress);
}
diff --git a/res/res_pjsip_registrar.c b/res/res_pjsip_registrar.c
index 53209575f..1e0f5ab72 100644
--- a/res/res_pjsip_registrar.c
+++ b/res/res_pjsip_registrar.c
@@ -563,6 +563,7 @@ static int match_aor(const char *aor_name, const char *id)
static char *find_aor_name(const char *username, const char *domain, const char *aors)
{
char *configured_aors;
+ char *aors_buf;
char *aor_name;
char *id_domain;
struct ast_sip_domain_alias *alias;
@@ -570,8 +571,10 @@ static char *find_aor_name(const char *username, const char *domain, const char
id_domain = ast_alloca(strlen(username) + strlen(domain) + 2);
sprintf(id_domain, "%s@%s", username, domain);
+ aors_buf = ast_strdupa(aors);
+
/* Look for exact match on username@domain */
- configured_aors = ast_strdupa(aors);
+ configured_aors = aors_buf;
while ((aor_name = ast_strip(strsep(&configured_aors, ",")))) {
if (match_aor(aor_name, id_domain)) {
return ast_strdup(aor_name);
@@ -586,7 +589,7 @@ static char *find_aor_name(const char *username, const char *domain, const char
sprintf(id_domain, "%s@%s", username, alias->domain);
ao2_cleanup(alias);
- configured_aors = ast_strdupa(aors);
+ configured_aors = strcpy(aors_buf, aors);/* Safe */
while ((aor_name = ast_strip(strsep(&configured_aors, ",")))) {
if (match_aor(aor_name, id_domain_alias)) {
return ast_strdup(aor_name);
@@ -594,8 +597,13 @@ static char *find_aor_name(const char *username, const char *domain, const char
}
}
+ if (ast_strlen_zero(username)) {
+ /* No username, no match */
+ return NULL;
+ }
+
/* Look for exact match on username only */
- configured_aors = ast_strdupa(aors);
+ configured_aors = strcpy(aors_buf, aors);/* Safe */
while ((aor_name = ast_strip(strsep(&configured_aors, ",")))) {
if (match_aor(aor_name, username)) {
return ast_strdup(aor_name);
diff --git a/res/res_pjsip_t38.c b/res/res_pjsip_t38.c
index 992902af2..01bfefdd9 100644
--- a/res/res_pjsip_t38.c
+++ b/res/res_pjsip_t38.c
@@ -501,25 +501,27 @@ static void t38_attach_framehook(struct ast_sip_session *session)
return;
}
- /* Skip attaching the framehook if the T.38 datastore already exists for the channel */
ast_channel_lock(session->channel);
- if ((datastore = ast_channel_datastore_find(session->channel, &t38_framehook_datastore, NULL))) {
+
+ /* Skip attaching the framehook if the T.38 datastore already exists for the channel */
+ datastore = ast_channel_datastore_find(session->channel, &t38_framehook_datastore,
+ NULL);
+ if (datastore) {
ast_channel_unlock(session->channel);
return;
}
- ast_channel_unlock(session->channel);
framehook_id = ast_framehook_attach(session->channel, &hook);
if (framehook_id < 0) {
- ast_log(LOG_WARNING, "Could not attach T.38 Frame hook to channel, T.38 will be unavailable on '%s'\n",
+ ast_log(LOG_WARNING, "Could not attach T.38 Frame hook, T.38 will be unavailable on '%s'\n",
ast_channel_name(session->channel));
+ ast_channel_unlock(session->channel);
return;
}
- ast_channel_lock(session->channel);
datastore = ast_datastore_alloc(&t38_framehook_datastore, NULL);
if (!datastore) {
- ast_log(LOG_ERROR, "Could not attach T.38 Frame hook to channel, T.38 will be unavailable on '%s'\n",
+ ast_log(LOG_ERROR, "Could not alloc T.38 Frame hook datastore, T.38 will be unavailable on '%s'\n",
ast_channel_name(session->channel));
ast_framehook_detach(session->channel, framehook_id);
ast_channel_unlock(session->channel);
diff --git a/res/res_rtp_multicast.c b/res/res_rtp_multicast.c
index 53bdf14a4..ea313476e 100644
--- a/res/res_rtp_multicast.c
+++ b/res/res_rtp_multicast.c
@@ -143,7 +143,7 @@ struct ast_multicast_rtp_options *ast_multicast_rtp_create_options(const char *t
mcast_options = ast_calloc(1, sizeof(*mcast_options)
+ strlen(type)
- + strlen(options) + 2);
+ + strlen(S_OR(options, "")) + 2);
if (!mcast_options) {
return NULL;
}
@@ -155,8 +155,9 @@ struct ast_multicast_rtp_options *ast_multicast_rtp_create_options(const char *t
mcast_options->type = pos;
pos += strlen(type) + 1;
- /* Safe */
- strcpy(pos, options);
+ if (!ast_strlen_zero(options)) {
+ strcpy(pos, options); /* Safe */
+ }
mcast_options->options = pos;
if (ast_app_parse_options(multicast_rtp_options, &mcast_options->opts,