2008-04-23 23:17:14 +03:00
|
|
|
{==============================================================================|
|
2008-04-24 10:12:01 +03:00
|
|
|
| Project : Delphree - Synapse | 004.004.000 |
|
2008-04-23 23:17:14 +03:00
|
|
|
|==============================================================================|
|
|
|
|
| Content: Library base |
|
|
|
|
|==============================================================================|
|
2008-04-24 10:05:26 +03:00
|
|
|
| The contents of this file are subject to the Mozilla Public License Ver. 1.1 |
|
2008-04-23 23:17:14 +03:00
|
|
|
| (the "License"); you may not use this file except in compliance with the |
|
|
|
|
| License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ |
|
|
|
|
| |
|
|
|
|
| Software distributed under the License is distributed on an "AS IS" basis, |
|
|
|
|
| WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for |
|
|
|
|
| the specific language governing rights and limitations under the License. |
|
|
|
|
|==============================================================================|
|
|
|
|
| The Original Code is Synapse Delphi Library. |
|
|
|
|
|==============================================================================|
|
|
|
|
| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
|
2008-04-24 09:44:13 +03:00
|
|
|
| Portions created by Lukas Gebauer are Copyright (c)1999,2000,2001. |
|
2008-04-23 23:17:14 +03:00
|
|
|
| All Rights Reserved. |
|
|
|
|
|==============================================================================|
|
|
|
|
| Contributor(s): |
|
|
|
|
|==============================================================================|
|
2008-04-23 23:24:29 +03:00
|
|
|
| History: see HISTORY.HTM from distribution package |
|
2008-04-23 23:48:39 +03:00
|
|
|
| (Found at URL: http://www.ararat.cz/synapse/) |
|
2008-04-23 23:17:14 +03:00
|
|
|
|==============================================================================}
|
|
|
|
|
2008-04-24 10:12:01 +03:00
|
|
|
{$Q-}
|
2008-04-24 10:05:26 +03:00
|
|
|
{$WEAKPACKAGEUNIT ON}
|
|
|
|
|
2008-04-23 23:17:14 +03:00
|
|
|
unit blcksock;
|
|
|
|
|
|
|
|
interface
|
|
|
|
|
|
|
|
uses
|
2008-04-24 10:05:26 +03:00
|
|
|
SysUtils, Classes,
|
2008-04-24 09:59:26 +03:00
|
|
|
{$IFDEF LINUX}
|
2008-04-24 10:05:26 +03:00
|
|
|
Libc, kernelioctl,
|
2008-04-24 09:59:26 +03:00
|
|
|
{$ELSE}
|
2008-04-24 10:05:26 +03:00
|
|
|
Windows, WinSock,
|
2008-04-24 09:59:26 +03:00
|
|
|
{$ENDIF}
|
2008-04-24 10:09:13 +03:00
|
|
|
synsock, SynaUtil;
|
2008-04-24 10:05:26 +03:00
|
|
|
|
|
|
|
const
|
|
|
|
cLocalhost = 'localhost';
|
2008-04-23 23:17:14 +03:00
|
|
|
|
|
|
|
type
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
ESynapseError = class(Exception)
|
|
|
|
public
|
|
|
|
ErrorCode: Integer;
|
|
|
|
ErrorMessage: string;
|
|
|
|
end;
|
|
|
|
|
2008-04-24 10:07:45 +03:00
|
|
|
THookSocketReason = (
|
|
|
|
HR_ResolvingBegin,
|
|
|
|
HR_ResolvingEnd,
|
|
|
|
HR_SocketCreate,
|
|
|
|
HR_SocketClose,
|
|
|
|
HR_Bind,
|
|
|
|
HR_Connect,
|
|
|
|
HR_CanRead,
|
|
|
|
HR_CanWrite,
|
|
|
|
HR_Listen,
|
|
|
|
HR_Accept,
|
|
|
|
HR_ReadCount,
|
|
|
|
HR_WriteCount
|
|
|
|
);
|
|
|
|
|
|
|
|
THookSocketStatus = procedure(Sender: TObject; Reason: THookSocketReason;
|
|
|
|
const Value: string) of object;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
TBlockSocket = class(TObject)
|
|
|
|
private
|
2008-04-24 10:07:45 +03:00
|
|
|
FOnStatus: THookSocketStatus;
|
2008-04-24 10:05:26 +03:00
|
|
|
FWsaData: TWSADATA;
|
|
|
|
FLocalSin: TSockAddrIn;
|
|
|
|
FRemoteSin: TSockAddrIn;
|
|
|
|
FLastError: Integer;
|
|
|
|
FBuffer: string;
|
|
|
|
FRaiseExcept: Boolean;
|
2008-04-24 10:12:01 +03:00
|
|
|
FNonBlockMode: Boolean;
|
|
|
|
FMaxLineLength: Integer;
|
|
|
|
FMaxBandwidth: Integer;
|
|
|
|
FNextSend: Cardinal;
|
2008-04-24 10:05:26 +03:00
|
|
|
function GetSizeRecvBuffer: Integer;
|
|
|
|
procedure SetSizeRecvBuffer(Size: Integer);
|
|
|
|
function GetSizeSendBuffer: Integer;
|
|
|
|
procedure SetSizeSendBuffer(Size: Integer);
|
2008-04-24 10:12:01 +03:00
|
|
|
procedure SetNonBlockMode(Value: Boolean);
|
2008-04-24 10:05:26 +03:00
|
|
|
protected
|
|
|
|
FSocket: TSocket;
|
|
|
|
FProtocol: Integer;
|
|
|
|
procedure CreateSocket; virtual;
|
|
|
|
procedure SetSin(var Sin: TSockAddrIn; IP, Port: string);
|
|
|
|
function GetSinIP(Sin: TSockAddrIn): string;
|
|
|
|
function GetSinPort(Sin: TSockAddrIn): Integer;
|
2008-04-24 10:07:45 +03:00
|
|
|
procedure DoStatus(Reason: THookSocketReason; const Value: string);
|
2008-04-24 10:12:01 +03:00
|
|
|
procedure LimitBandwidth(Length: Integer);
|
2008-04-24 10:05:26 +03:00
|
|
|
public
|
|
|
|
constructor Create;
|
|
|
|
constructor CreateAlternate(Stub: string);
|
|
|
|
destructor Destroy; override;
|
|
|
|
procedure CloseSocket; virtual;
|
|
|
|
procedure Bind(IP, Port: string);
|
2008-04-24 10:09:13 +03:00
|
|
|
procedure Connect(IP, Port: string); virtual;
|
2008-04-24 10:05:26 +03:00
|
|
|
function SendBuffer(Buffer: Pointer; Length: Integer): Integer; virtual;
|
|
|
|
procedure SendByte(Data: Byte); virtual;
|
|
|
|
procedure SendString(const Data: string); virtual;
|
|
|
|
function RecvBuffer(Buffer: Pointer; Length: Integer): Integer; virtual;
|
|
|
|
function RecvBufferEx(Buffer: Pointer; Length: Integer;
|
|
|
|
Timeout: Integer): Integer; virtual;
|
|
|
|
function RecvByte(Timeout: Integer): Byte; virtual;
|
|
|
|
function RecvString(Timeout: Integer): string; virtual;
|
2008-04-24 10:12:01 +03:00
|
|
|
function RecvTerminated(Timeout: Integer; const Terminator: string): string; virtual;
|
2008-04-24 10:09:13 +03:00
|
|
|
function RecvPacket(Timeout: Integer): string; virtual;
|
2008-04-24 10:05:26 +03:00
|
|
|
function PeekBuffer(Buffer: Pointer; Length: Integer): Integer; virtual;
|
|
|
|
function PeekByte(Timeout: Integer): Byte; virtual;
|
|
|
|
function WaitingData: Integer;
|
|
|
|
procedure SetLinger(Enable: Boolean; Linger: Integer);
|
|
|
|
procedure GetSins;
|
|
|
|
function SockCheck(SockResult: Integer): Integer;
|
|
|
|
procedure ExceptCheck;
|
|
|
|
function LocalName: string;
|
|
|
|
procedure ResolveNameToIP(Name: string; IPList: TStrings);
|
2008-04-24 10:09:13 +03:00
|
|
|
function ResolveName(Name: string): string;
|
|
|
|
function ResolvePort(Port: string): Word;
|
|
|
|
procedure SetRemoteSin(IP, Port: string);
|
|
|
|
function GetLocalSinIP: string; virtual;
|
|
|
|
function GetRemoteSinIP: string; virtual;
|
|
|
|
function GetLocalSinPort: Integer; virtual;
|
|
|
|
function GetRemoteSinPort: Integer; virtual;
|
2008-04-24 10:05:26 +03:00
|
|
|
function CanRead(Timeout: Integer): Boolean;
|
|
|
|
function CanWrite(Timeout: Integer): Boolean;
|
2008-04-24 10:09:13 +03:00
|
|
|
function SendBufferTo(Buffer: Pointer; Length: Integer): Integer; virtual;
|
|
|
|
function RecvBufferFrom(Buffer: Pointer; Length: Integer): Integer; virtual;
|
2008-04-24 10:05:26 +03:00
|
|
|
function GroupCanRead(const SocketList: TList; Timeout: Integer;
|
|
|
|
const CanReadList: TList): Boolean;
|
2008-04-24 10:12:01 +03:00
|
|
|
function EnableReuse(Value: Boolean): Boolean;
|
2008-04-24 10:05:26 +03:00
|
|
|
|
|
|
|
//See 'winsock2.txt' file in distribute package!
|
|
|
|
function SetTimeout(Timeout: Integer): Boolean;
|
2008-04-24 10:09:13 +03:00
|
|
|
function SetSendTimeout(Timeout: Integer): Boolean;
|
|
|
|
function SetRecvTimeout(Timeout: Integer): Boolean;
|
2008-04-24 10:05:26 +03:00
|
|
|
|
|
|
|
property LocalSin: TSockAddrIn read FLocalSin;
|
|
|
|
property RemoteSin: TSockAddrIn read FRemoteSin;
|
|
|
|
published
|
|
|
|
class function GetErrorDesc(ErrorCode: Integer): string;
|
|
|
|
property Socket: TSocket read FSocket write FSocket;
|
|
|
|
property LastError: Integer read FLastError;
|
|
|
|
property Protocol: Integer read FProtocol;
|
|
|
|
property LineBuffer: string read FBuffer write FBuffer;
|
|
|
|
property RaiseExcept: Boolean read FRaiseExcept write FRaiseExcept;
|
|
|
|
property SizeRecvBuffer: Integer read GetSizeRecvBuffer write SetSizeRecvBuffer;
|
|
|
|
property SizeSendBuffer: Integer read GetSizeSendBuffer write SetSizeSendBuffer;
|
|
|
|
property WSAData: TWSADATA read FWsaData;
|
2008-04-24 10:07:45 +03:00
|
|
|
property OnStatus: THookSocketStatus read FOnStatus write FOnStatus;
|
2008-04-24 10:12:01 +03:00
|
|
|
property NonBlockMode: Boolean read FNonBlockMode Write SetNonBlockMode;
|
|
|
|
property MaxLineLength: Integer read FMaxLineLength Write FMaxLineLength;
|
|
|
|
property MaxBandwidth: Integer read FMaxBandwidth Write FMaxBandwidth;
|
2008-04-24 10:05:26 +03:00
|
|
|
end;
|
|
|
|
|
2008-04-24 10:09:13 +03:00
|
|
|
TSocksBlockSocket = class(TBlockSocket)
|
|
|
|
protected
|
|
|
|
FSocksIP: string;
|
|
|
|
FSocksPort: string;
|
|
|
|
FSocksTimeout: integer;
|
|
|
|
FSocksUsername: string;
|
|
|
|
FSocksPassword: string;
|
|
|
|
FUsingSocks: Boolean;
|
|
|
|
FSocksResolver: Boolean;
|
|
|
|
FSocksLastError: integer;
|
|
|
|
FSocksResponseIP: string;
|
|
|
|
FSocksResponsePort: string;
|
|
|
|
FSocksLocalIP: string;
|
|
|
|
FSocksLocalPort: string;
|
|
|
|
FSocksRemoteIP: string;
|
|
|
|
FSocksRemotePort: string;
|
|
|
|
function SocksCode(IP, Port: string): string;
|
|
|
|
function SocksDecode(Value: string): integer;
|
2008-04-24 10:05:26 +03:00
|
|
|
public
|
2008-04-24 10:09:13 +03:00
|
|
|
constructor Create;
|
|
|
|
function SocksOpen: Boolean;
|
|
|
|
function SocksRequest(Cmd: Byte; const IP, Port: string): Boolean;
|
|
|
|
function SocksResponse: Boolean;
|
|
|
|
published
|
|
|
|
property SocksIP: string read FSocksIP write FSocksIP;
|
|
|
|
property SocksPort: string read FSocksPort write FSocksPort;
|
|
|
|
property SocksUsername: string read FSocksUsername write FSocksUsername;
|
|
|
|
property SocksPassword: string read FSocksPassword write FSocksPassword;
|
|
|
|
property UsingSocks: Boolean read FUsingSocks;
|
|
|
|
property SocksResolver: Boolean read FSocksResolver write FSocksResolver;
|
|
|
|
property SocksLastError: integer read FSocksLastError;
|
2008-04-24 10:05:26 +03:00
|
|
|
end;
|
|
|
|
|
2008-04-24 10:09:13 +03:00
|
|
|
TTCPBlockSocket = class(TSocksBlockSocket)
|
2008-04-24 10:05:26 +03:00
|
|
|
public
|
|
|
|
procedure CreateSocket; override;
|
|
|
|
procedure CloseSocket; override;
|
|
|
|
procedure Listen;
|
|
|
|
function Accept: TSocket;
|
2008-04-24 10:09:13 +03:00
|
|
|
procedure Connect(IP, Port: string); override;
|
|
|
|
function GetLocalSinIP: string; override;
|
|
|
|
function GetRemoteSinIP: string; override;
|
|
|
|
function GetLocalSinPort: Integer; override;
|
|
|
|
function GetRemoteSinPort: Integer; override;
|
|
|
|
end;
|
|
|
|
|
|
|
|
TUDPBlockSocket = class(TSocksBlockSocket)
|
|
|
|
protected
|
|
|
|
FSocksControlSock: TTCPBlockSocket;
|
|
|
|
function UdpAssociation: Boolean;
|
|
|
|
public
|
|
|
|
destructor Destroy; override;
|
|
|
|
procedure CreateSocket; override;
|
|
|
|
function EnableBroadcast(Value: Boolean): Boolean;
|
|
|
|
procedure Connect(IP, Port: string); override;
|
|
|
|
function SendBuffer(Buffer: Pointer; Length: Integer): Integer; override;
|
|
|
|
function RecvBuffer(Buffer: Pointer; Length: Integer): Integer; override;
|
|
|
|
function SendBufferTo(Buffer: Pointer; Length: Integer): Integer; override;
|
|
|
|
function RecvBufferFrom(Buffer: Pointer; Length: Integer): Integer; override;
|
2008-04-24 10:12:01 +03:00
|
|
|
procedure AddMulticast(MCastIP:string);
|
|
|
|
procedure DropMulticast(MCastIP:string);
|
2008-04-24 10:05:26 +03:00
|
|
|
end;
|
|
|
|
|
|
|
|
//See 'winsock2.txt' file in distribute package!
|
|
|
|
TICMPBlockSocket = class(TBlockSocket)
|
|
|
|
public
|
|
|
|
procedure CreateSocket; override;
|
|
|
|
end;
|
|
|
|
|
|
|
|
//See 'winsock2.txt' file in distribute package!
|
|
|
|
TRAWBlockSocket = class(TBlockSocket)
|
|
|
|
public
|
|
|
|
procedure CreateSocket; override;
|
|
|
|
end;
|
|
|
|
|
|
|
|
TIPHeader = record
|
|
|
|
VerLen: Byte;
|
|
|
|
TOS: Byte;
|
|
|
|
TotalLen: Word;
|
|
|
|
Identifer: Word;
|
|
|
|
FragOffsets: Word;
|
|
|
|
TTL: Byte;
|
|
|
|
Protocol: Byte;
|
|
|
|
CheckSum: Word;
|
|
|
|
SourceIp: DWORD;
|
|
|
|
DestIp: DWORD;
|
|
|
|
Options: DWORD;
|
|
|
|
end;
|
2008-04-23 23:17:14 +03:00
|
|
|
|
|
|
|
implementation
|
|
|
|
|
2008-04-24 10:12:01 +03:00
|
|
|
type
|
|
|
|
TMulticast = record
|
|
|
|
MCastAddr : u_long;
|
|
|
|
MCastIfc : u_long;
|
|
|
|
end;
|
|
|
|
|
2008-04-23 23:17:14 +03:00
|
|
|
constructor TBlockSocket.Create;
|
2008-04-24 09:59:26 +03:00
|
|
|
var
|
2008-04-24 10:05:26 +03:00
|
|
|
e: ESynapseError;
|
|
|
|
begin
|
|
|
|
inherited Create;
|
|
|
|
FRaiseExcept := False;
|
|
|
|
FSocket := INVALID_SOCKET;
|
|
|
|
FProtocol := IPPROTO_IP;
|
|
|
|
FBuffer := '';
|
2008-04-24 10:12:01 +03:00
|
|
|
FNonBlockMode := False;
|
|
|
|
FMaxLineLength := 0;
|
|
|
|
FMaxBandwidth := 0;
|
|
|
|
FNextSend := 0;
|
2008-04-24 10:05:26 +03:00
|
|
|
if not InitSocketInterface('') then
|
|
|
|
begin
|
|
|
|
e := ESynapseError.Create('Error loading Winsock DLL!');
|
|
|
|
e.ErrorCode := 0;
|
|
|
|
e.ErrorMessage := 'Error loading Winsock DLL!';
|
|
|
|
raise e;
|
|
|
|
end;
|
2008-04-24 09:59:26 +03:00
|
|
|
SockCheck(synsock.WSAStartup($101, FWsaData));
|
|
|
|
ExceptCheck;
|
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
constructor TBlockSocket.CreateAlternate(Stub: string);
|
2008-04-24 09:59:26 +03:00
|
|
|
var
|
2008-04-24 10:05:26 +03:00
|
|
|
e: ESynapseError;
|
|
|
|
begin
|
|
|
|
inherited Create;
|
|
|
|
FRaiseExcept := False;
|
|
|
|
FSocket := INVALID_SOCKET;
|
|
|
|
FProtocol := IPPROTO_IP;
|
|
|
|
FBuffer := '';
|
|
|
|
if not InitSocketInterface(Stub) then
|
|
|
|
begin
|
|
|
|
e := ESynapseError.Create('Error loading alternate Winsock DLL (' + Stub + ')!');
|
|
|
|
e.ErrorCode := 0;
|
|
|
|
e.ErrorMessage := 'Error loading Winsock DLL (' + Stub + ')!';
|
|
|
|
raise e;
|
|
|
|
end;
|
2008-04-24 09:59:26 +03:00
|
|
|
SockCheck(synsock.WSAStartup($101, FWsaData));
|
2008-04-23 23:46:58 +03:00
|
|
|
ExceptCheck;
|
2008-04-23 23:17:14 +03:00
|
|
|
end;
|
|
|
|
|
|
|
|
destructor TBlockSocket.Destroy;
|
|
|
|
begin
|
|
|
|
CloseSocket;
|
2008-04-24 10:07:45 +03:00
|
|
|
synsock.WSACleanup;
|
2008-04-24 09:59:26 +03:00
|
|
|
DestroySocketInterface;
|
2008-04-24 10:05:26 +03:00
|
|
|
inherited Destroy;
|
2008-04-23 23:17:14 +03:00
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
procedure TBlockSocket.SetSin(var Sin: TSockAddrIn; IP, Port: string);
|
2008-04-23 23:17:14 +03:00
|
|
|
var
|
|
|
|
ProtoEnt: PProtoEnt;
|
|
|
|
ServEnt: PServEnt;
|
|
|
|
HostEnt: PHostEnt;
|
|
|
|
begin
|
2008-04-24 10:07:45 +03:00
|
|
|
DoStatus(HR_ResolvingBegin, IP + ':' + Port);
|
2008-04-24 10:05:26 +03:00
|
|
|
FillChar(Sin, Sizeof(Sin), 0);
|
|
|
|
Sin.sin_family := AF_INET;
|
|
|
|
ProtoEnt := synsock.GetProtoByNumber(FProtocol);
|
|
|
|
ServEnt := nil;
|
|
|
|
if ProtoEnt <> nil then
|
|
|
|
ServEnt := synsock.GetServByName(PChar(Port), ProtoEnt^.p_name);
|
2008-04-23 23:17:14 +03:00
|
|
|
if ServEnt = nil then
|
2008-04-24 10:05:26 +03:00
|
|
|
Sin.sin_port := synsock.htons(StrToIntDef(Port, 0))
|
2008-04-23 23:17:14 +03:00
|
|
|
else
|
2008-04-24 10:05:26 +03:00
|
|
|
Sin.sin_port := ServEnt^.s_port;
|
|
|
|
if IP = '255.255.255.255' then
|
|
|
|
Sin.sin_addr.s_addr := u_long(INADDR_BROADCAST)
|
|
|
|
else
|
|
|
|
begin
|
|
|
|
Sin.sin_addr.s_addr := synsock.inet_addr(PChar(IP));
|
|
|
|
if SIn.sin_addr.s_addr = u_long(INADDR_NONE) then
|
|
|
|
begin
|
|
|
|
HostEnt := synsock.GetHostByName(PChar(IP));
|
|
|
|
if HostEnt <> nil then
|
|
|
|
SIn.sin_addr.S_addr := Longint(PLongint(HostEnt^.h_addr_list^)^);
|
|
|
|
end;
|
|
|
|
end;
|
2008-04-24 10:07:45 +03:00
|
|
|
DoStatus(HR_ResolvingEnd, IP+':'+Port);
|
2008-04-23 23:17:14 +03:00
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
function TBlockSocket.GetSinIP(Sin: TSockAddrIn): string;
|
2008-04-23 23:17:14 +03:00
|
|
|
var
|
2008-04-24 10:05:26 +03:00
|
|
|
p: PChar;
|
2008-04-23 23:17:14 +03:00
|
|
|
begin
|
2008-04-24 10:05:26 +03:00
|
|
|
p := synsock.inet_ntoa(Sin.sin_addr);
|
|
|
|
if p = nil then
|
|
|
|
Result := ''
|
|
|
|
else
|
|
|
|
Result := p;
|
2008-04-23 23:17:14 +03:00
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
function TBlockSocket.GetSinPort(Sin: TSockAddrIn): Integer;
|
2008-04-23 23:17:14 +03:00
|
|
|
begin
|
2008-04-24 10:05:26 +03:00
|
|
|
Result := synsock.ntohs(Sin.sin_port);
|
2008-04-23 23:17:14 +03:00
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
procedure TBlockSocket.CreateSocket;
|
2008-04-23 23:17:14 +03:00
|
|
|
begin
|
2008-04-24 10:05:26 +03:00
|
|
|
FBuffer := '';
|
|
|
|
if FSocket = INVALID_SOCKET then
|
|
|
|
FLastError := synsock.WSAGetLastError
|
|
|
|
else
|
|
|
|
FLastError := 0;
|
2008-04-23 23:46:58 +03:00
|
|
|
ExceptCheck;
|
2008-04-24 10:07:45 +03:00
|
|
|
DoStatus(HR_SocketCreate, '');
|
2008-04-23 23:17:14 +03:00
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
procedure TBlockSocket.CloseSocket;
|
2008-04-23 23:17:14 +03:00
|
|
|
begin
|
2008-04-24 10:12:01 +03:00
|
|
|
synsock.Shutdown(FSocket, 2);
|
2008-04-24 09:59:26 +03:00
|
|
|
synsock.CloseSocket(FSocket);
|
2008-04-24 10:07:45 +03:00
|
|
|
DoStatus(HR_SocketClose, '');
|
2008-04-23 23:17:14 +03:00
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
procedure TBlockSocket.Bind(IP, Port: string);
|
2008-04-23 23:17:14 +03:00
|
|
|
var
|
2008-04-24 10:05:26 +03:00
|
|
|
Sin: TSockAddrIn;
|
|
|
|
Len: Integer;
|
|
|
|
begin
|
|
|
|
SetSin(Sin, IP, Port);
|
|
|
|
SockCheck(synsock.Bind(FSocket, Sin, SizeOf(Sin)));
|
|
|
|
Len := SizeOf(FLocalSin);
|
|
|
|
synsock.GetSockName(FSocket, FLocalSin, Len);
|
|
|
|
FBuffer := '';
|
2008-04-23 23:46:58 +03:00
|
|
|
ExceptCheck;
|
2008-04-24 10:07:45 +03:00
|
|
|
DoStatus(HR_Bind, IP + ':' + Port);
|
2008-04-23 23:17:14 +03:00
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
procedure TBlockSocket.Connect(IP, Port: string);
|
2008-04-23 23:17:14 +03:00
|
|
|
var
|
2008-04-24 10:05:26 +03:00
|
|
|
Sin: TSockAddrIn;
|
2008-04-23 23:17:14 +03:00
|
|
|
begin
|
2008-04-24 10:05:26 +03:00
|
|
|
SetSin(Sin, IP, Port);
|
|
|
|
SockCheck(synsock.Connect(FSocket, Sin, SizeOf(Sin)));
|
2008-04-23 23:17:14 +03:00
|
|
|
GetSins;
|
2008-04-24 10:05:26 +03:00
|
|
|
FBuffer := '';
|
2008-04-23 23:46:58 +03:00
|
|
|
ExceptCheck;
|
2008-04-24 10:07:45 +03:00
|
|
|
DoStatus(HR_Connect, IP + ':' + Port);
|
2008-04-23 23:17:14 +03:00
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TBlockSocket.GetSins;
|
|
|
|
var
|
2008-04-24 10:05:26 +03:00
|
|
|
Len: Integer;
|
2008-04-23 23:17:14 +03:00
|
|
|
begin
|
2008-04-24 10:05:26 +03:00
|
|
|
Len := SizeOf(FLocalSin);
|
|
|
|
synsock.GetSockName(FSocket, FLocalSin, Len);
|
|
|
|
Len := SizeOf(FRemoteSin);
|
|
|
|
synsock.GetPeerName(FSocket, FremoteSin, Len);
|
2008-04-23 23:17:14 +03:00
|
|
|
end;
|
|
|
|
|
2008-04-24 10:12:01 +03:00
|
|
|
procedure TBlockSocket.LimitBandwidth(Length: Integer);
|
|
|
|
var
|
|
|
|
x: Cardinal;
|
|
|
|
begin
|
|
|
|
if FMaxBandwidth > 0 then
|
|
|
|
begin
|
|
|
|
x := FNextSend - GetTick;
|
|
|
|
if x > 0 then
|
|
|
|
Sleep(x);
|
|
|
|
FNextSend := GetTick + Trunc((FMaxBandwidth / 1000) * Length);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
function TBlockSocket.SendBuffer(Buffer: Pointer; Length: Integer): Integer;
|
2008-04-23 23:17:14 +03:00
|
|
|
begin
|
2008-04-24 10:12:01 +03:00
|
|
|
LimitBandwidth(Length);
|
2008-04-24 10:05:26 +03:00
|
|
|
Result := synsock.Send(FSocket, Buffer^, Length, 0);
|
|
|
|
SockCheck(Result);
|
2008-04-23 23:46:58 +03:00
|
|
|
ExceptCheck;
|
2008-04-24 10:07:45 +03:00
|
|
|
DoStatus(HR_WriteCount, IntToStr(Result));
|
2008-04-23 23:17:14 +03:00
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
procedure TBlockSocket.SendByte(Data: Byte);
|
2008-04-23 23:17:14 +03:00
|
|
|
begin
|
2008-04-24 10:09:13 +03:00
|
|
|
SendBuffer(@Data, 1);
|
2008-04-23 23:17:14 +03:00
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
procedure TBlockSocket.SendString(const Data: string);
|
2008-04-23 23:17:14 +03:00
|
|
|
begin
|
2008-04-24 10:09:13 +03:00
|
|
|
SendBuffer(PChar(Data), Length(Data));
|
2008-04-23 23:17:14 +03:00
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
function TBlockSocket.RecvBuffer(Buffer: Pointer; Length: Integer): Integer;
|
2008-04-23 23:17:14 +03:00
|
|
|
begin
|
2008-04-24 10:05:26 +03:00
|
|
|
Result := synsock.Recv(FSocket, Buffer^, Length, 0);
|
|
|
|
if Result = 0 then
|
2008-04-24 10:09:13 +03:00
|
|
|
FLastError := WSAECONNRESET
|
2008-04-24 10:05:26 +03:00
|
|
|
else
|
|
|
|
SockCheck(Result);
|
2008-04-23 23:46:58 +03:00
|
|
|
ExceptCheck;
|
2008-04-24 10:07:45 +03:00
|
|
|
DoStatus(HR_ReadCount, IntToStr(Result));
|
2008-04-23 23:17:14 +03:00
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
function TBlockSocket.RecvBufferEx(Buffer: Pointer; Length: Integer;
|
|
|
|
Timeout: Integer): Integer;
|
2008-04-24 09:46:22 +03:00
|
|
|
var
|
2008-04-24 10:05:26 +03:00
|
|
|
s, ss, st: string;
|
|
|
|
x, l, lss: Integer;
|
|
|
|
fb, fs: Integer;
|
|
|
|
max: Integer;
|
|
|
|
begin
|
|
|
|
FLastError := 0;
|
|
|
|
x := System.Length(FBuffer);
|
|
|
|
if Length <= x then
|
|
|
|
begin
|
|
|
|
fb := Length;
|
|
|
|
fs := 0;
|
|
|
|
end
|
|
|
|
else
|
|
|
|
begin
|
|
|
|
fb := x;
|
|
|
|
fs := Length - x;
|
|
|
|
end;
|
|
|
|
ss := '';
|
|
|
|
if fb > 0 then
|
|
|
|
begin
|
|
|
|
s := Copy(FBuffer, 1, fb);
|
|
|
|
Delete(FBuffer, 1, fb);
|
|
|
|
end;
|
|
|
|
if fs > 0 then
|
|
|
|
begin
|
|
|
|
Max := GetSizeRecvBuffer;
|
|
|
|
ss := '';
|
|
|
|
while System.Length(ss) < fs do
|
|
|
|
begin
|
|
|
|
if CanRead(Timeout) then
|
2008-04-24 09:46:22 +03:00
|
|
|
begin
|
2008-04-24 10:05:26 +03:00
|
|
|
l := WaitingData;
|
|
|
|
if l > max then
|
|
|
|
l := max;
|
|
|
|
if (system.Length(ss) + l) > fs then
|
|
|
|
l := fs - system.Length(ss);
|
|
|
|
SetLength(st, l);
|
2008-04-24 10:12:01 +03:00
|
|
|
x := RecvBuffer(Pointer(st), l);
|
2008-04-24 10:05:26 +03:00
|
|
|
if FLastError <> 0 then
|
|
|
|
Break;
|
|
|
|
lss := system.Length(ss);
|
|
|
|
SetLength(ss, lss + x);
|
|
|
|
Move(Pointer(st)^, Pointer(@ss[lss + 1])^, x);
|
|
|
|
{It is 3x faster then ss:=ss+copy(st,1,x);}
|
|
|
|
Sleep(0);
|
2008-04-24 09:46:22 +03:00
|
|
|
end
|
2008-04-24 10:05:26 +03:00
|
|
|
else
|
|
|
|
FLastError := WSAETIMEDOUT;
|
|
|
|
if FLastError <> 0 then
|
|
|
|
Break;
|
2008-04-24 09:46:22 +03:00
|
|
|
end;
|
2008-04-24 10:05:26 +03:00
|
|
|
fs := system.Length(ss);
|
|
|
|
end;
|
|
|
|
Result := fb + fs;
|
|
|
|
s := s + ss;
|
|
|
|
Move(Pointer(s)^, Buffer^, Result);
|
2008-04-24 09:46:22 +03:00
|
|
|
ExceptCheck;
|
|
|
|
end;
|
|
|
|
|
2008-04-24 10:09:13 +03:00
|
|
|
function TBlockSocket.RecvPacket(Timeout: Integer): string;
|
|
|
|
var
|
|
|
|
x: integer;
|
|
|
|
s: string;
|
|
|
|
begin
|
|
|
|
Result := '';
|
|
|
|
FLastError := 0;
|
|
|
|
x := -1;
|
|
|
|
if FBuffer <> '' then
|
|
|
|
begin
|
|
|
|
Result := FBuffer;
|
|
|
|
FBuffer := '';
|
|
|
|
end
|
|
|
|
else
|
|
|
|
if CanRead(Timeout) then
|
|
|
|
begin
|
|
|
|
x := WaitingData;
|
|
|
|
if x > 0 then
|
|
|
|
begin
|
|
|
|
SetLength(s, x);
|
|
|
|
x := RecvBuffer(Pointer(s), x);
|
|
|
|
Result := Copy(s, 1, x);
|
|
|
|
end;
|
|
|
|
end
|
|
|
|
else
|
|
|
|
FLastError := WSAETIMEDOUT;
|
|
|
|
ExceptCheck;
|
|
|
|
if x = 0 then
|
|
|
|
FLastError := WSAECONNRESET;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
function TBlockSocket.RecvByte(Timeout: Integer): Byte;
|
2008-04-23 23:17:14 +03:00
|
|
|
var
|
2008-04-24 10:12:01 +03:00
|
|
|
s: String;
|
2008-04-24 10:05:26 +03:00
|
|
|
begin
|
|
|
|
Result := 0;
|
|
|
|
if CanRead(Timeout) then
|
|
|
|
begin
|
2008-04-24 10:12:01 +03:00
|
|
|
SetLength(s, 1);
|
|
|
|
RecvBuffer(Pointer(s), 1);
|
|
|
|
if s <> '' then
|
|
|
|
Result := Ord(s[1]);
|
2008-04-24 10:05:26 +03:00
|
|
|
end
|
|
|
|
else
|
|
|
|
FLastError := WSAETIMEDOUT;
|
2008-04-23 23:46:58 +03:00
|
|
|
ExceptCheck;
|
2008-04-23 23:17:14 +03:00
|
|
|
end;
|
|
|
|
|
2008-04-24 10:12:01 +03:00
|
|
|
function TBlockSocket.RecvTerminated(Timeout: Integer; const Terminator: string): string;
|
2008-04-23 23:17:14 +03:00
|
|
|
const
|
2008-04-24 10:12:01 +03:00
|
|
|
MaxSize = 1024;
|
2008-04-23 23:17:14 +03:00
|
|
|
var
|
2008-04-24 10:05:26 +03:00
|
|
|
x: Integer;
|
|
|
|
s: string;
|
|
|
|
c: Char;
|
2008-04-24 10:12:01 +03:00
|
|
|
r,l: Integer;
|
2008-04-24 10:05:26 +03:00
|
|
|
begin
|
|
|
|
s := '';
|
2008-04-24 10:12:01 +03:00
|
|
|
l := Length(Terminator);
|
|
|
|
Result := '';
|
|
|
|
if l = 0 then
|
|
|
|
Exit;
|
2008-04-24 10:05:26 +03:00
|
|
|
FLastError := 0;
|
2008-04-23 23:17:14 +03:00
|
|
|
repeat
|
2008-04-24 10:12:01 +03:00
|
|
|
x := 0;
|
2008-04-24 10:05:26 +03:00
|
|
|
if FBuffer = '' then
|
|
|
|
begin
|
|
|
|
x := WaitingData;
|
2008-04-24 10:12:01 +03:00
|
|
|
if x > MaxSize then
|
|
|
|
x := MaxSize;
|
|
|
|
if x <= 1 then
|
2008-04-23 23:17:14 +03:00
|
|
|
begin
|
2008-04-24 10:05:26 +03:00
|
|
|
c := Char(RecvByte(Timeout));
|
|
|
|
if FLastError <> 0 then
|
|
|
|
Break;
|
|
|
|
FBuffer := c;
|
|
|
|
end
|
|
|
|
else
|
|
|
|
begin
|
|
|
|
SetLength(FBuffer, x);
|
2008-04-24 10:12:01 +03:00
|
|
|
r := RecvBuffer(Pointer(FBuffer), x);
|
2008-04-24 10:05:26 +03:00
|
|
|
if FLastError <> 0 then
|
|
|
|
Break;
|
|
|
|
if r < x then
|
|
|
|
SetLength(FBuffer, r);
|
2008-04-23 23:17:14 +03:00
|
|
|
end;
|
2008-04-24 10:05:26 +03:00
|
|
|
end;
|
2008-04-24 10:12:01 +03:00
|
|
|
s := s + FBuffer;
|
|
|
|
FBuffer := '';
|
|
|
|
x := Pos(Terminator, s);
|
2008-04-24 10:05:26 +03:00
|
|
|
if x > 0 then
|
2008-04-24 10:12:01 +03:00
|
|
|
begin
|
|
|
|
FBuffer := Copy(s, x + l, Length(s) - x - l + 1);
|
2008-04-24 10:05:26 +03:00
|
|
|
s := Copy(s, 1, x - 1);
|
2008-04-24 10:12:01 +03:00
|
|
|
end;
|
|
|
|
if (FMaxLineLength <> 0) and (Length(s) > FMaxLineLength) then
|
|
|
|
begin
|
|
|
|
FLastError := WSAENOBUFS;
|
|
|
|
Break;
|
|
|
|
end;
|
|
|
|
until x > 0;
|
|
|
|
if FLastError = 0 then
|
|
|
|
Result := s
|
2008-04-24 10:05:26 +03:00
|
|
|
else
|
|
|
|
Result := '';
|
2008-04-23 23:46:58 +03:00
|
|
|
ExceptCheck;
|
2008-04-23 23:17:14 +03:00
|
|
|
end;
|
|
|
|
|
2008-04-24 10:12:01 +03:00
|
|
|
function TBlockSocket.RecvString(Timeout: Integer): string;
|
|
|
|
var
|
|
|
|
s: string;
|
|
|
|
begin
|
|
|
|
Result := '';
|
|
|
|
s := RecvTerminated(Timeout, #13 + #10);
|
|
|
|
if FLastError = 0 then
|
|
|
|
Result := s;
|
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
function TBlockSocket.PeekBuffer(Buffer: Pointer; Length: Integer): Integer;
|
2008-04-23 23:17:14 +03:00
|
|
|
begin
|
2008-04-24 10:05:26 +03:00
|
|
|
Result := synsock.Recv(FSocket, Buffer^, Length, MSG_PEEK);
|
|
|
|
SockCheck(Result);
|
2008-04-23 23:46:58 +03:00
|
|
|
ExceptCheck;
|
2008-04-23 23:17:14 +03:00
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
function TBlockSocket.PeekByte(Timeout: Integer): Byte;
|
2008-04-23 23:17:14 +03:00
|
|
|
var
|
2008-04-24 10:12:01 +03:00
|
|
|
s: string;
|
2008-04-24 10:05:26 +03:00
|
|
|
begin
|
|
|
|
Result := 0;
|
|
|
|
if CanRead(Timeout) then
|
|
|
|
begin
|
2008-04-24 10:12:01 +03:00
|
|
|
SetLength(s, 1);
|
|
|
|
PeekBuffer(Pointer(s), 1);
|
|
|
|
if s <> '' then
|
|
|
|
Result := Ord(s[1]);
|
2008-04-24 10:05:26 +03:00
|
|
|
end
|
|
|
|
else
|
|
|
|
FLastError := WSAETIMEDOUT;
|
2008-04-23 23:46:58 +03:00
|
|
|
ExceptCheck;
|
2008-04-23 23:17:14 +03:00
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
function TBlockSocket.SockCheck(SockResult: Integer): Integer;
|
2008-04-23 23:17:14 +03:00
|
|
|
begin
|
2008-04-24 10:05:26 +03:00
|
|
|
if SockResult = SOCKET_ERROR then
|
|
|
|
Result := synsock.WSAGetLastError
|
|
|
|
else
|
|
|
|
Result := 0;
|
|
|
|
FLastError := Result;
|
2008-04-23 23:17:14 +03:00
|
|
|
end;
|
|
|
|
|
2008-04-23 23:46:58 +03:00
|
|
|
procedure TBlockSocket.ExceptCheck;
|
|
|
|
var
|
2008-04-24 10:05:26 +03:00
|
|
|
e: ESynapseError;
|
|
|
|
s: string;
|
|
|
|
begin
|
2008-04-24 10:12:01 +03:00
|
|
|
if FRaiseExcept and (LastError <> 0) and (LastError <> WSAEINPROGRESS)
|
|
|
|
and (LastError <> WSAEWOULDBLOCK) then
|
2008-04-24 10:05:26 +03:00
|
|
|
begin
|
|
|
|
s := GetErrorDesc(LastError);
|
|
|
|
e := ESynapseError.CreateFmt('TCP/IP Socket error %d: %s', [LastError, s]);
|
|
|
|
e.ErrorCode := LastError;
|
|
|
|
e.ErrorMessage := s;
|
|
|
|
raise e;
|
|
|
|
end;
|
2008-04-23 23:46:58 +03:00
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
function TBlockSocket.WaitingData: Integer;
|
2008-04-23 23:17:14 +03:00
|
|
|
var
|
2008-04-24 10:05:26 +03:00
|
|
|
x: Integer;
|
2008-04-23 23:17:14 +03:00
|
|
|
begin
|
2008-04-24 10:05:26 +03:00
|
|
|
synsock.IoctlSocket(FSocket, FIONREAD, u_long(x));
|
|
|
|
Result := x;
|
2008-04-23 23:17:14 +03:00
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
procedure TBlockSocket.SetLinger(Enable: Boolean; Linger: Integer);
|
2008-04-23 23:17:14 +03:00
|
|
|
var
|
2008-04-24 10:05:26 +03:00
|
|
|
li: TLinger;
|
2008-04-23 23:17:14 +03:00
|
|
|
begin
|
2008-04-24 10:05:26 +03:00
|
|
|
li.l_onoff := Ord(Enable);
|
2008-04-23 23:46:58 +03:00
|
|
|
li.l_linger := Linger div 1000;
|
2008-04-24 09:59:26 +03:00
|
|
|
SockCheck(synsock.SetSockOpt(FSocket, SOL_SOCKET, SO_LINGER, @li, SizeOf(li)));
|
2008-04-23 23:46:58 +03:00
|
|
|
ExceptCheck;
|
2008-04-23 23:17:14 +03:00
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
function TBlockSocket.LocalName: string;
|
2008-04-23 23:17:14 +03:00
|
|
|
var
|
2008-04-24 10:05:26 +03:00
|
|
|
buf: array[0..255] of Char;
|
|
|
|
BufPtr: PChar;
|
|
|
|
RemoteHost: PHostEnt;
|
|
|
|
begin
|
|
|
|
BufPtr := buf;
|
|
|
|
Result := '';
|
|
|
|
synsock.GetHostName(BufPtr, SizeOf(buf));
|
|
|
|
if BufPtr[0] <> #0 then
|
|
|
|
begin
|
|
|
|
// try get Fully Qualified Domain Name
|
|
|
|
RemoteHost := synsock.GetHostByName(BufPtr);
|
|
|
|
if RemoteHost <> nil then
|
|
|
|
Result := PChar(RemoteHost^.h_name);
|
|
|
|
end;
|
|
|
|
if Result = '' then
|
|
|
|
Result := '127.0.0.1';
|
2008-04-23 23:17:14 +03:00
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
procedure TBlockSocket.ResolveNameToIP(Name: string; IPList: TStrings);
|
2008-04-24 09:59:26 +03:00
|
|
|
type
|
2008-04-24 10:05:26 +03:00
|
|
|
TaPInAddr = array[0..250] of PInAddr;
|
2008-04-24 09:59:26 +03:00
|
|
|
PaPInAddr = ^TaPInAddr;
|
|
|
|
var
|
2008-04-24 10:05:26 +03:00
|
|
|
RemoteHost: PHostEnt;
|
|
|
|
IP: u_long;
|
|
|
|
PAdrPtr: PaPInAddr;
|
|
|
|
i: Integer;
|
|
|
|
s: string;
|
|
|
|
InAddr: TInAddr;
|
2008-04-24 09:59:26 +03:00
|
|
|
begin
|
|
|
|
IPList.Clear;
|
2008-04-24 10:05:26 +03:00
|
|
|
IP := synsock.inet_addr(PChar(Name));
|
|
|
|
if IP = u_long(INADDR_NONE) then
|
|
|
|
begin
|
|
|
|
RemoteHost := synsock.GetHostByName(PChar(Name));
|
|
|
|
if RemoteHost <> nil then
|
|
|
|
begin
|
|
|
|
PAdrPtr := PAPInAddr(RemoteHost^.h_addr_list);
|
|
|
|
i := 0;
|
|
|
|
while PAdrPtr^[i] <> nil do
|
2008-04-24 09:59:26 +03:00
|
|
|
begin
|
2008-04-24 10:05:26 +03:00
|
|
|
InAddr := PAdrPtr^[i]^;
|
|
|
|
with InAddr.S_un_b do
|
|
|
|
s := Format('%d.%d.%d.%d',
|
|
|
|
[Ord(s_b1), Ord(s_b2), Ord(s_b3), Ord(s_b4)]);
|
|
|
|
IPList.Add(s);
|
|
|
|
Inc(i);
|
|
|
|
end;
|
|
|
|
end;
|
2008-04-24 10:09:13 +03:00
|
|
|
if IPList.Count = 0 then
|
|
|
|
IPList.Add('0.0.0.0');
|
2008-04-24 10:05:26 +03:00
|
|
|
end
|
|
|
|
else
|
|
|
|
IPList.Add(Name);
|
2008-04-24 09:59:26 +03:00
|
|
|
end;
|
2008-04-23 23:17:14 +03:00
|
|
|
|
2008-04-24 10:09:13 +03:00
|
|
|
function TBlockSocket.ResolveName(Name: string): string;
|
|
|
|
var
|
|
|
|
l: TStringList;
|
|
|
|
begin
|
|
|
|
l := TStringList.Create;
|
|
|
|
try
|
|
|
|
ResolveNameToIP(Name, l);
|
|
|
|
Result := l[0];
|
|
|
|
finally
|
|
|
|
l.Free;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TBlockSocket.ResolvePort(Port: string): Word;
|
|
|
|
var
|
|
|
|
ProtoEnt: PProtoEnt;
|
|
|
|
ServEnt: PServEnt;
|
|
|
|
begin
|
|
|
|
ProtoEnt := synsock.GetProtoByNumber(FProtocol);
|
|
|
|
ServEnt := nil;
|
|
|
|
if ProtoEnt <> nil then
|
|
|
|
ServEnt := synsock.GetServByName(PChar(Port), ProtoEnt^.p_name);
|
|
|
|
if ServEnt = nil then
|
|
|
|
Result := synsock.htons(StrToIntDef(Port, 0))
|
|
|
|
else
|
|
|
|
Result := ServEnt^.s_port;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TBlockSocket.SetRemoteSin(IP, Port: string);
|
|
|
|
begin
|
|
|
|
SetSin(FRemoteSin, IP, Port);
|
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
function TBlockSocket.GetLocalSinIP: string;
|
2008-04-23 23:17:14 +03:00
|
|
|
begin
|
2008-04-24 10:05:26 +03:00
|
|
|
Result := GetSinIP(FLocalSin);
|
2008-04-23 23:17:14 +03:00
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
function TBlockSocket.GetRemoteSinIP: string;
|
2008-04-23 23:17:14 +03:00
|
|
|
begin
|
2008-04-24 10:05:26 +03:00
|
|
|
Result := GetSinIP(FRemoteSin);
|
2008-04-23 23:17:14 +03:00
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
function TBlockSocket.GetLocalSinPort: Integer;
|
2008-04-23 23:17:14 +03:00
|
|
|
begin
|
2008-04-24 10:05:26 +03:00
|
|
|
Result := GetSinPort(FLocalSin);
|
2008-04-23 23:17:14 +03:00
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
function TBlockSocket.GetRemoteSinPort: Integer;
|
2008-04-23 23:17:14 +03:00
|
|
|
begin
|
2008-04-24 10:05:26 +03:00
|
|
|
Result := GetSinPort(FRemoteSin);
|
2008-04-23 23:17:14 +03:00
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
function TBlockSocket.CanRead(Timeout: Integer): Boolean;
|
2008-04-23 23:17:14 +03:00
|
|
|
var
|
2008-04-24 10:05:26 +03:00
|
|
|
FDSet: TFDSet;
|
|
|
|
TimeVal: PTimeVal;
|
|
|
|
TimeV: TTimeVal;
|
|
|
|
x: Integer;
|
|
|
|
begin
|
|
|
|
TimeV.tv_usec := (Timeout mod 1000) * 1000;
|
|
|
|
TimeV.tv_sec := Timeout div 1000;
|
|
|
|
TimeVal := @TimeV;
|
|
|
|
if Timeout = -1 then
|
|
|
|
TimeVal := nil;
|
|
|
|
FD_ZERO(FDSet);
|
|
|
|
FD_SET(FSocket, FDSet);
|
|
|
|
x := synsock.Select(FSocket + 1, @FDSet, nil, nil, TimeVal);
|
2008-04-23 23:17:14 +03:00
|
|
|
SockCheck(x);
|
2008-04-24 10:05:26 +03:00
|
|
|
if FLastError <> 0 then
|
|
|
|
x := 0;
|
|
|
|
Result := x > 0;
|
2008-04-23 23:46:58 +03:00
|
|
|
ExceptCheck;
|
2008-04-24 10:07:45 +03:00
|
|
|
if Result then
|
|
|
|
DoStatus(HR_CanRead, '');
|
2008-04-23 23:17:14 +03:00
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
function TBlockSocket.CanWrite(Timeout: Integer): Boolean;
|
2008-04-23 23:17:14 +03:00
|
|
|
var
|
2008-04-24 10:05:26 +03:00
|
|
|
FDSet: TFDSet;
|
|
|
|
TimeVal: PTimeVal;
|
|
|
|
TimeV: TTimeVal;
|
|
|
|
x: Integer;
|
|
|
|
begin
|
|
|
|
TimeV.tv_usec := (Timeout mod 1000) * 1000;
|
|
|
|
TimeV.tv_sec := Timeout div 1000;
|
|
|
|
TimeVal := @TimeV;
|
|
|
|
if Timeout = -1 then
|
|
|
|
TimeVal := nil;
|
|
|
|
FD_ZERO(FDSet);
|
|
|
|
FD_SET(FSocket, FDSet);
|
|
|
|
x := synsock.Select(FSocket + 1, nil, @FDSet, nil, TimeVal);
|
2008-04-23 23:17:14 +03:00
|
|
|
SockCheck(x);
|
2008-04-24 10:05:26 +03:00
|
|
|
if FLastError <> 0 then
|
|
|
|
x := 0;
|
|
|
|
Result := x > 0;
|
2008-04-23 23:46:58 +03:00
|
|
|
ExceptCheck;
|
2008-04-24 10:07:45 +03:00
|
|
|
if Result then
|
|
|
|
DoStatus(HR_CanWrite, '');
|
2008-04-23 23:17:14 +03:00
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
function TBlockSocket.SendBufferTo(Buffer: Pointer; Length: Integer): Integer;
|
2008-04-23 23:17:14 +03:00
|
|
|
var
|
2008-04-24 10:05:26 +03:00
|
|
|
Len: Integer;
|
2008-04-23 23:17:14 +03:00
|
|
|
begin
|
2008-04-24 10:12:01 +03:00
|
|
|
LimitBandwidth(Length);
|
2008-04-24 10:05:26 +03:00
|
|
|
Len := SizeOf(FRemoteSin);
|
|
|
|
Result := synsock.SendTo(FSocket, Buffer^, Length, 0, FRemoteSin, Len);
|
|
|
|
SockCheck(Result);
|
2008-04-23 23:46:58 +03:00
|
|
|
ExceptCheck;
|
2008-04-24 10:12:01 +03:00
|
|
|
DoStatus(HR_WriteCount, IntToStr(Result));
|
2008-04-23 23:17:14 +03:00
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
function TBlockSocket.RecvBufferFrom(Buffer: Pointer; Length: Integer): Integer;
|
2008-04-23 23:17:14 +03:00
|
|
|
var
|
2008-04-24 10:05:26 +03:00
|
|
|
Len: Integer;
|
2008-04-23 23:17:14 +03:00
|
|
|
begin
|
2008-04-24 10:05:26 +03:00
|
|
|
Len := SizeOf(FRemoteSin);
|
|
|
|
Result := synsock.RecvFrom(FSocket, Buffer^, Length, 0, FRemoteSin, Len);
|
|
|
|
SockCheck(Result);
|
2008-04-23 23:46:58 +03:00
|
|
|
ExceptCheck;
|
2008-04-24 10:12:01 +03:00
|
|
|
DoStatus(HR_ReadCount, IntToStr(Result));
|
2008-04-23 23:17:14 +03:00
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
function TBlockSocket.GetSizeRecvBuffer: Integer;
|
2008-04-24 09:46:22 +03:00
|
|
|
var
|
2008-04-24 10:05:26 +03:00
|
|
|
l: Integer;
|
2008-04-24 09:46:22 +03:00
|
|
|
begin
|
2008-04-24 10:05:26 +03:00
|
|
|
l := SizeOf(Result);
|
|
|
|
SockCheck(synsock.GetSockOpt(FSocket, SOL_SOCKET, SO_RCVBUF, @Result, l));
|
|
|
|
if FLastError <> 0 then
|
|
|
|
Result := 1024;
|
2008-04-24 09:46:22 +03:00
|
|
|
ExceptCheck;
|
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
procedure TBlockSocket.SetSizeRecvBuffer(Size: Integer);
|
2008-04-24 09:46:22 +03:00
|
|
|
begin
|
2008-04-24 10:05:26 +03:00
|
|
|
SockCheck(synsock.SetSockOpt(FSocket, SOL_SOCKET, SO_RCVBUF, @Size, SizeOf(Size)));
|
2008-04-24 09:46:22 +03:00
|
|
|
ExceptCheck;
|
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
function TBlockSocket.GetSizeSendBuffer: Integer;
|
2008-04-24 09:46:22 +03:00
|
|
|
var
|
2008-04-24 10:05:26 +03:00
|
|
|
l: Integer;
|
2008-04-24 09:46:22 +03:00
|
|
|
begin
|
2008-04-24 10:05:26 +03:00
|
|
|
l := SizeOf(Result);
|
|
|
|
SockCheck(synsock.GetSockOpt(FSocket, SOL_SOCKET, SO_SNDBUF, @Result, l));
|
|
|
|
if FLastError <> 0 then
|
|
|
|
Result := 1024;
|
2008-04-24 09:46:22 +03:00
|
|
|
ExceptCheck;
|
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
procedure TBlockSocket.SetSizeSendBuffer(Size: Integer);
|
2008-04-24 09:46:22 +03:00
|
|
|
begin
|
2008-04-24 10:05:26 +03:00
|
|
|
SockCheck(synsock.SetSockOpt(FSocket, SOL_SOCKET, SO_SNDBUF, @Size, SizeOf(Size)));
|
2008-04-24 09:46:22 +03:00
|
|
|
ExceptCheck;
|
|
|
|
end;
|
2008-04-23 23:17:14 +03:00
|
|
|
|
2008-04-24 10:12:01 +03:00
|
|
|
procedure TBlockSocket.SetNonBlockMode(Value: Boolean);
|
|
|
|
var
|
|
|
|
x: integer;
|
|
|
|
begin
|
|
|
|
FNonBlockMode := Value;
|
|
|
|
if Value then
|
|
|
|
x := 1
|
|
|
|
else
|
|
|
|
x := 0;
|
|
|
|
synsock.IoctlSocket(FSocket, FIONBIO, u_long(x));
|
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
//See 'winsock2.txt' file in distribute package!
|
|
|
|
function TBlockSocket.SetTimeout(Timeout: Integer): Boolean;
|
|
|
|
begin
|
2008-04-24 10:09:13 +03:00
|
|
|
Result := SetSendTimeout(Timeout) and SetRecvTimeout(Timeout);
|
|
|
|
end;
|
|
|
|
|
|
|
|
//See 'winsock2.txt' file in distribute package!
|
|
|
|
function TBlockSocket.SetSendTimeout(Timeout: Integer): Boolean;
|
|
|
|
begin
|
|
|
|
Result := synsock.SetSockOpt(FSocket, SOL_SOCKET, SO_SNDTIMEO,
|
|
|
|
@Timeout, SizeOf(Timeout)) <> SOCKET_ERROR;
|
|
|
|
end;
|
|
|
|
|
|
|
|
//See 'winsock2.txt' file in distribute package!
|
|
|
|
function TBlockSocket.SetRecvTimeout(Timeout: Integer): Boolean;
|
|
|
|
begin
|
|
|
|
Result := synsock.SetSockOpt(FSocket, SOL_SOCKET, SO_RCVTIMEO,
|
|
|
|
@Timeout, SizeOf(Timeout)) <> SOCKET_ERROR;
|
2008-04-24 10:05:26 +03:00
|
|
|
end;
|
|
|
|
|
|
|
|
function TBlockSocket.GroupCanRead(const SocketList: TList; Timeout: Integer;
|
|
|
|
const CanReadList: TList): boolean;
|
|
|
|
var
|
|
|
|
FDSet: TFDSet;
|
|
|
|
TimeVal: PTimeVal;
|
|
|
|
TimeV: TTimeVal;
|
|
|
|
x, n: Integer;
|
|
|
|
Max: Integer;
|
|
|
|
begin
|
|
|
|
TimeV.tv_usec := (Timeout mod 1000) * 1000;
|
|
|
|
TimeV.tv_sec := Timeout div 1000;
|
|
|
|
TimeVal := @TimeV;
|
|
|
|
if Timeout = -1 then
|
|
|
|
TimeVal := nil;
|
|
|
|
FD_ZERO(FDSet);
|
|
|
|
Max := 0;
|
|
|
|
for n := 0 to SocketList.Count - 1 do
|
|
|
|
if TObject(SocketList.Items[n]) is TBlockSocket then
|
|
|
|
begin
|
|
|
|
if TBlockSocket(SocketList.Items[n]).Socket > Max then
|
|
|
|
Max := TBlockSocket(SocketList.Items[n]).Socket;
|
|
|
|
FD_SET(TBlockSocket(SocketList.Items[n]).Socket, FDSet);
|
|
|
|
end;
|
|
|
|
x := synsock.Select(Max + 1, @FDSet, nil, nil, TimeVal);
|
|
|
|
SockCheck(x);
|
|
|
|
ExceptCheck;
|
|
|
|
if FLastError <> 0 then
|
|
|
|
x := 0;
|
|
|
|
Result := x > 0;
|
|
|
|
CanReadList.Clear;
|
|
|
|
if Result then
|
|
|
|
for n := 0 to SocketList.Count - 1 do
|
|
|
|
if TObject(SocketList.Items[n]) is TBlockSocket then
|
|
|
|
if FD_ISSET(TBlockSocket(SocketList.Items[n]).Socket, FDSet) then
|
|
|
|
CanReadList.Add(TBlockSocket(SocketList.Items[n]));
|
|
|
|
end;
|
|
|
|
|
2008-04-24 10:12:01 +03:00
|
|
|
function TBlockSocket.EnableReuse(Value: Boolean): Boolean;
|
|
|
|
var
|
|
|
|
Opt: Integer;
|
|
|
|
Res: Integer;
|
|
|
|
begin
|
|
|
|
opt := Ord(Value);
|
|
|
|
Res := synsock.SetSockOpt(FSocket, SOL_SOCKET, SO_REUSEADDR, @Opt, SizeOf(opt));
|
|
|
|
SockCheck(Res);
|
|
|
|
Result := res = 0;
|
|
|
|
ExceptCheck;
|
|
|
|
end;
|
|
|
|
|
2008-04-24 10:07:45 +03:00
|
|
|
procedure TBlockSocket.DoStatus(Reason: THookSocketReason; const Value: string);
|
|
|
|
begin
|
|
|
|
if assigned(OnStatus) then
|
|
|
|
OnStatus(Self, Reason, Value);
|
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
class function TBlockSocket.GetErrorDesc(ErrorCode: Integer): string;
|
|
|
|
begin
|
|
|
|
case ErrorCode of
|
|
|
|
0:
|
|
|
|
Result := 'OK';
|
|
|
|
WSAEINTR: {10004}
|
|
|
|
Result := 'Interrupted system call';
|
|
|
|
WSAEBADF: {10009}
|
|
|
|
Result := 'Bad file number';
|
|
|
|
WSAEACCES: {10013}
|
|
|
|
Result := 'Permission denied';
|
|
|
|
WSAEFAULT: {10014}
|
|
|
|
Result := 'Bad address';
|
|
|
|
WSAEINVAL: {10022}
|
|
|
|
Result := 'Invalid argument';
|
|
|
|
WSAEMFILE: {10024}
|
|
|
|
Result := 'Too many open files';
|
|
|
|
WSAEWOULDBLOCK: {10035}
|
|
|
|
Result := 'Operation would block';
|
|
|
|
WSAEINPROGRESS: {10036}
|
|
|
|
Result := 'Operation now in progress';
|
|
|
|
WSAEALREADY: {10037}
|
|
|
|
Result := 'Operation already in progress';
|
|
|
|
WSAENOTSOCK: {10038}
|
|
|
|
Result := 'Socket operation on nonsocket';
|
|
|
|
WSAEDESTADDRREQ: {10039}
|
|
|
|
Result := 'Destination address required';
|
|
|
|
WSAEMSGSIZE: {10040}
|
|
|
|
Result := 'Message too long';
|
|
|
|
WSAEPROTOTYPE: {10041}
|
|
|
|
Result := 'Protocol wrong type for Socket';
|
|
|
|
WSAENOPROTOOPT: {10042}
|
|
|
|
Result := 'Protocol not available';
|
|
|
|
WSAEPROTONOSUPPORT: {10043}
|
|
|
|
Result := 'Protocol not supported';
|
|
|
|
WSAESOCKTNOSUPPORT: {10044}
|
|
|
|
Result := 'Socket not supported';
|
|
|
|
WSAEOPNOTSUPP: {10045}
|
|
|
|
Result := 'Operation not supported on Socket';
|
|
|
|
WSAEPFNOSUPPORT: {10046}
|
|
|
|
Result := 'Protocol family not supported';
|
|
|
|
WSAEAFNOSUPPORT: {10047}
|
|
|
|
Result := 'Address family not supported';
|
|
|
|
WSAEADDRINUSE: {10048}
|
|
|
|
Result := 'Address already in use';
|
|
|
|
WSAEADDRNOTAVAIL: {10049}
|
|
|
|
Result := 'Can''t assign requested address';
|
|
|
|
WSAENETDOWN: {10050}
|
|
|
|
Result := 'Network is down';
|
|
|
|
WSAENETUNREACH: {10051}
|
|
|
|
Result := 'Network is unreachable';
|
|
|
|
WSAENETRESET: {10052}
|
|
|
|
Result := 'Network dropped connection on reset';
|
|
|
|
WSAECONNABORTED: {10053}
|
|
|
|
Result := 'Software caused connection abort';
|
|
|
|
WSAECONNRESET: {10054}
|
|
|
|
Result := 'Connection reset by peer';
|
|
|
|
WSAENOBUFS: {10055}
|
|
|
|
Result := 'No Buffer space available';
|
|
|
|
WSAEISCONN: {10056}
|
|
|
|
Result := 'Socket is already connected';
|
|
|
|
WSAENOTCONN: {10057}
|
|
|
|
Result := 'Socket is not connected';
|
|
|
|
WSAESHUTDOWN: {10058}
|
|
|
|
Result := 'Can''t send after Socket shutdown';
|
|
|
|
WSAETOOMANYREFS: {10059}
|
|
|
|
Result := 'Too many references:can''t splice';
|
|
|
|
WSAETIMEDOUT: {10060}
|
|
|
|
Result := 'Connection timed out';
|
|
|
|
WSAECONNREFUSED: {10061}
|
|
|
|
Result := 'Connection refused';
|
|
|
|
WSAELOOP: {10062}
|
|
|
|
Result := 'Too many levels of symbolic links';
|
|
|
|
WSAENAMETOOLONG: {10063}
|
|
|
|
Result := 'File name is too long';
|
|
|
|
WSAEHOSTDOWN: {10064}
|
|
|
|
Result := 'Host is down';
|
|
|
|
WSAEHOSTUNREACH: {10065}
|
|
|
|
Result := 'No route to host';
|
|
|
|
WSAENOTEMPTY: {10066}
|
|
|
|
Result := 'Directory is not empty';
|
|
|
|
WSAEPROCLIM: {10067}
|
|
|
|
Result := 'Too many processes';
|
|
|
|
WSAEUSERS: {10068}
|
|
|
|
Result := 'Too many users';
|
|
|
|
WSAEDQUOT: {10069}
|
|
|
|
Result := 'Disk quota exceeded';
|
|
|
|
WSAESTALE: {10070}
|
|
|
|
Result := 'Stale NFS file handle';
|
|
|
|
WSAEREMOTE: {10071}
|
|
|
|
Result := 'Too many levels of remote in path';
|
|
|
|
WSASYSNOTREADY: {10091}
|
|
|
|
Result := 'Network subsystem is unusable';
|
|
|
|
WSAVERNOTSUPPORTED: {10092}
|
|
|
|
Result := 'Winsock DLL cannot support this application';
|
|
|
|
WSANOTINITIALISED: {10093}
|
|
|
|
Result := 'Winsock not initialized';
|
|
|
|
WSAEDISCON: {10101}
|
2008-04-24 10:12:01 +03:00
|
|
|
Result := 'Disconnect';
|
2008-04-24 10:05:26 +03:00
|
|
|
WSAHOST_NOT_FOUND: {11001}
|
|
|
|
Result := 'Host not found';
|
|
|
|
WSATRY_AGAIN: {11002}
|
|
|
|
Result := 'Non authoritative - host not found';
|
|
|
|
WSANO_RECOVERY: {11003}
|
|
|
|
Result := 'Non recoverable error';
|
|
|
|
WSANO_DATA: {11004}
|
|
|
|
Result := 'Valid name, no data record of requested type'
|
|
|
|
else
|
|
|
|
Result := 'Not a Winsock error (' + IntToStr(ErrorCode) + ')';
|
|
|
|
end;
|
|
|
|
end;
|
2008-04-23 23:34:31 +03:00
|
|
|
|
|
|
|
{======================================================================}
|
|
|
|
|
2008-04-24 10:09:13 +03:00
|
|
|
constructor TSocksBlockSocket.Create;
|
|
|
|
begin
|
|
|
|
inherited Create;
|
|
|
|
FSocksIP:= '';
|
|
|
|
FSocksPort:= '1080';
|
|
|
|
FSocksTimeout:= 300000;
|
|
|
|
FSocksUsername:= '';
|
|
|
|
FSocksPassword:= '';
|
|
|
|
FUsingSocks := False;
|
|
|
|
FSocksResolver := True;
|
|
|
|
FSocksLastError := 0;
|
|
|
|
FSocksResponseIP := '';
|
|
|
|
FSocksResponsePort := '';
|
|
|
|
FSocksLocalIP := '';
|
|
|
|
FSocksLocalPort := '';
|
|
|
|
FSocksRemoteIP := '';
|
|
|
|
FSocksRemotePort := '';
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TSocksBlockSocket.SocksOpen: boolean;
|
|
|
|
var
|
|
|
|
Buf: string;
|
|
|
|
n: integer;
|
|
|
|
begin
|
|
|
|
Result := False;
|
|
|
|
FUsingSocks := False;
|
|
|
|
if FSocksUsername = '' then
|
|
|
|
Buf := #5 + #1 + #0
|
|
|
|
else
|
|
|
|
Buf := #5 + #2 + #2 +#0;
|
|
|
|
SendString(Buf);
|
|
|
|
Buf := RecvPacket(FSocksTimeout);
|
|
|
|
FBuffer := Copy(Buf, 3, Length(buf) - 2);
|
|
|
|
if Length(Buf) < 2 then
|
|
|
|
Exit;
|
|
|
|
if Buf[1] <> #5 then
|
|
|
|
Exit;
|
|
|
|
n := Ord(Buf[2]);
|
|
|
|
case n of
|
|
|
|
0: //not need authorisation
|
|
|
|
;
|
|
|
|
2:
|
|
|
|
begin
|
|
|
|
Buf := #1 + char(Length(FSocksUsername)) + FSocksUsername
|
|
|
|
+ char(Length(FSocksPassword)) + FSocksPassword;
|
|
|
|
SendString(Buf);
|
|
|
|
Buf := RecvPacket(FSocksTimeout);
|
|
|
|
FBuffer := Copy(Buf, 3, Length(buf) - 2);
|
|
|
|
if Length(Buf) < 2 then
|
|
|
|
Exit;
|
|
|
|
if Buf[2] <> #0 then
|
|
|
|
Exit;
|
|
|
|
end;
|
|
|
|
else
|
|
|
|
Exit;
|
|
|
|
end;
|
|
|
|
FUsingSocks := True;
|
|
|
|
Result := True;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TSocksBlockSocket.SocksRequest(Cmd: Byte;
|
|
|
|
const IP, Port: string): Boolean;
|
|
|
|
var
|
|
|
|
Buf: string;
|
|
|
|
begin
|
|
|
|
Result := False;
|
|
|
|
Buf := #5 + char(Cmd) + #0 + SocksCode(IP, Port);
|
|
|
|
SendString(Buf);
|
|
|
|
Result := FLastError = 0;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TSocksBlockSocket.SocksResponse: Boolean;
|
|
|
|
var
|
|
|
|
Buf: string;
|
|
|
|
x: integer;
|
|
|
|
begin
|
|
|
|
Result := False;
|
|
|
|
FSocksResponseIP := '';
|
|
|
|
FSocksResponsePort := '';
|
|
|
|
Buf := RecvPacket(FSocksTimeout);
|
|
|
|
if FLastError <> 0 then
|
|
|
|
Exit;
|
|
|
|
if Length(Buf) < 5 then
|
|
|
|
Exit;
|
|
|
|
if Buf[1] <> #5 then
|
|
|
|
Exit;
|
|
|
|
FSocksLastError := Ord(Buf[2]);
|
|
|
|
if FSocksLastError <> 0 then
|
|
|
|
Exit;
|
|
|
|
x := SocksDecode(Buf);
|
|
|
|
FBuffer := Copy(Buf, x, Length(buf) - x + 1);
|
|
|
|
Result := True;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TSocksBlockSocket.SocksCode(IP, Port: string): string;
|
|
|
|
begin
|
|
|
|
if IsIP(IP) then
|
|
|
|
Result := #1 + IPToID(IP)
|
|
|
|
else
|
|
|
|
if FSocksResolver then
|
|
|
|
Result := #3 + char(Length(IP)) + IP
|
|
|
|
else
|
|
|
|
Result := #1 + IPToID(ResolveName(IP));
|
|
|
|
Result := Result + CodeInt(synsock.htons(ResolvePort(Port)));
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TSocksBlockSocket.SocksDecode(Value: string): integer;
|
|
|
|
var
|
|
|
|
Atyp: Byte;
|
|
|
|
y, n: integer;
|
|
|
|
w: Word;
|
|
|
|
begin
|
|
|
|
FSocksResponsePort := '0';
|
|
|
|
Atyp := Ord(Value[4]);
|
|
|
|
Result := 5;
|
|
|
|
case Atyp of
|
|
|
|
1:
|
|
|
|
begin
|
|
|
|
if Length(Value) < 10 then
|
|
|
|
Exit;
|
|
|
|
FSocksResponseIP := Format('%d.%d.%d.%d',
|
|
|
|
[Ord(Value[5]), Ord(Value[6]), Ord(Value[7]), Ord(Value[8])]);
|
|
|
|
Result := 9;
|
|
|
|
end;
|
|
|
|
3:
|
|
|
|
begin
|
|
|
|
y := Ord(Value[5]);
|
|
|
|
if Length(Value) < (5 + y + 2) then
|
|
|
|
Exit;
|
|
|
|
for n := 6 to 6 + y do
|
|
|
|
FSocksResponseIP := FSocksResponseIP + Value[n];
|
|
|
|
Result := 5 + y +1;
|
|
|
|
end;
|
|
|
|
else
|
|
|
|
Exit;
|
|
|
|
end;
|
|
|
|
w := DecodeInt(Value, Result);
|
|
|
|
FSocksResponsePort := IntToStr(w);
|
|
|
|
Result := Result + 2;
|
|
|
|
end;
|
|
|
|
|
|
|
|
{======================================================================}
|
|
|
|
|
|
|
|
destructor TUDPBlockSocket.Destroy;
|
|
|
|
begin
|
|
|
|
if Assigned(FSocksControlSock) then
|
|
|
|
FSocksControlSock.Free;
|
|
|
|
inherited;
|
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
procedure TUDPBlockSocket.CreateSocket;
|
2008-04-23 23:34:31 +03:00
|
|
|
begin
|
2008-04-24 10:05:26 +03:00
|
|
|
FSocket := synsock.Socket(PF_INET, Integer(SOCK_DGRAM), IPPROTO_UDP);
|
|
|
|
FProtocol := IPPROTO_UDP;
|
|
|
|
inherited CreateSocket;
|
2008-04-23 23:34:31 +03:00
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
function TUDPBlockSocket.EnableBroadcast(Value: Boolean): Boolean;
|
2008-04-23 23:34:31 +03:00
|
|
|
var
|
2008-04-24 10:05:26 +03:00
|
|
|
Opt: Integer;
|
|
|
|
Res: Integer;
|
2008-04-23 23:34:31 +03:00
|
|
|
begin
|
2008-04-24 10:05:26 +03:00
|
|
|
opt := Ord(Value);
|
|
|
|
Res := synsock.SetSockOpt(FSocket, SOL_SOCKET, SO_BROADCAST, @Opt, SizeOf(opt));
|
2008-04-23 23:34:31 +03:00
|
|
|
SockCheck(Res);
|
2008-04-24 10:05:26 +03:00
|
|
|
Result := res = 0;
|
2008-04-23 23:46:58 +03:00
|
|
|
ExceptCheck;
|
2008-04-23 23:34:31 +03:00
|
|
|
end;
|
|
|
|
|
2008-04-24 10:09:13 +03:00
|
|
|
procedure TUDPBlockSocket.Connect(IP, Port: string);
|
|
|
|
begin
|
|
|
|
SetRemoteSin(IP, Port);
|
|
|
|
FBuffer := '';
|
|
|
|
DoStatus(HR_Connect, IP + ':' + Port);
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TUDPBlockSocket.RecvBuffer(Buffer: Pointer; Length: Integer): Integer;
|
|
|
|
begin
|
|
|
|
Result := RecvBufferFrom(Buffer, Length);
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TUDPBlockSocket.SendBuffer(Buffer: Pointer; Length: Integer): Integer;
|
|
|
|
begin
|
|
|
|
Result := SendBufferTo(Buffer, Length);
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TUDPBlockSocket.UdpAssociation: Boolean;
|
|
|
|
var
|
|
|
|
b: Boolean;
|
|
|
|
begin
|
|
|
|
Result := True;
|
|
|
|
FUsingSocks := False;
|
|
|
|
if FSocksIP <> '' then
|
|
|
|
begin
|
|
|
|
Result := False;
|
|
|
|
if not Assigned(FSocksControlSock) then
|
|
|
|
FSocksControlSock := TTCPBlockSocket.Create;
|
|
|
|
FSocksControlSock.CloseSocket;
|
|
|
|
FSocksControlSock.CreateSocket;
|
|
|
|
FSocksControlSock.Connect(FSocksIP, FSocksPort);
|
|
|
|
if FSocksControlSock.LastError <> 0 then
|
|
|
|
Exit;
|
|
|
|
// if not assigned local port, assign it!
|
|
|
|
if GetLocalSinPort = 0 then
|
|
|
|
Bind(GetLocalSinIP, '0');
|
|
|
|
GetSins;
|
|
|
|
//open control TCP connection to SOCKS
|
|
|
|
b := FSocksControlSock.SocksOpen;
|
|
|
|
if b then
|
|
|
|
b := FSocksControlSock.SocksRequest(3, GetLocalSinIP,
|
|
|
|
IntToStr(GetLocalSinPort));
|
|
|
|
if b then
|
|
|
|
b := FSocksControlSock.SocksResponse;
|
|
|
|
if not b and (FLastError = 0) then
|
|
|
|
FLastError := WSANO_RECOVERY;
|
|
|
|
FUsingSocks :=FSocksControlSock.UsingSocks;
|
|
|
|
FSocksRemoteIP := FSocksControlSock.FSocksResponseIP;
|
|
|
|
FSocksRemotePort := FSocksControlSock.FSocksResponsePort;
|
|
|
|
Result := True;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TUDPBlockSocket.SendBufferTo(Buffer: Pointer; Length: Integer): Integer;
|
|
|
|
var
|
|
|
|
SIp: string;
|
|
|
|
SPort: integer;
|
|
|
|
Buf: string;
|
|
|
|
begin
|
|
|
|
UdpAssociation;
|
|
|
|
if FUsingSocks then
|
|
|
|
begin
|
|
|
|
Sip := GetRemoteSinIp;
|
|
|
|
SPort := GetRemoteSinPort;
|
|
|
|
SetRemoteSin(FSocksRemoteIP, FSocksRemotePort);
|
|
|
|
SetLength(Buf,Length);
|
|
|
|
Move(Buffer^, PChar(Buf)^, Length);
|
|
|
|
Buf := #0 + #0 + #0 + SocksCode(Sip, IntToStr(SPort)) + Buf;
|
|
|
|
Result := inherited SendBufferTo(PChar(Buf), System.Length(buf));
|
|
|
|
SetRemoteSin(Sip, IntToStr(SPort));
|
|
|
|
end
|
|
|
|
else
|
|
|
|
begin
|
|
|
|
Result := inherited SendBufferTo(Buffer, Length);
|
|
|
|
GetSins;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TUDPBlockSocket.RecvBufferFrom(Buffer: Pointer; Length: Integer): Integer;
|
|
|
|
var
|
|
|
|
Buf: string;
|
|
|
|
x: integer;
|
|
|
|
begin
|
|
|
|
Result := inherited RecvBufferFrom(Buffer, Length);
|
|
|
|
if FUsingSocks then
|
|
|
|
begin
|
|
|
|
SetLength(Buf, Result);
|
|
|
|
Move(Buffer^, PChar(Buf)^, Result);
|
|
|
|
x := SocksDecode(Buf);
|
|
|
|
Result := Result - x + 1;
|
|
|
|
Buf := Copy(Buf, x, Result);
|
|
|
|
Move(PChar(Buf)^, Buffer^, Result);
|
|
|
|
SetRemoteSin(FSocksResponseIP, FSocksResponsePort);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2008-04-24 10:12:01 +03:00
|
|
|
procedure TUDPBlockSocket.AddMulticast(MCastIP: string);
|
|
|
|
var
|
|
|
|
Multicast: TMulticast;
|
|
|
|
begin
|
|
|
|
Multicast.MCastAddr := synsock.inet_addr(PChar(MCastIP));
|
|
|
|
Multicast.MCastIfc := u_long(INADDR_ANY);
|
|
|
|
SockCheck(synsock.SetSockOpt(FSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
|
|
|
pchar(@Multicast), SizeOf(Multicast)));
|
|
|
|
ExceptCheck;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TUDPBlockSocket.DropMulticast(MCastIP: string);
|
|
|
|
var
|
|
|
|
Multicast: TMulticast;
|
|
|
|
begin
|
|
|
|
Multicast.MCastAddr := synsock.inet_addr(PChar(MCastIP));
|
|
|
|
Multicast.MCastIfc := u_long(INADDR_ANY);
|
|
|
|
SockCheck(synsock.SetSockOpt(FSocket, IPPROTO_IP, IP_DROP_MEMBERSHIP,
|
|
|
|
pchar(@Multicast), SizeOf(Multicast)));
|
|
|
|
ExceptCheck;
|
|
|
|
end;
|
|
|
|
|
2008-04-23 23:17:14 +03:00
|
|
|
{======================================================================}
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
procedure TTCPBlockSocket.CreateSocket;
|
2008-04-23 23:17:14 +03:00
|
|
|
begin
|
2008-04-24 10:05:26 +03:00
|
|
|
FSocket := synsock.Socket(PF_INET, Integer(SOCK_STREAM), IPPROTO_TCP);
|
|
|
|
FProtocol := IPPROTO_TCP;
|
|
|
|
inherited CreateSocket;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TTCPBlockSocket.CloseSocket;
|
|
|
|
begin
|
|
|
|
synsock.Shutdown(FSocket, 1);
|
|
|
|
inherited CloseSocket;
|
2008-04-23 23:17:14 +03:00
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TTCPBlockSocket.Listen;
|
2008-04-24 10:09:13 +03:00
|
|
|
var
|
|
|
|
b: Boolean;
|
|
|
|
Sip,SPort: string;
|
2008-04-23 23:17:14 +03:00
|
|
|
begin
|
2008-04-24 10:09:13 +03:00
|
|
|
if FSocksIP = '' then
|
|
|
|
begin
|
|
|
|
SockCheck(synsock.Listen(FSocket, SOMAXCONN));
|
|
|
|
GetSins;
|
|
|
|
end
|
|
|
|
else
|
|
|
|
begin
|
|
|
|
Sip := GetLocalSinIP;
|
|
|
|
if Sip = '0.0.0.0' then
|
|
|
|
Sip := LocalName;
|
|
|
|
SPort := IntToStr(GetLocalSinPort);
|
2008-04-24 10:12:01 +03:00
|
|
|
inherited Connect(FSocksIP, FSocksPort);
|
2008-04-24 10:09:13 +03:00
|
|
|
b := SocksOpen;
|
|
|
|
if b then
|
|
|
|
b := SocksRequest(2, Sip, SPort);
|
|
|
|
if b then
|
|
|
|
b := SocksResponse;
|
|
|
|
if not b and (FLastError = 0) then
|
|
|
|
FLastError := WSANO_RECOVERY;
|
|
|
|
FSocksLocalIP := FSocksResponseIP;
|
|
|
|
if FSocksLocalIP = '0.0.0.0' then
|
|
|
|
FSocksLocalIP := FSocksIP;
|
|
|
|
FSocksLocalPort := FSocksResponsePort;
|
|
|
|
FSocksRemoteIP := '';
|
|
|
|
FSocksRemotePort := '';
|
|
|
|
end;
|
2008-04-23 23:46:58 +03:00
|
|
|
ExceptCheck;
|
2008-04-24 10:07:45 +03:00
|
|
|
DoStatus(HR_Listen, '');
|
2008-04-23 23:17:14 +03:00
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
function TTCPBlockSocket.Accept: TSocket;
|
2008-04-23 23:17:14 +03:00
|
|
|
var
|
2008-04-24 10:05:26 +03:00
|
|
|
Len: Integer;
|
2008-04-23 23:17:14 +03:00
|
|
|
begin
|
2008-04-24 10:09:13 +03:00
|
|
|
if FUsingSocks then
|
|
|
|
begin
|
|
|
|
if not SocksResponse and (FLastError = 0) then
|
|
|
|
FLastError := WSANO_RECOVERY;
|
|
|
|
FSocksRemoteIP := FSocksResponseIP;
|
|
|
|
FSocksRemotePort := FSocksResponsePort;
|
|
|
|
Result := FSocket;
|
|
|
|
end
|
|
|
|
else
|
|
|
|
begin
|
|
|
|
Len := SizeOf(FRemoteSin);
|
|
|
|
Result := synsock.Accept(FSocket, @FRemoteSin, @Len);
|
|
|
|
SockCheck(Result);
|
|
|
|
end;
|
2008-04-23 23:46:58 +03:00
|
|
|
ExceptCheck;
|
2008-04-24 10:07:45 +03:00
|
|
|
DoStatus(HR_Accept, '');
|
2008-04-23 23:17:14 +03:00
|
|
|
end;
|
|
|
|
|
2008-04-24 10:09:13 +03:00
|
|
|
procedure TTCPBlockSocket.Connect(IP, Port: string);
|
|
|
|
var
|
|
|
|
b: Boolean;
|
|
|
|
begin
|
|
|
|
if FSocksIP = '' then
|
|
|
|
inherited Connect(IP, Port)
|
|
|
|
else
|
|
|
|
begin
|
|
|
|
inherited Connect(FSocksIP, FSocksPort);
|
|
|
|
b := SocksOpen;
|
|
|
|
if b then
|
|
|
|
b := SocksRequest(1, IP, Port);
|
|
|
|
if b then
|
|
|
|
b := SocksResponse;
|
|
|
|
if not b and (FLastError = 0) then
|
|
|
|
FLastError := WSANO_RECOVERY;
|
|
|
|
FSocksLocalIP := FSocksResponseIP;
|
|
|
|
FSocksLocalPort := FSocksResponsePort;
|
|
|
|
FSocksRemoteIP := IP;
|
|
|
|
FSocksRemotePort := Port;
|
|
|
|
ExceptCheck;
|
|
|
|
DoStatus(HR_Connect, IP + ':' + Port);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TTCPBlockSocket.GetLocalSinIP: string;
|
|
|
|
begin
|
|
|
|
if FUsingSocks then
|
|
|
|
Result := FSocksLocalIP
|
|
|
|
else
|
|
|
|
Result := inherited GetLocalSinIP;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TTCPBlockSocket.GetRemoteSinIP: string;
|
|
|
|
begin
|
|
|
|
if FUsingSocks then
|
|
|
|
Result := FSocksRemoteIP
|
|
|
|
else
|
|
|
|
Result := inherited GetRemoteSinIP;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TTCPBlockSocket.GetLocalSinPort: Integer;
|
|
|
|
begin
|
|
|
|
if FUsingSocks then
|
|
|
|
Result := StrToIntDef(FSocksLocalPort, 0)
|
|
|
|
else
|
|
|
|
Result := inherited GetLocalSinPort;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TTCPBlockSocket.GetRemoteSinPort: Integer;
|
|
|
|
begin
|
|
|
|
if FUsingSocks then
|
|
|
|
Result := StrToIntDef(FSocksRemotePort, 0)
|
|
|
|
else
|
|
|
|
Result := inherited GetRemoteSinPort;
|
|
|
|
end;
|
|
|
|
|
2008-04-23 23:17:14 +03:00
|
|
|
{======================================================================}
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
//See 'winsock2.txt' file in distribute package!
|
|
|
|
|
|
|
|
procedure TICMPBlockSocket.CreateSocket;
|
2008-04-23 23:17:14 +03:00
|
|
|
begin
|
2008-04-24 10:05:26 +03:00
|
|
|
FSocket := synsock.Socket(PF_INET, Integer(SOCK_RAW), IPPROTO_ICMP);
|
|
|
|
FProtocol := IPPROTO_ICMP;
|
|
|
|
inherited CreateSocket;
|
2008-04-23 23:17:14 +03:00
|
|
|
end;
|
|
|
|
|
2008-04-24 10:05:26 +03:00
|
|
|
{======================================================================}
|
|
|
|
|
|
|
|
//See 'winsock2.txt' file in distribute package!
|
|
|
|
|
|
|
|
procedure TRAWBlockSocket.CreateSocket;
|
2008-04-23 23:46:58 +03:00
|
|
|
begin
|
2008-04-24 10:05:26 +03:00
|
|
|
FSocket := synsock.Socket(PF_INET, Integer(SOCK_RAW), IPPROTO_RAW);
|
|
|
|
FProtocol := IPPROTO_RAW;
|
|
|
|
inherited CreateSocket;
|
|
|
|
end;
|
|
|
|
|
2008-04-23 23:17:14 +03:00
|
|
|
end.
|