summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 19e6ceb)
raw | patch | inline | side by side (parent: 19e6ceb)
author | fgsfds <pvt.fgsfds@gmail.com> | |
Mon, 5 Feb 2018 16:38:30 +0000 (19:38 +0300) | ||
committer | fgsfds <pvt.fgsfds@gmail.com> | |
Mon, 5 Feb 2018 16:38:30 +0000 (19:38 +0300) |
src/game/Doom2DF.lpr | patch | blob | history | |
src/game/g_net.pas | patch | blob | history | |
src/lib/miniupnpc/miniupnpc.pas | [new file with mode: 0644] | patch | blob |
diff --git a/src/game/Doom2DF.lpr b/src/game/Doom2DF.lpr
index 7cbb675bd6f16d96f2506d1223b31fd31cddf9e2..429c5f0cedc70f4af59855200e987197363db4bc 100644 (file)
--- a/src/game/Doom2DF.lpr
+++ b/src/game/Doom2DF.lpr
math,
GL,
GLExt,
+ miniupnpc in '../lib/miniupnpc/miniupnpc.pas',
SDL2 in '../lib/sdl2/sdl2.pas',
{$IFDEF USE_SDLMIXER}
SDL2_mixer in '../lib/sdl2/SDL2_mixer.pas',
diff --git a/src/game/g_net.pas b/src/game/g_net.pas
index cbf5120782839a5703caa116a5d0041465411410..93525c990b7913d41175c6f7ee67d724f713ce7a 100644 (file)
--- a/src/game/g_net.pas
+++ b/src/game/g_net.pas
interface
uses
- e_log, e_msg, ENet, Classes, MAPDEF;
+ e_log, e_msg, ENet, miniupnpc, Classes, MAPDEF;
const
NET_PROTOCOL_VER = 173;
NetForcePlayerUpdate: Boolean = False;
NetPredictSelf: Boolean = True;
- NetGotKeys: Boolean = False;
+ NetForwardPorts: Boolean = False;
NetGotEverything: Boolean = False;
+ NetGotKeys: Boolean = False;
+
+ NetPortForwarded: Word = 0;
+ NetPongForwarded: Boolean = False;
+ NetIGDControl: AnsiString;
+ NetIGDService: TURLStr;
NetDumpFile: TStream;
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
NetMode := NET_NONE;
+ g_Net_UnforwardPorts();
+
if NetDump then
g_Net_DumpEnd();
end;
NetAddr.host := IPAddr;
NetAddr.port := Port;
+ if NetForwardPorts then g_Net_ForwardPorts();
+
NetHost := enet_host_create(@NetAddr, NET_MAXCLIENTS, NET_CHANS, 0, 0);
if (NetHost = nil) then
NetDumpFile := nil;
end;
+function g_Net_ForwardPorts(ForwardPongPort: Boolean = True): Boolean;
+var
+ DevList: PUPNPDev;
+ Urls: TUPNPUrls;
+ Data: TIGDDatas;
+ LanAddr: array [0..255] of Char;
+ ExtAddr: array [0..40] of Char;
+ StrPort: AnsiString;
+ Err, I: Integer;
+begin
+ Result := False;
+
+ if NetPortForwarded = NetPort then
+ begin
+ Result := True;
+ exit;
+ end;
+
+ conwriteln('trying to forward server ports...');
+
+ NetPongForwarded := False;
+ NetPortForwarded := 0;
+
+ DevList := upnpDiscover(2000, nil, nil, 0, 0, Addr(Err));
+ if DevList = nil then
+ begin
+ conwritefln(' upnpDiscover() failed: %d', [Err]);
+ exit;
+ end;
+
+ I := UPNP_GetValidIGD(DevList, @Urls, @Data, Addr(LanAddr[0]), 256);
+
+ if I = 0 then
+ begin
+ conwriteln(' could not find an IGD device on this LAN, aborting');
+ FreeUPNPDevList(DevList);
+ FreeUPNPUrls(@Urls);
+ exit;
+ end
+ else if I = 1 then
+ conwritefln(' found IGD @ %s', [Urls.controlURL])
+ else
+ conwritefln(' found some kind of UPNP device @ %s, maybe it''ll work', [Urls.controlURL]);
+
+ UPNP_GetExternalIPAddress(Urls.controlURL, Addr(data.first.servicetype[1]), Addr(ExtAddr[0]));
+ if ExtAddr[0] <> #0 then
+ conwritefln(' external IP address: %s', [Addr(ExtAddr[0])]);
+
+ 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(NetPort + 1);
+ 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;
+
+procedure g_Net_UnforwardPorts();
+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;
+
initialization
NetIn.Alloc(NET_BUFSIZE);
diff --git a/src/lib/miniupnpc/miniupnpc.pas b/src/lib/miniupnpc/miniupnpc.pas
--- /dev/null
@@ -0,0 +1,213 @@
+{$DEFINE LIBMINIUPNPC_WINDOZE_STATIC}
+
+{$MODE OBJFPC}
+{$PACKRECORDS C}
+
+{$IFDEF WIN32}
+ {$DEFINE MSWINDOWS}
+{$ENDIF}
+
+{$LONGSTRINGS ON}
+{$MACRO ON}
+
+{$Z4} // Force four-byte enums
+
+unit miniupnpc;
+
+interface
+
+{$IFDEF MSWINDOWS}
+ {$IFDEF LIBMINIUPNPC_WINDOZE_STATIC}
+ {$LINKLIB libminiupnpc.a}
+ {$LINKLIB libiphlpapi.a}
+ {$DEFINE MINIUPNPC_IMPL := cdecl; external}
+ {$ELSE}
+ {$DEFINE MINIUPNPC_IMPL := cdecl; external 'miniupnpc.dll'}
+ {$ENDIF}
+{$ELSE}
+ {$DEFINE MINIUPNPC_IMPL := cdecl; external 'miniupnpc'}
+{$ENDIF}
+
+const MINIUPNPC_URL_MAXSIZE=128;
+Type
+ PUPNPDev = ^TUPNPDev;
+ TUPNPDev = record
+ pNext:PUPNPDev;
+ descURL:pchar;
+ st:pchar;
+ scope_id:word;
+ buffer:array[0..1] of byte;
+ end;
+
+ PUPNPUrls = ^TUPNPUrls;
+ TUPNPUrls = record
+ controlURL:pchar;
+ ipcondescURL:pchar;
+ controlURL_CIF:pchar;
+ controlURL_6FC:pchar;
+ rootdescURL:pchar;
+ end;
+ TUrlStr = array [1..MINIUPNPC_URL_MAXSIZE] of char;
+ TIGDdatas_service = record
+ controlurl : TUrlStr;
+ eventsuburl: TUrlStr;
+ scpdurl: TUrlStr;
+ servicetype: TUrlStr;
+ //char devicetype[MINIUPNPC_URL_MAXSIZE];
+ end;
+
+ PIGDdatas = ^TIGDdatas;
+ TIGDdatas = record
+ cureltname: TUrlStr;
+ urlbase: TUrlStr;
+ presentationurl : TUrlStr;
+ level:integer;
+ //int state;
+ //"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1"
+ CIF : TIGDdatas_service;
+ // "urn:schemas-upnp-org:service:WANIPConnection:1"
+ // "urn:schemas-upnp-org:service:WANPPPConnection:1"
+ first: TIGDdatas_service;
+ //if both WANIPConnection and WANPPPConnection are present
+ second: TIGDdatas_service;
+ //"urn:schemas-upnp-org:service:WANIPv6FirewallControl:1"
+ IPv6FC : TIGDdatas_service;
+ // tmp
+ tmp: TIGDdatas_service;
+ end;
+
+(* upnpDiscover()
+ * discover UPnP devices on the network.
+ * The discovered devices are returned as a chained list.
+ * It is up to the caller to free the list with freeUPNPDevlist().
+ * delay (in millisecond) is the maximum time for waiting any device
+ * response.
+ * If available, device list will be obtained from MiniSSDPd.
+ * Default path for minissdpd socket will be used if minissdpdsock argument
+ * is NULL.
+ * If multicastif is not NULL, it will be used instead of the default
+ * multicast interface for sending SSDP discover packets.
+ * If sameport is not null, SSDP packets will be sent from the source port
+ * 1900 (same as destination port) otherwise system assign a source port. *)
+function upnpDiscover(
+ delay:integer;
+ multicastif:pchar;
+ minissdpdsock:pchar;
+ sameport:integer;
+ IPV6:integer;
+ error:pinteger):PUPNPDev; MINIUPNPC_IMPL;
+
+
+(* UPNP_GetValidIGD() :
+ * return values :
+ * 0 = NO IGD found
+ * 1 = A valid connected IGD has been found
+ * 2 = A valid IGD has been found but it reported as
+ * not connected
+ * 3 = an UPnP device has been found but was not recognized as an IGD
+ *
+ * In any non zero return case, the urls and data structures
+ * passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to
+ * free allocated memory.
+ *)
+function UPNP_GetValidIGD(
+ devlist:PUPNPDev;
+ urls:PUPNPUrls;
+ data:PIGDdatas;
+ lanaddr:pchar;
+ lanaddrlen:integer):integer; MINIUPNPC_IMPL;
+
+
+(* UPNP_GetExternalIPAddress() call the corresponding UPNP method.
+ * if the third arg is not null the value is copied to it.
+ * at least 16 bytes must be available
+ *
+ * Return values :
+ * 0 : SUCCESS
+ * NON ZERO : ERROR Either an UPnP error code or an unknown error.
+ *
+ * possible UPnP Errors :
+ * 402 Invalid Args - See UPnP Device Architecture section on Control.
+ * 501 Action Failed - See UPnP Device Architecture section on Control. *)
+function UPNP_GetExternalIPAddress(
+ controlURL:pchar;
+ servicetype:pchar;
+ extIpAdd:pchar):integer; MINIUPNPC_IMPL;
+
+
+(* UPNP_AddPortMapping()
+ * if desc is NULL, it will be defaulted to "libminiupnpc"
+ * remoteHost is usually NULL because IGD don't support it.
+ *
+ * Return values :
+ * 0 : SUCCESS
+ * NON ZERO : ERROR. Either an UPnP error code or an unknown error.
+ *
+ * List of possible UPnP errors for AddPortMapping :
+ * errorCode errorDescription (short) - Description (long)
+ * 402 Invalid Args - See UPnP Device Architecture section on Control.
+ * 501 Action Failed - See UPnP Device Architecture section on Control.
+ * 715 WildCardNotPermittedInSrcIP - The source IP address cannot be
+ * wild-carded
+ * 716 WildCardNotPermittedInExtPort - The external port cannot be wild-carded
+ * 718 ConflictInMappingEntry - The port mapping entry specified conflicts
+ * with a mapping assigned previously to another client
+ * 724 SamePortValuesRequired - Internal and External port values
+ * must be the same
+ * 725 OnlyPermanentLeasesSupported - The NAT implementation only supports
+ * permanent lease times on port mappings
+ * 726 RemoteHostOnlySupportsWildcard - RemoteHost must be a wildcard
+ * and cannot be a specific IP address or DNS name
+ * 727 ExternalPortOnlySupportsWildcard - ExternalPort must be a wildcard and
+ * cannot be a specific port value *)
+
+function UPNP_AddPortMapping(
+ controlURL:pchar;
+ servicetype:pchar;
+ extPort:pchar;
+ inPort:pchar;
+ inClient:pchar;
+ desc:pchar;
+ proto:pchar;
+ remoteHost:pchar;
+ leaseDuration:pchar):integer; MINIUPNPC_IMPL;
+
+(* UPNP_DeletePortMapping()
+ * Use same argument values as what was used for AddPortMapping().
+ * remoteHost is usually NULL because IGD don't support it.
+ * Return Values :
+ * 0 : SUCCESS
+ * NON ZERO : error. Either an UPnP error code or an undefined error.
+ *
+ * List of possible UPnP errors for DeletePortMapping :
+ * 402 Invalid Args - See UPnP Device Architecture section on Control.
+ * 714 NoSuchEntryInArray - The specified value does not exist in the array *)
+
+function UPNP_DeletePortMapping(
+ controlURL:pchar;
+ servicetype:pchar;
+ extPort:pchar;
+ proto:pchar;
+ remoteHost:pchar):integer; MINIUPNPC_IMPL;
+
+
+
+function UPNP_GetGenericPortMappingEntry(
+ const controlURL :pchar;
+ const servicetype:pchar;
+ index:pchar;
+ extPort:pchar;
+ intClient:pchar;
+ intPort:pchar;
+ protocol:pchar;
+ desc:pchar;
+ enabled:pchar;
+ rHost:pchar;
+ duration:pchar):integer; MINIUPNPC_IMPL;
+
+procedure FreeUPNPUrls(urls: PUPNPUrls); MINIUPNPC_IMPL;
+procedure freeUPNPDevlist(devl: PUPNPDev); MINIUPNPC_IMPL;
+
+implementation
+
+end.