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