project_files/frontlib/net/netconn.c
changeset 7482 d70a5b0d1190
parent 7338 1ed603a54ebd
child 7497 7e1d72fc03c7
equal deleted inserted replaced
7479:c8c552ee3acb 7482:d70a5b0d1190
    16  * You should have received a copy of the GNU General Public License
    16  * You should have received a copy of the GNU General Public License
    17  * along with this program; if not, write to the Free Software
    17  * along with this program; if not, write to the Free Software
    18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
    18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
    19  */
    19  */
    20 
    20 
    21 // TODO: Check the state transitions. Document with a diagram or something
       
    22 
       
    23 #include "netconn_internal.h"
    21 #include "netconn_internal.h"
    24 #include "netprotocol.h"
    22 #include "netprotocol.h"
    25 #include "../util/logging.h"
    23 #include "../util/logging.h"
    26 #include "../util/util.h"
    24 #include "../util/util.h"
    27 #include "../md5/md5.h"
    25 #include "../md5/md5.h"
    51 			newConn->pendingTeamlist.teamCount = 0;
    49 			newConn->pendingTeamlist.teamCount = 0;
    52 			newConn->pendingTeamlist.teams = NULL;
    50 			newConn->pendingTeamlist.teams = NULL;
    53 			newConn->teamlist.teamCount = 0;
    51 			newConn->teamlist.teamCount = 0;
    54 			newConn->teamlist.teams = NULL;
    52 			newConn->teamlist.teams = NULL;
    55 			newConn->scheme = NULL;
    53 			newConn->scheme = NULL;
    56 			newConn->script = NULL;
    54 			newConn->style = NULL;
    57 			newConn->weaponset = NULL;
    55 			newConn->weaponset = NULL;
    58 
    56 
    59 			newConn->running = false;
    57 			newConn->running = false;
    60 			newConn->destroyRequested = false;
    58 			newConn->destroyRequested = false;
    61 			netconn_clearCallbacks(newConn);
    59 			netconn_clearCallbacks(newConn);
    84 			free(conn->playerName);
    82 			free(conn->playerName);
    85 			free(conn->dataDirPath);
    83 			free(conn->dataDirPath);
    86 
    84 
    87 			flib_metascheme_release(conn->metaCfg);
    85 			flib_metascheme_release(conn->metaCfg);
    88 
    86 
    89 			flib_map_release(conn->map);
    87 			flib_map_destroy(conn->map);
    90 			flib_teamlist_clear(&conn->pendingTeamlist);
    88 			flib_teamlist_clear(&conn->pendingTeamlist);
    91 			flib_teamlist_clear(&conn->teamlist);
    89 			flib_teamlist_clear(&conn->teamlist);
    92 			flib_scheme_release(conn->scheme);
    90 			flib_scheme_destroy(conn->scheme);
    93 			free(conn->script);
    91 			free(conn->style);
    94 			flib_weaponset_release(conn->weaponset);
    92 			flib_weaponset_release(conn->weaponset);
    95 
    93 
    96 			free(conn);
    94 			free(conn);
    97 		}
    95 		}
    98 	}
    96 	}
    99 }
    97 }
   100 
    98 
   101 bool flib_netconn_is_chief(flib_netconn *conn) {
    99 bool flib_netconn_is_chief(flib_netconn *conn) {
   102 	if(!log_badargs_if(conn==NULL) && flib_netconn_is_in_room_context(conn)) {
   100 	if(!log_badargs_if(conn==NULL) && conn->netconnState==NETCONN_STATE_ROOM) {
   103 		return conn->isChief;
   101 		return conn->isChief;
   104 	}
   102 	}
   105 	return false;
   103 	return false;
   106 }
   104 }
   107 
   105 
   113 }
   111 }
   114 
   112 
   115 void netconn_leaveRoom(flib_netconn *conn) {
   113 void netconn_leaveRoom(flib_netconn *conn) {
   116 	conn->netconnState = NETCONN_STATE_LOBBY;
   114 	conn->netconnState = NETCONN_STATE_LOBBY;
   117 	conn->isChief = false;
   115 	conn->isChief = false;
   118 	flib_map_release(conn->map);
   116 	flib_map_destroy(conn->map);
   119 	conn->map = flib_map_create_named("", "NoSuchMap");
   117 	conn->map = flib_map_create_named("", "NoSuchMap");
   120 	flib_teamlist_clear(&conn->pendingTeamlist);
   118 	flib_teamlist_clear(&conn->pendingTeamlist);
   121 	flib_teamlist_clear(&conn->teamlist);
   119 	flib_teamlist_clear(&conn->teamlist);
   122 	flib_scheme_release(conn->scheme);
   120 	flib_scheme_destroy(conn->scheme);
   123 	conn->scheme = NULL;
   121 	conn->scheme = NULL;
   124 	free(conn->script);
   122 	free(conn->style);
   125 	conn->script = NULL;
   123 	conn->style = NULL;
   126 	flib_weaponset_release(conn->weaponset);
   124 	flib_weaponset_release(conn->weaponset);
   127 	conn->weaponset = NULL;
   125 	conn->weaponset = NULL;
   128 }
       
   129 
       
   130 bool flib_netconn_is_in_room_context(flib_netconn *conn) {
       
   131 	return conn && (conn->netconnState == NETCONN_STATE_ROOM || conn->netconnState == NETCONN_STATE_INGAME);
       
   132 }
   126 }
   133 
   127 
   134 void netconn_setMap(flib_netconn *conn, const flib_map *map) {
   128 void netconn_setMap(flib_netconn *conn, const flib_map *map) {
   135 	flib_map *copy = flib_map_copy(map);
   129 	flib_map *copy = flib_map_copy(map);
   136 	if(copy) {
   130 	if(copy) {
   137 		flib_map_release(conn->map);
   131 		flib_map_destroy(conn->map);
   138 		conn->map = copy;
   132 		conn->map = copy;
   139 	}
   133 	}
   140 }
   134 }
   141 
   135 
   142 void netconn_setWeaponset(flib_netconn *conn, const flib_weaponset *weaponset) {
   136 void netconn_setWeaponset(flib_netconn *conn, const flib_weaponset *weaponset) {
   148 }
   142 }
   149 
   143 
   150 void netconn_setScript(flib_netconn *conn, const char *script) {
   144 void netconn_setScript(flib_netconn *conn, const char *script) {
   151 	char *copy = flib_strdupnull(script);
   145 	char *copy = flib_strdupnull(script);
   152 	if(copy) {
   146 	if(copy) {
   153 		free(conn->script);
   147 		free(conn->style);
   154 		conn->script = copy;
   148 		conn->style = copy;
   155 	}
   149 	}
   156 }
   150 }
   157 
   151 
   158 void netconn_setScheme(flib_netconn *conn, const flib_scheme *scheme) {
   152 void netconn_setScheme(flib_netconn *conn, const flib_scheme *scheme) {
   159 	flib_scheme *copy = flib_scheme_copy(scheme);
   153 	flib_scheme *copy = flib_scheme_copy(scheme);
   160 	if(copy) {
   154 	if(copy) {
   161 		flib_scheme_release(conn->scheme);
   155 		flib_scheme_destroy(conn->scheme);
   162 		conn->scheme = copy;
   156 		conn->scheme = copy;
   163 	}
   157 	}
   164 }
   158 }
   165 
   159 
   166 flib_gamesetup *flib_netconn_create_gamesetup(flib_netconn *conn) {
   160 flib_gamesetup *flib_netconn_create_gamesetup(flib_netconn *conn) {
   170 			flib_log_e("Incomplete room state");
   164 			flib_log_e("Incomplete room state");
   171 		} else {
   165 		} else {
   172 			flib_gamesetup stackSetup = {0};
   166 			flib_gamesetup stackSetup = {0};
   173 			stackSetup.gamescheme = conn->scheme;
   167 			stackSetup.gamescheme = conn->scheme;
   174 			stackSetup.map = conn->map;
   168 			stackSetup.map = conn->map;
   175 			stackSetup.script = conn->script;
   169 			stackSetup.style = conn->style;
   176 			stackSetup.teamlist = &conn->teamlist;
   170 			stackSetup.teamlist = &conn->teamlist;
   177 			flib_gamesetup *tmpSetup = flib_gamesetup_copy(&stackSetup);
   171 			flib_gamesetup *tmpSetup = flib_gamesetup_copy(&stackSetup);
   178 			if(tmpSetup) {
   172 			if(tmpSetup) {
   179 				for(int i=0; i<tmpSetup->teamlist->teamCount; i++) {
   173 				for(int i=0; i<tmpSetup->teamlist->teamCount; i++) {
   180 					flib_team_set_weaponset(tmpSetup->teamlist->teams[i], conn->weaponset);
   174 					flib_team_set_weaponset(tmpSetup->teamlist->teams[i], conn->weaponset);
   320 						break;
   314 						break;
   321 					}
   315 					}
   322 				}
   316 				}
   323 	        }
   317 	        }
   324 	    } else if (!strcmp(cmd, "ADD_TEAM")) {
   318 	    } else if (!strcmp(cmd, "ADD_TEAM")) {
   325 	        if(netmsg->partCount != 24 || !flib_netconn_is_in_room_context(conn)) {
   319 	        if(netmsg->partCount != 24 || conn->netconnState!=NETCONN_STATE_ROOM) {
   326 	            flib_log_w("Net: Bad ADD_TEAM message");
   320 	            flib_log_w("Net: Bad ADD_TEAM message");
   327 	        } else {
   321 	        } else {
   328 	        	flib_team *team = flib_team_from_netmsg(netmsg->parts+1);
   322 	        	flib_team *team = flib_team_from_netmsg(netmsg->parts+1);
   329 	        	if(!team || flib_teamlist_insert(&conn->teamlist, team, conn->teamlist.teamCount)) {
   323 	        	if(!team || flib_teamlist_insert(&conn->teamlist, team, conn->teamlist.teamCount)) {
   330 					flib_team_destroy(team);
   324 					flib_team_destroy(team);
   335 	        		team->remoteDriven = true;
   329 	        		team->remoteDriven = true;
   336 	        		conn->onTeamAddCb(conn->onTeamAddCtx, team);
   330 	        		conn->onTeamAddCb(conn->onTeamAddCtx, team);
   337 	        	}
   331 	        	}
   338 	        }
   332 	        }
   339 	    } else if (!strcmp(cmd, "REMOVE_TEAM")) {
   333 	    } else if (!strcmp(cmd, "REMOVE_TEAM")) {
   340 	        if(netmsg->partCount != 2 || !flib_netconn_is_in_room_context(conn)) {
   334 	        if(netmsg->partCount != 2 || conn->netconnState!=NETCONN_STATE_ROOM) {
   341 	            flib_log_w("Net: Bad REMOVETEAM message");
   335 	            flib_log_w("Net: Bad REMOVETEAM message");
   342 	        } else {
   336 	        } else {
   343 	        	flib_teamlist_delete(&conn->teamlist, netmsg->parts[1]);
   337 	        	flib_teamlist_delete(&conn->teamlist, netmsg->parts[1]);
   344 	        	conn->onTeamDeleteCb(conn->onTeamDeleteCtx, netmsg->parts[1]);
   338 	        	conn->onTeamDeleteCb(conn->onTeamDeleteCtx, netmsg->parts[1]);
   345 	        }
   339 	        }
   408 	            flib_log_w("Net: Bad LOBBY:LEFT message");
   402 	            flib_log_w("Net: Bad LOBBY:LEFT message");
   409 	        } else {
   403 	        } else {
   410 	        	conn->onLobbyLeaveCb(conn->onLobbyLeaveCtx, netmsg->parts[1], netmsg->partCount>2 ? netmsg->parts[2] : NULL);
   404 	        	conn->onLobbyLeaveCb(conn->onLobbyLeaveCtx, netmsg->parts[1], netmsg->partCount>2 ? netmsg->parts[2] : NULL);
   411 	        }
   405 	        }
   412 	    } else if (!strcmp(cmd, "RUN_GAME")) {
   406 	    } else if (!strcmp(cmd, "RUN_GAME")) {
   413 	        conn->netconnState = NETCONN_STATE_INGAME;
       
   414 	        // TODO send along the config
       
   415 	        conn->onRunGameCb(conn->onRunGameCtx);
   407 	        conn->onRunGameCb(conn->onRunGameCtx);
   416 	    } else if (!strcmp(cmd, "ASKPASSWORD")) {
   408 	    } else if (!strcmp(cmd, "ASKPASSWORD")) {
   417 	    	conn->onPasswordRequestCb(conn->onPasswordRequestCtx, conn->playerName);
   409 	    	conn->onPasswordRequestCb(conn->onPasswordRequestCtx, conn->playerName);
   418 	    } else if (!strcmp(cmd, "NOTICE")) {
   410 	    } else if (!strcmp(cmd, "NOTICE")) {
   419 	        if(netmsg->partCount < 2) {
   411 	        if(netmsg->partCount < 2) {
   428 				} else {
   420 				} else {
   429 					flib_log_w("Net: Unknown NOTICE message: %l", n);
   421 					flib_log_w("Net: Unknown NOTICE message: %l", n);
   430 				}
   422 				}
   431 	        }
   423 	        }
   432 	    } else if (!strcmp(cmd, "TEAM_ACCEPTED")) {
   424 	    } else if (!strcmp(cmd, "TEAM_ACCEPTED")) {
   433 	        if (netmsg->partCount != 2 || !flib_netconn_is_in_room_context(conn)) {
   425 	        if (netmsg->partCount != 2 || conn->netconnState!=NETCONN_STATE_ROOM) {
   434 	            flib_log_w("Net: Bad TEAM_ACCEPTED message");
   426 	            flib_log_w("Net: Bad TEAM_ACCEPTED message");
   435 	        } else {
   427 	        } else {
   436 	        	flib_team *team = flib_teamlist_find(&conn->pendingTeamlist, netmsg->parts[1]);
   428 	        	flib_team *team = flib_team_copy(flib_teamlist_find(&conn->pendingTeamlist, netmsg->parts[1]));
   437 	        	if(team) {
   429 	        	if(team) {
   438 	        		flib_teamlist_insert(&conn->teamlist, team, conn->teamlist.teamCount);
   430 	        		flib_teamlist_insert(&conn->teamlist, team, conn->teamlist.teamCount);
   439 	        		flib_teamlist_delete(&conn->pendingTeamlist, netmsg->parts[1]);
   431 	        		flib_teamlist_delete(&conn->pendingTeamlist, netmsg->parts[1]);
   440 	        	} else {
   432 	        	} else {
   441 	        		flib_log_e("Team accepted that was not requested: %s", netmsg->parts[1]);
   433 	        		flib_log_e("Team accepted that was not requested: %s", netmsg->parts[1]);
   442 	        	}
   434 	        	}
   443 	        	conn->onTeamAcceptedCb(conn->onTeamAcceptedCtx, netmsg->parts[1]);
   435 	        	conn->onTeamAcceptedCb(conn->onTeamAcceptedCtx, netmsg->parts[1]);
   444 	        }
   436 	        }
   445 	    } else if (!strcmp(cmd, "CFG")) {
   437 	    } else if (!strcmp(cmd, "CFG")) {
   446 	        if(netmsg->partCount < 3 || !flib_netconn_is_in_room_context(conn)) {
   438 	        if(netmsg->partCount < 3 || conn->netconnState!=NETCONN_STATE_ROOM) {
   447 	            flib_log_w("Net: Bad CFG message");
   439 	            flib_log_w("Net: Bad CFG message");
   448 	        } else {
   440 	        } else {
   449 	        	const char *subcmd = netmsg->parts[1];
   441 	        	const char *subcmd = netmsg->parts[1];
   450 				if(!strcmp(subcmd, "SCHEME") && netmsg->partCount == conn->metaCfg->modCount + conn->metaCfg->settingCount + 3) {
   442 				if(!strcmp(subcmd, "SCHEME") && netmsg->partCount == conn->metaCfg->modCount + conn->metaCfg->settingCount + 3) {
   451 					flib_scheme *cfg = flib_netmsg_to_cfg(conn->metaCfg, netmsg->parts+2);
   443 					flib_scheme *cfg = flib_scheme_from_netmsg(conn->metaCfg, netmsg->parts+2);
   452 					if(cfg) {
   444 					if(cfg) {
   453 						netconn_setScheme(conn, cfg);
   445 						flib_scheme_destroy(conn->scheme);
       
   446 						conn->scheme = cfg;
   454 						conn->onCfgSchemeCb(conn->onCfgSchemeCtx, cfg);
   447 						conn->onCfgSchemeCb(conn->onCfgSchemeCtx, cfg);
   455 					} else {
   448 					} else {
   456 						flib_log_e("Error processing CFG SCHEME message");
   449 						flib_log_e("Error processing CFG SCHEME message");
   457 					}
   450 					}
   458 					flib_scheme_release(cfg);
       
   459 				} else if(!strcmp(subcmd, "FULLMAPCONFIG") && netmsg->partCount == 7) {
   451 				} else if(!strcmp(subcmd, "FULLMAPCONFIG") && netmsg->partCount == 7) {
   460 					flib_map *map = flib_netmsg_to_map(netmsg->parts+2);
   452 					flib_map *map = flib_map_from_netmsg(netmsg->parts+2);
   461 					if(map) {
   453 					if(map) {
   462 						netconn_setMap(conn, map);
   454 						flib_map_destroy(conn->map);
       
   455 						conn->map = map;
   463 						conn->onMapChangedCb(conn->onMapChangedCtx, conn->map, NETCONN_MAPCHANGE_FULL);
   456 						conn->onMapChangedCb(conn->onMapChangedCtx, conn->map, NETCONN_MAPCHANGE_FULL);
   464 					} else {
   457 					} else {
   465 						flib_log_e("Error processing CFG FULLMAPCONFIG message");
   458 						flib_log_e("Error processing CFG FULLMAPCONFIG message");
   466 					}
   459 					}
   467 					flib_map_release(map);
       
   468 				} else if(!strcmp(subcmd, "MAP") && netmsg->partCount == 3) {
   460 				} else if(!strcmp(subcmd, "MAP") && netmsg->partCount == 3) {
   469 					char *mapname = flib_strdupnull(netmsg->parts[2]);
   461 					char *mapname = flib_strdupnull(netmsg->parts[2]);
   470 					if(mapname) {
   462 					if(mapname) {
   471 						free(conn->map->name);
   463 						free(conn->map->name);
   472 						conn->map->name = mapname;
   464 						conn->map->name = mapname;
   502 					conn->map->mazeSize = atoi(netmsg->parts[2]);
   494 					conn->map->mazeSize = atoi(netmsg->parts[2]);
   503 					conn->onMapChangedCb(conn->onMapChangedCtx, conn->map, NETCONN_MAPCHANGE_MAZE_SIZE);
   495 					conn->onMapChangedCb(conn->onMapChangedCtx, conn->map, NETCONN_MAPCHANGE_MAZE_SIZE);
   504 				} else if(!strcmp(subcmd, "DRAWNMAP") && netmsg->partCount == 3) {
   496 				} else if(!strcmp(subcmd, "DRAWNMAP") && netmsg->partCount == 3) {
   505 					size_t drawnMapSize = 0;
   497 					size_t drawnMapSize = 0;
   506 					uint8_t *drawnMapData = NULL;
   498 					uint8_t *drawnMapData = NULL;
   507 					if(!flib_netmsg_to_drawnmapdata(netmsg->parts[2], &drawnMapData, &drawnMapSize)) {
   499 					if(!flib_drawnmapdata_from_netmsg(netmsg->parts[2], &drawnMapData, &drawnMapSize)) {
   508 						free(conn->map->drawData);
   500 						free(conn->map->drawData);
   509 						conn->map->drawData = drawnMapData;
   501 						conn->map->drawData = drawnMapData;
   510 						conn->map->drawDataSize = drawnMapSize;
   502 						conn->map->drawDataSize = drawnMapSize;
   511 						conn->onMapChangedCb(conn->onMapChangedCtx, conn->map, NETCONN_MAPCHANGE_DRAWNMAP);
   503 						conn->onMapChangedCb(conn->onMapChangedCtx, conn->map, NETCONN_MAPCHANGE_DRAWNMAP);
   512 					} else {
   504 					} else {
   527 				} else {
   519 				} else {
   528 					flib_log_w("Net: Unknown or malformed CFG subcommand: %s", subcmd);
   520 					flib_log_w("Net: Unknown or malformed CFG subcommand: %s", subcmd);
   529 				}
   521 				}
   530 	        }
   522 	        }
   531 	    } else if (!strcmp(cmd, "HH_NUM")) {
   523 	    } else if (!strcmp(cmd, "HH_NUM")) {
   532 	        if (netmsg->partCount != 3 || !flib_netconn_is_in_room_context(conn)) {
   524 	        if (netmsg->partCount != 3 || conn->netconnState!=NETCONN_STATE_ROOM) {
   533 	            flib_log_w("Net: Bad HH_NUM message");
   525 	            flib_log_w("Net: Bad HH_NUM message");
   534 	        } else {
   526 	        } else {
   535 	        	int hogs = atoi(netmsg->parts[2]);
   527 	        	int hogs = atoi(netmsg->parts[2]);
   536 	        	if(hogs<=0 || hogs>HEDGEHOGS_PER_TEAM) {
   528 	        	if(hogs<=0 || hogs>HEDGEHOGS_PER_TEAM) {
   537 	        		flib_log_w("Net: Bad HH_NUM message: %s hogs", netmsg->parts[2]);
   529 	        		flib_log_w("Net: Bad HH_NUM message: %s hogs", netmsg->parts[2]);
   544 	        		}
   536 	        		}
   545 	        		conn->onHogCountChangedCb(conn->onHogCountChangedCtx, netmsg->parts[1], hogs);
   537 	        		conn->onHogCountChangedCb(conn->onHogCountChangedCtx, netmsg->parts[1], hogs);
   546 	        	}
   538 	        	}
   547 	        }
   539 	        }
   548 	    } else if (!strcmp(cmd, "TEAM_COLOR")) {
   540 	    } else if (!strcmp(cmd, "TEAM_COLOR")) {
   549 	        if (netmsg->partCount != 3 || !flib_netconn_is_in_room_context(conn)) {
   541 	        if (netmsg->partCount != 3 || conn->netconnState!=NETCONN_STATE_ROOM) {
   550 	            flib_log_w("Net: Bad TEAM_COLOR message");
   542 	            flib_log_w("Net: Bad TEAM_COLOR message");
   551 	        } else {
   543 	        } else {
   552 	        	long color;
   544 	        	long color;
   553 	        	if(sscanf(netmsg->parts[2], "%lu", &color) && color>=0 && color<flib_teamcolor_defaults_len) {
   545 	        	if(sscanf(netmsg->parts[2], "%lu", &color) && color>=0 && color<flib_teamcolor_count) {
   554 	        		flib_team *team = flib_teamlist_find(&conn->teamlist, netmsg->parts[1]);
   546 	        		flib_team *team = flib_teamlist_find(&conn->teamlist, netmsg->parts[1]);
   555 	        		if(team) {
   547 	        		if(team) {
   556 	        			team->colorIndex = color;
   548 	        			team->colorIndex = color;
   557 	        		} else {
   549 	        		} else {
   558 	        			flib_log_e("TEAM_COLOR message for unknown team %s", netmsg->parts[1]);
   550 	        			flib_log_e("TEAM_COLOR message for unknown team %s", netmsg->parts[1]);