- Socket HAL: added functons for asynchronous (non-blocking) connect

pull/93/head
Michael Zillgith 7 years ago
parent 4d32e3c1ae
commit 8d45d44cc2

@ -64,6 +64,15 @@ typedef struct sSocket* Socket;
/** Opaque reference for a set of server and socket handles */ /** Opaque reference for a set of server and socket handles */
typedef struct sHandleSet* HandleSet; typedef struct sHandleSet* HandleSet;
/** State of an asynchronous connect */
typedef enum
{
SOCKET_STATE_CONNECTING = 0,
SOCKET_STATE_FAILED = 1,
SOCKET_STATE_CONNECTED = 2
} SocketState;
/** /**
* \brief Create a new connection handle set (HandleSet) * \brief Create a new connection handle set (HandleSet)
* *
@ -224,6 +233,12 @@ Socket_setConnectTimeout(Socket self, uint32_t timeoutInMs);
bool bool
Socket_connect(Socket self, const char* address, int port); Socket_connect(Socket self, const char* address, int port);
bool
Socket_connectAsync(Socket self, const char* address, int port);
SocketState
Socket_checkAsyncConnectState(Socket self);
/** /**
* \brief read from socket to local buffer (non-blocking) * \brief read from socket to local buffer (non-blocking)
* *

@ -298,9 +298,8 @@ Socket_setConnectTimeout(Socket self, uint32_t timeoutInMs)
self->connectTimeout = timeoutInMs; self->connectTimeout = timeoutInMs;
} }
bool bool
Socket_connect(Socket self, const char* address, int port) Socket_connectAsync(Socket self, const char* address, int port)
{ {
struct sockaddr_in serverAddress; struct sockaddr_in serverAddress;
@ -312,38 +311,96 @@ Socket_connect(Socket self, const char* address, int port)
self->fd = socket(AF_INET, SOCK_STREAM, 0); self->fd = socket(AF_INET, SOCK_STREAM, 0);
fd_set fdSet;
FD_ZERO(&fdSet);
FD_SET(self->fd, &fdSet);
activateTcpNoDelay(self); activateTcpNoDelay(self);
#if (CONFIG_ACTIVATE_TCP_KEEPALIVE == 1)
activateKeepAlive(self->fd);
#endif
fcntl(self->fd, F_SETFL, O_NONBLOCK); fcntl(self->fd, F_SETFL, O_NONBLOCK);
if (connect(self->fd, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) < 0) { if (connect(self->fd, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) < 0) {
if (errno != EINPROGRESS)
if (errno != EINPROGRESS) {
self->fd = -1;
return false; return false;
}
} }
return true; /* is connecting or already connected */
}
SocketState
Socket_checkAsyncConnectState(Socket self)
{
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 0;
fd_set fdSet;
FD_ZERO(&fdSet);
FD_SET(self->fd, &fdSet);
int selectVal = select(self->fd + 1, NULL, &fdSet , NULL, &timeout);
if (selectVal == 1) {
/* Check if connection is established */
int so_error;
socklen_t len = sizeof so_error;
if (getsockopt(self->fd, SOL_SOCKET, SO_ERROR, &so_error, &len) >= 0) {
if (so_error == 0)
return SOCKET_STATE_CONNECTED;
}
return SOCKET_STATE_FAILED;
}
else if (selectVal == 0) {
return SOCKET_STATE_CONNECTING;
}
else {
return SOCKET_STATE_FAILED;
}
}
bool
Socket_connect(Socket self, const char* address, int port)
{
if (Socket_connectAsync(self, address, port) == false)
return false;
struct timeval timeout; struct timeval timeout;
timeout.tv_sec = self->connectTimeout / 1000; timeout.tv_sec = self->connectTimeout / 1000;
timeout.tv_usec = (self->connectTimeout % 1000) * 1000; timeout.tv_usec = (self->connectTimeout % 1000) * 1000;
fd_set fdSet;
FD_ZERO(&fdSet);
FD_SET(self->fd, &fdSet);
if (select(self->fd + 1, NULL, &fdSet , NULL, &timeout) == 1) { if (select(self->fd + 1, NULL, &fdSet , NULL, &timeout) == 1) {
/* Check if connection is established */
int so_error; int so_error;
socklen_t len = sizeof so_error; socklen_t len = sizeof so_error;
getsockopt(self->fd, SOL_SOCKET, SO_ERROR, &so_error, &len); if (getsockopt(self->fd, SOL_SOCKET, SO_ERROR, &so_error, &len) >= 0) {
if (so_error == 0) if (so_error == 0)
return true; return true;
}
} }
close (self->fd); close (self->fd);
self->fd = -1;
return false; return false;
} }
char* char*
Socket_getPeerAddress(Socket self) Socket_getPeerAddress(Socket self)
{ {

@ -319,6 +319,81 @@ Socket_setConnectTimeout(Socket self, uint32_t timeoutInMs)
self->connectTimeout = timeoutInMs; self->connectTimeout = timeoutInMs;
} }
bool
Socket_connectAsync(Socket self, const char* address, int port)
{
if (DEBUG_SOCKET)
printf("Socket_connect: %s:%i\n", address, port);
struct sockaddr_in serverAddress;
WSADATA wsa;
int ec;
if ((ec = WSAStartup(MAKEWORD(2,0), &wsa)) != 0) {
if (DEBUG_SOCKET)
printf("WIN32_SOCKET: winsock error: code %i\n", ec);
return false;
}
if (!prepareServerAddress(address, port, &serverAddress))
return false;
self->fd = socket(AF_INET, SOCK_STREAM, 0);
#if CONFIG_ACTIVATE_TCP_KEEPALIVE == 1
activateKeepAlive(self->fd);
#endif
setSocketNonBlocking(self);
if (connect(self->fd, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) == SOCKET_ERROR) {
if (WSAGetLastError() != WSAEWOULDBLOCK) {
self->fd = INVALID_SOCKET;
return false;
}
}
return true; /* is connecting or already connected */
}
SocketState
Socket_checkAsyncConnectState(Socket self)
{
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 0;
fd_set fdSet;
FD_ZERO(&fdSet);
FD_SET(self->fd, &fdSet);
int selectVal = select(self->fd + 1, NULL, &fdSet , NULL, &timeout);
if (selectVal == 1) {
/* Check if connection is established */
int so_error;
int len = sizeof so_error;
if (getsockopt(self->fd, SOL_SOCKET, SO_ERROR, (char*) (&so_error), &len) >= 0) {
if (so_error == 0)
return SOCKET_STATE_CONNECTED;
}
return SOCKET_STATE_FAILED;
}
else if (selectVal == 0) {
return SOCKET_STATE_CONNECTING;
}
else {
return SOCKET_STATE_FAILED;
}
}
bool bool
Socket_connect(Socket self, const char* address, int port) Socket_connect(Socket self, const char* address, int port)
{ {

@ -297,10 +297,12 @@ IsoClientConnection_associate(IsoClientConnection self, IsoConnectionParameters
CONFIG_TCP_KEEPALIVE_INTERVAL, CONFIG_TCP_KEEPALIVE_INTERVAL,
CONFIG_TCP_KEEPALIVE_CNT); CONFIG_TCP_KEEPALIVE_CNT);
#endif #endif
// (1) Function blocks
if (!Socket_connect(self->socket, params->hostname, params->tcpPort)) if (!Socket_connect(self->socket, params->hostname, params->tcpPort))
goto returnError; goto returnError;
// (2) Send connection request message
/* COTP (ISO transport) handshake */ /* COTP (ISO transport) handshake */
CotpConnection_init(self->cotpConnection, self->socket, self->receiveBuffer, self->cotpReadBuffer, self->cotpWriteBuffer); CotpConnection_init(self->cotpConnection, self->socket, self->receiveBuffer, self->cotpReadBuffer, self->cotpWriteBuffer);
@ -331,6 +333,7 @@ IsoClientConnection_associate(IsoClientConnection self, IsoConnectionParameters
uint64_t timeout = Hal_getTimeInMs() + CONFIG_TCP_READ_TIMEOUT_MS; uint64_t timeout = Hal_getTimeInMs() + CONFIG_TCP_READ_TIMEOUT_MS;
// (3) Waiting for response (blocking)
while (((packetState = CotpConnection_readToTpktBuffer(self->cotpConnection)) == TPKT_WAITING) while (((packetState = CotpConnection_readToTpktBuffer(self->cotpConnection)) == TPKT_WAITING)
&& (Hal_getTimeInMs() < timeout)) && (Hal_getTimeInMs() < timeout))
{ {
@ -345,6 +348,8 @@ IsoClientConnection_associate(IsoClientConnection self, IsoConnectionParameters
if (cotpIndication != COTP_CONNECT_INDICATION) if (cotpIndication != COTP_CONNECT_INDICATION)
goto returnError; goto returnError;
// (4) Send ACSE Initiate request
/* Upper layers handshake */ /* Upper layers handshake */
struct sBufferChain sAcsePayload; struct sBufferChain sAcsePayload;
BufferChain acsePayload = &sAcsePayload; BufferChain acsePayload = &sAcsePayload;
@ -416,6 +421,8 @@ IsoClientConnection_associate(IsoClientConnection self, IsoConnectionParameters
AcseIndication acseIndication; AcseIndication acseIndication;
// (5) Wait for ACSE initiate response message
acseIndication = AcseConnection_parseMessage(&(self->acseConnection), &self->presentation->nextPayload); acseIndication = AcseConnection_parseMessage(&(self->acseConnection), &self->presentation->nextPayload);
if (acseIndication != ACSE_ASSOCIATE) { if (acseIndication != ACSE_ASSOCIATE) {

Loading…
Cancel
Save