]> andersk Git - moira.git/blame - gdb/gdb_serv.c
lint
[moira.git] / gdb / gdb_serv.c
CommitLineData
5580185e 1/*
2 * $Source$
3 * $Header$
4 */
5
6#ifndef lint
7static 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
0a5ff702 39/* For copying and distribution information, please see
40/* the file <mit-copyright.h>.
5580185e 41/*
42/************************************************************************/
43
0a5ff702 44#include <mit-copyright.h>
5580185e 45#include <stdio.h>
46#include <strings.h>
47#include "gdb.h"
48#include <sys/ioctl.h>
49
50 /*----------------------------------------------------------*/
51 /*
52 /* The following field names and types describe the
53 /* tuple sent from clients to servers during negotiation.
54 /*
55 /*----------------------------------------------------------*/
56
57char *g_tsv_field_names[] = {"server_id",
58 "parms",
59 "host",
60 "user"};
61FIELD_TYPE g_tsv_ftypes[] = {STRING_T,
62 STRING_T,
63 STRING_T,
64 STRING_T};
65
66#define TSV_FLDCOUNT 4
67
68#define TSV_SERVER_ID 0
69#define TSV_PARMS 1
70#define TSV_HOST 2
71#define TSV_USER 3
72
73
74 /*----------------------------------------------------------*/
75 /*
76 /* The following field names and types describe the
77 /* tuple returned from the server to the client during
78 /* negotiation.
79 /*
80 /*----------------------------------------------------------*/
81
82char *g_fsv_field_names[] = {"disposition",
83 "server_id",
84 "parms"};
85FIELD_TYPE g_fsv_ftypes[] = {INTEGER_T,
86 STRING_T,
87 STRING_T};
88
89#define FSV_FLDCOUNT 3
90
91#define FSV_DISPOSITION 0
92#define FSV_SERVER_ID 1
93#define FSV_PARMS 2
94
95\f
96/************************************************************************/
97/*
98/* gdb_i_srv
99/*
100/* Initialize the server client layer.
101/*
102/* This routine is called during gdb_init to do the processing
103/* common to all server/client handing.
104/*
105/* In particular, we build the tuple descriptors for the
106/* messages used in negotiating the server/client startup.
107/*
108/************************************************************************/
109
110int
111gdb_i_srv()
112{
113 gdb_tosrv = create_tuple_descriptor(TSV_FLDCOUNT, g_tsv_field_names,
114 g_tsv_ftypes);
115 gdb_fmsrv = create_tuple_descriptor(FSV_FLDCOUNT, g_fsv_field_names,
116 g_fsv_ftypes);
117 gdb_client_tuple = NULL;
118 gdb_socklen = sizeof(gdb_sockaddr_of_client);
119}
120
121\f
122/************************************************************************/
123/*
124/* start_server_connection (start_server_connection)
125/*
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.
131/*
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.
141/*
142/************************************************************************/
143
144CONNECTION
145start_server_connection(server_id, parms)
146char *server_id;
147char *parms;
148{
149 CONNECTION con; /* the connection we're */
150 /* creating */
151 TUPLE response = NULL; /* each time we try a server */
152 /* it sends back its */
153 /* response here */
154 int retries = GDB_MAX_SERVER_RETRIES; /* number of servers we'll */
155 /* try before giving up in */
156 /* fear of a loop */
157
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 */
161 /* forwarded */
162 char latest_parms[GDB_MAX_SERVER_PARMS_SIZE];
163 /* likewise for parms */
164
165 GDB_INIT_CHECK
166
167 /*
168 * Try to allocate a connection and fill it in with null values.
169 */
170
171 con = g_make_con();
172
173 /*
174 * Loop asking different servers to accept our connection
175 * until one does or we are flatly refused.
176 */
177
178 /*
179 * Allocate a buffer, if necessary, and reset buffer pointers
180 * so first request will result in a long read into the buffer
181 */
182 g_allocate_connection_buffers(con);
183
184
185 g_try_server(&con, server_id, parms, &response);
186
187 while ((retries--) &&
188 con != NULL &&
189 response != NULL &&
190 *(int *)FIELD_FROM_TUPLE(response,FSV_DISPOSITION)==GDB_FORWARDED) {
191
192 (void) sever_connection(con);
193 con = g_make_con();
194 (void) strcpy(serv_id,
195 STRING_DATA(*(STRING *)
196 (FIELD_FROM_TUPLE(response,
197 FSV_SERVER_ID))));
198 (void) strcpy(latest_parms,
199 STRING_DATA(*(STRING *)
200 (FIELD_FROM_TUPLE(response,
201 FSV_PARMS))));
202 null_tuple_strings(response);
203 delete_tuple(response);
204 g_try_server(&con, serv_id, latest_parms, &response);
205 }
206
207 /*
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.
211 */
212 if (con == NULL ||
213 connection_status(con) != CON_UP) {
214 return con;
215 }
216
217 /*
218 * We have at least some active connection, now see whether we
219 * are going to get to keep it
220 */
221 if (response != NULL &&
222 *(int *)FIELD_FROM_TUPLE(response,FSV_DISPOSITION) == GDB_ACCEPTED) {
223 null_tuple_strings(response);
224 delete_tuple(response);
225 return con;
226 } else {
227 if (response != NULL) {
228 null_tuple_strings(response);
229 delete_tuple(response);
230 }
231 (void) sever_connection(con);
232 return NULL;
233 }
234}
235\f
236/************************************************************************/
237/*
238/* g_try_server
239/*
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.
244/*
245/************************************************************************/
246
247int
248g_try_server(conp, server_id, parms, responsep)
249CONNECTION *conp;
250char *server_id;
251char *parms;
252TUPLE *responsep;
253{
254
255 register CONNECTION con = *conp;
256 int flag = 1;
257
258 /*
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
264 * connection.
265 */
266
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 */
273 }
274 g_ver_oprotocol(con);
275 if (con->status != CON_UP) {
276 return;
277 }
278
279 /*
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.
283 */
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");
287 return;
288 }
289 if (con->in.fd +1 > gdb_mfd)
290 gdb_mfd = con->in.fd + 1;
291
292 g_ask_server(conp, server_id, parms, responsep);
293
294 return;
295}
296
297\f
298/************************************************************************/
299/*
300/* g_ask_server
301/*
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.
307/*
308/************************************************************************/
309
310int
311g_ask_server(conp, server_id, parms, responsep)
312CONNECTION *conp;
313char *server_id;
314char *parms;
315TUPLE *responsep;
316{
317 register CONNECTION con = *conp;
318 TUPLE out_tuple;
319 int rc;
320 /*----------------------------------------------------------*/
321 /*
322 /* Create a tuple to be sent out containing the
323 /* server_id and parms.
324 /*
325 /*----------------------------------------------------------*/
326
327 out_tuple = create_tuple(gdb_tosrv); /* descriptor was pre- */
328 /* built during */
329 /* initialization*/
330
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))),
334 server_id);
335
336 (void) string_alloc((STRING *)FIELD_FROM_TUPLE(out_tuple, TSV_PARMS),
337 strlen(parms)+1);
338 (void) strcpy(STRING_DATA(*((STRING *)FIELD_FROM_TUPLE(out_tuple,1))),
339 parms);
340
341 (void) string_alloc((STRING *)FIELD_FROM_TUPLE(out_tuple, TSV_HOST),
342 strlen(gdb_host)+1);
343 (void) strcpy(STRING_DATA(*((STRING *)FIELD_FROM_TUPLE(out_tuple,
344 TSV_HOST))),
345 gdb_host);
346 (void) string_alloc((STRING *)FIELD_FROM_TUPLE(out_tuple, TSV_USER),
347 strlen(gdb_uname)+1);
348 (void) strcpy(STRING_DATA(*((STRING *)FIELD_FROM_TUPLE(out_tuple,TSV_USER))),
349 gdb_uname);
350
351 /*----------------------------------------------------------*/
352 /*
353 /* Send the tuple to the server, and make sure that
354 /* we succeeded.
355 /*
356 /*----------------------------------------------------------*/
357
358 rc = send_object(con, (char *)&out_tuple, TUPLE_T);
359
360 null_tuple_strings(out_tuple);
361 delete_tuple(out_tuple);
362
363 if (rc != OP_SUCCESS) {
364 return; /* cleanup from dying send */
365 /* should have made this */
366 /* CON_STOPPING with errno */
367 }
368
369 /*----------------------------------------------------------*/
370 /*
371 /* OK, we sent it out, now lets read back the response.
372 /*
373 /*----------------------------------------------------------*/
374
375 rc = receive_object(con, (char *)responsep, TUPLE_T);
376
377 if (rc != OP_SUCCESS) {
378 return; /* cleanup from dying send */
379 /* should have made this */
380 /* CON_STOPPING with errno */
381 }
382}
383\f
384/************************************************************************/
385/*
386/* start_replying_to_client
387/*
388/* Queue an operation which will send a reply to the specified
389/* client.
390/*
391/************************************************************************/
392
393struct rtc_data {
394 TUPLE reply_data;
395 OPERATION tuple_send;
396};
397
398int g_irtc();
399int g_i2rtc();
400
401int
402start_replying_to_client(op, con, disposition, serverid, parms)
403OPERATION op;
404CONNECTION con;
405int disposition;
406char *serverid; /* null terminated */
407char *parms; /* " " */
408{
409 register struct rtc_data *arg;
410 register TUPLE t;
411
412 /*
413 * Make sure the supplied connection is a legal one
414 */
415 GDB_CHECK_CON(con, "start_replying_to_client")
416
417 arg = (struct rtc_data *)db_alloc(sizeof(struct rtc_data));
418
419 /*
420 * create an empty operation and a tuple
421 */
422 arg->tuple_send = create_operation();
423 arg->reply_data = create_tuple(gdb_fmsrv);
424 /*
425 * Fill in the response tuple
426 */
427 t = arg->reply_data; /* quicker and easier here */
428
429 *(int *)FIELD_FROM_TUPLE(t,FSV_DISPOSITION) = disposition;
430 (void) string_alloc((STRING *)FIELD_FROM_TUPLE(t, FSV_SERVER_ID),
431 strlen(serverid)+1);
432 (void) strcpy(STRING_DATA(*(STRING *)(FIELD_FROM_TUPLE(t, FSV_SERVER_ID))),
433 serverid);
434
435 (void) string_alloc((STRING *)FIELD_FROM_TUPLE(t, FSV_PARMS),
436 strlen(parms)+1);
437 (void) strcpy(STRING_DATA(*(STRING *)(FIELD_FROM_TUPLE(t, FSV_PARMS))),
438 parms);
439
440 /*
441 * Queue an operation ahead of us which will send the response tuple
442 * to the client
443 */
444 start_sending_object(arg->tuple_send, con, (char *)&arg->reply_data,
445 TUPLE_T);
446
447 /*
448 * Now queue us behind it. By the time we run our init routine,
449 * a connection should have been acquired.
450 */
451 initialize_operation(op, g_irtc, (char *)arg, (int (*)())NULL);
452 (void) queue_operation(con, CON_INPUT, op);
453}
454
455 /*----------------------------------------------------------*/
456 /*
457 /* g_irtc
458 /*
459 /* Init routine for replying to a client. If all went
460 /* well, (or even if it didn't), then we are done.
461 /* All we have to do is clean up the stuff we've allocated.
462 /*
463 /*----------------------------------------------------------*/
464
24582af9 465/*ARGSUSED*/
5580185e 466int
467g_irtc(op, hcon, arg)
468OPERATION op;
469HALF_CONNECTION hcon;
470struct rtc_data *arg;
471{
472 int rc;
473
474 /*
475 * Figure out the return information to our caller
476 */
477 rc = OP_STATUS(arg->tuple_send);
478
479 /*
480 * Release all transient data structures.
481 */
482 null_tuple_strings(arg->reply_data);
483 delete_tuple(arg->reply_data);
484 delete_operation(arg->tuple_send);
485 db_free((char *)arg, sizeof(struct rtc_data));
486 return rc;
487}
This page took 0.123937 seconds and 5 git commands to generate.