📄 sockets.c
字号:
sock = get_socket(s); if(!sock) { return -1; } /* get the peer if currently connected */ connected = (netconn_peer(sock->conn, &addr, &port) == ERR_OK); remote_addr.addr = ((struct sockaddr_in *)to)->sin_addr.s_addr; remote_port = ((struct sockaddr_in *)to)->sin_port;#if SOCKETS_DEBUG DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, size=%d, flags=0x%x to=", s, data, size, flags)); ip_addr_debug_print(&remote_addr); DEBUGF(SOCKETS_DEBUG, (" port=%u\n", ntohs(remote_port)));#endif netconn_connect(sock->conn, &remote_addr, ntohs(remote_port)); ret = lwip_send(s, data, size, flags); /* reset the remote address and port number of the connection */ if(connected) netconn_connect(sock->conn, &addr, port); else netconn_disconnect(sock->conn); return ret;}/*-----------------------------------------------------------------------------------*/intlwip_socket(int domain, int type, int protocol){ struct netconn *conn; int i; /* create a netconn */ switch(type) { case SOCK_DGRAM: conn = netconn_new_with_callback(NETCONN_UDP, event_callback); DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ", domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); break; case SOCK_STREAM: conn = netconn_new_with_callback(NETCONN_TCP, event_callback); DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_STREAM, %d) = ", domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); break; default: DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%d, %d/UNKNOWN, %d) = -1\n", domain, type, protocol)); set_errno(EINVAL); return -1; } if(!conn) { DEBUGF(SOCKETS_DEBUG, ("-1 / ENOBUFS (could not create netconn)\n")); set_errno(ENOBUFS); return -1; } i = alloc_socket(conn); if(i == -1) { netconn_delete(conn); set_errno(ENOBUFS); return -1; } conn->socket = i; DEBUGF(SOCKETS_DEBUG, ("%d\n", i)); set_errno(0); return i;}/*-----------------------------------------------------------------------------------*/intlwip_write(int s, void *data, int size){ return lwip_send(s, data, size, 0);}/*-----------------------------------------------------------------------------------*/static intlwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset){ int i, nready = 0; fd_set lreadset, lwriteset, lexceptset; struct lwip_socket *p_sock; FD_ZERO(&lreadset); FD_ZERO(&lwriteset); FD_ZERO(&lexceptset); /* Go through each socket in each list to count number of sockets which currently match */ for(i = 0; i < maxfdp1; i++) { if(FD_ISSET(i, readset)) { /* See if netconn of this socket is ready for read */ p_sock = get_socket(i); if (p_sock && (p_sock->lastdata || p_sock->rcvevent)) { FD_SET(i, &lreadset); DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i)); nready++; } } if(FD_ISSET(i, writeset)) { /* See if netconn of this socket is ready for write */ p_sock = get_socket(i); if (p_sock && p_sock->sendevent) { FD_SET(i, &lwriteset); DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for writing\n", i)); nready++; } } } *readset = lreadset; *writeset = lwriteset; FD_ZERO(exceptset); return nready;}/*-----------------------------------------------------------------------------------*/intlwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, struct timeval *timeout){ int i; int nready; fd_set lreadset, lwriteset, lexceptset; u32_t msectimeout; struct lwip_select_cb select_cb; struct lwip_select_cb *p_selcb; 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)); select_cb.next = 0; select_cb.readset = readset; select_cb.writeset = writeset; select_cb.exceptset = exceptset; select_cb.sem_signalled = 0; /* Protect ourselves searching through the list */ if (!selectsem) selectsem = sys_sem_new(1); sys_sem_wait(selectsem); if (readset) lreadset = *readset; else FD_ZERO(&lreadset); if (writeset) lwriteset = *writeset; else FD_ZERO(&lwriteset); if (exceptset) lexceptset = *exceptset; else FD_ZERO(&lexceptset); /* Go through each socket in each list to count number of sockets which currently match */ nready = lwip_selscan(maxfdp1, &lreadset, &lwriteset, &lexceptset); /* If we don't have any current events, then suspend if we are supposed to */ if (!nready) { if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) { sys_sem_signal(selectsem); if (readset) FD_ZERO(readset); if (writeset) FD_ZERO(writeset); if (exceptset) FD_ZERO(exceptset); DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n")); set_errno(0); return 0; } /* add our semaphore to list */ /* We don't actually need any dynamic memory. Our entry on the * list is only valid while we are in this function, so it's ok * to use local variables */ select_cb.sem = sys_sem_new(0); /* Note that we are still protected */ /* Put this select_cb on top of list */ select_cb.next = select_cb_list; select_cb_list = &select_cb; /* Now we can safely unprotect */ sys_sem_signal(selectsem); /* Now just wait to be woken */ if (timeout == 0) /* Wait forever */ msectimeout = 0; else msectimeout = ((timeout->tv_sec * 1000) + (timeout->tv_usec /1000)); i = sys_sem_wait_timeout(select_cb.sem, msectimeout); /* Take us off the list */ sys_sem_wait(selectsem); if (select_cb_list == &select_cb) select_cb_list = select_cb.next; else for (p_selcb = select_cb_list; p_selcb; p_selcb = p_selcb->next) if (p_selcb->next == &select_cb) { p_selcb->next = select_cb.next; break; } sys_sem_signal(selectsem); sys_sem_free(select_cb.sem); if (i == 0) /* Timeout */ { if (readset) FD_ZERO(readset); if (writeset) FD_ZERO(writeset); if (exceptset) FD_ZERO(exceptset); DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n")); set_errno(0); return 0; } if (readset) lreadset = *readset; else FD_ZERO(&lreadset); if (writeset) lwriteset = *writeset; else FD_ZERO(&lwriteset); if (exceptset) lexceptset = *exceptset; else FD_ZERO(&lexceptset); /* See what's set */ nready = lwip_selscan(maxfdp1, &lreadset, &lwriteset, &lexceptset); } else sys_sem_signal(selectsem); if (readset) *readset = lreadset; if (writeset) *writeset = lwriteset; if (exceptset) *exceptset = lexceptset; DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready)); set_errno(0); return nready;}/*-----------------------------------------------------------------------------------*/static voidevent_callback(struct netconn *conn, enum netconn_evt evt, u16_t len){ int s; struct lwip_socket *sock; struct lwip_select_cb *scb; /* Get socket */ if (conn) { s = conn->socket; if (s < 0) { /* Data comes in right away after an accept, even though * the server task might not have created a new socket yet. * Just count down (or up) if that's the case and we * will use the data later. Note that only receive events * can happen before the new socket is set up. */ if (evt == NETCONN_EVT_RCVPLUS) conn->socket--; return; } sock = get_socket(s); if (!sock) return; } else return; if (!selectsem) selectsem = sys_sem_new(1); sys_sem_wait(selectsem); /* Set event as required */ switch (evt) { case NETCONN_EVT_RCVPLUS: sock->rcvevent++; break; case NETCONN_EVT_RCVMINUS: sock->rcvevent--; break; case NETCONN_EVT_SENDPLUS: sock->sendevent = 1; break; case NETCONN_EVT_SENDMINUS: sock->sendevent = 0; break; } sys_sem_signal(selectsem); /* Now decide if anyone is waiting for this socket */ /* NOTE: This code is written this way to protect the select link list but to avoid a deadlock situation by releasing socksem before signalling for the select. This means we need to go through the list multiple times ONLY IF a select was actually waiting. We go through the list the number of waiting select calls + 1. This list is expected to be small. */ while (1) { sys_sem_wait(selectsem); for (scb = select_cb_list; scb; scb = scb->next) { if (scb->sem_signalled == 0) { /* Test this select call for our socket */ if (scb->readset && FD_ISSET(s, scb->readset)) if (sock->rcvevent) break; if (scb->writeset && FD_ISSET(s, scb->writeset)) if (sock->sendevent) break; } } if (scb) { scb->sem_signalled = 1; sys_sem_signal(selectsem); sys_sem_signal(scb->sem); } else { sys_sem_signal(selectsem); break; } } }/*-----------------------------------------------------------------------------------*/int lwip_shutdown(int s, int how){ DEBUGF(SOCKETS_DEBUG, ("lwip_shutdown(%d, how=%d)\n", s, how)); return lwip_close(s); /* XXX temporary hack until proper implementation */}int lwip_getpeername (int s, struct sockaddr *name, socklen_t *namelen){ struct lwip_socket *sock; struct sockaddr_in sin; struct ip_addr naddr; sock = get_socket(s); if(!sock) { return -1; } memset(&sin, 0, sizeof(sin)); sin.sin_len = sizeof(sin); sin.sin_family = AF_INET; /* get the IP address and port of the remote host */ netconn_peer(sock->conn, &naddr, &sin.sin_port); #if SOCKETS_DEBUG DEBUGF(SOCKETS_DEBUG, ("lwip_getpeername(%d, addr=", s)); ip_addr_debug_print(&naddr); DEBUGF(SOCKETS_DEBUG, (" port=%d)\n", sin.sin_port));#endif sin.sin_port = htons(sin.sin_port); sin.sin_addr.s_addr = naddr.addr; if(*namelen > sizeof(sin)) *namelen = sizeof(sin); memcpy(name, &sin, *namelen); sock_set_errno(sock, 0); return 0;}int lwip_getsockname (int s, struct sockaddr *name, socklen_t *namelen){ struct lwip_socket *sock; struct sockaddr_in sin; struct ip_addr *naddr; sock = get_socket(s); if(!sock) { return -1; } memset(&sin, 0, sizeof(sin)); sin.sin_len = sizeof(sin); sin.sin_family = AF_INET; /* get the IP address and port of the remote host */ netconn_addr(sock->conn, &naddr, &sin.sin_port);#if SOCKETS_DEBUG DEBUGF(SOCKETS_DEBUG, ("lwip_getsockname(%d, addr=", s)); ip_addr_debug_print(naddr); DEBUGF(SOCKETS_DEBUG, (" port=%d)\n", sin.sin_port));#endif sin.sin_port = htons(sin.sin_port); sin.sin_addr.s_addr = naddr->addr; if(*namelen > sizeof(sin)) *namelen = sizeof(sin); memcpy(name, &sin, *namelen); sock_set_errno(sock, 0); return 0;}int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen){ int err = ENOSYS; struct lwip_socket *sock = get_socket(s); if(!sock) { return -1; } if(level == SOL_SOCKET) { switch(optname) { case SO_ERROR: if(!optval || !optlen || (*optlen != sizeof(int))) { err = EINVAL; break; } *(int *)optval = sock->err; sock->err = 0; DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", s, *(int *)optval)); err = 0; break; default: DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", s, optname)); break; } } else { DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", s, level, optname)); } sock_set_errno(sock, err); return err ? -1 : 0;}int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen){ struct lwip_socket *sock = get_socket(s); int err = ENOSYS; if(!sock) { return -1; } if(level == SOL_SOCKET) { switch(optname) { case SO_REUSEADDR: DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, SO_REUSEADDR, ..)\n", s)); /* XXX just pretend we support this for now */ err = 0; break; default: DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", s, optname)); break; } } else { DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", s, level, optname)); } sock_set_errno(sock, err); return err ? -1 : 0;}int lwip_ioctl(int s, long cmd, void *argp){ struct lwip_socket *sock = get_socket(s); if(!sock) { return -1; } switch(cmd) { case FIONREAD: if(!argp) { sock_set_errno(sock, EINVAL); return -1; } *((u16_t*)argp) = sock->conn->recv_avail; DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %u\n", s, argp, *((u16_t*)argp))); sock_set_errno(sock, 0); return 0; case FIONBIO: if(argp && *(u32_t*)argp) sock->flags |= O_NONBLOCK; else sock->flags &= ~O_NONBLOCK; DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, !!(sock->flags & O_NONBLOCK))); sock_set_errno(sock, 0); return 0; default: DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp)); sock_set_errno(sock, ENOSYS); /* not yet implemented */ return -1; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -