FTimeOffset: integer;
FTimeOffsetStr: string;
FListenAddresses, FListenAddresses6: TStrings;
+ FBindAddress, FBindAddress6: string;
public
function GetVersionStr: string;
property ListenAddresses: TStrings read FListenAddresses;
property ListenAddresses6: TStrings read FListenAddresses6;
+ property BindAddress: string read FBindAddress;
+ property BindAddress6: string read FBindAddress6;
property Databytes: longint read FDatabytes;
{property TimeCorrection: integer read FTimeCorrection;}
property TimeOffset: integer read FTimeOffset;
FListenAddresses6.Delimiter:= ',';
FListenAddresses6.DelimitedText:= Config.ReadString('Server', 'ListenAddress6', '');
+ FBindAddress:= Config.ReadString('Server', 'BindAddress', '0.0.0.0');
+ FBindAddress6:= Config.ReadString('Server', 'BindAddress6', '[::]');
+
FDatabytes:= Config.ReadInteger('Server', 'Databytes', 1024 * 1024 * 1024);
FTimeOffset:= Config.ReadInteger('Server', 'TimeOffset', Config.ReadInteger('Server', 'TimeCorrection', 0) * 100);
FTimeOffsetStr:= MakeTimeOffsetStr(FTimeOffset);
unit Network;
interface
-uses Classes, Sockets, SocketUtils, DNSResolve, NetRFC, Common;
+uses Classes, Sockets, SocketUtils, ctypes, DNSResolve, NetRFC, Common;
const
TTCPConnection = class
constructor Create; overload;
constructor Create(const HostName: string; Port: word); overload;
- constructor Create(Socket: socket; const Addr: TSockAddr6); overload;
+ constructor Create(Socket: socket); overload;
destructor Destroy; override;
private
FConnected: boolean;
FSocket: socket;
FHostIP: TIPNamePair;
FSockTimeOut: DWord;
- SockAddr: TSockAddr6;
+ SrcSockAddr: TSockAddr;
+ SrcSockAddr6: TSockAddr6;
+ DstSockAddr: TSockAddr6;
+ protected
+ function IsNullAddress(SockAddr: PSockAddr): boolean;
+ function BindSrcAddr(Socket: socket; Family: word): cint;
public
+ function SetBindAddress(Family: word; const HostName: string): boolean;
function Connect(const HostName: string; Port: word): boolean;
procedure Disconnect;
procedure ReverseDNSLookup;
FConnected:= false;
FSocket:= -1;
FSockTimeOut:= DEF_SOCK_TIMEOUT;
+ FillChar(SrcSockAddr, SizeOf(SrcSockAddr), 0);
+ FillChar(SrcSockAddr6, SizeOf(SrcSockAddr6), 0);
+ FillChar(DstSockAddr, SizeOf(DstSockAddr), 0);
+ SrcSockAddr.sin_family:= AF_INET;
+ SrcSockAddr6.sin6_family:= AF_INET6;
end;
constructor TTCPConnection.Create(const HostName: string; Port: word);
Connect(HostName, Port);
end;
-constructor TTCPConnection.Create(Socket: socket; const Addr: TSockAddr6);
+constructor TTCPConnection.Create(Socket: socket);
{ Use an already connected socket. }
+var ssocklen, dsocklen: TSockLen;
begin
inherited Create;
FSocket:= Socket;
- SockAddr:= Addr;
- FHostIP:= TIPNamePair.Create('', IPToStr(@Addr));
+ ssocklen:= SizeOf(SrcSockAddr);
+ dsocklen:= SizeOf(DstSockAddr);
+ fpgetsockname(FSocket, @SrcSockAddr, @ssocklen);
+ fpgetpeername(FSocket, @DstSockAddr, @dsocklen);
+ FHostIP:= TIPNamePair.Create('', IPToStr(@DstSockAddr));
FConnected:= true;
end;
end;
+function TTCPConnection.IsNullAddress(SockAddr: PSockAddr): boolean;
+begin
+ if SockAddr^.sin_family = AF_INET then
+ Result:= SockAddr^.sin_addr.s_addr = 0
+ else if SockAddr^.sin_family = AF_INET6 then
+ Result:= (PSockAddr6(SockAddr)^.sin6_addr.u6_addr32[0] = 0)
+ and (PSockAddr6(SockAddr)^.sin6_addr.u6_addr32[1] = 0)
+ and (PSockAddr6(SockAddr)^.sin6_addr.u6_addr32[2] = 0)
+ and (PSockAddr6(SockAddr)^.sin6_addr.u6_addr32[3] = 0)
+ else
+ Result:= true;
+end;
+
+function TTCPConnection.BindSrcAddr(Socket: socket; Family: word): cint;
+var SockAddr: PSockAddr; addrlen: size_t;
+begin
+ case Family of
+ AF_INET:
+ begin
+ SockAddr:= @SrcSockAddr;
+ addrlen:= SizeOf(SrcSockAddr);
+ end;
+ AF_INET6:
+ begin
+ SockAddr:= @SrcSockAddr6;
+ addrlen:= SizeOf(SrcSockAddr6);
+ end;
+ end;
+
+ if not IsNullAddress(SockAddr) then
+ Result:= fpBind(Socket, SockAddr, addrlen)
+ else
+ Result:= 0;
+end;
+
+function TTCPConnection.SetBindAddress(Family: word; const HostName: string): boolean;
+var GAIResult: TGAIResult; SockAddr: PSockAddr;
+begin
+ GAIResult:= ResolveHost(HostName, Family);
+ if GAIResult.GAIError = 0 then begin
+ case GAIResult.AddrInfo^.ai_family of
+ AF_INET: SockAddr:= @SrcSockAddr;
+ AF_INET6: SockAddr:= @SrcSockAddr6;
+ end;
+ Move(GAIResult.AddrInfo^.ai_addr^, SockAddr^, GAIResult.AddrInfo^.ai_addrlen);
+ FreeHost(GAIResult);
+ Result:= true;
+ end
+ else
+ Result:= false;
+end;
+
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
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);
+ Move(GAIResult.AddrInfo^.ai_addr^, DstSockAddr, GAIResult.AddrInfo^.ai_addrlen);
+ DstSockAddr.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 BindSrcAddr(FSocket, GAIResult.AddrInfo^.ai_family) = 0 then begin
+
+ { Try to initiate connection. }
+ FConnected:= fpConnect(FSocket, @DstSockAddr, GAIResult.AddrInfo^.ai_addrlen) <> -1;
+
+ if FConnected then begin
+ FHostIP:= TIPNamePair.Create(HostName, IPToStr(@DstSockAddr));
+ SetSockTimeOut(FSockTimeOut);
+ end
+ else
+ CloseSocket(FSocket);
- if FConnected then begin
- FHostIP:= TIPNamePair.Create(HostName, IPToStr(@SockAddr));
- SetSockTimeOut(FSockTimeOut);
end
else
CloseSocket(FSocket);
var NHostIP: TIPNamePair;
begin
if FConnected then begin
- NHostIP:= TIPNamePair.Create(ResolveIP(PSockAddr(@SockAddr)), FHostIP.IP);
+ NHostIP:= TIPNamePair.Create(ResolveIP(PSockAddr(@DstSockAddr)), FHostIP.IP);
FHostIP.Free;
FHostIP:= NHostIP;
end;
connection. }
case FFeatureRequest of
NET_TCP_BASIC:
- TCPConnection:= TTCPConnection.Create(ClientSocket, SockAddr);
+ TCPConnection:= TTCPConnection.Create(ClientSocket);
NET_TCP_RFCSUPPORT:
- TCPConnection:= TTCPRFCConnection.Create(ClientSocket, SockAddr);
+ TCPConnection:= TTCPRFCConnection.Create(ClientSocket);
end;
{ Then start a new thread with the connection handler. }