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