512 lines
12 KiB
C++
512 lines
12 KiB
C++
#ifndef MULTIPLEX_TRANSPORT__H_
|
|
#define MULTIPLEX_TRANSPORT__H_
|
|
|
|
#ifdef _WIN32
|
|
#pragma once
|
|
#endif
|
|
|
|
|
|
class HMultiplexTransportTcpSocket;
|
|
|
|
|
|
class HMultiplexTransport : public HTransport
|
|
{
|
|
public:
|
|
HMultiplexTransport() {}
|
|
~HMultiplexTransport() {}
|
|
|
|
inline void SetMpSocket(HMultiplexTcpSocket * pSocket) { m_pMulplexTransportSocket = pSocket; }
|
|
inline HMultiplexTcpSocket * GetMpSocket() { return m_pMulplexTransportSocket; }
|
|
|
|
inline bool GetTransportInfo(const char * pName, void * pValue);
|
|
|
|
inline void Terminate();
|
|
|
|
inline int Send(const char * pData, int nSize);
|
|
|
|
protected:
|
|
HMultiplexTcpSocket * m_pMulplexTransportSocket;
|
|
|
|
|
|
friend class HMultiplexTransportTcpSocket;
|
|
friend class HMultiplexTransportSslSocket;
|
|
};
|
|
|
|
///////////////////////////////////////
|
|
|
|
class HMultiplexTransportTcpSocket : public HMultiplexTcpSocket
|
|
{
|
|
public:
|
|
HMultiplexTransportTcpSocket()
|
|
{
|
|
m_bAutoDelete = false;
|
|
m_nReconnectTime = 0;
|
|
m_pReceiveBuffer = (char *)malloc(g_nSocketReceiveBlockSize + 1);
|
|
m_pTransport = NULL;
|
|
}
|
|
|
|
HMultiplexTransportTcpSocket(SOCKET sock, struct sockaddr_in * psaiRemote, HMpsDispatcher * pDispatcher)
|
|
: HMultiplexTcpSocket(sock, psaiRemote, pDispatcher)
|
|
{
|
|
m_bAutoDelete = false;
|
|
m_nReconnectTime = 0;
|
|
m_pReceiveBuffer = (char *)malloc(g_nSocketReceiveBlockSize + 1);
|
|
m_pTransport = NULL;
|
|
}
|
|
|
|
~HMultiplexTransportTcpSocket()
|
|
{
|
|
if (m_pTransport)
|
|
delete m_pTransport;
|
|
|
|
free(m_pReceiveBuffer);
|
|
}
|
|
|
|
inline void AttachTransport(HMultiplexTransport * pTransport) { m_pTransport = pTransport; }
|
|
inline HMultiplexTransport * GetTransport() { return m_pTransport; }
|
|
|
|
inline void SetAutoDelete(bool bAutoDelete) { m_bAutoDelete = bAutoDelete; }
|
|
inline void SetAutoReconnect(DWORD nTime) { m_nReconnectTime = nTime; }
|
|
|
|
protected:
|
|
inline void OnClose()
|
|
{
|
|
if (m_bAutoDelete)
|
|
SetState(MPS_DELETE); // auto delete
|
|
else if (m_nReconnectTime > 0)
|
|
SetTimer(2181006, m_nReconnectTime);
|
|
|
|
m_pTransport->OnReceivedStatus(HTransport::T_END_TRANSPORT);
|
|
}
|
|
|
|
inline void OnConnect(bool bIsSuccess)
|
|
{
|
|
if (bIsSuccess == false)
|
|
{
|
|
m_pTransport->OnReceivedStatus(HTransport::T_FAILED_BEGIN);
|
|
return;
|
|
}
|
|
|
|
m_pTransport->OnReceivedStatus(HTransport::T_BEGIN_TRANSPORT);
|
|
}
|
|
|
|
inline void OnReceive()
|
|
{
|
|
if (m_pTransport == NULL)
|
|
return;
|
|
|
|
if (m_pTransport->OnPrepareReceive() == false)
|
|
return;
|
|
|
|
int nReceivedSize = Receive(m_pReceiveBuffer, g_nSocketReceiveBlockSize);
|
|
if (nReceivedSize <= 0)
|
|
return;
|
|
|
|
if (m_pTransport->OnReceived(m_pReceiveBuffer, nReceivedSize) < 0)
|
|
FinishTcp();
|
|
}
|
|
|
|
inline int OnSendRetry()
|
|
{
|
|
return m_pTransport->OnSendRetry();
|
|
}
|
|
|
|
inline void OnAccepted()
|
|
{
|
|
m_pTransport->OnReceivedStatus(HTransport::T_BEGIN_TRANSPORT);
|
|
}
|
|
|
|
ON_TIMER(HMultiplexTransportTcpSocket, OnTimer) // add void OnTimer(DWORD nTimerID) {}
|
|
|
|
protected:
|
|
char * m_pReceiveBuffer;
|
|
bool m_bAutoDelete;
|
|
DWORD m_nReconnectTime;
|
|
|
|
HMultiplexTransport * m_pTransport;
|
|
};
|
|
|
|
inline void HMultiplexTransportTcpSocket::OnTimer(unsigned int nTimerId)
|
|
{
|
|
KillTimer(2181006);
|
|
Create();
|
|
Connect(0);
|
|
}
|
|
|
|
///////////////////////////////////////
|
|
|
|
class HMultiplexTransportSslSocket : public HMultiplexSslSocket
|
|
{
|
|
public:
|
|
HMultiplexTransportSslSocket()
|
|
{
|
|
m_bAutoDelete = false;
|
|
m_nReconnectTime = 0;
|
|
m_pTransport = NULL;
|
|
}
|
|
|
|
HMultiplexTransportSslSocket(SOCKET sock, struct sockaddr_in * psaiRemote, HMpsDispatcher * pDispatcher)
|
|
: HMultiplexSslSocket(sock, psaiRemote, pDispatcher)
|
|
{
|
|
m_bAutoDelete = false;
|
|
m_nReconnectTime = 0;
|
|
m_pTransport = NULL;
|
|
}
|
|
|
|
~HMultiplexTransportSslSocket()
|
|
{
|
|
if (m_pTransport)
|
|
delete m_pTransport;
|
|
}
|
|
|
|
inline void AttachTransport(HMultiplexTransport * pTransport) { m_pTransport = pTransport; }
|
|
inline HMultiplexTransport * GetTransport() { return m_pTransport; }
|
|
|
|
inline void SetAutoDelete(bool bAutoDelete) { m_bAutoDelete = bAutoDelete; }
|
|
inline void SetAutoReconnect(DWORD nTime) { m_nReconnectTime = nTime; }
|
|
|
|
inline void OnAccepted()
|
|
{
|
|
HMultiplexSslSocket::OnAccepted();
|
|
|
|
m_pTransport->OnReceivedStatus(HTransport::T_BEGIN_TRANSPORT);
|
|
}
|
|
|
|
protected:
|
|
inline void OnClose()
|
|
{
|
|
if (m_bAutoDelete)
|
|
SetState(MPS_DELETE); // auto delete
|
|
else if (m_nReconnectTime > 0)
|
|
SetTimer(2181006, m_nReconnectTime);
|
|
|
|
m_pTransport->OnReceivedStatus(HTransport::T_END_TRANSPORT);
|
|
}
|
|
|
|
inline void OnReceive()
|
|
{
|
|
if (m_pTransport == NULL)
|
|
return;
|
|
|
|
if (m_pTransport->OnPrepareReceive() == false)
|
|
return;
|
|
|
|
Receive();
|
|
|
|
while (m_pStreamBufferForDecrypt->StoredSize() > 0)
|
|
{
|
|
//HLOGF(HLOG_WARNING, "SSL_TRACE, recv size = %d\n", m_pStreamBufferForDecrypt->StoredSize());
|
|
//HLOGD(HLOG_WARNING, m_pStreamBufferForDecrypt->Head(), 40, true);
|
|
|
|
if (m_pStreamBufferForDecrypt->StoredSize() > (size_t)g_nSocketReceiveBlockSize)
|
|
{
|
|
if (m_pTransport->OnReceived(m_pStreamBufferForDecrypt->Head(), g_nSocketReceiveBlockSize) < 0)
|
|
{
|
|
FinishTcp();
|
|
return;
|
|
}
|
|
m_pStreamBufferForDecrypt->Pop(g_nSocketReceiveBlockSize);
|
|
}
|
|
else
|
|
{
|
|
if (m_pTransport->OnReceived(m_pStreamBufferForDecrypt->Head(), m_pStreamBufferForDecrypt->StoredSize()) < 0)
|
|
{
|
|
FinishTcp();
|
|
return;
|
|
}
|
|
m_pStreamBufferForDecrypt->Reset();
|
|
}
|
|
}
|
|
}
|
|
|
|
inline int OnSendRetry()
|
|
{
|
|
if (m_bEncryptRetry)
|
|
return m_pTransport->OnSendRetry();
|
|
|
|
return SendBufferedData();
|
|
}
|
|
|
|
inline void OnConnectChild(bool bIsSuccess)
|
|
{
|
|
if (bIsSuccess == false)
|
|
{
|
|
SetState(MPS_CLOSING);
|
|
m_pTransport->OnReceivedStatus(HTransport::T_FAILED_BEGIN);
|
|
return;
|
|
}
|
|
|
|
m_pTransport->OnReceivedStatus(HTransport::T_BEGIN_TRANSPORT);
|
|
}
|
|
|
|
ON_TIMER(HMultiplexTransportSslSocket, OnTimer) // add void OnTimer(DWORD nTimerID) {}
|
|
|
|
protected:
|
|
bool m_bAutoDelete;
|
|
DWORD m_nReconnectTime;
|
|
|
|
HMultiplexTransport * m_pTransport;
|
|
};
|
|
|
|
inline void HMultiplexTransportSslSocket::OnTimer(unsigned int nTimerId)
|
|
{
|
|
KillTimer(2181006);
|
|
Create();
|
|
Connect(0);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////
|
|
|
|
inline bool HMultiplexTransport::GetTransportInfo(const char * pName, void * pValue)
|
|
{
|
|
if (strcmp(pName, "peer_ip") == 0)
|
|
{
|
|
int nResult = m_pMulplexTransportSocket->GetPeerAddress((char *)pValue, NULL);
|
|
if (nResult)
|
|
{
|
|
HLOGF(HLOG_WARNING, "[WARN], MplxTrnsp, Failed to GetPeerAddress 1, error = %d\n", nResult);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
else if (strcmp(pName, "peer_port") == 0)
|
|
{
|
|
int nResult = m_pMulplexTransportSocket->GetPeerAddress(NULL, (u_short *)pValue);
|
|
if (nResult)
|
|
{
|
|
HLOGF(HLOG_WARNING, "[WARN], MplxTrnsp, Failed to GetPeerAddress 2, error = %d\n", nResult);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
else if (strcmp(pName, "peer_address") == 0)
|
|
{
|
|
char szIp[32];
|
|
u_short nPort = 0;
|
|
int nResult = m_pMulplexTransportSocket->GetPeerAddress(szIp, &nPort);
|
|
if (nResult)
|
|
{
|
|
HLOGF(HLOG_WARNING, "[WARN], MplxTrnsp, Failed to GetPeerAddress 3, error = %d\n", nResult);
|
|
return false;
|
|
}
|
|
sprintf((char *)pValue, "%s:%d", szIp, nPort);
|
|
return true;
|
|
}
|
|
else if (strcmp(pName, "is_ssl_socket") == 0)
|
|
{
|
|
*((bool *)pValue) = m_pMulplexTransportSocket->IsSslSocket();
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
inline void HMultiplexTransport::Terminate()
|
|
{
|
|
m_pMulplexTransportSocket->FinishTcp();
|
|
}
|
|
|
|
inline int HMultiplexTransport::Send(const char * pData, int nSize)
|
|
{
|
|
return m_pMulplexTransportSocket->Send(pData, nSize);
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
|
|
template<class _THandler, class _TSocket>
|
|
class HMulplexTransportListenSocket : public HMultiplexListenSocket
|
|
{
|
|
public:
|
|
HMulplexTransportListenSocket() {}
|
|
~HMulplexTransportListenSocket() {}
|
|
|
|
protected:
|
|
HMultiplexTcpSocket * OnAccept(SOCKET sock, struct sockaddr_in * psaiRemote)
|
|
{
|
|
HMultiplexTransport * pMultiplexTransport = new HMultiplexTransport;
|
|
pMultiplexTransport->AttachHandler(new _THandler);
|
|
|
|
_TSocket * pSocket = new _TSocket(sock, psaiRemote, GetDispatcher());
|
|
pMultiplexTransport->SetMpSocket(pSocket);
|
|
|
|
pSocket->AttachTransport(pMultiplexTransport);
|
|
pSocket->SetAutoDelete(true);
|
|
|
|
return pSocket;
|
|
}
|
|
};
|
|
|
|
/////////////////////////////////////////////////
|
|
|
|
class HMulplexSocketConnector
|
|
{
|
|
public:
|
|
HMulplexSocketConnector() { m_pVecOutboundIp = NULL; m_nOutboundIpIndex = -1; }
|
|
virtual ~HMulplexSocketConnector() {}
|
|
|
|
inline void SetOutboundIpList(HStrVector * pVector) { m_pVecOutboundIp = pVector; }
|
|
inline void SetOutboundIpIndex(int nIndex) { m_nOutboundIpIndex = nIndex; }
|
|
|
|
virtual bool Connect(const char * pszAddress, u_short nPort, unsigned nTimeout, HMpsDispatcher * pDispatcher) { return false; }
|
|
|
|
protected:
|
|
HStrVector * m_pVecOutboundIp;
|
|
int m_nOutboundIpIndex;
|
|
};
|
|
|
|
template<class _THandler, class _TSocket>
|
|
class HMulplexTransportConnector : public HMulplexSocketConnector
|
|
{
|
|
public:
|
|
HMulplexTransportConnector() { m_pHandler = NULL; }
|
|
~HMulplexTransportConnector() {}
|
|
|
|
inline _THandler * GetHandler() { return m_pHandler; }
|
|
|
|
inline bool Connect(const char * pszAddress, u_short nPort, unsigned nTimeout, HMpsDispatcher * pDispatcher, unsigned long nAutoReconnectTime = 0)
|
|
{
|
|
HMultiplexTransport * pMultiplexTransport = new HMultiplexTransport;
|
|
|
|
m_pHandler = new _THandler;
|
|
pMultiplexTransport->AttachHandler(m_pHandler);
|
|
|
|
_TSocket * pSocket = new _TSocket;
|
|
if (pSocket->Create() == false)
|
|
{
|
|
delete pSocket;
|
|
delete pMultiplexTransport;
|
|
return false;
|
|
}
|
|
pMultiplexTransport->SetMpSocket(pSocket);
|
|
pSocket->AttachTransport(pMultiplexTransport);
|
|
|
|
if (nAutoReconnectTime > 0)
|
|
pSocket->SetAutoReconnect(nAutoReconnectTime);
|
|
else
|
|
pSocket->SetAutoDelete(true);
|
|
|
|
HLOGF(HLOG_INFO3, "INFO, MpConnector, Connect, inst = 0x%x, %s:%d\n", this, pszAddress, nPort);
|
|
|
|
if (IsIpString(pszAddress))
|
|
pSocket->SetRemoteAddress(pszAddress, nPort);
|
|
else
|
|
pSocket->SetRemoteAddressHostByName(pszAddress, nPort);
|
|
|
|
if (m_pVecOutboundIp && m_pVecOutboundIp->size() > 0)
|
|
{
|
|
// outbound load balance
|
|
static int nIpCount = m_pVecOutboundIp->size();
|
|
static int nIpIndex = 0;
|
|
static u_short nPort = 20000;
|
|
|
|
if (nIpCount <= 0)
|
|
return false;
|
|
|
|
if (++nIpIndex >= nIpCount)
|
|
nIpIndex = 0;
|
|
|
|
for (int i = 20000; i < 60000; i++)
|
|
{
|
|
if (++nPort >= 60000)
|
|
nPort = 20000;
|
|
|
|
if (m_nOutboundIpIndex != -1)
|
|
{
|
|
if (pSocket->Bind((*m_pVecOutboundIp)[m_nOutboundIpIndex], nPort))
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
if (pSocket->Bind((*m_pVecOutboundIp)[nIpIndex], nPort))
|
|
break;
|
|
}
|
|
|
|
Sleep(50);
|
|
}
|
|
}
|
|
|
|
if (pSocket->Connect(nTimeout) == false)
|
|
{
|
|
delete pSocket;
|
|
return false;
|
|
}
|
|
|
|
pDispatcher->Attach(pSocket);
|
|
return true;
|
|
}
|
|
|
|
private:
|
|
_THandler * m_pHandler;
|
|
};
|
|
|
|
/////////////////////////////////////////////////
|
|
|
|
template<class _THandler, class _TSocket>
|
|
class HMulplexTransportListenThread : public HMultiplexListenThread<HMultiplexTcpSocket>
|
|
{
|
|
public:
|
|
HMulplexTransportListenThread() {}
|
|
~HMulplexTransportListenThread() {}
|
|
|
|
protected:
|
|
HMultiplexTcpSocket * OnAccept(SOCKET sock, struct sockaddr_in * psaiRemote)
|
|
{
|
|
HMultiplexTransport * pMultiplexTransport = new HMultiplexTransport;
|
|
pMultiplexTransport->AttachHandler(new _THandler);
|
|
#if 1
|
|
HMpsDispatcher * pDispatcher = m_pListDispatcher->GetLazyDispatcher();
|
|
_TSocket * pSocket = new _TSocket(sock, psaiRemote, pDispatcher);
|
|
pMultiplexTransport->SetMpSocket(pSocket);
|
|
|
|
pSocket->AttachTransport(pMultiplexTransport);
|
|
pSocket->SetAutoDelete(true);
|
|
|
|
pDispatcher->AttachWithLock(pSocket);
|
|
return pSocket;
|
|
#else
|
|
HMpsDispatcherList::iterator iter;
|
|
int i = 0;
|
|
for (iter = m_pListDispatcher->begin(); iter != m_pListDispatcher->end(); iter++)
|
|
{
|
|
if ((*iter)->IsProcessing() == false)
|
|
i++;
|
|
}
|
|
//HLOGF(HLOG_WARNING, "[TRACE], MplxTrnspLstnThr_0x%x, lazy dispatcher count = %d\n", this, i);
|
|
|
|
for (;;)
|
|
{
|
|
for (iter = m_pListDispatcher->begin(); iter != m_pListDispatcher->end(); iter++)
|
|
{
|
|
if ((*iter)->IsProcessing() == false)
|
|
{
|
|
_TSocket * pSocket = new _TSocket(sock, psaiRemote, *iter);
|
|
pMultiplexTransport->SetMpSocket(pSocket);
|
|
|
|
pSocket->AttachTransport(pMultiplexTransport);
|
|
pSocket->SetAutoDelete(true);
|
|
|
|
(*iter)->AttachWithLock(pSocket);
|
|
return pSocket;
|
|
}
|
|
}
|
|
|
|
Sleep(10);
|
|
}
|
|
#endif
|
|
}
|
|
};
|
|
|
|
#if 1
|
|
typedef std::list<HMultiplexListenThread<HMultiplexTcpSocket> *> HMultiplexListenThreadList;
|
|
#else
|
|
class HMultiplexListenThreadList : public std::list<HMultiplexListenThread<HMultiplexTcpSocket> *>
|
|
{
|
|
public:
|
|
HMultiplexListenThreadList() {}
|
|
~HMultiplexListenThreadList() {}
|
|
};
|
|
#endif
|
|
|
|
#endif // MULTIPLEX_TRANSPORT__H_
|