From 6472d510d26d1b9fb2f30be2c2da82d45d84d509 Mon Sep 17 00:00:00 2001 From: Rafael Barreto Date: Mon, 3 May 2010 01:38:26 +0000 Subject: [PATCH] Central Moderation git-svn-id: svn://svn.code.sf.net/p/actiongame/code/trunk/ac@4800 e016b1c5-ed68-44aa-a2f7-31cac88cffde --- source/src/Makefile | 6 +- source/src/clientgame.cpp | 3 + source/src/cmodserver.cpp | 289 ++++++++++++++++++++++++++++++++++++++ source/src/cmodserver.h | 53 +++++++ source/src/server.cpp | 8 +- source/src/serverms.cpp | 20 ++- 6 files changed, 369 insertions(+), 10 deletions(-) create mode 100755 source/src/cmodserver.cpp create mode 100755 source/src/cmodserver.h diff --git a/source/src/Makefile b/source/src/Makefile index 96aba3cd..925c08ae 100644 --- a/source/src/Makefile +++ b/source/src/Makefile @@ -21,8 +21,8 @@ CLIENT_INCLUDES= $(INCLUDES) -I../include CLIENT_LIBS= -mwindows -L../lib -lSDL -lSDL_image -lSDL_ttf -lzdll -lopengl32 -lenet -lOpenAL32 -llibvorbisfile -ljpeg -llibintl -lws2_32 -lwinmm else override CXXFLAGS+= -rdynamic -CLIENT_INCLUDES= $(INCLUDES) -I/usr/X11R6/include `sdl-config --cflags` -idirafter ../include -CLIENT_LIBS= -L../enet -lenet -L/usr/X11R6/lib `sdl-config --libs` -lSDL_image -lSDL_ttf -lz -lGL -lopenal -lvorbisfile -ljpeg +CLIENT_INCLUDES= $(INCLUDES) -I/usr/include `sdl-config --cflags` -idirafter ../include +CLIENT_LIBS= -L../enet -lenet -L/usr/lib64 `sdl-config --libs` -lSDL_image -lSDL_ttf -lz -lGL -lopenal -lvorbisfile -ljpeg endif CLIENT_OBJS= \ @@ -30,6 +30,7 @@ CLIENT_OBJS= \ client.o \ clientgame.o \ clients2c.o \ + cmodserver.o \ command.o \ console.o \ docs.o \ @@ -93,6 +94,7 @@ SERVER_LIBS= -L../enet -lenet -lz endif SERVER_OBJS= \ + cmodserver.o \ log-standalone.o \ protocol-standalone.o \ server-standalone.o \ diff --git a/source/src/clientgame.cpp b/source/src/clientgame.cpp index dd57fa6d..c3b4dcee 100644 --- a/source/src/clientgame.cpp +++ b/source/src/clientgame.cpp @@ -41,12 +41,15 @@ void setskin(playerent *pl, int skin, int team) pl->setskin(team, skin); } +extern char *global_name; + bool duplicatename(playerent *d, char *name = NULL) { if(!name) name = d->name; if(d!=player1 && !strcmp(name, player1->name)) return true; if(!strcmp(name, "you")) return true; loopv(players) if(players[i] && d!=players[i] && !strcmp(name, players[i]->name)) return true; + global_name = player1->name; // this certainly is not the best place to put this return false; } diff --git a/source/src/cmodserver.cpp b/source/src/cmodserver.cpp new file mode 100755 index 00000000..ad6f2452 --- /dev/null +++ b/source/src/cmodserver.cpp @@ -0,0 +1,289 @@ +#include "cube.h" +#include "cmodserver.h" + +// moderator = client + operator, admin = server + operator, developer = client + server + operator +string ut[] = { "null", "client", "server", "both", "operator", "moderator", "admin", "developer" }; + +string mt[] = {"register", "getlist", "insert_bl", "remove_bl", "insert_wl", "remove_wl", "report", "can_trust", "show_us", "show_bl", "show_wl"}; + +string rt[] = {"speedhack", "aimbot", "weaponhack", "wallhack", "maphack", "opk", "teleport", "serverhack", "bug_exploit", "other"}; + +string rm[] = {"Success", "Failed", "Ignoring", "Expired", "Something weird happened", "For sure!", "Yes", "No", "This guy is blacklisted!", "Whitelisted"}; + +inline uint8_t umin8 (uint8_t a, uint8_t b){ + if (a < b) return a; + return b; +} + +/* the exact type would be int33_t */ +int64_t compare_ips (uint8_t *a, uint8_t *b) // little endian ips +{ + uint32_t ip1 = *(uint32_t *)a; + uint32_t ip2 = *(uint32_t *)b; + int r = 32 - umin8(a[4],b[4]); + return ((int64_t)(ip1 >> r) - (int64_t)(ip2 >> r)); +} + +void init_msg_structs ( char *message, s_vmsg *vmsg ) { + vmsg->mt = (uint16_t *) &message[0]; + vmsg->le = (uint8_t *) &message[0]; + vmsg->be = (uint8_t *) &message[1]; + vmsg->n = (uint32_t *) &message[2]; + vmsg->port = (uint16_t *) &message[2]; + vmsg->v = (uint8_t *) &message[2]; + /* 3 field messages: get_bl, remove_bl/wl */ + vmsg->t = (uint8_t *) &message[6]; + vmsg->k = (uint16_t *) &message[6]; + /* can trust */ + vmsg->ct = (uint8_t *) &message[6]; + /* 5/6 field messages: register, insert_wl */ + vmsg->name = (char *) &message[7]; + vmsg->version = (uint16_t *) &message[7+NAMELEN]; + /* 7 field messages: insert bl */ + vmsg->reason = (uint8_t *) &message[7+NAMELEN]; + vmsg->f = (uint8_t *) &message[8+NAMELEN]; // this is a vector of 5 elements + vmsg->exp = (uint8_t *) &message[13+NAMELEN]; +} + +int msg_size (int v) +{ + switch (v) { + case MT_REGISTER: // mt n t name v + return 10+NAMELEN; + break; + case MT_GETLIST: // mt n t + return 7; + break; + case MT_CANTRUST: // mt n t ct + return 10; + break; + case MT_INSERTBL: // mt n ip name reason exp t + return 14+NAMELEN; + break; + case MT_REPORT: // mt n ip name reason t + return 13+NAMELEN; + break; + case MT_REMOVEWL: + case MT_REMOVEBL: // mt n k + return 8; + break; + case MT_INSERTWL: // mt n ip name t + return 13+NAMELEN; // it is sending a null 8 bits (reason) + break; + case MT_SHOWUS: + case MT_SHOWBL: + case MT_SHOWWL: + return 7; + break; + default: + return MAXMSGSIZE; + } +} + +void invert_end32 (uint8_t *v) +{ + v[0] = v[0] ^ v[3]; + v[3] = v[0] ^ v[3]; + v[0] = v[0] ^ v[3]; + v[1] = v[1] ^ v[2]; + v[2] = v[1] ^ v[2]; + v[1] = v[1] ^ v[2]; +} + +void invert_end16 (uint8_t *v) +{ + v[0] = v[0] ^ v[1]; + v[1] = v[0] ^ v[1]; + v[0] = v[0] ^ v[1]; +} + +void fix_end (int mt, s_vmsg *vmsg) +{ + switch ( mt ) { + case MT_REGISTER: + invert_end16((uint8_t *)vmsg->version); + break; + case MT_CANTRUST: + invert_end16((uint8_t *)vmsg->ct); + break; + case MT_REMOVEBL: + case MT_REMOVEWL: + invert_end16((uint8_t *)vmsg->k); + break; + case MT_INSERTBL: + case MT_REPORT: + invert_end16((uint8_t *)vmsg->reason); + case MT_INSERTWL: + invert_end32((uint8_t *)vmsg->f); + break; + default: + break; + } +} + +int convert_ip ( char *string, uint8_t *f ) +{ + f[0] = f[1] = f[2] = f[3] = 0; + f[4] = 32; + + if ( strchr(string,'/') == NULL ) { + if ( sscanf (string,"%hhu.%hhu.%hhu.%hhu",&f[3],&f[2],&f[1],&f[0]) < 4 ) return 1; + } else { + if ( sscanf (string,"%hhu.%hhu.%hhu.%hhu/%hhu",&f[3],&f[2],&f[1],&f[0],&f[4]) < 5 || f[4] > 32 ) return 1; + } + return 0; +} + +int find_reason (char *reason) +{ + int i; + for ( i = 0; i < RT_LAST; i++ ) { + char *rs = reason; + const char *r = rt[i]; + while ( *rs != '\0' || *r != '\0' ) { + if ( *rs != *r ) break; + rs++; // VEJA AQUI + r++; + if ( *rs == '\0' && *rs == '\0' ) return i; + } + } + return -1; +} + +int get_ct (char *type) +{ + if ( !strncmp(type,"client",6) ) { + return UT_CLIENT; + } else if ( !strncmp(type,"server",6) ) { + return UT_SERVER; + } else if ( !strncmp(type,"both",4) ) { + return UT_BOTH; + } else if ( !strncmp(type,"op",2) ) { + return UT_OP; + } else return UT_NULL; +} + +int include_endian(s_vmsg *vmsg){ + if ( *vmsg->mt == *vmsg->le ) { + *vmsg->be = 128; + return 0; + } else if ( *vmsg->mt == *vmsg->be ) { + *vmsg->le = 128; + return 1; + } else { + return -1; + } +} + +uint id_number = 12345; // this is a test +ENetAddress cmodaddress = { ENET_HOST_ANY, AC_CMOD_PORT }; //CMOD + +int communicate(ENetAddress *addr, const char *host, ENetBuffer *buf) { + + if (addr->host == ENET_HOST_ANY && enet_address_set_host(addr, host)<0 ) { + addr->host = ENET_HOST_ANY; + printf(" * Error: Host %s cannot be resolved!\n",host); + return RM_FAIL; + } + + int sockfd = enet_socket_create(ENET_SOCKET_TYPE_STREAM); + + if (sockfd == ENET_SOCKET_NULL) { + printf(" * Error in creating socket.\n"); + enet_socket_destroy(sockfd); + return RM_FAIL; + } + + int n, m = 0; + while ( (n = enet_socket_connect(sockfd, addr)) < 0 && m < 10 ) m++; + if ( n < 0 ) { + printf(" * Error in connecting.\n"); + enet_socket_destroy(sockfd); + return RM_FAIL; + } + + n = enet_socket_send(sockfd, addr, buf, 1); + if (n < 0) { + printf(" * Error on write.\n"); + enet_socket_destroy(sockfd); + return RM_FAIL; + } + + bzero(buf->data, 1); + buf->dataLength = 1; + + n = enet_socket_receive(sockfd, addr, buf, 1); + + if ( n == 0 ) { + printf(" * Error: No response from %s\n",host); + enet_socket_destroy(sockfd); + return RM_FAIL; + } else if ( n < 0 ) { + printf(" * Error in reading from socket\n"); + enet_socket_destroy(sockfd); + return RM_FAIL; + } + + union { + int8_t d; + char c[2]; + } reply; + + reply.d = RM_FAIL; + + strncpy(reply.c,(char *)buf->data,1); + + if ( reply.d >= 0 && reply.d < RM_LAST ) { + printf(" ** Communication %s\n",rm[reply.d]); + enet_socket_destroy(sockfd); + return reply.d; + } + else printf(" * Error: Server sent an unexpected reply. Report this incident.\n"); + + enet_socket_destroy(sockfd); + return RM_FAIL; +} + +extern char *global_name; + +int cmodregister(int type) +{ + ENetBuffer buf; + s_vmsg vmsg; + char message[MAXMSGSIZE]; + init_msg_structs (message, &vmsg); + buf.data = message; + + bzero(message,msg_size(MT_REGISTER)); + buf.dataLength = msg_size(MT_REGISTER); + + *vmsg.mt = MT_REGISTER; + *vmsg.n = id_number; + + if ( include_endian(&vmsg) < 0 ) { + printf(" * Weird endianess. Please, report this incident.\n"); + return RM_FAIL; + } + + strncpy(vmsg.name,global_name,NAMELEN-1); + *vmsg.t = type; + *vmsg.version = AC_VERSION; + + return communicate(&cmodaddress, AC_CMOD_URI, &buf); +} + +int lastcmodreg = 0; +int cmodregistered = RM_DONE; + +int updatecmod(int millis, int type) +{ + if ( !lastcmodreg || lastcmodreg + 1000 * 60 * 20 + 3333 < millis ) { + cmodregistered = cmodregister(type); + if ( cmodregistered != RM_DONE ) { + //treat_failure(can_retrieve); + printf("You cannot register in the masterserver\n"); + return 0; + } else lastcmodreg = millis; + } + return 1; +} diff --git a/source/src/cmodserver.h b/source/src/cmodserver.h new file mode 100755 index 00000000..7efc1a8f --- /dev/null +++ b/source/src/cmodserver.h @@ -0,0 +1,53 @@ +/* http://www.linuxhowtos.org/C_C++/socket.htm */ +#include +#include +#include +#include +#include +#include +#include +#include +#include // sleep +#include + +#define MAXCOL 300 +#define IPLEN 21 +#define NAMELEN 21 +#define MAXBUF 1024 +#define MAXBLTIME 30 // days +#define MAXMSGSIZE 25+NAMELEN + +#define AC_CMOD_URI "ac.if.usp.br" // this is a test +#define AC_CMOD_PORT 28763 // this is a test + +enum +{UT_NULL, UT_CLIENT, UT_SERVER, UT_BOTH, UT_OP, UT_LAST}; + +enum +{MT_REGISTER, MT_GETLIST, MT_INSERTBL, MT_REMOVEBL, MT_INSERTWL, MT_REMOVEWL, MT_REPORT, MT_CANTRUST, MT_SHOWUS, MT_SHOWBL, MT_SHOWWL, MT_LAST}; + +enum +{RT_SPEED, RT_AIMBOT, RT_WEAPON, RT_WALL, RT_MAP, RT_OPK, RT_TELEPORT, RT_SERVER, RT_BUGEXP, RT_OTHER, RT_LAST}; + +enum +{RM_DONE, RM_FAIL, RM_IGN, RM_EXPIRED, RM_TRAGEDY, RM_FORSURE, RM_YES, RM_NO, RM_BLED, RM_WLED, RM_LAST}; + + +typedef struct { + uint16_t *mt; // the message type + uint8_t *le; // endianess + uint8_t *be; // endianess + uint32_t *n; // user id (client side) + uint16_t *port; + uint8_t *v; // endian verifier + uint8_t *t; // ut for get_bl + uint16_t *k; // index for remove_bl/wl + uint8_t *ct; // can trust ip + char *name; + uint16_t *version; + uint8_t *f; // ip fields + uint8_t *reason; + uint8_t *exp; // expiration in days +} s_vmsg; + + diff --git a/source/src/server.cpp b/source/src/server.cpp index 33c86918..e38b77ac 100644 --- a/source/src/server.cpp +++ b/source/src/server.cpp @@ -1,6 +1,5 @@ // server.cpp: little more than enhanced multicaster // runs dedicated or as client coroutine -// my first try // Brahma #include "cube.h" @@ -50,6 +49,8 @@ char *maplayout = NULL; int maplayout_factor; servermapbuffer mapbuffer; +// cmod +char *global_name; bool valid_client(int cn) { @@ -3484,6 +3485,8 @@ void fatal(const char *s, ...) exit(EXIT_FAILURE); } +string server_name = "unarmed server"; + int main(int argc, char **argv) { #ifdef WIN32 @@ -3517,6 +3520,9 @@ int main(int argc, char **argv) } } + if ( strlen(scl.servdesc_full) ) global_name = scl.servdesc_full; + else global_name = server_name; + if(service && !svcctrl) { #ifdef WIN32 diff --git a/source/src/serverms.cpp b/source/src/serverms.cpp index ada93054..395ee2c3 100644 --- a/source/src/serverms.cpp +++ b/source/src/serverms.cpp @@ -1,6 +1,7 @@ // all server side masterserver and pinging functionality #include "cube.h" +#include "cmodserver.h" #ifdef STANDALONE bool resolverwait(const char *name, ENetAddress *address) @@ -78,17 +79,21 @@ string masterpath; uchar masterrep[MAXTRANS]; ENetBuffer masterb; +extern int updatecmod(int millis, int type); + // send alive signal to masterserver every hour of uptime void updatemasterserver(int millis, const ENetAddress &localaddr) { - if(!millis || millis/(60*60*1000)!=lastupdatemaster) + if( !millis || millis/(60*60*1000)!=lastupdatemaster ) { - defformatstring(path)("%sregister.do?action=add&port=%d", masterpath, localaddr.port); - defformatstring(agent)("AssaultCube Server %d", AC_VERSION); - mssock = httpgetsend(masterserver, masterbase, path, "assaultcubeserver", agent, &msaddress); - masterrep[0] = 0; - masterb.data = masterrep; - masterb.dataLength = MAXTRANS-1; + if ( updatecmod(millis, UT_SERVER) ){ + defformatstring(path)("%sregister.do?action=add&port=%d", masterpath, localaddr.port); + defformatstring(agent)("AssaultCube Server %d", AC_VERSION); + mssock = httpgetsend(masterserver, masterbase, path, "assaultcubeserver", agent, &msaddress); + masterrep[0] = 0; + masterb.data = masterrep; + masterb.dataLength = MAXTRANS-1; + } lastupdatemaster = millis/(60*60*1000); } } @@ -294,6 +299,7 @@ void serverms(int mode, int numplayers, int minremain, char *smapname, int milli } } +// this function should be made better, because it is used just ONCE (no need of so much parameters) void servermsinit(const char *master, const char *ip, int infoport, bool listen) { const char *mid = strstr(master, "/");