vrpn  07.33
Virtual Reality Peripheral Network
vrpn_Auxiliary_Logger.C
Go to the documentation of this file.
1 #include <stddef.h> // for size_t
2 #include <stdio.h> // for fprintf, stderr
3 
5 
8  : vrpn_BaseClass(name, c)
9 {
11 }
12 
14 {
16  "vrpn_Auxiliary_Logger Logging_request");
18  "vrpn_Auxiliary_Logger Logging_response");
20  "vrpn_Auxiliary_Logger Logging_status_request");
21 
22  if ((request_logging_m_id == -1) || (report_logging_m_id == -1) ||
24  d_connection = NULL;
25  return -1;
26  }
27  else {
28  return 0;
29  }
30 }
31 
32 // Send a message of the specified type.
33 // Note that the pointers may be NULL, so we need to check for this.
35  vrpn_int32 type, const char *local_in_logfile_name,
36  const char *local_out_logfile_name, const char *remote_in_logfile_name,
37  const char *remote_out_logfile_name)
38 {
39  if (!d_connection) {
40  return false;
41  }
42 
43  // Figure out the lengths, handling NULL pointers.
44  vrpn_int32 lil = 0;
45  if (local_in_logfile_name) {
46  lil = static_cast<vrpn_int32>(strlen(local_in_logfile_name));
47  }
48  vrpn_int32 lol = 0;
49  if (local_out_logfile_name) {
50  lol = static_cast<vrpn_int32>(strlen(local_out_logfile_name));
51  }
52  vrpn_int32 ril = 0;
53  if (remote_in_logfile_name) {
54  ril = static_cast<vrpn_int32>(strlen(remote_in_logfile_name));
55  }
56  vrpn_int32 rol = 0;
57  if (remote_out_logfile_name) {
58  rol = static_cast<vrpn_int32>(strlen(remote_out_logfile_name));
59  }
60 
61  struct timeval now;
62  vrpn_int32 bufsize =
63  static_cast<vrpn_int32>(4 * sizeof(lil) + lil + lol + ril + rol);
64  char *buf = new char[bufsize];
65  if (buf == NULL) {
66  fprintf(stderr, "vrpn_Auxiliary_Logger::pack_log_message_of_type(): "
67  "Out of memory.\n");
68  return false;
69  }
70 
71  // Pack a message with the requested type from our sender ID that has
72  // first the four lengths of the strings and then the four strings.
73  // Do not include the NULL termination of the strings in the buffer.
74 
75  vrpn_gettimeofday(&now, NULL);
76  char *bpp = buf;
77  char **bp = &bpp;
78  vrpn_int32 bufleft = bufsize;
79  vrpn_buffer(bp, &bufleft, lil);
80  vrpn_buffer(bp, &bufleft, lol);
81  vrpn_buffer(bp, &bufleft, ril);
82  vrpn_buffer(bp, &bufleft, rol);
83  if (lil) {
84  vrpn_buffer(bp, &bufleft, local_in_logfile_name, lil);
85  }
86  if (lol) {
87  vrpn_buffer(bp, &bufleft, local_out_logfile_name, lol);
88  }
89  if (ril) {
90  vrpn_buffer(bp, &bufleft, remote_in_logfile_name, ril);
91  }
92  if (rol) {
93  vrpn_buffer(bp, &bufleft, remote_out_logfile_name, rol);
94  }
95  int ret =
96  d_connection->pack_message(bufsize - bufleft, now, type, d_sender_id,
98  delete[] buf;
99  return (ret == 0);
100 }
101 
102 // Unpack the strings from the buffer. Return non-NULL pointers to
103 // strings (an empty string when a file name is empty).
105  const char *buf, vrpn_int32 buflen, char **local_in_logfile_name,
106  char **local_out_logfile_name, char **remote_in_logfile_name,
107  char **remote_out_logfile_name)
108 {
109  const char *bufptr = buf;
110 
111  // Make sure that the buffer contains at least enough space for the four
112  // length
113  // values, then pull the lengths of the strings out of the buffer
114  vrpn_int32 localInNameLen, localOutNameLen, remoteInNameLen,
115  remoteOutNameLen;
116  if (static_cast<size_t>(buflen) < 4 * sizeof(localInNameLen)) {
117  fprintf(stderr, "vrpn_Auxiliary_Logger::unpack_log_message_from_buffer:"
118  " Buffer too small for lengths.\n");
119  return false;
120  }
121  vrpn_unbuffer(&bufptr, &localInNameLen);
122  vrpn_unbuffer(&bufptr, &localOutNameLen);
123  vrpn_unbuffer(&bufptr, &remoteInNameLen);
124  vrpn_unbuffer(&bufptr, &remoteOutNameLen);
125 
126  // Make sure we have enough room in the buffer for the four sizes and also
127  // the four
128  // strings of the appropriate size. If so, allocate the space for the
129  // strings and then
130  // copy them out and NULL-terminate them. They are not NULL-terminated in
131  // the message
132  // buffer.
133  int size = 4 * sizeof(localInNameLen) + localInNameLen + localOutNameLen +
134  remoteInNameLen + remoteOutNameLen;
135  if (buflen != size) {
136  fprintf(stderr, "vrpn_Auxiliary_Logger::unpack_log_message_from_buffer:"
137  " Buffer size incorrect\n");
138  return false;
139  }
140  (*local_in_logfile_name) = NULL;
141  (*local_out_logfile_name) = NULL;
142  (*remote_in_logfile_name) = NULL;
143  (*remote_out_logfile_name) = NULL;
144  if (localInNameLen > 0) {
145  if (((*local_in_logfile_name) = new char[localInNameLen + 1]) == NULL) {
146  fprintf(stderr, "vrpn_Auxiliary_Logger::unpack_log_message_from_"
147  "buffer: Out of memory\n");
148  return false;
149  }
150  memcpy(*local_in_logfile_name, bufptr, localInNameLen);
151  (*local_in_logfile_name)[localInNameLen] = '\0';
152  bufptr += localInNameLen;
153  }
154  else {
155  if (((*local_in_logfile_name) = new char[2]) == NULL) {
156  fprintf(stderr, "vrpn_Auxiliary_Logger::unpack_log_message_from_"
157  "buffer: Out of memory\n");
158  return false;
159  }
160  (*local_in_logfile_name)[0] = '\0';
161  }
162  if (localOutNameLen > 0) {
163  if (((*local_out_logfile_name) = new char[localOutNameLen + 1]) ==
164  NULL) {
165  fprintf(stderr, "vrpn_Auxiliary_Logger::unpack_log_message_from_"
166  "buffer: Out of memory\n");
167  return false;
168  }
169  memcpy(*local_out_logfile_name, bufptr, localOutNameLen);
170  (*local_out_logfile_name)[localOutNameLen] = '\0';
171  bufptr += localOutNameLen;
172  }
173  else {
174  if (((*local_out_logfile_name) = new char[2]) == NULL) {
175  fprintf(stderr, "vrpn_Auxiliary_Logger::unpack_log_message_from_"
176  "buffer: Out of memory\n");
177  return false;
178  }
179  (*local_out_logfile_name)[0] = '\0';
180  }
181  if (remoteInNameLen > 0) {
182  if (((*remote_in_logfile_name) = new char[remoteInNameLen + 1]) ==
183  NULL) {
184  fprintf(stderr, "vrpn_Auxiliary_Logger::unpack_log_message_from_"
185  "buffer: Out of memory\n");
186  return false;
187  }
188  memcpy(*remote_in_logfile_name, bufptr, remoteInNameLen);
189  (*remote_in_logfile_name)[remoteInNameLen] = '\0';
190  bufptr += remoteInNameLen;
191  }
192  else {
193  if (((*remote_in_logfile_name) = new char[2]) == NULL) {
194  fprintf(stderr, "vrpn_Auxiliary_Logger::unpack_log_message_from_"
195  "buffer: Out of memory\n");
196  return false;
197  }
198  (*remote_in_logfile_name)[0] = '\0';
199  }
200  if (remoteOutNameLen > 0) {
201  if (((*remote_out_logfile_name) = new char[remoteOutNameLen + 1]) ==
202  NULL) {
203  fprintf(stderr, "vrpn_Auxiliary_Logger::unpack_log_message_from_"
204  "buffer: Out of memory\n");
205  return false;
206  }
207  memcpy(*remote_out_logfile_name, bufptr, remoteOutNameLen);
208  (*remote_out_logfile_name)[remoteOutNameLen] = '\0';
209  bufptr += remoteOutNameLen;
210  }
211  else {
212  if (((*remote_out_logfile_name) = new char[2]) == NULL) {
213  fprintf(stderr, "vrpn_Auxiliary_Logger::unpack_log_message_from_"
214  "buffer: Out of memory\n");
215  return false;
216  }
217  (*remote_out_logfile_name)[0] = '\0';
218  }
219 
220  return true;
221 }
222 
224  vrpn_Connection *c)
225  : vrpn_Auxiliary_Logger(name, c)
226 {
227  // Register a handler for the dropped last connection message.
230  if (dropped_last_connection_m_id == -1) {
231  fprintf(stderr, "vrpn_Auxiliary_Logger_Server::vrpn_Auxiliary_Logger_"
232  "Server: can't register dropped last connection "
233  "type\n");
234  d_connection = NULL;
235  return;
236  }
239  this, vrpn_ANY_SENDER)) {
240  fprintf(stderr, "vrpn_Auxiliary_Logger_Server::vrpn_Auxiliary_Logger_"
241  "Server: can't register dropped last connection "
242  "handler\n");
243  d_connection = NULL;
244  }
245 
246  // Register a handler for the request logging message.
249  d_sender_id)) {
250  fprintf(stderr, "vrpn_Auxiliary_Logger_Server::vrpn_Auxiliary_Logger_"
251  "Server: can't register logging request handler\n");
252  d_connection = NULL;
253  }
254 
255  // Register a handler for the request logging-status message
258  d_sender_id)) {
259  fprintf(stderr, "vrpn_Auxiliary_Logger_Server::vrpn_Auxiliary_Logger_"
260  "Server: can't register logging-status request "
261  "handler\n");
262  d_connection = NULL;
263  }
264 }
265 
266 // This handles the last dropped connection message by turning off all
267 // logging.
269 {
270  handle_request_logging("", "", "", "");
271 }
272 
273 /* static */
274 // This method just passes the call on to the virtual function.
276  void *userdata, vrpn_HANDLERPARAM /*p*/)
277 {
279  static_cast<vrpn_Auxiliary_Logger_Server *>(userdata);
281  return 0;
282 }
283 
284 /* static */
286  void *userdata, vrpn_HANDLERPARAM /*p*/)
287 {
289  static_cast<vrpn_Auxiliary_Logger_Server *>(userdata);
291  return 0;
292 }
293 
294 /* static */
295 // This method just parses the raw data in the Handlerparam to produce strings
296 // and then
297 // passes the call on to the virtual function.
299  void *userdata, vrpn_HANDLERPARAM p)
300 {
302  static_cast<vrpn_Auxiliary_Logger_Server *>(userdata);
303  char *localInName = NULL, *localOutName = NULL, *remoteInName = NULL,
304  *remoteOutName = NULL;
305 
306  // Attempt to unpack the names from the buffer
308  &localInName, &localOutName,
309  &remoteInName, &remoteOutName)) {
310  fprintf(stderr, "vrpn_Auxiliary_Logger_Server::static_handle_request_"
311  "logging: Could not unpack buffer\n");
312  return -1;
313  }
314 
315  // Call the virtual function with the strings, then clean up memory and
316  // return.
317  me->handle_request_logging(localInName, localOutName, remoteInName,
318  remoteOutName);
319  if (localInName) {
320  delete[] localInName;
321  };
322  if (localOutName) {
323  delete[] localOutName;
324  };
325  if (remoteInName) {
326  delete[] remoteInName;
327  };
328  if (remoteOutName) {
329  delete[] remoteOutName;
330  };
331  return 0;
332 }
333 
335  const char *logger_name, const char *connection_to_log, vrpn_Connection *c)
336  : vrpn_Auxiliary_Logger_Server(logger_name, c)
337  , d_connection_name(NULL)
338  , d_logging_connection(NULL)
339 {
340  // Copy the name of the connection to log and its NULL terminator.
341  if ((connection_to_log == NULL) || (strlen(connection_to_log) == 0)) {
342  fprintf(stderr, "vrpn_Auxiliary_Logger_Server_Generic::vrpn_Auxiliary_"
343  "Logger_Server_Generic: Empty logging name passed "
344  "in\n");
345  d_connection = NULL;
346  return;
347  }
348  d_connection_name = new char[strlen(connection_to_log) + 1];
349  if (d_connection_name == NULL) {
350  fprintf(stderr, "vrpn_Auxiliary_Logger_Server_Generic::vrpn_Auxiliary_"
351  "Logger_Server_Generic: Out of memory\n");
352  d_connection = NULL;
353  return;
354  }
355  memcpy(d_connection_name, connection_to_log, strlen(connection_to_log) + 1);
356 }
357 
359 {
360  if (d_logging_connection) {
361  delete d_logging_connection;
362  d_logging_connection = NULL;
363  }
364 
365  if (d_connection_name) {
366  delete[] d_connection_name;
367  d_connection_name = NULL;
368  }
369 }
370 
371 // Close an existing logging connection, then (if any of the file
372 // names are non-empty) open a new logging connection to the
373 // connection we are to log (even if this process already has a
374 // connection to it) and then send back the report that we've started
375 // logging if we are able. If we cannot open it, then fill in all
376 // blank names for the return report.
378  const char *local_in_logfile_name, const char *local_out_logfile_name,
379  const char *remote_in_logfile_name, const char *remote_out_logfile_name)
380 {
381  // If we have a logging connection open, reduce its reference
382  // count (which may delete it but will leave it going if some
383  // other object has a pointer to it).
384  if (d_logging_connection) {
386  d_logging_connection = NULL;
387  }
388 
389  // If at least one of the names passed in is not empty, create
390  // a new logging connection. If this fails, report no logging.
391 
392  // Find the relevant part of the name (skip past last '@'
393  // if there is one); also find the port number.
394  const char *cname = d_connection_name;
395  const char *where_at; // Part of name past last '@'
396  if ((where_at = strrchr(cname, '@')) != NULL) {
397  cname = where_at + 1; // Chop off the front of the name
398  }
399 
400  // Pass "true" to force_connection so that it will open a new
401  // connection even if we already have one with that name.
403  where_at, local_in_logfile_name, local_out_logfile_name,
404  remote_in_logfile_name, remote_out_logfile_name, NULL, true);
406  struct timeval now;
407  vrpn_gettimeofday(&now, NULL);
408  send_text_message("handle_request_logging: Could not create connection "
409  "(files already exist?)",
410  now, vrpn_TEXT_ERROR);
411  send_report_logging(NULL, NULL, NULL, NULL);
412  if (d_logging_connection) {
413  delete d_logging_connection;
414  d_logging_connection = NULL;
415  }
416  return;
417  }
418 
419  // Report the logging that we're doing.
420  send_report_logging(local_in_logfile_name, local_out_logfile_name,
421  remote_in_logfile_name, remote_out_logfile_name);
422 }
423 
425 {
426  char *local_in;
427  char *local_out;
428  char *remote_in;
429  char *remote_out;
430  d_logging_connection->get_log_names(&local_in, &local_out, &remote_in,
431  &remote_out);
432  send_report_logging(local_in, local_out, remote_in, remote_out);
433  if (local_in) delete[] local_in;
434  if (local_out) delete[] local_out;
435  if (remote_in) delete[] remote_in;
436  if (remote_out) delete[] remote_out;
437 }
438 
440 {
441  if (d_connection) {
443  client_mainloop();
444  }
445 }
446 
448  vrpn_Connection *c)
449  : vrpn_Auxiliary_Logger(name, c)
450 {
451  // Register a handler for the report callback from this device,
452  // if we got a connection.
453  if (d_connection != NULL) {
455  handle_report_message, this,
456  d_sender_id)) {
457  fprintf(stderr,
458  "vrpn_Auxiliary_Logger_Remote: can't register handler\n");
459  d_connection = NULL;
460  }
461  }
462  else {
463  fprintf(stderr,
464  "vrpn_Auxiliary_Logger_Remote: Can't get connection!\n");
465  }
466 }
467 
468 /* Static */
469 int VRPN_CALLBACK
472 {
474  static_cast<vrpn_Auxiliary_Logger_Remote *>(userdata);
475  char *localInName = NULL, *localOutName = NULL, *remoteInName = NULL,
476  *remoteOutName = NULL;
477 
478  // Attempt to unpack the names from the buffer
480  &localInName, &localOutName,
481  &remoteInName, &remoteOutName)) {
482  fprintf(stderr, "vrpn_Auxiliary_Logger_Remote::handle_report_message: "
483  "Could not unpack buffer\n");
484  return -1;
485  }
486 
487  // Fill in the data type for the callback handlers.
488  vrpn_AUXLOGGERCB cs;
489  cs.msg_time = p.msg_time;
490  cs.local_in_logfile_name = localInName;
491  cs.local_out_logfile_name = localOutName;
492  cs.remote_in_logfile_name = remoteInName;
493  cs.remote_out_logfile_name = remoteOutName;
494 
495  // Go down the list of callbacks that have been registered.
496  // Fill in the parameter and call each.
498 
499  // Clean up memory and return.
500  if (localInName) {
501  delete[] localInName;
502  };
503  if (localOutName) {
504  delete[] localOutName;
505  };
506  if (remoteInName) {
507  delete[] remoteInName;
508  };
509  if (remoteOutName) {
510  delete[] remoteOutName;
511  };
512  return 0;
513 }
virtual int mainloop(const struct timeval *timeout=NULL)=0
Call each time through program main loop to handle receiving any incoming messages and sending any pa...
const char * local_out_logfile_name
struct timeval msg_time
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)
virtual void mainloop(void)
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
VRPN_API int vrpn_unbuffer(const char **buffer, timeval *t)
Utility routine for taking a struct timeval from a buffer that was sent as a message.
Definition: vrpn_Shared.C:312
virtual void handle_request_logging_status()=0
const vrpn_uint32 vrpn_CONNECTION_RELIABLE
Classes of service for messages, specify multiple by ORing them together Priority of satisfying these...
vrpn_int32 payload_len
void client_mainloop(void)
Handles functions that all clients should provide in their mainloop() (warning of no server...
virtual int register_types(void)
Register the types of messages this device sends/receives. Return 0 on success, -1 on fail...
const char * buffer
const char * remote_out_logfile_name
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
virtual vrpn_bool doing_okay(void) const
Returns vrpn_true if the connection is okay, vrpn_false if not.
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)
Generic connection class not specific to the transport mechanism.
vrpn_Auxiliary_Logger(const char *name, vrpn_Connection *c)
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)
#define VRPN_CALLBACK
vrpn_Auxiliary_Logger_Server(const char *name, vrpn_Connection *c)
const char * vrpn_dropped_last_connection
virtual int init(void)
Initialize things that the constructor can&#39;t. Returns 0 on success, -1 on failure.
static int VRPN_CALLBACK static_handle_request_logging_status(void *userdata, vrpn_HANDLERPARAM p)
int register_autodeleted_handler(vrpn_int32 type, vrpn_MESSAGEHANDLER handler, void *userdata, vrpn_int32 sender=vrpn_ANY_SENDER)
Registers a handler with the connection, and remembers to delete at destruction.
vrpn_Connection * d_connection
Connection that this object talks to.
vrpn_Callback_List< vrpn_AUXLOGGERCB > d_callback_list
This structure is what is passed to a vrpn_Connection message callback.
virtual int pack_message(vrpn_uint32 len, struct timeval time, vrpn_int32 type, vrpn_int32 sender, const char *buffer, vrpn_uint32 class_of_service)
Pack a message that will be sent the next time mainloop() is called. Turn off the RELIABLE flag if yo...
static int VRPN_CALLBACK static_handle_request_logging(void *userdata, vrpn_HANDLERPARAM p)
int send_text_message(const char *msg, struct timeval timestamp, vrpn_TEXT_SEVERITY type=vrpn_TEXT_NORMAL, vrpn_uint32 level=0)
Sends a NULL-terminated text message from the device d_sender_id.
const char * local_in_logfile_name
static int VRPN_CALLBACK handle_report_message(void *userdata, vrpn_HANDLERPARAM p)
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)
#define vrpn_gettimeofday
Definition: vrpn_Shared.h:89
vrpn_Connection * vrpn_get_connection_by_name(const char *cname, const char *local_in_logfile_name, const char *local_out_logfile_name, const char *remote_in_logfile_name, const char *remote_out_logfile_name, const char *NIC_IPaddress, bool force_connection)
Create a client connection of arbitrary type (VRPN UDP/TCP, TCP, File, Loopback, MPI).
VRPN_API int vrpn_buffer(char **insertPt, vrpn_int32 *buflen, const timeval t)
Utility routine for placing a timeval struct into a buffer that is to be sent as a message...
Definition: vrpn_Shared.C:241
virtual void handle_dropped_last_connection(void)
Class from which all user-level (and other) classes that communicate with vrpn_Connections should der...
static int VRPN_CALLBACK static_handle_dropped_last_connection(void *userdata, vrpn_HANDLERPARAM p)
vrpn_int32 d_sender_id
Sender ID registered with the connection.
void get_log_names(char **local_in_logname, char **local_out_logname, char **remote_in_logname, char **remote_out_logname)
This function returns the logfile names of this connection in the parameters. It will allocate memory...
vrpn_Auxiliary_Logger_Remote(const char *name, vrpn_Connection *c=NULL)
virtual vrpn_int32 register_message_type(const char *name)
void call_handlers(const CALLBACK_STRUCT &info)
This will pass the referenced parameter as a const to all the callbacks.
vrpn_Auxiliary_Logger_Server_Generic(const char *logger_name, const char *connection_to_log, vrpn_Connection *c=NULL)
const int vrpn_ANY_SENDER
vrpn_ANY_SENDER can be used to register callbacks on a given message type from any sender...
const char * remote_in_logfile_name