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