]> andersk Git - moira.git/blame - gdb/gdb_serv.c
fix RCS Id strings
[moira.git] / gdb / gdb_serv.c
CommitLineData
5580185e 1/*
097e9b93 2 * $Source$
3 * $Header$
5580185e 4 */
5
6#ifndef lint
7static char *rcsid_gdb_serv_c = "$Header$";
d9f43d51 8#endif
5580185e 9
10
097e9b93 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 ************************************************************************/
5580185e 24
0a5ff702 25#include <mit-copyright.h>
5580185e 26#include <stdio.h>
f4c08abd 27#include <string.h>
5580185e 28#include "gdb.h"
29#include <sys/ioctl.h>
097e9b93 30#ifdef SOLARIS
31#include <sys/filio.h>
d9f43d51 32#endif
33#ifdef POSIX
34#include <unistd.h>
097e9b93 35#endif
5580185e 36
097e9b93 37 /*----------------------------------------------------------
38 *
39 * The following field names and types describe the
40 * tuple sent from clients to servers during negotiation.
41 *
42 *----------------------------------------------------------*/
5580185e 43
44char *g_tsv_field_names[] = {"server_id",
45 "parms",
46 "host",
47 "user"};
48FIELD_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
69char *g_fsv_field_names[] = {"disposition",
70 "server_id",
71 "parms"};
72FIELD_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
097e9b93 82
5580185e 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
97int
98gdb_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
097e9b93 108
5580185e 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
131CONNECTION
132start_server_connection(server_id, parms)
133char *server_id;
134char *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}
097e9b93 222
5580185e 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
234int
235g_try_server(conp, server_id, parms, responsep)
236CONNECTION *conp;
237char *server_id;
238char *parms;
239TUPLE *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
097e9b93 284
5580185e 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
297int
298g_ask_server(conp, server_id, parms, responsep)
299CONNECTION *conp;
300char *server_id;
301char *parms;
302TUPLE *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
2251cae5 323 if (parms == NULL) parms = "";
5580185e 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}
097e9b93 371
372
5580185e 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
382struct rtc_data {
383 TUPLE reply_data;
384 OPERATION tuple_send;
385};
386
387int g_irtc();
388int g_i2rtc();
389
390int
391start_replying_to_client(op, con, disposition, serverid, parms)
392OPERATION op;
393CONNECTION con;
394int disposition;
395char *serverid; /* null terminated */
396char *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
24582af9 454/*ARGSUSED*/
5580185e 455int
456g_irtc(op, hcon, arg)
457OPERATION op;
458HALF_CONNECTION hcon;
459struct 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.151698 seconds and 5 git commands to generate.