aboutsummaryrefslogtreecommitdiff
path: root/ksocket
diff options
context:
space:
mode:
Diffstat (limited to 'ksocket')
-rw-r--r--ksocket/berkeley.c8
-rw-r--r--ksocket/berkeley.h16
-rw-r--r--ksocket/helper.hpp2
-rw-r--r--ksocket/ksocket.cpp350
-rw-r--r--ksocket/ksocket.h13
-rw-r--r--ksocket/ksocket.hpp233
-rw-r--r--ksocket/utils.c17
-rw-r--r--ksocket/utils.h30
-rw-r--r--ksocket/wsk.h4
9 files changed, 656 insertions, 17 deletions
diff --git a/ksocket/berkeley.c b/ksocket/berkeley.c
index e72f92e..73ccb79 100644
--- a/ksocket/berkeley.c
+++ b/ksocket/berkeley.c
@@ -297,14 +297,6 @@ VOID NTAPI KspUtilFreeAddrInfoEx(_In_ PADDRINFOEXW AddrInfo) {
// Public functions.
//////////////////////////////////////////////////////////////////////////
-uint32_t htonl(uint32_t hostlong) { return __builtin_bswap32(hostlong); }
-
-uint16_t htons(uint16_t hostshort) { return __builtin_bswap16(hostshort); }
-
-uint32_t ntohl(uint32_t netlong) { return __builtin_bswap32(netlong); }
-
-uint16_t ntohs(uint16_t netshort) { return __builtin_bswap16(netshort); }
-
int getaddrinfo(const char *node, const char *service,
const struct addrinfo *hints, struct addrinfo **res) {
NTSTATUS Status;
diff --git a/ksocket/berkeley.h b/ksocket/berkeley.h
index b879d3c..1475a89 100644
--- a/ksocket/berkeley.h
+++ b/ksocket/berkeley.h
@@ -1,6 +1,11 @@
-#pragma once
+#ifndef KSOCKET_BERKELEY_H
+#define KSOCKET_BERKELEY_H 1
+
+#ifdef BUILD_USERMODE
+#error "This file should only be included if building for kernel mode! Include <ksocket/ksocket.hpp> wrapper instead."
+#endif
+
#include <ntddk.h>
-#include <stdint.h>
#include <ksocket/wsk.h>
#define socket socket_connection
@@ -12,11 +17,6 @@ extern "C" {
typedef int socklen_t;
typedef intptr_t ssize_t;
-uint32_t htonl(uint32_t hostlong);
-uint16_t htons(uint16_t hostshort);
-uint32_t ntohl(uint32_t netlong);
-uint16_t ntohs(uint16_t netshort);
-
int getaddrinfo(const char *node, const char *service,
const struct addrinfo *hints, struct addrinfo **res);
void freeaddrinfo(struct addrinfo *res);
@@ -39,3 +39,5 @@ int closesocket(int sockfd);
#ifdef __cplusplus
}
#endif
+
+#endif
diff --git a/ksocket/helper.hpp b/ksocket/helper.hpp
index 153e549..9143b07 100644
--- a/ksocket/helper.hpp
+++ b/ksocket/helper.hpp
@@ -11,6 +11,8 @@
#include <EASTL/string.h>
#include <EASTL/vector.h>
+#include <ksocket/utils.h>
+
#ifndef SOCKET_ERROR
#define SOCKET_ERROR -1
#endif
diff --git a/ksocket/ksocket.cpp b/ksocket/ksocket.cpp
new file mode 100644
index 0000000..ca0625b
--- /dev/null
+++ b/ksocket/ksocket.cpp
@@ -0,0 +1,350 @@
+#include "ksocket.hpp"
+
+#include <EASTL/type_traits.h>
+#include <eastl_compat.hpp>
+
+#ifdef BUILD_USERMODE
+// clang-format off
+#include <winsock2.h>
+#include <windows.h>
+#include <ws2tcpip.h>
+// clang-format on
+#else
+#include <ksocket/berkeley.h>
+#include <ksocket/ksocket.h>
+#include <ksocket/wsk.h>
+#endif
+#include <ksocket/utils.h>
+
+struct KSocketImplCommon {
+ ADDRESS_FAMILY domain;
+ int type;
+ int proto;
+};
+
+#ifdef BUILD_USERMODE
+struct KSocketImpl {
+ ~KSocketImpl() { closesocket(s); }
+
+ SOCKET s;
+ KSocketImplCommon c;
+};
+#else
+struct KSocketImpl {
+ ~KSocketImpl() {
+ if (s >= 0) {
+ closesocket(s);
+ s = -1;
+ }
+ }
+
+ int s = -1;
+ KSocketImplCommon c;
+};
+#endif
+
+eastl::string KSocketAddress::to_string(bool with_port) const {
+ if (addr_used != 4) {
+ return "";
+ }
+
+ return ::to_string(addr.u8[0]) + "." + ::to_string(addr.u8[1]) + "." +
+ ::to_string(addr.u8[2]) + "." + ::to_string(addr.u8[3]) + ":" +
+ ::to_string(with_port);
+}
+
+void KSocketBuffer::insert_u8(KBuffer::iterator it, uint8_t value) {
+ buffer.insert(it, value);
+}
+
+void KSocketBuffer::insert_u16(KBuffer::iterator it, uint16_t value) {
+ uint16_t net_value;
+ uint8_t insert_value[2];
+
+ net_value = htons(value);
+ insert_value[0] = (net_value & 0x00FF) >> 0;
+ insert_value[1] = (net_value & 0xFF00) >> 8;
+ buffer.insert(it, insert_value, insert_value + eastl::size(insert_value));
+}
+
+void KSocketBuffer::insert_u32(KBuffer::iterator it, uint32_t value) {
+ uint32_t net_value;
+ uint8_t insert_value[4];
+
+ net_value = htonl(value);
+ insert_value[0] = (net_value & 0x000000FF) >> 0;
+ insert_value[1] = (net_value & 0x0000FF00) >> 8;
+ insert_value[2] = (net_value & 0x00FF0000) >> 16;
+ insert_value[3] = (net_value & 0xFF000000) >> 24;
+ buffer.insert(it, insert_value, insert_value + eastl::size(insert_value));
+}
+
+void KSocketBuffer::insert_u64(KBuffer::iterator it, uint64_t value) {
+ uint64_t net_value;
+ uint8_t insert_value[8];
+
+ net_value = htonll(value);
+ insert_value[0] = (net_value & 0x00000000000000FF) >> 0;
+ insert_value[1] = (net_value & 0x000000000000FF00) >> 8;
+ insert_value[2] = (net_value & 0x0000000000FF0000) >> 16;
+ insert_value[3] = (net_value & 0x00000000FF000000) >> 24;
+ insert_value[4] = (net_value & 0x000000FF00000000) >> 32;
+ insert_value[5] = (net_value & 0x0000FF0000000000) >> 40;
+ insert_value[6] = (net_value & 0x00FF000000000000) >> 48;
+ insert_value[7] = (net_value & 0xFF00000000000000) >> 56;
+ buffer.insert(it, insert_value, insert_value + eastl::size(insert_value));
+}
+
+void KSocketBuffer::insert_bytebuffer(KBuffer::iterator it,
+ const uint8_t bytebuffer[], size_t size) {
+ buffer.insert(it, bytebuffer, bytebuffer + size);
+}
+
+void KSocketBuffer::consume(size_t amount_bytes) {
+ if (amount_bytes == 0 || amount_bytes > buffer.size())
+ amount_bytes = buffer.size();
+
+ buffer.erase(buffer.begin(), buffer.begin() + amount_bytes);
+}
+
+eastl::string KSocketBuffer::toHex(eastl::string delim) {
+ eastl::string str;
+ char const *const hex = "0123456789ABCDEF";
+ char pout[3] = {};
+
+ for (const auto &input_byte : buffer) {
+ pout[0] = hex[(input_byte >> 4) & 0xF];
+ pout[1] = hex[input_byte & 0xF];
+ str += pout;
+ str += delim;
+ }
+
+ if (str.length() >= delim.length() && delim.length() > 0)
+ str.erase(str.length() - delim.length(), delim.length());
+
+ return str;
+}
+
+KSocket::~KSocket() {
+ if (m_socket != nullptr)
+ delete m_socket;
+}
+
+bool KSocket::setup(KSocketType sock_type, int proto) {
+ int domain, type;
+
+ m_lastError = KSE_SUCCESS;
+ if (m_socket != nullptr)
+ delete m_socket;
+ m_socket = new KSocketImpl();
+ if (m_socket == nullptr) {
+ m_lastError = KSE_SETUP_IMPL_NULL;
+ return false;
+ }
+
+ if (KSocket::socketTypeToTuple(sock_type, domain, type) != true) {
+ m_lastError = KSE_SETUP_INVALID_SOCKET_TYPE;
+ return false;
+ }
+ if (sock_type == KSocketType::KST_STREAM_CLIENT_IP6 ||
+ sock_type == KSocketType::KST_STREAM_SERVER_IP6 ||
+ sock_type == KSocketType::KST_DATAGRAM_IP6) {
+ m_lastError = KSE_SETUP_UNSUPPORTED_SOCKET_TYPE;
+ return false; // IPv6 is not supported for now
+ }
+ m_socketType = sock_type;
+
+#ifdef BUILD_USERMODE
+ m_socket->s = ::socket(domain, type, proto);
+#else
+ // DbgPrint("KSocketType: %d, domain: %d, type: %d, proto: %d", sock_type,
+ // domain, type, proto);
+ switch (sock_type) {
+ case KSocketType::KST_INVALID:
+ m_lastError = KSE_SETUP_INVALID_SOCKET_TYPE;
+ return false;
+ case KSocketType::KST_STREAM_CLIENT_IP4:
+ case KSocketType::KST_STREAM_CLIENT_IP6:
+ m_socket->s = ::socket_connection(domain, type, proto);
+ break;
+ case KSocketType::KST_STREAM_SERVER_IP4:
+ case KSocketType::KST_STREAM_SERVER_IP6:
+ m_socket->s = ::socket_listen(domain, type, proto);
+ break;
+ case KSocketType::KST_DATAGRAM_IP4:
+ case KSocketType::KST_DATAGRAM_IP6:
+ m_socket->s = ::socket_datagram(domain, type, proto);
+ break;
+ }
+#endif
+ m_socket->c.domain = static_cast<ADDRESS_FAMILY>(domain);
+ m_socket->c.type = type;
+ m_socket->c.proto = proto;
+#ifdef BUILD_USERMODE
+ return m_socket->s != INVALID_SOCKET;
+#else
+ return m_socket->s >= 0;
+#endif
+}
+
+bool KSocket::connect(eastl::string host, eastl::string port) {
+ struct addrinfo hints = {};
+ struct addrinfo *results;
+
+ m_lastError = KSE_SUCCESS;
+
+ if (m_socket == nullptr)
+ return false;
+
+ if (m_socketType != KSocketType::KST_STREAM_CLIENT_IP4 &&
+ m_socketType != KSocketType::KST_STREAM_CLIENT_IP6)
+ return false;
+
+ hints.ai_flags |= AI_CANONNAME;
+ hints.ai_family = m_socket->c.domain;
+ hints.ai_socktype = m_socket->c.type;
+ m_lastError = ::getaddrinfo(host.c_str(), port.c_str(), &hints, &results);
+ if (m_lastError != KSE_SUCCESS)
+ return false;
+
+ m_lastError =
+ ::connect(m_socket->s, results->ai_addr, (int)results->ai_addrlen);
+ freeaddrinfo(results);
+ return m_lastError == KSE_SUCCESS;
+}
+
+bool KSocket::bind(uint16_t port) {
+ struct sockaddr_in addr;
+
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = INADDR_ANY;
+ addr.sin_port = htons(port);
+
+ m_lastError = ::bind(m_socket->s, (struct sockaddr *)&addr, sizeof(addr));
+
+ return m_lastError == KSE_SUCCESS;
+}
+
+bool KSocket::listen(int backlog) {
+ m_lastError = KSE_SUCCESS;
+
+ if (m_socketType != KSocketType::KST_STREAM_SERVER_IP4 &&
+ m_socketType != KSocketType::KST_STREAM_SERVER_IP6)
+ return false;
+
+ m_lastError = ::listen(m_socket->s, backlog);
+
+ return m_lastError == KSE_SUCCESS;
+}
+
+bool KSocket::accept(KAcceptThreadCallback thread_callback) {
+ KAcceptedSocket ka;
+ struct sockaddr addr;
+ socklen_t addrlen = sizeof(addr);
+
+ if (m_socket->c.domain != AF_INET) {
+ m_lastError = KSE_SETUP_UNSUPPORTED_SOCKET_TYPE;
+ return false;
+ }
+
+ addr.sa_family = m_socket->c.domain;
+ ka.m_socket = new KSocketImpl();
+ if (ka.m_socket == nullptr) {
+ m_lastError = KSE_SETUP_IMPL_NULL;
+ return false;
+ }
+ ka.m_socketType = m_socketType;
+ ka.m_socket->c = m_socket->c;
+ ka.m_socket->s = ::accept(m_socket->s, &addr, &addrlen);
+
+ if (m_socket->c.domain == AF_INET) {
+ struct sockaddr_in *addr_in = reinterpret_cast<struct sockaddr_in *>(&addr);
+
+ ka.m_remote.addr_used = 4;
+ ka.m_remote.addr.u32[0] = addr_in->sin_addr.s_addr;
+ ka.m_remote.port = addr_in->sin_port;
+ } else {
+ m_lastError = KSE_SETUP_UNSUPPORTED_SOCKET_TYPE;
+ return false;
+ }
+
+#ifdef BUILD_USERMODE
+ if (ka.m_socket->s == INVALID_SOCKET)
+#else
+ if (ka.m_socket->s < 0)
+#endif
+ {
+ m_lastError = KSE_ACCEPT_FAILED;
+ return false;
+ }
+
+ return thread_callback(ka);
+}
+
+bool KSocket::close() {
+ int rv = closesocket(m_socket->s);
+
+ if (rv == 0) {
+ m_socket->s = -1;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool KSocket::send() {
+ m_lastError = KSE_SUCCESS;
+
+ if (m_sendBuffer.size() == 0)
+ return false;
+
+ m_lastError =
+ ::send(m_socket->s, reinterpret_cast<const char *>(m_sendBuffer.data()),
+ m_sendBuffer.size(), 0);
+ if (m_lastError > 0) {
+ m_sendBuffer.buffer.erase(m_sendBuffer.begin(),
+ m_sendBuffer.begin() + m_lastError);
+ return true;
+ }
+
+ return false;
+}
+
+bool KSocket::recv(size_t max_recv_size) {
+ const size_t current_size = m_recvBuffer.size();
+
+ m_recvBuffer.buffer.resize(current_size + max_recv_size);
+ m_lastError = ::recv(
+ m_socket->s, reinterpret_cast<char *>(m_recvBuffer.data() + current_size),
+ max_recv_size, 0);
+ if (m_lastError > 0) {
+ m_recvBuffer.buffer.resize(current_size + m_lastError);
+ return true;
+ }
+
+ return false;
+}
+
+bool KSocket::socketTypeToTuple(KSocketType sock_type, int &domain, int &type) {
+ switch (sock_type) {
+ case KSocketType::KST_INVALID:
+ break;
+ case KSocketType::KST_STREAM_CLIENT_IP4:
+ case KSocketType::KST_STREAM_SERVER_IP4:
+ domain = AF_INET;
+ type = SOCK_STREAM;
+ return true;
+ case KSocketType::KST_STREAM_CLIENT_IP6:
+ case KSocketType::KST_STREAM_SERVER_IP6:
+ domain = AF_INET6;
+ type = SOCK_STREAM;
+ return true;
+ case KSocketType::KST_DATAGRAM_IP4:
+ case KSocketType::KST_DATAGRAM_IP6:
+ domain = AF_INET;
+ type = SOCK_DGRAM;
+ return true;
+ }
+
+ return false;
+}
diff --git a/ksocket/ksocket.h b/ksocket/ksocket.h
index 0a6717e..e44035b 100644
--- a/ksocket/ksocket.h
+++ b/ksocket/ksocket.h
@@ -1,5 +1,12 @@
-#pragma once
-#include "wsk.h"
+#ifndef KSOCKET_H
+#define KSOCKET_H 1
+
+#ifdef BUILD_USERMODE
+#error \
+ "This file should only be included if building for kernel mode! Include <ksocket/ksocket.hpp> wrapper instead."
+#endif
+
+#include <ksocket/wsk.h>
#include <ntddk.h>
#define STATUS_UNSUPPORTED_WINDOWS_VERSION \
@@ -97,3 +104,5 @@ KsRecvFrom(_In_ PKSOCKET Socket, _In_ PVOID Buffer, _Inout_ PULONG Length,
#ifdef __cplusplus
}
#endif
+
+#endif
diff --git a/ksocket/ksocket.hpp b/ksocket/ksocket.hpp
new file mode 100644
index 0000000..abf03b6
--- /dev/null
+++ b/ksocket/ksocket.hpp
@@ -0,0 +1,233 @@
+#ifndef KSOCKET_HPP
+#define KSOCKET_HPP 1
+
+#include <EASTL/functional.h>
+#include <EASTL/string.h>
+#include <EASTL/vector.h>
+#include <cstdint>
+
+using KBuffer = eastl::vector<uint8_t>;
+
+struct KSocketImpl;
+
+enum {
+ KSE_SUCCESS = 0,
+ KSE_SETUP_IMPL_NULL = 1,
+ KSE_SETUP_INVALID_SOCKET_TYPE = 2,
+ KSE_SETUP_UNSUPPORTED_SOCKET_TYPE = 3,
+ KSE_ACCEPT_FAILED = 4,
+};
+
+enum class KSocketType {
+ KST_INVALID = 0,
+ KST_STREAM_CLIENT_IP4,
+ KST_STREAM_SERVER_IP4,
+ KST_STREAM_CLIENT_IP6,
+ KST_STREAM_SERVER_IP6,
+ KST_DATAGRAM_IP4,
+ KST_DATAGRAM_IP6
+};
+
+struct KSocketAddress {
+ eastl::string to_string(bool with_port = true) const;
+ uint8_t addr_used = 0;
+ union {
+ uint8_t u8[16];
+ uint16_t u16[8];
+ uint32_t u32[4];
+ uint64_t u64[2];
+ } addr;
+ uint16_t port = 0;
+};
+
+class KAcceptedSocket;
+using KAcceptThreadCallback = eastl::function<bool(KAcceptedSocket &accepted)>;
+
+struct KSocketBuffer {
+ void insert_i8(KBuffer::iterator it, int8_t value) {
+ insert_u8(it, static_cast<uint8_t>(value));
+ }
+ void insert_i16(KBuffer::iterator it, int16_t value) {
+ insert_u16(it, static_cast<uint16_t>(value));
+ }
+ void insert_i32(KBuffer::iterator it, int32_t value) {
+ insert_u32(it, static_cast<uint32_t>(value));
+ }
+ void insert_i64(KBuffer::iterator it, int64_t value) {
+ insert_u64(it, static_cast<uint64_t>(value));
+ }
+
+ void insert_u8(KBuffer::iterator it, uint8_t value);
+ void insert_u16(KBuffer::iterator it, uint16_t value);
+ void insert_u32(KBuffer::iterator it, uint32_t value);
+ void insert_u64(KBuffer::iterator it, uint64_t value);
+
+ void insert_string(KBuffer::iterator it, const eastl::string &value) {
+ insert_bytebuffer(it, reinterpret_cast<const uint8_t *>(value.c_str()),
+ value.length());
+ }
+ void insert_string(KBuffer::iterator it, const char buffer[], size_t size) {
+ insert_bytebuffer(it, reinterpret_cast<const uint8_t *>(buffer), size);
+ }
+ void insert_bytebuffer(KBuffer::iterator it, const void *bytebuffer,
+ size_t size) {
+ insert_bytebuffer(it, reinterpret_cast<const uint8_t *>(bytebuffer), size);
+ }
+ void insert_bytebuffer(KBuffer::iterator it, const uint8_t bytebuffer[],
+ size_t size);
+
+ void insert(KBuffer::iterator it, int8_t value) {
+ insert_u8(it, static_cast<uint8_t>(value));
+ }
+ void insert(KBuffer::iterator it, int16_t value) {
+ insert_u16(it, static_cast<uint16_t>(value));
+ }
+ void insert(KBuffer::iterator it, int32_t value) {
+ insert_u32(it, static_cast<uint32_t>(value));
+ }
+ void insert(KBuffer::iterator it, int64_t value) {
+ insert_u64(it, static_cast<uint64_t>(value));
+ }
+
+ void insert(KBuffer::iterator it, uint8_t value) { insert_u8(it, value); }
+ void insert(KBuffer::iterator it, uint16_t value) { insert_u16(it, value); }
+ void insert(KBuffer::iterator it, uint32_t value) { insert_u32(it, value); }
+ void insert(KBuffer::iterator it, uint64_t value) { insert_u64(it, value); }
+
+ void insert(KBuffer::iterator it, const eastl::string value) {
+ insert_string(it, eastl::move(value));
+ }
+ void insert(KBuffer::iterator it, const char buffer[], size_t size) {
+ insert_string(it, buffer, size);
+ }
+ void insert(KBuffer::iterator it, const char *value) {
+ insert_string(it, eastl::move(eastl::string(value)));
+ }
+ void insert(KBuffer::iterator it, const uint8_t bytebuffer[], size_t size) {
+ insert_bytebuffer(it, bytebuffer, size);
+ }
+
+ void consume(size_t amount_bytes = 0);
+
+ eastl::string to_string() {
+ return eastl::string(reinterpret_cast<const char *>(data()), size());
+ }
+ uint8_t *data() { return buffer.data(); }
+ size_t size() { return buffer.size(); }
+ KBuffer::iterator begin() { return buffer.begin(); }
+ KBuffer::iterator end() { return buffer.end(); }
+
+ eastl::string toHex(eastl::string delim = ":");
+
+ KBuffer buffer;
+};
+
+class KSocket {
+protected:
+ KSocket() : m_sendBuffer(), m_recvBuffer() {}
+ KSocket(const KSocket &) = delete;
+ ~KSocket();
+ bool setup(KSocketType sock_type, int proto = 0);
+
+ bool connect(eastl::string host, eastl::string port);
+ bool bind(uint16_t port);
+ bool listen(int backlog);
+ bool accept(KAcceptThreadCallback thread_callback);
+ bool close();
+
+ bool send();
+ bool recv(size_t max_recv_size);
+
+public:
+ int getLastError() const { return m_lastError; }
+
+ KSocketBuffer &getSendBuffer() { return m_sendBuffer; }
+ KSocketBuffer &getRecvBuffer() { return m_recvBuffer; }
+
+ static bool socketTypeToTuple(KSocketType sock_type, int &domain, int &type);
+
+private:
+ KSocketBuffer m_sendBuffer;
+ KSocketBuffer m_recvBuffer;
+ KSocketType m_socketType = KSocketType::KST_INVALID;
+ KSocketImpl *m_socket = nullptr;
+ int m_lastError = KSE_SUCCESS;
+};
+
+class KAcceptedSocket : public KSocket {
+ friend class KSocket;
+
+public:
+ KAcceptedSocket() : KSocket() {}
+ ~KAcceptedSocket() {}
+ bool setup(KSocketType sock_type, int proto = 0) = delete;
+
+ bool connect(eastl::string host, eastl::string port) = delete;
+ bool bind(uint16_t port) = delete;
+ bool listen(int backlog) = delete;
+ bool accept(KAcceptThreadCallback thread_callback) = delete;
+
+ bool send() { return KSocket::send(); }
+ bool recv(size_t max_recv_size = 65535) {
+ return KSocket::recv(max_recv_size);
+ }
+
+ int getLastError() { return KSocket::getLastError(); }
+
+ const KSocketAddress &getRemote() { return m_remote; }
+
+private:
+ KSocketAddress m_remote;
+};
+
+class KStreamClientIp4 : public KSocket {
+public:
+ KStreamClientIp4() : KSocket() {}
+ ~KStreamClientIp4() {}
+
+ bool setup() {
+ return KSocket::setup(KSocketType::KST_STREAM_CLIENT_IP4,
+ 6 /* IPPROTO_TCP */);
+ }
+
+ bool connect(eastl::string host, eastl::string port) {
+ return KSocket::connect(host, port);
+ }
+ bool bind(uint16_t) = delete;
+ bool listen(int) = delete;
+ bool accept(KAcceptThreadCallback) = delete;
+
+ bool send() { return KSocket::send(); }
+ bool recv(size_t max_recv_size = 65535) {
+ return KSocket::recv(max_recv_size);
+ }
+
+ int getLastError() { return KSocket::getLastError(); }
+};
+
+class KStreamServerIp4 : public KSocket {
+public:
+ KStreamServerIp4() : KSocket() {}
+ ~KStreamServerIp4() {}
+
+ bool setup() {
+ return KSocket::setup(KSocketType::KST_STREAM_SERVER_IP4,
+ 6 /* IPPROTO_TCP */);
+ }
+
+ bool connect(eastl::string host, eastl::string port) = delete;
+ bool bind(uint16_t port) { return KSocket::bind(port); }
+ bool listen(int backlog = 16) { return KSocket::listen(backlog); }
+ bool accept(KAcceptThreadCallback thread_callback) {
+ return KSocket::accept(thread_callback);
+ }
+
+ bool send() { return KSocket::send(); }
+ bool recv(size_t max_recv_size = 65535) {
+ return KSocket::recv(max_recv_size);
+ }
+
+ int getLastError() { return KSocket::getLastError(); }
+};
+
+#endif
diff --git a/ksocket/utils.c b/ksocket/utils.c
new file mode 100644
index 0000000..1fe26ea
--- /dev/null
+++ b/ksocket/utils.c
@@ -0,0 +1,17 @@
+#include "utils.h"
+
+uint64_t htonll(uint64_t hostlonglong) { return __builtin_bswap64(hostlonglong); }
+
+#ifndef BUILD_USERMODE
+uint32_t htonl(uint32_t hostlong) { return __builtin_bswap32(hostlong); }
+
+uint16_t htons(uint16_t hostshort) { return __builtin_bswap16(hostshort); }
+#endif
+
+uint64_t ntohll(uint64_t netlonglong) { return __builtin_bswap64(netlonglong); }
+
+#ifndef BUILD_USERMODE
+uint32_t ntohl(uint32_t netlong) { return __builtin_bswap32(netlong); }
+
+uint16_t ntohs(uint16_t netshort) { return __builtin_bswap16(netshort); }
+#endif
diff --git a/ksocket/utils.h b/ksocket/utils.h
new file mode 100644
index 0000000..e3c0474
--- /dev/null
+++ b/ksocket/utils.h
@@ -0,0 +1,30 @@
+#ifndef KSOCKET_UTILS_H
+#define KSOCKET_UTILS_H 1
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+uint64_t htonll(uint64_t hostlonglong);
+
+#ifndef BUILD_USERMODE
+uint32_t htonl(uint32_t hostlong);
+
+uint16_t htons(uint16_t hostshort);
+#endif
+
+uint64_t ntohll(uint64_t netlonglong);
+
+#ifndef BUILD_USERMODE
+uint32_t ntohl(uint32_t netlong);
+
+uint16_t ntohs(uint16_t netshort);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ksocket/wsk.h b/ksocket/wsk.h
index ccea103..25d7f06 100644
--- a/ksocket/wsk.h
+++ b/ksocket/wsk.h
@@ -1,6 +1,10 @@
#ifndef WSK_H
#define WSK_H 1
+#ifdef BUILD_USERMODE
+#error "This file should only be included if building for kernel mode! Include <ksocket/ksocket.hpp> wrapper instead."
+#endif
+
#include <ntddk.h>
#if !defined(__MINGW64__)