completed merge

This commit is contained in:
Matej Sekoranja
2014-06-10 00:09:08 +02:00
61 changed files with 3280 additions and 1955 deletions

View File

@@ -53,22 +53,17 @@ inline int sendto(int s, const char *buf, size_t len, int flags, const struct so
{
PVACCESS_REFCOUNT_MONITOR_CONSTRUCT(blockingUDPTransport);
// set receive timeout so that we do not have problems at shutdown (recvfrom would block)
struct timeval timeout;
memset(&timeout, 0, sizeof(struct timeval));
timeout.tv_sec = 1;
timeout.tv_usec = 0;
osiSocklen_t sockLen = sizeof(sockaddr);
// read the actual socket info
int retval = ::getsockname(_channel, &_remoteAddress.sa, &sockLen);
if(retval<0) {
// error obtaining remote address, fallback to bindAddress
_remoteAddress = _bindAddress;
if (unlikely(::setsockopt (_channel, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout)) < 0))
{
char errStr[64];
epicsSocketConvertErrnoToString(errStr, sizeof(errStr));
LOG(logLevelError,
"Failed to set SO_RCVTIMEO for UDP socket %s: %s.",
inetAddressToString(_bindAddress).c_str(), errStr);
char strBuffer[64];
epicsSocketConvertErrnoToString(strBuffer, sizeof(strBuffer));
LOG(logLevelDebug, "getsockname error: %s", strBuffer);
}
}
BlockingUDPTransport::~BlockingUDPTransport() {
@@ -84,9 +79,13 @@ inline int sendto(int s, const char *buf, size_t len, int flags, const struct so
void BlockingUDPTransport::start() {
String threadName = "UDP-receive "+inetAddressToString(_bindAddress);
LOG(logLevelDebug, "Starting thread: %s",threadName.c_str());
String threadName = "UDP-receive " + inetAddressToString(_bindAddress);
if (IS_LOGGABLE(logLevelTrace))
{
LOG(logLevelTrace, "Starting thread: %s.", threadName.c_str());
}
_threadId = epicsThreadCreate(threadName.c_str(),
epicsThreadPriorityMedium,
epicsThreadGetStackSize(epicsThreadStackSmall),
@@ -102,39 +101,44 @@ inline int sendto(int s, const char *buf, size_t len, int flags, const struct so
Lock guard(_mutex);
if(_closed.get()) return;
_closed.set();
}
if (IS_LOGGABLE(logLevelDebug))
{
LOG(logLevelDebug,
"UDP socket %s closed.",
inetAddressToString(_bindAddress).c_str());
epicsSocketSystemCallInterruptMechanismQueryInfo info =
epicsSocketSystemCallInterruptMechanismQuery ();
switch ( info ) {
case esscimqi_socketCloseRequired:
epicsSocketDestroy ( _channel );
break;
case esscimqi_socketBothShutdownRequired:
{
int status = ::shutdown ( _channel, SHUT_RDWR );
if ( status ) {
char sockErrBuf[64];
epicsSocketConvertErrnoToString (
sockErrBuf, sizeof ( sockErrBuf ) );
LOG(logLevelDebug,
"UDP socket %s failed to shutdown: %s.",
inetAddressToString(_bindAddress).c_str(), sockErrBuf);
}
epicsSocketDestroy ( _channel );
}
break;
case esscimqi_socketSigAlarmRequired:
// TODO (not supported anymore anyway)
default:
epicsSocketDestroy(_channel);
}
}
// TODO send yourself a packet
epicsSocketSystemCallInterruptMechanismQueryInfo info =
epicsSocketSystemCallInterruptMechanismQuery ();
switch ( info )
{
case esscimqi_socketCloseRequired:
epicsSocketDestroy ( _channel );
break;
case esscimqi_socketBothShutdownRequired:
{
/*int status =*/ ::shutdown ( _channel, SHUT_RDWR );
/*
if ( status ) {
char sockErrBuf[64];
epicsSocketConvertErrnoToString (
sockErrBuf, sizeof ( sockErrBuf ) );
LOG(logLevelDebug,
"UDP socket %s failed to shutdown: %s.",
inetAddressToString(_bindAddress).c_str(), sockErrBuf);
}
*/
epicsSocketDestroy ( _channel );
}
break;
case esscimqi_socketSigAlarmRequired:
// not supported anymore anyway
default:
epicsSocketDestroy(_channel);
}
// wait for send thread to exit cleanly
if (waitForThreadToComplete)
@@ -255,7 +259,7 @@ inline int sendto(int s, const char *buf, size_t len, int flags, const struct so
{
char errStr[64];
epicsSocketConvertErrnoToString(errStr, sizeof(errStr));
LOG(logLevelError, "Socket recvfrom error: %s", errStr);
LOG(logLevelError, "Socket recvfrom error: %s.", errStr);
}
close(false);
@@ -268,12 +272,11 @@ inline int sendto(int s, const char *buf, size_t len, int flags, const struct so
close(false);
}
String threadName = "UDP-receive "+inetAddressToString(_bindAddress);
/*
char threadName[40];
epicsThreadGetName(_threadId, threadName, 40);
*/
LOG(logLevelDebug, "Thread '%s' exiting", threadName.c_str());
if (IS_LOGGABLE(logLevelTrace))
{
String threadName = "UDP-receive "+inetAddressToString(_bindAddress);
LOG(logLevelTrace, "Thread '%s' exiting.", threadName.c_str());
}
_shutdownEvent.signal();
}
@@ -337,20 +340,30 @@ inline int sendto(int s, const char *buf, size_t len, int flags, const struct so
{
char errStr[64];
epicsSocketConvertErrnoToString(errStr, sizeof(errStr));
LOG(logLevelDebug, "Socket sendto error: %s", errStr);
LOG(logLevelDebug, "Socket sendto error: %s.", errStr);
return false;
}
// all sent
buffer->setPosition(buffer->getLimit());
return true;
}
bool BlockingUDPTransport::send(ByteBuffer* buffer) {
bool BlockingUDPTransport::send(ByteBuffer* buffer, InetAddressType target) {
if(!_sendAddresses) return false;
buffer->flip();
bool allOK = true;
for(size_t i = 0; i<_sendAddresses->size(); i++) {
// filter
if (target != inetAddressType_all)
if ((target == inetAddressType_unicast && !_isSendAddressUnicast[i]) ||
(target == inetAddressType_broadcast_multicast && _isSendAddressUnicast[i]))
continue;
int retval = sendto(_channel, buffer->getArray(),
buffer->getLimit(), 0, &((*_sendAddresses)[i].sa),
sizeof(sockaddr));
@@ -358,11 +371,14 @@ inline int sendto(int s, const char *buf, size_t len, int flags, const struct so
{
char errStr[64];
epicsSocketConvertErrnoToString(errStr, sizeof(errStr));
LOG(logLevelDebug, "Socket sendto error: %s", errStr);
LOG(logLevelDebug, "Socket sendto error: %s.", errStr);
allOK = false;
}
}
// all sent
buffer->setPosition(buffer->getLimit());
return allOK;
}
@@ -379,7 +395,7 @@ inline int sendto(int s, const char *buf, size_t len, int flags, const struct so
{
char errStr[64];
epicsSocketConvertErrnoToString(errStr, sizeof(errStr));
LOG(logLevelError, "Socket getsockopt SO_RCVBUF error: %s", errStr);
LOG(logLevelError, "Socket getsockopt SO_RCVBUF error: %s.", errStr);
}
return (size_t)sockBufSize;