Ran clang format on brynet.

This commit is contained in:
Relintai 2021-05-14 17:16:45 +02:00
parent 729c6b17d3
commit 07dcd7774a
43 changed files with 4803 additions and 5770 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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