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
#TRACE_TARGETS += $(DIR)/trace_fft
TRACE_TARGETS += $(DIR)/trace_list
TRACE_TARGETS += $(DIR)/trace_view
TRACE_TARGETS += $(DIR)/trace2file
ARCHSRCS := $(DIR)/trace.c $(DIR)/trace_tcp.c
ARCHOBJS := $(ARCHSRCS:.c=.lo)
......@@ -46,6 +48,13 @@ $(DIR)/trace_view: libtrace.la
$(DIR)/trace_view_LDFLAGS += -ltrace
$(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)
SRCS += $(ARCHSRCS)
SRCS += $(TRACE_DUMP_SRCS)
......@@ -53,9 +62,11 @@ SRCS += $(TRACE_DUMPDIFF_SRCS)
SRCS += $(TRACE_FFT_SRCS)
SRCS += $(TRACE_LIST_SRCS)
SRCS += $(TRACE_VIEW_SRCS)
SRCS += $(TRACE2FILE_SRCS)
CLEAN += $(TRACE_TARGETS) $(ARCHOBJS) $(LIBDIR)/libtrace.a
CLEAN += $(TRACE_DUMP_OBJS)
CLEAN += $(TRACE_DUMPDIFF_OBJS)
CLEAN += $(TRACE_FFT_OBJS)
CLEAN += $(TRACE_LIST_OBJS)
CLEAN += $(TRACE_VIEW_OBJS)
CLEAN += $(TRACE2FILE_OBJS)
......@@ -123,6 +123,7 @@ struct trace {
struct trace_value *value);
void (*handler_name)(struct trace *, char *name);
void (*handler_close)(struct trace *);
size_t (*handler_read)(struct trace *, void *buf, size_t len);
void *private;
};
......@@ -154,6 +155,7 @@ void trace_packet_put(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);
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)
struct trace *trace;
struct trace_pkt *pkt;
int interval = 1;
uint64_t nsec_interval;
if (argc < 4) {
printf("Usage:\n\n");
......@@ -126,14 +127,14 @@ int main(int argc, char **argv)
printf("Connection ready for tracing\n");
if (interval != 1) {
t_int.tv_sec *= interval;
t_int.tv_nsec *= interval;
if (interval) {
nsec_interval = t_int.tv_sec * 1000000000;
nsec_interval += t_int.tv_nsec;
if (t_int.tv_nsec >= 1000000000) {
t_int.tv_sec++;
t_int.tv_nsec -= 1000000000;
}
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,
......
......@@ -123,7 +123,14 @@ bool trace_fd_read(struct trace *trace)
ret = read(trace->fd, trace->rx_buffer + trace->rx_len, TRACE_BUF_BLOCK);
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++) {
......@@ -197,7 +204,7 @@ err_pkt:
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 start = 0;
......@@ -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) {
unsigned char *seq;
r = write(trace->fd, pkt->data + start, i - start);
r = write(fd, pkt->data + start, i - start);
if (r != i - start)
goto err_write;
......@@ -219,23 +226,34 @@ int trace_packet_write(struct trace *trace, struct trace_pkt *pkt)
seq = (unsigned char[2]){ TRACE_ESC, TRACE_ESC_ESC };
else
seq = (unsigned char[2]){ TRACE_ESC, TRACE_ESC_END };
r = write(trace->fd, seq, 2);
r = write(fd, seq, 2);
if (r != 2)
goto err_write;
} 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)
goto err_write;
start = i + 1;
}
}
r = write(trace->fd, &(char[1]){ TRACE_END }, 1);
r = write(fd, &(char[1]){ TRACE_END }, 1);
if (r < 0)
goto err_write;
return 0;
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);
if (trace->fd >= 0)
close(trace->fd);
......
......@@ -25,6 +25,8 @@
#include <magic.h>
#include <libwebsockets.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <dirent.h>
#include <dt_port_numbers.h>
#include <utils/tcp_connect.h>
......@@ -34,6 +36,138 @@
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
struct pollfd pollfds[MAX_POLL_ELEMENTS];
int count_pollfds = 0;
......@@ -143,7 +277,7 @@ static void start_status(struct libwebsocket *wsi, char *ident)
static int status_handle(struct status *status)
{
int r;
unsigned char *linebuf = status->linebuf;
char *linebuf = (char *)status->linebuf;
int pos = status->pos;
int fd = status->fd;
char *ident = status->ident;
......@@ -154,16 +288,19 @@ static int status_handle(struct status *status)
for (i = 0; i <r; i++) {
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;
sprintf(msg,
wb->msg_len = sprintf(wb->msg,
"status %s %s\n",
ident, linebuf);
if (!lws_send_pipe_choked(status->wsi))
libwebsocket_write (status->wsi,
(unsigned char*)msg, strlen(msg),
LWS_WRITE_TEXT);
writebuf_add(ws_client, wb);
ws_client_flush(ws_client);
if (r - i - 1 > 0)
memmove(
linebuf,
......@@ -173,10 +310,10 @@ static int status_handle(struct status *status)
}
}
pos += r;
} else if (errno != EAGAIN) {
} else if (r == 0 || errno != EAGAIN) {
close(fd);
fd = -1;
poll_remove(fd);
fd = -1;
}
status->pos = pos;
status->fd = fd;
......@@ -251,56 +388,57 @@ static void handler_trace_value(struct trace *trace,
struct trace_value *value)
{
struct libwebsocket *wsi;
char premsg[LWS_SEND_BUFFER_PRE_PADDING + LWS_SEND_BUFFER_POST_PADDING + strlen(trace->name) + 100];
char *msg = premsg + LWS_SEND_BUFFER_PRE_PADDING;
struct ws_client *ws_client;
struct writebuf *wb;
wsi = trace->private;
ws_client = ws_client_get_by_wsi(wsi);
wb = writebuf_alloc(strlen(trace->name) + 100);
switch (trace->type) {
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,
value->t.tv_sec, value->t.tv_nsec, value->value.f);
break;
case TRACE_VALUE_TYPE_BOOL:
sprintf(msg, "trace %s %ld.%09ld %d\n",
wb->msg_len = sprintf(wb->msg, "trace %s %ld.%09ld %d\n",
trace->name,
value->t.tv_sec, value->t.tv_nsec, value->value.b);
break;
case TRACE_VALUE_TYPE_UINT8:
sprintf(msg, "trace %s %ld.%09ld %u\n",
wb->msg_len = sprintf(wb->msg, "trace %s %ld.%09ld %u\n",
trace->name,
value->t.tv_sec, value->t.tv_nsec, value->value.u8);
break;
case TRACE_VALUE_TYPE_UINT16:
sprintf(msg, "trace %s %ld.%09ld %u\n",
wb->msg_len = sprintf(wb->msg, "trace %s %ld.%09ld %u\n",
trace->name,
value->t.tv_sec, value->t.tv_nsec, value->value.u16);
break;
case TRACE_VALUE_TYPE_UINT32:
sprintf(msg, "trace %s %ld.%09ld %u\n",
wb->msg_len = sprintf(wb->msg, "trace %s %ld.%09ld %u\n",
trace->name,
value->t.tv_sec, value->t.tv_nsec, value->value.u32);
break;
case TRACE_VALUE_TYPE_SINT8:
sprintf(msg, "trace %s %ld.%09ld %d\n",
wb->msg_len = sprintf(wb->msg, "trace %s %ld.%09ld %d\n",
trace->name,
value->t.tv_sec, value->t.tv_nsec, value->value.s8);
break;
case TRACE_VALUE_TYPE_SINT16:
sprintf(msg, "trace %s %ld.%09ld %d\n",
wb->msg_len = sprintf(wb->msg, "trace %s %ld.%09ld %d\n",
trace->name,
value->t.tv_sec, value->t.tv_nsec, value->value.s16);
break;
case TRACE_VALUE_TYPE_SINT32:
sprintf(msg, "trace %s %ld.%09ld %d\n",
wb->msg_len = sprintf(wb->msg, "trace %s %ld.%09ld %d\n",
trace->name,
value->t.tv_sec, value->t.tv_nsec, value->value.s32);
break;
}
if (!lws_send_pipe_choked(wsi))
libwebsocket_write(wsi, (unsigned char*)msg, strlen(msg),
LWS_WRITE_TEXT);
writebuf_add(ws_client, wb);
ws_client_flush(ws_client);
}
static void start_trace(struct libwebsocket *wsi, int freq, char *variable)
......@@ -310,8 +448,13 @@ static void start_trace(struct libwebsocket *wsi, int freq, char *variable)
enum trace_interval_type type;
int fd;
if (count_traces + 1 >= MAX_TRACE_ELEMENTS)
return;
trace = trace_open("localhost", 10000);
if (!trace)
return;
trace_name_set(trace, variable);
free(variable);
......@@ -465,6 +608,67 @@ int exec_cgi(struct libwebsocket *wsi, char *requested_uri, char *resource_path)
return -1;
}
int list_dir(struct libwebsocket_context *context, struct libwebsocket *wsi, char *requested_uri, char *resource_path)
{
unsigned char *outdata = malloc(1000);
size_t pos = 0;
DIR *dir;
struct dirent *dirent;
unsigned char *h = outdata;
char *server = "console_httpd libwebsockets";
char *type = "text/html";
if (lws_add_http_header_status(context, wsi, 200, &h, outdata + 1000))
return 1;
if (lws_add_http_header_by_token(context, wsi,
WSI_TOKEN_HTTP_SERVER,
(unsigned char *)server, strlen(server), &h, outdata + 1000))
return 1;
if (lws_add_http_header_by_token(context, wsi,
WSI_TOKEN_HTTP_CONTENT_TYPE,
(unsigned char *)type, strlen(type), &h, outdata + 1000))
return 1;
if (lws_finalize_http_header(context, wsi, &h, outdata + 1000))
return 1;
pos += h - outdata;
libwebsocket_write(wsi, outdata, pos, LWS_WRITE_HTTP_HEADERS);
free(outdata);
outdata = NULL;
pos = 0;
dir = opendir(resource_path);