Newer
Older
/* Original Author: Kris Burney & Jake Drahos
* Last Edits: Matthew Kelly & Dane Larson
* Interface between Quad, front end, Virtual and VRPN tracker.
* Main uses a standard socket select loop to receive data from any
* source described above. Based on the data received from sockets it
* calls receive functions based on the socket received from.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/select.h>
ucart
committed
//#include <bluetooth/bluetooth.h> Bluetooth not currently used
//#include <bluetooth/rfcomm.h> Bluetooth not currently used
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <netinet/tcp.h>
#include <fcntl.h>
#include <sys/stat.h>
#include "packet.h"
#include "param.h"
#include "source.h"
#include "output.h"
#include "bitwise.h"
#include "backend_adapter.h"
#include "backend_utils.h"
/* Backend-internal command magics */
#define TD_MAGIC "TRACKERDATA"
// function prototypes
void readAndPrint(void);
void sendVrpnPacket(struct ucart_vrpn_TrackerData *);
void getVRPNPacket(struct ucart_vrpn_TrackerData *);
void printVrpnData(struct ucart_vrpn_TrackerData *);
int safe_fd_set(int , fd_set* , int* );
int safe_fd_clr(int , fd_set* , int* );
static void safe_close_fd(int fd, pthread_mutex_t *mutexLock);
static void cb(struct ucart_vrpn_TrackerData *);
/* Return index of client, or -1 */
static ssize_t get_client_index(int fd);
/* Returns pointer to client buffer, or -1 */
static char * get_client_buffer(int fd);
/* Return pointer to client pending responses, or -1*/
static int * get_client_pend_responses(int fd);
/* Return positive integer if successful, -1 otherwise */
static int clientAddPendResponses(int fd, uint16_t packet_id);
/* Return positive integer if successful, -1 otherwise */
static int clientRemovePendResponses(int fd, uint16_t packet_id);
/* Receive data from client */
static void client_recv(int fd);
/* Checks to see if socket has disconnected. Returns 1 on disconnect, else returns 0 */
static int wasDisconnected(int fd);
/* handle controller responses from quad to frontend */
static void handleResponse(struct metadata *m, uint8_t * data);
static ssize_t readQuad(char * buf, size_t count, int index);
static ssize_t writeQuad(const uint8_t * buf, size_t count);
static ssize_t writeQuadIndex(const uint8_t * buf, size_t count, int index);
static int local_comm_channel;
#define MAX_CLIENTS 32
#define CLIENT_BUFFER_SIZE 1024
#define CLIENT_MAX_PENDING_RESPONSES 15
static char client_buffers[MAX_CLIENTS][CLIENT_BUFFER_SIZE];
static int client_fds[MAX_CLIENTS];
static int client_pending_responses[MAX_CLIENTS][CLIENT_MAX_PENDING_RESPONSES];
static char user_specified_log_name[256] = "";
static void sig_handler(int s) {
printf("Caught SIGPIPE from quad fifo..\n");
}
/**
* Handler function for exit signals. This allows the backend to properly close.
*/
static void sig_exit_handler(int s) {
printf("Exiting with condition %d\n", s);
keepRunning = 0;
// Currently doing much more than it should. It will be slimmed down
// in the future.
static void cb(struct ucart_vrpn_TrackerData * td) {
static int count = 0;
sendVrpnPacket(td);
count++;
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
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
int activity;
int i,j;
//Setup exit signals
signal(SIGINT, sig_exit_handler);
signal(SIGABRT, sig_exit_handler);
signal(SIGQUIT, sig_exit_handler);
signal(SIGTERM, sig_exit_handler);
FD_ZERO(&rfds_master);
/* Determine socket path */
char * backend_socket_path = DEFAULT_SOCKET;
if (getenv(SOCKET_ENV)) {
backend_socket_path = getenv(SOCKET_ENV);
}
/* Unlink if it exists */
unlink(backend_socket_path);
/* Create socket */
mode_t old_umask = umask(0111);
backendSocket = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0);
if (backendSocket < 0) {
err(-1, "socket");
}
printf("backendSocket = %d\n", backendSocket);
/* Create sockaddr and bind */
struct sockaddr_un sa;
sa.sun_family = AF_UNIX;
strncpy(sa.sun_path, backend_socket_path, 107);
sa.sun_path[107] = '\0';
if (bind(backendSocket, (struct sockaddr *) &sa, sizeof(sa))) {
err(-1, "bind");
}
umask(old_umask);
/* Listen */
if (listen(backendSocket, 16)) {
err(-1, "listen");
}
/* Add to socket set */
safe_fd_set(backendSocket, &rfds_master, &max_fd);
/* Initialize client buffers */
for (i = 0; i < MAX_CLIENTS; i++) {
client_fds[i] = -1;
client_buffers[i][0] = '\n';
for(int j = 0; j < CLIENT_MAX_PENDING_RESPONSES; j++) {
client_pending_responses[i][j] = -1;
}
}
//Socket and communication setup
for (i = 0; i < NUM_TRACKABLES; i++) {
//Lock the trackable communication mutex
if (pthread_mutex_lock(&(trackables[i].socket_mutex))) {
err(-2, "pthread_mutex_lock (%s:%d):", __FILE__, __LINE__);
}
//Check for trackable type
if (trackables[i].isAdapter == 0) {
if ((trackables[i].socket = connectToZybo(i)) < 0) {
perror("Error connecting to Quad...");
break;
}
if (!local_comm_channel) {
//if (trackables[i].isLocal == 0) {
printf("zyboSocket = %d\n", trackables[i].socket);
} else {
signal(SIGPIPE, sig_handler);
printf("zybo_fifo_rx = %d\nzybo_fifo_tx = %d\n", trackables[i].fifo_rx, trackables[i].fifo_tx);
}
} else {
printf("Starting client socket: %s\n", trackables[i].name);
if (adapterConnect(&(trackables[i])) != 0) {
perror("Error connecting to Adapter...");
break;
}
}
//Unlock the trackable communication mutex
if (pthread_mutex_unlock(&(trackables[i].socket_mutex))) {
err(-2, "pthread_mutex_unlock (%s:%d):", __FILE__, __LINE__);
}
}
if (i != NUM_TRACKABLES) {
for (j = 0; j < (i-1); j++) {
if (trackables[j].isAdapter == 1) {
adapterDisconnect(&(trackables[j]));
}
//else if (trackables[j].isLocal == 1) {
else if (local_comm_channel) {
safe_close_fd(trackables[j].fifo_rx, &trackables[j].socket_mutex);
safe_close_fd(trackables[j].fifo_tx, &trackables[j].socket_mutex);
}
else {
if (!getenv(NOQUAD_ENV)) {
safe_close_fd(trackables[j].socket, &trackables[j].socket_mutex);
}
}
}
exit(1);
}
// watch for input from stdin (fd 0) to see when it has input
safe_fd_set(fileno(stdin), &rfds_master, &max_fd);
//Setup safe fd set for all trackables
for (i = 0; i < NUM_TRACKABLES; i++) {
if (trackables[i].isAdapter == 0) {
if (!getenv(NOQUAD_ENV)) {
// watch for input from the zybo socket
safe_fd_set(trackables[i].socket, &rfds_master, &max_fd);
}
} else {
// watch for input from the adapter sockets
safe_fd_set(trackables[i].socket, &rfds_master, &max_fd);
}
}
//Check for a user specified log name
if(argc >= 2) {
strncat(user_specified_log_name, argv[1], strlen(argv[1]));
}
//Create VRPN trackers if using environment variable not set
if(!getenv(NOVRPN_ENV)){
printf("Creating VRPN trackers...\n");
for (i = 0; i < NUM_TRACKABLES; i++) {
//create vrpnTracker instance
trackables[i].tracker = ucart_vrpn_tracker_createInstance(trackables[i].server_name);
// this function will be called whenever tracker receives data
ucart_vrpn_tracker_addCallback(trackables[i].tracker, cb);
}
//TODO - remove tracker instance
tracker = trackables[0].tracker;
printf("Attempting to Start VRPN thread... ");
if (ucart_vrpn_start()) {
warnx("Failed\n");
}
else {
printf("Success\n");
}
} else {
printf("Ignoring VRPN information...\n");
}
struct timeval timeout = {
.tv_sec = 1,
.tv_usec = 0
};
//Main backend loop
while(keepRunning) {
fd_set rfds;
rfds = rfds_master;
activity = select(max_fd+1, &rfds, NULL, NULL, NULL);
if(activity == -1) {
perror("select() ");
} else if (activity) {
for(int fd = 0; fd <= max_fd; ++fd) {
if (FD_ISSET(fd, &rfds)) {
if(wasDisconnected(fd)){
break;
}
if (fd == fileno(stdin)) {
/**
* Ignore stdin from the backend
*/
} else if (fd == backendSocket) {
int new_fd = 0;
new_fd = accept(backendSocket, NULL, NULL);
if (new_fd < 0) {
warn("accept");
} else {
printf("Connection\n");
if (new_client(new_fd)) {
printf("Added client\n");
safe_fd_set(new_fd, &rfds_master, &max_fd);
}
}
} else if (get_client_index(fd) > -1) {
/* It is a socket to a frontend */
client_recv(fd);
} else {
for (i = 0; i < NUM_TRACKABLES; i++) {
if (fd == trackables[i].socket) {
quad_recv(i);
}
}
}
}
}
} else {
timeout.tv_sec = 1;
timeout.tv_usec = 0;
}
}
// Free VRPN trackers and stop VRPN Tracker Thread
if(!getenv(NOVRPN_ENV)){
if (ucart_vrpn_stop()) {
warnx("VRPN thread stop failed...\n");
} else {
printf("VRPN thread stopped\n");
}
for (i = 0; i < NUM_TRACKABLES; i++) {
ucart_vrpn_tracker_freeInstance(trackables[i].tracker);
}
}
//Disconnecting from trackables
printf("Disconnecting from Trackables\n");
for (i = 0; i < NUM_TRACKABLES; i++) {
if (trackables[i].isAdapter == 1) {
adapterDisconnect(&(trackables[i]));
}
//else if (trackables[i].isLocal == 1) {
else if (local_comm_channel) {
safe_close_fd(trackables[i].fifo_rx, &trackables[i].socket_mutex);
safe_close_fd(trackables[i].fifo_tx, &trackables[i].socket_mutex);
}
else {
if (!getenv(NOQUAD_ENV)) {
safe_close_fd(trackables[i].socket, &trackables[i].socket_mutex);
}
}
}
//Close log file if one was open
if (quadlog_file_open) {
fclose(quadlog_file);
}
return 0;
}
void sendVrpnPacket(struct ucart_vrpn_TrackerData *info) {
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
uint8_t packet[64];
struct metadata m;
uint8_t data[128];
struct position_update u;
u.id = currMessageID;
u.x = info->x;
u.y = info->y;
u.z = info->z;
u.pitch = info->pitch;
u.roll = info->roll;
u.yaw = info->yaw;
if (EncodeUpdate(&m, data, 128, &u) < 0) {
warnx("Big problems. sendVrpnPacket . EncodeUpdate");
return;
}
m.msg_id = currMessageID++;
ssize_t psize;
if ((psize = EncodePacket(packet, 64, &m, data)) < 0) {
warnx("Big problems. sendVrpnPacket. EncodePacket");
return;
}
for (int i = 0; i < NUM_TRACKABLES; i++) {
if (strcmp(trackables[i].server_name, info->server_name) == 0) {
writeQuadIndex(packet, psize, i);
break;
}
}
}
void getVRPNPacket(struct ucart_vrpn_TrackerData *td) {
#if VRPN_DEBUG_PRINT == 1
for (int i = 0; i < NUM_TRACKABLES; i++) {
if (strcmp(trackable, trackables[i].name) == 0) {
break;
}
}
#endif
//if ((status = ucart_vrpn_tracker_getData(trackables[i].tracker, td)) < 0) {
// TODO - remove tracker instance
if((status = ucart_vrpn_tracker_getData(tracker, td)) < 0) {
perror("Error receiving VRPN data from tracker...");
keepRunning = 0;
}
/* void getVRPNPacket(struct ucart_vrpn_TrackerData *td, int index) {
int status;
if ((status = ucart_vrpn_tracker_getData(trackables[i].tracker, td)) < 0) {
perror("Error receiving VRPN data from tracker...");
keepRunning = 0;
}
} */
printf("FPS: %lf Pos (xyz): (%lf %lf %lf) Att (pry): (%lf %lf %lf)\n",
td->fps, td->x, td->y, td->z, td->pitch, td->roll, td->yaw);
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
int connectToZybo(int index) {
int sock;
int status = -1;
if (getenv(NOQUAD_ENV)) {
return 0;
}
// Check for local comm channel or bluetooth
//if (trackables[index].isLocal == 1) {
if (getenv(QUAD_COMM_ENV) && strcmp(getenv(QUAD_COMM_ENV), "local") == 0) {
printf("Using Local Fifo Settings\n");
local_comm_channel = 1;
char * fifo_rx = trackables[index].fifo_tx_path;
char * fifo_tx = trackables[index].fifo_rx_path;
trackables[index].fifo_tx = open(fifo_tx, O_WRONLY | O_NONBLOCK);
if (trackables[index].fifo_tx < 0) {
warnx("Open zybo_fifo_tx...");
return -1;
}
trackables[index].fifo_rx = open(fifo_rx, O_RDWR | O_NONBLOCK);
if (trackables[index].fifo_rx < 0) {
warnx("Opening zybo_fifo_rx...");
return -1;
}
status = 0;
sock = trackables[index].fifo_rx;
}
ucart
committed
/*else if (trackables[index].isBluetooth == 1) { //Bluetooth functionality currently disabled
printf("Using BT Settings\n");
struct sockaddr_rc addr;
//allocate a socket
sock = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
//set the connection params ie. who connect to
addr.rc_family = AF_BLUETOOTH;
addr.rc_channel = trackables[index].bt_channel;
str2ba( trackables[index].bt_addr, &addr.rc_bdaddr );
printf("Attempting to connect to zybo. Please be patient...\n");
// blocking call to connect to socket sock ie. zybo board
status = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
ucart
committed
}*/
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
else {
printf("Using WIFI settings\n");
struct sockaddr_in addr;
addr.sin_family = AF_INET;
/* Quick and Dirty */
if (!inet_aton(trackables[index].quad_ip, &addr.sin_addr)) {
printf("Default IP %s is invalid\n",
trackables[index].quad_ip);
return -1;
}
/* Quick 'n dirty, oh yeah! */
addr.sin_port = htons(trackables[index].quad_port);
sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock < 0) {
perror("socket");
return -1;
}
printf("Connecting to Quad @ %s:%u\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
status = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
int flag = 1;
int result = setsockopt(sock, /* socket affected */
IPPROTO_TCP, /* set option at TCP level */
TCP_NODELAY, /* name of option */
(char *) &flag, /* the cast is historical cruft */
sizeof(int)); /* length of option value */
}
// connection failed
if(status < 0) {
close(sock);
perror("connect");
return -1;
} else {
printf("connection successful!...\n");
return sock;
}
/* add a fd to fd_set, and update max_fd */
int safe_fd_set(int fd, fd_set* fds, int* max_fd) {
assert(max_fd != NULL);
FD_SET(fd, fds);
if (fd > *max_fd) {
*max_fd = fd;
}
return 0;
}
/* clear fd from fds, update max fd if needed */
int safe_fd_clr(int fd, fd_set* fds, int* max_fd) {
assert(max_fd != NULL);
FD_CLR(fd, fds);
if (fd == *max_fd) {
(*max_fd)--;
}
return 0;
static ssize_t writeQuad(const uint8_t * buf, size_t count) {
ssize_t retval;
int index = 0;
for (int i = 0; i < NUM_TRACKABLES; i++) {
if (strcmp(trackables[i].name, trackable) == 0) {
index = i;
#if BACKEND_DEBUG_PRINT == 1
printf("Index: %d\tName: %s\n", index, trackables[index].name);
printf("packetToQuad = '");
for(int i = 0; i < (int)count; ++i) {
printf(" %.2x ", buf[i]);
}
printf("'\n");
#endif
return writeQuadIndex(buf, count, index);
}
}
//FIXME - Should never reach here
return -1;
}
static ssize_t writeQuadIndex(const uint8_t * buf, size_t count, int index) {
ssize_t retval;
#if BACKEND_DEBUG_PRINT == 1
printf("packetToQuad = '");
for(int i = 0; i < (int)count; ++i) {
printf(" %.2x ", buf[i]);
}
printf("'\n");
#endif
if (trackables[index].isAdapter == 0 && getenv(NOQUAD_ENV)) {
return count;
}
if (pthread_mutex_lock(&trackables[index].socket_mutex)) {
err(-2, "pthrtead_mutex_lock (%s:%d):", __FILE__, __LINE__);
}
//if (trackables[index].isLocal == 1) {
if (trackables[index].isAdapter == 0 && local_comm_channel) {
retval = write(trackables[index].fifo_tx, buf, count);
} else {
if (trackables[index].isAdapter == 0) {
retval = write(trackables[index].socket, buf, count);
} else {
retval = adapterWrite(trackables[index].conn, (const char *) buf, count);
}
}
if (pthread_mutex_unlock(&trackables[index].socket_mutex)) {
err(-2, "pthrtead_mutex_unlock (%s:%d):", __FILE__, __LINE__);
}
return retval;
static ssize_t readQuad(char * buf, size_t count, int index) {
ssize_t retval;
if (trackables[index].isAdapter == 0 && getenv(NOQUAD_ENV)) {
return count;
}
if (pthread_mutex_lock(&trackables[index].socket_mutex)) {
err(-2, "pthrtead_mutex_lock (%s:%d):", __FILE__, __LINE__);
}
retval = read(trackables[index].socket, buf, count);
if (pthread_mutex_unlock(&trackables[index].socket_mutex)) {
err(-2, "pthrtead_mutex_unlock (%s:%d):", __FILE__, __LINE__);
}
return retval;
}
static int new_client(int fd) {
ssize_t new_slot = -1;
for (ssize_t i = 0; i < MAX_CLIENTS; i++) {
if (client_fds[i] < 0) {
new_slot = i;
break;
}
}
if (new_slot == -1) {
warnx("Ran out of room! Consider increasing MAX_CLIENTS!");
return 0;
}
client_fds[new_slot] = fd;
client_buffers[new_slot][0] = '\0';
return 1;
static ssize_t get_client_index(int fd) {
for (ssize_t i = 0; i < MAX_CLIENTS; i++) {
if (client_fds[i] == fd) {
return i;
}
}
static char * get_client_buffer(int fd) {
ssize_t slot = get_client_index(fd);
if (slot == -1) {
return NULL;
} else {
return client_buffers[slot];
}
static int * get_client_pend_responses(int fd) {
ssize_t slot = get_client_index(fd);
if (slot == -1) {
return NULL;
} else {
return client_pending_responses[slot];
}
static int clientAddPendResponses(int fd, uint16_t packet_id) {
int *pendingResponses = get_client_pend_responses(fd);
for(int i = 0; i < CLIENT_MAX_PENDING_RESPONSES; i++) {
if(pendingResponses[i] == -1) {
pendingResponses[i] = packet_id;
return i;
}
}
return -1;
}
static int clientRemovePendResponses(int fd, uint16_t packet_id) {
int *pendingResponses = get_client_pend_responses(fd);
for(int i = 0; i < CLIENT_MAX_PENDING_RESPONSES; i++) {
if(pendingResponses[i] == packet_id) {
pendingResponses[i] = -1;
return i;
}
}
return -1;
ssize_t slot = get_client_index(fd);
if(slot == -1)
return -1;
char *clientBuffer = get_client_buffer(fd);
if(clientBuffer == NULL)
return -1;
clientBuffer[0] = '\0';
int *pendingResponses = get_client_pend_responses(fd);
if(pendingResponses == NULL)
return -1;
for(int i = 0; i < CLIENT_MAX_PENDING_RESPONSES; i++) {
pendingResponses[i] = -1;
}
client_fds[slot] = -1;
return 0;
}
static void safe_close_fd(int fd, pthread_mutex_t *mutexLock) {
if (pthread_mutex_lock(mutexLock)) {
err(-2, "pthrtead_mutex_lock (%s:%d):", __FILE__, __LINE__);
}
close(fd);
if (pthread_mutex_unlock(mutexLock)) {
err(-2, "pthrtead_mutex_unlock (%s:%d):", __FILE__, __LINE__);
}
char * buffer;
ssize_t len_pre;
char cmdString[64];
char * cursor;
ssize_t r;
int index = 0;
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
len_pre = strlen(buffer);
cursor = buffer + len_pre;
r = read(fd, cursor, CLIENT_BUFFER_SIZE - len_pre - 1);
if (r < 0) {
warn("read (fd: %d)", fd);
}
buffer[len_pre + r] = '\0';
/* Parse buffer and handle commands */
while (1) {
/* not using strtok because reasons */
size_t len = strlen(buffer);
ssize_t newline = -1;
for (size_t i = 0; i < len; i++) {
if (buffer[i] == '\n') {
newline = i;
break;
}
}
/* No newline found. End parsing */
if (newline == -1) {
break;
}
buffer[newline] = '\0';
printf("Client(%d) : '%s'\n",fd, buffer);
char * first_word;
char * tmp = strdup(buffer);
#if BACKEND_DEBUG_PRINT == 1
printf("tmpbuff = '%s'\n", tmp);
#endif
#if BACKEND_DEBUG_PRINT == 1
printf("first word = '%s'\n", first_word);
#endif
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
ssize_t msg_type, i;
for (i = 0; i < MAX_TYPE_ID; ++i) {
if ((msg_type = findCommand(first_word)) != -1)
break;
}
free(tmp);
if (msg_type == -1) {
/* buffer was not a quad command, handling internally to
* backend instead of forwarding to quad
*/
if (strncmp(buffer, TD_MAGIC, strlen(TD_MAGIC)) == 0) {
/* Request for tracker data */
struct ucart_vrpn_TrackerData td;
// TODO - check tracker of a specific trackable, also implement a request
// that can get the vrpn of a specific trackable
if (tracker == NULL) {
char * dummy = TD_MAGIC " 1.0 2.0 3.0 4.0 5.0 6.0\n";
write(fd, dummy, strlen(dummy));
} else if (ucart_vrpn_tracker_getData(tracker, &td)) {
write(fd, TD_MAGIC " ERROR\n", strlen(TD_MAGIC " ERROR\n"));
} else {
/* more than sufficient buffer */
char buffer[2048];
/* Map VRPN XYZ to Height Lat Long (right now it's
* a guess). Format is Height Lat Long P R Y */
if (snprintf(buffer,
2048,
TD_MAGIC " %lf %lf %lf %lf %lf %lf\n",
td.z,
td.y,
td.x,
td.pitch,
td.roll,
td.yaw) >= 2048) {
/* Output longer than buffer */
warnx("Increase format buffer size, output was too long!");
write(fd, TD_MAGIC " ERROR\n", strlen(TD_MAGIC " ERROR\n"));
}
write(fd, buffer, strlen(buffer));
}
}
else if (strncmp(buffer, "gettrackable", strlen("gettrackable")) == 0) {
char buffer[256];
if (snprintf(buffer,
256,
"gettrackable %s\n",
trackable) >= 256) {
warnx("Increase format buffer size, output was too long!");
write(fd, "gettrackable ERROR\n", strlen("gettrackable ERROR\n"));
}
write(fd, buffer, strlen(buffer));
}
else if (strncmp(buffer, "settrackable", strlen("settrackable")) == 0) {
char check[256];
sscanf(buffer,
"settrackable %s",
check);
if (strcmp(check,"(null)") != 0) {
for (i = 0; i < NUM_TRACKABLES; i++) {
if (strcmp(trackables[i].name, check) == 0) {
sscanf(buffer,
"settrackable %s",
trackable);
break;
}
}
}
}
} else {
uint8_t packet[64];
struct metadata m;
uint8_t *data = malloc(sizeof(*data) * 128);
ssize_t result;
ssize_t psize;
printf(" found a msg_type of %ld\n", msg_type);
switch (msg_type) {
case SETPARAM_ID:
result = EncodeSetParam(&m, data, 128, buffer);
break;
case GETPARAM_ID:
result = EncodeGetParam(&m, data, 128, buffer);
break;
case SETSOURCE_ID:
result = EncodeSetSource(&m, data, 128, buffer);
break;
case GETSOURCE_ID:
result = EncodeGetSource(&m, data, 128, buffer);
break;
case GETOUTPUT_ID:
result = EncodeGetOutput(&m, data, 128, buffer);
break;
case GETNODES_ID:
result = EncodeGetNodes(&m, data, 128, buffer);
break;
case ADDNODE_ID:
result = EncodeAddNode(&m, data, 128, buffer);
break;
case OUTPUT_OVERRIDE_ID:
result = EncodeSetOutputOverride(&m, data, 128, buffer);
break;
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
default:
result = -1;
break;
}
if (result < 0) {
warnx("Big problems. client_recv. EncodeMetaData");
free(data);
return;
}
m.msg_id = currMessageID++;
if ((psize = EncodePacket(packet, 64, &m, data)) < 0) {
warnx("Big problems. client_recv. EncodePacket");
free(data);
return;
}
/* Only add the client to the pending responses if it was a getparam command */
if (m.msg_type == GETPARAM_ID || m.msg_type == GETOUTPUT_ID ||
m.msg_type == GETSOURCE_ID || m.msg_type == GETNODES_ID || m.msg_type == ADDNODE_ID) {
if (clientAddPendResponses(fd, BytesTo16(packet[ID_L], packet[ID_H])) == -1) {
warnx("Ran out of room! Consider increasing CLIENT_MAX_PENDING_RESPONSES!\n");
}
}
int retval = writeQuad(packet, psize);
// printf("sent %d bytes\n", retval);
free(data);
}
char * rest = &buffer[newline] + 1;
size_t restLen = (strlen(rest) == 0) ? 1 : strlen(rest);
/* Delete parsed data and move the rest to the left */
memmove(buffer, rest, restLen +1);
}
static void quad_recv(int index) {
static unsigned char respBuf[CMD_MAX_LENGTH];
static size_t respBufLen;
struct metadata m;
uint8_t data[CMD_MAX_LENGTH];
size_t respLen;
ssize_t datalen;
size_t packetlen;
respLen = readQuad((char *) respBuf + respBufLen,
CMD_MAX_LENGTH - respBufLen, index);
if (respLen <= 0) {
perror("ERROR reading from quad...\n");
respBufLen = 0;
return;
}
respBufLen += respLen;
#if BACKEND_DEBUG_PRINT == 1
printf("packetFromQuad = '");
for(int i = 0; i < (int)respBufLen; ++i) {
printf(" %.2x ", respBuf[i]);
}
printf("'\n");
#endif
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
while(respBufLen) {
datalen = DecodePacket(&m, data, CMD_MAX_LENGTH, respBuf, respBufLen);
if (datalen == -1) {
warnx("No start Byte");
for (size_t i = 0; i < respBufLen; ++i) {
if (respBuf[i] == BEGIN_CHAR) {
memmove(respBuf, respBuf + i, respBufLen - i);
respBufLen -=i;
return;
}
}
respBufLen = 0;
return;
}
if (datalen == -5) {
warnx("Chechsum mismatch");
for (size_t i = 0; i < respBufLen; ++i) {
if (respBuf[i] == BEGIN_CHAR) {
memmove(respBuf, respBuf + i, respBufLen - i);
respBufLen -=i;
return;
}
}
respBufLen = 0;
return;
}
if (datalen < 0){
/* Not enough data yet. We need to wait for more */
return;
}
packetlen = PacketSize(&m);
memmove(respBuf, respBuf + packetlen, respBufLen - packetlen);
respBufLen -= packetlen;
char * debug_string;
switch (m.msg_type) {
case DEBUG_ID:
/* in case of debug. Quad send null terminated string in data */
debug_string = strndup((char *)data, m.data_len);
printf(" (Quad) : %s\n", debug_string);
free(debug_string);
break;
case LOG_ID:
if (!quadlog_file_open) {
char log_file[256];
create_log_name(log_file, 256, user_specified_log_name);
printf("New log file created: '%s'\n", log_file);
quadlog_file = fopen(log_file, "w");