source: rtems/c/src/librdbg/src/servtsp.c @ df49c60

4.104.114.84.95
Last change on this file since df49c60 was 981b99f, checked in by Joel Sherrill <joel.sherrill@…>, on Aug 10, 1999 at 4:41:44 PM

Patch from Eric Valette <valette@…> and Emmanuel Raguet
<raguet@…>:

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