]> andersk Git - moira.git/blame - gdb/gdb_serv.c
strings.h no longer exists on the sun, and string.h is POSIX anyway
[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$";
8#endif lint
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>
32#endif
5580185e 33
097e9b93 34 /*----------------------------------------------------------
35 *
36 * The following field names and types describe the
37 * tuple sent from clients to servers during negotiation.
38 *
39 *----------------------------------------------------------*/
5580185e 40
41char *g_tsv_field_names[] = {"server_id",
42 "parms",
43 "host",
44 "user"};
45FIELD_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
66char *g_fsv_field_names[] = {"disposition",
67 "server_id",
68 "parms"};
69FIELD_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
097e9b93 79
5580185e 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
94int
95gdb_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
097e9b93 105
5580185e 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
128CONNECTION
129start_server_connection(server_id, parms)
130char *server_id;
131char *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}
097e9b93 219
5580185e 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
231int
232g_try_server(conp, server_id, parms, responsep)
233CONNECTION *conp;
234char *server_id;
235char *parms;
236TUPLE *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
097e9b93 281
5580185e 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
294int
295g_ask_server(conp, server_id, parms, responsep)
296CONNECTION *conp;
297char *server_id;
298char *parms;
299TUPLE *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
2251cae5 320 if (parms == NULL) parms = "";
5580185e 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}
097e9b93 368
369
5580185e 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
379struct rtc_data {
380 TUPLE reply_data;
381 OPERATION tuple_send;
382};
383
384int g_irtc();
385int g_i2rtc();
386
387int
388start_replying_to_client(op, con, disposition, serverid, parms)
389OPERATION op;
390CONNECTION con;
391int disposition;
392char *serverid; /* null terminated */
393char *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
24582af9 451/*ARGSUSED*/
5580185e 452int
453g_irtc(op, hcon, arg)
454OPERATION op;
455HALF_CONNECTION hcon;
456struct 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.159 seconds and 5 git commands to generate.