]> andersk Git - moira.git/blob - gdb/gdb_serv.c
Remove `delete_user_by_uid' since it's never been used in any logs we have,
[moira.git] / gdb / gdb_serv.c
1 /*
2  * $Source$
3  * $Header$
4  */
5
6 #ifndef lint
7 static char *rcsid_gdb_serv_c = "$Header$";
8 #endif
9
10
11 /************************************************************************
12  *      
13  *                         gdb_serv.c
14  *      
15  *            GDB - Routines to implement the server/client model
16  *                  of connections.
17  *      
18  *      Author: Noah Mendelsohn
19  *      Copyright: 1986 MIT Project Athena 
20  *              For copying and distribution information, please see
21  *              the file <mit-copyright.h>.
22  *      
23  ************************************************************************/
24
25 #include <mit-copyright.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include "gdb.h"
29 #include <sys/ioctl.h>
30 #ifdef SOLARIS
31 #include <sys/filio.h>
32 #endif
33 #ifdef POSIX
34 #include <unistd.h>
35 #endif
36
37         /*----------------------------------------------------------
38          *      
39          *      The following field names and types describe the
40          *      tuple sent from clients to servers during negotiation.
41          *      
42          *----------------------------------------------------------*/
43
44 char *g_tsv_field_names[] = {"server_id",
45                             "parms",
46                             "host",
47                             "user"};
48 FIELD_TYPE g_tsv_ftypes[] = {STRING_T,
49                             STRING_T,
50                             STRING_T,
51                             STRING_T};
52
53 #define TSV_FLDCOUNT 4
54
55 #define TSV_SERVER_ID 0
56 #define TSV_PARMS     1
57 #define TSV_HOST      2
58 #define TSV_USER      3
59
60
61         /*----------------------------------------------------------*/
62         /*      
63         /*      The following field names and types describe the
64         /*      tuple returned from the server to the client during
65         /*      negotiation.
66         /*      
67         /*----------------------------------------------------------*/
68
69 char *g_fsv_field_names[] = {"disposition",
70                              "server_id",
71                              "parms"};
72 FIELD_TYPE g_fsv_ftypes[] = {INTEGER_T,
73                              STRING_T,
74                              STRING_T};
75
76 #define FSV_FLDCOUNT 3
77
78 #define FSV_DISPOSITION 0
79 #define FSV_SERVER_ID   1
80 #define FSV_PARMS       2
81
82
83 /************************************************************************/
84 /*      
85 /*                        gdb_i_srv
86 /*      
87 /*      Initialize the server client layer.
88 /*      
89 /*      This routine is called during gdb_init to do the processing
90 /*      common to all server/client handing.
91 /*      
92 /*      In particular, we build the tuple descriptors for the 
93 /*      messages used in negotiating the server/client startup.
94 /*      
95 /************************************************************************/
96
97 int
98 gdb_i_srv()
99 {
100         gdb_tosrv = create_tuple_descriptor(TSV_FLDCOUNT, g_tsv_field_names, 
101                                             g_tsv_ftypes);
102         gdb_fmsrv = create_tuple_descriptor(FSV_FLDCOUNT, g_fsv_field_names, 
103                                             g_fsv_ftypes);
104         gdb_client_tuple = NULL;
105         gdb_socklen = sizeof(gdb_sockaddr_of_client);
106 }
107
108
109 /************************************************************************/
110 /*      
111 /*                 start_server_connection (start_server_connection)
112 /*      
113 /*      This routine is called from a client that wishes to make a
114 /*      connection to a server.  In the current implementation, the
115 /*      string argument supplied is just the internet name of the 
116 /*      host on which the server runs.  This will later be generalized
117 /*      to a more flexible naming scheme.
118 /*      
119 /*      This routine builds a connection to the requested server, 
120 /*      sends the server i.d. and parms to the server (as strings), 
121 /*      and waits for a response indicating whether the server has
122 /*      agreed to the connection.  The server responds in one of three
123 /*      ways (1) connection accepted (2) connection declined (3) redirect.
124 /*      In this last case, the server returns a forwarding address to
125 /*      be substituted for the server_id, and the whole process is tried
126 /*      again repeatedly until a connection is established or a
127 /*      retry limit is exceeded.
128 /*      
129 /************************************************************************/
130
131 CONNECTION
132 start_server_connection(server_id, parms)
133 char *server_id;
134 char *parms;
135 {
136         CONNECTION con;                         /* the connection we're */
137                                                 /* creating */
138         TUPLE response = NULL;                  /* each time we try a server */
139                                                 /* it sends back its */
140                                                 /* response here */
141         int retries = GDB_MAX_SERVER_RETRIES;   /* number of servers we'll */
142                                                 /* try before giving up in */
143                                                 /* fear of a loop */
144
145         char serv_id[GDB_MAX_SERVER_ID_SIZE];   /* a place to store server */
146                                                 /* id's.  New ones go here */
147                                                 /* when our request is */
148                                                 /* forwarded */
149         char latest_parms[GDB_MAX_SERVER_PARMS_SIZE];
150                                                 /* likewise for parms */
151
152         GDB_INIT_CHECK
153
154        /*
155         * Try to allocate a connection and fill it in with null values.
156         */
157
158         con = g_make_con();
159
160        /*
161         * Loop asking different servers to accept our connection
162         * until one does or we are flatly refused.
163         */
164
165         /*
166          * Allocate a buffer, if necessary, and reset buffer pointers
167          * so first request will result in a long read into the buffer
168          */
169         g_allocate_connection_buffers(con);
170
171
172         g_try_server(&con, server_id, parms, &response);
173
174         while ((retries--) &&
175                con != NULL && 
176                response != NULL &&
177                *(int *)FIELD_FROM_TUPLE(response,FSV_DISPOSITION)==GDB_FORWARDED) {
178
179                 (void) sever_connection(con);
180                 con = g_make_con();
181                 (void) strcpy(serv_id, 
182                        STRING_DATA(*(STRING *) 
183                                    (FIELD_FROM_TUPLE(response, 
184                                                      FSV_SERVER_ID))));
185                 (void) strcpy(latest_parms, 
186                        STRING_DATA(*(STRING *) 
187                                    (FIELD_FROM_TUPLE(response, 
188                                                      FSV_PARMS))));
189                 null_tuple_strings(response);
190                 delete_tuple(response);
191                 g_try_server(&con, serv_id, latest_parms, &response);
192         }
193
194         /*
195          * At this point, we are done trying servers, now find out
196          * whether we get to keep the connnection or whether it
197          * didn't work.  First, see whether the connection is even up.
198          */
199         if (con == NULL ||
200             connection_status(con) != CON_UP) {
201                 return con;
202         }
203
204        /*
205         * We have at least some active connection, now see whether we 
206         * are going to get to keep it
207         */
208         if (response != NULL &&
209             *(int *)FIELD_FROM_TUPLE(response,FSV_DISPOSITION) == GDB_ACCEPTED) {
210                 null_tuple_strings(response);
211                 delete_tuple(response);
212                 return con;
213         } else {
214                 if (response != NULL) {
215                         null_tuple_strings(response);
216                         delete_tuple(response);
217                 }
218                 (void) sever_connection(con);
219                 return NULL;
220         }
221 }
222
223 /************************************************************************/
224 /*      
225 /*                           g_try_server
226 /*      
227 /*      Builds a single connection to a server and returns status
228 /*      to indicate whether the connection has been accepted, declined,
229 /*      or is to be retried.  This status is conveyed in a tuple received
230 /*      back from the server.
231 /*      
232 /************************************************************************/
233
234 int
235 g_try_server(conp, server_id, parms, responsep)
236 CONNECTION *conp;
237 char *server_id;
238 char *parms;
239 TUPLE *responsep;
240 {
241
242         register CONNECTION con = *conp;
243         int flag = 1;
244         
245        /* 
246         * In this implementation, we use a single fd for both inbound and
247         * outbound traffic.  Try to connect to other side.  Current
248         * implementation of this is synchronous--may be a problem?  If the
249         * connections come up, then verify the level of protocol being
250         * observed on the connections.  If incompatible, then turn off the
251         * connection.
252         */
253
254         if(!g_try_connecting(con,server_id) || 
255            con->status != CON_STARTING) {
256                 return;                         /* If there we an error, */
257                                                 /* connection will have been */
258                                                 /* left CON_STOPPING with */
259                                                 /* possible errno set */
260         }
261         g_ver_oprotocol(con);
262         if (con->status != CON_UP) {
263                 return;
264         }
265
266        /*
267         * We've successfully started the connection, now mark
268         * it for non-blocking I/O.  Also, update the high water
269         * mark of fd's controlled by our system.
270         */
271         if(ioctl(con->in.fd, FIONBIO, (char *)&flag)== (-1)) {
272                         g_stop_with_errno(con);
273                         gdb_perror("gdb: ioctl for non-block failed");
274                         return;
275         }
276         if (con->in.fd +1 > gdb_mfd) 
277                         gdb_mfd = con->in.fd + 1;
278
279         g_ask_server(conp, server_id, parms, responsep);        
280
281         return;
282 }
283
284
285 /************************************************************************/
286 /*      
287 /*                      g_ask_server
288 /*      
289 /*      Called once we are in touch with the server and our physical
290 /*      transmission protocol is comprehensible.  This routine
291 /*      sends out a tuple containing the server i.d. and parameter
292 /*      strings and it returns a tuple received back from the server
293 /*      containing the server's response.
294 /*      
295 /************************************************************************/
296
297 int
298 g_ask_server(conp, server_id, parms, responsep)
299 CONNECTION *conp;
300 char *server_id;
301 char *parms;
302 TUPLE *responsep;
303 {
304         register CONNECTION con = *conp;
305         TUPLE out_tuple;
306         int rc;
307         /*----------------------------------------------------------*/
308         /*      
309         /*      Create a tuple to be sent out containing the
310         /*      server_id and parms.
311         /*      
312         /*----------------------------------------------------------*/
313
314         out_tuple = create_tuple(gdb_tosrv);    /* descriptor was pre- */
315                                                 /* built during */
316                                                 /* initialization*/
317
318         (void) string_alloc((STRING *)FIELD_FROM_TUPLE(out_tuple, TSV_SERVER_ID),
319                      strlen(server_id)+1);
320         (void) strcpy(STRING_DATA(*((STRING *)FIELD_FROM_TUPLE(out_tuple,0))),
321                        server_id);
322
323         if (parms == NULL) parms = "";
324         (void) string_alloc((STRING *)FIELD_FROM_TUPLE(out_tuple, TSV_PARMS),
325                      strlen(parms)+1);
326         (void) strcpy(STRING_DATA(*((STRING *)FIELD_FROM_TUPLE(out_tuple,1))),
327                        parms);
328
329         (void) string_alloc((STRING *)FIELD_FROM_TUPLE(out_tuple, TSV_HOST),
330                      strlen(gdb_host)+1);
331         (void) strcpy(STRING_DATA(*((STRING *)FIELD_FROM_TUPLE(out_tuple,
332                                                                TSV_HOST))),
333                        gdb_host);
334         (void) string_alloc((STRING *)FIELD_FROM_TUPLE(out_tuple, TSV_USER),
335                      strlen(gdb_uname)+1);
336         (void) strcpy(STRING_DATA(*((STRING *)FIELD_FROM_TUPLE(out_tuple,TSV_USER))),
337                        gdb_uname);
338
339         /*----------------------------------------------------------*/
340         /*      
341         /*      Send the tuple to the server, and make sure that
342         /*      we succeeded.
343         /*      
344         /*----------------------------------------------------------*/
345
346         rc = send_object(con, (char *)&out_tuple, TUPLE_T);
347
348         null_tuple_strings(out_tuple);
349         delete_tuple(out_tuple);
350
351         if (rc != OP_SUCCESS) {
352                 return;                         /* cleanup from dying send */
353                                                 /* should have made this */
354                                                 /* CON_STOPPING with errno */
355         }
356
357         /*----------------------------------------------------------*/
358         /*      
359         /*      OK, we sent it out, now lets read back the response.
360         /*      
361         /*----------------------------------------------------------*/
362
363         rc = receive_object(con, (char *)responsep, TUPLE_T);
364
365         if (rc != OP_SUCCESS) {
366                 return;                         /* cleanup from dying send */
367                                                 /* should have made this */
368                                                 /* CON_STOPPING with errno */
369         }
370 }
371
372
373 /************************************************************************/
374 /*      
375 /*                      start_replying_to_client
376 /*      
377 /*      Queue an operation which will send a reply to the specified
378 /*      client.
379 /*      
380 /************************************************************************/
381
382 struct rtc_data {
383         TUPLE reply_data;
384         OPERATION tuple_send;
385 };
386
387 int g_irtc();
388 int g_i2rtc();
389
390 int
391 start_replying_to_client(op, con, disposition, serverid, parms)
392 OPERATION op;
393 CONNECTION con;
394 int disposition;
395 char *serverid;                                 /* null terminated */
396 char *parms;                                    /*   "     "       */
397 {
398         register struct rtc_data *arg;
399         register TUPLE t;
400
401        /*
402         * Make sure the supplied connection is a legal one
403         */
404         GDB_CHECK_CON(con, "start_replying_to_client")
405
406         arg = (struct rtc_data *)db_alloc(sizeof(struct rtc_data));
407
408        /*
409         * create an empty operation and a tuple
410         */
411         arg->tuple_send = create_operation();
412         arg->reply_data = create_tuple(gdb_fmsrv);
413        /*
414         * Fill in the response tuple
415         */
416         t = arg->reply_data;                    /* quicker and easier here */
417
418         *(int *)FIELD_FROM_TUPLE(t,FSV_DISPOSITION) = disposition;
419         (void) string_alloc((STRING *)FIELD_FROM_TUPLE(t, FSV_SERVER_ID),
420                      strlen(serverid)+1);
421         (void) strcpy(STRING_DATA(*(STRING *)(FIELD_FROM_TUPLE(t, FSV_SERVER_ID))),
422                                        serverid);
423
424         (void) string_alloc((STRING *)FIELD_FROM_TUPLE(t, FSV_PARMS),
425                      strlen(parms)+1);
426         (void) strcpy(STRING_DATA(*(STRING *)(FIELD_FROM_TUPLE(t, FSV_PARMS))),
427                                        parms);
428
429        /*
430         * Queue an operation ahead of us which will send the response tuple
431         * to the client
432         */
433         start_sending_object(arg->tuple_send, con, (char *)&arg->reply_data,
434                              TUPLE_T);
435         
436        /*
437         * Now queue us behind it.  By the time we run our init routine,
438         * a connection should have been acquired.
439         */
440         initialize_operation(op, g_irtc, (char *)arg, (int (*)())NULL);
441         (void) queue_operation(con, CON_INPUT, op);
442 }
443
444         /*----------------------------------------------------------*/
445         /*      
446         /*                      g_irtc
447         /*      
448         /*      Init routine for replying to a client.  If all went
449         /*      well, (or even if it didn't), then we are done.
450         /*      All we have to do is clean up the stuff we've allocated.
451         /*      
452         /*----------------------------------------------------------*/
453
454 /*ARGSUSED*/
455 int
456 g_irtc(op, hcon, arg)
457 OPERATION op;
458 HALF_CONNECTION hcon;
459 struct rtc_data *arg;
460 {
461         int rc;
462
463        /*
464         * Figure out the return information to our caller
465         */
466         rc = OP_STATUS(arg->tuple_send);
467
468        /*
469         * Release all transient data structures.
470         */
471         null_tuple_strings(arg->reply_data);
472         delete_tuple(arg->reply_data);
473         delete_operation(arg->tuple_send);
474         db_free((char *)arg, sizeof(struct rtc_data));
475         return rc;
476 }
This page took 0.079666 seconds and 5 git commands to generate.