00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include "lwip/opt.h"
00042 #include "lwip/api.h"
00043 #include "lwip/arch.h"
00044 #include "lwip/sys.h"
00045
00046 #include "lwip/sockets.h"
00047
00048 #define htons HTONS
00049 #define htonl HTONL
00050
00051 #define NUM_SOCKETS MEMP_NUM_NETCONN
00052
00053 struct lwip_socket {
00054 struct netconn *conn;
00055 struct netbuf *lastdata;
00056 u16_t lastoffset;
00057 u16_t rcvevent;
00058 u16_t sendevent;
00059 u16_t flags;
00060 int err;
00061 };
00062
00063 struct lwip_select_cb
00064 {
00065 struct lwip_select_cb *next;
00066 fd_set *readset;
00067 fd_set *writeset;
00068 fd_set *exceptset;
00069 int sem_signalled;
00070 sys_sem_t sem;
00071 };
00072
00073 static struct lwip_socket sockets[NUM_SOCKETS];
00074 static struct lwip_select_cb *select_cb_list = 0;
00075
00076 static sys_sem_t socksem = 0;
00077 static sys_sem_t selectsem = 0;
00078
00079 static void
00080 event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len);
00081
00082 static int err_to_errno_table[11] = {
00083 0,
00084 ENOMEM,
00085 ENOBUFS,
00086 ECONNABORTED,
00087 ECONNRESET,
00088 ESHUTDOWN,
00089 ENOTCONN,
00090 EINVAL,
00091 EIO,
00092 EHOSTUNREACH,
00093 EADDRINUSE
00094 };
00095
00096 #define err_to_errno(err) \
00097 ((err) < (sizeof(err_to_errno_table)/sizeof(int))) ? \
00098 err_to_errno_table[-(err)] : EIO
00099
00100 #ifdef ERRNO
00101 #define set_errno(err) errno = (err)
00102 #else
00103 #define set_errno(err)
00104 #endif
00105
00106 #define sock_set_errno(sk, e) do { \
00107 sk->err = (e); \
00108 set_errno(sk->err); \
00109 } while(0)
00110
00111
00112 static struct lwip_socket *
00113 get_socket(int s)
00114 {
00115 struct lwip_socket *sock;
00116
00117 if((s < 0) || (s > NUM_SOCKETS)) {
00118 DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): invalid\n", s));
00119 set_errno(EBADF);
00120 return NULL;
00121 }
00122
00123 sock = &sockets[s];
00124
00125 if(!sock->conn) {
00126 DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): not active\n", s));
00127 set_errno(EBADF);
00128 return NULL;
00129 }
00130
00131 return sock;
00132 }
00133
00134 static int
00135 alloc_socket(struct netconn *newconn)
00136 {
00137 int i;
00138
00139 if (!socksem)
00140 socksem = sys_sem_new(1);
00141
00142
00143 sys_sem_wait(socksem);
00144
00145
00146 for(i = 0; i < NUM_SOCKETS; ++i) {
00147 if(!sockets[i].conn) {
00148 sockets[i].conn = newconn;
00149 sockets[i].lastdata = NULL;
00150 sockets[i].lastoffset = 0;
00151 sockets[i].rcvevent = 0;
00152 sockets[i].sendevent = 1;
00153 sockets[i].flags = 0;
00154 sockets[i].err = 0;
00155 sys_sem_signal(socksem);
00156 return i;
00157 }
00158 }
00159 sys_sem_signal(socksem);
00160 return -1;
00161 }
00162
00163 int
00164 lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
00165 {
00166 struct lwip_socket *sock;
00167 struct netconn *newconn;
00168 struct ip_addr naddr;
00169 u16_t port;
00170 int newsock;
00171 struct sockaddr_in sin;
00172
00173 DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s));
00174 sock = get_socket(s);
00175 if(!sock) {
00176 return -1;
00177 }
00178
00179 newconn = netconn_accept(sock->conn);
00180
00181
00182 netconn_peer(newconn, &naddr, &port);
00183
00184 memset(&sin, 0, sizeof(sin));
00185 sin.sin_len = sizeof(sin);
00186 sin.sin_family = AF_INET;
00187 sin.sin_port = htons(port);
00188 sin.sin_addr.s_addr = naddr.addr;
00189
00190 if(*addrlen > sizeof(sin))
00191 *addrlen = sizeof(sin);
00192
00193 memcpy(addr, &sin, *addrlen);
00194
00195 newsock = alloc_socket(newconn);
00196 if(newsock == -1) {
00197 netconn_delete(newconn);
00198 sock_set_errno(sock, ENOBUFS);
00199 return -1;
00200 }
00201 newconn->callback = event_callback;
00202 sock = get_socket(newsock);
00203
00204 sys_sem_wait(socksem);
00205 sock->rcvevent += -1 - newconn->socket;
00206 newconn->socket = newsock;
00207 sys_sem_signal(socksem);
00208
00209 #if SOCKETS_DEBUG
00210 DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock));
00211 ip_addr_debug_print(&naddr);
00212 DEBUGF(SOCKETS_DEBUG, (" port=%u\n", port));
00213 #endif
00214
00215 sock_set_errno(sock, 0);
00216 return newsock;
00217 }
00218
00219 int
00220 lwip_bind(int s, struct sockaddr *name, socklen_t namelen)
00221 {
00222 struct lwip_socket *sock;
00223 struct ip_addr local_addr;
00224 u16_t local_port;
00225 err_t err;
00226
00227 sock = get_socket(s);
00228 if(!sock) {
00229 return -1;
00230 }
00231
00232 local_addr.addr = ((struct sockaddr_in *)name)->sin_addr.s_addr;
00233 local_port = ((struct sockaddr_in *)name)->sin_port;
00234
00235 #if SOCKETS_DEBUG
00236 DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s));
00237 ip_addr_debug_print(&local_addr);
00238 DEBUGF(SOCKETS_DEBUG, (" port=%u)\n", ntohs(local_port)));
00239 #endif
00240
00241 err = netconn_bind(sock->conn, &local_addr, ntohs(local_port));
00242
00243 if(err != ERR_OK) {
00244 DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err));
00245 sock_set_errno(sock, err_to_errno(err));
00246 return -1;
00247 }
00248
00249 DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) succeeded\n", s));
00250 sock_set_errno(sock, 0);
00251 return 0;
00252 }
00253
00254 int
00255 lwip_close(int s)
00256 {
00257 struct lwip_socket *sock;
00258
00259 DEBUGF(SOCKETS_DEBUG, ("lwip_close(%d)\n", s));
00260 if (!socksem)
00261 socksem = sys_sem_new(1);
00262
00263
00264 sys_sem_wait(socksem);
00265
00266 sock = get_socket(s);
00267 if(!sock) {
00268 sys_sem_signal(socksem);
00269 return -1;
00270 }
00271
00272 netconn_delete(sock->conn);
00273 if(sock->lastdata) {
00274 netbuf_delete(sock->lastdata);
00275 }
00276 sock->lastdata = NULL;
00277 sock->lastoffset = 0;
00278 sock->conn = NULL;
00279 sys_sem_signal(socksem);
00280 sock_set_errno(sock, 0);
00281 return 0;
00282 }
00283
00284 int
00285 lwip_connect(int s, struct sockaddr *name, socklen_t namelen)
00286 {
00287 struct lwip_socket *sock;
00288 err_t err;
00289
00290 sock = get_socket(s);
00291 if(!sock) {
00292 return -1;
00293 }
00294
00295 if (((struct sockaddr_in *)name)->sin_family == AF_UNSPEC) {
00296 DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, AF_UNSPEC)\n", s));
00297 err = netconn_disconnect(sock->conn);
00298 } else {
00299 struct ip_addr remote_addr;
00300 u16_t remote_port;
00301
00302 remote_addr.addr = ((struct sockaddr_in *)name)->sin_addr.s_addr;
00303 remote_port = ((struct sockaddr_in *)name)->sin_port;
00304
00305 #if SOCKETS_DEBUG
00306 DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s));
00307 ip_addr_debug_print(&remote_addr);
00308 DEBUGF(SOCKETS_DEBUG, (" port=%u)\n", ntohs(remote_port)));
00309 #endif
00310
00311 err = netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));
00312 }
00313
00314 if(err != ERR_OK) {
00315 DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) failed, err=%d\n", s, err));
00316 sock_set_errno(sock, err_to_errno(err));
00317 return -1;
00318 }
00319
00320 DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) succeeded\n", s));
00321 sock_set_errno(sock, 0);
00322 return 0;
00323 }
00324
00325 int
00326 lwip_listen(int s, int backlog)
00327 {
00328 struct lwip_socket *sock;
00329 err_t err;
00330
00331 DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog));
00332 sock = get_socket(s);
00333 if(!sock) {
00334 return -1;
00335 }
00336
00337 err = netconn_listen(sock->conn);
00338
00339 if(err != ERR_OK) {
00340 DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d) failed, err=%d\n", s, err));
00341 sock_set_errno(sock, err_to_errno(err));
00342 return -1;
00343 }
00344
00345 sock_set_errno(sock, 0);
00346 return 0;
00347 }
00348
00349 int
00350 lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
00351 struct sockaddr *from, socklen_t *fromlen)
00352 {
00353 struct lwip_socket *sock;
00354 struct netbuf *buf;
00355 u16_t buflen, copylen;
00356 struct ip_addr *addr;
00357 u16_t port;
00358
00359
00360 DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %d, 0x%x, ..)\n", s, mem, len, flags));
00361 sock = get_socket(s);
00362 if(!sock) {
00363 return -1;
00364 }
00365
00366
00367 if(sock->lastdata) {
00368 buf = sock->lastdata;
00369 } else {
00370
00371 if (((flags & MSG_DONTWAIT) || (sock->flags & O_NONBLOCK))
00372 && !sock->rcvevent)
00373 {
00374 DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s));
00375 sock_set_errno(sock, EWOULDBLOCK);
00376 return -1;
00377 }
00378
00379
00380
00381 buf = netconn_recv(sock->conn);
00382
00383 if(!buf) {
00384
00385 DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL!\n", s));
00386 sock_set_errno(sock, 0);
00387 return 0;
00388 }
00389 }
00390
00391 buflen = netbuf_len(buf);
00392
00393 buflen -= sock->lastoffset;
00394
00395 if(len > buflen) {
00396 copylen = buflen;
00397 } else {
00398 copylen = len;
00399 }
00400
00401
00402
00403 netbuf_copy_partial(buf, mem, copylen, sock->lastoffset);
00404
00405
00406 if(from && fromlen) {
00407 struct sockaddr_in sin;
00408
00409 addr = netbuf_fromaddr(buf);
00410 port = netbuf_fromport(buf);
00411
00412 memset(&sin, 0, sizeof(sin));
00413 sin.sin_len = sizeof(sin);
00414 sin.sin_family = AF_INET;
00415 sin.sin_port = htons(port);
00416 sin.sin_addr.s_addr = addr->addr;
00417
00418 if(*fromlen > sizeof(sin))
00419 *fromlen = sizeof(sin);
00420
00421 memcpy(from, &sin, *fromlen);
00422
00423 #if SOCKETS_DEBUG
00424 DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
00425 ip_addr_debug_print(addr);
00426 DEBUGF(SOCKETS_DEBUG, (" port=%u len=%u\n", port, copylen));
00427 #endif
00428 } else {
00429 #if SOCKETS_DEBUG > 0
00430 addr = netbuf_fromaddr(buf);
00431 port = netbuf_fromport(buf);
00432
00433 DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
00434 ip_addr_debug_print(addr);
00435 DEBUGF(SOCKETS_DEBUG, (" port=%u len=%u\n", port, copylen));
00436 #endif
00437
00438 }
00439
00440
00441
00442
00443 if(netconn_type(sock->conn) == NETCONN_TCP && buflen - copylen > 0) {
00444 sock->lastdata = buf;
00445 sock->lastoffset += copylen;
00446 } else {
00447 sock->lastdata = NULL;
00448 sock->lastoffset = 0;
00449 netbuf_delete(buf);
00450 }
00451
00452
00453 sock_set_errno(sock, 0);
00454 return copylen;
00455 }
00456
00457 int
00458 lwip_read(int s, void *mem, int len)
00459 {
00460 return lwip_recvfrom(s, mem, len, 0, NULL, NULL);
00461 }
00462
00463 int
00464 lwip_recv(int s, void *mem, int len, unsigned int flags)
00465 {
00466 return lwip_recvfrom(s, mem, len, flags, NULL, NULL);
00467 }
00468
00469 int
00470 lwip_send(int s, void *data, int size, unsigned int flags)
00471 {
00472 struct lwip_socket *sock;
00473 struct netbuf *buf;
00474 err_t err;
00475
00476 DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d, data=%p, size=%d, flags=0x%x)\n", s, data, size, flags));
00477
00478 sock = get_socket(s);
00479 if(!sock) {
00480 return -1;
00481 }
00482
00483 switch(netconn_type(sock->conn)) {
00484 case NETCONN_UDP:
00485
00486 buf = netbuf_new();
00487
00488 if(!buf) {
00489 DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) ENOBUFS\n", s));
00490 sock_set_errno(sock, ENOBUFS);
00491 return -1;
00492 }
00493
00494
00495
00496 netbuf_ref(buf, data, size);
00497
00498
00499 err = netconn_send(sock->conn, buf);
00500
00501
00502 netbuf_delete(buf);
00503 break;
00504 case NETCONN_TCP:
00505 err = netconn_write(sock->conn, data, size, NETCONN_COPY);
00506 break;
00507 default:
00508 err = ERR_ARG;
00509 break;
00510 }
00511 if(err != ERR_OK) {
00512 DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d\n", s, err));
00513 sock_set_errno(sock, err_to_errno(err));
00514 return -1;
00515 }
00516
00517 DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) ok size=%d\n", s, size));
00518 sock_set_errno(sock, 0);
00519 return size;
00520 }
00521
00522 int
00523 lwip_sendto(int s, void *data, int size, unsigned int flags,
00524 struct sockaddr *to, socklen_t tolen)
00525 {
00526 struct lwip_socket *sock;
00527 struct ip_addr remote_addr, addr;
00528 u16_t remote_port, port;
00529 int ret,connected;
00530
00531 sock = get_socket(s);
00532 if(!sock) {
00533 return -1;
00534 }
00535
00536
00537 connected = (netconn_peer(sock->conn, &addr, &port) == ERR_OK);
00538
00539 remote_addr.addr = ((struct sockaddr_in *)to)->sin_addr.s_addr;
00540 remote_port = ((struct sockaddr_in *)to)->sin_port;
00541
00542 #if SOCKETS_DEBUG
00543 DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, size=%d, flags=0x%x to=", s, data, size, flags));
00544 ip_addr_debug_print(&remote_addr);
00545 DEBUGF(SOCKETS_DEBUG, (" port=%u\n", ntohs(remote_port)));
00546 #endif
00547
00548 netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));
00549
00550 ret = lwip_send(s, data, size, flags);
00551
00552
00553
00554 if(connected)
00555 netconn_connect(sock->conn, &addr, port);
00556 else
00557 netconn_disconnect(sock->conn);
00558 return ret;
00559 }
00560
00561 int
00562 lwip_socket(int domain, int type, int protocol)
00563 {
00564 struct netconn *conn;
00565 int i;
00566
00567
00568 switch(type) {
00569 case SOCK_DGRAM:
00570 conn = netconn_new_with_callback(NETCONN_UDP, event_callback);
00571 DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ", domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
00572 break;
00573 case SOCK_STREAM:
00574 conn = netconn_new_with_callback(NETCONN_TCP, event_callback);
00575 DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_STREAM, %d) = ", domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
00576 break;
00577 default:
00578 DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%d, %d/UNKNOWN, %d) = -1\n", domain, type, protocol));
00579 set_errno(EINVAL);
00580 return -1;
00581 }
00582
00583 if(!conn) {
00584 DEBUGF(SOCKETS_DEBUG, ("-1 / ENOBUFS (could not create netconn)\n"));
00585 set_errno(ENOBUFS);
00586 return -1;
00587 }
00588
00589 i = alloc_socket(conn);
00590
00591 if(i == -1) {
00592 netconn_delete(conn);
00593 set_errno(ENOBUFS);
00594 return -1;
00595 }
00596 conn->socket = i;
00597 DEBUGF(SOCKETS_DEBUG, ("%d\n", i));
00598 set_errno(0);
00599 return i;
00600 }
00601
00602 int
00603 lwip_write(int s, void *data, int size)
00604 {
00605 return lwip_send(s, data, size, 0);
00606 }
00607
00608
00609 static int
00610 lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset)
00611 {
00612 int i, nready = 0;
00613 fd_set lreadset, lwriteset, lexceptset;
00614 struct lwip_socket *p_sock;
00615
00616 FD_ZERO(&lreadset);
00617 FD_ZERO(&lwriteset);
00618 FD_ZERO(&lexceptset);
00619
00620
00621
00622 for(i = 0; i < maxfdp1; i++)
00623 {
00624 if(FD_ISSET(i, readset))
00625 {
00626
00627 p_sock = get_socket(i);
00628 if (p_sock && (p_sock->lastdata || p_sock->rcvevent))
00629 {
00630 FD_SET(i, &lreadset);
00631 DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i));
00632 nready++;
00633 }
00634 }
00635 if(FD_ISSET(i, writeset))
00636 {
00637
00638 p_sock = get_socket(i);
00639 if (p_sock && p_sock->sendevent)
00640 {
00641 FD_SET(i, &lwriteset);
00642 DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for writing\n", i));
00643 nready++;
00644 }
00645 }
00646 }
00647 *readset = lreadset;
00648 *writeset = lwriteset;
00649 FD_ZERO(exceptset);
00650
00651 return nready;
00652 }
00653
00654
00655
00656 int
00657 lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
00658 struct timeval *timeout)
00659 {
00660 int i;
00661 int nready;
00662 fd_set lreadset, lwriteset, lexceptset;
00663 u32_t msectimeout;
00664 struct lwip_select_cb select_cb;
00665 struct lwip_select_cb *p_selcb;
00666
00667 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));
00668 select_cb.next = 0;
00669 select_cb.readset = readset;
00670 select_cb.writeset = writeset;
00671 select_cb.exceptset = exceptset;
00672 select_cb.sem_signalled = 0;
00673
00674
00675 if (!selectsem)
00676 selectsem = sys_sem_new(1);
00677 sys_sem_wait(selectsem);
00678
00679 if (readset)
00680 lreadset = *readset;
00681 else
00682 FD_ZERO(&lreadset);
00683 if (writeset)
00684 lwriteset = *writeset;
00685 else
00686 FD_ZERO(&lwriteset);
00687 if (exceptset)
00688 lexceptset = *exceptset;
00689 else
00690 FD_ZERO(&lexceptset);
00691
00692
00693
00694 nready = lwip_selscan(maxfdp1, &lreadset, &lwriteset, &lexceptset);
00695
00696
00697 if (!nready)
00698 {
00699 if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
00700 {
00701 sys_sem_signal(selectsem);
00702 if (readset)
00703 FD_ZERO(readset);
00704 if (writeset)
00705 FD_ZERO(writeset);
00706 if (exceptset)
00707 FD_ZERO(exceptset);
00708
00709 DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n"));
00710 set_errno(0);
00711 return 0;
00712 }
00713
00714
00715
00716
00717
00718
00719 select_cb.sem = sys_sem_new(0);
00720
00721
00722 select_cb.next = select_cb_list;
00723 select_cb_list = &select_cb;
00724
00725
00726 sys_sem_signal(selectsem);
00727
00728
00729 if (timeout == 0)
00730
00731 msectimeout = 0;
00732 else
00733 msectimeout = ((timeout->tv_sec * 1000) + (timeout->tv_usec /1000));
00734
00735 i = sys_sem_wait_timeout(select_cb.sem, msectimeout);
00736
00737
00738 sys_sem_wait(selectsem);
00739 if (select_cb_list == &select_cb)
00740 select_cb_list = select_cb.next;
00741 else
00742 for (p_selcb = select_cb_list; p_selcb; p_selcb = p_selcb->next)
00743 if (p_selcb->next == &select_cb)
00744 {
00745 p_selcb->next = select_cb.next;
00746 break;
00747 }
00748
00749 sys_sem_signal(selectsem);
00750
00751 sys_sem_free(select_cb.sem);
00752 if (i == 0)
00753 {
00754 if (readset)
00755 FD_ZERO(readset);
00756 if (writeset)
00757 FD_ZERO(writeset);
00758 if (exceptset)
00759 FD_ZERO(exceptset);
00760 DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n"));
00761 set_errno(0);
00762 return 0;
00763 }
00764
00765 if (readset)
00766 lreadset = *readset;
00767 else
00768 FD_ZERO(&lreadset);
00769 if (writeset)
00770 lwriteset = *writeset;
00771 else
00772 FD_ZERO(&lwriteset);
00773 if (exceptset)
00774 lexceptset = *exceptset;
00775 else
00776 FD_ZERO(&lexceptset);
00777
00778
00779 nready = lwip_selscan(maxfdp1, &lreadset, &lwriteset, &lexceptset);
00780 }
00781 else
00782 sys_sem_signal(selectsem);
00783
00784 if (readset)
00785 *readset = lreadset;
00786 if (writeset)
00787 *writeset = lwriteset;
00788 if (exceptset)
00789 *exceptset = lexceptset;
00790 DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready));
00791 set_errno(0);
00792 return nready;
00793 }
00794
00795
00796 static void
00797 event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
00798 {
00799 int s;
00800 struct lwip_socket *sock;
00801 struct lwip_select_cb *scb;
00802
00803
00804 if (conn)
00805 {
00806 s = conn->socket;
00807 if (s < 0)
00808 {
00809
00810
00811
00812
00813
00814 if (evt == NETCONN_EVT_RCVPLUS)
00815 conn->socket--;
00816 return;
00817 }
00818
00819 sock = get_socket(s);
00820 if (!sock)
00821 return;
00822 }
00823 else
00824 return;
00825
00826 if (!selectsem)
00827 selectsem = sys_sem_new(1);
00828
00829 sys_sem_wait(selectsem);
00830
00831 switch (evt)
00832 {
00833 case NETCONN_EVT_RCVPLUS:
00834 sock->rcvevent++;
00835 break;
00836 case NETCONN_EVT_RCVMINUS:
00837 sock->rcvevent--;
00838 break;
00839 case NETCONN_EVT_SENDPLUS:
00840 sock->sendevent = 1;
00841 break;
00842 case NETCONN_EVT_SENDMINUS:
00843 sock->sendevent = 0;
00844 break;
00845 }
00846 sys_sem_signal(selectsem);
00847
00848
00849
00850
00851
00852
00853
00854
00855 while (1)
00856 {
00857 sys_sem_wait(selectsem);
00858 for (scb = select_cb_list; scb; scb = scb->next)
00859 {
00860 if (scb->sem_signalled == 0)
00861 {
00862
00863 if (scb->readset && FD_ISSET(s, scb->readset))
00864 if (sock->rcvevent)
00865 break;
00866 if (scb->writeset && FD_ISSET(s, scb->writeset))
00867 if (sock->sendevent)
00868 break;
00869 }
00870 }
00871 if (scb)
00872 {
00873 scb->sem_signalled = 1;
00874 sys_sem_signal(selectsem);
00875 sys_sem_signal(scb->sem);
00876 } else {
00877 sys_sem_signal(selectsem);
00878 break;
00879 }
00880 }
00881
00882 }
00883
00884
00885
00886
00887 int lwip_shutdown(int s, int how)
00888 {
00889 DEBUGF(SOCKETS_DEBUG, ("lwip_shutdown(%d, how=%d)\n", s, how));
00890 return lwip_close(s);
00891 }
00892
00893 int lwip_getpeername (int s, struct sockaddr *name, socklen_t *namelen)
00894 {
00895 struct lwip_socket *sock;
00896 struct sockaddr_in sin;
00897 struct ip_addr naddr;
00898
00899 sock = get_socket(s);
00900 if(!sock) {
00901 return -1;
00902 }
00903
00904 memset(&sin, 0, sizeof(sin));
00905 sin.sin_len = sizeof(sin);
00906 sin.sin_family = AF_INET;
00907
00908
00909 netconn_peer(sock->conn, &naddr, &sin.sin_port);
00910
00911 #if SOCKETS_DEBUG
00912 DEBUGF(SOCKETS_DEBUG, ("lwip_getpeername(%d, addr=", s));
00913 ip_addr_debug_print(&naddr);
00914 DEBUGF(SOCKETS_DEBUG, (" port=%d)\n", sin.sin_port));
00915 #endif
00916
00917 sin.sin_port = htons(sin.sin_port);
00918 sin.sin_addr.s_addr = naddr.addr;
00919
00920 if(*namelen > sizeof(sin))
00921 *namelen = sizeof(sin);
00922
00923 memcpy(name, &sin, *namelen);
00924 sock_set_errno(sock, 0);
00925 return 0;
00926 }
00927
00928 int lwip_getsockname (int s, struct sockaddr *name, socklen_t *namelen)
00929 {
00930 struct lwip_socket *sock;
00931 struct sockaddr_in sin;
00932 struct ip_addr *naddr;
00933
00934 sock = get_socket(s);
00935 if(!sock) {
00936 return -1;
00937 }
00938
00939 memset(&sin, 0, sizeof(sin));
00940 sin.sin_len = sizeof(sin);
00941 sin.sin_family = AF_INET;
00942
00943
00944 netconn_addr(sock->conn, &naddr, &sin.sin_port);
00945
00946 #if SOCKETS_DEBUG
00947 DEBUGF(SOCKETS_DEBUG, ("lwip_getsockname(%d, addr=", s));
00948 ip_addr_debug_print(naddr);
00949 DEBUGF(SOCKETS_DEBUG, (" port=%d)\n", sin.sin_port));
00950 #endif
00951
00952 sin.sin_port = htons(sin.sin_port);
00953 sin.sin_addr.s_addr = naddr->addr;
00954
00955 if(*namelen > sizeof(sin))
00956 *namelen = sizeof(sin);
00957
00958 memcpy(name, &sin, *namelen);
00959 sock_set_errno(sock, 0);
00960 return 0;
00961 }
00962
00963 int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen)
00964 {
00965 int err = ENOSYS;
00966 struct lwip_socket *sock = get_socket(s);
00967
00968 if(!sock) {
00969 return -1;
00970 }
00971
00972 if(level == SOL_SOCKET) {
00973 switch(optname) {
00974 case SO_ERROR:
00975 if(!optval || !optlen || (*optlen != sizeof(int))) {
00976 err = EINVAL;
00977 break;
00978 }
00979 *(int *)optval = sock->err;
00980 sock->err = 0;
00981 DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", s, *(int *)optval));
00982 err = 0;
00983 break;
00984 default:
00985 DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", s, optname));
00986 break;
00987 }
00988 } else {
00989 DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", s, level, optname));
00990 }
00991 sock_set_errno(sock, err);
00992 return err ? -1 : 0;
00993 }
00994
00995 int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen)
00996 {
00997 struct lwip_socket *sock = get_socket(s);
00998 int err = ENOSYS;
00999
01000 if(!sock) {
01001 return -1;
01002 }
01003
01004 if(level == SOL_SOCKET) {
01005 switch(optname) {
01006 case SO_REUSEADDR:
01007 DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, SO_REUSEADDR, ..)\n", s));
01008
01009 err = 0;
01010 break;
01011 default:
01012 DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", s, optname));
01013 break;
01014 }
01015 } else {
01016 DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", s, level, optname));
01017 }
01018
01019 sock_set_errno(sock, err);
01020 return err ? -1 : 0;
01021 }
01022
01023 int lwip_ioctl(int s, long cmd, void *argp)
01024 {
01025 struct lwip_socket *sock = get_socket(s);
01026
01027 if(!sock) {
01028 return -1;
01029 }
01030
01031 switch(cmd) {
01032 case FIONREAD:
01033 if(!argp) {
01034 sock_set_errno(sock, EINVAL);
01035 return -1;
01036 }
01037
01038 *((u16_t*)argp) = sock->conn->recv_avail;
01039
01040 DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %u\n", s, argp, *((u16_t*)argp)));
01041 sock_set_errno(sock, 0);
01042 return 0;
01043
01044 case FIONBIO:
01045 if(argp && *(u32_t*)argp)
01046 sock->flags |= O_NONBLOCK;
01047 else
01048 sock->flags &= ~O_NONBLOCK;
01049 DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, !!(sock->flags & O_NONBLOCK)));
01050 sock_set_errno(sock, 0);
01051 return 0;
01052
01053 default:
01054 DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp));
01055 sock_set_errno(sock, ENOSYS);
01056 return -1;
01057 }
01058 }
01059