Make examples compileable

This commit is contained in:
Keith Winstein
2012-02-06 19:20:44 -05:00
parent 27eed9fdb7
commit a164a84496
8 changed files with 36 additions and 11 deletions
+1 -1
View File
@@ -1 +1 @@
SUBDIRS = protobufs util crypto terminal network statesync frontend
SUBDIRS = protobufs util crypto terminal network statesync frontend examples
+25
View File
@@ -0,0 +1,25 @@
AM_CXXFLAGS = --std=c++0x -pedantic -Werror -Wall -Wextra -Weffc++ -fno-default-inline -pipe
noinst_PROGRAMS = encrypt decrypt ntester parse termemu
LIBS = `pkg-config --libs protobuf-lite`
encrypt_SOURCES = encrypt.cc
encrypt_CPPFLAGS = -I$(srcdir)/../crypto
encrypt_LDADD = ../crypto/libmoshcrypto.a
decrypt_SOURCES = decrypt.cc
decrypt_CPPFLAGS = -I$(srcdir)/../crypto
decrypt_LDADD = ../crypto/libmoshcrypto.a
parse_SOURCES = parse.cc
parse_CPPFLAGS = -I$(srcdir)/../terminal -I$(srcdir)/../util
parse_LDADD = ../terminal/libmoshterminal.a ../util/libmoshutil.a -lutil
termemu_SOURCES = termemu.cc
termemu_CPPFLAGS = -I$(srcdir)/../terminal -I$(srcdir)/../util -I$(srcdir)/../statesync -I$(builddir)/../protobufs
termemu_LDADD = ../terminal/libmoshterminal.a ../util/libmoshutil.a ../statesync/libmoshstatesync.a ../protobufs/libmoshprotos.a -lutil
ntester_SOURCES = ntester.cc
ntester_CPPFLAGS = -I$(srcdir)/../statesync -I$(srcdir)/../terminal -I$(srcdir)/../network -I$(srcdir)/../crypto -I$(builddir)/../protobufs
ntester_LDADD = ../statesync/libmoshstatesync.a ../terminal/libmoshterminal.a ../network/libmoshnetwork.a ../crypto/libmoshcrypto.a ../protobufs/libmoshprotos.a -lutil -lrt -lm
+60
View File
@@ -0,0 +1,60 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#include <string.h>
#include <unistd.h>
#include <iostream>
#include "crypto.h"
using namespace Crypto;
int main( int argc, char *argv[] )
{
if ( argc != 2 ) {
fprintf( stderr, "Usage: %s KEY\n", argv[ 0 ] );
return 1;
}
try {
Base64Key key( argv[ 1 ] );
Session session( key );
/* Read input */
char *input = NULL;
int total_size = 0;
while ( 1 ) {
unsigned char buf[ 16384 ];
ssize_t bytes_read = read( STDIN_FILENO, buf, 16384 );
if ( bytes_read == 0 ) { /* EOF */
break;
} else if ( bytes_read < 0 ) {
perror( "read" );
exit( 1 );
} else {
input = (char *)realloc( input, total_size + bytes_read );
assert( input );
memcpy( input + total_size, buf, bytes_read );
total_size += bytes_read;
}
}
string ciphertext( input, total_size );
free( input );
/* Decrypt message */
Message message = session.decrypt( ciphertext );
fprintf( stderr, "Nonce = %ld\n",
(long)message.nonce.val() );
cout << message.text;
} catch ( CryptoException e ) {
cerr << e.text << endl;
exit( 1 );
}
return 0;
}
+61
View File
@@ -0,0 +1,61 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#include <string.h>
#include <unistd.h>
#include <iostream>
#include "crypto.h"
using namespace Crypto;
int main( int argc, char *argv[] )
{
if ( argc != 2 ) {
fprintf( stderr, "Usage: %s NONCE\n", argv[ 0 ] );
return 1;
}
try {
Base64Key key;
Session session( key );
Nonce nonce( myatoi( argv[ 1 ] ) );
/* Read input */
char *input = NULL;
int total_size = 0;
while ( 1 ) {
unsigned char buf[ 16384 ];
ssize_t bytes_read = read( STDIN_FILENO, buf, 16384 );
if ( bytes_read == 0 ) { /* EOF */
break;
} else if ( bytes_read < 0 ) {
perror( "read" );
exit( 1 );
} else {
input = (char *)realloc( input, total_size + bytes_read );
assert( input );
memcpy( input + total_size, buf, bytes_read );
total_size += bytes_read;
}
}
string plaintext( input, total_size );
free( input );
/* Encrypt message */
string ciphertext = session.encrypt( Message( nonce, plaintext ) );
cerr << "Key: " << key.printable_key() << endl;
cout << ciphertext;
} catch ( CryptoException e ) {
cerr << e.text << endl;
exit( 1 );
}
return 0;
}
+124
View File
@@ -0,0 +1,124 @@
#include <termios.h>
#include <unistd.h>
#include <poll.h>
#include "user.h"
#include "networktransport.cc"
using namespace Network;
int main( int argc, char *argv[] )
{
bool server = true;
char *key;
char *ip;
int port;
UserStream me, remote;
Transport<UserStream, UserStream> *n;
try {
if ( argc > 1 ) {
server = false;
/* client */
key = argv[ 1 ];
ip = argv[ 2 ];
port = atoi( argv[ 3 ] );
n = new Transport<UserStream, UserStream>( me, remote, key, ip, port );
} else {
n = new Transport<UserStream, UserStream>( me, remote, NULL );
}
} catch ( CryptoException e ) {
fprintf( stderr, "Fatal error: %s\n", e.text.c_str() );
exit( 1 );
}
fprintf( stderr, "Port bound is %d, key is %s\n", n->port(), n->get_key().c_str() );
if ( server ) {
struct pollfd my_pollfd;
my_pollfd.fd = n->fd();
my_pollfd.events = POLLIN;
uint64_t last_num = n->get_remote_state_num();
while ( true ) {
try {
if ( poll( &my_pollfd, 1, n->wait_time() ) < 0 ) {
perror( "poll" );
exit( 1 );
}
n->tick();
if ( my_pollfd.revents & POLLIN ) {
n->recv();
if ( n->get_remote_state_num() != last_num ) {
fprintf( stderr, "[%d=>%d %s]", (int)last_num, (int)n->get_remote_state_num(), n->get_remote_diff().c_str() );
last_num = n->get_remote_state_num();
}
}
} catch ( CryptoException e ) {
fprintf( stderr, "Cryptographic error: %s\n", e.text.c_str() );
}
}
} else {
struct termios saved_termios;
struct termios the_termios;
if ( tcgetattr( STDIN_FILENO, &the_termios ) < 0 ) {
perror( "tcgetattr" );
exit( 1 );
}
saved_termios = the_termios;
cfmakeraw( &the_termios );
if ( tcsetattr( STDIN_FILENO, TCSANOW, &the_termios ) < 0 ) {
perror( "tcsetattr" );
exit( 1 );
}
struct pollfd fds[ 2 ];
fds[ 0 ].fd = STDIN_FILENO;
fds[ 0 ].events = POLLIN;
fds[ 1 ].fd = n->fd();
fds[ 1 ].events = POLLIN;
while( true ) {
try {
if ( poll( fds, 2, n->wait_time() ) < 0 ) {
perror( "poll" );
}
n->tick();
if ( fds[ 0 ].revents & POLLIN ) {
char x;
assert( read( STDIN_FILENO, &x, 1 ) == 1 );
n->get_current_state().push_back( Parser::UserByte( x ) );
}
if ( fds[ 1 ].revents & POLLIN ) {
n->recv();
}
} catch ( NetworkException e ) {
fprintf( stderr, "%s: %s\r\n", e.function.c_str(), strerror( e.the_errno ) );
break;
} catch ( CryptoException e ) {
fprintf( stderr, "Cryptographic error: %s\n", e.text.c_str() );
}
}
if ( tcsetattr( STDIN_FILENO, TCSANOW, &saved_termios ) < 0 ) {
perror( "tcsetattr" );
exit( 1 );
}
}
delete n;
}
+187
View File
@@ -0,0 +1,187 @@
#include <pty.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <poll.h>
#include <string.h>
#include <locale.h>
#include <langinfo.h>
#include <wchar.h>
#include <assert.h>
#include <wctype.h>
#include <iostream>
#include <typeinfo>
#include "parser.h"
#include "swrite.h"
const size_t buf_size = 1024;
void emulate_terminal( int fd );
int copy( int src, int dest );
int vt_parser( int fd, Parser::UTF8Parser *parser );
int main( int argc __attribute__((unused)),
char *argv[] __attribute__((unused)),
char *envp[] )
{
int master;
struct termios saved_termios, raw_termios, child_termios;
if ( NULL == setlocale( LC_ALL, "" ) ) {
perror( "setlocale" );
exit( 1 );
}
if ( strcmp( nl_langinfo( CODESET ), "UTF-8" ) != 0 ) {
fprintf( stderr, "stm requires a UTF-8 locale.\n" );
exit( 1 );
}
if ( tcgetattr( STDIN_FILENO, &saved_termios ) < 0 ) {
perror( "tcgetattr" );
exit( 1 );
}
child_termios = saved_termios;
if ( !(child_termios.c_iflag & IUTF8) ) {
fprintf( stderr, "Warning: Locale is UTF-8 but termios IUTF8 flag not set. Setting IUTF8 flag.\n" );
child_termios.c_iflag |= IUTF8;
}
pid_t child = forkpty( &master, NULL, &child_termios, NULL );
if ( child == -1 ) {
perror( "forkpty" );
exit( 1 );
}
if ( child == 0 ) {
/* child */
char *my_argv[ 2 ];
my_argv[ 0 ] = strdup( "/bin/bash" );
assert( my_argv[ 0 ] );
my_argv[ 1 ] = NULL;
if ( execve( "/bin/bash", my_argv, envp ) < 0 ) {
perror( "execve" );
exit( 1 );
}
exit( 0 );
} else {
/* parent */
raw_termios = saved_termios;
cfmakeraw( &raw_termios );
if ( tcsetattr( STDIN_FILENO, TCSANOW, &raw_termios ) < 0 ) {
perror( "tcsetattr" );
exit( 1 );
}
emulate_terminal( master );
if ( tcsetattr( STDIN_FILENO, TCSANOW, &saved_termios ) < 0 ) {
perror( "tcsetattr" );
exit( 1 );
}
}
return 0;
}
void emulate_terminal( int fd )
{
Parser::UTF8Parser parser;
struct pollfd pollfds[ 2 ];
pollfds[ 0 ].fd = STDIN_FILENO;
pollfds[ 0 ].events = POLLIN;
pollfds[ 1 ].fd = fd;
pollfds[ 1 ].events = POLLIN;
while ( 1 ) {
int active_fds = poll( pollfds, 2, -1 );
if ( active_fds <= 0 ) {
perror( "poll" );
return;
}
if ( pollfds[ 0 ].revents & POLLIN ) {
if ( copy( STDIN_FILENO, fd ) < 0 ) {
return;
}
} else if ( pollfds[ 1 ].revents & POLLIN ) {
if ( vt_parser( fd, &parser ) < 0 ) {
return;
}
} else if ( (pollfds[ 0 ].revents | pollfds[ 1 ].revents)
& (POLLERR | POLLHUP | POLLNVAL) ) {
return;
} else {
fprintf( stderr, "poll mysteriously woken up\n" );
}
}
}
int copy( int src, int dest )
{
char buf[ buf_size ];
ssize_t bytes_read = read( src, buf, buf_size );
if ( bytes_read == 0 ) { /* EOF */
return -1;
} else if ( bytes_read < 0 ) {
perror( "read" );
return -1;
}
return swrite( dest, buf, bytes_read );
}
int vt_parser( int fd, Parser::UTF8Parser *parser )
{
char buf[ buf_size ];
/* fill buffer if possible */
ssize_t bytes_read = read( fd, buf, buf_size );
if ( bytes_read == 0 ) { /* EOF */
return -1;
} else if ( bytes_read < 0 ) {
perror( "read" );
return -1;
}
/* feed to parser */
for ( int i = 0; i < bytes_read; i++ ) {
std::list<Parser::Action *> actions = parser->input( buf[ i ] );
for ( std::list<Parser::Action *>::iterator j = actions.begin();
j != actions.end();
j++ ) {
Parser::Action *act = *j;
assert( act );
if ( act->char_present ) {
if ( iswprint( act->ch ) ) {
printf( "%s(0x%02x=%lc) ", act->name().c_str(), act->ch, act->ch );
} else {
printf( "%s(0x%02x) ", act->name().c_str(), act->ch );
}
} else {
printf( "[%s] ", act->name().c_str() );
}
delete act;
fflush( stdout );
}
}
return 0;
}
+299
View File
@@ -0,0 +1,299 @@
#include <pty.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <poll.h>
#include <string.h>
#include <locale.h>
#include <langinfo.h>
#include <wchar.h>
#include <assert.h>
#include <wctype.h>
#include <iostream>
#include <typeinfo>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/signalfd.h>
#include <termios.h>
#include <sys/types.h>
#include <pwd.h>
#include <sys/time.h>
#include "parser.h"
#include "completeterminal.h"
#include "swrite.h"
const size_t buf_size = 16384;
void emulate_terminal( int fd );
int main( void )
{
int master;
struct termios saved_termios, raw_termios, child_termios;
if ( NULL == setlocale( LC_ALL, "" ) ) {
perror( "setlocale" );
exit( 1 );
}
if ( strcmp( nl_langinfo( CODESET ), "UTF-8" ) != 0 ) {
fprintf( stderr, "stm requires a UTF-8 locale.\n" );
exit( 1 );
}
if ( tcgetattr( STDIN_FILENO, &saved_termios ) < 0 ) {
perror( "tcgetattr" );
exit( 1 );
}
child_termios = saved_termios;
if ( !(child_termios.c_iflag & IUTF8) ) {
fprintf( stderr, "Warning: Locale is UTF-8 but termios IUTF8 flag not set. Setting IUTF8 flag.\n" );
child_termios.c_iflag |= IUTF8;
}
pid_t child = forkpty( &master, NULL, &child_termios, NULL );
if ( child == -1 ) {
perror( "forkpty" );
exit( 1 );
}
if ( child == 0 ) {
/* child */
if ( setenv( "TERM", "xterm", true ) < 0 ) {
perror( "setenv" );
exit( 1 );
}
/* ask ncurses to send UTF-8 instead of ISO 2022 for line-drawing chars */
if ( setenv( "NCURSES_NO_UTF8_ACS", "1", true ) < 0 ) {
perror( "setenv" );
exit( 1 );
}
/* get shell name */
struct passwd *pw = getpwuid( geteuid() );
if ( pw == NULL ) {
perror( "getpwuid" );
exit( 1 );
}
char *my_argv[ 2 ];
my_argv[ 0 ] = strdup( pw->pw_shell );
assert( my_argv[ 0 ] );
my_argv[ 1 ] = NULL;
if ( execve( pw->pw_shell, my_argv, environ ) < 0 ) {
perror( "execve" );
exit( 1 );
}
exit( 0 );
} else {
/* parent */
raw_termios = saved_termios;
cfmakeraw( &raw_termios );
if ( tcsetattr( STDIN_FILENO, TCSANOW, &raw_termios ) < 0 ) {
perror( "tcsetattr" );
exit( 1 );
}
emulate_terminal( master );
if ( tcsetattr( STDIN_FILENO, TCSANOW, &saved_termios ) < 0 ) {
perror( "tcsetattr" );
exit( 1 );
}
}
printf( "[stm is exiting.]\n" );
return 0;
}
/* Print a frame if the last frame was more than 1/50 seconds ago */
bool tick( Terminal::Framebuffer &state, const Terminal::Framebuffer &new_frame )
{
static bool initialized = false;
static struct timeval last_time;
struct timeval this_time;
if ( gettimeofday( &this_time, NULL ) < 0 ) {
perror( "gettimeofday" );
}
double diff = (this_time.tv_sec - last_time.tv_sec)
+ .000001 * (this_time.tv_usec - last_time.tv_usec);
if ( (!initialized)
|| (diff >= 0.02) ) {
std::string update = Terminal::Display::new_frame( initialized, state, new_frame );
swrite( STDOUT_FILENO, update.c_str() );
state = new_frame;
initialized = true;
last_time = this_time;
return true;
}
return false;
}
/* This is the main loop.
1. New bytes from the user get applied to the terminal emulator
as "UserByte" actions.
2. New bytes from the host get sent to the Parser, and then
those actions are applied to the terminal.
3. Resize events (from a SIGWINCH signal) get turned into
"Resize" actions and applied to the terminal.
At every event from poll(), we run the tick() function to
possibly print a new frame (if we haven't printed one in the
last 1/50 second). The new frames are "differential" -- they
assume the previous frame was sent to the real terminal.
*/
void emulate_terminal( int fd )
{
/* establish WINCH fd and start listening for signal */
sigset_t signal_mask;
assert( sigemptyset( &signal_mask ) == 0 );
assert( sigaddset( &signal_mask, SIGWINCH ) == 0 );
/* stop "ignoring" WINCH signal */
assert( sigprocmask( SIG_BLOCK, &signal_mask, NULL ) == 0 );
int winch_fd = signalfd( -1, &signal_mask, 0 );
if ( winch_fd < 0 ) {
perror( "signalfd" );
return;
}
/* get current window size */
struct winsize window_size;
if ( ioctl( STDIN_FILENO, TIOCGWINSZ, &window_size ) < 0 ) {
perror( "ioctl TIOCGWINSZ" );
return;
}
/* tell child process */
if ( ioctl( fd, TIOCSWINSZ, &window_size ) < 0 ) {
perror( "ioctl TIOCSWINSZ" );
return;
}
/* open parser and terminal */
Terminal::Complete complete( window_size.ws_col, window_size.ws_row );
Terminal::Framebuffer state( window_size.ws_col, window_size.ws_row );
struct pollfd pollfds[ 3 ];
pollfds[ 0 ].fd = STDIN_FILENO;
pollfds[ 0 ].events = POLLIN;
pollfds[ 1 ].fd = fd;
pollfds[ 1 ].events = POLLIN;
pollfds[ 2 ].fd = winch_fd;
pollfds[ 2 ].events = POLLIN;
swrite( STDOUT_FILENO, Terminal::Emulator::open().c_str() );
int poll_timeout = -1;
while ( 1 ) {
int active_fds = poll( pollfds, 3, poll_timeout );
if ( active_fds < 0 ) {
perror( "poll" );
break;
}
if ( pollfds[ 0 ].revents & POLLIN ) {
/* input from user */
char buf[ buf_size ];
/* fill buffer if possible */
ssize_t bytes_read = read( pollfds[ 0 ].fd, buf, buf_size );
if ( bytes_read == 0 ) { /* EOF */
return;
} else if ( bytes_read < 0 ) {
perror( "read" );
return;
}
std::string terminal_to_host;
for ( int i = 0; i < bytes_read; i++ ) {
Parser::UserByte ub( buf[ i ] );
terminal_to_host += complete.act( &ub );
}
if ( swrite( fd, terminal_to_host.c_str(), terminal_to_host.length() ) < 0 ) {
break;
}
} else if ( pollfds[ 1 ].revents & POLLIN ) {
/* input from host */
char buf[ buf_size ];
/* fill buffer if possible */
ssize_t bytes_read = read( pollfds[ 1 ].fd, buf, buf_size );
if ( bytes_read == 0 ) { /* EOF */
return;
} else if ( bytes_read < 0 ) {
perror( "read" );
return;
}
std::string terminal_to_host = complete.act( std::string( buf, bytes_read ) );
if ( swrite( fd, terminal_to_host.c_str(), terminal_to_host.length() ) < 0 ) {
break;
}
} else if ( pollfds[ 2 ].revents & POLLIN ) {
/* resize */
struct signalfd_siginfo info;
assert( read( winch_fd, &info, sizeof( info ) ) == sizeof( info ) );
assert( info.ssi_signo == SIGWINCH );
/* get new size */
if ( ioctl( STDIN_FILENO, TIOCGWINSZ, &window_size ) < 0 ) {
perror( "ioctl TIOCGWINSZ" );
return;
}
/* tell emulator */
Parser::Resize r( window_size.ws_col, window_size.ws_row );
complete.act( &r );
/* tell child process */
if ( ioctl( fd, TIOCSWINSZ, &window_size ) < 0 ) {
perror( "ioctl TIOCSWINSZ" );
return;
}
} else if ( (pollfds[ 0 ].revents | pollfds[ 1 ].revents)
& (POLLERR | POLLHUP | POLLNVAL) ) {
break;
}
if ( tick( state, complete.get_fb()) ) { /* there was a frame */
poll_timeout = -1;
} else {
poll_timeout = 20;
}
}
std::string update = Terminal::Display::new_frame( true, state, complete.get_fb() );
swrite( STDOUT_FILENO, update.c_str() );
swrite( STDOUT_FILENO, Terminal::Emulator::close().c_str() );
}