// File: nvanbenschoten[P]byzantine-agreement/src/general.cc
// Function: generals::SendMessage(std::shared_ptr<udp::Client const>, msg::Message const&)
void SendMessage(udp::ClientPtr client, const msg::Message& msg) {
  size_t size =
      sizeof(msg::ByzantineMessage) + sizeof(uint32_t) * msg.ids.size();
  char buf[size];
  bzero(buf, size);

  // Copy the message part.
  msg::ByzantineMessage* c_msg = reinterpret_cast<msg::ByzantineMessage*>(buf);
  c_msg->type = htonl(kByzantineMessageType);
  c_msg->size = htonl(size);
  c_msg->round = htonl(msg.round);
  c_msg->order = htonl(static_cast<int>(msg.order));

  // C++ does not support flexible arrays, so we need to be a little tricky
  // here. We already made sure the buffer was the correct size by adding space
  // for each of the ids at the end of ByzantineMessage. Now we populate the
  // array.
  uint32_t* id_buf = reinterpret_cast<uint32_t*>(buf + sizeof(*c_msg));
  for (size_t i = 0; i < msg.ids.size(); ++i) {
    id_buf[i] = htonl(msg.ids[i]);
  }

  // Passed to SendWithAck to verify that any acknowledgement we hear is valid.
  auto isValidAck = [msg](udp::ClientPtr _, char* buf, size_t n) {
    auto ackRound = RoundOfAck(buf, n);
    bool valid = ackRound && *ackRound == msg.round;
    if (!valid) return udp::ServerAction::Continue;
    return udp::ServerAction::Stop;
  };

  client->SendWithAck(buf, size, kSendAttempts, isValidAck);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xc0, %rsp
movq %rdi, -0xa0(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x10(%rbp), %rdi
addq $0x8, %rdi
callq 0x25170
leaq 0x10(,%rax,4), %rax
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
movq %rsp, %rcx
movq %rcx, -0x20(%rbp)
movq %rax, %rcx
addq $0xf, %rcx
andq $-0x10, %rcx
movq %rsp, %rdi
subq %rcx, %rdi
movq %rdi, -0x98(%rbp)
movq %rdi, %rsp
movq %rax, -0x28(%rbp)
movq -0x18(%rbp), %rdx
xorl %esi, %esi
callq 0x6270
movq -0x98(%rbp), %rax
movq %rax, -0x30(%rbp)
movl $0x1, %edi
callq 0x6320
movl %eax, %ecx
movq -0x30(%rbp), %rax
movl %ecx, (%rax)
movq -0x18(%rbp), %rax
movl %eax, %edi
callq 0x6320
movl %eax, %ecx
movq -0x30(%rbp), %rax
movl %ecx, 0x4(%rax)
movq -0x10(%rbp), %rax
movl (%rax), %edi
callq 0x6320
movl %eax, %ecx
movq -0x30(%rbp), %rax
movl %ecx, 0x8(%rax)
movq -0x10(%rbp), %rax
movl 0x4(%rax), %edi
callq 0x6320
movl %eax, %edx
movq -0x98(%rbp), %rax
movq -0x30(%rbp), %rcx
movl %edx, 0xc(%rcx)
addq $0x10, %rax
movq %rax, -0x38(%rbp)
movq $0x0, -0x40(%rbp)
movq -0x40(%rbp), %rax
movq %rax, -0xa8(%rbp)
movq -0x10(%rbp), %rdi
addq $0x8, %rdi
callq 0x25170
movq %rax, %rcx
movq -0xa8(%rbp), %rax
cmpq %rcx, %rax
jae 0x25af3
movq -0x10(%rbp), %rdi
addq $0x8, %rdi
movq -0x40(%rbp), %rsi
callq 0x25190
movl (%rax), %edi
callq 0x6320
movl %eax, %edx
movq -0x38(%rbp), %rax
movq -0x40(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movq -0x40(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x40(%rbp)
jmp 0x25a99
movq -0x10(%rbp), %rsi
leaq -0x60(%rbp), %rdi
movq %rdi, -0xc0(%rbp)
callq 0x29020
movq -0xa0(%rbp), %rdi
callq 0x29060
movq -0xc0(%rbp), %rsi
movq %rax, -0xb8(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0xb0(%rbp)
leaq -0x80(%rbp), %rdi
callq 0x25bc0
jmp 0x25b37
movq -0xb0(%rbp), %rdx
movq -0x98(%rbp), %rsi
movq -0xb8(%rbp), %rdi
movl $0x3, %ecx
leaq -0x80(%rbp), %r8
callq 0x22c20
jmp 0x25b5c
leaq -0x80(%rbp), %rdi
callq 0x29080
leaq -0x60(%rbp), %rdi
callq 0x25c60
movq -0x20(%rbp), %rax
movq %rax, %rsp
movq %rbp, %rsp
popq %rbp
retq
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
jmp 0x25ba9
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
leaq -0x80(%rbp), %rdi
callq 0x29080
leaq -0x60(%rbp), %rdi
callq 0x25c60
movq -0x88(%rbp), %rdi
callq 0x6750
nop