home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 December / Chip_2001-12_cd1.bin / zkuste / delphi / unity / d23456 / SYNAPSE.ZIP / source / lib / blcksock.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  2001-09-23  |  39.6 KB  |  1,480 lines

  1. {==============================================================================|
  2. | Project : Delphree - Synapse                                   | 004.000.000 |
  3. |==============================================================================|
  4. | Content: Library base                                                        |
  5. |==============================================================================|
  6. | The contents of this file are subject to the Mozilla Public License Ver. 1.1 |
  7. | (the "License"); you may not use this file except in compliance with the     |
  8. | License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ |
  9. |                                                                              |
  10. | Software distributed under the License is distributed on an "AS IS" basis,   |
  11. | WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for |
  12. | the specific language governing rights and limitations under the License.    |
  13. |==============================================================================|
  14. | The Original Code is Synapse Delphi Library.                                 |
  15. |==============================================================================|
  16. | The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
  17. | Portions created by Lukas Gebauer are Copyright (c)1999,2000,2001.           |
  18. | All Rights Reserved.                                                         |
  19. |==============================================================================|
  20. | Contributor(s):                                                              |
  21. |==============================================================================|
  22. | History: see HISTORY.HTM from distribution package                           |
  23. |          (Found at URL: http://www.ararat.cz/synapse/)                       |
  24. |==============================================================================}
  25.  
  26. {$WEAKPACKAGEUNIT ON}
  27.  
  28. unit blcksock;
  29.  
  30. interface
  31.  
  32. uses
  33.   SysUtils, Classes,
  34. {$IFDEF LINUX}
  35.   Libc, kernelioctl,
  36. {$ELSE}
  37.   Windows, WinSock,
  38. {$ENDIF}
  39.   synsock, SynaUtil;
  40.  
  41. const
  42.   cLocalhost = 'localhost';
  43.  
  44. type
  45.  
  46.   ESynapseError = class(Exception)
  47.   public
  48.     ErrorCode: Integer;
  49.     ErrorMessage: string;
  50.   end;
  51.  
  52.   THookSocketReason = (
  53.     HR_ResolvingBegin,
  54.     HR_ResolvingEnd,
  55.     HR_SocketCreate,
  56.     HR_SocketClose,
  57.     HR_Bind,
  58.     HR_Connect,
  59.     HR_CanRead,
  60.     HR_CanWrite,
  61.     HR_Listen,
  62.     HR_Accept,
  63.     HR_ReadCount,
  64.     HR_WriteCount
  65.     );
  66.  
  67.   THookSocketStatus = procedure(Sender: TObject; Reason: THookSocketReason;
  68.     const Value: string) of object;
  69.  
  70.   TBlockSocket = class(TObject)
  71.   private
  72.     FOnStatus: THookSocketStatus;
  73.     FWsaData: TWSADATA;
  74.     FLocalSin: TSockAddrIn;
  75.     FRemoteSin: TSockAddrIn;
  76.     FLastError: Integer;
  77.     FBuffer: string;
  78.     FRaiseExcept: Boolean;
  79.     function GetSizeRecvBuffer: Integer;
  80.     procedure SetSizeRecvBuffer(Size: Integer);
  81.     function GetSizeSendBuffer: Integer;
  82.     procedure SetSizeSendBuffer(Size: Integer);
  83.   protected
  84.     FSocket: TSocket;
  85.     FProtocol: Integer;
  86.     procedure CreateSocket; virtual;
  87.     procedure SetSin(var Sin: TSockAddrIn; IP, Port: string);
  88.     function GetSinIP(Sin: TSockAddrIn): string;
  89.     function GetSinPort(Sin: TSockAddrIn): Integer;
  90.     procedure DoStatus(Reason: THookSocketReason; const Value: string);
  91.   public
  92.     constructor Create;
  93.     constructor CreateAlternate(Stub: string);
  94.     destructor Destroy; override;
  95.     procedure CloseSocket; virtual;
  96.     procedure Bind(IP, Port: string);
  97.     procedure Connect(IP, Port: string); virtual;
  98.     function SendBuffer(Buffer: Pointer; Length: Integer): Integer; virtual;
  99.     procedure SendByte(Data: Byte); virtual;
  100.     procedure SendString(const Data: string); virtual;
  101.     function RecvBuffer(Buffer: Pointer; Length: Integer): Integer; virtual;
  102.     function RecvBufferEx(Buffer: Pointer; Length: Integer;
  103.       Timeout: Integer): Integer; virtual;
  104.     function RecvByte(Timeout: Integer): Byte; virtual;
  105.     function RecvString(Timeout: Integer): string; virtual;
  106.     function RecvPacket(Timeout: Integer): string; virtual;
  107.     function PeekBuffer(Buffer: Pointer; Length: Integer): Integer; virtual;
  108.     function PeekByte(Timeout: Integer): Byte; virtual;
  109.     function WaitingData: Integer;
  110.     procedure SetLinger(Enable: Boolean; Linger: Integer);
  111.     procedure GetSins;
  112.     function SockCheck(SockResult: Integer): Integer;
  113.     procedure ExceptCheck;
  114.     function LocalName: string;
  115.     procedure ResolveNameToIP(Name: string; IPList: TStrings);
  116.     function ResolveName(Name: string): string;
  117.     function ResolvePort(Port: string): Word;
  118.     procedure SetRemoteSin(IP, Port: string);
  119.     function GetLocalSinIP: string; virtual;
  120.     function GetRemoteSinIP: string; virtual;
  121.     function GetLocalSinPort: Integer; virtual;
  122.     function GetRemoteSinPort: Integer; virtual;
  123.     function CanRead(Timeout: Integer): Boolean;
  124.     function CanWrite(Timeout: Integer): Boolean;
  125.     function SendBufferTo(Buffer: Pointer; Length: Integer): Integer; virtual;
  126.     function RecvBufferFrom(Buffer: Pointer; Length: Integer): Integer; virtual;
  127.     function GroupCanRead(const SocketList: TList; Timeout: Integer;
  128.       const CanReadList: TList): Boolean;
  129.  
  130.     //See 'winsock2.txt' file in distribute package!
  131.     function SetTimeout(Timeout: Integer): Boolean;
  132.     function SetSendTimeout(Timeout: Integer): Boolean;
  133.     function SetRecvTimeout(Timeout: Integer): Boolean;
  134.  
  135.     property LocalSin: TSockAddrIn read FLocalSin;
  136.     property RemoteSin: TSockAddrIn read FRemoteSin;
  137.   published
  138.     class function GetErrorDesc(ErrorCode: Integer): string;
  139.     property Socket: TSocket read FSocket write FSocket;
  140.     property LastError: Integer read FLastError;
  141.     property Protocol: Integer read FProtocol;
  142.     property LineBuffer: string read FBuffer write FBuffer;
  143.     property RaiseExcept: Boolean read FRaiseExcept write FRaiseExcept;
  144.     property SizeRecvBuffer: Integer read GetSizeRecvBuffer write SetSizeRecvBuffer;
  145.     property SizeSendBuffer: Integer read GetSizeSendBuffer write SetSizeSendBuffer;
  146.     property WSAData: TWSADATA read FWsaData;
  147.     property OnStatus: THookSocketStatus read FOnStatus write FOnStatus;
  148.   end;
  149.  
  150.   TSocksBlockSocket = class(TBlockSocket)
  151.   protected
  152.     FSocksIP: string;
  153.     FSocksPort: string;
  154.     FSocksTimeout: integer;
  155.     FSocksUsername: string;
  156.     FSocksPassword: string;
  157.     FUsingSocks: Boolean;
  158.     FSocksResolver: Boolean;
  159.     FSocksLastError: integer;
  160.     FSocksResponseIP: string;
  161.     FSocksResponsePort: string;
  162.     FSocksLocalIP: string;
  163.     FSocksLocalPort: string;
  164.     FSocksRemoteIP: string;
  165.     FSocksRemotePort: string;
  166.     function SocksCode(IP, Port: string): string;
  167.     function SocksDecode(Value: string): integer;
  168.   public
  169.     constructor Create;
  170.     function SocksOpen: Boolean;
  171.     function SocksRequest(Cmd: Byte; const IP, Port: string): Boolean;
  172.     function SocksResponse: Boolean;
  173.   published
  174.     property SocksIP: string read FSocksIP write FSocksIP;
  175.     property SocksPort: string read FSocksPort write FSocksPort;
  176.     property SocksUsername: string read FSocksUsername write FSocksUsername;
  177.     property SocksPassword: string read FSocksPassword write FSocksPassword;
  178.     property UsingSocks: Boolean read FUsingSocks;
  179.     property SocksResolver: Boolean read FSocksResolver write FSocksResolver;
  180.     property SocksLastError: integer read FSocksLastError;
  181.   end;
  182.  
  183.   TTCPBlockSocket = class(TSocksBlockSocket)
  184.   public
  185.     procedure CreateSocket; override;
  186.     procedure CloseSocket; override;
  187.     procedure Listen;
  188.     function Accept: TSocket;
  189.     procedure Connect(IP, Port: string); override;
  190.     function GetLocalSinIP: string; override;
  191.     function GetRemoteSinIP: string; override;
  192.     function GetLocalSinPort: Integer; override;
  193.     function GetRemoteSinPort: Integer; override;
  194.   end;
  195.  
  196.   TUDPBlockSocket = class(TSocksBlockSocket)
  197.   protected
  198.     FSocksControlSock: TTCPBlockSocket;
  199.     function UdpAssociation: Boolean;
  200.   public
  201.     destructor Destroy; override;
  202.     procedure CreateSocket; override;
  203.     function EnableBroadcast(Value: Boolean): Boolean;
  204.     procedure Connect(IP, Port: string); override;
  205.     function SendBuffer(Buffer: Pointer; Length: Integer): Integer; override;
  206.     function RecvBuffer(Buffer: Pointer; Length: Integer): Integer; override;
  207.     function SendBufferTo(Buffer: Pointer; Length: Integer): Integer; override;
  208.     function RecvBufferFrom(Buffer: Pointer; Length: Integer): Integer; override;
  209.   end;
  210.  
  211.   //See 'winsock2.txt' file in distribute package!
  212.   TICMPBlockSocket = class(TBlockSocket)
  213.   public
  214.     procedure CreateSocket; override;
  215.   end;
  216.  
  217.   //See 'winsock2.txt' file in distribute package!
  218.   TRAWBlockSocket = class(TBlockSocket)
  219.   public
  220.     procedure CreateSocket; override;
  221.   end;
  222.  
  223.   TIPHeader = record
  224.     VerLen: Byte;
  225.     TOS: Byte;
  226.     TotalLen: Word;
  227.     Identifer: Word;
  228.     FragOffsets: Word;
  229.     TTL: Byte;
  230.     Protocol: Byte;
  231.     CheckSum: Word;
  232.     SourceIp: DWORD;
  233.     DestIp: DWORD;
  234.     Options: DWORD;
  235.   end;
  236.  
  237. implementation
  238.  
  239. constructor TBlockSocket.Create;
  240. var
  241.   e: ESynapseError;
  242. begin
  243.   inherited Create;
  244.   FRaiseExcept := False;
  245.   FSocket := INVALID_SOCKET;
  246.   FProtocol := IPPROTO_IP;
  247.   FBuffer := '';
  248.   if not InitSocketInterface('') then
  249.   begin
  250.     e := ESynapseError.Create('Error loading Winsock DLL!');
  251.     e.ErrorCode := 0;
  252.     e.ErrorMessage := 'Error loading Winsock DLL!';
  253.     raise e;
  254.   end;
  255.   SockCheck(synsock.WSAStartup($101, FWsaData));
  256.   ExceptCheck;
  257. end;
  258.  
  259. constructor TBlockSocket.CreateAlternate(Stub: string);
  260. var
  261.   e: ESynapseError;
  262. begin
  263.   inherited Create;
  264.   FRaiseExcept := False;
  265.   FSocket := INVALID_SOCKET;
  266.   FProtocol := IPPROTO_IP;
  267.   FBuffer := '';
  268.   if not InitSocketInterface(Stub) then
  269.   begin
  270.     e := ESynapseError.Create('Error loading alternate Winsock DLL (' + Stub + ')!');
  271.     e.ErrorCode := 0;
  272.     e.ErrorMessage := 'Error loading Winsock DLL (' + Stub + ')!';
  273.     raise e;
  274.   end;
  275.   SockCheck(synsock.WSAStartup($101, FWsaData));
  276.   ExceptCheck;
  277. end;
  278.  
  279. destructor TBlockSocket.Destroy;
  280. begin
  281.   CloseSocket;
  282.   synsock.WSACleanup;
  283.   DestroySocketInterface;
  284.   inherited Destroy;
  285. end;
  286.  
  287. procedure TBlockSocket.SetSin(var Sin: TSockAddrIn; IP, Port: string);
  288. var
  289.   ProtoEnt: PProtoEnt;
  290.   ServEnt: PServEnt;
  291.   HostEnt: PHostEnt;
  292. begin
  293.   DoStatus(HR_ResolvingBegin, IP + ':' + Port);
  294.   FillChar(Sin, Sizeof(Sin), 0);
  295.   Sin.sin_family := AF_INET;
  296.   ProtoEnt := synsock.GetProtoByNumber(FProtocol);
  297.   ServEnt := nil;
  298.   if ProtoEnt <> nil then
  299.     ServEnt := synsock.GetServByName(PChar(Port), ProtoEnt^.p_name);
  300.   if ServEnt = nil then
  301.     Sin.sin_port := synsock.htons(StrToIntDef(Port, 0))
  302.   else
  303.     Sin.sin_port := ServEnt^.s_port;
  304.   if IP = '255.255.255.255' then
  305.     Sin.sin_addr.s_addr := u_long(INADDR_BROADCAST)
  306.   else
  307.   begin
  308.     Sin.sin_addr.s_addr := synsock.inet_addr(PChar(IP));
  309.     if SIn.sin_addr.s_addr = u_long(INADDR_NONE) then
  310.     begin
  311.       HostEnt := synsock.GetHostByName(PChar(IP));
  312.       if HostEnt <> nil then
  313.         SIn.sin_addr.S_addr := Longint(PLongint(HostEnt^.h_addr_list^)^);
  314.     end;
  315.   end;
  316.   DoStatus(HR_ResolvingEnd, IP+':'+Port);
  317. end;
  318.  
  319. function TBlockSocket.GetSinIP(Sin: TSockAddrIn): string;
  320. var
  321.   p: PChar;
  322. begin
  323.   p := synsock.inet_ntoa(Sin.sin_addr);
  324.   if p = nil then
  325.     Result := ''
  326.   else
  327.     Result := p;
  328. end;
  329.  
  330. function TBlockSocket.GetSinPort(Sin: TSockAddrIn): Integer;
  331. begin
  332.   Result := synsock.ntohs(Sin.sin_port);
  333. end;
  334.  
  335. procedure TBlockSocket.CreateSocket;
  336. begin
  337.   FBuffer := '';
  338.   if FSocket = INVALID_SOCKET then
  339.     FLastError := synsock.WSAGetLastError
  340.   else
  341.     FLastError := 0;
  342.   ExceptCheck;
  343.   DoStatus(HR_SocketCreate, '');
  344. end;
  345.  
  346. procedure TBlockSocket.CloseSocket;
  347. begin
  348.   synsock.CloseSocket(FSocket);
  349.   DoStatus(HR_SocketClose, '');
  350. end;
  351.  
  352. procedure TBlockSocket.Bind(IP, Port: string);
  353. var
  354.   Sin: TSockAddrIn;
  355.   Len: Integer;
  356. begin
  357.   SetSin(Sin, IP, Port);
  358.   SockCheck(synsock.Bind(FSocket, Sin, SizeOf(Sin)));
  359.   Len := SizeOf(FLocalSin);
  360.   synsock.GetSockName(FSocket, FLocalSin, Len);
  361.   FBuffer := '';
  362.   ExceptCheck;
  363.   DoStatus(HR_Bind, IP + ':' + Port);
  364. end;
  365.  
  366. procedure TBlockSocket.Connect(IP, Port: string);
  367. var
  368.   Sin: TSockAddrIn;
  369. begin
  370.   SetSin(Sin, IP, Port);
  371.   SockCheck(synsock.Connect(FSocket, Sin, SizeOf(Sin)));
  372.   GetSins;
  373.   FBuffer := '';
  374.   ExceptCheck;
  375.   DoStatus(HR_Connect, IP + ':' + Port);
  376. end;
  377.  
  378. procedure TBlockSocket.GetSins;
  379. var
  380.   Len: Integer;
  381. begin
  382.   Len := SizeOf(FLocalSin);
  383.   synsock.GetSockName(FSocket, FLocalSin, Len);
  384.   Len := SizeOf(FRemoteSin);
  385.   synsock.GetPeerName(FSocket, FremoteSin, Len);
  386. end;
  387.  
  388. function TBlockSocket.SendBuffer(Buffer: Pointer; Length: Integer): Integer;
  389. begin
  390.   Result := synsock.Send(FSocket, Buffer^, Length, 0);
  391.   SockCheck(Result);
  392.   ExceptCheck;
  393.   DoStatus(HR_WriteCount, IntToStr(Result));
  394. end;
  395.  
  396. procedure TBlockSocket.SendByte(Data: Byte);
  397. begin
  398.   SendBuffer(@Data, 1);
  399. end;
  400.  
  401. procedure TBlockSocket.SendString(const Data: string);
  402. begin
  403.   SendBuffer(PChar(Data), Length(Data));
  404. end;
  405.  
  406. function TBlockSocket.RecvBuffer(Buffer: Pointer; Length: Integer): Integer;
  407. begin
  408.   Result := synsock.Recv(FSocket, Buffer^, Length, 0);
  409.   if Result = 0 then
  410.     FLastError := WSAECONNRESET
  411.   else
  412.     SockCheck(Result);
  413.   ExceptCheck;
  414.   DoStatus(HR_ReadCount, IntToStr(Result));
  415. end;
  416.  
  417. function TBlockSocket.RecvBufferEx(Buffer: Pointer; Length: Integer;
  418.   Timeout: Integer): Integer;
  419. var
  420.   s, ss, st: string;
  421.   x, l, lss: Integer;
  422.   fb, fs: Integer;
  423.   max: Integer;
  424. begin
  425.   FLastError := 0;
  426.   x := System.Length(FBuffer);
  427.   if Length <= x then
  428.   begin
  429.     fb := Length;
  430.     fs := 0;
  431.   end
  432.   else
  433.   begin
  434.     fb := x;
  435.     fs := Length - x;
  436.   end;
  437.   ss := '';
  438.   if fb > 0 then
  439.   begin
  440.     s := Copy(FBuffer, 1, fb);
  441.     Delete(FBuffer, 1, fb);
  442.   end;
  443.   if fs > 0 then
  444.   begin
  445.     Max := GetSizeRecvBuffer;
  446.     ss := '';
  447.     while System.Length(ss) < fs do
  448.     begin
  449.       if CanRead(Timeout) then
  450.       begin
  451.         l := WaitingData;
  452.         if l > max then
  453.           l := max;
  454.         if (system.Length(ss) + l) > fs then
  455.           l := fs - system.Length(ss);
  456.         SetLength(st, l);
  457.         x := synsock.Recv(FSocket, Pointer(st)^, l, 0);
  458.         if x = 0 then
  459.           FLastError := WSAECONNRESET
  460.         else
  461.           SockCheck(x);
  462.         if FLastError <> 0 then
  463.           Break;
  464.         DoStatus(HR_ReadCount, IntToStr(x));
  465.         lss := system.Length(ss);
  466.         SetLength(ss, lss + x);
  467.         Move(Pointer(st)^, Pointer(@ss[lss + 1])^, x);
  468.         {It is 3x faster then ss:=ss+copy(st,1,x);}
  469.         Sleep(0);
  470.       end
  471.       else
  472.         FLastError := WSAETIMEDOUT;
  473.       if FLastError <> 0 then
  474.         Break;
  475.     end;
  476.     fs := system.Length(ss);
  477.   end;
  478.   Result := fb + fs;
  479.   s := s + ss;
  480.   Move(Pointer(s)^, Buffer^, Result);
  481.   ExceptCheck;
  482. end;
  483.  
  484. function TBlockSocket.RecvPacket(Timeout: Integer): string;
  485. var
  486.   x: integer;
  487.   s: string;
  488. begin
  489.   Result := '';
  490.   FLastError := 0;
  491.   x := -1;
  492.   if FBuffer <> '' then
  493.   begin
  494.     Result := FBuffer;
  495.     FBuffer := '';
  496.   end
  497.   else
  498.     if CanRead(Timeout) then
  499.     begin
  500.       x := WaitingData;
  501.       if x > 0 then
  502.       begin
  503.         SetLength(s, x);
  504.         x := RecvBuffer(Pointer(s), x);
  505.         Result := Copy(s, 1, x);
  506.       end;
  507.     end
  508.     else
  509.       FLastError := WSAETIMEDOUT;
  510.   ExceptCheck;
  511.   if x = 0 then
  512.     FLastError := WSAECONNRESET;
  513. end;
  514.  
  515.  
  516. function TBlockSocket.RecvByte(Timeout: Integer): Byte;
  517. var
  518.   y: Integer;
  519.   Data: Byte;
  520. begin
  521.   Data := 0;
  522.   Result := 0;
  523.   if CanRead(Timeout) then
  524.   begin
  525.     y := synsock.Recv(FSocket, Data, 1, 0);
  526.     if y = 0 then
  527.       FLastError := WSAECONNRESET
  528.     else
  529.       SockCheck(y);
  530.     Result := Data;
  531.     DoStatus(HR_ReadCount, '1');
  532.   end
  533.   else
  534.     FLastError := WSAETIMEDOUT;
  535.   ExceptCheck;
  536. end;
  537.  
  538. function TBlockSocket.RecvString(Timeout: Integer): string;
  539. const
  540.   MaxBuf = 1024;
  541. var
  542.   x: Integer;
  543.   s: string;
  544.   c: Char;
  545.   r: Integer;
  546. begin
  547.   s := '';
  548.   FLastError := 0;
  549.   c := #0;
  550.   repeat
  551.     if FBuffer = '' then
  552.     begin
  553.       x := WaitingData;
  554.       if x = 0 then
  555.         x := 1;
  556.       if x > MaxBuf then
  557.         x := MaxBuf;
  558.       if x = 1 then
  559.       begin
  560.         c := Char(RecvByte(Timeout));
  561.         if FLastError <> 0 then
  562.           Break;
  563.         FBuffer := c;
  564.       end
  565.       else
  566.       begin
  567.         SetLength(FBuffer, x);
  568.         r := synsock.Recv(FSocket, Pointer(FBuffer)^, x, 0);
  569.         SockCheck(r);
  570.         if r = 0 then
  571.           FLastError := WSAECONNRESET;
  572.         if FLastError <> 0 then
  573.           Break;
  574.         DoStatus(HR_ReadCount, IntToStr(r));
  575.         if r < x then
  576.           SetLength(FBuffer, r);
  577.       end;
  578.     end;
  579.     x := Pos(#10, FBuffer);
  580.     if x < 1 then x := Length(FBuffer);
  581.     s := s + Copy(FBuffer, 1, x - 1);
  582.     c := FBuffer[x];
  583.     Delete(FBuffer, 1, x);
  584.     s := s + c;
  585.   until c = #10;
  586.  
  587.   if FLastError = 0 then
  588.   begin
  589. {$IFDEF LINUX}
  590.     s := AdjustLineBreaks(s, tlbsCRLF);
  591. {$ELSE}
  592.     s := AdjustLineBreaks(s);
  593. {$ENDIF}
  594.     x := Pos(#13 + #10, s);
  595.     if x > 0 then
  596.       s := Copy(s, 1, x - 1);
  597.     Result := s;
  598.   end
  599.   else
  600.     Result := '';
  601.   ExceptCheck;
  602. end;
  603.  
  604. function TBlockSocket.PeekBuffer(Buffer: Pointer; Length: Integer): Integer;
  605. begin
  606.   Result := synsock.Recv(FSocket, Buffer^, Length, MSG_PEEK);
  607.   SockCheck(Result);
  608.   ExceptCheck;
  609. end;
  610.  
  611. function TBlockSocket.PeekByte(Timeout: Integer): Byte;
  612. var
  613.   y: Integer;
  614.   Data: Byte;
  615. begin
  616.   Data := 0;
  617.   Result := 0;
  618.   if CanRead(Timeout) then
  619.   begin
  620.     y := synsock.Recv(FSocket, Data, 1, MSG_PEEK);
  621.     if y = 0 then
  622.       FLastError := WSAECONNRESET;
  623.     SockCheck(y);
  624.     Result := Data;
  625.   end
  626.   else
  627.     FLastError := WSAETIMEDOUT;
  628.   ExceptCheck;
  629. end;
  630.  
  631. function TBlockSocket.SockCheck(SockResult: Integer): Integer;
  632. begin
  633.   if SockResult = SOCKET_ERROR then
  634.     Result := synsock.WSAGetLastError
  635.   else
  636.     Result := 0;
  637.   FLastError := Result;
  638. end;
  639.  
  640. procedure TBlockSocket.ExceptCheck;
  641. var
  642.   e: ESynapseError;
  643.   s: string;
  644. begin
  645.   if FRaiseExcept and (LastError <> 0) then
  646.   begin
  647.     s := GetErrorDesc(LastError);
  648.     e := ESynapseError.CreateFmt('TCP/IP Socket error %d: %s', [LastError, s]);
  649.     e.ErrorCode := LastError;
  650.     e.ErrorMessage := s;
  651.     raise e;
  652.   end;
  653. end;
  654.  
  655. function TBlockSocket.WaitingData: Integer;
  656. var
  657.   x: Integer;
  658. begin
  659.   synsock.IoctlSocket(FSocket, FIONREAD, u_long(x));
  660.   Result := x;
  661. end;
  662.  
  663. procedure TBlockSocket.SetLinger(Enable: Boolean; Linger: Integer);
  664. var
  665.   li: TLinger;
  666. begin
  667.   li.l_onoff := Ord(Enable);
  668.   li.l_linger := Linger div 1000;
  669.   SockCheck(synsock.SetSockOpt(FSocket, SOL_SOCKET, SO_LINGER, @li, SizeOf(li)));
  670.   ExceptCheck;
  671. end;
  672.  
  673. function TBlockSocket.LocalName: string;
  674. var
  675.   buf: array[0..255] of Char;
  676.   BufPtr: PChar;
  677.   RemoteHost: PHostEnt;
  678. begin
  679.   BufPtr := buf;
  680.   Result := '';
  681.   synsock.GetHostName(BufPtr, SizeOf(buf));
  682.   if BufPtr[0] <> #0 then
  683.   begin
  684.     // try get Fully Qualified Domain Name
  685.     RemoteHost := synsock.GetHostByName(BufPtr);
  686.     if RemoteHost <> nil then
  687.       Result := PChar(RemoteHost^.h_name);
  688.   end;
  689.   if Result = '' then
  690.     Result := '127.0.0.1';
  691. end;
  692.  
  693. procedure TBlockSocket.ResolveNameToIP(Name: string; IPList: TStrings);
  694. type
  695.   TaPInAddr = array[0..250] of PInAddr;
  696.   PaPInAddr = ^TaPInAddr;
  697. var
  698.   RemoteHost: PHostEnt;
  699.   IP: u_long;
  700.   PAdrPtr: PaPInAddr;
  701.   i: Integer;
  702.   s: string;
  703.   InAddr: TInAddr;
  704. begin
  705.   IPList.Clear;
  706.   IP := synsock.inet_addr(PChar(Name));
  707.   if IP = u_long(INADDR_NONE) then
  708.   begin
  709.     RemoteHost := synsock.GetHostByName(PChar(Name));
  710.     if RemoteHost <> nil then
  711.     begin
  712.       PAdrPtr := PAPInAddr(RemoteHost^.h_addr_list);
  713.       i := 0;
  714.       while PAdrPtr^[i] <> nil do
  715.       begin
  716.         InAddr := PAdrPtr^[i]^;
  717.         with InAddr.S_un_b do
  718.           s := Format('%d.%d.%d.%d',
  719.             [Ord(s_b1), Ord(s_b2), Ord(s_b3), Ord(s_b4)]);
  720.         IPList.Add(s);
  721.         Inc(i);
  722.       end;
  723.     end;
  724.     if IPList.Count = 0 then
  725.       IPList.Add('0.0.0.0');
  726.   end
  727.   else
  728.     IPList.Add(Name);
  729. end;
  730.  
  731. function TBlockSocket.ResolveName(Name: string): string;
  732. var
  733.   l: TStringList;
  734. begin
  735.   l := TStringList.Create;
  736.   try
  737.     ResolveNameToIP(Name, l);
  738.     Result := l[0];
  739.   finally
  740.     l.Free;
  741.   end;
  742. end;
  743.  
  744. function TBlockSocket.ResolvePort(Port: string): Word;
  745. var
  746.   ProtoEnt: PProtoEnt;
  747.   ServEnt: PServEnt;
  748. begin
  749.   ProtoEnt := synsock.GetProtoByNumber(FProtocol);
  750.   ServEnt := nil;
  751.   if ProtoEnt <> nil then
  752.     ServEnt := synsock.GetServByName(PChar(Port), ProtoEnt^.p_name);
  753.   if ServEnt = nil then
  754.     Result := synsock.htons(StrToIntDef(Port, 0))
  755.   else
  756.     Result := ServEnt^.s_port;
  757. end;
  758.  
  759. procedure TBlockSocket.SetRemoteSin(IP, Port: string);
  760. begin
  761.   SetSin(FRemoteSin, IP, Port);
  762. end;
  763.  
  764. function TBlockSocket.GetLocalSinIP: string;
  765. begin
  766.   Result := GetSinIP(FLocalSin);
  767. end;
  768.  
  769. function TBlockSocket.GetRemoteSinIP: string;
  770. begin
  771.   Result := GetSinIP(FRemoteSin);
  772. end;
  773.  
  774. function TBlockSocket.GetLocalSinPort: Integer;
  775. begin
  776.   Result := GetSinPort(FLocalSin);
  777. end;
  778.  
  779. function TBlockSocket.GetRemoteSinPort: Integer;
  780. begin
  781.   Result := GetSinPort(FRemoteSin);
  782. end;
  783.  
  784. function TBlockSocket.CanRead(Timeout: Integer): Boolean;
  785. var
  786.   FDSet: TFDSet;
  787.   TimeVal: PTimeVal;
  788.   TimeV: TTimeVal;
  789.   x: Integer;
  790. begin
  791.   TimeV.tv_usec := (Timeout mod 1000) * 1000;
  792.   TimeV.tv_sec := Timeout div 1000;
  793.   TimeVal := @TimeV;
  794.   if Timeout = -1 then
  795.     TimeVal := nil;
  796.   FD_ZERO(FDSet);
  797.   FD_SET(FSocket, FDSet);
  798.   x := synsock.Select(FSocket + 1, @FDSet, nil, nil, TimeVal);
  799.   SockCheck(x);
  800.   if FLastError <> 0 then
  801.     x := 0;
  802.   Result := x > 0;
  803.   ExceptCheck;
  804.   if Result then
  805.     DoStatus(HR_CanRead, '');
  806. end;
  807.  
  808. function TBlockSocket.CanWrite(Timeout: Integer): Boolean;
  809. var
  810.   FDSet: TFDSet;
  811.   TimeVal: PTimeVal;
  812.   TimeV: TTimeVal;
  813.   x: Integer;
  814. begin
  815.   TimeV.tv_usec := (Timeout mod 1000) * 1000;
  816.   TimeV.tv_sec := Timeout div 1000;
  817.   TimeVal := @TimeV;
  818.   if Timeout = -1 then
  819.     TimeVal := nil;
  820.   FD_ZERO(FDSet);
  821.   FD_SET(FSocket, FDSet);
  822.   x := synsock.Select(FSocket + 1, nil, @FDSet, nil, TimeVal);
  823.   SockCheck(x);
  824.   if FLastError <> 0 then
  825.     x := 0;
  826.   Result := x > 0;
  827.   ExceptCheck;
  828.   if Result then
  829.     DoStatus(HR_CanWrite, '');
  830. end;
  831.  
  832. function TBlockSocket.SendBufferTo(Buffer: Pointer; Length: Integer): Integer;
  833. var
  834.   Len: Integer;
  835. begin
  836.   Len := SizeOf(FRemoteSin);
  837.   Result := synsock.SendTo(FSocket, Buffer^, Length, 0, FRemoteSin, Len);
  838.   SockCheck(Result);
  839.   ExceptCheck;
  840. end;
  841.  
  842. function TBlockSocket.RecvBufferFrom(Buffer: Pointer; Length: Integer): Integer;
  843. var
  844.   Len: Integer;
  845. begin
  846.   Len := SizeOf(FRemoteSin);
  847.   Result := synsock.RecvFrom(FSocket, Buffer^, Length, 0, FRemoteSin, Len);
  848.   SockCheck(Result);
  849.   ExceptCheck;
  850. end;
  851.  
  852. function TBlockSocket.GetSizeRecvBuffer: Integer;
  853. var
  854.   l: Integer;
  855. begin
  856.   l := SizeOf(Result);
  857.   SockCheck(synsock.GetSockOpt(FSocket, SOL_SOCKET, SO_RCVBUF, @Result, l));
  858.   if FLastError <> 0 then
  859.     Result := 1024;
  860.   ExceptCheck;
  861. end;
  862.  
  863. procedure TBlockSocket.SetSizeRecvBuffer(Size: Integer);
  864. begin
  865.   SockCheck(synsock.SetSockOpt(FSocket, SOL_SOCKET, SO_RCVBUF, @Size, SizeOf(Size)));
  866.   ExceptCheck;
  867. end;
  868.  
  869. function TBlockSocket.GetSizeSendBuffer: Integer;
  870. var
  871.   l: Integer;
  872. begin
  873.   l := SizeOf(Result);
  874.   SockCheck(synsock.GetSockOpt(FSocket, SOL_SOCKET, SO_SNDBUF, @Result, l));
  875.   if FLastError <> 0 then
  876.     Result := 1024;
  877.   ExceptCheck;
  878. end;
  879.  
  880. procedure TBlockSocket.SetSizeSendBuffer(Size: Integer);
  881. begin
  882.   SockCheck(synsock.SetSockOpt(FSocket, SOL_SOCKET, SO_SNDBUF, @Size, SizeOf(Size)));
  883.   ExceptCheck;
  884. end;
  885.  
  886. //See 'winsock2.txt' file in distribute package!
  887. function TBlockSocket.SetTimeout(Timeout: Integer): Boolean;
  888. begin
  889.   Result := SetSendTimeout(Timeout) and SetRecvTimeout(Timeout);
  890. end;
  891.  
  892. //See 'winsock2.txt' file in distribute package!
  893. function TBlockSocket.SetSendTimeout(Timeout: Integer): Boolean;
  894. begin
  895.   Result := synsock.SetSockOpt(FSocket, SOL_SOCKET, SO_SNDTIMEO,
  896.     @Timeout, SizeOf(Timeout)) <> SOCKET_ERROR;
  897. end;
  898.  
  899. //See 'winsock2.txt' file in distribute package!
  900. function TBlockSocket.SetRecvTimeout(Timeout: Integer): Boolean;
  901. begin
  902.   Result := synsock.SetSockOpt(FSocket, SOL_SOCKET, SO_RCVTIMEO,
  903.     @Timeout, SizeOf(Timeout)) <> SOCKET_ERROR;
  904. end;
  905.  
  906. function TBlockSocket.GroupCanRead(const SocketList: TList; Timeout: Integer;
  907.   const CanReadList: TList): boolean;
  908. var
  909.   FDSet: TFDSet;
  910.   TimeVal: PTimeVal;
  911.   TimeV: TTimeVal;
  912.   x, n: Integer;
  913.   Max: Integer;
  914. begin
  915.   TimeV.tv_usec := (Timeout mod 1000) * 1000;
  916.   TimeV.tv_sec := Timeout div 1000;
  917.   TimeVal := @TimeV;
  918.   if Timeout = -1 then
  919.     TimeVal := nil;
  920.   FD_ZERO(FDSet);
  921.   Max := 0;
  922.   for n := 0 to SocketList.Count - 1 do
  923.     if TObject(SocketList.Items[n]) is TBlockSocket then
  924.     begin
  925.       if TBlockSocket(SocketList.Items[n]).Socket > Max then
  926.         Max := TBlockSocket(SocketList.Items[n]).Socket;
  927.       FD_SET(TBlockSocket(SocketList.Items[n]).Socket, FDSet);
  928.     end;
  929.   x := synsock.Select(Max + 1, @FDSet, nil, nil, TimeVal);
  930.   SockCheck(x);
  931.   ExceptCheck;
  932.   if FLastError <> 0 then
  933.     x := 0;
  934.   Result := x > 0;
  935.   CanReadList.Clear;
  936.   if Result then
  937.     for n := 0 to SocketList.Count - 1 do
  938.       if TObject(SocketList.Items[n]) is TBlockSocket then
  939.         if FD_ISSET(TBlockSocket(SocketList.Items[n]).Socket, FDSet) then
  940.           CanReadList.Add(TBlockSocket(SocketList.Items[n]));
  941. end;
  942.  
  943. procedure TBlockSocket.DoStatus(Reason: THookSocketReason; const Value: string);
  944. begin
  945.   if assigned(OnStatus) then
  946.     OnStatus(Self, Reason, Value);
  947. end;
  948.  
  949. class function TBlockSocket.GetErrorDesc(ErrorCode: Integer): string;
  950. begin
  951.   case ErrorCode of
  952.     0:
  953.       Result := 'OK';
  954.     WSAEINTR: {10004}
  955.       Result := 'Interrupted system call';
  956.     WSAEBADF: {10009}
  957.       Result := 'Bad file number';
  958.     WSAEACCES: {10013}
  959.       Result := 'Permission denied';
  960.     WSAEFAULT: {10014}
  961.       Result := 'Bad address';
  962.     WSAEINVAL: {10022}
  963.       Result := 'Invalid argument';
  964.     WSAEMFILE: {10024}
  965.       Result := 'Too many open files';
  966.     WSAEWOULDBLOCK: {10035}
  967.       Result := 'Operation would block';
  968.     WSAEINPROGRESS: {10036}
  969.       Result := 'Operation now in progress';
  970.     WSAEALREADY: {10037}
  971.       Result := 'Operation already in progress';
  972.     WSAENOTSOCK: {10038}
  973.       Result := 'Socket operation on nonsocket';
  974.     WSAEDESTADDRREQ: {10039}
  975.       Result := 'Destination address required';
  976.     WSAEMSGSIZE: {10040}
  977.       Result := 'Message too long';
  978.     WSAEPROTOTYPE: {10041}
  979.       Result := 'Protocol wrong type for Socket';
  980.     WSAENOPROTOOPT: {10042}
  981.       Result := 'Protocol not available';
  982.     WSAEPROTONOSUPPORT: {10043}
  983.       Result := 'Protocol not supported';
  984.     WSAESOCKTNOSUPPORT: {10044}
  985.       Result := 'Socket not supported';
  986.     WSAEOPNOTSUPP: {10045}
  987.       Result := 'Operation not supported on Socket';
  988.     WSAEPFNOSUPPORT: {10046}
  989.       Result := 'Protocol family not supported';
  990.     WSAEAFNOSUPPORT: {10047}
  991.       Result := 'Address family not supported';
  992.     WSAEADDRINUSE: {10048}
  993.       Result := 'Address already in use';
  994.     WSAEADDRNOTAVAIL: {10049}
  995.       Result := 'Can''t assign requested address';
  996.     WSAENETDOWN: {10050}
  997.       Result := 'Network is down';
  998.     WSAENETUNREACH: {10051}
  999.       Result := 'Network is unreachable';
  1000.     WSAENETRESET: {10052}
  1001.       Result := 'Network dropped connection on reset';
  1002.     WSAECONNABORTED: {10053}
  1003.       Result := 'Software caused connection abort';
  1004.     WSAECONNRESET: {10054}
  1005.       Result := 'Connection reset by peer';
  1006.     WSAENOBUFS: {10055}
  1007.       Result := 'No Buffer space available';
  1008.     WSAEISCONN: {10056}
  1009.       Result := 'Socket is already connected';
  1010.     WSAENOTCONN: {10057}
  1011.       Result := 'Socket is not connected';
  1012.     WSAESHUTDOWN: {10058}
  1013.       Result := 'Can''t send after Socket shutdown';
  1014.     WSAETOOMANYREFS: {10059}
  1015.       Result := 'Too many references:can''t splice';
  1016.     WSAETIMEDOUT: {10060}
  1017.       Result := 'Connection timed out';
  1018.     WSAECONNREFUSED: {10061}
  1019.       Result := 'Connection refused';
  1020.     WSAELOOP: {10062}
  1021.       Result := 'Too many levels of symbolic links';
  1022.     WSAENAMETOOLONG: {10063}
  1023.       Result := 'File name is too long';
  1024.     WSAEHOSTDOWN: {10064}
  1025.       Result := 'Host is down';
  1026.     WSAEHOSTUNREACH: {10065}
  1027.       Result := 'No route to host';
  1028.     WSAENOTEMPTY: {10066}
  1029.       Result := 'Directory is not empty';
  1030.     WSAEPROCLIM: {10067}
  1031.       Result := 'Too many processes';
  1032.     WSAEUSERS: {10068}
  1033.       Result := 'Too many users';
  1034.     WSAEDQUOT: {10069}
  1035.       Result := 'Disk quota exceeded';
  1036.     WSAESTALE: {10070}
  1037.       Result := 'Stale NFS file handle';
  1038.     WSAEREMOTE: {10071}
  1039.       Result := 'Too many levels of remote in path';
  1040.     WSASYSNOTREADY: {10091}
  1041.       Result := 'Network subsystem is unusable';
  1042.     WSAVERNOTSUPPORTED: {10092}
  1043.       Result := 'Winsock DLL cannot support this application';
  1044.     WSANOTINITIALISED: {10093}
  1045.       Result := 'Winsock not initialized';
  1046.     WSAEDISCON: {10101}
  1047.       Result := 'WSAEDISCON-10101';
  1048.     WSAHOST_NOT_FOUND: {11001}
  1049.       Result := 'Host not found';
  1050.     WSATRY_AGAIN: {11002}
  1051.       Result := 'Non authoritative - host not found';
  1052.     WSANO_RECOVERY: {11003}
  1053.       Result := 'Non recoverable error';
  1054.     WSANO_DATA: {11004}
  1055.       Result := 'Valid name, no data record of requested type'
  1056.   else
  1057.     Result := 'Not a Winsock error (' + IntToStr(ErrorCode) + ')';
  1058.   end;
  1059. end;
  1060.  
  1061. {======================================================================}
  1062.  
  1063. constructor TSocksBlockSocket.Create;
  1064. begin
  1065.   inherited Create;
  1066.   FSocksIP:= '';
  1067.   FSocksPort:= '1080';
  1068.   FSocksTimeout:= 300000;
  1069.   FSocksUsername:= '';
  1070.   FSocksPassword:= '';
  1071.   FUsingSocks := False;
  1072.   FSocksResolver := True;
  1073.   FSocksLastError := 0;
  1074.   FSocksResponseIP := '';
  1075.   FSocksResponsePort := '';
  1076.   FSocksLocalIP := '';
  1077.   FSocksLocalPort := '';
  1078.   FSocksRemoteIP := '';
  1079.   FSocksRemotePort := '';
  1080. end;
  1081.  
  1082. function TSocksBlockSocket.SocksOpen: boolean;
  1083. var
  1084.   Buf: string;
  1085.   n: integer;
  1086. begin
  1087.   Result := False;
  1088.   FUsingSocks := False;
  1089.   if FSocksUsername = '' then
  1090.     Buf := #5 + #1 + #0
  1091.   else
  1092.     Buf := #5 + #2 + #2 +#0;
  1093.   SendString(Buf);
  1094.   Buf := RecvPacket(FSocksTimeout);
  1095.   FBuffer := Copy(Buf, 3, Length(buf) - 2);
  1096.   if Length(Buf) < 2 then
  1097.     Exit;
  1098.   if Buf[1] <> #5 then
  1099.     Exit;
  1100.   n := Ord(Buf[2]);
  1101.   case n of
  1102.     0: //not need authorisation
  1103.       ;
  1104.     2:
  1105.       begin
  1106.         Buf := #1 + char(Length(FSocksUsername)) + FSocksUsername
  1107.           + char(Length(FSocksPassword)) + FSocksPassword;
  1108.         SendString(Buf);
  1109.         Buf := RecvPacket(FSocksTimeout);
  1110.         FBuffer := Copy(Buf, 3, Length(buf) - 2);
  1111.         if Length(Buf) < 2 then
  1112.           Exit;
  1113.         if Buf[2] <> #0 then
  1114.           Exit;
  1115.       end;
  1116.   else
  1117.     Exit;
  1118.   end;
  1119.   FUsingSocks := True;
  1120.   Result := True;
  1121. end;
  1122.  
  1123. function TSocksBlockSocket.SocksRequest(Cmd: Byte;
  1124.   const IP, Port: string): Boolean;
  1125. var
  1126.   Buf: string;
  1127. begin
  1128.   Result := False;
  1129.   Buf := #5 + char(Cmd) + #0 + SocksCode(IP, Port);
  1130.   SendString(Buf);
  1131.   Result := FLastError = 0;
  1132. end;
  1133.  
  1134. function TSocksBlockSocket.SocksResponse: Boolean;
  1135. var
  1136.   Buf: string;
  1137.   x: integer;
  1138. begin
  1139.   Result := False;
  1140.   FSocksResponseIP := '';
  1141.   FSocksResponsePort := '';
  1142.   Buf := RecvPacket(FSocksTimeout);
  1143.   if FLastError <> 0 then
  1144.     Exit;
  1145.   if Length(Buf) < 5 then
  1146.     Exit;
  1147.   if Buf[1] <> #5 then
  1148.     Exit;
  1149.   FSocksLastError := Ord(Buf[2]);
  1150.   if FSocksLastError <> 0 then
  1151.     Exit;
  1152.   x := SocksDecode(Buf);
  1153.   FBuffer := Copy(Buf, x, Length(buf) - x + 1);
  1154.   Result := True;
  1155. end;
  1156.  
  1157. function TSocksBlockSocket.SocksCode(IP, Port: string): string;
  1158. begin
  1159.   if IsIP(IP) then
  1160.     Result := #1 + IPToID(IP)
  1161.   else
  1162.     if FSocksResolver then
  1163.       Result := #3 + char(Length(IP)) + IP
  1164.     else
  1165.       Result := #1 + IPToID(ResolveName(IP));
  1166.   Result := Result + CodeInt(synsock.htons(ResolvePort(Port)));
  1167. end;
  1168.  
  1169. function TSocksBlockSocket.SocksDecode(Value: string): integer;
  1170. var
  1171.   Atyp: Byte;
  1172.   y, n: integer;
  1173.   w: Word;
  1174. begin
  1175.   FSocksResponsePort := '0';
  1176.   Atyp := Ord(Value[4]);
  1177.   Result := 5;
  1178.   case Atyp of
  1179.     1:
  1180.       begin
  1181.         if Length(Value) < 10 then
  1182.           Exit;
  1183.         FSocksResponseIP := Format('%d.%d.%d.%d',
  1184.             [Ord(Value[5]), Ord(Value[6]), Ord(Value[7]), Ord(Value[8])]);
  1185.         Result := 9;
  1186.       end;
  1187.     3:
  1188.       begin
  1189.         y := Ord(Value[5]);
  1190.         if Length(Value) < (5 + y + 2) then
  1191.           Exit;
  1192.         for n := 6 to 6 + y do
  1193.           FSocksResponseIP := FSocksResponseIP + Value[n];
  1194.         Result := 5 + y +1;
  1195.       end;
  1196.   else
  1197.     Exit;
  1198.   end;
  1199.   w := DecodeInt(Value, Result);
  1200.   FSocksResponsePort := IntToStr(w);
  1201.   Result := Result + 2;
  1202. end;
  1203.  
  1204. {======================================================================}
  1205.  
  1206. destructor TUDPBlockSocket.Destroy;
  1207. begin
  1208.   if Assigned(FSocksControlSock) then
  1209.     FSocksControlSock.Free;
  1210.   inherited;
  1211. end;
  1212.  
  1213. procedure TUDPBlockSocket.CreateSocket;
  1214. begin
  1215.   FSocket := synsock.Socket(PF_INET, Integer(SOCK_DGRAM), IPPROTO_UDP);
  1216.   FProtocol := IPPROTO_UDP;
  1217.   inherited CreateSocket;
  1218. end;
  1219.  
  1220. function TUDPBlockSocket.EnableBroadcast(Value: Boolean): Boolean;
  1221. var
  1222.   Opt: Integer;
  1223.   Res: Integer;
  1224. begin
  1225.   opt := Ord(Value);
  1226.   Res := synsock.SetSockOpt(FSocket, SOL_SOCKET, SO_BROADCAST, @Opt, SizeOf(opt));
  1227.   SockCheck(Res);
  1228.   Result := res = 0;
  1229.   ExceptCheck;
  1230. end;
  1231.  
  1232. procedure TUDPBlockSocket.Connect(IP, Port: string);
  1233. begin
  1234.   SetRemoteSin(IP, Port);
  1235.   FBuffer := '';
  1236.   DoStatus(HR_Connect, IP + ':' + Port);
  1237. end;
  1238.  
  1239. function TUDPBlockSocket.RecvBuffer(Buffer: Pointer; Length: Integer): Integer;
  1240. begin
  1241.   Result := RecvBufferFrom(Buffer, Length);
  1242. end;
  1243.  
  1244. function TUDPBlockSocket.SendBuffer(Buffer: Pointer; Length: Integer): Integer;
  1245. begin
  1246.   Result := SendBufferTo(Buffer, Length);
  1247. end;
  1248.  
  1249. function TUDPBlockSocket.UdpAssociation: Boolean;
  1250. var
  1251.   b: Boolean;
  1252. begin
  1253.   Result := True;
  1254.   FUsingSocks := False;
  1255.   if FSocksIP <> '' then
  1256.   begin
  1257.     Result := False;
  1258.     if not Assigned(FSocksControlSock) then
  1259.       FSocksControlSock := TTCPBlockSocket.Create;
  1260.     FSocksControlSock.CloseSocket;
  1261.     FSocksControlSock.CreateSocket;
  1262.     FSocksControlSock.Connect(FSocksIP, FSocksPort);
  1263.     if FSocksControlSock.LastError <> 0 then
  1264.       Exit;
  1265.     // if not assigned local port, assign it!
  1266.     if GetLocalSinPort = 0 then
  1267.       Bind(GetLocalSinIP, '0');
  1268.     GetSins;
  1269.     //open control TCP connection to SOCKS
  1270.     b := FSocksControlSock.SocksOpen;
  1271.     if b then
  1272.       b := FSocksControlSock.SocksRequest(3, GetLocalSinIP,
  1273.         IntToStr(GetLocalSinPort));
  1274.     if b then
  1275.       b := FSocksControlSock.SocksResponse;
  1276.     if not b and (FLastError = 0) then
  1277.       FLastError := WSANO_RECOVERY;
  1278.     FUsingSocks :=FSocksControlSock.UsingSocks;
  1279.     FSocksRemoteIP := FSocksControlSock.FSocksResponseIP;
  1280.     FSocksRemotePort := FSocksControlSock.FSocksResponsePort;
  1281.     Result := True;
  1282.   end;
  1283. end;
  1284.  
  1285. function TUDPBlockSocket.SendBufferTo(Buffer: Pointer; Length: Integer): Integer;
  1286. var
  1287.   SIp: string;
  1288.   SPort: integer;
  1289.   Buf: string;
  1290. begin
  1291.   UdpAssociation;
  1292.   if FUsingSocks then
  1293.   begin
  1294.     Sip := GetRemoteSinIp;
  1295.     SPort := GetRemoteSinPort;
  1296.     SetRemoteSin(FSocksRemoteIP, FSocksRemotePort);
  1297.     SetLength(Buf,Length);
  1298.     Move(Buffer^, PChar(Buf)^, Length);
  1299.     Buf := #0 + #0 + #0 + SocksCode(Sip, IntToStr(SPort)) + Buf;
  1300.     Result := inherited SendBufferTo(PChar(Buf), System.Length(buf));
  1301.     SetRemoteSin(Sip, IntToStr(SPort));
  1302.   end
  1303.   else
  1304.   begin
  1305.     Result := inherited SendBufferTo(Buffer, Length);
  1306.     GetSins;
  1307.   end;
  1308. end;
  1309.  
  1310. function TUDPBlockSocket.RecvBufferFrom(Buffer: Pointer; Length: Integer): Integer;
  1311. var
  1312.   Buf: string;
  1313.   x: integer;
  1314. begin
  1315.   Result := inherited RecvBufferFrom(Buffer, Length);
  1316.   if FUsingSocks then
  1317.   begin
  1318.     SetLength(Buf, Result);
  1319.     Move(Buffer^, PChar(Buf)^, Result);
  1320.     x := SocksDecode(Buf);
  1321.     Result := Result - x + 1;
  1322.     Buf := Copy(Buf, x, Result);
  1323.     Move(PChar(Buf)^, Buffer^, Result);
  1324.     SetRemoteSin(FSocksResponseIP, FSocksResponsePort);
  1325.   end;
  1326. end;
  1327.  
  1328. {======================================================================}
  1329.  
  1330. procedure TTCPBlockSocket.CreateSocket;
  1331. begin
  1332.   FSocket := synsock.Socket(PF_INET, Integer(SOCK_STREAM), IPPROTO_TCP);
  1333.   FProtocol := IPPROTO_TCP;
  1334.   inherited CreateSocket;
  1335. end;
  1336.  
  1337. procedure TTCPBlockSocket.CloseSocket;
  1338. begin
  1339.   synsock.Shutdown(FSocket, 1);
  1340.   inherited CloseSocket;
  1341. end;
  1342.  
  1343. procedure TTCPBlockSocket.Listen;
  1344. var
  1345.   b: Boolean;
  1346.   Sip,SPort: string;
  1347. begin
  1348.   if FSocksIP = '' then
  1349.   begin
  1350.     SockCheck(synsock.Listen(FSocket, SOMAXCONN));
  1351.     GetSins;
  1352.   end
  1353.   else
  1354.   begin
  1355.     Sip := GetLocalSinIP;
  1356.     if Sip = '0.0.0.0' then
  1357.       Sip := LocalName;
  1358.     SPort := IntToStr(GetLocalSinPort);
  1359.     Connect(FSocksIP, FSocksPort);
  1360.     b := SocksOpen;
  1361.     if b then
  1362.       b := SocksRequest(2, Sip, SPort);
  1363.     if b then
  1364.       b := SocksResponse;
  1365.     if not b and (FLastError = 0) then
  1366.       FLastError := WSANO_RECOVERY;
  1367.     FSocksLocalIP := FSocksResponseIP;
  1368.     if FSocksLocalIP = '0.0.0.0' then
  1369.       FSocksLocalIP := FSocksIP;
  1370.     FSocksLocalPort := FSocksResponsePort;
  1371.     FSocksRemoteIP := '';
  1372.     FSocksRemotePort := '';
  1373.   end;
  1374.   ExceptCheck;
  1375.   DoStatus(HR_Listen, '');
  1376. end;
  1377.  
  1378. function TTCPBlockSocket.Accept: TSocket;
  1379. var
  1380.   Len: Integer;
  1381. begin
  1382.   if FUsingSocks then
  1383.   begin
  1384.     if not SocksResponse and (FLastError = 0) then
  1385.       FLastError := WSANO_RECOVERY;
  1386.     FSocksRemoteIP := FSocksResponseIP;
  1387.     FSocksRemotePort := FSocksResponsePort;
  1388.     Result := FSocket;
  1389.   end
  1390.   else
  1391.   begin
  1392.     Len := SizeOf(FRemoteSin);
  1393.     Result := synsock.Accept(FSocket, @FRemoteSin, @Len);
  1394.     SockCheck(Result);
  1395.   end;
  1396.   ExceptCheck;
  1397.   DoStatus(HR_Accept, '');
  1398. end;
  1399.  
  1400. procedure TTCPBlockSocket.Connect(IP, Port: string);
  1401. var
  1402.   b: Boolean;
  1403. begin
  1404.   if FSocksIP = '' then
  1405.     inherited Connect(IP, Port)
  1406.   else
  1407.   begin
  1408.     inherited Connect(FSocksIP, FSocksPort);
  1409.     b := SocksOpen;
  1410.     if b then
  1411.       b := SocksRequest(1, IP, Port);
  1412.     if b then
  1413.       b := SocksResponse;
  1414.     if not b and (FLastError = 0) then
  1415.       FLastError := WSANO_RECOVERY;
  1416.     FSocksLocalIP := FSocksResponseIP;
  1417.     FSocksLocalPort := FSocksResponsePort;
  1418.     FSocksRemoteIP := IP;
  1419.     FSocksRemotePort := Port;
  1420.     ExceptCheck;
  1421.     DoStatus(HR_Connect, IP + ':' + Port);
  1422.   end;
  1423. end;
  1424.  
  1425. function TTCPBlockSocket.GetLocalSinIP: string;
  1426. begin
  1427.   if FUsingSocks then
  1428.     Result := FSocksLocalIP
  1429.   else
  1430.     Result := inherited GetLocalSinIP;
  1431. end;
  1432.  
  1433. function TTCPBlockSocket.GetRemoteSinIP: string;
  1434. begin
  1435.   if FUsingSocks then
  1436.     Result := FSocksRemoteIP
  1437.   else
  1438.     Result := inherited GetRemoteSinIP;
  1439. end;
  1440.  
  1441. function TTCPBlockSocket.GetLocalSinPort: Integer;
  1442. begin
  1443.   if FUsingSocks then
  1444.     Result := StrToIntDef(FSocksLocalPort, 0)
  1445.   else
  1446.     Result := inherited GetLocalSinPort;
  1447. end;
  1448.  
  1449. function TTCPBlockSocket.GetRemoteSinPort: Integer;
  1450. begin
  1451.   if FUsingSocks then
  1452.     Result := StrToIntDef(FSocksRemotePort, 0)
  1453.   else
  1454.     Result := inherited GetRemoteSinPort;
  1455. end;
  1456.  
  1457. {======================================================================}
  1458.  
  1459. //See 'winsock2.txt' file in distribute package!
  1460.  
  1461. procedure TICMPBlockSocket.CreateSocket;
  1462. begin
  1463.   FSocket := synsock.Socket(PF_INET, Integer(SOCK_RAW), IPPROTO_ICMP);
  1464.   FProtocol := IPPROTO_ICMP;
  1465.   inherited CreateSocket;
  1466. end;
  1467.  
  1468. {======================================================================}
  1469.  
  1470. //See 'winsock2.txt' file in distribute package!
  1471.  
  1472. procedure TRAWBlockSocket.CreateSocket;
  1473. begin
  1474.   FSocket := synsock.Socket(PF_INET, Integer(SOCK_RAW), IPPROTO_RAW);
  1475.   FProtocol := IPPROTO_RAW;
  1476.   inherited CreateSocket;
  1477. end;
  1478.  
  1479. end.
  1480.