aboutsummaryrefslogtreecommitdiffhomepage
path: root/node_modules/uws/src/Networking.h
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/uws/src/Networking.h')
-rw-r--r--node_modules/uws/src/Networking.h259
1 files changed, 259 insertions, 0 deletions
diff --git a/node_modules/uws/src/Networking.h b/node_modules/uws/src/Networking.h
new file mode 100644
index 0000000..7ae88a2
--- /dev/null
+++ b/node_modules/uws/src/Networking.h
@@ -0,0 +1,259 @@
+// the purpose of this header should be to provide SSL and networking wrapped in a common interface
+// it should allow cross-platform networking and SSL and also easy usage of mTCP and similar tech
+
+#ifndef NETWORKING_UWS_H
+#define NETWORKING_UWS_H
+
+#include <openssl/opensslv.h>
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#define SSL_CTX_up_ref(x) x->references++
+#define SSL_up_ref(x) x->references++
+#endif
+
+#ifndef __linux
+#define MSG_NOSIGNAL 0
+#else
+#include <endian.h>
+#endif
+
+#ifdef __APPLE__
+#include <libkern/OSByteOrder.h>
+#define htobe64(x) OSSwapHostToBigInt64(x)
+#define be64toh(x) OSSwapBigToHostInt64(x)
+#endif
+
+#ifdef _WIN32
+#define NOMINMAX
+#include <WinSock2.h>
+#include <Ws2tcpip.h>
+#pragma comment(lib, "ws2_32.lib")
+#define SHUT_WR SD_SEND
+#ifdef __MINGW32__
+// Windows has always been tied to LE
+#define htobe64(x) __builtin_bswap64(x)
+#define be64toh(x) __builtin_bswap64(x)
+#else
+#define __thread __declspec(thread)
+#define htobe64(x) htonll(x)
+#define be64toh(x) ntohll(x)
+#define pthread_t DWORD
+#define pthread_self GetCurrentThreadId
+#endif
+#define WIN32_EXPORT __declspec(dllexport)
+
+inline void close(SOCKET fd) {closesocket(fd);}
+inline int setsockopt(SOCKET fd, int level, int optname, const void *optval, socklen_t optlen) {
+ return setsockopt(fd, level, optname, (const char *) optval, optlen);
+}
+
+inline SOCKET dup(SOCKET socket) {
+ WSAPROTOCOL_INFOW pi;
+ if (WSADuplicateSocketW(socket, GetCurrentProcessId(), &pi) == SOCKET_ERROR) {
+ return INVALID_SOCKET;
+ }
+ return WSASocketW(pi.iAddressFamily, pi.iSocketType, pi.iProtocol, &pi, 0, WSA_FLAG_OVERLAPPED);
+}
+#else
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <cstring>
+#define SOCKET_ERROR -1
+#define INVALID_SOCKET -1
+#define WIN32_EXPORT
+#endif
+
+#include "Backend.h"
+#include <openssl/ssl.h>
+#include <csignal>
+#include <vector>
+#include <string>
+#include <mutex>
+#include <algorithm>
+#include <memory>
+
+namespace uS {
+
+// todo: mark sockets nonblocking in these functions
+// todo: probably merge this Context with the TLS::Context for same interface for SSL and non-SSL!
+struct Context {
+
+#ifdef USE_MTCP
+ mtcp_context *mctx;
+#endif
+
+ Context() {
+ // mtcp_create_context
+#ifdef USE_MTCP
+ mctx = mtcp_create_context(0); // cpu index?
+#endif
+ }
+
+ ~Context() {
+#ifdef USE_MTCP
+ mtcp_destroy_context(mctx);
+#endif
+ }
+
+ // returns INVALID_SOCKET on error
+ uv_os_sock_t acceptSocket(uv_os_sock_t fd) {
+ uv_os_sock_t acceptedFd;
+#if defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK)
+ // Linux, FreeBSD
+ acceptedFd = accept4(fd, nullptr, nullptr, SOCK_CLOEXEC | SOCK_NONBLOCK);
+#else
+ // Windows, OS X
+ acceptedFd = accept(fd, nullptr, nullptr);
+#endif
+
+#ifdef __APPLE__
+ if (acceptedFd != INVALID_SOCKET) {
+ int noSigpipe = 1;
+ setsockopt(acceptedFd, SOL_SOCKET, SO_NOSIGPIPE, &noSigpipe, sizeof(int));
+ }
+#endif
+ return acceptedFd;
+ }
+
+ // returns INVALID_SOCKET on error
+ uv_os_sock_t createSocket(int domain, int type, int protocol) {
+ int flags = 0;
+#if defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK)
+ flags = SOCK_CLOEXEC | SOCK_NONBLOCK;
+#endif
+
+ uv_os_sock_t createdFd = socket(domain, type | flags, protocol);
+
+#ifdef __APPLE__
+ if (createdFd != INVALID_SOCKET) {
+ int noSigpipe = 1;
+ setsockopt(createdFd, SOL_SOCKET, SO_NOSIGPIPE, &noSigpipe, sizeof(int));
+ }
+#endif
+
+ return createdFd;
+ }
+
+ void closeSocket(uv_os_sock_t fd) {
+#ifdef _WIN32
+ closesocket(fd);
+#else
+ close(fd);
+#endif
+ }
+
+ bool wouldBlock() {
+#ifdef _WIN32
+ return WSAGetLastError() == WSAEWOULDBLOCK;
+#else
+ return errno == EWOULDBLOCK;// || errno == EAGAIN;
+#endif
+ }
+};
+
+namespace TLS {
+
+class WIN32_EXPORT Context {
+private:
+ SSL_CTX *context = nullptr;
+ std::shared_ptr<std::string> password;
+
+ static int passwordCallback(char *buf, int size, int rwflag, void *u)
+ {
+ std::string *password = (std::string *) u;
+ int length = std::min<int>(size, password->length());
+ memcpy(buf, password->data(), length);
+ buf[length] = '\0';
+ return length;
+ }
+
+public:
+ friend Context WIN32_EXPORT createContext(std::string certChainFileName, std::string keyFileName, std::string keyFilePassword);
+ Context(SSL_CTX *context) : context(context) {
+
+ }
+
+ Context() = default;
+ Context(const Context &other);
+ Context &operator=(const Context &other);
+ ~Context();
+ operator bool() {
+ return context;
+ }
+
+ SSL_CTX *getNativeContext() {
+ return context;
+ }
+};
+
+Context WIN32_EXPORT createContext(std::string certChainFileName, std::string keyFileName, std::string keyFilePassword = std::string());
+
+}
+
+struct Socket;
+
+// NodeData is like a Context, maybe merge them?
+struct WIN32_EXPORT NodeData {
+ char *recvBufferMemoryBlock;
+ char *recvBuffer;
+ int recvLength;
+ Loop *loop;
+ uS::Context *netContext;
+ void *user = nullptr;
+ static const int preAllocMaxSize = 1024;
+ char **preAlloc;
+ SSL_CTX *clientContext;
+
+ Async *async = nullptr;
+ pthread_t tid;
+
+ std::recursive_mutex *asyncMutex;
+ std::vector<Poll *> transferQueue;
+ std::vector<Poll *> changePollQueue;
+ static void asyncCallback(Async *async);
+
+ static int getMemoryBlockIndex(size_t length) {
+ return (length >> 4) + bool(length & 15);
+ }
+
+ char *getSmallMemoryBlock(int index) {
+ if (preAlloc[index]) {
+ char *memory = preAlloc[index];
+ preAlloc[index] = nullptr;
+ return memory;
+ } else {
+ return new char[index << 4];
+ }
+ }
+
+ void freeSmallMemoryBlock(char *memory, int index) {
+ if (!preAlloc[index]) {
+ preAlloc[index] = memory;
+ } else {
+ delete [] memory;
+ }
+ }
+
+public:
+ void addAsync() {
+ async = new Async(loop);
+ async->setData(this);
+ async->start(NodeData::asyncCallback);
+ }
+
+ void clearPendingPollChanges(Poll *p) {
+ asyncMutex->lock();
+ changePollQueue.erase(
+ std::remove(changePollQueue.begin(), changePollQueue.end(), p),
+ changePollQueue.end()
+ );
+ asyncMutex->unlock();
+ }
+};
+
+}
+
+#endif // NETWORKING_UWS_H