MySocket.pas
上传用户:hndmjx
上传日期:2014-09-16
资源大小:3369k
文件大小:41k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. unit MySocket;
  2. {(C) Alex Demchenko(alex@ritlabs.com)}
  3. {$R-}                   //Remove range checking
  4. {$DEFINE USE_FORMS}     //If you don't use forms unit remove this line
  5. {$DEFINE REMOVEHTTP}
  6. interface
  7. uses
  8.   Windows, Messages, WinSock, {$IFDEF USE_FORMS}Forms, {$ENDIF} Classes, ICQWorks;
  9. function InitMySocket(var WSA: TWSAData): LongWord;
  10. procedure FinalMySocket;
  11. const
  12.   CNetPktLen = 8192;
  13. type
  14.   {$IFNDEF USE_FORMS}
  15.   TWndMethod = procedure(var Message: TMessage) of object;
  16.   {$ENDIF}
  17.   TOnRecv = procedure(Sender: TObject; Socket: TSocket; Buffer: Pointer; BufLen: LongWord) of object;
  18.   TOnPktParse = procedure(Sender: TObject; Buffer: Pointer; BufLen: LongWord) of object;
  19.   TOnPktParseAdv = procedure(Sender: TObject; Buffer: Pointer; BufLen: LongWord; Incoming: Boolean) of object;
  20.   TOnAdvPktParse = procedure(Sender: TObject; Buffer: Pointer; BufLen: LongWord; Incoming: Boolean) of object;
  21.   TOnResolve = procedure(Sender: TObject; Addr: String) of object;
  22.   TOnError = procedure(Sender: TObject; ErrorType: TErrorType; ErrorMsg: String) of object;
  23.   PNetPacket = ^TNetPacket;
  24.   TNetPacket = record
  25.     Buf: array[0..CNetPktLen - 1] of Byte;
  26.     BufLen: Word;
  27.     Offset: Word;
  28.     Next: PNetPacket;
  29.   end;
  30.   TNetBuffer = class(TObject)
  31.   private
  32.     FPkt: PNetPacket;
  33.   public
  34.     constructor Create;
  35.     destructor Destroy; override;
  36.     procedure Clear;
  37.     procedure AddPacket(Buffer: Pointer; BufLen: LongWord);
  38.     procedure DelPacket;
  39.     function GetPacket(Buffer: Pointer): LongWord;
  40.     function SkipData(Len: Word): Boolean;
  41.     procedure AddStr(Value: String);
  42.     function GetStr: String;
  43.   end;
  44.   TClSock = class(TObject)
  45.   private
  46.     FWndHandle: THandle;
  47.     FIp: String;
  48.     FDestPort: LongWord;
  49.     FClSock: TSocket;
  50.     FOnRecv: TOnRecv;
  51.     FOnDisconnect: TNotifyEvent;
  52.     FOnConnect: TNotifyEvent;
  53.     FOnConnectError: TNotifyEvent;
  54.     FOnPktParse: TOnPktParse;
  55.     FHostIp: array[0..MAXGETHOSTSTRUCT - 1] of Char;
  56.     FResolve: Boolean;
  57.     FOnResolve: TOnResolve;
  58.     FOnFailed: TNotifyEvent;
  59.     FOnError: TOnError;
  60.     FCanWrite: Boolean;
  61.     FBuffer: TNetBuffer;
  62.     FOnDataSent: TNotifyEvent;
  63.     function ResolveAddr(Value: Pointer): LongInt;
  64.     function TestResolve(IP: String): Boolean;
  65.     procedure InitConnect(dwIP: LongWord);
  66.     procedure OnSockMsg(var Msg: TMessage);
  67.     function IsConnected: Boolean;
  68.     procedure ProcessBuffer;
  69.   public
  70.     constructor Create;
  71.     destructor Destroy; override;
  72.     procedure Connect(ClearBuffer: Boolean = True); //Connect to remote host
  73.     procedure Resolve; //Just resolve remote host w/o connecting
  74.     procedure DoClose; //Close socket
  75.     procedure Disconnect;
  76.     procedure SendData(var Buf; BufLen: LongWord);
  77.     procedure SendStr(const Value: String);
  78.     property IP: String read FIp write FIp;
  79.     property DestPort: LongWord read FDestPort write FDestPort;
  80.     property Connected: Boolean read IsConnected;
  81.     property WndHandle: THandle read FWndHandle;
  82.   published
  83.     property OnDataSent: TNotifyEvent read FOnDataSent write FOnDataSent;
  84.     property OnRecieve: TOnRecv read FOnRecv write FOnRecv;
  85.     property OnDisconnect: TNotifyEvent read FOnDisconnect write FOnDisconnect;
  86.     property OnConnect: TNotifyEvent read FOnConnect write FOnConnect;
  87.     property OnConnectError: TNotifyEvent read FOnConnectError write FOnConnectError;
  88.     property OnPktParse: TOnPktParse read FOnPktParse write FOnPktParse;
  89.     property OnResolve: TOnResolve read FOnResolve write FOnResolve;
  90.     property OnResolveFailed: TNotifyEvent read FOnFailed write FOnFailed;
  91.     property OnError: TOnError read FOnError write FOnError;
  92.   end;
  93.   TProxySock = class(TObject)
  94.   private
  95.     {$IFNDEF REMOVEHTTP}
  96.     FICQRecv: TClSock;
  97.     FICQSID: String;
  98.     FICQSEQ: Word;
  99.     FICQPIP: String;
  100.     FICQPPORT: Word;
  101.     FBuf: array[0..$FFFF - 1] of Byte;  //
  102.     FCurLen: Word;                      //  HTTP Protocol
  103.     FLen: Word;                         //
  104.     {$ENDIF}
  105.     FSrcBuf: array[0..MAX_DATA_LEN - 1] of Byte;
  106.     FSrcLen: Word;
  107.     FSock: TClSock;
  108.     FProxyType: TProxyType;
  109.     FProxyHost: String;
  110.     FProxyPort: Word;
  111.     FProxyAuth: Boolean;
  112.     FProxyPass: String;
  113.     FUserID: String;
  114.     FHost: String;
  115.     FPort: Word;
  116.     FResolve: Boolean;
  117.     FSocks: Word;
  118.     FOnConnectError: TNotifyEvent;
  119.     FOnDisconnect: TNotifyEvent;
  120.     FOnPktParse: TOnAdvPktParse;
  121.     FOnError: TOnError;
  122.     FOnRecv: TOnRecv;
  123.     FOnConnectProc: TNotifyEvent;
  124.   private
  125.     {$IFNDEF REMOVEHTTP}
  126.     procedure HandleHTTPDataPak(Buffer: Pointer; BufLen: LongWord);
  127.     procedure SendHTTPData(Buffer: Pointer; BufLen: LongWord);
  128.     procedure HandleHTTPData(Buffer: Pointer; BufLen: LongWord);
  129.     {$ENDIF}
  130.     function GetWndHandle: THandle;
  131.     {$IFNDEF REMOVEHTTP}
  132.     procedure InitRecvConnection;
  133.     procedure OnHTTPRecvSockConnect(Sender: TObject);
  134.     procedure OnHTTPDataSent(Sender: TObject);
  135.     {$ENDIF}
  136.     procedure OnSockResolve(Sender: TObject; Addr: String);
  137.     procedure OnSockResolveFailed(Sender: TObject);
  138.     procedure OnSockConnect(Sender: TObject);
  139.     procedure OnSockRecv(Sender: TObject; Socket: TSocket; Buffer: Pointer; BufLen: LongWord);
  140.     procedure OnSockConnectError(Sender: TObject);
  141.     procedure OnSockDisconnect(Sender: TObject);
  142.     procedure OnSockError(Sender: TObject; ErrorType: TErrorType; ErrorMsg: String);
  143.     procedure OnPktParse(Sender: TObject; Buffer: Pointer; BufLen: LongWord);
  144.   protected
  145.     procedure OnReceive(Buffer: Pointer; BufLen: LongWord); dynamic;
  146.   public
  147.     constructor Create;
  148.     destructor Destroy; override;
  149.     procedure Connect; dynamic;
  150.     procedure Disconnect;
  151.     procedure SendData(var Buf; BufLen: LongWord);
  152.     property Host: String read FHost write FHost;
  153.     property Port: Word read FPort write FPort;
  154.     property ProxyType: TProxyType read FProxyType write FProxyType;
  155.     property ProxyHost: String read FProxyHost write FProxyHost;
  156.     property ProxyPort: Word read FProxyPort write FProxyPort;
  157.     property ProxyUserID: String read FUserID write FUserID;
  158.     property ProxyAuth: Boolean read FProxyAuth write FProxyAuth;
  159.     property ProxyPass: String read FProxyPass write FProxyPass;
  160.     property UseProxyResolve: Boolean read FResolve write FResolve default False;
  161.     property WndHandle: THandle read GetWndHandle;
  162.   published
  163.     property OnConnectError: TNotifyEvent read FOnConnectError write FOnConnectError;
  164.     property OnDisconnect: TNotifyEvent read FOnDisconnect write FOnDisconnect;
  165.     property OnPktParseA: TOnAdvPktParse read FOnPktParse write FOnPktParse;
  166.     property OnError: TOnError read FOnError write FOnError;
  167.     property OnReceiveProc: TOnRecv read FOnRecv write FOnRecv;
  168.     property OnConnectProc: TNotifyEvent read FOnConnectProc write FOnConnectProc;
  169.   end;
  170.   TMySock = class(TProxySock)
  171.   private
  172.     function GetClientSocket: TSocket;
  173.     procedure SetClientSocket(Socket: TSocket);
  174.     function IsConnected: Boolean;
  175.   public
  176.     property ClientSocket: TSocket read GetClientSocket write SetClientSocket;
  177.     property Connected: Boolean read IsConnected;
  178.   end;
  179.   TOnClientConnected = procedure(Sender: TObject; Socket: TMySock) of object;
  180.   TSrvSock = class(TObject)
  181.   private
  182.     FPort: Word;
  183.     FWndHandle: THandle;
  184.     FSrvSock: TSocket;
  185.     FOnClientConnected: TOnClientConnected;
  186.     procedure OnSockMsg(var Msg: TMessage);
  187.   public
  188.     constructor Create;
  189.     destructor Destroy; override;
  190.     function StartServer(Port: Word): Boolean;
  191.     function StopServer: Boolean;
  192.     property Port: Word read FPort;
  193.   published
  194.     property OnClientConnected: TOnClientConnected read FOnClientConnected write FOnClientConnected;
  195.   end;
  196. var
  197.   WSA: TWSAData;
  198. function GetLocalIP: LongInt;
  199. function FindBindPort: Word;
  200. {$IFNDEF USE_FORMS}
  201. function AllocateHWnd(Method: TWndMethod): THandle;
  202. procedure DeallocateHWnd(Wnd: THandle);
  203. {$ENDIF}
  204. implementation
  205. const
  206.   WSA_ACCEPT   = WM_USER + $10;
  207.   WSA_NETEVENT = WM_USER + $20;
  208.   WSA_RESOLVE_COMPLETE = WM_USER + $30;
  209.   b64alphabet: PChar = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  210. function EncodeBase64(Value: String): String;
  211. const
  212.   pad: PChar = '====';
  213.   function EncodeChunk(const Chunk: String): String;
  214.   var
  215.     W: LongWord;
  216.     i, n: Byte;
  217.   begin
  218.     n := Length(Chunk); W := 0;
  219.     for i := 0 to n - 1 do
  220.       W := W + Ord(Chunk[i + 1]) shl ((2 - i) * 8);
  221.     Result := b64alphabet[(W shr 18) and $3f] +
  222.               b64alphabet[(W shr 12) and $3f] +
  223.               b64alphabet[(W shr 06) and $3f] +
  224.               b64alphabet[(W shr 00) and $3f];
  225.     if n <> 3 then
  226.       Result := Copy(Result, 0, n + 1) + Copy(pad, 0, 3 - n);   //add padding when out len isn't 24 bits
  227.   end;
  228. begin
  229.   Result := '';
  230.   while Length(Value) > 0 do
  231.   begin
  232.     Result := Result + EncodeChunk(Copy(Value, 0, 3));
  233.     Delete(Value, 1, 3);
  234.   end;
  235. end;
  236. function DecodeBase64(Value: String): String;
  237.   function DecodeChunk(const Chunk: String): String;
  238.   var
  239.     W: LongWord;
  240.     i: Byte;
  241.   begin
  242.     W := 0; Result := '';
  243.     for i := 1 to 4 do
  244.       if Pos(Chunk[i], b64alphabet) <> 0 then
  245.         W := W + Word((Pos(Chunk[i], b64alphabet) - 1)) shl ((4 - i) * 6);
  246.     for i := 1 to 3 do
  247.       Result := Result + Chr(W shr ((3 - i) * 8) and $ff);
  248.   end;
  249. begin
  250.   Result := '';
  251.   if Length(Value) mod 4 <> 0 then Exit;
  252.   while Length(Value) > 0 do
  253.   begin
  254.     Result := Result + DecodeChunk(Copy(Value, 0, 4));
  255.     Delete(Value, 1, 4);
  256.   end;
  257. end;
  258. constructor TNetBuffer.Create;
  259. begin
  260.   inherited;
  261.   FPkt := nil;
  262. end;
  263. destructor TNetBuffer.Destroy;
  264. begin
  265.   Clear;
  266.   inherited;
  267. end;
  268. procedure TNetBuffer.Clear;
  269. var
  270.   p: Pointer;
  271. begin
  272.   while FPkt <> nil do
  273.   begin
  274.     p := FPkt^.Next;
  275.     FreeMem(FPkt);
  276.     FPkt := p;
  277.   end;
  278. end;
  279. procedure TNetBuffer.AddPacket(Buffer: Pointer; BufLen: LongWord);
  280. var
  281.   p: PNetPacket;
  282. begin
  283.   if BufLen > CNetPktLen then BufLen := CNetPktLen;
  284.   if FPkt = nil then
  285.   begin
  286.     GetMem(FPkt, SizeOf(TNetPacket));
  287.     p := FPkt;
  288.   end else
  289.   begin
  290.     p := FPkt;
  291.     while p <> nil do
  292.     begin
  293.       if p^.Next = nil then Break;
  294.       p := p^.Next;
  295.     end;
  296.     GetMem(p^.Next, SizeOf(TNetPacket));
  297.     p := p^.Next;
  298.   end;
  299.   p^.BufLen := BufLen;
  300.   p^.Offset := 0;
  301.   p^.Next := nil;
  302.   Move(Buffer^, p^.Buf, BufLen);
  303. end;
  304. procedure TNetBuffer.DelPacket;
  305. var
  306.   p: PNetPacket;
  307. begin
  308.   if FPkt = nil then Exit;
  309.   if FPkt^.Next <> nil then
  310.   begin
  311.     p := FPkt^.Next;
  312.     FreeMem(FPkt);
  313.     FPkt := p;
  314.   end else
  315.   begin
  316.     FreeMem(FPkt);
  317.     FPkt := nil;
  318.   end;
  319. end;
  320. function TNetBuffer.GetPacket(Buffer: Pointer): LongWord;
  321. begin
  322.   if (FPkt = nil) or (FPkt^.Offset >= FPkt^.BufLen) then
  323.   begin
  324.     Result := 0;
  325.     Exit;
  326.   end;
  327.   Move(Ptr(LongWord(@FPkt^.Buf) + FPkt^.Offset)^, Buffer^, FPkt^.BufLen - FPkt^.Offset);
  328.   Result := FPkt^.BufLen - FPkt^.Offset;
  329. end;
  330. function TNetBuffer.SkipData(Len: Word): Boolean;
  331. begin
  332.   if FPkt = nil then
  333.   begin
  334.     Result := True;
  335.     Exit;
  336.   end;
  337.   Inc(FPkt^.Offset, Len);
  338.   Result := FPkt^.Offset >= FPkt^.BufLen;
  339. end;
  340. procedure TNetBuffer.AddStr(Value: String);
  341. begin
  342.   AddPacket(@Value[1], Length(Value)); 
  343. end;
  344. function TNetBuffer.GetStr: String;
  345. var
  346.   p: array[0..CNetPktLen] of Char;
  347. begin
  348.   p[GetPacket(@p)] := #0;
  349.   Result := PChar(@p);
  350. end;
  351. function InitMySocket(var WSA: TWSAData): LongWord;
  352. begin
  353.   Result := WSAStartup(MAKEWORD(1, 1), WSA);
  354. end;
  355. procedure FinalMySocket;
  356. begin
  357.   WSACleanUp;
  358. end;
  359. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  360. {$IFNDEF USE_FORMS}
  361. type
  362.   PObjectInstance = ^TObjectInstance;
  363.   TObjectInstance = packed record
  364.     Code: Byte;
  365.     Offset: Integer;
  366.     case Integer of
  367.       0: (Next: PObjectInstance);
  368.       1: (Method: TWndMethod);
  369.   end;
  370.   PInstanceBlock = ^TInstanceBlock;
  371.   TInstanceBlock = packed record
  372.     Next: PInstanceBlock;
  373.     Code: array[1..2] of Byte;
  374.     WndProcPtr: Pointer;
  375.     Instances: array[0..100] of TObjectInstance;
  376.   end;
  377. var
  378.   InstBlockList: PInstanceBlock;
  379.   InstFreeList: PObjectInstance;
  380. { Standard window procedure }
  381. { In    ECX = Address of method pointer }
  382. { Out   EAX = Result }
  383. function StdWndProc(Window: HWND; Message, WParam: Longint;
  384.   LParam: Longint): Longint; stdcall; assembler;
  385. asm
  386.           XOR     EAX,EAX
  387.           PUSH    EAX
  388.           PUSH    LParam
  389.           PUSH    WParam
  390.           PUSH    Message
  391.           MOV     EDX,ESP
  392.           MOV     EAX,[ECX].Longint[4]
  393.           CALL    [ECX].Pointer
  394.           ADD     ESP,12
  395.           POP     EAX
  396. end;
  397. { Allocate an object instance }
  398. function CalcJmpOffset(Src, Dest: Pointer): Longint;
  399. begin
  400.   Result := Longint(Dest) - (Longint(Src) + 5);
  401. end;
  402. function MakeObjectInstance(Method: TWndMethod): Pointer;
  403. const
  404.   BlockCode: array[1..2] of Byte = (
  405.     $59,       { POP ECX }
  406.     $E9);      { JMP StdWndProc }
  407.   PageSize = 4096;
  408. var
  409.   Block: PInstanceBlock;
  410.   Instance: PObjectInstance;
  411. begin
  412.   if InstFreeList = nil then
  413.   begin
  414.     Block := VirtualAlloc(nil, PageSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  415.     Block^.Next := InstBlockList;
  416.     Move(BlockCode, Block^.Code, SizeOf(BlockCode));
  417.     Block^.WndProcPtr := Pointer(CalcJmpOffset(@Block^.Code[2], @StdWndProc));
  418.     Instance := @Block^.Instances;
  419.     repeat
  420.       Instance^.Code := $E8;  { CALL NEAR PTR Offset }
  421.       Instance^.Offset := CalcJmpOffset(Instance, @Block^.Code);
  422.       Instance^.Next := InstFreeList;
  423.       InstFreeList := Instance;
  424.       Inc(Longint(Instance), SizeOf(TObjectInstance));
  425.     until Longint(Instance) - Longint(Block) >= SizeOf(TInstanceBlock);
  426.     InstBlockList := Block;
  427.   end;
  428.   Result := InstFreeList;
  429.   Instance := InstFreeList;
  430.   InstFreeList := Instance^.Next;
  431.   Instance^.Method := Method;
  432. end;
  433. { Free an object instance }
  434. procedure FreeObjectInstance(ObjectInstance: Pointer);
  435. begin
  436.   if ObjectInstance <> nil then
  437.   begin
  438.     PObjectInstance(ObjectInstance)^.Next := InstFreeList;
  439.     InstFreeList := ObjectInstance;
  440.   end;
  441. end;
  442. var
  443.   UtilWindowClass: TWndClass = (
  444.     style: 0;
  445.     lpfnWndProc: @DefWindowProc;
  446.     cbClsExtra: 0;
  447.     cbWndExtra: 0;
  448.     hInstance: 0;
  449.     hIcon: 0;
  450.     hCursor: 0;
  451.     hbrBackground: 0;
  452.     lpszMenuName: nil;
  453.     lpszClassName: 'MySockUtilWindow'
  454.   );
  455. function AllocateHWnd(Method: TWndMethod): THandle;
  456. var
  457.   TempClass: TWndClass;
  458.   ClassRegistered: Boolean;
  459. begin
  460.   UtilWindowClass.hInstance := HInstance;
  461.   ClassRegistered := GetClassInfo(HInstance, UtilWindowClass.lpszClassName,
  462.     TempClass);
  463.   if not ClassRegistered or (TempClass.lpfnWndProc <> @DefWindowProc) then
  464.   begin
  465.     if ClassRegistered then
  466.       Windows.UnregisterClass(UtilWindowClass.lpszClassName, HInstance);
  467.     Windows.RegisterClass(UtilWindowClass);
  468.   end;
  469.   Result := CreateWindow(UtilWindowClass.lpszClassName,
  470.     '', WS_POPUP, 0, 0, 0, 0, 0, 0, HInstance, nil);
  471.   if Assigned(Method) then
  472.     SetWindowLong(Result, GWL_WNDPROC, Longint(MakeObjectInstance(Method)));
  473. end;
  474. procedure DeallocateHWnd(Wnd: THandle);
  475. var
  476.   Instance: Pointer;
  477. begin
  478.   Instance := Pointer(GetWindowLong(Wnd, GWL_WNDPROC));
  479.   DestroyWindow(Wnd);
  480.   if Instance <> @DefWindowProc then FreeObjectInstance(Instance);
  481. end;
  482. {$ENDIF}
  483. /////////////////////////////////////////////////////////////////////////////////////////////////////////
  484. constructor TClSock.Create;
  485. begin
  486.   inherited;
  487.   FWndHandle := AllocateHwnd(OnSockMsg);
  488.   FClSock := INVALID_SOCKET;
  489.   FResolve := False;
  490.   FBuffer := TNetBuffer.Create;
  491. end;
  492. destructor TClSock.Destroy;
  493. begin
  494.   DoClose;
  495.   DeallocateHwnd(FWndHandle);
  496.   FBuffer.Free;
  497.   inherited;
  498. end;
  499. function TClSock.TestResolve(IP: String): Boolean;
  500. begin
  501.   Result := inet_addr(PChar(IP)) <> LongInt(INADDR_NONE);
  502. end;
  503. function TClSock.ResolveAddr(Value: Pointer): LongInt;
  504. var
  505.   addr: in_addr;
  506.   hostent: PHostEnt;
  507. begin
  508.   Result := -1;
  509.   hostent := Value;
  510.   if hostent^.h_addr_list <> nil then
  511.   begin
  512.     addr.S_addr := PLongInt(hostent^.h_addr_list^)^;
  513.     Result := addr.S_addr;
  514.   end else
  515.     Exit;
  516. end;
  517. procedure TClSock.InitConnect(dwIP: LongWord);
  518. var
  519.   dest_sin: TSockAddr;
  520. begin
  521.   DoClose;
  522.   FClSock := socket(AF_INET, SOCK_STREAM, 0);
  523.   WSAAsyncSelect(FClSock, FWndHandle, WSA_NETEVENT, FD_CONNECT or FD_CLOSE or FD_READ or FD_WRITE);
  524.   dest_sin.sin_family := AF_INET;
  525.   dest_sin.sin_addr.s_addr := dwIP;
  526.   dest_sin.sin_port := htons(FDestPort);
  527.   if (WinSock.connect(FClSock, dest_sin, SizeOf(TSockAddr)) = SOCKET_ERROR) and (WSAGetLastError <> WSAEWOULDBLOCK) then
  528.   begin
  529.     DoClose;  
  530.     if Assigned(OnError) then
  531.       FOnError(Self, ERR_SOCKET, 'connect() returned SOCKET_ERROR');
  532.     if Assigned(OnConnectError) then
  533.       FOnConnectError(Self);
  534.     Exit;
  535.   end;
  536. end;
  537. procedure TClSock.OnSockMsg(var Msg: TMessage);
  538. var
  539.   rc: Integer;
  540.   buf: array[0..1023] of Byte;
  541.   inaddr: in_addr;
  542. begin
  543.   case Msg.Msg of
  544.     WSA_RESOLVE_COMPLETE:
  545.     begin
  546.       if FResolve then
  547.       begin
  548.         if Assigned(OnResolve) then
  549.         begin
  550.           if HIWORD(Msg.wParam) <> 0 then
  551.           begin
  552.            if Assigned(OnError) then
  553.               FOnError(Self, ERR_SOCKET, 'Cannot resolve host');
  554.             if Assigned(OnResolveFailed) then
  555.               FOnFailed(Self);
  556.             Exit;
  557.           end;
  558.           inaddr.S_addr := ResolveAddr(@FHostIP);
  559.           if Assigned(OnResolve) then
  560.             FOnResolve(Self, inet_ntoa(inaddr));
  561.           Exit;
  562.         end;
  563.       end;
  564.       if HIWORD(Msg.wParam) <> 0 then
  565.       begin
  566.         DoClose;      
  567.         if Assigned(OnError) then
  568.           FOnError(Self, ERR_SOCKET, 'Cannot resolve host');
  569.         if Assigned(OnConnectError) then
  570.           FOnConnectError(Self);
  571.         Exit;
  572.       end;
  573.       InitConnect(ResolveAddr(@FHostIP));
  574.     end;
  575.     WSA_NETEVENT:
  576.     begin
  577.       if WSAGetSelectEvent(Msg.lParam) = FD_READ then
  578.       begin
  579.         rc := recv(Msg.wParam, buf, SizeOf(buf) - 1, 0);
  580.         if rc <> SOCKET_ERROR then
  581.         begin
  582.           if Assigned(OnRecieve) then
  583.             FOnRecv(Self, Msg.wParam, @buf, rc);
  584.         end else
  585.         begin
  586.           if Assigned(OnError) then
  587.             FOnError(Self, ERR_SOCKET, 'Received some data, but recv() returned 0');
  588.           Disconnect;
  589.         end;
  590.         Exit;
  591.       end
  592.       //Connection with server was lost
  593.       else if WSAGetSelectEvent(Msg.lParam) = FD_CLOSE then
  594.         Disconnect
  595.       //Connection with server has been estabilished or connection error
  596.       else if WSAGetSelectEvent(Msg.lParam) = FD_CONNECT then
  597.       begin
  598.         if HIWORD(Msg.lParam) = 0 then
  599.         begin
  600.           if Assigned(OnConnect) then
  601.             FOnConnect(Self);
  602.         end else
  603.         begin
  604.           DoClose;
  605.           if Assigned(OnError) then
  606.             FOnError(Self, ERR_SOCKET, 'Cannot connect: no rote to host.');
  607.           if Assigned(OnConnectError) then
  608.             FOnConnectError(Self);
  609.           Exit;
  610.         end;
  611.       end
  612.       else if WSAGetSelectEvent(Msg.lParam) = FD_WRITE then
  613.       begin
  614.         FCanWrite := True;
  615.         ProcessBuffer;
  616.       end;
  617.     end else
  618.       Msg.Result := DefWindowProc(FWndHandle, Msg.Msg, Msg.WParam, Msg.LParam);
  619.   end;
  620. end;
  621. procedure TClSock.ProcessBuffer;
  622. var
  623.   ret: Integer;
  624.   Buf: array[0..CNetPktLen - 1] of Byte;
  625. begin
  626.   if not FCanWrite then Exit;
  627.   if FClSock <> INVALID_SOCKET then
  628.   begin
  629.     while True do
  630.     begin
  631.       ret := FBuffer.GetPacket(@Buf);
  632.       if ret < 1 then begin if Assigned(OnDataSent) then FOnDataSent(Self); Exit; end; {All data has been sent}
  633.       ret := send(FClSock, Buf, ret, 0);
  634.       if ret = SOCKET_ERROR then
  635.       begin
  636.         if WSAGetLastError = WSAEWOULDBLOCK then
  637.           FCanWrite := False
  638.         else begin
  639.           if Assigned(OnError) then
  640.             FOnError(Self, ERR_SOCKET, 'Could not send data');
  641.           Disconnect;
  642.         end;
  643.         Exit;
  644.       end else
  645.         if FBuffer.SkipData(ret) then
  646.           FBuffer.DelPacket;
  647.     end;
  648.   end;
  649. end;
  650. function TClSock.IsConnected: Boolean;
  651. begin
  652.   Result := FClSock <> INVALID_SOCKET;
  653. end;
  654. procedure TClSock.Connect(ClearBuffer: Boolean = True);
  655. begin
  656.   FResolve := False;
  657.   if ClearBuffer then FBuffer.Clear;
  658.   if not TestResolve(FIp) then
  659.   begin
  660.     if WSAAsyncGetHostByName(FWndHandle, WSA_RESOLVE_COMPLETE, PChar(FIp), @FHostIp, SizeOf(FHostIp)) = 0 then
  661.     begin
  662.       DoClose;
  663.       if Assigned(OnError) then
  664.         FOnError(Self, ERR_SOCKET, 'Cannot init async. resolving');
  665.       if Assigned(OnConnectError) then
  666.         FOnConnectError(Self);
  667.       Exit;
  668.     end;
  669.   end else
  670.   begin
  671.     InitConnect(inet_addr(PChar(FIp)));
  672.   end;
  673. end;
  674. procedure TClSock.Resolve;
  675. begin
  676.   FBuffer.Clear;
  677.   if not TestResolve(FIp) then
  678.   begin
  679.     FResolve := True;
  680.     if WSAAsyncGetHostByName(FWndHandle, WSA_RESOLVE_COMPLETE, PChar(FIp), @FHostIp, SizeOf(FHostIp)) = 0 then
  681.     begin
  682.       DoClose;    
  683.       if Assigned(OnError) then
  684.         FOnError(Self, ERR_SOCKET, 'Cannot init async. resolving');
  685.       if Assigned(OnResolveFailed) then
  686.         FOnFailed(Self);
  687.     end;
  688.   end else
  689.   begin
  690.     FResolve := False;
  691.     if Assigned(OnResolve) then
  692.       FOnResolve(Self, FIp);
  693.   end;
  694. end;
  695. procedure TClSock.DoClose;
  696. begin
  697.   if FClSock <> INVALID_SOCKET then
  698.   begin
  699.     closesocket(FClSock);
  700.     FClSock := INVALID_SOCKET;
  701.   end;
  702. end;
  703. procedure TClSock.Disconnect;
  704. var
  705.   OldSock: TSocket;
  706. begin
  707.   OldSock := FClSock;
  708.   DoClose;
  709.   if OldSock <> INVALID_SOCKET then
  710.     if Assigned(OnDisconnect) then
  711.       FOnDisconnect(Self);
  712. end;
  713. procedure TClSock.SendData(var Buf; BufLen: LongWord);
  714. begin
  715.   if Assigned(OnPktParse) then
  716.     FOnPktParse(Self, @Buf, BufLen);
  717.   FBuffer.AddPacket(@Buf, BufLen);
  718.   ProcessBuffer;
  719. end;
  720. procedure TClSock.SendStr(const Value: String);
  721. begin
  722.   SendData(PChar(Value)^, Length(Value));
  723. end;
  724. function GetLocalIP: LongInt;
  725. type
  726.   PaPInAddr = ^TaPInAddr;
  727.   TaPInAddr = array[0..$FFFE] of PInAddr;
  728. var
  729.   phe: PHostEnt;
  730.   pptr: PaPInAddr;
  731.   Buffer: array[0..63] of Char;
  732.   I: Integer;
  733. begin
  734.   Result := -1;
  735.   GetHostName(Buffer, SizeOf(Buffer));
  736.   phe := GetHostByName(buffer);
  737.   if phe = nil then Exit;
  738.   pptr := PaPInAddr(Phe^.h_addr_list);
  739.   I := 0;
  740.   while pptr^[I] <> nil do
  741.   begin
  742.     Result := pptr^[I]^.S_addr;
  743.     Inc(I);
  744.   end;
  745. end;
  746. function FindBindPort: Word;
  747. var
  748.   i: Word;
  749.   srv_address: sockaddr_in;
  750.   sock: TSocket;
  751. begin
  752.   Result := 0;
  753.   sock := socket(AF_INET, SOCK_STREAM, 0);
  754.   if sock = INVALID_SOCKET then
  755.     Exit;
  756.   srv_address.sin_family := AF_INET;
  757.   srv_address.sin_addr.s_addr := INADDR_ANY;
  758.   for i := 3000 to 50000 do
  759.   begin
  760.     srv_address.sin_port := htons(i);
  761.     if bind(sock, srv_address, SizeOf(srv_address)) <> SOCKET_ERROR then
  762.     begin
  763.       closesocket(sock);
  764.       Result := i;
  765.       Exit;
  766.     end;
  767.   end;
  768. end;
  769. {@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@2}
  770. constructor TProxySock.Create;
  771. begin
  772.   inherited Create;
  773.   //Socket for working with TCP connections
  774.   FSrcLen := 0;
  775.   {$IFNDEF REMOVEHTTP}
  776.   FCurLen := 0;
  777.   FLen := 0;
  778.   FICQSEQ := 0;
  779.   FICQRecv := TClSock.Create;
  780.   FICQRecv.OnConnect := OnHTTPRecvSockConnect;
  781.   FICQRecv.OnRecieve := OnSockRecv;
  782.   {$ENDIF}
  783.   FSock := TClSock.Create;
  784.   FSock.OnRecieve := OnSockRecv;
  785.   FSock.OnDisconnect := OnSockDisconnect;
  786.   FSock.OnConnectError := OnSockConnectError;
  787.   FSock.OnPktParse := OnPktParse;
  788.   FSock.OnConnect := OnSockConnect;
  789.   FSock.OnResolve := OnSockResolve;
  790.   FSock.OnResolveFailed := OnSockResolveFailed;
  791.   FSock.OnError := OnSockError;
  792. end;
  793. {*** DESTRUCTOR ***}
  794. destructor TProxySock.Destroy;
  795. begin
  796.   FSock.OnRecieve := nil;          //.                                               .
  797.   FSock.OnDisconnect := nil;       //.                                               .
  798.   FSock.OnConnectError := nil;     //.   DO NOT USE NOTIFICATIONS WHILE DESTROYING   .
  799.   FSock.OnPktParse := nil;         //.      THE OBJECT, CAUSES ACCESS VIOLATIONS     .
  800.   FSock.OnConnect := nil;          //.                                               .
  801.   FSock.OnResolve := nil;          //.
  802.   FSock.OnError := nil;
  803.   FSock.Free;
  804.   {$IFNDEF REMOVEHTTP}
  805.   FICQRecv.OnError := nil;
  806.   FICQRecv.OnDisconnect := nil;
  807.   FICQRecv.Free;
  808.   {$ENDIF}
  809.   
  810.   inherited;
  811. end;
  812. {Connect procedure. Use it to connect to the remote server.}
  813. procedure TProxySock.Connect;
  814. begin
  815.   if (ProxyType = P_SOCKS4) or (ProxyType = P_SOCKS5) {$IFNDEF REMOVEHTTP} or (ProxyType = P_HTTP) {$ENDIF} then
  816.   begin
  817.     {$IFNDEF REMOVEHTTP}
  818.     FICQRecv.Disconnect;
  819.     {$ENDIF}
  820.     FSock.Disconnect;
  821.     FSock.OnPktParse := nil;       //Do not dump proxy data
  822.     if not FResolve then
  823.     begin
  824.       FSock.IP := Host;
  825.       FSock.Resolve;
  826.       Exit;
  827.     end;
  828.     FSock.IP := ProxyHost;
  829.     FSock.DestPort := ProxyPort;
  830.     FSock.Connect;
  831.   end else
  832.   begin
  833.     FSock.IP := Host;
  834.     FSock.DestPort := Port;
  835.     FSock.Connect;
  836.   end;
  837. end;
  838. {Force socket disconnection.}
  839. procedure TProxySock.Disconnect;
  840. begin
  841.   FSock.Disconnect;
  842.   {$IFNDEF REMOVEHTTP}
  843.   FICQRecv.Disconnect;
  844.   {$ENDIF}
  845. end;
  846. {Called when socket cannot connect to remote host.}
  847. procedure TProxySock.OnSockConnectError(Sender: TObject);
  848. begin
  849.   if Assigned(OnConnectError) then
  850.     FOnConnectError(Self);
  851. end;
  852. {Called when closed connection.}
  853. procedure TProxySock.OnSockDisconnect(Sender: TObject);
  854. begin
  855.   if Assigned(OnDisconnect) then
  856.     FOnDisconnect(Self);
  857. end;
  858. procedure TProxySock.OnSockError(Sender: TObject; ErrorType: TErrorType; ErrorMsg: String);
  859. begin
  860.   if Assigned(OnError) then
  861.     FOnError(Self, ErrorType, ErrorMsg);
  862. end;
  863. function TProxySock.GetWndHandle: THandle;
  864. begin
  865.   Result := FSock.WndHandle;
  866. end;
  867. {$IFNDEF REMOVEHTTP}
  868. procedure TProxySock.InitRecvConnection;
  869. begin
  870.   FICQRecv.IP := ProxyHost;
  871.   FICQRecv.DestPort := ProxyPort;
  872.   FICQRecv.Disconnect;
  873.   FICQRecv.Connect;
  874. end;
  875. procedure TProxySock.OnHTTPRecvSockConnect(Sender: TObject);
  876. begin
  877.   FICQRecv.SendStr(CreateHTTP_RECV(FICQPIP, FICQSID));
  878. end;
  879. procedure TProxySock.OnHTTPDataSent(Sender: TObject);
  880. begin
  881.   //FSock.Disconnect;
  882. end;
  883. {$ENDIF}
  884. {Called when resolving of Host has been complete.}
  885. procedure TProxySock.OnSockResolve(Sender: TObject; Addr: String);
  886. begin
  887.   if FProxyType = P_NONE then Exit;
  888.   Host := Addr;
  889.   FSock.IP := ProxyHost;
  890.   FSock.DestPort := ProxyPort;
  891.   FSock.Connect;
  892. end;
  893. {Called when resolving failed.}
  894. procedure TProxySock.OnSockResolveFailed(Sender: TObject);
  895. begin
  896.   if Assigned(OnConnectError) then
  897.     FOnConnectError(Self);
  898. end;
  899. {Called after our socket connected to server.}
  900. procedure TProxySock.OnSockConnect(Sender: TObject);
  901. var
  902.   buf: array[0..255] of Byte;
  903. begin
  904.   if ProxyType = P_NONE then                                   //Do nothing if we are not using proxies
  905.   begin
  906.     if Assigned(OnConnectProc) then
  907.       FOnConnectProc(Self);
  908.     Exit
  909.   end
  910.   else if ProxyType = P_SOCKS4 then
  911.   begin
  912.     buf[0] := 4;                                                //Socks4
  913.     buf[1] := 1;                                                //Code: 1 - Connect
  914.     PWord(Ptr(LongWord(@Buf) + 2))^ := htons(Port);             //Port
  915.     PDWord(Ptr(LongWord(@Buf) + 4))^ := inet_addr(PChar(Host)); //Host
  916.     if ProxyAuth then                                           //Add some packet specified data when using proxy authentication
  917.     begin
  918.       if Length(ProxyUserID) > 0 then                           //Test if ProxyUserID string is not nil
  919.         Move(PChar(ProxyUserID)^, buf[8], Length(ProxyUserID)); //If it's not then add it to packet
  920.       buf[8 + Length(ProxyUserID) + 1] := 0;                    //Always present NULL termination byte
  921.     end else
  922.       buf[9] := 0;                                              //Always present NULL termination byte
  923.     FSock.SendData(buf, 8 + Length(ProxyUserID) + 1);
  924.   end
  925.   else if ProxyType = P_SOCKS5 then
  926.   begin
  927.     FSocks := 0;                        //Socks authorization progress
  928.     buf[0] := 5;                        //Socks5
  929.     buf[1] := 1;                        //Number of methods
  930.     if ProxyAuth then                   //Choose auth method
  931.       buf[2] := 2                       //Use authentication
  932.     else
  933.       buf[2] := 0;                      //Plain connect
  934.     FSock.SendData(buf, 3);             //Send SOCKS5 initialization packet
  935.   end
  936.   {$IFNDEF REMOVEHTTP}
  937.   else if ProxyType = P_HTTP then
  938.     FSock.SendStr(CreateHTTP_INIT);
  939.   {$ENDIF}
  940. end;
  941. {$IFNDEF REMOVEHTTP}
  942. procedure TProxySock.SendHTTPData(Buffer: Pointer; BufLen: LongWord);
  943. var
  944.   buf: TRawPkt;
  945. begin
  946.   if BufLen = 0 then Exit;
  947.   Inc(FICQSeq);
  948.   PktInitRaw(@buf);
  949.   PktStr(@buf, CreateHTTP_Header('POST', 'http://' + FICQPIP + '/data?sid=' + FICQSID + '&seq=' + IntToStr(FICQSeq), FICQPIP, BufLen));
  950.   PktAddArrBuf(@buf, Buffer, BufLen);
  951.   FSock.Ip := ProxyHost;
  952.   FSock.DestPort := ProxyPort;
  953.   if not FSock.Connected then
  954.     FSock.Connect(False);
  955.   FSock.SendData(buf, buf.Len);
  956. end;
  957. procedure TProxySock.HandleHTTPDataPak(Buffer: Pointer; BufLen: LongWord);
  958. var
  959.   pkt: TRawPkt;
  960.   ptype: Word;
  961.   sw: LongWord;
  962. begin
  963.   Move(Buffer^, pkt.Data, BufLen);
  964.   pkt.Len := 0;
  965.   GetInt(@pkt, 2); //Version
  966.   ptype := GetInt(@pkt, 2);
  967.   Inc(pkt.Len, 6);
  968.   case ptype of
  969.     2 {HELLO REPLY}:
  970.     begin
  971.       sw := GetInt(@pkt, 4); FICQSid := IntToHex(sw, 8);
  972.       sw := GetInt(@pkt, 4); FICQSid := FICQSid + IntToHex(sw, 8);
  973.       sw := GetInt(@pkt, 4); FICQSid := FICQSid + IntToHex(sw, 8);
  974.       sw := GetInt(@pkt, 4); FICQSid := FICQSid + IntToHex(sw, 8);
  975.       FICQPIP := GetWStr(@pkt);
  976.       FICQPPort := GetLInt(@pkt, 2);
  977.       CreateHTTP_LOGIN(@pkt, Host, Port);
  978.       SendHTTPData(@pkt, pkt.Len);
  979.     end;
  980.     5 {FLAP PACKETS}:
  981.       OnReceive(Ptr(LongWord(@pkt.Data) + pkt.Len + 2), BufLen - pkt.Len - 2);
  982.   end;
  983. end;
  984. procedure TProxySock.HandleHTTPData(Buffer: Pointer; BufLen: LongWord);
  985. function GetHTTPStatus(List: TStringList): String;
  986. var
  987.   i, c: Word;
  988.   S: String;
  989. begin
  990.   if List.Count < 1 then Exit;
  991.   S := List.Strings[0]; c := 0;
  992.   for i := 1 to Length(S) do
  993.     if c = 1 then
  994.       Result := Result + S[i]
  995.     else
  996.       if S[i] = ' ' then Inc(c);
  997. end;
  998. function GetHTTPLength(List: TStringList): Integer;
  999. var
  1000.   i: Word;
  1001. begin
  1002.   Result := 0;
  1003.   if List.Count < 1 then Exit;
  1004.   for i := 0 to List.Count - 1 do
  1005.     if Copy(List.Strings[i], 0, 16) = 'Content-Length: ' then
  1006.     begin
  1007.       Result := StrToInt(Copy(List.Strings[i], 16, $FF));
  1008.       Exit;
  1009.     end;
  1010. end;
  1011. {$WARNINGS OFF}
  1012. procedure HandleICQPakHTTP(Buffer: Pointer; BufLen: LongWord);
  1013. var
  1014.   Len: Word;
  1015.   Buf: TRawPkt;
  1016.   l: LongWord;
  1017. begin
  1018.   l := 0;
  1019.   if BufLen > $FFFF then Exit;
  1020.   while True do
  1021.   begin
  1022.     if l = BufLen then Break;
  1023.     Len := Swap16(PWord(Buffer)^);
  1024.     if (Len > 8192) or (Len < 12) then Break;
  1025.     Move(Ptr(LongWord(Buffer) + 2)^, Buf, Len);
  1026.     Inc(l, Len + 2);
  1027.     Buffer := Ptr(LongWord(Buffer) + Len + 2);
  1028.     {Handle ICQ Pak packet}
  1029.     HandleHTTPDataPak(@Buf, Len);
  1030.     //LogText('proto.txt', DumpPacket(@Buf, Len));
  1031.   end;
  1032. end;
  1033. {$WARNINGS ON}
  1034. var
  1035.   i: LongWord;
  1036.   List: TStringList;
  1037.   l: LongWord;
  1038.   s: String;
  1039. begin
  1040.   if BufLen < 1 then Exit;
  1041.   for i := 0 to BufLen - 1 do
  1042.   begin
  1043.     FBuf[FCurLen] := PByte(LongWord(Buffer) + i)^;
  1044.     Inc(FCurLen);
  1045.     if flen = 0 then
  1046.       if FCurLen > 3 then
  1047.         if Copy(PChar(@FBuf), FCurLen - 3, 4) = #13#10#13#10 then
  1048.         begin
  1049.           FCurLen := 0;
  1050.           List := TStringList.Create;
  1051.           List.Text := PChar(@FBuf);
  1052.           s := GetHTTPStatus(List);
  1053.           flen := GetHTTPLength(List);
  1054.           List.Free;
  1055.           if s <> '200 OK' then
  1056.           begin
  1057.             if Assigned(OnError) then
  1058.               FOnError(Self, ERR_PROTOCOL, 'Http proxy returned invalid status: ' + s);
  1059.             FSock.Disconnect;
  1060.             FICQRecv.Disconnect;
  1061.             Exit;
  1062.           end;
  1063.         end;
  1064.     if (FCurLen = flen) and (FCurLen <> 0) then
  1065.     begin
  1066.       l := FCurLen; flen := 0; FCurLen := 0; {using l, avoiding AVs}
  1067.       HandleICQPakHTTP(@FBuf, l);
  1068.       InitRecvConnection;
  1069.       {send HTTP_RECV}
  1070.       //FSock.SendStr(CreateHTTP_RECV(FICQPIP, FICQSID))
  1071.     end;
  1072.   end;
  1073. end;
  1074. {$ENDIF}
  1075. {Called when something received on socket.}
  1076. procedure TProxySock.OnSockRecv(Sender: TObject; Socket: TSocket; Buffer: Pointer; BufLen: LongWord);
  1077. var
  1078.   i: Word;
  1079.   UserLen, PassLen: Word;
  1080.   procedure DoSocks5Connect;
  1081.   var
  1082.     len: Word;
  1083.     buf: array[0..255] of Byte;
  1084.   begin
  1085.     if not UseProxyResolve then         //Socks5 supports on-server-resolving
  1086.       len := 4
  1087.     else
  1088.       len := Length(Host) + 1;
  1089.     buf[0] := 5;                        //Socks5
  1090.     buf[1] := 1;                        //Command: connect
  1091.     buf[2] := 0;                        //Reserved
  1092.     if UseProxyResolve then
  1093.     begin
  1094.       buf[3] := 3;
  1095.       buf[4] := len - 1;
  1096.       Move(PChar(Host)^, buf[5], len - 1);
  1097.     end else
  1098.     begin
  1099.       buf[3] := 1;
  1100.       PDWord(LongWord(@buf) + 4)^ := inet_addr(PChar(Host));
  1101.     end;
  1102.     PWord(LongWord(@buf) + 4 + Len)^ := htons(Port);
  1103.     FSock.SendData(buf, 6 + Len);
  1104.   end;
  1105. begin
  1106.   if BufLen = 0 then Exit;
  1107.   if ProxyType = P_SOCKS4 then
  1108.   begin
  1109.     for i := 0 to BufLen - 1 do
  1110.     begin
  1111.       FSrcBuf[FSrcLen] := PByte(LongWord(Buffer) + i)^;
  1112.       Inc(FSrcLen);
  1113.       if FSrcLen = 8 then
  1114.       begin
  1115.         FProxyType := P_NONE;           //After we connected to proxy we work as usual
  1116.         Dec(BufLen, i);
  1117.         FSrcLen := 0;
  1118.         if PByte(Ptr(LongWord(Buffer) + 1))^ <> 90 then
  1119.         begin
  1120.           if Assigned(OnError) then
  1121.             FOnError(Self, ERR_PROXY, 'SOCKS4 server cannot connect to remote server');
  1122.           if Assigned(OnConnectError) then
  1123.             FOnConnectError(Self);
  1124.           Exit;
  1125.         end;
  1126.         FSock.OnPktParse := OnPktParse;
  1127.         if Assigned(OnConnectProc) then
  1128.           FOnConnectProc(Self);
  1129.         if i < BufLen - 1 then
  1130.           OnSockRecv(Sender, Socket, Ptr(LongWord(Buffer) + i), BufLen);        //Continue handling of remaining data
  1131.       end;
  1132.     end;
  1133.     Exit;
  1134.   end else
  1135.   if ProxyType = P_SOCKS5 then
  1136.   begin
  1137.     for i := 0 to BufLen - 1 do
  1138.     begin
  1139.       FSrcBuf[FSrcLen] := PByte(LongWord(Buffer) + i)^;
  1140.       Inc(FSrcLen);
  1141.       case FSocks of
  1142.         0:
  1143.         begin
  1144.           if FSrcLen = 2 then
  1145.           begin
  1146.             if FSrcBuf[1] = $ff then
  1147.             begin
  1148.               if Assigned(OnError) then
  1149.                 FOnError(Self, ERR_PROXY, 'Auth methods are not supported by SOCKS5 server');
  1150.               if Assigned(OnConnectError) then
  1151.                 FOnConnectError(Self);
  1152.               Exit;
  1153.             end;
  1154.             FSrcLen := 0;
  1155.             if FSrcBuf[1] = 2 then
  1156.             begin
  1157.               UserLen := Length(ProxyUserID);
  1158.               PassLen := Length(ProxyPass);
  1159.               FSrcBuf[0] := 1;
  1160.               FSrcBuf[1] := UserLen;
  1161.               Move(PChar(ProxyUserID)^, Ptr(LongWord(@FSrcBuf) + 2)^, UserLen);
  1162.               FSrcBuf[UserLen + 2] := PassLen;
  1163.               Move(PChar(ProxyPass)^, Ptr(LongWord(@FSrcBuf) + 3 + UserLen)^, UserLen);
  1164.               FSock.SendData(FSrcBuf, 3 + UserLen + PassLen);
  1165.               Inc(FSocks);
  1166.             end else
  1167.             begin
  1168.               Inc(FSocks, 2);
  1169.               DoSocks5Connect;
  1170.             end;
  1171.           end;
  1172.         end;
  1173.         1:
  1174.         begin
  1175.           if FSrcLen = 2 then
  1176.           begin
  1177.             if FSrcBuf[1] <> 0 then
  1178.             begin
  1179.               if Assigned(OnError) then
  1180.                 FOnError(Self, ERR_PROXY, 'SOCKS5 server cannot authenticate us');
  1181.               if Assigned(OnConnectError) then
  1182.                 FOnConnectError(Self);
  1183.               Exit;
  1184.             end;
  1185.             FSrcLen := 0;
  1186.             Inc(FSocks);
  1187.             DoSocks5Connect;
  1188.           end;
  1189.         end;
  1190.         2:
  1191.         begin
  1192.           if FSrcLen = 10 then
  1193.           begin
  1194.             if (FSrcBuf[0] <> 5) or (FSrcBuf[1] <> 0) then
  1195.             begin
  1196.               if Assigned(OnError) then
  1197.                 FOnError(Self, ERR_PROXY, 'SOCKS5 server cannot connect to remote server');
  1198.               if Assigned(OnConnectError) then
  1199.                 FOnConnectError(Self);
  1200.               Exit;
  1201.             end;
  1202.             FSrcLen := 0;
  1203.             ProxyType := P_NONE;
  1204.             FSock.OnPktParse := OnPktParse;
  1205.             if Assigned(OnConnectProc) then
  1206.               FOnConnectProc(Self);
  1207.             if i < BufLen - 1 then
  1208.               OnSockRecv(Sender, Socket, Ptr(LongWord(Buffer) + i), BufLen);        //Continue handling of remaining data
  1209.           end;
  1210.         end;
  1211.       end;
  1212.     end;
  1213.     Exit;
  1214.   end; {$IFNDEF REMOVEHTTP} else
  1215.   if ProxyType = P_HTTP then
  1216.   begin
  1217.     HandleHTTPData(Buffer, BufLen);
  1218.     InitRecvConnection;
  1219.     Exit;
  1220.   end;{$ENDIF}
  1221.   OnReceive(Buffer, BufLen);
  1222. end;
  1223. {Called when some data has been sent through socket.}
  1224. procedure TProxySock.OnPktParse(Sender: TObject; Buffer: Pointer; BufLen: LongWord);
  1225. begin
  1226.   if Assigned(OnPktParseA) then
  1227.     FOnPktParse(Sender, Buffer, BufLen, False);
  1228. end;
  1229. {Sending data throgh socket.}
  1230. procedure TProxySock.SendData(var Buf; BufLen: LongWord);
  1231. {$IFNDEF REMOVEHTTP}
  1232. var
  1233.   pkt: TRawPkt;
  1234. {$ENDIF}
  1235. begin
  1236.   {$IFNDEF REMOVEHTTP}
  1237.   if FProxyType <> P_HTTP then
  1238.     FSock.SendData(Buf, BufLen)
  1239.   else begin
  1240.     if Assigned(OnPktParseA) then
  1241.       FOnPktParse(Self, @Buf, BufLen, False);
  1242.     CreateHTTP_DATA(@pkt, $0005, @Buf, BufLen);
  1243.     SendHTTPData(@pkt, pkt.Len);
  1244.   end;
  1245.   {$ELSE}
  1246.   FSock.SendData(Buf, BufLen)  
  1247.   {$ENDIF}
  1248. end;
  1249. {Forward handlers.}
  1250. procedure TProxySock.OnReceive;
  1251. begin
  1252.   if Assigned(OnReceiveProc) then
  1253.     FOnRecv(Self, FSock.FClSock, Buffer, BufLen);
  1254. end;
  1255. function TMySock.GetClientSocket: TSocket;
  1256. begin
  1257.   Result := FSock.FClSock;
  1258. end;
  1259. procedure TMySock.SetClientSocket(Socket: TSocket);
  1260. begin
  1261.   FSock.FClSock := Socket;
  1262. end;
  1263. function TMySock.IsConnected: Boolean;
  1264. begin
  1265.   Result := FSock.IsConnected;
  1266. end;
  1267. {@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@}
  1268. {-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=}
  1269. constructor TSrvSock.Create;
  1270. begin
  1271.   inherited;
  1272.   FWndHandle := AllocateHwnd(OnSockMsg);
  1273.   FSrvSock := INVALID_SOCKET;
  1274.   FPort := 0;
  1275. end;
  1276. destructor TSrvSock.Destroy;
  1277. begin
  1278.   StopServer;
  1279.   DeallocateHwnd(FWndHandle);
  1280.   
  1281.   inherited;
  1282. end;
  1283. procedure TSrvSock.OnSockMsg(var Msg: TMessage);
  1284. var
  1285.   rc: Integer;
  1286.   acc_sin_len: Integer;
  1287.   acc_sin: sockaddr_in;
  1288.   FClSock: TSocket;
  1289.   FCl: TMySock;
  1290. begin
  1291.   case Msg.Msg of
  1292.     WSA_ACCEPT:
  1293.     begin
  1294.       if WSAGETSELECTERROR(Msg.lParam) <> 0 then
  1295.       begin
  1296.         MessageBox(0, 'accept() Error', 'Error', MB_OK);
  1297.         //WSAAsyncSelect(FSrvSock, FWndHandle, 0, 0);
  1298.         Exit;
  1299.       end;
  1300.       //Size of acc_sin
  1301.       acc_sin_len := SizeOf(acc_sin);
  1302.       //Allow connection
  1303.       FClSock := accept(FSrvSock, @acc_sin, @acc_sin_len);
  1304.       if FClSock = INVALID_SOCKET then
  1305.       begin
  1306.         MessageBox(0, 'accept() Error, invalid socket', 'Error', MB_OK);
  1307.         Exit;
  1308.       end;
  1309.       FCl := TMySock.Create;
  1310.       FCl.ClientSocket := FClSock;
  1311.       //Allow network notifies in client socket
  1312.       rc := WSAAsyncSelect(FClSock, FCl.WndHandle, WSA_NETEVENT,
  1313.         FD_READ or FD_CLOSE or FD_WRITE);
  1314.       if rc > 0 then
  1315.       begin
  1316.         closesocket(FClSock);
  1317.         MessageBox(0, 'WSAAsyncSelect Error', 'Error', MB_OK);
  1318.         FCl.Free;
  1319.         Exit;
  1320.       end;
  1321.       if Assigned(OnClientConnected) then
  1322.         FOnClientConnected(Self, FCl);
  1323.     end else
  1324.       Msg.Result := DefWindowProc(FWndHandle, Msg.Msg, Msg.WParam, Msg.LParam);
  1325.   end;
  1326. end;
  1327. function TSrvSock.StartServer(Port: Word): Boolean;
  1328. var
  1329.   srv_address: sockaddr_in;
  1330.   rc: Integer;
  1331. begin
  1332.   Result := False;
  1333.   FPort := 0;
  1334.   //Creating server socket
  1335.   FSrvSock := socket(AF_INET, SOCK_STREAM, 0);
  1336.   if FSrvSock = INVALID_SOCKET then
  1337.   begin
  1338.     MessageBox(0, 'Could not create server socket()', 'Error', MB_OK);
  1339.     Exit;
  1340.   end;
  1341.   srv_address.sin_family := AF_INET;
  1342.   srv_address.sin_addr.s_addr := INADDR_ANY;  //Accept connection from all addresses
  1343.   srv_address.sin_port := htons(Port);        //Set local port
  1344.   //Binding a port
  1345.   if bind(FSrvSock, srv_address, SizeOf(srv_address)) = SOCKET_ERROR then
  1346.   begin
  1347.     //Closing socket on error
  1348.     closesocket(FSrvSock);
  1349.     MessageBox(0, 'Could not bind server', 'Error', MB_OK);
  1350.     Exit;
  1351.   end;
  1352.   //Setting socket in listen status
  1353.   if listen(FSrvSock, 5) = SOCKET_ERROR then
  1354.   begin
  1355.     closesocket(FSrvSock);
  1356.     MessageBox(0, 'listen() Error', 'Error', MB_OK);
  1357.     Exit;
  1358.   end;
  1359.   rc := WSAAsyncSelect(FSrvSock, FWndHandle, WSA_ACCEPT, FD_ACCEPT);
  1360.   if rc > 0 then
  1361.   begin
  1362.     closesocket(FSrvSock);
  1363.     MessageBox(0, 'WSAAsyncSelect Error', 'Error', MB_OK);
  1364.     Exit;
  1365.   end;
  1366.   Result := True;
  1367.   FPort := Port;
  1368. end;
  1369. function TSrvSock.StopServer: Boolean;
  1370. begin
  1371.   Result := False;
  1372.   if FSrvSock  <> INVALID_SOCKET then
  1373.   begin
  1374.     //Removing receiveing of all notifications
  1375.     WSAAsyncSelect(FSrvSock, FWndHandle, 0, 0);
  1376.     //If socket was created then close it
  1377.     closesocket(FSrvSock);
  1378.     FSrvSock := INVALID_SOCKET;
  1379.     Result := True;
  1380.   end;
  1381. end;
  1382. initialization
  1383. begin
  1384.   InitMySocket(WSA);
  1385.   {$IFNDEF USE_FORMS}
  1386.   InstBlockList := nil;
  1387.   InstFreeList := nil;
  1388.   {$ENDIF}
  1389. end;
  1390. finalization
  1391. begin
  1392.   FinalMySocket;
  1393. end;
  1394. end.