X-Git-Url: http://deadsoftware.ru/gitweb?p=d2df-sdl.git;a=blobdiff_plain;f=src%2Fgame%2Fg_net.pas;h=c15df2bae9406b2cc043fce515bdc11b113b21da;hp=85263e51e7e709388809188f5c664c832f9f84e3;hb=ef4db75afec0dcd71f0bbe75b5f0b20537c8eac1;hpb=d7d166dc3cd287276202e862746208892c4cc89f diff --git a/src/game/g_net.pas b/src/game/g_net.pas index 85263e5..c15df2b 100644 --- a/src/game/g_net.pas +++ b/src/game/g_net.pas @@ -1,4 +1,4 @@ -(* Copyright (C) DooM 2D:Forever Developers +(* Copyright (C) Doom 2D: Forever Developers * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,10 +19,10 @@ unit g_net; interface uses - e_log, e_msg, ENet, Classes, MAPDEF; + 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; @@ -44,6 +44,7 @@ const NET_CLIENT = 2; NET_BUFSIZE = $FFFF; + NET_PING_PORT = $DF2D; NET_EVERYONE = -1; @@ -65,6 +66,12 @@ const BANLIST_FILENAME = 'banlist.txt'; NETDUMP_FILENAME = 'netdump'; + {$IFDEF FREEBSD} + NilThreadId = nil; + {$ELSE} + NilThreadId = 0; + {$ENDIF} + type TNetClient = record ID: Byte; @@ -136,9 +143,19 @@ var NetForcePlayerUpdate: Boolean = False; NetPredictSelf: Boolean = True; - NetGotKeys: Boolean = False; + NetForwardPorts: Boolean = False; NetGotEverything: Boolean = False; + NetGotKeys: Boolean = False; + +{$IFDEF USE_MINIUPNPC} + NetPortForwarded: Word = 0; + NetPongForwarded: Boolean = False; + NetIGDControl: AnsiString; + NetIGDService: TURLStr; +{$ENDIF} + + NetPortThread: TThreadID = NilThreadId; NetDumpFile: TStream; @@ -162,7 +179,7 @@ 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); +procedure g_Net_SendData(Data: AByte; peer: pENetPeer; Reliable: Boolean; Chan: Byte = NET_CHAN_DOWNLOAD); function g_Net_Wait_Event(msgId: Word): TMemoryStream; function IpToStr(IP: LongWord): string; @@ -181,6 +198,9 @@ procedure g_Net_DumpSendBuffer(); procedure g_Net_DumpRecvBuffer(Buf: penet_uint8; Len: LongWord); procedure g_Net_DumpEnd(); +function g_Net_ForwardPorts(ForwardPongPort: Boolean = True): Boolean; +procedure g_Net_UnforwardPorts(); + implementation uses @@ -305,6 +325,12 @@ begin NetMode := NET_NONE; + if NetPortThread <> NilThreadId then + WaitForThreadTerminate(NetPortThread, 66666); + + NetPortThread := NilThreadId; + g_Net_UnforwardPorts(); + if NetDump then g_Net_DumpEnd(); end; @@ -321,6 +347,12 @@ end; { /// SERVER FUNCTIONS /// } +function ForwardThread(Param: Pointer): PtrInt; +begin + Result := 0; + if not g_Net_ForwardPorts() then Result := -1; +end; + function g_Net_Host(IPAddr: LongWord; Port: enet_uint16; MaxClients: Cardinal = 16): Boolean; begin if NetMode <> NET_NONE then @@ -348,6 +380,8 @@ 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 @@ -362,7 +396,7 @@ begin 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); @@ -477,6 +511,7 @@ begin NetOut.Clear(); NetOut.Write(Byte(Ord('D'))); NetOut.Write(Byte(Ord('F'))); + NetOut.Write(NetPort); NetOut.Write(ClTime); g_Net_Slist_WriteInfo(); NPl := 0; @@ -505,10 +540,8 @@ begin 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 @@ -789,9 +822,7 @@ begin ProcessLoading(true); - e_PollInput(); - - if e_KeyPressed(IK_ESCAPE) or e_KeyPressed(IK_SPACE) then + if e_KeyPressed(IK_ESCAPE) or e_KeyPressed(IK_SPACE) or e_KeyPressed(VK_ESCAPE) then OuterLoop := False; end; @@ -876,7 +907,7 @@ begin end; end; -procedure g_Net_SendData(Data:AByte; peer: pENetPeer; Reliable: Boolean; Chan: Byte = NET_CHAN_DOWNLOAD); +procedure g_Net_SendData(Data: AByte; peer: pENetPeer; Reliable: Boolean; Chan: Byte = NET_CHAN_DOWNLOAD); var P: pENetPacket; F: enet_uint32; @@ -954,9 +985,7 @@ begin ProcessLoading(true); - e_PollInput(); - - if e_KeyPressed(IK_ESCAPE) or e_KeyPressed(IK_SPACE) then + if e_KeyPressed(IK_ESCAPE) or e_KeyPressed(IK_SPACE) or e_KeyPressed(VK_ESCAPE) then break; end; Result := msgStream; @@ -1101,6 +1130,130 @@ begin NetDumpFile := nil; end; +function g_Net_ForwardPorts(ForwardPongPort: Boolean = True): Boolean; +{$IFDEF USE_MINIUPNPC} +var + DevList: PUPNPDev; + Urls: TUPNPUrls; + Data: TIGDDatas; + LanAddr: array [0..255] of Char; + StrPort: AnsiString; + Err, I: Integer; +begin + Result := False; + + if NetPortForwarded = NetPort then + begin + Result := True; + exit; + end; + + NetPongForwarded := False; + NetPortForwarded := 0; + + DevList := upnpDiscover(1000, nil, nil, 0, 0, 2, Addr(Err)); + if DevList = nil then + begin + conwritefln('port forwarding failed: upnpDiscover() failed: %d', [Err]); + exit; + end; + + I := UPNP_GetValidIGD(DevList, @Urls, @Data, Addr(LanAddr[0]), 256); + + if I = 0 then + begin + conwriteln('port forwarding failed: could not find an IGD device on this LAN'); + FreeUPNPDevList(DevList); + FreeUPNPUrls(@Urls); + exit; + end; + + StrPort := IntToStr(NetPort); + I := UPNP_AddPortMapping( + Urls.controlURL, Addr(data.first.servicetype[1]), + PChar(StrPort), PChar(StrPort), Addr(LanAddr[0]), PChar('D2DF'), + PChar('UDP'), nil, PChar('0') + ); + + if I <> 0 then + begin + conwritefln('forwarding port %d failed: error %d', [NetPort, I]); + FreeUPNPDevList(DevList); + FreeUPNPUrls(@Urls); + exit; + end; + + if ForwardPongPort then + begin + StrPort := IntToStr(NET_PING_PORT); + I := UPNP_AddPortMapping( + Urls.controlURL, Addr(data.first.servicetype[1]), + PChar(StrPort), PChar(StrPort), Addr(LanAddr[0]), PChar('D2DF'), + PChar('UDP'), nil, PChar('0') + ); + + if I <> 0 then + begin + conwritefln('forwarding port %d failed: error %d', [NetPort + 1, I]); + NetPongForwarded := False; + end + else + begin + conwritefln('forwarded port %d successfully', [NetPort + 1]); + NetPongForwarded := True; + end; + end; + + conwritefln('forwarded port %d successfully', [NetPort]); + NetIGDControl := AnsiString(Urls.controlURL); + NetIGDService := data.first.servicetype; + NetPortForwarded := NetPort; + + FreeUPNPDevList(DevList); + FreeUPNPUrls(@Urls); + Result := True; +end; +{$ELSE} +begin + Result := False; +end; +{$ENDIF} + +procedure g_Net_UnforwardPorts(); +{$IFDEF USE_MINIUPNPC} +var + I: Integer; + StrPort: AnsiString; +begin + if NetPortForwarded = 0 then Exit; + + conwriteln('unforwarding ports...'); + + StrPort := IntToStr(NetPortForwarded); + I := UPNP_DeletePortMapping( + PChar(NetIGDControl), Addr(NetIGDService[1]), + PChar(StrPort), PChar('UDP'), nil + ); + conwritefln(' port %d: %d', [NetPortForwarded, I]); + + if NetPongForwarded then + begin + NetPongForwarded := False; + StrPort := IntToStr(NetPortForwarded + 1); + I := UPNP_DeletePortMapping( + PChar(NetIGDControl), Addr(NetIGDService[1]), + PChar(StrPort), PChar('UDP'), nil + ); + conwritefln(' port %d: %d', [NetPortForwarded + 1, I]); + end; + + NetPortForwarded := 0; +end; +{$ELSE} +begin +end; +{$ENDIF} + initialization NetIn.Alloc(NET_BUFSIZE);