// File: /workspace/github_cpp_makefile_star2_O1/devanshdalal[P]cloud-computing-concepts-part-2/MP1Node.cpp
// Function: MP1Node::recvCallBack(void*, char*, int)
bool MP1Node::recvCallBack(void *env, char *data, int size)
{
    /*
	 * Your code goes here
	 */
    MessageHdr *msg = (MessageHdr *)data;
    const auto current_time = par->getcurrtime();
    // multicast the membership list.
    vector<MemberListEntry> &memberList = memberNode->memberList;
    switch (msg->msgType)
    {
    case JOINREQ: // this is the introducer.
    {
        AddNode(*(int *)(msg + 1));

        size_t msgsize = sizeof(MessageHdr) + memberList.size() * sizeof(int);
        // cout << "msgsize: " << sizeof(MessageHdr) << " " << sizeof(joinaddr->addr) << " " << sizeof(long) << " " << 1 << "\n";
        MessageHdr *message = (MessageHdr *)malloc(msgsize * sizeof(char));
        message->msgType = JOINREP;
        int *fields = (int *)(message + 1);
        for (int i = 0; i < memberList.size(); ++i)
        {
            fields[i] = memberList[i].getid();
        }
        // multicast to the group.
        PublishToAll(*message, msgsize);
    }
    break;

    case JOINREP:
    {
        // std::cout << "JOINREP " << this_node_ << "\n";
        int nodes = (size - sizeof(MessageHdr)) / sizeof(int);
        int *fields = (int *)(msg + 1);
        for (int i = 0; i < nodes; ++i)
        {
            if (m_.find(fields[i]) != m_.end())
                continue;
            AddNode(fields[i]);
        }
    }
    break;

    case PING:
    {
        const int &src = *(int *)(msg + 1);
        const int &dest = *((int *)(msg + 1) + 1);
        // std::cout << "PING " << this_node_ << " " << src << " " << dest << "\n";
        if (dest == this_node_)
        {
            // send a PONG to the requesting node.
            auto *message = CreateMessage(PONG, this_node_, src);
            Address a(std::to_string(src) + ":0");
            // memcpy(&a.addr, (char *)(msg + 1), sizeof(a.addr));
            emulNet->ENsend(&memberNode->addr, &a, (char *)message, MSGSIZE); // no need to check status
            // local_state_[src] = {FINALWAITING, current_time + WAITING_TIMEOUT, -1};
            free(msg);
        }
        else
        {
            // std::cout << "Indirect PING\n";
            // send a PING to the requested node and later send PONG back to the client to the requesting node.
            auto *message = CreateMessage(PING, this_node_, dest);
            Address a(std::to_string(dest) + ":0");
            emulNet->ENsend(&memberNode->addr, &a, (char *)message, MSGSIZE); // no need to check status
            local_state_[dest] = {FINALWAITING, current_time + WAITING_TIMEOUT, src};
            free(msg);
        }
    }
    break;

    case PONG:
    {
        const int &src = *(int *)(msg + 1);
        // const int &dest = *((int *)(msg + 1) + 1);
        // std::cout << "PONG " << this_node_ << " " << src << " " << dest << "\n";
        auto it = local_state_.find(src);
        if (it != local_state_.end())
        {
            NodeStatus &status = it->second;
            // std::cout << "PONG2 " << status.state << "a\n";
            switch (status.state)
            {
            case TIMEOUTWAITING:
                break;
            case SWIMWAITING:
                break;
            case FINALWAITING:
            {
                // std::cout << "FINALWAITING\n";
                auto *message = CreateMessage(PONG, src, status.node);
                Address a(std::to_string(status.node) + ":0");
                emulNet->ENsend(&memberNode->addr, &a, (char *)message, MSGSIZE);
                free(msg);
            }
            break;
            default:
                break;
            }
        }
        local_state_.erase(src);
        for (auto jt = local_state_.begin(); jt != local_state_.end(); ++jt)
        {
            // std::cout << "local_stateeee: " << jt->first << " " << jt->second.state << " " << jt->second.timeout << jt->second.node << "\n";
        }
        if (m_.find(src) == m_.end())
        {
            // std::cout << "Special case\n";
            // AddNode(src);
        }
    }
    break;

    case FAILED:
    {
        const int &failed = *(int *)(msg + 1);
        // std::cout << "FAILED " << failed << " " << this_node_ << " " << (m_.find(failed) != m_.end()) << " " << m_.size() << " " << memberList.size() << "\n";
        if (m_.find(failed) != m_.end())
        {
            m_.erase(failed);
            for (int i = 0; i < memberList.size(); ++i)
            {
                if (memberList[i].getid() == failed)
                {
                    memberList.erase(memberList.begin() + i);
                    break;
                }
            }
            Address a(std::to_string(failed) + ":0");
#ifdef DEBUGLOG
            log->logNodeRemove(&memberNode->addr, &a);
#endif
        }
    }
    break;

    default:
        break;
    }
    return true;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xc8, %rsp
movl %ecx, %r15d
movq %rdx, %r14
movq %rdi, %rbx
movq 0x18(%rdi), %rdi
callq 0xce42
movl %eax, %ebp
movl (%r14), %eax
cmpq $0x4, %rax
ja 0x4db7
movq 0x20(%rbx), %r13
leaq 0x13ae5(%rip), %rcx     # 0x18004
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movl 0x4(%r14), %esi
movq %rbx, 0x10(%rsp)
movq %rbx, %rdi
callq 0x3df2
movq 0x30(%r13), %rax
subq 0x28(%r13), %rax
sarq $0x3, %rax
movabsq $-0x5555555555555554, %r14 # imm = 0xAAAAAAAAAAAAAAAC
imulq %rax, %r14
addq $0x4, %r14
movq %r14, %rdi
callq 0x3370
movq %rax, %r15
movl $0x1, (%rax)
movq 0x28(%r13), %rdi
cmpq %rdi, 0x30(%r13)
je 0x45ad
xorl %r12d, %r12d
movabsq $-0x5555555555555555, %rbp # imm = 0xAAAAAAAAAAAAAAAB
xorl %ebx, %ebx
addq %r12, %rdi
callq 0xced2
movl %eax, 0x4(%r15,%rbx,4)
incq %rbx
movq 0x28(%r13), %rdi
movq 0x30(%r13), %rax
subq %rdi, %rax
sarq $0x3, %rax
imulq %rbp, %rax
addq $0x18, %r12
cmpq %rbx, %rax
ja 0x4581
movq 0x10(%rsp), %rdi
movq %r15, %rsi
movq %r14, %rdx
callq 0x4e72
jmp 0x4db7
leaq 0x4(%r14), %r15
leaq 0x68(%rbx), %r13
movslq 0x4(%r14), %rcx
xorl %r12d, %r12d
movq %rcx, %rax
xorl %edx, %edx
divq 0x70(%rbx)
movq %r13, %rdi
movq %rdx, %rsi
movq %r15, %rdx
callq 0x63c4
testq %rax, %rax
je 0x45f0
movq (%rax), %r12
testq %r12, %r12
je 0x4d91
cmpl $0x2, 0x10(%r12)
jne 0x4d91
movq %r13, 0x38(%rsp)
movq %rbx, 0x10(%rsp)
movl (%r15), %ebx
movl 0x20(%r12), %ebp
movl $0xc, %edi
callq 0x3370
movl $0x4, (%rax)
movl %ebx, 0x4(%rax)
movq %rax, 0x40(%rsp)
movl %ebp, 0x8(%rax)
movl 0x20(%r12), %r12d
movl %r12d, %ebp
negl %ebp
cmovsl %r12d, %ebp
movl $0x1, %r13d
cmpl $0xa, %ebp
jb 0x4c91
movl $0x4, %r13d
movl $0xd1b71759, %eax       # imm = 0xD1B71759
movl %ebp, %ecx
cmpl $0x63, %ecx
jbe 0x4c88
cmpl $0x3e7, %ecx            # imm = 0x3E7
jbe 0x4c8e
cmpl $0x2710, %ecx           # imm = 0x2710
jb 0x4c91
movl %ecx, %edx
imulq %rax, %rdx
shrq $0x2d, %rdx
addl $0x4, %r13d
cmpl $0x1869f, %ecx          # imm = 0x1869F
movl %edx, %ecx
ja 0x465c
addl $-0x3, %r13d
jmp 0x4c91
leaq 0x30(%rbx), %r15
movslq 0x4(%r14), %rcx
addq $0x4, %r14
movq %rcx, %rax
xorl %edx, %edx
divq 0x38(%rbx)
movq %r15, %rdi
movq %rdx, %rsi
movq %r14, %rdx
callq 0x5d80
testq %rax, %rax
je 0x4db7
cmpq $0x0, (%rax)
je 0x4db7
movq %r15, %rdi
movq %r14, %rsi
callq 0x6658
movq 0x28(%r13), %rdi
cmpq %rdi, 0x30(%r13)
je 0x48df
leaq 0x28(%r13), %rax
movq %rax, 0x10(%rsp)
xorl %r12d, %r12d
movabsq $-0x5555555555555555, %rbp # imm = 0xAAAAAAAAAAAAAAAB
xorl %r15d, %r15d
addq %r12, %rdi
callq 0xced2
cmpl (%r14), %eax
je 0x48cf
incq %r15
movq 0x28(%r13), %rdi
movq 0x30(%r13), %rax
subq %rdi, %rax
sarq $0x3, %rax
imulq %rbp, %rax
addq $0x18, %r12
cmpq %r15, %rax
ja 0x4706
jmp 0x48df
movl 0x8(%r14), %r15d
movq %rbx, 0x10(%rsp)
movl 0xa4(%rbx), %ebx
cmpl %ebx, %r15d
jne 0x4849
movl 0x4(%r14), %r15d
movl $0xc, %edi
callq 0x3370
movl $0x4, (%rax)
movl %ebx, 0x4(%rax)
movq %rax, 0x38(%rsp)
movl %r15d, 0x8(%rax)
movl %r15d, %ebp
negl %ebp
cmovsl %r15d, %ebp
movl $0x1, %r12d
cmpl $0xa, %ebp
movq 0x10(%rsp), %rbx
jb 0x495b
movl $0x4, %r12d
movl $0xd1b71759, %eax       # imm = 0xD1B71759
movl %ebp, %ecx
cmpl $0x63, %ecx
jbe 0x4949
cmpl $0x3e7, %ecx            # imm = 0x3E7
jbe 0x4958
cmpl $0x2710, %ecx           # imm = 0x2710
jb 0x495b
movl %ecx, %edx
imulq %rax, %rdx
shrq $0x2d, %rdx
addl $0x4, %r12d
cmpl $0x1869f, %ecx          # imm = 0x1869F
movl %edx, %ecx
ja 0x479d
addl $-0x3, %r12d
jmp 0x495b
movslq %r15d, %rax
movabsq $0x3fffffffc, %r12      # imm = 0x3FFFFFFFC
addq %rax, %r12
shrq $0x2, %r12
testl %r12d, %r12d
jle 0x4db7
addq $0x4, %r14
leaq 0x30(%rbx), %r15
andl $0x7fffffff, %r12d      # imm = 0x7FFFFFFF
movslq (%r14), %rcx
movq %rcx, %rax
xorl %edx, %edx
divq 0x38(%rbx)
movq %r15, %rdi
movq %rdx, %rsi
movq %r14, %rdx
callq 0x5d80
testq %rax, %rax
je 0x4830
cmpq $0x0, (%rax)
jne 0x483b
movl (%r14), %esi
movq %rbx, %rdi
callq 0x3df2
addq $0x4, %r14
decq %r12
jne 0x480b
jmp 0x4db7
movl $0xc, %edi
callq 0x3370
movl $0x3, (%rax)
movl %ebx, 0x4(%rax)
movq %rax, 0x38(%rsp)
movl %r15d, 0x8(%rax)
movl %r15d, %r12d
negl %r12d
cmovsl %r15d, %r12d
movl $0x1, %r13d
cmpl $0xa, %r12d
jb 0x4a62
movl $0x4, %r13d
movl $0xd1b71759, %eax       # imm = 0xD1B71759
movl %r12d, %ecx
cmpl $0x63, %ecx
jbe 0x494f
cmpl $0x3e7, %ecx            # imm = 0x3E7
jbe 0x4a5f
cmpl $0x2710, %ecx           # imm = 0x2710
jb 0x4a62
movl %ecx, %edx
imulq %rax, %rdx
shrq $0x2d, %rdx
addl $0x4, %r13d
cmpl $0x1869f, %ecx          # imm = 0x1869F
movl %edx, %ecx
ja 0x488d
addl $-0x3, %r13d
jmp 0x4a62
movq 0x10(%rsp), %rdi
addq (%rdi), %r12
movq %r12, %rsi
callq 0x673e
movl (%r14), %r13d
movl %r13d, %ebp
negl %ebp
cmovsl %r13d, %ebp
movl $0x1, %r14d
cmpl $0xa, %ebp
jb 0x4ba6
movl $0x4, %r14d
movl $0xd1b71759, %eax       # imm = 0xD1B71759
movl %ebp, %ecx
cmpl $0x63, %ecx
jbe 0x4b9d
cmpl $0x3e7, %ecx            # imm = 0x3E7
jbe 0x4ba3
cmpl $0x2710, %ecx           # imm = 0x2710
jb 0x4ba6
movl %ecx, %edx
imulq %rax, %rdx
shrq $0x2d, %rdx
addl $0x4, %r14d
cmpl $0x1869f, %ecx          # imm = 0x1869F
movl %edx, %ecx
ja 0x4907
addl $-0x3, %r14d
jmp 0x4ba6
addl $-0x2, %r12d
jmp 0x495b
addl $-0x2, %r13d
jmp 0x4a62
decl %r12d
shrl $0x1f, %r15d
movl %r15d, %esi
addl %r12d, %esi
leaq 0x28(%rsp), %rax
movq %rax, -0x10(%rax)
leaq 0x18(%rsp), %r13
movq %r13, %rdi
movl $0x2d, %edx
callq 0x32f0
movq (%r13), %rdi
addq %r15, %rdi
movl %r12d, %esi
movl %ebp, %edx
callq 0x5d13
leaq 0x136b0(%rip), %rsi     # 0x18048
movq %r13, %rdi
callq 0x34a0
leaq 0xb8(%rsp), %r15
movq %r15, -0x10(%r15)
movq (%rax), %rdx
movq %rax, %rcx
addq $0x10, %rcx
cmpq %rcx, %rdx
je 0x49d0
movq %rdx, 0xa8(%rsp)
movq (%rcx), %rdx
movq %rdx, 0xb8(%rsp)
jmp 0x49d7
movups (%rcx), %xmm0
movups %xmm0, (%r15)
movq 0x8(%rax), %rdx
leaq 0xa8(%rsp), %rsi
movq %rdx, 0x8(%rsi)
movq %rcx, (%rax)
movq $0x0, 0x8(%rax)
movb $0x0, 0x10(%rax)
leaq 0xa(%rsp), %rdi
callq 0x57dc
movq 0xa8(%rsp), %rdi
cmpq %r15, %rdi
je 0x4a1d
movq 0xb8(%rsp), %rsi
incq %rsi
callq 0x3280
movq 0x18(%rsp), %rdi
leaq 0x28(%rsp), %rax
cmpq %rax, %rdi
je 0x4a39
movq 0x28(%rsp), %rsi
incq %rsi
callq 0x3280
movq 0x8(%rbx), %rdi
movq 0x20(%rbx), %rsi
addq $0x8, %rsi
leaq 0xa(%rsp), %rdx
movq 0x38(%rsp), %rcx
movl $0xc, %r8d
callq 0x69dc
jmp 0x4b90
decl %r13d
shrl $0x1f, %r15d
movl %r15d, %esi
addl %r13d, %esi
leaq 0x28(%rsp), %rax
movq %rax, -0x10(%rax)
leaq 0x18(%rsp), %rbx
movq %rbx, %rdi
movl $0x2d, %edx
callq 0x32f0
movq (%rbx), %rdi
addq %r15, %rdi
movl %r13d, %esi
movl %r12d, %edx
callq 0x5d13
leaq 0x135a9(%rip), %rsi     # 0x18048
movq %rbx, %rdi
callq 0x34a0
leaq 0x98(%rsp), %r15
movq %r15, -0x10(%r15)
movq (%rax), %rdx
movq %rax, %rcx
addq $0x10, %rcx
cmpq %rcx, %rdx
je 0x4ad7
movq %rdx, 0x88(%rsp)
movq (%rcx), %rdx
movq %rdx, 0x98(%rsp)
jmp 0x4ade
movups (%rcx), %xmm0
movups %xmm0, (%r15)
movq 0x8(%rax), %rdx
leaq 0x88(%rsp), %rsi
movq %rdx, 0x8(%rsi)
movq %rcx, (%rax)
movq $0x0, 0x8(%rax)
movb $0x0, 0x10(%rax)
leaq 0xa(%rsp), %rdi
callq 0x57dc
movq 0x88(%rsp), %rdi
cmpq %r15, %rdi
je 0x4b24
movq 0x98(%rsp), %rsi
incq %rsi
callq 0x3280
leaq 0x8(%r14), %r12
movq 0x18(%rsp), %rdi
leaq 0x28(%rsp), %rax
cmpq %rax, %rdi
je 0x4b44
movq 0x28(%rsp), %rsi
incq %rsi
callq 0x3280
movq 0x10(%rsp), %rbx
movq 0x8(%rbx), %rdi
movq 0x20(%rbx), %rsi
addq $0x8, %rsi
leaq 0xa(%rsp), %rdx
movq 0x38(%rsp), %rcx
movl $0xc, %r8d
callq 0x69dc
addl $0xa, %ebp
movq %rbx, %rdi
movslq %ebp, %rbx
movl 0x4(%r14), %ebp
addq $0x68, %rdi
movq %r12, %rsi
callq 0x62a6
movl $0x2, (%rax)
movq %rbx, 0x8(%rax)
movl %ebp, 0x10(%rax)
movq %r14, %rdi
callq 0x3320
jmp 0x4db7
addl $-0x2, %r14d
jmp 0x4ba6
decl %r14d
shrl $0x1f, %r13d
movl %r13d, %esi
addl %r14d, %esi
leaq 0x28(%rsp), %r12
movq %r12, -0x10(%r12)
leaq 0x18(%rsp), %r15
movq %r15, %rdi
movl $0x2d, %edx
callq 0x32f0
movq (%r15), %rdi
addq %r13, %rdi
movl %r14d, %esi
movl %ebp, %edx
callq 0x5d13
leaq 0x13465(%rip), %rsi     # 0x18048
movq %r15, %rdi
callq 0x34a0
leaq 0x58(%rsp), %r14
movq %r14, -0x10(%r14)
movq (%rax), %rdx
movq %rax, %rcx
addq $0x10, %rcx
cmpq %rcx, %rdx
je 0x4c12
movq %rdx, 0x48(%rsp)
movq (%rcx), %rdx
movq %rdx, 0x58(%rsp)
jmp 0x4c19
movups (%rcx), %xmm0
movups %xmm0, (%r14)
movq 0x8(%rax), %rdx
leaq 0x48(%rsp), %rsi
movq %rdx, 0x8(%rsi)
movq %rcx, (%rax)
movq $0x0, 0x8(%rax)
movb $0x0, 0x10(%rax)
leaq 0xa(%rsp), %rdi
callq 0x57dc
movq 0x48(%rsp), %rdi
cmpq %r14, %rdi
je 0x4c56
movq 0x58(%rsp), %rsi
incq %rsi
callq 0x3280
movq 0x18(%rsp), %rdi
cmpq %r12, %rdi
je 0x4c6d
movq 0x28(%rsp), %rsi
incq %rsi
callq 0x3280
movq 0x10(%rbx), %rdi
movq 0x20(%rbx), %rsi
addq $0x8, %rsi
leaq 0xa(%rsp), %rdx
callq 0xc50a
jmp 0x4db7
addl $-0x2, %r13d
jmp 0x4c91
decl %r13d
shrl $0x1f, %r12d
movl %r12d, %esi
addl %r13d, %esi
leaq 0x28(%rsp), %rax
movq %rax, -0x10(%rax)
leaq 0x18(%rsp), %rbx
movq %rbx, %rdi
movl $0x2d, %edx
callq 0x32f0
movq (%rbx), %rdi
addq %r12, %rdi
movl %r13d, %esi
movl %ebp, %edx
callq 0x5d13
leaq 0x1337b(%rip), %rsi     # 0x18048
movq %rbx, %rdi
callq 0x34a0
leaq 0x78(%rsp), %r12
movq %r12, -0x10(%r12)
movq (%rax), %rdx
movq %rax, %rcx
addq $0x10, %rcx
cmpq %rcx, %rdx
movq 0x10(%rsp), %rbx
movq 0x38(%rsp), %r13
je 0x4d07
movq %rdx, 0x68(%rsp)
movq (%rcx), %rdx
movq %rdx, 0x78(%rsp)
jmp 0x4d0f
movups (%rcx), %xmm0
movups %xmm0, (%r12)
movq 0x8(%rax), %rdx
leaq 0x68(%rsp), %rsi
movq %rdx, 0x8(%rsi)
movq %rcx, (%rax)
movq $0x0, 0x8(%rax)
movb $0x0, 0x10(%rax)
leaq 0xa(%rsp), %rdi
callq 0x57dc
movq 0x68(%rsp), %rdi
cmpq %r12, %rdi
je 0x4d4c
movq 0x78(%rsp), %rsi
incq %rsi
callq 0x3280
movq 0x18(%rsp), %rdi
leaq 0x28(%rsp), %rax
cmpq %rax, %rdi
je 0x4d68
movq 0x28(%rsp), %rsi
incq %rsi
callq 0x3280
movq 0x8(%rbx), %rdi
movq 0x20(%rbx), %rsi
addq $0x8, %rsi
leaq 0xa(%rsp), %rdx
movq 0x40(%rsp), %rcx
movl $0xc, %r8d
callq 0x69dc
movq %r14, %rdi
callq 0x3320
movq %r13, %rdi
movq %r15, %rsi
callq 0x6572
leaq 0x30(%rbx), %rdi
movslq (%r15), %rcx
movq %rcx, %rax
xorl %edx, %edx
divq 0x38(%rbx)
movq %rdx, %rsi
movq %r15, %rdx
callq 0x5d80
movb $0x1, %al
addq $0xc8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rbx
movq 0x68(%rsp), %rdi
cmpq %r12, %rdi
je 0x4e4d
movq 0x78(%rsp), %rsi
jmp 0x4e3e
jmp 0x4e4a
movq %rax, %rbx
movq 0x48(%rsp), %rdi
cmpq %r14, %rdi
je 0x4e00
movq 0x58(%rsp), %rsi
incq %rsi
callq 0x3280
jmp 0x4e00
movq %rax, %rbx
movq 0x18(%rsp), %rdi
cmpq %r12, %rdi
jne 0x4e5c
jmp 0x4e69
movq %rax, %rbx
movq 0x88(%rsp), %rdi
cmpq %r15, %rdi
je 0x4e4d
movq 0x98(%rsp), %rsi
jmp 0x4e3e
movq %rax, %rbx
movq 0xa8(%rsp), %rdi
cmpq %r15, %rdi
je 0x4e4d
movq 0xb8(%rsp), %rsi
incq %rsi
callq 0x3280
jmp 0x4e4d
jmp 0x4e4a
movq %rax, %rbx
movq 0x18(%rsp), %rdi
leaq 0x28(%rsp), %rax
cmpq %rax, %rdi
je 0x4e69
movq 0x28(%rsp), %rsi
incq %rsi
callq 0x3280
movq %rbx, %rdi
callq 0x3470
nop