Skip to content

Commit

Permalink
Add the ability to inflate an LLRP Probe Reply and build a Probe Request
Browse files Browse the repository at this point in the history
  • Loading branch information
peternewman committed Feb 18, 2020
1 parent ed113e1 commit 8db5131
Show file tree
Hide file tree
Showing 6 changed files with 383 additions and 1 deletion.
107 changes: 107 additions & 0 deletions libs/acn/LLRPProbeReplyInflator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* LLRPProbeReplyInflator.cpp
* The Inflator for the LLRP Probe Reply PDUs
* Copyright (C) 2020 Peter Newman
*/

#include <iostream>
#include <memory>
#include "ola/Logging.h"
#include "include/ola/rdm/UID.h"
#include "include/ola/rdm/UIDSet.h"
#include "include/ola/strings/Format.h"
#include "libs/acn/LLRPProbeReplyInflator.h"
#include "libs/acn/LLRPProbeReplyPDU.h"

namespace ola {
namespace acn {

using ola::acn::LLRPProbeReplyPDU;
using ola::rdm::UID;
using ola::rdm::UIDSet;

/**
* Create a new LLRP Probe Reply inflator
*/
LLRPProbeReplyInflator::LLRPProbeReplyInflator()
: BaseInflator(PDU::ONE_BYTE) {
}

/**
* Set an LLRPProbeReplyHandler to run when receiving an LLRP Probe Reply
* message.
* @param handler the callback to invoke when there is and LLRP Probe Reply.
*/
void LLRPProbeReplyInflator::SetLLRPProbeReplyHandler(
LLRPProbeReplyHandler *handler) {
m_llrp_probe_reply_handler.reset(handler);
}


/*
* Decode the LLRP Probe Reply 'header', which is 0 bytes in length.
* @param headers the HeaderSet to add to
* @param data a pointer to the data
* @param length length of the data
* @returns true if successful, false otherwise
*/
bool LLRPProbeReplyInflator::DecodeHeader(HeaderSet *,
const uint8_t*,
unsigned int,
unsigned int *bytes_used) {
*bytes_used = 0;
return true;
}


/*
* Handle a LLRP Probe Reply PDU for E1.33.
*/
bool LLRPProbeReplyInflator::HandlePDUData(uint32_t vector,
const HeaderSet &headers,
const uint8_t *data,
unsigned int pdu_len) {
if (vector != LLRPProbeReplyPDU::VECTOR_PROBE_REPLY_DATA) {
OLA_INFO << "Not a probe reply, vector was " << vector;
return true;
}

ola::strings::FormatData(&std::cout, data, pdu_len);

LLRPProbeReplyPDU::llrp_probe_reply_pdu_data pdu_data;
if (pdu_len > sizeof(pdu_data)) {
OLA_WARN << "Got too much data, received " << pdu_len << " only expecting "
<< sizeof(pdu_data);
return false;
}

memcpy(reinterpret_cast<uint8_t*>(&pdu_data), data, sizeof(pdu_data));

OLA_DEBUG << "Probe from " << UID(pdu_data.target_uid);

LLRPProbeReply reply(UID(pdu_data.target_uid));

if (m_llrp_probe_reply_handler.get()) {
m_llrp_probe_reply_handler->Run(&headers,
reply);
} else {
OLA_WARN << "No LLRP Probe Reply handler defined!";
}
return true;
}
} // namespace acn
} // namespace ola
79 changes: 79 additions & 0 deletions libs/acn/LLRPProbeReplyInflator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* LLRPProbeReplyInflator.h
* Copyright (C) 2020 Peter Newman
*/

#ifndef LIBS_ACN_LLRPPROBEREPLYINFLATOR_H_
#define LIBS_ACN_LLRPPROBEREPLYINFLATOR_H_

#include "ola/Callback.h"
#include "ola/acn/ACNVectors.h"
#include "ola/rdm/UID.h"
#include "ola/rdm/UIDSet.h"
#include "libs/acn/BaseInflator.h"
#include "libs/acn/HeaderSet.h"
#include "libs/acn/LLRPProbeReplyPDU.h"

namespace ola {
namespace acn {

class LLRPProbeReplyInflator: public BaseInflator {
friend class LLRPProbeReplyInflatorTest;

public:
struct LLRPProbeReply {
LLRPProbeReply(const ola::rdm::UID &_uid)
: uid(_uid) {
}
ola::rdm::UID uid;
ola::network::MACAddress hardware_address;
ola::acn::LLRPProbeReplyPDU::LLRPComponentType component_type;
};


// These are pointers so the callers don't have to pull in all the headers.
typedef ola::Callback2<void,
const HeaderSet*, // the HeaderSet
const LLRPProbeReply& // Probe Reply Data
> LLRPProbeReplyHandler;

LLRPProbeReplyInflator();
~LLRPProbeReplyInflator() {}

uint32_t Id() const { return ola::acn::VECTOR_LLRP_PROBE_REPLY; }

void SetLLRPProbeReplyHandler(LLRPProbeReplyHandler *handler);

protected:
bool DecodeHeader(HeaderSet *headers,
const uint8_t *data,
unsigned int len,
unsigned int *bytes_used);

void ResetHeaderField() {} // namespace noop

virtual bool HandlePDUData(uint32_t vector,
const HeaderSet &headers,
const uint8_t *data,
unsigned int pdu_len);

private:
std::auto_ptr<LLRPProbeReplyHandler> m_llrp_probe_reply_handler;
};
} // namespace acn
} // namespace ola
#endif // LIBS_ACN_LLRPPROBEREPLYINFLATOR_H_
50 changes: 50 additions & 0 deletions libs/acn/LLRPProbeRequestPDU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,56 @@ using ola::io::OutputStream;
using ola::network::HostToNetwork;
using ola::rdm::UID;

unsigned int LLRPProbeRequestPDU::DataSize() const {
llrp_probe_request_pdu_data data;
return static_cast<unsigned int>(sizeof(llrp_probe_request_pdu_data) -
sizeof(data.known_uids) +
(m_known_uids.Size() * UID::LENGTH));

}

bool LLRPProbeRequestPDU::PackData(uint8_t *data, unsigned int *length) const {
llrp_probe_request_pdu_data pdu_data;
m_lower_uid.Pack(pdu_data.lower_uid, sizeof(pdu_data.lower_uid));
m_upper_uid.Pack(pdu_data.upper_uid, sizeof(pdu_data.upper_uid));
uint16_t filter = 0;
if (m_client_tcp_connection_inactive) {
filter |= FILTER_CLIENT_TCP_CONNECTION_INACTIVE;
}
if (m_brokers_only) {
filter |= FILTER_BROKERS_ONLY;
}
pdu_data.filter = HostToNetwork(filter);
// TODO(Peter): We need to check we've got <= 200 UIDs here
m_known_uids.Pack(pdu_data.known_uids, sizeof(pdu_data.known_uids));
*length = static_cast<unsigned int>(sizeof(llrp_probe_request_pdu_data) -
sizeof(pdu_data.known_uids) +
(m_known_uids.Size() * UID::LENGTH));

memcpy(data, &pdu_data, *length);
return true;
}

void LLRPProbeRequestPDU::PackData(ola::io::OutputStream *stream) const {
llrp_probe_request_pdu_data data;
m_lower_uid.Pack(data.lower_uid, sizeof(data.lower_uid));
m_upper_uid.Pack(data.upper_uid, sizeof(data.upper_uid));
uint16_t filter = 0;
if (m_client_tcp_connection_inactive) {
filter |= FILTER_CLIENT_TCP_CONNECTION_INACTIVE;
}
if (m_brokers_only) {
filter |= FILTER_BROKERS_ONLY;
}
data.filter = HostToNetwork(filter);
// TODO(Peter): We need to check we've got <= 200 UIDs here
m_known_uids.Pack(data.known_uids, sizeof(data.known_uids));
stream->Write(reinterpret_cast<uint8_t*>(&data),
static_cast<unsigned int>(sizeof(llrp_probe_request_pdu_data) -
sizeof(data.known_uids) +
(m_known_uids.Size() * UID::LENGTH)));
}

void LLRPProbeRequestPDU::PrependPDU(ola::io::IOStack *stack,
const UID &lower_uid,
const UID &upper_uid,
Expand Down
34 changes: 33 additions & 1 deletion libs/acn/LLRPProbeRequestPDU.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,33 @@
namespace ola {
namespace acn {

class LLRPProbeRequestPDU : private PDU {
class LLRPProbeRequestPDU : public PDU {
public:
explicit LLRPProbeRequestPDU(unsigned int vector,
const ola::rdm::UID &lower_uid,
const ola::rdm::UID &upper_uid,
bool client_tcp_connection_inactive,
bool brokers_only,
const ola::rdm::UIDSet &known_uids):
PDU(vector, ONE_BYTE, true),
m_lower_uid(lower_uid),
m_upper_uid(upper_uid),
m_client_tcp_connection_inactive(client_tcp_connection_inactive),
m_brokers_only(brokers_only),
m_known_uids(known_uids) {}

unsigned int HeaderSize() const { return 0; }
bool PackHeader(OLA_UNUSED uint8_t *data,
unsigned int *length) const {
*length = 0;
return true;
}
void PackHeader(OLA_UNUSED ola::io::OutputStream *stream) const {}

unsigned int DataSize() const;
bool PackData(uint8_t *data, unsigned int *length) const;
void PackData(ola::io::OutputStream *stream) const;

static void PrependPDU(ola::io::IOStack *stack,
const ola::rdm::UID &lower_uid,
const ola::rdm::UID &upper_uid,
Expand All @@ -55,6 +80,13 @@ class LLRPProbeRequestPDU : private PDU {
uint8_t known_uids[ola::rdm::UID::LENGTH * LLRP_KNOWN_UID_SIZE];
});
typedef struct llrp_probe_request_pdu_data_s llrp_probe_request_pdu_data;

private:
const ola::rdm::UID m_lower_uid;
const ola::rdm::UID m_upper_uid;
bool m_client_tcp_connection_inactive;
bool m_brokers_only;
const ola::rdm::UIDSet m_known_uids;
};
} // namespace acn
} // namespace ola
Expand Down
Loading

0 comments on commit 8db5131

Please sign in to comment.