// File: lianxings[P]ftp_benchmark/ftplib.cc
// Function: ftplib::FtpOpenPasv(ftphandle*, ftphandle**, ftplib::transfermode, int, char*)
int ftplib::FtpOpenPasv(ftphandle *nControl, ftphandle **nData, transfermode mode, int dir, char *cmd)
{
	int sData;
    int errorCode;
    int retry = 0;
	union {
		struct sockaddr sa;
		struct sockaddr_in in;
	} sin;
	struct linger lng = { 0, 0 };
	unsigned int l;
	int on=1;
	ftphandle *ctrl;
	char *cp;
	unsigned char v[6];
	int ret;

	if (nControl->dir != FTPLIB_CONTROL) 
        return -1;
	if ((dir != FTPLIB_READ) && (dir != FTPLIB_WRITE)) 	{
		sprintf(nControl->response, "Invalid direction %d\n", dir);
		return -1;
	}
	if ((mode != ftplib::ascii) && (mode != ftplib::image)) {
		sprintf(nControl->response, "Invalid mode %c\n", mode);
		return -1;
	}
	l = sizeof(sin);

	memset(&sin, 0, l);
	sin.in.sin_family = AF_INET;
	if (!FtpSendCmd("PASV",'2',nControl)) 
        return -1;
	cp = strchr(nControl->response,'(');
	if (cp == NULL) 
        return -1;
	cp++;
#if defined(_WIN32)
	unsigned int v_i[6];
    sscanf(cp,"%u,%u,%u,%u,%u,%u",&v_i[2],&v_i[3],&v_i[4],&v_i[5],&v_i[0],&v_i[1]);
    for (int i = 0; i < 6; i++) 
        v[i] = (unsigned char) v_i[i]; 
#else
	sscanf(cp,"%hhu,%hhu,%hhu,%hhu,%hhu,%hhu",&v[2],&v[3],&v[4],&v[5],&v[0],&v[1]);
#endif
	if (nControl->correctpasv) 
        if (!CorrectPasvResponse(v)) 
            return -1;
	sin.sa.sa_data[2] = v[2];
	sin.sa.sa_data[3] = v[3];
	sin.sa.sa_data[4] = v[4];
	sin.sa.sa_data[5] = v[5];
	sin.sa.sa_data[0] = v[0];
	sin.sa.sa_data[1] = v[1];

	if (mp_ftphandle->offset != 0)
	{
		char buf[256];
        sprint_rest(buf, mp_ftphandle->offset);
		if (!FtpSendCmd(buf,'3',nControl)) 
            return 0;
	}

	sData = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
	if (sData == -1) 	{
		perror("socket");
		return -1;
	}
	if (setsockopt(sData,SOL_SOCKET,SO_REUSEADDR, SETSOCKOPT_OPTVAL_TYPE &on,sizeof(on)) == -1) {
		perror("setsockopt");
		net_close(sData);
		return -1;
	}
	if (setsockopt(sData,SOL_SOCKET,SO_LINGER, SETSOCKOPT_OPTVAL_TYPE &lng,sizeof(lng)) == -1) 	{
		perror("setsockopt");
		net_close(sData);
		return -1;
	}

	if (nControl->dir != FTPLIB_CONTROL) 
        return -1;
	memcpy(cmd + strlen(cmd), "\r\n\0", 3);
#ifndef NOSSL
	if (nControl->tlsctrl) 
        ret = SSL_write(nControl->ssl,cmd,strlen(cmd));
	else 
        ret = net_write(nControl->handle,cmd,strlen(cmd));
#else
	ret = net_write(nControl->handle,cmd,strlen(cmd));
#endif

    if(gFtpDebug)
        printf("Thread:%-8ld  sock:%-4d  %s", syscall(SYS_gettid), nControl->handle, cmd);

	if (ret <= 0) 	{
	    errorCode = errno;
        printf("Thread:%-8ld  sock:%-4d  %s  send failed:%s\n", syscall(SYS_gettid), nControl->handle, cmd, strerror(errno));
		return -1;
	}

    while (true) {
        retry++;
        if (connect(sData, &sin.sa, sizeof(sin.sa)) == -1)  {
            if (retry >= 5) {
                errorCode = errno;
                std::cerr << "connect to establish data connnection failed: " << strerror(errorCode) << std::endl;
                net_close(sData);
                return -1;
            }
        } else {
            break;
        }
    }

    // 此处的步骤是： 先建立数据连接，然后再等待控制连接的应答
	if (!readresp('1', nControl)) 	{
		net_close(sData);
		return -1;
	}
    if(gFtpDebug)
        printf("Thread:%-8ld  sock:%-4d  %s\n", syscall(SYS_gettid), nControl->handle,  nControl->response);
    
	ctrl = static_cast<ftphandle*>(calloc(1,sizeof(ftphandle)));
	if (ctrl == NULL) 	{
		perror("calloc");
		net_close(sData);
		return -1;
	}
	if ((mode == 'A') && ((ctrl->buf = static_cast<char*>(malloc(FTPLIB_BUFSIZ))) == NULL)) 	{
		perror("calloc");
		net_close(sData);
		free(ctrl);
		return -1;
	}
	ctrl->handle = sData;
	ctrl->dir = dir;
	ctrl->ctrl = (nControl->cmode == ftplib::pasv) ? nControl : NULL;
	ctrl->idletime = nControl->idletime;
	ctrl->cbarg = nControl->cbarg;
	ctrl->xfered = 0;
	ctrl->xfered1 = 0;
	ctrl->cbbytes = nControl->cbbytes;
	if (ctrl->idletime.tv_sec || ctrl->idletime.tv_usec) ctrl->idlecb = nControl->idlecb;
	else ctrl->idlecb = NULL;
	if (ctrl->cbbytes ) ctrl->xfercb = nControl->xfercb;
	else ctrl->xfercb = NULL;
	*nData = ctrl;

	return 1;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1e0, %rsp            # imm = 0x1E0
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movl %ecx, -0x24(%rbp)
movl %r8d, -0x28(%rbp)
movq %r9, -0x30(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x188(%rbp)
movl $0x0, -0x3c(%rbp)
leaq -0x54(%rbp), %rdi
xorl %esi, %esi
movl $0x8, %edx
callq 0x4250
movl $0x1, -0x5c(%rbp)
movq -0x18(%rbp), %rax
cmpl $0x0, 0x28(%rax)
je 0x17b31
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x1817a
cmpl $0x1, -0x28(%rbp)
je 0x17b65
cmpl $0x2, -0x28(%rbp)
je 0x17b65
movq -0x18(%rbp), %rdi
addq $0x88, %rdi
movl -0x28(%rbp), %edx
leaq 0x5da8(%rip), %rsi      # 0x1d8fa
movb $0x0, %al
callq 0x40d0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x1817a
cmpl $0x41, -0x24(%rbp)
je 0x17b99
cmpl $0x49, -0x24(%rbp)
je 0x17b99
movq -0x18(%rbp), %rdi
addq $0x88, %rdi
movl -0x24(%rbp), %edx
leaq 0x5d8a(%rip), %rsi      # 0x1d910
movb $0x0, %al
callq 0x40d0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x1817a
movl $0x10, -0x58(%rbp)
movl -0x58(%rbp), %eax
movl %eax, %edx
leaq -0x4c(%rbp), %rdi
xorl %esi, %esi
callq 0x4250
movq -0x188(%rbp), %rdi
movw $0x2, -0x4c(%rbp)
movq -0x18(%rbp), %rcx
leaq 0x5d94(%rip), %rsi      # 0x1d95c
movl $0x32, %edx
callq 0x171c0
cmpl $0x0, %eax
jne 0x17be3
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x1817a
movq -0x18(%rbp), %rdi
addq $0x88, %rdi
movl $0x28, %esi
callq 0x4180
movq %rax, -0x70(%rbp)
cmpq $0x0, -0x70(%rbp)
jne 0x17c0f
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x1817a
movq -0x70(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x70(%rbp)
movq -0x70(%rbp), %rdi
leaq -0x76(%rbp), %rdx
addq $0x2, %rdx
leaq -0x76(%rbp), %rcx
addq $0x3, %rcx
leaq -0x76(%rbp), %r8
addq $0x4, %r8
leaq -0x76(%rbp), %r9
addq $0x5, %r9
leaq -0x76(%rbp), %r10
leaq -0x76(%rbp), %rax
addq $0x1, %rax
leaq 0x5cec(%rip), %rsi      # 0x1d93e
movq %r10, (%rsp)
movq %rax, 0x8(%rsp)
movb $0x0, %al
callq 0x4480
movq -0x18(%rbp), %rax
testb $0x1, 0x1b8(%rax)
je 0x17c92
movq -0x188(%rbp), %rdi
leaq -0x76(%rbp), %rsi
callq 0x18760
cmpl $0x0, %eax
jne 0x17c90
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x1817a
jmp 0x17c92
movq -0x188(%rbp), %rax
movb -0x74(%rbp), %cl
movb %cl, -0x48(%rbp)
movb -0x73(%rbp), %cl
movb %cl, -0x47(%rbp)
movb -0x72(%rbp), %cl
movb %cl, -0x46(%rbp)
movb -0x71(%rbp), %cl
movb %cl, -0x45(%rbp)
movb -0x76(%rbp), %cl
movb %cl, -0x4a(%rbp)
movb -0x75(%rbp), %cl
movb %cl, -0x49(%rbp)
movq (%rax), %rax
cmpq $0x0, 0x1b0(%rax)
je 0x17d16
movq -0x188(%rbp), %rdi
leaq -0x180(%rbp), %rsi
movq (%rdi), %rax
movq 0x1b0(%rax), %rdx
callq 0x16500
movq -0x188(%rbp), %rdi
leaq -0x180(%rbp), %rsi
movq -0x18(%rbp), %rcx
movl $0x33, %edx
callq 0x171c0
cmpl $0x0, %eax
jne 0x17d14
movl $0x0, -0x4(%rbp)
jmp 0x1817a
jmp 0x17d16
movl $0x2, %edi
movl $0x1, %esi
movl $0x6, %edx
callq 0x40f0
movl %eax, -0x34(%rbp)
cmpl $-0x1, -0x34(%rbp)
jne 0x17d4b
leaq 0x5aae(%rip), %rdi      # 0x1d7e8
callq 0x43a0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x1817a
movl -0x34(%rbp), %edi
movl $0x1, %esi
movl $0x2, %edx
leaq -0x5c(%rbp), %rcx
movl $0x4, %r8d
callq 0x4840
cmpl $-0x1, %eax
jne 0x17d8c
leaq 0x5a7c(%rip), %rdi      # 0x1d7ef
callq 0x43a0
movl -0x34(%rbp), %edi
callq 0x48b0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x1817a
movl -0x34(%rbp), %edi
movl $0x1, %esi
movl $0xd, %edx
leaq -0x54(%rbp), %rcx
movl $0x8, %r8d
callq 0x4840
cmpl $-0x1, %eax
jne 0x17dcd
leaq 0x5a3b(%rip), %rdi      # 0x1d7ef
callq 0x43a0
movl -0x34(%rbp), %edi
callq 0x48b0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x1817a
movq -0x18(%rbp), %rax
cmpl $0x0, 0x28(%rax)
je 0x17de3
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x1817a
movq -0x30(%rbp), %rax
movq %rax, -0x1a0(%rbp)
movq -0x30(%rbp), %rdi
callq 0x41d0
movq %rax, %rcx
movq -0x1a0(%rbp), %rax
movw 0x5cd2(%rip), %dx       # 0x1dada
movw %dx, (%rax,%rcx)
movb 0x5cca(%rip), %dl       # 0x1dadc
movb %dl, 0x2(%rax,%rcx)
movq -0x18(%rbp), %rax
movl 0x10(%rax), %eax
movl %eax, -0x194(%rbp)
movq -0x30(%rbp), %rax
movq %rax, -0x190(%rbp)
movq -0x30(%rbp), %rdi
callq 0x41d0
movl -0x194(%rbp), %edi
movq -0x190(%rbp), %rsi
movq %rax, %rdx
callq 0x4160
movl %eax, -0x7c(%rbp)
leaq 0xe77a(%rip), %rax      # 0x265d0
testb $0x1, (%rax)
je 0x17e83
movl $0xba, %edi
movb $0x0, %al
callq 0x4090
movq %rax, %rsi
movq -0x18(%rbp), %rax
movl 0x10(%rax), %edx
movq -0x30(%rbp), %rcx
leaq 0x5ae5(%rip), %rdi      # 0x1d961
movb $0x0, %al
callq 0x4070
cmpl $0x0, -0x7c(%rbp)
jg 0x17efb
callq 0x4060
movl (%rax), %eax
movl %eax, -0x38(%rbp)
movl $0xba, %edi
movb $0x0, %al
callq 0x4090
movq %rax, -0x1b8(%rbp)
movq -0x18(%rbp), %rax
movl 0x10(%rax), %eax
movl %eax, -0x1ac(%rbp)
movq -0x30(%rbp), %rax
movq %rax, -0x1a8(%rbp)
callq 0x4060
movl (%rax), %edi
callq 0x4150
movq -0x1b8(%rbp), %rsi
movl -0x1ac(%rbp), %edx
movq -0x1a8(%rbp), %rcx
movq %rax, %r8
leaq 0x5a95(%rip), %rdi      # 0x1d97d
movb $0x0, %al
callq 0x4070
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x1817a
jmp 0x17efd
movl -0x3c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x3c(%rbp)
movl -0x34(%rbp), %edi
leaq -0x4c(%rbp), %rsi
movl $0x10, %edx
callq 0x4390
cmpl $-0x1, %eax
jne 0x17f82
cmpl $0x5, -0x3c(%rbp)
jl 0x17f80
callq 0x4060
movl (%rax), %eax
movl %eax, -0x38(%rbp)
movq 0xe0bd(%rip), %rdi      # 0x25ff0
leaq 0x5a70(%rip), %rsi      # 0x1d9aa
callq 0x4490
movq %rax, -0x1c0(%rbp)
movl -0x38(%rbp), %edi
callq 0x4150
movq -0x1c0(%rbp), %rdi
movq %rax, %rsi
callq 0x4490
movq %rax, %rdi
movq 0xe031(%rip), %rsi      # 0x25f98
callq 0x44e0
movl -0x34(%rbp), %edi
callq 0x48b0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x1817a
jmp 0x17f84
jmp 0x17f89
jmp 0x17efd
movq -0x188(%rbp), %rdi
movq -0x18(%rbp), %rdx
movl $0x31, %esi
callq 0x16cc0
cmpl $0x0, %eax
jne 0x17fb7
movl -0x34(%rbp), %edi
callq 0x48b0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x1817a
leaq 0xe612(%rip), %rax      # 0x265d0
testb $0x1, (%rax)
je 0x17ff2
movl $0xba, %edi
movb $0x0, %al
callq 0x4090
movq %rax, %rsi
movq -0x18(%rbp), %rax
movl 0x10(%rax), %edx
movq -0x18(%rbp), %rcx
addq $0x88, %rcx
leaq 0x585d(%rip), %rdi      # 0x1d848
movb $0x0, %al
callq 0x4070
movl $0x1, %edi
movl $0x1c0, %esi            # imm = 0x1C0
callq 0x42b0
movq %rax, -0x68(%rbp)
cmpq $0x0, -0x68(%rbp)
jne 0x1802c
leaq 0x5705(%rip), %rdi      # 0x1d718
callq 0x43a0
movl -0x34(%rbp), %edi
callq 0x48b0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x1817a
cmpl $0x41, -0x24(%rbp)
jne 0x18073
movl $0x400, %edi            # imm = 0x400
callq 0x4620
movq -0x68(%rbp), %rcx
movq %rax, 0x20(%rcx)
cmpq $0x0, %rax
jne 0x18073
leaq 0x56c7(%rip), %rdi      # 0x1d718
callq 0x43a0
movl -0x34(%rbp), %edi
callq 0x48b0
movq -0x68(%rbp), %rdi
callq 0x45a0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x1817a
movl -0x34(%rbp), %ecx
movq -0x68(%rbp), %rax
movl %ecx, 0x10(%rax)
movl -0x28(%rbp), %ecx
movq -0x68(%rbp), %rax
movl %ecx, 0x28(%rax)
movq -0x18(%rbp), %rax
cmpl $0x1, 0x38(%rax)
jne 0x1809e
movq -0x18(%rbp), %rax
movq %rax, -0x1c8(%rbp)
jmp 0x180a9
xorl %eax, %eax
movq %rax, -0x1c8(%rbp)
jmp 0x180a9
movq -0x1c8(%rbp), %rcx
movq -0x68(%rbp), %rax
movq %rcx, 0x30(%rax)
movq -0x18(%rbp), %rcx
movq -0x68(%rbp), %rax
movq 0x40(%rcx), %rdx
movq %rdx, 0x40(%rax)
movq 0x48(%rcx), %rcx
movq %rcx, 0x48(%rax)
movq -0x18(%rbp), %rax
movq 0x68(%rax), %rcx
movq -0x68(%rbp), %rax
movq %rcx, 0x68(%rax)
movq -0x68(%rbp), %rax
movq $0x0, 0x70(%rax)
movq -0x68(%rbp), %rax
movq $0x0, 0x80(%rax)
movq -0x18(%rbp), %rax
movq 0x78(%rax), %rcx
movq -0x68(%rbp), %rax
movq %rcx, 0x78(%rax)
movq -0x68(%rbp), %rax
cmpq $0x0, 0x40(%rax)
jne 0x18121
movq -0x68(%rbp), %rax
cmpq $0x0, 0x48(%rax)
je 0x18133
movq -0x18(%rbp), %rax
movq 0x58(%rax), %rcx
movq -0x68(%rbp), %rax
movq %rcx, 0x58(%rax)
jmp 0x1813f
movq -0x68(%rbp), %rax
movq $0x0, 0x58(%rax)
movq -0x68(%rbp), %rax
cmpq $0x0, 0x78(%rax)
je 0x1815c
movq -0x18(%rbp), %rax
movq 0x50(%rax), %rcx
movq -0x68(%rbp), %rax
movq %rcx, 0x50(%rax)
jmp 0x18168
movq -0x68(%rbp), %rax
movq $0x0, 0x50(%rax)
movq -0x68(%rbp), %rcx
movq -0x20(%rbp), %rax
movq %rcx, (%rax)
movl $0x1, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x1e0, %rsp            # imm = 0x1E0
popq %rbp
retq
nopw %cs:(%rax,%rax)