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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [redboot/] [current/] [src/] [net/] [udp.c] - Blame information for rev 856

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

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      net/udp.c
4
//
5
//      Stand-alone UDP networking support for RedBoot
6
//
7
//==========================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
9
// -------------------------------------------                              
10
// This file is part of eCos, the Embedded Configurable Operating System.   
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under    
14
// the terms of the GNU General Public License as published by the Free     
15
// Software Foundation; either version 2 or (at your option) any later      
16
// version.                                                                 
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT      
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
21
// for more details.                                                        
22
//
23
// You should have received a copy of the GNU General Public License        
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
26
//
27
// As a special exception, if other files instantiate templates or use      
28
// macros or inline functions from this file, or you compile this file      
29
// and link it with other works to produce a work based on this file,       
30
// this file does not by itself cause the resulting work to be covered by   
31
// the GNU General Public License. However the source code for this file    
32
// must still be made available in accordance with section (3) of the GNU   
33
// General Public License v2.                                               
34
//
35
// This exception does not invalidate any other reasons why a work based    
36
// on this file might be covered by the GNU General Public License.         
37
// -------------------------------------------                              
38
// ####ECOSGPLCOPYRIGHTEND####                                              
39
//==========================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):    gthomas
43
// Contributors: gthomas
44
// Date:         2000-07-14
45
// Purpose:      
46
// Description:  
47
//              
48
// This code is part of RedBoot (tm).
49
//
50
//####DESCRIPTIONEND####
51
//
52
//==========================================================================
53
 
54
#include <redboot.h>
55
#include <net/net.h>
56
 
57
#ifdef UDP_STATS
58
static int udp_rx_total;
59
static int udp_rx_handled;
60
static int udp_rx_cksum;
61
static int udp_rx_dropped;
62
#endif
63
 
64
#define MAX_UDP_DATA (ETH_MAX_PKTLEN - (ETH_HDR_SIZE + \
65
                                        sizeof(ip_header_t)  + \
66
                                        sizeof(udp_header_t)))
67
 
68
/*
69
 * A major assumption is that only a very small number of sockets will
70
 * active, so a simple linear search of those sockets is acceptible.
71
 */
72
static udp_socket_t *udp_list;
73
 
74
 
75
/*
76
 * Install a handler for incoming udp packets.
77
 * Caller provides the udp_socket_t structure.
78
 * Returns zero if successful, -1 if socket is already used.
79
 */
80
int
81
__udp_install_listener(udp_socket_t *s, word port, udp_handler_t handler)
82
{
83
    udp_socket_t *p;
84
 
85
    /*
86
     * Make sure we only have one handler per port.
87
     */
88
    for (p = udp_list; p; p = p->next)
89
        if (p->our_port == port)
90
            return -1;
91
 
92
    s->our_port = htons(port);
93
    s->handler = handler;
94
    s->next = udp_list;
95
    udp_list = s;
96
 
97
    return 0;
98
}
99
 
100
 
101
/*
102
 * Remove the handler for the given socket.
103
 */
104
void
105
__udp_remove_listener(word port)
106
{
107
    udp_socket_t *prev, *s;
108
 
109
    for (prev = NULL, s = udp_list; s; prev = s, s = s->next)
110
        if (s->our_port == htons(port)) {
111
            if (prev)
112
                prev->next = s->next;
113
            else
114
                udp_list = s->next;
115
        }
116
}
117
 
118
 
119
/*
120
 * Handle incoming UDP packets.
121
 */
122
void
123
__udp_handler(pktbuf_t *pkt, ip_route_t *r)
124
{
125
    udp_header_t *udp = pkt->udp_hdr;
126
    ip_header_t  *ip = pkt->ip_hdr;
127
    udp_socket_t *s;
128
 
129
    if (udp->checksum == 0xffff)
130
        udp->checksum = 0;
131
 
132
    /* copy length for pseudo sum calculation */
133
    ip->length = udp->length;
134
 
135
    if (__sum((word *)udp, ntohs(udp->length), __pseudo_sum(ip)) == 0) {
136
        for (s = udp_list; s; s = s->next) {
137
            if (s->our_port == udp->dest_port) {
138
                (*s->handler)(s, ((char *)udp) + sizeof(udp_header_t),
139
                              ntohs(udp->length) - sizeof(udp_header_t),
140
                              r, ntohs(udp->src_port));
141
                __pktbuf_free(pkt);
142
                return;
143
            }
144
        }
145
    }
146
    __pktbuf_free(pkt);
147
}
148
 
149
 
150
/*
151
 * Send a UDP packet.
152
 */
153
int
154
__udp_send(char *buf, int len, ip_route_t *dest_ip,
155
           word dest_port, word src_port)
156
{
157
    pktbuf_t *pkt;
158
    udp_header_t *udp;
159
    ip_header_t *ip;
160
    unsigned short cksum;
161
    int ret;
162
 
163
    /* dumb */
164
    if (len > MAX_UDP_DATA)
165
        return -1;
166
 
167
    /* just drop it if can't get a buffer */
168
    if ((pkt = __pktbuf_alloc(ETH_MAX_PKTLEN)) == NULL)
169
        return -1;
170
 
171
    udp = pkt->udp_hdr;
172
    ip = pkt->ip_hdr;
173
 
174
    pkt->pkt_bytes = len + sizeof(udp_header_t);
175
 
176
    udp->src_port = htons(src_port);
177
    udp->dest_port = htons(dest_port);
178
    udp->length = htons(pkt->pkt_bytes);
179
    udp->checksum = 0;
180
 
181
    memcpy(((char *)udp) + sizeof(udp_header_t), buf, len);
182
 
183
    /* fill in some pseudo-header fields */
184
    memcpy(ip->source, __local_ip_addr, sizeof(ip_addr_t));
185
    memcpy(ip->destination, dest_ip->ip_addr, sizeof(ip_addr_t));
186
    ip->protocol = IP_PROTO_UDP;
187
    ip->length = udp->length;
188
 
189
    cksum = __sum((word *)udp, pkt->pkt_bytes, __pseudo_sum(ip));
190
    udp->checksum = htons(cksum);
191
 
192
    ret = __ip_send(pkt, IP_PROTO_UDP, dest_ip);
193
    __pktbuf_free(pkt);
194
    return ret;
195
}
196
 
197
int
198
__udp_sendto(char *data, int len, struct sockaddr_in *server,
199
             struct sockaddr_in *local)
200
{
201
    ip_route_t rt;
202
 
203
   if (__arp_lookup((ip_addr_t *)&server->sin_addr, &rt) < 0) {
204
       diag_printf("%s: Can't find address of server\n", __FUNCTION__);
205
       return -1;
206
   } else {
207
      __udp_send(data, len, &rt, ntohs(server->sin_port), ntohs(local->sin_port));
208
       return 0;
209
   }
210
}
211
 
212
static char               *recvfrom_buf;
213
static int                 recvfrom_len;
214
static struct sockaddr_in *recvfrom_server;
215
 
216
static void
217
__udp_recvfrom_handler(udp_socket_t *skt, char *buf, int len,
218
                       ip_route_t *src_route, word src_port)
219
{
220
    if (recvfrom_server == NULL || recvfrom_buf == NULL)
221
        return;
222
 
223
    if (recvfrom_server->sin_port && recvfrom_server->sin_port != htons(src_port))
224
        return;
225
 
226
    // Move data to waiting buffer
227
    recvfrom_len = len;
228
    memcpy(recvfrom_buf, buf, len);
229
    if (recvfrom_server) {
230
        recvfrom_server->sin_port = htons(src_port);
231
        memcpy(&recvfrom_server->sin_addr, &src_route->ip_addr, sizeof(src_route->ip_addr));
232
        recvfrom_buf = (char *)0;  // Tell reader we got a packet
233
    } else {
234
        diag_printf("udp_recvfrom - dropped packet of %d bytes\n", len);
235
    }
236
}
237
 
238
int
239
__udp_recvfrom(char *data, int len, struct sockaddr_in *server,
240
               struct sockaddr_in *local, struct timeval *timo)
241
{
242
    int res, my_port, total_ms;
243
    udp_socket_t skt;
244
    unsigned long start;
245
 
246
    my_port = ntohs(local->sin_port);
247
    if (__udp_install_listener(&skt, my_port, __udp_recvfrom_handler) < 0) {
248
        return -1;
249
    }
250
    recvfrom_buf = data;
251
    recvfrom_len = len;
252
    recvfrom_server = server;
253
    total_ms = (timo->tv_sec * 1000) + (timo->tv_usec / 1000);
254
    start = MS_TICKS();
255
    res = -1;
256
    do {
257
        __enet_poll();  // Handle the hardware
258
        if (!recvfrom_buf) {
259
            // Data have arrived
260
            res = recvfrom_len;
261
            break;
262
        }
263
    } while ((MS_TICKS_DELAY() - start) < total_ms);
264
    __udp_remove_listener(my_port);
265
    return res;
266
}

powered by: WebSVN 2.1.0

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