X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_net.pas;h=249ef8a05f51eca4269c778fd56e03f6987b3779;hb=1ff17b72a3780a18e413d0d30ed4f3393c826aeb;hp=07d9713477ed7da1251d54bfffac53b3cfd5d9b7;hpb=10f31fd950820bcd8b83aec43debcfc260b714b2;p=d2df-sdl.git diff --git a/src/game/g_net.pas b/src/game/g_net.pas index 07d9713..249ef8a 100644 --- a/src/game/g_net.pas +++ b/src/game/g_net.pas @@ -21,7 +21,7 @@ uses e_log, e_msg, utils, ENet, Classes, md5, MAPDEF{$IFDEF USE_MINIUPNPC}, miniupnpc;{$ELSE};{$ENDIF} const - NET_PROTOCOL_VER = 185; + NET_PROTOCOL_VER = 187; NET_MAXCLIENTS = 24; NET_CHANS = 12; @@ -105,6 +105,7 @@ type WaitForFirstSpawn: Boolean; // set to `true` in server, used to spawn a player on first full state request RCONAuth: Boolean; Voted: Boolean; + Crimes: Integer; Transfer: TNetFileTransfer; // only one transfer may be active NetOut: array [0..1] of TMsg; end; @@ -154,6 +155,10 @@ var NetMaxClients: Byte = 255; NetBannedHosts: array of TBanRecord; + NetAutoBanLimit: Integer = 5; + NetAutoBanPerm: Boolean = True; + NetAutoBanWarn: Boolean = False; + NetState: Integer = NET_STATE_NONE; NetMyID: Integer = -1; @@ -172,6 +177,8 @@ var NetGotEverything: Boolean = False; NetGotKeys: Boolean = False; + NetDeafLevel: Integer = 0; + {$IFDEF USE_MINIUPNPC} NetPortForwarded: Word = 0; NetPongForwarded: Boolean = False; @@ -221,6 +228,8 @@ function g_Net_UnbanHost(IP: LongWord): Boolean; overload; procedure g_Net_UnbanNonPermHosts(); procedure g_Net_SaveBanList(); +procedure g_Net_Penalize(C: pTNetClient; Reason: string); + procedure g_Net_DumpStart(); procedure g_Net_DumpSendBuffer(); procedure g_Net_DumpRecvBuffer(Buf: penet_uint8; Len: LongWord); @@ -271,7 +280,10 @@ begin end; procedure g_Net_InitLowLevel (); + var v: ENetVersion; begin + v := enet_linked_version(); + e_LogWritefln('ENet Version: %s.%s.%s', [ENET_VERSION_GET_MAJOR(v), ENET_VERSION_GET_MINOR(v), ENET_VERSION_GET_PATCH(v)]); if enet_init_success then raise Exception.Create('wuta?!'); enet_init_success := (enet_initialize() = 0); end; @@ -1492,8 +1504,6 @@ begin NetAddr.host := IPAddr; NetAddr.port := Port; - if NetForwardPorts then NetPortThread := BeginThread(ForwardThread); - NetHost := enet_host_create(@NetAddr, NET_MAXCLIENTS, NET_CHANS, 0, 0); if (NetHost = nil) then @@ -1504,6 +1514,8 @@ begin Exit; end; + if NetForwardPorts then NetPortThread := BeginThread(ForwardThread); + NetPongSock := enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM); if NetPongSock <> ENET_SOCKET_NULL then begin @@ -1550,6 +1562,8 @@ begin enet_peer_reset(NetClients[I].Peer); NetClients[I].Peer := nil; NetClients[I].Used := False; + NetClients[I].Player := 0; + NetClients[I].Crimes := 0; NetClients[I].NetOut[NET_UNRELIABLE].Free(); NetClients[I].NetOut[NET_RELIABLE].Free(); end; @@ -1606,7 +1620,7 @@ var Ping: array [0..9] of Byte; NPl: Byte; begin - if NetPongSock = ENET_SOCKET_NULL then Exit; + if (NetPongSock = ENET_SOCKET_NULL) or (NetHost = nil) then Exit; Buf.data := Addr(Ping[0]); Buf.dataLength := 2+8; @@ -1676,6 +1690,17 @@ begin Exit; end; + if g_Net_IsHostBanned(NetEvent.Peer^.address.host) then + begin + g_Console_Add(_lc[I_NET_MSG] + _lc[I_NET_MSG_HOST_REJECT] + + _lc[I_NET_DISC_BAN]); + NetEvent.peer^.data := GetMemory(SizeOf(Byte)); + Byte(NetEvent.peer^.data^) := 255; + enet_peer_disconnect(NetEvent.Peer, NET_DISC_BAN); + enet_host_flush(NetHost); + Exit; + end; + ID := g_Net_FindSlot(); if ID < 0 then @@ -1693,6 +1718,8 @@ begin NetClients[ID].Peer^.data := GetMemory(SizeOf(Byte)); Byte(NetClients[ID].Peer^.data^) := ID; NetClients[ID].State := NET_STATE_AUTH; + NetClients[ID].Player := 0; + NetClients[ID].Crimes := 0; NetClients[ID].RCONAuth := False; NetClients[ID].NetOut[NET_UNRELIABLE].Alloc(NET_BUFSIZE*2); NetClients[ID].NetOut[NET_RELIABLE].Alloc(NET_BUFSIZE*2); @@ -1747,6 +1774,7 @@ begin TC^.State := NET_STATE_NONE; TC^.Peer := nil; TC^.Player := 0; + TC^.Crimes := 0; TC^.RequestedFullUpdate := False; TC^.WaitForFirstSpawn := False; TC^.NetOut[NET_UNRELIABLE].Free(); @@ -2195,6 +2223,31 @@ begin end end; +procedure g_Net_Penalize(C: pTNetClient; Reason: string); +var + s: string; +begin + e_LogWritefln('NET: client #%u (cid #%u) triggered a penalty (%d/%d): %s', + [C^.ID, C^.Player, C^.Crimes, NetAutoBanLimit, Reason]); + + if (NetAutoBanLimit <= 0) then Exit; + + Inc(C^.Crimes); + + if (NetAutoBanWarn) then + MH_SEND_Chat('You have been warned by the server: ' + Reason, NET_CHAT_SYSTEM, C^.ID); + + if (C^.Crimes >= NetAutoBanLimit) then + begin + s := '#' + IntToStr(C^.ID); // can't be arsed + g_Net_BanHost(C^.Peer^.address.host, NetAutoBanPerm); + enet_peer_disconnect(C^.Peer, NET_DISC_BAN); + g_Console_Add(Format(_lc[I_PLAYER_BAN], [s])); + MH_SEND_GameEvent(NET_EV_PLAYER_BAN, 0, s); + g_Net_Slist_ServerPlayerLeaves(); + end; +end; + procedure g_Net_DumpStart(); begin if NetMode = NET_SERVER then @@ -2238,6 +2291,9 @@ var begin Result := False; + if NetHost = nil then + exit; + if NetPortForwarded = NetHost.address.port then begin Result := True; @@ -2436,6 +2492,7 @@ initialization conRegVar('cl_interp', @NetInterpLevel, '', 'net player interpolation steps'); conRegVar('cl_last_ip', @NetClientIP, '', 'address of the last you have connected to'); conRegVar('cl_last_port', @NetClientPort, '', 'port of the last server you have connected to'); + conRegVar('cl_deafen', @NetDeafLevel, '', 'filter server messages (0-3)'); conRegVar('sv_forwardports', @NetForwardPorts, '', 'forward server port using miniupnpc (requires server restart)'); conRegVar('sv_rcon', @NetAllowRCON, '', 'enable remote console'); @@ -2444,6 +2501,10 @@ initialization conRegVar('sv_reliable_interval', @NetRelupdRate, '', 'reliable update interval'); conRegVar('sv_master_interval', @NetMasterRate, '', 'master server update interval'); + conRegVar('sv_autoban_threshold', @NetAutoBanLimit, '', 'max crimes before autoban (0 = no autoban)'); + conRegVar('sv_autoban_permanent', @NetAutoBanPerm, '', 'whether autobans are permanent'); + conRegVar('sv_autoban_warn', @NetAutoBanWarn, '', 'send warnings to the client when he triggers penalties'); + conRegVar('net_master_list', @NetMasterList, '', 'list of master servers'); SetLength(NetClients, 0);