mavtables  0.2.1
MAVLink router and firewall.
ConnectionFactory.hpp
Go to the documentation of this file.
1 // MAVLink router and firewall.
2 // Copyright (C) 2018 Michael R. Shannon <mrshannon.aerospace@gmail.com>
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 
17 
18 #ifndef CONNECTIONFACTORY_HPP_
19 #define CONNECTIONFACTORY_HPP_
20 
21 
22 #include <chrono>
23 #include <memory>
24 #include <string>
25 
26 #include "config.hpp"
27 #include "Connection.hpp"
28 #include "semaphore.hpp"
29 
30 
31 /** A factory for making related connections that use a common semaphore.
32  */
33 template <class C = Connection,
34  class AP = AddressPool<>,
35  class PQ = PacketQueue>
37 {
38  public:
39  ConnectionFactory(std::shared_ptr<Filter> filter, bool mirror = false);
40  TEST_VIRTUAL ~ConnectionFactory() = default;
41  TEST_VIRTUAL std::unique_ptr<C> get(std::string name = "unknown");
42  TEST_VIRTUAL bool wait_for_packet(
43  const std::chrono::nanoseconds &timeout);
44 
45  private:
46  std::shared_ptr<Filter> filter_;
47  bool mirror_;
48  semaphore semaphore_;
49 };
50 
51 
52 /** Construct a connection factory.
53  *
54  * \tparam C The Connection class (or derived class) to use.
55  * \tparam AP The AddressPool class (or derived class) to use.
56  * \tparam PQ The PacketQueue class (or derived class) to use, must accept a
57  * callback function in it's constructor.
58  * \param filter The packet filter to use for determining whether and with what
59  * priority to add a packet to the queue for transmission. This will be
60  * given to each constructed \ref Connection. Cannot be nullptr.
61  * \param mirror Set to true if all \ref Connection's made by this factory are
62  * to be mirror connections. A mirror connection is one that will receive
63  * all packets, regardless of destination address. The default is false.
64  * \throws std::invalid_argument if the given \p filter pointer is null.
65  */
66 template <class C, class AP, class PQ>
68  std::shared_ptr<Filter> filter, bool mirror)
69  : filter_(std::move(filter)), mirror_(mirror)
70 {
71  if (filter_ == nullptr)
72  {
73  throw std::invalid_argument("Given filter pointer is null.");
74  }
75 }
76 
77 
78 /** Construct and return a new connection.
79  *
80  * This connection will share a common semaphore with all other connections
81  * made by this factory instance.
82  *
83  * \param name The name of the new connection.
84  * \returns The new connection.
85  */
86 template <class C, class AP, class PQ>
87 std::unique_ptr<C> ConnectionFactory<C, AP, PQ>::get(std::string name)
88 {
89  return std::make_unique<C>(
90  name, filter_, mirror_,
91  std::make_unique<AP>(),
92  std::make_unique<PQ>([this]()
93  {
94  semaphore_.notify();
95  }));
96 }
97 
98 
99 /** Wait for a packet to be available on any connection made by this factory.
100  *
101  * \param timeout How long to block waiting for a packet. Set to 0s for non
102  * blocking.
103  * \retval true There is a packet on at lest one of the connections created by
104  * this factory instance.
105  * \retval false The wait timed out, there is no packet available on any of the
106  * connections created by this factory instance.
107  */
108 template <class C, class AP, class PQ>
110  const std::chrono::nanoseconds &timeout)
111 {
112  return semaphore_.wait_for(timeout);
113 }
114 
115 
116 #endif // CONNECTIONFACTORY_HPP_
TEST_VIRTUAL std::unique_ptr< C > get(std::string name="unknown")
STL namespace.
TEST_VIRTUAL ~ConnectionFactory()=default
ConnectionFactory(std::shared_ptr< Filter > filter, bool mirror=false)
TEST_VIRTUAL bool wait_for_packet(const std::chrono::nanoseconds &timeout)