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) { |
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]); |