1

I want to Port Forward a port to an open server connection in Delphi (I'm using TServerSocket).

I'm using this procedure that I found in another StackOverflow question:

procedure AddUPnPEntry(Port: Integer; const Name: ShortString; LAN_IP: string);
var
  Nat: Variant;
  Ports: Variant;
begin
  if not (LAN_IP = '127.0.0.1') then
    begin
      Nat   := CreateOleObject('HNetCfg.NATUPnP');
      Ports := Nat.StaticPortMappingCollection;
      if not VarIsClear(Ports) then
        begin
          CoInitialize(nil);
          try
            ShowMessage(IntToStr(Ports.count));
            Ports.Add(Port,'TCP',Port,LAN_IP,True,name);
          finally
            CoUninitialize;
          end;
        end;
    end;
end;

I've already tried reading MSDN's documentation, using different code snippets (similar to this).

I want to understand why this code doesn't work. All I get is an Access Violation error message.

Just some extra info:

My router does support UPnP. I'm using Windows 7 and Delphi 7.

Claaaudio
  • 63
  • 6
  • The most likely culprit is the `Nat.StaticPortMappingCollection` property returning a `nil` interface pointer. You are not checking the `Ports` variable for that possibility before accessing the `Ports.Count` value. And BTW, you need to call `CoInitialize()` above the `try` and `CoUninitialize()` after the `except` block (I suggest using a `try..finally` for that), and make sure you empty the `Nat` and `Ports` variables before calling `CoUninitialize()`. – Remy Lebeau Apr 02 '19 at 19:41
  • I just tried and I still got acess violation. I also tried just running ```Ports.Add(Port,'TCP',Port,LAN_IP,True,name); ``` and didn't get any results. Is there something I'm missing? Am I'm using NatUPnP correctly? – Claaaudio Apr 02 '19 at 20:06
  • "*I just tried and I still got acess violation*" - tried WHAT exactly? Please be more specific. Update your question to show the updated code you are using. Did you see [this answer](https://stackoverflow.com/a/12806179/65863) to [this question](https://stackoverflow.com/questions/12805067/)? That question looks awful similar to the code you are using, but the answer shows the `Variant` check I mentioned above. – Remy Lebeau Apr 02 '19 at 20:25
  • I'll check it out. – Claaaudio Apr 02 '19 at 20:29
  • I updated the code snippet showing what I did but the function returns that the ```Ports``` variable is empty($0000000) and it just doesn't try to open the port. I'm confused on what I should be doing, should I start looking for another solution? – Claaaudio Apr 02 '19 at 20:41
  • You need to call `CoInitialize()` before calling `CreateOleObject()`. You didn't need to change that part of the code, just to add a check to make sure `Ports` was not empty before calling `Ports.Count` or `Ports.Add()`, eg: `OleCheck(CoInitialize(nil)); try Nat := CreateOleObject('HNetCfg.NATUPnP'); try Ports := Nat.StaticPortMappingCollection; if not VarIsClear(Ports) then begin try { use Ports as needed } finally Ports := Unassigned; end; finally Nat := Unassigned; end; finally CoUninitialize; end;` – Remy Lebeau Apr 02 '19 at 20:57

1 Answers1

2

I recommend using the Id-Components as they have the easy to use forwarding feautures. Attached are an example for TCP and UDP forwarding. You will need to fill out the server to forward to as well as the port on your machine and the port you want to forward it to on the server.

uses
IdMappedPortUDP, IdMappedPortTCP;


tcpForwader: TIdMappedPortTCP;     
udpForwader: TIdMappedPortUDP;

tcpForwader             := TIdMappedPortTCP.Create(nil);
tcpForwader.MappedHost  := <ServerToForwardTo>;
tcpForwader.MappedPort  := <PortOnServer>;
tcpForwader.DefaultPort := <LocalPort>;
tcpForwader.Active      := True;

udpForwader                := TIdMappedPortUDP.Create(nil);
udpForwader.MappedHost     := <ServerToForwardTo>;
udpForwader.MappedPort     := <PortOnServer>;
udpForwader.DefaultPort    := <LocalPort>;
udpForwader.Active         := True;
Andreas S.
  • 39
  • 3