summaryrefslogtreecommitdiffstats
path: root/dom/media/webrtc/transport/third_party/nrappkit/src/registry/registrycb.c
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/webrtc/transport/third_party/nrappkit/src/registry/registrycb.c')
-rw-r--r--dom/media/webrtc/transport/third_party/nrappkit/src/registry/registrycb.c440
1 files changed, 440 insertions, 0 deletions
diff --git a/dom/media/webrtc/transport/third_party/nrappkit/src/registry/registrycb.c b/dom/media/webrtc/transport/third_party/nrappkit/src/registry/registrycb.c
new file mode 100644
index 0000000000..4b326a1ee2
--- /dev/null
+++ b/dom/media/webrtc/transport/third_party/nrappkit/src/registry/registrycb.c
@@ -0,0 +1,440 @@
+/*
+ *
+ * registrycb.c
+ *
+ * $Source: /Users/ekr/tmp/nrappkit-dump/nrappkit/src/registry/registrycb.c,v $
+ * $Revision: 1.3 $
+ * $Date: 2007/06/26 22:37:51 $
+ *
+ * Callback-related functions
+ *
+ *
+ * Copyright (C) 2005, Network Resonance, Inc.
+ * Copyright (C) 2006, Network Resonance, Inc.
+ * All Rights Reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Network Resonance, Inc. nor the name of any
+ * contributors to this software may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ */
+
+#include <assert.h>
+#include <string.h>
+#include "registry.h"
+#include "registry_int.h"
+#include "r_assoc.h"
+#include "r_errors.h"
+#include "nr_common.h"
+#include "r_log.h"
+#include "r_macros.h"
+
+static char CB_ACTIONS[] = { NR_REG_CB_ACTION_ADD,
+ NR_REG_CB_ACTION_DELETE,
+ NR_REG_CB_ACTION_CHANGE,
+ NR_REG_CB_ACTION_FINAL };
+
+typedef struct nr_reg_cb_info_ {
+ char action;
+ void (*cb)(void *cb_arg, char action, NR_registry name);
+ void *cb_arg;
+ NR_registry name;
+} nr_reg_cb_info;
+
+/* callbacks that are registered, a mapping from names like "foo.bar.baz"
+ * to an r_assoc which contains possibly several nr_reg_cb_info*'s */
+static r_assoc *nr_registry_callbacks = 0;
+
+//static size_t SIZEOF_CB_ID = (sizeof(void (*)()) + 1);
+#define SIZEOF_CB_ID (sizeof(void (*)()) + 1)
+
+static int nr_reg_validate_action(char action);
+static int nr_reg_assoc_destroy(void *ptr);
+static int compute_cb_id(void *cb, char action, unsigned char cb_id[SIZEOF_CB_ID]);
+static int nr_reg_info_free(void *ptr);
+static int nr_reg_raise_event_recurse(char *name, char *tmp, int action);
+static int nr_reg_register_callback(NR_registry name, char action, void (*cb)(void *cb_arg, char action, NR_registry name), void *cb_arg);
+static int nr_reg_unregister_callback(char *name, char action, void (*cb)(void *cb_arg, char action, NR_registry name));
+
+int
+nr_reg_cb_init()
+{
+ int r, _status;
+
+ if (nr_registry_callbacks == 0) {
+ if ((r=r_assoc_create(&nr_registry_callbacks, r_assoc_crc32_hash_compute, 12)))
+ ABORT(r);
+ }
+
+ _status=0;
+ abort:
+ if (_status) {
+ r_log(NR_LOG_REGISTRY, LOG_DEBUG, "Couldn't init notifications: %s", nr_strerror(_status));
+ }
+ return(_status);
+}
+
+int
+nr_reg_validate_action(char action)
+{
+ int _status;
+ size_t i;
+
+ for (i = 0; i < sizeof(CB_ACTIONS); ++i) {
+ if (action == CB_ACTIONS[i])
+ return 0;
+ }
+ ABORT(R_BAD_ARGS);
+
+ _status=0;
+ abort:
+ return(_status);
+}
+
+int
+nr_reg_register_callback(NR_registry name, char action, void (*cb)(void *cb_arg, char action, NR_registry name), void *cb_arg)
+{
+ int r, _status;
+ r_assoc *assoc;
+ int create_assoc = 0;
+ nr_reg_cb_info *info;
+ int create_info = 0;
+ unsigned char cb_id[SIZEOF_CB_ID];
+
+ if (name == 0 || cb == 0)
+ ABORT(R_BAD_ARGS);
+
+ if (nr_registry_callbacks == 0)
+ ABORT(R_FAILED);
+
+ if ((r=nr_reg_is_valid(name)))
+ ABORT(r);
+
+ if ((r=nr_reg_validate_action(action)))
+ ABORT(r);
+
+ if ((r=r_assoc_fetch(nr_registry_callbacks, name, strlen(name)+1, (void*)&assoc))) {
+ if (r == R_NOT_FOUND)
+ create_assoc = 1;
+ else
+ ABORT(r);
+ }
+
+ if (create_assoc) {
+ if ((r=r_assoc_create(&assoc, r_assoc_crc32_hash_compute, 5)))
+ ABORT(r);
+
+ if ((r=r_assoc_insert(nr_registry_callbacks, name, strlen(name)+1, assoc, 0, nr_reg_assoc_destroy, R_ASSOC_NEW)))
+ ABORT(r);
+ }
+
+ if ((r=compute_cb_id(cb, action, cb_id)))
+ ABORT(r);
+
+ if ((r=r_assoc_fetch(assoc, (char*)cb_id, SIZEOF_CB_ID, (void*)&info))) {
+ if (r == R_NOT_FOUND)
+ create_info = 1;
+ else
+ ABORT(r);
+ }
+
+ if (create_info) {
+ if (!(info=(void*)RCALLOC(sizeof(*info))))
+ ABORT(R_NO_MEMORY);
+ }
+
+ strncpy(info->name, name, sizeof(info->name));
+ info->action = action;
+ info->cb = cb;
+ info->cb_arg = cb_arg;
+
+ if (create_info) {
+ if ((r=r_assoc_insert(assoc, (char*)cb_id, SIZEOF_CB_ID, info, 0, nr_reg_info_free, R_ASSOC_NEW)))
+ ABORT(r);
+ }
+
+ _status=0;
+ abort:
+ r_log(NR_LOG_REGISTRY, LOG_DEBUG, "register callback %p on '%s' for '%s' %s", cb, name, nr_reg_action_name(action), (_status ? "FAILED" : "succeeded"));
+
+ if (_status) {
+ if (create_info && info) RFREE(info);
+ if (create_assoc && assoc) nr_reg_assoc_destroy(&assoc);
+ }
+ return(_status);
+}
+
+int
+nr_reg_unregister_callback(char *name, char action, void (*cb)(void *cb_arg, char action, NR_registry name))
+{
+ int r, _status;
+ r_assoc *assoc;
+ int size;
+ unsigned char cb_id[SIZEOF_CB_ID];
+
+ if (name == 0 || cb == 0)
+ ABORT(R_BAD_ARGS);
+
+ if (nr_registry_callbacks == 0)
+ ABORT(R_FAILED);
+
+ if ((r=nr_reg_is_valid(name)))
+ ABORT(r);
+
+ if ((r=nr_reg_validate_action(action)))
+ ABORT(r);
+
+ if ((r=r_assoc_fetch(nr_registry_callbacks, name, strlen(name)+1, (void*)&assoc))) {
+ if (r != R_NOT_FOUND)
+ ABORT(r);
+ }
+ else {
+ if ((r=compute_cb_id(cb, action, cb_id)))
+ ABORT(r);
+
+ if ((r=r_assoc_delete(assoc, (char*)cb_id, SIZEOF_CB_ID))) {
+ if (r != R_NOT_FOUND)
+ ABORT(r);
+ }
+
+ if ((r=r_assoc_num_elements(assoc, &size)))
+ ABORT(r);
+
+ if (size == 0) {
+ if ((r=r_assoc_delete(nr_registry_callbacks, name, strlen(name)+1)))
+ ABORT(r);
+ }
+ }
+
+ _status=0;
+ abort:
+ r_log(NR_LOG_REGISTRY, LOG_DEBUG, "unregister callback %p on '%s' for '%s' %s", cb, name, nr_reg_action_name(action), (_status ? "FAILED" : "succeeded"));
+
+ return(_status);
+}
+
+int
+compute_cb_id(void *cb, char action, unsigned char cb_id[SIZEOF_CB_ID])
+{
+ /* callbacks are identified by the pointer to the cb function plus
+ * the action being watched */
+ assert(sizeof(cb) == sizeof(void (*)()));
+ assert(sizeof(cb) == (SIZEOF_CB_ID - 1));
+
+ memcpy(cb_id, &(cb), sizeof(cb));
+ cb_id[SIZEOF_CB_ID-1] = action;
+
+ return 0;
+}
+
+char *
+nr_reg_action_name(int action)
+{
+ char *name = "*Unknown*";
+
+ switch (action) {
+ case NR_REG_CB_ACTION_ADD: name = "add"; break;
+ case NR_REG_CB_ACTION_DELETE: name = "delete"; break;
+ case NR_REG_CB_ACTION_CHANGE: name = "change"; break;
+ case NR_REG_CB_ACTION_FINAL: name = "final"; break;
+ }
+
+ return name;
+}
+
+int
+nr_reg_assoc_destroy(void *ptr)
+{
+ return r_assoc_destroy((r_assoc**)&ptr);
+}
+
+int
+nr_reg_info_free(void *ptr)
+{
+ RFREE(ptr);
+ return 0;
+}
+
+/* call with tmp=0 */
+int
+nr_reg_raise_event_recurse(char *name, char *tmp, int action)
+{
+ int r, _status;
+ r_assoc *assoc;
+ nr_reg_cb_info *info;
+ r_assoc_iterator iter;
+ char *key;
+ int keyl;
+ char *c;
+ int free_tmp = 0;
+ int count;
+
+ if (tmp == 0) {
+ if (!(tmp = (char*)r_strdup(name)))
+ ABORT(R_NO_MEMORY);
+ free_tmp = 1;
+ }
+
+ if ((r=r_assoc_fetch(nr_registry_callbacks, tmp, strlen(tmp)+1, (void*)&assoc))) {
+ if (r != R_NOT_FOUND)
+ ABORT(r);
+
+ r_log(NR_LOG_REGISTRY, LOG_DEBUG, "No callbacks found on '%s'", tmp);
+ }
+ else {
+ if (!r_assoc_num_elements(assoc, &count)) {
+ r_log(NR_LOG_REGISTRY, LOG_DEBUG, "%d callback%s found on '%s'",
+ count, ((count == 1) ? "" : "s"), tmp);
+ }
+
+ if ((r=r_assoc_init_iter(assoc, &iter)))
+ ABORT(r);
+
+ for (;;) {
+ if ((r=r_assoc_iter(&iter, (void*)&key, &keyl, (void*)&info))) {
+ if (r == R_EOD)
+ break;
+ else
+ ABORT(r);
+ }
+
+ if (info->action == action) {
+ r_log(NR_LOG_REGISTRY, LOG_DEBUG,
+ "Invoking callback %p for '%s'",
+ info->cb,
+ nr_reg_action_name(info->action));
+
+ (void)info->cb(info->cb_arg, action, name);
+ }
+ else {
+ r_log(NR_LOG_REGISTRY, LOG_DEBUG,
+ "Skipping callback %p for '%s'",
+ info->cb,
+ nr_reg_action_name(info->action));
+ }
+ }
+ }
+
+ if (strlen(tmp) > 0) {
+ c = strrchr(tmp, '.');
+ if (c != 0)
+ *c = '\0';
+ else
+ tmp[0] = '\0';
+
+ if ((r=nr_reg_raise_event_recurse(name, tmp, action)))
+ ABORT(r);
+ }
+
+ _status=0;
+ abort:
+ if (free_tmp && tmp != 0) RFREE(tmp);
+ return(_status);
+}
+
+
+/* NON-STATIC METHODS */
+
+int
+nr_reg_raise_event(NR_registry name, int action)
+{
+ int r, _status;
+ int count;
+ char *event = nr_reg_action_name(action);
+
+ r_log(NR_LOG_REGISTRY, LOG_DEBUG, "raising event '%s' on '%s'", event, name);
+
+ if (name == 0)
+ ABORT(R_BAD_ARGS);
+
+ if ((r=nr_reg_validate_action(action)))
+ ABORT(r);
+
+ if ((r=r_assoc_num_elements(nr_registry_callbacks, &count)))
+ ABORT(r);
+
+ if (count > 0) {
+ if ((r=nr_reg_raise_event_recurse(name, 0, action)))
+ ABORT(r);
+ }
+ else {
+ r_log(NR_LOG_REGISTRY, LOG_DEBUG, "No callbacks found");
+ return 0;
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+}
+
+
+/* PUBLIC METHODS */
+
+int
+NR_reg_register_callback(NR_registry name, char action, void (*cb)(void *cb_arg, char action, NR_registry name), void *cb_arg)
+{
+ int r, _status;
+ size_t i;
+
+ for (i = 0; i < sizeof(CB_ACTIONS); ++i) {
+ if (action & CB_ACTIONS[i]) {
+ if ((r=nr_reg_register_callback(name, CB_ACTIONS[i], cb, cb_arg)))
+ ABORT(r);
+
+ action &= ~(CB_ACTIONS[i]);
+ }
+ }
+
+ if (action)
+ ABORT(R_BAD_ARGS);
+
+ _status=0;
+ abort:
+ return(_status);
+}
+
+int
+NR_reg_unregister_callback(NR_registry name, char action, void (*cb)(void *cb_arg, char action, NR_registry name))
+{
+ int r, _status;
+ size_t i;
+
+ for (i = 0; i < sizeof(CB_ACTIONS); ++i) {
+ if (action & CB_ACTIONS[i]) {
+ if ((r=nr_reg_unregister_callback(name, CB_ACTIONS[i], cb)))
+ ABORT(r);
+
+ action &= ~(CB_ACTIONS[i]);
+ }
+ }
+
+ if (action)
+ ABORT(R_BAD_ARGS);
+
+ _status=0;
+ abort:
+ return(_status);
+}