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