diff --git a/CHANGELOG b/CHANGELOG index 3574830d..2ac1830a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -460,6 +460,11 @@ HISTORY ++ Bug fixes: + 2007-11-12 Frédéric Bernon + * sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c: Fixed bug #20900. Now, most + of the netconn_peer and netconn_addr processing is done inside tcpip_thread + context in do_getaddr. + 2007-11-10 Simon Goldschmidt * etharp.c: Fixed bug: assert fired when MEMP_ARP_QUEUE was empty (which can happen any time). Now the packet simply isn't enqueued when out of memory. diff --git a/src/api/api_lib.c b/src/api/api_lib.c index 0d55059f..4762c551 100644 --- a/src/api/api_lib.c +++ b/src/api/api_lib.c @@ -179,93 +179,32 @@ netconn_type(struct netconn *conn) } /** - * Get the current perr a netconn is connected to. - * This might only be temporary for UDP netconns, - * doesn't work for RAW netconns and returns garbage - * if called for a TCP listen netconn. - * - * @param conn the netconn to query - * @param addr a pointer to which to save the remote IP address - * @param port a pointer to which to save the remote port - * @return ERR_CONN for invalid connections - * ERR_OK if the information was retrieved - */ -err_t -netconn_peer(struct netconn *conn, struct ip_addr *addr, u16_t *port) -{ - LWIP_ERROR("netconn_peer: invalid conn", (conn != NULL), return ERR_ARG;); - LWIP_ERROR("netconn_peer: invalid addr", (addr != NULL), return ERR_ARG;); - LWIP_ERROR("netconn_peer: invalid port", (port != NULL), return ERR_ARG;); - - /* Not a good safe-thread protection, will be improved */ - if (conn->pcb.ip == NULL) - return ERR_CONN; - - *addr = conn->pcb.ip->remote_ip; - - switch (NETCONNTYPE_GROUP(conn->type)) { -#if LWIP_RAW - case NETCONN_RAW: - /* return an error as connecting is only a helper for upper layers */ - return ERR_CONN; -#endif /* LWIP_RAW */ -#if LWIP_UDP - case NETCONN_UDP: - if ((conn->pcb.udp->flags & UDP_FLAGS_CONNECTED) == 0) - return ERR_CONN; - *port = conn->pcb.udp->remote_port; - break; -#endif /* LWIP_UDP */ -#if LWIP_TCP - case NETCONN_TCP: - *port = conn->pcb.tcp->remote_port; - break; -#endif /* LWIP_TCP */ - } - return ERR_OK; -} - -/** - * Get the local IP address and port of a netconn. + * Get the local or remote IP address and port of a netconn. * For RAW netconns, this returns the protocol instead of a port! * * @param conn the netconn to query - * @param addr a pointer to which to save the local IP address - * @param port a pointer to which to save the local port (or protocol for RAW) + * @param addr a pointer to which to save the IP address + * @param port a pointer to which to save the port (or protocol for RAW) * @return ERR_CONN for invalid connections * ERR_OK if the information was retrieved */ err_t -netconn_addr(struct netconn *conn, struct ip_addr *addr, u16_t *port) +netconn_getaddr(struct netconn *conn, struct ip_addr *addr, u16_t *port, u8_t local) { - LWIP_ERROR("netconn_addr: invalid conn", (conn != NULL), return ERR_ARG;); - LWIP_ERROR("netconn_addr: invalid addr", (addr != NULL), return ERR_ARG;); - LWIP_ERROR("netconn_addr: invalid port", (port != NULL), return ERR_ARG;); + struct api_msg msg; - /* Not a good safe-thread protection, will be improved */ - if (conn->pcb.ip == NULL) - return ERR_CONN; + LWIP_ERROR("netconn_getaddr: invalid conn", (conn != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_getaddr: invalid addr", (addr != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_getaddr: invalid port", (port != NULL), return ERR_ARG;); - *addr = conn->pcb.ip->local_ip; + msg.function = do_getaddr; + msg.msg.conn = conn; + msg.msg.msg.ad.ipaddr = addr; + msg.msg.msg.ad.port = port; + msg.msg.msg.ad.local = local; + TCPIP_APIMSG(&msg); - switch (NETCONNTYPE_GROUP(conn->type)) { -#if LWIP_RAW - case NETCONN_RAW: - *port = conn->pcb.raw->protocol; - break; -#endif /* LWIP_RAW */ -#if LWIP_UDP - case NETCONN_UDP: - *port = conn->pcb.udp->local_port; - break; -#endif /* LWIP_UDP */ -#if LWIP_TCP - case NETCONN_TCP: - *port = conn->pcb.tcp->local_port; - break; -#endif /* LWIP_TCP */ - } - return ERR_OK; + return conn->err; } /** @@ -346,7 +285,6 @@ netconn_disconnect(struct netconn *conn) msg.msg.conn = conn; TCPIP_APIMSG(&msg); return conn->err; - } /** @@ -575,7 +513,6 @@ netconn_write(struct netconn *conn, const void *dataptr, int size, u8_t apiflags but if it is, this is done inside api_msg.c:do_write(), so we can use the non-blocking version here. */ TCPIP_APIMSG(&msg); - return conn->err; } diff --git a/src/api/api_msg.c b/src/api/api_msg.c index be00e90c..948937d6 100644 --- a/src/api/api_msg.c +++ b/src/api/api_msg.c @@ -888,6 +888,54 @@ do_write(struct api_msg_msg *msg) TCPIP_APIMSG_ACK(msg); } +/** + * Return a connection's local or remote address + * Called from netconn_getaddr + * + * @param msg the api_msg_msg pointing to the connection + */ +void +do_getaddr(struct api_msg_msg *msg) +{ + if (msg->conn->pcb.ip != NULL) { + *(msg->msg.ad.ipaddr) = (msg->msg.ad.local?msg->conn->pcb.ip->local_ip:msg->conn->pcb.ip->remote_ip); + + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + if (msg->msg.ad.local) { + *(msg->msg.ad.port) = msg->conn->pcb.raw->protocol; + } else { + /* return an error as connecting is only a helper for upper layers */ + msg->conn->err = ERR_CONN; + } + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + if (msg->msg.ad.local) { + *(msg->msg.ad.port) = msg->conn->pcb.udp->local_port; + } else { + if ((msg->conn->pcb.udp->flags & UDP_FLAGS_CONNECTED) == 0) { + msg->conn->err = ERR_CONN; + } else { + *(msg->msg.ad.port) = msg->conn->pcb.udp->remote_port; + } + } + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + *(msg->msg.ad.port) = (msg->msg.ad.local?msg->conn->pcb.tcp->local_port:msg->conn->pcb.tcp->remote_port); + break; +#endif /* LWIP_TCP */ + } + } else { + msg->conn->err =ERR_CONN; + } + TCPIP_APIMSG_ACK(msg); +} + /** * Close a TCP pcb contained in a netconn * Called from netconn_close @@ -942,3 +990,4 @@ do_join_leave_group(struct api_msg_msg *msg) #endif /* LWIP_IGMP */ #endif /* LWIP_NETCONN */ + diff --git a/src/api/sockets.c b/src/api/sockets.c index 0e2ab5fd..cca3b932 100644 --- a/src/api/sockets.c +++ b/src/api/sockets.c @@ -967,8 +967,7 @@ lwip_shutdown(int s, int how) } static int -lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, - err_t (* netconn_addrfunc)(struct netconn *conn, struct ip_addr *addr, u16_t *port)) +lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local) { struct lwip_socket *sock; struct sockaddr_in sin; @@ -983,7 +982,7 @@ lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, sin.sin_family = AF_INET; /* get the IP address and port */ - netconn_addrfunc(sock->conn, &naddr, &sin.sin_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); @@ -1003,13 +1002,13 @@ lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, int lwip_getpeername(int s, struct sockaddr *name, socklen_t *namelen) { - return lwip_getaddrname(s, name, namelen, netconn_peer); + return lwip_getaddrname(s, name, namelen, 0); } int lwip_getsockname(int s, struct sockaddr *name, socklen_t *namelen) { - return lwip_getaddrname(s, name, namelen, netconn_addr); + return lwip_getaddrname(s, name, namelen, 1); } int diff --git a/src/include/lwip/api.h b/src/include/lwip/api.h index 5d2e13e3..b006859c 100644 --- a/src/include/lwip/api.h +++ b/src/include/lwip/api.h @@ -148,29 +148,31 @@ netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, void (*callback)(struct netconn *, enum netconn_evt, u16_t len)); err_t netconn_delete (struct netconn *conn); enum netconn_type netconn_type (struct netconn *conn); -err_t netconn_peer (struct netconn *conn, - struct ip_addr *addr, - u16_t *port); -err_t netconn_addr (struct netconn *conn, - struct ip_addr *addr, - u16_t *port); + +err_t netconn_getaddr (struct netconn *conn, + struct ip_addr *addr, + u16_t *port, + u8_t local); +#define netconn_peer(c,i,p) netconn_getaddr(c,i,p,0) +#define netconn_addr(c,i,p) netconn_getaddr(c,i,p,1) + err_t netconn_bind (struct netconn *conn, - struct ip_addr *addr, - u16_t port); + struct ip_addr *addr, + u16_t port); err_t netconn_connect (struct netconn *conn, - struct ip_addr *addr, - u16_t port); + struct ip_addr *addr, + u16_t port); err_t netconn_disconnect (struct netconn *conn); err_t netconn_listen (struct netconn *conn); struct netconn * netconn_accept (struct netconn *conn); struct netbuf * netconn_recv (struct netconn *conn); err_t netconn_sendto (struct netconn *conn, - struct netbuf *buf, struct ip_addr *addr, u16_t port); + struct netbuf *buf, struct ip_addr *addr, u16_t port); err_t netconn_send (struct netconn *conn, - struct netbuf *buf); + struct netbuf *buf); err_t netconn_write (struct netconn *conn, - const void *dataptr, int size, - u8_t apiflags); + const void *dataptr, int size, + u8_t apiflags); err_t netconn_close (struct netconn *conn); #if LWIP_IGMP diff --git a/src/include/lwip/api_msg.h b/src/include/lwip/api_msg.h index 800554d2..fc95f8ff 100644 --- a/src/include/lwip/api_msg.h +++ b/src/include/lwip/api_msg.h @@ -58,6 +58,11 @@ struct api_msg_msg { struct ip_addr *ipaddr; u16_t port; } bc; /* do_bind, do_connect */ + struct { + struct ip_addr *ipaddr; + u16_t *port; + u8_t local; + } ad; /* do_getaddr */ struct { const void *dataptr; int len; @@ -90,6 +95,7 @@ void do_listen ( struct api_msg_msg *msg); void do_send ( struct api_msg_msg *msg); void do_recv ( struct api_msg_msg *msg); void do_write ( struct api_msg_msg *msg); +void do_getaddr ( struct api_msg_msg *msg); void do_close ( struct api_msg_msg *msg); #if LWIP_IGMP void do_join_leave_group( struct api_msg_msg *msg);