?? sockets.c
字號:
}intlwip_recv(int s, void *mem, int len, unsigned int flags){ return lwip_recvfrom(s, mem, len, flags, NULL, NULL);}intlwip_send(int s, void *data, int size, unsigned int flags){ struct lwip_socket *sock; struct netbuf *buf; err_t err; LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d, data=%p, size=%d, flags=0x%x)\n", s, data, size, flags)); sock = get_socket(s); if (!sock) { set_errno(EBADF); return -1; } switch (netconn_type(sock->conn)) { case NETCONN_RAW: case NETCONN_UDP: case NETCONN_UDPLITE: case NETCONN_UDPNOCHKSUM: /* create a buffer */ buf = netbuf_new(); if (!buf) { LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) ENOBUFS\n", s)); sock_set_errno(sock, ENOBUFS); return -1; } /* make the buffer point to the data that should be sent */ netbuf_ref(buf, data, size); /* send the data */ err = netconn_send(sock->conn, buf); /* deallocated the buffer */ netbuf_delete(buf); break; case NETCONN_TCP: err = netconn_write(sock->conn, data, size, NETCONN_COPY); break; default: err = ERR_ARG; break; } if (err != ERR_OK) { LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d\n", s, err)); sock_set_errno(sock, err_to_errno(err)); return -1; } LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) ok size=%d\n", s, size)); sock_set_errno(sock, 0); return size;}intlwip_sendto(int s, void *data, int size, unsigned int flags, struct sockaddr *to, socklen_t tolen){ struct lwip_socket *sock; struct ip_addr remote_addr, addr; u16_t remote_port, port; int ret,connected; sock = get_socket(s); if (!sock) { set_errno(EBADF); 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; LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, size=%d, flags=0x%x to=", s, data, size, flags)); ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr); LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u\n", ntohs(remote_port))); 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_RAW: conn = netconn_new_with_proto_and_callback(NETCONN_RAW, protocol, event_callback); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); break; case SOCK_DGRAM: conn = netconn_new_with_callback(NETCONN_UDP, event_callback); LWIP_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); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_STREAM, %d) = ", domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); break; default: LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%d, %d/UNKNOWN, %d) = -1\n", domain, type, protocol)); set_errno(EINVAL); return -1; } if (!conn) { LWIP_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; LWIP_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); LWIP_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); LWIP_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; 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)); 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); LWIP_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 + 500)/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); LWIP_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; LWIP_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){ LWIP_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) { set_errno(EBADF); return -1;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -