home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 November / Chip_2002-11_cd1.bin / zkuste / delphi / kompon / d3456 / SYNAPSE.ZIP / source / lib / blcksock.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  2002-08-11  |  58.1 KB  |  2,115 lines

  1. {==============================================================================|
  2. | Project : Delphree - Synapse                                   | 006.001.004 |
  3. |==============================================================================|
  4. | Content: Library base                                                        |
  5. |==============================================================================|
  6. | Copyright (c)1999-2002, Lukas Gebauer                                        |
  7. | All rights reserved.                                                         |
  8. |                                                                              |
  9. | Redistribution and use in source and binary forms, with or without           |
  10. | modification, are permitted provided that the following conditions are met:  |
  11. |                                                                              |
  12. | Redistributions of source code must retain the above copyright notice, this  |
  13. | list of conditions and the following disclaimer.                             |
  14. |                                                                              |
  15. | Redistributions in binary form must reproduce the above copyright notice,    |
  16. | this list of conditions and the following disclaimer in the documentation    |
  17. | and/or other materials provided with the distribution.                       |
  18. |                                                                              |
  19. | Neither the name of Lukas Gebauer nor the names of its contributors may      |
  20. | be used to endorse or promote products derived from this software without    |
  21. | specific prior written permission.                                           |
  22. |                                                                              |
  23. | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"  |
  24. | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE    |
  25. | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE   |
  26. | ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR  |
  27. | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL       |
  28. | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR   |
  29. | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER   |
  30. | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT           |
  31. | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY    |
  32. | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH  |
  33. | DAMAGE.                                                                      |
  34. |==============================================================================|
  35. | The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
  36. | Portions created by Lukas Gebauer are Copyright (c)1999-2002.                |
  37. | All Rights Reserved.                                                         |
  38. |==============================================================================|
  39. | Contributor(s):                                                              |
  40. |==============================================================================|
  41. | History: see HISTORY.HTM from distribution package                           |
  42. |          (Found at URL: http://www.ararat.cz/synapse/)                       |
  43. |==============================================================================}
  44. {
  45. Special thanks to Gregor Ibic <gregor.ibic@intelicom.si>
  46.  (Intelicom d.o.o., http://www.intelicom.si)
  47.  for good inspiration about SSL programming.
  48. }
  49.  
  50. {$Q-}
  51. {$WEAKPACKAGEUNIT ON}
  52.  
  53. unit blcksock;
  54.  
  55. interface
  56.  
  57. uses
  58.   SysUtils, Classes,
  59. {$IFDEF LINUX}
  60.   Libc, kernelioctl,
  61. {$ELSE}
  62.   Windows, WinSock,
  63. {$ENDIF}
  64.   synsock, SynaUtil, SynaCode, SynaSSL;
  65.  
  66. const
  67.   cLocalhost = 'localhost';
  68.   cAnyHost = '0.0.0.0';
  69.   cBroadcast = '255.255.255.255';
  70.   cAnyPort = '0';
  71.  
  72. type
  73.  
  74.   ESynapseError = class(Exception)
  75.   public
  76.     ErrorCode: Integer;
  77.     ErrorMessage: string;
  78.   end;
  79.  
  80.   THookSocketReason = (
  81.     HR_ResolvingBegin,
  82.     HR_ResolvingEnd,
  83.     HR_SocketCreate,
  84.     HR_SocketClose,
  85.     HR_Bind,
  86.     HR_Connect,
  87.     HR_CanRead,
  88.     HR_CanWrite,
  89.     HR_Listen,
  90.     HR_Accept,
  91.     HR_ReadCount,
  92.     HR_WriteCount
  93.     );
  94.  
  95.   THookSocketStatus = procedure(Sender: TObject; Reason: THookSocketReason;
  96.     const Value: string) of object;
  97.  
  98.   TBlockSocket = class(TObject)
  99.   private
  100.     FOnStatus: THookSocketStatus;
  101.     FWsaData: TWSADATA;
  102.     FLocalSin: TSockAddrIn;
  103.     FRemoteSin: TSockAddrIn;
  104.     FLastError: Integer;
  105.     FLastErrorDesc: string;
  106.     FBuffer: string;
  107.     FRaiseExcept: Boolean;
  108.     FNonBlockMode: Boolean;
  109.     FMaxLineLength: Integer;
  110.     FMaxSendBandwidth: Integer;
  111.     FNextSend: Cardinal;
  112.     FMaxRecvBandwidth: Integer;
  113.     FNextRecv: Cardinal;
  114.     FConvertLineEnd: Boolean;
  115.     function GetSizeRecvBuffer: Integer;
  116.     procedure SetSizeRecvBuffer(Size: Integer);
  117.     function GetSizeSendBuffer: Integer;
  118.     procedure SetSizeSendBuffer(Size: Integer);
  119.     procedure SetNonBlockMode(Value: Boolean);
  120.   protected
  121.     FSocket: TSocket;
  122.     FProtocol: Integer;
  123.     procedure CreateSocket; virtual;
  124.     procedure AutoCreateSocket;
  125.     procedure SetSin(var Sin: TSockAddrIn; IP, Port: string);
  126.     function GetSinIP(Sin: TSockAddrIn): string;
  127.     function GetSinPort(Sin: TSockAddrIn): Integer;
  128.     procedure DoStatus(Reason: THookSocketReason; const Value: string);
  129.     procedure LimitBandwidth(Length: Integer; MaxB: integer; var Next: Cardinal);
  130.     procedure SetBandwidth(Value: Integer);
  131.   public
  132.     constructor Create;
  133.     constructor CreateAlternate(Stub: string);
  134.     destructor Destroy; override;
  135.     procedure CloseSocket; virtual;
  136.     procedure Bind(IP, Port: string);
  137.     procedure Connect(IP, Port: string); virtual;
  138.     function SendBuffer(Buffer: Pointer; Length: Integer): Integer; virtual;
  139.     procedure SendByte(Data: Byte); virtual;
  140.     procedure SendString(const Data: string); virtual;
  141.     function RecvBuffer(Buffer: Pointer; Length: Integer): Integer; virtual;
  142.     function RecvBufferEx(Buffer: Pointer; Length: Integer;
  143.       Timeout: Integer): Integer; virtual;
  144.     function RecvByte(Timeout: Integer): Byte; virtual;
  145.     function RecvString(Timeout: Integer): string; virtual;
  146.     function RecvTerminated(Timeout: Integer; const Terminator: string): string; virtual;
  147.     function RecvPacket(Timeout: Integer): string; virtual;
  148.     function PeekBuffer(Buffer: Pointer; Length: Integer): Integer; virtual;
  149.     function PeekByte(Timeout: Integer): Byte; virtual;
  150.     function WaitingData: Integer; virtual;
  151.     function WaitingDataEx: Integer;
  152.     procedure SetLinger(Enable: Boolean; Linger: Integer);
  153.     procedure GetSins;
  154.     function SockCheck(SockResult: Integer): Integer;
  155.     procedure ExceptCheck;
  156.     function LocalName: string;
  157.     procedure ResolveNameToIP(Name: string; IPList: TStrings);
  158.     function ResolveName(Name: string): string;
  159.     function ResolvePort(Port: string): Word;
  160.     procedure SetRemoteSin(IP, Port: string);
  161.     function GetLocalSinIP: string; virtual;
  162.     function GetRemoteSinIP: string; virtual;
  163.     function GetLocalSinPort: Integer; virtual;
  164.     function GetRemoteSinPort: Integer; virtual;
  165.     function CanRead(Timeout: Integer): Boolean;
  166.     function CanReadEx(Timeout: Integer): Boolean;
  167.     function CanWrite(Timeout: Integer): Boolean;
  168.     function SendBufferTo(Buffer: Pointer; Length: Integer): Integer; virtual;
  169.     function RecvBufferFrom(Buffer: Pointer; Length: Integer): Integer; virtual;
  170.     function GroupCanRead(const SocketList: TList; Timeout: Integer;
  171.       const CanReadList: TList): Boolean;
  172.     function EnableReuse(Value: Boolean): Boolean;
  173.  
  174.     //See 'winsock2.txt' file in distribute package!
  175.     function SetTimeout(Timeout: Integer): Boolean;
  176.     function SetSendTimeout(Timeout: Integer): Boolean;
  177.     function SetRecvTimeout(Timeout: Integer): Boolean;
  178.  
  179.     property LocalSin: TSockAddrIn read FLocalSin;
  180.     property RemoteSin: TSockAddrIn read FRemoteSin;
  181.   published
  182.     class function GetErrorDesc(ErrorCode: Integer): string;
  183.     property Socket: TSocket read FSocket write FSocket;
  184.     property LastError: Integer read FLastError;
  185.     property LastErrorDesc: string read FLastErrorDesc;
  186.     property Protocol: Integer read FProtocol;
  187.     property LineBuffer: string read FBuffer write FBuffer;
  188.     property RaiseExcept: Boolean read FRaiseExcept write FRaiseExcept;
  189.     property SizeRecvBuffer: Integer read GetSizeRecvBuffer write SetSizeRecvBuffer;
  190.     property SizeSendBuffer: Integer read GetSizeSendBuffer write SetSizeSendBuffer;
  191.     property WSAData: TWSADATA read FWsaData;
  192.     property OnStatus: THookSocketStatus read FOnStatus write FOnStatus;
  193.     property NonBlockMode: Boolean read FNonBlockMode Write SetNonBlockMode;
  194.     property MaxLineLength: Integer read FMaxLineLength Write FMaxLineLength;
  195.     property MaxSendBandwidth: Integer read FMaxSendBandwidth Write FMaxSendBandwidth;
  196.     property MaxRecvBandwidth: Integer read FMaxRecvBandwidth Write FMaxRecvBandwidth;
  197.     property MaxBandwidth: Integer Write SetBandwidth;
  198.     property ConvertLineEnd: Boolean read FConvertLineEnd Write FConvertLineEnd;
  199.   end;
  200.  
  201.   TSocksBlockSocket = class(TBlockSocket)
  202.   protected
  203.     FSocksIP: string;
  204.     FSocksPort: string;
  205.     FSocksTimeout: integer;
  206.     FSocksUsername: string;
  207.     FSocksPassword: string;
  208.     FUsingSocks: Boolean;
  209.     FSocksResolver: Boolean;
  210.     FSocksLastError: integer;
  211.     FSocksResponseIP: string;
  212.     FSocksResponsePort: string;
  213.     FSocksLocalIP: string;
  214.     FSocksLocalPort: string;
  215.     FSocksRemoteIP: string;
  216.     FSocksRemotePort: string;
  217.     FBypassFlag: Boolean;
  218.     function SocksCode(IP, Port: string): string;
  219.     function SocksDecode(Value: string): integer;
  220.   public
  221.     constructor Create;
  222.     function SocksOpen: Boolean;
  223.     function SocksRequest(Cmd: Byte; const IP, Port: string): Boolean;
  224.     function SocksResponse: Boolean;
  225.   published
  226.     property SocksIP: string read FSocksIP write FSocksIP;
  227.     property SocksPort: string read FSocksPort write FSocksPort;
  228.     property SocksUsername: string read FSocksUsername write FSocksUsername;
  229.     property SocksPassword: string read FSocksPassword write FSocksPassword;
  230.     property UsingSocks: Boolean read FUsingSocks;
  231.     property SocksResolver: Boolean read FSocksResolver write FSocksResolver;
  232.     property SocksLastError: integer read FSocksLastError;
  233.   end;
  234.  
  235.   TTCPBlockSocket = class(TSocksBlockSocket)
  236.   protected
  237.     FSslEnabled: Boolean;
  238.     FSslBypass: Boolean;
  239.     FSsl: PSSL;
  240.     Fctx: PSSL_CTX;
  241.     FSSLPassword: string;
  242.     FSSLCiphers: string;
  243.     FSSLCertificateFile: string;
  244.     FSSLPrivateKeyFile: string;
  245.     FSSLCertCAFile: string;
  246.     FSSLLastError: integer;
  247.     FSSLLastErrorDesc: string;
  248.     FSSLverifyCert: Boolean;
  249.     FHTTPTunnelIP: string;
  250.     FHTTPTunnelPort: string;
  251.     FHTTPTunnel: Boolean;
  252.     FHTTPTunnelRemoteIP: string;
  253.     FHTTPTunnelRemotePort: string;
  254.     FHTTPTunnelUser: string;
  255.     FHTTPTunnelPass: string;
  256.     procedure SetSslEnabled(Value: Boolean);
  257.     function SetSslKeys: boolean;
  258.     procedure SocksDoConnect(IP, Port: string);
  259.     procedure HTTPTunnelDoConnect(IP, Port: string);
  260.   public
  261.     constructor Create;
  262.     destructor Destroy; override;
  263.     procedure CreateSocket; override;
  264.     procedure CloseSocket; override;
  265.     function WaitingData: Integer; override;
  266.     procedure Listen;
  267.     function Accept: TSocket;
  268.     procedure Connect(IP, Port: string); override;
  269.     procedure SSLDoConnect;
  270.     procedure SSLDoShutdown;
  271.     function SSLAcceptConnection: Boolean;
  272.     function GetLocalSinIP: string; override;
  273.     function GetRemoteSinIP: string; override;
  274.     function GetLocalSinPort: Integer; override;
  275.     function GetRemoteSinPort: Integer; override;
  276.     function SendBuffer(Buffer: Pointer; Length: Integer): Integer; override;
  277.     function RecvBuffer(Buffer: Pointer; Length: Integer): Integer; override;
  278.     function SSLGetSSLVersion: string;
  279.     function SSLGetPeerSubject: string;
  280.     function SSLGetPeerIssuer: string;
  281.     function SSLGetPeerSubjectHash: Cardinal;
  282.     function SSLGetPeerIssuerHash: Cardinal;
  283.     function SSLGetPeerFingerprint: string;
  284.     function SSLCheck: Boolean;
  285.   published
  286.     property SSLEnabled: Boolean read FSslEnabled write SetSslEnabled;
  287.     property SSLBypass: Boolean read FSslBypass write FSslBypass;
  288.     property SSLPassword: string read FSSLPassword write FSSLPassword;
  289.     property SSLCiphers: string read FSSLCiphers write FSSLCiphers;
  290.     property SSLCertificateFile: string read FSSLCertificateFile write FSSLCertificateFile;
  291.     property SSLPrivateKeyFile: string read FSSLPrivateKeyFile write FSSLPrivateKeyFile;
  292.     property SSLCertCAFile: string read FSSLCertCAFile write FSSLCertCAFile;
  293.     property SSLLastError: integer read FSSLLastError;
  294.     property SSLLastErrorDesc: string read FSSLLastErrorDesc;
  295.     property SSLverifyCert: Boolean read FSSLverifyCert write FSSLverifyCert;
  296.     property HTTPTunnelIP: string read FHTTPTunnelIP Write FHTTPTunnelIP;
  297.     property HTTPTunnelPort: string read FHTTPTunnelPort Write FHTTPTunnelPort;
  298.     property HTTPTunnel: Boolean read FHTTPTunnel;
  299.     property HTTPTunnelUser: string read FHTTPTunnelUser Write FHTTPTunnelUser;
  300.     property HTTPTunnelPass: string read FHTTPTunnelPass Write FHTTPTunnelPass;
  301.   end;
  302.  
  303.   TUDPBlockSocket = class(TSocksBlockSocket)
  304.   protected
  305.     FSocksControlSock: TTCPBlockSocket;
  306.     function UdpAssociation: Boolean;
  307.   public
  308.     destructor Destroy; override;
  309.     procedure CreateSocket; override;
  310.     function EnableBroadcast(Value: Boolean): Boolean;
  311.     procedure Connect(IP, Port: string); override;
  312.     function SendBuffer(Buffer: Pointer; Length: Integer): Integer; override;
  313.     function RecvBuffer(Buffer: Pointer; Length: Integer): Integer; override;
  314.     function SendBufferTo(Buffer: Pointer; Length: Integer): Integer; override;
  315.     function RecvBufferFrom(Buffer: Pointer; Length: Integer): Integer; override;
  316.     procedure AddMulticast(MCastIP:string);
  317.     procedure DropMulticast(MCastIP:string);
  318.   end;
  319.  
  320.   //See 'winsock2.txt' file in distribute package!
  321.   TICMPBlockSocket = class(TBlockSocket)
  322.   public
  323.     procedure CreateSocket; override;
  324.   end;
  325.  
  326.   //See 'winsock2.txt' file in distribute package!
  327.   TRAWBlockSocket = class(TBlockSocket)
  328.   public
  329.     procedure CreateSocket; override;
  330.   end;
  331.  
  332.   TIPHeader = record
  333.     VerLen: Byte;
  334.     TOS: Byte;
  335.     TotalLen: Word;
  336.     Identifer: Word;
  337.     FragOffsets: Word;
  338.     TTL: Byte;
  339.     Protocol: Byte;
  340.     CheckSum: Word;
  341.     SourceIp: DWORD;
  342.     DestIp: DWORD;
  343.     Options: DWORD;
  344.   end;
  345.  
  346.   TSynaClient = Class(TObject)
  347.   protected
  348.     FTargetHost: string;
  349.     FTargetPort: string;
  350.     FIPInterface: string;
  351.     FTimeout: integer;
  352.   public
  353.     constructor Create;
  354.   published
  355.     property TargetHost: string read FTargetHost Write FTargetHost;
  356.     property TargetPort: string read FTargetPort Write FTargetPort;
  357.     property IPInterface: string read FIPInterface Write FIPInterface;
  358.     property Timeout: integer read FTimeout Write FTimeout;
  359.   end;
  360.  
  361. implementation
  362.  
  363. type
  364.   TMulticast = record
  365.     MCastAddr : u_long;
  366.     MCastIfc : u_long;
  367.   end;
  368.  
  369. constructor TBlockSocket.Create;
  370. var
  371.   e: ESynapseError;
  372. begin
  373.   inherited Create;
  374.   FRaiseExcept := False;
  375.   FSocket := INVALID_SOCKET;
  376.   FProtocol := IPPROTO_IP;
  377.   FBuffer := '';
  378.   FNonBlockMode := False;
  379.   FMaxLineLength := 0;
  380.   FMaxSendBandwidth := 0;
  381.   FNextSend := 0;
  382.   FMaxRecvBandwidth := 0;
  383.   FNextRecv := 0;
  384.   FConvertLineEnd := False;
  385.   if not InitSocketInterface('') then
  386.   begin
  387.     e := ESynapseError.Create('Error loading Winsock DLL!');
  388.     e.ErrorCode := 0;
  389.     e.ErrorMessage := 'Error loading Winsock DLL!';
  390.     raise e;
  391.   end;
  392.   SockCheck(synsock.WSAStartup($101, FWsaData));
  393.   ExceptCheck;
  394. end;
  395.  
  396. constructor TBlockSocket.CreateAlternate(Stub: string);
  397. var
  398.   e: ESynapseError;
  399. begin
  400.   inherited Create;
  401.   FRaiseExcept := False;
  402.   FSocket := INVALID_SOCKET;
  403.   FProtocol := IPPROTO_IP;
  404.   FBuffer := '';
  405.   if not InitSocketInterface(Stub) then
  406.   begin
  407.     e := ESynapseError.Create('Error loading alternate Winsock DLL (' + Stub + ')!');
  408.     e.ErrorCode := 0;
  409.     e.ErrorMessage := 'Error loading Winsock DLL (' + Stub + ')!';
  410.     raise e;
  411.   end;
  412.   SockCheck(synsock.WSAStartup($101, FWsaData));
  413.   ExceptCheck;
  414. end;
  415.  
  416. destructor TBlockSocket.Destroy;
  417. begin
  418.   CloseSocket;
  419.   synsock.WSACleanup;
  420.   DestroySocketInterface;
  421.   inherited Destroy;
  422. end;
  423.  
  424. procedure TBlockSocket.SetSin(var Sin: TSockAddrIn; IP, Port: string);
  425. type
  426.   pu_long = ^u_long;
  427. var
  428.   ProtoEnt: PProtoEnt;
  429.   ServEnt: PServEnt;
  430.   HostEnt: PHostEnt;
  431. begin
  432.   DoStatus(HR_ResolvingBegin, IP + ':' + Port);
  433.   FillChar(Sin, Sizeof(Sin), 0);
  434.   Sin.sin_family := AF_INET;
  435.   ProtoEnt := synsock.GetProtoByNumber(FProtocol);
  436.   ServEnt := nil;
  437.   if ProtoEnt <> nil then
  438.     ServEnt := synsock.GetServByName(PChar(Port), ProtoEnt^.p_name);
  439.   if ServEnt = nil then
  440.     Sin.sin_port := synsock.htons(StrToIntDef(Port, 0))
  441.   else
  442.     Sin.sin_port := ServEnt^.s_port;
  443.   if IP = cBroadcast then
  444.     Sin.sin_addr.s_addr := u_long(INADDR_BROADCAST)
  445.   else
  446.   begin
  447.     Sin.sin_addr.s_addr := synsock.inet_addr(PChar(IP));
  448.     if SIn.sin_addr.s_addr = u_long(INADDR_NONE) then
  449.     begin
  450.       HostEnt := synsock.GetHostByName(PChar(IP));
  451.       if HostEnt <> nil then
  452.         SIn.sin_addr.S_addr := u_long(Pu_long(HostEnt^.h_addr_list^)^);
  453.     end;
  454.   end;
  455.   DoStatus(HR_ResolvingEnd, IP + ':' + Port);
  456. end;
  457.  
  458. function TBlockSocket.GetSinIP(Sin: TSockAddrIn): string;
  459. var
  460.   p: PChar;
  461. begin
  462.   p := synsock.inet_ntoa(Sin.sin_addr);
  463.   if p = nil then
  464.     Result := ''
  465.   else
  466.     Result := p;
  467. end;
  468.  
  469. function TBlockSocket.GetSinPort(Sin: TSockAddrIn): Integer;
  470. begin
  471.   Result := synsock.ntohs(Sin.sin_port);
  472. end;
  473.  
  474. procedure TBlockSocket.CreateSocket;
  475. begin
  476.   FBuffer := '';
  477.   if FSocket = INVALID_SOCKET then
  478.     FLastError := synsock.WSAGetLastError
  479.   else
  480.     FLastError := 0;
  481.   ExceptCheck;
  482.   DoStatus(HR_SocketCreate, '');
  483. end;
  484.  
  485. procedure TBlockSocket.AutoCreateSocket;
  486. begin
  487.   if FSocket = INVALID_SOCKET then
  488.     CreateSocket;
  489. end;
  490.  
  491. procedure TBlockSocket.CloseSocket;
  492. begin
  493.   synsock.Shutdown(FSocket, 2);
  494.   synsock.CloseSocket(FSocket);
  495.   FSocket := INVALID_SOCKET;
  496.   DoStatus(HR_SocketClose, '');
  497. end;
  498.  
  499. procedure TBlockSocket.Bind(IP, Port: string);
  500. var
  501.   Sin: TSockAddrIn;
  502.   Len: Integer;
  503. begin
  504.   AutoCreateSocket;
  505.   SetSin(Sin, IP, Port);
  506.   SockCheck(synsock.Bind(FSocket, Sin, SizeOf(Sin)));
  507.   Len := SizeOf(FLocalSin);
  508.   synsock.GetSockName(FSocket, FLocalSin, Len);
  509.   FBuffer := '';
  510.   ExceptCheck;
  511.   DoStatus(HR_Bind, IP + ':' + Port);
  512. end;
  513.  
  514. procedure TBlockSocket.Connect(IP, Port: string);
  515. var
  516.   Sin: TSockAddrIn;
  517. begin
  518.   AutoCreateSocket;
  519.   SetSin(Sin, IP, Port);
  520.   SockCheck(synsock.Connect(FSocket, Sin, SizeOf(Sin)));
  521.   GetSins;
  522.   FBuffer := '';
  523.   ExceptCheck;
  524.   DoStatus(HR_Connect, IP + ':' + Port);
  525. end;
  526.  
  527. procedure TBlockSocket.GetSins;
  528. var
  529.   Len: Integer;
  530. begin
  531.   Len := SizeOf(FLocalSin);
  532.   synsock.GetSockName(FSocket, FLocalSin, Len);
  533.   Len := SizeOf(FRemoteSin);
  534.   synsock.GetPeerName(FSocket, FremoteSin, Len);
  535. end;
  536.  
  537. procedure TBlockSocket.SetBandwidth(Value: Integer);
  538. begin
  539.   MaxSendBandwidth := Value;
  540.   MaxRecvBandwidth := Value;
  541. end;
  542.  
  543. procedure TBlockSocket.LimitBandwidth(Length: Integer; MaxB: integer; var Next: Cardinal);
  544. var
  545.   x: Cardinal;
  546.   y: Cardinal;
  547. begin
  548.   if MaxB > 0 then
  549.   begin
  550.     y := GetTick;
  551.     if Next > y then
  552.     begin
  553.       x := Next - y;
  554.       if x > 0 then
  555.         sleep(x);
  556.     end;
  557.     Next := y + Trunc((Length / MaxB) * 1000);
  558.   end;
  559. end;
  560.  
  561. function TBlockSocket.SendBuffer(Buffer: Pointer; Length: Integer): Integer;
  562. begin
  563.   LimitBandwidth(Length, FMaxSendBandwidth, FNextsend);
  564.   Result := synsock.Send(FSocket, Buffer^, Length, 0);
  565.   SockCheck(Result);
  566.   ExceptCheck;
  567.   DoStatus(HR_WriteCount, IntToStr(Result));
  568. end;
  569.  
  570. procedure TBlockSocket.SendByte(Data: Byte);
  571. begin
  572.   SendBuffer(@Data, 1);
  573. end;
  574.  
  575. procedure TBlockSocket.SendString(const Data: string);
  576. begin
  577.   SendBuffer(PChar(Data), Length(Data));
  578. end;
  579.  
  580. function TBlockSocket.RecvBuffer(Buffer: Pointer; Length: Integer): Integer;
  581. begin
  582.   LimitBandwidth(Length, FMaxRecvBandwidth, FNextRecv);
  583.   Result := synsock.Recv(FSocket, Buffer^, Length, 0);
  584.   if Result = 0 then
  585.     FLastError := WSAECONNRESET
  586.   else
  587.     SockCheck(Result);
  588.   ExceptCheck;
  589.   DoStatus(HR_ReadCount, IntToStr(Result));
  590. end;
  591.  
  592. function TBlockSocket.RecvBufferEx(Buffer: Pointer; Length: Integer;
  593.   Timeout: Integer): Integer;
  594. var
  595.   s, ss, st: string;
  596.   x, l, lss: Integer;
  597.   fb, fs: Integer;
  598.   max: Integer;
  599. begin
  600.   FLastError := 0;
  601.   x := System.Length(FBuffer);
  602.   if Length <= x then
  603.   begin
  604.     fb := Length;
  605.     fs := 0;
  606.   end
  607.   else
  608.   begin
  609.     fb := x;
  610.     fs := Length - x;
  611.   end;
  612.   ss := '';
  613.   if fb > 0 then
  614.   begin
  615.     s := Copy(FBuffer, 1, fb);
  616.     Delete(FBuffer, 1, fb);
  617.   end;
  618.   if fs > 0 then
  619.   begin
  620.     Max := GetSizeRecvBuffer;
  621.     ss := '';
  622.     while System.Length(ss) < fs do
  623.     begin
  624.       if CanRead(Timeout) then
  625.       begin
  626.         l := WaitingData;
  627.         if l > max then
  628.           l := max;
  629.         if (system.Length(ss) + l) > fs then
  630.           l := fs - system.Length(ss);
  631.         SetLength(st, l);
  632.         x := RecvBuffer(Pointer(st), l);
  633.         if FLastError <> 0 then
  634.           Break;
  635.         lss := system.Length(ss);
  636.         SetLength(ss, lss + x);
  637.         Move(Pointer(st)^, Pointer(@ss[lss + 1])^, x);
  638.         {It is 3x faster then ss:=ss+copy(st,1,x);}
  639.         Sleep(0);
  640.       end
  641.       else
  642.         FLastError := WSAETIMEDOUT;
  643.       if FLastError <> 0 then
  644.         Break;
  645.     end;
  646.     fs := system.Length(ss);
  647.   end;
  648.   Result := fb + fs;
  649.   s := s + ss;
  650.   Move(Pointer(s)^, Buffer^, Result);
  651.   ExceptCheck;
  652. end;
  653.  
  654. function TBlockSocket.RecvPacket(Timeout: Integer): string;
  655. var
  656.   x: integer;
  657. begin
  658.   Result := '';
  659.   FLastError := 0;
  660.   x := -1;
  661.   if FBuffer <> '' then
  662.   begin
  663.     Result := FBuffer;
  664.     FBuffer := '';
  665.   end
  666.   else
  667.     if CanRead(Timeout) then
  668.     begin
  669.       x := WaitingData;
  670.       if x > 0 then
  671.       begin
  672.         SetLength(Result, x);
  673.         x := RecvBuffer(Pointer(Result), x);
  674.         if x >= 0 then
  675.           SetLength(Result, x);
  676.       end;
  677.     end
  678.     else
  679.       FLastError := WSAETIMEDOUT;
  680.   ExceptCheck;
  681.   if x = 0 then
  682.     FLastError := WSAECONNRESET;
  683. end;
  684.  
  685.  
  686. function TBlockSocket.RecvByte(Timeout: Integer): Byte;
  687. begin
  688.   Result := 0;
  689.   FLastError := 0;
  690.   if FBuffer = '' then
  691.     FBuffer := RecvPacket(Timeout);
  692.   if (FBuffer = '') and (FLastError = 0) then
  693.     FLastError := WSAETIMEDOUT;
  694.   if FLastError = 0 then
  695.   begin
  696.     Result := Ord(FBuffer[1]);
  697.     System.Delete(FBuffer, 1, 1);
  698.   end;
  699.   ExceptCheck;
  700. end;
  701.  
  702. function TBlockSocket.RecvTerminated(Timeout: Integer; const Terminator: string): string;
  703. var
  704.   x: Integer;
  705.   s: string;
  706.   l: Integer;
  707.   CorCRLF: Boolean;
  708.   t: string;
  709.   tl: integer;
  710. begin
  711.   FLastError := 0;
  712.   Result := '';
  713.   l := system.Length(Terminator);
  714.   if l = 0 then
  715.     Exit;
  716.   tl := l;
  717.   CorCRLF := FConvertLineEnd and (Terminator = #$0d + #$0a);
  718.   // if FBuffer contains requested data, return it...
  719.   if FBuffer<>'' then
  720.   begin
  721.     if CorCRLF then
  722.     begin
  723.       t := '';
  724.       x := PosCRLF(FBuffer, t);
  725.       tl := system.Length(t);
  726.     end
  727.     else
  728.     begin
  729.       x := pos(Terminator, FBuffer);
  730.       tl := l;
  731.     end;
  732.     if x > 0 then
  733.     begin
  734.       Result := copy(FBuffer, 1, x - 1);
  735.       System.Delete(FBuffer, 1, x + tl - 1);
  736.       Exit;
  737.     end;
  738.   end;
  739.   // now FBuffer is empty or not contains all data...
  740.   s := '';
  741.   x := 0;
  742.   repeat
  743.     //get rest of FBuffer or incomming new data...
  744.     s := s + RecvPacket(Timeout);
  745.     if FLastError <> 0 then
  746.       Break;
  747.     if CorCRLF then
  748.     begin
  749.       t := '';
  750.       x := PosCRLF(s, t);
  751.       tl := system.Length(t);
  752.     end
  753.     else
  754.     begin
  755.       x := pos(Terminator, s);
  756.       tl := l;
  757.     end;
  758.     if (FMaxLineLength <> 0) and (system.Length(s) > FMaxLineLength) then
  759.     begin
  760.       FLastError := WSAENOBUFS;
  761.       Break;
  762.     end;
  763.   until x > 0;
  764.   if x > 0 then
  765.   begin
  766.     Result := Copy(s, 1, x - 1);
  767.     System.Delete(s, 1, x + tl - 1);
  768.   end;
  769.   FBuffer := s;
  770.   ExceptCheck;
  771. end;
  772.  
  773. function TBlockSocket.RecvString(Timeout: Integer): string;
  774. var
  775.   s: string;
  776. begin
  777.   Result := '';
  778.   s := RecvTerminated(Timeout, #13 + #10);
  779.   if FLastError = 0 then
  780.     Result := s;
  781. end;
  782.  
  783. function TBlockSocket.PeekBuffer(Buffer: Pointer; Length: Integer): Integer;
  784. begin
  785.   Result := synsock.Recv(FSocket, Buffer^, Length, MSG_PEEK);
  786.   SockCheck(Result);
  787.   ExceptCheck;
  788. end;
  789.  
  790. function TBlockSocket.PeekByte(Timeout: Integer): Byte;
  791. var
  792.   s: string;
  793. begin
  794.   Result := 0;
  795.   if CanRead(Timeout) then
  796.   begin
  797.     SetLength(s, 1);
  798.     PeekBuffer(Pointer(s), 1);
  799.     if s <> '' then
  800.       Result := Ord(s[1]);
  801.   end
  802.   else
  803.     FLastError := WSAETIMEDOUT;
  804.   ExceptCheck;
  805. end;
  806.  
  807. function TBlockSocket.SockCheck(SockResult: Integer): Integer;
  808. begin
  809.   FLastErrorDesc := '';
  810.   if SockResult = integer(SOCKET_ERROR) then
  811.   begin
  812.     Result := synsock.WSAGetLastError;
  813.     FLastErrorDesc := GetErrorDesc(Result);
  814.   end
  815.   else
  816.     Result := 0;
  817.   FLastError := Result;
  818. end;
  819.  
  820. procedure TBlockSocket.ExceptCheck;
  821. var
  822.   e: ESynapseError;
  823.   s: string;
  824. begin
  825.   if FRaiseExcept and (LastError <> 0) and (LastError <> WSAEINPROGRESS)
  826.     and (LastError <> WSAEWOULDBLOCK) then
  827.   begin
  828.     s := GetErrorDesc(LastError);
  829.     e := ESynapseError.CreateFmt('TCP/IP Socket error %d: %s', [LastError, s]);
  830.     e.ErrorCode := LastError;
  831.     e.ErrorMessage := s;
  832.     raise e;
  833.   end;
  834. end;
  835.  
  836. function TBlockSocket.WaitingData: Integer;
  837. var
  838.   x: Integer;
  839. begin
  840.   synsock.IoctlSocket(FSocket, FIONREAD, u_long(x));
  841.   Result := x;
  842. end;
  843.  
  844. function TBlockSocket.WaitingDataEx: Integer;
  845. begin
  846.   if FBuffer <> '' then
  847.     Result := Length(FBuffer)
  848.   else
  849.     Result := WaitingData;
  850. end;
  851.  
  852.  
  853. procedure TBlockSocket.SetLinger(Enable: Boolean; Linger: Integer);
  854. var
  855.   li: TLinger;
  856. begin
  857.   li.l_onoff := Ord(Enable);
  858.   li.l_linger := Linger div 1000;
  859.   SockCheck(synsock.SetSockOpt(FSocket, SOL_SOCKET, SO_LINGER, @li, SizeOf(li)));
  860.   ExceptCheck;
  861. end;
  862.  
  863. function TBlockSocket.LocalName: string;
  864. var
  865.   buf: array[0..255] of Char;
  866.   BufPtr: PChar;
  867.   RemoteHost: PHostEnt;
  868. begin
  869.   BufPtr := buf;
  870.   Result := '';
  871.   synsock.GetHostName(BufPtr, SizeOf(buf));
  872.   if BufPtr[0] <> #0 then
  873.   begin
  874.     // try get Fully Qualified Domain Name
  875.     RemoteHost := synsock.GetHostByName(BufPtr);
  876.     if RemoteHost <> nil then
  877.       Result := PChar(RemoteHost^.h_name);
  878.   end;
  879.   if Result = '' then
  880.     Result := '127.0.0.1';
  881. end;
  882.  
  883. procedure TBlockSocket.ResolveNameToIP(Name: string; IPList: TStrings);
  884. type
  885.   TaPInAddr = array[0..250] of PInAddr;
  886.   PaPInAddr = ^TaPInAddr;
  887. var
  888.   RemoteHost: PHostEnt;
  889.   IP: u_long;
  890.   PAdrPtr: PaPInAddr;
  891.   i: Integer;
  892.   s: string;
  893.   InAddr: TInAddr;
  894. begin
  895.   IPList.Clear;
  896.   IP := synsock.inet_addr(PChar(Name));
  897.   if IP = u_long(INADDR_NONE) then
  898.   begin
  899.     RemoteHost := synsock.GetHostByName(PChar(Name));
  900.     if RemoteHost <> nil then
  901.     begin
  902.       PAdrPtr := PAPInAddr(RemoteHost^.h_addr_list);
  903.       i := 0;
  904.       while PAdrPtr^[i] <> nil do
  905.       begin
  906.         InAddr := PAdrPtr^[i]^;
  907.         with InAddr.S_un_b do
  908.           s := Format('%d.%d.%d.%d',
  909.             [Ord(s_b1), Ord(s_b2), Ord(s_b3), Ord(s_b4)]);
  910.         IPList.Add(s);
  911.         Inc(i);
  912.       end;
  913.     end;
  914.     if IPList.Count = 0 then
  915.       IPList.Add('0.0.0.0');
  916.   end
  917.   else
  918.     IPList.Add(Name);
  919. end;
  920.  
  921. function TBlockSocket.ResolveName(Name: string): string;
  922. var
  923.   l: TStringList;
  924. begin
  925.   l := TStringList.Create;
  926.   try
  927.     ResolveNameToIP(Name, l);
  928.     Result := l[0];
  929.   finally
  930.     l.Free;
  931.   end;
  932. end;
  933.  
  934. function TBlockSocket.ResolvePort(Port: string): Word;
  935. var
  936.   ProtoEnt: PProtoEnt;
  937.   ServEnt: PServEnt;
  938. begin
  939.   ProtoEnt := synsock.GetProtoByNumber(FProtocol);
  940.   ServEnt := nil;
  941.   if ProtoEnt <> nil then
  942.     ServEnt := synsock.GetServByName(PChar(Port), ProtoEnt^.p_name);
  943.   if ServEnt = nil then
  944.     Result := synsock.htons(StrToIntDef(Port, 0))
  945.   else
  946.     Result := ServEnt^.s_port;
  947. end;
  948.  
  949. procedure TBlockSocket.SetRemoteSin(IP, Port: string);
  950. begin
  951.   SetSin(FRemoteSin, IP, Port);
  952. end;
  953.  
  954. function TBlockSocket.GetLocalSinIP: string;
  955. begin
  956.   Result := GetSinIP(FLocalSin);
  957. end;
  958.  
  959. function TBlockSocket.GetRemoteSinIP: string;
  960. begin
  961.   Result := GetSinIP(FRemoteSin);
  962. end;
  963.  
  964. function TBlockSocket.GetLocalSinPort: Integer;
  965. begin
  966.   Result := GetSinPort(FLocalSin);
  967. end;
  968.  
  969. function TBlockSocket.GetRemoteSinPort: Integer;
  970. begin
  971.   Result := GetSinPort(FRemoteSin);
  972. end;
  973.  
  974. function TBlockSocket.CanRead(Timeout: Integer): Boolean;
  975. var
  976.   FDSet: TFDSet;
  977.   TimeVal: PTimeVal;
  978.   TimeV: TTimeVal;
  979.   x: Integer;
  980. begin
  981.   TimeV.tv_usec := (Timeout mod 1000) * 1000;
  982.   TimeV.tv_sec := Timeout div 1000;
  983.   TimeVal := @TimeV;
  984.   if Timeout = -1 then
  985.     TimeVal := nil;
  986.   FD_ZERO(FDSet);
  987.   FD_SET(FSocket, FDSet);
  988.   x := synsock.Select(FSocket + 1, @FDSet, nil, nil, TimeVal);
  989.   SockCheck(x);
  990.   if FLastError <> 0 then
  991.     x := 0;
  992.   Result := x > 0;
  993.   ExceptCheck;
  994.   if Result then
  995.     DoStatus(HR_CanRead, '');
  996. end;
  997.  
  998. function TBlockSocket.CanWrite(Timeout: Integer): Boolean;
  999. var
  1000.   FDSet: TFDSet;
  1001.   TimeVal: PTimeVal;
  1002.   TimeV: TTimeVal;
  1003.   x: Integer;
  1004. begin
  1005.   TimeV.tv_usec := (Timeout mod 1000) * 1000;
  1006.   TimeV.tv_sec := Timeout div 1000;
  1007.   TimeVal := @TimeV;
  1008.   if Timeout = -1 then
  1009.     TimeVal := nil;
  1010.   FD_ZERO(FDSet);
  1011.   FD_SET(FSocket, FDSet);
  1012.   x := synsock.Select(FSocket + 1, nil, @FDSet, nil, TimeVal);
  1013.   SockCheck(x);
  1014.   if FLastError <> 0 then
  1015.     x := 0;
  1016.   Result := x > 0;
  1017.   ExceptCheck;
  1018.   if Result then
  1019.     DoStatus(HR_CanWrite, '');
  1020. end;
  1021.  
  1022. function TBlockSocket.CanReadEx(Timeout: Integer): Boolean;
  1023. begin
  1024.   if FBuffer <> '' then
  1025.     Result := True
  1026.   else
  1027.     Result := CanRead(Timeout);
  1028. end;
  1029.  
  1030. function TBlockSocket.SendBufferTo(Buffer: Pointer; Length: Integer): Integer;
  1031. var
  1032.   Len: Integer;
  1033. begin
  1034.   LimitBandwidth(Length, FMaxSendBandwidth, FNextsend);
  1035.   Len := SizeOf(FRemoteSin);
  1036.   Result := synsock.SendTo(FSocket, Buffer^, Length, 0, FRemoteSin, Len);
  1037.   SockCheck(Result);
  1038.   ExceptCheck;
  1039.   DoStatus(HR_WriteCount, IntToStr(Result));
  1040. end;
  1041.  
  1042. function TBlockSocket.RecvBufferFrom(Buffer: Pointer; Length: Integer): Integer;
  1043. var
  1044.   Len: Integer;
  1045. begin
  1046.   LimitBandwidth(Length, FMaxRecvBandwidth, FNextRecv);
  1047.   Len := SizeOf(FRemoteSin);
  1048.   Result := synsock.RecvFrom(FSocket, Buffer^, Length, 0, FRemoteSin, Len);
  1049.   SockCheck(Result);
  1050.   ExceptCheck;
  1051.   DoStatus(HR_ReadCount, IntToStr(Result));
  1052. end;
  1053.  
  1054. function TBlockSocket.GetSizeRecvBuffer: Integer;
  1055. var
  1056.   l: Integer;
  1057. begin
  1058.   l := SizeOf(Result);
  1059.   SockCheck(synsock.GetSockOpt(FSocket, SOL_SOCKET, SO_RCVBUF, @Result, l));
  1060.   if FLastError <> 0 then
  1061.     Result := 1024;
  1062.   ExceptCheck;
  1063. end;
  1064.  
  1065. procedure TBlockSocket.SetSizeRecvBuffer(Size: Integer);
  1066. begin
  1067.   SockCheck(synsock.SetSockOpt(FSocket, SOL_SOCKET, SO_RCVBUF, @Size, SizeOf(Size)));
  1068.   ExceptCheck;
  1069. end;
  1070.  
  1071. function TBlockSocket.GetSizeSendBuffer: Integer;
  1072. var
  1073.   l: Integer;
  1074. begin
  1075.   l := SizeOf(Result);
  1076.   SockCheck(synsock.GetSockOpt(FSocket, SOL_SOCKET, SO_SNDBUF, @Result, l));
  1077.   if FLastError <> 0 then
  1078.     Result := 1024;
  1079.   ExceptCheck;
  1080. end;
  1081.  
  1082. procedure TBlockSocket.SetSizeSendBuffer(Size: Integer);
  1083. begin
  1084.   SockCheck(synsock.SetSockOpt(FSocket, SOL_SOCKET, SO_SNDBUF, @Size, SizeOf(Size)));
  1085.   ExceptCheck;
  1086. end;
  1087.  
  1088. procedure TBlockSocket.SetNonBlockMode(Value: Boolean);
  1089. var
  1090.   x: integer;
  1091. begin
  1092.   FNonBlockMode := Value;
  1093.   if Value then
  1094.     x := 1
  1095.   else
  1096.     x := 0;
  1097.   synsock.IoctlSocket(FSocket, FIONBIO, u_long(x));
  1098. end;
  1099.  
  1100. //See 'winsock2.txt' file in distribute package!
  1101. function TBlockSocket.SetTimeout(Timeout: Integer): Boolean;
  1102. begin
  1103.   Result := SetSendTimeout(Timeout) and SetRecvTimeout(Timeout);
  1104. end;
  1105.  
  1106. //See 'winsock2.txt' file in distribute package!
  1107. function TBlockSocket.SetSendTimeout(Timeout: Integer): Boolean;
  1108. begin
  1109.   Result := synsock.SetSockOpt(FSocket, SOL_SOCKET, SO_SNDTIMEO,
  1110.     @Timeout, SizeOf(Timeout)) <> SOCKET_ERROR;
  1111. end;
  1112.  
  1113. //See 'winsock2.txt' file in distribute package!
  1114. function TBlockSocket.SetRecvTimeout(Timeout: Integer): Boolean;
  1115. begin
  1116.   Result := synsock.SetSockOpt(FSocket, SOL_SOCKET, SO_RCVTIMEO,
  1117.     @Timeout, SizeOf(Timeout)) <> SOCKET_ERROR;
  1118. end;
  1119.  
  1120. function TBlockSocket.GroupCanRead(const SocketList: TList; Timeout: Integer;
  1121.   const CanReadList: TList): boolean;
  1122. var
  1123.   FDSet: TFDSet;
  1124.   TimeVal: PTimeVal;
  1125.   TimeV: TTimeVal;
  1126.   x, n: Integer;
  1127.   Max: Integer;
  1128. begin
  1129.   TimeV.tv_usec := (Timeout mod 1000) * 1000;
  1130.   TimeV.tv_sec := Timeout div 1000;
  1131.   TimeVal := @TimeV;
  1132.   if Timeout = -1 then
  1133.     TimeVal := nil;
  1134.   FD_ZERO(FDSet);
  1135.   Max := 0;
  1136.   for n := 0 to SocketList.Count - 1 do
  1137.     if TObject(SocketList.Items[n]) is TBlockSocket then
  1138.     begin
  1139.       if TBlockSocket(SocketList.Items[n]).Socket > Max then
  1140.         Max := TBlockSocket(SocketList.Items[n]).Socket;
  1141.       FD_SET(TBlockSocket(SocketList.Items[n]).Socket, FDSet);
  1142.     end;
  1143.   x := synsock.Select(Max + 1, @FDSet, nil, nil, TimeVal);
  1144.   SockCheck(x);
  1145.   ExceptCheck;
  1146.   if FLastError <> 0 then
  1147.     x := 0;
  1148.   Result := x > 0;
  1149.   CanReadList.Clear;
  1150.   if Result then
  1151.     for n := 0 to SocketList.Count - 1 do
  1152.       if TObject(SocketList.Items[n]) is TBlockSocket then
  1153.         if FD_ISSET(TBlockSocket(SocketList.Items[n]).Socket, FDSet) then
  1154.           CanReadList.Add(TBlockSocket(SocketList.Items[n]));
  1155. end;
  1156.  
  1157. function TBlockSocket.EnableReuse(Value: Boolean): Boolean;
  1158. var
  1159.   Opt: Integer;
  1160.   Res: Integer;
  1161. begin
  1162.   opt := Ord(Value);
  1163.   Res := synsock.SetSockOpt(FSocket, SOL_SOCKET, SO_REUSEADDR, @Opt, SizeOf(opt));
  1164.   SockCheck(Res);
  1165.   Result := res = 0;
  1166.   ExceptCheck;
  1167. end;
  1168.  
  1169. procedure TBlockSocket.DoStatus(Reason: THookSocketReason; const Value: string);
  1170. begin
  1171.   if assigned(OnStatus) then
  1172.     OnStatus(Self, Reason, Value);
  1173. end;
  1174.  
  1175. class function TBlockSocket.GetErrorDesc(ErrorCode: Integer): string;
  1176. begin
  1177.   case ErrorCode of
  1178.     0:
  1179.       Result := 'OK';
  1180.     WSAEINTR: {10004}
  1181.       Result := 'Interrupted system call';
  1182.     WSAEBADF: {10009}
  1183.       Result := 'Bad file number';
  1184.     WSAEACCES: {10013}
  1185.       Result := 'Permission denied';
  1186.     WSAEFAULT: {10014}
  1187.       Result := 'Bad address';
  1188.     WSAEINVAL: {10022}
  1189.       Result := 'Invalid argument';
  1190.     WSAEMFILE: {10024}
  1191.       Result := 'Too many open files';
  1192.     WSAEWOULDBLOCK: {10035}
  1193.       Result := 'Operation would block';
  1194.     WSAEINPROGRESS: {10036}
  1195.       Result := 'Operation now in progress';
  1196.     WSAEALREADY: {10037}
  1197.       Result := 'Operation already in progress';
  1198.     WSAENOTSOCK: {10038}
  1199.       Result := 'Socket operation on nonsocket';
  1200.     WSAEDESTADDRREQ: {10039}
  1201.       Result := 'Destination address required';
  1202.     WSAEMSGSIZE: {10040}
  1203.       Result := 'Message too long';
  1204.     WSAEPROTOTYPE: {10041}
  1205.       Result := 'Protocol wrong type for Socket';
  1206.     WSAENOPROTOOPT: {10042}
  1207.       Result := 'Protocol not available';
  1208.     WSAEPROTONOSUPPORT: {10043}
  1209.       Result := 'Protocol not supported';
  1210.     WSAESOCKTNOSUPPORT: {10044}
  1211.       Result := 'Socket not supported';
  1212.     WSAEOPNOTSUPP: {10045}
  1213.       Result := 'Operation not supported on Socket';
  1214.     WSAEPFNOSUPPORT: {10046}
  1215.       Result := 'Protocol family not supported';
  1216.     WSAEAFNOSUPPORT: {10047}
  1217.       Result := 'Address family not supported';
  1218.     WSAEADDRINUSE: {10048}
  1219.       Result := 'Address already in use';
  1220.     WSAEADDRNOTAVAIL: {10049}
  1221.       Result := 'Can''t assign requested address';
  1222.     WSAENETDOWN: {10050}
  1223.       Result := 'Network is down';
  1224.     WSAENETUNREACH: {10051}
  1225.       Result := 'Network is unreachable';
  1226.     WSAENETRESET: {10052}
  1227.       Result := 'Network dropped connection on reset';
  1228.     WSAECONNABORTED: {10053}
  1229.       Result := 'Software caused connection abort';
  1230.     WSAECONNRESET: {10054}
  1231.       Result := 'Connection reset by peer';
  1232.     WSAENOBUFS: {10055}
  1233.       Result := 'No Buffer space available';
  1234.     WSAEISCONN: {10056}
  1235.       Result := 'Socket is already connected';
  1236.     WSAENOTCONN: {10057}
  1237.       Result := 'Socket is not connected';
  1238.     WSAESHUTDOWN: {10058}
  1239.       Result := 'Can''t send after Socket shutdown';
  1240.     WSAETOOMANYREFS: {10059}
  1241.       Result := 'Too many references:can''t splice';
  1242.     WSAETIMEDOUT: {10060}
  1243.       Result := 'Connection timed out';
  1244.     WSAECONNREFUSED: {10061}
  1245.       Result := 'Connection refused';
  1246.     WSAELOOP: {10062}
  1247.       Result := 'Too many levels of symbolic links';
  1248.     WSAENAMETOOLONG: {10063}
  1249.       Result := 'File name is too long';
  1250.     WSAEHOSTDOWN: {10064}
  1251.       Result := 'Host is down';
  1252.     WSAEHOSTUNREACH: {10065}
  1253.       Result := 'No route to host';
  1254.     WSAENOTEMPTY: {10066}
  1255.       Result := 'Directory is not empty';
  1256.     WSAEPROCLIM: {10067}
  1257.       Result := 'Too many processes';
  1258.     WSAEUSERS: {10068}
  1259.       Result := 'Too many users';
  1260.     WSAEDQUOT: {10069}
  1261.       Result := 'Disk quota exceeded';
  1262.     WSAESTALE: {10070}
  1263.       Result := 'Stale NFS file handle';
  1264.     WSAEREMOTE: {10071}
  1265.       Result := 'Too many levels of remote in path';
  1266.     WSASYSNOTREADY: {10091}
  1267.       Result := 'Network subsystem is unusable';
  1268.     WSAVERNOTSUPPORTED: {10092}
  1269.       Result := 'Winsock DLL cannot support this application';
  1270.     WSANOTINITIALISED: {10093}
  1271.       Result := 'Winsock not initialized';
  1272.     WSAEDISCON: {10101}
  1273.       Result := 'Disconnect';
  1274.     WSAHOST_NOT_FOUND: {11001}
  1275.       Result := 'Host not found';
  1276.     WSATRY_AGAIN: {11002}
  1277.       Result := 'Non authoritative - host not found';
  1278.     WSANO_RECOVERY: {11003}
  1279.       Result := 'Non recoverable error';
  1280.     WSANO_DATA: {11004}
  1281.       Result := 'Valid name, no data record of requested type'
  1282.   else
  1283.     Result := 'Not a Winsock error (' + IntToStr(ErrorCode) + ')';
  1284.   end;
  1285. end;
  1286.  
  1287. {======================================================================}
  1288.  
  1289. constructor TSocksBlockSocket.Create;
  1290. begin
  1291.   inherited Create;
  1292.   FSocksIP:= '';
  1293.   FSocksPort:= '1080';
  1294.   FSocksTimeout:= 300000;
  1295.   FSocksUsername:= '';
  1296.   FSocksPassword:= '';
  1297.   FUsingSocks := False;
  1298.   FSocksResolver := True;
  1299.   FSocksLastError := 0;
  1300.   FSocksResponseIP := '';
  1301.   FSocksResponsePort := '';
  1302.   FSocksLocalIP := '';
  1303.   FSocksLocalPort := '';
  1304.   FSocksRemoteIP := '';
  1305.   FSocksRemotePort := '';
  1306.   FBypassFlag := False;
  1307. end;
  1308.  
  1309. function TSocksBlockSocket.SocksOpen: boolean;
  1310. var
  1311.   Buf: string;
  1312.   n: integer;
  1313. begin
  1314.   Result := False;
  1315.   FUsingSocks := False;
  1316.   FBypassFlag := True;
  1317.   try
  1318.     if FSocksUsername = '' then
  1319.       Buf := #5 + #1 + #0
  1320.     else
  1321.       Buf := #5 + #2 + #2 +#0;
  1322.     SendString(Buf);
  1323.     Buf := RecvPacket(FSocksTimeout);
  1324.     FBuffer := Copy(Buf, 3, Length(buf) - 2);
  1325.     if Length(Buf) < 2 then
  1326.       Exit;
  1327.     if Buf[1] <> #5 then
  1328.       Exit;
  1329.     n := Ord(Buf[2]);
  1330.     case n of
  1331.       0: //not need authorisation
  1332.         ;
  1333.       2:
  1334.         begin
  1335.           Buf := #1 + char(Length(FSocksUsername)) + FSocksUsername
  1336.             + char(Length(FSocksPassword)) + FSocksPassword;
  1337.           SendString(Buf);
  1338.           Buf := RecvPacket(FSocksTimeout);
  1339.           FBuffer := Copy(Buf, 3, Length(buf) - 2);
  1340.           if Length(Buf) < 2 then
  1341.             Exit;
  1342.           if Buf[2] <> #0 then
  1343.             Exit;
  1344.         end;
  1345.     else
  1346.       Exit;
  1347.     end;
  1348.     FUsingSocks := True;
  1349.     Result := True;
  1350.   finally
  1351.     FBypassFlag := False;
  1352.   end;
  1353. end;
  1354.  
  1355. function TSocksBlockSocket.SocksRequest(Cmd: Byte;
  1356.   const IP, Port: string): Boolean;
  1357. var
  1358.   Buf: string;
  1359. begin
  1360.   FBypassFlag := True;
  1361.   try
  1362.     Buf := #5 + char(Cmd) + #0 + SocksCode(IP, Port);
  1363.     SendString(Buf);
  1364.     Result := FLastError = 0;
  1365.   finally
  1366.     FBypassFlag := False;
  1367.   end;
  1368. end;
  1369.  
  1370. function TSocksBlockSocket.SocksResponse: Boolean;
  1371. var
  1372.   Buf: string;
  1373.   x: integer;
  1374. begin
  1375.   Result := False;
  1376.   FBypassFlag := True;
  1377.   try
  1378.     FSocksResponseIP := '';
  1379.     FSocksResponsePort := '';
  1380.     Buf := RecvPacket(FSocksTimeout);
  1381.     if FLastError <> 0 then
  1382.       Exit;
  1383.     if Length(Buf) < 5 then
  1384.       Exit;
  1385.     if Buf[1] <> #5 then
  1386.       Exit;
  1387.     FSocksLastError := Ord(Buf[2]);
  1388.     if FSocksLastError <> 0 then
  1389.       Exit;
  1390.     x := SocksDecode(Buf);
  1391.     FBuffer := Copy(Buf, x, Length(buf) - x + 1);
  1392.     Result := True;
  1393.   finally
  1394.     FBypassFlag := False;
  1395.   end;
  1396. end;
  1397.  
  1398. function TSocksBlockSocket.SocksCode(IP, Port: string): string;
  1399. begin
  1400.   if IsIP(IP) then
  1401.     Result := #1 + IPToID(IP)
  1402.   else
  1403.     if FSocksResolver then
  1404.       Result := #3 + char(Length(IP)) + IP
  1405.     else
  1406.       Result := #1 + IPToID(ResolveName(IP));
  1407.   Result := Result + CodeInt(synsock.htons(ResolvePort(Port)));
  1408. end;
  1409.  
  1410. function TSocksBlockSocket.SocksDecode(Value: string): integer;
  1411. var
  1412.   Atyp: Byte;
  1413.   y, n: integer;
  1414.   w: Word;
  1415. begin
  1416.   FSocksResponsePort := '0';
  1417.   Atyp := Ord(Value[4]);
  1418.   Result := 5;
  1419.   case Atyp of
  1420.     1:
  1421.       begin
  1422.         if Length(Value) < 10 then
  1423.           Exit;
  1424.         FSocksResponseIP := Format('%d.%d.%d.%d',
  1425.             [Ord(Value[5]), Ord(Value[6]), Ord(Value[7]), Ord(Value[8])]);
  1426.         Result := 9;
  1427.       end;
  1428.     3:
  1429.       begin
  1430.         y := Ord(Value[5]);
  1431.         if Length(Value) < (5 + y + 2) then
  1432.           Exit;
  1433.         for n := 6 to 6 + y - 1 do
  1434.           FSocksResponseIP := FSocksResponseIP + Value[n];
  1435.         Result := 5 + y + 1;
  1436.       end;
  1437.   else
  1438.     Exit;
  1439.   end;
  1440.   w := DecodeInt(Value, Result);
  1441.   FSocksResponsePort := IntToStr(w);
  1442.   Result := Result + 2;
  1443. end;
  1444.  
  1445. {======================================================================}
  1446.  
  1447. destructor TUDPBlockSocket.Destroy;
  1448. begin
  1449.   if Assigned(FSocksControlSock) then
  1450.     FSocksControlSock.Free;
  1451.   inherited;
  1452. end;
  1453.  
  1454. procedure TUDPBlockSocket.CreateSocket;
  1455. begin
  1456.   FSocket := synsock.Socket(PF_INET, Integer(SOCK_DGRAM), IPPROTO_UDP);
  1457.   FProtocol := IPPROTO_UDP;
  1458.   inherited CreateSocket;
  1459. end;
  1460.  
  1461. function TUDPBlockSocket.EnableBroadcast(Value: Boolean): Boolean;
  1462. var
  1463.   Opt: Integer;
  1464.   Res: Integer;
  1465. begin
  1466.   opt := Ord(Value);
  1467.   Res := synsock.SetSockOpt(FSocket, SOL_SOCKET, SO_BROADCAST, @Opt, SizeOf(opt));
  1468.   SockCheck(Res);
  1469.   Result := res = 0;
  1470.   ExceptCheck;
  1471. end;
  1472.  
  1473. procedure TUDPBlockSocket.Connect(IP, Port: string);
  1474. begin
  1475.   AutoCreateSocket;
  1476.   SetRemoteSin(IP, Port);
  1477.   FBuffer := '';
  1478.   DoStatus(HR_Connect, IP + ':' + Port);
  1479. end;
  1480.  
  1481. function TUDPBlockSocket.RecvBuffer(Buffer: Pointer; Length: Integer): Integer;
  1482. begin
  1483.   Result := RecvBufferFrom(Buffer, Length);
  1484. end;
  1485.  
  1486. function TUDPBlockSocket.SendBuffer(Buffer: Pointer; Length: Integer): Integer;
  1487. begin
  1488.   Result := SendBufferTo(Buffer, Length);
  1489. end;
  1490.  
  1491. function TUDPBlockSocket.UdpAssociation: Boolean;
  1492. var
  1493.   b: Boolean;
  1494. begin
  1495.   Result := True;
  1496.   FUsingSocks := False;
  1497.   if FSocksIP <> '' then
  1498.   begin
  1499.     Result := False;
  1500.     if not Assigned(FSocksControlSock) then
  1501.       FSocksControlSock := TTCPBlockSocket.Create;
  1502.     FSocksControlSock.CloseSocket;
  1503.     FSocksControlSock.CreateSocket;
  1504.     FSocksControlSock.Connect(FSocksIP, FSocksPort);
  1505.     if FSocksControlSock.LastError <> 0 then
  1506.       Exit;
  1507.     // if not assigned local port, assign it!
  1508.     if GetLocalSinPort = 0 then
  1509.       Bind(GetLocalSinIP, '0');
  1510.     GetSins;
  1511.     //open control TCP connection to SOCKS
  1512.     b := FSocksControlSock.SocksOpen;
  1513.     if b then
  1514.       b := FSocksControlSock.SocksRequest(3, GetLocalSinIP,
  1515.         IntToStr(GetLocalSinPort));
  1516.     if b then
  1517.       b := FSocksControlSock.SocksResponse;
  1518.     if not b and (FLastError = 0) then
  1519.       FLastError := WSANO_RECOVERY;
  1520.     FUsingSocks :=FSocksControlSock.UsingSocks;
  1521.     FSocksRemoteIP := FSocksControlSock.FSocksResponseIP;
  1522.     FSocksRemotePort := FSocksControlSock.FSocksResponsePort;
  1523.     Result := True;
  1524.   end;
  1525. end;
  1526.  
  1527. function TUDPBlockSocket.SendBufferTo(Buffer: Pointer; Length: Integer): Integer;
  1528. var
  1529.   SIp: string;
  1530.   SPort: integer;
  1531.   Buf: string;
  1532. begin
  1533.   UdpAssociation;
  1534.   if FUsingSocks then
  1535.   begin
  1536.     Sip := GetRemoteSinIp;
  1537.     SPort := GetRemoteSinPort;
  1538.     SetRemoteSin(FSocksRemoteIP, FSocksRemotePort);
  1539.     SetLength(Buf,Length);
  1540.     Move(Buffer^, PChar(Buf)^, Length);
  1541.     Buf := #0 + #0 + #0 + SocksCode(Sip, IntToStr(SPort)) + Buf;
  1542.     Result := inherited SendBufferTo(PChar(Buf), System.Length(buf));
  1543.     SetRemoteSin(Sip, IntToStr(SPort));
  1544.   end
  1545.   else
  1546.   begin
  1547.     Result := inherited SendBufferTo(Buffer, Length);
  1548.     GetSins;
  1549.   end;
  1550. end;
  1551.  
  1552. function TUDPBlockSocket.RecvBufferFrom(Buffer: Pointer; Length: Integer): Integer;
  1553. var
  1554.   Buf: string;
  1555.   x: integer;
  1556. begin
  1557.   Result := inherited RecvBufferFrom(Buffer, Length);
  1558.   if FUsingSocks then
  1559.   begin
  1560.     SetLength(Buf, Result);
  1561.     Move(Buffer^, PChar(Buf)^, Result);
  1562.     x := SocksDecode(Buf);
  1563.     Result := Result - x + 1;
  1564.     Buf := Copy(Buf, x, Result);
  1565.     Move(PChar(Buf)^, Buffer^, Result);
  1566.     SetRemoteSin(FSocksResponseIP, FSocksResponsePort);
  1567.   end;
  1568. end;
  1569.  
  1570. procedure TUDPBlockSocket.AddMulticast(MCastIP: string);
  1571. var
  1572.   Multicast: TMulticast;
  1573. begin
  1574.   Multicast.MCastAddr := synsock.inet_addr(PChar(MCastIP));
  1575.   Multicast.MCastIfc := u_long(INADDR_ANY);
  1576.   SockCheck(synsock.SetSockOpt(FSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
  1577.     pchar(@Multicast), SizeOf(Multicast)));
  1578.   ExceptCheck;
  1579. end;
  1580.  
  1581. procedure TUDPBlockSocket.DropMulticast(MCastIP: string);
  1582. var
  1583.   Multicast: TMulticast;
  1584. begin
  1585.   Multicast.MCastAddr := synsock.inet_addr(PChar(MCastIP));
  1586.   Multicast.MCastIfc := u_long(INADDR_ANY);
  1587.   SockCheck(synsock.SetSockOpt(FSocket, IPPROTO_IP, IP_DROP_MEMBERSHIP,
  1588.     pchar(@Multicast), SizeOf(Multicast)));
  1589.   ExceptCheck;
  1590. end;
  1591.  
  1592. {======================================================================}
  1593.  
  1594. function PasswordCallback(buf:PChar; size:Integer; rwflag:Integer; userdata: Pointer):Integer; cdecl;
  1595. var
  1596.   Password: String;
  1597. begin
  1598.   Password := '';
  1599.   if TTCPBlockSocket(userdata) is TTCPBlockSocket then
  1600.     Password := TTCPBlockSocket(userdata).SSLPassword;
  1601.   if Length(Password) > (Size - 1) then
  1602.     SetLength(Password, Size - 1);
  1603.   Result := Length(Password);
  1604.   StrLCopy(buf, PChar(Password + #0), Result + 1);
  1605. end;
  1606.  
  1607. constructor TTCPBlockSocket.Create;
  1608. begin
  1609.   inherited Create;
  1610.   FSslEnabled := False;
  1611.   FSslBypass := False;
  1612.   FSSLCiphers := 'DEFAULT';
  1613.   FSSLCertificateFile := '';
  1614.   FSSLPrivateKeyFile := '';
  1615.   FSSLPassword  := '';
  1616.   FSsl := nil;
  1617.   Fctx := nil;
  1618.   FSSLLastError := 0;
  1619.   FSSLLastErrorDesc := '';
  1620.   FSSLverifyCert := False;
  1621.   FHTTPTunnelIP := '';
  1622.   FHTTPTunnelPort := '';
  1623.   FHTTPTunnel := False;
  1624.   FHTTPTunnelRemoteIP := '';
  1625.   FHTTPTunnelRemotePort := '';
  1626.   FHTTPTunnelUser := '';
  1627.   FHTTPTunnelPass := '';
  1628. end;
  1629.  
  1630. destructor TTCPBlockSocket.Destroy;
  1631. begin
  1632.   if FSslEnabled then
  1633.     SslEnabled := False;
  1634.   inherited;
  1635. end;
  1636.  
  1637. procedure TTCPBlockSocket.CreateSocket;
  1638. begin
  1639.   FSocket := synsock.Socket(PF_INET, Integer(SOCK_STREAM), IPPROTO_TCP);
  1640.   FProtocol := IPPROTO_TCP;
  1641.   inherited CreateSocket;
  1642. end;
  1643.  
  1644. procedure TTCPBlockSocket.CloseSocket;
  1645. begin
  1646.   synsock.Shutdown(FSocket, 1);
  1647.   inherited CloseSocket;
  1648. end;
  1649.  
  1650. function TTCPBlockSocket.WaitingData: Integer;
  1651. begin
  1652.   Result := 0;
  1653.   if FSslEnabled and not(FSslBypass) and not(FBypassFlag) then
  1654.     Result := sslpending(Fssl);
  1655.   if Result = 0 then
  1656.     Result := inherited WaitingData;
  1657. end;
  1658.  
  1659. procedure TTCPBlockSocket.Listen;
  1660. var
  1661.   b: Boolean;
  1662.   Sip,SPort: string;
  1663. begin
  1664.   if FSocksIP = '' then
  1665.   begin
  1666.     SockCheck(synsock.Listen(FSocket, SOMAXCONN));
  1667.     GetSins;
  1668.   end
  1669.   else
  1670.   begin
  1671.     Sip := GetLocalSinIP;
  1672.     if Sip = '0.0.0.0' then
  1673.       Sip := LocalName;
  1674.     SPort := IntToStr(GetLocalSinPort);
  1675.     inherited Connect(FSocksIP, FSocksPort);
  1676.     b := SocksOpen;
  1677.     if b then
  1678.       b := SocksRequest(2, Sip, SPort);
  1679.     if b then
  1680.       b := SocksResponse;
  1681.     if not b and (FLastError = 0) then
  1682.       FLastError := WSANO_RECOVERY;
  1683.     FSocksLocalIP := FSocksResponseIP;
  1684.     if FSocksLocalIP = '0.0.0.0' then
  1685.       FSocksLocalIP := FSocksIP;
  1686.     FSocksLocalPort := FSocksResponsePort;
  1687.     FSocksRemoteIP := '';
  1688.     FSocksRemotePort := '';
  1689.   end;
  1690.   ExceptCheck;
  1691.   DoStatus(HR_Listen, '');
  1692. end;
  1693.  
  1694. function TTCPBlockSocket.Accept: TSocket;
  1695. var
  1696.   Len: Integer;
  1697. begin
  1698.   if FUsingSocks then
  1699.   begin
  1700.     if not SocksResponse and (FLastError = 0) then
  1701.       FLastError := WSANO_RECOVERY;
  1702.     FSocksRemoteIP := FSocksResponseIP;
  1703.     FSocksRemotePort := FSocksResponsePort;
  1704.     Result := FSocket;
  1705.   end
  1706.   else
  1707.   begin
  1708.     Len := SizeOf(FRemoteSin);
  1709.     Result := synsock.Accept(FSocket, @FRemoteSin, @Len);
  1710.     SockCheck(Result);
  1711.   end;
  1712.   ExceptCheck;
  1713.   DoStatus(HR_Accept, '');
  1714. end;
  1715.  
  1716. procedure TTCPBlockSocket.Connect(IP, Port: string);
  1717. begin
  1718.   AutoCreateSocket;
  1719.   if FSocksIP <> '' then
  1720.     SocksDoConnect(IP, Port)
  1721.   else
  1722.     if FHTTPTunnelIP <> '' then
  1723.       HTTPTunnelDoConnect(IP, Port)
  1724.     else
  1725.       inherited Connect(IP, Port);
  1726.   if FSslEnabled then
  1727.     SSLDoConnect;
  1728. end;
  1729.  
  1730. procedure TTCPBlockSocket.SocksDoConnect(IP, Port: string);
  1731. var
  1732.   b: Boolean;
  1733. begin
  1734.   inherited Connect(FSocksIP, FSocksPort);
  1735.   if FLastError = 0 then
  1736.   begin
  1737.     b := SocksOpen;
  1738.     if b then
  1739.       b := SocksRequest(1, IP, Port);
  1740.     if b then
  1741.       b := SocksResponse;
  1742.     if not b and (FLastError = 0) then
  1743.       FLastError := WSASYSNOTREADY;
  1744.     FSocksLocalIP := FSocksResponseIP;
  1745.     FSocksLocalPort := FSocksResponsePort;
  1746.     FSocksRemoteIP := IP;
  1747.     FSocksRemotePort := Port;
  1748.   end;
  1749.   ExceptCheck;
  1750.   DoStatus(HR_Connect, IP + ':' + Port);
  1751. end;
  1752.  
  1753. procedure TTCPBlockSocket.HTTPTunnelDoConnect(IP, Port: string);
  1754. //bugfixed by Mike Green (mgreen@emixode.com)
  1755. var
  1756.   s: string;
  1757. begin
  1758.   try
  1759.     FBypassFlag := True;
  1760.     inherited Connect(FHTTPTunnelIP, FHTTPTunnelPort);
  1761.     if FLastError <> 0 then
  1762.       Exit;
  1763.     FHTTPTunnel := False;
  1764.     SendString('CONNECT ' + IP + ':' + Port + ' HTTP/1.0' + #$0d + #$0a);
  1765.     if FHTTPTunnelUser <> '' then
  1766.     Sendstring('Proxy-Authorization: Basic ' +
  1767.       EncodeBase64(FHTTPTunnelUser + ':' + FHTTPTunnelPass) + #$0d + #$0a);
  1768.     SendString(#$0d + #$0a);
  1769.     repeat
  1770.       s := RecvTerminated(30000, #$0a);
  1771.       if FLastError <> 0 then
  1772.         Break;
  1773.       if (Pos('HTTP/', s) = 1) and (Length(s) > 11) then
  1774.         FHTTPTunnel := s[10] = '2';
  1775.     until (s = '') or (s = #$0d);
  1776.     if (FLasterror = 0) and not FHTTPTunnel then
  1777.       FLastError := WSASYSNOTREADY;
  1778.     FHTTPTunnelRemoteIP := IP;
  1779.     FHTTPTunnelRemotePort := Port;
  1780.   finally
  1781.     FBypassFlag := False;
  1782.   end;
  1783.   ExceptCheck;
  1784. end;
  1785.  
  1786. procedure TTCPBlockSocket.SSLDoConnect;
  1787. begin
  1788.   FLastError := 0;
  1789.   if not FSSLEnabled then
  1790.     SSLEnabled := True;
  1791.   if (FLastError = 0) then
  1792.     if sslsetfd(FSsl, FSocket) < 1 then
  1793.     begin
  1794.       FLastError := WSASYSNOTREADY;
  1795.       SSLCheck;
  1796.     end;
  1797.   if (FLastError = 0) then
  1798.     if sslconnect(FSsl) < 1 then
  1799.       FLastError := WSASYSNOTREADY;
  1800.   ExceptCheck;
  1801. end;
  1802.  
  1803. procedure TTCPBlockSocket.SSLDoShutdown;
  1804. begin
  1805.   FLastError := 0;
  1806.   if sslshutdown(FSsl) < 0 then
  1807.     FLastError := WSASYSNOTREADY;
  1808.   ExceptCheck;
  1809.   SSLEnabled := False;
  1810. end;
  1811.  
  1812. function TTCPBlockSocket.GetLocalSinIP: string;
  1813. begin
  1814.   if FUsingSocks then
  1815.     Result := FSocksLocalIP
  1816.   else
  1817.     Result := inherited GetLocalSinIP;
  1818. end;
  1819.  
  1820. function TTCPBlockSocket.GetRemoteSinIP: string;
  1821. begin
  1822.   if FUsingSocks then
  1823.     Result := FSocksRemoteIP
  1824.   else
  1825.     if FHTTPTunnel then
  1826.       Result := FHTTPTunnelRemoteIP
  1827.     else
  1828.       Result := inherited GetRemoteSinIP;
  1829. end;
  1830.  
  1831. function TTCPBlockSocket.GetLocalSinPort: Integer;
  1832. begin
  1833.   if FUsingSocks then
  1834.     Result := StrToIntDef(FSocksLocalPort, 0)
  1835.   else
  1836.     Result := inherited GetLocalSinPort;
  1837. end;
  1838.  
  1839. function TTCPBlockSocket.GetRemoteSinPort: Integer;
  1840. begin
  1841.   if FUsingSocks then
  1842.     Result := StrToIntDef(FSocksRemotePort, 0)
  1843.   else
  1844.     if FHTTPTunnel then
  1845.       Result := StrToIntDef(FHTTPTunnelRemotePort, 0)
  1846.     else
  1847.       Result := inherited GetRemoteSinPort;
  1848. end;
  1849.  
  1850. function TTCPBlockSocket.SSLCheck: Boolean;
  1851. var
  1852.   ErrBuf: array[0..255] of Char;
  1853. begin
  1854.   Result := true;
  1855.   FSSLLastErrorDesc := '';
  1856.   FSSLLastError := ErrGetError;
  1857.   ErrClearError;
  1858.   if FSSLLastError <> 0 then
  1859.   begin
  1860.     Result := False;
  1861.     ErrErrorString(FSSLLastError, ErrBuf);
  1862.     FSSLLastErrorDesc := ErrBuf;
  1863.   end;
  1864. end;
  1865.  
  1866. function TTCPBlockSocket.SetSslKeys: boolean;
  1867. begin
  1868.   Result := True;
  1869.   if FSSLCertificateFile <> '' then
  1870.     if SslCtxUseCertificateChainFile(FCtx, PChar(FSSLCertificateFile)) <> 1 then
  1871.     begin
  1872.       Result := False;
  1873.       SSLCheck;
  1874.       Exit;
  1875.     end;
  1876.   if FSSLPrivateKeyFile <> '' then
  1877.     if SslCtxUsePrivateKeyFile(FCtx, PChar(FSSLPrivateKeyFile), 1) <> 1 then
  1878.     begin
  1879.       Result := False;
  1880.       SSLCheck;
  1881.       Exit;
  1882.     end;
  1883.   if FSSLCertCAFile <> '' then
  1884.     if SslCtxLoadVerifyLocations(FCtx, PChar(FSSLCertCAFile), nil) <> 1 then
  1885.     begin
  1886.       Result := False;
  1887.       SSLCheck;
  1888.     end;
  1889. end;
  1890.  
  1891. procedure TTCPBlockSocket.SetSslEnabled(Value: Boolean);
  1892. var
  1893.   err: Boolean;
  1894. begin
  1895.   FLastError := 0;
  1896.   if Value <> FSslEnabled then
  1897.     if Value then
  1898.     begin
  1899.       FBuffer := '';
  1900.       FSSLLastErrorDesc := '';
  1901.       FSSLLastError := 0;
  1902.       if InitSSLInterface then
  1903.       begin
  1904.         SslLibraryInit;
  1905.         SslLoadErrorStrings;
  1906.         err := False;
  1907.         Fctx := nil;
  1908.         Fctx := SslCtxNew(SslMethodV23);
  1909.         if Fctx = nil then
  1910.         begin
  1911.           SSLCheck;
  1912.           FlastError := WSAEPROTONOSUPPORT;
  1913.           err := True;
  1914.         end
  1915.         else
  1916.         begin
  1917.           SslCtxSetCipherList(Fctx, PChar(FSSLCiphers));
  1918.           if FSSLverifyCert then
  1919.             SslCtxSetVerify(FCtx, SSL_VERIFY_PEER, nil)
  1920.           else
  1921.             SslCtxSetVerify(FCtx, SSL_VERIFY_NONE, nil);
  1922.           SslCtxSetDefaultPasswdCb(FCtx, @PasswordCallback);
  1923.           SslCtxSetDefaultPasswdCbUserdata(FCtx, self);
  1924.           if not SetSSLKeys then
  1925.             FLastError := WSAEINVAL
  1926.           else
  1927.           begin
  1928.             Fssl := nil;
  1929.             Fssl := SslNew(Fctx);
  1930.             if Fssl = nil then
  1931.             begin
  1932.               SSLCheck;
  1933.               FlastError := WSAEPROTONOSUPPORT;
  1934.               err := True;
  1935.             end;
  1936.           end;
  1937.         end;
  1938.         if err then
  1939.           DestroySSLInterface
  1940.         else
  1941.           FSslEnabled := True;
  1942.       end
  1943.       else
  1944.       begin
  1945.         DestroySSLInterface;
  1946.         FlastError := WSAEPROTONOSUPPORT;
  1947.       end;
  1948.     end
  1949.     else
  1950.     begin
  1951.       FBuffer := '';
  1952.       sslfree(Fssl);
  1953.       SslCtxFree(Fctx);
  1954.       DestroySSLInterface;
  1955.       FSslEnabled := False;
  1956.     end;
  1957.   ExceptCheck;
  1958. end;
  1959.  
  1960. function TTCPBlockSocket.RecvBuffer(Buffer: Pointer; Length: Integer): Integer;
  1961. var
  1962.   err: integer;
  1963. begin
  1964.   if FSslEnabled and not(FSslBypass) and not(FBypassFlag) then
  1965.   begin
  1966.     FLastError := 0;
  1967.     repeat
  1968.       Result := SslRead(FSsl, Buffer, Length);
  1969.       err := SslGetError(FSsl, Result);
  1970.     until (err <> SSL_ERROR_WANT_READ) and (err <> SSL_ERROR_WANT_WRITE);
  1971.     if err = SSL_ERROR_ZERO_RETURN then
  1972.       Result := 0
  1973.     else
  1974.       if (err <> 0) then
  1975.         FLastError := WSASYSNOTREADY;
  1976.     ExceptCheck;
  1977.     DoStatus(HR_ReadCount, IntToStr(Result));
  1978.   end
  1979.   else
  1980.     Result := inherited RecvBuffer(Buffer, Length);
  1981. end;
  1982.  
  1983. function TTCPBlockSocket.SendBuffer(Buffer: Pointer; Length: Integer): Integer;
  1984. var
  1985.   err: integer;
  1986. begin
  1987.   if FSslEnabled and not(FSslBypass) and not(FBypassFlag) then
  1988.   begin
  1989.     FLastError := 0;
  1990.     repeat
  1991.       Result := SslWrite(FSsl, Buffer, Length);
  1992.       err := SslGetError(FSsl, Result);
  1993.     until (err <> SSL_ERROR_WANT_READ) and (err <> SSL_ERROR_WANT_WRITE);
  1994.     if err = SSL_ERROR_ZERO_RETURN then
  1995.       Result := 0
  1996.     else
  1997.       if (err <> 0) then
  1998.         FLastError := WSASYSNOTREADY;
  1999.     ExceptCheck;
  2000.     DoStatus(HR_WriteCount, IntToStr(Result));
  2001.   end
  2002.   else
  2003.     Result := inherited SendBuffer(Buffer, Length);
  2004. end;
  2005.  
  2006. function TTCPBlockSocket.SSLAcceptConnection: Boolean;
  2007. begin
  2008.   FLastError := 0;
  2009.   if not FSSLEnabled then
  2010.     SSLEnabled := True;
  2011.   if (FLastError = 0) then
  2012.     if sslsetfd(FSsl, FSocket) < 1 then
  2013.     begin
  2014.       FLastError := WSASYSNOTREADY;
  2015.       SSLCheck;
  2016.     end;
  2017.   if (FLastError = 0) then
  2018.     if sslAccept(FSsl) < 1 then
  2019.       FLastError := WSASYSNOTREADY;
  2020.   ExceptCheck;
  2021.   Result := FLastError = 0;
  2022. end;
  2023.  
  2024. function TTCPBlockSocket.SSLGetSSLVersion: string;
  2025. begin
  2026.   Result := SSlGetVersion(FSsl);
  2027. end;
  2028.  
  2029. function TTCPBlockSocket.SSLGetPeerSubject: string;
  2030. var
  2031.   cert: PX509;
  2032.   s: string;
  2033. begin
  2034.   cert := SSLGetPeerCertificate(Fssl);
  2035.   setlength(s, 4096);
  2036.   Result := SslX509NameOneline(SslX509GetSubjectName(cert), PChar(s), length(s));
  2037.   SslX509Free(cert);
  2038. end;
  2039.  
  2040. function TTCPBlockSocket.SSLGetPeerIssuer: string;
  2041. var
  2042.   cert: PX509;
  2043.   s: string;
  2044. begin
  2045.   cert := SSLGetPeerCertificate(Fssl);
  2046.   setlength(s, 4096);
  2047.   Result := SslX509NameOneline(SslX509GetIssuerName(cert), PChar(s), length(s));
  2048.   SslX509Free(cert);
  2049. end;
  2050.  
  2051. function TTCPBlockSocket.SSLGetPeerSubjectHash: Cardinal;
  2052. var
  2053.   cert: PX509;
  2054. begin
  2055.   cert := SSLGetPeerCertificate(Fssl);
  2056.   Result := SslX509NameHash(SslX509GetSubjectName(cert));
  2057.   SslX509Free(cert);
  2058. end;
  2059.  
  2060. function TTCPBlockSocket.SSLGetPeerIssuerHash: Cardinal;
  2061. var
  2062.   cert: PX509;
  2063. begin
  2064.   cert := SSLGetPeerCertificate(Fssl);
  2065.   Result := SslX509NameHash(SslX509GetIssuerName(cert));
  2066.   SslX509Free(cert);
  2067. end;
  2068.  
  2069. function TTCPBlockSocket.SSLGetPeerFingerprint: string;
  2070. var
  2071.   cert: PX509;
  2072.   x: integer;
  2073. begin
  2074.   cert := SSLGetPeerCertificate(Fssl);
  2075.   setlength(Result, EVP_MAX_MD_SIZE);
  2076.   SslX509Digest(cert, SslEvpMd5, PChar(Result), @x);
  2077.   SetLength(Result, x);
  2078.   SslX509Free(cert);
  2079. end;
  2080.  
  2081. {======================================================================}
  2082.  
  2083. //See 'winsock2.txt' file in distribute package!
  2084.  
  2085. procedure TICMPBlockSocket.CreateSocket;
  2086. begin
  2087.   FSocket := synsock.Socket(PF_INET, Integer(SOCK_RAW), IPPROTO_ICMP);
  2088.   FProtocol := IPPROTO_ICMP;
  2089.   inherited CreateSocket;
  2090. end;
  2091.  
  2092. {======================================================================}
  2093.  
  2094. //See 'winsock2.txt' file in distribute package!
  2095.  
  2096. procedure TRAWBlockSocket.CreateSocket;
  2097. begin
  2098.   FSocket := synsock.Socket(PF_INET, Integer(SOCK_RAW), IPPROTO_RAW);
  2099.   FProtocol := IPPROTO_RAW;
  2100.   inherited CreateSocket;
  2101. end;
  2102.  
  2103. {======================================================================}
  2104.  
  2105. constructor TSynaClient.Create;
  2106. begin
  2107.   inherited Create;
  2108.   FIPInterface := cAnyHost;
  2109.   FTargetHost := cLocalhost;
  2110.   FTargetPort := cAnyPort;
  2111.   FTimeout := 5000;
  2112. end;
  2113.  
  2114. end.
  2115.