/[lwip]/lwip/src/api/sockets.c
ViewVC logotype

Diff of /lwip/src/api/sockets.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.7 by jani, Fri Jan 31 12:51:56 2003 UTC revision 1.8 by davidhaas, Thu Feb 6 22:18:56 2003 UTC
# Line 28  Line 28 
28   *   *
29   * Author: Adam Dunkels <adam@sics.se>   * Author: Adam Dunkels <adam@sics.se>
30   *   *
31     * Improved by Marc Boucher <marc@mbsi.ca> and David Haas <dhaas@alum.rpi.edu>
32     *
33   */   */
34    
35  #include "lwip/debug.h"  #include "lwip/debug.h"
36  #include "lwip/api.h"  #include "lwip/api.h"
37    #include "lwip/arch.h"
38    #include "lwip/sys.h"
39    
40  #include "lwip/sockets.h"  #include "lwip/sockets.h"
41    
42  #define NUM_SOCKETS 10  #define NUM_SOCKETS MEMP_NUM_NETCONN
43    
44  struct lwip_socket {  struct lwip_socket {
45    struct netconn *conn;    struct netconn *conn;
46    struct netbuf *lastdata;    struct netbuf *lastdata;
47    u16_t lastoffset;    u16_t lastoffset;
48      u16_t rcvevent;
49      u16_t sendevent;
50      u16_t flags;
51      int err;
52    };
53    
54    struct lwip_select_cb
55    {
56        struct lwip_select_cb *next;
57        fd_set *readset;
58        fd_set *writeset;
59        fd_set *exceptset;
60        int sem_signalled;
61        sys_sem_t sem;
62  };  };
63    
64  static struct lwip_socket sockets[NUM_SOCKETS];  static struct lwip_socket sockets[NUM_SOCKETS];
65    static struct lwip_select_cb *select_cb_list = 0;
66    
67    static sys_sem_t socksem = 0;
68    static sys_sem_t selectsem = 0;
69    
70    static void
71    event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len);
72    
73    static int err_to_errno_table[11] = {
74        0,                  /* ERR_OK    0      No error, everything OK. */
75        ENOMEM,             /* ERR_MEM  -1      Out of memory error.     */
76        ENOBUFS,            /* ERR_BUF  -2      Buffer error.            */
77        ECONNABORTED,       /* ERR_ABRT -3      Connection aborted.      */
78        ECONNRESET,         /* ERR_RST  -4      Connection reset.        */
79        ESHUTDOWN,          /* ERR_CLSD -5      Connection closed.       */
80        ENOTCONN,           /* ERR_CONN -6      Not connected.           */
81        EINVAL,             /* ERR_VAL  -7      Illegal value.           */
82        EIO,                /* ERR_ARG  -8      Illegal argument.        */
83        EHOSTUNREACH,       /* ERR_RTE  -9      Routing problem.         */
84        EADDRINUSE          /* ERR_USE  -10     Address in use.          */
85    };
86    
87    #define err_to_errno(err) \
88            ((err) < (sizeof(err_to_errno_table)/sizeof(int))) ? \
89                    err_to_errno_table[-(err)] : EIO
90    
91    #ifdef ERRNO
92    #define set_errno(err) errno = (err)
93    #else
94    #define set_errno(err)
95    #endif
96    
97    #define sock_set_errno(sk, e) do { \
98                            sk->err = (e); \
99                            set_errno(sk->err); \
100    } while(0)
101    
102  /*-----------------------------------------------------------------------------------*/  /*-----------------------------------------------------------------------------------*/
103  static struct lwip_socket *  static struct lwip_socket *
# Line 51  get_socket(int s) Line 105  get_socket(int s)
105  {  {
106    struct lwip_socket *sock;    struct lwip_socket *sock;
107        
108    if(s > NUM_SOCKETS) {    if((s < 0) || (s > NUM_SOCKETS)) {
109      /* errno = EBADF; */          DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): invalid\n", s));
110            set_errno(EBADF);
111      return NULL;      return NULL;
112    }    }
113        
114    sock = &sockets[s];    sock = &sockets[s];
115    
116    if(sock->conn == NULL) {    if(!sock->conn) {
117      /* errno = EBADF; */          DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): not active\n", s));
118            set_errno(EBADF);
119      return NULL;      return NULL;
120    }    }
121    
122    return sock;    return sock;
123  }  }
124  /*-----------------------------------------------------------------------------------*/  /*-----------------------------------------------------------------------------------*/
# Line 69  static int Line 126  static int
126  alloc_socket(struct netconn *newconn)  alloc_socket(struct netconn *newconn)
127  {  {
128    int i;    int i;
129    
130      if (!socksem)
131          socksem = sys_sem_new(1);
132    
133      /* Protect socket array */
134      sys_sem_wait(socksem);
135        
136    /* allocate a new socket identifier */    /* allocate a new socket identifier */
137    for(i = 0; i < NUM_SOCKETS; ++i) {    for(i = 0; i < NUM_SOCKETS; ++i) {
138      if(sockets[i].conn == NULL) {      if(!sockets[i].conn) {
139        sockets[i].conn = newconn;        sockets[i].conn = newconn;
140        sockets[i].lastdata = NULL;        sockets[i].lastdata = NULL;
141        sockets[i].lastoffset = 0;        sockets[i].lastoffset = 0;
142          sockets[i].rcvevent = 0;
143          sockets[i].sendevent = 1; /* TCP send buf is empty */
144          sockets[i].flags = 0;
145          sockets[i].err = 0;
146          sys_sem_signal(socksem);
147        return i;        return i;
148      }      }
149    }    }
150      sys_sem_signal(socksem);
151    return -1;    return -1;
152  }  }
153  /*-----------------------------------------------------------------------------------*/  /*-----------------------------------------------------------------------------------*/
# Line 90  lwip_accept(int s, struct sockaddr *addr Line 159  lwip_accept(int s, struct sockaddr *addr
159    struct ip_addr naddr;    struct ip_addr naddr;
160    u16_t port;    u16_t port;
161    int newsock;    int newsock;
162      struct sockaddr_in sin;
163    
164      DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s));
165    sock = get_socket(s);    sock = get_socket(s);
166    if(sock == NULL) {    if(!sock) {
167      return -1;      return -1;
168    }    }
169        
# Line 101  lwip_accept(int s, struct sockaddr *addr Line 172  lwip_accept(int s, struct sockaddr *addr
172    /* get the IP address and port of the remote host */    /* get the IP address and port of the remote host */
173    netconn_peer(newconn, &naddr, &port);    netconn_peer(newconn, &naddr, &port);
174        
175    ((struct sockaddr_in *)addr)->sin_addr.s_addr = naddr.addr;    memset(&sin, 0, sizeof(sin));
176    ((struct sockaddr_in *)addr)->sin_port = port;    sin.sin_len = sizeof(sin);
177      sin.sin_family = AF_INET;
178      sin.sin_port = htons(port);
179      sin.sin_addr.s_addr = naddr.addr;
180    
181      if(*addrlen > sizeof(sin))
182          *addrlen = sizeof(sin);
183    
184      memcpy(addr, &sin, *addrlen);
185    
186    newsock = alloc_socket(newconn);    newsock = alloc_socket(newconn);
187    if(newsock == -1) {      if(newsock == -1) {  
188      netconn_delete(newconn);      netconn_delete(newconn);
189      /* errno = ENOBUFS; */          sock_set_errno(sock, ENOBUFS);
190            return -1;
191    }    }
192      newconn->callback = event_callback;
193      sock = get_socket(newsock);
194      
195      sys_sem_wait(socksem);
196      sock->rcvevent += -1 - newconn->socket;
197      newconn->socket = newsock;
198      sys_sem_signal(socksem);
199    
200    #if SOCKETS_DEBUG
201      DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock));
202      ip_addr_debug_print(&naddr);
203      DEBUGF(SOCKETS_DEBUG, (" port=%u\n", port));
204    #endif
205      
206      sock_set_errno(sock, 0);
207    return newsock;    return newsock;
208  }  }
209  /*-----------------------------------------------------------------------------------*/  /*-----------------------------------------------------------------------------------*/
# Line 116  int Line 211  int
211  lwip_bind(int s, struct sockaddr *name, int namelen)  lwip_bind(int s, struct sockaddr *name, int namelen)
212  {  {
213    struct lwip_socket *sock;    struct lwip_socket *sock;
214    struct ip_addr remote_addr;    struct ip_addr local_addr;
215    u16_t remote_port;    u16_t local_port;
216    err_t err;    err_t err;
217        
218    sock = get_socket(s);    sock = get_socket(s);
219    if(sock == NULL) {    if(!sock) {
220      return -1;      return -1;
221    }    }
222        
223    remote_addr.addr = ((struct sockaddr_in *)name)->sin_addr.s_addr;    local_addr.addr = ((struct sockaddr_in *)name)->sin_addr.s_addr;
224    remote_port = ((struct sockaddr_in *)name)->sin_port;    local_port = ((struct sockaddr_in *)name)->sin_port;
225    
226    #if SOCKETS_DEBUG
227      DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s));
228      ip_addr_debug_print(&local_addr);
229      DEBUGF(SOCKETS_DEBUG, (" port=%u)\n", ntohs(local_port)));
230    #endif
231        
232    err = netconn_bind(sock->conn, &remote_addr, ntohs(remote_port));    err = netconn_bind(sock->conn, &local_addr, ntohs(local_port));
233    
234    if(err != ERR_OK) {    if(err != ERR_OK) {
235      /* errno = ... */          DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err));
236            sock_set_errno(sock, err_to_errno(err));
237      return -1;      return -1;
238    }    }
239    
240      DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) succeeded\n", s));
241      sock_set_errno(sock, 0);
242    return 0;    return 0;
243  }  }
244  /*-----------------------------------------------------------------------------------*/  /*-----------------------------------------------------------------------------------*/
# Line 143  lwip_close(int s) Line 247  lwip_close(int s)
247  {  {
248    struct lwip_socket *sock;    struct lwip_socket *sock;
249        
250    DEBUGF(SOCKETS_DEBUG, ("close: socket %d\n", s));    DEBUGF(SOCKETS_DEBUG, ("lwip_close(%d)\n", s));
251      if (!socksem)
252          socksem = sys_sem_new(1);
253    
254      /* We cannot allow multiple closes of the same socket. */
255      sys_sem_wait(socksem);
256      
257    sock = get_socket(s);    sock = get_socket(s);
258    if(sock == NULL) {    if(!sock) {
259      return -1;        sys_sem_signal(socksem);
260          return -1;
261    }    }
262        
     
263    netconn_delete(sock->conn);    netconn_delete(sock->conn);
264    if(sock->lastdata != NULL) {    if(sock->lastdata) {
265      netbuf_delete(sock->lastdata);      netbuf_delete(sock->lastdata);
266    }    }
267    sock->lastdata = NULL;    sock->lastdata = NULL;
268    sock->lastoffset = 0;    sock->lastoffset = 0;
269    sock->conn = NULL;    sock->conn = NULL;
270      sys_sem_signal(socksem);
271      sock_set_errno(sock, 0);
272    return 0;    return 0;
273  }  }
274  /*-----------------------------------------------------------------------------------*/  /*-----------------------------------------------------------------------------------*/
# Line 164  int Line 276  int
276  lwip_connect(int s, struct sockaddr *name, int namelen)  lwip_connect(int s, struct sockaddr *name, int namelen)
277  {  {
278    struct lwip_socket *sock;    struct lwip_socket *sock;
   struct ip_addr remote_addr;  
   u16_t remote_port;  
279    err_t err;    err_t err;
280    
281    sock = get_socket(s);    sock = get_socket(s);
282    if(sock == NULL) {    if(!sock) {
283      return -1;      return -1;
284    }    }
285      
286    if (((struct sockaddr_in *)name)->sin_family == AF_UNSPEC) {    if (((struct sockaddr_in *)name)->sin_family == AF_UNSPEC) {
287      err = netconn_disconnect(sock->conn);          DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, AF_UNSPEC)\n", s));
288    } else {            err = netconn_disconnect(sock->conn);
289      remote_addr.addr = ((struct sockaddr_in *)name)->sin_addr.s_addr;    } else {
290      remote_port = ((struct sockaddr_in *)name)->sin_port;          struct ip_addr remote_addr;
291      err = netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));          u16_t remote_port;
292    }    
293            remote_addr.addr = ((struct sockaddr_in *)name)->sin_addr.s_addr;
294            remote_port = ((struct sockaddr_in *)name)->sin_port;
295    
296    #if SOCKETS_DEBUG
297            DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s));
298            ip_addr_debug_print(&remote_addr);
299            DEBUGF(SOCKETS_DEBUG, (" port=%u)\n", ntohs(remote_port)));
300    #endif
301            
302            err = netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));
303       }
304    
305    if(err != ERR_OK) {    if(err != ERR_OK) {
306      /* errno = ... */          DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) failed, err=%d\n", s, err));
307            sock_set_errno(sock, err_to_errno(err));
308      return -1;      return -1;
309    }    }
310    
311      DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) succeeded\n", s));
312      sock_set_errno(sock, 0);
313    return 0;    return 0;
314  }  }
315  /*-----------------------------------------------------------------------------------*/  /*-----------------------------------------------------------------------------------*/
# Line 195  lwip_listen(int s, int backlog) Line 319  lwip_listen(int s, int backlog)
319    struct lwip_socket *sock;        struct lwip_socket *sock;    
320    err_t err;    err_t err;
321        
322      DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog));
323    sock = get_socket(s);    sock = get_socket(s);
324    if(sock == NULL) {    if(!sock) {
325      return -1;      return -1;
326    }    }
327    
328    err = netconn_listen(sock->conn);    err = netconn_listen(sock->conn);
329    
330    if(err != ERR_OK) {    if(err != ERR_OK) {
331      /* errno = ... */          DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d) failed, err=%d\n", s, err));
332            sock_set_errno(sock, err_to_errno(err));
333      return -1;      return -1;
334    }    }
335    
336      sock_set_errno(sock, 0);
337    return 0;    return 0;
338  }  }
339  /*-----------------------------------------------------------------------------------*/  /*-----------------------------------------------------------------------------------*/
# Line 221  lwip_recvfrom(int s, void *mem, int len, Line 348  lwip_recvfrom(int s, void *mem, int len,
348    u16_t port;    u16_t port;
349    
350        
351      DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %d, 0x%x, ..)\n", s, mem, len, flags));
352    sock = get_socket(s);    sock = get_socket(s);
353    if(sock == NULL) {    if(!sock) {
354      return -1;      return -1;
355    }    }
356    
357    /* Check if there is data left from the last recv operation. */    /* Check if there is data left from the last recv operation. */
358    if(sock->lastdata != NULL) {        if(sock->lastdata) {    
359      buf = sock->lastdata;      buf = sock->lastdata;
360    } else {    } else {
361        /* If this is non-blocking call, then check first */
362        if (((flags & MSG_DONTWAIT) || (sock->flags & O_NONBLOCK))
363            && !sock->rcvevent)
364        {
365          DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s));
366          sock_set_errno(sock, EWOULDBLOCK);
367          return -1;
368        }
369          
370      /* No data was left from the previous operation, so we try to get      /* No data was left from the previous operation, so we try to get
371         some from the network. */         some from the network. */
372      buf = netconn_recv(sock->conn);      buf = netconn_recv(sock->conn);
373            
374      if(buf == NULL) {      if(!buf) {
375        /* We should really do some error checking here. */        /* We should really do some error checking here. */
376          DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL!\n", s));
377          sock_set_errno(sock, 0);
378        return 0;        return 0;
379      }      }
380    }    }
# Line 255  lwip_recvfrom(int s, void *mem, int len, Line 394  lwip_recvfrom(int s, void *mem, int len,
394    netbuf_copy_partial(buf, mem, copylen, sock->lastoffset);    netbuf_copy_partial(buf, mem, copylen, sock->lastoffset);
395    
396    /* Check to see from where the data was. */    /* Check to see from where the data was. */
397    if(from != NULL && fromlen != NULL) {    if(from && fromlen) {
398        struct sockaddr_in sin;
399    
400        addr = netbuf_fromaddr(buf);
401        port = netbuf_fromport(buf);
402    
403        memset(&sin, 0, sizeof(sin));
404        sin.sin_len = sizeof(sin);
405        sin.sin_family = AF_INET;
406        sin.sin_port = htons(port);
407        sin.sin_addr.s_addr = addr->addr;
408    
409        if(*fromlen > sizeof(sin))
410          *fromlen = sizeof(sin);
411    
412        memcpy(from, &sin, *fromlen);
413    
414    #if SOCKETS_DEBUG
415        DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
416        ip_addr_debug_print(addr);
417        DEBUGF(SOCKETS_DEBUG, (" port=%u len=%u\n", port, copylen));
418    #endif
419      } else {
420    #if SOCKETS_DEBUG > 0
421      addr = netbuf_fromaddr(buf);      addr = netbuf_fromaddr(buf);
422      port = netbuf_fromport(buf);        port = netbuf_fromport(buf);  
423      ((struct sockaddr_in *)from)->sin_addr.s_addr = addr->addr;  
424      ((struct sockaddr_in *)from)->sin_port = port;      DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
425      ((struct sockaddr_in *)from)->sin_family = AF_INET;      ip_addr_debug_print(addr);
426      *fromlen = sizeof(struct sockaddr_in);      DEBUGF(SOCKETS_DEBUG, (" port=%u len=%u\n", port, copylen));
427    #endif
428    
429    }    }
430    
431    /* If this is a TCP socket, check if there is data left in the    /* If this is a TCP socket, check if there is data left in the
# Line 277  lwip_recvfrom(int s, void *mem, int len, Line 441  lwip_recvfrom(int s, void *mem, int len,
441    }    }
442    
443    
444      sock_set_errno(sock, 0);
445    return copylen;    return copylen;
446  }  }
447  /*-----------------------------------------------------------------------------------*/  /*-----------------------------------------------------------------------------------*/
448  int  int
449  lwip_read(int s, void *mem, int len)  lwip_read(int s, void *mem, int len)
450  {  {
451    return lwip_recv(s, mem, len, 0);    return lwip_recvfrom(s, mem, len, 0, NULL, NULL);
452  }  }
453  /*-----------------------------------------------------------------------------------*/  /*-----------------------------------------------------------------------------------*/
454  int  int
# Line 299  lwip_send(int s, void *data, int size, u Line 464  lwip_send(int s, void *data, int size, u
464    struct netbuf *buf;    struct netbuf *buf;
465    err_t err;    err_t err;
466    
467    DEBUGF(SOCKETS_DEBUG, ("send: socket %d, size %d\n", s, size));    DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d, data=%p, size=%d, flags=0x%x)\n", s, data, size, flags));
468    
469    sock = get_socket(s);    sock = get_socket(s);
470    if(sock == NULL) {    if(!sock) {
471      return -1;      return -1;
472    }      }  
473        
# Line 311  lwip_send(int s, void *data, int size, u Line 476  lwip_send(int s, void *data, int size, u
476      /* create a buffer */      /* create a buffer */
477      buf = netbuf_new();      buf = netbuf_new();
478    
479      if(buf == NULL) {      if(!buf) {
480        /* errno = ENOBUFS; */            DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) ENOBUFS\n", s));
481              sock_set_errno(sock, ENOBUFS);
482        return -1;        return -1;
483      }      }
484            
# Line 334  lwip_send(int s, void *data, int size, u Line 500  lwip_send(int s, void *data, int size, u
500      break;      break;
501    }    }
502    if(err != ERR_OK) {    if(err != ERR_OK) {
503      /* errno = ... */          DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d\n", s, err));
504            sock_set_errno(sock, err_to_errno(err));
505      return -1;          return -1;    
506    }    }
507        
508      DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) ok size=%d\n", s, size));
509      sock_set_errno(sock, 0);
510    return size;    return size;
511  }  }
512  /*-----------------------------------------------------------------------------------*/  /*-----------------------------------------------------------------------------------*/
# Line 351  lwip_sendto(int s, void *data, int size, Line 520  lwip_sendto(int s, void *data, int size,
520    int ret,connected;    int ret,connected;
521    
522    sock = get_socket(s);    sock = get_socket(s);
523    if(sock == NULL) {    if(!sock) {
524      return -1;      return -1;
525    }    }
526        
# Line 360  lwip_sendto(int s, void *data, int size, Line 529  lwip_sendto(int s, void *data, int size,
529        
530    remote_addr.addr = ((struct sockaddr_in *)to)->sin_addr.s_addr;    remote_addr.addr = ((struct sockaddr_in *)to)->sin_addr.s_addr;
531    remote_port = ((struct sockaddr_in *)to)->sin_port;    remote_port = ((struct sockaddr_in *)to)->sin_port;
532    
533    #if SOCKETS_DEBUG
534      DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, size=%d, flags=0x%x to=", s, data, size, flags));
535      ip_addr_debug_print(&remote_addr);
536      DEBUGF(SOCKETS_DEBUG, (" port=%u\n", ntohs(remote_port)));
537    #endif
538      
539    netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));    netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));
540        
541    ret = lwip_send(s, data, size, flags);    ret = lwip_send(s, data, size, flags);
542    
543    /* reset the remote address and port number    /* reset the remote address and port number
544       of the connection */       of the connection */
545    if (connected)    if(connected)
546      netconn_connect(sock->conn, &addr, port);          netconn_connect(sock->conn, &addr, port);
547    else    else
548      netconn_disconnect(sock->conn);                netconn_disconnect(sock->conn);
549    return ret;    return ret;
550  }  }
551  /*-----------------------------------------------------------------------------------*/  /*-----------------------------------------------------------------------------------*/
# Line 382  lwip_socket(int domain, int type, int pr Line 558  lwip_socket(int domain, int type, int pr
558    /* create a netconn */    /* create a netconn */
559    switch(type) {    switch(type) {
560    case SOCK_DGRAM:    case SOCK_DGRAM:
561      conn = netconn_new(NETCONN_UDP);      conn = netconn_new_with_callback(NETCONN_UDP, event_callback);
562            DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ", domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
563      break;      break;
564    case SOCK_STREAM:    case SOCK_STREAM:
565      conn = netconn_new(NETCONN_TCP);      conn = netconn_new_with_callback(NETCONN_TCP, event_callback);
566            DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_STREAM, %d) = ", domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
567      break;      break;
568    default:    default:
569      /* errno = ... */          DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%d, %d/UNKNOWN, %d) = -1\n", domain, type, protocol));
570            set_errno(EINVAL);
571      return -1;      return -1;
572    }    }
573    
574    if(conn == NULL) {    if(!conn) {
575      DEBUGF(SOCKETS_DEBUG, ("socket: could not create netconn.\n"));      DEBUGF(SOCKETS_DEBUG, ("-1 / ENOBUFS (could not create netconn)\n"));
576      /* errno = ENOBUFS; */          set_errno(ENOBUFS);
577      return -1;      return -1;
578    }    }
579    
580    i = alloc_socket(conn);    i = alloc_socket(conn);
581    
582    if(i == -1) {    if(i == -1) {
     /* errno = ENOBUFS; */  
583      netconn_delete(conn);      netconn_delete(conn);
584            set_errno(ENOBUFS);
585            return -1;
586    }    }
587      conn->socket = i;
588      DEBUGF(SOCKETS_DEBUG, ("%d\n", i));
589      set_errno(0);
590    return i;    return i;
591  }  }
592  /*-----------------------------------------------------------------------------------*/  /*-----------------------------------------------------------------------------------*/
# Line 412  lwip_write(int s, void *data, int size) Line 595  lwip_write(int s, void *data, int size)
595  {  {
596     return lwip_send(s, data, size, 0);     return lwip_send(s, data, size, 0);
597  }  }
598    
599    /*-----------------------------------------------------------------------------------*/
600    static int
601    lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset)
602    {
603        int i, nready = 0;
604        fd_set lreadset, lwriteset, lexceptset;
605        struct lwip_socket *p_sock;
606    
607        FD_ZERO(&lreadset);
608        FD_ZERO(&lwriteset);
609        FD_ZERO(&lexceptset);
610        
611        /* Go through each socket in each list to count number of sockets which
612           currently match */
613        for(i = 0; i < maxfdp1; i++)
614        {
615            if(FD_ISSET(i, readset))
616            {
617                /* See if netconn of this socket is ready for read */
618                p_sock = get_socket(i);
619                if (p_sock && (p_sock->lastdata || p_sock->rcvevent))
620                {
621                    FD_SET(i, &lreadset);
622                            DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i));
623                    nready++;
624                }
625            }
626            if(FD_ISSET(i, writeset))
627            {
628                /* See if netconn of this socket is ready for write */
629                p_sock = get_socket(i);
630                if (p_sock && p_sock->sendevent)
631                {
632                    FD_SET(i, &lwriteset);
633                            DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for writing\n", i));
634                    nready++;
635                }
636            }
637        }
638        *readset = lreadset;
639        *writeset = lwriteset;
640        FD_ZERO(exceptset);
641    
642        return nready;
643    }
644    
645    
646    /*-----------------------------------------------------------------------------------*/
647    int
648    lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
649                   const struct timeval *timeout)
650    {
651        int i;
652        int nready;
653        fd_set lreadset, lwriteset, lexceptset;
654        u32_t msectimeout;
655        struct lwip_select_cb select_cb;
656        struct lwip_select_cb *p_selcb;
657    
658            DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%ld tvusec=%ld)\n", maxfdp1, (void *)readset, (void *) writeset, (void *) exceptset, timeout ? timeout->tv_sec : -1L, timeout ? timeout->tv_usec : -1L));
659        select_cb.next = 0;
660        select_cb.readset = readset;
661        select_cb.writeset = writeset;
662        select_cb.exceptset = exceptset;
663        select_cb.sem_signalled = 0;
664        
665        /* Protect ourselves searching through the list */
666        if (!selectsem)
667            selectsem = sys_sem_new(1);
668        sys_sem_wait(selectsem);
669        
670        if (readset)
671            lreadset = *readset;
672        else
673            FD_ZERO(&lreadset);
674        if (writeset)
675            lwriteset = *writeset;
676        else
677            FD_ZERO(&lwriteset);
678        if (exceptset)
679            lexceptset = *exceptset;
680        else
681            FD_ZERO(&lexceptset);
682        
683        /* Go through each socket in each list to count number of sockets which
684           currently match */
685        nready = lwip_selscan(maxfdp1, &lreadset, &lwriteset, &lexceptset);
686        
687        /* If we don't have any current events, then suspend if we are supposed to */
688        if (!nready)
689        {
690            if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
691            {
692                sys_sem_signal(socksem);
693                if (readset)
694                    FD_ZERO(readset);
695                if (writeset)
696                    FD_ZERO(writeset);
697                if (exceptset)
698                    FD_ZERO(exceptset);
699    
700                            DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n"));
701                            set_errno(0);
702                return 0;
703            }
704            
705            /* add our semaphore to list */
706            /* We don't actually need any dynamic memory. Our entry on the
707             * list is only valid while we are in this function, so it's ok
708             * to use local variables */
709    
710            select_cb.sem = sys_sem_new(0);
711            /* Note that we are still protected */
712            /* Put this select_cb on top of list */
713            select_cb.next = select_cb_list;
714            select_cb_list = &select_cb;
715    
716            /* Now we can safely unprotect */
717            sys_sem_signal(selectsem);
718    
719            /* Now just wait to be woken */
720            if (timeout == 0)
721                /* Wait forever */
722                msectimeout = 0;
723            else
724                msectimeout =  ((timeout->tv_sec * 1000) + (timeout->tv_usec /1000));
725    
726            i = sys_sem_wait_timeout(select_cb.sem, msectimeout);
727    
728            /* Take us off the list */
729            sys_sem_wait(selectsem);
730            if (select_cb_list == &select_cb)
731                select_cb_list = select_cb.next;
732            else
733                for (p_selcb = select_cb_list; p_selcb; p_selcb = p_selcb->next)
734                    if (p_selcb->next == &select_cb)
735                    {
736                        p_selcb->next = select_cb.next;
737                        break;
738                    }
739            
740            sys_sem_signal(selectsem);
741            
742            sys_sem_free(select_cb.sem);
743            if (i == 0)             /* Timeout */
744            {
745                if (readset)
746                    FD_ZERO(readset);
747                if (writeset)
748                    FD_ZERO(writeset);
749                if (exceptset)
750                    FD_ZERO(exceptset);
751                            DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n"));
752                            set_errno(0);
753                return 0;
754            }
755    
756            if (readset)
757                lreadset = *readset;
758            else
759                FD_ZERO(&lreadset);
760            if (writeset)
761                lwriteset = *writeset;
762            else
763                FD_ZERO(&lwriteset);
764            if (exceptset)
765                lexceptset = *exceptset;
766            else
767                FD_ZERO(&lexceptset);
768    
769            /* See what's set */
770            nready = lwip_selscan(maxfdp1, &lreadset, &lwriteset, &lexceptset);
771        }
772        else
773            sys_sem_signal(selectsem);
774        
775        if (readset)
776            *readset = lreadset;
777        if (writeset)
778            *writeset = lwriteset;
779        if (exceptset)
780            *exceptset = lexceptset;
781            DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready));
782            set_errno(0);
783        return nready;
784    }
785    
786  /*-----------------------------------------------------------------------------------*/  /*-----------------------------------------------------------------------------------*/
787    static void
788    event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
789    {
790        int s;
791        struct lwip_socket *sock;
792        struct lwip_select_cb *scb;
793        
794        /* Get socket */
795        if (conn)
796        {
797            s = conn->socket;
798            if (s < 0)
799            {
800                /* Data comes in right away after an accept, even though
801                 * the server task might not have created a new socket yet.
802                 * Just count down (or up) if that's the case and we
803                 * will use the data later. Note that only receive events
804                 * can happen before the new socket is set up. */
805                if (evt == NETCONN_EVT_RCVPLUS)
806                    conn->socket--;
807                return;
808            }
809            
810            sock = get_socket(s);
811            if (!sock)
812                return;
813        }
814        else
815            return;
816    
817        if (!selectsem)
818            selectsem = sys_sem_new(1);
819        
820        sys_sem_wait(selectsem);
821        /* Set event as required */
822        switch (evt)
823        {
824          case NETCONN_EVT_RCVPLUS:
825            sock->rcvevent++;
826            break;
827          case NETCONN_EVT_RCVMINUS:
828            sock->rcvevent--;
829            break;
830          case NETCONN_EVT_SENDPLUS:
831            sock->sendevent = 1;
832            break;
833          case NETCONN_EVT_SENDMINUS:
834            sock->sendevent = 0;
835            break;
836        }
837        sys_sem_signal(selectsem);
838        
839        /* Now decide if anyone is waiting for this socket */
840        /* NOTE: This code is written this way to protect the select link list
841           but to avoid a deadlock situation by releasing socksem before
842           signalling for the select. This means we need to go through the list
843           multiple times ONLY IF a select was actually waiting. We go through
844           the list the number of waiting select calls + 1. This list is
845           expected to be small. */
846        while (1)
847        {
848            sys_sem_wait(selectsem);
849            for (scb = select_cb_list; scb; scb = scb->next)
850            {
851                if (scb->sem_signalled == 0)
852                {
853                    /* Test this select call for our socket */
854                    if (scb->readset && FD_ISSET(s, scb->readset))
855                        if (sock->rcvevent)
856                            break;
857                    if (scb->writeset && FD_ISSET(s, scb->writeset))
858                        if (sock->sendevent)
859                            break;
860                }
861            }
862            if (scb)
863            {
864                scb->sem_signalled = 1;
865                sys_sem_signal(selectsem);
866                sys_sem_signal(scb->sem);
867            } else {
868                sys_sem_signal(selectsem);
869                break;
870            }
871        }
872        
873    }
874    
875    /*-----------------------------------------------------------------------------------*/
876    
877    
878    int lwip_shutdown(int s, int how)
879    {
880            DEBUGF(SOCKETS_DEBUG, ("lwip_shutdown(%d, how=%d)\n", s, how));
881        return lwip_close(s); /* XXX temporary hack until proper implementation */
882    }
883    
884    int lwip_getpeername (int s, struct sockaddr *name, int *namelen)
885    {
886      struct lwip_socket *sock;
887      struct sockaddr_in sin;
888      struct ip_addr naddr;
889    
890      sock = get_socket(s);
891      if(!sock) {
892        return -1;
893      }
894      
895      memset(&sin, 0, sizeof(sin));
896      sin.sin_len = sizeof(sin);
897      sin.sin_family = AF_INET;
898    
899      /* get the IP address and port of the remote host */
900      netconn_peer(sock->conn, &naddr, &sin.sin_port);
901      
902    #if SOCKETS_DEBUG
903      DEBUGF(SOCKETS_DEBUG, ("lwip_getpeername(%d, addr=", s));
904      ip_addr_debug_print(&naddr);
905      DEBUGF(SOCKETS_DEBUG, (" port=%d)\n", sin.sin_port));
906    #endif
907      
908      sin.sin_port = htons(sin.sin_port);
909      sin.sin_addr.s_addr = naddr.addr;
910    
911      if(*namelen > sizeof(sin))
912          *namelen = sizeof(sin);
913    
914      memcpy(name, &sin, *namelen);
915      sock_set_errno(sock, 0);
916      return 0;
917    }
918    
919    int lwip_getsockname (int s, struct sockaddr *name, int *namelen)
920    {
921      struct lwip_socket *sock;
922      struct sockaddr_in sin;
923      struct ip_addr *naddr;
924    
925      sock = get_socket(s);
926      if(!sock) {
927        return -1;
928      }
929      
930      memset(&sin, 0, sizeof(sin));
931      sin.sin_len = sizeof(sin);
932      sin.sin_family = AF_INET;
933    
934      /* get the IP address and port of the remote host */
935      netconn_addr(sock->conn, &naddr, &sin.sin_port);
936    
937    #if SOCKETS_DEBUG
938      DEBUGF(SOCKETS_DEBUG, ("lwip_getsockname(%d, addr=", s));
939      ip_addr_debug_print(naddr);
940      DEBUGF(SOCKETS_DEBUG, (" port=%d)\n", sin.sin_port));
941    #endif
942      
943      sin.sin_port = htons(sin.sin_port);
944      sin.sin_addr.s_addr = naddr->addr;
945    
946      if(*namelen > sizeof(sin))
947          *namelen = sizeof(sin);
948    
949      memcpy(name, &sin, *namelen);
950      sock_set_errno(sock, 0);
951      return 0;
952    }
953    
954    int lwip_getsockopt (int s, int level, int optname, char *optval, int *optlen)
955    {
956            int err = ENOSYS;
957            struct lwip_socket *sock = get_socket(s);
958    
959            if(!sock) {
960                    return -1;
961            }
962    
963            if(level == SOL_SOCKET) {
964                    switch(optname) {
965                            case SO_ERROR:
966                                    if(!optval || !optlen || (*optlen != sizeof(int))) {
967                                            err = EINVAL;
968                                            break;
969                                    }
970                                    *(int *)optval = sock->err;
971                                    sock->err = 0;
972                                    DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", s, *(int *)optval));
973                                    err = 0;
974                                    break;
975                            default:
976                                    DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", s, optname));
977                                    break;
978                    }
979            } else {
980                    DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", s, level, optname));
981            }
982            sock_set_errno(sock, err);
983            return err ? -1 : 0;
984    }
985    
986    int lwip_setsockopt (int s, int level, int optname, const char *optval, int optlen)
987    {
988            struct lwip_socket *sock = get_socket(s);
989            int err = ENOSYS;
990    
991            if(!sock) {
992                    return -1;
993            }
994    
995            if(level == SOL_SOCKET) {
996                    switch(optname) {
997                            case SO_REUSEADDR:
998                                    DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, SO_REUSEADDR, ..)\n", s));
999                                    /* XXX just pretend we support this for now */
1000                                    err = 0;
1001                                    break;
1002                            default:
1003                                    DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", s, optname));
1004                                    break;
1005                    }
1006            } else {
1007                    DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", s, level, optname));
1008            }
1009    
1010            sock_set_errno(sock, err);
1011            return err ? -1 : 0;
1012    }
1013    
1014    int lwip_ioctl(int s, long cmd, void *argp)
1015    {
1016            struct lwip_socket *sock = get_socket(s);
1017    
1018            if(!sock) {
1019                    return -1;
1020            }
1021    
1022            switch(cmd) {
1023            case FIONREAD:
1024                    if(!argp) {
1025                            sock_set_errno(sock, EINVAL);
1026                            return -1;
1027                    }
1028    
1029                    *((u16_t*)argp) = sock->conn->recv_avail;
1030    
1031                    DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %u\n", s, argp, *((u16_t*)argp)));
1032                    sock_set_errno(sock, 0);
1033                    return 0;
1034    
1035            case FIONBIO:
1036                    if(argp && *(u32_t*)argp)
1037                            sock->flags |= O_NONBLOCK;
1038                    else
1039                            sock->flags &= ~O_NONBLOCK;
1040                    DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, !!(sock->flags & O_NONBLOCK)));
1041                    sock_set_errno(sock, 0);
1042                    return 0;
1043    
1044            default:
1045                    DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp));
1046                    sock_set_errno(sock, ENOSYS); /* not yet implemented */
1047                    return -1;
1048            }
1049    }
1050    

Legend:
Removed from v.1.7  
changed lines
  Added in v.1.8

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26