diff options
Diffstat (limited to 'res')
-rw-r--r-- | res/res.xml | 6 | ||||
-rw-r--r-- | res/res_ari.c | 16 | ||||
-rw-r--r-- | res/res_ari_applications.c | 6 | ||||
-rw-r--r-- | res/res_ari_asterisk.c | 26 | ||||
-rw-r--r-- | res/res_ari_bridges.c | 16 | ||||
-rw-r--r-- | res/res_ari_channels.c | 34 | ||||
-rw-r--r-- | res/res_ari_device_states.c | 4 | ||||
-rw-r--r-- | res/res_ari_endpoints.c | 10 | ||||
-rw-r--r-- | res/res_ari_events.c | 6 | ||||
-rw-r--r-- | res/res_ari_mailboxes.c | 4 | ||||
-rw-r--r-- | res/res_ari_playbacks.c | 6 | ||||
-rw-r--r-- | res/res_ari_recordings.c | 18 | ||||
-rw-r--r-- | res/res_ari_sounds.c | 4 | ||||
-rw-r--r-- | res/res_fax.c | 109 | ||||
-rw-r--r-- | res/res_format_attr_g729.c | 76 | ||||
-rw-r--r-- | res/res_odbc.c | 1 | ||||
-rw-r--r-- | res/res_odbc_transaction.c | 2 | ||||
-rw-r--r-- | res/res_pjsip.c | 26 | ||||
-rw-r--r-- | res/res_pjsip/config_global.c | 43 | ||||
-rw-r--r-- | res/res_pjsip/pjsip_configuration.c | 37 | ||||
-rw-r--r-- | res/res_pjsip/pjsip_options.c | 41 | ||||
-rw-r--r-- | res/res_pjsip_refer.c | 7 | ||||
-rw-r--r-- | res/res_pjsip_registrar.c | 14 | ||||
-rw-r--r-- | res/res_pjsip_t38.c | 14 | ||||
-rw-r--r-- | res/res_rtp_multicast.c | 7 |
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, |