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

OpenLightingProject / ola / 16900099157

12 Aug 2025 05:43AM UTC coverage: 45.72% (-0.02%) from 45.742%
16900099157

Pull #2016

github

web-flow
Merge c368ef6ae into eaf937e80
Pull Request #2016: Bump actions/checkout from 4 to 5

7586 of 17462 branches covered (43.44%)

22424 of 49046 relevant lines covered (45.72%)

51.77 hits per line

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

0.0
/tools/e133/E133Device.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
 * E133Device.cpp
17
 * Copyright (C) 2011 Simon Newton
18
 */
19

20
#include <ola/Callback.h>
21
#include <ola/Logging.h>
22
#include <ola/acn/ACNVectors.h>
23
#include <ola/acn/CID.h>
24
#include <ola/io/SelectServerInterface.h>
25
#include <ola/network/HealthCheckedConnection.h>
26
#include <ola/network/IPV4Address.h>
27
#include <ola/network/SocketAddress.h>
28
#include <ola/rdm/RDMCommandSerializer.h>
29
#include <ola/rdm/RDMControllerInterface.h>
30
#include <ola/rdm/RDMHelper.h>
31

32
#include <memory>
33
#include <string>
34
#include <vector>
35

36
#include "libs/acn/E133Header.h"
37
#include "libs/acn/E133PDU.h"
38
#include "libs/acn/RDMPDU.h"
39
#include "libs/acn/RDMInflator.h"
40
#include "libs/acn/E133StatusInflator.h"
41
#include "libs/acn/UDPTransport.h"
42

43
#include "tools/e133/E133Device.h"
44
#include "tools/e133/E133Endpoint.h"
45
#include "libs/acn/E133HealthCheckedConnection.h"
46
#include "tools/e133/EndpointManager.h"
47
#include "tools/e133/TCPConnectionStats.h"
48

49
using ola::NewCallback;
50
using ola::io::IOStack;
51
using ola::network::HealthCheckedConnection;
52
using ola::network::IPV4Address;
53
using ola::network::IPV4SocketAddress;
54
using ola::acn::RDMPDU;
55
using std::auto_ptr;
56
using std::string;
57
using std::vector;
58

59
// TODO(simon): At some point move this to a common E1.33 library.
60
ola::e133::E133StatusCode RDMStatusCodeToE133Status(
×
61
    ola::rdm::RDMStatusCode status_code) {
62
  switch (status_code) {
×
63
    case ola::rdm::RDM_COMPLETED_OK:
64
      return ola::e133::SC_E133_ACK;
65
    case ola::rdm::RDM_WAS_BROADCAST:
66
      return ola::e133::SC_E133_BROADCAST_COMPLETE;
67
    case ola::rdm::RDM_FAILED_TO_SEND:
68
    case ola::rdm::RDM_TIMEOUT:
69
      return ola::e133::SC_E133_RDM_TIMEOUT;
70
    case ola::rdm::RDM_UNKNOWN_UID:
71
      return ola::e133::SC_E133_UNKNOWN_UID;
72
    case ola::rdm::RDM_INVALID_RESPONSE:
73
    case ola::rdm::RDM_CHECKSUM_INCORRECT:
74
    case ola::rdm::RDM_TRANSACTION_MISMATCH:
75
    case ola::rdm::RDM_SUB_DEVICE_MISMATCH:
76
    case ola::rdm::RDM_SRC_UID_MISMATCH:
77
    case ola::rdm::RDM_DEST_UID_MISMATCH:
78
    case ola::rdm::RDM_WRONG_SUB_START_CODE:
79
    case ola::rdm::RDM_PACKET_TOO_SHORT:
80
    case ola::rdm::RDM_PACKET_LENGTH_MISMATCH:
81
    case ola::rdm::RDM_PARAM_LENGTH_MISMATCH:
82
    case ola::rdm::RDM_INVALID_COMMAND_CLASS:
83
    case ola::rdm::RDM_COMMAND_CLASS_MISMATCH:
84
    case ola::rdm::RDM_INVALID_RESPONSE_TYPE:
85
    case ola::rdm::RDM_PLUGIN_DISCOVERY_NOT_SUPPORTED:
86
    case ola::rdm::RDM_DUB_RESPONSE:
87
      return ola::e133::SC_E133_RDM_INVALID_RESPONSE;
88
  }
89
  return ola::e133::SC_E133_RDM_INVALID_RESPONSE;
90
}
91

92
E133Device::E133Device(ola::io::SelectServerInterface *ss,
×
93
                       const ola::acn::CID &cid,
94
                       const ola::network::IPV4Address &ip_address,
95
                       EndpointManager *endpoint_manager)
×
96
    : m_ss(ss),
×
97
      m_ip_address(ip_address),
×
98
      m_message_builder(cid, "OLA Device"),
×
99
      m_endpoint_manager(endpoint_manager),
×
100
      m_root_endpoint(NULL),
×
101
      m_root_rdm_device(NULL),
×
102
      m_incoming_udp_transport(&m_udp_socket, &m_root_inflator) {
×
103
  m_root_inflator.AddInflator(&m_e133_inflator);
×
104
  m_e133_inflator.AddInflator(&m_rdm_inflator);
×
105
  m_e133_inflator.AddInflator(&m_rdm_inflator);
×
106

107
  m_rdm_inflator.SetRDMHandler(
×
108
      NewCallback(this, &E133Device::EndpointRequest));
109
}
×
110

111
E133Device::~E133Device() {
×
112
  vector<uint16_t> endpoints;
×
113
  m_endpoint_manager->EndpointIDs(&endpoints);
×
114
  m_rdm_inflator.SetRDMHandler(NULL);
×
115
}
×
116

117
/**
118
 * Set the Root Endpoint, ownership is not transferred
119
 */
120
void E133Device::SetRootEndpoint(E133EndpointInterface *endpoint) {
×
121
  m_root_endpoint = endpoint;
×
122
}
×
123

124

125
/**
126
 * Init the device.
127
 */
128
bool E133Device::Init() {
×
129
  if (m_controller_connection.get()) {
×
130
    OLA_WARN << "Init already performed";
×
131
    return false;
×
132
  }
133

134
  OLA_INFO << "Attempting to start E1.33 device at " << m_ip_address;
×
135

136
  m_controller_connection.reset(new DesignatedControllerConnection(
×
137
        m_ss, m_ip_address, &m_message_builder, &m_tcp_stats));
×
138

139
  if (!m_controller_connection->Init()) {
×
140
    m_controller_connection.reset();
×
141
    return false;
×
142
  }
143

144
  // setup the UDP socket
145
  if (!m_udp_socket.Init()) {
×
146
    m_controller_connection.reset();
×
147
    return false;
×
148
  }
149

150
  if (!m_udp_socket.Bind(IPV4SocketAddress(IPV4Address::WildCard(),
×
151
                                           ola::acn::E133_PORT))) {
×
152
    m_controller_connection.reset();
×
153
    return false;
×
154
  }
155

156
  m_udp_socket.SetOnData(
×
157
        NewCallback(&m_incoming_udp_transport,
158
                    &ola::acn::IncomingUDPTransport::Receive));
159

160
  m_ss->AddReadDescriptor(&m_udp_socket);
×
161
  return true;
×
162
}
163

164

165
/**
166
 * Return the TCPConnectionStats.
167
 */
168
TCPConnectionStats* E133Device::GetTCPStats() {
×
169
  return &m_tcp_stats;
×
170
}
171

172

173
/**
174
 * Send an unsolicated RDM message on the TCP channel.
175
 * @param command the RDM command to send, ownership is transferred.
176
 */
177
void E133Device::SendStatusMessage(const ola::rdm::RDMResponse *response) {
×
178
  if (m_controller_connection.get()) {
×
179
    m_controller_connection->SendStatusMessage(ROOT_E133_ENDPOINT, response);
×
180
  } else {
181
    OLA_WARN << "Init has not been called";
×
182
  }
183
}
×
184

185

186
/**
187
 * Force close the designated controller's TCP connection.
188
 * @return, true if there was a connection to close, false otherwise.
189
 */
190
bool E133Device::CloseTCPConnection() {
×
191
  if (m_controller_connection.get()) {
×
192
    return m_controller_connection->CloseTCPConnection();
×
193
  } else {
194
    return false;
195
  }
196
}
197

198

199
/**
200
 * Handle requests to an endpoint.
201
 */
202
void E133Device::EndpointRequest(
×
203
    const ola::acn::TransportHeader *transport_header,
204
    const ola::acn::E133Header *e133_header,
205
    const string &raw_request) {
206
  IPV4SocketAddress target = transport_header->Source();
×
207
  uint16_t endpoint_id = e133_header->Endpoint();
×
208
  OLA_INFO << "Got request for endpoint " << endpoint_id << " from " << target;
×
209

210
  E133EndpointInterface *endpoint = NULL;
×
211
  if (endpoint_id)
×
212
    endpoint = m_endpoint_manager->GetEndpoint(endpoint_id);
×
213
  else
214
    endpoint = m_root_endpoint;
×
215

216
  if (!endpoint) {
×
217
    OLA_INFO << "Request to non-existent endpoint " << endpoint_id;
×
218
    SendStatusMessage(target, e133_header->Sequence(), endpoint_id,
×
219
                      ola::e133::SC_E133_NONEXISTENT_ENDPOINT,
220
                      "No such endpoint");
221
    return;
×
222
  }
223

224
  // attempt to unpack as a request
225
  ola::rdm::RDMRequest *request = ola::rdm::RDMRequest::InflateFromData(
×
226
    reinterpret_cast<const uint8_t*>(raw_request.data()),
×
227
    raw_request.size());
×
228

229
  if (!request) {
×
230
    OLA_WARN << "Failed to unpack E1.33 RDM message, ignoring request.";
×
231
    // There is no way to return 'invalid request' so pretend this is a timeout
232
    // but give a descriptive error msg.
233
    SendStatusMessage(target, e133_header->Sequence(), endpoint_id,
×
234
                      ola::e133::SC_E133_RDM_TIMEOUT,
235
                     "Invalid RDM request");
236
    return;
×
237
  }
238

239
  endpoint->SendRDMRequest(
×
240
      request,
241
      ola::NewSingleCallback(this,
×
242
                             &E133Device::EndpointRequestComplete,
243
                             target,
244
                             e133_header->Sequence(),
245
                             endpoint_id));
246
}
×
247

248

249
/**
250
 * Handle a completed RDM request.
251
 */
252
void E133Device::EndpointRequestComplete(
×
253
    ola::network::IPV4SocketAddress target,
254
    uint32_t sequence_number,
255
    uint16_t endpoint_id,
256
    ola::rdm::RDMReply *reply) {
257
  if (reply->StatusCode() != ola::rdm::RDM_COMPLETED_OK) {
×
258
    string description = ola::rdm::ResponseCodeToString(reply->StatusCode());
×
259
    ola::e133::E133StatusCode e133_status_code = RDMStatusCodeToE133Status(
×
260
        reply->StatusCode());
261
    SendStatusMessage(target, sequence_number, endpoint_id,
×
262
                      e133_status_code, description);
263
    return;
×
264
  }
×
265

266
  IOStack packet(m_message_builder.pool());
×
267
  ola::rdm::RDMCommandSerializer::Write(*reply->Response(), &packet);
×
268
  RDMPDU::PrependPDU(&packet);
×
269
  m_message_builder.BuildUDPRootE133(
×
270
      &packet, ola::acn::VECTOR_FRAMING_RDMNET, sequence_number,
271
      endpoint_id);
272

273
  if (!m_udp_socket.SendTo(&packet, target)) {
×
274
    OLA_WARN << "Failed to send E1.33 response to " << target;
×
275
  }
276
}
×
277

278

279
void E133Device::SendStatusMessage(
×
280
    const ola::network::IPV4SocketAddress target,
281
    uint32_t sequence_number,
282
    uint16_t endpoint_id,
283
    ola::e133::E133StatusCode status_code,
284
    const string &description) {
285
  IOStack packet(m_message_builder.pool());
×
286
  m_message_builder.BuildUDPE133StatusPDU(
×
287
      &packet, sequence_number, endpoint_id,
288
      status_code, description);
289
  if (!m_udp_socket.SendTo(&packet, target)) {
×
290
    OLA_WARN << "Failed to send E1.33 response to " << target;
×
291
  }
292
}
×
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

© 2025 Coveralls, Inc