From 8141f1e8913142de550333e7812a8f0245e2fef6 Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Fri, 1 Feb 2019 15:06:14 +0100 Subject: [PATCH] - fixed client TCP keep alive problem (see #115) --- hal/socket/bsd/socket_bsd.c | 21 ++++++++--- hal/socket/linux/socket_linux.c | 43 ++++++++++++++++------ hal/socket/win32/socket_win32.c | 22 +++++++---- src/goose/goose_receiver.c | 8 ++-- src/mms/iso_client/iso_client_connection.c | 21 ++++++----- 5 files changed, 78 insertions(+), 37 deletions(-) diff --git a/hal/socket/bsd/socket_bsd.c b/hal/socket/bsd/socket_bsd.c index 18079db7..cb5574df 100644 --- a/hal/socket/bsd/socket_bsd.c +++ b/hal/socket/bsd/socket_bsd.c @@ -216,7 +216,7 @@ ServerSocket_accept(ServerSocket self) fd = accept(self->fd, NULL, NULL ); if (fd >= 0) { - conSocket = TcpSocket_create(); + conSocket = (Socket) GLOBAL_CALLOC(1, sizeof(struct sSocket)); conSocket->fd = fd; } @@ -261,9 +261,20 @@ ServerSocket_destroy(ServerSocket self) Socket TcpSocket_create() { - Socket self = GLOBAL_MALLOC(sizeof(struct sSocket)); + Socket self = NULL; - self->fd = -1; + int sock = socket(AF_INET, SOCK_STREAM, 0); + + if (sock != -1) { + self = (Socket) GLOBAL_MALLOC(sizeof(struct sSocket)); + + self->fd = sock; + self->connectTimeout = 5000; + } + else { + if (DEBUG_SOCKET) + printf("SOCKET: failed to create socket (errno=%i)\n", errno); + } return self; } @@ -281,13 +292,11 @@ Socket_connect(Socket self, const char* address, int port) struct sockaddr_in serverAddress; if (DEBUG_SOCKET) - printf("Socket_connect: %s:%i\n", address, port); + printf("SOCKET: connect: %s:%i\n", address, port); if (!prepareServerAddress(address, port, &serverAddress)) return false; - self->fd = socket(AF_INET, SOCK_STREAM, 0); - fd_set fdSet; FD_ZERO(&fdSet); FD_SET(self->fd, &fdSet); diff --git a/hal/socket/linux/socket_linux.c b/hal/socket/linux/socket_linux.c index 69fca6a6..64c0a4b6 100644 --- a/hal/socket/linux/socket_linux.c +++ b/hal/socket/linux/socket_linux.c @@ -119,17 +119,30 @@ Socket_activateTcpKeepAlive(Socket self, int idleTime, int interval, int count) socklen_t optlen = sizeof(optval); optval = 1; - setsockopt(self->fd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen); + + if (setsockopt(self->fd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen)) { + if (DEBUG_SOCKET) + printf("Failed to enable TCP keepalive\n"); + } #if defined TCP_KEEPCNT optval = idleTime; - setsockopt(self->fd, IPPROTO_TCP, TCP_KEEPIDLE, &optval, optlen); + if (setsockopt(self->fd, IPPROTO_TCP, TCP_KEEPIDLE, &optval, optlen)) { + if (DEBUG_SOCKET) + printf("Failed to set TCP keepalive TCP_KEEPIDLE parameter\n"); + } optval = interval; - setsockopt(self->fd, IPPROTO_TCP, TCP_KEEPINTVL, &optval, optlen); + if (setsockopt(self->fd, IPPROTO_TCP, TCP_KEEPINTVL, &optval, optlen)) { + if (DEBUG_SOCKET) + printf("Failed to set TCP keepalive TCP_KEEPINTVL parameter\n"); + } optval = count; - setsockopt(self->fd, IPPROTO_TCP, TCP_KEEPCNT, &optval, optlen); + if (setsockopt(self->fd, IPPROTO_TCP, TCP_KEEPCNT, &optval, optlen)) { + if (DEBUG_SOCKET) + printf("Failed to set TCP keepalive TCP_KEEPCNT parameter\n"); + } #endif /* TCP_KEEPCNT */ #endif /* SO_KEEPALIVE */ @@ -236,7 +249,7 @@ ServerSocket_accept(ServerSocket self) fd = accept(self->fd, NULL, NULL ); if (fd >= 0) { - conSocket = TcpSocket_create(); + conSocket = (Socket) GLOBAL_CALLOC(1, sizeof(struct sSocket)); conSocket->fd = fd; activateTcpNoDelay(conSocket); @@ -283,10 +296,20 @@ ServerSocket_destroy(ServerSocket self) Socket TcpSocket_create() { - Socket self = (Socket) GLOBAL_MALLOC(sizeof(struct sSocket)); + Socket self = NULL; - self->fd = -1; - self->connectTimeout = 5000; + int sock = socket(AF_INET, SOCK_STREAM, 0); + + if (sock != -1) { + self = (Socket) GLOBAL_MALLOC(sizeof(struct sSocket)); + + self->fd = sock; + self->connectTimeout = 5000; + } + else { + if (DEBUG_SOCKET) + printf("SOCKET: failed to create socket (errno=%i)\n", errno); + } return self; } @@ -305,13 +328,11 @@ Socket_connect(Socket self, const char* address, int port) struct sockaddr_in serverAddress; if (DEBUG_SOCKET) - printf("Socket_connect: %s:%i\n", address, port); + printf("SOCKET: connect: %s:%i\n", address, port); if (!prepareServerAddress(address, port, &serverAddress)) return false; - self->fd = socket(AF_INET, SOCK_STREAM, 0); - fd_set fdSet; FD_ZERO(&fdSet); FD_SET(self->fd, &fdSet); diff --git a/hal/socket/win32/socket_win32.c b/hal/socket/win32/socket_win32.c index c686ddc7..a59f0f5a 100644 --- a/hal/socket/win32/socket_win32.c +++ b/hal/socket/win32/socket_win32.c @@ -276,7 +276,7 @@ ServerSocket_accept(ServerSocket self) fd = accept(self->fd, NULL, NULL); if (fd >= 0) { - conSocket = TcpSocket_create(); + conSocket = (Socket) GLOBAL_CALLOC(1, sizeof(struct sSocket)); conSocket->fd = fd; setSocketNonBlocking(conSocket); @@ -303,12 +303,22 @@ ServerSocket_destroy(ServerSocket self) Socket TcpSocket_create() { - Socket self = (Socket) GLOBAL_MALLOC(sizeof(struct sSocket)); + Socket self = NULL; - self->fd = INVALID_SOCKET; - self->connectTimeout = 5000; + int sock = socket(AF_INET, SOCK_STREAM, 0); - socketCount++; + if (sock != INVALID_SOCKET) { + self = (Socket) GLOBAL_MALLOC(sizeof(struct sSocket)); + + self->fd = sock; + self->connectTimeout = 5000; + + socketCount++; + } + else { + if (DEBUG_SOCKET) + printf("SOCKET: failed to create socket (error code=%i)\n", WSAGetLastError()); + } return self; } @@ -330,8 +340,6 @@ Socket_connect(Socket self, const char* address, int port) if (!prepareServerAddress(address, port, &serverAddress)) return false; - self->fd = socket(AF_INET, SOCK_STREAM, 0); - setSocketNonBlocking(self); fd_set fdSet; diff --git a/src/goose/goose_receiver.c b/src/goose/goose_receiver.c index 2a728093..b833e04e 100644 --- a/src/goose/goose_receiver.c +++ b/src/goose/goose_receiver.c @@ -684,7 +684,7 @@ parseGoosePayload(GooseReceiver self, uint8_t* buffer, int apduLength) return 0; } - exit_with_fault: +exit_with_fault: if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: Invalid goose payload\n"); return -1; @@ -744,7 +744,7 @@ parseGooseMessage(GooseReceiver self, int numbytes) printf("GOOSE_SUBSCRIBER: APDU length: %i\n", apduLength); } - // check if there is an interested subscriber + /* check if there is an interested subscriber */ LinkedList element = LinkedList_getNext(self->subscriberList); while (element != NULL) { @@ -792,7 +792,7 @@ gooseReceiverLoop(void* threadParameter) } #endif -// start GOOSE receiver in a separate thread +/* start GOOSE receiver in a separate thread */ void GooseReceiver_start(GooseReceiver self) { @@ -879,7 +879,7 @@ GooseReceiver_stopThreadless(GooseReceiver self) self->running = false; } -// call after reception of ethernet frame +/* call after reception of ethernet frame */ bool GooseReceiver_tick(GooseReceiver self) { diff --git a/src/mms/iso_client/iso_client_connection.c b/src/mms/iso_client/iso_client_connection.c index 4e5a315a..bddbebcc 100644 --- a/src/mms/iso_client/iso_client_connection.c +++ b/src/mms/iso_client/iso_client_connection.c @@ -287,6 +287,9 @@ IsoClientConnection_associate(IsoClientConnection self, IsoConnectionParameters { self->socket = TcpSocket_create(); + if (self->socket == NULL) + goto exit_error; + Socket_setConnectTimeout(self->socket, connectTimeoutInMs); #if (CONFIG_ACTIVATE_TCP_KEEPALIVE == 1) @@ -297,7 +300,7 @@ IsoClientConnection_associate(IsoClientConnection self, IsoConnectionParameters #endif if (!Socket_connect(self->socket, params->hostname, params->tcpPort)) - goto returnError; + goto exit_error; /* COTP (ISO transport) handshake */ CotpConnection_init(self->cotpConnection, self->socket, self->receiveBuffer, self->cotpReadBuffer, self->cotpWriteBuffer); @@ -315,7 +318,7 @@ IsoClientConnection_associate(IsoClientConnection self, IsoConnectionParameters if (DEBUG_ISO_CLIENT) printf("TLS handshake failed!\n"); - goto returnError; + goto exit_error; } } #endif /* (CONFIG_MMS_SUPPORT_TLS == 1) */ @@ -336,12 +339,12 @@ IsoClientConnection_associate(IsoClientConnection self, IsoConnectionParameters } if (packetState != TPKT_PACKET_COMPLETE) - goto returnError; + goto exit_error; cotpIndication = CotpConnection_parseIncomingMessage(self->cotpConnection); if (cotpIndication != COTP_CONNECT_INDICATION) - goto returnError; + goto exit_error; /* Upper layers handshake */ struct sBufferChain sAcsePayload; @@ -393,7 +396,7 @@ IsoClientConnection_associate(IsoClientConnection self, IsoConnectionParameters cotpIndication = CotpConnection_parseIncomingMessage(self->cotpConnection); if (cotpIndication != COTP_DATA_INDICATION) - goto returnError; + goto exit_error; IsoSessionIndication sessionIndication; @@ -403,13 +406,13 @@ IsoClientConnection_associate(IsoClientConnection self, IsoConnectionParameters if (sessionIndication != SESSION_CONNECT) { if (DEBUG_ISO_CLIENT) printf("IsoClientConnection_associate: no session connect indication\n"); - goto returnError; + goto exit_error; } if (!IsoPresentation_parseAcceptMessage(self->presentation, IsoSession_getUserData(self->session))) { if (DEBUG_ISO_CLIENT) printf("IsoClientConnection_associate: no presentation ok indication\n"); - goto returnError; + goto exit_error; } AcseIndication acseIndication; @@ -419,7 +422,7 @@ IsoClientConnection_associate(IsoClientConnection self, IsoConnectionParameters if (acseIndication != ACSE_ASSOCIATE) { if (DEBUG_ISO_CLIENT) printf("IsoClientConnection_associate: no ACSE_ASSOCIATE indication\n"); - goto returnError; + goto exit_error; } ByteBuffer_wrap(self->receivePayloadBuffer, self->acseConnection.userDataBuffer, @@ -446,7 +449,7 @@ IsoClientConnection_associate(IsoClientConnection self, IsoConnectionParameters return; -returnError: +exit_error: self->callback(ISO_IND_ASSOCIATION_FAILED, self->callbackParameter, NULL); setState(self, STATE_ERROR);