net: tcp: Supporting TCP client functionality when using IPv6
The application can initiate TCP connection when using IPv6. Change-Id: I632fa2559d5deb40d71288762bd13fbc2aac9cc7 Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
This commit is contained in:
parent
d57c2d35df
commit
61edc68c9e
8 changed files with 263 additions and 102 deletions
|
@ -220,7 +220,7 @@ packet_input(struct net_buf *buf)
|
||||||
#if UIP_ACTIVE_OPEN
|
#if UIP_ACTIVE_OPEN
|
||||||
struct uip_conn *
|
struct uip_conn *
|
||||||
tcp_connect(const uip_ipaddr_t *ripaddr, uint16_t port, void *appstate,
|
tcp_connect(const uip_ipaddr_t *ripaddr, uint16_t port, void *appstate,
|
||||||
struct process *process)
|
struct process *process, struct net_buf *buf)
|
||||||
{
|
{
|
||||||
struct uip_conn *c;
|
struct uip_conn *c;
|
||||||
|
|
||||||
|
@ -232,7 +232,7 @@ tcp_connect(const uip_ipaddr_t *ripaddr, uint16_t port, void *appstate,
|
||||||
c->appstate.p = process;
|
c->appstate.p = process;
|
||||||
c->appstate.state = appstate;
|
c->appstate.state = appstate;
|
||||||
|
|
||||||
tcpip_poll_tcp(c);
|
tcpip_poll_tcp(c, buf);
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
@ -837,12 +837,18 @@ tcpip_poll_udp(struct uip_udp_conn *conn)
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
#if UIP_TCP
|
#if UIP_TCP
|
||||||
void
|
void
|
||||||
tcpip_poll_tcp(struct uip_conn *conn)
|
tcpip_poll_tcp(struct uip_conn *conn, struct net_buf *data_buf)
|
||||||
{
|
{
|
||||||
/* We are sending here the initial SYN */
|
/* We are sending here the initial SYN */
|
||||||
struct net_buf *buf = ip_buf_get_tx(conn->appstate.state);
|
struct net_buf *buf = ip_buf_get_tx(conn->appstate.state);
|
||||||
uip_set_conn(buf) = conn;
|
uip_set_conn(data_buf) = conn;
|
||||||
conn->buf = ip_buf_ref(buf);
|
|
||||||
|
/* The conn->buf will be freed after we have established the connection,
|
||||||
|
* sent the message and received an ack to it. This will happen in
|
||||||
|
* net_core.c:net_send().
|
||||||
|
*/
|
||||||
|
conn->buf = ip_buf_ref(data_buf);
|
||||||
|
|
||||||
process_post_synch(&tcpip_process, TCP_POLL, conn, buf);
|
process_post_synch(&tcpip_process, TCP_POLL, conn, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -899,7 +905,6 @@ tcpip_uipcall(struct net_buf *buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* UIP_TCP */
|
#endif /* UIP_TCP */
|
||||||
|
|
||||||
if(ts->p != NULL) {
|
if(ts->p != NULL) {
|
||||||
process_post_synch(ts->p, tcpip_event, ts->state, buf);
|
process_post_synch(ts->p, tcpip_event, ts->state, buf);
|
||||||
}
|
}
|
||||||
|
|
|
@ -167,7 +167,8 @@ CCIF void tcp_unlisten(uint16_t port, struct process *handler);
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
CCIF struct uip_conn *tcp_connect(const uip_ipaddr_t *ripaddr, uint16_t port,
|
CCIF struct uip_conn *tcp_connect(const uip_ipaddr_t *ripaddr, uint16_t port,
|
||||||
void *appstate, struct process *process);
|
void *appstate, struct process *process,
|
||||||
|
struct net_buf *buf);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cause a specified TCP connection to be polled.
|
* Cause a specified TCP connection to be polled.
|
||||||
|
@ -180,7 +181,7 @@ CCIF struct uip_conn *tcp_connect(const uip_ipaddr_t *ripaddr, uint16_t port,
|
||||||
* \param conn A pointer to the TCP connection that should be polled.
|
* \param conn A pointer to the TCP connection that should be polled.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void tcpip_poll_tcp(struct uip_conn *conn);
|
void tcpip_poll_tcp(struct uip_conn *conn, struct net_buf *data_buf);
|
||||||
|
|
||||||
void tcpip_resend_syn(struct uip_conn *conn, struct net_buf *buf);
|
void tcpip_resend_syn(struct uip_conn *conn, struct net_buf *buf);
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@ uip_udp_packet_send(struct net_buf *buf, struct uip_udp_conn *c, const void *dat
|
||||||
memcpy(&uip_buf(buf)[UIP_LLH_LEN + UIP_IPUDPH_LEN], data,
|
memcpy(&uip_buf(buf)[UIP_LLH_LEN + UIP_IPUDPH_LEN], data,
|
||||||
len > UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPUDPH_LEN?
|
len > UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPUDPH_LEN?
|
||||||
UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPUDPH_LEN: len);
|
UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPUDPH_LEN: len);
|
||||||
if (uip_process(buf, UIP_UDP_SEND_CONN) == 0) {
|
if (uip_process(&buf, UIP_UDP_SEND_CONN) == 0) {
|
||||||
/* The packet was dropped, we can return now */
|
/* The packet was dropped, we can return now */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -284,8 +284,7 @@ void uip_setipid(uint16_t id);
|
||||||
*
|
*
|
||||||
* \hideinitializer
|
* \hideinitializer
|
||||||
*/
|
*/
|
||||||
#define uip_input(buf) uip_process(buf, UIP_DATA)
|
#define uip_input(buf) uip_process(&buf, UIP_DATA)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Periodic processing for a connection identified by its number.
|
* Periodic processing for a connection identified by its number.
|
||||||
|
@ -331,7 +330,7 @@ void uip_setipid(uint16_t id);
|
||||||
*/
|
*/
|
||||||
#if UIP_TCP
|
#if UIP_TCP
|
||||||
#define uip_periodic(buf, conn) do { uip_set_conn(buf) = &uip_conns[conn]; \
|
#define uip_periodic(buf, conn) do { uip_set_conn(buf) = &uip_conns[conn]; \
|
||||||
uip_process(buf, UIP_TIMER); } while (0)
|
uip_process(&buf, UIP_TIMER); } while (0)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Macro to determine whether a specific uIP connection is active
|
* Macro to determine whether a specific uIP connection is active
|
||||||
|
@ -355,7 +354,7 @@ void uip_setipid(uint16_t id);
|
||||||
* \hideinitializer
|
* \hideinitializer
|
||||||
*/
|
*/
|
||||||
#define uip_periodic_conn(buf, conn) do { uip_set_conn(buf) = conn; \
|
#define uip_periodic_conn(buf, conn) do { uip_set_conn(buf) = conn; \
|
||||||
uip_process(buf, UIP_TIMER); } while (0)
|
uip_process(&buf, UIP_TIMER); } while (0)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request that a particular connection should be polled.
|
* Request that a particular connection should be polled.
|
||||||
|
@ -369,7 +368,7 @@ void uip_setipid(uint16_t id);
|
||||||
* \hideinitializer
|
* \hideinitializer
|
||||||
*/
|
*/
|
||||||
#define uip_poll_conn(buf, conn) do { uip_set_conn(buf) = conn; \
|
#define uip_poll_conn(buf, conn) do { uip_set_conn(buf) = conn; \
|
||||||
uip_process(buf, UIP_POLL_REQUEST); } while (0)
|
uip_process(&buf, UIP_POLL_REQUEST); } while (0)
|
||||||
|
|
||||||
#endif /* UIP_TCP */
|
#endif /* UIP_TCP */
|
||||||
|
|
||||||
|
@ -423,7 +422,7 @@ void uip_setipid(uint16_t id);
|
||||||
* \hideinitializer
|
* \hideinitializer
|
||||||
*/
|
*/
|
||||||
#define uip_udp_periodic_conn(buf, conn) do { uip_set_udp_conn(buf) = conn; \
|
#define uip_udp_periodic_conn(buf, conn) do { uip_set_udp_conn(buf) = conn; \
|
||||||
uip_process(buf, UIP_UDP_TIMER); } while(0)
|
uip_process(&buf, UIP_UDP_TIMER); } while(0)
|
||||||
#endif /* UIP_UDP */
|
#endif /* UIP_UDP */
|
||||||
|
|
||||||
/** \brief Abandon the reassembly of the current packet */
|
/** \brief Abandon the reassembly of the current packet */
|
||||||
|
@ -1299,7 +1298,6 @@ extern uint8_t uip_ext_len;
|
||||||
extern uint16_t uip_urglen, uip_surglen;
|
extern uint16_t uip_urglen, uip_surglen;
|
||||||
#endif /* UIP_URGDATA > 0 */
|
#endif /* UIP_URGDATA > 0 */
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Representation of a uIP TCP connection.
|
* Representation of a uIP TCP connection.
|
||||||
*
|
*
|
||||||
|
@ -1569,7 +1567,7 @@ uip_ext_hdr_options_process(); */
|
||||||
*
|
*
|
||||||
* The actual uIP function which does all the work.
|
* The actual uIP function which does all the work.
|
||||||
*/
|
*/
|
||||||
uint8_t uip_process(struct net_buf *buf, uint8_t flag);
|
uint8_t uip_process(struct net_buf **buf, uint8_t flag);
|
||||||
|
|
||||||
/* The following flags are passed as an argument to the uip_process()
|
/* The following flags are passed as an argument to the uip_process()
|
||||||
function. They are used to distinguish between the two cases where
|
function. They are used to distinguish between the two cases where
|
||||||
|
|
|
@ -678,8 +678,9 @@ uip_add_rcv_nxt(struct net_buf *buf, uint16_t n)
|
||||||
#endif /* UIP_TCP */
|
#endif /* UIP_TCP */
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
uint8_t
|
uint8_t
|
||||||
uip_process(struct net_buf *buf, uint8_t flag)
|
uip_process(struct net_buf **buf_out, uint8_t flag)
|
||||||
{
|
{
|
||||||
|
struct net_buf *buf = &buf_out;
|
||||||
#if UIP_TCP
|
#if UIP_TCP
|
||||||
register struct uip_conn *uip_connr = uip_conn(buf);
|
register struct uip_conn *uip_connr = uip_conn(buf);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -92,6 +92,9 @@ extern void net_context_set_connection_status(struct net_context *context,
|
||||||
void *net_context_get_internal_connection(struct net_context *context);
|
void *net_context_get_internal_connection(struct net_context *context);
|
||||||
void net_context_set_internal_connection(struct net_context *context,
|
void net_context_set_internal_connection(struct net_context *context,
|
||||||
void *conn);
|
void *conn);
|
||||||
|
struct net_context *net_context_find_internal_connection(void *conn);
|
||||||
|
void net_context_tcp_set_pending(struct net_context *context,
|
||||||
|
struct net_buf *buf);
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
/* For Debug, logging, statistics */
|
/* For Debug, logging, statistics */
|
||||||
|
@ -988,7 +991,7 @@ static inline void handle_tcp_retransmit_timer(struct net_buf *not_used,
|
||||||
PRINTF("%s: connection %p buf %p\n", __func__, conn, conn ? conn->buf : 0);
|
PRINTF("%s: connection %p buf %p\n", __func__, conn, conn ? conn->buf : 0);
|
||||||
if (conn && conn->buf) {
|
if (conn && conn->buf) {
|
||||||
conn->timer = 0;
|
conn->timer = 0;
|
||||||
if (uip_process(conn->buf, UIP_TIMER)) {
|
if (uip_process(&conn->buf, UIP_TIMER)) {
|
||||||
tcpip_resend_syn(conn, conn->buf);
|
tcpip_resend_syn(conn, conn->buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1008,8 +1011,9 @@ static inline void tcp_cancel_retrans_timer(struct uip_conn *conn)
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
uint8_t
|
uint8_t
|
||||||
uip_process(struct net_buf *buf, uint8_t flag)
|
uip_process(struct net_buf **buf_out, uint8_t flag)
|
||||||
{
|
{
|
||||||
|
struct net_buf *buf = *buf_out;
|
||||||
#if UIP_TCP
|
#if UIP_TCP
|
||||||
register struct uip_conn *uip_connr = uip_conn(buf);
|
register struct uip_conn *uip_connr = uip_conn(buf);
|
||||||
uint8_t c;
|
uint8_t c;
|
||||||
|
@ -1020,6 +1024,7 @@ uip_process(struct net_buf *buf, uint8_t flag)
|
||||||
goto udp_send;
|
goto udp_send;
|
||||||
}
|
}
|
||||||
#endif /* UIP_UDP */
|
#endif /* UIP_UDP */
|
||||||
|
|
||||||
#if UIP_TCP
|
#if UIP_TCP
|
||||||
if(flag != UIP_TCP_SEND_CONN) {
|
if(flag != UIP_TCP_SEND_CONN) {
|
||||||
#endif
|
#endif
|
||||||
|
@ -1102,7 +1107,7 @@ uip_process(struct net_buf *buf, uint8_t flag)
|
||||||
#if UIP_TCP
|
#if UIP_TCP
|
||||||
uip_len(buf) = 0;
|
uip_len(buf) = 0;
|
||||||
uip_slen(buf) = 0;
|
uip_slen(buf) = 0;
|
||||||
|
|
||||||
/* Increase the initial sequence number. */
|
/* Increase the initial sequence number. */
|
||||||
if(++iss[3] == 0) {
|
if(++iss[3] == 0) {
|
||||||
if(++iss[2] == 0) {
|
if(++iss[2] == 0) {
|
||||||
|
@ -1125,6 +1130,11 @@ uip_process(struct net_buf *buf, uint8_t flag)
|
||||||
uip_connr->tcpstateflags = UIP_CLOSED;
|
uip_connr->tcpstateflags = UIP_CLOSED;
|
||||||
}
|
}
|
||||||
} else if(uip_connr->tcpstateflags != UIP_CLOSED) {
|
} else if(uip_connr->tcpstateflags != UIP_CLOSED) {
|
||||||
|
if (!uip_connr->buf) {
|
||||||
|
/* There cannot be any data pending if buf is NULL */
|
||||||
|
uip_outstanding(uip_connr) = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the connection has outstanding data, we increase the
|
* If the connection has outstanding data, we increase the
|
||||||
* connection's timer and see if it has reached the RTO value
|
* connection's timer and see if it has reached the RTO value
|
||||||
|
@ -1137,7 +1147,6 @@ uip_process(struct net_buf *buf, uint8_t flag)
|
||||||
uip_connr->tcpstateflags == UIP_SYN_RCVD) &&
|
uip_connr->tcpstateflags == UIP_SYN_RCVD) &&
|
||||||
uip_connr->nrtx == UIP_MAXSYNRTX)) {
|
uip_connr->nrtx == UIP_MAXSYNRTX)) {
|
||||||
uip_connr->tcpstateflags = UIP_CLOSED;
|
uip_connr->tcpstateflags = UIP_CLOSED;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We call UIP_APPCALL() with uip_flags set to
|
* We call UIP_APPCALL() with uip_flags set to
|
||||||
* UIP_TIMEDOUT to inform the application that the
|
* UIP_TIMEDOUT to inform the application that the
|
||||||
|
@ -1901,7 +1910,13 @@ uip_process(struct net_buf *buf, uint8_t flag)
|
||||||
uip_connr->snd_nxt[2] = iss[2];
|
uip_connr->snd_nxt[2] = iss[2];
|
||||||
uip_connr->snd_nxt[3] = iss[3];
|
uip_connr->snd_nxt[3] = iss[3];
|
||||||
uip_connr->len = 1;
|
uip_connr->len = 1;
|
||||||
uip_connr->buf = ip_buf_ref(buf);
|
|
||||||
|
if (flag == UIP_TCP_SEND_CONN) {
|
||||||
|
/* So we are trying send some data to other host */
|
||||||
|
if (uip_connr->buf && uip_connr->buf != buf) {
|
||||||
|
uip_connr->buf = ip_buf_ref(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* rcv_nxt should be the seqno from the incoming packet + 1. */
|
/* rcv_nxt should be the seqno from the incoming packet + 1. */
|
||||||
uip_connr->rcv_nxt[3] = UIP_TCP_BUF(buf)->seqno[3];
|
uip_connr->rcv_nxt[3] = UIP_TCP_BUF(buf)->seqno[3];
|
||||||
|
@ -2150,6 +2165,7 @@ tcp_send_syn:
|
||||||
uip_slen(buf) = 0;
|
uip_slen(buf) = 0;
|
||||||
ip_buf_sent_status(buf) = 0;
|
ip_buf_sent_status(buf) = 0;
|
||||||
uip_set_conn(buf) = uip_connr;
|
uip_set_conn(buf) = uip_connr;
|
||||||
|
|
||||||
if (uip_connr->buf) {
|
if (uip_connr->buf) {
|
||||||
/* Now that we know the original connection request, clear
|
/* Now that we know the original connection request, clear
|
||||||
* the buf in connr
|
* the buf in connr
|
||||||
|
@ -2158,11 +2174,26 @@ tcp_send_syn:
|
||||||
net_context_set_internal_connection(ip_buf_context(uip_connr->buf),
|
net_context_set_internal_connection(ip_buf_context(uip_connr->buf),
|
||||||
uip_connr);
|
uip_connr);
|
||||||
tcp_cancel_retrans_timer(uip_connr);
|
tcp_cancel_retrans_timer(uip_connr);
|
||||||
ip_buf_unref(uip_connr->buf);
|
|
||||||
uip_connr->buf = NULL;
|
/* We received ACK for syn */
|
||||||
|
if (uip_connr->buf) {
|
||||||
|
net_context_set_connection_status(ip_buf_context(uip_connr->buf), -EINPROGRESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now send the pending data */
|
||||||
|
buf = uip_connr->buf;
|
||||||
|
*buf_out = buf;
|
||||||
|
|
||||||
|
uip_flags(buf) = UIP_CONNECTED;
|
||||||
}
|
}
|
||||||
UIP_APPCALL(buf);
|
/* Right now we have received SYN-ACK so we can now start to send data.
|
||||||
goto appsend;
|
* The UIP_APPCALL() will cause a call to this function by the
|
||||||
|
* net_context.c TCP process thread which will call
|
||||||
|
* handle_tcp_connection().
|
||||||
|
*/
|
||||||
|
UIP_APPCALL(buf);
|
||||||
|
PRINTF("Returning now buf %p ref %p\n", buf, buf->ref);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
/* Inform the application that the connection failed */
|
/* Inform the application that the connection failed */
|
||||||
uip_flags(buf) = UIP_ABORT;
|
uip_flags(buf) = UIP_ABORT;
|
||||||
|
@ -2275,6 +2306,33 @@ tcp_send_syn:
|
||||||
*/
|
*/
|
||||||
uip_slen(buf) = 0;
|
uip_slen(buf) = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (uip_connr->buf) {
|
||||||
|
net_context_tcp_set_pending(ip_buf_context(uip_connr->buf), NULL);
|
||||||
|
net_context_set_internal_connection(ip_buf_context(uip_connr->buf),
|
||||||
|
uip_connr);
|
||||||
|
|
||||||
|
/* At this point we have received ACK to data in uip_connr->buf */
|
||||||
|
|
||||||
|
/* This is not an error but tells net_core.c:net_send() that
|
||||||
|
* user should be able to send now more data.
|
||||||
|
*/
|
||||||
|
net_context_set_connection_status(ip_buf_context(uip_connr->buf),
|
||||||
|
EISCONN);
|
||||||
|
|
||||||
|
/* Eventually the uip_connr->buf will be freed
|
||||||
|
* by net_core.c:net_send()
|
||||||
|
*/
|
||||||
|
|
||||||
|
tcp_cancel_retrans_timer(uip_connr);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/* We have no pending data so this will cause ACK to be sent to
|
||||||
|
* peer in few lines below.
|
||||||
|
*/
|
||||||
|
uip_flags(buf) |= UIP_NEWDATA;
|
||||||
|
}
|
||||||
|
|
||||||
UIP_APPCALL(buf);
|
UIP_APPCALL(buf);
|
||||||
|
|
||||||
appsend:
|
appsend:
|
||||||
|
@ -2323,6 +2381,15 @@ tcp_send_syn:
|
||||||
PRINTF("Setting connection %p to pending length %d\n",
|
PRINTF("Setting connection %p to pending length %d\n",
|
||||||
uip_connr, uip_connr->len);
|
uip_connr, uip_connr->len);
|
||||||
|
|
||||||
|
if (uip_connr->buf) {
|
||||||
|
if (uip_connr->buf != buf) {
|
||||||
|
PRINTF("Data packet %p already pending....\n",
|
||||||
|
uip_connr->buf);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uip_connr->buf = ip_buf_ref(buf);
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/* If the application already had unacknowledged data, we
|
/* If the application already had unacknowledged data, we
|
||||||
|
@ -2567,11 +2634,13 @@ uip_send(struct net_buf *buf, const void *data, int len)
|
||||||
memmove(uip_sappdata(buf), (data), uip_slen(buf));
|
memmove(uip_sappdata(buf), (data), uip_slen(buf));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (uip_process(buf, UIP_TCP_SEND_CONN)) {
|
if (uip_process(&buf, UIP_TCP_SEND_CONN)) {
|
||||||
int ret = tcpip_ipv6_output(buf);
|
int ret;
|
||||||
|
|
||||||
|
ret = tcpip_ipv6_output(buf);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
PRINTF("Packet %p sending failed.\n", buf);
|
PRINTF("Packet %p sending failed.\n", buf);
|
||||||
ip_buf_unref(buf);
|
ip_buf_sent_status(buf) = -EAGAIN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ struct net_context {
|
||||||
enum net_tcp_type tcp_type;
|
enum net_tcp_type tcp_type;
|
||||||
int connection_status;
|
int connection_status;
|
||||||
void *conn;
|
void *conn;
|
||||||
struct net_buf *last_sent;
|
struct net_buf *pending;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
@ -272,53 +272,25 @@ static int handle_tcp_connection(struct psock *p, enum tcp_event_type type,
|
||||||
|
|
||||||
int net_context_tcp_send(struct net_buf *buf)
|
int net_context_tcp_send(struct net_buf *buf)
|
||||||
{
|
{
|
||||||
|
bool connected, reset;
|
||||||
|
|
||||||
/* Prepare data to be sent */
|
/* Prepare data to be sent */
|
||||||
|
|
||||||
/* If we have already tried to send this buf, then set the flag
|
|
||||||
* accordingly so that psock can actually try to send the data.
|
|
||||||
*/
|
|
||||||
if (ip_buf_context(buf)->last_sent == buf) {
|
|
||||||
uip_flags(buf) |= UIP_REXMIT;
|
|
||||||
} else {
|
|
||||||
ip_buf_context(buf)->last_sent = buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
ip_buf_ref(buf);
|
|
||||||
|
|
||||||
process_post_synch(&ip_buf_context(buf)->tcp,
|
process_post_synch(&ip_buf_context(buf)->tcp,
|
||||||
tcpip_event,
|
tcpip_event,
|
||||||
INT_TO_POINTER(TCP_WRITE_EVENT),
|
INT_TO_POINTER(TCP_WRITE_EVENT),
|
||||||
buf);
|
buf);
|
||||||
|
|
||||||
|
connected = uip_flags(buf) & UIP_CONNECTED;
|
||||||
|
reset = uip_flags(buf) & UIP_ABORT;
|
||||||
|
|
||||||
/* If the buffer ref is 1, then the buffer was sent and it
|
/* If the buffer ref is 1, then the buffer was sent and it
|
||||||
* is cleared already.
|
* is cleared already.
|
||||||
*/
|
*/
|
||||||
if (buf->ref == 1) {
|
if (buf->ref == 1) {
|
||||||
ip_buf_unref(buf);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ip_buf_unref(buf);
|
|
||||||
|
|
||||||
/* If we get -EAGAIN, then we need to retry the packet sending
|
|
||||||
* after we have received ACK from peer. Store the packet to be
|
|
||||||
* sent out later.
|
|
||||||
*/
|
|
||||||
if (ip_buf_sent_status(buf) == -EAGAIN) {
|
|
||||||
if (!uip_conn(buf)) {
|
|
||||||
;
|
|
||||||
} else if (!uip_conn(buf)->buf) {
|
|
||||||
uip_conn(buf)->buf = ip_buf_ref(buf);
|
|
||||||
} else {
|
|
||||||
/* We just could not send the packet and thus need to
|
|
||||||
* discard it.
|
|
||||||
*/
|
|
||||||
ip_buf_sent_status(buf) = -EBUSY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ip_buf_context(buf)->connection_status = ip_buf_sent_status(buf);
|
|
||||||
|
|
||||||
return ip_buf_sent_status(buf);
|
return ip_buf_sent_status(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,11 +299,16 @@ int net_context_tcp_send(struct net_buf *buf)
|
||||||
*/
|
*/
|
||||||
PROCESS_THREAD(tcp, ev, data, buf, user_data)
|
PROCESS_THREAD(tcp, ev, data, buf, user_data)
|
||||||
{
|
{
|
||||||
|
NET_DBG("tcp %p ev %p data %p buf %p user_data %p next line %d\n",
|
||||||
|
process_thread_tcp, ev, data, buf, user_data,
|
||||||
|
process_pt->lc);
|
||||||
|
|
||||||
PROCESS_BEGIN();
|
PROCESS_BEGIN();
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
PROCESS_YIELD_UNTIL(ev == tcpip_event);
|
PROCESS_YIELD_UNTIL(ev == tcpip_event);
|
||||||
|
|
||||||
|
try_send:
|
||||||
if (POINTER_TO_INT(data) == TCP_WRITE_EVENT) {
|
if (POINTER_TO_INT(data) == TCP_WRITE_EVENT) {
|
||||||
/* We want to send data to peer. */
|
/* We want to send data to peer. */
|
||||||
struct net_context *context = user_data;
|
struct net_context *context = user_data;
|
||||||
|
@ -389,6 +366,23 @@ PROCESS_THREAD(tcp, ev, data, buf, user_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
|
} else {
|
||||||
|
if (buf && uip_aborted(buf)) {
|
||||||
|
struct net_context *context = user_data;
|
||||||
|
NET_DBG("Connection aborted context %p\n",
|
||||||
|
user_data);
|
||||||
|
context->connection_status = -ECONNRESET;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf && uip_connected(buf)) {
|
||||||
|
struct net_context *context = user_data;
|
||||||
|
NET_DBG("Connection established context %p\n",
|
||||||
|
user_data);
|
||||||
|
context->connection_status = -EALREADY;
|
||||||
|
data = INT_TO_POINTER(TCP_WRITE_EVENT);
|
||||||
|
goto try_send;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
read_data:
|
read_data:
|
||||||
|
@ -418,6 +412,9 @@ PROCESS_THREAD(tcp, ev, data, buf, user_data)
|
||||||
ip_buf_appdatalen(clone) = uip_len(buf);
|
ip_buf_appdatalen(clone) = uip_len(buf);
|
||||||
ip_buf_len(clone) = ip_buf_len(buf);
|
ip_buf_len(clone) = ip_buf_len(buf);
|
||||||
ip_buf_context(clone) = user_data;
|
ip_buf_context(clone) = user_data;
|
||||||
|
if (!ip_buf_context(buf)) {
|
||||||
|
ip_buf_context(buf) = user_data;
|
||||||
|
}
|
||||||
uip_set_conn(clone) = uip_conn(buf);
|
uip_set_conn(clone) = uip_conn(buf);
|
||||||
uip_flags(clone) = uip_flags(buf);
|
uip_flags(clone) = uip_flags(buf);
|
||||||
uip_flags(clone) |= UIP_CONNECTED;
|
uip_flags(clone) |= UIP_CONNECTED;
|
||||||
|
@ -442,7 +439,7 @@ PROCESS_THREAD(tcp, ev, data, buf, user_data)
|
||||||
PROCESS_END();
|
PROCESS_END();
|
||||||
}
|
}
|
||||||
|
|
||||||
int net_context_tcp_init(struct net_context *context,
|
int net_context_tcp_init(struct net_context *context, struct net_buf *buf,
|
||||||
enum net_tcp_type tcp_type)
|
enum net_tcp_type tcp_type)
|
||||||
{
|
{
|
||||||
if (!context || context->tuple.ip_proto != IPPROTO_TCP) {
|
if (!context || context->tuple.ip_proto != IPPROTO_TCP) {
|
||||||
|
@ -462,6 +459,12 @@ int net_context_tcp_init(struct net_context *context,
|
||||||
* us first, then we are the client.
|
* us first, then we are the client.
|
||||||
*/
|
*/
|
||||||
context->tcp_type = tcp_type;
|
context->tcp_type = tcp_type;
|
||||||
|
} else if (context->tcp_type != tcp_type) {
|
||||||
|
/* This means that we have already selected that we
|
||||||
|
* are either client or server. Use the context
|
||||||
|
* value.
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
context->tcp.thread = process_thread_tcp;
|
context->tcp.thread = process_thread_tcp;
|
||||||
|
@ -475,7 +478,7 @@ int net_context_tcp_init(struct net_context *context,
|
||||||
#if UIP_ACTIVE_OPEN
|
#if UIP_ACTIVE_OPEN
|
||||||
} else {
|
} else {
|
||||||
context->tcp.name = "TCP client";
|
context->tcp.name = "TCP client";
|
||||||
context->connection_status = -EAGAIN;
|
context->connection_status = -EINPROGRESS;
|
||||||
|
|
||||||
#ifdef CONFIG_NETWORKING_WITH_IPV6
|
#ifdef CONFIG_NETWORKING_WITH_IPV6
|
||||||
NET_DBG("Connecting to ");
|
NET_DBG("Connecting to ");
|
||||||
|
@ -485,7 +488,7 @@ int net_context_tcp_init(struct net_context *context,
|
||||||
tcp_connect((uip_ipaddr_t *)
|
tcp_connect((uip_ipaddr_t *)
|
||||||
&context->tuple.remote_addr->in6_addr,
|
&context->tuple.remote_addr->in6_addr,
|
||||||
UIP_HTONS(context->tuple.remote_port),
|
UIP_HTONS(context->tuple.remote_port),
|
||||||
context, &context->tcp);
|
context, &context->tcp, buf);
|
||||||
#else /* CONFIG_NETWORKING_WITH_IPV6 */
|
#else /* CONFIG_NETWORKING_WITH_IPV6 */
|
||||||
NET_DBG("Connecting to ");
|
NET_DBG("Connecting to ");
|
||||||
PRINT6ADDR((const uip_ipaddr_t *)&context->tuple.remote_addr->in_addr);
|
PRINT6ADDR((const uip_ipaddr_t *)&context->tuple.remote_addr->in_addr);
|
||||||
|
@ -494,7 +497,7 @@ int net_context_tcp_init(struct net_context *context,
|
||||||
tcp_connect((uip_ipaddr_t *)
|
tcp_connect((uip_ipaddr_t *)
|
||||||
&context->tuple.remote_addr->in_addr,
|
&context->tuple.remote_addr->in_addr,
|
||||||
UIP_HTONS(context->tuple.remote_port),
|
UIP_HTONS(context->tuple.remote_port),
|
||||||
context, &context->tcp);
|
context, &context->tcp, buf);
|
||||||
#endif /* CONFIG_NETWORKING_WITH_IPV6 */
|
#endif /* CONFIG_NETWORKING_WITH_IPV6 */
|
||||||
#endif /* UIP_ACTIVE_OPEN */
|
#endif /* UIP_ACTIVE_OPEN */
|
||||||
}
|
}
|
||||||
|
@ -543,6 +546,15 @@ void net_context_set_receiver_registered(struct net_context *context)
|
||||||
context->receiver_registered = true;
|
context->receiver_registered = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void net_context_unset_receiver_registered(struct net_context *context)
|
||||||
|
{
|
||||||
|
if (!context) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
context->receiver_registered = false;
|
||||||
|
}
|
||||||
|
|
||||||
int net_context_get_connection_status(struct net_context *context)
|
int net_context_get_connection_status(struct net_context *context)
|
||||||
{
|
{
|
||||||
if (!context) {
|
if (!context) {
|
||||||
|
@ -571,6 +583,7 @@ void net_context_set_connection_status(struct net_context *context,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context->tuple.ip_proto == IPPROTO_TCP) {
|
if (context->tuple.ip_proto == IPPROTO_TCP) {
|
||||||
|
NET_DBG("context %p status %d\n", context, status);
|
||||||
context->connection_status = status;
|
context->connection_status = status;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -608,3 +621,47 @@ void net_context_set_internal_connection(struct net_context *context,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct net_context *net_context_find_internal_connection(void *conn)
|
||||||
|
{
|
||||||
|
#if !defined(CONFIG_NETWORKING_WITH_TCP)
|
||||||
|
return NULL;
|
||||||
|
#else
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < NET_MAX_CONTEXT; i++) {
|
||||||
|
if (contexts[i].conn == conn) {
|
||||||
|
return &contexts[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
struct net_buf *net_context_tcp_get_pending(struct net_context *context)
|
||||||
|
{
|
||||||
|
#if !defined(CONFIG_NETWORKING_WITH_TCP)
|
||||||
|
return NULL;
|
||||||
|
#else
|
||||||
|
if (!context) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return context->pending;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_context_tcp_set_pending(struct net_context *context,
|
||||||
|
struct net_buf *buf)
|
||||||
|
{
|
||||||
|
#if !defined(CONFIG_NETWORKING_WITH_TCP)
|
||||||
|
return;
|
||||||
|
#else
|
||||||
|
if (!context) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
context->pending = buf;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
@ -65,9 +65,16 @@ struct simple_udp_connection *
|
||||||
net_context_get_udp_connection(struct net_context *context);
|
net_context_get_udp_connection(struct net_context *context);
|
||||||
int net_context_get_receiver_registered(struct net_context *context);
|
int net_context_get_receiver_registered(struct net_context *context);
|
||||||
void net_context_set_receiver_registered(struct net_context *context);
|
void net_context_set_receiver_registered(struct net_context *context);
|
||||||
int net_context_tcp_init(struct net_context *context,
|
int net_context_tcp_init(struct net_context *context, struct net_buf *buf,
|
||||||
enum net_tcp_type);
|
enum net_tcp_type);
|
||||||
int net_context_tcp_send(struct net_buf *buf);
|
int net_context_tcp_send(struct net_buf *buf);
|
||||||
|
void *net_context_get_internal_connection(struct net_context *context);
|
||||||
|
struct net_buf *net_context_tcp_get_pending(struct net_context *context);
|
||||||
|
void net_context_tcp_set_pending(struct net_context *context,
|
||||||
|
struct net_buf *buf);
|
||||||
|
void net_context_set_connection_status(struct net_context *context,
|
||||||
|
int status);
|
||||||
|
void net_context_unset_receiver_registered(struct net_context *context);
|
||||||
|
|
||||||
/* Stacks for the tx & rx fibers.
|
/* Stacks for the tx & rx fibers.
|
||||||
* FIXME: stack size needs fine-tuning
|
* FIXME: stack size needs fine-tuning
|
||||||
|
@ -103,46 +110,65 @@ int net_send(struct net_buf *buf)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (ip_buf_len(buf) == 0) {
|
if (!buf || ip_buf_len(buf) == 0) {
|
||||||
return -ENODATA;
|
return -ENODATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (buf->len && !uip_appdatalen(buf)) {
|
||||||
|
uip_appdatalen(buf) = buf->len;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_NETWORKING_WITH_TCP
|
#ifdef CONFIG_NETWORKING_WITH_TCP
|
||||||
#define MAX_TCP_RETRY_COUNT 5
|
#define MAX_TCP_RETRY_COUNT 5
|
||||||
net_context_tcp_init(ip_buf_context(buf), NET_TCP_TYPE_CLIENT);
|
if (ip_buf_context(buf) &&
|
||||||
if (ip_buf_context(buf)) {
|
net_context_get_tuple(ip_buf_context(buf))->ip_proto ==
|
||||||
if (net_context_get_connection_status(
|
|
||||||
ip_buf_context(buf)) == -ETIMEDOUT) {
|
|
||||||
return -ETIMEDOUT;
|
|
||||||
}
|
|
||||||
if (ip_buf_tcp_retry_count(buf) < MAX_TCP_RETRY_COUNT) {
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (net_context_get_tuple(
|
|
||||||
ip_buf_context(buf))->ip_proto ==
|
|
||||||
IPPROTO_TCP) {
|
IPPROTO_TCP) {
|
||||||
if (uip_conn(buf) && uip_conn(buf)->len > 0) {
|
struct uip_conn *conn;
|
||||||
/* There is already pending packet to
|
int status;
|
||||||
* be sent. Application needs to try to
|
|
||||||
* send data a bit later.
|
net_context_tcp_init(ip_buf_context(buf), buf,
|
||||||
* Do not wait forever thou so that
|
NET_TCP_TYPE_CLIENT);
|
||||||
* the connection can proceed if
|
|
||||||
* needed.
|
status = net_context_get_connection_status(
|
||||||
*/
|
ip_buf_context(buf));
|
||||||
ip_buf_tcp_retry_count(buf)++;
|
NET_DBG("context %p buf %p status %d\n",
|
||||||
return -EAGAIN;
|
ip_buf_context(buf), buf, status);
|
||||||
}
|
|
||||||
ret = net_context_get_connection_status(
|
switch (status) {
|
||||||
ip_buf_context(buf));
|
case EISCONN:
|
||||||
if (ret < 0) {
|
/* User should be able to send new data now. */
|
||||||
ip_buf_tcp_retry_count(buf)++;
|
NET_DBG("Send new data buf %p ref %d\n", buf, buf->ref);
|
||||||
return ret;
|
net_context_set_connection_status(ip_buf_context(buf),
|
||||||
|
0);
|
||||||
|
conn = (struct uip_conn *)net_context_get_internal_connection(ip_buf_context(buf));
|
||||||
|
if (conn->buf) {
|
||||||
|
ip_buf_unref(conn->buf);
|
||||||
|
|
||||||
|
if (conn->buf == buf) {
|
||||||
|
conn->buf = NULL;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
conn->buf = NULL;
|
||||||
}
|
}
|
||||||
} else {
|
break;
|
||||||
ip_buf_tcp_retry_count(buf) = 0;
|
|
||||||
ret = -EAGAIN;
|
case -EALREADY:
|
||||||
|
NET_DBG("Connection established\n");
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case -EINPROGRESS:
|
||||||
|
NET_DBG("Connection being established\n");
|
||||||
|
return status;
|
||||||
|
|
||||||
|
case -ECONNRESET:
|
||||||
|
NET_DBG("Connection reset\n");
|
||||||
|
net_context_unset_receiver_registered(
|
||||||
|
ip_buf_context(buf));
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = status;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -596,7 +622,7 @@ struct net_buf *net_receive(struct net_context *context, int32_t timeout)
|
||||||
break;
|
break;
|
||||||
case IPPROTO_TCP:
|
case IPPROTO_TCP:
|
||||||
#ifdef CONFIG_NETWORKING_WITH_TCP
|
#ifdef CONFIG_NETWORKING_WITH_TCP
|
||||||
ret = net_context_tcp_init(context, NET_TCP_TYPE_SERVER);
|
ret = net_context_tcp_init(context, NULL, NET_TCP_TYPE_SERVER);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
NET_DBG("TCP connection init failed\n");
|
NET_DBG("TCP connection init failed\n");
|
||||||
ret = -ENOENT;
|
ret = -ENOENT;
|
||||||
|
@ -763,7 +789,11 @@ static int check_and_send_packet(struct net_buf *buf)
|
||||||
*/
|
*/
|
||||||
ret = 1;
|
ret = 1;
|
||||||
} else {
|
} else {
|
||||||
ip_buf_sent_status(buf) = 0;
|
ip_buf_sent_status(buf) = ret;
|
||||||
|
ret = true; /* This will prevent caller to discard
|
||||||
|
* the buffer that needs to be resent
|
||||||
|
* again.
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
NET_DBG("TCP not supported\n");
|
NET_DBG("TCP not supported\n");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue