mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2024-12-26 21:14:09 +00:00
rawapi.txt, api_msg.c, tcp.c, tcp_in.c, tcp.h: changes for task #7675 "Enable to refuse data on a TCP_EVENT_RECV call". Important, behavior changes for the tcp_recv callback (see rawapi.txt).
This commit is contained in:
parent
52e6922e5a
commit
7518acf634
@ -19,6 +19,11 @@ HISTORY
|
||||
|
||||
++ New features:
|
||||
|
||||
2008-01-14 Frédéric Bernon
|
||||
* rawapi.txt, api_msg.c, tcp.c, tcp_in.c, tcp.h: changes for task #7675 "Enable
|
||||
to refuse data on a TCP_EVENT_RECV call". Important, behavior changes for the
|
||||
tcp_recv callback (see rawapi.txt).
|
||||
|
||||
2008-01-14 Frédéric Bernon, Marc Chaland
|
||||
* ip.c: Integrate patch #6369" ip_input : checking before realloc".
|
||||
|
||||
|
@ -188,7 +188,10 @@ window.
|
||||
|
||||
Sets the callback function that will be called when new data
|
||||
arrives. The callback function will be passed a NULL pbuf to
|
||||
indicate that the remote host has closed the connection.
|
||||
indicate that the remote host has closed the connection. If
|
||||
there are no errors and the callback function is to return
|
||||
ERR_OK, then it must free the pbuf. Otherwise, it must not
|
||||
free the pbuf so that lwIP core code can store it.
|
||||
|
||||
- void tcp_recved(struct tcp_pcb *pcb, u16_t len)
|
||||
|
||||
|
@ -165,7 +165,7 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
|
||||
#if LWIP_TCP
|
||||
/**
|
||||
* Receive callback function for TCP netconns.
|
||||
* Posts the packet to conn->recvmbox or deletes it on memory error.
|
||||
* Posts the packet to conn->recvmbox, but doesn't delete it on errors.
|
||||
*
|
||||
* @see tcp.h (struct tcp_pcb.recv) for parameters and return value
|
||||
*/
|
||||
@ -182,7 +182,6 @@ recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
|
||||
LWIP_ASSERT("recv_tcp: recv for wrong pcb!", conn->pcb.tcp == pcb);
|
||||
|
||||
if ((conn == NULL) || (conn->recvmbox == SYS_MBOX_NULL)) {
|
||||
pbuf_free(p);
|
||||
return ERR_VAL;
|
||||
}
|
||||
|
||||
@ -195,7 +194,9 @@ recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
|
||||
}
|
||||
/* Register event with callback */
|
||||
API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
|
||||
sys_mbox_post(conn->recvmbox, p);
|
||||
if (sys_mbox_trypost(conn->recvmbox, p) != ERR_OK) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
@ -770,7 +770,8 @@ tcp_slowtmr(void)
|
||||
}
|
||||
|
||||
/**
|
||||
* Is called every TCP_FAST_INTERVAL (250 ms) and sends delayed ACKs.
|
||||
* Is called every TCP_FAST_INTERVAL (250 ms) and process data previously
|
||||
* "refused" by upper layer (application) and sends delayed ACKs.
|
||||
*
|
||||
* Automatically called from tcp_tmr().
|
||||
*/
|
||||
@ -779,8 +780,19 @@ tcp_fasttmr(void)
|
||||
{
|
||||
struct tcp_pcb *pcb;
|
||||
|
||||
/* send delayed ACKs */
|
||||
for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
|
||||
/* If there is data which was previously "refused" by upper layer */
|
||||
if (pcb->refused_data != NULL) {
|
||||
/* Notify again application with data previously received. */
|
||||
err_t err;
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_fasttmr: notify kept packet\n"));
|
||||
TCP_EVENT_RECV(pcb, pcb->refused_data, ERR_OK, err);
|
||||
if (err == ERR_OK) {
|
||||
pcb->refused_data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* send delayed ACKs */
|
||||
if (pcb->flags & TF_ACK_DELAY) {
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_fasttmr: delayed ACK\n"));
|
||||
tcp_ack_now(pcb);
|
||||
@ -1135,15 +1147,20 @@ tcp_pcb_purge(struct tcp_pcb *pcb)
|
||||
pcb->state != LISTEN) {
|
||||
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge\n"));
|
||||
|
||||
if (pcb->unsent != NULL) {
|
||||
|
||||
if (pcb->refused_data != NULL) {
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->refused_data\n"));
|
||||
pbuf_free(pcb->refused_data);
|
||||
pcb->refused_data = NULL;
|
||||
}
|
||||
if (pcb->unsent != NULL) {
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: not all data sent\n"));
|
||||
}
|
||||
if (pcb->unacked != NULL) {
|
||||
if (pcb->unacked != NULL) {
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->unacked\n"));
|
||||
}
|
||||
#if TCP_QUEUE_OOSEQ /* LW */
|
||||
if (pcb->ooseq != NULL) {
|
||||
if (pcb->ooseq != NULL) {
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->ooseq\n"));
|
||||
}
|
||||
|
||||
|
@ -272,6 +272,23 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
recv_data = NULL;
|
||||
recv_flags = 0;
|
||||
|
||||
/* If there is data which was previously "refused" by upper layer */
|
||||
if (pcb->refused_data != NULL) {
|
||||
/* Notify again application with data previously received. */
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: notify kept packet\n"));
|
||||
TCP_EVENT_RECV(pcb, pcb->refused_data, ERR_OK, err);
|
||||
if (err == ERR_OK) {
|
||||
pcb->refused_data = NULL;
|
||||
} else {
|
||||
/* drop incoming packets, because pcb is "full" */
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: drop incoming packets, because pcb is \"full\"\n"));
|
||||
TCP_STATS_INC(tcp.drop);
|
||||
snmp_inc_tcpinerrs();
|
||||
pbuf_free(p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
tcp_input_pcb = pcb;
|
||||
err = tcp_process(pcb);
|
||||
tcp_input_pcb = NULL;
|
||||
@ -304,15 +321,23 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
if(flags & TCP_PSH) {
|
||||
recv_data->flags |= PBUF_FLAG_PUSH;
|
||||
}
|
||||
|
||||
/* Notify application that data has been received. */
|
||||
TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err);
|
||||
|
||||
/* If the upper layer can't receive this data, store it */
|
||||
if (err != ERR_OK) {
|
||||
pcb->refused_data = recv_data;
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: keep incoming packet, because pcb is \"full\"\n"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* If a FIN segment was received, we call the callback
|
||||
function with a NULL buffer to indicate EOF. */
|
||||
if (recv_flags & TF_GOT_FIN) {
|
||||
TCP_EVENT_RECV(pcb, NULL, ERR_OK, err);
|
||||
}
|
||||
|
||||
/* If there were no errors, we try to send something out. */
|
||||
if (err == ERR_OK) {
|
||||
tcp_output(pcb);
|
||||
|
@ -339,6 +339,8 @@ struct tcp_pcb {
|
||||
struct tcp_seg *ooseq; /* Received out of sequence segments. */
|
||||
#endif /* TCP_QUEUE_OOSEQ */
|
||||
|
||||
struct pbuf *refused_data; /* Data previously received but not yet taken by upper layer */
|
||||
|
||||
#if LWIP_CALLBACK_API
|
||||
/* Function to be called when more send buffer space is available.
|
||||
* @param arg user-supplied argument (tcp_pcb.callback_arg)
|
||||
@ -471,6 +473,7 @@ err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb,
|
||||
#define TCP_EVENT_RECV(pcb,p,err,ret) \
|
||||
if((pcb)->recv != NULL) \
|
||||
{ ret = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err)); } else { \
|
||||
ret = ERR_OK; \
|
||||
if (p) pbuf_free(p); }
|
||||
#define TCP_EVENT_CONNECTED(pcb,err,ret) \
|
||||
if((pcb)->connected != NULL) \
|
||||
|
Loading…
Reference in New Issue
Block a user