OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems-20020807/] [c/] [src/] [librdbg/] [src/] [servtsp.c] - Blame information for rev 1780

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1026 ivang
/*
2
 **************************************************************************
3
 *
4
 *  Component:  RDBG
5
 *  Module:     servtsp.c
6
 *
7
 *  Synopsis:   Transport management for remote debug server.
8
 *
9
 * servtsp.c,v 1.3 2002/02/01 17:00:01 joel Exp
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
 
23
static int out_sock;
24
static int warm_test;
25
 
26
static void TimeTestHandler ();
27
 
28
    /*
29
     *  TspInit - Initialize the transport system.
30
     *
31
     */
32
 
33
  void
34
TspInit (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
  bzero ((void *) (&addr), 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
73
TspTranslateRpcAddr (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
119
TspValidateAddr (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
148
TspConnGetIndex (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
176
TspSendWaitChange (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
218
TspSendMessage (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. %d)\n",
262
            taskName, msg.type, conn, cnt, 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
275
TspMessageReceive (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 *
307
TspGetHostName (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
323
TimeTestHandler ()
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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.