830 { |
830 { |
831 NetworkTCPSocketHandler *new_cs; |
831 NetworkTCPSocketHandler *new_cs; |
832 const NetworkClientInfo *ci; |
832 const NetworkClientInfo *ci; |
833 byte callback; |
833 byte callback; |
834 |
834 |
835 CommandPacket *cp = MallocT<CommandPacket>(1); |
|
836 |
|
837 // The client was never joined.. so this is impossible, right? |
835 // The client was never joined.. so this is impossible, right? |
838 // Ignore the packet, give the client a warning, and close his connection |
836 // Ignore the packet, give the client a warning, and close his connection |
839 if (cs->status < STATUS_DONE_MAP || cs->has_quit) { |
837 if (cs->status < STATUS_DONE_MAP || cs->has_quit) { |
840 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED); |
838 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED); |
841 return; |
839 return; |
842 } |
840 } |
843 |
841 |
|
842 CommandPacket *cp = MallocT<CommandPacket>(1); |
844 cp->player = (Owner)p->Recv_uint8(); |
843 cp->player = (Owner)p->Recv_uint8(); |
845 cp->cmd = p->Recv_uint32(); |
844 cp->cmd = p->Recv_uint32(); |
846 cp->p1 = p->Recv_uint32(); |
845 cp->p1 = p->Recv_uint32(); |
847 cp->p2 = p->Recv_uint32(); |
846 cp->p2 = p->Recv_uint32(); |
848 cp->tile = p->Recv_uint32(); |
847 cp->tile = p->Recv_uint32(); |
849 p->Recv_string(cp->text, lengthof(cp->text)); |
848 p->Recv_string(cp->text, lengthof(cp->text)); |
850 |
849 |
851 callback = p->Recv_uint8(); |
850 callback = p->Recv_uint8(); |
852 |
851 |
853 if (cs->has_quit) return; |
852 if (cs->has_quit) { |
|
853 free(cp); |
|
854 return; |
|
855 } |
854 |
856 |
855 ci = DEREF_CLIENT_INFO(cs); |
857 ci = DEREF_CLIENT_INFO(cs); |
856 |
858 |
857 /* Check if cp->cmd is valid */ |
859 /* Check if cp->cmd is valid */ |
858 if (!IsValidCommand(cp->cmd)) { |
860 if (!IsValidCommand(cp->cmd)) { |
859 IConsolePrintF(_icolour_err, "WARNING: invalid command from client %d (IP: %s).", ci->client_index, GetPlayerIP(ci)); |
861 IConsolePrintF(_icolour_err, "WARNING: invalid command from client %d (IP: %s).", ci->client_index, GetPlayerIP(ci)); |
860 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED); |
862 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED); |
|
863 free(cp); |
861 return; |
864 return; |
862 } |
865 } |
863 |
866 |
864 if (!CheckCommandFlags(cp, ci)) { |
867 if (!CheckCommandFlags(cp, ci)) { |
865 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_KICKED); |
868 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_KICKED); |
|
869 free(cp); |
866 return; |
870 return; |
867 } |
871 } |
868 |
872 |
869 /** Only CMD_PLAYER_CTRL is always allowed, for the rest, playas needs |
873 /** Only CMD_PLAYER_CTRL is always allowed, for the rest, playas needs |
870 * to match the player in the packet. If it doesn't, the client has done |
874 * to match the player in the packet. If it doesn't, the client has done |
872 */ |
876 */ |
873 if (!(cp->cmd == CMD_PLAYER_CTRL && cp->p1 == 0) && ci->client_playas != cp->player) { |
877 if (!(cp->cmd == CMD_PLAYER_CTRL && cp->p1 == 0) && ci->client_playas != cp->player) { |
874 IConsolePrintF(_icolour_err, "WARNING: player %d (IP: %s) tried to execute a command as player %d, kicking...", |
878 IConsolePrintF(_icolour_err, "WARNING: player %d (IP: %s) tried to execute a command as player %d, kicking...", |
875 ci->client_playas + 1, GetPlayerIP(ci), cp->player + 1); |
879 ci->client_playas + 1, GetPlayerIP(ci), cp->player + 1); |
876 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_PLAYER_MISMATCH); |
880 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_PLAYER_MISMATCH); |
|
881 free(cp); |
877 return; |
882 return; |
878 } |
883 } |
879 |
884 |
880 /** @todo CMD_PLAYER_CTRL with p1 = 0 announces a new player to the server. To give the |
885 /** @todo CMD_PLAYER_CTRL with p1 = 0 announces a new player to the server. To give the |
881 * player the correct ID, the server injects p2 and executes the command. Any other p1 |
886 * player the correct ID, the server injects p2 and executes the command. Any other p1 |
883 * @see CmdPlayerCtrl() players.c:655 |
888 * @see CmdPlayerCtrl() players.c:655 |
884 */ |
889 */ |
885 if (cp->cmd == CMD_PLAYER_CTRL) { |
890 if (cp->cmd == CMD_PLAYER_CTRL) { |
886 if (cp->p1 != 0) { |
891 if (cp->p1 != 0) { |
887 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_CHEATER); |
892 SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_CHEATER); |
|
893 free(cp); |
888 return; |
894 return; |
889 } |
895 } |
890 |
896 |
891 /* XXX - Execute the command as a valid player. Normally this would be done by a |
897 /* XXX - Execute the command as a valid player. Normally this would be done by a |
892 * spectator, but that is not allowed any commands. So do an impersonation. The drawback |
898 * spectator, but that is not allowed any commands. So do an impersonation. The drawback |