From 2133be9254088521e03c5a3b2923dc611261d223 Mon Sep 17 00:00:00 2001 From: Relintai Date: Fri, 7 Jan 2022 20:11:34 +0100 Subject: [PATCH] Removed brynet. --- libs/HEADS | 1 - libs/brynet/LICENSE | 21 - libs/brynet/Version.hpp | 3 - libs/brynet/base/Any.hpp | 24 - libs/brynet/base/AppStatus.hpp | 41 - libs/brynet/base/Array.hpp | 101 - libs/brynet/base/Buffer.hpp | 141 - libs/brynet/base/CPP_VERSION.hpp | 16 - libs/brynet/base/Noexcept.hpp | 9 - libs/brynet/base/NonCopyable.hpp | 12 - libs/brynet/base/Packet.hpp | 354 -- libs/brynet/base/Platform.hpp | 9 - libs/brynet/base/Stack.hpp | 140 - libs/brynet/base/Timer.hpp | 139 - libs/brynet/base/WaitGroup.hpp | 56 - libs/brynet/base/crypto/Base64.hpp | 98 - libs/brynet/base/crypto/SHA1.hpp | 566 --- libs/brynet/base/endian/Endian.hpp | 115 - libs/brynet/net/AsyncConnector.hpp | 32 - libs/brynet/net/Channel.hpp | 15 - libs/brynet/net/CurrentThread.hpp | 50 - libs/brynet/net/EventLoop.hpp | 382 -- libs/brynet/net/Exception.hpp | 26 - libs/brynet/net/ListenThread.hpp | 48 - libs/brynet/net/Poller.hpp | 212 -- libs/brynet/net/PromiseReceive.hpp | 128 - libs/brynet/net/SSLHelper.hpp | 151 - libs/brynet/net/SendableMsg.hpp | 47 - libs/brynet/net/Socket.hpp | 186 - libs/brynet/net/SocketLibFunction.hpp | 287 -- libs/brynet/net/SocketLibTypes.hpp | 72 - libs/brynet/net/TcpConnection.hpp | 1044 ------ libs/brynet/net/TcpService.hpp | 38 - libs/brynet/net/detail/ConnectionOption.hpp | 13 - libs/brynet/net/detail/ConnectorDetail.hpp | 128 - libs/brynet/net/detail/ConnectorWorkInfo.hpp | 301 -- libs/brynet/net/detail/IOLoopData.hpp | 51 - libs/brynet/net/detail/ListenThreadDetail.hpp | 140 - libs/brynet/net/detail/TCPServiceDetail.hpp | 142 - libs/brynet/net/detail/WakeupChannel.hpp | 106 - libs/brynet/net/http/HttpFormat.hpp | 196 - libs/brynet/net/http/HttpParser.hpp | 282 -- libs/brynet/net/http/HttpService.hpp | 299 -- libs/brynet/net/http/WebSocketFormat.hpp | 204 -- libs/brynet/net/http/http_parser.h | 3218 ----------------- libs/brynet/net/port/Win.hpp | 24 - libs/brynet/net/wrapper/ConnectionBuilder.hpp | 177 - .../net/wrapper/HttpConnectionBuilder.hpp | 77 - .../brynet/net/wrapper/HttpServiceBuilder.hpp | 64 - libs/brynet/net/wrapper/ServiceBuilder.hpp | 97 - 50 files changed, 10083 deletions(-) delete mode 100644 libs/brynet/LICENSE delete mode 100644 libs/brynet/Version.hpp delete mode 100644 libs/brynet/base/Any.hpp delete mode 100644 libs/brynet/base/AppStatus.hpp delete mode 100644 libs/brynet/base/Array.hpp delete mode 100644 libs/brynet/base/Buffer.hpp delete mode 100644 libs/brynet/base/CPP_VERSION.hpp delete mode 100644 libs/brynet/base/Noexcept.hpp delete mode 100644 libs/brynet/base/NonCopyable.hpp delete mode 100644 libs/brynet/base/Packet.hpp delete mode 100644 libs/brynet/base/Platform.hpp delete mode 100644 libs/brynet/base/Stack.hpp delete mode 100644 libs/brynet/base/Timer.hpp delete mode 100644 libs/brynet/base/WaitGroup.hpp delete mode 100644 libs/brynet/base/crypto/Base64.hpp delete mode 100644 libs/brynet/base/crypto/SHA1.hpp delete mode 100644 libs/brynet/base/endian/Endian.hpp delete mode 100644 libs/brynet/net/AsyncConnector.hpp delete mode 100644 libs/brynet/net/Channel.hpp delete mode 100644 libs/brynet/net/CurrentThread.hpp delete mode 100644 libs/brynet/net/EventLoop.hpp delete mode 100644 libs/brynet/net/Exception.hpp delete mode 100644 libs/brynet/net/ListenThread.hpp delete mode 100644 libs/brynet/net/Poller.hpp delete mode 100644 libs/brynet/net/PromiseReceive.hpp delete mode 100644 libs/brynet/net/SSLHelper.hpp delete mode 100644 libs/brynet/net/SendableMsg.hpp delete mode 100644 libs/brynet/net/Socket.hpp delete mode 100644 libs/brynet/net/SocketLibFunction.hpp delete mode 100644 libs/brynet/net/SocketLibTypes.hpp delete mode 100644 libs/brynet/net/TcpConnection.hpp delete mode 100644 libs/brynet/net/TcpService.hpp delete mode 100644 libs/brynet/net/detail/ConnectionOption.hpp delete mode 100644 libs/brynet/net/detail/ConnectorDetail.hpp delete mode 100644 libs/brynet/net/detail/ConnectorWorkInfo.hpp delete mode 100644 libs/brynet/net/detail/IOLoopData.hpp delete mode 100644 libs/brynet/net/detail/ListenThreadDetail.hpp delete mode 100644 libs/brynet/net/detail/TCPServiceDetail.hpp delete mode 100644 libs/brynet/net/detail/WakeupChannel.hpp delete mode 100644 libs/brynet/net/http/HttpFormat.hpp delete mode 100644 libs/brynet/net/http/HttpParser.hpp delete mode 100644 libs/brynet/net/http/HttpService.hpp delete mode 100644 libs/brynet/net/http/WebSocketFormat.hpp delete mode 100644 libs/brynet/net/http/http_parser.h delete mode 100644 libs/brynet/net/port/Win.hpp delete mode 100644 libs/brynet/net/wrapper/ConnectionBuilder.hpp delete mode 100644 libs/brynet/net/wrapper/HttpConnectionBuilder.hpp delete mode 100644 libs/brynet/net/wrapper/HttpServiceBuilder.hpp delete mode 100644 libs/brynet/net/wrapper/ServiceBuilder.hpp diff --git a/libs/HEADS b/libs/HEADS index 7f78a64..99ec0f7 100644 --- a/libs/HEADS +++ b/libs/HEADS @@ -1,4 +1,3 @@ RapidJSON 0ccdbf364c577803e2a751f5aededce935314313 -brynet a63ac30364641000ccf8f831eea864aa98f1d50d rapidxml 1.13 maddy adb1a910d4aadea09cb7b200f2ec204f61214596 \ No newline at end of file diff --git a/libs/brynet/LICENSE b/libs/brynet/LICENSE deleted file mode 100644 index 3ac9185..0000000 --- a/libs/brynet/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2017 IronsDu - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/libs/brynet/Version.hpp b/libs/brynet/Version.hpp deleted file mode 100644 index 64e3a5d..0000000 --- a/libs/brynet/Version.hpp +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -#define BRYNET_VERSION 1010000 diff --git a/libs/brynet/base/Any.hpp b/libs/brynet/base/Any.hpp deleted file mode 100644 index fa52c58..0000000 --- a/libs/brynet/base/Any.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include - -#ifdef BRYNET_HAVE_LANG_CXX17 -#include -#else -#include -#endif - -#ifdef BRYNET_HAVE_LANG_CXX17 -using BrynetAny = std::any; - -template -auto cast(const BrynetAny &ud) { - return std::any_cast(&ud); -} -#else -using BrynetAny = int64_t; -template -const T *cast(const BrynetAny &ud) { - return static_cast(&ud); -} -#endif diff --git a/libs/brynet/base/AppStatus.hpp b/libs/brynet/base/AppStatus.hpp deleted file mode 100644 index dbe8bd9..0000000 --- a/libs/brynet/base/AppStatus.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include - -#include -#include -#include - -#ifdef BRYNET_PLATFORM_WINDOWS -#include -#else -#include -#include -#include -#endif - -static bool app_kbhit() { -#ifdef BRYNET_PLATFORM_WINDOWS - return _kbhit(); -#else - struct termios oldt; - tcgetattr(STDIN_FILENO, &oldt); - auto newt = oldt; - newt.c_lflag &= ~(ICANON | ECHO); - tcsetattr(STDIN_FILENO, TCSANOW, &newt); - const auto oldf = fcntl(STDIN_FILENO, F_GETFL, 0); - fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK); - - const auto ch = getchar(); - - tcsetattr(STDIN_FILENO, TCSANOW, &oldt); - fcntl(STDIN_FILENO, F_SETFL, oldf); - - if (ch != EOF) { - ungetc(ch, stdin); - return true; - } - - return false; -#endif -} diff --git a/libs/brynet/base/Array.hpp b/libs/brynet/base/Array.hpp deleted file mode 100644 index f245d59..0000000 --- a/libs/brynet/base/Array.hpp +++ /dev/null @@ -1,101 +0,0 @@ -#pragma once - -#include -#include -#include - -struct array_s { - void *buffer; - size_t buffer_size; - size_t element_size; - size_t element_num; -}; - -static void array_delete(struct array_s *self) { - if (self == nullptr) { - return; - } - - if (self->buffer != nullptr) { - free(self->buffer); - self->buffer = nullptr; - } - - self->element_num = 0; - free(self); - self = nullptr; -} - -static struct array_s *array_new(size_t num, size_t element_size) { - auto ret = (struct array_s *)malloc(sizeof(struct array_s)); - if (ret == nullptr) { - return nullptr; - } - - const auto buffer_size = num * element_size; - - ret->buffer_size = 0; - ret->element_size = 0; - ret->element_num = 0; - ret->buffer = malloc(buffer_size); - - if (ret->buffer != nullptr) { - ret->element_size = element_size; - ret->element_num = num; - ret->buffer_size = buffer_size; - } else { - array_delete(ret); - ret = nullptr; - } - - return ret; -} - -static void *array_at(struct array_s *self, size_t index) { - void *ret = nullptr; - - if (index < self->element_num) { - ret = (char *)(self->buffer) + (index * self->element_size); - } else { - assert(false); - } - - return ret; -} - -static bool array_set(struct array_s *self, size_t index, const void *data) { - void *old_data = array_at(self, index); - - if (old_data != nullptr) { - memcpy(old_data, data, self->element_size); - return true; - } else { - return false; - } -} - -static bool array_increase(struct array_s *self, size_t increase_num) { - if (increase_num == 0) { - return false; - } - - const auto new_buffer_size = self->buffer_size + increase_num * self->element_size; - auto new_buffer = malloc(new_buffer_size); - - if (new_buffer != nullptr) { - memcpy(new_buffer, self->buffer, self->buffer_size); - free(self->buffer); - self->buffer = new_buffer; - self->element_num += increase_num; - self->buffer_size = new_buffer_size; - - return true; - } else { - assert(false); - return false; - } -} - -static size_t array_num(const struct array_s *self) { - return self->element_num; -} diff --git a/libs/brynet/base/Buffer.hpp b/libs/brynet/base/Buffer.hpp deleted file mode 100644 index dcb53bf..0000000 --- a/libs/brynet/base/Buffer.hpp +++ /dev/null @@ -1,141 +0,0 @@ -#pragma once - -#include -#include - -struct buffer_s { - char *data; - size_t data_len; - - size_t write_pos; - size_t read_pos; -}; - -static void buffer_delete(struct buffer_s *self) { - if (self == nullptr) { - return; - } - - if (self->data != nullptr) { - free(self->data); - self->data = nullptr; - } - - free(self); - self = nullptr; -} - -static struct buffer_s *buffer_new(size_t buffer_size) { - struct buffer_s *ret = (struct buffer_s *)malloc(sizeof(struct buffer_s)); - if (ret == nullptr) { - return nullptr; - } - - ret->data_len = 0; - ret->read_pos = 0; - ret->write_pos = 0; - ret->data = (char *)malloc(sizeof(char) * buffer_size); - - if (ret->data != nullptr) { - ret->data_len = buffer_size; - } else { - buffer_delete(ret); - ret = nullptr; - } - - return ret; -} - -static size_t buffer_getreadvalidcount(struct buffer_s *self) { - return self->write_pos - self->read_pos; -} - -static void buffer_adjustto_head(struct buffer_s *self) { - if (self->read_pos == 0) { - return; - } - - const auto len = buffer_getreadvalidcount(self); - if (len > 0) { - memmove(self->data, self->data + self->read_pos, len); - } - - self->read_pos = 0; - self->write_pos = len; -} - -static void buffer_init(struct buffer_s *self) { - self->read_pos = 0; - self->write_pos = 0; -} - -static size_t buffer_getwritepos(struct buffer_s *self) { - return self->write_pos; -} - -static size_t buffer_getreadpos(struct buffer_s *self) { - return self->read_pos; -} - -static bool buffer_addwritepos(struct buffer_s *self, size_t value) { - const size_t temp = self->write_pos + value; - if (temp <= self->data_len) { - self->write_pos = temp; - return true; - } else { - return false; - } -} - -static bool buffer_addreadpos(struct buffer_s *self, size_t value) { - const size_t temp = self->read_pos + value; - if (temp <= self->data_len) { - self->read_pos = temp; - return true; - } else { - return false; - } -} - -static size_t buffer_getwritevalidcount(struct buffer_s *self) { - return self->data_len - self->write_pos; -} - -static size_t buffer_getsize(struct buffer_s *self) { - return self->data_len; -} - -static char *buffer_getwriteptr(struct buffer_s *self) { - if (self->write_pos < self->data_len) { - return self->data + self->write_pos; - } else { - return nullptr; - } -} - -static char *buffer_getreadptr(struct buffer_s *self) { - if (self->read_pos < self->data_len) { - return self->data + self->read_pos; - } else { - return nullptr; - } -} - -static bool buffer_write(struct buffer_s *self, const char *data, size_t len) { - bool write_ret = true; - - if (buffer_getwritevalidcount(self) >= len) { - memcpy(buffer_getwriteptr(self), data, len); - buffer_addwritepos(self, len); - } else { - size_t left_len = self->data_len - buffer_getreadvalidcount(self); - if (left_len >= len) { - buffer_adjustto_head(self); - buffer_write(self, data, len); - } else { - write_ret = false; - } - } - - return write_ret; -} diff --git a/libs/brynet/base/CPP_VERSION.hpp b/libs/brynet/base/CPP_VERSION.hpp deleted file mode 100644 index 6046ba2..0000000 --- a/libs/brynet/base/CPP_VERSION.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#if (__cplusplus >= 201103L || \ - (defined(_MSC_VER) && _MSC_VER >= 1800)) -#define BRYNET_HAVE_LANG_CXX11 1 -#endif - -#if (__cplusplus >= 201402L || \ - (defined(_MSC_VER) && _MSC_VER >= 1900)) -#define BRYNET_HAVE_LANG_CXX14 1 -#endif - -#if (__cplusplus >= 201703L || \ - (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)) -#define BRYNET_HAVE_LANG_CXX17 1 -#endif diff --git a/libs/brynet/base/Noexcept.hpp b/libs/brynet/base/Noexcept.hpp deleted file mode 100644 index 316de5e..0000000 --- a/libs/brynet/base/Noexcept.hpp +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#include - -#ifdef BRYNET_HAVE_LANG_CXX17 -#define BRYNET_NOEXCEPT noexcept -#else -#define BRYNET_NOEXCEPT -#endif diff --git a/libs/brynet/base/NonCopyable.hpp b/libs/brynet/base/NonCopyable.hpp deleted file mode 100644 index bfae215..0000000 --- a/libs/brynet/base/NonCopyable.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -class NonCopyable { -public: - NonCopyable(const NonCopyable &) = delete; - const NonCopyable &operator=(const NonCopyable &) = delete; - -protected: - NonCopyable() = default; - ~NonCopyable() = default; -}; - diff --git a/libs/brynet/base/Packet.hpp b/libs/brynet/base/Packet.hpp deleted file mode 100644 index ee6774b..0000000 --- a/libs/brynet/base/Packet.hpp +++ /dev/null @@ -1,354 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -class BasePacketWriter : public NonCopyable { -public: - BasePacketWriter(char *buffer, size_t len, bool useBigEndian = false, bool isAutoMalloc = false) : - mIsAutoMalloc(isAutoMalloc), mBigEndian(useBigEndian) { - mMaxLen = len; - mPos = 0; - mBuffer = buffer; - mMallocBuffer = nullptr; - } - - virtual ~BasePacketWriter() { - if (mMallocBuffer != nullptr) { - free(mMallocBuffer); - mMallocBuffer = nullptr; - } - } - - void init() { - mPos = 0; - } - - size_t getMaxLen() const { - return mMaxLen; - } - - size_t getPos() const { - return mPos; - } - - const char *getData() const { - return mBuffer; - } - - bool isAutoGrow() const { - return mIsAutoMalloc; - } - - bool writeBool(bool value) { - static_assert(sizeof(bool) == sizeof(int8_t), ""); - return writeBuffer((char *)&value, sizeof(value)); - } - bool writeINT8(int8_t value) { - return writeBuffer((char *)&value, sizeof(value)); - } - bool writeUINT8(uint8_t value) { - return writeBuffer((char *)&value, sizeof(value)); - } - bool writeINT16(int16_t value) { - value = hostToNetwork16(value, mBigEndian); - return writeBuffer((char *)&value, sizeof(value)); - } - bool writeUINT16(uint16_t value) { - value = hostToNetwork16(value, mBigEndian); - return writeBuffer((char *)&value, sizeof(value)); - } - bool writeINT32(int32_t value) { - value = hostToNetwork32(value, mBigEndian); - return writeBuffer((char *)&value, sizeof(value)); - } - bool writeUINT32(uint32_t value) { - value = hostToNetwork32(value, mBigEndian); - return writeBuffer((char *)&value, sizeof(value)); - } - bool writeINT64(int64_t value) { - value = hostToNetwork64(value, mBigEndian); - return writeBuffer((char *)&value, sizeof(value)); - } - bool writeUINT64(uint64_t value) { - value = hostToNetwork64(value, mBigEndian); - return writeBuffer((char *)&value, sizeof(value)); - } - - bool writeBinary(const std::string &binary) { - return writeBuffer(binary.c_str(), binary.size()); - } - bool writeBinary(const char *binary, size_t binaryLen) { - return writeBuffer(binary, binaryLen); - } - bool writeBuffer(const char *buffer, size_t len) { - growBuffer(len); - - if (mMaxLen < (mPos + len)) { - return false; - } - - memcpy(mBuffer + mPos, buffer, len); - mPos += len; - return true; - } - - BasePacketWriter &operator<<(const bool &v) { - writeBool(v); - return *this; - } - BasePacketWriter &operator<<(const uint8_t &v) { - writeUINT8(v); - return *this; - } - BasePacketWriter &operator<<(const int8_t &v) { - writeINT8(v); - return *this; - } - BasePacketWriter &operator<<(const int16_t &v) { - writeINT16(v); - return *this; - } - BasePacketWriter &operator<<(const uint16_t &v) { - writeUINT16(v); - return *this; - } - BasePacketWriter &operator<<(const int32_t &v) { - writeINT32(v); - return *this; - } - BasePacketWriter &operator<<(const uint32_t &v) { - writeUINT32(v); - return *this; - } - BasePacketWriter &operator<<(const int64_t &v) { - writeINT64(v); - return *this; - } - BasePacketWriter &operator<<(const uint64_t &v) { - writeUINT64(v); - return *this; - } - BasePacketWriter &operator<<(const char *const &v) { - writeBinary(v); - return *this; - } - BasePacketWriter &operator<<(const std::string &v) { - writeBinary(v); - return *this; - } - -private: - // 为了避免直接<<导致没有指定字节序导致隐藏BUG,因为此函数设置为私有 - template - BasePacketWriter &operator<<(const T &v) { - static_assert(!std::is_pointer::value, "T must is't a pointer"); - static_assert(std::is_class::value, "T must a class or struct type"); - static_assert(std::is_pod::value, "T must a pod type"); - writeBuffer((const char *)&v, sizeof(v)); - return *this; - } - - template - void writev(const Arg1 &arg1, const Args &...args) { - this->operator<<(arg1); - writev(args...); - } - - void writev() { - } - -protected: - void growBuffer(size_t len) { - if (!mIsAutoMalloc || (mPos + len) <= mMaxLen) { - return; - } - - auto newBuffer = (char *)malloc(mMaxLen + len); - if (newBuffer == nullptr) { - return; - } - - memcpy(newBuffer, mBuffer, mPos); - - if (mMallocBuffer != nullptr) { - free(mMallocBuffer); - mMallocBuffer = nullptr; - } - - mMaxLen += len; - mMallocBuffer = newBuffer; - mBuffer = newBuffer; - } - -protected: - const bool mIsAutoMalloc; - bool mBigEndian; - size_t mPos; - size_t mMaxLen; - char *mBuffer; - char *mMallocBuffer; -}; - -class BasePacketReader { -public: - BasePacketReader(const char *buffer, - size_t len, - bool useBigEndian = false) : - mBigEndian(useBigEndian), - mSize(len) { - mPos = 0; - mSavedPos = 0; - mBuffer = buffer; - } - - virtual ~BasePacketReader() = default; - - void useBigEndian() { - mBigEndian = true; - } - - void useLittleEndian() { - mBigEndian = false; - } - - void savePos() { - mSavedPos = mPos; - } - - size_t savedPos() const { - return mSavedPos; - } - - size_t getLeft() const { - if (mPos > mSize) { - throw std::out_of_range("current pos is greater than max len"); - } - return mSize - mPos; - } - - bool enough(size_t len) const { - if (mPos > mSize) { - return false; - } - return (mSize - mPos) >= len; - } - - const char *begin() const { - return mBuffer; - } - - const char *currentBuffer() const { - return mBuffer + mPos; - } - - void consumeAll() { - mPos = mSize; - savePos(); - } - - size_t currentPos() const { - return mPos; - } - - size_t size() const { - return mSize; - } - - void addPos(size_t diff) { - const auto tmpPos = mPos + diff; - if (tmpPos > mSize) { - throw std::out_of_range("diff is to big"); - } - - mPos = tmpPos; - } - - bool readBool() { - static_assert(sizeof(bool) == sizeof(int8_t), ""); - bool value = false; - read(value); - return value; - } - int8_t readINT8() { - int8_t value = 0; - read(value); - return value; - } - uint8_t readUINT8() { - uint8_t value = 0; - read(value); - return value; - } - int16_t readINT16() { - int16_t value = 0; - read(value); - return networkToHost16(value, mBigEndian); - } - uint16_t readUINT16() { - uint16_t value = 0; - read(value); - return networkToHost16(value, mBigEndian); - } - int32_t readINT32() { - int32_t value = 0; - read(value); - return networkToHost32(value, mBigEndian); - } - uint32_t readUINT32() { - uint32_t value = 0; - read(value); - return networkToHost32(value, mBigEndian); - } - int64_t readINT64() { - int64_t value = 0; - read(value); - return networkToHost64(value, mBigEndian); - } - uint64_t readUINT64() { - uint64_t value = 0; - read(value); - return networkToHost64(value, mBigEndian); - } - -private: - // 为了避免直接read(uintXXX)导致没有指定字节序造成隐患BUG,因为此函数设置为私有 - template - void read(T &value) { - static_assert(std::is_same::type>::value, - "T must a normal type"); - static_assert(std::is_pod::value, - "T must a pod type"); - - if ((mPos + sizeof(value)) > mSize) { - throw std::out_of_range("T size is to big"); - } - - value = *(T *)(mBuffer + mPos); - mPos += sizeof(value); - } - -protected: - bool mBigEndian; - const size_t mSize; - const char *mBuffer; - size_t mPos; - size_t mSavedPos; -}; - -template -class AutoMallocPacket : public BasePacketWriter { -public: - explicit AutoMallocPacket(bool useBigEndian = false, - bool isAutoMalloc = false) : - BasePacketWriter(mData, SIZE, useBigEndian, isAutoMalloc) {} - -private: - char mData[SIZE]; -}; - -using BigPacket = AutoMallocPacket<32 * 1024>; diff --git a/libs/brynet/base/Platform.hpp b/libs/brynet/base/Platform.hpp deleted file mode 100644 index 763118c..0000000 --- a/libs/brynet/base/Platform.hpp +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#if defined _MSC_VER || defined __MINGW32__ -#define BRYNET_PLATFORM_WINDOWS -#elif defined __APPLE_CC__ || defined __APPLE__ -#define BRYNET_PLATFORM_DARWIN -#else -#define BRYNET_PLATFORM_LINUX -#endif diff --git a/libs/brynet/base/Stack.hpp b/libs/brynet/base/Stack.hpp deleted file mode 100644 index 8b68018..0000000 --- a/libs/brynet/base/Stack.hpp +++ /dev/null @@ -1,140 +0,0 @@ -#pragma once - -#include -#include - -struct stack_s { - struct array_s *array; - size_t element_size; - - size_t element_num; - size_t front; - size_t num; -}; - -static void stack_delete(struct stack_s *self) { - if (self == nullptr) { - return; - } - - if (self->array != nullptr) { - array_delete(self->array); - self->array = nullptr; - } - - self->element_num = 0; - self->front = 0; - self->num = 0; - free(self); - self = nullptr; -} - -static struct stack_s *stack_new(size_t num, size_t element_size) { - struct stack_s *ret = (struct stack_s *)malloc(sizeof(struct stack_s)); - if (ret == nullptr) { - return nullptr; - } - - ret->element_size = 0; - ret->element_num = 0; - ret->front = 0; - ret->num = 0; - ret->array = array_new(num, element_size); - - if (ret->array != nullptr) { - ret->element_size = element_size; - ret->element_num = num; - } else { - stack_delete(ret); - ret = nullptr; - } - - return ret; -} - -static void stack_init(struct stack_s *self) { - self->front = 0; - self->num = 0; -} - -static size_t stack_num(struct stack_s *self) { - return self->num; -} - -static bool stack_increase(struct stack_s *self, size_t increase_num) { - struct array_s *tmp = array_new(self->element_num + increase_num, - self->element_size); - if (tmp == nullptr) { - return false; - } - - { - size_t current_num = self->element_num; - size_t current_stack_num = stack_num(self); - for (size_t i = 0; i < current_stack_num; ++i) { - array_set(tmp, i, array_at(self->array, (self->front + i) % current_num)); - } - - self->front = 0; - array_delete(self->array); - self->array = tmp; - self->element_num = array_num(self->array); - } - - return true; -} - -static size_t stack_size(struct stack_s *self) { - return self->element_num; -} - -static bool stack_isfull(struct stack_s *self) { - return (self->num == self->element_num); -} - -static bool stack_push(struct stack_s *self, const void *data) { - if (stack_isfull(self)) { - stack_increase(self, stack_size(self)); - } - - if (stack_isfull(self)) { - return false; - } - - array_set(self->array, (self->front + self->num) % self->element_num, data); - self->num++; - return true; -} - -static void *stack_front(struct stack_s *self) { - void *ret = nullptr; - - if (stack_num(self) > 0) { - ret = array_at(self->array, self->front); - } - - return ret; -} - -static void *stack_popfront(struct stack_s *self) { - void *ret = stack_front(self); - - if (ret != nullptr) { - self->num--; - self->front++; - self->front %= self->element_num; - } - - return ret; -} - -static void *stack_popback(struct stack_s *self) { - void *ret = nullptr; - - if (stack_num(self) > 0) { - self->num--; - ret = array_at(self->array, (self->front + self->num) % self->element_num); - } - - return ret; -} diff --git a/libs/brynet/base/Timer.hpp b/libs/brynet/base/Timer.hpp deleted file mode 100644 index 8a3ad7d..0000000 --- a/libs/brynet/base/Timer.hpp +++ /dev/null @@ -1,139 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -class TimerMgr; - -class Timer final { -public: - using Ptr = std::shared_ptr; - using WeakPtr = std::weak_ptr; - using Callback = std::function; - - Timer(std::chrono::steady_clock::time_point startTime, - std::chrono::nanoseconds lastTime, - Callback &&callback) BRYNET_NOEXCEPT - : mCallback(std::move(callback)), - mStartTime(startTime), - mLastTime(lastTime) { - } - - const std::chrono::steady_clock::time_point &getStartTime() const { - return mStartTime; - } - - const std::chrono::nanoseconds &getLastTime() const { - return mLastTime; - } - - std::chrono::nanoseconds getLeftTime() const { - const auto now = std::chrono::steady_clock::now(); - return getLastTime() - (now - getStartTime()); - } - - void cancel() { - std::call_once(mExecuteOnceFlag, [this]() { - mCallback = nullptr; - }); - } - -private: - void operator()() { - Callback callback; - std::call_once(mExecuteOnceFlag, [&callback, this]() { - callback = std::move(mCallback); - mCallback = nullptr; - }); - - if (callback != nullptr) { - callback(); - } - } - -private: - std::once_flag mExecuteOnceFlag; - Callback mCallback; - const std::chrono::steady_clock::time_point mStartTime; - const std::chrono::nanoseconds mLastTime; - - friend class TimerMgr; -}; - -class TimerMgr final { -public: - using Ptr = std::shared_ptr; - - template - Timer::WeakPtr addTimer( - std::chrono::nanoseconds timeout, - F &&callback, - TArgs &&...args) { - auto timer = std::make_shared( - std::chrono::steady_clock::now(), - std::chrono::nanoseconds(timeout), - std::bind(std::forward(callback), std::forward(args)...)); - mTimers.push(timer); - - return timer; - } - - void addTimer(const Timer::Ptr &timer) { - mTimers.push(timer); - } - - void schedule() { - while (!mTimers.empty()) { - auto tmp = mTimers.top(); - if (tmp->getLeftTime() > std::chrono::nanoseconds::zero()) { - break; - } - - mTimers.pop(); - (*tmp)(); - } - } - - bool isEmpty() const { - return mTimers.empty(); - } - - // if timer empty, return zero - std::chrono::nanoseconds nearLeftTime() const { - if (mTimers.empty()) { - return std::chrono::nanoseconds::zero(); - } - - auto result = mTimers.top()->getLeftTime(); - if (result < std::chrono::nanoseconds::zero()) { - return std::chrono::nanoseconds::zero(); - } - - return result; - } - - void clear() { - while (!mTimers.empty()) { - mTimers.pop(); - } - } - -private: - class CompareTimer { - public: - bool operator()(const Timer::Ptr &left, - const Timer::Ptr &right) const { - const auto startDiff = left->getStartTime() - right->getStartTime(); - const auto lastDiff = left->getLastTime() - right->getLastTime(); - const auto diff = startDiff.count() + lastDiff.count(); - return diff > 0; - } - }; - - std::priority_queue, CompareTimer> mTimers; -}; diff --git a/libs/brynet/base/WaitGroup.hpp b/libs/brynet/base/WaitGroup.hpp deleted file mode 100644 index e07b5ea..0000000 --- a/libs/brynet/base/WaitGroup.hpp +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -class WaitGroup : public NonCopyable { -public: - typedef std::shared_ptr Ptr; - - static Ptr Create() { - struct make_shared_enabler : public WaitGroup { - }; - return std::make_shared(); - } - -public: - void add(int i = 1) { - mCounter += i; - } - - void done() { - mCounter--; - mCond.notify_all(); - } - - void wait() { - std::unique_lock l(mMutex); - mCond.wait(l, [&] { - return mCounter <= 0; - }); - } - - template - void wait(const std::chrono::duration &timeout) { - std::unique_lock l(mMutex); - mCond.wait_for(l, timeout, [&] { - return mCounter <= 0; - }); - } - -private: - WaitGroup() : - mCounter(0) { - } - - virtual ~WaitGroup() = default; - -private: - std::mutex mMutex; - std::atomic mCounter; - std::condition_variable mCond; -}; diff --git a/libs/brynet/base/crypto/Base64.hpp b/libs/brynet/base/crypto/Base64.hpp deleted file mode 100644 index c83c57f..0000000 --- a/libs/brynet/base/crypto/Base64.hpp +++ /dev/null @@ -1,98 +0,0 @@ -#ifndef _BRYNET_BASE_BASE64_H -#define _BRYNET_BASE_BASE64_H - -#include - -static const std::string base64_chars = - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789+/"; - -static bool is_base64(unsigned char c) { - return (isalnum(c) || (c == '+') || (c == '/')); -} - -static std::string base64_encode(unsigned char const *bytes_to_encode, unsigned int in_len) { - std::string ret; - int i = 0; - int j = 0; - unsigned char char_array_3[3]; - unsigned char char_array_4[4]; - - while (in_len--) { - char_array_3[i++] = *(bytes_to_encode++); - if (i == 3) { - char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; - char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); - char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); - char_array_4[3] = char_array_3[2] & 0x3f; - - for (i = 0; (i < 4); i++) - ret += base64_chars[char_array_4[i]]; - i = 0; - } - } - - if (i) { - for (j = i; j < 3; j++) - char_array_3[j] = '\0'; - - char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; - char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); - char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); - char_array_4[3] = char_array_3[2] & 0x3f; - - for (j = 0; (j < i + 1); j++) - ret += base64_chars[char_array_4[j]]; - - while ((i++ < 3)) - ret += '='; - } - - return ret; -} - -static std::string base64_decode(std::string const &encoded_string) { - int in_len = encoded_string.size(); - int i = 0; - int j = 0; - int in_ = 0; - unsigned char char_array_4[4], char_array_3[3]; - std::string ret; - - while (in_len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_])) { - char_array_4[i++] = encoded_string[in_]; - in_++; - if (i == 4) { - for (i = 0; i < 4; i++) - char_array_4[i] = base64_chars.find(char_array_4[i]); - - char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); - char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); - char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; - - for (i = 0; (i < 3); i++) - ret += char_array_3[i]; - i = 0; - } - } - - if (i) { - for (j = i; j < 4; j++) - char_array_4[j] = 0; - - for (j = 0; j < 4; j++) - char_array_4[j] = base64_chars.find(char_array_4[j]); - - char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); - char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); - char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; - - for (j = 0; (j < i - 1); j++) - ret += char_array_3[j]; - } - - return ret; -} - -#endif \ No newline at end of file diff --git a/libs/brynet/base/crypto/SHA1.hpp b/libs/brynet/base/crypto/SHA1.hpp deleted file mode 100644 index 4c88921..0000000 --- a/libs/brynet/base/crypto/SHA1.hpp +++ /dev/null @@ -1,566 +0,0 @@ -/* - 100% free public domain implementation of the SHA-1 algorithm - by Dominik Reichl - Web: http://www.dominik-reichl.de/ - - Version 2.1 - 2012-06-19 - - Deconstructor (resetting internal variables) is now only - implemented if SHA1_WIPE_VARIABLES is defined (which is the - default). - - Renamed inclusion guard to contain a GUID. - - Demo application is now using C++/STL objects and functions. - - Unicode build of the demo application now outputs the hashes of both - the ANSI and Unicode representations of strings. - - Various other demo application improvements. - - Version 2.0 - 2012-06-14 - - Added 'limits.h' include. - - Renamed inclusion guard and macros for compliancy (names beginning - with an underscore are reserved). - - Version 1.9 - 2011-11-10 - - Added Unicode test vectors. - - Improved support for hashing files using the HashFile method that - are larger than 4 GB. - - Improved file hashing performance (by using a larger buffer). - - Disabled unnecessary compiler warnings. - - Internal variables are now private. - - Version 1.8 - 2009-03-16 - - Converted project files to Visual Studio 2008 format. - - Added Unicode support for HashFile utility method. - - Added support for hashing files using the HashFile method that are - larger than 2 GB. - - HashFile now returns an error code instead of copying an error - message into the output buffer. - - GetHash now returns an error code and validates the input parameter. - - Added ReportHashStl STL utility method. - - Added REPORT_HEX_SHORT reporting mode. - - Improved Linux compatibility of test program. - - Version 1.7 - 2006-12-21 - - Fixed buffer underrun warning that appeared when compiling with - Borland C Builder (thanks to Rex Bloom and Tim Gallagher for the - patch). - - Breaking change: ReportHash writes the final hash to the start - of the buffer, i.e. it's not appending it to the string anymore. - - Made some function parameters const. - - Added Visual Studio 2005 project files to demo project. - - Version 1.6 - 2005-02-07 (thanks to Howard Kapustein for patches) - - You can set the endianness in your files, no need to modify the - header file of the CSHA1 class anymore. - - Aligned data support. - - Made support/compilation of the utility functions (ReportHash and - HashFile) optional (useful when bytes count, for example in embedded - environments). - - Version 1.5 - 2005-01-01 - - 64-bit compiler compatibility added. - - Made variable wiping optional (define SHA1_WIPE_VARIABLES). - - Removed unnecessary variable initializations. - - ROL32 improvement for the Microsoft compiler (using _rotl). - - Version 1.4 - 2004-07-22 - - CSHA1 now compiles fine with GCC 3.3 under Mac OS X (thanks to Larry - Hastings). - - Version 1.3 - 2003-08-17 - - Fixed a small memory bug and made a buffer array a class member to - ensure correct working when using multiple CSHA1 class instances at - one time. - - Version 1.2 - 2002-11-16 - - Borlands C++ compiler seems to have problems with string addition - using sprintf. Fixed the bug which caused the digest report function - not to work properly. CSHA1 is now Borland compatible. - - Version 1.1 - 2002-10-11 - - Removed two unnecessary header file includes and changed BOOL to - bool. Fixed some minor bugs in the web page contents. - - Version 1.0 - 2002-06-20 - - First official release. - - ================ Test Vectors ================ - - SHA1("abc" in ANSI) = - A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D - SHA1("abc" in Unicode LE) = - 9F04F41A 84851416 2050E3D6 8C1A7ABB 441DC2B5 - - SHA1("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" - in ANSI) = - 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 - SHA1("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" - in Unicode LE) = - 51D7D876 9AC72C40 9C5B0E3F 69C60ADC 9A039014 - - SHA1(A million repetitions of "a" in ANSI) = - 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F - SHA1(A million repetitions of "a" in Unicode LE) = - C4609560 A108A0C6 26AA7F2B 38A65566 739353C5 -*/ - -#ifndef SHA1_H_A545E61D43E9404E8D736869AB3CBFE7 -#define SHA1_H_A545E61D43E9404E8D736869AB3CBFE7 - -#if !defined(SHA1_UTILITY_FUNCTIONS) && !defined(SHA1_NO_UTILITY_FUNCTIONS) -#define SHA1_UTILITY_FUNCTIONS -#endif - -#if !defined(SHA1_STL_FUNCTIONS) && !defined(SHA1_NO_STL_FUNCTIONS) -#define SHA1_STL_FUNCTIONS -#if !defined(SHA1_UTILITY_FUNCTIONS) -#error STL functions require SHA1_UTILITY_FUNCTIONS. -#endif -#endif - -#include -#include - -#ifdef SHA1_UTILITY_FUNCTIONS -#include -#include -#endif - -#ifdef SHA1_STL_FUNCTIONS -#include -#endif - -#ifdef _MSC_VER -#include -#endif - -// You can define the endian mode in your files without modifying the SHA-1 -// source files. Just #define SHA1_LITTLE_ENDIAN or #define SHA1_BIG_ENDIAN -// in your files, before including the SHA1.h header file. If you don't -// define anything, the class defaults to little endian. -#if !defined(SHA1_LITTLE_ENDIAN) && !defined(SHA1_BIG_ENDIAN) -#define SHA1_LITTLE_ENDIAN -#endif - -// If you want variable wiping, #define SHA1_WIPE_VARIABLES, if not, -// #define SHA1_NO_WIPE_VARIABLES. If you don't define anything, it -// defaults to wiping. -#if !defined(SHA1_WIPE_VARIABLES) && !defined(SHA1_NO_WIPE_VARIABLES) -#define SHA1_WIPE_VARIABLES -#endif - -#if defined(SHA1_HAS_TCHAR) -#include -#else -#ifdef _MSC_VER -#include -#else -#ifndef TCHAR -#define TCHAR char -#endif -#ifndef _T -#define _T(__x) (__x) -#define _tmain main -#define _tprintf printf -#define _getts gets -#define _tcslen strlen -#define _tfopen fopen -#define _tcscpy strcpy -#define _tcscat strcat -#define _sntprintf snprintf -#endif -#endif -#endif - -/////////////////////////////////////////////////////////////////////////// -// Define variable types - -#ifndef UINT_8 -#ifdef _MSC_VER // Compiling with Microsoft compiler -#define UINT_8 unsigned __int8 -#else // !_MSC_VER -#define UINT_8 unsigned char -#endif // _MSC_VER -#endif - -#ifndef UINT_32 -#ifdef _MSC_VER // Compiling with Microsoft compiler -#define UINT_32 unsigned __int32 -#else // !_MSC_VER -#if (ULONG_MAX == 0xFFFFFFFFUL) -#define UINT_32 unsigned long -#else -#define UINT_32 unsigned int -#endif -#endif // _MSC_VER -#endif // UINT_32 - -#ifndef INT_64 -#ifdef _MSC_VER // Compiling with Microsoft compiler -#define INT_64 __int64 -#else // !_MSC_VER -#define INT_64 long long -#endif // _MSC_VER -#endif // INT_64 - -#ifndef UINT_64 -#ifdef _MSC_VER // Compiling with Microsoft compiler -#define UINT_64 unsigned __int64 -#else // !_MSC_VER -#define UINT_64 unsigned long long -#endif // _MSC_VER -#endif // UINT_64 - -/////////////////////////////////////////////////////////////////////////// -// Declare SHA-1 workspace - -typedef union { - UINT_8 c[64]; - UINT_32 l[16]; -} SHA1_WORKSPACE_BLOCK; - -#define SHA1_MAX_FILE_BUFFER (32 * 20 * 820) - -// Rotate p_val32 by p_nBits bits to the left -#ifndef ROL32 -#ifdef _MSC_VER -#define ROL32(p_val32, p_nBits) _rotl(p_val32, p_nBits) -#else -#define ROL32(p_val32, p_nBits) (((p_val32) << (p_nBits)) | ((p_val32) >> (32 - (p_nBits)))) -#endif -#endif - -#ifdef SHA1_LITTLE_ENDIAN -#define SHABLK0(i) (m_block->l[i] = \ - (ROL32(m_block->l[i], 24) & 0xFF00FF00) | (ROL32(m_block->l[i], 8) & 0x00FF00FF)) -#else -#define SHABLK0(i) (m_block->l[i]) -#endif - -#define SHABLK(i) (m_block->l[i & 15] = ROL32(m_block->l[(i + 13) & 15] ^ \ - m_block->l[(i + 8) & 15] ^ m_block->l[(i + 2) & 15] ^ m_block->l[i & 15], \ - 1)) - -// SHA-1 rounds -#define S_R0(v, w, x, y, z, i) \ - { \ - z += ((w & (x ^ y)) ^ y) + SHABLK0(i) + 0x5A827999 + ROL32(v, 5); \ - w = ROL32(w, 30); \ - } -#define S_R1(v, w, x, y, z, i) \ - { \ - z += ((w & (x ^ y)) ^ y) + SHABLK(i) + 0x5A827999 + ROL32(v, 5); \ - w = ROL32(w, 30); \ - } -#define S_R2(v, w, x, y, z, i) \ - { \ - z += (w ^ x ^ y) + SHABLK(i) + 0x6ED9EBA1 + ROL32(v, 5); \ - w = ROL32(w, 30); \ - } -#define S_R3(v, w, x, y, z, i) \ - { \ - z += (((w | x) & y) | (w & x)) + SHABLK(i) + 0x8F1BBCDC + ROL32(v, 5); \ - w = ROL32(w, 30); \ - } -#define S_R4(v, w, x, y, z, i) \ - { \ - z += (w ^ x ^ y) + SHABLK(i) + 0xCA62C1D6 + ROL32(v, 5); \ - w = ROL32(w, 30); \ - } - -class CSHA1 { -public: -#ifdef SHA1_UTILITY_FUNCTIONS - // Different formats for ReportHash(Stl) - enum REPORT_TYPE { - REPORT_HEX = 0, - REPORT_DIGIT = 1, - REPORT_HEX_SHORT = 2 - }; -#endif - - // Constructor and destructor - CSHA1() { - (void)m_reserved0; - (void)m_reserved1; - m_block = (SHA1_WORKSPACE_BLOCK *)m_workspace; - - Reset(); - } - -#ifdef SHA1_WIPE_VARIABLES - ~CSHA1() { - Reset(); - } -#endif - - void Reset() { - // SHA1 initialization constants - m_state[0] = 0x67452301; - m_state[1] = 0xEFCDAB89; - m_state[2] = 0x98BADCFE; - m_state[3] = 0x10325476; - m_state[4] = 0xC3D2E1F0; - - m_count[0] = 0; - m_count[1] = 0; - } - - // Hash in binary data and strings - void Update(const UINT_8 *pbData, UINT_32 uLen) { - UINT_32 j = ((m_count[0] >> 3) & 0x3F); - - if ((m_count[0] += (uLen << 3)) < (uLen << 3)) - ++m_count[1]; // Overflow - - m_count[1] += (uLen >> 29); - - UINT_32 i; - if ((j + uLen) > 63) { - i = 64 - j; - memcpy(&m_buffer[j], pbData, i); - Transform(m_state, m_buffer); - - for (; (i + 63) < uLen; i += 64) - Transform(m_state, &pbData[i]); - - j = 0; - } else - i = 0; - - if ((uLen - i) != 0) - memcpy(&m_buffer[j], &pbData[i], uLen - i); - } - -#ifdef SHA1_UTILITY_FUNCTIONS - // Hash in file contents - bool HashFile(const TCHAR *tszFileName) { - if (tszFileName == NULL) - return false; - - FILE *fpIn = _tfopen(tszFileName, _T("rb")); - if (fpIn == NULL) - return false; - - UINT_8 *pbData = new UINT_8[SHA1_MAX_FILE_BUFFER]; - if (pbData == NULL) { - fclose(fpIn); - return false; - } - - bool bSuccess = true; - while (true) { - const size_t uRead = fread(pbData, 1, SHA1_MAX_FILE_BUFFER, fpIn); - - if (uRead > 0) - Update(pbData, static_cast(uRead)); - - if (uRead < SHA1_MAX_FILE_BUFFER) { - if (feof(fpIn) == 0) - bSuccess = false; - break; - } - } - - fclose(fpIn); - delete[] pbData; - return bSuccess; - } -#endif - - // Finalize hash; call it before using ReportHash(Stl) - void Final() { - UINT_32 i; - - UINT_8 pbFinalCount[8]; - for (i = 0; i < 8; ++i) - pbFinalCount[i] = static_cast((m_count[((i >= 4) ? 0 : 1)] >> - ((3 - (i & 3)) * 8)) & - 0xFF); // Endian independent - - Update((UINT_8 *)"\200", 1); - - while ((m_count[0] & 504) != 448) - Update((UINT_8 *)"\0", 1); - - Update(pbFinalCount, 8); // Cause a Transform() - - for (i = 0; i < 20; ++i) - m_digest[i] = static_cast((m_state[i >> 2] >> ((3 - - (i & 3)) * - 8)) & - 0xFF); - - // Wipe variables for security reasons -#ifdef SHA1_WIPE_VARIABLES - memset(m_buffer, 0, 64); - memset(m_state, 0, 20); - memset(m_count, 0, 8); - memset(pbFinalCount, 0, 8); - Transform(m_state, m_buffer); -#endif - } - -#ifdef SHA1_UTILITY_FUNCTIONS - bool ReportHash(TCHAR *tszReport, REPORT_TYPE rtReportType = REPORT_HEX) const { - if (tszReport == NULL) - return false; - - TCHAR tszTemp[16]; - - if ((rtReportType == REPORT_HEX) || (rtReportType == REPORT_HEX_SHORT)) { - _sntprintf(tszTemp, 15, _T("%02X"), m_digest[0]); - _tcscpy(tszReport, tszTemp); - - const TCHAR *lpFmt = ((rtReportType == REPORT_HEX) ? _T(" %02X") : _T("%02X")); - for (size_t i = 1; i < 20; ++i) { - _sntprintf(tszTemp, 15, lpFmt, m_digest[i]); - _tcscat(tszReport, tszTemp); - } - } else if (rtReportType == REPORT_DIGIT) { - _sntprintf(tszTemp, 15, _T("%u"), m_digest[0]); - _tcscpy(tszReport, tszTemp); - - for (size_t i = 1; i < 20; ++i) { - _sntprintf(tszTemp, 15, _T(" %u"), m_digest[i]); - _tcscat(tszReport, tszTemp); - } - } else - return false; - - return true; - } -#endif - -#ifdef SHA1_STL_FUNCTIONS - bool ReportHashStl(std::basic_string &strOut, REPORT_TYPE rtReportType = - REPORT_HEX) const { - TCHAR tszOut[84]; - const bool bResult = ReportHash(tszOut, rtReportType); - if (bResult) - strOut = tszOut; - return bResult; - } -#endif - - // Get the raw message digest (20 bytes) - bool GetHash(UINT_8 *pbDest20) const { - if (pbDest20 == NULL) - return false; - memcpy(pbDest20, m_digest, 20); - return true; - } - -private: - // Private SHA-1 transformation - void Transform(UINT_32 *pState, const UINT_8 *pBuffer) { - UINT_32 a = pState[0], b = pState[1], c = pState[2], d = pState[3], e = pState[4]; - - memcpy(m_block, pBuffer, 64); - - // 4 rounds of 20 operations each, loop unrolled - S_R0(a, b, c, d, e, 0); - S_R0(e, a, b, c, d, 1); - S_R0(d, e, a, b, c, 2); - S_R0(c, d, e, a, b, 3); - S_R0(b, c, d, e, a, 4); - S_R0(a, b, c, d, e, 5); - S_R0(e, a, b, c, d, 6); - S_R0(d, e, a, b, c, 7); - S_R0(c, d, e, a, b, 8); - S_R0(b, c, d, e, a, 9); - S_R0(a, b, c, d, e, 10); - S_R0(e, a, b, c, d, 11); - S_R0(d, e, a, b, c, 12); - S_R0(c, d, e, a, b, 13); - S_R0(b, c, d, e, a, 14); - S_R0(a, b, c, d, e, 15); - S_R1(e, a, b, c, d, 16); - S_R1(d, e, a, b, c, 17); - S_R1(c, d, e, a, b, 18); - S_R1(b, c, d, e, a, 19); - S_R2(a, b, c, d, e, 20); - S_R2(e, a, b, c, d, 21); - S_R2(d, e, a, b, c, 22); - S_R2(c, d, e, a, b, 23); - S_R2(b, c, d, e, a, 24); - S_R2(a, b, c, d, e, 25); - S_R2(e, a, b, c, d, 26); - S_R2(d, e, a, b, c, 27); - S_R2(c, d, e, a, b, 28); - S_R2(b, c, d, e, a, 29); - S_R2(a, b, c, d, e, 30); - S_R2(e, a, b, c, d, 31); - S_R2(d, e, a, b, c, 32); - S_R2(c, d, e, a, b, 33); - S_R2(b, c, d, e, a, 34); - S_R2(a, b, c, d, e, 35); - S_R2(e, a, b, c, d, 36); - S_R2(d, e, a, b, c, 37); - S_R2(c, d, e, a, b, 38); - S_R2(b, c, d, e, a, 39); - S_R3(a, b, c, d, e, 40); - S_R3(e, a, b, c, d, 41); - S_R3(d, e, a, b, c, 42); - S_R3(c, d, e, a, b, 43); - S_R3(b, c, d, e, a, 44); - S_R3(a, b, c, d, e, 45); - S_R3(e, a, b, c, d, 46); - S_R3(d, e, a, b, c, 47); - S_R3(c, d, e, a, b, 48); - S_R3(b, c, d, e, a, 49); - S_R3(a, b, c, d, e, 50); - S_R3(e, a, b, c, d, 51); - S_R3(d, e, a, b, c, 52); - S_R3(c, d, e, a, b, 53); - S_R3(b, c, d, e, a, 54); - S_R3(a, b, c, d, e, 55); - S_R3(e, a, b, c, d, 56); - S_R3(d, e, a, b, c, 57); - S_R3(c, d, e, a, b, 58); - S_R3(b, c, d, e, a, 59); - S_R4(a, b, c, d, e, 60); - S_R4(e, a, b, c, d, 61); - S_R4(d, e, a, b, c, 62); - S_R4(c, d, e, a, b, 63); - S_R4(b, c, d, e, a, 64); - S_R4(a, b, c, d, e, 65); - S_R4(e, a, b, c, d, 66); - S_R4(d, e, a, b, c, 67); - S_R4(c, d, e, a, b, 68); - S_R4(b, c, d, e, a, 69); - S_R4(a, b, c, d, e, 70); - S_R4(e, a, b, c, d, 71); - S_R4(d, e, a, b, c, 72); - S_R4(c, d, e, a, b, 73); - S_R4(b, c, d, e, a, 74); - S_R4(a, b, c, d, e, 75); - S_R4(e, a, b, c, d, 76); - S_R4(d, e, a, b, c, 77); - S_R4(c, d, e, a, b, 78); - S_R4(b, c, d, e, a, 79); - - // Add the working vars back into state - pState[0] += a; - pState[1] += b; - pState[2] += c; - pState[3] += d; - pState[4] += e; - - // Wipe variables -#ifdef SHA1_WIPE_VARIABLES - a = b = c = d = e = 0; -#endif - } - - // Member variables - UINT_32 m_state[5]; - UINT_32 m_count[2]; - UINT_32 m_reserved0[1]; // Memory alignment padding - UINT_8 m_buffer[64]; - UINT_8 m_digest[20]; - UINT_32 m_reserved1[3]; // Memory alignment padding - - UINT_8 m_workspace[64]; - SHA1_WORKSPACE_BLOCK *m_block; // SHA1 pointer to the byte array above -}; - -#endif // SHA1_H_A545E61D43E9404E8D736869AB3CBFE7 diff --git a/libs/brynet/base/endian/Endian.hpp b/libs/brynet/base/endian/Endian.hpp deleted file mode 100644 index e49cdd7..0000000 --- a/libs/brynet/base/endian/Endian.hpp +++ /dev/null @@ -1,115 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -#ifdef BRYNET_PLATFORM_LINUX -#include -#elif defined BRYNET_PLATFORM_DARWIN -#include -#endif - - -inline uint64_t hl64ton(uint64_t hostValue) { - uint64_t ret = 0; - uint32_t high, low; - - low = hostValue & 0xFFFFFFFF; - high = (hostValue >> 32) & 0xFFFFFFFF; - low = htonl(low); - high = htonl(high); - ret = low; - ret <<= 32; - ret |= high; - - return ret; -} - -inline uint64_t ntohl64(uint64_t netValue) { - uint64_t ret = 0; - uint32_t high, low; - - low = netValue & 0xFFFFFFFF; - high = (netValue >> 32) & 0xFFFFFFFF; - low = ntohl(low); - high = ntohl(high); - ret = low; - ret <<= 32; - ret |= high; - - return ret; -} - -#ifdef BRYNET_PLATFORM_WINDOWS -inline uint64_t hostToNetwork64(uint64_t host64, bool convert = true) { - return convert ? hl64ton(host64) : host64; -} -inline uint32_t hostToNetwork32(uint32_t host32, bool convert = true) { - return convert ? htonl(host32) : host32; -} - -inline uint16_t hostToNetwork16(uint16_t host16, bool convert = true) { - return convert ? htons(host16) : host16; -} - -inline uint64_t networkToHost64(uint64_t net64, bool convert = true) { - return convert ? ntohl64(net64) : net64; -} - -inline uint32_t networkToHost32(uint32_t net32, bool convert = true) { - return convert ? ntohl(net32) : net32; -} - -inline uint16_t networkToHost16(uint16_t net16, bool convert = true) { - return convert ? ntohs(net16) : net16; -} -#elif defined BRYNET_PLATFORM_LINUX -inline uint64_t hostToNetwork64(uint64_t host64, bool convert = true) { - return convert ? htobe64(host64) : host64; -} -inline uint32_t hostToNetwork32(uint32_t host32, bool convert = true) { - return convert ? htobe32(host32) : host32; -} - -inline uint16_t hostToNetwork16(uint16_t host16, bool convert = true) { - return convert ? htobe16(host16) : host16; -} - -inline uint64_t networkToHost64(uint64_t net64, bool convert = true) { - return convert ? be64toh(net64) : net64; -} - -inline uint32_t networkToHost32(uint32_t net32, bool convert = true) { - return convert ? be32toh(net32) : net32; -} - -inline uint16_t networkToHost16(uint16_t net16, bool convert = true) { - return convert ? be16toh(net16) : net16; -} -#elif defined BRYNET_PLATFORM_DARWIN -inline uint64_t hostToNetwork64(uint64_t host64, bool convert = true) { - return convert ? hl64ton(host64) : host64; -} -inline uint32_t hostToNetwork32(uint32_t host32, bool convert = true) { - return convert ? htonl(host32) : host32; -} - -inline uint16_t hostToNetwork16(uint16_t host16, bool convert = true) { - return convert ? htons(host16) : host16; -} - -inline uint64_t networkToHost64(uint64_t net64, bool convert = true) { - return convert ? ntohl64(net64) : net64; -} - -inline uint32_t networkToHost32(uint32_t net32, bool convert = true) { - return convert ? ntohl(net32) : net32; -} - -inline uint16_t networkToHost16(uint16_t net16, bool convert = true) { - return convert ? ntohs(net16) : net16; -} -#endif diff --git a/libs/brynet/net/AsyncConnector.hpp b/libs/brynet/net/AsyncConnector.hpp deleted file mode 100644 index 7a03a12..0000000 --- a/libs/brynet/net/AsyncConnector.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include - -using ConnectOption = ConnectOption; - -class AsyncConnector : public AsyncConnectorDetail, - public std::enable_shared_from_this { -public: - using Ptr = std::shared_ptr; - - void startWorkerThread() { - AsyncConnectorDetail::startWorkerThread(); - } - - void stopWorkerThread() { - AsyncConnectorDetail::stopWorkerThread(); - } - - void asyncConnect(const ConnectOption &option) { - AsyncConnectorDetail::asyncConnect(option); - } - - static Ptr Create() { - class make_shared_enabler : public AsyncConnector { - }; - return std::make_shared(); - } - -private: - AsyncConnector() = default; -}; diff --git a/libs/brynet/net/Channel.hpp b/libs/brynet/net/Channel.hpp deleted file mode 100644 index b08775d..0000000 --- a/libs/brynet/net/Channel.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -class EventLoop; - -class Channel { -public: - virtual ~Channel() = default; - -private: - virtual void canSend() = 0; - virtual void canRecv(bool willClose) = 0; - virtual void onClose() = 0; - - friend class EventLoop; -}; diff --git a/libs/brynet/net/CurrentThread.hpp b/libs/brynet/net/CurrentThread.hpp deleted file mode 100644 index 0c9c20a..0000000 --- a/libs/brynet/net/CurrentThread.hpp +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once - -#include - -#ifdef BRYNET_PLATFORM_WINDOWS -#define WIN32_LEAN_AND_MEAN -#include -#include -#elif defined BRYNET_PLATFORM_LINUX -#include -#include -#include -#include -#include -#elif defined BRYNET_PLATFORM_DARWIN -#include -#include -#include -#endif - -#ifdef BRYNET_PLATFORM_WINDOWS -using THREAD_ID_TYPE = DWORD; -#elif defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN -using THREAD_ID_TYPE = int; -#endif - -static THREAD_ID_TYPE &tid() { -#ifdef BRYNET_PLATFORM_WINDOWS - static __declspec(thread) THREAD_ID_TYPE cachedTid = 0; -#elif defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN - static __thread THREAD_ID_TYPE cachedTid = 0; -#endif - - if (cachedTid == 0) { -#ifdef BRYNET_PLATFORM_WINDOWS - cachedTid = GetCurrentThreadId(); -#elif defined BRYNET_PLATFORM_LINUX - cachedTid = static_cast(::syscall(SYS_gettid)); -#elif defined BRYNET_PLATFORM_DARWIN - // warning: 'syscall' is deprecated: - // first deprecated in macOS 10.12 - syscall(2) is unsupported; - // please switch to a supported interface. - uint64_t tid64; - pthread_threadid_np(NULL, &tid64); - cachedTid = (pid_t)tid64; -#endif - } - - return cachedTid; -} diff --git a/libs/brynet/net/EventLoop.hpp b/libs/brynet/net/EventLoop.hpp deleted file mode 100644 index 39a36a2..0000000 --- a/libs/brynet/net/EventLoop.hpp +++ /dev/null @@ -1,382 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class Channel; -class TcpConnection; -using TcpConnectionPtr = std::shared_ptr; - -class EventLoop : public NonCopyable { -public: - using Ptr = std::shared_ptr; - using UserFunctor = std::function; - -public: - EventLoop() - BRYNET_NOEXCEPT - : -#ifdef BRYNET_PLATFORM_WINDOWS - mIOCP(CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 1)), - mWakeupChannel(std::make_unique(mIOCP)) -#elif defined BRYNET_PLATFORM_LINUX - mEpollFd(epoll_create(1)) -#elif defined BRYNET_PLATFORM_DARWIN - mKqueueFd(kqueue()) -#endif - { -#ifdef BRYNET_PLATFORM_WINDOWS - mPGetQueuedCompletionStatusEx = NULL; - auto kernel32_module = GetModuleHandleA("kernel32.dll"); - if (kernel32_module != NULL) { - mPGetQueuedCompletionStatusEx = reinterpret_cast(GetProcAddress( - kernel32_module, - "GetQueuedCompletionStatusEx")); - FreeLibrary(kernel32_module); - } -#elif defined BRYNET_PLATFORM_LINUX - auto eventfd = ::eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); - mWakeupChannel.reset(new WakeupChannel(eventfd)); - linkChannel(eventfd, mWakeupChannel.get()); -#elif defined BRYNET_PLATFORM_DARWIN - const int NOTIFY_IDENT = 42; // Magic number we use for our filter ID. - mWakeupChannel.reset(new WakeupChannel(mKqueueFd, NOTIFY_IDENT)); - //Add user event - struct kevent ev; - EV_SET(&ev, NOTIFY_IDENT, EVFILT_USER, EV_ADD | EV_CLEAR, 0, 0, NULL); - - struct timespec timeout = { 0, 0 }; - kevent(mKqueueFd, &ev, 1, NULL, 0, &timeout); -#endif - - mIsAlreadyPostWakeup = false; - mIsInBlock = true; - - reAllocEventSize(1024); - mSelfThreadID = -1; - mTimer = std::make_shared(); - } - - virtual ~EventLoop() BRYNET_NOEXCEPT { -#ifdef BRYNET_PLATFORM_WINDOWS - CloseHandle(mIOCP); - mIOCP = INVALID_HANDLE_VALUE; -#elif defined BRYNET_PLATFORM_LINUX - close(mEpollFd); - mEpollFd = -1; -#elif defined BRYNET_PLATFORM_DARWIN - close(mKqueueFd); - mKqueueFd = -1; -#endif - } - - void loop(int64_t milliseconds) { - tryInitThreadID(); - -#ifndef NDEBUG - assert(isInLoopThread()); -#endif - if (!isInLoopThread()) { - throw BrynetCommonException("only loop in io thread"); - } - - if (!mAfterLoopFunctors.empty()) { - milliseconds = 0; - } - -#ifdef BRYNET_PLATFORM_WINDOWS - ULONG numComplete = 0; - if (mPGetQueuedCompletionStatusEx != nullptr) { - if (!mPGetQueuedCompletionStatusEx(mIOCP, - mEventEntries.data(), - static_cast(mEventEntries.size()), - &numComplete, - static_cast(milliseconds), - false)) { - numComplete = 0; - } - } else { - for (auto &e : mEventEntries) { - const auto timeout = (numComplete == 0) ? static_cast(milliseconds) : 0; - /* don't check the return value of GQCS */ - GetQueuedCompletionStatus(mIOCP, - &e.dwNumberOfBytesTransferred, - &e.lpCompletionKey, - &e.lpOverlapped, - timeout); - if (e.lpOverlapped == nullptr) { - break; - } - ++numComplete; - } - } - - mIsInBlock = false; - - for (ULONG i = 0; i < numComplete; ++i) { - auto channel = (Channel *)mEventEntries[i].lpCompletionKey; - assert(channel != nullptr); - const auto ovl = reinterpret_cast(mEventEntries[i].lpOverlapped); - if (ovl->OP == port::Win::OverlappedType::OverlappedRecv) { - channel->canRecv(false); - } else if (ovl->OP == port::Win::OverlappedType::OverlappedSend) { - channel->canSend(); - } else { - assert(false); - } - } -#elif defined BRYNET_PLATFORM_LINUX - int numComplete = epoll_wait(mEpollFd, mEventEntries.data(), mEventEntries.size(), milliseconds); - - mIsInBlock = false; - - for (int i = 0; i < numComplete; ++i) { - auto channel = (Channel *)(mEventEntries[i].data.ptr); - auto event_data = mEventEntries[i].events; - - if (event_data & EPOLLRDHUP) { - channel->canRecv(true); - channel->onClose(); - continue; - } - - if (event_data & EPOLLIN) { - channel->canRecv(false); - } - - if (event_data & EPOLLOUT) { - channel->canSend(); - } - } -#elif defined BRYNET_PLATFORM_DARWIN - struct timespec timeout = { milliseconds / 1000, (milliseconds % 1000) * 1000 * 1000 }; - int numComplete = kevent(mKqueueFd, NULL, 0, mEventEntries.data(), mEventEntries.size(), &timeout); - - mIsInBlock = false; - - for (int i = 0; i < numComplete; ++i) { - auto channel = (Channel *)(mEventEntries[i].udata); - const struct kevent &event = mEventEntries[i]; - - if (event.filter == EVFILT_USER) { - continue; - } - - if (event.filter == EVFILT_READ) { - channel->canRecv(false); - } - - if (event.filter == EVFILT_WRITE) { - channel->canSend(); - } - } -#endif - - mIsAlreadyPostWakeup = false; - mIsInBlock = true; - - processAsyncFunctors(); - processAfterLoopFunctors(); - - if (static_cast(numComplete) == mEventEntries.size()) { - reAllocEventSize(mEventEntries.size() + 128); - } - - mTimer->schedule(); - } - - // loop指定毫秒数,但如果定时器不为空,则loop时间为当前最近定时器的剩余时间和milliseconds的较小值 - void loopCompareNearTimer(int64_t milliseconds) { - tryInitThreadID(); - -#ifndef NDEBUG - assert(isInLoopThread()); -#endif - if (!isInLoopThread()) { - throw BrynetCommonException("only loop in IO thread"); - } - - if (!mTimer->isEmpty()) { - auto nearTimeout = std::chrono::duration_cast(mTimer->nearLeftTime()); - milliseconds = std::min(milliseconds, nearTimeout.count()); - } - - loop(milliseconds); - } - - // 返回true表示实际发生了wakeup所需的操作(此返回值不代表接口本身操作成功与否,因为此函数永远成功) - bool wakeup() { - if (!isInLoopThread() && mIsInBlock && !mIsAlreadyPostWakeup.exchange(true)) { - return mWakeupChannel->wakeup(); - } - - return false; - } - - void runAsyncFunctor(UserFunctor &&f) { - if (isInLoopThread()) { - f(); - } else { - pushAsyncFunctor(std::move(f)); - wakeup(); - } - } - void runFunctorAfterLoop(UserFunctor &&f) { - assert(isInLoopThread()); - if (!isInLoopThread()) { - throw BrynetCommonException("only push after functor in io thread"); - } - - mAfterLoopFunctors.emplace_back(std::move(f)); - } - Timer::WeakPtr runAfter(std::chrono::nanoseconds timeout, UserFunctor &&callback) { - auto timer = std::make_shared( - std::chrono::steady_clock::now(), - std::chrono::nanoseconds(timeout), - std::move(callback)); - - if (isInLoopThread()) { - mTimer->addTimer(timer); - } else { - auto timerMgr = mTimer; - runAsyncFunctor([timerMgr, timer]() { - timerMgr->addTimer(timer); - }); - } - - return timer; - } - - inline bool isInLoopThread() const { - return mSelfThreadID == tid(); - } - -private: - void reAllocEventSize(size_t size) { - mEventEntries.resize(size); - } - - void processAfterLoopFunctors() { - mCopyAfterLoopFunctors.swap(mAfterLoopFunctors); - for (const auto &x : mCopyAfterLoopFunctors) { - x(); - } - mCopyAfterLoopFunctors.clear(); - } - void processAsyncFunctors() { - swapAsyncFunctors(); - - for (const auto &x : mCopyAsyncFunctors) { - x(); - } - mCopyAsyncFunctors.clear(); - } - void swapAsyncFunctors() { - std::lock_guard lck(mAsyncFunctorsMutex); - assert(mCopyAsyncFunctors.empty()); - mCopyAsyncFunctors.swap(mAsyncFunctors); - } - void pushAsyncFunctor(UserFunctor &&f) { - std::lock_guard lck(mAsyncFunctorsMutex); - mAsyncFunctors.emplace_back(std::move(f)); - } - -#ifdef BRYNET_PLATFORM_LINUX - int getEpollHandle() const { - return mEpollFd; - } -#elif defined BRYNET_PLATFORM_DARWIN - int getKqueueHandle() const { - return mKqueueFd; - } -#endif - bool linkChannel(BrynetSocketFD fd, const Channel *ptr) BRYNET_NOEXCEPT { -#ifdef BRYNET_PLATFORM_WINDOWS - return CreateIoCompletionPort((HANDLE)fd, mIOCP, (ULONG_PTR)ptr, 0) != nullptr; -#elif defined BRYNET_PLATFORM_LINUX - struct epoll_event ev = { 0, - { - nullptr - } }; - ev.events = EPOLLET | EPOLLIN | EPOLLOUT | EPOLLRDHUP; - ev.data.ptr = (void *)ptr; - return epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &ev) == 0; -#elif defined BRYNET_PLATFORM_DARWIN - struct kevent ev[2]; - memset(&ev, 0, sizeof(ev)); - int n = 0; - EV_SET(&ev[n++], fd, EVFILT_READ, EV_ADD | EV_CLEAR, NOTE_TRIGGER, 0, (void *)ptr); - EV_SET(&ev[n++], fd, EVFILT_WRITE, EV_ADD | EV_CLEAR, NOTE_TRIGGER, 0, (void *)ptr); - - struct timespec now = { 0, 0 }; - return kevent(mKqueueFd, ev, n, NULL, 0, &now) == 0; -#endif - } - TcpConnectionPtr getTcpConnection(BrynetSocketFD fd) { - auto it = mTcpConnections.find(fd); - if (it != mTcpConnections.end()) { - return (*it).second; - } - return nullptr; - } - void addTcpConnection(BrynetSocketFD fd, TcpConnectionPtr tcpConnection) { - mTcpConnections[fd] = std::move(tcpConnection); - } - void removeTcpConnection(BrynetSocketFD fd) { - mTcpConnections.erase(fd); - } - void tryInitThreadID() { - std::call_once(mOnceInitThreadID, [this]() { - mSelfThreadID = tid(); - }); - } - -private: -#ifdef BRYNET_PLATFORM_WINDOWS - std::vector mEventEntries; - - typedef BOOL(WINAPI *sGetQueuedCompletionStatusEx)(HANDLE, LPOVERLAPPED_ENTRY, ULONG, PULONG, DWORD, BOOL); - sGetQueuedCompletionStatusEx mPGetQueuedCompletionStatusEx; - HANDLE mIOCP; -#elif defined BRYNET_PLATFORM_LINUX - std::vector mEventEntries; - int mEpollFd; -#elif defined BRYNET_PLATFORM_DARWIN - std::vector mEventEntries; - int mKqueueFd; -#endif - std::unique_ptr mWakeupChannel; - - std::atomic_bool mIsInBlock; - std::atomic_bool mIsAlreadyPostWakeup; - - std::mutex mAsyncFunctorsMutex; - std::vector mAsyncFunctors; - std::vector mCopyAsyncFunctors; - - std::vector mAfterLoopFunctors; - std::vector mCopyAfterLoopFunctors; - - std::once_flag mOnceInitThreadID; - THREAD_ID_TYPE mSelfThreadID; - - TimerMgr::Ptr mTimer; - std::unordered_map mTcpConnections; - - friend class TcpConnection; -}; diff --git a/libs/brynet/net/Exception.hpp b/libs/brynet/net/Exception.hpp deleted file mode 100644 index 2ba0d50..0000000 --- a/libs/brynet/net/Exception.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include -#include - -class ConnectException : public std::runtime_error { -public: - explicit ConnectException(const std::string &message) : - std::runtime_error(message) { - } - - explicit ConnectException(const char *message) : - std::runtime_error(message) { - } -}; - -class BrynetCommonException : public std::runtime_error { -public: - explicit BrynetCommonException(const std::string &message) : - std::runtime_error(message) { - } - - explicit BrynetCommonException(const char *message) : - std::runtime_error(message) { - } -}; diff --git a/libs/brynet/net/ListenThread.hpp b/libs/brynet/net/ListenThread.hpp deleted file mode 100644 index 5cbbace..0000000 --- a/libs/brynet/net/ListenThread.hpp +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once - -#include - -class ListenThread : public ListenThreadDetail, - public std::enable_shared_from_this { -public: - using Ptr = std::shared_ptr; - using AccepCallback = std::function; - using TcpSocketProcessCallback = std::function; - - void startListen() { - ListenThreadDetail::startListen(); - } - - void stopListen() { - ListenThreadDetail::stopListen(); - } - -public: - static Ptr Create(bool isIPV6, - const std::string &ip, - int port, - const AccepCallback &callback, - const std::vector &processCallbacks = {}, - bool enabledReusePort = false) { - class make_shared_enabler : public ListenThread { - public: - make_shared_enabler(bool isIPV6, - const std::string &ip, - int port, - const AccepCallback &callback, - const std::vector &processCallbacks, - bool enabledReusePort) : - ListenThread(isIPV6, ip, port, callback, processCallbacks, enabledReusePort) {} - }; - return std::make_shared(isIPV6, ip, port, callback, processCallbacks, enabledReusePort); - } - -protected: - ListenThread(bool isIPV6, - const std::string &ip, - int port, - const AccepCallback &callback, - const std::vector &processCallbacks, - bool enabledReusePort) : - ListenThreadDetail(isIPV6, ip, port, callback, processCallbacks, enabledReusePort) {} -}; diff --git a/libs/brynet/net/Poller.hpp b/libs/brynet/net/Poller.hpp deleted file mode 100644 index 1828b64..0000000 --- a/libs/brynet/net/Poller.hpp +++ /dev/null @@ -1,212 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -#if defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN -#include -#endif - -#ifdef BRYNET_PLATFORM_WINDOWS -const static int CHECK_READ_FLAG = (POLLIN | POLLRDNORM | POLLRDBAND); -const static int CHECK_WRITE_FLAG = (POLLOUT | POLLWRNORM); -const static int CHECK_ERROR_FLAG = (POLLERR | POLLHUP); -#elif defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN -const static int CHECK_READ_FLAG = (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI); -const static int CHECK_WRITE_FLAG = (POLLOUT | POLLWRNORM | POLLWRBAND); -const static int CHECK_ERROR_FLAG = (POLLERR | POLLHUP); -#endif - -enum CheckType { - ReadCheck = 0x1, - WriteCheck = 0x2, - ErrorCheck = 0x4, -}; - -struct poller_s { - struct pollfd *pollFds; - int nfds; - int limitSize; -}; - -static void upstep_pollfd(struct poller_s *self, int upSize) { - if (upSize <= 0) { - return; - } - - struct pollfd *newPollfds = (struct pollfd *)malloc( - sizeof(struct pollfd) * (self->limitSize + upSize)); - if (newPollfds == nullptr) { - return; - } - - if (self->pollFds != nullptr) { - memcpy(newPollfds, self->pollFds, sizeof(struct pollfd) * self->nfds); - free(self->pollFds); - self->pollFds = nullptr; - } - self->pollFds = newPollfds; - self->limitSize += upSize; -} - -static struct pollfd *find_pollfd(struct poller_s *self, BrynetSocketFD fd) { - for (int i = 0; i < self->nfds; i++) { - if (self->pollFds[i].fd == fd) { - return self->pollFds + i; - } - } - - return nullptr; -} - -static void try_remove_pollfd(struct poller_s *self, BrynetSocketFD fd) { - int pos = -1; - for (int i = 0; i < self->nfds; i++) { - if (self->pollFds[i].fd == fd) { - pos = i; - break; - } - } - - if (pos != -1) { - memmove(self->pollFds + pos, - self->pollFds + pos + 1, - sizeof(struct pollfd) * (self->nfds - pos - 1)); - self->nfds--; - assert(self->nfds >= 0); - } -} - -static struct poller_s *poller_new(void) { - struct poller_s *ret = (struct poller_s *)malloc(sizeof(struct poller_s)); - if (ret != nullptr) { - ret->pollFds = NULL; - ret->limitSize = 0; - ret->nfds = 0; - upstep_pollfd(ret, 1024); - } - - return ret; -} - -static void poller_delete(struct poller_s *self) { - free(self->pollFds); - self->pollFds = nullptr; - self->nfds = 0; - self->limitSize = 0; - - free(self); - self = nullptr; -} - -static void poller_add(struct poller_s *self, BrynetSocketFD fd, int type) { - if (self->limitSize == self->nfds) { - upstep_pollfd(self, 128); - } - - if (self->limitSize <= self->nfds) { - return; - } - - struct pollfd *pf = find_pollfd(self, fd); - if (pf == nullptr) { - /*real add*/ - pf = self->pollFds + self->nfds; - pf->events = 0; - pf->fd = fd; - - self->nfds++; - } - - if (type & ReadCheck) { - pf->events |= CHECK_READ_FLAG; - } - - if (type & WriteCheck) { - pf->events |= CHECK_WRITE_FLAG; - } - - if (type & ErrorCheck) { - //pf->events |= CHECK_ERROR_FLAG; TODO::on windows, not supports - } -} - -static void poller_del(struct poller_s *self, BrynetSocketFD fd, int type) { - struct pollfd *pf = find_pollfd(self, fd); - if (pf == nullptr) { - return; - } - - if (type & ReadCheck) { - pf->events &= ~CHECK_READ_FLAG; - } - - if (type & WriteCheck) { - pf->events &= ~CHECK_WRITE_FLAG; - } - - if (type & ErrorCheck) { - pf->events &= ~CHECK_ERROR_FLAG; - } - - if (pf->events == 0) { - try_remove_pollfd(self, fd); - } -} - -static void poller_remove(struct poller_s *self, BrynetSocketFD fd) { - try_remove_pollfd(self, fd); -} - -static bool check_event(const struct pollfd *pf, enum CheckType type) { - if (pf == nullptr) { - return false; - } - - if ((type & ReadCheck) && - (pf->revents & CHECK_READ_FLAG)) { - return true; - } else if ((type & WriteCheck) && - (pf->revents & CHECK_WRITE_FLAG)) { - return true; - } else if ((type & ErrorCheck) && - (pf->revents & CHECK_ERROR_FLAG)) { - return true; - } else { - return false; - } -} - -static void poller_visitor(struct poller_s *self, - enum CheckType type, - struct stack_s *result) { - for (int i = 0; i < self->nfds; i++) { - if (check_event(self->pollFds + i, type)) { - stack_push(result, &self->pollFds[i].fd); - } - } -} - -static int poller_poll(struct poller_s *self, long overtime) { -#ifdef BRYNET_PLATFORM_WINDOWS - int ret = WSAPoll(&self->pollFds[0], self->nfds, overtime); -#elif defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN - int ret = poll(self->pollFds, self->nfds, overtime); -#endif - - if (ret == BRYNET_SOCKET_ERROR) { - ret = (BRYNET_ERRNO != BRYNET_EINTR) ? -1 : 0; - } - - return ret; -} - -static bool poller_check(struct poller_s *self, BrynetSocketFD fd, enum CheckType type) { - const struct pollfd *pf = find_pollfd(self, fd); - if (pf == NULL) { - return false; - } - return check_event(pf, type); -} diff --git a/libs/brynet/net/PromiseReceive.hpp b/libs/brynet/net/PromiseReceive.hpp deleted file mode 100644 index 5d83512..0000000 --- a/libs/brynet/net/PromiseReceive.hpp +++ /dev/null @@ -1,128 +0,0 @@ -#pragma once - -#include - -/* binary search in memory */ -void memsearch(const char *hay, size_t haysize, const char *needle, size_t needlesize, size_t &result, bool &isOK) { - size_t haypos, needlepos; - haysize -= needlesize; - - for (haypos = 0; haypos <= haysize; haypos++) { - for (needlepos = 0; needlepos < needlesize; needlepos++) { - if (hay[haypos + needlepos] != needle[needlepos]) { - // Next character in haystack. - break; - } - } - if (needlepos == needlesize) { - result = haypos; - isOK = true; - return; - } - } - - isOK = false; -} - -class PromiseReceive; - -std::shared_ptr setupPromiseReceive(const TcpConnection::Ptr &session); - -class PromiseReceive : public std::enable_shared_from_this { -public: - using Ptr = std::shared_ptr; - using Handle = std::function; - - PromiseReceive::Ptr receive(size_t len, Handle handle) { - return receive(std::make_shared(len), std::move(handle)); - } - - PromiseReceive::Ptr receive(std::shared_ptr len, Handle handle) { - return helpReceive(std::move(len), "", std::move(handle)); - } - - PromiseReceive::Ptr receiveUntil(std::string str, Handle handle) { - if (str.empty()) { - throw std::runtime_error("str is empty"); - } - - return helpReceive(nullptr, std::move(str), std::move(handle)); - } - -private: - PromiseReceive::Ptr helpReceive(std::shared_ptr len, std::string str, Handle handle) { - auto pr = std::make_shared(); - pr->len = std::move(len); - pr->str = std::move(str); - pr->handle = std::move(handle); - mPendingReceives.push_back(std::move(pr)); - - return shared_from_this(); - } - - size_t process(const char *buffer, const size_t len) { - size_t procLen = 0; - - while (!mPendingReceives.empty() && len >= procLen) { - auto pendingReceive = mPendingReceives.front(); - if (pendingReceive->len != nullptr) { - const auto tryReceiveLen = *pendingReceive->len; - if ((len - procLen) < tryReceiveLen) { - break; - } - - mPendingReceives.pop_front(); - procLen += tryReceiveLen; - if (pendingReceive->handle(buffer + procLen - tryReceiveLen, tryReceiveLen) && tryReceiveLen > 0) { - mPendingReceives.push_front(pendingReceive); - } - } else if (!pendingReceive->str.empty()) { - size_t pos = 0; - bool isOK = false; - auto data = buffer + procLen; - memsearch(buffer + procLen, - len - procLen, - pendingReceive->str.c_str(), - pendingReceive->str.size(), - pos, - isOK); - - if (!isOK) { - break; - } - - mPendingReceives.pop_front(); - procLen += (pos + pendingReceive->str.size()); - if (pendingReceive->handle(data, pos)) { - mPendingReceives.push_front(pendingReceive); - } - } else { - break; - } - } - - return procLen; - } - -private: - struct PendingReceive { - std::shared_ptr len; - std::string str; - Handle handle; - }; - - std::deque > mPendingReceives; - - friend std::shared_ptr setupPromiseReceive(const TcpConnection::Ptr &session); -}; - -std::shared_ptr setupPromiseReceive(const TcpConnection::Ptr &session) { - auto promiseReceive = std::make_shared(); - session->setDataCallback([promiseReceive](BasePacketReader &reader) { - auto procLen = promiseReceive->process(reader.begin(), reader.size()); - reader.addPos(procLen); - reader.savePos(); - }); - - return promiseReceive; -} diff --git a/libs/brynet/net/SSLHelper.hpp b/libs/brynet/net/SSLHelper.hpp deleted file mode 100644 index 450bab8..0000000 --- a/libs/brynet/net/SSLHelper.hpp +++ /dev/null @@ -1,151 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef BRYNET_USE_OPENSSL - -#ifdef __cplusplus -extern "C" { -#endif -#include -#include -#ifdef __cplusplus -} -#endif - -#endif - -#ifdef BRYNET_USE_OPENSSL - -#ifndef CRYPTO_THREADID_set_callback -static void cryptoSetThreadIDCallback(CRYPTO_THREADID *id) { -#ifdef BRYNET_PLATFORM_WINDOWS - CRYPTO_THREADID_set_numeric(id, - static_cast(GetCurrentThreadId())); -#elif defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN - CRYPTO_THREADID_set_numeric(id, - static_cast(pthread_self())); -#endif -} -#endif - -#ifndef CRYPTO_set_locking_callback -static std::unordered_map > cryptoLocks; -static void cryptoLockingCallback(int mode, - int type, - const char *file, int line) { - (void)file; - (void)line; - if (mode & CRYPTO_LOCK) { - cryptoLocks[type]->lock(); - } else if (mode & CRYPTO_UNLOCK) { - cryptoLocks[type]->unlock(); - } -} -#endif - -static std::once_flag initCryptoThreadSafeSupportOnceFlag; -static void InitCryptoThreadSafeSupport() { -#ifndef CRYPTO_THREADID_set_callback - CRYPTO_THREADID_set_callback(cryptoSetThreadIDCallback); -#endif - -#ifndef CRYPTO_set_locking_callback - for (int i = 0; i < CRYPTO_num_locks(); i++) { - cryptoLocks[i] = std::make_shared(); - } - CRYPTO_set_locking_callback(cryptoLockingCallback); -#endif -} -#endif - -class SSLHelper : public NonCopyable, - public std::enable_shared_from_this { -public: - using Ptr = std::shared_ptr; - -#ifdef BRYNET_USE_OPENSSL - bool initSSL(const std::string &certificate, - const std::string &privatekey) { - std::call_once(initCryptoThreadSafeSupportOnceFlag, - InitCryptoThreadSafeSupport); - - if (mOpenSSLCTX != nullptr) { - return false; - } - if (certificate.empty() || privatekey.empty()) { - return false; - } - - mOpenSSLCTX = SSL_CTX_new(SSLv23_method()); - SSL_CTX_set_client_CA_list(mOpenSSLCTX, - SSL_load_client_CA_file(certificate.c_str())); - SSL_CTX_set_verify_depth(mOpenSSLCTX, 10); - - if (SSL_CTX_use_certificate_chain_file(mOpenSSLCTX, - certificate.c_str()) <= 0) { - SSL_CTX_free(mOpenSSLCTX); - mOpenSSLCTX = nullptr; - return false; - } - - if (SSL_CTX_use_PrivateKey_file(mOpenSSLCTX, - privatekey.c_str(), - SSL_FILETYPE_PEM) <= 0) { - SSL_CTX_free(mOpenSSLCTX); - mOpenSSLCTX = nullptr; - return false; - } - - if (!SSL_CTX_check_private_key(mOpenSSLCTX)) { - SSL_CTX_free(mOpenSSLCTX); - mOpenSSLCTX = nullptr; - return false; - } - - return true; - } - - void destroySSL() { - if (mOpenSSLCTX != nullptr) { - SSL_CTX_free(mOpenSSLCTX); - mOpenSSLCTX = nullptr; - } - } - - SSL_CTX *getOpenSSLCTX() { - return mOpenSSLCTX; - } -#endif - static Ptr Create() { - class make_shared_enabler : public SSLHelper { - }; - return std::make_shared(); - } - -protected: - SSLHelper() BRYNET_NOEXCEPT { -#ifdef BRYNET_USE_OPENSSL - mOpenSSLCTX = nullptr; -#endif - } - - virtual ~SSLHelper() BRYNET_NOEXCEPT { -#ifdef BRYNET_USE_OPENSSL - destroySSL(); -#endif - } - -private: -#ifdef BRYNET_USE_OPENSSL - SSL_CTX *mOpenSSLCTX; -#endif -}; - diff --git a/libs/brynet/net/SendableMsg.hpp b/libs/brynet/net/SendableMsg.hpp deleted file mode 100644 index b0fa390..0000000 --- a/libs/brynet/net/SendableMsg.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#include -#include - -class SendableMsg { -public: - using Ptr = std::shared_ptr; - - virtual ~SendableMsg() = default; - - virtual const void *data() = 0; - virtual size_t size() = 0; -}; - -class StringSendMsg : public SendableMsg { -public: - explicit StringSendMsg(const char *buffer, size_t len) : - mMsg(buffer, len) {} - - explicit StringSendMsg(const std::string &buffer) : - mMsg(buffer) {} - - explicit StringSendMsg(std::string &&buffer) : - mMsg(std::move(buffer)) {} - - const void *data() override { - return static_cast(mMsg.data()); - } - size_t size() override { - return mMsg.size(); - } - -private: - std::string mMsg; -}; - -static SendableMsg::Ptr MakeStringMsg(const char *buffer, size_t len) { - return std::make_shared(buffer, len); -} - -static SendableMsg::Ptr MakeStringMsg(const std::string &buffer) { - return std::make_shared(buffer); -} - -static SendableMsg::Ptr MakeStringMsg(std::string &&buffer) { - return std::make_shared(std::move(buffer)); -} - diff --git a/libs/brynet/net/Socket.hpp b/libs/brynet/net/Socket.hpp deleted file mode 100644 index 53ad5a9..0000000 --- a/libs/brynet/net/Socket.hpp +++ /dev/null @@ -1,186 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -class TcpConnection; - -class UniqueFd final : public NonCopyable { -public: - explicit UniqueFd(BrynetSocketFD fd) : - mFD(fd) {} - - ~UniqueFd() { - SocketClose(mFD); - } - - UniqueFd(const UniqueFd &other) = delete; - UniqueFd &operator=(const UniqueFd &other) = delete; - - BrynetSocketFD getFD() const { - return mFD; - } - -private: - BrynetSocketFD mFD; -}; - -class TcpSocket : public NonCopyable { -private: - class TcpSocketDeleter { - public: - void operator()(TcpSocket *ptr) const { - delete ptr; - } - }; - -public: - using Ptr = std::unique_ptr; - -public: - static Ptr Create(BrynetSocketFD fd, bool serverSide) { - class make_unique_enabler : public TcpSocket { - public: - make_unique_enabler(BrynetSocketFD fd, bool serverSide) : - TcpSocket(fd, serverSide) {} - }; - - return Ptr(new make_unique_enabler(fd, serverSide)); - } - -public: - void setNodelay() const { - SocketNodelay(mFD); - } - - bool setNonblock() const { - return SocketNonblock(mFD); - } - - void setSendSize(int sdSize) const { - SocketSetSendSize(mFD, sdSize); - } - - void setRecvSize(int rdSize) const { - SocketSetRecvSize(mFD, rdSize); - } - - std::string getRemoteIP() const { - return GetIPOfSocket(mFD); - } - - bool isServerSide() const { - return mServerSide; - } - -protected: - TcpSocket(BrynetSocketFD fd, bool serverSide) : - mFD(fd), - mServerSide(serverSide) { - } - - virtual ~TcpSocket() { - SocketClose(mFD); - } - - BrynetSocketFD getFD() const { - return mFD; - } - -private: - const BrynetSocketFD mFD; - const bool mServerSide; - - friend class TcpConnection; -}; - -class EintrError : public std::exception { -}; - -class AcceptError : public std::runtime_error { -public: - explicit AcceptError(int errorCode) : - std::runtime_error(std::to_string(errorCode)), - mErrorCode(errorCode) {} - - int getErrorCode() const { - return mErrorCode; - } - -private: - int mErrorCode; -}; - -class ListenSocket : public NonCopyable { -private: - class ListenSocketDeleter { - public: - void operator()(ListenSocket *ptr) const { - delete ptr; - } - }; - -public: - using Ptr = std::unique_ptr; - -public: - TcpSocket::Ptr accept() { - const auto clientFD = Accept(mFD, nullptr, nullptr); - if (clientFD == BRYNET_INVALID_SOCKET) { -#if defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN - if (BRYNET_ERRNO == EMFILE) { - // Thanks libev and muduo. - // Read the section named "The special problem of - // accept()ing when you can't" in libev's doc. - // By Marc Lehmann, author of libev. - mIdle.reset(); - TcpSocket::Create(Accept(mFD, nullptr, nullptr), true); - mIdle = TcpSocket::Create(::open("/dev/null", O_RDONLY | O_CLOEXEC), true); - } -#endif - if (BRYNET_ERRNO == EINTR) { - throw EintrError(); - } else { - throw AcceptError(BRYNET_ERRNO); - } - } - - return TcpSocket::Create(clientFD, true); - } - -public: - static Ptr Create(BrynetSocketFD fd) { - class make_unique_enabler : public ListenSocket { - public: - explicit make_unique_enabler(BrynetSocketFD fd) : - ListenSocket(fd) {} - }; - - return Ptr(new make_unique_enabler(fd)); - } - -protected: - explicit ListenSocket(BrynetSocketFD fd) : - mFD(fd) { -#if defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN - mIdle = TcpSocket::Create(::open("/dev/null", O_RDONLY | O_CLOEXEC), true); -#endif - } - - virtual ~ListenSocket() { - SocketClose(mFD); - } - -private: - const BrynetSocketFD mFD; -#if defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN - TcpSocket::Ptr mIdle; -#endif - - friend class TcpConnection; -}; - diff --git a/libs/brynet/net/SocketLibFunction.hpp b/libs/brynet/net/SocketLibFunction.hpp deleted file mode 100644 index d036d8d..0000000 --- a/libs/brynet/net/SocketLibFunction.hpp +++ /dev/null @@ -1,287 +0,0 @@ -#pragma once - -#include - -#include -#include - -static bool InitSocket() { - bool ret = true; -#ifdef BRYNET_PLATFORM_WINDOWS - static WSADATA g_WSAData; - static bool WinSockIsInit = false; - if (WinSockIsInit) { - return true; - } - if (WSAStartup(MAKEWORD(2, 2), &g_WSAData) == 0) { - WinSockIsInit = true; - } else { - ret = false; - } -#elif defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN - signal(SIGPIPE, SIG_IGN); -#endif - - return ret; -} - -static void DestroySocket() { -#ifdef BRYNET_PLATFORM_WINDOWS - WSACleanup(); -#endif -} - -static int SocketNodelay(BrynetSocketFD fd) { - const int flag = 1; - return ::setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const char *)&flag, sizeof(flag)); -} - -static bool SocketBlock(BrynetSocketFD fd) { - int err; - unsigned long ul = false; -#ifdef BRYNET_PLATFORM_WINDOWS - err = ioctlsocket(fd, FIONBIO, &ul); -#elif defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN - err = ioctl(fd, FIONBIO, &ul); -#endif - - return err != BRYNET_SOCKET_ERROR; -} - -static bool SocketNonblock(BrynetSocketFD fd) { - int err; - unsigned long ul = true; -#ifdef BRYNET_PLATFORM_WINDOWS - err = ioctlsocket(fd, FIONBIO, &ul); -#elif defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN - err = ioctl(fd, FIONBIO, &ul); -#endif - - return err != BRYNET_SOCKET_ERROR; -} - -static int SocketSetSendSize(BrynetSocketFD fd, int sd_size) { - return ::setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const char *)&sd_size, sizeof(sd_size)); -} - -static int SocketSetRecvSize(BrynetSocketFD fd, int rd_size) { - return ::setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (const char *)&rd_size, sizeof(rd_size)); -} - -static int SocketSetReusePort(BrynetSocketFD fd) { -#ifdef BRYNET_PLATFORM_WINDOWS - return 0; -#else - int enable = 1; - return ::setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(enable)); -#endif -} - -static BrynetSocketFD SocketCreate(int af, int type, int protocol) { - return ::socket(af, type, protocol); -} - -static void SocketClose(BrynetSocketFD fd) { -#ifdef BRYNET_PLATFORM_WINDOWS - ::closesocket(fd); -#elif defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN - ::close(fd); -#endif -} - -static BrynetSocketFD Connect(bool isIPV6, const std::string &server_ip, int port) { - InitSocket(); - - struct sockaddr_in ip4Addr = sockaddr_in(); - struct sockaddr_in6 ip6Addr = sockaddr_in6(); - struct sockaddr_in *paddr = &ip4Addr; - int addrLen = sizeof(ip4Addr); - - BrynetSocketFD clientfd = isIPV6 ? SocketCreate(AF_INET6, SOCK_STREAM, 0) : SocketCreate(AF_INET, SOCK_STREAM, 0); - - if (clientfd == BRYNET_INVALID_SOCKET) { - return clientfd; - } - - bool ptonResult = false; - if (isIPV6) { - ip6Addr.sin6_family = AF_INET6; - ip6Addr.sin6_port = htons(port); - ptonResult = inet_pton(AF_INET6, - server_ip.c_str(), - &ip6Addr.sin6_addr) > 0; - paddr = (struct sockaddr_in *)&ip6Addr; - addrLen = sizeof(ip6Addr); - } else { - ip4Addr.sin_family = AF_INET; - ip4Addr.sin_port = htons(port); - ptonResult = inet_pton(AF_INET, - server_ip.c_str(), - &ip4Addr.sin_addr) > 0; - } - - if (!ptonResult) { - SocketClose(clientfd); - return BRYNET_INVALID_SOCKET; - } - - while (::connect(clientfd, (struct sockaddr *)paddr, addrLen) < 0) { - if (EINTR == BRYNET_ERRNO) { - continue; - } - - SocketClose(clientfd); - return BRYNET_INVALID_SOCKET; - } - - return clientfd; -} - -static BrynetSocketFD Listen(bool isIPV6, const char *ip, int port, int back_num, bool enabledReusePort) { - InitSocket(); - - struct sockaddr_in ip4Addr = sockaddr_in(); - struct sockaddr_in6 ip6Addr = sockaddr_in6(); - struct sockaddr_in *paddr = &ip4Addr; - int addrLen = sizeof(ip4Addr); - - const auto socketfd = isIPV6 ? socket(AF_INET6, SOCK_STREAM, 0) : socket(AF_INET, SOCK_STREAM, 0); - if (socketfd == BRYNET_INVALID_SOCKET) { - return BRYNET_INVALID_SOCKET; - } - - bool ptonResult = false; - if (isIPV6) { - ip6Addr.sin6_family = AF_INET6; - ip6Addr.sin6_port = htons(port); - ptonResult = inet_pton(AF_INET6, ip, &ip6Addr.sin6_addr) > 0; - paddr = (struct sockaddr_in *)&ip6Addr; - addrLen = sizeof(ip6Addr); - } else { - ip4Addr.sin_family = AF_INET; - ip4Addr.sin_port = htons(port); - ip4Addr.sin_addr.s_addr = INADDR_ANY; - ptonResult = inet_pton(AF_INET, ip, &ip4Addr.sin_addr) > 0; - } - - const int reuseaddr_value = 1; - if (!ptonResult || - ::setsockopt(socketfd, - SOL_SOCKET, - SO_REUSEADDR, - (const char *)&reuseaddr_value, - sizeof(int)) < 0) { - SocketClose(socketfd); - return BRYNET_INVALID_SOCKET; - } - - if (enabledReusePort && SocketSetReusePort(socketfd) < 0) { - SocketClose(socketfd); - return BRYNET_INVALID_SOCKET; - } - - const int bindRet = ::bind(socketfd, (struct sockaddr *)paddr, addrLen); - if (bindRet == BRYNET_SOCKET_ERROR || - listen(socketfd, back_num) == BRYNET_SOCKET_ERROR) { - SocketClose(socketfd); - return BRYNET_INVALID_SOCKET; - } - - return socketfd; -} - -static std::string getIPString(const struct sockaddr *sa) { -#ifdef BRYNET_PLATFORM_WINDOWS - using PAddrType = PVOID; -#elif defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN - using PAddrType = const void *; -#endif - char tmp[INET6_ADDRSTRLEN] = { 0 }; - switch (sa->sa_family) { - case AF_INET: - inet_ntop(AF_INET, (PAddrType)(&(((const struct sockaddr_in *)sa)->sin_addr)), - tmp, sizeof(tmp)); - break; - case AF_INET6: - inet_ntop(AF_INET6, (PAddrType)(&(((const struct sockaddr_in6 *)sa)->sin6_addr)), - tmp, sizeof(tmp)); - break; - default: - return "Unknown AF"; - } - - return tmp; -} - -static std::string GetIPOfSocket(BrynetSocketFD fd) { -#ifdef BRYNET_PLATFORM_WINDOWS - struct sockaddr name = sockaddr(); - int namelen = sizeof(name); - if (::getpeername(fd, (struct sockaddr *)&name, &namelen) == 0) { - return getIPString(&name); - } -#elif defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN - struct sockaddr_in name = sockaddr_in(); - socklen_t namelen = sizeof(name); - if (::getpeername(fd, (struct sockaddr *)&name, &namelen) == 0) { - return getIPString((const struct sockaddr *)&name); - } -#endif - - return ""; -} - -static int SocketSend(BrynetSocketFD fd, const char *buffer, int len) { - int transnum = ::send(fd, buffer, len, 0); - if (transnum < 0 && BRYNET_EWOULDBLOCK == BRYNET_ERRNO) { - transnum = 0; - } - - /* send error if transnum < 0 */ - return transnum; -} - -static BrynetSocketFD Accept(BrynetSocketFD listenSocket, struct sockaddr *addr, socklen_t *addrLen) { - return ::accept(listenSocket, addr, addrLen); -} - -static struct sockaddr_in6 getPeerAddr(BrynetSocketFD sockfd) { - struct sockaddr_in6 peeraddr = sockaddr_in6(); - auto addrlen = static_cast(sizeof peeraddr); - if (::getpeername(sockfd, (struct sockaddr *)(&peeraddr), &addrlen) < 0) { - return peeraddr; - } - return peeraddr; -} - -static struct sockaddr_in6 getLocalAddr(BrynetSocketFD sockfd) { - struct sockaddr_in6 localaddr = sockaddr_in6(); - auto addrlen = static_cast(sizeof localaddr); - if (::getsockname(sockfd, (struct sockaddr *)(&localaddr), &addrlen) < 0) { - return localaddr; - } - return localaddr; -} - -static bool IsSelfConnect(BrynetSocketFD fd) { - struct sockaddr_in6 localaddr = getLocalAddr(fd); - struct sockaddr_in6 peeraddr = getPeerAddr(fd); - - if (localaddr.sin6_family == AF_INET) { - const struct sockaddr_in *laddr4 = reinterpret_cast(&localaddr); - const struct sockaddr_in *raddr4 = reinterpret_cast(&peeraddr); - return laddr4->sin_port == raddr4->sin_port && laddr4->sin_addr.s_addr == raddr4->sin_addr.s_addr; - } else if (localaddr.sin6_family == AF_INET6) { -#ifdef BRYNET_PLATFORM_WINDOWS - return localaddr.sin6_port == peeraddr.sin6_port && memcmp(&localaddr.sin6_addr.u.Byte, - &peeraddr.sin6_addr.u.Byte, - sizeof localaddr.sin6_addr.u.Byte) == 0; -#elif defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN - return localaddr.sin6_port == peeraddr.sin6_port && memcmp(&localaddr.sin6_addr.s6_addr, - &peeraddr.sin6_addr.s6_addr, - sizeof localaddr.sin6_addr.s6_addr) == 0; -#endif - } else { - return false; - } -} diff --git a/libs/brynet/net/SocketLibTypes.hpp b/libs/brynet/net/SocketLibTypes.hpp deleted file mode 100644 index 59ae25f..0000000 --- a/libs/brynet/net/SocketLibTypes.hpp +++ /dev/null @@ -1,72 +0,0 @@ -#pragma once - -#include - -#ifdef BRYNET_PLATFORM_WINDOWS -#define WIN32_LEAN_AND_MEAN -#include -#include -#include -#include -#include - -#elif defined BRYNET_PLATFORM_LINUX -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#elif defined BRYNET_PLATFORM_DARWIN -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#else -#error "Unsupported OS, please commit an issuse." -#endif - -#ifdef BRYNET_PLATFORM_WINDOWS -typedef SOCKET BrynetSocketFD; -#define BRYNET_ERRNO WSAGetLastError() -#define BRYNET_ENOTSOCK WSAENOTSOCK -#define BRYNET_EWOULDBLOCK WSAEWOULDBLOCK -#define BRYNET_EINTR WSAEINTR -#define BRYNET_ECONNABORTED WSAECONNABORTED -#define BRYNET_SOCKET_ERROR SOCKET_ERROR -#define BRYNET_INVALID_SOCKET INVALID_SOCKET - -#elif defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN -#define BRYNET_ERRNO errno -#define BRYNET_ENOTSOCK EBADF -#define BRYNET_EWOULDBLOCK EAGAIN -#define BRYNET_EINTR EINTR -#define BRYNET_ECONNABORTED ECONNABORTED -typedef int BrynetSocketFD; -#define BRYNET_SOCKET_ERROR (-1) -#define BRYNET_INVALID_SOCKET (-1) -#endif diff --git a/libs/brynet/net/TcpConnection.hpp b/libs/brynet/net/TcpConnection.hpp deleted file mode 100644 index 8edeb0f..0000000 --- a/libs/brynet/net/TcpConnection.hpp +++ /dev/null @@ -1,1044 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef BRYNET_USE_OPENSSL - -#ifdef __cplusplus -extern "C" { -#endif -#include -#include -#ifdef __cplusplus -} -#endif - -#endif - -class TcpConnection : public Channel, - public NonCopyable, - public std::enable_shared_from_this { -public: - using Ptr = std::shared_ptr; - - using EnterCallback = std::function; - using DataCallback = std::function; - using DisconnectedCallback = std::function; - using PacketSendedCallback = std::function; - using HighWaterCallback = std::function; - -public: - Ptr static Create(TcpSocket::Ptr socket, - size_t maxRecvBufferSize, - EnterCallback &&enterCallback, - const EventLoop::Ptr &eventLoop, - const SSLHelper::Ptr &sslHelper = nullptr) { - class make_shared_enabler : public TcpConnection { - public: - make_shared_enabler(TcpSocket::Ptr socket, - size_t maxRecvBufferSize, - EnterCallback &&enterCallback, - EventLoop::Ptr eventLoop) : - TcpConnection(std::move(socket), - maxRecvBufferSize, - std::move(enterCallback), - std::move(eventLoop)) {} - }; - - const auto isServerSide = socket->isServerSide(); - auto session = std::make_shared( - std::move(socket), - maxRecvBufferSize, - std::move(enterCallback), - eventLoop); - (void)isServerSide; -#ifdef BRYNET_USE_OPENSSL - if (sslHelper != nullptr) { - if (isServerSide) { - if (sslHelper->getOpenSSLCTX() == nullptr || - !session->initAcceptSSL(sslHelper->getOpenSSLCTX())) { - throw std::runtime_error("init ssl failed"); - } - } else { - if (!session->initConnectSSL()) { - throw std::runtime_error("init ssl failed"); - } - } - } -#else - if (sslHelper != nullptr) { - throw std::runtime_error("not enable ssl"); - } -#endif - - eventLoop->runAsyncFunctor([session]() { - session->onEnterEventLoop(); - }); - return session; - } - - const EventLoop::Ptr &getEventLoop() const { - return mEventLoop; - } - - //TODO::如果所属EventLoop已经没有工作,则可能导致内存无限大,因为所投递的请求都没有得到处理 - void send(const SendableMsg::Ptr &msg, - PacketSendedCallback &&callback = nullptr) { - if (mEventLoop->isInLoopThread()) { - sendInLoop(msg, std::move(callback)); - } else { - auto sharedThis = shared_from_this(); - mEventLoop->runAsyncFunctor([sharedThis, msg, callback, this]() mutable { - sendInLoop(msg, std::move(callback)); - }); - } - } - - void send(const char *buffer, - size_t len, - PacketSendedCallback &&callback = nullptr) { - send(MakeStringMsg(buffer, len), std::move(callback)); - } - - void send(const std::string &buffer, - PacketSendedCallback &&callback = nullptr) { - send(MakeStringMsg(buffer), std::move(callback)); - } - - void send(std::string &&buffer, - PacketSendedCallback &&callback = nullptr) { - send(MakeStringMsg(std::move(buffer)), std::move(callback)); - } - - // setDataCallback(std::function) - template - void setDataCallback(Callback &&cb) { - verifyArgType(cb, &Callback::operator()); - - auto sharedThis = shared_from_this(); - mEventLoop->runAsyncFunctor([sharedThis, cb, this]() mutable { - mDataCallback = cb; - processRecvMessage(); - }); - } - - void setDisConnectCallback(DisconnectedCallback &&cb) { - auto sharedThis = shared_from_this(); - mEventLoop->runAsyncFunctor([sharedThis, cb, this]() mutable { - mDisConnectCallback = std::move(cb); - }); - } - - /* if checkTime is zero, will cancel check heartbeat */ - void setHeartBeat(std::chrono::nanoseconds checkTime) { - auto sharedThis = shared_from_this(); - mEventLoop->runAsyncFunctor([sharedThis, checkTime, this]() { - if (mTimer.lock() != nullptr) { - mTimer.lock()->cancel(); - mTimer.reset(); - } - - mCheckTime = checkTime; - startPingCheckTimer(); - }); - } - - void setHighWaterCallback(HighWaterCallback cb, size_t size) { - auto sharedThis = shared_from_this(); - mEventLoop->runAsyncFunctor([=]() mutable { - mHighWaterCallback = std::move(cb); - mHighWaterSize = size; - }); - } - - void postShrinkReceiveBuffer() { - auto sharedThis = shared_from_this(); - mEventLoop->runAsyncFunctor([sharedThis, this]() { - mEventLoop->runFunctorAfterLoop([sharedThis, this]() { - shrinkReceiveBuffer(); - }); - }); - } - - void postDisConnect() { - auto sharedThis = shared_from_this(); - mEventLoop->runAsyncFunctor([sharedThis, this]() { - procCloseInLoop(); - }); - } - - void postShutdown() { - auto sharedThis = shared_from_this(); - mEventLoop->runAsyncFunctor([sharedThis, this]() { - mEventLoop->runFunctorAfterLoop([sharedThis, this]() { - procShutdownInLoop(); - }); - }); - } - - const std::string &getIP() const { - return mIP; - } - -protected: - TcpConnection(TcpSocket::Ptr socket, - size_t maxRecvBufferSize, - EnterCallback &&enterCallback, - EventLoop::Ptr eventLoop) BRYNET_NOEXCEPT - : -#ifdef BRYNET_PLATFORM_WINDOWS - mOvlRecv(port::Win::OverlappedType::OverlappedRecv), - mOvlSend(port::Win::OverlappedType::OverlappedSend), - mPostClose(false), -#endif - mIP(socket->getRemoteIP()), - mSocket(std::move(socket)), - mEventLoop(std::move(eventLoop)), - mAlreadyClose(false), - mMaxRecvBufferSize(maxRecvBufferSize), - mSendingMsgSize(0), - mEnterCallback(std::move(enterCallback)), - mHighWaterSize(0) { - mRecvData = false; - mCheckTime = std::chrono::steady_clock::duration::zero(); - mIsPostFlush = false; - - mCanWrite = true; - -#ifdef BRYNET_PLATFORM_WINDOWS - mPostRecvCheck = false; - mPostWriteCheck = false; -#endif - growRecvBuffer(); - -#ifdef BRYNET_USE_OPENSSL - mSSLCtx = nullptr; - mSSL = nullptr; - mIsHandsharked = false; -#endif - } - - ~TcpConnection() BRYNET_NOEXCEPT override { -#ifdef BRYNET_USE_OPENSSL - if (mSSL != nullptr) { - SSL_free(mSSL); - mSSL = nullptr; - } - if (mSSLCtx != nullptr) { - SSL_CTX_free(mSSLCtx); - mSSLCtx = nullptr; - } -#endif - - if (mTimer.lock()) { - mTimer.lock()->cancel(); - } - } - -private: - void sendInLoop(const SendableMsg::Ptr &msg, - PacketSendedCallback &&callback = nullptr) { - if (mAlreadyClose) { - return; - } - - const auto len = msg->size(); - mSendingMsgSize += len; - mSendList.emplace_back(PendingPacket{ - msg, - len, - std::move(callback) }); - runAfterFlush(); - - if (mSendingMsgSize > mHighWaterSize && - mHighWaterCallback != nullptr) { - mHighWaterCallback(); - } - } - - void growRecvBuffer() { - if (mRecvBuffer == nullptr) { - mRecvBuffer.reset(buffer_new(std::min(16 * 1024, mMaxRecvBufferSize))); - mRecvBuffOriginSize = buffer_getsize(mRecvBuffer.get()); - } else { - if (buffer_getsize(mRecvBuffer.get()) >= mMaxRecvBufferSize) { - return; - } - - mCurrentTanhXDiff += 0.2; - const auto newTanh = std::tanh(mCurrentTanhXDiff); - const auto maxSizeDiff = mMaxRecvBufferSize - mRecvBuffOriginSize; - const auto NewSize = mRecvBuffOriginSize + (maxSizeDiff * newTanh); - - assert(NewSize <= mMaxRecvBufferSize); - std::unique_ptr newBuffer(buffer_new(NewSize)); - buffer_write(newBuffer.get(), - buffer_getreadptr(mRecvBuffer.get()), - buffer_getreadvalidcount(mRecvBuffer.get())); - mRecvBuffer = std::move(newBuffer); - } - } - - void shrinkReceiveBuffer() { - auto newSize = buffer_getreadvalidcount(mRecvBuffer.get()); - if (newSize == 0) { - newSize = std::min(16 * 1024, mMaxRecvBufferSize); - } - if (newSize == buffer_getsize(mRecvBuffer.get())) { - return; - } - - std::unique_ptr - newBuffer(buffer_new(newSize)); - buffer_write(newBuffer.get(), - buffer_getreadptr(mRecvBuffer.get()), - buffer_getreadvalidcount(mRecvBuffer.get())); - - mRecvBuffer = std::move(newBuffer); - mCurrentTanhXDiff = 0; - mRecvBuffOriginSize = newSize; - } - - /* must called in network thread */ - bool onEnterEventLoop() { - assert(mEventLoop->isInLoopThread()); - if (!mEventLoop->isInLoopThread()) { - return false; - } - - if (!SocketNonblock(mSocket->getFD()) || - !mEventLoop->linkChannel(mSocket->getFD(), this)) { - return false; - } - - const auto findRet = mEventLoop->getTcpConnection(mSocket->getFD()); - (void)findRet; - assert(findRet == nullptr); - -#ifdef BRYNET_USE_OPENSSL - if (mSSL != nullptr) { - mEventLoop->addTcpConnection(mSocket->getFD(), shared_from_this()); - processSSLHandshake(); - return true; - } -#endif - - if (!checkRead()) { - return false; - } - - mEventLoop->addTcpConnection(mSocket->getFD(), shared_from_this()); - causeEnterCallback(); - - return true; - } - -#ifdef BRYNET_USE_OPENSSL - bool initAcceptSSL(SSL_CTX *ctx) { - if (mSSL != nullptr) { - return false; - } - - mSSL = SSL_new(ctx); - if (SSL_set_fd(mSSL, mSocket->getFD()) != 1) { - ERR_print_errors_fp(stdout); - ::fflush(stdout); - return false; - } - - return true; - } - bool initConnectSSL() { - if (mSSLCtx != nullptr) { - return false; - } - - mSSLCtx = SSL_CTX_new(SSLv23_client_method()); - mSSL = SSL_new(mSSLCtx); - - if (SSL_set_fd(mSSL, mSocket->getFD()) != 1) { - ERR_print_errors_fp(stdout); - ::fflush(stdout); - return false; - } - - return true; - } -#endif - - void pingCheck() { - mTimer.reset(); - if (mRecvData) { - mRecvData = false; - startPingCheckTimer(); - } else { - procCloseInLoop(); - } - } - - void startPingCheckTimer() { - if (!mTimer.lock() && - mCheckTime != std::chrono::steady_clock::duration::zero()) { - std::weak_ptr weakThis = shared_from_this(); - mTimer = mEventLoop->runAfter(mCheckTime, [weakThis]() { - auto sharedThis = weakThis.lock(); - if (sharedThis != nullptr) { - sharedThis->pingCheck(); - } - }); - } - } - - void canRecv(const bool willClose) override { -#ifdef BRYNET_PLATFORM_WINDOWS - mPostRecvCheck = false; - if (mPostClose) { - if (!mPostWriteCheck) { - onClose(); - } - return; - } -#elif defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN - if (mAlreadyClose) { - return; - } -#endif - -#ifdef BRYNET_USE_OPENSSL - if (mSSL != nullptr && !mIsHandsharked && (!processSSLHandshake() || !mIsHandsharked)) { - return; - } -#endif - - do { - recv(); - adjustReceiveBuffer(); - } while (willClose && !mAlreadyClose && mRecvBuffer != nullptr && buffer_getwritevalidcount(mRecvBuffer.get()) > 0); - } - - void canSend() override { -#ifdef BRYNET_PLATFORM_WINDOWS - mPostWriteCheck = false; - if (mPostClose) { - if (!mPostRecvCheck) { - onClose(); - } - return; - } -#elif defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN - if (mAlreadyClose) { - return; - } -#endif - mCanWrite = true; - -#ifdef BRYNET_USE_OPENSSL - if (mSSL != nullptr && !mIsHandsharked && (!processSSLHandshake() || !mIsHandsharked)) { - return; - } -#endif - - runAfterFlush(); - } - - bool checkRead() { - bool check_ret = true; -#ifdef BRYNET_PLATFORM_WINDOWS - static CHAR temp[] = { 0 }; - static WSABUF in_buf = { 0, temp }; - - if (mPostRecvCheck) { - return check_ret; - } - - DWORD dwBytes = 0; - DWORD flag = 0; - const int ret = WSARecv(mSocket->getFD(), - &in_buf, - 1, - &dwBytes, - &flag, - &(mOvlRecv.base), - 0); - if (ret == BRYNET_SOCKET_ERROR) { - check_ret = (BRYNET_ERRNO == WSA_IO_PENDING); - } - - if (check_ret) { - mPostRecvCheck = true; - } -#endif - - return check_ret; - } - - bool checkWrite() { - bool check_ret = true; -#ifdef BRYNET_PLATFORM_WINDOWS - static WSABUF wsendbuf[1] = { { NULL, - 0 } }; - - if (mPostWriteCheck) { - return check_ret; - } - - DWORD send_len = 0; - const int ret = WSASend(mSocket->getFD(), - wsendbuf, - 1, - &send_len, - 0, - &(mOvlSend.base), - 0); - if (ret == BRYNET_SOCKET_ERROR) { - check_ret = (BRYNET_ERRNO == WSA_IO_PENDING); - } - - if (check_ret) { - mPostWriteCheck = true; - } -#endif - return check_ret; - } - - void adjustReceiveBuffer() { - if (!mRecvBuffer) { - return; - } - - if (buffer_getwritevalidcount(mRecvBuffer.get()) == 0 || buffer_getreadvalidcount(mRecvBuffer.get()) == 0) { - buffer_adjustto_head(mRecvBuffer.get()); - } - - if (buffer_getreadvalidcount(mRecvBuffer.get()) == buffer_getsize(mRecvBuffer.get())) { - growRecvBuffer(); - } - } - - void recv() { - bool must_close = false; -#ifdef BRYNET_USE_OPENSSL - const bool notInSSL = (mSSL == nullptr); -#else - const bool notInSSL = false; -#endif - - while (true) { - adjustReceiveBuffer(); - - const auto tryRecvLen = buffer_getwritevalidcount(mRecvBuffer.get()); - if (tryRecvLen == 0) { -#ifdef BRYNET_PLATFORM_WINDOWS - checkRead(); -#elif defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN - //force recheck IN-OUT Event - recheckEvent(); -#endif - break; - } - - int retlen = 0; -#ifdef BRYNET_USE_OPENSSL - if (mSSL != nullptr) { - retlen = SSL_read(mSSL, - buffer_getwriteptr(mRecvBuffer.get()), tryRecvLen); - } else { - retlen = ::recv(mSocket->getFD(), - buffer_getwriteptr(mRecvBuffer.get()), tryRecvLen, 0); - } -#else - retlen = ::recv(mSocket->getFD(), - buffer_getwriteptr(mRecvBuffer.get()), - static_cast(tryRecvLen), - 0); -#endif - - if (retlen == 0) { - must_close = true; - break; - } else if (retlen < 0) { -#ifdef BRYNET_USE_OPENSSL - if ((mSSL != nullptr && - SSL_get_error(mSSL, retlen) == SSL_ERROR_WANT_READ) || - (BRYNET_ERRNO == BRYNET_EWOULDBLOCK)) { - must_close = !checkRead(); - } else { - must_close = true; - } -#else - if (BRYNET_ERRNO != BRYNET_EWOULDBLOCK) { - must_close = true; - } else { - must_close = !checkRead(); - } -#endif - break; - } - - mRecvData = true; - buffer_addwritepos(mRecvBuffer.get(), static_cast(retlen)); - - if (notInSSL && retlen < static_cast(tryRecvLen)) { - must_close = !checkRead(); - break; - } - } - - processRecvMessage(); - - if (must_close) { - procCloseInLoop(); - } - } - - void flush() { -#ifdef BRYNET_PLATFORM_WINDOWS - normalFlush(); -#elif defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN -#ifdef BRYNET_USE_OPENSSL - if (mSSL != nullptr) { - normalFlush(); - } else { - quickFlush(); - } -#else - quickFlush(); -#endif -#endif - } - void normalFlush() { -#ifdef BRYNET_PLATFORM_WINDOWS - static __declspec(thread) char *threadLocalSendBuf = nullptr; -#elif defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN - static __thread char *threadLocalSendBuf = nullptr; -#endif - static const int SENDBUF_SIZE = 1024 * 32; - if (threadLocalSendBuf == nullptr) { - threadLocalSendBuf = static_cast(malloc(SENDBUF_SIZE)); - } - -#ifdef BRYNET_USE_OPENSSL - const bool notInSSL = (mSSL == nullptr); -#else - const bool notInSSL = false; -#endif - - bool must_close = false; - - while (!mSendList.empty() && mCanWrite) { - auto sendptr = threadLocalSendBuf; - size_t wait_send_size = 0; - - for (auto it = mSendList.begin(); it != mSendList.end(); ++it) { - auto &packet = *it; - auto packetLeftBuf = (char *)(packet.data->data()) + packet.data->size() - packet.left; - const auto packetLeftLen = packet.left; - - if ((wait_send_size + packetLeftLen) > SENDBUF_SIZE) { - if (it == mSendList.begin()) { - sendptr = packetLeftBuf; - wait_send_size = packetLeftLen; - } - break; - } - - memcpy(static_cast(sendptr + wait_send_size), static_cast(packetLeftBuf), packetLeftLen); - wait_send_size += packetLeftLen; - } - - if (wait_send_size == 0) { - break; - } - - int send_retlen = 0; -#ifdef BRYNET_USE_OPENSSL - if (mSSL != nullptr) { - send_retlen = SSL_write(mSSL, sendptr, wait_send_size); - } else { - send_retlen = ::send(mSocket->getFD(), sendptr, wait_send_size, 0); - } -#else - send_retlen = ::send(mSocket->getFD(), sendptr, static_cast(wait_send_size), 0); -#endif - if (send_retlen <= 0) { - -#ifdef BRYNET_USE_OPENSSL - if ((mSSL != nullptr && SSL_get_error(mSSL, send_retlen) == SSL_ERROR_WANT_WRITE) || - (BRYNET_ERRNO == BRYNET_EWOULDBLOCK)) { - mCanWrite = false; - must_close = !checkWrite(); - } else { - must_close = true; - } -#else - if (BRYNET_ERRNO == BRYNET_EWOULDBLOCK) { - mCanWrite = false; - must_close = !checkWrite(); - } else { - must_close = true; - } -#endif - break; - } - - auto tmp_len = static_cast(send_retlen); - for (auto it = mSendList.begin(); it != mSendList.end();) { - auto &packet = *it; - if (packet.left > tmp_len) { - packet.left -= tmp_len; - break; - } - - tmp_len -= packet.left; - if (packet.mCompleteCallback != nullptr) { - (packet.mCompleteCallback)(); - } - mSendingMsgSize -= packet.data->size(); - it = mSendList.erase(it); - } - - if (notInSSL && static_cast(send_retlen) != wait_send_size) { - mCanWrite = false; - must_close = !checkWrite(); - break; - } - } - - if (must_close) { - procCloseInLoop(); - } - } -#if defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN - void quickFlush() { -#ifndef MAX_IOVEC - constexpr size_t MAX_IOVEC = 1024; -#endif - - struct iovec iov[MAX_IOVEC]; - bool must_close = false; - - while (!mSendList.empty() && mCanWrite) { - size_t num = 0; - size_t ready_send_len = 0; - for (const auto &p : mSendList) { - iov[num].iov_base = (void *)(static_cast(p.data->data()) + p.data->size() - p.left); - iov[num].iov_len = p.left; - ready_send_len += p.left; - - num++; - if (num >= MAX_IOVEC) { - break; - } - } - - if (num == 0) { - break; - } - - const int send_len = writev(mSocket->getFD(), iov, static_cast(num)); - if (send_len <= 0) { - if (BRYNET_ERRNO == BRYNET_EWOULDBLOCK) { - mCanWrite = false; - must_close = !checkWrite(); - } else { - must_close = true; - } - break; - } - - auto tmp_len = static_cast(send_len); - for (auto it = mSendList.begin(); it != mSendList.end();) { - PendingPacket &b = *it; - if (b.left > tmp_len) { - b.left -= tmp_len; - break; - } - - tmp_len -= b.left; - if (b.mCompleteCallback != nullptr) { - b.mCompleteCallback(); - } - mSendingMsgSize -= b.data->size(); - it = mSendList.erase(it); - } - - if (static_cast(send_len) != ready_send_len) { - mCanWrite = false; - must_close = !checkWrite(); - break; - } - } - - if (must_close) { - procCloseInLoop(); - } - } -#endif - - void onClose() override { - if (mAlreadyClose) { - return; - } - mAlreadyClose = true; - -#if defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN - unregisterPollerEvent(); -#endif - - assert(mEnterCallback == nullptr); - auto callBack = mDisConnectCallback; - auto sharedThis = shared_from_this(); - auto eventLoop = mEventLoop; - std::shared_ptr socket = std::move(const_cast(mSocket)); - mEventLoop->runFunctorAfterLoop([callBack, - sharedThis, - eventLoop, - socket]() { - if (callBack != nullptr) { - callBack(sharedThis); - } - auto tmp = eventLoop->getTcpConnection(socket->getFD()); - assert(tmp == sharedThis); - if (tmp == sharedThis) { - eventLoop->removeTcpConnection(socket->getFD()); - } - }); - - mCanWrite = false; - mDataCallback = nullptr; - mDisConnectCallback = nullptr; - mHighWaterCallback = nullptr; - mRecvBuffer = nullptr; - mSendList.clear(); - } - - void procCloseInLoop() { - mCanWrite = false; -#ifdef BRYNET_PLATFORM_WINDOWS - if (mPostWriteCheck || mPostRecvCheck) { - if (mPostClose) { - return; - } - mPostClose = true; - //windows下立即关闭socket可能导致fd被另外的TcpConnection重用,而导致此对象在IOCP返回相关完成结果时内存已经释放 - if (mPostRecvCheck) { - CancelIoEx(HANDLE(mSocket->getFD()), &mOvlRecv.base); - } - if (mPostWriteCheck) { - CancelIoEx(HANDLE(mSocket->getFD()), &mOvlSend.base); - } - } else { - onClose(); - } -#elif defined BRYNET_PLATFORM_LINUX - onClose(); -#elif defined BRYNET_PLATFORM_DARWIN - onClose(); -#endif - } - - void procShutdownInLoop() { - mCanWrite = false; - if (mSocket != nullptr) { -#ifdef BRYNET_PLATFORM_WINDOWS - shutdown(mSocket->getFD(), SD_SEND); -#elif defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN - shutdown(mSocket->getFD(), SHUT_WR); -#endif - } - } - - void runAfterFlush() { - if (!mIsPostFlush && !mSendList.empty() && mCanWrite) { - auto sharedThis = shared_from_this(); - mEventLoop->runFunctorAfterLoop([sharedThis, this]() { - mIsPostFlush = false; - flush(); - }); - - mIsPostFlush = true; - } - } -#if defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN - void recheckEvent() { -#ifdef BRYNET_PLATFORM_LINUX - struct epoll_event ev = { 0, - { - nullptr - } }; - ev.events = EPOLLET | EPOLLIN | EPOLLOUT | EPOLLRDHUP; - ev.data.ptr = (Channel *)(this); - epoll_ctl(mEventLoop->getEpollHandle(), EPOLL_CTL_MOD, mSocket->getFD(), &ev); -#elif defined BRYNET_PLATFORM_DARWIN - struct kevent ev[2]; - memset(&ev, 0, sizeof(ev)); - int n = 0; - EV_SET(&ev[n++], mSocket->getFD(), EVFILT_READ, EV_ENABLE, 0, 0, (Channel *)(this)); - EV_SET(&ev[n++], mSocket->getFD(), EVFILT_WRITE, EV_ENABLE, 0, 0, (Channel *)(this)); - - struct timespec now = { 0, 0 }; - kevent(mEventLoop->getKqueueHandle(), ev, n, NULL, 0, &now); -#endif - } - void unregisterPollerEvent() { -#ifdef BRYNET_PLATFORM_LINUX - struct epoll_event ev = { 0, - { - nullptr - } }; - epoll_ctl(mEventLoop->getEpollHandle(), EPOLL_CTL_DEL, mSocket->getFD(), &ev); -#elif defined BRYNET_PLATFORM_DARWIN - struct kevent ev[2]; - memset(&ev, 0, sizeof(ev)); - int n = 0; - EV_SET(&ev[n++], mSocket->getFD(), EVFILT_READ, EV_DELETE, 0, 0, NULL); - EV_SET(&ev[n++], mSocket->getFD(), EVFILT_WRITE, EV_DELETE, 0, 0, NULL); - - struct timespec now = { 0, 0 }; - kevent(mEventLoop->getKqueueHandle(), ev, n, NULL, 0, &now); -#endif - } -#endif -#ifdef BRYNET_USE_OPENSSL - bool processSSLHandshake() { - if (mIsHandsharked) { - return true; - } - - bool mustClose = false; - int ret = 0; - - if (mSSLCtx != nullptr) { - ret = SSL_connect(mSSL); - } else { - ret = SSL_accept(mSSL); - } - - if (ret == 1) { - mIsHandsharked = true; - if (checkRead()) { - causeEnterCallback(); - } else { - mustClose = true; - } - } else if (ret == 0) { - mustClose = true; - } else if (ret < 0) { - int err = SSL_get_error(mSSL, ret); - if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) { - if (!checkRead()) { - mustClose = true; - } - } else { - mustClose = true; - } - } - - if (mustClose) { - causeEnterCallback(); - procCloseInLoop(); - return false; - } - return true; - } -#endif - void causeEnterCallback() { - assert(mEventLoop->isInLoopThread()); - if (mEventLoop->isInLoopThread() && mEnterCallback != nullptr) { - auto tmp = mEnterCallback; - mEnterCallback = nullptr; - tmp(shared_from_this()); - } - } - - void processRecvMessage() { - if (mDataCallback != nullptr && buffer_getreadvalidcount(mRecvBuffer.get()) > 0) { - auto reader = BasePacketReader(buffer_getreadptr(mRecvBuffer.get()), - buffer_getreadvalidcount(mRecvBuffer.get()), false); - mDataCallback(reader); - const auto consumedLen = reader.savedPos(); - assert(consumedLen <= reader.size()); - if (consumedLen <= reader.size()) { - buffer_addreadpos(mRecvBuffer.get(), consumedLen); - } - } - } - - template - static void verifyArgType(const CallbackType &, void (CallbackType::*)(Arg &) const) { - static_assert(std::is_reference::value, "arg must be reference type"); - static_assert(!std::is_const::type>::value, "arg can't be const type"); - } - -private: -#ifdef BRYNET_PLATFORM_WINDOWS - struct port::Win::OverlappedExt mOvlRecv; - struct port::Win::OverlappedExt mOvlSend; - - bool mPostRecvCheck; - bool mPostWriteCheck; - bool mPostClose; -#endif - const std::string mIP; - const TcpSocket::Ptr mSocket; - const EventLoop::Ptr mEventLoop; - bool mCanWrite; - bool mAlreadyClose; - - class BufferDeleter { - public: - void operator()(struct buffer_s *ptr) const { - buffer_delete(ptr); - } - }; - std::unique_ptr mRecvBuffer; - double mCurrentTanhXDiff = 0; - size_t mRecvBuffOriginSize = 0; - const size_t mMaxRecvBufferSize; - - struct PendingPacket { - SendableMsg::Ptr data; - size_t left; - PacketSendedCallback mCompleteCallback; - }; - - using PacketListType = std::deque; - PacketListType mSendList; - size_t mSendingMsgSize; - - EnterCallback mEnterCallback; - DataCallback mDataCallback; - DisconnectedCallback mDisConnectCallback; - HighWaterCallback mHighWaterCallback; - size_t mHighWaterSize; - - bool mIsPostFlush; - -#ifdef BRYNET_USE_OPENSSL - SSL_CTX *mSSLCtx; - SSL *mSSL; - bool mIsHandsharked; -#endif - bool mRecvData; - std::chrono::nanoseconds mCheckTime{}; - Timer::WeakPtr mTimer; -}; diff --git a/libs/brynet/net/TcpService.hpp b/libs/brynet/net/TcpService.hpp deleted file mode 100644 index 88fca99..0000000 --- a/libs/brynet/net/TcpService.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include - -using ConnectionOption = ConnectionOption; -class TcpService : public TcpServiceDetail, - public std::enable_shared_from_this { -public: - using Ptr = std::shared_ptr; - using FrameCallback = TcpServiceDetail::FrameCallback; - -public: - static Ptr Create() { - struct make_shared_enabler : public TcpService { - }; - return std::make_shared(); - } - - void startWorkerThread(size_t threadNum, - FrameCallback callback = nullptr) { - TcpServiceDetail::startWorkerThread(threadNum, callback); - } - - void stopWorkerThread() { - TcpServiceDetail::stopWorkerThread(); - } - - bool addTcpConnection(TcpSocket::Ptr socket, ConnectionOption options) { - return TcpServiceDetail::addTcpConnection(std::move(socket), options); - } - - EventLoop::Ptr getRandomEventLoop() { - return TcpServiceDetail::getRandomEventLoop(); - } - -private: - TcpService() = default; -}; diff --git a/libs/brynet/net/detail/ConnectionOption.hpp b/libs/brynet/net/detail/ConnectionOption.hpp deleted file mode 100644 index 3281695..0000000 --- a/libs/brynet/net/detail/ConnectionOption.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include -#include - -class ConnectionOption final { -public: - std::vector enterCallback; - SSLHelper::Ptr sslHelper; - bool useSSL = false; - bool forceSameThreadLoop = false; - size_t maxRecvBufferSize = 128; -}; diff --git a/libs/brynet/net/detail/ConnectorDetail.hpp b/libs/brynet/net/detail/ConnectorDetail.hpp deleted file mode 100644 index e21e735..0000000 --- a/libs/brynet/net/detail/ConnectorDetail.hpp +++ /dev/null @@ -1,128 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef BRYNET_HAVE_LANG_CXX17 -#include -#else -#include -#endif - -class AsyncConnectorDetail : public NonCopyable { -protected: - void startWorkerThread() { -#ifdef BRYNET_HAVE_LANG_CXX17 - std::lock_guard lck(mThreadGuard); -#else - std::lock_guard lck(mThreadGuard); -#endif - - if (mThread != nullptr) { - return; - } - - mIsRun = std::make_shared(true); - mWorkInfo = std::make_shared(); - mEventLoop = std::make_shared(); - - auto eventLoop = mEventLoop; - auto workerInfo = mWorkInfo; - auto isRun = mIsRun; - - mThread = std::make_shared([eventLoop, workerInfo, isRun]() { - while (*isRun) { - RunOnceCheckConnect(eventLoop, workerInfo); - } - - workerInfo->causeAllFailed(); - }); - } - - void stopWorkerThread() { -#ifdef BRYNET_HAVE_LANG_CXX17 - std::lock_guard lck(mThreadGuard); -#else - std::lock_guard lck(mThreadGuard); -#endif - - if (mThread == nullptr) { - return; - } - - mEventLoop->runAsyncFunctor([this]() { - *mIsRun = false; - }); - - try { - if (mThread->joinable()) { - mThread->join(); - } - } catch (std::system_error &e) { - (void)e; - } - - mEventLoop = nullptr; - mWorkInfo = nullptr; - mIsRun = nullptr; - mThread = nullptr; - } - - void asyncConnect(ConnectOption option) { -#ifdef BRYNET_HAVE_LANG_CXX17 - std::shared_lock lck(mThreadGuard); -#else - std::lock_guard lck(mThreadGuard); -#endif - - if (option.completedCallback == nullptr && option.failedCallback == nullptr) { - throw ConnectException("all callback is nullptr"); - } - if (option.ip.empty()) { - throw ConnectException("addr is empty"); - } - - if (!(*mIsRun)) { - throw ConnectException("work thread already stop"); - } - - auto workInfo = mWorkInfo; - auto address = AsyncConnectAddr(std::move(option.ip), - option.port, - option.timeout, - std::move(option.completedCallback), - std::move(option.failedCallback), - std::move(option.processCallbacks)); - mEventLoop->runAsyncFunctor([workInfo, address]() { - workInfo->processConnect(address); - }); - } - -protected: - AsyncConnectorDetail() { - mIsRun = std::make_shared(false); - } - - virtual ~AsyncConnectorDetail() { - stopWorkerThread(); - } - -private: - std::shared_ptr mEventLoop; - - std::shared_ptr mWorkInfo; - std::shared_ptr mThread; -#ifdef BRYNET_HAVE_LANG_CXX17 - std::shared_mutex mThreadGuard; -#else - std::mutex mThreadGuard; -#endif - std::shared_ptr mIsRun; -}; - diff --git a/libs/brynet/net/detail/ConnectorWorkInfo.hpp b/libs/brynet/net/detail/ConnectorWorkInfo.hpp deleted file mode 100644 index 059e272..0000000 --- a/libs/brynet/net/detail/ConnectorWorkInfo.hpp +++ /dev/null @@ -1,301 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef BRYNET_HAVE_LANG_CXX17 -#include -#else -#include -#endif - -class AsyncConnectAddr final { -public: - using CompletedCallback = std::function; - using ProcessTcpSocketCallback = std::function; - using FailedCallback = std::function; - -public: - AsyncConnectAddr(std::string &&ip, - int port, - std::chrono::nanoseconds timeout, - CompletedCallback &&successCB, - FailedCallback &&failedCB, - std::vector &&processCallbacks) : - mIP(std::move(ip)), - mPort(port), - mTimeout(timeout), - mSuccessCB(std::move(successCB)), - mFailedCB(std::move(failedCB)), - mProcessCallbacks(std::move(processCallbacks)) { - } - - const std::string &getIP() const { - return mIP; - } - - int getPort() const { - return mPort; - } - - const CompletedCallback &getSuccessCB() const { - return mSuccessCB; - } - - const FailedCallback &getFailedCB() const { - return mFailedCB; - } - - const std::vector &getProcessCallbacks() const { - return mProcessCallbacks; - } - - std::chrono::nanoseconds getTimeout() const { - return mTimeout; - } - -private: - const std::string mIP; - const int mPort; - const std::chrono::nanoseconds mTimeout; - const CompletedCallback mSuccessCB; - const FailedCallback mFailedCB; - const std::vector mProcessCallbacks; -}; - -class ConnectorWorkInfo final : public NonCopyable { -public: - using Ptr = std::shared_ptr; - - ConnectorWorkInfo() BRYNET_NOEXCEPT { - mPoller.reset(poller_new()); - mPollResult.reset(stack_new(1024, sizeof(BrynetSocketFD))); - } - - void checkConnectStatus(int millSecond) { - if (poller_poll(mPoller.get(), millSecond) <= 0) { - return; - } - - std::set totalFds; - std::set successFds; - - poller_visitor(mPoller.get(), WriteCheck, mPollResult.get()); - while (true) { - auto p = stack_popfront(mPollResult.get()); - if (p == nullptr) { - break; - } - - const auto fd = *(BrynetSocketFD *)p; - totalFds.insert(fd); - if (isConnectSuccess(fd, false) && - !IsSelfConnect(fd)) { - successFds.insert(fd); - } - } - - for (auto fd : totalFds) { - poller_remove(mPoller.get(), fd); - - const auto it = mConnectingInfos.find(fd); - if (it == mConnectingInfos.end()) { - continue; - } - - auto socket = TcpSocket::Create(fd, false); - const auto &connectingInfo = it->second; - if (successFds.find(fd) != successFds.end()) { - for (const auto &process : connectingInfo.processCallbacks) { - process(*socket); - } - if (connectingInfo.successCB != nullptr) { - connectingInfo.successCB(std::move(socket)); - } - } else { - if (connectingInfo.failedCB != nullptr) { - connectingInfo.failedCB(); - } - } - - mConnectingInfos.erase(it); - } - } - - bool isConnectSuccess(BrynetSocketFD clientfd, bool willCheckWrite) const { - if (willCheckWrite && !poller_check(mPoller.get(), clientfd, WriteCheck)) { - return false; - } - - int error = BRYNET_SOCKET_ERROR; - int len = sizeof(error); - if (getsockopt(clientfd, - SOL_SOCKET, - SO_ERROR, - (char *)&error, - (socklen_t *)&len) == BRYNET_SOCKET_ERROR) { - return false; - } - - return error == 0; - } - - void checkTimeout() { - for (auto it = mConnectingInfos.begin(); it != mConnectingInfos.end();) { - const auto now = std::chrono::steady_clock::now(); - if ((now - it->second.startConnectTime) < it->second.timeout) { - ++it; - continue; - } - - auto fd = it->first; - auto cb = it->second.failedCB; - - poller_remove(mPoller.get(), fd); - mConnectingInfos.erase(it++); - - SocketClose(fd); - if (cb != nullptr) { - //TODO::don't modify mConnectingInfos in cb - cb(); - } - } - } - - void processConnect(const AsyncConnectAddr &addr) { - struct sockaddr_in server_addr = sockaddr_in(); - BrynetSocketFD clientfd = BRYNET_INVALID_SOCKET; - -#ifdef BRYNET_PLATFORM_WINDOWS - const int ExpectedError = WSAEWOULDBLOCK; -#else - const int ExpectedError = EINPROGRESS; -#endif - int n = 0; - - InitSocket(); - - clientfd = SocketCreate(AF_INET, SOCK_STREAM, 0); - if (clientfd == BRYNET_INVALID_SOCKET) { - goto FAILED; - } - - SocketNonblock(clientfd); - server_addr.sin_family = AF_INET; - inet_pton(AF_INET, addr.getIP().c_str(), &server_addr.sin_addr.s_addr); - server_addr.sin_port = static_cast(htons(addr.getPort())); - - n = connect(clientfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)); - if (n == 0) { - if (IsSelfConnect(clientfd)) { - goto FAILED; - } - } else if (BRYNET_ERRNO != ExpectedError) { - goto FAILED; - } else { - ConnectingInfo ci; - ci.startConnectTime = std::chrono::steady_clock::now(); - ci.successCB = addr.getSuccessCB(); - ci.failedCB = addr.getFailedCB(); - ci.timeout = addr.getTimeout(); - ci.processCallbacks = addr.getProcessCallbacks(); - - mConnectingInfos[clientfd] = ci; - poller_add(mPoller.get(), clientfd, WriteCheck); - - return; - } - - if (addr.getSuccessCB() != nullptr) { - auto tcpSocket = TcpSocket::Create(clientfd, false); - for (const auto &process : addr.getProcessCallbacks()) { - process(*tcpSocket); - } - addr.getSuccessCB()(std::move(tcpSocket)); - } - return; - - FAILED: - if (clientfd != BRYNET_INVALID_SOCKET) { - SocketClose(clientfd); - clientfd = BRYNET_INVALID_SOCKET; - (void)clientfd; - } - if (addr.getFailedCB() != nullptr) { - addr.getFailedCB()(); - } - } - - void causeAllFailed() { - auto copyMap = mConnectingInfos; - mConnectingInfos.clear(); - - for (const auto &v : copyMap) { - auto fd = v.first; - auto cb = v.second.failedCB; - - poller_remove(mPoller.get(), fd); - SocketClose(fd); - if (cb != nullptr) { - cb(); - } - } - } - -private: - class ConnectingInfo { - public: - ConnectingInfo() { - timeout = std::chrono::nanoseconds::zero(); - } - - std::chrono::steady_clock::time_point startConnectTime; - std::chrono::nanoseconds timeout; - AsyncConnectAddr::CompletedCallback successCB; - AsyncConnectAddr::FailedCallback failedCB; - std::vector processCallbacks; - }; - - std::map mConnectingInfos; - - class PollerDeleter { - public: - void operator()(struct poller_s *ptr) const { - poller_delete(ptr); - } - }; - class StackDeleter { - public: - void operator()(struct stack_s *ptr) const { - stack_delete(ptr); - } - }; - - std::unique_ptr mPoller; - std::unique_ptr mPollResult; -}; - -static void RunOnceCheckConnect( - const std::shared_ptr &eventLoop, - const std::shared_ptr &workerInfo) { - eventLoop->loop(std::chrono::milliseconds(10).count()); - workerInfo->checkConnectStatus(0); - workerInfo->checkTimeout(); -} - -class ConnectOption final { -public: - std::string ip; - int port = 0; - std::chrono::nanoseconds timeout = std::chrono::seconds(10); - std::vector processCallbacks; - AsyncConnectAddr::CompletedCallback completedCallback; - AsyncConnectAddr::FailedCallback failedCallback; -}; diff --git a/libs/brynet/net/detail/IOLoopData.hpp b/libs/brynet/net/detail/IOLoopData.hpp deleted file mode 100644 index 104ac46..0000000 --- a/libs/brynet/net/detail/IOLoopData.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -class TcpServiceDetail; - -class IOLoopData : public NonCopyable, - public std::enable_shared_from_this { -public: - using Ptr = std::shared_ptr; - - static Ptr Create(EventLoop::Ptr eventLoop, - std::shared_ptr ioThread) { - class make_shared_enabler : public IOLoopData { - public: - make_shared_enabler(EventLoop::Ptr eventLoop, - std::shared_ptr ioThread) : - IOLoopData(std::move(eventLoop), std::move(ioThread)) {} - }; - - return std::make_shared(std::move(eventLoop), - std::move(ioThread)); - } - - const EventLoop::Ptr &getEventLoop() const { - return mEventLoop; - } - -protected: - const std::shared_ptr &getIOThread() const { - return mIOThread; - } - - IOLoopData(EventLoop::Ptr eventLoop, - std::shared_ptr ioThread) : - mEventLoop(std::move(eventLoop)), - mIOThread(std::move(ioThread)) {} - virtual ~IOLoopData() = default; - - const EventLoop::Ptr mEventLoop; - -private: - std::shared_ptr mIOThread; - - friend class TcpServiceDetail; -}; - -using IOLoopDataPtr = std::shared_ptr; diff --git a/libs/brynet/net/detail/ListenThreadDetail.hpp b/libs/brynet/net/detail/ListenThreadDetail.hpp deleted file mode 100644 index 80ecdf9..0000000 --- a/libs/brynet/net/detail/ListenThreadDetail.hpp +++ /dev/null @@ -1,140 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class ListenThreadDetail : public NonCopyable { -protected: - using AccepCallback = std::function; - using TcpSocketProcessCallback = std::function; - - void startListen() { - std::lock_guard lck(mListenThreadGuard); - - if (mListenThread != nullptr) { - return; - } - - const auto fd = Listen(mIsIPV6, mIP.c_str(), mPort, 512, mEnabledReusePort); - if (fd == BRYNET_INVALID_SOCKET) { - throw BrynetCommonException( - std::string("listen error of:") + std::to_string(BRYNET_ERRNO)); - } - - mRunListen = std::make_shared(true); - - auto listenSocket = std::shared_ptr(ListenSocket::Create(fd)); - auto isRunListen = mRunListen; - auto callback = mCallback; - auto processCallbacks = mProcessCallbacks; - mListenThread = std::make_shared( - [isRunListen, listenSocket, callback, processCallbacks]() mutable { - while (*isRunListen) { - auto clientSocket = runOnceListen(listenSocket); - if (clientSocket == nullptr) { - continue; - } - - if (*isRunListen) { - for (const auto &process : processCallbacks) { - process(*clientSocket); - } - callback(std::move(clientSocket)); - } - } - }); - } - - void stopListen() { - std::lock_guard lck(mListenThreadGuard); - - if (mListenThread == nullptr) { - return; - } - - *mRunListen = false; - auto selfIP = mIP; - if (selfIP == "0.0.0.0") { - selfIP = "127.0.0.1"; - } - - auto connector = AsyncConnector::Create(); - connector->startWorkerThread(); - - //TODO:: if the listen enable reuse_port, one time connect may be can't wakeup listen. - SocketConnectBuilder connectBuilder; - (void)connectBuilder - .WithConnector(connector) - .WithTimeout(std::chrono::seconds(2)) - .WithAddr(selfIP, mPort) - .syncConnect(); - - try { - if (mListenThread->joinable()) { - mListenThread->join(); - } - } catch (std::system_error &e) { - (void)e; - } - mListenThread = nullptr; - } - -protected: - ListenThreadDetail(bool isIPV6, - const std::string &ip, - int port, - const AccepCallback &callback, - const std::vector &processCallbacks, - bool enabledReusePort) : - mIsIPV6(isIPV6), - mIP(ip), - mPort(port), - mCallback(callback), - mProcessCallbacks(processCallbacks), - mEnabledReusePort(enabledReusePort) { - if (mCallback == nullptr) { - throw BrynetCommonException("accept callback is nullptr"); - } - mRunListen = std::make_shared(false); - } - - virtual ~ListenThreadDetail() BRYNET_NOEXCEPT { - stopListen(); - } - -private: - static TcpSocket::Ptr runOnceListen(const std::shared_ptr &listenSocket) { - try { - return listenSocket->accept(); - } catch (const EintrError &e) { - std::cerr << "accept eintr execption:" << e.what() << std::endl; - } catch (const AcceptError &e) { - std::cerr << "accept execption:" << e.what() << std::endl; - } - - return nullptr; - } - -private: - const bool mIsIPV6; - const std::string mIP; - const int mPort; - const AccepCallback mCallback; - const std::vector mProcessCallbacks; - const bool mEnabledReusePort; - - std::shared_ptr mRunListen; - std::shared_ptr mListenThread; - std::mutex mListenThreadGuard; -}; diff --git a/libs/brynet/net/detail/TCPServiceDetail.hpp b/libs/brynet/net/detail/TCPServiceDetail.hpp deleted file mode 100644 index a8ee7bb..0000000 --- a/libs/brynet/net/detail/TCPServiceDetail.hpp +++ /dev/null @@ -1,142 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class TcpServiceDetail : public NonCopyable { -protected: - using FrameCallback = std::function; - const static unsigned int sDefaultLoopTimeOutMS = 100; - - void startWorkerThread(size_t threadNum, - FrameCallback callback = nullptr) { - std::lock_guard lck(mServiceGuard); - std::lock_guard lock(mIOLoopGuard); - - if (!mIOLoopDatas.empty()) { - return; - } - - mRunIOLoop = std::make_shared(true); - - mIOLoopDatas.resize(threadNum); - for (auto &v : mIOLoopDatas) { - auto eventLoop = std::make_shared(); - auto runIoLoop = mRunIOLoop; - v = IOLoopData::Create(eventLoop, - std::make_shared( - [callback, runIoLoop, eventLoop]() { - while (*runIoLoop) { - eventLoop->loopCompareNearTimer(sDefaultLoopTimeOutMS); - if (callback != nullptr) { - callback(eventLoop); - } - } - })); - } - } - - void stopWorkerThread() { - std::lock_guard lck(mServiceGuard); - std::lock_guard lock(mIOLoopGuard); - - *mRunIOLoop = false; - - for (const auto &v : mIOLoopDatas) { - v->getEventLoop()->wakeup(); - try { - if (v->getIOThread()->joinable()) { - v->getIOThread()->join(); - } - } catch (std::system_error &e) { - (void)e; - } - } - mIOLoopDatas.clear(); - } - - bool addTcpConnection(TcpSocket::Ptr socket, ConnectionOption option) { - if (option.maxRecvBufferSize <= 0) { - throw BrynetCommonException("buffer size is zero"); - } - - EventLoop::Ptr eventLoop; - if (option.forceSameThreadLoop) { - eventLoop = getSameThreadEventLoop(); - } else { - eventLoop = getRandomEventLoop(); - } - if (eventLoop == nullptr) { - return false; - } - - auto wrapperEnterCallback = [option](const TcpConnection::Ptr &tcpConnection) { - for (const auto &callback : option.enterCallback) { - callback(tcpConnection); - } - }; - - if (option.useSSL && option.sslHelper == nullptr) { - option.sslHelper = SSLHelper::Create(); - } - - TcpConnection::Create(std::move(socket), - option.maxRecvBufferSize, - wrapperEnterCallback, - eventLoop, - option.sslHelper); - - return true; - } - - EventLoop::Ptr getRandomEventLoop() { - std::lock_guard lock(mIOLoopGuard); - - const auto ioLoopSize = mIOLoopDatas.size(); - if (ioLoopSize == 0) { - return nullptr; - } else if (ioLoopSize == 1) { - return mIOLoopDatas.front()->getEventLoop(); - } else { - return mIOLoopDatas[mRandom() % ioLoopSize]->getEventLoop(); - } - } - - TcpServiceDetail() BRYNET_NOEXCEPT - : mRandom(static_cast( - std::chrono::system_clock::now().time_since_epoch().count())) { - mRunIOLoop = std::make_shared(false); - } - - virtual ~TcpServiceDetail() BRYNET_NOEXCEPT { - stopWorkerThread(); - } - - EventLoop::Ptr getSameThreadEventLoop() { - std::lock_guard lock(mIOLoopGuard); - for (const auto &v : mIOLoopDatas) { - if (v->getEventLoop()->isInLoopThread()) { - return v->getEventLoop(); - } - } - return nullptr; - } - -private: - std::vector mIOLoopDatas; - mutable std::mutex mIOLoopGuard; - std::shared_ptr mRunIOLoop; - - std::mutex mServiceGuard; - std::mt19937 mRandom; -}; diff --git a/libs/brynet/net/detail/WakeupChannel.hpp b/libs/brynet/net/detail/WakeupChannel.hpp deleted file mode 100644 index 00ec1c7..0000000 --- a/libs/brynet/net/detail/WakeupChannel.hpp +++ /dev/null @@ -1,106 +0,0 @@ -#pragma once - -#include -#ifdef BRYNET_PLATFORM_WINDOWS -#include -#endif - -#include -#include - -#ifdef BRYNET_PLATFORM_WINDOWS -class WakeupChannel final : public Channel, public NonCopyable { -public: - explicit WakeupChannel(HANDLE iocp) : - mIOCP(iocp), - mWakeupOvl(port::Win::OverlappedType::OverlappedRecv) { - } - - bool wakeup() BRYNET_NOEXCEPT { - return PostQueuedCompletionStatus(mIOCP, - 0, - reinterpret_cast(this), - &mWakeupOvl.base); - } - -private: - void canRecv(bool) BRYNET_NOEXCEPT override { - ; - } - - void canSend() BRYNET_NOEXCEPT override { - ; - } - - void onClose() BRYNET_NOEXCEPT override { - ; - } - - HANDLE mIOCP; - port::Win::OverlappedExt mWakeupOvl; -}; -#elif defined BRYNET_PLATFORM_LINUX -class WakeupChannel final : public Channel, public NonCopyable { -public: - explicit WakeupChannel(BrynetSocketFD fd) : - mUniqueFd(fd) { - } - - bool wakeup() { - uint64_t one = 1; - return write(mUniqueFd.getFD(), &one, sizeof one) > 0; - } - -private: - void canRecv(bool) override { - char temp[1024 * 10]; - while (true) { - auto n = read(mUniqueFd.getFD(), temp, sizeof(temp)); - if (n == -1 || static_cast(n) < sizeof(temp)) { - break; - } - } - } - - void canSend() override { - } - - void onClose() override { - } - -private: - UniqueFd mUniqueFd; -}; - -#elif defined BRYNET_PLATFORM_DARWIN -class WakeupChannel final : public Channel, public NonCopyable { -public: - explicit WakeupChannel(int kqueuefd, int ident) : - mKqueueFd(kqueuefd), - mUserEvent(ident) { - } - - bool wakeup() { - struct kevent ev; - EV_SET(&ev, mUserEvent, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); - - struct timespec timeout = { 0, 0 }; - return kevent(mKqueueFd, &ev, 1, NULL, 0, &timeout) == 0; - } - -private: - void canRecv(bool) override { - } - - void canSend() override { - } - - void onClose() override { - } - -private: - int mKqueueFd; - int mUserEvent; -}; -#endif - diff --git a/libs/brynet/net/http/HttpFormat.hpp b/libs/brynet/net/http/HttpFormat.hpp deleted file mode 100644 index bd360cb..0000000 --- a/libs/brynet/net/http/HttpFormat.hpp +++ /dev/null @@ -1,196 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -class HttpQueryParameter final { -public: - void add(const std::string &k, const std::string &v) { - if (!mParameter.empty()) { - mParameter += "&"; - } - - mParameter += k; - mParameter += "="; - mParameter += v; - } - - const std::string &getResult() const { - return mParameter; - } - -private: - std::string mParameter; -}; - -class HttpRequest final { -public: - enum class HTTP_METHOD { - HTTP_METHOD_HEAD, - HTTP_METHOD_GET, - HTTP_METHOD_POST, - HTTP_METHOD_PUT, - HTTP_METHOD_DELETE, - HTTP_METHOD_MAX - }; - - HttpRequest() { - setMethod(HTTP_METHOD::HTTP_METHOD_GET); - } - - void setMethod(HTTP_METHOD protocol) { - mMethod = protocol; - assert(mMethod > HTTP_METHOD::HTTP_METHOD_HEAD && - mMethod < HTTP_METHOD::HTTP_METHOD_MAX); - } - - void setHost(const std::string &host) { - addHeadValue("Host", host); - } - - void setUrl(const std::string &url) { - mUrl = url; - } - - void setCookie(const std::string &v) { - addHeadValue("Cookie", v); - } - - void setContentType(const std::string &v) { - addHeadValue("Content-Type", v); - } - - void setQuery(const std::string &query) { - mQuery = query; - } - - void setBody(const std::string &body) { - addHeadValue("Content-Length", std::to_string(body.size())); - mBody = body; - } - - void setBody(std::string &&body) { - addHeadValue("Content-Length", std::to_string(body.size())); - mBody = std::move(body); - } - - void addHeadValue(const std::string &field, - const std::string &value) { - mHeadField[field] = value; - } - - std::string getResult() const { - const auto MethodMax = static_cast(HTTP_METHOD::HTTP_METHOD_MAX); - const static std::array HttpMethodString = { "HEAD", "GET", "POST", "PUT", "DELETE" }; - - std::string ret; - if (mMethod >= HTTP_METHOD::HTTP_METHOD_HEAD && - mMethod < HTTP_METHOD::HTTP_METHOD_MAX) { - ret += HttpMethodString[static_cast(mMethod)]; - } - - ret += " "; - ret += mUrl; - if (!mQuery.empty()) { - ret += "?"; - ret += mQuery; - } - - ret += " HTTP/1.1\r\n"; - - for (auto &v : mHeadField) { - ret += v.first; - ret += ": "; - ret += v.second; - ret += "\r\n"; - } - - ret += "\r\n"; - - if (!mBody.empty()) { - ret += mBody; - } - - return ret; - } - -private: - std::string mUrl; - std::string mQuery; - std::string mBody; - HTTP_METHOD mMethod; - std::map mHeadField; -}; - -class HttpResponse final { -public: - enum class HTTP_RESPONSE_STATUS { - NONE, - OK = 200, - }; - - HttpResponse() : - mStatus(HTTP_RESPONSE_STATUS::OK) { - } - - void setStatus(HTTP_RESPONSE_STATUS status) { - mStatus = status; - } - - void setContentType(const std::string &v) { - addHeadValue("Content-Type", v); - } - - void addHeadValue(const std::string &field, - const std::string &value) { - mHeadField[field] = value; - } - - void setBody(const std::string &body) { - addHeadValue("Content-Length", std::to_string(body.size())); - mBody = body; - } - - void setBody(std::string &&body) { - addHeadValue("Content-Length", std::to_string(body.size())); - mBody = std::move(body); - } - - std::string getResult() const { - std::string ret = "HTTP/1.1 "; - - ret += std::to_string(static_cast(mStatus)); - switch (mStatus) { - case HTTP_RESPONSE_STATUS::OK: - ret += " OK"; - break; - default: - ret += "UNKNOWN"; - break; - } - - ret += "\r\n"; - - for (auto &v : mHeadField) { - ret += v.first; - ret += ": "; - ret += v.second; - ret += "\r\n"; - } - - ret += "\r\n"; - - if (!mBody.empty()) { - ret += mBody; - } - - return ret; - } - -private: - HTTP_RESPONSE_STATUS mStatus; - std::map mHeadField; - std::string mBody; -}; diff --git a/libs/brynet/net/http/HttpParser.hpp b/libs/brynet/net/http/HttpParser.hpp deleted file mode 100644 index 39e21f8..0000000 --- a/libs/brynet/net/http/HttpParser.hpp +++ /dev/null @@ -1,282 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -#include "http_parser.h" - -class HttpService; - -class HTTPParser { -public: - using Ptr = std::shared_ptr; - - explicit HTTPParser(http_parser_type parserType) : - mParserType(parserType) { - mLastWasValue = true; - - mIsUpgrade = false; - mIsWebSocket = false; - mIsKeepAlive = false; - mISCompleted = false; - mStatusCode = 0; - mWSFrameType = WebSocketFormat::WebSocketFrameType::ERROR_FRAME; - mSettings.on_status = sStatusHandle; - mSettings.on_body = sBodyHandle; - mSettings.on_url = sUrlHandle; - mSettings.on_header_field = sHeadField; - mSettings.on_header_value = sHeadValue; - mSettings.on_headers_complete = sHeadComplete; - mSettings.on_message_begin = sMessageBegin; - mSettings.on_message_complete = sMessageEnd; - mSettings.on_chunk_header = sChunkHeader; - mSettings.on_chunk_complete = sChunkComplete; - mParser.data = this; - - http_parser_init(&mParser, mParserType); - } - - virtual ~HTTPParser() = default; - - bool isUpgrade() const { - return mIsUpgrade; - } - - bool isWebSocket() const { - return mIsWebSocket; - } - - bool isKeepAlive() const { - return mIsKeepAlive; - } - - bool isCompleted() const { - return mISCompleted; - } - - int method() const { - // mMethod's value defined in http_method, such as HTTP_GET、HTTP_POST. - // if mMethod is -1, it's invalid. - return mMethod; - } - - const std::string &getPath() const { - return mPath; - } - - const std::string &getQuery() const { - return mQuery; - } - - const std::string &getStatus() const { - return mStatus; - } - - int getStatusCode() const { - return mStatusCode; - } - - bool hasEntry(const std::string &key, - const std::string &value) const { - const auto it = mHeadValues.find(key); - return it != mHeadValues.end() && value == it->second; - } - - bool hasKey(const std::string &key) const { - return mHeadValues.find(key) != mHeadValues.end(); - } - - const std::string &getValue(const std::string &key) const { - const static std::string emptystr(""); - - auto it = mHeadValues.find(key); - if (it != mHeadValues.end()) { - return (*it).second; - } else { - return emptystr; - } - } - - const std::string &getBody() const { - return mBody; - } - - std::string &getWSCacheFrame() { - return mWSCacheFrame; - } - - std::string &getWSParseString() { - return mWSParsePayload; - } - - WebSocketFormat::WebSocketFrameType getWSFrameType() const { - return mWSFrameType; - } - - void cacheWSFrameType(WebSocketFormat::WebSocketFrameType frameType) { - mWSFrameType = frameType; - } - -private: - void clearParse() { - mMethod = -1; - mIsUpgrade = false; - mIsWebSocket = false; - mISCompleted = false; - mLastWasValue = true; - mUrl.clear(); - mQuery.clear(); - mBody.clear(); - mStatus.clear(); - mCurrentField.clear(); - mCurrentValue.clear(); - mHeadValues.clear(); - mPath.clear(); - } - - size_t tryParse(const char *buffer, size_t len) { - const size_t nparsed = http_parser_execute(&mParser, &mSettings, buffer, len); - if (mISCompleted) { - mIsUpgrade = mParser.upgrade; - mIsWebSocket = mIsUpgrade && hasEntry("Upgrade", "websocket"); - mIsKeepAlive = hasEntry("Connection", "Keep-Alive"); - mMethod = mParser.method; - http_parser_init(&mParser, mParserType); - } - - return nparsed; - } - -private: - static int sChunkHeader(http_parser *hp) { - (void)hp; - return 0; - } - - static int sChunkComplete(http_parser *hp) { - (void)hp; - return 0; - } - - static int sMessageBegin(http_parser *hp) { - HTTPParser *httpParser = (HTTPParser *)hp->data; - httpParser->clearParse(); - - return 0; - } - - static int sMessageEnd(http_parser *hp) { - HTTPParser *httpParser = (HTTPParser *)hp->data; - httpParser->mISCompleted = true; - return 0; - } - - static int sHeadComplete(http_parser *hp) { - HTTPParser *httpParser = (HTTPParser *)hp->data; - - if (httpParser->mUrl.empty()) { - return 0; - } - - struct http_parser_url u; - - const int result = http_parser_parse_url(httpParser->mUrl.data(), - httpParser->mUrl.size(), - 0, - &u); - if (result != 0) { - return -1; - } - - if (!(u.field_set & (1 << UF_PATH))) { - fprintf(stderr, - "\n\n*** failed to parse PATH in URL %s ***\n\n", - httpParser->mUrl.c_str()); - return -1; - } - - httpParser->mPath = std::string( - httpParser->mUrl.data() + u.field_data[UF_PATH].off, - u.field_data[UF_PATH].len); - if (u.field_set & (1 << UF_QUERY)) { - httpParser->mQuery = std::string( - httpParser->mUrl.data() + u.field_data[UF_QUERY].off, - u.field_data[UF_QUERY].len); - } - - return 0; - } - - static int sUrlHandle(http_parser *hp, const char *url, size_t length) { - HTTPParser *httpParser = (HTTPParser *)hp->data; - httpParser->mUrl.append(url, length); - - return 0; - } - - static int sHeadValue(http_parser *hp, const char *at, size_t length) { - HTTPParser *httpParser = (HTTPParser *)hp->data; - auto &value = httpParser->mHeadValues[httpParser->mCurrentField]; - value.append(at, length); - httpParser->mLastWasValue = true; - return 0; - } - - static int sHeadField(http_parser *hp, const char *at, size_t length) { - HTTPParser *httpParser = (HTTPParser *)hp->data; - if (httpParser->mLastWasValue) { - httpParser->mCurrentField.clear(); - } - httpParser->mCurrentField.append(at, length); - httpParser->mLastWasValue = false; - - return 0; - } - - static int sStatusHandle(http_parser *hp, const char *at, size_t length) { - HTTPParser *httpParser = (HTTPParser *)hp->data; - httpParser->mStatus.append(at, length); - httpParser->mStatusCode = hp->status_code; - return 0; - } - - static int sBodyHandle(http_parser *hp, const char *at, size_t length) { - HTTPParser *httpParser = (HTTPParser *)hp->data; - httpParser->mBody.append(at, length); - return 0; - } - -private: - const http_parser_type mParserType; - http_parser mParser; - http_parser_settings mSettings; - - int mMethod = -1; - bool mIsUpgrade = false; - bool mIsWebSocket = false; - bool mIsKeepAlive; - bool mISCompleted; - - bool mLastWasValue; - std::string mCurrentField; - std::string mCurrentValue; - - std::string mPath; - std::string mQuery; - std::string mStatus; - std::map mHeadValues; - int mStatusCode; - - std::string mUrl; - std::string mBody; - - std::string mWSCacheFrame; - std::string mWSParsePayload; - WebSocketFormat::WebSocketFrameType mWSFrameType; - -private: - friend class HttpService; -}; diff --git a/libs/brynet/net/http/HttpService.hpp b/libs/brynet/net/http/HttpService.hpp deleted file mode 100644 index 08cdd7c..0000000 --- a/libs/brynet/net/http/HttpService.hpp +++ /dev/null @@ -1,299 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -class HttpService; -class HttpSessionHandlers; - -class HttpSession : public NonCopyable { -public: - using Ptr = std::shared_ptr; - - using EnterCallback = std::function; - using HttpParserCallback = std::function; - using WsCallback = std::function; - - using ClosedCallback = std::function; - using WsConnectedCallback = std::function; - -public: - template - void send(PacketType &&packet, - TcpConnection::PacketSendedCallback &&callback = nullptr) { - mSession->send(std::forward(packet), - std::move(callback)); - } - void send(const char *packet, - size_t len, - TcpConnection::PacketSendedCallback &&callback = nullptr) { - mSession->send(packet, len, std::move(callback)); - } - - void postShutdown() const { - mSession->postShutdown(); - } - - void postClose() const { - mSession->postDisConnect(); - } - -protected: - explicit HttpSession(TcpConnection::Ptr session) { - mSession = std::move(session); - } - - virtual ~HttpSession() = default; - - static Ptr Create(TcpConnection::Ptr session) { - class make_shared_enabler : public HttpSession { - public: - explicit make_shared_enabler(TcpConnection::Ptr session) : - HttpSession(std::move(session)) {} - }; - return std::make_shared(std::move(session)); - } - - const TcpConnection::Ptr &getSession() const { - return mSession; - } - - const HttpParserCallback &getHttpCallback() const { - return mHttpRequestCallback; - } - - const ClosedCallback &getCloseCallback() const { - return mCloseCallback; - } - - const WsCallback &getWSCallback() const { - return mWSCallback; - } - - const WsConnectedCallback &getWSConnectedCallback() const { - return mWSConnectedCallback; - } - -private: - void setHttpCallback(HttpParserCallback &&callback) { - mHttpRequestCallback = std::move(callback); - } - - void setClosedCallback(ClosedCallback &&callback) { - mCloseCallback = std::move(callback); - } - - void setWSCallback(WsCallback &&callback) { - mWSCallback = std::move(callback); - } - - void setWSConnected(WsConnectedCallback &&callback) { - mWSConnectedCallback = std::move(callback); - } - -private: - TcpConnection::Ptr mSession; - HttpParserCallback mHttpRequestCallback; - WsCallback mWSCallback; - ClosedCallback mCloseCallback; - WsConnectedCallback mWSConnectedCallback; - - friend class HttpService; -}; - -class HttpSessionHandlers { -public: - void setHttpCallback(HttpSession::HttpParserCallback &&callback) { - mHttpRequestCallback = std::move(callback); - } - - void setClosedCallback(HttpSession::ClosedCallback &&callback) { - mCloseCallback = std::move(callback); - } - - void setWSCallback(HttpSession::WsCallback &&callback) { - mWSCallback = std::move(callback); - } - - void setWSConnected(HttpSession::WsConnectedCallback &&callback) { - mWSConnectedCallback = std::move(callback); - } - -private: - HttpSession::HttpParserCallback mHttpRequestCallback; - HttpSession::WsCallback mWSCallback; - HttpSession::ClosedCallback mCloseCallback; - HttpSession::WsConnectedCallback mWSConnectedCallback; - - friend class HttpService; -}; - -class HttpService { -public: - static void setup(const TcpConnection::Ptr &session, - const HttpSession::EnterCallback &enterCallback) { - auto httpSession = HttpSession::Create(session); - if (enterCallback != nullptr) { - HttpSessionHandlers handlers; - enterCallback(httpSession, handlers); - httpSession->setHttpCallback(std::move(handlers.mHttpRequestCallback)); - httpSession->setClosedCallback(std::move(handlers.mCloseCallback)); - httpSession->setWSCallback(std::move(handlers.mWSCallback)); - httpSession->setWSConnected(std::move(handlers.mWSConnectedCallback)); - } - HttpService::handle(httpSession); - } - -private: - static void handle(const HttpSession::Ptr &httpSession) { - /*TODO::keep alive and timeout close */ - auto &session = httpSession->getSession(); - auto httpParser = std::make_shared(HTTP_BOTH); - - session->setDisConnectCallback([httpSession, httpParser](const TcpConnection::Ptr &) { - if (!httpParser->isCompleted()) { - // try pass EOF to http parser - HttpService::ProcessHttp(nullptr, 0, httpParser, httpSession); - } - - const auto &tmp = httpSession->getCloseCallback(); - if (tmp != nullptr) { - tmp(httpSession); - } - }); - - session->setDataCallback([httpSession, httpParser]( - BasePacketReader &reader) { - size_t retLen = 0; - - if (httpParser->isWebSocket()) { - retLen = HttpService::ProcessWebSocket(reader.begin(), - reader.size(), - httpParser, - httpSession); - } else if (httpParser->isUpgrade()) { - // TODO::not support other upgrade protocol - } else { - retLen = HttpService::ProcessHttp(reader.begin(), - reader.size(), - httpParser, - httpSession); - // if http_parser_execute not consume all data that indicate cause error in parser. - // so we need close connection. - if (retLen != reader.size()) { - httpSession->postClose(); - } - } - - reader.addPos(retLen); - reader.savePos(); - }); - } - - static size_t ProcessWebSocket(const char *buffer, - size_t len, - const HTTPParser::Ptr &httpParser, - const HttpSession::Ptr &httpSession) { - size_t leftLen = len; - - const auto &wsCallback = httpSession->getWSCallback(); - auto &cacheFrame = httpParser->getWSCacheFrame(); - auto &parseString = httpParser->getWSParseString(); - - while (leftLen > 0) { - parseString.clear(); - - auto opcode = WebSocketFormat::WebSocketFrameType::ERROR_FRAME; - size_t frameSize = 0; - bool isFin = false; - - if (!WebSocketFormat::wsFrameExtractBuffer(buffer, - leftLen, - parseString, - opcode, - frameSize, - isFin)) { - // 如果没有解析出完整的ws frame则退出函数 - break; - } - - // 如果当前fram的fin为false或者opcode为延续包 - // 则将当前frame的payload添加到cache - if (!isFin || - opcode == WebSocketFormat::WebSocketFrameType::CONTINUATION_FRAME) { - cacheFrame += parseString; - parseString.clear(); - } - // 如果当前fram的fin为false,并且opcode不为延续包 - // 则表示收到分段payload的第一个段(frame),需要缓存当前frame的opcode - if (!isFin && - opcode != WebSocketFormat::WebSocketFrameType::CONTINUATION_FRAME) { - httpParser->cacheWSFrameType(opcode); - } - - leftLen -= frameSize; - buffer += frameSize; - - if (!isFin) { - continue; - } - - // 如果fin为true,并且opcode为延续包 - // 则表示分段payload全部接受完毕 - // 因此需要获取之前第一次收到分段frame的opcode作为整个payload的类型 - if (opcode == WebSocketFormat::WebSocketFrameType::CONTINUATION_FRAME) { - if (!cacheFrame.empty()) { - parseString = std::move(cacheFrame); - cacheFrame.clear(); - } - opcode = httpParser->getWSFrameType(); - } - - if (wsCallback != nullptr) { - wsCallback(httpSession, opcode, parseString); - } - } - - return (len - leftLen); - } - - static size_t ProcessHttp(const char *buffer, - size_t len, - const HTTPParser::Ptr &httpParser, - const HttpSession::Ptr &httpSession) { - size_t retlen = len; - if (!httpParser->isCompleted()) { - retlen = httpParser->tryParse(buffer, len); - if (!httpParser->isCompleted()) { - return retlen; - } - } - - if (httpParser->isWebSocket()) { - if (httpParser->hasKey("Sec-WebSocket-Key")) { - auto response = WebSocketFormat::wsHandshake( - httpParser->getValue("Sec-WebSocket-Key")); - httpSession->send(response.c_str(), - response.size()); - } - - const auto &wsConnectedCallback = httpSession->getWSConnectedCallback(); - if (wsConnectedCallback != nullptr) { - wsConnectedCallback(httpSession, *httpParser); - } - } else { - const auto &httpCallback = httpSession->getHttpCallback(); - if (httpCallback != nullptr) { - httpCallback(*httpParser, httpSession); - } - } - - return retlen; - } -}; - diff --git a/libs/brynet/net/http/WebSocketFormat.hpp b/libs/brynet/net/http/WebSocketFormat.hpp deleted file mode 100644 index 0994f8b..0000000 --- a/libs/brynet/net/http/WebSocketFormat.hpp +++ /dev/null @@ -1,204 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include -#include - -class WebSocketFormat { -public: - enum class WebSocketFrameType { - ERROR_FRAME = 0xff, - CONTINUATION_FRAME = 0x00, - TEXT_FRAME = 0x01, - BINARY_FRAME = 0x02, - CLOSE_FRAME = 0x08, - PING_FRAME = 0x09, - PONG_FRAME = 0x0A - }; - - static std::string wsHandshake(std::string secKey) { - secKey.append("258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); - - CSHA1 s1; - s1.Update((unsigned char *)secKey.c_str(), static_cast(secKey.size())); - s1.Final(); - unsigned char puDest[20]; - s1.GetHash(puDest); - - std::string base64Str = base64_encode((const unsigned char *)puDest, 20); - - std::string response = - "HTTP/1.1 101 Switching Protocols\r\n" - "Upgrade: websocket\r\n" - "Connection: Upgrade\r\n" - "Sec-WebSocket-Accept: "; - - response += base64Str; - response += "\r\n\r\n"; - - return response; - } - - static bool wsFrameBuild(const char *payload, - size_t payloadLen, - std::string &frame, - WebSocketFrameType frame_type = WebSocketFrameType::TEXT_FRAME, - bool isFin = true, - bool masking = false) { - const auto unixTime = std::chrono::system_clock::now().time_since_epoch().count(); - static std::mt19937 random(static_cast(unixTime)); - - static_assert(std::is_same::value, ""); - - const uint8_t head = static_cast(frame_type) | (isFin ? 0x80 : 0x00); - - frame.clear(); - frame.push_back(static_cast(head)); - if (payloadLen <= 125) { - // mask << 7 | payloadLen, mask = 0 - frame.push_back(static_cast(payloadLen)); - } else if (payloadLen <= 0xFFFF) { - // 126 + 16bit len - frame.push_back(126); - frame.push_back((payloadLen & 0xFF00) >> 8); - frame.push_back(payloadLen & 0x00FF); - } else { - // 127 + 64bit len - frame.push_back(127); - // assume payload len is less than u_int32_max - frame.push_back(0x00); - frame.push_back(0x00); - frame.push_back(0x00); - frame.push_back(0x00); - frame.push_back(static_cast((payloadLen & 0xFF000000) >> 24)); - frame.push_back(static_cast((payloadLen & 0x00FF0000) >> 16)); - frame.push_back(static_cast((payloadLen & 0x0000FF00) >> 8)); - frame.push_back(static_cast(payloadLen & 0x000000FF)); - } - - if (masking) { - frame[1] = ((uint8_t)frame[1]) | 0x80; - uint8_t mask[4]; - for (auto &m : mask) { - m = static_cast(random()); - frame.push_back(m); - } - - frame.reserve(frame.size() + payloadLen); - - for (size_t i = 0; i < payloadLen; i++) { - frame.push_back(static_cast(payload[i]) ^ mask[i % 4]); - } - } else { - frame.append(payload, payloadLen); - } - - return true; - } - - static bool wsFrameBuild(const std::string &payload, - std::string &frame, - WebSocketFrameType frame_type = WebSocketFrameType::TEXT_FRAME, - bool isFin = true, - bool masking = false) { - return wsFrameBuild(payload.c_str(), - payload.size(), - frame, - frame_type, - isFin, - masking); - } - - static bool wsFrameExtractBuffer(const char *inbuffer, - const size_t bufferSize, - std::string &payload, - WebSocketFrameType &outopcode, - size_t &frameSize, - bool &outfin) { - const auto buffer = (const unsigned char *)inbuffer; - - if (bufferSize < 2) { - return false; - } - - outfin = (buffer[0] & 0x80) != 0; - outopcode = (WebSocketFrameType)(buffer[0] & 0x0F); - const bool isMasking = (buffer[1] & 0x80) != 0; - uint32_t payloadlen = buffer[1] & 0x7F; - - uint32_t pos = 2; - if (payloadlen == 126) { - if (bufferSize < 4) { - return false; - } - - payloadlen = (buffer[2] << 8) + buffer[3]; - pos = 4; - } else if (payloadlen == 127) { - if (bufferSize < 10) { - return false; - } - - if (buffer[2] != 0 || - buffer[3] != 0 || - buffer[4] != 0 || - buffer[5] != 0) { - return false; - } - - if ((buffer[6] & 0x80) != 0) { - return false; - } - - payloadlen = (buffer[6] << 24) + - (buffer[7] << 16) + - (buffer[8] << 8) + - buffer[9]; - pos = 10; - } - - uint8_t mask[4]; - if (isMasking) { - if (bufferSize < (pos + 4)) { - return false; - } - - mask[0] = buffer[pos++]; - mask[1] = buffer[pos++]; - mask[2] = buffer[pos++]; - mask[3] = buffer[pos++]; - } - - if (bufferSize < (pos + payloadlen)) { - return false; - } - - if (isMasking) { - payload.reserve(payloadlen); - for (size_t j = 0; j < payloadlen; j++) - payload.push_back(buffer[pos + j] ^ mask[j % 4]); - } else { - payload.append((const char *)(buffer + pos), payloadlen); - } - - frameSize = payloadlen + pos; - - return true; - } - - static bool wsFrameExtractString(const std::string &buffer, - std::string &payload, - WebSocketFrameType &opcode, - size_t &frameSize, bool &isFin) { - return wsFrameExtractBuffer(buffer.c_str(), - buffer.size(), - payload, - opcode, - frameSize, - isFin); - } -}; diff --git a/libs/brynet/net/http/http_parser.h b/libs/brynet/net/http/http_parser.h deleted file mode 100644 index 62f7866..0000000 --- a/libs/brynet/net/http/http_parser.h +++ /dev/null @@ -1,3218 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ -#ifndef http_parser_h -#define http_parser_h - -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* Also update SONAME in the Makefile whenever you change these. */ -#define HTTP_PARSER_VERSION_MAJOR 2 -#define HTTP_PARSER_VERSION_MINOR 9 -#define HTTP_PARSER_VERSION_PATCH 2 - -#include -#if defined(_WIN32) && !defined(__MINGW32__) && \ - (!defined(_MSC_VER) || _MSC_VER < 1600) && !defined(__WINE__) -#include -typedef __int8 int8_t; -typedef unsigned __int8 uint8_t; -typedef __int16 int16_t; -typedef unsigned __int16 uint16_t; -typedef __int32 int32_t; -typedef unsigned __int32 uint32_t; -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; -#else -#include -#endif - -/* Compile with -DHTTP_PARSER_STRICT=0 to make less checks, but run - * faster - */ -#ifndef HTTP_PARSER_STRICT -#define HTTP_PARSER_STRICT 1 -#endif - -/* Maximium header size allowed. If the macro is not defined - * before including this header then the default is used. To - * change the maximum header size, define the macro in the build - * environment (e.g. -DHTTP_MAX_HEADER_SIZE=). To remove - * the effective limit on the size of the header, define the macro - * to a very large number (e.g. -DHTTP_MAX_HEADER_SIZE=0x7fffffff) - */ -#ifndef HTTP_MAX_HEADER_SIZE -#define HTTP_MAX_HEADER_SIZE (80 * 1024) -#endif - -typedef struct http_parser http_parser; -typedef struct http_parser_settings http_parser_settings; - - -/* Callbacks should return non-zero to indicate an error. The parser will - * then halt execution. - * - * The one exception is on_headers_complete. In a HTTP_RESPONSE parser - * returning '1' from on_headers_complete will tell the parser that it - * should not expect a body. This is used when receiving a response to a - * HEAD request which may contain 'Content-Length' or 'Transfer-Encoding: - * chunked' headers that indicate the presence of a body. - * - * Returning `2` from on_headers_complete will tell parser that it should not - * expect neither a body nor any futher responses on this connection. This is - * useful for handling responses to a CONNECT request which may not contain - * `Upgrade` or `Connection: upgrade` headers. - * - * http_data_cb does not return data chunks. It will be called arbitrarily - * many times for each string. E.G. you might get 10 callbacks for "on_url" - * each providing just a few characters more data. - */ -typedef int (*http_data_cb)(http_parser *, const char *at, size_t length); -typedef int (*http_cb)(http_parser *); - - -/* Status Codes */ -#define HTTP_STATUS_MAP(XX) \ - XX(100, CONTINUE, Continue) \ - XX(101, SWITCHING_PROTOCOLS, Switching Protocols) \ - XX(102, PROCESSING, Processing) \ - XX(200, OK, OK) \ - XX(201, CREATED, Created) \ - XX(202, ACCEPTED, Accepted) \ - XX(203, NON_AUTHORITATIVE_INFORMATION, Non - Authoritative Information) \ - XX(204, NO_CONTENT, No Content) \ - XX(205, RESET_CONTENT, Reset Content) \ - XX(206, PARTIAL_CONTENT, Partial Content) \ - XX(207, MULTI_STATUS, Multi - Status) \ - XX(208, ALREADY_REPORTED, Already Reported) \ - XX(226, IM_USED, IM Used) \ - XX(300, MULTIPLE_CHOICES, Multiple Choices) \ - XX(301, MOVED_PERMANENTLY, Moved Permanently) \ - XX(302, FOUND, Found) \ - XX(303, SEE_OTHER, See Other) \ - XX(304, NOT_MODIFIED, Not Modified) \ - XX(305, USE_PROXY, Use Proxy) \ - XX(307, TEMPORARY_REDIRECT, Temporary Redirect) \ - XX(308, PERMANENT_REDIRECT, Permanent Redirect) \ - XX(400, BAD_REQUEST, Bad Request) \ - XX(401, UNAUTHORIZED, Unauthorized) \ - XX(402, PAYMENT_REQUIRED, Payment Required) \ - XX(403, FORBIDDEN, Forbidden) \ - XX(404, NOT_FOUND, Not Found) \ - XX(405, METHOD_NOT_ALLOWED, Method Not Allowed) \ - XX(406, NOT_ACCEPTABLE, Not Acceptable) \ - XX(407, PROXY_AUTHENTICATION_REQUIRED, Proxy Authentication Required) \ - XX(408, REQUEST_TIMEOUT, Request Timeout) \ - XX(409, CONFLICT, Conflict) \ - XX(410, GONE, Gone) \ - XX(411, LENGTH_REQUIRED, Length Required) \ - XX(412, PRECONDITION_FAILED, Precondition Failed) \ - XX(413, PAYLOAD_TOO_LARGE, Payload Too Large) \ - XX(414, URI_TOO_LONG, URI Too Long) \ - XX(415, UNSUPPORTED_MEDIA_TYPE, Unsupported Media Type) \ - XX(416, RANGE_NOT_SATISFIABLE, Range Not Satisfiable) \ - XX(417, EXPECTATION_FAILED, Expectation Failed) \ - XX(421, MISDIRECTED_REQUEST, Misdirected Request) \ - XX(422, UNPROCESSABLE_ENTITY, Unprocessable Entity) \ - XX(423, LOCKED, Locked) \ - XX(424, FAILED_DEPENDENCY, Failed Dependency) \ - XX(426, UPGRADE_REQUIRED, Upgrade Required) \ - XX(428, PRECONDITION_REQUIRED, Precondition Required) \ - XX(429, TOO_MANY_REQUESTS, Too Many Requests) \ - XX(431, REQUEST_HEADER_FIELDS_TOO_LARGE, Request Header Fields Too Large) \ - XX(451, UNAVAILABLE_FOR_LEGAL_REASONS, Unavailable For Legal Reasons) \ - XX(500, INTERNAL_SERVER_ERROR, Internal Server Error) \ - XX(501, NOT_IMPLEMENTED, Not Implemented) \ - XX(502, BAD_GATEWAY, Bad Gateway) \ - XX(503, SERVICE_UNAVAILABLE, Service Unavailable) \ - XX(504, GATEWAY_TIMEOUT, Gateway Timeout) \ - XX(505, HTTP_VERSION_NOT_SUPPORTED, HTTP Version Not Supported) \ - XX(506, VARIANT_ALSO_NEGOTIATES, Variant Also Negotiates) \ - XX(507, INSUFFICIENT_STORAGE, Insufficient Storage) \ - XX(508, LOOP_DETECTED, Loop Detected) \ - XX(510, NOT_EXTENDED, Not Extended) \ - XX(511, NETWORK_AUTHENTICATION_REQUIRED, Network Authentication Required) - -enum http_status -{ -#define XX(num, name, string) HTTP_STATUS_##name = num, - HTTP_STATUS_MAP(XX) -#undef XX -}; - - -/* Request Methods */ -#define HTTP_METHOD_MAP(XX) \ - XX(0, DELETE, DELETE) \ - XX(1, GET, GET) \ - XX(2, HEAD, HEAD) \ - XX(3, POST, POST) \ - XX(4, PUT, PUT) \ - /* pathological */ \ - XX(5, CONNECT, CONNECT) \ - XX(6, OPTIONS, OPTIONS) \ - XX(7, TRACE, TRACE) \ - /* WebDAV */ \ - XX(8, COPY, COPY) \ - XX(9, LOCK, LOCK) \ - XX(10, MKCOL, MKCOL) \ - XX(11, MOVE, MOVE) \ - XX(12, PROPFIND, PROPFIND) \ - XX(13, PROPPATCH, PROPPATCH) \ - XX(14, SEARCH, SEARCH) \ - XX(15, UNLOCK, UNLOCK) \ - XX(16, BIND, BIND) \ - XX(17, REBIND, REBIND) \ - XX(18, UNBIND, UNBIND) \ - XX(19, ACL, ACL) \ - /* subversion */ \ - XX(20, REPORT, REPORT) \ - XX(21, MKACTIVITY, MKACTIVITY) \ - XX(22, CHECKOUT, CHECKOUT) \ - XX(23, MERGE, MERGE) \ - /* upnp */ \ - XX(24, MSEARCH, M - SEARCH) \ - XX(25, NOTIFY, NOTIFY) \ - XX(26, SUBSCRIBE, SUBSCRIBE) \ - XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \ - /* RFC-5789 */ \ - XX(28, PATCH, PATCH) \ - XX(29, PURGE, PURGE) \ - /* CalDAV */ \ - XX(30, MKCALENDAR, MKCALENDAR) \ - /* RFC-2068, section 19.6.1.2 */ \ - XX(31, LINK, LINK) \ - XX(32, UNLINK, UNLINK) \ - /* icecast */ \ - XX(33, SOURCE, SOURCE) - -enum http_method -{ -#define XX(num, name, string) HTTP_##name = num, - HTTP_METHOD_MAP(XX) -#undef XX -}; - - -enum http_parser_type -{ - HTTP_REQUEST, - HTTP_RESPONSE, - HTTP_BOTH -}; - - -/* Flag values for http_parser.flags field */ -enum flags -{ - F_CHUNKED = 1 << 0, - F_CONNECTION_KEEP_ALIVE = 1 << 1, - F_CONNECTION_CLOSE = 1 << 2, - F_CONNECTION_UPGRADE = 1 << 3, - F_TRAILING = 1 << 4, - F_UPGRADE = 1 << 5, - F_SKIPBODY = 1 << 6, - F_CONTENTLENGTH = 1 << 7 -}; - - -/* Map for errno-related constants - * - * The provided argument should be a macro that takes 2 arguments. - */ -#define HTTP_ERRNO_MAP(XX) \ - /* No error */ \ - XX(OK, "success") \ - \ - /* Callback-related errors */ \ - XX(CB_message_begin, "the on_message_begin callback failed") \ - XX(CB_url, "the on_url callback failed") \ - XX(CB_header_field, "the on_header_field callback failed") \ - XX(CB_header_value, "the on_header_value callback failed") \ - XX(CB_headers_complete, "the on_headers_complete callback failed") \ - XX(CB_body, "the on_body callback failed") \ - XX(CB_message_complete, "the on_message_complete callback failed") \ - XX(CB_status, "the on_status callback failed") \ - XX(CB_chunk_header, "the on_chunk_header callback failed") \ - XX(CB_chunk_complete, "the on_chunk_complete callback failed") \ - \ - /* Parsing-related errors */ \ - XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \ - XX(HEADER_OVERFLOW, \ - "too many header bytes seen; overflow detected") \ - XX(CLOSED_CONNECTION, \ - "data received after completed connection: close message") \ - XX(INVALID_VERSION, "invalid HTTP version") \ - XX(INVALID_STATUS, "invalid HTTP status code") \ - XX(INVALID_METHOD, "invalid HTTP method") \ - XX(INVALID_URL, "invalid URL") \ - XX(INVALID_HOST, "invalid host") \ - XX(INVALID_PORT, "invalid port") \ - XX(INVALID_PATH, "invalid path") \ - XX(INVALID_QUERY_STRING, "invalid query string") \ - XX(INVALID_FRAGMENT, "invalid fragment") \ - XX(LF_EXPECTED, "LF character expected") \ - XX(INVALID_HEADER_TOKEN, "invalid character in header") \ - XX(INVALID_CONTENT_LENGTH, \ - "invalid character in content-length header") \ - XX(UNEXPECTED_CONTENT_LENGTH, \ - "unexpected content-length header") \ - XX(INVALID_CHUNK_SIZE, \ - "invalid character in chunk size header") \ - XX(INVALID_CONSTANT, "invalid constant string") \ - XX(INVALID_INTERNAL_STATE, "encountered unexpected internal state") \ - XX(STRICT, "strict mode assertion failed") \ - XX(PAUSED, "parser is paused") \ - XX(UNKNOWN, "an unknown error occurred") - - -/* Define HPE_* values for each errno value above */ -#define HTTP_ERRNO_GEN(n, s) HPE_##n, -enum http_errno -{ - HTTP_ERRNO_MAP(HTTP_ERRNO_GEN) -}; -#undef HTTP_ERRNO_GEN - - -/* Get an http_errno value from an http_parser */ -#define HTTP_PARSER_ERRNO(p) ((enum http_errno)(p)->http_errno) - - -struct http_parser -{ - /** PRIVATE **/ - unsigned int type : 2; /* enum http_parser_type */ - unsigned int flags : 8; /* F_* values from 'flags' enum; semi-public */ - unsigned int state : 7; /* enum state from http_parser.c */ - unsigned int header_state : 7; /* enum header_state from http_parser.c */ - unsigned int index : 7; /* index into current matcher */ - unsigned int lenient_http_headers : 1; - - uint32_t nread; /* # bytes read in various scenarios */ - uint64_t content_length; /* # bytes in body (0 if no Content-Length header) */ - - /** READ-ONLY **/ - unsigned short http_major; - unsigned short http_minor; - unsigned int status_code : 16; /* responses only */ - unsigned int method : 8; /* requests only */ - unsigned int http_errno : 7; - - /* 1 = Upgrade header was present and the parser has exited because of that. - * 0 = No upgrade header present. - * Should be checked when http_parser_execute() returns in addition to - * error checking. - */ - unsigned int upgrade : 1; - - /** PUBLIC **/ - void *data; /* A pointer to get hook to the "connection" or "socket" object */ -}; - - -struct http_parser_settings -{ - http_cb on_message_begin; - http_data_cb on_url; - http_data_cb on_status; - http_data_cb on_header_field; - http_data_cb on_header_value; - http_cb on_headers_complete; - http_data_cb on_body; - http_cb on_message_complete; - /* When on_chunk_header is called, the current chunk length is stored - * in parser->content_length. - */ - http_cb on_chunk_header; - http_cb on_chunk_complete; -}; - - -enum http_parser_url_fields -{ - UF_SCHEMA = 0, - UF_HOST = 1, - UF_PORT = 2, - UF_PATH = 3, - UF_QUERY = 4, - UF_FRAGMENT = 5, - UF_USERINFO = 6, - UF_MAX = 7 -}; - - -/* Result structure for http_parser_parse_url(). - * - * Callers should index into field_data[] with UF_* values iff field_set - * has the relevant (1 << UF_*) bit set. As a courtesy to clients (and - * because we probably have padding left over), we convert any port to - * a uint16_t. - */ -struct http_parser_url -{ - uint16_t field_set; /* Bitmask of (1 << UF_*) values */ - uint16_t port; /* Converted UF_PORT string */ - - struct - { - uint16_t off; /* Offset into buffer in which field starts */ - uint16_t len; /* Length of run in buffer */ - } field_data[UF_MAX]; -}; - - -/* Returns the library version. Bits 16-23 contain the major version number, - * bits 8-15 the minor version number and bits 0-7 the patch level. - * Usage example: - * - * unsigned long version = http_parser_version(); - * unsigned major = (version >> 16) & 255; - * unsigned minor = (version >> 8) & 255; - * unsigned patch = version & 255; - * printf("http_parser v%u.%u.%u\n", major, minor, patch); - */ -static unsigned long http_parser_version(void); - -static void http_parser_init(http_parser *parser, enum http_parser_type type); - - -/* Initialize http_parser_settings members to 0 - */ -static void http_parser_settings_init(http_parser_settings *settings); - - -/* Executes the parser. Returns number of parsed bytes. Sets - * `parser->http_errno` on error. */ -static size_t http_parser_execute(http_parser *parser, - const http_parser_settings *settings, - const char *data, - size_t len); - - -/* If http_should_keep_alive() in the on_headers_complete or - * on_message_complete callback returns 0, then this should be - * the last message on the connection. - * If you are the server, respond with the "Connection: close" header. - * If you are the client, close the connection. - */ -static int http_should_keep_alive(const http_parser *parser); - -/* Returns a string version of the HTTP method. */ -static const char *http_method_str(enum http_method m); - -/* Returns a string version of the HTTP status code. */ -static const char *http_status_str(enum http_status s); - -/* Return a string name of the given error */ -static const char *http_errno_name(enum http_errno err); - -/* Return a string description of the given error */ -static const char *http_errno_description(enum http_errno err); - -/* Initialize all http_parser_url members to 0 */ -static void http_parser_url_init(struct http_parser_url *u); - -/* Parse a URL; return nonzero on failure */ -static int http_parser_parse_url(const char *buf, size_t buflen, - int is_connect, - struct http_parser_url *u); - -/* Pause or un-pause the parser; a nonzero value pauses */ -static void http_parser_pause(http_parser *parser, int paused); - -/* Checks if this is the final chunk of the body. */ -static int http_body_is_final(const http_parser *parser); - -/* Change the maximum header size provided at compile time. */ -static void http_parser_set_max_header_size(uint32_t size); - -static uint32_t max_header_size = HTTP_MAX_HEADER_SIZE; - -#ifndef ULLONG_MAX -#define ULLONG_MAX ((uint64_t) -1) /* 2^64-1 */ -#endif - -#ifndef MIN -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#endif - -#ifndef ARRAY_SIZE -#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) -#endif - -#ifndef BIT_AT -#define BIT_AT(a, i) \ - (!!((unsigned int) (a)[(unsigned int) (i) >> 3] & \ - (1 << ((unsigned int) (i) &7)))) -#endif - -#ifndef ELEM_AT -#define ELEM_AT(a, i, v) ((unsigned int) (i) < ARRAY_SIZE(a) ? (a)[(i)] : (v)) -#endif - -#define SET_ERRNO(e) \ - do \ - { \ - parser->nread = nread; \ - parser->http_errno = (e); \ - } while (0) - -#define CURRENT_STATE() p_state -#define UPDATE_STATE(V) p_state = (enum state)(V); -#define RETURN(V) \ - do \ - { \ - parser->nread = nread; \ - parser->state = CURRENT_STATE(); \ - return (V); \ - } while (0); -#define REEXECUTE() \ - goto reexecute; - -#ifdef __GNUC__ -#define LIKELY(X) __builtin_expect(!!(X), 1) -#define UNLIKELY(X) __builtin_expect(!!(X), 0) -#else -#define LIKELY(X) (X) -#define UNLIKELY(X) (X) -#endif - -/* Run the notify callback FOR, returning ER if it fails */ -#define CALLBACK_NOTIFY_(FOR, ER) \ - do \ - { \ - assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \ - \ - if (LIKELY(settings->on_##FOR)) \ - { \ - parser->state = CURRENT_STATE(); \ - if (UNLIKELY(0 != settings->on_##FOR(parser))) \ - { \ - SET_ERRNO(HPE_CB_##FOR); \ - } \ - UPDATE_STATE(parser->state); \ - \ - /* We either errored above or got paused; get out */ \ - if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) \ - { \ - return (ER); \ - } \ - } \ - } while (0) - -/* Run the notify callback FOR and consume the current byte */ -#define CALLBACK_NOTIFY(FOR) CALLBACK_NOTIFY_(FOR, p - data + 1) - -/* Run the notify callback FOR and don't consume the current byte */ -#define CALLBACK_NOTIFY_NOADVANCE(FOR) CALLBACK_NOTIFY_(FOR, p - data) - -/* Run data callback FOR with LEN bytes, returning ER if it fails */ -#define CALLBACK_DATA_(FOR, LEN, ER) \ - do \ - { \ - assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \ - \ - if (FOR##_mark) \ - { \ - if (LIKELY(settings->on_##FOR)) \ - { \ - parser->state = CURRENT_STATE(); \ - if (UNLIKELY(0 != \ - settings->on_##FOR(parser, FOR##_mark, (LEN)))) \ - { \ - SET_ERRNO(HPE_CB_##FOR); \ - } \ - UPDATE_STATE(parser->state); \ - \ - /* We either errored above or got paused; get out */ \ - if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) \ - { \ - return (ER); \ - } \ - } \ - FOR##_mark = NULL; \ - } \ - } while (0) - -/* Run the data callback FOR and consume the current byte */ -#define CALLBACK_DATA(FOR) \ - CALLBACK_DATA_(FOR, p - FOR##_mark, p - data + 1) - -/* Run the data callback FOR and don't consume the current byte */ -#define CALLBACK_DATA_NOADVANCE(FOR) \ - CALLBACK_DATA_(FOR, p - FOR##_mark, p - data) - -/* Set the mark FOR; non-destructive if mark is already set */ -#define MARK(FOR) \ - do \ - { \ - if (!FOR##_mark) \ - { \ - FOR##_mark = p; \ - } \ - } while (0) - -/* Don't allow the total size of the HTTP headers (including the status - * line) to exceed max_header_size. This check is here to protect - * embedders against denial-of-service attacks where the attacker feeds - * us a never-ending header that the embedder keeps buffering. - * - * This check is arguably the responsibility of embedders but we're doing - * it on the embedder's behalf because most won't bother and this way we - * make the web a little safer. max_header_size is still far bigger - * than any reasonable request or response so this should never affect - * day-to-day operation. - */ -#define COUNT_HEADER_SIZE(V) \ - do \ - { \ - nread += (uint32_t)(V); \ - if (UNLIKELY(nread > max_header_size)) \ - { \ - SET_ERRNO(HPE_HEADER_OVERFLOW); \ - goto error; \ - } \ - } while (0) - -#define PROXY_CONNECTION "proxy-connection" -#define CONNECTION "connection" -#define CONTENT_LENGTH "content-length" -#define TRANSFER_ENCODING "transfer-encoding" -#define UPGRADE "upgrade" -#define CHUNKED "chunked" -#define KEEP_ALIVE "keep-alive" -#define CLOSE "close" - -static const char *method_strings[] = - { -#define XX(num, name, string) #string, - HTTP_METHOD_MAP(XX) -#undef XX -}; - -/* Tokens as defined by rfc 2616. Also lowercases them. - * token = 1* - * separators = "(" | ")" | "<" | ">" | "@" - * | "," | ";" | ":" | "\" | <"> - * | "/" | "[" | "]" | "?" | "=" - * | "{" | "}" | SP | HT - */ -static const char tokens[256] = { - /* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */ - 0, 0, 0, 0, 0, 0, 0, 0, - /* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */ - 0, 0, 0, 0, 0, 0, 0, 0, - /* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */ - 0, 0, 0, 0, 0, 0, 0, 0, - /* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */ - 0, 0, 0, 0, 0, 0, 0, 0, - /* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */ - ' ', '!', 0, '#', '$', '%', '&', '\'', - /* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */ - 0, 0, '*', '+', 0, '-', '.', 0, - /* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */ - '0', '1', '2', '3', '4', '5', '6', '7', - /* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */ - '8', '9', 0, 0, 0, 0, 0, 0, - /* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */ - 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', - /* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */ - 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', - /* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */ - 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', - /* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */ - 'x', 'y', 'z', 0, 0, 0, '^', '_', - /* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */ - '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', - /* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */ - 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', - /* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */ - 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', - /* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */ - 'x', 'y', 'z', 0, '|', 0, '~', 0}; - -static const int8_t unhex[256] = - {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; - -#if HTTP_PARSER_STRICT -#define T(v) 0 -#else -#define T(v) v -#endif - -static const uint8_t normal_url_char[32] = { - /* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */ - 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0, - /* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */ - 0 | T(2) | 0 | 0 | T(16) | 0 | 0 | 0, - /* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */ - 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0, - /* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */ - 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0, - /* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */ - 0 | 2 | 4 | 0 | 16 | 32 | 64 | 128, - /* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, - /* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, - /* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 0, - /* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, - /* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, - /* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, - /* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, - /* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, - /* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, - /* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, - /* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */ - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 0, -}; - -#undef T - -enum state -{ - s_dead = 1 /* important that this is > 0 */ - - , - s_start_req_or_res, - s_res_or_resp_H, - s_start_res, - s_res_H, - s_res_HT, - s_res_HTT, - s_res_HTTP, - s_res_http_major, - s_res_http_dot, - s_res_http_minor, - s_res_http_end, - s_res_first_status_code, - s_res_status_code, - s_res_status_start, - s_res_status, - s_res_line_almost_done - - , - s_start_req - - , - s_req_method, - s_req_spaces_before_url, - s_req_schema, - s_req_schema_slash, - s_req_schema_slash_slash, - s_req_server_start, - s_req_server, - s_req_server_with_at, - s_req_path, - s_req_query_string_start, - s_req_query_string, - s_req_fragment_start, - s_req_fragment, - s_req_http_start, - s_req_http_H, - s_req_http_HT, - s_req_http_HTT, - s_req_http_HTTP, - s_req_http_I, - s_req_http_IC, - s_req_http_major, - s_req_http_dot, - s_req_http_minor, - s_req_http_end, - s_req_line_almost_done - - , - s_header_field_start, - s_header_field, - s_header_value_discard_ws, - s_header_value_discard_ws_almost_done, - s_header_value_discard_lws, - s_header_value_start, - s_header_value, - s_header_value_lws - - , - s_header_almost_done - - , - s_chunk_size_start, - s_chunk_size, - s_chunk_parameters, - s_chunk_size_almost_done - - , - s_headers_almost_done, - s_headers_done - - /* Important: 's_headers_done' must be the last 'header' state. All - * states beyond this must be 'body' states. It is used for overflow - * checking. See the PARSING_HEADER() macro. - */ - - , - s_chunk_data, - s_chunk_data_almost_done, - s_chunk_data_done - - , - s_body_identity, - s_body_identity_eof - - , - s_message_done -}; - -#define PARSING_HEADER(state) (state <= s_headers_done) - -enum header_states -{ - h_general = 0, - h_C, - h_CO, - h_CON - - , - h_matching_connection, - h_matching_proxy_connection, - h_matching_content_length, - h_matching_transfer_encoding, - h_matching_upgrade - - , - h_connection, - h_content_length, - h_content_length_num, - h_content_length_ws, - h_transfer_encoding, - h_upgrade - - , - h_matching_transfer_encoding_chunked, - h_matching_connection_token_start, - h_matching_connection_keep_alive, - h_matching_connection_close, - h_matching_connection_upgrade, - h_matching_connection_token - - , - h_transfer_encoding_chunked, - h_connection_keep_alive, - h_connection_close, - h_connection_upgrade -}; - -enum http_host_state -{ - s_http_host_dead = 1, - s_http_userinfo_start, - s_http_userinfo, - s_http_host_start, - s_http_host_v6_start, - s_http_host, - s_http_host_v6, - s_http_host_v6_end, - s_http_host_v6_zone_start, - s_http_host_v6_zone, - s_http_host_port_start, - s_http_host_port -}; - -/* Macros for character classes; depends on strict-mode */ -#define CR '\r' -#define LF '\n' -#define LOWER(c) (unsigned char) (c | 0x20) -#define IS_ALPHA(c) (LOWER(c) >= 'a' && LOWER(c) <= 'z') -#define IS_NUM(c) ((c) >= '0' && (c) <= '9') -#define IS_ALPHANUM(c) (IS_ALPHA(c) || IS_NUM(c)) -#define IS_HEX(c) (IS_NUM(c) || (LOWER(c) >= 'a' && LOWER(c) <= 'f')) -#define IS_MARK(c) ((c) == '-' || (c) == '_' || (c) == '.' || \ - (c) == '!' || (c) == '~' || (c) == '*' || (c) == '\'' || (c) == '(' || \ - (c) == ')') -#define IS_USERINFO_CHAR(c) (IS_ALPHANUM(c) || IS_MARK(c) || (c) == '%' || \ - (c) == ';' || (c) == ':' || (c) == '&' || (c) == '=' || (c) == '+' || \ - (c) == '$' || (c) == ',') - -#define STRICT_TOKEN(c) ((c == ' ') ? 0 : tokens[(unsigned char) c]) - -#if HTTP_PARSER_STRICT -#define TOKEN(c) STRICT_TOKEN(c) -#define IS_URL_CHAR(c) (BIT_AT(normal_url_char, (unsigned char) c)) -#define IS_HOST_CHAR(c) (IS_ALPHANUM(c) || (c) == '.' || (c) == '-') -#else -#define TOKEN(c) tokens[(unsigned char) c] -#define IS_URL_CHAR(c) \ - (BIT_AT(normal_url_char, (unsigned char) c) || ((c) &0x80)) -#define IS_HOST_CHAR(c) \ - (IS_ALPHANUM(c) || (c) == '.' || (c) == '-' || (c) == '_') -#endif - -/** - * Verify that a char is a valid visible (printable) US-ASCII - * character or %x80-FF - **/ -#define IS_HEADER_CHAR(ch) \ - (ch == CR || ch == LF || ch == 9 || ((unsigned char) ch > 31 && ch != 127)) - -#define start_state (parser->type == HTTP_REQUEST ? s_start_req : s_start_res) - -#if HTTP_PARSER_STRICT -#define STRICT_CHECK(cond) \ - do \ - { \ - if (cond) \ - { \ - SET_ERRNO(HPE_STRICT); \ - goto error; \ - } \ - } while (0) -#define NEW_MESSAGE() (http_should_keep_alive(parser) ? start_state : s_dead) -#else -#define STRICT_CHECK(cond) -#define NEW_MESSAGE() start_state -#endif - -/* Map errno values to strings for human-readable output */ -#define HTTP_STRERROR_GEN(n, s) {"HPE_" #n, s}, -static struct -{ - const char *name; - const char *description; -} http_strerror_tab[] = { - HTTP_ERRNO_MAP(HTTP_STRERROR_GEN)}; -#undef HTTP_STRERROR_GEN - -static int http_message_needs_eof(const http_parser *parser); - -/* Our URL parser. - * - * This is designed to be shared by http_parser_execute() for URL validation, - * hence it has a state transition + byte-for-byte interface. In addition, it - * is meant to be embedded in http_parser_parse_url(), which does the dirty - * work of turning state transitions URL components for its API. - * - * This function should only be invoked with non-space characters. It is - * assumed that the caller cares about (and can detect) the transition between - * URL and non-URL states by looking for these. - */ -static enum state -parse_url_char(enum state s, const char ch) -{ - if (ch == ' ' || ch == '\r' || ch == '\n') - { - return s_dead; - } - -#if HTTP_PARSER_STRICT - if (ch == '\t' || ch == '\f') - { - return s_dead; - } -#endif - - switch (s) - { - case s_req_spaces_before_url: - /* Proxied requests are followed by scheme of an absolute URI (alpha). - * All methods except CONNECT are followed by '/' or '*'. - */ - - if (ch == '/' || ch == '*') - { - return s_req_path; - } - - if (IS_ALPHA(ch)) - { - return s_req_schema; - } - - break; - - case s_req_schema: - if (IS_ALPHA(ch)) - { - return s; - } - - if (ch == ':') - { - return s_req_schema_slash; - } - - break; - - case s_req_schema_slash: - if (ch == '/') - { - return s_req_schema_slash_slash; - } - - break; - - case s_req_schema_slash_slash: - if (ch == '/') - { - return s_req_server_start; - } - - break; - - case s_req_server_with_at: - if (ch == '@') - { - return s_dead; - } - - /* fall through */ - case s_req_server_start: - case s_req_server: - if (ch == '/') - { - return s_req_path; - } - - if (ch == '?') - { - return s_req_query_string_start; - } - - if (ch == '@') - { - return s_req_server_with_at; - } - - if (IS_USERINFO_CHAR(ch) || ch == '[' || ch == ']') - { - return s_req_server; - } - - break; - - case s_req_path: - if (IS_URL_CHAR(ch)) - { - return s; - } - - switch (ch) - { - case '?': - return s_req_query_string_start; - - case '#': - return s_req_fragment_start; - } - - break; - - case s_req_query_string_start: - case s_req_query_string: - if (IS_URL_CHAR(ch)) - { - return s_req_query_string; - } - - switch (ch) - { - case '?': - /* allow extra '?' in query string */ - return s_req_query_string; - - case '#': - return s_req_fragment_start; - } - - break; - - case s_req_fragment_start: - if (IS_URL_CHAR(ch)) - { - return s_req_fragment; - } - - switch (ch) - { - case '?': - return s_req_fragment; - - case '#': - return s; - } - - break; - - case s_req_fragment: - if (IS_URL_CHAR(ch)) - { - return s; - } - - switch (ch) - { - case '?': - case '#': - return s; - } - - break; - - default: - break; - } - - /* We should never fall out of the switch above unless there's an error */ - return s_dead; -} - -static size_t http_parser_execute(http_parser *parser, - const http_parser_settings *settings, - const char *data, - size_t len) -{ - char c, ch; - int8_t unhex_val; - const char *p = data; - const char *header_field_mark = 0; - const char *header_value_mark = 0; - const char *url_mark = 0; - const char *body_mark = 0; - const char *status_mark = 0; - enum state p_state = (enum state) parser->state; - const unsigned int lenient = parser->lenient_http_headers; - uint32_t nread = parser->nread; - - /* We're in an error state. Don't bother doing anything. */ - if (HTTP_PARSER_ERRNO(parser) != HPE_OK) - { - return 0; - } - - if (len == 0) - { - switch (CURRENT_STATE()) - { - case s_body_identity_eof: - /* Use of CALLBACK_NOTIFY() here would erroneously return 1 byte read if - * we got paused. - */ - CALLBACK_NOTIFY_NOADVANCE(message_complete); - return 0; - - case s_dead: - case s_start_req_or_res: - case s_start_res: - case s_start_req: - return 0; - - default: - SET_ERRNO(HPE_INVALID_EOF_STATE); - return 1; - } - } - - if (CURRENT_STATE() == s_header_field) - header_field_mark = data; - if (CURRENT_STATE() == s_header_value) - header_value_mark = data; - switch (CURRENT_STATE()) - { - case s_req_path: - case s_req_schema: - case s_req_schema_slash: - case s_req_schema_slash_slash: - case s_req_server_start: - case s_req_server: - case s_req_server_with_at: - case s_req_query_string_start: - case s_req_query_string: - case s_req_fragment_start: - case s_req_fragment: - url_mark = data; - break; - case s_res_status: - status_mark = data; - break; - default: - break; - } - - for (p = data; p != data + len; p++) - { - ch = *p; - - if (PARSING_HEADER(CURRENT_STATE())) - COUNT_HEADER_SIZE(1); - - reexecute: - switch (CURRENT_STATE()) - { - - case s_dead: - /* this state is used after a 'Connection: close' message - * the parser will error out if it reads another message - */ - if (LIKELY(ch == CR || ch == LF)) - break; - - SET_ERRNO(HPE_CLOSED_CONNECTION); - goto error; - - case s_start_req_or_res: - { - if (ch == CR || ch == LF) - break; - parser->flags = 0; - parser->content_length = ULLONG_MAX; - - if (ch == 'H') - { - UPDATE_STATE(s_res_or_resp_H); - - CALLBACK_NOTIFY(message_begin); - } - else - { - parser->type = HTTP_REQUEST; - UPDATE_STATE(s_start_req); - REEXECUTE(); - } - - break; - } - - case s_res_or_resp_H: - if (ch == 'T') - { - parser->type = HTTP_RESPONSE; - UPDATE_STATE(s_res_HT); - } - else - { - if (UNLIKELY(ch != 'E')) - { - SET_ERRNO(HPE_INVALID_CONSTANT); - goto error; - } - - parser->type = HTTP_REQUEST; - parser->method = HTTP_HEAD; - parser->index = 2; - UPDATE_STATE(s_req_method); - } - break; - - case s_start_res: - { - if (ch == CR || ch == LF) - break; - parser->flags = 0; - parser->content_length = ULLONG_MAX; - - if (ch == 'H') - { - UPDATE_STATE(s_res_H); - } - else - { - SET_ERRNO(HPE_INVALID_CONSTANT); - goto error; - } - - CALLBACK_NOTIFY(message_begin); - break; - } - - case s_res_H: - STRICT_CHECK(ch != 'T'); - UPDATE_STATE(s_res_HT); - break; - - case s_res_HT: - STRICT_CHECK(ch != 'T'); - UPDATE_STATE(s_res_HTT); - break; - - case s_res_HTT: - STRICT_CHECK(ch != 'P'); - UPDATE_STATE(s_res_HTTP); - break; - - case s_res_HTTP: - STRICT_CHECK(ch != '/'); - UPDATE_STATE(s_res_http_major); - break; - - case s_res_http_major: - if (UNLIKELY(!IS_NUM(ch))) - { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - parser->http_major = ch - '0'; - UPDATE_STATE(s_res_http_dot); - break; - - case s_res_http_dot: - { - if (UNLIKELY(ch != '.')) - { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - UPDATE_STATE(s_res_http_minor); - break; - } - - case s_res_http_minor: - if (UNLIKELY(!IS_NUM(ch))) - { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - parser->http_minor = ch - '0'; - UPDATE_STATE(s_res_http_end); - break; - - case s_res_http_end: - { - if (UNLIKELY(ch != ' ')) - { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - UPDATE_STATE(s_res_first_status_code); - break; - } - - case s_res_first_status_code: - { - if (!IS_NUM(ch)) - { - if (ch == ' ') - { - break; - } - - SET_ERRNO(HPE_INVALID_STATUS); - goto error; - } - parser->status_code = ch - '0'; - UPDATE_STATE(s_res_status_code); - break; - } - - case s_res_status_code: - { - if (!IS_NUM(ch)) - { - switch (ch) - { - case ' ': - UPDATE_STATE(s_res_status_start); - break; - case CR: - case LF: - UPDATE_STATE(s_res_status_start); - REEXECUTE(); - break; - default: - SET_ERRNO(HPE_INVALID_STATUS); - goto error; - } - break; - } - - parser->status_code *= 10; - parser->status_code += ch - '0'; - - if (UNLIKELY(parser->status_code > 999)) - { - SET_ERRNO(HPE_INVALID_STATUS); - goto error; - } - - break; - } - - case s_res_status_start: - { - MARK(status); - UPDATE_STATE(s_res_status); - parser->index = 0; - - if (ch == CR || ch == LF) - REEXECUTE(); - - break; - } - - case s_res_status: - if (ch == CR) - { - UPDATE_STATE(s_res_line_almost_done); - CALLBACK_DATA(status); - break; - } - - if (ch == LF) - { - UPDATE_STATE(s_header_field_start); - CALLBACK_DATA(status); - break; - } - - break; - - case s_res_line_almost_done: - STRICT_CHECK(ch != LF); - UPDATE_STATE(s_header_field_start); - break; - - case s_start_req: - { - if (ch == CR || ch == LF) - break; - parser->flags = 0; - parser->content_length = ULLONG_MAX; - - if (UNLIKELY(!IS_ALPHA(ch))) - { - SET_ERRNO(HPE_INVALID_METHOD); - goto error; - } - - parser->method = (enum http_method) 0; - parser->index = 1; - switch (ch) - { - case 'A': - parser->method = HTTP_ACL; - break; - case 'B': - parser->method = HTTP_BIND; - break; - case 'C': - parser->method = HTTP_CONNECT; /* or COPY, CHECKOUT */ - break; - case 'D': - parser->method = HTTP_DELETE; - break; - case 'G': - parser->method = HTTP_GET; - break; - case 'H': - parser->method = HTTP_HEAD; - break; - case 'L': - parser->method = HTTP_LOCK; /* or LINK */ - break; - case 'M': - parser->method = HTTP_MKCOL; /* or MOVE, MKACTIVITY, MERGE, M-SEARCH, MKCALENDAR */ - break; - case 'N': - parser->method = HTTP_NOTIFY; - break; - case 'O': - parser->method = HTTP_OPTIONS; - break; - case 'P': - parser->method = HTTP_POST; - /* or PROPFIND|PROPPATCH|PUT|PATCH|PURGE */ - break; - case 'R': - parser->method = HTTP_REPORT; /* or REBIND */ - break; - case 'S': - parser->method = HTTP_SUBSCRIBE; /* or SEARCH, SOURCE */ - break; - case 'T': - parser->method = HTTP_TRACE; - break; - case 'U': - parser->method = HTTP_UNLOCK; /* or UNSUBSCRIBE, UNBIND, UNLINK */ - break; - default: - SET_ERRNO(HPE_INVALID_METHOD); - goto error; - } - UPDATE_STATE(s_req_method); - - CALLBACK_NOTIFY(message_begin); - - break; - } - - case s_req_method: - { - const char *matcher; - if (UNLIKELY(ch == '\0')) - { - SET_ERRNO(HPE_INVALID_METHOD); - goto error; - } - - matcher = method_strings[parser->method]; - if (ch == ' ' && matcher[parser->index] == '\0') - { - UPDATE_STATE(s_req_spaces_before_url); - } - else if (ch == matcher[parser->index]) - { - ; /* nada */ - } - else if ((ch >= 'A' && ch <= 'Z') || ch == '-') - { - - switch (parser->method << 16 | parser->index << 8 | ch) - { -#define XX(meth, pos, ch, new_meth) \ - case (HTTP_##meth << 16 | pos << 8 | ch): \ - parser->method = HTTP_##new_meth; \ - break; - - XX(POST, 1, 'U', PUT) - XX(POST, 1, 'A', PATCH) - XX(POST, 1, 'R', PROPFIND) - XX(PUT, 2, 'R', PURGE) - XX(CONNECT, 1, 'H', CHECKOUT) - XX(CONNECT, 2, 'P', COPY) - XX(MKCOL, 1, 'O', MOVE) - XX(MKCOL, 1, 'E', MERGE) - XX(MKCOL, 1, '-', MSEARCH) - XX(MKCOL, 2, 'A', MKACTIVITY) - XX(MKCOL, 3, 'A', MKCALENDAR) - XX(SUBSCRIBE, 1, 'E', SEARCH) - XX(SUBSCRIBE, 1, 'O', SOURCE) - XX(REPORT, 2, 'B', REBIND) - XX(PROPFIND, 4, 'P', PROPPATCH) - XX(LOCK, 1, 'I', LINK) - XX(UNLOCK, 2, 'S', UNSUBSCRIBE) - XX(UNLOCK, 2, 'B', UNBIND) - XX(UNLOCK, 3, 'I', UNLINK) -#undef XX - default: - SET_ERRNO(HPE_INVALID_METHOD); - goto error; - } - } - else - { - SET_ERRNO(HPE_INVALID_METHOD); - goto error; - } - - ++parser->index; - break; - } - - case s_req_spaces_before_url: - { - if (ch == ' ') - break; - - MARK(url); - if (parser->method == HTTP_CONNECT) - { - UPDATE_STATE(s_req_server_start); - } - - UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch)); - if (UNLIKELY(CURRENT_STATE() == s_dead)) - { - SET_ERRNO(HPE_INVALID_URL); - goto error; - } - - break; - } - - case s_req_schema: - case s_req_schema_slash: - case s_req_schema_slash_slash: - case s_req_server_start: - { - switch (ch) - { - /* No whitespace allowed here */ - case ' ': - case CR: - case LF: - SET_ERRNO(HPE_INVALID_URL); - goto error; - default: - UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch)); - if (UNLIKELY(CURRENT_STATE() == s_dead)) - { - SET_ERRNO(HPE_INVALID_URL); - goto error; - } - } - - break; - } - - case s_req_server: - case s_req_server_with_at: - case s_req_path: - case s_req_query_string_start: - case s_req_query_string: - case s_req_fragment_start: - case s_req_fragment: - { - switch (ch) - { - case ' ': - UPDATE_STATE(s_req_http_start); - CALLBACK_DATA(url); - break; - case CR: - case LF: - parser->http_major = 0; - parser->http_minor = 9; - UPDATE_STATE((ch == CR) ? s_req_line_almost_done : s_header_field_start); - CALLBACK_DATA(url); - break; - default: - UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch)); - if (UNLIKELY(CURRENT_STATE() == s_dead)) - { - SET_ERRNO(HPE_INVALID_URL); - goto error; - } - } - break; - } - - case s_req_http_start: - switch (ch) - { - case ' ': - break; - case 'H': - UPDATE_STATE(s_req_http_H); - break; - case 'I': - if (parser->method == HTTP_SOURCE) - { - UPDATE_STATE(s_req_http_I); - break; - } - /* fall through */ - default: - SET_ERRNO(HPE_INVALID_CONSTANT); - goto error; - } - break; - - case s_req_http_H: - STRICT_CHECK(ch != 'T'); - UPDATE_STATE(s_req_http_HT); - break; - - case s_req_http_HT: - STRICT_CHECK(ch != 'T'); - UPDATE_STATE(s_req_http_HTT); - break; - - case s_req_http_HTT: - STRICT_CHECK(ch != 'P'); - UPDATE_STATE(s_req_http_HTTP); - break; - - case s_req_http_I: - STRICT_CHECK(ch != 'C'); - UPDATE_STATE(s_req_http_IC); - break; - - case s_req_http_IC: - STRICT_CHECK(ch != 'E'); - UPDATE_STATE(s_req_http_HTTP); /* Treat "ICE" as "HTTP". */ - break; - - case s_req_http_HTTP: - STRICT_CHECK(ch != '/'); - UPDATE_STATE(s_req_http_major); - break; - - case s_req_http_major: - if (UNLIKELY(!IS_NUM(ch))) - { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - parser->http_major = ch - '0'; - UPDATE_STATE(s_req_http_dot); - break; - - case s_req_http_dot: - { - if (UNLIKELY(ch != '.')) - { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - UPDATE_STATE(s_req_http_minor); - break; - } - - case s_req_http_minor: - if (UNLIKELY(!IS_NUM(ch))) - { - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - } - - parser->http_minor = ch - '0'; - UPDATE_STATE(s_req_http_end); - break; - - case s_req_http_end: - { - if (ch == CR) - { - UPDATE_STATE(s_req_line_almost_done); - break; - } - - if (ch == LF) - { - UPDATE_STATE(s_header_field_start); - break; - } - - SET_ERRNO(HPE_INVALID_VERSION); - goto error; - break; - } - - /* end of request line */ - case s_req_line_almost_done: - { - if (UNLIKELY(ch != LF)) - { - SET_ERRNO(HPE_LF_EXPECTED); - goto error; - } - - UPDATE_STATE(s_header_field_start); - break; - } - - case s_header_field_start: - { - if (ch == CR) - { - UPDATE_STATE(s_headers_almost_done); - break; - } - - if (ch == LF) - { - /* they might be just sending \n instead of \r\n so this would be - * the second \n to denote the end of headers*/ - UPDATE_STATE(s_headers_almost_done); - REEXECUTE(); - } - - c = TOKEN(ch); - - if (UNLIKELY(!c)) - { - SET_ERRNO(HPE_INVALID_HEADER_TOKEN); - goto error; - } - - MARK(header_field); - - parser->index = 0; - UPDATE_STATE(s_header_field); - - switch (c) - { - case 'c': - parser->header_state = h_C; - break; - - case 'p': - parser->header_state = h_matching_proxy_connection; - break; - - case 't': - parser->header_state = h_matching_transfer_encoding; - break; - - case 'u': - parser->header_state = h_matching_upgrade; - break; - - default: - parser->header_state = h_general; - break; - } - break; - } - - case s_header_field: - { - const char *start = p; - for (; p != data + len; p++) - { - ch = *p; - c = TOKEN(ch); - - if (!c) - break; - - switch (parser->header_state) - { - case h_general: - { - size_t left = data + len - p; - const char *pe = p + MIN(left, max_header_size); - while (p + 1 < pe && TOKEN(p[1])) - { - p++; - } - break; - } - - case h_C: - parser->index++; - parser->header_state = (c == 'o' ? h_CO : h_general); - break; - - case h_CO: - parser->index++; - parser->header_state = (c == 'n' ? h_CON : h_general); - break; - - case h_CON: - parser->index++; - switch (c) - { - case 'n': - parser->header_state = h_matching_connection; - break; - case 't': - parser->header_state = h_matching_content_length; - break; - default: - parser->header_state = h_general; - break; - } - break; - - /* connection */ - - case h_matching_connection: - parser->index++; - if (parser->index > sizeof(CONNECTION) - 1 || c != CONNECTION[parser->index]) - { - parser->header_state = h_general; - } - else if (parser->index == sizeof(CONNECTION) - 2) - { - parser->header_state = h_connection; - } - break; - - /* proxy-connection */ - - case h_matching_proxy_connection: - parser->index++; - if (parser->index > sizeof(PROXY_CONNECTION) - 1 || c != PROXY_CONNECTION[parser->index]) - { - parser->header_state = h_general; - } - else if (parser->index == sizeof(PROXY_CONNECTION) - 2) - { - parser->header_state = h_connection; - } - break; - - /* content-length */ - - case h_matching_content_length: - parser->index++; - if (parser->index > sizeof(CONTENT_LENGTH) - 1 || c != CONTENT_LENGTH[parser->index]) - { - parser->header_state = h_general; - } - else if (parser->index == sizeof(CONTENT_LENGTH) - 2) - { - parser->header_state = h_content_length; - } - break; - - /* transfer-encoding */ - - case h_matching_transfer_encoding: - parser->index++; - if (parser->index > sizeof(TRANSFER_ENCODING) - 1 || c != TRANSFER_ENCODING[parser->index]) - { - parser->header_state = h_general; - } - else if (parser->index == sizeof(TRANSFER_ENCODING) - 2) - { - parser->header_state = h_transfer_encoding; - } - break; - - /* upgrade */ - - case h_matching_upgrade: - parser->index++; - if (parser->index > sizeof(UPGRADE) - 1 || c != UPGRADE[parser->index]) - { - parser->header_state = h_general; - } - else if (parser->index == sizeof(UPGRADE) - 2) - { - parser->header_state = h_upgrade; - } - break; - - case h_connection: - case h_content_length: - case h_transfer_encoding: - case h_upgrade: - if (ch != ' ') - parser->header_state = h_general; - break; - - default: - assert(0 && "Unknown header_state"); - break; - } - } - - if (p == data + len) - { - --p; - COUNT_HEADER_SIZE(p - start); - break; - } - - COUNT_HEADER_SIZE(p - start); - - if (ch == ':') - { - UPDATE_STATE(s_header_value_discard_ws); - CALLBACK_DATA(header_field); - break; - } - - SET_ERRNO(HPE_INVALID_HEADER_TOKEN); - goto error; - } - - case s_header_value_discard_ws: - if (ch == ' ' || ch == '\t') - break; - - if (ch == CR) - { - UPDATE_STATE(s_header_value_discard_ws_almost_done); - break; - } - - if (ch == LF) - { - UPDATE_STATE(s_header_value_discard_lws); - break; - } - - /* fall through */ - - case s_header_value_start: - { - MARK(header_value); - - UPDATE_STATE(s_header_value); - parser->index = 0; - - c = LOWER(ch); - - switch (parser->header_state) - { - case h_upgrade: - parser->flags |= F_UPGRADE; - parser->header_state = h_general; - break; - - case h_transfer_encoding: - /* looking for 'Transfer-Encoding: chunked' */ - if ('c' == c) - { - parser->header_state = h_matching_transfer_encoding_chunked; - } - else - { - parser->header_state = h_general; - } - break; - - case h_content_length: - if (UNLIKELY(!IS_NUM(ch))) - { - SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); - goto error; - } - - if (parser->flags & F_CONTENTLENGTH) - { - SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH); - goto error; - } - - parser->flags |= F_CONTENTLENGTH; - parser->content_length = ch - '0'; - parser->header_state = h_content_length_num; - break; - - /* when obsolete line folding is encountered for content length - * continue to the s_header_value state */ - case h_content_length_ws: - break; - - case h_connection: - /* looking for 'Connection: keep-alive' */ - if (c == 'k') - { - parser->header_state = h_matching_connection_keep_alive; - /* looking for 'Connection: close' */ - } - else if (c == 'c') - { - parser->header_state = h_matching_connection_close; - } - else if (c == 'u') - { - parser->header_state = h_matching_connection_upgrade; - } - else - { - parser->header_state = h_matching_connection_token; - } - break; - - /* Multi-value `Connection` header */ - case h_matching_connection_token_start: - break; - - default: - parser->header_state = h_general; - break; - } - break; - } - - case s_header_value: - { - const char *start = p; - enum header_states h_state = (enum header_states) parser->header_state; - for (; p != data + len; p++) - { - ch = *p; - if (ch == CR) - { - UPDATE_STATE(s_header_almost_done); - parser->header_state = h_state; - CALLBACK_DATA(header_value); - break; - } - - if (ch == LF) - { - UPDATE_STATE(s_header_almost_done); - COUNT_HEADER_SIZE(p - start); - parser->header_state = h_state; - CALLBACK_DATA_NOADVANCE(header_value); - REEXECUTE(); - } - - if (!lenient && !IS_HEADER_CHAR(ch)) - { - SET_ERRNO(HPE_INVALID_HEADER_TOKEN); - goto error; - } - - c = LOWER(ch); - - switch (h_state) - { - case h_general: - { - size_t left = data + len - p; - const char *pe = p + MIN(left, max_header_size); - - for (; p != pe; p++) - { - ch = *p; - if (ch == CR || ch == LF) - { - --p; - break; - } - if (!lenient && !IS_HEADER_CHAR(ch)) - { - SET_ERRNO(HPE_INVALID_HEADER_TOKEN); - goto error; - } - } - if (p == data + len) - --p; - break; - } - - case h_connection: - case h_transfer_encoding: - assert(0 && "Shouldn't get here."); - break; - - case h_content_length: - if (ch == ' ') - break; - h_state = h_content_length_num; - /* fall through */ - - case h_content_length_num: - { - uint64_t t; - - if (ch == ' ') - { - h_state = h_content_length_ws; - break; - } - - if (UNLIKELY(!IS_NUM(ch))) - { - SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); - parser->header_state = h_state; - goto error; - } - - t = parser->content_length; - t *= 10; - t += ch - '0'; - - /* Overflow? Test against a conservative limit for simplicity. */ - if (UNLIKELY((ULLONG_MAX - 10) / 10 < parser->content_length)) - { - SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); - parser->header_state = h_state; - goto error; - } - - parser->content_length = t; - break; - } - - case h_content_length_ws: - if (ch == ' ') - break; - SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); - parser->header_state = h_state; - goto error; - - /* Transfer-Encoding: chunked */ - case h_matching_transfer_encoding_chunked: - parser->index++; - if (parser->index > sizeof(CHUNKED) - 1 || c != CHUNKED[parser->index]) - { - h_state = h_general; - } - else if (parser->index == sizeof(CHUNKED) - 2) - { - h_state = h_transfer_encoding_chunked; - } - break; - - case h_matching_connection_token_start: - /* looking for 'Connection: keep-alive' */ - if (c == 'k') - { - h_state = h_matching_connection_keep_alive; - /* looking for 'Connection: close' */ - } - else if (c == 'c') - { - h_state = h_matching_connection_close; - } - else if (c == 'u') - { - h_state = h_matching_connection_upgrade; - } - else if (STRICT_TOKEN(c)) - { - h_state = h_matching_connection_token; - } - else if (c == ' ' || c == '\t') - { - /* Skip lws */ - } - else - { - h_state = h_general; - } - break; - - /* looking for 'Connection: keep-alive' */ - case h_matching_connection_keep_alive: - parser->index++; - if (parser->index > sizeof(KEEP_ALIVE) - 1 || c != KEEP_ALIVE[parser->index]) - { - h_state = h_matching_connection_token; - } - else if (parser->index == sizeof(KEEP_ALIVE) - 2) - { - h_state = h_connection_keep_alive; - } - break; - - /* looking for 'Connection: close' */ - case h_matching_connection_close: - parser->index++; - if (parser->index > sizeof(CLOSE) - 1 || c != CLOSE[parser->index]) - { - h_state = h_matching_connection_token; - } - else if (parser->index == sizeof(CLOSE) - 2) - { - h_state = h_connection_close; - } - break; - - /* looking for 'Connection: upgrade' */ - case h_matching_connection_upgrade: - parser->index++; - if (parser->index > sizeof(UPGRADE) - 1 || - c != UPGRADE[parser->index]) - { - h_state = h_matching_connection_token; - } - else if (parser->index == sizeof(UPGRADE) - 2) - { - h_state = h_connection_upgrade; - } - break; - - case h_matching_connection_token: - if (ch == ',') - { - h_state = h_matching_connection_token_start; - parser->index = 0; - } - break; - - case h_transfer_encoding_chunked: - if (ch != ' ') - h_state = h_general; - break; - - case h_connection_keep_alive: - case h_connection_close: - case h_connection_upgrade: - if (ch == ',') - { - if (h_state == h_connection_keep_alive) - { - parser->flags |= F_CONNECTION_KEEP_ALIVE; - } - else if (h_state == h_connection_close) - { - parser->flags |= F_CONNECTION_CLOSE; - } - else if (h_state == h_connection_upgrade) - { - parser->flags |= F_CONNECTION_UPGRADE; - } - h_state = h_matching_connection_token_start; - parser->index = 0; - } - else if (ch != ' ') - { - h_state = h_matching_connection_token; - } - break; - - default: - UPDATE_STATE(s_header_value); - h_state = h_general; - break; - } - } - parser->header_state = h_state; - - if (p == data + len) - --p; - - COUNT_HEADER_SIZE(p - start); - break; - } - - case s_header_almost_done: - { - if (UNLIKELY(ch != LF)) - { - SET_ERRNO(HPE_LF_EXPECTED); - goto error; - } - - UPDATE_STATE(s_header_value_lws); - break; - } - - case s_header_value_lws: - { - if (ch == ' ' || ch == '\t') - { - if (parser->header_state == h_content_length_num) - { - /* treat obsolete line folding as space */ - parser->header_state = h_content_length_ws; - } - UPDATE_STATE(s_header_value_start); - REEXECUTE(); - } - - /* finished the header */ - switch (parser->header_state) - { - case h_connection_keep_alive: - parser->flags |= F_CONNECTION_KEEP_ALIVE; - break; - case h_connection_close: - parser->flags |= F_CONNECTION_CLOSE; - break; - case h_transfer_encoding_chunked: - parser->flags |= F_CHUNKED; - break; - case h_connection_upgrade: - parser->flags |= F_CONNECTION_UPGRADE; - break; - default: - break; - } - - UPDATE_STATE(s_header_field_start); - REEXECUTE(); - } - - case s_header_value_discard_ws_almost_done: - { - STRICT_CHECK(ch != LF); - UPDATE_STATE(s_header_value_discard_lws); - break; - } - - case s_header_value_discard_lws: - { - if (ch == ' ' || ch == '\t') - { - UPDATE_STATE(s_header_value_discard_ws); - break; - } - else - { - switch (parser->header_state) - { - case h_connection_keep_alive: - parser->flags |= F_CONNECTION_KEEP_ALIVE; - break; - case h_connection_close: - parser->flags |= F_CONNECTION_CLOSE; - break; - case h_connection_upgrade: - parser->flags |= F_CONNECTION_UPGRADE; - break; - case h_transfer_encoding_chunked: - parser->flags |= F_CHUNKED; - break; - case h_content_length: - /* do not allow empty content length */ - SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); - goto error; - break; - default: - break; - } - - /* header value was empty */ - MARK(header_value); - UPDATE_STATE(s_header_field_start); - CALLBACK_DATA_NOADVANCE(header_value); - REEXECUTE(); - } - } - - case s_headers_almost_done: - { - STRICT_CHECK(ch != LF); - - if (parser->flags & F_TRAILING) - { - /* End of a chunked request */ - UPDATE_STATE(s_message_done); - CALLBACK_NOTIFY_NOADVANCE(chunk_complete); - REEXECUTE(); - } - - /* Cannot use chunked encoding and a content-length header together - per the HTTP specification. */ - if ((parser->flags & F_CHUNKED) && - (parser->flags & F_CONTENTLENGTH)) - { - SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH); - goto error; - } - - UPDATE_STATE(s_headers_done); - - /* Set this here so that on_headers_complete() callbacks can see it */ - if ((parser->flags & F_UPGRADE) && - (parser->flags & F_CONNECTION_UPGRADE)) - { - /* For responses, "Upgrade: foo" and "Connection: upgrade" are - * mandatory only when it is a 101 Switching Protocols response, - * otherwise it is purely informational, to announce support. - */ - parser->upgrade = - (parser->type == HTTP_REQUEST || parser->status_code == 101); - } - else - { - parser->upgrade = (parser->method == HTTP_CONNECT); - } - - /* Here we call the headers_complete callback. This is somewhat - * different than other callbacks because if the user returns 1, we - * will interpret that as saying that this message has no body. This - * is needed for the annoying case of recieving a response to a HEAD - * request. - * - * We'd like to use CALLBACK_NOTIFY_NOADVANCE() here but we cannot, so - * we have to simulate it by handling a change in errno below. - */ - if (settings->on_headers_complete) - { - switch (settings->on_headers_complete(parser)) - { - case 0: - break; - - case 2: - parser->upgrade = 1; - - /* fall through */ - case 1: - parser->flags |= F_SKIPBODY; - break; - - default: - SET_ERRNO(HPE_CB_headers_complete); - RETURN(p - data); /* Error */ - } - } - - if (HTTP_PARSER_ERRNO(parser) != HPE_OK) - { - RETURN(p - data); - } - - REEXECUTE(); - } - - case s_headers_done: - { - int hasBody; - STRICT_CHECK(ch != LF); - - parser->nread = 0; - nread = 0; - - hasBody = parser->flags & F_CHUNKED || - (parser->content_length > 0 && parser->content_length != ULLONG_MAX); - if (parser->upgrade && (parser->method == HTTP_CONNECT || - (parser->flags & F_SKIPBODY) || !hasBody)) - { - /* Exit, the rest of the message is in a different protocol. */ - UPDATE_STATE(NEW_MESSAGE()); - CALLBACK_NOTIFY(message_complete); - RETURN((p - data) + 1); - } - - if (parser->flags & F_SKIPBODY) - { - UPDATE_STATE(NEW_MESSAGE()); - CALLBACK_NOTIFY(message_complete); - } - else if (parser->flags & F_CHUNKED) - { - /* chunked encoding - ignore Content-Length header */ - UPDATE_STATE(s_chunk_size_start); - } - else - { - if (parser->content_length == 0) - { - /* Content-Length header given but zero: Content-Length: 0\r\n */ - UPDATE_STATE(NEW_MESSAGE()); - CALLBACK_NOTIFY(message_complete); - } - else if (parser->content_length != ULLONG_MAX) - { - /* Content-Length header given and non-zero */ - UPDATE_STATE(s_body_identity); - } - else - { - if (!http_message_needs_eof(parser)) - { - /* Assume content-length 0 - read the next */ - UPDATE_STATE(NEW_MESSAGE()); - CALLBACK_NOTIFY(message_complete); - } - else - { - /* Read body until EOF */ - UPDATE_STATE(s_body_identity_eof); - } - } - } - - break; - } - - case s_body_identity: - { - uint64_t to_read = MIN(parser->content_length, - (uint64_t)((data + len) - p)); - - assert(parser->content_length != 0 && parser->content_length != ULLONG_MAX); - - /* The difference between advancing content_length and p is because - * the latter will automaticaly advance on the next loop iteration. - * Further, if content_length ends up at 0, we want to see the last - * byte again for our message complete callback. - */ - MARK(body); - parser->content_length -= to_read; - p += to_read - 1; - - if (parser->content_length == 0) - { - UPDATE_STATE(s_message_done); - - /* Mimic CALLBACK_DATA_NOADVANCE() but with one extra byte. - * - * The alternative to doing this is to wait for the next byte to - * trigger the data callback, just as in every other case. The - * problem with this is that this makes it difficult for the test - * harness to distinguish between complete-on-EOF and - * complete-on-length. It's not clear that this distinction is - * important for applications, but let's keep it for now. - */ - CALLBACK_DATA_(body, p - body_mark + 1, p - data); - REEXECUTE(); - } - - break; - } - - /* read until EOF */ - case s_body_identity_eof: - MARK(body); - p = data + len - 1; - - break; - - case s_message_done: - UPDATE_STATE(NEW_MESSAGE()); - CALLBACK_NOTIFY(message_complete); - if (parser->upgrade) - { - /* Exit, the rest of the message is in a different protocol. */ - RETURN((p - data) + 1); - } - break; - - case s_chunk_size_start: - { - assert(nread == 1); - assert(parser->flags & F_CHUNKED); - - unhex_val = unhex[(unsigned char) ch]; - if (UNLIKELY(unhex_val == -1)) - { - SET_ERRNO(HPE_INVALID_CHUNK_SIZE); - goto error; - } - - parser->content_length = unhex_val; - UPDATE_STATE(s_chunk_size); - break; - } - - case s_chunk_size: - { - uint64_t t; - - assert(parser->flags & F_CHUNKED); - - if (ch == CR) - { - UPDATE_STATE(s_chunk_size_almost_done); - break; - } - - unhex_val = unhex[(unsigned char) ch]; - - if (unhex_val == -1) - { - if (ch == ';' || ch == ' ') - { - UPDATE_STATE(s_chunk_parameters); - break; - } - - SET_ERRNO(HPE_INVALID_CHUNK_SIZE); - goto error; - } - - t = parser->content_length; - t *= 16; - t += unhex_val; - - /* Overflow? Test against a conservative limit for simplicity. */ - if (UNLIKELY((ULLONG_MAX - 16) / 16 < parser->content_length)) - { - SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); - goto error; - } - - parser->content_length = t; - break; - } - - case s_chunk_parameters: - { - assert(parser->flags & F_CHUNKED); - /* just ignore this shit. TODO check for overflow */ - if (ch == CR) - { - UPDATE_STATE(s_chunk_size_almost_done); - break; - } - break; - } - - case s_chunk_size_almost_done: - { - assert(parser->flags & F_CHUNKED); - STRICT_CHECK(ch != LF); - - parser->nread = 0; - nread = 0; - - if (parser->content_length == 0) - { - parser->flags |= F_TRAILING; - UPDATE_STATE(s_header_field_start); - } - else - { - UPDATE_STATE(s_chunk_data); - } - CALLBACK_NOTIFY(chunk_header); - break; - } - - case s_chunk_data: - { - uint64_t to_read = MIN(parser->content_length, - (uint64_t)((data + len) - p)); - - assert(parser->flags & F_CHUNKED); - assert(parser->content_length != 0 && parser->content_length != ULLONG_MAX); - - /* See the explanation in s_body_identity for why the content - * length and data pointers are managed this way. - */ - MARK(body); - parser->content_length -= to_read; - p += to_read - 1; - - if (parser->content_length == 0) - { - UPDATE_STATE(s_chunk_data_almost_done); - } - - break; - } - - case s_chunk_data_almost_done: - assert(parser->flags & F_CHUNKED); - assert(parser->content_length == 0); - STRICT_CHECK(ch != CR); - UPDATE_STATE(s_chunk_data_done); - CALLBACK_DATA(body); - break; - - case s_chunk_data_done: - assert(parser->flags & F_CHUNKED); - STRICT_CHECK(ch != LF); - parser->nread = 0; - nread = 0; - UPDATE_STATE(s_chunk_size_start); - CALLBACK_NOTIFY(chunk_complete); - break; - - default: - assert(0 && "unhandled state"); - SET_ERRNO(HPE_INVALID_INTERNAL_STATE); - goto error; - } - } - - /* Run callbacks for any marks that we have leftover after we ran out of - * bytes. There should be at most one of these set, so it's OK to invoke - * them in series (unset marks will not result in callbacks). - * - * We use the NOADVANCE() variety of callbacks here because 'p' has already - * overflowed 'data' and this allows us to correct for the off-by-one that - * we'd otherwise have (since CALLBACK_DATA() is meant to be run with a 'p' - * value that's in-bounds). - */ - - assert(((header_field_mark ? 1 : 0) + - (header_value_mark ? 1 : 0) + - (url_mark ? 1 : 0) + - (body_mark ? 1 : 0) + - (status_mark ? 1 : 0)) <= 1); - - CALLBACK_DATA_NOADVANCE(header_field); - CALLBACK_DATA_NOADVANCE(header_value); - CALLBACK_DATA_NOADVANCE(url); - CALLBACK_DATA_NOADVANCE(body); - CALLBACK_DATA_NOADVANCE(status); - - RETURN(len); - -error: - if (HTTP_PARSER_ERRNO(parser) == HPE_OK) - { - SET_ERRNO(HPE_UNKNOWN); - } - - RETURN(p - data); -} - -/* Does the parser need to see an EOF to find the end of the message? */ -static int http_message_needs_eof(const http_parser *parser) -{ - if (parser->type == HTTP_REQUEST) - { - return 0; - } - - /* See RFC 2616 section 4.4 */ - if (parser->status_code / 100 == 1 || /* 1xx e.g. Continue */ - parser->status_code == 204 || /* No Content */ - parser->status_code == 304 || /* Not Modified */ - parser->flags & F_SKIPBODY) - { /* response to a HEAD request */ - return 0; - } - - if ((parser->flags & F_CHUNKED) || parser->content_length != ULLONG_MAX) - { - return 0; - } - - return 1; -} - -static int http_should_keep_alive(const http_parser *parser) -{ - if (parser->http_major > 0 && parser->http_minor > 0) - { - /* HTTP/1.1 */ - if (parser->flags & F_CONNECTION_CLOSE) - { - return 0; - } - } - else - { - /* HTTP/1.0 or earlier */ - if (!(parser->flags & F_CONNECTION_KEEP_ALIVE)) - { - return 0; - } - } - - return !http_message_needs_eof(parser); -} - -static const char * -http_method_str(enum http_method m) -{ - return ELEM_AT(method_strings, m, ""); -} - -static const char * -http_status_str(enum http_status s) -{ - switch (s) - { -#define XX(num, name, string) \ - case HTTP_STATUS_##name: \ - return #string; - HTTP_STATUS_MAP(XX) -#undef XX - default: - return ""; - } -} - -static void -http_parser_init(http_parser *parser, enum http_parser_type t) -{ - void *data = parser->data; /* preserve application data */ - memset(parser, 0, sizeof(*parser)); - parser->data = data; - parser->type = t; - parser->state = (t == HTTP_REQUEST ? s_start_req : (t == HTTP_RESPONSE ? s_start_res : s_start_req_or_res)); - parser->http_errno = HPE_OK; -} - -static void -http_parser_settings_init(http_parser_settings *settings) -{ - memset(settings, 0, sizeof(*settings)); -} - -static const char * -http_errno_name(enum http_errno err) -{ - assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab)); - return http_strerror_tab[err].name; -} - -static const char * -http_errno_description(enum http_errno err) -{ - assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab)); - return http_strerror_tab[err].description; -} - -static enum http_host_state -http_parse_host_char(enum http_host_state s, const char ch) -{ - switch (s) - { - case s_http_userinfo: - case s_http_userinfo_start: - if (ch == '@') - { - return s_http_host_start; - } - - if (IS_USERINFO_CHAR(ch)) - { - return s_http_userinfo; - } - break; - - case s_http_host_start: - if (ch == '[') - { - return s_http_host_v6_start; - } - - if (IS_HOST_CHAR(ch)) - { - return s_http_host; - } - - break; - - case s_http_host: - if (IS_HOST_CHAR(ch)) - { - return s_http_host; - } - - /* fall through */ - case s_http_host_v6_end: - if (ch == ':') - { - return s_http_host_port_start; - } - - break; - - case s_http_host_v6: - if (ch == ']') - { - return s_http_host_v6_end; - } - - /* fall through */ - case s_http_host_v6_start: - if (IS_HEX(ch) || ch == ':' || ch == '.') - { - return s_http_host_v6; - } - - if (s == s_http_host_v6 && ch == '%') - { - return s_http_host_v6_zone_start; - } - break; - - case s_http_host_v6_zone: - if (ch == ']') - { - return s_http_host_v6_end; - } - - /* fall through */ - case s_http_host_v6_zone_start: - /* RFC 6874 Zone ID consists of 1*( unreserved / pct-encoded) */ - if (IS_ALPHANUM(ch) || ch == '%' || ch == '.' || ch == '-' || ch == '_' || - ch == '~') - { - return s_http_host_v6_zone; - } - break; - - case s_http_host_port: - case s_http_host_port_start: - if (IS_NUM(ch)) - { - return s_http_host_port; - } - - break; - - default: - break; - } - return s_http_host_dead; -} - -static int -http_parse_host(const char *buf, struct http_parser_url *u, int found_at) -{ - enum http_host_state s; - - const char *p; - size_t buflen = u->field_data[UF_HOST].off + u->field_data[UF_HOST].len; - - assert(u->field_set & (1 << UF_HOST)); - - u->field_data[UF_HOST].len = 0; - - s = found_at ? s_http_userinfo_start : s_http_host_start; - - for (p = buf + u->field_data[UF_HOST].off; p < buf + buflen; p++) - { - enum http_host_state new_s = http_parse_host_char(s, *p); - - if (new_s == s_http_host_dead) - { - return 1; - } - - switch (new_s) - { - case s_http_host: - if (s != s_http_host) - { - u->field_data[UF_HOST].off = (uint16_t)(p - buf); - } - u->field_data[UF_HOST].len++; - break; - - case s_http_host_v6: - if (s != s_http_host_v6) - { - u->field_data[UF_HOST].off = (uint16_t)(p - buf); - } - u->field_data[UF_HOST].len++; - break; - - case s_http_host_v6_zone_start: - case s_http_host_v6_zone: - u->field_data[UF_HOST].len++; - break; - - case s_http_host_port: - if (s != s_http_host_port) - { - u->field_data[UF_PORT].off = (uint16_t)(p - buf); - u->field_data[UF_PORT].len = 0; - u->field_set |= (1 << UF_PORT); - } - u->field_data[UF_PORT].len++; - break; - - case s_http_userinfo: - if (s != s_http_userinfo) - { - u->field_data[UF_USERINFO].off = (uint16_t)(p - buf); - u->field_data[UF_USERINFO].len = 0; - u->field_set |= (1 << UF_USERINFO); - } - u->field_data[UF_USERINFO].len++; - break; - - default: - break; - } - s = new_s; - } - - /* Make sure we don't end somewhere unexpected */ - switch (s) - { - case s_http_host_start: - case s_http_host_v6_start: - case s_http_host_v6: - case s_http_host_v6_zone_start: - case s_http_host_v6_zone: - case s_http_host_port_start: - case s_http_userinfo: - case s_http_userinfo_start: - return 1; - default: - break; - } - - return 0; -} - -static void -http_parser_url_init(struct http_parser_url *u) -{ - memset(u, 0, sizeof(*u)); -} - -static int http_parser_parse_url(const char *buf, size_t buflen, int is_connect, - struct http_parser_url *u) -{ - enum state s; - const char *p; - enum http_parser_url_fields uf, old_uf; - int found_at = 0; - - if (buflen == 0) - { - return 1; - } - - u->port = u->field_set = 0; - s = is_connect ? s_req_server_start : s_req_spaces_before_url; - old_uf = UF_MAX; - - for (p = buf; p < buf + buflen; p++) - { - s = parse_url_char(s, *p); - - /* Figure out the next field that we're operating on */ - switch (s) - { - case s_dead: - return 1; - - /* Skip delimeters */ - case s_req_schema_slash: - case s_req_schema_slash_slash: - case s_req_server_start: - case s_req_query_string_start: - case s_req_fragment_start: - continue; - - case s_req_schema: - uf = UF_SCHEMA; - break; - - case s_req_server_with_at: - found_at = 1; - - /* fall through */ - case s_req_server: - uf = UF_HOST; - break; - - case s_req_path: - uf = UF_PATH; - break; - - case s_req_query_string: - uf = UF_QUERY; - break; - - case s_req_fragment: - uf = UF_FRAGMENT; - break; - - default: - assert(!"Unexpected state"); - return 1; - } - - /* Nothing's changed; soldier on */ - if (uf == old_uf) - { - u->field_data[uf].len++; - continue; - } - - u->field_data[uf].off = (uint16_t)(p - buf); - u->field_data[uf].len = 1; - - u->field_set |= (1 << uf); - old_uf = uf; - } - - /* host must be present if there is a schema */ - /* parsing http:///toto will fail */ - if ((u->field_set & (1 << UF_SCHEMA)) && - (u->field_set & (1 << UF_HOST)) == 0) - { - return 1; - } - - if (u->field_set & (1 << UF_HOST)) - { - if (http_parse_host(buf, u, found_at) != 0) - { - return 1; - } - } - - /* CONNECT requests can only contain "hostname:port" */ - if (is_connect && u->field_set != ((1 << UF_HOST) | (1 << UF_PORT))) - { - return 1; - } - - if (u->field_set & (1 << UF_PORT)) - { - uint16_t off; - uint16_t len; - const char *p; - const char *end; - unsigned long v; - - off = u->field_data[UF_PORT].off; - len = u->field_data[UF_PORT].len; - end = buf + off + len; - - /* NOTE: The characters are already validated and are in the [0-9] range */ - assert(off + len <= buflen && "Port number overflow"); - v = 0; - for (p = buf + off; p < end; p++) - { - v *= 10; - v += *p - '0'; - - /* Ports have a max value of 2^16 */ - if (v > 0xffff) - { - return 1; - } - } - - u->port = (uint16_t) v; - } - - return 0; -} - -static void -http_parser_pause(http_parser *parser, int paused) -{ - /* Users should only be pausing/unpausing a parser that is not in an error - * state. In non-debug builds, there's not much that we can do about this - * other than ignore it. - */ - if (HTTP_PARSER_ERRNO(parser) == HPE_OK || - HTTP_PARSER_ERRNO(parser) == HPE_PAUSED) - { - uint32_t nread = parser->nread; /* used by the SET_ERRNO macro */ - SET_ERRNO((paused) ? HPE_PAUSED : HPE_OK); - } - else - { - assert(0 && "Attempting to pause parser in error state"); - } -} - -static int http_body_is_final(const struct http_parser *parser) -{ - return parser->state == s_message_done; -} - -static unsigned long -http_parser_version(void) -{ - return HTTP_PARSER_VERSION_MAJOR * 0x10000 | - HTTP_PARSER_VERSION_MINOR * 0x00100 | - HTTP_PARSER_VERSION_PATCH * 0x00001; -} - -static void -http_parser_set_max_header_size(uint32_t size) -{ - max_header_size = size; -} - -#ifdef __cplusplus -} -#endif -#endif diff --git a/libs/brynet/net/port/Win.hpp b/libs/brynet/net/port/Win.hpp deleted file mode 100644 index 7d21a0e..0000000 --- a/libs/brynet/net/port/Win.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include - - -#ifdef BRYNET_PLATFORM_WINDOWS -class Win { -public: - enum class OverlappedType { - OverlappedNone = 0, - OverlappedRecv, - OverlappedSend, - }; - - struct OverlappedExt { - OVERLAPPED base; - const OverlappedType OP; - - OverlappedExt(OverlappedType op) BRYNET_NOEXCEPT : OP(op) { - memset(&base, 0, sizeof(base)); - } - }; -}; -#endif diff --git a/libs/brynet/net/wrapper/ConnectionBuilder.hpp b/libs/brynet/net/wrapper/ConnectionBuilder.hpp deleted file mode 100644 index a60a1fa..0000000 --- a/libs/brynet/net/wrapper/ConnectionBuilder.hpp +++ /dev/null @@ -1,177 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -using CompletedCallback = AsyncConnectAddr::CompletedCallback; -using ProcessTcpSocketCallback = AsyncConnectAddr::ProcessTcpSocketCallback; -using FailedCallback = AsyncConnectAddr::FailedCallback; - -template -class BaseSocketConnectBuilder { -public: - virtual ~BaseSocketConnectBuilder() = default; - - Derived &WithConnector(AsyncConnector::Ptr connector) { - mConnector = std::move(connector); - return static_cast(*this); - } - - Derived &WithAddr(std::string ip, size_t port) { - mConnectOption.ip = std::move(ip); - mConnectOption.port = port; - return static_cast(*this); - } - - Derived &WithTimeout(std::chrono::nanoseconds timeout) { - mConnectOption.timeout = timeout; - return static_cast(*this); - } - - Derived &AddSocketProcessCallback(const ProcessTcpSocketCallback &callback) { - mConnectOption.processCallbacks.push_back(callback); - return static_cast(*this); - } - - Derived &WithCompletedCallback(CompletedCallback callback) { - mConnectOption.completedCallback = std::move(callback); - return static_cast(*this); - } - - Derived &WithFailedCallback(FailedCallback callback) { - mConnectOption.failedCallback = std::move(callback); - return static_cast(*this); - } - - void asyncConnect() const { - if (mConnector == nullptr) { - throw BrynetCommonException("connector is nullptr"); - } - if (mConnectOption.ip.empty()) { - throw BrynetCommonException("address is empty"); - } - - mConnector->asyncConnect(mConnectOption); - } - - TcpSocket::Ptr syncConnect() { - if (mConnectOption.completedCallback != nullptr || mConnectOption.failedCallback != nullptr) { - throw std::runtime_error("already setting completed callback or failed callback"); - } - - auto socketPromise = std::make_shared >(); - mConnectOption.completedCallback = [socketPromise](TcpSocket::Ptr socket) { - socketPromise->set_value(std::move(socket)); - }; - mConnectOption.failedCallback = [socketPromise]() { - socketPromise->set_value(nullptr); - }; - - asyncConnect(); - - auto future = socketPromise->get_future(); - if (future.wait_for(mConnectOption.timeout) != std::future_status::ready) { - return nullptr; - } - - return future.get(); - } - -private: - AsyncConnector::Ptr mConnector; - ConnectOption mConnectOption; -}; - -class SocketConnectBuilder : public BaseSocketConnectBuilder { -}; - -template -class BaseConnectionBuilder { -public: - Derived &WithService(TcpService::Ptr service) { - mTcpService = std::move(service); - return static_cast(*this); - } - - Derived &WithConnector(AsyncConnector::Ptr connector) { - mConnectBuilder.WithConnector(std::move(connector)); - return static_cast(*this); - } - - Derived &WithAddr(std::string ip, size_t port) { - mConnectBuilder.WithAddr(std::move(ip), port); - return static_cast(*this); - } - - Derived &WithTimeout(std::chrono::nanoseconds timeout) { - mConnectBuilder.WithTimeout(timeout); - return static_cast(*this); - } - - Derived &AddSocketProcessCallback(const ProcessTcpSocketCallback &callback) { - mConnectBuilder.AddSocketProcessCallback(callback); - return static_cast(*this); - } - - Derived &WithFailedCallback(FailedCallback callback) { - mConnectBuilder.WithFailedCallback(std::move(callback)); - return static_cast(*this); - } - - Derived &WithMaxRecvBufferSize(size_t size) { - mOption.maxRecvBufferSize = size; - return static_cast(*this); - } - -#ifdef BRYNET_USE_OPENSSL - Derived &WithSSL() { - mOption.useSSL = true; - return static_cast(*this); - } -#endif - Derived &WithForceSameThreadLoop() { - mOption.forceSameThreadLoop = true; - return static_cast(*this); - } - - Derived &AddEnterCallback(const TcpConnection::EnterCallback &callback) { - mOption.enterCallback.push_back(callback); - return static_cast(*this); - } - - void asyncConnect() { - auto service = mTcpService; - auto option = mOption; - mConnectBuilder.WithCompletedCallback([service, option](TcpSocket::Ptr socket) mutable { - service->addTcpConnection(std::move(socket), option); - }); - - mConnectBuilder.asyncConnect(); - } - - TcpConnection::Ptr syncConnect() { - auto sessionPromise = std::make_shared >(); - - auto option = mOption; - option.enterCallback.push_back([sessionPromise](const TcpConnection::Ptr &session) { - sessionPromise->set_value(session); - }); - - auto socket = mConnectBuilder.syncConnect(); - if (socket == nullptr || !mTcpService->addTcpConnection(std::move(socket), option)) { - return nullptr; - } - return sessionPromise->get_future().get(); - } - -private: - TcpService::Ptr mTcpService; - ConnectionOption mOption; - SocketConnectBuilder mConnectBuilder; -}; - -class ConnectionBuilder : public BaseConnectionBuilder { -}; diff --git a/libs/brynet/net/wrapper/HttpConnectionBuilder.hpp b/libs/brynet/net/wrapper/HttpConnectionBuilder.hpp deleted file mode 100644 index 1f9fc2f..0000000 --- a/libs/brynet/net/wrapper/HttpConnectionBuilder.hpp +++ /dev/null @@ -1,77 +0,0 @@ -#pragma once - -#include -#include -#include - -class HttpConnectionBuilder { -public: - HttpConnectionBuilder &WithService(TcpService::Ptr service) { - mBuilder.WithService(std::move(service)); - return *this; - } - - HttpConnectionBuilder &WithConnector(AsyncConnector::Ptr connector) { - mBuilder.WithConnector(std::move(connector)); - return *this; - } - - HttpConnectionBuilder &WithAddr(std::string ip, size_t port) { - mBuilder.WithAddr(std::move(ip), port); - return *this; - } - - HttpConnectionBuilder &WithTimeout(std::chrono::nanoseconds timeout) { - mBuilder.WithTimeout(timeout); - return *this; - } - - HttpConnectionBuilder &AddSocketProcessCallback(const ProcessTcpSocketCallback &callback) { - mBuilder.AddSocketProcessCallback(callback); - return *this; - } - - HttpConnectionBuilder &WithEnterCallback(HttpSession::EnterCallback &&callback) { - mHttpEnterCallback = std::move(callback); - return *this; - } - - HttpConnectionBuilder &WithFailedCallback(FailedCallback callback) { - mBuilder.WithFailedCallback(std::move(callback)); - return *this; - } - - HttpConnectionBuilder &WithMaxRecvBufferSize(size_t size) { - mBuilder.WithMaxRecvBufferSize(size); - return *this; - } - -#ifdef BRYNET_USE_OPENSSL - HttpConnectionBuilder &WithSSL() { - mBuilder.WithSSL(); - return *this; - } -#endif - HttpConnectionBuilder &WithForceSameThreadLoop() { - mBuilder.WithForceSameThreadLoop(); - return *this; - } - - void asyncConnect() { - if (mHttpEnterCallback == nullptr) { - throw BrynetCommonException("not setting http enter callback"); - } - - auto callback = mHttpEnterCallback; - auto builder = mBuilder; - builder.AddEnterCallback([callback](const TcpConnection::Ptr &session) { - HttpService::setup(session, callback); - }); - builder.asyncConnect(); - } - -private: - HttpSession::EnterCallback mHttpEnterCallback; - ConnectionBuilder mBuilder; -}; - diff --git a/libs/brynet/net/wrapper/HttpServiceBuilder.hpp b/libs/brynet/net/wrapper/HttpServiceBuilder.hpp deleted file mode 100644 index 001ed6c..0000000 --- a/libs/brynet/net/wrapper/HttpServiceBuilder.hpp +++ /dev/null @@ -1,64 +0,0 @@ -#pragma once - -#include -#include -#include - -class HttpListenerBuilder { -public: - HttpListenerBuilder &WithService(TcpService::Ptr service) { - mBuilder.WithService(std::move(service)); - return *this; - } - - HttpListenerBuilder &WithEnterCallback(HttpSession::EnterCallback &&callback) { - mHttpEnterCallback = std::move(callback); - return *this; - } - - HttpListenerBuilder &AddSocketProcess(const ListenThread::TcpSocketProcessCallback &callback) { - mBuilder.AddSocketProcess(callback); - return *this; - } - - HttpListenerBuilder &WithMaxRecvBufferSize(size_t size) { - mBuilder.WithMaxRecvBufferSize(size); - return *this; - } -#ifdef BRYNET_USE_OPENSSL - HttpListenerBuilder &WithSSL(SSLHelper::Ptr sslHelper) { - mBuilder.WithSSL(std::move(sslHelper)); - return *this; - } -#endif - HttpListenerBuilder &WithForceSameThreadLoop() { - mBuilder.WithForceSameThreadLoop(); - return *this; - } - - HttpListenerBuilder &WithAddr(bool ipV6, std::string ip, size_t port) { - mBuilder.WithAddr(ipV6, std::move(ip), port); - return *this; - } - - HttpListenerBuilder &WithReusePort() { - mBuilder.WithReusePort(); - return *this; - } - - void asyncRun() { - if (mHttpEnterCallback == nullptr) { - throw BrynetCommonException("not setting http enter callback"); - } - - auto callback = mHttpEnterCallback; - mBuilder.AddEnterCallback([callback](const TcpConnection::Ptr &session) { - HttpService::setup(session, callback); - }); - mBuilder.asyncRun(); - } - -private: - HttpSession::EnterCallback mHttpEnterCallback; - ListenerBuilder mBuilder; -}; diff --git a/libs/brynet/net/wrapper/ServiceBuilder.hpp b/libs/brynet/net/wrapper/ServiceBuilder.hpp deleted file mode 100644 index f1ebd03..0000000 --- a/libs/brynet/net/wrapper/ServiceBuilder.hpp +++ /dev/null @@ -1,97 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -template -class BaseListenerBuilder { -public: - virtual ~BaseListenerBuilder() = default; - - Derived &WithService(TcpService::Ptr service) { - mTcpService = std::move(service); - return static_cast(*this); - } - - Derived &WithAddr(bool ipV6, std::string ip, size_t port) { - mIsIpV6 = ipV6; - mListenAddr = std::move(ip); - mPort = port; - return static_cast(*this); - } - - Derived &WithReusePort() { - mEnabledReusePort = true; - return static_cast(*this); - } - - Derived &AddSocketProcess(const ListenThread::TcpSocketProcessCallback &callback) { - mSocketProcessCallbacks.push_back(callback); - return static_cast(*this); - } - - Derived &WithMaxRecvBufferSize(size_t size) { - mSocketOption.maxRecvBufferSize = size; - return static_cast(*this); - } -#ifdef BRYNET_USE_OPENSSL - Derived &WithSSL(SSLHelper::Ptr sslHelper) { - mSocketOption.sslHelper = std::move(sslHelper); - mSocketOption.useSSL = true; - return static_cast(*this); - } -#endif - Derived &WithForceSameThreadLoop() { - mSocketOption.forceSameThreadLoop = true; - return static_cast(*this); - } - - Derived &AddEnterCallback(const TcpConnection::EnterCallback &callback) { - mSocketOption.enterCallback.push_back(callback); - return static_cast(*this); - } - - void asyncRun() { - if (mTcpService == nullptr) { - throw BrynetCommonException("tcp service is nullptr"); - } - if (mListenAddr.empty()) { - throw BrynetCommonException("not config listen addr"); - } - - auto service = mTcpService; - auto option = mSocketOption; - mListenThread = ListenThread::Create( - mIsIpV6, - mListenAddr, - mPort, - [service, option](TcpSocket::Ptr socket) { - service->addTcpConnection(std::move(socket), option); - }, - mSocketProcessCallbacks, - mEnabledReusePort); - mListenThread->startListen(); - } - - void stop() { - if (mListenThread) { - mListenThread->stopListen(); - } - } - -private: - TcpService::Ptr mTcpService; - std::vector mSocketProcessCallbacks; - ConnectionOption mSocketOption; - std::string mListenAddr; - int mPort = 0; - bool mIsIpV6 = false; - bool mEnabledReusePort = false; - ListenThread::Ptr mListenThread; -}; - -class ListenerBuilder : public BaseListenerBuilder { -};