88 |
} |
} |
89 |
return ERR_OK; |
return ERR_OK; |
90 |
} else { |
} else { |
91 |
DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write() called in invalid state\n")); |
DEBUGF(TCP_OUTPUT_DEBUG | DBG_STATE | 3, ("tcp_write() called in invalid state\n")); |
92 |
return ERR_CONN; |
return ERR_CONN; |
93 |
} |
} |
94 |
} |
} |
110 |
ptr = arg; |
ptr = arg; |
111 |
/* fail on too much data */ |
/* fail on too much data */ |
112 |
if(len > pcb->snd_buf) { |
if(len > pcb->snd_buf) { |
113 |
DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: too much data (len=%d > snd_buf=%d)\n", len, pcb->snd_buf)); |
DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too much data (len=%d > snd_buf=%d)\n", len, pcb->snd_buf)); |
114 |
return ERR_MEM; |
return ERR_MEM; |
115 |
} |
} |
116 |
|
|
125 |
length. If so, we return an error. */ |
length. If so, we return an error. */ |
126 |
queuelen = pcb->snd_queuelen; |
queuelen = pcb->snd_queuelen; |
127 |
if(queuelen >= TCP_SND_QUEUELEN) { |
if(queuelen >= TCP_SND_QUEUELEN) { |
128 |
DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: too long queue %d (max %d)\n", queuelen, TCP_SND_QUEUELEN)); |
DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too long queue %d (max %d)\n", queuelen, TCP_SND_QUEUELEN)); |
129 |
goto memerr; |
goto memerr; |
130 |
} |
} |
131 |
|
|
148 |
/* Allocate memory for tcp_seg, and fill in fields. */ |
/* Allocate memory for tcp_seg, and fill in fields. */ |
149 |
seg = memp_malloc(MEMP_TCP_SEG); |
seg = memp_malloc(MEMP_TCP_SEG); |
150 |
if(seg == NULL) { |
if(seg == NULL) { |
151 |
DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: could not allocate memory for tcp_seg\n")); |
DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: could not allocate memory for tcp_seg\n")); |
152 |
goto memerr; |
goto memerr; |
153 |
} |
} |
154 |
seg->next = NULL; |
seg->next = NULL; |
176 |
} |
} |
177 |
else if (copy) { |
else if (copy) { |
178 |
if((seg->p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_RAM)) == NULL) { |
if((seg->p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_RAM)) == NULL) { |
179 |
DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: could not allocate memory for pbuf copy size %u\n", seglen)); |
DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue : could not allocate memory for pbuf copy size %u\n", seglen)); |
180 |
goto memerr; |
goto memerr; |
181 |
} |
} |
182 |
++queuelen; |
++queuelen; |
194 |
* instead of PBUF_REF here. |
* instead of PBUF_REF here. |
195 |
*/ |
*/ |
196 |
if((p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_ROM)) == NULL) { |
if((p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_ROM)) == NULL) { |
197 |
DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: could not allocate memory for zero-copy pbuf\n")); |
DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: could not allocate memory for zero-copy pbuf\n")); |
198 |
goto memerr; |
goto memerr; |
199 |
} |
} |
200 |
++queuelen; |
++queuelen; |
206 |
/* If allocation fails, we have to deallocate the data pbuf as |
/* If allocation fails, we have to deallocate the data pbuf as |
207 |
well. */ |
well. */ |
208 |
pbuf_free(p); |
pbuf_free(p); |
209 |
DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: could not allocate memory for header pbuf\n")); |
DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: could not allocate memory for header pbuf\n")); |
210 |
goto memerr; |
goto memerr; |
211 |
} |
} |
212 |
++queuelen; |
++queuelen; |
219 |
/* Now that there are more segments queued, we check again if the |
/* Now that there are more segments queued, we check again if the |
220 |
length of the queue exceeds the configured maximum. */ |
length of the queue exceeds the configured maximum. */ |
221 |
if(queuelen > TCP_SND_QUEUELEN) { |
if(queuelen > TCP_SND_QUEUELEN) { |
222 |
DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: queue too long %d (%d)\n", queuelen, TCP_SND_QUEUELEN)); |
DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: queue too long %d (%d)\n", queuelen, TCP_SND_QUEUELEN)); |
223 |
goto memerr; |
goto memerr; |
224 |
} |
} |
225 |
|
|
231 |
/* Build TCP header. */ |
/* Build TCP header. */ |
232 |
if(pbuf_header(seg->p, TCP_HLEN)) { |
if(pbuf_header(seg->p, TCP_HLEN)) { |
233 |
|
|
234 |
DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: no room for TCP header in pbuf.\n")); |
DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: no room for TCP header in pbuf.\n")); |
235 |
|
|
236 |
#ifdef TCP_STATS |
#ifdef TCP_STATS |
237 |
++lwip_stats.tcp.err; |
++lwip_stats.tcp.err; |
257 |
segments such as SYN|ACK. */ |
segments such as SYN|ACK. */ |
258 |
memcpy(seg->dataptr, optdata, optlen); |
memcpy(seg->dataptr, optdata, optlen); |
259 |
} |
} |
260 |
DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: queueing %lu:%lu (0x%x)\n", |
DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE, ("tcp_enqueue: queueing %lu:%lu (0x%x)\n", |
261 |
ntohl(seg->tcphdr->seqno), |
ntohl(seg->tcphdr->seqno), |
262 |
ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg), |
ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg), |
263 |
flags)); |
flags)); |
295 |
useg->len += queue->len; |
useg->len += queue->len; |
296 |
useg->next = queue->next; |
useg->next = queue->next; |
297 |
|
|
298 |
DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: chaining, new len %u\n", useg->len)); |
DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE | DBG_STATE, ("tcp_enqueue: chaining, new len %u\n", useg->len)); |
299 |
if(seg == queue) { |
if(seg == queue) { |
300 |
seg = NULL; |
seg = NULL; |
301 |
} |
} |
343 |
pcb->unsent != NULL); |
pcb->unsent != NULL); |
344 |
|
|
345 |
} |
} |
346 |
DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %d (with mem err)\n", pcb->snd_queuelen)); |
DEBUGF(TCP_QLEN_DEBUG | DBG_STATE, ("tcp_enqueue: %d (with mem err)\n", pcb->snd_queuelen)); |
347 |
return ERR_MEM; |
return ERR_MEM; |
348 |
} |
} |
349 |
/*-----------------------------------------------------------------------------------*/ |
/*-----------------------------------------------------------------------------------*/ |