X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_net.pas;h=292f919b9e9c5beb4981f9f073313e52ed679595;hb=0afc0aed48395daa3f4f4845b12df146dc4f3ab3;hp=44485eb48aa1363a77c17e1a896ab2ef1cc253d4;hpb=6107d1bd653921f093e4d2c81f2905f4e520f6d4;p=d2df-sdl.git diff --git a/src/game/g_net.pas b/src/game/g_net.pas index 44485eb..292f919 100644 --- a/src/game/g_net.pas +++ b/src/game/g_net.pas @@ -22,22 +22,16 @@ uses const NET_PROTOCOL_VER = 188; - NET_MAXCLIENTS = 24; - NET_CHANS = 12; - - NET_CHAN_SERVICE = 0; - NET_CHAN_IMPORTANT = 1; - NET_CHAN_GAME = 2; - NET_CHAN_PLAYER = 3; - NET_CHAN_PLAYERPOS = 4; - NET_CHAN_MONSTER = 5; - NET_CHAN_MONSTERPOS = 6; - NET_CHAN_LARGEDATA = 7; - NET_CHAN_CHAT = 8; - NET_CHAN_DOWNLOAD = 9; - NET_CHAN_SHOTS = 10; - NET_CHAN_DOWNLOAD_EX = 11; + + // NOTE: We use different channels for unreliable and reliable packets because ENet seems to + // discard preceeding RELIABLE packets if a later UNRELIABLE (but not UNSEQUENCED) packet sent + // on the same channel has arrived earlier, which is useful for occasional full-state updates. + // However, we use a separate download channel to avoid being delayed by other reliable packets. + NET_CHAN_UNRELIABLE = 2; + NET_CHAN_RELIABLE = 1; + NET_CHAN_DOWNLOAD = 11; + NET_CHANNELS = 12; // TODO: Reduce to 3 and re-enumerate channels. Requires protocol increment. NET_NONE = 0; NET_SERVER = 1; @@ -207,32 +201,30 @@ procedure g_Net_Flush(); function g_Net_Host(IPAddr: LongWord; Port: enet_uint16; MaxClients: Cardinal = 16): Boolean; procedure g_Net_Host_Die(); -procedure g_Net_Host_Send(ID: Integer; Reliable: Boolean; Chan: Byte = NET_CHAN_GAME); +procedure g_Net_Host_Send(ID: Integer; Reliable: Boolean); procedure g_Net_Host_Update(); procedure g_Net_Host_Kick(ID: Integer; Reason: enet_uint32); +procedure g_Net_Host_Ban(ID: Integer; Perm: Boolean); +procedure g_Net_Host_Ban(C: pTNetClient; Perm: Boolean); function g_Net_Connect(IP: string; Port: enet_uint16): Boolean; procedure g_Net_Disconnect(Forced: Boolean = False); -procedure g_Net_Client_Send(Reliable: Boolean; Chan: Byte = NET_CHAN_GAME); +procedure g_Net_Client_Send(Reliable: Boolean); procedure g_Net_Client_Update(); function g_Net_Client_ByName(Name: string): pTNetClient; function g_Net_Client_ByPlayer(PID: Word): pTNetClient; function g_Net_ClientName_ByID(ID: Integer): string; -procedure g_Net_SendData(Data: AByte; peer: pENetPeer; Reliable: Boolean; Chan: Byte = NET_CHAN_DOWNLOAD); -//function g_Net_Wait_Event(msgId: Word): TMemoryStream; -//function g_Net_Wait_FileInfo (var tf: TNetFileTransfer; asMap: Boolean; out resList: TStringList): Integer; - function IpToStr(IP: LongWord): string; function StrToIp(IPstr: string; var IP: LongWord): Boolean; -function g_Net_IsHostBanned(IP: LongWord; Perm: Boolean = False): Boolean; -procedure g_Net_BanHost(IP: LongWord; Perm: Boolean = True); overload; -procedure g_Net_BanHost(IP: string; Perm: Boolean = True); overload; -function g_Net_UnbanHost(IP: string): Boolean; overload; -function g_Net_UnbanHost(IP: LongWord): Boolean; overload; -procedure g_Net_UnbanNonPermHosts(); +function g_Net_IsAddressBanned(IP: LongWord; Perm: Boolean = False): Boolean; +procedure g_Net_BanAddress(IP: LongWord; Perm: Boolean = True); overload; +procedure g_Net_BanAddress(IP: string; Perm: Boolean = True); overload; +function g_Net_UnbanAddress(IP: string): Boolean; overload; +function g_Net_UnbanAddress(IP: LongWord): Boolean; overload; +procedure g_Net_UnbanNonPerm(); procedure g_Net_SaveBanList(); procedure g_Net_Penalize(C: pTNetClient; Reason: string); @@ -388,7 +380,7 @@ begin if (m.CurSize < 1) then exit; pkt := enet_packet_create(m.Data, m.CurSize, ENET_PACKET_FLAG_RELIABLE); if not Assigned(pkt) then begin killClientByFT(nc); exit; end; - if (enet_peer_send(nc.Peer, NET_CHAN_DOWNLOAD_EX, pkt) <> 0) then begin killClientByFT(nc); exit; end; + if (enet_peer_send(nc.Peer, NET_CHAN_DOWNLOAD, pkt) <> 0) then begin killClientByFT(nc); exit; end; result := true; end; @@ -402,7 +394,7 @@ begin if (m.CurSize < 1) then exit; pkt := enet_packet_create(m.Data, m.CurSize, ENET_PACKET_FLAG_RELIABLE); if not Assigned(pkt) then exit; - if (enet_peer_send(NetPeer, NET_CHAN_DOWNLOAD_EX, pkt) <> 0) then exit; + if (enet_peer_send(NetPeer, NET_CHAN_DOWNLOAD, pkt) <> 0) then exit; result := true; end; @@ -815,7 +807,7 @@ begin ENET_EVENT_TYPE_RECEIVE: begin freePacket := true; - if (ev.channelID <> NET_CHAN_DOWNLOAD_EX) then + if (ev.channelID <> NET_CHAN_DOWNLOAD) then begin //e_LogWritefln('g_Net_Wait_MapInfo: skip message from non-transfer channel', []); freePacket := false; @@ -864,7 +856,7 @@ begin rc := msg.ReadLongInt(); if (rc < 0) or (rc > 1024) then begin - e_LogWritefln('g_Net_Wait_Event: invalid number of map external resources (%d)', [rc]); + e_LogWritefln('g_Net_Wait_MapInfo: invalid number of map external resources (%d)', [rc]); Result := -1; exit; end; @@ -898,7 +890,7 @@ begin end else begin - e_LogWritefln('g_Net_Wait_Event: invalid server packet type', []); + e_LogWritefln('g_Net_Wait_MapInfo: invalid server packet type', []); Result := -1; exit; end; @@ -997,9 +989,9 @@ begin ENET_EVENT_TYPE_RECEIVE: begin freePacket := true; - if (ev.channelID <> NET_CHAN_DOWNLOAD_EX) then + if (ev.channelID <> NET_CHAN_DOWNLOAD) then begin - //e_LogWriteln('g_Net_Wait_Event: skip message from non-transfer channel'); + //e_LogWriteln('g_Net_RequestResFileInfo: skip message from non-transfer channel'); freePacket := false; g_Net_Client_HandlePacket(ev.packet, g_Net_ClientLightMsgHandler); if (g_Res_received_map_start < 0) then begin result := -666; exit; end; @@ -1009,7 +1001,7 @@ begin ett := getNewTimeoutEnd(); if (ev.packet.dataLength < 1) then begin - e_LogWriteln('g_Net_Wait_Event: invalid server packet (no data)'); + e_LogWriteln('g_Net_RequestResFileInfo: invalid server packet (no data)'); Result := -1; exit; end; @@ -1182,9 +1174,9 @@ begin ENET_EVENT_TYPE_RECEIVE: begin freePacket := true; - if (ev.channelID <> NET_CHAN_DOWNLOAD_EX) then + if (ev.channelID <> NET_CHAN_DOWNLOAD) then begin - //e_LogWritefln('g_Net_Wait_Event: skip message from non-transfer channel', []); + //e_LogWritefln('g_Net_ReceiveResourceFile: skip message from non-transfer channel', []); freePacket := false; g_Net_Client_HandlePacket(ev.packet, g_Net_ClientLightMsgHandler); if (g_Res_received_map_start < 0) then begin result := -666; exit; end; @@ -1373,7 +1365,7 @@ begin begin Readln(F, IPstr); if StrToIp(IPstr, IP) then - g_Net_BanHost(IP); + g_Net_BanAddress(IP); end; CloseFile(F); g_Net_SaveBanList(); @@ -1391,19 +1383,11 @@ var I: Integer; begin F := 0; - Chan := NET_CHAN_GAME; + Chan := NET_CHAN_UNRELIABLE; if NetMode = NET_SERVER then for T := NET_UNRELIABLE to NET_RELIABLE do begin - if NetBuf[T].CurSize > 0 then - begin - P := enet_packet_create(NetBuf[T].Data, NetBuf[T].CurSize, F); - if not Assigned(P) then continue; - enet_host_broadcast(NetHost, Chan, P); - NetBuf[T].Clear(); - end; - for I := Low(NetClients) to High(NetClients) do begin if not NetClients[I].Used then continue; @@ -1416,7 +1400,7 @@ begin // next and last iteration is always RELIABLE F := LongWord(ENET_PACKET_FLAG_RELIABLE); - Chan := NET_CHAN_IMPORTANT; + Chan := NET_CHAN_RELIABLE; end else if NetMode = NET_CLIENT then for T := NET_UNRELIABLE to NET_RELIABLE do @@ -1430,7 +1414,7 @@ begin end; // next and last iteration is always RELIABLE F := LongWord(ENET_PACKET_FLAG_RELIABLE); - Chan := NET_CHAN_IMPORTANT; + Chan := NET_CHAN_RELIABLE; end; end; @@ -1519,7 +1503,7 @@ begin NetAddr.host := IPAddr; NetAddr.port := Port; - NetHost := enet_host_create(@NetAddr, NET_MAXCLIENTS, NET_CHANS, 0, 0); + NetHost := enet_host_create(@NetAddr, NET_MAXCLIENTS, NET_CHANNELS, 0, 0); if (NetHost = nil) then begin @@ -1600,14 +1584,13 @@ begin end; -procedure g_Net_Host_Send(ID: Integer; Reliable: Boolean; Chan: Byte = NET_CHAN_GAME); +procedure g_Net_Host_Send(ID: Integer; Reliable: Boolean); var T: Integer; begin - if (Reliable) then - T := NET_RELIABLE - else - T := NET_UNRELIABLE; + if Reliable + then T := NET_RELIABLE + else T := NET_UNRELIABLE; if (ID >= 0) then begin @@ -1619,9 +1602,15 @@ begin end else begin - // write size first - NetBuf[T].Write(Integer(NetOut.CurSize)); - NetBuf[T].Write(NetOut); + for ID := Low(NetClients) to High(NetClients) do + begin + if NetClients[ID].Used then + begin + // write size first + NetClients[ID].NetOut[T].Write(Integer(NetOut.CurSize)); + NetClients[ID].NetOut[T].Write(NetOut); + end; + end; end; if NetDump then g_Net_DumpSendBuffer(); @@ -1801,7 +1790,7 @@ begin Exit; end; - if g_Net_IsHostBanned(NetEvent.Peer^.address.host) then + if g_Net_IsAddressBanned(NetEvent.Peer^.address.host) then begin g_Console_Add(_lc[I_NET_MSG] + _lc[I_NET_MSG_HOST_REJECT] + _lc[I_NET_DISC_BAN]); @@ -1851,7 +1840,7 @@ begin ENET_EVENT_TYPE_RECEIVE: begin //e_LogWritefln('RECEIVE: chan=%u', [NetEvent.channelID]); - if (NetEvent.channelID = NET_CHAN_DOWNLOAD_EX) then + if (NetEvent.channelID = NET_CHAN_DOWNLOAD) then begin ProcessDownloadExPacket(); end @@ -1937,14 +1926,13 @@ begin e_WriteLog('NET: Disconnected', TMsgType.Notify); end; -procedure g_Net_Client_Send(Reliable: Boolean; Chan: Byte = NET_CHAN_GAME); +procedure g_Net_Client_Send(Reliable: Boolean); var T: Integer; begin - if (Reliable) then - T := NET_RELIABLE - else - T := NET_UNRELIABLE; + if Reliable + then T := NET_RELIABLE + else T := NET_UNRELIABLE; // write size first NetBuf[T].Write(Integer(NetOut.CurSize)); @@ -2003,7 +1991,7 @@ begin NetInitDone := True; end; - NetHost := enet_host_create(nil, 1, NET_CHANS, 0, 0); + NetHost := enet_host_create(nil, 1, NET_CHANNELS, 0, 0); if (NetHost = nil) then begin @@ -2016,7 +2004,7 @@ begin enet_address_set_host(@NetAddr, PChar(Addr(IP[1]))); NetAddr.port := Port; - NetPeer := enet_host_connect(NetHost, @NetAddr, NET_CHANS, NET_PROTOCOL_VER); + NetPeer := enet_host_connect(NetHost, @NetAddr, NET_CHANNELS, NET_PROTOCOL_VER); if (NetPeer = nil) then begin @@ -2142,32 +2130,12 @@ begin pl := g_Player_Get(NetClients[a].Player); if pl = nil then Exit; Result := pl.Name; + Exit; end; -end; - -procedure g_Net_SendData(Data: AByte; peer: pENetPeer; Reliable: Boolean; Chan: Byte = NET_CHAN_DOWNLOAD); -var - P: pENetPacket; - F: enet_uint32; - dataLength: Cardinal; -begin - dataLength := Length(Data); - - if Reliable - then F := LongWord(ENET_PACKET_FLAG_RELIABLE) - else F := 0; - - P := enet_packet_create(@Data[0], dataLength, F); - if not Assigned(P) then exit; - - if peer <> nil - then enet_peer_send(peer, Chan, P) - else enet_host_broadcast(NetHost, Chan, P); + Result := 'Client #' + IntToStr(ID); + end; - enet_host_flush(NetHost); -end; - -function g_Net_IsHostBanned(IP: LongWord; Perm: Boolean = False): Boolean; +function g_Net_IsAddressBanned(IP: LongWord; Perm: Boolean = False): Boolean; var I: Integer; begin @@ -2182,13 +2150,13 @@ begin end; end; -procedure g_Net_BanHost(IP: LongWord; Perm: Boolean = True); overload; +procedure g_Net_BanAddress(IP: LongWord; Perm: Boolean = True); overload; var I, P: Integer; begin if IP = 0 then Exit; - if g_Net_IsHostBanned(IP, Perm) then + if g_Net_IsAddressBanned(IP, Perm) then Exit; P := -1; @@ -2209,17 +2177,17 @@ begin NetBannedHosts[P].Perm := Perm; end; -procedure g_Net_BanHost(IP: string; Perm: Boolean = True); overload; +procedure g_Net_BanAddress(IP: string; Perm: Boolean = True); overload; var a: LongWord; b: Boolean; begin b := StrToIp(IP, a); if b then - g_Net_BanHost(a, Perm); + g_Net_BanAddress(a, Perm); end; -procedure g_Net_UnbanNonPermHosts(); +procedure g_Net_UnbanNonPerm(); var I: Integer; begin @@ -2233,16 +2201,16 @@ begin end; end; -function g_Net_UnbanHost(IP: string): Boolean; overload; +function g_Net_UnbanAddress(IP: string): Boolean; overload; var a: LongWord; begin Result := StrToIp(IP, a); if Result then - Result := g_Net_UnbanHost(a); + Result := g_Net_UnbanAddress(a); end; -function g_Net_UnbanHost(IP: LongWord): Boolean; overload; +function g_Net_UnbanAddress(IP: LongWord): Boolean; overload; var I: Integer; begin @@ -2281,6 +2249,36 @@ begin end end; +procedure g_Net_Host_Ban(C: pTNetClient; Perm: Boolean); +var + KickReason: enet_uint32; + Name: string; +begin + if (not C^.Used) then + exit; + + if Perm then + KickReason := NET_DISC_BAN + else + KickReason := NET_DISC_TEMPBAN; + + Name := g_Net_ClientName_ByID(C^.ID); + + g_Net_BanAddress(C^.Peer^.address.host, Perm); + g_Net_Host_Kick(C^.ID, KickReason); + g_Console_Add(Format(_lc[I_PLAYER_BAN], [Name])); + MH_SEND_GameEvent(NET_EV_PLAYER_BAN, 0, Name); + g_Net_Slist_ServerPlayerLeaves(); + g_Net_SaveBanList(); +end; + +procedure g_Net_Host_Ban(ID: Integer; Perm: Boolean); +begin + if (ID < 0) or (ID > High(NetClients)) then + exit; + g_Net_Host_Ban(@NetClients[ID], Perm); +end; + procedure g_Net_Penalize(C: pTNetClient; Reason: string); var s: string; @@ -2306,12 +2304,7 @@ begin if (C^.Crimes >= NetAutoBanLimit) then begin - s := '#' + IntToStr(C^.ID); // can't be arsed - g_Net_BanHost(C^.Peer^.address.host, NetAutoBanPerm); - g_Net_Host_Kick(C^.ID, 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;