Bugfix in tcp-socket: there were a few corner cases when the tcp-socket state would be messed up, which is fixed with this patch
This commit is contained in:
parent
df2cdbbd79
commit
0f1f12fdc7
|
@ -41,6 +41,8 @@
|
|||
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
static void relisten(struct tcp_socket *s);
|
||||
|
||||
LIST(socketlist);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
PROCESS(tcp_socket_process, "TCP socket process");
|
||||
|
@ -58,8 +60,8 @@ senddata(struct tcp_socket *s)
|
|||
{
|
||||
int len = MIN(s->output_data_max_seg, uip_mss());
|
||||
|
||||
if(s->output_data_len > 0) {
|
||||
len = MIN(s->output_data_len, len);
|
||||
if(s->output_senddata_len > 0) {
|
||||
len = MIN(s->output_senddata_len, len);
|
||||
s->output_data_send_nxt = len;
|
||||
uip_send(s->output_data_ptr, len);
|
||||
}
|
||||
|
@ -68,21 +70,27 @@ senddata(struct tcp_socket *s)
|
|||
static void
|
||||
acked(struct tcp_socket *s)
|
||||
{
|
||||
if(s->output_data_len > 0) {
|
||||
if(s->output_senddata_len > 0) {
|
||||
/* Copy the data in the outputbuf down and update outputbufptr and
|
||||
outputbuf_lastsent */
|
||||
|
||||
if(s->output_data_send_nxt > 0) {
|
||||
memcpy(&s->output_data_ptr[0],
|
||||
&s->output_data_ptr[s->output_data_send_nxt],
|
||||
s->output_data_maxlen - s->output_data_send_nxt);
|
||||
&s->output_data_ptr[s->output_data_send_nxt],
|
||||
s->output_data_maxlen - s->output_data_send_nxt);
|
||||
}
|
||||
if(s->output_data_len < s->output_data_send_nxt) {
|
||||
printf("tcp: acked assertion failed s->output_data_len (%d) < s->output_data_send_nxt (%d)\n",
|
||||
s->output_data_len,
|
||||
s->output_data_send_nxt);
|
||||
s->output_data_len,
|
||||
s->output_data_send_nxt);
|
||||
tcp_markconn(uip_conn, NULL);
|
||||
uip_abort();
|
||||
call_event(s, TCP_SOCKET_ABORTED);
|
||||
relisten(s);
|
||||
return;
|
||||
}
|
||||
s->output_data_len -= s->output_data_send_nxt;
|
||||
s->output_senddata_len = s->output_data_len;
|
||||
s->output_data_send_nxt = 0;
|
||||
|
||||
call_event(s, TCP_SOCKET_DATA_SENT);
|
||||
|
@ -134,6 +142,11 @@ appcall(void *state)
|
|||
{
|
||||
struct tcp_socket *s = state;
|
||||
|
||||
if(s != NULL && s->c != NULL && s->c != uip_conn) {
|
||||
/* Safe-guard: this should not happen, as the incoming event relates to
|
||||
* a previous connection */
|
||||
return;
|
||||
}
|
||||
if(uip_connected()) {
|
||||
/* Check if this connection originated in a local listen
|
||||
socket. We do this by checking the state pointer - if NULL,
|
||||
|
@ -176,8 +189,10 @@ appcall(void *state)
|
|||
}
|
||||
|
||||
if(uip_aborted()) {
|
||||
tcp_markconn(uip_conn, NULL);
|
||||
call_event(s, TCP_SOCKET_ABORTED);
|
||||
relisten(s);
|
||||
|
||||
}
|
||||
|
||||
if(s == NULL) {
|
||||
|
@ -203,13 +218,16 @@ appcall(void *state)
|
|||
if(s->output_data_len == 0 && s->flags & TCP_SOCKET_FLAGS_CLOSING) {
|
||||
s->flags &= ~TCP_SOCKET_FLAGS_CLOSING;
|
||||
uip_close();
|
||||
s->c = NULL;
|
||||
tcp_markconn(uip_conn, NULL);
|
||||
call_event(s, TCP_SOCKET_CLOSED);
|
||||
s->c = NULL;
|
||||
/*call_event(s, TCP_SOCKET_CLOSED);*/
|
||||
relisten(s);
|
||||
}
|
||||
|
||||
if(uip_closed()) {
|
||||
tcp_markconn(uip_conn, NULL);
|
||||
s->c = NULL;
|
||||
call_event(s, TCP_SOCKET_CLOSED);
|
||||
relisten(s);
|
||||
}
|
||||
|
@ -255,6 +273,7 @@ tcp_socket_register(struct tcp_socket *s, void *ptr,
|
|||
s->ptr = ptr;
|
||||
s->input_data_ptr = input_databuf;
|
||||
s->input_data_maxlen = input_databuf_len;
|
||||
s->output_data_len = 0;
|
||||
s->output_data_ptr = output_databuf;
|
||||
s->output_data_maxlen = output_databuf_len;
|
||||
s->input_callback = input_callback;
|
||||
|
@ -268,12 +287,15 @@ tcp_socket_register(struct tcp_socket *s, void *ptr,
|
|||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
tcp_socket_connect(struct tcp_socket *s,
|
||||
uip_ipaddr_t *ipaddr,
|
||||
uint16_t port)
|
||||
const uip_ipaddr_t *ipaddr,
|
||||
uint16_t port)
|
||||
{
|
||||
if(s == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if(s->c != NULL) {
|
||||
tcp_markconn(s->c, NULL);
|
||||
}
|
||||
PROCESS_CONTEXT_BEGIN(&tcp_socket_process);
|
||||
s->c = tcp_connect(ipaddr, uip_htons(port), s);
|
||||
PROCESS_CONTEXT_END();
|
||||
|
@ -317,7 +339,7 @@ tcp_socket_unlisten(struct tcp_socket *s)
|
|||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
tcp_socket_send(struct tcp_socket *s,
|
||||
const uint8_t *data, int datalen)
|
||||
const uint8_t *data, int datalen)
|
||||
{
|
||||
int len;
|
||||
|
||||
|
@ -329,6 +351,11 @@ tcp_socket_send(struct tcp_socket *s,
|
|||
|
||||
memcpy(&s->output_data_ptr[s->output_data_len], data, len);
|
||||
s->output_data_len += len;
|
||||
|
||||
if(s->output_senddata_len == 0) {
|
||||
s->output_senddata_len = s->output_data_len;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
@ -365,3 +392,9 @@ tcp_socket_unregister(struct tcp_socket *s)
|
|||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
tcp_socket_max_sendlen(struct tcp_socket *s)
|
||||
{
|
||||
return s->output_data_maxlen - s->output_data_len;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#ifndef TCP_SOCKET_H
|
||||
#define TCP_SOCKET_H
|
||||
|
||||
#include "uip.h"
|
||||
|
||||
struct tcp_socket;
|
||||
|
||||
typedef enum {
|
||||
|
@ -95,6 +97,7 @@ struct tcp_socket {
|
|||
uint16_t output_data_maxlen;
|
||||
uint16_t output_data_len;
|
||||
uint16_t output_data_send_nxt;
|
||||
uint16_t output_senddata_len;
|
||||
uint16_t output_data_max_seg;
|
||||
|
||||
uint8_t flags;
|
||||
|
@ -170,7 +173,7 @@ int tcp_socket_register(struct tcp_socket *s, void *ptr,
|
|||
*
|
||||
*/
|
||||
int tcp_socket_connect(struct tcp_socket *s,
|
||||
uip_ipaddr_t *ipaddr,
|
||||
const uip_ipaddr_t *ipaddr,
|
||||
uint16_t port);
|
||||
|
||||
/**
|
||||
|
@ -266,4 +269,19 @@ int tcp_socket_close(struct tcp_socket *s);
|
|||
*
|
||||
*/
|
||||
int tcp_socket_unregister(struct tcp_socket *s);
|
||||
|
||||
/**
|
||||
* \brief The maximum amount of data that could currently be sent
|
||||
* \param s A pointer to a TCP socket
|
||||
* \return The number of bytes available in the output buffer
|
||||
*
|
||||
* This function queries the TCP socket and returns the
|
||||
* number of bytes available in the output buffer. This
|
||||
* function is used before calling tcp_socket_send() to
|
||||
* ensure that one application level message can be held
|
||||
* in the output buffer.
|
||||
*
|
||||
*/
|
||||
int tcp_socket_max_sendlen(struct tcp_socket *s);
|
||||
|
||||
#endif /* TCP_SOCKET_H */
|
||||
|
|
Loading…
Reference in a new issue