1 String WwwFormat(Time tm); 2 bool ScanWwwTime(const char *s, Time& tm); 3 Time ScanWwwTime(const char *s); 4 5 String MIMECharsetName(byte charset); 6 7 String UrlEncode(const char *s, const char *end); 8 String UrlEncode(const char *s, int len); 9 String UrlEncode(const String& s); 10 String UrlDecode(const char *s, const char *end); 11 String UrlDecode(const char *s, int len); 12 String UrlDecode(const String& s); 13 14 String QPEncode(const char* s); 15 String QPDecode(const char *s, bool undescore_to_space = false); 16 17 String Base64Encode(const char *s, const char *end); 18 String Base64Encode(const char *s, int len); 19 String Base64Encode(const String& data); 20 String Base64Decode(const char *s, const char *end); 21 String Base64Decode(const char *s, int len); 22 String Base64Decode(const String& data); 23 24 String DeHtml(const char *s); 25 26 void HMAC_SHA1(const byte *text, int text_len, const byte *key, int key_len, byte *digest); 27 String HMAC_SHA1(const String& text, const String& key); 28 String HMAC_SHA1_Hex(const String& text, const String& key); 29 30 const Index<String>& GetMIMETypes(); 31 String FileExtToMIME(const String& ext); 32 String MIMEToFileExt(const String& mime); 33 34 class IpAddrInfo { 35 enum { COUNT = 128 }; 36 struct Entry { 37 const char *host; 38 const char *port; 39 int family; 40 int status; 41 addrinfo *addr; 42 }; 43 static Entry pool[COUNT]; 44 45 enum { 46 EMPTY = 0, WORKING, CANCELED, RESOLVED, FAILED 47 }; 48 49 String host, port; 50 int family; 51 Entry *entry; 52 Entry exe[1]; 53 54 static void EnterPool(); 55 static void LeavePool(); 56 static auxthread_t auxthread__ Thread(void *ptr); 57 58 void Start(); 59 60 IpAddrInfo(const IpAddrInfo&); 61 62 public: 63 enum IpAddrFamily { 64 FAMILY_ANY = 0, FAMILY_IPV4, FAMILY_IPV6 65 }; 66 void Start(const String& host, int port, int family = FAMILY_ANY); 67 bool InProgress(); 68 bool Execute(const String& host, int port, int family = FAMILY_ANY); 69 addrinfo *GetResult() const; 70 void Clear(); 71 72 IpAddrInfo(); ~IpAddrInfo()73 ~IpAddrInfo() { Clear(); } 74 }; 75 76 struct SSLInfo { 77 String cipher; 78 bool cert_avail; 79 bool cert_verified; // Peer verification not yet working - this is always false 80 String cert_subject; 81 String cert_issuer; 82 Date cert_notbefore; 83 Date cert_notafter; 84 int cert_version; 85 String cert_serial; 86 }; 87 88 enum { WAIT_READ = 1, WAIT_WRITE = 2, WAIT_IS_EXCEPTION = 4 }; 89 90 class TcpSocket : NoCopy { 91 enum { BUFFERSIZE = 512 }; 92 enum { NONE, CONNECT, ACCEPT, SSL_CONNECTED }; 93 SOCKET socket; 94 int mode; 95 char buffer[BUFFERSIZE]; 96 char *ptr; 97 char *end; 98 bool is_eof; 99 bool is_error; 100 bool is_timeout; 101 bool is_abort; 102 bool ipv6; 103 104 int timeout; 105 int waitstep; 106 int done; 107 108 int global_timeout; 109 int start_time; 110 #if defined(PLATFORM_WIN32) || defined(PLATFORM_BSD) 111 int connection_start; 112 #endif 113 int ssl_start; 114 115 int errorcode; 116 String errordesc; 117 118 struct SSL { 119 virtual bool Start() = 0; 120 virtual bool Wait(dword flags, int end_time) = 0; 121 virtual int Send(const void *buffer, int maxlen) = 0; 122 virtual int Recv(void *buffer, int maxlen) = 0; 123 virtual void Close() = 0; 124 virtual dword Handshake() = 0; 125 ~SSLSSL126 virtual ~SSL() {} 127 }; 128 129 One<SSL> ssl; 130 One<SSLInfo> sslinfo; 131 String cert, pkey, sni; 132 bool asn1; 133 134 struct SSLImp; 135 friend struct SSLImp; 136 137 static SSL *(*CreateSSL)(TcpSocket& socket); 138 static SSL *CreateSSLImp(TcpSocket& socket); 139 140 friend void InitCreateSSL(); 141 friend class IpAddrInfo; 142 143 int GetEndTime() const; 144 bool RawWait(dword flags, int end_time); 145 bool Wait(dword events, int end_time); 146 SOCKET AcceptRaw(dword *ipaddr, int timeout_msec); 147 bool SetupSocket(); 148 bool Open(int family, int type, int protocol); 149 int RawRecv(void *buffer, int maxlen); 150 int Recv(void *buffer, int maxlen); 151 int RawSend(const void *buffer, int maxlen); 152 int Send(const void *buffer, int maxlen); 153 bool RawConnect(addrinfo *arp); 154 void RawClose(); 155 156 void ReadBuffer(int end_time); 157 int Get_(); 158 int Peek_(); 159 int Peek_(int end_time); Peek(int end_time)160 int Peek(int end_time) { return ptr < end ? (byte)*ptr : Peek_(end_time); } 161 bool IsGlobalTimeout(); 162 163 void Reset(); 164 165 void SetSockError(const char *context, const char *errdesc); 166 void SetSockError(const char *context); 167 168 bool WouldBlock(); 169 170 static int GetErrorCode(); 171 static void Init(); 172 173 TcpSocket(const TcpSocket&); 174 175 public: 176 Event<> WhenWait; 177 178 void SetSockError(const char *context, int code, const char *errdesc); 179 180 enum { ERROR_GLOBAL_TIMEOUT = -1000000, ERROR_SSLHANDSHAKE_TIMEOUT, ERROR_LAST }; 181 182 static String GetHostName(); 183 GetDone()184 int GetDone() const { return done; } 185 IsOpen()186 bool IsOpen() const { return socket != INVALID_SOCKET; } 187 bool IsEof() const; 188 IsError()189 bool IsError() const { return is_error; } ClearError()190 void ClearError() { is_error = false; errorcode = 0; errordesc.Clear(); } GetError()191 int GetError() const { return errorcode; } GetErrorDesc()192 String GetErrorDesc() const { return errordesc; } 193 Abort()194 void Abort() { is_abort = true; } IsAbort()195 bool IsAbort() const { return is_abort; } ClearAbort()196 void ClearAbort() { is_abort = false; } 197 IsTimeout()198 bool IsTimeout() const { return is_timeout; } 199 GetSOCKET()200 SOCKET GetSOCKET() const { return socket; } 201 String GetPeerAddr() const; 202 203 void Attach(SOCKET socket); 204 bool Connect(const char *host, int port); 205 bool Connect(IpAddrInfo& info); 206 bool WaitConnect(); 207 bool Listen(int port, int listen_count = 5, bool ipv6 = false, bool reuse = true, void* addr = NULL); 208 bool Listen(const IpAddrInfo& addr, int port, int listen_count = 5, bool ipv6 = false, bool reuse = true); 209 bool Accept(TcpSocket& listen_socket); 210 void Close(); 211 void Shutdown(); 212 213 void NoDelay(); 214 void Linger(int msecs); NoLinger()215 void NoLinger() { Linger(Null); } 216 217 bool Wait(dword events); WaitRead()218 bool WaitRead() { return Wait(WAIT_READ); } WaitWrite()219 bool WaitWrite() { return Wait(WAIT_WRITE); } 220 Peek()221 int Peek() { return ptr < end ? (byte)*ptr : Peek_(); } Term()222 int Term() { return Peek(); } Get()223 int Get() { return ptr < end ? (byte)*ptr++ : Get_(); } 224 int Get(void *buffer, int len); 225 String Get(int len); 226 227 int Put(const void *s, int len); Put(const String & s)228 int Put(const String& s) { return Put(s.Begin(), s.GetLength()); } 229 230 bool GetAll(void *buffer, int len); 231 String GetAll(int len); 232 String GetLine(int maxlen = 65536); 233 234 bool PutAll(const void *s, int len); 235 bool PutAll(const String& s); 236 237 bool StartSSL(); IsSSL()238 bool IsSSL() const { return ssl; } 239 dword SSLHandshake(); 240 void SSLCertificate(const String& cert, const String& pkey, bool asn1); 241 void SSLServerNameIndication(const String& name); GetSSLInfo()242 const SSLInfo *GetSSLInfo() const { return ~sslinfo; } 243 244 void Clear(); 245 Timeout(int ms)246 TcpSocket& Timeout(int ms) { timeout = ms; return *this; } GetTimeout()247 int GetTimeout() const { return timeout; } 248 TcpSocket& GlobalTimeout(int ms); NoGlobalTimeout()249 TcpSocket& NoGlobalTimeout() { return GlobalTimeout(Null); } Blocking()250 TcpSocket& Blocking() { return Timeout(Null); } IsBlocking()251 bool IsBlocking() { return IsNull(GetTimeout()); } WaitStep(int ms)252 TcpSocket& WaitStep(int ms) { waitstep = ms; return *this; } GetWaitStep()253 int GetWaitStep() const { return waitstep; } 254 255 TcpSocket(); ~TcpSocket()256 ~TcpSocket() { Close(); } 257 }; 258 259 class SocketWaitEvent { 260 Vector<Tuple<int, dword>> socket; 261 fd_set read[1], write[1], exception[1]; 262 SocketWaitEvent(const SocketWaitEvent &); 263 264 public: Clear()265 void Clear() { socket.Clear(); } Add(SOCKET s,dword events)266 void Add(SOCKET s, dword events) { socket.Add(MakeTuple((int)s, events)); } Add(TcpSocket & s,dword events)267 void Add(TcpSocket& s, dword events) { Add(s.GetSOCKET(), events); } 268 int Wait(int timeout); 269 dword Get(int i) const; 270 dword operator[](int i) const { return Get(i); } 271 272 SocketWaitEvent(); 273 }; 274 275 struct UrlInfo { 276 String url; 277 278 String scheme; 279 String host; 280 String port; 281 String username; 282 String password; 283 String path; 284 String query; 285 String fragment; 286 287 VectorMap<String, String> parameters; 288 VectorMap<String, Vector<String>> array_parameters; 289 ClearUrlInfo290 void Clear() { *this = UrlInfo(); } 291 void Parse(const String& url); 292 293 String operator[](const char *id) const; 294 const Vector<String>& GetArray(const char *id) const; 295 UrlInfoUrlInfo296 UrlInfo() {} UrlInfoUrlInfo297 UrlInfo(const String& url) { Parse(url); } 298 }; 299 300 struct HttpCookie : Moveable<HttpCookie> { 301 String id; 302 String value; 303 String domain; 304 String path; 305 String raw; 306 307 void Clear(); 308 bool Parse(const String& cookie); 309 }; 310 311 struct HttpHeader { 312 String first_line; 313 String f1, f2, f3; 314 VectorMap<String, String> fields; 315 VectorMap<String, HttpCookie> cookies; 316 bool scgi; 317 318 String operator[](const char *id) const { return fields.Get(id, Null); } 319 String GetCookie(const char *id) const; 320 321 bool Response(String& protocol, int& code, String& reason) const; 322 bool Request(String& method, String& uri, String& version) const; 323 GetProtocolHttpHeader324 String GetProtocol() const { return f1; } 325 int GetCode() const; GetReasonHttpHeader326 String GetReason() const { return f3; } 327 GetMethodHttpHeader328 String GetMethod() const { return f1; } GetURIHttpHeader329 String GetURI() const { return f2; } GetVersionHttpHeader330 String GetVersion() const { return f3; } 331 332 bool HasContentLength() const; 333 int64 GetContentLength() const; 334 335 void Clear(); 336 bool ParseAdd(const String& hdrs); 337 bool Parse(const String& hdrs); 338 bool ParseSCGI(const String& scgi_hdr); 339 340 bool Read(TcpSocket& socket); 341 HttpHeaderHttpHeader342 HttpHeader() { scgi = false; } 343 344 private: 345 void Add(const String& id, const String& value); 346 HttpHeader(const HttpHeader&); 347 }; 348 349 class HttpRequest : public TcpSocket { 350 int phase; 351 dword waitevents; 352 String data; 353 int64 count; 354 355 HttpHeader header; 356 357 String error; 358 String body; 359 int64 content_length; 360 bool has_content_length; 361 bool chunked_encoding; 362 363 enum { 364 DEFAULT_HTTP_PORT = 80, 365 DEFAULT_HTTPS_PORT = 443 366 }; 367 368 int max_header_size; 369 int max_content_size; 370 int max_redirects; 371 int max_retries; 372 int timeout; 373 374 String host; 375 int port; 376 String proxy_host; 377 int proxy_port; 378 String proxy_username; 379 String proxy_password; 380 String ssl_proxy_host; 381 int ssl_proxy_port; 382 String ssl_proxy_username; 383 String ssl_proxy_password; 384 String path; 385 String phost; 386 bool ssl; 387 bool ssl_get_proxy; 388 389 int method; 390 String custom_method; 391 String accept; 392 String agent; 393 bool force_digest; 394 bool is_post; 395 bool std_headers; 396 bool hasurlvar; 397 bool keep_alive; 398 bool all_content; 399 String contenttype; 400 String username; 401 String password; 402 String authorization; 403 String request_headers; 404 String postdata; 405 String multipart; 406 VectorMap<String, HttpCookie> cookies; 407 408 String protocol; 409 int status_code; 410 String reason_phrase; 411 412 int start_time; 413 int retry_count; 414 int redirect_count; 415 416 int chunk; 417 418 IpAddrInfo addrinfo; 419 bool gzip; 420 Zlib z; 421 422 Stream *poststream; 423 int64 postlen; 424 425 String chunk_crlf; 426 427 void Init(); 428 429 void StartPhase(int s); 430 void Start(); 431 void Dns(); 432 void StartConnect(); 433 void ProcessSSLProxyResponse(); 434 void AfterConnect(); 435 void StartRequest(); 436 bool SendingData(bool request = false); 437 438 bool ReadingHeader(); 439 bool ReadingTrailer(); 440 void StartBody(); 441 bool ReadingBody(); 442 void ReadingChunkHeader(); 443 void Finish(); 444 bool IsRequestTimeout(); 445 void CopyCookies(); 446 447 void HttpError(const char *s); 448 void Out(const void *ptr, int size); 449 450 String CalculateDigest(const String& authenticate) const; 451 452 public: 453 enum { 454 METHOD_GET = 0, 455 METHOD_POST = 1, 456 METHOD_HEAD = 2, 457 METHOD_PUT = 3, 458 METHOD_DELETE = 4, 459 METHOD_TRACE = 5, 460 METHOD_OPTIONS = 6, 461 METHOD_CONNECT = 7, 462 METHOD_PATCH = 8, 463 }; 464 465 Event<const void *, int> WhenContent; 466 Event<> WhenStart; 467 Event<> WhenDo; 468 Gate<> WhenAuthenticate; 469 MaxHeaderSize(int m)470 HttpRequest& MaxHeaderSize(int m) { max_header_size = m; return *this; } MaxContentSize(int m)471 HttpRequest& MaxContentSize(int m) { max_content_size = m; return *this; } MaxRedirect(int n)472 HttpRequest& MaxRedirect(int n) { max_redirects = n; return *this; } MaxRetries(int n)473 HttpRequest& MaxRetries(int n) { max_retries = n; return *this; } RequestTimeout(int ms)474 HttpRequest& RequestTimeout(int ms) { timeout = ms; return *this; } ChunkSize(int n)475 HttpRequest& ChunkSize(int n) { chunk = n; return *this; } 476 HttpRequest& AllContent(bool b = true) { all_content = b; return *this; } 477 478 HttpRequest& Method(int m, const char *custom_name = NULL); GET()479 HttpRequest& GET() { return Method(METHOD_GET); } POST()480 HttpRequest& POST() { return Method(METHOD_POST); } HEAD()481 HttpRequest& HEAD() { return Method(METHOD_HEAD); } PUT()482 HttpRequest& PUT() { return Method(METHOD_PUT); } DEL()483 HttpRequest& DEL() { return Method(METHOD_DELETE); } TRACE()484 HttpRequest& TRACE() { return Method(METHOD_TRACE); } OPTIONS()485 HttpRequest& OPTIONS() { return Method(METHOD_OPTIONS); } CONNECT()486 HttpRequest& CONNECT() { return Method(METHOD_CONNECT); } PATCH()487 HttpRequest& PATCH() { return Method(METHOD_PATCH); } 488 Host(const String & h)489 HttpRequest& Host(const String& h) { host = h; return *this; } Port(int p)490 HttpRequest& Port(int p) { port = p; return *this; } 491 HttpRequest& SSL(bool b = true) { ssl = b; return *this; } Path(const String & p)492 HttpRequest& Path(const String& p) { path = p; return *this; } Authorization(const String & h)493 HttpRequest& Authorization(const String& h) { authorization = h; return *this; } User(const String & u,const String & p)494 HttpRequest& User(const String& u, const String& p) { username = u; password = p; return *this; } Digest()495 HttpRequest& Digest() { force_digest = true; return *this; } Digest(const String & u,const String & p)496 HttpRequest& Digest(const String& u, const String& p) { User(u, p); return Digest(); } SetDigest(const String & d)497 HttpRequest& SetDigest(const String& d) { return Authorization("Digest " + d); } 498 HttpRequest& Url(const char *url); 499 HttpRequest& UrlVar(const char *id, const String& data); operator()500 HttpRequest& operator()(const char *id, const String& data) { return UrlVar(id, data); } PostData(const String & pd)501 HttpRequest& PostData(const String& pd) { postdata = pd; poststream = NULL; return *this; } 502 HttpRequest& PostStream(Stream& s, int64 len = Null); 503 504 bool ResolveDigestAuthentication(); 505 PostUData(const String & pd)506 HttpRequest& PostUData(const String& pd) { return PostData(UrlEncode(pd)); } Post(const String & data)507 HttpRequest& Post(const String& data) { POST(); return PostData(data); } 508 HttpRequest& Post(const char *id, const String& data); 509 HttpRequest& Part(const char *id, const String& data, 510 const char *content_type = NULL, const char *filename = NULL); 511 ClearPost()512 HttpRequest& ClearPost() { PostData(Null); poststream = NULL; ; multipart.Clear(); GET(); return *this; } 513 Headers(const String & h)514 HttpRequest& Headers(const String& h) { request_headers = h; return *this; } ClearHeaders()515 HttpRequest& ClearHeaders() { return Headers(Null); } AddHeaders(const String & h)516 HttpRequest& AddHeaders(const String& h) { request_headers.Cat(h); return *this; } 517 HttpRequest& Header(const char *id, const String& data); 518 519 HttpRequest& Cookie(const HttpCookie& c); 520 HttpRequest& Cookie(const String& id, const String& value, 521 const String& domain = Null, const String& path = Null); 522 HttpRequest& CopyCookies(const HttpRequest& r); ClearCookies()523 HttpRequest& ClearCookies() { cookies.Clear(); return *this; } 524 StdHeaders(bool sh)525 HttpRequest& StdHeaders(bool sh) { std_headers = sh; return *this; } NoStdHeaders()526 HttpRequest& NoStdHeaders() { return StdHeaders(false); } Accept(const String & a)527 HttpRequest& Accept(const String& a) { accept = a; return *this; } UserAgent(const String & a)528 HttpRequest& UserAgent(const String& a) { agent = a; return *this; } ContentType(const String & a)529 HttpRequest& ContentType(const String& a) { contenttype = a; return *this; } 530 HttpRequest& KeepAlive(bool ka = true) { keep_alive = ka; return *this;} 531 Proxy(const String & host,int port)532 HttpRequest& Proxy(const String& host, int port) { proxy_host = host; proxy_port = port; return *this; } 533 HttpRequest& Proxy(const char *p); ProxyAuth(const String & u,const String & p)534 HttpRequest& ProxyAuth(const String& u, const String& p) { proxy_username = u; proxy_password = p; return *this; } 535 SSLProxy(const String & host,int port)536 HttpRequest& SSLProxy(const String& host, int port) { ssl_proxy_host = host; ssl_proxy_port = port; return *this; } 537 HttpRequest& SSLProxy(const char *p); SSLProxyAuth(const String & u,const String & p)538 HttpRequest& SSLProxyAuth(const String& u, const String& p) { ssl_proxy_username = u; ssl_proxy_password = p; return *this; } 539 HttpRequest& SSLProxyGET(bool b = true) { ssl_get_proxy = b; return *this; } 540 CommonProxy(const String & host,int port)541 HttpRequest& CommonProxy(const String& host, int port) { Proxy(host, port); return SSLProxy(host, port); } CommonProxy(const char * p)542 HttpRequest& CommonProxy(const char *p) { Proxy(p); return SSLProxy(p); } CommonProxyAuth(const String & u,const String & p)543 HttpRequest& CommonProxyAuth(const String& u, const String& p) { ProxyAuth(u, p); return SSLProxyAuth(u, p); } 544 IsSocketError()545 bool IsSocketError() const { return TcpSocket::IsError(); } IsHttpError()546 bool IsHttpError() const { return !IsNull(error) ; } IsError()547 bool IsError() const { return IsSocketError() || IsHttpError(); } GetErrorDesc()548 String GetErrorDesc() const { return IsSocketError() ? TcpSocket::GetErrorDesc() : error; } ClearError()549 void ClearError() { TcpSocket::ClearError(); error.Clear(); } 550 GetHeader(const char * id)551 String GetHeader(const char *id) { return header[id]; } 552 String operator[](const char *id) { return GetHeader(id); } 553 String GetRedirectUrl(); 554 bool HasContentLength(); 555 int64 GetContentLength(); GetStatusCode()556 int GetStatusCode() const { return status_code; } GetReasonPhrase()557 String GetReasonPhrase() const { return reason_phrase; } 558 GetHttpHeader()559 const HttpHeader& GetHttpHeader() const { return header; } GetCookie(const char * id)560 String GetCookie(const char *id) { return header.GetCookie(id); } 561 GetContent()562 String GetContent() const { return body; } 563 String operator~() const { return GetContent(); } String()564 operator String() const { return GetContent(); } ClearContent()565 void ClearContent() { body.Clear(); } 566 567 enum Phase { 568 BEGIN, START, DNS, 569 SSLPROXYREQUEST, SSLPROXYRESPONSE, SSLHANDSHAKE, 570 REQUEST, HEADER, BODY, 571 CHUNK_HEADER, CHUNK_BODY, CHUNK_CRLF, TRAILER, 572 FINISHED, FAILED, 573 }; 574 575 bool Do(); GetWaitEvents()576 dword GetWaitEvents() { return waitevents; } GetPhase()577 int GetPhase() const { return phase; } 578 String GetPhaseName() const; InProgress()579 bool InProgress() const { return phase != FAILED && phase != FINISHED; } IsFailure()580 bool IsFailure() const { return phase == FAILED; } IsSuccess()581 bool IsSuccess() const { return phase == FINISHED && status_code >= 200 && status_code < 300; } 582 583 String Execute(); 584 585 void New(); 586 void NewRequest(); 587 void Clear(); 588 589 HttpRequest(); 590 HttpRequest(const char *url); 591 592 static void Trace(bool b = true); 593 static void TraceHeader(bool b = true); 594 static void TraceBody(bool b = true); 595 static void TraceShort(bool b = true); 596 }; 597 598 bool HttpResponse(TcpSocket& socket, bool scgi, int code, const char *phrase, 599 const char *content_type = NULL, const String& data = Null, 600 const char *server = NULL, bool gzip = false); 601 602 #include <Core/Core.h> 603 604 class WebSocket { 605 String error; 606 607 TcpSocket std_socket; 608 TcpSocket *socket; 609 610 String uri; 611 String host; 612 IpAddrInfo addrinfo; 613 bool ssl; 614 String request_headers; 615 616 String data; 617 int data_pos; 618 619 int opcode; 620 int64 length; 621 bool mask; 622 int key[4]; 623 624 struct Input : Moveable<Input> { 625 dword opcode; 626 String data; 627 }; 628 629 BiVector<Input> in_queue; 630 631 BiVector<String> out_queue; 632 int out_at; 633 634 bool close_sent; 635 bool close_received; 636 637 dword current_opcode; 638 639 bool client; 640 641 enum { 642 HTTP_REQUEST_HEADER = -100, 643 HTTP_RESPONSE_HEADER = -101, 644 READING_FRAME_HEADER = -102, 645 DNS = -103, 646 SSL_HANDSHAKE = -104, 647 648 FIN = 0x80, 649 TEXT = 0x1, 650 BINARY = 0x2, 651 CLOSE = 0x8, 652 PING = 0x9, 653 PONG = 0xa, 654 655 MASK = 0x80, 656 }; 657 658 void Clear(); 659 void Error(const String& error); 660 661 void Out(const String& s); 662 663 void Output(); 664 665 void StartConnect(); 666 void Dns(); 667 void SSLHandshake(); 668 void SendRequest(); 669 bool ReadHttpHeader(); 670 void ResponseHeader(); 671 void RequestHeader(); 672 void FrameHeader(); 673 void FrameData(); 674 675 int GetFinIndex() const; 676 677 void SendRaw(int hdr, const String& data, dword mask = 0); 678 void Do0(); 679 680 static String FormatBlock(const String& s); 681 682 public: 683 WebSocket& NonBlocking(bool b = true) { socket->Timeout(b ? 0 : Null); return *this; } 684 Headers(const String & h)685 WebSocket& Headers(const String& h) { request_headers = h; return *this; } ClearHeaders()686 WebSocket& ClearHeaders() { return Headers(Null); } AddHeaders(const String & h)687 WebSocket& AddHeaders(const String& h) { request_headers.Cat(h); return *this; } 688 WebSocket& Header(const char *id, const String& data); 689 GetHeaders()690 String GetHeaders() { return request_headers; } 691 IsBlocking()692 bool IsBlocking() const { return IsNull(socket->GetTimeout()); } 693 IsError()694 bool IsError() const { return socket->IsError() || error.GetCount(); } GetError()695 String GetError() const { return Nvl(socket->GetErrorDesc(), error); } 696 697 bool Accept(TcpSocket& listener_socket); 698 bool Connect(const String& uri, const String& host, bool ssl, int port); Connect(const String & uri,const String & host,bool ssl)699 bool Connect(const String& uri, const String& host, bool ssl) { return Connect(uri, host, ssl, ssl ? 440 : 80); } 700 bool Connect(const String& url); 701 702 void Do(); 703 704 String Receive(); IsFin()705 bool IsFin() const { return current_opcode & FIN; } IsText()706 bool IsText() const { return current_opcode & TEXT; } IsBinary()707 bool IsBinary() const { return current_opcode & BINARY; } 708 SendText(const String & data)709 void SendText(const String& data) { SendRaw(FIN|TEXT, data); } SendTextMasked(const String & data)710 void SendTextMasked(const String& data) { SendRaw(FIN|TEXT, data, MASK); } SendBinary(const String & data)711 void SendBinary(const String& data) { SendRaw(FIN|BINARY, data); } Ping(const String & data)712 void Ping(const String& data) { SendRaw(FIN|PING, data); } 713 BeginText(const String & data)714 void BeginText(const String& data) { SendRaw(TEXT, data); } BeginBinary(const String & data)715 void BeginBinary(const String& data) { SendRaw(BINARY, data); } Continue(const String & data)716 void Continue(const String& data) { SendRaw(0, data); } Fin(const String & data)717 void Fin(const String& data) { SendRaw(FIN, data); } 718 719 void Close(const String& msg = Null, bool wait_reply = false); IsOpen()720 bool IsOpen() const { return socket->IsOpen(); } IsClosed()721 bool IsClosed() const { return !IsOpen(); } 722 GetWaitEvents()723 dword GetWaitEvents() const { return WAIT_READ|(!!out_queue.GetCount() * WAIT_WRITE); } GetSOCKET()724 SOCKET GetSOCKET() const { return socket ? socket->GetSOCKET() : INVALID_SOCKET; } GetPeerAddr()725 String GetPeerAddr() const { return socket ? socket->GetPeerAddr() : ""; } AddTo(SocketWaitEvent & e)726 void AddTo(SocketWaitEvent& e) { e.Add(*socket, GetWaitEvents()); } 727 728 static void Trace(bool b = true); 729 730 WebSocket(); 731 732 // backward compatibility: 733 bool WebAccept(TcpSocket& socket, HttpHeader& hdr); 734 bool WebAccept(TcpSocket& socket); 735 GetOpCode()736 int GetOpCode() const { return current_opcode & 15; } 737 SendText(const String & data,bool fin)738 bool SendText(const String& data, bool fin) { SendRaw((fin ? 0x80 : 0)|TEXT, data); return !IsError(); } 739 bool SendText(const void *data, int len, bool fin = true) { return SendText(String((char *)data, len), fin); } 740 SendBinary(const String & data,bool fin)741 bool SendBinary(const String& data, bool fin) { SendRaw((fin ? 0x80 : 0)|BINARY, data); return !IsError(); } 742 bool SendBinary(const void *data, int len, bool fin = true) { return SendText(String((char *)data, len), fin); } 743 GetErrorDesc()744 String GetErrorDesc() const { return GetError(); } 745 746 // keep mispeled method names Recieve()747 String Recieve() { return Receive(); } 748 }; 749 750 void ParseProxyUrl(const char *p, String& proxy_host, int& proxy_port); 751