Leosac  0.7.0
OpenSourceAccessControl
DoormanInstance.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014-2016 Leosac
3 
4  This file is part of Leosac.
5 
6  Leosac is free software: you can redistribute it and/or modify
7  it under the terms of the GNU Affero General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  Leosac is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU Affero General Public License for more details.
15 
16  You should have received a copy of the GNU Affero General Public License
17  along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include "DoormanInstance.hpp"
21 #include "DoormanModule.hpp"
22 #include "core/auth/Auth.hpp"
23 #include "tools/log.hpp"
24 
25 using namespace Leosac::Module::Doorman;
26 
27 DoormanInstance::DoormanInstance(DoormanModule &module, zmqpp::context &ctx,
28  std::string const &name,
29  const std::vector<std::string> &auth_contexts,
30  const std::vector<DoormanAction> &actions)
31  : module_(module)
32  , name_(name)
33  , actions_(actions)
34  , bus_sub_(ctx, zmqpp::socket_type::sub)
35 {
36  bus_sub_.connect("inproc://zmq-bus-pub");
37  for (auto &endpoint : auth_contexts)
38  bus_sub_.subscribe("S_" + endpoint);
39 
40  for (auto &action : actions_)
41  {
42  if (targets_.count(action.target_))
43  continue; // already have a socket to this target.
44 
45  // create socket (and connect them) to target
46  zmqpp::socket target_socket(ctx, zmqpp::socket_type::req);
47  target_socket.connect("inproc://" + action.target_);
48  targets_.insert(std::make_pair(action.target_, std::move(target_socket)));
49  }
50 }
51 
52 zmqpp::socket &DoormanInstance::bus_sub()
53 {
54  return bus_sub_;
55 }
56 
58 {
59  zmqpp::message bus_msg;
60  std::string auth_name; // name of the auth context that sent the message.
61  Leosac::Auth::AccessStatus access_status;
62 
63  bus_sub_.receive(bus_msg);
64  assert(bus_msg.parts() >= 2);
65  bus_msg >> auth_name >> access_status;
66  DEBUG("DOORMAN HERE");
67 
68  for (auto &action : actions_)
69  {
70  if (ignore_action(action, access_status))
71  continue;
72  DEBUG("ACTION (target = " << action.target_ << ")");
73 
74  zmqpp::message msg;
75  for (auto &frame : action.cmd_)
76  {
77  // we try to convert argument to int. if it works we send as int64_t,
78  // otherwise as string
79  bool err = false;
80  int v = 0;
81  try
82  {
83  v = std::stoi(frame);
84  }
85  catch (...)
86  {
87  err = true;
88  }
89  if (err)
90  msg << frame;
91  else
92  msg << static_cast<int64_t>(v);
93  DEBUG("would do : " << frame << " to target: " << action.target_);
94  }
95  command_send_recv(action.target_, std::move(msg));
96  }
97 }
98 
99 void DoormanInstance::command_send_recv(std::string const &target_name,
100  zmqpp::message msg)
101 {
102  zmqpp::socket &target_socket = targets_.at(target_name);
103  zmqpp::message response;
104 
105  target_socket.send(msg);
106  target_socket.receive(response);
107 
108  std::string req_status;
109  response >> req_status;
110 
111  if (req_status != "OK")
112  {
113  WARN("Command failed :(");
114  }
115 }
116 
118 DoormanInstance::find_target(const std::string &name) const
119 {
120  for (const auto &d : module_.doors())
121  {
122  if (d->gpio()->name() == name)
123  return d;
124  }
125  return nullptr;
126 }
127 
129  Leosac::Auth::AccessStatus status) const
130 {
131  if (action.on_ != status)
132  return true;
133 
134  auto target = find_target(action.target_);
135  if (target && (target->is_always_closed(std::chrono::system_clock::now()) ||
136  target->is_always_open(std::chrono::system_clock::now())))
137  {
138  NOTICE("Door " << target->name() << " is in immutable state (always open, "
139  "or always closed) so we ignore this "
140  "action against it");
141  return true;
142  }
143  return false;
144 }
std::shared_ptr< AuthTarget > AuthTargetPtr
Definition: AuthFwd.hpp:93
bool ignore_action(const DoormanAction &action, Auth::AccessStatus status) const
Should we ignore this action.
void command_send_recv(const std::string &target_name, zmqpp::message msg)
Send a command to a target and wait for response.
std::map< std::string, zmqpp::socket > targets_
Socket (REP) connected to each target this doorman may have.
Definition: log.hpp:36
Helper struct to wrap an "action".
DoormanInstance(DoormanModule &module, zmqpp::context &ctx, const std::string &name, const std::vector< std::string > &auth_contexts, const std::vector< DoormanAction > &actions)
Create a new doorman.
Definition: log.hpp:35
Auth::AuthTargetPtr find_target(const std::string &name) const
std::vector< DoormanAction > actions_
const std::vector< Auth::AuthTargetPtr > & doors() const
void handle_bus_msg()
Activity we care about happened on the bus.
Leosac::Auth::AccessStatus on_
When should this action be done? on GRANTED or DENIED ?
Definition: log.hpp:38
std::string target_
Target component.
Module that allows user to configure action to be taken to react to messages from other modules...
Main class for the module, it create handlers and run them to, well, handle events and send command...