108 #pragma pack(push, 1) 124 memset(
this, 0,
sizeof(*
this) );
142 memset(
this, 0,
sizeof(*
this) );
145 template <
typename _Ty >
148 return reinterpret_cast<_Ty*
>(
this + 1 );
153 #pragma pack(push, 2) 162 memset(
this, 0,
sizeof(*
this) );
165 template <
typename _Ty >
168 return reinterpret_cast<_Ty*
>(
this + 1 );
179 memset(
this, 0,
sizeof(*
this) );
182 template <
typename _Ty >
185 return reinterpret_cast<_Ty*
>(
this + 1 );
197 memset(
this, 0,
sizeof(*
this) );
200 template <
typename _Ty >
203 return reinterpret_cast<_Ty*
>(
this + 1 );
214 memset(
this, 0,
sizeof(*
this) );
217 template <
typename _Ty >
220 return reinterpret_cast<_Ty*
>(
this + 1 );
232 memset(
this, 0,
sizeof(*
this) );
235 template <
typename _Ty >
238 return reinterpret_cast<_Ty*
>(
this + 1 );
246 template <
typename _Ty >
249 return reinterpret_cast<_Ty*
>(
this + 1 );
281 errCode =
htont(errCode);
282 data.
append( &errCode,
sizeof(errCode) );
305 :
ClientCtx( clientId, clientEpStr, clientSockPtr ), url(
http::Url::urlSimple), websocket(this)
318 bool isWebSocketWrapper =
false;
323 template <
class _ClientCtx = WsHttpClientCtx >
330 using MessageHandlerFunction = std::function< void( ClientCtxSharedPointer clientCtxPtr, winux::AnsiString const & data, int messageType ) >;
331 using CloseHandlerFunction = std::function< void( ClientCtxSharedPointer clientCtxPtr, winux::uint16 errCode, winux::AnsiString const & errStr ) >;
332 using ErrorHandlerFunction = std::function< void( ClientCtxSharedPointer clientCtxPtr, WebSocketErrorCode ec ) >;
335 :
Server<_ClientCtx>( ip::
EndPoint( serverIp, port ), threadCount, listenBacklog, durationSec )
356 int rc = clientCtxPtr->clientSockPtr->recvWaitUntilTarget(
358 &clientCtxPtr->forClient.data,
359 &clientCtxPtr->forClient.extraData,
360 &clientCtxPtr->forClient.hadBytes,
361 &clientCtxPtr->forClient.startpos,
362 &clientCtxPtr->forClient.pos,
363 this->_pool.getDurationSec(),
365 [&clientCtxPtr] (
int had,
void* ) {
366 clientCtxPtr->forClient.retryCount = 0;
370 if ( clientCtxPtr->forClient.pos != -1 )
373 clientCtxPtr->requestHeaderStr = clientCtxPtr->forClient.data.toAnsi();
374 clientCtxPtr->requestHeader.clear();
375 clientCtxPtr->requestHeader.parse(clientCtxPtr->requestHeaderStr);
377 clientCtxPtr->forClient.resetStatus();
378 clientCtxPtr->forClient.data = std::move(clientCtxPtr->forClient.extraData);
380 int contentLength =
static_cast<http::Header&
>(clientCtxPtr->requestHeader).getHeader<int>(
"Content-Length");
381 clientCtxPtr->forClient.targetBytes = contentLength - clientCtxPtr->forClient.data.getSize();
382 if ( clientCtxPtr->forClient.targetBytes > 0 )
393 else if ( rcWait == 0 )
395 clientCtxPtr->forClient.retryCount++;
403 ColorOutput(
winux::fgRed,
"Client[", clientCtxPtr->clientId,
"]从客户`", clientCtxPtr->clientEpStr,
"`接收一个请求头时长时间没有数据到来" );
404 ColorOutput(
winux::fgFuchsia,
"Client[", clientCtxPtr->clientId,
"]移除客户`", clientCtxPtr->clientEpStr,
"`,还剩", this->_clients.size() - 1,
"客户" );
405 this->removeClient(clientCtxPtr->clientId);
411 ColorOutput(
winux::fgFuchsia,
"Client[", clientCtxPtr->clientId,
"]移除客户`", clientCtxPtr->clientEpStr,
"`,还剩", this->_clients.size() - 1,
"客户" );
412 this->removeClient(clientCtxPtr->clientId);
420 int rc = clientCtxPtr->clientSockPtr->recvWaitUntilSize(
421 clientCtxPtr->forClient.targetBytes,
422 &clientCtxPtr->forClient.data,
423 &clientCtxPtr->forClient.hadBytes,
424 this->_pool.getDurationSec(),
426 [&clientCtxPtr] (
int had,
void* ) {
427 clientCtxPtr->forClient.retryCount = 0;
431 if ( clientCtxPtr->forClient.hadBytes == clientCtxPtr->forClient.targetBytes )
434 clientCtxPtr->requestBody = std::move(clientCtxPtr->forClient.data);
435 clientCtxPtr->forClient.resetStatus();
440 else if ( rcWait == 0 )
442 clientCtxPtr->forClient.retryCount++;
450 ColorOutput(
winux::fgRed,
"Client[", clientCtxPtr->clientId,
"]从客户`", clientCtxPtr->clientEpStr,
"`接收一个请求体时长时间没有数据到来" );
451 ColorOutput(
winux::fgFuchsia,
"Client[", clientCtxPtr->clientId,
"]移除客户`", clientCtxPtr->clientEpStr,
"`,还剩", this->_clients.size() - 1,
"客户" );
452 this->removeClient(clientCtxPtr->clientId);
457 ColorOutput(
winux::fgRed,
"Client[", clientCtxPtr->clientId,
"]从客户`", clientCtxPtr->clientEpStr,
"`接收请求体出错" );
458 ColorOutput(
winux::fgFuchsia,
"Client[", clientCtxPtr->clientId,
"]移除客户`", clientCtxPtr->clientEpStr,
"`,还剩", this->_clients.size() - 1,
"客户" );
459 this->removeClient(clientCtxPtr->clientId);
466 ColorOutput(
winux::fgGreen,
"Client[", clientCtxPtr->clientId,
"]从客户`", clientCtxPtr->clientEpStr,
"`接收请求头(bytes:", clientCtxPtr->requestHeaderStr.size(),
")" );
467 std::cout << clientCtxPtr->requestHeaderStr;
468 ColorOutput(
winux::fgAtrovirens,
"Client[", clientCtxPtr->clientId,
"]从客户`", clientCtxPtr->clientEpStr,
"`接收请求体(bytes:", clientCtxPtr->requestBody.getSize(),
")\n" );
471 std::stringbuf rspBuf;
472 std::ostream rspOut(&rspBuf);
475 rspHdr[
"Content-Type"] =
"text/html";
477 clientCtxPtr->url.
clear();
478 clientCtxPtr->url.parse( clientCtxPtr->requestHeader.getUrl() );
481 this->_webProcess( clientCtxPtr, clientCtxPtr->requestHeader, clientCtxPtr->url, rspHdr, rspOut );
485 if ( rspStr.size() > 0 )
486 rspHdr(
"Content-Length") << rspStr.size();
489 if ( clientCtxPtr->clientSockPtr->sendUntil( rspHdr.
toString() + rspStr ) )
492 if (
winux::StrLower( clientCtxPtr->requestHeader[
"Connection"] ) ==
"keep-alive" )
497 else if ( clientCtxPtr->isWebSocketWrapper )
502 this->onOpen(clientCtxPtr);
510 ColorOutput(
winux::fgFuchsia,
"Client[", clientCtxPtr->clientId,
"]移除客户`", clientCtxPtr->clientEpStr,
"`,还剩", this->_clients.size() - 1,
"客户" );
511 this->removeClient(clientCtxPtr->clientId);
516 if ( clientCtxPtr->isWebSocketWrapper )
522 ColorOutput(
winux::fgFuchsia,
"Client[", clientCtxPtr->clientId,
"]移除客户`", clientCtxPtr->clientEpStr,
"`,还剩", this->_clients.size() - 1,
"客户" );
523 this->removeClient(clientCtxPtr->clientId);
539 rspHdr[
"Upgrade"] =
"websocket";
540 rspHdr[
"Connection"] =
"Upgrade";
542 rspHdr[
"Sec-WebSocket-Accept"] = secWebsocketAccept;
544 ColorOutput(
winux::fgAqua,
"Client[", clientCtxPtr->clientId,
"]客户`", clientCtxPtr->clientEpStr,
"`升级为websocket连接" );
551 clientCtxPtr->isWebSocketWrapper =
true;
559 rspOut <<
"This is a websocket server!";
573 if ( !clientCtxPtr->clientSockPtr->recvUntilSize(
sizeof(
ws::FrameBase), &frameBuf ) )
578 goto RecvFrameFailure;
597 ColorOutput(
winux::fgRed,
"Client[", clientCtxPtr->clientId,
"]客户`", clientCtxPtr->clientEpStr,
"`读取16位帧载荷长度失败" );
598 goto RecvFrameFailure;
610 ColorOutput(
winux::fgRed,
"Client[", clientCtxPtr->clientId,
"]客户`", clientCtxPtr->clientEpStr,
"`读取64位帧载荷长度失败" );
611 goto RecvFrameFailure;
622 if ( !clientCtxPtr->clientSockPtr->recvUntilSize( 4, &frameBuf ) )
627 goto RecvFrameFailure;
632 if ( !clientCtxPtr->clientSockPtr->recvUntilSize( (
int)wantBytes, &frameBuf ) )
636 ColorOutput(
winux::fgRed,
"Client[", clientCtxPtr->clientId,
"]客户`", clientCtxPtr->clientEpStr,
"`读取载荷数据失败" );
637 goto RecvFrameFailure;
647 char * data = frame->
data<
char>();
648 size_t len = frame->payloadLen;
658 char * data = frame->
data<
char>();
659 int len = frame->payloadLen;
662 for (
int i = 0; i < len; ++i )
663 data[i] ^= frame->maskingKey[ i % 4 ];
673 char * data = frame->
data<
char>();
674 int len =
ntoht(frame->extendedPayloadLen);
684 char * data = frame->
data<
char>();
685 int len =
ntoht(frame->extendedPayloadLen);
688 for (
int i = 0; i < len; ++i )
689 data[i] ^= frame->maskingKey[ i % 4 ];
699 char * data = frame->
data<
char>();
710 char * data = frame->
data<
char>();
715 data[i] ^= frame->maskingKey[ i % 4 ];
726 ColorOutput(
winux::fgFuchsia,
"Client[", clientCtxPtr->clientId,
"]移除客户`", clientCtxPtr->clientEpStr,
"`,还剩", this->_clients.size() - 1,
"客户" );
727 this->removeClient(clientCtxPtr->clientId);
733 ColorOutput(
winux::fgGreen,
"Client[", clientCtxPtr->clientId,
"]客户`", clientCtxPtr->clientEpStr,
"`收到一个帧{fin:", (
winux::uint)fin,
",opcode:", opcode,
",datasize:", payloadData.
getSize(),
"}" );
741 clientCtxPtr->websocket.messageBuf.append( payloadData.
getBuf<
char>(), payloadData.
getSize() );
742 this->onMessage( clientCtxPtr, clientCtxPtr->websocket.messageBuf, clientCtxPtr->websocket.messageType );
743 clientCtxPtr->websocket.messageBuf.clear();
744 clientCtxPtr->websocket.messageType = 0;
748 clientCtxPtr->websocket.messageBuf.append( payloadData.
getBuf<
char>(), payloadData.
getSize() );
765 clientCtxPtr->websocket.messageBuf.append( payloadData.
getBuf<
char>(), payloadData.
getSize() );
766 clientCtxPtr->websocket.messageType =
opcode;
767 this->onMessage( clientCtxPtr, clientCtxPtr->websocket.messageBuf, clientCtxPtr->websocket.messageType );
768 clientCtxPtr->websocket.messageBuf.clear();
769 clientCtxPtr->websocket.messageType = 0;
773 clientCtxPtr->websocket.messageBuf.append( payloadData.
getBuf<
char>(), payloadData.
getSize() );
774 clientCtxPtr->websocket.messageType =
opcode;
787 if ( payloadData.
getSize() > 0 )
790 errCode =
ntoht(closeData->code);
792 ColorOutput(
winux::fgMaroon,
"Client[", clientCtxPtr->clientId,
"]客户`", clientCtxPtr->clientEpStr,
"`收到一个Close帧{errcode:", errCode,
",errstr:", errStr,
"}" );
802 clientCtxPtr->clientSockPtr->close();
805 this->onClose( clientCtxPtr, errCode, errStr );
808 ColorOutput(
winux::fgFuchsia,
"Client[", clientCtxPtr->clientId,
"]移除客户`", clientCtxPtr->clientEpStr,
"`,还剩", this->_clients.size() - 1,
"客户" );
809 this->removeClient(clientCtxPtr->clientId);
815 if ( clientCtxPtr->websocket.close( errCode, errStr ) )
818 clientCtxPtr->clientSockPtr->close();
821 this->onClose( clientCtxPtr, errCode, errStr );
823 ColorOutput(
winux::fgFuchsia,
"Client[", clientCtxPtr->clientId,
"]移除客户`", clientCtxPtr->clientEpStr,
"`,还剩", this->_clients.size() - 1,
"客户" );
824 this->removeClient(clientCtxPtr->clientId);
848 ColorOutput(
winux::fgRed,
"Client[", clientCtxPtr->clientId,
"]客户`", clientCtxPtr->clientEpStr,
"`收到一个意外帧{fin:",(
winux::uint)fin,
",opcode:",opcode,
",datasize:",payloadData.
getSize(),
"}" );
849 ColorOutput(
winux::fgFuchsia,
"Client[", clientCtxPtr->clientId,
"]移除客户`", clientCtxPtr->clientEpStr,
"`,还剩", this->_clients.size() - 1,
"客户" );
850 this->removeClient(clientCtxPtr->clientId);
857 if ( _openHandler ) _openHandler(clientCtxPtr);
862 if ( _messageHandler ) _messageHandler( clientCtxPtr, data, messageType );
867 if ( _closeHandler ) _closeHandler( clientCtxPtr, errCode, errStr );
872 if ( _errorHandler ) _errorHandler( clientCtxPtr, ec );
#define EIENNET_FUNC_DECL(ret)
void _doRequestTask(ClientCtxSharedPointer clientCtxPtr)
void * getBuf() const
暴露缓冲区指针
String StrLower(String const &str)
bool SendWebSocketFrame(eiennet::Socket *sock, OpCode opcode, bool fin, bool mask, winux::byte *payloadData=nullptr, winux::uint payloadDataSize=0)
virtual void onMessage(ClientCtxSharedPointer clientCtxPtr, winux::AnsiString const &data, int messageType)
std::basic_string< char > AnsiString
MessageHandlerFunction _messageHandler
virtual void onStartup(ClientCtxSharedPointer clientCtxPtr) override
virtual void onError(ClientCtxSharedPointer clientCtxPtr, WebSocketErrorCode ec)
static void ColorOutput(winux::ConsoleAttr const &ca, _ArgType &&...arg)
void onCloseHandler(CloseHandlerFunction handler)
WsHttpServer(winux::String const &serverIp, winux::ushort port, int threadCount=10, int listenBacklog=10, double durationSec=0.1)
void _doRecvRequestHeaderTask(ClientCtxSharedPointer clientCtxPtr)
std::function< void(ClientCtxSharedPointer clientCtxPtr, winux::AnsiString const &data, int messageType) > MessageHandlerFunction
void _doRecvRequestBodyTask(ClientCtxSharedPointer clientCtxPtr)
OpenHandlerFunction _openHandler
winux::uint16 extendedPayloadLen
Buffer Sha1(void const *buf, size_t size)
将数据进行sha1编码,返回二进制数据
std::function< void(ClientCtxSharedPointer clientCtxPtr, WebSocketErrorCode ec) > ErrorHandlerFunction
void onOpenHandler(OpenHandlerFunction handler)
std::function< void(ClientCtxSharedPointer clientCtxPtr, winux::uint16 errCode, winux::AnsiString const &errStr) > CloseHandlerFunction
winux::String const & getRawQueryStr() const
获取未解析的查询段字符串.不以'?'开头.
WsHttpClientCtx(winux::uint64 clientId, winux::String clientEpStr, winux::SharedPointer< ip::tcp::Socket > clientSockPtr)
virtual void onOpen(ClientCtxSharedPointer clientCtxPtr)
std::function< void(ClientCtxSharedPointer clientCtxPtr) > OpenHandlerFunction
void _webProcess(ClientCtxSharedPointer &clientCtxPtr, http::Header const &reqHdr, http::Url const &url, http::Header &rspHdr, std::ostream &rspOut)
winux::AnsiString requestHeaderStr
winux::AnsiString messageBuf
bool SendWebSocketBuffer(eiennet::Socket *sock, OpCode opcode, bool mask, winux::Buffer payloadData=winux::Buffer(), int perFrameMaxPayloadSize=-1)
void onMessageHandler(MessageHandlerFunction handler)
winux::uint64 extendedPayloadLen
WebSocketWrapper websocket
uint getSize() const
获取数据大小
缓冲区,表示内存中一块2进制数据(利用malloc/realloc进行内存分配)
ErrorHandlerFunction _errorHandler
winux::uint64 extendedPayloadLen
virtual ~WsHttpClientCtx()
String Base64Encode(void const *buf, int size)
Base64编码
winux::GrowBuffer requestBody
DataRecvSendCtx forClient
void _doRecvWebSocketFrameTask(ClientCtxSharedPointer clientCtxPtr)
typename Server< _ClientCtx >::ClientCtxSharedPointer ClientCtxSharedPointer
WebSocketErrorCode
WebSocket错误码
winux::String getPath() const
获取路径.
virtual void onClose(ClientCtxSharedPointer clientCtxPtr, winux::uint16 errCode, winux::AnsiString const &errStr)
CloseHandlerFunction _closeHandler
unsigned long long uint64
bool close(winux::uint16 errCode=-1, winux::AnsiString const &errStr="")
WebSocketWrapper(ClientCtx *clientCtx)
winux::SharedPointer< ip::tcp::Socket > clientSockPtr
void onErrorHandler(ErrorHandlerFunction handler)
bool send(winux::AnsiString const &data, ws::OpCode opcode=ws::dataText)
std::basic_string< tchar > String
void append(void const *data, uint size)
添加数据
bool SendWebSocketAnsi(eiennet::Socket *sock, OpCode opcode, bool mask, winux::AnsiString payloadData=winux::AnsiString(), int perFrameMaxPayloadSize=-1)
winux::uint16 extendedPayloadLen
void _doProcessWebSocketFrameTask(ClientCtxSharedPointer clientCtxPtr, bool fin, winux::uint opcode, winux::Buffer &payloadData)
http::Header requestHeader