]> asedeno.scripts.mit.edu Git - 1ts-debian.git/blob - zephyr/server/client.c
85918e7927b6965c382ee0691efd788523656e1e
[1ts-debian.git] / zephyr / server / client.c
1 /* This file is part of the Project Athena Zephyr Notification System.
2  * It contains functions for the Client Manager subsystem of the Zephyr server.
3  *
4  *      Created by:     John T. Kohl
5  *
6  *      $Id$
7  *
8  *      Copyright (c) 1987,1988,1991 by the Massachusetts Institute of Technology.
9  *      For copying and distribution information, see the file
10  *      "mit-copyright.h". 
11  */
12
13 #include <zephyr/mit-copyright.h>
14 #include "zserver.h"
15 #include <sys/socket.h>
16
17 #if !defined (lint) && !defined (SABER)
18 static const char rcsid_client_c[] =
19 "$Id$";
20 #endif
21
22 /*
23  * External functions:
24  *
25  * Code_t client_register(notice, who, client, server, wantdefaults)
26  *      ZNotice_t *notice;
27  *      struct sockaddr_in *who;
28  *      Client **client; (RETURN)
29  *      Server *server;
30  *      int wantdefaults;
31  *
32  * Code_t client_deregister(client, host, flush)
33  *      Client *client;
34  *      Host *host;
35  *      int flush;
36  *
37  * Client *client_find(who, unsigned int port)
38  *      struct in_addr *host;
39  *      unsigned int port;
40  *
41  * void client_dump_clients(fp, clist)
42  *      FILE *fp;
43  *      Client *clist;
44  */
45
46 /*
47  * a client: allocate space, find or insert the address in the
48  *      server's list of hosts, initialize and insert the client into
49  *      the host's list of clients.
50  *
51  * This routine assumes that the client has not been registered yet.
52  * The caller should check by calling client_find.
53  */
54
55 #define HASHSIZE 1024
56 static Client *client_bucket[HASHSIZE];
57
58 #define INET_HASH(host, port) ((htonl((host)->s_addr) + \
59                                 htons((unsigned short) (port))) % HASHSIZE)
60
61 Code_t
62 client_register(notice, host, client_p, wantdefaults)
63     ZNotice_t *notice;
64     struct in_addr *host;
65     Client **client_p;
66     int wantdefaults;
67 {
68     Client *client;
69     Code_t retval;
70
71     /* chain the client's host onto this server's host list */
72
73 #if 1
74     zdbug((LOG_DEBUG, "client_register: adding %s at %s/%d",
75            notice->z_sender, inet_ntoa(*host), ntohs(notice->z_port)));
76 #endif
77
78     if (!notice->z_port)
79         return ZSRV_BADSUBPORT;
80
81     *client_p = client = client_find(host, notice->z_port);
82     if (!client) {
83         *client_p = client = (Client *) malloc(sizeof(Client));
84         if (!client)
85             return ENOMEM;
86         memset(&client->addr, 0, sizeof(struct sockaddr_in));
87 #ifdef KERBEROS
88         memset(&client->session_key, 0, sizeof(client->session_key));
89 #endif
90         client->last_send = 0;
91         client->last_ack = NOW;
92         client->addr.sin_family = AF_INET;
93         client->addr.sin_addr.s_addr = host->s_addr;
94         client->addr.sin_port = notice->z_port;
95         client->subs = NULL;
96         client->realm = NULL;
97         client->principal = make_string(notice->z_sender, 0);
98         LIST_INSERT(&client_bucket[INET_HASH(&client->addr.sin_addr,
99                                              notice->z_port)], client);
100     }
101
102     /* Add default subscriptions only if this is not resulting from a brain
103      * dump, AND this request wants defaults. */
104     if (!bdumping && wantdefaults)
105         return subscr_def_subs(client);
106     else
107         return ZERR_NONE;
108 }
109
110 /*
111  * Deregister the client, freeing resources.  
112  * Remove any packets in the nack queue, release subscriptions, release
113  * locations, and dequeue him from the host.
114  */
115
116 void
117 client_deregister(client, flush)
118     Client *client;
119     int flush;
120 {
121     LIST_DELETE(client);
122     nack_release(client);
123     subscr_cancel_client(client);
124     free_string(client->principal);
125     if (flush)
126         uloc_flush_client(&client->addr);
127     free(client);
128 }
129
130 void
131 client_flush_host(host)
132     struct in_addr *host;
133 {
134     int i;
135     Client *client, *next;
136
137     for (i = 0; i < HASHSIZE; i++) {
138         for (client = client_bucket[i]; client; client = next) {
139             next = client->next;
140             if (client->addr.sin_addr.s_addr == host->s_addr)
141                 client_deregister(client, 1);
142         }
143     }
144     uloc_hflush(host);
145 }
146
147 Code_t
148 client_send_clients()
149 {
150     int i;
151     Client *client;
152     Code_t retval;
153
154     for (i = 0; i < HASHSIZE; i++) {
155         /* Allow packets to be processed between rows of the hash table. */
156         if (packets_waiting()) {
157             bdumping = 0;
158             bdump_concurrent = 1;
159             handle_packet();
160             bdump_concurrent = 0;
161             bdumping = 1;
162         }
163         for (client = client_bucket[i]; client; client = client->next) {
164             if (client->subs) {
165                 retval = subscr_send_subs(client);
166                 if (retval != ZERR_NONE)
167                     return retval;
168             }
169         }
170     }
171     return ZERR_NONE;
172 }
173
174 /*
175  * dump info about clients in this clist onto the fp.
176  * assumed to be called with SIGFPE blocked
177  * (true if called from signal handler)
178  */
179
180 void
181 client_dump_clients(fp)
182     FILE *fp;
183 {
184     Client *client;
185     int i;
186
187     for (i = 0; i < HASHSIZE; i++) {
188         for (client = client_bucket[i]; client; client = client->next) {
189             fprintf(fp, "%s/%d (%s):\n", inet_ntoa(client->addr.sin_addr),
190                     ntohs(client->addr.sin_port), client->principal->string);
191             subscr_dump_subs(fp, client->subs);
192         }
193     }
194 }
195
196 /*
197  * find a client by host and port
198  */
199
200 Client *
201 client_find(host, port)
202     struct in_addr *host;
203     unsigned int port;
204 {
205     Client *client;
206     long hashval;
207
208     hashval = INET_HASH(host, port);
209     for (client = client_bucket[hashval]; client; client = client->next) {
210         if (client->addr.sin_addr.s_addr == host->s_addr
211             && client->addr.sin_port == port)
212             return client;
213     }
214     return NULL;
215 }
216