diff --git a/src/api/api_lib.c b/src/api/api_lib.c index df99c17f..c4740aaa 100644 --- a/src/api/api_lib.c +++ b/src/api/api_lib.c @@ -286,6 +286,8 @@ netconn_peer(struct netconn *conn, struct ip_addr **addr, case NETCONN_UDPLITE: case NETCONN_UDPNOCHKSUM: case NETCONN_UDP: + if ((conn->pcb.udp->flags & UDP_FLAGS_CONNECTED) == 0) + return -1; *addr = &(conn->pcb.udp->remote_ip); *port = conn->pcb.udp->remote_port; break; @@ -345,6 +347,7 @@ netconn_bind(struct netconn *conn, struct ip_addr *addr, memp_freep(MEMP_API_MSG, msg); return conn->err; } + /*-----------------------------------------------------------------------------------*/ err_t netconn_connect(struct netconn *conn, struct ip_addr *addr, @@ -375,6 +378,26 @@ netconn_connect(struct netconn *conn, struct ip_addr *addr, memp_freep(MEMP_API_MSG, msg); return conn->err; } + +err_t +netconn_disconnect(struct netconn *conn) +{ + struct api_msg *msg; + + if(conn == NULL) { + return ERR_VAL; + } + + if((msg = memp_mallocp(MEMP_API_MSG)) == NULL) { + return ERR_MEM; + } + msg->type = API_MSG_DISCONNECT; + msg->msg.conn = conn; + api_msg_post(msg); + memp_freep(MEMP_API_MSG, msg); + return conn->err; + +} /*-----------------------------------------------------------------------------------*/ err_t netconn_listen(struct netconn *conn) diff --git a/src/api/api_msg.c b/src/api/api_msg.c index 165ffdf4..1b84e0de 100644 --- a/src/api/api_msg.c +++ b/src/api/api_msg.c @@ -71,7 +71,6 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p, pbuf_free(p); return; } - if(conn->recvmbox != SYS_MBOX_NULL) { buf = memp_mallocp(MEMP_NETBUF); if(buf == NULL) { @@ -370,6 +369,26 @@ do_connect(struct api_msg_msg *msg) break; } } + +static void +do_disconnect(struct api_msg_msg *msg) +{ + + switch(msg->conn->type) { +#if LWIP_UDP + case NETCONN_UDPLITE: + /* FALLTHROUGH */ + case NETCONN_UDPNOCHKSUM: + /* FALLTHROUGH */ + case NETCONN_UDP: + udp_disconnect(msg->conn->pcb.udp); + break; +#endif + case NETCONN_TCP: + break; + } +} + /*-----------------------------------------------------------------------------------*/ static void do_listen(struct api_msg_msg *msg) @@ -524,6 +543,7 @@ static api_msg_decode decode[API_MSG_MAX] = { do_delconn, do_bind, do_connect, + do_disconnect, do_listen, do_accept, do_send, diff --git a/src/api/sockets.c b/src/api/sockets.c index ac14d5d7..cbaf573f 100644 --- a/src/api/sockets.c +++ b/src/api/sockets.c @@ -172,11 +172,14 @@ lwip_connect(int s, struct sockaddr *name, int namelen) if(sock == NULL) { return -1; } - - remote_addr.addr = ((struct sockaddr_in *)name)->sin_addr.s_addr; - remote_port = ((struct sockaddr_in *)name)->sin_port; - - err = netconn_connect(sock->conn, &remote_addr, ntohs(remote_port)); + + if (((struct sockaddr_in *)name)->sin_family == AF_UNSPEC) { + err = netconn_disconnect(sock->conn); + } else { + remote_addr.addr = ((struct sockaddr_in *)name)->sin_addr.s_addr; + remote_port = ((struct sockaddr_in *)name)->sin_port; + err = netconn_connect(sock->conn, &remote_addr, ntohs(remote_port)); + } if(err != ERR_OK) { /* errno = ... */ @@ -343,7 +346,7 @@ lwip_sendto(int s, void *data, int size, unsigned int flags, struct lwip_socket *sock; struct ip_addr remote_addr, *addr; u16_t remote_port, port; - int ret; + int ret,connected; sock = get_socket(s); if(sock == NULL) { @@ -351,7 +354,7 @@ lwip_sendto(int s, void *data, int size, unsigned int flags, } /* get the peer if currently connected */ - netconn_peer(sock->conn, &addr, &port); + 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; @@ -361,7 +364,10 @@ lwip_sendto(int s, void *data, int size, unsigned int flags, /* reset the remote address and port number of the connection */ - netconn_connect(sock->conn, addr, port); + if (connected) + netconn_connect(sock->conn, addr, port); + else + netconn_disconnect(sock->conn); return ret; } /*-----------------------------------------------------------------------------------*/ diff --git a/src/core/udp.c b/src/core/udp.c index d7e49777..81608f54 100644 --- a/src/core/udp.c +++ b/src/core/udp.c @@ -28,7 +28,7 @@ * * Author: Adam Dunkels * - * $Id: udp.c,v 1.10 2003/01/21 14:09:31 jani Exp $ + * $Id: udp.c,v 1.11 2003/01/22 16:18:05 jani Exp $ */ /*-----------------------------------------------------------------------------------*/ @@ -199,16 +199,15 @@ udp_input(struct pbuf *p, struct netif *inp) break; } } - /* no fully matching pcb found? */ + /* no fully matching pcb found? then look for an unconnected pcb */ if(pcb == NULL) { /* Iterate through the UDP pcb list for a pcb that matches the local address. */ for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) { DEBUGF(UDP_DEBUG, ("udp_input: pcb local port %d (dgram %d)\n", pcb->local_port, dest)); - if(pcb->local_port == dest && - (ip_addr_isany(&pcb->remote_ip) || - ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src))) && + if((pcb->flags & UDP_FLAGS_CONNECTED) == 0 && + pcb->local_port == dest && (ip_addr_isany(&pcb->local_ip) || ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) { break; @@ -396,13 +395,14 @@ err_t udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port) { struct udp_pcb *ipcb; - - /* Insert UDP PCB into the list of active UDP PCBs. */ + u8_t rebind = 0; + + /* Check for double bind and rebind of the same pcb */ for(ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { - if(pcb == ipcb) { - /* Already on the list, just return. */ - return ERR_OK; - } + if (pcb == ipcb) { + rebind = 1; + break; + } else if (ipcb->local_port == port) { if(ip_addr_isany(&(ipcb->local_ip)) || ip_addr_isany(ipaddr) || @@ -416,9 +416,11 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port) ip_addr_set(&pcb->local_ip, ipaddr); pcb->local_port = port; - /* We need to place the PCB on the list. */ - pcb->next = udp_pcbs; - udp_pcbs = pcb; + /* We need to place the PCB on the list if not already there. */ + if (rebind == 0) { + pcb->next = udp_pcbs; + udp_pcbs = pcb; + } DEBUGF(UDP_DEBUG, ("udp_bind: bound to port %d\n", port)); return ERR_OK; @@ -430,6 +432,7 @@ udp_connect(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port) struct udp_pcb *ipcb; ip_addr_set(&pcb->remote_ip, ipaddr); pcb->remote_port = port; + pcb->flags |= UDP_FLAGS_CONNECTED; /* Insert UDP PCB into the list of active UDP PCBs. */ for(ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { @@ -443,6 +446,12 @@ udp_connect(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port) udp_pcbs = pcb; return ERR_OK; } + +void +udp_disconnect(struct udp_pcb *pcb) +{ + pcb->flags &= ~UDP_FLAGS_CONNECTED; +} /*-----------------------------------------------------------------------------------*/ void udp_recv(struct udp_pcb *pcb, @@ -474,6 +483,7 @@ struct udp_pcb * udp_new(void) { struct udp_pcb *pcb; pcb = memp_malloc(MEMP_UDP_PCB); + pcb->flags = 0; if(pcb != NULL) { memset(pcb, 0, sizeof(struct udp_pcb)); return pcb; diff --git a/src/include/lwip/api.h b/src/include/lwip/api.h index 58f0dcdc..c19b903d 100644 --- a/src/include/lwip/api.h +++ b/src/include/lwip/api.h @@ -122,6 +122,7 @@ err_t netconn_bind (struct netconn *conn, err_t netconn_connect (struct netconn *conn, 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); diff --git a/src/include/lwip/api_msg.h b/src/include/lwip/api_msg.h index ec8a6ded..60bd3584 100644 --- a/src/include/lwip/api_msg.h +++ b/src/include/lwip/api_msg.h @@ -49,6 +49,7 @@ enum api_msg_type { API_MSG_BIND, API_MSG_CONNECT, + API_MSG_DISCONNECT, API_MSG_LISTEN, API_MSG_ACCEPT, diff --git a/src/include/lwip/sockets.h b/src/include/lwip/sockets.h index 8b808b61..8899a872 100644 --- a/src/include/lwip/sockets.h +++ b/src/include/lwip/sockets.h @@ -56,6 +56,7 @@ struct sockaddr { #define SOCK_STREAM 1 #define SOCK_DGRAM 2 +#define AF_UNSPEC 0 #define AF_INET 2 #define PF_INET AF_INET diff --git a/src/include/lwip/udp.h b/src/include/lwip/udp.h index 10b73715..09144e2e 100644 --- a/src/include/lwip/udp.h +++ b/src/include/lwip/udp.h @@ -51,6 +51,7 @@ struct udp_hdr { #define UDP_FLAGS_NOCHKSUM 0x01 #define UDP_FLAGS_UDPLITE 0x02 +#define UDP_FLAGS_CONNECTED 0x04 struct udp_pcb { struct udp_pcb *next; @@ -74,6 +75,7 @@ err_t udp_bind (struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port); err_t udp_connect (struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port); +void udp_disconnect (struct udp_pcb *pcb); void udp_recv (struct udp_pcb *pcb, void (* recv)(void *arg, struct udp_pcb *upcb, struct pbuf *p,