project_files/frontlib/net/netconn_send.c
changeset 7271 5608ac657362
child 7275 15f722e0b96f
equal deleted inserted replaced
7269:5b0aeef8ba2a 7271:5608ac657362
       
     1 #include "netconn_internal.h"
       
     2 
       
     3 #include "../util/logging.h"
       
     4 #include "../util/util.h"
       
     5 #include "../util/buffer.h"
       
     6 #include "../md5/md5.h"
       
     7 #include "../base64/base64.h"
       
     8 
       
     9 #include <stdlib.h>
       
    10 #include <string.h>
       
    11 #include <zlib.h>
       
    12 
       
    13 // TODO state changes
       
    14 
       
    15 // cmdname is always given as literal from functions in this file, so it is never null.
       
    16 static int sendVoid(flib_netconn *conn, const char *cmdname) {
       
    17 	if(!conn) {
       
    18 		flib_log_e("null parameter trying to send %s command.", cmdname);
       
    19 		return -1;
       
    20 	}
       
    21 	return flib_netbase_sendf(conn->netBase, "%s\n\n", cmdname);
       
    22 }
       
    23 
       
    24 static int sendStr(flib_netconn *conn, const char *cmdname, const char *str) {
       
    25 	if(!conn || !str) {
       
    26 		flib_log_e("null parameter trying to send %s command.", cmdname);
       
    27 		return -1;
       
    28 	}
       
    29 	return flib_netbase_sendf(conn->netBase, "%s\n%s\n\n", cmdname, str);
       
    30 }
       
    31 
       
    32 static int sendInt(flib_netconn *conn, const char *cmdname, int param) {
       
    33 	if(!conn) {
       
    34 		flib_log_e("null parameter trying to send %s command.", cmdname);
       
    35 		return -1;
       
    36 	}
       
    37 	return flib_netbase_sendf(conn->netBase, "%s\n%i\n\n", cmdname, param);
       
    38 }
       
    39 
       
    40 int flib_netconn_send_quit(flib_netconn *conn, const char *quitmsg) {
       
    41 	return sendStr(conn, "QUIT", quitmsg ? quitmsg : "User quit");
       
    42 }
       
    43 
       
    44 int flib_netconn_send_chat(flib_netconn *conn, const char *chat) {
       
    45 	return sendStr(conn, "CHAT", chat);
       
    46 }
       
    47 
       
    48 int flib_netconn_send_teamchat(flib_netconn *conn, const char *chat) {
       
    49 	return sendStr(conn, "TEAMCHAT", chat);
       
    50 }
       
    51 
       
    52 int flib_netconn_send_nick(flib_netconn *conn, const char *nick) {
       
    53 	int result = -1;
       
    54 	if(!conn || !nick) {
       
    55 		flib_log_e("null parameter in flib_netconn_send_nick");
       
    56 	} else {
       
    57 		char *tmpName = flib_strdupnull(nick);
       
    58 		if(tmpName) {
       
    59 			if(!flib_netbase_sendf(conn->netBase, "%s\n%s\n\n", "NICK", nick)) {
       
    60 				free(conn->playerName);
       
    61 				conn->playerName = tmpName;
       
    62 				tmpName = NULL;
       
    63 				result = 0;
       
    64 			}
       
    65 		}
       
    66 		free(tmpName);
       
    67 	}
       
    68 	return result;
       
    69 }
       
    70 
       
    71 int flib_netconn_send_password(flib_netconn *conn, const char *latin1Passwd) {
       
    72 	int result = -1;
       
    73 	if(!conn || !latin1Passwd) {
       
    74 		flib_log_e("null parameter in flib_netconn_send_password");
       
    75 	} else {
       
    76 		md5_state_t md5state;
       
    77 		uint8_t md5bytes[16];
       
    78 		char md5hex[33];
       
    79 		md5_init(&md5state);
       
    80 		md5_append(&md5state, (unsigned char*)latin1Passwd, strlen(latin1Passwd));
       
    81 		md5_finish(&md5state, md5bytes);
       
    82 		for(int i=0;i<sizeof(md5bytes); i++) {
       
    83 			// Needs to be lowercase - server checks case sensitive
       
    84 			snprintf(md5hex+i*2, 3, "%02x", (unsigned)md5bytes[i]);
       
    85 		}
       
    86 		result = flib_netbase_sendf(conn->netBase, "%s\n%s\n\n", "PASSWORD", md5hex);
       
    87 	}
       
    88 	return result;
       
    89 }
       
    90 
       
    91 int flib_netconn_send_joinRoom(flib_netconn *conn, const char *room) {
       
    92 	return sendStr(conn, "JOIN_ROOM", room);
       
    93 }
       
    94 
       
    95 int flib_netconn_send_createRoom(flib_netconn *conn, const char *room) {
       
    96 	return sendStr(conn, "CREATE_ROOM", room);
       
    97 }
       
    98 
       
    99 int flib_netconn_send_renameRoom(flib_netconn *conn, const char *roomName) {
       
   100 	return sendStr(conn, "ROOM_NAME", roomName);
       
   101 }
       
   102 
       
   103 int flib_netconn_send_leaveRoom(flib_netconn *conn) {
       
   104 	return sendVoid(conn, "PART");
       
   105 }
       
   106 
       
   107 int flib_netconn_send_toggleReady(flib_netconn *conn) {
       
   108 	return sendVoid(conn, "TOGGLE_READY");
       
   109 }
       
   110 
       
   111 int flib_netconn_send_addTeam(flib_netconn *conn, const flib_team *team) {
       
   112 	int result = -1;
       
   113 	if(!conn || !team) {
       
   114 		flib_log_e("null parameter in flib_netconn_send_addTeam");
       
   115 	} else {
       
   116 		bool missingInfo = !team->name || !team->color || !team->grave || !team->fort || !team->voicepack || !team->flag;
       
   117 		for(int i=0; i<HEDGEHOGS_PER_TEAM; i++) {
       
   118 			missingInfo |= !team->hogs[i].name || !team->hogs[i].hat;
       
   119 		}
       
   120 		if(missingInfo) {
       
   121 			flib_log_e("Incomplete team definition for flib_netconn_send_addTeam");
       
   122 		} else {
       
   123 			flib_vector *vec = flib_vector_create();
       
   124 			if(vec) {
       
   125 				bool error = false;
       
   126 				error |= flib_vector_appendf(vec, "ADD_TEAM\n%s\n%lu\n%s\n%s\n%s\n%s\n%i\n", team->name, (unsigned long)team->color, team->grave, team->fort, team->voicepack, team->flag, team->hogs[0].difficulty);
       
   127 				for(int i=0; i<HEDGEHOGS_PER_TEAM; i++) {
       
   128 					error |= flib_vector_appendf(vec, "%s\n%s\n", team->hogs[i].name, team->hogs[i].hat);
       
   129 				}
       
   130 				error |= flib_vector_appendf(vec, "\n");
       
   131 				if(!error) {
       
   132 					result = flib_netbase_send_raw(conn->netBase, flib_vector_data(vec), flib_vector_size(vec));
       
   133 				}
       
   134 			}
       
   135 			flib_vector_destroy(vec);
       
   136 		}
       
   137 	}
       
   138 	return result;
       
   139 }
       
   140 
       
   141 int flib_netconn_send_removeTeam(flib_netconn *conn, const char *teamname) {
       
   142 	return sendStr(conn, "REMOVE_TEAM", teamname);
       
   143 }
       
   144 
       
   145 int flib_netconn_send_engineMessage(flib_netconn *conn, const uint8_t *message, size_t size) {
       
   146 	int result = -1;
       
   147 	if(!conn || (!message && size>0)) {
       
   148 		flib_log_e("null parameter in flib_netconn_send_engineMessage");
       
   149 	} else {
       
   150 		char *base64encout = NULL;
       
   151 		base64_encode_alloc((const char*)message, size, &base64encout);
       
   152 		if(base64encout) {
       
   153 			result = flib_netbase_sendf(conn->netBase, "EM\n%s\n\n", base64encout);
       
   154 		}
       
   155 		free(base64encout);
       
   156 	}
       
   157 	return result;
       
   158 }
       
   159 
       
   160 int flib_netconn_send_teamHogCount(flib_netconn *conn, const char *teamname, int hogcount) {
       
   161 	if(!conn || !teamname || hogcount<1 || hogcount>HEDGEHOGS_PER_TEAM) {
       
   162 		flib_log_e("invalid parameter in flib_netconn_send_teamHogCount");
       
   163 		return -1;
       
   164 	}
       
   165 	return flib_netbase_sendf(conn->netBase, "HH_NUM\n%s\n%i\n\n", teamname, hogcount);
       
   166 }
       
   167 
       
   168 int flib_netconn_send_teamColor(flib_netconn *conn, const char *teamname, uint32_t colorRGB) {
       
   169 	if(!conn || !teamname) {
       
   170 		flib_log_e("null parameter in flib_netconn_send_teamColor");
       
   171 		return -1;
       
   172 	}
       
   173 	return flib_netbase_sendf(conn->netBase, "TEAM_COLOR\n%s\n%lu\n\n", teamname, (unsigned long)colorRGB);
       
   174 }
       
   175 
       
   176 int flib_netconn_send_weaponset(flib_netconn *conn, const flib_weaponset *weaponset) {
       
   177 	if(!conn || !weaponset) {
       
   178 		flib_log_e("null parameter in flib_netconn_send_weaponset");
       
   179 		return -1;
       
   180 	}
       
   181 
       
   182 	char ammostring[WEAPONS_COUNT*4+1];
       
   183 	strcpy(ammostring, weaponset->loadout);
       
   184 	strcat(ammostring, weaponset->crateprob);
       
   185 	strcat(ammostring, weaponset->delay);
       
   186 	strcat(ammostring, weaponset->crateammo);
       
   187 	return flib_netbase_sendf(conn->netBase, "CFG\nAMMO\n%s\n%s\n\n", weaponset->name, ammostring);
       
   188 }
       
   189 
       
   190 int flib_netconn_send_map(flib_netconn *conn, const flib_map *map) {
       
   191 	if(!conn || !map) {
       
   192 		flib_log_e("null parameter in flib_netconn_send_map");
       
   193 		return -1;
       
   194 	}
       
   195 	bool error = false;
       
   196 
       
   197 	if(map->seed) {
       
   198 		error |= flib_netconn_send_mapSeed(conn, map->seed);
       
   199 	}
       
   200 	error |= flib_netconn_send_mapTemplate(conn, map->templateFilter);
       
   201 	if(map->theme) {
       
   202 		error |= flib_netconn_send_mapTheme(conn, map->theme);
       
   203 	}
       
   204 	error |= flib_netconn_send_mapGen(conn, map->mapgen);
       
   205 	error |= flib_netconn_send_mapMazeSize(conn, map->mazeSize);
       
   206 	if(map->name) {
       
   207 		error |= flib_netconn_send_mapName(conn, map->name);
       
   208 	}
       
   209 	if(map->drawData && map->drawDataSize>0) {
       
   210 		error |= flib_netconn_send_mapDrawdata(conn, map->drawData, map->drawDataSize);
       
   211 	}
       
   212 	return error;
       
   213 }
       
   214 
       
   215 int flib_netconn_send_mapName(flib_netconn *conn, const char *mapName) {
       
   216 	return sendStr(conn, "CFG\nMAP", mapName);
       
   217 }
       
   218 
       
   219 int flib_netconn_send_mapGen(flib_netconn *conn, int mapGen) {
       
   220 	return sendInt(conn, "CFG\nMAPGEN", mapGen);
       
   221 }
       
   222 
       
   223 int flib_netconn_send_mapTemplate(flib_netconn *conn, int templateFilter) {
       
   224 	return sendInt(conn, "CFG\nTEMPLATE", templateFilter);
       
   225 }
       
   226 
       
   227 int flib_netconn_send_mapMazeSize(flib_netconn *conn, int mazeSize) {
       
   228 	return sendInt(conn, "CFG\nMAZE_SIZE", mazeSize);
       
   229 }
       
   230 
       
   231 int flib_netconn_send_mapSeed(flib_netconn *conn, const char *seed) {
       
   232 	return sendStr(conn, "CFG\nSEED", seed);
       
   233 }
       
   234 
       
   235 int flib_netconn_send_mapTheme(flib_netconn *conn, const char *theme) {
       
   236 	return sendStr(conn, "CFG\nTHEME", theme);
       
   237 }
       
   238 
       
   239 int flib_netconn_send_mapDrawdata(flib_netconn *conn, const uint8_t *drawData, size_t size) {
       
   240 	int result = -1;
       
   241 	if(!conn || (!drawData && size>0) || size>SIZE_MAX/2) {
       
   242 		flib_log_e("invalid parameter in flib_netconn_send_map");
       
   243 	} else {
       
   244 		uLongf zippedSize = compressBound(size);
       
   245 		uint8_t *zipped = flib_malloc(zippedSize+4); // 4 extra bytes for header
       
   246 		if(zipped) {
       
   247 			// Create the QCompress size header (uint32 big endian)
       
   248 			zipped[0] = (size>>24) & 0xff;
       
   249 			zipped[1] = (size>>16) & 0xff;
       
   250 			zipped[2] = (size>>8) & 0xff;
       
   251 			zipped[3] = (size) & 0xff;
       
   252 
       
   253 			if(compress(zipped+4, &zippedSize, drawData, size) != Z_OK) {
       
   254 				flib_log_e("Error compressing drawn map data.");
       
   255 			} else {
       
   256 				char *base64encout = NULL;
       
   257 				base64_encode_alloc((const char*)zipped, zippedSize+4, &base64encout);
       
   258 				if(!base64encout) {
       
   259 					flib_log_e("Error base64-encoding drawn map data.");
       
   260 				} else {
       
   261 					result = flib_netbase_sendf(conn->netBase, "CFG\nDRAWNMAP\n%s\n\n", base64encout);
       
   262 				}
       
   263 				free(base64encout);
       
   264 			}
       
   265 		}
       
   266 		free(zipped);
       
   267 	}
       
   268 	return result;
       
   269 }
       
   270 
       
   271 int flib_netconn_send_script(flib_netconn *conn, const char *scriptName) {
       
   272 	return sendStr(conn, "CFG\nSCRIPT", scriptName);
       
   273 }
       
   274 
       
   275 int flib_netconn_send_scheme(flib_netconn *conn, const flib_cfg *scheme) {
       
   276 	int result = -1;
       
   277 	if(!conn || !scheme) {
       
   278 		flib_log_e("null parameter in flib_netconn_send_scheme");
       
   279 	} else {
       
   280 		flib_vector *vec = flib_vector_create();
       
   281 		if(vec) {
       
   282 			bool error = false;
       
   283 			error |= flib_vector_appendf(vec, "CFG\nSCHEME\n%s\n", scheme->name);
       
   284 			for(int i=0; i<scheme->meta->modCount; i++) {
       
   285 				error |= flib_vector_appendf(vec, "%s\n", scheme->mods[i] ? "true" : "false");
       
   286 			}
       
   287 			for(int i=0; i<scheme->meta->settingCount; i++) {
       
   288 				error |= flib_vector_appendf(vec, "%i\n", scheme->settings[i]);
       
   289 			}
       
   290 			error |= flib_vector_appendf(vec, "\n");
       
   291 			if(!error) {
       
   292 				result = flib_netbase_send_raw(conn->netBase, flib_vector_data(vec), flib_vector_size(vec));
       
   293 			}
       
   294 		}
       
   295 		flib_vector_destroy(vec);
       
   296 	}
       
   297 	return result;
       
   298 }
       
   299 
       
   300 int flib_netconn_send_roundfinished(flib_netconn *conn, bool withoutError) {
       
   301 	return sendInt(conn, "ROUNDFINISHED", withoutError ? 1 : 0);
       
   302 }
       
   303 
       
   304 int flib_netconn_send_ban(flib_netconn *conn, const char *playerName) {
       
   305 	return sendStr(conn, "BAN", playerName);
       
   306 }
       
   307 
       
   308 int flib_netconn_send_kick(flib_netconn *conn, const char *playerName) {
       
   309 	return sendStr(conn, "KICK", playerName);
       
   310 }
       
   311 
       
   312 int flib_netconn_send_playerInfo(flib_netconn *conn, const char *playerName) {
       
   313 	return sendStr(conn, "INFO", playerName);
       
   314 }
       
   315 
       
   316 int flib_netconn_send_playerFollow(flib_netconn *conn, const char *playerName) {
       
   317 	return sendStr(conn, "FOLLOW", playerName);
       
   318 }
       
   319 
       
   320 int flib_netconn_send_startGame(flib_netconn *conn) {
       
   321 	return sendVoid(conn, "START_GAME");
       
   322 }
       
   323 
       
   324 int flib_netconn_send_toggleRestrictJoins(flib_netconn *conn) {
       
   325 	return sendVoid(conn, "TOGGLE_RESTRICT_JOINS");
       
   326 }
       
   327 
       
   328 int flib_netconn_send_toggleRestrictTeams(flib_netconn *conn) {
       
   329 	return sendVoid(conn, "TOGGLE_RESTRICT_TEAMS");
       
   330 }
       
   331 
       
   332 int flib_netconn_send_clearAccountsCache(flib_netconn *conn) {
       
   333 	return sendVoid(conn, "CLEAR_ACCOUNTS_CACHE");
       
   334 }
       
   335 
       
   336 int flib_netconn_send_setServerVar(flib_netconn *conn, const char *name, const char *value) {
       
   337 	if(!conn || !name || !value) {
       
   338 		flib_log_e("null parameter trying to send SET_SERVER_VAR command.");
       
   339 		return -1;
       
   340 	}
       
   341 	return flib_netbase_sendf(conn->netBase, "%s\n%s\n%s\n\n", "SET_SERVER_VAR", name, value);
       
   342 }
       
   343 
       
   344 int flib_netconn_send_getServerVars(flib_netconn *conn) {
       
   345 	return sendVoid(conn, "GET_SERVER_VAR");
       
   346 }