30 #include <pcap/pcap.h>
34 #include <boost/endian/conversion.hpp>
42 const ethernet::Address& remoteEndpoint)
44 , m_pcap(localEndpoint.getName())
45 , m_srcAddress(localEndpoint.getEthernetAddress())
46 , m_destAddress(remoteEndpoint)
47 , m_interfaceName(localEndpoint.getName())
48 , m_hasRecentlyReceived(false)
58 NDN_THROW_NESTED(
Error(e.what()));
62 handleNetifStateChange(localEndpoint.getState());
64 m_netifStateChangedConn = localEndpoint.onStateChanged.connect(
65 [
this] (ndn::net::InterfaceState, ndn::net::InterfaceState newState) {
66 handleNetifStateChange(newState);
69 m_netifMtuChangedConn = localEndpoint.onMtuChanged.connect(
70 [
this] (uint32_t, uint32_t mtu) {
85 boost::system::error_code error;
99 EthernetTransport::handleNetifStateChange(ndn::net::InterfaceState netifState)
102 if (netifState == ndn::net::InterfaceState::RUNNING) {
113 EthernetTransport::doSend(
const Block& packet)
121 EthernetTransport::sendPacket(
const ndn::Block& block)
123 ndn::EncodingBuffer buffer(block);
126 if (block.size() < ethernet::MIN_DATA_LEN) {
127 static const uint8_t padding[ethernet::MIN_DATA_LEN] = {};
128 buffer.appendBytes(ndn::make_span(padding).subspan(block.size()));
132 uint16_t ethertype = boost::endian::native_to_big(ethernet::ETHERTYPE_NDN);
133 buffer.prependBytes({
reinterpret_cast<const uint8_t*
>(ðertype), ethernet::TYPE_LEN});
138 int sent = pcap_inject(
m_pcap, buffer.data(), buffer.size());
141 else if (
static_cast<size_t>(sent) < buffer.size())
142 handleError(
"Failed to send the full frame: size=" + to_string(buffer.size()) +
143 " sent=" + to_string(sent));
150 EthernetTransport::asyncRead()
152 m_socket.async_read_some(boost::asio::null_buffers(),
153 [
this] (
const auto& e,
auto) { this->handleRead(e); });
157 EthernetTransport::handleRead(
const boost::system::error_code& error)
162 if (error != boost::asio::error::operation_aborted &&
166 handleError(
"Receive operation failed: " + error.message());
171 span<const uint8_t> pkt;
179 const ether_header* eh;
186 ethernet::Address sender(eh->ether_shost);
187 pkt = pkt.subspan(ethernet::HDR_LEN);
194 if (nDropped - m_nDropped > 0)
196 m_nDropped = nDropped;
209 std::tie(isOk, element) = Block::fromBuffer(payload);
215 m_hasRecentlyReceived =
true;
217 static_assert(
sizeof(
EndpointId) >= ethernet::ADDR_LEN,
"EndpointId is too small");
220 std::memcpy(&endpoint, sender.data(), sender.size());
223 this->
receive(element, endpoint);
227 EthernetTransport::handleError(
const std::string& errorMessage)
void receivePayload(span< const uint8_t > payload, const ethernet::Address &sender)
Processes the payload of an incoming frame.
void doClose() final
performs Transport specific operations to close the transport
boost::asio::posix::stream_descriptor m_socket
ethernet::Address m_srcAddress
ethernet::Address m_destAddress
EthernetTransport(const ndn::net::NetworkInterface &localEndpoint, const ethernet::Address &remoteEndpoint)
int getFd() const
Obtain a file descriptor that can be used in calls such as select(2) and poll(2).
std::string getLastError() const noexcept
Get last error message.
void activate(int dlt)
Start capturing packets.
size_t getNDropped() const
Get the number of packets dropped by the kernel, as reported by libpcap.
std::tuple< span< const uint8_t >, std::string > readNextPacket() const noexcept
Read the next packet captured on the interface.
void close() noexcept
Stop capturing and close the handle.
TransportState getState() const
void setState(TransportState newState)
set transport state
void receive(const Block &packet, const EndpointId &endpoint=0)
Pass a received link-layer packet to the upper layer for further processing.
ndn::nfd::FacePersistency getPersistency() const
#define NFD_LOG_FACE_ERROR(msg)
Log a message at ERROR level.
#define NFD_LOG_FACE_DEBUG(msg)
Log a message at DEBUG level.
#define NFD_LOG_FACE_WARN(msg)
Log a message at WARN level.
#define NFD_LOG_FACE_TRACE(msg)
Log a message at TRACE level.
#define NFD_LOG_INIT(name)
std::tuple< const ether_header *, std::string > checkFrameHeader(span< const uint8_t > packet, const Address &localAddr, const Address &destAddr)
uint64_t EndpointId
Identifies a remote endpoint on the link.
@ CLOSED
the transport is closed, and can be safely deallocated
@ CLOSING
the transport is being closed gracefully, either by the peer or by a call to close()
@ FAILED
the transport is being closed due to a failure
@ DOWN
the transport is temporarily down, and is being recovered
@ UP
the transport is up and can transmit packets
Copyright (c) 2014-2015, Regents of the University of California, Arizona Board of Regents,...
boost::asio::io_service & getGlobalIoService()
Returns the global io_service instance for the calling thread.