#ifndef VRPN_REDUNDANT_TRANSMISSION_H
#define VRPN_REDUNDANT_TRANSMISSION_H
#include "vrpn_Shared.h" // for timeval, types
#include "vrpn_BaseClass.h"
#include "vrpn_Connection.h" // for vrpn_HANDLERPARAM, vrpn_Connection
class vrpn_RedundantTransmission {
public:
vrpn_RedundantTransmission (vrpn_Connection * c);
~vrpn_RedundantTransmission (void);
// ACCESSORS
vrpn_uint32 defaultRetransmissions (void) const;
timeval defaultInterval (void) const;
vrpn_bool isEnabled (void) const;
// MANIPULATORS
virtual void mainloop (void);
void enable (vrpn_bool);
virtual void setDefaults (vrpn_uint32 numRetransmissions,
timeval transmissionInterval);
virtual int pack_message
(vrpn_uint32 len, timeval time, vrpn_uint32 type,
vrpn_uint32 sender, const char * buffer,
vrpn_uint32 class_of_service,
vrpn_int32 numRetransmissions = -1,
timeval * transmissionInterval = NULL);
protected:
vrpn_Connection * d_connection;
struct queuedMessage {
vrpn_HANDLERPARAM p;
vrpn_uint32 remainingTransmissions;
timeval transmissionInterval;
timeval nextValidTime;
queuedMessage * next;
};
queuedMessage * d_messageList;
vrpn_uint32 d_numMessagesQueued;
// Default values.
vrpn_uint32 d_numTransmissions;
timeval d_transmissionInterval;
vrpn_bool d_isEnabled;
};
struct vrpn_RedundantController_Protocol {
char * encode_set (int * len, vrpn_uint32 num, timeval interval);
void decode_set (const char ** buf, vrpn_uint32 * num, timeval * interval);
char * encode_enable (int * len, vrpn_bool);
void decode_enable (const char ** buf, vrpn_bool *);
void register_types (vrpn_Connection *);
vrpn_int32 d_set_type;
vrpn_int32 d_enable_type;
};
class vrpn_RedundantController : public vrpn_BaseClass {
public:
vrpn_RedundantController (vrpn_RedundantTransmission *, vrpn_Connection *);
~vrpn_RedundantController (void);
void mainloop (void);
// Do nothing; vrpn_BaseClass requires this.
protected:
virtual int register_types (void);
vrpn_RedundantController_Protocol d_protocol;
static int handle_set (void *, vrpn_HANDLERPARAM);
static int handle_enable (void *, vrpn_HANDLERPARAM);
vrpn_RedundantTransmission * d_object;
};
class vrpn_RedundantRemote : public vrpn_BaseClass {
public:
vrpn_RedundantRemote (vrpn_Connection *);
~vrpn_RedundantRemote (void);
void mainloop (void);
// Do nothing; vrpn_BaseClass requires this.
void set (int numRetransmissions, timeval transmissionInterval);
void enable (vrpn_bool);
protected:
int register_types (void);
vrpn_RedundantController_Protocol d_protocol;
};
// A TypeDispatcher insists on too much control of its table for
// us to use one here - we want to use the same indices as the
// vrpn_Connection we're attached to, but if we had our own TypeDispatcher
// we'd have an independent, inconsistent set of type & sender ids.
#define VRPN_RR_LENGTH 8
class vrpn_RedundantReceiver {
public:
vrpn_RedundantReceiver (vrpn_Connection *);
~vrpn_RedundantReceiver (void);
virtual int register_handler (vrpn_int32 type,
vrpn_MESSAGEHANDLER handler, void * userdata,
vrpn_int32 sender = vrpn_ANY_SENDER);
virtual int unregister_handler (vrpn_int32 type,
vrpn_MESSAGEHANDLER handler, void * userdata,
vrpn_int32 sender = vrpn_ANY_SENDER);
void record (vrpn_bool);
void writeMemory (const char * filename);
void clearMemory (void);
protected:
vrpn_Connection * d_connection;
struct RRRecord {
RRRecord (void);
timeval timestampSeen [VRPN_RR_LENGTH];
int numSeen [VRPN_RR_LENGTH];
int nextTimestampToReplace;
vrpnMsgCallbackEntry * cb;
vrpn_bool handlerIsRegistered;
};
RRRecord d_records [vrpn_CONNECTION_MAX_TYPES];
RRRecord d_generic;
struct RRMemory {
timeval timestamp;
int numSeen;
RRMemory * next;
};
RRMemory * d_memory;
RRMemory * d_lastMemory;
vrpn_bool d_record;
static int handle_possiblyRedundantMessage (void *, vrpn_HANDLERPARAM);
};
#endif // VRPN_REDUNDANT_TRANSMISSION_H