📄 idstacklinux.pas
字号:
{ $HDR$}
{**********************************************************************}
{ Unit archived using Team Coherence }
{ Team Coherence is Copyright 2002 by Quality Software Components }
{ }
{ For further information / comments, visit our WEB site at }
{ http://www.TeamCoherence.com }
{**********************************************************************}
{}
{ $Log: 10347: IdStackLinux.pas
{
{ Rev 1.1 4/20/03 1:50:42 PM RLebeau
{ Updated TranslateStringToTInAddr() to use new TIdSTack::GetIPInfo() method.
}
{
{ Rev 1.0 2002.11.12 10:53:30 PM czhower
}
unit IdStackLinux;
interface
uses
Classes,
Libc,
IdStack, IdStackConsts;
type
TIdSocketListLinux = class (TIdSocketList)
protected
FFDSet: TFDSet;
FMaxHandle: TIdStackSocketHandle;
//
function GetItem(AIndex: Integer): TIdStackSocketHandle; override;
public
procedure Add(AHandle: TIdStackSocketHandle); override;
procedure Remove(AHandle: TIdStackSocketHandle); override;
function Count: Integer; override;
End;//TIdSocketList
TIdStackLinux = class(TIdStack)
protected
procedure PopulateLocalAddresses; override;
function WSGetLocalAddress: string; override;
function WSGetLocalAddresses: TStrings; override;
public
function TInAddrToString(var AInAddr): string; override;
procedure TranslateStringToTInAddr(AIP: string; var AInAddr); override;
function WSTranslateSocketErrorMsg(const AErr: integer): string; override;
//
function WSAccept(ASocket: TIdStackSocketHandle; var VIP: string; var VPort: Integer)
: TIdStackSocketHandle; override;
function WSBind(ASocket: TIdStackSocketHandle; const AFamily: Integer;
const AIP: string; const APort: Integer): Integer; override;
function WSCloseSocket(ASocket: TIdStackSocketHandle): Integer; override;
function WSConnect(const ASocket: TIdStackSocketHandle; const AFamily: Integer;
const AIP: string; const APort: Integer): Integer; override;
function WSGetHostByAddr(const AAddress: string): string; override;
function WSGetHostByName(const AHostName: string): string; override;
function WSGetHostName: string; override;
function WSGetLastError: Integer; override;
function WSGetServByName(const AServiceName: string): Integer; override;
function WSGetServByPort(const APortNumber: Integer): TStrings; override;
function WSGetSockOpt(ASocket: TIdStackSocketHandle; Alevel, AOptname: Integer; AOptval: PChar;
var AOptlen: Integer): Integer; override;
procedure WSGetPeerName(ASocket: TIdStackSocketHandle;
var VFamily: Integer; var VIP: string; var VPort: Integer); override;
procedure WSGetSockName(ASocket: TIdStackSocketHandle;
var VFamily: Integer; var VIP: string; var VPort: Integer); override;
function WSHToNs(AHostShort: Word): Word; override;
function WSListen(ASocket: TIdStackSocketHandle; ABackLog: Integer): Integer; override;
function WSNToHs(ANetShort: Word): Word; override;
function WSHToNL(AHostLong: LongWord): LongWord; override;
function WSNToHL(ANetLong: LongWord): LongWord; override;
function WSRecv(ASocket: TIdStackSocketHandle; var ABuffer; const ABufferLength, AFlags: Integer)
: integer; override;
function WSRecvFrom(const ASocket: TIdStackSocketHandle; var ABuffer;
const ALength, AFlags: Integer; var VIP: string; var VPort: Integer): Integer; override;
function WSSelect(ARead, AWrite, AErrors: TList; ATimeout: Integer): Integer; override;
function WSSend(ASocket: TIdStackSocketHandle; var ABuffer;
const ABufferLength, AFlags: Integer): Integer; override;
function WSSendTo(ASocket: TIdStackSocketHandle; var ABuffer;
const ABufferLength, AFlags: Integer; const AIP: string; const APort: integer): Integer;
override;
function WSSetSockOpt(ASocket: TIdStackSocketHandle; ALevel, AOptName: Integer; AOptVal: PChar;
AOptLen: Integer): Integer; override;
function WSSocket(AFamily, AStruct, AProtocol: Integer): TIdStackSocketHandle; override;
function WSShutdown(ASocket: TIdStackSocketHandle; AHow: Integer): Integer; override;
end;
TLinger = record
l_onoff: Word;
l_linger: Word;
end;
TIdLinger = TLinger;
implementation
uses
IdException,
IdGlobal, IdResourceStrings,
SysUtils;
const
Id_MSG_NOSIGNAL = MSG_NOSIGNAL;
Id_WSAEPIPE = EPIPE;
function TIdStackLinux.TInAddrToString(var AInAddr): string;
begin
with TInAddr(AInAddr).S_un_b do begin
Result := IntToStr(Ord(s_b1)) + '.' + IntToStr(Ord(s_b2)) + '.' + IntToStr(Ord(s_b3)) + '.' {Do not Localize}
+ IntToStr(Ord(s_b4));
end;
end;
function TIdStackLinux.WSAccept(ASocket: TIdStackSocketHandle;
var VIP: string; var VPort: Integer): TIdStackSocketHandle;
var
i: Cardinal;
LAddr: SockAddr;
begin
i := SizeOf(LAddr);
Result := Accept(ASocket, @LAddr, @i);
if Result <> SOCKET_ERROR then begin
VIP := TInAddrToString(LAddr.sin_addr);
VPort := NToHs(LAddr.sin_port);
end else begin
if GetLastError = EBADF then begin
SetLastError(EINTR);
end;
end;
end;
function TIdStackLinux.WSBind(ASocket: TIdStackSocketHandle;
const AFamily: Integer; const AIP: string;
const APort: Integer): Integer;
var
Addr: SockAddr;
begin
Addr.sin_family := AFamily;
if length(AIP) = 0 then begin
Addr.sin_addr.s_addr := INADDR_ANY;
end else begin
TranslateStringToTInAddr(AIP, Addr.sin_addr);
end;
Addr.sin_port := HToNs(APort);
Result := Bind(ASocket, addr, SizeOf(Addr));
end;
function TIdStackLinux.WSCloseSocket(ASocket: TIdStackSocketHandle): Integer;
begin
Result := Libc.__close(ASocket);
end;
function TIdStackLinux.WSConnect(const ASocket: TIdStackSocketHandle;
const AFamily: Integer; const AIP: string;
const APort: Integer): Integer;
var
Addr: SockAddr;
begin
Addr.sin_family := AFamily;
TranslateStringToTInAddr(AIP, Addr.sin_addr);
Addr.sin_port := HToNs(APort);
Result := Connect(ASocket, Addr, SizeOf(Addr));
end;
function TIdStackLinux.WSGetHostByName(const AHostName: string): string;
var
pa: PChar;
sa: TInAddr;
Host: PHostEnt;
begin
//we don't use _r functions because they are depreciated and the non-r's are safe in Linux.
//They could be problematic in Sun Solorus and BSD.
Host := GethostByName(PChar(AHostName));
if (Host <> nil) then
begin
pa := Host^.h_addr_list^;
sa.S_un_b.s_b1 := Ord(pa[0]);
sa.S_un_b.s_b2 := Ord(pa[1]);
sa.S_un_b.s_b3 := Ord(pa[2]);
sa.S_un_b.s_b4 := Ord(pa[3]);
Result := TInAddrToString(sa);
end
else
begin
RaiseSocketError(h_errno);
end;
end;
function TIdStackLinux.WSGetHostName: string;
begin
SetLength(Result, 250);
GetHostName(PChar(Result), Length(Result));
Result := String(PChar(Result));
end;
function TIdStackLinux.WSListen(ASocket: TIdStackSocketHandle;
ABackLog: Integer): Integer;
begin
Result := Listen(ASocket, ABacklog);
end;
function TIdStackLinux.WSRecv(ASocket: TIdStackSocketHandle; var ABuffer;
const ABufferLength, AFlags: Integer): integer;
begin
Result := Recv(ASocket, ABuffer, ABufferLength, AFlags or Id_MSG_NOSIGNAL);
end;
function TIdStackLinux.WSRecvFrom(const ASocket: TIdStackSocketHandle;
var ABuffer; const ALength, AFlags: Integer; var VIP: string;
var VPort: Integer): Integer;
var
iSize: Cardinal;
Addr: sockaddr;
begin
iSize := SizeOf(Addr);
Result := RecvFrom(ASocket, ABuffer, ALength, AFlags or Id_MSG_NOSIGNAL, @Addr, @iSize);
VIP := TInAddrToString(Addr.sin_addr);
VPort := NToHs(Addr.sin_port);
end;
function TIdStackLinux.WSSelect(ARead, AWrite, AErrors: TList; ATimeout: Integer): Integer;
var
tmTo: TTimeVal;
FDRead, FDWrite, FDError: TFDSet;
LMaxHandle: TIdStackSocketHandle;
{ TODO : Optimize and cache these routines }
procedure GetFDSet(AList: TList; var ASet: TFDSet);
var
i: Integer;
begin
if assigned( AList ) then
begin
AList.Clear;
for i := 0 to __FD_SETSIZE - 1 do
begin
if FD_ISSET(i, ASet) then
begin
AList.Add(TObject(i));
end;
end;
end;
end;
procedure SetFDSet(AList: TList; var ASet: TFDSet);
var
i: integer;
begin
if AList <> nil then begin
if AList.Count > __FD_SETSIZE then begin
raise EIdSetSizeExceeded.Create(RSSetSizeExceeded);
end;
for i := 0 to AList.Count - 1 do begin
FD_SET(TIdStackSocketHandle(AList[i]), ASet);
LMaxHandle := Max(LMaxHandle, TIdStackSocketHandle(AList[i]) + 1);
end;
end;
end;
begin
LMaxHandle := 0;
FD_ZERO(FDRead);
FD_ZERO(FDWrite);
FD_ZERO(FDError);
SetFDSet(ARead, FDRead);
SetFDSet(AWrite, FDWrite);
SetFDSet(AErrors, FDError);
if ATimeout = IdTimeoutInfinite then begin
Result := Select(LMaxHandle, @FDRead, @FDWrite, @FDError, nil);
end else begin
tmTo.tv_sec := ATimeout div 1000;
tmTo.tv_usec := (ATimeout mod 1000) * 1000;
Result := Select(LMaxHandle, @FDRead, @FDWrite, @FDError, @tmTO);
end;
GetFDSet(ARead, FDRead);
GetFDSet(AWrite, FDWrite);
GetFDSet(AErrors, FDError);
end;
function TIdStackLinux.WSSend(ASocket: TIdStackSocketHandle;
var ABuffer; const ABufferLength, AFlags: Integer): Integer;
begin
Result := Send(ASocket, ABuffer, ABufferLength, AFlags or Id_MSG_NOSIGNAL);
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -