completed merge
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user