mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2025-11-16 12:34:34 +00:00
Applied patch #1399 to implement socket options
This commit is contained in:
@@ -154,7 +154,7 @@ netbuf_copy_partial(struct netbuf *buf, void *dataptr, u16_t len, u16_t offset)
|
||||
|
||||
left = 0;
|
||||
|
||||
if (buf == NULL) {
|
||||
if(buf == NULL || dataptr == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -197,11 +197,14 @@ struct
|
||||
netconn *netconn_new(enum netconn_type t)
|
||||
{
|
||||
struct netconn *conn;
|
||||
struct api_msg *msg;
|
||||
|
||||
conn = memp_malloc(MEMP_NETCONN);
|
||||
if (conn == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
conn->err = ERR_OK;
|
||||
conn->type = t;
|
||||
conn->pcb.tcp = NULL;
|
||||
|
||||
@@ -216,6 +219,23 @@ netconn *netconn_new(enum netconn_type t)
|
||||
conn->socket = 0;
|
||||
conn->callback = 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;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
@@ -238,7 +238,62 @@ accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
|
||||
static void
|
||||
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
|
||||
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
|
||||
previously transmitted data on the connection remains
|
||||
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);
|
||||
}
|
||||
msg->conn->err = err;
|
||||
|
||||
@@ -164,6 +164,7 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s));
|
||||
sock = get_socket(s);
|
||||
if (!sock) {
|
||||
set_errno(EBADF);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -217,6 +218,7 @@ lwip_bind(int s, struct sockaddr *name, socklen_t namelen)
|
||||
|
||||
sock = get_socket(s);
|
||||
if (!sock) {
|
||||
set_errno(EBADF);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -257,6 +259,7 @@ lwip_close(int s)
|
||||
sock = get_socket(s);
|
||||
if (!sock) {
|
||||
sys_sem_signal(socksem);
|
||||
set_errno(EBADF);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -280,6 +283,7 @@ lwip_connect(int s, struct sockaddr *name, socklen_t namelen)
|
||||
|
||||
sock = get_socket(s);
|
||||
if (!sock) {
|
||||
set_errno(EBADF);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -322,6 +326,7 @@ lwip_listen(int s, int backlog)
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog));
|
||||
sock = get_socket(s);
|
||||
if (!sock) {
|
||||
set_errno(EBADF);
|
||||
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));
|
||||
sock = get_socket(s);
|
||||
if (!sock) {
|
||||
set_errno(EBADF);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -468,11 +474,14 @@ lwip_send(int s, void *data, int size, unsigned int flags)
|
||||
|
||||
sock = get_socket(s);
|
||||
if (!sock) {
|
||||
set_errno(EBADF);
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (netconn_type(sock->conn)) {
|
||||
case NETCONN_UDP:
|
||||
case NETCONN_UDPLITE:
|
||||
case NETCONN_UDPNOCHKSUM:
|
||||
/* create a buffer */
|
||||
buf = netbuf_new();
|
||||
|
||||
@@ -521,6 +530,7 @@ lwip_sendto(int s, void *data, int size, unsigned int flags,
|
||||
|
||||
sock = get_socket(s);
|
||||
if (!sock) {
|
||||
set_errno(EBADF);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -895,6 +905,7 @@ int lwip_getpeername (int s, struct sockaddr *name, socklen_t *namelen)
|
||||
|
||||
sock = get_socket(s);
|
||||
if (!sock) {
|
||||
set_errno(EBADF);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -930,6 +941,7 @@ int lwip_getsockname (int s, struct sockaddr *name, socklen_t *namelen)
|
||||
|
||||
sock = get_socket(s);
|
||||
if (!sock) {
|
||||
set_errno(EBADF);
|
||||
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 err = ENOSYS;
|
||||
int err = 0;
|
||||
struct lwip_socket *sock = get_socket(s);
|
||||
|
||||
if (!sock) {
|
||||
if(!sock) {
|
||||
set_errno(EBADF);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (level == SOL_SOCKET) {
|
||||
switch (optname) {
|
||||
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) {
|
||||
|
||||
case SO_ACCEPTCONN:
|
||||
case SO_BROADCAST:
|
||||
/* UNIMPL case SO_DEBUG: */
|
||||
/* UNIMPL case SO_DONTROUTE: */
|
||||
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;
|
||||
}
|
||||
*(int *)optval = sock->err;
|
||||
sock->err = 0;
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", s, *(int *)optval));
|
||||
err = 0;
|
||||
break;
|
||||
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;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", s, level, optname));
|
||||
|
||||
/* 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;
|
||||
sock->err = 0;
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", s, *(int *)optval));
|
||||
break;
|
||||
} /* switch */
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
sock_set_errno(sock, err);
|
||||
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)
|
||||
{
|
||||
struct lwip_socket *sock = get_socket(s);
|
||||
int err = ENOSYS;
|
||||
int err = 0;
|
||||
|
||||
if (!sock) {
|
||||
if(!sock) {
|
||||
set_errno(EBADF);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (level == SOL_SOCKET) {
|
||||
switch (optname) {
|
||||
case SO_REUSEADDR:
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, SO_REUSEADDR, ..)\n", s));
|
||||
/* XXX just pretend we support this for now */
|
||||
err = 0;
|
||||
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) {
|
||||
|
||||
case SO_BROADCAST:
|
||||
/* UNIMPL case SO_DEBUG: */
|
||||
/* 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;
|
||||
default:
|
||||
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, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", s, optname));
|
||||
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;
|
||||
}
|
||||
} 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));
|
||||
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);
|
||||
return err ? -1 : 0;
|
||||
}
|
||||
@@ -1021,7 +1318,8 @@ int lwip_ioctl(int s, long cmd, void *argp)
|
||||
{
|
||||
struct lwip_socket *sock = get_socket(s);
|
||||
|
||||
if (!sock) {
|
||||
if(!sock) {
|
||||
set_errno(EBADF);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1035,7 +1333,7 @@ int lwip_ioctl(int s, long cmd, void *argp)
|
||||
*((u16_t*)argp) = sock->conn->recv_avail;
|
||||
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %u\n", s, argp, *((u16_t*)argp)));
|
||||
sock_set_errno(sock, 0);
|
||||
sock_set_errno(sock, 0);
|
||||
return 0;
|
||||
|
||||
case FIONBIO:
|
||||
@@ -1044,7 +1342,7 @@ int lwip_ioctl(int s, long cmd, void *argp)
|
||||
else
|
||||
sock->flags &= ~O_NONBLOCK;
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, !!(sock->flags & O_NONBLOCK)));
|
||||
sock_set_errno(sock, 0);
|
||||
sock_set_errno(sock, 0);
|
||||
return 0;
|
||||
|
||||
default:
|
||||
|
||||
@@ -126,8 +126,8 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
||||
snmp_inc_icmpoutechoreps();
|
||||
|
||||
pbuf_header(p, hlen);
|
||||
ip_output_if (p, &(iphdr->src), IP_HDRINCL,
|
||||
IPH_TTL(iphdr), IP_PROTO_ICMP, inp);
|
||||
ip_output_if(p, &(iphdr->src), IP_HDRINCL,
|
||||
IPH_TTL(iphdr), 0, IP_PROTO_ICMP, inp);
|
||||
break;
|
||||
default:
|
||||
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();
|
||||
|
||||
ip_output(q, NULL, &(iphdr->src),
|
||||
ICMP_TTL, IP_PROTO_ICMP);
|
||||
ICMP_TTL, 0, IP_PROTO_ICMP);
|
||||
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 */
|
||||
snmp_inc_icmpouttimeexcds();
|
||||
ip_output(q, NULL, &(iphdr->src),
|
||||
ICMP_TTL, IP_PROTO_ICMP);
|
||||
ICMP_TTL, 0, IP_PROTO_ICMP);
|
||||
pbuf_free(q);
|
||||
}
|
||||
|
||||
|
||||
@@ -448,8 +448,8 @@ ip_input(struct pbuf *p, struct netif *inp) {
|
||||
*/
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
err_t
|
||||
ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
u8_t ttl,
|
||||
ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
u8_t ttl, u8_t tos,
|
||||
u8_t proto, struct netif *netif)
|
||||
{
|
||||
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);
|
||||
|
||||
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_OFFSET_SET(iphdr, htons(IP_DF));
|
||||
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
|
||||
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;
|
||||
|
||||
@@ -535,7 +535,7 @@ ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
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
|
||||
|
||||
@@ -175,7 +175,7 @@ raw_send_payload(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -318,6 +318,10 @@ tcp_listen(struct tcp_pcb *pcb)
|
||||
lpcb->callback_arg = pcb->callback_arg;
|
||||
lpcb->local_port = pcb->local_port;
|
||||
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);
|
||||
memp_free(MEMP_TCP_PCB, pcb);
|
||||
#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
|
||||
inactive for too long, will drop the data (it will eventually
|
||||
be retransmitted). */
|
||||
@@ -810,6 +829,8 @@ tcp_alloc(u8_t prio)
|
||||
pcb->snd_buf = TCP_SND_BUF;
|
||||
pcb->snd_queuelen = 0;
|
||||
pcb->rcv_wnd = TCP_WND;
|
||||
pcb->tos = 0;
|
||||
pcb->ttl = TCP_TTL;
|
||||
pcb->mss = TCP_MSS;
|
||||
pcb->rto = 3000 / TCP_SLOW_INTERVAL;
|
||||
pcb->sa = 0;
|
||||
@@ -829,6 +850,10 @@ tcp_alloc(u8_t prio)
|
||||
#if LWIP_CALLBACK_API
|
||||
pcb->recv = tcp_recv_null;
|
||||
#endif /* LWIP_CALLBACK_API */
|
||||
|
||||
/* Init KEEPALIVE timer */
|
||||
pcb->keepalive = TCP_KEEPDEFAULT;
|
||||
pcb->keep_cnt = 0;
|
||||
}
|
||||
return pcb;
|
||||
}
|
||||
|
||||
@@ -396,7 +396,8 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
|
||||
#if LWIP_CALLBACK_API
|
||||
npcb->accept = pcb->accept;
|
||||
#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
|
||||
for it. */
|
||||
TCP_REG(&tcp_active_pcbs, npcb);
|
||||
@@ -483,6 +484,7 @@ tcp_process(struct tcp_pcb *pcb)
|
||||
|
||||
/* Update the PCB (in)activity timer. */
|
||||
pcb->tmr = tcp_ticks;
|
||||
pcb->keep_cnt = 0;
|
||||
|
||||
/* Do different things depending on the TCP state. */
|
||||
switch (pcb->state) {
|
||||
|
||||
@@ -405,7 +405,8 @@ tcp_output(struct tcp_pcb *pcb)
|
||||
tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),
|
||||
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);
|
||||
pbuf_free(p);
|
||||
|
||||
@@ -527,7 +528,7 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
||||
++lwip_stats.tcp.xmit;
|
||||
#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);
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
@@ -561,7 +562,8 @@ tcp_rst(u32_t seqno, u32_t ackno,
|
||||
#ifdef TCP_STATS
|
||||
++lwip_stats.tcp.xmit;
|
||||
#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);
|
||||
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);
|
||||
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
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 */
|
||||
|
||||
|
||||
|
||||
@@ -407,7 +407,7 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
|
||||
/* chksum zero must become 0xffff, as zero means 'no checksum' */
|
||||
if (udphdr->chksum == 0x0000) udphdr->chksum = 0xffff;
|
||||
/* 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();
|
||||
} else {
|
||||
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();
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDP,)\n"));
|
||||
/* 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? */
|
||||
@@ -650,6 +650,9 @@ udp_new(void) {
|
||||
/* initialize PCB to all zeroes */
|
||||
memset(pcb, 0, sizeof(struct udp_pcb));
|
||||
}
|
||||
|
||||
pcb->ttl = UDP_TTL;
|
||||
|
||||
return pcb;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
@@ -47,9 +47,9 @@ u8_t ip_lookup(void *header, struct netif *inp);
|
||||
struct netif *ip_route(struct ip_addr *dest);
|
||||
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,
|
||||
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,
|
||||
u8_t ttl, u8_t proto,
|
||||
u8_t ttl, u8_t tos, u8_t proto,
|
||||
struct netif *netif);
|
||||
|
||||
#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 */
|
||||
#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
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
|
||||
@@ -39,9 +39,11 @@
|
||||
#include "lwip/ip.h"
|
||||
|
||||
struct raw_pcb {
|
||||
/* Common members of all PCB types */
|
||||
IP_PCB;
|
||||
|
||||
struct raw_pcb *next;
|
||||
|
||||
struct ip_addr local_ip;/*, remote_ip;*/
|
||||
u16_t protocol;
|
||||
|
||||
void (* recv)(void *arg, struct raw_pcb *pcb, struct pbuf *p,
|
||||
|
||||
@@ -70,6 +70,7 @@ struct sockaddr {
|
||||
#define SO_USELOOPBACK 0x0040 /* bypass hardware when possible */
|
||||
#define SO_LINGER 0x0080 /* linger on close if data present */
|
||||
#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)
|
||||
|
||||
@@ -117,6 +118,36 @@ struct linger {
|
||||
#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.
|
||||
*
|
||||
|
||||
@@ -151,6 +151,19 @@ void tcp_rexmit (struct tcp_pcb *pcb);
|
||||
|
||||
#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
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
@@ -200,17 +213,30 @@ enum tcp_state {
|
||||
|
||||
/* the TCP protocol control block */
|
||||
struct tcp_pcb {
|
||||
/* Common members of all PCB types */
|
||||
IP_PCB;
|
||||
|
||||
/* Protocol specific PCB members */
|
||||
|
||||
struct tcp_pcb *next; /* for the linked list */
|
||||
|
||||
enum tcp_state state; /* TCP state */
|
||||
|
||||
u8_t prio;
|
||||
void *callback_arg;
|
||||
|
||||
struct ip_addr local_ip;
|
||||
u16_t local_port;
|
||||
enum tcp_state state; /* TCP state */
|
||||
|
||||
struct ip_addr remote_ip;
|
||||
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 */
|
||||
u32_t rcv_nxt; /* next seqno expected */
|
||||
u16_t rcv_wnd; /* receiver window */
|
||||
@@ -223,14 +249,6 @@ struct tcp_pcb {
|
||||
u16_t rtime;
|
||||
|
||||
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. */
|
||||
u16_t rttest; /* RTT estimate in 500ms ticks */
|
||||
@@ -288,21 +306,32 @@ struct tcp_pcb {
|
||||
/* Function to be called whenever a fatal error occurs. */
|
||||
void (* errf)(void *arg, err_t err);
|
||||
#endif /* LWIP_CALLBACK_API */
|
||||
|
||||
/* idle time before KEEPALIVE is sent */
|
||||
u32_t keepalive;
|
||||
|
||||
/* KEEPALIVE counter */
|
||||
u8_t keep_cnt;
|
||||
};
|
||||
|
||||
struct tcp_pcb_listen {
|
||||
/* Common members of all PCB types */
|
||||
IP_PCB;
|
||||
|
||||
/* Protocol specific PCB members */
|
||||
struct tcp_pcb_listen *next; /* for the linked list */
|
||||
u8_t prio;
|
||||
void *callback_arg;
|
||||
|
||||
struct ip_addr local_ip;
|
||||
u16_t local_port;
|
||||
/* Even if state is obviously LISTEN this is here for
|
||||
* field compatibility with tpc_pcb to which it is cast sometimes
|
||||
* Until a cleaner solution emerges this is here.FIXME
|
||||
*/
|
||||
enum tcp_state state; /* TCP state */
|
||||
|
||||
u8_t prio;
|
||||
void *callback_arg;
|
||||
|
||||
u16_t local_port;
|
||||
|
||||
#if LWIP_CALLBACK_API
|
||||
/* Function to call when a listener has been connected. */
|
||||
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);
|
||||
|
||||
void tcp_keepalive(struct tcp_pcb *pcb);
|
||||
|
||||
extern struct tcp_pcb *tcp_input_pcb;
|
||||
extern u32_t tcp_ticks;
|
||||
|
||||
|
||||
@@ -52,12 +52,16 @@ struct udp_hdr {
|
||||
#define UDP_FLAGS_CONNECTED 0x04U
|
||||
|
||||
struct udp_pcb {
|
||||
/* Common members of all PCB types */
|
||||
IP_PCB;
|
||||
|
||||
/* Protocol specific PCB members */
|
||||
|
||||
struct udp_pcb *next;
|
||||
|
||||
struct ip_addr local_ip, remote_ip;
|
||||
u8_t flags;
|
||||
u16_t local_port, remote_port;
|
||||
|
||||
u8_t flags;
|
||||
u16_t chksum_len;
|
||||
|
||||
void (* recv)(void *arg, struct udp_pcb *pcb, struct pbuf *p,
|
||||
|
||||
Reference in New Issue
Block a user