// File: /workspace/github_c_makefile_star2_O0/FH0[P]tun_direct/lwip-2.1.2/src/core/tcp_out.c
// Function: tcp_output_segment
static err_t
tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb, struct netif *netif)
{
  err_t err;
  u16_t len;
  u32_t *opts;
#if TCP_CHECKSUM_ON_COPY
  int seg_chksum_was_swapped = 0;
#endif

  LWIP_ASSERT("tcp_output_segment: invalid seg", seg != NULL);
  LWIP_ASSERT("tcp_output_segment: invalid pcb", pcb != NULL);
  LWIP_ASSERT("tcp_output_segment: invalid netif", netif != NULL);

  if (tcp_output_segment_busy(seg)) {
    /* This should not happen: rexmit functions should have checked this.
       However, since this function modifies p->len, we must not continue in this case. */
    LWIP_DEBUGF(TCP_RTO_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_output_segment: segment busy\n"));
    return ERR_OK;
  }

  /* The TCP header has already been constructed, but the ackno and
   wnd fields remain. */
  seg->tcphdr->ackno = lwip_htonl(pcb->rcv_nxt);

  /* advertise our receive window size in this TCP segment */
#if LWIP_WND_SCALE
  if (seg->flags & TF_SEG_OPTS_WND_SCALE) {
    /* The Window field in a SYN segment itself (the only type where we send
       the window scale option) is never scaled. */
    seg->tcphdr->wnd = lwip_htons(TCPWND_MIN16(pcb->rcv_ann_wnd));
  } else
#endif /* LWIP_WND_SCALE */
  {
    seg->tcphdr->wnd = lwip_htons(TCPWND_MIN16(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd)));
  }

  pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;

  /* Add any requested options.  NB MSS option is only set on SYN
     packets, so ignore it here */
  /* cast through void* to get rid of alignment warnings */
  opts = (u32_t *)(void *)(seg->tcphdr + 1);
  if (seg->flags & TF_SEG_OPTS_MSS) {
    u16_t mss;
#if TCP_CALCULATE_EFF_SEND_MSS
    mss = tcp_eff_send_mss_netif(TCP_MSS, netif, &pcb->remote_ip);
#else /* TCP_CALCULATE_EFF_SEND_MSS */
    mss = TCP_MSS;
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
    *opts = TCP_BUILD_MSS_OPTION(mss);
    opts += 1;
  }
#if LWIP_TCP_TIMESTAMPS
  pcb->ts_lastacksent = pcb->rcv_nxt;

  if (seg->flags & TF_SEG_OPTS_TS) {
    tcp_build_timestamp_option(pcb, opts);
    opts += 3;
  }
#endif
#if LWIP_WND_SCALE
  if (seg->flags & TF_SEG_OPTS_WND_SCALE) {
    tcp_build_wnd_scale_option(opts);
    opts += 1;
  }
#endif
#if LWIP_TCP_SACK_OUT
  if (seg->flags & TF_SEG_OPTS_SACK_PERM) {
    /* Pad with two NOP options to make everything nicely aligned
     * NOTE: When we send both timestamp and SACK_PERM options,
     * we could use the first two NOPs before the timestamp to store SACK_PERM option,
     * but that would complicate the code.
     */
    *(opts++) = PP_HTONL(0x01010402);
  }
#endif

  /* Set retransmission timer running if it is not currently enabled
     This must be set before checking the route. */
  if (pcb->rtime < 0) {
    pcb->rtime = 0;
  }

  if (pcb->rttest == 0) {
    pcb->rttest = tcp_ticks;
    pcb->rtseq = lwip_ntohl(seg->tcphdr->seqno);

    LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq));
  }
  LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n",
                                 lwip_htonl(seg->tcphdr->seqno), lwip_htonl(seg->tcphdr->seqno) +
                                 seg->len));

  len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload);
  if (len == 0) {
    /** Exclude retransmitted segments from this count. */
    MIB2_STATS_INC(mib2.tcpoutsegs);
  }

  seg->p->len -= len;
  seg->p->tot_len -= len;

  seg->p->payload = seg->tcphdr;

  seg->tcphdr->chksum = 0;

#ifdef LWIP_HOOK_TCP_OUT_ADD_TCPOPTS
  opts = LWIP_HOOK_TCP_OUT_ADD_TCPOPTS(seg->p, seg->tcphdr, pcb, opts);
#endif
  LWIP_ASSERT("options not filled", (u8_t *)opts == ((u8_t *)(seg->tcphdr + 1)) + LWIP_TCP_OPT_LENGTH_SEGMENT(seg->flags, pcb));

#if CHECKSUM_GEN_TCP
  IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) {
#if TCP_CHECKSUM_ON_COPY
    u32_t acc;
#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK
    u16_t chksum_slow = ip_chksum_pseudo(seg->p, IP_PROTO_TCP,
                                         seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip);
#endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */
    if ((seg->flags & TF_SEG_DATA_CHECKSUMMED) == 0) {
      LWIP_ASSERT("data included but not checksummed",
                  seg->p->tot_len == TCPH_HDRLEN_BYTES(seg->tcphdr));
    }

    /* rebuild TCP header checksum (TCP header changes for retransmissions!) */
    acc = ip_chksum_pseudo_partial(seg->p, IP_PROTO_TCP,
                                   seg->p->tot_len, TCPH_HDRLEN_BYTES(seg->tcphdr), &pcb->local_ip, &pcb->remote_ip);
    /* add payload checksum */
    if (seg->chksum_swapped) {
      seg_chksum_was_swapped = 1;
      seg->chksum = SWAP_BYTES_IN_WORD(seg->chksum);
      seg->chksum_swapped = 0;
    }
    acc = (u16_t)~acc + seg->chksum;
    seg->tcphdr->chksum = (u16_t)~FOLD_U32T(acc);
#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK
    if (chksum_slow != seg->tcphdr->chksum) {
      TCP_CHECKSUM_ON_COPY_SANITY_CHECK_FAIL(
        ("tcp_output_segment: calculated checksum is %"X16_F" instead of %"X16_F"\n",
         seg->tcphdr->chksum, chksum_slow));
      seg->tcphdr->chksum = chksum_slow;
    }
#endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */
#else /* TCP_CHECKSUM_ON_COPY */
    seg->tcphdr->chksum = ip_chksum_pseudo(seg->p, IP_PROTO_TCP,
                                           seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip);
#endif /* TCP_CHECKSUM_ON_COPY */
  }
#endif /* CHECKSUM_GEN_TCP */
  TCP_STATS_INC(tcp.xmit);

  NETIF_SET_HINTS(netif, &(pcb->netif_hints));
  err = ip_output_if(seg->p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl,
                     pcb->tos, IP_PROTO_TCP, netif);
  NETIF_RESET_HINTS(netif);

#if TCP_CHECKSUM_ON_COPY
  if (seg_chksum_was_swapped) {
    /* if data is added to this segment later, chksum needs to be swapped,
       so restore this now */
    seg->chksum = SWAP_BYTES_IN_WORD(seg->chksum);
    seg->chksum_swapped = 1;
  }
#endif

  return err;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movl $0x0, -0x34(%rbp)
cmpq $0x0, -0x10(%rbp)
jne 0x15613
jmp 0x155e4
leaq 0x11ce1(%rip), %rdi     # 0x272cc
leaq 0x13af2(%rip), %rsi     # 0x290e4
movl $0x5b8, %edx            # imm = 0x5B8
leaq 0x133d4(%rip), %rcx     # 0x289d2
movb $0x0, %al
callq 0x20d0
xorl %eax, %eax
movl %eax, %edi
callq 0x21b0
callq 0x2040
jmp 0x15615
jmp 0x15617
cmpq $0x0, -0x18(%rbp)
jne 0x1564f
jmp 0x15620
leaq 0x11ca5(%rip), %rdi     # 0x272cc
leaq 0x13ad6(%rip), %rsi     # 0x29104
movl $0x5b9, %edx            # imm = 0x5B9
leaq 0x13398(%rip), %rcx     # 0x289d2
movb $0x0, %al
callq 0x20d0
xorl %eax, %eax
movl %eax, %edi
callq 0x21b0
callq 0x2040
jmp 0x15651
jmp 0x15653
cmpq $0x0, -0x20(%rbp)
jne 0x1568b
jmp 0x1565c
leaq 0x11c69(%rip), %rdi     # 0x272cc
leaq 0x13aba(%rip), %rsi     # 0x29124
movl $0x5ba, %edx            # imm = 0x5BA
leaq 0x1335c(%rip), %rcx     # 0x289d2
movb $0x0, %al
callq 0x20d0
xorl %eax, %eax
movl %eax, %edi
callq 0x21b0
callq 0x2040
jmp 0x1568d
movq -0x10(%rbp), %rdi
callq 0x15ce0
cmpl $0x0, %eax
je 0x156a8
jmp 0x1569d
jmp 0x1569f
movb $0x0, -0x1(%rbp)
jmp 0x15b24
movq -0x18(%rbp), %rax
movl 0x5c(%rax), %edi
callq 0x251f0
movl %eax, %ecx
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rax
movl %ecx, 0x8(%rax)
movq -0x18(%rbp), %rax
movzwl 0x62(%rax), %edi
callq 0x251c0
movw %ax, %cx
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rax
movw %cx, 0xe(%rax)
movq -0x18(%rbp), %rax
movl 0x5c(%rax), %ecx
movq -0x18(%rbp), %rax
movzwl 0x62(%rax), %eax
addl %eax, %ecx
movq -0x18(%rbp), %rax
movl %ecx, 0x64(%rax)
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rax
addq $0x14, %rax
movq %rax, -0x30(%rbp)
movq -0x10(%rbp), %rax
movzbl 0x17(%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
je 0x15758
movq -0x20(%rbp), %rsi
movq -0x18(%rbp), %rdx
addq $0x18, %rdx
movl $0x5b4, %edi            # imm = 0x5B4
callq 0xd140
movw %ax, -0x36(%rbp)
movzwl -0x36(%rbp), %edi
andl $0xffff, %edi           # imm = 0xFFFF
orl $0x2040000, %edi        # imm = 0x2040000
callq 0x251f0
movl %eax, %ecx
movq -0x30(%rbp), %rax
movl %ecx, (%rax)
movq -0x30(%rbp), %rax
addq $0x4, %rax
movq %rax, -0x30(%rbp)
movq -0x18(%rbp), %rax
movswl 0x68(%rax), %eax
cmpl $0x0, %eax
jge 0x1576f
movq -0x18(%rbp), %rax
movw $0x0, 0x68(%rax)
movq -0x18(%rbp), %rax
cmpl $0x0, 0x6c(%rax)
jne 0x157a6
leaq 0x1a19c(%rip), %rax     # 0x2f91c
movl (%rax), %ecx
movq -0x18(%rbp), %rax
movl %ecx, 0x6c(%rax)
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rax
movl 0x4(%rax), %edi
callq 0x251f0
movl %eax, %ecx
movq -0x18(%rbp), %rax
movl %ecx, 0x70(%rax)
jmp 0x157a4
jmp 0x157a6
jmp 0x157a8
jmp 0x157aa
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rax
movq -0x10(%rbp), %rcx
movq 0x8(%rcx), %rcx
movq 0x8(%rcx), %rcx
subq %rcx, %rax
movw %ax, -0x24(%rbp)
movzwl -0x24(%rbp), %eax
cmpl $0x0, %eax
jne 0x157d0
jmp 0x157d0
movzwl -0x24(%rbp), %edx
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movzwl 0x12(%rax), %ecx
subl %edx, %ecx
movw %cx, 0x12(%rax)
movzwl -0x24(%rbp), %edx
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movzwl 0x10(%rax), %ecx
subl %edx, %ecx
movw %cx, 0x10(%rax)
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rcx
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq %rcx, 0x8(%rax)
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rax
movw $0x0, 0x10(%rax)
movq -0x30(%rbp), %rax
movq -0x10(%rbp), %rcx
movq 0x18(%rcx), %rcx
addq $0x14, %rcx
movq -0x10(%rbp), %rdx
movzbl 0x17(%rdx), %edi
andl $0x1, %edi
xorl %edx, %edx
movl $0x4, %esi
cmpl $0x0, %edi
cmovnel %esi, %edx
movslq %edx, %rdx
addq %rdx, %rcx
movq -0x10(%rbp), %rdx
movzbl 0x17(%rdx), %esi
andl $0x2, %esi
xorl %edx, %edx
cmpl $0x0, %esi
cmovnel %edx, %edx
movslq %edx, %rdx
addq %rdx, %rcx
movq -0x10(%rbp), %rdx
movzbl 0x17(%rdx), %esi
andl $0x8, %esi
xorl %edx, %edx
cmpl $0x0, %esi
cmovnel %edx, %edx
movslq %edx, %rdx
addq %rdx, %rcx
movq -0x10(%rbp), %rdx
movzbl 0x17(%rdx), %esi
andl $0x10, %esi
xorl %edx, %edx
cmpl $0x0, %esi
cmovnel %edx, %edx
movslq %edx, %rdx
addq %rdx, %rcx
cmpq %rcx, %rax
je 0x158cd
jmp 0x1589e
leaq 0x11a27(%rip), %rdi     # 0x272cc
leaq 0x1389a(%rip), %rsi     # 0x29146
movl $0x61c, %edx            # imm = 0x61C
leaq 0x1311a(%rip), %rcx     # 0x289d2
movb $0x0, %al
callq 0x20d0
xorl %eax, %eax
movl %eax, %edi
callq 0x21b0
callq 0x2040
jmp 0x158cf
movq -0x10(%rbp), %rax
movzbl 0x17(%rax), %eax
andl $0x4, %eax
cmpl $0x0, %eax
jne 0x1594f
jmp 0x158e1
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movzwl 0x10(%rax), %eax
movl %eax, -0x40(%rbp)
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rax
movzwl 0xc(%rax), %edi
callq 0x251c0
movw %ax, %cx
movl -0x40(%rbp), %eax
movzwl %cx, %ecx
sarl $0xc, %ecx
movzwl %cx, %ecx
shll $0x2, %ecx
movzbl %cl, %ecx
cmpl %ecx, %eax
je 0x1594b
jmp 0x1591c
leaq 0x119a9(%rip), %rdi     # 0x272cc
leaq 0x1382f(%rip), %rsi     # 0x29159
movl $0x628, %edx            # imm = 0x628
leaq 0x1309c(%rip), %rcx     # 0x289d2
movb $0x0, %al
callq 0x20d0
xorl %eax, %eax
movl %eax, %edi
callq 0x21b0
callq 0x2040
jmp 0x1594d
jmp 0x1594f
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x50(%rbp)
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movw 0x10(%rax), %ax
movw %ax, -0x42(%rbp)
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rax
movzwl 0xc(%rax), %edi
callq 0x251c0
movq -0x50(%rbp), %rdi
movw -0x42(%rbp), %cx
movzwl %ax, %eax
sarl $0xc, %eax
movzwl %ax, %eax
shll $0x2, %eax
movzbl %al, %eax
movq -0x18(%rbp), %r8
movq -0x18(%rbp), %r9
addq $0x18, %r9
movl $0x6, %esi
movzwl %cx, %edx
movzwl %ax, %ecx
callq 0x25e80
movzwl %ax, %eax
movl %eax, -0x3c(%rbp)
movq -0x10(%rbp), %rax
cmpb $0x0, 0x16(%rax)
je 0x159fc
movl $0x1, -0x34(%rbp)
movq -0x10(%rbp), %rax
movzwl 0x14(%rax), %eax
andl $0xff, %eax
shll $0x8, %eax
movq -0x10(%rbp), %rcx
movzwl 0x14(%rcx), %ecx
andl $0xff00, %ecx           # imm = 0xFF00
sarl $0x8, %ecx
orl %ecx, %eax
movw %ax, %cx
movq -0x10(%rbp), %rax
movw %cx, 0x14(%rax)
movq -0x10(%rbp), %rax
movb $0x0, 0x16(%rax)
movl -0x3c(%rbp), %eax
xorl $-0x1, %eax
movzwl %ax, %eax
movq -0x10(%rbp), %rcx
movzwl 0x14(%rcx), %ecx
addl %ecx, %eax
movl %eax, -0x3c(%rbp)
movl -0x3c(%rbp), %eax
shrl $0x10, %eax
movl %eax, %eax
movl -0x3c(%rbp), %ecx
andq $0xffff, %rcx           # imm = 0xFFFF
addq %rcx, %rax
xorl $-0x1, %eax
movw %ax, %cx
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rax
movw %cx, 0x10(%rax)
movq -0x18(%rbp), %rax
addq $0x18, %rax
cmpq $0x0, %rax
je 0x15a99
movq -0x18(%rbp), %rax
movzbl 0x2c(%rax), %eax
cmpl $0x6, %eax
jne 0x15a99
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rdi
movq -0x18(%rbp), %rsi
movq -0x18(%rbp), %rdx
addq $0x18, %rdx
movq -0x18(%rbp), %rax
movb 0x33(%rax), %cl
movq -0x18(%rbp), %rax
movb 0x32(%rax), %r8b
movq -0x20(%rbp), %rax
movl $0x6, %r9d
movzbl %cl, %ecx
movzbl %r8b, %r8d
movq %rax, (%rsp)
callq 0x1d560
movsbl %al, %eax
movl %eax, -0x54(%rbp)
jmp 0x15adc
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rdi
movq -0x18(%rbp), %rsi
movq -0x18(%rbp), %rdx
addq $0x18, %rdx
movq -0x18(%rbp), %rax
movb 0x33(%rax), %cl
movq -0x18(%rbp), %rax
movb 0x32(%rax), %r8b
movq -0x20(%rbp), %rax
movl $0x6, %r9d
movzbl %cl, %ecx
movzbl %r8b, %r8d
movq %rax, (%rsp)
callq 0x19c10
movsbl %al, %eax
movl %eax, -0x54(%rbp)
movl -0x54(%rbp), %eax
movb %al, -0x21(%rbp)
cmpl $0x0, -0x34(%rbp)
je 0x15b1e
movq -0x10(%rbp), %rax
movzwl 0x14(%rax), %eax
andl $0xff, %eax
shll $0x8, %eax
movq -0x10(%rbp), %rcx
movzwl 0x14(%rcx), %ecx
andl $0xff00, %ecx           # imm = 0xFF00
sarl $0x8, %ecx
orl %ecx, %eax
movw %ax, %cx
movq -0x10(%rbp), %rax
movw %cx, 0x14(%rax)
movq -0x10(%rbp), %rax
movb $0x1, 0x16(%rax)
movb -0x21(%rbp), %al
movb %al, -0x1(%rbp)
movb -0x1(%rbp), %al
addq $0x60, %rsp
popq %rbp
retq
nopl (%rax)