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

Subversion Repositories openrisc

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

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

powered by: WebSVN 2.1.0

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