-
Notifications
You must be signed in to change notification settings - Fork 1
/
vrpn_Auxiliary_Logger.h
253 lines (219 loc) · 11.5 KB
/
vrpn_Auxiliary_Logger.h
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
// This is a base class interface that has been designed for use by
// scientific data-collection applications that make use of VRPN to
// connect to microscope imagers and tracking system for nanoscale
// science research at UNC.
// The idea of this interface is to enable a client GUI to start and
// stop logging of full-rate data on the server while receiving only
// a subset of the data during the experiment for preview; this keeps
// from overloading the network bandwidth with data and also keeps
// the client-side log files from filling up. When new log file(s)
// are requested, the old log files are closed.
// Note that a particular implementation of the auxiliary logger server
// may need to know about a second connection (not the one it talks
// to its client over) in case that is where it is doing its logging.
#ifndef VRPN_AUXILIARY_LOGGER_H
#define VRPN_AUXILIARY_LOGGER_H
#include <string.h> // for NULL
#include "vrpn_BaseClass.h" // for vrpn_Callback_List, etc
#include "vrpn_Configure.h" // for VRPN_CALLBACK, VRPN_API
#include "vrpn_Connection.h"
#include "vrpn_Shared.h" // for timeval
#include "vrpn_Types.h" // for vrpn_int32
class VRPN_API vrpn_Auxiliary_Logger : public vrpn_BaseClass {
public:
vrpn_Auxiliary_Logger(const char *name, vrpn_Connection *c);
protected:
// Handle registration of all message types we're going to deal with.
virtual int register_types(void);
vrpn_int32 request_logging_m_id; // ID of remote->server request message
vrpn_int32 report_logging_m_id; // ID of server->client response message
vrpn_int32 request_logging_status_m_id; // ID of remote->server
// status-request message
// Pack a log description into the message whose type is passed
// as the parameter (this is used to pack both the request and
// report messages.
bool pack_log_message_of_type(vrpn_int32 type,
const char *local_in_logfile_name,
const char *local_out_logfile_name,
const char *remote_in_logfile_name,
const char *remote_out_logfile_name);
// Unpack a log description from a message into the four strings that
// were passed in (this is used to unpack both the request and the
// report messages).
// NOTE: This routine will allocate space for the strings. The caller
// must delete [] this space when they are done with it to avoid
// memory leaks.
bool unpack_log_message_from_buffer(const char *buf, vrpn_int32 buflen,
char **local_in_logfile_name,
char **local_out_logfile_name,
char **remote_in_logfile_name,
char **remote_out_logfile_name);
};
// Virtual base server class for an auxiliiary logger. An implementation must
// implement the specified message-handling functions and must call the base-
// class constructor to set up the calling of them.
class VRPN_API vrpn_Auxiliary_Logger_Server : public vrpn_Auxiliary_Logger {
public:
vrpn_Auxiliary_Logger_Server(const char *name, vrpn_Connection *c);
// Required for servers.
virtual void mainloop(void) { server_mainloop(); }
protected:
// Handle a logging-request message. The request contains four file
// names, two for local (to the Auxiliary server itself) and two for
// remote (the far side of its connection to the server). It must
// also respond to the client with a message saying what logging has
// been set up (using the send_logging_response function). Logging is
// turned off on a particular file by sending an empty-string name ("").
// The in/out local/remote are with respect to the connection that the
// logging is to occur on, which may or may not be the same one that the
// client has connected to the object on using the constructor above.
// Make sure to send a response saying what you did.
virtual void
handle_request_logging(const char *local_in_logfile_name,
const char *local_out_logfile_name,
const char *remote_in_logfile_name,
const char *remote_out_logfile_name) = 0;
// Send a response to the client telling it what logging has been
// established.
bool send_report_logging(const char *local_in_logfile_name,
const char *local_out_logfile_name,
const char *remote_in_logfile_name,
const char *remote_out_logfile_name)
{
if (!d_connection) {
return false;
}
return pack_log_message_of_type(
report_logging_m_id, local_in_logfile_name, local_out_logfile_name,
remote_in_logfile_name, remote_out_logfile_name);
}
// Handle dropped last connection on server object by turning off
// logging. The static method basically looks up the this
// pointer and calls the virtual method. A derived class should
// re-implement the non-static method below if it doesn't want to drop all
// logging or if it wants to do something else in addition. The static
// method basically just calls the non-static method.
virtual void handle_dropped_last_connection(void);
vrpn_int32 dropped_last_connection_m_id; // ID of message that all
// connections dropped
static int VRPN_CALLBACK
static_handle_dropped_last_connection(void *userdata, vrpn_HANDLERPARAM p);
// Static portion of handling (unpacking) the request_logging message. It
// then calls the non-static virtual method above.
static int VRPN_CALLBACK
static_handle_request_logging(void *userdata, vrpn_HANDLERPARAM p);
// Handle request for logging status.
virtual void handle_request_logging_status() = 0;
static int VRPN_CALLBACK
static_handle_request_logging_status(void *userdata, vrpn_HANDLERPARAM p);
};
// Generic server that will start auxiliary logs on the connection whose name
// is passed in (which can be the same as the name of the connection it is
// created on, but does not have to be). The "local" in and out are with
// respect to the new connection that is made; the "remote" in and out are with
// respect to the named connection. No logging is started in the constructor.
class VRPN_API vrpn_Auxiliary_Logger_Server_Generic
: public vrpn_Auxiliary_Logger_Server {
public:
// Does not start logging, just records what to log when it is started.
vrpn_Auxiliary_Logger_Server_Generic(const char *logger_name,
const char *connection_to_log,
vrpn_Connection *c = NULL);
~vrpn_Auxiliary_Logger_Server_Generic();
// Close an existing logging connection, then (if any of the file
// names are non-empty) open a new logging connection to the
// connection we are to log (even if this process already has a
// connection to it) and then send back the report that we've started
// logging if we are able. If we cannot open it, then fill in all
// blank names for the return report.
virtual void handle_request_logging(const char *local_in_logfile_name,
const char *local_out_logfile_name,
const char *remote_in_logfile_name,
const char *remote_out_logfile_name);
virtual void handle_request_logging_status();
// If we have an active logging connection, mainloop it and save all of its
// pending messages in addition to handling the base-class functions.
// Then call the parent class mainloop().
virtual void mainloop(void)
{
if (d_logging_connection) {
d_logging_connection->mainloop();
d_logging_connection->save_log_so_far();
}
vrpn_Auxiliary_Logger_Server::mainloop();
}
protected:
char *d_connection_name; // Name to connect to when logging.
vrpn_Connection *d_logging_connection; // Connection to use for logging.
};
//-----------------------------------------------------------
//************** Client code uses the following *************
// Type of a client routine to request new logging and to handle a
// report of changed logging. This callback is called when the
// logging server reports a new set of files, which should happen
// after each request is made.
typedef struct _vrpn_AUXLOGGERCB {
struct timeval msg_time; // Timestamp of new logging
const char *
local_in_logfile_name; // Name of the incoming local log ("" if none).
const char *local_out_logfile_name;
const char *remote_in_logfile_name;
const char *remote_out_logfile_name;
} vrpn_AUXLOGGERCB;
typedef void(VRPN_CALLBACK *vrpn_AUXLOGGERREPORTHANDLER)(
void *userdata, const vrpn_AUXLOGGERCB info);
class VRPN_API vrpn_Auxiliary_Logger_Remote : public vrpn_Auxiliary_Logger {
public:
vrpn_Auxiliary_Logger_Remote(const char *name, vrpn_Connection *c = NULL);
// Send a request to the server asking it to log the following. Each of
// these is with respect to the connection that the auxiliary logger server
// is handling, which may or may not be the one that it is connected to to
// receive this message; it refers to the other side of the new connection
// that the server establishes to do its logging. Passing a NULL or empty
// string ("") to any of the entries disables that log.
// WARNING: If the server is set to connect to its own connection and log
// it, then you must explicitly request a set of empty log files to stop
// it logging the last time because otherwise it never gets the message
// that it dropped the last connection and will continue logging after the
// object is destroyed.
bool send_logging_request(const char *local_in_logfile_name,
const char *local_out_logfile_name = "",
const char *remote_in_logfile_name = "",
const char *remote_out_logfile_name = "")
{
if (!d_connection) {
return false;
}
return pack_log_message_of_type(
request_logging_m_id, local_in_logfile_name, local_out_logfile_name,
remote_in_logfile_name, remote_out_logfile_name);
}
bool send_logging_status_request()
{
if (!d_connection) {
return false;
}
return pack_log_message_of_type(request_logging_status_m_id, NULL, NULL,
NULL, NULL);
}
// Register/unregister a callback handler for the logging response.
virtual int register_report_handler(void *userdata,
vrpn_AUXLOGGERREPORTHANDLER handler)
{
return d_callback_list.register_handler(userdata, handler);
};
virtual int unregister_report_handler(void *userdata,
vrpn_AUXLOGGERREPORTHANDLER handler)
{
return d_callback_list.unregister_handler(userdata, handler);
}
// This routine calls the mainloop of the connection it's on
virtual void mainloop(void);
protected:
// Static handler for the logging report message.
// Use the base-class unpack method to convert the data into strings.
vrpn_Callback_List<vrpn_AUXLOGGERCB> d_callback_list;
static int VRPN_CALLBACK
handle_report_message(void *userdata, vrpn_HANDLERPARAM p);
};
#endif