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