// File: KinderRiven[P]rdma_demo/client.cc
// Function: connect_qpair(rdma_context_t*)
static void connect_qpair(rdma_context_t* context)
{
    printf("|connect.\n");
    struct addrinfo hints;
    struct addrinfo *result, *rp;
    int sock_fd = -1, ret = 0;

    memset(&hints, 0, sizeof(struct addrinfo));
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_family = AF_UNSPEC;
    ret = getaddrinfo("172.18.13.42", "4396", &hints, &result);

    for (rp = result; rp != NULL; rp = rp->ai_next) {
        sock_fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
        if (sock_fd == -1) {
            continue;
        }
        ret = connect(sock_fd, rp->ai_addr, rp->ai_addrlen);
        if (ret == 0) {
            context->sockfd = sock_fd;
            printf("|--connect ok.[%d]\n", sock_fd);
            break;
        }
        close(sock_fd);
        sock_fd = -1;
    }
    freeaddrinfo(result);

    // send
    qp_info_t* local_qp_info = (qp_info_t*)malloc(sizeof(qp_info_t));
    context->local_qp = local_qp_info;
    local_qp_info->addr = (uint64_t)context->ib_buf; // 注册内存的地址
    local_qp_info->rkey = context->mr->rkey; // 注册内存的remote key
    local_qp_info->qp_num = context->qp[0]->qp_num; // qp number
    local_qp_info->lid = context->port_attr.lid;
    memcpy((void*)(&local_qp_info->gid), (void*)(&context->gid), sizeof(context->gid));
    size_t sz = sock_write(sock_fd, local_qp_info, sizeof(qp_info_t));
    printf("|--sock_write[%zu/%zu]\n", sz, sizeof(qp_info_t));
    printf("|----[addr:%llx][rkey:%d]\n", local_qp_info->addr, local_qp_info->rkey);
    printf("|----[lid:%d][qp_num:%d]\n", local_qp_info->lid, local_qp_info->qp_num);
    printf("|----[gid:");
    uint8_t* _lo_gids = (uint8_t*)(&local_qp_info->gid);
    for (int i = 0; i < 16; i++) {
        printf("%02x", _lo_gids[i]);
        if (i & 1) {
            printf(":");
        }
    }
    printf("]\n");

    // recv
    qp_info_t* remote_qp_info = (qp_info_t*)malloc(sizeof(qp_info_t));
    context->remote_qp = remote_qp_info;
    sz = sock_read(sock_fd, remote_qp_info, sizeof(qp_info_t));
    printf("|--sock_read[%zu/%zu]\n", sz, sizeof(qp_info_t));
    printf("|----[addr:%llx][rkey:%d]\n", remote_qp_info->addr, remote_qp_info->rkey);
    printf("|----[lid:%d][qp_num:%d]\n", remote_qp_info->lid, remote_qp_info->qp_num);
    printf("|----[gid:");
    uint8_t* _rm_gids = (uint8_t*)(&remote_qp_info->gid);
    for (int i = 0; i < 16; i++) {
        printf("%02x", _rm_gids[i]);
        if (i & 1) {
            printf(":");
        }
    }
    printf("]\n");

    ret = modify_qp_to_init(context->qp[0]);
    printf("|--modify_qp_to_init = %d\n", ret);

    // modify the QP to RTR
    ret = modify_qp_to_rtr(context->qp[0], remote_qp_info->qp_num, remote_qp_info->lid, (uint8_t*)(&remote_qp_info->gid));
    printf("|--modify_qp_to_rtr = %d\n", ret);

    // modify QP state to RTS
    ret = modify_qp_to_rts(context->qp[0]);
    printf("|--modify_qp_to_rts = %d\n", ret);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x90, %rsp
movq %rdi, -0x8(%rbp)
leaq 0x1e31(%rip), %rdi      # 0x3347
movb $0x0, %al
callq 0x1050
movl $0xffffffff, -0x4c(%rbp) # imm = 0xFFFFFFFF
movl $0x0, -0x50(%rbp)
leaq -0x38(%rbp), %rdi
xorl %esi, %esi
movl $0x30, %edx
callq 0x10b0
movl $0x1, -0x30(%rbp)
movl $0x0, -0x34(%rbp)
leaq 0x1e02(%rip), %rdi      # 0x3352
leaq 0x1e08(%rip), %rsi      # 0x335f
leaq -0x38(%rbp), %rdx
leaq -0x40(%rbp), %rcx
callq 0x1130
movl %eax, -0x50(%rbp)
movq -0x40(%rbp), %rax
movq %rax, -0x48(%rbp)
cmpq $0x0, -0x48(%rbp)
je 0x15ff
movq -0x48(%rbp), %rax
movl 0x4(%rax), %edi
movq -0x48(%rbp), %rax
movl 0x8(%rax), %esi
movq -0x48(%rbp), %rax
movl 0xc(%rax), %edx
callq 0x1070
movl %eax, -0x4c(%rbp)
cmpl $-0x1, -0x4c(%rbp)
jne 0x159f
jmp 0x15ee
movl -0x4c(%rbp), %edi
movq -0x48(%rbp), %rax
movq 0x18(%rax), %rsi
movq -0x48(%rbp), %rax
movl 0x10(%rax), %edx
callq 0x10e0
movl %eax, -0x50(%rbp)
cmpl $0x0, -0x50(%rbp)
jne 0x15df
movl -0x4c(%rbp), %ecx
movq -0x8(%rbp), %rax
movl %ecx, 0x574(%rax)
movl -0x4c(%rbp), %esi
leaq 0x1d8e(%rip), %rdi      # 0x3364
movb $0x0, %al
callq 0x1050
jmp 0x15ff
movl -0x4c(%rbp), %edi
callq 0x11d0
movl $0xffffffff, -0x4c(%rbp) # imm = 0xFFFFFFFF
movq -0x48(%rbp), %rax
movq 0x28(%rax), %rax
movq %rax, -0x48(%rbp)
jmp 0x156f
movq -0x40(%rbp), %rdi
callq 0x1140
movl $0x22, %edi
callq 0x1150
movq %rax, -0x58(%rbp)
movq -0x58(%rbp), %rcx
movq -0x8(%rbp), %rax
movq %rcx, 0x560(%rax)
movq -0x8(%rbp), %rax
movq (%rax), %rcx
movq -0x58(%rbp), %rax
movq %rcx, (%rax)
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rax
movl 0x28(%rax), %ecx
movq -0x58(%rbp), %rax
movl %ecx, 0x8(%rax)
movq -0x8(%rbp), %rax
movq 0x28(%rax), %rax
movl 0x34(%rax), %ecx
movq -0x58(%rbp), %rax
movl %ecx, 0xc(%rax)
movq -0x8(%rbp), %rax
movw 0x452(%rax), %cx
movq -0x58(%rbp), %rax
movw %cx, 0x10(%rax)
movq -0x58(%rbp), %rax
movq -0x8(%rbp), %rcx
movq 0x550(%rcx), %rdx
movq %rdx, 0x12(%rax)
movq 0x558(%rcx), %rcx
movq %rcx, 0x1a(%rax)
movl -0x4c(%rbp), %edi
movq -0x58(%rbp), %rsi
movl $0x22, %edx
callq 0x1390
movq %rax, -0x60(%rbp)
movq -0x60(%rbp), %rsi
leaq 0x1cd0(%rip), %rdi      # 0x3378
movl $0x22, %edx
movb $0x0, %al
callq 0x1050
movq -0x58(%rbp), %rax
movq (%rax), %rsi
movq -0x58(%rbp), %rax
movl 0x8(%rax), %edx
leaq 0x1cc7(%rip), %rdi      # 0x3390
movb $0x0, %al
callq 0x1050
movq -0x58(%rbp), %rax
movzwl 0x10(%rax), %esi
movq -0x58(%rbp), %rax
movl 0xc(%rax), %edx
leaq 0x1cc5(%rip), %rdi      # 0x33ab
movb $0x0, %al
callq 0x1050
leaq 0x1cd1(%rip), %rdi      # 0x33c5
movb $0x0, %al
callq 0x1050
movq -0x58(%rbp), %rax
addq $0x12, %rax
movq %rax, -0x68(%rbp)
movl $0x0, -0x6c(%rbp)
cmpl $0x10, -0x6c(%rbp)
jge 0x1754
movq -0x68(%rbp), %rax
movslq -0x6c(%rbp), %rcx
movzbl (%rax,%rcx), %esi
leaq 0x1a11(%rip), %rdi      # 0x3138
movb $0x0, %al
callq 0x1050
movl -0x6c(%rbp), %eax
andl $0x1, %eax
cmpl $0x0, %eax
je 0x1747
leaq 0x1c8e(%rip), %rdi      # 0x33ce
movb $0x0, %al
callq 0x1050
jmp 0x1749
movl -0x6c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x6c(%rbp)
jmp 0x170e
leaq 0x1a87(%rip), %rdi      # 0x31e2
movb $0x0, %al
callq 0x1050
movl $0x22, %edi
callq 0x1150
movq %rax, -0x78(%rbp)
movq -0x78(%rbp), %rcx
movq -0x8(%rbp), %rax
movq %rcx, 0x568(%rax)
movl -0x4c(%rbp), %edi
movq -0x78(%rbp), %rsi
movl $0x22, %edx
callq 0x12e0
movq %rax, -0x60(%rbp)
movq -0x60(%rbp), %rsi
leaq 0x1c31(%rip), %rdi      # 0x33d0
movl $0x22, %edx
movb $0x0, %al
callq 0x1050
movq -0x78(%rbp), %rax
movq (%rax), %rsi
movq -0x78(%rbp), %rax
movl 0x8(%rax), %edx
leaq 0x1bd0(%rip), %rdi      # 0x3390
movb $0x0, %al
callq 0x1050
movq -0x78(%rbp), %rax
movzwl 0x10(%rax), %esi
movq -0x78(%rbp), %rax
movl 0xc(%rax), %edx
leaq 0x1bce(%rip), %rdi      # 0x33ab
movb $0x0, %al
callq 0x1050
leaq 0x1bda(%rip), %rdi      # 0x33c5
movb $0x0, %al
callq 0x1050
movq -0x78(%rbp), %rax
addq $0x12, %rax
movq %rax, -0x80(%rbp)
movl $0x0, -0x84(%rbp)
cmpl $0x10, -0x84(%rbp)
jge 0x185d
movq -0x80(%rbp), %rax
movslq -0x84(%rbp), %rcx
movzbl (%rax,%rcx), %esi
leaq 0x1911(%rip), %rdi      # 0x3138
movb $0x0, %al
callq 0x1050
movl -0x84(%rbp), %eax
andl $0x1, %eax
cmpl $0x0, %eax
je 0x184a
leaq 0x1b8b(%rip), %rdi      # 0x33ce
movb $0x0, %al
callq 0x1050
jmp 0x184c
movl -0x84(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x84(%rbp)
jmp 0x1808
leaq 0x197e(%rip), %rdi      # 0x31e2
movb $0x0, %al
callq 0x1050
movq -0x8(%rbp), %rax
movq 0x28(%rax), %rdi
callq 0x2270
movl %eax, -0x50(%rbp)
movl -0x50(%rbp), %esi
leaq 0x1b62(%rip), %rdi      # 0x33e7
movb $0x0, %al
callq 0x1050
movq -0x8(%rbp), %rax
movq 0x28(%rax), %rdi
movq -0x78(%rbp), %rax
movl 0xc(%rax), %esi
movq -0x78(%rbp), %rax
movw 0x10(%rax), %ax
movq -0x78(%rbp), %rcx
addq $0x12, %rcx
movzwl %ax, %edx
callq 0x22e0
movl %eax, -0x50(%rbp)
movl -0x50(%rbp), %esi
leaq 0x1b42(%rip), %rdi      # 0x3402
movb $0x0, %al
callq 0x1050
movq -0x8(%rbp), %rax
movq 0x28(%rax), %rdi
callq 0x23b0
movl %eax, -0x50(%rbp)
movl -0x50(%rbp), %esi
leaq 0x1b3b(%rip), %rdi      # 0x341c
movb $0x0, %al
callq 0x1050
addq $0x90, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)