VOID tunet_start(USERCONFIG *uc) { assert(uc != NULL); if(thread_tunet) { os_thread_kill(thread_tunet); while(thread_tunet) os_sleep(20); } logs_append(g_logs, "TUNET_START", NULL, NULL, 0); memcpy(&userconfig, uc, sizeof(USERCONFIG)); strcpy(keepalive_server, ""); keepalive_server_port = 0; strcpy(msg_server, ""); msg_server_port = 0; main_socket = os_socket_tcp_close(main_socket); keepalive_socket = os_socket_tcp_close(keepalive_socket); logout_socket = os_socket_tcp_close(logout_socket); tunet_state = TUNET_STATE_LOGIN; main_socket_buffer = buffer_clear(main_socket_buffer); keepalive_socket_buffer = buffer_clear(keepalive_socket_buffer); logout_socket_buffer = buffer_clear(logout_socket_buffer); thread_tunet = os_thread_create(tunet_thread, NULL, FALSE, FALSE); }
THREADRET tunet_thread(THREAD *self) { BOOL hasErr = FALSE; fd_set rset; fd_set wset; fd_set eset; struct timeval tv; time_t keepalive_watchDog=0; tv.tv_sec=2; tv.tv_usec=0; int ret,flags; int maxsock; int main_retry=0; char flag,connected=0; logs_append(g_logs, "TUNET_THREAD_STARTING", NULL, NULL, 0); while(os_thread_is_running(self) || os_thread_is_paused(self)) { // printf("main_socket=%d\n",main_socket); if (keepalive_watchDog) { if (time(NULL)-keepalive_watchDog>=36) { if(tunet_keepalive()==ERR) break; } } if (tunet_state==TUNET_STATE_RECV_REMAINING_DATA || tunet_state==TUNET_STATE_RECV_WELCOME) { keepalive_watchDog=time(NULL); } hasErr=FALSE; if(tunet_get_state() == TUNET_STATE_NONE) { break; } if(tunet_get_state() == TUNET_STATE_ERROR) { //an server-side error occurs when trying to login/logout logs_append(g_logs, "TUNET_ERROR", NULL, NULL, 0); break; } if (tunet_state ==TUNET_STATE_LOGOUT) { if (!connected) { break; } tunet_connect_logout_server(); } if (tunet_state==TUNET_STATE_LOGOUT||tunet_state==TUNET_STATE_LOGOUT_RECV_LOGOUT) { hasErr |= (tunet_logout_send_logout() == ERR); hasErr |= (tunet_logout_recv_logout() == ERR); if(hasErr) { //if an error occurs when LOGOUT, we can just omit it, and exit the thread. break; } os_thread_test_paused(self); os_sleep(20); }else { if(tunet_state == TUNET_STATE_LOGIN){ tunet_connect_main_server(); } if(tunet_connect_keepalive_server()==ERR){ break; } if (tunet_state == TUNET_STATE_KEEPALIVE||tunet_state==TUNET_STATE_RECV_REMAINING_DATA) { connected=1; } FD_ZERO(&rset); FD_ZERO(&wset); FD_ZERO(&eset); maxsock=0; flag=0; if (main_socket) { FD_SET(main_socket, &rset); FD_SET(main_socket, &wset); FD_SET(main_socket, &eset); if (main_socket>=maxsock) { maxsock=main_socket; } flag=1; } if (keepalive_socket) { FD_SET(keepalive_socket,&rset); FD_SET(keepalive_socket,&eset); if (keepalive_socket>=maxsock) { maxsock=keepalive_socket; } } ret=select(maxsock+1,&rset,&wset,&eset,&tv); if (ret<0) { logs_append(g_logs, "TUNET_NETWORK_ERROR", "UNKNOWN", NULL, 0); break; }else if (ret==0) { if (tunet_state==TUNET_STATE_LOGIN) { if (main_retry>=3) { logs_append(g_logs, "TUNET_NETWORK_ERROR", "MAIN", NULL, 0); break; } main_retry++; } os_thread_test_paused(self); continue; } if (flag) { if (FD_ISSET(main_socket,&wset)) { tunet_logon_send_tunet_user(); tunet_logon_reply_welcome(); } if (FD_ISSET(main_socket,&rset)) { if(tunet_logon_recv_welcome()==ERR){ logs_append(g_logs, "TUNET_NETWORK_ERROR", "RECV_WELCOME", NULL, 0); break; } if(tunet_logon_recv_remaining_data()==ERR){ logs_append(g_logs, "TUNET_NETWORK_ERROR", "RECV_REMAINING_DATA", NULL, 0); break; } } if (FD_ISSET(main_socket, &eset)) { logs_append(g_logs, "TUNET_NETWORK_ERROR", "MAIN", NULL, 0); break; } } if (FD_ISSET(keepalive_socket,&rset)) { if(tunet_keepalive()==ERR){ logs_append(g_logs, "TUNET_NETWORK_ERROR", "KEEPALIVE", NULL, 0); break; } keepalive_watchDog=time(NULL); } if (FD_ISSET(keepalive_socket, &eset)) { logs_append(g_logs, "TUNET_NETWORK_ERROR", "KEEPALIVE", NULL, 0); break; } os_thread_test_paused(self); } } main_socket = os_socket_tcp_close(main_socket); keepalive_socket = os_socket_tcp_close(keepalive_socket); logout_socket = os_socket_tcp_close(logout_socket); main_socket_buffer = buffer_clear(main_socket_buffer); keepalive_socket_buffer = buffer_clear(keepalive_socket_buffer); logout_socket_buffer = buffer_clear(logout_socket_buffer); tunet_state = TUNET_STATE_NONE; logs_append(g_logs, "TUNET_THREAD_EXITING", NULL, NULL, 0); thread_tunet = os_thread_free(thread_tunet); return 0; }
static int tunet_logon_recv_remaining_data() { BYTE tmpbuf[1024 * 8]; CHAR tmp[1024]; CHAR sztmp[255]; BYTE *p; INT len; BYTE key77[8]; STRING *str = NULL; char des3data[12]; des3_context ctx3; TIME tm; UINT32 datalen, port; UINT32 uint_money; BYTE btag; // BOOL sr, sw, se; if(!main_socket) return OK; // printf("tunet_logon_recv_remaining_data() called.\n"); // os_socket_tcp_status(main_socket, &sr, &sw, &se); if(tunet_state != TUNET_STATE_RECV_REMAINING_DATA && tunet_state != TUNET_STATE_KEEPALIVE) return OK; /* if(se) { logs_append(g_logs, "TUNET_NETWORK_ERROR", "RECV_REMAINING_DATA", NULL, 0); return ERR; } if(!sr) return OK; */ len = os_socket_tcp_recv(main_socket, tmpbuf, sizeof(tmpbuf)); if(len == -1) { logs_append(g_logs, "TUNET_NETWORK_ERROR", "RECV_REMAINING_DATA", NULL, 0); return ERR; } if(len > 0) { main_socket_buffer = buffer_append(main_socket_buffer, tmpbuf, len); logs_append(g_logs, "TUNET_LOGON_RECV", "REMAINING", tmpbuf, len); buf2output(tmpbuf, len, tmp, 16); //dprintf("data received(recv remaining):\n%s\n", tmp); p = main_socket_buffer->data; while(buffer_fetch_BYTE(main_socket_buffer, &p, &btag)) { switch(btag) { case 0x01: if(!buffer_fetch_DWORD(main_socket_buffer, &p, &datalen)) return OK; datalen = htonl(datalen); memset(keepalive_server, 0, sizeof(keepalive_server)); if(!buffer_fetch_bytes(main_socket_buffer, &p, (BYTE *)keepalive_server, datalen)) return OK; if(!buffer_fetch_DWORD(main_socket_buffer, &p, &port)) return OK; port = htonl(port); keepalive_server_port = (short)port; snprintf(sztmp, sizeof(sztmp), "%s:%d", keepalive_server, keepalive_server_port); //dprintf("保持活动服务器:%s\n", sztmp); //we got the KEEPALIVE server, try to keep alive os_tick_clear(keepalive_timeout); tunet_state = TUNET_STATE_KEEPALIVE; logs_append(g_logs, "TUNET_LOGON_KEEPALIVE_SERVER", sztmp, NULL, 0); main_socket_buffer = buffer_rollto(main_socket_buffer, p); p = main_socket_buffer->data; break; case 0x02: //出错消息 if(!buffer_fetch_DWORD(main_socket_buffer, &p, &datalen)) return OK; datalen = htonl(datalen); //dprintf("出错消息长 %d\n", datalen); if(!buffer_fetch_STRING(main_socket_buffer, &p, &str, datalen)) return OK; //dprintf("%s\n", str->str); tunet_state = TUNET_STATE_ERROR; logs_append(g_logs, "TUNET_LOGON_ERROR", str->str, NULL, 0); str = string_free(str); main_socket_buffer = buffer_rollto(main_socket_buffer, p); p = main_socket_buffer->data; break; case 0x05: if(buffer_fetch_BYTE(main_socket_buffer, &p, &btag)) { if(btag != 0) { //dprintf("与消息中介服务器通信结束。\n"); main_socket = os_socket_tcp_close(main_socket); logs_append(g_logs, "TUNET_LOGON_FINISH_MSGSERVER", NULL, NULL, 0); main_socket_buffer = buffer_rollto(main_socket_buffer, p); p = main_socket_buffer->data; break; } } BUF_ROLL(p, -1); //restore the point for further use //出错消息 if(!buffer_fetch_DWORD(main_socket_buffer, &p, &datalen)) return OK; datalen = htonl(datalen); //dprintf("出错消息长 %d\n", datalen); if(!buffer_fetch_STRING(main_socket_buffer, &p, &str, datalen)) return OK; //dprintf("%s\n", str->str); tunet_state = TUNET_STATE_ERROR; logs_append(g_logs, "TUNET_LOGON_ERROR", str->str, NULL, 0); str = string_free(str); main_socket_buffer = buffer_rollto(main_socket_buffer, p); p = main_socket_buffer->data; break; case 0x04: case 0x08: if(!buffer_fetch_DWORD(main_socket_buffer, &p, &datalen)) return OK; datalen = htonl(datalen); memset(msg_server, 0, sizeof(msg_server)); if(!buffer_fetch_bytes(main_socket_buffer, &p, (BYTE *)msg_server, datalen)) return OK; if(!buffer_fetch_DWORD(main_socket_buffer, &p, &port)) return OK; port = htonl(port); msg_server_port = (short)port; if(!buffer_fetch_bytes(main_socket_buffer, &p, key77, 8)) return OK; //登陆消息 if(!buffer_fetch_DWORD(main_socket_buffer, &p, &datalen)) return OK; datalen = htonl(datalen); //dprintf("登陆消息长 %d\n", datalen); if(!buffer_fetch_STRING(main_socket_buffer, &p, &str, datalen)) return OK; //dprintf("%s\n", str->str); logs_append(g_logs, "TUNET_LOGON_MSG", str->str, NULL, 0); str = string_free(str); //make a new key for keep-alive //dprintf("key77 == %s\n", buf2hex(key77, 8, tmp)); memset(des3data, 0, sizeof(des3data)); des3_set_3keys( &ctx3, userconfig.md5Password, userconfig.md5Password + 8, userconfig.md5Password ); des3_encrypt( &ctx3, (uint8 *)key77, (uint8 *)des3data); memcpy(keepalive_key, des3data, 8); main_socket_buffer = buffer_rollto(main_socket_buffer, p); p = main_socket_buffer->data; //-------------------------------- snprintf(sztmp, sizeof(sztmp), "%s:%d", msg_server, msg_server_port); //dprintf("准备连接到消息中介服务器 %s 获得活动服务器地址....\n", sztmp); logs_append(g_logs, "TUNET_LOGON_MSGSERVER", sztmp, NULL, 0); main_socket_buffer = buffer_rollto(main_socket_buffer, p); p = main_socket_buffer->data; //switch to another server to get alive-server ip strcpy(keepalive_server, ""); main_socket = os_socket_tcp_close(main_socket); main_socket = os_socket_tcp_connect(msg_server, msg_server_port, FALSE); break; case 0x1b: if(!buffer_fetch_DWORD(main_socket_buffer, &p, &uint_money)) return OK; uint_money = htonl(uint_money); snprintf(sztmp, sizeof(sztmp), "%0.2f", tunet_imoney_to_fmoney(uint_money)); //dprintf("您在登陆前的余额是:%s\n", sztmp); logs_append(g_logs, "TUNET_LOGON_MONEY", sztmp, NULL, 0); if(buffer_has_data(main_socket_buffer, p, 16)) { snprintf(sztmp, sizeof(sztmp), "%d.%d.%d.%d/%d.%d.%d.%d", p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7]); logs_append(g_logs, "TUNET_LOGON_IPs", sztmp, NULL, 0); //dprintf("登陆IP状况: %s\n", sztmp); BUF_ROLL(p, 8); tm = os_time_convert(htonl(BUFDWORD(p))); snprintf(sztmp, sizeof(sztmp), "%d-%d-%d %d:%d:%d", tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second ); logs_append(g_logs, "TUNET_LOGON_SERVERTIME", sztmp, NULL, 0); //dprintf("当前服务器时间: %s\n", sztmp); BUF_ROLL(p, 4); tm = os_time_convert(htonl(BUFDWORD(p))); snprintf(sztmp, sizeof(sztmp), "%d-%d-%d %d:%d:%d", tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second ); logs_append(g_logs, "TUNET_LOGON_LASTTIME", sztmp, NULL, 0); //dprintf("上次登陆时间: %s\n", sztmp); BUF_ROLL(p, 4); } else { return OK; } main_socket_buffer = buffer_rollto(main_socket_buffer, p); p = main_socket_buffer->data; break; } } } return OK; }
THREADRET tunet_thread(THREAD *self) { BOOL hasErr = FALSE; logs_append(g_logs, "TUNET_THREAD_STARTING", NULL, NULL, 0); while(os_thread_is_running(self) || os_thread_is_paused(self)) { if(tunet_state == TUNET_STATE_LOGIN) tunet_connect_main_server(); hasErr = FALSE; hasErr |= (tunet_logon_send_tunet_user() == ERR); hasErr |= (tunet_logon_recv_welcome() == ERR); hasErr |= (tunet_logon_reply_welcome() == ERR); hasErr |= (tunet_logon_recv_remaining_data() == ERR); hasErr |= (tunet_connect_keepalive_server() == ERR); hasErr |= (tunet_keepalive() == ERR); if(hasErr) { /* COMMENT: We won't help the user to retry for some network error shoud be dealt by the users. //a network error occurs when try to LOGIN main_socket = os_socket_tcp_close(main_socket); keepalive_socket = os_socket_tcp_close(keepalive_socket); tunet_state = TUNET_STATE_LOGIN; continue; */ break; } hasErr = FALSE; if(tunet_state == TUNET_STATE_LOGOUT) tunet_connect_logout_server(); hasErr |= (tunet_logout_send_logout() == ERR); hasErr |= (tunet_logout_recv_logout() == ERR); if(hasErr) { //if an error occurs when LOGOUT, we can just omit it, and exit the thread. break; } if(tunet_get_state() == TUNET_STATE_NONE) { //nothing to do , exit the thread break; } if(tunet_get_state() == TUNET_STATE_ERROR) { //an server-side error occurs when trying to login/logout logs_append(g_logs, "TUNET_ERROR", NULL, NULL, 0); break; } os_thread_test_paused(self); os_sleep(20); } main_socket = os_socket_tcp_close(main_socket); keepalive_socket = os_socket_tcp_close(keepalive_socket); logout_socket = os_socket_tcp_close(logout_socket); main_socket_buffer = buffer_clear(main_socket_buffer); keepalive_socket_buffer = buffer_clear(keepalive_socket_buffer); logout_socket_buffer = buffer_clear(logout_socket_buffer); tunet_state = TUNET_STATE_NONE; logs_append(g_logs, "TUNET_THREAD_EXITING", NULL, NULL, 0); thread_tunet = os_thread_free(thread_tunet); return 0; }