// Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // // Copyright (C) 2000 by DooM Legacy Team. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // //----------------------------------------------------------------------------- #ifdef __GNUC__ #include #include #endif #include #include #include #include "ipcs.h" #include "common.h" #include "mysql.h" #include "md5.h" #include //#include //============================================================================= #ifdef __GNUC__ #define ATTRPACK __attribute__ ((packed)) #else #define ATTRPACK #endif #define PT_ASKINFOVIAMS 15 static CServerSocket server_socket; FILE *logfile; FILE *errorfile; FILE *mysqlfile; FILE *sockfile; FILE *pidfile; #if defined(_MSC_VER) #pragma pack(1) #endif typedef struct { char ip[16]; // Big enough to hold a full address. UINT16 port; UINT8 padding1[2]; UINT32 time; } ATTRPACK ms_holepunch_packet_t; typedef struct { char clientaddr[22]; UINT8 padding1[2]; UINT32 time; } ATTRPACK msaskinfo_pak; // // SRB2 network packet data. // typedef struct { UINT32 checksum; UINT8 ack; // if not null the node asks for acknowledgement, the receiver must resend the ack UINT8 ackreturn; // the return of the ack number UINT8 packettype; UINT8 reserved; // padding msaskinfo_pak msaskinfo; } ATTRPACK doomdata_t; #if defined(_MSC_VER) #pragma pack() #endif //============================================================================= #define HOSTNAME "loopback" #define USER "srb2_ms" #define PASSWORD "gLRDRb7WgLRDRb7W" #define DATABASE "srb2_ms" // MySQL Stuff :D const char *server = HOSTNAME; const char *user = USER; const char *password = PASSWORD; const char *database = DATABASE; time_t lastupdate; MYSQL *conn; MYSQL_RES *res; MYSQL_ROW row; int mysqlconnected = 0; /* char *str_replace(char * t1, char * t2, char * t6) { char*t4; char*t5=new(0); while(strstr(t6,t1)){ t4=strstr(t6,t1); strncpy(t5+strlen(t5),t6,t4-t6); strcat(t5,t2); t4+=strlen(t1); t6=t4; } return strcat(t5,t4); } */ /* // Cue was here char *str_quakeformat(char *msg) { char *quakemsg , *quakemsg1, *quakemsg2; char *quakemsg3, *quakemsg4, *quakemsg5; char *quakemsg6, *quakemsg7, *quakemsg8; quakemsg1 = new(sizeof(char) * (strlen(msg) + 1)); strcpy(quakemsg1, msg); quakemsg2 = str_replace("^1", "\x81",quakemsg1); quakemsg3 = str_replace("^2", "\x82",quakemsg2); quakemsg4 = str_replace("^3", "\x83",quakemsg3); quakemsg5 = str_replace("^4", "\x84",quakemsg4); quakemsg6 = str_replace("^5", "\x85",quakemsg5); quakemsg7 = str_replace("^6", "\x86",quakemsg6); quakemsg8 = str_replace("^7", "\x87",quakemsg7); quakemsg = str_replace("^0", "\x80",quakemsg8); delete(quakemsg1); delete(quakemsg2); delete(quakemsg3); delete(quakemsg4); delete(quakemsg5); delete(quakemsg6); delete(quakemsg7); delete(quakemsg8); return quakemsg; } */ void MySQL_Conn(bool force) { //if(mysql_ping(conn)) //mysqlconnected = 0; logPrintf(mysqlfile, "Trying to connect to MySQL...\n"); if(mysqlconnected != 1 || force) { if(force) mysql_close(conn); const char *server = HOSTNAME; const char *user = USER; const char *password = PASSWORD; const char *database = DATABASE; conn = mysql_init(NULL); /* Connect to database */ if (!mysql_real_connect(conn, server, user, password, database, 8219, NULL, 0)) { logPrintf(errorfile, "%s\n", mysql_error(conn)); } conn = mysql_init(NULL); /* Connect to database */ if (!mysql_real_connect(conn, server, user, password, database, 0, NULL, 0)) { logPrintf(errorfile, "%s\n", mysql_error(conn)); mysqlconnected = 0; } else { logPrintf(mysqlfile, "Connection to MySQL Database successful!\n"); mysqlconnected = 1; } } } static int MySQL_CheckBan(const char *ip, UINT32 id, bool sendinfo, bool type) { msg_t msg; int writecode; MySQL_Conn(false); msg.id = id; char banqueryp1[500] = "SELECT bid,INET_NTOA(ipstart),INET_NTOA(ipend),DATE_FORMAT(FROM_UNIXTIME(full_endtime),'%%a %%b %%e %%Y at %%k:%%i (CDT)'),reason,hostonly,permanent FROM ms_bans WHERE INET_ATON('%s') BETWEEN `ipstart` AND `ipend` AND (`full_endtime` > %ld OR `permanent` = '1') LIMIT 1"; // char exqueryp1[500] = "SELECT * FROM ms_exceptions WHERE `ip` = '%s' AND `bid` = '%s' LIMIT 1"; // char exquery[500]; char banquery[500]; // char bid[5]; time_t current_time = time (NULL); sprintf(banquery, banqueryp1, ip, current_time); logPrintf(mysqlfile, "Executing MySQL Query: %s\n", banquery); if(mysql_query(conn, banquery)) { logPrintf(errorfile, "MYSQL ERROR: %s\n", mysql_error(conn)); MySQL_Conn(true); return false; } else { res = mysql_store_result(conn); if(mysql_num_rows(res) >= 1) { logPrintf(logfile, "We got a ban coming on!\n"); row = mysql_fetch_row(res); if(!type && strcmp(row[5],"1") == 0) return false; if(sendinfo) { logPrintf(logfile, "And we're meant to tell them some more!\n"); msg_ban_t *info = (msg_ban_t *) msg.buffer; info->header[0] = '\0'; logPrintf(logfile, "Got Ban: %s - %s, ends %s, for %s\n", row[1], row[2], row[3], row[4]); logPrintf(logfile, "COPY: ipstart\n"); strcpy(info->ipstart, row[1]); logPrintf(logfile, "COPY: ipend\n"); strcpy(info->ipend, row[2]); logPrintf(logfile, "COPY: endtime\n"); if(strcmp(row[6], "0") == 0) { logPrintf(logfile, "COPY: It's not permanent.\n"); strcpy(info->endstamp, row[3]); } else { logPrintf(logfile, "COPY: It's permanent.\n"); strcpy(info->endstamp, "Never"); } logPrintf(logfile, "COPY: reason\n"); strcpy(info->reason, row[4]); logPrintf(logfile, "COPY: hostonly\n"); if(strcmp(row[5],"0") == 0) info->hostonly = false; else info->hostonly = true; if(info->hostonly) logPrintf(logfile, "BAN HAMMER: %s - %s || Reason: %s || Endstamp: %s || HOSTONLY\n", info->ipstart, info->ipend, info->reason, info->endstamp); else logPrintf(logfile, "BAN HAMMER: %s - %s || Reason: %s || Endstamp: %s || NOTHOSTONLY\n", info->ipstart, info->ipend, info->reason, info->endstamp); mysql_free_result(res); msg.type = GET_BANNED_MSG; msg.length = sizeof (msg_ban_t); msg.room = 0; logPrintf(logfile, "Sending message?\n"); writecode = server_socket.write(&msg); logPrintf(logfile, "Message sent! :D\n"); if (writecode < 0) { dbgPrintf(LIGHTRED, "Write error... %d client %d " "deleted\n", writecode, id); return true; } } return true; } else { mysql_free_result(res); return false; } } } int MySQL_CheckRoom(UINT32 room) { MySQL_Conn(false); char checkqueryp1[500] = "SELECT private FROM `ms_rooms` WHERE `room_id` = '%d' AND `private` = '1' LIMIT 1"; char checkquery[500]; sprintf(checkquery, checkqueryp1, room); logPrintf(mysqlfile, "Executing MySQL Query: %s\n", checkquery); if(mysql_query(conn, checkquery)) { logPrintf(errorfile, "MYSQL ERROR: %s\n", mysql_error(conn)); MySQL_Conn(true); return false; } else { res = mysql_store_result(conn); if(mysql_num_rows(res) < 1) return true; else return false; } } void MySQL_AddServer(const char *ip, const char *port, const char *name, const char *version, UINT32 room, bool firstadd, const char *key) { char escapedName[255]; char escapedPort[10]; char escapedVersion[10]; char escapedKey[32]; char insertquery[5000]; char checkquery[500]; char updatequery[5000]; char queryp1[5000] = "INSERT INTO `ms_servers` (`name`,`ip`,`port`,`version`,`timestamp`,`room`,`key`) VALUES ('%s','%s','%s','%s','%ld','%d','%s')"; char checkqueryp1[500] = "SELECT room_override FROM `ms_servers` WHERE `ip` = '%s'"; char updatequeryp1[5000]; if(firstadd) { logPrintf(logfile, "First add.\n"); strcpy(updatequeryp1, "UPDATE `ms_servers` SET `name` = '%s', `port` = '%s', `version` = '%s', timestamp = '%ld', upnow = '1', `room` = '%d', `delisted` = '0', `key` = '%s' WHERE `ip` = '%s'"); } else { logPrintf(logfile, "Update ping.\n"); strcpy(updatequeryp1, "UPDATE `ms_servers` SET `name` = '%s', `port` = '%s', `version` = '%s', timestamp = '%ld', upnow = '1', `room` = '%d', `key` = '%s' WHERE `ip` = '%s' AND `delisted` = '0'"); } MySQL_Conn(false); mysql_real_escape_string(conn, escapedName, name, (unsigned long)strlen(name)); mysql_real_escape_string(conn, escapedPort, port, (unsigned long)strlen(port)); mysql_real_escape_string(conn, escapedVersion, version, (unsigned long)strlen(version)); mysql_real_escape_string(conn, escapedKey, key, (unsigned long)strlen(key)); if(!MySQL_CheckBan(ip,0,false,1)) { if(!MySQL_CheckRoom(room)) { logPrintf(errorfile, "IP %s tried to use the private room %d! THIS SHOULD NOT HAPPEN\n", ip, room); return; } sprintf(checkquery, checkqueryp1, ip); time_t timestamp; timestamp = time (NULL); logPrintf(logfile, "Checking for existing servers in table with the same IP...\n"); logPrintf(mysqlfile, "Executing MySQL Query: %s\n", checkquery); if(mysql_query(conn, checkquery)) { logPrintf(errorfile, "MYSQL ERROR: %s\n", mysql_error(conn)); MySQL_Conn(true); } else { res = mysql_store_result(conn); logPrintf(logfile, "Found %d rows...\n", mysql_num_rows(res)); if(mysql_num_rows(res) < 1) { mysql_free_result(res); logPrintf(logfile, "Adding the temporary server: %s:%s || Name: %s || Version: %s || Time: %ld || Room: %d || Key: %s\n", ip, port, name, version, timestamp, room, key); sprintf(insertquery, queryp1, escapedName, ip, escapedPort, escapedVersion, timestamp, room, escapedKey); logPrintf(mysqlfile, "Executing MySQL Query: %s\n", insertquery); if(mysql_query(conn, insertquery)) { logPrintf(errorfile, "MYSQL ERROR: %s\n", mysql_error(conn)); MySQL_Conn(true); } else { logPrintf(logfile, "Server added successfully!\n"); } } else { row = mysql_fetch_row(res); if(atoi(row[0]) != 0) room = atoi(row[0]); mysql_free_result(res); logPrintf(logfile, "Server's IP already exists, so let's just update it instead...\n"); logPrintf(logfile, "Updating Server Data for %s\n", ip); sprintf(updatequery, updatequeryp1, escapedName, escapedPort, escapedVersion, timestamp, room, escapedKey, ip); logPrintf(mysqlfile, "Executing MySQL Query: %s\n", updatequery); if(mysql_query(conn, updatequery)) { logPrintf(errorfile, "MYSQL ERROR: %s\n", mysql_error(conn)); MySQL_Conn(true); } else { logPrintf(logfile, "Server status for Server: %s:%s || Name: %s || Version: %s || Time: %ld || Room: %d || Key: %s set successfully.\n", ip, port, name, version, timestamp, room, key); } } } } else { logPrintf(logfile, "IP %s is banned so do nothing.\n", ip); } } void MySQL_ListServers(UINT32 id, UINT32 type, const char *ip, UINT32 room) { msg_t msg; int writecode; MySQL_Conn(false); msg.id = id; msg.type = type; char servquery[1000]; if(room == 0) sprintf(servquery, "SELECT ip, port, name, version FROM ( SELECT * FROM `ms_servers` WHERE `upnow` = '1' ORDER BY `sid` ASC) as t2 ORDER BY `sticky` DESC"); else { char servqueryp1[1000] = "SELECT ip, port, name, version FROM ( SELECT * FROM `ms_servers` WHERE `upnow` = '1' AND `room` = '%d' ORDER BY `sid` ASC) as t2 ORDER BY `sticky` DESC"; sprintf(servquery, servqueryp1, room); } if(!MySQL_CheckBan(ip,0,false,0)) { logPrintf(mysqlfile, "Executing MySQL Query: %s\n", servquery); if(mysql_query(conn, servquery)) { logPrintf(errorfile, "MYSQL ERROR: %s\n", mysql_error(conn)); MySQL_Conn(true); } else { res = mysql_store_result(conn); logPrintf(logfile, "Found %d servers...\n", mysql_num_rows(res)); while ((row = mysql_fetch_row(res)) != NULL) { msg_server_t *info = (msg_server_t *) msg.buffer; info->header[0] = '\0'; // nothing interresting in it (for now) strcpy(info->ip, row[0]); strcpy(info->port, row[1]); strcpy(info->name, row[2]); strcpy(info->version, row[3]); msg.length = sizeof (msg_server_t); msg.room = 0; logPrintf(logfile, "Sending message?\n"); writecode = server_socket.write(&msg); logPrintf(logfile, "Message sent! :D\n"); if (writecode < 0) { dbgPrintf(LIGHTRED, "Write error... %d client %d " "deleted\n", writecode, id); return; } } mysql_free_result(res); } } else { logPrintf(logfile, "IP %s is banned so do nothing.\n", ip); } } void MySQL_ListRooms(UINT32 id, UINT32 type, const char *ip, bool sendtype) { msg_t msg; int writecode; //(void)ip; MySQL_Conn(false); msg.id = id; msg.type = type; char roomquery[1000]; logPrintf(logfile, "Check their ban status first... (ID %d)\n",id); if(MySQL_CheckBan(ip,id,true,sendtype)) return; //Hmph! I suppose it'll be up to me to handle this. ~Inuyasha if (sendtype) { char overridequery[500]; sprintf(overridequery, "SELECT room_override FROM `ms_servers` WHERE `ip` = '%s' AND `room_override` > 0", ip); logPrintf(mysqlfile, "Checking for room overrides! Executing MySQL Query: %s\n", overridequery); if (mysql_query(conn, overridequery)) { logPrintf(errorfile, "MYSQL ERROR: %s\n", mysql_error(conn)); MySQL_Conn(true); return; } res = mysql_store_result(conn); if (mysql_num_rows(res) >= 1) { int overriddenRoom; row = mysql_fetch_row(res); overriddenRoom = atoi(row[0]); mysql_free_result(res); sprintf(roomquery, "SELECT room_id, title, motd FROM `ms_rooms` WHERE `room_id` = '%d' LIMIT 1", overriddenRoom); if (mysql_query(conn, roomquery)) { logPrintf(errorfile, "MYSQL ERROR: %s\n", mysql_error(conn)); MySQL_Conn(true); return; } res = mysql_store_result(conn); if (mysql_num_rows(res) >= 1) { msg_rooms_t *info = (msg_rooms_t *) msg.buffer; char roommotd[300]; row = mysql_fetch_row(res); info->header[0] = '\0'; // nothing interesting in it (for now) strcpy(info->name, row[1]); // Just in case, let's make sure we don't overflow. sprintf(roommotd, "\x85Your server has had a room override applied to it, so this is the only room you may host in.\x80\n\n%s", row[2]); strncpy(info->motd, roommotd, 255); info->motd[255] = '\0'; info->id = atoi(row[0]); logPrintf(logfile, "Sending Room %s with ID %d and MOTD %s\n", info->name, info->id, info->motd); msg.length = sizeof (msg_rooms_t); msg.room = 0; logPrintf(logfile, "Sending message?\n"); writecode = server_socket.write(&msg); logPrintf(logfile, "Message sent! :D\n"); if (writecode < 0) { dbgPrintf(LIGHTRED, "Write error... %d client %d " "deleted\n", writecode, id); } mysql_free_result(res); return; } else { logPrintf(errorfile, "Someone's room override isn't set correctly! Room %d doesn't exist!", overriddenRoom); mysql_free_result(res); } } } if(sendtype) sprintf(roomquery, "SELECT room_id, title, motd FROM `ms_rooms` WHERE `private` = '0' AND `visible` = '1' ORDER BY `order` ASC"); else sprintf(roomquery, "SELECT room_id, title, motd FROM `ms_rooms` WHERE `visible` = '1' ORDER BY `order` ASC"); if(mysql_query(conn, roomquery)) { logPrintf(errorfile, "MYSQL ERROR: %s\n", mysql_error(conn)); MySQL_Conn(true); } else { res = mysql_store_result(conn); logPrintf(logfile, "Found %d rooms...\n", mysql_num_rows(res)); while ((row = mysql_fetch_row(res)) != NULL) { msg_rooms_t *info = (msg_rooms_t *) msg.buffer; info->header[0] = '\0'; // nothing interresting in it (for now) strcpy(info->name, row[1]); strcpy(info->motd, row[2]); info->id = atoi(row[0]); logPrintf(logfile, "Sending Room %s with ID %d and MOTD %s\n", info->name, info->id, info->motd); msg.length = sizeof (msg_rooms_t); msg.room = 0; logPrintf(logfile, "Sending message?\n"); writecode = server_socket.write(&msg); logPrintf(logfile, "Message sent! :D\n"); if (writecode < 0) { dbgPrintf(LIGHTRED, "Write error... %d client %d " "deleted\n", writecode, id); return; } } mysql_free_result(res); } } void MySQL_CheckVersion(UINT32 id, UINT32 type, const char *ip, UINT32 modid, const char *modversion) { msg_t msg; int writecode; (void)ip; MySQL_Conn(false); msg.id = id; msg.type = type; char versionquery[1000]; sprintf(versionquery, "SELECT * FROM `ms_versions` WHERE `mod_id` = '%d' AND `mod_version` > %s LIMIT 1",modid, modversion); logPrintf(mysqlfile, "Executing MySQL Query: %s\n", versionquery); if(mysql_query(conn, versionquery)) { logPrintf(errorfile, "MYSQL ERROR: %s\n", mysql_error(conn)); MySQL_Conn(true); } else { res = mysql_store_result(conn); if(mysql_num_rows(res) < 1) { logPrintf(logfile, "Buffer to NULL\n"); strcpy(msg.buffer,"NULL"); } else { row = mysql_fetch_row(res); logPrintf(logfile, "Version found: %s || Codebase: %s || Version: %s || Version String: %s || Mod ID: %s\n", row[4], row[3], row[1], row[2], row[0]); strcpy(msg.buffer,row[2]); } msg.length = sizeof msg.buffer; msg.room = 0; logPrintf(logfile, "Sending message?\n"); writecode = server_socket.write(&msg); logPrintf(logfile, "Message sent! :D\n"); if (writecode < 0) { dbgPrintf(LIGHTRED, "Write error... %d client %d " "deleted\n", writecode, id); return; } mysql_free_result(res); } } void MySQL_ListServServers(UINT32 id, UINT32 type, const char *ip) { msg_t msg; int writecode; static char str[1024]; //char banqueryp1[500] = "SELECT reason,name,FROM_UNIXTIME(endtime) FROM ms_bans WHERE INET_ATON('%s') BETWEEN `ipstart` AND `ipend` AND `endtime` < %ld LIMIT 1"; //char banquery[500]; //time_t current_time = time (NULL); char servquery[1000] = "SELECT ip, port, name, version, permanent FROM ( SELECT * FROM `ms_servers` WHERE `upnow` = '1' OR `permanent` = '1' ORDER BY `sid` ASC) as ms_servers ORDER BY `sticky` DESC"; MySQL_Conn(false); if(!MySQL_CheckBan(ip,0,false,0)) { msg.id = id; msg.type = type; msg.room = 0; logPrintf(mysqlfile, "Executing MySQL Query: %s\n", servquery); if(mysql_query(conn, servquery)) { logPrintf(errorfile, "MYSQL ERROR: %s\n", mysql_error(conn)); MySQL_Conn(true); } else { res = mysql_store_result(conn); logPrintf(logfile, "Found %d servers...\n", mysql_num_rows(res)); while ((row = mysql_fetch_row(res)) != NULL) { if(strcmp(row[4], "0") == 1) snprintf(str, sizeof str, "IP\t\t: %s\nPort\t\t: %s\nHostname\t: %s\nVersion\t\t: %s\nPermanent\t: %s\n", row[0], row[1], row[2], row[3], "Yes"); else snprintf(str, sizeof str, "IP\t\t: %s\nPort\t\t: %s\nHostname\t: %s\nVersion\t\t: %s\nPermanent\t: %s\n", row[0], row[1], row[2], row[3], "No"); msg.length = (INT32)(strlen(str)+1); // send also the '\0' strcpy(msg.buffer, str); dbgPrintf(CYAN, "Writing: (%d)\n%s\n", msg.length, msg.buffer); writecode = server_socket.write(&msg); if (writecode < 0) { dbgPrintf(LIGHTRED, "Write error... %d client %d deleted\n", writecode, id); return; } } mysql_free_result(res); } } else { logPrintf(logfile, "IP %s is banned so do nothing! Let them find out for themselves.\n", ip); } } void MySQL_RemoveServer(char *ip, char *port, char *name, char *version) { char escapedName[255]; char updatequery[5000]; char updatequeryp1[5000] = "UPDATE `ms_servers` SET upnow = '0' WHERE `ip` = '%s' AND `permanent` = '0'"; MySQL_Conn(false); mysql_real_escape_string(conn, escapedName, name, (unsigned long)strlen(name)); sprintf(updatequery, updatequeryp1, ip); logPrintf(mysqlfile, "Executing MySQL Query: %s\n", updatequery); if(mysql_query(conn, updatequery)) { logPrintf(errorfile, "MYSQL ERROR: %s\n", mysql_error(conn)); MySQL_Conn(true); } else { logPrintf(logfile, "Server: %s:%s || Name: %s || Version: %s removed successfully.\n", ip, port, name, version); } } /* LIVE FUNCTIONS */ void LIVE_AuthUser(UINT32 id, char *buffer) { msg_live_auth_t *auth; char escapedName[255]; char saltedPassword[62]; char hashedPassword[34]; char namequery[1000]; char namequeryp1[1000] = "SELECT username,userid,salt,password FROM `user` WHERE `username` = '%s' LIMIT 1"; char userquery[1000]; char userqueryp1[1000] = "SELECT userid,username,live_authkey,live_publickey FROM `user` WHERE `userid` = '%s' LIMIT 1"; msg_t msg2; char ip[32]; int writecode; msg2.type = LIVE_INVALID_USER; auth = (msg_live_auth_t *)buffer; logPrintf(logfile, "Got User %s Pass %s\n", auth->username, auth->password); // retrieve the true ip of the server strcpy(ip, server_socket.getClientIP(id)); MySQL_Conn(false); msg2.id = id; logPrintf(logfile, "Check their ban status first... (ID %d)\n",id); if(MySQL_CheckBan(ip,0,false,0)) return; mysql_real_escape_string(conn, escapedName, auth->username, (unsigned long)strlen(auth->username)); sprintf(namequery, namequeryp1, escapedName); logPrintf(mysqlfile, "Executing MySQL Query: %s\n", namequery); if(mysql_query(conn, namequery)) { logPrintf(errorfile, "MYSQL ERROR: %s\n", mysql_error(conn)); MySQL_Conn(true); } else { res = mysql_store_result(conn); if(mysql_num_rows(res) < 1) { logPrintf(logfile, "Invalid user: %s\n", auth->username); msg2.type = LIVE_INVALID_USER; } else { row = mysql_fetch_row(res); sprintf(saltedPassword, "%s%s", auth->password, row[2]); logPrintf(logfile, "Pre-hash: %s (Salt is %s)\n", saltedPassword, row[2]); sprintf(hashedPassword, md5(saltedPassword).c_str()); logPrintf(logfile, "Got Hashed Password: %s\n", hashedPassword); if(strcmp(hashedPassword, row[3]) != 0) { msg2.type = LIVE_INVALID_USER; logPrintf(logfile, "INVALID USER!\n"); } else { msg2.type = LIVE_SEND_USER; sprintf(userquery, userqueryp1, row[1]); mysql_free_result(res); logPrintf(mysqlfile, "Executing MySQL Query: %s\n", userquery); if(mysql_query(conn, userquery)) { logPrintf(errorfile, "MYSQL ERROR: %s\n", mysql_error(conn)); MySQL_Conn(true); } else { res = mysql_store_result(conn); if(mysql_num_rows(res) < 1) { logPrintf(errorfile, "User Information Error, invalid USER ID!\n"); msg2.type = LIVE_INVALID_USER; } else { row = mysql_fetch_row(res); msg_live_user_t *user = (msg_live_user_t *) msg2.buffer; user->header[0] = '\0'; // nothing interresting in it (for now) user->uid = atoi(row[0]); strcpy(user->username, row[1]); logPrintf(logfile, "Found user: %s, id %s\n", row[1], row[0]); logPrintf(logfile, "Sending User %s with ID %d\n", user->username, user->uid); msg2.length = sizeof (msg_live_user_t); } } } } } msg2.length = sizeof msg2.buffer; msg2.room = 0; logPrintf(logfile, "Sending message?\n"); writecode = server_socket.write(&msg2); logPrintf(logfile, "Message sent! :D\n"); if (writecode < 0) { dbgPrintf(LIGHTRED, "Write error... %d client %d " "deleted\n", writecode, id); return; } mysql_free_result(res); } /* ** sendServersInformations() */ static void sendServersInformations(UINT32 id, UINT32 room) { msg_t msg; int writecode; char ip[16]; strcpy(ip, server_socket.getClientIP(id)); (void)room; logPrintf(logfile, "Sending servers informations\n"); msg.id = id; msg.type = SEND_SERVER_MSG; msg.room = 0; MySQL_ListServServers(id, SEND_SERVER_MSG, ip); // Awesome new MySQL Code! msg.length = 0; //dbgPrintf(CYAN, "Writing: (%d) %s\n", msg.length, ""); writecode = server_socket.write(&msg); if (writecode < 0) { dbgPrintf(LIGHTRED, "Write error... %d client %d deleted\n", writecode, id); } } /* ** sendShortServersInformations() */ static void sendShortServersInformations(UINT32 id, UINT32 room) { msg_t msg; int writecode; char ip[16]; strcpy(ip, server_socket.getClientIP(id)); logPrintf(logfile, "Sending short servers informations\n"); msg.id = id; msg.type = SEND_SHORT_SERVER_MSG; MySQL_ListServers(id, SEND_SHORT_SERVER_MSG, ip, room); // New code that's full of win! logPrintf(logfile, "Packet Room: %d\n", room); msg.length = 0; writecode = server_socket.write(&msg); if (writecode < 0) { dbgPrintf(LIGHTRED, "Write error... %d client %d deleted\n", writecode, id); } } /* ** sendRoomInformations() */ static void sendRoomInformations(UINT32 id, UINT32 room, bool type) { msg_t msg; int writecode; char ip[16]; strcpy(ip, server_socket.getClientIP(id)); (void)room; logPrintf(logfile, "Sending room information\n"); msg.id = id; msg.type = SEND_ROOMS_MSG; msg.room = 0; MySQL_ListRooms(id, SEND_ROOMS_MSG, ip, type); // New code that's full of win! msg.length = 0; writecode = server_socket.write(&msg); if (writecode < 0) { dbgPrintf(LIGHTRED, "Write error... %d client %d deleted\n", writecode, id); } } /* ** sendVersionInformations() */ static void sendVersionInformations(UINT32 id, UINT32 modid, char *modversion) { msg_t msg; int writecode; char ip[16]; strcpy(ip, server_socket.getClientIP(id)); logPrintf(logfile, "Sending version information\n"); msg.id = id; msg.type = SEND_VERSION_MSG; msg.room = 0; MySQL_CheckVersion(id, SEND_VERSION_MSG, ip, modid, modversion); // New code that's full of win! msg.length = sizeof msg.buffer; writecode = server_socket.write(&msg); if (writecode < 0) { dbgPrintf(LIGHTRED, "Write error... %d client %d deleted\n", writecode, id); } } /* ** addServer() */ static void addServer(int id, char *buffer, bool firstadd) { msg_server_t *info; char oldversion = 0; //TODO: Be sure there is no flood from a given IP: // If a host need more than 2 servers, then it should be registrated // manually info = (msg_server_t *)buffer; // I want to be sure the informations are correct, of course! info->port[sizeof (info->port)-1] = '\0'; info->name[sizeof (info->name)-1] = '\0'; info->version[sizeof (info->version)-1] = '\0'; // retrieve the true ip of the server strcpy(info->ip, server_socket.getClientIP(id)); //strcpy(info->port, server_socket.getClientPort(id)); if (info->version[0] == '1' && info->version[1] == '.' && info->version[2] == '0' && info->version[3] == '9' && info->version[4] == '.') { if ((info->version[5] == '2') || (info->version[5] == '3')) { oldversion = 1; } } if (info->version[0] == '1' && info->version[1] == '.' && info->version[2] == '6' && info->version[3] == '9' && info->version[4] == '.' && info->version[5] == '6') { oldversion = 1; } if (!oldversion) { MySQL_AddServer(info->ip, info->port, info->name, info->version, info->room, firstadd, info->key); } else { logPrintf(logfile, "Not adding the temporary server: %s %s %s %s\n", info->ip, info->port, info->name, info->version); } } /* ** removeServer() */ static void removeServer(int id, char *buffer) { msg_server_t *info; info = (msg_server_t *)buffer; // I want to be sure the informations are correct, of course! info->port[sizeof (info->port)-1] = '\0'; info->name[sizeof (info->name)-1] = '\0'; info->version[sizeof (info->version)-1] = '\0'; // retrieve the true ip of the server strcpy(info->ip, server_socket.getClientIP(id)); logPrintf(logfile, "Removing the temporary server: %s %s %s %s\n", info->ip, info->port, info->name, info->version); MySQL_RemoveServer(info->ip, info->port, info->name, info->version); // New and win. } /* ** analyseUDP() */ static int analyseUDP(size_t size, const char *buffer) { // this would be the part of reading the PT_SERVERINFO packet, // but i'm not about to backport that sloppy code (void)size; (void)buffer; return INVALID_MSG; } /* ** UDPMessage() */ static int UDPMessage(size_t size, const char *buffer) { if (size == 4) { return 0; } else if (size == sizeof(ms_holepunch_packet_t)) { return 0; } else if (size > 58) { dbgPrintf(LIGHTGREEN, "Got a UDP %d byte long message\n", size); return analyseUDP(size, buffer); } else return INVALID_MSG; } /* ** analyseMessage() */ static int analyseMessage(msg_t *msg) { switch (msg->type) { case UDP_RECV_MSG: return UDPMessage(msg->length, msg->buffer); case ACCEPT_MSG: break; case ADD_SERVER_MSG: addServer(msg->id, msg->buffer, true); break; case PING_SERVER_MSG: addServer(msg->id, msg->buffer, false); break; case REMOVE_SERVER_MSG: removeServer(msg->id, msg->buffer); break; case GET_SERVER_MSG: sendServersInformations(msg->id, msg->room); break; case GET_SHORT_SERVER_MSG: sendShortServersInformations(msg->id, msg->room); break; case GET_ROOMS_MSG: sendRoomInformations(msg->id, msg->room, 0); break; case GET_ROOMS_HOST_MSG: sendRoomInformations(msg->id, msg->room, 1); break; case GET_VERSION_MSG: sendVersionInformations(msg->id, msg->room, msg->buffer); break; case LIVE_AUTH_USER: LIVE_AuthUser(msg->id, msg->buffer); break; default: return INVALID_MSG; } return 0; } /* ** main() */ int main(int argc, char *argv[]) { msg_t msg; #ifdef __unix__ pid_t pid; char pidstr[12]; #endif if (argc <= 1) { fprintf(stderr, "usage: %s port\n", argv[0]); exit(1); } if (server_socket.listen(argv[1]) < 0) { fprintf(stderr, "Error while initializing the server\n"); exit(2); } logfile = openFile("server.log"); errorfile = openFile("error.log"); mysqlfile = openFile("mysql.log"); sockfile = openFile("sockets.log"); MySQL_Conn(false); #if !defined (DEBUG) && defined (__unix__) pid = fork(); switch (pid) { case 0: break; // child case -1: printf("Error while launching the server in background\n"); return -1; default: pidfile = fopen("msd.pid", "w+"); sprintf(pidstr, "%d", pid); fputs(pidstr, pidfile); fclose(pidfile); return 0; // parent: keep child in background } #endif srand((unsigned)time(NULL)); // Alam: GUIDs for (;;) { memset(&msg, 0, sizeof (msg)); // remove previous message if (!server_socket.read(&msg)) { // valid message: header message seems ok analyseMessage(&msg); //servers_list.show(); // for debug purpose } } #ifndef _MSC_VER /* NOTREACHED */ return 0; #endif }