1 // minihttp.cpp - All functionality required for a minimal TCP/HTTP client packed in one file. 2 // Released under the WTFPL (See minihttp.h) 3 4 #ifdef _MSC_VER 5 # ifndef _CRT_SECURE_NO_WARNINGS 6 # define _CRT_SECURE_NO_WARNINGS 7 # endif 8 # ifndef _CRT_SECURE_NO_DEPRECATE 9 # define _CRT_SECURE_NO_DEPRECATE 10 # endif 11 #endif 12 13 #ifdef WINRT 14 # include <winsock2.h> 15 # include <ws2tcpip.h> 16 #elif _WIN32 17 # ifndef _WIN32_WINNT 18 # define _WIN32_WINNT 0x0501 19 # endif 20 # include <winsock2.h> 21 # include <ws2tcpip.h> 22 #if !defined(EWOULDBLOCK) 23 # define EWOULDBLOCK WSAEWOULDBLOCK 24 #endif 25 #if !defined(ETIMEDOUT) 26 # define ETIMEDOUT WSAETIMEDOUT 27 #endif 28 #if !defined(ECONNRESET) 29 # define ECONNRESET WSAECONNRESET 30 #endif 31 #if !defined(ENOTCONN) 32 # define ENOTCONN WSAENOTCONN 33 #endif 34 # include <io.h> 35 #else 36 # include <sys/types.h> 37 # include <unistd.h> 38 # include <fcntl.h> 39 # include <sys/socket.h> 40 # include <netinet/in.h> 41 # include <netdb.h> 42 # define SOCKET_ERROR (-1) 43 # define INVALID_SOCKET (SOCKET)(~0) 44 typedef intptr_t SOCKET; 45 #endif 46 47 #include <stdio.h> 48 #include <stdlib.h> 49 #include <string.h> 50 #include <sstream> 51 #include <cctype> 52 #include <cerrno> 53 #include <algorithm> 54 #include <assert.h> 55 #include <iostream> 56 #include <string> 57 58 #ifdef MINIHTTP_USE_POLARSSL 59 # include "polarssl/net.h" 60 # include "polarssl/ssl.h" 61 # include "polarssl/entropy.h" 62 # include "polarssl/ctr_drbg.h" 63 #endif 64 65 #include "platform/HttpClient.h" 66 #include "platform/Log.h" 67 #include "Utils.h" 68 69 #define SOCKETVALID(s) ((s) != INVALID_SOCKET) 70 71 //#define _DEBUG 72 73 #ifdef _MSC_VER 74 # define STRNICMP _strnicmp 75 #else 76 # define STRNICMP strncasecmp 77 #endif 78 #ifdef _DEBUG 79 # define traceprint(...) {printf(__VA_ARGS__);} 80 #else 81 # define traceprint(...) {} 82 #endif 83 84 namespace OpenZWave 85 { 86 namespace Internal 87 { 88 namespace Platform 89 { 90 91 #ifdef MINIHTTP_USE_POLARSSL 92 // ------------------------ SSL STUFF ------------------------- HasSSL()93 bool HasSSL 94 ( 95 ) 96 { 97 return true; 98 } 99 100 struct SSLCtx 101 { SSLCtxOpenZWave::Internal::Platform::SSLCtx102 SSLCtx 103 ( 104 ): 105 _inited(0) 106 { 107 entropy_init(&entropy); 108 x509_crt_init(&cacert); 109 memset(&ssl, 0, sizeof(ssl_context)); 110 } ~SSLCtxOpenZWave::Internal::Platform::SSLCtx111 ~SSLCtx 112 ( 113 ) 114 { 115 entropy_free(&entropy); 116 x509_crt_free(&cacert); 117 ssl_free(&ssl); 118 if(_inited & 1) 119 ctr_drbg_free(&ctr_drbg); 120 if(_inited & 2) 121 ssl_free(&ssl); 122 } initOpenZWave::Internal::Platform::SSLCtx123 bool init 124 ( 125 ) 126 { 127 const char *pers = "minihttp"; 128 const size_t perslen = strlen(pers); 129 130 int err = ctr_drbg_init(&ctr_drbg, entropy_func, &entropy, (unsigned char *)pers, perslen); 131 if(err) 132 { 133 traceprint("SSLCtx::init(): ctr_drbg_init() returned %d\n", err); 134 return false; 135 } 136 _inited |= 1; 137 138 err = ssl_init(&ssl); 139 if(err) 140 { 141 traceprint("SSLCtx::init(): ssl_init() returned %d\n", err); 142 return false; 143 } 144 _inited |= 2; 145 146 return true; 147 } resetOpenZWave::Internal::Platform::SSLCtx148 void reset 149 ( 150 ) 151 { 152 ssl_session_reset(&ssl); 153 } 154 entropy_context entropy; 155 ctr_drbg_context ctr_drbg; 156 ssl_context ssl; 157 x509_crt cacert; 158 159 private: 160 unsigned _inited; 161 }; 162 163 // ------------------------------------------------------------ 164 #else // MINIHTTP_USE_POLARSSL 165 bool HasSSL() 166 { 167 return false; 168 } 169 #endif // MINIHTTP_USE_POLARSSL 170 171 #define DEFAULT_BUFSIZE 4096 172 _GetError()173 inline int _GetError() 174 { 175 #ifdef _WIN32 176 return WSAGetLastError(); 177 #else 178 return errno; 179 #endif 180 } 181 _GetErrorStr(int e)182 inline std::string _GetErrorStr(int e) 183 { 184 std::string ret; 185 #ifdef WINRT 186 LPTSTR s = (LPTSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 512); 187 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, e, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), s, 512, NULL ); 188 char buffer[1024]; 189 wcstombs(buffer, s, sizeof(buffer)); 190 HeapFree(GetProcessHeap(), 0, s); 191 ret = buffer; 192 #elif _WIN32 193 LPTSTR s; 194 ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, e, 0, (LPTSTR)&s, 0, NULL); 195 if(s) 196 ret = s; 197 ::LocalFree(s); 198 #else 199 const char *s = strerror(e); 200 if (s) 201 ret = s; 202 #endif 203 return ret; 204 } 205 InitNetwork()206 bool InitNetwork() 207 { 208 #ifdef _WIN32 209 WSADATA wsadata; 210 if(WSAStartup(MAKEWORD(2,2), &wsadata)) 211 { 212 traceprint("WSAStartup ERROR: %s", _GetErrorStr(_GetError()).c_str()); 213 return false; 214 } 215 #endif 216 return true; 217 } 218 StopNetwork()219 void StopNetwork() 220 { 221 #ifdef _WIN32 222 WSACleanup(); 223 #endif 224 } 225 _Resolve(const char * host,unsigned int port,struct sockaddr_in * addr)226 static bool _Resolve(const char *host, unsigned int port, struct sockaddr_in *addr) 227 { 228 char port_str[16]; 229 sprintf(port_str, "%u", port); 230 231 struct addrinfo hnt, *res = 0; 232 memset(&hnt, 0, sizeof(hnt)); 233 hnt.ai_family = AF_INET; 234 hnt.ai_socktype = SOCK_STREAM; 235 if (getaddrinfo(host, port_str, &hnt, &res)) 236 { 237 traceprint("RESOLVE ERROR: %s", _GetErrorStr(_GetError()).c_str()); 238 return false; 239 } 240 if (res) 241 { 242 if (res->ai_family != AF_INET) 243 { 244 traceprint("RESOLVE WTF: %s", _GetErrorStr(_GetError()).c_str()); 245 freeaddrinfo(res); 246 return false; 247 } 248 memcpy(addr, res->ai_addr, res->ai_addrlen); 249 freeaddrinfo(res); 250 return true; 251 } 252 return false; 253 } 254 255 // FIXME: this does currently not handle links like: 256 // http://example.com/index.html#pos 257 SplitURI(const std::string & uri,std::string & protocol,std::string & host,std::string & file,int & port,bool & useSSL)258 bool SplitURI(const std::string& uri, std::string& protocol, std::string& host, std::string& file, int& port, bool& useSSL) 259 { 260 const char *p = uri.c_str(); 261 const char *sl = strstr(p, "//"); 262 unsigned int offs = 0; 263 if (sl) 264 { 265 size_t colon = uri.find(':'); 266 size_t firstslash = uri.find('/'); 267 if (colon < firstslash) 268 protocol = uri.substr(0, colon); 269 if (strncmp(p, "http://", 7) == 0) 270 { 271 useSSL = false; 272 offs = 7; 273 } 274 else if (strncmp(p, "https://", 8) == 0) 275 { 276 useSSL = true; 277 offs = 8; 278 } 279 else 280 return false; 281 282 p = sl + 2; 283 } 284 285 sl = strchr(p, '/'); 286 if (!sl) 287 { 288 host = p; 289 file = "/"; 290 } 291 else 292 { 293 host = uri.substr(offs, sl - p); 294 file = sl; 295 } 296 297 port = -1; 298 size_t colon = host.find(':'); 299 if (colon != std::string::npos) 300 { 301 port = atoi(host.c_str() + colon); 302 host.erase(port); 303 } 304 305 return true; 306 } 307 URLEncode(const std::string & s,std::string & enc)308 void URLEncode(const std::string& s, std::string& enc) 309 { 310 const size_t len = s.length(); 311 char buf[3]; 312 buf[0] = '%'; 313 for (size_t i = 0; i < len; i++) 314 { 315 const unsigned char c = s[i]; 316 // from https://www.ietf.org/rfc/rfc1738.txt, page 3 317 // with some changes for compatibility 318 if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == ',') 319 enc += (char) c; 320 else if (c == ' ') 321 enc += '+'; 322 else 323 { 324 unsigned nib = (c >> 4) & 0xf; 325 buf[1] = nib < 10 ? '0' + nib : 'a' + (nib - 10); 326 nib = c & 0xf; 327 buf[2] = nib < 10 ? '0' + nib : 'a' + (nib - 10); 328 enc.append(&buf[0], 3); 329 } 330 } 331 } 332 _SetNonBlocking(SOCKET s,bool nonblock)333 static bool _SetNonBlocking(SOCKET s, bool nonblock) 334 { 335 if (!SOCKETVALID(s)) 336 return false; 337 #ifdef MINIHTTP_USE_POLARSSL 338 if(nonblock) 339 return net_set_nonblock(s) == 0; 340 else 341 return net_set_block(s) == 0; 342 #elif defined(_WIN32) 343 ULONG tmp = !!nonblock; 344 if(::ioctlsocket(s, FIONBIO, &tmp) == SOCKET_ERROR) 345 return false; 346 #else 347 int tmp = ::fcntl(s, F_GETFL); 348 if (tmp < 0) 349 return false; 350 if (::fcntl(s, F_SETFL, nonblock ? (tmp | O_NONBLOCK) : (tmp |= ~O_NONBLOCK)) < 0) 351 return false; 352 #endif 353 return true; 354 } 355 TcpSocket()356 TcpSocket::TcpSocket() : 357 _inbuf(NULL), _readptr(NULL), _writeptr(NULL), _inbufSize(0), _writeSize(0), _recvSize(0), _lastport(0), _nonblocking(false), _s(INVALID_SOCKET), _sslctx(NULL) 358 { 359 } 360 ~TcpSocket()361 TcpSocket::~TcpSocket() 362 { 363 close(); 364 if (_inbuf) 365 free(_inbuf); 366 } 367 isOpen()368 bool TcpSocket::isOpen() 369 { 370 return SOCKETVALID(_s); 371 } 372 close()373 void TcpSocket::close() 374 { 375 if (!SOCKETVALID(_s)) 376 return; 377 378 traceprint("TcpSocket::close\n"); 379 380 _OnCloseInternal(); 381 382 #ifdef MINIHTTP_USE_POLARSSL 383 if(_sslctx) 384 ((SSLCtx*)_sslctx)->reset(); 385 net_close(_s); 386 shutdownSSL(); 387 #else 388 # ifdef _WIN32 389 ::closesocket((SOCKET)_s); 390 # else 391 ::close(_s); 392 # endif 393 #endif 394 395 _s = INVALID_SOCKET; 396 _recvSize = 0; 397 } 398 _OnCloseInternal()399 void TcpSocket::_OnCloseInternal() 400 { 401 _OnClose(); 402 } 403 SetNonBlocking(bool nonblock)404 bool TcpSocket::SetNonBlocking(bool nonblock) 405 { 406 _nonblocking = nonblock; 407 return _SetNonBlocking(_s, nonblock); 408 } 409 SetBufsizeIn(unsigned int s)410 void TcpSocket::SetBufsizeIn(unsigned int s) 411 { 412 if (s < 512) 413 s = 512; 414 if (s != _inbufSize) 415 _inbuf = (char*) realloc(_inbuf, s); 416 _inbufSize = s; 417 _writeSize = s - 1; 418 _readptr = _writeptr = _inbuf; 419 } 420 _openSocket(SOCKET * ps,const char * host,unsigned port)421 static bool _openSocket(SOCKET *ps, const char *host, unsigned port) 422 { 423 #ifdef MINIHTTP_USE_POLARSSL 424 int s; 425 int err = net_connect(&s, host, port); 426 if(err) 427 { 428 traceprint("open_ssl: net_connect(%s, %u) returned %d\n", host, port, err); 429 return false; 430 } 431 #else 432 sockaddr_in addr; 433 if (!_Resolve(host, port, &addr)) 434 { 435 traceprint("RESOLV ERROR: %s\n", _GetErrorStr(_GetError()).c_str()); 436 return false; 437 } 438 439 SOCKET s = socket(AF_INET, SOCK_STREAM, 0); 440 441 if (!SOCKETVALID(s)) 442 { 443 traceprint("SOCKET ERROR: %s\n", _GetErrorStr(_GetError()).c_str()); 444 return false; 445 } 446 447 if (::connect(s, (sockaddr*) &addr, sizeof(sockaddr))) 448 { 449 traceprint("CONNECT ERROR: %s\n", _GetErrorStr(_GetError()).c_str()); 450 return false; 451 } 452 #endif 453 454 *ps = s; 455 return true; 456 } 457 458 #ifdef MINIHTTP_USE_POLARSSL traceprint_ssl(void * ctx,int level,const char * str)459 void traceprint_ssl 460 ( 461 void *ctx, 462 int level, 463 const char *str 464 ) 465 { 466 (void)ctx; 467 printf("ssl: [%d] %s\n", level, str); 468 } _openSSL(void * ps,SSLCtx * ctx)469 static bool _openSSL 470 ( 471 void *ps, 472 SSLCtx *ctx 473 ) 474 { 475 ssl_set_endpoint(&ctx->ssl, SSL_IS_CLIENT); 476 ssl_set_authmode(&ctx->ssl, SSL_VERIFY_OPTIONAL); 477 ssl_set_ca_chain(&ctx->ssl, &ctx->cacert, NULL, NULL); 478 479 /* SSLv3 is deprecated, set minimum to TLS 1.0 */ 480 ssl_set_min_version(&ctx->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1); 481 482 // The following is removed from newer polarssl versions 483 #ifdef SSL_ARC4_DISABLED 484 /* RC4 is deprecated, disable it */ 485 ssl_set_arc4_support(&ctx->ssl, SSL_ARC4_DISABLED ); 486 #endif 487 488 ssl_set_rng(&ctx->ssl, ctr_drbg_random, &ctx->ctr_drbg); 489 ssl_set_dbg(&ctx->ssl, traceprint_ssl, NULL); 490 //ssl_set_ciphersuites( &ctx->ssl, ssl_default_ciphersuites); // FIXME 491 ssl_set_bio(&ctx->ssl, net_recv, ps, net_send, ps); 492 493 traceprint("SSL handshake now...\n"); 494 int err; 495 while( (err = ssl_handshake(&ctx->ssl)) ) 496 { 497 if(err != POLARSSL_ERR_NET_WANT_READ && err != POLARSSL_ERR_NET_WANT_WRITE) 498 { 499 traceprint("open_ssl: ssl_handshake returned -0x%x\n\n", -err); 500 return false; 501 } 502 } 503 traceprint("SSL handshake done\n"); 504 return true; 505 } 506 #endif 507 open(const char * host,unsigned int port)508 bool TcpSocket::open(const char *host, unsigned int port) 509 { 510 if (isOpen()) 511 { 512 if ((host && host != _host) || (port && port != _lastport)) 513 close(); 514 // ... and continue connecting to new host/port 515 else 516 return true; // still connected, to same host and port. 517 } 518 519 if (host) 520 _host = host; 521 else 522 host = _host.c_str(); 523 524 if (port) 525 _lastport = port; 526 else 527 { 528 port = _lastport; 529 if (!port) 530 return false; 531 } 532 533 traceprint("TcpSocket::open(): host = [%s], port = %d\n", host, port); 534 535 assert(!SOCKETVALID(_s)); 536 537 _recvSize = 0; 538 539 { 540 SOCKET s; 541 if (!_openSocket(&s, host, port)) 542 return false; 543 _s = s; 544 545 #ifdef SO_NOSIGPIPE 546 // Don't fire SIGPIPE when trying to write to a closed socket 547 { 548 int set = 1; 549 setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, (void *) &set, sizeof(int)); 550 } 551 #endif 552 553 } 554 555 _SetNonBlocking(_s, _nonblocking); // restore setting if it was set in invalid state. static call because _s is intentionally still invalid here. 556 557 #ifdef MINIHTTP_USE_POLARSSL 558 if(_sslctx) 559 { 560 traceprint("TcpSocket::open(): SSL requested...\n"); 561 if(!_openSSL(&_s, (SSLCtx*)_sslctx)) 562 { 563 close(); 564 return false; 565 } 566 } 567 #endif 568 569 _OnOpen(); 570 571 return true; 572 } 573 574 #ifdef MINIHTTP_USE_POLARSSL shutdownSSL()575 void TcpSocket::shutdownSSL 576 ( 577 ) 578 { 579 delete ((SSLCtx*)_sslctx); 580 _sslctx = NULL; 581 } 582 initSSL(const char * certs)583 bool TcpSocket::initSSL 584 ( 585 const char *certs 586 ) 587 { 588 SSLCtx *ctx = (SSLCtx*)_sslctx; 589 if(ctx) 590 ctx->reset(); 591 else 592 { 593 ctx = new SSLCtx(); 594 _sslctx = ctx; 595 if(!ctx->init()) 596 { 597 shutdownSSL(); 598 return false; 599 } 600 } 601 602 if(certs) 603 { 604 int err = x509_crt_parse(&ctx->cacert, (const unsigned char*)certs, strlen(certs)); 605 if(err) 606 { 607 shutdownSSL(); 608 traceprint("x509_crt_parse() returned %d\n", err); 609 return false; 610 } 611 } 612 613 return true; 614 } 615 verifySSL()616 SSLResult TcpSocket::verifySSL 617 ( 618 ) 619 { 620 if(!_sslctx) 621 return SSLR_NO_SSL; 622 623 SSLCtx *ctx = (SSLCtx*)_sslctx; 624 unsigned r = SSLR_OK; 625 int res = ssl_get_verify_result(&ctx->ssl); 626 if(res) 627 { 628 if(res & BADCERT_EXPIRED) 629 r |= SSLR_CERT_EXPIRED; 630 631 if(res & BADCERT_REVOKED) 632 r |= SSLR_CERT_REVOKED; 633 634 if(res & BADCERT_CN_MISMATCH) 635 r |= SSLR_CERT_CN_MISMATCH; 636 637 if(res & BADCERT_NOT_TRUSTED) 638 r |= SSLR_CERT_NOT_TRUSTED; 639 640 if(res & BADCERT_MISSING) 641 r |= SSLR_CERT_MISSING; 642 643 if(res & BADCERT_SKIP_VERIFY) 644 r |= SSLR_CERT_SKIP_VERIFY; 645 646 if(res & BADCERT_FUTURE) 647 r |= SSLR_CERT_FUTURE; 648 649 // More than just this? 650 if(res & (BADCERT_SKIP_VERIFY | SSLR_CERT_NOT_TRUSTED)) 651 r |= SSLR_FAIL; 652 } 653 654 return (SSLResult)r; 655 } 656 #else // MINIHTTP_USE_POLARSSL shutdownSSL()657 void TcpSocket::shutdownSSL() 658 { 659 } 660 initSSL(const char * certs)661 bool TcpSocket::initSSL(const char *certs) 662 { 663 traceprint("initSSL: Compiled without SSL support!"); 664 return false; 665 } 666 verifySSL()667 SSLResult TcpSocket::verifySSL() 668 { 669 return SSLR_NO_SSL; 670 } 671 #endif 672 SendBytes(const void * str,unsigned int len)673 bool TcpSocket::SendBytes(const void *str, unsigned int len) 674 { 675 if (!len) 676 return true; 677 if (!SOCKETVALID(_s)) 678 return false; 679 //traceprint("SEND: '%s'\n", str); 680 681 unsigned written = 0; 682 while (true) // FIXME: buffer bytes to an internal queue instead? 683 { 684 int ret = _writeBytes((const unsigned char*) str + written, len - written); 685 if (ret > 0) 686 { 687 assert((unsigned )ret <= len); 688 written += (unsigned) ret; 689 if (written >= len) 690 break; 691 } 692 else if (ret < 0) 693 { 694 #ifdef _DEBUG 695 int err = ret == -1 ? _GetError() : ret; 696 traceprint("SendBytes: error %d: %s\n", err, _GetErrorStr(err).c_str()); 697 #endif 698 close(); 699 return false; 700 } 701 // and if ret == 0, keep trying. 702 } 703 704 assert(written == len); 705 return true; 706 } 707 _writeBytes(const unsigned char * buf,size_t len)708 int TcpSocket::_writeBytes(const unsigned char *buf, size_t len) 709 { 710 int ret = 0; 711 712 #ifdef MINIHTTP_USE_POLARSSL 713 int err; 714 if(_sslctx) 715 err = ssl_write(&((SSLCtx*)_sslctx)->ssl, buf, len); 716 else 717 err = net_send(&_s, buf, len); 718 719 switch(err) 720 { 721 case POLARSSL_ERR_NET_WANT_WRITE: 722 ret = 0; // FIXME: Nothing written, try later? 723 default: 724 ret = err; 725 } 726 #else 727 int flags = 0; 728 #ifdef MSG_NOSIGNAL 729 flags |= MSG_NOSIGNAL; 730 #endif 731 return ::send(_s, (const char*) buf, len, flags); 732 #endif 733 734 return ret; 735 } 736 _ShiftBuffer()737 void TcpSocket::_ShiftBuffer() 738 { 739 size_t by = _readptr - _inbuf; 740 memmove(_inbuf, _readptr, by); 741 _readptr = _inbuf; 742 _writeptr = _inbuf + by; 743 _writeSize = _inbufSize - by - 1; 744 } 745 _OnData()746 void TcpSocket::_OnData() 747 { 748 _OnRecv(_readptr, _recvSize); 749 } 750 _readBytes(unsigned char * buf,size_t maxlen)751 int TcpSocket::_readBytes(unsigned char *buf, size_t maxlen) 752 { 753 #ifdef MINIHTTP_USE_POLARSSL 754 if(_sslctx) 755 return ssl_read(&((SSLCtx*)_sslctx)->ssl, buf, maxlen); 756 else 757 return net_recv(&_s, buf, maxlen); 758 #else 759 return recv(_s, (char*) buf, maxlen, 0); // last char is used as string terminator 760 #endif 761 } 762 update()763 bool TcpSocket::update() 764 { 765 if (!_OnUpdate()) 766 return false; 767 768 if (!isOpen()) 769 return false; 770 771 if (!_inbuf) 772 SetBufsizeIn(DEFAULT_BUFSIZE); 773 774 int bytes = _readBytes((unsigned char*) _writeptr, _writeSize); 775 //traceprint("TcpSocket::update: _readBytes() result %d\n", bytes); 776 if (bytes > 0) // we received something 777 { 778 _inbuf[bytes] = 0; 779 _recvSize = bytes; 780 781 // reset pointers for next read 782 _writeSize = _inbufSize - 1; 783 _readptr = _writeptr = _inbuf; 784 785 _OnData(); 786 } 787 else if (bytes == 0) // remote has closed the connection 788 { 789 close(); 790 } 791 else // whoops, error? 792 { 793 // Possible that the error is returned directly (in that case, < -1, or -1 is returned and the error has to be retrieved seperately. 794 // But in the latter case, error numbers may be positive (at least on windows...) 795 int err = bytes == -1 ? _GetError() : bytes; 796 switch (err) 797 { 798 case EWOULDBLOCK: 799 #if defined(EAGAIN) && (EWOULDBLOCK != EAGAIN) 800 case EAGAIN: // linux man pages say this can also happen instead of EWOULDBLOCK 801 #endif 802 return false; 803 804 #ifdef MINIHTTP_USE_POLARSSL 805 case POLARSSL_ERR_NET_WANT_READ: 806 break; // Try again later 807 #endif 808 809 default: 810 traceprint("SOCKET UPDATE ERROR: (%d): %s\n", err, _GetErrorStr(err).c_str()) 811 ; 812 case ECONNRESET: 813 case ENOTCONN: 814 case ETIMEDOUT: 815 #ifdef _WIN32 816 case WSAECONNABORTED: 817 case WSAESHUTDOWN: 818 #endif 819 close(); 820 break; 821 } 822 } 823 return true; 824 } 825 826 // ========================== 827 // ===== HTTP SPECIFIC ====== 828 // ========================== 829 #ifdef MINIHTTP_SUPPORT_HTTP 830 add(const char * key,const char * value)831 POST& POST::add(const char *key, const char *value) 832 { 833 if (!empty()) 834 data += '&'; 835 URLEncode(key, data); 836 data += '='; 837 URLEncode(value, data); 838 return *this; 839 } 840 HttpSocket()841 HttpSocket::HttpSocket() : 842 TcpSocket(), _user_agent("OpenZWave"), _accept_encoding(), _tmpHdr(), _keep_alive(0), _remaining(0), _contentLen(0), _status(0), _inProgress(false), _chunkedTransfer(false), _mustClose(true), _followRedir(true), _alwaysHandle(false), _filename(), _pFile(NULL) 843 { 844 } 845 ~HttpSocket()846 HttpSocket::~HttpSocket() 847 { 848 } 849 _OnOpen()850 void HttpSocket::_OnOpen() 851 { 852 TcpSocket::_OnOpen(); 853 _chunkedTransfer = false; 854 _mustClose = true; 855 } 856 _OnCloseInternal()857 void HttpSocket::_OnCloseInternal() 858 { 859 if (!IsRedirecting() || _alwaysHandle) 860 _OnClose(); 861 } 862 _OnUpdate()863 bool HttpSocket::_OnUpdate() 864 { 865 if (!TcpSocket::_OnUpdate()) 866 return false; 867 868 if (_inProgress && !_chunkedTransfer && !_remaining && _status) 869 _FinishRequest(); 870 871 //traceprint("HttpSocket::_OnUpdate, Q = %d\n", (unsigned)_requestQ.size()); 872 873 // initiate transfer if queue is not empty, but the socket somehow forgot to proceed 874 if (_requestQ.size() && !_remaining && !_chunkedTransfer && !_inProgress) 875 _DequeueMore(); 876 877 return true; 878 } 879 Download(const std::string & url,const char * extraRequest,void * user,const POST * post)880 bool HttpSocket::Download(const std::string& url, const char *extraRequest, void *user, const POST *post) 881 { 882 if (_filename.length() == 0) 883 { 884 traceprint("No Filename Set\n"); 885 return false; 886 } 887 Request req; 888 req.user = user; 889 if (post) 890 req.post = *post; 891 SplitURI(url, req.protocol, req.host, req.resource, req.port, req.useSSL); 892 if (IsRedirecting() && req.host.empty()) // if we're following a redirection to the same host, the server is likely to omit its hostname 893 req.host = _curRequest.host; 894 if (req.port < 0) 895 req.port = req.useSSL ? 443 : 80; 896 if (extraRequest) 897 req.extraGetHeaders = extraRequest; 898 return SendRequest(req, false); 899 } 900 _Redirect(std::string loc,bool forceGET)901 bool HttpSocket::_Redirect(std::string loc, bool forceGET) 902 { 903 traceprint("Following HTTP redirect to: %s\n", loc.c_str()); 904 if (loc.empty()) 905 return false; 906 907 Request req; 908 req.user = _curRequest.user; 909 req.useSSL = _curRequest.useSSL; 910 if (!forceGET) 911 req.post = _curRequest.post; 912 SplitURI(loc, req.protocol, req.host, req.resource, req.port, req.useSSL); 913 if (req.protocol.empty()) // assume local resource 914 { 915 req.host = _curRequest.host; 916 req.resource = loc; 917 } 918 if (req.host.empty()) 919 req.host = _curRequest.host; 920 if (req.port < 0) 921 req.port = _curRequest.port; 922 req.extraGetHeaders = _curRequest.extraGetHeaders; 923 return SendRequest(req, false); 924 } 925 SendRequest(const std::string what,const char * extraRequest,void * user)926 bool HttpSocket::SendRequest(const std::string what, const char *extraRequest, void *user) 927 { 928 Request req(what, _host, _lastport, user); 929 if (extraRequest) 930 req.extraGetHeaders = extraRequest; 931 return SendRequest(req, false); 932 } 933 QueueRequest(const std::string what,const char * extraRequest,void * user)934 bool HttpSocket::QueueRequest(const std::string what, const char *extraRequest, void *user) 935 { 936 Request req(what, _host, _lastport, user); 937 if (extraRequest) 938 req.extraGetHeaders = extraRequest; 939 return SendRequest(req, true); 940 } 941 SendRequest(Request & req,bool enqueue)942 bool HttpSocket::SendRequest(Request& req, bool enqueue) 943 { 944 if (req.host.empty() || !req.port) 945 return false; 946 947 const bool post = !req.post.empty(); 948 949 std::stringstream r; 950 const char *crlf = "\r\n"; 951 r << (post ? "POST " : "GET ") << req.resource << " HTTP/1.1" << crlf; 952 r << "Host: " << req.host << crlf; 953 if (_keep_alive) 954 { 955 r << "Connection: Keep-Alive" << crlf; 956 r << "Keep-Alive: " << _keep_alive << crlf; 957 } 958 else 959 r << "Connection: close" << crlf; 960 961 if (_user_agent.length()) 962 r << "User-Agent: " << _user_agent << crlf; 963 964 if (_accept_encoding.length()) 965 r << "Accept-Encoding: " << _accept_encoding << crlf; 966 967 if (post) 968 { 969 r << "Content-Length: " << req.post.length() << crlf; 970 r << "Content-Type: application/x-www-form-urlencoded" << crlf; 971 } 972 973 if (req.extraGetHeaders.length()) 974 { 975 r << req.extraGetHeaders; 976 if (req.extraGetHeaders.compare(req.extraGetHeaders.length() - 2, std::string::npos, crlf)) 977 r << crlf; 978 } 979 980 r << crlf; // header terminator 981 982 // FIXME: appending this to the 'header' field is probably not a good idea 983 if (post) 984 r << req.post.str(); 985 986 req.header = r.str(); 987 988 return _EnqueueOrSend(req, enqueue); 989 } 990 _EnqueueOrSend(const Request & req,bool forceQueue)991 bool HttpSocket::_EnqueueOrSend(const Request& req, bool forceQueue) 992 { 993 traceprint("HttpSocket::_EnqueueOrSend, forceQueue = %d\n", forceQueue); 994 if (_inProgress || forceQueue) // do not send while receiving other data 995 { 996 traceprint("HTTP: Transfer pending; putting into queue. Now %u waiting.\n", (unsigned int)_requestQ.size()); 997 _requestQ.push(req); 998 return true; 999 } 1000 // ok, we can send directly 1001 traceprint("HTTP: Open request for immediate send.\n"); 1002 if (!_OpenRequest(req)) 1003 return false; 1004 bool sent = SendBytes(req.header.c_str(), req.header.length()); 1005 _inProgress = sent; 1006 return sent; 1007 } 1008 1009 // called whenever a request is finished completely and the socket checks for more things to send _DequeueMore()1010 void HttpSocket::_DequeueMore() 1011 { 1012 traceprint("HttpSocket::_DequeueMore, Q = %u\n", (unsigned)_requestQ.size()); 1013 _FinishRequest(); // In case this was not done yet. 1014 1015 // _inProgress is known to be false here 1016 if (_requestQ.size()) // still have other requests queued? 1017 if (_EnqueueOrSend(_requestQ.front(), false)) // could we send? 1018 _requestQ.pop(); // if so, we are done with this request 1019 1020 // otherwise, we are done for now. socket is kept alive for future sends. Nothing to do. 1021 } 1022 _OpenRequest(const Request & req)1023 bool HttpSocket::_OpenRequest(const Request& req) 1024 { 1025 if (_inProgress) 1026 { 1027 traceprint("HttpSocket::_OpenRequest(): _inProgress == true, should not be called."); 1028 return false; 1029 } 1030 if (req.useSSL && !hasSSL()) 1031 { 1032 traceprint("HttpSocket::_OpenRequest(): Is an SSL connection, but SSL was not inited, doing that now\n"); 1033 if (!initSSL(NULL)) // FIXME: supply cert list? 1034 { 1035 traceprint("FAILED to init SSL"); 1036 return false; 1037 } 1038 } 1039 if (!open(req.host.c_str(), req.port)) 1040 return false; 1041 _inProgress = true; 1042 _curRequest = req; 1043 _status = 0; 1044 return true; 1045 } 1046 _FinishRequest()1047 void HttpSocket::_FinishRequest() 1048 { 1049 traceprint("HttpSocket::_FinishRequest\n"); 1050 if (_inProgress) 1051 { 1052 traceprint("... in progress. redirecting = %d\n", IsRedirecting()); 1053 if (!IsRedirecting() || _alwaysHandle) 1054 _OnRequestDone(); // notify about finished request 1055 _inProgress = false; 1056 _hdrs.clear(); 1057 if (_mustClose) 1058 close(); 1059 } 1060 } 1061 _ProcessChunk()1062 void HttpSocket::_ProcessChunk() 1063 { 1064 if (!_chunkedTransfer) 1065 return; 1066 1067 unsigned int chunksize = -1; 1068 1069 while (true) 1070 { 1071 // less data required until chunk end than received, means the new chunk starts somewhere in the middle 1072 // of the received data block. finish this chunk first. 1073 if (_remaining) 1074 { 1075 if (_remaining <= _recvSize) // it contains the rest of the chunk, including CRLF 1076 { 1077 _OnRecvInternal(_readptr, _remaining - 2); // implicitly skip CRLF 1078 _readptr += _remaining; 1079 _recvSize -= _remaining; 1080 _remaining = 0; // done with this one. 1081 if (!chunksize) // and if chunksize was 0, we are done with all chunks. 1082 break; 1083 } 1084 else // buffer did not yet arrive completely 1085 { 1086 _OnRecvInternal(_readptr, _recvSize); 1087 _remaining -= _recvSize; 1088 _recvSize = 0; // done with the whole buffer, but not with the chunk 1089 return; // nothing else to do here 1090 } 1091 } 1092 1093 // each chunk identifier ends with CRLF. 1094 // if we don't find that, we hit the corner case that the chunk identifier was not fully received. 1095 // in that case, adjust the buffer and wait for the rest of the data to be appended 1096 char *term = strstr(_readptr, "\r\n"); 1097 if (!term) 1098 { 1099 if (_recvSize) // if there is still something queued, move it to the left of the buffer and append on next read 1100 _ShiftBuffer(); 1101 return; 1102 } 1103 term += 2; // skip CRLF 1104 1105 // when we are here, the (next) chunk header was completely received. 1106 chunksize = strtoul(_readptr, NULL, 16); 1107 _remaining = chunksize + 2; // the http protocol specifies that each chunk has a trailing CRLF 1108 _recvSize -= (term - _readptr); 1109 _readptr = term; 1110 } 1111 1112 if (!chunksize) // this was the last chunk, no further data expected unless requested 1113 { 1114 _chunkedTransfer = false; 1115 _DequeueMore(); 1116 if (_recvSize) 1117 traceprint("_ProcessChunk: There are %u bytes left in the buffer, huh?\n", _recvSize); 1118 if (_mustClose) 1119 close(); 1120 } 1121 } 1122 _ParseHeaderFields(const char * s,size_t size)1123 void HttpSocket::_ParseHeaderFields(const char *s, size_t size) 1124 { 1125 // Key: Value data\r\n 1126 1127 const char * const maxs = s + size; 1128 while (s < maxs) 1129 { 1130 while (isspace(*s)) 1131 { 1132 ++s; 1133 if (s >= maxs) 1134 return; 1135 } 1136 const char * const colon = strchr(s, ':'); 1137 if (!colon) 1138 return; 1139 const char *valEnd = strchr(colon, '\n'); // last char of val data 1140 if (!valEnd) 1141 return; 1142 while (valEnd[-1] == '\n' || valEnd[-1] == '\r') // skip backwards if necessary 1143 --valEnd; 1144 const char *val = colon + 1; // value starts after ':' ... 1145 while (isspace(*val) && val < valEnd) // skip spaces after the colon 1146 ++val; 1147 std::string key(s, colon - s); 1148 key = ToLower(key); 1149 std::string valstr(val, valEnd - val); 1150 _hdrs[key] = valstr; 1151 traceprint("HDR: %s: %s\n", key.c_str(), valstr.c_str()); 1152 s = valEnd; 1153 } 1154 } 1155 Hdr(const char * h) const1156 const char *HttpSocket::Hdr(const char *h) const 1157 { 1158 std::map<std::string, std::string>::const_iterator it = _hdrs.find(h); 1159 return it == _hdrs.end() ? NULL : it->second.c_str(); 1160 } 1161 safeatoi(const char * s)1162 static int safeatoi(const char *s) 1163 { 1164 return s ? atoi(s) : 0; 1165 } 1166 _HandleStatus()1167 bool HttpSocket::_HandleStatus() 1168 { 1169 _remaining = _contentLen = safeatoi(Hdr("content-length")); 1170 1171 const char *encoding = Hdr("transfer-encoding"); 1172 _chunkedTransfer = encoding && !STRNICMP(encoding, "chunked", 7); 1173 1174 const char *conn = Hdr("connection"); // if its not keep-alive, server will close it, so we can too 1175 _mustClose = !conn || STRNICMP(conn, "keep-alive", 10); 1176 1177 const bool success = IsSuccess(); 1178 1179 if (!(_chunkedTransfer || _contentLen) && success) 1180 traceprint("_ParseHeader: Not chunked transfer and content-length==0, this will go fail"); 1181 1182 traceprint("Got HTTP Status %d\n", _status); 1183 1184 if (success) 1185 return true; 1186 1187 bool forceGET = false; 1188 switch (_status) 1189 { 1190 case 303: 1191 forceGET = true; // As per spec, continue with a GET request 1192 case 301: 1193 case 302: 1194 case 307: 1195 case 308: 1196 if (_followRedir) 1197 if (const char *loc = Hdr("location")) 1198 _Redirect(loc, forceGET); 1199 return false; 1200 1201 default: 1202 return false; 1203 } 1204 } 1205 IsRedirecting() const1206 bool HttpSocket::IsRedirecting() const 1207 { 1208 switch (_status) 1209 { 1210 case 301: 1211 case 302: 1212 case 303: 1213 case 307: 1214 case 308: 1215 return true; 1216 } 1217 return false; 1218 } 1219 IsSuccess() const1220 bool HttpSocket::IsSuccess() const 1221 { 1222 const unsigned s = _status; 1223 return s >= 200 && s <= 205; 1224 } 1225 _ParseHeader()1226 void HttpSocket::_ParseHeader() 1227 { 1228 _tmpHdr += _inbuf; 1229 const char *hptr = _tmpHdr.c_str(); 1230 1231 if ((_recvSize >= 5 || _tmpHdr.size() >= 5) && memcmp("HTTP/", hptr, 5)) 1232 { 1233 traceprint("_ParseHeader: not HTTP stream\n"); 1234 return; 1235 } 1236 1237 const char *hdrend = strstr(hptr, "\r\n\r\n"); 1238 if (!hdrend) 1239 { 1240 traceprint("_ParseHeader: could not find end-of-header marker, or incomplete buf; delaying.\n"); 1241 return; 1242 } 1243 1244 //traceprint(hptr); 1245 1246 hptr = strchr(hptr + 5, ' '); // skip "HTTP/", already known 1247 if (!hptr) 1248 return; // WTF? 1249 ++hptr; // number behind first space is the status code 1250 _status = atoi(hptr); 1251 1252 // Default values 1253 _chunkedTransfer = false; 1254 _contentLen = 0; // yet unknown 1255 1256 hptr = strstr(hptr, "\r\n"); 1257 _ParseHeaderFields(hptr + 2, hdrend - hptr); 1258 1259 // FIXME: return value indicates success. 1260 // Bail out on non-success, or at least make it so that _OnRecv() is not called. 1261 // (Unless an override bool is given that even non-successful answers get their data delivered!) 1262 _HandleStatus(); 1263 1264 // get ready 1265 _readptr = strstr(_inbuf, "\r\n\r\n") + 4; // skip double newline. must have been found in hptr earlier. 1266 _recvSize -= (_readptr - _inbuf); // skip the header part 1267 _tmpHdr.clear(); 1268 } 1269 1270 // generic http header parsing _OnData()1271 void HttpSocket::_OnData() 1272 { 1273 if (!(_chunkedTransfer || (_remaining && _recvSize))) 1274 _ParseHeader(); 1275 1276 if (_chunkedTransfer) 1277 { 1278 _ProcessChunk(); // first, try to finish one or more chunks 1279 } 1280 else if (_remaining && _recvSize) // something remaining? if so, we got a header earlier, but not all data 1281 { 1282 _remaining -= _recvSize; 1283 _OnRecvInternal(_readptr, _recvSize); 1284 1285 if (int(_remaining) < 0) 1286 { 1287 traceprint("_OnRecv: _remaining wrap-around, huh??\n"); 1288 _remaining = 0; 1289 } 1290 if (!_remaining) // received last block? 1291 { 1292 if (_mustClose) 1293 close(); 1294 else 1295 _DequeueMore(); 1296 } 1297 1298 // nothing else to do here. 1299 } 1300 1301 // otherwise, the server sent just the header, with the data following in the next packet 1302 } 1303 _OnRecv(void * buf,unsigned int size)1304 void HttpSocket::_OnRecv(void *buf, unsigned int size) 1305 { 1306 if (!size) 1307 return; 1308 1309 if (!_pFile) 1310 { 1311 _pFile = fopen(_filename.c_str(), "w"); 1312 } 1313 if (!_pFile) 1314 { 1315 Log::Write(LogLevel_Error, "Failed to open file %s: %s", _filename.c_str(), strerror(errno)); 1316 return; 1317 } 1318 1319 fwrite(buf, size, 1, _pFile); 1320 } 1321 _OnClose()1322 void HttpSocket::_OnClose() 1323 { 1324 if (!ExpectMoreData()) 1325 _FinishRequest(); 1326 if (_pFile) 1327 { 1328 fclose(_pFile); 1329 _pFile = NULL; 1330 } 1331 } 1332 _OnRecvInternal(void * buf,unsigned int size)1333 void HttpSocket::_OnRecvInternal(void *buf, unsigned int size) 1334 { 1335 if (IsSuccess() || _alwaysHandle) 1336 _OnRecv(buf, size); 1337 } 1338 1339 #endif 1340 1341 // =========================== 1342 // ===== SOCKET SET ========== 1343 // =========================== 1344 #ifdef MINIHTTP_SUPPORT_SOCKET_SET 1345 ~SocketSet()1346 SocketSet::~SocketSet() 1347 { 1348 deleteAll(); 1349 } 1350 deleteAll()1351 void SocketSet::deleteAll() 1352 { 1353 for (Store::iterator it = _store.begin(); it != _store.end(); ++it) 1354 delete it->first; 1355 _store.clear(); 1356 } 1357 update()1358 bool SocketSet::update() 1359 { 1360 bool interesting = false; 1361 Store::iterator it = _store.begin(); 1362 for (; it != _store.end();) 1363 { 1364 TcpSocket *sock = it->first; 1365 SocketSetData& sdata = it->second; 1366 interesting = sock->update() || interesting; 1367 if (sdata.deleteWhenDone && !sock->isOpen() && !sock->HasPendingTask()) 1368 { 1369 traceprint("Delete socket\n"); 1370 delete sock; 1371 _store.erase(it++); 1372 } 1373 else 1374 ++it; 1375 } 1376 return interesting; 1377 } 1378 remove(TcpSocket * s)1379 void SocketSet::remove(TcpSocket *s) 1380 { 1381 _store.erase(s); 1382 } 1383 add(TcpSocket * s,bool deleteWhenDone)1384 void SocketSet::add(TcpSocket *s, bool deleteWhenDone) 1385 { 1386 s->SetNonBlocking(true); 1387 SocketSetData sdata; 1388 sdata.deleteWhenDone = deleteWhenDone; 1389 _store[s] = sdata; 1390 } 1391 1392 #endif 1393 } // namespace Platform 1394 } // namespace Internal 1395 } // namespace OpenZWave 1396