// File: /workspace/github_c_makefile_star2_O0/sszllzss[P]webSocket_Libevent_ThreadPool/ev_websocket.c
// Function: ev_webSocket_clientLinkToServer(event_base*, char*, int, char*, void (*)(bufferevent*, void*), void (*)(bufferevent*, void*), void (*)(bufferevent*, short, void*), void*)
struct bufferevent *  ev_webSocket_clientLinkToServer(struct event_base * base ,char *ip, int port, char *interface_path, bufferevent_data_cb read_cb, bufferevent_data_cb write_cb, bufferevent_event_cb event_cb, void * arg)
{
    int ret, fd , timeOut;
    struct evutil_addrinfo hints;
    struct evutil_addrinfo *addr_out = NULL;
    //int i;
    unsigned char loginBuf[512] = {0}, recBuf[512] = {0}, shakeKey[128] = {0}, *p;

    memset(&hints,0 , sizeof(hints));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    hints.ai_flags = EVUTIL_AI_ADDRCONFIG;
    int err = evutil_getaddrinfo(ip, NULL, &hints, &addr_out);
    if(err != 0)
    {
        De_printf("ev_webSocket_clientLinkToServer:你输入的'%s'无效或者无法解析！/r/n", ip);
        De_fprintf(stderr, "ev_webSocket_clientLinkToServer:Error while resoliving '%s':%s", 
                ip, evutil_gai_strerror(err));
        return NULL;
    }
    assert(addr_out);
    // zhd服务器端网络地址结构体   
    struct sockaddr_in report_addr; 	
    memset(&report_addr,0,sizeof(report_addr)); 			// 数据初始化--清零     
    report_addr.sin_family = AF_INET; 							// 设置为IP通信     
    report_addr.sin_addr.s_addr = ((struct sockaddr_in *)addr_out->ai_addr)->sin_addr.s_addr;
    //report_addr.sin_addr.s_addr = inet_addr(ip);			// 服务器IP地址     
    report_addr.sin_port = htons(port); 							// 服务器端口号     
    evutil_freeaddrinfo(addr_out);
    if(port<=0)
    {
        De_printf("ev_webSocket_clientLinkToServer:端口输入错误");
    }
    //create unix socket  
    if((fd = socket(AF_INET,SOCK_STREAM, 0)) < 0) 
    {  
        De_printf("webSocket_login : cannot create socket\r\n");  
        return NULL;  
    }
    /* 
    // 测试 -----  创建握手key 和 匹配返回key
    webSocket_buildShakeKey(shakeKey); 
    printf("key1:%s\r\n", shakeKey);
    webSocket_buildRespondShakeKey(shakeKey, strlen(shakeKey), shakeKey);
    printf("key2:%s\r\n", shakeKey);
    */
    //非阻塞
    ret = fcntl(fd , F_GETFL , 0);
    fcntl(fd , F_SETFL , ret | O_NONBLOCK);

    //connect
    timeOut = 0;
    while(connect(fd , (struct sockaddr *)&report_addr,sizeof(struct sockaddr)) == -1)
    {
        if(++timeOut > REPORT_LOGIN_CONNECT_TIMEOUT)
        {
            printf("webSocket_login : %s:%d cannot connect !  %d\r\n" , ip, port, timeOut);  
            //
            sprintf((char *)loginBuf, "webSocket_login : %s:%d cannot connect !  %d" , ip, port, timeOut);
            close(fd); 
            return NULL;  
        }
        delayms(1);  //1ms 
    }

    //发送http协议头
    memset(shakeKey, 0, sizeof(shakeKey));
    webSocket_buildShakeKey(shakeKey);  // 创建握手key

    memset(loginBuf, 0, sizeof(loginBuf));  // 创建协议包
    webSocket_buildHttpHead(ip, port, interface_path, shakeKey, (char *)loginBuf);   
    // 发出协议包
    ret = send(fd , loginBuf , strlen((const char*)loginBuf) , MSG_NOSIGNAL);     
    //
    //printf("\r\nconnect time : %d\r\nsend:\n%s\r\n" , timeOut, loginBuf); 

    while(1)
    {
        memset(recBuf , 0 , sizeof(recBuf));
        ret = recv(fd , recBuf , sizeof(recBuf) ,  MSG_NOSIGNAL);
        if(ret > 0)
        {
            if(strncmp((const char *)recBuf, (const char *)"HTTP", strlen((const char *)"HTTP")) == 0)    // 返回的是http回应信息
            {
                //printf("\r\nlogin_recv : %d / %d\r\n%s\r\n" , ret, timeOut, recBuf); 
                if((p = (unsigned char *)strstr((const char *)recBuf, (const char *)"Sec-WebSocket-Accept: ")) != NULL)    // 检查握手信号
                {
                    p += strlen((const char *)"Sec-WebSocket-Accept: ");
                    sscanf((const char *)p, "%s\r\n", p);
                    if(webSocket_matchShakeKey(shakeKey, strlen((const char *)shakeKey), p, strlen((const char *)p)) == 0)  // 握手成功, 发送登录数据包
                    {
                        //创建bufferevnt
                        struct bufferevent * bufferev =  bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
                        bufferevent_setcb(bufferev, read_cb, write_cb, event_cb, arg);
                        bufferevent_enable(bufferev, EV_READ| EV_WRITE);
                        return bufferev;
                    }
                    else    // 握手信号不对, 重发协议包
                    {
                        ret = send(fd , loginBuf , strlen((const char*)loginBuf) , MSG_NOSIGNAL);     // 重发协议包
                    }
                }
                else
                {
                    ret = send(fd , loginBuf , strlen((const char*)loginBuf) , MSG_NOSIGNAL);     // 重发协议包
                }
            }/*
                else
                {
            // 显示数据
            if(recBuf[0] >= ' ' && recBuf[0] <= '~')
            { 
            printf("\r\nlogin_recv : %d\r\n%s\r\n" , ret, recBuf); 
            }
            else
            {
            printf("\r\nlogin_recv : %d\r\n" , ret); for(i = 0; i < ret; i++) printf("%.2X ", recBuf[i]); printf("\r\n");
            }
            }*/
        }
        else if(ret <= 0)
        {
            ;
        }
        if(++timeOut > REPORT_LOGIN_RESPOND_TIMEOUT)
        {
            close(fd); 
            return NULL;
        }
        delayms(1);  //1ms
    }
    //
    close(fd); 
    return NULL;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x580, %rsp            # imm = 0x580
movq 0x18(%rbp), %rax
movq 0x10(%rbp), %rax
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movl %edx, -0x1c(%rbp)
movq %rcx, -0x28(%rbp)
movq %r8, -0x30(%rbp)
movq %r9, -0x38(%rbp)
movq $0x0, -0x80(%rbp)
leaq -0x280(%rbp), %rdi
xorl %esi, %esi
movl $0x200, %edx            # imm = 0x200
callq 0x4290
leaq -0x480(%rbp), %rdi
xorl %esi, %esi
movl $0x200, %edx            # imm = 0x200
callq 0x4290
leaq -0x500(%rbp), %rdi
xorl %esi, %esi
movl $0x80, %edx
callq 0x4290
leaq -0x78(%rbp), %rdi
xorl %esi, %esi
movl $0x30, %edx
callq 0x4290
movl $0x2, -0x74(%rbp)
movl $0x1, -0x70(%rbp)
movl $0x6, -0x6c(%rbp)
movl $0x20, -0x78(%rbp)
movq -0x18(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
leaq -0x78(%rbp), %rdx
leaq -0x80(%rbp), %rcx
callq 0x4170
movl %eax, -0x50c(%rbp)
cmpl $0x0, -0x50c(%rbp)
je 0x605b
jmp 0x5f81
leaq 0xe213(%rip), %rdi      # 0x1419b
leaq 0xe2b3(%rip), %rsi      # 0x14242
leaq 0xe228(%rip), %rdx      # 0x141be
movl $0x3a7, %ecx            # imm = 0x3A7
movb $0x0, %al
callq 0x4080
movq -0x18(%rbp), %rsi
leaq 0xe2b5(%rip), %rdi      # 0x14262
movb $0x0, %al
callq 0x4080
leaq 0xfd2e(%rip), %rdi      # 0x15ce9
movb $0x0, %al
callq 0x4080
jmp 0x5fc4
movq 0x1700d(%rip), %rax     # 0x1cfd8
movq (%rax), %rdi
leaq 0xe1c6(%rip), %rsi      # 0x1419b
leaq 0xe266(%rip), %rdx      # 0x14242
leaq 0xe1db(%rip), %rcx      # 0x141be
movl $0x3a9, %r8d            # imm = 0x3A9
movb $0x0, %al
callq 0x46e0
movq 0x16fe1(%rip), %rax     # 0x1cfd8
movq (%rax), %rax
movq %rax, -0x538(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x530(%rbp)
movl -0x50c(%rbp), %edi
callq 0x4800
movq -0x538(%rbp), %rdi
movq -0x530(%rbp), %rdx
movq %rax, %rcx
leaq 0xe283(%rip), %rsi      # 0x142b2
movb $0x0, %al
callq 0x46e0
movq 0x16f9b(%rip), %rax     # 0x1cfd8
movq (%rax), %rdi
leaq 0xfca2(%rip), %rsi      # 0x15ce9
movb $0x0, %al
callq 0x46e0
movq $0x0, -0x8(%rbp)
jmp 0x64e3
cmpq $0x0, -0x80(%rbp)
je 0x6064
jmp 0x6083
leaq 0xe286(%rip), %rdi      # 0x142f1
leaq 0xe14c(%rip), %rsi      # 0x141be
movl $0x3ac, %edx            # imm = 0x3AC
leaq 0xe27c(%rip), %rcx      # 0x142fa
callq 0x4310
leaq -0x51c(%rbp), %rdi
xorl %esi, %esi
movl $0x10, %edx
callq 0x4290
movw $0x2, -0x51c(%rbp)
movq -0x80(%rbp), %rax
movq 0x18(%rax), %rax
movl 0x4(%rax), %eax
movl %eax, -0x518(%rbp)
movl -0x1c(%rbp), %eax
movzwl %ax, %edi
callq 0x4090
movw %ax, -0x51a(%rbp)
movq -0x80(%rbp), %rdi
callq 0x4650
cmpl $0x0, -0x1c(%rbp)
jg 0x6112
jmp 0x60d3
leaq 0xe0c1(%rip), %rdi      # 0x1419b
leaq 0xe161(%rip), %rsi      # 0x14242
leaq 0xe0d6(%rip), %rdx      # 0x141be
movl $0x3b7, %ecx            # imm = 0x3B7
movb $0x0, %al
callq 0x4080
leaq 0xe2a5(%rip), %rdi      # 0x143a0
movb $0x0, %al
callq 0x4080
leaq 0xfbe0(%rip), %rdi      # 0x15ce9
movb $0x0, %al
callq 0x4080
jmp 0x6112
movl $0x2, %edi
movl $0x1, %esi
xorl %edx, %edx
callq 0x4130
movl %eax, -0x40(%rbp)
cmpl $0x0, %eax
jge 0x6177
jmp 0x612d
leaq 0xe067(%rip), %rdi      # 0x1419b
leaq 0xe107(%rip), %rsi      # 0x14242
leaq 0xe07c(%rip), %rdx      # 0x141be
movl $0x3bc, %ecx            # imm = 0x3BC
movb $0x0, %al
callq 0x4080
leaq 0xe27e(%rip), %rdi      # 0x143d3
movb $0x0, %al
callq 0x4080
leaq 0xfb86(%rip), %rdi      # 0x15ce9
movb $0x0, %al
callq 0x4080
movq $0x0, -0x8(%rbp)
jmp 0x64e3
movl -0x40(%rbp), %edi
movl $0x3, %esi
xorl %edx, %edx
movb $0x0, %al
callq 0x42c0
movl %eax, -0x3c(%rbp)
movl -0x40(%rbp), %edi
movl -0x3c(%rbp), %edx
orl $0x800, %edx            # imm = 0x800
movl $0x4, %esi
movb $0x0, %al
callq 0x42c0
movl $0x0, -0x44(%rbp)
movl -0x40(%rbp), %edi
leaq -0x51c(%rbp), %rsi
movl $0x10, %edx
callq 0x4400
cmpl $-0x1, %eax
jne 0x6233
movl -0x44(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x44(%rbp)
leaq 0x172ed(%rip), %rcx     # 0x1d4c0
cmpl (%rcx), %eax
jle 0x6224
movq -0x18(%rbp), %rsi
movl -0x1c(%rbp), %edx
movl -0x44(%rbp), %ecx
leaq 0xe214(%rip), %rdi      # 0x143fc
movb $0x0, %al
callq 0x4080
leaq -0x280(%rbp), %rdi
movq -0x18(%rbp), %rdx
movl -0x1c(%rbp), %ecx
movl -0x44(%rbp), %r8d
leaq 0xe223(%rip), %rsi      # 0x1442b
movb $0x0, %al
callq 0x4110
movl -0x40(%rbp), %edi
callq 0x48f0
movq $0x0, -0x8(%rbp)
jmp 0x64e3
movl $0x1, %edi
callq 0x64f0
jmp 0x61aa
leaq -0x500(%rbp), %rdi
xorl %esi, %esi
movl $0x80, %edx
callq 0x4290
leaq -0x500(%rbp), %rdi
callq 0x50b0
leaq -0x280(%rbp), %rdi
xorl %esi, %esi
movl $0x200, %edx            # imm = 0x200
callq 0x4290
movq -0x18(%rbp), %rdi
movl -0x1c(%rbp), %esi
movq -0x28(%rbp), %rdx
leaq -0x500(%rbp), %rcx
leaq -0x280(%rbp), %r8
callq 0x5320
movl -0x40(%rbp), %eax
movl %eax, -0x544(%rbp)
leaq -0x280(%rbp), %rax
movq %rax, -0x540(%rbp)
leaq -0x280(%rbp), %rdi
callq 0x4220
movl -0x544(%rbp), %edi
movq -0x540(%rbp), %rsi
movq %rax, %rdx
movl $0x4000, %ecx           # imm = 0x4000
callq 0x4250
movl %eax, -0x3c(%rbp)
leaq -0x480(%rbp), %rdi
xorl %esi, %esi
movl $0x200, %edx            # imm = 0x200
callq 0x4290
movl -0x40(%rbp), %edi
leaq -0x480(%rbp), %rsi
movl $0x200, %edx            # imm = 0x200
movl $0x4000, %ecx           # imm = 0x4000
callq 0x4180
movl %eax, -0x3c(%rbp)
cmpl $0x0, -0x3c(%rbp)
jle 0x64a4
leaq -0x480(%rbp), %rdi
leaq 0xe14e(%rip), %rsi      # 0x14458
movl $0x4, %edx
callq 0x4240
cmpl $0x0, %eax
jne 0x64a2
leaq -0x480(%rbp), %rdi
leaq 0xe132(%rip), %rsi      # 0x1445d
callq 0x4120
movq %rax, -0x508(%rbp)
cmpq $0x0, %rax
je 0x6460
movq -0x508(%rbp), %rax
addq $0x16, %rax
movq %rax, -0x508(%rbp)
movq -0x508(%rbp), %rdi
movq -0x508(%rbp), %rdx
leaq 0xe1a2(%rip), %rsi      # 0x1450a
movb $0x0, %al
callq 0x44c0
leaq -0x500(%rbp), %rax
movq %rax, -0x560(%rbp)
leaq -0x500(%rbp), %rdi
callq 0x4220
movl %eax, -0x554(%rbp)
movq -0x508(%rbp), %rax
movq %rax, -0x550(%rbp)
movq -0x508(%rbp), %rdi
callq 0x4220
movq -0x560(%rbp), %rdi
movl -0x554(%rbp), %esi
movq -0x550(%rbp), %rdx
movl %eax, %ecx
callq 0x5200
cmpl $0x0, %eax
jne 0x641e
movq -0x10(%rbp), %rdi
movl -0x40(%rbp), %esi
movl $0x1, %edx
callq 0x47f0
movq %rax, -0x528(%rbp)
movq -0x528(%rbp), %rdi
movq -0x30(%rbp), %rsi
movq -0x38(%rbp), %rdx
movq 0x10(%rbp), %rcx
movq 0x18(%rbp), %r8
callq 0x4500
movq -0x528(%rbp), %rdi
movl $0x6, %esi
callq 0x48b0
movq -0x528(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x64e3
movl -0x40(%rbp), %eax
movl %eax, -0x56c(%rbp)
leaq -0x280(%rbp), %rax
movq %rax, -0x568(%rbp)
leaq -0x280(%rbp), %rdi
callq 0x4220
movl -0x56c(%rbp), %edi
movq -0x568(%rbp), %rsi
movq %rax, %rdx
movl $0x4000, %ecx           # imm = 0x4000
callq 0x4250
movl %eax, -0x3c(%rbp)
jmp 0x64a0
movl -0x40(%rbp), %eax
movl %eax, -0x57c(%rbp)
leaq -0x280(%rbp), %rax
movq %rax, -0x578(%rbp)
leaq -0x280(%rbp), %rdi
callq 0x4220
movl -0x57c(%rbp), %edi
movq -0x578(%rbp), %rsi
movq %rax, %rdx
movl $0x4000, %ecx           # imm = 0x4000
callq 0x4250
movl %eax, -0x3c(%rbp)
jmp 0x64a2
jmp 0x64ae
cmpl $0x0, -0x3c(%rbp)
jg 0x64ac
jmp 0x64ac
jmp 0x64ae
movl -0x44(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x44(%rbp)
leaq 0x1702a(%rip), %rcx     # 0x1d4e8
cmpl (%rcx), %eax
jle 0x64d4
movl -0x40(%rbp), %edi
callq 0x48f0
movq $0x0, -0x8(%rbp)
jmp 0x64e3
movl $0x1, %edi
callq 0x64f0
jmp 0x62c3
movq -0x8(%rbp), %rax
addq $0x580, %rsp            # imm = 0x580
popq %rbp
retq