// File: /workspace/github_cpp_makefile_star2_O1/nvanbenschoten[P]byzantine-agreement/src/general.cc
// Function: generals::Lieutenant::Decide()
msg::Order Lieutenant::Decide() {
  server_.Listen(
      // Called on all incoming Byzantine Messages.
      [this](udp::ClientPtr client, char* buf, size_t n) {
        auto from = client->RemoteAddress();
        auto msg = ByzantineMsgFromBuf(buf, n);
        if (!msg || !ValidMessage(*msg, from)) {
          // If the message was not valid, return without trying to use it.
          return ContinueUnlessTimeout();
        }

        logging::out << "Received " << *msg << " from p" << msg->ids.back()
                     << "\n";
        SendAckForRound(client, round_);

        bool newRound = false;
        if (FirstRound()) {
          // Only handle the first real order.
          if (msg->order != msg::Order::NO_ORDER && orders_seen_.size() == 0) {
            orders_seen_.insert(msg->order);
            msgs_this_round_.insert(*msg);
            newRound = true;
          }
        } else {
          // Handle if not a replay of a previous message (msg with same ids).
          if (ids_this_round_.count(msg->ids) == 0) {
            ids_this_round_.insert(msg->ids);

            // Handle the order in the message based on if we've seen the same
            // order or not.
            if (msg->order != msg::Order::NO_ORDER &&
                orders_seen_.count(msg->order) == 0) {
              // We have not seen this order yet, so we add it to the
              // orders_seen set and forward it in the next round.
              orders_seen_.insert(msg->order);
            } else {
              // We have already seen this order, so we forward a no_order
              // instead next round.
              msg->order = msg::Order::NO_ORDER;
            }

            // Record the message so we can forward it next round.
            msgs_this_round_.insert(*msg);

            // Determine if this is the last message needed for the round.
            newRound = RoundComplete();
          }
        }

        if (newRound) {
          return MoveToNewRoundOrStop();
        }
        return ContinueUnlessTimeout();
      },
      // Called on socket timeout.
      [this]() { return HandleRoundTimeout(); });

  return DecideOrder();
}

// Assembly:
pushq %rbx
subq $0x40, %rsp
movq %rdi, %rbx
addq $0x68, %rdi
xorps %xmm0, %xmm0
leaq 0x20(%rsp), %rsi
movaps %xmm0, (%rsi)
movaps %xmm0, 0x10(%rsi)
movq %rbx, (%rsi)
leaq 0x97f(%rip), %rax       # 0x1289c
movq %rax, 0x18(%rsi)
leaq 0xcfe(%rip), %rax       # 0x12c26
movq %rax, 0x10(%rsi)
movq %rsp, %rdx
movaps %xmm0, (%rdx)
movaps %xmm0, 0x10(%rdx)
movq %rbx, (%rdx)
leaq 0xd0c(%rip), %rax       # 0x12c4c
movq %rax, 0x18(%rdx)
leaq 0xd09(%rip), %rax       # 0x12c54
movq %rax, 0x10(%rdx)
callq 0x107d2
movq 0x10(%rsp), %rax
testq %rax, %rax
je 0x11f6b
movq %rsp, %rdi
movq %rdi, %rsi
movl $0x3, %edx
callq *%rax
movq 0x30(%rsp), %rax
testq %rax, %rax
je 0x11f84
leaq 0x20(%rsp), %rdi
movq %rdi, %rsi
movl $0x3, %edx
callq *%rax
cmpq $0x1, 0x98(%rbx)
jne 0x11fd8
movq 0x80(%rbx), %rcx
addq $0x78, %rbx
movq %rbx, %rax
testq %rcx, %rcx
je 0x11fbb
movq %rbx, %rax
xorl %edx, %edx
cmpl $0x0, 0x20(%rcx)
setle %dl
cmovgq %rcx, %rax
movq 0x10(%rcx,%rdx,8), %rcx
testq %rcx, %rcx
jne 0x11fa4
movq %rbx, %rcx
cmpq %rbx, %rax
je 0x11fce
cmpl $0x2, 0x20(%rax)
cmovgeq %rbx, %rax
movq %rax, %rcx
movl $0x1, %eax
cmpq %rbx, %rcx
jne 0x11fda
xorl %eax, %eax
addq $0x40, %rsp
popq %rbx
retq
jmp 0x12021
jmp 0x12021
movq %rax, %rbx
movq 0x10(%rsp), %rax
testq %rax, %rax
je 0x11ffe
movq %rsp, %rdi
movq %rdi, %rsi
movl $0x3, %edx
callq *%rax
movq 0x30(%rsp), %rax
testq %rax, %rax
je 0x12017
leaq 0x20(%rsp), %rdi
movq %rdi, %rsi
movl $0x3, %edx
callq *%rax
movq %rbx, %rdi
callq 0x5600
jmp 0x12021
movq %rax, %rdi
callq 0x9b2f
nop