18,356
社区成员
发帖
与我相关
我的任务
分享
BOOL CHTTPServer::OnReceived(sandrer::CIocpBufferImpl *pBuffer, sandrer::IOCPCTX pContext)
{
CTX_Lock(pContext);
iocp_trace("Context [0x%p] enter SSL received, buffer [0x%p](index %d).", pContext, pBuffer, pBuffer->GetIndex());
SSLDATA *p_session = (SSLDATA *)CTX_GetUserData(pContext);
if (p_session == NULL)
{
CTX_Unlock(pContext);
return FALSE;
}
//ERR_clear_error();
BOOL bHandshaked = FALSE;
int nBuffSize = (int)pBuffer->GetSize();
int nTransBytes = (int)pBuffer->GetUsed();
PBYTE pTransData = pBuffer->GetBuffer();
char ip[16];
UINT port = CTX_GetRemoteIP(pContext, ip);
iocp_trace("received %d bytes from %s:%u", nTransBytes, ip, port);
// 将加密数据写入 BIO 中
int nSSLBytes = BIO_write(p_session->bio_recv, pTransData, nTransBytes);
if (nSSLBytes != nTransBytes)
{
int nSSLError = SSL_get_error(p_session->ssl, nSSLBytes);
iocp_trace("BIO_write error %d when we received data.", nSSLError);
if (!BIO_should_retry(p_session->bio_recv))
{
CTX_Unlock(pContext);
DisconnectClient(pContext);
return FALSE;
}
}
// 尝试从 BIO 中取出解密数据, 如果出错则表示数据未完整需要等待下次获取
int i = 0;
for (;;)
{
nSSLBytes = SSL_read(p_session->ssl, pTransData, nBuffSize - 1);
iocp_trace("Context [0x%p] SSL_read %d times %d bytes", pContext, ++i, nSSLBytes);
// 判断一下握手操作是否已完成
if (!p_session->is_handshake && SSL_is_init_finished(p_session->ssl))
{
iocp_trace("handshake finish with %s:%u", ip, port);
bHandshaked = TRUE;
}
if (nSSLBytes > 0)
{
#pragma message("接收到非握手数据, 交给上层处理")
pTransData[nSSLBytes] = 0;
printf("%d bytes non-handshake data from %s:%u:\n%s\n", nSSLBytes, ip, port, (LPCSTR)pTransData);
// 判断是否读完
if (!BIO_eof(p_session->bio_recv))
continue;
}
else if (__sslFailed(p_session->ssl, nSSLBytes))
{
CTX_Unlock(pContext);
DisconnectClient(pContext);
return FALSE;
}
else
{
iocp_trace("Context [0x%p] SSL_read result %d", pContext, nSSLBytes);
}
break;
}
// 与客户端的握手操作未完成, 需要从 BIO 中尝试取得握手回复消息发送给对方
if (!p_session->is_handshake)
{
i = 0;
p_session->is_handshake = bHandshaked;
// 循环读取直到读完
for (;;)
{
nSSLBytes = BIO_read(p_session->bio_send, pTransData, nBuffSize);
iocp_trace("Context [0x%p] BIO_read %d times %d bytes", pContext, ++i, nSSLBytes);
if (nSSLBytes > 0)
{
pBuffer->SetUsed(nSSLBytes);
CIocpModel::SendData(pBuffer, pContext);
if (BIO_eof(p_session->bio_send))
{
CTX_Unlock(pContext);
return TRUE;
}
pBuffer = AllocateBuffer(sandrer::IOCPBP_WRITETCP, TRUE);
if (pBuffer == NULL)
{
CTX_Unlock(pContext);
DisconnectClient(pContext);
return TRUE;
}
pTransData = pBuffer->GetBuffer();
nBuffSize = (int)pBuffer->GetSize();
continue;
}
else if (__sslFailed(p_session->ssl, nSSLBytes))
{
CTX_Unlock(pContext);
DisconnectClient(pContext);
return FALSE;
}
break;
}
}
CTX_Unlock(pContext);
return FALSE;
}