Exemplo n.º 1
0
bool CClient::Start()
{
	do 
	{
		if (m_socket == INVALID_SOCKET)
		{
			m_socket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
			if (m_socket == INVALID_SOCKET)
			{
				LOGNET("Fail to create client[%d] socket.", GetID());
				break;
			}
		}

		static GUID GuidAcceptEx = WSAID_ACCEPTEX;
		static LPFN_ACCEPTEX AcceptEx = (LPFN_ACCEPTEX)GetExtensionFunction(m_pServer->GetListenSocket(), GuidAcceptEx);
		NetData* pData = m_accept.GetNetData();
		pData->extra = this;
		DWORD recvLen = 0;
		if (AcceptEx(m_pServer->GetListenSocket(), m_socket, pData->buffer.buf, 0, 
			sizeof(SOCKADDR_IN)+16, sizeof(SOCKADDR_IN)+16, &recvLen, &pData->overlapped) == FALSE)
		{
			if (WSAGetLastError() != WSA_IO_PENDING)
			{
				LOGNET("Client[%d] fail to call AcceptEx.", GetID());
				break;
			}
		}

		return true;
	} while (false);

	Stop();
	return false;
}
Exemplo n.º 2
0
void Connection::sendMsg(SendPacket* p)
{
	if (m_status != CONN_STATUS_CONNECTED)
	{
		LOGERROR() << "sendmsg status not connected"
			<<"id"<<m_id
			<<LOGEND();
		return;
	}
	short opCode = p->getOPCode();
	std::string body = p->getData();

	unsigned int pack = (13 << 24) + (body.size() & 0xFFFFFF);

	char header[MSG_HEADER_SIZE] = {0};
	memmove(header,					(char*)&opCode, sizeof(opCode));
	memmove(header+sizeof(opCode),	(char*)&pack,	sizeof(pack));

	std::stringstream ss;
	ss << std::string(header, 6) << body;
	m_outData.push_back(ss.str());
	LOGNET() << "try send msg " << opCode << " pack size " << body.size() << LOGEND();

	tryWrite();
}
Exemplo n.º 3
0
// get some data
void Connection::handleRead(const boost::system::error_code& error, size_t len)
{
	if(!error)
	{
		LOGNET() << ">>> got " << len << " data from " 
				<<"id"<<m_id
				<<LOGEND();
		m_offSet += len;
		m_msgBuffer.push_back(std::string(m_buffer, m_buffer+m_offSet));
		m_offSet = 0;
		// continue to read
		tryRead();
		handlePacket();
	}
	else
	{
		if (m_status == CONN_STATUS_CONNECTED)
		{
			m_status = CONN_STATUS_DISCONNECT;
		}
		else
		{
			// triggered by other event
		}
		
		if (m_writeStatus != SW_STATUS_WRITTING)
		{
			m_errHandler(error, this, "handleread");
		}
		else
		{
			// write callback will call immediately
		}
	}
}
Exemplo n.º 4
0
void Connection::handleWrite(const boost::system::error_code& error, size_t len)
{
	if(!error)
	{
		m_writeStatus = SW_STATUS_WRITEDONE;

		assert(m_outData.size() > 0);
		// ok write some chars
		//std::string& buf = m_outData.front();
		// first buffer all flushed
		if (len == m_tempBuf.length())
		{
			LOGNET() << "<<< write full " << len << " " 
				<<"id"<<m_id
				<< LOGEND();
			m_outData.pop_front();
			tryWrite();
		}
		else
		{
			//LOGNET() << "<<< write partial " << len << " should " << buf.length() << " " 
			LOGNET() << "<<< write partial " << len << " should " << m_tempBuf.length() << " " 
				<<"id"<<m_id
				<< LOGEND();
			assert(len < m_tempBuf.length());
			//buf = buf.substr(len);
			m_tempBuf = m_tempBuf.substr(len);
			tryWrite();
		}
	}
	else
	{
		if (m_status == CONN_STATUS_CONNECTED)
		{
			m_status = CONN_STATUS_DISCONNECT;
		}
		else
		{
			// triggered by other event
		}

		if (m_errHandler)
		{
			m_errHandler(error, this, "handlewrite");
		}
	}
}
Exemplo n.º 5
0
void CClient::TimeRoutine(int now)
{
	CLock lock(&m_criticalSection);
	switch (m_status)
	{
	case NETSTATUS_CompletionNotify:
		{
			if (m_lastActionTime)
			{
				if (now-m_lastActionTime > MAX_IDLE_TIME)
				{
					LOG("Client[%d] has been idled for a long time.", GetID());
					Restart(NETOP_Receive);
				}
			}
			else
			{
				DWORD connectTime = 0;
				int optSize = sizeof(connectTime);
				if (getsockopt(m_socket, SOL_SOCKET, SO_CONNECT_TIME, (char*)&connectTime, &optSize) == SOCKET_ERROR)
				{
					LOGNET("Client[%d] fail to get socket connection time.", GetID());
				}
				else
				{
					if (connectTime!=0xFFFFFFFF && connectTime>DENIAL_SERVICE_TIME)
					{
						LOG("Client[%d] may be a malicious application.", GetID());
						Restart(NETOP_Receive);
					}
				}
			}
		}
		break;
	case NETSTATUS_Disconnecting:
		{
			if (m_lastActionTime)
			{
				if (now-m_lastActionTime > MAX_DISCONNECT_TIME)
				{
					LOG("Client[%d] has been in disconnecting for a long time.", GetID());
					Restart(NETOP_Disconnect);
				}
			}
			else
			{
				LOG("Client[%d] has been in disconnecting, but last action time is zero.", GetID());
			}
		}
		break;
	default:
		break;
	}
}
Exemplo n.º 6
0
bool CClient::AppendDisconnect(bool restart)
{
	static GUID GuidDisconnectEx = WSAID_DISCONNECTEX;
	static LPFN_DISCONNECTEX DisconnectEx = (LPFN_DISCONNECTEX)GetExtensionFunction(m_socket, GuidDisconnectEx);
	CLock lock(&m_criticalSection);
	NetData* pData = m_discon.GetNetData();
	if (DisconnectEx(m_socket, &pData->overlapped, TF_REUSE_SOCKET, 0) == FALSE)
	{
		if (WSAGetLastError() != WSA_IO_PENDING)
		{
			LOGNET("Client[%d] to call DisconnectEx.", GetID());
			return false;
		}
	}
	m_status = NETSTATUS_Disconnecting;
	m_lastActionTime = (int)time(NULL);
	return true;
}
Exemplo n.º 7
0
bool CClient::AppendReceive()
{
	CLock lock(&m_criticalSection);
	if (m_status != NETSTATUS_CompletionNotify)
		return true;
	NetData* pData = m_recv.GetNetData();
	DWORD recvBytes = 0;
	DWORD flag = 0;
	if (WSARecv(m_socket, &pData->buffer, 1, &recvBytes, &flag, &pData->overlapped, NULL) == SOCKET_ERROR)
	{
		if (WSAGetLastError() != WSA_IO_PENDING)
		{
			LOGNET("Client[%d] fail to call WSARecv.", GetID());
			return false;
		}
	}
	return true;
}
Exemplo n.º 8
0
bool CClient::AppendSend()
{
	CLock lock(&m_criticalSection);
	if (m_status != NETSTATUS_CompletionNotify)
		return true;
	m_send.Tidy();
	NetData* pData = m_send.GetNetData();
	DWORD sendBytes = 0;
	if (WSASend(m_socket, &pData->buffer, 1, &sendBytes, 0, &pData->overlapped, NULL) == SOCKET_ERROR)
	{
		if (WSAGetLastError() != WSA_IO_PENDING)
		{
			LOGNET("Client[%d] fail to call WSASend.", GetID());
			return false;
		}
	}
	return true;
}
Exemplo n.º 9
0
bool CClient::PostConnect(NetData* pData)
{
	CLock lock(&m_criticalSection);
	m_status = NETSTATUS_Connected;
	SOCKADDR* localAddr = NULL;
	SOCKADDR* remoteAddr = NULL;
	int localAddrLen = 0;
	int remoteAddrLen = 0;
	GetAcceptExSockaddrs(pData->buffer.buf, 0,
		sizeof(SOCKADDR_IN)+16, sizeof(SOCKADDR_IN)+16, 
		&localAddr, &localAddrLen, &remoteAddr, &remoteAddrLen);

	SOCKET listenSocket = m_pServer->GetListenSocket();
	if (setsockopt(m_socket, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (const char*)&listenSocket, sizeof(listenSocket)) == SOCKET_ERROR)
	{
		LOGNET("Client[%d] fail to update accept context.", GetID());
		return false;
	}

	if (!m_completePort)
	{
		if (CreateIoCompletionPort((HANDLE)m_socket, m_pManager->GetIOCompletePort(), (ULONG_PTR)this, 0) == NULL)
		{
			LOG("Fail to associate client[%d] socket with completion port.", GetID());
			return false;
		}
		m_completePort = true;
	}
	m_send.Clean();
	m_recv.Clean();
	m_discon.Clean();
	m_accept.Clean();
	m_lastActionTime = 0;
	m_status = NETSTATUS_CompletionNotify;
	return true;
}
Exemplo n.º 10
0
void Connection::handlePacket()
{
	int count = 0;
	while(count++ < 20)
	{
		if(this->getBufSize() <= 0)
		{
			break;
		}
		std::string header;
		bool flag = this->getMsgSize(&header, MSG_HEADER_SIZE);
		if (!flag)
		{
			LOGERROR() << "not enough header" << LOGEND();
			break;
		}
		else
		{
			char* buf = &header[0];
			// check msg header
			int offset = 0;
			short msgID = 0;
			memcpy(&msgID, buf, sizeof(msgID));

			unsigned int pack = 0;
			memcpy(&pack, buf+sizeof(msgID), sizeof(pack));

			int msgSize = pack & 0xFFFFFF;
			unsigned int chaos	= pack >> 24;
			if (chaos != 13)
			{
				LOGERROR() << "wrong pack chaos " << chaos << " msg " << msgID << " from " 
							<<"id"<<m_id
							<< LOGEND();
				return;
			}
			// todo check valid msgid
			// body
			std::string body;
			flag = getMsgSize(&body, MSG_HEADER_SIZE+msgSize);
			if(flag)
			{
				this->skipMsgSize(msgSize+MSG_HEADER_SIZE);

				body.erase(0, MSG_HEADER_SIZE);
				LOGNET() << ">>> got msg " << msgID << " size " << msgSize << LOGEND();
				Packet p(msgID, body);

				MsgHandlerType handler = MsgHandler::getHandler(p.getOP());
				if (handler)
				{
					bool flag = handler(this, &p);
					if (!flag)
					{
						LOGERROR() << "return false handle " << p.getOP() << LOGEND();
					}
				}
				else
				{
					LOGERROR() << "didn't find handler for " << p.getOP() << LOGEND();
				}
			}
			else
			{
				LOGNET() << "not enough body need " << msgSize << 
					" but have " << m_offSet - MSG_HEADER_SIZE << 
					" msgID=" << msgID << LOGEND();
			}
		}
	}
}