trace_proxy.c 16.6 KB
Newer Older
Jeroen Vreeken's avatar
Jeroen Vreeken committed
1
/*
Jeroen Vreeken's avatar
Jeroen Vreeken committed
2
	Copyright Jeroen Vreeken (pe1rxq@amsat.org), 2008, 2009, 2013
Jeroen Vreeken's avatar
Jeroen Vreeken committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
	Copyright Stichting C.A. Muller Radioastronomiestation, 2008, 2009

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.

 */

Jeroen Vreeken's avatar
Jeroen Vreeken committed
20
21
22
23
24
25
#include "dt_port_numbers.h"
#include "dt_host.h"

#include <trace.h>
#include "tcp_listen.h"

Jeroen Vreeken's avatar
Jeroen Vreeken committed
26
#include <stdio.h>
Jeroen Vreeken's avatar
Jeroen Vreeken committed
27
28
#include <signal.h>
#include <sys/select.h>
Jeroen Vreeken's avatar
Jeroen Vreeken committed
29
30
#include <sys/ioctl.h>
#include <unistd.h>
Jeroen Vreeken's avatar
Jeroen Vreeken committed
31
32
#include <string.h>
#include <stdlib.h>
Jeroen Vreeken's avatar
Jeroen Vreeken committed
33
34
#include <errno.h>

Jeroen Vreeken's avatar
Jeroen Vreeken committed
35
#define TIMEOUT 10
36
#define VALCLIENT_UPDATE_NSEC (100*1000*1000)
Jeroen Vreeken's avatar
Jeroen Vreeken committed
37

Jeroen Vreeken's avatar
Jeroen Vreeken committed
38
39
static char *tr_host;
static int tr_port;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
40

Jeroen Vreeken's avatar
Jeroen Vreeken committed
41
42
static struct trace_pkt *interval_pkt;
static struct timespec base_interval;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
43

Jeroen Vreeken's avatar
Jeroen Vreeken committed
44
45
46
struct private {
	int nr_clients;
	struct trace **clients;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
47

Jeroen Vreeken's avatar
Jeroen Vreeken committed
48
	time_t lastclient;
49
	struct trace_value lastvalue;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
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
static int nr_client_traces = 0;
static struct trace **client_traces;

static int nr_server_traces = 0;
static struct trace **server_traces;

static void common_denom(struct timespec *common, struct timespec *int1, struct timespec *int2)
{
	uint64_t i1, i2, b;
	uint64_t d1, d2;
	uint64_t inew;
	
	i1 = int1->tv_sec * 1000000000 + int1->tv_nsec;
	i2 = int2->tv_sec * 1000000000 + int2->tv_nsec;
	b = base_interval.tv_sec * 1000000000 + base_interval.tv_nsec;
	
	d1 = i1 / b;
	d2 = i2 / b;
	
	if (d2 && d1 > d2 && !(d1 % d2)) {
		inew = d2;
	} else if (d1 && d2 > d1 && !(d2 % d1)) {
		inew = d1;
	} else {
		inew = 1;
	}
	
	common->tv_sec = base_interval.tv_sec * inew;
	common->tv_nsec = base_interval.tv_nsec * inew;
	common->tv_sec += common->tv_nsec / 1000000000;
	common->tv_nsec %= 1000000000;
}

static void server_interval_check(struct trace *server)
{
	struct private *priv = server->private;
	enum trace_interval_type type = 0;
	struct timespec interval;
	int i;
	bool has_valclient;
	bool fullrate = false;
	
	interval.tv_sec = 0;
	interval.tv_nsec = 0;
	
	has_valclient = priv->lastclient + TIMEOUT > time(NULL);
	
	if (has_valclient) {
		interval.tv_sec = 0;
		interval.tv_nsec = VALCLIENT_UPDATE_NSEC;
	}

	for (i = 0; i < priv->nr_clients; i++) {
		switch (priv->clients[i]->interval_type) {
			case TRACE_INTERVAL_TYPE_INTERVAL:
				if (type) {
					fullrate = true;
				} else {
					type = TRACE_INTERVAL_TYPE_INTERVAL;
				}
				
				/* Search for a common interval for all clients */
				common_denom(&interval, 
				    &interval, &priv->clients[i]->interval);

				break;
			case TRACE_INTERVAL_TYPE_CHANGED:
				if (type) {
					fullrate = true;
				} else {
					type = TRACE_INTERVAL_TYPE_CHANGED;
				}
				break;
			default:
				break;
		}
		
	}

	if (!type && has_valclient) {
		type = TRACE_INTERVAL_TYPE_INTERVAL;
		interval.tv_sec = 0;
		interval.tv_nsec = VALCLIENT_UPDATE_NSEC;
	}

	if (fullrate) {
		type = TRACE_INTERVAL_TYPE_INTERVAL;
		interval.tv_sec = base_interval.tv_sec;
		interval.tv_nsec = base_interval.tv_nsec;
	}

	if ((server->interval_type != type) ||
	    (server->interval.tv_sec != interval.tv_sec) ||
	    (server->interval.tv_nsec != interval.tv_nsec)) {
		struct trace_pkt *pkt;
		
		printf("Changing server trace %s from %ld.%09ld, %d to %ld.%09ld, %d\n",
		    server->name,
		    server->interval.tv_sec, server->interval.tv_nsec, 
		    server->interval_type,
		    interval.tv_sec, interval.tv_nsec, type);
		
		pkt = trace_packet_new();
		trace_packet_interval_set(pkt, 
		    &interval, type);
		trace_packet_write(server, pkt);
		trace_packet_put(pkt);
	}
}

static struct trace *server_find_client(struct trace *trace)
{
	int i, j;
	
	for (i = 0; i < nr_server_traces; i++) {
		struct trace *server;
		struct private *priv;
		
		server = server_traces[i];
		priv = server->private;
		
		for (j = 0; j < priv->nr_clients; j++) {
			if (priv->clients[j] == trace)
				return server;
		}
	}
	
	return NULL;
}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
182

Jeroen Vreeken's avatar
Jeroen Vreeken committed
183
184
185
186
187
188
189
190
191
static void handler_interval(struct trace *trace, 
    struct timespec *interval, enum trace_interval_type type)
{
	base_interval = *interval;
	
	interval_pkt = trace_packet_new();
	trace_packet_interval_set(interval_pkt, 
	    interval, TRACE_INTERVAL_TYPE_INTERVAL);
}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
192

193
194
195
196
static void client_interval(struct trace *trace, 
    struct timespec *interval, enum trace_interval_type type)
{
	struct trace_pkt *pkt;
197
	struct trace *server;
198

199
200
201
202
	printf("Client %s requests %ld.%09ld type %d\n",
	    trace->name,
	    interval->tv_sec, interval->tv_nsec, type);
	/* Send back interval to client (as ACK) */
203
204
205
206
207
	pkt = trace_packet_new();
	trace_packet_interval_set(pkt, 
	    interval, type);
	trace_packet_write(trace, pkt);
	trace_packet_put(pkt);
208
209
210
211
212
213

	server = server_find_client(trace);
	if (!server)
		return;
		
	server_interval_check(server);
214
215
}

Jeroen Vreeken's avatar
Jeroen Vreeken committed
216
static struct trace_pkt *list_pkt;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
217

Jeroen Vreeken's avatar
Jeroen Vreeken committed
218
219
220
221
static void handler_list_entry(struct trace *trace, 
    char *name, enum trace_value_type type, char *unit)
{
	trace_packet_list_add(list_pkt, name, type, unit);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
222

Jeroen Vreeken's avatar
Jeroen Vreeken committed
223
224
	trace_autorecover(trace, false);
}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
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
static bool check_client(struct private *priv, int nr)
{
	if (trace_state_get(priv->clients[nr]) == TRACE_STATE_DISCONNECTED) {
		trace_free(priv->clients[nr]);
		memmove(&priv->clients[nr], &priv->clients[nr+1],
		    (priv->nr_clients-nr-1)*sizeof(struct trace *));
		priv->nr_clients--;
		printf("Trace lost a client, %d left\n",
		    priv->nr_clients);
		return true;
	}
	return false;
}


static bool timespec_mod(struct timespec *t, struct timespec *tdiv)
{
	/* TODO: make a proper mod taking both fields into account */
	if (tdiv->tv_sec) {
		return t->tv_sec % tdiv->tv_sec || t->tv_nsec;
	} else if (tdiv->tv_nsec) {
		return t->tv_nsec % tdiv->tv_nsec;
	}
	return false;
}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
251

Jeroen Vreeken's avatar
Jeroen Vreeken committed
252
253
static void server_value(struct trace *trace,
    struct trace_value *value)
Jeroen Vreeken's avatar
Jeroen Vreeken committed
254
{
Jeroen Vreeken's avatar
Jeroen Vreeken committed
255
256
	struct trace_pkt *pkt;
	struct private *priv = trace->private;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
257
258
	int i;
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
259
	if (priv->nr_clients) {
260
261
262
263
264
265
266
267
		bool changed;
		
		if (priv->lastvalue.value.u32 != value->value.u32)
			changed = true;
		else
			changed = false;
		priv->lastvalue.value.u32 = value->value.u32;
		
Jeroen Vreeken's avatar
Jeroen Vreeken committed
268
269
270
271
		pkt = trace_packet_new();
		trace_packet_value_add(pkt, value, trace->type);
	
		for (i = 0; i < priv->nr_clients; i++) {
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
			bool send = false;
			
			switch (priv->clients[i]->interval_type) {
				case TRACE_INTERVAL_TYPE_CHANGED:
					send = changed;
					break;
				case TRACE_INTERVAL_TYPE_INTERVAL:
					send =!timespec_mod(&value->t,
					    &priv->clients[i]->interval);
					break;
				default:
					send = true;
					break;
			}
				
			if (!send)
				continue;

Jeroen Vreeken's avatar
Jeroen Vreeken committed
290
			trace_packet_write(priv->clients[i], pkt);
291
			if (check_client(priv, i)) {
292
				server_interval_check(trace);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
293
294
				i--;
				continue;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
295
296
			}
		}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
297
298
299
		trace_packet_put(pkt);
	}
}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
300

Jeroen Vreeken's avatar
Jeroen Vreeken committed
301
302
303
304
305
306
static void server_timestamp(struct trace *trace, 
    struct timespec *timestamp)
{
	struct trace_pkt *pkt;
	struct private *priv = trace->private;
	int i;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
307
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
308
309
310
	if (priv->nr_clients) {
		pkt = trace_packet_new();
		trace_packet_timestamp_set(pkt, timestamp);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
311
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
312
313
		for (i = 0; i < priv->nr_clients; i++) {
			trace_packet_write(priv->clients[i], pkt);
314
			if (check_client(priv, i)) {
315
				server_interval_check(trace);
316
317
318
				i--;
				continue;
			}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
319
320
		}
		trace_packet_put(pkt);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
321
322
	}
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
323
324
325
326
327
328
	if (!priv->nr_clients && trace->fd >= 0 && priv->lastclient + TIMEOUT < time(NULL)) {
		printf("Timeout, closing trace\n");
		trace_close(trace);
		trace_autorecover(trace, false);
	}
}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
329
330


Jeroen Vreeken's avatar
Jeroen Vreeken committed
331
332
333
334
335
static void server_type(struct trace *trace, enum trace_value_type type)
{
	struct trace_pkt *pkt;
	struct private *priv = trace->private;
	int i;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
336
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
337
338
	pkt = trace_packet_new();
	trace_packet_type_set(pkt, type);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
339
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
340
341
342
343
344
	for (i = 0; i < priv->nr_clients; i++) {
		trace_packet_write(priv->clients[i], pkt);
	}
	
	trace_packet_put(pkt);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
345
346
}

Jeroen Vreeken's avatar
Jeroen Vreeken committed
347
static void client_accept(int fd_listen)
Jeroen Vreeken's avatar
Jeroen Vreeken committed
348
{
Jeroen Vreeken's avatar
Jeroen Vreeken committed
349
350
	int fd;
	struct trace *client;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
351
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
352
353
	fd = tcp_accept(fd_listen);
	if (fd < 0)
Jeroen Vreeken's avatar
Jeroen Vreeken committed
354
355
		return;
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
356
	printf("New client\n");
Jeroen Vreeken's avatar
Jeroen Vreeken committed
357
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
358
359
360
	client = trace_alloc();
	if (!client) {
		close(fd);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
361
362
363
		return;
	}
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
364
365
366
367
	trace_initialize_fd(client, fd);

	trace_packet_write(client, interval_pkt);
	trace_packet_write(client, list_pkt);
368
	client->handler_interval = client_interval;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
369
370
371
372
373
374

	client_traces = realloc(client_traces, 
	    sizeof(struct trace *) * (nr_client_traces + 1));

	client_traces[nr_client_traces] = client;
	nr_client_traces++;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
375
376
}

Jeroen Vreeken's avatar
Jeroen Vreeken committed
377
static void free_client(int i)
Jeroen Vreeken's avatar
Jeroen Vreeken committed
378
{
Jeroen Vreeken's avatar
Jeroen Vreeken committed
379
380
381
	memmove(&client_traces[i], &client_traces[i+1],
	    (nr_client_traces-i-1)*sizeof(struct trace *));
	nr_client_traces--;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
382
383
}

Jeroen Vreeken's avatar
Jeroen Vreeken committed
384
385

static void free_server(int i)
Jeroen Vreeken's avatar
Jeroen Vreeken committed
386
{
Jeroen Vreeken's avatar
Jeroen Vreeken committed
387
388
389
	memmove(&server_traces[i], &server_traces[i+1],
	    (nr_server_traces-i-1)*sizeof(struct trace *));
	nr_server_traces--;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
390
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
391
	printf("Freed server, %d left\n", nr_server_traces);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
392
393
}

Jeroen Vreeken's avatar
Jeroen Vreeken committed
394
static struct trace *server_find(char *name)
Jeroen Vreeken's avatar
Jeroen Vreeken committed
395
{
Jeroen Vreeken's avatar
Jeroen Vreeken committed
396
397
	struct trace *trace;
	struct private *priv;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
398
399
	int i;
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
400
401
402
	for (i = 0; i < nr_server_traces; i++) {
		if (!strcmp(server_traces[i]->name, name))
			break;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
403
	}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
404
405
	
	if (i == nr_server_traces) {
406
407
		struct trace_pkt *pkt;
		
Jeroen Vreeken's avatar
Jeroen Vreeken committed
408
409
410
		trace = trace_open(tr_host, tr_port);
		trace_name_set(trace, name);
		
411
412
413
414
415
416
417
418
		trace->interval_type = TRACE_INTERVAL_TYPE_INTERVAL;
		
		pkt = trace_packet_new();
		trace_packet_interval_set(pkt, 
		    &base_interval, trace->interval_type);
		trace_packet_write(trace, pkt);
		trace_packet_put(pkt);
		
Jeroen Vreeken's avatar
Jeroen Vreeken committed
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
		server_traces = realloc(server_traces, 
		    sizeof(struct trace *) * (nr_server_traces + 1));
		
		priv = calloc(sizeof(struct private), 1);
		trace->private = priv;
		
		server_traces[nr_server_traces] = trace;
		
		nr_server_traces++;		
		
		trace->handler_value = server_value;
		trace->handler_timestamp = server_timestamp;
		trace->handler_type = server_type;
		trace_autorecover(trace, true);
	}

	return server_traces[i];
Jeroen Vreeken's avatar
Jeroen Vreeken committed
436
437
}

Jeroen Vreeken's avatar
Jeroen Vreeken committed
438
static void client_add(struct trace *client)
Jeroen Vreeken's avatar
Jeroen Vreeken committed
439
{
Jeroen Vreeken's avatar
Jeroen Vreeken committed
440
441
	struct trace *trace;
	struct private *priv;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
442
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
443
	printf("Going to add client to trace '%s'\n", client->name);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
444
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
445
446
447
	trace = server_find(client->name);
	
	priv = trace->private;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
448

Jeroen Vreeken's avatar
Jeroen Vreeken committed
449
450
451
452
453
454
455
	if (trace->type_set) {
		struct trace_pkt *pkt;
		
		pkt = trace_packet_new();
		trace_packet_type_set(pkt, trace->type);
		trace_packet_write(client, pkt);
		trace_packet_put(pkt);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
456
	}
457
458
459
460
461
462
463
464
	if (trace->value_set) {
		struct trace_pkt *pkt;

		pkt = trace_packet_new();
		trace_packet_value_add(pkt, &trace->value, trace->type);
		trace_packet_write(client, pkt);
		trace_packet_put(pkt);
	}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
465
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
466
467
468
469
	priv->clients = realloc(priv->clients, 
	    sizeof(struct trace *) * (priv->nr_clients + 1));
	priv->clients[priv->nr_clients] = client;
	priv->nr_clients++;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
470

471
	server_interval_check(trace);
472

Jeroen Vreeken's avatar
Jeroen Vreeken committed
473
474
475
476
477
	printf("Trace now has %d clients\n", priv->nr_clients);
}

struct valclient {
	int fd;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
478
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
479
480
481
482
483
484
485
486
487
488
489
490
491
492
	size_t len;
	char request[1024];
};

int nr_valclients;
struct valclient **valclients;

static void free_val(int i)
{
	free(valclients[i]);

	memmove(&valclients[i], &valclients[i+1],
	    (nr_valclients-i-1)*sizeof(struct valclient *));
	nr_valclients--;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
493
494
}

Jeroen Vreeken's avatar
Jeroen Vreeken committed
495
static void val_accept(fd_listenval)
Jeroen Vreeken's avatar
Jeroen Vreeken committed
496
497
{
	int fd;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
498
	struct valclient *valclient;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
499
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
500
	fd = tcp_accept(fd_listenval);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
501
502
503
504
505
	if (fd < 0)
		return;
	
	ioctl(fd, FIONBIO, &(int){ 1 });
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
506
	valclient = calloc(1, sizeof(struct valclient));
Jeroen Vreeken's avatar
Jeroen Vreeken committed
507
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
508
509
	valclient->fd = fd;
	valclient->len = 0;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
510
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
511
512
	valclients = realloc(valclients, 
	    sizeof(struct valclient*)*(nr_valclients + 1));
Jeroen Vreeken's avatar
Jeroen Vreeken committed
513

Jeroen Vreeken's avatar
Jeroen Vreeken committed
514
515
	valclients[nr_valclients] = valclient;
	nr_valclients++;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
516
517
}

Jeroen Vreeken's avatar
Jeroen Vreeken committed
518
static void val_handle(struct valclient *valclient)
Jeroen Vreeken's avatar
Jeroen Vreeken committed
519
{
Jeroen Vreeken's avatar
Jeroen Vreeken committed
520
	ssize_t r;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
521
	int i;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
522
	char reply[1024];
Jeroen Vreeken's avatar
Jeroen Vreeken committed
523
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
524
525
526
527
528
529
530
	r = read(valclient->fd, &valclient->request[valclient->len],
	    1024 - valclient->len);
	
	if ((r < 0 && errno != EAGAIN) || r == 0) {
		close(valclient->fd);
		valclient->fd = -1;
		return;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
531
	}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
532
	valclient->len += r;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
533
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
534
535
536
537
538
539
540
	for (i = 0; i < valclient->len - 1; i++) {
		if (!valclient->request[i] && !valclient->request[i+1]) {
			char *name;
			char *replyp;
			time_t now = time(NULL);

			replyp = reply;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
541
			
Jeroen Vreeken's avatar
Jeroen Vreeken committed
542
543
544
545
			for (name = valclient->request; name[0]; 
			    name += strlen(name) + 1) {
				struct trace *trace;
				struct private *priv;
546
				bool int_check;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
547
548
549
550

				trace = server_find(name);
				priv = trace->private;
				
551
552
553
554
555
556
				int_check = priv->lastclient + TIMEOUT < now;
				
				priv->lastclient = now;

				if (int_check);
					server_interval_check(trace);
557

Jeroen Vreeken's avatar
Jeroen Vreeken committed
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
				switch(trace->type) {
					case TRACE_VALUE_TYPE_FLOAT:
						replyp += sprintf(replyp, "%g ",
						    trace->value.value.f);
						break;
					case TRACE_VALUE_TYPE_BOOL:
						replyp += sprintf(replyp, "%d ",
						    trace->value.value.b);
						break;
					case TRACE_VALUE_TYPE_UINT8:
						replyp += sprintf(replyp, "%d ",
						    trace->value.value.u8);
						break;
					case TRACE_VALUE_TYPE_UINT16:
						replyp += sprintf(replyp, "%d ",
						    trace->value.value.u16);
						break;
					case TRACE_VALUE_TYPE_UINT32:
						replyp += sprintf(replyp, "%d ",
						    trace->value.value.u32);
						break;
					case TRACE_VALUE_TYPE_SINT8:
						replyp += sprintf(replyp, "%d ",
						    trace->value.value.s8);
						break;
					case TRACE_VALUE_TYPE_SINT16:
						replyp += sprintf(replyp, "%d ",
						    trace->value.value.s16);
						break;
					case TRACE_VALUE_TYPE_SINT32:
						replyp += sprintf(replyp, "%d ",
						    trace->value.value.s32);
						break;
				}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
592
			}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
593
594
595
596
			sprintf(replyp, "\n");
			write(valclient->fd, reply, strlen(reply));
			close(valclient->fd);
			valclient->fd = -1;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
597
598
599
600
		}
	}
}

Jeroen Vreeken's avatar
Jeroen Vreeken committed
601
int main (int argc, char **argv)
Jeroen Vreeken's avatar
Jeroen Vreeken committed
602
603
604
{
	int fd_listen, fd_listenval;
	fd_set fd_rd;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
605
	struct trace *list;
606
	int high, i, j;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
607
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
	fd_listen = tcp_listen(CONSOLE_TRACE_PORT, 0, 100);
	if (fd_listen < 0) {
		printf("Could not open listen port %d\n", CONSOLE_TRACE_PORT);
		return 1;
	}

	fd_listenval = tcp_listen(CONSOLE_TRACE_VAL_PORT, 0, 100);
	if (fd_listenval < 0) {
		printf("Could not open listen port %d\n", CONSOLE_TRACE_VAL_PORT);
		return 1;
	}
	
	signal(SIGPIPE, SIG_IGN);

        /* determine socket on dt_ctrl */
Jeroen Vreeken's avatar
Jeroen Vreeken committed
623
624
	tr_host = dt_host_controller();
	tr_port = CTRL_TRACE_PORT;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646

	/* Get list of all traces */
	printf("Going to retrieve list of traces\n");

	list = trace_open(tr_host, tr_port);
	list->handler_interval = handler_interval;
	list->handler_list_entry = handler_list_entry;
	trace_autorecover(list, true);

	list_pkt = trace_packet_new();

	while (trace_state_get(list) != TRACE_STATE_READY) {
		struct timeval timeout;
		high = 0;

		timeout.tv_sec = 1;
		timeout.tv_usec = 10;
		
		FD_ZERO(&fd_rd);
		trace_fd_set(list, &fd_rd, &high);	
		select(high + 1, &fd_rd, NULL, NULL, &timeout);
		trace_handle(list, &fd_rd);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
647
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
648
649
650
651
652
653
654
655
656
		/* Prevent cpu hogging */
		if (trace_state_get(list) != TRACE_STATE_READY)
			sleep(1);
		printf("state: %d\n", trace_state_get(list));
	}
	trace_close(list);
	trace_free(list);

	printf("Recieved list from server, now waiting for clients\n");
Jeroen Vreeken's avatar
Jeroen Vreeken committed
657
658
659
660

	while (1) {
		struct timeval timeout;
		
Jeroen Vreeken's avatar
Jeroen Vreeken committed
661
662
		FD_ZERO(&fd_rd);
		
Jeroen Vreeken's avatar
Jeroen Vreeken committed
663
		timeout.tv_sec = 10;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
664
		timeout.tv_usec = 0;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
665
666
667
668
		
		high = fd_listen;
		FD_SET(fd_listen, &fd_rd);
		FD_SET(fd_listenval, &fd_rd);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
669
670
671
672
673
		if (fd_listenval > high)
			high = fd_listenval;

		for (i = 0; i < nr_client_traces; i++) {
			trace_fd_set(client_traces[i], &fd_rd, &high);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
674
		}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
675
		for (i = 0; i < nr_server_traces; i++) {
676
677
			struct private *priv = server_traces[i]->private;
			
Jeroen Vreeken's avatar
Jeroen Vreeken committed
678
			trace_fd_set(server_traces[i], &fd_rd, &high);
679
680
681
			for (j = 0; j < priv->nr_clients; j++) {
				trace_fd_set(priv->clients[j], &fd_rd, &high);
			}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
682
		}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
683
684
685
686
		for (i = 0; i < nr_valclients; i++) {
			FD_SET(valclients[i]->fd, &fd_rd);
			if (valclients[i]->fd > high)
				high = valclients[i]->fd;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
687
688
689
690
		}
		
		select(high + 1, &fd_rd, NULL, NULL, &timeout);
		
Jeroen Vreeken's avatar
Jeroen Vreeken committed
691
		if (FD_ISSET(fd_listen, &fd_rd)) {
Jeroen Vreeken's avatar
Jeroen Vreeken committed
692
			client_accept(fd_listen);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
693
694
695
696
697
698
699
700
701
702
703
		}
		if (FD_ISSET(fd_listenval, &fd_rd)) {
			val_accept(fd_listenval);
		}
		for (i = 0; i < nr_valclients; i++) {
			if (FD_ISSET(valclients[i]->fd, &fd_rd)) {
				val_handle(valclients[i]);
			}
			if (valclients[i]->fd < 0) {
				free_val(i);
				i--;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
704
705
			}
		}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
706
707
708
709
710
711
712
713
714
		
		for (i = 0; i < nr_client_traces; i++) {
			if(trace_handle(client_traces[i], &fd_rd))
				continue;
			
			if (client_traces[i]->name_set) {
				client_add(client_traces[i]);
				free_client(i);
				i--;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
715
716
				continue;
			}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
717
718
719
720
721
722
723
			
			if (trace_state_get(client_traces[i]) ==
			    TRACE_STATE_DISCONNECTED) {
				trace_free(client_traces[i]);
				free_client(i);
				printf("Freeing client %d\n", i);
				i--;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
724
725
726
				continue;
			}
		}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
727
		for (i = 0; i < nr_server_traces; i++) {
728
729
			struct private *priv = server_traces[i]->private;
			
Jeroen Vreeken's avatar
Jeroen Vreeken committed
730
731
			if (trace_handle(server_traces[i], &fd_rd))
				continue;
732
733
734
			for (j = 0; j < priv->nr_clients; j++) {
				trace_handle(priv->clients[j], &fd_rd);
			}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
735
736
737
738
739
740
741
742
743
744
745

			if (trace_state_get(server_traces[i]) ==
			    TRACE_STATE_DISCONNECTED &&
			    !server_traces[i]->recover) {
			    	free(server_traces[i]->private);
				trace_free(server_traces[i]);
				free_server(i);
				printf("Freeing server trace %d\n", i);
				i--;
				continue;
			}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
746
747
748
749
750
		}
	}

	return 0;
}