NetServices Stack source
Dependents: HelloWorld ServoInterfaceBoardExample1 4180_Lab4
Diff: lwip/core/tcp_out.c
- Revision:
- 5:dd63a1e02b1b
- Parent:
- 0:632c9925f013
--- a/lwip/core/tcp_out.c Fri Jul 09 14:46:47 2010 +0000 +++ b/lwip/core/tcp_out.c Tue Jul 27 15:59:42 2010 +0000 @@ -221,6 +221,14 @@ struct pbuf *p; u16_t alloc = length; +#if LWIP_NETIF_TX_SINGLE_PBUF + LWIP_UNUSED_ARG(max_length); + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(apiflags); + LWIP_UNUSED_ARG(first_seg); + /* always create MSS-sized pbufs */ + alloc = TCP_MSS; +#else /* LWIP_NETIF_TX_SINGLE_PBUF */ if (length < max_length) { /* Should we allocate an oversized pbuf, or just the minimum * length required? If tcp_write is going to be called again @@ -241,6 +249,7 @@ alloc = LWIP_MIN(max_length, LWIP_MEM_ALIGN_SIZE(length + TCP_OVERSIZE)); } } +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ p = pbuf_alloc(layer, alloc, PBUF_RAM); if (p == NULL) { return NULL; @@ -273,6 +282,56 @@ } #endif /* TCP_CHECKSUM_ON_COPY */ +/** Checks if tcp_write is allowed or not (checks state, snd_buf and snd_queuelen). + * + * @param pcb the tcp pcb to check for + * @param len length of data to send (checked agains snd_buf) + * @return ERR_OK if tcp_write is allowed to proceed, another err_t otherwise + */ +static err_t +tcp_write_checks(struct tcp_pcb *pcb, u16_t len) +{ + /* connection is in invalid state for data transmission? */ + if ((pcb->state != ESTABLISHED) && + (pcb->state != CLOSE_WAIT) && + (pcb->state != SYN_SENT) && + (pcb->state != SYN_RCVD)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_STATE | LWIP_DBG_LEVEL_SEVERE, ("tcp_write() called in invalid state\n")); + return ERR_CONN; + } else if (len == 0) { + return ERR_OK; + } + + /* fail on too much data */ + if (len > pcb->snd_buf) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_write: too much data (len=%"U16_F" > snd_buf=%"U16_F")\n", + len, pcb->snd_buf)); + pcb->flags |= TF_NAGLEMEMERR; + return ERR_MEM; + } + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen)); + + /* If total number of pbufs on the unsent/unacked queues exceeds the + * configured maximum, return an error */ + /* check for configured max queuelen and possible overflow */ + if ((pcb->snd_queuelen >= TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_write: too long queue %"U16_F" (max %"U16_F")\n", + pcb->snd_queuelen, TCP_SND_QUEUELEN)); + TCP_STATS_INC(tcp.memerr); + pcb->flags |= TF_NAGLEMEMERR; + return ERR_MEM; + } + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_write: pbufs on queue => at least one queue non-empty", + pcb->unacked != NULL || pcb->unsent != NULL); + } else { + LWIP_ASSERT("tcp_write: no pbufs on queue => both queues empty", + pcb->unacked == NULL && pcb->unsent == NULL); + } + return ERR_OK; +} + /** * Write data for sending (but does not send it immediately). * @@ -307,6 +366,7 @@ u8_t concat_chksum_swapped = 0; u16_t concat_chksummed = 0; #endif /* TCP_CHECKSUM_ON_COPY */ + err_t err; #if LWIP_NETIF_TX_SINGLE_PBUF /* Always copy to try to create single pbufs for TX */ @@ -315,50 +375,14 @@ LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, data=%p, len=%"U16_F", apiflags=%"U16_F")\n", (void *)pcb, arg, len, (u16_t)apiflags)); - /* connection is in invalid state for data transmission? */ - if ((pcb->state != ESTABLISHED) && - (pcb->state != CLOSE_WAIT) && - (pcb->state != SYN_SENT) && - (pcb->state != SYN_RCVD)) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_STATE | LWIP_DBG_LEVEL_SEVERE, ("tcp_write() called in invalid state\n")); - return ERR_CONN; - } else if (len == 0) { - return ERR_OK; - } - - LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, arg=%p, len=%"U16_F", apiflags=%"U16_F")\n", - (void *)pcb, arg, len, (u16_t)apiflags)); LWIP_ERROR("tcp_write: arg == NULL (programmer violates API)", arg != NULL, return ERR_ARG;); - /* fail on too much data */ - if (len > pcb->snd_buf) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_write: too much data (len=%"U16_F" > snd_buf=%"U16_F")\n", - len, pcb->snd_buf)); - pcb->flags |= TF_NAGLEMEMERR; - return ERR_MEM; + err = tcp_write_checks(pcb, len); + if (err != ERR_OK) { + return err; } - - LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen)); - - /* If total number of pbufs on the unsent/unacked queues exceeds the - * configured maximum, return an error */ queuelen = pcb->snd_queuelen; - /* check for configured max queuelen and possible overflow */ - if ((queuelen >= TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_write: too long queue %"U16_F" (max %"U16_F")\n", - queuelen, TCP_SND_QUEUELEN)); - TCP_STATS_INC(tcp.memerr); - pcb->flags |= TF_NAGLEMEMERR; - return ERR_MEM; - } - if (queuelen != 0) { - LWIP_ASSERT("tcp_write: pbufs on queue => at least one queue non-empty", - pcb->unacked != NULL || pcb->unsent != NULL); - } else { - LWIP_ASSERT("tcp_write: no pbufs on queue => both queues empty", - pcb->unacked == NULL && pcb->unsent == NULL); - } #if LWIP_TCP_TIMESTAMPS if ((pcb->flags & TF_TIMESTAMP)) { @@ -802,7 +826,7 @@ tcp_build_timestamp_option(struct tcp_pcb *pcb, u32_t *opts) { /* Pad with two NOP options to make everything nicely aligned */ - opts[0] = htonl(0x0101080A); + opts[0] = PP_HTONL(0x0101080A); opts[1] = htonl(sys_now()); opts[2] = htonl(pcb->ts_recent); } @@ -961,7 +985,12 @@ } tcp_output_segment(seg, pcb); + snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg); + + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: pcb->snd_nxt was %"U32_F" seqno=%"U32_F" len=%"U32_F" new snd_nxt=%"U32_F"\n", //DG + pcb->snd_nxt, ntohl(seg->tcphdr->seqno), TCP_TCPLEN(seg), snd_nxt)); + if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) { pcb->snd_nxt = snd_nxt; } @@ -1132,6 +1161,9 @@ #endif /* TCP_CHECKSUM_ON_COPY */ #endif /* CHECKSUM_GEN_TCP */ TCP_STATS_INC(tcp.xmit); + + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: Before ip_out seqno = %"U32_F"\n", + htonl(seg->tcphdr->seqno))); //DG #if LWIP_NETIF_HWADDRHINT ip_output_hinted(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos, @@ -1140,6 +1172,11 @@ ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos, IP_PROTO_TCP); #endif /* LWIP_NETIF_HWADDRHINT*/ + + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: After ip_out seqno = %"U32_F"\n", + htonl(seg->tcphdr->seqno))); //DG + + } /** @@ -1183,7 +1220,7 @@ tcphdr->seqno = htonl(seqno); tcphdr->ackno = htonl(ackno); TCPH_HDRLEN_FLAGS_SET(tcphdr, TCP_HLEN/4, TCP_RST | TCP_ACK); - tcphdr->wnd = htons(TCP_WND); + tcphdr->wnd = PP_HTONS(TCP_WND); tcphdr->chksum = 0; tcphdr->urgp = 0;