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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [lwIP_Demo_Rowley_ARM7/] [lwip-1.1.0/] [src/] [api/] [sockets.c] - Blame information for rev 620

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

Line No. Rev Author Line
1 583 jeremybenn
/*
2
 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without modification,
6
 * are permitted provided that the following conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 *    this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
11
 *    this list of conditions and the following disclaimer in the documentation
12
 *    and/or other materials provided with the distribution.
13
 * 3. The name of the author may not be used to endorse or promote products
14
 *    derived from this software without specific prior written permission.
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19
 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
21
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
25
 * OF SUCH DAMAGE.
26
 *
27
 * This file is part of the lwIP TCP/IP stack.
28
 *
29
 * 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 <string.h>
36
#include <errno.h>
37
 
38
#include "lwip/opt.h"
39
#include "lwip/api.h"
40
#include "lwip/arch.h"
41
#include "lwip/sys.h"
42
 
43
#include "lwip/sockets.h"
44
 
45
#define NUM_SOCKETS MEMP_NUM_NETCONN
46
 
47
struct lwip_socket {
48
  struct netconn *conn;
49
  struct netbuf *lastdata;
50
  u16_t lastoffset;
51
  u16_t rcvevent;
52
  u16_t sendevent;
53
  u16_t  flags;
54
  int err;
55
};
56
 
57
struct lwip_select_cb
58
{
59
    struct lwip_select_cb *next;
60
    fd_set *readset;
61
    fd_set *writeset;
62
    fd_set *exceptset;
63
    int sem_signalled;
64
    sys_sem_t sem;
65
};
66
 
67
static struct lwip_socket sockets[NUM_SOCKETS];
68
static struct lwip_select_cb *select_cb_list = 0;
69
 
70
static sys_sem_t socksem = 0;
71
static sys_sem_t selectsem = 0;
72
 
73
static void
74
event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len);
75
 
76
static int err_to_errno_table[11] = {
77
    0,      /* ERR_OK    0      No error, everything OK. */
78
    ENOMEM,    /* ERR_MEM  -1      Out of memory error.     */
79
    ENOBUFS,    /* ERR_BUF  -2      Buffer error.            */
80
    ECONNABORTED,  /* ERR_ABRT -3      Connection aborted.      */
81
    ECONNRESET,    /* ERR_RST  -4      Connection reset.        */
82
    ESHUTDOWN,    /* ERR_CLSD -5      Connection closed.       */
83
    ENOTCONN,    /* ERR_CONN -6      Not connected.           */
84
    EINVAL,    /* ERR_VAL  -7      Illegal value.           */
85
    EIO,    /* ERR_ARG  -8      Illegal argument.        */
86
    EHOSTUNREACH,  /* ERR_RTE  -9      Routing problem.         */
87
    EADDRINUSE    /* ERR_USE  -10     Address in use.          */
88
};
89
 
90
#define err_to_errno(err) \
91
  ((err) < (sizeof(err_to_errno_table)/sizeof(int))) ? \
92
    err_to_errno_table[-(err)] : EIO
93
 
94
#ifdef ERRNO
95
#define set_errno(err) errno = (err)
96
#else
97
#define set_errno(err)
98
#endif
99
 
100
#define sock_set_errno(sk, e) do { \
101
      sk->err = (e); \
102
      set_errno(sk->err); \
103
} while (0)
104
 
105
 
106
static struct lwip_socket *
107
get_socket(int s)
108
{
109
  struct lwip_socket *sock;
110
 
111
  if ((s < 0) || (s > NUM_SOCKETS)) {
112
    LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): invalid\n", s));
113
    set_errno(EBADF);
114
    return NULL;
115
  }
116
 
117
  sock = &sockets[s];
118
 
119
  if (!sock->conn) {
120
    LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): not active\n", s));
121
    set_errno(EBADF);
122
    return NULL;
123
  }
124
 
125
  return sock;
126
}
127
 
128
static int
129
alloc_socket(struct netconn *newconn)
130
{
131
  int i;
132
 
133
  if (!socksem)
134
      socksem = sys_sem_new(1);
135
 
136
  /* Protect socket array */
137
  sys_sem_wait(socksem);
138
 
139
  /* allocate a new socket identifier */
140
  for(i = 0; i < NUM_SOCKETS; ++i) {
141
    if (!sockets[i].conn) {
142
      sockets[i].conn = newconn;
143
      sockets[i].lastdata = NULL;
144
      sockets[i].lastoffset = 0;
145
      sockets[i].rcvevent = 0;
146
      sockets[i].sendevent = 1; /* TCP send buf is empty */
147
      sockets[i].flags = 0;
148
      sockets[i].err = 0;
149
      sys_sem_signal(socksem);
150
      return i;
151
    }
152
  }
153
  sys_sem_signal(socksem);
154
  return -1;
155
}
156
 
157
int
158
lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
159
{
160
  struct lwip_socket *sock;
161
  struct netconn *newconn;
162
  struct ip_addr naddr;
163
  u16_t port;
164
  int newsock;
165
  struct sockaddr_in sin;
166
 
167
  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s));
168
  sock = get_socket(s);
169
  if (!sock) {
170
    set_errno(EBADF);
171
    return -1;
172
  }
173
 
174
  newconn = netconn_accept(sock->conn);
175
 
176
  /* get the IP address and port of the remote host */
177
  netconn_peer(newconn, &naddr, &port);
178
 
179
  memset(&sin, 0, sizeof(sin));
180
  sin.sin_len = sizeof(sin);
181
  sin.sin_family = AF_INET;
182
  sin.sin_port = htons(port);
183
  sin.sin_addr.s_addr = naddr.addr;
184
 
185
  if (*addrlen > sizeof(sin))
186
      *addrlen = sizeof(sin);
187
 
188
  memcpy(addr, &sin, *addrlen);
189
 
190
  newsock = alloc_socket(newconn);
191
  if (newsock == -1) {
192
    netconn_delete(newconn);
193
  sock_set_errno(sock, ENOBUFS);
194
  return -1;
195
  }
196
  newconn->callback = event_callback;
197
  sock = get_socket(newsock);
198
 
199
  sys_sem_wait(socksem);
200
  sock->rcvevent += -1 - newconn->socket;
201
  newconn->socket = newsock;
202
  sys_sem_signal(socksem);
203
 
204
  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock));
205
  ip_addr_debug_print(SOCKETS_DEBUG, &naddr);
206
  LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u\n", port));
207
 
208
  sock_set_errno(sock, 0);
209
  return newsock;
210
}
211
 
212
int
213
lwip_bind(int s, struct sockaddr *name, socklen_t namelen)
214
{
215
  struct lwip_socket *sock;
216
  struct ip_addr local_addr;
217
  u16_t local_port;
218
  err_t err;
219
 
220
  sock = get_socket(s);
221
  if (!sock) {
222
    set_errno(EBADF);
223
    return -1;
224
  }
225
 
226
  local_addr.addr = ((struct sockaddr_in *)name)->sin_addr.s_addr;
227
  local_port = ((struct sockaddr_in *)name)->sin_port;
228
 
229
  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s));
230
  ip_addr_debug_print(SOCKETS_DEBUG, &local_addr);
231
  LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u)\n", ntohs(local_port)));
232
 
233
  err = netconn_bind(sock->conn, &local_addr, ntohs(local_port));
234
 
235
  if (err != ERR_OK) {
236
    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err));
237
    sock_set_errno(sock, err_to_errno(err));
238
    return -1;
239
  }
240
 
241
  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) succeeded\n", s));
242
  sock_set_errno(sock, 0);
243
  return 0;
244
}
245
 
246
int
247
lwip_close(int s)
248
{
249
  struct lwip_socket *sock;
250
 
251
  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_close(%d)\n", s));
252
  if (!socksem)
253
      socksem = sys_sem_new(1);
254
 
255
  /* We cannot allow multiple closes of the same socket. */
256
  sys_sem_wait(socksem);
257
 
258
  sock = get_socket(s);
259
  if (!sock) {
260
      sys_sem_signal(socksem);
261
      set_errno(EBADF);
262
      return -1;
263
  }
264
 
265
  netconn_delete(sock->conn);
266
  if (sock->lastdata) {
267
    netbuf_delete(sock->lastdata);
268
  }
269
  sock->lastdata = NULL;
270
  sock->lastoffset = 0;
271
  sock->conn = NULL;
272
  sys_sem_signal(socksem);
273
  sock_set_errno(sock, 0);
274
  return 0;
275
}
276
 
277
int
278
lwip_connect(int s, struct sockaddr *name, socklen_t namelen)
279
{
280
  struct lwip_socket *sock;
281
  err_t err;
282
 
283
  sock = get_socket(s);
284
  if (!sock) {
285
    set_errno(EBADF);
286
    return -1;
287
  }
288
 
289
  if (((struct sockaddr_in *)name)->sin_family == AF_UNSPEC) {
290
    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, AF_UNSPEC)\n", s));
291
    err = netconn_disconnect(sock->conn);
292
  } else {
293
    struct ip_addr remote_addr;
294
    u16_t remote_port;
295
 
296
    remote_addr.addr = ((struct sockaddr_in *)name)->sin_addr.s_addr;
297
    remote_port = ((struct sockaddr_in *)name)->sin_port;
298
 
299
    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s));
300
    ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr);
301
    LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u)\n", ntohs(remote_port)));
302
 
303
    err = netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));
304
   }
305
 
306
  if (err != ERR_OK) {
307
    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) failed, err=%d\n", s, err));
308
    sock_set_errno(sock, err_to_errno(err));
309
    return -1;
310
  }
311
 
312
  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) succeeded\n", s));
313
  sock_set_errno(sock, 0);
314
  return 0;
315
}
316
 
317
int
318
lwip_listen(int s, int backlog)
319
{
320
  struct lwip_socket *sock;
321
  err_t err;
322
 
323
  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog));
324
  sock = get_socket(s);
325
  if (!sock) {
326
    set_errno(EBADF);
327
    return -1;
328
  }
329
 
330
  err = netconn_listen(sock->conn);
331
 
332
  if (err != ERR_OK) {
333
    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d) failed, err=%d\n", s, err));
334
    sock_set_errno(sock, err_to_errno(err));
335
    return -1;
336
  }
337
 
338
  sock_set_errno(sock, 0);
339
  return 0;
340
}
341
 
342
int
343
lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
344
        struct sockaddr *from, socklen_t *fromlen)
345
{
346
  struct lwip_socket *sock;
347
  struct netbuf *buf;
348
  u16_t buflen, copylen;
349
  struct ip_addr *addr;
350
  u16_t port;
351
 
352
 
353
  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %d, 0x%x, ..)\n", s, mem, len, flags));
354
  sock = get_socket(s);
355
  if (!sock) {
356
    set_errno(EBADF);
357
    return -1;
358
  }
359
 
360
  /* Check if there is data left from the last recv operation. */
361
  if (sock->lastdata) {
362
    buf = sock->lastdata;
363
  } else {
364
    /* If this is non-blocking call, then check first */
365
    if (((flags & MSG_DONTWAIT) || (sock->flags & O_NONBLOCK))
366
  && !sock->rcvevent)
367
    {
368
      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s));
369
      sock_set_errno(sock, EWOULDBLOCK);
370
      return -1;
371
    }
372
 
373
    /* No data was left from the previous operation, so we try to get
374
       some from the network. */
375
    buf = netconn_recv(sock->conn);
376
 
377
    if (!buf) {
378
      /* We should really do some error checking here. */
379
      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL!\n", s));
380
      sock_set_errno(sock, 0);
381
      return 0;
382
    }
383
  }
384
 
385
  buflen = netbuf_len(buf);
386
 
387
  buflen -= sock->lastoffset;
388
 
389
  if (len > buflen) {
390
    copylen = buflen;
391
  } else {
392
    copylen = len;
393
  }
394
 
395
  /* copy the contents of the received buffer into
396
     the supplied memory pointer mem */
397
  netbuf_copy_partial(buf, mem, copylen, sock->lastoffset);
398
 
399
  /* Check to see from where the data was. */
400
  if (from && fromlen) {
401
    struct sockaddr_in sin;
402
 
403
    addr = netbuf_fromaddr(buf);
404
    port = netbuf_fromport(buf);
405
 
406
    memset(&sin, 0, sizeof(sin));
407
    sin.sin_len = sizeof(sin);
408
    sin.sin_family = AF_INET;
409
    sin.sin_port = htons(port);
410
    sin.sin_addr.s_addr = addr->addr;
411
 
412
    if (*fromlen > sizeof(sin))
413
      *fromlen = sizeof(sin);
414
 
415
    memcpy(from, &sin, *fromlen);
416
 
417
    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
418
    ip_addr_debug_print(SOCKETS_DEBUG, addr);
419
    LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u len=%u\n", port, copylen));
420
  } else {
421
#if SOCKETS_DEBUG
422
    addr = netbuf_fromaddr(buf);
423
    port = netbuf_fromport(buf);
424
 
425
    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
426
    ip_addr_debug_print(SOCKETS_DEBUG, addr);
427
    LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u len=%u\n", port, copylen));
428
#endif
429
 
430
  }
431
 
432
  /* If this is a TCP socket, check if there is data left in the
433
     buffer. If so, it should be saved in the sock structure for next
434
     time around. */
435
  if (netconn_type(sock->conn) == NETCONN_TCP && buflen - copylen > 0) {
436
    sock->lastdata = buf;
437
    sock->lastoffset += copylen;
438
  } else {
439
    sock->lastdata = NULL;
440
    sock->lastoffset = 0;
441
    netbuf_delete(buf);
442
  }
443
 
444
 
445
  sock_set_errno(sock, 0);
446
  return copylen;
447
}
448
 
449
int
450
lwip_read(int s, void *mem, int len)
451
{
452
  return lwip_recvfrom(s, mem, len, 0, NULL, NULL);
453
}
454
 
455
int
456
lwip_recv(int s, void *mem, int len, unsigned int flags)
457
{
458
  return lwip_recvfrom(s, mem, len, flags, NULL, NULL);
459
}
460
 
461
int
462
lwip_send(int s, void *data, int size, unsigned int flags)
463
{
464
  struct lwip_socket *sock;
465
  struct netbuf *buf;
466
  err_t err;
467
 
468
  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d, data=%p, size=%d, flags=0x%x)\n", s, data, size, flags));
469
 
470
  sock = get_socket(s);
471
  if (!sock) {
472
    set_errno(EBADF);
473
    return -1;
474
  }
475
 
476
  switch (netconn_type(sock->conn)) {
477
  case NETCONN_RAW:
478
  case NETCONN_UDP:
479
  case NETCONN_UDPLITE:
480
  case NETCONN_UDPNOCHKSUM:
481
    /* create a buffer */
482
    buf = netbuf_new();
483
 
484
    if (!buf) {
485
      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) ENOBUFS\n", s));
486
      sock_set_errno(sock, ENOBUFS);
487
      return -1;
488
    }
489
 
490
    /* make the buffer point to the data that should
491
       be sent */
492
    netbuf_ref(buf, data, size);
493
 
494
    /* send the data */
495
    err = netconn_send(sock->conn, buf);
496
 
497
    /* deallocated the buffer */
498
    netbuf_delete(buf);
499
    break;
500
  case NETCONN_TCP:
501
    err = netconn_write(sock->conn, data, size, NETCONN_COPY);
502
    break;
503
  default:
504
    err = ERR_ARG;
505
    break;
506
  }
507
  if (err != ERR_OK) {
508
    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d\n", s, err));
509
    sock_set_errno(sock, err_to_errno(err));
510
    return -1;
511
  }
512
 
513
  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) ok size=%d\n", s, size));
514
  sock_set_errno(sock, 0);
515
  return size;
516
}
517
 
518
int
519
lwip_sendto(int s, void *data, int size, unsigned int flags,
520
       struct sockaddr *to, socklen_t tolen)
521
{
522
  struct lwip_socket *sock;
523
  struct ip_addr remote_addr, addr;
524
  u16_t remote_port, port;
525
  int ret,connected;
526
 
527
  sock = get_socket(s);
528
  if (!sock) {
529
    set_errno(EBADF);
530
    return -1;
531
  }
532
 
533
  /* get the peer if currently connected */
534
  connected = (netconn_peer(sock->conn, &addr, &port) == ERR_OK);
535
 
536
  remote_addr.addr = ((struct sockaddr_in *)to)->sin_addr.s_addr;
537
  remote_port = ((struct sockaddr_in *)to)->sin_port;
538
 
539
  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, size=%d, flags=0x%x to=", s, data, size, flags));
540
  ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr);
541
  LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u\n", ntohs(remote_port)));
542
 
543
  netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));
544
 
545
  ret = lwip_send(s, data, size, flags);
546
 
547
  /* reset the remote address and port number
548
     of the connection */
549
  if (connected)
550
    netconn_connect(sock->conn, &addr, port);
551
  else
552
  netconn_disconnect(sock->conn);
553
  return ret;
554
}
555
 
556
int
557
lwip_socket(int domain, int type, int protocol)
558
{
559
  struct netconn *conn;
560
  int i;
561
 
562
  /* create a netconn */
563
  switch (type) {
564
  case SOCK_RAW:
565
    conn = netconn_new_with_proto_and_callback(NETCONN_RAW, protocol, event_callback);
566
    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
567
    break;
568
  case SOCK_DGRAM:
569
    conn = netconn_new_with_callback(NETCONN_UDP, event_callback);
570
    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ", domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
571
    break;
572
  case SOCK_STREAM:
573
    conn = netconn_new_with_callback(NETCONN_TCP, event_callback);
574
    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_STREAM, %d) = ", domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
575
    break;
576
  default:
577
    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%d, %d/UNKNOWN, %d) = -1\n", domain, type, protocol));
578
    set_errno(EINVAL);
579
    return -1;
580
  }
581
 
582
  if (!conn) {
583
    LWIP_DEBUGF(SOCKETS_DEBUG, ("-1 / ENOBUFS (could not create netconn)\n"));
584
    set_errno(ENOBUFS);
585
    return -1;
586
  }
587
 
588
  i = alloc_socket(conn);
589
 
590
  if (i == -1) {
591
    netconn_delete(conn);
592
  set_errno(ENOBUFS);
593
  return -1;
594
  }
595
  conn->socket = i;
596
  LWIP_DEBUGF(SOCKETS_DEBUG, ("%d\n", i));
597
  set_errno(0);
598
  return i;
599
}
600
 
601
int
602
lwip_write(int s, void *data, int size)
603
{
604
   return lwip_send(s, data, size, 0);
605
}
606
 
607
 
608
static int
609
lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset)
610
{
611
    int i, nready = 0;
612
    fd_set lreadset, lwriteset, lexceptset;
613
    struct lwip_socket *p_sock;
614
 
615
    FD_ZERO(&lreadset);
616
    FD_ZERO(&lwriteset);
617
    FD_ZERO(&lexceptset);
618
 
619
    /* Go through each socket in each list to count number of sockets which
620
       currently match */
621
    for(i = 0; i < maxfdp1; i++)
622
    {
623
        if (FD_ISSET(i, readset))
624
        {
625
            /* See if netconn of this socket is ready for read */
626
            p_sock = get_socket(i);
627
            if (p_sock && (p_sock->lastdata || p_sock->rcvevent))
628
            {
629
                FD_SET(i, &lreadset);
630
                LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i));
631
                nready++;
632
            }
633
        }
634
        if (FD_ISSET(i, writeset))
635
        {
636
            /* See if netconn of this socket is ready for write */
637
            p_sock = get_socket(i);
638
            if (p_sock && p_sock->sendevent)
639
            {
640
                FD_SET(i, &lwriteset);
641
                LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for writing\n", i));
642
                nready++;
643
            }
644
        }
645
    }
646
    *readset = lreadset;
647
    *writeset = lwriteset;
648
    FD_ZERO(exceptset);
649
 
650
    return nready;
651
}
652
 
653
 
654
 
655
int
656
lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
657
               struct timeval *timeout)
658
{
659
    int i;
660
    int nready;
661
    fd_set lreadset, lwriteset, lexceptset;
662
    u32_t msectimeout;
663
    struct lwip_select_cb select_cb;
664
    struct lwip_select_cb *p_selcb;
665
 
666
    LWIP_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));
667
 
668
    select_cb.next = 0;
669
    select_cb.readset = readset;
670
    select_cb.writeset = writeset;
671
    select_cb.exceptset = exceptset;
672
    select_cb.sem_signalled = 0;
673
 
674
    /* Protect ourselves searching through the list */
675
    if (!selectsem)
676
        selectsem = sys_sem_new(1);
677
    sys_sem_wait(selectsem);
678
 
679
    if (readset)
680
        lreadset = *readset;
681
    else
682
        FD_ZERO(&lreadset);
683
    if (writeset)
684
        lwriteset = *writeset;
685
    else
686
        FD_ZERO(&lwriteset);
687
    if (exceptset)
688
        lexceptset = *exceptset;
689
    else
690
        FD_ZERO(&lexceptset);
691
 
692
    /* Go through each socket in each list to count number of sockets which
693
       currently match */
694
    nready = lwip_selscan(maxfdp1, &lreadset, &lwriteset, &lexceptset);
695
 
696
    /* If we don't have any current events, then suspend if we are supposed to */
697
    if (!nready)
698
    {
699
        if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
700
        {
701
            sys_sem_signal(selectsem);
702
            if (readset)
703
                FD_ZERO(readset);
704
            if (writeset)
705
                FD_ZERO(writeset);
706
            if (exceptset)
707
                FD_ZERO(exceptset);
708
 
709
            LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n"));
710
            set_errno(0);
711
 
712
            return 0;
713
        }
714
 
715
        /* add our semaphore to list */
716
        /* We don't actually need any dynamic memory. Our entry on the
717
         * list is only valid while we are in this function, so it's ok
718
         * to use local variables */
719
 
720
        select_cb.sem = sys_sem_new(0);
721
        /* Note that we are still protected */
722
        /* Put this select_cb on top of list */
723
        select_cb.next = select_cb_list;
724
        select_cb_list = &select_cb;
725
 
726
        /* Now we can safely unprotect */
727
        sys_sem_signal(selectsem);
728
 
729
        /* Now just wait to be woken */
730
        if (timeout == 0)
731
            /* Wait forever */
732
            msectimeout = 0;
733
        else
734
            msectimeout =  ((timeout->tv_sec * 1000) + ((timeout->tv_usec + 500)/1000));
735
 
736
        i = sys_sem_wait_timeout(select_cb.sem, msectimeout);
737
 
738
        /* Take us off the list */
739
        sys_sem_wait(selectsem);
740
        if (select_cb_list == &select_cb)
741
            select_cb_list = select_cb.next;
742
        else
743
            for (p_selcb = select_cb_list; p_selcb; p_selcb = p_selcb->next)
744
                if (p_selcb->next == &select_cb)
745
                {
746
                    p_selcb->next = select_cb.next;
747
                    break;
748
                }
749
 
750
        sys_sem_signal(selectsem);
751
 
752
        sys_sem_free(select_cb.sem);
753
        if (i == 0)             /* Timeout */
754
        {
755
            if (readset)
756
                FD_ZERO(readset);
757
            if (writeset)
758
                FD_ZERO(writeset);
759
            if (exceptset)
760
                FD_ZERO(exceptset);
761
 
762
            LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n"));
763
            set_errno(0);
764
 
765
            return 0;
766
        }
767
 
768
        if (readset)
769
            lreadset = *readset;
770
        else
771
            FD_ZERO(&lreadset);
772
        if (writeset)
773
            lwriteset = *writeset;
774
        else
775
            FD_ZERO(&lwriteset);
776
        if (exceptset)
777
            lexceptset = *exceptset;
778
        else
779
            FD_ZERO(&lexceptset);
780
 
781
        /* See what's set */
782
        nready = lwip_selscan(maxfdp1, &lreadset, &lwriteset, &lexceptset);
783
    }
784
    else
785
        sys_sem_signal(selectsem);
786
 
787
    if (readset)
788
        *readset = lreadset;
789
    if (writeset)
790
        *writeset = lwriteset;
791
    if (exceptset)
792
        *exceptset = lexceptset;
793
 
794
    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready));
795
    set_errno(0);
796
 
797
    return nready;
798
}
799
 
800
 
801
static void
802
event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
803
{
804
    int s;
805
    struct lwip_socket *sock;
806
    struct lwip_select_cb *scb;
807
 
808
    /* Get socket */
809
    if (conn)
810
    {
811
        s = conn->socket;
812
        if (s < 0)
813
        {
814
            /* Data comes in right away after an accept, even though
815
             * the server task might not have created a new socket yet.
816
             * Just count down (or up) if that's the case and we
817
             * will use the data later. Note that only receive events
818
             * can happen before the new socket is set up. */
819
            if (evt == NETCONN_EVT_RCVPLUS)
820
                conn->socket--;
821
            return;
822
        }
823
 
824
        sock = get_socket(s);
825
        if (!sock)
826
            return;
827
    }
828
    else
829
        return;
830
 
831
    if (!selectsem)
832
        selectsem = sys_sem_new(1);
833
 
834
    sys_sem_wait(selectsem);
835
    /* Set event as required */
836
    switch (evt)
837
    {
838
      case NETCONN_EVT_RCVPLUS:
839
        sock->rcvevent++;
840
        break;
841
      case NETCONN_EVT_RCVMINUS:
842
        sock->rcvevent--;
843
        break;
844
      case NETCONN_EVT_SENDPLUS:
845
        sock->sendevent = 1;
846
        break;
847
      case NETCONN_EVT_SENDMINUS:
848
        sock->sendevent = 0;
849
        break;
850
    }
851
    sys_sem_signal(selectsem);
852
 
853
    /* Now decide if anyone is waiting for this socket */
854
    /* NOTE: This code is written this way to protect the select link list
855
       but to avoid a deadlock situation by releasing socksem before
856
       signalling for the select. This means we need to go through the list
857
       multiple times ONLY IF a select was actually waiting. We go through
858
       the list the number of waiting select calls + 1. This list is
859
       expected to be small. */
860
    while (1)
861
    {
862
        sys_sem_wait(selectsem);
863
        for (scb = select_cb_list; scb; scb = scb->next)
864
        {
865
            if (scb->sem_signalled == 0)
866
            {
867
                /* Test this select call for our socket */
868
                if (scb->readset && FD_ISSET(s, scb->readset))
869
                    if (sock->rcvevent)
870
                        break;
871
                if (scb->writeset && FD_ISSET(s, scb->writeset))
872
                    if (sock->sendevent)
873
                        break;
874
            }
875
        }
876
        if (scb)
877
        {
878
            scb->sem_signalled = 1;
879
            sys_sem_signal(selectsem);
880
            sys_sem_signal(scb->sem);
881
        } else {
882
            sys_sem_signal(selectsem);
883
            break;
884
        }
885
    }
886
 
887
}
888
 
889
 
890
 
891
 
892
int lwip_shutdown(int s, int how)
893
{
894
  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_shutdown(%d, how=%d)\n", s, how));
895
  return lwip_close(s); /* XXX temporary hack until proper implementation */
896
}
897
 
898
int lwip_getpeername (int s, struct sockaddr *name, socklen_t *namelen)
899
{
900
  struct lwip_socket *sock;
901
  struct sockaddr_in sin;
902
  struct ip_addr naddr;
903
 
904
  sock = get_socket(s);
905
  if (!sock) {
906
    set_errno(EBADF);
907
    return -1;
908
  }
909
 
910
  memset(&sin, 0, sizeof(sin));
911
  sin.sin_len = sizeof(sin);
912
  sin.sin_family = AF_INET;
913
 
914
  /* get the IP address and port of the remote host */
915
  netconn_peer(sock->conn, &naddr, &sin.sin_port);
916
 
917
  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getpeername(%d, addr=", s));
918
  ip_addr_debug_print(SOCKETS_DEBUG, &naddr);
919
  LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%d)\n", sin.sin_port));
920
 
921
  sin.sin_port = htons(sin.sin_port);
922
  sin.sin_addr.s_addr = naddr.addr;
923
 
924
  if (*namelen > sizeof(sin))
925
      *namelen = sizeof(sin);
926
 
927
  memcpy(name, &sin, *namelen);
928
  sock_set_errno(sock, 0);
929
  return 0;
930
}
931
 
932
int lwip_getsockname (int s, struct sockaddr *name, socklen_t *namelen)
933
{
934
  struct lwip_socket *sock;
935
  struct sockaddr_in sin;
936
  struct ip_addr *naddr;
937
 
938
  sock = get_socket(s);
939
  if (!sock) {
940
    set_errno(EBADF);
941
    return -1;
942
  }
943
 
944
  memset(&sin, 0, sizeof(sin));
945
  sin.sin_len = sizeof(sin);
946
  sin.sin_family = AF_INET;
947
 
948
  /* get the IP address and port of the remote host */
949
  netconn_addr(sock->conn, &naddr, &sin.sin_port);
950
 
951
  LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockname(%d, addr=", s));
952
  ip_addr_debug_print(SOCKETS_DEBUG, naddr);
953
  LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%d)\n", sin.sin_port));
954
 
955
  sin.sin_port = htons(sin.sin_port);
956
  sin.sin_addr.s_addr = naddr->addr;
957
 
958
  if (*namelen > sizeof(sin))
959
      *namelen = sizeof(sin);
960
 
961
  memcpy(name, &sin, *namelen);
962
  sock_set_errno(sock, 0);
963
  return 0;
964
}
965
 
966
int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen)
967
{
968
  int err = 0;
969
  struct lwip_socket *sock = get_socket(s);
970
 
971
  if(!sock) {
972
        set_errno(EBADF);
973
    return -1;
974
  }
975
 
976
  if( NULL == optval || NULL == optlen ) {
977
    sock_set_errno( sock, EFAULT );
978
    return -1;
979
  }
980
 
981
  /* Do length and type checks for the various options first, to keep it readable. */
982
  switch( level ) {
983
 
984
/* Level: SOL_SOCKET */
985
  case SOL_SOCKET:
986
      switch(optname) {
987
 
988
      case SO_ACCEPTCONN:
989
      case SO_BROADCAST:
990
      /* UNIMPL case SO_DEBUG: */
991
      /* UNIMPL case SO_DONTROUTE: */
992
      case SO_ERROR:
993
      case SO_KEEPALIVE:
994
      /* UNIMPL case SO_OOBINLINE: */
995
      /* UNIMPL case SO_RCVBUF: */
996
      /* UNIMPL case SO_SNDBUF: */
997
      /* UNIMPL case SO_RCVLOWAT: */
998
      /* UNIMPL case SO_SNDLOWAT: */
999
#if SO_REUSE
1000
      case SO_REUSEADDR:
1001
      case SO_REUSEPORT:
1002
#endif /* SO_REUSE */
1003
      case SO_TYPE:
1004
      /* UNIMPL case SO_USELOOPBACK: */
1005
        if( *optlen < sizeof(int) ) {
1006
          err = EINVAL;
1007
        }
1008
          break;
1009
 
1010
      default:
1011
        LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", s, optname));
1012
        err = ENOPROTOOPT;
1013
      }  /* switch */
1014
      break;
1015
 
1016
/* Level: IPPROTO_IP */
1017
  case IPPROTO_IP:
1018
      switch(optname) {
1019
      /* UNIMPL case IP_HDRINCL: */
1020
      /* UNIMPL case IP_RCVDSTADDR: */
1021
      /* UNIMPL case IP_RCVIF: */
1022
      case IP_TTL:
1023
      case IP_TOS:
1024
        if( *optlen < sizeof(int) ) {
1025
          err = EINVAL;
1026
        }
1027
        break;
1028
 
1029
      default:
1030
        LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", s, optname));
1031
        err = ENOPROTOOPT;
1032
      }  /* switch */
1033
      break;
1034
 
1035
/* Level: IPPROTO_TCP */
1036
  case IPPROTO_TCP:
1037
      if( *optlen < sizeof(int) ) {
1038
        err = EINVAL;
1039
        break;
1040
    }
1041
 
1042
      /* If this is no TCP socket, ignore any options. */
1043
      if ( sock->conn->type != NETCONN_TCP ) return 0;
1044
 
1045
      switch( optname ) {
1046
      case TCP_NODELAY:
1047
      case TCP_KEEPALIVE:
1048
        break;
1049
 
1050
      default:
1051
        LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", s, optname));
1052
        err = ENOPROTOOPT;
1053
      }  /* switch */
1054
      break;
1055
 
1056
/* UNDEFINED LEVEL */
1057
  default:
1058
      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", s, level, optname));
1059
      err = ENOPROTOOPT;
1060
  }  /* switch */
1061
 
1062
 
1063
  if( 0 != err ) {
1064
    sock_set_errno(sock, err);
1065
    return -1;
1066
  }
1067
 
1068
 
1069
 
1070
  /* Now do the actual option processing */
1071
 
1072
  switch(level) {
1073
 
1074
/* Level: SOL_SOCKET */
1075
  case SOL_SOCKET:
1076
    switch( optname ) {
1077
 
1078
    /* The option flags */
1079
    case SO_ACCEPTCONN:
1080
    case SO_BROADCAST:
1081
    /* UNIMPL case SO_DEBUG: */
1082
    /* UNIMPL case SO_DONTROUTE: */
1083
    case SO_KEEPALIVE:
1084
    /* UNIMPL case SO_OOBINCLUDE: */
1085
#if SO_REUSE
1086
    case SO_REUSEADDR:
1087
    case SO_REUSEPORT:
1088
#endif /* SO_REUSE */
1089
    /*case SO_USELOOPBACK: UNIMPL */
1090
      *(int*)optval = sock->conn->pcb.tcp->so_options & optname;
1091
      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, optname=0x%x, ..) = %s\n", s, optname, (*(int*)optval?"on":"off")));
1092
      break;
1093
 
1094
    case SO_TYPE:
1095
      switch (sock->conn->type) {
1096
      case NETCONN_RAW:
1097
        *(int*)optval = SOCK_RAW;
1098
        break;
1099
      case NETCONN_TCP:
1100
        *(int*)optval = SOCK_STREAM;
1101
        break;
1102
      case NETCONN_UDP:
1103
      case NETCONN_UDPLITE:
1104
      case NETCONN_UDPNOCHKSUM:
1105
        *(int*)optval = SOCK_DGRAM;
1106
        break;
1107
      default: /* unrecognized socket type */
1108
        *(int*)optval = sock->conn->type;
1109
        LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n", s, *(int *)optval));
1110
      }  /* switch */
1111
      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n", s, *(int *)optval));
1112
      break;
1113
 
1114
    case SO_ERROR:
1115
      *(int *)optval = sock->err;
1116
      sock->err = 0;
1117
      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", s, *(int *)optval));
1118
      break;
1119
    }  /* switch */
1120
    break;
1121
 
1122
/* Level: IPPROTO_IP */
1123
  case IPPROTO_IP:
1124
    switch( optname ) {
1125
    case IP_TTL:
1126
      *(int*)optval = sock->conn->pcb.tcp->ttl;
1127
      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TTL) = %d\n", s, *(int *)optval));
1128
      break;
1129
    case IP_TOS:
1130
      *(int*)optval = sock->conn->pcb.tcp->tos;
1131
      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n", s, *(int *)optval));
1132
      break;
1133
    }  /* switch */
1134
    break;
1135
 
1136
/* Level: IPPROTO_TCP */
1137
  case IPPROTO_TCP:
1138
    switch( optname ) {
1139
    case TCP_NODELAY:
1140
      *(int*)optval = (sock->conn->pcb.tcp->flags & TF_NODELAY);
1141
      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n", s, (*(int*)optval)?"on":"off") );
1142
      break;
1143
    case TCP_KEEPALIVE:
1144
      *(int*)optval = (int)sock->conn->pcb.tcp->keepalive;
1145
      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPALIVE) = %d\n", s, *(int *)optval));
1146
      break;
1147
    }  /* switch */
1148
    break;
1149
  }
1150
 
1151
 
1152
  sock_set_errno(sock, err);
1153
  return err ? -1 : 0;
1154
}
1155
 
1156
int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen)
1157
{
1158
  struct lwip_socket *sock = get_socket(s);
1159
  int err = 0;
1160
 
1161
  if(!sock) {
1162
        set_errno(EBADF);
1163
    return -1;
1164
  }
1165
 
1166
  if( NULL == optval ) {
1167
    sock_set_errno( sock, EFAULT );
1168
    return -1;
1169
  }
1170
 
1171
 
1172
  /* Do length and type checks for the various options first, to keep it readable. */
1173
  switch( level ) {
1174
 
1175
/* Level: SOL_SOCKET */
1176
  case SOL_SOCKET:
1177
    switch(optname) {
1178
 
1179
    case SO_BROADCAST:
1180
    /* UNIMPL case SO_DEBUG: */
1181
    /* UNIMPL case SO_DONTROUTE: */
1182
    case SO_KEEPALIVE:
1183
    /* UNIMPL case SO_OOBINLINE: */
1184
    /* UNIMPL case SO_RCVBUF: */
1185
    /* UNIMPL case SO_SNDBUF: */
1186
    /* UNIMPL case SO_RCVLOWAT: */
1187
    /* UNIMPL case SO_SNDLOWAT: */
1188
#if SO_REUSE
1189
    case SO_REUSEADDR:
1190
    case SO_REUSEPORT:
1191
#endif /* SO_REUSE */
1192
    /* UNIMPL case SO_USELOOPBACK: */
1193
      if( optlen < sizeof(int) ) {
1194
        err = EINVAL;
1195
      }
1196
      break;
1197
    default:
1198
      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", s, optname));
1199
      err = ENOPROTOOPT;
1200
    }  /* switch */
1201
    break;
1202
 
1203
/* Level: IPPROTO_IP */
1204
  case IPPROTO_IP:
1205
    switch(optname) {
1206
    /* UNIMPL case IP_HDRINCL: */
1207
    /* UNIMPL case IP_RCVDSTADDR: */
1208
    /* UNIMPL case IP_RCVIF: */
1209
    case IP_TTL:
1210
    case IP_TOS:
1211
      if( optlen < sizeof(int) ) {
1212
        err = EINVAL;
1213
      }
1214
        break;
1215
      default:
1216
      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", s, optname));
1217
      err = ENOPROTOOPT;
1218
    }  /* switch */
1219
    break;
1220
 
1221
/* Level: IPPROTO_TCP */
1222
  case IPPROTO_TCP:
1223
    if( optlen < sizeof(int) ) {
1224
      err = EINVAL;
1225
        break;
1226
    }
1227
 
1228
    /* If this is no TCP socket, ignore any options. */
1229
    if ( sock->conn->type != NETCONN_TCP ) return 0;
1230
 
1231
    switch( optname ) {
1232
    case TCP_NODELAY:
1233
    case TCP_KEEPALIVE:
1234
      break;
1235
 
1236
    default:
1237
      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", s, optname));
1238
      err = ENOPROTOOPT;
1239
    }  /* switch */
1240
    break;
1241
 
1242
/* UNDEFINED LEVEL */
1243
  default:
1244
    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", s, level, optname));
1245
    err = ENOPROTOOPT;
1246
  }  /* switch */
1247
 
1248
 
1249
  if( 0 != err ) {
1250
    sock_set_errno(sock, err);
1251
    return -1;
1252
  }
1253
 
1254
 
1255
 
1256
  /* Now do the actual option processing */
1257
 
1258
  switch(level) {
1259
 
1260
/* Level: SOL_SOCKET */
1261
  case SOL_SOCKET:
1262
    switch(optname) {
1263
 
1264
    /* The option flags */
1265
    case SO_BROADCAST:
1266
    /* UNIMPL case SO_DEBUG: */
1267
    /* UNIMPL case SO_DONTROUTE: */
1268
    case SO_KEEPALIVE:
1269
    /* UNIMPL case SO_OOBINCLUDE: */
1270
#if SO_REUSE
1271
    case SO_REUSEADDR:
1272
    case SO_REUSEPORT:
1273
#endif /* SO_REUSE */
1274
    /* UNIMPL case SO_USELOOPBACK: */
1275
      if ( *(int*)optval ) {
1276
        sock->conn->pcb.tcp->so_options |= optname;
1277
      } else {
1278
        sock->conn->pcb.tcp->so_options &= ~optname;
1279
      }
1280
      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n", s, optname, (*(int*)optval?"on":"off")));
1281
      break;
1282
    }  /* switch */
1283
    break;
1284
 
1285
/* Level: IPPROTO_IP */
1286
  case IPPROTO_IP:
1287
    switch( optname ) {
1288
    case IP_TTL:
1289
      sock->conn->pcb.tcp->ttl = (u8_t)(*(int*)optval);
1290
      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %u\n", s, sock->conn->pcb.tcp->ttl));
1291
      break;
1292
    case IP_TOS:
1293
      sock->conn->pcb.tcp->tos = (u8_t)(*(int*)optval);
1294
      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %u\n", s, sock->conn->pcb.tcp->tos));
1295
      break;
1296
    }  /* switch */
1297
    break;
1298
 
1299
/* Level: IPPROTO_TCP */
1300
  case IPPROTO_TCP:
1301
    switch( optname ) {
1302
    case TCP_NODELAY:
1303
      if ( *(int*)optval ) {
1304
        sock->conn->pcb.tcp->flags |= TF_NODELAY;
1305
      } else {
1306
        sock->conn->pcb.tcp->flags &= ~TF_NODELAY;
1307
      }
1308
      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n", s, (*(int *)optval)?"on":"off") );
1309
      break;
1310
    case TCP_KEEPALIVE:
1311
      sock->conn->pcb.tcp->keepalive = (u32_t)(*(int*)optval);
1312
      LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %lu\n", s, sock->conn->pcb.tcp->keepalive));
1313
      break;
1314
    }  /* switch */
1315
    break;
1316
  }  /* switch */
1317
 
1318
  sock_set_errno(sock, err);
1319
  return err ? -1 : 0;
1320
}
1321
 
1322
int lwip_ioctl(int s, long cmd, void *argp)
1323
{
1324
  struct lwip_socket *sock = get_socket(s);
1325
 
1326
  if(!sock) {
1327
        set_errno(EBADF);
1328
    return -1;
1329
  }
1330
 
1331
  switch (cmd) {
1332
  case FIONREAD:
1333
    if (!argp) {
1334
      sock_set_errno(sock, EINVAL);
1335
      return -1;
1336
    }
1337
 
1338
    *((u16_t*)argp) = sock->conn->recv_avail;
1339
 
1340
    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %u\n", s, argp, *((u16_t*)argp)));
1341
    sock_set_errno(sock, 0);
1342
    return 0;
1343
 
1344
  case FIONBIO:
1345
    if (argp && *(u32_t*)argp)
1346
      sock->flags |= O_NONBLOCK;
1347
    else
1348
      sock->flags &= ~O_NONBLOCK;
1349
    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, !!(sock->flags & O_NONBLOCK)));
1350
    sock_set_errno(sock, 0);
1351
    return 0;
1352
 
1353
  default:
1354
    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp));
1355
    sock_set_errno(sock, ENOSYS); /* not yet implemented */
1356
    return -1;
1357
  }
1358
}
1359
 

powered by: WebSVN 2.1.0

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