fastdo  0.6.16
http_old.hpp
浏览该文件的文档.
1 #pragma once
2 
3 namespace http
4 {
6 namespace old_v1
7 {
10 {
11  winux::Configure const * constConfObj; // 可能为nullptr
19  double durationSec;
22 
23  std::map< winux::String, winux::String > mime; // MIME
24 
26  HttpServerConfig( winux::Configure const & confObj );
28  HttpServerConfig( winux::String const & serverIp, winux::ushort port, int threadCount, int listenBacklog, double durationSec );
29 
30  winux::String getMime( winux::String const & extName ) const;
31  void initMimeList();
32 };
33 
36 {
37 public:
39  : ClientCtx( clientId, clientEpStr, clientSockPtr ), url(http::urlSimple), config(nullptr)
40  {
41  }
42  virtual ~HttpClientCtx()
43  {
44  if ( !this->config || this->config->outputVerbose )
45  ColorOutput( winux::fgPurple, "Client[", clientId, "]客户场景`", clientEpStr, "`析构" );
46  }
47  eiennet::DataRecvSendCtx forClient; // 数据收发场景
48  winux::AnsiString requestHeaderStr; // 请求头字符串
50  winux::GrowBuffer requestBody; // 请求体数据
51  http::Url url; // URL
52  HttpServerConfig * config; // 引用配置对象
53 };
54 
56 class HTTPWRAPPER_DLL HttpServer : public eiennet::old_v1::Server<HttpClientCtx>
57 {
58 public:
60 
61  #define RESPONSE_HANDLER_PARAMS http::old_v1::HttpServer::ClientCtxSharedPointer & clientCtxPtr, http::Header const & reqHdr, http::Url const & url, http::Header & rspHdr, std::ostream & rspOut
62  using ResponseHandlerFunction = std::function< void ( RESPONSE_HANDLER_PARAMS ) >;
63 
65  HttpServer( HttpServerConfig const & confObj );
67  HttpServer( winux::String const & serverIp, winux::ushort port, int threadCount = 4, int listenBacklog = 10, double durationSec = 0.1 );
69  void setHandler( winux::String const & urlPath, ResponseHandlerFunction handler ) { _handlers[urlPath] = handler; }
70 
71 protected:
72  // 业务启动函数
73  virtual void onStartup( ClientCtxSharedPointer clientCtxPtr ) override;
74 
75  // 尝试接收一个请求头的任务
76  void _doRecvRequestHeaderTask( ClientCtxSharedPointer clientCtxPtr );
77 
78  // 尝试接收一个请求体的任务
79  void _doRecvRequestBodyTask( ClientCtxSharedPointer clientCtxPtr );
80 
81  // 处理一个请求的任务
82  void _doRequestTask( ClientCtxSharedPointer clientCtxPtr );
83 
84  // Web逻辑处理
85  void _webProcess( ClientCtxSharedPointer & clientCtxPtr, http::Header const & reqHdr, http::Url const & url, http::Header & rspHdr, std::ostream & rspOut );
86 
87 private:
88  std::map< winux::String, ResponseHandlerFunction > _handlers; // 响应处理函数
89  http::StaticFileMemoryCache _cache; // 静态文件内存缓存
90 
91  friend class HttpClientCtx;
92 };
93 
154 namespace ws
155 {
156 
159 {
161  dataText = 0x1U,
162  dataBinary = 0x2U,
163  dataRsv3 = 0x3U,
164  dataRsv4 = 0x4U,
165  dataRsv5 = 0x5U,
166  dataRsv6 = 0x6U,
167  dataRsv7 = 0x7U,
168  ctrlClose = 0x8U,
169  ctrlPing = 0x9U,
170  ctrlPong = 0xAU,
171  ctrlRsvB = 0xBU,
172  ctrlRsvC = 0xCU,
173  ctrlRsvD = 0xDU,
174  ctrlRsvE = 0xEU,
175  ctrlRsvF = 0xFU,
176 };
177 
180 {
183  //errCnnUpgradeFail,
184 };
185 
188 {
189  ftBasic = 0b0010,
190  ftBasicMasked = 0b0011,
191  ftExtended16 = 0b0100,
193  ftExtended64 = 0b1000,
195 };
196 
199 {
204 };
205 
206 #pragma pack(push, 1)
207 
209 struct FrameBase
210 {
211  winux::uint8 opcode:4;
212  winux::uint8 rsv3:1;
213  winux::uint8 rsv2:1;
214  winux::uint8 rsv1:1;
216 
217  winux::uint8 payloadLen:7;
218  winux::uint8 mask:1;
219 
221  {
222  memset( this, 0, sizeof(*this) );
223  }
224 };
225 
226 // 基本帧 payload len < 126, mask == 0
228 {
230  {
231  memset( this, 0, sizeof(*this) );
232  }
233 
234  template < typename _Ty >
235  _Ty * data()
236  {
237  return reinterpret_cast<_Ty*>( this + 1 );
238  }
239 };
240 #pragma pack(pop)
241 
242 #pragma pack(push, 2)
243 
244 // 基本掩码帧 payload len < 126, mask == 1
246 {
247  winux::uint8 maskingKey[4];
248 
250  {
251  memset( this, 0, sizeof(*this) );
252  }
253 
254  template < typename _Ty >
255  _Ty * data()
256  {
257  return reinterpret_cast<_Ty*>( this + 1 );
258  }
259 };
260 
261 // 16位数据扩展帧 payload len == 126, mask == 0
263 {
265 
267  {
268  memset( this, 0, sizeof(*this) );
269  }
270 
271  template < typename _Ty >
272  _Ty * data()
273  {
274  return reinterpret_cast<_Ty*>( this + 1 );
275  }
276 };
277 
278 // 16位数据扩展掩码帧 payload len == 126, mask == 1
280 {
282  winux::uint8 maskingKey[4];
283 
285  {
286  memset( this, 0, sizeof(*this) );
287  }
288 
289  template < typename _Ty >
290  _Ty * data()
291  {
292  return reinterpret_cast<_Ty*>( this + 1 );
293  }
294 };
295 
296 // 64位数据扩展帧 payload len == 127, mask == 0
298 {
300 
302  {
303  memset( this, 0, sizeof(*this) );
304  }
305 
306  template < typename _Ty >
307  _Ty * data()
308  {
309  return reinterpret_cast<_Ty*>( this + 1 );
310  }
311 };
312 
313 // 64位数据扩展掩码帧 payload len == 127, mask == 1
315 {
317  winux::uint8 maskingKey[4];
318 
320  {
321  memset( this, 0, sizeof(*this) );
322  }
323 
324  template < typename _Ty >
325  _Ty * data()
326  {
327  return reinterpret_cast<_Ty*>( this + 1 );
328  }
329 };
330 
331 // 关闭帧载荷数据
333 {
335  template < typename _Ty >
336  _Ty * data()
337  {
338  return reinterpret_cast<_Ty*>( this + 1 );
339  }
340 };
341 
342 
343 #pragma pack(pop)
344 
345 // 发送WebSocket帧
346 HTTPWRAPPER_FUNC_DECL(bool) SendWebSocketFrame( eiennet::Socket * sock, OpCode opcode, bool fin, bool mask, winux::byte * payloadData = nullptr, size_t payloadDataSize = 0 );
347 // 发送WebSocket数据
348 HTTPWRAPPER_FUNC_DECL(bool) SendWebSocketBuffer( eiennet::Socket * sock, OpCode opcode, bool mask, winux::Buffer payloadData = winux::Buffer(), size_t perFrameMaxPayloadSize = -1 );
349 // 发送WebSocket数据
350 HTTPWRAPPER_FUNC_DECL(bool) SendWebSocketAnsi( eiennet::Socket * sock, OpCode opcode, bool mask, winux::AnsiString payloadData = winux::AnsiString(), size_t perFrameMaxPayloadSize = -1 );
351 
352 
354 
356 {
357  WebSocketWrapper( eiennet::old_v1::ClientCtx * clientCtx ) : clientCtx(clientCtx)
358  {
359  }
361  winux::AnsiString messageBuf; // websocket消息缓冲区,用于接收多帧数据(一条消息可能分片)
362  int messageType = 0; // 消息类型,1文本;2二进制
363  ws::ReadyState state = ws::stateConnecting; // 连接状态
364 
365  // 发生close帧
366  bool close( winux::uint16 errCode = -1, winux::AnsiString const & errStr = "" )
367  {
368  winux::GrowBuffer data;
369  if ( errCode != (winux::uint16)-1 )
370  {
371  errCode = eiennet::htont(errCode);
372  data.append( &errCode, sizeof(errCode) );
373  data.appendString(errStr);
374  }
375  if ( !SendWebSocketBuffer( clientCtx->clientSockPtr.get(), ws::ctrlClose, false, std::move(data) ) ) return false;
376 
377  if ( this->state == ws::stateClosing )
378  this->state = ws::stateClosed;
379  else
380  this->state = ws::stateClosing;
381  return true;
382  }
383 
384  bool send( winux::AnsiString const & data, ws::OpCode opcode = ws::dataText )
385  {
386  return SendWebSocketAnsi( clientCtx->clientSockPtr.get(), opcode, false, data, 65535 );
387  }
388 };
389 
392 {
393 public:
395  : ClientCtx( clientId, clientEpStr, clientSockPtr ), url(http::urlSimple), config(nullptr), isWebSocketWrapper(false), websocket(this)
396  {
397  }
399  {
400  if ( !this->config || this->config->outputVerbose )
401  ColorOutputLine( winux::fgPurple, "Client[", clientId, "]客户场景`", clientEpStr, "`析构" );
402  }
403  eiennet::DataRecvSendCtx forClient; // 数据收发场景
404  winux::AnsiString requestHeaderStr; // 请求头字符串
406  winux::GrowBuffer requestBody; // 请求体数据
407  http::Url url; // URL
408  HttpServerConfig * config; // 配置参数
409 
410  bool isWebSocketWrapper; // 是否启用websocket包装
412 };
413 
415 template < class _ClientCtx = WsHttpClientCtx >
416 class WsHttpServer : public eiennet::old_v1::Server<_ClientCtx>
417 {
418 public:
420 
421  using OpenHandlerFunction = std::function< void( ClientCtxSharedPointer clientCtxPtr ) >;
422  using MessageHandlerFunction = std::function< void( ClientCtxSharedPointer clientCtxPtr, winux::AnsiString const & data, int messageType ) >;
423  using CloseHandlerFunction = std::function< void( ClientCtxSharedPointer clientCtxPtr, winux::uint16 errCode, winux::AnsiString const & errStr ) >;
424  using ErrorHandlerFunction = std::function< void( ClientCtxSharedPointer clientCtxPtr, WebSocketErrorCode ec ) >;
425 
426  using ResponseHandlerFunction = std::function< void ( ClientCtxSharedPointer & clientCtxPtr, http::Header const & reqHdr, http::Url const & url, http::Header & rspHdr, std::ostream & rspOut ) >;
427 
429 
430  WsHttpServer( HttpServerConfig const & confObj ) :
431  eiennet::old_v1::Server<_ClientCtx>( eiennet::ip::EndPoint( confObj.serverIp, confObj.serverPort ), confObj.threadCount, confObj.listenBacklog ),
432  config(confObj),
433  _cache(confObj.cacheLifeTime)
434  {
435  }
436 
437  WsHttpServer( winux::String const & serverIp, winux::ushort port, int threadCount = 10, int listenBacklog = 10, double durationSec = 0.1 ) :
438  eiennet::old_v1::Server<_ClientCtx>( eiennet::ip::EndPoint( serverIp, port ), threadCount, listenBacklog ),
439  config( serverIp, port, threadCount, listenBacklog, durationSec ),
440  _cache(config.cacheLifeTime)
441  {
442  }
444  void setHandler( winux::String const & urlPath, ResponseHandlerFunction handler ) { _handlers[urlPath] = handler; }
445 
447  void onOpenHandler( OpenHandlerFunction handler ) { _openHandler = handler; }
449  void onMessageHandler( MessageHandlerFunction handler ) { _messageHandler = handler; }
451  void onCloseHandler( CloseHandlerFunction handler ) { _closeHandler = handler; }
453  void onErrorHandler( ErrorHandlerFunction handler ) { _errorHandler = handler; }
454 
455 protected:
456  // 业务启动函数
457  virtual void onStartup( ClientCtxSharedPointer clientCtxPtr ) override
458  {
459  clientCtxPtr->config = &this->config;
460  if ( this->config.outputVerbose ) ColorOutputLine( winux::fgYellow, "Client[", clientCtxPtr->clientId, "]客户`", clientCtxPtr->clientEpStr, "`到来" );
461  this->_pool.task( &WsHttpServer::_doRecvRequestHeaderTask, this, clientCtxPtr ).post();
462  }
463 
464  // 尝试接收一个请求头的任务
466  {
467  int rcWait;
468  int rc = clientCtxPtr->clientSockPtr->recvWaitUntilTarget(
469  "\r\n\r\n",
470  &clientCtxPtr->forClient.data,
471  &clientCtxPtr->forClient.extraData,
472  &clientCtxPtr->forClient.hadBytes,
473  &clientCtxPtr->forClient.startpos,
474  &clientCtxPtr->forClient.pos,
475  this->config.durationSec,
476  &rcWait,
477  [&clientCtxPtr] ( int had, void* ) {
478  clientCtxPtr->forClient.retryCount = 0; // 重置次数
479  }
480  );
481 
482  if ( clientCtxPtr->forClient.pos != -1 ) // 接收成功
483  {
484  // 解析请求头
485  clientCtxPtr->requestHeaderStr = clientCtxPtr->forClient.data.toAnsi();
486  clientCtxPtr->requestHeader.clear();
487  clientCtxPtr->requestHeader.parse(clientCtxPtr->requestHeaderStr);
488 
489  clientCtxPtr->forClient.resetStatus(); // 重置收发状态
490  clientCtxPtr->forClient.data = std::move(clientCtxPtr->forClient.extraData); // 把额外接收的数据当作请求体数据
491  // 从Content-Length获取请求体大小
492  int contentLength = static_cast<http::Header&>(clientCtxPtr->requestHeader).getHeader<int>("Content-Length");
493  clientCtxPtr->forClient.targetBytes = contentLength - clientCtxPtr->forClient.data.getSize(); // 需要接收的目标大小
494  if ( clientCtxPtr->forClient.targetBytes > 0 ) // 需要完全接收请求体
495  {
496  // 投递尝试接收请求体
497  this->_pool.task( &WsHttpServer::_doRecvRequestBodyTask, this, clientCtxPtr ).post();
498  }
499  else // 不需要接收或已经接收完全请求体
500  {
501  // 保存请求体数据
502  clientCtxPtr->requestBody = std::move(clientCtxPtr->forClient.data);
503 
504  // 投递处理请求任务
505  this->_pool.task( &WsHttpServer::_doRequestTask, this, clientCtxPtr ).post();
506  }
507  }
508  else if ( rcWait == 0 )
509  {
510  clientCtxPtr->forClient.retryCount++;
511  if ( clientCtxPtr->forClient.retryCount < this->config.retryCount )
512  {
513  // 重投尝试接收请求头
514  this->_pool.task( &WsHttpServer::_doRecvRequestHeaderTask, this, clientCtxPtr ).post();
515  }
516  else
517  {
518  if ( this->config.outputVerbose ) ColorOutputLine( winux::fgRed, "Client[", clientCtxPtr->clientId, "]从客户`", clientCtxPtr->clientEpStr, "`接收一个请求头时长时间没有数据到来" );
519  if ( this->config.outputVerbose ) ColorOutputLine( winux::fgFuchsia, "Client[", clientCtxPtr->clientId, "]移除客户`", clientCtxPtr->clientEpStr, "`,还剩", this->getClientsCount() - 1, "客户" );
520  this->removeClient(clientCtxPtr->clientId);
521  }
522  }
523  else
524  {
525  if ( this->config.outputVerbose ) ColorOutputLine( winux::fgRed, "Client[", clientCtxPtr->clientId, "]从客户`", clientCtxPtr->clientEpStr, "`接收头部出错" );
526  if ( this->config.outputVerbose ) ColorOutputLine( winux::fgFuchsia, "Client[", clientCtxPtr->clientId, "]移除客户`", clientCtxPtr->clientEpStr, "`,还剩", this->getClientsCount() - 1, "客户" );
527  this->removeClient(clientCtxPtr->clientId);
528  }
529  }
530 
531  // 尝试接收一个请求体的任务
533  {
534  int rcWait;
535  int rc = clientCtxPtr->clientSockPtr->recvWaitUntilSize(
536  clientCtxPtr->forClient.targetBytes,
537  &clientCtxPtr->forClient.data,
538  &clientCtxPtr->forClient.hadBytes,
539  this->config.durationSec,
540  &rcWait,
541  [&clientCtxPtr] ( int had, void* ) {
542  clientCtxPtr->forClient.retryCount = 0;
543  }
544  );
545 
546  if ( clientCtxPtr->forClient.hadBytes == clientCtxPtr->forClient.targetBytes ) // 接收完成
547  {
548  // 保存请求体数据
549  clientCtxPtr->requestBody = std::move(clientCtxPtr->forClient.data);
550  clientCtxPtr->forClient.resetStatus(); // 重置收发状态
551 
552  // 投递处理请求任务
553  this->_pool.task( &WsHttpServer::_doRequestTask, this, clientCtxPtr ).post();
554  }
555  else if ( rcWait == 0 )
556  {
557  clientCtxPtr->forClient.retryCount++;
558  if ( clientCtxPtr->forClient.retryCount < this->config.retryCount )
559  {
560  // 重投尝试接收请求体
561  this->_pool.task( &WsHttpServer::_doRecvRequestBodyTask, this, clientCtxPtr ).post();
562  }
563  else
564  {
565  if ( this->config.outputVerbose ) ColorOutputLine( winux::fgRed, "Client[", clientCtxPtr->clientId, "]从客户`", clientCtxPtr->clientEpStr, "`接收一个请求体时长时间没有数据到来" );
566  if ( this->config.outputVerbose ) ColorOutputLine( winux::fgFuchsia, "Client[", clientCtxPtr->clientId, "]移除客户`", clientCtxPtr->clientEpStr, "`,还剩", this->getClientsCount() - 1, "客户" );
567  this->removeClient(clientCtxPtr->clientId);
568  }
569  }
570  else
571  {
572  if ( this->config.outputVerbose ) ColorOutputLine( winux::fgRed, "Client[", clientCtxPtr->clientId, "]从客户`", clientCtxPtr->clientEpStr, "`接收请求体出错" );
573  if ( this->config.outputVerbose ) ColorOutputLine( winux::fgFuchsia, "Client[", clientCtxPtr->clientId, "]移除客户`", clientCtxPtr->clientEpStr, "`,还剩", this->getClientsCount() - 1, "客户" );
574  this->removeClient(clientCtxPtr->clientId);
575  }
576  }
577 
578  // 处理一个请求的任务
580  {
581  if ( this->config.outputVerbose ) ColorOutputLine( winux::fgGreen, "Client[", clientCtxPtr->clientId, "]从客户`", clientCtxPtr->clientEpStr, "`接收请求头(bytes:", clientCtxPtr->requestHeaderStr.size(), ")" );
582  if ( this->config.outputVerbose ) std::cout << clientCtxPtr->requestHeaderStr;
583  if ( this->config.outputVerbose ) ColorOutputLine( winux::fgAtrovirens, "Client[", clientCtxPtr->clientId, "]从客户`", clientCtxPtr->clientEpStr, "`接收请求体(bytes:", clientCtxPtr->requestBody.getSize(), ")\n" );
584 
585  // 构造响应
586  std::stringbuf rspBuf;
587  std::ostream rspOut(&rspBuf);
588  http::Header rspHdr;
589  rspHdr.setResponseLine( "HTTP/1.1 200 OK", false );
590  rspHdr["Content-Type"] = "text/html";
591 
592  clientCtxPtr->url.clear();
593  clientCtxPtr->url.parse( clientCtxPtr->requestHeader.getUrl() );
594 
595  // 调用具体HTTP业务处理
596  this->_httpProcess( clientCtxPtr, clientCtxPtr->requestHeader, clientCtxPtr->url, rspHdr, rspOut );
597 
598  // 输出响应
599  winux::AnsiString rspStr = rspBuf.str();
600  rspHdr("Content-Length") << rspStr.size();
601  winux::AnsiString rspHdrStr = rspHdr.toString();
602 
603  // 发送响应
604  if ( clientCtxPtr->clientSockPtr->sendUntil( rspHdrStr + rspStr ) )
605  {
606  if ( this->config.outputVerbose ) ColorOutputLine( winux::fgGreen, "Client[", clientCtxPtr->clientId, "]服务器发送给客户`", clientCtxPtr->clientEpStr, "`响应(bytes:", rspHdrStr.size() + rspStr.size(), ")" );
607 
608  // 如果不保活就删除连接,否则继续投请求任务
609  if ( winux::StrLower( clientCtxPtr->requestHeader["Connection"] ) == "keep-alive" )
610  {
611  // 尝试接收下一个请求头
612  this->_pool.task( &WsHttpServer::_doRecvRequestHeaderTask, this, clientCtxPtr ).post();
613  }
614  else if ( clientCtxPtr->isWebSocketWrapper ) // 是否启用websocket包装,投递websocket处理任务
615  {
616  // 已经成功建立websocket连接
617  clientCtxPtr->websocket.state = ws::stateOpen;
618  // 调用onopen事件虚函数
619  this->onOpen(clientCtxPtr);
620 
621  // 投递接收websocket帧任务
622  this->_pool.task( &WsHttpServer::_doRecvWebSocketFrameTask, this, clientCtxPtr ).post();
623  }
624  else
625  {
626  if ( this->config.outputVerbose ) ColorOutputLine( winux::fgAqua, "Client[", clientCtxPtr->clientId, "]客户`", clientCtxPtr->clientEpStr, "`不保活,通信完毕即关闭" );
627  if ( this->config.outputVerbose ) ColorOutputLine( winux::fgFuchsia, "Client[", clientCtxPtr->clientId, "]移除客户`", clientCtxPtr->clientEpStr, "`,还剩", this->getClientsCount() - 1, "客户" );
628  this->removeClient(clientCtxPtr->clientId);
629  }
630  }
631  else // 发送响应失败
632  {
633  if ( clientCtxPtr->isWebSocketWrapper )
634  {
635  // websocket出错,连接意外失效
636  this->onError( clientCtxPtr, errCnnUnexpectedInvalid );
637  }
638  if ( this->config.outputVerbose ) ColorOutputLine( winux::fgRed, "Client[", clientCtxPtr->clientId, "]客户`", clientCtxPtr->clientEpStr, "`发送响应失败" );
639  if ( this->config.outputVerbose ) ColorOutputLine( winux::fgFuchsia, "Client[", clientCtxPtr->clientId, "]移除客户`", clientCtxPtr->clientEpStr, "`,还剩", this->getClientsCount() - 1, "客户" );
640  this->removeClient(clientCtxPtr->clientId);
641  }
642  }
643 
644  // 具体HTTP业务处理
645  void _httpProcess( ClientCtxSharedPointer & clientCtxPtr, http::Header const & reqHdr, http::Url const & url, http::Header & rspHdr, std::ostream & rspOut )
646  {
647  // 是否升级为websocket连接
648  if (
649  reqHdr.hasHeader("Upgrade") && reqHdr.getHeader("Upgrade") == "websocket" &&
650  reqHdr.hasHeader("Connection") && reqHdr.getHeader("Connection") == "Upgrade" &&
651  reqHdr.hasHeader("Sec-WebSocket-Key")
652  )
653  {
654  rspHdr.clear();
655  rspHdr.setResponseLine( "HTTP/1.1 101 Switching Protocols", false );
656  rspHdr["Upgrade"] = "websocket";
657  rspHdr["Connection"] = "Upgrade";
658  winux::String secWebsocketAccept = Base64EncodeBuffer( winux::Sha1( reqHdr.getHeader("Sec-WebSocket-Key") + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" ) );
659  rspHdr["Sec-WebSocket-Accept"] = secWebsocketAccept;
660 
661  if ( this->config.outputVerbose ) ColorOutputLine( winux::fgAqua, "Client[", clientCtxPtr->clientId, "]客户`", clientCtxPtr->clientEpStr, "`升级为websocket连接" );
662  if ( this->config.outputVerbose ) std::cout << rspHdr.toString();
663 
664  // 正在升级为websocket
665  clientCtxPtr->websocket.state = ws::stateConnecting;
666 
667  // 启用WebSocket包装
668  clientCtxPtr->isWebSocketWrapper = true;
669  }
670  else
671  {
672  this->_webProcess( clientCtxPtr, reqHdr, url, rspHdr, rspOut );
673  }
674  }
675 
676  // Web处理
677  void _webProcess( ClientCtxSharedPointer & clientCtxPtr, http::Header const & reqHdr, http::Url const & url, http::Header & rspHdr, std::ostream & rspOut )
678  {
679  winux::String urlPath = url.getPath();
680 
681  if ( winux::isset( _handlers, urlPath ) ) // 有响应处理
682  {
683  _handlers[urlPath].operator()( clientCtxPtr, clientCtxPtr->requestHeader, url, rspHdr, rspOut );
684 
685  if ( this->config.outputVerbose )
686  ColorOutputLine( winux::fgAqua, "Client[", clientCtxPtr->clientId, "] `", clientCtxPtr->clientEpStr, "` → request_uri: ", url.toString() );
687  }
688  else // 无响应处理,可以处理静态文件
689  {
690  winux::String filePath;
691  if ( urlPath.empty() )
692  {
693  winux::String fileName = this->config.documentIndex;
694  filePath = winux::CombinePath( this->config.documentRoot, fileName );
695  }
696  else
697  {
698  bool isDir = false;
699  filePath = winux::CombinePath( this->config.documentRoot, urlPath );
700  if ( winux::DetectPath( filePath, &isDir ) )
701  {
702  if ( isDir )
703  {
704  winux::String fileName = this->config.documentIndex;
705  filePath = winux::CombinePath( filePath, fileName );
706  }
707  }
708  else
709  {
710  goto ERR_NOT_FOUND;
711  }
712  }
713 
714  if ( _cache.hasCache(filePath) ) // 是否存在缓存
715  {
716  http::StaticFileMemoryCache::CacheItem const & cacheItem = _cache.get(filePath);
717  rspHdr["Content-Type"] = cacheItem.mime;
718  rspOut.write( cacheItem.content.getBuf<char const>(), cacheItem.content.getSize() );
719  if ( this->config.outputVerbose )
720  ColorOutputLine( winux::fgAqua, "Client[", clientCtxPtr->clientId, "] `", clientCtxPtr->clientEpStr, "` 读取到了缓存`",filePath,"`" );
721  }
722  else if ( winux::DetectPath(filePath) ) // 静态文件是否存在
723  {
724  winux::String extName;
725  winux::FileTitle( filePath, &extName );
726  http::StaticFileMemoryCache::CacheItem & cacheItem = _cache.writeCache( filePath, this->config.getMime(extName), winux::FileGetContentsEx( filePath, false ) );
727  rspHdr["Content-Type"] = cacheItem.mime;
728  rspOut.write( cacheItem.content.getBuf<char const>(), cacheItem.content.getSize() );
729  if ( this->config.outputVerbose )
730  ColorOutputLine( winux::fgAqua, "Client[", clientCtxPtr->clientId, "] `", clientCtxPtr->clientEpStr, "` 读取到了静态文件`",filePath,"`" );
731  }
732  else
733  {
734  ERR_NOT_FOUND:
735  // 响应
736  rspOut << "<h1>HTTP 404</h1><strong>URLpath: `" << filePath << "` is not found!</strong>";
737  rspHdr.setStatusCode("404").setStatusStr("Not found");
738  }
739 
740  if ( this->config.outputVerbose )
741  ColorOutputLine( winux::fgAqua, "Client[", clientCtxPtr->clientId, "] `", clientCtxPtr->clientEpStr, "` → request_uri: ", url.toString(), ", filepath: ", filePath );
742  }
743  }
744 
745  // 接收一个WebSocket帧的任务
747  {
748  winux::GrowBuffer frameBuf;
749  ws::FrameBase * frame0;
750  winux::int64 wantBytes = 0;
751  winux::uint8 frameType = 0;
752 
753  // 先读取2字节的帧基础
754  if ( !clientCtxPtr->clientSockPtr->recvUntilSize( sizeof(ws::FrameBase), &frameBuf ) )
755  {
756  // websocket出错,连接意外失效
757  this->onError( clientCtxPtr, errCnnUnexpectedInvalid );
758  if ( this->config.outputVerbose ) ColorOutputLine( winux::fgRed, "Client[", clientCtxPtr->clientId, "]客户`", clientCtxPtr->clientEpStr, "`读取帧基础失败" );
759  goto RecvFrameFailure;
760  }
761 
762  frame0 = frameBuf.getBuf<ws::FrameBase>();
763 
764  // 判断并读取载荷数据长度
765  if ( frame0->payloadLen < 126 )
766  {
767  frameType |= ws::ftBasic;
768  auto frame1 = frameBuf.getBuf<ws::FrameBasic>();
769  wantBytes += frame1->payloadLen;
770  }
771  else if ( frame0->payloadLen == 126 )
772  {
773  frameType |= ws::ftExtended16;
774  if ( !clientCtxPtr->clientSockPtr->recvUntilSize( sizeof(ws::FrameExtended16::extendedPayloadLen), &frameBuf ) )
775  {
776  // websocket出错,连接意外失效
777  this->onError( clientCtxPtr, errCnnUnexpectedInvalid );
778  if ( this->config.outputVerbose ) ColorOutputLine( winux::fgRed, "Client[", clientCtxPtr->clientId, "]客户`", clientCtxPtr->clientEpStr, "`读取16位帧载荷长度失败" );
779  goto RecvFrameFailure;
780  }
781  auto len = eiennet::ntoht( frameBuf.getBuf<ws::FrameExtended16>()->extendedPayloadLen ); // `extendedPayloadLen` is network byte order
782  wantBytes += len;
783  }
784  else // 127
785  {
786  frameType |= ws::ftExtended64;
787  if ( !clientCtxPtr->clientSockPtr->recvUntilSize( sizeof(ws::FrameExtended64::extendedPayloadLen), &frameBuf ) )
788  {
789  // websocket出错,连接意外失效
790  this->onError( clientCtxPtr, errCnnUnexpectedInvalid );
791  if ( this->config.outputVerbose ) ColorOutputLine( winux::fgRed, "Client[", clientCtxPtr->clientId, "]客户`", clientCtxPtr->clientEpStr, "`读取64位帧载荷长度失败" );
792  goto RecvFrameFailure;
793  }
794  auto len = eiennet::ntoht( frameBuf.getBuf<ws::FrameExtended64>()->extendedPayloadLen ); // `extendedPayloadLen` is network byte order
795  wantBytes += len;
796  }
797 
798  // 是否有掩码
799  if ( frame0->mask )
800  {
801  frameType |= 1;
802  // 读取掩码
803  if ( !clientCtxPtr->clientSockPtr->recvUntilSize( 4, &frameBuf ) )
804  {
805  // websocket出错,连接意外失效
806  this->onError( clientCtxPtr, errCnnUnexpectedInvalid );
807  if ( this->config.outputVerbose ) ColorOutputLine( winux::fgRed, "Client[", clientCtxPtr->clientId, "]客户`", clientCtxPtr->clientEpStr, "`读取帧掩码失败" );
808  goto RecvFrameFailure;
809  }
810  }
811 
812  // 读取载荷数据
813  if ( !clientCtxPtr->clientSockPtr->recvUntilSize( (int)wantBytes, &frameBuf ) )
814  {
815  // websocket出错,连接意外失效
816  this->onError( clientCtxPtr, errCnnUnexpectedInvalid );
817  if ( this->config.outputVerbose ) ColorOutputLine( winux::fgRed, "Client[", clientCtxPtr->clientId, "]客户`", clientCtxPtr->clientEpStr, "`读取载荷数据失败" );
818  goto RecvFrameFailure;
819  }
820 
821  // 进入帧处理
822  switch ( frameType )
823  {
824  case ws::ftBasic:
825  {
826  auto frame = frameBuf.getBuf<ws::FrameBasic>();
827  // 得到数据
828  char * data = frame->data<char>();
829  size_t len = frame->payloadLen;
830 
831  // 投递处理WebSocket帧任务
832  this->_pool.task( &WsHttpServer::_doProcessWebSocketFrameTask, this, clientCtxPtr, (bool)frame->fin, (winux::uint)frame->opcode, winux::Buffer( data, len ) ).post();
833  }
834  break;
835  case ws::ftBasicMasked:
836  {
837  auto frame = frameBuf.getBuf<ws::FrameBasicMasked>();
838  // 得到数据
839  char * data = frame->data<char>();
840  int len = frame->payloadLen;
841 
842  // 掩码算法
843  for ( int i = 0; i < len; ++i )
844  data[i] ^= frame->maskingKey[ i % 4 ];
845 
846  // 投递处理WebSocket帧任务
847  this->_pool.task( &WsHttpServer::_doProcessWebSocketFrameTask, this, clientCtxPtr, (bool)frame->fin, (winux::uint)frame->opcode, winux::Buffer( data, len ) ).post();
848  }
849  break;
850  case ws::ftExtended16:
851  {
852  auto frame = frameBuf.getBuf<ws::FrameExtended16>();
853  // 得到数据
854  char * data = frame->data<char>();
855  int len = eiennet::ntoht(frame->extendedPayloadLen);
856 
857  // 投递处理WebSocket帧任务
858  this->_pool.task( &WsHttpServer::_doProcessWebSocketFrameTask, this, clientCtxPtr, (bool)frame->fin, (winux::uint)frame->opcode, winux::Buffer( data, len ) ).post();
859  }
860  break;
862  {
863  auto frame = frameBuf.getBuf<ws::FrameExtended16Masked>();
864  // 得到数据
865  char * data = frame->data<char>();
866  int len = eiennet::ntoht(frame->extendedPayloadLen);
867 
868  // 掩码算法
869  for ( int i = 0; i < len; ++i )
870  data[i] ^= frame->maskingKey[ i % 4 ];
871 
872  // 投递处理WebSocket帧任务
873  this->_pool.task( &WsHttpServer::_doProcessWebSocketFrameTask, this, clientCtxPtr, (bool)frame->fin, (winux::uint)frame->opcode, winux::Buffer( data, (winux::uint)len ) ).post();
874  }
875  break;
876  case ws::ftExtended64:
877  {
878  auto frame = frameBuf.getBuf<ws::FrameExtended64>();
879  // 得到数据
880  char * data = frame->data<char>();
881  winux::int64 len = eiennet::ntoht(frame->extendedPayloadLen);
882 
883  // 投递处理WebSocket帧任务
884  this->_pool.task( &WsHttpServer::_doProcessWebSocketFrameTask, this, clientCtxPtr, (bool)frame->fin, (winux::uint)frame->opcode, winux::Buffer( data, (winux::uint)len ) ).post();
885  }
886  break;
888  {
889  auto frame = frameBuf.getBuf<ws::FrameExtended64Masked>();
890  // 得到数据
891  char * data = frame->data<char>();
892  winux::int64 len = eiennet::ntoht(frame->extendedPayloadLen);
893 
894  // 掩码算法
895  for ( winux::int64 i = 0; i < len; ++i )
896  data[i] ^= frame->maskingKey[ i % 4 ];
897 
898  // 投递处理WebSocket帧任务
899  this->_pool.task( &WsHttpServer::_doProcessWebSocketFrameTask, this, clientCtxPtr, (bool)frame->fin, (winux::uint)frame->opcode, winux::Buffer( data, (winux::uint)len ) ).post();
900  }
901  break;
902  }
903 
904  return;
905 
906  RecvFrameFailure:
907  if ( this->config.outputVerbose ) ColorOutputLine( winux::fgFuchsia, "Client[", clientCtxPtr->clientId, "]移除客户`", clientCtxPtr->clientEpStr, "`,还剩", this->getClientsCount() - 1, "客户" );
908  this->removeClient(clientCtxPtr->clientId);
909  }
910 
911  // 处理WebSocket帧的任务
912  void _doProcessWebSocketFrameTask( ClientCtxSharedPointer clientCtxPtr, bool fin, winux::uint opcode, winux::Buffer & payloadData )
913  {
914  if ( this->config.outputVerbose ) ColorOutputLine( winux::fgGreen, "Client[", clientCtxPtr->clientId, "]客户`", clientCtxPtr->clientEpStr, "`收到一个帧{fin:", (winux::uint)fin, ",opcode:", opcode, ",datasize:", payloadData.getSize(), "}" );
915 
916  switch ( opcode )
917  {
918  case ws::dataContinued:
919  {
920  if ( fin )
921  {
922  clientCtxPtr->websocket.messageBuf.append( payloadData.getBuf<char>(), payloadData.getSize() );
923  this->onMessage( clientCtxPtr, clientCtxPtr->websocket.messageBuf, clientCtxPtr->websocket.messageType );
924  clientCtxPtr->websocket.messageBuf.clear();
925  clientCtxPtr->websocket.messageType = 0;
926  }
927  else
928  {
929  clientCtxPtr->websocket.messageBuf.append( payloadData.getBuf<char>(), payloadData.getSize() );
930  }
931 
932  // 投递接收下一个websocket帧的任务
933  this->_pool.task( &WsHttpServer::_doRecvWebSocketFrameTask, this, clientCtxPtr ).post();
934  }
935  break;
936  case ws::dataText:
937  case ws::dataBinary:
938  case ws::dataRsv3:
939  case ws::dataRsv4:
940  case ws::dataRsv5:
941  case ws::dataRsv6:
942  case ws::dataRsv7:
943  {
944  if ( fin )
945  {
946  clientCtxPtr->websocket.messageBuf.append( payloadData.getBuf<char>(), payloadData.getSize() );
947  clientCtxPtr->websocket.messageType = opcode;
948  this->onMessage( clientCtxPtr, clientCtxPtr->websocket.messageBuf, clientCtxPtr->websocket.messageType );
949  clientCtxPtr->websocket.messageBuf.clear();
950  clientCtxPtr->websocket.messageType = 0;
951  }
952  else
953  {
954  clientCtxPtr->websocket.messageBuf.append( payloadData.getBuf<char>(), payloadData.getSize() );
955  clientCtxPtr->websocket.messageType = opcode;
956  }
957 
958  // 投递接收下一个websocket帧的任务
959  this->_pool.task( &WsHttpServer::_doRecvWebSocketFrameTask, this, clientCtxPtr ).post();
960  }
961  break;
962  case ws::ctrlClose:
963  {
964  // 收到一个close帧
965  // 如果有载荷
966  winux::uint16 errCode = 0;
967  winux::AnsiString errStr;
968  if ( payloadData.getSize() > 0 )
969  {
970  auto closeData = payloadData.getBuf<ws::CloseFramePayloadData>();
971  errCode = eiennet::ntoht(closeData->code);
972  errStr.assign( closeData->data<char>(), payloadData.getSize() - sizeof(ws::CloseFramePayloadData::code) );
973  if ( this->config.outputVerbose ) ColorOutputLine( winux::fgMaroon, "Client[", clientCtxPtr->clientId, "]客户`", clientCtxPtr->clientEpStr, "`收到一个Close帧{errcode:", errCode, ",errstr:", errStr, "}" );
974  }
975  else // 没有载荷数据
976  {
977  if ( this->config.outputVerbose ) ColorOutputLine( winux::fgMaroon, "Client[", clientCtxPtr->clientId, "]客户`", clientCtxPtr->clientEpStr, "`收到一个Close帧" );
978  }
979 
980  // 收到一个close帧,如果处在closing状态,应立即关闭连接并改为closed状态;如果不处在closing状态则改为closing,发送一个close帧到对方后改为closed。
981  if ( clientCtxPtr->websocket.state == ws::stateClosing )
982  {
983  clientCtxPtr->clientSockPtr->close();
984  clientCtxPtr->websocket.state = ws::stateClosed;
985 
986  this->onClose( clientCtxPtr, errCode, errStr ); // 处理onclose事件
987 
988  // 删除场景
989  if ( this->config.outputVerbose ) ColorOutputLine( winux::fgFuchsia, "Client[", clientCtxPtr->clientId, "]移除客户`", clientCtxPtr->clientEpStr, "`,还剩", this->getClientsCount() - 1, "客户" );
990  this->removeClient(clientCtxPtr->clientId);
991  }
992  else
993  {
994  clientCtxPtr->websocket.state = ws::stateClosing;
995 
996  if ( clientCtxPtr->websocket.close( errCode, errStr ) )
997  {
998  if ( this->config.outputVerbose ) ColorOutputLine( winux::fgAqua, "服务器回了一个close帧" );
999  clientCtxPtr->clientSockPtr->close();
1000  clientCtxPtr->websocket.state = ws::stateClosed;
1001  }
1002 
1003  this->onClose( clientCtxPtr, errCode, errStr ); // 处理onclose事件
1004 
1005  if ( this->config.outputVerbose ) ColorOutputLine( winux::fgFuchsia, "Client[", clientCtxPtr->clientId, "]移除客户`", clientCtxPtr->clientEpStr, "`,还剩", this->getClientsCount() - 1, "客户" );
1006  this->removeClient(clientCtxPtr->clientId);
1007  }
1008  }
1009  break;
1010  case ws::ctrlPing:
1011  {
1012  // 收到一个ping帧,回一个pong帧
1013  SendWebSocketAnsi( clientCtxPtr->clientSockPtr.get(), ws::ctrlPong, false );
1014 
1015  // 投递接收下一个websocket帧任务
1016  this->_pool.task( &WsHttpServer::_doRecvWebSocketFrameTask, this, clientCtxPtr ).post();
1017  }
1018  break;
1019  case ws::ctrlPong:
1020  {
1021  // 收到pong帧,无视
1022 
1023  // 投递接收下一个websocket帧任务
1024  this->_pool.task( &WsHttpServer::_doRecvWebSocketFrameTask, this, clientCtxPtr ).post();
1025  }
1026  break;
1027  default:
1028  // 意外帧
1029  if ( this->config.outputVerbose ) ColorOutputLine( winux::fgRed, "Client[", clientCtxPtr->clientId, "]客户`", clientCtxPtr->clientEpStr, "`收到一个意外帧{fin:",(winux::uint)fin,",opcode:",opcode,",datasize:",payloadData.getSize(),"}" );
1030  if ( this->config.outputVerbose ) ColorOutputLine( winux::fgFuchsia, "Client[", clientCtxPtr->clientId, "]移除客户`", clientCtxPtr->clientEpStr, "`,还剩", this->getClientsCount() - 1, "客户" );
1031  this->removeClient(clientCtxPtr->clientId);
1032  break;
1033  }
1034  }
1035 
1036  virtual void onOpen( ClientCtxSharedPointer clientCtxPtr )
1037  {
1038  if ( _openHandler ) _openHandler(clientCtxPtr);
1039  }
1040 
1041  virtual void onMessage( ClientCtxSharedPointer clientCtxPtr, winux::AnsiString const & data, int messageType )
1042  {
1043  if ( _messageHandler ) _messageHandler( clientCtxPtr, data, messageType );
1044  }
1045 
1046  virtual void onClose( ClientCtxSharedPointer clientCtxPtr, winux::uint16 errCode, winux::AnsiString const & errStr )
1047  {
1048  if ( _closeHandler ) _closeHandler( clientCtxPtr, errCode, errStr );
1049  }
1050 
1051  virtual void onError( ClientCtxSharedPointer clientCtxPtr, WebSocketErrorCode ec )
1052  {
1053  if ( _errorHandler ) _errorHandler( clientCtxPtr, ec );
1054  }
1055 
1060 
1061  std::map< winux::String, ResponseHandlerFunction > _handlers; // 响应处理函数
1062  http::StaticFileMemoryCache _cache; // 静态文件内存缓存
1063 
1064 };
1065 
1066 } // namespace ws
1067 
1068 } // namespace old_v1
1069 
1070 } // namespace http
XString< char > AnsiString
Definition: utilities.hpp:257
#define HTTPWRAPPER_FUNC_DECL(ret)
Definition: http_base.hpp:28
eiennet::old_v1::ClientCtx * clientCtx
Definition: http_old.hpp:360
__int64 int64
Definition: utilities.hpp:232
http::StaticFileMemoryCache _cache
Definition: http_old.hpp:1062
void append(void const *data, size_t size)
添加数据:C语言缓冲区
代表HTTP头部
Definition: http_Header.hpp:10
void _doRequestTask(ClientCtxSharedPointer clientCtxPtr)
Definition: http_old.hpp:579
void * getBuf() const
暴露缓冲区指针
Definition: utilities.hpp:993
ErrorHandlerFunction _errorHandler
Definition: http_old.hpp:1059
#define HTTPWRAPPER_DLL
Definition: http_base.hpp:24
eiennet::DataRecvSendCtx forClient
Definition: http_old.hpp:47
void _doRecvWebSocketFrameTask(ClientCtxSharedPointer clientCtxPtr)
Definition: http_old.hpp:746
void onErrorHandler(ErrorHandlerFunction handler)
设置WebSocket出错事件处理
Definition: http_old.hpp:453
winux::SharedPointer< ip::tcp::Socket > clientSockPtr
std::function< void(http::old_v1::HttpServer::ClientCtxSharedPointer &clientCtxPtr, http::Header const &reqHdr, http::Url const &url, http::Header &rspHdr, std::ostream &rspOut) > ResponseHandlerFunction
Definition: http_old.hpp:62
void clear()
清空
HTTP服务器配置
Definition: http_old.hpp:9
virtual void onStartup(ClientCtxSharedPointer clientCtxPtr) override
Definition: http_old.hpp:457
void onOpenHandler(OpenHandlerFunction handler)
设置WebSocket打开事件处理
Definition: http_old.hpp:447
CloseHandlerFunction _closeHandler
Definition: http_old.hpp:1058
winux::String getHeader(winux::String const &name, winux::String const &defval=winux::String()) const
Definition: http_Header.hpp:86
void _doProcessWebSocketFrameTask(ClientCtxSharedPointer clientCtxPtr, bool fin, winux::uint opcode, winux::Buffer &payloadData)
Definition: http_old.hpp:912
winux::String toString(bool isAddCrlfAtEnd=true) const
转为字符串,isAddCrlfAtEnd指示末尾是否添加\r\n
WsHttpServer(HttpServerConfig const &confObj)
Definition: http_old.hpp:430
OpCode
操作码
Definition: http_old.hpp:158
void setHandler(winux::String const &urlPath, ResponseHandlerFunction handler)
设置动态页面处理
Definition: http_old.hpp:444
HTTP客户场景
Definition: http_old.hpp:35
static void ColorOutputLine(winux::ConsoleAttr const &ca, _ArgType &&...arg)
Definition: console.hpp:197
static void ColorOutput(winux::ConsoleAttr const &ca, _ArgType &&...arg)
Definition: console.hpp:215
HttpServerConfig config
配置参数
Definition: http_old.hpp:59
配置文件类
Definition: archives.hpp:10
bool SendWebSocketBuffer(eiennet::Socket *sock, OpCode opcode, bool mask, winux::Buffer payloadData=winux::Buffer(), size_t perFrameMaxPayloadSize=-1)
XString< tchar > String
Definition: utilities.hpp:261
std::function< void(ClientCtxSharedPointer clientCtxPtr, winux::uint16 errCode, winux::AnsiString const &errStr) > CloseHandlerFunction
Definition: http_old.hpp:423
bool send(winux::AnsiString const &data, ws::OpCode opcode=ws::dataText)
Definition: http_old.hpp:384
XString< _ChTy > StrLower(XString< _ChTy > str)
HTTP服务器
Definition: http_old.hpp:56
Header & setStatusCode(winux::String const &statusCode)
状态码. For a response: required.
void _webProcess(ClientCtxSharedPointer &clientCtxPtr, http::Header const &reqHdr, http::Url const &url, http::Header &rspHdr, std::ostream &rspOut)
Definition: http_old.hpp:677
FrameType
数据帧类型
Definition: http_old.hpp:187
Buffer Sha1(void const *buf, size_t size)
将数据进行sha1编码,返回二进制数据
HTTP协议的相关简单类封装
Definition: http_base.hpp:32
bool SendWebSocketFrame(eiennet::Socket *sock, OpCode opcode, bool fin, bool mask, winux::byte *payloadData=nullptr, size_t payloadDataSize=0)
size_t getSize() const
获取数据大小
Definition: utilities.hpp:1025
eiennet::DataRecvSendCtx forClient
Definition: http_old.hpp:403
winux::GrowBuffer requestBody
Definition: http_old.hpp:50
URL类
Definition: http_Url.hpp:19
OpenHandlerFunction _openHandler
Definition: http_old.hpp:1056
HttpServerConfig * config
Definition: http_old.hpp:52
std::function< void(ClientCtxSharedPointer &clientCtxPtr, http::Header const &reqHdr, http::Url const &url, http::Header &rspHdr, std::ostream &rspOut) > ResponseHandlerFunction
Definition: http_old.hpp:426
WsHttpServer(winux::String const &serverIp, winux::ushort port, int threadCount=10, int listenBacklog=10, double durationSec=0.1)
Definition: http_old.hpp:437
引用计数共享指针
Definition: smartptr.hpp:456
HttpClientCtx(winux::uint64 clientId, winux::String clientEpStr, winux::SharedPointer< eiennet::ip::tcp::Socket > clientSockPtr)
Definition: http_old.hpp:38
套接字基础类
ReadyState
就绪状态
Definition: http_old.hpp:198
缓冲区,表示内存中一块二进制数据(利用malloc/realloc进行内存分配)
Definition: utilities.hpp:906
数据收发场景,存放数据收发过程中的一些变量
WsHttpClientCtx(winux::uint64 clientId, winux::String clientEpStr, winux::SharedPointer< eiennet::ip::tcp::Socket > clientSockPtr)
Definition: http_old.hpp:394
String CombinePath(String const &dirPath, String const &fileName)
把一个目录路径和一个文件名组合成一个新路径
virtual void onOpen(ClientCtxSharedPointer clientCtxPtr)
Definition: http_old.hpp:1036
bool DetectPath(String const &path, bool *isDir=NULL)
探测一个路径是存在还是不存在,是目录还是文件
void _doRecvRequestBodyTask(ClientCtxSharedPointer clientCtxPtr)
Definition: http_old.hpp:532
std::map< winux::String, winux::String > mime
Definition: http_old.hpp:23
void onCloseHandler(CloseHandlerFunction handler)
设置WebSocket关闭事件处理
Definition: http_old.hpp:451
virtual void onMessage(ClientCtxSharedPointer clientCtxPtr, winux::AnsiString const &data, int messageType)
Definition: http_old.hpp:1041
简单的分段
Definition: http_Url.hpp:9
bool hasHeader(winux::String const &name) const
Definition: http_Header.hpp:95
bool isset(_MAP const &m, _KEY const &k)
检测map中是否有该键的值
Definition: utilities.hpp:807
客户场景类基础
unsigned int uint
Definition: utilities.hpp:215
std::map< winux::String, ResponseHandlerFunction > _handlers
Definition: http_old.hpp:1061
void onMessageHandler(MessageHandlerFunction handler)
设置WebSocket消息到达事件处理
Definition: http_old.hpp:449
bool close(winux::uint16 errCode=-1, winux::AnsiString const &errStr="")
Definition: http_old.hpp:366
virtual void onError(ClientCtxSharedPointer clientCtxPtr, WebSocketErrorCode ec)
Definition: http_old.hpp:1051
void setResponseLine(winux::String const &responseLine, bool setStatus=true)
设置响应行 格式: HttpVersion StatusCode StatusStr eg. HTTP/1.1 200 OK
String FileTitle(String const &fileName, String *extName=NULL)
获取文件标题
typename eiennet::old_v1::Server< _ClientCtx >::ClientCtxSharedPointer ClientCtxSharedPointer
Definition: http_old.hpp:419
unsigned char byte
Definition: utilities.hpp:249
网络通信库
virtual void onClose(ClientCtxSharedPointer clientCtxPtr, winux::uint16 errCode, winux::AnsiString const &errStr)
Definition: http_old.hpp:1046
http::Header requestHeader
Definition: http_old.hpp:49
高效的可增长缓冲区,1.33倍冗余量
Definition: utilities.hpp:1103
XString< _ChTy > Base64EncodeBuffer(Buffer const &buf)
Base64编码
Definition: encoding.hpp:178
void setHandler(winux::String const &urlPath, ResponseHandlerFunction handler)
设置动态页面处理
Definition: http_old.hpp:69
WebSocketWrapper(eiennet::old_v1::ClientCtx *clientCtx)
Definition: http_old.hpp:357
静态文件内存缓存(带互斥锁)
std::function< void(ClientCtxSharedPointer clientCtxPtr) > OpenHandlerFunction
Definition: http_old.hpp:421
winux::String getMime(winux::String const &extName) const
_Ty ntoht(_Ty v)
unsigned short ushort
Definition: utilities.hpp:218
unsigned short uint16
Definition: utilities.hpp:218
_Ty htont(_Ty v)
bool SendWebSocketAnsi(eiennet::Socket *sock, OpCode opcode, bool mask, winux::AnsiString payloadData=winux::AnsiString(), size_t perFrameMaxPayloadSize=-1)
winux::Configure const * constConfObj
Definition: http_old.hpp:11
winux::AnsiString requestHeaderStr
Definition: http_old.hpp:48
void _doRecvRequestHeaderTask(ClientCtxSharedPointer clientCtxPtr)
Definition: http_old.hpp:465
winux::String toString() const
根据flags和存储的信息组装成整个URL串
winux::String getPath() const
获取路径。不以&#39;/&#39;开头
std::function< void(ClientCtxSharedPointer clientCtxPtr, winux::AnsiString const &data, int messageType) > MessageHandlerFunction
Definition: http_old.hpp:422
WebSocketErrorCode
WebSocket错误码
Definition: http_old.hpp:179
服务器类基础
void _httpProcess(ClientCtxSharedPointer &clientCtxPtr, http::Header const &reqHdr, http::Url const &url, http::Header &rspHdr, std::ostream &rspOut)
Definition: http_old.hpp:645
#define U(s)
Definition: strings.hpp:1141
MessageHandlerFunction _messageHandler
Definition: http_old.hpp:1057
WebSocket场景包装
Definition: http_old.hpp:355
unsigned __int64 uint64
Definition: utilities.hpp:230
Header & setStatusStr(winux::String const &statusStr)
状态文本. For a response: Not required
WebSocket封装
unsigned char uint8
Definition: utilities.hpp:220
winux::AnsiString requestHeaderStr
Definition: http_old.hpp:404
void appendString(XString< _ChTy > const &data)
添加数据:XString对象
Definition: utilities.hpp:1135
Buffer FileGetContentsEx(String const &filename, bool textMode)
载入文件内容为一个Buffer,textMode表示是否为文本模式
std::function< void(ClientCtxSharedPointer clientCtxPtr, WebSocketErrorCode ec) > ErrorHandlerFunction
Definition: http_old.hpp:424