mirror of
https://github.com/Relintai/rcpp_framework.git
synced 2025-04-20 01:43:12 +02:00
Ran clang format on brynet.
This commit is contained in:
parent
729c6b17d3
commit
07dcd7774a
@ -8,23 +8,23 @@
|
||||
#include <cstdint>
|
||||
#endif
|
||||
|
||||
namespace brynet { namespace base {
|
||||
namespace brynet {
|
||||
namespace base {
|
||||
|
||||
#ifdef BRYNET_HAVE_LANG_CXX17
|
||||
using BrynetAny = std::any;
|
||||
|
||||
template<typename T>
|
||||
auto cast(const BrynetAny& ud)
|
||||
{
|
||||
return std::any_cast<T>(&ud);
|
||||
template <typename T>
|
||||
auto cast(const BrynetAny &ud) {
|
||||
return std::any_cast<T>(&ud);
|
||||
}
|
||||
#else
|
||||
using BrynetAny = int64_t;
|
||||
template<typename T>
|
||||
const T* cast(const BrynetAny& ud)
|
||||
{
|
||||
return static_cast<const T*>(&ud);
|
||||
template <typename T>
|
||||
const T *cast(const BrynetAny &ud) {
|
||||
return static_cast<const T *>(&ud);
|
||||
}
|
||||
#endif
|
||||
|
||||
}}// namespace brynet::base
|
||||
} // namespace base
|
||||
} // namespace brynet
|
||||
|
@ -14,34 +14,34 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace brynet { namespace base {
|
||||
namespace brynet {
|
||||
namespace base {
|
||||
|
||||
static bool app_kbhit()
|
||||
{
|
||||
static bool app_kbhit() {
|
||||
#ifdef BRYNET_PLATFORM_WINDOWS
|
||||
return _kbhit();
|
||||
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);
|
||||
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();
|
||||
const auto ch = getchar();
|
||||
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
|
||||
fcntl(STDIN_FILENO, F_SETFL, oldf);
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
|
||||
fcntl(STDIN_FILENO, F_SETFL, oldf);
|
||||
|
||||
if (ch != EOF)
|
||||
{
|
||||
ungetc(ch, stdin);
|
||||
return true;
|
||||
}
|
||||
if (ch != EOF) {
|
||||
ungetc(ch, stdin);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
}}// namespace brynet::base
|
||||
} // namespace base
|
||||
} // namespace brynet
|
||||
|
@ -4,125 +4,104 @@
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
namespace brynet { namespace base {
|
||||
namespace brynet {
|
||||
namespace base {
|
||||
|
||||
struct array_s
|
||||
{
|
||||
void* buffer;
|
||||
size_t buffer_size;
|
||||
size_t element_size;
|
||||
size_t element_num;
|
||||
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;
|
||||
}
|
||||
static void array_delete(struct array_s *self) {
|
||||
if (self == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->buffer != nullptr)
|
||||
{
|
||||
free(self->buffer);
|
||||
self->buffer = nullptr;
|
||||
}
|
||||
if (self->buffer != nullptr) {
|
||||
free(self->buffer);
|
||||
self->buffer = nullptr;
|
||||
}
|
||||
|
||||
self->element_num = 0;
|
||||
free(self);
|
||||
self = 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;
|
||||
}
|
||||
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;
|
||||
const auto buffer_size = num * element_size;
|
||||
|
||||
ret->buffer_size = 0;
|
||||
ret->element_size = 0;
|
||||
ret->element_num = 0;
|
||||
ret->buffer = malloc(buffer_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;
|
||||
}
|
||||
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;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void* array_at(struct array_s* self, size_t index)
|
||||
{
|
||||
void* ret = nullptr;
|
||||
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);
|
||||
}
|
||||
if (index < self->element_num) {
|
||||
ret = (char *)(self->buffer) + (index * self->element_size);
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool array_set(struct array_s* self, size_t index, const void* data)
|
||||
{
|
||||
void* old_data = array_at(self, index);
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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);
|
||||
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;
|
||||
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;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static size_t array_num(const struct array_s* self)
|
||||
{
|
||||
return self->element_num;
|
||||
static size_t array_num(const struct array_s *self) {
|
||||
return self->element_num;
|
||||
}
|
||||
|
||||
}}// namespace brynet::base
|
||||
} // namespace base
|
||||
} // namespace brynet
|
||||
|
@ -3,184 +3,145 @@
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
namespace brynet { namespace base {
|
||||
namespace brynet {
|
||||
namespace base {
|
||||
|
||||
struct buffer_s
|
||||
{
|
||||
char* data;
|
||||
size_t data_len;
|
||||
struct buffer_s {
|
||||
char *data;
|
||||
size_t data_len;
|
||||
|
||||
size_t write_pos;
|
||||
size_t read_pos;
|
||||
size_t write_pos;
|
||||
size_t read_pos;
|
||||
};
|
||||
|
||||
static void buffer_delete(struct buffer_s* self)
|
||||
{
|
||||
if (self == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
static void buffer_delete(struct buffer_s *self) {
|
||||
if (self == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->data != nullptr)
|
||||
{
|
||||
free(self->data);
|
||||
self->data = nullptr;
|
||||
}
|
||||
if (self->data != nullptr) {
|
||||
free(self->data);
|
||||
self->data = nullptr;
|
||||
}
|
||||
|
||||
free(self);
|
||||
self = 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;
|
||||
}
|
||||
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);
|
||||
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;
|
||||
}
|
||||
if (ret->data != nullptr) {
|
||||
ret->data_len = buffer_size;
|
||||
} else {
|
||||
buffer_delete(ret);
|
||||
ret = nullptr;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static size_t buffer_getreadvalidcount(struct buffer_s* self)
|
||||
{
|
||||
return self->write_pos - self->read_pos;
|
||||
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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
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;
|
||||
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 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_getwritepos(struct buffer_s *self) {
|
||||
return self->write_pos;
|
||||
}
|
||||
|
||||
static size_t buffer_getreadpos(struct buffer_s* self)
|
||||
{
|
||||
return self->read_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_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 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_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 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_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 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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
return write_ret;
|
||||
}
|
||||
|
||||
}}// namespace brynet::base
|
||||
} // namespace base
|
||||
} // namespace brynet
|
||||
|
@ -1,16 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#if (__cplusplus >= 201103L || \
|
||||
(defined(_MSC_VER) && _MSC_VER >= 1800))
|
||||
(defined(_MSC_VER) && _MSC_VER >= 1800))
|
||||
#define BRYNET_HAVE_LANG_CXX11 1
|
||||
#endif
|
||||
|
||||
#if (__cplusplus >= 201402L || \
|
||||
(defined(_MSC_VER) && _MSC_VER >= 1900))
|
||||
(defined(_MSC_VER) && _MSC_VER >= 1900))
|
||||
#define BRYNET_HAVE_LANG_CXX14 1
|
||||
#endif
|
||||
|
||||
#if (__cplusplus >= 201703L || \
|
||||
(defined(_MSVC_LANG) && _MSVC_LANG >= 201703L))
|
||||
(defined(_MSVC_LANG) && _MSVC_LANG >= 201703L))
|
||||
#define BRYNET_HAVE_LANG_CXX17 1
|
||||
#endif
|
||||
|
@ -1,16 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
namespace brynet { namespace base {
|
||||
namespace brynet {
|
||||
namespace base {
|
||||
|
||||
class NonCopyable
|
||||
{
|
||||
class NonCopyable {
|
||||
public:
|
||||
NonCopyable(const NonCopyable&) = delete;
|
||||
const NonCopyable& operator=(const NonCopyable&) = delete;
|
||||
NonCopyable(const NonCopyable &) = delete;
|
||||
const NonCopyable &operator=(const NonCopyable &) = delete;
|
||||
|
||||
protected:
|
||||
NonCopyable() = default;
|
||||
~NonCopyable() = default;
|
||||
NonCopyable() = default;
|
||||
~NonCopyable() = default;
|
||||
};
|
||||
|
||||
}}// namespace brynet::base
|
||||
} // namespace base
|
||||
} // namespace brynet
|
||||
|
@ -7,426 +7,358 @@
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
namespace brynet { namespace base {
|
||||
namespace brynet {
|
||||
namespace base {
|
||||
|
||||
class BasePacketWriter : public NonCopyable
|
||||
{
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
virtual ~BasePacketWriter() {
|
||||
if (mMallocBuffer != nullptr) {
|
||||
free(mMallocBuffer);
|
||||
mMallocBuffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
mPos = 0;
|
||||
}
|
||||
void init() {
|
||||
mPos = 0;
|
||||
}
|
||||
|
||||
size_t getMaxLen() const
|
||||
{
|
||||
return mMaxLen;
|
||||
}
|
||||
size_t getMaxLen() const {
|
||||
return mMaxLen;
|
||||
}
|
||||
|
||||
size_t getPos() const
|
||||
{
|
||||
return mPos;
|
||||
}
|
||||
size_t getPos() const {
|
||||
return mPos;
|
||||
}
|
||||
|
||||
const char* getData() const
|
||||
{
|
||||
return mBuffer;
|
||||
}
|
||||
const char *getData() const {
|
||||
return mBuffer;
|
||||
}
|
||||
|
||||
bool isAutoGrow() const
|
||||
{
|
||||
return mIsAutoMalloc;
|
||||
}
|
||||
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 = endian::hostToNetwork16(value, mBigEndian);
|
||||
return writeBuffer((char*) &value, sizeof(value));
|
||||
}
|
||||
bool writeUINT16(uint16_t value)
|
||||
{
|
||||
value = endian::hostToNetwork16(value, mBigEndian);
|
||||
return writeBuffer((char*) &value, sizeof(value));
|
||||
}
|
||||
bool writeINT32(int32_t value)
|
||||
{
|
||||
value = endian::hostToNetwork32(value, mBigEndian);
|
||||
return writeBuffer((char*) &value, sizeof(value));
|
||||
}
|
||||
bool writeUINT32(uint32_t value)
|
||||
{
|
||||
value = endian::hostToNetwork32(value, mBigEndian);
|
||||
return writeBuffer((char*) &value, sizeof(value));
|
||||
}
|
||||
bool writeINT64(int64_t value)
|
||||
{
|
||||
value = endian::hostToNetwork64(value, mBigEndian);
|
||||
return writeBuffer((char*) &value, sizeof(value));
|
||||
}
|
||||
bool writeUINT64(uint64_t value)
|
||||
{
|
||||
value = endian::hostToNetwork64(value, mBigEndian);
|
||||
return writeBuffer((char*) &value, sizeof(value));
|
||||
}
|
||||
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 = endian::hostToNetwork16(value, mBigEndian);
|
||||
return writeBuffer((char *)&value, sizeof(value));
|
||||
}
|
||||
bool writeUINT16(uint16_t value) {
|
||||
value = endian::hostToNetwork16(value, mBigEndian);
|
||||
return writeBuffer((char *)&value, sizeof(value));
|
||||
}
|
||||
bool writeINT32(int32_t value) {
|
||||
value = endian::hostToNetwork32(value, mBigEndian);
|
||||
return writeBuffer((char *)&value, sizeof(value));
|
||||
}
|
||||
bool writeUINT32(uint32_t value) {
|
||||
value = endian::hostToNetwork32(value, mBigEndian);
|
||||
return writeBuffer((char *)&value, sizeof(value));
|
||||
}
|
||||
bool writeINT64(int64_t value) {
|
||||
value = endian::hostToNetwork64(value, mBigEndian);
|
||||
return writeBuffer((char *)&value, sizeof(value));
|
||||
}
|
||||
bool writeUINT64(uint64_t value) {
|
||||
value = endian::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);
|
||||
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;
|
||||
}
|
||||
if (mMaxLen < (mPos + len)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(mBuffer + mPos, buffer, len);
|
||||
mPos += len;
|
||||
return true;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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<typename T>
|
||||
BasePacketWriter& operator<<(const T& v)
|
||||
{
|
||||
static_assert(!std::is_pointer<T>::value, "T must is't a pointer");
|
||||
static_assert(std::is_class<T>::value, "T must a class or struct type");
|
||||
static_assert(std::is_pod<T>::value, "T must a pod type");
|
||||
writeBuffer((const char*) &v, sizeof(v));
|
||||
return *this;
|
||||
}
|
||||
// 为了避免直接<<导致没有指定字节序导致隐藏BUG,因为此函数设置为私有
|
||||
template <typename T>
|
||||
BasePacketWriter &operator<<(const T &v) {
|
||||
static_assert(!std::is_pointer<T>::value, "T must is't a pointer");
|
||||
static_assert(std::is_class<T>::value, "T must a class or struct type");
|
||||
static_assert(std::is_pod<T>::value, "T must a pod type");
|
||||
writeBuffer((const char *)&v, sizeof(v));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Arg1, typename... Args>
|
||||
void writev(const Arg1& arg1, const Args&... args)
|
||||
{
|
||||
this->operator<<(arg1);
|
||||
writev(args...);
|
||||
}
|
||||
template <typename Arg1, typename... Args>
|
||||
void writev(const Arg1 &arg1, const Args &...args) {
|
||||
this->operator<<(arg1);
|
||||
writev(args...);
|
||||
}
|
||||
|
||||
void writev()
|
||||
{
|
||||
}
|
||||
void writev() {
|
||||
}
|
||||
|
||||
protected:
|
||||
void growBuffer(size_t len)
|
||||
{
|
||||
if (!mIsAutoMalloc || (mPos + len) <= mMaxLen)
|
||||
{
|
||||
return;
|
||||
}
|
||||
void growBuffer(size_t len) {
|
||||
if (!mIsAutoMalloc || (mPos + len) <= mMaxLen) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto newBuffer = (char*) malloc(mMaxLen + len);
|
||||
if (newBuffer == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
auto newBuffer = (char *)malloc(mMaxLen + len);
|
||||
if (newBuffer == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(newBuffer, mBuffer, mPos);
|
||||
memcpy(newBuffer, mBuffer, mPos);
|
||||
|
||||
if (mMallocBuffer != nullptr)
|
||||
{
|
||||
free(mMallocBuffer);
|
||||
mMallocBuffer = nullptr;
|
||||
}
|
||||
if (mMallocBuffer != nullptr) {
|
||||
free(mMallocBuffer);
|
||||
mMallocBuffer = nullptr;
|
||||
}
|
||||
|
||||
mMaxLen += len;
|
||||
mMallocBuffer = newBuffer;
|
||||
mBuffer = newBuffer;
|
||||
}
|
||||
mMaxLen += len;
|
||||
mMallocBuffer = newBuffer;
|
||||
mBuffer = newBuffer;
|
||||
}
|
||||
|
||||
protected:
|
||||
const bool mIsAutoMalloc;
|
||||
bool mBigEndian;
|
||||
size_t mPos;
|
||||
size_t mMaxLen;
|
||||
char* mBuffer;
|
||||
char* mMallocBuffer;
|
||||
const bool mIsAutoMalloc;
|
||||
bool mBigEndian;
|
||||
size_t mPos;
|
||||
size_t mMaxLen;
|
||||
char *mBuffer;
|
||||
char *mMallocBuffer;
|
||||
};
|
||||
|
||||
class BasePacketReader
|
||||
{
|
||||
class BasePacketReader {
|
||||
public:
|
||||
BasePacketReader(const char* buffer,
|
||||
size_t len,
|
||||
bool useBigEndian = false)
|
||||
: mBigEndian(useBigEndian),
|
||||
mSize(len)
|
||||
{
|
||||
mPos = 0;
|
||||
mSavedPos = 0;
|
||||
mBuffer = buffer;
|
||||
}
|
||||
BasePacketReader(const char *buffer,
|
||||
size_t len,
|
||||
bool useBigEndian = false) :
|
||||
mBigEndian(useBigEndian),
|
||||
mSize(len) {
|
||||
mPos = 0;
|
||||
mSavedPos = 0;
|
||||
mBuffer = buffer;
|
||||
}
|
||||
|
||||
virtual ~BasePacketReader() = default;
|
||||
virtual ~BasePacketReader() = default;
|
||||
|
||||
void useBigEndian()
|
||||
{
|
||||
mBigEndian = true;
|
||||
}
|
||||
void useBigEndian() {
|
||||
mBigEndian = true;
|
||||
}
|
||||
|
||||
void useLittleEndian()
|
||||
{
|
||||
mBigEndian = false;
|
||||
}
|
||||
void useLittleEndian() {
|
||||
mBigEndian = false;
|
||||
}
|
||||
|
||||
void savePos()
|
||||
{
|
||||
mSavedPos = mPos;
|
||||
}
|
||||
void savePos() {
|
||||
mSavedPos = mPos;
|
||||
}
|
||||
|
||||
size_t savedPos() const
|
||||
{
|
||||
return mSavedPos;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
bool enough(size_t len) const {
|
||||
if (mPos > mSize) {
|
||||
return false;
|
||||
}
|
||||
return (mSize - mPos) >= len;
|
||||
}
|
||||
|
||||
const char* begin() const
|
||||
{
|
||||
return mBuffer;
|
||||
}
|
||||
const char *begin() const {
|
||||
return mBuffer;
|
||||
}
|
||||
|
||||
const char* currentBuffer() const
|
||||
{
|
||||
return mBuffer + mPos;
|
||||
}
|
||||
const char *currentBuffer() const {
|
||||
return mBuffer + mPos;
|
||||
}
|
||||
|
||||
void consumeAll()
|
||||
{
|
||||
mPos = mSize;
|
||||
savePos();
|
||||
}
|
||||
void consumeAll() {
|
||||
mPos = mSize;
|
||||
savePos();
|
||||
}
|
||||
|
||||
size_t currentPos() const
|
||||
{
|
||||
return mPos;
|
||||
}
|
||||
size_t currentPos() const {
|
||||
return mPos;
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
return mSize;
|
||||
}
|
||||
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");
|
||||
}
|
||||
void addPos(size_t diff) {
|
||||
const auto tmpPos = mPos + diff;
|
||||
if (tmpPos > mSize) {
|
||||
throw std::out_of_range("diff is to big");
|
||||
}
|
||||
|
||||
mPos = tmpPos;
|
||||
}
|
||||
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 endian::networkToHost16(value, mBigEndian);
|
||||
}
|
||||
uint16_t readUINT16()
|
||||
{
|
||||
uint16_t value = 0;
|
||||
read(value);
|
||||
return endian::networkToHost16(value, mBigEndian);
|
||||
}
|
||||
int32_t readINT32()
|
||||
{
|
||||
int32_t value = 0;
|
||||
read(value);
|
||||
return endian::networkToHost32(value, mBigEndian);
|
||||
}
|
||||
uint32_t readUINT32()
|
||||
{
|
||||
uint32_t value = 0;
|
||||
read(value);
|
||||
return endian::networkToHost32(value, mBigEndian);
|
||||
}
|
||||
int64_t readINT64()
|
||||
{
|
||||
int64_t value = 0;
|
||||
read(value);
|
||||
return endian::networkToHost64(value, mBigEndian);
|
||||
}
|
||||
uint64_t readUINT64()
|
||||
{
|
||||
uint64_t value = 0;
|
||||
read(value);
|
||||
return endian::networkToHost64(value, mBigEndian);
|
||||
}
|
||||
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 endian::networkToHost16(value, mBigEndian);
|
||||
}
|
||||
uint16_t readUINT16() {
|
||||
uint16_t value = 0;
|
||||
read(value);
|
||||
return endian::networkToHost16(value, mBigEndian);
|
||||
}
|
||||
int32_t readINT32() {
|
||||
int32_t value = 0;
|
||||
read(value);
|
||||
return endian::networkToHost32(value, mBigEndian);
|
||||
}
|
||||
uint32_t readUINT32() {
|
||||
uint32_t value = 0;
|
||||
read(value);
|
||||
return endian::networkToHost32(value, mBigEndian);
|
||||
}
|
||||
int64_t readINT64() {
|
||||
int64_t value = 0;
|
||||
read(value);
|
||||
return endian::networkToHost64(value, mBigEndian);
|
||||
}
|
||||
uint64_t readUINT64() {
|
||||
uint64_t value = 0;
|
||||
read(value);
|
||||
return endian::networkToHost64(value, mBigEndian);
|
||||
}
|
||||
|
||||
private:
|
||||
// 为了避免直接read(uintXXX)导致没有指定字节序造成隐患BUG,因为此函数设置为私有
|
||||
template<typename T>
|
||||
void read(T& value)
|
||||
{
|
||||
static_assert(std::is_same<T, typename std::remove_pointer<T>::type>::value,
|
||||
"T must a normal type");
|
||||
static_assert(std::is_pod<T>::value,
|
||||
"T must a pod type");
|
||||
// 为了避免直接read(uintXXX)导致没有指定字节序造成隐患BUG,因为此函数设置为私有
|
||||
template <typename T>
|
||||
void read(T &value) {
|
||||
static_assert(std::is_same<T, typename std::remove_pointer<T>::type>::value,
|
||||
"T must a normal type");
|
||||
static_assert(std::is_pod<T>::value,
|
||||
"T must a pod type");
|
||||
|
||||
if ((mPos + sizeof(value)) > mSize)
|
||||
{
|
||||
throw std::out_of_range("T size is to big");
|
||||
}
|
||||
if ((mPos + sizeof(value)) > mSize) {
|
||||
throw std::out_of_range("T size is to big");
|
||||
}
|
||||
|
||||
value = *(T*) (mBuffer + mPos);
|
||||
mPos += sizeof(value);
|
||||
}
|
||||
value = *(T *)(mBuffer + mPos);
|
||||
mPos += sizeof(value);
|
||||
}
|
||||
|
||||
protected:
|
||||
bool mBigEndian;
|
||||
const size_t mSize;
|
||||
const char* mBuffer;
|
||||
size_t mPos;
|
||||
size_t mSavedPos;
|
||||
bool mBigEndian;
|
||||
const size_t mSize;
|
||||
const char *mBuffer;
|
||||
size_t mPos;
|
||||
size_t mSavedPos;
|
||||
};
|
||||
|
||||
template<size_t SIZE>
|
||||
class AutoMallocPacket : public BasePacketWriter
|
||||
{
|
||||
template <size_t SIZE>
|
||||
class AutoMallocPacket : public BasePacketWriter {
|
||||
public:
|
||||
explicit AutoMallocPacket(bool useBigEndian = false,
|
||||
bool isAutoMalloc = false)
|
||||
: BasePacketWriter(mData, SIZE, useBigEndian, isAutoMalloc)
|
||||
{}
|
||||
explicit AutoMallocPacket(bool useBigEndian = false,
|
||||
bool isAutoMalloc = false) :
|
||||
BasePacketWriter(mData, SIZE, useBigEndian, isAutoMalloc) {}
|
||||
|
||||
private:
|
||||
char mData[SIZE];
|
||||
char mData[SIZE];
|
||||
};
|
||||
|
||||
using BigPacket = AutoMallocPacket<32 * 1024>;
|
||||
|
||||
}}// namespace brynet::base
|
||||
} // namespace base
|
||||
} // namespace brynet
|
||||
|
@ -3,167 +3,144 @@
|
||||
#include <brynet/base/Array.hpp>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace brynet { namespace base {
|
||||
namespace brynet {
|
||||
namespace base {
|
||||
|
||||
struct stack_s
|
||||
{
|
||||
struct array_s* array;
|
||||
size_t element_size;
|
||||
struct stack_s {
|
||||
struct array_s *array;
|
||||
size_t element_size;
|
||||
|
||||
size_t element_num;
|
||||
size_t front;
|
||||
size_t num;
|
||||
size_t element_num;
|
||||
size_t front;
|
||||
size_t num;
|
||||
};
|
||||
|
||||
static void stack_delete(struct stack_s* self)
|
||||
{
|
||||
if (self == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
static void stack_delete(struct stack_s *self) {
|
||||
if (self == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->array != nullptr)
|
||||
{
|
||||
array_delete(self->array);
|
||||
self->array = nullptr;
|
||||
}
|
||||
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;
|
||||
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;
|
||||
}
|
||||
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);
|
||||
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;
|
||||
}
|
||||
if (ret->array != nullptr) {
|
||||
ret->element_size = element_size;
|
||||
ret->element_num = num;
|
||||
} else {
|
||||
stack_delete(ret);
|
||||
ret = nullptr;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void stack_init(struct stack_s* self)
|
||||
{
|
||||
self->front = 0;
|
||||
self->num = 0;
|
||||
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 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;
|
||||
}
|
||||
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));
|
||||
}
|
||||
{
|
||||
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);
|
||||
}
|
||||
self->front = 0;
|
||||
array_delete(self->array);
|
||||
self->array = tmp;
|
||||
self->element_num = array_num(self->array);
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
static size_t stack_size(struct stack_s* self)
|
||||
{
|
||||
return self->element_num;
|
||||
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_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));
|
||||
}
|
||||
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;
|
||||
}
|
||||
if (stack_isfull(self)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
array_set(self->array, (self->front + self->num) % self->element_num, data);
|
||||
self->num++;
|
||||
return true;
|
||||
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;
|
||||
static void *stack_front(struct stack_s *self) {
|
||||
void *ret = nullptr;
|
||||
|
||||
if (stack_num(self) > 0)
|
||||
{
|
||||
ret = array_at(self->array, self->front);
|
||||
}
|
||||
if (stack_num(self) > 0) {
|
||||
ret = array_at(self->array, self->front);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void* stack_popfront(struct stack_s* self)
|
||||
{
|
||||
void* ret = stack_front(self);
|
||||
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;
|
||||
}
|
||||
if (ret != nullptr) {
|
||||
self->num--;
|
||||
self->front++;
|
||||
self->front %= self->element_num;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void* stack_popback(struct stack_s* self)
|
||||
{
|
||||
void* ret = nullptr;
|
||||
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);
|
||||
}
|
||||
if (stack_num(self) > 0) {
|
||||
self->num--;
|
||||
ret = array_at(self->array, (self->front + self->num) % self->element_num);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
}}// namespace brynet::base
|
||||
} // namespace base
|
||||
} // namespace brynet
|
||||
|
@ -8,158 +8,138 @@
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
|
||||
namespace brynet { namespace base {
|
||||
namespace brynet {
|
||||
namespace base {
|
||||
|
||||
class TimerMgr;
|
||||
|
||||
class Timer final
|
||||
{
|
||||
class Timer final {
|
||||
public:
|
||||
using Ptr = std::shared_ptr<Timer>;
|
||||
using WeakPtr = std::weak_ptr<Timer>;
|
||||
using Callback = std::function<void(void)>;
|
||||
using Ptr = std::shared_ptr<Timer>;
|
||||
using WeakPtr = std::weak_ptr<Timer>;
|
||||
using Callback = std::function<void(void)>;
|
||||
|
||||
Timer(std::chrono::steady_clock::time_point startTime,
|
||||
std::chrono::nanoseconds lastTime,
|
||||
Callback&& callback) BRYNET_NOEXCEPT
|
||||
: mCallback(std::move(callback)),
|
||||
mStartTime(startTime),
|
||||
mLastTime(lastTime)
|
||||
{
|
||||
}
|
||||
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::steady_clock::time_point &getStartTime() const {
|
||||
return mStartTime;
|
||||
}
|
||||
|
||||
const std::chrono::nanoseconds& getLastTime() const
|
||||
{
|
||||
return mLastTime;
|
||||
}
|
||||
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());
|
||||
}
|
||||
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;
|
||||
});
|
||||
}
|
||||
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;
|
||||
});
|
||||
void operator()() {
|
||||
Callback callback;
|
||||
std::call_once(mExecuteOnceFlag, [&callback, this]() {
|
||||
callback = std::move(mCallback);
|
||||
mCallback = nullptr;
|
||||
});
|
||||
|
||||
if (callback != nullptr)
|
||||
{
|
||||
callback();
|
||||
}
|
||||
}
|
||||
if (callback != nullptr) {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::once_flag mExecuteOnceFlag;
|
||||
Callback mCallback;
|
||||
const std::chrono::steady_clock::time_point mStartTime;
|
||||
const std::chrono::nanoseconds mLastTime;
|
||||
std::once_flag mExecuteOnceFlag;
|
||||
Callback mCallback;
|
||||
const std::chrono::steady_clock::time_point mStartTime;
|
||||
const std::chrono::nanoseconds mLastTime;
|
||||
|
||||
friend class TimerMgr;
|
||||
friend class TimerMgr;
|
||||
};
|
||||
|
||||
class TimerMgr final
|
||||
{
|
||||
class TimerMgr final {
|
||||
public:
|
||||
using Ptr = std::shared_ptr<TimerMgr>;
|
||||
using Ptr = std::shared_ptr<TimerMgr>;
|
||||
|
||||
template<typename F, typename... TArgs>
|
||||
Timer::WeakPtr addTimer(
|
||||
std::chrono::nanoseconds timeout,
|
||||
F&& callback,
|
||||
TArgs&&... args)
|
||||
{
|
||||
auto timer = std::make_shared<Timer>(
|
||||
std::chrono::steady_clock::now(),
|
||||
std::chrono::nanoseconds(timeout),
|
||||
std::bind(std::forward<F>(callback), std::forward<TArgs>(args)...));
|
||||
mTimers.push(timer);
|
||||
template <typename F, typename... TArgs>
|
||||
Timer::WeakPtr addTimer(
|
||||
std::chrono::nanoseconds timeout,
|
||||
F &&callback,
|
||||
TArgs &&...args) {
|
||||
auto timer = std::make_shared<Timer>(
|
||||
std::chrono::steady_clock::now(),
|
||||
std::chrono::nanoseconds(timeout),
|
||||
std::bind(std::forward<F>(callback), std::forward<TArgs>(args)...));
|
||||
mTimers.push(timer);
|
||||
|
||||
return timer;
|
||||
}
|
||||
return timer;
|
||||
}
|
||||
|
||||
void addTimer(const Timer::Ptr& timer)
|
||||
{
|
||||
mTimers.push(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;
|
||||
}
|
||||
void schedule() {
|
||||
while (!mTimers.empty()) {
|
||||
auto tmp = mTimers.top();
|
||||
if (tmp->getLeftTime() > std::chrono::nanoseconds::zero()) {
|
||||
break;
|
||||
}
|
||||
|
||||
mTimers.pop();
|
||||
(*tmp)();
|
||||
}
|
||||
}
|
||||
mTimers.pop();
|
||||
(*tmp)();
|
||||
}
|
||||
}
|
||||
|
||||
bool isEmpty() const
|
||||
{
|
||||
return mTimers.empty();
|
||||
}
|
||||
bool isEmpty() const {
|
||||
return mTimers.empty();
|
||||
}
|
||||
|
||||
// if timer empty, return zero
|
||||
std::chrono::nanoseconds nearLeftTime() const
|
||||
{
|
||||
if (mTimers.empty())
|
||||
{
|
||||
return std::chrono::nanoseconds::zero();
|
||||
}
|
||||
// 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();
|
||||
}
|
||||
auto result = mTimers.top()->getLeftTime();
|
||||
if (result < std::chrono::nanoseconds::zero()) {
|
||||
return std::chrono::nanoseconds::zero();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
while (!mTimers.empty())
|
||||
{
|
||||
mTimers.pop();
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
};
|
||||
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<Timer::Ptr, std::vector<Timer::Ptr>, CompareTimer> mTimers;
|
||||
std::priority_queue<Timer::Ptr, std::vector<Timer::Ptr>, CompareTimer> mTimers;
|
||||
};
|
||||
|
||||
}}// namespace brynet::base
|
||||
} // namespace base
|
||||
} // namespace brynet
|
||||
|
@ -7,61 +7,55 @@
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
namespace brynet { namespace base {
|
||||
namespace brynet {
|
||||
namespace base {
|
||||
|
||||
class WaitGroup : public NonCopyable
|
||||
{
|
||||
class WaitGroup : public NonCopyable {
|
||||
public:
|
||||
typedef std::shared_ptr<WaitGroup> Ptr;
|
||||
typedef std::shared_ptr<WaitGroup> Ptr;
|
||||
|
||||
static Ptr Create()
|
||||
{
|
||||
struct make_shared_enabler : public WaitGroup
|
||||
{
|
||||
};
|
||||
return std::make_shared<make_shared_enabler>();
|
||||
}
|
||||
static Ptr Create() {
|
||||
struct make_shared_enabler : public WaitGroup {
|
||||
};
|
||||
return std::make_shared<make_shared_enabler>();
|
||||
}
|
||||
|
||||
public:
|
||||
void add(int i = 1)
|
||||
{
|
||||
mCounter += i;
|
||||
}
|
||||
void add(int i = 1) {
|
||||
mCounter += i;
|
||||
}
|
||||
|
||||
void done()
|
||||
{
|
||||
mCounter--;
|
||||
mCond.notify_all();
|
||||
}
|
||||
void done() {
|
||||
mCounter--;
|
||||
mCond.notify_all();
|
||||
}
|
||||
|
||||
void wait()
|
||||
{
|
||||
std::unique_lock<std::mutex> l(mMutex);
|
||||
mCond.wait(l, [&] {
|
||||
return mCounter <= 0;
|
||||
});
|
||||
}
|
||||
void wait() {
|
||||
std::unique_lock<std::mutex> l(mMutex);
|
||||
mCond.wait(l, [&] {
|
||||
return mCounter <= 0;
|
||||
});
|
||||
}
|
||||
|
||||
template<class Rep, class Period>
|
||||
void wait(const std::chrono::duration<Rep, Period>& timeout)
|
||||
{
|
||||
std::unique_lock<std::mutex> l(mMutex);
|
||||
mCond.wait_for(l, timeout, [&] {
|
||||
return mCounter <= 0;
|
||||
});
|
||||
}
|
||||
template <class Rep, class Period>
|
||||
void wait(const std::chrono::duration<Rep, Period> &timeout) {
|
||||
std::unique_lock<std::mutex> l(mMutex);
|
||||
mCond.wait_for(l, timeout, [&] {
|
||||
return mCounter <= 0;
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
WaitGroup()
|
||||
: mCounter(0)
|
||||
{
|
||||
}
|
||||
WaitGroup() :
|
||||
mCounter(0) {
|
||||
}
|
||||
|
||||
virtual ~WaitGroup() = default;
|
||||
virtual ~WaitGroup() = default;
|
||||
|
||||
private:
|
||||
std::mutex mMutex;
|
||||
std::atomic<int> mCounter;
|
||||
std::condition_variable mCond;
|
||||
std::mutex mMutex;
|
||||
std::atomic<int> mCounter;
|
||||
std::condition_variable mCond;
|
||||
};
|
||||
}}// namespace brynet::base
|
||||
} // namespace base
|
||||
} // namespace brynet
|
||||
|
@ -3,108 +3,104 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace brynet { namespace base { namespace crypto {
|
||||
namespace brynet {
|
||||
namespace base {
|
||||
namespace crypto {
|
||||
|
||||
static const std::string base64_chars =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"0123456789+/";
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"0123456789+/";
|
||||
|
||||
static bool is_base64(unsigned char c)
|
||||
{
|
||||
return (isalnum(c) || (c == '+') || (c == '/'));
|
||||
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];
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
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';
|
||||
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;
|
||||
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]];
|
||||
for (j = 0; (j < i + 1); j++)
|
||||
ret += base64_chars[char_array_4[j]];
|
||||
|
||||
while ((i++ < 3))
|
||||
ret += '=';
|
||||
}
|
||||
while ((i++ < 3))
|
||||
ret += '=';
|
||||
}
|
||||
|
||||
return 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;
|
||||
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]);
|
||||
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];
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
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]);
|
||||
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];
|
||||
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];
|
||||
}
|
||||
for (j = 0; (j < i - 1); j++)
|
||||
ret += char_array_3[j];
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
}}}// namespace brynet::base::crypto
|
||||
} // namespace crypto
|
||||
} // namespace base
|
||||
} // namespace brynet
|
||||
|
||||
#endif
|
@ -174,50 +174,49 @@
|
||||
// Define variable types
|
||||
|
||||
#ifndef UINT_8
|
||||
#ifdef _MSC_VER// Compiling with Microsoft compiler
|
||||
#ifdef _MSC_VER // Compiling with Microsoft compiler
|
||||
#define UINT_8 unsigned __int8
|
||||
#else// !_MSC_VER
|
||||
#else // !_MSC_VER
|
||||
#define UINT_8 unsigned char
|
||||
#endif// _MSC_VER
|
||||
#endif // _MSC_VER
|
||||
#endif
|
||||
|
||||
#ifndef UINT_32
|
||||
#ifdef _MSC_VER// Compiling with Microsoft compiler
|
||||
#ifdef _MSC_VER // Compiling with Microsoft compiler
|
||||
#define UINT_32 unsigned __int32
|
||||
#else// !_MSC_VER
|
||||
#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
|
||||
#endif // _MSC_VER
|
||||
#endif // UINT_32
|
||||
|
||||
#ifndef INT_64
|
||||
#ifdef _MSC_VER// Compiling with Microsoft compiler
|
||||
#ifdef _MSC_VER // Compiling with Microsoft compiler
|
||||
#define INT_64 __int64
|
||||
#else// !_MSC_VER
|
||||
#else // !_MSC_VER
|
||||
#define INT_64 long long
|
||||
#endif// _MSC_VER
|
||||
#endif// INT_64
|
||||
#endif // _MSC_VER
|
||||
#endif // INT_64
|
||||
|
||||
#ifndef UINT_64
|
||||
#ifdef _MSC_VER// Compiling with Microsoft compiler
|
||||
#ifdef _MSC_VER // Compiling with Microsoft compiler
|
||||
#define UINT_64 unsigned __int64
|
||||
#else// !_MSC_VER
|
||||
#else // !_MSC_VER
|
||||
#define UINT_64 unsigned long long
|
||||
#endif// _MSC_VER
|
||||
#endif// UINT_64
|
||||
#endif // _MSC_VER
|
||||
#endif // UINT_64
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Declare SHA-1 workspace
|
||||
|
||||
typedef union {
|
||||
UINT_8 c[64];
|
||||
UINT_32 l[16];
|
||||
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
|
||||
@ -231,361 +230,337 @@ typedef union {
|
||||
|
||||
#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))
|
||||
(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))
|
||||
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); \
|
||||
}
|
||||
{ \
|
||||
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); \
|
||||
}
|
||||
{ \
|
||||
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); \
|
||||
}
|
||||
{ \
|
||||
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); \
|
||||
}
|
||||
{ \
|
||||
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); \
|
||||
}
|
||||
{ \
|
||||
z += (w ^ x ^ y) + SHABLK(i) + 0xCA62C1D6 + ROL32(v, 5); \
|
||||
w = ROL32(w, 30); \
|
||||
}
|
||||
|
||||
|
||||
class CSHA1
|
||||
{
|
||||
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
|
||||
};
|
||||
// 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;
|
||||
// Constructor and destructor
|
||||
CSHA1() {
|
||||
(void)m_reserved0;
|
||||
(void)m_reserved1;
|
||||
m_block = (SHA1_WORKSPACE_BLOCK *)m_workspace;
|
||||
|
||||
Reset();
|
||||
}
|
||||
Reset();
|
||||
}
|
||||
|
||||
#ifdef SHA1_WIPE_VARIABLES
|
||||
~CSHA1()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
~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;
|
||||
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;
|
||||
}
|
||||
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);
|
||||
// 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
|
||||
if ((m_count[0] += (uLen << 3)) < (uLen << 3))
|
||||
++m_count[1]; // Overflow
|
||||
|
||||
m_count[1] += (uLen >> 29);
|
||||
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);
|
||||
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]);
|
||||
for (; (i + 63) < uLen; i += 64)
|
||||
Transform(m_state, &pbData[i]);
|
||||
|
||||
j = 0;
|
||||
}
|
||||
else
|
||||
i = 0;
|
||||
j = 0;
|
||||
} else
|
||||
i = 0;
|
||||
|
||||
if ((uLen - i) != 0)
|
||||
memcpy(&m_buffer[j], &pbData[i], uLen - i);
|
||||
}
|
||||
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;
|
||||
// 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;
|
||||
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;
|
||||
}
|
||||
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);
|
||||
bool bSuccess = true;
|
||||
while (true) {
|
||||
const size_t uRead = fread(pbData, 1, SHA1_MAX_FILE_BUFFER, fpIn);
|
||||
|
||||
if (uRead > 0)
|
||||
Update(pbData, static_cast<UINT_32>(uRead));
|
||||
if (uRead > 0)
|
||||
Update(pbData, static_cast<UINT_32>(uRead));
|
||||
|
||||
if (uRead < SHA1_MAX_FILE_BUFFER)
|
||||
{
|
||||
if (feof(fpIn) == 0)
|
||||
bSuccess = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (uRead < SHA1_MAX_FILE_BUFFER) {
|
||||
if (feof(fpIn) == 0)
|
||||
bSuccess = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fpIn);
|
||||
delete[] pbData;
|
||||
return bSuccess;
|
||||
}
|
||||
fclose(fpIn);
|
||||
delete[] pbData;
|
||||
return bSuccess;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Finalize hash; call it before using ReportHash(Stl)
|
||||
void Final()
|
||||
{
|
||||
UINT_32 i;
|
||||
// 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<UINT_8>((m_count[((i >= 4) ? 0 : 1)] >>
|
||||
((3 - (i & 3)) * 8)) &
|
||||
0xFF);// Endian independent
|
||||
UINT_8 pbFinalCount[8];
|
||||
for (i = 0; i < 8; ++i)
|
||||
pbFinalCount[i] = static_cast<UINT_8>((m_count[((i >= 4) ? 0 : 1)] >>
|
||||
((3 - (i & 3)) * 8)) &
|
||||
0xFF); // Endian independent
|
||||
|
||||
Update((UINT_8*) "\200", 1);
|
||||
Update((UINT_8 *)"\200", 1);
|
||||
|
||||
while ((m_count[0] & 504) != 448)
|
||||
Update((UINT_8*) "\0", 1);
|
||||
while ((m_count[0] & 504) != 448)
|
||||
Update((UINT_8 *)"\0", 1);
|
||||
|
||||
Update(pbFinalCount, 8);// Cause a Transform()
|
||||
Update(pbFinalCount, 8); // Cause a Transform()
|
||||
|
||||
for (i = 0; i < 20; ++i)
|
||||
m_digest[i] = static_cast<UINT_8>((m_state[i >> 2] >> ((3 -
|
||||
(i & 3)) *
|
||||
8)) &
|
||||
0xFF);
|
||||
for (i = 0; i < 20; ++i)
|
||||
m_digest[i] = static_cast<UINT_8>((m_state[i >> 2] >> ((3 -
|
||||
(i & 3)) *
|
||||
8)) &
|
||||
0xFF);
|
||||
|
||||
// Wipe variables for security reasons
|
||||
// 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);
|
||||
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;
|
||||
bool ReportHash(TCHAR *tszReport, REPORT_TYPE rtReportType = REPORT_HEX) const {
|
||||
if (tszReport == NULL)
|
||||
return false;
|
||||
|
||||
TCHAR tszTemp[16];
|
||||
TCHAR tszTemp[16];
|
||||
|
||||
if ((rtReportType == REPORT_HEX) || (rtReportType == REPORT_HEX_SHORT))
|
||||
{
|
||||
_sntprintf(tszTemp, 15, _T("%02X"), m_digest[0]);
|
||||
_tcscpy(tszReport, tszTemp);
|
||||
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);
|
||||
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;
|
||||
for (size_t i = 1; i < 20; ++i) {
|
||||
_sntprintf(tszTemp, 15, _T(" %u"), m_digest[i]);
|
||||
_tcscat(tszReport, tszTemp);
|
||||
}
|
||||
} else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SHA1_STL_FUNCTIONS
|
||||
bool ReportHashStl(std::basic_string<TCHAR>& strOut, REPORT_TYPE rtReportType =
|
||||
REPORT_HEX) const
|
||||
{
|
||||
TCHAR tszOut[84];
|
||||
const bool bResult = ReportHash(tszOut, rtReportType);
|
||||
if (bResult)
|
||||
strOut = tszOut;
|
||||
return bResult;
|
||||
}
|
||||
bool ReportHashStl(std::basic_string<TCHAR> &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;
|
||||
}
|
||||
// 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];
|
||||
// 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);
|
||||
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);
|
||||
// 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;
|
||||
// Add the working vars back into state
|
||||
pState[0] += a;
|
||||
pState[1] += b;
|
||||
pState[2] += c;
|
||||
pState[3] += d;
|
||||
pState[4] += e;
|
||||
|
||||
// Wipe variables
|
||||
// Wipe variables
|
||||
#ifdef SHA1_WIPE_VARIABLES
|
||||
a = b = c = d = e = 0;
|
||||
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
|
||||
// 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
|
||||
UINT_8 m_workspace[64];
|
||||
SHA1_WORKSPACE_BLOCK *m_block; // SHA1 pointer to the byte array above
|
||||
};
|
||||
|
||||
#endif// SHA1_H_A545E61D43E9404E8D736869AB3CBFE7
|
||||
#endif // SHA1_H_A545E61D43E9404E8D736869AB3CBFE7
|
||||
|
@ -12,127 +12,111 @@
|
||||
#include <sys/_endian.h>
|
||||
#endif
|
||||
|
||||
namespace brynet { namespace base { namespace endian {
|
||||
namespace brynet {
|
||||
namespace base {
|
||||
namespace endian {
|
||||
|
||||
inline uint64_t hl64ton(uint64_t hostValue)
|
||||
{
|
||||
uint64_t ret = 0;
|
||||
uint32_t high, low;
|
||||
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;
|
||||
low = hostValue & 0xFFFFFFFF;
|
||||
high = (hostValue >> 32) & 0xFFFFFFFF;
|
||||
low = htonl(low);
|
||||
high = htonl(high);
|
||||
ret = low;
|
||||
ret <<= 32;
|
||||
ret |= high;
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline uint64_t ntohl64(uint64_t netValue)
|
||||
{
|
||||
uint64_t ret = 0;
|
||||
uint32_t high, low;
|
||||
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;
|
||||
low = netValue & 0xFFFFFFFF;
|
||||
high = (netValue >> 32) & 0xFFFFFFFF;
|
||||
low = ntohl(low);
|
||||
high = ntohl(high);
|
||||
ret = low;
|
||||
ret <<= 32;
|
||||
ret |= high;
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef BRYNET_PLATFORM_WINDOWS
|
||||
inline uint64_t hostToNetwork64(uint64_t host64, bool convert = true)
|
||||
{
|
||||
return convert ? hl64ton(host64) : host64;
|
||||
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 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 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 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 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;
|
||||
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 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 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 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 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 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;
|
||||
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 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 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 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 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 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;
|
||||
inline uint16_t networkToHost16(uint16_t net16, bool convert = true) {
|
||||
return convert ? ntohs(net16) : net16;
|
||||
}
|
||||
#endif
|
||||
|
||||
}}}// namespace brynet::base::endian
|
||||
} // namespace endian
|
||||
} // namespace base
|
||||
} // namespace brynet
|
@ -2,40 +2,36 @@
|
||||
|
||||
#include <brynet/net/detail/ConnectorDetail.hpp>
|
||||
|
||||
namespace brynet { namespace net {
|
||||
namespace brynet {
|
||||
namespace net {
|
||||
|
||||
using ConnectOption = detail::ConnectOption;
|
||||
class AsyncConnector : public detail::AsyncConnectorDetail,
|
||||
public std::enable_shared_from_this<AsyncConnector>
|
||||
{
|
||||
public std::enable_shared_from_this<AsyncConnector> {
|
||||
public:
|
||||
using Ptr = std::shared_ptr<AsyncConnector>;
|
||||
using Ptr = std::shared_ptr<AsyncConnector>;
|
||||
|
||||
void startWorkerThread()
|
||||
{
|
||||
detail::AsyncConnectorDetail::startWorkerThread();
|
||||
}
|
||||
void startWorkerThread() {
|
||||
detail::AsyncConnectorDetail::startWorkerThread();
|
||||
}
|
||||
|
||||
void stopWorkerThread()
|
||||
{
|
||||
detail::AsyncConnectorDetail::stopWorkerThread();
|
||||
}
|
||||
void stopWorkerThread() {
|
||||
detail::AsyncConnectorDetail::stopWorkerThread();
|
||||
}
|
||||
|
||||
void asyncConnect(const ConnectOption& option)
|
||||
{
|
||||
detail::AsyncConnectorDetail::asyncConnect(option);
|
||||
}
|
||||
void asyncConnect(const ConnectOption &option) {
|
||||
detail::AsyncConnectorDetail::asyncConnect(option);
|
||||
}
|
||||
|
||||
static Ptr Create()
|
||||
{
|
||||
class make_shared_enabler : public AsyncConnector
|
||||
{
|
||||
};
|
||||
return std::make_shared<make_shared_enabler>();
|
||||
}
|
||||
static Ptr Create() {
|
||||
class make_shared_enabler : public AsyncConnector {
|
||||
};
|
||||
return std::make_shared<make_shared_enabler>();
|
||||
}
|
||||
|
||||
private:
|
||||
AsyncConnector() = default;
|
||||
AsyncConnector() = default;
|
||||
};
|
||||
|
||||
}}// namespace brynet::net
|
||||
} // namespace net
|
||||
} // namespace brynet
|
||||
|
@ -1,20 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
namespace brynet { namespace net {
|
||||
namespace brynet {
|
||||
namespace net {
|
||||
|
||||
class EventLoop;
|
||||
|
||||
class Channel
|
||||
{
|
||||
class Channel {
|
||||
public:
|
||||
virtual ~Channel() = default;
|
||||
virtual ~Channel() = default;
|
||||
|
||||
private:
|
||||
virtual void canSend() = 0;
|
||||
virtual void canRecv(bool willClose) = 0;
|
||||
virtual void onClose() = 0;
|
||||
virtual void canSend() = 0;
|
||||
virtual void canRecv(bool willClose) = 0;
|
||||
virtual void onClose() = 0;
|
||||
|
||||
friend class EventLoop;
|
||||
friend class EventLoop;
|
||||
};
|
||||
|
||||
}}// namespace brynet::net
|
||||
} // namespace net
|
||||
} // namespace brynet
|
||||
|
@ -18,7 +18,9 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace brynet { namespace net { namespace current_thread {
|
||||
namespace brynet {
|
||||
namespace net {
|
||||
namespace current_thread {
|
||||
|
||||
#ifdef BRYNET_PLATFORM_WINDOWS
|
||||
using THREAD_ID_TYPE = DWORD;
|
||||
@ -26,31 +28,31 @@ using THREAD_ID_TYPE = DWORD;
|
||||
using THREAD_ID_TYPE = int;
|
||||
#endif
|
||||
|
||||
static THREAD_ID_TYPE& tid()
|
||||
{
|
||||
static THREAD_ID_TYPE &tid() {
|
||||
#ifdef BRYNET_PLATFORM_WINDOWS
|
||||
static __declspec(thread) THREAD_ID_TYPE cachedTid = 0;
|
||||
static __declspec(thread) THREAD_ID_TYPE cachedTid = 0;
|
||||
#elif defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN
|
||||
static __thread THREAD_ID_TYPE cachedTid = 0;
|
||||
static __thread THREAD_ID_TYPE cachedTid = 0;
|
||||
#endif
|
||||
|
||||
if (cachedTid == 0)
|
||||
{
|
||||
if (cachedTid == 0) {
|
||||
#ifdef BRYNET_PLATFORM_WINDOWS
|
||||
cachedTid = GetCurrentThreadId();
|
||||
cachedTid = GetCurrentThreadId();
|
||||
#elif defined BRYNET_PLATFORM_LINUX
|
||||
cachedTid = static_cast<pid_t>(::syscall(SYS_gettid));
|
||||
cachedTid = static_cast<pid_t>(::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;
|
||||
// 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;
|
||||
return cachedTid;
|
||||
}
|
||||
|
||||
}}}// namespace brynet::net::current_thread
|
||||
} // namespace current_thread
|
||||
} // namespace net
|
||||
} // namespace brynet
|
||||
|
@ -18,427 +18,371 @@
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace brynet { namespace net {
|
||||
namespace brynet {
|
||||
namespace net {
|
||||
|
||||
class Channel;
|
||||
class TcpConnection;
|
||||
using TcpConnectionPtr = std::shared_ptr<TcpConnection>;
|
||||
|
||||
class EventLoop : public brynet::base::NonCopyable
|
||||
{
|
||||
class EventLoop : public brynet::base::NonCopyable {
|
||||
public:
|
||||
using Ptr = std::shared_ptr<EventLoop>;
|
||||
using UserFunctor = std::function<void(void)>;
|
||||
using Ptr = std::shared_ptr<EventLoop>;
|
||||
using UserFunctor = std::function<void(void)>;
|
||||
|
||||
public:
|
||||
EventLoop()
|
||||
BRYNET_NOEXCEPT
|
||||
:
|
||||
EventLoop()
|
||||
BRYNET_NOEXCEPT
|
||||
:
|
||||
#ifdef BRYNET_PLATFORM_WINDOWS
|
||||
mIOCP(CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 1)),
|
||||
mWakeupChannel(std::make_unique<detail::WakeupChannel>(mIOCP))
|
||||
mIOCP(CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 1)),
|
||||
mWakeupChannel(std::make_unique<detail::WakeupChannel>(mIOCP))
|
||||
#elif defined BRYNET_PLATFORM_LINUX
|
||||
mEpollFd(epoll_create(1))
|
||||
mEpollFd(epoll_create(1))
|
||||
#elif defined BRYNET_PLATFORM_DARWIN
|
||||
mKqueueFd(kqueue())
|
||||
mKqueueFd(kqueue())
|
||||
#endif
|
||||
{
|
||||
{
|
||||
#ifdef BRYNET_PLATFORM_WINDOWS
|
||||
mPGetQueuedCompletionStatusEx = NULL;
|
||||
auto kernel32_module = GetModuleHandleA("kernel32.dll");
|
||||
if (kernel32_module != NULL)
|
||||
{
|
||||
mPGetQueuedCompletionStatusEx = reinterpret_cast<sGetQueuedCompletionStatusEx>(GetProcAddress(
|
||||
kernel32_module,
|
||||
"GetQueuedCompletionStatusEx"));
|
||||
FreeLibrary(kernel32_module);
|
||||
}
|
||||
mPGetQueuedCompletionStatusEx = NULL;
|
||||
auto kernel32_module = GetModuleHandleA("kernel32.dll");
|
||||
if (kernel32_module != NULL) {
|
||||
mPGetQueuedCompletionStatusEx = reinterpret_cast<sGetQueuedCompletionStatusEx>(GetProcAddress(
|
||||
kernel32_module,
|
||||
"GetQueuedCompletionStatusEx"));
|
||||
FreeLibrary(kernel32_module);
|
||||
}
|
||||
#elif defined BRYNET_PLATFORM_LINUX
|
||||
auto eventfd = ::eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
|
||||
mWakeupChannel.reset(new detail::WakeupChannel(eventfd));
|
||||
linkChannel(eventfd, mWakeupChannel.get());
|
||||
auto eventfd = ::eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
|
||||
mWakeupChannel.reset(new detail::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 detail::WakeupChannel(mKqueueFd, NOTIFY_IDENT));
|
||||
//Add user event
|
||||
struct kevent ev;
|
||||
EV_SET(&ev, NOTIFY_IDENT, EVFILT_USER, EV_ADD | EV_CLEAR, 0, 0, NULL);
|
||||
const int NOTIFY_IDENT = 42; // Magic number we use for our filter ID.
|
||||
mWakeupChannel.reset(new detail::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);
|
||||
struct timespec timeout = { 0, 0 };
|
||||
kevent(mKqueueFd, &ev, 1, NULL, 0, &timeout);
|
||||
#endif
|
||||
|
||||
mIsAlreadyPostWakeup = false;
|
||||
mIsInBlock = true;
|
||||
mIsAlreadyPostWakeup = false;
|
||||
mIsInBlock = true;
|
||||
|
||||
reAllocEventSize(1024);
|
||||
mSelfThreadID = -1;
|
||||
mTimer = std::make_shared<brynet::base::TimerMgr>();
|
||||
}
|
||||
reAllocEventSize(1024);
|
||||
mSelfThreadID = -1;
|
||||
mTimer = std::make_shared<brynet::base::TimerMgr>();
|
||||
}
|
||||
|
||||
virtual ~EventLoop() BRYNET_NOEXCEPT
|
||||
{
|
||||
virtual ~EventLoop() BRYNET_NOEXCEPT {
|
||||
#ifdef BRYNET_PLATFORM_WINDOWS
|
||||
CloseHandle(mIOCP);
|
||||
mIOCP = INVALID_HANDLE_VALUE;
|
||||
CloseHandle(mIOCP);
|
||||
mIOCP = INVALID_HANDLE_VALUE;
|
||||
#elif defined BRYNET_PLATFORM_LINUX
|
||||
close(mEpollFd);
|
||||
mEpollFd = -1;
|
||||
close(mEpollFd);
|
||||
mEpollFd = -1;
|
||||
#elif defined BRYNET_PLATFORM_DARWIN
|
||||
close(mKqueueFd);
|
||||
mKqueueFd = -1;
|
||||
close(mKqueueFd);
|
||||
mKqueueFd = -1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void loop(int64_t milliseconds)
|
||||
{
|
||||
tryInitThreadID();
|
||||
void loop(int64_t milliseconds) {
|
||||
tryInitThreadID();
|
||||
|
||||
#ifndef NDEBUG
|
||||
assert(isInLoopThread());
|
||||
assert(isInLoopThread());
|
||||
#endif
|
||||
if (!isInLoopThread())
|
||||
{
|
||||
throw BrynetCommonException("only loop in io thread");
|
||||
}
|
||||
if (!isInLoopThread()) {
|
||||
throw BrynetCommonException("only loop in io thread");
|
||||
}
|
||||
|
||||
if (!mAfterLoopFunctors.empty())
|
||||
{
|
||||
milliseconds = 0;
|
||||
}
|
||||
if (!mAfterLoopFunctors.empty()) {
|
||||
milliseconds = 0;
|
||||
}
|
||||
|
||||
#ifdef BRYNET_PLATFORM_WINDOWS
|
||||
ULONG numComplete = 0;
|
||||
if (mPGetQueuedCompletionStatusEx != nullptr)
|
||||
{
|
||||
if (!mPGetQueuedCompletionStatusEx(mIOCP,
|
||||
mEventEntries.data(),
|
||||
static_cast<ULONG>(mEventEntries.size()),
|
||||
&numComplete,
|
||||
static_cast<DWORD>(milliseconds),
|
||||
false))
|
||||
{
|
||||
numComplete = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto& e : mEventEntries)
|
||||
{
|
||||
const auto timeout = (numComplete == 0) ? static_cast<DWORD>(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;
|
||||
}
|
||||
}
|
||||
ULONG numComplete = 0;
|
||||
if (mPGetQueuedCompletionStatusEx != nullptr) {
|
||||
if (!mPGetQueuedCompletionStatusEx(mIOCP,
|
||||
mEventEntries.data(),
|
||||
static_cast<ULONG>(mEventEntries.size()),
|
||||
&numComplete,
|
||||
static_cast<DWORD>(milliseconds),
|
||||
false)) {
|
||||
numComplete = 0;
|
||||
}
|
||||
} else {
|
||||
for (auto &e : mEventEntries) {
|
||||
const auto timeout = (numComplete == 0) ? static_cast<DWORD>(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;
|
||||
mIsInBlock = false;
|
||||
|
||||
for (ULONG i = 0; i < numComplete; ++i)
|
||||
{
|
||||
auto channel = (Channel*) mEventEntries[i].lpCompletionKey;
|
||||
assert(channel != nullptr);
|
||||
const auto ovl = reinterpret_cast<const port::Win::OverlappedExt*>(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);
|
||||
}
|
||||
}
|
||||
for (ULONG i = 0; i < numComplete; ++i) {
|
||||
auto channel = (Channel *)mEventEntries[i].lpCompletionKey;
|
||||
assert(channel != nullptr);
|
||||
const auto ovl = reinterpret_cast<const port::Win::OverlappedExt *>(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);
|
||||
int numComplete = epoll_wait(mEpollFd, mEventEntries.data(), mEventEntries.size(), milliseconds);
|
||||
|
||||
mIsInBlock = false;
|
||||
mIsInBlock = false;
|
||||
|
||||
for (int i = 0; i < numComplete; ++i)
|
||||
{
|
||||
auto channel = (Channel*) (mEventEntries[i].data.ptr);
|
||||
auto event_data = mEventEntries[i].events;
|
||||
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 & EPOLLRDHUP) {
|
||||
channel->canRecv(true);
|
||||
channel->onClose();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (event_data & EPOLLIN)
|
||||
{
|
||||
channel->canRecv(false);
|
||||
}
|
||||
if (event_data & EPOLLIN) {
|
||||
channel->canRecv(false);
|
||||
}
|
||||
|
||||
if (event_data & EPOLLOUT)
|
||||
{
|
||||
channel->canSend();
|
||||
}
|
||||
}
|
||||
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);
|
||||
struct timespec timeout = { milliseconds / 1000, (milliseconds % 1000) * 1000 * 1000 };
|
||||
int numComplete = kevent(mKqueueFd, NULL, 0, mEventEntries.data(), mEventEntries.size(), &timeout);
|
||||
|
||||
mIsInBlock = false;
|
||||
mIsInBlock = false;
|
||||
|
||||
for (int i = 0; i < numComplete; ++i)
|
||||
{
|
||||
auto channel = (Channel*) (mEventEntries[i].udata);
|
||||
const struct kevent& event = mEventEntries[i];
|
||||
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_USER) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (event.filter == EVFILT_READ)
|
||||
{
|
||||
channel->canRecv(false);
|
||||
}
|
||||
if (event.filter == EVFILT_READ) {
|
||||
channel->canRecv(false);
|
||||
}
|
||||
|
||||
if (event.filter == EVFILT_WRITE)
|
||||
{
|
||||
channel->canSend();
|
||||
}
|
||||
}
|
||||
if (event.filter == EVFILT_WRITE) {
|
||||
channel->canSend();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
mIsAlreadyPostWakeup = false;
|
||||
mIsInBlock = true;
|
||||
mIsAlreadyPostWakeup = false;
|
||||
mIsInBlock = true;
|
||||
|
||||
processAsyncFunctors();
|
||||
processAfterLoopFunctors();
|
||||
processAsyncFunctors();
|
||||
processAfterLoopFunctors();
|
||||
|
||||
if (static_cast<size_t>(numComplete) == mEventEntries.size())
|
||||
{
|
||||
reAllocEventSize(mEventEntries.size() + 128);
|
||||
}
|
||||
if (static_cast<size_t>(numComplete) == mEventEntries.size()) {
|
||||
reAllocEventSize(mEventEntries.size() + 128);
|
||||
}
|
||||
|
||||
mTimer->schedule();
|
||||
}
|
||||
mTimer->schedule();
|
||||
}
|
||||
|
||||
// loop指定毫秒数,但如果定时器不为空,则loop时间为当前最近定时器的剩余时间和milliseconds的较小值
|
||||
void loopCompareNearTimer(int64_t milliseconds)
|
||||
{
|
||||
tryInitThreadID();
|
||||
// loop指定毫秒数,但如果定时器不为空,则loop时间为当前最近定时器的剩余时间和milliseconds的较小值
|
||||
void loopCompareNearTimer(int64_t milliseconds) {
|
||||
tryInitThreadID();
|
||||
|
||||
#ifndef NDEBUG
|
||||
assert(isInLoopThread());
|
||||
assert(isInLoopThread());
|
||||
#endif
|
||||
if (!isInLoopThread())
|
||||
{
|
||||
throw BrynetCommonException("only loop in IO thread");
|
||||
}
|
||||
if (!isInLoopThread()) {
|
||||
throw BrynetCommonException("only loop in IO thread");
|
||||
}
|
||||
|
||||
if (!mTimer->isEmpty())
|
||||
{
|
||||
auto nearTimeout = std::chrono::duration_cast<std::chrono::milliseconds>(mTimer->nearLeftTime());
|
||||
milliseconds = std::min<int64_t>(milliseconds, nearTimeout.count());
|
||||
}
|
||||
if (!mTimer->isEmpty()) {
|
||||
auto nearTimeout = std::chrono::duration_cast<std::chrono::milliseconds>(mTimer->nearLeftTime());
|
||||
milliseconds = std::min<int64_t>(milliseconds, nearTimeout.count());
|
||||
}
|
||||
|
||||
loop(milliseconds);
|
||||
}
|
||||
loop(milliseconds);
|
||||
}
|
||||
|
||||
// 返回true表示实际发生了wakeup所需的操作(此返回值不代表接口本身操作成功与否,因为此函数永远成功)
|
||||
bool wakeup()
|
||||
{
|
||||
if (!isInLoopThread() && mIsInBlock && !mIsAlreadyPostWakeup.exchange(true))
|
||||
{
|
||||
return mWakeupChannel->wakeup();
|
||||
}
|
||||
// 返回true表示实际发生了wakeup所需的操作(此返回值不代表接口本身操作成功与否,因为此函数永远成功)
|
||||
bool wakeup() {
|
||||
if (!isInLoopThread() && mIsInBlock && !mIsAlreadyPostWakeup.exchange(true)) {
|
||||
return mWakeupChannel->wakeup();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
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");
|
||||
}
|
||||
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));
|
||||
}
|
||||
brynet::base::Timer::WeakPtr runAfter(std::chrono::nanoseconds timeout, UserFunctor&& callback)
|
||||
{
|
||||
auto timer = std::make_shared<brynet::base::Timer>(
|
||||
std::chrono::steady_clock::now(),
|
||||
std::chrono::nanoseconds(timeout),
|
||||
std::move(callback));
|
||||
mAfterLoopFunctors.emplace_back(std::move(f));
|
||||
}
|
||||
brynet::base::Timer::WeakPtr runAfter(std::chrono::nanoseconds timeout, UserFunctor &&callback) {
|
||||
auto timer = std::make_shared<brynet::base::Timer>(
|
||||
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);
|
||||
});
|
||||
}
|
||||
if (isInLoopThread()) {
|
||||
mTimer->addTimer(timer);
|
||||
} else {
|
||||
auto timerMgr = mTimer;
|
||||
runAsyncFunctor([timerMgr, timer]() {
|
||||
timerMgr->addTimer(timer);
|
||||
});
|
||||
}
|
||||
|
||||
return timer;
|
||||
}
|
||||
return timer;
|
||||
}
|
||||
|
||||
inline bool isInLoopThread() const
|
||||
{
|
||||
return mSelfThreadID == current_thread::tid();
|
||||
}
|
||||
inline bool isInLoopThread() const {
|
||||
return mSelfThreadID == current_thread::tid();
|
||||
}
|
||||
|
||||
private:
|
||||
void reAllocEventSize(size_t size)
|
||||
{
|
||||
mEventEntries.resize(size);
|
||||
}
|
||||
void reAllocEventSize(size_t size) {
|
||||
mEventEntries.resize(size);
|
||||
}
|
||||
|
||||
void processAfterLoopFunctors()
|
||||
{
|
||||
mCopyAfterLoopFunctors.swap(mAfterLoopFunctors);
|
||||
for (const auto& x : mCopyAfterLoopFunctors)
|
||||
{
|
||||
x();
|
||||
}
|
||||
mCopyAfterLoopFunctors.clear();
|
||||
}
|
||||
void processAsyncFunctors()
|
||||
{
|
||||
swapAsyncFunctors();
|
||||
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<std::mutex> lck(mAsyncFunctorsMutex);
|
||||
assert(mCopyAsyncFunctors.empty());
|
||||
mCopyAsyncFunctors.swap(mAsyncFunctors);
|
||||
}
|
||||
void pushAsyncFunctor(UserFunctor&& f)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(mAsyncFunctorsMutex);
|
||||
mAsyncFunctors.emplace_back(std::move(f));
|
||||
}
|
||||
for (const auto &x : mCopyAsyncFunctors) {
|
||||
x();
|
||||
}
|
||||
mCopyAsyncFunctors.clear();
|
||||
}
|
||||
void swapAsyncFunctors() {
|
||||
std::lock_guard<std::mutex> lck(mAsyncFunctorsMutex);
|
||||
assert(mCopyAsyncFunctors.empty());
|
||||
mCopyAsyncFunctors.swap(mAsyncFunctors);
|
||||
}
|
||||
void pushAsyncFunctor(UserFunctor &&f) {
|
||||
std::lock_guard<std::mutex> lck(mAsyncFunctorsMutex);
|
||||
mAsyncFunctors.emplace_back(std::move(f));
|
||||
}
|
||||
|
||||
#ifdef BRYNET_PLATFORM_LINUX
|
||||
int getEpollHandle() const
|
||||
{
|
||||
return mEpollFd;
|
||||
}
|
||||
int getEpollHandle() const {
|
||||
return mEpollFd;
|
||||
}
|
||||
#elif defined BRYNET_PLATFORM_DARWIN
|
||||
int getKqueueHandle() const
|
||||
{
|
||||
return mKqueueFd;
|
||||
}
|
||||
int getKqueueHandle() const {
|
||||
return mKqueueFd;
|
||||
}
|
||||
#endif
|
||||
bool linkChannel(BrynetSocketFD fd, const Channel* ptr) BRYNET_NOEXCEPT
|
||||
{
|
||||
bool linkChannel(BrynetSocketFD fd, const Channel *ptr) BRYNET_NOEXCEPT {
|
||||
#ifdef BRYNET_PLATFORM_WINDOWS
|
||||
return CreateIoCompletionPort((HANDLE) fd, mIOCP, (ULONG_PTR) ptr, 0) != nullptr;
|
||||
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;
|
||||
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 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;
|
||||
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 = current_thread::tid();
|
||||
});
|
||||
}
|
||||
}
|
||||
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 = current_thread::tid();
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
#ifdef BRYNET_PLATFORM_WINDOWS
|
||||
std::vector<OVERLAPPED_ENTRY> mEventEntries;
|
||||
std::vector<OVERLAPPED_ENTRY> mEventEntries;
|
||||
|
||||
typedef BOOL(WINAPI* sGetQueuedCompletionStatusEx)(HANDLE, LPOVERLAPPED_ENTRY, ULONG, PULONG, DWORD, BOOL);
|
||||
sGetQueuedCompletionStatusEx mPGetQueuedCompletionStatusEx;
|
||||
HANDLE mIOCP;
|
||||
typedef BOOL(WINAPI *sGetQueuedCompletionStatusEx)(HANDLE, LPOVERLAPPED_ENTRY, ULONG, PULONG, DWORD, BOOL);
|
||||
sGetQueuedCompletionStatusEx mPGetQueuedCompletionStatusEx;
|
||||
HANDLE mIOCP;
|
||||
#elif defined BRYNET_PLATFORM_LINUX
|
||||
std::vector<epoll_event> mEventEntries;
|
||||
int mEpollFd;
|
||||
std::vector<epoll_event> mEventEntries;
|
||||
int mEpollFd;
|
||||
#elif defined BRYNET_PLATFORM_DARWIN
|
||||
std::vector<struct kevent> mEventEntries;
|
||||
int mKqueueFd;
|
||||
std::vector<struct kevent> mEventEntries;
|
||||
int mKqueueFd;
|
||||
#endif
|
||||
std::unique_ptr<detail::WakeupChannel> mWakeupChannel;
|
||||
std::unique_ptr<detail::WakeupChannel> mWakeupChannel;
|
||||
|
||||
std::atomic_bool mIsInBlock;
|
||||
std::atomic_bool mIsAlreadyPostWakeup;
|
||||
std::atomic_bool mIsInBlock;
|
||||
std::atomic_bool mIsAlreadyPostWakeup;
|
||||
|
||||
std::mutex mAsyncFunctorsMutex;
|
||||
std::vector<UserFunctor> mAsyncFunctors;
|
||||
std::vector<UserFunctor> mCopyAsyncFunctors;
|
||||
std::mutex mAsyncFunctorsMutex;
|
||||
std::vector<UserFunctor> mAsyncFunctors;
|
||||
std::vector<UserFunctor> mCopyAsyncFunctors;
|
||||
|
||||
std::vector<UserFunctor> mAfterLoopFunctors;
|
||||
std::vector<UserFunctor> mCopyAfterLoopFunctors;
|
||||
std::vector<UserFunctor> mAfterLoopFunctors;
|
||||
std::vector<UserFunctor> mCopyAfterLoopFunctors;
|
||||
|
||||
std::once_flag mOnceInitThreadID;
|
||||
current_thread::THREAD_ID_TYPE mSelfThreadID;
|
||||
std::once_flag mOnceInitThreadID;
|
||||
current_thread::THREAD_ID_TYPE mSelfThreadID;
|
||||
|
||||
brynet::base::TimerMgr::Ptr mTimer;
|
||||
std::unordered_map<BrynetSocketFD, TcpConnectionPtr> mTcpConnections;
|
||||
brynet::base::TimerMgr::Ptr mTimer;
|
||||
std::unordered_map<BrynetSocketFD, TcpConnectionPtr> mTcpConnections;
|
||||
|
||||
friend class TcpConnection;
|
||||
friend class TcpConnection;
|
||||
};
|
||||
|
||||
}}// namespace brynet::net
|
||||
} // namespace net
|
||||
} // namespace brynet
|
||||
|
@ -3,34 +3,30 @@
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
namespace brynet { namespace net {
|
||||
namespace brynet {
|
||||
namespace net {
|
||||
|
||||
class ConnectException : public std::runtime_error
|
||||
{
|
||||
class ConnectException : public std::runtime_error {
|
||||
public:
|
||||
explicit ConnectException(const std::string& message)
|
||||
: std::runtime_error(message)
|
||||
{
|
||||
}
|
||||
explicit ConnectException(const std::string &message) :
|
||||
std::runtime_error(message) {
|
||||
}
|
||||
|
||||
explicit ConnectException(const char* message)
|
||||
: std::runtime_error(message)
|
||||
{
|
||||
}
|
||||
explicit ConnectException(const char *message) :
|
||||
std::runtime_error(message) {
|
||||
}
|
||||
};
|
||||
|
||||
class BrynetCommonException : public std::runtime_error
|
||||
{
|
||||
class BrynetCommonException : public std::runtime_error {
|
||||
public:
|
||||
explicit BrynetCommonException(const std::string& message)
|
||||
: std::runtime_error(message)
|
||||
{
|
||||
}
|
||||
explicit BrynetCommonException(const std::string &message) :
|
||||
std::runtime_error(message) {
|
||||
}
|
||||
|
||||
explicit BrynetCommonException(const char* message)
|
||||
: std::runtime_error(message)
|
||||
{
|
||||
}
|
||||
explicit BrynetCommonException(const char *message) :
|
||||
std::runtime_error(message) {
|
||||
}
|
||||
};
|
||||
|
||||
}}// namespace brynet::net
|
||||
} // namespace net
|
||||
} // namespace brynet
|
||||
|
@ -2,58 +2,53 @@
|
||||
|
||||
#include <brynet/net/detail/ListenThreadDetail.hpp>
|
||||
|
||||
namespace brynet { namespace net {
|
||||
namespace brynet {
|
||||
namespace net {
|
||||
|
||||
class ListenThread : public detail::ListenThreadDetail,
|
||||
public std::enable_shared_from_this<ListenThread>
|
||||
{
|
||||
public std::enable_shared_from_this<ListenThread> {
|
||||
public:
|
||||
using Ptr = std::shared_ptr<ListenThread>;
|
||||
using AccepCallback = std::function<void(TcpSocket::Ptr)>;
|
||||
using TcpSocketProcessCallback = std::function<void(TcpSocket&)>;
|
||||
using Ptr = std::shared_ptr<ListenThread>;
|
||||
using AccepCallback = std::function<void(TcpSocket::Ptr)>;
|
||||
using TcpSocketProcessCallback = std::function<void(TcpSocket &)>;
|
||||
|
||||
void startListen()
|
||||
{
|
||||
detail::ListenThreadDetail::startListen();
|
||||
}
|
||||
void startListen() {
|
||||
detail::ListenThreadDetail::startListen();
|
||||
}
|
||||
|
||||
void stopListen()
|
||||
{
|
||||
detail::ListenThreadDetail::stopListen();
|
||||
}
|
||||
void stopListen() {
|
||||
detail::ListenThreadDetail::stopListen();
|
||||
}
|
||||
|
||||
public:
|
||||
static Ptr Create(bool isIPV6,
|
||||
const std::string& ip,
|
||||
int port,
|
||||
const AccepCallback& callback,
|
||||
const std::vector<TcpSocketProcessCallback>& 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<TcpSocketProcessCallback>& processCallbacks,
|
||||
bool enabledReusePort)
|
||||
: ListenThread(isIPV6, ip, port, callback, processCallbacks, enabledReusePort)
|
||||
{}
|
||||
};
|
||||
return std::make_shared<make_shared_enabler>(isIPV6, ip, port, callback, processCallbacks, enabledReusePort);
|
||||
}
|
||||
static Ptr Create(bool isIPV6,
|
||||
const std::string &ip,
|
||||
int port,
|
||||
const AccepCallback &callback,
|
||||
const std::vector<TcpSocketProcessCallback> &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<TcpSocketProcessCallback> &processCallbacks,
|
||||
bool enabledReusePort) :
|
||||
ListenThread(isIPV6, ip, port, callback, processCallbacks, enabledReusePort) {}
|
||||
};
|
||||
return std::make_shared<make_shared_enabler>(isIPV6, ip, port, callback, processCallbacks, enabledReusePort);
|
||||
}
|
||||
|
||||
protected:
|
||||
ListenThread(bool isIPV6,
|
||||
const std::string& ip,
|
||||
int port,
|
||||
const AccepCallback& callback,
|
||||
const std::vector<TcpSocketProcessCallback>& processCallbacks,
|
||||
bool enabledReusePort)
|
||||
: detail::ListenThreadDetail(isIPV6, ip, port, callback, processCallbacks, enabledReusePort)
|
||||
{}
|
||||
ListenThread(bool isIPV6,
|
||||
const std::string &ip,
|
||||
int port,
|
||||
const AccepCallback &callback,
|
||||
const std::vector<TcpSocketProcessCallback> &processCallbacks,
|
||||
bool enabledReusePort) :
|
||||
detail::ListenThreadDetail(isIPV6, ip, port, callback, processCallbacks, enabledReusePort) {}
|
||||
};
|
||||
|
||||
}}// namespace brynet::net
|
||||
} // namespace net
|
||||
} // namespace brynet
|
||||
|
@ -9,7 +9,8 @@
|
||||
#include <poll.h>
|
||||
#endif
|
||||
|
||||
namespace brynet { namespace base {
|
||||
namespace brynet {
|
||||
namespace base {
|
||||
|
||||
#ifdef BRYNET_PLATFORM_WINDOWS
|
||||
const static int CHECK_READ_FLAG = (POLLIN | POLLRDNORM | POLLRDBAND);
|
||||
@ -21,242 +22,197 @@ 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,
|
||||
enum CheckType {
|
||||
ReadCheck = 0x1,
|
||||
WriteCheck = 0x2,
|
||||
ErrorCheck = 0x4,
|
||||
};
|
||||
|
||||
struct poller_s
|
||||
{
|
||||
struct pollfd* pollFds;
|
||||
int nfds;
|
||||
int limitSize;
|
||||
struct poller_s {
|
||||
struct pollfd *pollFds;
|
||||
int nfds;
|
||||
int limitSize;
|
||||
};
|
||||
|
||||
static void upstep_pollfd(struct poller_s* self, int upSize)
|
||||
{
|
||||
if (upSize <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void poller_delete(struct poller_s* self)
|
||||
{
|
||||
free(self->pollFds);
|
||||
self->pollFds = nullptr;
|
||||
self->nfds = 0;
|
||||
self->limitSize = 0;
|
||||
static void poller_delete(struct poller_s *self) {
|
||||
free(self->pollFds);
|
||||
self->pollFds = nullptr;
|
||||
self->nfds = 0;
|
||||
self->limitSize = 0;
|
||||
|
||||
free(self);
|
||||
self = nullptr;
|
||||
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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
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++;
|
||||
}
|
||||
self->nfds++;
|
||||
}
|
||||
|
||||
if (type & ReadCheck)
|
||||
{
|
||||
pf->events |= CHECK_READ_FLAG;
|
||||
}
|
||||
if (type & ReadCheck) {
|
||||
pf->events |= CHECK_READ_FLAG;
|
||||
}
|
||||
|
||||
if (type & WriteCheck)
|
||||
{
|
||||
pf->events |= CHECK_WRITE_FLAG;
|
||||
}
|
||||
if (type & WriteCheck) {
|
||||
pf->events |= CHECK_WRITE_FLAG;
|
||||
}
|
||||
|
||||
if (type & ErrorCheck)
|
||||
{
|
||||
//pf->events |= CHECK_ERROR_FLAG; TODO::on windows, not supports
|
||||
}
|
||||
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;
|
||||
}
|
||||
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 & ReadCheck) {
|
||||
pf->events &= ~CHECK_READ_FLAG;
|
||||
}
|
||||
|
||||
if (type & WriteCheck)
|
||||
{
|
||||
pf->events &= ~CHECK_WRITE_FLAG;
|
||||
}
|
||||
if (type & WriteCheck) {
|
||||
pf->events &= ~CHECK_WRITE_FLAG;
|
||||
}
|
||||
|
||||
if (type & ErrorCheck)
|
||||
{
|
||||
pf->events &= ~CHECK_ERROR_FLAG;
|
||||
}
|
||||
if (type & ErrorCheck) {
|
||||
pf->events &= ~CHECK_ERROR_FLAG;
|
||||
}
|
||||
|
||||
if (pf->events == 0)
|
||||
{
|
||||
try_remove_pollfd(self, fd);
|
||||
}
|
||||
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 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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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 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)
|
||||
{
|
||||
static int poller_poll(struct poller_s *self, long overtime) {
|
||||
#ifdef BRYNET_PLATFORM_WINDOWS
|
||||
int ret = WSAPoll(&self->pollFds[0], self->nfds, overtime);
|
||||
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);
|
||||
int ret = poll(self->pollFds, self->nfds, overtime);
|
||||
#endif
|
||||
|
||||
if (ret == BRYNET_SOCKET_ERROR)
|
||||
{
|
||||
ret = (BRYNET_ERRNO != BRYNET_EINTR) ? -1 : 0;
|
||||
}
|
||||
if (ret == BRYNET_SOCKET_ERROR) {
|
||||
ret = (BRYNET_ERRNO != BRYNET_EINTR) ? -1 : 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
}}// namespace brynet::base
|
||||
} // namespace base
|
||||
} // namespace brynet
|
||||
|
@ -2,155 +2,133 @@
|
||||
|
||||
#include <brynet/net/TcpService.hpp>
|
||||
|
||||
namespace brynet { namespace net {
|
||||
namespace brynet {
|
||||
namespace net {
|
||||
|
||||
/* 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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
isOK = false;
|
||||
}
|
||||
|
||||
class PromiseReceive;
|
||||
|
||||
std::shared_ptr<PromiseReceive> setupPromiseReceive(const TcpConnection::Ptr& session);
|
||||
std::shared_ptr<PromiseReceive> setupPromiseReceive(const TcpConnection::Ptr &session);
|
||||
|
||||
class PromiseReceive : public std::enable_shared_from_this<PromiseReceive>
|
||||
{
|
||||
class PromiseReceive : public std::enable_shared_from_this<PromiseReceive> {
|
||||
public:
|
||||
using Ptr = std::shared_ptr<PromiseReceive>;
|
||||
using Handle = std::function<bool(const char* buffer, size_t len)>;
|
||||
using Ptr = std::shared_ptr<PromiseReceive>;
|
||||
using Handle = std::function<bool(const char *buffer, size_t len)>;
|
||||
|
||||
PromiseReceive::Ptr receive(size_t len, Handle handle)
|
||||
{
|
||||
return receive(std::make_shared<size_t>(len), std::move(handle));
|
||||
}
|
||||
PromiseReceive::Ptr receive(size_t len, Handle handle) {
|
||||
return receive(std::make_shared<size_t>(len), std::move(handle));
|
||||
}
|
||||
|
||||
PromiseReceive::Ptr receive(std::shared_ptr<size_t> len, Handle handle)
|
||||
{
|
||||
return helpReceive(std::move(len), "", std::move(handle));
|
||||
}
|
||||
PromiseReceive::Ptr receive(std::shared_ptr<size_t> 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");
|
||||
}
|
||||
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));
|
||||
}
|
||||
return helpReceive(nullptr, std::move(str), std::move(handle));
|
||||
}
|
||||
|
||||
private:
|
||||
PromiseReceive::Ptr helpReceive(std::shared_ptr<size_t> len, std::string str, Handle handle)
|
||||
{
|
||||
auto pr = std::make_shared<PendingReceive>();
|
||||
pr->len = std::move(len);
|
||||
pr->str = std::move(str);
|
||||
pr->handle = std::move(handle);
|
||||
mPendingReceives.push_back(std::move(pr));
|
||||
PromiseReceive::Ptr helpReceive(std::shared_ptr<size_t> len, std::string str, Handle handle) {
|
||||
auto pr = std::make_shared<PendingReceive>();
|
||||
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();
|
||||
}
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
size_t process(const char* buffer, const size_t len)
|
||||
{
|
||||
size_t procLen = 0;
|
||||
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;
|
||||
}
|
||||
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);
|
||||
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;
|
||||
}
|
||||
if (!isOK) {
|
||||
break;
|
||||
}
|
||||
|
||||
mPendingReceives.pop_front();
|
||||
procLen += (pos + pendingReceive->str.size());
|
||||
if (pendingReceive->handle(data, pos))
|
||||
{
|
||||
mPendingReceives.push_front(pendingReceive);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
mPendingReceives.pop_front();
|
||||
procLen += (pos + pendingReceive->str.size());
|
||||
if (pendingReceive->handle(data, pos)) {
|
||||
mPendingReceives.push_front(pendingReceive);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return procLen;
|
||||
}
|
||||
return procLen;
|
||||
}
|
||||
|
||||
private:
|
||||
struct PendingReceive
|
||||
{
|
||||
std::shared_ptr<size_t> len;
|
||||
std::string str;
|
||||
Handle handle;
|
||||
};
|
||||
struct PendingReceive {
|
||||
std::shared_ptr<size_t> len;
|
||||
std::string str;
|
||||
Handle handle;
|
||||
};
|
||||
|
||||
std::deque<std::shared_ptr<PendingReceive>> mPendingReceives;
|
||||
std::deque<std::shared_ptr<PendingReceive> > mPendingReceives;
|
||||
|
||||
friend std::shared_ptr<PromiseReceive> setupPromiseReceive(const TcpConnection::Ptr& session);
|
||||
friend std::shared_ptr<PromiseReceive> setupPromiseReceive(const TcpConnection::Ptr &session);
|
||||
};
|
||||
|
||||
std::shared_ptr<PromiseReceive> setupPromiseReceive(const TcpConnection::Ptr& session)
|
||||
{
|
||||
auto promiseReceive = std::make_shared<PromiseReceive>();
|
||||
session->setDataCallback([promiseReceive](brynet::base::BasePacketReader& reader) {
|
||||
auto procLen = promiseReceive->process(reader.begin(), reader.size());
|
||||
reader.addPos(procLen);
|
||||
reader.savePos();
|
||||
});
|
||||
std::shared_ptr<PromiseReceive> setupPromiseReceive(const TcpConnection::Ptr &session) {
|
||||
auto promiseReceive = std::make_shared<PromiseReceive>();
|
||||
session->setDataCallback([promiseReceive](brynet::base::BasePacketReader &reader) {
|
||||
auto procLen = promiseReceive->process(reader.begin(), reader.size());
|
||||
reader.addPos(procLen);
|
||||
reader.savePos();
|
||||
});
|
||||
|
||||
return promiseReceive;
|
||||
return promiseReceive;
|
||||
}
|
||||
|
||||
}}// namespace brynet::net
|
||||
} // namespace net
|
||||
} // namespace brynet
|
||||
|
@ -22,154 +22,135 @@ extern "C" {
|
||||
|
||||
#endif
|
||||
|
||||
namespace brynet { namespace net {
|
||||
namespace brynet {
|
||||
namespace net {
|
||||
|
||||
#ifdef BRYNET_USE_OPENSSL
|
||||
|
||||
#ifndef CRYPTO_THREADID_set_callback
|
||||
static void cryptoSetThreadIDCallback(CRYPTO_THREADID* id)
|
||||
{
|
||||
static void cryptoSetThreadIDCallback(CRYPTO_THREADID *id) {
|
||||
#ifdef BRYNET_PLATFORM_WINDOWS
|
||||
CRYPTO_THREADID_set_numeric(id,
|
||||
static_cast<unsigned long>(GetCurrentThreadId()));
|
||||
CRYPTO_THREADID_set_numeric(id,
|
||||
static_cast<unsigned long>(GetCurrentThreadId()));
|
||||
#elif defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN
|
||||
CRYPTO_THREADID_set_numeric(id,
|
||||
static_cast<unsigned long>(pthread_self()));
|
||||
CRYPTO_THREADID_set_numeric(id,
|
||||
static_cast<unsigned long>(pthread_self()));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef CRYPTO_set_locking_callback
|
||||
static std::unordered_map<int, std::shared_ptr<std::mutex>> cryptoLocks;
|
||||
static std::unordered_map<int, std::shared_ptr<std::mutex> > 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();
|
||||
}
|
||||
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()
|
||||
{
|
||||
static void InitCryptoThreadSafeSupport() {
|
||||
#ifndef CRYPTO_THREADID_set_callback
|
||||
CRYPTO_THREADID_set_callback(cryptoSetThreadIDCallback);
|
||||
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<std::mutex>();
|
||||
}
|
||||
CRYPTO_set_locking_callback(cryptoLockingCallback);
|
||||
for (int i = 0; i < CRYPTO_num_locks(); i++) {
|
||||
cryptoLocks[i] = std::make_shared<std::mutex>();
|
||||
}
|
||||
CRYPTO_set_locking_callback(cryptoLockingCallback);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
class SSLHelper : public brynet::base::NonCopyable,
|
||||
public std::enable_shared_from_this<SSLHelper>
|
||||
{
|
||||
public std::enable_shared_from_this<SSLHelper> {
|
||||
public:
|
||||
using Ptr = std::shared_ptr<SSLHelper>;
|
||||
using Ptr = std::shared_ptr<SSLHelper>;
|
||||
|
||||
#ifdef BRYNET_USE_OPENSSL
|
||||
bool initSSL(const std::string& certificate,
|
||||
const std::string& privatekey)
|
||||
{
|
||||
std::call_once(initCryptoThreadSafeSupportOnceFlag,
|
||||
InitCryptoThreadSafeSupport);
|
||||
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;
|
||||
}
|
||||
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);
|
||||
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_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_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;
|
||||
}
|
||||
if (!SSL_CTX_check_private_key(mOpenSSLCTX)) {
|
||||
SSL_CTX_free(mOpenSSLCTX);
|
||||
mOpenSSLCTX = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void destroySSL()
|
||||
{
|
||||
if (mOpenSSLCTX != nullptr)
|
||||
{
|
||||
SSL_CTX_free(mOpenSSLCTX);
|
||||
mOpenSSLCTX = nullptr;
|
||||
}
|
||||
}
|
||||
void destroySSL() {
|
||||
if (mOpenSSLCTX != nullptr) {
|
||||
SSL_CTX_free(mOpenSSLCTX);
|
||||
mOpenSSLCTX = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
SSL_CTX* getOpenSSLCTX()
|
||||
{
|
||||
return mOpenSSLCTX;
|
||||
}
|
||||
SSL_CTX *getOpenSSLCTX() {
|
||||
return mOpenSSLCTX;
|
||||
}
|
||||
#endif
|
||||
static Ptr Create()
|
||||
{
|
||||
class make_shared_enabler : public SSLHelper
|
||||
{
|
||||
};
|
||||
return std::make_shared<make_shared_enabler>();
|
||||
}
|
||||
static Ptr Create() {
|
||||
class make_shared_enabler : public SSLHelper {
|
||||
};
|
||||
return std::make_shared<make_shared_enabler>();
|
||||
}
|
||||
|
||||
protected:
|
||||
SSLHelper() BRYNET_NOEXCEPT
|
||||
{
|
||||
SSLHelper() BRYNET_NOEXCEPT {
|
||||
#ifdef BRYNET_USE_OPENSSL
|
||||
mOpenSSLCTX = nullptr;
|
||||
mOpenSSLCTX = nullptr;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~SSLHelper() BRYNET_NOEXCEPT
|
||||
{
|
||||
virtual ~SSLHelper() BRYNET_NOEXCEPT {
|
||||
#ifdef BRYNET_USE_OPENSSL
|
||||
destroySSL();
|
||||
destroySSL();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
#ifdef BRYNET_USE_OPENSSL
|
||||
SSL_CTX* mOpenSSLCTX;
|
||||
SSL_CTX *mOpenSSLCTX;
|
||||
#endif
|
||||
};
|
||||
|
||||
}}// namespace brynet::net
|
||||
} // namespace net
|
||||
} // namespace brynet
|
||||
|
@ -1,60 +1,52 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace brynet { namespace net {
|
||||
namespace brynet {
|
||||
namespace net {
|
||||
|
||||
class SendableMsg
|
||||
{
|
||||
class SendableMsg {
|
||||
public:
|
||||
using Ptr = std::shared_ptr<SendableMsg>;
|
||||
using Ptr = std::shared_ptr<SendableMsg>;
|
||||
|
||||
virtual ~SendableMsg() = default;
|
||||
virtual ~SendableMsg() = default;
|
||||
|
||||
virtual const void* data() = 0;
|
||||
virtual size_t size() = 0;
|
||||
virtual const void *data() = 0;
|
||||
virtual size_t size() = 0;
|
||||
};
|
||||
|
||||
class StringSendMsg : public SendableMsg
|
||||
{
|
||||
class StringSendMsg : public SendableMsg {
|
||||
public:
|
||||
explicit StringSendMsg(const char* buffer, size_t len)
|
||||
: mMsg(buffer, len)
|
||||
{}
|
||||
explicit StringSendMsg(const char *buffer, size_t len) :
|
||||
mMsg(buffer, len) {}
|
||||
|
||||
explicit StringSendMsg(const std::string& buffer)
|
||||
: mMsg(buffer)
|
||||
{}
|
||||
explicit StringSendMsg(const std::string &buffer) :
|
||||
mMsg(buffer) {}
|
||||
|
||||
explicit StringSendMsg(std::string&& buffer)
|
||||
: mMsg(std::move(buffer))
|
||||
{}
|
||||
explicit StringSendMsg(std::string &&buffer) :
|
||||
mMsg(std::move(buffer)) {}
|
||||
|
||||
const void* data() override
|
||||
{
|
||||
return static_cast<const void*>(mMsg.data());
|
||||
}
|
||||
size_t size() override
|
||||
{
|
||||
return mMsg.size();
|
||||
}
|
||||
const void *data() override {
|
||||
return static_cast<const void *>(mMsg.data());
|
||||
}
|
||||
size_t size() override {
|
||||
return mMsg.size();
|
||||
}
|
||||
|
||||
private:
|
||||
std::string mMsg;
|
||||
std::string mMsg;
|
||||
};
|
||||
|
||||
static SendableMsg::Ptr MakeStringMsg(const char* buffer, size_t len)
|
||||
{
|
||||
return std::make_shared<StringSendMsg>(buffer, len);
|
||||
static SendableMsg::Ptr MakeStringMsg(const char *buffer, size_t len) {
|
||||
return std::make_shared<StringSendMsg>(buffer, len);
|
||||
}
|
||||
|
||||
static SendableMsg::Ptr MakeStringMsg(const std::string& buffer)
|
||||
{
|
||||
return std::make_shared<StringSendMsg>(buffer);
|
||||
static SendableMsg::Ptr MakeStringMsg(const std::string &buffer) {
|
||||
return std::make_shared<StringSendMsg>(buffer);
|
||||
}
|
||||
|
||||
static SendableMsg::Ptr MakeStringMsg(std::string&& buffer)
|
||||
{
|
||||
return std::make_shared<StringSendMsg>(std::move(buffer));
|
||||
static SendableMsg::Ptr MakeStringMsg(std::string &&buffer) {
|
||||
return std::make_shared<StringSendMsg>(std::move(buffer));
|
||||
}
|
||||
|
||||
}}// namespace brynet::net
|
||||
} // namespace net
|
||||
} // namespace brynet
|
@ -7,220 +7,185 @@
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
namespace brynet { namespace net {
|
||||
namespace brynet {
|
||||
namespace net {
|
||||
|
||||
class TcpConnection;
|
||||
|
||||
class UniqueFd final : public brynet::base::NonCopyable
|
||||
{
|
||||
class UniqueFd final : public brynet::base::NonCopyable {
|
||||
public:
|
||||
explicit UniqueFd(BrynetSocketFD fd)
|
||||
: mFD(fd)
|
||||
{}
|
||||
explicit UniqueFd(BrynetSocketFD fd) :
|
||||
mFD(fd) {}
|
||||
|
||||
~UniqueFd()
|
||||
{
|
||||
brynet::net::base::SocketClose(mFD);
|
||||
}
|
||||
~UniqueFd() {
|
||||
brynet::net::base::SocketClose(mFD);
|
||||
}
|
||||
|
||||
UniqueFd(const UniqueFd& other) = delete;
|
||||
UniqueFd& operator=(const UniqueFd& other) = delete;
|
||||
UniqueFd(const UniqueFd &other) = delete;
|
||||
UniqueFd &operator=(const UniqueFd &other) = delete;
|
||||
|
||||
BrynetSocketFD getFD() const
|
||||
{
|
||||
return mFD;
|
||||
}
|
||||
BrynetSocketFD getFD() const {
|
||||
return mFD;
|
||||
}
|
||||
|
||||
private:
|
||||
BrynetSocketFD mFD;
|
||||
BrynetSocketFD mFD;
|
||||
};
|
||||
|
||||
class TcpSocket : public brynet::base::NonCopyable
|
||||
{
|
||||
class TcpSocket : public brynet::base::NonCopyable {
|
||||
private:
|
||||
class TcpSocketDeleter
|
||||
{
|
||||
public:
|
||||
void operator()(TcpSocket* ptr) const
|
||||
{
|
||||
delete ptr;
|
||||
}
|
||||
};
|
||||
class TcpSocketDeleter {
|
||||
public:
|
||||
void operator()(TcpSocket *ptr) const {
|
||||
delete ptr;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
using Ptr = std::unique_ptr<TcpSocket, TcpSocketDeleter>;
|
||||
using Ptr = std::unique_ptr<TcpSocket, TcpSocketDeleter>;
|
||||
|
||||
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)
|
||||
{}
|
||||
};
|
||||
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));
|
||||
}
|
||||
return Ptr(new make_unique_enabler(fd, serverSide));
|
||||
}
|
||||
|
||||
public:
|
||||
void setNodelay() const
|
||||
{
|
||||
brynet::net::base::SocketNodelay(mFD);
|
||||
}
|
||||
void setNodelay() const {
|
||||
brynet::net::base::SocketNodelay(mFD);
|
||||
}
|
||||
|
||||
bool setNonblock() const
|
||||
{
|
||||
return brynet::net::base::SocketNonblock(mFD);
|
||||
}
|
||||
bool setNonblock() const {
|
||||
return brynet::net::base::SocketNonblock(mFD);
|
||||
}
|
||||
|
||||
void setSendSize(int sdSize) const
|
||||
{
|
||||
brynet::net::base::SocketSetSendSize(mFD, sdSize);
|
||||
}
|
||||
void setSendSize(int sdSize) const {
|
||||
brynet::net::base::SocketSetSendSize(mFD, sdSize);
|
||||
}
|
||||
|
||||
void setRecvSize(int rdSize) const
|
||||
{
|
||||
brynet::net::base::SocketSetRecvSize(mFD, rdSize);
|
||||
}
|
||||
void setRecvSize(int rdSize) const {
|
||||
brynet::net::base::SocketSetRecvSize(mFD, rdSize);
|
||||
}
|
||||
|
||||
std::string getRemoteIP() const
|
||||
{
|
||||
return brynet::net::base::GetIPOfSocket(mFD);
|
||||
}
|
||||
std::string getRemoteIP() const {
|
||||
return brynet::net::base::GetIPOfSocket(mFD);
|
||||
}
|
||||
|
||||
bool isServerSide() const
|
||||
{
|
||||
return mServerSide;
|
||||
}
|
||||
bool isServerSide() const {
|
||||
return mServerSide;
|
||||
}
|
||||
|
||||
protected:
|
||||
TcpSocket(BrynetSocketFD fd, bool serverSide)
|
||||
: mFD(fd),
|
||||
mServerSide(serverSide)
|
||||
{
|
||||
}
|
||||
TcpSocket(BrynetSocketFD fd, bool serverSide) :
|
||||
mFD(fd),
|
||||
mServerSide(serverSide) {
|
||||
}
|
||||
|
||||
virtual ~TcpSocket()
|
||||
{
|
||||
brynet::net::base::SocketClose(mFD);
|
||||
}
|
||||
virtual ~TcpSocket() {
|
||||
brynet::net::base::SocketClose(mFD);
|
||||
}
|
||||
|
||||
BrynetSocketFD getFD() const
|
||||
{
|
||||
return mFD;
|
||||
}
|
||||
BrynetSocketFD getFD() const {
|
||||
return mFD;
|
||||
}
|
||||
|
||||
private:
|
||||
const BrynetSocketFD mFD;
|
||||
const bool mServerSide;
|
||||
const BrynetSocketFD mFD;
|
||||
const bool mServerSide;
|
||||
|
||||
friend class TcpConnection;
|
||||
friend class TcpConnection;
|
||||
};
|
||||
|
||||
class EintrError : public std::exception
|
||||
{
|
||||
class EintrError : public std::exception {
|
||||
};
|
||||
|
||||
class AcceptError : public std::runtime_error
|
||||
{
|
||||
class AcceptError : public std::runtime_error {
|
||||
public:
|
||||
explicit AcceptError(int errorCode)
|
||||
: std::runtime_error(std::to_string(errorCode)),
|
||||
mErrorCode(errorCode)
|
||||
{}
|
||||
explicit AcceptError(int errorCode) :
|
||||
std::runtime_error(std::to_string(errorCode)),
|
||||
mErrorCode(errorCode) {}
|
||||
|
||||
int getErrorCode() const
|
||||
{
|
||||
return mErrorCode;
|
||||
}
|
||||
int getErrorCode() const {
|
||||
return mErrorCode;
|
||||
}
|
||||
|
||||
private:
|
||||
int mErrorCode;
|
||||
int mErrorCode;
|
||||
};
|
||||
|
||||
class ListenSocket : public brynet::base::NonCopyable
|
||||
{
|
||||
class ListenSocket : public brynet::base::NonCopyable {
|
||||
private:
|
||||
class ListenSocketDeleter
|
||||
{
|
||||
public:
|
||||
void operator()(ListenSocket* ptr) const
|
||||
{
|
||||
delete ptr;
|
||||
}
|
||||
};
|
||||
class ListenSocketDeleter {
|
||||
public:
|
||||
void operator()(ListenSocket *ptr) const {
|
||||
delete ptr;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
using Ptr = std::unique_ptr<ListenSocket, ListenSocketDeleter>;
|
||||
using Ptr = std::unique_ptr<ListenSocket, ListenSocketDeleter>;
|
||||
|
||||
public:
|
||||
TcpSocket::Ptr accept()
|
||||
{
|
||||
const auto clientFD = brynet::net::base::Accept(mFD, nullptr, nullptr);
|
||||
if (clientFD == BRYNET_INVALID_SOCKET)
|
||||
{
|
||||
TcpSocket::Ptr accept() {
|
||||
const auto clientFD = brynet::net::base::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(brynet::net::base::Accept(mFD, nullptr, nullptr), true);
|
||||
mIdle = brynet::net::TcpSocket::Create(::open("/dev/null", O_RDONLY | O_CLOEXEC), true);
|
||||
}
|
||||
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(brynet::net::base::Accept(mFD, nullptr, nullptr), true);
|
||||
mIdle = brynet::net::TcpSocket::Create(::open("/dev/null", O_RDONLY | O_CLOEXEC), true);
|
||||
}
|
||||
#endif
|
||||
if (BRYNET_ERRNO == EINTR)
|
||||
{
|
||||
throw EintrError();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw AcceptError(BRYNET_ERRNO);
|
||||
}
|
||||
}
|
||||
if (BRYNET_ERRNO == EINTR) {
|
||||
throw EintrError();
|
||||
} else {
|
||||
throw AcceptError(BRYNET_ERRNO);
|
||||
}
|
||||
}
|
||||
|
||||
return TcpSocket::Create(clientFD, true);
|
||||
}
|
||||
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)
|
||||
{}
|
||||
};
|
||||
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));
|
||||
}
|
||||
return Ptr(new make_unique_enabler(fd));
|
||||
}
|
||||
|
||||
protected:
|
||||
explicit ListenSocket(BrynetSocketFD fd)
|
||||
: mFD(fd)
|
||||
{
|
||||
explicit ListenSocket(BrynetSocketFD fd) :
|
||||
mFD(fd) {
|
||||
#if defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN
|
||||
mIdle = brynet::net::TcpSocket::Create(::open("/dev/null", O_RDONLY | O_CLOEXEC), true);
|
||||
mIdle = brynet::net::TcpSocket::Create(::open("/dev/null", O_RDONLY | O_CLOEXEC), true);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~ListenSocket()
|
||||
{
|
||||
brynet::net::base::SocketClose(mFD);
|
||||
}
|
||||
virtual ~ListenSocket() {
|
||||
brynet::net::base::SocketClose(mFD);
|
||||
}
|
||||
|
||||
private:
|
||||
const BrynetSocketFD mFD;
|
||||
const BrynetSocketFD mFD;
|
||||
#if defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN
|
||||
brynet::net::TcpSocket::Ptr mIdle;
|
||||
brynet::net::TcpSocket::Ptr mIdle;
|
||||
#endif
|
||||
|
||||
friend class TcpConnection;
|
||||
friend class TcpConnection;
|
||||
};
|
||||
|
||||
}}// namespace brynet::net
|
||||
} // namespace net
|
||||
} // namespace brynet
|
||||
|
@ -5,335 +5,291 @@
|
||||
#include <brynet/net/SocketLibTypes.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace brynet { namespace net { namespace base {
|
||||
namespace brynet {
|
||||
namespace net {
|
||||
namespace base {
|
||||
|
||||
static bool InitSocket()
|
||||
{
|
||||
bool ret = true;
|
||||
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;
|
||||
}
|
||||
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);
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void DestroySocket()
|
||||
{
|
||||
static void DestroySocket() {
|
||||
#ifdef BRYNET_PLATFORM_WINDOWS
|
||||
WSACleanup();
|
||||
WSACleanup();
|
||||
#endif
|
||||
}
|
||||
|
||||
static int SocketNodelay(BrynetSocketFD fd)
|
||||
{
|
||||
const int flag = 1;
|
||||
return ::setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const char*) &flag, sizeof(flag));
|
||||
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;
|
||||
static bool SocketBlock(BrynetSocketFD fd) {
|
||||
int err;
|
||||
unsigned long ul = false;
|
||||
#ifdef BRYNET_PLATFORM_WINDOWS
|
||||
err = ioctlsocket(fd, FIONBIO, &ul);
|
||||
err = ioctlsocket(fd, FIONBIO, &ul);
|
||||
#elif defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN
|
||||
err = ioctl(fd, FIONBIO, &ul);
|
||||
err = ioctl(fd, FIONBIO, &ul);
|
||||
#endif
|
||||
|
||||
return err != BRYNET_SOCKET_ERROR;
|
||||
return err != BRYNET_SOCKET_ERROR;
|
||||
}
|
||||
|
||||
static bool SocketNonblock(BrynetSocketFD fd)
|
||||
{
|
||||
int err;
|
||||
unsigned long ul = true;
|
||||
static bool SocketNonblock(BrynetSocketFD fd) {
|
||||
int err;
|
||||
unsigned long ul = true;
|
||||
#ifdef BRYNET_PLATFORM_WINDOWS
|
||||
err = ioctlsocket(fd, FIONBIO, &ul);
|
||||
err = ioctlsocket(fd, FIONBIO, &ul);
|
||||
#elif defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN
|
||||
err = ioctl(fd, FIONBIO, &ul);
|
||||
err = ioctl(fd, FIONBIO, &ul);
|
||||
#endif
|
||||
|
||||
return err != BRYNET_SOCKET_ERROR;
|
||||
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 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 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)
|
||||
{
|
||||
static int SocketSetReusePort(BrynetSocketFD fd) {
|
||||
#ifdef BRYNET_PLATFORM_WINDOWS
|
||||
return 0;
|
||||
return 0;
|
||||
#else
|
||||
int enable = 1;
|
||||
return ::setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(enable));
|
||||
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 BrynetSocketFD SocketCreate(int af, int type, int protocol) {
|
||||
return ::socket(af, type, protocol);
|
||||
}
|
||||
|
||||
static void SocketClose(BrynetSocketFD fd)
|
||||
{
|
||||
static void SocketClose(BrynetSocketFD fd) {
|
||||
#ifdef BRYNET_PLATFORM_WINDOWS
|
||||
::closesocket(fd);
|
||||
::closesocket(fd);
|
||||
#elif defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN
|
||||
::close(fd);
|
||||
::close(fd);
|
||||
#endif
|
||||
}
|
||||
|
||||
static BrynetSocketFD Connect(bool isIPV6, const std::string& server_ip, int port)
|
||||
{
|
||||
InitSocket();
|
||||
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);
|
||||
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);
|
||||
BrynetSocketFD clientfd = isIPV6 ? SocketCreate(AF_INET6, SOCK_STREAM, 0) : SocketCreate(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
if (clientfd == BRYNET_INVALID_SOCKET)
|
||||
{
|
||||
return clientfd;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
if (!ptonResult) {
|
||||
SocketClose(clientfd);
|
||||
return BRYNET_INVALID_SOCKET;
|
||||
}
|
||||
|
||||
while (::connect(clientfd, (struct sockaddr*) paddr, addrLen) < 0)
|
||||
{
|
||||
if (EINTR == BRYNET_ERRNO)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
while (::connect(clientfd, (struct sockaddr *)paddr, addrLen) < 0) {
|
||||
if (EINTR == BRYNET_ERRNO) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SocketClose(clientfd);
|
||||
return BRYNET_INVALID_SOCKET;
|
||||
}
|
||||
SocketClose(clientfd);
|
||||
return BRYNET_INVALID_SOCKET;
|
||||
}
|
||||
|
||||
return clientfd;
|
||||
return clientfd;
|
||||
}
|
||||
|
||||
static BrynetSocketFD Listen(bool isIPV6, const char* ip, int port, int back_num, bool enabledReusePort)
|
||||
{
|
||||
InitSocket();
|
||||
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);
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
return socketfd;
|
||||
}
|
||||
|
||||
static std::string getIPString(const struct sockaddr* sa)
|
||||
{
|
||||
static std::string getIPString(const struct sockaddr *sa) {
|
||||
#ifdef BRYNET_PLATFORM_WINDOWS
|
||||
using PAddrType = PVOID;
|
||||
using PAddrType = PVOID;
|
||||
#elif defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN
|
||||
using PAddrType = const void*;
|
||||
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";
|
||||
}
|
||||
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;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static std::string GetIPOfSocket(BrynetSocketFD fd)
|
||||
{
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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 "";
|
||||
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;
|
||||
}
|
||||
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;
|
||||
/* send error if transnum < 0 */
|
||||
return transnum;
|
||||
}
|
||||
|
||||
static BrynetSocketFD Accept(BrynetSocketFD listenSocket, struct sockaddr* addr, socklen_t* addrLen)
|
||||
{
|
||||
return ::accept(listenSocket, addr, addrLen);
|
||||
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<socklen_t>(sizeof peeraddr);
|
||||
if (::getpeername(sockfd, (struct sockaddr*) (&peeraddr), &addrlen) < 0)
|
||||
{
|
||||
return peeraddr;
|
||||
}
|
||||
return peeraddr;
|
||||
static struct sockaddr_in6 getPeerAddr(BrynetSocketFD sockfd) {
|
||||
struct sockaddr_in6 peeraddr = sockaddr_in6();
|
||||
auto addrlen = static_cast<socklen_t>(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<socklen_t>(sizeof localaddr);
|
||||
if (::getsockname(sockfd, (struct sockaddr*) (&localaddr), &addrlen) < 0)
|
||||
{
|
||||
return localaddr;
|
||||
}
|
||||
return localaddr;
|
||||
static struct sockaddr_in6 getLocalAddr(BrynetSocketFD sockfd) {
|
||||
struct sockaddr_in6 localaddr = sockaddr_in6();
|
||||
auto addrlen = static_cast<socklen_t>(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);
|
||||
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<struct sockaddr_in*>(&localaddr);
|
||||
const struct sockaddr_in* raddr4 = reinterpret_cast<struct sockaddr_in*>(&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)
|
||||
{
|
||||
if (localaddr.sin6_family == AF_INET) {
|
||||
const struct sockaddr_in *laddr4 = reinterpret_cast<struct sockaddr_in *>(&localaddr);
|
||||
const struct sockaddr_in *raddr4 = reinterpret_cast<struct sockaddr_in *>(&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;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}}}// namespace brynet::net::base
|
||||
} // namespace base
|
||||
} // namespace net
|
||||
} // namespace brynet
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2,48 +2,43 @@
|
||||
|
||||
#include <brynet/net/detail/TCPServiceDetail.hpp>
|
||||
|
||||
namespace brynet { namespace net {
|
||||
namespace brynet {
|
||||
namespace net {
|
||||
|
||||
using ConnectionOption = detail::ConnectionOption;
|
||||
class TcpService : public detail::TcpServiceDetail,
|
||||
public std::enable_shared_from_this<TcpService>
|
||||
{
|
||||
public std::enable_shared_from_this<TcpService> {
|
||||
public:
|
||||
using Ptr = std::shared_ptr<TcpService>;
|
||||
using FrameCallback = detail::TcpServiceDetail::FrameCallback;
|
||||
using Ptr = std::shared_ptr<TcpService>;
|
||||
using FrameCallback = detail::TcpServiceDetail::FrameCallback;
|
||||
|
||||
public:
|
||||
static Ptr Create()
|
||||
{
|
||||
struct make_shared_enabler : public TcpService
|
||||
{
|
||||
};
|
||||
return std::make_shared<make_shared_enabler>();
|
||||
}
|
||||
static Ptr Create() {
|
||||
struct make_shared_enabler : public TcpService {
|
||||
};
|
||||
return std::make_shared<make_shared_enabler>();
|
||||
}
|
||||
|
||||
void startWorkerThread(size_t threadNum,
|
||||
FrameCallback callback = nullptr)
|
||||
{
|
||||
detail::TcpServiceDetail::startWorkerThread(threadNum, callback);
|
||||
}
|
||||
void startWorkerThread(size_t threadNum,
|
||||
FrameCallback callback = nullptr) {
|
||||
detail::TcpServiceDetail::startWorkerThread(threadNum, callback);
|
||||
}
|
||||
|
||||
void stopWorkerThread()
|
||||
{
|
||||
detail::TcpServiceDetail::stopWorkerThread();
|
||||
}
|
||||
void stopWorkerThread() {
|
||||
detail::TcpServiceDetail::stopWorkerThread();
|
||||
}
|
||||
|
||||
bool addTcpConnection(TcpSocket::Ptr socket, ConnectionOption options)
|
||||
{
|
||||
return detail::TcpServiceDetail::addTcpConnection(std::move(socket), options);
|
||||
}
|
||||
bool addTcpConnection(TcpSocket::Ptr socket, ConnectionOption options) {
|
||||
return detail::TcpServiceDetail::addTcpConnection(std::move(socket), options);
|
||||
}
|
||||
|
||||
EventLoop::Ptr getRandomEventLoop()
|
||||
{
|
||||
return detail::TcpServiceDetail::getRandomEventLoop();
|
||||
}
|
||||
EventLoop::Ptr getRandomEventLoop() {
|
||||
return detail::TcpServiceDetail::getRandomEventLoop();
|
||||
}
|
||||
|
||||
private:
|
||||
TcpService() = default;
|
||||
TcpService() = default;
|
||||
};
|
||||
|
||||
}}// namespace brynet::net
|
||||
} // namespace net
|
||||
} // namespace brynet
|
||||
|
@ -3,16 +3,19 @@
|
||||
#include <brynet/net/SSLHelper.hpp>
|
||||
#include <brynet/net/TcpConnection.hpp>
|
||||
|
||||
namespace brynet { namespace net { namespace detail {
|
||||
namespace brynet {
|
||||
namespace net {
|
||||
namespace detail {
|
||||
|
||||
class ConnectionOption final
|
||||
{
|
||||
class ConnectionOption final {
|
||||
public:
|
||||
std::vector<TcpConnection::EnterCallback> enterCallback;
|
||||
SSLHelper::Ptr sslHelper;
|
||||
bool useSSL = false;
|
||||
bool forceSameThreadLoop = false;
|
||||
size_t maxRecvBufferSize = 128;
|
||||
std::vector<TcpConnection::EnterCallback> enterCallback;
|
||||
SSLHelper::Ptr sslHelper;
|
||||
bool useSSL = false;
|
||||
bool forceSameThreadLoop = false;
|
||||
size_t maxRecvBufferSize = 128;
|
||||
};
|
||||
|
||||
}}}// namespace brynet::net::detail
|
||||
} // namespace detail
|
||||
} // namespace net
|
||||
} // namespace brynet
|
||||
|
@ -15,133 +15,121 @@
|
||||
#include <mutex>
|
||||
#endif
|
||||
|
||||
namespace brynet { namespace net { namespace detail {
|
||||
namespace brynet {
|
||||
namespace net {
|
||||
namespace detail {
|
||||
|
||||
class AsyncConnectorDetail : public brynet::base::NonCopyable
|
||||
{
|
||||
class AsyncConnectorDetail : public brynet::base::NonCopyable {
|
||||
protected:
|
||||
void startWorkerThread()
|
||||
{
|
||||
void startWorkerThread() {
|
||||
#ifdef BRYNET_HAVE_LANG_CXX17
|
||||
std::lock_guard<std::shared_mutex> lck(mThreadGuard);
|
||||
std::lock_guard<std::shared_mutex> lck(mThreadGuard);
|
||||
#else
|
||||
std::lock_guard<std::mutex> lck(mThreadGuard);
|
||||
std::lock_guard<std::mutex> lck(mThreadGuard);
|
||||
#endif
|
||||
|
||||
if (mThread != nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (mThread != nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
mIsRun = std::make_shared<bool>(true);
|
||||
mWorkInfo = std::make_shared<detail::ConnectorWorkInfo>();
|
||||
mEventLoop = std::make_shared<EventLoop>();
|
||||
mIsRun = std::make_shared<bool>(true);
|
||||
mWorkInfo = std::make_shared<detail::ConnectorWorkInfo>();
|
||||
mEventLoop = std::make_shared<EventLoop>();
|
||||
|
||||
auto eventLoop = mEventLoop;
|
||||
auto workerInfo = mWorkInfo;
|
||||
auto isRun = mIsRun;
|
||||
auto eventLoop = mEventLoop;
|
||||
auto workerInfo = mWorkInfo;
|
||||
auto isRun = mIsRun;
|
||||
|
||||
mThread = std::make_shared<std::thread>([eventLoop, workerInfo, isRun]() {
|
||||
while (*isRun)
|
||||
{
|
||||
detail::RunOnceCheckConnect(eventLoop, workerInfo);
|
||||
}
|
||||
mThread = std::make_shared<std::thread>([eventLoop, workerInfo, isRun]() {
|
||||
while (*isRun) {
|
||||
detail::RunOnceCheckConnect(eventLoop, workerInfo);
|
||||
}
|
||||
|
||||
workerInfo->causeAllFailed();
|
||||
});
|
||||
}
|
||||
workerInfo->causeAllFailed();
|
||||
});
|
||||
}
|
||||
|
||||
void stopWorkerThread()
|
||||
{
|
||||
void stopWorkerThread() {
|
||||
#ifdef BRYNET_HAVE_LANG_CXX17
|
||||
std::lock_guard<std::shared_mutex> lck(mThreadGuard);
|
||||
std::lock_guard<std::shared_mutex> lck(mThreadGuard);
|
||||
#else
|
||||
std::lock_guard<std::mutex> lck(mThreadGuard);
|
||||
std::lock_guard<std::mutex> lck(mThreadGuard);
|
||||
#endif
|
||||
|
||||
if (mThread == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (mThread == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
mEventLoop->runAsyncFunctor([this]() {
|
||||
*mIsRun = false;
|
||||
});
|
||||
mEventLoop->runAsyncFunctor([this]() {
|
||||
*mIsRun = false;
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
if (mThread->joinable())
|
||||
{
|
||||
mThread->join();
|
||||
}
|
||||
}
|
||||
catch (std::system_error& e)
|
||||
{
|
||||
(void) e;
|
||||
}
|
||||
try {
|
||||
if (mThread->joinable()) {
|
||||
mThread->join();
|
||||
}
|
||||
} catch (std::system_error &e) {
|
||||
(void)e;
|
||||
}
|
||||
|
||||
mEventLoop = nullptr;
|
||||
mWorkInfo = nullptr;
|
||||
mIsRun = nullptr;
|
||||
mThread = nullptr;
|
||||
}
|
||||
mEventLoop = nullptr;
|
||||
mWorkInfo = nullptr;
|
||||
mIsRun = nullptr;
|
||||
mThread = nullptr;
|
||||
}
|
||||
|
||||
void asyncConnect(detail::ConnectOption option)
|
||||
{
|
||||
void asyncConnect(detail::ConnectOption option) {
|
||||
#ifdef BRYNET_HAVE_LANG_CXX17
|
||||
std::shared_lock<std::shared_mutex> lck(mThreadGuard);
|
||||
std::shared_lock<std::shared_mutex> lck(mThreadGuard);
|
||||
#else
|
||||
std::lock_guard<std::mutex> lck(mThreadGuard);
|
||||
std::lock_guard<std::mutex> 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 (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");
|
||||
}
|
||||
if (!(*mIsRun)) {
|
||||
throw ConnectException("work thread already stop");
|
||||
}
|
||||
|
||||
auto workInfo = mWorkInfo;
|
||||
auto address = detail::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);
|
||||
});
|
||||
}
|
||||
auto workInfo = mWorkInfo;
|
||||
auto address = detail::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<bool>(false);
|
||||
}
|
||||
AsyncConnectorDetail() {
|
||||
mIsRun = std::make_shared<bool>(false);
|
||||
}
|
||||
|
||||
virtual ~AsyncConnectorDetail()
|
||||
{
|
||||
stopWorkerThread();
|
||||
}
|
||||
virtual ~AsyncConnectorDetail() {
|
||||
stopWorkerThread();
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<EventLoop> mEventLoop;
|
||||
std::shared_ptr<EventLoop> mEventLoop;
|
||||
|
||||
std::shared_ptr<detail::ConnectorWorkInfo> mWorkInfo;
|
||||
std::shared_ptr<std::thread> mThread;
|
||||
std::shared_ptr<detail::ConnectorWorkInfo> mWorkInfo;
|
||||
std::shared_ptr<std::thread> mThread;
|
||||
#ifdef BRYNET_HAVE_LANG_CXX17
|
||||
std::shared_mutex mThreadGuard;
|
||||
std::shared_mutex mThreadGuard;
|
||||
#else
|
||||
std::mutex mThreadGuard;
|
||||
std::mutex mThreadGuard;
|
||||
#endif
|
||||
std::shared_ptr<bool> mIsRun;
|
||||
std::shared_ptr<bool> mIsRun;
|
||||
};
|
||||
|
||||
}}}// namespace brynet::net::detail
|
||||
} // namespace detail
|
||||
} // namespace net
|
||||
} // namespace brynet
|
||||
|
@ -16,343 +16,294 @@
|
||||
#include <mutex>
|
||||
#endif
|
||||
|
||||
namespace brynet { namespace net { namespace detail {
|
||||
namespace brynet {
|
||||
namespace net {
|
||||
namespace detail {
|
||||
|
||||
class AsyncConnectAddr final
|
||||
{
|
||||
class AsyncConnectAddr final {
|
||||
public:
|
||||
using CompletedCallback = std::function<void(TcpSocket::Ptr)>;
|
||||
using ProcessTcpSocketCallback = std::function<void(TcpSocket&)>;
|
||||
using FailedCallback = std::function<void()>;
|
||||
using CompletedCallback = std::function<void(TcpSocket::Ptr)>;
|
||||
using ProcessTcpSocketCallback = std::function<void(TcpSocket &)>;
|
||||
using FailedCallback = std::function<void()>;
|
||||
|
||||
public:
|
||||
AsyncConnectAddr(std::string&& ip,
|
||||
int port,
|
||||
std::chrono::nanoseconds timeout,
|
||||
CompletedCallback&& successCB,
|
||||
FailedCallback&& failedCB,
|
||||
std::vector<ProcessTcpSocketCallback>&& processCallbacks)
|
||||
: mIP(std::move(ip)),
|
||||
mPort(port),
|
||||
mTimeout(timeout),
|
||||
mSuccessCB(std::move(successCB)),
|
||||
mFailedCB(std::move(failedCB)),
|
||||
mProcessCallbacks(std::move(processCallbacks))
|
||||
{
|
||||
}
|
||||
AsyncConnectAddr(std::string &&ip,
|
||||
int port,
|
||||
std::chrono::nanoseconds timeout,
|
||||
CompletedCallback &&successCB,
|
||||
FailedCallback &&failedCB,
|
||||
std::vector<ProcessTcpSocketCallback> &&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;
|
||||
}
|
||||
const std::string &getIP() const {
|
||||
return mIP;
|
||||
}
|
||||
|
||||
int getPort() const
|
||||
{
|
||||
return mPort;
|
||||
}
|
||||
int getPort() const {
|
||||
return mPort;
|
||||
}
|
||||
|
||||
const CompletedCallback& getSuccessCB() const
|
||||
{
|
||||
return mSuccessCB;
|
||||
}
|
||||
const CompletedCallback &getSuccessCB() const {
|
||||
return mSuccessCB;
|
||||
}
|
||||
|
||||
const FailedCallback& getFailedCB() const
|
||||
{
|
||||
return mFailedCB;
|
||||
}
|
||||
const FailedCallback &getFailedCB() const {
|
||||
return mFailedCB;
|
||||
}
|
||||
|
||||
const std::vector<ProcessTcpSocketCallback>& getProcessCallbacks() const
|
||||
{
|
||||
return mProcessCallbacks;
|
||||
}
|
||||
const std::vector<ProcessTcpSocketCallback> &getProcessCallbacks() const {
|
||||
return mProcessCallbacks;
|
||||
}
|
||||
|
||||
std::chrono::nanoseconds getTimeout() const
|
||||
{
|
||||
return mTimeout;
|
||||
}
|
||||
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<ProcessTcpSocketCallback> mProcessCallbacks;
|
||||
const std::string mIP;
|
||||
const int mPort;
|
||||
const std::chrono::nanoseconds mTimeout;
|
||||
const CompletedCallback mSuccessCB;
|
||||
const FailedCallback mFailedCB;
|
||||
const std::vector<ProcessTcpSocketCallback> mProcessCallbacks;
|
||||
};
|
||||
|
||||
class ConnectorWorkInfo final : public brynet::base::NonCopyable
|
||||
{
|
||||
class ConnectorWorkInfo final : public brynet::base::NonCopyable {
|
||||
public:
|
||||
using Ptr = std::shared_ptr<ConnectorWorkInfo>;
|
||||
using Ptr = std::shared_ptr<ConnectorWorkInfo>;
|
||||
|
||||
ConnectorWorkInfo() BRYNET_NOEXCEPT
|
||||
{
|
||||
mPoller.reset(brynet::base::poller_new());
|
||||
mPollResult.reset(brynet::base::stack_new(1024, sizeof(BrynetSocketFD)));
|
||||
}
|
||||
ConnectorWorkInfo() BRYNET_NOEXCEPT {
|
||||
mPoller.reset(brynet::base::poller_new());
|
||||
mPollResult.reset(brynet::base::stack_new(1024, sizeof(BrynetSocketFD)));
|
||||
}
|
||||
|
||||
void checkConnectStatus(int millSecond)
|
||||
{
|
||||
if (poller_poll(mPoller.get(), millSecond) <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
void checkConnectStatus(int millSecond) {
|
||||
if (poller_poll(mPoller.get(), millSecond) <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::set<BrynetSocketFD> totalFds;
|
||||
std::set<BrynetSocketFD> successFds;
|
||||
std::set<BrynetSocketFD> totalFds;
|
||||
std::set<BrynetSocketFD> successFds;
|
||||
|
||||
poller_visitor(mPoller.get(), brynet::base::WriteCheck, mPollResult.get());
|
||||
while (true)
|
||||
{
|
||||
auto p = stack_popfront(mPollResult.get());
|
||||
if (p == nullptr)
|
||||
{
|
||||
break;
|
||||
}
|
||||
poller_visitor(mPoller.get(), brynet::base::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) &&
|
||||
!brynet::net::base::IsSelfConnect(fd))
|
||||
{
|
||||
successFds.insert(fd);
|
||||
}
|
||||
}
|
||||
const auto fd = *(BrynetSocketFD *)p;
|
||||
totalFds.insert(fd);
|
||||
if (isConnectSuccess(fd, false) &&
|
||||
!brynet::net::base::IsSelfConnect(fd)) {
|
||||
successFds.insert(fd);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto fd : totalFds)
|
||||
{
|
||||
poller_remove(mPoller.get(), fd);
|
||||
for (auto fd : totalFds) {
|
||||
poller_remove(mPoller.get(), fd);
|
||||
|
||||
const auto it = mConnectingInfos.find(fd);
|
||||
if (it == mConnectingInfos.end())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
mConnectingInfos.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
bool isConnectSuccess(BrynetSocketFD clientfd, bool willCheckWrite) const
|
||||
{
|
||||
if (willCheckWrite && !poller_check(mPoller.get(), clientfd, brynet::base::WriteCheck))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool isConnectSuccess(BrynetSocketFD clientfd, bool willCheckWrite) const {
|
||||
if (willCheckWrite && !poller_check(mPoller.get(), clientfd, brynet::base::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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
auto fd = it->first;
|
||||
auto cb = it->second.failedCB;
|
||||
|
||||
poller_remove(mPoller.get(), fd);
|
||||
mConnectingInfos.erase(it++);
|
||||
poller_remove(mPoller.get(), fd);
|
||||
mConnectingInfos.erase(it++);
|
||||
|
||||
brynet::net::base::SocketClose(fd);
|
||||
if (cb != nullptr)
|
||||
{
|
||||
//TODO::don't modify mConnectingInfos in cb
|
||||
cb();
|
||||
}
|
||||
}
|
||||
}
|
||||
brynet::net::base::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;
|
||||
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;
|
||||
const int ExpectedError = WSAEWOULDBLOCK;
|
||||
#else
|
||||
const int ExpectedError = EINPROGRESS;
|
||||
const int ExpectedError = EINPROGRESS;
|
||||
#endif
|
||||
int n = 0;
|
||||
int n = 0;
|
||||
|
||||
brynet::net::base::InitSocket();
|
||||
brynet::net::base::InitSocket();
|
||||
|
||||
clientfd = brynet::net::base::SocketCreate(AF_INET, SOCK_STREAM, 0);
|
||||
if (clientfd == BRYNET_INVALID_SOCKET)
|
||||
{
|
||||
goto FAILED;
|
||||
}
|
||||
clientfd = brynet::net::base::SocketCreate(AF_INET, SOCK_STREAM, 0);
|
||||
if (clientfd == BRYNET_INVALID_SOCKET) {
|
||||
goto FAILED;
|
||||
}
|
||||
|
||||
brynet::net::base::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<decltype(server_addr.sin_port)>(htons(addr.getPort()));
|
||||
brynet::net::base::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<decltype(server_addr.sin_port)>(htons(addr.getPort()));
|
||||
|
||||
n = connect(clientfd, (struct sockaddr*) &server_addr, sizeof(struct sockaddr));
|
||||
if (n == 0)
|
||||
{
|
||||
if (brynet::net::base::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();
|
||||
n = connect(clientfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));
|
||||
if (n == 0) {
|
||||
if (brynet::net::base::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, brynet::base::WriteCheck);
|
||||
mConnectingInfos[clientfd] = ci;
|
||||
poller_add(mPoller.get(), clientfd, brynet::base::WriteCheck);
|
||||
|
||||
return;
|
||||
}
|
||||
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;
|
||||
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)
|
||||
{
|
||||
brynet::net::base::SocketClose(clientfd);
|
||||
clientfd = BRYNET_INVALID_SOCKET;
|
||||
(void) clientfd;
|
||||
}
|
||||
if (addr.getFailedCB() != nullptr)
|
||||
{
|
||||
addr.getFailedCB()();
|
||||
}
|
||||
}
|
||||
FAILED:
|
||||
if (clientfd != BRYNET_INVALID_SOCKET) {
|
||||
brynet::net::base::SocketClose(clientfd);
|
||||
clientfd = BRYNET_INVALID_SOCKET;
|
||||
(void)clientfd;
|
||||
}
|
||||
if (addr.getFailedCB() != nullptr) {
|
||||
addr.getFailedCB()();
|
||||
}
|
||||
}
|
||||
|
||||
void causeAllFailed()
|
||||
{
|
||||
auto copyMap = mConnectingInfos;
|
||||
mConnectingInfos.clear();
|
||||
void causeAllFailed() {
|
||||
auto copyMap = mConnectingInfos;
|
||||
mConnectingInfos.clear();
|
||||
|
||||
for (const auto& v : copyMap)
|
||||
{
|
||||
auto fd = v.first;
|
||||
auto cb = v.second.failedCB;
|
||||
for (const auto &v : copyMap) {
|
||||
auto fd = v.first;
|
||||
auto cb = v.second.failedCB;
|
||||
|
||||
poller_remove(mPoller.get(), fd);
|
||||
brynet::net::base::SocketClose(fd);
|
||||
if (cb != nullptr)
|
||||
{
|
||||
cb();
|
||||
}
|
||||
}
|
||||
}
|
||||
poller_remove(mPoller.get(), fd);
|
||||
brynet::net::base::SocketClose(fd);
|
||||
if (cb != nullptr) {
|
||||
cb();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
class ConnectingInfo
|
||||
{
|
||||
public:
|
||||
ConnectingInfo()
|
||||
{
|
||||
timeout = std::chrono::nanoseconds::zero();
|
||||
}
|
||||
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<AsyncConnectAddr::ProcessTcpSocketCallback> processCallbacks;
|
||||
};
|
||||
std::chrono::steady_clock::time_point startConnectTime;
|
||||
std::chrono::nanoseconds timeout;
|
||||
AsyncConnectAddr::CompletedCallback successCB;
|
||||
AsyncConnectAddr::FailedCallback failedCB;
|
||||
std::vector<AsyncConnectAddr::ProcessTcpSocketCallback> processCallbacks;
|
||||
};
|
||||
|
||||
std::map<BrynetSocketFD, ConnectingInfo> mConnectingInfos;
|
||||
std::map<BrynetSocketFD, ConnectingInfo> mConnectingInfos;
|
||||
|
||||
class PollerDeleter
|
||||
{
|
||||
public:
|
||||
void operator()(struct brynet::base::poller_s* ptr) const
|
||||
{
|
||||
brynet::base::poller_delete(ptr);
|
||||
}
|
||||
};
|
||||
class StackDeleter
|
||||
{
|
||||
public:
|
||||
void operator()(struct brynet::base::stack_s* ptr) const
|
||||
{
|
||||
brynet::base::stack_delete(ptr);
|
||||
}
|
||||
};
|
||||
class PollerDeleter {
|
||||
public:
|
||||
void operator()(struct brynet::base::poller_s *ptr) const {
|
||||
brynet::base::poller_delete(ptr);
|
||||
}
|
||||
};
|
||||
class StackDeleter {
|
||||
public:
|
||||
void operator()(struct brynet::base::stack_s *ptr) const {
|
||||
brynet::base::stack_delete(ptr);
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<struct brynet::base::poller_s, PollerDeleter> mPoller;
|
||||
std::unique_ptr<struct brynet::base::stack_s, StackDeleter> mPollResult;
|
||||
std::unique_ptr<struct brynet::base::poller_s, PollerDeleter> mPoller;
|
||||
std::unique_ptr<struct brynet::base::stack_s, StackDeleter> mPollResult;
|
||||
};
|
||||
|
||||
static void RunOnceCheckConnect(
|
||||
const std::shared_ptr<brynet::net::EventLoop>& eventLoop,
|
||||
const std::shared_ptr<ConnectorWorkInfo>& workerInfo)
|
||||
{
|
||||
eventLoop->loop(std::chrono::milliseconds(10).count());
|
||||
workerInfo->checkConnectStatus(0);
|
||||
workerInfo->checkTimeout();
|
||||
const std::shared_ptr<brynet::net::EventLoop> &eventLoop,
|
||||
const std::shared_ptr<ConnectorWorkInfo> &workerInfo) {
|
||||
eventLoop->loop(std::chrono::milliseconds(10).count());
|
||||
workerInfo->checkConnectStatus(0);
|
||||
workerInfo->checkTimeout();
|
||||
}
|
||||
|
||||
class ConnectOption final
|
||||
{
|
||||
class ConnectOption final {
|
||||
public:
|
||||
std::string ip;
|
||||
int port = 0;
|
||||
std::chrono::nanoseconds timeout = std::chrono::seconds(10);
|
||||
std::vector<AsyncConnectAddr::ProcessTcpSocketCallback> processCallbacks;
|
||||
AsyncConnectAddr::CompletedCallback completedCallback;
|
||||
AsyncConnectAddr::FailedCallback failedCallback;
|
||||
std::string ip;
|
||||
int port = 0;
|
||||
std::chrono::nanoseconds timeout = std::chrono::seconds(10);
|
||||
std::vector<AsyncConnectAddr::ProcessTcpSocketCallback> processCallbacks;
|
||||
AsyncConnectAddr::CompletedCallback completedCallback;
|
||||
AsyncConnectAddr::FailedCallback failedCallback;
|
||||
};
|
||||
|
||||
}}}// namespace brynet::net::detail
|
||||
} // namespace detail
|
||||
} // namespace net
|
||||
} // namespace brynet
|
||||
|
@ -5,58 +5,55 @@
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
||||
namespace brynet { namespace net { namespace detail {
|
||||
namespace brynet {
|
||||
namespace net {
|
||||
namespace detail {
|
||||
|
||||
class TcpServiceDetail;
|
||||
|
||||
class IOLoopData : public brynet::base::NonCopyable,
|
||||
public std::enable_shared_from_this<IOLoopData>
|
||||
{
|
||||
public std::enable_shared_from_this<IOLoopData> {
|
||||
public:
|
||||
using Ptr = std::shared_ptr<IOLoopData>;
|
||||
using Ptr = std::shared_ptr<IOLoopData>;
|
||||
|
||||
static Ptr Create(EventLoop::Ptr eventLoop,
|
||||
std::shared_ptr<std::thread> ioThread)
|
||||
{
|
||||
class make_shared_enabler : public IOLoopData
|
||||
{
|
||||
public:
|
||||
make_shared_enabler(EventLoop::Ptr eventLoop,
|
||||
std::shared_ptr<std::thread> ioThread)
|
||||
: IOLoopData(std::move(eventLoop), std::move(ioThread))
|
||||
{}
|
||||
};
|
||||
static Ptr Create(EventLoop::Ptr eventLoop,
|
||||
std::shared_ptr<std::thread> ioThread) {
|
||||
class make_shared_enabler : public IOLoopData {
|
||||
public:
|
||||
make_shared_enabler(EventLoop::Ptr eventLoop,
|
||||
std::shared_ptr<std::thread> ioThread) :
|
||||
IOLoopData(std::move(eventLoop), std::move(ioThread)) {}
|
||||
};
|
||||
|
||||
return std::make_shared<make_shared_enabler>(std::move(eventLoop),
|
||||
std::move(ioThread));
|
||||
}
|
||||
return std::make_shared<make_shared_enabler>(std::move(eventLoop),
|
||||
std::move(ioThread));
|
||||
}
|
||||
|
||||
const EventLoop::Ptr& getEventLoop() const
|
||||
{
|
||||
return mEventLoop;
|
||||
}
|
||||
const EventLoop::Ptr &getEventLoop() const {
|
||||
return mEventLoop;
|
||||
}
|
||||
|
||||
protected:
|
||||
const std::shared_ptr<std::thread>& getIOThread() const
|
||||
{
|
||||
return mIOThread;
|
||||
}
|
||||
const std::shared_ptr<std::thread> &getIOThread() const {
|
||||
return mIOThread;
|
||||
}
|
||||
|
||||
IOLoopData(EventLoop::Ptr eventLoop,
|
||||
std::shared_ptr<std::thread> ioThread)
|
||||
: mEventLoop(std::move(eventLoop)),
|
||||
mIOThread(std::move(ioThread))
|
||||
{}
|
||||
virtual ~IOLoopData() = default;
|
||||
IOLoopData(EventLoop::Ptr eventLoop,
|
||||
std::shared_ptr<std::thread> ioThread) :
|
||||
mEventLoop(std::move(eventLoop)),
|
||||
mIOThread(std::move(ioThread)) {}
|
||||
virtual ~IOLoopData() = default;
|
||||
|
||||
const EventLoop::Ptr mEventLoop;
|
||||
const EventLoop::Ptr mEventLoop;
|
||||
|
||||
private:
|
||||
std::shared_ptr<std::thread> mIOThread;
|
||||
std::shared_ptr<std::thread> mIOThread;
|
||||
|
||||
friend class TcpServiceDetail;
|
||||
friend class TcpServiceDetail;
|
||||
};
|
||||
|
||||
using IOLoopDataPtr = std::shared_ptr<IOLoopData>;
|
||||
|
||||
}}}// namespace brynet::net::detail
|
||||
} // namespace detail
|
||||
} // namespace net
|
||||
} // namespace brynet
|
||||
|
@ -14,155 +14,135 @@
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
namespace brynet { namespace net { namespace detail {
|
||||
namespace brynet {
|
||||
namespace net {
|
||||
namespace detail {
|
||||
|
||||
class ListenThreadDetail : public brynet::base::NonCopyable
|
||||
{
|
||||
class ListenThreadDetail : public brynet::base::NonCopyable {
|
||||
protected:
|
||||
using AccepCallback = std::function<void(TcpSocket::Ptr)>;
|
||||
using TcpSocketProcessCallback = std::function<void(TcpSocket&)>;
|
||||
using AccepCallback = std::function<void(TcpSocket::Ptr)>;
|
||||
using TcpSocketProcessCallback = std::function<void(TcpSocket &)>;
|
||||
|
||||
void startListen()
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(mListenThreadGuard);
|
||||
void startListen() {
|
||||
std::lock_guard<std::mutex> lck(mListenThreadGuard);
|
||||
|
||||
if (mListenThread != nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (mListenThread != nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto fd = brynet::net::base::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));
|
||||
}
|
||||
const auto fd = brynet::net::base::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<bool>(true);
|
||||
mRunListen = std::make_shared<bool>(true);
|
||||
|
||||
auto listenSocket = std::shared_ptr<ListenSocket>(ListenSocket::Create(fd));
|
||||
auto isRunListen = mRunListen;
|
||||
auto callback = mCallback;
|
||||
auto processCallbacks = mProcessCallbacks;
|
||||
mListenThread = std::make_shared<std::thread>(
|
||||
[isRunListen, listenSocket, callback, processCallbacks]() mutable {
|
||||
while (*isRunListen)
|
||||
{
|
||||
auto clientSocket = runOnceListen(listenSocket);
|
||||
if (clientSocket == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
auto listenSocket = std::shared_ptr<ListenSocket>(ListenSocket::Create(fd));
|
||||
auto isRunListen = mRunListen;
|
||||
auto callback = mCallback;
|
||||
auto processCallbacks = mProcessCallbacks;
|
||||
mListenThread = std::make_shared<std::thread>(
|
||||
[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));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if (*isRunListen) {
|
||||
for (const auto &process : processCallbacks) {
|
||||
process(*clientSocket);
|
||||
}
|
||||
callback(std::move(clientSocket));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void stopListen()
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(mListenThreadGuard);
|
||||
void stopListen() {
|
||||
std::lock_guard<std::mutex> lck(mListenThreadGuard);
|
||||
|
||||
if (mListenThread == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (mListenThread == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
*mRunListen = false;
|
||||
auto selfIP = mIP;
|
||||
if (selfIP == "0.0.0.0")
|
||||
{
|
||||
selfIP = "127.0.0.1";
|
||||
}
|
||||
*mRunListen = false;
|
||||
auto selfIP = mIP;
|
||||
if (selfIP == "0.0.0.0") {
|
||||
selfIP = "127.0.0.1";
|
||||
}
|
||||
|
||||
auto connector = AsyncConnector::Create();
|
||||
connector->startWorkerThread();
|
||||
auto connector = AsyncConnector::Create();
|
||||
connector->startWorkerThread();
|
||||
|
||||
//TODO:: if the listen enable reuse_port, one time connect may be can't wakeup listen.
|
||||
wrapper::SocketConnectBuilder connectBuilder;
|
||||
(void) connectBuilder
|
||||
.WithConnector(connector)
|
||||
.WithTimeout(std::chrono::seconds(2))
|
||||
.WithAddr(selfIP, mPort)
|
||||
.syncConnect();
|
||||
//TODO:: if the listen enable reuse_port, one time connect may be can't wakeup listen.
|
||||
wrapper::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;
|
||||
}
|
||||
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<TcpSocketProcessCallback>& 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<bool>(false);
|
||||
}
|
||||
ListenThreadDetail(bool isIPV6,
|
||||
const std::string &ip,
|
||||
int port,
|
||||
const AccepCallback &callback,
|
||||
const std::vector<TcpSocketProcessCallback> &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<bool>(false);
|
||||
}
|
||||
|
||||
virtual ~ListenThreadDetail() BRYNET_NOEXCEPT
|
||||
{
|
||||
stopListen();
|
||||
}
|
||||
virtual ~ListenThreadDetail() BRYNET_NOEXCEPT {
|
||||
stopListen();
|
||||
}
|
||||
|
||||
private:
|
||||
static brynet::net::TcpSocket::Ptr runOnceListen(const std::shared_ptr<ListenSocket>& 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;
|
||||
}
|
||||
static brynet::net::TcpSocket::Ptr runOnceListen(const std::shared_ptr<ListenSocket> &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;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
const bool mIsIPV6;
|
||||
const std::string mIP;
|
||||
const int mPort;
|
||||
const AccepCallback mCallback;
|
||||
const std::vector<TcpSocketProcessCallback> mProcessCallbacks;
|
||||
const bool mEnabledReusePort;
|
||||
const bool mIsIPV6;
|
||||
const std::string mIP;
|
||||
const int mPort;
|
||||
const AccepCallback mCallback;
|
||||
const std::vector<TcpSocketProcessCallback> mProcessCallbacks;
|
||||
const bool mEnabledReusePort;
|
||||
|
||||
std::shared_ptr<bool> mRunListen;
|
||||
std::shared_ptr<std::thread> mListenThread;
|
||||
std::mutex mListenThreadGuard;
|
||||
std::shared_ptr<bool> mRunListen;
|
||||
std::shared_ptr<std::thread> mListenThread;
|
||||
std::mutex mListenThreadGuard;
|
||||
};
|
||||
|
||||
}}}// namespace brynet::net::detail
|
||||
} // namespace detail
|
||||
} // namespace net
|
||||
} // namespace brynet
|
||||
|
@ -13,165 +13,138 @@
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
namespace brynet { namespace net { namespace detail {
|
||||
namespace brynet {
|
||||
namespace net {
|
||||
namespace detail {
|
||||
|
||||
class TcpServiceDetail : public brynet::base::NonCopyable
|
||||
{
|
||||
class TcpServiceDetail : public brynet::base::NonCopyable {
|
||||
protected:
|
||||
using FrameCallback = std::function<void(const EventLoop::Ptr&)>;
|
||||
const static unsigned int sDefaultLoopTimeOutMS = 100;
|
||||
using FrameCallback = std::function<void(const EventLoop::Ptr &)>;
|
||||
const static unsigned int sDefaultLoopTimeOutMS = 100;
|
||||
|
||||
void startWorkerThread(size_t threadNum,
|
||||
FrameCallback callback = nullptr)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(mServiceGuard);
|
||||
std::lock_guard<std::mutex> lock(mIOLoopGuard);
|
||||
void startWorkerThread(size_t threadNum,
|
||||
FrameCallback callback = nullptr) {
|
||||
std::lock_guard<std::mutex> lck(mServiceGuard);
|
||||
std::lock_guard<std::mutex> lock(mIOLoopGuard);
|
||||
|
||||
if (!mIOLoopDatas.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!mIOLoopDatas.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mRunIOLoop = std::make_shared<bool>(true);
|
||||
mRunIOLoop = std::make_shared<bool>(true);
|
||||
|
||||
mIOLoopDatas.resize(threadNum);
|
||||
for (auto& v : mIOLoopDatas)
|
||||
{
|
||||
auto eventLoop = std::make_shared<EventLoop>();
|
||||
auto runIoLoop = mRunIOLoop;
|
||||
v = IOLoopData::Create(eventLoop,
|
||||
std::make_shared<std::thread>(
|
||||
[callback, runIoLoop, eventLoop]() {
|
||||
while (*runIoLoop)
|
||||
{
|
||||
eventLoop->loopCompareNearTimer(sDefaultLoopTimeOutMS);
|
||||
if (callback != nullptr)
|
||||
{
|
||||
callback(eventLoop);
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
mIOLoopDatas.resize(threadNum);
|
||||
for (auto &v : mIOLoopDatas) {
|
||||
auto eventLoop = std::make_shared<EventLoop>();
|
||||
auto runIoLoop = mRunIOLoop;
|
||||
v = IOLoopData::Create(eventLoop,
|
||||
std::make_shared<std::thread>(
|
||||
[callback, runIoLoop, eventLoop]() {
|
||||
while (*runIoLoop) {
|
||||
eventLoop->loopCompareNearTimer(sDefaultLoopTimeOutMS);
|
||||
if (callback != nullptr) {
|
||||
callback(eventLoop);
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
void stopWorkerThread()
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(mServiceGuard);
|
||||
std::lock_guard<std::mutex> lock(mIOLoopGuard);
|
||||
void stopWorkerThread() {
|
||||
std::lock_guard<std::mutex> lck(mServiceGuard);
|
||||
std::lock_guard<std::mutex> lock(mIOLoopGuard);
|
||||
|
||||
*mRunIOLoop = false;
|
||||
*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();
|
||||
}
|
||||
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");
|
||||
}
|
||||
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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
};
|
||||
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();
|
||||
}
|
||||
if (option.useSSL && option.sslHelper == nullptr) {
|
||||
option.sslHelper = SSLHelper::Create();
|
||||
}
|
||||
|
||||
TcpConnection::Create(std::move(socket),
|
||||
option.maxRecvBufferSize,
|
||||
wrapperEnterCallback,
|
||||
eventLoop,
|
||||
option.sslHelper);
|
||||
TcpConnection::Create(std::move(socket),
|
||||
option.maxRecvBufferSize,
|
||||
wrapperEnterCallback,
|
||||
eventLoop,
|
||||
option.sslHelper);
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
EventLoop::Ptr getRandomEventLoop()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mIOLoopGuard);
|
||||
EventLoop::Ptr getRandomEventLoop() {
|
||||
std::lock_guard<std::mutex> 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();
|
||||
}
|
||||
}
|
||||
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<unsigned int>(
|
||||
std::chrono::system_clock::now().time_since_epoch().count()))
|
||||
{
|
||||
mRunIOLoop = std::make_shared<bool>(false);
|
||||
}
|
||||
TcpServiceDetail() BRYNET_NOEXCEPT
|
||||
: mRandom(static_cast<unsigned int>(
|
||||
std::chrono::system_clock::now().time_since_epoch().count())) {
|
||||
mRunIOLoop = std::make_shared<bool>(false);
|
||||
}
|
||||
|
||||
virtual ~TcpServiceDetail() BRYNET_NOEXCEPT
|
||||
{
|
||||
stopWorkerThread();
|
||||
}
|
||||
virtual ~TcpServiceDetail() BRYNET_NOEXCEPT {
|
||||
stopWorkerThread();
|
||||
}
|
||||
|
||||
EventLoop::Ptr getSameThreadEventLoop()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mIOLoopGuard);
|
||||
for (const auto& v : mIOLoopDatas)
|
||||
{
|
||||
if (v->getEventLoop()->isInLoopThread())
|
||||
{
|
||||
return v->getEventLoop();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
EventLoop::Ptr getSameThreadEventLoop() {
|
||||
std::lock_guard<std::mutex> lock(mIOLoopGuard);
|
||||
for (const auto &v : mIOLoopDatas) {
|
||||
if (v->getEventLoop()->isInLoopThread()) {
|
||||
return v->getEventLoop();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<IOLoopDataPtr> mIOLoopDatas;
|
||||
mutable std::mutex mIOLoopGuard;
|
||||
std::shared_ptr<bool> mRunIOLoop;
|
||||
std::vector<IOLoopDataPtr> mIOLoopDatas;
|
||||
mutable std::mutex mIOLoopGuard;
|
||||
std::shared_ptr<bool> mRunIOLoop;
|
||||
|
||||
std::mutex mServiceGuard;
|
||||
std::mt19937 mRandom;
|
||||
std::mutex mServiceGuard;
|
||||
std::mt19937 mRandom;
|
||||
};
|
||||
|
||||
}}}// namespace brynet::net::detail
|
||||
} // namespace detail
|
||||
} // namespace net
|
||||
} // namespace brynet
|
||||
|
@ -8,122 +8,106 @@
|
||||
#include <brynet/net/Channel.hpp>
|
||||
#include <brynet/net/Socket.hpp>
|
||||
|
||||
namespace brynet { namespace net { namespace detail {
|
||||
namespace brynet {
|
||||
namespace net {
|
||||
namespace detail {
|
||||
|
||||
#ifdef BRYNET_PLATFORM_WINDOWS
|
||||
class WakeupChannel final : public Channel, public brynet::base::NonCopyable
|
||||
{
|
||||
class WakeupChannel final : public Channel, public brynet::base::NonCopyable {
|
||||
public:
|
||||
explicit WakeupChannel(HANDLE iocp)
|
||||
: mIOCP(iocp),
|
||||
mWakeupOvl(port::Win::OverlappedType::OverlappedRecv)
|
||||
{
|
||||
}
|
||||
explicit WakeupChannel(HANDLE iocp) :
|
||||
mIOCP(iocp),
|
||||
mWakeupOvl(port::Win::OverlappedType::OverlappedRecv) {
|
||||
}
|
||||
|
||||
bool wakeup() BRYNET_NOEXCEPT
|
||||
{
|
||||
return PostQueuedCompletionStatus(mIOCP,
|
||||
0,
|
||||
reinterpret_cast<ULONG_PTR>(this),
|
||||
&mWakeupOvl.base);
|
||||
}
|
||||
bool wakeup() BRYNET_NOEXCEPT {
|
||||
return PostQueuedCompletionStatus(mIOCP,
|
||||
0,
|
||||
reinterpret_cast<ULONG_PTR>(this),
|
||||
&mWakeupOvl.base);
|
||||
}
|
||||
|
||||
private:
|
||||
void canRecv(bool) BRYNET_NOEXCEPT override
|
||||
{
|
||||
;
|
||||
}
|
||||
void canRecv(bool) BRYNET_NOEXCEPT override {
|
||||
;
|
||||
}
|
||||
|
||||
void canSend() BRYNET_NOEXCEPT override
|
||||
{
|
||||
;
|
||||
}
|
||||
void canSend() BRYNET_NOEXCEPT override {
|
||||
;
|
||||
}
|
||||
|
||||
void onClose() BRYNET_NOEXCEPT override
|
||||
{
|
||||
;
|
||||
}
|
||||
void onClose() BRYNET_NOEXCEPT override {
|
||||
;
|
||||
}
|
||||
|
||||
HANDLE mIOCP;
|
||||
port::Win::OverlappedExt mWakeupOvl;
|
||||
HANDLE mIOCP;
|
||||
port::Win::OverlappedExt mWakeupOvl;
|
||||
};
|
||||
#elif defined BRYNET_PLATFORM_LINUX
|
||||
class WakeupChannel final : public Channel, public brynet::base::NonCopyable
|
||||
{
|
||||
class WakeupChannel final : public Channel, public brynet::base::NonCopyable {
|
||||
public:
|
||||
explicit WakeupChannel(BrynetSocketFD fd)
|
||||
: mUniqueFd(fd)
|
||||
{
|
||||
}
|
||||
explicit WakeupChannel(BrynetSocketFD fd) :
|
||||
mUniqueFd(fd) {
|
||||
}
|
||||
|
||||
bool wakeup()
|
||||
{
|
||||
uint64_t one = 1;
|
||||
return write(mUniqueFd.getFD(), &one, sizeof one) > 0;
|
||||
}
|
||||
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<size_t>(n) < sizeof(temp))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
void canRecv(bool) override {
|
||||
char temp[1024 * 10];
|
||||
while (true) {
|
||||
auto n = read(mUniqueFd.getFD(), temp, sizeof(temp));
|
||||
if (n == -1 || static_cast<size_t>(n) < sizeof(temp)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void canSend() override
|
||||
{
|
||||
}
|
||||
void canSend() override {
|
||||
}
|
||||
|
||||
void onClose() override
|
||||
{
|
||||
}
|
||||
void onClose() override {
|
||||
}
|
||||
|
||||
private:
|
||||
UniqueFd mUniqueFd;
|
||||
UniqueFd mUniqueFd;
|
||||
};
|
||||
|
||||
#elif defined BRYNET_PLATFORM_DARWIN
|
||||
class WakeupChannel final : public Channel, public brynet::base::NonCopyable
|
||||
{
|
||||
class WakeupChannel final : public Channel, public brynet::base::NonCopyable {
|
||||
public:
|
||||
explicit WakeupChannel(int kqueuefd, int ident)
|
||||
: mKqueueFd(kqueuefd),
|
||||
mUserEvent(ident)
|
||||
{
|
||||
}
|
||||
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);
|
||||
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;
|
||||
}
|
||||
struct timespec timeout = { 0, 0 };
|
||||
return kevent(mKqueueFd, &ev, 1, NULL, 0, &timeout) == 0;
|
||||
}
|
||||
|
||||
private:
|
||||
void canRecv(bool) override
|
||||
{
|
||||
}
|
||||
void canRecv(bool) override {
|
||||
}
|
||||
|
||||
void canSend() override
|
||||
{
|
||||
}
|
||||
void canSend() override {
|
||||
}
|
||||
|
||||
void onClose() override
|
||||
{
|
||||
}
|
||||
void onClose() override {
|
||||
}
|
||||
|
||||
private:
|
||||
int mKqueueFd;
|
||||
int mUserEvent;
|
||||
int mKqueueFd;
|
||||
int mUserEvent;
|
||||
};
|
||||
#endif
|
||||
|
||||
}}}// namespace brynet::net::detail
|
||||
} // namespace detail
|
||||
} // namespace net
|
||||
} // namespace brynet
|
||||
|
@ -5,230 +5,200 @@
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace brynet { namespace net { namespace http {
|
||||
namespace brynet {
|
||||
namespace net {
|
||||
namespace http {
|
||||
|
||||
class HttpQueryParameter final
|
||||
{
|
||||
class HttpQueryParameter final {
|
||||
public:
|
||||
void add(const std::string& k, const std::string& v)
|
||||
{
|
||||
if (!mParameter.empty())
|
||||
{
|
||||
mParameter += "&";
|
||||
}
|
||||
void add(const std::string &k, const std::string &v) {
|
||||
if (!mParameter.empty()) {
|
||||
mParameter += "&";
|
||||
}
|
||||
|
||||
mParameter += k;
|
||||
mParameter += "=";
|
||||
mParameter += v;
|
||||
}
|
||||
mParameter += k;
|
||||
mParameter += "=";
|
||||
mParameter += v;
|
||||
}
|
||||
|
||||
const std::string& getResult() const
|
||||
{
|
||||
return mParameter;
|
||||
}
|
||||
const std::string &getResult() const {
|
||||
return mParameter;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string mParameter;
|
||||
std::string mParameter;
|
||||
};
|
||||
|
||||
class HttpRequest final
|
||||
{
|
||||
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
|
||||
};
|
||||
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);
|
||||
}
|
||||
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 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 setHost(const std::string &host) {
|
||||
addHeadValue("Host", host);
|
||||
}
|
||||
|
||||
void setUrl(const std::string& url)
|
||||
{
|
||||
mUrl = url;
|
||||
}
|
||||
void setUrl(const std::string &url) {
|
||||
mUrl = url;
|
||||
}
|
||||
|
||||
void setCookie(const std::string& v)
|
||||
{
|
||||
addHeadValue("Cookie", v);
|
||||
}
|
||||
void setCookie(const std::string &v) {
|
||||
addHeadValue("Cookie", v);
|
||||
}
|
||||
|
||||
void setContentType(const std::string& v)
|
||||
{
|
||||
addHeadValue("Content-Type", v);
|
||||
}
|
||||
void setContentType(const std::string &v) {
|
||||
addHeadValue("Content-Type", v);
|
||||
}
|
||||
|
||||
void setQuery(const std::string& query)
|
||||
{
|
||||
mQuery = query;
|
||||
}
|
||||
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(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 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;
|
||||
}
|
||||
void addHeadValue(const std::string &field,
|
||||
const std::string &value) {
|
||||
mHeadField[field] = value;
|
||||
}
|
||||
|
||||
std::string getResult() const
|
||||
{
|
||||
const auto MethodMax = static_cast<size_t>(HTTP_METHOD::HTTP_METHOD_MAX);
|
||||
const static std::array<std::string, MethodMax> HttpMethodString =
|
||||
{"HEAD", "GET", "POST", "PUT", "DELETE"};
|
||||
std::string getResult() const {
|
||||
const auto MethodMax = static_cast<size_t>(HTTP_METHOD::HTTP_METHOD_MAX);
|
||||
const static std::array<std::string, MethodMax> 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<size_t>(mMethod)];
|
||||
}
|
||||
std::string ret;
|
||||
if (mMethod >= HTTP_METHOD::HTTP_METHOD_HEAD &&
|
||||
mMethod < HTTP_METHOD::HTTP_METHOD_MAX) {
|
||||
ret += HttpMethodString[static_cast<size_t>(mMethod)];
|
||||
}
|
||||
|
||||
ret += " ";
|
||||
ret += mUrl;
|
||||
if (!mQuery.empty())
|
||||
{
|
||||
ret += "?";
|
||||
ret += mQuery;
|
||||
}
|
||||
ret += " ";
|
||||
ret += mUrl;
|
||||
if (!mQuery.empty()) {
|
||||
ret += "?";
|
||||
ret += mQuery;
|
||||
}
|
||||
|
||||
ret += " HTTP/1.1\r\n";
|
||||
ret += " HTTP/1.1\r\n";
|
||||
|
||||
for (auto& v : mHeadField)
|
||||
{
|
||||
ret += v.first;
|
||||
ret += ": ";
|
||||
ret += v.second;
|
||||
ret += "\r\n";
|
||||
}
|
||||
for (auto &v : mHeadField) {
|
||||
ret += v.first;
|
||||
ret += ": ";
|
||||
ret += v.second;
|
||||
ret += "\r\n";
|
||||
}
|
||||
|
||||
ret += "\r\n";
|
||||
ret += "\r\n";
|
||||
|
||||
if (!mBody.empty())
|
||||
{
|
||||
ret += mBody;
|
||||
}
|
||||
if (!mBody.empty()) {
|
||||
ret += mBody;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string mUrl;
|
||||
std::string mQuery;
|
||||
std::string mBody;
|
||||
HTTP_METHOD mMethod;
|
||||
std::map<std::string, std::string> mHeadField;
|
||||
std::string mUrl;
|
||||
std::string mQuery;
|
||||
std::string mBody;
|
||||
HTTP_METHOD mMethod;
|
||||
std::map<std::string, std::string> mHeadField;
|
||||
};
|
||||
|
||||
class HttpResponse final
|
||||
{
|
||||
class HttpResponse final {
|
||||
public:
|
||||
enum class HTTP_RESPONSE_STATUS
|
||||
{
|
||||
NONE,
|
||||
OK = 200,
|
||||
};
|
||||
enum class HTTP_RESPONSE_STATUS {
|
||||
NONE,
|
||||
OK = 200,
|
||||
};
|
||||
|
||||
HttpResponse()
|
||||
: mStatus(HTTP_RESPONSE_STATUS::OK)
|
||||
{
|
||||
}
|
||||
HttpResponse() :
|
||||
mStatus(HTTP_RESPONSE_STATUS::OK) {
|
||||
}
|
||||
|
||||
void setStatus(HTTP_RESPONSE_STATUS status)
|
||||
{
|
||||
mStatus = status;
|
||||
}
|
||||
void setStatus(HTTP_RESPONSE_STATUS status) {
|
||||
mStatus = status;
|
||||
}
|
||||
|
||||
void setContentType(const std::string& v)
|
||||
{
|
||||
addHeadValue("Content-Type", v);
|
||||
}
|
||||
void setContentType(const std::string &v) {
|
||||
addHeadValue("Content-Type", v);
|
||||
}
|
||||
|
||||
void addHeadValue(const std::string& field,
|
||||
const std::string& value)
|
||||
{
|
||||
mHeadField[field] = value;
|
||||
}
|
||||
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(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 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 ";
|
||||
std::string getResult() const {
|
||||
std::string ret = "HTTP/1.1 ";
|
||||
|
||||
ret += std::to_string(static_cast<int>(mStatus));
|
||||
switch (mStatus)
|
||||
{
|
||||
case HTTP_RESPONSE_STATUS::OK:
|
||||
ret += " OK";
|
||||
break;
|
||||
default:
|
||||
ret += "UNKNOWN";
|
||||
break;
|
||||
}
|
||||
ret += std::to_string(static_cast<int>(mStatus));
|
||||
switch (mStatus) {
|
||||
case HTTP_RESPONSE_STATUS::OK:
|
||||
ret += " OK";
|
||||
break;
|
||||
default:
|
||||
ret += "UNKNOWN";
|
||||
break;
|
||||
}
|
||||
|
||||
ret += "\r\n";
|
||||
ret += "\r\n";
|
||||
|
||||
for (auto& v : mHeadField)
|
||||
{
|
||||
ret += v.first;
|
||||
ret += ": ";
|
||||
ret += v.second;
|
||||
ret += "\r\n";
|
||||
}
|
||||
for (auto &v : mHeadField) {
|
||||
ret += v.first;
|
||||
ret += ": ";
|
||||
ret += v.second;
|
||||
ret += "\r\n";
|
||||
}
|
||||
|
||||
ret += "\r\n";
|
||||
ret += "\r\n";
|
||||
|
||||
if (!mBody.empty())
|
||||
{
|
||||
ret += mBody;
|
||||
}
|
||||
if (!mBody.empty()) {
|
||||
ret += mBody;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
HTTP_RESPONSE_STATUS mStatus;
|
||||
std::map<std::string, std::string> mHeadField;
|
||||
std::string mBody;
|
||||
HTTP_RESPONSE_STATUS mStatus;
|
||||
std::map<std::string, std::string> mHeadField;
|
||||
std::string mBody;
|
||||
};
|
||||
|
||||
}}}// namespace brynet::net::http
|
||||
} // namespace http
|
||||
} // namespace net
|
||||
} // namespace brynet
|
||||
|
@ -8,320 +8,283 @@
|
||||
|
||||
#include "http_parser.h"
|
||||
|
||||
namespace brynet { namespace net { namespace http {
|
||||
namespace brynet {
|
||||
namespace net {
|
||||
namespace http {
|
||||
|
||||
class HttpService;
|
||||
|
||||
class HTTPParser
|
||||
{
|
||||
class HTTPParser {
|
||||
public:
|
||||
using Ptr = std::shared_ptr<HTTPParser>;
|
||||
using Ptr = std::shared_ptr<HTTPParser>;
|
||||
|
||||
explicit HTTPParser(http_parser_type parserType)
|
||||
: mParserType(parserType)
|
||||
{
|
||||
mLastWasValue = true;
|
||||
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;
|
||||
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);
|
||||
}
|
||||
http_parser_init(&mParser, mParserType);
|
||||
}
|
||||
|
||||
virtual ~HTTPParser() = default;
|
||||
virtual ~HTTPParser() = default;
|
||||
|
||||
bool isUpgrade() const
|
||||
{
|
||||
return mIsUpgrade;
|
||||
}
|
||||
bool isUpgrade() const {
|
||||
return mIsUpgrade;
|
||||
}
|
||||
|
||||
bool isWebSocket() const
|
||||
{
|
||||
return mIsWebSocket;
|
||||
}
|
||||
bool isWebSocket() const {
|
||||
return mIsWebSocket;
|
||||
}
|
||||
|
||||
bool isKeepAlive() const
|
||||
{
|
||||
return mIsKeepAlive;
|
||||
}
|
||||
bool isKeepAlive() const {
|
||||
return mIsKeepAlive;
|
||||
}
|
||||
|
||||
bool isCompleted() const {
|
||||
return mISCompleted;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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& getPath() const
|
||||
{
|
||||
return mPath;
|
||||
}
|
||||
const std::string &getQuery() const {
|
||||
return mQuery;
|
||||
}
|
||||
|
||||
const std::string& getQuery() const
|
||||
{
|
||||
return mQuery;
|
||||
}
|
||||
const std::string &getStatus() const {
|
||||
return mStatus;
|
||||
}
|
||||
|
||||
const std::string& getStatus() const
|
||||
{
|
||||
return mStatus;
|
||||
}
|
||||
int getStatusCode() const {
|
||||
return mStatusCode;
|
||||
}
|
||||
|
||||
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 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();
|
||||
}
|
||||
|
||||
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("");
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
auto it = mHeadValues.find(key);
|
||||
if (it != mHeadValues.end())
|
||||
{
|
||||
return (*it).second;
|
||||
}
|
||||
else
|
||||
{
|
||||
return emptystr;
|
||||
}
|
||||
}
|
||||
const std::string &getBody() const {
|
||||
return mBody;
|
||||
}
|
||||
|
||||
const std::string& getBody() const
|
||||
{
|
||||
return mBody;
|
||||
}
|
||||
std::string &getWSCacheFrame() {
|
||||
return mWSCacheFrame;
|
||||
}
|
||||
|
||||
std::string& getWSCacheFrame()
|
||||
{
|
||||
return mWSCacheFrame;
|
||||
}
|
||||
std::string &getWSParseString() {
|
||||
return mWSParsePayload;
|
||||
}
|
||||
|
||||
std::string& getWSParseString()
|
||||
{
|
||||
return mWSParsePayload;
|
||||
}
|
||||
WebSocketFormat::WebSocketFrameType getWSFrameType() const {
|
||||
return mWSFrameType;
|
||||
}
|
||||
|
||||
WebSocketFormat::WebSocketFrameType getWSFrameType() const
|
||||
{
|
||||
return mWSFrameType;
|
||||
}
|
||||
|
||||
void cacheWSFrameType(WebSocketFormat::WebSocketFrameType frameType)
|
||||
{
|
||||
mWSFrameType = frameType;
|
||||
}
|
||||
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();
|
||||
}
|
||||
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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
return nparsed;
|
||||
}
|
||||
|
||||
private:
|
||||
static int sChunkHeader(http_parser* hp)
|
||||
{
|
||||
(void) hp;
|
||||
return 0;
|
||||
}
|
||||
static int sChunkHeader(http_parser *hp) {
|
||||
(void)hp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sChunkComplete(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();
|
||||
static int sMessageBegin(http_parser *hp) {
|
||||
HTTPParser *httpParser = (HTTPParser *)hp->data;
|
||||
httpParser->clearParse();
|
||||
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sMessageEnd(http_parser* hp)
|
||||
{
|
||||
HTTPParser* httpParser = (HTTPParser*) hp->data;
|
||||
httpParser->mISCompleted = true;
|
||||
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;
|
||||
static int sHeadComplete(http_parser *hp) {
|
||||
HTTPParser *httpParser = (HTTPParser *)hp->data;
|
||||
|
||||
if (httpParser->mUrl.empty())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (httpParser->mUrl.empty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct http_parser_url u;
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sUrlHandle(http_parser* hp, const char* url, size_t length)
|
||||
{
|
||||
HTTPParser* httpParser = (HTTPParser*) hp->data;
|
||||
httpParser->mUrl.append(url, length);
|
||||
static int sUrlHandle(http_parser *hp, const char *url, size_t length) {
|
||||
HTTPParser *httpParser = (HTTPParser *)hp->data;
|
||||
httpParser->mUrl.append(url, length);
|
||||
|
||||
return 0;
|
||||
}
|
||||
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 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;
|
||||
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;
|
||||
}
|
||||
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 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;
|
||||
}
|
||||
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;
|
||||
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;
|
||||
int mMethod = -1;
|
||||
bool mIsUpgrade = false;
|
||||
bool mIsWebSocket = false;
|
||||
bool mIsKeepAlive;
|
||||
bool mISCompleted;
|
||||
|
||||
bool mLastWasValue;
|
||||
std::string mCurrentField;
|
||||
std::string mCurrentValue;
|
||||
bool mLastWasValue;
|
||||
std::string mCurrentField;
|
||||
std::string mCurrentValue;
|
||||
|
||||
std::string mPath;
|
||||
std::string mQuery;
|
||||
std::string mStatus;
|
||||
std::map<std::string, std::string> mHeadValues;
|
||||
int mStatusCode;
|
||||
std::string mPath;
|
||||
std::string mQuery;
|
||||
std::string mStatus;
|
||||
std::map<std::string, std::string> mHeadValues;
|
||||
int mStatusCode;
|
||||
|
||||
std::string mUrl;
|
||||
std::string mBody;
|
||||
std::string mUrl;
|
||||
std::string mBody;
|
||||
|
||||
std::string mWSCacheFrame;
|
||||
std::string mWSParsePayload;
|
||||
WebSocketFormat::WebSocketFrameType mWSFrameType;
|
||||
std::string mWSCacheFrame;
|
||||
std::string mWSParsePayload;
|
||||
WebSocketFormat::WebSocketFrameType mWSFrameType;
|
||||
|
||||
private:
|
||||
friend class HttpService;
|
||||
friend class HttpService;
|
||||
};
|
||||
|
||||
}}}// namespace brynet::net::http
|
||||
} // namespace http
|
||||
} // namespace net
|
||||
} // namespace brynet
|
||||
|
@ -6,350 +6,301 @@
|
||||
#include <brynet/net/http/WebSocketFormat.hpp>
|
||||
#include <memory>
|
||||
|
||||
namespace brynet { namespace net { namespace http {
|
||||
namespace brynet {
|
||||
namespace net {
|
||||
namespace http {
|
||||
|
||||
class HttpService;
|
||||
class HttpSessionHandlers;
|
||||
|
||||
class HttpSession : public brynet::base::NonCopyable
|
||||
{
|
||||
class HttpSession : public brynet::base::NonCopyable {
|
||||
public:
|
||||
using Ptr = std::shared_ptr<HttpSession>;
|
||||
using Ptr = std::shared_ptr<HttpSession>;
|
||||
|
||||
using EnterCallback = std::function<void(const HttpSession::Ptr&, HttpSessionHandlers&)>;
|
||||
using HttpParserCallback = std::function<void(const HTTPParser&, const HttpSession::Ptr&)>;
|
||||
using WsCallback = std::function<void(const HttpSession::Ptr&,
|
||||
WebSocketFormat::WebSocketFrameType opcode,
|
||||
const std::string& payload)>;
|
||||
using EnterCallback = std::function<void(const HttpSession::Ptr &, HttpSessionHandlers &)>;
|
||||
using HttpParserCallback = std::function<void(const HTTPParser &, const HttpSession::Ptr &)>;
|
||||
using WsCallback = std::function<void(const HttpSession::Ptr &,
|
||||
WebSocketFormat::WebSocketFrameType opcode,
|
||||
const std::string &payload)>;
|
||||
|
||||
using ClosedCallback = std::function<void(const HttpSession::Ptr&)>;
|
||||
using WsConnectedCallback = std::function<void(const HttpSession::Ptr&, const HTTPParser&)>;
|
||||
using ClosedCallback = std::function<void(const HttpSession::Ptr &)>;
|
||||
using WsConnectedCallback = std::function<void(const HttpSession::Ptr &, const HTTPParser &)>;
|
||||
|
||||
public:
|
||||
template<typename PacketType>
|
||||
void send(PacketType&& packet,
|
||||
TcpConnection::PacketSendedCallback&& callback = nullptr)
|
||||
{
|
||||
mSession->send(std::forward<PacketType&&>(packet),
|
||||
std::move(callback));
|
||||
}
|
||||
void send(const char* packet,
|
||||
size_t len,
|
||||
TcpConnection::PacketSendedCallback&& callback = nullptr)
|
||||
{
|
||||
mSession->send(packet, len, std::move(callback));
|
||||
}
|
||||
template <typename PacketType>
|
||||
void send(PacketType &&packet,
|
||||
TcpConnection::PacketSendedCallback &&callback = nullptr) {
|
||||
mSession->send(std::forward<PacketType &&>(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 postShutdown() const {
|
||||
mSession->postShutdown();
|
||||
}
|
||||
|
||||
void postClose() const
|
||||
{
|
||||
mSession->postDisConnect();
|
||||
}
|
||||
void postClose() const {
|
||||
mSession->postDisConnect();
|
||||
}
|
||||
|
||||
protected:
|
||||
explicit HttpSession(TcpConnection::Ptr session)
|
||||
{
|
||||
mSession = std::move(session);
|
||||
}
|
||||
explicit HttpSession(TcpConnection::Ptr session) {
|
||||
mSession = std::move(session);
|
||||
}
|
||||
|
||||
virtual ~HttpSession() = default;
|
||||
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<make_shared_enabler>(std::move(session));
|
||||
}
|
||||
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<make_shared_enabler>(std::move(session));
|
||||
}
|
||||
|
||||
const TcpConnection::Ptr& getSession() const
|
||||
{
|
||||
return mSession;
|
||||
}
|
||||
const TcpConnection::Ptr &getSession() const {
|
||||
return mSession;
|
||||
}
|
||||
|
||||
const HttpParserCallback& getHttpCallback() const
|
||||
{
|
||||
return mHttpRequestCallback;
|
||||
}
|
||||
const HttpParserCallback &getHttpCallback() const {
|
||||
return mHttpRequestCallback;
|
||||
}
|
||||
|
||||
const ClosedCallback& getCloseCallback() const
|
||||
{
|
||||
return mCloseCallback;
|
||||
}
|
||||
const ClosedCallback &getCloseCallback() const {
|
||||
return mCloseCallback;
|
||||
}
|
||||
|
||||
const WsCallback& getWSCallback() const
|
||||
{
|
||||
return mWSCallback;
|
||||
}
|
||||
const WsCallback &getWSCallback() const {
|
||||
return mWSCallback;
|
||||
}
|
||||
|
||||
const WsConnectedCallback& getWSConnectedCallback() const
|
||||
{
|
||||
return mWSConnectedCallback;
|
||||
}
|
||||
const WsConnectedCallback &getWSConnectedCallback() const {
|
||||
return mWSConnectedCallback;
|
||||
}
|
||||
|
||||
private:
|
||||
void setHttpCallback(HttpParserCallback&& callback)
|
||||
{
|
||||
mHttpRequestCallback = std::move(callback);
|
||||
}
|
||||
void setHttpCallback(HttpParserCallback &&callback) {
|
||||
mHttpRequestCallback = std::move(callback);
|
||||
}
|
||||
|
||||
void setClosedCallback(ClosedCallback&& callback)
|
||||
{
|
||||
mCloseCallback = std::move(callback);
|
||||
}
|
||||
void setClosedCallback(ClosedCallback &&callback) {
|
||||
mCloseCallback = std::move(callback);
|
||||
}
|
||||
|
||||
void setWSCallback(WsCallback&& callback)
|
||||
{
|
||||
mWSCallback = std::move(callback);
|
||||
}
|
||||
void setWSCallback(WsCallback &&callback) {
|
||||
mWSCallback = std::move(callback);
|
||||
}
|
||||
|
||||
void setWSConnected(WsConnectedCallback&& callback)
|
||||
{
|
||||
mWSConnectedCallback = std::move(callback);
|
||||
}
|
||||
void setWSConnected(WsConnectedCallback &&callback) {
|
||||
mWSConnectedCallback = std::move(callback);
|
||||
}
|
||||
|
||||
private:
|
||||
TcpConnection::Ptr mSession;
|
||||
HttpParserCallback mHttpRequestCallback;
|
||||
WsCallback mWSCallback;
|
||||
ClosedCallback mCloseCallback;
|
||||
WsConnectedCallback mWSConnectedCallback;
|
||||
TcpConnection::Ptr mSession;
|
||||
HttpParserCallback mHttpRequestCallback;
|
||||
WsCallback mWSCallback;
|
||||
ClosedCallback mCloseCallback;
|
||||
WsConnectedCallback mWSConnectedCallback;
|
||||
|
||||
friend class HttpService;
|
||||
friend class HttpService;
|
||||
};
|
||||
|
||||
class HttpSessionHandlers
|
||||
{
|
||||
class HttpSessionHandlers {
|
||||
public:
|
||||
void setHttpCallback(HttpSession::HttpParserCallback&& callback)
|
||||
{
|
||||
mHttpRequestCallback = std::move(callback);
|
||||
}
|
||||
void setHttpCallback(HttpSession::HttpParserCallback &&callback) {
|
||||
mHttpRequestCallback = std::move(callback);
|
||||
}
|
||||
|
||||
void setClosedCallback(HttpSession::ClosedCallback&& callback)
|
||||
{
|
||||
mCloseCallback = std::move(callback);
|
||||
}
|
||||
void setClosedCallback(HttpSession::ClosedCallback &&callback) {
|
||||
mCloseCallback = std::move(callback);
|
||||
}
|
||||
|
||||
void setWSCallback(HttpSession::WsCallback&& callback)
|
||||
{
|
||||
mWSCallback = std::move(callback);
|
||||
}
|
||||
void setWSCallback(HttpSession::WsCallback &&callback) {
|
||||
mWSCallback = std::move(callback);
|
||||
}
|
||||
|
||||
void setWSConnected(HttpSession::WsConnectedCallback&& callback)
|
||||
{
|
||||
mWSConnectedCallback = 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;
|
||||
HttpSession::HttpParserCallback mHttpRequestCallback;
|
||||
HttpSession::WsCallback mWSCallback;
|
||||
HttpSession::ClosedCallback mCloseCallback;
|
||||
HttpSession::WsConnectedCallback mWSConnectedCallback;
|
||||
|
||||
friend class HttpService;
|
||||
friend class HttpService;
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
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<HTTPParser>(HTTP_BOTH);
|
||||
static void handle(const HttpSession::Ptr &httpSession) {
|
||||
/*TODO::keep alive and timeout close */
|
||||
auto &session = httpSession->getSession();
|
||||
auto httpParser = std::make_shared<HTTPParser>(HTTP_BOTH);
|
||||
|
||||
session->setDisConnectCallback([httpSession, httpParser](const TcpConnection::Ptr&) {
|
||||
if (!httpParser->isCompleted())
|
||||
{
|
||||
// try pass EOF to http parser
|
||||
HttpService::ProcessHttp(nullptr, 0, httpParser, httpSession);
|
||||
}
|
||||
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);
|
||||
}
|
||||
});
|
||||
const auto &tmp = httpSession->getCloseCallback();
|
||||
if (tmp != nullptr) {
|
||||
tmp(httpSession);
|
||||
}
|
||||
});
|
||||
|
||||
session->setDataCallback([httpSession, httpParser](
|
||||
brynet::base::BasePacketReader& reader) {
|
||||
size_t retLen = 0;
|
||||
session->setDataCallback([httpSession, httpParser](
|
||||
brynet::base::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();
|
||||
}
|
||||
}
|
||||
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();
|
||||
});
|
||||
}
|
||||
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;
|
||||
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();
|
||||
const auto &wsCallback = httpSession->getWSCallback();
|
||||
auto &cacheFrame = httpParser->getWSCacheFrame();
|
||||
auto &parseString = httpParser->getWSParseString();
|
||||
|
||||
while (leftLen > 0)
|
||||
{
|
||||
parseString.clear();
|
||||
while (leftLen > 0) {
|
||||
parseString.clear();
|
||||
|
||||
auto opcode = WebSocketFormat::WebSocketFrameType::ERROR_FRAME;
|
||||
size_t frameSize = 0;
|
||||
bool isFin = false;
|
||||
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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
// 如果当前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;
|
||||
leftLen -= frameSize;
|
||||
buffer += frameSize;
|
||||
|
||||
if (!isFin)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
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();
|
||||
}
|
||||
// 如果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);
|
||||
}
|
||||
}
|
||||
if (wsCallback != nullptr) {
|
||||
wsCallback(httpSession, opcode, parseString);
|
||||
}
|
||||
}
|
||||
|
||||
return (len - leftLen);
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
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());
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
return retlen;
|
||||
}
|
||||
};
|
||||
|
||||
}}}// namespace brynet::net::http
|
||||
} // namespace http
|
||||
} // namespace net
|
||||
} // namespace brynet
|
||||
|
@ -8,232 +8,205 @@
|
||||
#include <random>
|
||||
#include <string>
|
||||
|
||||
namespace brynet { namespace net { namespace http {
|
||||
namespace brynet {
|
||||
namespace net {
|
||||
namespace http {
|
||||
|
||||
class WebSocketFormat
|
||||
{
|
||||
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
|
||||
};
|
||||
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");
|
||||
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<unsigned int>(secKey.size()));
|
||||
s1.Final();
|
||||
unsigned char puDest[20];
|
||||
s1.GetHash(puDest);
|
||||
CSHA1 s1;
|
||||
s1.Update((unsigned char *)secKey.c_str(), static_cast<unsigned int>(secKey.size()));
|
||||
s1.Final();
|
||||
unsigned char puDest[20];
|
||||
s1.GetHash(puDest);
|
||||
|
||||
std::string base64Str = brynet::base::crypto::base64_encode((const unsigned char*) puDest, 20);
|
||||
std::string base64Str = brynet::base::crypto::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: ";
|
||||
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";
|
||||
response += base64Str;
|
||||
response += "\r\n\r\n";
|
||||
|
||||
return response;
|
||||
}
|
||||
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<unsigned int>(unixTime));
|
||||
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<unsigned int>(unixTime));
|
||||
|
||||
static_assert(std::is_same<std::string::value_type, char>::value, "");
|
||||
static_assert(std::is_same<std::string::value_type, char>::value, "");
|
||||
|
||||
const uint8_t head = static_cast<uint8_t>(frame_type) | (isFin ? 0x80 : 0x00);
|
||||
const uint8_t head = static_cast<uint8_t>(frame_type) | (isFin ? 0x80 : 0x00);
|
||||
|
||||
frame.clear();
|
||||
frame.push_back(static_cast<char>(head));
|
||||
if (payloadLen <= 125)
|
||||
{
|
||||
// mask << 7 | payloadLen, mask = 0
|
||||
frame.push_back(static_cast<uint8_t>(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<char>((payloadLen & 0xFF000000) >> 24));
|
||||
frame.push_back(static_cast<char>((payloadLen & 0x00FF0000) >> 16));
|
||||
frame.push_back(static_cast<char>((payloadLen & 0x0000FF00) >> 8));
|
||||
frame.push_back(static_cast<char>(payloadLen & 0x000000FF));
|
||||
}
|
||||
frame.clear();
|
||||
frame.push_back(static_cast<char>(head));
|
||||
if (payloadLen <= 125) {
|
||||
// mask << 7 | payloadLen, mask = 0
|
||||
frame.push_back(static_cast<uint8_t>(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<char>((payloadLen & 0xFF000000) >> 24));
|
||||
frame.push_back(static_cast<char>((payloadLen & 0x00FF0000) >> 16));
|
||||
frame.push_back(static_cast<char>((payloadLen & 0x0000FF00) >> 8));
|
||||
frame.push_back(static_cast<char>(payloadLen & 0x000000FF));
|
||||
}
|
||||
|
||||
if (masking)
|
||||
{
|
||||
frame[1] = ((uint8_t) frame[1]) | 0x80;
|
||||
uint8_t mask[4];
|
||||
for (auto& m : mask)
|
||||
{
|
||||
m = static_cast<uint8_t>(random());
|
||||
frame.push_back(m);
|
||||
}
|
||||
if (masking) {
|
||||
frame[1] = ((uint8_t)frame[1]) | 0x80;
|
||||
uint8_t mask[4];
|
||||
for (auto &m : mask) {
|
||||
m = static_cast<uint8_t>(random());
|
||||
frame.push_back(m);
|
||||
}
|
||||
|
||||
frame.reserve(frame.size() + payloadLen);
|
||||
frame.reserve(frame.size() + payloadLen);
|
||||
|
||||
for (size_t i = 0; i < payloadLen; i++)
|
||||
{
|
||||
frame.push_back(static_cast<uint8_t>(payload[i]) ^ mask[i % 4]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
frame.append(payload, payloadLen);
|
||||
}
|
||||
for (size_t i = 0; i < payloadLen; i++) {
|
||||
frame.push_back(static_cast<uint8_t>(payload[i]) ^ mask[i % 4]);
|
||||
}
|
||||
} else {
|
||||
frame.append(payload, payloadLen);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
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 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;
|
||||
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;
|
||||
}
|
||||
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;
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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[2] != 0 ||
|
||||
buffer[3] != 0 ||
|
||||
buffer[4] != 0 ||
|
||||
buffer[5] != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((buffer[6] & 0x80) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if ((buffer[6] & 0x80) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
payloadlen = (buffer[6] << 24) +
|
||||
(buffer[7] << 16) +
|
||||
(buffer[8] << 8) +
|
||||
buffer[9];
|
||||
pos = 10;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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++];
|
||||
}
|
||||
mask[0] = buffer[pos++];
|
||||
mask[1] = buffer[pos++];
|
||||
mask[2] = buffer[pos++];
|
||||
mask[3] = buffer[pos++];
|
||||
}
|
||||
|
||||
if (bufferSize < (pos + payloadlen))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
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);
|
||||
}
|
||||
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;
|
||||
frameSize = payloadlen + pos;
|
||||
|
||||
return true;
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
}}}// namespace brynet::net::http
|
||||
} // namespace http
|
||||
} // namespace net
|
||||
} // namespace brynet
|
||||
|
@ -2,30 +2,30 @@
|
||||
|
||||
#include <brynet/net/SocketLibTypes.hpp>
|
||||
|
||||
namespace brynet { namespace net { namespace port {
|
||||
namespace brynet {
|
||||
namespace net {
|
||||
namespace port {
|
||||
|
||||
#ifdef BRYNET_PLATFORM_WINDOWS
|
||||
class Win
|
||||
{
|
||||
class Win {
|
||||
public:
|
||||
enum class OverlappedType
|
||||
{
|
||||
OverlappedNone = 0,
|
||||
OverlappedRecv,
|
||||
OverlappedSend,
|
||||
};
|
||||
enum class OverlappedType {
|
||||
OverlappedNone = 0,
|
||||
OverlappedRecv,
|
||||
OverlappedSend,
|
||||
};
|
||||
|
||||
struct OverlappedExt
|
||||
{
|
||||
OVERLAPPED base;
|
||||
const OverlappedType OP;
|
||||
struct OverlappedExt {
|
||||
OVERLAPPED base;
|
||||
const OverlappedType OP;
|
||||
|
||||
OverlappedExt(OverlappedType op) BRYNET_NOEXCEPT : OP(op)
|
||||
{
|
||||
memset(&base, 0, sizeof(base));
|
||||
}
|
||||
};
|
||||
OverlappedExt(OverlappedType op) BRYNET_NOEXCEPT : OP(op) {
|
||||
memset(&base, 0, sizeof(base));
|
||||
}
|
||||
};
|
||||
};
|
||||
#endif
|
||||
|
||||
}}}// namespace brynet::net::port
|
||||
} // namespace port
|
||||
} // namespace net
|
||||
} // namespace brynet
|
||||
|
@ -6,205 +6,180 @@
|
||||
#include <future>
|
||||
#include <utility>
|
||||
|
||||
namespace brynet { namespace net { namespace wrapper {
|
||||
namespace brynet {
|
||||
namespace net {
|
||||
namespace wrapper {
|
||||
|
||||
using CompletedCallback = detail::AsyncConnectAddr::CompletedCallback;
|
||||
using ProcessTcpSocketCallback = detail::AsyncConnectAddr::ProcessTcpSocketCallback;
|
||||
using FailedCallback = detail::AsyncConnectAddr::FailedCallback;
|
||||
|
||||
template<typename Derived>
|
||||
class BaseSocketConnectBuilder
|
||||
{
|
||||
template <typename Derived>
|
||||
class BaseSocketConnectBuilder {
|
||||
public:
|
||||
virtual ~BaseSocketConnectBuilder() = default;
|
||||
virtual ~BaseSocketConnectBuilder() = default;
|
||||
|
||||
Derived& WithConnector(AsyncConnector::Ptr connector)
|
||||
{
|
||||
mConnector = std::move(connector);
|
||||
return static_cast<Derived&>(*this);
|
||||
}
|
||||
Derived &WithConnector(AsyncConnector::Ptr connector) {
|
||||
mConnector = std::move(connector);
|
||||
return static_cast<Derived &>(*this);
|
||||
}
|
||||
|
||||
Derived& WithAddr(std::string ip, size_t port)
|
||||
{
|
||||
mConnectOption.ip = std::move(ip);
|
||||
mConnectOption.port = port;
|
||||
return static_cast<Derived&>(*this);
|
||||
}
|
||||
Derived &WithAddr(std::string ip, size_t port) {
|
||||
mConnectOption.ip = std::move(ip);
|
||||
mConnectOption.port = port;
|
||||
return static_cast<Derived &>(*this);
|
||||
}
|
||||
|
||||
Derived& WithTimeout(std::chrono::nanoseconds timeout)
|
||||
{
|
||||
mConnectOption.timeout = timeout;
|
||||
return static_cast<Derived&>(*this);
|
||||
}
|
||||
Derived &WithTimeout(std::chrono::nanoseconds timeout) {
|
||||
mConnectOption.timeout = timeout;
|
||||
return static_cast<Derived &>(*this);
|
||||
}
|
||||
|
||||
Derived& AddSocketProcessCallback(const ProcessTcpSocketCallback& callback)
|
||||
{
|
||||
mConnectOption.processCallbacks.push_back(callback);
|
||||
return static_cast<Derived&>(*this);
|
||||
}
|
||||
Derived &AddSocketProcessCallback(const ProcessTcpSocketCallback &callback) {
|
||||
mConnectOption.processCallbacks.push_back(callback);
|
||||
return static_cast<Derived &>(*this);
|
||||
}
|
||||
|
||||
Derived& WithCompletedCallback(CompletedCallback callback)
|
||||
{
|
||||
mConnectOption.completedCallback = std::move(callback);
|
||||
return static_cast<Derived&>(*this);
|
||||
}
|
||||
Derived &WithCompletedCallback(CompletedCallback callback) {
|
||||
mConnectOption.completedCallback = std::move(callback);
|
||||
return static_cast<Derived &>(*this);
|
||||
}
|
||||
|
||||
Derived& WithFailedCallback(FailedCallback callback)
|
||||
{
|
||||
mConnectOption.failedCallback = std::move(callback);
|
||||
return static_cast<Derived&>(*this);
|
||||
}
|
||||
Derived &WithFailedCallback(FailedCallback callback) {
|
||||
mConnectOption.failedCallback = std::move(callback);
|
||||
return static_cast<Derived &>(*this);
|
||||
}
|
||||
|
||||
void asyncConnect() const
|
||||
{
|
||||
if (mConnector == nullptr)
|
||||
{
|
||||
throw BrynetCommonException("connector is nullptr");
|
||||
}
|
||||
if (mConnectOption.ip.empty())
|
||||
{
|
||||
throw BrynetCommonException("address is empty");
|
||||
}
|
||||
void asyncConnect() const {
|
||||
if (mConnector == nullptr) {
|
||||
throw BrynetCommonException("connector is nullptr");
|
||||
}
|
||||
if (mConnectOption.ip.empty()) {
|
||||
throw BrynetCommonException("address is empty");
|
||||
}
|
||||
|
||||
mConnector->asyncConnect(mConnectOption);
|
||||
}
|
||||
mConnector->asyncConnect(mConnectOption);
|
||||
}
|
||||
|
||||
TcpSocket::Ptr syncConnect()
|
||||
{
|
||||
if (mConnectOption.completedCallback != nullptr || mConnectOption.failedCallback != nullptr)
|
||||
{
|
||||
throw std::runtime_error("already setting completed callback or failed callback");
|
||||
}
|
||||
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<std::promise<TcpSocket::Ptr>>();
|
||||
mConnectOption.completedCallback = [socketPromise](TcpSocket::Ptr socket) {
|
||||
socketPromise->set_value(std::move(socket));
|
||||
};
|
||||
mConnectOption.failedCallback = [socketPromise]() {
|
||||
socketPromise->set_value(nullptr);
|
||||
};
|
||||
auto socketPromise = std::make_shared<std::promise<TcpSocket::Ptr> >();
|
||||
mConnectOption.completedCallback = [socketPromise](TcpSocket::Ptr socket) {
|
||||
socketPromise->set_value(std::move(socket));
|
||||
};
|
||||
mConnectOption.failedCallback = [socketPromise]() {
|
||||
socketPromise->set_value(nullptr);
|
||||
};
|
||||
|
||||
asyncConnect();
|
||||
asyncConnect();
|
||||
|
||||
auto future = socketPromise->get_future();
|
||||
if (future.wait_for(mConnectOption.timeout) != std::future_status::ready)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
auto future = socketPromise->get_future();
|
||||
if (future.wait_for(mConnectOption.timeout) != std::future_status::ready) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return future.get();
|
||||
}
|
||||
return future.get();
|
||||
}
|
||||
|
||||
private:
|
||||
AsyncConnector::Ptr mConnector;
|
||||
ConnectOption mConnectOption;
|
||||
AsyncConnector::Ptr mConnector;
|
||||
ConnectOption mConnectOption;
|
||||
};
|
||||
|
||||
class SocketConnectBuilder : public BaseSocketConnectBuilder<SocketConnectBuilder>
|
||||
{
|
||||
class SocketConnectBuilder : public BaseSocketConnectBuilder<SocketConnectBuilder> {
|
||||
};
|
||||
|
||||
template<typename Derived>
|
||||
class BaseConnectionBuilder
|
||||
{
|
||||
template <typename Derived>
|
||||
class BaseConnectionBuilder {
|
||||
public:
|
||||
Derived& WithService(TcpService::Ptr service)
|
||||
{
|
||||
mTcpService = std::move(service);
|
||||
return static_cast<Derived&>(*this);
|
||||
}
|
||||
Derived &WithService(TcpService::Ptr service) {
|
||||
mTcpService = std::move(service);
|
||||
return static_cast<Derived &>(*this);
|
||||
}
|
||||
|
||||
Derived& WithConnector(AsyncConnector::Ptr connector)
|
||||
{
|
||||
mConnectBuilder.WithConnector(std::move(connector));
|
||||
return static_cast<Derived&>(*this);
|
||||
}
|
||||
Derived &WithConnector(AsyncConnector::Ptr connector) {
|
||||
mConnectBuilder.WithConnector(std::move(connector));
|
||||
return static_cast<Derived &>(*this);
|
||||
}
|
||||
|
||||
Derived& WithAddr(std::string ip, size_t port)
|
||||
{
|
||||
mConnectBuilder.WithAddr(std::move(ip), port);
|
||||
return static_cast<Derived&>(*this);
|
||||
}
|
||||
Derived &WithAddr(std::string ip, size_t port) {
|
||||
mConnectBuilder.WithAddr(std::move(ip), port);
|
||||
return static_cast<Derived &>(*this);
|
||||
}
|
||||
|
||||
Derived& WithTimeout(std::chrono::nanoseconds timeout)
|
||||
{
|
||||
mConnectBuilder.WithTimeout(timeout);
|
||||
return static_cast<Derived&>(*this);
|
||||
}
|
||||
Derived &WithTimeout(std::chrono::nanoseconds timeout) {
|
||||
mConnectBuilder.WithTimeout(timeout);
|
||||
return static_cast<Derived &>(*this);
|
||||
}
|
||||
|
||||
Derived& AddSocketProcessCallback(const ProcessTcpSocketCallback& callback)
|
||||
{
|
||||
mConnectBuilder.AddSocketProcessCallback(callback);
|
||||
return static_cast<Derived&>(*this);
|
||||
}
|
||||
Derived &AddSocketProcessCallback(const ProcessTcpSocketCallback &callback) {
|
||||
mConnectBuilder.AddSocketProcessCallback(callback);
|
||||
return static_cast<Derived &>(*this);
|
||||
}
|
||||
|
||||
Derived& WithFailedCallback(FailedCallback callback)
|
||||
{
|
||||
mConnectBuilder.WithFailedCallback(std::move(callback));
|
||||
return static_cast<Derived&>(*this);
|
||||
}
|
||||
Derived &WithFailedCallback(FailedCallback callback) {
|
||||
mConnectBuilder.WithFailedCallback(std::move(callback));
|
||||
return static_cast<Derived &>(*this);
|
||||
}
|
||||
|
||||
Derived& WithMaxRecvBufferSize(size_t size)
|
||||
{
|
||||
mOption.maxRecvBufferSize = size;
|
||||
return static_cast<Derived&>(*this);
|
||||
}
|
||||
Derived &WithMaxRecvBufferSize(size_t size) {
|
||||
mOption.maxRecvBufferSize = size;
|
||||
return static_cast<Derived &>(*this);
|
||||
}
|
||||
|
||||
#ifdef BRYNET_USE_OPENSSL
|
||||
Derived& WithSSL()
|
||||
{
|
||||
mOption.useSSL = true;
|
||||
return static_cast<Derived&>(*this);
|
||||
}
|
||||
Derived &WithSSL() {
|
||||
mOption.useSSL = true;
|
||||
return static_cast<Derived &>(*this);
|
||||
}
|
||||
#endif
|
||||
Derived& WithForceSameThreadLoop()
|
||||
{
|
||||
mOption.forceSameThreadLoop = true;
|
||||
return static_cast<Derived&>(*this);
|
||||
}
|
||||
Derived &WithForceSameThreadLoop() {
|
||||
mOption.forceSameThreadLoop = true;
|
||||
return static_cast<Derived &>(*this);
|
||||
}
|
||||
|
||||
Derived& AddEnterCallback(const TcpConnection::EnterCallback& callback)
|
||||
{
|
||||
mOption.enterCallback.push_back(callback);
|
||||
return static_cast<Derived&>(*this);
|
||||
}
|
||||
Derived &AddEnterCallback(const TcpConnection::EnterCallback &callback) {
|
||||
mOption.enterCallback.push_back(callback);
|
||||
return static_cast<Derived &>(*this);
|
||||
}
|
||||
|
||||
void asyncConnect()
|
||||
{
|
||||
auto service = mTcpService;
|
||||
auto option = mOption;
|
||||
mConnectBuilder.WithCompletedCallback([service, option](TcpSocket::Ptr socket) mutable {
|
||||
service->addTcpConnection(std::move(socket), option);
|
||||
});
|
||||
void asyncConnect() {
|
||||
auto service = mTcpService;
|
||||
auto option = mOption;
|
||||
mConnectBuilder.WithCompletedCallback([service, option](TcpSocket::Ptr socket) mutable {
|
||||
service->addTcpConnection(std::move(socket), option);
|
||||
});
|
||||
|
||||
mConnectBuilder.asyncConnect();
|
||||
}
|
||||
mConnectBuilder.asyncConnect();
|
||||
}
|
||||
|
||||
TcpConnection::Ptr syncConnect()
|
||||
{
|
||||
auto sessionPromise = std::make_shared<std::promise<TcpConnection::Ptr>>();
|
||||
TcpConnection::Ptr syncConnect() {
|
||||
auto sessionPromise = std::make_shared<std::promise<TcpConnection::Ptr> >();
|
||||
|
||||
auto option = mOption;
|
||||
option.enterCallback.push_back([sessionPromise](const TcpConnection::Ptr& session) {
|
||||
sessionPromise->set_value(session);
|
||||
});
|
||||
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();
|
||||
}
|
||||
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;
|
||||
TcpService::Ptr mTcpService;
|
||||
ConnectionOption mOption;
|
||||
SocketConnectBuilder mConnectBuilder;
|
||||
};
|
||||
|
||||
class ConnectionBuilder : public BaseConnectionBuilder<ConnectionBuilder>
|
||||
{
|
||||
class ConnectionBuilder : public BaseConnectionBuilder<ConnectionBuilder> {
|
||||
};
|
||||
|
||||
}}}// namespace brynet::net::wrapper
|
||||
} // namespace wrapper
|
||||
} // namespace net
|
||||
} // namespace brynet
|
||||
|
@ -4,90 +4,81 @@
|
||||
#include <brynet/net/wrapper/ConnectionBuilder.hpp>
|
||||
#include <utility>
|
||||
|
||||
namespace brynet { namespace net { namespace wrapper {
|
||||
namespace brynet {
|
||||
namespace net {
|
||||
namespace wrapper {
|
||||
|
||||
class HttpConnectionBuilder
|
||||
{
|
||||
class HttpConnectionBuilder {
|
||||
public:
|
||||
HttpConnectionBuilder& WithService(TcpService::Ptr service)
|
||||
{
|
||||
mBuilder.WithService(std::move(service));
|
||||
return *this;
|
||||
}
|
||||
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 &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 &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 &WithTimeout(std::chrono::nanoseconds timeout) {
|
||||
mBuilder.WithTimeout(timeout);
|
||||
return *this;
|
||||
}
|
||||
|
||||
HttpConnectionBuilder& AddSocketProcessCallback(const ProcessTcpSocketCallback& callback)
|
||||
{
|
||||
mBuilder.AddSocketProcessCallback(callback);
|
||||
return *this;
|
||||
}
|
||||
HttpConnectionBuilder &AddSocketProcessCallback(const ProcessTcpSocketCallback &callback) {
|
||||
mBuilder.AddSocketProcessCallback(callback);
|
||||
return *this;
|
||||
}
|
||||
|
||||
HttpConnectionBuilder& WithEnterCallback(http::HttpSession::EnterCallback&& callback)
|
||||
{
|
||||
mHttpEnterCallback = std::move(callback);
|
||||
return *this;
|
||||
}
|
||||
HttpConnectionBuilder &WithEnterCallback(http::HttpSession::EnterCallback &&callback) {
|
||||
mHttpEnterCallback = std::move(callback);
|
||||
return *this;
|
||||
}
|
||||
|
||||
HttpConnectionBuilder& WithFailedCallback(FailedCallback callback)
|
||||
{
|
||||
mBuilder.WithFailedCallback(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;
|
||||
}
|
||||
HttpConnectionBuilder &WithMaxRecvBufferSize(size_t size) {
|
||||
mBuilder.WithMaxRecvBufferSize(size);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifdef BRYNET_USE_OPENSSL
|
||||
HttpConnectionBuilder& WithSSL()
|
||||
{
|
||||
mBuilder.WithSSL();
|
||||
return *this;
|
||||
}
|
||||
HttpConnectionBuilder &WithSSL() {
|
||||
mBuilder.WithSSL();
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
HttpConnectionBuilder& WithForceSameThreadLoop()
|
||||
{
|
||||
mBuilder.WithForceSameThreadLoop();
|
||||
return *this;
|
||||
}
|
||||
HttpConnectionBuilder &WithForceSameThreadLoop() {
|
||||
mBuilder.WithForceSameThreadLoop();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void asyncConnect()
|
||||
{
|
||||
if (mHttpEnterCallback == nullptr)
|
||||
{
|
||||
throw BrynetCommonException("not setting http enter callback");
|
||||
}
|
||||
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) {
|
||||
http::HttpService::setup(session, callback);
|
||||
});
|
||||
builder.asyncConnect();
|
||||
}
|
||||
auto callback = mHttpEnterCallback;
|
||||
auto builder = mBuilder;
|
||||
builder.AddEnterCallback([callback](const TcpConnection::Ptr &session) {
|
||||
http::HttpService::setup(session, callback);
|
||||
});
|
||||
builder.asyncConnect();
|
||||
}
|
||||
|
||||
private:
|
||||
http::HttpSession::EnterCallback mHttpEnterCallback;
|
||||
ConnectionBuilder mBuilder;
|
||||
http::HttpSession::EnterCallback mHttpEnterCallback;
|
||||
ConnectionBuilder mBuilder;
|
||||
};
|
||||
|
||||
}}}// namespace brynet::net::wrapper
|
||||
} // namespace wrapper
|
||||
} // namespace net
|
||||
} // namespace brynet
|
||||
|
@ -4,76 +4,69 @@
|
||||
#include <brynet/net/wrapper/ServiceBuilder.hpp>
|
||||
#include <utility>
|
||||
|
||||
namespace brynet { namespace net { namespace wrapper {
|
||||
namespace brynet {
|
||||
namespace net {
|
||||
namespace wrapper {
|
||||
|
||||
class HttpListenerBuilder
|
||||
{
|
||||
class HttpListenerBuilder {
|
||||
public:
|
||||
HttpListenerBuilder& WithService(TcpService::Ptr service)
|
||||
{
|
||||
mBuilder.WithService(std::move(service));
|
||||
return *this;
|
||||
}
|
||||
HttpListenerBuilder &WithService(TcpService::Ptr service) {
|
||||
mBuilder.WithService(std::move(service));
|
||||
return *this;
|
||||
}
|
||||
|
||||
HttpListenerBuilder& WithEnterCallback(http::HttpSession::EnterCallback&& callback)
|
||||
{
|
||||
mHttpEnterCallback = std::move(callback);
|
||||
return *this;
|
||||
}
|
||||
HttpListenerBuilder &WithEnterCallback(http::HttpSession::EnterCallback &&callback) {
|
||||
mHttpEnterCallback = std::move(callback);
|
||||
return *this;
|
||||
}
|
||||
|
||||
HttpListenerBuilder& AddSocketProcess(const ListenThread::TcpSocketProcessCallback& callback)
|
||||
{
|
||||
mBuilder.AddSocketProcess(callback);
|
||||
return *this;
|
||||
}
|
||||
HttpListenerBuilder &AddSocketProcess(const ListenThread::TcpSocketProcessCallback &callback) {
|
||||
mBuilder.AddSocketProcess(callback);
|
||||
return *this;
|
||||
}
|
||||
|
||||
HttpListenerBuilder& WithMaxRecvBufferSize(size_t size)
|
||||
{
|
||||
mBuilder.WithMaxRecvBufferSize(size);
|
||||
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;
|
||||
}
|
||||
HttpListenerBuilder &WithSSL(SSLHelper::Ptr sslHelper) {
|
||||
mBuilder.WithSSL(std::move(sslHelper));
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
HttpListenerBuilder& WithForceSameThreadLoop()
|
||||
{
|
||||
mBuilder.WithForceSameThreadLoop();
|
||||
return *this;
|
||||
}
|
||||
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 &WithAddr(bool ipV6, std::string ip, size_t port) {
|
||||
mBuilder.WithAddr(ipV6, std::move(ip), port);
|
||||
return *this;
|
||||
}
|
||||
|
||||
HttpListenerBuilder& WithReusePort()
|
||||
{
|
||||
mBuilder.WithReusePort();
|
||||
return *this;
|
||||
}
|
||||
HttpListenerBuilder &WithReusePort() {
|
||||
mBuilder.WithReusePort();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void asyncRun()
|
||||
{
|
||||
if (mHttpEnterCallback == nullptr)
|
||||
{
|
||||
throw BrynetCommonException("not setting http enter callback");
|
||||
}
|
||||
void asyncRun() {
|
||||
if (mHttpEnterCallback == nullptr) {
|
||||
throw BrynetCommonException("not setting http enter callback");
|
||||
}
|
||||
|
||||
auto callback = mHttpEnterCallback;
|
||||
mBuilder.AddEnterCallback([callback](const TcpConnection::Ptr& session) {
|
||||
http::HttpService::setup(session, callback);
|
||||
});
|
||||
mBuilder.asyncRun();
|
||||
}
|
||||
auto callback = mHttpEnterCallback;
|
||||
mBuilder.AddEnterCallback([callback](const TcpConnection::Ptr &session) {
|
||||
http::HttpService::setup(session, callback);
|
||||
});
|
||||
mBuilder.asyncRun();
|
||||
}
|
||||
|
||||
private:
|
||||
http::HttpSession::EnterCallback mHttpEnterCallback;
|
||||
ListenerBuilder mBuilder;
|
||||
http::HttpSession::EnterCallback mHttpEnterCallback;
|
||||
ListenerBuilder mBuilder;
|
||||
};
|
||||
|
||||
}}}// namespace brynet::net::wrapper
|
||||
} // namespace wrapper
|
||||
} // namespace net
|
||||
} // namespace brynet
|
||||
|
@ -6,111 +6,100 @@
|
||||
#include <brynet/net/detail/ConnectionOption.hpp>
|
||||
#include <utility>
|
||||
|
||||
namespace brynet { namespace net { namespace wrapper {
|
||||
namespace brynet {
|
||||
namespace net {
|
||||
namespace wrapper {
|
||||
|
||||
template<typename Derived>
|
||||
class BaseListenerBuilder
|
||||
{
|
||||
template <typename Derived>
|
||||
class BaseListenerBuilder {
|
||||
public:
|
||||
virtual ~BaseListenerBuilder() = default;
|
||||
virtual ~BaseListenerBuilder() = default;
|
||||
|
||||
Derived& WithService(TcpService::Ptr service)
|
||||
{
|
||||
mTcpService = std::move(service);
|
||||
return static_cast<Derived&>(*this);
|
||||
}
|
||||
Derived &WithService(TcpService::Ptr service) {
|
||||
mTcpService = std::move(service);
|
||||
return static_cast<Derived &>(*this);
|
||||
}
|
||||
|
||||
Derived& WithAddr(bool ipV6, std::string ip, size_t port)
|
||||
{
|
||||
mIsIpV6 = ipV6;
|
||||
mListenAddr = std::move(ip);
|
||||
mPort = port;
|
||||
return static_cast<Derived&>(*this);
|
||||
}
|
||||
Derived &WithAddr(bool ipV6, std::string ip, size_t port) {
|
||||
mIsIpV6 = ipV6;
|
||||
mListenAddr = std::move(ip);
|
||||
mPort = port;
|
||||
return static_cast<Derived &>(*this);
|
||||
}
|
||||
|
||||
Derived& WithReusePort()
|
||||
{
|
||||
mEnabledReusePort = true;
|
||||
return static_cast<Derived&>(*this);
|
||||
}
|
||||
Derived &WithReusePort() {
|
||||
mEnabledReusePort = true;
|
||||
return static_cast<Derived &>(*this);
|
||||
}
|
||||
|
||||
Derived& AddSocketProcess(const ListenThread::TcpSocketProcessCallback& callback)
|
||||
{
|
||||
mSocketProcessCallbacks.push_back(callback);
|
||||
return static_cast<Derived&>(*this);
|
||||
}
|
||||
Derived &AddSocketProcess(const ListenThread::TcpSocketProcessCallback &callback) {
|
||||
mSocketProcessCallbacks.push_back(callback);
|
||||
return static_cast<Derived &>(*this);
|
||||
}
|
||||
|
||||
Derived& WithMaxRecvBufferSize(size_t size)
|
||||
{
|
||||
mSocketOption.maxRecvBufferSize = size;
|
||||
return static_cast<Derived&>(*this);
|
||||
}
|
||||
Derived &WithMaxRecvBufferSize(size_t size) {
|
||||
mSocketOption.maxRecvBufferSize = size;
|
||||
return static_cast<Derived &>(*this);
|
||||
}
|
||||
#ifdef BRYNET_USE_OPENSSL
|
||||
Derived& WithSSL(SSLHelper::Ptr sslHelper)
|
||||
{
|
||||
mSocketOption.sslHelper = std::move(sslHelper);
|
||||
mSocketOption.useSSL = true;
|
||||
return static_cast<Derived&>(*this);
|
||||
}
|
||||
Derived &WithSSL(SSLHelper::Ptr sslHelper) {
|
||||
mSocketOption.sslHelper = std::move(sslHelper);
|
||||
mSocketOption.useSSL = true;
|
||||
return static_cast<Derived &>(*this);
|
||||
}
|
||||
#endif
|
||||
Derived& WithForceSameThreadLoop()
|
||||
{
|
||||
mSocketOption.forceSameThreadLoop = true;
|
||||
return static_cast<Derived&>(*this);
|
||||
}
|
||||
Derived &WithForceSameThreadLoop() {
|
||||
mSocketOption.forceSameThreadLoop = true;
|
||||
return static_cast<Derived &>(*this);
|
||||
}
|
||||
|
||||
Derived& AddEnterCallback(const TcpConnection::EnterCallback& callback)
|
||||
{
|
||||
mSocketOption.enterCallback.push_back(callback);
|
||||
return static_cast<Derived&>(*this);
|
||||
}
|
||||
Derived &AddEnterCallback(const TcpConnection::EnterCallback &callback) {
|
||||
mSocketOption.enterCallback.push_back(callback);
|
||||
return static_cast<Derived &>(*this);
|
||||
}
|
||||
|
||||
void asyncRun()
|
||||
{
|
||||
if (mTcpService == nullptr)
|
||||
{
|
||||
throw BrynetCommonException("tcp service is nullptr");
|
||||
}
|
||||
if (mListenAddr.empty())
|
||||
{
|
||||
throw BrynetCommonException("not config listen addr");
|
||||
}
|
||||
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](brynet::net::TcpSocket::Ptr socket) {
|
||||
service->addTcpConnection(std::move(socket), option);
|
||||
},
|
||||
mSocketProcessCallbacks,
|
||||
mEnabledReusePort);
|
||||
mListenThread->startListen();
|
||||
}
|
||||
auto service = mTcpService;
|
||||
auto option = mSocketOption;
|
||||
mListenThread = ListenThread::Create(
|
||||
mIsIpV6,
|
||||
mListenAddr,
|
||||
mPort,
|
||||
[service, option](brynet::net::TcpSocket::Ptr socket) {
|
||||
service->addTcpConnection(std::move(socket), option);
|
||||
},
|
||||
mSocketProcessCallbacks,
|
||||
mEnabledReusePort);
|
||||
mListenThread->startListen();
|
||||
}
|
||||
|
||||
void stop()
|
||||
{
|
||||
if (mListenThread)
|
||||
{
|
||||
mListenThread->stopListen();
|
||||
}
|
||||
}
|
||||
void stop() {
|
||||
if (mListenThread) {
|
||||
mListenThread->stopListen();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
TcpService::Ptr mTcpService;
|
||||
std::vector<ListenThread::TcpSocketProcessCallback> mSocketProcessCallbacks;
|
||||
ConnectionOption mSocketOption;
|
||||
std::string mListenAddr;
|
||||
int mPort = 0;
|
||||
bool mIsIpV6 = false;
|
||||
bool mEnabledReusePort = false;
|
||||
ListenThread::Ptr mListenThread;
|
||||
TcpService::Ptr mTcpService;
|
||||
std::vector<ListenThread::TcpSocketProcessCallback> mSocketProcessCallbacks;
|
||||
ConnectionOption mSocketOption;
|
||||
std::string mListenAddr;
|
||||
int mPort = 0;
|
||||
bool mIsIpV6 = false;
|
||||
bool mEnabledReusePort = false;
|
||||
ListenThread::Ptr mListenThread;
|
||||
};
|
||||
|
||||
class ListenerBuilder : public BaseListenerBuilder<ListenerBuilder>
|
||||
{
|
||||
class ListenerBuilder : public BaseListenerBuilder<ListenerBuilder> {
|
||||
};
|
||||
|
||||
}}}// namespace brynet::net::wrapper
|
||||
} // namespace wrapper
|
||||
} // namespace net
|
||||
} // namespace brynet
|
||||
|
Loading…
Reference in New Issue
Block a user