Merge "res_calendar: Specialized calendars depend on symbols of general calendar."
[asterisk/asterisk.git] / main / core_local.c
index 98db5e5..23c7cce 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "asterisk.h"
 
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
 /* ------------------------------------------------------------------- */
 
 #include "asterisk/channel.h"
@@ -235,6 +233,41 @@ struct local_pvt {
        char exten[AST_MAX_EXTENSION];
 };
 
+void ast_local_lock_all(struct ast_channel *chan, void **tech_pvt,
+       struct ast_channel **base_chan, struct ast_channel **base_owner)
+{
+       struct local_pvt *p = ast_channel_tech_pvt(chan);
+
+       *tech_pvt = NULL;
+       *base_chan = NULL;
+       *base_owner = NULL;
+
+       if (p) {
+               *tech_pvt = ao2_bump(p);
+               ast_unreal_lock_all(&p->base, base_chan, base_owner);
+       }
+}
+
+void ast_local_unlock_all(void *tech_pvt, struct ast_channel *base_chan,
+       struct ast_channel *base_owner)
+{
+       if (base_chan) {
+               ast_channel_unlock(base_chan);
+               ast_channel_unref(base_chan);
+       }
+
+       if (base_owner) {
+               ast_channel_unlock(base_owner);
+               ast_channel_unref(base_owner);
+       }
+
+       if (tech_pvt) {
+               struct local_pvt *p = tech_pvt;
+               ao2_unlock(&p->base);
+               ao2_ref(tech_pvt, -1);
+       }
+}
+
 struct ast_channel *ast_local_get_peer(struct ast_channel *ast)
 {
        struct local_pvt *p = ast_channel_tech_pvt(ast);
@@ -328,12 +361,12 @@ static struct ast_multi_channel_blob *local_channel_optimization_blob(struct loc
        RAII_VAR(struct ast_channel_snapshot *, local_one_snapshot, NULL, ao2_cleanup);
        RAII_VAR(struct ast_channel_snapshot *, local_two_snapshot, NULL, ao2_cleanup);
 
-       local_one_snapshot = ast_channel_snapshot_create(p->base.owner);
+       local_one_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(p->base.owner));
        if (!local_one_snapshot) {
                return NULL;
        }
 
-       local_two_snapshot = ast_channel_snapshot_create(p->base.chan);
+       local_two_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(p->base.chan));
        if (!local_two_snapshot) {
                return NULL;
        }
@@ -357,6 +390,10 @@ static void local_optimization_started_cb(struct ast_unreal_pvt *base, struct as
        RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
        struct local_pvt *p = (struct local_pvt *)base;
 
+       if (!ast_local_optimization_begin_type()) {
+               return;
+       }
+
        json_object = ast_json_pack("{s: i, s: i}",
                        "dest", dest, "id", id);
 
@@ -371,7 +408,7 @@ static void local_optimization_started_cb(struct ast_unreal_pvt *base, struct as
 
        if (source) {
                RAII_VAR(struct ast_channel_snapshot *, source_snapshot, NULL, ao2_cleanup);
-               source_snapshot = ast_channel_snapshot_create(source);
+               source_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(source));
                if (!source_snapshot) {
                        return;
                }
@@ -395,6 +432,10 @@ static void local_optimization_finished_cb(struct ast_unreal_pvt *base, int succ
        RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
        struct local_pvt *p = (struct local_pvt *)base;
 
+       if (!ast_local_optimization_end_type()) {
+               return;
+       }
+
        json_object = ast_json_pack("{s: i, s: i}", "success", success, "id", id);
 
        if (!json_object) {
@@ -501,6 +542,10 @@ static void publish_local_bridge_message(struct local_pvt *p)
        struct ast_channel *owner;
        struct ast_channel *chan;
 
+       if (!ast_local_bridge_type()) {
+               return;
+       }
+
        ast_unreal_lock_all(&p->base, &chan, &owner);
 
        blob = ast_json_pack("{s: s, s: s, s: b}",
@@ -516,12 +561,12 @@ static void publish_local_bridge_message(struct local_pvt *p)
                goto end;
        }
 
-       one_snapshot = ast_channel_snapshot_create(owner);
+       one_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(owner));
        if (!one_snapshot) {
                goto end;
        }
 
-       two_snapshot = ast_channel_snapshot_create(chan);
+       two_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(chan));
        if (!two_snapshot) {
                goto end;
        }
@@ -873,7 +918,7 @@ static struct ast_channel *local_request(const char *type, struct ast_format_cap
 {
        struct local_pvt *p;
        struct ast_channel *chan;
-       struct ast_callid *callid;
+       ast_callid callid;
 
        /* Allocate a new private structure and then Asterisk channels */
        p = local_alloc(data, cap);
@@ -886,9 +931,6 @@ static struct ast_channel *local_request(const char *type, struct ast_format_cap
        if (chan) {
                ao2_link(locals, p);
        }
-       if (callid) {
-               ast_callid_unref(callid);
-       }
        ao2_ref(p, -1); /* kill the ref from the alloc */
 
        return chan;
@@ -989,26 +1031,16 @@ static int locals_cmp_cb(void *obj, void *arg, int flags)
  */
 static void local_shutdown(void)
 {
-       struct local_pvt *p;
-       struct ao2_iterator it;
-
        /* First, take us out of the channel loop */
        ast_cli_unregister_multiple(cli_local, ARRAY_LEN(cli_local));
        ast_manager_unregister("LocalOptimizeAway");
        ast_channel_unregister(&local_tech);
 
-       it = ao2_iterator_init(locals, 0);
-       while ((p = ao2_iterator_next(&it))) {
-               if (p->base.owner) {
-                       ast_softhangup(p->base.owner, AST_SOFTHANGUP_APPUNLOAD);
-               }
-               ao2_ref(p, -1);
-       }
-       ao2_iterator_destroy(&it);
        ao2_ref(locals, -1);
        locals = NULL;
 
-       ast_format_cap_destroy(local_tech.capabilities);
+       ao2_cleanup(local_tech.capabilities);
+       local_tech.capabilities = NULL;
 
        STASIS_MESSAGE_TYPE_CLEANUP(ast_local_optimization_begin_type);
        STASIS_MESSAGE_TYPE_CLEANUP(ast_local_optimization_end_type);
@@ -1030,14 +1062,15 @@ int ast_local_init(void)
                return -1;
        }
 
-       if (!(local_tech.capabilities = ast_format_cap_alloc(0))) {
+       if (!(local_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
                return -1;
        }
-       ast_format_cap_add_all(local_tech.capabilities);
+       ast_format_cap_append_by_type(local_tech.capabilities, AST_MEDIA_TYPE_UNKNOWN);
 
        locals = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_MUTEX, 0, NULL, locals_cmp_cb);
        if (!locals) {
-               ast_format_cap_destroy(local_tech.capabilities);
+               ao2_cleanup(local_tech.capabilities);
+               local_tech.capabilities = NULL;
                return -1;
        }
 
@@ -1045,12 +1078,13 @@ int ast_local_init(void)
        if (ast_channel_register(&local_tech)) {
                ast_log(LOG_ERROR, "Unable to register channel class 'Local'\n");
                ao2_ref(locals, -1);
-               ast_format_cap_destroy(local_tech.capabilities);
+               ao2_cleanup(local_tech.capabilities);
+               local_tech.capabilities = NULL;
                return -1;
        }
        ast_cli_register_multiple(cli_local, ARRAY_LEN(cli_local));
        ast_manager_register_xml_core("LocalOptimizeAway", EVENT_FLAG_SYSTEM|EVENT_FLAG_CALL, manager_optimize_away);
 
-       ast_register_atexit(local_shutdown);
+       ast_register_cleanup(local_shutdown);
        return 0;
 }