async-socket-transport.hpp
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
22 #ifndef NDN_ASYNC_SOCKET_TRANSPORT_HPP
23 #define NDN_ASYNC_SOCKET_TRANSPORT_HPP
24 
25 #include <stdexcept>
26 #include <boost/bind.hpp>
27 #include <boost/asio.hpp>
28 #include <ndn-cpp/transport/transport.hpp>
29 #include "../c/encoding/element-reader.h"
30 #include "../encoding/element-listener.hpp"
31 #include "../util/dynamic-uint8-vector.hpp"
32 
33 namespace ndn {
34 
43 template<class AsioProtocol> class AsyncSocketTransport {
44 public:
51  AsyncSocketTransport(boost::asio::io_service& ioService)
52  : ioService_(ioService), socket_(new typename AsioProtocol::socket(ioService)),
53  elementBuffer_(new DynamicUInt8Vector(1000)), isConnected_(false)
54  {
55  ndn_ElementReader_initialize(&elementReader_, 0, elementBuffer_.get());
56  }
57 
69  void
70  connect
71  (const typename AsioProtocol::endpoint& endPoint,
72  ElementListener& elementListener, const Transport::OnConnected& onConnected)
73  {
74  close();
75 
76  ndn_ElementReader_reset(&elementReader_, &elementListener);
77 
78  socket_->async_connect
79  (endPoint,
80  boost::bind(&AsyncSocketTransport::connectHandler, this, _1, onConnected));
81  }
82 
90  void
91  send(const uint8_t *data, size_t dataLength)
92  {
93  if (!isConnected_)
94  throw std::runtime_error
95  ("AsyncSocketTransport.send: The socket is not connected");
96 
97  // Assume that this is called from a dispatch so that we are already in the
98  // ioService_ thread. Just do a blocking write.
99  boost::system::error_code errorCode;
100  boost::asio::write
101  (*socket_, boost::asio::buffer(data, dataLength), errorCode);
102  if (errorCode != boost::system::errc::success)
103  throw std::runtime_error("AsyncSocketTransport.send: Error in write");
104  }
105 
106  bool
107  getIsConnected()
108  {
109  return isConnected_;
110  }
111 
115  void
117  {
118  try {
119  socket_->close();
120  }
121  catch (...) {
122  // Ignore any exceptions.
123  }
124 
125  isConnected_ = false;
126  }
127 
128 private:
132  void
133  connectHandler
134  (const boost::system::error_code& errorCode,
135  const Transport::OnConnected& onConnected)
136  {
137  if (errorCode != boost::system::errc::success)
138  // TODO: How to report errors to the application?
139  throw std::runtime_error("AsyncSocketTransport: Error in async_connect");
140 
141  isConnected_ = true;
142  onConnected();
143 
144  socket_->async_receive
145  (boost::asio::buffer(receiveBuffer_, sizeof(receiveBuffer_)), 0,
146  boost::bind(&AsyncSocketTransport::readHandler, this, _1, _2));
147  }
148 
153  void
154  readHandler(const boost::system::error_code& errorCode, size_t nBytesReceived)
155  {
156  if (errorCode != boost::system::errc::success) {
157  if (errorCode == boost::system::errc::operation_canceled)
158  // Assume the socket has been closed. Do nothing.
159  return;
160 
161  close();
162  // TODO: How to report errors to the application?
163  throw std::runtime_error("AsyncSocketTransport: Error in async_receive");
164  }
165 
166  ndn_Error error;
167  if ((error = ndn_ElementReader_onReceivedData
168  (&elementReader_, receiveBuffer_, nBytesReceived)))
169  throw std::runtime_error(ndn_getErrorString(error));
170 
171  // Request another async receive to loop back to here.
172  socket_->async_receive
173  (boost::asio::buffer(receiveBuffer_, sizeof(receiveBuffer_)), 0,
174  boost::bind(&AsyncSocketTransport::readHandler, this, _1, _2));
175  }
176 
177  boost::asio::io_service& ioService_;
178  ptr_lib::shared_ptr<typename AsioProtocol::socket> socket_;
179  uint8_t receiveBuffer_[MAX_NDN_PACKET_SIZE];
180  ptr_lib::shared_ptr<DynamicUInt8Vector> elementBuffer_;
181  ndn_ElementReader elementReader_;
182  bool isConnected_;
183 };
184 
185 }
186 
187 #endif
Copyright (C) 2013-2016 Regents of the University of California.
Definition: common.hpp:35
An ElementListener extends an ndn_ElementListener struct to proved an abstract virtual onReceivedElem...
Definition: element-listener.hpp:33
void connect(const typename AsioProtocol::endpoint &endPoint, ElementListener &elementListener, const Transport::OnConnected &onConnected)
Connect according to the info in connectionInfo, and use elementListener.
Definition: async-socket-transport.hpp:71
void close()
Close the connection to the host.
Definition: async-socket-transport.hpp:116
void send(const uint8_t *data, size_t dataLength)
Set data to the host.
Definition: async-socket-transport.hpp:91
AsyncSocketTransport(boost::asio::io_service &ioService)
Create an AsyncSocketTransport in the unconnected state.
Definition: async-socket-transport.hpp:51
A DynamicUInt8Vector extends ndn_DynamicUInt8Array to hold a shared_ptr > for use wit...
Definition: dynamic-uint8-vector.hpp:37
A ndn_ElementReader lets you call ndn_ElementReader_onReceivedData multiple times which uses an ndn_T...
Definition: element-reader-types.h:59