7 static char *rcsid_gdb_serv_c = "$Header$";
30 /************************************************************************/
34 /* GDB - Routines to implement the server/client model
37 /* Author: Noah Mendelsohn
38 /* Copyright: 1986 MIT Project Athena
39 /* For copying and distribution information, please see
40 /* the file <mit-copyright.h>.
42 /************************************************************************/
44 #include <mit-copyright.h>
48 #include <sys/ioctl.h>
50 /*----------------------------------------------------------*/
52 /* The following field names and types describe the
53 /* tuple sent from clients to servers during negotiation.
55 /*----------------------------------------------------------*/
57 char *g_tsv_field_names[] = {"server_id",
61 FIELD_TYPE g_tsv_ftypes[] = {STRING_T,
66 #define TSV_FLDCOUNT 4
68 #define TSV_SERVER_ID 0
74 /*----------------------------------------------------------*/
76 /* The following field names and types describe the
77 /* tuple returned from the server to the client during
80 /*----------------------------------------------------------*/
82 char *g_fsv_field_names[] = {"disposition",
85 FIELD_TYPE g_fsv_ftypes[] = {INTEGER_T,
89 #define FSV_FLDCOUNT 3
91 #define FSV_DISPOSITION 0
92 #define FSV_SERVER_ID 1
96 /************************************************************************/
100 /* Initialize the server client layer.
102 /* This routine is called during gdb_init to do the processing
103 /* common to all server/client handing.
105 /* In particular, we build the tuple descriptors for the
106 /* messages used in negotiating the server/client startup.
108 /************************************************************************/
113 gdb_tosrv = create_tuple_descriptor(TSV_FLDCOUNT, g_tsv_field_names,
115 gdb_fmsrv = create_tuple_descriptor(FSV_FLDCOUNT, g_fsv_field_names,
117 gdb_client_tuple = NULL;
118 gdb_socklen = sizeof(gdb_sockaddr_of_client);
122 /************************************************************************/
124 /* start_server_connection (start_server_connection)
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.
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.
142 /************************************************************************/
145 start_server_connection(server_id, parms)
149 CONNECTION con; /* the connection we're */
151 TUPLE response = NULL; /* each time we try a server */
152 /* it sends back its */
154 int retries = GDB_MAX_SERVER_RETRIES; /* number of servers we'll */
155 /* try before giving up in */
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 */
162 char latest_parms[GDB_MAX_SERVER_PARMS_SIZE];
163 /* likewise for parms */
168 * Try to allocate a connection and fill it in with null values.
174 * Loop asking different servers to accept our connection
175 * until one does or we are flatly refused.
179 * Allocate a buffer, if necessary, and reset buffer pointers
180 * so first request will result in a long read into the buffer
182 g_allocate_connection_buffers(con);
185 g_try_server(&con, server_id, parms, &response);
187 while ((retries--) &&
190 *(int *)FIELD_FROM_TUPLE(response,FSV_DISPOSITION)==GDB_FORWARDED) {
192 (void) sever_connection(con);
194 (void) strcpy(serv_id,
195 STRING_DATA(*(STRING *)
196 (FIELD_FROM_TUPLE(response,
198 (void) strcpy(latest_parms,
199 STRING_DATA(*(STRING *)
200 (FIELD_FROM_TUPLE(response,
202 null_tuple_strings(response);
203 delete_tuple(response);
204 g_try_server(&con, serv_id, latest_parms, &response);
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.
213 connection_status(con) != CON_UP) {
218 * We have at least some active connection, now see whether we
219 * are going to get to keep it
221 if (response != NULL &&
222 *(int *)FIELD_FROM_TUPLE(response,FSV_DISPOSITION) == GDB_ACCEPTED) {
223 null_tuple_strings(response);
224 delete_tuple(response);
227 if (response != NULL) {
228 null_tuple_strings(response);
229 delete_tuple(response);
231 (void) sever_connection(con);
236 /************************************************************************/
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.
245 /************************************************************************/
248 g_try_server(conp, server_id, parms, responsep)
255 register CONNECTION con = *conp;
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
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 */
274 g_ver_oprotocol(con);
275 if (con->status != CON_UP) {
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.
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");
289 if (con->in.fd +1 > gdb_mfd)
290 gdb_mfd = con->in.fd + 1;
292 g_ask_server(conp, server_id, parms, responsep);
298 /************************************************************************/
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.
308 /************************************************************************/
311 g_ask_server(conp, server_id, parms, responsep)
317 register CONNECTION con = *conp;
320 /*----------------------------------------------------------*/
322 /* Create a tuple to be sent out containing the
323 /* server_id and parms.
325 /*----------------------------------------------------------*/
327 out_tuple = create_tuple(gdb_tosrv); /* descriptor was pre- */
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))),
336 if (parms == NULL) parms = "";
337 (void) string_alloc((STRING *)FIELD_FROM_TUPLE(out_tuple, TSV_PARMS),
339 (void) strcpy(STRING_DATA(*((STRING *)FIELD_FROM_TUPLE(out_tuple,1))),
342 (void) string_alloc((STRING *)FIELD_FROM_TUPLE(out_tuple, TSV_HOST),
344 (void) strcpy(STRING_DATA(*((STRING *)FIELD_FROM_TUPLE(out_tuple,
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))),
352 /*----------------------------------------------------------*/
354 /* Send the tuple to the server, and make sure that
357 /*----------------------------------------------------------*/
359 rc = send_object(con, (char *)&out_tuple, TUPLE_T);
361 null_tuple_strings(out_tuple);
362 delete_tuple(out_tuple);
364 if (rc != OP_SUCCESS) {
365 return; /* cleanup from dying send */
366 /* should have made this */
367 /* CON_STOPPING with errno */
370 /*----------------------------------------------------------*/
372 /* OK, we sent it out, now lets read back the response.
374 /*----------------------------------------------------------*/
376 rc = receive_object(con, (char *)responsep, TUPLE_T);
378 if (rc != OP_SUCCESS) {
379 return; /* cleanup from dying send */
380 /* should have made this */
381 /* CON_STOPPING with errno */
385 /************************************************************************/
387 /* start_replying_to_client
389 /* Queue an operation which will send a reply to the specified
392 /************************************************************************/
396 OPERATION tuple_send;
403 start_replying_to_client(op, con, disposition, serverid, parms)
407 char *serverid; /* null terminated */
408 char *parms; /* " " */
410 register struct rtc_data *arg;
414 * Make sure the supplied connection is a legal one
416 GDB_CHECK_CON(con, "start_replying_to_client")
418 arg = (struct rtc_data *)db_alloc(sizeof(struct rtc_data));
421 * create an empty operation and a tuple
423 arg->tuple_send = create_operation();
424 arg->reply_data = create_tuple(gdb_fmsrv);
426 * Fill in the response tuple
428 t = arg->reply_data; /* quicker and easier here */
430 *(int *)FIELD_FROM_TUPLE(t,FSV_DISPOSITION) = disposition;
431 (void) string_alloc((STRING *)FIELD_FROM_TUPLE(t, FSV_SERVER_ID),
433 (void) strcpy(STRING_DATA(*(STRING *)(FIELD_FROM_TUPLE(t, FSV_SERVER_ID))),
436 (void) string_alloc((STRING *)FIELD_FROM_TUPLE(t, FSV_PARMS),
438 (void) strcpy(STRING_DATA(*(STRING *)(FIELD_FROM_TUPLE(t, FSV_PARMS))),
442 * Queue an operation ahead of us which will send the response tuple
445 start_sending_object(arg->tuple_send, con, (char *)&arg->reply_data,
449 * Now queue us behind it. By the time we run our init routine,
450 * a connection should have been acquired.
452 initialize_operation(op, g_irtc, (char *)arg, (int (*)())NULL);
453 (void) queue_operation(con, CON_INPUT, op);
456 /*----------------------------------------------------------*/
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.
464 /*----------------------------------------------------------*/
468 g_irtc(op, hcon, arg)
470 HALF_CONNECTION hcon;
471 struct rtc_data *arg;
476 * Figure out the return information to our caller
478 rc = OP_STATUS(arg->tuple_send);
481 * Release all transient data structures.
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));