diff --git a/libstratosphere/include/stratosphere/socket.hpp b/libstratosphere/include/stratosphere/socket.hpp index fc933378..f42d359b 100644 --- a/libstratosphere/include/stratosphere/socket.hpp +++ b/libstratosphere/include/stratosphere/socket.hpp @@ -18,4 +18,5 @@ #include #include #include +#include #include diff --git a/libstratosphere/include/stratosphere/socket/socket_api.hpp b/libstratosphere/include/stratosphere/socket/socket_api.hpp index 4e13549f..cc99f0aa 100644 --- a/libstratosphere/include/stratosphere/socket/socket_api.hpp +++ b/libstratosphere/include/stratosphere/socket/socket_api.hpp @@ -16,9 +16,13 @@ #pragma once #include #include +#include namespace ams::socket { + Errno GetLastError(); + void SetLastError(Errno err); + u32 InetHtonl(u32 host); u16 InetHtons(u16 host); u32 InetNtohl(u32 net); diff --git a/libstratosphere/include/stratosphere/socket/socket_errno.hpp b/libstratosphere/include/stratosphere/socket/socket_errno.hpp new file mode 100644 index 00000000..faf8b2f9 --- /dev/null +++ b/libstratosphere/include/stratosphere/socket/socket_errno.hpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2018-2020 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 . + */ +#pragma once +#include + +namespace ams::socket { + + enum class Errno : u32 { + ESuccess = 0, + /* ... */ + ENoSpc = 28, + /* ... */ + }; + + enum class HErrno : s32 { + Netdb_Internal = -1, + Netdb_Success = 0, + Host_Not_Found = 1, + Try_Again = 2, + No_Recovery = 3, + No_Data = 4, + + No_Address = No_Data, + }; + + enum class AiErrno : u32 { + EAi_Success = 0, + /* ... */ + }; + + constexpr inline bool operator!(Errno e) { return e == Errno::ESuccess; } + constexpr inline bool operator!(HErrno e) { return e == HErrno::Netdb_Success; } + constexpr inline bool operator!(AiErrno e) { return e == AiErrno::EAi_Success; } + +} diff --git a/libstratosphere/include/stratosphere/socket/socket_types.hpp b/libstratosphere/include/stratosphere/socket/socket_types.hpp index 4a6f1f9c..c8bbb9dd 100644 --- a/libstratosphere/include/stratosphere/socket/socket_types.hpp +++ b/libstratosphere/include/stratosphere/socket/socket_types.hpp @@ -34,6 +34,31 @@ namespace ams::socket { constexpr inline InAddrT InAddr_None = EncodeInAddr<255, 255, 255, 255>; constexpr inline InAddrT InAddr_Loopback = EncodeInAddr<127, 0, 0, 1>; + enum class Protocol : s32 { + IpProto_Ip = 0, + IpProto_Icmp = 1, + + IpProto_Tcp = 6, + + IpProto_Udp = 17, + + IpProto_UdpLite = 136, + + IpProto_Raw = 255, + + IpProto_Max = 256, + }; + + enum class Type : u32 { + Sock_Default = 0, + Sock_Stream = 1, + Sock_Dgram = 2, + Sock_Raw = 3, + Sock_SeqPacket = 5, + + Sock_NonBlock = 0x20000000, + }; + enum class Family : u8 { Af_Unspec = 0, Pf_Unspec = Af_Unspec, @@ -66,4 +91,54 @@ namespace ams::socket { InAddrT s_addr; }; + enum class AddrInfoFlag : u32 { + Ai_None = (0 << 0), + Ai_Passive = (1 << 0), + Ai_CanonName = (1 << 1), + Ai_NumericHost = (1 << 2), + Ai_NumericServ = (1 << 3), + + Ai_AddrConfig = (1 << 10), + }; + + struct SockAddr { + u8 sa_len; + Family sa_family; + char sa_data[14]; + }; + + struct SockAddrIn { + u8 sin_len; + Family sin_family; + InPortT sin_port; + InAddr sin_addr; + u8 sin_zero[8]; + }; + static_assert(sizeof(SockAddr) == sizeof(SockAddrIn)); + + struct AddrInfo { + AddrInfoFlag ai_flags; + Family ai_family; + Type ai_socktype; + Protocol ai_protocol; + SockLenT ai_addrlen; + SockAddr *ai_addr; + char *ai_canonname; + AddrInfo *ai_next; + }; + + #define AMS_SOCKET_IMPL_DEFINE_ENUM_OPERATORS(__ENUM__) \ + constexpr inline __ENUM__ operator | (__ENUM__ lhs, __ENUM__ rhs) { return static_cast<__ENUM__>(static_cast>(lhs) | static_cast>(rhs)); } \ + constexpr inline __ENUM__ operator |=(__ENUM__ &lhs, __ENUM__ rhs) { return lhs = lhs | rhs; } \ + constexpr inline __ENUM__ operator & (__ENUM__ lhs, __ENUM__ rhs) { return static_cast<__ENUM__>(static_cast>(lhs) & static_cast>(rhs)); } \ + constexpr inline __ENUM__ operator &=(__ENUM__ &lhs, __ENUM__ rhs) { return lhs = lhs & rhs; } \ + constexpr inline __ENUM__ operator ^ (__ENUM__ lhs, __ENUM__ rhs) { return static_cast<__ENUM__>(static_cast>(lhs) ^ static_cast>(rhs)); } \ + constexpr inline __ENUM__ operator ^=(__ENUM__ &lhs, __ENUM__ rhs) { return lhs = lhs ^ rhs; } \ + constexpr inline __ENUM__ operator ~ (__ENUM__ e) { return static_cast<__ENUM__>(~static_cast>(e)); } + + AMS_SOCKET_IMPL_DEFINE_ENUM_OPERATORS(Type) + AMS_SOCKET_IMPL_DEFINE_ENUM_OPERATORS(AddrInfoFlag) + + #undef AMS_SOCKET_IMPL_DEFINE_ENUM_OPERATORS + } diff --git a/libstratosphere/source/socket/impl/socket_api.hpp b/libstratosphere/source/socket/impl/socket_api.hpp index f370515e..292b4bdc 100644 --- a/libstratosphere/source/socket/impl/socket_api.hpp +++ b/libstratosphere/source/socket/impl/socket_api.hpp @@ -17,6 +17,9 @@ namespace ams::socket::impl { + Errno GetLastError(); + void SetLastError(Errno err); + u32 InetHtonl(u32 host); u16 InetHtons(u16 host); u32 InetNtohl(u32 net); diff --git a/libstratosphere/source/socket/impl/socket_api.os.horizon.cpp b/libstratosphere/source/socket/impl/socket_api.os.horizon.cpp index 57213085..ed4fa987 100644 --- a/libstratosphere/source/socket/impl/socket_api.os.horizon.cpp +++ b/libstratosphere/source/socket/impl/socket_api.os.horizon.cpp @@ -38,6 +38,16 @@ namespace ams::socket::impl { return ams::Free(ptr); } + Errno GetLastError() { + /* TODO: check that client library is initialized. */ + return static_cast(errno); + } + + void SetLastError(Errno err) { + /* TODO: check that client library is initialized. */ + errno = static_cast(err); + } + u32 InetHtonl(u32 host) { if constexpr (util::IsBigEndian()) { return host; diff --git a/libstratosphere/source/socket/socket_api.cpp b/libstratosphere/source/socket/socket_api.cpp index 28f40550..f1171c2c 100644 --- a/libstratosphere/source/socket/socket_api.cpp +++ b/libstratosphere/source/socket/socket_api.cpp @@ -18,6 +18,14 @@ namespace ams::socket { + Errno GetLastError() { + return impl::GetLastError(); + } + + void SetLastError(Errno err) { + return impl::SetLastError(err); + } + u32 InetHtonl(u32 host) { return impl::InetHtonl(host); }