CMSDK 2.0.1
Cross-platform C++ base library and SDK for the Psyclone AIOS platform
Loading...
Searching...
No Matches
NetworkConnections.cpp
Go to the documentation of this file.
1
9#ifndef WINDOWS
10 #include <arpa/inet.h>
11#endif // WINDOWS
12#if defined(_USE_SSL_) && defined(WINDOWS)
13 // CryptoAPI: used to import the Windows ROOT certificate store into
14 // OpenSSL's X509_STORE (OpenSSL's default verify paths point at the
15 // build-time OPENSSLDIR, which does not exist on end-user machines).
16 #include <wincrypt.h>
17 // wincrypt.h defines macros that collide with OpenSSL type names.
18 #undef X509_NAME
19 #undef X509_EXTENSIONS
20 #undef X509_CERT_PAIR
21 #undef PKCS7_SIGNER_INFO
22 #undef OCSP_REQUEST
23 #undef OCSP_RESPONSE
24#endif // _USE_SSL_ && WINDOWS
25
26namespace cmlabs{
27
28#ifdef _USE_SSL_
29// Drain OpenSSL's thread-local error queue and route it through the CMSDK log
30// system instead of dumping it straight to stdout/stderr with
31// ERR_print_errors_fp(). Two reasons: (1) it keeps SSL diagnostics on the
32// normal LOG_NETWORK channel (respecting log level and receiver), so the unit
33// test harness - which silences the log in non-verbose mode - no longer shows
34// raw OpenSSL lines from the negative-path verify tests; (2) real failures are
35// still visible when network logging is enabled. @param level LogPrint level.
36static void LogSSLErrors(const char* context, int level) {
37 unsigned long e;
38 bool any = false;
39 char buf[256];
40 while ((e = ERR_get_error()) != 0) {
41 ERR_error_string_n(e, buf, sizeof(buf));
42 LogPrint(0, LOG_NETWORK, level, "SSL: %s: %s", context ? context : "error", buf);
43 any = true;
44 }
45 if (!any)
46 LogPrint(0, LOG_NETWORK, level, "SSL: %s (no OpenSSL error detail)", context ? context : "error");
47}
48#endif // _USE_SSL_
49
51// SSL Encryption Protocol
53
54bool SSLCheckBufferForCompatibility(const char* buffer, uint32 length) {
55 if (length < 14)
56 return false;
57 return ( utils::stristr(buffer, "ClientVersion ") == buffer );
58}
59
60bool AESCheckBufferForCompatibility(const char* buffer, uint32 length) {
61 if (length < 14)
62 return false;
63 return ( utils::stristr(buffer, "xxxxxxxxx ") == buffer );
64}
65
66
69
70 encryption = NOENC;
71 localAddress = 0;
72 threadID = 0;
73 lastActivity = 0;
74 socket = INVALID_SOCKET;
75 receiver = NULL;
76 dataReceiver = NULL;
77}
78
80 disconnect();
81 localAddress = 0;
82 threadID = 0;
83 lastActivity = 0;
84 socket = INVALID_SOCKET;
85 receiver = NULL;
86 dataReceiver = NULL;
87}
88
89
90void TCPListener::disconnectInternal(uint16 error) {
91 stop();
92 if (socket != INVALID_SOCKET) {
93 shutdown(socket, SD_BOTH);
94 closesocket(socket);
95 socket = INVALID_SOCKET;
96 }
97 if (receiver && error)
98 receiver->registerError(error, this);
99}
100
101bool TCPListener::disconnect(uint16 error) {
102 mutex.enter(1000);
103 disconnectInternal(error);
104 mutex.leave();
105 return true;
106}
107
109 return (socket != INVALID_SOCKET);
110}
111
112bool TCPListener::init(uint16 port, uint8 encryption, NetworkConnectionReceiver* receiver, NetworkDataReceiver* dataReceiver) {
113 if (port == 0) {
114 LogPrint(0, LOG_NETWORK, 0, "Could not start TCPListener on port 0...");
115 return false;
116 }
117
118 mutex.enter(1000);
119 this->encryption = encryption;
120 memcpy(((char*)&localAddress)+sizeof(uint32), &port, sizeof(uint16));
121 // Open TCP port
122
123 // Setup listening on port node->networkPort
124 if((socket=::socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET){
125 LogPrint(0, LOG_NETWORK, 0, "Could not create TCPListener socket (%d)...", utils::GetLastOSErrorNumber());
126 mutex.leave();
127 return false;
128 }
129
130 #ifdef WINDOWS
131 // Set the exclusive address option, preventing other software binding to
132 // non-INADDR_ANY (i.e. interface addresses such as localhost directly)
133 int one = 1;
134 setsockopt(socket, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char *) &one, sizeof(one));
135 #else
136 /*
137 This socket option tells the kernel that even if this port is busy (in
138 the TIME_WAIT state), go ahead and reuse it anyway. If it is busy,
139 but with another state, you will still get an address already in use
140 error. It is useful if your server has been shut down, and then
141 restarted right away while sockets are still active on its port. You
142 should be aware that if any unexpected data comes in, it may confuse
143 your server, but while this is possible, it is not likely.
144 */
145 int one = 1;
146 setsockopt(socket,SOL_SOCKET,SO_REUSEADDR,&one,sizeof(one));
147 #endif
148
149 struct sockaddr_in addr;
150 addr.sin_family= AF_INET;
151 addr.sin_addr.s_addr=INADDR_ANY;
152 addr.sin_port=htons(port);
153
154 if(bind(socket,(SOCKADDR*)&addr,sizeof(struct sockaddr_in))==SOCKET_ERROR){
155 LogPrint(0, LOG_NETWORK, 0, "Could not create TCPListener on port %u...", port);
156 disconnectInternal(0);
157 mutex.leave();
158 return false;
159 }
160
161 // Set blocking mode
163
164 if(listen(socket,SOMAXCONN)==SOCKET_ERROR){
165 disconnectInternal(0);
166 mutex.leave();
167 return false;
168 }
169
170 if (receiver != NULL) {
171 this->receiver = receiver;
172 // Start networking thread
174 LogPrint(0, LOG_NETWORK, 0, "Could not start TCPListener thread...");
175 disconnectInternal(0);
176 mutex.leave();
177 return false;
178 }
179 }
180 this->dataReceiver = dataReceiver;
181
182 LogPrint(0, LOG_NETWORK, 3, "Started TCPListener thread on port %u...", port);
183 mutex.leave();
184 return true;
185}
186
188 return localAddress;
189}
190
191bool TCPListener::setSSLCertificate(const char* sslCertPath, const char* sslKeyPath) {
192 this->sslCertPath = sslCertPath;
193 this->sslKeyPath = sslKeyPath;
194 return true;
195}
196
198 SOCKET new_sock;
199 TCPConnection* newCon;
200 #ifdef _USE_SSL_
201 SSLConnection* sslCon;
202 #endif // _USE_SSL_
203 uint64 start = GetTimeNow(), timespent;
204
205 while ( (timespent = (GetTimeNow() - start)/1000) < timeout) {
206 // Listen for incoming connections
207 mutex.enter(1000);
208 new_sock = accept(socket, NULL, NULL);
209
210 if ((int) new_sock < 0) {
211 int err = utils::GetLastOSErrorNumber();
212 mutex.leave();
213 if ( (err == SOCKETWOULDBLOCK) || (err == SOCKETTRYAGAIN) ) {
214 // No connection available right now, continue waiting
215 utils::WaitForSocketReadability(socket, (uint32)(timeout-timespent));
216 // printf("[%u] ", GETIPPORT(localAddress));
217 }
218 else {
219 LogPrint(0, LOG_NETWORK, 2, "Shutting down network listener with error code: %d", new_sock);
220 // Socket error, disconnect and exit
221 #ifdef WINDOWS
222 if (err != WSAENOTSOCK)
223 #endif
225 return NULL;
226 }
227 }
228 else {
229 mutex.leave();
230 // We have a winner!
231 // Check for encryption
232 #ifdef _USE_SSL_
233 if (encryption == SSLENC) {
234 LogPrint(0, LOG_NETWORK, 2, "Accepting incoming TCP SSL connection...");
235 sslCon = new SSLConnection();
236 if (!sslCon->init(sslCertPath.c_str(), sslKeyPath.c_str())) {
237 shutdown(new_sock, SD_BOTH);
238 closesocket(new_sock);
239 delete(sslCon);
240 sslCon = NULL;
241 LogPrint(0, LOG_NETWORK, 2, "Failed initing incoming TCP SSL connection...");
242 continue;
243 }
244 LogPrint(0, LOG_NETWORK, 2, "SSL connection initialised");
245 if (!sslCon->connect(new_sock, localAddress, dataReceiver)) {
246 delete(sslCon);
247 sslCon = NULL;
248 LogPrint(0, LOG_NETWORK, 2, "Failed connecting incoming TCP SSL connection...");
249 continue;
250 }
251 LogPrint(0, LOG_NETWORK, 5, "Successfully accepted incoming TCP SSL connection");
252 return sslCon;
253 }
254 else if (encryption == AESENC) {
255 }
256 else {
257 #endif // _USE_SSL_
258 lastActivity = GetTimeNow();
259 newCon = new TCPConnection();
260 // LogPrint(0, LOG_NETWORK, 1, "Incoming connection: %d... ", (int)new_sock);
261 if (!newCon->connect(new_sock, localAddress, dataReceiver)) {
262 //printf("FAILED\n");
263 LogPrint(0, LOG_NETWORK, 2, "Failed connecting incoming TCP connection...");
264 delete(newCon);
265 }
266 else {
267 //printf("SUCCESS\n");
268 LogPrint(0, LOG_NETWORK, 5, "Successfully accepted incoming TCP connection");
269 return newCon;
270 }
271 #ifdef _USE_SSL_
272 }
273 #endif // _USE_SSL_
274 }
275 }
276 return NULL;
277}
278
279
280bool TCPListener::run() {
282
283 if (receiver == NULL)
284 return false;
285
286 isRunning = true;
287 while (shouldContinue) {
288 if ( (con = acceptConnection(100)) != NULL) {
289 if (receiver != NULL)
290 receiver->receiveNetworkConnection(con);
291 else
292 delete(con);
293 }
294 }
295 isRunning = false;
296 return true;
297}
298
299
300
301
302
303
304
305
308
309 type = 0;
310 localAddress = 0;
311 remoteAddress = 0;
312 threadID = 0;
313 lastActivity = 0;
315 remote = false;
317 bufferLen = 0;
318 buffer = NULL;
321 receiver = NULL;
325 greetingData = NULL;
326 greetingSize = 0;
327 // Defence-in-depth for teardown: if a force-cancel path ever survives the
328 // cooperative-only shutdown, the cancel must not land while a worker holds
329 // this buffer mutex (freed by delete(con) -> UAF in the trailing leave()).
330 // setCancelSafe stores its state OUT-OF-LINE, so sizeof(Mutex) and the
331 // layout of NetworkConnection stay byte-identical (required: embedded by
332 // value in layout-sensitive/SWIG-wrapped types).
333 mutex.setCancelSafe(true);
334}
335
337 //printf("~NetworkConnection(%p)\n", this); fflush(stdout);
338 disconnect();
339 localAddress = 0;
340 remoteAddress = 0;
341 threadID = 0;
342 lastActivity = 0;
344 remote = false;
345 if (buffer != NULL)
346 delete [] buffer;
347 bufferLen = 0;
350 receiver = NULL;
351 buffer = NULL;
352 if (greetingData)
353 // delete [], not delete: allocated with new char[size] in setGreetingData().
354 // Scalar delete on an array allocation is an alloc-dealloc mismatch -
355 // undefined behaviour, reported by ASan.
356 delete [] greetingData;
357 greetingData = NULL;
358 greetingSize = 0;
359}
360
361bool NetworkConnection::setGreetingData(const char* data, uint32 size) {
362 if (greetingData)
363 // delete [], not delete: new char[] below (matches the destructor at :353).
364 delete [] greetingData;
365 if (!data)
366 greetingData = NULL;
367 else {
368 greetingData = new char[size];
369 memcpy(greetingData, data, size);
370 }
371 greetingSize = size;
372 return true;
373}
374
375
377 connectTimeoutMS = timeoutMS;
378 return true;
379}
380
384
386 return remote;
387}
388
390 LogPrint(0, LOG_NETWORK, 5, "Shutting down network connection with code: %u", error);
391 stop();
392 if (socket != INVALID_SOCKET) {
393 shutdown(socket, SD_BOTH);
394 try {
396 }
397 catch (...) {}
399 }
400 // NOTE: do NOT clear bufferContentLen/Pos here - a peer that closes right
401 // after replying (HTTP Connection: close) must not wipe the buffered reply.
402 if (receiver && error)
403 receiver->registerError(error, this);
404}
405
407 mutex.enter(1000);
408 disconnectInternal(error);
409 mutex.leave();
410 return true;
411}
412
414 if (len < 128) return false;
415 char* newBuffer = new char[len];
420 }
421 else {
424 }
425
426 if (buffer != NULL)
427 delete [] buffer;
428 bufferLen = len;
429 buffer = newBuffer;
430 return true;
431}
432
433//int32 NetworkConnection::peekStream() {
434//
435// mutex.enter();
436//
437// // and read from the socket
438// int count = ::recvfrom(socket,buffer+bufferContentLen,bufferLen-bufferContentLen,MSG_PEEK,NULL,0);
439// if(count==SOCKET_ERROR) {
440// int err = utils::GetLastOSErrorNumber();
441// mutex.leave();
442// if ( (err == SOCKETWOULDBLOCK) || (err == SOCKETTRYAGAIN) )
443// return 0;
444// else {
445// disconnect(NETWORKERROR_RECEIVE);
446// return -1;
447// }
448// }
449// mutex.leave();
450// return count;
451//}
452
454
455 // Assume that the mutex is locked
456 // LogPrint(0,0,0,"<<<<<<< READINTOBUFFER <<<<<<<<\n");
457
458#ifdef TCPCON_PRINT_DEBUG
459 uint64 start = GetTimeNow();
460#endif
461 int c = 0;
462 int32 count = 0;
463 // The socket is put in non-blocking mode once at connect/accept and is never
464 // flipped back (see TCPConnection::send), so we no longer re-set it here -
465 // that was two fcntl() syscalls on every read of the receive hot path.
466 // Read from the socket while data is still available
467 do {
468 //LogPrint(0,0,0,"<<<<<<< READINTOBUFFER RECVFROM start <<<<<<<<\n");
470 // c = ::recv(socket,buffer+bufferContentLen,bufferLen-bufferContentLen,0);
471 // LogPrint(0,0,0,"<<<<<<< READINTOBUFFER RECVFROM end %d <<<<<<<<\n", c);
472 if(c==SOCKET_ERROR) {
473 int err = utils::GetLastOSErrorNumber();
474 if ( (err == SOCKETWOULDBLOCK) || (err == SOCKETTRYAGAIN) )
475 break;
476 else {
477 #ifdef WINDOWS
478 if (err != WSAENOTSOCK)
479 #endif
481 return -1;
482 }
483 }
484 if (!c) {
485 bool dataAvailable = utils::WaitForSocketReadability(socket, (uint32)(10));
486 if (dataAvailable) {
487 // this indicates that the socket is in a CLOSE_WAIT state,
488 // i.e. the other end has closed the socket so we should too...
489 LogPrint(0, LOG_NETWORK, 2, "*** SOCKET DISCONNECT DETECTED ***\n");
491 }
492 }
493
494 if (c) {
495 //rounds++;
496 count += c;
497 bufferContentLen += c;
498
499 if (bufferLen-bufferContentLen < 512) {
501 //printf("x"); fflush(stdout);
505 }
506 else {
507 //printf("o"); fflush(stdout);
509 }
510 //resize++;
511 }
512 }
513 } while (c > 0);
514
515 #ifdef TCPCON_PRINT_DEBUG
516 if (this->type == TCPCON) {
517 if (count) {
518 char* tmp = new char[count+1];
519 memcpy(tmp, buffer+bufferContentLen-count, count);
520 tmp[count] = 0;
521 LogPrint(0,LOG_NETWORK,0,"<<<<<<< READINTOBUFFER <<<<<<<< TCP RECV BUF %d bytes '%s' (%.3fms) %d / %d\n", count, tmp, GetTimeAge(start)/1000.0, rounds, resize);
522 delete [] tmp;
523 }
524 else {
525 // LogPrint(0,LOG_NETWORK,0,"<<<<<<< READINTOBUFFER <<<<<<<< NOTHING\n");
526 }
527 }
528 #endif
529
530 #ifdef UDPCON_PRINT_DEBUG
531 if (this->type == UDPCON) {
532 if (count) {
533 char* tmp = new char[count+1];
534 memcpy(tmp, buffer+bufferContentLen-count, count);
535 tmp[count] = 0;
536 LogPrint(0,LOG_NETWORK,0,"<<<<<<< READINTOBUFFER <<<<<<<< UDP RECV BUF %u bytes '%s'\n", count, tmp);
537 delete [] tmp;
538 }
539 else {
540 // LogPrint(0,LOG_NETWORK,0,"<<<<<<< READINTOBUFFER <<<<<<<< UDP NOTHING\n");
541 }
542 }
543 #endif
544
545 return count;
546}
547
548bool NetworkConnection::receiveAvailable(char* data, uint32& size, uint32 maxSize, uint32 timeout, bool peek) {
549
550 mutex.enter(1000);
551 if (maxSize > bufferLen-bufferContentLen) {
552 if (bufferContentLen + bufferContentPos > maxSize) {
556 }
557 else
559 }
560
561 uint64 start = GetTimeNow();
562 uint32 count = 0;
563 bool dataAvailable;
564
565 int32 c = readIntoBuffer();
566 if (c < 0 && bufferContentLen - bufferContentPos == 0) {
567 mutex.leave();
568 return false;
569 }
570
571 if (timeout > 0) {
572
573 // Wait for full size to be available, if not already
574 int32 timespent = 0;
575 if (bufferContentLen - bufferContentPos < maxSize) {
576 while (true) {
577 mutex.leave();
578 dataAvailable = utils::WaitForSocketReadability(socket, (uint32)(timeout-timespent));
579 mutex.enter(1000);
580 if ((c = readIntoBuffer()) < 0) {
582 break; // connection gone, but serve what we already buffered
583 mutex.leave();
584 return false;
585 }
586 if (!c && dataAvailable) {
587 // this indicates that the socket is in a CLOSE_WAIT state,
588 // i.e. the other end has closed the socket so we should too...
589 LogPrint(0, LOG_NETWORK, 2, "*** SOCKET DISCONNECT DETECTED ***\n");
591 }
592 if (bufferContentLen - bufferContentPos >= maxSize)
593 break;
594 if ((timespent = GetTimeAgeMS(start)) >= (int32)timeout)
595 break;
596 }
597 }
598 }
599
601 if (size > maxSize)
602 size = maxSize;
603
604 inputBytes += size;
605 if ( size > 0 ) {
606 memcpy(data, buffer+bufferContentPos, size);
607 if (!peek) {
608 bufferContentPos += size;
611 }
612 }
613 mutex.leave();
614 return true;
615}
616
617bool NetworkConnection::receive(char* data, uint32 size, uint32 timeout, bool peek) {
618 // Exact-size, timeout-bounded read from the shared receive buffer. The
619 // buffer mutex makes this safe against the connection's reader thread;
620 // while more bytes are needed the mutex is RELEASED around the
621 // WaitForSocketReadability() select() so writers/other readers are not
622 // blocked for the whole timeout. With peek=true the bytes are copied but
623 // left in the buffer — protocol handlers use this to sniff frame headers
624 // (e.g. MessageProtocol peeks size+id before allocating the body buffer).
625
626 mutex.enter(1000);
627
628 uint64 start = GetTimeNow();
629
630 // Only read from the socket if we don't already have enough buffered. A single
631 // readIntoBuffer() drains everything currently available - often the whole
632 // message, or several pipelined messages, in one go - so the body read (and
633 // subsequent messages) are then served straight from the buffer with no
634 // recvfrom() syscall at all. Previously readIntoBuffer() ran on every receive()
635 // regardless, costing a wasted syscall per peek and per body read.
636 if (bufferContentLen - bufferContentPos < size) {
637 int32 c = readIntoBuffer();
638 if (c < 0) {
639 mutex.leave();
640 return false;
641 }
642
643 // Wait for the full size to be available, if not already.
644 int32 timespent = 0;
645 while (bufferContentLen - bufferContentPos < size) {
646 mutex.leave();
647 utils::WaitForSocketReadability(socket, (uint32)(timeout-timespent));
648 mutex.enter(1000);
649 if ((c = readIntoBuffer()) < 0) {
650 mutex.leave();
651 return false;
652 }
654 break;
655 if ((timespent = GetTimeAgeMS(start)) >= (int32)timeout) {
656 mutex.leave();
657 return false;
658 }
659 }
660 }
661
662 // LogPrint(0,LOG_NETWORK,0,"Receiving %u (buffer %u) bytes via network...", size, bufferContentLen - bufferContentPos);
663 //printf("**************** Buffer ok (%u, %u = %u->%u), left (%u), size (%u), next %u, %u ****************\n",
664 // bufferLen, bufferContentLen - bufferContentPos, bufferContentPos, bufferContentLen,
665 // bufferLen-bufferContentLen+bufferContentPos, size,
666 // *(uint32*)(buffer+bufferContentPos), *(uint32*)(buffer+bufferContentPos+4));
667
668 int64 t = GetTimeAge(start);
669 if (t > 0)
670 inputSpeed = (uint32)(size*1000000.0/(double)t);
671 inputBytes += size;
672
673 memcpy(data, buffer+bufferContentPos, size);
674 if (!peek) {
675 bufferContentPos += size;
678 }
679 mutex.leave();
680 return true;
681}
682
683bool NetworkConnection::discard(uint32 size) {
684 mutex.enter(1000);
686 if (bufferContentLen - bufferContentPos >= size) {
687 bufferContentPos += size;
690 inputBytes += size;
691 mutex.leave();
692 return true;
693 }
694 else {
695 mutex.leave();
696 return false;
697 }
698}
699
701 mutex.enter(1000);
704 if (c) {
705 LogPrint(0,LOG_NETWORK,3,"Cleared %u chars from buffer...", c);
706 // if (c > 1)
707 // utils::PrintBinary(buffer+bufferContentPos, c, false, "Cleared Buffer Content");
708 }
710 inputBytes += c;
711 mutex.leave();
712 return c;
713}
714
715
718 return true;
719 else {
721 }
722}
723
727
728
730
731 if (socket == INVALID_SOCKET)
732 return false;
733
734 char peekBuffer[1];
735 // First use the socket a bit
736 if (!mutex.enter(1000))
737 return false;
738
740 int res = recv(socket, peekBuffer, 1, MSG_PEEK);
741 if (res > 0) {
742 mutex.leave();
743 return true;
744 }
745 else if (res < 0) {
746 int err = utils::GetLastOSErrorNumber();
747 // UDP needs TRYAGAIN
748 if (err == SOCKETWOULDBLOCK) {
749 mutex.leave();
750 return true;
751 }
752
753 #ifdef WINDOWS
754 else if ((type == UDPCON) && (err == SOCKETTRYAGAIN)) {
755 mutex.leave();
756 return true;
757 }
758 else if (err == WSAENOTCONN) {} // Windows needs this one...
759 else if (err == WSAENOTSOCK) {} // Windows needs this one...
760 else if (err == WSAEOPNOTSUPP) {} // WinCE may need this one...???.
761 #else
762 else if (err == SOCKETTRYAGAIN) {
763 mutex.leave();
764 return true;
765 }
766 #endif //WINDOWS
767 else {
768 // Error will be handled by the caller
770 mutex.leave();
771 return false;
772 }
773 // mutex.leave();
774 }
775 else { // if err == 0
776 // Error will be handled by the caller
778 mutex.leave();
779 return false;
780 }
781
782 struct timeval tv;
783 tv.tv_sec = 0;
784 tv.tv_usec = 10;
785
786 int maxfd = 0;
787 fd_set wfds;
788 // create a list of sockets to check for activity
789 FD_ZERO(&wfds);
790 // specify socket
791 FD_SET(socket, &wfds);
792
793 mutex.leave();
794
795 #ifdef WINDOWS
796 int len;
797 #else
798 #ifdef Darwin
799 #if GCC_VERSION < 40000
800 int len;
801 maxfd = socket + 1;
802 #else
803 socklen_t len;
804 maxfd = socket + 1;
805 #endif // GCC_VERSION < 40000
806 #else
807 socklen_t len;
808 maxfd = socket + 1;
809 #endif
810 #endif
811
812 if (timeout > 0) {
813 ldiv_t d = ldiv(timeout*1000, 1000000);
814 tv.tv_sec = d.quot;
815 tv.tv_usec = d.rem;
816 }
817
818 // Check for writability
819 res = select(maxfd, NULL, &wfds, NULL, &tv);
820
821 if (res <= 0)
822 return false;
823
824 //printf("wait res > 0\n");
825
826 int error;
827 len = sizeof(error);
828
829 if (!mutex.enter(1000))
830 return false;
831
832 if (FD_ISSET(socket, &wfds) != 0) {
833 if (getsockopt(socket, SOL_SOCKET, SO_ERROR, (char*)&error, &len) != 0) {
834
835 int wsaError = utils::GetLastOSErrorNumber();
836 mutex.leave();
837 if (wsaError == 0) {
838 // No error, just unable to send...
839 return true;
840 }
841 #ifdef WINDOWS
842 else if (wsaError == WSAENETDOWN ) {
843 return false;
844 }
845 else if (wsaError == WSAEFAULT ) {
846 return false;
847 }
848 else if (wsaError == WSAEINPROGRESS ) {
849 return false;
850 }
851 else if (wsaError == WSAEINVAL ) {
852 return false;
853 }
854 else if (wsaError == WSAENOPROTOOPT ) {
855 if (error == 0) {
856 return true;
857 }
858 }
859 else if (wsaError == WSAENOTSOCK ) {
860 return false;
861 }
862 #endif
863 return false;
864 }
865 mutex.leave();
866 if (error == 0)
867 return true;
868 }
869 else
870 mutex.leave();
871
872 return false;
873}
874
876 struct timeval tv;
877 tv.tv_sec = 0;
878 tv.tv_usec = 10;
879
880 int maxfd = 0;
881 fd_set wfds;
882 // create a list of sockets to check for activity
883 FD_ZERO(&wfds);
884 // specify socket
885 FD_SET(s, &wfds);
886
887
888 #ifdef WINDOWS
889 int len;
890 #else
891 #ifdef Darwin
892 #if GCC_VERSION < 40000
893 int len;
894 maxfd = s + 1;
895 #else
896 socklen_t len;
897 maxfd = s + 1;
898 #endif // GCC_VERSION < 40000
899 #else
900 socklen_t len;
901 maxfd = s + 1;
902 #endif
903 #endif
904
905 if (timeout > 0) {
906 ldiv_t d = ldiv(timeout * 1000, 1000000);
907 tv.tv_sec = d.quot;
908 tv.tv_usec = d.rem;
909 }
910
911 // Check for writability
912 int res = select(maxfd, NULL, &wfds, NULL, &tv);
913
914 if (res <= 0)
915 return false;
916
917 //printf("wait res > 0\n");
918
919 int error;
920 len = sizeof(error);
921
922 if (FD_ISSET(s, &wfds) != 0) {
923 if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char*)&error, &len) != 0) {
924
925 int wsaError = utils::GetLastOSErrorNumber();
926 if (wsaError == 0) {
927 // No error, just unable to send...
928 return true;
929 }
930 #ifdef WINDOWS
931 else if (wsaError == WSAENETDOWN) {
932 return false;
933 }
934 else if (wsaError == WSAEFAULT) {
935 return false;
936 }
937 else if (wsaError == WSAEINPROGRESS) {
938 return false;
939 }
940 else if (wsaError == WSAEINVAL) {
941 return false;
942 }
943 else if (wsaError == WSAENOPROTOOPT) {
944 if (error == 0) {
945 return true;
946 }
947 }
948 else if (wsaError == WSAENOTSOCK) {
949 return false;
950 }
951 #endif
952 return false;
953 }
954 if (error == 0)
955 return true;
956 }
957 return false;
958}
959
961
962 if (socket == INVALID_SOCKET)
963 return false;
964
965 // First use the socket a bit
966 if (!mutex.enter(1000))
967 return false;
968
969 struct timeval tv;
970 tv.tv_sec = 0;
971 tv.tv_usec = 10;
972
973 int maxfd = 0;
974 fd_set wfds;
975 // create a list of sockets to check for activity
976 FD_ZERO(&wfds);
977 // specify socket
978 FD_SET(socket, &wfds);
979
980 mutex.leave();
981
982 #ifdef WINDOWS
983 int len;
984 #else
985 #ifdef Darwin
986 #if GCC_VERSION < 40000
987 int len;
988 maxfd = socket + 1;
989 #else
990 socklen_t len;
991 maxfd = socket + 1;
992 #endif // GCC_VERSION < 40000
993 #else
994 socklen_t len;
995 maxfd = socket + 1;
996 #endif
997 #endif
998
999 if (timeout > 0) {
1000 ldiv_t d = ldiv(timeout * 1000, 1000000);
1001 tv.tv_sec = d.quot;
1002 tv.tv_usec = d.rem;
1003 }
1004
1005 // Check for writability
1006 int res = select(maxfd, NULL, &wfds, NULL, &tv);
1007
1008 if (res <= 0)
1009 return false;
1010
1011 //printf("wait res > 0\n");
1012
1013 int error;
1014 len = sizeof(error);
1015
1016 mutex.enter(1000);
1017 if (FD_ISSET(socket, &wfds) != 0) {
1018 if (getsockopt(socket, SOL_SOCKET, SO_ERROR, (char*)&error, &len) != 0) {
1019
1020 int wsaError = utils::GetLastOSErrorNumber();
1021 mutex.leave();
1022 if (wsaError == 0) {
1023 // No error, just unable to send...
1024 return true;
1025 }
1026#ifdef WINDOWS
1027 else if (wsaError == WSAENETDOWN) {
1028 return false;
1029 }
1030 else if (wsaError == WSAEFAULT) {
1031 return false;
1032 }
1033 else if (wsaError == WSAEINPROGRESS) {
1034 return false;
1035 }
1036 else if (wsaError == WSAEINVAL) {
1037 return false;
1038 }
1039 else if (wsaError == WSAENOPROTOOPT) {
1040 if (error == 0) {
1041 return true;
1042 }
1043 }
1044 else if (wsaError == WSAENOTSOCK) {
1045 return false;
1046 }
1047#endif
1048 return false;
1049 }
1050 mutex.leave();
1051 if (error == 0)
1052 return true;
1053 }
1054 else
1055 mutex.leave();
1056
1057 return false;
1058}
1059
1061 if (receiver == NULL)
1062 return false;
1063
1064 uint32 size;
1065 uint32 buflen = INITIALBUFFERSIZE;
1066 char* myBuffer = (char*) malloc(buflen);
1067 if (myBuffer == NULL)
1068 return false;
1069
1070 LogPrint(0, LOG_NETWORK, 2, "Incoming network connection from %u.%u.%u.%u:%u, started run...",
1072
1073 isRunning = true;
1074 while (shouldContinue) {
1075 if (receive((char*)&size, sizeof(size), 50, true)) {
1076
1077 if (buflen < size) {
1078 buflen = size;
1079 myBuffer = (char*) realloc(myBuffer, buflen);
1080 if (myBuffer == NULL) {
1081 isRunning = false;
1083 return false;
1084 }
1085 }
1086
1087 // Receive the full data structure
1088 if (!receive(myBuffer, size, 500)) {
1089 isRunning = false;
1090 free(myBuffer);
1091 // Error already reported & already disconnected
1092 return false;
1093 }
1094
1095 if (receiver) {
1096 receiver->receiveData(myBuffer, size, this);
1097 }
1098 }
1099 }
1100 isRunning = false;
1101 free(myBuffer);
1102 return true;
1103}
1104
1108
1110 return inputSpeed;
1111}
1112
1114 return type;
1115}
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1131
1134
1136 // Setup socket
1137 mutex.enter(1000);
1138 if((socket=::socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP))==INVALID_SOCKET){
1139 LogPrint(0, LOG_NETWORK, 0, "Could not create UDPConnection socket...");
1141 mutex.leave();
1142 return false;
1143 }
1144
1145 #ifdef WINDOWS
1146 // Set the exclusive address option, preventing other software binding to
1147 // non-INADDR_ANY (i.e. interface addresses such as localhost directly)
1148 int one = 1;
1149 setsockopt(socket, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char *) &one, sizeof(one));
1150 #else
1151 /*
1152 This socket option tells the kernel that even if this port is busy (in
1153 the TIME_WAIT state), go ahead and reuse it anyway. If it is busy,
1154 but with another state, you will still get an address already in use
1155 error. It is useful if your server has been shut down, and then
1156 restarted right away while sockets are still active on its port. You
1157 should be aware that if any unexpected data comes in, it may confuse
1158 your server, but while this is possible, it is not likely.
1159 */
1160 int one = 1;
1161 setsockopt(socket,SOL_SOCKET,SO_REUSEADDR,&one,sizeof(one));
1162 #endif
1163
1164 setsockopt(socket,SOL_SOCKET,SO_BROADCAST,(char*)&one,sizeof(one));
1165
1166 // Set blocking mode
1168
1169 mutex.leave();
1170 return true;
1171}
1172
1174 if (port == 0) {
1175 LogPrint(0, LOG_NETWORK, 0, "Could not start UDPConnection on port 0...");
1176 return false;
1177 }
1178
1179 memcpy(((char*)&localAddress)+sizeof(uint32), &port, sizeof(uint16));
1180 // Open UDP port
1181
1182 // Setup listening on port node->networkPort
1183 mutex.enter(1000);
1184 if((socket=::socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP))==INVALID_SOCKET){
1185 LogPrint(0, LOG_NETWORK, 0, "Could not create UDPConnection socket...");
1187 mutex.leave();
1188 return false;
1189 }
1190
1191 #ifdef WINDOWS
1192 // Set the exclusive address option, preventing other software binding to
1193 // non-INADDR_ANY (i.e. interface addresses such as localhost directly)
1194 int one = 1;
1195 setsockopt(socket, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char *) &one, sizeof(one));
1196 #else
1197 /*
1198 This socket option tells the kernel that even if this port is busy (in
1199 the TIME_WAIT state), go ahead and reuse it anyway. If it is busy,
1200 but with another state, you will still get an address already in use
1201 error. It is useful if your server has been shut down, and then
1202 restarted right away while sockets are still active on its port. You
1203 should be aware that if any unexpected data comes in, it may confuse
1204 your server, but while this is possible, it is not likely.
1205 */
1206 int one = 1;
1207 setsockopt(socket,SOL_SOCKET,SO_REUSEADDR,&one,sizeof(one));
1208 #endif
1209
1210 setsockopt(socket,SOL_SOCKET,SO_BROADCAST,(char*)&one,sizeof(one));
1211
1212 struct sockaddr_in addr;
1213 addr.sin_family= AF_INET;
1214 addr.sin_addr.s_addr=INADDR_ANY;
1215 addr.sin_port=htons(port);
1216
1217 if(bind(socket,(SOCKADDR*)&addr,sizeof(struct sockaddr_in))==SOCKET_ERROR){
1218 LogPrint(0, LOG_NETWORK, 0, "Could not create UDPConnection on port %u...", port);
1220 mutex.leave();
1221 return false;
1222 }
1223 LogPrint(0, LOG_NETWORK, 2, "Created UDPConnection on port %u...", port);
1224
1225 // Set blocking mode
1227
1228 if (receiver != NULL) {
1229 this->receiver = receiver;
1230 // Start networking thread
1232 LogPrint(0, LOG_NETWORK, 0, "Could not start UDPConnection thread...");
1234 mutex.leave();
1235 return false;
1236 }
1237 }
1238
1239 mutex.leave();
1240 return true;
1241}
1242
1243bool UDPConnection::send(const char* data, uint32 size, uint64 receiver) {
1244 uint64 start;
1245 sockaddr_in recvAddr;
1246 recvAddr.sin_family = AF_INET;
1247 int64 t;
1248
1249 if (!receiver && !defaultReceiver) {
1250 // this should broadcast ##############
1251 return false;
1252 }
1253 else {
1254 uint64 rec = receiver ? receiver : defaultReceiver;
1255 uint16 p = GETIPPORT(rec);
1256 recvAddr.sin_port = htons(p);
1257 memcpy(&recvAddr.sin_addr.s_addr, &rec, 4);
1258 if (!sendMutex.enter(500))
1259 return false;
1260 start = GetTimeNow();
1261
1262 uint32 pos = 0;
1263 int32 n;
1264
1265 while (true) {
1266 try {
1267 n = ::sendto(socket, data + pos, size - pos, 0, (SOCKADDR*)&recvAddr, sizeof(sockaddr_in));
1268 }
1269 catch (...) {
1270 // printf("--- UDP error sending reply (%u)...\n", size);
1272 sendMutex.leave();
1273 return false;
1274 }
1275 if (n == SOCKET_ERROR) {
1276 // printf("--- UDP error sending reply (%u)...\n", size);
1278 sendMutex.leave();
1279 return false;
1280 }
1281 pos += n;
1282 // Have we written everything?
1283 if (pos >= size)
1284 break;
1285 // else wait for writeability
1287 // check for ridiculous timeout
1288 if ((t = GetTimeAgeMS(start)) > 10000) {
1290 sendMutex.leave();
1291 return false;
1292 }
1293 // and go again
1294 }
1295 }
1296 t = GetTimeAge(start);
1297 if (t > 0)
1298 outputSpeed = (uint32)(size*1000000.0/(double)t);
1299 outputBytes += size;
1300 sendMutex.leave();
1301
1302 #ifdef UDPCON_PRINT_DEBUG
1303 if (size < 1024) {
1304 char* tmp = new char[size+1];
1305 memcpy(tmp, data, size);
1306 tmp[size] = 0;
1307 LogPrint(0,LOG_NETWORK,0,">>>>>>> SEND >>>>>>>> UDP Sent %u bytes '%s' to %u.%u.%u.%u:%u\n", size, tmp, GETIPADDRESSQUAD(receiver), GETIPPORT(receiver));
1308 delete [] tmp;
1309 }
1310 else {
1311 #ifdef UDPCON_PRINTBINARY_DEBUG
1312 char* tmp = new char[size+1];
1313 memcpy(tmp, data, size);
1314 tmp[size] = 0;
1315 LogPrint(0,LOG_NETWORK,0,">>>>>>> SEND >>>>>>>> UDP Sent %u bytes '%s'\n", size, tmp);
1316 delete [] tmp;
1317 #else
1318 char* tmp = new char[1024];
1319 memcpy(tmp, data, 1023);
1320 tmp[1023] = 0;
1321 LogPrint(0,LOG_NETWORK,0,">>>>>>> SEND >>>>>>>> UDP Sent %u bytes '%s' to %u.%u.%u.%u:%u\n", size, tmp, GETIPADDRESSQUAD(receiver), GETIPPORT(receiver));
1322 delete [] tmp;
1323 #endif
1324 }
1325 #endif
1326
1327 return true;
1328}
1329
1330bool UDPConnection::reconnect(uint32 timeoutMS) {
1331 disconnect();
1333}
1334
1337 return true;
1338}
1339
1341 return localAddress;
1342}
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1359
1362
1364 mutex.enter(1000);
1365 bufferContentLen = 0;
1366 bufferContentPos = 0;
1367 localAddress = localAddr;
1368
1369 socket = s;
1371
1372 // Set blocking mode
1374
1375 struct linger tmp = {1, 0};
1376 setsockopt(socket, SOL_SOCKET, SO_LINGER, (char *)&tmp, sizeof(tmp));
1377 int delay = 1;
1378 setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char*) &delay, sizeof(delay));
1379 //char buffsize = 1;
1380 //setsockopt(socket, SOL_SOCKET, SO_SNDBUF, &buffsize, sizeof(buffsize));
1381 //buffsize = 1;
1382 //setsockopt(socket, SOL_SOCKET, SO_RCVBUF, &buffsize, sizeof(buffsize));
1383
1384 LogPrint(0, LOG_NETWORK, 2, "Incoming TCP connection from %u.%u.%u.%u:%u, starting run...",
1386
1387 if (receiver != NULL) {
1388 this->receiver = receiver;
1389 // Start networking thread
1391 LogPrint(0, LOG_NETWORK, 0, "Could not start TCPConnection thread...");
1393 mutex.leave();
1394 return false;
1395 }
1396 }
1397
1398 remote = true;
1399 mutex.leave();
1400 return true;
1401}
1402
1403bool TCPConnection::connect(uint64 addr, uint32 timeoutMS, NetworkDataReceiver* receiver) {
1404 // Timeout-aware connect, identical on Winsock and BSD sockets thanks to the
1405 // SOCKET/closesocket/GetLastOSErrorNumber abstractions: the socket is put
1406 // into non-blocking mode first, so ::connect() returns immediately with
1407 // EWOULDBLOCK/EINPROGRESS and didConnect() then select()-waits up to
1408 // timeoutMS for writability (= connection established). On success the
1409 // socket gets SO_LINGER {1,0} (hard close, RST instead of TIME_WAIT) and
1410 // TCP_NODELAY (no Nagle batching — vital for small request/reply frames).
1411 // Passing a NetworkDataReceiver switches the connection to push mode by
1412 // starting a dedicated reader thread (TCPConnectionRun).
1413
1414 // first create a temporary socket so we don't have to block the mutex while connecting
1415 SOCKET tempSocket;
1416
1417 if (timeoutMS) {
1418 if (!connectTimeoutMS)
1419 connectTimeoutMS = timeoutMS;
1420 }
1421 else
1422 timeoutMS = connectTimeoutMS;
1423
1424 if((tempSocket =::socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET){
1425 int retries = 0;
1426 int err = utils::GetLastOSErrorNumber();
1427 while ((err == SOCKETWOULDBLOCK) || (err == SOCKETTRYAGAIN)) {
1428 utils::Sleep(20);
1429 if ((tempSocket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) != INVALID_SOCKET)
1430 break;
1432 retries++;
1433 if (retries > 10)
1434 break;
1435 }
1436 if (tempSocket == INVALID_SOCKET) {
1437 // mutex is not locked
1438 LogPrint(0, LOG_NETWORK, 0, "Could not create TCPConnection socket (%d)...", err);
1439 return false;
1440 }
1441 }
1442
1443 bufferContentLen = 0;
1444 bufferContentPos = 0;
1445
1446 // Set blocking mode
1448
1449 struct sockaddr_in saServer;
1450 saServer.sin_family = AF_INET;
1451 saServer.sin_port = htons(GETIPPORT(addr));
1452 memcpy(&saServer.sin_addr.s_addr, &addr, 4);
1453
1454 // Connect to the server
1455 int res;
1456 if ((res = ::connect(tempSocket, (struct sockaddr*)&saServer, sizeof(struct sockaddr))) != 0) {
1457 int err = utils::GetLastOSErrorNumber();
1458 if ( (err == SOCKETWOULDBLOCK) || (err == SOCKETTRYAGAIN) ) {
1459 if (!didConnect(tempSocket, timeoutMS)) {
1460 closesocket(tempSocket);
1461 return false;
1462 }
1463 }
1464 else {
1465 closesocket(tempSocket);
1466 return false;
1467 }
1468 }
1469
1470 // Set blocking mode
1471 // utils::SetSocketNonBlockingMode(socket);
1472
1473 struct linger tmp = {1, 0};
1474 setsockopt(tempSocket, SOL_SOCKET, SO_LINGER, (char *)&tmp, sizeof(tmp));
1475 int delay = 1;
1476 setsockopt(tempSocket, IPPROTO_TCP, TCP_NODELAY, (char*) &delay, sizeof(delay));
1477 //char buffsize = 1;
1478 //setsockopt(tempSocket, SOL_SOCKET, SO_SNDBUF, &buffsize, sizeof(buffsize));
1479 //buffsize = 1;
1480 //setsockopt(tempSocket, SOL_SOCKET, SO_RCVBUF, &buffsize, sizeof(buffsize));
1481
1482 // Now block the mutex
1483 if (!mutex.enter(1000)) {
1484 LogPrint(0, LOG_NETWORK, 0, "Could not lock connection mutex...");
1485 closesocket(tempSocket);
1486 return false;
1487 }
1488
1489 socket = tempSocket;
1490
1491 if (receiver != NULL) {
1492 this->receiver = receiver;
1493 // Start networking thread
1495 LogPrint(0, LOG_NETWORK, 0, "Could not start TCPConnection thread...");
1497 mutex.leave();
1498 return false;
1499 }
1500 }
1501
1502 remoteAddress = addr;
1503 remote = false;
1504
1505 mutex.leave();
1506 return true;
1507}
1508
1509bool TCPConnection::connect(const char* addr, uint16 port, uint64& location, uint32 timeoutMS, NetworkDataReceiver* receiver) {
1510 // Resolve address
1511 uint32 address;
1512 if (!utils::LookupIPAddress(addr, address))
1513 return false;
1514 return connect(location = GETIPADDRESSPORT(address, port), timeoutMS, receiver);
1515}
1516
1517bool TCPConnection::connect(const uint32* addresses, uint16 addressCount, uint16 port, uint64& location, uint32 timeoutMS, NetworkDataReceiver* receiver) {
1518 // Try all addresses
1519 for (uint16 n=0; n<addressCount; n++) {
1520 if (connect(location = GETIPADDRESSPORT(addresses[n], port), timeoutMS, receiver))
1521 return true;
1522 }
1523 return false;
1524}
1525
1526
1527bool TCPConnection::delayedConnect(uint64 addr, uint32 timeoutMS, NetworkDataReceiver* receiver) {
1528 mutex.enter(1000);
1529
1530 connectTimeoutMS = timeoutMS;
1531 remoteAddress = addr;
1532 remote = false;
1533
1534 if (receiver != NULL) {
1535 this->receiver = receiver;
1536 // Start networking thread
1538 LogPrint(0, LOG_NETWORK, 0, "Could not start TCPConnection thread...");
1539 mutex.leave();
1540 return false;
1541 }
1542 }
1543
1544 mutex.leave();
1545 return true;
1546}
1547
1548bool TCPConnection::delayedConnect(const char* addr, uint16 port, uint64& location, uint32 timeoutMS, NetworkDataReceiver* receiver) {
1549 // Resolve address
1550 uint32 address;
1551 if (!utils::LookupIPAddress(addr, address))
1552 return false;
1553 return delayedConnect(location = GETIPADDRESSPORT(address, port), timeoutMS, receiver);
1554}
1555
1556
1557//#define TCPCON_PRINT_DEBUG
1558
1559bool TCPConnection::send(const char* data, uint32 size, uint64 receiver) {
1560 // Ignore receiver, only for UDP
1561 // ### Consider splitting large data up into smaller chunks ###
1562 if (!size)
1563 return false;
1564 if (!sendMutex.enter(500))
1565 return false;
1566 uint64 start = GetTimeNow();
1567 // The socket stays in non-blocking mode (set once at connect/accept). We used
1568 // to flip it to blocking for the duration of the send and back to non-blocking
1569 // afterwards, which cost four fcntl() syscalls on every message AND raced with
1570 // the receive thread reading the same socket. Instead we drive the non-blocking
1571 // send loop directly and only wait for writeability when the kernel send buffer
1572 // is genuinely full (EWOULDBLOCK).
1573
1574 // Charles:
1575 //const char *data = (const char *) tdata;
1576 // IntT done = 0;
1577 // do {
1578 // int n = write(fd,&(data[done]),length - done);
1579 // if(n < 0) {
1580 // if(errno == EAGAIN || errno == EINTR) // Recoverable error?
1581 // continue;
1582 // return -1;
1583 // }
1584 // done += n;
1585 // } while(done < length);
1586 // return done;
1587
1588 int64 t;
1589 uint32 pos = 0;
1590 int32 n;
1591
1592 while (true) {
1593 try {
1594 n = ::send(socket, data + pos, size - pos, 0);
1595 }
1596 catch (...) {
1597 //printf("--- TCP error sending reply (%u) error: %u...\n", size, WSAGetLastError());
1599 sendMutex.leave();
1600 return false;
1601 }
1602 //n = ::send(socket, data + pos,
1603 // (size - pos>5120000) ? 5120000 : size - pos,
1604 // 0);
1605 if(n == SOCKET_ERROR) {
1606 int err = utils::GetLastOSErrorNumber();
1607 if ((err == SOCKETWOULDBLOCK) || (err == SOCKETTRYAGAIN)) {
1608 // Kernel send buffer is full - wait until it drains, then retry
1609 // the same chunk. Nothing has been consumed, so 'pos' is unchanged.
1610 if ((t = GetTimeAgeMS(start)) > 10000) {
1612 sendMutex.leave();
1613 return false;
1614 }
1616 continue;
1617 }
1618 //printf("--- TCP error sending reply (%u) error: %u...\n", size, WSAGetLastError());
1620 sendMutex.leave();
1621 return false;
1622 }
1623 pos += n;
1624 // Have we written everything?
1625 if (pos >= size)
1626 break;
1627 // check for ridiculous timeout
1628 if ((t = GetTimeAgeMS(start)) > 10000) {
1630 sendMutex.leave();
1631 return false;
1632 }
1633 // and go again
1634 }
1635
1636 t = GetTimeAge(start);
1637 if (t > 0)
1638 outputSpeed = (uint32)(size*1000000.0/(double)t);
1639 outputBytes += size;
1640 sendMutex.leave();
1641
1642 #ifdef TCPCON_PRINT_DEBUG
1643 if (size < 1024) {
1644 char* tmp = new char[size+1];
1645 memcpy(tmp, data, size);
1646 tmp[size] = 0;
1647 LogPrint(0,LOG_NETWORK,0,">>>>>>> SEND >>>>>>>> TCP Sent %u bytes (%.3f) '%s'\n", size, t/1000.0, tmp);
1648 delete [] tmp;
1649 }
1650 else {
1651 #ifdef TCPCON_PRINTBINARY_DEBUG
1652 char* tmp = new char[size+1];
1653 memcpy(tmp, data, size);
1654 tmp[size] = 0;
1655 LogPrint(0,LOG_NETWORK,0,">>>>>>> SEND >>>>>>>> TCP Sent %u bytes '%s'\n", size, tmp);
1656 delete [] tmp;
1657 #else
1658 char* tmp = new char[1024];
1659 memcpy(tmp, data, 1023);
1660 tmp[1023] = 0;
1661 LogPrint(0,LOG_NETWORK,0,">>>>>>> SEND >>>>>>>> TCP Sent %u bytes (%.3f) '%s'\n", size, t / 1000.0, tmp);
1662 delete [] tmp;
1663 #endif
1664 }
1665 #endif
1666
1667
1668// utils::Sleep(100);
1669 return true;
1670}
1671
1672
1673
1674bool TCPConnection::reconnect(uint32 timeoutMS) {
1675 disconnect();
1676 return connect(remoteAddress, timeoutMS, receiver);
1677}
1678
1679
1681
1682 if (socket == INVALID_SOCKET)
1683 return false;
1684
1685 struct sockaddr_in remoteAddr;
1686
1687 #ifdef WINDOWS
1688 int remoteAddrLen;
1689 #else
1690 #ifdef Darwin
1691 #if GCC_VERSION < 40000
1692 int remoteAddrLen;
1693 #else
1694 socklen_t remoteAddrLen;
1695 #endif // GCC_VERSION < 40000
1696 #else
1697 socklen_t remoteAddrLen;
1698 #endif
1699 #endif // WINDOWS
1700
1701 remoteAddrLen = sizeof(struct sockaddr_in);
1702
1703 if (getpeername(socket, (struct sockaddr*) &remoteAddr, &remoteAddrLen) != 0)
1704 return false;
1705
1706 uint32 address = remoteAddr.sin_addr.s_addr;
1707 if ( address == LOCALHOSTIP ) {
1708 // Get the actual local ip address, if possible
1709 utils::GetLocalIPAddress(address);
1710 }
1711 addr = GETIPADDRESSPORT(address, (uint16)remoteAddr.sin_port);
1712 return true;
1713}
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730bool IsSSLInitialised = false;
1731
1732#ifdef _USE_SSL_
1733#ifdef WINDOWS
1734 // #include "openssl/applink.c"
1735#endif
1736#endif
1737
1738
1740 type = SSLCON;
1744 #ifdef _USE_SSL_
1745 if (!IsSSLInitialised) {
1746 // Init SSL
1747 //CRYPTO_malloc_init();
1748 OpenSSL_add_all_algorithms();
1749 //ERR_load_BIO_strings();
1750 ERR_load_crypto_strings();
1751 SSL_load_error_strings();
1752
1753 certbio = BIO_new(BIO_s_file());
1754 outbio = BIO_new_fp(stdout, BIO_NOCLOSE);
1755
1756 SSL_library_init();
1757
1758 IsSSLInitialised = true;
1759 }
1760 ctx = NULL;
1761 ssl = NULL;
1762 #endif // _USE_SSL_
1763}
1764
1766 #ifdef _USE_SSL_
1767 mutex.enter(1000);
1768 if (ctx) {
1769 SSL_CTX_free(ctx);
1770 ctx = NULL;
1771 }
1772 mutex.leave();
1773 #else // _USE_SSL_
1774 #endif // _USE_SSL_
1775}
1776
1777// Process-wide default for client certificate verification. False = verify
1778// peers against the CA trust store (secure by default). Set from the global
1779// <psyspec allowselfsigned="yes"> attribute; per-connection
1780// setAllowSelfSigned() overrides it either way.
1782
1786
1790
1791// Process-wide default custom CA location (set from <psyspec cafile/capath>);
1792// per-connection setCALocation() overrides it. Empty = use OS trust store.
1795
1796void SSLConnection::SetDefaultCALocation(const char* caFile, const char* caPath) {
1797 DefaultCAFile = caFile ? caFile : "";
1798 DefaultCAPath = caPath ? caPath : "";
1799}
1800
1801void SSLConnection::setCALocation(const char* caFile, const char* caPath) {
1802 this->caFile = caFile ? caFile : "";
1803 this->caPath = caPath ? caPath : "";
1804 #ifdef _USE_SSL_
1805 if (ctx)
1806 applyClientVerify();
1807 #endif // _USE_SSL_
1808}
1809
1810void SSLConnection::setVerifyHostName(const char* host) {
1811 verifyHostName = host ? host : "";
1812}
1813
1815 allowSelfSigned = allow;
1816 #ifdef _USE_SSL_
1817 if (ctx)
1818 applyClientVerify();
1819 #endif // _USE_SSL_
1820}
1821
1822#ifdef _USE_SSL_
1823// Configure peer verification on the client context according to the
1824// allowSelfSigned policy for this connection.
1825bool SSLConnection::applyClientVerify() {
1826 if (!ctx)
1827 return false;
1828 if (allowSelfSigned) {
1829 SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
1830 }
1831 else {
1832 if (!caFile.empty() || !caPath.empty()) {
1833 // Verify the server certificate against a custom CA file/dir
1834 // (e.g. a self-minted CA) instead of the OS trust store
1835 if (SSL_CTX_load_verify_locations(ctx,
1836 caFile.empty() ? NULL : caFile.c_str(),
1837 caPath.empty() ? NULL : caPath.c_str()) != 1)
1838 LogPrint(0, LOG_NETWORK, 0, "SSL: could not load CA location (file: %s, path: %s)",
1839 caFile.empty() ? "-" : caFile.c_str(), caPath.empty() ? "-" : caPath.c_str());
1840 }
1841 else {
1842 #ifdef WINDOWS
1843 // Verify the server certificate against the OS trust store.
1844 // OpenSSL's SSL_CTX_set_default_verify_paths() is useless on
1845 // Windows (it points at the build-time OPENSSLDIR), so import
1846 // the Windows ROOT system store into the context's X509 store
1847 // via CryptoAPI instead.
1848 bool loadedOSRoots = false;
1849 HCERTSTORE hStore = CertOpenSystemStoreA(0, "ROOT");
1850 if (hStore) {
1851 X509_STORE* store = SSL_CTX_get_cert_store(ctx);
1852 PCCERT_CONTEXT pWinCert = NULL;
1853 while ((pWinCert = CertEnumCertificatesInStore(hStore, pWinCert)) != NULL) {
1854 const unsigned char* enc = pWinCert->pbCertEncoded;
1855 X509* x = d2i_X509(NULL, &enc, pWinCert->cbCertEncoded);
1856 if (x) {
1857 // Returns 0 for duplicates - not a failure
1858 if (X509_STORE_add_cert(store, x) == 1)
1859 loadedOSRoots = true;
1860 X509_free(x);
1861 }
1862 }
1863 CertCloseStore(hStore, 0);
1864 }
1865 ERR_clear_error(); // duplicate-cert noise from X509_STORE_add_cert
1866 if (!loadedOSRoots)
1867 LogPrint(0, LOG_NETWORK, 0, "SSL: could not load Windows ROOT certificate store");
1868 #else
1869 // Verify the server certificate against the OS/CA trust store
1870 if (SSL_CTX_set_default_verify_paths(ctx) != 1)
1871 LogPrint(0, LOG_NETWORK, 0, "SSL: could not load default CA trust store");
1872 #endif // WINDOWS
1873 }
1874 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
1875 }
1876 return true;
1877}
1878
1879int SSLConnection::getVerifyMode() {
1880 if (!ctx)
1881 return -1;
1882 return SSL_CTX_get_verify_mode(ctx);
1883}
1884#endif // _USE_SSL_
1885
1886bool SSLConnection::init(const char *certFile, const char *keyFile) {
1887 mutex.enter(1000);
1888 #ifdef _USE_SSL_
1889 LogPrint(0, LOG_NETWORK, 2, "SSL connection init start");
1890 // Compatible with SSLv2, SSLv3 and TLSv1
1891 const SSL_METHOD *method = SSLv23_server_method();
1892 // Create new context from method.
1893 ctx = SSL_CTX_new(method);
1894 if(!ctx) {
1895 LogPrint(0, LOG_NETWORK, 0, "Unable to create a new SSL context structure");
1896 BIO_printf(outbio, "Unable to create a new SSL context structure.\n");
1897 mutex.leave();
1898 return false;
1899 }
1900 LogPrint(0, LOG_NETWORK, 2, "SSL connection init created, setting files...");
1901
1902 if ( SSL_CTX_use_certificate_chain_file(ctx, certFile) <= 0) {
1903 LogPrint(0, LOG_NETWORK, 0, "Unable to use SSL certificate chain file: %s", certFile);
1904 LogSSLErrors("certificate chain file", 0);
1905 mutex.leave();
1906 return false;
1907 }
1908 if ( SSL_CTX_use_PrivateKey_file(ctx, keyFile, SSL_FILETYPE_PEM) <= 0) {
1909 LogPrint(0, LOG_NETWORK, 0, "Unable to use SSL private key file: %s", keyFile);
1910 LogSSLErrors("private key file", 0);
1911 mutex.leave();
1912 return false;
1913 }
1914 LogPrint(0, LOG_NETWORK, 2, "SSL connection init files set");
1915
1916 // Verify that the two keys goto together.
1917 if ( !SSL_CTX_check_private_key(ctx) ) {
1918 LogPrint(0, LOG_NETWORK, 0, "SSL private key invalid: %s", keyFile);
1919 fprintf(stderr, "Private key is invalid.\n");
1920 mutex.leave();
1921 return false;
1922 }
1923 mutex.leave();
1924 LogPrint(0, LOG_NETWORK, 2, "SSL connection init done");
1925 return true;
1926 #else // _USE_SSL_
1927 mutex.leave();
1928 return false;
1929 #endif // _USE_SSL_
1930}
1931
1933 mutex.enter(1000);
1934 #ifdef _USE_SSL_
1935 // Compatible with SSLv2, SSLv3 and TLSv1
1936 const SSL_METHOD *method = SSLv23_method();
1937 // Create new context from method.
1938 ctx = SSL_CTX_new(method);
1939 if(!ctx) {
1940 BIO_printf(outbio, "Unable to create a new SSL context structure.\n");
1941 mutex.leave();
1942 return false;
1943 }
1944
1945 //SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2);
1946
1947 // Client-side certificate verification (secure by default; see
1948 // setAllowSelfSigned/SetDefaultAllowSelfSigned)
1949 applyClientVerify();
1950
1951 mutex.leave();
1952 return true;
1953 #else // _USE_SSL_
1954 mutex.leave();
1955 return false;
1956 #endif // _USE_SSL_
1957}
1958
1959bool SSLConnection::didConnect(int timeout) {
1960 return NetworkConnection::didConnect(timeout);
1961}
1962
1964
1965 // ######################
1966 //return true;
1967
1968 //printf("ISCON1\n");fflush(stdout);
1969
1970#ifdef _USE_SSL_
1971
1972 if ((socket == INVALID_SOCKET) || !ssl)
1973 return false;
1974
1975 char peekBuffer[1];
1976 // First use the socket a bit
1977
1978 //utils::Sleep(100);
1979
1980 if (!mutex.enter(200, __FUNCTION__))
1981 return false;
1982 //printf("ISCON2\n");fflush(stdout);
1983 int res = recv(socket, peekBuffer, 1, MSG_PEEK);
1984 if (res > 0) {
1985 mutex.leave();
1986 //printf("ISCON3\n");fflush(stdout);
1987 return true;
1988 }
1989 else if (res < 0) {
1990 int err = utils::GetLastOSErrorNumber();
1991 // UDP needs TRYAGAIN
1992 if (err == SOCKETWOULDBLOCK) {
1993 mutex.leave();
1994 //printf("ISCON4\n");fflush(stdout);
1995 return true;
1996 }
1997
1998 #ifdef WINDOWS
1999 else if ((type == UDPCON) && (err == SOCKETTRYAGAIN)) {
2000 mutex.leave();
2001 //printf("ISCON5\n");fflush(stdout);
2002 return true;
2003 }
2004 else if (err == WSAENOTCONN) {} // Windows needs this one...
2005 else if (err == WSAEOPNOTSUPP) {} // WinCE may need this one...???.
2006 #else
2007 else if (err == SOCKETTRYAGAIN) {
2008 mutex.leave();
2009 return true;
2010 }
2011 #endif //WINDOWS
2012 else {
2013 // Error will be handled by the caller
2014 //printf("ISCON6\n");fflush(stdout);
2015 disconnect(0);
2016 mutex.leave();
2017 return false;
2018 }
2019 // mutex.leave();
2020 }
2021 else { // if err == 0
2022 // Error will be handled by the caller
2023 //printf("ISCON7\n");fflush(stdout);
2024 disconnect(0);
2025 mutex.leave();
2026 return false;
2027 }
2028
2029 //printf("ISCON10\n");fflush(stdout);
2030
2031 struct timeval tv;
2032 tv.tv_sec = 0;
2033 tv.tv_usec = 10;
2034
2035 int maxfd = 0;
2036 fd_set wfds;
2037 // create a list of sockets to check for activity
2038 FD_ZERO(&wfds);
2039 // specify socket
2040 FD_SET(socket, &wfds);
2041
2042 mutex.leave();
2043
2044 #ifdef WINDOWS
2045 int len;
2046 #else
2047 #ifdef Darwin
2048 #if GCC_VERSION < 40000
2049 int len;
2050 maxfd = socket + 1;
2051 #else
2052 socklen_t len;
2053 maxfd = socket + 1;
2054 #endif // GCC_VERSION < 40000
2055 #else
2056 socklen_t len;
2057 maxfd = socket + 1;
2058 #endif
2059 #endif
2060
2061 if (timeout > 0) {
2062 ldiv_t d = ldiv(timeout*1000, 1000000);
2063 tv.tv_sec = d.quot;
2064 tv.tv_usec = d.rem;
2065 }
2066
2067 // Check for writability
2068 //printf("ISCON11\n");fflush(stdout);
2069 res = select(maxfd, NULL, &wfds, NULL, &tv);
2070 //printf("ISCON12\n");fflush(stdout);
2071
2072 if (res <= 0)
2073 return false;
2074
2075 //printf("wait res > 0\n");
2076
2077 int error;
2078 len = sizeof(error);
2079
2080 mutex.enter(1000);
2081 //printf("ISCON13\n");fflush(stdout);
2082 if (FD_ISSET(socket, &wfds) != 0) {
2083 if (getsockopt(socket, SOL_SOCKET, SO_ERROR, (char*)&error, &len) != 0) {
2084
2085 int wsaError = utils::GetLastOSErrorNumber();
2086 mutex.leave();
2087 if (wsaError == 0) {
2088 // No error, just unable to send...
2089 return true;
2090 }
2091 #ifdef WINDOWS
2092 else if (wsaError == WSAENETDOWN ) {
2093 return false;
2094 }
2095 else if (wsaError == WSAEFAULT ) {
2096 return false;
2097 }
2098 else if (wsaError == WSAEINPROGRESS ) {
2099 return false;
2100 }
2101 else if (wsaError == WSAEINVAL ) {
2102 return false;
2103 }
2104 else if (wsaError == WSAENOPROTOOPT ) {
2105 if (error == 0) {
2106 return true;
2107 }
2108 }
2109 else if (wsaError == WSAENOTSOCK ) {
2110 return false;
2111 }
2112 #endif
2113 return false;
2114 }
2115 mutex.leave();
2116 if (error == 0)
2117 return true;
2118 }
2119 else
2120 mutex.leave();
2121
2122#endif //_USE_SSL_
2123 return false;
2124}
2125
2126bool SSLConnection::disconnect(uint16 error) {
2127 #ifdef _USE_SSL_
2128 mutex.enter(1000);
2129 if (!ctx || !ssl) {
2130 mutex.leave();
2131 return false;
2132 }
2133 SSL_shutdown(ssl);
2134 SSL_free(ssl);
2135 ssl = NULL;
2136 disconnectInternal(error);
2137 mutex.leave();
2138 return true;
2139 #else // _USE_SSL_
2140 return false;
2141 #endif // _USE_SSL_
2142}
2143
2145 #ifdef _USE_SSL_
2146 if (!ctx || !(ssl = SSL_new(ctx)))
2147 return false;
2148
2149 mutex.enter(1000);
2150 bufferContentLen = 0;
2151 bufferContentPos = 0;
2152 localAddress = localAddr;
2153
2154 socket = s;
2156
2157 // Set blocking mode
2159
2160 struct linger tmp = {1, 0};
2161 setsockopt(s, SOL_SOCKET, SO_LINGER, (char *)&tmp, sizeof(tmp));
2162 int delay = 1;
2163 setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char*) &delay, sizeof(delay));
2164
2165 LogPrint(0, LOG_NETWORK, 2, "SSL connection options set, accepting connection...");
2166
2167 remote = true;
2168 SSL_set_fd(ssl, (int)socket);
2169 int ret = SSL_accept(ssl);
2170 int err;
2171 int errCount = 0;
2172
2173 while (ret == -1) {
2174 err = SSL_get_error(ssl, ret);
2175 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
2176
2177 if ((++errCount) > 10) {
2178 LogPrint(0, LOG_NETWORK, 1, "SSL connection accept took too long, disconnecting...");
2179 SSL_shutdown(ssl);
2180 SSL_free(ssl);
2181 ssl = NULL;
2183 mutex.leave();
2184 return false;
2185 }
2186
2188 ret = SSL_accept(ssl);
2189 }
2190 else {
2191 SSL_shutdown(ssl);
2192 SSL_free(ssl);
2193 ssl = NULL;
2195 mutex.leave();
2196 return false;
2197 }
2198 }
2199
2200 LogPrint(0, LOG_NETWORK, 2, "SSL connection accepted, setting up receiver...");
2201
2202 if (receiver != NULL) {
2203 this->receiver = receiver;
2204 // Start networking thread
2206 LogPrint(0, LOG_NETWORK, 0, "Could not start SSLConnection thread...");
2207 SSL_shutdown(ssl);
2208 SSL_free(ssl);
2209 ssl = NULL;
2211 mutex.leave();
2212 return false;
2213 }
2214 }
2215
2216 mutex.leave();
2217 return true;
2218 #else // _USE_SSL_
2219 return false;
2220 #endif // _USE_SSL_
2221}
2222
2223bool SSLConnection::connect(uint64 addr, uint32 timeoutMS, NetworkDataReceiver* receiver) {
2224 #ifdef _USE_SSL_
2225 // Make client SSL connection; create the client context on demand so the
2226 // verification policy is always applied
2227 if (!ctx && !init()) {
2228 return false;
2229 }
2230 if (!ctx || !(ssl = SSL_new(ctx))) {
2231 LogSSLErrors("SSL_new", 0);
2232 return false;
2233 }
2234
2235 // Hostname verification: when peer verification is on and an expected
2236 // hostname is known (recorded by connect(const char*,...) or set via
2237 // setVerifyHostName), require the peer certificate to match it and
2238 // send SNI. With allowSelfSigned or no hostname (raw IP connects),
2239 // only the chain-of-trust check (or none) applies, as before.
2240 if (!allowSelfSigned && !verifyHostName.empty()) {
2241 if (SSL_set1_host(ssl, verifyHostName.c_str()) != 1) {
2242 LogPrint(0, LOG_NETWORK, 0, "SSL: could not set expected hostname '%s' for verification", verifyHostName.c_str());
2243 SSL_free(ssl);
2244 ssl = NULL;
2245 return false;
2246 }
2247 SSL_set_tlsext_host_name(ssl, verifyHostName.c_str());
2248 }
2249
2250 mutex.enter(1000);
2251 if (timeoutMS) {
2252 if (!connectTimeoutMS)
2253 connectTimeoutMS = timeoutMS;
2254 }
2255 else
2256 timeoutMS = connectTimeoutMS;
2257 if((socket=::socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET){
2258 LogPrint(0, LOG_NETWORK, 0, "Could not create SSLListener socket (%d)...", utils::GetLastOSErrorNumber());
2259 mutex.leave();
2260 return false;
2261 }
2262
2263 bufferContentLen = 0;
2264 bufferContentPos = 0;
2265
2266 // Set blocking mode
2268
2269 struct sockaddr_in saServer;
2270 saServer.sin_family = AF_INET;
2271 saServer.sin_port = htons(GETIPPORT(addr));
2272 memcpy(&saServer.sin_addr.s_addr, &addr, 4);
2273
2274
2275 // Connect to the server
2276 int res;
2277 if ((res = ::connect(socket, (struct sockaddr*)&saServer, sizeof(struct sockaddr))) != 0) {
2278
2279 int err = utils::GetLastOSErrorNumber();
2280 if ( (err == SOCKETWOULDBLOCK) || (err == SOCKETTRYAGAIN) ) {
2281 if (!didConnect(1000)) {
2282 SSL_free(ssl);
2283 ssl = NULL;
2285 mutex.leave();
2286 return false;
2287 }
2288 }
2289 else {
2290 SSL_free(ssl);
2291 ssl = NULL;
2293 mutex.leave();
2294 return false;
2295 }
2296 }
2297
2298 struct linger tmp = {1, 0};
2299 setsockopt(socket, SOL_SOCKET, SO_LINGER, (char *)&tmp, sizeof(tmp));
2300 int delay = 1;
2301 setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char*) &delay, sizeof(delay));
2302
2303 // Connect the SSL struct to our connection
2304 if (!SSL_set_fd (ssl, (int)socket)) {
2305 LogSSLErrors("SSL_set_fd", 0);
2306 SSL_free(ssl);
2307 ssl = NULL;
2309 mutex.leave();
2310 return false;
2311 }
2312
2313 //SSL_set_connect_state(ssl);
2314 SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
2315
2316 // Set blocking mode
2317 // utils::SetSocketNonBlockingMode(socket);
2318
2319 int ret; //, err;
2320 // Initiate SSL handshake
2321 while ( (ret = SSL_connect(ssl)) != 1) {
2322 switch (SSL_get_error(ssl, ret)) {
2323 case SSL_ERROR_WANT_READ:
2325 break;
2326 case SSL_ERROR_WANT_WRITE:
2328 break;
2329 default:
2330 // Handshake failed (e.g. peer certificate verification failed).
2331 // Log at level 1 so the detail is available with network logging
2332 // on, but stays off the console in quiet runs (incl. the unit
2333 // test harness's negative-path verify tests).
2334 LogSSLErrors("handshake failed", 1);
2335 SSL_free(ssl);
2336 ssl = NULL;
2338 mutex.leave();
2339 return false;
2340 }
2341 //err = SSL_get_error(ssl, ret);
2342 //if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
2343 // utils::WaitForSocketWriteability(socket, 200);
2344 // if ( (ret = SSL_connect(ssl)) != 1) {
2345 // ERR_print_errors_fp(stderr);
2346 // disconnect();
2347 // mutex.leave();
2348 // return false;
2349 // }
2350 //}
2351 }
2352
2353 uint32 certnamemax = 1000;
2354 char *certname;
2355 X509 *cert = NULL;
2356
2357 cert = SSL_get_peer_certificate(ssl);
2358 if (cert != NULL) {
2359 certname = new char[certnamemax+1];
2360 certinfo = X509_NAME_oneline(X509_get_subject_name(cert), certname, certnamemax);
2361 delete [] certname;
2362 X509_free(cert);
2363 }
2364
2365 if (receiver != NULL) {
2366 this->receiver = receiver;
2367 // Start networking thread
2369 LogPrint(0, LOG_NETWORK, 0, "Could not start SSLConnection thread...");
2370 SSL_free(ssl);
2371 ssl = NULL;
2373 mutex.leave();
2374 return false;
2375 }
2376 }
2377
2378 remoteAddress = addr;
2379 remote = false;
2380
2381 mutex.leave();
2382 return true;
2383 #else // _USE_SSL_
2384 return false;
2385 #endif // _USE_SSL_
2386}
2387
2388bool SSLConnection::connect(const char* addr, uint16 port, uint64& location, uint32 timeoutMS, NetworkDataReceiver* receiver) {
2389 #ifdef _USE_SSL_
2390 uint32 address;
2391 if (!utils::LookupIPAddress(addr, address))
2392 return false;
2393 // Record the hostname for certificate hostname verification (unless one
2394 // was set explicitly, or addr is an IP literal)
2395 if (verifyHostName.empty() && addr && (inet_addr(addr) == INADDR_NONE))
2396 verifyHostName = addr;
2397 return connect(location = GETIPADDRESSPORT(address, port), timeoutMS, receiver);
2398 #else // _USE_SSL_
2399 return false;
2400 #endif // _USE_SSL_
2401}
2402
2403bool SSLConnection::connect(const uint32* addresses, uint16 addressCount, uint16 port, uint64& location, uint32 timeoutMS, NetworkDataReceiver* receiver) {
2404 #ifdef _USE_SSL_
2405 // Try all addresses
2406 for (uint16 n=0; n<addressCount; n++) {
2407 if (connect(location = GETIPADDRESSPORT(addresses[n], port), timeoutMS, receiver))
2408 return true;
2409 }
2410 return false;
2411 #else // _USE_SSL_
2412 return false;
2413 #endif // _USE_SSL_
2414}
2415
2416bool SSLConnection::delayedConnect(uint64 addr, uint32 timeoutMS, NetworkDataReceiver* receiver) {
2417 #ifdef _USE_SSL_
2418 mutex.enter(1000);
2419
2420 connectTimeoutMS = timeoutMS;
2421 remoteAddress = addr;
2422 remote = false;
2423
2424 if (receiver != NULL) {
2425 this->receiver = receiver;
2426 // Start networking thread
2428 LogPrint(0, LOG_NETWORK, 0, "Could not start SSLConnection thread...");
2429 mutex.leave();
2430 return false;
2431 }
2432 }
2433
2434 mutex.leave();
2435 return true;
2436 #else // _USE_SSL_
2437 return false;
2438 #endif // _USE_SSL_
2439}
2440
2441bool SSLConnection::delayedConnect(const char* addr, uint16 port, uint64& location, uint32 timeoutMS, NetworkDataReceiver* receiver) {
2442 #ifdef _USE_SSL_
2443 // Resolve address
2444 uint32 address;
2445 if (!utils::LookupIPAddress(addr, address))
2446 return false;
2447 // Record the hostname for certificate hostname verification (unless one
2448 // was set explicitly, or addr is an IP literal)
2449 if (verifyHostName.empty() && addr && (inet_addr(addr) == INADDR_NONE))
2450 verifyHostName = addr;
2451 return delayedConnect(location = GETIPADDRESSPORT(address, port), timeoutMS, receiver);
2452 #else // _USE_SSL_
2453 return false;
2454 #endif // _USE_SSL_
2455}
2456
2457bool SSLConnection::send(const char* data, uint32 size, uint64 receiver) {
2458 #ifdef _USE_SSL_
2459 if (!size)
2460 return false;
2461 // Ignore receiver, only for UDP
2462 if (!sendMutex.enter(500))
2463 return false;
2464 if (!ssl) {
2465 sendMutex.leave();
2466 return false;
2467 }
2468 uint64 start = GetTimeNow();
2469 //utils::SetSocketBlockingMode(socket);
2470
2471 int ret;
2472 while ( (ret = SSL_write(ssl, data, size)) <= 0) {
2473 switch (SSL_get_error(ssl, ret)) {
2474 case SSL_ERROR_WANT_READ:
2476 break;
2477 case SSL_ERROR_WANT_WRITE:
2479 break;
2480 default:
2481 sendMutex.leave();
2483 return false;
2484 }
2485 }
2486
2487 if (ret < (int)size) {
2488 sendMutex.leave();
2490 return false;
2491 }
2493 //utils::SetSocketNonBlockingMode(socket);
2494
2495 int64 t = GetTimeAge(start);
2496 if (t > 0)
2497 outputSpeed = (uint32)(size*1000000.0/(double)t);
2498 outputBytes += size;
2499 sendMutex.leave();
2500
2501 #ifdef TCPCON_PRINT_DEBUG
2502 if (size < 1024) {
2503 char* tmp = new char[size+1];
2504 memcpy(tmp, data, size);
2505 tmp[size] = 0;
2506 LogPrint(0,LOG_NETWORK,0,">>>>>>> SEND >>>>>>>> SSL Sent %u bytes '%s'\n", size, tmp);
2507 delete [] tmp;
2508 }
2509 else {
2510 #ifdef TCPCON_PRINTBINARY_DEBUG
2511 char* tmp = new char[size+1];
2512 memcpy(tmp, data, size);
2513 tmp[size] = 0;
2514 LogPrint(0,LOG_NETWORK,0,">>>>>>> SEND >>>>>>>> SSL Sent %u bytes '%s'\n", size, tmp);
2515 delete [] tmp;
2516 #endif
2517 }
2518 #endif
2519 return true;
2520 #else // _USE_SSL_
2521 return false;
2522 #endif // _USE_SSL_
2523}
2524
2525
2526
2527bool SSLConnection::reconnect(uint32 timeoutMS) {
2528 #ifdef _USE_SSL_
2529 disconnect();
2530 return connect(remoteAddress, timeoutMS, receiver);
2531 #else // _USE_SSL_
2532 return false;
2533 #endif // _USE_SSL_
2534}
2535
2536
2538
2539 if (socket == INVALID_SOCKET)
2540 return false;
2541
2542 struct sockaddr_in remoteAddr;
2543
2544 #ifdef WINDOWS
2545 int remoteAddrLen;
2546 #else
2547 #ifdef Darwin
2548 #if GCC_VERSION < 40000
2549 int remoteAddrLen;
2550 #else
2551 socklen_t remoteAddrLen;
2552 #endif // GCC_VERSION < 40000
2553 #else
2554 socklen_t remoteAddrLen;
2555 #endif
2556 #endif // WINDOWS
2557
2558 remoteAddrLen = sizeof(struct sockaddr_in);
2559
2560 if (getpeername(socket, (struct sockaddr*) &remoteAddr, &remoteAddrLen) != 0)
2561 return false;
2562
2563 uint32 address = remoteAddr.sin_addr.s_addr;
2564 if ( address == LOCALHOSTIP ) {
2565 // Get the actual local ip address, if possible
2566 utils::GetLocalIPAddress(address);
2567 }
2568 addr = GETIPADDRESSPORT(address, (uint16)remoteAddr.sin_port);
2569 return true;
2570}
2571
2573 #ifdef _USE_SSL_
2574 mutex.enter(1000);
2575 if (!ssl) {
2576 mutex.leave();
2577 return -1;
2578 }
2579 // and read from the socket
2580 // int count = ::recvfrom(socket,buffer+bufferContentLen,bufferLen-bufferContentLen,MSG_PEEK,NULL,0);
2581 int count = SSL_pending(ssl);
2582 mutex.leave();
2583 return count;
2584 #else // _USE_SSL_
2585 return -1;
2586 #endif // _USE_SSL_
2587}
2588
2590
2591 // Assume that the mutex is locked
2592
2593 #ifdef _USE_SSL_
2594
2595 if (!ssl)
2596 return -1;
2597
2598 int32 count = 0;
2599 int pending = SSL_pending(ssl);
2600 if (pending <= 0)
2601 return 0;
2602
2603 // Check for buffer resize
2604 if ((int32)bufferLen-(int32)bufferContentLen < pending) {
2605 if ((int32)bufferLen-(int32)bufferContentLen + (int32)bufferContentPos > pending) {
2608 bufferContentPos = 0;
2609 }
2610 else
2612 }
2613
2614 // Read pending bytes from the socket
2615 count = SSL_read(ssl, buffer+bufferContentLen, pending);
2616
2617 if (count < 0)
2618 return 0;
2619 else if (count == 0) {
2621 return -1;
2622 }
2623
2624 #ifdef TCPCON_PRINT_DEBUG
2625 char* tmp = new char[count+1];
2626 memcpy(tmp, buffer+bufferContentLen, count);
2627 tmp[count] = 0;
2628 LogPrint(0,LOG_NETWORK,0,"<<<<<<< SSL READINTOBUFFER <<<<<<<< TCP RECV BUF %u bytes '%s'\n", count, tmp);
2629 delete [] tmp;
2630 #endif
2631
2632 bufferContentLen += count;
2633
2634 return count;
2635 #else // _USE_SSL_
2636 return -1;
2637 #endif // _USE_SSL_
2638}
2639
2640bool SSLConnection::receiveAvailable(char* data, uint32& size, uint32 maxSize, uint32 timeout, bool peek) {
2641
2642 #ifdef _USE_SSL_
2643 mutex.enter(1000);
2644
2645 if (!ssl) {
2646 mutex.leave();
2647 return false;
2648 }
2649
2651 if (bufferContentPos > maxSize) {
2654 bufferContentPos = 0;
2655 }
2656 else
2657 resizeBuffer((bufferLen+maxSize) * 2);
2658 }
2659
2660 uint64 start = GetTimeNow(), timespent;
2661
2662 int count, err, timeleft;
2663 // Do we have enough data in the buffer already
2664 while (bufferContentLen - bufferContentPos < maxSize) {
2665 // and read from the socket
2666 count = SSL_read(ssl,buffer+bufferContentLen,bufferLen-bufferContentLen);
2667 if(count <= 0) {
2668 err = SSL_get_error(ssl, count);
2669 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
2670 }
2671 else {
2672 mutex.leave();
2674 return false;
2675 }
2676 }
2677 else if (count > 0) {
2678 #ifdef TCPCON_PRINT_DEBUG
2679 char* tmp = new char[count+1];
2680 memcpy(tmp, buffer+bufferContentLen, count);
2681 tmp[count] = 0;
2682 LogPrint(0,LOG_NETWORK,0,"<<<<<<< RECEIVE <<<<<<<< TCP RECV AVAIL %u bytes '%s'\n", count, tmp);
2683 delete [] tmp;
2684 #endif
2685 bufferContentLen += count;
2686 if (bufferContentLen - bufferContentPos >= maxSize)
2687 break;
2688 }
2689 if ((timespent = (GetTimeNow() - start)/1000) >= timeout) {
2690 // if (timeout > 0)
2691 // printf("**** TCP::receive available %u ***\n", bufferContentLen - bufferContentPos);
2692 break;
2693 }
2694 else {
2695 mutex.leave();
2696 timeleft = (int)(timeout-timespent);
2697 utils::WaitForSocketReadability(socket, timeleft < 50 ? timeleft : 50);
2698 }
2699 mutex.enter(1000);
2700 }
2701
2703 if (size > maxSize)
2704 size = maxSize;
2705
2706 inputBytes += size;
2707 if ( size > 0 ) {
2708 memcpy(data, buffer+bufferContentPos, size);
2709 if (!peek) {
2710 bufferContentPos += size;
2713 }
2714 }
2715 mutex.leave();
2716 return true;
2717 #else // _USE_SSL_
2718 return false;
2719 #endif // _USE_SSL_
2720}
2721
2722bool SSLConnection::receive(char* data, uint32 size, uint32 timeout, bool peek) {
2723
2724 #ifdef _USE_SSL_
2725 mutex.enter(1000);
2726
2727 if (!ssl) {
2728 mutex.leave();
2729 return false;
2730 }
2731
2733 if (bufferContentPos > size) {
2736 bufferContentPos = 0;
2737 }
2738 else
2739 resizeBuffer((bufferLen+size) * 2);
2740 }
2741
2742 uint64 start = GetTimeNow();
2743 int32 timespent;
2744
2745 int count, err, timeleft;
2746 // Do we have enough data in the buffer already
2747 while (bufferContentLen - bufferContentPos < size) {
2748 if (!ssl) {
2749 mutex.leave();
2750 return false;
2751 }
2752
2753 // and read from the socket
2754
2755 // int count = ::recvfrom(socket,buffer+bufferContentLen,bufferLen-bufferContentLen,0,NULL,0);
2756
2757 count = SSL_read((SSL *)ssl, buffer+bufferContentLen,size);
2758
2759 if(count <= 0) {
2760 err = SSL_get_error(ssl, count);
2761 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
2762 }
2763 else {
2764 mutex.leave();
2766 return false;
2767 }
2768 }
2769 else if (count > 0) {
2770 #ifdef TCPCON_PRINTBINARY_DEBUG
2771 char* tmp = new char[count+1];
2772 memcpy(tmp, buffer+bufferContentLen, count);
2773 tmp[count] = 0;
2774 LogPrint(0,LOG_NETWORK,0,"<<<<<<<< RECEIVE <<<<<<< TCP RECV %u bytes '%s'", count, tmp);
2775 delete [] tmp;
2776 #endif
2777 bufferContentLen += count;
2778 if (bufferContentLen - bufferContentPos >= size)
2779 break;
2780 }
2781 if ((timespent = GetTimeAgeMS(start)) >= (int32)timeout) {
2782 // printf("**** TCP::receive only got %u out of %u bytes ***\n", bufferContentLen - bufferContentPos, size);
2783 mutex.leave();
2784 return false;
2785 }
2786 else {
2787 //utils::Sleep(5);
2788 //uint64 t = GetTimeNow();
2789 mutex.leave();
2790 timeleft = (int)(timeout-timespent);
2791 utils::WaitForSocketReadability(socket, timeleft < 50 ? timeleft : 50);
2792 //printf("WaitForRead: %lu (%lu)\n", GetTimeAgeMS(t), timeout-timespent);
2793 }
2794 mutex.enter(1000);
2795 }
2796
2797 int64 t = GetTimeAge(start);
2798 if (t > 0)
2799 inputSpeed = (uint32)(size*1000000.0/(double)t);
2800 inputBytes += size;
2801
2802 memcpy(data, buffer+bufferContentPos, size);
2803 if (!peek) {
2804 bufferContentPos += size;
2807 }
2808 mutex.leave();
2809 return true;
2810 #else // _USE_SSL_
2811 return false;
2812 #endif // _USE_SSL_
2813}
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2825 if (arg == NULL) thread_ret_val(1);
2826 thread_ret_val((int)(((TCPListener*)arg)->run() ? 0 : 1));
2827}
2828
2830 if (arg == NULL) thread_ret_val(1);
2831 thread_ret_val((int)(((TCPConnection*)arg)->run() ? 0 : 1));
2832}
2833
2835 if (arg == NULL) thread_ret_val(1);
2836 thread_ret_val((int)(((UDPConnection*)arg)->run() ? 0 : 1));
2837}
2838
2840 if (arg == NULL) thread_ret_val(1);
2841 thread_ret_val((int)(((SSLConnection*)arg)->run() ? 0 : 1));
2842}
2843
2844
2845
2846bool NetworkTest_TCPServer(uint16 port, uint32 count2) {
2847 uint32 period = 100000;
2848
2849 TCPListener* listener = new TCPListener();
2850 if (!listener->init(port, NOENC)) {
2851 delete(listener);
2852 printf("Could not bind to port %u, exiting... \n\n", port);
2853 return false;
2854 }
2855
2856 char* startdata = new char[12], *data;
2857 uint32 size, count;
2858 NetworkConnection* con;
2859 uint32 c = 0;
2860 while (true) {
2861 c = 0;
2862 printf("\n\nListening to port %u for a new connection... ", port);
2863 while ( (con = listener->acceptConnection(10000)) == NULL) {}
2864
2865 while (con->isConnected()) {
2866 // Reading count and size
2867 if (!con->receive(startdata, 12, 10000)) {
2868 printf("[%u] Could not receive start data, exiting...\n", c);
2869 break;
2870 }
2871 if ((*(uint32*)startdata) != 123456789) {
2872 printf("[%u] Start data wrong, exiting...\n", c);
2873 break;
2874 }
2875 size = *(((uint32*)startdata)+1);
2876 count = *(((uint32*)startdata)+2);
2877 c = 0;
2878 data = new char[size];
2879
2880 printf("Got it - starting test with size %u and count %u...\n\n", size, count);
2881
2882 while (con->isConnected() && (c++ < count) ) {
2883 if (!con->receive(data, size, 10000)) {
2884 printf("[%u] Could not receive data %u, exiting...\n", port, c);
2885 break;
2886 }
2887 if (!con->send(data, size)) {
2888 printf("[%u] Could not send data %u, exiting...\n", port, c);
2889 break;
2890 }
2891 }
2892 delete [] data;
2893 }
2894 delete(con);
2895
2896
2897 //while (con->isConnected()) {
2898 // t1 = GetTimeNow();
2899 // if (!NetworkTest_SendReceiveData(con, data, dataLen, c, true)) {
2900 // delete(con);
2901 // break;
2902 // }
2903 // t2 = GetTimeNow();
2904 // d += t2-t1;
2905 // if ((c > 0) && (c % period == 0)) {
2906 // printf("Round time: %.3f us...\n", (double)d/period);
2907 // d = 0;
2908 // }
2909 // c++;
2910 // if ( (count > 0) && (c > count) ) {
2911 // delete(con);
2912 // delete(listener);
2913 // return true;;
2914 // }
2915 //}
2916
2917 }
2918 delete [] startdata;
2919 return true;
2920}
2921
2922
2923bool NetworkTest_TCPClient(const char* address, uint16 port, uint32 count2) {
2924 TCPConnection* con = new TCPConnection();
2925 uint64 location;
2926 if (!con->connect(address, port, location, 5000)) {
2927 delete(con);
2928 printf("Could not connect to '%s' on port %u, exiting...\n", address, port);
2929 return false;
2930 }
2931 printf("Connected to '%s' on port %u, starting test...\n", address, port);
2932
2933 char* startdata = new char[12];
2934 memset(startdata, 0, 12);
2935 *((uint32*)startdata) = 123456789;
2936
2937 uint32 maxSize = 1024*64, innercount = 20, count = 1000, steps = 64, s, c, step;
2938 char* data = new char[maxSize];
2939 double* vals = new double[count];
2940 double* avgvals = new double[steps];
2941 double* maxvals = new double[steps];
2942 double* minvals = new double[steps];
2943 double* stdvals = new double[steps];
2944 double sum, avg, mx, mn, std;
2945
2946 uint64 t1, t2;
2947
2948 while (con->isConnected()) {
2949
2950 for (step=0; step<steps; step++) {
2951 s = (maxSize/steps*(step+1));
2952 *(((uint32*)startdata)+1) = s;
2953 *(((uint32*)startdata)+2) = count * innercount;
2954 if (!con->send(startdata, 12)) {
2955 printf("[%u] Could not send startdata, exiting...\n", port);
2956 break;
2957 }
2958 printf("Step %u size %u...\n", step, s);
2959 for (c=0; c<count; c++) {
2960 t1 = GetTimeNow();
2961 for (uint32 i=0; i<innercount; i++) {
2962 if (!con->send(data, s)) {
2963 printf("[%u] Could not send data %u, exiting...\n", port, c);
2964 break;
2965 }
2966 if (!con->receive(data, s, 10000)) {
2967 printf("[%u] Could not receive data %u, exiting...\n", port, c);
2968 break;
2969 }
2970 }
2971 t2 = GetTimeNow();
2972 vals[c] = (t2-t1)/(double)innercount;
2973 }
2974
2975 sum = avg = std = 0;
2976 mx = mn = vals[0];
2977 for (c=0; c<count; c++) {
2978 sum += vals[c];
2979 if (vals[c] > mx) mx = vals[c];
2980 if (vals[c] < mn) mn = vals[c];
2981 }
2982 avg = sum/count;
2983
2984 sum = 0;
2985 for (c=0; c<count; c++)
2986 sum += pow((vals[c] - avg), 2);
2987 std = sqrt(sum/count-1);
2988
2989 avgvals[step] = avg;
2990 maxvals[step] = mx;
2991 minvals[step] = mn;
2992 stdvals[step] = std;
2993 }
2994
2995 printf("Test results (size, avg, min, max, std in us):\n");
2996 for (step=0; step<steps; step++) {
2997 s = (maxSize/steps*(step+1));
2998 printf("%u %u %.3f %.3f %.3f %.3f\n",
2999 step, s, avgvals[step], minvals[step], maxvals[step], stdvals[step]);
3000 }
3001
3002 break;
3003 }
3004
3005 delete [] startdata;
3006 delete [] data;
3007 delete [] vals;
3008 delete [] avgvals;
3009 delete [] maxvals;
3010 delete [] minvals;
3011 delete [] stdvals;
3012
3013
3014
3015
3016// strcpy(data+(2*sizeof(uint32)), "Testing");
3017
3018// utils::PrintBinary(data, dataLen, true, "Initial Structure");
3019
3020// uint32 c = 0;
3021// uint64 t1, t2, d = 0;
3022
3023
3024
3025
3026
3027
3028 //while (con->isConnected()) {
3029 // t1 = GetTimeNow();
3030 // if (!NetworkTest_SendReceiveData(con, data, dataLen, c)) {
3031 // delete(con);
3032 // return false;
3033 // }
3034 // t2 = GetTimeNow();
3035 // d += t2-t1;
3036 // if ((c > 0) && (c % period == 0)) {
3037 // printf("Round time: %.3f us...\n", (double)d/period);
3038 // d = 0;
3039 // }
3040 // c++;
3041 // if ( (count > 0) && (c > count) )
3042 // break;
3043 //}
3044 delete(con);
3045 return true;
3046}
3047
3048bool NetworkTest_SendReceiveData(TCPConnection* con, char* data, uint32 dataLen, uint32 c, bool receiveFirst) {
3049
3050 uint32 expectC = c*2;
3051 if (!receiveFirst) {
3052 expectC++;
3053 // Send data
3054 if (!con->send(data, dataLen)) {
3055 printf("[%u] Could not send data, exiting...\n", c);
3056 return false;
3057 }
3058 //utils::PrintBinary(data, dataLen, true, "Send1");
3059 }
3060
3061 memset(data, 0, dataLen);
3062 // Wait for reply data
3063 if (!con->receive(data, dataLen, 10000)) {
3064 printf("[%u] Could not receive data, exiting...\n", c);
3065 return false;
3066 }
3067 //utils::PrintBinary(data, dataLen, true, "Receive");
3068 // Check reply data
3069 if (*(uint32*)data != dataLen) {
3070 printf("[%u] Did not receive correct length (%u != %u), exiting...\n", c, *(uint32*)data, dataLen);
3071 // utils::PrintBinary(data, dataLen, true, "Structure");
3072 return false;
3073 }
3074 // Check reply data
3075 if (*((uint32*)data+1) != expectC) {
3076 printf("[%u] Did not receive correct count (%u != %u), exiting...\n", c, *((uint32*)data+1), expectC);
3077 // utils::PrintBinary(data, dataLen, true, "Structure");
3078 return false;
3079 }
3080 // Check reply data
3081 if (strcmp(data+(2*sizeof(uint32)), "Testing") != 0) {
3082 data[dataLen-1] = 0;
3083 printf("[%u] Did not receive correct text ('%s' != 'Testing'), exiting...\n", c, data+(2*sizeof(uint32)));
3084 // utils::PrintBinary(data, dataLen, true, "Structure");
3085 return false;
3086 }
3087 *((uint32*)data+1) = *((uint32*)data+1) + 1;
3088
3089// printf("[%u] Receive OK\n", c);
3090 if (receiveFirst) {
3091 // Send data
3092 if (!con->send(data, dataLen)) {
3093 printf("[%u] Could not send data, exiting...\n", c);
3094 return false;
3095 }
3096 //utils::PrintBinary(data, dataLen, true, "Send2");
3097 }
3098 return true;
3099}
3100
3101
3102}
Raw socket transport layer: TCP/UDP/SSL connections and TCP listeners with buffered,...
#define SSLCON
SSL/TLS-encrypted TCP connection.
#define AESENC
AES encryption (reserved; not currently implemented).
#define NETWORKERROR_SEND_TIMEOUT
A write could not complete within the timeout.
#define NETWORKERROR_RECEIVE
A read from the socket failed (peer closed or socket error).
#define TCPCON
Plain TCP stream connection.
#define UDPCON
UDP datagram connection.
#define NETWORKERROR_ACCEPT
accept() failed on a listener socket.
#define NOENC
Plain, unencrypted transport.
#define SSLENC
SSL/TLS encryption (requires build with _USE_SSL_).
#define NETWORKERROR_SEND_ERROR
A write to the socket failed.
#define INITIALBUFFERSIZE
Initial size in bytes of a connection's internal receive buffer; it grows on demand via NetworkConnec...
#define NETWORKERROR_MEMORYFULL
The receive buffer could not grow to hold incoming data.
#define GETIPADDRESSQUAD(a)
Definition Utils.h:1649
#define SD_BOTH
Definition Utils.h:151
#define thread_ret_val(ret)
Definition Utils.h:131
#define INVALID_SOCKET
Definition Utils.h:137
#define CHECKNETWORKINIT
Definition Utils.h:1583
#define closesocket(X)
Definition Utils.h:138
#define SOCKETWOULDBLOCK
Definition Utils.h:139
#define THREAD_RET
Definition Utils.h:127
#define LOCALHOSTIP
Definition Utils.h:1642
#define THREAD_FUNCTION_CALL
Definition Utils.h:129
#define SOCKET_ERROR
Definition Utils.h:136
#define LogPrint
Definition Utils.h:313
#define SOCKETTRYAGAIN
Definition Utils.h:140
#define LOG_NETWORK
Definition Utils.h:198
#define GETIPADDRESSPORT(a, p)
Definition Utils.h:1648
struct sockaddr SOCKADDR
Definition Utils.h:135
#define GETIPPORT(a)
Definition Utils.h:1646
#define THREAD_ARG
Definition Utils.h:130
#define SOCKET
Definition Utils.h:134
Abstract base class for all point-to-point network connections.
virtual bool send(const char *data, uint32 size, uint64 receiver=0)=0
Send raw bytes on the connection.
virtual uint32 clearBuffer()
Discard all currently buffered input.
NetworkDataReceiver * receiver
virtual bool waitForDataToBeWritten(uint32 timeout)
Block until the socket is writable.
bool setConnectTimeout(uint32 timeoutMS)
Set the timeout used by subsequent connect()/reconnect() attempts.
virtual bool receiveAvailable(char *data, uint32 &size, uint32 maxSize, uint32 timeout, bool peek=false)
Receive whatever bytes are available (up to maxSize).
virtual bool receive(char *data, uint32 size, uint32 timeout, bool peek=false)
Receive exactly size bytes into data, waiting up to timeout ms.
virtual bool disconnect(uint16 error=0)
Close the connection and release the socket.
virtual bool waitForDataToRead(uint32 timeout)
Block until data is readable (buffered or on the socket).
char * greetingData
Owned copy of the greeting bytes (NULL if unset).
void disconnectInternal(uint16 error)
virtual bool resizeBuffer(uint32 len)
virtual bool discard(uint32 size)
Drop size bytes from the front of the receive buffer (after a peek).
virtual bool didConnect(int timeout=0)
Check/complete an in-progress (delayed) connect on the existing socket.
virtual bool isConnected(int timeout=0)
Test whether the connection is currently alive.
bool setGreetingData(const char *data, uint32 size)
Set greeting bytes sent automatically right after a connection is established (used e....
uint32 greetingSize
Size of greetingData in bytes.
Callback interface for asynchronous delivery of newly accepted connections.
virtual bool registerError(uint16 error, TCPListener *con)=0
Called when the listener encounters an error.
virtual bool receiveNetworkConnection(NetworkConnection *con)=0
Called when the listener has accepted a new connection.
Callback interface for asynchronous (push) delivery of received bytes.
bool isRunning
Set by the worker while its loop is active.
virtual bool stop(uint32 timeout=200)
Ask the worker loop to finish and wait for it to do so.
uint32 threadID
ThreadManager slot ID of the worker thread (0 until known).
bool shouldContinue
Loop-continuation flag; cleared by stop().
SSL/TLS-encrypted TCP connection (OpenSSL) with configurable peer verification.
static std::string DefaultCAFile
bool isConnected(int timeout=0)
Test whether the connection is currently alive.
bool receiveAvailable(char *data, uint32 &size, uint32 maxSize, uint32 timeout, bool peek=false)
Receive whatever bytes are available (up to maxSize).
bool init()
Initialise the OpenSSL context for a client-side connection.
bool findRemoteAddress(uint64 &addr)
bool didConnect(int timeout=0)
Check/complete an in-progress (delayed) connect on the existing socket.
std::string certinfo
Human-readable summary of the peer certificate (subject/issuer), filled after handshake.
void setCALocation(const char *caFile, const char *caPath)
static std::string DefaultCAPath
void setVerifyHostName(const char *host)
friend THREAD_RET THREAD_FUNCTION_CALL SSLConnectionRun(THREAD_ARG arg)
bool disconnect(uint16 error=0)
Shut down the TLS session and close the socket.
bool receive(char *data, uint32 size, uint32 timeout, bool peek=false)
Receive exactly size bytes into data, waiting up to timeout ms.
bool send(const char *data, uint32 size, uint64 receiver=0)
Send bytes over the encrypted stream.
bool connect(SOCKET s, uint64 localAddr, NetworkDataReceiver *receiver=NULL)
Adopt an already-accepted socket and perform the server-side TLS handshake.
static bool GetDefaultAllowSelfSigned()
void setAllowSelfSigned(bool allow)
int32 peekStream()
Peek how many decrypted bytes are pending inside the SSL layer.
bool reconnect(uint32 timeoutMS)
Reconnect and re-handshake to the previous endpoint.
static void SetDefaultCALocation(const char *caFile, const char *caPath)
static void SetDefaultAllowSelfSigned(bool allow)
bool delayedConnect(uint64 addr, uint32 timeoutMS, NetworkDataReceiver *receiver)
Begin a non-blocking connect (TLS handshake completes in didConnect()).
int32 readIntoBuffer()
Read decrypted bytes from the SSL layer into the internal buffer.
Plain TCP stream connection (client-initiated or accepted from a listener).
friend THREAD_RET THREAD_FUNCTION_CALL TCPConnectionRun(THREAD_ARG arg)
Thread entry point for a TCPConnection's push-mode reader loop.
bool findRemoteAddress(uint64 &addr)
Query the OS for the peer address of the connected socket.
bool send(const char *data, uint32 size, uint64 receiver=0)
Send bytes on the stream (see NetworkConnection::send()).
bool connect(SOCKET s, uint64 localAddr, NetworkDataReceiver *receiver=NULL)
Adopt an already-connected socket (server side, from a TCPListener).
bool delayedConnect(uint64 addr, uint32 timeoutMS, NetworkDataReceiver *receiver)
Begin a non-blocking connect; completion is checked with didConnect().
bool reconnect(uint32 timeoutMS)
Reconnect to the previously resolved remote endpoint.
TCP server socket: binds a port and accepts inbound connections (plain or SSL).
friend THREAD_RET THREAD_FUNCTION_CALL TCPListenerRun(THREAD_ARG arg)
Thread entry point for a TCPListener's internal accept loop.
NetworkConnection * acceptConnection(uint32 timeout)
Synchronously wait for and accept one inbound connection.
bool setSSLCertificate(const char *sslCertPath, const char *sslKeyPath)
Set the SSL certificate and private key used for inbound SSL connections.
bool disconnect(uint16 error=0)
Stop listening and close the socket.
bool init(uint16 port, uint8 encryption, NetworkConnectionReceiver *receiver=NULL, NetworkDataReceiver *dataReceiver=NULL)
Bind and start listening on a port.
static bool CreateThread(THREAD_FUNCTION func, void *args, uint32 &newID, uint32 reqID=0)
Create a new native thread and start it immediately.
bool initForOutputOnly()
Create an unbound socket usable only for sending datagrams.
bool reconnect(uint32 timeoutMS)
Rebind the local port (UDP has no session to re-establish).
bool send(const char *data, uint32 size, uint64 receiver=0)
Send one datagram.
bool connect(uint16 port, NetworkDataReceiver *receiver=NULL)
Bind a local UDP port for receiving datagrams.
uint64 defaultReceiver
Default destination endpoint for send() when none is given.
friend THREAD_RET THREAD_FUNCTION_CALL UDPConnectionRun(THREAD_ARG arg)
Thread entry point for a UDPConnection's push-mode reader loop.
bool setDefaultReceiver(uint64 receiver)
Set the default destination used by send() when receiver == 0.
THREAD_RET THREAD_FUNCTION_CALL TCPListenerRun(THREAD_ARG arg)
Thread entry point for a TCPListener's internal accept loop.
bool NetworkTest_TCPClient(const char *address, uint16 port, uint32 count=0)
Loopback test client matching NetworkTest_TCPServer().
THREAD_RET THREAD_FUNCTION_CALL UDPConnectionRun(THREAD_ARG arg)
Thread entry point for a UDPConnection's push-mode reader loop.
bool NetworkTest_TCPServer(uint16 port, uint32 count=0)
Loopback test server: listens on port and echoes test payloads.
THREAD_RET THREAD_FUNCTION_CALL TCPConnectionRun(THREAD_ARG arg)
Thread entry point for a TCPConnection's push-mode reader loop.
bool NetworkTest_SendReceiveData(TCPConnection *con, char *data, uint32 dataLen, uint32 c, bool receiveFirst=false)
Send-and-verify helper used by the TCP tests.
uint64 GetTimeNow()
Return the current absolute time (µs since year 0) according to the TMC.
Definition PsyTime.cpp:69
int32 GetTimeAgeMS(uint64 t)
Age of a timestamp relative to now, in milliseconds.
Definition PsyTime.cpp:35
int64 GetTimeAge(uint64 t)
Age of a timestamp relative to now.
Definition PsyTime.cpp:25
bool Sleep(uint32 ms)
Suspend the calling thread.
Definition Utils.cpp:3121
const char * stristr(const char *str, const char *substr, uint32 len=0)
Case-insensitive strstr.
Definition Utils.cpp:7476
int GetLastOSErrorNumber()
Get the last OS error number (errno / GetLastError()).
Definition Utils.cpp:6668
bool WaitForSocketReadability(SOCKET s, int32 timeout)
Wait until a socket has data to read.
Definition Utils.cpp:6726
bool WaitForSocketWriteability(SOCKET s, int32 timeout)
Wait until a socket can be written without blocking.
Definition Utils.cpp:6694
bool GetLocalIPAddress(uint32 &address)
Get the primary local IPv4 address.
Definition Utils.cpp:7048
bool LookupIPAddress(const char *name, uint32 &address)
Resolve a hostname to an IPv4 address.
Definition Utils.cpp:6787
bool SetSocketNonBlockingMode(SOCKET s)
Put a socket into non-blocking mode.
Definition Utils.cpp:6763
THREAD_RET THREAD_FUNCTION_CALL SSLConnectionRun(THREAD_ARG arg)
bool AESCheckBufferForCompatibility(const char *buffer, uint32 length)
bool SSLCheckBufferForCompatibility(const char *buffer, uint32 length)
STL namespace.