Commit 4b4f6282 authored by Jeroen Vreeken's avatar Jeroen Vreeken
Browse files

Fix a 100% cpu bug in websocket module

Remove old status cgi binary
Use status cod in websocket for status handling
parent c43b8625
......@@ -339,14 +339,14 @@ int trace_packet_type_set(struct trace_pkt *pkt, enum trace_value_type type)
return 0;
}
void trace_fd_set(struct trace *trace, fd_set *set, int *high)
bool trace_fd_set(struct trace *trace, fd_set *set, int *high)
{
if (trace->fd < 0) {
if (!trace->recover)
return;
return false;
if (trace->recovertime >= time(NULL))
return;
return false;
trace->recovertime = time(NULL);
log_send(LOG_T_DEBUG, "Attempt to recover trace %s",
......@@ -374,7 +374,7 @@ void trace_fd_set(struct trace *trace, fd_set *set, int *high)
}
if (trace->fd < 0) {
log_send(LOG_T_DEBUG, "Failed to recover");
return;
return false;
}
log_send(LOG_T_DEBUG, "Reconnected trace");
}
......@@ -383,6 +383,8 @@ void trace_fd_set(struct trace *trace, fd_set *set, int *high)
if (trace->fd > *high)
*high = trace->fd;
return true;
}
int trace_handle(struct trace *trace, fd_set *set)
......
......@@ -169,7 +169,7 @@ int trace_packet_name_set(struct trace_pkt *pkt, char *name);
int trace_packet_type_set(struct trace_pkt *pkt, enum trace_value_type type);
int trace_packet_value_add(struct trace_pkt *pkt, struct trace_value *value, enum trace_value_type type);
void trace_fd_set(struct trace *trace, fd_set *set, int *high);
bool trace_fd_set(struct trace *trace, fd_set *set, int *high);
int trace_handle(struct trace *trace, fd_set *set);
enum trace_state trace_state_get(struct trace *trace);
......
......@@ -29,7 +29,10 @@
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#ifdef __linux__
#include <linux/sockios.h>
#endif
#include "tcp_connect.h"
......@@ -112,6 +115,7 @@ int tcp_connect(char *host, int port)
int tcp_flushwrite(int sock)
{
#ifdef __linux__
int retries = 20;
while(retries--) {
......@@ -126,6 +130,7 @@ int tcp_flushwrite(int sock)
}
return 0;
#endif
}
int tcp_flushread(int sock)
......
......@@ -25,7 +25,6 @@ all: lib/libaa.la lib/libpredict.la \
console_weather console_dt_model \
await_controller \
console_sattracker \
status.cgi_install \
mod_websocket_dt/mod_websocket_dt.so \
......@@ -85,12 +84,6 @@ spg_auth: spg_auth.o setpoint.o
console_sattracker_LDFLAGS= -lpthread $(LIBNOVA) -lm -lpredict
console_sattracker: console_sattracker.o setpoint.o lib/libpredict.la
status.cgi: status.cgi.o
status.cgi_install: status.cgi
@echo " CP status.cgi"
@cp status.cgi ../htdocs
lib/libaa.la:
@$(MAKE) -C aalib
......@@ -129,7 +122,6 @@ clean:
spg_auth \
spg_list \
spg_log_parser \
status.cgi \
trace_proxy \
trace_proxy \
trace_log
......
......@@ -122,7 +122,10 @@ void *trace_thread(void *arg)
FD_ZERO(&fdrx);
trace_fd_set(trace, &fdrx, &high);
if (!trace_fd_set(trace, &fdrx, &high)) {
sleep(1);
continue;
}
to.tv_sec = 1;
to.tv_usec = 0;
......@@ -180,6 +183,101 @@ static void start_trace(struct plugin_private *priv, int freq, char *variable)
priv->nr_threads++;
}
struct status {
char *ident;
struct plugin_private *priv;
};
void *status_thread(void *arg)
{
struct status *status = arg;
char *ident = status->ident;
struct plugin_private *priv = status->priv;
char *host;
int port = -1;
int fd = -1;
free(status);
host = dt_host_console();
if (!strcmp(ident, "sat"))
port = CONSOLE_SAT_STAT_PORT;
else if (!strcmp(ident, "sun"))
port = CONSOLE_SUN_STAT_PORT;
else if (!strcmp(ident, "moon"))
port = CONSOLE_MOON_STAT_PORT;
else if (!strcmp(ident, "auth"))
port = CONSOLE_STATUS_PORT;
else if (!strcmp(ident, "j2000"))
port = CONSOLE_J2000_POS_PORT;
else if (!strcmp(ident, "log"))
port = CONSOLE_LOG_PORT;
else if (!strcmp(ident, "weather"))
port = CONSOLE_WEATHER_PORT;
else if (!strcmp(ident, "dt_model"))
port = CONSOLE_DT_MODEL_STAT_PORT;
while (priv->connected) {
unsigned char linebuf[1000];
char *msg;
int r;
fd_set fd_rd;
struct timeval timeout;
if (fd < 0) {
fd = tcp_connect(host, port);
if (fd < 0) {
sleep(1);
continue;
}
}
timeout.tv_usec = 0;
timeout.tv_sec = 10;
FD_ZERO(&fd_rd);
FD_SET(fd, &fd_rd);
select(fd + 1, &fd_rd, NULL, NULL, &timeout);
if (FD_ISSET(fd, &fd_rd)) {
r = read(fd, linebuf, 999);
if (r > 0) {
linebuf[r] = 0;
asprintf(&msg, "status %s %s",
ident, linebuf);
priv->server->send(priv->server,
MESSAGE_TYPE_TEXT,
(unsigned char *)msg, strlen(msg));
} else {
close(fd);
fd = -1;
sleep(1);
}
}
}
free(ident);
return NULL;
}
static void start_status(struct plugin_private *priv, char *ident)
{
struct status *status;
status = malloc(sizeof(struct status));
status->priv = priv;
status->ident = ident;
pthread_create(&priv->threads[priv->nr_threads], NULL,
status_thread, status);
priv->nr_threads++;
}
static void do_command(char *ident, char *command)
{
char *host;
......@@ -290,6 +388,11 @@ static size_t on_message(void *plugin_private,
command = text + strlen(cmd) + 1;
do_shell(command);
} else if (!strcmp(cmd, "status")) {
char *ident;
sscanf(text, "%*s %as", &ident);
start_status(priv, ident);
} else {
server->send(priv->server, MESSAGE_TYPE_TEXT,
buffer, buffer_size);
......
/*
HTTP frontend for status updates
Copyright Jeroen Vreeken (pe1rxq@amsat.org), 2013
Copyright Stichting C.A. Muller Radioastronomiestation, 2013
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 <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include "tcp_connect.h"
#include "dt_port_numbers.h"
#include "dt_host.h"
int main(int argc, char **argv)
{
int fd;
char *query;
char *host;
int port = -1;
query=getenv("QUERY_STRING");
host = dt_host_console();
if (!strcmp(query, "sat"))
port = CONSOLE_SAT_STAT_PORT;
else if (!strcmp(query, "sun"))
port = CONSOLE_SUN_STAT_PORT;
else if (!strcmp(query, "moon"))
port = CONSOLE_MOON_STAT_PORT;
else if (!strcmp(query, "auth"))
port = CONSOLE_STATUS_PORT;
else if (!strcmp(query, "j2000"))
port = CONSOLE_J2000_POS_PORT;
else if (!strcmp(query, "log"))
port = CONSOLE_LOG_PORT;
else if (!strcmp(query, "weather"))
port = CONSOLE_WEATHER_PORT;
else if (!strcmp(query, "dt_model"))
port = CONSOLE_DT_MODEL_STAT_PORT;
fd = tcp_connect(host, port);
if (fd >= 0) {
ioctl(fd, FIONBIO, &(int){ 0 });
printf("Content-type: text/event-stream\n");
printf("Cache-Control: no-cache\n");
printf("Pragma: no-cache\n");
printf("\n");
while (1) {
char linebuf[1000];
int r;
fd_set fd_rd;
struct timeval timeout;
timeout.tv_usec = 0;
timeout.tv_sec = 10;
FD_ZERO(&fd_rd);
FD_SET(fd, &fd_rd);
select(fd + 1, &fd_rd, NULL, NULL, &timeout);
if (FD_ISSET(fd, &fd_rd)) {
r = read(fd, linebuf, 999);
if (r > 0) {
linebuf[r] = 0;
r = printf("data: %s\n", linebuf);
fflush(0);
if (r < 0)
break;
} else {
printf(": lost connection\n\n");
fflush(0);
sleep(1);
break;
}
} else {
printf(":\n\n");
fflush(0);
}
}
} else {
printf("Content-type: text/event-stream\n");
printf("Cache-Control: no-cache\n");
printf("Pragma: no-cache\n");
printf("\n");
sleep(1);
printf(":failed\n");
printf(":No response from %s:%d '%s'\n\n", host, port, query);
fflush(0);
}
return 0;
}
......@@ -41,6 +41,8 @@ function dt_websocket(url)
this.ws.onopen = function()
{
var i;
for (i = 0; i < dt_socket_onopen.length; i++) {
dt_socket_onopen[i].func(dt_socket_onopen[i].obj);
}
......@@ -55,6 +57,7 @@ function dt_websocket(url)
this.ws.onmessage = function(msg)
{
var args = msg.data.split(" ");
var i;
for (i = 0; i < dt_socket_onmessage.length; i++) {
if(dt_socket_onmessage[i].name == args[0]) {
......
......@@ -19,29 +19,67 @@
*/
var status_loaded;
if (!status_loaded) {
status_loaded = true;
eval(load("dt_websocket.js"));
var status_connected;
function status_cb_default (switches)
{
/* default callback */
}
var status_priv_list = new Array();
function status_onopen(obj)
{
for (i = 0; i < status_priv_list.length; i++) {
dt_websocket_send("status " +
status_priv_list[i].ident);
}
status_connected = true;
}
dt_websocket_onopen_add("status", status_onopen, null);
function status_onmessage(obj, args)
{
for (i = 0; i < status_priv_list.length; i++) {
if (status_priv_list[i].ident == args[1]) {
status_priv_list[i].callback(args.slice(2).join(" "));
break;
}
}
}
dt_websocket_onmessage_add("status", status_onmessage, null);
function status(url, ident)
{
var realthis = this;
this.url = url;
this.ident = ident;
this.callback = status_cb_default;
this.source;
this.nr = -1;
this.open = function status_open() {
this.source = new EventSource(this.url + "?" + this.ident);
this.source.onmessage = this.onmessage;
}
this.onmessage = function (event) {
realthis.callback(event.data);
if (realthis.nr < 0) {
realthis.nr = status_priv_list.length;
status_priv_list[realthis.nr] = realthis;
}
if (status_connected) {
dt_websocket_send("status " +
realthis.ident);
}
}
}
} /* status_loaded */
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment