summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: bd64003)
raw | patch | inline | side by side (parent: bd64003)
author | Stas'M <x86corez@gmail.com> | |
Fri, 18 May 2018 10:35:41 +0000 (13:35 +0300) | ||
committer | Stas'M <x86corez@gmail.com> | |
Fri, 18 May 2018 10:50:02 +0000 (13:50 +0300) |
src/game/g_net.pas | patch | blob | history | |
src/game/g_netmaster.pas | patch | blob | history |
diff --git a/src/game/g_net.pas b/src/game/g_net.pas
index b9f28b981c9bccac022b724867106534932cc390..fc5287a4dacc8708686611304a0a76afaa10706c 100644 (file)
--- a/src/game/g_net.pas
+++ b/src/game/g_net.pas
e_log, e_msg, ENet, Classes, MAPDEF{$IFDEF USE_MINIUPNPC}, miniupnpc;{$ELSE};{$ENDIF}
const
- NET_PROTOCOL_VER = 173;
+ NET_PROTOCOL_VER = 174;
NET_MAXCLIENTS = 24;
NET_CHANS = 11;
NET_CLIENT = 2;
NET_BUFSIZE = $FFFF;
+ NET_PING_PORT = $DF2D;
NET_EVERYONE = -1;
if NetPongSock <> ENET_SOCKET_NULL then
begin
NetPongAddr.host := IPAddr;
- NetPongAddr.port := Port + 1;
+ NetPongAddr.port := NET_PING_PORT;
if enet_socket_bind(NetPongSock, @NetPongAddr) < 0 then
begin
enet_socket_destroy(NetPongSock);
NetOut.Clear();
NetOut.Write(Byte(Ord('D')));
NetOut.Write(Byte(Ord('F')));
+ NetOut.Write(NetPort);
NetOut.Write(ClTime);
g_Net_Slist_WriteInfo();
NPl := 0;
Result := 0;
if NetUseMaster then
- begin
g_Net_Slist_Check;
- g_Net_Host_CheckPings;
- end;
+ g_Net_Host_CheckPings;
while (enet_host_service(NetHost, @NetEvent, 0) > 0) do
begin
if ForwardPongPort then
begin
- StrPort := IntToStr(NetPort + 1);
+ StrPort := IntToStr(NET_PING_PORT);
I := UPNP_AddPortMapping(
Urls.controlURL, Addr(data.first.servicetype[1]),
PChar(StrPort), PChar(StrPort), Addr(LanAddr[0]), PChar('D2DF'),
index f4ce7984547a0362e13b66e2d6a2885a67b1ce1d..2e26b3a4911353ed68525980b511e80f984e2445 100644 (file)
--- a/src/game/g_netmaster.pas
+++ b/src/game/g_netmaster.pas
enet_socket_send(Sock, Addr(S.PingAddr), @Buf, 1);
end;
+procedure PingBcast(Sock: ENetSocket);
+var
+ S: TNetServer;
+begin
+ S.IP := '255.255.255.255';
+ S.Port := NET_PING_PORT;
+ enet_address_set_host(Addr(S.PingAddr), PChar(Addr(S.IP[1])));
+ S.Ping := -1;
+ S.PingAddr.port := S.Port;
+ PingServer(S, Sock);
+end;
+
function g_Net_Slist_Fetch(var SL: TNetServerList): Boolean;
var
Cnt: Byte;
Buf: ENetBuffer;
InMsg: TMsg;
SvAddr: ENetAddress;
+ FromSL: Boolean;
+
+ procedure ProcessLocal();
+ var
+ IPBuf: Array[0..19] of Byte;
+ begin
+ I := Length(SL);
+ SetLength(SL, I + 1);
+ with SL[I] do
+ begin
+ FillChar(IPBuf, Length(IPBuf), 0);
+ enet_address_get_host_ip(Addr(SvAddr.host), PChar(Addr(IPBuf)), Length(IPBuf));
+ IP := PChar(Addr(IPBuf));
+ Port := InMsg.ReadWord();
+ Ping := InMsg.ReadInt64();
+ Ping := GetTimerMS() - Ping;
+ Name := InMsg.ReadString();
+ Map := InMsg.ReadString();
+ GameMode := InMsg.ReadByte();
+ Players := InMsg.ReadByte();
+ MaxPlayers := InMsg.ReadByte();
+ Protocol := InMsg.ReadByte();
+ Password := InMsg.ReadByte() = 1;
+ LocalPl := InMsg.ReadByte();
+ Bots := InMsg.ReadWord();
+ end;
+ end;
+ procedure CheckLocalServers();
+ begin
+ SetLength(SL, 0);
+
+ Sock := enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM);
+ if Sock = ENET_SOCKET_NULL then Exit;
+ enet_socket_set_option(Sock, ENET_SOCKOPT_NONBLOCK, 1);
+ enet_socket_set_option(Sock, ENET_SOCKOPT_BROADCAST, 1);
+ PingBcast(Sock);
+
+ T := GetTimerMS();
+
+ InMsg.Alloc(NET_BUFSIZE);
+ Buf.data := InMsg.Data;
+ Buf.dataLength := InMsg.MaxSize;
+ while GetTimerMS() - T <= 500 do
+ begin
+ InMsg.Clear();
+
+ RX := enet_socket_receive(Sock, @SvAddr, @Buf, 1);
+ if RX <= 0 then continue;
+ InMsg.CurSize := RX;
+
+ InMsg.BeginReading();
+
+ if InMsg.ReadChar() <> 'D' then continue;
+ if InMsg.ReadChar() <> 'F' then continue;
+
+ ProcessLocal();
+ end;
+
+ InMsg.Free();
+ enet_socket_destroy(Sock);
+
+ if Length(SL) = 0 then SL := nil;
+ end;
begin
Result := False;
SL := nil;
if (NetMHost <> nil) or (NetMPeer <> nil) then
+ begin
+ CheckLocalServers();
Exit;
+ end;
if not g_Net_Slist_Connect then
+ begin
+ CheckLocalServers();
Exit;
+ end;
e_WriteLog('Fetching serverlist...', TMsgType.Notify);
g_Console_Add(_lc[I_NET_MSG] + _lc[I_NET_SLIST_FETCH]);
SL[I].Password := InMsg.ReadByte() = 1;
enet_address_set_host(Addr(SL[I].PingAddr), PChar(Addr(SL[I].IP[1])));
SL[I].Ping := -1;
- SL[I].PingAddr.port := SL[I].Port + 1;
+ SL[I].PingAddr.port := NET_PING_PORT;
end;
end;
g_Net_Slist_Disconnect;
NetOut.Clear();
- if Length(SL) = 0 then Exit;
+ if Length(SL) = 0 then
+ begin
+ CheckLocalServers();
+ Exit;
+ end;
Sock := enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM);
if Sock = ENET_SOCKET_NULL then Exit;
for I := Low(SL) to High(SL) do
PingServer(SL[I], Sock);
+ enet_socket_set_option(Sock, ENET_SOCKOPT_BROADCAST, 1);
+ PingBcast(Sock);
+
T := GetTimerMS();
InMsg.Alloc(NET_BUFSIZE);
Buf.data := InMsg.Data;
Buf.dataLength := InMsg.MaxSize;
Cnt := 0;
- while Cnt < Length(SL) do
+ while GetTimerMS() - T <= 500 do
begin
- if GetTimerMS() - T > 500 then break;
-
InMsg.Clear();
RX := enet_socket_receive(Sock, @SvAddr, @Buf, 1);
if InMsg.ReadChar() <> 'D' then continue;
if InMsg.ReadChar() <> 'F' then continue;
+ FromSL := False;
for I := Low(SL) to High(SL) do
if (SL[I].PingAddr.host = SvAddr.host) and
(SL[I].PingAddr.port = SvAddr.port) then
begin
with SL[I] do
begin
+ Port := InMsg.ReadWord();
Ping := InMsg.ReadInt64();
Ping := GetTimerMS() - Ping;
Name := InMsg.ReadString();
LocalPl := InMsg.ReadByte();
Bots := InMsg.ReadWord();
end;
+ FromSL := True;
Inc(Cnt);
break;
end;
+ if not FromSL then
+ ProcessLocal();
end;
InMsg.Free();
slWaitStr := _lc[I_NET_SLIST_NOSERVERS];
end
else
- slWaitStr := _lc[I_NET_SLIST_ERROR];
+ if SL = nil then
+ slWaitStr := _lc[I_NET_SLIST_ERROR];
slFetched := True;
slSelection := 0;
end;