Lines Matching refs:pcb

81 static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb);
87 * @param pcb tcp pcb for which to send a packet (used to initialize tcp_hdr)
94 tcp_output_alloc_header(struct tcp_pcb *pcb, u16_t optlen, u16_t datalen,
103 tcphdr->src = htons(pcb->local_port);
104 tcphdr->dest = htons(pcb->remote_port);
106 tcphdr->ackno = htonl(pcb->rcv_nxt);
108 tcphdr->wnd = htons(pcb->rcv_ann_wnd);
113 pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
121 * @param pcb the tcp_pcb over which to send a segment
125 tcp_send_fin(struct tcp_pcb *pcb)
128 if (pcb->unsent != NULL) {
130 for (last_unsent = pcb->unsent; last_unsent->next != NULL;
136 pcb->flags |= TF_FIN;
141 return tcp_enqueue_flags(pcb, TCP_FIN);
149 * @param pcb Protocol control block for the TCP connection.
159 tcp_create_segment(struct tcp_pcb *pcb, struct pbuf *p, u8_t flags, u32_t seqno, u8_t optflags)
192 seg->tcphdr->src = htons(pcb->local_port);
193 seg->tcphdr->dest = htons(pcb->remote_port);
212 * @param pcb The TCP connection that willo enqueue the pbuf.
220 u16_t *oversize, struct tcp_pcb *pcb, u8_t apiflags,
228 LWIP_UNUSED_ARG(pcb);
247 (!(pcb->flags & TF_NODELAY) &&
249 pcb->unsent != NULL ||
250 pcb->unacked != NULL))) {
266 #define tcp_pbuf_prealloc(layer, length, mx, os, pcb, api, fst) pbuf_alloc((layer), (length), PBUF_RAM)
289 * @param pcb the tcp pcb to check for
294 tcp_write_checks(struct tcp_pcb *pcb, u16_t len)
297 if ((pcb->state != ESTABLISHED) &&
298 (pcb->state != CLOSE_WAIT) &&
299 (pcb->state != SYN_SENT) &&
300 (pcb->state != SYN_RCVD)) {
308 if (len > pcb->snd_buf) {
310 len, pcb->snd_buf));
311 pcb->flags |= TF_NAGLEMEMERR;
315 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen));
320 if ((pcb->snd_queuelen >= TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
322 pcb->snd_queuelen, TCP_SND_QUEUELEN));
324 pcb->flags |= TF_NAGLEMEMERR;
327 if (pcb->snd_queuelen != 0) {
329 pcb->unacked != NULL || pcb->unsent != NULL);
332 pcb->unacked == NULL && pcb->unsent == NULL);
345 * @param pcb Protocol control block for the TCP connection to enqueue data for.
354 tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
373 u16_t mss_local = LWIP_MIN(pcb->mss, pcb->snd_wnd_max/2);
380 LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, data=%p, len=%"U16_F", apiflags=%"U16_F")\n",
381 (void *)pcb, arg, len, (u16_t)apiflags));
385 err = tcp_write_checks(pcb, len);
389 queuelen = pcb->snd_queuelen;
392 if ((pcb->flags & TF_TIMESTAMP)) {
403 * 2. Chain a new pbuf to the end of pcb->unsent.
407 * return ERR_MEM and not change anything in pcb. Therefore, all
409 * of the function. Some pcb fields are maintained in local copies:
411 * queuelen = pcb->snd_queuelen
412 * oversize = pcb->unsent_oversize
422 if (pcb->unsent != NULL) {
426 /* @todo: this could be sped up by keeping last_unsent in the pcb */
427 for (last_unsent = pcb->unsent; last_unsent->next != NULL;
443 /* check that pcb->unsent_oversize matches last_unsent->unsent_oversize */
444 LWIP_ASSERT("unsent_oversize mismatch (pcb vs. last_unsent)",
445 pcb->unsent_oversize == last_unsent->oversize_left);
447 oversize = pcb->unsent_oversize;
461 * Phase 2: Chain a new pbuf to the end of pcb->unsent.
476 if ((concat_p = tcp_pbuf_prealloc(PBUF_RAW, seglen, space, &oversize, pcb, apiflags, 1)) == NULL) {
511 LWIP_ASSERT("unsent_oversize mismatch (pcb->unsent is NULL)",
512 pcb->unsent_oversize == 0);
520 * variable, ready to be appended to pcb->unsent.
535 if ((p = tcp_pbuf_prealloc(PBUF_TRANSPORT, seglen + optlen, mss_local, &oversize, pcb, apiflags, queue == NULL)) == NULL) {
586 if ((seg = tcp_create_segment(pcb, p, 0, pcb->snd_lbb + pos, optflags)) == NULL) {
643 pcb->unsent_oversize = oversize;
650 LWIP_ASSERT("tcp_write: cannot concatenate when pcb->unsent is empty",
664 * Phase 3: Append queue to pcb->unsent. Queue may be NULL, but that
668 pcb->unsent = queue;
674 * Finally update the pcb state.
676 pcb->snd_lbb += len;
677 pcb->snd_buf -= len;
678 pcb->snd_queuelen = queuelen;
681 pcb->snd_queuelen));
682 if (pcb->snd_queuelen != 0) {
684 pcb->unacked != NULL || pcb->unsent != NULL);
694 pcb->flags |= TF_NAGLEMEMERR;
703 if (pcb->snd_queuelen != 0) {
704 LWIP_ASSERT("tcp_write: valid queue length", pcb->unacked != NULL ||
705 pcb->unsent != NULL);
707 LWIP_DEBUGF(TCP_QLEN_DEBUG | LWIP_DBG_STATE, ("tcp_write: %"S16_F" (with mem err)\n", pcb->snd_queuelen));
716 * @param pcb Protocol control block for the TCP connection.
722 tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags)
729 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue_flags: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen));
735 if ((pcb->snd_queuelen >= TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
737 pcb->snd_queuelen, TCP_SND_QUEUELEN));
739 pcb->flags |= TF_NAGLEMEMERR;
747 if ((pcb->flags & TF_TIMESTAMP)) {
757 if (pcb->snd_buf == 0) {
765 pcb->flags |= TF_NAGLEMEMERR;
773 if ((seg = tcp_create_segment(pcb, p, flags, pcb->snd_lbb, optflags)) == NULL) {
774 pcb->flags |= TF_NAGLEMEMERR;
787 /* Now append seg to pcb->unsent queue */
788 if (pcb->unsent == NULL) {
789 pcb->unsent = seg;
792 for (useg = pcb->unsent; useg->next != NULL; useg = useg->next);
797 pcb->unsent_oversize = 0;
802 pcb->snd_lbb++;
804 pcb->snd_buf--;
807 pcb->flags |= TF_FIN;
811 pcb->snd_queuelen += pbuf_clen(seg->p);
812 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue_flags: %"S16_F" (after enqueued)\n", pcb->snd_queuelen));
813 if (pcb->snd_queuelen != 0) {
815 pcb->unacked != NULL || pcb->unsent != NULL);
824 * @param pcb tcp_pcb
828 tcp_build_timestamp_option(struct tcp_pcb *pcb, u32_t *opts)
833 opts[2] = htonl(pcb->ts_recent);
839 * @param pcb Protocol control block for the TCP connection to send the ACK
842 tcp_send_empty_ack(struct tcp_pcb *pcb)
849 if (pcb->flags & TF_TIMESTAMP) {
854 p = tcp_output_alloc_header(pcb, optlen, 0, htonl(pcb->snd_nxt));
861 ("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt));
863 pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
867 pcb->ts_lastacksent = pcb->rcv_nxt;
869 if (pcb->flags & TF_TIMESTAMP) {
870 tcp_build_timestamp_option(pcb, (u32_t *)(tcphdr + 1));
875 tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),
879 ip_output_hinted(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
880 IP_PROTO_TCP, &(pcb->addr_hint));
882 ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
893 * @param pcb Protocol control block for the TCP connection to send data
898 tcp_output(struct tcp_pcb *pcb)
906 /* pcb->state LISTEN not allowed here */
908 pcb->state != LISTEN);
914 if (tcp_input_pcb == pcb) {
918 wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd);
920 seg = pcb->unsent;
928 if (pcb->flags & TF_ACK_NOW &&
930 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
931 return tcp_send_empty_ack(pcb);
935 useg = pcb->unacked;
943 (void*)pcb->unsent));
951 pcb->snd_wnd, pcb->cwnd, wnd, pcb->lastack));
956 pcb->snd_wnd, pcb->cwnd, wnd,
957 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len,
958 ntohl(seg->tcphdr->seqno), pcb->lastack));
963 ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
970 * either seg->next != NULL or pcb->unacked == NULL;
973 if((tcp_do_output_nagle(pcb) == 0) &&
974 ((pcb->flags & (TF_NAGLEMEMERR | TF_FIN)) == 0)){
979 pcb->snd_wnd, pcb->cwnd, wnd,
981 pcb->lastack,
982 ntohl(seg->tcphdr->seqno), pcb->lastack, i));
986 pcb->unsent = seg->next;
988 if (pcb->state != SYN_SENT) {
990 pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
993 tcp_output_segment(seg, pcb);
995 if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) {
996 pcb->snd_nxt = snd_nxt;
1002 if (pcb->unacked == NULL) {
1003 pcb->unacked = seg;
1012 struct tcp_seg **cur_seg = &(pcb->unacked);
1029 seg = pcb->unsent;
1032 if (pcb->unsent == NULL) {
1034 pcb->unsent_oversize = 0;
1038 pcb->flags &= ~TF_NAGLEMEMERR;
1046 * @param pcb the tcp_pcb for the TCP connection used to send the segment
1049 tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
1060 seg->tcphdr->ackno = htonl(pcb->rcv_nxt);
1063 seg->tcphdr->wnd = htons(pcb->rcv_ann_wnd);
1065 pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
1073 mss = tcp_eff_send_mss(TCP_MSS, &pcb->remote_ip);
1081 pcb->ts_lastacksent = pcb->rcv_nxt;
1084 tcp_build_timestamp_option(pcb, opts);
1091 if (pcb->rtime == -1) {
1092 pcb->rtime = 0;
1097 if (ip_addr_isany(&(pcb->local_ip))) {
1098 netif = ip_route(&(pcb->remote_ip));
1102 ip_addr_copy(pcb->local_ip, netif->ip_addr);
1105 if (pcb->rttest == 0) {
1106 pcb->rttest = tcp_ticks;
1107 pcb->rtseq = ntohl(seg->tcphdr->seqno);
1109 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq));
1128 u16_t chksum_slow = inet_chksum_pseudo(seg->p, &(pcb->local_ip),
1129 &(pcb->remote_ip),
1138 acc = inet_chksum_pseudo_partial(seg->p, &(pcb->local_ip),
1139 &(pcb->remote_ip),
1158 seg->tcphdr->chksum = inet_chksum_pseudo(seg->p, &(pcb->local_ip),
1159 &(pcb->remote_ip),
1166 ip_output_hinted(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
1167 IP_PROTO_TCP, &(pcb->addr_hint));
1169 ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
1180 * matching local pcb was found), tcp_listen_input() (if incoming segment
1225 /* Send output with hardcoded TTL since we have no access to the pcb */
1236 * @param pcb the tcp_pcb for which to re-enqueue all unacked segments
1239 tcp_rexmit_rto(struct tcp_pcb *pcb)
1243 if (pcb->unacked == NULL) {
1248 for (seg = pcb->unacked; seg->next != NULL; seg = seg->next);
1250 seg->next = pcb->unsent;
1252 pcb->unsent = pcb->unacked;
1254 pcb->unacked = NULL;
1258 ++pcb->nrtx;
1261 pcb->rttest = 0;
1264 tcp_output(pcb);
1272 * @param pcb the tcp_pcb for which to retransmit the first unacked segment
1275 tcp_rexmit(struct tcp_pcb *pcb)
1280 if (pcb->unacked == NULL) {
1286 seg = pcb->unacked;
1287 pcb->unacked = seg->next;
1289 cur_seg = &(pcb->unsent);
1299 pcb->unsent_oversize = 0;
1303 ++pcb->nrtx;
1306 pcb->rttest = 0;
1318 * @param pcb the tcp_pcb for which to retransmit the first unacked segment
1321 tcp_rexmit_fast(struct tcp_pcb *pcb)
1323 if (pcb->unacked != NULL && !(pcb->flags & TF_INFR)) {
1328 (u16_t)pcb->dupacks, pcb->lastack,
1329 ntohl(pcb->unacked->tcphdr->seqno)));
1330 tcp_rexmit(pcb);
1334 if (pcb->cwnd > pcb->snd_wnd) {
1335 pcb->ssthresh = pcb->snd_wnd / 2;
1337 pcb->ssthresh = pcb->cwnd / 2;
1341 if (pcb->ssthresh < 2*pcb->mss) {
1345 pcb->ssthresh, 2*pcb->mss));
1346 pcb->ssthresh = 2*pcb->mss;
1349 pcb->cwnd = pcb->ssthresh + 3 * pcb->mss;
1350 pcb->flags |= TF_INFR;
1361 * @param pcb the tcp_pcb for which to send a keepalive packet
1364 tcp_keepalive(struct tcp_pcb *pcb)
1370 ip4_addr1_16(&pcb->remote_ip), ip4_addr2_16(&pcb->remote_ip),
1371 ip4_addr3_16(&pcb->remote_ip), ip4_addr4_16(&pcb->remote_ip)));
1373 LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F" pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n",
1374 tcp_ticks, pcb->tmr, pcb->keep_cnt_sent));
1376 p = tcp_output_alloc_header(pcb, 0, 0, htonl(pcb->snd_nxt - 1));
1385 tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip,
1392 ip_output_hinted(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP,
1393 &(pcb->addr_hint));
1395 ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
1401 pcb->snd_nxt - 1, pcb->rcv_nxt));
1411 * @param pcb the tcp_pcb for which to send a zero-window probe packet
1414 tcp_zero_window_probe(struct tcp_pcb *pcb)
1425 ip4_addr1_16(&pcb->remote_ip), ip4_addr2_16(&pcb->remote_ip),
1426 ip4_addr3_16(&pcb->remote_ip), ip4_addr4_16(&pcb->remote_ip)));
1430 " pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n",
1431 tcp_ticks, pcb->tmr, pcb->keep_cnt_sent));
1433 seg = pcb->unacked;
1436 seg = pcb->unsent;
1446 p = tcp_output_alloc_header(pcb, 0, len, seg->tcphdr->seqno);
1466 tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip,
1473 ip_output_hinted(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP,
1474 &(pcb->addr_hint));
1476 ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
1483 pcb->snd_nxt - 1, pcb->rcv_nxt));