project_files/frontlib/net/netprotocol.c
branchhedgeroid
changeset 7857 2bc61f8841a1
parent 7566 57d343ee382f
child 10017 de822cd3df3a
equal deleted inserted replaced
7855:ddcdedd3330b 7857:2bc61f8841a1
       
     1 /*
       
     2  * Hedgewars, a free turn based strategy game
       
     3  * Copyright (C) 2012 Simeon Maxein <smaxein@googlemail.com>
       
     4  *
       
     5  * This program is free software; you can redistribute it and/or
       
     6  * modify it under the terms of the GNU General Public License
       
     7  * as published by the Free Software Foundation; either version 2
       
     8  * of the License, or (at your option) any later version.
       
     9  *
       
    10  * This program is distributed in the hope that it will be useful,
       
    11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    13  * GNU General Public License for more details.
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License
       
    16  * along with this program; if not, write to the Free Software
       
    17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
       
    18  */
       
    19 
       
    20 #include "netprotocol.h"
       
    21 
       
    22 #include "../util/util.h"
       
    23 #include "../util/logging.h"
       
    24 
       
    25 #include "../base64/base64.h"
       
    26 
       
    27 #include <zlib.h>
       
    28 
       
    29 #include <string.h>
       
    30 #include <stdio.h>
       
    31 #include <errno.h>
       
    32 #include <stdlib.h>
       
    33 
       
    34 static int fillTeamFromMsg(flib_team *team, char **parts) {
       
    35 	team->name = flib_strdupnull(parts[0]);
       
    36 	team->grave = flib_strdupnull(parts[1]);
       
    37 	team->fort = flib_strdupnull(parts[2]);
       
    38 	team->voicepack = flib_strdupnull(parts[3]);
       
    39 	team->flag = flib_strdupnull(parts[4]);
       
    40 	team->ownerName = flib_strdupnull(parts[5]);
       
    41 	if(!team->name || !team->grave || !team->fort || !team->voicepack || !team->flag || !team->ownerName) {
       
    42 		return -1;
       
    43 	}
       
    44 
       
    45 	errno = 0;
       
    46 	long difficulty = strtol(parts[6], NULL, 10);
       
    47 	if(errno) {
       
    48 		return -1;
       
    49 	}
       
    50 
       
    51 	for(int i=0; i<HEDGEHOGS_PER_TEAM; i++) {
       
    52 		flib_hog *hog = &team->hogs[i];
       
    53 		hog->difficulty = difficulty;
       
    54 		hog->name = flib_strdupnull(parts[7+2*i]);
       
    55 		hog->hat = flib_strdupnull(parts[8+2*i]);
       
    56 		if(!hog->name || !hog->hat) {
       
    57 			return -1;
       
    58 		}
       
    59 	}
       
    60 
       
    61 	// Set some default assumptions as well
       
    62 	team->colorIndex = DEFAULT_COLOR_INDEX;
       
    63 	team->hogsInGame = DEFAULT_HEDGEHOG_COUNT;
       
    64 	team->remoteDriven = true;
       
    65 	return 0;
       
    66 }
       
    67 
       
    68 flib_team *flib_team_from_netmsg(char **parts) {
       
    69 	flib_team *result = NULL;
       
    70 	flib_team *tmpTeam = flib_calloc(1, sizeof(flib_team));
       
    71 	if(tmpTeam) {
       
    72 		if(!fillTeamFromMsg(tmpTeam, parts)) {
       
    73 			result = tmpTeam;
       
    74 			tmpTeam = NULL;
       
    75 		} else {
       
    76 			flib_log_e("Error parsing team from net.");
       
    77 		}
       
    78 	}
       
    79 	flib_team_destroy(tmpTeam);
       
    80 	return result;
       
    81 }
       
    82 
       
    83 flib_scheme *flib_scheme_from_netmsg(char **parts) {
       
    84 	flib_scheme *result = flib_scheme_create(parts[0]);
       
    85 	if(result) {
       
    86 		for(int i=0; i<flib_meta.modCount; i++) {
       
    87 			result->mods[i] = !strcmp(parts[i+1], "true");
       
    88 		}
       
    89 		for(int i=0; i<flib_meta.settingCount; i++) {
       
    90 			result->settings[i] = atoi(parts[i+flib_meta.modCount+1]);
       
    91 		}
       
    92 	}
       
    93 	return result;
       
    94 }
       
    95 
       
    96 flib_map *flib_map_from_netmsg(char **parts) {
       
    97 	flib_map *result = flib_map_create_named(parts[3], parts[0]);
       
    98 	if(result) {
       
    99 		result->mapgen = atoi(parts[1]);
       
   100 		result->mazeSize = atoi(parts[2]);
       
   101 		result->templateFilter = atoi(parts[4]);
       
   102 	}
       
   103 	return result;
       
   104 }
       
   105 
       
   106 int flib_drawnmapdata_from_netmsg(char *netmsg, uint8_t** outbuf, size_t *outlen) {
       
   107 	int result = -1;
       
   108 
       
   109 	// First step: base64 decoding
       
   110 	char *base64decout = NULL;
       
   111 	size_t base64declen;
       
   112 	bool ok = base64_decode_alloc(netmsg, strlen(netmsg), &base64decout, &base64declen);
       
   113 	if(ok && base64declen>3) {
       
   114 		// Second step: unzip with the QCompress header. That header is just a big-endian
       
   115 		// uint32 indicating the length of the uncompressed data.
       
   116 		uint8_t *ubyteBuf = (uint8_t*)base64decout;
       
   117 		uint32_t unzipLen =
       
   118 				(((uint32_t)ubyteBuf[0])<<24)
       
   119 				+ (((uint32_t)ubyteBuf[1])<<16)
       
   120 				+ (((uint32_t)ubyteBuf[2])<<8)
       
   121 				+ ubyteBuf[3];
       
   122 		if(unzipLen==0) {
       
   123 			*outbuf = NULL;
       
   124 			*outlen = 0;
       
   125 			result = 0;
       
   126 		} else {
       
   127 			uint8_t *out = flib_malloc(unzipLen);
       
   128 			if(out) {
       
   129 				uLongf actualUnzipLen = unzipLen;
       
   130 				int resultcode = uncompress(out, &actualUnzipLen, (Bytef*)(base64decout+4), base64declen-4);
       
   131 				if(resultcode == Z_OK) {
       
   132 					*outbuf = out;
       
   133 					*outlen = actualUnzipLen;
       
   134 					out = NULL;
       
   135 					result = 0;
       
   136 				} else {
       
   137 					flib_log_e("Uncompressing drawn map failed. Code: %i", resultcode);
       
   138 				}
       
   139 			}
       
   140 			free(out);
       
   141 		}
       
   142 	} else {
       
   143 		flib_log_e("base64 decoding of drawn map failed.");
       
   144 	}
       
   145 	free(base64decout);
       
   146 	return result;
       
   147 }
       
   148 
       
   149 flib_room *flib_room_from_netmsg(char **params) {
       
   150 	flib_room *result = NULL;
       
   151 	flib_room *tmpRoom = flib_calloc(1, sizeof(flib_room));
       
   152 	if(tmpRoom) {
       
   153 		tmpRoom->inProgress = !strcmp(params[0], "True");
       
   154 		tmpRoom->name = flib_strdupnull(params[1]);
       
   155 		tmpRoom->playerCount = atoi(params[2]);
       
   156 		tmpRoom->teamCount = atoi(params[3]);
       
   157 		tmpRoom->owner = flib_strdupnull(params[4]);
       
   158 		tmpRoom->map = flib_strdupnull(params[5]);
       
   159 		tmpRoom->scheme = flib_strdupnull(params[6]);
       
   160 		tmpRoom->weapons = flib_strdupnull(params[7]);
       
   161 		if(tmpRoom->name && tmpRoom->owner && tmpRoom->map && tmpRoom->scheme && tmpRoom->weapons) {
       
   162 			result = tmpRoom;
       
   163 			tmpRoom = NULL;
       
   164 		}
       
   165 	}
       
   166 	flib_room_destroy(tmpRoom);
       
   167 	return result;
       
   168 }
       
   169 
       
   170 int fillRoomArray(flib_room **array, char **params, int count) {
       
   171 	for(int i=0; i<count; i++) {
       
   172 		array[i] = flib_room_from_netmsg(params + 8*i);
       
   173 		if(!array[i]) {
       
   174 			return -1;
       
   175 		}
       
   176 	}
       
   177 	return 0;
       
   178 }
       
   179 
       
   180 flib_room **flib_room_array_from_netmsg(char **params, int count) {
       
   181 	flib_room **result = flib_calloc(count, sizeof(flib_room*));
       
   182 	if(result) {
       
   183 		if(fillRoomArray(result, params, count)) {
       
   184 			for(int i=0; i<count; i++) {
       
   185 				flib_room_destroy(result[i]);
       
   186 			}
       
   187 			free(result);
       
   188 			result = NULL;
       
   189 		}
       
   190 	}
       
   191 	return result;
       
   192 }