vrpn 07.35
Virtual Reality Peripheral Network
Loading...
Searching...
No Matches
vrpn_ForwarderController.C
Go to the documentation of this file.
1#include <stdio.h> // for fprintf, stderr
2#include <string.h> // for memcpy, strlen, NULL, etc
3
4#include "vrpn_Connection.h" // for vrpn_Connection, etc
6#include "vrpn_Shared.h" // for timeval, vrpn_gettimeofday
7#if !(defined(_WIN32) && defined(VRPN_USE_WINSOCK_SOCKETS))
8#include <netinet/in.h> // for htonl, ntohl
9#endif
10
11#include "vrpn_Forwarder.h" // for vrpn_ConnectionForwarder
12
14 : d_connection(c)
15 , d_myId(-1)
16{
17
18 if (!c) return;
19
21
22 d_myId = c->register_sender("vrpn_Forwarder_Brain");
23
25 c->register_message_type("vrpn_Forwarder_Brain start_forwarding");
26 d_forward_type = c->register_message_type("vrpn_Forwarder_Brain forward");
27}
28
30{
31
32 if (d_connection) {
34 }
35}
36
37// static
38char *
40 vrpn_int32 remote_port)
41{
42 char *outbuf;
43
44 vrpn_int32 nPort;
45
46 *length = sizeof(vrpn_int32);
47 try { outbuf = new char[*length]; }
48 catch (...) {
49 *length = 0;
50 return NULL;
51 }
52
53 nPort = htonl(remote_port);
54 memcpy(outbuf, &nPort, sizeof(vrpn_int32));
55
56 return outbuf;
57}
58
59// static
61 const char *buffer, vrpn_int32 *remote_port)
62{
63 vrpn_int32 port;
64
65 if (!buffer || !remote_port) return;
66
67 memcpy(&port, buffer, sizeof(vrpn_int32));
68 *remote_port = ntohl(port);
69}
70
71// static
73 vrpn_int32 *length, vrpn_int32 remote_port, const char *service_name,
74 const char *message_type)
75{
76 char *outbuf;
77
78 vrpn_int32 nPort;
79 vrpn_int32 nSLen;
80 vrpn_int32 nTLen;
81
82 if (!service_name || !message_type) { *length = 0; return NULL; }
83 *length = static_cast<int>(3 * sizeof(vrpn_int32) + strlen(service_name) +
84 strlen(message_type));
85 try { outbuf = new char[*length]; }
86 catch (...) {
87 *length = 0;
88 return NULL;
89 }
90
91 // fprintf(stderr, "Encoding forward %s of %s on port %d.\n",
92 // message_type, service_name, remote_port);
93
94 // Put all the char [] at the end of the message so we don't have to
95 // worry about padding and alignment.
96
97 nPort = htonl(remote_port);
98 nSLen = htonl(static_cast<vrpn_int32>(strlen(service_name)));
99 nTLen = htonl(static_cast<vrpn_int32>(strlen(message_type)));
100 memcpy(outbuf, &nPort, sizeof(vrpn_int32));
101 memcpy(outbuf + sizeof(vrpn_int32), &nSLen, sizeof(vrpn_int32));
102 memcpy(outbuf + 2 * sizeof(vrpn_int32), &nTLen, sizeof(vrpn_int32));
103 strcpy(outbuf + 3 * sizeof(vrpn_int32), service_name);
104 strcpy(outbuf + 3 * sizeof(vrpn_int32) + strlen(service_name),
105 message_type);
106
107 return outbuf;
108}
109
110// static
112 vrpn_int32 *remote_port,
113 char **service_name,
114 char **message_type)
115{
116 vrpn_int32 port;
117 vrpn_int32 Slength;
118 vrpn_int32 Tlength;
119 char *Soutbuf;
120 char *Toutbuf;
121
122 if (!buffer || !remote_port || !message_type) return;
123
124 // All the char [] are at the end of the message so we don't have to
125 // worry about padding and alignment.
126
127 memcpy(&port, buffer, sizeof(vrpn_int32));
128 *remote_port = ntohl(port);
129 memcpy(&Slength, buffer + sizeof(vrpn_int32), sizeof(vrpn_int32));
130 Slength = ntohl(Slength);
131 try { Soutbuf = new char[1 + Slength]; }
132 catch (...) {
133 *remote_port = -1;
134 *service_name = NULL;
135 *message_type = NULL;
136 return;
137 }
138 memcpy(&Tlength, buffer + 2 * sizeof(vrpn_int32), sizeof(vrpn_int32));
139 Tlength = ntohl(Tlength);
140 try { Toutbuf = new char[1 + Tlength]; }
141 catch (...) {
142 *remote_port = -1;
143 *service_name = NULL;
144 *message_type = NULL;
145 return;
146 }
147 strncpy(Soutbuf, buffer + 3 * sizeof(vrpn_int32), Slength);
148 Soutbuf[Slength] = '\0';
149 *service_name = Soutbuf;
150 strncpy(Toutbuf, buffer + 3 * sizeof(vrpn_int32) + Slength, Tlength);
151 Toutbuf[Tlength] = '\0';
152 *message_type = Toutbuf;
153}
154
157 , d_myForwarders(NULL)
158{
159
160 if (!c) return;
161
162 c->register_handler(d_start_forwarding_type, handle_start, this, d_myId);
163 c->register_handler(d_forward_type, handle_forward, this, d_myId);
164}
165
167{
168
169 if (!d_connection) return;
170
172 this, d_myId);
173 d_connection->unregister_handler(d_forward_type, handle_forward, this,
174 d_myId);
175
176 // Destroy my list of forwarders
178 for (fp = d_myForwarders; fp; fp = fp->next) {
179 if (fp->connection) {
180 try {
181 delete fp->connection;
182 } catch (...) {
183 fprintf(stderr, "vrpn_Forwarder_Server::~vrpn_Forwarder_Server(): delete failed\n");
184 return;
185 }
186 }
187 if (fp->forwarder) {
188 try {
189 delete fp->forwarder;
190 } catch (...) {
191 fprintf(stderr, "vrpn_Forwarder_Server::~vrpn_Forwarder_Server(): delete failed\n");
192 return;
193 }
194 }
195 }
196}
197
199{
200
202
203 for (fp = d_myForwarders; fp; fp = fp->next)
204 if (fp->connection) fp->connection->mainloop();
205}
206
207vrpn_bool vrpn_Forwarder_Server::start_remote_forwarding(vrpn_int32 remote_port)
208{
210
211 // Make sure it isn't already there
212
213 for (fp = d_myForwarders; fp; fp = fp->next)
214 if (fp->port == remote_port) {
215 fprintf(stderr, "vrpn_Forwarder_Server::start_remote_forwarding: "
216 "Already open on port %d.\n",
217 remote_port);
218 return false;
219 }
220
221 // Create it and add it to the list
222
223 try { fp = new vrpn_Forwarder_List; }
224 catch (...) {
225 fprintf(stderr, "vrpn_Forwarder_Server::start_remote_forwarding: "
226 "Out of memory.\n");
227 return false;
228 }
229
230 fp->port = remote_port;
231 fp->connection = vrpn_create_server_connection(remote_port);
233 catch (...) {
234 fprintf(stderr, "vrpn_Forwarder_Server::start_remote_forwarding: "
235 "Out of memory.\n");
236 return false;
237 }
238
239 fp->next = d_myForwarders;
240 d_myForwarders = fp;
241
242 // fprintf(stderr, "vrpn_Forwarder_Server::start_remote_forwarding: "
243 //"On port %d.\n", remote_port);
244 return true;
245}
246
248 const char *service_name,
249 const char *message_type)
250{
251
253 vrpn_Forwarder_List *it = NULL;
254 int retval;
255
256 // Find the forwarder requested
257
258 for (fp = d_myForwarders; fp; fp = fp->next)
259 if (fp->port == remote_port) it = fp;
260
261 if (!it) {
262 fprintf(stderr,
263 "vrpn_Forwarder_Server: No forwarder open on port %d.\n",
264 remote_port);
265 return;
266 }
267
268 // Forward that message type from that service
269
270 retval = it->forwarder->forward(message_type, service_name, message_type,
271 service_name);
272 if (retval) {
273 fprintf(stderr, "vrpn_Forwarder_Server: Couldn't forward messages of "
274 "type \"%s\" on port %d.\n",
275 message_type, remote_port);
276 return;
277 }
278}
279
280// static
281int vrpn_Forwarder_Server::handle_start(void *userdata, vrpn_HANDLERPARAM p)
282{
284 vrpn_int32 port;
285
287 me->start_remote_forwarding(port);
288 return 0;
289}
290
291// static
292int vrpn_Forwarder_Server::handle_forward(void *userdata, vrpn_HANDLERPARAM p)
293{
295 vrpn_int32 port;
296 char *typebuffer;
297 char *servicebuffer;
298
299 decode_forward_message_type(p.buffer, &port, &servicebuffer, &typebuffer);
300 if (!servicebuffer || !typebuffer) return -1; // memory allocation failure
301 me->forward_message_type(port, servicebuffer, typebuffer);
302
303 try {
304 delete[] servicebuffer;
305 delete[] typebuffer;
306 } catch (...) {
307 fprintf(stderr, "vrpn_Forwarder_Server::handle_forward(): delete failed\n");
308 return -1;
309 }
310 return 0;
311}
312
315{
316}
317
319
321{
322
323 struct timeval now;
324 char *buffer;
325 vrpn_int32 length;
326
327 vrpn_gettimeofday(&now, NULL);
328 buffer = encode_start_remote_forwarding(&length, remote_port);
329
330 if (!buffer) return false; // memory allocation failure
331
334 try {
335 delete[] buffer;
336 } catch (...) {
337 fprintf(stderr, "vrpn_Forwarder_Server::start_remote_forwarding(): delete failed\n");
338 return false;
339 }
340 return ret == 0;
341}
342
344 const char *service_name,
345 const char *message_type)
346{
347 struct timeval now;
348 char *buffer;
349 vrpn_int32 length;
350
351 vrpn_gettimeofday(&now, NULL);
352 buffer = encode_forward_message_type(&length, remote_port, service_name,
353 message_type);
354
355 if (!buffer) return; // memory allocation failure
356
357 d_connection->pack_message(length, now, d_forward_type, d_myId, buffer,
359 try {
360 delete[] buffer;
361 } catch (...) {
362 fprintf(stderr, "vrpn_Forwarder_Server::forward_message_type(): delete failed\n");
363 return;
364 }
365}
int forward(const char *sourceName, const char *sourceServiceName, const char *destinationName, const char *destinationServiceName, vrpn_uint32 classOfService=vrpn_CONNECTION_RELIABLE)
Generic connection class not specific to the transport mechanism.
void addReference()
Counting references to this connection.
virtual vrpn_int32 register_message_type(const char *name)
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...
virtual vrpn_int32 register_sender(const char *name)
Get a token to use for the string name of the sender or type. Remember to check for -1 meaning failur...
virtual int unregister_handler(vrpn_int32 type, vrpn_MESSAGEHANDLER handler, void *userdata, vrpn_int32 sender=vrpn_ANY_SENDER)
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...
virtual int register_handler(vrpn_int32 type, vrpn_MESSAGEHANDLER handler, void *userdata, vrpn_int32 sender=vrpn_ANY_SENDER)
Set up (or remove) a handler for a message of a given type. Optionally, specify which sender to handl...
vrpn_Connection * d_connection
vrpn_Forwarder_Brain(vrpn_Connection *)
static char * encode_start_remote_forwarding(vrpn_int32 *length, vrpn_int32 remote_port)
static void decode_forward_message_type(const char *buffer, vrpn_int32 *remote_port, char **service_name, char **message_type)
static void decode_start_remote_forwarding(const char *buffer, vrpn_int32 *remote_port)
static char * encode_forward_message_type(vrpn_int32 *length, vrpn_int32 remote_port, const char *service_name, const char *message_type)
virtual vrpn_bool start_remote_forwarding(vrpn_int32 remote_port)
vrpn_Forwarder_Controller(vrpn_Connection *)
virtual void forward_message_type(vrpn_int32 remote_port, const char *service_name, const char *message_type)
virtual void forward_message_type(vrpn_int32 remote_port, const char *service_name, const char *message_type)
vrpn_Forwarder_Server(vrpn_Connection *)
virtual vrpn_bool start_remote_forwarding(vrpn_int32 remote_port)
vrpn_Forwarder_List * d_myForwarders
vrpn_Forwarder_List * next
vrpn_ConnectionForwarder * forwarder
vrpn_Connection * connection
This structure is what is passed to a vrpn_Connection message callback.
const char * buffer
vrpn_Connection * vrpn_create_server_connection(const char *cname, const char *local_in_logfile_name, const char *local_out_logfile_name)
Create a server connection of arbitrary type (VRPN UDP/TCP, TCP, File, Loopback, MPI).
const vrpn_uint32 vrpn_CONNECTION_RELIABLE
Classes of service for messages, specify multiple by ORing them together Priority of satisfying these...
class VRPN_API vrpn_ConnectionForwarder
#define vrpn_gettimeofday
Definition: vrpn_Shared.h:99