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 #ifndef PERFDHCP_RECEIVER_H
8 #define PERFDHCP_RECEIVER_H
9 
10 #include <perfdhcp/perf_socket.h>
11 #include <perfdhcp/command_options.h>
12 
13 #include <dhcp/pkt.h>
14 
15 #include <queue>
16 #include <thread>
17 #include <mutex>
18 #include <atomic>
19 
20 namespace isc {
21 namespace perfdhcp {
22 
23 /// \brief A receiving DHCP packets class.
24 ///
25 /// Receiver can be used in two modes: single-thread and multi-thread.
26 ///
27 /// In single-thread mode the class directly reads packets from socket
28 /// and returns them to consumer using getPkt method.
29 ///
30 /// In case of multi-thread mode the class starts a thread in the background.
31 /// The thread reads the packets and pushes them to pkt_queue_. Then
32 /// in main thread packets can be consumed from the queue using getPkt
33 /// method.
34 class Receiver {
35 private:
36     /// \brief Flag indicating if thread should run (true) or not (false).
37     std::atomic_flag run_flag_;
38 
39     /// \brief Thread for receiving packets.
40     std::unique_ptr<std::thread> recv_thread_;
41 
42     /// \brief Queue for passing packets from receiver thread to main thread.
43     std::queue<dhcp::PktPtr> pkt_queue_;
44 
45     /// \brief Mutex for controlling access to the queue.
46     std::mutex pkt_queue_mutex_;
47 
48     BasePerfSocket &socket_;
49 
50     /// \brief Single- or thread-mode indicator.
51     bool single_threaded_;
52 
53     uint8_t ip_version_;
54 
55 public:
56     /// \brief Receiver constructor.
57     ///
58     /// \param socket A socket for receiving packets.
59     /// \param single_threaded A flag indicating running mode.
60     /// \param ip_version An IP version: 4 or 6
Receiver(BasePerfSocket & socket,bool single_threaded,uint8_t ip_version)61     Receiver(BasePerfSocket &socket, bool single_threaded, uint8_t ip_version) :
62         socket_(socket),
63         single_threaded_(single_threaded),
64         ip_version_(ip_version) {
65         run_flag_.clear();
66     }
67 
68     /// \brief Destructor.
69     ~Receiver();
70 
71     /// \brief Start a receiving thread in multi-thread mode.
72     ///
73     /// In single-thread mode it does nothing.
74     void start();
75 
76     /// \brief Stop a receiving thread in multi-thread mode.
77     ///
78     /// In single-thread mode it does nothing.
79     void stop();
80 
81     /// \brief Get DHCP packet.
82     ///
83     /// In single-thread mode it reads directly from the socket.
84     /// In multi-thread mode it reads packets from the queue.
85     dhcp::PktPtr getPkt();
86 
87 private:
88     /// \brief Receiving thread main function.
89     void run();
90 
91     /// \brief Receive packets from sockets and pushes them to the queue.
92     ///
93     /// It runs in a loop until socket is empty.
94     void receivePackets();
95 
96     /// \brief Read a packet directly from the socket.
97     dhcp::PktPtr readPktFromSocket();
98 };
99 
100 }
101 }
102 
103 #endif /* PERFDHCP_RECEIVER_H */
104