mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-13 00:04:53 +00:00
Merge in current pimp_my_sip work, including:
1. Security events 2. Websocket support 3. Diversion header + redirecting support 4. An anonymous endpoint identifier 5. Inbound extension state subscription support 6. PIDF notify generation 7. One touch recording support (special thanks Sean Bright!) 8. Blind and attended transfer support 9. Automatic inbound registration expiration 10. SRTP support 11. Media offer control dialplan function 12. Connected line support 13. SendText() support 14. Qualify support 15. Inband DTMF detection 16. Call and pickup groups 17. Messaging support Thanks everyone! Side note: I'm reminded of the song "How Far We've Come" by Matchbox Twenty. git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@392565 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -134,8 +134,93 @@ static char *handle_cli_show_endpoints(struct ast_cli_entry *e, int cmd, struct
|
||||
return CLI_SUCCESS;
|
||||
}
|
||||
|
||||
static int show_contact(void *obj, void *arg, int flags)
|
||||
{
|
||||
struct ast_sip_contact *contact = obj;
|
||||
struct ast_cli_args *a = arg;
|
||||
RAII_VAR(struct ast_sip_contact_status *, status, ast_sorcery_retrieve_by_id(
|
||||
ast_sip_get_sorcery(), CONTACT_STATUS,
|
||||
ast_sorcery_object_get_id(contact)), ao2_cleanup);
|
||||
|
||||
ast_cli(a->fd, "\tContact %s:\n", contact->uri);
|
||||
|
||||
if (!status) {
|
||||
ast_cli(a->fd, "\tStatus not found!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ast_cli(a->fd, "\t\tavailable = %s\n", status->status ? "yes" : "no");
|
||||
|
||||
if (status->status) {
|
||||
ast_cli(a->fd, "\t\tRTT = %lld microseconds\n", (long long)status->rtt);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void show_endpoint(struct ast_sip_endpoint *endpoint, struct ast_cli_args *a)
|
||||
{
|
||||
char *aor_name, *aors;
|
||||
|
||||
if (ast_strlen_zero(endpoint->aors)) {
|
||||
return;
|
||||
}
|
||||
|
||||
aors = ast_strdupa(endpoint->aors);
|
||||
|
||||
while ((aor_name = strsep(&aors, ","))) {
|
||||
RAII_VAR(struct ast_sip_aor *, aor,
|
||||
ast_sip_location_retrieve_aor(aor_name), ao2_cleanup);
|
||||
RAII_VAR(struct ao2_container *, contacts, NULL, ao2_cleanup);
|
||||
|
||||
if (!aor || !(contacts = ast_sip_location_retrieve_aor_contacts(aor))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ast_cli(a->fd, "AOR %s:\n", ast_sorcery_object_get_id(aor));
|
||||
ao2_callback(contacts, OBJ_NODATA, show_contact, a);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static char *cli_show_endpoint(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
||||
{
|
||||
RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
|
||||
const char *endpoint_name;
|
||||
|
||||
switch (cmd) {
|
||||
case CLI_INIT:
|
||||
e->command = "sip show endpoint";
|
||||
e->usage =
|
||||
"Usage: sip show endpoint <endpoint>\n"
|
||||
" Show the given SIP endpoint.\n";
|
||||
return NULL;
|
||||
case CLI_GENERATE:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (a->argc != 4) {
|
||||
return CLI_SHOWUSAGE;
|
||||
}
|
||||
|
||||
endpoint_name = a->argv[3];
|
||||
|
||||
if (!(endpoint = ast_sorcery_retrieve_by_id(
|
||||
ast_sip_get_sorcery(), "endpoint", endpoint_name))) {
|
||||
ast_cli(a->fd, "Unable to retrieve endpoint %s\n", endpoint_name);
|
||||
return CLI_FAILURE;
|
||||
}
|
||||
|
||||
ast_cli(a->fd, "Endpoint %s:\n", endpoint_name);
|
||||
show_endpoint(endpoint, a);
|
||||
|
||||
return CLI_SUCCESS;
|
||||
}
|
||||
|
||||
static struct ast_cli_entry cli_commands[] = {
|
||||
AST_CLI_DEFINE(handle_cli_show_endpoints, "Show SIP Endpoints"),
|
||||
AST_CLI_DEFINE(cli_show_endpoint, "Show SIP Endpoint")
|
||||
};
|
||||
|
||||
static int dtmf_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
|
||||
@@ -291,6 +376,22 @@ static int direct_media_method_handler(const struct aco_option *opt, struct ast_
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int connected_line_method_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
|
||||
{
|
||||
struct ast_sip_endpoint *endpoint = obj;
|
||||
|
||||
if (!strcasecmp(var->value, "invite") || !strcasecmp(var->value, "reinvite")) {
|
||||
endpoint->connected_line_method = AST_SIP_SESSION_REFRESH_METHOD_INVITE;
|
||||
} else if (!strcasecmp(var->value, "update")) {
|
||||
endpoint->connected_line_method = AST_SIP_SESSION_REFRESH_METHOD_UPDATE;
|
||||
} else {
|
||||
ast_log(LOG_NOTICE, "Unrecognized option value %s for %s on endpoint %s\n",
|
||||
var->value, var->name, ast_sorcery_object_get_id(endpoint));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int direct_media_glare_mitigation_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
|
||||
{
|
||||
struct ast_sip_endpoint *endpoint = obj;
|
||||
@@ -353,6 +454,65 @@ static int caller_id_tag_handler(const struct aco_option *opt, struct ast_variab
|
||||
return endpoint->id.tag ? 0 : -1;
|
||||
}
|
||||
|
||||
static int media_encryption_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
|
||||
{
|
||||
struct ast_sip_endpoint *endpoint = obj;
|
||||
|
||||
if (!strcasecmp("no", var->value)) {
|
||||
endpoint->media_encryption = AST_SIP_MEDIA_ENCRYPT_NONE;
|
||||
} else if (!strcasecmp("sdes", var->value)) {
|
||||
endpoint->media_encryption = AST_SIP_MEDIA_ENCRYPT_SDES;
|
||||
/*} else if (!strcasecmp("dtls", var->value)) {
|
||||
endpoint->media_encryption = AST_SIP_MEDIA_ENCRYPT_DTLS;*/
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int group_handler(const struct aco_option *opt,
|
||||
struct ast_variable *var, void *obj)
|
||||
{
|
||||
struct ast_sip_endpoint *endpoint = obj;
|
||||
|
||||
if (!strncmp(var->name, "callgroup", 9)) {
|
||||
if (!(endpoint->callgroup = ast_get_group(var->value))) {
|
||||
return -1;
|
||||
}
|
||||
} else if (!strncmp(var->name, "pickupgroup", 11)) {
|
||||
if (!(endpoint->pickupgroup = ast_get_group(var->value))) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int named_groups_handler(const struct aco_option *opt,
|
||||
struct ast_variable *var, void *obj)
|
||||
{
|
||||
struct ast_sip_endpoint *endpoint = obj;
|
||||
|
||||
if (!strncmp(var->name, "namedcallgroup", 14)) {
|
||||
if (!(endpoint->named_callgroups =
|
||||
ast_get_namedgroups(var->value))) {
|
||||
return -1;
|
||||
}
|
||||
} else if (!strncmp(var->name, "namedpickupgroup", 16)) {
|
||||
if (!(endpoint->named_pickupgroups =
|
||||
ast_get_namedgroups(var->value))) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *sip_nat_hook_alloc(const char *name)
|
||||
{
|
||||
return ao2_alloc(sizeof(struct ast_sip_nat_hook), NULL);
|
||||
@@ -450,7 +610,6 @@ int ast_res_sip_initialize_configuration(void)
|
||||
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "context", "default", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, context));
|
||||
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "disallow", "", OPT_CODEC_T, 0, FLDSET(struct ast_sip_endpoint, prefs, codecs));
|
||||
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "allow", "", OPT_CODEC_T, 1, FLDSET(struct ast_sip_endpoint, prefs, codecs));
|
||||
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "qualify_frequency", 0, OPT_UINT_T, PARSE_IN_RANGE, FLDSET(struct ast_sip_endpoint, qualify_frequency), 0, 86400);
|
||||
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtmfmode", "rfc4733", dtmf_handler, NULL, 0, 0);
|
||||
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtp_ipv6", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, rtp_ipv6));
|
||||
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtp_symmetric", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, rtp_symmetric));
|
||||
@@ -472,6 +631,7 @@ int ast_res_sip_initialize_configuration(void)
|
||||
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "identify_by", "username,location", ident_handler, NULL, 0, 0);
|
||||
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "direct_media", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, direct_media));
|
||||
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "direct_media_method", "invite", direct_media_method_handler, NULL, 0, 0);
|
||||
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "connected_line_method", "invite", connected_line_method_handler, NULL, 0, 0);
|
||||
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "direct_media_glare_mitigation", "none", direct_media_glare_mitigation_handler, NULL, 0, 0);
|
||||
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "disable_direct_media_on_nat", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, disable_direct_media_on_nat));
|
||||
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "callerid", "", caller_id_handler, NULL, 0, 0);
|
||||
@@ -481,8 +641,17 @@ int ast_res_sip_initialize_configuration(void)
|
||||
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "trust_id_outbound", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, trust_id_outbound));
|
||||
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "send_pai", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, send_pai));
|
||||
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "send_rpid", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, send_rpid));
|
||||
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "send_diversion", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, send_diversion));
|
||||
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "mailboxes", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, mailboxes));
|
||||
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "aggregate_mwi", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, aggregate_mwi));
|
||||
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "media_encryption", "no", media_encryption_handler, NULL, 0, 0);
|
||||
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "use_avpf", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, use_avpf));
|
||||
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "one_touch_recording", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, one_touch_recording));
|
||||
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "inband_progress", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, inband_progress));
|
||||
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "callgroup", "", group_handler, NULL, 0, 0);
|
||||
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "pickupgroup", "", group_handler, NULL, 0, 0);
|
||||
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "namedcallgroup", "", named_groups_handler, NULL, 0, 0);
|
||||
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "namedpickupgroup", "", named_groups_handler, NULL, 0, 0);
|
||||
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "devicestate_busy_at", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, devicestate_busy_at));
|
||||
|
||||
if (ast_sip_initialize_sorcery_transport(sip_sorcery)) {
|
||||
@@ -499,6 +668,13 @@ int ast_res_sip_initialize_configuration(void)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ast_sip_initialize_sorcery_qualify(sip_sorcery)) {
|
||||
ast_log(LOG_ERROR, "Failed to register SIP qualify support with sorcery\n");
|
||||
ast_sorcery_unref(sip_sorcery);
|
||||
sip_sorcery = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ast_sorcery_observer_add(sip_sorcery, "contact", &state_contact_observer);
|
||||
|
||||
if (ast_sip_initialize_sorcery_domain_alias(sip_sorcery)) {
|
||||
@@ -539,6 +715,8 @@ static void endpoint_destructor(void* obj)
|
||||
destroy_auths(endpoint->sip_inbound_auths, endpoint->num_inbound_auths);
|
||||
destroy_auths(endpoint->sip_outbound_auths, endpoint->num_outbound_auths);
|
||||
ast_party_id_free(&endpoint->id);
|
||||
endpoint->named_callgroups = ast_unref_namedgroups(endpoint->named_callgroups);
|
||||
endpoint->named_pickupgroups = ast_unref_namedgroups(endpoint->named_pickupgroups);
|
||||
ao2_cleanup(endpoint->persistent);
|
||||
}
|
||||
|
||||
@@ -596,4 +774,3 @@ struct ast_sorcery *ast_sip_get_sorcery(void)
|
||||
{
|
||||
return sip_sorcery;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user