15 #ifndef VISIONTRANSFER_DATACHANNEL_CONTROL_H
16 #define VISIONTRANSFER_DATACHANNEL_CONTROL_H
24 #include <visiontransfer/datachannelservicebase.h>
26 namespace visiontransfer {
32 class DataChannelControlCommands {
36 CTLRequestAdvertisement,
37 CTLProvideAdvertisement,
38 CTLRequestSubscriptions,
39 CTLProvideSubscriptions,
40 CTLRequestUnsubscriptions,
41 CTLProvideUnsubscriptions
48 class DataChannelControlUtil {
50 static DataChannelControlCommands::Command getCommand(
unsigned char* data,
int datalen) {
51 if (datalen < 2)
throw std::runtime_error(
"Buffer too small");
52 return (DataChannelControlCommands::Command) ntohs(*((uint16_t*) data));
55 static int packAdvertisementMessage(
unsigned char* data,
int datalen, DataChannelControlCommands::Command cmd,
const std::map<DataChannel::ID, std::shared_ptr<DataChannel> >& channels) {
56 int origDataLen = datalen;
57 if (datalen < 3)
throw std::runtime_error(
"Buffer too small");
58 *((uint16_t*)data) = htons(cmd);
59 uint8_t num = (uint8_t) std::min(255, (
int) channels.size());
62 data += 3; datalen -= 3;
64 for (
auto kv: channels) {
65 i++;
if (i>num)
break;
66 if (datalen < 3)
throw std::runtime_error(
"Buffer too small");
68 const std::string& infoString = p->getInfoString();
69 uint8_t strSize = (uint8_t) std::min(255, (
int) infoString.size());
70 int elemLen = 1 + 1 + 1 + strSize;
71 if (datalen < elemLen)
throw std::runtime_error(
"Buffer too small");
72 data[0] = p->getChannelID();
73 data[1] = p->getChannelType();
75 std::memcpy(data + 3, infoString.c_str(), strSize);
76 data += elemLen; datalen -= elemLen;
78 return (origDataLen - datalen);
80 static std::vector<DataChannelInfo> unpackAdvertisementMessage(
unsigned char* data,
int datalen) {
81 std::vector<DataChannelInfo> result;
82 if (datalen < 3)
throw std::runtime_error(
"Buffer too small");
83 uint8_t num = data[2];
84 data += 3; datalen -= 3;
85 for (
int i=0; i<num; ++i) {
86 if (datalen < 3)
throw std::runtime_error(
"Buffer too small");
88 uint8_t type = data[1];
89 uint8_t strSize = data[2];
90 int elemLen = 1 + 1 + 1 + strSize;
91 if (datalen < elemLen)
throw std::runtime_error(
"Buffer too small");
92 result.emplace_back(DataChannelInfo((DataChannel::ID)
id, (DataChannel::Type) type, std::string(data[3], strSize)));
93 data += elemLen; datalen -= elemLen;
99 static int packSubscriptionMessage(
unsigned char* data,
int datalen, DataChannelControlCommands::Command cmd,
const std::vector<DataChannel::ID>& subscriptions) {
100 if (datalen < 4)
throw std::runtime_error(
"Buffer too small");
101 *((uint16_t*)data) = htons(cmd);
102 uint8_t num = (uint8_t) std::min(255, (
int) subscriptions.size());
104 data += 3; datalen -= 3;
105 if (datalen < (1*num))
throw std::runtime_error(
"Buffer too small");
106 for (
int i=0; i<num; ++i) {
107 auto p = subscriptions[i];
109 data += 1; datalen -= 1;
113 static std::vector<DataChannel::ID> unpackSubscriptionMessage(
unsigned char* data,
int datalen) {
114 std::vector<DataChannel::ID> result;
115 if (datalen < 3)
throw std::runtime_error(
"Buffer too small");
116 uint8_t num = data[2];
117 data += 3; datalen -= 3;
118 if (datalen < (1*num))
throw std::runtime_error(
"Buffer too small");
119 for (
int i=0; i<num; ++i) {
120 result.emplace_back(
static_cast<DataChannel::ID
>(data[0]));
121 data += 1; datalen -= 1;