VRPN 06.04

VRPN main page

Obtaining VRPN

VRPN Support

Installing and Testing

Compiling and Modifying

Client code

Server code

Troubleshooting

Connections

Logging and Playback

Shared Objects

Sound

Clock Synchronization

Text Messages

Doxygen documentation

VRPN on PDAs

Coming attractions & suggestions

UNC-specific information

Registering a callback handler

A vrpn_Connection delivers messages using callback routines. Devices should usually register interest in messages whose sender matches theirs for each type of message they generate. The call to register a callback function to a connection using its register_handler() method::

	virtual int register_handler(long type, vrpn_MESSAGEHANDLER handler,
				     void *userdata, long sender = vrpn_ANY_SENDER);

The type and sender parameters are the tokens received when they were registered. These are used to filter messages so the handler is called only for messages of the appropriate type from the specified sender. The default sender matches any sender, so will deliver all messages of that type.

The userdata parameter is passed to the handler procedure; if non-NULL, it should point to a structure containing information that the callback handler will use to process the message (more on this below).

The handler parameter is the name of the function that is to be called when a message of the specified type is received. It must be of the type vrpn_MESSAGEHANDLER:

	typedef	int (*vrpn_MESSAGEHANDLER)(void *userdata, vrpn_HANDLERPARAM p);

This is a function that takes two parameters. The first is the userdata parameter that will be set to the value that was specified when the callback handler was installed. Normally, this will be typecast into a pointer to either a class or a structure that contains information that the handler needs to know in order to process the messages. For example, it may be a pointer to a transformation matrix that is to be filled in from a tracker report.

The second parameter passed to the callback handler is a structure that contains information about the message and the message itself:

	typedef	struct {
		long		type;
		long		sender;
		struct timeval	msg_time;
		int		payload_len;
		const char	*buffer;
	} vrpn_HANDLERPARAM;

The type and sender parameters are those specified by the routine that called pack_message(), translated into their local values by the local connection object. These parameters can often be ignored by a handler, as it will only be called for the type and sender that it was specified to receive. If one handler was installed for multiple message types or senders, then these fields will be helpful.

The msg_time parameter is the one specified by the routine that called pack_message(). This is the time according to the sender's clock. A future implementation may synchronize clocks between the two ends of a connection, in which case this may in the future be translated into the clock on the local machine.

The buffer points to the actual message, which is of payload_len length. This is the message exactly as sent to pack_message(). This should be an architecture-independent representation, in case the byte order or other data representations (structure packing, floating-point format, alignment constraints) differ between the sender and receiver, which may be on different architectures. VRPN guarantees that the message will start on a 4-byte boundary. The sender and receiver of a message need to agree on the message format.

The handler routine should return 0 on success and -1 on failure. Failure means failure to parse the message, which indicates a faulty connection, so the connection will be shut down.

Example

The following code will open a connection, describe a sender and type, and register a callback handler. This example has not been compiled and tested, but hopefully there are no bugs. This example will read the messages generated by the example of sending a message and print them. This example is for a server-based system. A client would use vrpn_get_connection_by_name() rather than 'new vrpn_Connection()', as described under getting a connection.

	int my_handler(void *userdata, vrpn_HANDLERPARAM p) {
		char	*prompt = (char*)userdata;	// Type-cast to the right type

		printf("%s:%s\n", prompt, p.;buffer);	// Assume it's a string message
		return 0;
	}

	main() {
		vrpn_Connection *connection = new vrpn_Connection();
		long my_type = connection->register_message_type("Test_type");
		long my_id = connection->register_sender("Test0");

		connection->register_handler(my_type, my_handler,
					 (void*)"Test message", my_id);

		while (1) connection->mainloop();
	}