26 #include <boost/archive/binary_iarchive.hpp> 27 #include <boost/archive/binary_oarchive.hpp> 28 #include <boost/property_tree/ptree_serialization.hpp> 29 #include <netinet/in.h> 34 const boost::property_tree::ptree &cfg,
38 , server_(ctx,
zmqpp::socket_type::stream)
39 , bus_sub_(ctx,
zmqpp::socket_type::sub)
40 , core_(ctx,
zmqpp::socket_type::req)
44 core_.connect(
"inproc://leosac-kernel");
46 bus_sub_.connect(
"inproc://zmq-bus-pub");
58 boost::property_tree::ptree module_config =
config_.get_child(
"module_config");
60 uint16_t port = module_config.get<uint16_t>(
"port", 4242);
61 std::string reader_name = module_config.get_child(
"reader").data();
62 stream_mode_ = module_config.get<
bool>(
"stream_mode",
true);
64 INFO(
"Rpleth module will bind to " 65 << port <<
" and will control the device nammed " << reader_name
67 reader_ = std::unique_ptr<Hardware::FWiegandReader>(
69 server_.bind(
"tcp://*:" + std::to_string(port));
79 msg >> identity >> content;
81 if (content.size() == 0)
87 INFO(
"client disconnected");
96 INFO(
"Client connected");
104 clients_[identity].write(reinterpret_cast<const uint8_t *>(content.c_str()),
117 std::array<uint8_t, buffer_size> buffer;
122 if (response.
command == RplethProtocol::HIDCommands::Greenled ||
123 response.
command == RplethProtocol::HIDCommands::Beep)
129 msg << client_identity;
130 msg.add_raw(&buffer[0], size);
151 else if (response.
type == RplethProtocol::TypeCode::HID &&
152 response.
command == RplethProtocol::HIDCommands::Greenled)
154 else if (response.
type == RplethProtocol::TypeCode::HID &&
155 response.
command == RplethProtocol::HIDCommands::Beep)
157 else if (response.
type == RplethProtocol::TypeCode::HID &&
158 response.
command == RplethProtocol::HIDCommands::SendCards)
160 else if (response.
type == RplethProtocol::TypeCode::HID &&
161 response.
command == RplethProtocol::HIDCommands::ReceiveCardsWaited)
163 else if (response.
type == RplethProtocol::TypeCode::Rpleth &&
164 response.
command == RplethProtocol::RplethCommands::DHCPState)
166 else if (response.
type == RplethProtocol::TypeCode::Rpleth &&
167 response.
command == RplethProtocol::RplethCommands::SetDHCP)
169 else if (response.
type == RplethProtocol::TypeCode::Rpleth &&
170 response.
command == RplethProtocol::RplethCommands::SetIP)
172 else if (response.
type == RplethProtocol::TypeCode::Rpleth &&
173 response.
command == RplethProtocol::RplethCommands::SetSubnet)
175 else if (response.
type == RplethProtocol::TypeCode::Rpleth &&
176 response.
command == RplethProtocol::RplethCommands::SetGateway)
178 else if (response.
type == RplethProtocol::TypeCode::Rpleth &&
179 response.
command == RplethProtocol::RplethCommands::Reset)
183 WARN(
"Unhandled packet.");
188 catch (std::exception &e)
190 ERROR(
"Exception while handling rpleth packet: " << e.what());
207 msg >> card_id >> nb_bit_read;
209 DEBUG(
"Rpleth module registered card with id " 210 << card_id <<
" and " << nb_bit_read <<
" significants bits");
215 card_id.erase(std::remove(card_id.begin(), card_id.end(),
':'), card_id.end());
227 auto itr_start = packet.
data.begin();
228 std::vector<Byte>::const_iterator my_start = itr_start;
229 std::vector<Byte>::const_iterator it;
231 WARN(
"Should not be here");
235 while (my_start != packet.
data.end())
237 it = std::find(itr_start, packet.
data.end(),
'|');
239 while (my_start != packet.
data.end() && my_start != it)
245 if (my_start == packet.
data.end())
256 std::list<std::string> to_send;
258 WARN(
"Should not be here");
259 DEBUG(
"Packet size = " << packet.
data.size());
260 if (packet.
data.size() != 1)
262 WARN(
"Invalid Packet");
265 if (packet.
data[0] == 0x01)
267 DEBUG(
"Present list");
273 DEBUG(
"Absent list");
276 auto lambda = [
this](
const std::string &str) ->
bool {
283 to_send.erase(std::remove_if(to_send.begin(), to_send.end(), lambda),
288 std::vector<Byte> data;
289 data.reserve(to_send.size() * 8);
290 for (
auto &card : to_send)
293 card.erase(std::remove(card.begin(), card.end(),
':'), card.end());
294 data.insert(data.end(), card.begin(), card.end());
297 response.
data = data;
298 response.
dataLen = data.size();
304 if (packet.
data.size() > 0)
306 if (packet.
data[0] == 0x01)
308 else if (packet.
data[0] == 0x00)
311 WARN(
"Malformed (Rpleth Beep) packet. Data byte is invalid");
314 WARN(
"Malformed (Rpleth Beep) packet. Not enough data");
319 if (packet.
data.size() > 0)
321 if (packet.
data[0] == 0x01)
323 else if (packet.
data[0] == 0x00)
326 WARN(
"Malformed (Rpleth GreenLed) packet. Data byte is invalid");
329 WARN(
"Malformed (Rpleth GreenLed) packet. Not enough data");
359 std::array<uint8_t, 64> buf;
362 msg.add_raw(&buf, size);
367 cards_read_stream_.clear();
370 static uint64_t htonll(uint64_t value)
373 if (*(
char *)&num == 42)
375 uint32_t high_part = htonl((uint32_t)(value >> 32));
376 uint32_t low_part = htonl((uint32_t)(value & 0xFFFFFFFFLL));
377 return (((uint64_t)low_part) << 32) | high_part;
391 std::vector<uint8_t> ret;
397 ret.resize(
sizeof(num));
398 std::memcpy(&ret[0], &num,
sizeof(num));
407 response.
type = RplethProtocol::TypeCode::Rpleth;
408 response.
command = RplethProtocol::RplethCommands::DHCPState;
411 if (network_cfg.get<
bool>(
"enabled"))
414 response.
data = network_cfg.get<
bool>(
"dhcp")
415 ? std::vector<uint8_t>({1})
416 : std::vector<uint8_t>({0});
424 catch (
const std::exception &e)
426 ERROR(
"Exception while getting DHCP state: " << e.what());
437 response.
type = RplethProtocol::TypeCode::Rpleth;
438 response.
command = RplethProtocol::RplethCommands::SetDHCP;
441 ERROR(
"Invalid Rpleth Packet");
442 else if (network_cfg.get<
bool>(
"enabled"))
444 network_cfg.erase(
"dhcp");
445 network_cfg.put(
"dhcp", p.
data[0] ?
true :
false);
449 WARN(
"Failed to update network config.");
452 NOTICE(
"Network not managed by Leosac, doing nothing.");
462 response.
type = RplethProtocol::TypeCode::Rpleth;
463 response.
command = RplethProtocol::RplethCommands::SetIP;
466 ERROR(
"Invalid Rpleth Packet");
467 else if (network_cfg.get<
bool>(
"enabled"))
469 std::ostringstream oss;
470 for (
unsigned char i = 0; i < 4; ++i)
472 oss << std::to_string(p.
data[i]);
476 INFO(
"new ip = {" << oss.str() <<
"}");
477 network_cfg.erase(
"default_ip");
478 network_cfg.put(
"default_ip", oss.str());
482 WARN(
"Failed to update network config.");
485 NOTICE(
"Network not managed by Leosac, doing nothing.");
495 response.
type = RplethProtocol::TypeCode::Rpleth;
496 response.
command = RplethProtocol::RplethCommands::SetSubnet;
499 ERROR(
"Invalid Rpleth Packet");
500 else if (network_cfg.get<
bool>(
"enabled"))
502 std::ostringstream oss;
503 for (
unsigned char i = 0; i < 4; ++i)
505 oss << std::to_string(p.
data[i]);
509 network_cfg.erase(
"netmask");
510 network_cfg.put(
"netmask", oss.str());
514 WARN(
"Failed to update network config.");
517 NOTICE(
"Network not managed by Leosac, doing nothing.");
527 response.
type = RplethProtocol::TypeCode::Rpleth;
528 response.
command = RplethProtocol::RplethCommands::SetGateway;
531 ERROR(
"Invalid Rpleth Packet");
532 else if (network_cfg.get<
bool>(
"enabled"))
534 std::ostringstream oss;
535 for (
unsigned char i = 0; i < 4; ++i)
537 oss << std::to_string(p.
data[i]);
541 network_cfg.erase(
"gateway");
542 network_cfg.put(
"gateway", oss.str());
546 WARN(
"Failed to update network config.");
549 NOTICE(
"Network not managed by Leosac, doing nothing.");
555 std::ostringstream oss;
556 boost::archive::binary_oarchive archive(oss);
557 boost::property_tree::save(archive, tree, 1);
558 core_.send(zmqpp::message() <<
"SET_NETCONFIG" << oss.str());
562 return ret ==
"OK" ? true :
false;
567 boost::property_tree::ptree network_config;
570 core_.send(
"GET_NETCONFIG");
572 zmqpp::message response;
573 core_.receive(response);
574 assert(response.parts() == 1);
577 std::istringstream iss(data);
578 boost::archive::binary_iarchive archive(iss);
579 boost::property_tree::load(archive, network_config, 1);
581 return network_config;
587 core_.send(
"RESTART");
RplethPacket rpleth_receive_cards(const RplethPacket &packet)
Handle Rpleth ReceiveUnpresentedCards command.
boost::property_tree::ptree get_network_config()
Retrieve the network configuration from the core.
Facade object for a Wiegand Reader device.
RplethPacket get_dhcp_state()
Handle Rpleth GetDHCP command.
RplethPacket set_reader_ip(const RplethPacket &p)
Update the IP of this Leosac unit.
static RplethPacket decodeCommand(CircularBuffer &buffer, bool from_server=false)
Decode a packet from a circular buffer object.
void rpleth_publish_card()
Flush the cards_read_stream_ list to clients.
This define message formatting for data source SIMPLE_WIEGAND.
Rpleth protocol implementation.
void handle_socket()
Handle data available on server socket.
RplethPacket set_reader_gw(const RplethPacket &p)
Update the reader gateway.
virtual int nb_bits() const override
bool handle_client_msg(const std::string &client_identity, CircularBuffer &buf)
Try to handle a client message.
std::map< std::string, CircularBuffer > clients_
void rpleth_send_cards(const RplethPacket &packet)
Handle Rpleth SendCards command: we will store the list of received card somewhere safe...
zmqpp::socket core_
REQ socket to core.
Namespace where implementation for Rpleth support takes place.
std::list< std::string > cards_pushed_
List of cards pushed by SendCards Rpleth command.
Implementation of a ring buffer.
RplethPacket set_dhcp_state(const RplethPacket &p)
Enable or disable DHCP.
static std::vector< uint8_t > card_convert_from_text(const std::pair< std::string, int > &card_info)
Convert a card number from textual hexadecimal representation to a 8 bytes byte-vector in Network Byt...
RplethPacket handle_client_packet(RplethPacket packet)
If we successfully built a packet, lets handle it.
static constexpr int buffer_size
static std::size_t encodeCommand(const RplethPacket &packet, Byte *buffer, std::size_t size)
zmqpp::socket bus_sub_
Subscribe to the message bus and listen for event sent by the wiegand reader we watch.
std::list< std::pair< std::string, int > > cards_read_stream_
If stream mode is on, all cards read are stored here.
std::vector< std::string > failed_clients_
Client that are "failed".
Base class for module implementation.
RplethModule(zmqpp::context &ctx, zmqpp::socket *pipe, const boost::property_tree::ptree &cfg, CoreUtilsPtr utils)
void rpleth_beep(const RplethPacket &p)
Handle Rpleth Beep command.
bool client_failed(const std::string &identity) const
Is the client in an invalid state ?
std::size_t toRead() const
virtual uint64_t to_raw_int() const override
Convert the bits of the card to an integer.
zmqpp::reactor reactor_
The reactor object we poll() on in the main loop.
zmqpp::socket server_
Stream socket to receive Rpleth connection.
bool client_connected(const std::string &identity) const
Do we already know this client ?
std::shared_ptr< CoreUtils > CoreUtilsPtr
std::list< std::string > cards_read_
Valid cards our Wiegand reader read: cards that were not pushed are not stored here.
RplethPacket set_reader_netmask(const RplethPacket &p)
Update netmask of this Leosac unit.
boost::property_tree::ptree config_
The configuration tree passed to the start_module function.
std::unique_ptr< Hardware::FWiegandReader > reader_
Interface to the reader.
virtual const std::string & card_id() const override
void handle_wiegand_event()
We received a message (on the BUS, from the wiegand reader we watch), that means a card was inserted...
void rpleth_greenled(const RplethPacket &p)
Handle rpleth greenled command.
bool push_network_config(const boost::property_tree::ptree &tree)
Push a configuration to the core as the new network config.