media/mtransport/third_party/nrappkit/src/registry/registrycb.c

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /*
     2  *
     3  *    registrycb.c
     4  *
     5  *    $Source: /Users/ekr/tmp/nrappkit-dump/nrappkit/src/registry/registrycb.c,v $
     6  *    $Revision: 1.3 $
     7  *    $Date: 2007/06/26 22:37:51 $
     8  *
     9  *    Callback-related functions
    10  *
    11  *
    12  *    Copyright (C) 2005, Network Resonance, Inc.
    13  *    Copyright (C) 2006, Network Resonance, Inc.
    14  *    All Rights Reserved
    15  *
    16  *    Redistribution and use in source and binary forms, with or without
    17  *    modification, are permitted provided that the following conditions
    18  *    are met:
    19  *
    20  *    1. Redistributions of source code must retain the above copyright
    21  *       notice, this list of conditions and the following disclaimer.
    22  *    2. Redistributions in binary form must reproduce the above copyright
    23  *       notice, this list of conditions and the following disclaimer in the
    24  *       documentation and/or other materials provided with the distribution.
    25  *    3. Neither the name of Network Resonance, Inc. nor the name of any
    26  *       contributors to this software may be used to endorse or promote
    27  *       products derived from this software without specific prior written
    28  *       permission.
    29  *
    30  *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
    31  *    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    32  *    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    33  *    ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
    34  *    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    35  *    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    36  *    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    37  *    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    38  *    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    39  *    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    40  *    POSSIBILITY OF SUCH DAMAGE.
    41  *
    42  *
    43  */
    45 #include <assert.h>
    46 #include <string.h>
    47 #include "registry.h"
    48 #include "registry_int.h"
    49 #include "r_assoc.h"
    50 #include "r_errors.h"
    51 #include "nr_common.h"
    52 #include "r_log.h"
    53 #include "r_macros.h"
    55 static char CB_ACTIONS[] = { NR_REG_CB_ACTION_ADD,
    56                              NR_REG_CB_ACTION_DELETE,
    57                              NR_REG_CB_ACTION_CHANGE,
    58                              NR_REG_CB_ACTION_FINAL };
    60 typedef struct nr_reg_cb_info_ {
    61      char            action;
    62      void          (*cb)(void *cb_arg, char action, NR_registry name);
    63      void           *cb_arg;
    64      NR_registry     name;
    65 } nr_reg_cb_info;
    67 /* callbacks that are registered, a mapping from names like "foo.bar.baz"
    68  * to an r_assoc which contains possibly several nr_reg_cb_info*'s */
    69 static r_assoc     *nr_registry_callbacks = 0;
    71 //static size_t SIZEOF_CB_ID = (sizeof(void (*)()) + 1);
    72 #define SIZEOF_CB_ID  (sizeof(void (*)()) + 1)
    74 static int nr_reg_validate_action(char action);
    75 static int nr_reg_assoc_destroy(void *ptr);
    76 static int compute_cb_id(void *cb, char action, unsigned char cb_id[SIZEOF_CB_ID]);
    77 static int nr_reg_info_free(void *ptr);
    78 static int nr_reg_raise_event_recurse(char *name, char *tmp, int action);
    79 static int nr_reg_register_callback(NR_registry name, char action, void (*cb)(void *cb_arg, char action, NR_registry name), void *cb_arg);
    80 static int nr_reg_unregister_callback(char *name, char action, void (*cb)(void *cb_arg, char action, NR_registry name));
    82 int
    83 nr_reg_cb_init()
    84 {
    85     int r, _status;
    87     if (nr_registry_callbacks == 0) {
    88         if ((r=r_assoc_create(&nr_registry_callbacks, r_assoc_crc32_hash_compute, 12)))
    89             ABORT(r);
    90     }
    92     _status=0;
    93   abort:
    94     if (_status) {
    95        r_log(NR_LOG_REGISTRY, LOG_DEBUG, "Couldn't init notifications: %s", nr_strerror(_status));
    96     }
    97     return(_status);
    98 }
   100 int
   101 nr_reg_validate_action(char action)
   102 {
   103     int _status;
   104     int i;
   106     for (i = 0; i < sizeof(CB_ACTIONS); ++i) {
   107         if (action == CB_ACTIONS[i])
   108             return 0;
   109     }
   110     ABORT(R_BAD_ARGS);
   112     _status=0;
   113   abort:
   114     return(_status);
   115 }
   117 int
   118 nr_reg_register_callback(NR_registry name, char action, void (*cb)(void *cb_arg, char action, NR_registry name), void *cb_arg)
   119 {
   120     int r, _status;
   121     r_assoc *assoc;
   122     int create_assoc = 0;
   123     nr_reg_cb_info *info;
   124     int create_info = 0;
   125     unsigned char cb_id[SIZEOF_CB_ID];
   127     if (name == 0 || cb == 0)
   128       ABORT(R_BAD_ARGS);
   130     if (nr_registry_callbacks == 0)
   131       ABORT(R_FAILED);
   133     if ((r=nr_reg_is_valid(name)))
   134       ABORT(r);
   136     if ((r=nr_reg_validate_action(action)))
   137       ABORT(r);
   139     if ((r=r_assoc_fetch(nr_registry_callbacks, name, strlen(name)+1, (void*)&assoc))) {
   140       if (r == R_NOT_FOUND)
   141         create_assoc = 1;
   142       else
   143         ABORT(r);
   144     }
   146     if (create_assoc) {
   147       if ((r=r_assoc_create(&assoc, r_assoc_crc32_hash_compute, 5)))
   148         ABORT(r);
   150       if ((r=r_assoc_insert(nr_registry_callbacks, name, strlen(name)+1, assoc, 0, nr_reg_assoc_destroy, R_ASSOC_NEW)))
   151         ABORT(r);
   152     }
   154     if ((r=compute_cb_id(cb, action, cb_id)))
   155       ABORT(r);
   157     if ((r=r_assoc_fetch(assoc, (char*)cb_id, SIZEOF_CB_ID, (void*)&info))) {
   158       if (r == R_NOT_FOUND)
   159         create_info = 1;
   160       else
   161         ABORT(r);
   162     }
   164     if (create_info) {
   165       if (!(info=(void*)RCALLOC(sizeof(*info))))
   166         ABORT(R_NO_MEMORY);
   167     }
   169     strncpy(info->name, name, sizeof(info->name));
   170     info->action = action;
   171     info->cb = cb;
   172     info->cb_arg = cb_arg;
   174     if (create_info) {
   175       if ((r=r_assoc_insert(assoc, (char*)cb_id, SIZEOF_CB_ID, info, 0, nr_reg_info_free, R_ASSOC_NEW)))
   176         ABORT(r);
   177     }
   179     _status=0;
   180   abort:
   181     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"));
   183     if (_status) {
   184       if (create_info && info) RFREE(info);
   185       if (create_assoc && assoc) nr_reg_assoc_destroy(&assoc);
   186     }
   187     return(_status);
   188 }
   190 int
   191 nr_reg_unregister_callback(char *name, char action, void (*cb)(void *cb_arg, char action, NR_registry name))
   192 {
   193     int r, _status;
   194     r_assoc *assoc;
   195     int size;
   196     unsigned char cb_id[SIZEOF_CB_ID];
   198     if (name == 0 || cb == 0)
   199       ABORT(R_BAD_ARGS);
   201     if (nr_registry_callbacks == 0)
   202       ABORT(R_FAILED);
   204     if ((r=nr_reg_is_valid(name)))
   205       ABORT(r);
   207     if ((r=nr_reg_validate_action(action)))
   208       ABORT(r);
   210     if ((r=r_assoc_fetch(nr_registry_callbacks, name, strlen(name)+1, (void*)&assoc))) {
   211       if (r != R_NOT_FOUND)
   212         ABORT(r);
   213     }
   214     else {
   215       if ((r=compute_cb_id(cb, action, cb_id)))
   216         ABORT(r);
   218       if ((r=r_assoc_delete(assoc, (char*)cb_id, SIZEOF_CB_ID))) {
   219         if (r != R_NOT_FOUND)
   220           ABORT(r);
   221       }
   223       if ((r=r_assoc_num_elements(assoc, &size)))
   224         ABORT(r);
   226       if (size == 0) {
   227         if ((r=r_assoc_delete(nr_registry_callbacks, name, strlen(name)+1)))
   228           ABORT(r);
   229       }
   230     }
   232     _status=0;
   233   abort:
   234     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"));
   236     return(_status);
   237 }
   239 int
   240 compute_cb_id(void *cb, char action, unsigned char cb_id[SIZEOF_CB_ID])
   241 {
   242    /* callbacks are identified by the pointer to the cb function plus
   243     * the action being watched */
   244    assert(sizeof(cb) == sizeof(void (*)()));
   245    assert(sizeof(cb) == (SIZEOF_CB_ID - 1));
   247    memcpy(cb_id, &(cb), sizeof(cb));
   248    cb_id[SIZEOF_CB_ID-1] = action;
   250    return 0;
   251 }
   253 char *
   254 nr_reg_action_name(int action)
   255 {
   256     char *name = "*Unknown*";
   258     switch (action) {
   259     case NR_REG_CB_ACTION_ADD:     name = "add";     break;
   260     case NR_REG_CB_ACTION_DELETE:  name = "delete";  break;
   261     case NR_REG_CB_ACTION_CHANGE:  name = "change";  break;
   262     case NR_REG_CB_ACTION_FINAL:   name = "final";  break;
   263     }
   265     return name;
   266 }
   268 int
   269 nr_reg_assoc_destroy(void *ptr)
   270 {
   271   return r_assoc_destroy((r_assoc**)&ptr);
   272 }
   274 int
   275 nr_reg_info_free(void *ptr)
   276 {
   277   RFREE(ptr);
   278   return 0;
   279 }
   281 /* call with tmp=0 */
   282 int
   283 nr_reg_raise_event_recurse(char *name, char *tmp, int action)
   284 {
   285     int r, _status;
   286     r_assoc *assoc;
   287     nr_reg_cb_info *info;
   288     r_assoc_iterator iter;
   289     char *key;
   290     int keyl;
   291     char *c;
   292     int free_tmp = 0;
   293     int count;
   295     if (tmp == 0) {
   296       if (!(tmp = (char*)r_strdup(name)))
   297         ABORT(R_NO_MEMORY);
   298       free_tmp = 1;
   299     }
   301     if ((r=r_assoc_fetch(nr_registry_callbacks, tmp, strlen(tmp)+1, (void*)&assoc))) {
   302       if (r != R_NOT_FOUND)
   303         ABORT(r);
   305       r_log(NR_LOG_REGISTRY, LOG_DEBUG, "No callbacks found on '%s'", tmp);
   306     }
   307     else {
   308       if (!r_assoc_num_elements(assoc, &count)) {
   309           r_log(NR_LOG_REGISTRY, LOG_DEBUG, "%d callback%s found on '%s'",
   310                 count, ((count == 1) ? "" : "s"), tmp);
   311       }
   313       if ((r=r_assoc_init_iter(assoc, &iter)))
   314           ABORT(r);
   316       for (;;) {
   317         if ((r=r_assoc_iter(&iter, (void*)&key, &keyl, (void*)&info))) {
   318           if (r == R_EOD)
   319             break;
   320           else
   321             ABORT(r);
   322         }
   324         if (info->action == action) {
   325           r_log(NR_LOG_REGISTRY, LOG_DEBUG,
   326                 "Invoking callback %p for '%s'",
   327                 info->cb,
   328                 nr_reg_action_name(info->action));
   330           (void)info->cb(info->cb_arg, action, name);
   331         }
   332         else {
   333           r_log(NR_LOG_REGISTRY, LOG_DEBUG,
   334                 "Skipping callback %p for '%s'",
   335                 info->cb,
   336                 nr_reg_action_name(info->action));
   337         }
   338       }
   339     }
   341     if (strlen(tmp) > 0) {
   342         c = strrchr(tmp, '.');
   343         if (c != 0)
   344           *c = '\0';
   345         else
   346           tmp[0] = '\0';
   348         if ((r=nr_reg_raise_event_recurse(name, tmp, action)))
   349           ABORT(r);
   350     }
   352     _status=0;
   353   abort:
   354     if (free_tmp && tmp != 0) RFREE(tmp);
   355     return(_status);
   356 }
   359 /* NON-STATIC METHODS */
   361 int
   362 nr_reg_raise_event(char *name, int action)
   363 {
   364     int r, _status;
   365     int count;
   366     char *event = nr_reg_action_name(action);
   368     r_log(NR_LOG_REGISTRY, LOG_DEBUG, "raising event '%s' on '%s'", event, name);
   370     if (name == 0)
   371       ABORT(R_BAD_ARGS);
   373     if ((r=nr_reg_validate_action(action)))
   374       ABORT(r);
   376     if ((r=r_assoc_num_elements(nr_registry_callbacks, &count)))
   377       ABORT(r);
   379     if (count > 0) {
   380       if ((r=nr_reg_raise_event_recurse(name, 0, action)))
   381         ABORT(r);
   382     }
   383     else {
   384       r_log(NR_LOG_REGISTRY, LOG_DEBUG, "No callbacks found");
   385       return 0;
   386     }
   388     _status=0;
   389   abort:
   390     return(_status);
   391 }
   394 /* PUBLIC METHODS */
   396 int
   397 NR_reg_register_callback(NR_registry name, char action, void (*cb)(void *cb_arg, char action, NR_registry name), void *cb_arg)
   398 {
   399     int r, _status;
   400     int i;
   402     for (i = 0; i < sizeof(CB_ACTIONS); ++i) {
   403         if (action & CB_ACTIONS[i]) {
   404             if ((r=nr_reg_register_callback(name, CB_ACTIONS[i], cb, cb_arg)))
   405                 ABORT(r);
   407             action &= ~(CB_ACTIONS[i]);
   408         }
   409     }
   411     if (action)
   412         ABORT(R_BAD_ARGS);
   414     _status=0;
   415   abort:
   416     return(_status);
   417 }
   419 int
   420 NR_reg_unregister_callback(char *name, char action, void (*cb)(void *cb_arg, char action, NR_registry name))
   421 {
   422     int r, _status;
   423     int i;
   425     for (i = 0; i < sizeof(CB_ACTIONS); ++i) {
   426         if (action & CB_ACTIONS[i]) {
   427             if ((r=nr_reg_unregister_callback(name, CB_ACTIONS[i], cb)))
   428                 ABORT(r);
   430             action &= ~(CB_ACTIONS[i]);
   431         }
   432     }
   434     if (action)
   435         ABORT(R_BAD_ARGS);
   437     _status=0;
   438   abort:
   439     return(_status);
   440 }

mercurial