You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
Updates the SocketSubsystem to better support multiple protocol types and handling platforms that are locked to a specific protocol as well. Also removes the enum usage in the sockets/subsystem classes which reverts and better implements 4504445. #JIRA: UE-68869, UENET-911, UENET-891 #rb: ryan.gerleve [CL 4849963 by Jake Leonard in Dev-Networking branch]
196 lines
5.2 KiB
C++
196 lines
5.2 KiB
C++
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "Unix/SocketSubsystemUnix.h"
|
|
#include "Misc/CommandLine.h"
|
|
#include "SocketSubsystemModule.h"
|
|
#include "BSDSockets/IPAddressBSD.h"
|
|
#include "BSDSockets/SocketsBSD.h"
|
|
|
|
#include <ifaddrs.h>
|
|
#include <net/if.h>
|
|
|
|
FSocketSubsystemUnix* FSocketSubsystemUnix::SocketSingleton = NULL;
|
|
|
|
FName CreateSocketSubsystem( FSocketSubsystemModule& SocketSubsystemModule )
|
|
{
|
|
FName SubsystemName(TEXT("UNIX"));
|
|
// Create and register our singleton factor with the main online subsystem for easy access
|
|
FSocketSubsystemUnix* SocketSubsystem = FSocketSubsystemUnix::Create();
|
|
FString Error;
|
|
if (SocketSubsystem->Init(Error))
|
|
{
|
|
SocketSubsystemModule.RegisterSocketSubsystem(SubsystemName, SocketSubsystem);
|
|
return SubsystemName;
|
|
}
|
|
else
|
|
{
|
|
FSocketSubsystemUnix::Destroy();
|
|
return NAME_None;
|
|
}
|
|
}
|
|
|
|
void DestroySocketSubsystem( FSocketSubsystemModule& SocketSubsystemModule )
|
|
{
|
|
SocketSubsystemModule.UnregisterSocketSubsystem(FName(TEXT("UNIX")));
|
|
FSocketSubsystemUnix::Destroy();
|
|
}
|
|
|
|
/**
|
|
* Singleton interface for the Android socket subsystem
|
|
* @return the only instance of the Android socket subsystem
|
|
*/
|
|
FSocketSubsystemUnix* FSocketSubsystemUnix::Create()
|
|
{
|
|
if (SocketSingleton == NULL)
|
|
{
|
|
SocketSingleton = new FSocketSubsystemUnix();
|
|
}
|
|
|
|
return SocketSingleton;
|
|
}
|
|
|
|
/**
|
|
* Destroy the singleton Android socket subsystem
|
|
*/
|
|
void FSocketSubsystemUnix::Destroy()
|
|
{
|
|
if (SocketSingleton != NULL)
|
|
{
|
|
SocketSingleton->Shutdown();
|
|
delete SocketSingleton;
|
|
SocketSingleton = NULL;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Does Unix platform initialization of the sockets library
|
|
*
|
|
* @param Error a string that is filled with error information
|
|
*
|
|
* @return TRUE if initialized ok, FALSE otherwise
|
|
*/
|
|
bool FSocketSubsystemUnix::Init(FString& Error)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Performs Android specific socket clean up
|
|
*/
|
|
void FSocketSubsystemUnix::Shutdown(void)
|
|
{
|
|
}
|
|
|
|
|
|
/**
|
|
* @return Whether the device has a properly configured network device or not
|
|
*/
|
|
bool FSocketSubsystemUnix::HasNetworkDevice()
|
|
{
|
|
// @TODO: implement
|
|
return true;
|
|
}
|
|
|
|
FSocket* FSocketSubsystemUnix::CreateSocket(const FName& SocketType, const FString& SocketDescription, const FName& ProtocolType)
|
|
{
|
|
FSocketBSD* NewSocket = (FSocketBSD*)FSocketSubsystemBSD::CreateSocket(SocketType, SocketDescription, ProtocolType);
|
|
|
|
if (NewSocket != nullptr)
|
|
{
|
|
NewSocket->SetIPv6Only(false);
|
|
}
|
|
else
|
|
{
|
|
UE_LOG(LogSockets, Warning, TEXT("Failed to create socket %s [%s]"), *SocketType.ToString(), *SocketDescription);
|
|
}
|
|
|
|
return NewSocket;
|
|
}
|
|
|
|
TSharedRef<FInternetAddr> FSocketSubsystemUnix::GetLocalHostAddr(FOutputDevice& Out, bool& bCanBindAll)
|
|
{
|
|
bCanBindAll = true;
|
|
|
|
TArray<TSharedPtr<FInternetAddr>> ResultArray;
|
|
if (GetLocalAdapterAddresses(ResultArray))
|
|
{
|
|
if (FParse::Param(FCommandLine::Get(), TEXT("PRIMARYNET")) || FParse::Param(FCommandLine::Get(), TEXT("MULTIHOME")))
|
|
{
|
|
bCanBindAll = false;
|
|
}
|
|
|
|
UE_LOG(LogSockets, Verbose, TEXT("Local address is %s"), *(ResultArray[0]->ToString(false)));
|
|
return ResultArray[0]->Clone();
|
|
}
|
|
else
|
|
{
|
|
UE_LOG(LogSockets, Warning, TEXT("GetLocalAdapterAddresses had no results!"));
|
|
}
|
|
|
|
// Fall back to this.
|
|
TSharedRef<FInternetAddr> Addr = CreateInternetAddr();
|
|
Addr->SetAnyAddress();
|
|
return Addr;
|
|
}
|
|
|
|
bool FSocketSubsystemUnix::GetLocalAdapterAddresses(TArray<TSharedPtr<FInternetAddr> >& OutAddresses)
|
|
{
|
|
TSharedRef<FInternetAddr> MultihomeAddress = FSocketSubsystemBSD::CreateInternetAddr();
|
|
bool bHasMultihome = GetMultihomeAddress(MultihomeAddress);
|
|
|
|
// Multihome addresses should always be the first in the array.
|
|
if (bHasMultihome)
|
|
{
|
|
OutAddresses.Add(MultihomeAddress);
|
|
}
|
|
|
|
ifaddrs* Interfaces = NULL;
|
|
int InterfaceQueryRet = getifaddrs(&Interfaces);
|
|
UE_LOG(LogSockets, Verbose, TEXT("Querying net interfaces returned: %d"), InterfaceQueryRet);
|
|
if (InterfaceQueryRet == 0)
|
|
{
|
|
// Loop through linked list of interfaces
|
|
for (ifaddrs* Travel = Interfaces; Travel != NULL; Travel = Travel->ifa_next)
|
|
{
|
|
// Skip over empty data sets.
|
|
if (Travel->ifa_addr == NULL)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
uint16 AddrFamily = Travel->ifa_addr->sa_family;
|
|
// Find any up and non-loopback addresses
|
|
if ((Travel->ifa_flags & IFF_UP) != 0 &&
|
|
(Travel->ifa_flags & IFF_LOOPBACK) == 0 &&
|
|
(AddrFamily == AF_INET || AddrFamily == AF_INET6))
|
|
{
|
|
TSharedRef<FInternetAddrBSD> NewAddress = MakeShareable(new FInternetAddrBSD(this));
|
|
NewAddress->SetIp(*((sockaddr_storage*)Travel->ifa_addr));
|
|
uint32 AddressInterface = ntohl(if_nametoindex(Travel->ifa_name));
|
|
|
|
// Write the scope id if what we found was the multihome address.
|
|
// Don't write it to our list again though.
|
|
if (bHasMultihome && NewAddress == MultihomeAddress)
|
|
{
|
|
StaticCastSharedRef<FInternetAddrBSD>(MultihomeAddress)->SetScopeId(AddressInterface);
|
|
}
|
|
else
|
|
{
|
|
NewAddress->SetScopeId(AddressInterface);
|
|
OutAddresses.Add(NewAddress);
|
|
}
|
|
UE_LOG(LogSockets, Verbose, TEXT("Got Address %s on interface %d"), *(NewAddress->ToString(false)), AddressInterface);
|
|
}
|
|
}
|
|
|
|
freeifaddrs(Interfaces);
|
|
}
|
|
else
|
|
{
|
|
UE_LOG(LogSockets, Warning, TEXT("getifaddrs returned result %d"), InterfaceQueryRet);
|
|
return bHasMultihome; // if getifaddrs somehow doesn't work but we have multihome, then it's fine.
|
|
}
|
|
|
|
return (OutAddresses.Num() > 0);
|
|
}
|