]> asedeno.scripts.mit.edu Git - 1ts-debian.git/blobdiff - zephyr/server/client.c
upstream tag
[1ts-debian.git] / zephyr / server / client.c
diff --git a/zephyr/server/client.c b/zephyr/server/client.c
new file mode 100644 (file)
index 0000000..cae4413
--- /dev/null
@@ -0,0 +1,216 @@
+/* This file is part of the Project Athena Zephyr Notification System.
+ * It contains functions for the Client Manager subsystem of the Zephyr server.
+ *
+ *     Created by:     John T. Kohl
+ *
+ *     $Id: client.c,v 1.34 1999/01/22 23:19:41 ghudson Exp $
+ *
+ *     Copyright (c) 1987,1988,1991 by the Massachusetts Institute of Technology.
+ *     For copying and distribution information, see the file
+ *     "mit-copyright.h". 
+ */
+
+#include <zephyr/mit-copyright.h>
+#include "zserver.h"
+#include <sys/socket.h>
+
+#if !defined (lint) && !defined (SABER)
+static const char rcsid_client_c[] =
+"$Id: client.c,v 1.34 1999/01/22 23:19:41 ghudson Exp $";
+#endif
+
+/*
+ * External functions:
+ *
+ * Code_t client_register(notice, who, client, server, wantdefaults)
+ *     ZNotice_t *notice;
+ *     struct sockaddr_in *who;
+ *     Client **client; (RETURN)
+ *     Server *server;
+ *     int wantdefaults;
+ *
+ * Code_t client_deregister(client, host, flush)
+ *     Client *client;
+ *     Host *host;
+ *     int flush;
+ *
+ * Client *client_find(who, unsigned int port)
+ *     struct in_addr *host;
+ *     unsigned int port;
+ *
+ * void client_dump_clients(fp, clist)
+ *     FILE *fp;
+ *     Client *clist;
+ */
+
+/*
+ * a client: allocate space, find or insert the address in the
+ *     server's list of hosts, initialize and insert the client into
+ *     the host's list of clients.
+ *
+ * This routine assumes that the client has not been registered yet.
+ * The caller should check by calling client_find.
+ */
+
+#define HASHSIZE 1024
+static Client *client_bucket[HASHSIZE];
+
+#define INET_HASH(host, port) ((htonl((host)->s_addr) + \
+                               htons((unsigned short) (port))) % HASHSIZE)
+
+Code_t
+client_register(notice, host, client_p, wantdefaults)
+    ZNotice_t *notice;
+    struct in_addr *host;
+    Client **client_p;
+    int wantdefaults;
+{
+    Client *client;
+    Code_t retval;
+
+    /* chain the client's host onto this server's host list */
+
+#if 1
+    zdbug((LOG_DEBUG, "client_register: adding %s at %s/%d",
+          notice->z_sender, inet_ntoa(*host), ntohs(notice->z_port)));
+#endif
+
+    if (!notice->z_port)
+       return ZSRV_BADSUBPORT;
+
+    *client_p = client = client_find(host, notice->z_port);
+    if (!client) {
+       *client_p = client = (Client *) malloc(sizeof(Client));
+       if (!client)
+           return ENOMEM;
+       memset(&client->addr, 0, sizeof(struct sockaddr_in));
+#ifdef KERBEROS
+       memset(&client->session_key, 0, sizeof(client->session_key));
+#endif
+       client->last_send = 0;
+       client->last_ack = NOW;
+       client->addr.sin_family = AF_INET;
+       client->addr.sin_addr.s_addr = host->s_addr;
+       client->addr.sin_port = notice->z_port;
+       client->subs = NULL;
+       client->realm = NULL;
+       client->principal = make_string(notice->z_sender, 0);
+       LIST_INSERT(&client_bucket[INET_HASH(&client->addr.sin_addr,
+                                            notice->z_port)], client);
+    }
+
+    /* Add default subscriptions only if this is not resulting from a brain
+     * dump, AND this request wants defaults. */
+    if (!bdumping && wantdefaults)
+       return subscr_def_subs(client);
+    else
+       return ZERR_NONE;
+}
+
+/*
+ * Deregister the client, freeing resources.  
+ * Remove any packets in the nack queue, release subscriptions, release
+ * locations, and dequeue him from the host.
+ */
+
+void
+client_deregister(client, flush)
+    Client *client;
+    int flush;
+{
+    LIST_DELETE(client);
+    nack_release(client);
+    subscr_cancel_client(client);
+    free_string(client->principal);
+    if (flush)
+       uloc_flush_client(&client->addr);
+    free(client);
+}
+
+void
+client_flush_host(host)
+    struct in_addr *host;
+{
+    int i;
+    Client *client, *next;
+
+    for (i = 0; i < HASHSIZE; i++) {
+       for (client = client_bucket[i]; client; client = next) {
+           next = client->next;
+           if (client->addr.sin_addr.s_addr == host->s_addr)
+               client_deregister(client, 1);
+       }
+    }
+    uloc_hflush(host);
+}
+
+Code_t
+client_send_clients()
+{
+    int i;
+    Client *client;
+    Code_t retval;
+
+    for (i = 0; i < HASHSIZE; i++) {
+       /* Allow packets to be processed between rows of the hash table. */
+       if (packets_waiting()) {
+           bdumping = 0;
+           bdump_concurrent = 1;
+           handle_packet();
+           bdump_concurrent = 0;
+           bdumping = 1;
+       }
+       for (client = client_bucket[i]; client; client = client->next) {
+           if (client->subs) {
+               retval = subscr_send_subs(client);
+               if (retval != ZERR_NONE)
+                   return retval;
+           }
+       }
+    }
+    return ZERR_NONE;
+}
+
+/*
+ * dump info about clients in this clist onto the fp.
+ * assumed to be called with SIGFPE blocked
+ * (true if called from signal handler)
+ */
+
+void
+client_dump_clients(fp)
+    FILE *fp;
+{
+    Client *client;
+    int i;
+
+    for (i = 0; i < HASHSIZE; i++) {
+       for (client = client_bucket[i]; client; client = client->next) {
+           fprintf(fp, "%s/%d (%s):\n", inet_ntoa(client->addr.sin_addr),
+                   ntohs(client->addr.sin_port), client->principal->string);
+           subscr_dump_subs(fp, client->subs);
+       }
+    }
+}
+
+/*
+ * find a client by host and port
+ */
+
+Client *
+client_find(host, port)
+    struct in_addr *host;
+    unsigned int port;
+{
+    Client *client;
+    long hashval;
+
+    hashval = INET_HASH(host, port);
+    for (client = client_bucket[hashval]; client; client = client->next) {
+       if (client->addr.sin_addr.s_addr == host->s_addr
+           && client->addr.sin_port == port)
+           return client;
+    }
+    return NULL;
+}
+