00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 #include "lwip/def.h"
00054 #include "lwip/opt.h"
00055
00056 #include "lwip/mem.h"
00057 #include "lwip/memp.h"
00058 #include "lwip/sys.h"
00059
00060 #include "lwip/netif.h"
00061
00062 #include "lwip/inet.h"
00063 #include "lwip/tcp.h"
00064
00065 #include "lwip/stats.h"
00066
00067 #if LWIP_TCP
00068 #define MIN(x,y) (x) < (y)? (x): (y)
00069
00070 #define htons HTONS
00071 #define htonl HTONL
00072
00073
00074 static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb);
00075
00076
00077
00078 err_t
00079 tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags)
00080 {
00081 return tcp_enqueue(pcb, NULL, 0, flags, 1, NULL, 0);
00082
00083 }
00084
00085 err_t
00086 tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t copy)
00087 {
00088 DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, arg=%p, len=%u, copy=%d)\n", (void *)pcb, arg, len, copy));
00089 if(pcb->state == SYN_SENT ||
00090 pcb->state == SYN_RCVD ||
00091 pcb->state == ESTABLISHED ||
00092 pcb->state == CLOSE_WAIT) {
00093 if(len > 0) {
00094 return tcp_enqueue(pcb, (void *)arg, len, 0, copy, NULL, 0);
00095 }
00096 return ERR_OK;
00097 } else {
00098 DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write() called in invalid state\n"));
00099 return ERR_CONN;
00100 }
00101 }
00102
00103 err_t
00104 tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
00105 u8_t flags, u8_t copy,
00106 u8_t *optdata, u8_t optlen)
00107 {
00108 struct pbuf *p;
00109 struct tcp_seg *seg, *useg, *queue;
00110 u32_t left, seqno;
00111 u16_t seglen;
00112 void *ptr;
00113 u8_t queuelen;
00114
00115 DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue(pcb=%p, arg=%p, len=%u, flags=%x, copy=%d)\n", (void *)pcb, arg, len, flags, copy));
00116 left = len;
00117 ptr = arg;
00118
00119 if(len > pcb->snd_buf) {
00120 DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: too much data (len=%d > snd_buf=%d)\n", len, pcb->snd_buf));
00121 return ERR_MEM;
00122 }
00123
00124
00125
00126 seqno = pcb->snd_lbb;
00127
00128 queue = NULL;
00129 DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: queuelen: %d\n", pcb->snd_queuelen));
00130
00131
00132
00133 queuelen = pcb->snd_queuelen;
00134 if(queuelen >= TCP_SND_QUEUELEN) {
00135 DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: too long queue %d (max %d)\n", queuelen, TCP_SND_QUEUELEN));
00136 goto memerr;
00137 }
00138
00139 if(pcb->snd_queuelen != 0) {
00140 LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||
00141 pcb->unsent != NULL);
00142 }
00143
00144 seg = NULL;
00145 seglen = 0;
00146
00147
00148
00149 while(queue == NULL || left > 0) {
00150
00151
00152
00153 seglen = left > pcb->mss? pcb->mss: left;
00154
00155
00156 seg = memp_malloc(MEMP_TCP_SEG);
00157 if(seg == NULL) {
00158 DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: could not allocate memory for tcp_seg\n"));
00159 goto memerr;
00160 }
00161 seg->next = NULL;
00162 seg->p = NULL;
00163
00164 if(queue == NULL) {
00165 queue = seg;
00166 }
00167 else {
00168
00169 for(useg = queue; useg->next != NULL; useg = useg->next);
00170 useg->next = seg;
00171 }
00172
00173
00174
00175
00176
00177 if (optdata != NULL) {
00178 if((seg->p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) {
00179 goto memerr;
00180 }
00181 ++queuelen;
00182 seg->dataptr = seg->p->payload;
00183 }
00184 else if (copy) {
00185 if((seg->p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_RAM)) == NULL) {
00186 DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: could not allocate memory for pbuf copy size %u\n", seglen));
00187 goto memerr;
00188 }
00189 ++queuelen;
00190 if(arg != NULL) {
00191 memcpy(seg->p->payload, ptr, seglen);
00192 }
00193 seg->dataptr = seg->p->payload;
00194 }
00195
00196 else {
00197
00198
00199
00200
00201
00202
00203 if((p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_ROM)) == NULL) {
00204 DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: could not allocate memory for zero-copy pbuf\n"));
00205 goto memerr;
00206 }
00207 ++queuelen;
00208 p->payload = ptr;
00209 seg->dataptr = ptr;
00210
00211
00212 if((seg->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_RAM)) == NULL) {
00213
00214
00215 pbuf_free(p);
00216 DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: could not allocate memory for header pbuf\n"));
00217 goto memerr;
00218 }
00219 ++queuelen;
00220
00221
00222 pbuf_chain(seg->p, p);
00223 }
00224
00225
00226
00227 if(queuelen > TCP_SND_QUEUELEN) {
00228 DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: queue too long %d (%d)\n", queuelen, TCP_SND_QUEUELEN));
00229 goto memerr;
00230 }
00231
00232 seg->len = seglen;
00233
00234
00235
00236
00237
00238 if(pbuf_header(seg->p, TCP_HLEN)) {
00239
00240 DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: no room for TCP header in pbuf.\n"));
00241
00242 #ifdef TCP_STATS
00243 ++lwip_stats.tcp.err;
00244 #endif
00245 goto memerr;
00246 }
00247 seg->tcphdr = seg->p->payload;
00248 seg->tcphdr->src = htons(pcb->local_port);
00249 seg->tcphdr->dest = htons(pcb->remote_port);
00250 seg->tcphdr->seqno = htonl(seqno);
00251 seg->tcphdr->urgp = 0;
00252 TCPH_FLAGS_SET(seg->tcphdr, flags);
00253
00254
00255
00256 if(optdata == NULL) {
00257 TCPH_OFFSET_SET(seg->tcphdr, 5 << 4);
00258 }
00259 else {
00260 TCPH_OFFSET_SET(seg->tcphdr, (5 + optlen / 4) << 4);
00261
00262
00263
00264 memcpy(seg->dataptr, optdata, optlen);
00265 }
00266 DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: queueing %lu:%lu (0x%x)\n",
00267 ntohl(seg->tcphdr->seqno),
00268 ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
00269 flags));
00270
00271 left -= seglen;
00272 seqno += seglen;
00273 ptr = (void *)((char *)ptr + seglen);
00274 }
00275
00276
00277
00278
00279
00280 if(pcb->unsent == NULL) {
00281 useg = NULL;
00282 }
00283 else {
00284 for(useg = pcb->unsent; useg->next != NULL; useg = useg->next);
00285 }
00286
00287
00288
00289 if(useg != NULL &&
00290 TCP_TCPLEN(useg) != 0 &&
00291 !(TCPH_FLAGS(useg->tcphdr) & (TCP_SYN | TCP_FIN)) &&
00292 !(flags & (TCP_SYN | TCP_FIN)) &&
00293 useg->len + queue->len <= pcb->mss) {
00294
00295 pbuf_header(queue->p, -TCP_HLEN);
00296 pbuf_chain(useg->p, queue->p);
00297 useg->len += queue->len;
00298 useg->next = queue->next;
00299
00300 DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue: chaining, new len %u\n", useg->len));
00301 if(seg == queue) {
00302 seg = NULL;
00303 }
00304 memp_free(MEMP_TCP_SEG, queue);
00305 }
00306 else {
00307 if(useg == NULL) {
00308 pcb->unsent = queue;
00309
00310 }
00311 else {
00312 useg->next = queue;
00313 }
00314 }
00315 if((flags & TCP_SYN) || (flags & TCP_FIN)) {
00316 ++len;
00317 }
00318 pcb->snd_lbb += len;
00319 pcb->snd_buf -= len;
00320 pcb->snd_queuelen = queuelen;
00321 DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %d (after enqueued)\n", pcb->snd_queuelen));
00322 if(pcb->snd_queuelen != 0) {
00323 LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||
00324 pcb->unsent != NULL);
00325
00326 }
00327
00328
00329
00330 if(seg != NULL && seglen > 0 && seg->tcphdr != NULL) {
00331 TCPH_FLAGS_SET(seg->tcphdr, TCPH_FLAGS(seg->tcphdr) | TCP_PSH);
00332 }
00333
00334 return ERR_OK;
00335 memerr:
00336 #ifdef TCP_STATS
00337 ++lwip_stats.tcp.memerr;
00338 #endif
00339
00340 if(queue != NULL) {
00341 tcp_segs_free(queue);
00342 }
00343 if(pcb->snd_queuelen != 0) {
00344 LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||
00345 pcb->unsent != NULL);
00346
00347 }
00348 DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %d (with mem err)\n", pcb->snd_queuelen));
00349 return ERR_MEM;
00350 }
00351
00352
00353 err_t
00354 tcp_output(struct tcp_pcb *pcb)
00355 {
00356 struct pbuf *p;
00357 struct tcp_hdr *tcphdr;
00358 struct tcp_seg *seg, *useg;
00359 u32_t wnd;
00360 #if TCP_CWND_DEBUG
00361 int i = 0;
00362 #endif
00363
00364
00365
00366
00367
00368 if(tcp_input_pcb == pcb) {
00369 return ERR_OK;
00370 }
00371
00372 wnd = MIN(pcb->snd_wnd, pcb->cwnd);
00373
00374
00375 seg = pcb->unsent;
00376
00377
00378
00379
00380
00381
00382
00383 if(pcb->flags & TF_ACK_NOW &&
00384 (seg == NULL ||
00385 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
00386 pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
00387 p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
00388 if(p == NULL) {
00389 DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n"));
00390 return ERR_BUF;
00391 }
00392 DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: sending ACK for %lu\n", pcb->rcv_nxt));
00393
00394 tcphdr = p->payload;
00395 tcphdr->src = htons(pcb->local_port);
00396 tcphdr->dest = htons(pcb->remote_port);
00397 tcphdr->seqno = htonl(pcb->snd_nxt);
00398 tcphdr->ackno = htonl(pcb->rcv_nxt);
00399 TCPH_FLAGS_SET(tcphdr, TCP_ACK);
00400 tcphdr->wnd = htons(pcb->rcv_wnd);
00401 tcphdr->urgp = 0;
00402 TCPH_OFFSET_SET(tcphdr, 5 << 4);
00403
00404 tcphdr->chksum = 0;
00405 tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),
00406 IP_PROTO_TCP, p->tot_len);
00407
00408 ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), TCP_TTL,
00409 IP_PROTO_TCP);
00410 pbuf_free(p);
00411
00412 return ERR_OK;
00413 }
00414
00415 #if TCP_OUTPUT_DEBUG
00416 if(seg == NULL) {
00417 DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n", pcb->unsent));
00418 }
00419 #endif
00420 #if TCP_CWND_DEBUG
00421 if(seg == NULL) {
00422 DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %lu, cwnd %lu, wnd %lu, seg == NULL, ack %lu\n",
00423 pcb->snd_wnd, pcb->cwnd, wnd,
00424 pcb->lastack));
00425 } else {
00426 DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %lu, cwnd %lu, wnd %lu, effwnd %lu, seq %lu, ack %lu\n",
00427 pcb->snd_wnd, pcb->cwnd, wnd,
00428 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len,
00429 ntohl(seg->tcphdr->seqno), pcb->lastack));
00430 }
00431 #endif
00432
00433 while(seg != NULL &&
00434 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
00435 #if TCP_CWND_DEBUG
00436 DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %lu, cwnd %lu, wnd %lu, effwnd %lu, seq %lu, ack %lu, i%d\n",
00437 pcb->snd_wnd, pcb->cwnd, wnd,
00438 ntohl(seg->tcphdr->seqno) + seg->len -
00439 pcb->lastack,
00440 ntohl(seg->tcphdr->seqno), pcb->lastack, i));
00441 ++i;
00442 #endif
00443
00444 pcb->unsent = seg->next;
00445
00446 if(pcb->state != SYN_SENT) {
00447 TCPH_FLAGS_SET(seg->tcphdr, TCPH_FLAGS(seg->tcphdr) | TCP_ACK);
00448 pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
00449 }
00450
00451 tcp_output_segment(seg, pcb);
00452 pcb->snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);
00453 if(TCP_SEQ_LT(pcb->snd_max, pcb->snd_nxt)) {
00454 pcb->snd_max = pcb->snd_nxt;
00455 }
00456
00457 if(TCP_TCPLEN(seg) > 0) {
00458 seg->next = NULL;
00459 if(pcb->unacked == NULL) {
00460 pcb->unacked = seg;
00461
00462
00463 } else {
00464 for(useg = pcb->unacked; useg->next != NULL; useg = useg->next);
00465 useg->next = seg;
00466 }
00467 } else {
00468 tcp_seg_free(seg);
00469 }
00470 seg = pcb->unsent;
00471 }
00472 return ERR_OK;
00473 }
00474
00475 static void
00476 tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
00477 {
00478 u16_t len;
00479 struct netif *netif;
00480
00481
00482
00483 seg->tcphdr->ackno = htonl(pcb->rcv_nxt);
00484
00485
00486 if(pcb->rcv_wnd < pcb->mss) {
00487 seg->tcphdr->wnd = 0;
00488 } else {
00489
00490 seg->tcphdr->wnd = htons(pcb->rcv_wnd);
00491 }
00492
00493
00494
00495 if(ip_addr_isany(&(pcb->local_ip))) {
00496 netif = ip_route(&(pcb->remote_ip));
00497 if(netif == NULL) {
00498 return;
00499 }
00500 ip_addr_set(&(pcb->local_ip), &(netif->ip_addr));
00501 }
00502
00503 pcb->rtime = 0;
00504
00505 if(pcb->rttest == 0) {
00506 pcb->rttest = tcp_ticks;
00507 pcb->rtseq = ntohl(seg->tcphdr->seqno);
00508
00509 DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %lu\n", pcb->rtseq));
00510 }
00511 DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %lu:%lu\n",
00512 htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) +
00513 seg->len));
00514
00515 len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload);
00516
00517 seg->p->len -= len;
00518 seg->p->tot_len -= len;
00519
00520 seg->p->payload = seg->tcphdr;
00521
00522 seg->tcphdr->chksum = 0;
00523 seg->tcphdr->chksum = inet_chksum_pseudo(seg->p,
00524 &(pcb->local_ip),
00525 &(pcb->remote_ip),
00526 IP_PROTO_TCP, seg->p->tot_len);
00527 #ifdef TCP_STATS
00528 ++lwip_stats.tcp.xmit;
00529 #endif
00530
00531 ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), TCP_TTL,
00532 IP_PROTO_TCP);
00533 }
00534
00535 void
00536 tcp_rst(u32_t seqno, u32_t ackno,
00537 struct ip_addr *local_ip, struct ip_addr *remote_ip,
00538 u16_t local_port, u16_t remote_port)
00539 {
00540 struct pbuf *p;
00541 struct tcp_hdr *tcphdr;
00542 p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
00543 if(p == NULL) {
00544 DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n"));
00545 return;
00546 }
00547
00548 tcphdr = p->payload;
00549 tcphdr->src = htons(local_port);
00550 tcphdr->dest = htons(remote_port);
00551 tcphdr->seqno = htonl(seqno);
00552 tcphdr->ackno = htonl(ackno);
00553 TCPH_FLAGS_SET(tcphdr, TCP_RST | TCP_ACK);
00554 tcphdr->wnd = htons(TCP_WND);
00555 tcphdr->urgp = 0;
00556 TCPH_OFFSET_SET(tcphdr, 5 << 4);
00557
00558 tcphdr->chksum = 0;
00559 tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip,
00560 IP_PROTO_TCP, p->tot_len);
00561
00562 #ifdef TCP_STATS
00563 ++lwip_stats.tcp.xmit;
00564 #endif
00565 ip_output(p, local_ip, remote_ip, TCP_TTL, IP_PROTO_TCP);
00566 pbuf_free(p);
00567 DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %lu ackno %lu.\n", seqno, ackno));
00568 }
00569
00570 void
00571 tcp_rexmit(struct tcp_pcb *pcb)
00572 {
00573 struct tcp_seg *seg;
00574
00575 if(pcb->unacked == NULL) {
00576 return;
00577 }
00578
00579
00580 for(seg = pcb->unacked; seg->next != NULL; seg = seg->next);
00581
00582 seg->next = pcb->unsent;
00583 pcb->unsent = pcb->unacked;
00584
00585 pcb->unacked = NULL;
00586
00587
00588 pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno);
00589
00590 ++pcb->nrtx;
00591
00592
00593 pcb->rttest = 0;
00594
00595
00596 tcp_output(pcb);
00597
00598 }
00599 #endif
00600
00601
00602
00603
00604
00605
00606
00607
00608