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

Last change on this file was 1929, checked in by murphpo, 11 years ago

Adding updated WARPxilnet, required for WARPLab 7 ref design

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