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}
328
330 //printf("~NetworkConnection(%p)\n", this); fflush(stdout);
331 disconnect();
332 localAddress = 0;
333 remoteAddress = 0;
334 threadID = 0;
335 lastActivity = 0;
337 remote = false;
338 if (buffer != NULL)
339 delete(buffer);
340 bufferLen = 0;
343 receiver = NULL;
344 buffer = NULL;
345 if (greetingData)
346 delete greetingData;
347 greetingData = NULL;
348 greetingSize = 0;
349}
350
351bool NetworkConnection::setGreetingData(const char* data, uint32 size) {
352 if (greetingData)
353 delete greetingData;
354 if (!data)
355 greetingData = NULL;
356 else {
357 greetingData = new char[size];
358 memcpy(greetingData, data, size);
359 }
360 greetingSize = size;
361 return true;
362}
363
364
366 connectTimeoutMS = timeoutMS;
367 return true;
368}
369
373
375 return remote;
376}
377
379 LogPrint(0, LOG_NETWORK, 5, "Shutting down network connection with code: %u", error);
380 stop();
381 if (socket != INVALID_SOCKET) {
382 shutdown(socket, SD_BOTH);
383 try {
385 }
386 catch (...) {}
388 }
389 // NOTE: do NOT clear bufferContentLen/Pos here - a peer that closes right
390 // after replying (HTTP Connection: close) must not wipe the buffered reply.
391 if (receiver && error)
392 receiver->registerError(error, this);
393}
394
396 mutex.enter(1000);
397 disconnectInternal(error);
398 mutex.leave();
399 return true;
400}
401
403 if (len < 128) return false;
404 char* newBuffer = new char[len];
409 }
410 else {
413 }
414
415 if (buffer != NULL)
416 delete [] buffer;
417 bufferLen = len;
418 buffer = newBuffer;
419 return true;
420}
421
422//int32 NetworkConnection::peekStream() {
423//
424// mutex.enter();
425//
426// // and read from the socket
427// int count = ::recvfrom(socket,buffer+bufferContentLen,bufferLen-bufferContentLen,MSG_PEEK,NULL,0);
428// if(count==SOCKET_ERROR) {
429// int err = utils::GetLastOSErrorNumber();
430// mutex.leave();
431// if ( (err == SOCKETWOULDBLOCK) || (err == SOCKETTRYAGAIN) )
432// return 0;
433// else {
434// disconnect(NETWORKERROR_RECEIVE);
435// return -1;
436// }
437// }
438// mutex.leave();
439// return count;
440//}
441
443
444 // Assume that the mutex is locked
445 // LogPrint(0,0,0,"<<<<<<< READINTOBUFFER <<<<<<<<\n");
446
447#ifdef TCPCON_PRINT_DEBUG
448 uint64 start = GetTimeNow();
449#endif
450 int c = 0;
451 int32 count = 0;
452 // The socket is put in non-blocking mode once at connect/accept and is never
453 // flipped back (see TCPConnection::send), so we no longer re-set it here -
454 // that was two fcntl() syscalls on every read of the receive hot path.
455 // Read from the socket while data is still available
456 do {
457 //LogPrint(0,0,0,"<<<<<<< READINTOBUFFER RECVFROM start <<<<<<<<\n");
459 // c = ::recv(socket,buffer+bufferContentLen,bufferLen-bufferContentLen,0);
460 // LogPrint(0,0,0,"<<<<<<< READINTOBUFFER RECVFROM end %d <<<<<<<<\n", c);
461 if(c==SOCKET_ERROR) {
462 int err = utils::GetLastOSErrorNumber();
463 if ( (err == SOCKETWOULDBLOCK) || (err == SOCKETTRYAGAIN) )
464 break;
465 else {
466 #ifdef WINDOWS
467 if (err != WSAENOTSOCK)
468 #endif
470 return -1;
471 }
472 }
473 if (!c) {
474 bool dataAvailable = utils::WaitForSocketReadability(socket, (uint32)(10));
475 if (dataAvailable) {
476 // this indicates that the socket is in a CLOSE_WAIT state,
477 // i.e. the other end has closed the socket so we should too...
478 LogPrint(0, LOG_NETWORK, 2, "*** SOCKET DISCONNECT DETECTED ***\n");
480 }
481 }
482
483 if (c) {
484 //rounds++;
485 count += c;
486 bufferContentLen += c;
487
488 if (bufferLen-bufferContentLen < 512) {
490 //printf("x"); fflush(stdout);
494 }
495 else {
496 //printf("o"); fflush(stdout);
498 }
499 //resize++;
500 }
501 }
502 } while (c > 0);
503
504 #ifdef TCPCON_PRINT_DEBUG
505 if (this->type == TCPCON) {
506 if (count) {
507 char* tmp = new char[count+1];
508 memcpy(tmp, buffer+bufferContentLen-count, count);
509 tmp[count] = 0;
510 LogPrint(0,LOG_NETWORK,0,"<<<<<<< READINTOBUFFER <<<<<<<< TCP RECV BUF %d bytes '%s' (%.3fms) %d / %d\n", count, tmp, GetTimeAge(start)/1000.0, rounds, resize);
511 delete [] tmp;
512 }
513 else {
514 // LogPrint(0,LOG_NETWORK,0,"<<<<<<< READINTOBUFFER <<<<<<<< NOTHING\n");
515 }
516 }
517 #endif
518
519 #ifdef UDPCON_PRINT_DEBUG
520 if (this->type == UDPCON) {
521 if (count) {
522 char* tmp = new char[count+1];
523 memcpy(tmp, buffer+bufferContentLen-count, count);
524 tmp[count] = 0;
525 LogPrint(0,LOG_NETWORK,0,"<<<<<<< READINTOBUFFER <<<<<<<< UDP RECV BUF %u bytes '%s'\n", count, tmp);
526 delete [] tmp;
527 }
528 else {
529 // LogPrint(0,LOG_NETWORK,0,"<<<<<<< READINTOBUFFER <<<<<<<< UDP NOTHING\n");
530 }
531 }
532 #endif
533
534 return count;
535}
536
537bool NetworkConnection::receiveAvailable(char* data, uint32& size, uint32 maxSize, uint32 timeout, bool peek) {
538
539 mutex.enter(1000);
540 if (maxSize > bufferLen-bufferContentLen) {
541 if (bufferContentLen + bufferContentPos > maxSize) {
545 }
546 else
548 }
549
550 uint64 start = GetTimeNow();
551 uint32 count = 0;
552 bool dataAvailable;
553
554 int32 c = readIntoBuffer();
555 if (c < 0 && bufferContentLen - bufferContentPos == 0) {
556 mutex.leave();
557 return false;
558 }
559
560 if (timeout > 0) {
561
562 // Wait for full size to be available, if not already
563 int32 timespent = 0;
564 if (bufferContentLen - bufferContentPos < maxSize) {
565 while (true) {
566 mutex.leave();
567 dataAvailable = utils::WaitForSocketReadability(socket, (uint32)(timeout-timespent));
568 mutex.enter(1000);
569 if ((c = readIntoBuffer()) < 0) {
571 break; // connection gone, but serve what we already buffered
572 mutex.leave();
573 return false;
574 }
575 if (!c && dataAvailable) {
576 // this indicates that the socket is in a CLOSE_WAIT state,
577 // i.e. the other end has closed the socket so we should too...
578 LogPrint(0, LOG_NETWORK, 2, "*** SOCKET DISCONNECT DETECTED ***\n");
580 }
581 if (bufferContentLen - bufferContentPos >= maxSize)
582 break;
583 if ((timespent = GetTimeAgeMS(start)) >= (int32)timeout)
584 break;
585 }
586 }
587 }
588
590 if (size > maxSize)
591 size = maxSize;
592
593 inputBytes += size;
594 if ( size > 0 ) {
595 memcpy(data, buffer+bufferContentPos, size);
596 if (!peek) {
597 bufferContentPos += size;
600 }
601 }
602 mutex.leave();
603 return true;
604}
605
606bool NetworkConnection::receive(char* data, uint32 size, uint32 timeout, bool peek) {
607 // Exact-size, timeout-bounded read from the shared receive buffer. The
608 // buffer mutex makes this safe against the connection's reader thread;
609 // while more bytes are needed the mutex is RELEASED around the
610 // WaitForSocketReadability() select() so writers/other readers are not
611 // blocked for the whole timeout. With peek=true the bytes are copied but
612 // left in the buffer — protocol handlers use this to sniff frame headers
613 // (e.g. MessageProtocol peeks size+id before allocating the body buffer).
614
615 mutex.enter(1000);
616
617 uint64 start = GetTimeNow();
618
619 // Only read from the socket if we don't already have enough buffered. A single
620 // readIntoBuffer() drains everything currently available - often the whole
621 // message, or several pipelined messages, in one go - so the body read (and
622 // subsequent messages) are then served straight from the buffer with no
623 // recvfrom() syscall at all. Previously readIntoBuffer() ran on every receive()
624 // regardless, costing a wasted syscall per peek and per body read.
625 if (bufferContentLen - bufferContentPos < size) {
626 int32 c = readIntoBuffer();
627 if (c < 0) {
628 mutex.leave();
629 return false;
630 }
631
632 // Wait for the full size to be available, if not already.
633 int32 timespent = 0;
634 while (bufferContentLen - bufferContentPos < size) {
635 mutex.leave();
636 utils::WaitForSocketReadability(socket, (uint32)(timeout-timespent));
637 mutex.enter(1000);
638 if ((c = readIntoBuffer()) < 0) {
639 mutex.leave();
640 return false;
641 }
643 break;
644 if ((timespent = GetTimeAgeMS(start)) >= (int32)timeout) {
645 mutex.leave();
646 return false;
647 }
648 }
649 }
650
651 // LogPrint(0,LOG_NETWORK,0,"Receiving %u (buffer %u) bytes via network...", size, bufferContentLen - bufferContentPos);
652 //printf("**************** Buffer ok (%u, %u = %u->%u), left (%u), size (%u), next %u, %u ****************\n",
653 // bufferLen, bufferContentLen - bufferContentPos, bufferContentPos, bufferContentLen,
654 // bufferLen-bufferContentLen+bufferContentPos, size,
655 // *(uint32*)(buffer+bufferContentPos), *(uint32*)(buffer+bufferContentPos+4));
656
657 int64 t = GetTimeAge(start);
658 if (t > 0)
659 inputSpeed = (uint32)(size*1000000.0/(double)t);
660 inputBytes += size;
661
662 memcpy(data, buffer+bufferContentPos, size);
663 if (!peek) {
664 bufferContentPos += size;
667 }
668 mutex.leave();
669 return true;
670}
671
672bool NetworkConnection::discard(uint32 size) {
673 mutex.enter(1000);
675 if (bufferContentLen - bufferContentPos >= size) {
676 bufferContentPos += size;
679 inputBytes += size;
680 mutex.leave();
681 return true;
682 }
683 else {
684 mutex.leave();
685 return false;
686 }
687}
688
690 mutex.enter(1000);
693 if (c) {
694 LogPrint(0,LOG_NETWORK,3,"Cleared %u chars from buffer...", c);
695 // if (c > 1)
696 // utils::PrintBinary(buffer+bufferContentPos, c, false, "Cleared Buffer Content");
697 }
699 inputBytes += c;
700 mutex.leave();
701 return c;
702}
703
704
707 return true;
708 else {
710 }
711}
712
716
717
719
720 if (socket == INVALID_SOCKET)
721 return false;
722
723 char peekBuffer[1];
724 // First use the socket a bit
725 if (!mutex.enter(1000))
726 return false;
727
729 int res = recv(socket, peekBuffer, 1, MSG_PEEK);
730 if (res > 0) {
731 mutex.leave();
732 return true;
733 }
734 else if (res < 0) {
735 int err = utils::GetLastOSErrorNumber();
736 // UDP needs TRYAGAIN
737 if (err == SOCKETWOULDBLOCK) {
738 mutex.leave();
739 return true;
740 }
741
742 #ifdef WINDOWS
743 else if ((type == UDPCON) && (err == SOCKETTRYAGAIN)) {
744 mutex.leave();
745 return true;
746 }
747 else if (err == WSAENOTCONN) {} // Windows needs this one...
748 else if (err == WSAENOTSOCK) {} // Windows needs this one...
749 else if (err == WSAEOPNOTSUPP) {} // WinCE may need this one...???.
750 #else
751 else if (err == SOCKETTRYAGAIN) {
752 mutex.leave();
753 return true;
754 }
755 #endif //WINDOWS
756 else {
757 // Error will be handled by the caller
759 mutex.leave();
760 return false;
761 }
762 // mutex.leave();
763 }
764 else { // if err == 0
765 // Error will be handled by the caller
767 mutex.leave();
768 return false;
769 }
770
771 struct timeval tv;
772 tv.tv_sec = 0;
773 tv.tv_usec = 10;
774
775 int maxfd = 0;
776 fd_set wfds;
777 // create a list of sockets to check for activity
778 FD_ZERO(&wfds);
779 // specify socket
780 FD_SET(socket, &wfds);
781
782 mutex.leave();
783
784 #ifdef WINDOWS
785 int len;
786 #else
787 #ifdef Darwin
788 #if GCC_VERSION < 40000
789 int len;
790 maxfd = socket + 1;
791 #else
792 socklen_t len;
793 maxfd = socket + 1;
794 #endif // GCC_VERSION < 40000
795 #else
796 socklen_t len;
797 maxfd = socket + 1;
798 #endif
799 #endif
800
801 if (timeout > 0) {
802 ldiv_t d = ldiv(timeout*1000, 1000000);
803 tv.tv_sec = d.quot;
804 tv.tv_usec = d.rem;
805 }
806
807 // Check for writability
808 res = select(maxfd, NULL, &wfds, NULL, &tv);
809
810 if (res <= 0)
811 return false;
812
813 //printf("wait res > 0\n");
814
815 int error;
816 len = sizeof(error);
817
818 if (!mutex.enter(1000))
819 return false;
820
821 if (FD_ISSET(socket, &wfds) != 0) {
822 if (getsockopt(socket, SOL_SOCKET, SO_ERROR, (char*)&error, &len) != 0) {
823
824 int wsaError = utils::GetLastOSErrorNumber();
825 mutex.leave();
826 if (wsaError == 0) {
827 // No error, just unable to send...
828 return true;
829 }
830 #ifdef WINDOWS
831 else if (wsaError == WSAENETDOWN ) {
832 return false;
833 }
834 else if (wsaError == WSAEFAULT ) {
835 return false;
836 }
837 else if (wsaError == WSAEINPROGRESS ) {
838 return false;
839 }
840 else if (wsaError == WSAEINVAL ) {
841 return false;
842 }
843 else if (wsaError == WSAENOPROTOOPT ) {
844 if (error == 0) {
845 return true;
846 }
847 }
848 else if (wsaError == WSAENOTSOCK ) {
849 return false;
850 }
851 #endif
852 return false;
853 }
854 mutex.leave();
855 if (error == 0)
856 return true;
857 }
858 else
859 mutex.leave();
860
861 return false;
862}
863
865 struct timeval tv;
866 tv.tv_sec = 0;
867 tv.tv_usec = 10;
868
869 int maxfd = 0;
870 fd_set wfds;
871 // create a list of sockets to check for activity
872 FD_ZERO(&wfds);
873 // specify socket
874 FD_SET(s, &wfds);
875
876
877 #ifdef WINDOWS
878 int len;
879 #else
880 #ifdef Darwin
881 #if GCC_VERSION < 40000
882 int len;
883 maxfd = s + 1;
884 #else
885 socklen_t len;
886 maxfd = s + 1;
887 #endif // GCC_VERSION < 40000
888 #else
889 socklen_t len;
890 maxfd = s + 1;
891 #endif
892 #endif
893
894 if (timeout > 0) {
895 ldiv_t d = ldiv(timeout * 1000, 1000000);
896 tv.tv_sec = d.quot;
897 tv.tv_usec = d.rem;
898 }
899
900 // Check for writability
901 int res = select(maxfd, NULL, &wfds, NULL, &tv);
902
903 if (res <= 0)
904 return false;
905
906 //printf("wait res > 0\n");
907
908 int error;
909 len = sizeof(error);
910
911 if (FD_ISSET(s, &wfds) != 0) {
912 if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char*)&error, &len) != 0) {
913
914 int wsaError = utils::GetLastOSErrorNumber();
915 if (wsaError == 0) {
916 // No error, just unable to send...
917 return true;
918 }
919 #ifdef WINDOWS
920 else if (wsaError == WSAENETDOWN) {
921 return false;
922 }
923 else if (wsaError == WSAEFAULT) {
924 return false;
925 }
926 else if (wsaError == WSAEINPROGRESS) {
927 return false;
928 }
929 else if (wsaError == WSAEINVAL) {
930 return false;
931 }
932 else if (wsaError == WSAENOPROTOOPT) {
933 if (error == 0) {
934 return true;
935 }
936 }
937 else if (wsaError == WSAENOTSOCK) {
938 return false;
939 }
940 #endif
941 return false;
942 }
943 if (error == 0)
944 return true;
945 }
946 return false;
947}
948
950
951 if (socket == INVALID_SOCKET)
952 return false;
953
954 // First use the socket a bit
955 if (!mutex.enter(1000))
956 return false;
957
958 struct timeval tv;
959 tv.tv_sec = 0;
960 tv.tv_usec = 10;
961
962 int maxfd = 0;
963 fd_set wfds;
964 // create a list of sockets to check for activity
965 FD_ZERO(&wfds);
966 // specify socket
967 FD_SET(socket, &wfds);
968
969 mutex.leave();
970
971 #ifdef WINDOWS
972 int len;
973 #else
974 #ifdef Darwin
975 #if GCC_VERSION < 40000
976 int len;
977 maxfd = socket + 1;
978 #else
979 socklen_t len;
980 maxfd = socket + 1;
981 #endif // GCC_VERSION < 40000
982 #else
983 socklen_t len;
984 maxfd = socket + 1;
985 #endif
986 #endif
987
988 if (timeout > 0) {
989 ldiv_t d = ldiv(timeout * 1000, 1000000);
990 tv.tv_sec = d.quot;
991 tv.tv_usec = d.rem;
992 }
993
994 // Check for writability
995 int res = select(maxfd, NULL, &wfds, NULL, &tv);
996
997 if (res <= 0)
998 return false;
999
1000 //printf("wait res > 0\n");
1001
1002 int error;
1003 len = sizeof(error);
1004
1005 mutex.enter(1000);
1006 if (FD_ISSET(socket, &wfds) != 0) {
1007 if (getsockopt(socket, SOL_SOCKET, SO_ERROR, (char*)&error, &len) != 0) {
1008
1009 int wsaError = utils::GetLastOSErrorNumber();
1010 mutex.leave();
1011 if (wsaError == 0) {
1012 // No error, just unable to send...
1013 return true;
1014 }
1015#ifdef WINDOWS
1016 else if (wsaError == WSAENETDOWN) {
1017 return false;
1018 }
1019 else if (wsaError == WSAEFAULT) {
1020 return false;
1021 }
1022 else if (wsaError == WSAEINPROGRESS) {
1023 return false;
1024 }
1025 else if (wsaError == WSAEINVAL) {
1026 return false;
1027 }
1028 else if (wsaError == WSAENOPROTOOPT) {
1029 if (error == 0) {
1030 return true;
1031 }
1032 }
1033 else if (wsaError == WSAENOTSOCK) {
1034 return false;
1035 }
1036#endif
1037 return false;
1038 }
1039 mutex.leave();
1040 if (error == 0)
1041 return true;
1042 }
1043 else
1044 mutex.leave();
1045
1046 return false;
1047}
1048
1050 if (receiver == NULL)
1051 return false;
1052
1053 uint32 size;
1054 uint32 buflen = INITIALBUFFERSIZE;
1055 char* myBuffer = (char*) malloc(buflen);
1056 if (myBuffer == NULL)
1057 return false;
1058
1059 LogPrint(0, LOG_NETWORK, 2, "Incoming network connection from %u.%u.%u.%u:%u, started run...",
1061
1062 isRunning = true;
1063 while (shouldContinue) {
1064 if (receive((char*)&size, sizeof(size), 50, true)) {
1065
1066 if (buflen < size) {
1067 buflen = size;
1068 myBuffer = (char*) realloc(myBuffer, buflen);
1069 if (myBuffer == NULL) {
1070 isRunning = false;
1072 return false;
1073 }
1074 }
1075
1076 // Receive the full data structure
1077 if (!receive(myBuffer, size, 500)) {
1078 isRunning = false;
1079 free(myBuffer);
1080 // Error already reported & already disconnected
1081 return false;
1082 }
1083
1084 if (receiver) {
1085 receiver->receiveData(myBuffer, size, this);
1086 }
1087 }
1088 }
1089 isRunning = false;
1090 free(myBuffer);
1091 return true;
1092}
1093
1097
1099 return inputSpeed;
1100}
1101
1103 return type;
1104}
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1120
1123
1125 // Setup socket
1126 mutex.enter(1000);
1127 if((socket=::socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP))==INVALID_SOCKET){
1128 LogPrint(0, LOG_NETWORK, 0, "Could not create UDPConnection socket...");
1130 mutex.leave();
1131 return false;
1132 }
1133
1134 #ifdef WINDOWS
1135 // Set the exclusive address option, preventing other software binding to
1136 // non-INADDR_ANY (i.e. interface addresses such as localhost directly)
1137 int one = 1;
1138 setsockopt(socket, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char *) &one, sizeof(one));
1139 #else
1140 /*
1141 This socket option tells the kernel that even if this port is busy (in
1142 the TIME_WAIT state), go ahead and reuse it anyway. If it is busy,
1143 but with another state, you will still get an address already in use
1144 error. It is useful if your server has been shut down, and then
1145 restarted right away while sockets are still active on its port. You
1146 should be aware that if any unexpected data comes in, it may confuse
1147 your server, but while this is possible, it is not likely.
1148 */
1149 int one = 1;
1150 setsockopt(socket,SOL_SOCKET,SO_REUSEADDR,&one,sizeof(one));
1151 #endif
1152
1153 setsockopt(socket,SOL_SOCKET,SO_BROADCAST,(char*)&one,sizeof(one));
1154
1155 // Set blocking mode
1157
1158 mutex.leave();
1159 return true;
1160}
1161
1163 if (port == 0) {
1164 LogPrint(0, LOG_NETWORK, 0, "Could not start UDPConnection on port 0...");
1165 return false;
1166 }
1167
1168 memcpy(((char*)&localAddress)+sizeof(uint32), &port, sizeof(uint16));
1169 // Open UDP port
1170
1171 // Setup listening on port node->networkPort
1172 mutex.enter(1000);
1173 if((socket=::socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP))==INVALID_SOCKET){
1174 LogPrint(0, LOG_NETWORK, 0, "Could not create UDPConnection socket...");
1176 mutex.leave();
1177 return false;
1178 }
1179
1180 #ifdef WINDOWS
1181 // Set the exclusive address option, preventing other software binding to
1182 // non-INADDR_ANY (i.e. interface addresses such as localhost directly)
1183 int one = 1;
1184 setsockopt(socket, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char *) &one, sizeof(one));
1185 #else
1186 /*
1187 This socket option tells the kernel that even if this port is busy (in
1188 the TIME_WAIT state), go ahead and reuse it anyway. If it is busy,
1189 but with another state, you will still get an address already in use
1190 error. It is useful if your server has been shut down, and then
1191 restarted right away while sockets are still active on its port. You
1192 should be aware that if any unexpected data comes in, it may confuse
1193 your server, but while this is possible, it is not likely.
1194 */
1195 int one = 1;
1196 setsockopt(socket,SOL_SOCKET,SO_REUSEADDR,&one,sizeof(one));
1197 #endif
1198
1199 setsockopt(socket,SOL_SOCKET,SO_BROADCAST,(char*)&one,sizeof(one));
1200
1201 struct sockaddr_in addr;
1202 addr.sin_family= AF_INET;
1203 addr.sin_addr.s_addr=INADDR_ANY;
1204 addr.sin_port=htons(port);
1205
1206 if(bind(socket,(SOCKADDR*)&addr,sizeof(struct sockaddr_in))==SOCKET_ERROR){
1207 LogPrint(0, LOG_NETWORK, 0, "Could not create UDPConnection on port %u...", port);
1209 mutex.leave();
1210 return false;
1211 }
1212 LogPrint(0, LOG_NETWORK, 2, "Created UDPConnection on port %u...", port);
1213
1214 // Set blocking mode
1216
1217 if (receiver != NULL) {
1218 this->receiver = receiver;
1219 // Start networking thread
1221 LogPrint(0, LOG_NETWORK, 0, "Could not start UDPConnection thread...");
1223 mutex.leave();
1224 return false;
1225 }
1226 }
1227
1228 mutex.leave();
1229 return true;
1230}
1231
1232bool UDPConnection::send(const char* data, uint32 size, uint64 receiver) {
1233 uint64 start;
1234 sockaddr_in recvAddr;
1235 recvAddr.sin_family = AF_INET;
1236 int64 t;
1237
1238 if (!receiver && !defaultReceiver) {
1239 // this should broadcast ##############
1240 return false;
1241 }
1242 else {
1243 uint64 rec = receiver ? receiver : defaultReceiver;
1244 uint16 p = GETIPPORT(rec);
1245 recvAddr.sin_port = htons(p);
1246 memcpy(&recvAddr.sin_addr.s_addr, &rec, 4);
1247 if (!sendMutex.enter(500))
1248 return false;
1249 start = GetTimeNow();
1250
1251 uint32 pos = 0;
1252 int32 n;
1253
1254 while (true) {
1255 try {
1256 n = ::sendto(socket, data + pos, size - pos, 0, (SOCKADDR*)&recvAddr, sizeof(sockaddr_in));
1257 }
1258 catch (...) {
1259 // printf("--- UDP error sending reply (%u)...\n", size);
1261 sendMutex.leave();
1262 return false;
1263 }
1264 if (n == SOCKET_ERROR) {
1265 // printf("--- UDP error sending reply (%u)...\n", size);
1267 sendMutex.leave();
1268 return false;
1269 }
1270 pos += n;
1271 // Have we written everything?
1272 if (pos >= size)
1273 break;
1274 // else wait for writeability
1276 // check for ridiculous timeout
1277 if ((t = GetTimeAgeMS(start)) > 10000) {
1279 sendMutex.leave();
1280 return false;
1281 }
1282 // and go again
1283 }
1284 }
1285 t = GetTimeAge(start);
1286 if (t > 0)
1287 outputSpeed = (uint32)(size*1000000.0/(double)t);
1288 outputBytes += size;
1289 sendMutex.leave();
1290
1291 #ifdef UDPCON_PRINT_DEBUG
1292 if (size < 1024) {
1293 char* tmp = new char[size+1];
1294 memcpy(tmp, data, size);
1295 tmp[size] = 0;
1296 LogPrint(0,LOG_NETWORK,0,">>>>>>> SEND >>>>>>>> UDP Sent %u bytes '%s' to %u.%u.%u.%u:%u\n", size, tmp, GETIPADDRESSQUAD(receiver), GETIPPORT(receiver));
1297 delete [] tmp;
1298 }
1299 else {
1300 #ifdef UDPCON_PRINTBINARY_DEBUG
1301 char* tmp = new char[size+1];
1302 memcpy(tmp, data, size);
1303 tmp[size] = 0;
1304 LogPrint(0,LOG_NETWORK,0,">>>>>>> SEND >>>>>>>> UDP Sent %u bytes '%s'\n", size, tmp);
1305 delete [] tmp;
1306 #else
1307 char* tmp = new char[1024];
1308 memcpy(tmp, data, 1023);
1309 tmp[1023] = 0;
1310 LogPrint(0,LOG_NETWORK,0,">>>>>>> SEND >>>>>>>> UDP Sent %u bytes '%s' to %u.%u.%u.%u:%u\n", size, tmp, GETIPADDRESSQUAD(receiver), GETIPPORT(receiver));
1311 delete [] tmp;
1312 #endif
1313 }
1314 #endif
1315
1316 return true;
1317}
1318
1319bool UDPConnection::reconnect(uint32 timeoutMS) {
1320 disconnect();
1322}
1323
1326 return true;
1327}
1328
1330 return localAddress;
1331}
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1348
1351
1353 mutex.enter(1000);
1354 bufferContentLen = 0;
1355 bufferContentPos = 0;
1356 localAddress = localAddr;
1357
1358 socket = s;
1360
1361 // Set blocking mode
1363
1364 struct linger tmp = {1, 0};
1365 setsockopt(socket, SOL_SOCKET, SO_LINGER, (char *)&tmp, sizeof(tmp));
1366 int delay = 1;
1367 setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char*) &delay, sizeof(delay));
1368 //char buffsize = 1;
1369 //setsockopt(socket, SOL_SOCKET, SO_SNDBUF, &buffsize, sizeof(buffsize));
1370 //buffsize = 1;
1371 //setsockopt(socket, SOL_SOCKET, SO_RCVBUF, &buffsize, sizeof(buffsize));
1372
1373 LogPrint(0, LOG_NETWORK, 2, "Incoming TCP connection from %u.%u.%u.%u:%u, starting run...",
1375
1376 if (receiver != NULL) {
1377 this->receiver = receiver;
1378 // Start networking thread
1380 LogPrint(0, LOG_NETWORK, 0, "Could not start TCPConnection thread...");
1382 mutex.leave();
1383 return false;
1384 }
1385 }
1386
1387 remote = true;
1388 mutex.leave();
1389 return true;
1390}
1391
1392bool TCPConnection::connect(uint64 addr, uint32 timeoutMS, NetworkDataReceiver* receiver) {
1393 // Timeout-aware connect, identical on Winsock and BSD sockets thanks to the
1394 // SOCKET/closesocket/GetLastOSErrorNumber abstractions: the socket is put
1395 // into non-blocking mode first, so ::connect() returns immediately with
1396 // EWOULDBLOCK/EINPROGRESS and didConnect() then select()-waits up to
1397 // timeoutMS for writability (= connection established). On success the
1398 // socket gets SO_LINGER {1,0} (hard close, RST instead of TIME_WAIT) and
1399 // TCP_NODELAY (no Nagle batching — vital for small request/reply frames).
1400 // Passing a NetworkDataReceiver switches the connection to push mode by
1401 // starting a dedicated reader thread (TCPConnectionRun).
1402
1403 // first create a temporary socket so we don't have to block the mutex while connecting
1404 SOCKET tempSocket;
1405
1406 if (timeoutMS) {
1407 if (!connectTimeoutMS)
1408 connectTimeoutMS = timeoutMS;
1409 }
1410 else
1411 timeoutMS = connectTimeoutMS;
1412
1413 if((tempSocket =::socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET){
1414 int retries = 0;
1415 int err = utils::GetLastOSErrorNumber();
1416 while ((err == SOCKETWOULDBLOCK) || (err == SOCKETTRYAGAIN)) {
1417 utils::Sleep(20);
1418 if ((tempSocket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) != INVALID_SOCKET)
1419 break;
1421 retries++;
1422 if (retries > 10)
1423 break;
1424 }
1425 if (tempSocket == INVALID_SOCKET) {
1426 // mutex is not locked
1427 LogPrint(0, LOG_NETWORK, 0, "Could not create TCPConnection socket (%d)...", err);
1428 return false;
1429 }
1430 }
1431
1432 bufferContentLen = 0;
1433 bufferContentPos = 0;
1434
1435 // Set blocking mode
1437
1438 struct sockaddr_in saServer;
1439 saServer.sin_family = AF_INET;
1440 saServer.sin_port = htons(GETIPPORT(addr));
1441 memcpy(&saServer.sin_addr.s_addr, &addr, 4);
1442
1443 // Connect to the server
1444 int res;
1445 if ((res = ::connect(tempSocket, (struct sockaddr*)&saServer, sizeof(struct sockaddr))) != 0) {
1446 int err = utils::GetLastOSErrorNumber();
1447 if ( (err == SOCKETWOULDBLOCK) || (err == SOCKETTRYAGAIN) ) {
1448 if (!didConnect(tempSocket, timeoutMS)) {
1449 closesocket(tempSocket);
1450 return false;
1451 }
1452 }
1453 else {
1454 closesocket(tempSocket);
1455 return false;
1456 }
1457 }
1458
1459 // Set blocking mode
1460 // utils::SetSocketNonBlockingMode(socket);
1461
1462 struct linger tmp = {1, 0};
1463 setsockopt(tempSocket, SOL_SOCKET, SO_LINGER, (char *)&tmp, sizeof(tmp));
1464 int delay = 1;
1465 setsockopt(tempSocket, IPPROTO_TCP, TCP_NODELAY, (char*) &delay, sizeof(delay));
1466 //char buffsize = 1;
1467 //setsockopt(tempSocket, SOL_SOCKET, SO_SNDBUF, &buffsize, sizeof(buffsize));
1468 //buffsize = 1;
1469 //setsockopt(tempSocket, SOL_SOCKET, SO_RCVBUF, &buffsize, sizeof(buffsize));
1470
1471 // Now block the mutex
1472 if (!mutex.enter(1000)) {
1473 LogPrint(0, LOG_NETWORK, 0, "Could not lock connection mutex...");
1474 closesocket(tempSocket);
1475 return false;
1476 }
1477
1478 socket = tempSocket;
1479
1480 if (receiver != NULL) {
1481 this->receiver = receiver;
1482 // Start networking thread
1484 LogPrint(0, LOG_NETWORK, 0, "Could not start TCPConnection thread...");
1486 mutex.leave();
1487 return false;
1488 }
1489 }
1490
1491 remoteAddress = addr;
1492 remote = false;
1493
1494 mutex.leave();
1495 return true;
1496}
1497
1498bool TCPConnection::connect(const char* addr, uint16 port, uint64& location, uint32 timeoutMS, NetworkDataReceiver* receiver) {
1499 // Resolve address
1500 uint32 address;
1501 if (!utils::LookupIPAddress(addr, address))
1502 return false;
1503 return connect(location = GETIPADDRESSPORT(address, port), timeoutMS, receiver);
1504}
1505
1506bool TCPConnection::connect(const uint32* addresses, uint16 addressCount, uint16 port, uint64& location, uint32 timeoutMS, NetworkDataReceiver* receiver) {
1507 // Try all addresses
1508 for (uint16 n=0; n<addressCount; n++) {
1509 if (connect(location = GETIPADDRESSPORT(addresses[n], port), timeoutMS, receiver))
1510 return true;
1511 }
1512 return false;
1513}
1514
1515
1516bool TCPConnection::delayedConnect(uint64 addr, uint32 timeoutMS, NetworkDataReceiver* receiver) {
1517 mutex.enter(1000);
1518
1519 connectTimeoutMS = timeoutMS;
1520 remoteAddress = addr;
1521 remote = false;
1522
1523 if (receiver != NULL) {
1524 this->receiver = receiver;
1525 // Start networking thread
1527 LogPrint(0, LOG_NETWORK, 0, "Could not start TCPConnection thread...");
1528 mutex.leave();
1529 return false;
1530 }
1531 }
1532
1533 mutex.leave();
1534 return true;
1535}
1536
1537bool TCPConnection::delayedConnect(const char* addr, uint16 port, uint64& location, uint32 timeoutMS, NetworkDataReceiver* receiver) {
1538 // Resolve address
1539 uint32 address;
1540 if (!utils::LookupIPAddress(addr, address))
1541 return false;
1542 return delayedConnect(location = GETIPADDRESSPORT(address, port), timeoutMS, receiver);
1543}
1544
1545
1546//#define TCPCON_PRINT_DEBUG
1547
1548bool TCPConnection::send(const char* data, uint32 size, uint64 receiver) {
1549 // Ignore receiver, only for UDP
1550 // ### Consider splitting large data up into smaller chunks ###
1551 if (!size)
1552 return false;
1553 if (!sendMutex.enter(500))
1554 return false;
1555 uint64 start = GetTimeNow();
1556 // The socket stays in non-blocking mode (set once at connect/accept). We used
1557 // to flip it to blocking for the duration of the send and back to non-blocking
1558 // afterwards, which cost four fcntl() syscalls on every message AND raced with
1559 // the receive thread reading the same socket. Instead we drive the non-blocking
1560 // send loop directly and only wait for writeability when the kernel send buffer
1561 // is genuinely full (EWOULDBLOCK).
1562
1563 // Charles:
1564 //const char *data = (const char *) tdata;
1565 // IntT done = 0;
1566 // do {
1567 // int n = write(fd,&(data[done]),length - done);
1568 // if(n < 0) {
1569 // if(errno == EAGAIN || errno == EINTR) // Recoverable error?
1570 // continue;
1571 // return -1;
1572 // }
1573 // done += n;
1574 // } while(done < length);
1575 // return done;
1576
1577 int64 t;
1578 uint32 pos = 0;
1579 int32 n;
1580
1581 while (true) {
1582 try {
1583 n = ::send(socket, data + pos, size - pos, 0);
1584 }
1585 catch (...) {
1586 //printf("--- TCP error sending reply (%u) error: %u...\n", size, WSAGetLastError());
1588 sendMutex.leave();
1589 return false;
1590 }
1591 //n = ::send(socket, data + pos,
1592 // (size - pos>5120000) ? 5120000 : size - pos,
1593 // 0);
1594 if(n == SOCKET_ERROR) {
1595 int err = utils::GetLastOSErrorNumber();
1596 if ((err == SOCKETWOULDBLOCK) || (err == SOCKETTRYAGAIN)) {
1597 // Kernel send buffer is full - wait until it drains, then retry
1598 // the same chunk. Nothing has been consumed, so 'pos' is unchanged.
1599 if ((t = GetTimeAgeMS(start)) > 10000) {
1601 sendMutex.leave();
1602 return false;
1603 }
1605 continue;
1606 }
1607 //printf("--- TCP error sending reply (%u) error: %u...\n", size, WSAGetLastError());
1609 sendMutex.leave();
1610 return false;
1611 }
1612 pos += n;
1613 // Have we written everything?
1614 if (pos >= size)
1615 break;
1616 // check for ridiculous timeout
1617 if ((t = GetTimeAgeMS(start)) > 10000) {
1619 sendMutex.leave();
1620 return false;
1621 }
1622 // and go again
1623 }
1624
1625 t = GetTimeAge(start);
1626 if (t > 0)
1627 outputSpeed = (uint32)(size*1000000.0/(double)t);
1628 outputBytes += size;
1629 sendMutex.leave();
1630
1631 #ifdef TCPCON_PRINT_DEBUG
1632 if (size < 1024) {
1633 char* tmp = new char[size+1];
1634 memcpy(tmp, data, size);
1635 tmp[size] = 0;
1636 LogPrint(0,LOG_NETWORK,0,">>>>>>> SEND >>>>>>>> TCP Sent %u bytes (%.3f) '%s'\n", size, t/1000.0, tmp);
1637 delete [] tmp;
1638 }
1639 else {
1640 #ifdef TCPCON_PRINTBINARY_DEBUG
1641 char* tmp = new char[size+1];
1642 memcpy(tmp, data, size);
1643 tmp[size] = 0;
1644 LogPrint(0,LOG_NETWORK,0,">>>>>>> SEND >>>>>>>> TCP Sent %u bytes '%s'\n", size, tmp);
1645 delete [] tmp;
1646 #else
1647 char* tmp = new char[1024];
1648 memcpy(tmp, data, 1023);
1649 tmp[1023] = 0;
1650 LogPrint(0,LOG_NETWORK,0,">>>>>>> SEND >>>>>>>> TCP Sent %u bytes (%.3f) '%s'\n", size, t / 1000.0, tmp);
1651 delete [] tmp;
1652 #endif
1653 }
1654 #endif
1655
1656
1657// utils::Sleep(100);
1658 return true;
1659}
1660
1661
1662
1663bool TCPConnection::reconnect(uint32 timeoutMS) {
1664 disconnect();
1665 return connect(remoteAddress, timeoutMS, receiver);
1666}
1667
1668
1670
1671 if (socket == INVALID_SOCKET)
1672 return false;
1673
1674 struct sockaddr_in remoteAddr;
1675
1676 #ifdef WINDOWS
1677 int remoteAddrLen;
1678 #else
1679 #ifdef Darwin
1680 #if GCC_VERSION < 40000
1681 int remoteAddrLen;
1682 #else
1683 socklen_t remoteAddrLen;
1684 #endif // GCC_VERSION < 40000
1685 #else
1686 socklen_t remoteAddrLen;
1687 #endif
1688 #endif // WINDOWS
1689
1690 remoteAddrLen = sizeof(struct sockaddr_in);
1691
1692 if (getpeername(socket, (struct sockaddr*) &remoteAddr, &remoteAddrLen) != 0)
1693 return false;
1694
1695 uint32 address = remoteAddr.sin_addr.s_addr;
1696 if ( address == LOCALHOSTIP ) {
1697 // Get the actual local ip address, if possible
1698 utils::GetLocalIPAddress(address);
1699 }
1700 addr = GETIPADDRESSPORT(address, (uint16)remoteAddr.sin_port);
1701 return true;
1702}
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719bool IsSSLInitialised = false;
1720
1721#ifdef _USE_SSL_
1722#ifdef WINDOWS
1723 // #include "openssl/applink.c"
1724#endif
1725#endif
1726
1727
1729 type = SSLCON;
1733 #ifdef _USE_SSL_
1734 if (!IsSSLInitialised) {
1735 // Init SSL
1736 //CRYPTO_malloc_init();
1737 OpenSSL_add_all_algorithms();
1738 //ERR_load_BIO_strings();
1739 ERR_load_crypto_strings();
1740 SSL_load_error_strings();
1741
1742 certbio = BIO_new(BIO_s_file());
1743 outbio = BIO_new_fp(stdout, BIO_NOCLOSE);
1744
1745 SSL_library_init();
1746
1747 IsSSLInitialised = true;
1748 }
1749 ctx = NULL;
1750 ssl = NULL;
1751 #endif // _USE_SSL_
1752}
1753
1755 #ifdef _USE_SSL_
1756 mutex.enter(1000);
1757 if (ctx) {
1758 SSL_CTX_free(ctx);
1759 ctx = NULL;
1760 }
1761 mutex.leave();
1762 #else // _USE_SSL_
1763 #endif // _USE_SSL_
1764}
1765
1766// Process-wide default for client certificate verification. False = verify
1767// peers against the CA trust store (secure by default). Set from the global
1768// <psyspec allowselfsigned="yes"> attribute; per-connection
1769// setAllowSelfSigned() overrides it either way.
1771
1775
1779
1780// Process-wide default custom CA location (set from <psyspec cafile/capath>);
1781// per-connection setCALocation() overrides it. Empty = use OS trust store.
1784
1785void SSLConnection::SetDefaultCALocation(const char* caFile, const char* caPath) {
1786 DefaultCAFile = caFile ? caFile : "";
1787 DefaultCAPath = caPath ? caPath : "";
1788}
1789
1790void SSLConnection::setCALocation(const char* caFile, const char* caPath) {
1791 this->caFile = caFile ? caFile : "";
1792 this->caPath = caPath ? caPath : "";
1793 #ifdef _USE_SSL_
1794 if (ctx)
1795 applyClientVerify();
1796 #endif // _USE_SSL_
1797}
1798
1799void SSLConnection::setVerifyHostName(const char* host) {
1800 verifyHostName = host ? host : "";
1801}
1802
1804 allowSelfSigned = allow;
1805 #ifdef _USE_SSL_
1806 if (ctx)
1807 applyClientVerify();
1808 #endif // _USE_SSL_
1809}
1810
1811#ifdef _USE_SSL_
1812// Configure peer verification on the client context according to the
1813// allowSelfSigned policy for this connection.
1814bool SSLConnection::applyClientVerify() {
1815 if (!ctx)
1816 return false;
1817 if (allowSelfSigned) {
1818 SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
1819 }
1820 else {
1821 if (!caFile.empty() || !caPath.empty()) {
1822 // Verify the server certificate against a custom CA file/dir
1823 // (e.g. a self-minted CA) instead of the OS trust store
1824 if (SSL_CTX_load_verify_locations(ctx,
1825 caFile.empty() ? NULL : caFile.c_str(),
1826 caPath.empty() ? NULL : caPath.c_str()) != 1)
1827 LogPrint(0, LOG_NETWORK, 0, "SSL: could not load CA location (file: %s, path: %s)",
1828 caFile.empty() ? "-" : caFile.c_str(), caPath.empty() ? "-" : caPath.c_str());
1829 }
1830 else {
1831 #ifdef WINDOWS
1832 // Verify the server certificate against the OS trust store.
1833 // OpenSSL's SSL_CTX_set_default_verify_paths() is useless on
1834 // Windows (it points at the build-time OPENSSLDIR), so import
1835 // the Windows ROOT system store into the context's X509 store
1836 // via CryptoAPI instead.
1837 bool loadedOSRoots = false;
1838 HCERTSTORE hStore = CertOpenSystemStoreA(0, "ROOT");
1839 if (hStore) {
1840 X509_STORE* store = SSL_CTX_get_cert_store(ctx);
1841 PCCERT_CONTEXT pWinCert = NULL;
1842 while ((pWinCert = CertEnumCertificatesInStore(hStore, pWinCert)) != NULL) {
1843 const unsigned char* enc = pWinCert->pbCertEncoded;
1844 X509* x = d2i_X509(NULL, &enc, pWinCert->cbCertEncoded);
1845 if (x) {
1846 // Returns 0 for duplicates - not a failure
1847 if (X509_STORE_add_cert(store, x) == 1)
1848 loadedOSRoots = true;
1849 X509_free(x);
1850 }
1851 }
1852 CertCloseStore(hStore, 0);
1853 }
1854 ERR_clear_error(); // duplicate-cert noise from X509_STORE_add_cert
1855 if (!loadedOSRoots)
1856 LogPrint(0, LOG_NETWORK, 0, "SSL: could not load Windows ROOT certificate store");
1857 #else
1858 // Verify the server certificate against the OS/CA trust store
1859 if (SSL_CTX_set_default_verify_paths(ctx) != 1)
1860 LogPrint(0, LOG_NETWORK, 0, "SSL: could not load default CA trust store");
1861 #endif // WINDOWS
1862 }
1863 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
1864 }
1865 return true;
1866}
1867
1868int SSLConnection::getVerifyMode() {
1869 if (!ctx)
1870 return -1;
1871 return SSL_CTX_get_verify_mode(ctx);
1872}
1873#endif // _USE_SSL_
1874
1875bool SSLConnection::init(const char *certFile, const char *keyFile) {
1876 mutex.enter(1000);
1877 #ifdef _USE_SSL_
1878 LogPrint(0, LOG_NETWORK, 2, "SSL connection init start");
1879 // Compatible with SSLv2, SSLv3 and TLSv1
1880 const SSL_METHOD *method = SSLv23_server_method();
1881 // Create new context from method.
1882 ctx = SSL_CTX_new(method);
1883 if(!ctx) {
1884 LogPrint(0, LOG_NETWORK, 0, "Unable to create a new SSL context structure");
1885 BIO_printf(outbio, "Unable to create a new SSL context structure.\n");
1886 mutex.leave();
1887 return false;
1888 }
1889 LogPrint(0, LOG_NETWORK, 2, "SSL connection init created, setting files...");
1890
1891 if ( SSL_CTX_use_certificate_chain_file(ctx, certFile) <= 0) {
1892 LogPrint(0, LOG_NETWORK, 0, "Unable to use SSL certificate chain file: %s", certFile);
1893 LogSSLErrors("certificate chain file", 0);
1894 mutex.leave();
1895 return false;
1896 }
1897 if ( SSL_CTX_use_PrivateKey_file(ctx, keyFile, SSL_FILETYPE_PEM) <= 0) {
1898 LogPrint(0, LOG_NETWORK, 0, "Unable to use SSL private key file: %s", keyFile);
1899 LogSSLErrors("private key file", 0);
1900 mutex.leave();
1901 return false;
1902 }
1903 LogPrint(0, LOG_NETWORK, 2, "SSL connection init files set");
1904
1905 // Verify that the two keys goto together.
1906 if ( !SSL_CTX_check_private_key(ctx) ) {
1907 LogPrint(0, LOG_NETWORK, 0, "SSL private key invalid: %s", keyFile);
1908 fprintf(stderr, "Private key is invalid.\n");
1909 mutex.leave();
1910 return false;
1911 }
1912 mutex.leave();
1913 LogPrint(0, LOG_NETWORK, 2, "SSL connection init done");
1914 return true;
1915 #else // _USE_SSL_
1916 mutex.leave();
1917 return false;
1918 #endif // _USE_SSL_
1919}
1920
1922 mutex.enter(1000);
1923 #ifdef _USE_SSL_
1924 // Compatible with SSLv2, SSLv3 and TLSv1
1925 const SSL_METHOD *method = SSLv23_method();
1926 // Create new context from method.
1927 ctx = SSL_CTX_new(method);
1928 if(!ctx) {
1929 BIO_printf(outbio, "Unable to create a new SSL context structure.\n");
1930 mutex.leave();
1931 return false;
1932 }
1933
1934 //SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2);
1935
1936 // Client-side certificate verification (secure by default; see
1937 // setAllowSelfSigned/SetDefaultAllowSelfSigned)
1938 applyClientVerify();
1939
1940 mutex.leave();
1941 return true;
1942 #else // _USE_SSL_
1943 mutex.leave();
1944 return false;
1945 #endif // _USE_SSL_
1946}
1947
1948bool SSLConnection::didConnect(int timeout) {
1949 return NetworkConnection::didConnect(timeout);
1950}
1951
1953
1954 // ######################
1955 //return true;
1956
1957 //printf("ISCON1\n");fflush(stdout);
1958
1959#ifdef _USE_SSL_
1960
1961 if ((socket == INVALID_SOCKET) || !ssl)
1962 return false;
1963
1964 char peekBuffer[1];
1965 // First use the socket a bit
1966
1967 //utils::Sleep(100);
1968
1969 if (!mutex.enter(200, __FUNCTION__))
1970 return false;
1971 //printf("ISCON2\n");fflush(stdout);
1972 int res = recv(socket, peekBuffer, 1, MSG_PEEK);
1973 if (res > 0) {
1974 mutex.leave();
1975 //printf("ISCON3\n");fflush(stdout);
1976 return true;
1977 }
1978 else if (res < 0) {
1979 int err = utils::GetLastOSErrorNumber();
1980 // UDP needs TRYAGAIN
1981 if (err == SOCKETWOULDBLOCK) {
1982 mutex.leave();
1983 //printf("ISCON4\n");fflush(stdout);
1984 return true;
1985 }
1986
1987 #ifdef WINDOWS
1988 else if ((type == UDPCON) && (err == SOCKETTRYAGAIN)) {
1989 mutex.leave();
1990 //printf("ISCON5\n");fflush(stdout);
1991 return true;
1992 }
1993 else if (err == WSAENOTCONN) {} // Windows needs this one...
1994 else if (err == WSAEOPNOTSUPP) {} // WinCE may need this one...???.
1995 #else
1996 else if (err == SOCKETTRYAGAIN) {
1997 mutex.leave();
1998 return true;
1999 }
2000 #endif //WINDOWS
2001 else {
2002 // Error will be handled by the caller
2003 //printf("ISCON6\n");fflush(stdout);
2004 disconnect(0);
2005 mutex.leave();
2006 return false;
2007 }
2008 // mutex.leave();
2009 }
2010 else { // if err == 0
2011 // Error will be handled by the caller
2012 //printf("ISCON7\n");fflush(stdout);
2013 disconnect(0);
2014 mutex.leave();
2015 return false;
2016 }
2017
2018 //printf("ISCON10\n");fflush(stdout);
2019
2020 struct timeval tv;
2021 tv.tv_sec = 0;
2022 tv.tv_usec = 10;
2023
2024 int maxfd = 0;
2025 fd_set wfds;
2026 // create a list of sockets to check for activity
2027 FD_ZERO(&wfds);
2028 // specify socket
2029 FD_SET(socket, &wfds);
2030
2031 mutex.leave();
2032
2033 #ifdef WINDOWS
2034 int len;
2035 #else
2036 #ifdef Darwin
2037 #if GCC_VERSION < 40000
2038 int len;
2039 maxfd = socket + 1;
2040 #else
2041 socklen_t len;
2042 maxfd = socket + 1;
2043 #endif // GCC_VERSION < 40000
2044 #else
2045 socklen_t len;
2046 maxfd = socket + 1;
2047 #endif
2048 #endif
2049
2050 if (timeout > 0) {
2051 ldiv_t d = ldiv(timeout*1000, 1000000);
2052 tv.tv_sec = d.quot;
2053 tv.tv_usec = d.rem;
2054 }
2055
2056 // Check for writability
2057 //printf("ISCON11\n");fflush(stdout);
2058 res = select(maxfd, NULL, &wfds, NULL, &tv);
2059 //printf("ISCON12\n");fflush(stdout);
2060
2061 if (res <= 0)
2062 return false;
2063
2064 //printf("wait res > 0\n");
2065
2066 int error;
2067 len = sizeof(error);
2068
2069 mutex.enter(1000);
2070 //printf("ISCON13\n");fflush(stdout);
2071 if (FD_ISSET(socket, &wfds) != 0) {
2072 if (getsockopt(socket, SOL_SOCKET, SO_ERROR, (char*)&error, &len) != 0) {
2073
2074 int wsaError = utils::GetLastOSErrorNumber();
2075 mutex.leave();
2076 if (wsaError == 0) {
2077 // No error, just unable to send...
2078 return true;
2079 }
2080 #ifdef WINDOWS
2081 else if (wsaError == WSAENETDOWN ) {
2082 return false;
2083 }
2084 else if (wsaError == WSAEFAULT ) {
2085 return false;
2086 }
2087 else if (wsaError == WSAEINPROGRESS ) {
2088 return false;
2089 }
2090 else if (wsaError == WSAEINVAL ) {
2091 return false;
2092 }
2093 else if (wsaError == WSAENOPROTOOPT ) {
2094 if (error == 0) {
2095 return true;
2096 }
2097 }
2098 else if (wsaError == WSAENOTSOCK ) {
2099 return false;
2100 }
2101 #endif
2102 return false;
2103 }
2104 mutex.leave();
2105 if (error == 0)
2106 return true;
2107 }
2108 else
2109 mutex.leave();
2110
2111#endif //_USE_SSL_
2112 return false;
2113}
2114
2115bool SSLConnection::disconnect(uint16 error) {
2116 #ifdef _USE_SSL_
2117 mutex.enter(1000);
2118 if (!ctx || !ssl) {
2119 mutex.leave();
2120 return false;
2121 }
2122 SSL_shutdown(ssl);
2123 SSL_free(ssl);
2124 ssl = NULL;
2125 disconnectInternal(error);
2126 mutex.leave();
2127 return true;
2128 #else // _USE_SSL_
2129 return false;
2130 #endif // _USE_SSL_
2131}
2132
2134 #ifdef _USE_SSL_
2135 if (!ctx || !(ssl = SSL_new(ctx)))
2136 return false;
2137
2138 mutex.enter(1000);
2139 bufferContentLen = 0;
2140 bufferContentPos = 0;
2141 localAddress = localAddr;
2142
2143 socket = s;
2145
2146 // Set blocking mode
2148
2149 struct linger tmp = {1, 0};
2150 setsockopt(s, SOL_SOCKET, SO_LINGER, (char *)&tmp, sizeof(tmp));
2151 int delay = 1;
2152 setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char*) &delay, sizeof(delay));
2153
2154 LogPrint(0, LOG_NETWORK, 2, "SSL connection options set, accepting connection...");
2155
2156 remote = true;
2157 SSL_set_fd(ssl, (int)socket);
2158 int ret = SSL_accept(ssl);
2159 int err;
2160 int errCount = 0;
2161
2162 while (ret == -1) {
2163 err = SSL_get_error(ssl, ret);
2164 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
2165
2166 if ((++errCount) > 10) {
2167 LogPrint(0, LOG_NETWORK, 1, "SSL connection accept took too long, disconnecting...");
2168 SSL_shutdown(ssl);
2169 SSL_free(ssl);
2170 ssl = NULL;
2172 mutex.leave();
2173 return false;
2174 }
2175
2177 ret = SSL_accept(ssl);
2178 }
2179 else {
2180 SSL_shutdown(ssl);
2181 SSL_free(ssl);
2182 ssl = NULL;
2184 mutex.leave();
2185 return false;
2186 }
2187 }
2188
2189 LogPrint(0, LOG_NETWORK, 2, "SSL connection accepted, setting up receiver...");
2190
2191 if (receiver != NULL) {
2192 this->receiver = receiver;
2193 // Start networking thread
2195 LogPrint(0, LOG_NETWORK, 0, "Could not start SSLConnection thread...");
2196 SSL_shutdown(ssl);
2197 SSL_free(ssl);
2198 ssl = NULL;
2200 mutex.leave();
2201 return false;
2202 }
2203 }
2204
2205 mutex.leave();
2206 return true;
2207 #else // _USE_SSL_
2208 return false;
2209 #endif // _USE_SSL_
2210}
2211
2212bool SSLConnection::connect(uint64 addr, uint32 timeoutMS, NetworkDataReceiver* receiver) {
2213 #ifdef _USE_SSL_
2214 // Make client SSL connection; create the client context on demand so the
2215 // verification policy is always applied
2216 if (!ctx && !init()) {
2217 return false;
2218 }
2219 if (!ctx || !(ssl = SSL_new(ctx))) {
2220 LogSSLErrors("SSL_new", 0);
2221 return false;
2222 }
2223
2224 // Hostname verification: when peer verification is on and an expected
2225 // hostname is known (recorded by connect(const char*,...) or set via
2226 // setVerifyHostName), require the peer certificate to match it and
2227 // send SNI. With allowSelfSigned or no hostname (raw IP connects),
2228 // only the chain-of-trust check (or none) applies, as before.
2229 if (!allowSelfSigned && !verifyHostName.empty()) {
2230 if (SSL_set1_host(ssl, verifyHostName.c_str()) != 1) {
2231 LogPrint(0, LOG_NETWORK, 0, "SSL: could not set expected hostname '%s' for verification", verifyHostName.c_str());
2232 SSL_free(ssl);
2233 ssl = NULL;
2234 return false;
2235 }
2236 SSL_set_tlsext_host_name(ssl, verifyHostName.c_str());
2237 }
2238
2239 mutex.enter(1000);
2240 if (timeoutMS) {
2241 if (!connectTimeoutMS)
2242 connectTimeoutMS = timeoutMS;
2243 }
2244 else
2245 timeoutMS = connectTimeoutMS;
2246 if((socket=::socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET){
2247 LogPrint(0, LOG_NETWORK, 0, "Could not create SSLListener socket (%d)...", utils::GetLastOSErrorNumber());
2248 mutex.leave();
2249 return false;
2250 }
2251
2252 bufferContentLen = 0;
2253 bufferContentPos = 0;
2254
2255 // Set blocking mode
2257
2258 struct sockaddr_in saServer;
2259 saServer.sin_family = AF_INET;
2260 saServer.sin_port = htons(GETIPPORT(addr));
2261 memcpy(&saServer.sin_addr.s_addr, &addr, 4);
2262
2263
2264 // Connect to the server
2265 int res;
2266 if ((res = ::connect(socket, (struct sockaddr*)&saServer, sizeof(struct sockaddr))) != 0) {
2267
2268 int err = utils::GetLastOSErrorNumber();
2269 if ( (err == SOCKETWOULDBLOCK) || (err == SOCKETTRYAGAIN) ) {
2270 if (!didConnect(1000)) {
2271 SSL_free(ssl);
2272 ssl = NULL;
2274 mutex.leave();
2275 return false;
2276 }
2277 }
2278 else {
2279 SSL_free(ssl);
2280 ssl = NULL;
2282 mutex.leave();
2283 return false;
2284 }
2285 }
2286
2287 struct linger tmp = {1, 0};
2288 setsockopt(socket, SOL_SOCKET, SO_LINGER, (char *)&tmp, sizeof(tmp));
2289 int delay = 1;
2290 setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char*) &delay, sizeof(delay));
2291
2292 // Connect the SSL struct to our connection
2293 if (!SSL_set_fd (ssl, (int)socket)) {
2294 LogSSLErrors("SSL_set_fd", 0);
2295 SSL_free(ssl);
2296 ssl = NULL;
2298 mutex.leave();
2299 return false;
2300 }
2301
2302 //SSL_set_connect_state(ssl);
2303 SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
2304
2305 // Set blocking mode
2306 // utils::SetSocketNonBlockingMode(socket);
2307
2308 int ret; //, err;
2309 // Initiate SSL handshake
2310 while ( (ret = SSL_connect(ssl)) != 1) {
2311 switch (SSL_get_error(ssl, ret)) {
2312 case SSL_ERROR_WANT_READ:
2314 break;
2315 case SSL_ERROR_WANT_WRITE:
2317 break;
2318 default:
2319 // Handshake failed (e.g. peer certificate verification failed).
2320 // Log at level 1 so the detail is available with network logging
2321 // on, but stays off the console in quiet runs (incl. the unit
2322 // test harness's negative-path verify tests).
2323 LogSSLErrors("handshake failed", 1);
2324 SSL_free(ssl);
2325 ssl = NULL;
2327 mutex.leave();
2328 return false;
2329 }
2330 //err = SSL_get_error(ssl, ret);
2331 //if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
2332 // utils::WaitForSocketWriteability(socket, 200);
2333 // if ( (ret = SSL_connect(ssl)) != 1) {
2334 // ERR_print_errors_fp(stderr);
2335 // disconnect();
2336 // mutex.leave();
2337 // return false;
2338 // }
2339 //}
2340 }
2341
2342 uint32 certnamemax = 1000;
2343 char *certname;
2344 X509 *cert = NULL;
2345
2346 cert = SSL_get_peer_certificate(ssl);
2347 if (cert != NULL) {
2348 certname = new char[certnamemax+1];
2349 certinfo = X509_NAME_oneline(X509_get_subject_name(cert), certname, certnamemax);
2350 delete [] certname;
2351 X509_free(cert);
2352 }
2353
2354 if (receiver != NULL) {
2355 this->receiver = receiver;
2356 // Start networking thread
2358 LogPrint(0, LOG_NETWORK, 0, "Could not start SSLConnection thread...");
2359 SSL_free(ssl);
2360 ssl = NULL;
2362 mutex.leave();
2363 return false;
2364 }
2365 }
2366
2367 remoteAddress = addr;
2368 remote = false;
2369
2370 mutex.leave();
2371 return true;
2372 #else // _USE_SSL_
2373 return false;
2374 #endif // _USE_SSL_
2375}
2376
2377bool SSLConnection::connect(const char* addr, uint16 port, uint64& location, uint32 timeoutMS, NetworkDataReceiver* receiver) {
2378 #ifdef _USE_SSL_
2379 uint32 address;
2380 if (!utils::LookupIPAddress(addr, address))
2381 return false;
2382 // Record the hostname for certificate hostname verification (unless one
2383 // was set explicitly, or addr is an IP literal)
2384 if (verifyHostName.empty() && addr && (inet_addr(addr) == INADDR_NONE))
2385 verifyHostName = addr;
2386 return connect(location = GETIPADDRESSPORT(address, port), timeoutMS, receiver);
2387 #else // _USE_SSL_
2388 return false;
2389 #endif // _USE_SSL_
2390}
2391
2392bool SSLConnection::connect(const uint32* addresses, uint16 addressCount, uint16 port, uint64& location, uint32 timeoutMS, NetworkDataReceiver* receiver) {
2393 #ifdef _USE_SSL_
2394 // Try all addresses
2395 for (uint16 n=0; n<addressCount; n++) {
2396 if (connect(location = GETIPADDRESSPORT(addresses[n], port), timeoutMS, receiver))
2397 return true;
2398 }
2399 return false;
2400 #else // _USE_SSL_
2401 return false;
2402 #endif // _USE_SSL_
2403}
2404
2405bool SSLConnection::delayedConnect(uint64 addr, uint32 timeoutMS, NetworkDataReceiver* receiver) {
2406 #ifdef _USE_SSL_
2407 mutex.enter(1000);
2408
2409 connectTimeoutMS = timeoutMS;
2410 remoteAddress = addr;
2411 remote = false;
2412
2413 if (receiver != NULL) {
2414 this->receiver = receiver;
2415 // Start networking thread
2417 LogPrint(0, LOG_NETWORK, 0, "Could not start SSLConnection thread...");
2418 mutex.leave();
2419 return false;
2420 }
2421 }
2422
2423 mutex.leave();
2424 return true;
2425 #else // _USE_SSL_
2426 return false;
2427 #endif // _USE_SSL_
2428}
2429
2430bool SSLConnection::delayedConnect(const char* addr, uint16 port, uint64& location, uint32 timeoutMS, NetworkDataReceiver* receiver) {
2431 #ifdef _USE_SSL_
2432 // Resolve address
2433 uint32 address;
2434 if (!utils::LookupIPAddress(addr, address))
2435 return false;
2436 // Record the hostname for certificate hostname verification (unless one
2437 // was set explicitly, or addr is an IP literal)
2438 if (verifyHostName.empty() && addr && (inet_addr(addr) == INADDR_NONE))
2439 verifyHostName = addr;
2440 return delayedConnect(location = GETIPADDRESSPORT(address, port), timeoutMS, receiver);
2441 #else // _USE_SSL_
2442 return false;
2443 #endif // _USE_SSL_
2444}
2445
2446bool SSLConnection::send(const char* data, uint32 size, uint64 receiver) {
2447 #ifdef _USE_SSL_
2448 if (!size)
2449 return false;
2450 // Ignore receiver, only for UDP
2451 if (!sendMutex.enter(500))
2452 return false;
2453 if (!ssl) {
2454 sendMutex.leave();
2455 return false;
2456 }
2457 uint64 start = GetTimeNow();
2458 //utils::SetSocketBlockingMode(socket);
2459
2460 int ret;
2461 while ( (ret = SSL_write(ssl, data, size)) <= 0) {
2462 switch (SSL_get_error(ssl, ret)) {
2463 case SSL_ERROR_WANT_READ:
2465 break;
2466 case SSL_ERROR_WANT_WRITE:
2468 break;
2469 default:
2470 sendMutex.leave();
2472 return false;
2473 }
2474 }
2475
2476 if (ret < (int)size) {
2477 sendMutex.leave();
2479 return false;
2480 }
2482 //utils::SetSocketNonBlockingMode(socket);
2483
2484 int64 t = GetTimeAge(start);
2485 if (t > 0)
2486 outputSpeed = (uint32)(size*1000000.0/(double)t);
2487 outputBytes += size;
2488 sendMutex.leave();
2489
2490 #ifdef TCPCON_PRINT_DEBUG
2491 if (size < 1024) {
2492 char* tmp = new char[size+1];
2493 memcpy(tmp, data, size);
2494 tmp[size] = 0;
2495 LogPrint(0,LOG_NETWORK,0,">>>>>>> SEND >>>>>>>> SSL Sent %u bytes '%s'\n", size, tmp);
2496 delete [] tmp;
2497 }
2498 else {
2499 #ifdef TCPCON_PRINTBINARY_DEBUG
2500 char* tmp = new char[size+1];
2501 memcpy(tmp, data, size);
2502 tmp[size] = 0;
2503 LogPrint(0,LOG_NETWORK,0,">>>>>>> SEND >>>>>>>> SSL Sent %u bytes '%s'\n", size, tmp);
2504 delete [] tmp;
2505 #endif
2506 }
2507 #endif
2508 return true;
2509 #else // _USE_SSL_
2510 return false;
2511 #endif // _USE_SSL_
2512}
2513
2514
2515
2516bool SSLConnection::reconnect(uint32 timeoutMS) {
2517 #ifdef _USE_SSL_
2518 disconnect();
2519 return connect(remoteAddress, timeoutMS, receiver);
2520 #else // _USE_SSL_
2521 return false;
2522 #endif // _USE_SSL_
2523}
2524
2525
2527
2528 if (socket == INVALID_SOCKET)
2529 return false;
2530
2531 struct sockaddr_in remoteAddr;
2532
2533 #ifdef WINDOWS
2534 int remoteAddrLen;
2535 #else
2536 #ifdef Darwin
2537 #if GCC_VERSION < 40000
2538 int remoteAddrLen;
2539 #else
2540 socklen_t remoteAddrLen;
2541 #endif // GCC_VERSION < 40000
2542 #else
2543 socklen_t remoteAddrLen;
2544 #endif
2545 #endif // WINDOWS
2546
2547 remoteAddrLen = sizeof(struct sockaddr_in);
2548
2549 if (getpeername(socket, (struct sockaddr*) &remoteAddr, &remoteAddrLen) != 0)
2550 return false;
2551
2552 uint32 address = remoteAddr.sin_addr.s_addr;
2553 if ( address == LOCALHOSTIP ) {
2554 // Get the actual local ip address, if possible
2555 utils::GetLocalIPAddress(address);
2556 }
2557 addr = GETIPADDRESSPORT(address, (uint16)remoteAddr.sin_port);
2558 return true;
2559}
2560
2562 #ifdef _USE_SSL_
2563 mutex.enter(1000);
2564 if (!ssl) {
2565 mutex.leave();
2566 return -1;
2567 }
2568 // and read from the socket
2569 // int count = ::recvfrom(socket,buffer+bufferContentLen,bufferLen-bufferContentLen,MSG_PEEK,NULL,0);
2570 int count = SSL_pending(ssl);
2571 mutex.leave();
2572 return count;
2573 #else // _USE_SSL_
2574 return -1;
2575 #endif // _USE_SSL_
2576}
2577
2579
2580 // Assume that the mutex is locked
2581
2582 #ifdef _USE_SSL_
2583
2584 if (!ssl)
2585 return -1;
2586
2587 int32 count = 0;
2588 int pending = SSL_pending(ssl);
2589 if (pending <= 0)
2590 return 0;
2591
2592 // Check for buffer resize
2593 if ((int32)bufferLen-(int32)bufferContentLen < pending) {
2594 if ((int32)bufferLen-(int32)bufferContentLen + (int32)bufferContentPos > pending) {
2597 bufferContentPos = 0;
2598 }
2599 else
2601 }
2602
2603 // Read pending bytes from the socket
2604 count = SSL_read(ssl, buffer+bufferContentLen, pending);
2605
2606 if (count < 0)
2607 return 0;
2608 else if (count == 0) {
2610 return -1;
2611 }
2612
2613 #ifdef TCPCON_PRINT_DEBUG
2614 char* tmp = new char[count+1];
2615 memcpy(tmp, buffer+bufferContentLen, count);
2616 tmp[count] = 0;
2617 LogPrint(0,LOG_NETWORK,0,"<<<<<<< SSL READINTOBUFFER <<<<<<<< TCP RECV BUF %u bytes '%s'\n", count, tmp);
2618 delete [] tmp;
2619 #endif
2620
2621 bufferContentLen += count;
2622
2623 return count;
2624 #else // _USE_SSL_
2625 return -1;
2626 #endif // _USE_SSL_
2627}
2628
2629bool SSLConnection::receiveAvailable(char* data, uint32& size, uint32 maxSize, uint32 timeout, bool peek) {
2630
2631 #ifdef _USE_SSL_
2632 mutex.enter(1000);
2633
2634 if (!ssl) {
2635 mutex.leave();
2636 return false;
2637 }
2638
2640 if (bufferContentPos > maxSize) {
2643 bufferContentPos = 0;
2644 }
2645 else
2646 resizeBuffer((bufferLen+maxSize) * 2);
2647 }
2648
2649 uint64 start = GetTimeNow(), timespent;
2650
2651 int count, err, timeleft;
2652 // Do we have enough data in the buffer already
2653 while (bufferContentLen - bufferContentPos < maxSize) {
2654 // and read from the socket
2655 count = SSL_read(ssl,buffer+bufferContentLen,bufferLen-bufferContentLen);
2656 if(count <= 0) {
2657 err = SSL_get_error(ssl, count);
2658 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
2659 }
2660 else {
2661 mutex.leave();
2663 return false;
2664 }
2665 }
2666 else if (count > 0) {
2667 #ifdef TCPCON_PRINT_DEBUG
2668 char* tmp = new char[count+1];
2669 memcpy(tmp, buffer+bufferContentLen, count);
2670 tmp[count] = 0;
2671 LogPrint(0,LOG_NETWORK,0,"<<<<<<< RECEIVE <<<<<<<< TCP RECV AVAIL %u bytes '%s'\n", count, tmp);
2672 delete [] tmp;
2673 #endif
2674 bufferContentLen += count;
2675 if (bufferContentLen - bufferContentPos >= maxSize)
2676 break;
2677 }
2678 if ((timespent = (GetTimeNow() - start)/1000) >= timeout) {
2679 // if (timeout > 0)
2680 // printf("**** TCP::receive available %u ***\n", bufferContentLen - bufferContentPos);
2681 break;
2682 }
2683 else {
2684 mutex.leave();
2685 timeleft = (int)(timeout-timespent);
2686 utils::WaitForSocketReadability(socket, timeleft < 50 ? timeleft : 50);
2687 }
2688 mutex.enter(1000);
2689 }
2690
2692 if (size > maxSize)
2693 size = maxSize;
2694
2695 inputBytes += size;
2696 if ( size > 0 ) {
2697 memcpy(data, buffer+bufferContentPos, size);
2698 if (!peek) {
2699 bufferContentPos += size;
2702 }
2703 }
2704 mutex.leave();
2705 return true;
2706 #else // _USE_SSL_
2707 return false;
2708 #endif // _USE_SSL_
2709}
2710
2711bool SSLConnection::receive(char* data, uint32 size, uint32 timeout, bool peek) {
2712
2713 #ifdef _USE_SSL_
2714 mutex.enter(1000);
2715
2716 if (!ssl) {
2717 mutex.leave();
2718 return false;
2719 }
2720
2722 if (bufferContentPos > size) {
2725 bufferContentPos = 0;
2726 }
2727 else
2728 resizeBuffer((bufferLen+size) * 2);
2729 }
2730
2731 uint64 start = GetTimeNow();
2732 int32 timespent;
2733
2734 int count, err, timeleft;
2735 // Do we have enough data in the buffer already
2736 while (bufferContentLen - bufferContentPos < size) {
2737 if (!ssl) {
2738 mutex.leave();
2739 return false;
2740 }
2741
2742 // and read from the socket
2743
2744 // int count = ::recvfrom(socket,buffer+bufferContentLen,bufferLen-bufferContentLen,0,NULL,0);
2745
2746 count = SSL_read((SSL *)ssl, buffer+bufferContentLen,size);
2747
2748 if(count <= 0) {
2749 err = SSL_get_error(ssl, count);
2750 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
2751 }
2752 else {
2753 mutex.leave();
2755 return false;
2756 }
2757 }
2758 else if (count > 0) {
2759 #ifdef TCPCON_PRINTBINARY_DEBUG
2760 char* tmp = new char[count+1];
2761 memcpy(tmp, buffer+bufferContentLen, count);
2762 tmp[count] = 0;
2763 LogPrint(0,LOG_NETWORK,0,"<<<<<<<< RECEIVE <<<<<<< TCP RECV %u bytes '%s'", count, tmp);
2764 delete [] tmp;
2765 #endif
2766 bufferContentLen += count;
2767 if (bufferContentLen - bufferContentPos >= size)
2768 break;
2769 }
2770 if ((timespent = GetTimeAgeMS(start)) >= (int32)timeout) {
2771 // printf("**** TCP::receive only got %u out of %u bytes ***\n", bufferContentLen - bufferContentPos, size);
2772 mutex.leave();
2773 return false;
2774 }
2775 else {
2776 //utils::Sleep(5);
2777 //uint64 t = GetTimeNow();
2778 mutex.leave();
2779 timeleft = (int)(timeout-timespent);
2780 utils::WaitForSocketReadability(socket, timeleft < 50 ? timeleft : 50);
2781 //printf("WaitForRead: %lu (%lu)\n", GetTimeAgeMS(t), timeout-timespent);
2782 }
2783 mutex.enter(1000);
2784 }
2785
2786 int64 t = GetTimeAge(start);
2787 if (t > 0)
2788 inputSpeed = (uint32)(size*1000000.0/(double)t);
2789 inputBytes += size;
2790
2791 memcpy(data, buffer+bufferContentPos, size);
2792 if (!peek) {
2793 bufferContentPos += size;
2796 }
2797 mutex.leave();
2798 return true;
2799 #else // _USE_SSL_
2800 return false;
2801 #endif // _USE_SSL_
2802}
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2814 if (arg == NULL) thread_ret_val(1);
2815 thread_ret_val((int)(((TCPListener*)arg)->run() ? 0 : 1));
2816}
2817
2819 if (arg == NULL) thread_ret_val(1);
2820 thread_ret_val((int)(((TCPConnection*)arg)->run() ? 0 : 1));
2821}
2822
2824 if (arg == NULL) thread_ret_val(1);
2825 thread_ret_val((int)(((UDPConnection*)arg)->run() ? 0 : 1));
2826}
2827
2829 if (arg == NULL) thread_ret_val(1);
2830 thread_ret_val((int)(((SSLConnection*)arg)->run() ? 0 : 1));
2831}
2832
2833
2834
2835bool NetworkTest_TCPServer(uint16 port, uint32 count2) {
2836 uint32 period = 100000;
2837
2838 TCPListener* listener = new TCPListener();
2839 if (!listener->init(port, NOENC)) {
2840 delete(listener);
2841 printf("Could not bind to port %u, exiting... \n\n", port);
2842 return false;
2843 }
2844
2845 char* startdata = new char[12], *data;
2846 uint32 size, count;
2847 NetworkConnection* con;
2848 uint32 c = 0;
2849 while (true) {
2850 c = 0;
2851 printf("\n\nListening to port %u for a new connection... ", port);
2852 while ( (con = listener->acceptConnection(10000)) == NULL) {}
2853
2854 while (con->isConnected()) {
2855 // Reading count and size
2856 if (!con->receive(startdata, 12, 10000)) {
2857 printf("[%u] Could not receive start data, exiting...\n", c);
2858 break;
2859 }
2860 if ((*(uint32*)startdata) != 123456789) {
2861 printf("[%u] Start data wrong, exiting...\n", c);
2862 break;
2863 }
2864 size = *(((uint32*)startdata)+1);
2865 count = *(((uint32*)startdata)+2);
2866 c = 0;
2867 data = new char[size];
2868
2869 printf("Got it - starting test with size %u and count %u...\n\n", size, count);
2870
2871 while (con->isConnected() && (c++ < count) ) {
2872 if (!con->receive(data, size, 10000)) {
2873 printf("[%u] Could not receive data %u, exiting...\n", port, c);
2874 break;
2875 }
2876 if (!con->send(data, size)) {
2877 printf("[%u] Could not send data %u, exiting...\n", port, c);
2878 break;
2879 }
2880 }
2881 delete [] data;
2882 }
2883 delete(con);
2884
2885
2886 //while (con->isConnected()) {
2887 // t1 = GetTimeNow();
2888 // if (!NetworkTest_SendReceiveData(con, data, dataLen, c, true)) {
2889 // delete(con);
2890 // break;
2891 // }
2892 // t2 = GetTimeNow();
2893 // d += t2-t1;
2894 // if ((c > 0) && (c % period == 0)) {
2895 // printf("Round time: %.3f us...\n", (double)d/period);
2896 // d = 0;
2897 // }
2898 // c++;
2899 // if ( (count > 0) && (c > count) ) {
2900 // delete(con);
2901 // delete(listener);
2902 // return true;;
2903 // }
2904 //}
2905
2906 }
2907 delete [] startdata;
2908 return true;
2909}
2910
2911
2912bool NetworkTest_TCPClient(const char* address, uint16 port, uint32 count2) {
2913 TCPConnection* con = new TCPConnection();
2914 uint64 location;
2915 if (!con->connect(address, port, location, 5000)) {
2916 delete(con);
2917 printf("Could not connect to '%s' on port %u, exiting...\n", address, port);
2918 return false;
2919 }
2920 printf("Connected to '%s' on port %u, starting test...\n", address, port);
2921
2922 char* startdata = new char[12];
2923 memset(startdata, 0, 12);
2924 *((uint32*)startdata) = 123456789;
2925
2926 uint32 maxSize = 1024*64, innercount = 20, count = 1000, steps = 64, s, c, step;
2927 char* data = new char[maxSize];
2928 double* vals = new double[count];
2929 double* avgvals = new double[steps];
2930 double* maxvals = new double[steps];
2931 double* minvals = new double[steps];
2932 double* stdvals = new double[steps];
2933 double sum, avg, mx, mn, std;
2934
2935 uint64 t1, t2;
2936
2937 while (con->isConnected()) {
2938
2939 for (step=0; step<steps; step++) {
2940 s = (maxSize/steps*(step+1));
2941 *(((uint32*)startdata)+1) = s;
2942 *(((uint32*)startdata)+2) = count * innercount;
2943 if (!con->send(startdata, 12)) {
2944 printf("[%u] Could not send startdata, exiting...\n", port);
2945 break;
2946 }
2947 printf("Step %u size %u...\n", step, s);
2948 for (c=0; c<count; c++) {
2949 t1 = GetTimeNow();
2950 for (uint32 i=0; i<innercount; i++) {
2951 if (!con->send(data, s)) {
2952 printf("[%u] Could not send data %u, exiting...\n", port, c);
2953 break;
2954 }
2955 if (!con->receive(data, s, 10000)) {
2956 printf("[%u] Could not receive data %u, exiting...\n", port, c);
2957 break;
2958 }
2959 }
2960 t2 = GetTimeNow();
2961 vals[c] = (t2-t1)/(double)innercount;
2962 }
2963
2964 sum = avg = std = 0;
2965 mx = mn = vals[0];
2966 for (c=0; c<count; c++) {
2967 sum += vals[c];
2968 if (vals[c] > mx) mx = vals[c];
2969 if (vals[c] < mn) mn = vals[c];
2970 }
2971 avg = sum/count;
2972
2973 sum = 0;
2974 for (c=0; c<count; c++)
2975 sum += pow((vals[c] - avg), 2);
2976 std = sqrt(sum/count-1);
2977
2978 avgvals[step] = avg;
2979 maxvals[step] = mx;
2980 minvals[step] = mn;
2981 stdvals[step] = std;
2982 }
2983
2984 printf("Test results (size, avg, min, max, std in us):\n");
2985 for (step=0; step<steps; step++) {
2986 s = (maxSize/steps*(step+1));
2987 printf("%u %u %.3f %.3f %.3f %.3f\n",
2988 step, s, avgvals[step], minvals[step], maxvals[step], stdvals[step]);
2989 }
2990
2991 break;
2992 }
2993
2994 delete [] startdata;
2995 delete [] data;
2996 delete [] vals;
2997 delete [] avgvals;
2998 delete [] maxvals;
2999 delete [] minvals;
3000 delete [] stdvals;
3001
3002
3003
3004
3005// strcpy(data+(2*sizeof(uint32)), "Testing");
3006
3007// utils::PrintBinary(data, dataLen, true, "Initial Structure");
3008
3009// uint32 c = 0;
3010// uint64 t1, t2, d = 0;
3011
3012
3013
3014
3015
3016
3017 //while (con->isConnected()) {
3018 // t1 = GetTimeNow();
3019 // if (!NetworkTest_SendReceiveData(con, data, dataLen, c)) {
3020 // delete(con);
3021 // return false;
3022 // }
3023 // t2 = GetTimeNow();
3024 // d += t2-t1;
3025 // if ((c > 0) && (c % period == 0)) {
3026 // printf("Round time: %.3f us...\n", (double)d/period);
3027 // d = 0;
3028 // }
3029 // c++;
3030 // if ( (count > 0) && (c > count) )
3031 // break;
3032 //}
3033 delete(con);
3034 return true;
3035}
3036
3037bool NetworkTest_SendReceiveData(TCPConnection* con, char* data, uint32 dataLen, uint32 c, bool receiveFirst) {
3038
3039 uint32 expectC = c*2;
3040 if (!receiveFirst) {
3041 expectC++;
3042 // Send data
3043 if (!con->send(data, dataLen)) {
3044 printf("[%u] Could not send data, exiting...\n", c);
3045 return false;
3046 }
3047 //utils::PrintBinary(data, dataLen, true, "Send1");
3048 }
3049
3050 memset(data, 0, dataLen);
3051 // Wait for reply data
3052 if (!con->receive(data, dataLen, 10000)) {
3053 printf("[%u] Could not receive data, exiting...\n", c);
3054 return false;
3055 }
3056 //utils::PrintBinary(data, dataLen, true, "Receive");
3057 // Check reply data
3058 if (*(uint32*)data != dataLen) {
3059 printf("[%u] Did not receive correct length (%u != %u), exiting...\n", c, *(uint32*)data, dataLen);
3060 // utils::PrintBinary(data, dataLen, true, "Structure");
3061 return false;
3062 }
3063 // Check reply data
3064 if (*((uint32*)data+1) != expectC) {
3065 printf("[%u] Did not receive correct count (%u != %u), exiting...\n", c, *((uint32*)data+1), expectC);
3066 // utils::PrintBinary(data, dataLen, true, "Structure");
3067 return false;
3068 }
3069 // Check reply data
3070 if (strcmp(data+(2*sizeof(uint32)), "Testing") != 0) {
3071 data[dataLen-1] = 0;
3072 printf("[%u] Did not receive correct text ('%s' != 'Testing'), exiting...\n", c, data+(2*sizeof(uint32)));
3073 // utils::PrintBinary(data, dataLen, true, "Structure");
3074 return false;
3075 }
3076 *((uint32*)data+1) = *((uint32*)data+1) + 1;
3077
3078// printf("[%u] Receive OK\n", c);
3079 if (receiveFirst) {
3080 // Send data
3081 if (!con->send(data, dataLen)) {
3082 printf("[%u] Could not send data, exiting...\n", c);
3083 return false;
3084 }
3085 //utils::PrintBinary(data, dataLen, true, "Send2");
3086 }
3087 return true;
3088}
3089
3090
3091}
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:1505
#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:1439
#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:1498
#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:1504
struct sockaddr SOCKADDR
Definition Utils.h:135
#define GETIPPORT(a)
Definition Utils.h:1502
#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:2830
const char * stristr(const char *str, const char *substr, uint32 len=0)
Case-insensitive strstr.
Definition Utils.cpp:6442
int GetLastOSErrorNumber()
Get the last OS error number (errno / GetLastError()).
Definition Utils.cpp:5649
bool WaitForSocketReadability(SOCKET s, int32 timeout)
Wait until a socket has data to read.
Definition Utils.cpp:5707
bool WaitForSocketWriteability(SOCKET s, int32 timeout)
Wait until a socket can be written without blocking.
Definition Utils.cpp:5675
bool GetLocalIPAddress(uint32 &address)
Get the primary local IPv4 address.
Definition Utils.cpp:6029
bool LookupIPAddress(const char *name, uint32 &address)
Resolve a hostname to an IPv4 address.
Definition Utils.cpp:5768
bool SetSocketNonBlockingMode(SOCKET s)
Put a socket into non-blocking mode.
Definition Utils.cpp:5744
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.