#include #include #include #include #include #include #ifndef __WIN32__ #include #include #include #else #include #include #endif #include "main.h" #include "list.h" #include "tux.h" #include "proto.h" #include "client.h" #include "screen_analyze.h" #include "screen_world.h" #include "udp.h" #include "tcp.h" #include "buffer.h" static sock_udp_t *sock_server_udp; static sock_tcp_t *sock_server_tcp; static list_t *listRecvMsg; static buffer_t *clientRecvBuffer; static buffer_t *clientSendBuffer; static my_time_t lastPing; static my_time_t lastPingServerAlive; #ifdef SUPPORT_TRAFFIC static my_time_t lastTraffic; static int traffic_down; static int traffic_up; #endif typedef struct proto_cmd_client_struct { char *name; int len; void (*fce_proto)(char *msg); } proto_cmd_client_t; static proto_cmd_client_t proto_cmd_list[] = { { .name = "error", .len = 5, .fce_proto = proto_recv_error_client }, { .name = "init", .len = 4, .fce_proto = proto_recv_init_client }, { .name = "event", .len = 5, .fce_proto = proto_recv_event_client }, { .name = "newtux", .len = 6, .fce_proto = proto_recv_newtux_client }, { .name = "del", .len = 3, .fce_proto = proto_recv_del_client }, { .name = "additem", .len = 7, .fce_proto = proto_recv_additem_client }, { .name = "shot", .len = 4, .fce_proto = proto_recv_shot_client }, { .name = "kill", .len = 4, .fce_proto = proto_recv_kill_client }, { .name = "module", .len = 6, .fce_proto = proto_recv_module_client }, { .name = "chat", .len = 4, .fce_proto = proto_recv_chat_client }, { .name = "ping", .len = 4, .fce_proto = proto_recv_ping_client }, { .name = "end", .len = 3, .fce_proto = proto_recv_end_client }, { .name = "", .len = 0, .fce_proto = NULL }, }; static proto_cmd_client_t* findCmdProto(char *msg) { int len; int i; len = strlen(msg); for( i = 0 ; proto_cmd_list[i].len != 0 ; i++ ) { proto_cmd_client_t *thisCmd; thisCmd = &proto_cmd_list[i]; if( len >= thisCmd->len && strncmp(msg, thisCmd->name, thisCmd->len) == 0 ) { return thisCmd; } } return NULL; } static int initUdpClient(char *ip, int port, int proto) { sock_server_udp = connectUdpSocket(ip, port, proto); if( sock_server_udp == NULL ) { return -1; } #ifdef DEBUG printf(_("Connected to: %s on port: %d via UDP\n"), ip, port); #endif return 0; } static int initTcpClient(char *ip, int port, int proto) { sock_server_tcp = connectTcpSocket(ip, port, proto); if( sock_server_tcp == NULL ) { return -1; } disableNagle(sock_server_tcp); setTcpSockNonBlock(sock_server_tcp); #ifdef DEBUG printf(_("Connected to: %s on port: %d via TCP\n"), ip, port); #endif return 0; } int initClient(char *ip, int port, int proto) { char name[STR_NAME_SIZE]; int ret; listRecvMsg = newList(); lastPing = getMyTime(); lastPingServerAlive = getMyTime(); #ifdef SUPPORT_TRAFFIC lastTraffic = getMyTime(); traffic_down = 0; traffic_up = 0; #endif clientRecvBuffer = newBuffer(CLIENT_BUFFER_LIMIT); clientSendBuffer = newBuffer(CLIENT_BUFFER_LIMIT); if( ! isParamFlag("--udp") && ! isParamFlag("--tcp") ) { ret = initUdpClient(ip, port, proto); if( ret < 0 ) { return -1; } } if( isParamFlag("--udp") && ! isParamFlag("--tcp") ) { ret = initUdpClient(ip, port, proto); if( ret < 0 ) { return -1; } } if( isParamFlag("--tcp") && ! isParamFlag("--udp") ) { ret = initTcpClient(ip, port, proto); if( ret < 0 ) { return -1; } } getSettingNameRight(name); proto_send_hello_client(name); return 0; } static void errorWithServer() { fprintf(stderr, _("Server did not respond!\n")); setMsgToAnalyze(_("Server is not running or being blocked. I was unable to connect.")); setWorldEnd(); } static void sendBuffer() { void *data; int len; int res; len = getBufferSize(clientSendBuffer); if( len == 0 ) { return; } data = getBufferData(clientSendBuffer); res = writeTcpSocket(sock_server_tcp, data, len); if( res < 0 ) { errorWithServer(); return; } cutBuffer(clientSendBuffer, res); } void sendServer(char *msg) { int ret; assert( msg != NULL ); #ifndef PUBLIC_SERVER if( isParamFlag("--send") ) { printf(_("Sending: \"%s\""), msg); } #endif #ifdef SUPPORT_TRAFFIC traffic_up += strlen(msg); #endif if( sock_server_udp != NULL ) { ret = writeUdpSocket(sock_server_udp, sock_server_udp, msg, strlen(msg)); } if( sock_server_tcp != NULL ) { //ret = writeTcpSocket(sock_server_tcp, msg, strlen(msg)); ret = addBuffer(clientSendBuffer, msg, strlen(msg)); } if( ret < 0 ) { errorWithServer(); return; } } static int eventServerSelect() { char buffer[STR_PROTO_SIZE]; int ret; memset(buffer, 0, STR_PROTO_SIZE); if( sock_server_udp != NULL ) { ret = readUdpSocket(sock_server_udp, sock_server_udp, buffer, STR_PROTO_SIZE-1); } if( sock_server_tcp != NULL ) { ret = readTcpSocket(sock_server_tcp, buffer, STR_PROTO_SIZE-1); } if( ret < 0 ) { errorWithServer(); return ret; } #ifdef SUPPORT_TRAFFIC traffic_down += ret; #endif if( addBuffer(clientRecvBuffer, buffer, ret) < 0 ) { errorWithServer(); return ret; } while( getBufferLine(clientRecvBuffer, buffer, STR_PROTO_SIZE) >= 0 ) { if( strlen(buffer) > 0) { addList(listRecvMsg, strdup(buffer) ); } } return ret; } static void eventClientWorkRecvList() { proto_cmd_client_t *protoCmd; char *line; int i; /* obsluha udalosti od servera */ assert( listRecvMsg != NULL ); for( i = 0 ; i < listRecvMsg->count ; i++ ) { line = (char *)listRecvMsg->list[i]; protoCmd = findCmdProto(line); #ifndef PUBLIC_SERVER if( isParamFlag("--recv") ) { printf(_("Recieved: \"%s\""), line); } #endif if( protoCmd != NULL ) { protoCmd->fce_proto(line); lastPingServerAlive = getMyTime(); } } destroyListItem(listRecvMsg, free); listRecvMsg = newList(); } static void eventPingServer() { my_time_t currentTime; currentTime = getMyTime(); if( currentTime - lastPing > CLIENT_TIMEOUT ) { proto_send_ping_client(); lastPing = getMyTime(); } } static bool_t isServerAlive() { my_time_t currentTime; currentTime = getMyTime(); if( currentTime - lastPingServerAlive > SERVER_TIMEOUT_ALIVE ) { return FALSE; } return TRUE; } static void selectClientSocket() { fd_set readfds; struct timeval tv; int max_fd; int sock; bool_t isNext; if( sock_server_udp != NULL ) { if( isServerAlive() == FALSE ) { errorWithServer(); return; } } do{ isNext = FALSE; tv.tv_sec = 0; tv.tv_usec = 0; FD_ZERO(&readfds); if( sock_server_udp != NULL ) { sock = sock_server_udp->sock; } if( sock_server_tcp != NULL ) { sock = sock_server_tcp->sock; } FD_SET(sock, &readfds); max_fd = sock; select(max_fd+1, &readfds, (fd_set *)NULL, (fd_set *)NULL, &tv); if( FD_ISSET(sock, &readfds) ) { if( eventServerSelect() > 0 ) { isNext = TRUE; } } }while( isNext == TRUE ); } #ifdef SUPPORT_TRAFFIC static void eventTraffic() { my_time_t currentTime; currentTime = getMyTime(); if( currentTime - lastTraffic > 5000 ) { lastTraffic = currentTime; #ifdef DEBUG printf(_("down: %d\n") _("up : %d\n"), traffic_down, traffic_up); #endif traffic_down = 0; traffic_up = 0; } } #endif void eventClient() { #ifdef SUPPORT_TRAFFIC eventTraffic(); #endif eventPingServer(); selectClientSocket(); eventClientWorkRecvList(); sendBuffer(); } static void quitUdpClient() { assert( sock_server_udp != NULL ); closeUdpSocket(sock_server_udp); #ifdef DEBUG printf(_("Closing UDP connection.\n")); #endif } static void quitTcpClient() { assert( sock_server_tcp != NULL ); closeTcpSocket(sock_server_tcp); #ifdef DEBUG printf(_("Closing TCP connection.\n")); #endif } void quitClient() { proto_send_end_client(); assert( listRecvMsg != NULL ); destroyListItem(listRecvMsg, free); destroyBuffer(clientRecvBuffer); destroyBuffer(clientSendBuffer); if( sock_server_udp != NULL ) { quitUdpClient(); } if( sock_server_tcp != NULL ) { quitTcpClient(); } }