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