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