|
@@ -18,6 +18,13 @@ unit fpsockets;
|
|
{$mode ObjFPC}{$H+}
|
|
{$mode ObjFPC}{$H+}
|
|
{$TypedAddress on}
|
|
{$TypedAddress on}
|
|
{$modeswitch advancedrecords}
|
|
{$modeswitch advancedrecords}
|
|
|
|
+{$macro on}
|
|
|
|
+
|
|
|
|
+{$IFDEF FPC_DOTTEDUNITS}
|
|
|
|
+{$define socketsunit:=System.Net.Sockets}
|
|
|
|
+{$ELSE FPC_DOTTEDUNITS}
|
|
|
|
+{$define socketsunit:=sockets}
|
|
|
|
+{$ENDIF FPC_DOTTEDUNITS}
|
|
|
|
|
|
interface
|
|
interface
|
|
|
|
|
|
@@ -221,8 +228,14 @@ function ConnectionState(const ASocket: TFPSocket): TConnectionState;
|
|
|
|
|
|
type
|
|
type
|
|
PAddressUnion = ^TAddressUnion;
|
|
PAddressUnion = ^TAddressUnion;
|
|
|
|
+
|
|
|
|
+ { TAddressUnion }
|
|
|
|
+
|
|
TAddressUnion = record
|
|
TAddressUnion = record
|
|
- case TFPSocketType of
|
|
|
|
|
|
+ function GetAddr : socketsunit.psockaddr;
|
|
|
|
+ function GetAddrSize : cint;
|
|
|
|
+ procedure GetAddrAndSize(out aAddr: socketsunit.pSockAddr;out aSize: cint);
|
|
|
|
+ case SocketType : TFPSocketType of
|
|
stIPv4: (In4Addr: sockaddr_in);
|
|
stIPv4: (In4Addr: sockaddr_in);
|
|
stIPv6: (In6Addr: sockaddr_in6);
|
|
stIPv6: (In6Addr: sockaddr_in6);
|
|
stUnixSocket: (UnixAddr: sockaddr_un);
|
|
stUnixSocket: (UnixAddr: sockaddr_un);
|
|
@@ -245,13 +258,6 @@ uses
|
|
math;
|
|
math;
|
|
{$ENDIF FPC_DOTTEDUNITS}
|
|
{$ENDIF FPC_DOTTEDUNITS}
|
|
|
|
|
|
-{$macro on}
|
|
|
|
-{$IFDEF FPC_DOTTEDUNITS}
|
|
|
|
-{$define socketsunit:=System.Net.Sockets}
|
|
|
|
-{$ELSE FPC_DOTTEDUNITS}
|
|
|
|
-{$define socketsunit:=sockets}
|
|
|
|
-{$ENDIF FPC_DOTTEDUNITS}
|
|
|
|
-
|
|
|
|
{ Helper }
|
|
{ Helper }
|
|
|
|
|
|
const
|
|
const
|
|
@@ -286,12 +292,14 @@ begin
|
|
AAddress := IN4MappedIN6Address(AAddress.Address);
|
|
AAddress := IN4MappedIN6Address(AAddress.Address);
|
|
if AAddress.AddressType = atIN4 then
|
|
if AAddress.AddressType = atIN4 then
|
|
begin
|
|
begin
|
|
|
|
+ Result.SocketType:=stIPv4;
|
|
Result.In4Addr.sin_family := AF_INET;
|
|
Result.In4Addr.sin_family := AF_INET;
|
|
Result.In4Addr.sin_port := HToNS(APort);
|
|
Result.In4Addr.sin_port := HToNS(APort);
|
|
Result.In4Addr.sin_addr.s_addr := LongWord(StrToNetAddr(AAddress.Address));
|
|
Result.In4Addr.sin_addr.s_addr := LongWord(StrToNetAddr(AAddress.Address));
|
|
end
|
|
end
|
|
else if AAddress.AddressType = atIN6 then
|
|
else if AAddress.AddressType = atIN6 then
|
|
begin
|
|
begin
|
|
|
|
+ Result.SocketType:=stIPv6;
|
|
Result.In6Addr.sin6_family := AF_INET6;
|
|
Result.In6Addr.sin6_family := AF_INET6;
|
|
Result.In6Addr.sin6_port := HToNS(APort);
|
|
Result.In6Addr.sin6_port := HToNS(APort);
|
|
Result.In6Addr.sin6_addr := StrToHostAddr6(AAddress.Address);
|
|
Result.In6Addr.sin6_addr := StrToHostAddr6(AAddress.Address);
|
|
@@ -300,6 +308,7 @@ begin
|
|
end
|
|
end
|
|
else if AAddress.AddressType = atUnixSock then
|
|
else if AAddress.AddressType = atUnixSock then
|
|
begin
|
|
begin
|
|
|
|
+ Result.SocketType:=stUnixSocket;
|
|
if Length(AAddress.Address) > SizeOf(Result.UnixAddr.sun_path)-1 then
|
|
if Length(AAddress.Address) > SizeOf(Result.UnixAddr.sun_path)-1 then
|
|
raise EUnsupportedAddress.Create('Unix address should be at most 108 characters');
|
|
raise EUnsupportedAddress.Create('Unix address should be at most 108 characters');
|
|
Result.UnixAddr.sun_family := AF_UNIX;
|
|
Result.UnixAddr.sun_family := AF_UNIX;
|
|
@@ -540,11 +549,14 @@ procedure Bind(const ASocket: TFPSocket; const AAddress: TNetworkAddress;
|
|
var
|
|
var
|
|
enableReuse: Integer = 1;
|
|
enableReuse: Integer = 1;
|
|
addr: TAddressUnion;
|
|
addr: TAddressUnion;
|
|
|
|
+ addrptr : socketsunit.psockaddr;
|
|
|
|
+ addrlen : cint;
|
|
begin
|
|
begin
|
|
if ReuseAddr then
|
|
if ReuseAddr then
|
|
fpsetsockopt(ASocket.FD, SOL_SOCKET, SO_REUSEADDR, @enableReuse, SizeOf(enableReuse));
|
|
fpsetsockopt(ASocket.FD, SOL_SOCKET, SO_REUSEADDR, @enableReuse, SizeOf(enableReuse));
|
|
addr := CreateAddr(AAddress, APort, ASocket.SocketType = stIPDualStack);
|
|
addr := CreateAddr(AAddress, APort, ASocket.SocketType = stIPDualStack);
|
|
- if fpbind(ASocket.FD, socketsunit.PSockAddr(@addr), SizeOf(addr)) <> 0 then raise
|
|
|
|
|
|
+ addr.GetAddrAndSize(addrptr,addrlen);
|
|
|
|
+ if fpbind(ASocket.FD, addrptr, addrlen) <> 0 then raise
|
|
ESocketCodeError.Create(socketerror, 'bind (%s:%d)'.Format([AAddress.Address, APort]));
|
|
ESocketCodeError.Create(socketerror, 'bind (%s:%d)'.Format([AAddress.Address, APort]));
|
|
end;
|
|
end;
|
|
|
|
|
|
@@ -557,7 +569,7 @@ end;
|
|
function AcceptConnection(const ASocket: TFPSocket): TFPSocketConnection;
|
|
function AcceptConnection(const ASocket: TFPSocket): TFPSocketConnection;
|
|
var
|
|
var
|
|
addr: TAddressUnion;
|
|
addr: TAddressUnion;
|
|
- addrLen: TSocklen = SizeOf(addr);
|
|
|
|
|
|
+ addrLen: TSocklen;
|
|
begin
|
|
begin
|
|
Result.Socket.FD := fpaccept(ASocket.FD, socketsunit.psockaddr(@addr), @addrLen);
|
|
Result.Socket.FD := fpaccept(ASocket.FD, socketsunit.psockaddr(@addr), @addrLen);
|
|
if SocketInvalid(Result.Socket.FD) then
|
|
if SocketInvalid(Result.Socket.FD) then
|
|
@@ -588,8 +600,8 @@ function Connect(const ASocket: TFPSocket; const AAddress: TNetworkAddress;
|
|
APort: Word): TConnectionState;
|
|
APort: Word): TConnectionState;
|
|
var
|
|
var
|
|
addr: TAddressUnion;
|
|
addr: TAddressUnion;
|
|
- addrlen : cint;
|
|
|
|
- addrptr : socketsunit.psockaddr;
|
|
|
|
|
|
+ AddrLen : cint;
|
|
|
|
+ addrPtr : socketsunit.psockaddr;
|
|
|
|
|
|
const
|
|
const
|
|
{$IFDEF WINDOWS}
|
|
{$IFDEF WINDOWS}
|
|
@@ -617,24 +629,7 @@ const
|
|
{$ENDIF}
|
|
{$ENDIF}
|
|
begin
|
|
begin
|
|
addr := CreateAddr(AAddress, APort, ASocket.SocketType = stIPDualStack);
|
|
addr := CreateAddr(AAddress, APort, ASocket.SocketType = stIPDualStack);
|
|
- case ASocket.SocketType of
|
|
|
|
- stIPv4,
|
|
|
|
- stIPDualStack:
|
|
|
|
- begin
|
|
|
|
- addrlen:=sizeof(sockaddr_in);
|
|
|
|
- addrptr:=psockaddr(@addr.In4Addr);
|
|
|
|
- end;
|
|
|
|
- stIPv6 :
|
|
|
|
- begin
|
|
|
|
- addrlen:=sizeof(sockaddr_in6);
|
|
|
|
- addrptr:=psockaddr(@addr.In6Addr);
|
|
|
|
- end;
|
|
|
|
- stUnixSocket :
|
|
|
|
- begin
|
|
|
|
- addrlen:=sizeof(sockaddr_un);
|
|
|
|
- addrptr:=psockaddr(@addr.UnixAddr);
|
|
|
|
- end;
|
|
|
|
- end;
|
|
|
|
|
|
+ Addr.GetAddrAndSize(addrPtr,AddrLen);
|
|
if fpconnect(ASocket.FD, addrptr, addrlen) <> 0 then
|
|
if fpconnect(ASocket.FD, addrptr, addrlen) <> 0 then
|
|
case socketerror of
|
|
case socketerror of
|
|
EALREADY,
|
|
EALREADY,
|
|
@@ -1265,5 +1260,41 @@ begin
|
|
FExpectedSize := AExpected;
|
|
FExpectedSize := AExpected;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+{ TAddressUnion }
|
|
|
|
+
|
|
|
|
+function TAddressUnion.GetAddr: socketsunit.psockaddr;
|
|
|
|
+begin
|
|
|
|
+ case SocketType of
|
|
|
|
+ stIPv4,
|
|
|
|
+ stIPDualStack:
|
|
|
|
+ Result:=psockaddr(@self.In4Addr);
|
|
|
|
+ stIPv6 :
|
|
|
|
+ Result:=psockaddr(@self.In6Addr);
|
|
|
|
+ stUnixSocket :
|
|
|
|
+ result:=psockaddr(@self.UnixAddr);
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+function TAddressUnion.GetAddrSize: cint;
|
|
|
|
+
|
|
|
|
+begin
|
|
|
|
+ case SocketType of
|
|
|
|
+ stIPv4,
|
|
|
|
+ stIPDualStack:
|
|
|
|
+ Result:=sizeof(sockaddr_in);
|
|
|
|
+ stIPv6 :
|
|
|
|
+ Result:=sizeof(sockaddr_in6);
|
|
|
|
+ stUnixSocket :
|
|
|
|
+ Result:=sizeof(sockaddr_un);
|
|
|
|
+ end;
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+procedure TAddressUnion.GetAddrAndSize(out aAddr: socketsunit.pSockAddr;out aSize: cint);
|
|
|
|
+begin
|
|
|
|
+ aAddr:=GetAddr;
|
|
|
|
+ aSize:=GetAddrSize;
|
|
|
|
+end;
|
|
|
|
+
|
|
end.
|
|
end.
|
|
|
|
|