Browse Source

+ Completed nonblocking treatment

michael 25 years ago
parent
commit
a7014bd027
1 changed files with 51 additions and 17 deletions
  1. 51 17
      fcl/inc/ssockets.pp

+ 51 - 17
fcl/inc/ssockets.pp

@@ -12,7 +12,8 @@ type
     seBindFailed,
     seListenFailed,
     seConnectFailed,
-    seAcceptFailed);
+    seAcceptFailed,
+    seAcceptWouldBlock);
 
   TSocketOption = (soDebug,soReuseAddr,soKeepAlive,soDontRoute,soBroadcast,
                    soOOBinline);
@@ -65,13 +66,14 @@ type
     Procedure Listen;
     Procedure StartAccepting;
     Procedure StopAccepting;
+    Procedure SetNonBlocking;
     Property Bound : Boolean Read FBound;
     Property MaxConnections : longint Read FMaxConnections Write FMaxConnections;
     Property QueueSize : Longint Read FQueueSize Write FQueueSize default 5;
     Property OnConnect : TConnectEvent Read FOnConnect Write FOnConnect;
     Property OnConnectQuery : TConnectQuery Read FOnConnectQuery Write FOnConnectQuery;
     Property OnIdle : TNotifyEvent Read FOnIdle Write FOnIdle;
-    Property NonBlocking : Boolean Read FNonBlocking Write FNonBlocking;
+    Property NonBlocking : Boolean Read FNonBlocking;
     Property Socket : Longint Read FSocket;
     Property SockType : Longint Read FSockType;
   end;
@@ -128,7 +130,10 @@ type
 
 Implementation
 
-uses inet;
+uses inet,linux;
+
+Const
+  SocketWouldBlock = -2;
 
 { ---------------------------------------------------------------------
   ESocketError  
@@ -141,7 +146,8 @@ resourcestring
   strSocketListenFailed = 'Listening on port #%d failed: %s';
   strSocketConnectFailed = 'Connect to %s failed.';
   strSocketAcceptFailed = 'Could not accept a client connection: %s';
-
+  strSocketAcceptWouldBlock = 'Accept would block on socket: %d';
+  
 constructor ESocketError.Create(ACode: TSocketErrorType; const MsgArgs: array of const);
 var
   s: String;
@@ -154,6 +160,7 @@ begin
     seListenFailed  : s := strSocketListenFailed;
     seConnectFailed : s := strSocketConnectFailed;
     seAcceptFailed  : s := strSocketAcceptFailed;
+    seAcceptWouldBLock : S:= strSocketAcceptWouldBlock;
   end;
   s := Format(s, MsgArgs);
   inherited Create(s);
@@ -229,19 +236,29 @@ Var
 begin
   Listen;
   Repeat
-    NewSocket:=Accept;
-    If NewSocket<>-1 then
-      begin
-      Inc (NoConnections);
-      If DoConnectQuery(NewSocket) Then
-        begin
-        Stream:=SockToStream(NewSocket);
-        DoConnect(Stream);
-        end
-      end
-    Else 
-      If NonBlocking Then  
-        DoOnIdle;     
+    Repeat
+      Try 
+        NewSocket:=Accept;
+        If NewSocket>=0 then
+          begin
+          Inc (NoConnections);
+          If DoConnectQuery(NewSocket) Then
+            begin
+            Stream:=SockToStream(NewSocket);
+            DoConnect(Stream);
+            end
+          end
+      except
+        On E : ESocketError do
+          If E.Code=seAcceptWouldBlock then
+            begin
+            DoOnIdle;
+            NewSocket:=-1;
+            end;
+          else
+            Raise;  
+       end;     
+    Until (NewSocket>=0) or (Not NonBlocking);      
   Until Not (FAccepting) or ((FMaxConnections<>-1) and (NoConnections>=FMaxConnections));
 end;
 
@@ -273,6 +290,13 @@ begin
     FOnConnectQuery(Self,ASocket,Result);
 end;
 
+Procedure TSocketServer.SetNonBlocking;
+
+begin
+  fcntl(FSocket,F_SETFL,OPEN_NONBLOCK);
+  FNonBlocking:=True;
+end;
+
 { ---------------------------------------------------------------------
     TInetServer
   ---------------------------------------------------------------------}
@@ -317,6 +341,11 @@ Var l : longint;
 begin
   L:=SizeOf(FAddr);
   Result:=Sockets.Accept(Socket,Faddr,L);
+  If Result<0 then
+    If SocketError=Sys_EWOULDBLOCK then 
+      Raise ESocketError.Create(seAcceptWouldBlock,[socket])
+    else
+      Raise ESocketError.Create(seAcceptFailed,[socket]);
 end;
 
 { ---------------------------------------------------------------------
@@ -361,6 +390,11 @@ Var L : longint;
 begin
   L:=Length(FFileName);
   Result:=Sockets.Accept(Socket,FUnixAddr,L);
+  If Result<0 then
+    If SocketError=Sys_EWOULDBLOCK then 
+      Raise ESocketError.Create(seAcceptWouldBlock,[socket])
+    else
+      Raise ESocketError.Create(seAcceptFailed,[socket]);
 end;
 
 Function  TUnixServer.SockToStream (ASocket : Longint) : TSocketStream;