win32 port
This commit is contained in:
@@ -1946,6 +1946,7 @@ int main (int argc, char *argv[])
|
||||
epicsThreadSleep(timeOut);
|
||||
}
|
||||
|
||||
epics::pvAccess::ca::CAClientFactory::stop();
|
||||
ClientFactory::stop();
|
||||
}
|
||||
// service RPC mode
|
||||
@@ -2137,7 +2138,6 @@ int main (int argc, char *argv[])
|
||||
|
||||
channel->destroy();
|
||||
|
||||
epics::pvAccess::ca::CAClientFactory::stop();
|
||||
ClientFactory::stop();
|
||||
}
|
||||
|
||||
|
||||
@@ -619,6 +619,8 @@ inline int sendto(int s, const char *buf, size_t len, int flags, const struct so
|
||||
nullTransportClient, responseHandler,
|
||||
listenLocalAddress, PVA_PROTOCOL_REVISION,
|
||||
PVA_DEFAULT_PRIORITY));
|
||||
if (!transport)
|
||||
continue;
|
||||
listenLocalAddress = *transport->getRemoteAddress();
|
||||
// to allow automatic assignment of listen port (for testing)
|
||||
if (listenPort == 0)
|
||||
@@ -660,17 +662,20 @@ inline int sendto(int s, const char *buf, size_t len, int flags, const struct so
|
||||
nullTransportClient, responseHandler,
|
||||
bcastAddress, PVA_PROTOCOL_REVISION,
|
||||
PVA_DEFAULT_PRIORITY));
|
||||
/* The other wrinkle is that nothing should be sent from this second
|
||||
* socket. So replies are made through the unicast socket.
|
||||
*
|
||||
transport2->setReplyTransport(transport);
|
||||
*/
|
||||
// NOTE: search responses all always send from sendTransport
|
||||
if (transport2)
|
||||
{
|
||||
/* The other wrinkle is that nothing should be sent from this second
|
||||
* socket. So replies are made through the unicast socket.
|
||||
*
|
||||
transport2->setReplyTransport(transport);
|
||||
*/
|
||||
// NOTE: search responses all always send from sendTransport
|
||||
|
||||
if (ignoreAddressVector.get() && ignoreAddressVector->size())
|
||||
transport2->setIgnoredAddresses(ignoreAddressVector.get());
|
||||
if (ignoreAddressVector.get() && ignoreAddressVector->size())
|
||||
transport2->setIgnoredAddresses(ignoreAddressVector.get());
|
||||
|
||||
tappedNIF.push_back(bcastAddress);
|
||||
tappedNIF.push_back(bcastAddress);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -710,7 +715,11 @@ inline int sendto(int s, const char *buf, size_t len, int flags, const struct so
|
||||
nullTransportClient, responseHandler,
|
||||
anyAddress, PVA_PROTOCOL_REVISION,
|
||||
PVA_DEFAULT_PRIORITY));
|
||||
|
||||
if (!sendTransport)
|
||||
{
|
||||
THROW_BASE_EXCEPTION("Failed to initialize UDP transport.");
|
||||
}
|
||||
|
||||
// TODO current implementation shares the port (aka beacon and search port)
|
||||
int32 sendPort = listenPort;
|
||||
|
||||
@@ -778,14 +787,27 @@ inline int sendto(int s, const char *buf, size_t len, int flags, const struct so
|
||||
// Setup local multicasting
|
||||
//
|
||||
|
||||
// WIN32 do not allow binding to multicast address, use any address w/ port
|
||||
#if defined(_WIN32)
|
||||
anyAddress.ia.sin_port = htons(listenPort);
|
||||
#endif
|
||||
|
||||
BlockingUDPTransport::shared_pointer localMulticastTransport;
|
||||
try
|
||||
{
|
||||
// NOTE: multicast receiver socket must be "bound" to INADDR_ANY or multicast address
|
||||
localMulticastTransport = static_pointer_cast<BlockingUDPTransport>(connector->connect(
|
||||
nullTransportClient, responseHandler,
|
||||
group, PVA_PROTOCOL_REVISION,
|
||||
PVA_DEFAULT_PRIORITY));
|
||||
#if !defined(_WIN32)
|
||||
group,
|
||||
#else
|
||||
anyAddress,
|
||||
#endif
|
||||
PVA_PROTOCOL_REVISION,
|
||||
PVA_DEFAULT_PRIORITY));
|
||||
if (!localMulticastTransport)
|
||||
throw std::runtime_error("Failed to bind UDP socket.");
|
||||
|
||||
localMulticastTransport->setTappedNIF(&tappedNIF);
|
||||
localMulticastTransport->join(group, loAddr);
|
||||
localMulticastTransport->start();
|
||||
@@ -797,7 +819,7 @@ inline int sendto(int s, const char *buf, size_t len, int flags, const struct so
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
LOG(logLevelDebug, "Failed to initialize local multicast, funcionality disabled. Reason: %s.", ex.what());
|
||||
LOG(logLevelDebug, "Failed to initialize local multicast, functionality disabled. Reason: %s.", ex.what());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include <pv/timer.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/sharedPtr.h>
|
||||
#include <pv/fairQueue.h>
|
||||
|
||||
#ifdef remoteEpicsExportSharedSymbols
|
||||
# define epicsExportSharedSymbols
|
||||
@@ -33,6 +32,7 @@
|
||||
|
||||
#include <pv/pvaConstants.h>
|
||||
#include <pv/configuration.h>
|
||||
#include <pv/fairQueue.h>
|
||||
|
||||
/// TODO only here because of the Lockable
|
||||
#include <pv/pvAccess.h>
|
||||
|
||||
@@ -50,7 +50,7 @@ const std::string &Properties::getProperty(const string &key, const string &defa
|
||||
}
|
||||
}
|
||||
|
||||
void Properties::Properties::load()
|
||||
void Properties::load()
|
||||
{
|
||||
load(_fileName);
|
||||
}
|
||||
|
||||
@@ -214,13 +214,12 @@ int getLoopbackNIF(osiSockAddr &loAddr, string const & localNIF, unsigned short
|
||||
|
||||
|
||||
|
||||
// copy of base-3.14.12.4/src/libCom/osi/os/default/osdNetIntf.c
|
||||
// TODO support windows (see osi/os/WIN32/osdNetIntf.c)
|
||||
|
||||
#include <osiSock.h>
|
||||
//#include <epicsAssert.h>
|
||||
#include <errlog.h>
|
||||
|
||||
#if !defined(_WIN32)
|
||||
|
||||
/*
|
||||
* Determine the size of an ifreq structure
|
||||
* Made difficult by the fact that addresses larger than the structure
|
||||
@@ -387,6 +386,7 @@ int discoverInterfaces(IfaceNodeVector &list, SOCKET socket, const osiSockAddr *
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
// if it is a match, accept the interface even if it does not support broadcast (i.e. 127.0.0.1)
|
||||
if (match)
|
||||
node.ifaceBCast.sa.sa_family = AF_UNSPEC;
|
||||
else
|
||||
@@ -406,5 +406,127 @@ int discoverInterfaces(IfaceNodeVector &list, SOCKET socket, const osiSockAddr *
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
#define VC_EXTRALEAN
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
int discoverInterfaces(IfaceNodeVector &list, SOCKET socket, const osiSockAddr *pMatchAddr)
|
||||
{
|
||||
int status;
|
||||
INTERFACE_INFO *pIfinfo;
|
||||
INTERFACE_INFO *pIfinfoList;
|
||||
unsigned nelem;
|
||||
int numifs;
|
||||
DWORD cbBytesReturned;
|
||||
int match;
|
||||
|
||||
/* only valid for winsock 2 and above
|
||||
TODO resolve dllimport compilation problem and uncomment this check
|
||||
if (wsaMajorVersion() < 2 ) {
|
||||
fprintf(stderr, "Need to set EPICS_CA_AUTO_ADDR_LIST=NO for winsock 1\n");
|
||||
return -1;
|
||||
}
|
||||
*/
|
||||
|
||||
nelem = 100;
|
||||
pIfinfoList = (INTERFACE_INFO *) calloc(nelem, sizeof(INTERFACE_INFO));
|
||||
if(!pIfinfoList){
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = WSAIoctl (socket, SIO_GET_INTERFACE_LIST,
|
||||
NULL, 0,
|
||||
(LPVOID)pIfinfoList, nelem*sizeof(INTERFACE_INFO),
|
||||
&cbBytesReturned, NULL, NULL);
|
||||
|
||||
if (status != 0 || cbBytesReturned == 0) {
|
||||
fprintf(stderr, "WSAIoctl SIO_GET_INTERFACE_LIST failed %d\n",WSAGetLastError());
|
||||
free(pIfinfoList);
|
||||
return -1;
|
||||
}
|
||||
|
||||
numifs = cbBytesReturned/sizeof(INTERFACE_INFO);
|
||||
for (pIfinfo = pIfinfoList; pIfinfo < (pIfinfoList+numifs); pIfinfo++){
|
||||
|
||||
/*
|
||||
* dont bother with interfaces that have been disabled
|
||||
*/
|
||||
if (!(pIfinfo->iiFlags & IFF_UP)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* If its not an internet interface then dont use it
|
||||
* + work around WS2 bug
|
||||
*/
|
||||
if (pIfinfo->iiAddress.Address.sa_family != AF_INET) {
|
||||
if (pIfinfo->iiAddress.Address.sa_family == 0) {
|
||||
pIfinfo->iiAddress.Address.sa_family = AF_INET;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* if it isnt a wildcarded interface then look for
|
||||
* an exact match
|
||||
*/
|
||||
match = 0;
|
||||
if (pMatchAddr && pMatchAddr->sa.sa_family != AF_UNSPEC) {
|
||||
if (pIfinfo->iiAddress.Address.sa_family != pMatchAddr->sa.sa_family) {
|
||||
continue;
|
||||
}
|
||||
if (pIfinfo->iiAddress.Address.sa_family != AF_INET) {
|
||||
continue;
|
||||
}
|
||||
if (pMatchAddr->sa.sa_family != AF_INET) {
|
||||
continue;
|
||||
}
|
||||
if (pMatchAddr->ia.sin_addr.s_addr != htonl(INADDR_ANY)) {
|
||||
if (pIfinfo->iiAddress.AddressIn.sin_addr.s_addr != pMatchAddr->ia.sin_addr.s_addr) {
|
||||
continue;
|
||||
}
|
||||
else
|
||||
match = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* dont use the loop back interface, unless it maches pMatchAddr
|
||||
*/
|
||||
if (!match) {
|
||||
if (pIfinfo->iiFlags & IFF_LOOPBACK) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
ifaceNode node;
|
||||
node.ifaceAddr.ia = pIfinfo->iiAddress.AddressIn;
|
||||
|
||||
if (pIfinfo->iiFlags & IFF_BROADCAST) {
|
||||
const unsigned mask = pIfinfo->iiNetmask.AddressIn.sin_addr.s_addr;
|
||||
const unsigned bcast = pIfinfo->iiBroadcastAddress.AddressIn.sin_addr.s_addr;
|
||||
const unsigned addr = pIfinfo->iiAddress.AddressIn.sin_addr.s_addr;
|
||||
unsigned result = (addr & mask) | (bcast &~mask);
|
||||
node.ifaceBCast.ia.sin_family = AF_INET;
|
||||
node.ifaceBCast.ia.sin_addr.s_addr = result;
|
||||
node.ifaceBCast.ia.sin_port = htons ( 0 );
|
||||
}
|
||||
else {
|
||||
node.ifaceBCast.ia = pIfinfo->iiBroadcastAddress.AddressIn;
|
||||
}
|
||||
|
||||
|
||||
list.push_back(node);
|
||||
}
|
||||
|
||||
free (pIfinfoList);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ namespace epics {
|
||||
va_end(arg);
|
||||
|
||||
printf("\n");
|
||||
fflush(stdout); // needed for WIN32
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -191,7 +191,7 @@ public:
|
||||
inline size_t size() const {return confs.size();}
|
||||
};
|
||||
|
||||
struct ConfigurationBuilder
|
||||
struct epicsShareClass ConfigurationBuilder
|
||||
{
|
||||
ConfigurationBuilder();
|
||||
ConfigurationBuilder& push_env();
|
||||
|
||||
@@ -7,7 +7,11 @@
|
||||
#ifndef FAIRQUEUE_H
|
||||
#define FAIRQUEUE_H
|
||||
|
||||
#include <shareLib.h>
|
||||
#ifdef epicsExportSharedSymbols
|
||||
# define fairQueueExportSharedSymbols
|
||||
# undef epicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
#include <epicsEvent.h>
|
||||
#include <epicsMutex.h>
|
||||
#include <epicsGuard.h>
|
||||
@@ -16,6 +20,13 @@
|
||||
|
||||
#include <pv/sharedPtr.h>
|
||||
|
||||
#ifdef fairQueueExportSharedSymbols
|
||||
# define epicsExportSharedSymbols
|
||||
# undef fairQueueExportSharedSymbols
|
||||
#endif
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics {namespace pvAccess {
|
||||
|
||||
|
||||
@@ -42,13 +53,13 @@ namespace epics {namespace pvAccess {
|
||||
* as push_back() does not broadcast (only wakes up one waiter)
|
||||
*/
|
||||
template<typename T>
|
||||
class epicsShareClass fair_queue
|
||||
class fair_queue
|
||||
{
|
||||
typedef epicsGuard<epicsMutex> guard_t;
|
||||
public:
|
||||
typedef std::tr1::shared_ptr<T> value_type;
|
||||
|
||||
class epicsShareClass entry {
|
||||
class entry {
|
||||
/* In c++, use of ellLib (which implies offsetof()) should be restricted
|
||||
* to POD structs. So enode_t exists as a POD struct for which offsetof()
|
||||
* is safe and well defined. enode_t::self is used in place of
|
||||
|
||||
Reference in New Issue
Block a user