📄 sockets.c
字号:
} } if (do_signal) { scb->sem_signalled = 1; /* Don't call SYS_ARCH_UNPROTECT() before signaling the semaphore, as this might lead to the select thread taking itself off the list, invalidagin the semaphore. */ sys_sem_signal(&scb->sem); } } /* unlock interrupts with each step */ last_select_cb_ctr = select_cb_ctr; SYS_ARCH_UNPROTECT(lev); /* this makes sure interrupt protection time is short */ SYS_ARCH_PROTECT(lev); if (last_select_cb_ctr != select_cb_ctr) { /* someone has changed select_cb_list, restart at the beginning */ goto again; } } SYS_ARCH_UNPROTECT(lev);}/** * Unimplemented: Close one end of a full-duplex connection. * Currently, the full connection is closed. */intlwip_shutdown(int s, int how){ struct lwip_sock *sock; err_t err; u8_t shut_rx = 0, shut_tx = 0; LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_shutdown(%d, how=%d)\n", s, how)); sock = get_socket(s); if (!sock) { return -1; } if (sock->conn != NULL) { if (netconn_type(sock->conn) != NETCONN_TCP) { sock_set_errno(sock, EOPNOTSUPP); return EOPNOTSUPP; } } else { sock_set_errno(sock, ENOTCONN); return ENOTCONN; } if (how == SHUT_RD) { shut_rx = 1; } else if (how == SHUT_WR) { shut_tx = 1; } else if(how == SHUT_RDWR) { shut_rx = 1; shut_tx = 1; } else { sock_set_errno(sock, EINVAL); return EINVAL; } err = netconn_shutdown(sock->conn, shut_rx, shut_tx); sock_set_errno(sock, err_to_errno(err)); return (err == ERR_OK ? 0 : -1);}static intlwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local){ struct lwip_sock *sock; struct sockaddr_in sin; ip_addr_t 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 */ netconn_getaddr(sock->conn, &naddr, &sin.sin_port, local); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getaddrname(%d, addr=", s)); ip_addr_debug_print(SOCKETS_DEBUG, &naddr); LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", sin.sin_port)); sin.sin_port = htons(sin.sin_port); inet_addr_from_ipaddr(&sin.sin_addr, &naddr); if (*namelen > sizeof(sin)) { *namelen = sizeof(sin); } MEMCPY(name, &sin, *namelen); sock_set_errno(sock, 0); return 0;}intlwip_getpeername(int s, struct sockaddr *name, socklen_t *namelen){ return lwip_getaddrname(s, name, namelen, 0);}intlwip_getsockname(int s, struct sockaddr *name, socklen_t *namelen){ return lwip_getaddrname(s, name, namelen, 1);}intlwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen){ err_t err = ERR_OK; struct lwip_sock *sock = get_socket(s); struct lwip_setgetsockopt_data data; if (!sock) { return -1; } if ((NULL == optval) || (NULL == optlen)) { sock_set_errno(sock, EFAULT); return -1; } /* Do length and type checks for the various options first, to keep it readable. */ switch (level) { /* Level: SOL_SOCKET */ case SOL_SOCKET: switch (optname) { case SO_ACCEPTCONN: case SO_BROADCAST: /* UNIMPL case SO_DEBUG: */ /* UNIMPL case SO_DONTROUTE: */ case SO_ERROR: case SO_KEEPALIVE: /* UNIMPL case SO_CONTIMEO: */ /* UNIMPL case SO_SNDTIMEO: */#if LWIP_SO_RCVTIMEO case SO_RCVTIMEO:#endif /* LWIP_SO_RCVTIMEO */#if LWIP_SO_RCVBUF case SO_RCVBUF:#endif /* LWIP_SO_RCVBUF */ /* UNIMPL case SO_OOBINLINE: */ /* UNIMPL case SO_SNDBUF: */ /* UNIMPL case SO_RCVLOWAT: */ /* UNIMPL case SO_SNDLOWAT: */#if SO_REUSE case SO_REUSEADDR: case SO_REUSEPORT:#endif /* SO_REUSE */ case SO_TYPE: /* UNIMPL case SO_USELOOPBACK: */ if (*optlen < sizeof(int)) { err = EINVAL; } break; case SO_NO_CHECK: if (*optlen < sizeof(int)) { err = EINVAL; }#if LWIP_UDP if ((sock->conn->type != NETCONN_UDP) || ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0)) { /* this flag is only available for UDP, not for UDP lite */ err = EAFNOSUPPORT; }#endif /* LWIP_UDP */ break; default: LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", s, optname)); err = ENOPROTOOPT; } /* switch (optname) */ break; /* Level: IPPROTO_IP */ case IPPROTO_IP: switch (optname) { /* UNIMPL case IP_HDRINCL: */ /* UNIMPL case IP_RCVDSTADDR: */ /* UNIMPL case IP_RCVIF: */ case IP_TTL: case IP_TOS: if (*optlen < sizeof(int)) { err = EINVAL; } break;#if LWIP_IGMP case IP_MULTICAST_TTL: if (*optlen < sizeof(u8_t)) { err = EINVAL; } break; case IP_MULTICAST_IF: if (*optlen < sizeof(struct in_addr)) { err = EINVAL; } break; case IP_MULTICAST_LOOP: if (*optlen < sizeof(u8_t)) { err = EINVAL; } if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) { err = EAFNOSUPPORT; } break;#endif /* LWIP_IGMP */ default: LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", s, optname)); err = ENOPROTOOPT; } /* switch (optname) */ break; #if LWIP_TCP/* Level: IPPROTO_TCP */ case IPPROTO_TCP: if (*optlen < sizeof(int)) { err = EINVAL; break; } /* If this is no TCP socket, ignore any options. */ if (sock->conn->type != NETCONN_TCP) return 0; switch (optname) { case TCP_NODELAY: case TCP_KEEPALIVE:#if LWIP_TCP_KEEPALIVE case TCP_KEEPIDLE: case TCP_KEEPINTVL: case TCP_KEEPCNT:#endif /* LWIP_TCP_KEEPALIVE */ break; default: LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", s, optname)); err = ENOPROTOOPT; } /* switch (optname) */ break;#endif /* LWIP_TCP */#if LWIP_UDP && LWIP_UDPLITE/* Level: IPPROTO_UDPLITE */ case IPPROTO_UDPLITE: if (*optlen < sizeof(int)) { err = EINVAL; break; } /* If this is no UDP lite socket, ignore any options. */ if (sock->conn->type != NETCONN_UDPLITE) { return 0; } switch (optname) { case UDPLITE_SEND_CSCOV: case UDPLITE_RECV_CSCOV: break; default: LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n", s, optname)); err = ENOPROTOOPT; } /* switch (optname) */ break;#endif /* LWIP_UDP && LWIP_UDPLITE*//* UNDEFINED LEVEL */ default: LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", s, level, optname)); err = ENOPROTOOPT; } /* switch */ if (err != ERR_OK) { sock_set_errno(sock, err); return -1; } /* Now do the actual option processing */ data.sock = sock;#ifdef LWIP_DEBUG data.s = s;#endif /* LWIP_DEBUG */ data.level = level; data.optname = optname; data.optval = optval; data.optlen = optlen; data.err = err; tcpip_callback(lwip_getsockopt_internal, &data); sys_arch_sem_wait(&sock->conn->op_completed, 0); /* maybe lwip_getsockopt_internal has changed err */ err = data.err; sock_set_errno(sock, err); return err ? -1 : 0;}static voidlwip_getsockopt_internal(void *arg){ struct lwip_sock *sock;#ifdef LWIP_DEBUG int s;#endif /* LWIP_DEBUG */ int level, optname; void *optval; struct lwip_setgetsockopt_data *data; LWIP_ASSERT("arg != NULL", arg != NULL); data = (struct lwip_setgetsockopt_data*)arg; sock = data->sock;#ifdef LWIP_DEBUG s = data->s;#endif /* LWIP_DEBUG */ level = data->level; optname = data->optname; optval = data->optval; switch (level) {/* Level: SOL_SOCKET */ case SOL_SOCKET: switch (optname) { /* The option flags */ case SO_ACCEPTCONN: case SO_BROADCAST: /* UNIMPL case SO_DEBUG: */ /* UNIMPL case SO_DONTROUTE: */ case SO_KEEPALIVE: /* UNIMPL case SO_OOBINCLUDE: */#if SO_REUSE case SO_REUSEADDR: case SO_REUSEPORT:#endif /* SO_REUSE */ /*case SO_USELOOPBACK: UNIMPL */ *(int*)optval = sock->conn->pcb.ip->so_options & optname; LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, optname=0x%x, ..) = %s\n", s, optname, (*(int*)optval?"on":"off"))); break; case SO_TYPE: switch (NETCONNTYPE_GROUP(sock->conn->type)) { case NETCONN_RAW: *(int*)optval = SOCK_RAW; break; case NETCONN_TCP: *(int*)optval = SOCK_STREAM; break; case NETCONN_UDP: *(int*)optval = SOCK_DGRAM; break; default: /* unrecognized socket type */ *(int*)optval = sock->conn->type; LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n", s, *(int *)optval)); } /* switch (sock->conn->type) */ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n", s, *(int *)optval)); break; case SO_ERROR: /* only overwrite ERR_OK or tempoary errors */ if ((sock->err == 0) || (sock->err == EINPROGRESS)) { sock_set_errno(sock, err_to_errno(sock->conn->last_err)); } *(int *)optval = sock->err; sock->err = 0; LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", s, *(int *)optval)); break;#if LWIP_SO_RCVTIMEO case SO_RCVTIMEO: *(int *)optval = netconn_get_recvtimeout(sock->conn); break;#endif /* LWIP_SO_RCVTIMEO */#if LWIP_SO_RCVBUF case SO_RCVBUF: *(int *)optval = netconn_get_recvbufsize(sock->conn); break;#endif /* LWIP_SO_RCVBUF */#if LWIP_UDP case SO_NO_CHECK: *(int*)optval = (udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_NOCHKSUM) ? 1 : 0; break;#endif /* LWIP_UDP*/ default: LWIP_ASSERT("unhandled optname", 0); break; } /* switch (optname) */ break;/* Level: IPPROTO_IP */ case IPPROTO_IP: switch (optname) { case IP_TTL: *(int*)optval = sock->conn->pcb.ip->ttl; LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TTL) = %d\n", s, *(int *)optval)); break; case IP_TOS: *(int*)optval = sock->conn->pcb.ip->tos; LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n", s, *(int *)optval)); break;#if LWIP_IGMP case IP_MULTICAST_TTL: *(u8_t*)optval = sock->conn->pcb.ip->ttl; LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_TTL) = %d\n", s, *(int *)optval)); break; case IP_MULTICAST_IF: inet_addr_from_ipaddr((struct in_addr*)optval, &sock->conn->pcb.udp->multicast_ip); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_IF) = 0x%"X32_F"\n", s, *(u32_t *)optval)); break; case IP_MULTICAST_LOOP: if ((sock->conn->pcb.udp->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) { *(u8_t*)optval = 1; } else { *(u8_t*)optval = 0; } LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_LOOP) = %d\n", s, *(int *)optval));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -