Commit 514cb21b authored by Jeroen Vreeken's avatar Jeroen Vreeken
Browse files

Lots of UI updates

Introduce trace2file and new trace parser code
Sat tracker fixes
parent ae3e6837
...@@ -5,6 +5,8 @@ TRACE_TARGETS += $(DIR)/trace_dumpdiff ...@@ -5,6 +5,8 @@ TRACE_TARGETS += $(DIR)/trace_dumpdiff
#TRACE_TARGETS += $(DIR)/trace_fft #TRACE_TARGETS += $(DIR)/trace_fft
TRACE_TARGETS += $(DIR)/trace_list TRACE_TARGETS += $(DIR)/trace_list
TRACE_TARGETS += $(DIR)/trace_view TRACE_TARGETS += $(DIR)/trace_view
TRACE_TARGETS += $(DIR)/trace2file
ARCHSRCS := $(DIR)/trace.c $(DIR)/trace_tcp.c ARCHSRCS := $(DIR)/trace.c $(DIR)/trace_tcp.c
ARCHOBJS := $(ARCHSRCS:.c=.lo) ARCHOBJS := $(ARCHSRCS:.c=.lo)
...@@ -46,6 +48,13 @@ $(DIR)/trace_view: libtrace.la ...@@ -46,6 +48,13 @@ $(DIR)/trace_view: libtrace.la
$(DIR)/trace_view_LDFLAGS += -ltrace $(DIR)/trace_view_LDFLAGS += -ltrace
$(DIR)/trace_view: $(TRACE_VIEW_OBJS) $(DIR)/trace_view: $(TRACE_VIEW_OBJS)
TRACE2FILE_SRCS := $(DIR)/trace2file.c
TRACE2FILE_OBJS := $(TRACE2FILE_SRCS:.c=.o)
$(DIR)/trace2file: libtrace.la
$(DIR)/trace2file_LDFLAGS += -ltrace
$(DIR)/trace2file: $(TRACE2FILE_OBJS)
TARGETS += $(TRACE_TARGETS) TARGETS += $(TRACE_TARGETS)
SRCS += $(ARCHSRCS) SRCS += $(ARCHSRCS)
SRCS += $(TRACE_DUMP_SRCS) SRCS += $(TRACE_DUMP_SRCS)
...@@ -53,9 +62,11 @@ SRCS += $(TRACE_DUMPDIFF_SRCS) ...@@ -53,9 +62,11 @@ SRCS += $(TRACE_DUMPDIFF_SRCS)
SRCS += $(TRACE_FFT_SRCS) SRCS += $(TRACE_FFT_SRCS)
SRCS += $(TRACE_LIST_SRCS) SRCS += $(TRACE_LIST_SRCS)
SRCS += $(TRACE_VIEW_SRCS) SRCS += $(TRACE_VIEW_SRCS)
SRCS += $(TRACE2FILE_SRCS)
CLEAN += $(TRACE_TARGETS) $(ARCHOBJS) $(LIBDIR)/libtrace.a CLEAN += $(TRACE_TARGETS) $(ARCHOBJS) $(LIBDIR)/libtrace.a
CLEAN += $(TRACE_DUMP_OBJS) CLEAN += $(TRACE_DUMP_OBJS)
CLEAN += $(TRACE_DUMPDIFF_OBJS) CLEAN += $(TRACE_DUMPDIFF_OBJS)
CLEAN += $(TRACE_FFT_OBJS) CLEAN += $(TRACE_FFT_OBJS)
CLEAN += $(TRACE_LIST_OBJS) CLEAN += $(TRACE_LIST_OBJS)
CLEAN += $(TRACE_VIEW_OBJS) CLEAN += $(TRACE_VIEW_OBJS)
CLEAN += $(TRACE2FILE_OBJS)
...@@ -123,6 +123,7 @@ struct trace { ...@@ -123,6 +123,7 @@ struct trace {
struct trace_value *value); struct trace_value *value);
void (*handler_name)(struct trace *, char *name); void (*handler_name)(struct trace *, char *name);
void (*handler_close)(struct trace *); void (*handler_close)(struct trace *);
size_t (*handler_read)(struct trace *, void *buf, size_t len);
void *private; void *private;
}; };
...@@ -154,6 +155,7 @@ void trace_packet_put(struct trace_pkt *pkt); ...@@ -154,6 +155,7 @@ void trace_packet_put(struct trace_pkt *pkt);
void trace_packet_initialize(struct trace_pkt *pkt); void trace_packet_initialize(struct trace_pkt *pkt);
int trace_packet_write_fd(int fd, struct trace_pkt *pkt);
int trace_packet_write(struct trace *trace, struct trace_pkt *pkt); int trace_packet_write(struct trace *trace, struct trace_pkt *pkt);
struct trace_pkt *trace_packet_new(void); struct trace_pkt *trace_packet_new(void);
......
/*
Copyright Jeroen Vreeken (pe1rxq@amsat.org), 2007, 2008, 2011, 2013
Copyright Stichting C.A. Muller Radioastronomiestation, 2007, 2008, 2011
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/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <math.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <trace/trace.h>
static struct timespec t_int;
static char *tracename;
static int fd_file = 1;
static void handler_interval(struct trace *trace,
struct timespec *interval, enum trace_interval_type type)
{
memcpy(&t_int, interval, sizeof(struct timespec));
printf("interval: %ld.%09ld\n", interval->tv_sec, interval->tv_nsec);
}
size_t trace_handler_read(struct trace *trace, void *buf, size_t len)
{
ssize_t r;
r = write(fd_file, buf, len);
if (r != len) {
printf("Could not write %d bytes to file %d : %d: %s\n",
r, fd_file, len, strerror(errno));
exit(1);
}
return 0;
}
int main(int argc, char **argv)
{
struct trace *trace;
struct trace_pkt *pkt;
int interval = 1;
uint64_t nsec_interval;
if (argc < 5) {
printf("Usage:\n\n");
printf("%s [host] [port] [trace] [file] <interval>\n", argv[0]);
return 0;
}
tracename = argv[3];
trace = trace_open(argv[1], atoi(argv[2]));
fd_file = open(argv[4], O_WRONLY | O_APPEND | O_CREAT,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (fd_file < 0) {
printf("%s Could not open output file %s\n", argv[0], argv[4]);
return 0;
}
if (argc >= 6) {
interval = atoi(argv[5]);
}
trace->handler_interval = handler_interval;
while (trace_state_get(trace) == TRACE_STATE_CONNECTED) {
fd_set fdrx;
int high = 0;
FD_ZERO(&fdrx);
trace_fd_set(trace, &fdrx, &high);
select(high + 1, &fdrx, NULL, NULL, NULL);
trace_handle(trace, &fdrx);
}
printf("Connection ready for tracing\n");
if (interval) {
nsec_interval = t_int.tv_sec * 1000000000;
nsec_interval += t_int.tv_nsec;
nsec_interval *= interval;
t_int.tv_nsec = nsec_interval % 1000000000;
t_int.tv_sec = nsec_interval / 1000000000;
pkt = trace_packet_new();
trace_packet_interval_set(pkt,
&t_int, TRACE_INTERVAL_TYPE_INTERVAL);
trace_packet_write(trace, pkt);
trace_packet_write_fd(fd_file, pkt);
trace_packet_put(pkt);
}
pkt = trace_packet_new();
trace_packet_name_set(pkt, tracename);
trace_packet_write(trace, pkt);
trace_packet_write_fd(fd_file, pkt);
trace_packet_put(pkt);
trace->handler_read = trace_handler_read;
printf("Wait for data and dump to file\n");
while (trace_state_get(trace) == TRACE_STATE_RECEIVING ||
trace_state_get(trace) == TRACE_STATE_READY) {
fd_set fdrx;
int high = 0;
FD_ZERO(&fdrx);
trace_fd_set(trace, &fdrx, &high);
select(high + 1, &fdrx, NULL, NULL, NULL);
trace_handle(trace, &fdrx);
}
return 0;
}
...@@ -92,6 +92,7 @@ int main(int argc, char **argv) ...@@ -92,6 +92,7 @@ int main(int argc, char **argv)
struct trace *trace; struct trace *trace;
struct trace_pkt *pkt; struct trace_pkt *pkt;
int interval = 1; int interval = 1;
uint64_t nsec_interval;
if (argc < 4) { if (argc < 4) {
printf("Usage:\n\n"); printf("Usage:\n\n");
...@@ -126,14 +127,14 @@ int main(int argc, char **argv) ...@@ -126,14 +127,14 @@ int main(int argc, char **argv)
printf("Connection ready for tracing\n"); printf("Connection ready for tracing\n");
if (interval != 1) { if (interval) {
t_int.tv_sec *= interval; nsec_interval = t_int.tv_sec * 1000000000;
t_int.tv_nsec *= interval; nsec_interval += t_int.tv_nsec;
if (t_int.tv_nsec >= 1000000000) { nsec_interval *= interval;
t_int.tv_sec++;
t_int.tv_nsec -= 1000000000; t_int.tv_nsec = nsec_interval % 1000000000;
} t_int.tv_sec = nsec_interval / 1000000000;
pkt = trace_packet_new(); pkt = trace_packet_new();
trace_packet_interval_set(pkt, trace_packet_interval_set(pkt,
......
...@@ -123,7 +123,14 @@ bool trace_fd_read(struct trace *trace) ...@@ -123,7 +123,14 @@ bool trace_fd_read(struct trace *trace)
ret = read(trace->fd, trace->rx_buffer + trace->rx_len, TRACE_BUF_BLOCK); ret = read(trace->fd, trace->rx_buffer + trace->rx_len, TRACE_BUF_BLOCK);
if (ret > 0) { if (ret > 0) {
trace->rx_len += ret; size_t newbuf = ret;
if (trace->handler_read) {
newbuf = trace->handler_read(trace,
trace->rx_buffer + trace->rx_len, ret);
}
trace->rx_len += newbuf;
} }
for (i = 0; i < trace->rx_len; i++) { for (i = 0; i < trace->rx_len; i++) {
...@@ -197,7 +204,7 @@ err_pkt: ...@@ -197,7 +204,7 @@ err_pkt:
return NULL; return NULL;
} }
int trace_packet_write(struct trace *trace, struct trace_pkt *pkt) int trace_packet_write_fd(int fd, struct trace_pkt *pkt)
{ {
int i; int i;
int start = 0; int start = 0;
...@@ -210,7 +217,7 @@ int trace_packet_write(struct trace *trace, struct trace_pkt *pkt) ...@@ -210,7 +217,7 @@ int trace_packet_write(struct trace *trace, struct trace_pkt *pkt)
if (pkt->data[i] == TRACE_ESC || pkt->data[i] == TRACE_END) { if (pkt->data[i] == TRACE_ESC || pkt->data[i] == TRACE_END) {
unsigned char *seq; unsigned char *seq;
r = write(trace->fd, pkt->data + start, i - start); r = write(fd, pkt->data + start, i - start);
if (r != i - start) if (r != i - start)
goto err_write; goto err_write;
...@@ -219,23 +226,34 @@ int trace_packet_write(struct trace *trace, struct trace_pkt *pkt) ...@@ -219,23 +226,34 @@ int trace_packet_write(struct trace *trace, struct trace_pkt *pkt)
seq = (unsigned char[2]){ TRACE_ESC, TRACE_ESC_ESC }; seq = (unsigned char[2]){ TRACE_ESC, TRACE_ESC_ESC };
else else
seq = (unsigned char[2]){ TRACE_ESC, TRACE_ESC_END }; seq = (unsigned char[2]){ TRACE_ESC, TRACE_ESC_END };
r = write(trace->fd, seq, 2); r = write(fd, seq, 2);
if (r != 2) if (r != 2)
goto err_write; goto err_write;
} else if (i == pkt->len -1) { } else if (i == pkt->len -1) {
r = write(trace->fd, pkt->data + start, i - start + 1); r = write(fd, pkt->data + start, i - start + 1);
if (r != i - start + 1) if (r != i - start + 1)
goto err_write; goto err_write;
start = i + 1; start = i + 1;
} }
} }
r = write(trace->fd, &(char[1]){ TRACE_END }, 1); r = write(fd, &(char[1]){ TRACE_END }, 1);
if (r < 0) if (r < 0)
goto err_write; goto err_write;
return 0; return 0;
err_write: err_write:
return -1;
}
int trace_packet_write(struct trace *trace, struct trace_pkt *pkt)
{
int r;
r = trace_packet_write_fd(trace->fd, pkt);
if (r == 0)
return 0;
log_send(LOG_T_DEBUG, "Error during write, closing %d", trace->fd); log_send(LOG_T_DEBUG, "Error during write, closing %d", trace->fd);
if (trace->fd >= 0) if (trace->fd >= 0)
close(trace->fd); close(trace->fd);
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
#include <magic.h> #include <magic.h>
#include <libwebsockets.h> #include <libwebsockets.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/types.h>
#include <dirent.h>
#include <dt_port_numbers.h> #include <dt_port_numbers.h>
#include <utils/tcp_connect.h> #include <utils/tcp_connect.h>
...@@ -34,6 +36,138 @@ ...@@ -34,6 +36,138 @@
magic_t magic; magic_t magic;
struct writebuf {
char *data;
char *msg;
size_t msg_len;
struct writebuf *next;
};
struct ws_client {
struct libwebsocket_context *context;
struct libwebsocket *wsi;
struct writebuf *writeq;
struct ws_client *next;
};
struct writebuf *writebuf_alloc(size_t msglen)
{
struct writebuf *wb;
wb = malloc(sizeof(struct writebuf));
if (!wb)
return NULL;
wb->data = malloc(msglen +
LWS_SEND_BUFFER_PRE_PADDING +
LWS_SEND_BUFFER_POST_PADDING);
wb->msg = wb->data + LWS_SEND_BUFFER_PRE_PADDING;
return wb;
}
void writebuf_free(struct writebuf *wb)
{
free(wb->data);
free(wb);
}
void writebuf_add(struct ws_client *client, struct writebuf *wb)
{
struct writebuf **entry;
for (entry = &client->writeq; *entry; entry = &(*entry)->next);
*entry = wb;
wb->next = NULL;
}
struct writebuf *writebuf_next(struct ws_client *client)
{
struct writebuf *wb;
if (!client->writeq)
return NULL;
wb = client->writeq;
client->writeq = wb->next;
return wb;
}
struct ws_client *ws_client_list = NULL;
struct ws_client *ws_client_add(struct libwebsocket_context *context, struct libwebsocket *wsi)
{
struct ws_client *client;
client = calloc(sizeof(struct ws_client), 1);
if (!client)
return NULL;
client->context = context;
client->wsi = wsi;
client->next = ws_client_list;
ws_client_list = client;
return client;
}
void ws_client_remove(struct ws_client *client)
{
struct ws_client **entry;
for (entry = &ws_client_list; *entry; entry = &(*entry)->next) {
if (*entry == client) {
struct writebuf *wb;
while ((wb = writebuf_next(client))) {
writebuf_free(wb);
}
*entry = (*entry)->next;
free(client);
return;
}
}
}
struct ws_client *ws_client_get_by_wsi(struct libwebsocket *wsi)
{
struct ws_client *entry;
for (entry = ws_client_list; entry; entry = entry->next)
if (entry->wsi == wsi)
return entry;
printf("wsi %p not found\n", wsi);
return NULL;
}
void ws_client_flush(struct ws_client *client)
{
while (client->writeq) {
struct writebuf *wb;
if (lws_send_pipe_choked(client->wsi))
break;
wb = writebuf_next(client);
libwebsocket_write(client->wsi, (unsigned char *)wb->msg, wb->msg_len, LWS_WRITE_TEXT);
writebuf_free(wb);
}
if (client->writeq) {
libwebsocket_callback_on_writable(client->context, client->wsi);
}
}
#define MAX_POLL_ELEMENTS 256 #define MAX_POLL_ELEMENTS 256
struct pollfd pollfds[MAX_POLL_ELEMENTS]; struct pollfd pollfds[MAX_POLL_ELEMENTS];
int count_pollfds = 0; int count_pollfds = 0;
...@@ -143,7 +277,7 @@ static void start_status(struct libwebsocket *wsi, char *ident) ...@@ -143,7 +277,7 @@ static void start_status(struct libwebsocket *wsi, char *ident)
static int status_handle(struct status *status) static int status_handle(struct status *status)
{ {
int r; int r;
unsigned char *linebuf = status->linebuf; char *linebuf = (char *)status->linebuf;
int pos = status->pos; int pos = status->pos;
int fd = status->fd; int fd = status->fd;
char *ident = status->ident; char *ident = status->ident;
...@@ -154,16 +288,19 @@ static int status_handle(struct status *status) ...@@ -154,16 +288,19 @@ static int status_handle(struct status *status)
for (i = 0; i <r; i++) { for (i = 0; i <r; i++) {
if (linebuf[pos + i] == '\n') { if (linebuf[pos + i] == '\n') {
char *msg = status->msg; struct ws_client *ws_client;
struct writebuf *wb;
ws_client = ws_client_get_by_wsi(status->wsi);
wb = writebuf_alloc(strlen(ident)+strlen(linebuf)+100);
linebuf[pos + i] = 0; linebuf[pos + i] = 0;
sprintf(msg, wb->msg_len = sprintf(wb->msg,
"status %s %s\n", "status %s %s\n",
ident, linebuf); ident, linebuf);
if (!lws_send_pipe_choked(status->wsi)) writebuf_add(ws_client, wb);
libwebsocket_write (status->wsi, ws_client_flush(ws_client);
(unsigned char*)msg, strlen(msg),
LWS_WRITE_TEXT);
if (r - i - 1 > 0) if (r - i - 1 > 0)
memmove( memmove(
linebuf, linebuf,
...@@ -173,10 +310,10 @@ static int status_handle(struct status *status) ...@@ -173,10 +310,10 @@ static int status_handle(struct status *status)
} }
} }
pos += r; pos += r;
} else if (errno != EAGAIN) { } else if (r == 0 || errno != EAGAIN) {
close(fd); close(fd);
fd = -1;
poll_remove(fd); poll_remove(fd);
fd = -1;
} }
status->pos = pos; status->pos = pos;
status->fd = fd; status->fd = fd;
...@@ -251,56 +388,57 @@ static void handler_trace_value(struct trace *trace, ...@@ -251,56 +388,57 @@ static void handler_trace_value(struct trace *trace,
struct trace_value *value) struct trace_value *value)
{ {
struct libwebsocket *wsi; struct libwebsocket *wsi;
char premsg[LWS_SEND_BUFFER_PRE_PADDING + LWS_SEND_BUFFER_POST_PADDING + strlen(trace->name) + 100]; struct ws_client *ws_client;
char *msg = premsg + LWS_SEND_BUFFER_PRE_PADDING; struct writebuf *wb;
wsi = trace->private; wsi = trace->private;
ws_client = ws_client_get_by_wsi(wsi);
wb = writebuf_alloc(strlen(trace->name) + 100);
switch (trace->type) { switch (trace->type) {
case TRACE_VALUE_TYPE_FLOAT: case TRACE_VALUE_TYPE_FLOAT:
sprintf(msg, "trace %s %ld.%09ld %e\n", wb->msg_len = sprintf(wb->msg, "trace %s %ld.%09ld %e\n",
trace->name, trace->name,
value->t.tv_sec, value->t.tv_nsec, value->value.f); value->t.tv_sec, value->t.tv_nsec, value->value.f);
break; break;
case TRACE_VALUE_TYPE_BOOL: case TRACE_VALUE_TYPE_BOOL:
sprintf(msg, "trace %s %ld.%09ld %d\n",