Kyty/source/emulator/src/Network.cpp

1811 lines
34 KiB
C++

#include "Emulator/Network.h"
#include "Kyty/Core/ByteBuffer.h"
#include "Kyty/Core/Common.h"
#include "Kyty/Core/DbgAssert.h"
#include "Kyty/Core/String.h"
#include "Kyty/Core/Threads.h"
#include "Kyty/Core/Vector.h"
#include "Emulator/Kernel/Pthread.h"
#include "Emulator/Libs/Errno.h"
#include "Emulator/Libs/Libs.h"
#include <atomic>
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs::Network {
class Network
{
public:
class Id
{
public:
static constexpr int MAX_ID = 65536;
enum class Type : uint32_t
{
Invalid = 0,
Http = 1,
Ssl = 2,
Template = 3,
Connection = 4,
Request = 5,
};
explicit Id(int id): m_id(static_cast<uint32_t>(id) & 0xffffu), m_type(static_cast<uint32_t>(id) >> 16u) {}
[[nodiscard]] int ToInt() const { return static_cast<int>(m_id + (static_cast<uint32_t>(m_type) << 16u)); }
[[nodiscard]] bool IsValid() const { return GetType() != Type::Invalid; }
[[nodiscard]] Type GetType() const
{
switch (m_type)
{
case static_cast<uint32_t>(Type::Http): return Type::Http; break;
case static_cast<uint32_t>(Type::Ssl): return Type::Ssl; break;
case static_cast<uint32_t>(Type::Template): return Type::Template; break;
case static_cast<uint32_t>(Type::Connection): return Type::Connection; break;
case static_cast<uint32_t>(Type::Request): return Type::Request; break;
default: return Type::Invalid;
}
}
friend class Network;
private:
Id() = default;
static Id Invalid() { return {}; }
static Id Create(int net_id, Type type)
{
Id r;
r.m_id = net_id;
r.m_type = static_cast<uint32_t>(type);
return r;
}
[[nodiscard]] int GetId() const { return static_cast<int>(m_id); }
uint32_t m_id = 0;
uint32_t m_type = static_cast<uint32_t>(Type::Invalid);
};
using HttpsCallback = KYTY_SYSV_ABI int (*)(int, unsigned int, void* const*, int, void*);
Network() = default;
virtual ~Network() = default;
KYTY_CLASS_NO_COPY(Network);
int PoolCreate(const char* name, int size);
bool PoolDestroy(int memid);
Id SslInit(uint64_t pool_size);
bool SslTerm(Id ssl_ctx_id);
Id HttpInit(int memid, Id ssl_ctx_id, uint64_t pool_size);
bool HttpTerm(Id http_ctx_id);
Id HttpCreateTemplate(Id http_ctx_id, const char* user_agent, int http_ver, bool is_auto_proxy_conf);
bool HttpDeleteTemplate(Id tmpl_id);
bool HttpSetNonblock(Id id, bool enable);
bool HttpsSetSslCallback(Id id, HttpsCallback cbfunc, void* user_arg);
bool HttpsDisableOption(Id id, uint32_t ssl_flags);
bool HttpAddRequestHeader(Id id, const char* name, const char* value, bool add);
bool HttpValid(Id http_ctx_id);
bool HttpValidTemplate(Id tmpl_id);
bool HttpValidConnection(Id conn_id);
bool HttpValidRequest(Id req_id);
Id HttpCreateConnectionWithURL(Id tmpl_id, const char* url, bool enable_keep_alive);
bool HttpDeleteConnection(Id conn_id);
Id HttpCreateRequestWithURL2(Id conn_id, const char* method, const char* url, uint64_t content_length);
bool HttpDeleteRequest(Id req_id);
bool HttpSetResolveTimeOut(Id id, uint32_t usec);
bool HttpSetResolveRetry(Id id, int32_t retry);
bool HttpSetConnectTimeOut(Id id, uint32_t usec);
bool HttpSetSendTimeOut(Id id, uint32_t usec);
bool HttpSetRecvTimeOut(Id id, uint32_t usec);
bool HttpSetAutoRedirect(Id id, int enable);
bool HttpSetAuthEnabled(Id id, int enable);
private:
struct Pool
{
bool used = false;
String name;
int size = 0;
};
struct Ssl
{
bool used = false;
uint64_t size = 0;
};
struct Http
{
bool used = false;
uint64_t size = 0;
int memid = 0;
int ssl_ctx_id = 0;
};
struct HttpHeader
{
String name;
String value;
};
struct HttpBase
{
Vector<HttpHeader> headers;
bool used = false;
bool nonblock = false;
bool auto_redirect = true;
bool auth_enabled = true;
HttpsCallback ssl_cbfunc = nullptr;
void* ssl_user_arg = nullptr;
uint32_t ssl_flags = 0xA7;
int http_ctx_id = 0;
uint32_t resolve_timeout = 1'000000;
int32_t resolve_retry = 4;
uint32_t connect_timeout = 30'000000;
uint32_t send_timeout = 120'000000;
uint32_t recv_timeout = 120'000000;
};
struct HttpTemplate: public HttpBase
{
String user_agent;
int http_ver = 0;
bool is_auto_proxy_conf = true;
};
struct HttpConnection: public HttpTemplate
{
explicit HttpConnection(const HttpTemplate& tmpl): HttpTemplate(tmpl) {}
// int tmpl_id = 0;
String url;
bool enable_keep_alive = false;
};
struct HttpRequest: public HttpConnection
{
explicit HttpRequest(HttpConnection& conn): HttpConnection(conn) {}
// int conn_id = 0;
String method;
String url;
uint64_t content_length = 0;
};
static constexpr int POOLS_MAX = 32;
static constexpr int SSL_MAX = 32;
static constexpr int HTTP_MAX = 32;
Core::Mutex m_mutex;
Pool m_pools[POOLS_MAX];
Ssl m_ssl[SSL_MAX];
Http m_http[HTTP_MAX];
Vector<HttpTemplate> m_templates;
Vector<HttpConnection> m_connections;
Vector<HttpRequest> m_requests;
};
static Network* g_net = nullptr;
KYTY_SUBSYSTEM_INIT(Network)
{
EXIT_IF(g_net != nullptr);
g_net = new Network;
}
KYTY_SUBSYSTEM_UNEXPECTED_SHUTDOWN(Network) {}
KYTY_SUBSYSTEM_DESTROY(Network) {}
int Network::PoolCreate(const char* name, int size)
{
Core::LockGuard lock(m_mutex);
for (int id = 0; id < POOLS_MAX; id++)
{
if (!m_pools[id].used)
{
m_pools[id].used = true;
m_pools[id].size = size;
m_pools[id].name = String::FromUtf8(name);
return id;
}
}
return -1;
}
bool Network::PoolDestroy(int memid)
{
Core::LockGuard lock(m_mutex);
if (memid >= 0 && memid < POOLS_MAX && m_pools[memid].used)
{
m_pools[memid].used = false;
return true;
}
return false;
}
Network::Id Network::SslInit(uint64_t pool_size)
{
Core::LockGuard lock(m_mutex);
for (int id = 0; id < SSL_MAX; id++)
{
if (!m_ssl[id].used)
{
m_ssl[id].used = true;
m_ssl[id].size = pool_size;
return Id::Create(id, Id::Type::Ssl);
}
}
return Id::Invalid();
}
bool Network::SslTerm(Id ssl_ctx_id)
{
Core::LockGuard lock(m_mutex);
if (ssl_ctx_id.GetType() == Id::Type::Ssl && ssl_ctx_id.GetId() >= 0 && ssl_ctx_id.GetId() < SSL_MAX && m_ssl[ssl_ctx_id.GetId()].used)
{
m_ssl[ssl_ctx_id.GetId()].used = false;
return true;
}
return false;
}
Network::Id Network::HttpInit(int memid, Id ssl_ctx_id, uint64_t pool_size)
{
Core::LockGuard lock(m_mutex);
if (ssl_ctx_id.GetType() == Id::Type::Ssl && ssl_ctx_id.GetId() >= 0 && ssl_ctx_id.GetId() < SSL_MAX &&
m_ssl[ssl_ctx_id.GetId()].used && memid >= 0 && memid < POOLS_MAX && m_pools[memid].used)
{
for (int id = 0; id < HTTP_MAX; id++)
{
if (!m_http[id].used)
{
m_http[id].used = true;
m_http[id].size = pool_size;
m_http[id].ssl_ctx_id = ssl_ctx_id.GetId();
m_http[id].memid = memid;
return Id::Create(id, Id::Type::Http);
}
}
}
return Id::Invalid();
}
bool Network::HttpValid(Id http_ctx_id)
{
Core::LockGuard lock(m_mutex);
return (http_ctx_id.GetType() == Id::Type::Http && http_ctx_id.GetId() >= 0 && http_ctx_id.GetId() < HTTP_MAX &&
m_http[http_ctx_id.GetId()].used);
}
bool Network::HttpValidTemplate(Id tmpl_id)
{
Core::LockGuard lock(m_mutex);
return (tmpl_id.GetType() == Id::Type::Template && m_templates.IndexValid(tmpl_id.GetId()) && m_templates.At(tmpl_id.GetId()).used);
}
bool Network::HttpValidConnection(Id conn_id)
{
Core::LockGuard lock(m_mutex);
return (conn_id.GetType() == Id::Type::Connection && m_connections.IndexValid(conn_id.GetId()) &&
m_connections.At(conn_id.GetId()).used);
}
bool Network::HttpValidRequest(Id req_id)
{
Core::LockGuard lock(m_mutex);
return (req_id.GetType() == Id::Type::Request && m_requests.IndexValid(req_id.GetId()) && m_requests.At(req_id.GetId()).used);
}
bool Network::HttpTerm(Id http_ctx_id)
{
Core::LockGuard lock(m_mutex);
if (HttpValid(http_ctx_id))
{
m_http[http_ctx_id.GetId()].used = false;
return true;
}
return false;
}
Network::Id Network::HttpCreateTemplate(Id http_ctx_id, const char* user_agent, int http_ver, bool is_auto_proxy_conf)
{
Core::LockGuard lock(m_mutex);
if (HttpValid(http_ctx_id))
{
HttpTemplate tn {};
tn.used = true;
tn.http_ver = http_ver;
tn.user_agent = String::FromUtf8(user_agent);
tn.is_auto_proxy_conf = is_auto_proxy_conf;
tn.http_ctx_id = http_ctx_id.GetId();
tn.nonblock = false;
int index = 0;
for (auto& t: m_templates)
{
if (!t.used)
{
t = tn;
return Id::Create(index, Id::Type::Template);
}
index++;
}
if (index < Id::MAX_ID)
{
m_templates.Add(tn);
return Id::Create(index, Id::Type::Template);
}
}
return Id::Invalid();
}
Network::Id Network::HttpCreateConnectionWithURL(Id tmpl_id, const char* url, bool enable_keep_alive)
{
Core::LockGuard lock(m_mutex);
if (HttpValidTemplate(tmpl_id))
{
HttpConnection cn(m_templates[tmpl_id.GetId()]);
cn.used = true;
cn.enable_keep_alive = enable_keep_alive;
cn.url = String::FromUtf8(url);
// cn.tmpl_id = tmpl_id.ToInt();
int index = 0;
for (auto& t: m_connections)
{
if (!t.used)
{
t = cn;
return Id::Create(index, Id::Type::Connection);
}
index++;
}
if (index < Id::MAX_ID)
{
m_connections.Add(cn);
return Id::Create(index, Id::Type::Connection);
}
}
return Id::Invalid();
}
bool Network::HttpDeleteConnection(Id conn_id)
{
Core::LockGuard lock(m_mutex);
if (HttpValidConnection(conn_id))
{
m_connections[conn_id.GetId()].used = false;
return true;
}
return false;
}
Network::Id Network::HttpCreateRequestWithURL2(Id conn_id, const char* method, const char* url, uint64_t content_length)
{
Core::LockGuard lock(m_mutex);
if (HttpValidConnection(conn_id))
{
HttpRequest cn(m_connections[conn_id.GetId()]);
cn.used = true;
cn.method = String::FromUtf8(method);
cn.url = String::FromUtf8(url);
// cn.conn_id = conn_id.ToInt();
cn.content_length = content_length;
int index = 0;
for (auto& t: m_requests)
{
if (!t.used)
{
t = cn;
return Id::Create(index, Id::Type::Request);
}
index++;
}
if (index < Id::MAX_ID)
{
m_requests.Add(cn);
return Id::Create(index, Id::Type::Request);
}
}
return Id::Invalid();
}
bool Network::HttpDeleteRequest(Id req_id)
{
Core::LockGuard lock(m_mutex);
if (HttpValidRequest(req_id))
{
m_requests[req_id.GetId()].used = false;
return true;
}
return false;
}
bool Network::HttpDeleteTemplate(Id tmpl_id)
{
Core::LockGuard lock(m_mutex);
if (HttpValidTemplate(tmpl_id))
{
m_templates[tmpl_id.GetId()].used = false;
return true;
}
return false;
}
bool Network::HttpSetNonblock(Id id, bool enable)
{
Core::LockGuard lock(m_mutex);
HttpBase* base = nullptr;
if (HttpValidTemplate(id))
{
base = &m_templates[id.GetId()];
} else if (HttpValidConnection(id))
{
base = &m_connections[id.GetId()];
} else if (HttpValidRequest(id))
{
base = &m_requests[id.GetId()];
}
if (base != nullptr)
{
base->nonblock = enable;
return true;
}
return false;
}
bool Network::HttpsSetSslCallback(Id id, HttpsCallback cbfunc, void* user_arg)
{
Core::LockGuard lock(m_mutex);
HttpBase* base = nullptr;
if (HttpValidTemplate(id))
{
base = &m_templates[id.GetId()];
} else if (HttpValidConnection(id))
{
base = &m_connections[id.GetId()];
} else if (HttpValidRequest(id))
{
base = &m_requests[id.GetId()];
}
if (base != nullptr)
{
base->ssl_cbfunc = cbfunc;
base->ssl_user_arg = user_arg;
return true;
}
return false;
}
bool Network::HttpsDisableOption(Id id, uint32_t ssl_flags)
{
Core::LockGuard lock(m_mutex);
HttpBase* base = nullptr;
if (HttpValidTemplate(id))
{
base = &m_templates[id.GetId()];
} else if (HttpValidConnection(id))
{
base = &m_connections[id.GetId()];
} else if (HttpValidRequest(id))
{
base = &m_requests[id.GetId()];
}
if (base != nullptr)
{
base->ssl_flags &= ~ssl_flags;
return true;
}
return false;
}
bool Network::HttpAddRequestHeader(Id id, const char* name, const char* value, bool add)
{
Core::LockGuard lock(m_mutex);
HttpBase* base = nullptr;
if (HttpValidTemplate(id))
{
base = &m_templates[id.GetId()];
} else if (HttpValidConnection(id))
{
base = &m_connections[id.GetId()];
} else if (HttpValidRequest(id))
{
base = &m_requests[id.GetId()];
}
if (base != nullptr)
{
HttpHeader nh({String::FromUtf8(name), String::FromUtf8(value)});
if (add)
{
base->headers.Add(nh);
} else
{
for (auto& h: base->headers)
{
if (h.name == nh.name)
{
h.value = nh.value;
}
}
}
return true;
}
return false;
}
bool Network::HttpSetResolveTimeOut(Id id, uint32_t usec)
{
Core::LockGuard lock(m_mutex);
HttpBase* base = nullptr;
if (HttpValidTemplate(id))
{
base = &m_templates[id.GetId()];
} else if (HttpValidConnection(id))
{
base = &m_connections[id.GetId()];
}
if (base != nullptr)
{
base->resolve_timeout = usec;
return true;
}
return false;
}
bool Network::HttpSetResolveRetry(Id id, int32_t retry)
{
Core::LockGuard lock(m_mutex);
HttpBase* base = nullptr;
if (HttpValidTemplate(id))
{
base = &m_templates[id.GetId()];
} else if (HttpValidConnection(id))
{
base = &m_connections[id.GetId()];
}
if (base != nullptr)
{
base->resolve_retry = retry;
return true;
}
return false;
}
bool Network::HttpSetConnectTimeOut(Id id, uint32_t usec)
{
Core::LockGuard lock(m_mutex);
HttpBase* base = nullptr;
if (HttpValidTemplate(id))
{
base = &m_templates[id.GetId()];
} else if (HttpValidConnection(id))
{
base = &m_connections[id.GetId()];
} else if (HttpValidRequest(id))
{
base = &m_requests[id.GetId()];
}
if (base != nullptr)
{
base->connect_timeout = usec;
return true;
}
return false;
}
bool Network::HttpSetSendTimeOut(Id id, uint32_t usec)
{
Core::LockGuard lock(m_mutex);
HttpBase* base = nullptr;
if (HttpValidTemplate(id))
{
base = &m_templates[id.GetId()];
} else if (HttpValidConnection(id))
{
base = &m_connections[id.GetId()];
} else if (HttpValidRequest(id))
{
base = &m_requests[id.GetId()];
}
if (base != nullptr)
{
base->send_timeout = usec;
return true;
}
return false;
}
bool Network::HttpSetRecvTimeOut(Id id, uint32_t usec)
{
Core::LockGuard lock(m_mutex);
HttpBase* base = nullptr;
if (HttpValidTemplate(id))
{
base = &m_templates[id.GetId()];
} else if (HttpValidConnection(id))
{
base = &m_connections[id.GetId()];
} else if (HttpValidRequest(id))
{
base = &m_requests[id.GetId()];
}
if (base != nullptr)
{
base->recv_timeout = usec;
return true;
}
return false;
}
bool Network::HttpSetAutoRedirect(Id id, int enable)
{
Core::LockGuard lock(m_mutex);
HttpBase* base = nullptr;
if (HttpValidTemplate(id))
{
base = &m_templates[id.GetId()];
} else if (HttpValidConnection(id))
{
base = &m_connections[id.GetId()];
} else if (HttpValidRequest(id))
{
base = &m_requests[id.GetId()];
}
if (base != nullptr)
{
base->auto_redirect = (enable != 0);
return true;
}
return false;
}
bool Network::HttpSetAuthEnabled(Id id, int enable)
{
Core::LockGuard lock(m_mutex);
HttpBase* base = nullptr;
if (HttpValidTemplate(id))
{
base = &m_templates[id.GetId()];
} else if (HttpValidConnection(id))
{
base = &m_connections[id.GetId()];
} else if (HttpValidRequest(id))
{
base = &m_requests[id.GetId()];
}
if (base != nullptr)
{
base->auth_enabled = (enable != 0);
return true;
}
return false;
}
namespace Net {
LIB_NAME("Net", "Net");
struct NetEtherAddr
{
uint8_t data[6] = {0};
};
int KYTY_SYSV_ABI NetInit()
{
PRINT_NAME();
return OK;
}
int KYTY_SYSV_ABI NetTerm()
{
PRINT_NAME();
return OK;
}
int KYTY_SYSV_ABI NetPoolCreate(const char* name, int size, int flags)
{
PRINT_NAME();
printf("\t name = %s\n", name);
printf("\t size = %d\n", size);
printf("\t flags = %d\n", flags);
EXIT_IF(g_net == nullptr);
EXIT_NOT_IMPLEMENTED(flags != 0);
EXIT_NOT_IMPLEMENTED(size == 0);
int id = g_net->PoolCreate(name, size);
if (id < 0)
{
return NET_ERROR_ENFILE;
}
return id;
}
int KYTY_SYSV_ABI NetPoolDestroy(int memid)
{
PRINT_NAME();
EXIT_IF(g_net == nullptr);
if (!g_net->PoolDestroy(memid))
{
return NET_ERROR_EBADF;
}
return OK;
}
int KYTY_SYSV_ABI NetInetPton(int af, const char* src, void* dst)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(af != 2);
EXIT_NOT_IMPLEMENTED(src == nullptr);
EXIT_NOT_IMPLEMENTED(dst == nullptr);
EXIT_NOT_IMPLEMENTED(strcmp(src, "127.0.0.1") != 0);
printf("\t src = %.16s\n", src);
*static_cast<uint32_t*>(dst) = 0x7f000001;
return OK;
}
int KYTY_SYSV_ABI NetEtherNtostr(const NetEtherAddr* n, char* str, size_t len)
{
PRINT_NAME();
NetEtherAddr zero {};
EXIT_NOT_IMPLEMENTED(len != 18);
EXIT_NOT_IMPLEMENTED(n == nullptr);
EXIT_NOT_IMPLEMENTED(str == nullptr);
EXIT_NOT_IMPLEMENTED(memcmp(n->data, zero.data, sizeof(zero.data)) != 0);
strcpy(str, "00:00:00:00:00:00"); // NOLINT
return OK;
}
int KYTY_SYSV_ABI NetGetMacAddress(NetEtherAddr* addr, int flags)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(addr == nullptr);
EXIT_NOT_IMPLEMENTED(flags != 0);
memset(addr->data, 0, sizeof(addr->data));
return OK;
}
} // namespace Net
namespace Ssl {
LIB_NAME("Ssl", "Ssl");
int KYTY_SYSV_ABI SslInit(uint64_t pool_size)
{
PRINT_NAME();
printf("\t size = %" PRIu64 "\n", pool_size);
EXIT_IF(g_net == nullptr);
EXIT_NOT_IMPLEMENTED(pool_size == 0);
auto id = g_net->SslInit(pool_size);
if (!id.IsValid())
{
return SSL_ERROR_OUT_OF_SIZE;
}
return id.ToInt();
}
int KYTY_SYSV_ABI SslTerm(int ssl_ctx_id)
{
PRINT_NAME();
EXIT_IF(g_net == nullptr);
if (!g_net->SslTerm(Network::Id(ssl_ctx_id)))
{
return SSL_ERROR_INVALID_ID;
}
return OK;
}
} // namespace Ssl
namespace Http {
struct HttpEpoll
{
Network::Id http_ctx_id = Network::Id(0);
Network::Id request_id = Network::Id(0);
void* user_arg = nullptr;
};
LIB_NAME("Http", "Http");
int KYTY_SYSV_ABI HttpInit(int memid, int ssl_ctx_id, uint64_t pool_size)
{
PRINT_NAME();
printf("\t memid = %d\n", memid);
printf("\t ssl_ctx_id = %d\n", ssl_ctx_id);
printf("\t size = %" PRIu64 "\n", pool_size);
EXIT_IF(g_net == nullptr);
EXIT_NOT_IMPLEMENTED(pool_size == 0);
auto id = g_net->HttpInit(memid, Network::Id(ssl_ctx_id), pool_size);
if (!id.IsValid())
{
return HTTP_ERROR_OUT_OF_MEMORY;
}
return id.ToInt();
}
int KYTY_SYSV_ABI HttpTerm(int http_ctx_id)
{
PRINT_NAME();
EXIT_IF(g_net == nullptr);
if (!g_net->HttpTerm(Network::Id(http_ctx_id)))
{
return HTTP_ERROR_INVALID_ID;
}
return OK;
}
int KYTY_SYSV_ABI HttpCreateTemplate(int http_ctx_id, const char* user_agent, int http_ver, int is_auto_proxy_conf)
{
PRINT_NAME();
printf("\t http_ctx_id = %d\n", http_ctx_id);
printf("\t user_agent = %s\n", user_agent);
printf("\t http_ver = %d\n", http_ver);
printf("\t is_auto_proxy_conf = %d\n", is_auto_proxy_conf);
EXIT_IF(g_net == nullptr);
auto id = g_net->HttpCreateTemplate(Network::Id(http_ctx_id), user_agent, http_ver, is_auto_proxy_conf != 0);
if (!id.IsValid())
{
return HTTP_ERROR_OUT_OF_MEMORY;
}
return id.ToInt();
}
int KYTY_SYSV_ABI HttpDeleteTemplate(int tmpl_id)
{
PRINT_NAME();
EXIT_IF(g_net == nullptr);
if (!g_net->HttpDeleteTemplate(Network::Id(tmpl_id)))
{
return HTTP_ERROR_INVALID_ID;
}
return OK;
}
int KYTY_SYSV_ABI HttpSetNonblock(int id, int enable)
{
PRINT_NAME();
printf("\t id = %d\n", id);
printf("\t enable = %d\n", enable);
if (!g_net->HttpSetNonblock(Network::Id(id), enable != 0))
{
return HTTP_ERROR_INVALID_ID;
}
return OK;
}
int KYTY_SYSV_ABI HttpsSetSslCallback(int id, HttpsCallback cbfunc, void* user_arg)
{
PRINT_NAME();
printf("\t id = %d\n", id);
if (!g_net->HttpsSetSslCallback(Network::Id(id), cbfunc, user_arg))
{
return HTTP_ERROR_INVALID_ID;
}
return OK;
}
int KYTY_SYSV_ABI HttpsDisableOption(int id, uint32_t ssl_flags)
{
PRINT_NAME();
printf("\t id = %d\n", id);
printf("\t ssl_flags = %u\n", ssl_flags);
if (!g_net->HttpsDisableOption(Network::Id(id), ssl_flags))
{
return HTTP_ERROR_INVALID_ID;
}
return OK;
}
int KYTY_SYSV_ABI HttpSetResolveTimeOut(int id, uint32_t usec)
{
PRINT_NAME();
printf("\t id = %d\n", id);
printf("\t usec = %u\n", usec);
if (!g_net->HttpSetResolveTimeOut(Network::Id(id), usec))
{
return HTTP_ERROR_INVALID_ID;
}
return OK;
}
int KYTY_SYSV_ABI HttpSetResolveRetry(int id, int32_t retry)
{
PRINT_NAME();
printf("\t id = %d\n", id);
printf("\t retry = %d\n", retry);
if (!g_net->HttpSetResolveRetry(Network::Id(id), retry))
{
return HTTP_ERROR_INVALID_ID;
}
return OK;
}
int KYTY_SYSV_ABI HttpSetConnectTimeOut(int id, uint32_t usec)
{
PRINT_NAME();
printf("\t id = %d\n", id);
printf("\t usec = %u\n", usec);
if (!g_net->HttpSetConnectTimeOut(Network::Id(id), usec))
{
return HTTP_ERROR_INVALID_ID;
}
return OK;
}
int KYTY_SYSV_ABI HttpSetSendTimeOut(int id, uint32_t usec)
{
PRINT_NAME();
printf("\t id = %d\n", id);
printf("\t usec = %u\n", usec);
if (!g_net->HttpSetSendTimeOut(Network::Id(id), usec))
{
return HTTP_ERROR_INVALID_ID;
}
return OK;
}
int KYTY_SYSV_ABI HttpSetRecvTimeOut(int id, uint32_t usec)
{
PRINT_NAME();
printf("\t id = %d\n", id);
printf("\t usec = %u\n", usec);
if (!g_net->HttpSetRecvTimeOut(Network::Id(id), usec))
{
return HTTP_ERROR_INVALID_ID;
}
return OK;
}
int KYTY_SYSV_ABI HttpSetAutoRedirect(int id, int enable)
{
PRINT_NAME();
printf("\t id = %d\n", id);
printf("\t enable = %d\n", enable);
if (!g_net->HttpSetAutoRedirect(Network::Id(id), enable))
{
return HTTP_ERROR_INVALID_ID;
}
return OK;
}
int KYTY_SYSV_ABI HttpSetAuthEnabled(int id, int enable)
{
PRINT_NAME();
printf("\t id = %d\n", id);
printf("\t enable = %d\n", enable);
if (!g_net->HttpSetAuthEnabled(Network::Id(id), enable))
{
return HTTP_ERROR_INVALID_ID;
}
return OK;
}
int KYTY_SYSV_ABI HttpAddRequestHeader(int id, const char* name, const char* value, uint32_t mode)
{
PRINT_NAME();
printf("\t id = %d\n", id);
printf("\t name = %s\n", name);
printf("\t value = %s\n", value);
printf("\t mode = %u\n", mode);
EXIT_NOT_IMPLEMENTED(mode != 0 && mode != 1);
if (!g_net->HttpAddRequestHeader(Network::Id(id), name, value, mode == 1))
{
return HTTP_ERROR_INVALID_ID;
}
return OK;
}
int KYTY_SYSV_ABI HttpCreateEpoll(int http_ctx_id, HttpEpollHandle* eh)
{
PRINT_NAME();
printf("\t http_ctx_id = %d\n", http_ctx_id);
EXIT_IF(g_net == nullptr);
EXIT_NOT_IMPLEMENTED(eh == nullptr);
EXIT_NOT_IMPLEMENTED(!g_net->HttpValid(Network::Id(http_ctx_id)));
*eh = new HttpEpoll;
(*eh)->http_ctx_id = Network::Id(http_ctx_id);
return OK;
}
int KYTY_SYSV_ABI HttpDestroyEpoll(int http_ctx_id, HttpEpollHandle eh)
{
PRINT_NAME();
printf("\t http_ctx_id = %d\n", http_ctx_id);
EXIT_IF(g_net == nullptr);
EXIT_NOT_IMPLEMENTED(eh == nullptr);
EXIT_NOT_IMPLEMENTED(!g_net->HttpValid(Network::Id(http_ctx_id)));
delete eh;
return OK;
}
int KYTY_SYSV_ABI HttpSetEpoll(int id, HttpEpollHandle eh, void* user_arg)
{
PRINT_NAME();
printf("\t id = %d\n", id);
EXIT_NOT_IMPLEMENTED(eh == nullptr);
EXIT_NOT_IMPLEMENTED(!g_net->HttpValidRequest(Network::Id(id)));
eh->request_id = Network::Id(id);
eh->user_arg = user_arg;
return OK;
}
int KYTY_SYSV_ABI HttpUnsetEpoll(int id)
{
PRINT_NAME();
printf("\t id = %d\n", id);
EXIT_NOT_IMPLEMENTED(!g_net->HttpValidRequest(Network::Id(id)));
return OK;
}
int KYTY_SYSV_ABI HttpSendRequest(int request_id, const void* /*post_data*/, size_t /*size*/)
{
PRINT_NAME();
printf("\t request_id = %d\n", request_id);
return HTTP_ERROR_TIMEOUT;
}
int KYTY_SYSV_ABI HttpCreateConnectionWithURL(int tmpl_id, const char* url, int enable_keep_alive)
{
PRINT_NAME();
printf("\t tmpl_id = %d\n", tmpl_id);
printf("\t url = %s\n", url);
printf("\t enable_keep_alive = %d\n", enable_keep_alive);
EXIT_IF(g_net == nullptr);
auto id = g_net->HttpCreateConnectionWithURL(Network::Id(tmpl_id), url, enable_keep_alive != 0);
if (!id.IsValid())
{
return HTTP_ERROR_OUT_OF_MEMORY;
}
return id.ToInt();
}
int KYTY_SYSV_ABI HttpDeleteConnection(int conn_id)
{
PRINT_NAME();
printf("\t conn_id = %d\n", conn_id);
EXIT_IF(g_net == nullptr);
if (!g_net->HttpDeleteConnection(Network::Id(conn_id)))
{
return HTTP_ERROR_INVALID_ID;
}
return OK;
}
int KYTY_SYSV_ABI HttpCreateRequestWithURL2(int conn_id, const char* method, const char* url, uint64_t content_length)
{
PRINT_NAME();
printf("\t conn_id = %d\n", conn_id);
printf("\t url = %s\n", url);
printf("\t method = %s\n", method);
printf("\t content_length = %" PRIu64 "\n", content_length);
EXIT_IF(g_net == nullptr);
auto id = g_net->HttpCreateRequestWithURL2(Network::Id(conn_id), method, url, content_length);
if (!id.IsValid())
{
return HTTP_ERROR_OUT_OF_MEMORY;
}
return id.ToInt();
}
int KYTY_SYSV_ABI HttpDeleteRequest(int req_id)
{
PRINT_NAME();
printf("\t req_id = %d\n", req_id);
EXIT_IF(g_net == nullptr);
if (!g_net->HttpDeleteRequest(Network::Id(req_id)))
{
return HTTP_ERROR_INVALID_ID;
}
return OK;
}
} // namespace Http
namespace NetCtl {
LIB_NAME("NetCtl", "NetCtl");
struct NetInAddr
{
uint32_t s_addr = 0;
};
struct NetEtherAddr
{
uint8_t data[6];
};
struct NetCtlNatInfo
{
unsigned int size = sizeof(NetCtlNatInfo);
int stunStatus = 0;
int natType = 0;
NetInAddr mappedAddr;
};
union NetCtlInfo
{
uint32_t device;
NetEtherAddr ether_addr;
uint32_t mtu;
uint32_t link;
NetEtherAddr bssid;
char ssid[32 + 1];
uint32_t wifi_security;
uint8_t rssi_dbm;
uint8_t rssi_percentage;
uint8_t channel;
uint32_t ip_config;
char dhcp_hostname[255 + 1];
char pppoe_auth_name[127 + 1];
char ip_address[16];
char netmask[16];
char default_route[16];
char primary_dns[16];
char secondary_dns[16];
uint32_t http_proxy_config;
char http_proxy_server[255 + 1];
uint16_t http_proxy_port;
};
int KYTY_SYSV_ABI NetCtlInit()
{
PRINT_NAME();
return OK;
}
void KYTY_SYSV_ABI NetCtlTerm()
{
PRINT_NAME();
}
int KYTY_SYSV_ABI NetCtlGetNatInfo(NetCtlNatInfo* nat_info)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(nat_info == nullptr);
EXIT_NOT_IMPLEMENTED(nat_info->size != sizeof(NetCtlNatInfo));
nat_info->stunStatus = 1;
nat_info->natType = 3;
nat_info->mappedAddr.s_addr = 0x7f000001;
return OK;
}
int KYTY_SYSV_ABI NetCtlCheckCallback()
{
PRINT_NAME();
return OK;
}
int KYTY_SYSV_ABI NetCtlGetState(int* state)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(state == nullptr);
*state = 0; // Disconnected
return OK;
}
int KYTY_SYSV_ABI NetCtlRegisterCallback(NetCtlCallback func, void* /*arg*/, int* cid)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(func == nullptr);
EXIT_NOT_IMPLEMENTED(cid == nullptr);
*cid = 1;
return OK;
}
int KYTY_SYSV_ABI NetCtlGetInfo(int code, NetCtlInfo* info)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(info == nullptr);
printf("\t code = %d\n", code);
switch (code)
{
case 2: memset(info->ether_addr.data, 0, sizeof(info->ether_addr.data)); break;
case 11: info->ip_config = 0; break;
case 14: strcpy(info->ip_address, "127.0.0.1"); break;
default: EXIT("unknown code: %d\n", code);
}
return OK;
}
} // namespace NetCtl
namespace NpManager {
LIB_NAME("NpManager", "NpManager");
struct NpTitleId
{
char id[12 + 1];
uint8_t padding[3];
};
struct NpTitleSecret
{
uint8_t data[128];
};
struct NpCountryCode
{
char data[2];
char term;
char padding[1];
};
struct NpAgeRestriction
{
NpCountryCode country_code;
int8_t age;
uint8_t padding[3];
};
struct NpContentRestriction
{
size_t size;
int8_t default_age_restriction;
char padding[3];
int32_t age_restriction_count;
const NpAgeRestriction* age_restriction;
};
struct NpOnlineId
{
char data[16];
char term;
char dummy[3];
};
struct NpId
{
NpOnlineId handle;
uint8_t opt[8];
uint8_t reserved[8];
};
struct NpCreateAsyncRequestParameter
{
size_t size;
LibKernel::KernelCpumask cpu_affinity_mask;
int thread_priority;
uint8_t padding[4];
};
int KYTY_SYSV_ABI NpCheckCallback()
{
PRINT_NAME();
return OK;
}
int KYTY_SYSV_ABI NpSetNpTitleId(const NpTitleId* title_id, const NpTitleSecret* title_secret)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(title_id == nullptr);
EXIT_NOT_IMPLEMENTED(title_secret == nullptr);
printf("\t title_id = %.12s\n", title_id->id);
printf("\t title_secret = %s\n", String::HexFromBin(Core::ByteBuffer(title_secret->data, 128)).C_Str());
return OK;
}
int KYTY_SYSV_ABI NpSetContentRestriction(const NpContentRestriction* restriction)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(restriction == nullptr);
EXIT_NOT_IMPLEMENTED(restriction->size != sizeof(NpContentRestriction));
printf("\t default_age_restriction = %" PRIi8 "\n", restriction->default_age_restriction);
printf("\t age_restriction_count = %" PRIi32 "\n", restriction->age_restriction_count);
for (int i = 0; i < restriction->age_restriction_count; i++)
{
printf("\t age_restriction[%d].age = %" PRIi8 "\n", i, restriction->age_restriction[i].age);
printf("\t age_restriction[%d].country_code.data = %.2s\n", i, restriction->age_restriction[i].country_code.data);
}
return OK;
}
int KYTY_SYSV_ABI NpRegisterStateCallback(void* /*callback*/, void* /*userdata*/)
{
PRINT_NAME();
return OK;
}
void KYTY_SYSV_ABI NpRegisterGamePresenceCallback(void* /*callback*/, void* /*userdata*/)
{
PRINT_NAME();
}
int KYTY_SYSV_ABI NpRegisterPlusEventCallback(void* /*callback*/, void* /*userdata*/)
{
PRINT_NAME();
return OK;
}
int KYTY_SYSV_ABI NpRegisterNpReachabilityStateCallback(void* /*callback*/, void* /*userdata*/)
{
PRINT_NAME();
return OK;
}
int KYTY_SYSV_ABI NpGetNpId(int user_id, NpId* np_id)
{
PRINT_NAME();
printf("\t user_id = %d\n", user_id);
EXIT_NOT_IMPLEMENTED(np_id == nullptr);
int s = snprintf(np_id->handle.data, 16, "Kyty");
EXIT_NOT_IMPLEMENTED(s >= 16);
np_id->handle.term = 0;
return OK;
}
int KYTY_SYSV_ABI NpGetOnlineId(int user_id, NpOnlineId* online_id)
{
PRINT_NAME();
printf("\t user_id = %d\n", user_id);
EXIT_NOT_IMPLEMENTED(online_id == nullptr);
int s = snprintf(online_id->data, 16, "Kyty");
EXIT_NOT_IMPLEMENTED(s >= 16);
online_id->term = 0;
return OK;
}
int KYTY_SYSV_ABI NpCreateAsyncRequest(const NpCreateAsyncRequestParameter* param)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(param == nullptr);
printf("\t size = %" PRIu64 "\n", param->size);
printf("\t cpu_affinity_mask = %" PRIu64 "\n", param->cpu_affinity_mask);
printf("\t thread_priority = %d\n", param->thread_priority);
static std::atomic_int id = 0;
EXIT_NOT_IMPLEMENTED(id >= 1);
return ++id;
}
int KYTY_SYSV_ABI NpDeleteRequest(int req_id)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(req_id != 1);
printf("\t req_id = %d\n", req_id);
return OK;
}
int KYTY_SYSV_ABI NpCheckNpAvailability(int req_id, const char* user, void* result)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(req_id != 1);
EXIT_NOT_IMPLEMENTED(user == nullptr);
EXIT_NOT_IMPLEMENTED(result != nullptr);
printf("\t req_id = %d\n", req_id);
printf("\t user = %s\n", user);
return OK;
}
int KYTY_SYSV_ABI NpPollAsync(int req_id, int* result)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(req_id != 1);
EXIT_NOT_IMPLEMENTED(result == nullptr);
printf("\t req_id = %d\n", req_id);
*result = 0;
return 0;
}
int KYTY_SYSV_ABI NpGetState(int user_id, uint32_t* state)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(state == nullptr);
printf("\t user_id = %d\n", user_id);
*state = 1; // Signed out
return OK;
}
} // namespace NpManager
namespace NpManagerForToolkit {
LIB_NAME("NpManagerForToolkit", "NpManager");
int KYTY_SYSV_ABI NpRegisterStateCallbackForToolkit(void* /*callback*/, void* /*userdata*/)
{
PRINT_NAME();
return OK;
}
int KYTY_SYSV_ABI NpCheckCallbackForLib()
{
PRINT_NAME();
return OK;
}
} // namespace NpManagerForToolkit
namespace NpTrophy {
LIB_NAME("NpTrophy", "NpTrophy");
struct NpTrophyFlagArray
{
uint32_t flag_bits[4];
};
int KYTY_SYSV_ABI NpTrophyCreateHandle(int* handle)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(handle == nullptr);
*handle = 1;
return OK;
}
int KYTY_SYSV_ABI NpTrophyCreateContext(int* context, int user_id, uint32_t service_label, uint64_t options)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(context == nullptr);
EXIT_NOT_IMPLEMENTED(options != 0);
*context = 1;
printf("\t user_id = %d\n", user_id);
printf("\t service_label = %u\n", service_label);
return OK;
}
int KYTY_SYSV_ABI NpTrophyRegisterContext(int context, int handle, uint64_t options)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(options != 0);
EXIT_NOT_IMPLEMENTED(context != 1);
EXIT_NOT_IMPLEMENTED(handle != 1);
printf("\t context = %d\n", context);
printf("\t handle = %d\n", handle);
return OK;
}
int KYTY_SYSV_ABI NpTrophyDestroyHandle(int handle)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(handle != 1);
printf("\t handle = %d\n", handle);
return OK;
}
int KYTY_SYSV_ABI NpTrophyGetTrophyUnlockState(int context, int handle, NpTrophyFlagArray* flags, uint32_t* count)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(flags == nullptr);
EXIT_NOT_IMPLEMENTED(count == nullptr);
EXIT_NOT_IMPLEMENTED(context != 1);
EXIT_NOT_IMPLEMENTED(handle != 1);
printf("\t context = %d\n", context);
printf("\t handle = %d\n", handle);
flags->flag_bits[0] = 0;
flags->flag_bits[1] = 0;
flags->flag_bits[2] = 0;
flags->flag_bits[3] = 0;
*count = 0;
return OK;
}
} // namespace NpTrophy
namespace NpWebApi {
LIB_NAME("NpWebApi", "NpWebApi");
int KYTY_SYSV_ABI NpWebApiInitialize(int http_ctx_id, size_t pool_size)
{
PRINT_NAME();
EXIT_IF(g_net == nullptr);
printf("\t http_ctx_id = %d\n", http_ctx_id);
printf("\t pool_size = %" PRIu64 "\n", pool_size);
EXIT_NOT_IMPLEMENTED(!g_net->HttpValid(Network::Id(http_ctx_id)));
static int id = 0;
return ++id;
}
int KYTY_SYSV_ABI NpWebApiTerminate(int lib_ctx_id)
{
PRINT_NAME();
printf("\t lib_ctx_id = %d\n", lib_ctx_id);
return OK;
}
} // namespace NpWebApi
} // namespace Kyty::Libs::Network
#endif // KYTY_EMU_ENABLED