trace_proxy.c 15.2 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
#include <dt_port_numbers.h>
#include <utils/dt_host.h>
Jeroen Vreeken's avatar
Jeroen Vreeken committed
22

Jeroen Vreeken's avatar
Jeroen Vreeken committed
23
#include <trace/trace.h>
24
#include <log/log.h>
Jeroen Vreeken's avatar
Jeroen Vreeken committed
25
#include <utils/tcp_listen.h>
Jeroen Vreeken's avatar
Jeroen Vreeken committed
26

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

Jeroen Vreeken's avatar
Jeroen Vreeken committed
36
#define TIMEOUT 10
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

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

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

Jeroen Vreeken's avatar
Jeroen Vreeken committed
49
	time_t lastclient;
50
	struct trace_value lastvalue;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
51
	bool firstvalue;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
52
53
	
	bool keep; /* keep this trace even without active clients */
Jeroen Vreeken's avatar
Jeroen Vreeken committed
54
55
56
};


Jeroen Vreeken's avatar
Jeroen Vreeken committed
57
58
59
static char **keep_traces;
static int nr_keep_traces = 0;

60
61
62
63
64
65
66
67
68
69
70
71
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;
	
72
73
74
	i1 = (uint64_t)int1->tv_sec * 1000000000ull + (uint64_t)int1->tv_nsec;
	i2 = (uint64_t)int2->tv_sec * 1000000000ull + (uint64_t)int2->tv_nsec;
	b = (uint64_t)base_interval.tv_sec * 1000000000ull + (uint64_t)base_interval.tv_nsec;
75
76
77
78
79
	if (!b) {
		memcpy(common, int1, sizeof(struct timespec));
		return;
	}
		
80
81
	d1 = i1 / b;
	d2 = i2 / b;
82
		
Jeroen Vreeken's avatar
Jeroen Vreeken committed
83
84
85
	if (d1 == d2) {
		inew = d1;
	} else if (d2 && d1 > d2 && !(d1 % d2)) {
86
87
88
89
		inew = d2;
	} else if (d1 && d2 > d1 && !(d2 % d1)) {
		inew = d1;
	} else {
Jeroen Vreeken's avatar
Jeroen Vreeken committed
90
91
92
93
94
95
		if (!d1 && d2)
			inew = d2;
		else if (d1 && !d2)
			inew = d1;
		else
			inew = 1;
96
	}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
97

98
	common->tv_sec = base_interval.tv_sec * inew;
99
100
	common->tv_nsec = ((uint64_t)base_interval.tv_nsec * inew) % 1000000000ull;
	common->tv_sec += ((uint64_t)base_interval.tv_nsec * inew) / 1000000000ull;
101
102
103
104
105
106
107
108
109
110
}

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 fullrate = false;
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
111
112
113
114
115
116
	if (priv->keep) {
		interval.tv_sec = 1;
		type = TRACE_INTERVAL_TYPE_INTERVAL;
	} else {
		interval.tv_sec = 0;
	}
117
118
119
120
121
122
	interval.tv_nsec = 0;
	
	
	for (i = 0; i < priv->nr_clients; i++) {
		switch (priv->clients[i]->interval_type) {
			case TRACE_INTERVAL_TYPE_INTERVAL:
Jeroen Vreeken's avatar
Jeroen Vreeken committed
123
124
				if (type && type != TRACE_INTERVAL_TYPE_INTERVAL) {
					printf("Different types requested\n");
125
126
127
128
129
130
131
132
133
134
135
					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:
Jeroen Vreeken's avatar
Jeroen Vreeken committed
136
137
				if (type && type != TRACE_INTERVAL_TYPE_CHANGED) {
					printf("Different types requested\n");
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
					fullrate = true;
				} else {
					type = TRACE_INTERVAL_TYPE_CHANGED;
				}
				break;
			default:
				break;
		}
		
	}

	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)) {
		
		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);
		
165
		trace_interval_set(server, &interval, type);
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
	}
}

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
188

Jeroen Vreeken's avatar
Jeroen Vreeken committed
189
190
191
192
193
194
195
196
197
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
198

199
200
201
202
static void client_interval(struct trace *trace, 
    struct timespec *interval, enum trace_interval_type type)
{
	struct trace_pkt *pkt;
203
	struct trace *server;
204

205
206
207
208
	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) */
209
210
211
212
213
	pkt = trace_packet_new();
	trace_packet_interval_set(pkt, 
	    interval, type);
	trace_packet_write(trace, pkt);
	trace_packet_put(pkt);
214
215
216
217
218
219

	server = server_find_client(trace);
	if (!server)
		return;
		
	server_interval_check(server);
220
221
}

Jeroen Vreeken's avatar
Jeroen Vreeken committed
222
static struct trace_pkt *list_pkt;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
223
224
225
226
227
228
229
230
231
232
233
234
235
static char **list_names;
static int nr_list_names;

static bool check_list(char *name)
{
	int i;
	
	for (i = 0; i < nr_list_names; i++) {
		if (!strcmp(name, list_names[i]))
			return true;
	}
	return false;
}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
236

Jeroen Vreeken's avatar
Jeroen Vreeken committed
237
238
239
240
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
241

Jeroen Vreeken's avatar
Jeroen Vreeken committed
242
243
244
245
	nr_list_names++;
	list_names = realloc(list_names, sizeof(char *)*nr_list_names);
	list_names[nr_list_names-1] = strdup(name);

Jeroen Vreeken's avatar
Jeroen Vreeken committed
246
247
	trace_autorecover(trace, false);
}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
248

249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
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)
{
266
267
268
269
270
271
272
273
274
	uint64_t t64, tdiv64;
	
	t64 = (uint64_t)t->tv_sec * 1000000000ull + (uint64_t)t->tv_nsec;
	tdiv64 = (uint64_t)tdiv->tv_sec * 1000000000ull + (uint64_t)tdiv->tv_nsec;
	
	if (!tdiv64)
		return false;
	
	return t64 % tdiv64;
275
}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
276

277
static void server_value(struct trace *trace, int channel,
Jeroen Vreeken's avatar
Jeroen Vreeken committed
278
    struct trace_value *value)
Jeroen Vreeken's avatar
Jeroen Vreeken committed
279
{
Jeroen Vreeken's avatar
Jeroen Vreeken committed
280
281
	struct trace_pkt *pkt;
	struct private *priv = trace->private;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
282
283
	int i;
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
284
	if (priv->nr_clients) {
285
286
287
288
289
290
291
		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
292

Jeroen Vreeken's avatar
Jeroen Vreeken committed
293
		pkt = trace_packet_new();
294
		trace_packet_value_add(pkt, 0, value, trace->type);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
295
296
	
		for (i = 0; i < priv->nr_clients; i++) {
297
298
299
300
			bool send = false;
			
			switch (priv->clients[i]->interval_type) {
				case TRACE_INTERVAL_TYPE_CHANGED:
Jeroen Vreeken's avatar
Jeroen Vreeken committed
301
					send = changed || priv->firstvalue;
302
303
304
305
306
307
308
309
310
311
312
313
314
					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
315
			trace_packet_write(priv->clients[i], pkt);
316
			if (check_client(priv, i)) {
317
				server_interval_check(trace);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
318
319
				i--;
				continue;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
320
321
			}
		}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
322
323
		trace_packet_put(pkt);
	}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
324
	priv->firstvalue = false;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
325
}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
326

Jeroen Vreeken's avatar
Jeroen Vreeken committed
327
328
329
330
331
332
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
333
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
334
335
336
	if (priv->nr_clients) {
		pkt = trace_packet_new();
		trace_packet_timestamp_set(pkt, timestamp);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
337
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
338
		for (i = 0; i < priv->nr_clients; i++) {
339
340
341
342
343
			if (priv->clients[i]->interval_type ==
			    TRACE_INTERVAL_TYPE_INTERVAL &&
			    priv->clients[i]->interval.tv_sec &&
			    timestamp->tv_sec % priv->clients[i]->interval.tv_sec)
				continue;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
344
			trace_packet_write(priv->clients[i], pkt);
345
			if (check_client(priv, i)) {
346
				server_interval_check(trace);
347
348
349
				i--;
				continue;
			}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
350
351
		}
		trace_packet_put(pkt);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
352
353
	}
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
354
	if (!priv->nr_clients && trace->fd >= 0 && priv->lastclient + TIMEOUT < time(NULL) && !priv->keep) {
Jeroen Vreeken's avatar
Jeroen Vreeken committed
355
356
357
358
359
		printf("Timeout, closing trace\n");
		trace_close(trace);
		trace_autorecover(trace, false);
	}
}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
360
361


Jeroen Vreeken's avatar
Jeroen Vreeken committed
362
363
364
365
366
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
367
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
368
369
	pkt = trace_packet_new();
	trace_packet_type_set(pkt, type);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
370
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
371
372
373
374
375
	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
376
377
}

Jeroen Vreeken's avatar
Jeroen Vreeken committed
378
static void client_accept(int fd_listen)
Jeroen Vreeken's avatar
Jeroen Vreeken committed
379
{
Jeroen Vreeken's avatar
Jeroen Vreeken committed
380
381
	int fd;
	struct trace *client;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
382
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
383
384
	fd = tcp_accept(fd_listen);
	if (fd < 0)
Jeroen Vreeken's avatar
Jeroen Vreeken committed
385
386
		return;
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
387
	printf("New client\n");
Jeroen Vreeken's avatar
Jeroen Vreeken committed
388
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
389
390
391
	client = trace_alloc();
	if (!client) {
		close(fd);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
392
393
394
		return;
	}
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
395
396
	trace_initialize_fd(client, fd);

397
	trace_packet_write(client, caps_pkt);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
398
399
	trace_packet_write(client, interval_pkt);
	trace_packet_write(client, list_pkt);
400
	client->handler_interval = client_interval;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
401
402
403
404
405
406

	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
407
408
}

Jeroen Vreeken's avatar
Jeroen Vreeken committed
409
static void free_client(int i)
Jeroen Vreeken's avatar
Jeroen Vreeken committed
410
{
Jeroen Vreeken's avatar
Jeroen Vreeken committed
411
412
413
	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
414
415
}

Jeroen Vreeken's avatar
Jeroen Vreeken committed
416
417

static void free_server(int i)
Jeroen Vreeken's avatar
Jeroen Vreeken committed
418
{
Jeroen Vreeken's avatar
Jeroen Vreeken committed
419
420
421
	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
422
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
423
	printf("Freed server, %d left\n", nr_server_traces);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
424
425
}

Jeroen Vreeken's avatar
Jeroen Vreeken committed
426
static struct trace *server_find(char *name)
Jeroen Vreeken's avatar
Jeroen Vreeken committed
427
{
Jeroen Vreeken's avatar
Jeroen Vreeken committed
428
429
	struct trace *trace;
	struct private *priv;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
430
431
	int i;
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
432
433
434
	if (!check_list(name))
		return NULL;
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
435
436
437
	for (i = 0; i < nr_server_traces; i++) {
		if (!strcmp(server_traces[i]->name, name))
			break;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
438
	}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
439
440
	
	if (i == nr_server_traces) {
441
442
		struct trace_pkt *pkt;
		
Jeroen Vreeken's avatar
Jeroen Vreeken committed
443
		trace = trace_open(tr_host, tr_port);
444
		trace_name_set(trace, 0, name);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
445
		
446
447
448
449
450
451
452
453
		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
454
455
456
457
458
		server_traces = realloc(server_traces, 
		    sizeof(struct trace *) * (nr_server_traces + 1));
		
		priv = calloc(sizeof(struct private), 1);
		trace->private = priv;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
459
		priv->firstvalue = true;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
460
461
462
463
464
465
466
467
468
469
470
471
		
		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
472
473
}

Jeroen Vreeken's avatar
Jeroen Vreeken committed
474
static void client_add(struct trace *client)
Jeroen Vreeken's avatar
Jeroen Vreeken committed
475
{
Jeroen Vreeken's avatar
Jeroen Vreeken committed
476
477
	struct trace *trace;
	struct private *priv;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
478
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
479
	printf("Going to add client to trace '%s'\n", client->name);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
480
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
481
	trace = server_find(client->name);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
482
483
484
	if (!trace) {
		trace_free(client);
		printf("Trace not found\n");
485
		return;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
486
	}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
487
488
	
	priv = trace->private;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
489

Jeroen Vreeken's avatar
Jeroen Vreeken committed
490
491
492
493
494
495
496
	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
497
	}
498
499
500
	if (trace->value_set) {
		struct trace_pkt *pkt;

Jeroen Vreeken's avatar
Jeroen Vreeken committed
501
502
503
504
505
		pkt = trace_packet_new();
		trace_packet_timestamp_set(pkt, &trace->value.t);
		trace_packet_write(client, pkt);
		trace_packet_put(pkt);

506
		pkt = trace_packet_new();
507
		trace_packet_value_add(pkt, 0, &trace->value, trace->type);
508
509
510
		trace_packet_write(client, pkt);
		trace_packet_put(pkt);
	}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
511
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
512
513
514
515
	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
516

517
	server_interval_check(trace);
518

Jeroen Vreeken's avatar
Jeroen Vreeken committed
519
520
521
	printf("Trace now has %d clients\n", priv->nr_clients);
}

Jeroen Vreeken's avatar
Jeroen Vreeken committed
522

Jeroen Vreeken's avatar
Jeroen Vreeken committed
523
int main (int argc, char **argv)
Jeroen Vreeken's avatar
Jeroen Vreeken committed
524
{
Jeroen Vreeken's avatar
Jeroen Vreeken committed
525
	int fd_listen;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
526
	fd_set fd_rd;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
527
	struct trace *list;
528
	int high, i, j;
529
530
531
532

	log_client_start(dt_host_console(), CONSOLE_LOG_PORT_IN,
	   LOG_T_DEBUG, LOG_T_INFO, "trace_proxy");

Jeroen Vreeken's avatar
Jeroen Vreeken committed
533
534
535
536
537
538
539
540
541
	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;
	}

	signal(SIGPIPE, SIG_IGN);

        /* determine socket on dt_ctrl */
542
543
	tr_host = dt_host_trace_proxy_src_host();
	tr_port = dt_host_trace_proxy_src_port();
Jeroen Vreeken's avatar
Jeroen Vreeken committed
544
545
546
547
548
549
550
551
552

	/* 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);

553
554
555
	caps_pkt = trace_packet_new();
	trace_packet_capabilities_set(caps_pkt, TRACE_CAP_PROXY);

Jeroen Vreeken's avatar
Jeroen Vreeken committed
556
557
558
559
560
561
562
563
564
565
566
567
568
	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
569
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
570
571
572
573
574
575
576
577
		/* 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);

Daan Vreeken's avatar
Daan Vreeken committed
578
	printf("Received list from server, now waiting for clients\n");
Jeroen Vreeken's avatar
Jeroen Vreeken committed
579

Jeroen Vreeken's avatar
Jeroen Vreeken committed
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
	dt_host_trace_proxy_keep(&keep_traces, &nr_keep_traces);
	for (i = 0; i < nr_keep_traces; i++) {
		struct trace *trace;
		
		trace = server_find(keep_traces[i]);
		if (trace) {
			struct private *priv = trace->private;
			
			priv->keep = true;
			server_interval_check(trace);
			printf("Pre-opened trace: %s\n", keep_traces[i]);
		} else {
			printf("Failed to pre-open: %s\n", keep_traces[i]);
		}
	}

Jeroen Vreeken's avatar
Jeroen Vreeken committed
596
597
598
	while (1) {
		struct timeval timeout;
		
Jeroen Vreeken's avatar
Jeroen Vreeken committed
599
600
		FD_ZERO(&fd_rd);
		
Jeroen Vreeken's avatar
Jeroen Vreeken committed
601
		timeout.tv_sec = 10;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
602
		timeout.tv_usec = 0;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
603
604
605
		
		high = fd_listen;
		FD_SET(fd_listen, &fd_rd);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
606
607
608

		for (i = 0; i < nr_client_traces; i++) {
			trace_fd_set(client_traces[i], &fd_rd, &high);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
609
		}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
610
		for (i = 0; i < nr_server_traces; i++) {
611
612
			struct private *priv = server_traces[i]->private;
			
Jeroen Vreeken's avatar
Jeroen Vreeken committed
613
			trace_fd_set(server_traces[i], &fd_rd, &high);
614
615
616
			for (j = 0; j < priv->nr_clients; j++) {
				trace_fd_set(priv->clients[j], &fd_rd, &high);
			}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
617
618
619
620
		}
		
		select(high + 1, &fd_rd, NULL, NULL, &timeout);
		
Jeroen Vreeken's avatar
Jeroen Vreeken committed
621
		if (FD_ISSET(fd_listen, &fd_rd)) {
Jeroen Vreeken's avatar
Jeroen Vreeken committed
622
			client_accept(fd_listen);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
623
		}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
624

Jeroen Vreeken's avatar
Jeroen Vreeken committed
625
626
627
628
629
630
631
632
		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
633
634
				continue;
			}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
635
636
637
638
639
640
641
			
			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
642
643
644
				continue;
			}
		}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
645
		for (i = 0; i < nr_server_traces; i++) {
646
647
			struct private *priv = server_traces[i]->private;
			
Jeroen Vreeken's avatar
Jeroen Vreeken committed
648
649
			if (trace_handle(server_traces[i], &fd_rd))
				continue;
650
651
652
			for (j = 0; j < priv->nr_clients; j++) {
				trace_handle(priv->clients[j], &fd_rd);
			}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
653
654
655
656
657
658
659
660
661
662
663

			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
664
665
666
667
668
		}
	}

	return 0;
}