T recv() { // two options again // - there is data available // - we have to wait until there is data available std::cerr << " [recv: entered recv]\n"; buffer_lock.lock(); std::cerr << " [recv: got buffer]\n"; if (buffer_has_data()) { std::cerr << " [recv: buffer has data]\n"; // we can in fact just get data from the buffer T data = buffer_pop(); buffer_lock.unlock(); std::cerr << " [recv: unlocked buffer]\n"; // it is possible someone was trying to send data, notify (one of) them. provides_value.unlock(); std::cerr << " [recv: unlocked provides_value]\n"; return data; } else { // we need to wait until someone sends us data buffer_lock.unlock(); std::cerr << " [recv: unlocked buffer]\n"; needs_value.lock(); std::cerr << " [recv: single lock needs_value]\n"; needs_value.lock(); // double lock std::cerr << " [recv: double lock unlocked]\n"; // unlock by a sender buffer_lock.lock(); std::cerr << " [recv: got buffer lock]\n"; assert(buffer_has_data()); T data = buffer_pop(); std::cerr << " [recv: popped data]\n"; buffer_lock.unlock(); std::cerr << " [recv: unlocked buffer]\n"; // unlock the double lock needs_value.unlock(); std::cerr << " [recv: unlocked double lock]\n"; // it is possible someone was trying to send data provides_value.unlock(); std::cerr << " [recv: unlocked provides_value]\n"; return data; } }
BOOL buffer_fetch_BYTE(BUFFER *buf, BYTE **ptr, BYTE *b) { BYTE *p = *ptr; if(!buffer_has_data(buf, p, sizeof(BYTE))) return FALSE; *b = BUF_FETCH_BYTE(p); *ptr = p; return TRUE; }
BOOL buffer_fetch_WORD(BUFFER *buf, BYTE **ptr, WORD *w) { BYTE *p = *ptr; if(!buffer_has_data(buf, p, sizeof(WORD))) return FALSE; *w = BUF_FETCH_WORD(p); *ptr = p; return TRUE; }
BOOL buffer_fetch_STRING(BUFFER *buf, BYTE **ptr, STRING **pstr, INT len) { BYTE *p = *ptr; if(!buffer_has_data(buf, p, len)) return FALSE; *pstr = string_nappend(NULL, (CHAR *)p, len); BUF_ROLL(p, len); *ptr = p; return TRUE; }
BOOL buffer_fetch_bytes(BUFFER *buf, BYTE **ptr, BYTE *bytes, INT len) { BYTE *p = *ptr; if(!buffer_has_data(buf, p, len)) return FALSE; //pstr = string_nappend(NULL, p, len); memcpy(bytes, p, len); BUF_ROLL(p, len); *ptr = p; return TRUE; }
BOOL socket_fetch_BYTE(SOCKET sock, BUFFER *buf, BYTE **ptr, BYTE *b) { int len; BYTE tmpbuf[1024]; BYTE *p = *ptr; while (!buffer_has_data(buf, p, sizeof(BYTE))) { len = os_socket_tcp_recv_nonblock(sock, tmpbuf, sizeof(tmpbuf)); buffer_append(buf, tmpbuf, len); } *b = BUF_FETCH_BYTE(p); *ptr = p; return TRUE; }
BOOL socket_fetch_bytes(SOCKET sock, BUFFER *buf, BYTE **ptr, BYTE *bytes, INT len1) { int len; BYTE tmpbuf[1024]; BYTE *p = *ptr; while (!buffer_has_data(buf, p, len1)) { len = os_socket_tcp_recv_nonblock(sock, tmpbuf, sizeof(tmpbuf)); buffer_append(buf, tmpbuf, len); } memcpy(bytes, p, len1); BUF_ROLL(p, len1); *ptr = p; return TRUE; }
BOOL socket_fetch_STRING(SOCKET sock, BUFFER *buf, BYTE **ptr, STRING **pstr, INT len1) { int len; BYTE tmpbuf[1024]; BYTE *p = *ptr; while (!buffer_has_data(buf, p, len1)) { len = os_socket_tcp_recv_nonblock(sock, tmpbuf, sizeof(tmpbuf)); buffer_append(buf, tmpbuf, len); } *pstr = string_nappend(NULL, (CHAR *)p, len1); BUF_ROLL(p, len1); *ptr = p; return TRUE; }
static int tunet_logout_recv_logout() { BYTE tmpbuf[1024 * 8]; CHAR tmp[1024]; BYTE btag; UINT32 unknowntag; BYTE *p; int len; DWORD datalen; const CHAR *LOGOUT_TUNET = "LOGOUT TUNET"; STRING *str = NULL; BOOL sr, sw, se; if(!logout_socket) return OK; os_socket_tcp_status(logout_socket, &sr, &sw, &se); if(tunet_state != TUNET_STATE_LOGOUT_RECV_LOGOUT) return OK; if(se) { logs_append(g_logs, "TUNET_NETWORK_ERROR", "RECV_LOGOUT", NULL, 0); return ERR; } if(!sr) return OK; len = os_socket_tcp_recv(logout_socket, tmpbuf, sizeof(tmpbuf)); if(len == -1) { logs_append(g_logs, "TUNET_NETWORK_ERROR", "RECV_LOGOUT", NULL, 0); return ERR; } if(len > 0) { logout_socket_buffer = buffer_append(logout_socket_buffer, tmpbuf, len); buf2output(tmpbuf, len, tmp, len); //dprintf("data received(logout):\n%s\n", tmp); logs_append(g_logs, "TUNET_LOGOUT_RECV", NULL, tmpbuf, len); p = logout_socket_buffer->data; while(buffer_fetch_BYTE(logout_socket_buffer, &p, &btag)) { // printf("recv logout. 0x%x\n",btag); switch(btag) { case 0x10: if(!buffer_has_data(logout_socket_buffer, p, strlen(LOGOUT_TUNET) + 4)) return OK; buffer_fetch_STRING(logout_socket_buffer, &p, &str, strlen(LOGOUT_TUNET)); if(strcmp(str->str, LOGOUT_TUNET) != 0) { //dprintf("[tunet_logout_recv] unknown string\n"); tunet_state = TUNET_STATE_ERROR; return OK; } str = string_free(str); buffer_fetch_DWORD(logout_socket_buffer, &p, &unknowntag); //say "we will logout" os_socket_tcp_send(logout_socket, (BYTE *)"\x0cLOGOUT", 7); logout_socket_buffer = buffer_rollto(logout_socket_buffer, p); p = logout_socket_buffer->data; break; // case 0x0d: case 0x0e: if(!buffer_fetch_DWORD(logout_socket_buffer, &p, &datalen)) return OK; datalen = htonl(datalen); //dprintf("注销反馈消息长 %d\n", datalen); if(!buffer_fetch_STRING(logout_socket_buffer, &p, &str, datalen)) return OK; //dprintf("%s\n", str->str); logs_append(g_logs, "TUNET_LOGOUT_MSG", str->str, NULL, 0); logs_append(g_logs, "TUNET_LOGOUT", NULL, NULL, 0); str = string_free(str); tunet_state = TUNET_STATE_NONE; logout_socket_buffer = buffer_rollto(logout_socket_buffer, p); p = logout_socket_buffer->data; break; } } } return OK; }
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; }