Skip to content

Commit

Permalink
Added files and code for a communication thread that inserts keep-ali…
Browse files Browse the repository at this point in the history
…ve tokens.

This prevents socat from dropping the connection if the communication is idle.
  • Loading branch information
modmaker committed Jun 15, 2012
1 parent 771ebd8 commit e0d92d9
Show file tree
Hide file tree
Showing 4 changed files with 191 additions and 23 deletions.
4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ SOURCES = \
temp.c \
thermistor.c \
traject.c \
comm.c \
$(PROGRAM).c

CC = $(CROSS_COMPILE)gcc
Expand Down Expand Up @@ -161,6 +162,7 @@ temp.o: temp.c temp.h beaglebone.h analog.h debug.h mendel.h
thermistor.o: thermistor.c beaglebone.h thermistor.h
traject.o: traject.c bebopr.h traject.h pruss_stepper.h algo2cmds.h \
debug.h beaglebone.h mendel.h
comm.o: comm.c comm.h mendel.h bebopr.h debug.h beaglebone.h
mendel.o: mendel.c heater.h temp.h beaglebone.h pwm.h bebopr.h mendel.h \
gcode_process.h gcode_parse.h limit_switches.h traject.h pruss_stepper.h \
algo2cmds.h
algo2cmds.h comm.h
161 changes: 161 additions & 0 deletions comm.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@

#define _GNU_SOURCE /* for pipe2 */

#include <sys/types.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <poll.h>
#include <pthread.h>

#include "comm.h"
#include "mendel.h"
#include "bebopr.h"
#include "debug.h"
#include "beaglebone.h"

/*
* Simple keep alive implementation needed until I find out
* how to keep the socat connection alive otherwise
*/

static struct pollfd fds[ 4];

static int fd_stdin;
static int fd_stdout;
static int alt_stdin;
static int alt_stdout;


static void* comm_thread( void* arg)
{
const int timeout = 10000; /* ms */

if (debug_flags & DEBUG_LIMSW) {
printf( "Socket connection keep-alive thread: started.");
}

// read from system stdin
fds[ 0].fd = fd_stdin;
fds[ 0].events = POLLIN | POLLPRI;
// write to system stdout
fds[ 1].fd = fd_stdout;
fds[ 1].events = POLLERR | POLLHUP;
// read from stdout pipe
fds[ 2].fd = alt_stdout;
fds[ 2].events = POLLIN | POLLPRI;
// write to stdin pipe
fds[ 3].fd = alt_stdin;
fds[ 3].events = POLLERR | POLLHUP;

while (1) {
int rc = poll( fds, NR_ITEMS( fds), timeout);
if (rc < 0) {
perror( "comm_thread: poll() failed, bailing out!");
break;
} else if (rc == 0) {
// timeout, send dummy character to keep connection alive
printf( "%c", 255);
fflush( stdout);
fprintf( stderr, "<KEEP ALIVE SENT>\n");
} else {
// input pending
for (int i = 0 ; i < NR_ITEMS( fds) ; ++i) {
int events = fds[ i].revents;
if (events & POLLHUP) {
if (i == 0) {
fprintf( stderr, "comm_thread: lost connection on STDIN, closing down.\n");
close( alt_stdout);
close( alt_stdin);
pthread_exit( NULL);
} else {
fprintf( stderr, "Poll on fd %d returns POLLHUP\n", i);
}
} else if (events & POLLERR) {
fprintf( stderr, "Poll on fd %d returns POLLERR\n", i);
} else if (events & POLLNVAL) {
fprintf( stderr, "Poll on fd %d returns POLLNVAL\n", i);
} else if (events & POLLPRI) {
fprintf( stderr, "Poll on fd %d returns POLLPRI\n", i);
} else if (events & POLLIN) {
if (i == 2) {
// stdout pipe has output for stdout
char s[ 1];
read( fds[ 2].fd, s, sizeof( s));
write( fds[ 1].fd, s, sizeof( s));
} else if (i == 0) {
// stdin has input for stdin pipe
char s[ 1];
read( fds[ 0].fd, s, sizeof( s));
write( fds[ 3].fd, s, sizeof( s));
} else {
fprintf( stderr, "Poll on fd %d returns POLLIN\n", i);
}
} else if (events & POLLOUT) {
fprintf( stderr, "Poll on fd %d returns POLLOUT\n", i);
}
}
}
}
pthread_exit( NULL);
}

static pthread_t worker;

/*
* Fixup file descriptors so that all stdin and stdout of the application
* is piped to alt_stdout (for stdout) and alt_stdin (for stdin).
* Now we can watch and modify the datastream from and to the application.
* That allows us to insert keep-alive characters to keep socat happy!
*/
int comm_init( void)
{
int result;
int fds[ 2];

// keep a copy of the program's original fds for stdin and stdout
fd_stdin = fcntl( 0, F_DUPFD);
fd_stdout = fcntl( 1, F_DUPFD);
fprintf( stderr, "fd_stdin = %d, fd_stdout = %d\n", fd_stdin, fd_stdout);

// create the stdout pipe with all new fds
result = pipe2( fds, 0);
if (result < 0) {
perror( "stdout pipe creation failed");
return -1;
}
fprintf( stderr, "stdout pipe created: output side fd = %d, input side fd = %d\n", fds[ 0], fds[ 1]);
// close application's stdout descriptor (1)
close( 1);
// connect input/write side of stdout pipe to application's stdout descriptor (1)
result = fcntl( fds[ 1], F_DUPFD);
close( fds[ 1]);
fds[ 1] = result;
fprintf( stderr, "stdout pipe fixed: output side fd = %d, input side fd = %d\n", fds[ 0], fds[ 1]);

alt_stdout = fds[ 0];
fprintf( stderr, "alt_stdout = %d\n", alt_stdout);

close( 0);
result = pipe2( fds, 0);
if (result < 0) {
perror( "pipe_out creation failed");
return -1;
}
fprintf( stderr, "stdin pipe created: output side fd = %d, input side fd = %d\n", fds[ 0], fds[ 1]);
alt_stdin = fds[ 1];
fprintf( stderr, "alt_stdin = %d\n", alt_stdout);

result = mendel_thread_create( "comm", &worker, NULL, &comm_thread, NULL);
if (result != 0) {
exit( EXIT_FAILURE);
}
struct sched_param param = {
.sched_priority = 74
};
// SCHED_RR seems to work for now, otherwise use SCHED_FIFO
pthread_setschedparam( worker, SCHED_RR, &param);

return 0;
}
8 changes: 8 additions & 0 deletions comm.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef _COMM_H
#define _COMM_H


extern int comm_init( void);


#endif
41 changes: 19 additions & 22 deletions mendel.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "gcode_parse.h"
#include "limit_switches.h"
#include "pruss_stepper.h"
#include "comm.h"


static int arm_init( void)
Expand Down Expand Up @@ -66,13 +67,18 @@ int init( void)
signal( SIGHUP, signal_handler);
signal( SIGTERM, signal_handler);

// configure
result = mendel_sub_init( "bebopr", bebopr_pre_init);
// set up arm & linux specific stuff
result = mendel_sub_init( "arm", arm_init);
if (result != 0) {
return result;
}
// set up arm & linux specific stuff
result = mendel_sub_init( "arm", arm_init);
// keep connector alive
result = mendel_sub_init( "comm", comm_init);
if (result != 0) {
return result;
}
// configure
result = mendel_sub_init( "bebopr", bebopr_pre_init);
if (result != 0) {
return result;
}
Expand Down Expand Up @@ -129,36 +135,27 @@ int mendel_sub_init( const char* name, int (*subsys)( void))
// FIXME: Implement proper program termination and un-init functions.
int main (void)
{
int block = 0;
if (init() != 0) {
fprintf( stderr, "Initialization failed, terminating the application.\n");
fprintf( stderr, "Initialization failed, terminating.\n");
exit( EXIT_FAILURE);
}

fprintf( stderr, "Starting main loop...\n");

for (;;) {
char s[ 100];
if (pruss_queue_full()) {
if (block) {
usleep( 1000);
} else {
fprintf( stderr, "<queue_full>");
block = 1;
}

if (fgets( s, sizeof( s), stdin) == NULL) {
fprintf( stderr, "main loop - EOF on input, terminating.\n");
exit( 0);
} else {
block = 0;
if (fgets( s, sizeof( s), stdin) != NULL) {
char* p = s;
fprintf( stderr, "Got '%s'\r\n", s);
while (*p) {
gcode_parse_char( *p++);
}
} else {
sched_yield();
char* p = s;
while (*p) {
gcode_parse_char( *p++);
}
}
}
}

// -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
// ex:ts=4:sw=4:sts=4:et

0 comments on commit e0d92d9

Please sign in to comment.