Kea  2.1.7-git
receiver.cc
Go to the documentation of this file.
1 // Copyright (C) 2018-2021 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 
7 #include <config.h>
8 
9 #include <perfdhcp/receiver.h>
11 
12 #include <dhcp/iface_mgr.h>
13 
14 #include <functional>
15 
16 using namespace std;
17 using namespace isc::dhcp;
18 
19 namespace isc {
20 namespace perfdhcp {
21 
22 
23 void
24 Receiver::start() {
25  if (single_threaded_) {
26  return;
27  }
28  if (run_flag_.test_and_set()) {
29  run_flag_.clear();
30  isc_throw(isc::Unexpected, "run_flag_ should be false.");
31  }
32  recv_thread_.reset(new std::thread(std::bind(&Receiver::run, this)));
33 }
34 
35 void
36 Receiver::stop() {
37  if (single_threaded_) {
38  return;
39  }
40 
41  // If thread is running then...
42  if (run_flag_.test_and_set()) {
43  // Clear flags to order the thread to stop its main loop.
44  run_flag_.clear();
45  recv_thread_->join();
46  }
47 }
48 
49 Receiver::~Receiver() {
50  if (single_threaded_) {
51  return;
52  }
53  stop();
54 }
55 
56 
57 PktPtr
58 Receiver::getPkt() {
59  if (single_threaded_) {
60  // In single thread mode read packet directly from the socket and return it.
61  return readPktFromSocket();
62  } else {
63  // In multi thread mode read packet from the queue which is feed by Receiver thread.
64  std::lock_guard<std::mutex> lock(pkt_queue_mutex_);
65  if (pkt_queue_.empty()) {
66  if (ip_version_ == 4) {
67  return Pkt4Ptr();
68  } else {
69  return Pkt6Ptr();
70  }
71  }
72  auto pkt = pkt_queue_.front();
73  pkt_queue_.pop();
74  return pkt;
75  }
76 }
77 
78 void
79 Receiver::run() {
80  if (single_threaded_) {
81  isc_throw(isc::Unexpected, "run should not be invoked in single-thread mode.");
82  }
83  try {
84  // If the flag is still true receive packets.
85  while (run_flag_.test_and_set()) {
86  receivePackets();
87  }
88 
89  // Clear run flag so that subsequent call to stop will not try to stop again.
90  run_flag_.clear();
91  } catch (const exception& e) {
92  cerr << "Something went wrong: " << e.what() << endl;
93  usleep(1000);
94  } catch (...) {
95  cerr << "Something went wrong" << endl;
96  usleep(1000);
97  }
98 }
99 
100 PktPtr
101 Receiver::readPktFromSocket() {
102  PktPtr pkt;
103  uint32_t timeout;
104  if (single_threaded_) {
105  // In case of single thread just check socket and if empty exit immediately
106  // to not slow down sending part.
107  timeout = 0;
108  } else {
109  // In case of multi thread wait for packets a little bit (1ms) as it is run
110  // in separate thread and do not interfere with sending thread.
111  timeout = 1000;
112  }
113  try {
114  if (ip_version_ == 4) {
115  pkt = socket_.receive4(0, timeout);
116  } else {
117  pkt = socket_.receive6(0, timeout);
118  }
119  } catch (const Exception& e) {
120  cerr << "Failed to receive DHCP packet: " << e.what() << endl;
121  }
122 
123  return (pkt);
124 }
125 
126 void
127 Receiver::receivePackets() {
128  while (true) {
129  PktPtr pkt = readPktFromSocket();
130  if (!pkt) {
131  break;
132  }
133 
134  // Drop the packet if not supported. Do not bother main thread about it.
135  if (pkt->getType() == DHCPOFFER || pkt->getType() == DHCPACK ||
136  pkt->getType() == DHCPV6_ADVERTISE || pkt->getType() == DHCPV6_REPLY) {
137  // Otherwise push the packet to the queue, to main thread.
138  std::lock_guard<std::mutex> lock(pkt_queue_mutex_);
139  pkt_queue_.push(pkt);
140  }
141  }
142 }
143 
144 }
145 }
STL namespace.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
boost::shared_ptr< Pkt6 > Pkt6Ptr
A pointer to Pkt6 packet.
Definition: pkt6.h:28
A generic exception that is thrown when an unexpected error condition occurs.
boost::shared_ptr< Pkt4 > Pkt4Ptr
A pointer to Pkt4 object.
Definition: pkt4.h:544
boost::shared_ptr< isc::dhcp::Pkt > PktPtr
A pointer to either Pkt4 or Pkt6 packet.
Definition: pkt.h:797
This is a base class for exceptions thrown from the DNS library module.
Defines the logger used by the top-level component of kea-lfc.