source: rtems/c/src/librdbg/src/servtsp.c @ 4a501bd

4.104.114.84.95
Last change on this file since 4a501bd was 718f981, checked in by Ralf Corsepius <ralf.corsepius@…>, on 07/18/03 at 05:19:20

2003-07-18 Ralf Corsepius <corsepiu@…>

  • src/rdbg.c: Use memset instead of bzero (deprecated).
  • src/servtsp.c: Ditto.
  • Property mode set to 100644
File size: 10.0 KB
Line 
1/*
2 **************************************************************************
3 *
4 *  Component:  RDBG
5 *  Module:     servtsp.c
6 *
7 *  Synopsis:   Transport management for remote debug server.
8 *
9 * $Id$
10 *
11 **************************************************************************
12 */
13
14#include <sys/errno.h>
15#include <rdbg/rdbg.h>
16#include <rdbg/servrpc.h>
17#include <signal.h>
18#include <rpc/rpc.h>
19#include <rpc/svc.h>
20#include <netinet/in.h>
21#include <sys/socket.h>
22
23static int out_sock;
24static int warm_test;
25
26static void TimeTestHandler ();
27
28    /*
29     *  TspInit - Initialize the transport system.
30     *
31     */
32
33  void
34TspInit (int id)
35{
36  struct sigaction sa;
37  struct sockaddr_in addr;
38
39  /*
40   * setup a socket to send event messages back through
41   */
42  out_sock = socket (PF_INET, SOCK_DGRAM, 0);
43  if (out_sock < 0) {
44    DPRINTF (("TspInit: socket() failed %d errno %d\n",
45              out_sock, getErrno ()));
46    return;                     /* failed to open socket, let caller deal with */
47  }
48
49  memset ((void *) (&addr), 0, sizeof (addr));
50  addr.sin_family = AF_INET;
51  addr.sin_port = htons (BackPort);
52  if (bind (out_sock, (struct sockaddr *) &addr, sizeof (addr)) < 0) {
53    DPRINTF (("TspInit: bind() failed\n"));
54  }
55  /*
56   * setup alarm timer for warm testing
57   */
58  memset (&sa, 0, sizeof (sa));
59  sa.sa_handler = TimeTestHandler;
60  sigaction (SIGALRM, &sa, 0);
61}
62
63    /*
64     *  TspTranslateRpcAddr - translate from an RPC handle to an
65     *                        opaque address.
66     *
67     *  Converts the sender's address into the opaque data structure
68     *  used for network addresses. This is used to look up the sender
69     *  on each call.
70     */
71
72  Boolean
73TspTranslateRpcAddr (struct svc_req *rqstp, NET_OPAQUE * opaque)
74{
75  struct sockaddr_in *addr;     /* used as template to extract net info */
76  unsigned char *up;
77
78  memset (opaque, 0, sizeof (NET_OPAQUE));
79  /*
80   *  We interpret the remote address as a standard netbuf name.
81   *  The format is 2 bytes of address family (normally AF_INET)
82   *  and then a length (5) and then the IP address.
83   */
84  if (rqstp->rq_xprt->xp_addrlen != 16) {
85    DPRINTF (("TspTranslateRpcAddr: Unknown remote address!!!\n"));
86    setErrno (EPROTONOSUPPORT);
87    return False;               /* invalid, so fails */
88  }
89  /*
90   * addr = &rqstp->rq_xprt->xp_raddr;
91   */
92  addr = svc_getcaller (rqstp->rq_xprt);
93  /*
94   * verify it is AF_INET
95   */
96  if (addr->sin_family != AF_INET) {    /* no, error */
97    DPRINTF (("TspTranslateRpcAddr: Not an internet address!!\n"));
98    setErrno (EAFNOSUPPORT);    /* invalid addr family */
99    return False;
100  }
101  /*
102   * good address type
103   */
104  up = (unsigned char *) &addr->sin_addr.s_addr;
105  DPRINTF (("TspTranslateRpcAddr: Sent by %u.%u.%u.%u port #%u\n",
106            up[0], up[1], up[2], up[3], htons (addr->sin_port)));
107  memcpy (opaque, addr, sizeof (struct sockaddr_in));
108  return True;
109}
110
111    /*
112     *  TspValidateAddr - validate a passed in opaque address.
113     *
114     *  Checks that the passed in address is in the format
115     *  expected.
116     */
117
118  Boolean
119TspValidateAddr (NET_OPAQUE * opaque, NET_OPAQUE * sender)
120{
121  struct sockaddr_in *addr;     /* used as template to extract net info */
122
123  addr = (struct sockaddr_in *) opaque;
124  /*
125   * Verify it is AF_INET. Should check against sender IP address too
126   */
127  if (addr->sin_family != AF_INET) {
128    DPRINTF (("TspValidateAddr: Back port invalid: %d\n",
129              htons (addr->sin_port)));
130    return False;               /* not valid */
131  }
132  /*
133   * otherwise, we copy in the IP address, since client may not know it
134   */
135  addr->sin_addr.s_addr = ((struct sockaddr_in *) sender)->sin_addr.s_addr;
136  DPRINTF (("TspValidateAddr: Back port is %d\n", htons (addr->sin_port)));
137  return True;
138}
139
140    /*
141     *  TspConnGetIndex - lookup an rpc caller's address as a connection entry.
142     *
143     *  Looks up an ip address of a caller to locate the
144     *  connection index in our connection array.
145     */
146
147  int
148TspConnGetIndex (struct svc_req *rqstp)
149{
150  int conn;
151  /*
152   * &rqstp->rq_xprt->xp_raddr;
153   */
154  struct sockaddr_in *addr = svc_getcaller (rqstp->rq_xprt);
155
156  for (conn = 0; conn < conn_list_cnt; conn++) {
157    if (!conn_list[conn].in_use)
158      continue;                 /* not used */
159
160    if (addr->sin_addr.s_addr == ((struct sockaddr_in *)
161                                  &conn_list[conn].sender)->sin_addr.s_addr
162        && addr->sin_port == ((struct sockaddr_in *)
163                              &conn_list[conn].sender)->sin_port) {
164      return conn;
165    }
166  }
167  return -1;
168}
169
170    /*
171     *  TspSendWaitChange - send wait-change message to clients to
172     *                      notify change.
173     */
174
175  void
176TspSendWaitChange (int conn,        /* connection to send to */
177                   BACK_MSG msg,    /* BMSG type */
178                   UINT16 spec,     /* special information */
179                   PID pid,         /* pid it refers to */
180                   UINT32 context,  /* additional context for message */
181                   Boolean force)  /* force into being only message */
182{                               
183  int idx;
184  struct SEND_LIST *snd_ptr;
185
186  if (force) {
187    /*
188     * force to top, which means others gone
189     */
190    idx = 0;
191    conn_list[conn].send_idx = 1;
192    conn_list[conn].retry = 0;
193  } else {
194    for (idx = 0; idx < (int) conn_list[conn].send_idx; idx++) {
195      if (conn_list[conn].send_list[idx].send_type == msg
196          && conn_list[conn].send_list[idx].pid == pid)
197        return;                 /* already pended for this pid */
198    }
199    idx = conn_list[conn].send_idx;
200    if (idx + 1 > MAX_SEND)
201      return;                   /* we lose it, what should we do??? */
202    conn_list[conn].send_idx++;
203  }
204  snd_ptr = &conn_list[conn].send_list[idx];
205  snd_ptr->send_type = msg;     /* message to send */
206  snd_ptr->retry = TSP_RETRIES; /* about 1 minute of retries */
207  snd_ptr->spec = htons ((u_short) spec);
208  snd_ptr->pid = htonl (pid);
209  snd_ptr->context = htonl (context);
210  TspSendMessage (conn, False); /* now do the send */
211}
212
213    /*
214     *  TspSendMessage - send message at top of send list for connection.
215     */
216
217  void
218TspSendMessage (int conn, Boolean resend)
219{
220  struct sockaddr_in addr;
221  struct UDP_MSG msg;
222  int cnt;
223
224  if (!resend && conn_list[conn].retry)
225    return;                     /* already waiting for reply */
226
227  /*
228   *  Note on above: if no back port we can't remove unless
229   *  someone blows off.
230   */
231  if (!resend) {
232    /*
233     * first time, setup. Set retry count:
234     */
235    conn_list[conn].retry = conn_list[conn].send_list[0].retry;
236    conn_list[conn].last_msg_num++; /* new sequence number */
237    if (!warm_test++) {         /* starting, so enable timer */
238      alarm (2);                /* resend every 2 seconds as needed */
239    }
240  }
241
242  msg.type = conn_list[conn].send_list[0].send_type;
243  msg.msg_num = conn_list[conn].last_msg_num;
244  msg.spec = conn_list[conn].send_list[0].spec;
245  msg.pid = conn_list[conn].send_list[0].pid;
246  msg.context = conn_list[conn].send_list[0].context;
247
248  memset (&addr, 0, sizeof (addr));
249  addr.sin_family = AF_INET;
250  addr.sin_port =
251    ((struct sockaddr_in *) &conn_list[conn].back_port)->sin_port;
252  addr.sin_addr.s_addr =
253    ((struct sockaddr_in *) &conn_list[conn].back_port)->sin_addr.s_addr;
254
255  DPRINTF (("TspSendMessage: Sending msg %d (%s) to port %d\n",
256            msg.type, BmsgNames[msg.type], HL_W (addr.sin_port)));
257
258  cnt = sendto (out_sock, &msg, sizeof (msg), 0, (struct sockaddr *) &addr,
259                sizeof (addr));
260  if (cnt != sizeof (msg)) {      /* failed on send */
261    printf ("%s: Failed to send msg %d to conn %d (%d vs. %ld)\n",
262            taskName, msg.type, conn, cnt, (long int) sizeof (msg));
263  }
264}
265
266    /*
267     *  TspMessageReceive - confirmation received, now send next if any.
268     *
269     *  - since UDP is connectionless, we batch up the sends and use
270     *    one at a time until we get a message indicating ready for
271     *    next (from ack).
272     */
273
274  void
275TspMessageReceive (int conn, PID pid)
276{
277  /*
278   * We remove the send list entry and use next if any
279   */
280  conn_list[conn].retry = 0;    /* reset */
281  if (!warm_test || !--warm_test) {
282    alarm (0);                  /* reset timer if not used */
283  }
284#ifdef DDEBUG
285  if (conn_list[conn].send_list[0].send_type == BMSG_WARM) {
286    DPRINTF (("TspMessageReceive: Connection reset for conn %d\n", conn));
287  }
288#endif
289  /*
290   * Move up by one if needed
291   */
292  if (!--conn_list[conn].send_idx)
293    return;                     /* no more to do */
294
295  memcpy (conn_list[conn].send_list, conn_list[conn].send_list + 1, conn_list[conn].send_idx * sizeof (struct SEND_LIST));  /* copy down */
296  TspSendMessage (conn, 0);
297}
298
299    /*
300     *  TspGetHostName - return client's host name.
301     *
302     *  - this routine returns the name of the client's host or the net
303     *    number of unknown.
304     */
305
306  char *
307TspGetHostName (conn_idx)
308     int conn_idx;              /* client connection number */
309{
310  static char buff[30];         /* largest net num */
311  unsigned char *cp;
312
313  cp = conn_list[conn_idx].sender.c + 4;
314  sprintf (buff, "%u.%u.%u.%u", cp[0], cp[1], cp[2], cp[3]);
315  return buff;
316}
317
318    /*
319     *  TimeTestHandler - alarm timer handler to resend warm/wait test.
320     */
321
322  static void
323TimeTestHandler ()
324{
325  int conn;
326
327  if (!warm_test)
328    return;                     /* no longer enabled */
329
330  for (conn = 0; conn < conn_list_cnt; conn++) {
331    /*
332     * locate all that are using this
333     */
334    if (!conn_list[conn].in_use)
335      continue;                 /* not used */
336
337    if (!conn_list[conn].retry)
338      continue;
339    /*
340     * found one that we are testing
341     */
342    if (!--conn_list[conn].retry) {
343      /*
344       *  Counted down the retries: blow off.
345       *  Need to have connection flag to indicate not blowing
346       *  off for cases where client is stopped due to being
347       *  debugged.
348       */
349      ConnDelete (conn, NULL, CLOSE_IGNORE);
350      continue;
351    }
352    TspSendMessage (conn, True);    /* send another message */
353  }
354  alarm (2);                    /* setup for 2 seconds from now */
355}
Note: See TracBrowser for help on using the repository browser.