- 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 */
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)
*
@ -224,6 +233,12 @@ Socket_setConnectTimeout(Socket self, uint32_t timeoutInMs);
bool
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)
*

@ -298,9 +298,8 @@ Socket_setConnectTimeout(Socket self, uint32_t timeoutInMs)
self->connectTimeout = timeoutInMs;
}
bool
Socket_connect(Socket self, const char* address, int port)
Socket_connectAsync(Socket self, const char* address, int port)
{
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);
fd_set fdSet;
FD_ZERO(&fdSet);
FD_SET(self->fd, &fdSet);
activateTcpNoDelay(self);
#if (CONFIG_ACTIVATE_TCP_KEEPALIVE == 1)
activateKeepAlive(self->fd);
#endif
fcntl(self->fd, F_SETFL, O_NONBLOCK);
if (connect(self->fd, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) < 0) {
if (errno != EINPROGRESS)
if (errno != EINPROGRESS) {
self->fd = -1;
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;
timeout.tv_sec = self->connectTimeout / 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) {
/* Check if connection is established */
int 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)
return true;
if (so_error == 0)
return true;
}
}
close (self->fd);
self->fd = -1;
return false;
}
char*
Socket_getPeerAddress(Socket self)
{

@ -319,6 +319,81 @@ Socket_setConnectTimeout(Socket self, uint32_t 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
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_CNT);
#endif
// (1) Function blocks
if (!Socket_connect(self->socket, params->hostname, params->tcpPort))
goto returnError;
// (2) Send connection request message
/* COTP (ISO transport) handshake */
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;
// (3) Waiting for response (blocking)
while (((packetState = CotpConnection_readToTpktBuffer(self->cotpConnection)) == TPKT_WAITING)
&& (Hal_getTimeInMs() < timeout))
{
@ -345,6 +348,8 @@ IsoClientConnection_associate(IsoClientConnection self, IsoConnectionParameters
if (cotpIndication != COTP_CONNECT_INDICATION)
goto returnError;
// (4) Send ACSE Initiate request
/* Upper layers handshake */
struct sBufferChain sAcsePayload;
BufferChain acsePayload = &sAcsePayload;
@ -416,6 +421,8 @@ IsoClientConnection_associate(IsoClientConnection self, IsoConnectionParameters
AcseIndication acseIndication;
// (5) Wait for ACSE initiate response message
acseIndication = AcseConnection_parseMessage(&(self->acseConnection), &self->presentation->nextPayload);
if (acseIndication != ACSE_ASSOCIATE) {

Loading…
Cancel
Save