// File: /workspace/github_cpp_makefile_star2_O2/zkl94[P]distributed-key-value-store/MP1Node.cpp
// Function: MP1Node::handleJOINREQ(void*, char*, int)
void MP1Node::handleJOINREQ(void *env, char *data, int size) {
    #ifdef DEBUG_JOINREQ
        cout << "received a join request" << endl;
    #endif

    // when introducer receives JOINREQ, add the node to member list, and return JOINREP with cluster member list
    char addr[6];
    // msg: sizeof(MessageHdr) + 6 + sizeof(long)
    MessageHdr *msg = (MessageHdr *)data;
    memcpy(&addr, (char *)(msg)+4, 6);
    int id = 0;
    short port;
    memcpy(&id, &addr[0], sizeof(int));
    memcpy(&port, &addr[4], sizeof(short));

    #ifdef DEBUG_JOINREQ
        cout << "id = " << id << "; port = " << port << endl;
    #endif

    #ifdef DEBUG_JOINREQ
        cout << "before adding member list entry, there are " << memberNode->memberList.size() << " entries" << endl;
    #endif

    // newly added node have 0 heartbeat
    MemberListEntry *newEntry = new MemberListEntry(id, port, 0, par->getcurrtime());
    memberNode->memberList.push_back(*newEntry);

    logNodeAddWrapper(memberNode, id, port);

    #ifdef DEBUG_JOINREQ
        cout << "after adding member list entry, there are " << memberNode->memberList.size() << " entries" << endl;
    #endif

    // return JOINREP with cluster member list
    int entry_num = memberNode->memberList.size();
    int currentOffset = 0;
    // allocate maximum space possibly needed
    size_t JOINREPMsgSize = sizeof(MessageHdr) + (sizeof(addr) + sizeof(long)) * entry_num;
    MessageHdr *JOINREPMsg;
    JOINREPMsg = (MessageHdr *) malloc(JOINREPMsgSize * sizeof(char));
    JOINREPMsg->msgType = JOINREP;
    // for the message type offset
    currentOffset += sizeof(int);

    for (MemberListEntry memberListEntry: memberNode->memberList) {
        // if it is to be deleted, don't add it to member list messages
        if (this->tobedeleted->count(memberListEntry.getid()) != 0) {
            continue;
        }

        Address address;
        string _address = to_string(memberListEntry.getid()) + ":" + to_string(memberListEntry.getport());
        address = Address(_address);
        // add to JOINREPMsg
        memcpy((char *)(JOINREPMsg) + currentOffset, &address.addr, sizeof(address.addr));
        currentOffset += sizeof(address.addr);
        memcpy((char *)(JOINREPMsg) + currentOffset, &memberListEntry.heartbeat, sizeof(long));
        currentOffset += sizeof(long);
        // only send heartbeat, timestamp is set by receivers with par->getcurrtime()
        // also, timestamp is not global and thus no need to sync
    }

    #ifdef DEBUG_JOINREQ
        cout << "currentOffset = " << currentOffset << " JOINREPMsgSize = " << JOINREPMsgSize << endl;
    #endif

    // not necessarily because to be deleted entries are not included
    // assert(currentOffset == (int)JOINREPMsgSize);

    string _address = to_string(id) + ":" + to_string(port);
    Address address = Address(_address);
    emulNet->ENsend(&memberNode->addr, &address, (char *)JOINREPMsg, currentOffset);
    #ifdef DEBUG_JOINREQ
        cout << "JOINREP successfully sent" <<endl;
    #endif
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x108, %rsp            # imm = 0x108
movq %rdi, %rbx
movl 0x4(%rdx), %r12d
movswl 0x8(%rdx), %ebp
pushq $0x18
popq %r15
movq %r15, %rdi
callq 0x3260
movq %rax, %r14
movq %rbx, 0x8(%rsp)
movq 0x18(%rbx), %rdi
callq 0x9f08
movslq %eax, %r8
movq %r14, %rdi
movl %r12d, %esi
movl %ebp, %edx
xorl %ecx, %ecx
callq 0x9f42
movq 0x8(%rsp), %rbx
movq 0x20(%rbx), %rdi
addq $0x28, %rdi
movq %r14, %rsi
callq 0x49e8
movq 0x20(%rbx), %rsi
movq %rbx, %rdi
movl %r12d, 0x14(%rsp)
movl %r12d, %edx
movl %ebp, 0x10(%rsp)
movl %ebp, %ecx
callq 0x40d6
movq 0x20(%rbx), %rax
movq 0x28(%rax), %r13
movq 0x30(%rax), %rax
movq %rax, 0x28(%rsp)
subq %r13, %rax
cqto
idivq %r15
cltq
imulq $0xe, %rax, %rdi
addq $0x4, %rdi
callq 0x3330
movq %rax, 0x20(%rsp)
movl $0x1, (%rax)
pushq $0x4
popq %rax
movq %rax, (%rsp)
leaq 0xd0(%rsp), %rbp
leaq 0x50(%rsp), %r12
leaq 0x30(%rsp), %r14
cmpq 0x28(%rsp), %r13
je 0x4408
movq %r14, %rbx
movq %rbp, %rdi
movq %r13, %rsi
callq 0x9f5a
movq 0x8(%rsp), %rax
movq 0x38(%rax), %r14
movq %rbp, %rdi
callq 0x9f90
movl %eax, 0x50(%rsp)
movq %r14, %rdi
movq %r12, %rsi
callq 0x4ba2
testq %rax, %rax
je 0x4314
movq %rbx, %r14
jmp 0x43ff
movq %rbp, %rdi
callq 0x9f90
leaq 0x90(%rsp), %r14
movq %r14, %rdi
movl %eax, %esi
callq 0x4a9a
movq %rbx, %rdi
movq %r14, %rsi
leaq 0xe976(%rip), %rdx      # 0x12cb1
callq 0x4a7b
movq %rbp, %r15
movq %rbp, %rdi
callq 0x9f94
leaq 0x70(%rsp), %r14
movswl %ax, %esi
movq %r14, %rdi
callq 0x4a9a
movq %r12, %rdi
movq %r14, %rbp
movq %rbx, %r14
movq %rbx, %rsi
movq %rbp, %rdx
callq 0x4a14
movq %rbp, %rdi
callq 0x3110
movq %r14, %rdi
callq 0x3110
leaq 0x90(%rsp), %rdi
callq 0x3110
leaq 0xe8(%rsp), %rbx
movq %rbx, %rdi
movq %r12, %rsi
callq 0x3340
movq %r14, %rdi
movq %rbx, %rsi
callq 0x4af4
leaq 0x1a(%rsp), %rdi
movq %r14, %rsi
callq 0x9f22
movq %rbx, %rdi
callq 0x3110
movq (%rsp), %rsi
movslq %esi, %rsi
movzwl 0x1e(%rsp), %eax
movq 0x20(%rsp), %rdx
movw %ax, 0x4(%rdx,%rsi)
movl 0x1a(%rsp), %eax
movl %eax, (%rdx,%rsi)
leal 0x6(%rsi), %eax
cltq
movq 0xd8(%rsp), %rcx
movq %rcx, (%rdx,%rax)
addl $0xe, %esi
movq %rsi, (%rsp)
movq %r12, %rdi
callq 0x3110
movq %r15, %rbp
addq $0x18, %r13
jmp 0x42ce
leaq 0x90(%rsp), %rbx
movq %rbx, %rdi
movl 0x14(%rsp), %esi
callq 0x4a9a
leaq 0xe88e(%rip), %rdx      # 0x12cb1
leaq 0x30(%rsp), %rdi
movq %rbx, %rsi
callq 0x4a7b
leaq 0x70(%rsp), %rdi
movl 0x10(%rsp), %esi
callq 0x4a9a
leaq 0x50(%rsp), %rdi
leaq 0x30(%rsp), %rsi
leaq 0x70(%rsp), %rdx
callq 0x4a14
leaq 0x70(%rsp), %rdi
callq 0x3110
leaq 0x30(%rsp), %rdi
callq 0x3110
leaq 0x90(%rsp), %rdi
callq 0x3110
leaq 0xb0(%rsp), %rdi
leaq 0x50(%rsp), %rsi
callq 0x3340
leaq 0x30(%rsp), %rdi
leaq 0xb0(%rsp), %rsi
callq 0x4af4
leaq 0xb0(%rsp), %rdi
callq 0x3110
movq 0x8(%rsp), %rax
movq 0x8(%rax), %rdi
movq 0x20(%rax), %rsi
addq $0x8, %rsi
leaq 0x30(%rsp), %rdx
movq 0x20(%rsp), %rcx
movq (%rsp), %r8
callq 0x56ee
leaq 0x50(%rsp), %rdi
callq 0x3110
addq $0x108, %rsp            # imm = 0x108
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rbx
leaq 0xb0(%rsp), %rdi
jmp 0x452d
jmp 0x4513
jmp 0x4539
jmp 0x450e
jmp 0x4509
movq %rax, %rbx
pushq $0x18
popq %rsi
movq %r14, %rdi
callq 0x3270
jmp 0x4553
movq %rax, %rbx
jmp 0x4532
movq %rax, %rbx
jmp 0x4546
movq %rax, %rbx
leaq 0x70(%rsp), %rdi
callq 0x3110
jmp 0x453c
movq %rax, %rbx
leaq 0xe8(%rsp), %rdi
callq 0x3110
leaq 0x50(%rsp), %rdi
jmp 0x454e
movq %rax, %rbx
leaq 0x30(%rsp), %rdi
callq 0x3110
leaq 0x90(%rsp), %rdi
callq 0x3110
movq %rbx, %rdi
callq 0x3420
nop