summaryrefslogtreecommitdiff
path: root/server/class.c
diff options
context:
space:
mode:
authorGravatar Greg Hudson <ghudson@mit.edu>1997-09-14 17:50:06 +0000
committerGravatar Greg Hudson <ghudson@mit.edu>1997-09-14 17:50:06 +0000
commitac16f380e349fa39ec7e26bccb5456cb300006a5 (patch)
treec07ca88af97b4f6b77d28a2dc723d2e4621ed302 /server/class.c
parentd33e482744fad80d95cdd89ed380c5b8401e49bf (diff)
Pull in sources from zephyr locker. See /mit/zephyr/repository for
detailed change information.
Diffstat (limited to 'server/class.c')
-rw-r--r--server/class.c562
1 files changed, 225 insertions, 337 deletions
diff --git a/server/class.c b/server/class.c
index b70bf4e..b4c46d8 100644
--- a/server/class.c
+++ b/server/class.c
@@ -12,41 +12,40 @@
*/
#include <zephyr/mit-copyright.h>
+#include "zserver.h" /* includes zephyr/zephyr.h */
+#include <assert.h>
#if !defined (lint) && !defined (SABER)
-static char rcsid_class_c[] =
- "$Id$";
+static const char rcsid_class_c[] =
+"$Id$";
#endif
-#include "zserver.h" /* includes zephyr/zephyr.h */
-
-#include <ctype.h> /* for isupper, tolower */
-
/*
* Class manager subsystem.
*
*
* External functions are:
*
- * Code_t triplet_register(client, subs)
+ * Code_t triplet_register(client, subs, realm)
*
- * Code_t triplet_deregister(client, subs)
+ * Code_t triplet_deregister(client, subs, realm)
*
- * ZClientList_t *triplet_lookup(subs)
- * ZClient_t *client;
- * ZSubscr_t *subs;
+ * Client *triplet_lookup(subs)
+ * Client *client;
+ * Destlist *subs;
*
- * ZAcl_t *class_get_acl(ZString class_name)
+ * Acl *class_get_acl(class_name)
+ * String *class_name;
*
* Code_t class_restrict(class_name, acl)
* char *class_name;
- * ZAcl_t *acl;
+ * Acl *acl;
*
* Code_t class_setup_restricted(class_name, acl)
* char *class_name;
- * ZAcl_t *acl;
+ * Acl *acl;
*
- * and several ZDestination methods.
+ * and several Destination methods.
*/
/*
@@ -56,7 +55,7 @@ static char rcsid_class_c[] =
* name (which hashes into the bucket associated with this list) and a
* doubly linked list of clients which are interested in this class.
* The data pointed to by these clients is owned by other modules. Care
- * must be taken by the caller not to register a free()'d client
+ * must be taken by the caller not to a free()'d client
* structure.
*
* If any hash bucket is empty, the pointer is null.
@@ -71,26 +70,23 @@ static char rcsid_class_c[] =
/* Private variables */
#define EMPTY_CLASS 2000
+#define ALLOC_OFFSET 8 /* Allocate 32 bytes less than a power of 2. */
+#define ALLOC_INIT 8 /* Initial number of subscriptions. */
+
#define HASHSIZE 1023
#define HASHVAL(c, i, r) (((c)->hash_val ^ (i)->hash_val ^ (r)->hash_val) \
% HASHSIZE)
#define DEST_HASHVAL(dest) HASHVAL((dest).classname, (dest).inst, (dest).recip)
-static ZTriplet_t *class_bucket[HASHSIZE]; /* the hash table of pointers */
-
+static Triplet *triplet_bucket[HASHSIZE]; /* the hash table of pointers */
-#ifdef __STDC__
-# define P(s) s
-#else
-# define P(s) ()
-#endif
-
-static Code_t remove_client P((ZTriplet_t *ptr, ZClient_t *client));
-static Code_t insert_client P((ZTriplet_t *ptr, ZClient_t *client));
-static ZClientList_t *client_alloc P((ZClient_t *client));
-static ZTriplet_t *triplet_alloc P((ZSTRING *classname, ZSTRING *inst,
- ZSTRING *recipient));
-static void free_class P((ZTriplet_t *));
+static Code_t remove_client __P((Triplet *triplet, Client *client,
+ Realm *realm));
+static Code_t insert_client __P((Triplet *triplet, Client *client,
+ Realm *realm));
+static Triplet *triplet_alloc __P((String *classname, String *inst,
+ String *recipient));
+static void free_triplet __P((Triplet *));
/* public routines */
@@ -102,169 +98,112 @@ static void free_class P((ZTriplet_t *));
* been case-sensitive in the recipient string. In most cases, a
* failed match will fail on the classname or instance, and a successful
* match will succeed on the (d1->recip == d2->recip) check, so this
- * shouldn't affect performance. Note that this invalidates the overall
- * hash value check, which was of dubious value to start with.
+ * shouldn't affect performance.
*/
int ZDest_eq(d1, d2)
- ZDestination *d1, *d2;
+ Destination *d1, *d2;
{
- return((d1->classname == d2->classname) &&
- (d1->inst == d2->inst) &&
- (d1->recip == d2->recip ||
- strcasecmp(d1->recip->string, d2->recip->string) == 0));
+ return((d1->classname == d2->classname) &&
+ (d1->inst == d2->inst) &&
+ (d1->recip == d2->recip ||
+ strcasecmp(d1->recip->string, d2->recip->string) == 0));
}
-/* register the client as interested in a triplet */
+/* the client as interested in a triplet */
Code_t
-triplet_register(client, dest)
- ZClient_t *client;
- ZDestination *dest;
+triplet_register(client, dest, realm)
+ Client *client;
+ Destination *dest;
+ Realm *realm;
{
- register ZTriplet_t *ptr, *ptr2;
- unsigned long hashval;
-
- hashval = DEST_HASHVAL(*dest);
-
- if (!(ptr = class_bucket[hashval])) {
- /* not registered */
-
- ptr = triplet_alloc(dest->classname, dest->inst, dest->recip);
- if (!ptr)
- return(ENOMEM);
-
- /* allocate the head of the bucket */
-
- if (!(ptr2 = (ZTriplet_t *) xmalloc(sizeof(ZTriplet_t))))
- return(ENOMEM);
-
- ptr2->zct_clientlist = 0;
- ptr2->zct_acl = 0;
- ptr2->q_forw = ptr;
- ptr2->q_back = ptr;
- ptr->q_forw = ptr2;
- ptr->q_back = ptr2;
-
- class_bucket[hashval] = ptr2;
- return(insert_client(ptr, client));
-
- } else {
- for (ptr2 = ptr->q_forw; ptr2 != ptr; ptr2 = ptr2->q_forw) {
- /* walk down the list, looking for a match */
- if (ZDest_eq(&ptr2->zct_dest,dest))
- return(insert_client(ptr2, client));
- }
+ Triplet *triplet;
+ unsigned long hashval;
- /* fell off the end, no match */
- ptr2 = triplet_alloc(dest->classname, dest->inst, dest->recip);
- if (!ptr2)
- return(ENOMEM);
+ hashval = DEST_HASHVAL(*dest);
+ for (triplet = triplet_bucket[hashval]; triplet; triplet = triplet->next) {
+ if (ZDest_eq(&triplet->dest, dest))
+ return insert_client(triplet, client, realm);
+ }
- xinsque(ptr2, ptr); /* insert new class into hash bucket */
- return(insert_client(ptr2, client));
- }
+ /* Triplet not present in hash table, insert it. */
+ triplet = triplet_alloc(dest->classname, dest->inst, dest->recip);
+ LIST_INSERT(&triplet_bucket[hashval], triplet);
+ return insert_client(triplet, client, realm);
}
/* dissociate client from the class, garbage collecting if appropriate */
Code_t
-triplet_deregister(client, dest)
- ZClient_t *client;
- ZDestination *dest;
+triplet_deregister(client, dest, realm)
+ Client *client;
+ Destination *dest;
+ Realm *realm;
{
- register ZTriplet_t *ptr, *ptr2;
- int retval = -1;
- unsigned long hashval;
+ Triplet *triplet;
+ int retval;
+ unsigned long hashval;
- hashval = DEST_HASHVAL(*dest);
-#if 0
- zdbug((LOG_DEBUG, "class_dereg: %s %s", dest->classname->string,
- dest->inst->string));
-#endif
- ptr = class_bucket[hashval];
- if (!ptr)
- /* no such class to deregister */
- return(ZSRV_BADASSOC);
-
- for (ptr2 = ptr->q_forw; ptr2 != ptr; ptr2 = ptr2->q_forw) {
- /* walk down the list, looking for a match */
- if (ZDest_eq(&ptr2->zct_dest,dest)) {
- retval = remove_client(ptr2, client);
- if (retval == EMPTY_CLASS) {
#if 0
- zdbug((LOG_DEBUG,"empty class"));
+ zdbug((LOG_DEBUG, "class_dereg: %s %s", dest->classname->string,
+ dest->inst->string));
#endif
- /* Don't free up restricted classes. */
- if (ptr2->zct_acl)
- return(ZERR_NONE);
- else {
- xremque(ptr2);
- free_class(ptr2);
- return(ZERR_NONE);
- }
- }
- /* if not EMPTY_CLASS, it's either ZSRV_BADASSOC
- (not found) or ZERR_NONE (found and removed),
- so break */
- break;
- }
+ hashval = DEST_HASHVAL(*dest);
+ for (triplet = triplet_bucket[hashval]; triplet; triplet = triplet->next) {
+ if (ZDest_eq(&triplet->dest, dest)) {
+ retval = remove_client(triplet, client, realm);
+ if (retval != ZERR_NONE)
+ return retval;
+ if (*triplet->clients == NULL && !triplet->acl) {
+ LIST_DELETE(triplet);
+ free_triplet(triplet);
+ }
+ return ZERR_NONE;
}
-
- /* fell off: either client not found or client found
- and removed, retval contains the result */
- return(retval);
+ }
+ return(ZSRV_BADASSOC);
}
-
+
/* return a linked list of what clients are interested in this triplet */
-ZClientList_t *
+Client **
triplet_lookup(dest)
- ZDestination *dest;
+ Destination *dest;
{
- register ZTriplet_t *class, *p;
- unsigned long hashval;
-
- hashval = DEST_HASHVAL(*dest);
- p = class_bucket[hashval];
- if (p == NULLZT)
- return NULLZCLT;
-
- /* Go search the list for the class */
- for (class = p->q_forw; class != p; class = class->q_forw) {
- /* walk down the list, looking for a match */
- if (ZDest_eq(&class->zct_dest,dest))
- return class->zct_clientlist;
- }
- return NULLZCLT;
+ Triplet *triplet;
+ unsigned long hashval;
+
+ hashval = DEST_HASHVAL(*dest);
+ for (triplet = triplet_bucket[hashval]; triplet; triplet = triplet->next) {
+ if (ZDest_eq(&triplet->dest, dest))
+ return triplet->clients;
+ }
+ return NULL;
}
/*
- * return the acl structure associated with class, or NULLZACLT if there is
+ * return the acl structure associated with class, or NULL if there is
* no such acl struct
*/
-ZAcl_t *
+Acl *
class_get_acl(class_name)
- ZSTRING *class_name;
+ String *class_name;
{
- register ZTriplet_t *ptr, *ptr2;
- unsigned long hashval;
-
- hashval = HASHVAL(class_name, empty, empty);
- if (!(ptr = class_bucket[hashval]))
- return(NULLZACLT);
-
- /* walk down the list, looking for a match */
- for (ptr2 = ptr->q_back; ptr2 != ptr; ptr2 = ptr2->q_back)
- if ((ptr2->zct_dest.classname == class_name) &&
- (ptr2->zct_dest.inst == empty) &&
- (ptr2->zct_dest.recip == empty))
- return(ptr2->zct_acl);
-
- /* fell off the end, no match ==> not restricted */
- return(NULLZACLT);
+ Triplet *triplet;
+ unsigned long hashval;
+
+ hashval = HASHVAL(class_name, empty, empty);
+ for (triplet = triplet_bucket[hashval]; triplet; triplet = triplet->next) {
+ if (triplet->dest.classname == class_name &&
+ triplet->dest.inst == empty && triplet->dest.recip == empty)
+ return triplet->acl;
+ }
+
+ /* No acl found, not restricted. */
+ return NULL;
}
/*
@@ -275,35 +214,28 @@ class_get_acl(class_name)
Code_t
class_restrict(class_name, acl)
- char *class_name;
- ZAcl_t *acl;
+ char *class_name;
+ Acl *acl;
{
- register ZTriplet_t *ptr, *ptr2;
- ZSTRING *d;
- unsigned long hashval;
-
- d = make_zstring(class_name,1);
- hashval = HASHVAL(d, empty, empty);
-
- if (!(ptr = class_bucket[hashval])) {
- free_zstring(d);
- return(ZSRV_NOCLASS);
+ Triplet *triplet;
+ String *d;
+ unsigned long hashval;
+
+ d = make_string(class_name,1);
+ hashval = HASHVAL(d, empty, empty);
+ for (triplet = triplet_bucket[hashval]; triplet; triplet = triplet->next) {
+ if (triplet->dest.classname == d && triplet->dest.inst == empty &&
+ triplet->dest.recip == empty) {
+ if (triplet->acl)
+ return ZSRV_CLASSRESTRICTED;
+ triplet->acl = acl;
+ free_string(d);
+ return ZERR_NONE;
}
- for (ptr2 = ptr->q_forw; ptr2 != ptr; ptr2 = ptr2->q_forw)
- /* walk down the list, looking for a match */
- if ((ptr2->zct_dest.classname == d) &&
- (ptr2->zct_dest.inst == empty) &&
- (ptr2->zct_dest.recip == empty)) {
- if (ptr2->zct_acl)
- return ZSRV_CLASSRESTRICTED;
- ptr2->zct_acl = acl;
- free_zstring(d);
- return(ZERR_NONE);
- }
+ }
- /* fell off the end, no match */
- free_zstring(d);
- return(ZSRV_NOCLASS);
+ free_string(d);
+ return ZSRV_NOCLASS;
}
/*
@@ -311,132 +243,100 @@ class_restrict(class_name, acl)
* structure acl. return ZERR_NONE if no error, or ZSRV_CLASSXISTS
* if the class is already registered, or ENOMEM in case of malloc failure.
*/
-
+
Code_t
class_setup_restricted(class_name, acl)
- char *class_name;
- ZAcl_t *acl;
+ char *class_name;
+ Acl *acl;
{
- register ZTriplet_t *ptr, *ptr2;
- ZSTRING *d;
- unsigned long hashval;
-
- d = make_zstring(class_name,1);
- hashval = HASHVAL(d, empty, empty);
-
- if (!(ptr = class_bucket[hashval])) {
- /* not registered */
-
- ptr = triplet_alloc(d,empty,empty);
- if (!ptr)
- return(ENOMEM);
-
- ptr->zct_acl = acl;
-
- /* allocate the head of the bucket */
- ptr2 = (ZTriplet_t *) xmalloc(sizeof(ZTriplet_t));
- if (!ptr2)
- return(ENOMEM);
-
- ptr2->q_forw = ptr;
- ptr2->q_back = ptr;
- ptr->q_forw = ptr2;
- ptr->q_back = ptr2;
-
- class_bucket[hashval] = ptr2;
- free_zstring(d);
- return(ZERR_NONE);
- } else {
- for (ptr2 = ptr->q_forw; ptr2 != ptr; ptr2 = ptr2->q_forw)
- /* walk down the list, looking for a match */
- if ((ptr2->zct_dest.classname == d) &&
- (ptr2->zct_dest.inst == empty) &&
- (ptr2->zct_dest.recip == empty)) {
- free_zstring(d);
- return(ZSRV_CLASSXISTS);
- }
- if (!(ptr2 = triplet_alloc(d,empty,empty))) {
- free_zstring(d);
- return(ENOMEM);
- }
-
- free_zstring(d);
- ptr2->zct_acl = acl;
- xinsque(ptr2, ptr);
- return(ZERR_NONE);
+ Triplet *triplet;
+ String *d;
+ unsigned long hashval;
+
+ d = make_string(class_name,1);
+ hashval = HASHVAL(d, empty, empty);
+ for (triplet = triplet_bucket[hashval]; triplet; triplet = triplet->next) {
+ if (triplet->dest.classname == d && triplet->dest.inst == empty &&
+ triplet->dest.recip == d) {
+ free_string(d);
+ return ZSRV_CLASSXISTS;
}
+ }
+
+ /* Triplet not present in hash table, insert it. */
+ triplet = triplet_alloc(d, empty, empty);
+ free_string(d);
+ if (!triplet)
+ return ENOMEM;
+ triplet->acl = acl;
+ LIST_INSERT(&triplet_bucket[hashval], triplet);
+ return ZERR_NONE;
}
/* private routines */
/* allocate space for a class structure */
-static ZTriplet_t *
+static Triplet *
triplet_alloc(classname,inst,recipient)
- ZSTRING *classname;
- ZSTRING *inst;
- ZSTRING *recipient;
+ String *classname, *inst, *recipient;
{
- register ZTriplet_t *ptr;
- ZClientList_t *clist;
-
- if (!(ptr = (ZTriplet_t *) xmalloc(sizeof(ZTriplet_t))))
- return(NULLZT);
-
- ptr->q_forw = ptr->q_back = ptr;
- ptr->zct_dest.classname = dup_zstring(classname);
- ptr->zct_dest.inst = dup_zstring(inst);
- ptr->zct_dest.recip = dup_zstring(recipient);
-
- if (!(clist = (ZClientList_t *) xmalloc (sizeof (ZClientList_t)))) {
- xfree(ptr);
- return(NULLZT);
- }
- clist->q_forw = clist->q_back = clist;
- ptr->zct_clientlist = clist;
- ptr->zct_acl = NULLZACLT;
+ Triplet *triplet;
+ Client *clist;
- return (ptr);
-}
-
-/* allocate space for a client entry */
-
-static ZClientList_t *
-client_alloc(client)
- ZClient_t *client;
-{
- register ZClientList_t *ptr;
- if (!(ptr = (ZClientList_t *) xmalloc(sizeof(ZClientList_t))))
- return(NULLZCLT);
+ triplet = (Triplet *) malloc(sizeof(Triplet));
+ if (!triplet)
+ return NULL;
- ptr->q_forw = ptr->q_back = ptr;
- ptr->zclt_client = client;
+ triplet->dest.classname = dup_string(classname);
+ triplet->dest.inst = dup_string(inst);
+ triplet->dest.recip = dup_string(recipient);
+ triplet->clients = NULL;
+ triplet->acl = NULL;
- return(ptr);
+ return triplet;
}
/* insert a client into the list associated with the class *ptr */
static Code_t
-insert_client(ptr, client)
- ZTriplet_t *ptr;
- ZClient_t *client;
+insert_client(triplet, client, realm)
+ Triplet *triplet;
+ Client *client;
+ Realm *realm;
{
- register ZClientList_t *listp, *clist;
-
- for (clist = ptr->zct_clientlist->q_forw;
- clist != ptr->zct_clientlist;
- clist = clist->q_forw) {
- /* don't duplicate */
- if (clist->zclt_client == client)
- return(ZSRV_CLASSXISTS);
+ Client **clientp, **newclients;
+ int new_size;
+
+ if (triplet->clients) {
+ /* Avoid duplication. */
+ for (clientp = triplet->clients; *clientp; clientp++) {
+ if (*clientp == client || (realm && (*clientp)->realm == realm))
+ return ZSRV_CLASSXISTS;
}
- if (!(listp = client_alloc(client)))
- return(ENOMEM);
+ if (clientp + 1 - triplet->clients >= triplet->clients_size) {
+ new_size = triplet->clients_size * 2 + ALLOC_OFFSET;
+ newclients = (Client **) realloc(triplet->clients,
+ new_size * sizeof(Client *));
+ if (newclients == NULL)
+ return ENOMEM;
+ clientp = newclients + (clientp - triplet->clients);
+ triplet->clients = newclients;
+ triplet->clients_size = new_size;
+ }
+ } else {
+ /* Allocate an initial list of client pointers. */
+ triplet->clients = (Client **) malloc(ALLOC_INIT * sizeof(Client *));
+ if (triplet->clients == NULL)
+ return ENOMEM;
+ triplet->clients_size = ALLOC_INIT;
+ clientp = triplet->clients;
+ }
- xinsque(listp, ptr->zct_clientlist);
- return(ZERR_NONE);
+ *clientp = client;
+ clientp[1] = NULL;
+ return ZERR_NONE;
}
/*
@@ -444,70 +344,58 @@ insert_client(ptr, client)
* collecting if appropriate
*/
-static Code_t remove_client(ptr, client)
- ZTriplet_t *ptr;
- ZClient_t *client;
+static Code_t remove_client(triplet, client, realm)
+ Triplet *triplet;
+ Client *client;
+ Realm *realm;
{
- register ZClientList_t *listp = ptr->zct_clientlist;
- register ZClientList_t *listp2;
-
- if (!listp)
- return(ZSRV_BADASSOC);
- for (listp2 = listp->q_forw;
- listp2 != listp;
- listp2 = listp2->q_forw)
- /* walk down list, looking for him */
- if (listp2->zclt_client == client) {
- xremque(listp2);
- xfree(listp2);
- if (listp->q_forw == listp)
- return(EMPTY_CLASS);
- else
- return(ZERR_NONE);
- }
- return(ZSRV_BADASSOC);
+ Client **clientp;
+
+ for (clientp = triplet->clients; *clientp; clientp++) {
+ if (*clientp == client || (realm && (*clientp)->realm == realm)) {
+ for (; *clientp; clientp++)
+ *clientp = clientp[1];
+ return ZERR_NONE;
+ }
+ }
+
+ return ZSRV_BADASSOC;
}
-static void free_class(class)
- ZTriplet_t *class;
+static void free_triplet(triplet)
+ Triplet *triplet;
{
- free_zstring(class->zct_dest.classname);
- free_zstring(class->zct_dest.inst);
- free_zstring(class->zct_dest.recip);
- if (class->zct_acl != NULL)
- xfree(class->zct_acl);
- if (class->zct_clientlist != NULL)
- xfree(class->zct_clientlist);
- xfree(class);
+ if (triplet->clients)
+ free(triplet->clients);
+ free_string(triplet->dest.classname);
+ free_string(triplet->dest.inst);
+ free_string(triplet->dest.recip);
+ free(triplet);
}
-
-void class_dump_subs(fp)
- register FILE *fp;
+
+void triplet_dump_subs(fp)
+ FILE *fp;
{
int i;
- ZTriplet_t *trpq, *trp;
- ZClientList_t *cltq, *clt;
+ Triplet *triplet;
+ Client **clientp;
for (i = 0; i < HASHSIZE; i++) {
- trpq = class_bucket[i];
- if (!trpq)
- continue;
- for (trp = trpq->q_forw; trp != trpq; trp = trp->q_forw) {
+ for (triplet = triplet_bucket[i]; triplet; triplet = triplet->next) {
fputs("Triplet '", fp);
- subscr_quote(trp->zct_dest.classname->string, fp);
+ dump_quote(triplet->dest.classname->string, fp);
fputs("' '", fp);
- subscr_quote(trp->zct_dest.inst->string, fp);
+ dump_quote(triplet->dest.inst->string, fp);
fputs("' '", fp);
- subscr_quote(trp->zct_dest.recip->string, fp);
+ dump_quote(triplet->dest.recip->string, fp);
fputs("':\n", fp);
- cltq = trp->zct_clientlist;
- if (!cltq)
- continue;
- for (clt = cltq->q_forw; clt != cltq; clt = clt->q_forw) {
- fprintf(fp, "\t%s %d (%s)\n",
- inet_ntoa(clt->zclt_client->zct_sin.sin_addr),
- ntohs(clt->zclt_client->zct_sin.sin_port),
- clt->zclt_client->zct_principal->string);
+ if (triplet->clients) {
+ for (clientp = triplet->clients; *clientp; clientp++) {
+ fprintf(fp, "\t%s %d (%s)\n",
+ inet_ntoa((*clientp)->addr.sin_addr),
+ ntohs((*clientp)->addr.sin_port),
+ (*clientp)->principal->string);
+ }
}
}
}