]> asedeno.scripts.mit.edu Git - 1ts-debian.git/blob - zephyr/server/client.c
9098ac09c3319c95e7adbb96dd7dc63d7da37b31
[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 HAVE_KRB5
88         client->session_keyblock = NULL;
89 #else
90 #ifdef HAVE_KRB4
91         memset(&client->session_key, 0, sizeof(client->session_key));
92 #endif
93 #endif
94         client->last_send = 0;
95         client->last_ack = NOW;
96         client->addr.sin_family = AF_INET;
97         client->addr.sin_addr.s_addr = host->s_addr;
98         client->addr.sin_port = notice->z_port;
99         client->subs = NULL;
100         client->realm = NULL;
101         client->principal = make_string(notice->z_sender, 0);
102         LIST_INSERT(&client_bucket[INET_HASH(&client->addr.sin_addr,
103                                              notice->z_port)], client);
104     }
105
106     /* Add default subscriptions only if this is not resulting from a brain
107      * dump, AND this request wants defaults. */
108     if (!bdumping && wantdefaults)
109         return subscr_def_subs(client);
110     else
111         return ZERR_NONE;
112 }
113
114 /*
115  * Deregister the client, freeing resources.  
116  * Remove any packets in the nack queue, release subscriptions, release
117  * locations, and dequeue him from the host.
118  */
119
120 void
121 client_deregister(client, flush)
122     Client *client;
123     int flush;
124 {
125     LIST_DELETE(client);
126     nack_release(client);
127     subscr_cancel_client(client);
128     free_string(client->principal);
129 #ifdef HAVE_KRB5
130     if (client->session_keyblock)
131          krb5_free_keyblock(Z_krb5_ctx, client->session_keyblock);
132 #endif
133     if (flush)
134         uloc_flush_client(&client->addr);
135     free(client);
136 }
137
138 void
139 client_flush_host(host)
140     struct in_addr *host;
141 {
142     int i;
143     Client *client, *next;
144
145     for (i = 0; i < HASHSIZE; i++) {
146         for (client = client_bucket[i]; client; client = next) {
147             next = client->next;
148             if (client->addr.sin_addr.s_addr == host->s_addr)
149                 client_deregister(client, 1);
150         }
151     }
152     uloc_hflush(host);
153 }
154
155 Code_t
156 client_send_clients()
157 {
158     int i;
159     Client *client;
160     Code_t retval;
161
162     for (i = 0; i < HASHSIZE; i++) {
163         /* Allow packets to be processed between rows of the hash table. */
164         if (packets_waiting()) {
165             bdumping = 0;
166             bdump_concurrent = 1;
167             handle_packet();
168             bdump_concurrent = 0;
169             bdumping = 1;
170         }
171         for (client = client_bucket[i]; client; client = client->next) {
172             if (client->subs) {
173                 retval = subscr_send_subs(client);
174                 if (retval != ZERR_NONE)
175                     return retval;
176             }
177         }
178     }
179     return ZERR_NONE;
180 }
181
182 /*
183  * dump info about clients in this clist onto the fp.
184  * assumed to be called with SIGFPE blocked
185  * (true if called from signal handler)
186  */
187
188 void
189 client_dump_clients(fp)
190     FILE *fp;
191 {
192     Client *client;
193     int i;
194
195     for (i = 0; i < HASHSIZE; i++) {
196         for (client = client_bucket[i]; client; client = client->next) {
197             fprintf(fp, "%s/%d (%s):\n", inet_ntoa(client->addr.sin_addr),
198                     ntohs(client->addr.sin_port), client->principal->string);
199             subscr_dump_subs(fp, client->subs);
200         }
201     }
202 }
203
204 /*
205  * find a client by host and port
206  */
207
208 Client *
209 client_find(host, port)
210     struct in_addr *host;
211     unsigned int port;
212 {
213     Client *client;
214     long hashval;
215
216     hashval = INET_HASH(host, port);
217     for (client = client_bucket[hashval]; client; client = client->next) {
218         if (client->addr.sin_addr.s_addr == host->s_addr
219             && client->addr.sin_port == port)
220             return client;
221     }
222     return NULL;
223 }
224