(Network) Call fpSocket with proper address family
[mgsmtp.git] / Network.pas
index d5b458da2d5919570e2805ae5416b63eac408752..ec602d1a8995022c6c12ec3a21766d988d49f037 100644 (file)
@@ -41,6 +41,13 @@ uses Classes, Sockets, SocketUtils, DNSResolve, NetRFC, Common;
 
 const
 
+   { Address families: }
+   { These are here so users of this unit don't necessarily have to
+     use Sockets as well. }
+   AF_UNSPEC            =  Sockets.AF_UNSPEC;
+   AF_INET              =  Sockets.AF_INET;
+   AF_INET6             =  Sockets.AF_INET6;
+
    { Connection feature requests: }
    NET_TCP_BASIC        =  0;
    NET_TCP_RFCSUPPORT   =  1;
@@ -54,14 +61,14 @@ type
    TTCPConnection = class
       constructor Create; overload;
       constructor Create(const HostName: string; Port: word); overload;
-      constructor Create(Socket: socket; const Addr: TSockAddr); overload;
+      constructor Create(Socket: socket; const Addr: TSockAddr6); overload;
       destructor Destroy; override;
    private
       FConnected: boolean;
       FSocket: socket;
       FHostIP: TIPNamePair;
       FSockTimeOut: DWord;
-      SockAddr: TSockAddr;
+      SockAddr: TSockAddr6;
    public
       function Connect(const HostName: string; Port: word): boolean;
       procedure Disconnect;
@@ -99,14 +106,15 @@ type
    end;
 
    TTCPListener = class(TThread)
-      constructor Create(const Address: string; Port: word; FeatureRequest: word);
+      constructor Create(const Address: string; Port: word; Family: word; FeatureRequest: word);
       {destructor Destroy; override;}
    private
       FFeatureRequest: word;
+      FFamily: word;
       FListenAddress: string;
       FListenPort: word;
       FListenSocket: socket;
-      SockAddr: TSockAddr;
+      SockAddr: TSockAddr6;
    protected
       procedure HandleClient(Connection: TTCPConnection); virtual; abstract;
       procedure Execute; override;
@@ -137,13 +145,13 @@ begin
    Connect(HostName, Port);
 end;
 
-constructor TTCPConnection.Create(Socket: socket; const Addr: TSockAddr);
+constructor TTCPConnection.Create(Socket: socket; const Addr: TSockAddr6);
 { Use an already connected socket. }
 begin
    inherited Create;
    FSocket:= Socket;
    SockAddr:= Addr;
-   FHostIP:= TIPNamePair.Create('', NetAddrToStr(Addr.sin_addr));
+   FHostIP:= TIPNamePair.Create('', IPToStr(@Addr));
    FConnected:= true;
 end;
 
@@ -164,8 +172,9 @@ begin
 end;
 
 
-constructor TTCPListener.Create(const Address: string; Port: word; FeatureRequest: word);
+constructor TTCPListener.Create(const Address: string; Port: word; Family: word; FeatureRequest: word);
 begin
+   FFamily:= Family;
    FListenAddress:= Address;
    FListenPort:= Port;
    FFeatureRequest:= FeatureRequest;
@@ -179,26 +188,29 @@ function TTCPConnection.Connect(const HostName: string; Port: word): boolean;
 { Resolves the given hostname, and tries to connect it on the given port. }
 var GAIResult: TGAIResult;
 begin
-   FSocket:= fpSocket(af_inet, sock_stream, 0);
-   if (FSocket <> -1) then begin
-      GAIResult:= ResolveHost(HostName);
-         if GAIResult.GAIError = 0 then begin
-            SockAddr:= GAIResult.AddrInfo^.ai_addr^;
-                SockAddr.sin_port:= htons(Port);
-
-                if SockAddr.sin_addr.s_addr <> 0 then
-                   { Try to initiate connection. }
-                   FConnected:= fpConnect(FSocket, @SockAddr, SizeOf(SockAddr)) <> -1;
-
-                if FConnected then begin
-                   FHostIP:= TIPNamePair.Create(HostName, NetAddrToStr(SockAddr.sin_addr));
-                   SetSockTimeOut(FSockTimeOut);
-                end
-                else
-                   CloseSocket(FSocket);
+   GAIResult:= ResolveHost(HostName, AF_UNSPEC);
+   if GAIResult.GAIError = 0 then begin
+      Move(GAIResult.AddrInfo^.ai_addr^, SockAddr, GAIResult.AddrInfo^.ai_addrlen);
+      SockAddr.sin6_port:= htons(Port);
+
+      { Create socket. }
+      FSocket:= fpSocket(GAIResult.AddrInfo^.ai_family, SOCK_STREAM, 0);
+
+      if (FSocket <> -1) then begin
+
+         { Try to initiate connection. }
+         FConnected:= fpConnect(FSocket, @SockAddr, GAIResult.AddrInfo^.ai_addrlen) <> -1;
+
+         if FConnected then begin
+            FHostIP:= TIPNamePair.Create(HostName, IPToStr(@SockAddr));
+            SetSockTimeOut(FSockTimeOut);
+         end
+         else
+            CloseSocket(FSocket);
 
-         FreeHost(GAIResult);
       end;
+
+      FreeHost(GAIResult);
    end;
    Result:= FConnected;
 end;
@@ -217,7 +229,7 @@ procedure TTCPConnection.ReverseDNSLookup;
 var NHostIP: TIPNamePair;
 begin
    if FConnected then begin
-      NHostIP:= TIPNamePair.Create(ResolveIP(@SockAddr), FHostIP.IP);
+      NHostIP:= TIPNamePair.Create(ResolveIP(PSockAddr(@SockAddr)), FHostIP.IP);
       FHostIP.Free;
       FHostIP:= NHostIP;
    end;
@@ -227,13 +239,13 @@ function TTCPConnection.VerifyFCrDNS: boolean;
 var GAIResult: TGAIResult; ai: PAddrInfo;
 begin
    Result:= false;
-   GAIResult:= ResolveHost(HostIP.Name);
+   GAIResult:= ResolveHost(HostIP.Name, AF_UNSPEC);
    if GAIResult.GAIError = 0 then begin
       ai:= GAIResult.AddrInfo;
-         { One of the addresses must match. }
-         while (ai <> nil) and not Result do begin
-            Result:= NetAddrToStr(ai^.ai_addr^.sin_addr) = HostIP.IP;
-                ai:= ai^.ai_next;
+      { One of the addresses must match. }
+      while (ai <> nil) and not Result do begin
+         Result:= IPToStr(ai^.ai_addr) = HostIP.IP;
+         ai:= ai^.ai_next;
       end;
    end;
 end;
@@ -303,14 +315,14 @@ end;
 function TTCPListener.StartListen: boolean;
 var GAIResult: TGAIResult;
 begin
-   FListenSocket:= fpSocket(af_inet, sock_stream, 0);
+   FListenSocket:= fpSocket(FFamily, SOCK_STREAM, 0);
    if FListenSocket <> -1 then begin
-      GAIResult:= ResolveHost(FListenAddress);
-         if GAIResult.GAIError = 0 then begin
-            SockAddr:= GAIResult.AddrInfo^.ai_addr^;
-                SockAddr.sin_port:= htons(FListenPort);
+      GAIResult:= ResolveHost(FListenAddress, FFamily);
+      if GAIResult.GAIError = 0 then begin
+         Move(GAIResult.AddrInfo^.ai_addr^, SockAddr, GAIResult.AddrInfo^.ai_addrlen);
+         SockAddr.sin6_port:= htons(FListenPort);
 
-         if fpBind(FListenSocket, @SockAddr, SizeOf(SockAddr)) <> -1 then begin
+         if fpBind(FListenSocket, @SockAddr, GAIResult.AddrInfo^.ai_addrlen) <> -1 then begin
             { It seems the maximum connection value isn't enforced by the
               Free Pascal library, so this 512 is a constant, dummy value. }
             if fpListen(FListenSocket, 512) <> -1 then begin