diff --git a/.cproject b/.cproject index fb31768..0e2a39f 100644 --- a/.cproject +++ b/.cproject @@ -26,7 +26,6 @@ @@ -45,7 +44,7 @@ - @@ -308,7 +307,6 @@ make - all true true @@ -316,12 +314,19 @@ make - clean true true false + + make + + uninstall + true + true + false + diff --git a/pvAccessApp/Makefile b/pvAccessApp/Makefile index 01422d6..b093ac9 100644 --- a/pvAccessApp/Makefile +++ b/pvAccessApp/Makefile @@ -37,8 +37,9 @@ LIBSRCS += CreateRequestFactory.cpp SRC_DIRS += $(PVACCESS)/remote INC += remote.h -INC += blockingUDPTransport.h +INC += blockingUDP.h LIBSRCS += blockingUDPTransport.cpp +LIBSRCS += blockingUDPConnector.cpp LIBRARY = pvAccess diff --git a/pvAccessApp/remote/blockingUDPTransport.h b/pvAccessApp/remote/blockingUDP.h similarity index 82% rename from pvAccessApp/remote/blockingUDPTransport.h rename to pvAccessApp/remote/blockingUDP.h index 7b9b9ef..f9281c2 100644 --- a/pvAccessApp/remote/blockingUDPTransport.h +++ b/pvAccessApp/remote/blockingUDP.h @@ -5,8 +5,8 @@ * Author: Miha Vitorovic */ -#ifndef BLOCKINGUDPTRANSPORT_H_ -#define BLOCKINGUDPTRANSPORT_H_ +#ifndef BLOCKINGUDP_H_ +#define BLOCKINGUDP_H_ /* pvAccess */ #include "remote.h" @@ -16,6 +16,7 @@ /* pvData */ #include #include +#include /* EPICSv3 */ #include @@ -230,9 +231,53 @@ namespace epics { */ char* _readBuffer; + /** + * Used for process sync. + */ + Mutex* _mutex; + + }; + + class BlockingUDPConnector : public Connector, NoDefaultMethods { + public: + + BlockingUDPConnector(bool reuseSocket, + InetAddrVector* sendAddresses, bool broadcast) : + _sendAddresses(sendAddresses), _reuseSocket(reuseSocket), + _broadcast(broadcast) { + } + + virtual ~BlockingUDPConnector() { + // TODO: delete _sendAddresses here? + } + + /** + * NOTE: transport client is ignored for broadcast (UDP). + */ + virtual Transport* connect(TransportClient* client, + ResponseHandler* responseHandler, osiSockAddr* bindAddress, + short transportRevision, short priority); + + private: + + /** + * Send address. + */ + InetAddrVector* _sendAddresses; + + /** + * Reuse socket flag. + */ + bool _reuseSocket; + + /** + * Broadcast flag. + */ + bool _broadcast; + }; } } -#endif /* BLOCKINGUDPTRANSPORT_H_ */ +#endif /* BLOCKINGUDP_H_ */ diff --git a/pvAccessApp/remote/blockingUDPConnector.cpp b/pvAccessApp/remote/blockingUDPConnector.cpp new file mode 100644 index 0000000..f207fee --- /dev/null +++ b/pvAccessApp/remote/blockingUDPConnector.cpp @@ -0,0 +1,68 @@ +/* + * blockingUDPConnector.cpp + * + * Created on: Dec 27, 2010 + * Author: Miha Vitorovic + */ + +/* pvAccess */ +#include "blockingUDP.h" +#include "remote.h" + +/* pvData */ +#include + +/* EPICSv3 */ +#include + +/* standard */ +#include +#include + +namespace epics { + namespace pvAccess { + + Transport* BlockingUDPConnector::connect(TransportClient* client, + ResponseHandler* responseHandler, osiSockAddr* bindAddress, + short transportRevision, short priority) { + errlogSevPrintf(errlogInfo, "Creating datagram socket to: %s", + inetAddressToString(bindAddress).c_str()); + + SOCKET socket = ::socket(PF_INET, SOCK_DGRAM, 0); + + /* from MSDN: + * Note: If the setsockopt function is called before the bind + * function, TCP/IP options will not be checked by using TCP/IP + * until the bind occurs. In this case, the setsockopt function + * call will always succeed, but the bind function call can fail + * because of an early setsockopt call failing. + */ + + int retval = ::bind(socket, (sockaddr*)&(bindAddress->sa), + sizeof(sockaddr)); + if(retval<0) { + errlogSevPrintf(errlogMajor, "Error binding socket: %s", + strerror(errno)); + THROW_BASE_EXCEPTION(strerror(errno)); + } + + // set the socket options + + int optval = 1; // true + + retval = ::setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, &optval, + sizeof(optval)); + if(retval<0) errlogSevPrintf(errlogMajor, + "Error binding socket: %s", strerror(errno)); + + retval = ::setsockopt(socket, SOL_SOCKET, SO_BROADCAST, &optval, + sizeof(optval)); + + // sockets are blocking by default + + return new BlockingUDPTransport(responseHandler, socket, + bindAddress, _sendAddresses, transportRevision); + } + + } +} diff --git a/pvAccessApp/remote/blockingUDPTransport.cpp b/pvAccessApp/remote/blockingUDPTransport.cpp index 764ae8d..9a83973 100644 --- a/pvAccessApp/remote/blockingUDPTransport.cpp +++ b/pvAccessApp/remote/blockingUDPTransport.cpp @@ -5,13 +5,14 @@ */ /* pvAccess */ -#include "blockingUDPTransport.h" +#include "blockingUDP.h" #include "caConstants.h" #include "inetAddressUtil.h" /* pvData */ #include +#include /* EPICSv3 */ #include @@ -21,7 +22,8 @@ /* standard */ #include -#include +#include +#include #include #include @@ -33,31 +35,22 @@ namespace epics { BlockingUDPTransport::BlockingUDPTransport( ResponseHandler* responseHandler, SOCKET channel, osiSockAddr* bindAddress, InetAddrVector* sendAddresses, - short remoteTransportRevision) { - _responseHandler = responseHandler; - _channel = channel; - _bindAddress = bindAddress; - _sendAddresses = sendAddresses; - - _socketAddress = bindAddress; - - // allocate receive buffer - _receiveBuffer = new ByteBuffer(MAX_UDP_RECV); - - // allocate send buffer and non-reentrant lock - _sendBuffer = new ByteBuffer(MAX_UDP_SEND); - - _ignoredAddresses = NULL; - _sendTo = NULL; - _closed = false; - _lastMessageStartPosition = 0; - _readBuffer = new char[MAX_UDP_RECV]; + short remoteTransportRevision) : + _closed(false), _responseHandler(responseHandler), + _channel(channel), _socketAddress(bindAddress), + _bindAddress(bindAddress), _sendAddresses(sendAddresses), + _ignoredAddresses(NULL), _sendTo(NULL), _receiveBuffer( + new ByteBuffer(MAX_UDP_RECV)), _sendBuffer( + new ByteBuffer(MAX_UDP_RECV)), + _lastMessageStartPosition(0), _readBuffer( + new char[MAX_UDP_RECV]), _mutex(new Mutex()) { } BlockingUDPTransport::~BlockingUDPTransport() { delete _receiveBuffer; delete _sendBuffer; delete _readBuffer; + delete _mutex; } void BlockingUDPTransport::start() { @@ -87,7 +80,7 @@ namespace epics { } void BlockingUDPTransport::enqueueSendRequest(TransportSender* sender) { - // TODO: Java version uses synchronized. Why? + Lock lock(_mutex); _sendTo = NULL; _sendBuffer->clear(); diff --git a/pvAccessApp/remote/remote.h b/pvAccessApp/remote/remote.h index 57038c1..e8b0dc2 100644 --- a/pvAccessApp/remote/remote.h +++ b/pvAccessApp/remote/remote.h @@ -204,6 +204,60 @@ namespace epics { int payloadSize, ByteBuffer* payloadBuffer) =0; }; + /** + * Client (user) of the transport. + * @author Matej Sekoranja + * @version $Id: TransportClient.java,v 1.1 2010/05/03 14:45:39 mrkraimer Exp $ + */ + class TransportClient { + public: + /** + * Notification of unresponsive transport (e.g. no heartbeat detected) . + */ + virtual void transportUnresponsive() =0; + + /** + * Notification of responsive transport (e.g. heartbeat detected again), + * called to discard transportUnresponsive notification. + * @param transport responsive transport. + */ + virtual void transportResponsive(Transport* transport) =0; + + /** + * Notification of network change (server restarted). + */ + virtual void transportChanged() =0; + + /** + * Notification of forcefully closed transport. + */ + virtual void transportClosed() =0; + + }; + + + /** + * Interface defining socket connector (Connector-Transport pattern). + * @author Matej Sekoranja + * @version $Id: Connector.java,v 1.1 2010/05/03 14:45:39 mrkraimer Exp $ + */ + class Connector { + public: + /** + * Connect. + * @param[in] client client requesting connection (transport). + * @param[in] address address of the server. + * @param[in] responseHandler reponse handler. + * @param[in] transportRevision transport revision to be used. + * @param[in] priority process priority. + * @return transport instance. + * @throws ConnectionException + */ + virtual Transport* connect(TransportClient* client, ResponseHandler* responseHandler, + osiSockAddr* address, short transportRevision, short priority) =0; + + }; + } } diff --git a/pvAccessApp/utils/introspectionRegistry.h b/pvAccessApp/utils/introspectionRegistry.h index dd32d1d..549fbdd 100644 --- a/pvAccessApp/utils/introspectionRegistry.h +++ b/pvAccessApp/utils/introspectionRegistry.h @@ -5,18 +5,20 @@ #ifndef INTROSPECTIONREGISTRY_H #define INTROSPECTIONREGISTRY_H -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include + #include -#include "lock.h" -#include "pvIntrospect.h" -#include "pvData.h" -#include "byteBuffer.h" -#include "serialize.h" -#include "serializeHelper.h" -#include "status.h" -#include "standardField.h" +#include +#include + using namespace epics::pvData; using namespace std;