1
0
mirror of https://github.com/Ylianst/MeshAgent synced 2025-12-12 22:33:55 +00:00

Added domain socket support on Linux and MacOS

This commit is contained in:
Bryan Roe
2019-01-11 12:37:59 -08:00
parent b8928208d7
commit eaff1c25e4
3 changed files with 210 additions and 55 deletions

View File

@@ -31,6 +31,11 @@ limitations under the License.
#include "ILibAsyncServerSocket.h" #include "ILibAsyncServerSocket.h"
#include "ILibAsyncSocket.h" #include "ILibAsyncSocket.h"
#ifdef _POSIX
#include <sys/socket.h>
#include <sys/un.h>
#endif
#define DEBUGSTATEMENT(x) #define DEBUGSTATEMENT(x)
#define INET_SOCKADDR_LENGTH(x) ((x==AF_INET6?sizeof(struct sockaddr_in6):sizeof(struct sockaddr_in))) #define INET_SOCKADDR_LENGTH(x) ((x==AF_INET6?sizeof(struct sockaddr_in6):sizeof(struct sockaddr_in)))
@@ -621,6 +626,10 @@ ILibAsyncServerSocket_ServerModule ILibCreateAsyncServerSocketModuleWithMemoryEx
struct ILibAsyncServerSocketModule *RetVal; struct ILibAsyncServerSocketModule *RetVal;
struct sockaddr_in6 localAddress; struct sockaddr_in6 localAddress;
#ifdef WIN32
if (local->sa_family == AF_UNIX) { return(NULL); } // NOT YET SUPPORTED on Windows
#endif
// Instantiate a new AsyncServer module // Instantiate a new AsyncServer module
RetVal = (struct ILibAsyncServerSocketModule*)ILibChain_Link_Allocate(sizeof(struct ILibAsyncServerSocketModule), ServerUserMappedMemorySize); RetVal = (struct ILibAsyncServerSocketModule*)ILibChain_Link_Allocate(sizeof(struct ILibAsyncServerSocketModule), ServerUserMappedMemorySize);
@@ -636,6 +645,13 @@ ILibAsyncServerSocket_ServerModule ILibCreateAsyncServerSocketModuleWithMemoryEx
RetVal->MaxConnection = MaxConnections; RetVal->MaxConnection = MaxConnections;
RetVal->AsyncSockets = (void**)malloc(MaxConnections * sizeof(void*)); RetVal->AsyncSockets = (void**)malloc(MaxConnections * sizeof(void*));
if (RetVal->AsyncSockets == NULL) { free(RetVal); ILIBMARKPOSITION(253); return NULL; } if (RetVal->AsyncSockets == NULL) { free(RetVal); ILIBMARKPOSITION(253); return NULL; }
if (local->sa_family == AF_UNIX)
{
// Get our IPC socket
if ((RetVal->ListenSocket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { free(RetVal->AsyncSockets); free(RetVal); return 0; }
}
else
{
RetVal->portNumber = ntohs(((struct sockaddr_in6*)local)->sin6_port); RetVal->portNumber = ntohs(((struct sockaddr_in6*)local)->sin6_port);
RetVal->initialPortNumber = RetVal->portNumber; RetVal->initialPortNumber = RetVal->portNumber;
@@ -644,6 +660,9 @@ ILibAsyncServerSocket_ServerModule ILibCreateAsyncServerSocketModuleWithMemoryEx
// Setup the IPv6 & IPv4 support on same socket // Setup the IPv6 & IPv4 support on same socket
if (((struct sockaddr_in6*)local)->sin6_family == AF_INET6) if (setsockopt(RetVal->ListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&off, sizeof(off)) != 0) ILIBCRITICALERREXIT(253); if (((struct sockaddr_in6*)local)->sin6_family == AF_INET6) if (setsockopt(RetVal->ListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&off, sizeof(off)) != 0) ILIBCRITICALERREXIT(253);
}
#ifdef SO_NOSIGPIPE #ifdef SO_NOSIGPIPE
setsockopt(RetVal->ListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&ra, sizeof(int)); // Turn off SIGPIPE if writing to disconnected socket setsockopt(RetVal->ListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&ra, sizeof(int)); // Turn off SIGPIPE if writing to disconnected socket
@@ -661,17 +680,26 @@ ILibAsyncServerSocket_ServerModule ILibCreateAsyncServerSocketModuleWithMemoryEx
#if defined(WIN32) #if defined(WIN32)
if (bind(RetVal->ListenSocket, local, INET_SOCKADDR_LENGTH(((struct sockaddr_in6*)local)->sin6_family)) != 0) { closesocket(RetVal->ListenSocket); free(RetVal->AsyncSockets); free(RetVal); return 0; } if (bind(RetVal->ListenSocket, local, INET_SOCKADDR_LENGTH(((struct sockaddr_in6*)local)->sin6_family)) != 0) { closesocket(RetVal->ListenSocket); free(RetVal->AsyncSockets); free(RetVal); return 0; }
#else #else
if (local->sa_family == AF_UNIX)
{
if (bind(RetVal->ListenSocket, local, SUN_LEN((struct sockaddr_un*)local)) != 0) { close(RetVal->ListenSocket); free(RetVal->AsyncSockets); free(RetVal); return 0; }
}
else
{
if (bind(RetVal->ListenSocket, local, INET_SOCKADDR_LENGTH(((struct sockaddr_in6*)local)->sin6_family)) != 0) { close(RetVal->ListenSocket); free(RetVal->AsyncSockets); free(RetVal); return 0; } if (bind(RetVal->ListenSocket, local, INET_SOCKADDR_LENGTH(((struct sockaddr_in6*)local)->sin6_family)) != 0) { close(RetVal->ListenSocket); free(RetVal->AsyncSockets); free(RetVal); return 0; }
}
#endif #endif
// Fetch the local port number // Fetch the local port number
#if defined(WINSOCK2) #if defined(WINSOCK2)
getsockname(RetVal->ListenSocket, (struct sockaddr*)&localAddress, (int*)&receivingAddressLength); getsockname(RetVal->ListenSocket, (struct sockaddr*)&localAddress, (int*)&receivingAddressLength);
#else #else
getsockname(RetVal->ListenSocket, (struct sockaddr*)&localAddress, (socklen_t*)&receivingAddressLength); if (local->sa_family != AF_UNIX) { getsockname(RetVal->ListenSocket, (struct sockaddr*)&localAddress, (socklen_t*)&receivingAddressLength); }
#endif #endif
if (local->sa_family != AF_UNIX)
{
if (localAddress.sin6_family == AF_INET6) RetVal->portNumber = ntohs(localAddress.sin6_port); else RetVal->portNumber = ntohs(((struct sockaddr_in*)&localAddress)->sin_port); if (localAddress.sin6_family == AF_INET6) RetVal->portNumber = ntohs(localAddress.sin6_port); else RetVal->portNumber = ntohs(((struct sockaddr_in*)&localAddress)->sin_port);
}
// Create our socket pool // Create our socket pool
for(i = 0; i < MaxConnections; ++i) for(i = 0; i < MaxConnections; ++i)
{ {
@@ -709,10 +737,14 @@ void ILibAsyncServerSocket_GetLocal(ILibAsyncServerSocket_ServerModule ServerSoc
{ {
socklen_t ssize = (socklen_t)addrLen; socklen_t ssize = (socklen_t)addrLen;
if (getsockname(((struct ILibAsyncServerSocketModule*)ServerSocketModule)->ListenSocket, addr, &ssize) != 0) if (getsockname(((struct ILibAsyncServerSocketModule*)ServerSocketModule)->ListenSocket, addr, &ssize) != 0)
{
ssize = (socklen_t)sizeof(struct sockaddr_in);
if (getsockname(((struct ILibAsyncServerSocketModule*)ServerSocketModule)->ListenSocket, addr, &ssize) != 0)
{ {
((struct sockaddr_in6*)addr)->sin6_family = AF_UNSPEC; ((struct sockaddr_in6*)addr)->sin6_family = AF_UNSPEC;
} }
} }
}
/*! \fn ILibAsyncServerSocket_GetPortNumber(ILibAsyncServerSocket_ServerModule ServerSocketModule) /*! \fn ILibAsyncServerSocket_GetPortNumber(ILibAsyncServerSocket_ServerModule ServerSocketModule)
\brief Returns the port number the server is bound to \brief Returns the port number the server is bound to
\param ServerSocketModule The ILibAsyncServer to query \param ServerSocketModule The ILibAsyncServer to query

View File

@@ -47,6 +47,15 @@ limitations under the License.
#include "ILibAsyncSocket.h" #include "ILibAsyncSocket.h"
#include "ILibRemoteLogging.h" #include "ILibRemoteLogging.h"
#ifdef _DEBUG
#include "ILibCrypto.h"
#endif
#ifdef _POSIX
#include <sys/socket.h>
#include <sys/un.h>
#endif
#ifndef MICROSTACK_NOTLS #ifndef MICROSTACK_NOTLS
#include <openssl/err.h> #include <openssl/err.h>
#include <openssl/ssl.h> #include <openssl/ssl.h>
@@ -121,6 +130,9 @@ typedef struct ILibAsyncSocketModule
unsigned int PendingBytesToSend; unsigned int PendingBytesToSend;
unsigned int TotalBytesSent; unsigned int TotalBytesSent;
#ifdef _POSIX
struct sockaddr_un DomainAddress;
#endif
// The IPv4/IPv6 compliant address of the remote endpoint. We are not going to be using IPv6 all the time, // The IPv4/IPv6 compliant address of the remote endpoint. We are not going to be using IPv6 all the time,
@@ -353,8 +365,10 @@ void ILibAsyncSocket_Destroy(void *socketModule)
// If this is an SSL socket, free the SSL state // If this is an SSL socket, free the SSL state
if (module->ssl != NULL) if (module->ssl != NULL)
{ {
SSL_TRACE1("SSL_free()");
SSL_free(module->ssl); // Frees SSL session and BIO buffer at the same time SSL_free(module->ssl); // Frees SSL session and BIO buffer at the same time
module->ssl = NULL; module->ssl = NULL;
SSL_TRACE2("SSL_free()");
} }
#endif #endif
@@ -548,7 +562,9 @@ ILibAsyncSocket_SendStatus ILibAsyncSocket_SendTo_MultiWrite(ILibAsyncSocket_Soc
bufferLen = va_arg(vlist, int); bufferLen = va_arg(vlist, int);
UserFree = va_arg(vlist, ILibAsyncSocket_MemoryOwnership); UserFree = va_arg(vlist, ILibAsyncSocket_MemoryOwnership);
SSL_TRACE1("SSL_write()");
SSL_write(module->ssl, buffer, bufferLen); SSL_write(module->ssl, buffer, bufferLen);
SSL_TRACE2("SSL_write()");
if (UserFree == ILibAsyncSocket_MemoryOwnership_CHAIN) { free(buffer); } if (UserFree == ILibAsyncSocket_MemoryOwnership_CHAIN) { free(buffer); }
} }
va_end(vlist); va_end(vlist);
@@ -669,7 +685,7 @@ ILibAsyncSocket_SendStatus ILibAsyncSocket_SendTo_MultiWrite(ILibAsyncSocket_Soc
else if (module->PendingSend_Tail == NULL && module->FinConnect != 0) else if (module->PendingSend_Tail == NULL && module->FinConnect != 0)
{ {
// No pending data, so we can try to send now // No pending data, so we can try to send now
if (remoteAddress == NULL) if (remoteAddress == NULL || remoteAddress->sa_family == AF_UNIX)
{ {
// Set MSG_NOSIGNAL since we don't want to get Broken Pipe signals in Linux, ignored if Windows. // Set MSG_NOSIGNAL since we don't want to get Broken Pipe signals in Linux, ignored if Windows.
bytesSent = send(module->internalSocket, buffer, bufferLen, MSG_NOSIGNAL); bytesSent = send(module->internalSocket, buffer, bufferLen, MSG_NOSIGNAL);
@@ -754,11 +770,13 @@ void ILibAsyncSocket_Disconnect(ILibAsyncSocket_SocketModule socketModule)
wasssl = module->ssl; wasssl = module->ssl;
if (module->ssl != NULL) if (module->ssl != NULL)
{ {
SSL_TRACE1("ILibAsyncSocket_Disconnect()");
SSL_shutdown(module->ssl); SSL_shutdown(module->ssl);
sem_post(&(module->SendLock)); sem_post(&(module->SendLock));
SSL_free(module->ssl); // Frees SSL session and both BIO buffers at the same time SSL_free(module->ssl); // Frees SSL session and both BIO buffers at the same time
sem_wait(&(module->SendLock)); sem_wait(&(module->SendLock));
module->ssl = NULL; module->ssl = NULL;
SSL_TRACE2("ILibAsyncSocket_Disconnect()");
} }
#endif #endif
@@ -826,7 +844,7 @@ void ILibAsyncSocket_Disconnect(ILibAsyncSocket_SocketModule socketModule)
*/ */
void ILibAsyncSocket_ConnectTo(void* socketModule, struct sockaddr *localInterface, struct sockaddr *remoteInterface, ILibAsyncSocket_OnInterrupt InterruptPtr, void *user) void ILibAsyncSocket_ConnectTo(void* socketModule, struct sockaddr *localInterface, struct sockaddr *remoteInterface, ILibAsyncSocket_OnInterrupt InterruptPtr, void *user)
{ {
int flags = 1; int flags = 1, v;
char *tmp; char *tmp;
struct ILibAsyncSocketModule *module = (struct ILibAsyncSocketModule*)socketModule; struct ILibAsyncSocketModule *module = (struct ILibAsyncSocketModule*)socketModule;
struct sockaddr_in6 any; struct sockaddr_in6 any;
@@ -841,9 +859,22 @@ void ILibAsyncSocket_ConnectTo(void* socketModule, struct sockaddr *localInterfa
memset(&(module->RemoteAddress), 0, sizeof(struct sockaddr_in6)); memset(&(module->RemoteAddress), 0, sizeof(struct sockaddr_in6));
memset(&(module->LocalAddress) , 0, sizeof(struct sockaddr_in6)); memset(&(module->LocalAddress) , 0, sizeof(struct sockaddr_in6));
memset(&(module->SourceAddress), 0, sizeof(struct sockaddr_in6)); memset(&(module->SourceAddress), 0, sizeof(struct sockaddr_in6));
#ifdef _POSIX
memset(&(module->DomainAddress), 0, sizeof(struct sockaddr_un));
#endif
// Setup // Setup
if (remoteInterface->sa_family == AF_UNIX)
{
#ifdef _POSIX
memcpy_s(&(module->DomainAddress), sizeof(struct sockaddr_un), remoteInterface, sizeof(struct sockaddr_un));
#endif
module->RemoteAddress.sin6_family = AF_UNIX;
}
else
{
memcpy_s(&(module->RemoteAddress), sizeof(struct sockaddr_in6), remoteInterface, INET_SOCKADDR_LENGTH(remoteInterface->sa_family)); memcpy_s(&(module->RemoteAddress), sizeof(struct sockaddr_in6), remoteInterface, INET_SOCKADDR_LENGTH(remoteInterface->sa_family));
}
module->PendingBytesToSend = 0; module->PendingBytesToSend = 0;
module->TotalBytesSent = 0; module->TotalBytesSent = 0;
module->PAUSE = 0; module->PAUSE = 0;
@@ -854,7 +885,7 @@ void ILibAsyncSocket_ConnectTo(void* socketModule, struct sockaddr *localInterfa
module->MallocSize = module->InitialSize; module->MallocSize = module->InitialSize;
// If localInterface is NULL, we will assume INADDRANY - IPv4/IPv6 based on remote address // If localInterface is NULL, we will assume INADDRANY - IPv4/IPv6 based on remote address
if (localInterface == NULL) if (localInterface == NULL && module->RemoteAddress.sin6_family != AF_UNIX)
{ {
memset(&any, 0, sizeof(struct sockaddr_in6)); memset(&any, 0, sizeof(struct sockaddr_in6));
#ifdef MICROSTACK_PROXY #ifdef MICROSTACK_PROXY
@@ -867,12 +898,22 @@ void ILibAsyncSocket_ConnectTo(void* socketModule, struct sockaddr *localInterfa
// The local port should always be zero // The local port should always be zero
#ifdef _DEBUG #ifdef _DEBUG
if (localInterface != NULL)
{
if (localInterface->sa_family == AF_INET && ((struct sockaddr_in*)localInterface)->sin_port != 0) { PRINTERROR(); ILIBCRITICALEXIT(253); } if (localInterface->sa_family == AF_INET && ((struct sockaddr_in*)localInterface)->sin_port != 0) { PRINTERROR(); ILIBCRITICALEXIT(253); }
if (localInterface->sa_family == AF_INET6 && ((struct sockaddr_in6*)localInterface)->sin6_port != 0) { PRINTERROR(); ILIBCRITICALEXIT(253); } if (localInterface->sa_family == AF_INET6 && ((struct sockaddr_in6*)localInterface)->sin6_port != 0) { PRINTERROR(); ILIBCRITICALEXIT(253); }
}
#endif #endif
// Allocate a new socket // Allocate a new socket
if (module->RemoteAddress.sin6_family != AF_UNIX)
{
if ((module->internalSocket = ILibGetSocket(localInterface, SOCK_STREAM, IPPROTO_TCP)) == 0) { ILIBCRITICALEXIT(253); return; } if ((module->internalSocket = ILibGetSocket(localInterface, SOCK_STREAM, IPPROTO_TCP)) == 0) { ILIBCRITICALEXIT(253); return; }
}
else
{
if ((int)(module->internalSocket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { ILIBCRITICALEXIT(253); return; }
}
// Initialise the buffer pointers, since no data is in them yet. // Initialise the buffer pointers, since no data is in them yet.
module->FinConnect = 0; module->FinConnect = 0;
@@ -882,8 +923,11 @@ void ILibAsyncSocket_ConnectTo(void* socketModule, struct sockaddr *localInterfa
module->BeginPointer = 0; module->BeginPointer = 0;
module->EndPointer = 0; module->EndPointer = 0;
if (module->RemoteAddress.sin6_family != AF_UNIX)
{
// Turn on keep-alives for the socket // Turn on keep-alives for the socket
if (setsockopt(module->internalSocket, SOL_SOCKET, SO_KEEPALIVE, (char*)&flags, sizeof(flags)) != 0) ILIBCRITICALERREXIT(253); if (setsockopt(module->internalSocket, SOL_SOCKET, SO_KEEPALIVE, (char*)&flags, sizeof(flags)) != 0) ILIBCRITICALERREXIT(253);
}
// Set the socket to non-blocking mode, because we need to play nice and share the MicroStack thread // Set the socket to non-blocking mode, because we need to play nice and share the MicroStack thread
#if defined(_WIN32_WCE) || defined(WIN32) #if defined(_WIN32_WCE) || defined(WIN32)
@@ -895,9 +939,9 @@ void ILibAsyncSocket_ConnectTo(void* socketModule, struct sockaddr *localInterfa
// Connect the socket, and force the chain to unblock, since the select statement doesn't have us in the fdset yet. // Connect the socket, and force the chain to unblock, since the select statement doesn't have us in the fdset yet.
#ifdef MICROSTACK_PROXY #ifdef MICROSTACK_PROXY
if (module->ProxyAddress.sin6_family != 0) if (module->ProxyAddress.sin6_family != 0 && module->RemoteAddress.sin6_family != AF_UNIX)
{ {
if (connect(module->internalSocket, (struct sockaddr*)&(module->ProxyAddress), INET_SOCKADDR_LENGTH(module->ProxyAddress.sin6_family)) != -1) if ((v=connect(module->internalSocket, (struct sockaddr*)&(module->ProxyAddress), INET_SOCKADDR_LENGTH(module->ProxyAddress.sin6_family))) != -1)
{ {
// Connect failed. Set a short time and call disconnect. // Connect failed. Set a short time and call disconnect.
module->FinConnect = -1; module->FinConnect = -1;
@@ -907,17 +951,32 @@ void ILibAsyncSocket_ConnectTo(void* socketModule, struct sockaddr *localInterfa
} }
else else
#endif #endif
if (connect(module->internalSocket, (struct sockaddr*)remoteInterface, INET_SOCKADDR_LENGTH(remoteInterface->sa_family)) != -1) if (module->RemoteAddress.sin6_family != AF_UNIX)
{
if ((v=connect(module->internalSocket, (struct sockaddr*)remoteInterface, INET_SOCKADDR_LENGTH(remoteInterface->sa_family))) != -1)
{ {
// Connect failed. Set a short time and call disconnect. // Connect failed. Set a short time and call disconnect.
module->FinConnect = -1; module->FinConnect = -1;
ILibLifeTime_Add(module->LifeTime, socketModule, 0, &ILibAsyncSocket_Disconnect, NULL); ILibLifeTime_Add(module->LifeTime, socketModule, 0, &ILibAsyncSocket_Disconnect, NULL);
return; return;
} }
}
else
{
#ifdef _POSIX
if ((v=connect(module->internalSocket, (struct sockaddr *)&(module->DomainAddress), SUN_LEN(&(module->DomainAddress)))) < 0)
#endif
{
// Connect failed. Set a short time and call disconnect.
module->FinConnect = -1;
ILibLifeTime_Add(module->LifeTime, socketModule, 0, &ILibAsyncSocket_Disconnect, NULL);
return;
}
}
#ifdef _DEBUG #ifdef _DEBUG
#ifdef _POSIX #ifdef _POSIX
if (errno != EINPROGRESS) // The result of the connect should always be "WOULD BLOCK" on Linux. But sometimes this fails. if (v != 0 && errno != EINPROGRESS) // The result of the connect should always be "WOULD BLOCK" on Linux. But sometimes this fails.
{ {
// This happens when the interface is no longer available. Disconnect socket. // This happens when the interface is no longer available. Disconnect socket.
module->FinConnect = -1; module->FinConnect = -1;
@@ -1060,6 +1119,7 @@ void ILibProcessAsyncSocket(struct ILibAsyncSocketModule *Reader, int pendingRea
#ifdef MICROSTACK_TLS_DETECT #ifdef MICROSTACK_TLS_DETECT
if (Reader->ssl != NULL && Reader->TLSChecked == 0) if (Reader->ssl != NULL && Reader->TLSChecked == 0)
{ {
#ifndef __APPLE__
bytesReceived = recv(Reader->internalSocket, Reader->buffer, Reader->MallocSize, MSG_PEEK | MSG_NOSIGNAL); bytesReceived = recv(Reader->internalSocket, Reader->buffer, Reader->MallocSize, MSG_PEEK | MSG_NOSIGNAL);
if (ILibAsyncSocket_TLSDetect(Reader, Reader->buffer, 0, bytesReceived) == 0) if (ILibAsyncSocket_TLSDetect(Reader, Reader->buffer, 0, bytesReceived) == 0)
{ {
@@ -1070,6 +1130,7 @@ void ILibProcessAsyncSocket(struct ILibAsyncSocketModule *Reader, int pendingRea
if (Reader->OnConnect != NULL) Reader->OnConnect(Reader, -1, Reader->user); if (Reader->OnConnect != NULL) Reader->OnConnect(Reader, -1, Reader->user);
} }
} }
#endif
Reader->TLSChecked = 1; Reader->TLSChecked = 1;
} }
#endif #endif
@@ -1082,17 +1143,31 @@ void ILibProcessAsyncSocket(struct ILibAsyncSocketModule *Reader, int pendingRea
if (Reader->ssl != NULL) if (Reader->ssl != NULL)
{ {
BIO_clear_retry_flags(Reader->readBio); BIO_clear_retry_flags(Reader->readBio);
#if defined(WINSOCK2) #if defined(WINSOCK2)
if (Reader->RemoteAddress.sin6_family == AF_UNIX)
{
bytesReceived = recv(Reader->internalSocket, Reader->readBioBuffer_mem + Reader->readBioBuffer->length, (int)(Reader->readBioBuffer->max - Reader->readBioBuffer->length), 0);
}
else
{
bytesReceived = recvfrom(Reader->internalSocket, Reader->readBioBuffer_mem + Reader->readBioBuffer->length, (int)(Reader->readBioBuffer->max - Reader->readBioBuffer->length), 0, (struct sockaddr*)&(Reader->SourceAddress), (int*)&len); bytesReceived = recvfrom(Reader->internalSocket, Reader->readBioBuffer_mem + Reader->readBioBuffer->length, (int)(Reader->readBioBuffer->max - Reader->readBioBuffer->length), 0, (struct sockaddr*)&(Reader->SourceAddress), (int*)&len);
}
#else #else
if (Reader->RemoteAddress.sin6_family == AF_UNIX)
{
bytesReceived = (int)recv(Reader->internalSocket, Reader->readBioBuffer->data + Reader->readBioBuffer->length, (int)(Reader->readBioBuffer->max - Reader->readBioBuffer->length), 0);
}
else
{
bytesReceived = (int)recvfrom(Reader->internalSocket, Reader->readBioBuffer->data + Reader->readBioBuffer->length, (int)(Reader->readBioBuffer->max - Reader->readBioBuffer->length), 0, (struct sockaddr*)&(Reader->SourceAddress), (socklen_t*)&len); bytesReceived = (int)recvfrom(Reader->internalSocket, Reader->readBioBuffer->data + Reader->readBioBuffer->length, (int)(Reader->readBioBuffer->max - Reader->readBioBuffer->length), 0, (struct sockaddr*)&(Reader->SourceAddress), (socklen_t*)&len);
}
#endif #endif
if (bytesReceived > 0) if (bytesReceived > 0)
{ {
Reader->readBioBuffer->length += bytesReceived; Reader->readBioBuffer->length += bytesReceived;
if (Reader->TLSHandshakeCompleted == 0) if (Reader->TLSHandshakeCompleted == 0)
{ {
SSL_TRACE1("SSL_handshake()");
switch ((sslerror = SSL_do_handshake(Reader->ssl))) switch ((sslerror = SSL_do_handshake(Reader->ssl)))
{ {
case 0: case 0:
@@ -1108,6 +1183,9 @@ void ILibProcessAsyncSocket(struct ILibAsyncSocketModule *Reader, int pendingRea
if (Reader->OnConnect != NULL) if (Reader->OnConnect != NULL)
{ {
Reader->OnConnect(Reader, -1, Reader->user); Reader->OnConnect(Reader, -1, Reader->user);
#ifdef _DEBUG
//util_savekeys(Reader->ssl); // SAVES TLS PRIVATE KEYS - WARNING: !!! THIS CODE SHOULD ALWAYS BE COMMENTED OUT !!!!
#endif
} }
ILibAsyncSocket_ProcessEncryptedBuffer(Reader); ILibAsyncSocket_ProcessEncryptedBuffer(Reader);
break; break;
@@ -1125,9 +1203,11 @@ void ILibProcessAsyncSocket(struct ILibAsyncSocketModule *Reader, int pendingRea
} }
break; break;
} }
SSL_TRACE2("SSL_handshake()");
} }
else else
{ {
SSL_TRACE1("SSL_read()");
while ((j = SSL_read(Reader->ssl, Reader->buffer + Reader->EndPointer, Reader->MallocSize - Reader->EndPointer))>0) while ((j = SSL_read(Reader->ssl, Reader->buffer + Reader->EndPointer, Reader->MallocSize - Reader->EndPointer))>0)
{ {
// We got new TLS Data // We got new TLS Data
@@ -1154,6 +1234,7 @@ void ILibProcessAsyncSocket(struct ILibAsyncSocketModule *Reader, int pendingRea
ILibAsyncSocket_ProcessEncryptedBuffer(Reader); ILibAsyncSocket_ProcessEncryptedBuffer(Reader);
} }
} }
SSL_TRACE2("SSL_read()");
} }
} }
if (Reader->readBioBuffer->length == 0) if (Reader->readBioBuffer->length == 0)
@@ -1166,12 +1247,29 @@ void ILibProcessAsyncSocket(struct ILibAsyncSocketModule *Reader, int pendingRea
#endif #endif
{ {
#if defined(WINSOCK2) #if defined(WINSOCK2)
if (Reader->RemoteAddress.sin6_family == AF_UNIX)
{
bytesReceived = recv(Reader->internalSocket, Reader->buffer + Reader->EndPointer, Reader->MallocSize - Reader->EndPointer, 0);
}
else
{
bytesReceived = recvfrom(Reader->internalSocket, Reader->buffer + Reader->EndPointer, Reader->MallocSize - Reader->EndPointer, 0, (struct sockaddr*)&(Reader->SourceAddress), (int*)&len); bytesReceived = recvfrom(Reader->internalSocket, Reader->buffer + Reader->EndPointer, Reader->MallocSize - Reader->EndPointer, 0, (struct sockaddr*)&(Reader->SourceAddress), (int*)&len);
}
#else #else
if (Reader->RemoteAddress.sin6_family == AF_UNIX)
{
bytesReceived = (int)recv(Reader->internalSocket, Reader->buffer + Reader->EndPointer, Reader->MallocSize - Reader->EndPointer, 0);
}
else
{
bytesReceived = (int)recvfrom(Reader->internalSocket, Reader->buffer + Reader->EndPointer, Reader->MallocSize - Reader->EndPointer, 0, (struct sockaddr*)&(Reader->SourceAddress), (socklen_t*)&len); bytesReceived = (int)recvfrom(Reader->internalSocket, Reader->buffer + Reader->EndPointer, Reader->MallocSize - Reader->EndPointer, 0, (struct sockaddr*)&(Reader->SourceAddress), (socklen_t*)&len);
}
#endif #endif
if (Reader->RemoteAddress.sin6_family != AF_UNIX)
{
ILib6to4((struct sockaddr*)&(Reader->SourceAddress)); ILib6to4((struct sockaddr*)&(Reader->SourceAddress));
ILibRemoteLogging_printf(ILibChainGetLogger(Reader->Transport.ChainLink.ParentChain), ILibRemoteLogging_Modules_Microstack_AsyncSocket, ILibRemoteLogging_Flags_VerbosityLevel_2, "AsyncSocket[%p] recv returned %d", (void*)Reader, bytesReceived); ILibRemoteLogging_printf(ILibChainGetLogger(Reader->Transport.ChainLink.ParentChain), ILibRemoteLogging_Modules_Microstack_AsyncSocket, ILibRemoteLogging_Flags_VerbosityLevel_2, "AsyncSocket[%p] recv returned %d", (void*)Reader, bytesReceived);
}
if (bytesReceived > 0) if (bytesReceived > 0)
{ {
@@ -1481,8 +1579,10 @@ void ILibAsyncSocket_PrivateShutdown(void* socketModule)
#ifndef MICROSTACK_NOTLS #ifndef MICROSTACK_NOTLS
if ((wasssl = module->ssl) != NULL) if ((wasssl = module->ssl) != NULL)
{ {
SSL_TRACE1("ILibAsyncSocket_PrivateShutdown()");
SSL_free(module->ssl); // Frees SSL session and BIO buffer at the same time SSL_free(module->ssl); // Frees SSL session and BIO buffer at the same time
module->ssl = NULL; module->ssl = NULL;
SSL_TRACE2("ILibAsyncSocket_PrivateShutdown()");
} }
#endif #endif
@@ -1568,7 +1668,7 @@ void ILibAsyncSocket_PostSelect(void* socketModule, int slct, fd_set *readset, f
{ {
serr = 1; serr = 1;
} }
else else if(fd_read!=0)
{ {
// Fetch the socket error code // Fetch the socket error code
#if defined(WINSOCK2) #if defined(WINSOCK2)
@@ -1580,12 +1680,13 @@ void ILibAsyncSocket_PostSelect(void* socketModule, int slct, fd_set *readset, f
#ifdef MICROSTACK_PROXY #ifdef MICROSTACK_PROXY
// Handle proxy, we need to read the proxy response, all of it and not a byte more. // Handle proxy, we need to read the proxy response, all of it and not a byte more.
if (module->FinConnect == 1 && module->ProxyState == 1 && serr == 0 && fd_read != 0) if (module->FinConnect == 1 && module->ProxyState == 1 && serr == 0 && fd_read != 0 && module->RemoteAddress.sin6_family != AF_UNIX)
{ {
char *ptr1, *ptr2; char *ptr1, *ptr2;
int len2, len3; int len2;
int slen = sizeof(struct sockaddr_in6);
serr = 555; // Fake proxy error serr = 555; // Fake proxy error
len2 = recv(module->internalSocket, ILibScratchPad2, 1024, MSG_PEEK | MSG_NOSIGNAL); // Klockwork says this could block, but it can't, becuase socket was set to nonblock len2 = recvfrom(module->internalSocket, ILibScratchPad2, 1024, 0, (struct sockaddr*)&(module->SourceAddress), (socklen_t*)&slen);
if (len2 > 0 && len2 < 1024) if (len2 > 0 && len2 < 1024)
{ {
ILibScratchPad2[len2] = 0; ILibScratchPad2[len2] = 0;
@@ -1593,8 +1694,6 @@ void ILibAsyncSocket_PostSelect(void* socketModule, int slct, fd_set *readset, f
ptr2 = strstr(ILibScratchPad2, " 200 "); ptr2 = strstr(ILibScratchPad2, " 200 ");
if (ptr1 != NULL && ptr2 != NULL && ptr2 < ptr1) if (ptr1 != NULL && ptr2 != NULL && ptr2 < ptr1)
{ {
len3 = (int)((ptr1 + 4) - ILibScratchPad2);
recv(module->internalSocket, ILibScratchPad2, len3, MSG_NOSIGNAL);
module->FinConnect = 0; // Let pretend we never connected, this will trigger all the connection stuff. module->FinConnect = 0; // Let pretend we never connected, this will trigger all the connection stuff.
module->ProxyState = 2; // Move the proxy connection state forward. module->ProxyState = 2; // Move the proxy connection state forward.
serr = 0; // Proxy connected collectly. serr = 0; // Proxy connected collectly.
@@ -1625,11 +1724,14 @@ void ILibAsyncSocket_PostSelect(void* socketModule, int slct, fd_set *readset, f
{ {
// Connected // Connected
len = sizeof(struct sockaddr_in6); len = sizeof(struct sockaddr_in6);
if (module->RemoteAddress.sin6_family != AF_UNIX)
{
#if defined(WINSOCK2) #if defined(WINSOCK2)
getsockname(module->internalSocket, (struct sockaddr*)(&module->LocalAddress), (int*)&len); getsockname(module->internalSocket, (struct sockaddr*)(&module->LocalAddress), (int*)&len);
#else #else
getsockname(module->internalSocket, (struct sockaddr*)(&module->LocalAddress), (socklen_t*)&len); getsockname(module->internalSocket, (struct sockaddr*)(&module->LocalAddress), (socklen_t*)&len);
#endif #endif
}
module->FinConnect = 1; module->FinConnect = 1;
module->PAUSE = 0; module->PAUSE = 0;
@@ -1644,7 +1746,7 @@ void ILibAsyncSocket_PostSelect(void* socketModule, int slct, fd_set *readset, f
// If this is a proxy connection, send the proxy connect header now. // If this is a proxy connection, send the proxy connect header now.
#ifdef MICROSTACK_PROXY #ifdef MICROSTACK_PROXY
if (module->ProxyAddress.sin6_family != 0 && module->ProxyState == 0) if (module->ProxyAddress.sin6_family != 0 && module->ProxyState == 0 && module->RemoteAddress.sin6_family != AF_UNIX)
{ {
int len2; int len2;
ILibInet_ntop((int)(module->RemoteAddress.sin6_family), (void*)&(((struct sockaddr_in*)&(module->RemoteAddress))->sin_addr), ILibScratchPad, 4096); ILibInet_ntop((int)(module->RemoteAddress.sin6_family), (void*)&(((struct sockaddr_in*)&(module->RemoteAddress))->sin_addr), ILibScratchPad, 4096);
@@ -1727,7 +1829,7 @@ void ILibAsyncSocket_PostSelect(void* socketModule, int slct, fd_set *readset, f
SEM_TRACK(AsyncSocket_TrackLock("ILibAsyncSocket_PostSelect", 1, module);) SEM_TRACK(AsyncSocket_TrackLock("ILibAsyncSocket_PostSelect", 1, module);)
sem_wait(&(module->SendLock)); sem_wait(&(module->SendLock));
// Write Handling // Write Handling
if (module->FinConnect > 0 && module->internalSocket != ~0 && fd_write != 0 && module->PendingSend_Head != NULL) if (module->FinConnect > 0 && module->internalSocket != ~0 && fd_write != 0 && module->PendingSend_Head != NULL && (module->ProxyState != 1))
{ {
// //
// Keep trying to send data, until we are told we can't // Keep trying to send data, until we are told we can't
@@ -1788,7 +1890,7 @@ void ILibAsyncSocket_PostSelect(void* socketModule, int slct, fd_set *readset, f
else else
#endif #endif
{ {
if (module->PendingSend_Head->remoteAddress.sin6_family == 0) if (module->PendingSend_Head->remoteAddress.sin6_family == 0 || module->PendingSend_Head->remoteAddress.sin6_family == AF_UNIX)
{ {
bytesSent = (int)send(module->internalSocket, module->PendingSend_Head->buffer + module->PendingSend_Head->bytesSent, module->PendingSend_Head->bufferSize - module->PendingSend_Head->bytesSent, MSG_NOSIGNAL); // Klocwork reports that this could block while holding a lock... This socket has been set to O_NONBLOCK, so that will never happen bytesSent = (int)send(module->internalSocket, module->PendingSend_Head->buffer + module->PendingSend_Head->bytesSent, module->PendingSend_Head->bufferSize - module->PendingSend_Head->bytesSent, MSG_NOSIGNAL); // Klocwork reports that this could block while holding a lock... This socket has been set to O_NONBLOCK, so that will never happen
} }
@@ -2001,6 +2103,7 @@ SSL* ILibAsyncSocket_SetSSLContextEx(ILibAsyncSocket_SocketModule socketModule,
#ifdef MICROSTACK_TLS_DETECT #ifdef MICROSTACK_TLS_DETECT
module->TLSChecked = server == ILibAsyncSocket_TLS_Mode_Server_with_TLSDetectLogic ? 0 : 1; module->TLSChecked = server == ILibAsyncSocket_TLS_Mode_Server_with_TLSDetectLogic ? 0 : 1;
#endif #endif
SSL_TRACE1("SetSSLContextEx()");
module->ssl = SSL_new(ssl_ctx); module->ssl = SSL_new(ssl_ctx);
module->TLSHandshakeCompleted = 0; module->TLSHandshakeCompleted = 0;
module->readBio = BIO_new_mem_buf(module->readBioBuffer_mem, (int)sizeof(module->readBioBuffer_mem)); module->readBio = BIO_new_mem_buf(module->readBioBuffer_mem, (int)sizeof(module->readBioBuffer_mem));
@@ -2027,6 +2130,7 @@ SSL* ILibAsyncSocket_SetSSLContextEx(ILibAsyncSocket_SocketModule socketModule,
{ {
SSL_set_accept_state(module->ssl); // Setup server SSL state SSL_set_accept_state(module->ssl); // Setup server SSL state
} }
SSL_TRACE2("SetSSLContextEx()");
return(module->ssl); return(module->ssl);
} }
} }
@@ -2118,6 +2222,11 @@ void ILibAsyncSocket_UseThisSocket(ILibAsyncSocket_SocketModule socketModule, in
#endif #endif
} }
int ILibAsyncSocket_IsDomainSocket(ILibAsyncSocket_SocketModule socketModule)
{
return(((struct ILibAsyncSocketModule*)socketModule)->RemoteAddress.sin6_family == AF_UNIX ? 1 : 0);
}
/*! \fn ILibAsyncSocket_GetRemoteInterface(ILibAsyncSocket_SocketModule socketModule) /*! \fn ILibAsyncSocket_GetRemoteInterface(ILibAsyncSocket_SocketModule socketModule)
\brief Returns the Remote Interface of a connected session \brief Returns the Remote Interface of a connected session
\param socketModule The ILibAsyncSocket to query \param socketModule The ILibAsyncSocket to query
@@ -2154,10 +2263,14 @@ int ILibAsyncSocket_GetLocalInterface(ILibAsyncSocket_SocketModule socketModule,
} }
else else
{ {
#if defined(WINSOCK2) #if defined(WIN32)
getsockname(module->internalSocket, localAddress, (int*)&receivingAddressLength); getsockname(module->internalSocket, localAddress, (int*)&receivingAddressLength);
#else #else
getsockname(module->internalSocket, localAddress, (socklen_t*)&receivingAddressLength); if (getsockname(module->internalSocket, localAddress, (socklen_t*)&receivingAddressLength) < 0)
{
receivingAddressLength = sizeof(struct sockaddr_in);
if (getsockname(module->internalSocket, localAddress, (socklen_t*)&receivingAddressLength) < 0) { receivingAddressLength = 0; }
}
#endif #endif
return receivingAddressLength; return receivingAddressLength;
} }
@@ -2322,8 +2435,13 @@ int ILibAsyncSocket_TLS_WasHandshakeError(ILibAsyncSocket_SocketModule socketMod
*/ */
X509 *ILibAsyncSocket_SslGetCert(ILibAsyncSocket_SocketModule socketModule) X509 *ILibAsyncSocket_SslGetCert(ILibAsyncSocket_SocketModule socketModule)
{ {
X509 *ret;
SSL_TRACE1("ILibAsyncSocket_SslGetCert()");
struct ILibAsyncSocketModule *sm = (struct ILibAsyncSocketModule*)socketModule; struct ILibAsyncSocketModule *sm = (struct ILibAsyncSocketModule*)socketModule;
return SSL_get_peer_certificate(sm->ssl); ret = SSL_get_peer_certificate(sm->ssl);
SSL_TRACE2("ILibAsyncSocket_SslGetCert()");
return(ret);
} }
//! Get's the Cert Chain presented by the Peer //! Get's the Cert Chain presented by the Peer
@@ -2335,7 +2453,11 @@ X509 *ILibAsyncSocket_SslGetCert(ILibAsyncSocket_SocketModule socketModule)
*/ */
STACK_OF(X509) *ILibAsyncSocket_SslGetCerts(ILibAsyncSocket_SocketModule socketModule) STACK_OF(X509) *ILibAsyncSocket_SslGetCerts(ILibAsyncSocket_SocketModule socketModule)
{ {
STACK_OF(X509) *ret;
SSL_TRACE1("ILibAsyncSocket_SslGetCerts()");
struct ILibAsyncSocketModule *sm = (struct ILibAsyncSocketModule*)socketModule; struct ILibAsyncSocketModule *sm = (struct ILibAsyncSocketModule*)socketModule;
return SSL_get_peer_cert_chain(sm->ssl); ret = SSL_get_peer_cert_chain(sm->ssl);
SSL_TRACE2("ILibAsyncSocket_SslGetCerts()");
return (ret);
} }
#endif #endif

View File

@@ -225,6 +225,7 @@ int ILibAsyncSocket_IsFree(ILibAsyncSocket_SocketModule socketModule);
int ILibAsyncSocket_IsConnected(ILibAsyncSocket_SocketModule socketModule); int ILibAsyncSocket_IsConnected(ILibAsyncSocket_SocketModule socketModule);
int ILibAsyncSocket_GetLocalInterface(ILibAsyncSocket_SocketModule socketModule, struct sockaddr *localAddress); int ILibAsyncSocket_GetLocalInterface(ILibAsyncSocket_SocketModule socketModule, struct sockaddr *localAddress);
int ILibAsyncSocket_GetRemoteInterface(ILibAsyncSocket_SocketModule socketModule, struct sockaddr *remoteAddress); int ILibAsyncSocket_GetRemoteInterface(ILibAsyncSocket_SocketModule socketModule, struct sockaddr *remoteAddress);
int ILibAsyncSocket_IsDomainSocket(ILibAsyncSocket_SocketModule socketModule);
unsigned short ILibAsyncSocket_GetLocalPort(ILibAsyncSocket_SocketModule socketModule); unsigned short ILibAsyncSocket_GetLocalPort(ILibAsyncSocket_SocketModule socketModule);
void ILibAsyncSocket_Resume(ILibAsyncSocket_SocketModule socketModule); void ILibAsyncSocket_Resume(ILibAsyncSocket_SocketModule socketModule);