|
@@ -6,8 +6,7 @@
|
|
#include <sys/types.h>
|
|
#include <sys/types.h>
|
|
#include <Windows.h>
|
|
#include <Windows.h>
|
|
#include <ws2tcpip.h>
|
|
#include <ws2tcpip.h>
|
|
-#define CLOSESOCKET(S) closesocket(S); \
|
|
|
|
- WSACleanup();
|
|
|
|
|
|
+#define CLOSESOCKET(S) closesocket(S)
|
|
#define IOCTLSOCKET ioctlsocket
|
|
#define IOCTLSOCKET ioctlsocket
|
|
#else
|
|
#else
|
|
#include <sys/socket.h>
|
|
#include <sys/socket.h>
|
|
@@ -75,7 +74,7 @@ void NL_Connection_printf(void* payload) {
|
|
void NL_addHandleToSet(UA_Int32 handle, NL_data* nl) {
|
|
void NL_addHandleToSet(UA_Int32 handle, NL_data* nl) {
|
|
FD_SET(handle, &(nl->readerHandles));
|
|
FD_SET(handle, &(nl->readerHandles));
|
|
#ifdef WIN32
|
|
#ifdef WIN32
|
|
- int err = WSAGetLastError();
|
|
|
|
|
|
+ // int err = WSAGetLastError();
|
|
#endif
|
|
#endif
|
|
nl->maxReaderHandle = (handle > nl->maxReaderHandle) ? handle : nl->maxReaderHandle;
|
|
nl->maxReaderHandle = (handle > nl->maxReaderHandle) ? handle : nl->maxReaderHandle;
|
|
}
|
|
}
|
|
@@ -89,8 +88,21 @@ void NL_checkFdSet(void* payload) {
|
|
c->reader((void*)c);
|
|
c->reader((void*)c);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+#if 0
|
|
|
|
+char _str_error[256];
|
|
|
|
+char* strerror(int errno) {
|
|
|
|
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
|
|
+ NULL, errno,
|
|
|
|
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
|
|
+ &_str_error[0], 256, NULL);
|
|
|
|
+ return &_str_error[0];
|
|
|
|
+}
|
|
|
|
+#endif
|
|
|
|
+
|
|
UA_Int32 NL_msgLoop(NL_data* nl, struct timeval *tv, UA_Int32(*worker)(void*), void *arg, UA_Boolean *running) {
|
|
UA_Int32 NL_msgLoop(NL_data* nl, struct timeval *tv, UA_Int32(*worker)(void*), void *arg, UA_Boolean *running) {
|
|
UA_Int32 result;
|
|
UA_Int32 result;
|
|
|
|
+ UA_Int32 err;
|
|
while (*running) {
|
|
while (*running) {
|
|
// determine the largest handle
|
|
// determine the largest handle
|
|
nl->maxReaderHandle = 0;
|
|
nl->maxReaderHandle = 0;
|
|
@@ -98,51 +110,66 @@ UA_Int32 NL_msgLoop(NL_data* nl, struct timeval *tv, UA_Int32(*worker)(void*), v
|
|
DBG_VERBOSE(printf("\n------------\nUA_Stack_msgLoop - maxHandle=%d\n", nl->maxReaderHandle));
|
|
DBG_VERBOSE(printf("\n------------\nUA_Stack_msgLoop - maxHandle=%d\n", nl->maxReaderHandle));
|
|
|
|
|
|
// copy tv, some unixes do overwrite and return the remaining time
|
|
// copy tv, some unixes do overwrite and return the remaining time
|
|
|
|
+ // FIXME: actually we might want to do this ourselves to call the
|
|
|
|
+ // worker on a more regular cyclic basis
|
|
struct timeval tmptv;
|
|
struct timeval tmptv;
|
|
memcpy(&tmptv,tv,sizeof(struct timeval));
|
|
memcpy(&tmptv,tv,sizeof(struct timeval));
|
|
|
|
|
|
// and wait
|
|
// and wait
|
|
DBG_VERBOSE(printf("UA_Stack_msgLoop - enter select sec=%d,usec=%d\n",(UA_Int32) tmptv.tv_sec, (UA_Int32) tmptv.tv_usec));
|
|
DBG_VERBOSE(printf("UA_Stack_msgLoop - enter select sec=%d,usec=%d\n",(UA_Int32) tmptv.tv_sec, (UA_Int32) tmptv.tv_usec));
|
|
result = select(nl->maxReaderHandle + 1, &(nl->readerHandles), UA_NULL, UA_NULL, &tmptv);
|
|
result = select(nl->maxReaderHandle + 1, &(nl->readerHandles), UA_NULL, UA_NULL, &tmptv);
|
|
-
|
|
|
|
DBG_VERBOSE(printf("UA_Stack_msgLoop - leave select result=%d,sec=%d,usec=%d\n",result, (UA_Int32) tmptv.tv_sec, (UA_Int32) tmptv.tv_usec));
|
|
DBG_VERBOSE(printf("UA_Stack_msgLoop - leave select result=%d,sec=%d,usec=%d\n",result, (UA_Int32) tmptv.tv_sec, (UA_Int32) tmptv.tv_usec));
|
|
|
|
+
|
|
|
|
+ // handle timeout (winsock: result=0, unix: result=0,errno=0||EAGAIN)
|
|
|
|
+ // and errors (winsock: result=SOCKET_ERROR (-1), unix: result = 0)
|
|
|
|
+ if (result <= 0) {
|
|
#ifdef WIN32
|
|
#ifdef WIN32
|
|
- if (result == -1) {
|
|
|
|
- DBG_ERR(printf("UA_Stack_msgLoop - errno = { %d, %s }\n", WSAGetLastError()));
|
|
|
|
- }
|
|
|
|
- else if (result >= 0){ // activity on listener or client ports
|
|
|
|
|
|
+ err = (result == SOCKET_ERROR) ? WSAGetLastError() : 0;
|
|
#else
|
|
#else
|
|
- if (result == 0) {
|
|
|
|
- UA_Int32 err = errno;
|
|
|
|
-
|
|
|
|
|
|
+ err = errno;
|
|
|
|
+#endif
|
|
switch (err) {
|
|
switch (err) {
|
|
|
|
+ // handle known errors
|
|
|
|
+#ifdef WIN32
|
|
|
|
+ case WSANOTINITIALISED:
|
|
|
|
+ case WSAEFAULT:
|
|
|
|
+ case WSAENETDOWN:
|
|
|
|
+ case WSAEINVAL:
|
|
|
|
+ case WSAEINTR:
|
|
|
|
+ case WSAEINPROGRESS:
|
|
|
|
+ case WSAENOTSOCK:
|
|
|
|
+#else
|
|
case EBADF:
|
|
case EBADF:
|
|
case EINTR:
|
|
case EINTR:
|
|
case EINVAL:
|
|
case EINVAL:
|
|
- //FIXME: handle errors
|
|
|
|
- DBG_ERR(printf("UA_Stack_msgLoop - errno={%d,%s}\n", errno, strerror(errno)));
|
|
|
|
|
|
+#endif
|
|
|
|
+ // FIXME: handle errors
|
|
|
|
+ printf("UA_Stack_msgLoop - result=%d, errno={%d,%s}\n", result, errno, strerror(errno));
|
|
break;
|
|
break;
|
|
- case EAGAIN: // timer due, call worker
|
|
|
|
- default: //
|
|
|
|
- DBG_VERBOSE(printf("UA_Stack_msgLoop - errno={%d,%s}\n", errno, strerror(errno)));
|
|
|
|
- DBG_VERBOSE(printf("UA_Stack_msgLoop - call worker\n"));
|
|
|
|
- worker(arg);
|
|
|
|
- DBG_VERBOSE(printf("UA_Stack_msgLoop - return from worker\n"));
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- else if (result > 0){ // activity on listener or client ports
|
|
|
|
|
|
+ // otherwise we've got a timeout and call the worker
|
|
|
|
+#ifndef WIN32
|
|
|
|
+ case EAGAIN:
|
|
#endif
|
|
#endif
|
|
|
|
+ default:
|
|
|
|
+ DBG_VERBOSE(printf("UA_Stack_msgLoop - result=%d, errno={%d,%s}\n", result, errno, strerror(errno)));
|
|
|
|
+ worker(arg);
|
|
|
|
+ }
|
|
|
|
+ } else { // activity on listener or client ports
|
|
DBG_VERBOSE(printf("UA_Stack_msgLoop - activities on %d handles\n",result));
|
|
DBG_VERBOSE(printf("UA_Stack_msgLoop - activities on %d handles\n",result));
|
|
UA_list_iteratePayload(&(nl->connections),NL_checkFdSet);
|
|
UA_list_iteratePayload(&(nl->connections),NL_checkFdSet);
|
|
|
|
+ // FIXME: Thought it would be a conceptional flaw to call the worker
|
|
|
|
+ // here. However, there is no guarantee that the timeout would be
|
|
|
|
+ // triggered, so we call it in this branch as well.
|
|
|
|
+ worker(arg);
|
|
}
|
|
}
|
|
- // Calling worker here would execute worker any times we had received something or were interrupted
|
|
|
|
- // worker(arg);
|
|
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+#ifdef WIN32
|
|
|
|
+ // finally we should clean up the winsock.dll
|
|
|
|
+ WSACleanup();
|
|
|
|
+#endif
|
|
return UA_SUCCESS;
|
|
return UA_SUCCESS;
|
|
}
|
|
}
|
|
-#endif
|
|
|
|
|
|
+#endif /* MULTITASKING */
|
|
|
|
|
|
|
|
|
|
/** the tcp reader function */
|
|
/** the tcp reader function */
|
|
@@ -188,13 +215,15 @@ void* NL_TCP_reader(NL_Connection *c) {
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
TL_Process((c->connection),&readBuffer);
|
|
TL_Process((c->connection),&readBuffer);
|
|
|
|
+ } else {
|
|
|
|
+ perror("NL_TCP_reader - ERROR reading from socket");
|
|
|
|
+ UA_TL_Connection_setState(c->connection, CONNECTIONSTATE_CLOSE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
UA_TL_Connection_getState(c->connection, &connectionState);
|
|
UA_TL_Connection_getState(c->connection, &connectionState);
|
|
DBG_VERBOSE(printf("NL_TCP_reader - connectionState=%d\n",connectionState));
|
|
DBG_VERBOSE(printf("NL_TCP_reader - connectionState=%d\n",connectionState));
|
|
if (connectionState == CONNECTIONSTATE_CLOSE) {
|
|
if (connectionState == CONNECTIONSTATE_CLOSE) {
|
|
- DBG_VERBOSE(printf("NL_TCP_reader - closing connection"));
|
|
|
|
// set connection's state to CONNECTIONSTATE_CLOSED and call callback to actually close
|
|
// set connection's state to CONNECTIONSTATE_CLOSED and call callback to actually close
|
|
UA_TL_Connection_close(c->connection);
|
|
UA_TL_Connection_close(c->connection);
|
|
#ifndef MULTITHREADING
|
|
#ifndef MULTITHREADING
|