• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

OpenLightingProject / ola / 10576413709

27 Aug 2024 10:31AM UTC coverage: 45.677% (-0.01%) from 45.687%
10576413709

push

github

web-flow
Merge pull request #1960 from peternewman/e1.33-cherry-pick

E1.33 cherry pick vii

7787 of 17922 branches covered (43.45%)

10 of 42 new or added lines in 9 files covered. (23.81%)

4 existing lines in 2 files now uncovered.

22243 of 48696 relevant lines covered (45.68%)

54.1 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/tools/e133/ManagementEndpoint.cpp
1
/*
2
 * This program is free software; you can redistribute it and/or modify
3
 * it under the terms of the GNU General Public License as published by
4
 * the Free Software Foundation; either version 2 of the License, or
5
 * (at your option) any later version.
6
 *
7
 * This program is distributed in the hope that it will be useful,
8
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 * GNU Library General Public License for more details.
11
 *
12
 * You should have received a copy of the GNU General Public License
13
 * along with this program; if not, write to the Free Software
14
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
15
 *
16
 * ManagementEndpoint.cpp
17
 * Copyright (C) 2012 Simon Newton
18
 */
19

20
#include <ola/Logging.h>
21
#include <ola/network/NetworkUtils.h>
22
#include <ola/rdm/RDMCommand.h>
23
#include <ola/rdm/RDMEnums.h>
24
#include <ola/rdm/RDMResponseCodes.h>
25
#include <ola/rdm/ResponderHelper.h>
26
#include <ola/rdm/UID.h>
27

28
#include <algorithm>
29
#include <memory>
30
#include <string>
31
#include <vector>
32

33
#include "tools/e133/E133Endpoint.h"
34
#include "tools/e133/EndpointManager.h"
35
#include "tools/e133/ManagementEndpoint.h"
36
#include "tools/e133/TCPConnectionStats.h"
37

38
using ola::network::HostToNetwork;
39
using ola::rdm::NR_ENDPOINT_NUMBER_INVALID;
40
using ola::rdm::NR_FORMAT_ERROR;
41
using ola::rdm::NR_UNKNOWN_PID;
42
using ola::rdm::RDMCallback;
43
using ola::rdm::RDMDiscoveryCallback;
44
using ola::rdm::RDMRequest;
45
using ola::rdm::RDMResponse;
46
using ola::rdm::ResponderHelper;
47
using ola::rdm::UID;
48
using ola::rdm::UIDSet;
49
using std::auto_ptr;
50
using std::vector;
51

52
ManagementEndpoint::RDMOps *ManagementEndpoint::RDMOps::instance = NULL;
53

54
const ola::rdm::ResponderOps<ManagementEndpoint>::ParamHandler
55
    ManagementEndpoint::PARAM_HANDLERS[] = {
56
  { ola::rdm::PID_ENDPOINT_LIST,
57
    &ManagementEndpoint::GetEndpointList,
58
    NULL},
59
  { ola::rdm::PID_ENDPOINT_LIST_CHANGE,
60
    &ManagementEndpoint::GetEndpointListChange,
61
    NULL},
62
  { ola::rdm::PID_IDENTIFY_ENDPOINT,
63
    &ManagementEndpoint::GetIdentifyEndpoint,
64
    &ManagementEndpoint::SetIdentifyEndpoint},
65
  { ola::rdm::PID_ENDPOINT_TO_UNIVERSE,
66
    &ManagementEndpoint::GetEndpointToUniverse,
67
    &ManagementEndpoint::SetEndpointToUniverse},
68
  // PID_RDM_TRAFFIC_ENABLE
69
  { ola::rdm::PID_ENDPOINT_MODE,
70
    &ManagementEndpoint::GetEndpointMode,
71
    &ManagementEndpoint::SetEndpointMode},
72
  { ola::rdm::PID_ENDPOINT_LABEL,
73
    &ManagementEndpoint::GetEndpointLabel,
74
    &ManagementEndpoint::SetEndpointLabel},
75
  // PID_DISCOVERY_STATE
76
  // PID_BACKGROUND_DISCOVERY
77
  // PID_ENDPOINT_TIMING
78
  // PID_ENDPOINT_TIMING_DESCRIPTION
79
  { ola::rdm::PID_ENDPOINT_RESPONDER_LIST_CHANGE,
80
    &ManagementEndpoint::GetEndpointResponderListChange,
81
    NULL},
82
  { ola::rdm::PID_ENDPOINT_RESPONDERS,
83
    &ManagementEndpoint::GetEndpointResponders,
84
    NULL},
85
  // PID_BINDING_AND_CONTROL_FIELDS
86
  { ola::rdm::PID_TCP_COMMS_STATUS,
87
    &ManagementEndpoint::GetTCPCommsStatus,
88
    &ManagementEndpoint::SetTCPCommsStatus},
89
  // PID_BACKGROUND_QUEUED_STATUS_POLICY
90
  // PID_BACKGROUND_QUEUED_STATUS_POLICY_DESCRIPTION
91
  // PID_BACKGROUND_STATUS_TYPE
92
  // PID_QUEUED_STATUS_ENDPOINT_COLLECTION
93
  // PID_QUEUED_STATUS_UID_COLLECTION
94
};
95

96
/**
97
 * Create a new ManagementEndpoint. Ownership of the arguments is not taken.
98
 * The endpoint needs to out-live the controller since the controller may be
99
 * passed callbacks that reference this endpoint.
100
 */
101
ManagementEndpoint::ManagementEndpoint(
×
102
    DiscoverableRDMControllerInterface *controller,
103
    const EndpointProperties &properties,
104
    const ola::rdm::UID &uid,
105
    const class EndpointManager *endpoint_manager,
106
    class TCPConnectionStats *tcp_stats)
×
107
    : E133Endpoint(controller, properties),
108
      m_uid(uid),
×
109
      m_endpoint_manager(endpoint_manager),
×
110
      m_tcp_stats(tcp_stats),
×
111
      m_controller(controller) {
×
112
}
×
113

114

115
/**
116
 * Handle a RDM request by either passing it through or handling it internally.
117
 * @param request the RDMRequest object
118
 * @param on_complete the callback to run when we've handled this request.
119
 */
120
void ManagementEndpoint::SendRDMRequest(RDMRequest *request,
×
121
                                        RDMCallback *on_complete) {
122
  const UID dst_uid = request->DestinationUID();
×
123
  if (dst_uid.IsBroadcast() && m_controller) {
×
124
    // This request needs to go to both the E1.33 responder and the other
125
    // responders.
126
    // TODO(simon): We need to use a broadcast tracker here like in
127
    // Universe.cpp
128
    /*
129
    */
130
  } else if (request->DestinationUID().DirectedToUID(m_uid)) {
×
131
    RDMOps::Instance()->HandleRDMRequest(
×
132
        this, m_uid, ola::rdm::ROOT_RDM_DEVICE, request, on_complete);
133
  } else if (m_controller) {
×
134
    // This request just goes to the other responders.
135
    m_controller->SendRDMRequest(request, on_complete);
×
136
  } else {
137
    ola::rdm::RunRDMCallback(on_complete, ola::rdm::RDM_UNKNOWN_UID);
×
138
    delete request;
×
139
  }
140
}
×
141

142

143
/**
144
 * Run full discovery.
145
 */
146
void ManagementEndpoint::RunFullDiscovery(RDMDiscoveryCallback *callback) {
×
147
  if (m_controller) {
×
148
    m_controller->RunFullDiscovery(
×
149
        NewSingleCallback(this, &ManagementEndpoint::DiscoveryComplete,
×
150
                          callback));
151
  } else {
152
    UIDSet uids;
×
153
    uids.AddUID(m_uid);
×
154
    callback->Run(uids);
×
155
  }
×
156
}
×
157

158

159
/**
160
 * Run incremental discovery.
161
 */
162
void ManagementEndpoint::RunIncrementalDiscovery(
×
163
    RDMDiscoveryCallback *callback) {
164
  if (m_controller) {
×
165
    m_controller->RunIncrementalDiscovery(
×
166
        NewSingleCallback(this, &ManagementEndpoint::DiscoveryComplete,
×
167
                          callback));
168
  } else {
169
    UIDSet uids;
×
170
    uids.AddUID(m_uid);
×
171
    callback->Run(uids);
×
172
  }
×
173
}
×
174

175

176
/**
177
 * Handle PID_ENDPOINT_LIST.
178
 */
179
RDMResponse *ManagementEndpoint::GetEndpointList(const RDMRequest *request) {
×
180
  if (request->ParamDataSize()) {
×
181
    return NackWithReason(request, NR_FORMAT_ERROR);
×
182
  }
183

184
  struct EndpointListParamData {
×
185
    uint32_t list_change;
186
    uint16_t endpoint_id[0];
187
  };
188

189
  vector<uint16_t> endpoints;
×
190
  m_endpoint_manager->EndpointIDs(&endpoints);
×
191
  unsigned int param_data_size = 4 + 2 * endpoints.size();
×
192
  uint8_t *raw_data = new uint8_t[param_data_size];
×
193
  EndpointListParamData *param_data = reinterpret_cast<EndpointListParamData*>(
×
194
      raw_data);
195

196
  param_data->list_change = HostToNetwork(
×
197
      m_endpoint_manager->list_change_number());
×
198
  for (unsigned int i = 0; i < endpoints.size(); i++) {
×
199
    param_data->endpoint_id[i] = HostToNetwork(endpoints[i]);
×
200
  }
201

202
  RDMResponse *response = GetResponseFromData(request, raw_data,
×
203
                                              param_data_size);
204
  delete[] raw_data;
×
205
  return response;
×
206
}
×
207

208

209
/**
210
 * Handle PID_ENDPOINT_LIST_CHANGE.
211
 */
212
RDMResponse *ManagementEndpoint::GetEndpointListChange(
×
213
    const RDMRequest *request) {
214
  if (request->ParamDataSize()) {
×
215
    return NackWithReason(request, NR_FORMAT_ERROR);
×
216
  }
217

218
  uint32_t change = HostToNetwork(m_endpoint_manager->list_change_number());
×
219
  return GetResponseFromData(
×
220
      request, reinterpret_cast<uint8_t*>(&change), sizeof(change));
221
}
222

223

224
/**
225
 * Handle PID_IDENTIFY_ENDPOINT
226
 */
NEW
227
RDMResponse *ManagementEndpoint::GetIdentifyEndpoint(
×
228
    const RDMRequest *request) {
229
  uint16_t endpoint_id;
×
230
  if (!ResponderHelper::ExtractUInt16(request, &endpoint_id)) {
×
231
    return NackWithReason(request, NR_FORMAT_ERROR);
×
232
  }
233

234
  E133Endpoint *endpoint = m_endpoint_manager->GetEndpoint(endpoint_id);
×
235

236
  // endpoint not found
237
  if (!endpoint) {
×
238
    return NackWithReason(request, ola::rdm::NR_ENDPOINT_NUMBER_INVALID);
×
239
  }
240

241
  PACK(
×
242
  struct IdentifyEndpointParamData {
243
    uint16_t endpoint_number;
244
    uint8_t identify_mode;
245
  });
NEW
246
  IdentifyEndpointParamData identify_endpoint_message = {
×
247
    HostToNetwork(endpoint_id), endpoint->identify_mode()
×
248
  };
×
249

250
  return GetResponseFromData(
×
251
      request,
252
      reinterpret_cast<uint8_t*>(&identify_endpoint_message),
253
      sizeof(identify_endpoint_message));
254
}
255

NEW
256
RDMResponse *ManagementEndpoint::SetIdentifyEndpoint(
×
257
    const RDMRequest *request) {
258
  PACK(
×
259
  struct IdentifyEndpointParamData {
260
    uint16_t endpoint_number;
261
    uint8_t identify_mode;
262
  });
NEW
263
  IdentifyEndpointParamData identify_endpoint_message;
×
264

NEW
265
  if (request->ParamDataSize() != sizeof(identify_endpoint_message)) {
×
266
    return NackWithReason(request, NR_FORMAT_ERROR);
×
267
  }
268

NEW
269
  memcpy(reinterpret_cast<uint8_t*>(&identify_endpoint_message),
×
270
         request->ParamData(),
×
271
         sizeof(identify_endpoint_message));
272

273
  E133Endpoint *endpoint = m_endpoint_manager->GetEndpoint(
×
NEW
274
    ola::network::NetworkToHost(identify_endpoint_message.endpoint_number));
×
275
  // endpoint not found
276
  if (!endpoint) {
×
277
    return NackWithReason(request, ola::rdm::NR_ENDPOINT_NUMBER_INVALID);
×
278
  }
279

NEW
280
  endpoint->set_identify_mode(identify_endpoint_message.identify_mode);
×
281
  return GetResponseFromData(request, NULL, 0);
×
282
}
283

284

285
/**
286
 * Handle PID_ENDPOINT_TO_UNIVERSE
287
 */
288
RDMResponse *ManagementEndpoint::GetEndpointToUniverse(
×
289
    const RDMRequest *request) {
290
  // TODO(simon): add me
291
  return NackWithReason(request, NR_UNKNOWN_PID);
×
292
}
293

294
RDMResponse *ManagementEndpoint::SetEndpointToUniverse(
×
295
    const RDMRequest *request) {
296
  // TODO(simon): add me
297
  return NackWithReason(request, NR_UNKNOWN_PID);
×
298
}
299

300
/**
301
 * Handle PID_ENDPOINT_MODE
302
 */
303
RDMResponse *ManagementEndpoint::GetEndpointMode(const RDMRequest *request) {
×
304
  // TODO(simon): add me
305
  return NackWithReason(request, NR_UNKNOWN_PID);
×
306
}
307

308
RDMResponse *ManagementEndpoint::SetEndpointMode(const RDMRequest *request) {
×
309
  // TODO(simon): add me
310
  return NackWithReason(request, NR_UNKNOWN_PID);
×
311
}
312

313
/**
314
 * Handle PID_ENDPOINT_LABEL
315
 */
316
RDMResponse *ManagementEndpoint::GetEndpointLabel(const RDMRequest *request) {
×
317
  // TODO(simon): add me
318
  return NackWithReason(request, NR_UNKNOWN_PID);
×
319
}
320

321
RDMResponse *ManagementEndpoint::SetEndpointLabel(const RDMRequest *request) {
×
322
  // TODO(simon): add me
323
  return NackWithReason(request, NR_UNKNOWN_PID);
×
324
}
325

326
/**
327
 * Handle PID_ENDPOINT_RESPONDER_LIST_CHANGE
328
 */
NEW
329
RDMResponse *ManagementEndpoint::GetEndpointResponderListChange(
×
330
    const RDMRequest *request) {
331
  uint16_t endpoint_id;
×
332
  if (!ResponderHelper::ExtractUInt16(request, &endpoint_id)) {
×
333
    return NackWithReason(request, NR_FORMAT_ERROR);
×
334
  }
335

336
  E133Endpoint *endpoint = m_endpoint_manager->GetEndpoint(endpoint_id);
×
337

338
  // endpoint not found
339
  if (!endpoint) {
×
340
    return NackWithReason(request, ola::rdm::NR_ENDPOINT_NUMBER_INVALID);
×
341
  }
342

NEW
343
  uint32_t list_change_id = HostToNetwork(endpoint->responder_list_change());
×
344
  return GetResponseFromData(
×
345
      request,
346
      reinterpret_cast<uint8_t*>(&list_change_id),
347
      sizeof(list_change_id));
348
}
349

350
/**
351
 * Handle PID_ENDPOINT_RESPONDERS
352
 */
NEW
353
RDMResponse *ManagementEndpoint::GetEndpointResponders(
×
354
    const RDMRequest *request) {
355
  uint16_t endpoint_id;
×
356
  if (!ResponderHelper::ExtractUInt16(request, &endpoint_id)) {
×
357
    return NackWithReason(request, NR_FORMAT_ERROR);
×
358
  }
359

360
  E133Endpoint *endpoint = NULL;
×
361
  if (endpoint_id)
×
362
    endpoint = m_endpoint_manager->GetEndpoint(endpoint_id);
×
363
  else
364
    endpoint = this;
×
365

366
  OLA_INFO << "Endpoint ID: " << endpoint_id << ", endpoint " << endpoint;
×
367
  // endpoint not found
368
  if (!endpoint) {
×
369
    return NackWithReason(request, ola::rdm::NR_ENDPOINT_NUMBER_INVALID);
×
370
  }
371

372
  UIDSet uids;
×
NEW
373
  uint32_t list_change_id = HostToNetwork(endpoint->responder_list_change());
×
NEW
374
  endpoint->EndpointResponders(&uids);
×
375

NEW
376
  struct ResponderListParamData {
×
377
    uint16_t endpoint;
378
    uint32_t list_change;
379
    uint8_t data[0];
380
  };
381

382
  // TODO(simon): fix this - we can overflow an RDM packet if there are too
383
  // many responders!
384
  unsigned int param_data_size = 2 + 4 + uids.Size() * UID::UID_SIZE;
×
385
  uint8_t *raw_data = new uint8_t[param_data_size];
×
NEW
386
  ResponderListParamData *param_data =
×
387
      reinterpret_cast<ResponderListParamData*>(raw_data);
388

389
  // TODO(simon): fix this to track changes.
390
  param_data->endpoint = HostToNetwork(endpoint_id);
×
391
  param_data->list_change = list_change_id;
×
392
  uint8_t *ptr = raw_data + 6;
×
393
  unsigned int offset = 0;
×
394
  UIDSet::Iterator iter = uids.Begin();
×
395
  for (; iter != uids.End(); ++iter) {
×
396
    OLA_INFO << "  " << *iter;
×
397
    iter->Pack(ptr + offset, param_data_size - offset - 4);
×
398
    offset += UID::UID_SIZE;
×
399
  }
400

401
  RDMResponse *response = GetResponseFromData(request, raw_data,
×
402
                                              param_data_size);
403
  delete[] raw_data;
×
404
  return response;
×
405
}
×
406

407
/**
408
 * Handle PID_TCP_COMMS_STATUS
409
 */
410
RDMResponse *ManagementEndpoint::GetTCPCommsStatus(const RDMRequest *request) {
×
411
  if (request->ParamDataSize()) {
×
412
    return NackWithReason(request, NR_FORMAT_ERROR);
×
413
  }
414

415
  PACK(
×
416
  struct tcp_stats_message_s {
417
    uint32_t ip_address;
418
    uint16_t unhealthy_events;
419
    uint16_t connection_events;
420
  });
421
  struct tcp_stats_message_s tcp_stats_message;
×
422

423
  tcp_stats_message.ip_address = m_tcp_stats->ip_address.AsInt();
×
424
  tcp_stats_message.unhealthy_events =
×
425
    HostToNetwork(m_tcp_stats->unhealthy_events);
×
426
  tcp_stats_message.connection_events =
×
427
    HostToNetwork(m_tcp_stats->connection_events);
×
428

429
  return GetResponseFromData(
×
430
      request,
431
      reinterpret_cast<uint8_t*>(&tcp_stats_message),
432
      sizeof(tcp_stats_message));
433
}
434

435
RDMResponse *ManagementEndpoint::SetTCPCommsStatus(const RDMRequest *request) {
×
436
  m_tcp_stats->ResetCounters();
×
437
  return GetResponseFromData(request, NULL, 0);
×
438
}
439

440
/**
441
 * Add our UID to the set and run the Discovery Callback.
442
 */
443
void ManagementEndpoint::DiscoveryComplete(RDMDiscoveryCallback *callback,
×
444
                                           const UIDSet &uids) {
445
  UIDSet all_uids(uids);
×
446
  all_uids.AddUID(m_uid);
×
447
  callback->Run(all_uids);
×
448
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc