Applied patch #1399 to implement socket options

This commit is contained in:
kieranm 2003-08-21 09:59:21 +00:00
parent 0d4190b909
commit cca1607ab5
15 changed files with 612 additions and 65 deletions

View File

@ -154,7 +154,7 @@ netbuf_copy_partial(struct netbuf *buf, void *dataptr, u16_t len, u16_t offset)
left = 0; left = 0;
if (buf == NULL) { if(buf == NULL || dataptr == NULL) {
return; return;
} }
@ -197,11 +197,14 @@ struct
netconn *netconn_new(enum netconn_type t) netconn *netconn_new(enum netconn_type t)
{ {
struct netconn *conn; struct netconn *conn;
struct api_msg *msg;
conn = memp_malloc(MEMP_NETCONN); conn = memp_malloc(MEMP_NETCONN);
if (conn == NULL) { if (conn == NULL) {
return NULL; return NULL;
} }
conn->err = ERR_OK;
conn->type = t; conn->type = t;
conn->pcb.tcp = NULL; conn->pcb.tcp = NULL;
@ -216,6 +219,23 @@ netconn *netconn_new(enum netconn_type t)
conn->socket = 0; conn->socket = 0;
conn->callback = 0; conn->callback = 0;
conn->recv_avail = 0; conn->recv_avail = 0;
if((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
memp_free(MEMP_NETCONN, conn);
return NULL;
}
msg->type = API_MSG_NEWCONN;
msg->msg.conn = conn;
api_msg_post(msg);
sys_mbox_fetch(conn->mbox, NULL);
memp_free(MEMP_API_MSG, msg);
if ( conn->err != ERR_OK ) {
memp_free(MEMP_NETCONN, conn);
return NULL;
}
return conn; return conn;
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/

View File

@ -238,7 +238,62 @@ accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
static void static void
do_newconn(struct api_msg_msg *msg) do_newconn(struct api_msg_msg *msg)
{ {
if(msg->conn->pcb.tcp != NULL) {
/* This "new" connection already has a PCB allocated. */
/* Is this an error condition? Should it be deleted?
We currently just are happy and return. */
sys_mbox_post(msg->conn->mbox, NULL);
return;
} }
msg->conn->err = ERR_OK;
/* Allocate a PCB for this connection */
switch(msg->conn->type) {
#if LWIP_UDP
case NETCONN_UDPLITE:
msg->conn->pcb.udp = udp_new();
if(msg->conn->pcb.udp == NULL) {
msg->conn->err = ERR_MEM;
break;
}
udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
break;
case NETCONN_UDPNOCHKSUM:
msg->conn->pcb.udp = udp_new();
if(msg->conn->pcb.udp == NULL) {
msg->conn->err = ERR_MEM;
break;
}
udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
break;
case NETCONN_UDP:
msg->conn->pcb.udp = udp_new();
if(msg->conn->pcb.udp == NULL) {
msg->conn->err = ERR_MEM;
break;
}
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
break;
#endif /* LWIP_UDP */
#if LWIP_TCP
case NETCONN_TCP:
msg->conn->pcb.tcp = tcp_new();
if(msg->conn->pcb.tcp == NULL) {
msg->conn->err = ERR_MEM;
break;
}
setup_tcp(msg->conn);
break;
#endif
}
sys_mbox_post(msg->conn->mbox, NULL);
}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
static void static void
do_delconn(struct api_msg_msg *msg) do_delconn(struct api_msg_msg *msg)
@ -571,7 +626,7 @@ do_write(struct api_msg_msg *msg)
segments when new outgoing data arrives from the user if any segments when new outgoing data arrives from the user if any
previously transmitted data on the connection remains previously transmitted data on the connection remains
unacknowledged. */ unacknowledged. */
if (err == ERR_OK && msg->conn->pcb.tcp->unacked == NULL) { if(err == ERR_OK && (msg->conn->pcb.tcp->unacked == NULL || (msg->conn->pcb.tcp->flags & TF_NODELAY)) ) {
tcp_output(msg->conn->pcb.tcp); tcp_output(msg->conn->pcb.tcp);
} }
msg->conn->err = err; msg->conn->err = err;

View File

@ -164,6 +164,7 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s)); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s));
sock = get_socket(s); sock = get_socket(s);
if (!sock) { if (!sock) {
set_errno(EBADF);
return -1; return -1;
} }
@ -217,6 +218,7 @@ lwip_bind(int s, struct sockaddr *name, socklen_t namelen)
sock = get_socket(s); sock = get_socket(s);
if (!sock) { if (!sock) {
set_errno(EBADF);
return -1; return -1;
} }
@ -257,6 +259,7 @@ lwip_close(int s)
sock = get_socket(s); sock = get_socket(s);
if (!sock) { if (!sock) {
sys_sem_signal(socksem); sys_sem_signal(socksem);
set_errno(EBADF);
return -1; return -1;
} }
@ -280,6 +283,7 @@ lwip_connect(int s, struct sockaddr *name, socklen_t namelen)
sock = get_socket(s); sock = get_socket(s);
if (!sock) { if (!sock) {
set_errno(EBADF);
return -1; return -1;
} }
@ -322,6 +326,7 @@ lwip_listen(int s, int backlog)
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog)); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog));
sock = get_socket(s); sock = get_socket(s);
if (!sock) { if (!sock) {
set_errno(EBADF);
return -1; return -1;
} }
@ -351,6 +356,7 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %d, 0x%x, ..)\n", s, mem, len, flags)); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %d, 0x%x, ..)\n", s, mem, len, flags));
sock = get_socket(s); sock = get_socket(s);
if (!sock) { if (!sock) {
set_errno(EBADF);
return -1; return -1;
} }
@ -468,11 +474,14 @@ lwip_send(int s, void *data, int size, unsigned int flags)
sock = get_socket(s); sock = get_socket(s);
if (!sock) { if (!sock) {
set_errno(EBADF);
return -1; return -1;
} }
switch (netconn_type(sock->conn)) { switch (netconn_type(sock->conn)) {
case NETCONN_UDP: case NETCONN_UDP:
case NETCONN_UDPLITE:
case NETCONN_UDPNOCHKSUM:
/* create a buffer */ /* create a buffer */
buf = netbuf_new(); buf = netbuf_new();
@ -521,6 +530,7 @@ lwip_sendto(int s, void *data, int size, unsigned int flags,
sock = get_socket(s); sock = get_socket(s);
if (!sock) { if (!sock) {
set_errno(EBADF);
return -1; return -1;
} }
@ -895,6 +905,7 @@ int lwip_getpeername (int s, struct sockaddr *name, socklen_t *namelen)
sock = get_socket(s); sock = get_socket(s);
if (!sock) { if (!sock) {
set_errno(EBADF);
return -1; return -1;
} }
@ -930,6 +941,7 @@ int lwip_getsockname (int s, struct sockaddr *name, socklen_t *namelen)
sock = get_socket(s); sock = get_socket(s);
if (!sock) { if (!sock) {
set_errno(EBADF);
return -1; return -1;
} }
@ -959,32 +971,183 @@ int lwip_getsockname (int s, struct sockaddr *name, socklen_t *namelen)
int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen) int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen)
{ {
int err = ENOSYS; int err = 0;
struct lwip_socket *sock = get_socket(s); struct lwip_socket *sock = get_socket(s);
if(!sock) { if(!sock) {
set_errno(EBADF);
return -1; return -1;
} }
if (level == SOL_SOCKET) { 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) { switch(optname) {
case SO_ACCEPTCONN:
case SO_BROADCAST:
/* UNIMPL case SO_DEBUG: */
/* UNIMPL case SO_DONTROUTE: */
case SO_ERROR: case SO_ERROR:
if (!optval || !optlen || (*optlen != sizeof(int))) { case SO_KEEPALIVE:
/* UNIMPL case SO_OOBINLINE: */
/* UNIMPL case SO_RCVBUF: */
/* UNIMPL case SO_SNDBUF: */
/* UNIMPL case SO_RCVLOWAT: */
/* UNIMPL case SO_SNDLOWAT: */
/* UNIMPL case SO_REUSEADDR: */
/* UNIMPL case SO_REUSEPORT: */
case SO_TYPE:
/* UNIMPL case SO_USELOOPBACK: */
if( *optlen < sizeof(int) ) {
err = EINVAL;
}
break;
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", s, optname));
err = ENOPROTOOPT;
} /* switch */
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;
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", s, optname));
err = ENOPROTOOPT;
} /* switch */
break;
/* Level: IPPROTO_TCP */
case IPPROTO_TCP:
if( *optlen < sizeof(int) ) {
err = EINVAL; err = EINVAL;
break; 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:
break;
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", s, optname));
err = ENOPROTOOPT;
} /* switch */
break;
/* 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( 0 != err ) {
sock_set_errno(sock, err);
return -1;
}
/* Now do the actual option processing */
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: */
/* UNIMPL case SO_REUSEADDR: */
/* UNIMPL case SO_REUSEPORT: */
/*case SO_USELOOPBACK: UNIMPL */
*(int*)optval = sock->conn->pcb.tcp->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 (sock->conn->type) {
case NETCONN_TCP:
*(int*)optval = SOCK_STREAM;
break;
case NETCONN_UDP:
case NETCONN_UDPLITE:
case NETCONN_UDPNOCHKSUM:
*(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 */
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n", s, *(int *)optval));
break;
case SO_ERROR:
*(int *)optval = sock->err; *(int *)optval = sock->err;
sock->err = 0; sock->err = 0;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", s, *(int *)optval)); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", s, *(int *)optval));
err = 0;
break; break;
default: } /* switch */
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", s, optname)); break;
/* Level: IPPROTO_IP */
case IPPROTO_IP:
switch( optname ) {
case IP_TTL:
*(int*)optval = sock->conn->pcb.tcp->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.tcp->tos;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n", s, *(int *)optval));
break;
} /* switch */
break;
/* Level: IPPROTO_TCP */
case IPPROTO_TCP:
switch( optname ) {
case TCP_NODELAY:
*(int*)optval = (sock->conn->pcb.tcp->flags & TF_NODELAY);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n", s, (*(int*)optval)?"on":"off") );
break;
case TCP_KEEPALIVE:
*(int*)optval = sock->conn->pcb.tcp->keepalive;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPALIVE) = %d\n", s, *(int *)optval));
break;
} /* switch */
break; break;
} }
} else {
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", s, level, optname));
}
sock_set_errno(sock, err); sock_set_errno(sock, err);
return err ? -1 : 0; return err ? -1 : 0;
} }
@ -992,27 +1155,161 @@ int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *opt
int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen) int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen)
{ {
struct lwip_socket *sock = get_socket(s); struct lwip_socket *sock = get_socket(s);
int err = ENOSYS; int err = 0;
if(!sock) { if(!sock) {
set_errno(EBADF);
return -1; return -1;
} }
if (level == SOL_SOCKET) { if( NULL == optval ) {
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) { switch(optname) {
case SO_REUSEADDR:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, SO_REUSEADDR, ..)\n", s)); case SO_BROADCAST:
/* XXX just pretend we support this for now */ /* UNIMPL case SO_DEBUG: */
err = 0; /* UNIMPL case SO_DONTROUTE: */
case SO_KEEPALIVE:
/* UNIMPL case SO_OOBINLINE: */
/* UNIMPL case SO_RCVBUF: */
/* UNIMPL case SO_SNDBUF: */
/* UNIMPL case SO_RCVLOWAT: */
/* UNIMPL case SO_SNDLOWAT: */
/* UNIMPL case SO_REUSEADDR: */
/* UNIMPL case SO_REUSEPORT: */
/* UNIMPL case SO_USELOOPBACK: */
if( optlen < sizeof(int) ) {
err = EINVAL;
}
break; break;
default: default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", s, optname)); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", s, optname));
err = ENOPROTOOPT;
} /* switch */
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;
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", s, optname));
err = ENOPROTOOPT;
} /* switch */
break;
/* Level: IPPROTO_TCP */
case IPPROTO_TCP:
if( optlen < sizeof(int) ) {
err = EINVAL;
break; break;
} }
} else {
/* 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:
break;
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", s, optname));
err = ENOPROTOOPT;
} /* switch */
break;
/* UNDEFINED LEVEL */
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", s, level, optname)); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", s, level, optname));
err = ENOPROTOOPT;
} /* switch */
if( 0 != err ) {
sock_set_errno(sock, err);
return -1;
} }
/* Now do the actual option processing */
switch(level) {
/* Level: SOL_SOCKET */
case SOL_SOCKET:
switch(optname) {
/* The option flags */
case SO_BROADCAST:
/* UNIMPL case SO_DEBUG: */
/* UNIMPL case SO_DONTROUTE: */
case SO_KEEPALIVE:
/* UNIMPL case SO_OOBINCLUDE: */
/* UNIMPL case SO_REUSEADDR: */
/* UNIMPL case SO_REUSEPORT: */
/* UNIMPL case SO_USELOOPBACK: */
if ( *(int*)optval ) {
sock->conn->pcb.tcp->so_options |= optname;
} else {
sock->conn->pcb.tcp->so_options &= ~optname;
}
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n", s, optname, (*(int*)optval?"on":"off")));
break;
} /* switch */
break;
/* Level: IPPROTO_IP */
case IPPROTO_IP:
switch( optname ) {
case IP_TTL:
sock->conn->pcb.tcp->ttl = (u8_t)(*(int*)optval);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %u\n", s, sock->conn->pcb.tcp->ttl));
break;
case IP_TOS:
sock->conn->pcb.tcp->tos = (u8_t)(*(int*)optval);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %u\n", s, sock->conn->pcb.tcp->tos));
break;
} /* switch */
break;
/* Level: IPPROTO_TCP */
case IPPROTO_TCP:
switch( optname ) {
case TCP_NODELAY:
if ( *(int*)optval ) {
sock->conn->pcb.tcp->flags |= TF_NODELAY;
} else {
sock->conn->pcb.tcp->flags &= ~TF_NODELAY;
}
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n", s, (*(int *)optval)?"on":"off") );
break;
case TCP_KEEPALIVE:
sock->conn->pcb.tcp->keepalive = (u32_t)(*(int*)optval);;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %u\n", s, sock->conn->pcb.tcp->keepalive));
break;
} /* switch */
break;
} /* switch */
sock_set_errno(sock, err); sock_set_errno(sock, err);
return err ? -1 : 0; return err ? -1 : 0;
} }
@ -1022,6 +1319,7 @@ int lwip_ioctl(int s, long cmd, void *argp)
struct lwip_socket *sock = get_socket(s); struct lwip_socket *sock = get_socket(s);
if(!sock) { if(!sock) {
set_errno(EBADF);
return -1; return -1;
} }

View File

@ -127,7 +127,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
pbuf_header(p, hlen); pbuf_header(p, hlen);
ip_output_if(p, &(iphdr->src), IP_HDRINCL, ip_output_if(p, &(iphdr->src), IP_HDRINCL,
IPH_TTL(iphdr), IP_PROTO_ICMP, inp); IPH_TTL(iphdr), 0, IP_PROTO_ICMP, inp);
break; break;
default: default:
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %d code %d not supported.\n", (int)type, (int)code)); LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %d code %d not supported.\n", (int)type, (int)code));
@ -169,7 +169,7 @@ icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
snmp_inc_icmpoutdestunreachs(); snmp_inc_icmpoutdestunreachs();
ip_output(q, NULL, &(iphdr->src), ip_output(q, NULL, &(iphdr->src),
ICMP_TTL, IP_PROTO_ICMP); ICMP_TTL, 0, IP_PROTO_ICMP);
pbuf_free(q); pbuf_free(q);
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -210,7 +210,7 @@ icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
/* increase number of destination unreachable messages attempted to send */ /* increase number of destination unreachable messages attempted to send */
snmp_inc_icmpouttimeexcds(); snmp_inc_icmpouttimeexcds();
ip_output(q, NULL, &(iphdr->src), ip_output(q, NULL, &(iphdr->src),
ICMP_TTL, IP_PROTO_ICMP); ICMP_TTL, 0, IP_PROTO_ICMP);
pbuf_free(q); pbuf_free(q);
} }

View File

@ -449,7 +449,7 @@ ip_input(struct pbuf *p, struct netif *inp) {
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
err_t err_t
ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl, u8_t ttl, u8_t tos,
u8_t proto, struct netif *netif) u8_t proto, struct netif *netif)
{ {
static struct ip_hdr *iphdr; static struct ip_hdr *iphdr;
@ -475,7 +475,7 @@ ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
ip_addr_set(&(iphdr->dest), dest); ip_addr_set(&(iphdr->dest), dest);
IPH_VHLTOS_SET(iphdr, 4, IP_HLEN / 4, 0); IPH_VHLTOS_SET(iphdr, 4, IP_HLEN / 4, tos);
IPH_LEN_SET(iphdr, htons(p->tot_len)); IPH_LEN_SET(iphdr, htons(p->tot_len));
IPH_OFFSET_SET(iphdr, htons(IP_DF)); IPH_OFFSET_SET(iphdr, htons(IP_DF));
IPH_ID_SET(iphdr, htons(ip_id)); IPH_ID_SET(iphdr, htons(ip_id));
@ -521,7 +521,7 @@ ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
err_t err_t
ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl, u8_t proto) u8_t ttl, u8_t tos, u8_t proto)
{ {
struct netif *netif; struct netif *netif;
@ -535,7 +535,7 @@ ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
return ERR_RTE; return ERR_RTE;
} }
return ip_output_if (p, src, dest, ttl, proto, netif); return ip_output_if(p, src, dest, ttl, tos, proto, netif);
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
#if IP_DEBUG #if IP_DEBUG

View File

@ -175,7 +175,7 @@ raw_send_payload(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
src_ip = &(pcb->local_ip); src_ip = &(pcb->local_ip);
} }
err = ip_output_if (p, src_ip, ipaddr, 64, pcb->protocol, netif); err = ip_output_if (p, src_ip, ipaddr, 64, pcb->tos, pcb->protocol, netif);
return ERR_OK; return ERR_OK;
} }

View File

@ -318,6 +318,10 @@ tcp_listen(struct tcp_pcb *pcb)
lpcb->callback_arg = pcb->callback_arg; lpcb->callback_arg = pcb->callback_arg;
lpcb->local_port = pcb->local_port; lpcb->local_port = pcb->local_port;
lpcb->state = LISTEN; lpcb->state = LISTEN;
lpcb->so_options = pcb->so_options;
lpcb->so_options |= SOF_ACCEPTCONN;
lpcb->ttl = pcb->ttl;
lpcb->tos = pcb->tos;
ip_addr_set(&lpcb->local_ip, &pcb->local_ip); ip_addr_set(&lpcb->local_ip, &pcb->local_ip);
memp_free(MEMP_TCP_PCB, pcb); memp_free(MEMP_TCP_PCB, pcb);
#if LWIP_CALLBACK_API #if LWIP_CALLBACK_API
@ -520,6 +524,21 @@ tcp_slowtmr(void)
} }
} }
/* Check if KEEPALIVE should be sent */
if((pcb->so_options & SOF_KEEPALIVE) && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) {
if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keepalive + TCP_MAXIDLE) / TCP_SLOW_INTERVAL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to %u.%u.%u.%u.\n",
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
tcp_abort(pcb);
}
else if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keepalive + pcb->keep_cnt * TCP_KEEPINTVL) / TCP_SLOW_INTERVAL) {
tcp_keepalive(pcb);
pcb->keep_cnt++;
}
}
/* If this PCB has queued out of sequence data, but has been /* If this PCB has queued out of sequence data, but has been
inactive for too long, will drop the data (it will eventually inactive for too long, will drop the data (it will eventually
be retransmitted). */ be retransmitted). */
@ -810,6 +829,8 @@ tcp_alloc(u8_t prio)
pcb->snd_buf = TCP_SND_BUF; pcb->snd_buf = TCP_SND_BUF;
pcb->snd_queuelen = 0; pcb->snd_queuelen = 0;
pcb->rcv_wnd = TCP_WND; pcb->rcv_wnd = TCP_WND;
pcb->tos = 0;
pcb->ttl = TCP_TTL;
pcb->mss = TCP_MSS; pcb->mss = TCP_MSS;
pcb->rto = 3000 / TCP_SLOW_INTERVAL; pcb->rto = 3000 / TCP_SLOW_INTERVAL;
pcb->sa = 0; pcb->sa = 0;
@ -829,6 +850,10 @@ tcp_alloc(u8_t prio)
#if LWIP_CALLBACK_API #if LWIP_CALLBACK_API
pcb->recv = tcp_recv_null; pcb->recv = tcp_recv_null;
#endif /* LWIP_CALLBACK_API */ #endif /* LWIP_CALLBACK_API */
/* Init KEEPALIVE timer */
pcb->keepalive = TCP_KEEPDEFAULT;
pcb->keep_cnt = 0;
} }
return pcb; return pcb;
} }

View File

@ -396,7 +396,8 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
#if LWIP_CALLBACK_API #if LWIP_CALLBACK_API
npcb->accept = pcb->accept; npcb->accept = pcb->accept;
#endif /* LWIP_CALLBACK_API */ #endif /* LWIP_CALLBACK_API */
/* inherit socket options */
npcb->so_options = pcb->so_options & (SOF_DEBUG|SOF_DONTROUTE|SOF_KEEPALIVE|SOF_OOBINLINE|SOF_LINGER);
/* Register the new PCB so that we can begin receiving segments /* Register the new PCB so that we can begin receiving segments
for it. */ for it. */
TCP_REG(&tcp_active_pcbs, npcb); TCP_REG(&tcp_active_pcbs, npcb);
@ -483,6 +484,7 @@ tcp_process(struct tcp_pcb *pcb)
/* Update the PCB (in)activity timer. */ /* Update the PCB (in)activity timer. */
pcb->tmr = tcp_ticks; pcb->tmr = tcp_ticks;
pcb->keep_cnt = 0;
/* Do different things depending on the TCP state. */ /* Do different things depending on the TCP state. */
switch (pcb->state) { switch (pcb->state) {

View File

@ -405,7 +405,8 @@ tcp_output(struct tcp_pcb *pcb)
tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip), tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),
IP_PROTO_TCP, p->tot_len); IP_PROTO_TCP, p->tot_len);
ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), TCP_TTL,
ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
IP_PROTO_TCP); IP_PROTO_TCP);
pbuf_free(p); pbuf_free(p);
@ -527,7 +528,7 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
++lwip_stats.tcp.xmit; ++lwip_stats.tcp.xmit;
#endif /* TCP_STATS */ #endif /* TCP_STATS */
ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), TCP_TTL, ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
IP_PROTO_TCP); IP_PROTO_TCP);
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -561,7 +562,8 @@ tcp_rst(u32_t seqno, u32_t ackno,
#ifdef TCP_STATS #ifdef TCP_STATS
++lwip_stats.tcp.xmit; ++lwip_stats.tcp.xmit;
#endif /* TCP_STATS */ #endif /* TCP_STATS */
ip_output(p, local_ip, remote_ip, TCP_TTL, IP_PROTO_TCP); /* Send output with hardcoded TTL since we have no access to the pcb */
ip_output(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP);
pbuf_free(p); pbuf_free(p);
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %lu ackno %lu.\n", seqno, ackno)); LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %lu ackno %lu.\n", seqno, ackno));
} }
@ -595,6 +597,50 @@ tcp_rexmit(struct tcp_pcb *pcb)
tcp_output(pcb); tcp_output(pcb);
} }
/*-----------------------------------------------------------------------------------*/
void
tcp_keepalive(struct tcp_pcb *pcb)
{
struct pbuf *p;
struct tcp_hdr *tcphdr;
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to %u.%u.%u.%u\n",
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %ld pcb->tmr %ld pcb->keep_cnt %ld\n", tcp_ticks, pcb->tmr, pcb->keep_cnt));
p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
if(p == NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: could not allocate memory for pbuf\n"));
return;
}
tcphdr = p->payload;
tcphdr->src = htons(pcb->local_port);
tcphdr->dest = htons(pcb->remote_port);
tcphdr->seqno = htonl(pcb->snd_nxt - 1);
tcphdr->ackno = htonl(pcb->rcv_nxt);
tcphdr->wnd = htons(pcb->rcv_wnd);
tcphdr->urgp = 0;
TCPH_HDRLEN_SET(tcphdr, 5);
tcphdr->chksum = 0;
tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip, IP_PROTO_TCP, p->tot_len);
#ifdef TCP_STATS
++lwip_stats.tcp.xmit;
#endif /* TCP_STATS */
/* Send output to IP */
ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
pbuf_free(p);
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_keepalive: seqno %lu ackno %lu.\n", pcb->snd_nxt - 1, pcb->rcv_nxt));
}
#endif /* LWIP_TCP */ #endif /* LWIP_TCP */

View File

@ -407,7 +407,7 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
/* chksum zero must become 0xffff, as zero means 'no checksum' */ /* chksum zero must become 0xffff, as zero means 'no checksum' */
if (udphdr->chksum == 0x0000) udphdr->chksum = 0xffff; if (udphdr->chksum == 0x0000) udphdr->chksum = 0xffff;
/* output to IP */ /* output to IP */
err = ip_output_if (q, src_ip, &pcb->remote_ip, UDP_TTL, IP_PROTO_UDPLITE, netif); err = ip_output_if (p, src_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, IP_PROTO_UDPLITE, netif);
snmp_inc_udpoutdatagrams(); snmp_inc_udpoutdatagrams();
} else { } else {
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %u\n", q->tot_len)); LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %u\n", q->tot_len));
@ -422,7 +422,7 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
snmp_inc_udpoutdatagrams(); snmp_inc_udpoutdatagrams();
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDP,)\n")); LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDP,)\n"));
/* output to IP */ /* output to IP */
err = ip_output_if (q, src_ip, &pcb->remote_ip, UDP_TTL, IP_PROTO_UDP, netif); err = ip_output_if(p, src_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, IP_PROTO_UDP, netif);
} }
/* did we chain a header earlier? */ /* did we chain a header earlier? */
@ -650,6 +650,9 @@ udp_new(void) {
/* initialize PCB to all zeroes */ /* initialize PCB to all zeroes */
memset(pcb, 0, sizeof(struct udp_pcb)); memset(pcb, 0, sizeof(struct udp_pcb));
} }
pcb->ttl = UDP_TTL;
return pcb; return pcb;
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/

View File

@ -47,9 +47,9 @@ u8_t ip_lookup(void *header, struct netif *inp);
struct netif *ip_route(struct ip_addr *dest); struct netif *ip_route(struct ip_addr *dest);
err_t ip_input(struct pbuf *p, struct netif *inp); err_t ip_input(struct pbuf *p, struct netif *inp);
err_t ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, err_t ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl, u8_t proto); u8_t ttl, u8_t tos, u8_t proto);
err_t ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, err_t ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl, u8_t proto, u8_t ttl, u8_t tos, u8_t proto,
struct netif *netif); struct netif *netif);
#define IP_HLEN 20 #define IP_HLEN 20
@ -67,6 +67,36 @@ err_t ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
#endif /* IP_HDRINCL */ #endif /* IP_HDRINCL */
#define IP_HDRINCL NULL #define IP_HDRINCL NULL
/* This is the common part of all PCB types. It needs to be at the
beginning of a PCB type definition. It is located here so that
changes to this common part are made in one location instead of
having to change all PCB structs. */
#define IP_PCB struct ip_addr local_ip; \
struct ip_addr remote_ip; \
/* Socket options */ \
u16_t so_options; \
/* Type Of Service */ \
u8_t tos; \
/* Time To Live */ \
u8_t ttl
/*
* Option flags per-socket. These are the same like SO_XXX.
*/
#define SOF_DEBUG (u16_t)0x0001U /* turn on debugging info recording */
#define SOF_ACCEPTCONN (u16_t)0x0002U /* socket has had listen() */
#define SOF_REUSEADDR (u16_t)0x0004U /* allow local address reuse */
#define SOF_KEEPALIVE (u16_t)0x0008U /* keep connections alive */
#define SOF_DONTROUTE (u16_t)0x0010U /* just use interface addresses */
#define SOF_BROADCAST (u16_t)0x0020U /* permit sending of broadcast msgs */
#define SOF_USELOOPBACK (u16_t)0x0040U /* bypass hardware when possible */
#define SOF_LINGER (u16_t)0x0080U /* linger on close if data present */
#define SOF_OOBINLINE (u16_t)0x0100U /* leave received OOB data in line */
#define SOF_REUSEPORT (u16_t)0x0200U /* allow local address & port reuse */
#ifdef PACK_STRUCT_USE_INCLUDES #ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h" # include "arch/bpstruct.h"
#endif #endif

View File

@ -39,9 +39,11 @@
#include "lwip/ip.h" #include "lwip/ip.h"
struct raw_pcb { struct raw_pcb {
/* Common members of all PCB types */
IP_PCB;
struct raw_pcb *next; struct raw_pcb *next;
struct ip_addr local_ip;/*, remote_ip;*/
u16_t protocol; u16_t protocol;
void (* recv)(void *arg, struct raw_pcb *pcb, struct pbuf *p, void (* recv)(void *arg, struct raw_pcb *pcb, struct pbuf *p,

View File

@ -70,6 +70,7 @@ struct sockaddr {
#define SO_USELOOPBACK 0x0040 /* bypass hardware when possible */ #define SO_USELOOPBACK 0x0040 /* bypass hardware when possible */
#define SO_LINGER 0x0080 /* linger on close if data present */ #define SO_LINGER 0x0080 /* linger on close if data present */
#define SO_OOBINLINE 0x0100 /* leave received OOB data in line */ #define SO_OOBINLINE 0x0100 /* leave received OOB data in line */
#define SO_REUSEPORT 0x0200 /* allow local address & port reuse */
#define SO_DONTLINGER (int)(~SO_LINGER) #define SO_DONTLINGER (int)(~SO_LINGER)
@ -117,6 +118,36 @@ struct linger {
#define MSG_DONTWAIT 0x40 /* Nonblocking i/o for this operation only */ #define MSG_DONTWAIT 0x40 /* Nonblocking i/o for this operation only */
/*
* Options for level IPPROTO_IP
*/
#define IP_TOS 1
#define IP_TTL 2
#define IPTOS_TOS_MASK 0x1E
#define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK)
#define IPTOS_LOWDELAY 0x10
#define IPTOS_THROUGHPUT 0x08
#define IPTOS_RELIABILITY 0x04
#define IPTOS_LOWCOST 0x02
#define IPTOS_MINCOST IPTOS_LOWCOST
/*
* Definitions for IP precedence (also in ip_tos) (hopefully unused)
*/
#define IPTOS_PREC_MASK 0xe0
#define IPTOS_PREC(tos) ((tos) & IPTOS_PREC_MASK)
#define IPTOS_PREC_NETCONTROL 0xe0
#define IPTOS_PREC_INTERNETCONTROL 0xc0
#define IPTOS_PREC_CRITIC_ECP 0xa0
#define IPTOS_PREC_FLASHOVERRIDE 0x80
#define IPTOS_PREC_FLASH 0x60
#define IPTOS_PREC_IMMEDIATE 0x40
#define IPTOS_PREC_PRIORITY 0x20
#define IPTOS_PREC_ROUTINE 0x00
/* /*
* Commands for ioctlsocket(), taken from the BSD file fcntl.h. * Commands for ioctlsocket(), taken from the BSD file fcntl.h.
* *

View File

@ -151,6 +151,19 @@ void tcp_rexmit (struct tcp_pcb *pcb);
#define TCP_MSL 60000 /* The maximum segment lifetime in microseconds */ #define TCP_MSL 60000 /* The maximum segment lifetime in microseconds */
/*
* User-settable options (used with setsockopt).
*/
#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */
#define TCP_KEEPALIVE 0x02 /* send KEEPALIVE probes when idle for pcb->keepalive miliseconds */
/* Keepalive values */
#define TCP_KEEPDEFAULT 7200000 /* KEEPALIVE timer in miliseconds */
#define TCP_KEEPINTVL 75000 /* Time between KEEPALIVE probes in miliseconds */
#define TCP_KEEPCNT 9 /* Counter for KEEPALIVE probes */
#define TCP_MAXIDLE TCP_KEEPCNT * TCP_KEEPINTVL /* Maximum KEEPALIVE probe time */
#ifdef PACK_STRUCT_USE_INCLUDES #ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h" # include "arch/bpstruct.h"
#endif #endif
@ -200,17 +213,30 @@ enum tcp_state {
/* the TCP protocol control block */ /* the TCP protocol control block */
struct tcp_pcb { struct tcp_pcb {
/* Common members of all PCB types */
IP_PCB;
/* Protocol specific PCB members */
struct tcp_pcb *next; /* for the linked list */ struct tcp_pcb *next; /* for the linked list */
enum tcp_state state; /* TCP state */
u8_t prio; u8_t prio;
void *callback_arg; void *callback_arg;
struct ip_addr local_ip;
u16_t local_port; u16_t local_port;
enum tcp_state state; /* TCP state */
struct ip_addr remote_ip;
u16_t remote_port; u16_t remote_port;
u8_t flags;
#define TF_ACK_DELAY (u8_t)0x01U /* Delayed ACK. */
#define TF_ACK_NOW (u8_t)0x02U /* Immediate ACK. */
#define TF_INFR (u8_t)0x04U /* In fast recovery. */
#define TF_RESET (u8_t)0x08U /* Connection was reset. */
#define TF_CLOSED (u8_t)0x10U /* Connection was sucessfully closed. */
#define TF_GOT_FIN (u8_t)0x20U /* Connection was closed by the remote end. */
#define TF_NODELAY (u8_t)0x40U /* Disable Nagle algorithm */
/* receiver varables */ /* receiver varables */
u32_t rcv_nxt; /* next seqno expected */ u32_t rcv_nxt; /* next seqno expected */
u16_t rcv_wnd; /* receiver window */ u16_t rcv_wnd; /* receiver window */
@ -224,14 +250,6 @@ struct tcp_pcb {
u16_t mss; /* maximum segment size */ u16_t mss; /* maximum segment size */
u8_t flags;
#define TF_ACK_DELAY (u8_t)0x01U /* Delayed ACK. */
#define TF_ACK_NOW (u8_t)0x02U /* Immediate ACK. */
#define TF_INFR (u8_t)0x04U /* In fast recovery. */
#define TF_RESET (u8_t)0x08U /* Connection was reset. */
#define TF_CLOSED (u8_t)0x10U /* Connection was sucessfully closed. */
#define TF_GOT_FIN (u8_t)0x20U /* Connection was closed by the remote end. */
/* RTT estimation variables. */ /* RTT estimation variables. */
u16_t rttest; /* RTT estimate in 500ms ticks */ u16_t rttest; /* RTT estimate in 500ms ticks */
u32_t rtseq; /* sequence number being timed */ u32_t rtseq; /* sequence number being timed */
@ -288,21 +306,32 @@ struct tcp_pcb {
/* Function to be called whenever a fatal error occurs. */ /* Function to be called whenever a fatal error occurs. */
void (* errf)(void *arg, err_t err); void (* errf)(void *arg, err_t err);
#endif /* LWIP_CALLBACK_API */ #endif /* LWIP_CALLBACK_API */
/* idle time before KEEPALIVE is sent */
u32_t keepalive;
/* KEEPALIVE counter */
u8_t keep_cnt;
}; };
struct tcp_pcb_listen { struct tcp_pcb_listen {
struct tcp_pcb_listen *next; /* for the linked list */ /* Common members of all PCB types */
u8_t prio; IP_PCB;
void *callback_arg;
/* Protocol specific PCB members */
struct tcp_pcb_listen *next; /* for the linked list */
struct ip_addr local_ip;
u16_t local_port;
/* Even if state is obviously LISTEN this is here for /* Even if state is obviously LISTEN this is here for
* field compatibility with tpc_pcb to which it is cast sometimes * field compatibility with tpc_pcb to which it is cast sometimes
* Until a cleaner solution emerges this is here.FIXME * Until a cleaner solution emerges this is here.FIXME
*/ */
enum tcp_state state; /* TCP state */ enum tcp_state state; /* TCP state */
u8_t prio;
void *callback_arg;
u16_t local_port;
#if LWIP_CALLBACK_API #if LWIP_CALLBACK_API
/* Function to call when a listener has been connected. */ /* Function to call when a listener has been connected. */
err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err); err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err);
@ -402,6 +431,8 @@ void tcp_rst(u32_t seqno, u32_t ackno,
u32_t tcp_next_iss(void); u32_t tcp_next_iss(void);
void tcp_keepalive(struct tcp_pcb *pcb);
extern struct tcp_pcb *tcp_input_pcb; extern struct tcp_pcb *tcp_input_pcb;
extern u32_t tcp_ticks; extern u32_t tcp_ticks;

View File

@ -52,12 +52,16 @@ struct udp_hdr {
#define UDP_FLAGS_CONNECTED 0x04U #define UDP_FLAGS_CONNECTED 0x04U
struct udp_pcb { struct udp_pcb {
/* Common members of all PCB types */
IP_PCB;
/* Protocol specific PCB members */
struct udp_pcb *next; struct udp_pcb *next;
struct ip_addr local_ip, remote_ip; u8_t flags;
u16_t local_port, remote_port; u16_t local_port, remote_port;
u8_t flags;
u16_t chksum_len; u16_t chksum_len;
void (* recv)(void *arg, struct udp_pcb *pcb, struct pbuf *p, void (* recv)(void *arg, struct udp_pcb *pcb, struct pbuf *p,