win32 port

This commit is contained in:
Matej Sekoranja
2016-03-06 21:21:26 +01:00
parent 9b6fdaaaff
commit 87c11d83d2
8 changed files with 179 additions and 23 deletions

View File

@@ -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();
}

View File

@@ -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());
}
}

View File

@@ -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>

View File

@@ -50,7 +50,7 @@ const std::string &Properties::getProperty(const string &key, const string &defa
}
}
void Properties::Properties::load()
void Properties::load()
{
load(_fileName);
}

View File

@@ -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
}
}

View File

@@ -53,6 +53,7 @@ namespace epics {
va_end(arg);
printf("\n");
fflush(stdout); // needed for WIN32
}
}

View File

@@ -191,7 +191,7 @@ public:
inline size_t size() const {return confs.size();}
};
struct ConfigurationBuilder
struct epicsShareClass ConfigurationBuilder
{
ConfigurationBuilder();
ConfigurationBuilder& push_env();

View File

@@ -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