X-Git-Url: http://git.megabrutal.com/?p=mgsmtp.git;a=blobdiff_plain;f=Network.pas;h=d19aeeacbda844998fea48c0701f40c7cf56afeb;hp=d5b458da2d5919570e2805ae5416b63eac408752;hb=HEAD;hpb=443339e2756df295317b7136b3262e368fdb9bfa diff --git a/Network.pas b/Network.pas index d5b458d..d19aeea 100644 --- a/Network.pas +++ b/Network.pas @@ -37,7 +37,7 @@ unit Network; interface -uses Classes, Sockets, SocketUtils, DNSResolve, NetRFC, Common; +uses Classes, Sockets, SocketUtils, SysUtils, DNSResolve, NetRFC, Common; const @@ -54,15 +54,16 @@ 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); overload; destructor Destroy; override; private FConnected: boolean; FSocket: socket; FHostIP: TIPNamePair; FSockTimeOut: DWord; - SockAddr: TSockAddr; + SrcSockAddr, DstSockAddr: TSockAddr; public + function SetBindAddress(const HostName: string): boolean; function Connect(const HostName: string; Port: word): boolean; procedure Disconnect; procedure ReverseDNSLookup; @@ -101,17 +102,18 @@ type TTCPListener = class(TThread) constructor Create(const Address: string; Port: word; FeatureRequest: word); {destructor Destroy; override;} - private + protected FFeatureRequest: word; FListenAddress: string; FListenPort: word; FListenSocket: socket; SockAddr: TSockAddr; - protected procedure HandleClient(Connection: TTCPConnection); virtual; abstract; procedure Execute; override; public + property ListenAddress: string read FListenAddress; property ListenPort: word read FListenPort; + function GetSockAddrStr: string; function StartListen: boolean; procedure StopListen; end; @@ -128,6 +130,8 @@ begin FConnected:= false; FSocket:= -1; FSockTimeOut:= DEF_SOCK_TIMEOUT; + FillChar(SrcSockAddr, SizeOf(SrcSockAddr), 0); + FillChar(DstSockAddr, SizeOf(DstSockAddr), 0); end; constructor TTCPConnection.Create(const HostName: string; Port: word); @@ -137,13 +141,17 @@ begin Connect(HostName, Port); end; -constructor TTCPConnection.Create(Socket: socket; const Addr: TSockAddr); +constructor TTCPConnection.Create(Socket: socket); { Use an already connected socket. } +var ssocklen, dsocklen: TSockLen; begin inherited Create; FSocket:= Socket; - SockAddr:= Addr; - FHostIP:= TIPNamePair.Create('', NetAddrToStr(Addr.sin_addr)); + ssocklen:= SizeOf(SrcSockAddr); + dsocklen:= SizeOf(DstSockAddr); + fpgetsockname(FSocket, @SrcSockAddr, @ssocklen); + fpgetpeername(FSocket, @DstSockAddr, @dsocklen); + FHostIP:= TIPNamePair.Create('', NetAddrToStr(DstSockAddr.sin_addr)); FConnected:= true; end; @@ -175,29 +183,44 @@ begin end; +function TTCPConnection.SetBindAddress(const HostName: string): boolean; +var GAIResult: TGAIResult; +begin + GAIResult:= ResolveHost(HostName); + if GAIResult.GAIError = 0 then begin + SrcSockAddr:= GAIResult.AddrInfo^.ai_addr^; + 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 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); + if (SrcSockAddr.sin_addr.s_addr = 0) or (fpBind(FSocket, @SrcSockAddr, SizeOf(SrcSockAddr)) = 0) then begin + GAIResult:= ResolveHost(HostName); + if GAIResult.GAIError = 0 then begin + DstSockAddr:= GAIResult.AddrInfo^.ai_addr^; + DstSockAddr.sin_port:= htons(Port); + + if DstSockAddr.sin_addr.s_addr <> 0 then + { Try to initiate connection. } + FConnected:= fpConnect(FSocket, @DstSockAddr, SizeOf(DstSockAddr)) <> -1; + + if FConnected then begin + FHostIP:= TIPNamePair.Create(HostName, NetAddrToStr(DstSockAddr.sin_addr)); + SetSockTimeOut(FSockTimeOut); + end + else + CloseSocket(FSocket); - FreeHost(GAIResult); + FreeHost(GAIResult); + end; end; end; Result:= FConnected; @@ -217,7 +240,7 @@ procedure TTCPConnection.ReverseDNSLookup; var NHostIP: TIPNamePair; begin if FConnected then begin - NHostIP:= TIPNamePair.Create(ResolveIP(@SockAddr), FHostIP.IP); + NHostIP:= TIPNamePair.Create(ResolveIP(@DstSockAddr), FHostIP.IP); FHostIP.Free; FHostIP:= NHostIP; end; @@ -300,6 +323,11 @@ begin end; +function TTCPListener.GetSockAddrStr: string; +begin + Result:= NetAddrToStr(SockAddr.sin_addr) + ':' + IntToStr(ntohs(SockAddr.sin_port)); +end; + function TTCPListener.StartListen: boolean; var GAIResult: TGAIResult; begin @@ -350,9 +378,9 @@ begin 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. }