// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "Containers/UnrealString.h" #include "CoreMinimal.h" #include "CoreTypes.h" #include "Misc/Timespan.h" #include "SocketTypes.h" #include "UObject/NameTypes.h" #include "UObject/UnrealNames.h" class FInternetAddr; /** * This is our abstract base class that hides the platform specific socket implementation */ class FSocket : public TSharedFromThis { protected: /** Indicates the type of socket this is */ const ESocketType SocketType; /** Debug description of socket usage. */ FString SocketDescription; /** Protocol used in creation of a socket */ FName SocketProtocol; public: /** Default constructor. */ SOCKETS_API FSocket(); /** * Specifies the type of socket being created * * @param InSocketType The type of socket being created * @param InSocketDescription The debug description of the socket */ UE_DEPRECATED(4.22, "Please migrate to the constructor that specifies protocol stack") inline FSocket(ESocketType InSocketType, const FString& InSocketDescription) : SocketType(InSocketType), SocketDescription(InSocketDescription), SocketProtocol(NAME_None) { } UE_DEPRECATED(4.23, "Please migrate to the constructor that takes an FName for the protocol stack") inline FSocket(ESocketType InSocketType, const FString& InSocketDescription, ESocketProtocolFamily InSocketProtocol) : SocketType(InSocketType), SocketDescription(InSocketDescription) { if (InSocketProtocol == ESocketProtocolFamily::IPv4) { SocketProtocol = FNetworkProtocolTypes::IPv4; } else if (InSocketProtocol == ESocketProtocolFamily::IPv6) { SocketProtocol = FNetworkProtocolTypes::IPv6; } else { SocketProtocol = NAME_None; } } /** * Specifies the type of socket being created * * @param InSocketType The type of socket being created * @param InSocketDescription The debug description of the socket * @param InSocketProtocol the protocol stack this socket should be created on. */ SOCKETS_API FSocket(ESocketType InSocketType, const FString& InSocketDescription, const FName& InSocketProtocol); /** Virtual destructor. */ SOCKETS_API virtual ~FSocket(); /** * Shuts down the socket, making it unusable for reads and/or writes. This does not close the socket! * * @param Types * @return true if successful, false otherwise. */ virtual bool Shutdown(ESocketShutdownMode Mode) = 0; /** * Closes the socket * * @return true if it closes without errors, false otherwise. */ virtual bool Close() = 0; /** * Binds a socket to a network byte ordered address. * * @param Addr The address to bind to. * @return true if successful, false otherwise. */ virtual bool Bind(const FInternetAddr& Addr) = 0; /** * Connects a socket to a network byte ordered address. * * @param Addr The address to connect to. * @return true if successful, false otherwise. */ virtual bool Connect(const FInternetAddr& Addr) = 0; /** * Places the socket into a state to listen for incoming connections. * * @param MaxBacklog The number of connections to queue before refusing them. * @return true if successful, false otherwise. */ virtual bool Listen(int32 MaxBacklog) = 0; /** * Waits for a pending connection on the socket. * * @param out bHasPendingConnection Will indicate whether a connection is pending or not. * @param WaitTime The maximum time to wait for a connection. If zero, the function will not * wait and will return immediately with a value in bHasPendingConnection. * @return true if successful, false otherwise. */ virtual bool WaitForPendingConnection(bool& bHasPendingConnection, const FTimespan& WaitTime) = 0; /** * Queries the socket to determine if there is a pending connection. * * @param bHasPendingConnection Will indicate whether a connection is pending or not. * @return true if successful, false otherwise. */ bool HasPendingConnection(bool& bHasPendingConnection) { return WaitForPendingConnection(bHasPendingConnection, FTimespan::Zero()); } /** * Queries the socket to determine if there is pending data on the queue. * * @param PendingDataSize Will indicate how much data is on the pipe for a single recv call. * @return true if the socket has data, false otherwise. */ virtual bool HasPendingData(uint32& PendingDataSize) = 0; /** * Accepts a connection that is pending. * * @param SocketDescription Debug description of socket, * @return The new (heap-allocated) socket, or nullptr if unsuccessful. */ virtual class FSocket* Accept(const FString& InSocketDescription) = 0; /** * Accepts a connection that is pending. * * @param OutAddr The address of the connection. * @param SocketDescription Debug description of socket. * @return The new (heap-allocated) socket, or nullptr if unsuccessful. */ virtual class FSocket* Accept(FInternetAddr& OutAddr, const FString& InSocketDescription) = 0; /** * Sends a buffer to a network byte ordered address. * * @param Data The buffer to send. * @param Count The size of the data to send. * @param BytesSent Will indicate how much was sent. * @param Destination The network byte ordered address to send to. */ SOCKETS_API virtual bool SendTo(const uint8* Data, int32 Count, int32& BytesSent, const FInternetAddr& Destination); /** * Sends a buffer on a connected socket. * * @param Data The buffer to send. * @param Count The size of the data to send. * @param BytesSent Will indicate how much was sent. */ SOCKETS_API virtual bool Send(const uint8* Data, int32 Count, int32& BytesSent); /** * Reads a chunk of data from the socket and gathers the source address. * * A return value of 'true' does not necessarily mean that data was returned. * Callers must check the 'BytesRead' parameter for the actual amount of data * returned. A value of zero indicates that there was no data available for reading. * * @param Data The buffer to read into. * @param BufferSize The max size of the buffer. * @param BytesRead Will indicate how many bytes were read from the socket. * @param Source Will contain the receiving the address of the sender of the data. * @param Flags The receive flags. * @return true on success, false in case of a closed socket or an unrecoverable error. */ SOCKETS_API virtual bool RecvFrom(uint8* Data, int32 BufferSize, int32& BytesRead, FInternetAddr& Source, ESocketReceiveFlags::Type Flags = ESocketReceiveFlags::None); /** * Reads a chunk of data from a connected socket * * A return value of 'true' does not necessarily mean that data was returned. * Callers must check the 'BytesRead' parameter for the actual amount of data * returned. A value of zero indicates that there was no data available for reading. * * @param Data The buffer to read into * @param BufferSize The max size of the buffer * @param BytesRead Will indicate how many bytes were read from the socket * @param Flags the receive flags * @return true on success, false in case of a closed socket or an unrecoverable error. */ SOCKETS_API virtual bool Recv(uint8* Data, int32 BufferSize, int32& BytesRead, ESocketReceiveFlags::Type Flags = ESocketReceiveFlags::None); /** * Reads multiple packets from the socket at once, gathering the source address and other optional platform specific data. * Use ISocketSubsystem::IsSocketRecvMultiSupported to check if the current socket platform supports this. * NOTE: For optimal performance, one FRecvMulti instance should be used, for the lifetime of the socket. * * @param MultiData The FRecvMulti instance that receives packet data and holds platform specific buffers for receiving data. * @param Flags The receive flags. * @return Whether or not data was successfully received */ SOCKETS_API virtual bool RecvMulti(FRecvMulti& MultiData, ESocketReceiveFlags::Type Flags=ESocketReceiveFlags::None); /** * Blocks until the specified condition is met. * * @param Condition The condition to wait for. * @param WaitTime The maximum time to wait. * @return true if the condition was met, false if the time limit expired or an error occurred. */ virtual bool Wait(ESocketWaitConditions::Type Condition, FTimespan WaitTime) = 0; /** * Determines the connection state of the socket. * * @return Connection state. */ virtual ESocketConnectionState GetConnectionState() = 0; /** * Reads the address the socket is bound to and returns it. * * @param OutAddr The address the socket is bound to. */ virtual void GetAddress(FInternetAddr& OutAddr) = 0; /** * Reads the address of the peer the socket is connected to. * * @param OutAddr Address of the peer the socket is connected to. * @return true if the address was retrieved correctly, false otherwise. */ virtual bool GetPeerAddress(FInternetAddr& OutAddr) = 0; /** * Sets this socket into non-blocking mode. * * @param bIsNonBlocking Whether to enable blocking or not. * @return true if successful, false otherwise. */ virtual bool SetNonBlocking(bool bIsNonBlocking = true) = 0; /** * Sets a socket into broadcast mode (UDP only). * * @param bAllowBroadcast Whether to enable broadcast or not. * @return true if successful, false otherwise. */ virtual bool SetBroadcast(bool bAllowBroadcast = true) = 0; /** * Sets this socket into TCP_NODELAY mode (TCP only). * * @param bIsNoDelay Whether to enable no delay mode. * @return true if successful, false otherwise. */ virtual bool SetNoDelay(bool bIsNoDelay = true) = 0; /** * Joins this socket to the specified multicast group. * * The multicast group address must be in the range 224.0.0.0 to 239.255.255.255. * * @param GroupAddress The IP address of the multicast group. * @return true on success, false otherwise. * @see LeaveMulticastGroup, SetMulticastLoopback, SetMulticastTtl */ virtual bool JoinMulticastGroup(const FInternetAddr& GroupAddress) = 0; /** * Joins this socket to the specified multicast group on the specified interface. * * The multicast group address must be in the range 224.0.0.0 to 239.255.255.255. * * @param GroupAddress The IP address of the multicast group. * @param InterfaceAddress The address representing the interface. * @return true on success, false otherwise. * @see LeaveMulticastGroup, SetMulticastLoopback, SetMulticastTtl */ virtual bool JoinMulticastGroup(const FInternetAddr& GroupAddress, const FInternetAddr& InterfaceAddress) = 0; /** * Removes this UDP client from the specified multicast group. * * @param The multicast group address to leave. * @return true on success, false otherwise. * @see JoinMulticastGroup, SetMulticastLoopback, SetMulticastTtl */ virtual bool LeaveMulticastGroup(const FInternetAddr& GroupAddress) = 0; /** * Removes this UDP client from the specified multicast group on the specified interface. * * @param GroupAddress The multicast group address to leave. * @param InterfaceAddress The address representing the interface. * @return true on success, false otherwise. * @see JoinMulticastGroup, SetMulticastLoopback, SetMulticastTtl */ virtual bool LeaveMulticastGroup(const FInternetAddr& GroupAddress, const FInternetAddr& InterfaceAddress) = 0; /** * Enables or disables multicast loopback on the socket (UDP only). * * This setting determines whether multicast datagrams are looped * back to the sending socket. By default, multicast loopback is * enabled. It must be enabled if more than one listener is present * on a host. * * @param bLoopback Whether loopback should be enabled. * @see LeaveMulticastGroup, JoinMulticastGroup, SetMulticastTtl */ virtual bool SetMulticastLoopback(bool bLoopback) = 0; /** * Sets the time to live (TTL) for multicast datagrams. * * The default TTL for multicast datagrams is 1, which prevents them * from being forwarded beyond the local subnet. Higher values will * allow multicast datagrams to be sent into neighboring subnets, if * multicast capable routers are present. * * @param TimeToLive Number of hops the datagram can make. * @see LeaveMulticastGroup, JoinMulticastGroup, SetMulticastLoopback */ virtual bool SetMulticastTtl(uint8 TimeToLive) = 0; /** * Sets the interface used to send outgoing multicast datagrams. * * Multicast traffic is sent using the default interface, this allows * to explicitly set the interface used to send outgoing multicast datagrams. * * @param InterfaceAddress The interface address. * @return true if the call succeeded, false otherwise. */ virtual bool SetMulticastInterface(const FInternetAddr& InterfaceAddress) = 0; /** * Sets whether a socket can be bound to an address in use. * * @param bAllowReuse Whether to allow reuse or not. * @return true if the call succeeded, false otherwise. */ virtual bool SetReuseAddr(bool bAllowReuse = true) = 0; /** * Sets whether and how long a socket will linger after closing. * * @param bShouldLinger Whether to have the socket remain open for a time period after closing or not. * @param Timeout The amount of time to linger before closing. * @return true if the call succeeded, false otherwise. */ virtual bool SetLinger(bool bShouldLinger = true, int32 Timeout = 0) = 0; /** * Enables error queue support for the socket. * * @param bUseErrorQueue Whether to enable error queuing or not. * @return true if the call succeeded, false otherwise. */ virtual bool SetRecvErr(bool bUseErrorQueue = true) = 0; /** * Sets the size of the send buffer to use. * * @param Size The size to change it to. * @param NewSize Will contain the size that was set (in case OS can't set that). * @return true if the call succeeded, false otherwise. */ virtual bool SetSendBufferSize(int32 Size, int32& NewSize) = 0; /** * Sets the size of the receive buffer to use. * * @param Size The size to change it to. * @param NewSize Will contain the size that was set (in case OS can't set that). * @return true if the call succeeded, false otherwise. */ virtual bool SetReceiveBufferSize(int32 Size, int32& NewSize) = 0; /** * Sets whether to retrieve the system-level receive timestamp, for sockets * * @param bRetrieveTimestamp Whether to retrieve the timestamp upon receive * @return True if the call succeeded, false otherwise. */ SOCKETS_API virtual bool SetRetrieveTimestamp(bool bRetrieveTimestamp=true); /** * Reads the port this socket is bound to. * * @return Port number. * @see GetSocketType, GetDescription */ virtual int32 GetPortNo() = 0; /** * Sets whether to enable IP_PKTINFO support * * @param bEnable Whether to enable/disable * @return True if the call succeeded, false otherwise. */ SOCKETS_API virtual bool SetIpPktInfo(bool bEnable); /** * Reads a chunk of data from the socket and gathers the source address and the destination using IP_PKTINFO * * A return value of 'true' does not necessarily mean that data was returned. * Callers must check the 'BytesRead' parameter for the actual amount of data * returned. A value of zero indicates that there was no data available for reading. * * @param Data The buffer to read into. * @param BufferSize The max size of the buffer. * @param BytesRead Will indicate how many bytes were read from the socket. * @param Source Will contain the receiving the address of the sender of the data. * @param Destination Will contain the destination address used by the sender of the data. * @param Flags The receive flags. * @return true on success, false in case of a closed socket or an unrecoverable error. */ SOCKETS_API virtual bool RecvFromWithPktInfo(uint8* Data, int32 BufferSize, int32& BytesRead, FInternetAddr& Source, FInternetAddr& Destination, ESocketReceiveFlags::Type Flags = ESocketReceiveFlags::None); /** * Get the type of protocol the socket is bound to * * @return Socket type. * @see GetDescription, GetPortNo */ FORCEINLINE ESocketType GetSocketType() const { return SocketType; } /** * Get the debug description of the socket. * * @return Debug string. * @see GetPortNo, GetSocketType */ FORCEINLINE FString GetDescription() const { return SocketDescription; } /** * Get the type of protocol the socket is bound to * * @return Socket type. * @see GetDescription, GetPortNo */ FORCEINLINE FName GetProtocol() const { return SocketProtocol; } };