transport: Implementation of semi-async UNIX transport (for TLV format only)
This implementation uses boost::asio to simplify all the implementation.
- connect and send operations are sync
- receive operation is async
Change-Id: If21147fbb579dc073c385a0f3a2aeef2d83fab04
diff --git a/Makefile.am b/Makefile.am
index 4134735..d6ae92b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -125,9 +125,8 @@
src/security/policy/self-verify-policy-manager.cpp \
src/security/security-exception.cpp \
src/security/signature/sha256-with-rsa-handler.cpp \
- src/transport/tcp-transport.cpp \
src/transport/transport.cpp \
- src/transport/udp-transport.cpp \
+ src/transport/unix-transport.cpp \
src/util/blob-stream.hpp \
src/util/blob.cpp \
src/util/changed-event.cpp \
diff --git a/include/ndn-cpp/transport/unix-transport.hpp b/include/ndn-cpp/transport/unix-transport.hpp
new file mode 100644
index 0000000..bb77bb4
--- /dev/null
+++ b/include/ndn-cpp/transport/unix-transport.hpp
@@ -0,0 +1,66 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NDN_UDPTRANSPORT_HPP
+#define NDN_UDPTRANSPORT_HPP
+
+#include <string>
+#include "transport.hpp"
+
+namespace ndn {
+
+class UnixTransport : public Transport {
+public:
+ UnixTransport(const std::string &unixSocket = "/tmp/.ndnd.sock");
+ ~UnixTransport();
+
+ /**
+ * Connect according to the info in ConnectionInfo, and processEvents() will use elementListener.
+ * @param connectionInfo A reference to a TcpTransport::ConnectionInfo.
+ * @param elementListener Not a shared_ptr because we assume that it will remain valid during the life of this object.
+ */
+ virtual void
+ connect(ElementListener& elementListener);
+
+ /**
+ * Set data to the host
+ * @param data A pointer to the buffer of data to send.
+ * @param dataLength The number of bytes in data.
+ */
+ virtual void
+ send(const uint8_t *data, size_t dataLength);
+
+ /**
+ * Process any data to receive. For each element received, call elementListener.onReceivedElement.
+ * This is non-blocking and will return immediately if there is no data to receive.
+ * You should normally not call this directly since it is called by Face.processEvents.
+ * @throw This may throw an exception for reading data or in the callback for processing the data. If you
+ * call this from an main event loop, you may want to catch and log/disregard all exceptions.
+ */
+ virtual void
+ processEvents();
+
+ virtual bool
+ getIsConnected();
+
+ /**
+ * Close the connection to the host.
+ */
+ virtual void
+ close();
+
+private:
+ std::string unixSocket_;
+ bool isConnected_;
+
+ class Impl;
+ std::auto_ptr<Impl> impl_;
+};
+
+}
+
+#endif
diff --git a/src/transport/unix-transport.cpp b/src/transport/unix-transport.cpp
new file mode 100644
index 0000000..603f5e3
--- /dev/null
+++ b/src/transport/unix-transport.cpp
@@ -0,0 +1,128 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * See COPYING for copyright and distribution information.
+ */
+
+#include <stdexcept>
+#include <stdlib.h>
+
+#include <ndn-cpp/face.hpp>
+#include <ndn-cpp/transport/unix-transport.hpp>
+
+#include <boost/asio.hpp>
+#include <boost/bind.hpp>
+
+using namespace std;
+typedef boost::asio::local::datagram_protocol protocol;
+
+namespace ndn {
+
+const size_t MAX_LENGTH = 9000;
+
+class UnixTransport::Impl
+{
+public:
+ Impl() : socket_(io_)
+ {
+ }
+
+ bool
+ connect(const std::string &unixSocket, ElementListener& elementListener)
+ {
+ socket_.open();
+ socket_.connect(protocol::endpoint(unixSocket));
+ // socket_.async_connect(protocol::endpoint(unixSocket));
+
+ socket_.async_receive(boost::asio::buffer(inputBuffer_, MAX_LENGTH), 0,
+ boost::bind(&Impl::handle_async_receive, this, _1, _2));
+
+ return true;
+ }
+
+ void
+ send(const uint8_t *data, size_t dataLength)
+ {
+ socket_.send(boost::asio::buffer(data, dataLength));
+ }
+
+ void
+ processEvents()
+ {
+ io_.poll();
+ // from boost docs:
+ // The poll() function runs handlers that are ready to run, without blocking, until the io_service has been stopped or there are no more ready handlers.
+ }
+
+ void
+ handle_async_receive(const boost::system::error_code& error, std::size_t bytes_recvd)
+ {
+ if (!error && bytes_recvd > 0)
+ {
+ // inputBuffer_ has bytes_recvd received bytes of data
+ }
+
+ socket_.async_receive(boost::asio::buffer(inputBuffer_, MAX_LENGTH), 0,
+ boost::bind(&Impl::handle_async_receive, this, _1, _2));
+ }
+
+ void
+ close()
+ {
+ socket_.close();
+ }
+
+private:
+ boost::asio::io_service io_;
+
+ protocol::socket socket_;
+
+ uint8_t inputBuffer_[MAX_LENGTH];
+};
+
+UnixTransport::UnixTransport(const std::string &unixSocket/* = "/tmp/.ndnd.sock"*/)
+ : unixSocket_(unixSocket)
+ , isConnected_(false)
+ , impl_(new UnixTransport::Impl())
+{
+}
+
+UnixTransport::~UnixTransport()
+{
+}
+
+void
+UnixTransport::connect(ElementListener& elementListener)
+{
+ if (impl_->connect(unixSocket_, elementListener))
+ {
+ isConnected_ = true;
+ }
+}
+
+void
+UnixTransport::send(const uint8_t *data, size_t dataLength)
+{
+ impl_->send(data, dataLength);
+}
+
+void
+UnixTransport::processEvents()
+{
+ impl_->processEvents();
+}
+
+bool
+UnixTransport::getIsConnected()
+{
+ return isConnected_;
+}
+
+void
+UnixTransport::close()
+{
+ impl_->close();
+}
+
+}