2020-11-24 15:41:18 +01:00
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include <memory>
|
|
|
|
|
#include <functional>
|
|
|
|
|
#include <deque>
|
|
|
|
|
#include <chrono>
|
|
|
|
|
#include <cassert>
|
|
|
|
|
#include <cstring>
|
|
|
|
|
#include <cmath>
|
|
|
|
|
|
|
|
|
|
#include <brynet/base/Buffer.hpp>
|
|
|
|
|
#include <brynet/base/Timer.hpp>
|
|
|
|
|
#include <brynet/base/NonCopyable.hpp>
|
|
|
|
|
#include <brynet/base/Any.hpp>
|
|
|
|
|
#include <brynet/base/Noexcept.hpp>
|
|
|
|
|
#include <brynet/net/SocketLibFunction.hpp>
|
|
|
|
|
#include <brynet/net/Channel.hpp>
|
|
|
|
|
#include <brynet/net/EventLoop.hpp>
|
|
|
|
|
#include <brynet/net/Socket.hpp>
|
|
|
|
|
#include <brynet/net/SSLHelper.hpp>
|
|
|
|
|
|
|
|
|
|
#ifdef BRYNET_USE_OPENSSL
|
|
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
|
extern "C" {
|
|
|
|
|
#endif
|
|
|
|
|
#include <openssl/ssl.h>
|
|
|
|
|
#include <openssl/err.h>
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
namespace brynet { namespace net {
|
|
|
|
|
|
|
|
|
|
class TcpConnection : public Channel,
|
|
|
|
|
public brynet::base::NonCopyable,
|
|
|
|
|
public std::enable_shared_from_this<TcpConnection>
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
using Ptr = std::shared_ptr<TcpConnection>;
|
|
|
|
|
|
|
|
|
|
using EnterCallback = std::function<void(Ptr)>;
|
2020-11-25 00:20:41 +01:00
|
|
|
|
using DataCallback = std::function<size_t(const char* buffer, size_t len)>;
|
2020-11-24 15:41:18 +01:00
|
|
|
|
using DisconnectedCallback = std::function<void(Ptr)>;
|
|
|
|
|
using PacketSendedCallback = std::function<void(void)>;
|
|
|
|
|
|
2020-11-25 00:20:41 +01:00
|
|
|
|
using PacketPtr = std::shared_ptr<std::string>;
|
|
|
|
|
|
2020-11-24 15:41:18 +01:00
|
|
|
|
public:
|
|
|
|
|
Ptr static Create(TcpSocket::Ptr socket,
|
|
|
|
|
size_t maxRecvBufferSize,
|
|
|
|
|
EnterCallback&& enterCallback,
|
|
|
|
|
const EventLoop::Ptr& eventLoop,
|
|
|
|
|
const SSLHelper::Ptr& sslHelper = nullptr)
|
|
|
|
|
{
|
|
|
|
|
class make_shared_enabler : public TcpConnection
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
make_shared_enabler(TcpSocket::Ptr socket,
|
|
|
|
|
size_t maxRecvBufferSize,
|
|
|
|
|
EnterCallback&& enterCallback,
|
|
|
|
|
EventLoop::Ptr eventLoop)
|
|
|
|
|
:
|
|
|
|
|
TcpConnection(std::move(socket),
|
|
|
|
|
maxRecvBufferSize,
|
|
|
|
|
std::move(enterCallback),
|
|
|
|
|
std::move(eventLoop))
|
|
|
|
|
{}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const auto isServerSide = socket->isServerSide();
|
|
|
|
|
auto session = std::make_shared<make_shared_enabler>(
|
|
|
|
|
std::move(socket),
|
|
|
|
|
maxRecvBufferSize,
|
|
|
|
|
std::move(enterCallback),
|
|
|
|
|
eventLoop);
|
|
|
|
|
(void)isServerSide;
|
|
|
|
|
#ifdef BRYNET_USE_OPENSSL
|
|
|
|
|
if(sslHelper != nullptr)
|
|
|
|
|
{
|
|
|
|
|
if (isServerSide)
|
|
|
|
|
{
|
|
|
|
|
if (sslHelper->getOpenSSLCTX() == nullptr ||
|
|
|
|
|
!session->initAcceptSSL(sslHelper->getOpenSSLCTX()))
|
|
|
|
|
{
|
|
|
|
|
throw std::runtime_error("init ssl failed");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (!session->initConnectSSL())
|
|
|
|
|
{
|
|
|
|
|
throw std::runtime_error("init ssl failed");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
if (sslHelper != nullptr)
|
|
|
|
|
{
|
|
|
|
|
throw std::runtime_error("not enable ssl");
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
eventLoop->runAsyncFunctor([session]()
|
2020-11-25 00:20:41 +01:00
|
|
|
|
{
|
|
|
|
|
session->onEnterEventLoop();
|
|
|
|
|
});
|
2020-11-24 15:41:18 +01:00
|
|
|
|
return session;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const EventLoop::Ptr& getEventLoop() const
|
|
|
|
|
{
|
|
|
|
|
return mEventLoop;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//TODO::如果所属EventLoop已经没有工作,则可能导致内存无限大,因为所投递的请求都没有得到处理
|
|
|
|
|
|
|
|
|
|
void send(
|
|
|
|
|
const char* buffer,
|
|
|
|
|
size_t len,
|
|
|
|
|
PacketSendedCallback&& callback = nullptr)
|
|
|
|
|
{
|
2020-11-25 00:20:41 +01:00
|
|
|
|
send(makePacket(buffer, len), std::move(callback));
|
2020-11-24 15:41:18 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-11-25 00:20:41 +01:00
|
|
|
|
template<typename PacketType>
|
2020-11-24 15:41:18 +01:00
|
|
|
|
void send(
|
2020-11-25 00:20:41 +01:00
|
|
|
|
PacketType&& packet,
|
|
|
|
|
PacketSendedCallback&&
|
|
|
|
|
callback = nullptr)
|
2020-11-24 15:41:18 +01:00
|
|
|
|
{
|
2020-11-25 00:20:41 +01:00
|
|
|
|
auto packetCapture = std::forward<PacketType>(packet);
|
|
|
|
|
auto callbackCapture = std::move(callback);
|
2020-11-24 15:41:18 +01:00
|
|
|
|
auto sharedThis = shared_from_this();
|
2020-11-25 00:20:41 +01:00
|
|
|
|
mEventLoop->runAsyncFunctor(
|
|
|
|
|
[sharedThis, packetCapture, callbackCapture]() mutable {
|
|
|
|
|
const auto len = packetCapture->size();
|
2020-11-24 15:41:18 +01:00
|
|
|
|
sharedThis->mSendList.emplace_back(PendingPacket{
|
2020-11-25 00:20:41 +01:00
|
|
|
|
std::move(packetCapture),
|
2020-11-24 15:41:18 +01:00
|
|
|
|
len,
|
2020-11-25 00:20:41 +01:00
|
|
|
|
std::move(callbackCapture) });
|
2020-11-24 15:41:18 +01:00
|
|
|
|
sharedThis->runAfterFlush();
|
2020-11-25 00:20:41 +01:00
|
|
|
|
});
|
2020-11-24 15:41:18 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-11-25 00:20:41 +01:00
|
|
|
|
void setDataCallback(DataCallback&& cb)
|
2020-11-24 15:41:18 +01:00
|
|
|
|
{
|
|
|
|
|
auto sharedThis = shared_from_this();
|
2020-11-25 00:20:41 +01:00
|
|
|
|
mEventLoop->runAsyncFunctor([sharedThis, cb]() mutable {
|
|
|
|
|
sharedThis->mDataCallback = std::move(cb);
|
2020-11-24 15:41:18 +01:00
|
|
|
|
sharedThis->processRecvMessage();
|
2020-11-25 00:20:41 +01:00
|
|
|
|
});
|
2020-11-24 15:41:18 +01:00
|
|
|
|
}
|
|
|
|
|
void setDisConnectCallback(DisconnectedCallback&& cb)
|
|
|
|
|
{
|
|
|
|
|
auto sharedThis = shared_from_this();
|
2020-11-25 00:20:41 +01:00
|
|
|
|
mEventLoop->runAsyncFunctor([sharedThis, cb]() mutable {
|
2020-11-24 15:41:18 +01:00
|
|
|
|
sharedThis->mDisConnectCallback = std::move(cb);
|
2020-11-25 00:20:41 +01:00
|
|
|
|
});
|
2020-11-24 15:41:18 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* if checkTime is zero, will cancel check heartbeat */
|
|
|
|
|
void setHeartBeat(std::chrono::nanoseconds checkTime)
|
|
|
|
|
{
|
|
|
|
|
auto sharedThis = shared_from_this();
|
2020-11-25 00:20:41 +01:00
|
|
|
|
mEventLoop->runAsyncFunctor([sharedThis, checkTime]() {
|
2020-11-24 15:41:18 +01:00
|
|
|
|
if (sharedThis->mTimer.lock() != nullptr)
|
|
|
|
|
{
|
|
|
|
|
sharedThis->mTimer.lock()->cancel();
|
|
|
|
|
sharedThis->mTimer.reset();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sharedThis->mCheckTime = checkTime;
|
|
|
|
|
sharedThis->startPingCheckTimer();
|
2020-11-25 00:20:41 +01:00
|
|
|
|
});
|
2020-11-24 15:41:18 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void postDisConnect()
|
|
|
|
|
{
|
|
|
|
|
auto sharedThis = shared_from_this();
|
2020-11-25 00:20:41 +01:00
|
|
|
|
mEventLoop->runAsyncFunctor([sharedThis]() {
|
2020-11-24 15:41:18 +01:00
|
|
|
|
sharedThis->procCloseInLoop();
|
2020-11-25 00:20:41 +01:00
|
|
|
|
});
|
2020-11-24 15:41:18 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void postShutdown()
|
|
|
|
|
{
|
|
|
|
|
auto sharedThis = shared_from_this();
|
2020-11-25 00:20:41 +01:00
|
|
|
|
mEventLoop->runAsyncFunctor([sharedThis]() {
|
|
|
|
|
sharedThis->mEventLoop->runFunctorAfterLoop([sharedThis]() {
|
2020-11-24 15:41:18 +01:00
|
|
|
|
sharedThis->procShutdownInLoop();
|
2020-11-25 00:20:41 +01:00
|
|
|
|
});
|
2020-11-24 15:41:18 +01:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const std::string& getIP() const
|
|
|
|
|
{
|
|
|
|
|
return mIP;
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-25 00:20:41 +01:00
|
|
|
|
static TcpConnection::PacketPtr makePacket(const char* buffer, size_t len)
|
|
|
|
|
{
|
|
|
|
|
return std::make_shared<std::string>(buffer, len);
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-24 15:41:18 +01:00
|
|
|
|
protected:
|
|
|
|
|
TcpConnection(TcpSocket::Ptr socket,
|
|
|
|
|
size_t maxRecvBufferSize,
|
|
|
|
|
EnterCallback&& enterCallback,
|
|
|
|
|
EventLoop::Ptr eventLoop) BRYNET_NOEXCEPT
|
|
|
|
|
:
|
|
|
|
|
#ifdef BRYNET_PLATFORM_WINDOWS
|
|
|
|
|
mOvlRecv(port::Win::OverlappedType::OverlappedRecv),
|
|
|
|
|
mOvlSend(port::Win::OverlappedType::OverlappedSend),
|
|
|
|
|
mPostClose(false),
|
|
|
|
|
#endif
|
|
|
|
|
mIP(socket->getRemoteIP()),
|
|
|
|
|
mSocket(std::move(socket)),
|
|
|
|
|
mEventLoop(std::move(eventLoop)),
|
|
|
|
|
mAlreadyClose(false),
|
|
|
|
|
mMaxRecvBufferSize(maxRecvBufferSize),
|
|
|
|
|
mEnterCallback(std::move(enterCallback))
|
|
|
|
|
{
|
|
|
|
|
mRecvData = false;
|
|
|
|
|
mCheckTime = std::chrono::steady_clock::duration::zero();
|
|
|
|
|
mIsPostFlush = false;
|
|
|
|
|
|
|
|
|
|
mCanWrite = true;
|
|
|
|
|
|
|
|
|
|
#ifdef BRYNET_PLATFORM_WINDOWS
|
|
|
|
|
mPostRecvCheck = false;
|
|
|
|
|
mPostWriteCheck = false;
|
|
|
|
|
#endif
|
|
|
|
|
growRecvBuffer();
|
|
|
|
|
|
|
|
|
|
#ifdef BRYNET_USE_OPENSSL
|
|
|
|
|
mSSLCtx = nullptr;
|
|
|
|
|
mSSL = nullptr;
|
|
|
|
|
mIsHandsharked = false;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
~TcpConnection() BRYNET_NOEXCEPT override
|
|
|
|
|
{
|
|
|
|
|
#ifdef BRYNET_USE_OPENSSL
|
|
|
|
|
if (mSSL != nullptr)
|
|
|
|
|
{
|
|
|
|
|
SSL_free(mSSL);
|
|
|
|
|
mSSL = nullptr;
|
|
|
|
|
}
|
|
|
|
|
if (mSSLCtx != nullptr)
|
|
|
|
|
{
|
|
|
|
|
SSL_CTX_free(mSSLCtx);
|
|
|
|
|
mSSLCtx = nullptr;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (mTimer.lock())
|
|
|
|
|
{
|
|
|
|
|
mTimer.lock()->cancel();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
void growRecvBuffer()
|
|
|
|
|
{
|
|
|
|
|
if (mRecvBuffer == nullptr)
|
|
|
|
|
{
|
|
|
|
|
mRecvBuffer.reset(brynet::base::buffer_new(std::min<size_t>(16 * 1024, mMaxRecvBufferSize)));
|
|
|
|
|
mRecvBuffOriginSize = buffer_getsize(mRecvBuffer.get());
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (buffer_getsize(mRecvBuffer.get()) >= mMaxRecvBufferSize)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mCurrentTanhXDiff += 0.2;
|
|
|
|
|
const auto newTanh = std::tanh(mCurrentTanhXDiff);
|
|
|
|
|
const auto maxSizeDiff = mMaxRecvBufferSize - mRecvBuffOriginSize;
|
|
|
|
|
const auto NewSize = mRecvBuffOriginSize + (maxSizeDiff * newTanh);
|
|
|
|
|
|
|
|
|
|
assert(NewSize <= mMaxRecvBufferSize);
|
|
|
|
|
std::unique_ptr<struct brynet::base::buffer_s, BufferDeleter> newBuffer(brynet::base::buffer_new(NewSize));
|
|
|
|
|
buffer_write(newBuffer.get(),
|
|
|
|
|
buffer_getreadptr(mRecvBuffer.get()),
|
|
|
|
|
buffer_getreadvalidcount(mRecvBuffer.get()));
|
|
|
|
|
mRecvBuffer = std::move(newBuffer);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* must called in network thread */
|
|
|
|
|
bool onEnterEventLoop()
|
|
|
|
|
{
|
|
|
|
|
assert(mEventLoop->isInLoopThread());
|
|
|
|
|
if (!mEventLoop->isInLoopThread())
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!brynet::net::base::SocketNonblock(mSocket->getFD()) ||
|
|
|
|
|
!mEventLoop->linkChannel(mSocket->getFD(), this))
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const auto findRet = mEventLoop->getTcpConnection(mSocket->getFD());
|
|
|
|
|
(void)findRet;
|
|
|
|
|
assert(findRet == nullptr);
|
|
|
|
|
|
|
|
|
|
#ifdef BRYNET_USE_OPENSSL
|
|
|
|
|
if (mSSL != nullptr)
|
|
|
|
|
{
|
|
|
|
|
mEventLoop->addTcpConnection(mSocket->getFD(), shared_from_this());
|
|
|
|
|
processSSLHandshake();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (!checkRead())
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mEventLoop->addTcpConnection(mSocket->getFD(), shared_from_this());
|
|
|
|
|
causeEnterCallback();
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef BRYNET_USE_OPENSSL
|
|
|
|
|
bool initAcceptSSL(SSL_CTX* ctx)
|
|
|
|
|
{
|
|
|
|
|
if (mSSL != nullptr)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mSSL = SSL_new(ctx);
|
|
|
|
|
if (SSL_set_fd(mSSL, mSocket->getFD()) != 1)
|
|
|
|
|
{
|
|
|
|
|
ERR_print_errors_fp(stdout);
|
|
|
|
|
::fflush(stdout);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
bool initConnectSSL()
|
|
|
|
|
{
|
|
|
|
|
if (mSSLCtx != nullptr)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mSSLCtx = SSL_CTX_new(SSLv23_client_method());
|
|
|
|
|
mSSL = SSL_new(mSSLCtx);
|
|
|
|
|
|
|
|
|
|
if (SSL_set_fd(mSSL, mSocket->getFD()) != 1)
|
|
|
|
|
{
|
|
|
|
|
ERR_print_errors_fp(stdout);
|
|
|
|
|
::fflush(stdout);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
void pingCheck()
|
|
|
|
|
{
|
|
|
|
|
mTimer.reset();
|
|
|
|
|
if (mRecvData)
|
|
|
|
|
{
|
|
|
|
|
mRecvData = false;
|
|
|
|
|
startPingCheckTimer();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
procCloseInLoop();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void startPingCheckTimer()
|
|
|
|
|
{
|
|
|
|
|
if (!mTimer.lock() &&
|
|
|
|
|
mCheckTime != std::chrono::steady_clock::duration::zero())
|
|
|
|
|
{
|
|
|
|
|
std::weak_ptr<TcpConnection> weakedThis = shared_from_this();
|
|
|
|
|
mTimer = mEventLoop->runAfter(mCheckTime, [weakedThis]() {
|
|
|
|
|
auto sharedThis = weakedThis.lock();
|
|
|
|
|
if (sharedThis != nullptr)
|
|
|
|
|
{
|
|
|
|
|
sharedThis->pingCheck();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void canRecv() override
|
|
|
|
|
{
|
|
|
|
|
#ifdef BRYNET_PLATFORM_WINDOWS
|
|
|
|
|
mPostRecvCheck = false;
|
|
|
|
|
if (mPostClose)
|
|
|
|
|
{
|
|
|
|
|
if (!mPostWriteCheck)
|
|
|
|
|
{
|
|
|
|
|
onClose();
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#elif defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN
|
|
|
|
|
if (mAlreadyClose)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef BRYNET_USE_OPENSSL
|
|
|
|
|
if (mSSL != nullptr
|
|
|
|
|
&& !mIsHandsharked
|
|
|
|
|
&& (!processSSLHandshake() || !mIsHandsharked))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
recv();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void canSend() override
|
|
|
|
|
{
|
|
|
|
|
#ifdef BRYNET_PLATFORM_WINDOWS
|
|
|
|
|
mPostWriteCheck = false;
|
|
|
|
|
if (mPostClose)
|
|
|
|
|
{
|
|
|
|
|
if (!mPostRecvCheck)
|
|
|
|
|
{
|
|
|
|
|
onClose();
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#elif defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN
|
|
|
|
|
if (mAlreadyClose)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
mCanWrite = true;
|
|
|
|
|
|
|
|
|
|
#ifdef BRYNET_USE_OPENSSL
|
|
|
|
|
if (mSSL != nullptr
|
|
|
|
|
&& !mIsHandsharked
|
|
|
|
|
&& (!processSSLHandshake() || !mIsHandsharked))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
runAfterFlush();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool checkRead()
|
|
|
|
|
{
|
|
|
|
|
bool check_ret = true;
|
|
|
|
|
#ifdef BRYNET_PLATFORM_WINDOWS
|
|
|
|
|
static CHAR temp[] = { 0 };
|
|
|
|
|
static WSABUF in_buf = { 0, temp };
|
|
|
|
|
|
|
|
|
|
if (mPostRecvCheck)
|
|
|
|
|
{
|
|
|
|
|
return check_ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DWORD dwBytes = 0;
|
|
|
|
|
DWORD flag = 0;
|
|
|
|
|
const int ret = WSARecv(mSocket->getFD(),
|
|
|
|
|
&in_buf,
|
|
|
|
|
1,
|
|
|
|
|
&dwBytes,
|
|
|
|
|
&flag,
|
|
|
|
|
&(mOvlRecv.base),
|
|
|
|
|
0);
|
|
|
|
|
if (ret == BRYNET_SOCKET_ERROR)
|
|
|
|
|
{
|
|
|
|
|
check_ret = (BRYNET_ERRNO == WSA_IO_PENDING);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (check_ret)
|
|
|
|
|
{
|
|
|
|
|
mPostRecvCheck = true;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
return check_ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool checkWrite()
|
|
|
|
|
{
|
|
|
|
|
bool check_ret = true;
|
|
|
|
|
#ifdef BRYNET_PLATFORM_WINDOWS
|
|
|
|
|
static WSABUF wsendbuf[1] = { {NULL, 0} };
|
|
|
|
|
|
|
|
|
|
if (mPostWriteCheck)
|
|
|
|
|
{
|
|
|
|
|
return check_ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DWORD send_len = 0;
|
|
|
|
|
const int ret = WSASend(mSocket->getFD(),
|
|
|
|
|
wsendbuf,
|
|
|
|
|
1,
|
|
|
|
|
&send_len,
|
|
|
|
|
0,
|
|
|
|
|
&(mOvlSend.base),
|
|
|
|
|
0);
|
|
|
|
|
if (ret == BRYNET_SOCKET_ERROR)
|
|
|
|
|
{
|
|
|
|
|
check_ret = (BRYNET_ERRNO == WSA_IO_PENDING);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (check_ret)
|
|
|
|
|
{
|
|
|
|
|
mPostWriteCheck = true;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
return check_ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void recv()
|
|
|
|
|
{
|
|
|
|
|
bool must_close = false;
|
|
|
|
|
#ifdef BRYNET_USE_OPENSSL
|
|
|
|
|
const bool notInSSL = (mSSL == nullptr);
|
|
|
|
|
#else
|
|
|
|
|
const bool notInSSL = false;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
while (true)
|
|
|
|
|
{
|
|
|
|
|
if (buffer_getwritevalidcount(mRecvBuffer.get()) == 0
|
|
|
|
|
|| buffer_getreadvalidcount(mRecvBuffer.get()) == 0)
|
|
|
|
|
{
|
|
|
|
|
buffer_adjustto_head(mRecvBuffer.get());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const auto tryRecvLen = buffer_getwritevalidcount(mRecvBuffer.get());
|
|
|
|
|
if (tryRecvLen == 0)
|
|
|
|
|
{
|
|
|
|
|
#ifdef BRYNET_PLATFORM_WINDOWS
|
|
|
|
|
checkRead();
|
|
|
|
|
#elif defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN
|
|
|
|
|
//force recheck IN-OUT Event
|
|
|
|
|
recheckEvent();
|
|
|
|
|
#endif
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int retlen = 0;
|
|
|
|
|
#ifdef BRYNET_USE_OPENSSL
|
|
|
|
|
if (mSSL != nullptr)
|
|
|
|
|
{
|
|
|
|
|
retlen = SSL_read(mSSL,
|
|
|
|
|
buffer_getwriteptr(mRecvBuffer.get()), tryRecvLen);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
retlen = ::recv(mSocket->getFD(),
|
|
|
|
|
buffer_getwriteptr(mRecvBuffer.get()), tryRecvLen, 0);
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
retlen = ::recv(mSocket->getFD(),
|
|
|
|
|
buffer_getwriteptr(mRecvBuffer.get()),
|
|
|
|
|
static_cast<int>(tryRecvLen),
|
|
|
|
|
0);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (retlen == 0)
|
|
|
|
|
{
|
|
|
|
|
must_close = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else if (retlen < 0)
|
|
|
|
|
{
|
|
|
|
|
#ifdef BRYNET_USE_OPENSSL
|
|
|
|
|
if ((mSSL != nullptr &&
|
|
|
|
|
SSL_get_error(mSSL, retlen) == SSL_ERROR_WANT_READ) ||
|
|
|
|
|
(BRYNET_ERRNO == BRYNET_EWOULDBLOCK))
|
|
|
|
|
{
|
|
|
|
|
must_close = !checkRead();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
must_close = true;
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
if (BRYNET_ERRNO != BRYNET_EWOULDBLOCK)
|
|
|
|
|
{
|
|
|
|
|
must_close = true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
must_close = !checkRead();
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mRecvData = true;
|
|
|
|
|
buffer_addwritepos(mRecvBuffer.get(), static_cast<size_t>(retlen));
|
|
|
|
|
if (buffer_getreadvalidcount(mRecvBuffer.get())
|
|
|
|
|
== buffer_getsize(mRecvBuffer.get()))
|
|
|
|
|
{
|
|
|
|
|
growRecvBuffer();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (notInSSL && retlen < static_cast<int>(tryRecvLen))
|
|
|
|
|
{
|
|
|
|
|
must_close = !checkRead();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
processRecvMessage();
|
|
|
|
|
|
|
|
|
|
if (must_close)
|
|
|
|
|
{
|
|
|
|
|
procCloseInLoop();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void flush()
|
|
|
|
|
{
|
|
|
|
|
#ifdef BRYNET_PLATFORM_WINDOWS
|
|
|
|
|
normalFlush();
|
|
|
|
|
#elif defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN
|
|
|
|
|
#ifdef BRYNET_USE_OPENSSL
|
|
|
|
|
if (mSSL != nullptr)
|
|
|
|
|
{
|
|
|
|
|
normalFlush();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
quickFlush();
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
quickFlush();
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
void normalFlush()
|
|
|
|
|
{
|
|
|
|
|
#ifdef BRYNET_PLATFORM_WINDOWS
|
|
|
|
|
static __declspec(thread) char* threadLocalSendBuf = nullptr;
|
|
|
|
|
#elif defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN
|
|
|
|
|
static __thread char* threadLocalSendBuf = nullptr;
|
|
|
|
|
#endif
|
|
|
|
|
static const int SENDBUF_SIZE = 1024 * 32;
|
|
|
|
|
if (threadLocalSendBuf == nullptr)
|
|
|
|
|
{
|
2020-11-25 00:20:41 +01:00
|
|
|
|
threadLocalSendBuf = (char*)malloc(SENDBUF_SIZE);
|
2020-11-24 15:41:18 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef BRYNET_USE_OPENSSL
|
|
|
|
|
const bool notInSSL = (mSSL == nullptr);
|
|
|
|
|
#else
|
|
|
|
|
const bool notInSSL = false;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
bool must_close = false;
|
|
|
|
|
|
|
|
|
|
while (!mSendList.empty() && mCanWrite)
|
|
|
|
|
{
|
2020-11-25 00:20:41 +01:00
|
|
|
|
char* sendptr = threadLocalSendBuf;
|
2020-11-24 15:41:18 +01:00
|
|
|
|
size_t wait_send_size = 0;
|
|
|
|
|
|
|
|
|
|
for (auto it = mSendList.begin(); it != mSendList.end(); ++it)
|
|
|
|
|
{
|
|
|
|
|
auto& packet = *it;
|
2020-11-25 00:20:41 +01:00
|
|
|
|
auto packetLeftBuf = (char*)(packet.data->c_str() + (packet.data->size() - packet.left));
|
2020-11-24 15:41:18 +01:00
|
|
|
|
const auto packetLeftLen = packet.left;
|
|
|
|
|
|
|
|
|
|
if ((wait_send_size + packetLeftLen) > SENDBUF_SIZE)
|
|
|
|
|
{
|
|
|
|
|
if (it == mSendList.begin())
|
|
|
|
|
{
|
|
|
|
|
sendptr = packetLeftBuf;
|
|
|
|
|
wait_send_size = packetLeftLen;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-25 00:20:41 +01:00
|
|
|
|
memcpy(sendptr + wait_send_size, packetLeftBuf, packetLeftLen);
|
2020-11-24 15:41:18 +01:00
|
|
|
|
wait_send_size += packetLeftLen;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (wait_send_size == 0)
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int send_retlen = 0;
|
|
|
|
|
#ifdef BRYNET_USE_OPENSSL
|
|
|
|
|
if (mSSL != nullptr)
|
|
|
|
|
{
|
|
|
|
|
send_retlen = SSL_write(mSSL, sendptr, wait_send_size);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
send_retlen = ::send(mSocket->getFD(), sendptr, wait_send_size, 0);
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
send_retlen = ::send(mSocket->getFD(), sendptr, static_cast<int>(wait_send_size), 0);
|
|
|
|
|
#endif
|
|
|
|
|
if (send_retlen <= 0)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
#ifdef BRYNET_USE_OPENSSL
|
|
|
|
|
if ((mSSL != nullptr && SSL_get_error(mSSL, send_retlen) == SSL_ERROR_WANT_WRITE) ||
|
|
|
|
|
(BRYNET_ERRNO == BRYNET_EWOULDBLOCK))
|
|
|
|
|
{
|
|
|
|
|
mCanWrite = false;
|
|
|
|
|
must_close = !checkWrite();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
must_close = true;
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
if (BRYNET_ERRNO == BRYNET_EWOULDBLOCK)
|
|
|
|
|
{
|
|
|
|
|
mCanWrite = false;
|
|
|
|
|
must_close = !checkWrite();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
must_close = true;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto tmp_len = static_cast<size_t>(send_retlen);
|
|
|
|
|
for (auto it = mSendList.begin(); it != mSendList.end();)
|
|
|
|
|
{
|
|
|
|
|
auto& packet = *it;
|
|
|
|
|
if (packet.left > tmp_len)
|
|
|
|
|
{
|
|
|
|
|
packet.left -= tmp_len;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tmp_len -= packet.left;
|
|
|
|
|
if (packet.mCompleteCallback != nullptr)
|
|
|
|
|
{
|
|
|
|
|
(packet.mCompleteCallback)();
|
|
|
|
|
}
|
|
|
|
|
it = mSendList.erase(it);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (notInSSL && static_cast<size_t>(send_retlen) != wait_send_size)
|
|
|
|
|
{
|
|
|
|
|
mCanWrite = false;
|
|
|
|
|
must_close = !checkWrite();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (must_close)
|
|
|
|
|
{
|
|
|
|
|
procCloseInLoop();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#if defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN
|
|
|
|
|
void quickFlush()
|
|
|
|
|
{
|
|
|
|
|
#ifndef MAX_IOVEC
|
|
|
|
|
constexpr size_t MAX_IOVEC = 1024;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
struct iovec iov[MAX_IOVEC];
|
|
|
|
|
bool must_close = false;
|
|
|
|
|
|
|
|
|
|
while (!mSendList.empty() && mCanWrite)
|
|
|
|
|
{
|
|
|
|
|
size_t num = 0;
|
|
|
|
|
size_t ready_send_len = 0;
|
|
|
|
|
for (const auto& p : mSendList)
|
|
|
|
|
{
|
2020-11-25 00:20:41 +01:00
|
|
|
|
iov[num].iov_base = (void*)(p.data->c_str() + (p.data->size() - p.left));
|
2020-11-24 15:41:18 +01:00
|
|
|
|
iov[num].iov_len = p.left;
|
|
|
|
|
ready_send_len += p.left;
|
|
|
|
|
|
|
|
|
|
num++;
|
|
|
|
|
if (num >= MAX_IOVEC)
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (num == 0)
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const int send_len = writev(mSocket->getFD(), iov, static_cast<int>(num));
|
|
|
|
|
if (send_len <= 0)
|
|
|
|
|
{
|
|
|
|
|
if (BRYNET_ERRNO == BRYNET_EWOULDBLOCK)
|
|
|
|
|
{
|
|
|
|
|
mCanWrite = false;
|
|
|
|
|
must_close = !checkWrite();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
must_close = true;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto tmp_len = static_cast<size_t>(send_len);
|
|
|
|
|
for (auto it = mSendList.begin(); it != mSendList.end();)
|
|
|
|
|
{
|
|
|
|
|
PendingPacket& b = *it;
|
|
|
|
|
if (b.left > tmp_len)
|
|
|
|
|
{
|
|
|
|
|
b.left -= tmp_len;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tmp_len -= b.left;
|
|
|
|
|
if (b.mCompleteCallback != nullptr)
|
|
|
|
|
{
|
|
|
|
|
b.mCompleteCallback();
|
|
|
|
|
}
|
|
|
|
|
it = mSendList.erase(it);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (static_cast<size_t>(send_len) != ready_send_len)
|
|
|
|
|
{
|
|
|
|
|
mCanWrite = false;
|
|
|
|
|
must_close = !checkWrite();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (must_close)
|
|
|
|
|
{
|
|
|
|
|
procCloseInLoop();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
void onClose() override
|
|
|
|
|
{
|
|
|
|
|
if (mAlreadyClose)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
mAlreadyClose = true;
|
|
|
|
|
|
|
|
|
|
#if defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN
|
|
|
|
|
unregisterPollerEvent();
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
assert(mEnterCallback == nullptr);
|
|
|
|
|
auto callBack = mDisConnectCallback;
|
|
|
|
|
auto sharedThis = shared_from_this();
|
|
|
|
|
auto eventLoop = mEventLoop;
|
|
|
|
|
std::shared_ptr<TcpSocket> socket = std::move(const_cast<TcpSocket::Ptr&&>(mSocket));
|
|
|
|
|
mEventLoop->runFunctorAfterLoop([callBack,
|
|
|
|
|
sharedThis,
|
|
|
|
|
eventLoop,
|
|
|
|
|
socket]() {
|
|
|
|
|
if (callBack != nullptr)
|
|
|
|
|
{
|
|
|
|
|
callBack(sharedThis);
|
|
|
|
|
}
|
|
|
|
|
auto tmp = eventLoop->getTcpConnection(socket->getFD());
|
|
|
|
|
assert(tmp == sharedThis);
|
|
|
|
|
if (tmp == sharedThis)
|
|
|
|
|
{
|
|
|
|
|
eventLoop->removeTcpConnection(socket->getFD());
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
mCanWrite = false;
|
|
|
|
|
mDisConnectCallback = nullptr;
|
|
|
|
|
mDataCallback = nullptr;
|
|
|
|
|
mRecvBuffer = nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void procCloseInLoop()
|
|
|
|
|
{
|
|
|
|
|
mCanWrite = false;
|
|
|
|
|
#ifdef BRYNET_PLATFORM_WINDOWS
|
|
|
|
|
if (mPostWriteCheck || mPostRecvCheck)
|
|
|
|
|
{
|
|
|
|
|
if (mPostClose)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
mPostClose = true;
|
|
|
|
|
//windows下立即关闭socket可能导致fd被另外的TcpConnection重用,而导致此对象在IOCP返回相关完成结果时内存已经释放
|
|
|
|
|
if (mPostRecvCheck)
|
|
|
|
|
{
|
|
|
|
|
CancelIoEx(HANDLE(mSocket->getFD()), &mOvlRecv.base);
|
|
|
|
|
}
|
|
|
|
|
if (mPostWriteCheck)
|
|
|
|
|
{
|
|
|
|
|
CancelIoEx(HANDLE(mSocket->getFD()), &mOvlSend.base);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
onClose();
|
|
|
|
|
}
|
|
|
|
|
#elif defined BRYNET_PLATFORM_LINUX
|
|
|
|
|
onClose();
|
|
|
|
|
#elif defined BRYNET_PLATFORM_DARWIN
|
|
|
|
|
onClose();
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void procShutdownInLoop()
|
|
|
|
|
{
|
|
|
|
|
mCanWrite = false;
|
|
|
|
|
if (mSocket != nullptr)
|
|
|
|
|
{
|
|
|
|
|
#ifdef BRYNET_PLATFORM_WINDOWS
|
|
|
|
|
shutdown(mSocket->getFD(), SD_SEND);
|
|
|
|
|
#elif defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN
|
|
|
|
|
shutdown(mSocket->getFD(), SHUT_WR);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void runAfterFlush()
|
|
|
|
|
{
|
|
|
|
|
if (!mIsPostFlush && !mSendList.empty() && mCanWrite)
|
|
|
|
|
{
|
|
|
|
|
auto sharedThis = shared_from_this();
|
|
|
|
|
mEventLoop->runFunctorAfterLoop([sharedThis]() {
|
|
|
|
|
sharedThis->mIsPostFlush = false;
|
|
|
|
|
sharedThis->flush();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
mIsPostFlush = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#if defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN
|
|
|
|
|
void recheckEvent()
|
|
|
|
|
{
|
|
|
|
|
#ifdef BRYNET_PLATFORM_LINUX
|
|
|
|
|
struct epoll_event ev = { 0, { nullptr } };
|
|
|
|
|
ev.events = EPOLLET | EPOLLIN | EPOLLOUT | EPOLLRDHUP;
|
|
|
|
|
ev.data.ptr = (Channel*)(this);
|
|
|
|
|
epoll_ctl(mEventLoop->getEpollHandle(), EPOLL_CTL_MOD, mSocket->getFD(), &ev);
|
|
|
|
|
#elif defined BRYNET_PLATFORM_DARWIN
|
|
|
|
|
struct kevent ev[2];
|
|
|
|
|
memset(&ev, 0, sizeof(ev));
|
|
|
|
|
int n = 0;
|
|
|
|
|
EV_SET(&ev[n++], mSocket->getFD(), EVFILT_READ, EV_ENABLE, 0, 0, (Channel*)(this));
|
|
|
|
|
EV_SET(&ev[n++], mSocket->getFD(), EVFILT_WRITE, EV_ENABLE, 0, 0, (Channel*)(this));
|
|
|
|
|
|
|
|
|
|
struct timespec now = { 0, 0 };
|
|
|
|
|
kevent(mEventLoop->getKqueueHandle(), ev, n, NULL, 0, &now);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
void unregisterPollerEvent()
|
|
|
|
|
{
|
|
|
|
|
#ifdef BRYNET_PLATFORM_LINUX
|
|
|
|
|
struct epoll_event ev = { 0, { nullptr } };
|
|
|
|
|
epoll_ctl(mEventLoop->getEpollHandle(), EPOLL_CTL_DEL, mSocket->getFD(), &ev);
|
|
|
|
|
#elif defined BRYNET_PLATFORM_DARWIN
|
|
|
|
|
struct kevent ev[2];
|
|
|
|
|
memset(&ev, 0, sizeof(ev));
|
|
|
|
|
int n = 0;
|
|
|
|
|
EV_SET(&ev[n++], mSocket->getFD(), EVFILT_READ, EV_DELETE, 0, 0, NULL);
|
|
|
|
|
EV_SET(&ev[n++], mSocket->getFD(), EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
|
|
|
|
|
|
|
|
|
|
struct timespec now = { 0, 0 };
|
|
|
|
|
kevent(mEventLoop->getKqueueHandle(), ev, n, NULL, 0, &now);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef BRYNET_USE_OPENSSL
|
|
|
|
|
bool processSSLHandshake()
|
|
|
|
|
{
|
|
|
|
|
if (mIsHandsharked)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool mustClose = false;
|
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
|
|
if (mSSLCtx != nullptr)
|
|
|
|
|
{
|
|
|
|
|
ret = SSL_connect(mSSL);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ret = SSL_accept(mSSL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ret == 1)
|
|
|
|
|
{
|
|
|
|
|
mIsHandsharked = true;
|
|
|
|
|
if (checkRead())
|
|
|
|
|
{
|
|
|
|
|
causeEnterCallback();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
mustClose = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (ret == 0)
|
|
|
|
|
{
|
|
|
|
|
mustClose = true;
|
|
|
|
|
}
|
|
|
|
|
else if (ret < 0)
|
|
|
|
|
{
|
|
|
|
|
int err = SSL_get_error(mSSL, ret);
|
|
|
|
|
if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ)
|
|
|
|
|
{
|
|
|
|
|
if (!checkRead())
|
|
|
|
|
{
|
|
|
|
|
mustClose = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
mustClose = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mustClose)
|
|
|
|
|
{
|
|
|
|
|
causeEnterCallback();
|
|
|
|
|
procCloseInLoop();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
void causeEnterCallback()
|
|
|
|
|
{
|
|
|
|
|
assert(mEventLoop->isInLoopThread());
|
|
|
|
|
if (mEventLoop->isInLoopThread() && mEnterCallback != nullptr)
|
|
|
|
|
{
|
|
|
|
|
auto tmp = mEnterCallback;
|
|
|
|
|
mEnterCallback = nullptr;
|
|
|
|
|
tmp(shared_from_this());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void processRecvMessage()
|
|
|
|
|
{
|
|
|
|
|
if (mDataCallback != nullptr && buffer_getreadvalidcount(mRecvBuffer.get()) > 0)
|
|
|
|
|
{
|
2020-11-25 00:20:41 +01:00
|
|
|
|
const auto proclen = mDataCallback(buffer_getreadptr(mRecvBuffer.get()),
|
|
|
|
|
buffer_getreadvalidcount(mRecvBuffer.get()));
|
|
|
|
|
assert(proclen <= buffer_getreadvalidcount(mRecvBuffer.get()));
|
|
|
|
|
if (proclen <= buffer_getreadvalidcount(mRecvBuffer.get()))
|
2020-11-24 15:41:18 +01:00
|
|
|
|
{
|
2020-11-25 00:20:41 +01:00
|
|
|
|
buffer_addreadpos(mRecvBuffer.get(), proclen);
|
2020-11-24 15:41:18 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
|
|
#ifdef BRYNET_PLATFORM_WINDOWS
|
|
|
|
|
struct port::Win::OverlappedExt mOvlRecv;
|
|
|
|
|
struct port::Win::OverlappedExt mOvlSend;
|
|
|
|
|
|
|
|
|
|
bool mPostRecvCheck;
|
|
|
|
|
bool mPostWriteCheck;
|
|
|
|
|
bool mPostClose;
|
|
|
|
|
#endif
|
|
|
|
|
const std::string mIP;
|
|
|
|
|
const TcpSocket::Ptr mSocket;
|
|
|
|
|
const EventLoop::Ptr mEventLoop;
|
|
|
|
|
bool mCanWrite;
|
|
|
|
|
bool mAlreadyClose;
|
|
|
|
|
|
|
|
|
|
class BufferDeleter
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
void operator()(struct brynet::base::buffer_s* ptr) const
|
|
|
|
|
{
|
|
|
|
|
brynet::base::buffer_delete(ptr);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
std::unique_ptr<struct brynet::base::buffer_s, BufferDeleter> mRecvBuffer;
|
|
|
|
|
double mCurrentTanhXDiff = 0;
|
|
|
|
|
size_t mRecvBuffOriginSize = 0;
|
|
|
|
|
const size_t mMaxRecvBufferSize;
|
|
|
|
|
|
|
|
|
|
struct PendingPacket
|
|
|
|
|
{
|
2020-11-25 00:20:41 +01:00
|
|
|
|
PacketPtr data;
|
2020-11-24 15:41:18 +01:00
|
|
|
|
size_t left;
|
|
|
|
|
PacketSendedCallback mCompleteCallback;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
using PacketListType = std::deque<PendingPacket>;
|
|
|
|
|
PacketListType mSendList;
|
|
|
|
|
|
|
|
|
|
EnterCallback mEnterCallback;
|
|
|
|
|
DataCallback mDataCallback;
|
|
|
|
|
DisconnectedCallback mDisConnectCallback;
|
|
|
|
|
|
|
|
|
|
bool mIsPostFlush;
|
|
|
|
|
|
|
|
|
|
#ifdef BRYNET_USE_OPENSSL
|
|
|
|
|
SSL_CTX* mSSLCtx;
|
|
|
|
|
SSL* mSSL;
|
|
|
|
|
bool mIsHandsharked;
|
|
|
|
|
#endif
|
|
|
|
|
bool mRecvData;
|
|
|
|
|
std::chrono::nanoseconds mCheckTime{};
|
|
|
|
|
brynet::base::Timer::WeakPtr mTimer;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
} }
|