mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2025-04-17 11:42:56 +00:00
Fix udp_bind to allow rebind for same socket (yesterday's commit broke that) and introduce connection info for UDP pcbs.New function netconn_disconnect, do_disconnect for deatching UDP from a remote addres.Fix #2240
This commit is contained in:
parent
16434f0d01
commit
46c575c038
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
@ -28,7 +28,7 @@
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
* $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;
|
||||
|
@ -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);
|
||||
|
@ -49,6 +49,7 @@ enum api_msg_type {
|
||||
|
||||
API_MSG_BIND,
|
||||
API_MSG_CONNECT,
|
||||
API_MSG_DISCONNECT,
|
||||
|
||||
API_MSG_LISTEN,
|
||||
API_MSG_ACCEPT,
|
||||
|
@ -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
|
||||
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user