transport.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2014-2022, Regents of the University of California,
4  * Arizona Board of Regents,
5  * Colorado State University,
6  * University Pierre & Marie Curie, Sorbonne University,
7  * Washington University in St. Louis,
8  * Beijing Institute of Technology,
9  * The University of Memphis.
10  *
11  * This file is part of NFD (Named Data Networking Forwarding Daemon).
12  * See AUTHORS.md for complete list of NFD authors and contributors.
13  *
14  * NFD is free software: you can redistribute it and/or modify it under the terms
15  * of the GNU General Public License as published by the Free Software Foundation,
16  * either version 3 of the License, or (at your option) any later version.
17  *
18  * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20  * PURPOSE. See the GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License along with
23  * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
24  */
25 
26 #include "transport.hpp"
27 #include "face.hpp"
28 
29 namespace nfd::face {
30 
31 NFD_LOG_INIT(Transport);
32 
33 std::ostream&
34 operator<<(std::ostream& os, TransportState state)
35 {
36  switch (state) {
37  case TransportState::UP:
38  return os << "UP";
40  return os << "DOWN";
42  return os << "CLOSING";
44  return os << "FAILED";
46  return os << "CLOSED";
47  default:
48  return os << "NONE";
49  }
50 }
51 
52 Transport::Transport() = default;
53 
54 Transport::~Transport() = default;
55 
56 void
58 {
59  BOOST_ASSERT(m_face == nullptr);
60  BOOST_ASSERT(m_service == nullptr);
61 
62  m_face = &face;
63  m_service = &service;
64 }
65 
66 void
68 {
69  if (m_state != TransportState::UP && m_state != TransportState::DOWN) {
70  return;
71  }
72 
74  this->doClose();
75  // warning: don't access any members after this:
76  // the Transport may be deallocated if doClose changes state to CLOSED
77 }
78 
79 void
80 Transport::send(const Block& packet)
81 {
82  BOOST_ASSERT(packet.isValid());
83  BOOST_ASSERT(this->getMtu() == MTU_UNLIMITED ||
84  packet.size() <= static_cast<size_t>(this->getMtu()));
85 
86  TransportState state = this->getState();
87  if (state != TransportState::UP && state != TransportState::DOWN) {
88  NFD_LOG_FACE_TRACE("send ignored in " << state << " state");
89  return;
90  }
91 
92  if (state == TransportState::UP) {
93  ++this->nOutPackets;
94  this->nOutBytes += packet.size();
95  }
96 
97  this->doSend(packet);
98 }
99 
100 void
101 Transport::receive(const Block& packet, const EndpointId& endpoint)
102 {
103  BOOST_ASSERT(packet.isValid());
104  BOOST_ASSERT(this->getMtu() == MTU_UNLIMITED ||
105  packet.size() <= static_cast<size_t>(this->getMtu()));
106 
107  ++this->nInPackets;
108  this->nInBytes += packet.size();
109 
110  m_service->receivePacket(packet, endpoint);
111 }
112 
113 void
114 Transport::setMtu(ssize_t mtu) noexcept
115 {
116  BOOST_ASSERT(mtu == MTU_UNLIMITED || mtu >= 0);
117 
118  if (mtu == m_mtu) {
119  return;
120  }
121 
122  if (m_mtu != MTU_INVALID) {
123  NFD_LOG_FACE_INFO("setMtu " << m_mtu << " -> " << mtu);
124  }
125 
126  m_mtu = mtu;
127 }
128 
129 bool
130 Transport::canChangePersistencyTo(ndn::nfd::FacePersistency newPersistency) const
131 {
132  // not changing, or setting initial persistency in subclass constructor
133  if (m_persistency == newPersistency || m_persistency == ndn::nfd::FACE_PERSISTENCY_NONE) {
134  return true;
135  }
136 
137  if (newPersistency == ndn::nfd::FACE_PERSISTENCY_NONE) {
138  NFD_LOG_FACE_TRACE("cannot change persistency to NONE");
139  return false;
140  }
141 
142  return this->canChangePersistencyToImpl(newPersistency);
143 }
144 
145 bool
146 Transport::canChangePersistencyToImpl(ndn::nfd::FacePersistency newPersistency) const
147 {
148  return false;
149 }
150 
151 void
152 Transport::setPersistency(ndn::nfd::FacePersistency newPersistency)
153 {
154  BOOST_ASSERT(canChangePersistencyTo(newPersistency));
155 
156  if (m_persistency == newPersistency) {
157  return;
158  }
159 
160  auto oldPersistency = m_persistency;
161  m_persistency = newPersistency;
162 
163  if (oldPersistency != ndn::nfd::FACE_PERSISTENCY_NONE) {
164  NFD_LOG_FACE_INFO("setPersistency " << oldPersistency << " -> " << newPersistency);
165  this->afterChangePersistency(oldPersistency);
166  }
167 }
168 
169 void
170 Transport::afterChangePersistency(ndn::nfd::FacePersistency oldPersistency)
171 {
172 }
173 
174 void
176 {
177  if (m_state == newState) {
178  return;
179  }
180 
181  bool isValid = false;
182  switch (m_state) {
183  case TransportState::UP:
184  isValid = newState == TransportState::DOWN ||
185  newState == TransportState::CLOSING ||
186  newState == TransportState::FAILED;
187  break;
189  isValid = newState == TransportState::UP ||
190  newState == TransportState::CLOSING ||
191  newState == TransportState::FAILED;
192  break;
195  isValid = newState == TransportState::CLOSED;
196  break;
197  default:
198  break;
199  }
200 
201  if (!isValid) {
202  NDN_THROW(std::runtime_error("Invalid state transition"));
203  }
204 
205  NFD_LOG_FACE_INFO("setState " << m_state << " -> " << newState);
206 
207  TransportState oldState = m_state;
208  m_state = newState;
209  afterStateChange(oldState, newState);
210  // warning: don't access any members after this:
211  // the Transport may be deallocated in the signal handler if newState is CLOSED
212 }
213 
214 std::ostream&
215 operator<<(std::ostream& os, const FaceLogHelper<Transport>& flh)
216 {
217  const Transport& transport = flh.obj;
218  const Face* face = transport.getFace();
219  FaceId faceId = face == nullptr ? INVALID_FACEID : face->getId();
220 
221  os << "[id=" << faceId << ",local=" << transport.getLocalUri()
222  << ",remote=" << transport.getRemoteUri() << "] ";
223  return os;
224 }
225 
226 } // namespace nfd::face
Generalization of a network interface.
Definition: face.hpp:118
FaceId getId() const noexcept
Returns the face ID.
Definition: face.hpp:195
For internal use by FaceLogging macros.
ByteCounter nInBytes
Total bytes received.
Definition: transport.hpp:85
PacketCounter nInPackets
Count of incoming packets.
Definition: transport.hpp:65
PacketCounter nOutPackets
Count of outgoing packets.
Definition: transport.hpp:74
ByteCounter nOutBytes
Total bytes sent.
Definition: transport.hpp:95
The lower half of a Face.
Definition: transport.hpp:123
void receive(const Block &packet, const EndpointId &endpoint={})
Pass a received link-layer packet to the upper layer for further processing.
Definition: transport.cpp:101
void setPersistency(ndn::nfd::FacePersistency newPersistency)
Changes the persistency setting of the transport.
Definition: transport.cpp:152
ssize_t getMtu() const noexcept
Returns the maximum payload size.
Definition: transport.hpp:279
FaceUri getLocalUri() const noexcept
Returns a FaceUri representing the local endpoint.
Definition: transport.hpp:209
virtual void afterChangePersistency(ndn::nfd::FacePersistency oldPersistency)
Invoked after the persistency has been changed.
Definition: transport.cpp:170
void setMtu(ssize_t mtu) noexcept
Definition: transport.cpp:114
void send(const Block &packet)
Send a link-layer packet.
Definition: transport.cpp:80
void setFaceAndLinkService(Face &face, LinkService &service) noexcept
Set Face and LinkService for this transport.
Definition: transport.cpp:57
signal::Signal< Transport, TransportState, TransportState > afterStateChange
Called when the transport state changes.
Definition: transport.hpp:308
const Face * getFace() const noexcept
Returns the Face to which this transport is attached.
Definition: transport.hpp:155
TransportState getState() const noexcept
Returns the current transport state.
Definition: transport.hpp:300
virtual void doClose()=0
Performs Transport specific operations to close the transport.
bool canChangePersistencyTo(ndn::nfd::FacePersistency newPersistency) const
Check whether the persistency can be changed to newPersistency.
Definition: transport.cpp:130
FaceUri getRemoteUri() const noexcept
Returns a FaceUri representing the remote endpoint.
Definition: transport.hpp:218
Transport()
Default constructor.
virtual bool canChangePersistencyToImpl(ndn::nfd::FacePersistency newPersistency) const
Invoked by canChangePersistencyTo to perform the check.
Definition: transport.cpp:146
void setState(TransportState newState)
Set transport state.
Definition: transport.cpp:175
void close()
Request the transport to be closed.
Definition: transport.cpp:67
#define NFD_LOG_FACE_INFO(msg)
Log a message at INFO level.
#define NFD_LOG_FACE_TRACE(msg)
Log a message at TRACE level.
#define NFD_LOG_INIT(name)
Definition: logger.hpp:31
std::ostream & operator<<(std::ostream &os, const FaceLogHelper< Face > &flh)
Definition: face.cpp:63
TransportState
Indicates the state of a transport.
Definition: transport.hpp:37
@ 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
constexpr FaceId INVALID_FACEID
Indicates an invalid FaceId.
Definition: face-common.hpp:51
constexpr ssize_t MTU_INVALID
(for internal use) Indicates that the MTU field is unset.
Definition: transport.hpp:106
std::variant< std::monostate, ethernet::Address, udp::Endpoint > EndpointId
Identifies a remote endpoint on the link.
Definition: face-common.hpp:78
constexpr ssize_t MTU_UNLIMITED
Indicates that the transport has no limit on payload size.
Definition: transport.hpp:101
uint64_t FaceId
Identifies a face.
Definition: face-common.hpp:48