This file is indexed.

/usr/include/ola/rdm/DiscoveryAgent.h is in libola-dev 0.10.3.nojsmin-2+deb9u1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
/*
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 *
 * DiscoveryAgent.h
 * Implements the RDM Discovery algorithm.
 * Copyright (C) 2011 Simon Newton
 */

/**
 * @addtogroup rdm_controller
 * @{
 * @file include/ola/rdm/DiscoveryAgent.h
 * @brief Implements the RDM Discovery algorithm
 * @}
 */

#ifndef INCLUDE_OLA_RDM_DISCOVERYAGENT_H_
#define INCLUDE_OLA_RDM_DISCOVERYAGENT_H_

#include <ola/Callback.h>
#include <ola/rdm/UID.h>
#include <ola/rdm/UIDSet.h>
#include <memory>
#include <queue>
#include <stack>
#include <utility>

namespace ola {
namespace rdm {

/**
 * @brief The interface used by the DiscoveryTarget to send RDM commands.
 *
 * This class abstracts away the method of sending RDM commands from the
 * discovery algorithm in DiscoveryAgent.
 *
 * For each of the MuteDevice, UnMuteAll and Branch methods, the implementation
 * should send the appropriate RDM command and then run the provided callback
 * when the command has been sent.
 */
class DiscoveryTargetInterface {
 public:
  /**
   * @brief The callback run when a mute command completes.
   * @tparam ok true if the device muted correctly, false if the device failed
   *   to ack the mute.
   */
  typedef ola::BaseCallback1<void, bool> MuteDeviceCallback;

  /**
   * @brief The callback run when an unmute command completes.
   */
  typedef ola::BaseCallback0<void> UnMuteDeviceCallback;

  /**
   * @brief The callback run when a DUB command completes.
   * @tparam data The DUB response, if any was received. Otherwise pass NULL.
   * @tparam length The length of the DUB response.
   */
  typedef ola::BaseCallback2<void, const uint8_t*, unsigned int>
    BranchCallback;

  virtual ~DiscoveryTargetInterface() {}

  /**
   * @brief Mute a device.
   * @param target the device to mute
   * @param mute_complete the callback to run when the mute operations
   * completes.
   */
  virtual void MuteDevice(const UID &target,
                          MuteDeviceCallback *mute_complete) = 0;

  /**
   * @brief Unmute all devices.
   * @param unmute_complete the callback to run when the unmute operation
   * completes.
   */
  virtual void UnMuteAll(UnMuteDeviceCallback *unmute_complete) = 0;

  /**
   * @brief Send a DUB command
   * @param lower the lower bound UID.
   * @param upper the upper bound UID.
   * @param callback the callback to run when the DUB completes.
   *
   * Any data received in response to the DUB command should be passed back
   * when the callback is run.
   */
  virtual void Branch(const UID &lower,
                      const UID &upper,
                      BranchCallback *callback) = 0;
};


/**
 * @brief An asyncronous RDM Discovery algorithm.
 *
 * This implements the binary search algorithm from the E1.20 standard. The
 * implementation is asyncronous and relies on callbacks to indicate when each
 * step completes.
 *
 * To use the DiscoveryAgent, one should write a class that implements the
 * DiscoveryTargetInterface interface and then pass a pointer to that object to
 * the DiscoveryAgent.
 *
 * The discovery process goes something like this:
 *   - if incremental, copy all previously discovered UIDs to the mute list
 *   - push (0, 0xffffffffffff) onto the resolution stack
 *   - unmute all
 *   - mute all previously discovered UIDs, for any that fail to mute remove
 *     them from the UIDSet.
 *   - Send a discovery unique branch message
 *     - If we get a valid response, mute, and send the same branch again
 *     - If we get a collision, split the UID range, and try each branch
 *       separately.
 *
 * We also track responders that fail to ack a mute request (we attempt to mute
 * MAX_MUTE_ATTEMPTS times) and branches that contain responders which continue
 * to respond once muted. The latter causes a branch to be marked as corrupt,
 * which prevents us from looping forver.
 */
class DiscoveryAgent {
 public:
  /**
   * @brief Create a new DiscoveryAgent
   * @param target the DiscoveryTargetInterface to use for sending commands.
   */
  explicit DiscoveryAgent(DiscoveryTargetInterface *target);

  /**
   * @brief Destructor.
   */
  ~DiscoveryAgent();

  typedef ola::SingleUseCallback2<void, bool, const UIDSet&>
    DiscoveryCompleteCallback;

  /**
   * @brief Cancel any in-progress discovery operation.
   * If a discovery operation is running, this will result in the callback
   * being run.
   */
  void Abort();

  /**
   * @brief Initiate a full discovery operation.
   * @param on_complete the callback to run once discovery completes.
   */
  void StartFullDiscovery(DiscoveryCompleteCallback *on_complete);

  /**
   * @brief Initiate an incremental discovery operation.
   * @param on_complete the callback to run once discovery completes.
   */
  void StartIncrementalDiscovery(DiscoveryCompleteCallback *on_complete);

 private:
  /**
   * @brief Represents a range of UIDs (a branch of the UID tree)
   */
  struct UIDRange {
    UIDRange(const UID &_lower, const UID &_upper, UIDRange *_parent)
        : lower(_lower),
          upper(_upper),
          parent(_parent),
          attempt(0),
          failures(0),
          uids_discovered(0),
          branch_corrupt(false) {
    }
    UID lower;
    UID upper;
    UIDRange *parent;  // the parent Range
    unsigned int attempt;  // the # of attempts for this branch
    unsigned int failures;
    unsigned int uids_discovered;
    bool branch_corrupt;  // true if this branch contains a bad device
  };

  typedef std::stack<UIDRange*> UIDRanges;

  DiscoveryTargetInterface *m_target;
  UIDSet m_uids;
  // uids that are misbehaved in some way
  UIDSet m_bad_uids;
  DiscoveryCompleteCallback *m_on_complete;
  // uids to mute during incremental discovery
  std::queue<UID> m_uids_to_mute;
  // Callbacks used by the DiscoveryTarget
  std::auto_ptr<DiscoveryTargetInterface::UnMuteDeviceCallback>
      m_unmute_callback;
  std::auto_ptr<DiscoveryTargetInterface::MuteDeviceCallback>
      m_incremental_mute_callback;
  std::auto_ptr<DiscoveryTargetInterface::MuteDeviceCallback>
      m_branch_mute_callback;
  std::auto_ptr<DiscoveryTargetInterface::BranchCallback> m_branch_callback;

  // The stack of UIDRanges
  UIDRanges m_uid_ranges;
  UID m_muting_uid;  // the uid we're currently trying to mute
  unsigned int m_unmute_count;
  unsigned int m_mute_attempts;
  bool m_tree_corrupt;  // true if there was a problem with discovery

  void InitDiscovery(DiscoveryCompleteCallback *on_complete,
                     bool incremental);

  void UnMuteComplete();
  void MaybeMuteNextDevice();
  void IncrementalMuteComplete(bool status);
  void SendDiscovery();

  void BranchComplete(const uint8_t *data, unsigned int length);
  void BranchMuteComplete(bool status);
  void HandleCollision();
  void FreeCurrentRange();

  static const unsigned int PREAMBLE_SIZE = 8;
  static const unsigned int EUID_SIZE = 12;
  static const unsigned int CHECKSUM_SIZE = 4;

  /*
   * The maximum numbers of times we'll retry discovery if we get a
   * collision, but after splitting the range in two no nodes can be found.
   */
  static const unsigned int MAX_EMPTY_BRANCH_ATTEMPTS = 5;
  /*
   * The maximum number of times we'll perform discovery on a branch when we
   * get an inconsistent result (responder not muting, etc.)
   */
  static const unsigned int MAX_BRANCH_FAILURES = 5;

  // The number of times we'll attempt to mute a UID
  static const unsigned int MAX_MUTE_ATTEMPTS = 5;
  // The number of times we'll send a broadcast unmute command
  // This should be more than 1 to ensure that all devices are unmuted.
  static const unsigned int BROADCAST_UNMUTE_REPEATS = 3;

  static const uint8_t PREAMBLE = 0xfe;
  static const uint8_t PREAMBLE_SEPARATOR = 0xaa;
};
}  // namespace rdm
}  // namespace ola
#endif  // INCLUDE_OLA_RDM_DISCOVERYAGENT_H_