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