Ver Fonte

* Make sure it compiles on other platforms

Michaël Van Canneyt há 1 mês atrás
pai
commit
fd0dd60f55
2 ficheiros alterados com 90 adições e 15 exclusões
  1. 89 12
      packages/fcl-net/src/fpsockets.pp
  2. 1 3
      packages/fcl-net/src/ssockets.pp

+ 89 - 12
packages/fcl-net/src/fpsockets.pp

@@ -21,12 +21,22 @@ unit fpsockets;
 
 interface
 
+// If a platform is fully operational, add it here
+{$IF DEFINED(WINDOWS) or DEFINED(UNIX) }
+{$DEFINE FULL_IP_STACK}
+{$DEFINE HAVE_SELECT_CALL}
+{$ENDIF}
+
 {$IFDEF FPC_DOTTEDUNITS}
 uses
-  {$IfDef WINDOWS}WinApi.WinSock2{$Else}UnixApi.Base, UnixApi.TermIO{$EndIf}, System.SysUtils, System.Net.Sockets, System.Nullable, System.Tuples;
+  {$IfDef WINDOWS}WinApi.WinSock2, {$ENDIF}
+  {$ifdef unix} UnixApi.Base, UnixApi.TermIO, {$EndIf}
+  System.SysUtils, System.Net.Sockets, System.Nullable, System.Tuples;
 {$ELSE FPC_DOTTEDUNITS}
 uses
-  {$IfDef WINDOWS}WinSock2{$Else}BaseUnix, termio{$EndIf},  sysutils, sockets, nullable, tuples;
+  {$IfDEF WINDOWS}WinSock2, {$ENDIF}
+  {$IFDEF LINUX}BaseUnix, termio, {$EndIf}  
+  sysutils, sockets, nullable, tuples;
 {$ENDIF FPC_DOTTEDUNITS}
 
 type
@@ -184,9 +194,11 @@ function LocalEndpoint(const ASocket: TFPSocket): specialize TPair<TNetworkAddre
 function RemoteEndpoint(const ASocket: TFPSocket): specialize TPair<TNetworkAddress, Word>;
 
 // Timeout in MS
+{$IFDEF HAVE_SELECT_CALL}
 function DataAvailable(const SocketArray: specialize TArray<TFPSocket>; TimeOut: Integer = 0): specialize TArray<TFPSocket>; overload;
 function DataAvailable(const ASocket: TFPSocket; TimeOut: Integer = 0): Boolean; overload; //inline;
 function DataAvailable(const SocketArray: array of TFPSocket; TimeOut: Integer = 0): specialize TArray<TFPSocket>; overload; inline;
+{$ENDIF}
 
 function BytesAvailable(const ASocket: TFPSocket): SizeInt;
 
@@ -237,8 +249,19 @@ uses
 { Helper }
 
 const
-  IPPROTO_IPV6 = {$IfDef WINDOWS}41{$Else}41{$EndIf};
-  IPV6_V6ONLY = {$IfDef WINDOWS}27{$Else}26{$EndIf};
+  {$IFDEF WINDOWS}
+  IPPROTO_IPV6 = 41;
+  IPV6_V6ONLY = 27;
+  {$ENDIF}
+  {$IFDEF UNIX}
+  IPPROTO_IPV6 = 41;
+  IPV6_V6ONLY = 26;
+  {$ENDIF}
+  
+  {$IFNDEF FULL_IP_STACK}
+  IPPROTO_IPV6 = -1;
+  IPV6_V6ONLY = -1;
+  {$ENDIF}
 
 function WouldBlock(SockErr: Integer): Boolean; inline;
 begin
@@ -323,6 +346,7 @@ end;
 function CreateRawSocket(ADomain: TFPSocketType; ASockProto: TFPSocketProto; AProto: Integer; RaiseSocketException: Boolean): TSocket;
 var
   AFam, AType, v6Only: Integer;
+  IPV6 : Boolean;
 begin
   case ADomain of
   stIPv4: AFam := AF_INET;
@@ -344,11 +368,13 @@ begin
   if ADomain = stIPDualStack then
   begin
     v6Only := 0;
+    if IPV6_V6ONLY=-1 then
+      raise EDualStackNotSupported.Create('Dualstack option not supported on this system.');
     if fpsetsockopt(Result, IPPROTO_IPV6, IPV6_V6ONLY, @v6Only, SizeOf(v6Only)) <> 0 then
-    begin
-      socketsunit.CloseSocket(Result);
+      begin
+        socketsunit.CloseSocket(Result);
       raise EDualStackNotSupported.Create('Dualstack option not supported on this system: ' + socketerror.ToString);
-    end;
+      end;
   end;
 end;
 
@@ -553,9 +579,20 @@ function Connect(const ASocket: TFPSocket; const AAddress: TNetworkAddress;
 var
   addr: TAddressUnion;
 const
+  {$IFDEF WINDOWS} 
   EALREADY = {$IfDef Windows}WSAEALREADY{$Else}ESysEALREADY{$EndIf};
   EINPROGRESS = {$IfDef Windows}WSAEINPROGRESS{$Else}ESysEINPROGRESS{$EndIf};
   ECONNREFUSED = {$IfDef Windows}WSAECONNREFUSED{$Else}ESysECONNREFUSED{$EndIf};
+  {$ENDIF}
+  {$IFDEF UNIX}
+  {$ENDIF}
+  
+  {$IFNDEF FULL_IP_STACK}
+  // Fallback
+  EALREADY     = -2;
+  EINPROGRESS  = -3;
+  ECONNREFUSED = -4;
+  {$ENDIF}
 begin
   addr := CreateAddr(AAddress, APort, ASocket.SocketType = stIPDualStack);
   if fpconnect(ASocket.FD, socketsunit.psockaddr(@addr), SizeOf(addr)) <> 0 then
@@ -697,6 +734,7 @@ begin
   UdpMessage := ReceiveFrom(ASocket, @Result.Ptr^.Data[1], MaxLength, AFlags);
   if UdpMessage.DataSize = 0 then
     Exit(null);
+    
   SetLength(Result.Ptr^.Data, UdpMessage.DataSize);
   Result.Ptr^.FromAddr := UdpMessage.FromAddr;
   Result.Ptr^.FromPort := UdpMessage.FromPort;
@@ -879,6 +917,7 @@ begin
       end;
     Len += ReadLen;
     MaxCount := BytesAvailable(ASocket) div SizeOfT;
+    
   until ((Len<Length(Result)*SizeOf(T)) Or (MaxCount = 0)) And ((Len mod SizeOf(T)) = 0);
   SetLength(Result, Len div SizeOf(T));
 end;
@@ -950,15 +989,18 @@ begin
   Result := SendTo(ASocket, ReceiverAddr, ReceiverPort, @AData[0], Length(AData) * SizeOf(T), AFlags);
 end;
 
-procedure SetNonBlocking(const ASocket: TFPSocket; AValue: Boolean);
 {$IfDef Windows}
+procedure SetNonBlocking(const ASocket: TFPSocket; AValue: Boolean);
 var
   nonblock: u_long;
 begin
   nonblock := Ord(AValue);
   ioctlsocket(ASocket.FD, LongInt(FIONBIO), @nonblock);
 end;
-{$Else}
+{$ENDIF}
+{$IFDEF UNIX}
+procedure SetNonBlocking(const ASocket: TFPSocket; AValue: Boolean);
+
 var
   State: cint;
 begin
@@ -971,6 +1013,16 @@ begin
 end;
 {$EndIf}
 
+{$IFNDEF FULL_IP_STACK}
+procedure SetNonBlocking(const ASocket: TFPSocket; AValue: Boolean);
+
+begin
+  if avalue then
+    Raise ENotImplemented.Create('NonBlocking socket')
+end;
+{$ENDIF}
+
+{$IFDEF HAVE_SELECT_CALL}
 function DataAvailable(const SocketArray: specialize TArray<TFPSocket>;
   TimeOut: Integer): specialize TArray<TFPSocket>;
 var
@@ -1040,17 +1092,42 @@ begin
     Result := Count;
 end;
 
+{$ELSE HAVE_SELECT_CALL}
+
+function BytesAvailable(const ASocket: TFPSocket): SizeInt;
+begin
+  Result:=0;
+end;
+
+{$ENDIF HAVE_SELECT_CALL}
+
+
+
 function StreamClosed(const ASocket:TFPSocket):Boolean;
 begin
-  Result := (ASocket.Protocol <> spStream) Or (
+  Result := (ASocket.Protocol <> spStream) 
+            {$IFDEF HAVE_SELECT_CALL}
+            Or (
               DataAvailable(ASocket, 0) And
               (BytesAvailable(ASocket) = 0)
-            );
+            )
+            {$ENDIF}
+            ;
 end;
 
 function ConnectionState(const ASocket:TFPSocket): TConnectionState;
 const
-  ECONNREFUSED = {$IfDef WINDOWS}WSAECONNREFUSED{$ELSE}ESysECONNREFUSED{$EndIf};
+  {$IFDEF WINDOWS}
+  ECONNREFUSED = WSAECONNREFUSED;
+  {$ENDIF}
+  
+  {$IFDEF UNIX}
+  ECONNREFUSED = ESysECONNREFUSED;
+  {$EndIf}
+  
+  {$IFNDEF FULL_IP_STACK}
+  ECONNREFUSED = -999;
+  {$ENDIF}
 begin
   if (ASocket.Protocol <> spStream) then
     Exit(csNotConnected);

+ 1 - 3
packages/fcl-net/src/ssockets.pp

@@ -966,9 +966,7 @@ begin
 {$elseif defined(windows) or defined(hasamiga)}
   CloseSocket(FSocket);
 {$else}
-  {$WARNING Method Abort is not tested on this platform!}
-  fpShutdown(ASocket.FD,SHUT_RDWR);
-  CloseSocket(ASocket);
+  CloseSocket(FSocket);
 {$endif}
 end;