10 #include <arpa/inet.h>
55void TCPListener::disconnectInternal(uint16 error) {
62 if (receiver && error)
68 disconnectInternal(error);
84 this->encryption = encryption;
85 memcpy(((
char*)&localAddress)+
sizeof(uint32), &port,
sizeof(uint16));
89 if((socket=::socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==
INVALID_SOCKET){
99 setsockopt(socket, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (
char *) &one,
sizeof(one));
111 setsockopt(socket,SOL_SOCKET,SO_REUSEADDR,&one,
sizeof(one));
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);
121 disconnectInternal(0);
130 disconnectInternal(0);
135 if (receiver != NULL) {
136 this->receiver = receiver;
140 disconnectInternal(0);
145 this->dataReceiver = dataReceiver;
157 this->sslCertPath = sslCertPath;
158 this->sslKeyPath = sslKeyPath;
170 while ( (timespent = (
GetTimeNow() - start)/1000) < timeout) {
173 new_sock = accept(socket, NULL, NULL);
175 if ((
int) new_sock < 0) {
184 LogPrint(0,
LOG_NETWORK, 2,
"Shutting down network listener with error code: %d", new_sock);
187 if (err != WSAENOTSOCK)
198 if (encryption ==
SSLENC) {
201 if (!sslCon->
init(sslCertPath.c_str(), sslKeyPath.c_str())) {
210 if (!sslCon->
connect(new_sock, localAddress, dataReceiver)) {
219 else if (encryption ==
AESENC) {
226 if (!newCon->
connect(new_sock, localAddress, dataReceiver)) {
245bool TCPListener::run() {
248 if (receiver == NULL)
254 if (receiver != NULL)
357 receiver->registerError(error,
this);
368 if (len < 128)
return false;
369 char* newBuffer =
new char[len];
412#ifdef TCPCON_PRINT_DEBUG
432 if (err != WSAENOTSOCK)
469 #ifdef TCPCON_PRINT_DEBUG
472 char* tmp =
new char[count+1];
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);
484 #ifdef UDPCON_PRINT_DEBUG
487 char* tmp =
new char[count+1];
490 LogPrint(0,
LOG_NETWORK,0,
"<<<<<<< READINTOBUFFER <<<<<<<< UDP RECV BUF %u bytes '%s'\n", count, tmp);
538 if (!c && dataAvailable) {
546 if ((timespent =
GetTimeAgeMS(start)) >= (int32)timeout)
607 if ((timespent =
GetTimeAgeMS(start)) >= (int32)timeout) {
622 inputSpeed = (uint32)(size*1000000.0/(
double)t);
688 if (!
mutex.enter(1000))
692 int res = recv(
socket, peekBuffer, 1, MSG_PEEK);
710 else if (err == WSAENOTCONN) {}
711 else if (err == WSAENOTSOCK) {}
712 else if (err == WSAEOPNOTSUPP) {}
751 #if GCC_VERSION < 40000
765 ldiv_t d = ldiv(timeout*1000, 1000000);
771 res = select(maxfd, NULL, &wfds, NULL, &tv);
781 if (!
mutex.enter(1000))
784 if (FD_ISSET(
socket, &wfds) != 0) {
785 if (getsockopt(
socket, SOL_SOCKET, SO_ERROR, (
char*)&error, &len) != 0) {
794 else if (wsaError == WSAENETDOWN ) {
797 else if (wsaError == WSAEFAULT ) {
800 else if (wsaError == WSAEINPROGRESS ) {
803 else if (wsaError == WSAEINVAL ) {
806 else if (wsaError == WSAENOPROTOOPT ) {
811 else if (wsaError == WSAENOTSOCK ) {
844 #if GCC_VERSION < 40000
858 ldiv_t d = ldiv(timeout * 1000, 1000000);
864 int res = select(maxfd, NULL, &wfds, NULL, &tv);
874 if (FD_ISSET(s, &wfds) != 0) {
875 if (getsockopt(s, SOL_SOCKET, SO_ERROR, (
char*)&error, &len) != 0) {
883 else if (wsaError == WSAENETDOWN) {
886 else if (wsaError == WSAEFAULT) {
889 else if (wsaError == WSAEINPROGRESS) {
892 else if (wsaError == WSAEINVAL) {
895 else if (wsaError == WSAENOPROTOOPT) {
900 else if (wsaError == WSAENOTSOCK) {
918 if (!
mutex.enter(1000))
938 #if GCC_VERSION < 40000
952 ldiv_t d = ldiv(timeout * 1000, 1000000);
958 int res = select(maxfd, NULL, &wfds, NULL, &tv);
969 if (FD_ISSET(
socket, &wfds) != 0) {
970 if (getsockopt(
socket, SOL_SOCKET, SO_ERROR, (
char*)&error, &len) != 0) {
979 else if (wsaError == WSAENETDOWN) {
982 else if (wsaError == WSAEFAULT) {
985 else if (wsaError == WSAEINPROGRESS) {
988 else if (wsaError == WSAEINVAL) {
991 else if (wsaError == WSAENOPROTOOPT) {
996 else if (wsaError == WSAENOTSOCK) {
1018 char* myBuffer = (
char*) malloc(buflen);
1019 if (myBuffer == NULL)
1022 LogPrint(0,
LOG_NETWORK, 2,
"Incoming network connection from %u.%u.%u.%u:%u, started run...",
1027 if (
receive((
char*)&size,
sizeof(size), 50,
true)) {
1029 if (buflen < size) {
1031 myBuffer = (
char*) realloc(myBuffer, buflen);
1032 if (myBuffer == NULL) {
1040 if (!
receive(myBuffer, size, 500)) {
1048 receiver->receiveData(myBuffer, size,
this);
1101 setsockopt(
socket, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (
char *) &one,
sizeof(one));
1113 setsockopt(
socket,SOL_SOCKET,SO_REUSEADDR,&one,
sizeof(one));
1116 setsockopt(
socket,SOL_SOCKET,SO_BROADCAST,(
char*)&one,
sizeof(one));
1131 memcpy(((
char*)&
localAddress)+
sizeof(uint32), &port,
sizeof(uint16));
1147 setsockopt(
socket, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (
char *) &one,
sizeof(one));
1159 setsockopt(
socket,SOL_SOCKET,SO_REUSEADDR,&one,
sizeof(one));
1162 setsockopt(
socket,SOL_SOCKET,SO_BROADCAST,(
char*)&one,
sizeof(one));
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);
1197 sockaddr_in recvAddr;
1198 recvAddr.sin_family = AF_INET;
1208 recvAddr.sin_port = htons(p);
1209 memcpy(&recvAddr.sin_addr.s_addr, &rec, 4);
1219 n = ::sendto(
socket, data + pos, size - pos, 0, (
SOCKADDR*)&recvAddr,
sizeof(sockaddr_in));
1254 #ifdef UDPCON_PRINT_DEBUG
1256 char* tmp =
new char[size+1];
1257 memcpy(tmp, data, size);
1263 #ifdef UDPCON_PRINTBINARY_DEBUG
1264 char* tmp =
new char[size+1];
1265 memcpy(tmp, data, size);
1270 char* tmp =
new char[1024];
1271 memcpy(tmp, data, 1023);
1327 struct linger tmp = {1, 0};
1328 setsockopt(
socket, SOL_SOCKET, SO_LINGER, (
char *)&tmp,
sizeof(tmp));
1330 setsockopt(
socket, IPPROTO_TCP, TCP_NODELAY, (
char*) &delay,
sizeof(delay));
1336 LogPrint(0,
LOG_NETWORK, 2,
"Incoming TCP connection from %u.%u.%u.%u:%u, starting run...",
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);
1408 if ((res =
::connect(tempSocket, (
struct sockaddr*)&saServer,
sizeof(
struct sockaddr))) != 0) {
1425 struct linger tmp = {1, 0};
1426 setsockopt(tempSocket, SOL_SOCKET, SO_LINGER, (
char *)&tmp,
sizeof(tmp));
1428 setsockopt(tempSocket, IPPROTO_TCP, TCP_NODELAY, (
char*) &delay,
sizeof(delay));
1435 if (!
mutex.enter(1000)) {
1471 for (uint16 n=0; n<addressCount; n++) {
1594 #ifdef TCPCON_PRINT_DEBUG
1596 char* tmp =
new char[size+1];
1597 memcpy(tmp, data, size);
1599 LogPrint(0,
LOG_NETWORK,0,
">>>>>>> SEND >>>>>>>> TCP Sent %u bytes (%.3f) '%s'\n", size, t/1000.0, tmp);
1603 #ifdef TCPCON_PRINTBINARY_DEBUG
1604 char* tmp =
new char[size+1];
1605 memcpy(tmp, data, size);
1610 char* tmp =
new char[1024];
1611 memcpy(tmp, data, 1023);
1613 LogPrint(0,
LOG_NETWORK,0,
">>>>>>> SEND >>>>>>>> TCP Sent %u bytes (%.3f) '%s'\n", size, t / 1000.0, tmp);
1637 struct sockaddr_in remoteAddr;
1643 #if GCC_VERSION < 40000
1646 socklen_t remoteAddrLen;
1649 socklen_t remoteAddrLen;
1653 remoteAddrLen =
sizeof(
struct sockaddr_in);
1655 if (getpeername(
socket, (
struct sockaddr*) &remoteAddr, &remoteAddrLen) != 0)
1658 uint32 address = remoteAddr.sin_addr.s_addr;
1700 OpenSSL_add_all_algorithms();
1702 ERR_load_crypto_strings();
1703 SSL_load_error_strings();
1705 certbio = BIO_new(BIO_s_file());
1706 outbio = BIO_new_fp(stdout, BIO_NOCLOSE);
1758 applyClientVerify();
1770 applyClientVerify();
1777bool SSLConnection::applyClientVerify() {
1781 SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
1787 if (SSL_CTX_load_verify_locations(ctx,
1795 if (SSL_CTX_set_default_verify_paths(ctx) != 1)
1798 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
1803int SSLConnection::getVerifyMode() {
1806 return SSL_CTX_get_verify_mode(ctx);
1815 const SSL_METHOD *method = SSLv23_server_method();
1817 ctx = SSL_CTX_new(method);
1820 BIO_printf(outbio,
"Unable to create a new SSL context structure.\n");
1826 if ( SSL_CTX_use_certificate_chain_file(ctx, certFile) <= 0) {
1828 ERR_print_errors_fp(stderr);
1832 if ( SSL_CTX_use_PrivateKey_file(ctx, keyFile, SSL_FILETYPE_PEM) <= 0) {
1834 ERR_print_errors_fp(stderr);
1841 if ( !SSL_CTX_check_private_key(ctx) ) {
1843 fprintf(stderr,
"Private key is invalid.\n");
1860 const SSL_METHOD *method = SSLv23_method();
1862 ctx = SSL_CTX_new(method);
1864 BIO_printf(outbio,
"Unable to create a new SSL context structure.\n");
1873 applyClientVerify();
1904 if (!
mutex.enter(200, __FUNCTION__))
1907 int res = recv(
socket, peekBuffer, 1, MSG_PEEK);
1928 else if (err == WSAENOTCONN) {}
1929 else if (err == WSAEOPNOTSUPP) {}
1972 #if GCC_VERSION < 40000
1986 ldiv_t d = ldiv(timeout*1000, 1000000);
1993 res = select(maxfd, NULL, &wfds, NULL, &tv);
2002 len =
sizeof(error);
2006 if (FD_ISSET(
socket, &wfds) != 0) {
2007 if (getsockopt(
socket, SOL_SOCKET, SO_ERROR, (
char*)&error, &len) != 0) {
2011 if (wsaError == 0) {
2016 else if (wsaError == WSAENETDOWN ) {
2019 else if (wsaError == WSAEFAULT ) {
2022 else if (wsaError == WSAEINPROGRESS ) {
2025 else if (wsaError == WSAEINVAL ) {
2028 else if (wsaError == WSAENOPROTOOPT ) {
2033 else if (wsaError == WSAENOTSOCK ) {
2070 if (!ctx || !(ssl = SSL_new(ctx)))
2084 struct linger tmp = {1, 0};
2085 setsockopt(s, SOL_SOCKET, SO_LINGER, (
char *)&tmp,
sizeof(tmp));
2087 setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (
char*) &delay,
sizeof(delay));
2092 SSL_set_fd(ssl, (
int)
socket);
2093 int ret = SSL_accept(ssl);
2098 err = SSL_get_error(ssl, ret);
2099 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
2101 if ((++errCount) > 10) {
2112 ret = SSL_accept(ssl);
2151 if (!ctx && !
init()) {
2154 if (!ctx || !(ssl = SSL_new(ctx))) {
2155 ERR_print_errors_fp(stdout);
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);
2201 if ((res =
::connect(
socket, (
struct sockaddr*)&saServer,
sizeof(
struct sockaddr))) != 0) {
2222 struct linger tmp = {1, 0};
2223 setsockopt(
socket, SOL_SOCKET, SO_LINGER, (
char *)&tmp,
sizeof(tmp));
2225 setsockopt(
socket, IPPROTO_TCP, TCP_NODELAY, (
char*) &delay,
sizeof(delay));
2228 if (!SSL_set_fd (ssl, (
int)
socket)) {
2229 ERR_print_errors_fp(stdout);
2238 SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
2245 while ( (ret = SSL_connect(ssl)) != 1) {
2246 switch (SSL_get_error(ssl, ret)) {
2247 case SSL_ERROR_WANT_READ:
2250 case SSL_ERROR_WANT_WRITE:
2254 ERR_print_errors_fp(stderr);
2273 uint32 certnamemax = 1000;
2277 cert = SSL_get_peer_certificate(ssl);
2279 certname =
new char[certnamemax+1];
2280 certinfo = X509_NAME_oneline(X509_get_subject_name(cert), certname, certnamemax);
2315 if (
verifyHostName.empty() && addr && (inet_addr(addr) == INADDR_NONE))
2326 for (uint16 n=0; n<addressCount; n++) {
2369 if (
verifyHostName.empty() && addr && (inet_addr(addr) == INADDR_NONE))
2392 while ( (ret = SSL_write(ssl, data, size)) <= 0) {
2393 switch (SSL_get_error(ssl, ret)) {
2394 case SSL_ERROR_WANT_READ:
2397 case SSL_ERROR_WANT_WRITE:
2407 if (ret < (
int)size) {
2421 #ifdef TCPCON_PRINT_DEBUG
2423 char* tmp =
new char[size+1];
2424 memcpy(tmp, data, size);
2430 #ifdef TCPCON_PRINTBINARY_DEBUG
2431 char* tmp =
new char[size+1];
2432 memcpy(tmp, data, size);
2462 struct sockaddr_in remoteAddr;
2468 #if GCC_VERSION < 40000
2471 socklen_t remoteAddrLen;
2474 socklen_t remoteAddrLen;
2478 remoteAddrLen =
sizeof(
struct sockaddr_in);
2480 if (getpeername(
socket, (
struct sockaddr*) &remoteAddr, &remoteAddrLen) != 0)
2483 uint32 address = remoteAddr.sin_addr.s_addr;
2501 int count = SSL_pending(ssl);
2519 int pending = SSL_pending(ssl);
2539 else if (count == 0) {
2544 #ifdef TCPCON_PRINT_DEBUG
2545 char* tmp =
new char[count+1];
2548 LogPrint(0,
LOG_NETWORK,0,
"<<<<<<< SSL READINTOBUFFER <<<<<<<< TCP RECV BUF %u bytes '%s'\n", count, tmp);
2582 int count, err, timeleft;
2588 err = SSL_get_error(ssl, count);
2589 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
2597 else if (count > 0) {
2598 #ifdef TCPCON_PRINT_DEBUG
2599 char* tmp =
new char[count+1];
2602 LogPrint(0,
LOG_NETWORK,0,
"<<<<<<< RECEIVE <<<<<<<< TCP RECV AVAIL %u bytes '%s'\n", count, tmp);
2609 if ((timespent = (
GetTimeNow() - start)/1000) >= timeout) {
2616 timeleft = (int)(timeout-timespent);
2665 int count, err, timeleft;
2680 err = SSL_get_error(ssl, count);
2681 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
2689 else if (count > 0) {
2690 #ifdef TCPCON_PRINTBINARY_DEBUG
2691 char* tmp =
new char[count+1];
2701 if ((timespent =
GetTimeAgeMS(start)) >= (int32)timeout) {
2710 timeleft = (int)(timeout-timespent);
2719 inputSpeed = (uint32)(size*1000000.0/(
double)t);
2767 uint32 period = 100000;
2772 printf(
"Could not bind to port %u, exiting... \n\n", port);
2776 char* startdata =
new char[12], *data;
2782 printf(
"\n\nListening to port %u for a new connection... ", port);
2787 if (!con->
receive(startdata, 12, 10000)) {
2788 printf(
"[%u] Could not receive start data, exiting...\n", c);
2791 if ((*(uint32*)startdata) != 123456789) {
2792 printf(
"[%u] Start data wrong, exiting...\n", c);
2795 size = *(((uint32*)startdata)+1);
2796 count = *(((uint32*)startdata)+2);
2798 data =
new char[size];
2800 printf(
"Got it - starting test with size %u and count %u...\n\n", size, count);
2803 if (!con->
receive(data, size, 10000)) {
2804 printf(
"[%u] Could not receive data %u, exiting...\n", port, c);
2807 if (!con->
send(data, size)) {
2808 printf(
"[%u] Could not send data %u, exiting...\n", port, c);
2838 delete [] startdata;
2846 if (!con->
connect(address, port, location, 5000)) {
2848 printf(
"Could not connect to '%s' on port %u, exiting...\n", address, port);
2851 printf(
"Connected to '%s' on port %u, starting test...\n", address, port);
2853 char* startdata =
new char[12];
2854 memset(startdata, 0, 12);
2855 *((uint32*)startdata) = 123456789;
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;
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);
2878 printf(
"Step %u size %u...\n", step, s);
2879 for (c=0; c<count; c++) {
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);
2886 if (!con->
receive(data, s, 10000)) {
2887 printf(
"[%u] Could not receive data %u, exiting...\n", port, c);
2892 vals[c] = (t2-t1)/(
double)innercount;
2895 sum = avg =
std = 0;
2897 for (c=0; c<count; c++) {
2899 if (vals[c] > mx) mx = vals[c];
2900 if (vals[c] < mn) mn = vals[c];
2905 for (c=0; c<count; c++)
2906 sum += pow((vals[c] - avg), 2);
2907 std = sqrt(sum/count-1);
2909 avgvals[step] = avg;
2912 stdvals[step] =
std;
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]);
2925 delete [] startdata;
2970 uint32 expectC = c*2;
2971 if (!receiveFirst) {
2974 if (!con->
send(data, dataLen)) {
2975 printf(
"[%u] Could not send data, exiting...\n", c);
2981 memset(data, 0, dataLen);
2983 if (!con->
receive(data, dataLen, 10000)) {
2984 printf(
"[%u] Could not receive data, exiting...\n", c);
2989 if (*(uint32*)data != dataLen) {
2990 printf(
"[%u] Did not receive correct length (%u != %u), exiting...\n", c, *(uint32*)data, dataLen);
2995 if (*((uint32*)data+1) != expectC) {
2996 printf(
"[%u] Did not receive correct count (%u != %u), exiting...\n", c, *((uint32*)data+1), expectC);
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)));
3007 *((uint32*)data+1) = *((uint32*)data+1) + 1;
3012 if (!con->
send(data, dataLen)) {
3013 printf(
"[%u] Could not send data, exiting...\n", c);
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 thread_ret_val(ret)
#define THREAD_FUNCTION_CALL
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 getOutputSpeed()
virtual uint32 clearBuffer()
Discard all currently buffered input.
NetworkDataReceiver * receiver
virtual bool waitForDataToBeWritten(uint32 timeout)
Block until the socket is writable.
virtual uint64 getRemoteAddress()
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).
virtual uint8 getConnectionType()
virtual uint32 getInputSpeed()
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.
virtual int32 readIntoBuffer()
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)
static bool DefaultAllowSelfSigned
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.
std::string verifyHostName
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.
int32 GetTimeAgeMS(uint64 t)
Age of a timestamp relative to now, in milliseconds.
int64 GetTimeAge(uint64 t)
Age of a timestamp relative to now.
#define GETIPADDRESSQUAD(a)
int GetLastOSErrorNumber()
Get the last OS error number (errno / GetLastError()).
bool Sleep(uint32 ms)
Suspend the calling thread.
bool WaitForSocketReadability(SOCKET s, int32 timeout)
Wait until a socket has data to read.
bool WaitForSocketWriteability(SOCKET s, int32 timeout)
Wait until a socket can be written without blocking.
bool GetLocalIPAddress(uint32 &address)
Get the primary local IPv4 address.
bool LookupIPAddress(const char *name, uint32 &address)
Resolve a hostname to an IPv4 address.
const char * stristr(const char *str, const char *substr, uint32 len=0)
Case-insensitive strstr.
#define GETIPADDRESSPORT(a, p)
bool SetSocketNonBlockingMode(SOCKET s)
Put a socket into non-blocking mode.
THREAD_RET THREAD_FUNCTION_CALL SSLConnectionRun(THREAD_ARG arg)
bool AESCheckBufferForCompatibility(const char *buffer, uint32 length)
bool SSLCheckBufferForCompatibility(const char *buffer, uint32 length)