// File: /workspace/github_cpp_makefile_star2_O3/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 0xcd1e
movl %eax, %ebp
movl (%r14), %eax
cmpq $0x4, %rax
ja 0x4cfd
movq 0x20(%rbx), %r13
leaq 0x13b37(%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 0x28(%r13), %r15
movq 0x30(%r13), %rbx
movq %rbx, %rax
subq %r15, %rax
sarq $0x3, %rax
movabsq $-0x5555555555555554, %rdi # imm = 0xAAAAAAAAAAAAAAAC
imulq %rax, %rdi
addq $0x4, %rdi
movq %rdi, 0x18(%rsp)
callq 0x3370
movq %rax, %r12
movl $0x1, (%rax)
cmpq %r15, %rbx
je 0x4561
xorl %ebp, %ebp
movabsq $-0x5555555555555555, %rbx # imm = 0xAAAAAAAAAAAAAAAB
xorl %r14d, %r14d
addq %rbp, %r15
movq %r15, %rdi
callq 0xcdae
movl %eax, 0x4(%r12,%r14,4)
incq %r14
movq 0x28(%r13), %r15
movq 0x30(%r13), %rax
subq %r15, %rax
sarq $0x3, %rax
imulq %rbx, %rax
addq $0x18, %rbp
cmpq %r14, %rax
ja 0x4532
movq 0x10(%rsp), %rdi
movq %r12, %rsi
movq 0x18(%rsp), %rdx
callq 0x4db8
jmp 0x4cfd
leaq 0x4(%r14), %r15
leaq 0x68(%rbx), %r12
movq %r12, %rdi
movq %r15, %rsi
callq 0x64c2
testq %rax, %rax
je 0x4ce3
cmpl $0x2, 0x10(%rax)
jne 0x4ce3
movq %r12, 0x18(%rsp)
movq %rbx, 0x10(%rsp)
movl (%r15), %ebx
movl 0x20(%rax), %r12d
movl $0xc, %edi
callq 0x3370
movl $0x4, (%rax)
movl %ebx, 0x4(%rax)
movq %rax, 0x40(%rsp)
movl %r12d, 0x8(%rax)
movl %r12d, %ebp
negl %ebp
cmovsl %r12d, %ebp
movl $0x1, %r13d
cmpl $0xa, %ebp
jb 0x4be3
movl $0x4, %r13d
movl $0xd1b71759, %eax       # imm = 0xD1B71759
movl %ebp, %ecx
cmpl $0x63, %ecx
jbe 0x4bda
cmpl $0x3e7, %ecx            # imm = 0x3E7
jbe 0x4be0
cmpl $0x2710, %ecx           # imm = 0x2710
jb 0x4be3
movl %ecx, %edx
imulq %rax, %rdx
shrq $0x2d, %rdx
addl $0x4, %r13d
cmpl $0x1869f, %ecx          # imm = 0x1869F
movl %edx, %ecx
ja 0x45f0
addl $-0x3, %r13d
jmp 0x4be3
addq $0x4, %r14
leaq 0x30(%rbx), %r15
movq %r15, %rdi
movq %r14, %rsi
callq 0x5cd8
testq %rax, %rax
je 0x4cfd
movq %r15, %rdi
movq %r14, %rsi
callq 0x660e
movq 0x28(%r13), %rdi
cmpq %rdi, 0x30(%r13)
je 0x4845
leaq 0x28(%r13), %rax
movq %rax, 0x10(%rsp)
xorl %r12d, %r12d
movabsq $-0x5555555555555555, %rbp # imm = 0xAAAAAAAAAAAAAAAB
xorl %r15d, %r15d
addq %r12, %rdi
callq 0xcdae
cmpl (%r14), %eax
je 0x4835
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 0x4680
jmp 0x4845
movl 0x8(%r14), %r15d
movq %rbx, 0x10(%rsp)
movl 0xa4(%rbx), %ebx
cmpl %ebx, %r15d
jne 0x47af
movl 0x4(%r14), %r13d
movl $0xc, %edi
callq 0x3370
movl $0x4, (%rax)
movl %r15d, 0x4(%rax)
movq %rax, 0x18(%rsp)
movl %r13d, 0x8(%rax)
movl %r13d, %ebp
negl %ebp
cmovsl %r13d, %ebp
movl $0x1, %r12d
cmpl $0xa, %ebp
movq 0x10(%rsp), %rbx
jb 0x4999
movl $0x4, %r12d
movl $0xd1b71759, %eax       # imm = 0xD1B71759
movl %ebp, %ecx
cmpl $0x63, %ecx
jbe 0x4987
cmpl $0x3e7, %ecx            # imm = 0x3E7
jbe 0x4996
cmpl $0x2710, %ecx           # imm = 0x2710
jb 0x4999
movl %ecx, %edx
imulq %rax, %rdx
shrq $0x2d, %rdx
addl $0x4, %r12d
cmpl $0x1869f, %ecx          # imm = 0x1869F
movl %edx, %ecx
ja 0x4718
addl $-0x3, %r12d
jmp 0x4999
movslq %r15d, %rax
movabsq $0x3fffffffc, %r12      # imm = 0x3FFFFFFFC
addq %rax, %r12
shrq $0x2, %r12
testl %r12d, %r12d
jle 0x4cfd
addq $0x4, %r14
leaq 0x30(%rbx), %r15
andl $0x7fffffff, %r12d      # imm = 0x7FFFFFFF
movq %r15, %rdi
movq %r14, %rsi
callq 0x5cd8
testq %rax, %rax
jne 0x47a1
movl (%r14), %esi
movq %rbx, %rdi
callq 0x3df2
addq $0x4, %r14
decq %r12
jne 0x4786
jmp 0x4cfd
movl $0xc, %edi
callq 0x3370
movl $0x3, (%rax)
movl %ebx, 0x4(%rax)
movq %rax, 0x18(%rsp)
movl %r15d, 0x8(%rax)
movl %r15d, %r12d
negl %r12d
cmovsl %r15d, %r12d
movl $0x1, %r13d
cmpl $0xa, %r12d
jb 0x4a9f
movl $0x4, %r13d
movl $0xd1b71759, %eax       # imm = 0xD1B71759
movl %r12d, %ecx
cmpl $0x63, %ecx
jbe 0x498d
cmpl $0x3e7, %ecx            # imm = 0x3E7
jbe 0x4a9c
cmpl $0x2710, %ecx           # imm = 0x2710
jb 0x4a9f
movl %ecx, %edx
imulq %rax, %rdx
shrq $0x2d, %rdx
addl $0x4, %r13d
cmpl $0x1869f, %ecx          # imm = 0x1869F
movl %edx, %ecx
ja 0x47f3
addl $-0x3, %r13d
jmp 0x4a9f
movq 0x10(%rsp), %rdi
addq (%rdi), %r12
movq %r12, %rsi
callq 0x66fe
movl (%r14), %r13d
movl %r13d, %ebp
negl %ebp
cmovsl %r13d, %ebp
movl $0x1, %r14d
cmpl $0xa, %ebp
jb 0x48a5
movl $0x4, %r14d
movl $0xd1b71759, %eax       # imm = 0xD1B71759
movl %ebp, %ecx
cmpl $0x63, %ecx
jbe 0x489c
cmpl $0x3e7, %ecx            # imm = 0x3E7
jbe 0x48a2
cmpl $0x2710, %ecx           # imm = 0x2710
jb 0x48a5
movl %ecx, %edx
imulq %rax, %rdx
shrq $0x2d, %rdx
addl $0x4, %r14d
cmpl $0x1869f, %ecx          # imm = 0x1869F
movl %edx, %ecx
ja 0x4869
addl $-0x3, %r14d
jmp 0x48a5
addl $-0x2, %r14d
jmp 0x48a5
decl %r14d
shrl $0x1f, %r13d
movl %r13d, %esi
addl %r14d, %esi
leaq 0x30(%rsp), %r12
movq %r12, -0x10(%r12)
leaq 0x20(%rsp), %r15
movq %r15, %rdi
movl $0x2d, %edx
callq 0x32f0
movq (%r15), %rdi
addq %r13, %rdi
movl %r14d, %esi
movl %ebp, %edx
callq 0x5c6b
leaq 0x13766(%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 0x4911
movq %rdx, 0x48(%rsp)
movq (%rcx), %rdx
movq %rdx, 0x58(%rsp)
jmp 0x4918
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 0x572e
movq 0x48(%rsp), %rdi
cmpq %r14, %rdi
je 0x4955
movq 0x58(%rsp), %rsi
incq %rsi
callq 0x3280
movq 0x20(%rsp), %rdi
cmpq %r12, %rdi
je 0x496c
movq 0x30(%rsp), %rsi
incq %rsi
callq 0x3280
movq 0x10(%rbx), %rdi
movq 0x20(%rbx), %rsi
addq $0x8, %rsi
leaq 0xa(%rsp), %rdx
callq 0xc3e6
jmp 0x4cfd
addl $-0x2, %r12d
jmp 0x4999
addl $-0x2, %r13d
jmp 0x4a9f
decl %r12d
shrl $0x1f, %r13d
movl %r13d, %esi
addl %r12d, %esi
leaq 0x30(%rsp), %rax
movq %rax, -0x10(%rax)
leaq 0x20(%rsp), %r15
movq %r15, %rdi
movl $0x2d, %edx
callq 0x32f0
movq (%r15), %rdi
addq %r13, %rdi
movl %r12d, %esi
movl %ebp, %edx
callq 0x5c6b
leaq 0x13673(%rip), %rsi     # 0x18048
movq %r15, %rdi
callq 0x34a0
leaq 0xb8(%rsp), %r15
movq %r15, -0x10(%r15)
movq (%rax), %rdx
movq %rax, %rcx
addq $0x10, %rcx
cmpq %rcx, %rdx
je 0x4a0d
movq %rdx, 0xa8(%rsp)
movq (%rcx), %rdx
movq %rdx, 0xb8(%rsp)
jmp 0x4a14
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 0x572e
movq 0xa8(%rsp), %rdi
cmpq %r15, %rdi
je 0x4a5a
movq 0xb8(%rsp), %rsi
incq %rsi
callq 0x3280
movq 0x20(%rsp), %rdi
leaq 0x30(%rsp), %rax
cmpq %rax, %rdi
je 0x4a76
movq 0x30(%rsp), %rsi
incq %rsi
callq 0x3280
movq 0x8(%rbx), %rdi
movq 0x20(%rbx), %rsi
addq $0x8, %rsi
leaq 0xa(%rsp), %rdx
movq 0x18(%rsp), %rcx
movl $0xc, %r8d
callq 0x6994
jmp 0x4bcd
decl %r13d
shrl $0x1f, %r15d
movl %r15d, %esi
addl %r13d, %esi
leaq 0x30(%rsp), %rax
movq %rax, -0x10(%rax)
leaq 0x20(%rsp), %rbx
movq %rbx, %rdi
movl $0x2d, %edx
callq 0x32f0
movq (%rbx), %rdi
addq %r15, %rdi
movl %r13d, %esi
movl %r12d, %edx
callq 0x5c6b
leaq 0x1356c(%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 0x4b14
movq %rdx, 0x88(%rsp)
movq (%rcx), %rdx
movq %rdx, 0x98(%rsp)
jmp 0x4b1b
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 0x572e
movq 0x88(%rsp), %rdi
cmpq %r15, %rdi
je 0x4b61
movq 0x98(%rsp), %rsi
incq %rsi
callq 0x3280
leaq 0x8(%r14), %r12
movq 0x20(%rsp), %rdi
leaq 0x30(%rsp), %rax
cmpq %rax, %rdi
je 0x4b81
movq 0x30(%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 0x18(%rsp), %rcx
movl $0xc, %r8d
callq 0x6994
addl $0xa, %ebp
movq %rbx, %rdi
movslq %ebp, %rbx
movl 0x4(%r14), %ebp
addq $0x68, %rdi
movq %r12, %rsi
callq 0x622a
movl $0x2, (%rax)
movq %rbx, 0x8(%rax)
movl %ebp, 0x10(%rax)
movq %r14, %rdi
callq 0x3320
jmp 0x4cfd
addl $-0x2, %r13d
jmp 0x4be3
decl %r13d
shrl $0x1f, %r12d
movl %r12d, %esi
addl %r13d, %esi
leaq 0x30(%rsp), %rax
movq %rax, -0x10(%rax)
leaq 0x20(%rsp), %rbx
movq %rbx, %rdi
movl $0x2d, %edx
callq 0x32f0
movq (%rbx), %rdi
addq %r12, %rdi
movl %r13d, %esi
movl %ebp, %edx
callq 0x5c6b
leaq 0x13429(%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
je 0x4c54
movq %rdx, 0x68(%rsp)
movq (%rcx), %rdx
movq %rdx, 0x78(%rsp)
jmp 0x4c5c
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 0x572e
movq 0x68(%rsp), %rdi
cmpq %r12, %rdi
je 0x4c99
movq 0x78(%rsp), %rsi
incq %rsi
callq 0x3280
movq 0x20(%rsp), %rdi
leaq 0x30(%rsp), %rax
cmpq %rax, %rdi
movq 0x18(%rsp), %r12
je 0x4cba
movq 0x30(%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 0x6994
movq %r14, %rdi
callq 0x3320
movq %r12, %rdi
movq %r15, %rsi
callq 0x651e
addq $0x30, %rbx
movq %rbx, %rdi
movq %r15, %rsi
callq 0x5cd8
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 0x4d68
movq 0x78(%rsp), %rsi
jmp 0x4d59
jmp 0x4d65
movq %rax, %rbx
movq 0x88(%rsp), %rdi
cmpq %r15, %rdi
je 0x4d68
movq 0x98(%rsp), %rsi
jmp 0x4d59
movq %rax, %rbx
movq 0xa8(%rsp), %rdi
cmpq %r15, %rdi
je 0x4d68
movq 0xb8(%rsp), %rsi
incq %rsi
callq 0x3280
jmp 0x4d68
jmp 0x4d65
movq %rax, %rbx
movq 0x20(%rsp), %rdi
leaq 0x30(%rsp), %rax
cmpq %rax, %rdi
je 0x4d84
movq 0x30(%rsp), %rsi
incq %rsi
callq 0x3280
movq %rbx, %rdi
callq 0x3470
movq %rax, %rbx
movq 0x48(%rsp), %rdi
cmpq %r14, %rdi
je 0x4dab
movq 0x58(%rsp), %rsi
incq %rsi
callq 0x3280
jmp 0x4dab
movq %rax, %rbx
movq 0x20(%rsp), %rdi
cmpq %r12, %rdi
jne 0x4d77
jmp 0x4d84
nop