Added comments to the tcp_enqueue() function.

This commit is contained in:
adamdunkels 2003-01-08 14:11:24 +00:00
parent ced453a72b
commit d04f7aa4bc

View File

@ -109,10 +109,15 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
return ERR_MEM; return ERR_MEM;
} }
/* seqno will be the sequence number of the first segment enqueued
by the call to this function. */
seqno = pcb->snd_lbb; seqno = pcb->snd_lbb;
queue = NULL; queue = NULL;
DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %d\n", pcb->snd_queuelen)); DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %d\n", pcb->snd_queuelen));
/* Check if the queue length exceeds the configured maximum queue
length. If so, we return an error. */
queuelen = pcb->snd_queuelen; queuelen = pcb->snd_queuelen;
if(queuelen >= TCP_SND_QUEUELEN) { if(queuelen >= TCP_SND_QUEUELEN) {
DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: too long queue %d (max %d)\n", queuelen, TCP_SND_QUEUELEN)); DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: too long queue %d (max %d)\n", queuelen, TCP_SND_QUEUELEN));
@ -129,11 +134,15 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
seg = NULL; seg = NULL;
seglen = 0; seglen = 0;
/* First, break up the data into segments and tuck them together in
the local "queue" variable. */
while(queue == NULL || left > 0) { while(queue == NULL || left > 0) {
/* The segment length should be the MSS if the data to be enqueued
is larger than the MSS. */
seglen = left > pcb->mss? pcb->mss: left; seglen = left > pcb->mss? pcb->mss: left;
/* allocate memory for tcp_seg, and fill in fields */ /* Allocate memory for tcp_seg, and fill in fields. */
seg = memp_malloc(MEMP_TCP_SEG); seg = memp_malloc(MEMP_TCP_SEG);
if(seg == NULL) { if(seg == NULL) {
DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: could not allocate memory for tcp_seg\n")); DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: could not allocate memory for tcp_seg\n"));
@ -142,10 +151,10 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
seg->next = NULL; seg->next = NULL;
seg->p = NULL; seg->p = NULL;
if(queue == NULL) { if(queue == NULL) {
queue = seg; queue = seg;
} else { } else {
/* Attach the segment to the end of the queued segments. */
for(useg = queue; useg->next != NULL; useg = useg->next); for(useg = queue; useg->next != NULL; useg = useg->next);
useg->next = seg; useg->next = seg;
} }
@ -172,6 +181,8 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
seg->dataptr = seg->p->payload; seg->dataptr = seg->p->payload;
} else { } else {
/* Do not copy the data. */ /* Do not copy the data. */
/* First, allocate a pbuf for holding the data. */
if((p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_ROM)) == NULL) { if((p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_ROM)) == NULL) {
DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: could not allocate memory for pbuf non-copy\n")); DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: could not allocate memory for pbuf non-copy\n"));
goto memerr; goto memerr;
@ -179,14 +190,23 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
++queuelen; ++queuelen;
p->payload = ptr; p->payload = ptr;
seg->dataptr = ptr; seg->dataptr = ptr;
/* Second, allocate a pbuf for the headers. */
if((seg->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_RAM)) == NULL) { if((seg->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_RAM)) == NULL) {
/* If allocation fails, we have to deallocate the data pbuf as
well. */
pbuf_free(p); pbuf_free(p);
DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: could not allocate memory for header pbuf\n")); DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: could not allocate memory for header pbuf\n"));
goto memerr; goto memerr;
} }
++queuelen; ++queuelen;
/* Chain the headers and data pbufs together. */
pbuf_chain(seg->p, p); pbuf_chain(seg->p, p);
} }
/* Now that there are more segments queued, we check again if the
length of the queue exceeds the configured maximum. */
if(queuelen > TCP_SND_QUEUELEN) { if(queuelen > TCP_SND_QUEUELEN) {
DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: queue too long %d (%d)\n", queuelen, TCP_SND_QUEUELEN)); DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: queue too long %d (%d)\n", queuelen, TCP_SND_QUEUELEN));
goto memerr; goto memerr;
@ -197,7 +217,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
++seg->len; ++seg->len;
}*/ }*/
/* build TCP header */ /* Build TCP header. */
if(pbuf_header(seg->p, TCP_HLEN)) { if(pbuf_header(seg->p, TCP_HLEN)) {
DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: no room for TCP header in pbuf.\n")); DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: no room for TCP header in pbuf.\n"));
@ -215,6 +235,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
TCPH_FLAGS_SET(seg->tcphdr, flags); TCPH_FLAGS_SET(seg->tcphdr, flags);
/* don't fill in tcphdr->ackno and tcphdr->wnd until later */ /* don't fill in tcphdr->ackno and tcphdr->wnd until later */
/* Copy the options into the header, if they are present. */
if(optdata == NULL) { if(optdata == NULL) {
TCPH_OFFSET_SET(seg->tcphdr, 5 << 4); TCPH_OFFSET_SET(seg->tcphdr, 5 << 4);
} else { } else {
@ -235,7 +256,9 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
} }
/* Go to the last segment on the ->unsent queue. */ /* Now that the data to be enqueued has been broken up into TCP
segments in the queue variable, we add them to the end of the
pcb->unsent queue. */
if(pcb->unsent == NULL) { if(pcb->unsent == NULL) {
useg = NULL; useg = NULL;
} else { } else {