strat: add windows socket api, linux/macos TODO

This commit is contained in:
Michael Scire 2022-03-27 14:36:31 -07:00
parent 1bef1b58d4
commit c0d5140ef0
17 changed files with 2258 additions and 28 deletions

View file

@ -0,0 +1,99 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#include <stratosphere/socket/socket_types.hpp>
#include <stratosphere/socket/socket_options.hpp>
#include <stratosphere/socket/socket_constants.hpp>
#include <stratosphere/socket/socket_errno.hpp>
namespace ams::socket::impl {
#if defined(ATMOSPHERE_OS_WINDOWS)
class PosixWinSockConverter {
private:
struct SocketData {
SOCKET winsock;
bool exempt;
bool shutdown;
constexpr SocketData() : winsock(static_cast<SOCKET>(INVALID_SOCKET)), exempt(), shutdown() { /* ... */ }
};
private:
os::SdkMutex m_mutex{};
SocketData m_data[MaxSocketsPerClient]{};
private:
static constexpr int GetInitialIndex(SOCKET winsock) {
/* The lower 2 bits of a winsock are always zero; Nintendo uses the upper bits as a hashmap index into m_data. */
return (winsock >> 2) % MaxSocketsPerClient;
}
public:
constexpr PosixWinSockConverter() = default;
s32 AcquirePosixHandle(SOCKET winsock, bool exempt = false);
s32 GetShutdown(bool &shutdown, s32 posix);
s32 GetSocketExempt(bool &exempt, s32 posix);
SOCKET PosixToWinsockSocket(s32 posix);
void ReleaseAllPosixHandles();
void ReleasePosixHandle(s32 posix);
s32 SetShutdown(s32 posix, bool shutdown);
s32 SetSocketExempt(s32 posix, bool exempt);
s32 WinsockToPosixSocket(SOCKET winsock);
};
s32 MapProtocolValue(Protocol protocol);
Protocol MapProtocolValue(s32 protocol);
s32 MapTypeValue(Type type);
Type MapTypeValue(s32 type);
s8 MapFamilyValue(Family family);
Family MapFamilyValue(s8 family);
s32 MapMsgFlagValue(MsgFlag flag);
MsgFlag MapMsgFlagValue(s32 flag);
u32 MapAddrInfoFlagValue(AddrInfoFlag flag);
AddrInfoFlag MapAddrInfoFlagValue(u32 flag);
u32 MapShutdownMethodValue(ShutdownMethod how);
ShutdownMethod MapShutdownMethodValue(u32 how);
u32 MapFcntlFlagValue(FcntlFlag flag);
FcntlFlag MapFcntlFlagValue(u32 flag);
s32 MapLevelValue(Level level);
Level MapLevelValue(s32 level);
s32 MapOptionValue(Level level, Option option);
Option MapOptionValue(s32 level, s32 option);
s32 MapErrnoValue(Errno error);
Errno MapErrnoValue(s32 error);
#endif
#define AMS_SOCKET_IMPL_DECLARE_CONVERSION(AMS, PLATFORM) \
void CopyToPlatform(PLATFORM *dst, const AMS *src); \
void CopyFromPlatform(AMS *dst, const PLATFORM *src);
AMS_SOCKET_IMPL_DECLARE_CONVERSION(SockAddrIn, sockaddr_in);
AMS_SOCKET_IMPL_DECLARE_CONVERSION(TimeVal, timeval);
AMS_SOCKET_IMPL_DECLARE_CONVERSION(Linger, linger);
#undef AMS_SOCKET_IMPL_DECLARE_CONVERSION
}

View file

@ -49,6 +49,8 @@ namespace ams::socket {
s32 Accept(s32 desc, SockAddr *out_address, SockLenT *out_addr_len);
s32 Bind(s32 desc, const SockAddr *address, SockLenT len);
s32 Connect(s32 desc, const SockAddr *address, SockLenT len);
s32 GetSockName(s32 desc, SockAddr *out_address, SockLenT *out_addr_len);
s32 SetSockOpt(s32 desc, Level level, Option option_name, const void *option_value, SockLenT option_size);

View file

@ -21,6 +21,8 @@ namespace ams::socket {
constexpr inline s32 InvalidSocket = -1;
constexpr inline s32 SocketError = -1;
constexpr inline u32 MaxSocketsPerClient = 0x80;
constexpr inline auto DefaultTcpAutoBufferSizeMax = 192_KB;
constexpr inline auto MinTransferMemorySize = (2 * DefaultTcpAutoBufferSizeMax + 128_KB);
constexpr inline auto MinSocketAllocatorSize = 128_KB;

View file

@ -19,21 +19,143 @@
namespace ams::socket {
enum class Errno : u32 {
ESuccess = 0,
ESuccess = 0,
EPerm = 1,
ENoEnt = 2,
ESrch = 3,
EIntr = 4,
EIo = 5,
ENxIo = 6,
E2Big = 7,
ENoExec = 8,
EBadf = 9,
EChild = 10,
EAgain = 11,
EWouldBlock = EAgain,
ENoMem = 12,
EAcces = 13,
EFault = 14,
ENotBlk = 15,
EBusy = 16,
EExist = 17,
EXDev = 18,
ENoDev = 19,
ENotDir = 20,
EIsDir = 21,
EInval = 22,
ENFile = 23,
EMFile = 24,
ENotTy = 25,
ETxtBsy = 26,
EFBig = 27,
ENoSpc = 28,
ESPipe = 29,
ERofs = 30,
EMLink = 31,
EPipe = 32,
EDom = 33,
ERange = 34,
EDeadLk = 35,
EDeadLock = EDeadLk,
ENameTooLong = 36,
ENoLck = 37,
ENoSys = 38,
ENotEmpty = 39,
ELoop = 40,
ENoMsg = 42,
EIdrm = 43,
EChrng = 44,
EL2NSync = 45,
EL3Hlt = 46,
EL3Rst = 47,
ELnrng = 48,
EUnatch = 49,
ENoCsi = 50,
EL2Hlt = 51,
EBade = 52,
EBadr = 53,
EXFull = 54,
ENoAno = 55,
EBadRqc = 56,
EBadSsl = 57,
EBFont = 59,
ENoStr = 60,
ENoData = 61,
ETime = 62,
ENoSr = 63,
ENoNet = 64,
ENoPkg = 65,
ERemote = 66,
ENoLink = 67,
EAdv = 68,
ESrmnt = 69,
EComm = 70,
EProto = 71,
EMultiHop = 72,
EDotDot = 73,
EBadMsg = 74,
EOverflow = 75,
ENotUnuq = 76,
EBadFd = 77,
ERemChg = 78,
ELibAcc = 79,
ELibBad = 80,
ELibScn = 81,
ELibMax = 82,
ELibExec = 83,
EIlSeq = 84,
ERestart = 85,
EStrPipe = 86,
EUsers = 87,
ENotSock = 88,
EDestAddrReq = 89,
EMsgSize = 90,
EPrototype = 91,
ENoProtoOpt = 92,
EProtoNoSupport = 93,
ESocktNoSupport = 94,
EOpNotSupp = 95,
ENotSup = EOpNotSupp,
EPfNoSupport = 96,
EAfNoSupport = 97,
EAddrInUse = 98,
EAddrNotAvail = 99,
ENetDown = 100,
ENetUnreach = 101,
ENetReset = 102,
EConnAborted = 103,
EConnReset = 104,
ENoBufs = 105,
EIsConn = 106,
ENotConn = 107,
EShutDown = 108,
ETooManyRefs = 109,
ETimedOut = 110,
EConnRefused = 111,
EHostDown = 112,
EHostUnreach = 113,
EAlready = 114,
EInProgress = 115,
EStale = 116,
EUClean = 117,
ENotNam = 118,
ENAvail = 119,
EIsNam = 120,
ERemoteIo = 121,
EDQuot = 122,
ENoMedium = 123,
EMediumType = 124,
ECanceled = 125,
ENoKey = 126,
EKeyExpired = 127,
EKeyRevoked = 128,
EKeyRejected = 129,
EOwnerDead = 130,
ENotRecoverable = 131,
ERfKill = 132,
EHwPoison = 133,
/* ... */
EAgain = 11,
ENoMem = 12,
/* ... */
EFault = 14,
/* ... */
EInval = 22,
/* ... */
ENoSpc = 28,
/* ... */
EL3Hlt = 46,
/* ... */
EOpNotSupp = 95,
ENotSup = EOpNotSupp,
EProcLim = 156,
};
enum class HErrno : s32 {

View file

@ -29,10 +29,88 @@ namespace ams::socket {
};
enum class Option : u32 {
So_Debug = (1 << 0),
/* ... */
So_ReuseAddr = (1 << 2),
/* ... */
/* ==================================== */
So_Debug = (1 << 0),
So_AcceptConn = (1 << 1),
So_ReuseAddr = (1 << 2),
So_KeepAlive = (1 << 3),
So_DontRoute = (1 << 4),
So_Broadcast = (1 << 5),
So_UseLoopback = (1 << 6),
So_Linger = (1 << 7),
So_OobInline = (1 << 8),
So_ReusePort = (1 << 9),
So_SndBuf = (1 << 12) | 0x01,
So_RcvBuf = (1 << 12) | 0x02,
So_SndLoWat = (1 << 12) | 0x03,
So_RcvLoWat = (1 << 12) | 0x04,
So_SndTimeo = (1 << 12) | 0x05,
So_RcvTimeo = (1 << 12) | 0x06,
So_Error = (1 << 12) | 0x07,
So_Type = (1 << 12) | 0x08,
So_Label = (1 << 12) | 0x09,
So_PeerLabel = (1 << 12) | 0x10,
So_ListenQLimit = (1 << 12) | 0x11,
So_ListenQLen = (1 << 12) | 0x12,
So_ListenIncQLen = (1 << 12) | 0x13,
So_SetFib = (1 << 12) | 0x14,
So_User_Cookie = (1 << 12) | 0x15,
So_Protocol = (1 << 12) | 0x16,
So_Nn_Shutdown_Exempt = (1 << 16),
So_Vendor = (1u << 31),
So_Nn_Linger = So_Vendor | 0x01,
/* ==================================== */
/* ==================================== */
Ip_Options = 1,
Ip_HdrIncl = 2,
Ip_Tos = 3,
Ip_Ttl = 4,
Ip_RecvOpts = 5,
Ip_Multicast_If = 9,
Ip_Multicast_Ttl = 10,
Ip_Multicast_Loop = 11,
Ip_Add_Membership = 12,
Ip_Drop_Membership = 13,
Ip_Multicast_Vif = 14,
Ip_Rsvp_On = 15,
Ip_Rsvp_Off = 16,
Ip_Rsvp_Vif_On = 17,
Ip_Rsvp_Vif_Off = 18,
Ip_PortRange = 19,
Ip_Faith = 22,
Ip_OnesBcast = 23,
Ip_BindAny = 24,
Ip_RecvTtl = 65,
Ip_MinTtl = 66,
Ip_DontFrag = 67,
Ip_RecvTos = 68,
Ip_Add_Source_Membership = 70,
Ip_Drop_Source_Membership = 71,
Ip_Block_Source = 72,
Ip_Unblock_Source = 73,
/* ==================================== */
/* ==================================== */
Tcp_NoDelay = (1 << 0),
Tcp_MaxSeg = (1 << 1),
Tcp_NoPush = (1 << 2),
Tcp_NoOpt = (1 << 3),
Tcp_Md5Sig = (1 << 4),
Tcp_Info = (1 << 5),
Tcp_Congestion = (1 << 6),
Tcp_KeepInit = (1 << 7),
Tcp_KeepIdle = (1 << 8),
Tcp_KeepIntvl = (1 << 9),
Tcp_KeepCnt = (1 << 10),
Tcp_Vendor = So_Vendor,
/* ==================================== */
};
}

View file

@ -42,6 +42,8 @@ namespace ams::socket {
IpProto_Udp = 17,
IpProto_None = 59,
IpProto_UdpLite = 136,
IpProto_Raw = 255,
@ -80,12 +82,29 @@ namespace ams::socket {
};
enum class MsgFlag : s32 {
MsgFlag_None = (0 << 0),
Msg_None = (0 << 0),
Msg_Oob = (1 << 0),
Msg_Peek = (1 << 1),
Msg_DontRoute = (1 << 2),
/* ... */
MsgFlag_WaitAll = (1 << 6),
Msg_Trunc = (1 << 4),
Msg_CTrunc = (1 << 5),
Msg_WaitAll = (1 << 6),
Msg_DontWait = (1 << 7),
/* ... */
};
enum class FcntlCommand : u32 {
F_GetFl = 3,
F_SetFl = 4,
};
enum class FcntlFlag : u32 {
None = (0 << 0),
O_NonBlock = (1 << 11),
};
enum class ShutdownMethod : u32 {
Shut_Rd = 0,
Shut_Wr = 1,
@ -140,6 +159,16 @@ namespace ams::socket {
AddrInfo *ai_next;
};
struct TimeVal {
long tv_sec;
long tv_usec;
};
struct Linger {
int l_onoff;
int l_linger;
};
#define AMS_SOCKET_IMPL_DEFINE_ENUM_OPERATORS(__ENUM__) \
constexpr inline __ENUM__ operator | (__ENUM__ lhs, __ENUM__ rhs) { return static_cast<__ENUM__>(static_cast<std::underlying_type_t<__ENUM__>>(lhs) | static_cast<std::underlying_type_t<__ENUM__>>(rhs)); } \
constexpr inline __ENUM__ operator |=(__ENUM__ &lhs, __ENUM__ rhs) { return lhs = lhs | rhs; } \
@ -151,6 +180,8 @@ namespace ams::socket {
AMS_SOCKET_IMPL_DEFINE_ENUM_OPERATORS(Type)
AMS_SOCKET_IMPL_DEFINE_ENUM_OPERATORS(AddrInfoFlag)
AMS_SOCKET_IMPL_DEFINE_ENUM_OPERATORS(MsgFlag)
AMS_SOCKET_IMPL_DEFINE_ENUM_OPERATORS(FcntlFlag)
#undef AMS_SOCKET_IMPL_DEFINE_ENUM_OPERATORS