mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2024-11-04 14:29:39 +00:00
sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c: Fix bug #19162 "lwip_sento: a possible to corrupt remote addr/port connection state". Reduce problems "not enought memory" with netbuf (if we receive lot of datagrams). Improve lwip_sendto (only one exchange between sockets api and api_msg which run in tcpip_thread context). Add netconn_sento function. WARNING, if you directly access to "fromaddr" & "fromport" field from netbuf struct, these fields are now renamed "addr" & "port".
This commit is contained in:
parent
05ea5f05ae
commit
5a12aeb4a1
14
CHANGELOG
14
CHANGELOG
@ -23,6 +23,14 @@ HISTORY
|
||||
|
||||
++ New features:
|
||||
|
||||
2007-05-04 Frédéric Bernon, Jonathan Larmour
|
||||
* sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c: Fix bug #19162 "lwip_sento: a possible
|
||||
to corrupt remote addr/port connection state". Reduce problems "not enought memory" with
|
||||
netbuf (if we receive lot of datagrams). Improve lwip_sendto (only one exchange between
|
||||
sockets api and api_msg which run in tcpip_thread context). Add netconn_sento function.
|
||||
Warning, if you directly access to "fromaddr" & "fromport" field from netbuf struct,
|
||||
these fields are now renamed "addr" & "port".
|
||||
|
||||
2007-04-11 Jonathan Larmour
|
||||
* sys.h, api_lib.c: Provide new sys_mbox_tryfetch function. Require ports to provide new
|
||||
sys_arch_mbox_tryfetch function to get a message if one is there, otherwise return
|
||||
@ -503,9 +511,9 @@ HISTORY
|
||||
|
||||
2004-10-16 Kieran Mansley <kjm25@cam.ac.uk>
|
||||
* tcp.c: Add code to tcp_recved() to send an ACK (window update) immediately,
|
||||
even if one is already pending, if the rcv_wnd is above a threshold
|
||||
(currently TCP_WND/2). This avoids waiting for a timer to expire to send a
|
||||
delayed ACK in order to open the window if the stack is only receiving data.
|
||||
even if one is already pending, if the rcv_wnd is above a threshold
|
||||
(currently TCP_WND/2). This avoids waiting for a timer to expire to send a
|
||||
delayed ACK in order to open the window if the stack is only receiving data.
|
||||
|
||||
2004-09-12 Kieran Mansley <kjm25@cam.ac.uk>
|
||||
* tcp*.*: Retransmit time-out handling improvement by Sam Jansen.
|
||||
|
@ -49,6 +49,7 @@ netbuf *netbuf_new(void)
|
||||
if (buf != NULL) {
|
||||
buf->p = NULL;
|
||||
buf->ptr = NULL;
|
||||
buf->addr = NULL;
|
||||
return buf;
|
||||
} else {
|
||||
return NULL;
|
||||
@ -116,12 +117,6 @@ netbuf_chain(struct netbuf *head, struct netbuf *tail)
|
||||
memp_free(MEMP_NETBUF, tail);
|
||||
}
|
||||
|
||||
u16_t
|
||||
netbuf_len(struct netbuf *buf)
|
||||
{
|
||||
return buf->p->tot_len;
|
||||
}
|
||||
|
||||
err_t
|
||||
netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len)
|
||||
{
|
||||
@ -184,24 +179,6 @@ netbuf_copy_partial(struct netbuf *buf, void *dataptr, u16_t len, u16_t offset)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
netbuf_copy(struct netbuf *buf, void *dataptr, u16_t len)
|
||||
{
|
||||
netbuf_copy_partial(buf, dataptr, len, 0);
|
||||
}
|
||||
|
||||
struct ip_addr *
|
||||
netbuf_fromaddr(struct netbuf *buf)
|
||||
{
|
||||
return buf->fromaddr;
|
||||
}
|
||||
|
||||
u16_t
|
||||
netbuf_fromport(struct netbuf *buf)
|
||||
{
|
||||
return buf->fromport;
|
||||
}
|
||||
|
||||
struct
|
||||
netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u16_t proto,
|
||||
void (*callback)(struct netconn *, enum netconn_evt, u16_t len))
|
||||
@ -253,7 +230,6 @@ netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u16_t proto,
|
||||
return conn;
|
||||
}
|
||||
|
||||
|
||||
struct
|
||||
netconn *netconn_new(enum netconn_type t)
|
||||
{
|
||||
@ -267,7 +243,6 @@ netconn *netconn_new_with_callback(enum netconn_type t,
|
||||
return netconn_new_with_proto_and_callback(t,0,callback);
|
||||
}
|
||||
|
||||
|
||||
err_t
|
||||
netconn_delete(struct netconn *conn)
|
||||
{
|
||||
@ -485,10 +460,12 @@ netconn_recv(struct netconn *conn)
|
||||
if (conn == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
if (conn->recvmbox == SYS_MBOX_NULL) {
|
||||
conn->err = ERR_CONN;
|
||||
return NULL;
|
||||
if ((conn->recvmbox = sys_mbox_new()) == SYS_MBOX_NULL) {
|
||||
conn->err = ERR_CONN;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (conn->err != ERR_OK) {
|
||||
@ -533,8 +510,8 @@ netconn_recv(struct netconn *conn)
|
||||
|
||||
buf->p = p;
|
||||
buf->ptr = p;
|
||||
buf->fromport = 0;
|
||||
buf->fromaddr = NULL;
|
||||
buf->port = 0;
|
||||
buf->addr = NULL;
|
||||
|
||||
/* Let the stack know that we have taken the data. */
|
||||
msg.type = API_MSG_RECV;
|
||||
@ -564,6 +541,16 @@ netconn_recv(struct netconn *conn)
|
||||
return buf;
|
||||
}
|
||||
|
||||
err_t
|
||||
netconn_sendto(struct netconn *conn, struct netbuf *buf, struct ip_addr *addr, u16_t port)
|
||||
{ if (buf!=NULL) {
|
||||
buf->addr = addr;
|
||||
buf->port = port;
|
||||
return netconn_send( conn, buf);
|
||||
}
|
||||
return ERR_VAL;
|
||||
}
|
||||
|
||||
err_t
|
||||
netconn_send(struct netconn *conn, struct netbuf *buf)
|
||||
{
|
||||
@ -580,7 +567,7 @@ netconn_send(struct netconn *conn, struct netbuf *buf)
|
||||
LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %d bytes\n", buf->p->tot_len));
|
||||
msg.type = API_MSG_SEND;
|
||||
msg.msg.conn = conn;
|
||||
msg.msg.msg.p = buf->p;
|
||||
msg.msg.msg.b = buf;
|
||||
api_msg_post(&msg);
|
||||
return conn->err;
|
||||
}
|
||||
|
@ -57,8 +57,8 @@ recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p,
|
||||
pbuf_ref(p);
|
||||
buf->p = p;
|
||||
buf->ptr = p;
|
||||
buf->fromaddr = addr;
|
||||
buf->fromport = pcb->protocol;
|
||||
buf->addr = addr;
|
||||
buf->port = pcb->protocol;
|
||||
|
||||
conn->recv_avail += p->tot_len;
|
||||
/* Register event with callback */
|
||||
@ -95,8 +95,8 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
|
||||
} else {
|
||||
buf->p = p;
|
||||
buf->ptr = p;
|
||||
buf->fromaddr = addr;
|
||||
buf->fromport = port;
|
||||
buf->addr = addr;
|
||||
buf->port = port;
|
||||
}
|
||||
|
||||
conn->recv_avail += p->tot_len;
|
||||
@ -581,7 +581,11 @@ do_send(struct api_msg_msg *msg)
|
||||
switch (msg->conn->type) {
|
||||
#if LWIP_RAW
|
||||
case NETCONN_RAW:
|
||||
raw_send(msg->conn->pcb.raw, msg->msg.p);
|
||||
if (msg->msg.b->addr==NULL) {
|
||||
raw_send(msg->conn->pcb.raw, msg->msg.b->p);
|
||||
} else {
|
||||
raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, msg->msg.b->addr);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if LWIP_UDP
|
||||
@ -590,7 +594,11 @@ do_send(struct api_msg_msg *msg)
|
||||
case NETCONN_UDPNOCHKSUM:
|
||||
/* FALLTHROUGH */
|
||||
case NETCONN_UDP:
|
||||
udp_send(msg->conn->pcb.udp, msg->msg.p);
|
||||
if (msg->msg.b->addr==NULL) {
|
||||
udp_send(msg->conn->pcb.udp, msg->msg.b->p);
|
||||
} else {
|
||||
udp_sendto(msg->conn->pcb.udp, msg->msg.b->p, msg->msg.b->addr, msg->msg.b->port);
|
||||
}
|
||||
break;
|
||||
#endif /* LWIP_UDP */
|
||||
case NETCONN_TCP:
|
||||
|
@ -461,7 +461,6 @@ int
|
||||
lwip_send(int s, const 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));
|
||||
@ -470,45 +469,14 @@ lwip_send(int s, const void *data, int size, unsigned int flags)
|
||||
if (!sock)
|
||||
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 */
|
||||
if ((err = netbuf_ref(buf, data, size))==ERR_OK) {
|
||||
/* 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;
|
||||
if (sock->conn->type!=NETCONN_TCP)
|
||||
return lwip_sendto( s, data, size, flags, NULL, 0);
|
||||
|
||||
err = netconn_write( sock->conn, data, size, NETCONN_COPY);
|
||||
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d size=%d\n", s, err, size));
|
||||
sock_set_errno(sock, err_to_errno(err));
|
||||
return (err==ERR_OK?size:-1);
|
||||
}
|
||||
|
||||
int
|
||||
@ -516,37 +484,51 @@ lwip_sendto(int s, const 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 err,connected;
|
||||
struct netbuf buf;
|
||||
struct ip_addr remote_addr;
|
||||
u16_t remote_port;
|
||||
int err;
|
||||
|
||||
sock = get_socket(s);
|
||||
if (!sock)
|
||||
return -1;
|
||||
|
||||
LWIP_ASSERT("lwip_sendto: invalid address", (tolen == sizeof(struct sockaddr_in)) && ((((struct sockaddr_in *)to)->sin_family) == AF_INET));
|
||||
if (sock->conn->type==NETCONN_TCP)
|
||||
return lwip_send( s, data, size, flags);
|
||||
|
||||
LWIP_ASSERT("lwip_sendto: invalid address", (((to==NULL) && (tolen==0)) || ((tolen == sizeof(struct sockaddr_in)) && ((((struct sockaddr_in *)to)->sin_family) == AF_INET))) );
|
||||
|
||||
/* 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;
|
||||
/* initialize a buffer */
|
||||
buf.p = buf.ptr = NULL;
|
||||
if (to) {
|
||||
remote_addr.addr = ((struct sockaddr_in *)to)->sin_addr.s_addr;
|
||||
remote_port = ntohs(((struct sockaddr_in *)to)->sin_port);
|
||||
buf.addr = &remote_addr;
|
||||
buf.port = remote_port;
|
||||
} else {
|
||||
remote_addr.addr = 0;
|
||||
remote_port = 0;
|
||||
buf.addr = NULL;
|
||||
buf.port = 0;
|
||||
}
|
||||
|
||||
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)));
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u\n", remote_port));
|
||||
|
||||
/* make the buffer point to the data that should be sent */
|
||||
if ((err = netbuf_ref(&buf, data, size))==ERR_OK) {
|
||||
/* send the data */
|
||||
err = netconn_send(sock->conn, &buf);
|
||||
}
|
||||
|
||||
netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));
|
||||
|
||||
err = 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 err;
|
||||
/* deallocated the buffer */
|
||||
if (buf.p != NULL) {
|
||||
pbuf_free(buf.p);
|
||||
}
|
||||
|
||||
sock_set_errno(sock, err_to_errno(err));
|
||||
return (err==ERR_OK?size:-1);
|
||||
}
|
||||
|
||||
int
|
||||
@ -600,7 +582,6 @@ lwip_write(int s, const void *data, int size)
|
||||
return lwip_send(s, data, size, 0);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset)
|
||||
{
|
||||
@ -646,8 +627,6 @@ lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset)
|
||||
return nready;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
|
||||
struct timeval *timeout)
|
||||
@ -794,7 +773,6 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
|
||||
return nready;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
|
||||
{
|
||||
@ -877,12 +855,8 @@ event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int lwip_shutdown(int s, int how)
|
||||
{
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_shutdown(%d, how=%d)\n", s, how));
|
||||
@ -1063,7 +1037,6 @@ int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *opt
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* Now do the actual option processing */
|
||||
|
||||
switch(level) {
|
||||
@ -1167,7 +1140,6 @@ int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *opt
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
sock_set_errno(sock, err);
|
||||
return err ? -1 : 0;
|
||||
}
|
||||
@ -1185,7 +1157,6 @@ int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* Do length and type checks for the various options first, to keep it readable. */
|
||||
switch( level ) {
|
||||
|
||||
@ -1420,15 +1391,15 @@ int lwip_ioctl(int s, long cmd, void *argp)
|
||||
|
||||
*((u16_t*)argp) = sock->conn->recv_avail;
|
||||
|
||||
/* Check if there is data left from the last recv operation. /maq 041215 */
|
||||
/* Check if there is data left from the last recv operation. /maq 041215 */
|
||||
if (sock->lastdata) {
|
||||
buflen = netbuf_len(sock->lastdata);
|
||||
buflen -= sock->lastoffset;
|
||||
|
||||
*((u16_t*)argp) += buflen;
|
||||
}
|
||||
*((u16_t*)argp) += buflen;
|
||||
}
|
||||
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %u\n", s, argp, *((u16_t*)argp)));
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %u\n", s, argp, *((u16_t*)argp)));
|
||||
sock_set_errno(sock, 0);
|
||||
return 0;
|
||||
|
||||
|
@ -80,8 +80,8 @@ enum netconn_igmp {
|
||||
|
||||
struct netbuf {
|
||||
struct pbuf *p, *ptr;
|
||||
struct ip_addr *fromaddr;
|
||||
u16_t fromport;
|
||||
struct ip_addr *addr;
|
||||
u16_t port;
|
||||
};
|
||||
|
||||
struct netconn {
|
||||
@ -121,12 +121,13 @@ err_t netbuf_data (struct netbuf *buf,
|
||||
s8_t netbuf_next (struct netbuf *buf);
|
||||
void netbuf_first (struct netbuf *buf);
|
||||
|
||||
void netbuf_copy (struct netbuf *buf,
|
||||
void *dataptr, u16_t len);
|
||||
void netbuf_copy_partial(struct netbuf *buf, void *dataptr,
|
||||
u16_t len, u16_t offset);
|
||||
struct ip_addr * netbuf_fromaddr (struct netbuf *buf);
|
||||
u16_t netbuf_fromport (struct netbuf *buf);
|
||||
|
||||
#define netbuf_copy(buf,dataptr,len) netbuf_copy_partial(buf, dataptr, len, 0)
|
||||
#define netbuf_len(buf) ((buf)->p->tot_len)
|
||||
#define netbuf_fromaddr(buf) ((buf)->addr)
|
||||
#define netbuf_fromport(buf) ((buf)->port)
|
||||
|
||||
/* Network connection functions: */
|
||||
struct netconn * netconn_new (enum netconn_type type);
|
||||
@ -154,6 +155,8 @@ 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);
|
||||
err_t netconn_send (struct netconn *conn,
|
||||
struct netbuf *buf);
|
||||
err_t netconn_write (struct netconn *conn,
|
||||
|
@ -70,7 +70,8 @@ struct api_msg_msg {
|
||||
struct netconn *conn;
|
||||
enum netconn_type conntype;
|
||||
union {
|
||||
struct pbuf *p;
|
||||
struct pbuf *p;
|
||||
struct netbuf *b;
|
||||
struct {
|
||||
struct ip_addr *ipaddr;
|
||||
u16_t port;
|
||||
|
Loading…
Reference in New Issue
Block a user