// File: /workspace/github_c_makefile_star2_O2/FH0[P]tun_direct/lwip-2.1.2/src/core/tcp_out.c
// Function: tcp_zero_window_probe
err_t
tcp_zero_window_probe(struct tcp_pcb *pcb)
{
  err_t err;
  struct pbuf *p;
  struct tcp_hdr *tcphdr;
  struct tcp_seg *seg;
  u16_t len;
  u8_t is_fin;
  u32_t snd_nxt;
  u8_t optlen = LWIP_TCP_OPT_LENGTH_SEGMENT(0, pcb);

  LWIP_ASSERT("tcp_zero_window_probe: invalid pcb", pcb != NULL);

  LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: sending ZERO WINDOW probe to "));
  ip_addr_debug_print_val(TCP_DEBUG, pcb->remote_ip);
  LWIP_DEBUGF(TCP_DEBUG, ("\n"));

  LWIP_DEBUGF(TCP_DEBUG,
              ("tcp_zero_window_probe: tcp_ticks %"U32_F
               "   pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n",
               tcp_ticks, pcb->tmr, (u16_t)pcb->keep_cnt_sent));

  /* Only consider unsent, persist timer should be off when there is data in-flight */
  seg = pcb->unsent;
  if (seg == NULL) {
    /* Not expected, persist timer should be off when the send buffer is empty */
    return ERR_OK;
  }

  /* increment probe count. NOTE: we record probe even if it fails
     to actually transmit due to an error. This ensures memory exhaustion/
     routing problem doesn't leave a zero-window pcb as an indefinite zombie.
     RTO mechanism has similar behavior, see pcb->nrtx */
  if (pcb->persist_probe < 0xFF) {
    ++pcb->persist_probe;
  }

  is_fin = ((TCPH_FLAGS(seg->tcphdr) & TCP_FIN) != 0) && (seg->len == 0);
  /* we want to send one seqno: either FIN or data (no options) */
  len = is_fin ? 0 : 1;

  p = tcp_output_alloc_header(pcb, optlen, len, seg->tcphdr->seqno);
  if (p == NULL) {
    LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: no memory for pbuf\n"));
    return ERR_MEM;
  }
  tcphdr = (struct tcp_hdr *)p->payload;

  if (is_fin) {
    /* FIN segment, no data */
    TCPH_FLAGS_SET(tcphdr, TCP_ACK | TCP_FIN);
  } else {
    /* Data segment, copy in one byte from the head of the unacked queue */
    char *d = ((char *)p->payload + TCP_HLEN);
    /* Depending on whether the segment has already been sent (unacked) or not
       (unsent), seg->p->payload points to the IP header or TCP header.
       Ensure we copy the first TCP data byte: */
    pbuf_copy_partial(seg->p, d, 1, seg->p->tot_len - seg->len);
  }

  /* The byte may be acknowledged without the window being opened. */
  snd_nxt = lwip_ntohl(seg->tcphdr->seqno) + 1;
  if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) {
    pcb->snd_nxt = snd_nxt;
  }
  tcp_output_fill_options(pcb, p, 0, optlen);

  err = tcp_output_control_segment(pcb, p, &pcb->local_ip, &pcb->remote_ip);

  LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: seqno %"U32_F
                          " ackno %"U32_F" err %d.\n",
                          pcb->snd_nxt - 1, pcb->rcv_nxt, (int)err));
  return err;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
testq %rdi, %rdi
je 0xc607
movq %rdi, %rbx
movq 0xa8(%rdi), %r12
testq %r12, %r12
je 0xc54e
movb 0xfe(%rbx), %al
cmpb $-0x1, %al
je 0xc538
incb %al
movb %al, 0xfe(%rbx)
movq 0x18(%r12), %rax
movzwl 0xc(%rax), %edi
callq 0x12ed0
testb $0x1, %al
jne 0xc552
xorl %ebp, %ebp
jmp 0xc55d
xorl %eax, %eax
jmp 0xc5a3
cmpw $0x0, 0x10(%r12)
sete %bpl
movl %ebp, %eax
xorb $0x1, %al
movq 0x18(%r12), %rcx
movl 0x4(%rcx), %edx
movzbl %al, %esi
movq %rbx, %rdi
callq 0xc462
testq %rax, %rax
je 0xc5a1
movq %rax, %r14
movq 0x8(%rax), %r15
testb %bpl, %bpl
je 0xc5ac
movzwl 0xc(%r15), %ebp
andl $0xffffc0ff, %ebp       # imm = 0xFFFFC0FF
pushq $0x11
popq %rdi
callq 0x12ed0
orl %ebp, %eax
movw %ax, 0xc(%r15)
jmp 0xc5cd
movb $-0x1, %al
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
addq $0x14, %r15
movq 0x8(%r12), %rdi
movzwl 0x10(%rdi), %eax
subw 0x10(%r12), %ax
movzwl %ax, %ecx
pushq $0x1
popq %rdx
movq %r15, %rsi
callq 0x54e3
leaq 0x18(%rbx), %r15
movq 0x18(%r12), %rax
movl 0x4(%rax), %edi
callq 0x12ed7
incl %eax
cmpl %eax, 0x88(%rbx)
jns 0xc5ee
movl %eax, 0x88(%rbx)
movq %rbx, %rdi
movq %r14, %rsi
movq %rbx, %rdx
movq %r15, %rcx
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
jmp 0xc3a0
leaq 0x7cbe(%rip), %rdi      # 0x142cc
leaq 0x96b9(%rip), %rsi      # 0x15cce
leaq 0x917b(%rip), %rcx      # 0x15797
movl $0x84f, %edx            # imm = 0x84F
xorl %eax, %eax
callq 0x20d0
xorl %edi, %edi
callq 0x21b0
callq 0x2050