// File: /workspace/github_cpp_makefile_star2_O3/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
xorl %eax, %eax
leaq 0x20(%rsp), %rsi
movq %rax, 0x8(%rsi)
movq %rbx, (%rsi)
leaq 0x92f(%rip), %rcx       # 0x1271e
movq %rcx, 0x18(%rsi)
leaq 0xdcc(%rip), %rcx       # 0x12bc6
movq %rcx, 0x10(%rsi)
movq %rsp, %rdx
movq %rax, 0x8(%rdx)
movq %rbx, (%rdx)
leaq 0xddd(%rip), %rax       # 0x12bec
movq %rax, 0x18(%rdx)
leaq 0xdda(%rip), %rax       # 0x12bf4
movq %rax, 0x10(%rdx)
callq 0x105c6
movq 0x10(%rsp), %rax
testq %rax, %rax
je 0x11e3a
movq %rsp, %rdi
movq %rdi, %rsi
movl $0x3, %edx
callq *%rax
movq 0x30(%rsp), %rax
testq %rax, %rax
je 0x11e53
leaq 0x20(%rsp), %rdi
movq %rdi, %rsi
movl $0x3, %edx
callq *%rax
cmpq $0x1, 0x98(%rbx)
jne 0x11e97
movq 0x80(%rbx), %rax
testq %rax, %rax
je 0x11e97
addq $0x78, %rbx
movq %rbx, %rcx
xorl %edx, %edx
cmpl $0x0, 0x20(%rax)
setle %dl
cmovgq %rax, %rcx
movq 0x10(%rax,%rdx,8), %rax
testq %rax, %rax
jne 0x11e70
cmpq %rbx, %rcx
je 0x11e97
movl $0x1, %eax
cmpl $0x2, 0x20(%rcx)
jl 0x11e99
xorl %eax, %eax
addq $0x40, %rsp
popq %rbx
retq
jmp 0x11ee0
jmp 0x11ee0
movq %rax, %rbx
movq 0x10(%rsp), %rax
testq %rax, %rax
je 0x11ebd
movq %rsp, %rdi
movq %rdi, %rsi
movl $0x3, %edx
callq *%rax
movq 0x30(%rsp), %rax
testq %rax, %rax
je 0x11ed6
leaq 0x20(%rsp), %rdi
movq %rdi, %rsi
movl $0x3, %edx
callq *%rax
movq %rbx, %rdi
callq 0x5600
jmp 0x11ee0
movq %rax, %rdi
callq 0x9b59