source: edk_user_repository/WARP/sw_services/WARPxilnet_v3_03_a/src/xilnet_xilsock.c

Last change on this file was 2608, checked in by welsh, 10 years ago

Fixed bug when socket is released: free bit was not being set causing the socket to not be reused by the framework. Updated send function to allow for multiple buffers to be used instead of just the single send buffer provided by xilnet.

File size: 14.7 KB
Line 
1
2////////////////////////////////////////////////////////////////////////////////
3// Copyright (c) 2004 Xilinx, Inc.  All rights reserved.
4//
5// Xilinx, Inc.
6// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
7// COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
8// ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
9// STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
10// IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
11// FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
12// XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
13// THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
14// ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
15// FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
16// AND FITNESS FOR A PARTICULAR PURPOSE.
17//
18// File   : xilsock.c
19// Date   : 2002, March 20.
20// Author : Sathya Thammanur
21// Company: Xilinx
22// Group  : Emerging Software Technologies
23//
24// Summary:
25// Xilinx internal socket related functions (xilsock functions)
26//
27// $Id: xilsock.c,v 1.2.8.6 2005/11/15 23:41:10 salindac Exp $
28//
29////////////////////////////////////////////////////////////////////////////////
30
31////////////////////////////////////////////////////////////////////////////////
32// see copyright.txt for Rice University/Mango Communications modifications
33////////////////////////////////////////////////////////////////////////////////
34
35#include <xilnet_config.h>
36
37/*
38 * Print the xilsock error message
39 */
40
41void xilsock_print_error_msg( unsigned int eth_dev_num ) {
42    xil_printf("  **** ERROR:  Ethernet device %d is not supported by the WARPxilnet library.  \n", (eth_dev_num+1) );
43    xil_printf("               Please check library configuration in the BSP.   \n" );
44}
45
46
47
48/*
49 * Initialization of xilsock_sockets
50 */
51
52int xilsock_init (unsigned int eth_dev_num) {
53
54    int i;
55   
56    struct xilsock_socket * sockets = (struct xilsock_socket *)eth_device[eth_dev_num].xilsock_sockets;
57   
58    // Check to see if the xilnet driver uses the Ethernet instance
59    if ( !eth_device[eth_dev_num].uses_driver ) {
60        xilsock_print_error_msg( eth_dev_num );
61        return -1;
62    }
63
64    if (!eth_device[eth_dev_num].is_xilsock_init) {
65        for (i = 0; i < NO_OF_XILSOCKS; i++) {
66            sockets[i].type          = 0;
67            sockets[i].domain        = 0;
68            sockets[i].proto         = 0;
69            sockets[i].listen        = 0;
70            sockets[i].bound         = 0;
71            sockets[i].accept        = 0;
72            sockets[i].connect       = 0;
73            sockets[i].closing       = 0;
74            sockets[i].closed        = 0;
75            sockets[i].free          = 1;
76            sockets[i].conn.tcp_conn = NULL;
77            sockets[i].recvbuf.buf   = NULL;
78            sockets[i].recvbuf.size  = 0;
79        }
80        eth_device[eth_dev_num].is_xilsock_init = 1;
81    }
82    return eth_device[eth_dev_num].is_xilsock_init;
83}
84
85
86/*
87 * Release a socket
88 */
89
90void xilsock_rel_socket (int sd, unsigned int eth_dev_num) {
91
92    struct xilsock_socket * sockets = (struct xilsock_socket *)eth_device[eth_dev_num].xilsock_sockets;
93
94    // Check to see if the xilnet driver uses the Ethernet instance
95    if ( !eth_device[eth_dev_num].uses_driver ) {
96        xilsock_print_error_msg( eth_dev_num );
97        return;
98    }
99
100    // Zero out the socket
101    memset( &( sockets[sd] ), 0x0, sizeof( xilsock_socket ) );
102
103    // Set the free field
104    sockets[sd].free = 1;
105   
106   
107#if 0   
108    if (sockets[sd].type == SOCK_STREAM) {
109        sockets[sd].conn.tcp_conn = NULL;
110    }
111    else {
112        sockets[sd].conn.udp_conn = NULL;
113    }
114    sockets[sd].type         = 0;
115    sockets[sd].domain       = 0;
116    sockets[sd].proto        = 0;
117    sockets[sd].listen       = 0;
118    sockets[sd].bound        = 0;
119    sockets[sd].accept       = 0;
120    sockets[sd].connect      = 0;
121    sockets[sd].closing      = 0;
122    sockets[sd].closed       = 0;
123    sockets[sd].free         = 1;
124    sockets[sd].recvbuf.buf  = NULL;
125    sockets[sd].recvbuf.size = 0;
126#endif
127
128}
129
130
131/*
132 * Allocate a xilsock_socket and return socket descriptor
133 * if not able to alloc socket, return -1
134 */
135
136int xilsock_socket(int domain, int type, int proto, unsigned int eth_dev_num) {
137
138    int sd;
139    struct xilsock_socket * sockets = (struct xilsock_socket *)eth_device[eth_dev_num].xilsock_sockets;
140
141    // Check to see if the xilnet driver uses the Ethernet instance
142    if ( !eth_device[eth_dev_num].uses_driver ) {
143        xilsock_print_error_msg( eth_dev_num );
144        return -1;
145    }
146
147    // find a free xilsock_socket
148    if (!xilsock_init(eth_dev_num)){
149        xil_printf("xilsock is not initialized\n");
150        return (-1);
151    }
152   
153    for (sd = 0; sd < NO_OF_XILSOCKS; sd++) {
154        if (sockets[sd].free) {
155            // initialise the socket & make it unavailable
156            sockets[sd].domain = domain;
157            sockets[sd].type   = type;
158            sockets[sd].proto  = proto;
159            sockets[sd].free   = 0;
160
161            // Debug print:
162            // xil_printf("Socket %d: [%d, %d, %d, %d] \n", sd, domain, type, proto, eth_dev_num);
163            return sd;
164        }
165    }
166    // return as no sockets available
167    xil_printf("No sockets available on ethernet device %d!\n", eth_dev_num);
168    return -1;
169}
170
171
172/*
173 * bind a socket to the specified address.
174 * binds addr to socket sd. returns 1 if bound
175 * returns -1 if not able to bind
176 */
177
178int xilsock_bind(int sd, struct sockaddr* addr, int addrlen, void (*callback) (), unsigned int eth_dev_num) {
179
180    int connd;
181    struct xilsock_socket  * sockets = (struct xilsock_socket  *)eth_device[eth_dev_num].xilsock_sockets;
182    struct xilnet_udp_conn * conns   = (struct xilnet_udp_conn *)eth_device[eth_dev_num].xilnet_udp_conns;
183
184    // Check to see if the xilnet driver uses the Ethernet instance
185    if ( !eth_device[eth_dev_num].uses_driver ) {
186        xilsock_print_error_msg( eth_dev_num );
187        return -1;
188    }
189
190    // open a tcp conn/udp conn
191    if (sockets[sd].type == SOCK_STREAM) {
192        xil_printf("*** Error xilsock_bind: tcp sockets not available \n");
193        xilsock_rel_socket(sd, eth_dev_num);
194        return -1;
195    }
196    else if (sockets[sd].type == SOCK_DGRAM) {
197        if ( (connd = xilnet_udp_open_conn (((struct sockaddr_in*)addr)->sin_port, callback, eth_dev_num)) == -1) {
198            xil_printf("*** Error xilsock_bind: udp sockets not available \n");
199            xilsock_rel_socket(sd, eth_dev_num);
200            return -1;
201        }
202        sockets[sd].conn.udp_conn = (conns + connd);
203        // update fd of udp conn
204        conns[connd].fd = sd;
205    }
206
207    return 1;
208}
209
210
211/*
212 * listen on a socket
213 * called from listen()
214 */
215
216int xilsock_listen(int s, int backlog, unsigned int eth_dev_num) {
217
218    struct xilsock_socket  * sockets = (struct xilsock_socket  *)eth_device[eth_dev_num].xilsock_sockets;
219
220    // Check to see if the xilnet driver uses the Ethernet instance
221    if ( !eth_device[eth_dev_num].uses_driver ) {
222        xilsock_print_error_msg( eth_dev_num );
223        return -1;
224    }
225
226    sockets[s].listen = 1;
227    return 1;
228}
229
230
231
232/*
233 * recv data on socket
234 * called from recv()
235 * returns -1 if no data recvd for "s" (non_blocking call) or
236 * number of bytes recvd for "s"
237 */
238
239int xilsock_recv(int s, unsigned char *buf, unsigned int len, unsigned int eth_dev_num) {
240
241    unsigned int n;
242    struct xilsock_socket  * sockets = (struct xilsock_socket  *)eth_device[eth_dev_num].xilsock_sockets;
243    int bytes_recvd = 0;
244
245    // Check to see if the xilnet driver uses the Ethernet instance
246    if ( !eth_device[eth_dev_num].uses_driver ) {
247        xilsock_print_error_msg( eth_dev_num );
248        return -1;
249    }
250
251    if (s > NO_OF_XILSOCKS) {
252        xil_printf("*** Error xilsock_recv: invalid socket descriptor %d \n", s);
253        return -1;
254    }
255
256   n = xilnet_eth_recv_frame(eth_dev_num);
257
258   // Return if data not for socket s
259   if ((n == -1) || (sockets[s].recvbuf.buf == NULL))
260      return -1;
261
262   // Copy data if required onto buf
263   if (sockets[s].recvbuf.buf != buf)
264   {
265      memcpy(buf, sockets[s].recvbuf.buf, len);
266      bytes_recvd = sockets[s].recvbuf.size;
267
268      //reset socket buffer and size
269      sockets[s].recvbuf.buf  = NULL;
270      sockets[s].recvbuf.size = 0;
271   }
272
273   // return no of bytes recvd for this conn
274   return bytes_recvd;
275}
276
277
278/*
279 * send data on socket
280 * called from send()
281 */
282
283int xilsock_send(int s,  unsigned char* buf, unsigned int len, unsigned int eth_dev_num) {
284
285    xil_printf("*** Error xilsock_send: TCP connections are not supported\n");
286    return -1;
287
288#if 0
289    struct xilnet_tcp_conn *conn;
290    struct xilsock_socket  * sockets = (struct xilsock_socket  *)eth_device[eth_dev_num].xilsock_sockets;
291    unsigned char          * sendbuf = (unsigned char *)eth_device[eth_dev_num].sendbuf;
292
293
294    conn = sockets[s].conn.tcp_conn;
295
296    if (!conn) {
297        xil_printf("*** Error xilsock_send: no such socket %d \n", conn);
298        return -1;
299    }
300
301    if (buf != sendbuf) {
302        memset(sendbuf, 0, eth_device[eth_dev_num].buf_size);
303        memcpy(sendbuf+LINK_HDR_LEN+IP_HDR_LEN*4+(TCP_HDR_LEN*4), buf, len);
304    }
305
306     xilnet_tcp_send_pkt(conn, sendbuf+LINK_HDR_LEN+IP_HDR_LEN*4, len, TCP_ACK, eth_dev_num);
307     xilnet_ip_header(sendbuf+LINK_HDR_LEN, len+(TCP_HDR_LEN*4)+IP_HDR_LEN*4, IP_PROTO_TCP, conn->dst_ip, eth_dev_num);
308
309     xilnet_eth_send_frame(sendbuf, len+(TCP_HDR_LEN*4)+IP_HDR_LEN*4+ETH_HDR_LEN, conn->dst_ip, NULL, ETH_PROTO_IP, eth_dev_num);
310
311     return len;
312#endif
313}
314
315
316/*
317 * recvfrom socket
318 * Data recvd on any UDP socket
319 * return -1 if data not for socket "s" [non-blocking call]
320 */
321int xilsock_recvfrom(int s, unsigned char *buf, unsigned int len,
322                     struct sockaddr* from, unsigned int *fromlen, unsigned int eth_dev_num)
323{
324    int n;
325    int bytes_recvd = 0;
326    struct xilsock_socket  * sockets = (struct xilsock_socket  *)eth_device[eth_dev_num].xilsock_sockets;
327    struct xilnet_udp_conn * conn    = sockets[s].conn.udp_conn;
328
329    // Check to see if the xilnet driver uses the Ethernet instance
330    if ( !eth_device[eth_dev_num].uses_driver ) {
331        xilsock_print_error_msg( eth_dev_num );
332        return -1;
333    }
334
335    if (s > NO_OF_XILSOCKS) {
336        xil_printf("*** Error xilsock_recvfrom: invalid socket descriptor %d \n", s);
337        return -1;
338    }
339
340    n = xilnet_eth_recv_frame(eth_dev_num);
341
342    // Return if data not for socket s
343    if ((n < 0 ) || (sockets[s].recvbuf.buf == NULL))
344        return -1;
345
346   // Copy data if required onto buf
347   if (sockets[s].recvbuf.buf != buf)
348   {
349      memcpy(buf, sockets[s].recvbuf.buf, len);
350      bytes_recvd = sockets[s].recvbuf.size;
351
352      //reset socket buffer and size
353      sockets[s].recvbuf.buf = NULL;
354      sockets[s].recvbuf.size = 0;
355   }
356
357   // Copy the source address onto "to"
358   ((struct sockaddr_in*)from)->sin_addr.s_addr =
359      (conn->dst_ip[0] << 24) + (conn->dst_ip[1] << 16) + (conn->dst_ip[2] << 8) + conn->dst_ip[3];
360   ((struct sockaddr_in*)from)->sin_port = conn->dst_port;
361   *fromlen = sizeof(from);
362
363   // return no of bytes recvd for this conn
364   return bytes_recvd;
365}
366
367
368/*
369 * sendto socket
370 * called from sendto()
371 */
372
373int xilsock_sendto(int s,  unsigned char* buf, unsigned int len, struct sockaddr* to, unsigned int eth_dev_num)
374{
375
376    struct xilnet_udp_conn * conn;
377    struct xilsock_socket  * sockets = (struct xilsock_socket  *)eth_device[eth_dev_num].xilsock_sockets;
378    unsigned int             dstaddr = ((struct sockaddr_in*)to)->sin_addr.s_addr;
379    unsigned char          * sendbuf = buf;
380
381    // Updated function so that it uses the provided buffer instead of copying the data to the sendbuf of the
382    //   given ethernet device.  This enables callers to maintain buffers beyond the single send buffer
383    //   provided by the Xilnet framework.
384    //
385    // unsigned char          * sendbuf = (unsigned char *)eth_device[eth_dev_num].sendbuf;
386
387    // Check to see if the xilnet driver uses the Ethernet instance
388    if ( !eth_device[eth_dev_num].uses_driver ) {
389        xilsock_print_error_msg( eth_dev_num );
390        return -1;
391    }
392   
393    conn = sockets[s].conn.udp_conn;
394    conn->dst_ip[0] = (unsigned char) ((dstaddr >> 24) & 0xFF);
395    conn->dst_ip[1] = (unsigned char) ((dstaddr >> 16) & 0xFF);
396    conn->dst_ip[2] = (unsigned char) ((dstaddr >> 8) & 0xFF);
397    conn->dst_ip[3] = (unsigned char) ((dstaddr) & 0xFF);
398    conn->dst_port  = ((struct sockaddr_in*)to)->sin_port;
399
400    if (!conn) {
401        xil_printf("*** Error xilsock_sendto: no such socket %d \n", conn);
402        return -1;
403    }
404
405    // See comments above.
406    //
407    // if (buf != sendbuf) {
408    //     memset(sendbuf, 0, eth_device[eth_dev_num].buf_size);
409    //     memcpy(sendbuf+LINK_HDR_LEN+IP_HDR_LEN*4+UDP_HDR_LEN, buf, len);
410    // }
411
412    // calls to udp stack
413    xilnet_udp_header(conn, sendbuf+LINK_HDR_LEN+IP_HDR_LEN*4, len+UDP_HDR_LEN, eth_dev_num);
414
415    xilnet_ip_header(sendbuf+LINK_HDR_LEN, len+UDP_HDR_LEN+IP_HDR_LEN*4, IP_PROTO_UDP, conn->dst_ip, eth_dev_num);
416
417    xilnet_eth_send_frame(sendbuf, len+UDP_HDR_LEN+IP_HDR_LEN*4+ETH_HDR_LEN, conn->dst_ip, NULL, ETH_PROTO_IP, eth_dev_num);
418
419    return len;
420}
421
422
423/*
424 * close socket
425 */
426
427void xilsock_close(int s, unsigned int eth_dev_num) {
428
429#if 0
430    unsigned char flags = 0;
431    unsigned short check = 0;
432    unsigned char *tcp_reply;
433    unsigned char          * sendbuf = (unsigned char *)eth_device[eth_dev_num].sendbuf;
434#endif
435    struct xilsock_socket  * sockets = (struct xilsock_socket  *)eth_device[eth_dev_num].xilsock_sockets;
436
437    // Check to see if the xilnet driver uses the Ethernet instance
438    if ( !eth_device[eth_dev_num].uses_driver ) {
439        xilsock_print_error_msg( eth_dev_num );
440        return;
441    }
442
443    if (sockets[s].type == SOCK_STREAM) {
444
445        xil_printf("*** Error xilsock_close: TCP connections are not supported\n");
446
447#if 0
448        struct xilnet_tcp_conn *conn = sockets[s].conn.tcp_conn;
449
450        // construct the FIN and wait for ack & FIN from client
451        flags = (TCP_FIN | TCP_ACK);
452        ((struct xilnet_tcp_conn*)conn)->state = TCP_FIN_WAIT1;
453        memset(sendbuf, 0, LINK_FRAME_LEN);
454        tcp_reply = sendbuf+ETH_HDR_LEN+(IP_HDR_LEN*4);
455
456        xilnet_tcp_header(((struct xilnet_tcp_conn*)conn), tcp_reply, 1, flags, eth_dev_num);
457
458        // calculate tcp checksum
459        check = xilnet_udp_tcp_calc_chksum(tcp_reply, (TCP_HDR_LEN*4), eth_device[eth_dev_num].node_ip_addr, ((struct xilnet_tcp_conn*)conn)->dst_ip, IP_PROTO_TCP);
460        tcp_reply[TCP_CHECK_OFF]   = (check & 0xff00) >> 8;
461        tcp_reply[TCP_CHECK_OFF+1] = (check & 0x00ff);
462
463        xilnet_ip_header(sendbuf+ETH_HDR_LEN,(IP_HDR_LEN*4)+(TCP_HDR_LEN*4), IP_PROTO_TCP, ((struct xilnet_tcp_conn*)conn)->dst_ip, eth_dev_num);
464        xilnet_eth_send_frame(sendbuf, (TCP_HDR_LEN*4)+(IP_HDR_LEN*4)+ETH_HDR_LEN, ((struct xilnet_tcp_conn*)conn)->dst_ip, NULL, ETH_PROTO_IP, eth_dev_num);
465#endif
466
467    }
468    else if (sockets[s].type == SOCK_DGRAM) {
469        xilnet_udp_close_conn(sockets[s].conn.udp_conn, eth_dev_num);
470        // close the socket
471        xilsock_rel_socket(s, eth_dev_num);
472    }
473}
Note: See TracBrowser for help on using the repository browser.