|
@@ -18,7 +18,8 @@ unit ssockets;
|
|
interface
|
|
interface
|
|
|
|
|
|
uses
|
|
uses
|
|
- SysUtils, Classes, ctypes, sockets;
|
|
|
|
|
|
+// This must be here, to prevent it from overriding the sockets definitions... :/
|
|
|
|
+ SysUtils, Classes, ctypes, sockets;
|
|
|
|
|
|
type
|
|
type
|
|
|
|
|
|
@@ -111,6 +112,7 @@ type
|
|
|
|
|
|
TSocketServer = Class(TObject)
|
|
TSocketServer = Class(TObject)
|
|
Private
|
|
Private
|
|
|
|
+ FIdleTimeOut: Cardinal;
|
|
FOnAcceptError: TOnAcceptError;
|
|
FOnAcceptError: TOnAcceptError;
|
|
FOnIdle : TNotifyEvent;
|
|
FOnIdle : TNotifyEvent;
|
|
FNonBlocking : Boolean;
|
|
FNonBlocking : Boolean;
|
|
@@ -139,6 +141,7 @@ type
|
|
Function SockToStream (ASocket : Longint) : TSocketStream;Virtual;Abstract;
|
|
Function SockToStream (ASocket : Longint) : TSocketStream;Virtual;Abstract;
|
|
Procedure Close; Virtual;
|
|
Procedure Close; Virtual;
|
|
Procedure Abort;
|
|
Procedure Abort;
|
|
|
|
+ Function RunIdleLoop : Boolean;
|
|
function GetConnection: TSocketStream; virtual; abstract;
|
|
function GetConnection: TSocketStream; virtual; abstract;
|
|
Function HandleAcceptError(E : ESocketError) : TAcceptErrorAction;
|
|
Function HandleAcceptError(E : ESocketError) : TAcceptErrorAction;
|
|
Property Handler : TSocketHandler Read FHandler;
|
|
Property Handler : TSocketHandler Read FHandler;
|
|
@@ -166,6 +169,9 @@ type
|
|
Property ReuseAddress : Boolean Read GetReuseAddress Write SetReuseAddress;
|
|
Property ReuseAddress : Boolean Read GetReuseAddress Write SetReuseAddress;
|
|
// -1 means no linger. Any value >=0 sets linger on.
|
|
// -1 means no linger. Any value >=0 sets linger on.
|
|
Property Linger: Integer Read GetLinger Write Setlinger;
|
|
Property Linger: Integer Read GetLinger Write Setlinger;
|
|
|
|
+ // Accept Timeout in milliseconds.
|
|
|
|
+ // If Different from 0, then there will be an idle loop before accepting new connections, Calling OnIdle if no new connection appeared in the specified timeout.
|
|
|
|
+ Property AcceptIdleTimeOut : Cardinal Read FIdleTimeOut Write FIdleTimeout;
|
|
end;
|
|
end;
|
|
|
|
|
|
{ TInetServer }
|
|
{ TInetServer }
|
|
@@ -239,7 +245,10 @@ Implementation
|
|
|
|
|
|
uses
|
|
uses
|
|
{$ifdef unix}
|
|
{$ifdef unix}
|
|
- BaseUnix, Unix,
|
|
|
|
|
|
+ BaseUnix,Unix,
|
|
|
|
+{$endif}
|
|
|
|
+{$ifdef windows}
|
|
|
|
+ winsock2, windows,
|
|
{$endif}
|
|
{$endif}
|
|
resolve;
|
|
resolve;
|
|
|
|
|
|
@@ -296,7 +305,8 @@ end;
|
|
|
|
|
|
function TSocketHandler.Shutdown(BiDirectional: Boolean): boolean;
|
|
function TSocketHandler.Shutdown(BiDirectional: Boolean): boolean;
|
|
begin
|
|
begin
|
|
- CheckSocket
|
|
|
|
|
|
+ CheckSocket ;
|
|
|
|
+ Result:=False;
|
|
end;
|
|
end;
|
|
|
|
|
|
function TSocketHandler.Recv(Const Buffer; Count: Integer): Integer;
|
|
function TSocketHandler.Recv(Const Buffer; Count: Integer): Integer;
|
|
@@ -445,20 +455,20 @@ begin
|
|
Result:=FHandler.Send(Buffer,Count);
|
|
Result:=FHandler.Send(Buffer,Count);
|
|
end;
|
|
end;
|
|
|
|
|
|
-function TSocketStream.GetLocalAddress: TSockAddr;
|
|
|
|
|
|
+function TSocketStream.GetLocalAddress: sockets.TSockAddr;
|
|
var
|
|
var
|
|
len: LongInt;
|
|
len: LongInt;
|
|
begin
|
|
begin
|
|
- len := SizeOf(TSockAddr);
|
|
|
|
|
|
+ len := SizeOf(sockets.TSockAddr);
|
|
if fpGetSockName(Handle, @Result, @len) <> 0 then
|
|
if fpGetSockName(Handle, @Result, @len) <> 0 then
|
|
FillChar(Result, SizeOf(Result), 0);
|
|
FillChar(Result, SizeOf(Result), 0);
|
|
end;
|
|
end;
|
|
|
|
|
|
-function TSocketStream.GetRemoteAddress: TSockAddr;
|
|
|
|
|
|
+function TSocketStream.GetRemoteAddress: sockets.TSockAddr;
|
|
var
|
|
var
|
|
len: LongInt;
|
|
len: LongInt;
|
|
begin
|
|
begin
|
|
- len := SizeOf(TSockAddr);
|
|
|
|
|
|
+ len := SizeOf(sockets.TSockAddr);
|
|
if fpGetPeerName(Handle, @Result, @len) <> 0 then
|
|
if fpGetPeerName(Handle, @Result, @len) <> 0 then
|
|
FillChar(Result, SizeOf(Result), 0);
|
|
FillChar(Result, SizeOf(Result), 0);
|
|
end;
|
|
end;
|
|
@@ -499,7 +509,7 @@ end;
|
|
TSocketServer
|
|
TSocketServer
|
|
---------------------------------------------------------------------}
|
|
---------------------------------------------------------------------}
|
|
|
|
|
|
-Constructor TSocketServer.Create(ASocket : Longint; AHandler : TSocketHandler);
|
|
|
|
|
|
+constructor TSocketServer.Create(ASocket: Longint; AHandler: TSocketHandler);
|
|
|
|
|
|
begin
|
|
begin
|
|
FSocket:=ASocket;
|
|
FSocket:=ASocket;
|
|
@@ -510,7 +520,7 @@ begin
|
|
FHandler:=AHandler;
|
|
FHandler:=AHandler;
|
|
end;
|
|
end;
|
|
|
|
|
|
-Destructor TSocketServer.Destroy;
|
|
|
|
|
|
+destructor TSocketServer.Destroy;
|
|
|
|
|
|
begin
|
|
begin
|
|
Close;
|
|
Close;
|
|
@@ -518,7 +528,7 @@ begin
|
|
Inherited;
|
|
Inherited;
|
|
end;
|
|
end;
|
|
|
|
|
|
-Procedure TSocketServer.Close;
|
|
|
|
|
|
+procedure TSocketServer.Close;
|
|
|
|
|
|
begin
|
|
begin
|
|
If FSocket<>-1 Then
|
|
If FSocket<>-1 Then
|
|
@@ -542,7 +552,37 @@ begin
|
|
{$endif}
|
|
{$endif}
|
|
end;
|
|
end;
|
|
|
|
|
|
-Procedure TSocketServer.Listen;
|
|
|
|
|
|
+function TSocketServer.RunIdleLoop: Boolean;
|
|
|
|
+
|
|
|
|
+// Run Accept idle loop. Return True if there is a new connection waiting
|
|
|
|
+
|
|
|
|
+var
|
|
|
|
+ FDS: TFDSet;
|
|
|
|
+ TimeV: TTimeVal;
|
|
|
|
+begin
|
|
|
|
+ Repeat
|
|
|
|
+ Result:=False;
|
|
|
|
+ TimeV.tv_usec := (AcceptIdleTimeout mod 1000) * 1000;
|
|
|
|
+ TimeV.tv_sec := AcceptIdleTimeout div 1000;
|
|
|
|
+{$ifdef unix}
|
|
|
|
+ FDS := Default(TFDSet);
|
|
|
|
+ fpFD_Zero(FDS);
|
|
|
|
+ fpFD_Set(FSocket, FDS);
|
|
|
|
+ Result := fpSelect(FSocket + 1, @FDS, @FDS, @FDS, @TimeV) > 0;
|
|
|
|
+{$else}
|
|
|
|
+{$ifdef windows}
|
|
|
|
+ FDS := Default(TFDSet);
|
|
|
|
+ FD_Zero(FDS);
|
|
|
|
+ FD_Set(FSocket, FDS);
|
|
|
|
+ Result := Select(FSocket + 1, @FDS, @FDS, @FDS, @TimeV) > 0;
|
|
|
|
+{$endif}
|
|
|
|
+{$endif}
|
|
|
|
+ If not Result then
|
|
|
|
+ DoOnIdle;
|
|
|
|
+ Until Result or (Not FAccepting);
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+procedure TSocketServer.Listen;
|
|
|
|
|
|
begin
|
|
begin
|
|
If Not FBound then
|
|
If Not FBound then
|
|
@@ -551,7 +591,7 @@ begin
|
|
Raise ESocketError.Create(seListenFailed,[FSocket,SocketError]);
|
|
Raise ESocketError.Create(seListenFailed,[FSocket,SocketError]);
|
|
end;
|
|
end;
|
|
|
|
|
|
-function TSocketServer.GetSockopt(ALevel, AOptName: cint; Var optval;
|
|
|
|
|
|
+function TSocketServer.GetSockopt(ALevel, AOptName: cint; var optval;
|
|
var optlen: tsocklen): Boolean;
|
|
var optlen: tsocklen): Boolean;
|
|
begin
|
|
begin
|
|
Result:=fpGetSockOpt(FSocket,ALevel,AOptName,@optval,@optlen)<>-1;
|
|
Result:=fpGetSockOpt(FSocket,ALevel,AOptName,@optval,@optlen)<>-1;
|
|
@@ -589,7 +629,7 @@ begin
|
|
FOnAcceptError(Self,FSocket,E,Result);
|
|
FOnAcceptError(Self,FSocket,E,Result);
|
|
end;
|
|
end;
|
|
|
|
|
|
-Procedure TSocketServer.StartAccepting;
|
|
|
|
|
|
+procedure TSocketServer.StartAccepting;
|
|
|
|
|
|
Var
|
|
Var
|
|
NoConnections : Integer;
|
|
NoConnections : Integer;
|
|
@@ -602,7 +642,10 @@ begin
|
|
Repeat
|
|
Repeat
|
|
Repeat
|
|
Repeat
|
|
Try
|
|
Try
|
|
- Stream:=GetConnection;
|
|
|
|
|
|
+ If (AcceptIdleTimeOut=0) or RunIdleLoop then
|
|
|
|
+ Stream:=GetConnection
|
|
|
|
+ else
|
|
|
|
+ Stream:=Nil;
|
|
if Assigned(Stream) then
|
|
if Assigned(Stream) then
|
|
begin
|
|
begin
|
|
Inc (NoConnections);
|
|
Inc (NoConnections);
|
|
@@ -633,7 +676,7 @@ begin
|
|
Abort;
|
|
Abort;
|
|
end;
|
|
end;
|
|
|
|
|
|
-Procedure TSocketServer.DoOnIdle;
|
|
|
|
|
|
+procedure TSocketServer.DoOnIdle;
|
|
|
|
|
|
begin
|
|
begin
|
|
If Assigned(FOnIdle) then
|
|
If Assigned(FOnIdle) then
|
|
@@ -689,14 +732,14 @@ begin
|
|
Result:=l.l_linger;
|
|
Result:=l.l_linger;
|
|
end;
|
|
end;
|
|
|
|
|
|
-Procedure TSocketServer.DoConnect(ASocket : TSocketStream);
|
|
|
|
|
|
+procedure TSocketServer.DoConnect(ASocket: TSocketStream);
|
|
|
|
|
|
begin
|
|
begin
|
|
If Assigned(FOnConnect) Then
|
|
If Assigned(FOnConnect) Then
|
|
FOnConnect(Self,ASocket);
|
|
FOnConnect(Self,ASocket);
|
|
end;
|
|
end;
|
|
|
|
|
|
-Function TSocketServer.DoConnectQuery(ASocket : Longint) : Boolean;
|
|
|
|
|
|
+function TSocketServer.DoConnectQuery(ASocket: longint): Boolean;
|
|
|
|
|
|
begin
|
|
begin
|
|
Result:=True;
|
|
Result:=True;
|
|
@@ -704,7 +747,7 @@ begin
|
|
FOnConnectQuery(Self,ASocket,Result);
|
|
FOnConnectQuery(Self,ASocket,Result);
|
|
end;
|
|
end;
|
|
|
|
|
|
-Procedure TSocketServer.SetNonBlocking;
|
|
|
|
|
|
+procedure TSocketServer.SetNonBlocking;
|
|
|
|
|
|
begin
|
|
begin
|
|
{$ifdef Unix}
|
|
{$ifdef Unix}
|