diff --git a/src/crypto/ae.h b/src/crypto/ae.h index bb1b9a057..a0d803449 100644 --- a/src/crypto/ae.h +++ b/src/crypto/ae.h @@ -32,14 +32,14 @@ extern "C" { /* Return status codes: Negative return values indicate an error occurred. * For full explanations of error values, consult the implementation's * documentation. */ -#define AE_SUCCESS ( 0 ) /* Indicates successful completion of call */ -#define AE_INVALID ( -1 ) /* Indicates bad tag during decryption */ +#define AE_SUCCESS ( 0 ) /* Indicates successful completion of call */ +#define AE_INVALID ( -1 ) /* Indicates bad tag during decryption */ #define AE_NOT_SUPPORTED ( -2 ) /* Indicates unsupported option requested */ /* Flags: When data can be processed "incrementally", these flags are used * to indicate whether the submitted data is the last or not. */ #define AE_FINALIZE ( 1 ) /* This is the last of data */ -#define AE_PENDING ( 0 ) /* More data of is coming */ +#define AE_PENDING ( 0 ) /* More data of is coming */ /* -------------------------------------------------------------------------- * @@ -55,10 +55,10 @@ typedef struct _ae_ctx ae_ctx; * * ----------------------------------------------------------------------- */ -ae_ctx *ae_allocate( void *misc ); /* Allocate ae_ctx, set optional ptr */ -void ae_free( ae_ctx *ctx ); /* Deallocate ae_ctx struct */ -int ae_clear( ae_ctx *ctx ); /* Undo initialization */ -int ae_ctx_sizeof( void ); /* Return sizeof(ae_ctx) */ +ae_ctx* ae_allocate( void* misc ); /* Allocate ae_ctx, set optional ptr */ +void ae_free( ae_ctx* ctx ); /* Deallocate ae_ctx struct */ +int ae_clear( ae_ctx* ctx ); /* Undo initialization */ +int ae_ctx_sizeof( void ); /* Return sizeof(ae_ctx) */ /* ae_allocate() allocates an ae_ctx structure, but does not initialize it. * ae_free() deallocates an ae_ctx structure, but does not zeroize it. * ae_clear() zeroes sensitive values associated with an ae_ctx structure @@ -72,8 +72,7 @@ int ae_ctx_sizeof( void ); /* Return sizeof(ae_ctx) */ * * ----------------------------------------------------------------------- */ -int ae_init( ae_ctx *ctx, const void *key, int key_len, int nonce_len, - int tag_len ); +int ae_init( ae_ctx* ctx, const void* key, int key_len, int nonce_len, int tag_len ); /* -------------------------------------------------------------------------- * * Initialize an ae_ctx context structure. @@ -92,8 +91,15 @@ int ae_init( ae_ctx *ctx, const void *key, int key_len, int nonce_len, * * ----------------------------------------------------------------------- */ -int ae_encrypt( ae_ctx *ctx, const void *nonce, const void *pt, int pt_len, - const void *ad, int ad_len, void *ct, void *tag, int final ); +int ae_encrypt( ae_ctx* ctx, + const void* nonce, + const void* pt, + int pt_len, + const void* ad, + int ad_len, + void* ct, + void* tag, + int final ); /* -------------------------------------------------------------------------- * * Encrypt plaintext; provide for authentication of ciphertext/associated data. @@ -122,8 +128,14 @@ int ae_encrypt( ae_ctx *ctx, const void *nonce, const void *pt, int pt_len, * * ----------------------------------------------------------------------- */ -int ae_decrypt( ae_ctx *ctx, const void *nonce, const void *ct, int ct_len, - const void *ad, int ad_len, void *pt, const void *tag, +int ae_decrypt( ae_ctx* ctx, + const void* nonce, + const void* ct, + int ct_len, + const void* ad, + int ad_len, + void* pt, + const void* tag, int final ); /* -------------------------------------------------------------------------- * diff --git a/src/crypto/base64.cc b/src/crypto/base64.cc index fb1c0aad3..4ef141c9c 100644 --- a/src/crypto/base64.cc +++ b/src/crypto/base64.cc @@ -36,38 +36,33 @@ #include "base64.h" #include "fatal_assert.h" -static const char table[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static const unsigned char reverse[] = { - // clang-format off - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f, - 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, - 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, - 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - // clang-format on + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, + 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, + 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }; -/* Reverse maps from an ASCII char to a base64 sixbit value. Returns > 0x3f on - * failure. */ -static unsigned char base64_char_to_sixbit( unsigned char c ) { - return reverse[ c ]; +/* Reverse maps from an ASCII char to a base64 sixbit value. Returns > 0x3f on failure. */ +static unsigned char base64_char_to_sixbit( unsigned char c ) +{ + return reverse[c]; } -bool base64_decode( const char *b64, const size_t b64_len, uint8_t *raw, - size_t *raw_len ) { +bool base64_decode( const char* b64, const size_t b64_len, uint8_t* raw, size_t* raw_len ) +{ fatal_assert( b64_len == 24 ); /* only useful for Mosh keys */ fatal_assert( *raw_len == 16 ); @@ -81,41 +76,41 @@ bool base64_decode( const char *b64, const size_t b64_len, uint8_t *raw, bytes |= sixbit; /* write groups of 3 */ if ( i % 4 == 3 ) { - raw[ 0 ] = bytes >> 16; - raw[ 1 ] = bytes >> 8; - raw[ 2 ] = bytes; + raw[0] = bytes >> 16; + raw[1] = bytes >> 8; + raw[2] = bytes; raw += 3; bytes = 0; } } /* last byte of output */ *raw = bytes >> 4; - if ( b64[ 0 ] != '=' || b64[ 1 ] != '=' ) { + if ( b64[0] != '=' || b64[1] != '=' ) { return false; } return true; } -void base64_encode( const uint8_t *raw, const size_t raw_len, char *b64, - const size_t b64_len ) { +void base64_encode( const uint8_t* raw, const size_t raw_len, char* b64, const size_t b64_len ) +{ fatal_assert( b64_len == 24 ); /* only useful for Mosh keys */ fatal_assert( raw_len == 16 ); /* first 15 bytes of input */ for ( int i = 0; i < 5; i++ ) { - uint32_t bytes = ( raw[ 0 ] << 16 ) | ( raw[ 1 ] << 8 ) | raw[ 2 ]; - b64[ 0 ] = table[ ( bytes >> 18 ) & 0x3f ]; - b64[ 1 ] = table[ ( bytes >> 12 ) & 0x3f ]; - b64[ 2 ] = table[ ( bytes >> 6 ) & 0x3f ]; - b64[ 3 ] = table[ (bytes)&0x3f ]; + uint32_t bytes = ( raw[0] << 16 ) | ( raw[1] << 8 ) | raw[2]; + b64[0] = table[( bytes >> 18 ) & 0x3f]; + b64[1] = table[( bytes >> 12 ) & 0x3f]; + b64[2] = table[( bytes >> 6 ) & 0x3f]; + b64[3] = table[(bytes)&0x3f]; raw += 3; b64 += 4; } /* last byte of input, last 4 of output */ uint8_t lastchar = *raw; - b64[ 0 ] = table[ ( lastchar >> 2 ) & 0x3f ]; - b64[ 1 ] = table[ ( lastchar << 4 ) & 0x3f ]; - b64[ 2 ] = '='; - b64[ 3 ] = '='; + b64[0] = table[( lastchar >> 2 ) & 0x3f]; + b64[1] = table[( lastchar << 4 ) & 0x3f]; + b64[2] = '='; + b64[3] = '='; } diff --git a/src/crypto/base64.h b/src/crypto/base64.h index b2bbe218c..1ed39b123 100644 --- a/src/crypto/base64.h +++ b/src/crypto/base64.h @@ -32,8 +32,6 @@ #include -bool base64_decode( const char *b64, const size_t b64_len, uint8_t *raw, - size_t *raw_len ); +bool base64_decode( const char* b64, const size_t b64_len, uint8_t* raw, size_t* raw_len ); -void base64_encode( const uint8_t *raw, const size_t raw_len, char *b64, - const size_t b64_len ); +void base64_encode( const uint8_t* raw, const size_t raw_len, char* b64, const size_t b64_len ); diff --git a/src/crypto/byteorder.h b/src/crypto/byteorder.h index 4994edf6a..91fbb5570 100644 --- a/src/crypto/byteorder.h +++ b/src/crypto/byteorder.h @@ -70,53 +70,55 @@ /* Use unions rather than casts, to comply with strict aliasing rules. */ -inline uint64_t htobe64( uint64_t x ) { - uint8_t xs[ 8 ] = { static_cast( ( x >> 56 ) & 0xFF ), - static_cast( ( x >> 48 ) & 0xFF ), - static_cast( ( x >> 40 ) & 0xFF ), - static_cast( ( x >> 32 ) & 0xFF ), - static_cast( ( x >> 24 ) & 0xFF ), - static_cast( ( x >> 16 ) & 0xFF ), - static_cast( ( x >> 8 ) & 0xFF ), - static_cast( (x)&0xFF ) }; +inline uint64_t htobe64( uint64_t x ) +{ + uint8_t xs[8] = { static_cast( ( x >> 56 ) & 0xFF ), + static_cast( ( x >> 48 ) & 0xFF ), + static_cast( ( x >> 40 ) & 0xFF ), + static_cast( ( x >> 32 ) & 0xFF ), + static_cast( ( x >> 24 ) & 0xFF ), + static_cast( ( x >> 16 ) & 0xFF ), + static_cast( ( x >> 8 ) & 0xFF ), + static_cast( (x)&0xFF ) }; union { - const uint8_t *p8; - const uint64_t *p64; + const uint8_t* p8; + const uint64_t* p64; } u; u.p8 = xs; return *u.p64; } -inline uint64_t be64toh( uint64_t x ) { +inline uint64_t be64toh( uint64_t x ) +{ union { - const uint8_t *p8; - const uint64_t *p64; + const uint8_t* p8; + const uint64_t* p64; } u; u.p64 = &x; - return ( uint64_t( u.p8[ 0 ] ) << 56 ) | ( uint64_t( u.p8[ 1 ] ) << 48 ) - | ( uint64_t( u.p8[ 2 ] ) << 40 ) | ( uint64_t( u.p8[ 3 ] ) << 32 ) - | ( uint64_t( u.p8[ 4 ] ) << 24 ) | ( uint64_t( u.p8[ 5 ] ) << 16 ) - | ( uint64_t( u.p8[ 6 ] ) << 8 ) | ( uint64_t( u.p8[ 7 ] ) ); + return ( uint64_t( u.p8[0] ) << 56 ) | ( uint64_t( u.p8[1] ) << 48 ) | ( uint64_t( u.p8[2] ) << 40 ) + | ( uint64_t( u.p8[3] ) << 32 ) | ( uint64_t( u.p8[4] ) << 24 ) | ( uint64_t( u.p8[5] ) << 16 ) + | ( uint64_t( u.p8[6] ) << 8 ) | ( uint64_t( u.p8[7] ) ); } -inline uint16_t htobe16( uint16_t x ) { - uint8_t xs[ 2 ] = { static_cast( ( x >> 8 ) & 0xFF ), - static_cast( (x)&0xFF ) }; +inline uint16_t htobe16( uint16_t x ) +{ + uint8_t xs[2] = { static_cast( ( x >> 8 ) & 0xFF ), static_cast( (x)&0xFF ) }; union { - const uint8_t *p8; - const uint16_t *p16; + const uint8_t* p8; + const uint16_t* p16; } u; u.p8 = xs; return *u.p16; } -inline uint16_t be16toh( uint16_t x ) { +inline uint16_t be16toh( uint16_t x ) +{ union { - const uint8_t *p8; - const uint16_t *p16; + const uint8_t* p8; + const uint16_t* p16; } u; u.p16 = &x; - return ( uint16_t( u.p8[ 0 ] ) << 8 ) | ( uint16_t( u.p8[ 1 ] ) ); + return ( uint16_t( u.p8[0] ) << 8 ) | ( uint16_t( u.p8[1] ) ); } #endif diff --git a/src/crypto/crypto.cc b/src/crypto/crypto.cc index c16d0b769..5de36c230 100644 --- a/src/crypto/crypto.cc +++ b/src/crypto/crypto.cc @@ -32,11 +32,11 @@ #include #include +#include #include #include #include #include -#include #include "base64.h" #include "byteorder.h" @@ -46,8 +46,9 @@ using namespace Crypto; -long int myatoi( const char *str ) { - char *end; +long int myatoi( const char* str ) +{ + char* end; errno = 0; long int ret = strtol( str, &end, 10 ); @@ -59,7 +60,8 @@ long int myatoi( const char *str ) { return ret; } -uint64_t Crypto::unique( void ) { +uint64_t Crypto::unique( void ) +{ static uint64_t counter = 0; uint64_t rv = counter++; if ( counter == 0 ) { @@ -68,15 +70,17 @@ uint64_t Crypto::unique( void ) { return rv; } -AlignedBuffer::AlignedBuffer( size_t len, const char *data ) - : m_len( len ), m_allocated( NULL ), m_data( NULL ) { +AlignedBuffer::AlignedBuffer( size_t len, const char* data ) + : m_len( len ) + , m_allocated( NULL ) + , m_data( NULL ) +{ size_t alloc_len = len ? len : 1; #if defined( HAVE_POSIX_MEMALIGN ) - if ( ( 0 != posix_memalign( &m_allocated, 16, alloc_len ) ) - || ( m_allocated == NULL ) ) { + if ( ( 0 != posix_memalign( &m_allocated, 16, alloc_len ) ) || ( m_allocated == NULL ) ) { throw std::bad_alloc(); } - m_data = (char *)m_allocated; + m_data = (char*)m_allocated; #else /* malloc() a region 15 bytes larger than we need, and find @@ -94,7 +98,7 @@ AlignedBuffer::AlignedBuffer( size_t len, const char *data ) assert( iptr >= (uintptr_t)m_allocated ); assert( iptr <= ( 15 + (uintptr_t)m_allocated ) ); - m_data = (char *)iptr; + m_data = (char*)iptr; #endif /* !defined(HAVE_POSIX_MEMALIGN) */ @@ -103,7 +107,8 @@ AlignedBuffer::AlignedBuffer( size_t len, const char *data ) } } -Base64Key::Base64Key( string printable_key ) { +Base64Key::Base64Key( string printable_key ) +{ if ( printable_key.length() != 22 ) { throw CryptoException( "Key must be 22 letters long." ); } @@ -125,53 +130,66 @@ Base64Key::Base64Key( string printable_key ) { } } -Base64Key::Base64Key() { PRNG().fill( key, sizeof( key ) ); } +Base64Key::Base64Key() +{ + PRNG().fill( key, sizeof( key ) ); +} -Base64Key::Base64Key( PRNG &prng ) { prng.fill( key, sizeof( key ) ); } +Base64Key::Base64Key( PRNG& prng ) +{ + prng.fill( key, sizeof( key ) ); +} -string Base64Key::printable_key( void ) const { - char base64[ 24 ]; +string Base64Key::printable_key( void ) const +{ + char base64[24]; base64_encode( key, 16, base64, 24 ); - if ( ( base64[ 23 ] != '=' ) || ( base64[ 22 ] != '=' ) ) { - throw CryptoException( string( "Unexpected output from base64_encode: " ) - + string( base64, 24 ) ); + if ( ( base64[23] != '=' ) || ( base64[22] != '=' ) ) { + throw CryptoException( string( "Unexpected output from base64_encode: " ) + string( base64, 24 ) ); } - base64[ 22 ] = 0; + base64[22] = 0; return string( base64 ); } Session::Session( Base64Key s_key ) - : key( s_key ), - ctx_buf( ae_ctx_sizeof() ), - ctx( (ae_ctx *)ctx_buf.data() ), - blocks_encrypted( 0 ), - plaintext_buffer( RECEIVE_MTU ), - ciphertext_buffer( RECEIVE_MTU ), - nonce_buffer( Nonce::NONCE_LEN ) { + : key( s_key ) + , ctx_buf( ae_ctx_sizeof() ) + , ctx( (ae_ctx*)ctx_buf.data() ) + , blocks_encrypted( 0 ) + , plaintext_buffer( RECEIVE_MTU ) + , ciphertext_buffer( RECEIVE_MTU ) + , nonce_buffer( Nonce::NONCE_LEN ) +{ if ( AE_SUCCESS != ae_init( ctx, key.data(), 16, 12, 16 ) ) { throw CryptoException( "Could not initialize AES-OCB context." ); } } -Session::~Session() { fatal_assert( ae_clear( ctx ) == AE_SUCCESS ); } +Session::~Session() +{ + fatal_assert( ae_clear( ctx ) == AE_SUCCESS ); +} -Nonce::Nonce( uint64_t val ) { +Nonce::Nonce( uint64_t val ) +{ uint64_t val_net = htobe64( val ); memset( bytes, 0, 4 ); memcpy( bytes + 4, &val_net, 8 ); } -uint64_t Nonce::val( void ) const { +uint64_t Nonce::val( void ) const +{ uint64_t ret; memcpy( &ret, bytes + 4, 8 ); return be64toh( ret ); } -Nonce::Nonce( const char *s_bytes, size_t len ) { +Nonce::Nonce( const char* s_bytes, size_t len ) +{ if ( len != 8 ) { throw CryptoException( "Nonce representation must be 8 octets long." ); } @@ -180,7 +198,8 @@ Nonce::Nonce( const char *s_bytes, size_t len ) { memcpy( bytes + 4, s_bytes, 8 ); } -const string Session::encrypt( const Message &plaintext ) { +const string Session::encrypt( const Message& plaintext ) +{ const size_t pt_len = plaintext.text.size(); const int ciphertext_len = pt_len + 16; @@ -191,15 +210,15 @@ const string Session::encrypt( const Message &plaintext ) { memcpy( nonce_buffer.data(), plaintext.nonce.data(), Nonce::NONCE_LEN ); if ( ciphertext_len - != ae_encrypt( ctx, /* ctx */ - nonce_buffer.data(), /* nonce */ - plaintext_buffer.data(), /* pt */ - pt_len, /* pt_len */ - NULL, /* ad */ - 0, /* ad_len */ + != ae_encrypt( ctx, /* ctx */ + nonce_buffer.data(), /* nonce */ + plaintext_buffer.data(), /* pt */ + pt_len, /* pt_len */ + NULL, /* ad */ + 0, /* ad_len */ ciphertext_buffer.data(), /* ct */ - NULL, /* tag */ - AE_FINALIZE ) ) { /* final */ + NULL, /* tag */ + AE_FINALIZE ) ) { /* final */ throw CryptoException( "ae_encrypt() returned error." ); } @@ -230,7 +249,8 @@ const string Session::encrypt( const Message &plaintext ) { return plaintext.nonce.cc_str() + text; } -const Message Session::decrypt( const char *str, size_t len ) { +const Message Session::decrypt( const char* str, size_t len ) +{ if ( len < 24 ) { throw CryptoException( "Ciphertext must contain nonce and tag." ); } @@ -238,8 +258,7 @@ const Message Session::decrypt( const char *str, size_t len ) { int body_len = len - 8; int pt_len = body_len - 16; - if ( pt_len - < 0 ) { /* super-assertion that pt_len does not equal AE_INVALID */ + if ( pt_len < 0 ) { /* super-assertion that pt_len does not equal AE_INVALID */ fprintf( stderr, "BUG.\n" ); exit( 1 ); } @@ -252,15 +271,15 @@ const Message Session::decrypt( const char *str, size_t len ) { memcpy( nonce_buffer.data(), nonce.data(), Nonce::NONCE_LEN ); if ( pt_len - != ae_decrypt( ctx, /* ctx */ - nonce_buffer.data(), /* nonce */ + != ae_decrypt( ctx, /* ctx */ + nonce_buffer.data(), /* nonce */ ciphertext_buffer.data(), /* ct */ - body_len, /* ct_len */ - NULL, /* ad */ - 0, /* ad_len */ - plaintext_buffer.data(), /* pt */ - NULL, /* tag */ - AE_FINALIZE ) ) { /* final */ + body_len, /* ct_len */ + NULL, /* ad */ + 0, /* ad_len */ + plaintext_buffer.data(), /* pt */ + NULL, /* tag */ + AE_FINALIZE ) ) { /* final */ throw CryptoException( "Packet failed integrity check." ); } @@ -273,7 +292,8 @@ static rlim_t saved_core_rlimit; /* Disable dumping core, as a precaution to avoid saving sensitive data to disk. */ -void Crypto::disable_dumping_core( void ) { +void Crypto::disable_dumping_core( void ) +{ struct rlimit limit; if ( 0 != getrlimit( RLIMIT_CORE, &limit ) ) { /* We don't throw CryptoException because this is called very early @@ -290,7 +310,8 @@ void Crypto::disable_dumping_core( void ) { } } -void Crypto::reenable_dumping_core( void ) { +void Crypto::reenable_dumping_core( void ) +{ /* Silent failure is safe. */ struct rlimit limit; if ( 0 == getrlimit( RLIMIT_CORE, &limit ) ) { diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h index c13655514..013d47edb 100644 --- a/src/crypto/crypto.h +++ b/src/crypto/crypto.h @@ -33,131 +33,138 @@ #ifndef CRYPTO_HPP #define CRYPTO_HPP +#include "ae.h" +#include #include #include #include -#include #include -#include "ae.h" -long int myatoi( const char *str ); +long int myatoi( const char* str ); class PRNG; namespace Crypto { - using std::string; - - class CryptoException : public std::exception { - public: - string text; - bool fatal; - CryptoException( string s_text, bool s_fatal = false ) - : text( s_text ), fatal( s_fatal ) {}; - const char *what() const throw() { return text.c_str(); } - ~CryptoException() throw() {} - }; - - /* - * OCB (and other algorithms) require a source of nonce/sequence - * numbers that never repeats its output. Enforce that with this - * function. - */ - uint64_t unique( void ); - - /* 16-byte-aligned buffer, with length. */ - class AlignedBuffer { - private: - size_t m_len; - void *m_allocated; - char *m_data; - - public: - AlignedBuffer( size_t len, const char *data = NULL ); - - ~AlignedBuffer() { free( m_allocated ); } - - char *data( void ) const { return m_data; } - size_t len( void ) const { return m_len; } - - private: - /* Not implemented */ - AlignedBuffer( const AlignedBuffer & ); - AlignedBuffer &operator=( const AlignedBuffer & ); - }; - - class Base64Key { - private: - unsigned char key[ 16 ]; - - public: - Base64Key(); /* random key */ - Base64Key( PRNG &prng ); - Base64Key( string printable_key ); - string printable_key( void ) const; - unsigned char *data( void ) { return key; } - }; - - class Nonce { - public: - static const int NONCE_LEN = 12; - - private: - char bytes[ NONCE_LEN ]; - - public: - Nonce( uint64_t val ); - Nonce( const char *s_bytes, size_t len ); - - string cc_str( void ) const { return string( bytes + 4, 8 ); } - const char *data( void ) const { return bytes; } - uint64_t val( void ) const; - }; - - class Message { - public: - const Nonce nonce; - const string text; - - Message( const char *nonce_bytes, size_t nonce_len, const char *text_bytes, - size_t text_len ) - : nonce( nonce_bytes, nonce_len ), text( text_bytes, text_len ) {} - - Message( const Nonce &s_nonce, const string &s_text ) - : nonce( s_nonce ), text( s_text ) {} - }; - - class Session { - private: - Base64Key key; - AlignedBuffer ctx_buf; - ae_ctx *ctx; - uint64_t blocks_encrypted; - - AlignedBuffer plaintext_buffer; - AlignedBuffer ciphertext_buffer; - AlignedBuffer nonce_buffer; - - public: - static const int RECEIVE_MTU = 2048; - /* Overhead (not counting the nonce, which is handled by network transport) - */ - static const int ADDED_BYTES = 16 /* final OCB block */; - - Session( Base64Key s_key ); - ~Session(); - - const string encrypt( const Message &plaintext ); - const Message decrypt( const char *str, size_t len ); - const Message decrypt( const string &ciphertext ) { - return decrypt( ciphertext.data(), ciphertext.size() ); - } - - Session( const Session & ); - Session &operator=( const Session & ); - }; - - void disable_dumping_core( void ); - void reenable_dumping_core( void ); +using std::string; + +class CryptoException : public std::exception +{ +public: + string text; + bool fatal; + CryptoException( string s_text, bool s_fatal = false ) + : text( s_text ) + , fatal( s_fatal ) {}; + const char* what() const throw() { return text.c_str(); } + ~CryptoException() throw() {} +}; + +/* + * OCB (and other algorithms) require a source of nonce/sequence + * numbers that never repeats its output. Enforce that with this + * function. + */ +uint64_t unique( void ); + +/* 16-byte-aligned buffer, with length. */ +class AlignedBuffer +{ +private: + size_t m_len; + void* m_allocated; + char* m_data; + +public: + AlignedBuffer( size_t len, const char* data = NULL ); + + ~AlignedBuffer() { free( m_allocated ); } + + char* data( void ) const { return m_data; } + size_t len( void ) const { return m_len; } + +private: + /* Not implemented */ + AlignedBuffer( const AlignedBuffer& ); + AlignedBuffer& operator=( const AlignedBuffer& ); +}; + +class Base64Key +{ +private: + unsigned char key[16]; + +public: + Base64Key(); /* random key */ + Base64Key( PRNG& prng ); + Base64Key( string printable_key ); + string printable_key( void ) const; + unsigned char* data( void ) { return key; } +}; + +class Nonce +{ +public: + static const int NONCE_LEN = 12; + +private: + char bytes[NONCE_LEN]; + +public: + Nonce( uint64_t val ); + Nonce( const char* s_bytes, size_t len ); + + string cc_str( void ) const { return string( bytes + 4, 8 ); } + const char* data( void ) const { return bytes; } + uint64_t val( void ) const; +}; + +class Message +{ +public: + const Nonce nonce; + const string text; + + Message( const char* nonce_bytes, size_t nonce_len, const char* text_bytes, size_t text_len ) + : nonce( nonce_bytes, nonce_len ) + , text( text_bytes, text_len ) + {} + + Message( const Nonce& s_nonce, const string& s_text ) + : nonce( s_nonce ) + , text( s_text ) + {} +}; + +class Session +{ +private: + Base64Key key; + AlignedBuffer ctx_buf; + ae_ctx* ctx; + uint64_t blocks_encrypted; + + AlignedBuffer plaintext_buffer; + AlignedBuffer ciphertext_buffer; + AlignedBuffer nonce_buffer; + +public: + static const int RECEIVE_MTU = 2048; + /* Overhead (not counting the nonce, which is handled by network transport) */ + static const int ADDED_BYTES = 16 /* final OCB block */; + + Session( Base64Key s_key ); + ~Session(); + + const string encrypt( const Message& plaintext ); + const Message decrypt( const char* str, size_t len ); + const Message decrypt( const string& ciphertext ) { return decrypt( ciphertext.data(), ciphertext.size() ); } + + Session( const Session& ); + Session& operator=( const Session& ); +}; + +void disable_dumping_core( void ); +void reenable_dumping_core( void ); } #endif diff --git a/src/crypto/ocb_internal.cc b/src/crypto/ocb_internal.cc index 3d6d734b7..4fc2bdee2 100644 --- a/src/crypto/ocb_internal.cc +++ b/src/crypto/ocb_internal.cc @@ -24,14 +24,11 @@ / Comments are welcome: Ted Krovetz - Dedicated to Laurel K /------------------------------------------------------------------------- */ -// clang-format off - #include "config.h" /* This module implements the ae.h interface for OpenSSL, Apple Common / Crypto, and Nettle. */ -#if !defined(USE_OPENSSL_AES) && !defined(USE_APPLE_COMMON_CRYPTO_AES) && \ - !defined(USE_NETTLE_AES) +#if !defined( USE_OPENSSL_AES ) && !defined( USE_APPLE_COMMON_CRYPTO_AES ) && !defined( USE_NETTLE_AES ) #error ocb_internal.cc only works with OpenSSL, Apple Common Crypto, or Nettle #endif @@ -57,15 +54,15 @@ /* Set the AES key length to use and length of authentication tag to produce. / Setting either to 0 requires the value be set at runtime via ae_init(). / Some optimizations occur for each when set to a fixed value. */ -#define OCB_KEY_LEN 16 /* 0, 16, 24 or 32. 0 means set in ae_init */ -#define OCB_TAG_LEN 16 /* 0 to 16. 0 means set in ae_init */ +#define OCB_KEY_LEN 16 /* 0, 16, 24 or 32. 0 means set in ae_init */ +#define OCB_TAG_LEN 16 /* 0 to 16. 0 means set in ae_init */ /* This implementation has built-in support for multiple AES APIs. Set any / one of the following to non-zero to specify which to use. */ #if 0 -#define USE_APPLE_COMMON_CRYPTO_AES 0 -#define USE_NETTLE_AES 0 -#define USE_OPENSSL_AES 1 /* http://openssl.org */ +#define USE_APPLE_COMMON_CRYPTO_AES 0 +#define USE_NETTLE_AES 0 +#define USE_OPENSSL_AES 1 /* http://openssl.org */ #endif /* During encryption and decryption, various "L values" are required. @@ -75,7 +72,7 @@ / L values to precompute. L_TABLE_SZ must be at least 3. L_TABLE_SZ*16 bytes / are used for L values in ae_ctx. Plaintext and ciphertexts shorter than / 2^L_TABLE_SZ blocks need no L values calculated dynamically. */ -#define L_TABLE_SZ 16 +#define L_TABLE_SZ 16 /* Set L_TABLE_SZ_IS_ENOUGH non-zero iff you know that all plaintexts / will be shorter than 2^(L_TABLE_SZ+4) bytes in length. This results @@ -91,89 +88,98 @@ #include "fatal_assert.h" #include #include -#if defined(HAVE_STRINGS_H) +#if defined( HAVE_STRINGS_H ) #include #endif -#if defined(HAVE_ENDIAN_H) +#if defined( HAVE_ENDIAN_H ) #include -#elif defined(HAVE_SYS_ENDIAN_H) -#include +#elif defined( HAVE_SYS_ENDIAN_H ) #include +#include #endif #include /* Define standard sized integers */ -#if defined(_MSC_VER) && (_MSC_VER < 1600) - typedef unsigned __int8 uint8_t; - typedef unsigned __int32 uint32_t; - typedef unsigned __int64 uint64_t; - typedef __int64 int64_t; +#if defined( _MSC_VER ) && ( _MSC_VER < 1600 ) +typedef unsigned __int8 uint8_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int64 uint64_t; +typedef __int64 int64_t; #else - #include +#include #endif /* Compiler-specific intrinsics and fixes: bswap64, ntz */ #if _MSC_VER - #define inline __inline /* MSVC doesn't recognize "inline" in C */ - #define restrict __restrict /* MSVC doesn't recognize "restrict" in C */ - #define __SSE2__ (_M_IX86 || _M_AMD64 || _M_X64) /* Assume SSE2 */ - #define __SSSE3__ (_M_IX86 || _M_AMD64 || _M_X64) /* Assume SSSE3 */ - #include - #pragma intrinsic(_byteswap_uint64, _BitScanForward, memcpy) +#define inline __inline /* MSVC doesn't recognize "inline" in C */ +#define restrict __restrict /* MSVC doesn't recognize "restrict" in C */ +#define __SSE2__ ( _M_IX86 || _M_AMD64 || _M_X64 ) /* Assume SSE2 */ +#define __SSSE3__ ( _M_IX86 || _M_AMD64 || _M_X64 ) /* Assume SSSE3 */ +#include +#pragma intrinsic( _byteswap_uint64, _BitScanForward, memcpy ) #elif __GNUC__ - #ifndef inline - #define inline __inline__ /* No "inline" in GCC ansi C mode */ - #endif - #ifndef restrict - #define restrict __restrict__ /* No "restrict" in GCC ansi C mode */ - #endif +#ifndef inline +#define inline __inline__ /* No "inline" in GCC ansi C mode */ +#endif +#ifndef restrict +#define restrict __restrict__ /* No "restrict" in GCC ansi C mode */ +#endif #endif #if _MSC_VER - #define bswap64(x) _byteswap_uint64(x) +#define bswap64( x ) _byteswap_uint64( x ) #elif HAVE_DECL_BSWAP64 - /* nothing */ +/* nothing */ #elif HAVE_DECL___BUILTIN_BSWAP64 - #define bswap64(x) __builtin_bswap64(x) /* GCC 4.3+ */ +#define bswap64( x ) __builtin_bswap64( x ) /* GCC 4.3+ */ #else - #define bswap32(x) \ - ((((x) & 0xff000000u) >> 24) | (((x) & 0x00ff0000u) >> 8) | \ - (((x) & 0x0000ff00u) << 8) | (((x) & 0x000000ffu) << 24)) - - static inline uint64_t bswap64(uint64_t x) { - union { uint64_t u64; uint32_t u32[2]; } in, out; - in.u64 = x; - out.u32[0] = bswap32(in.u32[1]); - out.u32[1] = bswap32(in.u32[0]); - return out.u64; - } +#define bswap32( x ) \ + ( ( ( (x)&0xff000000u ) >> 24 ) | ( ( (x)&0x00ff0000u ) >> 8 ) | ( ( (x)&0x0000ff00u ) << 8 ) \ + | ( ( (x)&0x000000ffu ) << 24 ) ) + +static inline uint64_t bswap64( uint64_t x ) +{ + union { + uint64_t u64; + uint32_t u32[2]; + } in, out; + in.u64 = x; + out.u32[0] = bswap32( in.u32[1] ); + out.u32[1] = bswap32( in.u32[0] ); + return out.u64; +} #endif #if _MSC_VER - static inline unsigned ntz(unsigned x) {_BitScanForward(&x,x);return x;} +static inline unsigned ntz( unsigned x ) +{ + _BitScanForward( &x, x ); + return x; +} #elif HAVE_DECL___BUILTIN_CTZ - #define ntz(x) __builtin_ctz((unsigned)(x)) /* GCC 3.4+ */ +#define ntz( x ) __builtin_ctz( (unsigned)( x ) ) /* GCC 3.4+ */ #elif HAVE_DECL_FFS - #define ntz(x) (ffs(x) - 1) +#define ntz( x ) ( ffs( x ) - 1 ) #else - #if (L_TABLE_SZ <= 9) && (L_TABLE_SZ_IS_ENOUGH) /* < 2^13 byte texts */ - static inline unsigned ntz(unsigned x) { - static const unsigned char tz_table[] = {0, - 2,3,2,4,2,3,2,5,2,3,2,4,2,3,2,6,2,3,2,4,2,3,2,5,2,3,2,4,2,3,2,7, - 2,3,2,4,2,3,2,5,2,3,2,4,2,3,2,6,2,3,2,4,2,3,2,5,2,3,2,4,2,3,2,8, - 2,3,2,4,2,3,2,5,2,3,2,4,2,3,2,6,2,3,2,4,2,3,2,5,2,3,2,4,2,3,2,7, - 2,3,2,4,2,3,2,5,2,3,2,4,2,3,2,6,2,3,2,4,2,3,2,5,2,3,2,4,2,3,2}; - return tz_table[x/4]; - } - #else /* From http://supertech.csail.mit.edu/papers/debruijn.pdf */ - static inline unsigned ntz(unsigned x) { - static const unsigned char tz_table[32] = - { 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, - 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9}; - return tz_table[((uint32_t)((x & -x) * 0x077CB531u)) >> 27]; - } - #endif +#if ( L_TABLE_SZ <= 9 ) && ( L_TABLE_SZ_IS_ENOUGH ) /* < 2^13 byte texts */ +static inline unsigned ntz( unsigned x ) +{ + static const unsigned char tz_table[] + = { 0, 2, 3, 2, 4, 2, 3, 2, 5, 2, 3, 2, 4, 2, 3, 2, 6, 2, 3, 2, 4, 2, 3, 2, 5, 2, 3, 2, 4, 2, 3, 2, + 7, 2, 3, 2, 4, 2, 3, 2, 5, 2, 3, 2, 4, 2, 3, 2, 6, 2, 3, 2, 4, 2, 3, 2, 5, 2, 3, 2, 4, 2, 3, 2, + 8, 2, 3, 2, 4, 2, 3, 2, 5, 2, 3, 2, 4, 2, 3, 2, 6, 2, 3, 2, 4, 2, 3, 2, 5, 2, 3, 2, 4, 2, 3, 2, + 7, 2, 3, 2, 4, 2, 3, 2, 5, 2, 3, 2, 4, 2, 3, 2, 6, 2, 3, 2, 4, 2, 3, 2, 5, 2, 3, 2, 4, 2, 3, 2 }; + return tz_table[x / 4]; +} +#else /* From http://supertech.csail.mit.edu/papers/debruijn.pdf */ +static inline unsigned ntz( unsigned x ) +{ + static const unsigned char tz_table[32] = { 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, + 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 }; + return tz_table[( (uint32_t)( ( x & -x ) * 0x077CB531u ) ) >> 27]; +} +#endif #endif /* ----------------------------------------------------------------------- */ @@ -181,178 +187,210 @@ /* ----------------------------------------------------------------------- */ #if __SSE2__ - #include /* SSE instructions and _mm_malloc */ - #include /* SSE2 instructions */ - typedef __m128i block; - #define xor_block(x,y) _mm_xor_si128(x,y) - #define zero_block() _mm_setzero_si128() - #define unequal_blocks(x,y) \ - (_mm_movemask_epi8(_mm_cmpeq_epi8(x,y)) != 0xffff) - #if __SSSE3__ - #include /* SSSE3 instructions */ - #define swap_if_le(b) \ - _mm_shuffle_epi8(b,_mm_set_epi8(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)) - #else - static inline block swap_if_le(block b) { - block a = _mm_shuffle_epi32 (b, _MM_SHUFFLE(0,1,2,3)); - a = _mm_shufflehi_epi16(a, _MM_SHUFFLE(2,3,0,1)); - a = _mm_shufflelo_epi16(a, _MM_SHUFFLE(2,3,0,1)); - return _mm_xor_si128(_mm_srli_epi16(a,8), _mm_slli_epi16(a,8)); - } - #endif - static inline block gen_offset(uint64_t KtopStr[3], unsigned bot) { - block hi = _mm_load_si128((__m128i *)(KtopStr+0)); /* hi = B A */ - block lo = _mm_loadu_si128((__m128i *)(KtopStr+1)); /* lo = C B */ - __m128i lshift = _mm_cvtsi32_si128(bot); - __m128i rshift = _mm_cvtsi32_si128(64-bot); - lo = _mm_xor_si128(_mm_sll_epi64(hi,lshift),_mm_srl_epi64(lo,rshift)); - #if __SSSE3__ - return _mm_shuffle_epi8(lo,_mm_set_epi8(8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7)); - #else - return swap_if_le(_mm_shuffle_epi32(lo, _MM_SHUFFLE(1,0,3,2))); - #endif - } - static inline block double_block(block bl) { - const __m128i mask = _mm_set_epi32(135,1,1,1); - __m128i tmp = _mm_srai_epi32(bl, 31); - tmp = _mm_and_si128(tmp, mask); - tmp = _mm_shuffle_epi32(tmp, _MM_SHUFFLE(2,1,0,3)); - bl = _mm_slli_epi32(bl, 1); - return _mm_xor_si128(bl,tmp); - } +#include /* SSE2 instructions */ +#include /* SSE instructions and _mm_malloc */ +typedef __m128i block; +#define xor_block( x, y ) _mm_xor_si128( x, y ) +#define zero_block() _mm_setzero_si128() +#define unequal_blocks( x, y ) ( _mm_movemask_epi8( _mm_cmpeq_epi8( x, y ) ) != 0xffff ) +#if __SSSE3__ +#include /* SSSE3 instructions */ +#define swap_if_le( b ) _mm_shuffle_epi8( b, _mm_set_epi8( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ) ) +#else +static inline block swap_if_le( block b ) +{ + block a = _mm_shuffle_epi32( b, _MM_SHUFFLE( 0, 1, 2, 3 ) ); + a = _mm_shufflehi_epi16( a, _MM_SHUFFLE( 2, 3, 0, 1 ) ); + a = _mm_shufflelo_epi16( a, _MM_SHUFFLE( 2, 3, 0, 1 ) ); + return _mm_xor_si128( _mm_srli_epi16( a, 8 ), _mm_slli_epi16( a, 8 ) ); +} +#endif +static inline block gen_offset( uint64_t KtopStr[3], unsigned bot ) +{ + block hi = _mm_load_si128( (__m128i*)( KtopStr + 0 ) ); /* hi = B A */ + block lo = _mm_loadu_si128( (__m128i*)( KtopStr + 1 ) ); /* lo = C B */ + __m128i lshift = _mm_cvtsi32_si128( bot ); + __m128i rshift = _mm_cvtsi32_si128( 64 - bot ); + lo = _mm_xor_si128( _mm_sll_epi64( hi, lshift ), _mm_srl_epi64( lo, rshift ) ); +#if __SSSE3__ + return _mm_shuffle_epi8( lo, _mm_set_epi8( 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7 ) ); +#else + return swap_if_le( _mm_shuffle_epi32( lo, _MM_SHUFFLE( 1, 0, 3, 2 ) ) ); +#endif +} +static inline block double_block( block bl ) +{ + const __m128i mask = _mm_set_epi32( 135, 1, 1, 1 ); + __m128i tmp = _mm_srai_epi32( bl, 31 ); + tmp = _mm_and_si128( tmp, mask ); + tmp = _mm_shuffle_epi32( tmp, _MM_SHUFFLE( 2, 1, 0, 3 ) ); + bl = _mm_slli_epi32( bl, 1 ); + return _mm_xor_si128( bl, tmp ); +} #elif __ALTIVEC__ && _CALL_ELF != 2 - #include - typedef vector unsigned block; - #define xor_block(x,y) vec_xor(x,y) - #define zero_block() vec_splat_u32(0) - #define unequal_blocks(x,y) vec_any_ne(x,y) - #define swap_if_le(b) (b) - #if __PPC64__ - static block gen_offset(uint64_t KtopStr[3], unsigned bot) { - union {uint64_t u64[2]; block bl;} rval; - rval.u64[0] = (KtopStr[0] << bot) | (KtopStr[1] >> (64-bot)); - rval.u64[1] = (KtopStr[1] << bot) | (KtopStr[2] >> (64-bot)); - return rval.bl; - } - #else - /* Special handling: Shifts are mod 32, and no 64-bit types */ - static block gen_offset(uint64_t KtopStr[3], unsigned bot) { - const vector unsigned k32 = {32,32,32,32}; - vector unsigned hi = *(vector unsigned *)(KtopStr+0); - vector unsigned lo = *(vector unsigned *)(KtopStr+2); - vector unsigned bot_vec; - if (bot < 32) { - lo = vec_sld(hi,lo,4); - } else { - vector unsigned t = vec_sld(hi,lo,4); - lo = vec_sld(hi,lo,8); - hi = t; - bot = bot - 32; - } - if (bot == 0) return hi; - *(unsigned *)&bot_vec = bot; - vector unsigned lshift = vec_splat(bot_vec,0); - vector unsigned rshift = vec_sub(k32,lshift); - hi = vec_sl(hi,lshift); - lo = vec_sr(lo,rshift); - return vec_xor(hi,lo); - } - #endif - static inline block double_block(block b) { - const vector unsigned char mask = {135,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; - const vector unsigned char perm = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0}; - const vector unsigned char shift7 = vec_splat_u8(7); - const vector unsigned char shift1 = vec_splat_u8(1); - vector unsigned char c = (vector unsigned char)b; - vector unsigned char t = vec_sra(c,shift7); - t = vec_and(t,mask); - t = vec_perm(t,t,perm); - c = vec_sl(c,shift1); - return (block)vec_xor(c,t); - } +#include +typedef vector unsigned block; +#define xor_block( x, y ) vec_xor( x, y ) +#define zero_block() vec_splat_u32( 0 ) +#define unequal_blocks( x, y ) vec_any_ne( x, y ) +#define swap_if_le( b ) ( b ) +#if __PPC64__ +static block gen_offset( uint64_t KtopStr[3], unsigned bot ) +{ + union { + uint64_t u64[2]; + block bl; + } rval; + rval.u64[0] = ( KtopStr[0] << bot ) | ( KtopStr[1] >> ( 64 - bot ) ); + rval.u64[1] = ( KtopStr[1] << bot ) | ( KtopStr[2] >> ( 64 - bot ) ); + return rval.bl; +} +#else +/* Special handling: Shifts are mod 32, and no 64-bit types */ +static block gen_offset( uint64_t KtopStr[3], unsigned bot ) +{ + const vector unsigned k32 = { 32, 32, 32, 32 }; + vector unsigned hi = *(vector unsigned*)( KtopStr + 0 ); + vector unsigned lo = *(vector unsigned*)( KtopStr + 2 ); + vector unsigned bot_vec; + if ( bot < 32 ) { + lo = vec_sld( hi, lo, 4 ); + } else { + vector unsigned t = vec_sld( hi, lo, 4 ); + lo = vec_sld( hi, lo, 8 ); + hi = t; + bot = bot - 32; + } + if ( bot == 0 ) + return hi; + *(unsigned*)&bot_vec = bot; + vector unsigned lshift = vec_splat( bot_vec, 0 ); + vector unsigned rshift = vec_sub( k32, lshift ); + hi = vec_sl( hi, lshift ); + lo = vec_sr( lo, rshift ); + return vec_xor( hi, lo ); +} +#endif +static inline block double_block( block b ) +{ + const vector unsigned char mask = { 135, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; + const vector unsigned char perm = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0 }; + const vector unsigned char shift7 = vec_splat_u8( 7 ); + const vector unsigned char shift1 = vec_splat_u8( 1 ); + vector unsigned char c = (vector unsigned char)b; + vector unsigned char t = vec_sra( c, shift7 ); + t = vec_and( t, mask ); + t = vec_perm( t, t, perm ); + c = vec_sl( c, shift1 ); + return (block)vec_xor( c, t ); +} #elif __ARM_NEON__ - #include - typedef int8x16_t block; /* Yay! Endian-neutral reads! */ - #define xor_block(x,y) veorq_s8(x,y) - #define zero_block() vdupq_n_s8(0) - static inline int unequal_blocks(block a, block b) { - int64x2_t t=veorq_s64((int64x2_t)a,(int64x2_t)b); - return (vgetq_lane_s64(t,0)|vgetq_lane_s64(t,1))!=0; - } - #define swap_if_le(b) (b) /* Using endian-neutral int8x16_t */ - /* KtopStr is reg correct by 64 bits, return mem correct */ - static block gen_offset(uint64_t KtopStr[3], unsigned bot) { - const union { unsigned x; unsigned char endian; } little = { 1 }; - const int64x2_t k64 = {-64,-64}; - uint64x2_t hi, lo; - memcpy(&hi, KtopStr, sizeof(hi)); - memcpy(&lo, KtopStr+1, sizeof(lo)); - int64x2_t ls = vdupq_n_s64(bot); - int64x2_t rs = vqaddq_s64(k64,ls); - block rval = (block)veorq_u64(vshlq_u64(hi,ls),vshlq_u64(lo,rs)); - if (little.endian) - rval = vrev64q_s8(rval); - return rval; - } - static inline block double_block(block b) - { - const block mask = {-121,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; - block tmp = vshrq_n_s8(b,7); - tmp = vandq_s8(tmp, mask); - tmp = vextq_s8(tmp, tmp, 1); /* Rotate high byte to end */ - b = vshlq_n_s8(b,1); - return veorq_s8(tmp,b); - } +#include +typedef int8x16_t block; /* Yay! Endian-neutral reads! */ +#define xor_block( x, y ) veorq_s8( x, y ) +#define zero_block() vdupq_n_s8( 0 ) +static inline int unequal_blocks( block a, block b ) +{ + int64x2_t t = veorq_s64( (int64x2_t)a, (int64x2_t)b ); + return ( vgetq_lane_s64( t, 0 ) | vgetq_lane_s64( t, 1 ) ) != 0; +} +#define swap_if_le( b ) ( b ) /* Using endian-neutral int8x16_t */ +/* KtopStr is reg correct by 64 bits, return mem correct */ +static block gen_offset( uint64_t KtopStr[3], unsigned bot ) +{ + const union { + unsigned x; + unsigned char endian; + } little = { 1 }; + const int64x2_t k64 = { -64, -64 }; + uint64x2_t hi, lo; + memcpy( &hi, KtopStr, sizeof( hi ) ); + memcpy( &lo, KtopStr + 1, sizeof( lo ) ); + int64x2_t ls = vdupq_n_s64( bot ); + int64x2_t rs = vqaddq_s64( k64, ls ); + block rval = (block)veorq_u64( vshlq_u64( hi, ls ), vshlq_u64( lo, rs ) ); + if ( little.endian ) + rval = vrev64q_s8( rval ); + return rval; +} +static inline block double_block( block b ) +{ + const block mask = { -121, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; + block tmp = vshrq_n_s8( b, 7 ); + tmp = vandq_s8( tmp, mask ); + tmp = vextq_s8( tmp, tmp, 1 ); /* Rotate high byte to end */ + b = vshlq_n_s8( b, 1 ); + return veorq_s8( tmp, b ); +} #else - typedef struct { uint64_t l,r; } block; - static inline block xor_block(block x, block y) { - x.l^=y.l; x.r^=y.r; return x; - } - static inline block zero_block(void) { const block t = {0,0}; return t; } - #define unequal_blocks(x, y) ((((x).l^(y).l)|((x).r^(y).r)) != 0) - static inline block swap_if_le(block b) { - const union { unsigned x; unsigned char endian; } little = { 1 }; - if (little.endian) { - block r; - r.l = bswap64(b.l); - r.r = bswap64(b.r); - return r; - } else - return b; - } +typedef struct +{ + uint64_t l, r; +} block; +static inline block xor_block( block x, block y ) +{ + x.l ^= y.l; + x.r ^= y.r; + return x; +} +static inline block zero_block( void ) +{ + const block t = { 0, 0 }; + return t; +} +#define unequal_blocks( x, y ) ( ( ( ( x ).l ^ ( y ).l ) | ( ( x ).r ^ ( y ).r ) ) != 0 ) +static inline block swap_if_le( block b ) +{ + const union { + unsigned x; + unsigned char endian; + } little = { 1 }; + if ( little.endian ) { + block r; + r.l = bswap64( b.l ); + r.r = bswap64( b.r ); + return r; + } else + return b; +} - /* KtopStr is reg correct by 64 bits, return mem correct */ - static block gen_offset(uint64_t KtopStr[3], unsigned bot) { - block rval; - if (bot != 0) { - rval.l = (KtopStr[0] << bot) | (KtopStr[1] >> (64-bot)); - rval.r = (KtopStr[1] << bot) | (KtopStr[2] >> (64-bot)); - } else { - rval.l = KtopStr[0]; - rval.r = KtopStr[1]; - } - return swap_if_le(rval); - } - - #if __GNUC__ && !__clang__ && __arm__ - static inline block double_block(block b) { - __asm__ ("adds %1,%1,%1\n\t" - "adcs %H1,%H1,%H1\n\t" - "adcs %0,%0,%0\n\t" - "adcs %H0,%H0,%H0\n\t" - "it cs\n\t" - "eorcs %1,%1,#135" - : "+r"(b.l), "+r"(b.r) : : "cc"); - return b; - } - #else - static inline block double_block(block b) { - uint64_t t = (uint64_t)((int64_t)b.l >> 63); - b.l = (b.l + b.l) ^ (b.r >> 63); - b.r = (b.r + b.r) ^ (t & 135); - return b; - } - #endif +/* KtopStr is reg correct by 64 bits, return mem correct */ +static block gen_offset( uint64_t KtopStr[3], unsigned bot ) +{ + block rval; + if ( bot != 0 ) { + rval.l = ( KtopStr[0] << bot ) | ( KtopStr[1] >> ( 64 - bot ) ); + rval.r = ( KtopStr[1] << bot ) | ( KtopStr[2] >> ( 64 - bot ) ); + } else { + rval.l = KtopStr[0]; + rval.r = KtopStr[1]; + } + return swap_if_le( rval ); +} + +#if __GNUC__ && !__clang__ && __arm__ +static inline block double_block( block b ) +{ + __asm__( "adds %1,%1,%1\n\t" + "adcs %H1,%H1,%H1\n\t" + "adcs %0,%0,%0\n\t" + "adcs %H0,%H0,%H0\n\t" + "it cs\n\t" + "eorcs %1,%1,#135" + : "+r"( b.l ), "+r"( b.r ) + : + : "cc" ); + return b; +} +#else +static inline block double_block( block b ) +{ + uint64_t t = (uint64_t)( (int64_t)b.l >> 63 ); + b.l = ( b.l + b.l ) ^ ( b.r >> 63 ); + b.r = ( b.r + b.r ) ^ ( t & 135 ); + return b; +} +#endif #endif @@ -364,114 +402,129 @@ #if USE_OPENSSL_AES /*---------------*/ -#include /* http://openssl.org/ */ +#include /* http://openssl.org/ */ namespace ocb_aes { typedef EVP_CIPHER_CTX KEY; -enum { BLOCK_SIZE = 16 }; +enum +{ + BLOCK_SIZE = 16 +}; + +static KEY* KEY_new() +{ + KEY* key = EVP_CIPHER_CTX_new(); + if ( key == NULL ) { + throw std::bad_alloc(); + } + return key; +} -static KEY *KEY_new() { - KEY *key = EVP_CIPHER_CTX_new(); - if (key == NULL) { - throw std::bad_alloc(); - } - return key; +static void KEY_delete( KEY* key ) +{ + EVP_CIPHER_CTX_free( key ); } -static void KEY_delete(KEY *key) { EVP_CIPHER_CTX_free(key); } - -static void set_encrypt_key(const unsigned char *user_key, int bits, KEY *key) { - // Do not copy and paste this code! It is far too low-level to be - // general-purpose. If you're looking for an example of using AEAD - // through OpenSSL's EVP_CIPHER API, have a look at ocb_openssl.cc - // instead. - // - // This function and the others in this section replicate the behavior of - // OpenSSL's deprecated AES_* primitives. Those primitives implemented AES - // without any block cipher mode--that is, in ECB mode. Normally, using ECB - // mode anywhere would be questionable, but it's safe here because it's - // being used to implement a higher-level cryptographic mode (OCB mode), - // which is in turn used by Mosh. - - fatal_assert(bits == 128); - if (EVP_EncryptInit_ex(key, EVP_aes_128_ecb(), /*impl=*/NULL, user_key, /*iv=*/NULL) != 1 || - EVP_CIPHER_CTX_set_padding(key, false) != 1) { - throw Crypto::CryptoException("Could not initialize AES encryption context."); - } +static void set_encrypt_key( const unsigned char* user_key, int bits, KEY* key ) +{ + // Do not copy and paste this code! It is far too low-level to be + // general-purpose. If you're looking for an example of using AEAD + // through OpenSSL's EVP_CIPHER API, have a look at ocb_openssl.cc + // instead. + // + // This function and the others in this section replicate the behavior of + // OpenSSL's deprecated AES_* primitives. Those primitives implemented AES + // without any block cipher mode--that is, in ECB mode. Normally, using ECB + // mode anywhere would be questionable, but it's safe here because it's + // being used to implement a higher-level cryptographic mode (OCB mode), + // which is in turn used by Mosh. + + fatal_assert( bits == 128 ); + if ( EVP_EncryptInit_ex( key, EVP_aes_128_ecb(), /*impl=*/NULL, user_key, /*iv=*/NULL ) != 1 + || EVP_CIPHER_CTX_set_padding( key, false ) != 1 ) { + throw Crypto::CryptoException( "Could not initialize AES encryption context." ); + } } -static void set_decrypt_key(const unsigned char *user_key, int bits, KEY *key) { - // Do not copy and paste this code! See notes in set_encrypt_key. - fatal_assert(bits == 128); - if (EVP_DecryptInit_ex(key, EVP_aes_128_ecb(), /*impl=*/NULL, user_key, /*iv=*/NULL) != 1 || - EVP_CIPHER_CTX_set_padding(key, false) != 1) { - throw Crypto::CryptoException("Could not initialize AES decryption context."); - } +static void set_decrypt_key( const unsigned char* user_key, int bits, KEY* key ) +{ + // Do not copy and paste this code! See notes in set_encrypt_key. + fatal_assert( bits == 128 ); + if ( EVP_DecryptInit_ex( key, EVP_aes_128_ecb(), /*impl=*/NULL, user_key, /*iv=*/NULL ) != 1 + || EVP_CIPHER_CTX_set_padding( key, false ) != 1 ) { + throw Crypto::CryptoException( "Could not initialize AES decryption context." ); + } } -static void encrypt(const unsigned char *in, unsigned char *out, KEY *key) { - // Even though the functions in this section use ECB mode (which is - // stateless), OpenSSL still requires calls to EncryptInit and - // EncryptFinal. Since ECB mode has no IV and they key is unchanged, - // every parameter to this function can be NULL (which OpenSSL - // interprets as "don't change this"). - if (EVP_EncryptInit_ex(key, /*type=*/NULL, /*impl=*/NULL, /*key=*/NULL, /*iv=*/NULL) != 1) { - throw Crypto::CryptoException("Could not start AES encryption operation."); - } - - int len; - if (EVP_EncryptUpdate(key, out, &len, in, BLOCK_SIZE) != 1) { - throw Crypto::CryptoException("Could not AES-encrypt block."); - } - - int total_len = len; - if (EVP_EncryptFinal_ex(key, out + total_len, &len) != 1) { - throw Crypto::CryptoException("Could not finish AES encryption operation."); - } - total_len += len; - fatal_assert(total_len == BLOCK_SIZE); +static void encrypt( const unsigned char* in, unsigned char* out, KEY* key ) +{ + // Even though the functions in this section use ECB mode (which is + // stateless), OpenSSL still requires calls to EncryptInit and + // EncryptFinal. Since ECB mode has no IV and they key is unchanged, + // every parameter to this function can be NULL (which OpenSSL + // interprets as "don't change this"). + if ( EVP_EncryptInit_ex( key, /*type=*/NULL, /*impl=*/NULL, /*key=*/NULL, /*iv=*/NULL ) != 1 ) { + throw Crypto::CryptoException( "Could not start AES encryption operation." ); + } + + int len; + if ( EVP_EncryptUpdate( key, out, &len, in, BLOCK_SIZE ) != 1 ) { + throw Crypto::CryptoException( "Could not AES-encrypt block." ); + } + + int total_len = len; + if ( EVP_EncryptFinal_ex( key, out + total_len, &len ) != 1 ) { + throw Crypto::CryptoException( "Could not finish AES encryption operation." ); + } + total_len += len; + fatal_assert( total_len == BLOCK_SIZE ); } -static void decrypt(const unsigned char *in, unsigned char *out, KEY *key) { - // See notes in encrypt about EncryptInit and EncryptFinal; the same - // notes apply to DecryptInit and DecryptFinal here. - if (EVP_DecryptInit_ex(key, /*type=*/NULL, /*impl=*/NULL, /*key=*/NULL, /*iv=*/NULL) != 1) { - throw Crypto::CryptoException("Could not start AES decryption operation."); - } - - int len; - if (EVP_DecryptUpdate(key, out, &len, in, BLOCK_SIZE) != 1) { - throw Crypto::CryptoException("Could not AES-decrypt block."); - } - - int total_len = len; - if (EVP_DecryptFinal_ex(key, out + total_len, &len) != 1) { - throw Crypto::CryptoException("Could not finish AES decryption operation."); - } - total_len += len; - fatal_assert(total_len == BLOCK_SIZE); +static void decrypt( const unsigned char* in, unsigned char* out, KEY* key ) +{ + // See notes in encrypt about EncryptInit and EncryptFinal; the same + // notes apply to DecryptInit and DecryptFinal here. + if ( EVP_DecryptInit_ex( key, /*type=*/NULL, /*impl=*/NULL, /*key=*/NULL, /*iv=*/NULL ) != 1 ) { + throw Crypto::CryptoException( "Could not start AES decryption operation." ); + } + + int len; + if ( EVP_DecryptUpdate( key, out, &len, in, BLOCK_SIZE ) != 1 ) { + throw Crypto::CryptoException( "Could not AES-decrypt block." ); + } + + int total_len = len; + if ( EVP_DecryptFinal_ex( key, out + total_len, &len ) != 1 ) { + throw Crypto::CryptoException( "Could not finish AES decryption operation." ); + } + total_len += len; + fatal_assert( total_len == BLOCK_SIZE ); } /* How to ECB encrypt an array of blocks, in place */ -static void ecb_encrypt_blks(block *blks, unsigned nblks, KEY *key) { - while (nblks) { - --nblks; - encrypt(reinterpret_cast(blks+nblks), reinterpret_cast(blks+nblks), key); - } +static void ecb_encrypt_blks( block* blks, unsigned nblks, KEY* key ) +{ + while ( nblks ) { + --nblks; + encrypt( + reinterpret_cast( blks + nblks ), reinterpret_cast( blks + nblks ), key ); + } } -static void ecb_decrypt_blks(block *blks, unsigned nblks, KEY *key) { - while (nblks) { - --nblks; - decrypt(reinterpret_cast(blks+nblks), reinterpret_cast(blks+nblks), key); - } +static void ecb_decrypt_blks( block* blks, unsigned nblks, KEY* key ) +{ + while ( nblks ) { + --nblks; + decrypt( + reinterpret_cast( blks + nblks ), reinterpret_cast( blks + nblks ), key ); + } } -} // namespace ocb_aes +} // namespace ocb_aes -#define BPI 4 /* Number of blocks in buffer per ECB call */ +#define BPI 4 /* Number of blocks in buffer per ECB call */ /*-------------------*/ #elif USE_APPLE_COMMON_CRYPTO_AES @@ -481,58 +534,59 @@ static void ecb_decrypt_blks(block *blks, unsigned nblks, KEY *key) { namespace ocb_aes { -typedef struct { - CCCryptorRef ref; - uint8_t b[4096]; +typedef struct +{ + CCCryptorRef ref; + uint8_t b[4096]; } KEY; -static KEY *KEY_new() { return new KEY; } +static KEY* KEY_new() +{ + return new KEY; +} -static void KEY_delete(KEY *key) { delete key; } +static void KEY_delete( KEY* key ) +{ + delete key; +} -static void set_encrypt_key(const unsigned char *handle, const int bits, KEY *key) +static void set_encrypt_key( const unsigned char* handle, const int bits, KEY* key ) { - CCCryptorStatus rv = CCCryptorCreateFromData( - kCCEncrypt, - kCCAlgorithmAES128, - kCCOptionECBMode, - handle, - bits / 8, - NULL, - &(key->b), - sizeof (key->b), - &(key->ref), - NULL); - - fatal_assert(rv == kCCSuccess); + CCCryptorStatus rv = CCCryptorCreateFromData( kCCEncrypt, + kCCAlgorithmAES128, + kCCOptionECBMode, + handle, + bits / 8, + NULL, + &( key->b ), + sizeof( key->b ), + &( key->ref ), + NULL ); + + fatal_assert( rv == kCCSuccess ); } -static void set_decrypt_key(const unsigned char *handle, const int bits, KEY *key) +static void set_decrypt_key( const unsigned char* handle, const int bits, KEY* key ) { - CCCryptorStatus rv = CCCryptorCreateFromData( - kCCDecrypt, - kCCAlgorithmAES128, - kCCOptionECBMode, - handle, - bits / 8, - NULL, - &(key->b), - sizeof (key->b), - &(key->ref), - NULL); - - fatal_assert(rv == kCCSuccess); + CCCryptorStatus rv = CCCryptorCreateFromData( kCCDecrypt, + kCCAlgorithmAES128, + kCCOptionECBMode, + handle, + bits / 8, + NULL, + &( key->b ), + sizeof( key->b ), + &( key->ref ), + NULL ); + + fatal_assert( rv == kCCSuccess ); } -static void encrypt(unsigned char *src, unsigned char *dst, KEY *key) { - size_t dataOutMoved; - CCCryptorStatus rv = CCCryptorUpdate( - key->ref, - (const void *)src, - kCCBlockSizeAES128, - (void *)dst, - kCCBlockSizeAES128, - &dataOutMoved); - fatal_assert(rv == kCCSuccess); - fatal_assert(dataOutMoved == kCCBlockSizeAES128); +static void encrypt( unsigned char* src, unsigned char* dst, KEY* key ) +{ + size_t dataOutMoved; + CCCryptorStatus rv = CCCryptorUpdate( + key->ref, (const void*)src, kCCBlockSizeAES128, (void*)dst, kCCBlockSizeAES128, &dataOutMoved ); + fatal_assert( rv == kCCSuccess ); + fatal_assert( dataOutMoved == kCCBlockSizeAES128 ); } #if 0 /* unused */ @@ -540,26 +594,23 @@ static void decrypt(unsigned char *src, unsigned char *dst, KEY *key) { encrypt(src, dst, key); } #endif -static void ecb_encrypt_blks(block *blks, unsigned nblks, KEY *key) { - const size_t dataSize = kCCBlockSizeAES128 * nblks; - size_t dataOutMoved; - CCCryptorStatus rv = CCCryptorUpdate( - key->ref, - (const void *)blks, - dataSize, - (void *)blks, - dataSize, - &dataOutMoved); - fatal_assert(rv == kCCSuccess); - fatal_assert(dataOutMoved == dataSize); +static void ecb_encrypt_blks( block* blks, unsigned nblks, KEY* key ) +{ + const size_t dataSize = kCCBlockSizeAES128 * nblks; + size_t dataOutMoved; + CCCryptorStatus rv + = CCCryptorUpdate( key->ref, (const void*)blks, dataSize, (void*)blks, dataSize, &dataOutMoved ); + fatal_assert( rv == kCCSuccess ); + fatal_assert( dataOutMoved == dataSize ); } -static void ecb_decrypt_blks(block *blks, unsigned nblks, KEY *key) { - ecb_encrypt_blks(blks, nblks, key); +static void ecb_decrypt_blks( block* blks, unsigned nblks, KEY* key ) +{ + ecb_encrypt_blks( blks, nblks, key ); } -} // namespace ocb_aes +} // namespace ocb_aes -#define BPI 4 /* Number of blocks in buffer per ECB call */ +#define BPI 4 /* Number of blocks in buffer per ECB call */ /*-------------------*/ #elif USE_NETTLE_AES @@ -571,22 +622,29 @@ namespace ocb_aes { typedef struct aes128_ctx KEY; -static KEY *KEY_new() { return new KEY; } +static KEY* KEY_new() +{ + return new KEY; +} -static void KEY_delete(KEY *key) { delete key; } +static void KEY_delete( KEY* key ) +{ + delete key; +} -static void set_encrypt_key(const unsigned char *handle, const int bits, KEY *key) +static void set_encrypt_key( const unsigned char* handle, const int bits, KEY* key ) { - fatal_assert(bits == 128); - nettle_aes128_set_encrypt_key(key, (const uint8_t *)handle); + fatal_assert( bits == 128 ); + nettle_aes128_set_encrypt_key( key, (const uint8_t*)handle ); } -static void set_decrypt_key(const unsigned char *handle, const int bits, KEY *key) +static void set_decrypt_key( const unsigned char* handle, const int bits, KEY* key ) { - fatal_assert(bits == 128); - nettle_aes128_set_decrypt_key(key, (const uint8_t *)handle); + fatal_assert( bits == 128 ); + nettle_aes128_set_decrypt_key( key, (const uint8_t*)handle ); } -static void encrypt(unsigned char *src, unsigned char *dst, KEY *key) { - nettle_aes128_encrypt(key, AES_BLOCK_SIZE, dst, src); +static void encrypt( unsigned char* src, unsigned char* dst, KEY* key ) +{ + nettle_aes128_encrypt( key, AES_BLOCK_SIZE, dst, src ); } #if 0 /* unused */ @@ -594,16 +652,18 @@ static void decrypt(unsigned char *src, unsigned char *dst, KEY *key) { nettle_aes128_decrypt(key, AES_BLOCK_SIZE, dst, src); } #endif -static void ecb_encrypt_blks(block *blks, unsigned nblks, KEY *key) { - nettle_aes128_encrypt(key, nblks * AES_BLOCK_SIZE, (unsigned char*)blks, (unsigned char*)blks); +static void ecb_encrypt_blks( block* blks, unsigned nblks, KEY* key ) +{ + nettle_aes128_encrypt( key, nblks * AES_BLOCK_SIZE, (unsigned char*)blks, (unsigned char*)blks ); } -static void ecb_decrypt_blks(block *blks, unsigned nblks, KEY *key) { - nettle_aes128_decrypt(key, nblks * AES_BLOCK_SIZE, (unsigned char*)blks, (unsigned char*)blks); +static void ecb_decrypt_blks( block* blks, unsigned nblks, KEY* key ) +{ + nettle_aes128_decrypt( key, nblks * AES_BLOCK_SIZE, (unsigned char*)blks, (unsigned char*)blks ); } -} // namespace ocb_aes +} // namespace ocb_aes -#define BPI 4 /* Number of blocks in buffer per ECB call */ +#define BPI 4 /* Number of blocks in buffer per ECB call */ #else #error "No AES implementation selected." @@ -623,23 +683,24 @@ static void ecb_decrypt_blks(block *blks, unsigned nblks, KEY *key) { / with the plaintext or ciphertext. /------------------------------------------------------------------------- */ -struct _ae_ctx { - block offset; /* Memory correct */ - block checksum; /* Memory correct */ - block Lstar; /* Memory correct */ - block Ldollar; /* Memory correct */ - block L[L_TABLE_SZ]; /* Memory correct */ - block ad_checksum; /* Memory correct */ - block ad_offset; /* Memory correct */ - block cached_Top; /* Memory correct */ - uint64_t KtopStr[3]; /* Register correct, each item */ - uint32_t ad_blocks_processed; - uint32_t blocks_processed; - ocb_aes::KEY *decrypt_key; - ocb_aes::KEY *encrypt_key; - #if (OCB_TAG_LEN == 0) - unsigned tag_len; - #endif +struct _ae_ctx +{ + block offset; /* Memory correct */ + block checksum; /* Memory correct */ + block Lstar; /* Memory correct */ + block Ldollar; /* Memory correct */ + block L[L_TABLE_SZ]; /* Memory correct */ + block ad_checksum; /* Memory correct */ + block ad_offset; /* Memory correct */ + block cached_Top; /* Memory correct */ + uint64_t KtopStr[3]; /* Register correct, each item */ + uint32_t ad_blocks_processed; + uint32_t blocks_processed; + ocb_aes::KEY* decrypt_key; + ocb_aes::KEY* encrypt_key; +#if ( OCB_TAG_LEN == 0 ) + unsigned tag_len; +#endif }; /* ----------------------------------------------------------------------- */ @@ -647,21 +708,21 @@ struct _ae_ctx { /* ----------------------------------------------------------------------- */ #if L_TABLE_SZ_IS_ENOUGH -#define getL(_ctx, _tz) ((_ctx)->L[_tz]) +#define getL( _ctx, _tz ) ( ( _ctx )->L[_tz] ) #else -static block getL(const ae_ctx *ctx, unsigned tz) +static block getL( const ae_ctx* ctx, unsigned tz ) { - if (tz < L_TABLE_SZ) - return ctx->L[tz]; - else { - unsigned i; - /* Bring L[MAX] into registers, make it register correct */ - block rval = swap_if_le(ctx->L[L_TABLE_SZ-1]); - rval = double_block(rval); - for (i=L_TABLE_SZ; i < tz; i++) - rval = double_block(rval); - return swap_if_le(rval); /* To memory correct */ - } + if ( tz < L_TABLE_SZ ) + return ctx->L[tz]; + else { + unsigned i; + /* Bring L[MAX] into registers, make it register correct */ + block rval = swap_if_le( ctx->L[L_TABLE_SZ - 1] ); + rval = double_block( rval ); + for ( i = L_TABLE_SZ; i < tz; i++ ) + rval = double_block( rval ); + return swap_if_le( rval ); /* To memory correct */ + } } #endif @@ -676,403 +737,437 @@ static block getL(const ae_ctx *ctx, unsigned tz) /* ----------------------------------------------------------------------- */ -int ae_clear (ae_ctx *ctx) /* Zero ae_ctx and undo initialization */ +int ae_clear( ae_ctx* ctx ) /* Zero ae_ctx and undo initialization */ { - ocb_aes::KEY_delete(ctx->encrypt_key); - ocb_aes::KEY_delete(ctx->decrypt_key); - memset(ctx, 0, sizeof(ae_ctx)); - return AE_SUCCESS; + ocb_aes::KEY_delete( ctx->encrypt_key ); + ocb_aes::KEY_delete( ctx->decrypt_key ); + memset( ctx, 0, sizeof( ae_ctx ) ); + return AE_SUCCESS; } -int ae_ctx_sizeof(void) { return (int) sizeof(ae_ctx); } +int ae_ctx_sizeof( void ) +{ + return (int)sizeof( ae_ctx ); +} /* ----------------------------------------------------------------------- */ -int ae_init(ae_ctx *ctx, const void *key, int key_len, int nonce_len, int tag_len) +int ae_init( ae_ctx* ctx, const void* key, int key_len, int nonce_len, int tag_len ) { - unsigned i; - block tmp_blk; - - if (nonce_len != 12) - return AE_NOT_SUPPORTED; - - ctx->decrypt_key = ocb_aes::KEY_new(); - ctx->encrypt_key = ocb_aes::KEY_new(); - - /* Initialize encryption & decryption keys */ - #if (OCB_KEY_LEN > 0) - key_len = OCB_KEY_LEN; - #endif - ocb_aes::set_encrypt_key(reinterpret_cast(key), key_len*8, ctx->encrypt_key); - ocb_aes::set_decrypt_key(reinterpret_cast(key), static_cast(key_len*8), ctx->decrypt_key); - - /* Zero things that need zeroing */ - ctx->cached_Top = ctx->ad_checksum = zero_block(); - ctx->ad_blocks_processed = 0; - - /* Compute key-dependent values */ - ocb_aes::encrypt(reinterpret_cast(&ctx->cached_Top), - reinterpret_cast(&ctx->Lstar), ctx->encrypt_key); - tmp_blk = swap_if_le(ctx->Lstar); - tmp_blk = double_block(tmp_blk); - ctx->Ldollar = swap_if_le(tmp_blk); - tmp_blk = double_block(tmp_blk); - ctx->L[0] = swap_if_le(tmp_blk); - for (i = 1; i < L_TABLE_SZ; i++) { - tmp_blk = double_block(tmp_blk); - ctx->L[i] = swap_if_le(tmp_blk); - } + unsigned i; + block tmp_blk; + + if ( nonce_len != 12 ) + return AE_NOT_SUPPORTED; - #if (OCB_TAG_LEN == 0) - ctx->tag_len = tag_len; - #else - (void) tag_len; /* Suppress var not used error */ - #endif + ctx->decrypt_key = ocb_aes::KEY_new(); + ctx->encrypt_key = ocb_aes::KEY_new(); + +/* Initialize encryption & decryption keys */ +#if ( OCB_KEY_LEN > 0 ) + key_len = OCB_KEY_LEN; +#endif + ocb_aes::set_encrypt_key( reinterpret_cast( key ), key_len * 8, ctx->encrypt_key ); + ocb_aes::set_decrypt_key( + reinterpret_cast( key ), static_cast( key_len * 8 ), ctx->decrypt_key ); + + /* Zero things that need zeroing */ + ctx->cached_Top = ctx->ad_checksum = zero_block(); + ctx->ad_blocks_processed = 0; + + /* Compute key-dependent values */ + ocb_aes::encrypt( reinterpret_cast( &ctx->cached_Top ), + reinterpret_cast( &ctx->Lstar ), + ctx->encrypt_key ); + tmp_blk = swap_if_le( ctx->Lstar ); + tmp_blk = double_block( tmp_blk ); + ctx->Ldollar = swap_if_le( tmp_blk ); + tmp_blk = double_block( tmp_blk ); + ctx->L[0] = swap_if_le( tmp_blk ); + for ( i = 1; i < L_TABLE_SZ; i++ ) { + tmp_blk = double_block( tmp_blk ); + ctx->L[i] = swap_if_le( tmp_blk ); + } + +#if ( OCB_TAG_LEN == 0 ) + ctx->tag_len = tag_len; +#else + (void)tag_len; /* Suppress var not used error */ +#endif - return AE_SUCCESS; + return AE_SUCCESS; } /* ----------------------------------------------------------------------- */ -static block gen_offset_from_nonce(ae_ctx *ctx, const void *nonce) +static block gen_offset_from_nonce( ae_ctx* ctx, const void* nonce ) { - const union { unsigned x; unsigned char endian; } little = { 1 }; - union { uint32_t u32[4]; uint8_t u8[16]; block bl; } tmp; - unsigned idx; - - /* Replace cached nonce Top if needed */ - tmp.u32[0] = (little.endian?0x01000000:0x00000001); - tmp.u32[1] = ((uint32_t *)nonce)[0]; - tmp.u32[2] = ((uint32_t *)nonce)[1]; - tmp.u32[3] = ((uint32_t *)nonce)[2]; - idx = (unsigned)(tmp.u8[15] & 0x3f); /* Get low 6 bits of nonce */ - tmp.u8[15] = tmp.u8[15] & 0xc0; /* Zero low 6 bits of nonce */ - if ( unequal_blocks(tmp.bl,ctx->cached_Top) ) { /* Cached? */ - ctx->cached_Top = tmp.bl; /* Update cache, KtopStr */ - ocb_aes::encrypt(tmp.u8, (unsigned char *)&ctx->KtopStr, ctx->encrypt_key); - if (little.endian) { /* Make Register Correct */ - ctx->KtopStr[0] = bswap64(ctx->KtopStr[0]); - ctx->KtopStr[1] = bswap64(ctx->KtopStr[1]); - } - ctx->KtopStr[2] = ctx->KtopStr[0] ^ - (ctx->KtopStr[0] << 8) ^ (ctx->KtopStr[1] >> 56); - } - return gen_offset(ctx->KtopStr, idx); + const union { + unsigned x; + unsigned char endian; + } little = { 1 }; + union { + uint32_t u32[4]; + uint8_t u8[16]; + block bl; + } tmp; + unsigned idx; + + /* Replace cached nonce Top if needed */ + tmp.u32[0] = ( little.endian ? 0x01000000 : 0x00000001 ); + tmp.u32[1] = ( (uint32_t*)nonce )[0]; + tmp.u32[2] = ( (uint32_t*)nonce )[1]; + tmp.u32[3] = ( (uint32_t*)nonce )[2]; + idx = (unsigned)( tmp.u8[15] & 0x3f ); /* Get low 6 bits of nonce */ + tmp.u8[15] = tmp.u8[15] & 0xc0; /* Zero low 6 bits of nonce */ + if ( unequal_blocks( tmp.bl, ctx->cached_Top ) ) { /* Cached? */ + ctx->cached_Top = tmp.bl; /* Update cache, KtopStr */ + ocb_aes::encrypt( tmp.u8, (unsigned char*)&ctx->KtopStr, ctx->encrypt_key ); + if ( little.endian ) { /* Make Register Correct */ + ctx->KtopStr[0] = bswap64( ctx->KtopStr[0] ); + ctx->KtopStr[1] = bswap64( ctx->KtopStr[1] ); + } + ctx->KtopStr[2] = ctx->KtopStr[0] ^ ( ctx->KtopStr[0] << 8 ) ^ ( ctx->KtopStr[1] >> 56 ); + } + return gen_offset( ctx->KtopStr, idx ); } -static void process_ad(ae_ctx *ctx, const void *ad, int ad_len, int final) +static void process_ad( ae_ctx* ctx, const void* ad, int ad_len, int final ) { - union { uint32_t u32[4]; uint8_t u8[16]; block bl; } tmp; - block ad_offset, ad_checksum; - const block * adp = (block *)ad; - unsigned i,k,tz,remaining; - - ad_offset = ctx->ad_offset; - ad_checksum = ctx->ad_checksum; - i = ad_len/(BPI*16); - if (i) { - unsigned ad_block_num = ctx->ad_blocks_processed; - do { - block ta[BPI], oa[BPI]; - ad_block_num += BPI; - tz = ntz(ad_block_num); - oa[0] = xor_block(ad_offset, ctx->L[0]); - ta[0] = xor_block(oa[0], adp[0]); - oa[1] = xor_block(oa[0], ctx->L[1]); - ta[1] = xor_block(oa[1], adp[1]); - oa[2] = xor_block(ad_offset, ctx->L[1]); - ta[2] = xor_block(oa[2], adp[2]); - #if BPI == 4 - ad_offset = xor_block(oa[2], getL(ctx, tz)); - ta[3] = xor_block(ad_offset, adp[3]); - #elif BPI == 8 - oa[3] = xor_block(oa[2], ctx->L[2]); - ta[3] = xor_block(oa[3], adp[3]); - oa[4] = xor_block(oa[1], ctx->L[2]); - ta[4] = xor_block(oa[4], adp[4]); - oa[5] = xor_block(oa[0], ctx->L[2]); - ta[5] = xor_block(oa[5], adp[5]); - oa[6] = xor_block(ad_offset, ctx->L[2]); - ta[6] = xor_block(oa[6], adp[6]); - ad_offset = xor_block(oa[6], getL(ctx, tz)); - ta[7] = xor_block(ad_offset, adp[7]); - #endif - ocb_aes::ecb_encrypt_blks(ta, BPI, ctx->encrypt_key); - ad_checksum = xor_block(ad_checksum, ta[0]); - ad_checksum = xor_block(ad_checksum, ta[1]); - ad_checksum = xor_block(ad_checksum, ta[2]); - ad_checksum = xor_block(ad_checksum, ta[3]); - #if (BPI == 8) - ad_checksum = xor_block(ad_checksum, ta[4]); - ad_checksum = xor_block(ad_checksum, ta[5]); - ad_checksum = xor_block(ad_checksum, ta[6]); - ad_checksum = xor_block(ad_checksum, ta[7]); - #endif - adp += BPI; - } while (--i); - ctx->ad_blocks_processed = ad_block_num; - ctx->ad_offset = ad_offset; - ctx->ad_checksum = ad_checksum; - } - - if (final) { - block ta[BPI]; - - /* Process remaining associated data, compute its tag contribution */ - remaining = ((unsigned)ad_len) % (BPI*16); - if (remaining) { - k=0; - #if (BPI == 8) - if (remaining >= 64) { - tmp.bl = xor_block(ad_offset, ctx->L[0]); - ta[0] = xor_block(tmp.bl, adp[0]); - tmp.bl = xor_block(tmp.bl, ctx->L[1]); - ta[1] = xor_block(tmp.bl, adp[1]); - ad_offset = xor_block(ad_offset, ctx->L[1]); - ta[2] = xor_block(ad_offset, adp[2]); - ad_offset = xor_block(ad_offset, ctx->L[2]); - ta[3] = xor_block(ad_offset, adp[3]); - remaining -= 64; - k=4; - } - #endif - if (remaining >= 32) { - ad_offset = xor_block(ad_offset, ctx->L[0]); - ta[k] = xor_block(ad_offset, adp[k]); - ad_offset = xor_block(ad_offset, getL(ctx, ntz(k+2))); - ta[k+1] = xor_block(ad_offset, adp[k+1]); - remaining -= 32; - k+=2; - } - if (remaining >= 16) { - ad_offset = xor_block(ad_offset, ctx->L[0]); - ta[k] = xor_block(ad_offset, adp[k]); - remaining = remaining - 16; - ++k; - } - if (remaining) { - ad_offset = xor_block(ad_offset,ctx->Lstar); - tmp.bl = zero_block(); - memcpy(tmp.u8, adp+k, remaining); - tmp.u8[remaining] = (unsigned char)0x80u; - ta[k] = xor_block(ad_offset, tmp.bl); - ++k; - } - ocb_aes::ecb_encrypt_blks(ta, k, ctx->encrypt_key); - switch (k) { - #if (BPI == 8) - case 8: ad_checksum = xor_block(ad_checksum, ta[7]); - /* fallthrough */ - case 7: ad_checksum = xor_block(ad_checksum, ta[6]); - /* fallthrough */ - case 6: ad_checksum = xor_block(ad_checksum, ta[5]); - /* fallthrough */ - case 5: ad_checksum = xor_block(ad_checksum, ta[4]); - /* fallthrough */ - #endif - case 4: ad_checksum = xor_block(ad_checksum, ta[3]); - /* fallthrough */ - case 3: ad_checksum = xor_block(ad_checksum, ta[2]); - /* fallthrough */ - case 2: ad_checksum = xor_block(ad_checksum, ta[1]); - /* fallthrough */ - case 1: ad_checksum = xor_block(ad_checksum, ta[0]); - } - ctx->ad_checksum = ad_checksum; - } - } + union { + uint32_t u32[4]; + uint8_t u8[16]; + block bl; + } tmp; + block ad_offset, ad_checksum; + const block* adp = (block*)ad; + unsigned i, k, tz, remaining; + + ad_offset = ctx->ad_offset; + ad_checksum = ctx->ad_checksum; + i = ad_len / ( BPI * 16 ); + if ( i ) { + unsigned ad_block_num = ctx->ad_blocks_processed; + do { + block ta[BPI], oa[BPI]; + ad_block_num += BPI; + tz = ntz( ad_block_num ); + oa[0] = xor_block( ad_offset, ctx->L[0] ); + ta[0] = xor_block( oa[0], adp[0] ); + oa[1] = xor_block( oa[0], ctx->L[1] ); + ta[1] = xor_block( oa[1], adp[1] ); + oa[2] = xor_block( ad_offset, ctx->L[1] ); + ta[2] = xor_block( oa[2], adp[2] ); +#if BPI == 4 + ad_offset = xor_block( oa[2], getL( ctx, tz ) ); + ta[3] = xor_block( ad_offset, adp[3] ); +#elif BPI == 8 + oa[3] = xor_block( oa[2], ctx->L[2] ); + ta[3] = xor_block( oa[3], adp[3] ); + oa[4] = xor_block( oa[1], ctx->L[2] ); + ta[4] = xor_block( oa[4], adp[4] ); + oa[5] = xor_block( oa[0], ctx->L[2] ); + ta[5] = xor_block( oa[5], adp[5] ); + oa[6] = xor_block( ad_offset, ctx->L[2] ); + ta[6] = xor_block( oa[6], adp[6] ); + ad_offset = xor_block( oa[6], getL( ctx, tz ) ); + ta[7] = xor_block( ad_offset, adp[7] ); +#endif + ocb_aes::ecb_encrypt_blks( ta, BPI, ctx->encrypt_key ); + ad_checksum = xor_block( ad_checksum, ta[0] ); + ad_checksum = xor_block( ad_checksum, ta[1] ); + ad_checksum = xor_block( ad_checksum, ta[2] ); + ad_checksum = xor_block( ad_checksum, ta[3] ); +#if ( BPI == 8 ) + ad_checksum = xor_block( ad_checksum, ta[4] ); + ad_checksum = xor_block( ad_checksum, ta[5] ); + ad_checksum = xor_block( ad_checksum, ta[6] ); + ad_checksum = xor_block( ad_checksum, ta[7] ); +#endif + adp += BPI; + } while ( --i ); + ctx->ad_blocks_processed = ad_block_num; + ctx->ad_offset = ad_offset; + ctx->ad_checksum = ad_checksum; + } + + if ( final ) { + block ta[BPI]; + + /* Process remaining associated data, compute its tag contribution */ + remaining = ( (unsigned)ad_len ) % ( BPI * 16 ); + if ( remaining ) { + k = 0; +#if ( BPI == 8 ) + if ( remaining >= 64 ) { + tmp.bl = xor_block( ad_offset, ctx->L[0] ); + ta[0] = xor_block( tmp.bl, adp[0] ); + tmp.bl = xor_block( tmp.bl, ctx->L[1] ); + ta[1] = xor_block( tmp.bl, adp[1] ); + ad_offset = xor_block( ad_offset, ctx->L[1] ); + ta[2] = xor_block( ad_offset, adp[2] ); + ad_offset = xor_block( ad_offset, ctx->L[2] ); + ta[3] = xor_block( ad_offset, adp[3] ); + remaining -= 64; + k = 4; + } +#endif + if ( remaining >= 32 ) { + ad_offset = xor_block( ad_offset, ctx->L[0] ); + ta[k] = xor_block( ad_offset, adp[k] ); + ad_offset = xor_block( ad_offset, getL( ctx, ntz( k + 2 ) ) ); + ta[k + 1] = xor_block( ad_offset, adp[k + 1] ); + remaining -= 32; + k += 2; + } + if ( remaining >= 16 ) { + ad_offset = xor_block( ad_offset, ctx->L[0] ); + ta[k] = xor_block( ad_offset, adp[k] ); + remaining = remaining - 16; + ++k; + } + if ( remaining ) { + ad_offset = xor_block( ad_offset, ctx->Lstar ); + tmp.bl = zero_block(); + memcpy( tmp.u8, adp + k, remaining ); + tmp.u8[remaining] = (unsigned char)0x80u; + ta[k] = xor_block( ad_offset, tmp.bl ); + ++k; + } + ocb_aes::ecb_encrypt_blks( ta, k, ctx->encrypt_key ); + switch ( k ) { +#if ( BPI == 8 ) + case 8: + ad_checksum = xor_block( ad_checksum, ta[7] ); + /* fallthrough */ + case 7: + ad_checksum = xor_block( ad_checksum, ta[6] ); + /* fallthrough */ + case 6: + ad_checksum = xor_block( ad_checksum, ta[5] ); + /* fallthrough */ + case 5: + ad_checksum = xor_block( ad_checksum, ta[4] ); + /* fallthrough */ +#endif + case 4: + ad_checksum = xor_block( ad_checksum, ta[3] ); + /* fallthrough */ + case 3: + ad_checksum = xor_block( ad_checksum, ta[2] ); + /* fallthrough */ + case 2: + ad_checksum = xor_block( ad_checksum, ta[1] ); + /* fallthrough */ + case 1: + ad_checksum = xor_block( ad_checksum, ta[0] ); + } + ctx->ad_checksum = ad_checksum; + } + } } /* ----------------------------------------------------------------------- */ -int ae_encrypt(ae_ctx * ctx, - const void * nonce, - const void *pt, - int pt_len, - const void *ad, - int ad_len, - void *ct, - void *tag, - int final) +int ae_encrypt( ae_ctx* ctx, + const void* nonce, + const void* pt, + int pt_len, + const void* ad, + int ad_len, + void* ct, + void* tag, + int final ) { - union { uint32_t u32[4]; uint8_t u8[16]; block bl; } tmp; - block offset, checksum; - unsigned i, k; - block * ctp = (block *)ct; - const block * ptp = (block *)pt; - - /* Non-null nonce means start of new message, init per-message values */ - if (nonce) { - ctx->offset = gen_offset_from_nonce(ctx, nonce); - ctx->ad_offset = ctx->checksum = zero_block(); - ctx->ad_blocks_processed = ctx->blocks_processed = 0; - if (ad_len >= 0) - ctx->ad_checksum = zero_block(); + union { + uint32_t u32[4]; + uint8_t u8[16]; + block bl; + } tmp; + block offset, checksum; + unsigned i, k; + block* ctp = (block*)ct; + const block* ptp = (block*)pt; + + /* Non-null nonce means start of new message, init per-message values */ + if ( nonce ) { + ctx->offset = gen_offset_from_nonce( ctx, nonce ); + ctx->ad_offset = ctx->checksum = zero_block(); + ctx->ad_blocks_processed = ctx->blocks_processed = 0; + if ( ad_len >= 0 ) + ctx->ad_checksum = zero_block(); + } + + /* Process associated data */ + if ( ad_len > 0 ) + process_ad( ctx, ad, ad_len, final ); + + /* Encrypt plaintext data BPI blocks at a time */ + offset = ctx->offset; + checksum = ctx->checksum; + i = pt_len / ( BPI * 16 ); + if ( i ) { + block oa[BPI]; + unsigned block_num = ctx->blocks_processed; + oa[BPI - 1] = offset; + do { + block ta[BPI]; + block_num += BPI; + oa[0] = xor_block( oa[BPI - 1], ctx->L[0] ); + ta[0] = xor_block( oa[0], ptp[0] ); + checksum = xor_block( checksum, ptp[0] ); + oa[1] = xor_block( oa[0], ctx->L[1] ); + ta[1] = xor_block( oa[1], ptp[1] ); + checksum = xor_block( checksum, ptp[1] ); + oa[2] = xor_block( oa[1], ctx->L[0] ); + ta[2] = xor_block( oa[2], ptp[2] ); + checksum = xor_block( checksum, ptp[2] ); +#if BPI == 4 + oa[3] = xor_block( oa[2], getL( ctx, ntz( block_num ) ) ); + ta[3] = xor_block( oa[3], ptp[3] ); + checksum = xor_block( checksum, ptp[3] ); +#elif BPI == 8 + oa[3] = xor_block( oa[2], ctx->L[2] ); + ta[3] = xor_block( oa[3], ptp[3] ); + checksum = xor_block( checksum, ptp[3] ); + oa[4] = xor_block( oa[1], ctx->L[2] ); + ta[4] = xor_block( oa[4], ptp[4] ); + checksum = xor_block( checksum, ptp[4] ); + oa[5] = xor_block( oa[0], ctx->L[2] ); + ta[5] = xor_block( oa[5], ptp[5] ); + checksum = xor_block( checksum, ptp[5] ); + oa[6] = xor_block( oa[7], ctx->L[2] ); + ta[6] = xor_block( oa[6], ptp[6] ); + checksum = xor_block( checksum, ptp[6] ); + oa[7] = xor_block( oa[6], getL( ctx, ntz( block_num ) ) ); + ta[7] = xor_block( oa[7], ptp[7] ); + checksum = xor_block( checksum, ptp[7] ); +#endif + ocb_aes::ecb_encrypt_blks( ta, BPI, ctx->encrypt_key ); + ctp[0] = xor_block( ta[0], oa[0] ); + ctp[1] = xor_block( ta[1], oa[1] ); + ctp[2] = xor_block( ta[2], oa[2] ); + ctp[3] = xor_block( ta[3], oa[3] ); +#if ( BPI == 8 ) + ctp[4] = xor_block( ta[4], oa[4] ); + ctp[5] = xor_block( ta[5], oa[5] ); + ctp[6] = xor_block( ta[6], oa[6] ); + ctp[7] = xor_block( ta[7], oa[7] ); +#endif + ptp += BPI; + ctp += BPI; + } while ( --i ); + ctx->offset = offset = oa[BPI - 1]; + ctx->blocks_processed = block_num; + ctx->checksum = checksum; + } + + if ( final ) { + block ta[BPI + 1], oa[BPI]; + + /* Process remaining plaintext and compute its tag contribution */ + unsigned remaining = ( (unsigned)pt_len ) % ( BPI * 16 ); + k = 0; /* How many blocks in ta[] need ECBing */ + if ( remaining ) { +#if ( BPI == 8 ) + if ( remaining >= 64 ) { + oa[0] = xor_block( offset, ctx->L[0] ); + ta[0] = xor_block( oa[0], ptp[0] ); + checksum = xor_block( checksum, ptp[0] ); + oa[1] = xor_block( oa[0], ctx->L[1] ); + ta[1] = xor_block( oa[1], ptp[1] ); + checksum = xor_block( checksum, ptp[1] ); + oa[2] = xor_block( oa[1], ctx->L[0] ); + ta[2] = xor_block( oa[2], ptp[2] ); + checksum = xor_block( checksum, ptp[2] ); + offset = oa[3] = xor_block( oa[2], ctx->L[2] ); + ta[3] = xor_block( offset, ptp[3] ); + checksum = xor_block( checksum, ptp[3] ); + remaining -= 64; + k = 4; + } +#endif + if ( remaining >= 32 ) { + oa[k] = xor_block( offset, ctx->L[0] ); + ta[k] = xor_block( oa[k], ptp[k] ); + checksum = xor_block( checksum, ptp[k] ); + offset = oa[k + 1] = xor_block( oa[k], ctx->L[1] ); + ta[k + 1] = xor_block( offset, ptp[k + 1] ); + checksum = xor_block( checksum, ptp[k + 1] ); + remaining -= 32; + k += 2; + } + if ( remaining >= 16 ) { + offset = oa[k] = xor_block( offset, ctx->L[0] ); + ta[k] = xor_block( offset, ptp[k] ); + checksum = xor_block( checksum, ptp[k] ); + remaining -= 16; + ++k; + } + if ( remaining ) { + tmp.bl = zero_block(); + memcpy( tmp.u8, ptp + k, remaining ); + tmp.u8[remaining] = (unsigned char)0x80u; + checksum = xor_block( checksum, tmp.bl ); + ta[k] = offset = xor_block( offset, ctx->Lstar ); + ++k; + } } - - /* Process associated data */ - if (ad_len > 0) - process_ad(ctx, ad, ad_len, final); - - /* Encrypt plaintext data BPI blocks at a time */ - offset = ctx->offset; - checksum = ctx->checksum; - i = pt_len/(BPI*16); - if (i) { - block oa[BPI]; - unsigned block_num = ctx->blocks_processed; - oa[BPI-1] = offset; - do { - block ta[BPI]; - block_num += BPI; - oa[0] = xor_block(oa[BPI-1], ctx->L[0]); - ta[0] = xor_block(oa[0], ptp[0]); - checksum = xor_block(checksum, ptp[0]); - oa[1] = xor_block(oa[0], ctx->L[1]); - ta[1] = xor_block(oa[1], ptp[1]); - checksum = xor_block(checksum, ptp[1]); - oa[2] = xor_block(oa[1], ctx->L[0]); - ta[2] = xor_block(oa[2], ptp[2]); - checksum = xor_block(checksum, ptp[2]); - #if BPI == 4 - oa[3] = xor_block(oa[2], getL(ctx, ntz(block_num))); - ta[3] = xor_block(oa[3], ptp[3]); - checksum = xor_block(checksum, ptp[3]); - #elif BPI == 8 - oa[3] = xor_block(oa[2], ctx->L[2]); - ta[3] = xor_block(oa[3], ptp[3]); - checksum = xor_block(checksum, ptp[3]); - oa[4] = xor_block(oa[1], ctx->L[2]); - ta[4] = xor_block(oa[4], ptp[4]); - checksum = xor_block(checksum, ptp[4]); - oa[5] = xor_block(oa[0], ctx->L[2]); - ta[5] = xor_block(oa[5], ptp[5]); - checksum = xor_block(checksum, ptp[5]); - oa[6] = xor_block(oa[7], ctx->L[2]); - ta[6] = xor_block(oa[6], ptp[6]); - checksum = xor_block(checksum, ptp[6]); - oa[7] = xor_block(oa[6], getL(ctx, ntz(block_num))); - ta[7] = xor_block(oa[7], ptp[7]); - checksum = xor_block(checksum, ptp[7]); - #endif - ocb_aes::ecb_encrypt_blks(ta, BPI, ctx->encrypt_key); - ctp[0] = xor_block(ta[0], oa[0]); - ctp[1] = xor_block(ta[1], oa[1]); - ctp[2] = xor_block(ta[2], oa[2]); - ctp[3] = xor_block(ta[3], oa[3]); - #if (BPI == 8) - ctp[4] = xor_block(ta[4], oa[4]); - ctp[5] = xor_block(ta[5], oa[5]); - ctp[6] = xor_block(ta[6], oa[6]); - ctp[7] = xor_block(ta[7], oa[7]); - #endif - ptp += BPI; - ctp += BPI; - } while (--i); - ctx->offset = offset = oa[BPI-1]; - ctx->blocks_processed = block_num; - ctx->checksum = checksum; + offset = xor_block( offset, ctx->Ldollar ); /* Part of tag gen */ + ta[k] = xor_block( offset, checksum ); /* Part of tag gen */ + ocb_aes::ecb_encrypt_blks( ta, k + 1, ctx->encrypt_key ); + offset = xor_block( ta[k], ctx->ad_checksum ); /* Part of tag gen */ + if ( remaining ) { + --k; + tmp.bl = xor_block( tmp.bl, ta[k] ); + memcpy( ctp + k, tmp.u8, remaining ); + } + switch ( k ) { +#if ( BPI == 8 ) + case 7: + ctp[6] = xor_block( ta[6], oa[6] ); + /* fallthrough */ + case 6: + ctp[5] = xor_block( ta[5], oa[5] ); + /* fallthrough */ + case 5: + ctp[4] = xor_block( ta[4], oa[4] ); + /* fallthrough */ + case 4: + ctp[3] = xor_block( ta[3], oa[3] ); + /* fallthrough */ +#endif + case 3: + ctp[2] = xor_block( ta[2], oa[2] ); + /* fallthrough */ + case 2: + ctp[1] = xor_block( ta[1], oa[1] ); + /* fallthrough */ + case 1: + ctp[0] = xor_block( ta[0], oa[0] ); } - if (final) { - block ta[BPI+1], oa[BPI]; - - /* Process remaining plaintext and compute its tag contribution */ - unsigned remaining = ((unsigned)pt_len) % (BPI*16); - k = 0; /* How many blocks in ta[] need ECBing */ - if (remaining) { - #if (BPI == 8) - if (remaining >= 64) { - oa[0] = xor_block(offset, ctx->L[0]); - ta[0] = xor_block(oa[0], ptp[0]); - checksum = xor_block(checksum, ptp[0]); - oa[1] = xor_block(oa[0], ctx->L[1]); - ta[1] = xor_block(oa[1], ptp[1]); - checksum = xor_block(checksum, ptp[1]); - oa[2] = xor_block(oa[1], ctx->L[0]); - ta[2] = xor_block(oa[2], ptp[2]); - checksum = xor_block(checksum, ptp[2]); - offset = oa[3] = xor_block(oa[2], ctx->L[2]); - ta[3] = xor_block(offset, ptp[3]); - checksum = xor_block(checksum, ptp[3]); - remaining -= 64; - k = 4; - } - #endif - if (remaining >= 32) { - oa[k] = xor_block(offset, ctx->L[0]); - ta[k] = xor_block(oa[k], ptp[k]); - checksum = xor_block(checksum, ptp[k]); - offset = oa[k+1] = xor_block(oa[k], ctx->L[1]); - ta[k+1] = xor_block(offset, ptp[k+1]); - checksum = xor_block(checksum, ptp[k+1]); - remaining -= 32; - k+=2; - } - if (remaining >= 16) { - offset = oa[k] = xor_block(offset, ctx->L[0]); - ta[k] = xor_block(offset, ptp[k]); - checksum = xor_block(checksum, ptp[k]); - remaining -= 16; - ++k; - } - if (remaining) { - tmp.bl = zero_block(); - memcpy(tmp.u8, ptp+k, remaining); - tmp.u8[remaining] = (unsigned char)0x80u; - checksum = xor_block(checksum, tmp.bl); - ta[k] = offset = xor_block(offset,ctx->Lstar); - ++k; - } - } - offset = xor_block(offset, ctx->Ldollar); /* Part of tag gen */ - ta[k] = xor_block(offset, checksum); /* Part of tag gen */ - ocb_aes::ecb_encrypt_blks(ta, k + 1, ctx->encrypt_key); - offset = xor_block(ta[k], ctx->ad_checksum); /* Part of tag gen */ - if (remaining) { - --k; - tmp.bl = xor_block(tmp.bl, ta[k]); - memcpy(ctp+k, tmp.u8, remaining); - } - switch (k) { - #if (BPI == 8) - case 7: ctp[6] = xor_block(ta[6], oa[6]); - /* fallthrough */ - case 6: ctp[5] = xor_block(ta[5], oa[5]); - /* fallthrough */ - case 5: ctp[4] = xor_block(ta[4], oa[4]); - /* fallthrough */ - case 4: ctp[3] = xor_block(ta[3], oa[3]); - /* fallthrough */ - #endif - case 3: ctp[2] = xor_block(ta[2], oa[2]); - /* fallthrough */ - case 2: ctp[1] = xor_block(ta[1], oa[1]); - /* fallthrough */ - case 1: ctp[0] = xor_block(ta[0], oa[0]); - } - - /* Tag is placed at the correct location - */ - if (tag) { - #if (OCB_TAG_LEN == 16) - *(block *)tag = offset; - #elif (OCB_TAG_LEN > 0) - memcpy((char *)tag, &offset, OCB_TAG_LEN); - #else - memcpy((char *)tag, &offset, ctx->tag_len); - #endif - } else { - #if (OCB_TAG_LEN > 0) - memcpy((char *)ct + pt_len, &offset, OCB_TAG_LEN); - pt_len += OCB_TAG_LEN; - #else - memcpy((char *)ct + pt_len, &offset, ctx->tag_len); - pt_len += ctx->tag_len; - #endif - } + /* Tag is placed at the correct location + */ + if ( tag ) { +#if ( OCB_TAG_LEN == 16 ) + *(block*)tag = offset; +#elif ( OCB_TAG_LEN > 0 ) + memcpy( (char*)tag, &offset, OCB_TAG_LEN ); +#else + memcpy( (char*)tag, &offset, ctx->tag_len ); +#endif + } else { +#if ( OCB_TAG_LEN > 0 ) + memcpy( (char*)ct + pt_len, &offset, OCB_TAG_LEN ); + pt_len += OCB_TAG_LEN; +#else + memcpy( (char*)ct + pt_len, &offset, ctx->tag_len ); + pt_len += ctx->tag_len; +#endif } - return (int) pt_len; + } + return (int)pt_len; } /* ----------------------------------------------------------------------- */ @@ -1084,373 +1179,421 @@ int ae_encrypt(ae_ctx * ctx, Use this to avoid timing side-channel attacks. Returns 0 for memory regions with equal contents; non-zero otherwise. */ -static int constant_time_memcmp(const void *av, const void *bv, size_t n) { - const uint8_t *a = (const uint8_t *) av; - const uint8_t *b = (const uint8_t *) bv; - uint8_t result = 0; - size_t i; - - for (i=0; i 0) - ct_len -= OCB_TAG_LEN; - #else - ct_len -= ctx->tag_len; - #endif - - /* Non-null nonce means start of new message, init per-message values */ - if (nonce) { - ctx->offset = gen_offset_from_nonce(ctx, nonce); - ctx->ad_offset = ctx->checksum = zero_block(); - ctx->ad_blocks_processed = ctx->blocks_processed = 0; - if (ad_len >= 0) - ctx->ad_checksum = zero_block(); - } + union { + uint32_t u32[4]; + uint8_t u8[16]; + block bl; + } tmp; + block offset, checksum; + unsigned i, k; + block* ctp = (block*)ct; + block* ptp = (block*)pt; + + /* Reduce ct_len tag bundled in ct */ + if ( ( final ) && ( !tag ) ) +#if ( OCB_TAG_LEN > 0 ) + ct_len -= OCB_TAG_LEN; +#else + ct_len -= ctx->tag_len; +#endif - /* Process associated data */ - if (ad_len > 0) - process_ad(ctx, ad, ad_len, final); - - /* Encrypt plaintext data BPI blocks at a time */ - offset = ctx->offset; - checksum = ctx->checksum; - i = ct_len/(BPI*16); - if (i) { - block oa[BPI]; - unsigned block_num = ctx->blocks_processed; - oa[BPI-1] = offset; - do { - block ta[BPI]; - block_num += BPI; - oa[0] = xor_block(oa[BPI-1], ctx->L[0]); - ta[0] = xor_block(oa[0], ctp[0]); - oa[1] = xor_block(oa[0], ctx->L[1]); - ta[1] = xor_block(oa[1], ctp[1]); - oa[2] = xor_block(oa[1], ctx->L[0]); - ta[2] = xor_block(oa[2], ctp[2]); - #if BPI == 4 - oa[3] = xor_block(oa[2], getL(ctx, ntz(block_num))); - ta[3] = xor_block(oa[3], ctp[3]); - #elif BPI == 8 - oa[3] = xor_block(oa[2], ctx->L[2]); - ta[3] = xor_block(oa[3], ctp[3]); - oa[4] = xor_block(oa[1], ctx->L[2]); - ta[4] = xor_block(oa[4], ctp[4]); - oa[5] = xor_block(oa[0], ctx->L[2]); - ta[5] = xor_block(oa[5], ctp[5]); - oa[6] = xor_block(oa[7], ctx->L[2]); - ta[6] = xor_block(oa[6], ctp[6]); - oa[7] = xor_block(oa[6], getL(ctx, ntz(block_num))); - ta[7] = xor_block(oa[7], ctp[7]); - #endif - ocb_aes::ecb_decrypt_blks(ta,BPI,ctx->decrypt_key); - ptp[0] = xor_block(ta[0], oa[0]); - checksum = xor_block(checksum, ptp[0]); - ptp[1] = xor_block(ta[1], oa[1]); - checksum = xor_block(checksum, ptp[1]); - ptp[2] = xor_block(ta[2], oa[2]); - checksum = xor_block(checksum, ptp[2]); - ptp[3] = xor_block(ta[3], oa[3]); - checksum = xor_block(checksum, ptp[3]); - #if (BPI == 8) - ptp[4] = xor_block(ta[4], oa[4]); - checksum = xor_block(checksum, ptp[4]); - ptp[5] = xor_block(ta[5], oa[5]); - checksum = xor_block(checksum, ptp[5]); - ptp[6] = xor_block(ta[6], oa[6]); - checksum = xor_block(checksum, ptp[6]); - ptp[7] = xor_block(ta[7], oa[7]); - checksum = xor_block(checksum, ptp[7]); - #endif - ptp += BPI; - ctp += BPI; - } while (--i); - ctx->offset = offset = oa[BPI-1]; - ctx->blocks_processed = block_num; - ctx->checksum = checksum; + /* Non-null nonce means start of new message, init per-message values */ + if ( nonce ) { + ctx->offset = gen_offset_from_nonce( ctx, nonce ); + ctx->ad_offset = ctx->checksum = zero_block(); + ctx->ad_blocks_processed = ctx->blocks_processed = 0; + if ( ad_len >= 0 ) + ctx->ad_checksum = zero_block(); + } + + /* Process associated data */ + if ( ad_len > 0 ) + process_ad( ctx, ad, ad_len, final ); + + /* Encrypt plaintext data BPI blocks at a time */ + offset = ctx->offset; + checksum = ctx->checksum; + i = ct_len / ( BPI * 16 ); + if ( i ) { + block oa[BPI]; + unsigned block_num = ctx->blocks_processed; + oa[BPI - 1] = offset; + do { + block ta[BPI]; + block_num += BPI; + oa[0] = xor_block( oa[BPI - 1], ctx->L[0] ); + ta[0] = xor_block( oa[0], ctp[0] ); + oa[1] = xor_block( oa[0], ctx->L[1] ); + ta[1] = xor_block( oa[1], ctp[1] ); + oa[2] = xor_block( oa[1], ctx->L[0] ); + ta[2] = xor_block( oa[2], ctp[2] ); +#if BPI == 4 + oa[3] = xor_block( oa[2], getL( ctx, ntz( block_num ) ) ); + ta[3] = xor_block( oa[3], ctp[3] ); +#elif BPI == 8 + oa[3] = xor_block( oa[2], ctx->L[2] ); + ta[3] = xor_block( oa[3], ctp[3] ); + oa[4] = xor_block( oa[1], ctx->L[2] ); + ta[4] = xor_block( oa[4], ctp[4] ); + oa[5] = xor_block( oa[0], ctx->L[2] ); + ta[5] = xor_block( oa[5], ctp[5] ); + oa[6] = xor_block( oa[7], ctx->L[2] ); + ta[6] = xor_block( oa[6], ctp[6] ); + oa[7] = xor_block( oa[6], getL( ctx, ntz( block_num ) ) ); + ta[7] = xor_block( oa[7], ctp[7] ); +#endif + ocb_aes::ecb_decrypt_blks( ta, BPI, ctx->decrypt_key ); + ptp[0] = xor_block( ta[0], oa[0] ); + checksum = xor_block( checksum, ptp[0] ); + ptp[1] = xor_block( ta[1], oa[1] ); + checksum = xor_block( checksum, ptp[1] ); + ptp[2] = xor_block( ta[2], oa[2] ); + checksum = xor_block( checksum, ptp[2] ); + ptp[3] = xor_block( ta[3], oa[3] ); + checksum = xor_block( checksum, ptp[3] ); +#if ( BPI == 8 ) + ptp[4] = xor_block( ta[4], oa[4] ); + checksum = xor_block( checksum, ptp[4] ); + ptp[5] = xor_block( ta[5], oa[5] ); + checksum = xor_block( checksum, ptp[5] ); + ptp[6] = xor_block( ta[6], oa[6] ); + checksum = xor_block( checksum, ptp[6] ); + ptp[7] = xor_block( ta[7], oa[7] ); + checksum = xor_block( checksum, ptp[7] ); +#endif + ptp += BPI; + ctp += BPI; + } while ( --i ); + ctx->offset = offset = oa[BPI - 1]; + ctx->blocks_processed = block_num; + ctx->checksum = checksum; + } + + if ( final ) { + block ta[BPI + 1], oa[BPI]; + + /* Process remaining plaintext and compute its tag contribution */ + unsigned remaining = ( (unsigned)ct_len ) % ( BPI * 16 ); + k = 0; /* How many blocks in ta[] need ECBing */ + if ( remaining ) { +#if ( BPI == 8 ) + if ( remaining >= 64 ) { + oa[0] = xor_block( offset, ctx->L[0] ); + ta[0] = xor_block( oa[0], ctp[0] ); + oa[1] = xor_block( oa[0], ctx->L[1] ); + ta[1] = xor_block( oa[1], ctp[1] ); + oa[2] = xor_block( oa[1], ctx->L[0] ); + ta[2] = xor_block( oa[2], ctp[2] ); + offset = oa[3] = xor_block( oa[2], ctx->L[2] ); + ta[3] = xor_block( offset, ctp[3] ); + remaining -= 64; + k = 4; + } +#endif + if ( remaining >= 32 ) { + oa[k] = xor_block( offset, ctx->L[0] ); + ta[k] = xor_block( oa[k], ctp[k] ); + offset = oa[k + 1] = xor_block( oa[k], ctx->L[1] ); + ta[k + 1] = xor_block( offset, ctp[k + 1] ); + remaining -= 32; + k += 2; + } + if ( remaining >= 16 ) { + offset = oa[k] = xor_block( offset, ctx->L[0] ); + ta[k] = xor_block( offset, ctp[k] ); + remaining -= 16; + ++k; + } + if ( remaining ) { + block pad; + offset = xor_block( offset, ctx->Lstar ); + ocb_aes::encrypt( reinterpret_cast( &offset ), tmp.u8, ctx->encrypt_key ); + pad = tmp.bl; + memcpy( tmp.u8, ctp + k, remaining ); + tmp.bl = xor_block( tmp.bl, pad ); + tmp.u8[remaining] = (unsigned char)0x80u; + memcpy( ptp + k, tmp.u8, remaining ); + checksum = xor_block( checksum, tmp.bl ); + } + } + ocb_aes::ecb_decrypt_blks( ta, k, ctx->decrypt_key ); + switch ( k ) { +#if ( BPI == 8 ) + case 7: + ptp[6] = xor_block( ta[6], oa[6] ); + checksum = xor_block( checksum, ptp[6] ); + /* fallthrough */ + case 6: + ptp[5] = xor_block( ta[5], oa[5] ); + checksum = xor_block( checksum, ptp[5] ); + /* fallthrough */ + case 5: + ptp[4] = xor_block( ta[4], oa[4] ); + checksum = xor_block( checksum, ptp[4] ); + /* fallthrough */ + case 4: + ptp[3] = xor_block( ta[3], oa[3] ); + checksum = xor_block( checksum, ptp[3] ); + /* fallthrough */ +#endif + case 3: + ptp[2] = xor_block( ta[2], oa[2] ); + checksum = xor_block( checksum, ptp[2] ); + /* fallthrough */ + case 2: + ptp[1] = xor_block( ta[1], oa[1] ); + checksum = xor_block( checksum, ptp[1] ); + /* fallthrough */ + case 1: + ptp[0] = xor_block( ta[0], oa[0] ); + checksum = xor_block( checksum, ptp[0] ); } - if (final) { - block ta[BPI+1], oa[BPI]; - - /* Process remaining plaintext and compute its tag contribution */ - unsigned remaining = ((unsigned)ct_len) % (BPI*16); - k = 0; /* How many blocks in ta[] need ECBing */ - if (remaining) { - #if (BPI == 8) - if (remaining >= 64) { - oa[0] = xor_block(offset, ctx->L[0]); - ta[0] = xor_block(oa[0], ctp[0]); - oa[1] = xor_block(oa[0], ctx->L[1]); - ta[1] = xor_block(oa[1], ctp[1]); - oa[2] = xor_block(oa[1], ctx->L[0]); - ta[2] = xor_block(oa[2], ctp[2]); - offset = oa[3] = xor_block(oa[2], ctx->L[2]); - ta[3] = xor_block(offset, ctp[3]); - remaining -= 64; - k = 4; - } - #endif - if (remaining >= 32) { - oa[k] = xor_block(offset, ctx->L[0]); - ta[k] = xor_block(oa[k], ctp[k]); - offset = oa[k+1] = xor_block(oa[k], ctx->L[1]); - ta[k+1] = xor_block(offset, ctp[k+1]); - remaining -= 32; - k+=2; - } - if (remaining >= 16) { - offset = oa[k] = xor_block(offset, ctx->L[0]); - ta[k] = xor_block(offset, ctp[k]); - remaining -= 16; - ++k; - } - if (remaining) { - block pad; - offset = xor_block(offset,ctx->Lstar); - ocb_aes::encrypt(reinterpret_cast(&offset), tmp.u8, ctx->encrypt_key); - pad = tmp.bl; - memcpy(tmp.u8,ctp+k,remaining); - tmp.bl = xor_block(tmp.bl, pad); - tmp.u8[remaining] = (unsigned char)0x80u; - memcpy(ptp+k, tmp.u8, remaining); - checksum = xor_block(checksum, tmp.bl); - } - } - ocb_aes::ecb_decrypt_blks(ta,k,ctx->decrypt_key); - switch (k) { - #if (BPI == 8) - case 7: ptp[6] = xor_block(ta[6], oa[6]); - checksum = xor_block(checksum, ptp[6]); - /* fallthrough */ - case 6: ptp[5] = xor_block(ta[5], oa[5]); - checksum = xor_block(checksum, ptp[5]); - /* fallthrough */ - case 5: ptp[4] = xor_block(ta[4], oa[4]); - checksum = xor_block(checksum, ptp[4]); - /* fallthrough */ - case 4: ptp[3] = xor_block(ta[3], oa[3]); - checksum = xor_block(checksum, ptp[3]); - /* fallthrough */ - #endif - case 3: ptp[2] = xor_block(ta[2], oa[2]); - checksum = xor_block(checksum, ptp[2]); - /* fallthrough */ - case 2: ptp[1] = xor_block(ta[1], oa[1]); - checksum = xor_block(checksum, ptp[1]); - /* fallthrough */ - case 1: ptp[0] = xor_block(ta[0], oa[0]); - checksum = xor_block(checksum, ptp[0]); - } - - /* Calculate expected tag */ - offset = xor_block(offset, ctx->Ldollar); - tmp.bl = xor_block(offset, checksum); - ocb_aes::encrypt(tmp.u8, tmp.u8, ctx->encrypt_key); - tmp.bl = xor_block(tmp.bl, ctx->ad_checksum); /* Full tag */ - - /* Compare with proposed tag, change ct_len if invalid */ - if ((OCB_TAG_LEN == 16) && tag) { - if (unequal_blocks(tmp.bl, *(block *)tag)) - ct_len = AE_INVALID; - } else { - #if (OCB_TAG_LEN > 0) - int len = OCB_TAG_LEN; - #else - int len = ctx->tag_len; - #endif - if (tag) { - if (constant_time_memcmp(tag,tmp.u8,len) != 0) - ct_len = AE_INVALID; - } else { - if (constant_time_memcmp((char *)ct + ct_len,tmp.u8,len) != 0) - ct_len = AE_INVALID; - } - } + /* Calculate expected tag */ + offset = xor_block( offset, ctx->Ldollar ); + tmp.bl = xor_block( offset, checksum ); + ocb_aes::encrypt( tmp.u8, tmp.u8, ctx->encrypt_key ); + tmp.bl = xor_block( tmp.bl, ctx->ad_checksum ); /* Full tag */ + + /* Compare with proposed tag, change ct_len if invalid */ + if ( ( OCB_TAG_LEN == 16 ) && tag ) { + if ( unequal_blocks( tmp.bl, *(block*)tag ) ) + ct_len = AE_INVALID; + } else { +#if ( OCB_TAG_LEN > 0 ) + int len = OCB_TAG_LEN; +#else + int len = ctx->tag_len; +#endif + if ( tag ) { + if ( constant_time_memcmp( tag, tmp.u8, len ) != 0 ) + ct_len = AE_INVALID; + } else { + if ( constant_time_memcmp( (char*)ct + ct_len, tmp.u8, len ) != 0 ) + ct_len = AE_INVALID; + } } - return ct_len; - } + } + return ct_len; +} /* ----------------------------------------------------------------------- */ /* Simple test program */ /* ----------------------------------------------------------------------- */ -#if defined(OCB_TEST_PROGRAM) +#if defined( OCB_TEST_PROGRAM ) #include #include #if __GNUC__ - #define ALIGN(n) __attribute__ ((aligned(n))) +#define ALIGN( n ) __attribute__( ( aligned( n ) ) ) #elif _MSC_VER - #define ALIGN(n) __declspec(align(n)) +#define ALIGN( n ) __declspec( align( n ) ) #else /* Not GNU/Microsoft: delete alignment uses. */ - #define ALIGN(n) +#define ALIGN( n ) #endif -static void pbuf(void *p, unsigned len, const void *s) +static void pbuf( void* p, unsigned len, const void* s ) { - unsigned i; - if (s) - printf("%s", (char *)s); - for (i = 0; i < len; i++) - printf("%02X", (unsigned)(((unsigned char *)p)[i])); - printf("\n"); + unsigned i; + if ( s ) + printf( "%s", (char*)s ); + for ( i = 0; i < len; i++ ) + printf( "%02X", (unsigned)( ( (unsigned char*)p )[i] ) ); + printf( "\n" ); } -static void vectors(ae_ctx *ctx, int len) +static void vectors( ae_ctx* ctx, int len ) { - ALIGN(16) uint8_t pt[128]; - ALIGN(16) uint8_t ct[144]; - ALIGN(16) uint8_t nonce[] = {0,1,2,3,4,5,6,7,8,9,10,11}; - int i; - for (i=0; i < 128; i++) pt[i] = i; - i = ae_encrypt(ctx,nonce,pt,len,pt,len,ct,NULL,AE_FINALIZE); - printf("P=%d,A=%d: ",len,len); pbuf(ct, i, NULL); - i = ae_encrypt(ctx,nonce,pt,0,pt,len,ct,NULL,AE_FINALIZE); - printf("P=%d,A=%d: ",0,len); pbuf(ct, i, NULL); - i = ae_encrypt(ctx,nonce,pt,len,pt,0,ct,NULL,AE_FINALIZE); - printf("P=%d,A=%d: ",len,0); pbuf(ct, i, NULL); + ALIGN( 16 ) uint8_t pt[128]; + ALIGN( 16 ) uint8_t ct[144]; + ALIGN( 16 ) uint8_t nonce[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; + int i; + for ( i = 0; i < 128; i++ ) + pt[i] = i; + i = ae_encrypt( ctx, nonce, pt, len, pt, len, ct, NULL, AE_FINALIZE ); + printf( "P=%d,A=%d: ", len, len ); + pbuf( ct, i, NULL ); + i = ae_encrypt( ctx, nonce, pt, 0, pt, len, ct, NULL, AE_FINALIZE ); + printf( "P=%d,A=%d: ", 0, len ); + pbuf( ct, i, NULL ); + i = ae_encrypt( ctx, nonce, pt, len, pt, 0, ct, NULL, AE_FINALIZE ); + printf( "P=%d,A=%d: ", len, 0 ); + pbuf( ct, i, NULL ); } static void validate() { - ALIGN(16) uint8_t pt[1024]; - ALIGN(16) uint8_t ct[1024]; - ALIGN(16) uint8_t tag[16]; - ALIGN(16) uint8_t nonce[12] = {0,}; - ALIGN(16) uint8_t key[32] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; - ALIGN(16) uint8_t valid[] = {0xB2,0xB4,0x1C,0xBF,0x9B,0x05,0x03,0x7D, - 0xA7,0xF1,0x6C,0x24,0xA3,0x5C,0x1C,0x94}; - ae_ctx ctx; - uint8_t *val_buf, *next; - int i, len; - - val_buf = (uint8_t *)malloc(22400 + 16); - next = val_buf = (uint8_t *)(((size_t)val_buf + 16) & ~((size_t)15)); - - if (0) { - ae_init(&ctx, key, 16, 12, 16); - /* pbuf(&ctx, sizeof(ctx), "CTX: "); */ - vectors(&ctx,0); - vectors(&ctx,8); - vectors(&ctx,16); - vectors(&ctx,24); - vectors(&ctx,32); - vectors(&ctx,40); + ALIGN( 16 ) uint8_t pt[1024]; + ALIGN( 16 ) uint8_t ct[1024]; + ALIGN( 16 ) uint8_t tag[16]; + ALIGN( 16 ) + uint8_t nonce[12] = { + 0, + }; + ALIGN( 16 ) uint8_t key[32] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; + ALIGN( 16 ) + uint8_t valid[] + = { 0xB2, 0xB4, 0x1C, 0xBF, 0x9B, 0x05, 0x03, 0x7D, 0xA7, 0xF1, 0x6C, 0x24, 0xA3, 0x5C, 0x1C, 0x94 }; + ae_ctx ctx; + uint8_t *val_buf, *next; + int i, len; + + val_buf = (uint8_t*)malloc( 22400 + 16 ); + next = val_buf = (uint8_t*)( ( (size_t)val_buf + 16 ) & ~( (size_t)15 ) ); + + if ( 0 ) { + ae_init( &ctx, key, 16, 12, 16 ); + /* pbuf(&ctx, sizeof(ctx), "CTX: "); */ + vectors( &ctx, 0 ); + vectors( &ctx, 8 ); + vectors( &ctx, 16 ); + vectors( &ctx, 24 ); + vectors( &ctx, 32 ); + vectors( &ctx, 40 ); + } + + memset( key, 0, 32 ); + memset( pt, 0, 128 ); + ae_init( &ctx, key, 16, 12, 16 ); + + /* RFC Vector test */ + for ( i = 0; i < 128; i++ ) { + int first = ( ( i / 3 ) / ( BPI * 16 ) ) * ( BPI * 16 ); + int second = first; + int third = i - ( first + second ); + + nonce[11] = i; + + if ( 0 ) { + ae_encrypt( &ctx, nonce, pt, i, pt, i, ct, NULL, AE_FINALIZE ); + memcpy( next, ct, (size_t)i + 16 ); + next = next + i + 16; + + ae_encrypt( &ctx, nonce, pt, i, pt, 0, ct, NULL, AE_FINALIZE ); + memcpy( next, ct, (size_t)i + 16 ); + next = next + i + 16; + + ae_encrypt( &ctx, nonce, pt, 0, pt, i, ct, NULL, AE_FINALIZE ); + memcpy( next, ct, 16 ); + next = next + 16; + } else { + ae_encrypt( &ctx, nonce, pt, first, pt, first, ct, NULL, AE_PENDING ); + ae_encrypt( &ctx, NULL, pt + first, second, pt + first, second, ct + first, NULL, AE_PENDING ); + ae_encrypt( &ctx, + NULL, + pt + first + second, + third, + pt + first + second, + third, + ct + first + second, + NULL, + AE_FINALIZE ); + memcpy( next, ct, (size_t)i + 16 ); + next = next + i + 16; + + ae_encrypt( &ctx, nonce, pt, first, pt, 0, ct, NULL, AE_PENDING ); + ae_encrypt( &ctx, NULL, pt + first, second, pt, 0, ct + first, NULL, AE_PENDING ); + ae_encrypt( &ctx, NULL, pt + first + second, third, pt, 0, ct + first + second, NULL, AE_FINALIZE ); + memcpy( next, ct, (size_t)i + 16 ); + next = next + i + 16; + + ae_encrypt( &ctx, nonce, pt, 0, pt, first, ct, NULL, AE_PENDING ); + ae_encrypt( &ctx, NULL, pt, 0, pt + first, second, ct, NULL, AE_PENDING ); + ae_encrypt( &ctx, NULL, pt, 0, pt + first + second, third, ct, NULL, AE_FINALIZE ); + memcpy( next, ct, 16 ); + next = next + 16; } - - memset(key,0,32); - memset(pt,0,128); - ae_init(&ctx, key, 16, 12, 16); - - /* RFC Vector test */ - for (i = 0; i < 128; i++) { - int first = ((i/3)/(BPI*16))*(BPI*16); - int second = first; - int third = i - (first + second); - - nonce[11] = i; - - if (0) { - ae_encrypt(&ctx,nonce,pt,i,pt,i,ct,NULL,AE_FINALIZE); - memcpy(next,ct,(size_t)i+16); - next = next+i+16; - - ae_encrypt(&ctx,nonce,pt,i,pt,0,ct,NULL,AE_FINALIZE); - memcpy(next,ct,(size_t)i+16); - next = next+i+16; - - ae_encrypt(&ctx,nonce,pt,0,pt,i,ct,NULL,AE_FINALIZE); - memcpy(next,ct,16); - next = next+16; - } else { - ae_encrypt(&ctx,nonce,pt,first,pt,first,ct,NULL,AE_PENDING); - ae_encrypt(&ctx,NULL,pt+first,second,pt+first,second,ct+first,NULL,AE_PENDING); - ae_encrypt(&ctx,NULL,pt+first+second,third,pt+first+second,third,ct+first+second,NULL,AE_FINALIZE); - memcpy(next,ct,(size_t)i+16); - next = next+i+16; - - ae_encrypt(&ctx,nonce,pt,first,pt,0,ct,NULL,AE_PENDING); - ae_encrypt(&ctx,NULL,pt+first,second,pt,0,ct+first,NULL,AE_PENDING); - ae_encrypt(&ctx,NULL,pt+first+second,third,pt,0,ct+first+second,NULL,AE_FINALIZE); - memcpy(next,ct,(size_t)i+16); - next = next+i+16; - - ae_encrypt(&ctx,nonce,pt,0,pt,first,ct,NULL,AE_PENDING); - ae_encrypt(&ctx,NULL,pt,0,pt+first,second,ct,NULL,AE_PENDING); - ae_encrypt(&ctx,NULL,pt,0,pt+first+second,third,ct,NULL,AE_FINALIZE); - memcpy(next,ct,16); - next = next+16; - } - - } - nonce[11] = 0; - ae_encrypt(&ctx,nonce,NULL,0,val_buf,next-val_buf,ct,tag,AE_FINALIZE); - pbuf(tag,16,0); - if (memcmp(valid,tag,16) == 0) - printf("Vectors: PASS\n"); - else - printf("Vectors: FAIL\n"); - - - /* Encrypt/Decrypt test */ - for (i = 0; i < 128; i++) { - int first = ((i/3)/(BPI*16))*(BPI*16); - int second = first; - int third = i - (first + second); - - nonce[11] = i%128; - - if (1) { - len = ae_encrypt(&ctx,nonce,val_buf,i,val_buf,i,ct,tag,AE_FINALIZE); - len = ae_encrypt(&ctx,nonce,val_buf,i,val_buf,-1,ct,tag,AE_FINALIZE); - len = ae_decrypt(&ctx,nonce,ct,len,val_buf,-1,pt,tag,AE_FINALIZE); - if (len == -1) { printf("Authentication error: %d\n", i); return; } - if (len != i) { printf("Length error: %d\n", i); return; } - if (memcmp(val_buf,pt,i)) { printf("Decrypt error: %d\n", i); return; } - } else { - len = ae_encrypt(&ctx,nonce,val_buf,i,val_buf,i,ct,NULL,AE_FINALIZE); - ae_decrypt(&ctx,nonce,ct,first,val_buf,first,pt,NULL,AE_PENDING); - ae_decrypt(&ctx,NULL,ct+first,second,val_buf+first,second,pt+first,NULL,AE_PENDING); - len = ae_decrypt(&ctx,NULL,ct+first+second,len-(first+second),val_buf+first+second,third,pt+first+second,NULL,AE_FINALIZE); - if (len == -1) { printf("Authentication error: %d\n", i); return; } - if (memcmp(val_buf,pt,i)) { printf("Decrypt error: %d\n", i); return; } - } - + } + nonce[11] = 0; + ae_encrypt( &ctx, nonce, NULL, 0, val_buf, next - val_buf, ct, tag, AE_FINALIZE ); + pbuf( tag, 16, 0 ); + if ( memcmp( valid, tag, 16 ) == 0 ) + printf( "Vectors: PASS\n" ); + else + printf( "Vectors: FAIL\n" ); + + /* Encrypt/Decrypt test */ + for ( i = 0; i < 128; i++ ) { + int first = ( ( i / 3 ) / ( BPI * 16 ) ) * ( BPI * 16 ); + int second = first; + int third = i - ( first + second ); + + nonce[11] = i % 128; + + if ( 1 ) { + len = ae_encrypt( &ctx, nonce, val_buf, i, val_buf, i, ct, tag, AE_FINALIZE ); + len = ae_encrypt( &ctx, nonce, val_buf, i, val_buf, -1, ct, tag, AE_FINALIZE ); + len = ae_decrypt( &ctx, nonce, ct, len, val_buf, -1, pt, tag, AE_FINALIZE ); + if ( len == -1 ) { + printf( "Authentication error: %d\n", i ); + return; + } + if ( len != i ) { + printf( "Length error: %d\n", i ); + return; + } + if ( memcmp( val_buf, pt, i ) ) { + printf( "Decrypt error: %d\n", i ); + return; + } + } else { + len = ae_encrypt( &ctx, nonce, val_buf, i, val_buf, i, ct, NULL, AE_FINALIZE ); + ae_decrypt( &ctx, nonce, ct, first, val_buf, first, pt, NULL, AE_PENDING ); + ae_decrypt( &ctx, NULL, ct + first, second, val_buf + first, second, pt + first, NULL, AE_PENDING ); + len = ae_decrypt( &ctx, + NULL, + ct + first + second, + len - ( first + second ), + val_buf + first + second, + third, + pt + first + second, + NULL, + AE_FINALIZE ); + if ( len == -1 ) { + printf( "Authentication error: %d\n", i ); + return; + } + if ( memcmp( val_buf, pt, i ) ) { + printf( "Decrypt error: %d\n", i ); + return; + } } - printf("Decrypt: PASS\n"); + } + printf( "Decrypt: PASS\n" ); } int main() { - validate(); - return 0; + validate(); + return 0; } #endif diff --git a/src/crypto/ocb_openssl.cc b/src/crypto/ocb_openssl.cc index 81cd1b9ee..14d08c57c 100644 --- a/src/crypto/ocb_openssl.cc +++ b/src/crypto/ocb_openssl.cc @@ -1,49 +1,60 @@ #include "ae.h" #include "config.h" +#include #include #include -#include -struct _ae_ctx { - EVP_CIPHER_CTX *enc_ctx; - EVP_CIPHER_CTX *dec_ctx; +struct _ae_ctx +{ + EVP_CIPHER_CTX* enc_ctx; + EVP_CIPHER_CTX* dec_ctx; int tag_len; }; -int ae_clear( ae_ctx *ctx ) { +int ae_clear( ae_ctx* ctx ) +{ EVP_CIPHER_CTX_free( ctx->enc_ctx ); EVP_CIPHER_CTX_free( ctx->dec_ctx ); OPENSSL_cleanse( ctx, sizeof( *ctx ) ); return AE_SUCCESS; } -int ae_ctx_sizeof() { return sizeof( _ae_ctx ); } +int ae_ctx_sizeof() +{ + return sizeof( _ae_ctx ); +} // If direction is 1, initializes encryption. If 0, initializes // decryption. See the documentation of EVP_CipherInit_ex -static int ae_evp_cipher_init( EVP_CIPHER_CTX **in_ctx, int direction, - const unsigned char *key, int nonce_len, - int tag_len ) { +static int ae_evp_cipher_init( EVP_CIPHER_CTX** in_ctx, + int direction, + const unsigned char* key, + int nonce_len, + int tag_len ) +{ // Create an OpenSSL EVP context. It does not yet have any specific // cipher associated with it. if ( !( *in_ctx = EVP_CIPHER_CTX_new() ) ) { return -3; } - EVP_CIPHER_CTX *ctx = *in_ctx; + EVP_CIPHER_CTX* ctx = *in_ctx; // Although OCB-AES has the same initialization process between // encryption and decryption, an EVP_CIPHER_CTX must be initialized // for a specific direction. - if ( EVP_CipherInit_ex( ctx, EVP_aes_128_ocb(), - /*impl=*/NULL, /*key=*/key, /*iv=*/NULL, direction ) + if ( EVP_CipherInit_ex( ctx, + EVP_aes_128_ocb(), + /*impl=*/NULL, + /*key=*/key, + /*iv=*/NULL, + direction ) != 1 ) { return -3; } // Attempt to set the nonce length. If it fails, the length must not // be supported. However, that should have been handled by the // pre-condition check above. - if ( EVP_CIPHER_CTX_ctrl( ctx, EVP_CTRL_AEAD_SET_IVLEN, nonce_len, NULL ) - != 1 ) { + if ( EVP_CIPHER_CTX_ctrl( ctx, EVP_CTRL_AEAD_SET_IVLEN, nonce_len, NULL ) != 1 ) { return -3; } // A NULL tag length means that EVP_CTRL_AEAD_SET_TAG is only being @@ -54,8 +65,8 @@ static int ae_evp_cipher_init( EVP_CIPHER_CTX **in_ctx, int direction, return AE_SUCCESS; } -int ae_init( ae_ctx *ctx, const void *key, int key_len, int nonce_len, - int tag_len ) { +int ae_init( ae_ctx* ctx, const void* key, int key_len, int nonce_len, int tag_len ) +{ // Pre-condition: Only nonces of length 12 are supported. The // documentation of `ae_init` in ae.h specifies that `ctx` is // untouched if an invalid configuration is requested. Delegating @@ -69,15 +80,13 @@ int ae_init( ae_ctx *ctx, const void *key, int key_len, int nonce_len, return AE_NOT_SUPPORTED; } int r = AE_SUCCESS; - if ( ( r = ae_evp_cipher_init( &ctx->enc_ctx, 1, - reinterpret_cast( key ), - nonce_len, tag_len ) ) + if ( ( r = ae_evp_cipher_init( + &ctx->enc_ctx, 1, reinterpret_cast( key ), nonce_len, tag_len ) ) != AE_SUCCESS ) { return r; } - if ( ( r = ae_evp_cipher_init( &ctx->dec_ctx, 0, - reinterpret_cast( key ), - nonce_len, tag_len ) ) + if ( ( r = ae_evp_cipher_init( + &ctx->dec_ctx, 0, reinterpret_cast( key ), nonce_len, tag_len ) ) != AE_SUCCESS ) { return r; } @@ -85,14 +94,20 @@ int ae_init( ae_ctx *ctx, const void *key, int key_len, int nonce_len, return AE_SUCCESS; } -int ae_encrypt( ae_ctx *ctx, const void *nonce_ptr, const void *pt_ptr, - int pt_len, const void *ad_ptr, int ad_len, void *ct_ptr, - void *tag, int final ) { - const unsigned char *nonce = - reinterpret_cast( nonce_ptr ); - const unsigned char *pt = reinterpret_cast( pt_ptr ); - const unsigned char *ad = reinterpret_cast( ad_ptr ); - unsigned char *ct = reinterpret_cast( ct_ptr ); +int ae_encrypt( ae_ctx* ctx, + const void* nonce_ptr, + const void* pt_ptr, + int pt_len, + const void* ad_ptr, + int ad_len, + void* ct_ptr, + void* tag, + int final ) +{ + const unsigned char* nonce = reinterpret_cast( nonce_ptr ); + const unsigned char* pt = reinterpret_cast( pt_ptr ); + const unsigned char* ad = reinterpret_cast( ad_ptr ); + unsigned char* ct = reinterpret_cast( ct_ptr ); // Streaming mode is not supported; nonce must always be provided. if ( final != AE_FINALIZE ) { return AE_NOT_SUPPORTED; @@ -100,20 +115,20 @@ int ae_encrypt( ae_ctx *ctx, const void *nonce_ptr, const void *pt_ptr, if ( nonce == NULL ) { return AE_NOT_SUPPORTED; } - if ( EVP_EncryptInit_ex( ctx->enc_ctx, /*type=*/NULL, /*impl=*/NULL, - /*key=*/NULL, nonce ) + if ( EVP_EncryptInit_ex( ctx->enc_ctx, + /*type=*/NULL, + /*impl=*/NULL, + /*key=*/NULL, + nonce ) != 1 ) { return -3; } int len = 0; - if ( ad != NULL && ad_len > 0 - && EVP_EncryptUpdate( ctx->enc_ctx, /*out=*/NULL, &len, ad, ad_len ) - != 1 ) { + if ( ad != NULL && ad_len > 0 && EVP_EncryptUpdate( ctx->enc_ctx, /*out=*/NULL, &len, ad, ad_len ) != 1 ) { return -3; } len = 0; - if ( pt != NULL && pt_len > 0 - && EVP_EncryptUpdate( ctx->enc_ctx, ct, &len, pt, pt_len ) != 1 ) { + if ( pt != NULL && pt_len > 0 && EVP_EncryptUpdate( ctx->enc_ctx, ct, &len, pt, pt_len ) != 1 ) { return -3; } int ciphertext_len = len; @@ -123,10 +138,8 @@ int ae_encrypt( ae_ctx *ctx, const void *nonce_ptr, const void *pt_ptr, ciphertext_len += len; // If `tag` is provided, the authentication tag goes // there. Otherwise, it is appended after the ciphertext. - void *tag_location = tag != NULL ? tag : ct + ciphertext_len; - if ( EVP_CIPHER_CTX_ctrl( ctx->enc_ctx, EVP_CTRL_AEAD_GET_TAG, ctx->tag_len, - tag_location ) - != 1 ) { + void* tag_location = tag != NULL ? tag : ct + ciphertext_len; + if ( EVP_CIPHER_CTX_ctrl( ctx->enc_ctx, EVP_CTRL_AEAD_GET_TAG, ctx->tag_len, tag_location ) != 1 ) { return -3; } if ( tag == NULL ) { @@ -135,14 +148,20 @@ int ae_encrypt( ae_ctx *ctx, const void *nonce_ptr, const void *pt_ptr, return ciphertext_len; } -int ae_decrypt( ae_ctx *ctx, const void *nonce_ptr, const void *ct_ptr, - int ct_len, const void *ad_ptr, int ad_len, void *pt_ptr, - const void *tag, int final ) { - const unsigned char *nonce = - reinterpret_cast( nonce_ptr ); - const unsigned char *ct = reinterpret_cast( ct_ptr ); - const unsigned char *ad = reinterpret_cast( ad_ptr ); - unsigned char *pt = reinterpret_cast( pt_ptr ); +int ae_decrypt( ae_ctx* ctx, + const void* nonce_ptr, + const void* ct_ptr, + int ct_len, + const void* ad_ptr, + int ad_len, + void* pt_ptr, + const void* tag, + int final ) +{ + const unsigned char* nonce = reinterpret_cast( nonce_ptr ); + const unsigned char* ct = reinterpret_cast( ct_ptr ); + const unsigned char* ad = reinterpret_cast( ad_ptr ); + unsigned char* pt = reinterpret_cast( pt_ptr ); if ( ct_len < ctx->tag_len ) { return AE_INVALID; } @@ -153,38 +172,35 @@ int ae_decrypt( ae_ctx *ctx, const void *nonce_ptr, const void *ct_ptr, if ( tag == NULL ) { ct_len -= ctx->tag_len; } - // Like encryption, nonce must always be provided and streaming is not - // supported. + // Like encryption, nonce must always be provided and streaming is not supported. if ( final != AE_FINALIZE ) { return AE_NOT_SUPPORTED; } if ( nonce == NULL ) { return AE_NOT_SUPPORTED; } - if ( EVP_DecryptInit_ex( ctx->dec_ctx, /*type=*/NULL, /*impl=*/NULL, - /*key=*/NULL, nonce ) + if ( EVP_DecryptInit_ex( ctx->dec_ctx, + /*type=*/NULL, + /*impl=*/NULL, + /*key=*/NULL, + nonce ) != 1 ) { return -3; } int len = 0; - if ( ad != NULL && ad_len > 0 - && EVP_DecryptUpdate( ctx->dec_ctx, /*out=*/NULL, &len, ad, ad_len ) - != 1 ) { + if ( ad != NULL && ad_len > 0 && EVP_DecryptUpdate( ctx->dec_ctx, /*out=*/NULL, &len, ad, ad_len ) != 1 ) { return -3; } len = 0; - if ( ct != NULL && ct_len > 0 - && EVP_DecryptUpdate( ctx->dec_ctx, pt, &len, ct, ct_len ) != 1 ) { + if ( ct != NULL && ct_len > 0 && EVP_DecryptUpdate( ctx->dec_ctx, pt, &len, ct, ct_len ) != 1 ) { return -3; } int plaintext_len = len; // If `tag` is provided, the authentication is read from // there. Otherwise, it's the last bytes of the ciphertext. (This is // a convention, not a requirement of OCB mode). - const void *tag_location = tag != NULL ? tag : ct + ct_len; - if ( EVP_CIPHER_CTX_ctrl( ctx->dec_ctx, EVP_CTRL_AEAD_SET_TAG, ctx->tag_len, - (void *)tag_location ) - != 1 ) { + const void* tag_location = tag != NULL ? tag : ct + ct_len; + if ( EVP_CIPHER_CTX_ctrl( ctx->dec_ctx, EVP_CTRL_AEAD_SET_TAG, ctx->tag_len, (void*)tag_location ) != 1 ) { return -3; } if ( EVP_DecryptFinal_ex( ctx->dec_ctx, pt + plaintext_len, &len ) != 1 ) { diff --git a/src/crypto/prng.h b/src/crypto/prng.h index cb394552e..a3426c15f 100644 --- a/src/crypto/prng.h +++ b/src/crypto/prng.h @@ -33,8 +33,8 @@ #ifndef PRNG_HPP #define PRNG_HPP -#include #include +#include #include #include "crypto.h" @@ -47,41 +47,48 @@ static const char rdev[] = "/dev/urandom"; using namespace Crypto; -class PRNG { +class PRNG +{ private: std::ifstream randfile; /* unimplemented to satisfy -Weffc++ */ - PRNG( const PRNG & ); - PRNG &operator=( const PRNG & ); + PRNG( const PRNG& ); + PRNG& operator=( const PRNG& ); public: - PRNG() : randfile( rdev, std::ifstream::in | std::ifstream::binary ) {} + PRNG() + : randfile( rdev, std::ifstream::in | std::ifstream::binary ) + {} - void fill( void *dest, size_t size ) { + void fill( void* dest, size_t size ) + { if ( 0 == size ) { return; } - randfile.read( static_cast( dest ), size ); + randfile.read( static_cast( dest ), size ); if ( !randfile ) { throw CryptoException( "Could not read from " + std::string( rdev ) ); } } - uint8_t uint8() { + uint8_t uint8() + { uint8_t x; fill( &x, 1 ); return x; } - uint32_t uint32() { + uint32_t uint32() + { uint32_t x; fill( &x, 4 ); return x; } - uint64_t uint64() { + uint64_t uint64() + { uint64_t x; fill( &x, 8 ); return x; diff --git a/src/examples/benchmark.cc b/src/examples/benchmark.cc index a9bb6d601..8eae180d5 100644 --- a/src/examples/benchmark.cc +++ b/src/examples/benchmark.cc @@ -33,6 +33,7 @@ #include "config.h" #include +#include #include #include #include @@ -44,7 +45,6 @@ #include #include #include -#include #if HAVE_PTY_H #include @@ -63,30 +63,30 @@ const int ITERATIONS = 100000; using namespace Terminal; -int main( int argc, char **argv ) { +int main( int argc, char** argv ) +{ try { int fbmod = 0; int width = 80, height = 24; int iterations = ITERATIONS; if ( argc > 1 ) { - iterations = atoi( argv[ 1 ] ); + iterations = atoi( argv[1] ); if ( iterations < 1 || iterations > 1000000000 ) { fprintf( stderr, "bogus iteration count\n" ); exit( 1 ); } } if ( argc > 3 ) { - width = atoi( argv[ 2 ] ); - height = atoi( argv[ 3 ] ); + width = atoi( argv[2] ); + height = atoi( argv[3] ); if ( width < 1 || width > 1000 || height < 1 || height > 1000 ) { fprintf( stderr, "bogus window size\n" ); exit( 1 ); } } - Framebuffer local_framebuffers[ 2 ] = { Framebuffer( width, height ), - Framebuffer( width, height ) }; - Framebuffer *local_framebuffer = &( local_framebuffers[ fbmod ] ); - Framebuffer *new_state = &( local_framebuffers[ !fbmod ] ); + Framebuffer local_framebuffers[2] = { Framebuffer( width, height ), Framebuffer( width, height ) }; + Framebuffer* local_framebuffer = &( local_framebuffers[fbmod] ); + Framebuffer* new_state = &( local_framebuffers[!fbmod] ); Overlay::OverlayManager overlays; Display display( true ); Complete local_terminal( width, height ); @@ -97,8 +97,7 @@ int main( int argc, char **argv ) { for ( int i = 0; i < iterations; i++ ) { /* type a character */ - overlays.get_prediction_engine().new_user_byte( i + 'x', - *local_framebuffer ); + overlays.get_prediction_engine().new_user_byte( i + 'x', *local_framebuffer ); /* fetch target state */ *new_state = local_terminal.get_fb(); @@ -107,8 +106,7 @@ int main( int argc, char **argv ) { overlays.apply( *new_state ); /* calculate minimal difference from where we are */ - const string diff( - display.new_frame( false, *local_framebuffer, *new_state ) ); + const string diff( display.new_frame( false, *local_framebuffer, *new_state ) ); /* make sure to use diff */ if ( diff.size() > INT_MAX ) { @@ -116,10 +114,10 @@ int main( int argc, char **argv ) { } fbmod = !fbmod; - local_framebuffer = &( local_framebuffers[ fbmod ] ); - new_state = &( local_framebuffers[ !fbmod ] ); + local_framebuffer = &( local_framebuffers[fbmod] ); + new_state = &( local_framebuffers[!fbmod] ); } - } catch ( const std::exception &e ) { + } catch ( const std::exception& e ) { fprintf( stderr, "Exception caught: %s\n", e.what() ); return 1; } diff --git a/src/examples/decrypt.cc b/src/examples/decrypt.cc index a086a6c31..4a838d33e 100644 --- a/src/examples/decrypt.cc +++ b/src/examples/decrypt.cc @@ -30,22 +30,23 @@ also delete it here. */ -#include #include #include +#include #include "crypto.h" using namespace Crypto; -int main( int argc, char *argv[] ) { +int main( int argc, char* argv[] ) +{ if ( argc != 2 ) { - fprintf( stderr, "Usage: %s KEY\n", argv[ 0 ] ); + fprintf( stderr, "Usage: %s KEY\n", argv[0] ); return 1; } try { - Base64Key key( argv[ 1 ] ); + Base64Key key( argv[1] ); Session session( key ); /* Read input */ @@ -58,7 +59,7 @@ int main( int argc, char *argv[] ) { fprintf( stderr, "Nonce = %ld\n", (long)message.nonce.val() ); std::cout << message.text; - } catch ( const CryptoException &e ) { + } catch ( const CryptoException& e ) { std::cerr << e.what() << std::endl; exit( 1 ); } diff --git a/src/examples/encrypt.cc b/src/examples/encrypt.cc index fd8e31016..0be696d06 100644 --- a/src/examples/encrypt.cc +++ b/src/examples/encrypt.cc @@ -30,24 +30,25 @@ also delete it here. */ -#include #include #include +#include #include "crypto.h" using namespace Crypto; -int main( int argc, char *argv[] ) { +int main( int argc, char* argv[] ) +{ if ( argc != 2 ) { - fprintf( stderr, "Usage: %s NONCE\n", argv[ 0 ] ); + fprintf( stderr, "Usage: %s NONCE\n", argv[0] ); return 1; } try { Base64Key key; Session session( key ); - Nonce nonce( myatoi( argv[ 1 ] ) ); + Nonce nonce( myatoi( argv[1] ) ); /* Read input */ std::ostringstream input; @@ -60,7 +61,7 @@ int main( int argc, char *argv[] ) { std::cerr << "Key: " << key.printable_key() << std::endl; std::cout << ciphertext; - } catch ( const CryptoException &e ) { + } catch ( const CryptoException& e ) { std::cerr << e.what() << std::endl; exit( 1 ); } diff --git a/src/examples/ntester.cc b/src/examples/ntester.cc index 7925ab167..29d74da65 100644 --- a/src/examples/ntester.cc +++ b/src/examples/ntester.cc @@ -42,39 +42,38 @@ using namespace Network; -int main( int argc, char *argv[] ) { +int main( int argc, char* argv[] ) +{ bool server = true; - char *key; - char *ip; - char *port; + char* key; + char* ip; + char* port; UserStream me, remote; - typedef shared::shared_ptr > NetworkPointer; - Transport *raw_n; + typedef shared::shared_ptr> NetworkPointer; + Transport* raw_n; try { if ( argc > 1 ) { server = false; /* client */ - key = argv[ 1 ]; - ip = argv[ 2 ]; - port = argv[ 3 ]; + key = argv[1]; + ip = argv[2]; + port = argv[3]; - raw_n = - new Transport( me, remote, key, ip, port ); + raw_n = new Transport( me, remote, key, ip, port ); } else { raw_n = new Transport( me, remote, NULL, NULL ); } - } catch ( const std::exception &e ) { + } catch ( const std::exception& e ) { fprintf( stderr, "Fatal startup error: %s\n", e.what() ); exit( 1 ); } NetworkPointer n( raw_n ); - fprintf( stderr, "Port bound is %s, key is %s\n", n->port().c_str(), - n->get_key().c_str() ); + fprintf( stderr, "Port bound is %s, key is %s\n", n->port().c_str(), n->get_key().c_str() ); if ( server ) { - Select &sel = Select::get_instance(); + Select& sel = Select::get_instance(); uint64_t last_num = n->get_remote_state_num(); while ( true ) { try { @@ -94,13 +93,12 @@ int main( int argc, char *argv[] ) { 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() ); + 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 ( const std::exception &e ) { + } catch ( const std::exception& e ) { fprintf( stderr, "Server error: %s\n", e.what() ); } } @@ -122,15 +120,14 @@ int main( int argc, char *argv[] ) { exit( 1 ); } - Select &sel = Select::get_instance(); + Select& sel = Select::get_instance(); while ( true ) { sel.clear_fds(); sel.add_fd( STDIN_FILENO ); std::vector fd_list( n->fds() ); - for ( std::vector::const_iterator it = fd_list.begin(); - it != fd_list.end(); it++ ) { + for ( std::vector::const_iterator it = fd_list.begin(); it != fd_list.end(); it++ ) { sel.add_fd( *it ); } @@ -148,8 +145,7 @@ int main( int argc, char *argv[] ) { } bool network_ready_to_read = false; - for ( std::vector::const_iterator it = fd_list.begin(); - it != fd_list.end(); it++ ) { + for ( std::vector::const_iterator it = fd_list.begin(); it != fd_list.end(); it++ ) { if ( sel.read( *it ) ) { /* packet received from the network */ /* we only read one socket each run */ @@ -160,7 +156,7 @@ int main( int argc, char *argv[] ) { if ( network_ready_to_read ) { n->recv(); } - } catch ( const std::exception &e ) { + } catch ( const std::exception& e ) { fprintf( stderr, "Client error: %s\n", e.what() ); } } diff --git a/src/examples/parse.cc b/src/examples/parse.cc index 27d6afdab..d62576960 100644 --- a/src/examples/parse.cc +++ b/src/examples/parse.cc @@ -40,10 +40,10 @@ #include #include #include +#include #include #include #include -#include #if HAVE_PTY_H #include @@ -64,10 +64,10 @@ const size_t buf_size = 1024; static void emulate_terminal( int fd ); static int copy( int src, int dest ); -static int vt_parser( int fd, Parser::UTF8Parser *parser ); +static int vt_parser( int fd, Parser::UTF8Parser* parser ); -int main( int argc __attribute__( ( unused ) ), - char *argv[] __attribute__( ( unused ) ), char *envp[] ) { +int main( int argc __attribute__( ( unused ) ), char* argv[] __attribute__( ( unused ) ), char* envp[] ) +{ int master; struct termios saved_termios, raw_termios, child_termios; @@ -83,16 +83,13 @@ int main( int argc __attribute__( ( unused ) ), #ifdef HAVE_IUTF8 if ( !( child_termios.c_iflag & IUTF8 ) ) { - fprintf( stderr, - "Warning: Locale is UTF-8 but termios IUTF8 flag not set. Setting " - "IUTF8 flag.\n" ); + fprintf( stderr, "Warning: Locale is UTF-8 but termios IUTF8 flag not set. Setting IUTF8 flag.\n" ); child_termios.c_iflag |= IUTF8; } #else fprintf( stderr, - "Warning: termios IUTF8 flag not defined. Character-erase of " - "multibyte character sequence probably does not work properly on " - "this platform.\n" ); + "Warning: termios IUTF8 flag not defined. Character-erase of multibyte character sequence probably does " + "not work properly on this platform.\n" ); #endif /* HAVE_IUTF8 */ pid_t child = forkpty( &master, NULL, &child_termios, NULL ); @@ -104,11 +101,11 @@ int main( int argc __attribute__( ( unused ) ), if ( child == 0 ) { /* child */ - char *my_argv[ 2 ]; - my_argv[ 0 ] = strdup( "/bin/bash" ); - assert( my_argv[ 0 ] ); + char* my_argv[2]; + my_argv[0] = strdup( "/bin/bash" ); + assert( my_argv[0] ); - my_argv[ 1 ] = NULL; + my_argv[1] = NULL; if ( execve( "/bin/bash", my_argv, envp ) < 0 ) { perror( "execve" ); @@ -137,10 +134,11 @@ int main( int argc __attribute__( ( unused ) ), return 0; } -static void emulate_terminal( int fd ) { +static void emulate_terminal( int fd ) +{ Parser::UTF8Parser parser; - Select &sel = Select::get_instance(); + Select& sel = Select::get_instance(); sel.add_fd( STDIN_FILENO ); sel.add_fd( fd ); @@ -165,8 +163,9 @@ static void emulate_terminal( int fd ) { } } -static int copy( int src, int dest ) { - char buf[ buf_size ]; +static int copy( int src, int dest ) +{ + char buf[buf_size]; ssize_t bytes_read = read( src, buf, buf_size ); if ( bytes_read == 0 ) { /* EOF */ @@ -179,8 +178,9 @@ static int copy( int src, int dest ) { return swrite( dest, buf, bytes_read ); } -static int vt_parser( int fd, Parser::UTF8Parser *parser ) { - char buf[ buf_size ]; +static 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 ); @@ -194,17 +194,15 @@ static int vt_parser( int fd, Parser::UTF8Parser *parser ) { /* feed to parser */ Parser::Actions actions; for ( int i = 0; i < bytes_read; i++ ) { - parser->input( buf[ i ], actions ); - for ( Parser::Actions::iterator j = actions.begin(); j != actions.end(); - j++ ) { + parser->input( buf[i], actions ); + for ( Parser::Actions::iterator j = actions.begin(); j != actions.end(); j++ ) { assert( *j ); - Parser::Action &act = **j; + Parser::Action& act = **j; if ( act.char_present ) { if ( iswprint( act.ch ) ) { - printf( "%s(0x%02x=%lc) ", act.name().c_str(), (unsigned int)act.ch, - (wint_t)act.ch ); + printf( "%s(0x%02x=%lc) ", act.name().c_str(), (unsigned int)act.ch, (wint_t)act.ch ); } else { printf( "%s(0x%02x) ", act.name().c_str(), (unsigned int)act.ch ); } diff --git a/src/examples/termemu.cc b/src/examples/termemu.cc index 80a637957..4fffb4221 100644 --- a/src/examples/termemu.cc +++ b/src/examples/termemu.cc @@ -34,6 +34,7 @@ #include #include +#include #include #include #include @@ -46,11 +47,10 @@ #include #include #include +#include #include #include #include -#include -#include #if HAVE_PTY_H #include @@ -72,7 +72,8 @@ const size_t buf_size = 16384; static void emulate_terminal( int fd ); -int main( int argc, char *argv[] ) { +int main( int argc, char* argv[] ) +{ int master; struct termios saved_termios, raw_termios, child_termios; @@ -88,16 +89,13 @@ int main( int argc, char *argv[] ) { #ifdef HAVE_IUTF8 if ( !( child_termios.c_iflag & IUTF8 ) ) { - fprintf( stderr, - "Warning: Locale is UTF-8 but termios IUTF8 flag not set. Setting " - "IUTF8 flag.\n" ); + fprintf( stderr, "Warning: Locale is UTF-8 but termios IUTF8 flag not set. Setting IUTF8 flag.\n" ); child_termios.c_iflag |= IUTF8; } #else fprintf( stderr, - "Warning: termios IUTF8 flag not defined. Character-erase of " - "multibyte character sequence probably does not work properly on " - "this platform.\n" ); + "Warning: termios IUTF8 flag not defined. Character-erase of multibyte character sequence probably does " + "not work properly on this platform.\n" ); #endif /* HAVE_IUTF8 */ pid_t child = forkpty( &master, NULL, &child_termios, NULL ); @@ -120,26 +118,26 @@ int main( int argc, char *argv[] ) { exit( 1 ); } - char *my_argv[ 2 ]; + char* my_argv[2]; if ( argc > 1 ) { argv++; } else { /* get shell name */ - my_argv[ 0 ] = getenv( "SHELL" ); - if ( my_argv[ 0 ] == NULL || *my_argv[ 0 ] == '\0' ) { - struct passwd *pw = getpwuid( getuid() ); + my_argv[0] = getenv( "SHELL" ); + if ( my_argv[0] == NULL || *my_argv[0] == '\0' ) { + struct passwd* pw = getpwuid( getuid() ); if ( pw == NULL ) { perror( "getpwuid" ); exit( 1 ); } - my_argv[ 0 ] = strdup( pw->pw_shell ); + my_argv[0] = strdup( pw->pw_shell ); } - assert( my_argv[ 0 ] ); - my_argv[ 1 ] = NULL; + assert( my_argv[0] ); + my_argv[1] = NULL; argv = my_argv; } - if ( execvp( argv[ 0 ], argv ) < 0 ) { + if ( execvp( argv[0], argv ) < 0 ) { perror( "execve" ); exit( 1 ); } @@ -157,7 +155,7 @@ int main( int argc, char *argv[] ) { try { emulate_terminal( master ); - } catch ( const std::exception &e ) { + } catch ( const std::exception& e ) { fprintf( stderr, "\r\nException caught: %s\r\n", e.what() ); } @@ -173,9 +171,8 @@ int main( int argc, char *argv[] ) { } /* Print a frame if the last frame was more than 1/50 seconds ago */ -static bool tick( Terminal::Framebuffer &state, - Terminal::Framebuffer &new_frame, - const Terminal::Display &display ) { +static bool tick( Terminal::Framebuffer& state, Terminal::Framebuffer& new_frame, const Terminal::Display& display ) +{ static bool initialized = false; static struct timeval last_time; @@ -185,8 +182,7 @@ static bool tick( Terminal::Framebuffer &state, perror( "gettimeofday" ); } - double diff = ( this_time.tv_sec - last_time.tv_sec ) - + .000001 * ( this_time.tv_usec - last_time.tv_usec ); + 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 = display.new_frame( initialized, state, new_frame ); @@ -219,7 +215,8 @@ static bool tick( Terminal::Framebuffer &state, assume the previous frame was sent to the real terminal. */ -static void emulate_terminal( int fd ) { +static void emulate_terminal( int fd ) +{ /* get current window size */ struct winsize window_size; if ( ioctl( STDIN_FILENO, TIOCGWINSZ, &window_size ) < 0 ) { @@ -240,7 +237,7 @@ static void emulate_terminal( int fd ) { /* open display */ Terminal::Display display( true ); /* use TERM to initialize */ - Select &sel = Select::get_instance(); + Select& sel = Select::get_instance(); sel.add_fd( STDIN_FILENO ); sel.add_fd( fd ); sel.add_signal( SIGWINCH ); @@ -258,7 +255,7 @@ static void emulate_terminal( int fd ) { if ( sel.read( STDIN_FILENO ) ) { /* input from user */ - char buf[ buf_size ]; + char buf[buf_size]; /* fill buffer if possible */ ssize_t bytes_read = read( STDIN_FILENO, buf, buf_size ); @@ -272,16 +269,15 @@ static void emulate_terminal( int fd ) { std::string terminal_to_host; for ( int i = 0; i < bytes_read; i++ ) { - terminal_to_host += complete.act( Parser::UserByte( buf[ i ] ) ); + terminal_to_host += complete.act( Parser::UserByte( buf[i] ) ); } - if ( swrite( fd, terminal_to_host.c_str(), terminal_to_host.length() ) - < 0 ) { + if ( swrite( fd, terminal_to_host.c_str(), terminal_to_host.length() ) < 0 ) { break; } } else if ( sel.read( fd ) ) { /* input from host */ - char buf[ buf_size ]; + char buf[buf_size]; /* fill buffer if possible */ ssize_t bytes_read = read( fd, buf, buf_size ); @@ -292,10 +288,8 @@ static void emulate_terminal( int fd ) { 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 ) { + 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 ( sel.signal( SIGWINCH ) ) { diff --git a/src/frontend/mosh-client.cc b/src/frontend/mosh-client.cc index 4a73f18f4..f312b3c24 100644 --- a/src/frontend/mosh-client.cc +++ b/src/frontend/mosh-client.cc @@ -43,9 +43,9 @@ /* These need to be included last because of conflicting defines. */ /* - * stmclient.h includes termios.h, and that will break termio/termios pull in on - * Solaris. The solution is to include termio.h also. But Mac OS X doesn't have - * termio.h, so this needs a guard. + * stmclient.h includes termios.h, and that will break termio/termios pull in on Solaris. + * The solution is to include termio.h also. + * But Mac OS X doesn't have termio.h, so this needs a guard. */ #ifdef HAVE_TERMIO_H #include @@ -70,28 +70,30 @@ #error "SysV or X/Open-compatible Curses header file required" #endif -static void print_version( FILE *file ) { - fputs( "mosh-client (" PACKAGE_STRING ") [build " BUILD_VERSION - "]\n" +static void print_version( FILE* file ) +{ + fputs( "mosh-client (" PACKAGE_STRING ") [build " BUILD_VERSION "]\n" "Copyright 2012 Keith Winstein \n" - "License GPLv3+: GNU GPL version 3 or later " - ".\n" + "License GPLv3+: GNU GPL version 3 or later .\n" "This is free software: you are free to change and redistribute it.\n" "There is NO WARRANTY, to the extent permitted by law.\n", file ); } -static void print_usage( FILE *file, const char *argv0 ) { +static void print_usage( FILE* file, const char* argv0 ) +{ print_version( file ); fprintf( file, "\nUsage: %s [-# 'ARGS'] IP PORT\n" " %s -c\n", - argv0, argv0 ); + argv0, + argv0 ); } -static void print_colorcount( void ) { +static void print_colorcount( void ) +{ /* check colors */ - setupterm( (char *)0, 1, (int *)0 ); + setupterm( (char*)0, 1, (int*)0 ); char colors_name[] = "colors"; int color_val = tigetnum( colors_name ); @@ -103,9 +105,9 @@ static void print_colorcount( void ) { } #ifdef NACL -int mosh_main( int argc, char *argv[] ) +int mosh_main( int argc, char* argv[] ) #else -int main( int argc, char *argv[] ) +int main( int argc, char* argv[] ) #endif { unsigned int verbose = 0; @@ -117,11 +119,11 @@ int main( int argc, char *argv[] ) /* Get arguments */ for ( int i = 1; i < argc; i++ ) { - if ( 0 == strcmp( argv[ i ], "--help" ) ) { - print_usage( stdout, argv[ 0 ] ); + if ( 0 == strcmp( argv[i], "--help" ) ) { + print_usage( stdout, argv[0] ); exit( 0 ); } - if ( 0 == strcmp( argv[ i ], "--version" ) ) { + if ( 0 == strcmp( argv[i], "--version" ) ) { print_version( stdout ); exit( 0 ); } @@ -130,52 +132,53 @@ int main( int argc, char *argv[] ) int opt; while ( ( opt = getopt( argc, argv, "#:cv" ) ) != -1 ) { switch ( opt ) { - case '#': - // Ignore the original arguments to mosh wrapper - break; - case 'c': - print_colorcount(); - exit( 0 ); - break; - case 'v': verbose++; break; - default: - print_usage( stderr, argv[ 0 ] ); - exit( 1 ); - break; + case '#': + // Ignore the original arguments to mosh wrapper + break; + case 'c': + print_colorcount(); + exit( 0 ); + break; + case 'v': + verbose++; + break; + default: + print_usage( stderr, argv[0] ); + exit( 1 ); + break; } } char *ip, *desired_port; if ( argc - optind != 2 ) { - print_usage( stderr, argv[ 0 ] ); + print_usage( stderr, argv[0] ); exit( 1 ); } - ip = argv[ optind ]; - desired_port = argv[ optind + 1 ]; + ip = argv[optind]; + desired_port = argv[optind + 1]; /* Sanity-check arguments */ - if ( desired_port - && ( strspn( desired_port, "0123456789" ) != strlen( desired_port ) ) ) { - fprintf( stderr, "%s: Bad UDP port (%s)\n\n", argv[ 0 ], desired_port ); - print_usage( stderr, argv[ 0 ] ); + if ( desired_port && ( strspn( desired_port, "0123456789" ) != strlen( desired_port ) ) ) { + fprintf( stderr, "%s: Bad UDP port (%s)\n\n", argv[0], desired_port ); + print_usage( stderr, argv[0] ); exit( 1 ); } /* Read key from environment */ - char *env_key = getenv( "MOSH_KEY" ); + char* env_key = getenv( "MOSH_KEY" ); if ( env_key == NULL ) { fputs( "MOSH_KEY environment variable not found.\n", stderr ); exit( 1 ); } /* Read prediction preference */ - char *predict_mode = getenv( "MOSH_PREDICTION_DISPLAY" ); + char* predict_mode = getenv( "MOSH_PREDICTION_DISPLAY" ); /* can be NULL */ /* Read prediction insertion preference */ - char *predict_overwrite = getenv( "MOSH_PREDICTION_OVERWRITE" ); + char* predict_overwrite = getenv( "MOSH_PREDICTION_OVERWRITE" ); /* can be NULL */ string key( env_key ); @@ -190,8 +193,7 @@ int main( int argc, char *argv[] ) bool success = false; try { - STMClient client( ip, desired_port, key.c_str(), predict_mode, verbose, - predict_overwrite ); + STMClient client( ip, desired_port, key.c_str(), predict_mode, verbose, predict_overwrite ); client.init(); try { @@ -202,13 +204,13 @@ int main( int argc, char *argv[] ) } client.shutdown(); - } catch ( const Network::NetworkException &e ) { + } catch ( const Network::NetworkException& e ) { fprintf( stderr, "Network exception: %s\r\n", e.what() ); success = false; - } catch ( const Crypto::CryptoException &e ) { + } catch ( const Crypto::CryptoException& e ) { fprintf( stderr, "Crypto exception: %s\r\n", e.what() ); success = false; - } catch ( const std::exception &e ) { + } catch ( const std::exception& e ) { fprintf( stderr, "Error: %s\r\n", e.what() ); success = false; } diff --git a/src/frontend/mosh-server.cc b/src/frontend/mosh-server.cc index bed6b1251..336c40aa8 100644 --- a/src/frontend/mosh-server.cc +++ b/src/frontend/mosh-server.cc @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -46,9 +47,8 @@ #include #include #include -#include -#include #include +#include #ifdef HAVE_UTEMPTER #include #endif @@ -94,42 +94,47 @@ #include "networktransport-impl.h" -typedef Network::Transport - ServerConnection; +typedef Network::Transport ServerConnection; -static void serve( int host_fd, Terminal::Complete &terminal, - ServerConnection &network, long network_timeout, +static void serve( int host_fd, + Terminal::Complete& terminal, + ServerConnection& network, + long network_timeout, long network_signaled_timeout ); -static int run_server( const char *desired_ip, const char *desired_port, - const string &command_path, char *command_argv[], - const int colors, unsigned int verbose, bool with_motd ); - -static void print_version( FILE *file ) { - fputs( "mosh-server (" PACKAGE_STRING ") [build " BUILD_VERSION - "]\n" +static int run_server( const char* desired_ip, + const char* desired_port, + const string& command_path, + char* command_argv[], + const int colors, + unsigned int verbose, + bool with_motd ); + +static void print_version( FILE* file ) +{ + fputs( "mosh-server (" PACKAGE_STRING ") [build " BUILD_VERSION "]\n" "Copyright 2012 Keith Winstein \n" - "License GPLv3+: GNU GPL version 3 or later " - ".\n" + "License GPLv3+: GNU GPL version 3 or later .\n" "This is free software: you are free to change and redistribute it.\n" "There is NO WARRANTY, to the extent permitted by law.\n", file ); } -static void print_usage( FILE *stream, const char *argv0 ) { +static void print_usage( FILE* stream, const char* argv0 ) +{ fprintf( stream, - "Usage: %s new [-s] [-v] [-i LOCALADDR] [-p PORT[:PORT2]] [-c " - "COLORS] [-l NAME=VALUE] [-- COMMAND...]\n", + "Usage: %s new [-s] [-v] [-i LOCALADDR] [-p PORT[:PORT2]] [-c COLORS] [-l NAME=VALUE] [-- COMMAND...]\n", argv0 ); } -static bool print_motd( const char *filename ); +static bool print_motd( const char* filename ); static void chdir_homedir( void ); static bool motd_hushed( void ); -static void warn_unattached( const string &ignore_entry ); +static void warn_unattached( const string& ignore_entry ); /* Simple spinloop */ -static void spin( void ) { +static void spin( void ) +{ static unsigned int spincount = 0; spincount++; @@ -142,20 +147,18 @@ static void spin( void ) { } } -static string get_SSH_IP( void ) { - const char *SSH_CONNECTION = getenv( "SSH_CONNECTION" ); +static string get_SSH_IP( void ) +{ + const char* SSH_CONNECTION = getenv( "SSH_CONNECTION" ); if ( !SSH_CONNECTION ) { /* Older sshds don't set this */ - fputs( "Warning: SSH_CONNECTION not found; binding to any interface.\n", - stderr ); + fputs( "Warning: SSH_CONNECTION not found; binding to any interface.\n", stderr ); return string( "" ); } std::istringstream ss( SSH_CONNECTION ); string dummy, local_interface_IP; ss >> dummy >> dummy >> local_interface_IP; if ( !ss ) { - fputs( - "Warning: Could not parse SSH_CONNECTION; binding to any interface.\n", - stderr ); + fputs( "Warning: Could not parse SSH_CONNECTION; binding to any interface.\n", stderr ); return string( "" ); } @@ -163,27 +166,26 @@ static string get_SSH_IP( void ) { const char IPv6_prefix[] = "::ffff:"; if ( ( local_interface_IP.length() > strlen( IPv6_prefix ) ) - && ( 0 - == strncasecmp( local_interface_IP.c_str(), IPv6_prefix, - strlen( IPv6_prefix ) ) ) ) { + && ( 0 == strncasecmp( local_interface_IP.c_str(), IPv6_prefix, strlen( IPv6_prefix ) ) ) ) { return local_interface_IP.substr( strlen( IPv6_prefix ) ); } return local_interface_IP; } -int main( int argc, char *argv[] ) { +int main( int argc, char* argv[] ) +{ /* For security, make sure we don't dump core */ Crypto::disable_dumping_core(); /* Detect edge case */ fatal_assert( argc > 0 ); - const char *desired_ip = NULL; + const char* desired_ip = NULL; string desired_ip_str; - const char *desired_port = NULL; + const char* desired_port = NULL; string command_path; - char **command_argv = NULL; + char** command_argv = NULL; int colors = 0; unsigned int verbose = 0; /* don't close stdin/stdout/stderr */ /* Will cause mosh-server not to correctly detach on old versions of sshd. */ @@ -191,16 +193,15 @@ int main( int argc, char *argv[] ) { /* strip off command */ for ( int i = 1; i < argc; i++ ) { - if ( 0 == strcmp( argv[ i ], "--help" ) - || 0 == strcmp( argv[ i ], "-h" ) ) { - print_usage( stdout, argv[ 0 ] ); + if ( 0 == strcmp( argv[i], "--help" ) || 0 == strcmp( argv[i], "-h" ) ) { + print_usage( stdout, argv[0] ); exit( 0 ); } - if ( 0 == strcmp( argv[ i ], "--version" ) ) { + if ( 0 == strcmp( argv[i], "--version" ) ) { print_version( stdout ); exit( 0 ); } - if ( 0 == strcmp( argv[ i ], "--" ) ) { /* -- is mandatory */ + if ( 0 == strcmp( argv[i], "--" ) ) { /* -- is mandatory */ if ( i != argc - 1 ) { command_argv = argv + i + 1; } @@ -210,82 +211,91 @@ int main( int argc, char *argv[] ) { } /* Parse new command-line syntax */ - if ( ( argc >= 2 ) && ( strcmp( argv[ 1 ], "new" ) == 0 ) ) { + if ( ( argc >= 2 ) && ( strcmp( argv[1], "new" ) == 0 ) ) { /* new option syntax */ int opt; while ( ( opt = getopt( argc - 1, argv + 1, "@:i:p:c:svl:" ) ) != -1 ) { switch ( opt ) { - /* - * This undocumented option does nothing but eat its argument. - * Useful in scripting where you prepend something to a - * mosh-server argv, and might end up with something like - * "mosh-server new -v new -c 256", now you can say - * "mosh-server new -v -@ new -c 256" to discard the second - * "new". - */ - case '@': break; - case 'i': desired_ip = optarg; break; - case 'p': desired_port = optarg; break; - case 's': - desired_ip = NULL; - desired_ip_str = get_SSH_IP(); - if ( !desired_ip_str.empty() ) { - desired_ip = desired_ip_str.c_str(); - fatal_assert( desired_ip ); - } - break; - case 'c': try { colors = myatoi( optarg ); - } catch ( const CryptoException & ) { - fprintf( stderr, "%s: Bad number of colors (%s)\n", argv[ 0 ], - optarg ); - print_usage( stderr, argv[ 0 ] ); - exit( 1 ); - } - break; - case 'v': verbose++; break; - case 'l': locale_vars.push_back( string( optarg ) ); break; - default: - /* don't die on unknown options */ - print_usage( stderr, argv[ 0 ] ); - break; + /* + * This undocumented option does nothing but eat its argument. + * Useful in scripting where you prepend something to a + * mosh-server argv, and might end up with something like + * "mosh-server new -v new -c 256", now you can say + * "mosh-server new -v -@ new -c 256" to discard the second + * "new". + */ + case '@': + break; + case 'i': + desired_ip = optarg; + break; + case 'p': + desired_port = optarg; + break; + case 's': + desired_ip = NULL; + desired_ip_str = get_SSH_IP(); + if ( !desired_ip_str.empty() ) { + desired_ip = desired_ip_str.c_str(); + fatal_assert( desired_ip ); + } + break; + case 'c': + try { + colors = myatoi( optarg ); + } catch ( const CryptoException& ) { + fprintf( stderr, "%s: Bad number of colors (%s)\n", argv[0], optarg ); + print_usage( stderr, argv[0] ); + exit( 1 ); + } + break; + case 'v': + verbose++; + break; + case 'l': + locale_vars.push_back( string( optarg ) ); + break; + default: + /* don't die on unknown options */ + print_usage( stderr, argv[0] ); + break; } } } else if ( argc == 1 ) { /* legacy argument parsing for older client wrapper script */ /* do nothing */ } else if ( argc == 2 ) { - desired_ip = argv[ 1 ]; + desired_ip = argv[1]; } else if ( argc == 3 ) { - desired_ip = argv[ 1 ]; - desired_port = argv[ 2 ]; + desired_ip = argv[1]; + desired_port = argv[2]; } else { - print_usage( stderr, argv[ 0 ] ); + print_usage( stderr, argv[0] ); exit( 1 ); } /* Sanity-check arguments */ int dpl, dph; - if ( desired_port - && !Connection::parse_portrange( desired_port, dpl, dph ) ) { - fprintf( stderr, "%s: Bad UDP port range (%s)\n", argv[ 0 ], desired_port ); - print_usage( stderr, argv[ 0 ] ); + if ( desired_port && !Connection::parse_portrange( desired_port, dpl, dph ) ) { + fprintf( stderr, "%s: Bad UDP port range (%s)\n", argv[0], desired_port ); + print_usage( stderr, argv[0] ); exit( 1 ); } bool with_motd = false; #ifdef HAVE_SYSLOG - openlog( argv[ 0 ], LOG_PID | LOG_NDELAY, LOG_AUTH ); + openlog( argv[0], LOG_PID | LOG_NDELAY, LOG_AUTH ); #endif /* Get shell */ - char *my_argv[ 2 ]; + char* my_argv[2]; string shell_name; if ( !command_argv ) { /* get shell name */ - const char *shell = getenv( "SHELL" ); + const char* shell = getenv( "SHELL" ); if ( shell == NULL ) { - struct passwd *pw = getpwuid( getuid() ); + struct passwd* pw = getpwuid( getuid() ); if ( pw == NULL ) { perror( "getpwuid" ); exit( 1 ); @@ -310,15 +320,15 @@ int main( int argc, char *argv[] ) { /* prepend '-' to make login shell */ shell_name = '-' + shell_name; - my_argv[ 0 ] = const_cast( shell_name.c_str() ); - my_argv[ 1 ] = NULL; + my_argv[0] = const_cast( shell_name.c_str() ); + my_argv[1] = NULL; command_argv = my_argv; with_motd = true; } if ( command_path.empty() ) { - command_path = command_argv[ 0 ]; + command_path = command_argv[0]; } /* Adopt implementation locale */ @@ -330,9 +340,8 @@ int main( int argc, char *argv[] ) { /* apply locale-related environment variables from client */ clear_locale_variables(); - for ( list::const_iterator i = locale_vars.begin(); - i != locale_vars.end(); i++ ) { - char *env_string = strdup( i->c_str() ); + for ( list::const_iterator i = locale_vars.begin(); i != locale_vars.end(); i++ ) { + char* env_string = strdup( i->c_str() ); fatal_assert( env_string ); if ( 0 != putenv( env_string ) ) { perror( "putenv" ); @@ -351,39 +360,43 @@ int main( int argc, char *argv[] ) { "the character set \"%s\",\n\n" "The client-supplied environment (%s) specifies\n" "the character set \"%s\".\n\n", - native_ctype.str().c_str(), native_charset.c_str(), - client_ctype.str().c_str(), client_charset.c_str() ); + native_ctype.str().c_str(), + native_charset.c_str(), + client_ctype.str().c_str(), + client_charset.c_str() ); int unused __attribute( ( unused ) ) = system( "locale" ); exit( 1 ); } } try { - return run_server( desired_ip, desired_port, command_path, command_argv, - colors, verbose, with_motd ); - } catch ( const Network::NetworkException &e ) { + return run_server( desired_ip, desired_port, command_path, command_argv, colors, verbose, with_motd ); + } catch ( const Network::NetworkException& e ) { fprintf( stderr, "Network exception: %s\n", e.what() ); return 1; - } catch ( const Crypto::CryptoException &e ) { + } catch ( const Crypto::CryptoException& e ) { fprintf( stderr, "Crypto exception: %s\n", e.what() ); return 1; } } -static int run_server( const char *desired_ip, const char *desired_port, - const string &command_path, char *command_argv[], - const int colors, unsigned int verbose, - bool with_motd ) { +static int run_server( const char* desired_ip, + const char* desired_port, + const string& command_path, + char* command_argv[], + const int colors, + unsigned int verbose, + bool with_motd ) +{ /* get network idle timeout */ long network_timeout = 0; - char *timeout_envar = getenv( "MOSH_SERVER_NETWORK_TMOUT" ); + char* timeout_envar = getenv( "MOSH_SERVER_NETWORK_TMOUT" ); if ( timeout_envar && *timeout_envar ) { errno = 0; - char *endptr; + char* endptr; network_timeout = strtol( timeout_envar, &endptr, 10 ); if ( *endptr != '\0' || ( network_timeout == 0 && errno == EINVAL ) ) { - fputs( "MOSH_SERVER_NETWORK_TMOUT not a valid integer, ignoring\n", - stderr ); + fputs( "MOSH_SERVER_NETWORK_TMOUT not a valid integer, ignoring\n", stderr ); } else if ( network_timeout < 0 ) { fputs( "MOSH_SERVER_NETWORK_TMOUT is negative, ignoring\n", stderr ); network_timeout = 0; @@ -391,15 +404,13 @@ static int run_server( const char *desired_ip, const char *desired_port, } /* get network signaled idle timeout */ long network_signaled_timeout = 0; - char *signal_envar = getenv( "MOSH_SERVER_SIGNAL_TMOUT" ); + char* signal_envar = getenv( "MOSH_SERVER_SIGNAL_TMOUT" ); if ( signal_envar && *signal_envar ) { errno = 0; - char *endptr; + char* endptr; network_signaled_timeout = strtol( signal_envar, &endptr, 10 ); - if ( *endptr != '\0' - || ( network_signaled_timeout == 0 && errno == EINVAL ) ) { - fputs( "MOSH_SERVER_SIGNAL_TMOUT not a valid integer, ignoring\n", - stderr ); + if ( *endptr != '\0' || ( network_signaled_timeout == 0 && errno == EINVAL ) ) { + fputs( "MOSH_SERVER_SIGNAL_TMOUT not a valid integer, ignoring\n", stderr ); } else if ( network_signaled_timeout < 0 ) { fputs( "MOSH_SERVER_SIGNAL_TMOUT is negative, ignoring\n", stderr ); network_signaled_timeout = 0; @@ -407,8 +418,7 @@ static int run_server( const char *desired_ip, const char *desired_port, } /* get initial window size */ struct winsize window_size; - if ( ioctl( STDIN_FILENO, TIOCGWINSZ, &window_size ) < 0 - || window_size.ws_col == 0 || window_size.ws_row == 0 ) { + if ( ioctl( STDIN_FILENO, TIOCGWINSZ, &window_size ) < 0 || window_size.ws_col == 0 || window_size.ws_row == 0 ) { /* Fill in sensible defaults. */ /* They will be overwritten by client on first connection. */ memset( &window_size, 0, sizeof( window_size ) ); @@ -422,8 +432,7 @@ static int run_server( const char *desired_ip, const char *desired_port, /* open network */ Network::UserStream blank; typedef shared::shared_ptr NetworkPointer; - NetworkPointer network( - new ServerConnection( terminal, blank, desired_ip, desired_port ) ); + NetworkPointer network( new ServerConnection( terminal, blank, desired_ip, desired_port ) ); network->set_verbose( verbose ); Select::set_verbose( verbose ); @@ -436,8 +445,7 @@ static int run_server( const char *desired_ip, const char *desired_port, if ( isatty( STDIN_FILENO ) ) { puts( "\r\n" ); } - printf( "MOSH CONNECT %s %s\n", network->port().c_str(), - network->get_key().c_str() ); + printf( "MOSH CONNECT %s %s\n", network->port().c_str(), network->get_key().c_str() ); /* don't let signals kill us */ struct sigaction sa; @@ -453,24 +461,19 @@ static int run_server( const char *desired_ip, const char *desired_port, if ( the_pid < 0 ) { perror( "fork" ); } else if ( the_pid > 0 ) { - fputs( - "\nmosh-server (" PACKAGE_STRING ") [build " BUILD_VERSION - "]\n" - "Copyright 2012 Keith Winstein \n" - "License GPLv3+: GNU GPL version 3 or later " - ".\n" - "This is free software: you are free to change and redistribute it.\n" - "There is NO WARRANTY, to the extent permitted by law.\n\n", - stderr ); - - fprintf( stderr, "[mosh-server detached, pid = %d]\n", - static_cast( the_pid ) ); + fputs( "\nmosh-server (" PACKAGE_STRING ") [build " BUILD_VERSION "]\n" + "Copyright 2012 Keith Winstein \n" + "License GPLv3+: GNU GPL version 3 or later .\n" + "This is free software: you are free to change and redistribute it.\n" + "There is NO WARRANTY, to the extent permitted by law.\n\n", + stderr ); + + fprintf( stderr, "[mosh-server detached, pid = %d]\n", static_cast( the_pid ) ); #ifndef HAVE_IUTF8 - fputs( - "\nWarning: termios IUTF8 flag not defined.\n" - "Character-erase of multibyte character sequence\n" - "probably does not work properly on this platform.\n", - stderr ); + fputs( "\nWarning: termios IUTF8 flag not defined.\n" + "Character-erase of multibyte character sequence\n" + "probably does not work properly on this platform.\n", + stderr ); #endif /* HAVE_IUTF8 */ fflush( NULL ); @@ -487,8 +490,7 @@ static int run_server( const char *desired_ip, const char *desired_port, /* close file descriptors */ if ( verbose == 0 ) { - /* Necessary to properly detach on old versions of sshd (e.g. - * RHEL/CentOS 5.0). */ + /* Necessary to properly detach on old versions of sshd (e.g. RHEL/CentOS 5.0). */ int nullfd; nullfd = open( "/dev/null", O_RDWR ); @@ -509,7 +511,7 @@ static int run_server( const char *desired_ip, const char *desired_port, } } - char utmp_entry[ 64 ] = { 0 }; + char utmp_entry[64] = { 0 }; snprintf( utmp_entry, 64, "mosh [%ld]", static_cast( getpid() ) ); /* Fork child process */ @@ -558,8 +560,7 @@ static int run_server( const char *desired_ip, const char *desired_port, const char default_term[] = "xterm"; const char color_term[] = "xterm-256color"; - if ( setenv( "TERM", ( colors == 256 ) ? color_term : default_term, true ) - < 0 ) { + if ( setenv( "TERM", ( colors == 256 ) ? color_term : default_term, true ) < 0 ) { perror( "setenv" ); exit( 1 ); } @@ -597,7 +598,7 @@ static int run_server( const char *desired_ip, const char *desired_port, } /* Wait for parent to release us. */ - char linebuf[ 81 ]; + char linebuf[81]; if ( fgets( linebuf, sizeof linebuf, stdin ) == NULL ) { err( 1, "parent signal" ); } @@ -627,11 +628,10 @@ static int run_server( const char *desired_ip, const char *desired_port, #endif try { - serve( master, terminal, *network, network_timeout, - network_signaled_timeout ); - } catch ( const Network::NetworkException &e ) { + serve( master, terminal, *network, network_timeout, network_signaled_timeout ); + } catch ( const Network::NetworkException& e ) { fprintf( stderr, "Network exception: %s\n", e.what() ); - } catch ( const Crypto::CryptoException &e ) { + } catch ( const Crypto::CryptoException& e ) { fprintf( stderr, "Crypto exception: %s\n", e.what() ); } @@ -650,16 +650,17 @@ static int run_server( const char *desired_ip, const char *desired_port, return 0; } -static void serve( int host_fd, Terminal::Complete &terminal, - ServerConnection &network, long network_timeout, - long network_signaled_timeout ) { +static void serve( int host_fd, + Terminal::Complete& terminal, + ServerConnection& network, + long network_timeout, + long network_signaled_timeout ) +{ /* scale timeouts */ - const uint64_t network_timeout_ms = - static_cast( network_timeout ) * 1000; - const uint64_t network_signaled_timeout_ms = - static_cast( network_signaled_timeout ) * 1000; + const uint64_t network_timeout_ms = static_cast( network_timeout ) * 1000; + const uint64_t network_signaled_timeout_ms = static_cast( network_signaled_timeout ) * 1000; /* prepare to poll for events */ - Select &sel = Select::get_instance(); + Select& sel = Select::get_instance(); sel.add_signal( SIGTERM ); sel.add_signal( SIGINT ); sel.add_signal( SIGUSR1 ); @@ -676,10 +677,9 @@ static void serve( int host_fd, Terminal::Complete &terminal, #endif #ifdef HAVE_SYSLOG - struct passwd *pw = getpwuid( getuid() ); + struct passwd* pw = getpwuid( getuid() ); if ( pw == NULL ) { - throw NetworkException( - std::string( "serve: getpwuid: " ) + strerror( errno ), 0 ); + throw NetworkException( std::string( "serve: getpwuid: " ) + strerror( errno ), 0 ); } syslog( LOG_INFO, "user %s session begin", pw->pw_name ); #endif @@ -694,8 +694,7 @@ static void serve( int host_fd, Terminal::Complete &terminal, timeout = std::min( timeout, network.wait_time() ); timeout = std::min( timeout, terminal.wait_time( now ) ); - if ( ( !network.get_remote_state_num() ) - || network.shutdown_in_progress() ) { + if ( ( !network.get_remote_state_num() ) || network.shutdown_in_progress() ) { timeout = std::min( timeout, 5000 ); } /* @@ -703,9 +702,7 @@ static void serve( int host_fd, Terminal::Complete &terminal, * We may want to wake up sooner. */ if ( network_timeout_ms ) { - int64_t network_sleep = - network_timeout_ms - - ( now - network.get_latest_remote_state().timestamp ); + int64_t network_sleep = network_timeout_ms - ( now - network.get_latest_remote_state().timestamp ); if ( network_sleep < 0 ) { network_sleep = 0; } else if ( network_sleep > INT_MAX ) { @@ -732,8 +729,7 @@ static void serve( int host_fd, Terminal::Complete &terminal, } now = Network::timestamp(); - uint64_t time_since_remote_state = - now - network.get_latest_remote_state().timestamp; + uint64_t time_since_remote_state = now - network.get_latest_remote_state().timestamp; string terminal_to_host; if ( sel.read( network_fd ) ) { @@ -748,18 +744,17 @@ static void serve( int host_fd, Terminal::Complete &terminal, us.apply_string( network.get_remote_diff() ); /* apply userstream to terminal */ for ( size_t i = 0; i < us.size(); i++ ) { - const Parser::Action &action = us.get_action( i ); + const Parser::Action& action = us.get_action( i ); if ( typeid( action ) == typeid( Parser::Resize ) ) { /* apply only the last consecutive Resize action */ if ( i < us.size() - 1 ) { - const Parser::Action &next = us.get_action( i + 1 ); + const Parser::Action& next = us.get_action( i + 1 ); if ( typeid( next ) == typeid( Parser::Resize ) ) { continue; } } /* tell child process of resize */ - const Parser::Resize &res = - static_cast( action ); + const Parser::Resize& res = static_cast( action ); struct winsize window_size; if ( ioctl( host_fd, TIOCGWINSZ, &window_size ) < 0 ) { perror( "ioctl TIOCGWINSZ" ); @@ -799,38 +794,30 @@ static void serve( int host_fd, Terminal::Complete &terminal, * - HAVE_UTEMPTER - update utmp entry if we have become "connected" * - HAVE_SYSLOG - log connection information to syslog **/ - if ( ( force_connection_change_evt ) - || saved_addr_len != network.get_remote_addr_len() - || memcmp( &saved_addr, &network.get_remote_addr(), - saved_addr_len ) - != 0 ) { + if ( ( force_connection_change_evt ) || saved_addr_len != network.get_remote_addr_len() + || memcmp( &saved_addr, &network.get_remote_addr(), saved_addr_len ) != 0 ) { saved_addr = network.get_remote_addr(); saved_addr_len = network.get_remote_addr_len(); - char host[ NI_MAXHOST ]; - int errcode = - getnameinfo( &saved_addr.sa, saved_addr_len, host, - sizeof( host ), NULL, 0, NI_NUMERICHOST ); + char host[NI_MAXHOST]; + int errcode + = getnameinfo( &saved_addr.sa, saved_addr_len, host, sizeof( host ), NULL, 0, NI_NUMERICHOST ); if ( errcode != 0 ) { - throw NetworkException( std::string( "serve: getnameinfo: " ) - + gai_strerror( errcode ), - 0 ); + throw NetworkException( std::string( "serve: getnameinfo: " ) + gai_strerror( errcode ), 0 ); } #ifdef HAVE_UTEMPTER utempter_remove_record( host_fd ); - char tmp[ 64 + NI_MAXHOST ]; - snprintf( tmp, 64 + NI_MAXHOST, "%s via mosh [%ld]", host, - static_cast( getpid() ) ); + char tmp[64 + NI_MAXHOST]; + snprintf( tmp, 64 + NI_MAXHOST, "%s via mosh [%ld]", host, static_cast( getpid() ) ); utempter_add_record( host_fd, tmp ); connected_utmp = true; #endif #ifdef HAVE_SYSLOG - syslog( LOG_INFO, "user %s connected from host: %s", pw->pw_name, - host ); + syslog( LOG_INFO, "user %s connected from host: %s", pw->pw_name, host ); #endif } #endif @@ -848,7 +835,7 @@ static void serve( int host_fd, Terminal::Complete &terminal, if ( ( !network.shutdown_in_progress() ) && sel.read( host_fd ) ) { /* input from the host needs to be fed to the terminal */ const int buf_size = 16384; - char buf[ buf_size ]; + char buf[buf_size]; /* fill buffer if possible */ ssize_t bytes_read = read( host_fd, buf, buf_size ); @@ -866,33 +853,28 @@ static void serve( int host_fd, Terminal::Complete &terminal, } /* write user input and terminal writeback to the host */ - if ( swrite( host_fd, terminal_to_host.c_str(), - terminal_to_host.length() ) - < 0 ) { + if ( swrite( host_fd, terminal_to_host.c_str(), terminal_to_host.length() ) < 0 ) { network.start_shutdown(); } bool idle_shutdown = false; - if ( network_timeout_ms - && network_timeout_ms <= time_since_remote_state ) { + if ( network_timeout_ms && network_timeout_ms <= time_since_remote_state ) { idle_shutdown = true; - fprintf( - stderr, "Network idle for %llu seconds.\n", - static_cast( time_since_remote_state / 1000 ) ); + fprintf( stderr, + "Network idle for %llu seconds.\n", + static_cast( time_since_remote_state / 1000 ) ); } if ( sel.signal( SIGUSR1 ) - && ( !network_signaled_timeout_ms - || network_signaled_timeout_ms <= time_since_remote_state ) ) { + && ( !network_signaled_timeout_ms || network_signaled_timeout_ms <= time_since_remote_state ) ) { idle_shutdown = true; - fprintf( - stderr, "Network idle for %llu seconds when SIGUSR1 received\n", - static_cast( time_since_remote_state / 1000 ) ); + fprintf( stderr, + "Network idle for %llu seconds when SIGUSR1 received\n", + static_cast( time_since_remote_state / 1000 ) ); } if ( sel.any_signal() || idle_shutdown ) { /* shutdown signal */ - if ( network.has_remote_addr() - && ( !network.shutdown_in_progress() ) ) { + if ( network.has_remote_addr() && ( !network.shutdown_in_progress() ) ) { network.start_shutdown(); } else { break; @@ -905,8 +887,7 @@ static void serve( int host_fd, Terminal::Complete &terminal, } /* quit after shutdown acknowledgement timeout */ - if ( network.shutdown_in_progress() - && network.shutdown_ack_timed_out() ) { + if ( network.shutdown_in_progress() && network.shutdown_ack_timed_out() ) { break; } @@ -920,7 +901,7 @@ static void serve( int host_fd, Terminal::Complete &terminal, if ( connected_utmp && time_since_remote_state > 30000 ) { utempter_remove_record( host_fd ); - char tmp[ 64 ]; + char tmp[64]; snprintf( tmp, 64, "mosh [%ld]", static_cast( getpid() ) ); utempter_add_record( host_fd, tmp ); @@ -933,19 +914,18 @@ static void serve( int host_fd, Terminal::Complete &terminal, network.set_current_state( terminal ); } - if ( !network.get_remote_state_num() - && time_since_remote_state >= timeout_if_no_client ) { - fprintf( - stderr, "No connection within %llu seconds.\n", - static_cast( timeout_if_no_client / 1000 ) ); + if ( !network.get_remote_state_num() && time_since_remote_state >= timeout_if_no_client ) { + fprintf( stderr, + "No connection within %llu seconds.\n", + static_cast( timeout_if_no_client / 1000 ) ); break; } network.tick(); - } catch ( const Network::NetworkException &e ) { + } catch ( const Network::NetworkException& e ) { fprintf( stderr, "%s\n", e.what() ); spin(); - } catch ( const Crypto::CryptoException &e ) { + } catch ( const Crypto::CryptoException& e ) { if ( e.fatal ) { throw; } else { @@ -959,15 +939,16 @@ static void serve( int host_fd, Terminal::Complete &terminal, } /* Print the motd from a given file, if available */ -static bool print_motd( const char *filename ) { - FILE *motd = fopen( filename, "r" ); +static bool print_motd( const char* filename ) +{ + FILE* motd = fopen( filename, "r" ); if ( !motd ) { return false; } const int BUFSIZE = 256; - char buffer[ BUFSIZE ]; + char buffer[BUFSIZE]; while ( 1 ) { size_t bytes_read = fread( buffer, 1, BUFSIZE, motd ); if ( bytes_read == 0 ) { @@ -983,10 +964,11 @@ static bool print_motd( const char *filename ) { return true; } -static void chdir_homedir( void ) { - const char *home = getenv( "HOME" ); +static void chdir_homedir( void ) +{ + const char* home = getenv( "HOME" ); if ( home == NULL ) { - struct passwd *pw = getpwuid( getuid() ); + struct passwd* pw = getpwuid( getuid() ); if ( pw == NULL ) { perror( "getpwuid" ); return; /* non-fatal */ @@ -1003,24 +985,27 @@ static void chdir_homedir( void ) { } } -static bool motd_hushed( void ) { +static bool motd_hushed( void ) +{ /* must be in home directory already */ struct stat buf; return 0 == lstat( ".hushlogin", &buf ); } #ifdef HAVE_UTMPX_H -static bool device_exists( const char *ut_line ) { +static bool device_exists( const char* ut_line ) +{ string device_name = string( "/dev/" ) + string( ut_line ); struct stat buf; return 0 == lstat( device_name.c_str(), &buf ); } #endif -static void warn_unattached( const string &ignore_entry ) { +static void warn_unattached( const string& ignore_entry ) +{ #ifdef HAVE_UTMPX_H /* get username */ - const struct passwd *pw = getpwuid( getuid() ); + const struct passwd* pw = getpwuid( getuid() ); if ( pw == NULL ) { perror( "getpwuid" ); /* non-fatal */ @@ -1032,14 +1017,12 @@ static void warn_unattached( const string &ignore_entry ) { /* look for unattached sessions */ vector unattached_mosh_servers; - while ( struct utmpx *entry = getutxent() ) { - if ( ( entry->ut_type == USER_PROCESS ) - && ( username == string( entry->ut_user ) ) ) { + while ( struct utmpx* entry = getutxent() ) { + if ( ( entry->ut_type == USER_PROCESS ) && ( username == string( entry->ut_user ) ) ) { /* does line show unattached mosh session */ string text( entry->ut_host ); - if ( ( text.size() >= 5 ) && ( text.substr( 0, 5 ) == "mosh " ) - && ( text[ text.size() - 1 ] == ']' ) && ( text != ignore_entry ) - && device_exists( entry->ut_line ) ) { + if ( ( text.size() >= 5 ) && ( text.substr( 0, 5 ) == "mosh " ) && ( text[text.size() - 1] == ']' ) + && ( text != ignore_entry ) && device_exists( entry->ut_line ) ) { unattached_mosh_servers.push_back( text ); } } @@ -1049,22 +1032,19 @@ static void warn_unattached( const string &ignore_entry ) { if ( unattached_mosh_servers.empty() ) { return; } else if ( unattached_mosh_servers.size() == 1 ) { - printf( - "\033[37;44mMosh: You have a detached Mosh session on this server " - "(%s).\033[m\n\n", - unattached_mosh_servers.front().c_str() ); + printf( "\033[37;44mMosh: You have a detached Mosh session on this server (%s).\033[m\n\n", + unattached_mosh_servers.front().c_str() ); } else { string pid_string; - for ( vector::const_iterator it = unattached_mosh_servers.begin(); - it != unattached_mosh_servers.end(); it++ ) { + for ( vector::const_iterator it = unattached_mosh_servers.begin(); it != unattached_mosh_servers.end(); + it++ ) { pid_string += " - " + *it + "\n"; } - printf( - "\033[37;44mMosh: You have %d detached Mosh sessions on this server, " - "with PIDs:\n%s\033[m\n", - (int)unattached_mosh_servers.size(), pid_string.c_str() ); + printf( "\033[37;44mMosh: You have %d detached Mosh sessions on this server, with PIDs:\n%s\033[m\n", + (int)unattached_mosh_servers.size(), + pid_string.c_str() ); } #endif /* HAVE_UTMPX_H */ } diff --git a/src/frontend/stmclient.cc b/src/frontend/stmclient.cc index 8eb44bc67..5f55450f1 100644 --- a/src/frontend/stmclient.cc +++ b/src/frontend/stmclient.cc @@ -65,7 +65,8 @@ using std::wstring; -void STMClient::resume( void ) { +void STMClient::resume( void ) +{ /* Restore termios state */ if ( tcsetattr( STDIN_FILENO, TCSANOW, &raw_termios ) < 0 ) { perror( "tcsetattr" ); @@ -79,7 +80,8 @@ void STMClient::resume( void ) { repaint_requested = true; } -void STMClient::init( void ) { +void STMClient::init( void ) +{ if ( !is_utf8_locale() ) { LocaleVar native_ctype = get_ctype(); string native_charset( locale_charset() ); @@ -88,7 +90,8 @@ void STMClient::init( void ) { "mosh-client needs a UTF-8 native locale to run.\n\n" "Unfortunately, the client's environment (%s) specifies\n" "the character set \"%s\".\n\n", - native_ctype.str().c_str(), native_charset.c_str() ); + native_ctype.str().c_str(), + native_charset.c_str() ); int unused __attribute( ( unused ) ) = system( "locale" ); exit( 1 ); } @@ -104,10 +107,8 @@ void STMClient::init( void ) { #ifdef HAVE_IUTF8 if ( !( raw_termios.c_iflag & IUTF8 ) ) { - // fprintf( stderr, "Warning: Locale is UTF-8 but termios IUTF8 flag not - // set. Setting IUTF8 flag.\n" ); - /* Probably not really necessary since we are putting terminal driver into - * raw mode anyway. */ + // fprintf( stderr, "Warning: Locale is UTF-8 but termios IUTF8 flag not set. Setting IUTF8 flag.\n" ); + /* Probably not really necessary since we are putting terminal driver into raw mode anyway. */ raw_termios.c_iflag |= IUTF8; } #endif /* HAVE_IUTF8 */ @@ -128,18 +129,16 @@ void STMClient::init( void ) { } /* Set terminal escape key. */ - const char *escape_key_env; + const char* escape_key_env; if ( ( escape_key_env = getenv( "MOSH_ESCAPE_KEY" ) ) != NULL ) { if ( strlen( escape_key_env ) == 1 ) { - escape_key = (int)escape_key_env[ 0 ]; + escape_key = (int)escape_key_env[0]; if ( escape_key > 0 && escape_key < 128 ) { if ( escape_key < 32 ) { - /* If escape is ctrl-something, pass it with repeating the key without - * ctrl. */ + /* If escape is ctrl-something, pass it with repeating the key without ctrl. */ escape_pass_key = escape_key + (int)'@'; } else { - /* If escape is something else, pass it with repeating the key itself. - */ + /* If escape is something else, pass it with repeating the key itself. */ escape_pass_key = escape_key; } if ( escape_pass_key >= 'A' && escape_pass_key <= 'Z' ) { @@ -170,8 +169,8 @@ void STMClient::init( void ) { /* There are so many better ways to shoot oneself into leg than setting escape key to Ctrl-C, Ctrl-D, NewLine, Ctrl-L or CarriageReturn that we just won't allow that. */ - if ( escape_key == 0x03 || escape_key == 0x04 || escape_key == 0x0A - || escape_key == 0x0C || escape_key == 0x0D ) { + if ( escape_key == 0x03 || escape_key == 0x04 || escape_key == 0x0A || escape_key == 0x0C + || escape_key == 0x0D ) { escape_key = 0x1E; escape_pass_key = '^'; escape_pass_key2 = '^'; @@ -179,17 +178,14 @@ void STMClient::init( void ) { /* Adjust escape help differently if escape is a control character. */ if ( escape_key > 0 ) { - char escape_pass_name_buf[ 16 ]; - char escape_key_name_buf[ 16 ]; - snprintf( escape_pass_name_buf, sizeof escape_pass_name_buf, "\"%c\"", - escape_pass_key ); + char escape_pass_name_buf[16]; + char escape_key_name_buf[16]; + snprintf( escape_pass_name_buf, sizeof escape_pass_name_buf, "\"%c\"", escape_pass_key ); if ( escape_key < 32 ) { - snprintf( escape_key_name_buf, sizeof escape_key_name_buf, "Ctrl-%c", - escape_pass_key ); + snprintf( escape_key_name_buf, sizeof escape_key_name_buf, "Ctrl-%c", escape_pass_key ); escape_requires_lf = false; } else { - snprintf( escape_key_name_buf, sizeof escape_key_name_buf, "\"%c\"", - escape_key ); + snprintf( escape_key_name_buf, sizeof escape_key_name_buf, "\"%c\"", escape_key ); escape_requires_lf = true; } string tmp; @@ -197,17 +193,17 @@ void STMClient::init( void ) { wstring escape_pass_name = std::wstring( tmp.begin(), tmp.end() ); tmp = string( escape_key_name_buf ); wstring escape_key_name = std::wstring( tmp.begin(), tmp.end() ); - escape_key_help = L"Commands: Ctrl-Z suspends, \".\" quits, " - + escape_pass_name + L" gives literal " + escape_key_name; + escape_key_help + = L"Commands: Ctrl-Z suspends, \".\" quits, " + escape_pass_name + L" gives literal " + escape_key_name; overlays.get_notification_engine().set_escape_key_string( tmp ); } - wchar_t tmp[ 128 ]; - swprintf( tmp, 128, L"Nothing received from server on UDP port %s.", - port.c_str() ); + wchar_t tmp[128]; + swprintf( tmp, 128, L"Nothing received from server on UDP port %s.", port.c_str() ); connecting_notification = wstring( tmp ); } -void STMClient::shutdown( void ) { +void STMClient::shutdown( void ) +{ /* Restore screen state */ overlays.get_notification_engine().set_notification_string( wstring( L"" ) ); overlays.get_notification_engine().server_heard( timestamp() ); @@ -225,22 +221,22 @@ void STMClient::shutdown( void ) { if ( still_connecting() ) { fprintf( stderr, "\nmosh did not make a successful connection to %s:%s.\n" - "Please verify that UDP port %s is not firewalled and can reach " - "the server.\n\n" - "(By default, mosh uses a UDP port between 60000 and 61000. The " - "-p option\n" + "Please verify that UDP port %s is not firewalled and can reach the server.\n\n" + "(By default, mosh uses a UDP port between 60000 and 61000. The -p option\n" "selects a specific UDP port number.)\n", - ip.c_str(), port.c_str(), port.c_str() ); + ip.c_str(), + port.c_str(), + port.c_str() ); } else if ( network && !clean_shutdown ) { - fputs( - "\n\nmosh did not shut down cleanly. Please note that the\n" - "mosh-server process may still be running on the server.\n", - stderr ); + fputs( "\n\nmosh did not shut down cleanly. Please note that the\n" + "mosh-server process may still be running on the server.\n", + stderr ); } } -void STMClient::main_init( void ) { - Select &sel = Select::get_instance(); +void STMClient::main_init( void ) +{ + Select& sel = Select::get_instance(); sel.add_signal( SIGWINCH ); sel.add_signal( SIGTERM ); sel.add_signal( SIGINT ); @@ -255,33 +251,30 @@ void STMClient::main_init( void ) { } /* local state */ - local_framebuffer = - Terminal::Framebuffer( window_size.ws_col, window_size.ws_row ); + local_framebuffer = Terminal::Framebuffer( window_size.ws_col, window_size.ws_row ); new_state = Terminal::Framebuffer( 1, 1 ); /* initialize screen */ - string init = - display.new_frame( false, local_framebuffer, local_framebuffer ); + string init = display.new_frame( false, local_framebuffer, local_framebuffer ); swrite( STDOUT_FILENO, init.data(), init.size() ); /* open network */ Network::UserStream blank; Terminal::Complete local_terminal( window_size.ws_col, window_size.ws_row ); - network = NetworkPointer( new NetworkType( blank, local_terminal, key.c_str(), - ip.c_str(), port.c_str() ) ); + network = NetworkPointer( new NetworkType( blank, local_terminal, key.c_str(), ip.c_str(), port.c_str() ) ); network->set_send_delay( 1 ); /* minimal delay on outgoing keystrokes */ /* tell server the size of the terminal */ - network->get_current_state().push_back( - Parser::Resize( window_size.ws_col, window_size.ws_row ) ); + network->get_current_state().push_back( Parser::Resize( window_size.ws_col, window_size.ws_row ) ); /* be noisy as necessary */ network->set_verbose( verbose ); Select::set_verbose( verbose ); } -void STMClient::output_new_frame( void ) { +void STMClient::output_new_frame( void ) +{ if ( !network ) { /* clean shutdown even when not initialized */ return; } @@ -293,8 +286,7 @@ void STMClient::output_new_frame( void ) { overlays.apply( new_state ); /* calculate minimal difference from where we are */ - const string diff( - display.new_frame( !repaint_requested, local_framebuffer, new_state ) ); + const string diff( display.new_frame( !repaint_requested, local_framebuffer, new_state ) ); swrite( STDOUT_FILENO, diff.data(), diff.size() ); repaint_requested = false; @@ -302,26 +294,24 @@ void STMClient::output_new_frame( void ) { local_framebuffer = new_state; } -void STMClient::process_network_input( void ) { +void STMClient::process_network_input( void ) +{ network->recv(); /* Now give hints to the overlays */ - overlays.get_notification_engine().server_heard( - network->get_latest_remote_state().timestamp ); - overlays.get_notification_engine().server_acked( - network->get_sent_state_acked_timestamp() ); - - overlays.get_prediction_engine().set_local_frame_acked( - network->get_sent_state_acked() ); - overlays.get_prediction_engine().set_send_interval( - network->send_interval() ); + overlays.get_notification_engine().server_heard( network->get_latest_remote_state().timestamp ); + overlays.get_notification_engine().server_acked( network->get_sent_state_acked_timestamp() ); + + overlays.get_prediction_engine().set_local_frame_acked( network->get_sent_state_acked() ); + overlays.get_prediction_engine().set_send_interval( network->send_interval() ); overlays.get_prediction_engine().set_local_frame_late_acked( - network->get_latest_remote_state().state.get_echo_ack() ); + network->get_latest_remote_state().state.get_echo_ack() ); } -bool STMClient::process_user_input( int fd ) { +bool STMClient::process_user_input( int fd ) +{ const int buf_size = 16384; - char buf[ buf_size ]; + char buf[buf_size]; /* fill buffer if possible */ ssize_t bytes_read = read( fd, buf, buf_size ); @@ -332,13 +322,12 @@ bool STMClient::process_user_input( int fd ) { return false; } - NetworkType &net = *network; + NetworkType& net = *network; if ( net.shutdown_in_progress() ) { return true; } - overlays.get_prediction_engine().set_local_frame_sent( - net.get_sent_state_last() ); + overlays.get_prediction_engine().set_local_frame_sent( net.get_sent_state_last() ); /* Don't predict for bulk data. */ bool paste = bytes_read > 100; @@ -347,24 +336,22 @@ bool STMClient::process_user_input( int fd ) { } for ( int i = 0; i < bytes_read; i++ ) { - char the_byte = buf[ i ]; + char the_byte = buf[i]; if ( !paste ) { - overlays.get_prediction_engine().new_user_byte( the_byte, - local_framebuffer ); + overlays.get_prediction_engine().new_user_byte( the_byte, local_framebuffer ); } if ( quit_sequence_started ) { if ( the_byte == '.' ) { /* Quit sequence is Ctrl-^ . */ if ( net.has_remote_addr() && ( !net.shutdown_in_progress() ) ) { - overlays.get_notification_engine().set_notification_string( - wstring( L"Exiting on user request..." ), true ); + overlays.get_notification_engine().set_notification_string( wstring( L"Exiting on user request..." ), + true ); net.start_shutdown(); return true; } return false; - } else if ( the_byte - == 0x1a ) { /* Suspend sequence is escape_key Ctrl-Z */ + } else if ( the_byte == 0x1a ) { /* Suspend sequence is escape_key Ctrl-Z */ /* Restore terminal and terminal-driver state */ swrite( STDOUT_FILENO, display.close().c_str() ); @@ -381,40 +368,35 @@ bool STMClient::process_user_input( int fd ) { kill( 0, SIGSTOP ); resume(); - } else if ( ( the_byte == escape_pass_key ) - || ( the_byte == escape_pass_key2 ) ) { + } else if ( ( the_byte == escape_pass_key ) || ( the_byte == escape_pass_key2 ) ) { /* Emulation sequence to type escape_key is escape_key + escape_pass_key (that is escape key without Ctrl) */ net.get_current_state().push_back( Parser::UserByte( escape_key ) ); } else { - /* Escape key followed by anything other than . and ^ gets sent - * literally */ + /* Escape key followed by anything other than . and ^ gets sent literally */ net.get_current_state().push_back( Parser::UserByte( escape_key ) ); net.get_current_state().push_back( Parser::UserByte( the_byte ) ); } quit_sequence_started = false; - if ( overlays.get_notification_engine().get_notification_string() - == escape_key_help ) { + if ( overlays.get_notification_engine().get_notification_string() == escape_key_help ) { overlays.get_notification_engine().set_notification_string( L"" ); } continue; } - quit_sequence_started = ( escape_key > 0 ) && ( the_byte == escape_key ) - && ( lf_entered || ( !escape_requires_lf ) ); + quit_sequence_started + = ( escape_key > 0 ) && ( the_byte == escape_key ) && ( lf_entered || ( !escape_requires_lf ) ); if ( quit_sequence_started ) { lf_entered = false; - overlays.get_notification_engine().set_notification_string( - escape_key_help, true, false ); + overlays.get_notification_engine().set_notification_string( escape_key_help, true, false ); continue; } lf_entered = ( ( the_byte == 0x0A ) - || ( the_byte == 0x0D ) ); /* LineFeed, Ctrl-J, '\n' or - CarriageReturn, Ctrl-M, '\r' */ + || ( the_byte == 0x0D ) ); /* LineFeed, Ctrl-J, '\n' or CarriageReturn, Ctrl-M, '\r' */ if ( the_byte == 0x0C ) { /* Ctrl-L */ repaint_requested = true; @@ -426,7 +408,8 @@ bool STMClient::process_user_input( int fd ) { return true; } -bool STMClient::process_resize( void ) { +bool STMClient::process_resize( void ) +{ /* get new size */ if ( ioctl( STDIN_FILENO, TIOCGWINSZ, &window_size ) < 0 ) { perror( "ioctl TIOCGWINSZ" ); @@ -440,8 +423,7 @@ bool STMClient::process_resize( void ) { network->get_current_state().push_back( res ); } - /* note remote emulator will probably reply with its own Resize to adjust our - * state */ + /* note remote emulator will probably reply with its own Resize to adjust our state */ /* tell prediction engine */ overlays.get_prediction_engine().reset(); @@ -449,7 +431,8 @@ bool STMClient::process_resize( void ) { return true; } -bool STMClient::main( void ) { +bool STMClient::main( void ) +{ /* initialize signal handling and structures */ main_init(); @@ -463,7 +446,7 @@ bool STMClient::main( void ) { #endif /* prepare to poll for events */ - Select &sel = Select::get_instance(); + Select& sel = Select::get_instance(); while ( 1 ) { try { @@ -480,8 +463,7 @@ bool STMClient::main( void ) { /* network->fd() can in theory change over time */ sel.clear_fds(); std::vector fd_list( network->fds() ); - for ( std::vector::const_iterator it = fd_list.begin(); - it != fd_list.end(); it++ ) { + for ( std::vector::const_iterator it = fd_list.begin(); it != fd_list.end(); it++ ) { sel.add_fd( *it ); } sel.add_fd( STDIN_FILENO ); @@ -494,8 +476,7 @@ bool STMClient::main( void ) { bool network_ready_to_read = false; - for ( std::vector::const_iterator it = fd_list.begin(); - it != fd_list.end(); it++ ) { + for ( std::vector::const_iterator it = fd_list.begin(); it != fd_list.end(); it++ ) { if ( sel.read( *it ) ) { /* packet received from the network */ /* we only read one socket each run */ @@ -508,14 +489,11 @@ bool STMClient::main( void ) { } if ( sel.read( STDIN_FILENO ) - && !process_user_input( - STDIN_FILENO ) ) { /* input from the user needs to be fed to the - network */ + && !process_user_input( STDIN_FILENO ) ) { /* input from the user needs to be fed to the network */ if ( !network->has_remote_addr() ) { break; } else if ( !network->shutdown_in_progress() ) { - overlays.get_notification_engine().set_notification_string( - wstring( L"Exiting..." ), true ); + overlays.get_notification_engine().set_notification_string( wstring( L"Exiting..." ), true ); network->start_shutdown(); } } @@ -528,28 +506,25 @@ bool STMClient::main( void ) { resume(); } - if ( sel.signal( SIGTERM ) || sel.signal( SIGINT ) || sel.signal( SIGHUP ) - || sel.signal( SIGPIPE ) ) { + if ( sel.signal( SIGTERM ) || sel.signal( SIGINT ) || sel.signal( SIGHUP ) || sel.signal( SIGPIPE ) ) { /* shutdown signal */ if ( !network->has_remote_addr() ) { break; } else if ( !network->shutdown_in_progress() ) { overlays.get_notification_engine().set_notification_string( - wstring( L"Signal received, shutting down..." ), true ); + wstring( L"Signal received, shutting down..." ), true ); network->start_shutdown(); } } /* quit if our shutdown has been acknowledged */ - if ( network->shutdown_in_progress() - && network->shutdown_acknowledged() ) { + if ( network->shutdown_in_progress() && network->shutdown_acknowledged() ) { clean_shutdown = true; break; } /* quit after shutdown acknowledgement timeout */ - if ( network->shutdown_in_progress() - && network->shutdown_ack_timed_out() ) { + if ( network->shutdown_in_progress() && network->shutdown_ack_timed_out() ) { break; } @@ -561,36 +536,31 @@ bool STMClient::main( void ) { /* write diagnostic message if can't reach server */ if ( still_connecting() && ( !network->shutdown_in_progress() ) - && ( timestamp() - network->get_latest_remote_state().timestamp - > 250 ) ) { - if ( timestamp() - network->get_latest_remote_state().timestamp - > 15000 ) { + && ( timestamp() - network->get_latest_remote_state().timestamp > 250 ) ) { + if ( timestamp() - network->get_latest_remote_state().timestamp > 15000 ) { if ( !network->shutdown_in_progress() ) { overlays.get_notification_engine().set_notification_string( - wstring( L"Timed out waiting for server..." ), true ); + wstring( L"Timed out waiting for server..." ), true ); network->start_shutdown(); } } else { - overlays.get_notification_engine().set_notification_string( - connecting_notification ); + overlays.get_notification_engine().set_notification_string( connecting_notification ); } } else if ( ( network->get_remote_state_num() != 0 ) - && ( overlays.get_notification_engine() - .get_notification_string() - == connecting_notification ) ) { + && ( overlays.get_notification_engine().get_notification_string() == connecting_notification ) ) { overlays.get_notification_engine().set_notification_string( L"" ); } network->tick(); - string &send_error = network->get_send_error(); + string& send_error = network->get_send_error(); if ( !send_error.empty() ) { overlays.get_notification_engine().set_network_error( send_error ); send_error.clear(); } else { overlays.get_notification_engine().clear_network_error(); } - } catch ( const Network::NetworkException &e ) { + } catch ( const Network::NetworkException& e ) { if ( !network->shutdown_in_progress() ) { overlays.get_notification_engine().set_network_error( e.what() ); } @@ -600,14 +570,13 @@ bool STMClient::main( void ) { req.tv_nsec = 200000000; /* 0.2 sec */ nanosleep( &req, NULL ); freeze_timestamp(); - } catch ( const Crypto::CryptoException &e ) { + } catch ( const Crypto::CryptoException& e ) { if ( e.fatal ) { throw; } else { - wchar_t tmp[ 128 ]; + wchar_t tmp[128]; swprintf( tmp, 128, L"Crypto exception: %s", e.what() ); - overlays.get_notification_engine().set_notification_string( - wstring( tmp ) ); + overlays.get_notification_engine().set_notification_string( wstring( tmp ) ); } } } diff --git a/src/frontend/stmclient.h b/src/frontend/stmclient.h index 7ad01ad06..bd8f9d57d 100644 --- a/src/frontend/stmclient.h +++ b/src/frontend/stmclient.h @@ -33,9 +33,9 @@ #ifndef STM_CLIENT_HPP #define STM_CLIENT_HPP +#include #include #include -#include #include "completeterminal.h" #include "networktransport.h" @@ -43,7 +43,8 @@ #include "terminaloverlay.h" #include "user.h" -class STMClient { +class STMClient +{ private: std::string ip; std::string port; @@ -61,8 +62,7 @@ class STMClient { Terminal::Framebuffer local_framebuffer, new_state; Overlay::OverlayManager overlays; - typedef Network::Transport - NetworkType; + typedef Network::Transport NetworkType; typedef shared::shared_ptr NetworkPointer; NetworkPointer network; Terminal::Display display; @@ -79,7 +79,8 @@ class STMClient { void output_new_frame( void ); - bool still_connecting( void ) const { + bool still_connecting( void ) const + { /* Initially, network == NULL */ return network && ( network->get_remote_state_num() == 0 ); } @@ -87,44 +88,45 @@ class STMClient { void resume( void ); /* restore state after SIGCONT */ public: - STMClient( const char *s_ip, const char *s_port, const char *s_key, - const char *predict_mode, unsigned int s_verbose, - const char *predict_overwrite ) - : ip( s_ip ? s_ip : "" ), - port( s_port ? s_port : "" ), - key( s_key ? s_key : "" ), - escape_key( 0x1E ), - escape_pass_key( '^' ), - escape_pass_key2( '^' ), - escape_requires_lf( false ), - escape_key_help( L"?" ), - saved_termios(), - raw_termios(), - window_size(), - local_framebuffer( 1, 1 ), - new_state( 1, 1 ), - overlays(), - network(), - display( true ), /* use TERM environment var to initialize display */ - connecting_notification(), - repaint_requested( false ), - lf_entered( false ), - quit_sequence_started( false ), - clean_shutdown( false ), - verbose( s_verbose ) { + STMClient( const char* s_ip, + const char* s_port, + const char* s_key, + const char* predict_mode, + unsigned int s_verbose, + const char* predict_overwrite ) + : ip( s_ip ? s_ip : "" ) + , port( s_port ? s_port : "" ) + , key( s_key ? s_key : "" ) + , escape_key( 0x1E ) + , escape_pass_key( '^' ) + , escape_pass_key2( '^' ) + , escape_requires_lf( false ) + , escape_key_help( L"?" ) + , saved_termios() + , raw_termios() + , window_size() + , local_framebuffer( 1, 1 ) + , new_state( 1, 1 ) + , overlays() + , network() + , display( true ) + , /* use TERM environment var to initialize display */ + connecting_notification() + , repaint_requested( false ) + , lf_entered( false ) + , quit_sequence_started( false ) + , clean_shutdown( false ) + , verbose( s_verbose ) + { if ( predict_mode ) { if ( !strcmp( predict_mode, "always" ) ) { - overlays.get_prediction_engine().set_display_preference( - Overlay::PredictionEngine::Always ); + overlays.get_prediction_engine().set_display_preference( Overlay::PredictionEngine::Always ); } else if ( !strcmp( predict_mode, "never" ) ) { - overlays.get_prediction_engine().set_display_preference( - Overlay::PredictionEngine::Never ); + overlays.get_prediction_engine().set_display_preference( Overlay::PredictionEngine::Never ); } else if ( !strcmp( predict_mode, "adaptive" ) ) { - overlays.get_prediction_engine().set_display_preference( - Overlay::PredictionEngine::Adaptive ); + overlays.get_prediction_engine().set_display_preference( Overlay::PredictionEngine::Adaptive ); } else if ( !strcmp( predict_mode, "experimental" ) ) { - overlays.get_prediction_engine().set_display_preference( - Overlay::PredictionEngine::Experimental ); + overlays.get_prediction_engine().set_display_preference( Overlay::PredictionEngine::Experimental ); } else { fprintf( stderr, "Unknown prediction mode %s.\n", predict_mode ); exit( 1 ); @@ -140,8 +142,8 @@ class STMClient { bool main( void ); /* unused */ - STMClient( const STMClient & ); - STMClient &operator=( const STMClient & ); + STMClient( const STMClient& ); + STMClient& operator=( const STMClient& ); }; #endif diff --git a/src/frontend/terminaloverlay.cc b/src/frontend/terminaloverlay.cc index b677d5bc5..dd347b5f5 100644 --- a/src/frontend/terminaloverlay.cc +++ b/src/frontend/terminaloverlay.cc @@ -30,20 +30,19 @@ also delete it here. */ -#include -#include #include +#include #include #include +#include #include "terminaloverlay.h" using namespace Overlay; -void ConditionalOverlayCell::apply( Framebuffer &fb, uint64_t confirmed_epoch, - int row, bool flag ) const { - if ( ( !active ) || ( row >= fb.ds.get_height() ) - || ( col >= fb.ds.get_width() ) ) { +void ConditionalOverlayCell::apply( Framebuffer& fb, uint64_t confirmed_epoch, int row, bool flag ) const +{ + if ( ( !active ) || ( row >= fb.ds.get_height() ) || ( col >= fb.ds.get_width() ) ) { return; } @@ -57,9 +56,7 @@ void ConditionalOverlayCell::apply( Framebuffer &fb, uint64_t confirmed_epoch, if ( unknown ) { if ( flag && ( col != fb.ds.get_width() - 1 ) ) { - fb.get_mutable_cell( row, col ) - ->get_renditions() - .set_attribute( Renditions::underlined, true ); + fb.get_mutable_cell( row, col )->get_renditions().set_attribute( Renditions::underlined, true ); } return; } @@ -67,17 +64,16 @@ void ConditionalOverlayCell::apply( Framebuffer &fb, uint64_t confirmed_epoch, if ( *fb.get_cell( row, col ) != replacement ) { *( fb.get_mutable_cell( row, col ) ) = replacement; if ( flag ) { - fb.get_mutable_cell( row, col ) - ->get_renditions() - .set_attribute( Renditions::underlined, true ); + fb.get_mutable_cell( row, col )->get_renditions().set_attribute( Renditions::underlined, true ); } } } -Validity ConditionalOverlayCell::get_validity( const Framebuffer &fb, int row, - uint64_t early_ack - __attribute__( ( unused ) ), - uint64_t late_ack ) const { +Validity ConditionalOverlayCell::get_validity( const Framebuffer& fb, + int row, + uint64_t early_ack __attribute__( ( unused ) ), + uint64_t late_ack ) const +{ if ( !active ) { return Inactive; } @@ -86,7 +82,7 @@ Validity ConditionalOverlayCell::get_validity( const Framebuffer &fb, int row, return IncorrectOrExpired; } - const Cell ¤t = *( fb.get_cell( row, col ) ); + const Cell& current = *( fb.get_cell( row, col ) ); /* see if it hasn't been updated yet */ if ( late_ack < expiration_frame ) { @@ -104,7 +100,8 @@ Validity ConditionalOverlayCell::get_validity( const Framebuffer &fb, int row, if ( current.contents_match( replacement ) ) { vector::const_iterator it = original_contents.begin(); for ( ; it != original_contents.end(); it++ ) { - if ( it->contents_match( replacement ) ) break; + if ( it->contents_match( replacement ) ) + break; } if ( it == original_contents.end() ) { return Correct; @@ -114,10 +111,10 @@ Validity ConditionalOverlayCell::get_validity( const Framebuffer &fb, int row, return IncorrectOrExpired; } -Validity ConditionalCursorMove::get_validity( const Framebuffer &fb, - uint64_t early_ack - __attribute( ( unused ) ), - uint64_t late_ack ) const { +Validity ConditionalCursorMove::get_validity( const Framebuffer& fb, + uint64_t early_ack __attribute( ( unused ) ), + uint64_t late_ack ) const +{ if ( !active ) { return Inactive; } @@ -128,8 +125,7 @@ Validity ConditionalCursorMove::get_validity( const Framebuffer &fb, } if ( late_ack >= expiration_frame ) { - if ( ( fb.ds.get_cursor_col() == col ) - && ( fb.ds.get_cursor_row() == row ) ) { + if ( ( fb.ds.get_cursor_col() == col ) && ( fb.ds.get_cursor_row() == row ) ) { return Correct; } return IncorrectOrExpired; @@ -138,8 +134,8 @@ Validity ConditionalCursorMove::get_validity( const Framebuffer &fb, return Pending; } -void ConditionalCursorMove::apply( Framebuffer &fb, - uint64_t confirmed_epoch ) const { +void ConditionalCursorMove::apply( Framebuffer& fb, uint64_t confirmed_epoch ) const +{ if ( !active ) { return; } @@ -157,29 +153,30 @@ void ConditionalCursorMove::apply( Framebuffer &fb, } NotificationEngine::NotificationEngine() - : last_word_from_server( timestamp() ), - last_acked_state( timestamp() ), - escape_key_string(), - message(), - message_is_network_error( false ), - message_expiration( -1 ), - show_quit_keystroke( true ) {} - -static std::string human_readable_duration( int num_seconds, - const std::string &seconds_abbr ) { - char tmp[ 128 ]; + : last_word_from_server( timestamp() ) + , last_acked_state( timestamp() ) + , escape_key_string() + , message() + , message_is_network_error( false ) + , message_expiration( -1 ) + , show_quit_keystroke( true ) +{} + +static std::string human_readable_duration( int num_seconds, const std::string& seconds_abbr ) +{ + char tmp[128]; if ( num_seconds < 60 ) { snprintf( tmp, 128, "%d %s", num_seconds, seconds_abbr.c_str() ); } else if ( num_seconds < 3600 ) { snprintf( tmp, 128, "%d:%02d", num_seconds / 60, num_seconds % 60 ); } else { - snprintf( tmp, 128, "%d:%02d:%02d", num_seconds / 3600, - ( num_seconds / 60 ) % 60, num_seconds % 60 ); + snprintf( tmp, 128, "%d:%02d:%02d", num_seconds / 3600, ( num_seconds / 60 ) % 60, num_seconds % 60 ); } return tmp; } -void NotificationEngine::apply( Framebuffer &fb ) const { +void NotificationEngine::apply( Framebuffer& fb ) const +{ uint64_t now = timestamp(); bool time_expired = need_countup( now ); @@ -207,7 +204,7 @@ void NotificationEngine::apply( Framebuffer &fb ) const { } /* write message */ - wchar_t tmp[ 128 ]; + wchar_t tmp[128]; /* We want to prefer the "last contact" message if we simply haven't heard from the server in a while, but print the "last reply" message @@ -219,7 +216,7 @@ void NotificationEngine::apply( Framebuffer &fb ) const { const char reply_message[] = "reply"; double time_elapsed = since_heard; - const char *explanation = server_message; + const char* explanation = server_message; if ( reply_late( now ) && ( !server_late( now ) ) ) { time_elapsed = since_ack; @@ -228,88 +225,93 @@ void NotificationEngine::apply( Framebuffer &fb ) const { const static char blank[] = ""; - const char *keystroke_str = - show_quit_keystroke ? escape_key_string.c_str() : blank; + const char* keystroke_str = show_quit_keystroke ? escape_key_string.c_str() : blank; if ( message.empty() && ( !time_expired ) ) { return; } if ( message.empty() && time_expired ) { - swprintf( - tmp, 128, L"mosh: Last %s %s ago.%s", explanation, - human_readable_duration( static_cast( time_elapsed ), "seconds" ) - .c_str(), - keystroke_str ); + swprintf( tmp, + 128, + L"mosh: Last %s %s ago.%s", + explanation, + human_readable_duration( static_cast( time_elapsed ), "seconds" ).c_str(), + keystroke_str ); } else if ( ( !message.empty() ) && ( !time_expired ) ) { swprintf( tmp, 128, L"mosh: %ls%s", message.c_str(), keystroke_str ); } else { - swprintf( tmp, 128, L"mosh: %ls (%s without %s.)%s", message.c_str(), - human_readable_duration( static_cast( time_elapsed ), "s" ) - .c_str(), - explanation, keystroke_str ); + swprintf( tmp, + 128, + L"mosh: %ls (%s without %s.)%s", + message.c_str(), + human_readable_duration( static_cast( time_elapsed ), "s" ).c_str(), + explanation, + keystroke_str ); } wstring string_to_draw( tmp ); int overlay_col = 0; - Cell *combining_cell = fb.get_mutable_cell( 0, 0 ); + Cell* combining_cell = fb.get_mutable_cell( 0, 0 ); - /* We unfortunately duplicate the terminal's logic for how to render a Unicode - * sequence into graphemes */ - for ( wstring::const_iterator i = string_to_draw.begin(); - i != string_to_draw.end(); i++ ) { + /* We unfortunately duplicate the terminal's logic for how to render a Unicode sequence into graphemes */ + for ( wstring::const_iterator i = string_to_draw.begin(); i != string_to_draw.end(); i++ ) { if ( overlay_col >= fb.ds.get_width() ) { break; } wchar_t ch = *i; int chwidth = ch == L'\0' ? -1 : wcwidth( ch ); - Cell *this_cell = 0; + Cell* this_cell = 0; switch ( chwidth ) { - case 1: /* normal character */ - case 2: /* wide character */ - this_cell = fb.get_mutable_cell( 0, overlay_col ); - fb.reset_cell( this_cell ); - this_cell->get_renditions().set_attribute( Renditions::bold, true ); - this_cell->get_renditions().set_foreground_color( 7 ); - this_cell->get_renditions().set_background_color( 4 ); - - this_cell->append( ch ); - this_cell->set_wide( chwidth == 2 ); - combining_cell = this_cell; - - overlay_col += chwidth; - break; - case 0: /* combining character */ - if ( !combining_cell ) { + case 1: /* normal character */ + case 2: /* wide character */ + this_cell = fb.get_mutable_cell( 0, overlay_col ); + fb.reset_cell( this_cell ); + this_cell->get_renditions().set_attribute( Renditions::bold, true ); + this_cell->get_renditions().set_foreground_color( 7 ); + this_cell->get_renditions().set_background_color( 4 ); + + this_cell->append( ch ); + this_cell->set_wide( chwidth == 2 ); + combining_cell = this_cell; + + overlay_col += chwidth; break; - } + case 0: /* combining character */ + if ( !combining_cell ) { + break; + } - if ( combining_cell->empty() ) { - assert( !combining_cell->get_wide() ); - combining_cell->set_fallback( true ); - overlay_col++; - } + if ( combining_cell->empty() ) { + assert( !combining_cell->get_wide() ); + combining_cell->set_fallback( true ); + overlay_col++; + } - if ( !combining_cell->full() ) { - combining_cell->append( ch ); - } - break; - case -1: /* unprintable character */ break; - default: assert( !"unexpected character width from wcwidth()" ); + if ( !combining_cell->full() ) { + combining_cell->append( ch ); + } + break; + case -1: /* unprintable character */ + break; + default: + assert( !"unexpected character width from wcwidth()" ); } } } -void NotificationEngine::adjust_message( void ) { +void NotificationEngine::adjust_message( void ) +{ if ( timestamp() >= message_expiration ) { message.clear(); } } -int NotificationEngine::wait_time( void ) const { +int NotificationEngine::wait_time( void ) const +{ uint64_t next_expiry = INT_MAX; uint64_t now = timestamp(); @@ -329,7 +331,8 @@ int NotificationEngine::wait_time( void ) const { return next_expiry; } -void OverlayManager::apply( Framebuffer &fb ) { +void OverlayManager::apply( Framebuffer& fb ) +{ predictions.cull( fb ); predictions.apply( fb ); notifications.adjust_message(); @@ -337,37 +340,37 @@ void OverlayManager::apply( Framebuffer &fb ) { title.apply( fb ); } -void TitleEngine::set_prefix( const wstring &s ) { +void TitleEngine::set_prefix( const wstring& s ) +{ prefix = Terminal::Framebuffer::title_type( s.begin(), s.end() ); } -void ConditionalOverlayRow::apply( Framebuffer &fb, uint64_t confirmed_epoch, - bool flag ) const { - for ( overlay_cells_type::const_iterator it = overlay_cells.begin(); - it != overlay_cells.end(); it++ ) { +void ConditionalOverlayRow::apply( Framebuffer& fb, uint64_t confirmed_epoch, bool flag ) const +{ + for ( overlay_cells_type::const_iterator it = overlay_cells.begin(); it != overlay_cells.end(); it++ ) { it->apply( fb, confirmed_epoch, row_num, flag ); } } -void PredictionEngine::apply( Framebuffer &fb ) const { +void PredictionEngine::apply( Framebuffer& fb ) const +{ if ( ( display_preference == Never ) || !( srtt_trigger || glitch_trigger || ( display_preference == Always ) || ( display_preference == Experimental ) ) ) { return; } - for ( cursors_type::const_iterator it = cursors.begin(); it != cursors.end(); - it++ ) { + for ( cursors_type::const_iterator it = cursors.begin(); it != cursors.end(); it++ ) { it->apply( fb, confirmed_epoch ); } - for ( overlays_type::const_iterator it = overlays.begin(); - it != overlays.end(); it++ ) { + for ( overlays_type::const_iterator it = overlays.begin(); it != overlays.end(); it++ ) { it->apply( fb, confirmed_epoch, flagging ); } } -void PredictionEngine::kill_epoch( uint64_t epoch, const Framebuffer &fb ) { +void PredictionEngine::kill_epoch( uint64_t epoch, const Framebuffer& fb ) +{ for ( cursors_type::iterator it = cursors.begin(); it != cursors.end(); ) { cursors_type::iterator it_next = it; it_next++; @@ -377,15 +380,12 @@ void PredictionEngine::kill_epoch( uint64_t epoch, const Framebuffer &fb ) { it = it_next; } - cursors.push_back( - ConditionalCursorMove( local_frame_sent + 1, fb.ds.get_cursor_row(), - fb.ds.get_cursor_col(), prediction_epoch ) ); + cursors.push_back( ConditionalCursorMove( + local_frame_sent + 1, fb.ds.get_cursor_row(), fb.ds.get_cursor_col(), prediction_epoch ) ); cursor().active = true; - for ( overlays_type::iterator i = overlays.begin(); i != overlays.end(); - i++ ) { - for ( overlay_cells_type::iterator j = i->overlay_cells.begin(); - j != i->overlay_cells.end(); j++ ) { + for ( overlays_type::iterator i = overlays.begin(); i != overlays.end(); i++ ) { + for ( overlay_cells_type::iterator j = i->overlay_cells.begin(); j != i->overlay_cells.end(); j++ ) { if ( j->tentative( epoch - 1 ) ) { j->reset(); } @@ -395,7 +395,8 @@ void PredictionEngine::kill_epoch( uint64_t epoch, const Framebuffer &fb ) { become_tentative(); } -void PredictionEngine::reset( void ) { +void PredictionEngine::reset( void ) +{ cursors.clear(); overlays.clear(); become_tentative(); @@ -403,30 +404,30 @@ void PredictionEngine::reset( void ) { // fprintf( stderr, "RESETTING\n" ); } -void PredictionEngine::init_cursor( const Framebuffer &fb ) { +void PredictionEngine::init_cursor( const Framebuffer& fb ) +{ if ( cursors.empty() ) { /* initialize new cursor prediction */ - cursors.push_back( - ConditionalCursorMove( local_frame_sent + 1, fb.ds.get_cursor_row(), - fb.ds.get_cursor_col(), prediction_epoch ) ); + cursors.push_back( ConditionalCursorMove( + local_frame_sent + 1, fb.ds.get_cursor_row(), fb.ds.get_cursor_col(), prediction_epoch ) ); cursor().active = true; } else if ( cursor().tentative_until_epoch != prediction_epoch ) { - cursors.push_back( ConditionalCursorMove( - local_frame_sent + 1, cursor().row, cursor().col, prediction_epoch ) ); + cursors.push_back( + ConditionalCursorMove( local_frame_sent + 1, cursor().row, cursor().col, prediction_epoch ) ); cursor().active = true; } } -void PredictionEngine::cull( const Framebuffer &fb ) { +void PredictionEngine::cull( const Framebuffer& fb ) +{ if ( display_preference == Never ) { return; } - if ( ( last_height != fb.ds.get_height() ) - || ( last_width != fb.ds.get_width() ) ) { + if ( ( last_height != fb.ds.get_height() ) || ( last_width != fb.ds.get_width() ) ) { last_height = fb.ds.get_height(); last_width = fb.ds.get_width(); reset(); @@ -437,11 +438,8 @@ void PredictionEngine::cull( const Framebuffer &fb ) { /* control srtt_trigger with hysteresis */ if ( send_interval > SRTT_TRIGGER_HIGH ) { srtt_trigger = true; - } else if ( srtt_trigger - && ( send_interval - <= SRTT_TRIGGER_LOW ) /* 20 ms is current minimum value */ - && ( !active() ) ) { /* only turn off when no predictions being - shown */ + } else if ( srtt_trigger && ( send_interval <= SRTT_TRIGGER_LOW ) /* 20 ms is current minimum value */ + && ( !active() ) ) { /* only turn off when no predictions being shown */ srtt_trigger = false; } @@ -469,106 +467,101 @@ void PredictionEngine::cull( const Framebuffer &fb ) { continue; } - for ( overlay_cells_type::iterator j = i->overlay_cells.begin(); - j != i->overlay_cells.end(); j++ ) { - switch ( j->get_validity( fb, i->row_num, local_frame_acked, - local_frame_late_acked ) ) { - case IncorrectOrExpired: - if ( j->tentative( confirmed_epoch ) ) { - - /* - fprintf( stderr, "Bad tentative prediction in row %d, col %d (think - %lc, actually %lc)\n", i->row_num, j->col, - j->replacement.debug_contents(), - fb.get_cell( i->row_num, j->col )->debug_contents() - ); - */ - - if ( display_preference == Experimental ) { - j->reset(); + for ( overlay_cells_type::iterator j = i->overlay_cells.begin(); j != i->overlay_cells.end(); j++ ) { + switch ( j->get_validity( fb, i->row_num, local_frame_acked, local_frame_late_acked ) ) { + case IncorrectOrExpired: + if ( j->tentative( confirmed_epoch ) ) { + + /* + fprintf( stderr, "Bad tentative prediction in row %d, col %d (think %lc, actually %lc)\n", + i->row_num, j->col, + j->replacement.debug_contents(), + fb.get_cell( i->row_num, j->col )->debug_contents() + ); + */ + + if ( display_preference == Experimental ) { + j->reset(); + } else { + kill_epoch( j->tentative_until_epoch, fb ); + } + /* + if ( j->display_time != uint64_t(-1) ) { + fprintf( stderr, "TIMING %ld - %ld (TENT)\n", time(NULL), now - j->display_time ); + } + */ } else { - kill_epoch( j->tentative_until_epoch, fb ); - } - /* - if ( j->display_time != uint64_t(-1) ) { - fprintf( stderr, "TIMING %ld - %ld (TENT)\n", time(NULL), now - - j->display_time ); + /* + fprintf( stderr, "[%d=>%d] Killing prediction in row %d, col %d (think %lc, actually %lc)\n", + (int)local_frame_acked, (int)j->expiration_frame, + i->row_num, j->col, + j->replacement.debug_contents(), + fb.get_cell( i->row_num, j->col )->debug_contents() ); + */ + /* + if ( j->display_time != uint64_t(-1) ) { + fprintf( stderr, "TIMING %ld - %ld\n", time(NULL), now - j->display_time ); + } + */ + + if ( display_preference == Experimental ) { + j->reset(); + } else { + reset(); + return; + } } - */ - } else { - /* - fprintf( stderr, "[%d=>%d] Killing prediction in row %d, col %d (think - %lc, actually %lc)\n", (int)local_frame_acked, - (int)j->expiration_frame, i->row_num, j->col, - j->replacement.debug_contents(), - fb.get_cell( i->row_num, j->col )->debug_contents() ); - */ + break; + case Correct: /* if ( j->display_time != uint64_t(-1) ) { - fprintf( stderr, "TIMING %ld - %ld\n", time(NULL), now - - j->display_time ); + fprintf( stderr, "TIMING %ld + %ld\n", now, now - j->display_time ); } */ - if ( display_preference == Experimental ) { - j->reset(); - } else { - reset(); - return; - } - } - break; - case Correct: - /* - if ( j->display_time != uint64_t(-1) ) { - fprintf( stderr, "TIMING %ld + %ld\n", now, now - j->display_time ); - } - */ - - if ( j->tentative_until_epoch > confirmed_epoch ) { - confirmed_epoch = j->tentative_until_epoch; + if ( j->tentative_until_epoch > confirmed_epoch ) { + confirmed_epoch = j->tentative_until_epoch; - /* - fprintf( stderr, "%lc in (%d,%d) confirms epoch %lu (predicting in - epoch %lu)\n", j->replacement.debug_contents(), i->row_num, j->col, - confirmed_epoch, prediction_epoch ); - */ - } + /* + fprintf( stderr, "%lc in (%d,%d) confirms epoch %lu (predicting in epoch %lu)\n", + j->replacement.debug_contents(), i->row_num, j->col, + confirmed_epoch, prediction_epoch ); + */ + } - /* When predictions come in quickly, slowly take away the glitch - * trigger. */ - if ( now - j->prediction_time < GLITCH_THRESHOLD - && ( glitch_trigger > 0 - && now - GLITCH_REPAIR_MININTERVAL - >= last_quick_confirmation ) ) { - glitch_trigger--; - last_quick_confirmation = now; - } + /* When predictions come in quickly, slowly take away the glitch trigger. */ + if ( now - j->prediction_time < GLITCH_THRESHOLD + && ( glitch_trigger > 0 && now - GLITCH_REPAIR_MININTERVAL >= last_quick_confirmation ) ) { + glitch_trigger--; + last_quick_confirmation = now; + } - /* match rest of row to the actual renditions */ - { - const Renditions &actual_renditions = - fb.get_cell( i->row_num, j->col )->get_renditions(); - for ( overlay_cells_type::iterator k = j; k != i->overlay_cells.end(); - k++ ) { - k->replacement.get_renditions() = actual_renditions; + /* match rest of row to the actual renditions */ + { + const Renditions& actual_renditions = fb.get_cell( i->row_num, j->col )->get_renditions(); + for ( overlay_cells_type::iterator k = j; k != i->overlay_cells.end(); k++ ) { + k->replacement.get_renditions() = actual_renditions; + } } - } - /* fallthrough */ - case CorrectNoCredit: j->reset(); break; - case Pending: - /* When a prediction takes a long time to be confirmed, we - activate the predictions even if SRTT is low */ - if ( ( now - j->prediction_time ) >= GLITCH_FLAG_THRESHOLD ) { - glitch_trigger = GLITCH_REPAIR_COUNT * 2; /* display and underline */ - } else if ( ( ( now - j->prediction_time ) >= GLITCH_THRESHOLD ) - && ( glitch_trigger < GLITCH_REPAIR_COUNT ) ) { - glitch_trigger = GLITCH_REPAIR_COUNT; /* just display */ - } + /* fallthrough */ + case CorrectNoCredit: + j->reset(); + + break; + case Pending: + /* When a prediction takes a long time to be confirmed, we + activate the predictions even if SRTT is low */ + if ( ( now - j->prediction_time ) >= GLITCH_FLAG_THRESHOLD ) { + glitch_trigger = GLITCH_REPAIR_COUNT * 2; /* display and underline */ + } else if ( ( ( now - j->prediction_time ) >= GLITCH_THRESHOLD ) + && ( glitch_trigger < GLITCH_REPAIR_COUNT ) ) { + glitch_trigger = GLITCH_REPAIR_COUNT; /* just display */ + } - break; - default: break; + break; + default: + break; } } @@ -577,11 +570,10 @@ void PredictionEngine::cull( const Framebuffer &fb ) { /* go through cursor predictions */ if ( !cursors.empty() - && cursor().get_validity( fb, local_frame_acked, local_frame_late_acked ) - == IncorrectOrExpired ) { + && cursor().get_validity( fb, local_frame_acked, local_frame_late_acked ) == IncorrectOrExpired ) { /* - fprintf( stderr, "Sadly, we're predicting (%d,%d) vs. (%d,%d) [tau: %ld, - expiration_time=%ld, now=%ld]\n", cursor().row, cursor().col, + fprintf( stderr, "Sadly, we're predicting (%d,%d) vs. (%d,%d) [tau: %ld, expiration_time=%ld, now=%ld]\n", + cursor().row, cursor().col, fb.ds.get_cursor_row(), fb.ds.get_cursor_col(), cursor().tentative_until_epoch, @@ -598,10 +590,8 @@ void PredictionEngine::cull( const Framebuffer &fb ) { /* NB: switching from list to another STL container could break this code. So we don't use the cursors_type typedef. */ - for ( list::iterator it = cursors.begin(); - it != cursors.end(); ) { - if ( it->get_validity( fb, local_frame_acked, local_frame_late_acked ) - != Pending ) { + for ( list::iterator it = cursors.begin(); it != cursors.end(); ) { + if ( it->get_validity( fb, local_frame_acked, local_frame_late_acked ) != Pending ) { it = cursors.erase( it ); } else { it++; @@ -609,8 +599,8 @@ void PredictionEngine::cull( const Framebuffer &fb ) { } } -ConditionalOverlayRow &PredictionEngine::get_or_make_row( int row_num, - int num_cols ) { +ConditionalOverlayRow& PredictionEngine::get_or_make_row( int row_num, int num_cols ) +{ overlays_type::iterator it; for ( it = overlays.begin(); it != overlays.end(); it++ ) { @@ -626,15 +616,15 @@ ConditionalOverlayRow &PredictionEngine::get_or_make_row( int row_num, ConditionalOverlayRow r( row_num ); r.overlay_cells.reserve( num_cols ); for ( int i = 0; i < num_cols; i++ ) { - r.overlay_cells.push_back( - ConditionalOverlayCell( 0, i, prediction_epoch ) ); - assert( r.overlay_cells[ i ].col == i ); + r.overlay_cells.push_back( ConditionalOverlayCell( 0, i, prediction_epoch ) ); + assert( r.overlay_cells[i].col == i ); } overlays.push_back( r ); return overlays.back(); } -void PredictionEngine::new_user_byte( char the_byte, const Framebuffer &fb ) { +void PredictionEngine::new_user_byte( char the_byte, const Framebuffer& fb ) +{ if ( display_preference == Never ) { return; } @@ -646,8 +636,7 @@ void PredictionEngine::new_user_byte( char the_byte, const Framebuffer &fb ) { uint64_t now = timestamp(); - /* translate application-mode cursor control function to ANSI cursor control - * sequence */ + /* translate application-mode cursor control function to ANSI cursor control sequence */ if ( ( last_byte == 0x1b ) && ( the_byte == 'O' ) ) { the_byte = '['; } @@ -656,16 +645,15 @@ void PredictionEngine::new_user_byte( char the_byte, const Framebuffer &fb ) { Parser::Actions actions; parser.input( the_byte, actions ); - for ( Parser::Actions::iterator it = actions.begin(); it != actions.end(); - it++ ) { - Parser::Action &act = **it; + for ( Parser::Actions::iterator it = actions.begin(); it != actions.end(); it++ ) { + Parser::Action& act = **it; /* fprintf( stderr, "Action: %s (%lc)\n", act->name().c_str(), act->char_present ? act->ch : L'_' ); */ - const std::type_info &type_act = typeid( act ); + const std::type_info& type_act = typeid( act ); if ( type_act == typeid( Parser::Print ) ) { /* make new prediction */ @@ -678,16 +666,14 @@ void PredictionEngine::new_user_byte( char the_byte, const Framebuffer &fb ) { if ( ch == 0x7f ) { /* backspace */ // fprintf( stderr, "Backspace.\n" ); - ConditionalOverlayRow &the_row = - get_or_make_row( cursor().row, fb.ds.get_width() ); + ConditionalOverlayRow& the_row = get_or_make_row( cursor().row, fb.ds.get_width() ); if ( cursor().col > 0 ) { cursor().col--; cursor().expire( local_frame_sent + 1, now ); if ( predict_overwrite ) { - ConditionalOverlayCell &cell = - the_row.overlay_cells[ cursor().col ]; + ConditionalOverlayCell& cell = the_row.overlay_cells[cursor().col]; cell.reset_with_orig(); cell.active = true; cell.tentative_until_epoch = prediction_epoch; @@ -699,20 +685,17 @@ void PredictionEngine::new_user_byte( char the_byte, const Framebuffer &fb ) { cell.replacement.append( ' ' ); } else { for ( int i = cursor().col; i < fb.ds.get_width(); i++ ) { - ConditionalOverlayCell &cell = the_row.overlay_cells[ i ]; + ConditionalOverlayCell& cell = the_row.overlay_cells[i]; cell.reset_with_orig(); cell.active = true; cell.tentative_until_epoch = prediction_epoch; cell.expire( local_frame_sent + 1, now ); - cell.original_contents.push_back( - *fb.get_cell( cursor().row, i ) ); + cell.original_contents.push_back( *fb.get_cell( cursor().row, i ) ); if ( i + 2 < fb.ds.get_width() ) { - ConditionalOverlayCell &next_cell = - the_row.overlay_cells[ i + 1 ]; - const Cell *next_cell_actual = - fb.get_cell( cursor().row, i + 1 ); + ConditionalOverlayCell& next_cell = the_row.overlay_cells[i + 1]; + const Cell* next_cell_actual = fb.get_cell( cursor().row, i + 1 ); if ( next_cell.active ) { if ( next_cell.unknown ) { @@ -741,29 +724,26 @@ void PredictionEngine::new_user_byte( char the_byte, const Framebuffer &fb ) { assert( cursor().row < fb.ds.get_height() ); assert( cursor().col < fb.ds.get_width() ); - ConditionalOverlayRow &the_row = - get_or_make_row( cursor().row, fb.ds.get_width() ); + ConditionalOverlayRow& the_row = get_or_make_row( cursor().row, fb.ds.get_width() ); if ( cursor().col + 1 >= fb.ds.get_width() ) { /* prediction in the last column is tricky */ - /* e.g., emacs will show wrap character, shell will just put the - * character there */ + /* e.g., emacs will show wrap character, shell will just put the character there */ become_tentative(); } /* do the insert */ - int rightmost_column = - predict_overwrite ? cursor().col : fb.ds.get_width() - 1; + int rightmost_column = predict_overwrite ? cursor().col : fb.ds.get_width() - 1; for ( int i = rightmost_column; i > cursor().col; i-- ) { - ConditionalOverlayCell &cell = the_row.overlay_cells[ i ]; + ConditionalOverlayCell& cell = the_row.overlay_cells[i]; cell.reset_with_orig(); cell.active = true; cell.tentative_until_epoch = prediction_epoch; cell.expire( local_frame_sent + 1, now ); cell.original_contents.push_back( *fb.get_cell( cursor().row, i ) ); - ConditionalOverlayCell &prev_cell = the_row.overlay_cells[ i - 1 ]; - const Cell *prev_cell_actual = fb.get_cell( cursor().row, i - 1 ); + ConditionalOverlayCell& prev_cell = the_row.overlay_cells[i - 1]; + const Cell* prev_cell_actual = fb.get_cell( cursor().row, i - 1 ); if ( i == fb.ds.get_width() - 1 ) { cell.unknown = true; @@ -780,7 +760,7 @@ void PredictionEngine::new_user_byte( char the_byte, const Framebuffer &fb ) { } } - ConditionalOverlayCell &cell = the_row.overlay_cells[ cursor().col ]; + ConditionalOverlayCell& cell = the_row.overlay_cells[cursor().col]; cell.reset_with_orig(); cell.active = true; cell.tentative_until_epoch = prediction_epoch; @@ -789,28 +769,24 @@ void PredictionEngine::new_user_byte( char the_byte, const Framebuffer &fb ) { /* heuristic: match renditions of character to the left */ if ( cursor().col > 0 ) { - ConditionalOverlayCell &prev_cell = - the_row.overlay_cells[ cursor().col - 1 ]; - const Cell *prev_cell_actual = - fb.get_cell( cursor().row, cursor().col - 1 ); + ConditionalOverlayCell& prev_cell = the_row.overlay_cells[cursor().col - 1]; + const Cell* prev_cell_actual = fb.get_cell( cursor().row, cursor().col - 1 ); if ( prev_cell.active && ( !prev_cell.unknown ) ) { - cell.replacement.get_renditions() = - prev_cell.replacement.get_renditions(); + cell.replacement.get_renditions() = prev_cell.replacement.get_renditions(); } else { - cell.replacement.get_renditions() = - prev_cell_actual->get_renditions(); + cell.replacement.get_renditions() = prev_cell_actual->get_renditions(); } } cell.replacement.clear(); cell.replacement.append( ch ); - cell.original_contents.push_back( - *fb.get_cell( cursor().row, cursor().col ) ); + cell.original_contents.push_back( *fb.get_cell( cursor().row, cursor().col ) ); /* - fprintf( stderr, "[%d=>%d] Predicting %lc in row %d, col %d [tue: - %lu]\n", (int)local_frame_acked, (int)cell.expiration_frame, ch, - cursor().row, cursor().col, cell.tentative_until_epoch ); + fprintf( stderr, "[%d=>%d] Predicting %lc in row %d, col %d [tue: %lu]\n", + (int)local_frame_acked, (int)cell.expiration_frame, + ch, cursor().row, cursor().col, + cell.tentative_until_epoch ); */ cursor().expire( local_frame_sent + 1, now ); @@ -856,7 +832,8 @@ void PredictionEngine::new_user_byte( char the_byte, const Framebuffer &fb ) { } } -void PredictionEngine::newline_carriage_return( const Framebuffer &fb ) { +void PredictionEngine::newline_carriage_return( const Framebuffer& fb ) +{ uint64_t now = timestamp(); init_cursor( fb ); cursor().col = 0; @@ -878,10 +855,8 @@ void PredictionEngine::newline_carriage_return( const Framebuffer &fb ) { */ /* make blank prediction for last row */ - ConditionalOverlayRow &the_row = - get_or_make_row( cursor().row, fb.ds.get_width() ); - for ( overlay_cells_type::iterator j = the_row.overlay_cells.begin(); - j != the_row.overlay_cells.end(); j++ ) { + ConditionalOverlayRow& the_row = get_or_make_row( cursor().row, fb.ds.get_width() ); + for ( overlay_cells_type::iterator j = the_row.overlay_cells.begin(); j != the_row.overlay_cells.end(); j++ ) { j->active = true; j->tentative_until_epoch = prediction_epoch; j->expire( local_frame_sent + 1, now ); @@ -892,7 +867,8 @@ void PredictionEngine::newline_carriage_return( const Framebuffer &fb ) { } } -void PredictionEngine::become_tentative( void ) { +void PredictionEngine::become_tentative( void ) +{ if ( display_preference != Experimental ) { prediction_epoch++; } @@ -903,15 +879,14 @@ void PredictionEngine::become_tentative( void ) { */ } -bool PredictionEngine::active( void ) const { +bool PredictionEngine::active( void ) const +{ if ( !cursors.empty() ) { return true; } - for ( overlays_type::const_iterator i = overlays.begin(); i != overlays.end(); - i++ ) { - for ( overlay_cells_type::const_iterator j = i->overlay_cells.begin(); - j != i->overlay_cells.end(); j++ ) { + for ( overlays_type::const_iterator i = overlays.begin(); i != overlays.end(); i++ ) { + for ( overlay_cells_type::const_iterator j = i->overlay_cells.begin(); j != i->overlay_cells.end(); j++ ) { if ( j->active ) { return true; } diff --git a/src/frontend/terminaloverlay.h b/src/frontend/terminaloverlay.h index 359f48196..980ad865f 100644 --- a/src/frontend/terminaloverlay.h +++ b/src/frontend/terminaloverlay.h @@ -42,338 +42,341 @@ #include namespace Overlay { - using namespace Terminal; - using namespace Network; - using std::deque; - using std::list; - using std::vector; - using std::wstring; - - enum Validity { - Pending, - Correct, - CorrectNoCredit, - IncorrectOrExpired, - Inactive - }; - - class ConditionalOverlay { - public: - uint64_t expiration_frame; - int col; - bool active; /* represents a prediction at all */ - uint64_t tentative_until_epoch; /* when to show */ - uint64_t prediction_time; /* used to find long-pending predictions */ - - ConditionalOverlay( uint64_t s_exp, int s_col, uint64_t s_tentative ) - : expiration_frame( s_exp ), - col( s_col ), - active( false ), - tentative_until_epoch( s_tentative ), - prediction_time( uint64_t( -1 ) ) {} - - virtual ~ConditionalOverlay() {} - - bool tentative( uint64_t confirmed_epoch ) const { - return tentative_until_epoch > confirmed_epoch; - } - void reset( void ) { - expiration_frame = tentative_until_epoch = -1; - active = false; - } - void expire( uint64_t s_exp, uint64_t now ) { - expiration_frame = s_exp; - prediction_time = now; - } - }; - - class ConditionalCursorMove : public ConditionalOverlay { - public: - int row; - - void apply( Framebuffer &fb, uint64_t confirmed_epoch ) const; - - Validity get_validity( const Framebuffer &fb, uint64_t early_ack, - uint64_t late_ack ) const; - - ConditionalCursorMove( uint64_t s_exp, int s_row, int s_col, - uint64_t s_tentative ) - : ConditionalOverlay( s_exp, s_col, s_tentative ), row( s_row ) {} - }; - - class ConditionalOverlayCell : public ConditionalOverlay { - public: - Cell replacement; - bool unknown; - - vector - original_contents; /* we don't give credit for correct predictions - that match the original contents */ - - void apply( Framebuffer &fb, uint64_t confirmed_epoch, int row, - bool flag ) const; - Validity get_validity( const Framebuffer &fb, int row, uint64_t early_ack, - uint64_t late_ack ) const; - - ConditionalOverlayCell( uint64_t s_exp, int s_col, uint64_t s_tentative ) - : ConditionalOverlay( s_exp, s_col, s_tentative ), - replacement( 0 ), - unknown( false ), - original_contents() {} - - void reset( void ) { - unknown = false; - original_contents.clear(); - ConditionalOverlay::reset(); - } - void reset_with_orig( void ) { - if ( ( !active ) || unknown ) { - reset(); - return; - } - - original_contents.push_back( replacement ); - ConditionalOverlay::reset(); - } - }; - - class ConditionalOverlayRow { - public: - int row_num; - - typedef vector overlay_cells_type; - overlay_cells_type overlay_cells; - - void apply( Framebuffer &fb, uint64_t confirmed_epoch, bool flag ) const; - - ConditionalOverlayRow( int s_row_num ) - : row_num( s_row_num ), overlay_cells() {} - }; - - /* the various overlays */ - class NotificationEngine { - private: - uint64_t last_word_from_server; - uint64_t last_acked_state; - string escape_key_string; - wstring message; - bool message_is_network_error; - uint64_t message_expiration; - bool show_quit_keystroke; - - bool server_late( uint64_t ts ) const { - return ( ts - last_word_from_server ) > 6500; - } - bool reply_late( uint64_t ts ) const { - return ( ts - last_acked_state ) > 10000; - } - bool need_countup( uint64_t ts ) const { - return server_late( ts ) || reply_late( ts ); +using namespace Terminal; +using namespace Network; +using std::deque; +using std::list; +using std::vector; +using std::wstring; + +enum Validity +{ + Pending, + Correct, + CorrectNoCredit, + IncorrectOrExpired, + Inactive +}; + +class ConditionalOverlay +{ +public: + uint64_t expiration_frame; + int col; + bool active; /* represents a prediction at all */ + uint64_t tentative_until_epoch; /* when to show */ + uint64_t prediction_time; /* used to find long-pending predictions */ + + ConditionalOverlay( uint64_t s_exp, int s_col, uint64_t s_tentative ) + : expiration_frame( s_exp ) + , col( s_col ) + , active( false ) + , tentative_until_epoch( s_tentative ) + , prediction_time( uint64_t( -1 ) ) + {} + + virtual ~ConditionalOverlay() {} + + bool tentative( uint64_t confirmed_epoch ) const { return tentative_until_epoch > confirmed_epoch; } + void reset( void ) + { + expiration_frame = tentative_until_epoch = -1; + active = false; + } + void expire( uint64_t s_exp, uint64_t now ) + { + expiration_frame = s_exp; + prediction_time = now; + } +}; + +class ConditionalCursorMove : public ConditionalOverlay +{ +public: + int row; + + void apply( Framebuffer& fb, uint64_t confirmed_epoch ) const; + + Validity get_validity( const Framebuffer& fb, uint64_t early_ack, uint64_t late_ack ) const; + + ConditionalCursorMove( uint64_t s_exp, int s_row, int s_col, uint64_t s_tentative ) + : ConditionalOverlay( s_exp, s_col, s_tentative ) + , row( s_row ) + {} +}; + +class ConditionalOverlayCell : public ConditionalOverlay +{ +public: + Cell replacement; + bool unknown; + + vector original_contents; /* we don't give credit for correct predictions + that match the original contents */ + + void apply( Framebuffer& fb, uint64_t confirmed_epoch, int row, bool flag ) const; + Validity get_validity( const Framebuffer& fb, int row, uint64_t early_ack, uint64_t late_ack ) const; + + ConditionalOverlayCell( uint64_t s_exp, int s_col, uint64_t s_tentative ) + : ConditionalOverlay( s_exp, s_col, s_tentative ) + , replacement( 0 ) + , unknown( false ) + , original_contents() + {} + + void reset( void ) + { + unknown = false; + original_contents.clear(); + ConditionalOverlay::reset(); + } + void reset_with_orig( void ) + { + if ( ( !active ) || unknown ) { + reset(); + return; } - public: - void adjust_message( void ); - void apply( Framebuffer &fb ) const; - const wstring &get_notification_string( void ) const { return message; } - void server_heard( uint64_t s_last_word ) { - last_word_from_server = s_last_word; + original_contents.push_back( replacement ); + ConditionalOverlay::reset(); + } +}; + +class ConditionalOverlayRow +{ +public: + int row_num; + + typedef vector overlay_cells_type; + overlay_cells_type overlay_cells; + + void apply( Framebuffer& fb, uint64_t confirmed_epoch, bool flag ) const; + + ConditionalOverlayRow( int s_row_num ) + : row_num( s_row_num ) + , overlay_cells() + {} +}; + +/* the various overlays */ +class NotificationEngine +{ +private: + uint64_t last_word_from_server; + uint64_t last_acked_state; + string escape_key_string; + wstring message; + bool message_is_network_error; + uint64_t message_expiration; + bool show_quit_keystroke; + + bool server_late( uint64_t ts ) const { return ( ts - last_word_from_server ) > 6500; } + bool reply_late( uint64_t ts ) const { return ( ts - last_acked_state ) > 10000; } + bool need_countup( uint64_t ts ) const { return server_late( ts ) || reply_late( ts ); } + +public: + void adjust_message( void ); + void apply( Framebuffer& fb ) const; + const wstring& get_notification_string( void ) const { return message; } + void server_heard( uint64_t s_last_word ) { last_word_from_server = s_last_word; } + void server_acked( uint64_t s_last_acked ) { last_acked_state = s_last_acked; } + int wait_time( void ) const; + + void set_notification_string( const wstring& s_message, + bool permanent = false, + bool s_show_quit_keystroke = true ) + { + message = s_message; + if ( permanent ) { + message_expiration = -1; + } else { + message_expiration = timestamp() + 1000; } - void server_acked( uint64_t s_last_acked ) { - last_acked_state = s_last_acked; - } - int wait_time( void ) const; - - void set_notification_string( const wstring &s_message, - bool permanent = false, - bool s_show_quit_keystroke = true ) { - message = s_message; - if ( permanent ) { - message_expiration = -1; - } else { - message_expiration = timestamp() + 1000; - } - message_is_network_error = false; - show_quit_keystroke = s_show_quit_keystroke; + message_is_network_error = false; + show_quit_keystroke = s_show_quit_keystroke; + } + + void set_escape_key_string( const string& s_name ) + { + char tmp[128]; + snprintf( tmp, sizeof tmp, " [To quit: %s .]", s_name.c_str() ); + escape_key_string = tmp; + } + + void set_network_error( const std::string& s ) + { + wchar_t tmp[128]; + swprintf( tmp, 128, L"%s", s.c_str() ); + + message = tmp; + message_is_network_error = true; + message_expiration = timestamp() + Network::ACK_INTERVAL + 100; + } + + void clear_network_error() + { + if ( message_is_network_error ) { + message_expiration = std::min( message_expiration, timestamp() + 1000 ); } + } - void set_escape_key_string( const string &s_name ) { - char tmp[ 128 ]; - snprintf( tmp, sizeof tmp, " [To quit: %s .]", s_name.c_str() ); - escape_key_string = tmp; - } + NotificationEngine(); +}; - void set_network_error( const std::string &s ) { - wchar_t tmp[ 128 ]; - swprintf( tmp, 128, L"%s", s.c_str() ); +class PredictionEngine +{ +private: + static const uint64_t SRTT_TRIGGER_LOW = 20; /* <= ms cures SRTT trigger to show predictions */ + static const uint64_t SRTT_TRIGGER_HIGH = 30; /* > ms starts SRTT trigger */ - message = tmp; - message_is_network_error = true; - message_expiration = timestamp() + Network::ACK_INTERVAL + 100; - } + static const uint64_t FLAG_TRIGGER_LOW = 50; /* <= ms cures flagging */ + static const uint64_t FLAG_TRIGGER_HIGH = 80; /* > ms starts flagging */ - void clear_network_error() { - if ( message_is_network_error ) { - message_expiration = std::min( message_expiration, timestamp() + 1000 ); - } - } + static const uint64_t GLITCH_THRESHOLD = 250; /* prediction outstanding this long is glitch */ + static const uint64_t GLITCH_REPAIR_COUNT = 10; /* non-glitches required to cure glitch trigger */ + static const uint64_t GLITCH_REPAIR_MININTERVAL = 150; /* required time in between non-glitches */ - NotificationEngine(); - }; - - class PredictionEngine { - private: - static const uint64_t SRTT_TRIGGER_LOW = - 20; /* <= ms cures SRTT trigger to show predictions */ - static const uint64_t SRTT_TRIGGER_HIGH = 30; /* > ms starts SRTT trigger */ + static const uint64_t GLITCH_FLAG_THRESHOLD = 5000; /* prediction outstanding this long => underline */ - static const uint64_t FLAG_TRIGGER_LOW = 50; /* <= ms cures flagging */ - static const uint64_t FLAG_TRIGGER_HIGH = 80; /* > ms starts flagging */ + char last_byte; + Parser::UTF8Parser parser; - static const uint64_t GLITCH_THRESHOLD = - 250; /* prediction outstanding this long is glitch */ - static const uint64_t GLITCH_REPAIR_COUNT = - 10; /* non-glitches required to cure glitch trigger */ - static const uint64_t GLITCH_REPAIR_MININTERVAL = - 150; /* required time in between non-glitches */ + typedef list overlays_type; + overlays_type overlays; - static const uint64_t GLITCH_FLAG_THRESHOLD = - 5000; /* prediction outstanding this long => underline */ + typedef list cursors_type; + cursors_type cursors; - char last_byte; - Parser::UTF8Parser parser; + typedef ConditionalOverlayRow::overlay_cells_type overlay_cells_type; - typedef list overlays_type; - overlays_type overlays; + uint64_t local_frame_sent, local_frame_acked, local_frame_late_acked; - typedef list cursors_type; - cursors_type cursors; + ConditionalOverlayRow& get_or_make_row( int row_num, int num_cols ); - typedef ConditionalOverlayRow::overlay_cells_type overlay_cells_type; + uint64_t prediction_epoch; + uint64_t confirmed_epoch; - uint64_t local_frame_sent, local_frame_acked, local_frame_late_acked; + void become_tentative( void ); - ConditionalOverlayRow &get_or_make_row( int row_num, int num_cols ); + void newline_carriage_return( const Framebuffer& fb ); - uint64_t prediction_epoch; - uint64_t confirmed_epoch; + bool flagging; /* whether we are underlining predictions */ + bool srtt_trigger; /* show predictions because of slow round trip time */ + unsigned int glitch_trigger; /* show predictions temporarily because of long-pending prediction */ + uint64_t last_quick_confirmation; - void become_tentative( void ); + ConditionalCursorMove& cursor( void ) + { + assert( !cursors.empty() ); + return cursors.back(); + } - void newline_carriage_return( const Framebuffer &fb ); + void kill_epoch( uint64_t epoch, const Framebuffer& fb ); - bool flagging; /* whether we are underlining predictions */ - bool srtt_trigger; /* show predictions because of slow round trip time */ - unsigned int glitch_trigger; /* show predictions temporarily because of - long-pending prediction */ - uint64_t last_quick_confirmation; + void init_cursor( const Framebuffer& fb ); - ConditionalCursorMove &cursor( void ) { - assert( !cursors.empty() ); - return cursors.back(); - } + unsigned int send_interval; - void kill_epoch( uint64_t epoch, const Framebuffer &fb ); + int last_height, last_width; - void init_cursor( const Framebuffer &fb ); - - unsigned int send_interval; - - int last_height, last_width; - - public: - enum DisplayPreference { Always, Never, Adaptive, Experimental }; - - private: - DisplayPreference display_preference; - bool predict_overwrite; - - bool active( void ) const; - - bool timing_tests_necessary( void ) const { - /* Are there any timing-based triggers that haven't fired yet? */ - return !( glitch_trigger && flagging ); - } - - public: - void set_display_preference( DisplayPreference s_pref ) { - display_preference = s_pref; - } - void set_predict_overwrite( bool overwrite ) { - predict_overwrite = overwrite; - } - - void apply( Framebuffer &fb ) const; - void new_user_byte( char the_byte, const Framebuffer &fb ); - void cull( const Framebuffer &fb ); - - void reset( void ); - - void set_local_frame_sent( uint64_t x ) { local_frame_sent = x; } - void set_local_frame_acked( uint64_t x ) { local_frame_acked = x; } - void set_local_frame_late_acked( uint64_t x ) { - local_frame_late_acked = x; - } - - void set_send_interval( unsigned int x ) { send_interval = x; } - - int wait_time( void ) const { - return ( timing_tests_necessary() && active() ) ? 50 : INT_MAX; - } - - PredictionEngine( void ) - : last_byte( 0 ), - parser(), - overlays(), - cursors(), - local_frame_sent( 0 ), - local_frame_acked( 0 ), - local_frame_late_acked( 0 ), - prediction_epoch( 1 ), - confirmed_epoch( 0 ), - flagging( false ), - srtt_trigger( false ), - glitch_trigger( 0 ), - last_quick_confirmation( 0 ), - send_interval( 250 ), - last_height( 0 ), - last_width( 0 ), - display_preference( Adaptive ), - predict_overwrite( false ) {} +public: + enum DisplayPreference + { + Always, + Never, + Adaptive, + Experimental }; - class TitleEngine { - private: - Terminal::Framebuffer::title_type prefix; - - public: - void apply( Framebuffer &fb ) const { fb.prefix_window_title( prefix ); } - TitleEngine() : prefix() {} - void set_prefix( const wstring &s ); - }; - - /* the overlay manager */ - class OverlayManager { - private: - NotificationEngine notifications; - PredictionEngine predictions; - TitleEngine title; - - public: - void apply( Framebuffer &fb ); - - NotificationEngine &get_notification_engine( void ) { - return notifications; - } - PredictionEngine &get_prediction_engine( void ) { return predictions; } - - void set_title_prefix( const wstring &s ) { title.set_prefix( s ); } - - OverlayManager() : notifications(), predictions(), title() {} - - int wait_time( void ) const { - return std::min( notifications.wait_time(), predictions.wait_time() ); - } - }; +private: + DisplayPreference display_preference; + bool predict_overwrite; + + bool active( void ) const; + + bool timing_tests_necessary( void ) const + { + /* Are there any timing-based triggers that haven't fired yet? */ + return !( glitch_trigger && flagging ); + } + +public: + void set_display_preference( DisplayPreference s_pref ) { display_preference = s_pref; } + void set_predict_overwrite( bool overwrite ) { predict_overwrite = overwrite; } + + void apply( Framebuffer& fb ) const; + void new_user_byte( char the_byte, const Framebuffer& fb ); + void cull( const Framebuffer& fb ); + + void reset( void ); + + void set_local_frame_sent( uint64_t x ) { local_frame_sent = x; } + void set_local_frame_acked( uint64_t x ) { local_frame_acked = x; } + void set_local_frame_late_acked( uint64_t x ) { local_frame_late_acked = x; } + + void set_send_interval( unsigned int x ) { send_interval = x; } + + int wait_time( void ) const { return ( timing_tests_necessary() && active() ) ? 50 : INT_MAX; } + + PredictionEngine( void ) + : last_byte( 0 ) + , parser() + , overlays() + , cursors() + , local_frame_sent( 0 ) + , local_frame_acked( 0 ) + , local_frame_late_acked( 0 ) + , prediction_epoch( 1 ) + , confirmed_epoch( 0 ) + , flagging( false ) + , srtt_trigger( false ) + , glitch_trigger( 0 ) + , last_quick_confirmation( 0 ) + , send_interval( 250 ) + , last_height( 0 ) + , last_width( 0 ) + , display_preference( Adaptive ) + , predict_overwrite( false ) + {} +}; + +class TitleEngine +{ +private: + Terminal::Framebuffer::title_type prefix; + +public: + void apply( Framebuffer& fb ) const { fb.prefix_window_title( prefix ); } + TitleEngine() + : prefix() + {} + void set_prefix( const wstring& s ); +}; + +/* the overlay manager */ +class OverlayManager +{ +private: + NotificationEngine notifications; + PredictionEngine predictions; + TitleEngine title; + +public: + void apply( Framebuffer& fb ); + + NotificationEngine& get_notification_engine( void ) { return notifications; } + PredictionEngine& get_prediction_engine( void ) { return predictions; } + + void set_title_prefix( const wstring& s ) { title.set_prefix( s ); } + + OverlayManager() + : notifications() + , predictions() + , title() + {} + + int wait_time( void ) const { return std::min( notifications.wait_time(), predictions.wait_time() ); } +}; } #endif diff --git a/src/fuzz/terminal_fuzzer.cc b/src/fuzz/terminal_fuzzer.cc index c0184f63a..0f15ce017 100644 --- a/src/fuzz/terminal_fuzzer.cc +++ b/src/fuzz/terminal_fuzzer.cc @@ -4,12 +4,13 @@ #include "completeterminal.h" #include "parser.h" -extern "C" int LLVMFuzzerTestOneInput( const uint8_t *data, size_t size ) { +extern "C" int LLVMFuzzerTestOneInput( const uint8_t* data, size_t size ) +{ Terminal::Display display( false ); Terminal::Complete complete( 80, 24 ); Terminal::Framebuffer state( 80, 24 ); for ( size_t i = 0; i < size; i++ ) { - complete.act( Parser::UserByte( data[ i ] ) ); + complete.act( Parser::UserByte( data[i] ) ); } display.new_frame( true, state, complete.get_fb() ); diff --git a/src/fuzz/terminal_parser_fuzzer.cc b/src/fuzz/terminal_parser_fuzzer.cc index 0747dc7d0..e0a426ff4 100644 --- a/src/fuzz/terminal_parser_fuzzer.cc +++ b/src/fuzz/terminal_parser_fuzzer.cc @@ -3,12 +3,13 @@ #include "parser.h" -extern "C" int LLVMFuzzerTestOneInput( const uint8_t *data, size_t size ) { +extern "C" int LLVMFuzzerTestOneInput( const uint8_t* data, size_t size ) +{ Parser::UTF8Parser parser; Parser::Actions result; for ( size_t i = 0; i < size; i++ ) { - parser.input( data[ i ], result ); + parser.input( data[i], result ); } return 0; diff --git a/src/network/compressor.cc b/src/network/compressor.cc index 39ccdcc30..10de2880d 100644 --- a/src/network/compressor.cc +++ b/src/network/compressor.cc @@ -38,28 +38,25 @@ using namespace Network; using std::string; -string Compressor::compress_str( const string &input ) { +string Compressor::compress_str( const string& input ) +{ long unsigned int len = BUFFER_SIZE; - dos_assert( - Z_OK - == compress( buffer, &len, - reinterpret_cast( input.data() ), - input.size() ) ); - return string( reinterpret_cast( buffer ), len ); + dos_assert( Z_OK + == compress( buffer, &len, reinterpret_cast( input.data() ), input.size() ) ); + return string( reinterpret_cast( buffer ), len ); } -string Compressor::uncompress_str( const string &input ) { +string Compressor::uncompress_str( const string& input ) +{ long unsigned int len = BUFFER_SIZE; - dos_assert( - Z_OK - == uncompress( buffer, &len, - reinterpret_cast( input.data() ), - input.size() ) ); - return string( reinterpret_cast( buffer ), len ); + dos_assert( Z_OK + == uncompress( buffer, &len, reinterpret_cast( input.data() ), input.size() ) ); + return string( reinterpret_cast( buffer ), len ); } /* construct on first use */ -Compressor &Network::get_compressor( void ) { +Compressor& Network::get_compressor( void ) +{ static Compressor the_compressor; return the_compressor; } diff --git a/src/network/compressor.h b/src/network/compressor.h index a4dc308a2..c45c23d73 100644 --- a/src/network/compressor.h +++ b/src/network/compressor.h @@ -36,26 +36,28 @@ #include namespace Network { - class Compressor { - private: - static const int BUFFER_SIZE = - 2048 * 2048; /* effective limit on terminal size */ +class Compressor +{ +private: + static const int BUFFER_SIZE = 2048 * 2048; /* effective limit on terminal size */ - unsigned char buffer[ BUFFER_SIZE ]; + unsigned char buffer[BUFFER_SIZE]; - public: - Compressor() : buffer() {} - ~Compressor() {} +public: + Compressor() + : buffer() + {} + ~Compressor() {} - std::string compress_str( const std::string &input ); - std::string uncompress_str( const std::string &input ); + std::string compress_str( const std::string& input ); + std::string uncompress_str( const std::string& input ); - /* unused */ - Compressor( const Compressor & ); - Compressor &operator=( const Compressor & ); - }; + /* unused */ + Compressor( const Compressor& ); + Compressor& operator=( const Compressor& ); +}; - Compressor &get_compressor( void ); +Compressor& get_compressor( void ); } #endif diff --git a/src/network/network.cc b/src/network/network.cc index 1008589be..db97922f1 100644 --- a/src/network/network.cc +++ b/src/network/network.cc @@ -67,47 +67,44 @@ const uint64_t DIRECTION_MASK = uint64_t( 1 ) << 63; const uint64_t SEQUENCE_MASK = uint64_t( -1 ) ^ DIRECTION_MASK; /* Read in packet */ -Packet::Packet( const Message &message ) - : seq( message.nonce.val() & SEQUENCE_MASK ), - direction( ( message.nonce.val() & DIRECTION_MASK ) ? TO_CLIENT : - TO_SERVER ), - timestamp( -1 ), - timestamp_reply( -1 ), - payload() { +Packet::Packet( const Message& message ) + : seq( message.nonce.val() & SEQUENCE_MASK ) + , direction( ( message.nonce.val() & DIRECTION_MASK ) ? TO_CLIENT : TO_SERVER ) + , timestamp( -1 ) + , timestamp_reply( -1 ) + , payload() +{ dos_assert( message.text.size() >= 2 * sizeof( uint16_t ) ); - const uint16_t *data = (uint16_t *)message.text.data(); - timestamp = be16toh( data[ 0 ] ); - timestamp_reply = be16toh( data[ 1 ] ); + const uint16_t* data = (uint16_t*)message.text.data(); + timestamp = be16toh( data[0] ); + timestamp_reply = be16toh( data[1] ); - payload = string( message.text.begin() + 2 * sizeof( uint16_t ), - message.text.end() ); + payload = string( message.text.begin() + 2 * sizeof( uint16_t ), message.text.end() ); } /* Output from packet */ -Message Packet::toMessage( void ) { - uint64_t direction_seq = - ( uint64_t( direction == TO_CLIENT ) << 63 ) | ( seq & SEQUENCE_MASK ); +Message Packet::toMessage( void ) +{ + uint64_t direction_seq = ( uint64_t( direction == TO_CLIENT ) << 63 ) | ( seq & SEQUENCE_MASK ); - uint16_t ts_net[ 2 ] = { static_cast( htobe16( timestamp ) ), - static_cast( - htobe16( timestamp_reply ) ) }; + uint16_t ts_net[2] + = { static_cast( htobe16( timestamp ) ), static_cast( htobe16( timestamp_reply ) ) }; - string timestamps = string( (char *)ts_net, 2 * sizeof( uint16_t ) ); + string timestamps = string( (char*)ts_net, 2 * sizeof( uint16_t ) ); return Message( Nonce( direction_seq ), timestamps + payload ); } -Packet Connection::new_packet( const string &s_payload ) { +Packet Connection::new_packet( const string& s_payload ) +{ uint16_t outgoing_timestamp_reply = -1; uint64_t now = timestamp(); - if ( now - saved_timestamp_received_at - < 1000 ) { /* we have a recent received timestamp */ + if ( now - saved_timestamp_received_at < 1000 ) { /* we have a recent received timestamp */ /* send "corrected" timestamp advanced by how long we held it */ - outgoing_timestamp_reply = - saved_timestamp + ( now - saved_timestamp_received_at ); + outgoing_timestamp_reply = saved_timestamp + ( now - saved_timestamp_received_at ); saved_timestamp = -1; saved_timestamp_received_at = 0; } @@ -117,7 +114,8 @@ Packet Connection::new_packet( const string &s_payload ) { return p; } -void Connection::hop_port( void ) { +void Connection::hop_port( void ) +{ assert( !server ); setup(); @@ -127,9 +125,9 @@ void Connection::hop_port( void ) { prune_sockets(); } -void Connection::prune_sockets( void ) { - /* don't keep old sockets if the new socket has been working for long enough - */ +void Connection::prune_sockets( void ) +{ + /* don't keep old sockets if the new socket has been working for long enough */ if ( socks.size() > 1 ) { if ( timestamp() - last_port_choice > MAX_OLD_SOCKET_AGE ) { int num_to_kill = socks.size() - 1; @@ -151,7 +149,8 @@ void Connection::prune_sockets( void ) { } Connection::Socket::Socket( int family ) - : _fd( socket( family, SOCK_DGRAM, 0 ) ) { + : _fd( socket( family, SOCK_DGRAM, 0 ) ) +{ if ( _fd < 0 ) { throw NetworkException( "socket", errno ); } @@ -159,8 +158,7 @@ Connection::Socket::Socket( int family ) /* Disable path MTU discovery */ #ifdef HAVE_IP_MTU_DISCOVER int flag = IP_PMTUDISC_DONT; - if ( setsockopt( _fd, IPPROTO_IP, IP_MTU_DISCOVER, &flag, sizeof flag ) - < 0 ) { + if ( setsockopt( _fd, IPPROTO_IP, IP_MTU_DISCOVER, &flag, sizeof flag ) < 0 ) { throw NetworkException( "setsockopt", errno ); } #endif @@ -175,76 +173,84 @@ Connection::Socket::Socket( int family ) #ifdef HAVE_IP_RECVTOS int tosflag = true; if ( setsockopt( _fd, IPPROTO_IP, IP_RECVTOS, &tosflag, sizeof tosflag ) < 0 - && family == IPPROTO_IP ) { /* FreeBSD disallows this option on IPv6 - sockets. */ + && family == IPPROTO_IP ) { /* FreeBSD disallows this option on IPv6 sockets. */ perror( "setsockopt( IP_RECVTOS )" ); } #endif } -void Connection::setup( void ) { last_port_choice = timestamp(); } +void Connection::setup( void ) +{ + last_port_choice = timestamp(); +} -const std::vector Connection::fds( void ) const { +const std::vector Connection::fds( void ) const +{ std::vector ret; - for ( std::deque::const_iterator it = socks.begin(); - it != socks.end(); it++ ) { + for ( std::deque::const_iterator it = socks.begin(); it != socks.end(); it++ ) { ret.push_back( it->fd() ); } return ret; } -void Connection::set_MTU( int family ) { +void Connection::set_MTU( int family ) +{ switch ( family ) { - case AF_INET: MTU = DEFAULT_IPV4_MTU - IPV4_HEADER_LEN; break; - case AF_INET6: MTU = DEFAULT_IPV6_MTU - IPV6_HEADER_LEN; break; - default: throw NetworkException( "Unknown address family", 0 ); + case AF_INET: + MTU = DEFAULT_IPV4_MTU - IPV4_HEADER_LEN; + break; + case AF_INET6: + MTU = DEFAULT_IPV6_MTU - IPV6_HEADER_LEN; + break; + default: + throw NetworkException( "Unknown address family", 0 ); } } -class AddrInfo { +class AddrInfo +{ public: - struct addrinfo *res; - AddrInfo( const char *node, const char *service, - const struct addrinfo *hints ) - : res( NULL ) { + struct addrinfo* res; + AddrInfo( const char* node, const char* service, const struct addrinfo* hints ) + : res( NULL ) + { int errcode = getaddrinfo( node, service, hints, &res ); if ( errcode != 0 ) { - throw NetworkException( std::string( "Bad IP address (" ) - + ( node != NULL ? node : "(null)" ) - + "): " + gai_strerror( errcode ), + throw NetworkException( std::string( "Bad IP address (" ) + ( node != NULL ? node : "(null)" ) + + "): " + gai_strerror( errcode ), 0 ); } } ~AddrInfo() { freeaddrinfo( res ); } private: - AddrInfo( const AddrInfo & ); - AddrInfo &operator=( const AddrInfo & ); + AddrInfo( const AddrInfo& ); + AddrInfo& operator=( const AddrInfo& ); }; -Connection::Connection( const char *desired_ip, - const char *desired_port ) /* server */ - : socks(), - has_remote_addr( false ), - remote_addr(), - remote_addr_len( 0 ), - server( true ), - MTU( DEFAULT_SEND_MTU ), - key(), - session( key ), - direction( TO_CLIENT ), - saved_timestamp( -1 ), - saved_timestamp_received_at( 0 ), - expected_receiver_seq( 0 ), - last_heard( -1 ), - last_port_choice( -1 ), - last_roundtrip_success( -1 ), - RTT_hit( false ), - SRTT( 1000 ), - RTTVAR( 500 ), - send_error() { +Connection::Connection( const char* desired_ip, const char* desired_port ) /* server */ + : socks() + , has_remote_addr( false ) + , remote_addr() + , remote_addr_len( 0 ) + , server( true ) + , MTU( DEFAULT_SEND_MTU ) + , key() + , session( key ) + , direction( TO_CLIENT ) + , saved_timestamp( -1 ) + , saved_timestamp_received_at( 0 ) + , expected_receiver_seq( 0 ) + , last_heard( -1 ) + , last_port_choice( -1 ) + , last_roundtrip_success( -1 ) + , RTT_hit( false ) + , SRTT( 1000 ) + , RTTVAR( 500 ) + , send_error() +{ setup(); /* The mosh wrapper always gives an IP request, in order @@ -257,9 +263,7 @@ Connection::Connection( const char *desired_ip, int desired_port_low = -1; int desired_port_high = -1; - if ( desired_port - && !parse_portrange( desired_port, desired_port_low, - desired_port_high ) ) { + if ( desired_port && !parse_portrange( desired_port, desired_port_low, desired_port_high ) ) { throw NetworkException( "Invalid port range", 0 ); } @@ -269,7 +273,7 @@ Connection::Connection( const char *desired_ip, if ( try_bind( desired_ip, desired_port_low, desired_port_high ) ) { return; } - } catch ( const NetworkException &e ) { + } catch ( const NetworkException& e ) { fprintf( stderr, "Error binding to IP %s: %s\n", desired_ip, e.what() ); } } @@ -279,7 +283,7 @@ Connection::Connection( const char *desired_ip, if ( try_bind( NULL, desired_port_low, desired_port_high ) ) { return; } - } catch ( const NetworkException &e ) { + } catch ( const NetworkException& e ) { fprintf( stderr, "Error binding to any interface: %s\n", e.what() ); throw; /* this time it's fatal */ } @@ -287,7 +291,8 @@ Connection::Connection( const char *desired_ip, throw NetworkException( "Could not bind", errno ); } -bool Connection::try_bind( const char *addr, int port_low, int port_high ) { +bool Connection::try_bind( const char* addr, int port_low, int port_high ) +{ struct addrinfo hints; memset( &hints, 0, sizeof( hints ) ); hints.ai_family = AF_UNSPEC; @@ -311,18 +316,20 @@ bool Connection::try_bind( const char *addr, int port_low, int port_high ) { socks.push_back( Socket( local_addr.sa.sa_family ) ); for ( int i = search_low; i <= search_high; i++ ) { switch ( local_addr.sa.sa_family ) { - case AF_INET: local_addr.sin.sin_port = htons( i ); break; - case AF_INET6: local_addr.sin6.sin6_port = htons( i ); break; - default: throw NetworkException( "Unknown address family", 0 ); + case AF_INET: + local_addr.sin.sin_port = htons( i ); + break; + case AF_INET6: + local_addr.sin6.sin6_port = htons( i ); + break; + default: + throw NetworkException( "Unknown address family", 0 ); } if ( local_addr.sa.sa_family == AF_INET6 - && memcmp( &local_addr.sin6.sin6_addr, &in6addr_any, - sizeof( in6addr_any ) ) - == 0 ) { + && memcmp( &local_addr.sin6.sin6_addr, &in6addr_any, sizeof( in6addr_any ) ) == 0 ) { const int off = 0; - if ( setsockopt( sock(), IPPROTO_IPV6, IPV6_V6ONLY, &off, - sizeof( off ) ) ) { + if ( setsockopt( sock(), IPPROTO_IPV6, IPV6_V6ONLY, &off, sizeof( off ) ) ) { perror( "setsockopt( IPV6_V6ONLY, off )" ); } } @@ -330,43 +337,46 @@ bool Connection::try_bind( const char *addr, int port_low, int port_high ) { if ( ::bind( sock(), &local_addr.sa, local_addr_len ) == 0 ) { set_MTU( local_addr.sa.sa_family ); return true; - } // else fallthrough to below code, on last iteration. + } // else fallthrough to below code, on last iteration. } int saved_errno = errno; socks.pop_back(); - char host[ NI_MAXHOST ], serv[ NI_MAXSERV ]; - int errcode = - getnameinfo( &local_addr.sa, local_addr_len, host, sizeof( host ), serv, - sizeof( serv ), NI_DGRAM | NI_NUMERICHOST | NI_NUMERICSERV ); + char host[NI_MAXHOST], serv[NI_MAXSERV]; + int errcode = getnameinfo( &local_addr.sa, + local_addr_len, + host, + sizeof( host ), + serv, + sizeof( serv ), + NI_DGRAM | NI_NUMERICHOST | NI_NUMERICSERV ); if ( errcode != 0 ) { - throw NetworkException( - std::string( "bind: getnameinfo: " ) + gai_strerror( errcode ), 0 ); + throw NetworkException( std::string( "bind: getnameinfo: " ) + gai_strerror( errcode ), 0 ); } fprintf( stderr, "Failed binding to %s:%s\n", host, serv ); throw NetworkException( "bind", saved_errno ); } -Connection::Connection( const char *key_str, const char *ip, - const char *port ) /* client */ - : socks(), - has_remote_addr( false ), - remote_addr(), - remote_addr_len( 0 ), - server( false ), - MTU( DEFAULT_SEND_MTU ), - key( key_str ), - session( key ), - direction( TO_SERVER ), - saved_timestamp( -1 ), - saved_timestamp_received_at( 0 ), - expected_receiver_seq( 0 ), - last_heard( -1 ), - last_port_choice( -1 ), - last_roundtrip_success( -1 ), - RTT_hit( false ), - SRTT( 1000 ), - RTTVAR( 500 ), - send_error() { +Connection::Connection( const char* key_str, const char* ip, const char* port ) /* client */ + : socks() + , has_remote_addr( false ) + , remote_addr() + , remote_addr_len( 0 ) + , server( false ) + , MTU( DEFAULT_SEND_MTU ) + , key( key_str ) + , session( key ) + , direction( TO_SERVER ) + , saved_timestamp( -1 ) + , saved_timestamp_received_at( 0 ) + , expected_receiver_seq( 0 ) + , last_heard( -1 ) + , last_port_choice( -1 ) + , last_roundtrip_success( -1 ) + , RTT_hit( false ) + , SRTT( 1000 ) + , RTTVAR( 500 ) + , send_error() +{ setup(); /* associate socket with remote host and port */ @@ -376,8 +386,7 @@ Connection::Connection( const char *key_str, const char *ip, hints.ai_socktype = SOCK_DGRAM; hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV; AddrInfo ai( ip, port, &hints ); - fatal_assert( static_cast( ai.res->ai_addrlen ) - <= sizeof( remote_addr ) ); + fatal_assert( static_cast( ai.res->ai_addrlen ) <= sizeof( remote_addr ) ); remote_addr_len = ai.res->ai_addrlen; memcpy( &remote_addr.sa, ai.res->ai_addr, remote_addr_len ); @@ -388,7 +397,8 @@ Connection::Connection( const char *key_str, const char *ip, set_MTU( remote_addr.sa.sa_family ); } -void Connection::send( const string &s ) { +void Connection::send( const string& s ) +{ if ( !has_remote_addr ) { return; } @@ -397,8 +407,7 @@ void Connection::send( const string &s ) { string p = session.encrypt( px.toMessage() ); - ssize_t bytes_sent = sendto( sock(), p.data(), p.size(), MSG_DONTWAIT, - &remote_addr.sa, remote_addr_len ); + ssize_t bytes_sent = sendto( sock(), p.data(), p.size(), MSG_DONTWAIT, &remote_addr.sa, remote_addr_len ); if ( bytes_sent != static_cast( p.size() ) ) { /* Make sendto() failure available to the frontend. */ @@ -417,21 +426,20 @@ void Connection::send( const string &s ) { fprintf( stderr, "Server now detached from client.\n" ); } } else { /* client */ - if ( ( now - last_port_choice > PORT_HOP_INTERVAL ) - && ( now - last_roundtrip_success > PORT_HOP_INTERVAL ) ) { + if ( ( now - last_port_choice > PORT_HOP_INTERVAL ) && ( now - last_roundtrip_success > PORT_HOP_INTERVAL ) ) { hop_port(); } } } -string Connection::recv( void ) { +string Connection::recv( void ) +{ assert( !socks.empty() ); - for ( std::deque::const_iterator it = socks.begin(); - it != socks.end(); it++ ) { + for ( std::deque::const_iterator it = socks.begin(); it != socks.end(); it++ ) { string payload; try { payload = recv_one( it->fd() ); - } catch ( NetworkException &e ) { + } catch ( NetworkException& e ) { if ( ( e.the_errno == EAGAIN ) || ( e.the_errno == EWOULDBLOCK ) ) { continue; } else { @@ -446,14 +454,15 @@ string Connection::recv( void ) { throw NetworkException( "No packet received" ); } -string Connection::recv_one( int sock_to_recv ) { +string Connection::recv_one( int sock_to_recv ) +{ /* receive source address, ECN, and payload in msghdr structure */ Addr packet_remote_addr; struct msghdr header; struct iovec msg_iovec; - char msg_payload[ Session::RECEIVE_MTU ]; - char msg_control[ Session::RECEIVE_MTU ]; + char msg_payload[Session::RECEIVE_MTU]; + char msg_control[Session::RECEIVE_MTU]; /* receive source address */ header.msg_name = &packet_remote_addr; @@ -485,7 +494,7 @@ string Connection::recv_one( int sock_to_recv ) { /* receive ECN */ bool congestion_experienced = false; - struct cmsghdr *ecn_hdr = CMSG_FIRSTHDR( &header ); + struct cmsghdr* ecn_hdr = CMSG_FIRSTHDR( &header ); if ( ecn_hdr && ecn_hdr->cmsg_level == IPPROTO_IP && ( ecn_hdr->cmsg_type == IP_TOS #ifdef IP_RECVTOS @@ -493,7 +502,7 @@ string Connection::recv_one( int sock_to_recv ) { #endif ) ) { /* got one */ - uint8_t *ecn_octet_p = (uint8_t *)CMSG_DATA( ecn_hdr ); + uint8_t* ecn_octet_p = (uint8_t*)CMSG_DATA( ecn_hdr ); assert( ecn_octet_p ); congestion_experienced = ( *ecn_octet_p & 0x03 ) == 0x03; @@ -501,19 +510,14 @@ string Connection::recv_one( int sock_to_recv ) { Packet p( session.decrypt( msg_payload, received_len ) ); - dos_assert( p.direction - == ( server ? - TO_SERVER : - TO_CLIENT ) ); /* prevent malicious playback to sender */ + dos_assert( p.direction == ( server ? TO_SERVER : TO_CLIENT ) ); /* prevent malicious playback to sender */ if ( p.seq - < expected_receiver_seq ) { /* don't use (but do return) out-of-order - packets for timestamp or targeting */ + < expected_receiver_seq ) { /* don't use (but do return) out-of-order packets for timestamp or targeting */ return p.payload; } - expected_receiver_seq = - p.seq + 1; /* this is security-sensitive because a replay attack could - otherwise screw up the timestamp and targeting */ + expected_receiver_seq = p.seq + 1; /* this is security-sensitive because a replay attack could otherwise + screw up the timestamp and targeting */ if ( p.timestamp != uint16_t( -1 ) ) { saved_timestamp = p.timestamp; @@ -521,8 +525,7 @@ string Connection::recv_one( int sock_to_recv ) { if ( congestion_experienced ) { /* signal counterparty to slow down */ - /* this will gradually slow the counterparty down to the minimum frame - * rate */ + /* this will gradually slow the counterparty down to the minimum frame rate */ saved_timestamp -= CONGESTION_TIMESTAMP_PENALTY; if ( server ) { fprintf( stderr, "Received explicit congestion notification.\n" ); @@ -534,7 +537,7 @@ string Connection::recv_one( int sock_to_recv ) { uint16_t now = timestamp16(); double R = timestamp_diff( now, p.timestamp_reply ); - if ( R < 5000 ) { /* ignore large values, e.g. server was Ctrl-Zed */ + if ( R < 5000 ) { /* ignore large values, e.g. server was Ctrl-Zed */ if ( !RTT_hit ) { /* first measurement */ SRTT = R; RTTVAR = R / 2; @@ -555,25 +558,27 @@ string Connection::recv_one( int sock_to_recv ) { if ( server && /* only client can roam */ ( remote_addr_len != header.msg_namelen - || memcmp( &remote_addr, &packet_remote_addr, remote_addr_len ) - != 0 ) ) { + || memcmp( &remote_addr, &packet_remote_addr, remote_addr_len ) != 0 ) ) { remote_addr = packet_remote_addr; remote_addr_len = header.msg_namelen; - char host[ NI_MAXHOST ], serv[ NI_MAXSERV ]; - int errcode = getnameinfo( &remote_addr.sa, remote_addr_len, host, - sizeof( host ), serv, sizeof( serv ), + char host[NI_MAXHOST], serv[NI_MAXSERV]; + int errcode = getnameinfo( &remote_addr.sa, + remote_addr_len, + host, + sizeof( host ), + serv, + sizeof( serv ), NI_DGRAM | NI_NUMERICHOST | NI_NUMERICSERV ); if ( errcode != 0 ) { - throw NetworkException( - std::string( "recv_one: getnameinfo: " ) + gai_strerror( errcode ), - 0 ); + throw NetworkException( std::string( "recv_one: getnameinfo: " ) + gai_strerror( errcode ), 0 ); } fprintf( stderr, "Server now attached to client at %s:%s\n", host, serv ); } return p.payload; } -std::string Connection::port( void ) const { +std::string Connection::port( void ) const +{ Addr local_addr; socklen_t addrlen = sizeof( local_addr ); @@ -581,20 +586,22 @@ std::string Connection::port( void ) const { throw NetworkException( "getsockname", errno ); } - char serv[ NI_MAXSERV ]; - int errcode = getnameinfo( &local_addr.sa, addrlen, NULL, 0, serv, - sizeof( serv ), NI_DGRAM | NI_NUMERICSERV ); + char serv[NI_MAXSERV]; + int errcode = getnameinfo( &local_addr.sa, addrlen, NULL, 0, serv, sizeof( serv ), NI_DGRAM | NI_NUMERICSERV ); if ( errcode != 0 ) { - throw NetworkException( - std::string( "port: getnameinfo: " ) + gai_strerror( errcode ), 0 ); + throw NetworkException( std::string( "port: getnameinfo: " ) + gai_strerror( errcode ), 0 ); } return std::string( serv ); } -uint64_t Network::timestamp( void ) { return frozen_timestamp(); } +uint64_t Network::timestamp( void ) +{ + return frozen_timestamp(); +} -uint16_t Network::timestamp16( void ) { +uint16_t Network::timestamp16( void ) +{ uint16_t ts = timestamp() % 65536; if ( ts == uint16_t( -1 ) ) { ts++; @@ -602,7 +609,8 @@ uint16_t Network::timestamp16( void ) { return ts; } -uint16_t Network::timestamp_diff( uint16_t tsnew, uint16_t tsold ) { +uint16_t Network::timestamp_diff( uint16_t tsnew, uint16_t tsold ) +{ int diff = tsnew - tsold; if ( diff < 0 ) { diff += 65536; @@ -614,7 +622,8 @@ uint16_t Network::timestamp_diff( uint16_t tsnew, uint16_t tsold ) { return diff; } -uint64_t Connection::timeout( void ) const { +uint64_t Connection::timeout( void ) const +{ uint64_t RTO = lrint( ceil( SRTT + 4 * RTTVAR ) ); if ( RTO < MIN_RTO ) { RTO = MIN_RTO; @@ -624,15 +633,21 @@ uint64_t Connection::timeout( void ) const { return RTO; } -Connection::Socket::~Socket() { fatal_assert( close( _fd ) == 0 ); } +Connection::Socket::~Socket() +{ + fatal_assert( close( _fd ) == 0 ); +} -Connection::Socket::Socket( const Socket &other ) : _fd( dup( other._fd ) ) { +Connection::Socket::Socket( const Socket& other ) + : _fd( dup( other._fd ) ) +{ if ( _fd < 0 ) { throw NetworkException( "socket", errno ); } } -Connection::Socket &Connection::Socket::operator=( const Socket &other ) { +Connection::Socket& Connection::Socket::operator=( const Socket& other ) +{ if ( dup2( other._fd, _fd ) < 0 ) { throw NetworkException( "socket", errno ); } @@ -640,12 +655,11 @@ Connection::Socket &Connection::Socket::operator=( const Socket &other ) { return *this; } -bool Connection::parse_portrange( const char *desired_port, - int &desired_port_low, - int &desired_port_high ) { +bool Connection::parse_portrange( const char* desired_port, int& desired_port_low, int& desired_port_high ) +{ /* parse "port" or "portlow:porthigh" */ desired_port_low = desired_port_high = 0; - char *end; + char* end; long value; /* parse first (only?) port */ @@ -656,8 +670,7 @@ bool Connection::parse_portrange( const char *desired_port, return false; } if ( ( value < 0 ) || ( value > 65535 ) ) { - fprintf( stderr, "(Low) port number %ld outside valid range [0..65535]\n", - value ); + fprintf( stderr, "(Low) port number %ld outside valid range [0..65535]\n", value ); return false; } @@ -667,7 +680,7 @@ bool Connection::parse_portrange( const char *desired_port, return true; } /* port range; parse high port */ - const char *cp = end + 1; + const char* cp = end + 1; errno = 0; value = strtol( cp, &end, 10 ); if ( ( errno != 0 ) || ( *end != '\0' ) ) { @@ -675,15 +688,13 @@ bool Connection::parse_portrange( const char *desired_port, return false; } if ( ( value < 0 ) || ( value > 65535 ) ) { - fprintf( stderr, "High port number %ld outside valid range [0..65535]\n", - value ); + fprintf( stderr, "High port number %ld outside valid range [0..65535]\n", value ); return false; } desired_port_high = (int)value; if ( desired_port_low > desired_port_high ) { - fprintf( stderr, "Low port %d greater than high port %d\n", - desired_port_low, desired_port_high ); + fprintf( stderr, "Low port %d greater than high port %d\n", desired_port_low, desired_port_high ); return false; } diff --git a/src/network/network.h b/src/network/network.h index 024938c9d..4fa71838a 100644 --- a/src/network/network.h +++ b/src/network/network.h @@ -34,14 +34,14 @@ #define NETWORK_HPP #include +#include +#include #include #include #include #include -#include -#include -#include #include +#include #include #include "crypto.h" @@ -49,197 +49,201 @@ using namespace Crypto; namespace Network { - static const unsigned int MOSH_PROTOCOL_VERSION = 2; /* bumped for echo-ack */ - - uint64_t timestamp( void ); - uint16_t timestamp16( void ); - uint16_t timestamp_diff( uint16_t tsnew, uint16_t tsold ); - - class NetworkException : public std::exception { - public: - string function; - int the_errno; - +static const unsigned int MOSH_PROTOCOL_VERSION = 2; /* bumped for echo-ack */ + +uint64_t timestamp( void ); +uint16_t timestamp16( void ); +uint16_t timestamp_diff( uint16_t tsnew, uint16_t tsold ); + +class NetworkException : public std::exception +{ +public: + string function; + int the_errno; + +private: + string my_what; + +public: + NetworkException( string s_function = "", int s_errno = 0 ) + : function( s_function ) + , the_errno( s_errno ) + , my_what( function + ": " + strerror( the_errno ) ) + {} + const char* what() const throw() { return my_what.c_str(); } + ~NetworkException() throw() {} +}; + +enum Direction +{ + TO_SERVER = 0, + TO_CLIENT = 1 +}; + +class Packet +{ +public: + const uint64_t seq; + Direction direction; + uint16_t timestamp, timestamp_reply; + string payload; + + Packet( Direction s_direction, uint16_t s_timestamp, uint16_t s_timestamp_reply, const string& s_payload ) + : seq( Crypto::unique() ) + , direction( s_direction ) + , timestamp( s_timestamp ) + , timestamp_reply( s_timestamp_reply ) + , payload( s_payload ) + {} + + Packet( const Message& message ); + + Message toMessage( void ); +}; + +union Addr { + struct sockaddr sa; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + struct sockaddr_storage ss; +}; + +class Connection +{ +private: + /* + * For IPv4, guess the typical (minimum) header length; + * fragmentation is not dangerous, just inefficient. + */ + static const int IPV4_HEADER_LEN = 20 /* base IP header */ + + 8 /* UDP */; + /* + * For IPv6, we don't want to ever have MTU issues, so make a + * conservative guess about header size. + */ + static const int IPV6_HEADER_LEN = 40 /* base IPv6 header */ + + 16 /* 2 minimum-sized extension headers */ + + 8 /* UDP */; + /* Application datagram MTU. For constructors and fallback. */ + static const int DEFAULT_SEND_MTU = 500; + /* + * IPv4 MTU. Don't use full Ethernet-derived MTU, + * mobile networks have high tunneling overhead. + * + * As of July 2016, VPN traffic over Amtrak Acela wifi seems to be + * dropped if tunnelled packets are 1320 bytes or larger. Use a + * 1280-byte IPv4 MTU for now. + * + * We may have to implement ICMP-less PMTUD (RFC 4821) eventually. + */ + static const int DEFAULT_IPV4_MTU = 1280; + /* IPv6 MTU. Use the guaranteed minimum to avoid fragmentation. */ + static const int DEFAULT_IPV6_MTU = 1280; + + static const uint64_t MIN_RTO = 50; /* ms */ + static const uint64_t MAX_RTO = 1000; /* ms */ + + static const int PORT_RANGE_LOW = 60001; + static const int PORT_RANGE_HIGH = 60999; + + static const unsigned int SERVER_ASSOCIATION_TIMEOUT = 40000; + static const unsigned int PORT_HOP_INTERVAL = 10000; + + static const unsigned int MAX_PORTS_OPEN = 10; + static const unsigned int MAX_OLD_SOCKET_AGE = 60000; + + static const int CONGESTION_TIMESTAMP_PENALTY = 500; /* ms */ + + bool try_bind( const char* addr, int port_low, int port_high ); + + class Socket + { private: - string my_what; + int _fd; public: - NetworkException( string s_function = "", int s_errno = 0 ) - : function( s_function ), - the_errno( s_errno ), - my_what( function + ": " + strerror( the_errno ) ) {} - const char *what() const throw() { return my_what.c_str(); } - ~NetworkException() throw() {} - }; - - enum Direction { TO_SERVER = 0, TO_CLIENT = 1 }; + int fd( void ) const { return _fd; } + Socket( int family ); + ~Socket(); - class Packet { - public: - const uint64_t seq; - Direction direction; - uint16_t timestamp, timestamp_reply; - string payload; - - Packet( Direction s_direction, uint16_t s_timestamp, - uint16_t s_timestamp_reply, const string &s_payload ) - : seq( Crypto::unique() ), - direction( s_direction ), - timestamp( s_timestamp ), - timestamp_reply( s_timestamp_reply ), - payload( s_payload ) {} - - Packet( const Message &message ); - - Message toMessage( void ); + Socket( const Socket& other ); + Socket& operator=( const Socket& other ); }; - union Addr { - struct sockaddr sa; - struct sockaddr_in sin; - struct sockaddr_in6 sin6; - struct sockaddr_storage ss; - }; + std::deque socks; + bool has_remote_addr; + Addr remote_addr; + socklen_t remote_addr_len; - class Connection { - private: - /* - * For IPv4, guess the typical (minimum) header length; - * fragmentation is not dangerous, just inefficient. - */ - static const int IPV4_HEADER_LEN = 20 /* base IP header */ - + 8 /* UDP */; - /* - * For IPv6, we don't want to ever have MTU issues, so make a - * conservative guess about header size. - */ - static const int IPV6_HEADER_LEN = - 40 /* base IPv6 header */ - + 16 /* 2 minimum-sized extension headers */ - + 8 /* UDP */; - /* Application datagram MTU. For constructors and fallback. */ - static const int DEFAULT_SEND_MTU = 500; - /* - * IPv4 MTU. Don't use full Ethernet-derived MTU, - * mobile networks have high tunneling overhead. - * - * As of July 2016, VPN traffic over Amtrak Acela wifi seems to be - * dropped if tunnelled packets are 1320 bytes or larger. Use a - * 1280-byte IPv4 MTU for now. - * - * We may have to implement ICMP-less PMTUD (RFC 4821) eventually. - */ - static const int DEFAULT_IPV4_MTU = 1280; - /* IPv6 MTU. Use the guaranteed minimum to avoid fragmentation. */ - static const int DEFAULT_IPV6_MTU = 1280; - - static const uint64_t MIN_RTO = 50; /* ms */ - static const uint64_t MAX_RTO = 1000; /* ms */ - - static const int PORT_RANGE_LOW = 60001; - static const int PORT_RANGE_HIGH = 60999; + bool server; - static const unsigned int SERVER_ASSOCIATION_TIMEOUT = 40000; - static const unsigned int PORT_HOP_INTERVAL = 10000; + int MTU; /* application datagram MTU */ - static const unsigned int MAX_PORTS_OPEN = 10; - static const unsigned int MAX_OLD_SOCKET_AGE = 60000; + Base64Key key; + Session session; - static const int CONGESTION_TIMESTAMP_PENALTY = 500; /* ms */ + void setup( void ); - bool try_bind( const char *addr, int port_low, int port_high ); + Direction direction; + uint16_t saved_timestamp; + uint64_t saved_timestamp_received_at; + uint64_t expected_receiver_seq; - class Socket { - private: - int _fd; + uint64_t last_heard; + uint64_t last_port_choice; + uint64_t last_roundtrip_success; /* transport layer needs to tell us this */ - public: - int fd( void ) const { return _fd; } - Socket( int family ); - ~Socket(); + bool RTT_hit; + double SRTT; + double RTTVAR; - Socket( const Socket &other ); - Socket &operator=( const Socket &other ); - }; + /* Error from send()/sendto(). */ + string send_error; - std::deque socks; - bool has_remote_addr; - Addr remote_addr; - socklen_t remote_addr_len; + Packet new_packet( const string& s_payload ); - bool server; + void hop_port( void ); - int MTU; /* application datagram MTU */ + int sock( void ) const + { + assert( !socks.empty() ); + return socks.back().fd(); + } - Base64Key key; - Session session; + void prune_sockets( void ); - void setup( void ); + string recv_one( int sock_to_recv ); - Direction direction; - uint16_t saved_timestamp; - uint64_t saved_timestamp_received_at; - uint64_t expected_receiver_seq; + void set_MTU( int family ); - uint64_t last_heard; - uint64_t last_port_choice; - uint64_t last_roundtrip_success; /* transport layer needs to tell us this */ +public: + /* Network transport overhead. */ + static const int ADDED_BYTES = 8 /* seqno/nonce */ + 4 /* timestamps */; - bool RTT_hit; - double SRTT; - double RTTVAR; + Connection( const char* desired_ip, const char* desired_port ); /* server */ + Connection( const char* key_str, const char* ip, const char* port ); /* client */ - /* Error from send()/sendto(). */ - string send_error; + void send( const string& s ); + string recv( void ); + const std::vector fds( void ) const; + int get_MTU( void ) const { return MTU; } - Packet new_packet( const string &s_payload ); + std::string port( void ) const; + string get_key( void ) const { return key.printable_key(); } + bool get_has_remote_addr( void ) const { return has_remote_addr; } - void hop_port( void ); + uint64_t timeout( void ) const; + double get_SRTT( void ) const { return SRTT; } - int sock( void ) const { - assert( !socks.empty() ); - return socks.back().fd(); - } + const Addr& get_remote_addr( void ) const { return remote_addr; } + socklen_t get_remote_addr_len( void ) const { return remote_addr_len; } - void prune_sockets( void ); - - string recv_one( int sock_to_recv ); - - void set_MTU( int family ); - - public: - /* Network transport overhead. */ - static const int ADDED_BYTES = 8 /* seqno/nonce */ + 4 /* timestamps */; + string& get_send_error( void ) { return send_error; } - Connection( const char *desired_ip, const char *desired_port ); /* server */ - Connection( const char *key_str, const char *ip, - const char *port ); /* client */ + void set_last_roundtrip_success( uint64_t s_success ) { last_roundtrip_success = s_success; } - void send( const string &s ); - string recv( void ); - const std::vector fds( void ) const; - int get_MTU( void ) const { return MTU; } - - std::string port( void ) const; - string get_key( void ) const { return key.printable_key(); } - bool get_has_remote_addr( void ) const { return has_remote_addr; } - - uint64_t timeout( void ) const; - double get_SRTT( void ) const { return SRTT; } - - const Addr &get_remote_addr( void ) const { return remote_addr; } - socklen_t get_remote_addr_len( void ) const { return remote_addr_len; } - - string &get_send_error( void ) { return send_error; } - - void set_last_roundtrip_success( uint64_t s_success ) { - last_roundtrip_success = s_success; - } - - static bool parse_portrange( const char *desired_port_range, - int &desired_port_low, - int &desired_port_high ); - }; + static bool parse_portrange( const char* desired_port_range, int& desired_port_low, int& desired_port_high ); +}; } #endif diff --git a/src/network/networktransport-impl.h b/src/network/networktransport-impl.h index 59c1f6a8d..3a636db4a 100644 --- a/src/network/networktransport-impl.h +++ b/src/network/networktransport-impl.h @@ -39,40 +39,42 @@ using namespace Network; -template -Transport::Transport( MyState &initial_state, - RemoteState &initial_remote, - const char *desired_ip, - const char *desired_port ) - : connection( desired_ip, desired_port ), - sender( &connection, initial_state ), - received_states( - 1, TimestampedState( timestamp(), 0, initial_remote ) ), - receiver_quench_timer( 0 ), - last_receiver_state( initial_remote ), - fragments(), - verbose( 0 ) { +template +Transport::Transport( MyState& initial_state, + RemoteState& initial_remote, + const char* desired_ip, + const char* desired_port ) + : connection( desired_ip, desired_port ) + , sender( &connection, initial_state ) + , received_states( 1, TimestampedState( timestamp(), 0, initial_remote ) ) + , receiver_quench_timer( 0 ) + , last_receiver_state( initial_remote ) + , fragments() + , verbose( 0 ) +{ /* server */ } -template -Transport::Transport( MyState &initial_state, - RemoteState &initial_remote, - const char *key_str, const char *ip, - const char *port ) - : connection( key_str, ip, port ), - sender( &connection, initial_state ), - received_states( - 1, TimestampedState( timestamp(), 0, initial_remote ) ), - receiver_quench_timer( 0 ), - last_receiver_state( initial_remote ), - fragments(), - verbose( 0 ) { +template +Transport::Transport( MyState& initial_state, + RemoteState& initial_remote, + const char* key_str, + const char* ip, + const char* port ) + : connection( key_str, ip, port ) + , sender( &connection, initial_state ) + , received_states( 1, TimestampedState( timestamp(), 0, initial_remote ) ) + , receiver_quench_timer( 0 ) + , last_receiver_state( initial_remote ) + , fragments() + , verbose( 0 ) +{ /* client */ } -template -void Transport::recv( void ) { +template +void Transport::recv( void ) +{ string s( connection.recv() ); Fragment frag( s ); @@ -86,13 +88,12 @@ void Transport::recv( void ) { sender.process_acknowledgment_through( inst.ack_num() ); /* inform network layer of roundtrip (end-to-end-to-end) connectivity */ - connection.set_last_roundtrip_success( - sender.get_sent_state_acked_timestamp() ); + connection.set_last_roundtrip_success( sender.get_sent_state_acked_timestamp() ); /* first, make sure we don't already have the new state */ - for ( typename list >::iterator i = - received_states.begin(); - i != received_states.end(); i++ ) { + for ( typename list>::iterator i = received_states.begin(); + i != received_states.end(); + i++ ) { if ( inst.new_num() == i->num ) { return; } @@ -100,8 +101,7 @@ void Transport::recv( void ) { /* now, make sure we do have the old state */ bool found = 0; - typename list >::iterator reference_state = - received_states.begin(); + typename list>::iterator reference_state = received_states.begin(); while ( reference_state != received_states.end() ) { if ( inst.old_num() == reference_state->num ) { found = true; @@ -111,11 +111,9 @@ void Transport::recv( void ) { } if ( !found ) { - // fprintf( stderr, "Ignoring out-of-order packet. Reference state %d - // has been discarded or hasn't yet been received.\n", - // int(inst.old_num) ); - return; /* this is security-sensitive and part of how we enforce - idempotency */ + // fprintf( stderr, "Ignoring out-of-order packet. Reference state %d has been discarded or hasn't yet been + // received.\n", int(inst.old_num) ); + return; /* this is security-sensitive and part of how we enforce idempotency */ } /* Do not accept state if our queue is full */ @@ -129,11 +127,11 @@ void Transport::recv( void ) { uint64_t now = timestamp(); if ( now < receiver_quench_timer ) { /* deny letting state grow further */ if ( verbose ) { - fprintf( stderr, - "[%u] Receiver queue full, discarding %d (malicious sender " - "or long-unidirectional connectivity?)\n", - (unsigned int)( timestamp() % 100000 ), - (int)inst.new_num() ); + fprintf( + stderr, + "[%u] Receiver queue full, discarding %d (malicious sender or long-unidirectional connectivity?)\n", + (unsigned int)( timestamp() % 100000 ), + (int)inst.new_num() ); } return; } else { @@ -151,23 +149,28 @@ void Transport::recv( void ) { } /* Insert new state in sorted place */ - for ( typename list >::iterator i = - received_states.begin(); - i != received_states.end(); i++ ) { + for ( typename list>::iterator i = received_states.begin(); + i != received_states.end(); + i++ ) { if ( i->num > new_state.num ) { received_states.insert( i, new_state ); if ( verbose ) { - fprintf( stderr, "[%u] Received OUT-OF-ORDER state %d [ack %d]\n", - (unsigned int)( timestamp() % 100000 ), (int)new_state.num, + fprintf( stderr, + "[%u] Received OUT-OF-ORDER state %d [ack %d]\n", + (unsigned int)( timestamp() % 100000 ), + (int)new_state.num, (int)inst.ack_num() ); } return; } } if ( verbose ) { - fprintf( stderr, "[%u] Received state %d [coming from %d, ack %d]\n", - (unsigned int)( timestamp() % 100000 ), (int)new_state.num, - (int)inst.old_num(), (int)inst.ack_num() ); + fprintf( stderr, + "[%u] Received state %d [coming from %d, ack %d]\n", + (unsigned int)( timestamp() % 100000 ), + (int)new_state.num, + (int)inst.old_num(), + (int)inst.ack_num() ); } received_states.push_back( new_state ); sender.set_ack_num( received_states.back().num ); @@ -179,15 +182,13 @@ void Transport::recv( void ) { } } -/* The sender uses throwaway_num to tell us the earliest received state that we - * need to keep around */ -template -void Transport::process_throwaway_until( - uint64_t throwaway_num ) { - typename list >::iterator i = - received_states.begin(); +/* The sender uses throwaway_num to tell us the earliest received state that we need to keep around */ +template +void Transport::process_throwaway_until( uint64_t throwaway_num ) +{ + typename list>::iterator i = received_states.begin(); while ( i != received_states.end() ) { - typename list >::iterator inext = i; + typename list>::iterator inext = i; inext++; if ( i->num < throwaway_num ) { received_states.erase( i ); @@ -198,18 +199,18 @@ void Transport::process_throwaway_until( fatal_assert( received_states.size() > 0 ); } -template -string Transport::get_remote_diff( void ) { - /* find diff between last receiver state and current remote state, then - * rationalize states */ +template +string Transport::get_remote_diff( void ) +{ + /* find diff between last receiver state and current remote state, then rationalize states */ string ret( received_states.back().state.diff_from( last_receiver_state ) ); - const RemoteState *oldest_receiver_state = &received_states.front().state; + const RemoteState* oldest_receiver_state = &received_states.front().state; - for ( typename list >::reverse_iterator i = - received_states.rbegin(); - i != received_states.rend(); i++ ) { + for ( typename list>::reverse_iterator i = received_states.rbegin(); + i != received_states.rend(); + i++ ) { i->state.subtract( oldest_receiver_state ); } diff --git a/src/network/networktransport.h b/src/network/networktransport.h index e363679ae..422f3f9db 100644 --- a/src/network/networktransport.h +++ b/src/network/networktransport.h @@ -33,10 +33,10 @@ #ifndef NETWORK_TRANSPORT_HPP #define NETWORK_TRANSPORT_HPP -#include -#include #include +#include #include +#include #include #include "network.h" @@ -44,112 +44,91 @@ #include "transportsender.h" namespace Network { - template - class Transport { - private: - /* the underlying, encrypted network connection */ - Connection connection; - - /* sender side */ - TransportSender sender; - - /* helper methods for recv() */ - void process_throwaway_until( uint64_t throwaway_num ); - - /* simple receiver */ - list > received_states; - uint64_t receiver_quench_timer; - RemoteState last_receiver_state; /* the state we were in when user last - queried state */ - FragmentAssembly fragments; - unsigned int verbose; - - public: - Transport( MyState &initial_state, RemoteState &initial_remote, - const char *desired_ip, const char *desired_port ); - Transport( MyState &initial_state, RemoteState &initial_remote, - const char *key_str, const char *ip, const char *port ); - - /* Send data or an ack if necessary. */ - void tick( void ) { sender.tick(); } - - /* Returns the number of ms to wait until next possible event. */ - int wait_time( void ) { return sender.wait_time(); } - - /* Blocks waiting for a packet. */ - void recv( void ); - - /* Find diff between last receiver state and current remote state, then - * rationalize states. */ - string get_remote_diff( void ); - - /* Shut down other side of connection. */ - /* Illegal to change current_state after this. */ - void start_shutdown( void ) { sender.start_shutdown(); } - bool shutdown_in_progress( void ) const { - return sender.get_shutdown_in_progress(); - } - bool shutdown_acknowledged( void ) const { - return sender.get_shutdown_acknowledged(); - } - bool shutdown_ack_timed_out( void ) const { - return sender.shutdown_ack_timed_out(); - } - bool has_remote_addr( void ) const { - return connection.get_has_remote_addr(); - } - - /* Other side has requested shutdown and we have sent one ACK */ - bool counterparty_shutdown_ack_sent( void ) const { - return sender.get_counterparty_shutdown_acknowledged(); - } - - std::string port( void ) const { return connection.port(); } - string get_key( void ) const { return connection.get_key(); } - - MyState &get_current_state( void ) { return sender.get_current_state(); } - void set_current_state( const MyState &x ) { - sender.set_current_state( x ); - } - - uint64_t get_remote_state_num( void ) const { - return received_states.back().num; - } - - const TimestampedState &get_latest_remote_state( void ) const { - return received_states.back(); - } - - const std::vector fds( void ) const { return connection.fds(); } - - void set_verbose( unsigned int s_verbose ) { - sender.set_verbose( s_verbose ); - verbose = s_verbose; - } - - void set_send_delay( int new_delay ) { sender.set_send_delay( new_delay ); } - - uint64_t get_sent_state_acked_timestamp( void ) const { - return sender.get_sent_state_acked_timestamp(); - } - uint64_t get_sent_state_acked( void ) const { - return sender.get_sent_state_acked(); - } - uint64_t get_sent_state_last( void ) const { - return sender.get_sent_state_last(); - } - - unsigned int send_interval( void ) const { return sender.send_interval(); } - - const Addr &get_remote_addr( void ) const { - return connection.get_remote_addr(); - } - socklen_t get_remote_addr_len( void ) const { - return connection.get_remote_addr_len(); - } - - std::string &get_send_error( void ) { return connection.get_send_error(); } - }; +template +class Transport +{ +private: + /* the underlying, encrypted network connection */ + Connection connection; + + /* sender side */ + TransportSender sender; + + /* helper methods for recv() */ + void process_throwaway_until( uint64_t throwaway_num ); + + /* simple receiver */ + list> received_states; + uint64_t receiver_quench_timer; + RemoteState last_receiver_state; /* the state we were in when user last queried state */ + FragmentAssembly fragments; + unsigned int verbose; + +public: + Transport( MyState& initial_state, + RemoteState& initial_remote, + const char* desired_ip, + const char* desired_port ); + Transport( MyState& initial_state, + RemoteState& initial_remote, + const char* key_str, + const char* ip, + const char* port ); + + /* Send data or an ack if necessary. */ + void tick( void ) { sender.tick(); } + + /* Returns the number of ms to wait until next possible event. */ + int wait_time( void ) { return sender.wait_time(); } + + /* Blocks waiting for a packet. */ + void recv( void ); + + /* Find diff between last receiver state and current remote state, then rationalize states. */ + string get_remote_diff( void ); + + /* Shut down other side of connection. */ + /* Illegal to change current_state after this. */ + void start_shutdown( void ) { sender.start_shutdown(); } + bool shutdown_in_progress( void ) const { return sender.get_shutdown_in_progress(); } + bool shutdown_acknowledged( void ) const { return sender.get_shutdown_acknowledged(); } + bool shutdown_ack_timed_out( void ) const { return sender.shutdown_ack_timed_out(); } + bool has_remote_addr( void ) const { return connection.get_has_remote_addr(); } + + /* Other side has requested shutdown and we have sent one ACK */ + bool counterparty_shutdown_ack_sent( void ) const { return sender.get_counterparty_shutdown_acknowledged(); } + + std::string port( void ) const { return connection.port(); } + string get_key( void ) const { return connection.get_key(); } + + MyState& get_current_state( void ) { return sender.get_current_state(); } + void set_current_state( const MyState& x ) { sender.set_current_state( x ); } + + uint64_t get_remote_state_num( void ) const { return received_states.back().num; } + + const TimestampedState& get_latest_remote_state( void ) const { return received_states.back(); } + + const std::vector fds( void ) const { return connection.fds(); } + + void set_verbose( unsigned int s_verbose ) + { + sender.set_verbose( s_verbose ); + verbose = s_verbose; + } + + void set_send_delay( int new_delay ) { sender.set_send_delay( new_delay ); } + + uint64_t get_sent_state_acked_timestamp( void ) const { return sender.get_sent_state_acked_timestamp(); } + uint64_t get_sent_state_acked( void ) const { return sender.get_sent_state_acked(); } + uint64_t get_sent_state_last( void ) const { return sender.get_sent_state_last(); } + + unsigned int send_interval( void ) const { return sender.send_interval(); } + + const Addr& get_remote_addr( void ) const { return connection.get_remote_addr(); } + socklen_t get_remote_addr_len( void ) const { return connection.get_remote_addr_len(); } + + std::string& get_send_error( void ) { return connection.get_send_error(); } +}; } #endif diff --git a/src/network/transportfragment.cc b/src/network/transportfragment.cc index 840a324c7..88d0645a4 100644 --- a/src/network/transportfragment.cc +++ b/src/network/transportfragment.cc @@ -41,17 +41,20 @@ using namespace Network; using namespace TransportBuffers; -static string network_order_string( uint16_t host_order ) { +static string network_order_string( uint16_t host_order ) +{ uint16_t net_int = htobe16( host_order ); - return string( (char *)&net_int, sizeof( net_int ) ); + return string( (char*)&net_int, sizeof( net_int ) ); } -static string network_order_string( uint64_t host_order ) { +static string network_order_string( uint64_t host_order ) +{ uint64_t net_int = htobe64( host_order ); - return string( (char *)&net_int, sizeof( net_int ) ); + return string( (char*)&net_int, sizeof( net_int ) ); } -string Fragment::tostring( void ) { +string Fragment::tostring( void ) +{ assert( initialized ); string ret; @@ -59,8 +62,7 @@ string Fragment::tostring( void ) { ret += network_order_string( id ); fatal_assert( - !( fragment_num & 0x8000 ) ); /* effective limit on size of a terminal - screen change or buffered user input */ + !( fragment_num & 0x8000 ) ); /* effective limit on size of a terminal screen change or buffered user input */ uint16_t combined_fragment_num = ( final << 15 ) | fragment_num; ret += network_order_string( combined_fragment_num ); @@ -71,25 +73,27 @@ string Fragment::tostring( void ) { return ret; } -Fragment::Fragment( const string &x ) - : id( -1 ), - fragment_num( -1 ), - final( false ), - initialized( true ), - contents() { +Fragment::Fragment( const string& x ) + : id( -1 ) + , fragment_num( -1 ) + , final( false ) + , initialized( true ) + , contents() +{ fatal_assert( x.size() >= frag_header_len ); contents = string( x.begin() + frag_header_len, x.end() ); uint64_t data64; - uint16_t *data16 = (uint16_t *)x.data(); + uint16_t* data16 = (uint16_t*)x.data(); memcpy( &data64, x.data(), sizeof( data64 ) ); id = be64toh( data64 ); - fragment_num = be16toh( data16[ 4 ] ); + fragment_num = be16toh( data16[4] ); final = ( fragment_num & 0x8000 ) >> 15; fragment_num &= 0x7FFF; } -bool FragmentAssembly::add_fragment( Fragment &frag ) { +bool FragmentAssembly::add_fragment( Fragment& frag ) +{ /* see if this is a totally new packet */ if ( current_id != frag.id ) { fragments.clear(); @@ -100,8 +104,7 @@ bool FragmentAssembly::add_fragment( Fragment &frag ) { current_id = frag.id; } else { /* not a new packet */ /* see if we already have this fragment */ - if ( ( fragments.size() > frag.fragment_num ) - && ( fragments.at( frag.fragment_num ).initialized ) ) { + if ( ( fragments.size() > frag.fragment_num ) && ( fragments.at( frag.fragment_num ).initialized ) ) { /* make sure new version is same as what we already have */ assert( fragments.at( frag.fragment_num ) == frag ); } else { @@ -127,7 +130,8 @@ bool FragmentAssembly::add_fragment( Fragment &frag ) { return fragments_arrived == fragments_total; } -Instruction FragmentAssembly::get_assembly( void ) { +Instruction FragmentAssembly::get_assembly( void ) +{ assert( fragments_arrived == fragments_total ); string encoded; @@ -138,8 +142,7 @@ Instruction FragmentAssembly::get_assembly( void ) { } Instruction ret; - fatal_assert( - ret.ParseFromString( get_compressor().uncompress_str( encoded ) ) ); + fatal_assert( ret.ParseFromString( get_compressor().uncompress_str( encoded ) ) ); fragments.clear(); fragments_arrived = 0; @@ -148,27 +151,24 @@ Instruction FragmentAssembly::get_assembly( void ) { return ret; } -bool Fragment::operator==( const Fragment &x ) const { - return ( id == x.id ) && ( fragment_num == x.fragment_num ) - && ( final == x.final ) && ( initialized == x.initialized ) - && ( contents == x.contents ); +bool Fragment::operator==( const Fragment& x ) const +{ + return ( id == x.id ) && ( fragment_num == x.fragment_num ) && ( final == x.final ) + && ( initialized == x.initialized ) && ( contents == x.contents ); } -vector Fragmenter::make_fragments( const Instruction &inst, - size_t MTU ) { +vector Fragmenter::make_fragments( const Instruction& inst, size_t MTU ) +{ MTU -= Fragment::frag_header_len; - if ( ( inst.old_num() != last_instruction.old_num() ) - || ( inst.new_num() != last_instruction.new_num() ) + if ( ( inst.old_num() != last_instruction.old_num() ) || ( inst.new_num() != last_instruction.new_num() ) || ( inst.ack_num() != last_instruction.ack_num() ) || ( inst.throwaway_num() != last_instruction.throwaway_num() ) || ( inst.chaff() != last_instruction.chaff() ) - || ( inst.protocol_version() != last_instruction.protocol_version() ) - || ( last_MTU != MTU ) ) { + || ( inst.protocol_version() != last_instruction.protocol_version() ) || ( last_MTU != MTU ) ) { next_instruction_id++; } - if ( ( inst.old_num() == last_instruction.old_num() ) - && ( inst.new_num() == last_instruction.new_num() ) ) { + if ( ( inst.old_num() == last_instruction.old_num() ) && ( inst.new_num() == last_instruction.new_num() ) ) { assert( inst.diff() == last_instruction.diff() ); } @@ -192,8 +192,7 @@ vector Fragmenter::make_fragments( const Instruction &inst, final = true; } - ret.push_back( - Fragment( next_instruction_id, fragment_num++, final, this_fragment ) ); + ret.push_back( Fragment( next_instruction_id, fragment_num++, final, this_fragment ) ); } return ret; diff --git a/src/network/transportfragment.h b/src/network/transportfragment.h index 96f3c44d7..33c8ad098 100644 --- a/src/network/transportfragment.h +++ b/src/network/transportfragment.h @@ -40,76 +40,83 @@ #include "transportinstruction.pb.h" namespace Network { - using std::string; - using std::vector; - using namespace TransportBuffers; - - class Fragment { - public: - static const size_t frag_header_len = - sizeof( uint64_t ) + sizeof( uint16_t ); - - uint64_t id; - uint16_t fragment_num; - bool final; - - bool initialized; - - string contents; - - Fragment() - : id( -1 ), - fragment_num( -1 ), - final( false ), - initialized( false ), - contents() {} - - Fragment( uint64_t s_id, uint16_t s_fragment_num, bool s_final, - const string &s_contents ) - : id( s_id ), - fragment_num( s_fragment_num ), - final( s_final ), - initialized( true ), - contents( s_contents ) {} - - Fragment( const string &x ); - - string tostring( void ); - - bool operator==( const Fragment &x ) const; - }; - - class FragmentAssembly { - private: - vector fragments; - uint64_t current_id; - int fragments_arrived, fragments_total; - - public: - FragmentAssembly() - : fragments(), - current_id( -1 ), - fragments_arrived( 0 ), - fragments_total( -1 ) {} - bool add_fragment( Fragment &inst ); - Instruction get_assembly( void ); - }; - - class Fragmenter { - private: - uint64_t next_instruction_id; - Instruction last_instruction; - size_t last_MTU; - - public: - Fragmenter() - : next_instruction_id( 0 ), last_instruction(), last_MTU( -1 ) { - last_instruction.set_old_num( -1 ); - last_instruction.set_new_num( -1 ); - } - vector make_fragments( const Instruction &inst, size_t MTU ); - uint64_t last_ack_sent( void ) const { return last_instruction.ack_num(); } - }; +using std::string; +using std::vector; +using namespace TransportBuffers; + +class Fragment +{ +public: + static const size_t frag_header_len = sizeof( uint64_t ) + sizeof( uint16_t ); + + uint64_t id; + uint16_t fragment_num; + bool final; + + bool initialized; + + string contents; + + Fragment() + : id( -1 ) + , fragment_num( -1 ) + , final( false ) + , initialized( false ) + , contents() + {} + + Fragment( uint64_t s_id, uint16_t s_fragment_num, bool s_final, const string& s_contents ) + : id( s_id ) + , fragment_num( s_fragment_num ) + , final( s_final ) + , initialized( true ) + , contents( s_contents ) + {} + + Fragment( const string& x ); + + string tostring( void ); + + bool operator==( const Fragment& x ) const; +}; + +class FragmentAssembly +{ +private: + vector fragments; + uint64_t current_id; + int fragments_arrived, fragments_total; + +public: + FragmentAssembly() + : fragments() + , current_id( -1 ) + , fragments_arrived( 0 ) + , fragments_total( -1 ) + {} + bool add_fragment( Fragment& inst ); + Instruction get_assembly( void ); +}; + +class Fragmenter +{ +private: + uint64_t next_instruction_id; + Instruction last_instruction; + size_t last_MTU; + +public: + Fragmenter() + : next_instruction_id( 0 ) + , last_instruction() + , last_MTU( -1 ) + { + last_instruction.set_old_num( -1 ); + last_instruction.set_new_num( -1 ); + } + vector make_fragments( const Instruction& inst, size_t MTU ); + uint64_t last_ack_sent( void ) const { return last_instruction.ack_num(); } +}; } diff --git a/src/network/transportsender-impl.h b/src/network/transportsender-impl.h index ffe405402..3e70d3a29 100644 --- a/src/network/transportsender-impl.h +++ b/src/network/transportsender-impl.h @@ -33,11 +33,11 @@ #ifndef TRANSPORT_SENDER_IMPL_HPP #define TRANSPORT_SENDER_IMPL_HPP +#include +#include #include #include #include -#include -#include #include "transportfragment.h" #include "transportsender.h" @@ -46,31 +46,31 @@ using namespace Network; -template -TransportSender::TransportSender( Connection *s_connection, - MyState &initial_state ) - : connection( s_connection ), - current_state( initial_state ), - sent_states( 1, - TimestampedState( timestamp(), 0, initial_state ) ), - assumed_receiver_state( sent_states.begin() ), - fragmenter(), - next_ack_time( timestamp() ), - next_send_time( timestamp() ), - verbose( 0 ), - shutdown_in_progress( false ), - shutdown_tries( 0 ), - shutdown_start( -1 ), - ack_num( 0 ), - pending_data_ack( false ), - SEND_MINDELAY( 8 ), - last_heard( 0 ), - prng(), - mindelay_clock( -1 ) {} +template +TransportSender::TransportSender( Connection* s_connection, MyState& initial_state ) + : connection( s_connection ) + , current_state( initial_state ) + , sent_states( 1, TimestampedState( timestamp(), 0, initial_state ) ) + , assumed_receiver_state( sent_states.begin() ) + , fragmenter() + , next_ack_time( timestamp() ) + , next_send_time( timestamp() ) + , verbose( 0 ) + , shutdown_in_progress( false ) + , shutdown_tries( 0 ) + , shutdown_start( -1 ) + , ack_num( 0 ) + , pending_data_ack( false ) + , SEND_MINDELAY( 8 ) + , last_heard( 0 ) + , prng() + , mindelay_clock( -1 ) +{} /* Try to send roughly two frames per RTT, bounded by limits on frame rate */ -template -unsigned int TransportSender::send_interval( void ) const { +template +unsigned int TransportSender::send_interval( void ) const +{ int SEND_INTERVAL = lrint( ceil( connection->get_SRTT() / 2.0 ) ); if ( SEND_INTERVAL < SEND_INTERVAL_MIN ) { SEND_INTERVAL = SEND_INTERVAL_MIN; @@ -82,8 +82,9 @@ unsigned int TransportSender::send_interval( void ) const { } /* Housekeeping routine to calculate next send and ack times */ -template -void TransportSender::calculate_timers( void ) { +template +void TransportSender::calculate_timers( void ) +{ uint64_t now = timestamp(); /* Update assumed receiver state */ @@ -101,19 +102,14 @@ void TransportSender::calculate_timers( void ) { mindelay_clock = now; } - next_send_time = std::max( mindelay_clock + SEND_MINDELAY, - sent_states.back().timestamp + send_interval() ); - } else if ( !( current_state == assumed_receiver_state->state ) - && ( last_heard + ACTIVE_RETRY_TIMEOUT > now ) ) { + next_send_time = std::max( mindelay_clock + SEND_MINDELAY, sent_states.back().timestamp + send_interval() ); + } else if ( !( current_state == assumed_receiver_state->state ) && ( last_heard + ACTIVE_RETRY_TIMEOUT > now ) ) { next_send_time = sent_states.back().timestamp + send_interval(); if ( mindelay_clock != uint64_t( -1 ) ) { - next_send_time = - std::max( next_send_time, mindelay_clock + SEND_MINDELAY ); + next_send_time = std::max( next_send_time, mindelay_clock + SEND_MINDELAY ); } - } else if ( !( current_state == sent_states.front().state ) - && ( last_heard + ACTIVE_RETRY_TIMEOUT > now ) ) { - next_send_time = - sent_states.back().timestamp + connection->timeout() + ACK_DELAY; + } else if ( !( current_state == sent_states.front().state ) && ( last_heard + ACTIVE_RETRY_TIMEOUT > now ) ) { + next_send_time = sent_states.back().timestamp + connection->timeout() + ACK_DELAY; } else { next_send_time = uint64_t( -1 ); } @@ -125,8 +121,9 @@ void TransportSender::calculate_timers( void ) { } /* How many ms to wait until next event */ -template -int TransportSender::wait_time( void ) { +template +int TransportSender::wait_time( void ) +{ calculate_timers(); uint64_t next_wakeup = next_ack_time; @@ -148,8 +145,9 @@ int TransportSender::wait_time( void ) { } /* Send data or an empty ack if necessary */ -template -void TransportSender::tick( void ) { +template +void TransportSender::tick( void ) +{ calculate_timers(); /* updates assumed receiver state and rationalizes */ if ( !connection->get_has_remote_addr() ) { @@ -169,21 +167,17 @@ void TransportSender::tick( void ) { attempt_prospective_resend_optimization( diff ); if ( verbose ) { - /* verify diff has round-trip identity (modulo Unicode fallback rendering) - */ + /* verify diff has round-trip identity (modulo Unicode fallback rendering) */ MyState newstate( assumed_receiver_state->state ); newstate.apply_string( diff ); if ( current_state.compare( newstate ) ) { - fprintf( stderr, - "Warning, round-trip Instruction verification failed!\n" ); + fprintf( stderr, "Warning, round-trip Instruction verification failed!\n" ); } - /* Also verify that both the original frame and generated frame have the - * same initial diff. */ + /* Also verify that both the original frame and generated frame have the same initial diff. */ std::string current_diff( current_state.init_diff() ); std::string new_diff( newstate.init_diff() ); if ( current_diff != new_diff ) { - fprintf( stderr, - "Warning, target state Instruction verification failed!\n" ); + fprintf( stderr, "Warning, target state Instruction verification failed!\n" ); } } @@ -203,8 +197,9 @@ void TransportSender::tick( void ) { } } -template -void TransportSender::send_empty_ack( void ) { +template +void TransportSender::send_empty_ack( void ) +{ uint64_t now = timestamp(); assert( now >= next_ack_time ); @@ -216,8 +211,7 @@ void TransportSender::send_empty_ack( void ) { new_num = uint64_t( -1 ); } - // sent_states.push_back( TimestampedState( - // sent_states.back().timestamp, new_num, current_state ) ); + // sent_states.push_back( TimestampedState( sent_states.back().timestamp, new_num, current_state ) ); add_sent_state( now, new_num, current_state ); send_in_fragments( "", new_num ); @@ -225,11 +219,10 @@ void TransportSender::send_empty_ack( void ) { next_send_time = uint64_t( -1 ); } -template -void TransportSender::add_sent_state( uint64_t the_timestamp, - uint64_t num, MyState &state ) { - sent_states.push_back( - TimestampedState( the_timestamp, num, state ) ); +template +void TransportSender::add_sent_state( uint64_t the_timestamp, uint64_t num, MyState& state ) +{ + sent_states.push_back( TimestampedState( the_timestamp, num, state ) ); if ( sent_states.size() > 32 ) { /* limit on state queue */ typename sent_states_type::iterator last = sent_states.end(); for ( int i = 0; i < 16; i++ ) { @@ -239,8 +232,9 @@ void TransportSender::add_sent_state( uint64_t the_timestamp, } } -template -void TransportSender::send_to_receiver( const string &diff ) { +template +void TransportSender::send_to_receiver( const string& diff ) +{ uint64_t new_num; if ( current_state == sent_states.back().state ) { /* previously sent */ new_num = sent_states.back().num; @@ -259,26 +253,26 @@ void TransportSender::send_to_receiver( const string &diff ) { add_sent_state( timestamp(), new_num, current_state ); } - send_in_fragments( diff, new_num ); // Can throw NetworkException + send_in_fragments( diff, new_num ); // Can throw NetworkException /* successfully sent, probably */ - /* ("probably" because the FIRST size-exceeded datagram doesn't get an error) - */ + /* ("probably" because the FIRST size-exceeded datagram doesn't get an error) */ assumed_receiver_state = sent_states.end(); assumed_receiver_state--; next_ack_time = timestamp() + ACK_INTERVAL; next_send_time = uint64_t( -1 ); } -template -void TransportSender::update_assumed_receiver_state( void ) { +template +void TransportSender::update_assumed_receiver_state( void ) +{ uint64_t now = timestamp(); - /* start from what is known and give benefit of the doubt to unacknowledged - states transmitted recently enough ago */ + /* start from what is known and give benefit of the doubt to unacknowledged states + transmitted recently enough ago */ assumed_receiver_state = sent_states.begin(); - typename list >::iterator i = sent_states.begin(); + typename list>::iterator i = sent_states.begin(); i++; while ( i != sent_states.end() ) { @@ -294,32 +288,34 @@ void TransportSender::update_assumed_receiver_state( void ) { } } -template -void TransportSender::rationalize_states( void ) { - const MyState *known_receiver_state = &sent_states.front().state; +template +void TransportSender::rationalize_states( void ) +{ + const MyState* known_receiver_state = &sent_states.front().state; current_state.subtract( known_receiver_state ); - for ( typename list >::reverse_iterator i = - sent_states.rbegin(); - i != sent_states.rend(); i++ ) { + for ( typename list>::reverse_iterator i = sent_states.rbegin(); + i != sent_states.rend(); + i++ ) { i->state.subtract( known_receiver_state ); } } -template -const string TransportSender::make_chaff( void ) { +template +const string TransportSender::make_chaff( void ) +{ const size_t CHAFF_MAX = 16; const size_t chaff_len = prng.uint8() % ( CHAFF_MAX + 1 ); - char chaff[ CHAFF_MAX ]; + char chaff[CHAFF_MAX]; prng.fill( chaff, chaff_len ); return string( chaff, chaff_len ); } -template -void TransportSender::send_in_fragments( const string &diff, - uint64_t new_num ) { +template +void TransportSender::send_in_fragments( const string& diff, uint64_t new_num ) +{ Instruction inst; inst.set_protocol_version( MOSH_PROTOCOL_VERSION ); @@ -335,30 +331,34 @@ void TransportSender::send_in_fragments( const string &diff, } vector fragments = fragmenter.make_fragments( - inst, connection->get_MTU() - Network::Connection::ADDED_BYTES - - Crypto::Session::ADDED_BYTES ); - for ( vector::iterator i = fragments.begin(); i != fragments.end(); - i++ ) { + inst, connection->get_MTU() - Network::Connection::ADDED_BYTES - Crypto::Session::ADDED_BYTES ); + for ( vector::iterator i = fragments.begin(); i != fragments.end(); i++ ) { connection->send( i->tostring() ); if ( verbose ) { - fprintf( stderr, - "[%u] Sent [%d=>%d] id %d, frag %d ack=%d, throwaway=%d, " - "len=%d, frame rate=%.2f, timeout=%d, srtt=%.1f\n", - (unsigned int)( timestamp() % 100000 ), (int)inst.old_num(), - (int)inst.new_num(), (int)i->id, (int)i->fragment_num, - (int)inst.ack_num(), (int)inst.throwaway_num(), - (int)i->contents.size(), 1000.0 / (double)send_interval(), - (int)connection->timeout(), connection->get_SRTT() ); + fprintf( + stderr, + "[%u] Sent [%d=>%d] id %d, frag %d ack=%d, throwaway=%d, len=%d, frame rate=%.2f, timeout=%d, srtt=%.1f\n", + (unsigned int)( timestamp() % 100000 ), + (int)inst.old_num(), + (int)inst.new_num(), + (int)i->id, + (int)i->fragment_num, + (int)inst.ack_num(), + (int)inst.throwaway_num(), + (int)i->contents.size(), + 1000.0 / (double)send_interval(), + (int)connection->timeout(), + connection->get_SRTT() ); } } pending_data_ack = false; } -template -void TransportSender::process_acknowledgment_through( - uint64_t ack_num ) { +template +void TransportSender::process_acknowledgment_through( uint64_t ack_num ) +{ /* Ignore ack if we have culled the state it's acknowledging */ typename sent_states_type::iterator i; @@ -382,13 +382,13 @@ void TransportSender::process_acknowledgment_through( } /* give up on getting acknowledgement for shutdown */ -template -bool TransportSender::shutdown_ack_timed_out( void ) const { +template +bool TransportSender::shutdown_ack_timed_out( void ) const +{ if ( shutdown_in_progress ) { if ( shutdown_tries >= SHUTDOWN_RETRIES ) { return true; - } else if ( timestamp() - shutdown_start - >= uint64_t( ACTIVE_RETRY_TIMEOUT ) ) { + } else if ( timestamp() - shutdown_start >= uint64_t( ACTIVE_RETRY_TIMEOUT ) ) { return true; } } @@ -397,16 +397,17 @@ bool TransportSender::shutdown_ack_timed_out( void ) const { } /* Executed upon entry to new receiver state */ -template -void TransportSender::set_ack_num( uint64_t s_ack_num ) { +template +void TransportSender::set_ack_num( uint64_t s_ack_num ) +{ ack_num = s_ack_num; } /* Investigate diff against known receiver state instead */ /* Mutates proposed_diff */ -template -void TransportSender::attempt_prospective_resend_optimization( - string &proposed_diff ) { +template +void TransportSender::attempt_prospective_resend_optimization( string& proposed_diff ) +{ if ( assumed_receiver_state == sent_states.begin() ) { return; } @@ -418,8 +419,7 @@ void TransportSender::attempt_prospective_resend_optimization( less than 1000 bytes. */ if ( ( resend_diff.size() <= proposed_diff.size() ) - || ( ( resend_diff.size() < 1000 ) - && ( resend_diff.size() - proposed_diff.size() < 100 ) ) ) { + || ( ( resend_diff.size() < 1000 ) && ( resend_diff.size() - proposed_diff.size() < 100 ) ) ) { assumed_receiver_state = sent_states.begin(); proposed_diff = resend_diff; } diff --git a/src/network/transportsender.h b/src/network/transportsender.h index 6c1fcdaec..228234a37 100644 --- a/src/network/transportsender.h +++ b/src/network/transportsender.h @@ -43,142 +43,135 @@ #include "transportstate.h" namespace Network { - using std::list; - using std::pair; - using namespace TransportBuffers; +using std::list; +using std::pair; +using namespace TransportBuffers; - /* timing parameters */ - const int SEND_INTERVAL_MIN = 20; /* ms between frames */ - const int SEND_INTERVAL_MAX = 250; /* ms between frames */ - const int ACK_INTERVAL = 3000; /* ms between empty acks */ - const int ACK_DELAY = 100; /* ms before delayed ack */ - const int SHUTDOWN_RETRIES = - 16; /* number of shutdown packets to send before giving up */ - const int ACTIVE_RETRY_TIMEOUT = 10000; /* attempt to resend at frame rate */ +/* timing parameters */ +const int SEND_INTERVAL_MIN = 20; /* ms between frames */ +const int SEND_INTERVAL_MAX = 250; /* ms between frames */ +const int ACK_INTERVAL = 3000; /* ms between empty acks */ +const int ACK_DELAY = 100; /* ms before delayed ack */ +const int SHUTDOWN_RETRIES = 16; /* number of shutdown packets to send before giving up */ +const int ACTIVE_RETRY_TIMEOUT = 10000; /* attempt to resend at frame rate */ - template - class TransportSender { - private: - /* helper methods for tick() */ - void update_assumed_receiver_state( void ); - void attempt_prospective_resend_optimization( string &proposed_diff ); - void rationalize_states( void ); - void send_to_receiver( const string &diff ); - void send_empty_ack( void ); - void send_in_fragments( const string &diff, uint64_t new_num ); - void add_sent_state( uint64_t the_timestamp, uint64_t num, MyState &state ); +template +class TransportSender +{ +private: + /* helper methods for tick() */ + void update_assumed_receiver_state( void ); + void attempt_prospective_resend_optimization( string& proposed_diff ); + void rationalize_states( void ); + void send_to_receiver( const string& diff ); + void send_empty_ack( void ); + void send_in_fragments( const string& diff, uint64_t new_num ); + void add_sent_state( uint64_t the_timestamp, uint64_t num, MyState& state ); - /* state of sender */ - Connection *connection; + /* state of sender */ + Connection* connection; - MyState current_state; + MyState current_state; - typedef list > sent_states_type; - sent_states_type sent_states; - /* first element: known, acknowledged receiver state */ - /* last element: last sent state */ + typedef list> sent_states_type; + sent_states_type sent_states; + /* first element: known, acknowledged receiver state */ + /* last element: last sent state */ - /* somewhere in the middle: the assumed state of the receiver */ - typename sent_states_type::iterator assumed_receiver_state; + /* somewhere in the middle: the assumed state of the receiver */ + typename sent_states_type::iterator assumed_receiver_state; - /* for fragment creation */ - Fragmenter fragmenter; + /* for fragment creation */ + Fragmenter fragmenter; - /* timing state */ - uint64_t next_ack_time; - uint64_t next_send_time; + /* timing state */ + uint64_t next_ack_time; + uint64_t next_send_time; - void calculate_timers( void ); + void calculate_timers( void ); - unsigned int verbose; - bool shutdown_in_progress; - int shutdown_tries; - uint64_t shutdown_start; + unsigned int verbose; + bool shutdown_in_progress; + int shutdown_tries; + uint64_t shutdown_start; - /* information about receiver state */ - uint64_t ack_num; - bool pending_data_ack; + /* information about receiver state */ + uint64_t ack_num; + bool pending_data_ack; - unsigned int SEND_MINDELAY; /* ms to collect all input */ + unsigned int SEND_MINDELAY; /* ms to collect all input */ - uint64_t last_heard; /* last time received new state */ + uint64_t last_heard; /* last time received new state */ - /* chaff to disguise instruction length */ - PRNG prng; - const string make_chaff( void ); + /* chaff to disguise instruction length */ + PRNG prng; + const string make_chaff( void ); - uint64_t mindelay_clock; /* time of first pending change to current state */ + uint64_t mindelay_clock; /* time of first pending change to current state */ - public: - /* constructor */ - TransportSender( Connection *s_connection, MyState &initial_state ); +public: + /* constructor */ + TransportSender( Connection* s_connection, MyState& initial_state ); - /* Send data or an ack if necessary */ - void tick( void ); + /* Send data or an ack if necessary */ + void tick( void ); - /* Returns the number of ms to wait until next possible event. */ - int wait_time( void ); + /* Returns the number of ms to wait until next possible event. */ + int wait_time( void ); - /* Executed upon receipt of ack */ - void process_acknowledgment_through( uint64_t ack_num ); + /* Executed upon receipt of ack */ + void process_acknowledgment_through( uint64_t ack_num ); - /* Executed upon entry to new receiver state */ - void set_ack_num( uint64_t s_ack_num ); + /* Executed upon entry to new receiver state */ + void set_ack_num( uint64_t s_ack_num ); - /* Accelerate reply ack */ - void set_data_ack( void ) { pending_data_ack = true; } + /* Accelerate reply ack */ + void set_data_ack( void ) { pending_data_ack = true; } - /* Received something */ - void remote_heard( uint64_t ts ) { last_heard = ts; } + /* Received something */ + void remote_heard( uint64_t ts ) { last_heard = ts; } - /* Starts shutdown sequence */ - void start_shutdown( void ) { - if ( !shutdown_in_progress ) { - shutdown_start = timestamp(); - shutdown_in_progress = true; - } + /* Starts shutdown sequence */ + void start_shutdown( void ) + { + if ( !shutdown_in_progress ) { + shutdown_start = timestamp(); + shutdown_in_progress = true; } - - /* Misc. getters and setters */ - /* Cannot modify current_state while shutdown in progress */ - MyState &get_current_state( void ) { - assert( !shutdown_in_progress ); - return current_state; - } - void set_current_state( const MyState &x ) { - assert( !shutdown_in_progress ); - current_state = x; - current_state.reset_input(); - } - void set_verbose( unsigned int s_verbose ) { verbose = s_verbose; } - - bool get_shutdown_in_progress( void ) const { return shutdown_in_progress; } - bool get_shutdown_acknowledged( void ) const { - return sent_states.front().num == uint64_t( -1 ); - } - bool get_counterparty_shutdown_acknowledged( void ) const { - return fragmenter.last_ack_sent() == uint64_t( -1 ); - } - uint64_t get_sent_state_acked_timestamp( void ) const { - return sent_states.front().timestamp; - } - uint64_t get_sent_state_acked( void ) const { - return sent_states.front().num; - } - uint64_t get_sent_state_last( void ) const { - return sent_states.back().num; - } - - bool shutdown_ack_timed_out( void ) const; - - void set_send_delay( int new_delay ) { SEND_MINDELAY = new_delay; } - - unsigned int send_interval( void ) const; - - /* nonexistent methods to satisfy -Weffc++ */ - TransportSender( const TransportSender &x ); - TransportSender &operator=( const TransportSender &x ); - }; + } + + /* Misc. getters and setters */ + /* Cannot modify current_state while shutdown in progress */ + MyState& get_current_state( void ) + { + assert( !shutdown_in_progress ); + return current_state; + } + void set_current_state( const MyState& x ) + { + assert( !shutdown_in_progress ); + current_state = x; + current_state.reset_input(); + } + void set_verbose( unsigned int s_verbose ) { verbose = s_verbose; } + + bool get_shutdown_in_progress( void ) const { return shutdown_in_progress; } + bool get_shutdown_acknowledged( void ) const { return sent_states.front().num == uint64_t( -1 ); } + bool get_counterparty_shutdown_acknowledged( void ) const { return fragmenter.last_ack_sent() == uint64_t( -1 ); } + uint64_t get_sent_state_acked_timestamp( void ) const { return sent_states.front().timestamp; } + uint64_t get_sent_state_acked( void ) const { return sent_states.front().num; } + uint64_t get_sent_state_last( void ) const { return sent_states.back().num; } + + bool shutdown_ack_timed_out( void ) const; + + void set_send_delay( int new_delay ) { SEND_MINDELAY = new_delay; } + + unsigned int send_interval( void ) const; + + /* nonexistent methods to satisfy -Weffc++ */ + TransportSender( const TransportSender& x ); + TransportSender& operator=( const TransportSender& x ); +}; } #endif diff --git a/src/network/transportstate.h b/src/network/transportstate.h index 001b1c3b4..5a862f6aa 100644 --- a/src/network/transportstate.h +++ b/src/network/transportstate.h @@ -34,17 +34,20 @@ #define TRANSPORT_STATE_HPP namespace Network { - template - class TimestampedState { - public: - uint64_t timestamp; - uint64_t num; - State state; - - TimestampedState( uint64_t s_timestamp, uint64_t s_num, - const State &s_state ) - : timestamp( s_timestamp ), num( s_num ), state( s_state ) {} - }; +template +class TimestampedState +{ +public: + uint64_t timestamp; + uint64_t num; + State state; + + TimestampedState( uint64_t s_timestamp, uint64_t s_num, const State& s_state ) + : timestamp( s_timestamp ) + , num( s_num ) + , state( s_state ) + {} +}; } #endif diff --git a/src/statesync/completeterminal.cc b/src/statesync/completeterminal.cc index 544b72cdd..0dbbb0152 100644 --- a/src/statesync/completeterminal.cc +++ b/src/statesync/completeterminal.cc @@ -42,14 +42,15 @@ using namespace Parser; using namespace Terminal; using namespace HostBuffers; -string Complete::act( const string &str ) { +string Complete::act( const string& str ) +{ for ( unsigned int i = 0; i < str.size(); i++ ) { /* parse octet into up to three actions */ - parser.input( str[ i ], actions ); + parser.input( str[i], actions ); /* apply actions to terminal and delete them */ for ( Actions::iterator it = actions.begin(); it != actions.end(); it++ ) { - Action &act = **it; + Action& act = **it; act.act_on_terminal( &terminal ); } actions.clear(); @@ -58,37 +59,34 @@ string Complete::act( const string &str ) { return terminal.read_octets_to_host(); } -string Complete::act( const Action &act ) { +string Complete::act( const Action& act ) +{ /* apply action to terminal */ act.act_on_terminal( &terminal ); return terminal.read_octets_to_host(); } /* interface for Network::Transport */ -string Complete::diff_from( const Complete &existing ) const { +string Complete::diff_from( const Complete& existing ) const +{ HostBuffers::HostMessage output; if ( existing.get_echo_ack() != get_echo_ack() ) { assert( get_echo_ack() >= existing.get_echo_ack() ); - Instruction *new_echo = output.add_instruction(); + Instruction* new_echo = output.add_instruction(); new_echo->MutableExtension( echoack )->set_echo_ack_num( get_echo_ack() ); } if ( !( existing.get_fb() == get_fb() ) ) { - if ( ( existing.get_fb().ds.get_width() - != terminal.get_fb().ds.get_width() ) - || ( existing.get_fb().ds.get_height() - != terminal.get_fb().ds.get_height() ) ) { - Instruction *new_res = output.add_instruction(); - new_res->MutableExtension( resize )->set_width( - terminal.get_fb().ds.get_width() ); - new_res->MutableExtension( resize )->set_height( - terminal.get_fb().ds.get_height() ); + if ( ( existing.get_fb().ds.get_width() != terminal.get_fb().ds.get_width() ) + || ( existing.get_fb().ds.get_height() != terminal.get_fb().ds.get_height() ) ) { + Instruction* new_res = output.add_instruction(); + new_res->MutableExtension( resize )->set_width( terminal.get_fb().ds.get_width() ); + new_res->MutableExtension( resize )->set_height( terminal.get_fb().ds.get_height() ); } - string update = - display.new_frame( true, existing.get_fb(), terminal.get_fb() ); + string update = display.new_frame( true, existing.get_fb(), terminal.get_fb() ); if ( !update.empty() ) { - Instruction *new_inst = output.add_instruction(); + Instruction* new_inst = output.add_instruction(); new_inst->MutableExtension( hostbytes )->set_hoststring( update ); } } @@ -96,51 +94,49 @@ string Complete::diff_from( const Complete &existing ) const { return output.SerializeAsString(); } -string Complete::init_diff( void ) const { - return diff_from( - Complete( get_fb().ds.get_width(), get_fb().ds.get_height() ) ); +string Complete::init_diff( void ) const +{ + return diff_from( Complete( get_fb().ds.get_width(), get_fb().ds.get_height() ) ); } -void Complete::apply_string( const string &diff ) { +void Complete::apply_string( const string& diff ) +{ HostBuffers::HostMessage input; fatal_assert( input.ParseFromString( diff ) ); for ( int i = 0; i < input.instruction_size(); i++ ) { if ( input.instruction( i ).HasExtension( hostbytes ) ) { - string terminal_to_host = - act( input.instruction( i ).GetExtension( hostbytes ).hoststring() ); - assert( terminal_to_host - .empty() ); /* server never interrogates client terminal */ + string terminal_to_host = act( input.instruction( i ).GetExtension( hostbytes ).hoststring() ); + assert( terminal_to_host.empty() ); /* server never interrogates client terminal */ } else if ( input.instruction( i ).HasExtension( resize ) ) { act( Resize( input.instruction( i ).GetExtension( resize ).width(), input.instruction( i ).GetExtension( resize ).height() ) ); } else if ( input.instruction( i ).HasExtension( echoack ) ) { - uint64_t inst_echo_ack_num = - input.instruction( i ).GetExtension( echoack ).echo_ack_num(); + uint64_t inst_echo_ack_num = input.instruction( i ).GetExtension( echoack ).echo_ack_num(); assert( inst_echo_ack_num >= echo_ack ); echo_ack = inst_echo_ack_num; } } } -bool Complete::operator==( Complete const &x ) const { +bool Complete::operator==( Complete const& x ) const +{ // assert( parser == x.parser ); /* parser state is irrelevant for us */ return ( terminal == x.terminal ) && ( echo_ack == x.echo_ack ); } -bool Complete::set_echo_ack( uint64_t now ) { +bool Complete::set_echo_ack( uint64_t now ) +{ bool ret = false; uint64_t newest_echo_ack = 0; - for ( input_history_type::const_iterator i = input_history.begin(); - i != input_history.end(); i++ ) { + for ( input_history_type::const_iterator i = input_history.begin(); i != input_history.end(); i++ ) { if ( i->second <= now - ECHO_TIMEOUT ) { newest_echo_ack = i->first; } } - for ( input_history_type::iterator i = input_history.begin(); - i != input_history.end(); ) { + for ( input_history_type::iterator i = input_history.begin(); i != input_history.end(); ) { input_history_type::iterator i_next = i; i_next++; if ( i->first < newest_echo_ack ) { @@ -158,11 +154,13 @@ bool Complete::set_echo_ack( uint64_t now ) { return ret; } -void Complete::register_input_frame( uint64_t n, uint64_t now ) { +void Complete::register_input_frame( uint64_t n, uint64_t now ) +{ input_history.push_back( std::make_pair( n, now ) ); } -int Complete::wait_time( uint64_t now ) const { +int Complete::wait_time( uint64_t now ) const +{ if ( input_history.size() < 2 ) { return INT_MAX; } @@ -177,18 +175,18 @@ int Complete::wait_time( uint64_t now ) const { return next_echo_ack_time - now; } -bool Complete::compare( const Complete &other ) const { +bool Complete::compare( const Complete& other ) const +{ bool ret = false; - const Framebuffer &fb = terminal.get_fb(); - const Framebuffer &other_fb = other.terminal.get_fb(); + const Framebuffer& fb = terminal.get_fb(); + const Framebuffer& other_fb = other.terminal.get_fb(); const int height = fb.ds.get_height(); const int other_height = other_fb.ds.get_height(); const int width = fb.ds.get_width(); const int other_width = other_fb.ds.get_width(); if ( height != other_height || width != other_width ) { - fprintf( stderr, "Framebuffer size (%dx%d, %dx%d) differs.\n", width, - height, other_width, other_height ); + fprintf( stderr, "Framebuffer size (%dx%d, %dx%d) differs.\n", width, height, other_width, other_height ); return true; } @@ -203,9 +201,12 @@ bool Complete::compare( const Complete &other ) const { if ( ( fb.ds.get_cursor_row() != other_fb.ds.get_cursor_row() ) || ( fb.ds.get_cursor_col() != other_fb.ds.get_cursor_col() ) ) { - fprintf( stderr, "Cursor mismatch: (%d, %d) vs. (%d, %d).\n", - fb.ds.get_cursor_row(), fb.ds.get_cursor_col(), - other_fb.ds.get_cursor_row(), other_fb.ds.get_cursor_col() ); + fprintf( stderr, + "Cursor mismatch: (%d, %d) vs. (%d, %d).\n", + fb.ds.get_cursor_row(), + fb.ds.get_cursor_col(), + other_fb.ds.get_cursor_row(), + other_fb.ds.get_cursor_col() ); ret = true; } /* XXX should compare other terminal state too (mouse mode, bell. etc.) */ diff --git a/src/statesync/completeterminal.h b/src/statesync/completeterminal.h index 312d12d34..d229dddba 100644 --- a/src/statesync/completeterminal.h +++ b/src/statesync/completeterminal.h @@ -33,61 +33,62 @@ #ifndef COMPLETE_TERMINAL_HPP #define COMPLETE_TERMINAL_HPP -#include #include +#include #include "parser.h" #include "terminal.h" -/* This class represents the complete terminal -- a UTF8Parser feeding Actions - * to an Emulator. */ +/* This class represents the complete terminal -- a UTF8Parser feeding Actions to an Emulator. */ namespace Terminal { - class Complete { - private: - Parser::UTF8Parser parser; - Terminal::Emulator terminal; - Terminal::Display display; - - // Only used locally by act(), but kept here as a performance optimization, - // to avoid construction/destruction. It must always be empty - // outside calls to act() to keep horrible things from happening. - Parser::Actions actions; - - typedef std::list > input_history_type; - input_history_type input_history; - uint64_t echo_ack; - - static const int ECHO_TIMEOUT = 50; /* for late ack */ - - public: - Complete( size_t width, size_t height ) - : parser(), - terminal( width, height ), - display( false ), - actions(), - input_history(), - echo_ack( 0 ) {} - - std::string act( const std::string &str ); - std::string act( const Parser::Action &act ); - - const Framebuffer &get_fb( void ) const { return terminal.get_fb(); } - void reset_input( void ) { parser.reset_input(); } - uint64_t get_echo_ack( void ) const { return echo_ack; } - bool set_echo_ack( uint64_t now ); - void register_input_frame( uint64_t n, uint64_t now ); - int wait_time( uint64_t now ) const; - - /* interface for Network::Transport */ - void subtract( const Complete * ) const {} - std::string diff_from( const Complete &existing ) const; - std::string init_diff( void ) const; - void apply_string( const std::string &diff ); - bool operator==( const Complete &x ) const; - - bool compare( const Complete &other ) const; - }; +class Complete +{ +private: + Parser::UTF8Parser parser; + Terminal::Emulator terminal; + Terminal::Display display; + + // Only used locally by act(), but kept here as a performance optimization, + // to avoid construction/destruction. It must always be empty + // outside calls to act() to keep horrible things from happening. + Parser::Actions actions; + + typedef std::list> input_history_type; + input_history_type input_history; + uint64_t echo_ack; + + static const int ECHO_TIMEOUT = 50; /* for late ack */ + +public: + Complete( size_t width, size_t height ) + : parser() + , terminal( width, height ) + , display( false ) + , actions() + , input_history() + , echo_ack( 0 ) + {} + + std::string act( const std::string& str ); + std::string act( const Parser::Action& act ); + + const Framebuffer& get_fb( void ) const { return terminal.get_fb(); } + void reset_input( void ) { parser.reset_input(); } + uint64_t get_echo_ack( void ) const { return echo_ack; } + bool set_echo_ack( uint64_t now ); + void register_input_frame( uint64_t n, uint64_t now ); + int wait_time( uint64_t now ) const; + + /* interface for Network::Transport */ + void subtract( const Complete* ) const {} + std::string diff_from( const Complete& existing ) const; + std::string init_diff( void ) const; + void apply_string( const std::string& diff ); + bool operator==( const Complete& x ) const; + + bool compare( const Complete& other ) const; +}; } #endif diff --git a/src/statesync/user.cc b/src/statesync/user.cc index 9e95ce196..5e8301e9a 100644 --- a/src/statesync/user.cc +++ b/src/statesync/user.cc @@ -41,14 +41,14 @@ using namespace Parser; using namespace Network; using namespace ClientBuffers; -void UserStream::subtract( const UserStream *prefix ) { +void UserStream::subtract( const UserStream* prefix ) +{ // if we are subtracting ourself from ourself, just clear the deque if ( this == prefix ) { actions.clear(); return; } - for ( deque::const_iterator i = prefix->actions.begin(); - i != prefix->actions.end(); i++ ) { + for ( deque::const_iterator i = prefix->actions.begin(); i != prefix->actions.end(); i++ ) { assert( this != prefix ); assert( !actions.empty() ); assert( *i == actions.front() ); @@ -56,11 +56,11 @@ void UserStream::subtract( const UserStream *prefix ) { } } -string UserStream::diff_from( const UserStream &existing ) const { +string UserStream::diff_from( const UserStream& existing ) const +{ deque::const_iterator my_it = actions.begin(); - for ( deque::const_iterator i = existing.actions.begin(); - i != existing.actions.end(); i++ ) { + for ( deque::const_iterator i = existing.actions.begin(); i != existing.actions.end(); i++ ) { assert( my_it != actions.end() ); assert( *i == *my_it ); my_it++; @@ -70,32 +70,28 @@ string UserStream::diff_from( const UserStream &existing ) const { while ( my_it != actions.end() ) { switch ( my_it->type ) { - case UserByteType: - { + case UserByteType: { char the_byte = my_it->userbyte.c; /* can we combine this with a previous Keystroke? */ if ( ( output.instruction_size() > 0 ) - && ( output.instruction( output.instruction_size() - 1 ) - .HasExtension( keystroke ) ) ) { + && ( output.instruction( output.instruction_size() - 1 ).HasExtension( keystroke ) ) ) { output.mutable_instruction( output.instruction_size() - 1 ) - ->MutableExtension( keystroke ) - ->mutable_keys() - ->append( string( &the_byte, 1 ) ); + ->MutableExtension( keystroke ) + ->mutable_keys() + ->append( string( &the_byte, 1 ) ); } else { - Instruction *new_inst = output.add_instruction(); + Instruction* new_inst = output.add_instruction(); new_inst->MutableExtension( keystroke )->set_keys( &the_byte, 1 ); } - } - break; - case ResizeType: - { - Instruction *new_inst = output.add_instruction(); + } break; + case ResizeType: { + Instruction* new_inst = output.add_instruction(); new_inst->MutableExtension( resize )->set_width( my_it->resize.width ); - new_inst->MutableExtension( resize )->set_height( - my_it->resize.height ); - } - break; - default: assert( !"unexpected event type" ); break; + new_inst->MutableExtension( resize )->set_height( my_it->resize.height ); + } break; + default: + assert( !"unexpected event type" ); + break; } my_it++; @@ -104,32 +100,34 @@ string UserStream::diff_from( const UserStream &existing ) const { return output.SerializeAsString(); } -void UserStream::apply_string( const string &diff ) { +void UserStream::apply_string( const string& diff ) +{ ClientBuffers::UserMessage input; fatal_assert( input.ParseFromString( diff ) ); for ( int i = 0; i < input.instruction_size(); i++ ) { if ( input.instruction( i ).HasExtension( keystroke ) ) { - string the_bytes = - input.instruction( i ).GetExtension( keystroke ).keys(); + string the_bytes = input.instruction( i ).GetExtension( keystroke ).keys(); for ( unsigned int loc = 0; loc < the_bytes.size(); loc++ ) { actions.push_back( UserEvent( UserByte( the_bytes.at( loc ) ) ) ); } } else if ( input.instruction( i ).HasExtension( resize ) ) { - actions.push_back( UserEvent( - Resize( input.instruction( i ).GetExtension( resize ).width(), - input.instruction( i ).GetExtension( resize ).height() ) ) ); + actions.push_back( UserEvent( Resize( input.instruction( i ).GetExtension( resize ).width(), + input.instruction( i ).GetExtension( resize ).height() ) ) ); } } } -const Parser::Action &UserStream::get_action( unsigned int i ) const { - switch ( actions[ i ].type ) { - case UserByteType: return actions[ i ].userbyte; - case ResizeType: return actions[ i ].resize; - default: - assert( !"unexpected action type" ); - static const Parser::Ignore nothing = Parser::Ignore(); - return nothing; +const Parser::Action& UserStream::get_action( unsigned int i ) const +{ + switch ( actions[i].type ) { + case UserByteType: + return actions[i].userbyte; + case ResizeType: + return actions[i].resize; + default: + assert( !"unexpected action type" ); + static const Parser::Ignore nothing = Parser::Ignore(); + return nothing; } } diff --git a/src/statesync/user.h b/src/statesync/user.h index 11f2a4497..7e12a12dd 100644 --- a/src/statesync/user.h +++ b/src/statesync/user.h @@ -41,62 +41,70 @@ #include "parseraction.h" namespace Network { - using std::deque; - using std::list; - using std::string; - - enum UserEventType { UserByteType = 0, ResizeType = 1 }; - - class UserEvent { - public: - UserEventType type; - Parser::UserByte userbyte; - Parser::Resize resize; - - UserEvent( const Parser::UserByte &s_userbyte ) - : type( UserByteType ), userbyte( s_userbyte ), resize( -1, -1 ) {} - UserEvent( const Parser::Resize &s_resize ) - : type( ResizeType ), userbyte( 0 ), resize( s_resize ) {} - - private: - UserEvent(); - - public: - bool operator==( const UserEvent &x ) const { - return ( type == x.type ) && ( userbyte == x.userbyte ) - && ( resize == x.resize ); - } - }; - - class UserStream { - private: - deque actions; - - public: - UserStream() : actions() {} - - void push_back( const Parser::UserByte &s_userbyte ) { - actions.push_back( UserEvent( s_userbyte ) ); - } - void push_back( const Parser::Resize &s_resize ) { - actions.push_back( UserEvent( s_resize ) ); - } - - bool empty( void ) const { return actions.empty(); } - size_t size( void ) const { return actions.size(); } - const Parser::Action &get_action( unsigned int i ) const; - - /* interface for Network::Transport */ - void subtract( const UserStream *prefix ); - string diff_from( const UserStream &existing ) const; - string init_diff( void ) const { return diff_from( UserStream() ); }; - void apply_string( const string &diff ); - bool operator==( const UserStream &x ) const { - return actions == x.actions; - } - - bool compare( const UserStream & ) { return false; } - }; +using std::deque; +using std::list; +using std::string; + +enum UserEventType +{ + UserByteType = 0, + ResizeType = 1 +}; + +class UserEvent +{ +public: + UserEventType type; + Parser::UserByte userbyte; + Parser::Resize resize; + + UserEvent( const Parser::UserByte& s_userbyte ) + : type( UserByteType ) + , userbyte( s_userbyte ) + , resize( -1, -1 ) + {} + UserEvent( const Parser::Resize& s_resize ) + : type( ResizeType ) + , userbyte( 0 ) + , resize( s_resize ) + {} + +private: + UserEvent(); + +public: + bool operator==( const UserEvent& x ) const + { + return ( type == x.type ) && ( userbyte == x.userbyte ) && ( resize == x.resize ); + } +}; + +class UserStream +{ +private: + deque actions; + +public: + UserStream() + : actions() + {} + + void push_back( const Parser::UserByte& s_userbyte ) { actions.push_back( UserEvent( s_userbyte ) ); } + void push_back( const Parser::Resize& s_resize ) { actions.push_back( UserEvent( s_resize ) ); } + + bool empty( void ) const { return actions.empty(); } + size_t size( void ) const { return actions.size(); } + const Parser::Action& get_action( unsigned int i ) const; + + /* interface for Network::Transport */ + void subtract( const UserStream* prefix ); + string diff_from( const UserStream& existing ) const; + string init_diff( void ) const { return diff_from( UserStream() ); }; + void apply_string( const string& diff ); + bool operator==( const UserStream& x ) const { return actions == x.actions; } + + bool compare( const UserStream& ) { return false; } +}; } #endif diff --git a/src/terminal/parser.cc b/src/terminal/parser.cc index 5c3d70b26..9737d5aac 100644 --- a/src/terminal/parser.cc +++ b/src/terminal/parser.cc @@ -33,15 +33,15 @@ #include #include #include -#include #include +#include #include "parser.h" const Parser::StateFamily Parser::family; -static void append_or_delete( Parser::ActionPointer act, - Parser::Actions &vec ) { +static void append_or_delete( Parser::ActionPointer act, Parser::Actions& vec ) +{ assert( act ); if ( !act->ignore() ) { @@ -49,7 +49,8 @@ static void append_or_delete( Parser::ActionPointer act, } } -void Parser::Parser::input( wchar_t ch, Actions &ret ) { +void Parser::Parser::input( wchar_t ch, Actions& ret ) +{ Transition tx = state->input( ch ); if ( tx.next_state != NULL ) { @@ -64,12 +65,16 @@ void Parser::Parser::input( wchar_t ch, Actions &ret ) { } } -Parser::UTF8Parser::UTF8Parser() : parser(), buf_len( 0 ) { +Parser::UTF8Parser::UTF8Parser() + : parser() + , buf_len( 0 ) +{ assert( BUF_SIZE >= (size_t)MB_CUR_MAX ); - buf[ 0 ] = '\0'; + buf[0] = '\0'; } -void Parser::UTF8Parser::input( char c, Actions &ret ) { +void Parser::UTF8Parser::input( char c, Actions& ret ) +{ assert( buf_len < BUF_SIZE ); /* 1-byte UTF-8 character, aka ASCII? Cheat. */ @@ -78,7 +83,7 @@ void Parser::UTF8Parser::input( char c, Actions &ret ) { return; } - buf[ buf_len++ ] = c; + buf[buf_len++] = c; /* This function will only work in a UTF-8 locale. */ wchar_t pwc; @@ -104,11 +109,10 @@ void Parser::UTF8Parser::input( char c, Actions &ret ) { pwc = L'\0'; bytes_parsed = 1; } else if ( bytes_parsed == (size_t)-1 ) { - /* invalid sequence, use replacement character and try again with last - * char */ + /* invalid sequence, use replacement character and try again with last char */ assert( errno == EILSEQ ); if ( buf_len > 1 ) { - buf[ 0 ] = buf[ buf_len - 1 ]; + buf[0] = buf[buf_len - 1]; bytes_parsed = buf_len - 1; buf_len = 1; } else { @@ -136,8 +140,7 @@ void Parser::UTF8Parser::input( char c, Actions &ret ) { pwc = (wchar_t)0xFFFD; } - if ( ( pwcheck >= 0xD800 ) - && ( pwcheck <= 0xDFFF ) ) { /* surrogate code point */ + if ( ( pwcheck >= 0xD800 ) && ( pwcheck <= 0xDFFF ) ) { /* surrogate code point */ /* OS X unfortunately allows these sequences without EILSEQ, but they are ill-formed UTF-8 and we shouldn't repeat them to the @@ -152,9 +155,12 @@ void Parser::UTF8Parser::input( char c, Actions &ret ) { } } -Parser::Parser::Parser( const Parser &other ) : state( other.state ) {} +Parser::Parser::Parser( const Parser& other ) + : state( other.state ) +{} -Parser::Parser &Parser::Parser::operator=( const Parser &other ) { +Parser::Parser& Parser::Parser::operator=( const Parser& other ) +{ state = other.state; return *this; } diff --git a/src/terminal/parser.h b/src/terminal/parser.h index 8de07027a..a7b0843c8 100644 --- a/src/terminal/parser.h +++ b/src/terminal/parser.h @@ -45,44 +45,49 @@ #include "parsertransition.h" namespace Parser { - extern const StateFamily family; +extern const StateFamily family; - class Parser { - private: - State const *state; +class Parser +{ +private: + State const* state; - public: - Parser() : state( &family.s_Ground ) {} +public: + Parser() + : state( &family.s_Ground ) + {} - Parser( const Parser &other ); - Parser &operator=( const Parser & ); - ~Parser() {} + Parser( const Parser& other ); + Parser& operator=( const Parser& ); + ~Parser() {} - void input( wchar_t ch, Actions &actions ); + void input( wchar_t ch, Actions& actions ); - void reset_input( void ) { state = &family.s_Ground; } - }; + void reset_input( void ) { state = &family.s_Ground; } +}; - static const size_t BUF_SIZE = 8; +static const size_t BUF_SIZE = 8; - class UTF8Parser { - private: - Parser parser; +class UTF8Parser +{ +private: + Parser parser; - char buf[ BUF_SIZE ]; - size_t buf_len; + char buf[BUF_SIZE]; + size_t buf_len; - public: - UTF8Parser(); +public: + UTF8Parser(); - void input( char c, Actions &actions ); + void input( char c, Actions& actions ); - void reset_input( void ) { - parser.reset_input(); - buf[ 0 ] = '\0'; - buf_len = 0; - } - }; + void reset_input( void ) + { + parser.reset_input(); + buf[0] = '\0'; + buf_len = 0; + } +}; } #endif diff --git a/src/terminal/parseraction.cc b/src/terminal/parseraction.cc index c49631774..fbbdf7396 100644 --- a/src/terminal/parseraction.cc +++ b/src/terminal/parseraction.cc @@ -38,51 +38,62 @@ using namespace Parser; -void Print::act_on_terminal( Terminal::Emulator *emu ) const { +void Print::act_on_terminal( Terminal::Emulator* emu ) const +{ emu->print( this ); } -void Execute::act_on_terminal( Terminal::Emulator *emu ) const { +void Execute::act_on_terminal( Terminal::Emulator* emu ) const +{ emu->execute( this ); } -void Clear::act_on_terminal( Terminal::Emulator *emu ) const { +void Clear::act_on_terminal( Terminal::Emulator* emu ) const +{ emu->dispatch.clear( this ); } -void Param::act_on_terminal( Terminal::Emulator *emu ) const { +void Param::act_on_terminal( Terminal::Emulator* emu ) const +{ emu->dispatch.newparamchar( this ); } -void Collect::act_on_terminal( Terminal::Emulator *emu ) const { +void Collect::act_on_terminal( Terminal::Emulator* emu ) const +{ emu->dispatch.collect( this ); } -void CSI_Dispatch::act_on_terminal( Terminal::Emulator *emu ) const { +void CSI_Dispatch::act_on_terminal( Terminal::Emulator* emu ) const +{ emu->CSI_dispatch( this ); } -void Esc_Dispatch::act_on_terminal( Terminal::Emulator *emu ) const { +void Esc_Dispatch::act_on_terminal( Terminal::Emulator* emu ) const +{ emu->Esc_dispatch( this ); } -void OSC_Put::act_on_terminal( Terminal::Emulator *emu ) const { +void OSC_Put::act_on_terminal( Terminal::Emulator* emu ) const +{ emu->dispatch.OSC_put( this ); } -void OSC_Start::act_on_terminal( Terminal::Emulator *emu ) const { +void OSC_Start::act_on_terminal( Terminal::Emulator* emu ) const +{ emu->dispatch.OSC_start( this ); } -void OSC_End::act_on_terminal( Terminal::Emulator *emu ) const { +void OSC_End::act_on_terminal( Terminal::Emulator* emu ) const +{ emu->OSC_end( this ); } -void UserByte::act_on_terminal( Terminal::Emulator *emu ) const { - emu->dispatch.terminal_to_host.append( - emu->user.input( this, emu->fb.ds.application_mode_cursor_keys ) ); +void UserByte::act_on_terminal( Terminal::Emulator* emu ) const +{ + emu->dispatch.terminal_to_host.append( emu->user.input( this, emu->fb.ds.application_mode_cursor_keys ) ); } -void Resize::act_on_terminal( Terminal::Emulator *emu ) const { +void Resize::act_on_terminal( Terminal::Emulator* emu ) const +{ emu->resize( width, height ); } diff --git a/src/terminal/parseraction.h b/src/terminal/parseraction.h index cedfe120f..18005f741 100644 --- a/src/terminal/parseraction.h +++ b/src/terminal/parseraction.h @@ -39,124 +39,145 @@ #include "shared.h" namespace Terminal { - class Emulator; +class Emulator; } namespace Parser { - class Action { - public: - wchar_t ch; - bool char_present; - - virtual std::string name( void ) = 0; - - virtual void act_on_terminal( Terminal::Emulator * ) const {}; - - virtual bool ignore() const { return false; } - - Action() : ch( -1 ), char_present( false ) {}; - virtual ~Action() {}; - }; - - typedef shared::shared_ptr ActionPointer; - typedef std::vector Actions; - - class Ignore : public Action { - public: - std::string name( void ) { return std::string( "Ignore" ); } - bool ignore() const { return true; } - }; - class Print : public Action { - public: - std::string name( void ) { return std::string( "Print" ); } - void act_on_terminal( Terminal::Emulator *emu ) const; - }; - class Execute : public Action { - public: - std::string name( void ) { return std::string( "Execute" ); } - void act_on_terminal( Terminal::Emulator *emu ) const; - }; - class Clear : public Action { - public: - std::string name( void ) { return std::string( "Clear" ); } - void act_on_terminal( Terminal::Emulator *emu ) const; - }; - class Collect : public Action { - public: - std::string name( void ) { return std::string( "Collect" ); } - void act_on_terminal( Terminal::Emulator *emu ) const; - }; - class Param : public Action { - public: - std::string name( void ) { return std::string( "Param" ); } - void act_on_terminal( Terminal::Emulator *emu ) const; - }; - class Esc_Dispatch : public Action { - public: - std::string name( void ) { return std::string( "Esc_Dispatch" ); } - void act_on_terminal( Terminal::Emulator *emu ) const; - }; - class CSI_Dispatch : public Action { - public: - std::string name( void ) { return std::string( "CSI_Dispatch" ); } - void act_on_terminal( Terminal::Emulator *emu ) const; - }; - class Hook : public Action { - public: - std::string name( void ) { return std::string( "Hook" ); } - }; - class Put : public Action { - public: - std::string name( void ) { return std::string( "Put" ); } - }; - class Unhook : public Action { - public: - std::string name( void ) { return std::string( "Unhook" ); } - }; - class OSC_Start : public Action { - public: - std::string name( void ) { return std::string( "OSC_Start" ); } - void act_on_terminal( Terminal::Emulator *emu ) const; - }; - class OSC_Put : public Action { - public: - std::string name( void ) { return std::string( "OSC_Put" ); } - void act_on_terminal( Terminal::Emulator *emu ) const; - }; - class OSC_End : public Action { - public: - std::string name( void ) { return std::string( "OSC_End" ); } - void act_on_terminal( Terminal::Emulator *emu ) const; - }; - - class UserByte : public Action { - /* user keystroke -- not part of the host-source state machine*/ - public: - char c; /* The user-source byte. We don't try to interpret the charset */ - - std::string name( void ) { return std::string( "UserByte" ); } - void act_on_terminal( Terminal::Emulator *emu ) const; - - UserByte( int s_c ) : c( s_c ) {} - - bool operator==( const UserByte &other ) const { return c == other.c; } - }; - - class Resize : public Action { - /* resize event -- not part of the host-source state machine*/ - public: - size_t width, height; - - std::string name( void ) { return std::string( "Resize" ); } - void act_on_terminal( Terminal::Emulator *emu ) const; - - Resize( size_t s_width, size_t s_height ) - : width( s_width ), height( s_height ) {} - - bool operator==( const Resize &other ) const { - return ( width == other.width ) && ( height == other.height ); - } - }; +class Action +{ +public: + wchar_t ch; + bool char_present; + + virtual std::string name( void ) = 0; + + virtual void act_on_terminal( Terminal::Emulator* ) const {}; + + virtual bool ignore() const { return false; } + + Action() + : ch( -1 ) + , char_present( false ) {}; + virtual ~Action() {}; +}; + +typedef shared::shared_ptr ActionPointer; +typedef std::vector Actions; + +class Ignore : public Action +{ +public: + std::string name( void ) { return std::string( "Ignore" ); } + bool ignore() const { return true; } +}; +class Print : public Action +{ +public: + std::string name( void ) { return std::string( "Print" ); } + void act_on_terminal( Terminal::Emulator* emu ) const; +}; +class Execute : public Action +{ +public: + std::string name( void ) { return std::string( "Execute" ); } + void act_on_terminal( Terminal::Emulator* emu ) const; +}; +class Clear : public Action +{ +public: + std::string name( void ) { return std::string( "Clear" ); } + void act_on_terminal( Terminal::Emulator* emu ) const; +}; +class Collect : public Action +{ +public: + std::string name( void ) { return std::string( "Collect" ); } + void act_on_terminal( Terminal::Emulator* emu ) const; +}; +class Param : public Action +{ +public: + std::string name( void ) { return std::string( "Param" ); } + void act_on_terminal( Terminal::Emulator* emu ) const; +}; +class Esc_Dispatch : public Action +{ +public: + std::string name( void ) { return std::string( "Esc_Dispatch" ); } + void act_on_terminal( Terminal::Emulator* emu ) const; +}; +class CSI_Dispatch : public Action +{ +public: + std::string name( void ) { return std::string( "CSI_Dispatch" ); } + void act_on_terminal( Terminal::Emulator* emu ) const; +}; +class Hook : public Action +{ +public: + std::string name( void ) { return std::string( "Hook" ); } +}; +class Put : public Action +{ +public: + std::string name( void ) { return std::string( "Put" ); } +}; +class Unhook : public Action +{ +public: + std::string name( void ) { return std::string( "Unhook" ); } +}; +class OSC_Start : public Action +{ +public: + std::string name( void ) { return std::string( "OSC_Start" ); } + void act_on_terminal( Terminal::Emulator* emu ) const; +}; +class OSC_Put : public Action +{ +public: + std::string name( void ) { return std::string( "OSC_Put" ); } + void act_on_terminal( Terminal::Emulator* emu ) const; +}; +class OSC_End : public Action +{ +public: + std::string name( void ) { return std::string( "OSC_End" ); } + void act_on_terminal( Terminal::Emulator* emu ) const; +}; + +class UserByte : public Action +{ + /* user keystroke -- not part of the host-source state machine*/ +public: + char c; /* The user-source byte. We don't try to interpret the charset */ + + std::string name( void ) { return std::string( "UserByte" ); } + void act_on_terminal( Terminal::Emulator* emu ) const; + + UserByte( int s_c ) + : c( s_c ) + {} + + bool operator==( const UserByte& other ) const { return c == other.c; } +}; + +class Resize : public Action +{ + /* resize event -- not part of the host-source state machine*/ +public: + size_t width, height; + + std::string name( void ) { return std::string( "Resize" ); } + void act_on_terminal( Terminal::Emulator* emu ) const; + + Resize( size_t s_width, size_t s_height ) + : width( s_width ) + , height( s_height ) + {} + + bool operator==( const Resize& other ) const { return ( width == other.width ) && ( height == other.height ); } +}; } #endif diff --git a/src/terminal/parserstate.cc b/src/terminal/parserstate.cc index 7e3b19a65..a6a080e5e 100644 --- a/src/terminal/parserstate.cc +++ b/src/terminal/parserstate.cc @@ -36,10 +36,10 @@ using namespace Parser; -Transition State::anywhere_rule( wchar_t ch ) const { +Transition State::anywhere_rule( wchar_t ch ) const +{ if ( ( ch == 0x18 ) || ( ch == 0x1A ) || ( ( 0x80 <= ch ) && ( ch <= 0x8F ) ) - || ( ( 0x91 <= ch ) && ( ch <= 0x97 ) ) || ( ch == 0x99 ) - || ( ch == 0x9A ) ) { + || ( ( 0x91 <= ch ) && ( ch <= 0x97 ) ) || ( ch == 0x99 ) || ( ch == 0x9A ) ) { return Transition( shared::make_shared(), &family->s_Ground ); } else if ( ch == 0x9C ) { return Transition( &family->s_Ground ); @@ -55,11 +55,11 @@ Transition State::anywhere_rule( wchar_t ch ) const { return Transition( &family->s_CSI_Entry ); } - return Transition( (State *)NULL, - ActionPointer() ); /* don't allocate an Ignore action */ + return Transition( (State*)NULL, ActionPointer() ); /* don't allocate an Ignore action */ } -Transition State::input( wchar_t ch ) const { +Transition State::input( wchar_t ch ) const +{ /* Check for immediate transitions. */ Transition anywhere = anywhere_rule( ch ); if ( anywhere.next_state ) { @@ -75,17 +75,19 @@ Transition State::input( wchar_t ch ) const { return ret; } -static bool C0_prime( wchar_t ch ) { - return ( ch <= 0x17 ) || ( ch == 0x19 ) - || ( ( 0x1C <= ch ) && ( ch <= 0x1F ) ); +static bool C0_prime( wchar_t ch ) +{ + return ( ch <= 0x17 ) || ( ch == 0x19 ) || ( ( 0x1C <= ch ) && ( ch <= 0x1F ) ); } -static bool GLGR( wchar_t ch ) { - return ( ( 0x20 <= ch ) && ( ch <= 0x7F ) ) /* GL area */ - || ( ( 0xA0 <= ch ) && ( ch <= 0xFF ) ); /* GR area */ +static bool GLGR( wchar_t ch ) +{ + return ( ( 0x20 <= ch ) && ( ch <= 0x7F ) ) /* GL area */ + || ( ( 0xA0 <= ch ) && ( ch <= 0xFF ) ); /* GR area */ } -Transition Ground::input_state_rule( wchar_t ch ) const { +Transition Ground::input_state_rule( wchar_t ch ) const +{ if ( C0_prime( ch ) ) { return Transition( shared::make_shared() ); } @@ -97,24 +99,23 @@ Transition Ground::input_state_rule( wchar_t ch ) const { return Transition(); } -ActionPointer Escape::enter( void ) const { +ActionPointer Escape::enter( void ) const +{ return shared::make_shared(); } -Transition Escape::input_state_rule( wchar_t ch ) const { +Transition Escape::input_state_rule( wchar_t ch ) const +{ if ( C0_prime( ch ) ) { return Transition( shared::make_shared() ); } if ( ( 0x20 <= ch ) && ( ch <= 0x2F ) ) { - return Transition( shared::make_shared(), - &family->s_Escape_Intermediate ); + return Transition( shared::make_shared(), &family->s_Escape_Intermediate ); } - if ( ( ( 0x30 <= ch ) && ( ch <= 0x4F ) ) - || ( ( 0x51 <= ch ) && ( ch <= 0x57 ) ) || ( ch == 0x59 ) - || ( ch == 0x5A ) || ( ch == 0x5C ) - || ( ( 0x60 <= ch ) && ( ch <= 0x7E ) ) ) { + if ( ( ( 0x30 <= ch ) && ( ch <= 0x4F ) ) || ( ( 0x51 <= ch ) && ( ch <= 0x57 ) ) || ( ch == 0x59 ) + || ( ch == 0x5A ) || ( ch == 0x5C ) || ( ( 0x60 <= ch ) && ( ch <= 0x7E ) ) ) { return Transition( shared::make_shared(), &family->s_Ground ); } @@ -137,7 +138,8 @@ Transition Escape::input_state_rule( wchar_t ch ) const { return Transition(); } -Transition Escape_Intermediate::input_state_rule( wchar_t ch ) const { +Transition Escape_Intermediate::input_state_rule( wchar_t ch ) const +{ if ( C0_prime( ch ) ) { return Transition( shared::make_shared() ); } @@ -153,11 +155,13 @@ Transition Escape_Intermediate::input_state_rule( wchar_t ch ) const { return Transition(); } -ActionPointer CSI_Entry::enter( void ) const { +ActionPointer CSI_Entry::enter( void ) const +{ return shared::make_shared(); } -Transition CSI_Entry::input_state_rule( wchar_t ch ) const { +Transition CSI_Entry::input_state_rule( wchar_t ch ) const +{ if ( C0_prime( ch ) ) { return Transition( shared::make_shared() ); } @@ -179,14 +183,14 @@ Transition CSI_Entry::input_state_rule( wchar_t ch ) const { } if ( ( 0x20 <= ch ) && ( ch <= 0x2F ) ) { - return Transition( shared::make_shared(), - &family->s_CSI_Intermediate ); + return Transition( shared::make_shared(), &family->s_CSI_Intermediate ); } return Transition(); } -Transition CSI_Param::input_state_rule( wchar_t ch ) const { +Transition CSI_Param::input_state_rule( wchar_t ch ) const +{ if ( C0_prime( ch ) ) { return Transition( shared::make_shared() ); } @@ -200,8 +204,7 @@ Transition CSI_Param::input_state_rule( wchar_t ch ) const { } if ( ( 0x20 <= ch ) && ( ch <= 0x2F ) ) { - return Transition( shared::make_shared(), - &family->s_CSI_Intermediate ); + return Transition( shared::make_shared(), &family->s_CSI_Intermediate ); } if ( ( 0x40 <= ch ) && ( ch <= 0x7E ) ) { @@ -211,7 +214,8 @@ Transition CSI_Param::input_state_rule( wchar_t ch ) const { return Transition(); } -Transition CSI_Intermediate::input_state_rule( wchar_t ch ) const { +Transition CSI_Intermediate::input_state_rule( wchar_t ch ) const +{ if ( C0_prime( ch ) ) { return Transition( shared::make_shared() ); } @@ -231,7 +235,8 @@ Transition CSI_Intermediate::input_state_rule( wchar_t ch ) const { return Transition(); } -Transition CSI_Ignore::input_state_rule( wchar_t ch ) const { +Transition CSI_Ignore::input_state_rule( wchar_t ch ) const +{ if ( C0_prime( ch ) ) { return Transition( shared::make_shared() ); } @@ -243,14 +248,15 @@ Transition CSI_Ignore::input_state_rule( wchar_t ch ) const { return Transition(); } -ActionPointer DCS_Entry::enter( void ) const { +ActionPointer DCS_Entry::enter( void ) const +{ return shared::make_shared(); } -Transition DCS_Entry::input_state_rule( wchar_t ch ) const { +Transition DCS_Entry::input_state_rule( wchar_t ch ) const +{ if ( ( 0x20 <= ch ) && ( ch <= 0x2F ) ) { - return Transition( shared::make_shared(), - &family->s_DCS_Intermediate ); + return Transition( shared::make_shared(), &family->s_DCS_Intermediate ); } if ( ch == 0x3A ) { @@ -272,7 +278,8 @@ Transition DCS_Entry::input_state_rule( wchar_t ch ) const { return Transition(); } -Transition DCS_Param::input_state_rule( wchar_t ch ) const { +Transition DCS_Param::input_state_rule( wchar_t ch ) const +{ if ( ( ( 0x30 <= ch ) && ( ch <= 0x39 ) ) || ( ch == 0x3B ) ) { return Transition( shared::make_shared() ); } @@ -282,8 +289,7 @@ Transition DCS_Param::input_state_rule( wchar_t ch ) const { } if ( ( 0x20 <= ch ) && ( ch <= 0x2F ) ) { - return Transition( shared::make_shared(), - &family->s_DCS_Intermediate ); + return Transition( shared::make_shared(), &family->s_DCS_Intermediate ); } if ( ( 0x40 <= ch ) && ( ch <= 0x7E ) ) { @@ -293,7 +299,8 @@ Transition DCS_Param::input_state_rule( wchar_t ch ) const { return Transition(); } -Transition DCS_Intermediate::input_state_rule( wchar_t ch ) const { +Transition DCS_Intermediate::input_state_rule( wchar_t ch ) const +{ if ( ( 0x20 <= ch ) && ( ch <= 0x2F ) ) { return Transition( shared::make_shared() ); } @@ -309,15 +316,18 @@ Transition DCS_Intermediate::input_state_rule( wchar_t ch ) const { return Transition(); } -ActionPointer DCS_Passthrough::enter( void ) const { +ActionPointer DCS_Passthrough::enter( void ) const +{ return shared::make_shared(); } -ActionPointer DCS_Passthrough::exit( void ) const { +ActionPointer DCS_Passthrough::exit( void ) const +{ return shared::make_shared(); } -Transition DCS_Passthrough::input_state_rule( wchar_t ch ) const { +Transition DCS_Passthrough::input_state_rule( wchar_t ch ) const +{ if ( C0_prime( ch ) || ( ( 0x20 <= ch ) && ( ch <= 0x7E ) ) ) { return Transition( shared::make_shared() ); } @@ -329,7 +339,8 @@ Transition DCS_Passthrough::input_state_rule( wchar_t ch ) const { return Transition(); } -Transition DCS_Ignore::input_state_rule( wchar_t ch ) const { +Transition DCS_Ignore::input_state_rule( wchar_t ch ) const +{ if ( ch == 0x9C ) { return Transition( &family->s_Ground ); } @@ -337,15 +348,18 @@ Transition DCS_Ignore::input_state_rule( wchar_t ch ) const { return Transition(); } -ActionPointer OSC_String::enter( void ) const { +ActionPointer OSC_String::enter( void ) const +{ return shared::make_shared(); } -ActionPointer OSC_String::exit( void ) const { +ActionPointer OSC_String::exit( void ) const +{ return shared::make_shared(); } -Transition OSC_String::input_state_rule( wchar_t ch ) const { +Transition OSC_String::input_state_rule( wchar_t ch ) const +{ if ( ( 0x20 <= ch ) && ( ch <= 0x7F ) ) { return Transition( shared::make_shared() ); } @@ -357,7 +371,8 @@ Transition OSC_String::input_state_rule( wchar_t ch ) const { return Transition(); } -Transition SOS_PM_APC_String::input_state_rule( wchar_t ch ) const { +Transition SOS_PM_APC_String::input_state_rule( wchar_t ch ) const +{ if ( ch == 0x9C ) { return Transition( &family->s_Ground ); } diff --git a/src/terminal/parserstate.h b/src/terminal/parserstate.h index e9ea2ee9b..407fc3790 100644 --- a/src/terminal/parserstate.h +++ b/src/terminal/parserstate.h @@ -36,87 +36,99 @@ #include "parsertransition.h" namespace Parser { - class StateFamily; - - class State { - protected: - virtual Transition input_state_rule( wchar_t ch ) const = 0; - StateFamily *family; - - private: - Transition anywhere_rule( wchar_t ch ) const; - - public: - void setfamily( StateFamily *s_family ) { family = s_family; } - Transition input( wchar_t ch ) const; - virtual ActionPointer enter( void ) const { - return shared::make_shared(); - } - virtual ActionPointer exit( void ) const { - return shared::make_shared(); - } - - State() : family( NULL ) {}; - virtual ~State() {}; - - State( const State & ); - State &operator=( const State & ); - }; - - class Ground : public State { - Transition input_state_rule( wchar_t ch ) const; - }; - - class Escape : public State { - ActionPointer enter( void ) const; - Transition input_state_rule( wchar_t ch ) const; - }; - - class Escape_Intermediate : public State { - Transition input_state_rule( wchar_t ch ) const; - }; - - class CSI_Entry : public State { - ActionPointer enter( void ) const; - Transition input_state_rule( wchar_t ch ) const; - }; - class CSI_Param : public State { - Transition input_state_rule( wchar_t ch ) const; - }; - class CSI_Intermediate : public State { - Transition input_state_rule( wchar_t ch ) const; - }; - class CSI_Ignore : public State { - Transition input_state_rule( wchar_t ch ) const; - }; - - class DCS_Entry : public State { - ActionPointer enter( void ) const; - Transition input_state_rule( wchar_t ch ) const; - }; - class DCS_Param : public State { - Transition input_state_rule( wchar_t ch ) const; - }; - class DCS_Intermediate : public State { - Transition input_state_rule( wchar_t ch ) const; - }; - class DCS_Passthrough : public State { - ActionPointer enter( void ) const; - Transition input_state_rule( wchar_t ch ) const; - ActionPointer exit( void ) const; - }; - class DCS_Ignore : public State { - Transition input_state_rule( wchar_t ch ) const; - }; - - class OSC_String : public State { - ActionPointer enter( void ) const; - Transition input_state_rule( wchar_t ch ) const; - ActionPointer exit( void ) const; - }; - class SOS_PM_APC_String : public State { - Transition input_state_rule( wchar_t ch ) const; - }; +class StateFamily; + +class State +{ +protected: + virtual Transition input_state_rule( wchar_t ch ) const = 0; + StateFamily* family; + +private: + Transition anywhere_rule( wchar_t ch ) const; + +public: + void setfamily( StateFamily* s_family ) { family = s_family; } + Transition input( wchar_t ch ) const; + virtual ActionPointer enter( void ) const { return shared::make_shared(); } + virtual ActionPointer exit( void ) const { return shared::make_shared(); } + + State() + : family( NULL ) {}; + virtual ~State() {}; + + State( const State& ); + State& operator=( const State& ); +}; + +class Ground : public State +{ + Transition input_state_rule( wchar_t ch ) const; +}; + +class Escape : public State +{ + ActionPointer enter( void ) const; + Transition input_state_rule( wchar_t ch ) const; +}; + +class Escape_Intermediate : public State +{ + Transition input_state_rule( wchar_t ch ) const; +}; + +class CSI_Entry : public State +{ + ActionPointer enter( void ) const; + Transition input_state_rule( wchar_t ch ) const; +}; +class CSI_Param : public State +{ + Transition input_state_rule( wchar_t ch ) const; +}; +class CSI_Intermediate : public State +{ + Transition input_state_rule( wchar_t ch ) const; +}; +class CSI_Ignore : public State +{ + Transition input_state_rule( wchar_t ch ) const; +}; + +class DCS_Entry : public State +{ + ActionPointer enter( void ) const; + Transition input_state_rule( wchar_t ch ) const; +}; +class DCS_Param : public State +{ + Transition input_state_rule( wchar_t ch ) const; +}; +class DCS_Intermediate : public State +{ + Transition input_state_rule( wchar_t ch ) const; +}; +class DCS_Passthrough : public State +{ + ActionPointer enter( void ) const; + Transition input_state_rule( wchar_t ch ) const; + ActionPointer exit( void ) const; +}; +class DCS_Ignore : public State +{ + Transition input_state_rule( wchar_t ch ) const; +}; + +class OSC_String : public State +{ + ActionPointer enter( void ) const; + Transition input_state_rule( wchar_t ch ) const; + ActionPointer exit( void ) const; +}; +class SOS_PM_APC_String : public State +{ + Transition input_state_rule( wchar_t ch ) const; +}; } #endif diff --git a/src/terminal/parserstatefamily.h b/src/terminal/parserstatefamily.h index 8e5e63a90..31481f8f5 100644 --- a/src/terminal/parserstatefamily.h +++ b/src/terminal/parserstatefamily.h @@ -36,58 +36,60 @@ #include "parserstate.h" namespace Parser { - class StateFamily { - public: - Ground s_Ground; +class StateFamily +{ +public: + Ground s_Ground; - Escape s_Escape; - Escape_Intermediate s_Escape_Intermediate; + Escape s_Escape; + Escape_Intermediate s_Escape_Intermediate; - CSI_Entry s_CSI_Entry; - CSI_Param s_CSI_Param; - CSI_Intermediate s_CSI_Intermediate; - CSI_Ignore s_CSI_Ignore; + CSI_Entry s_CSI_Entry; + CSI_Param s_CSI_Param; + CSI_Intermediate s_CSI_Intermediate; + CSI_Ignore s_CSI_Ignore; - DCS_Entry s_DCS_Entry; - DCS_Param s_DCS_Param; - DCS_Intermediate s_DCS_Intermediate; - DCS_Passthrough s_DCS_Passthrough; - DCS_Ignore s_DCS_Ignore; + DCS_Entry s_DCS_Entry; + DCS_Param s_DCS_Param; + DCS_Intermediate s_DCS_Intermediate; + DCS_Passthrough s_DCS_Passthrough; + DCS_Ignore s_DCS_Ignore; - OSC_String s_OSC_String; - SOS_PM_APC_String s_SOS_PM_APC_String; + OSC_String s_OSC_String; + SOS_PM_APC_String s_SOS_PM_APC_String; - StateFamily() - : s_Ground(), - s_Escape(), - s_Escape_Intermediate(), - s_CSI_Entry(), - s_CSI_Param(), - s_CSI_Intermediate(), - s_CSI_Ignore(), - s_DCS_Entry(), - s_DCS_Param(), - s_DCS_Intermediate(), - s_DCS_Passthrough(), - s_DCS_Ignore(), - s_OSC_String(), - s_SOS_PM_APC_String() { - s_Ground.setfamily( this ); - s_Escape.setfamily( this ); - s_Escape_Intermediate.setfamily( this ); - s_CSI_Entry.setfamily( this ); - s_CSI_Param.setfamily( this ); - s_CSI_Intermediate.setfamily( this ); - s_CSI_Ignore.setfamily( this ); - s_DCS_Entry.setfamily( this ); - s_DCS_Param.setfamily( this ); - s_DCS_Intermediate.setfamily( this ); - s_DCS_Passthrough.setfamily( this ); - s_DCS_Ignore.setfamily( this ); - s_OSC_String.setfamily( this ); - s_SOS_PM_APC_String.setfamily( this ); - } - }; + StateFamily() + : s_Ground() + , s_Escape() + , s_Escape_Intermediate() + , s_CSI_Entry() + , s_CSI_Param() + , s_CSI_Intermediate() + , s_CSI_Ignore() + , s_DCS_Entry() + , s_DCS_Param() + , s_DCS_Intermediate() + , s_DCS_Passthrough() + , s_DCS_Ignore() + , s_OSC_String() + , s_SOS_PM_APC_String() + { + s_Ground.setfamily( this ); + s_Escape.setfamily( this ); + s_Escape_Intermediate.setfamily( this ); + s_CSI_Entry.setfamily( this ); + s_CSI_Param.setfamily( this ); + s_CSI_Intermediate.setfamily( this ); + s_CSI_Ignore.setfamily( this ); + s_DCS_Entry.setfamily( this ); + s_DCS_Param.setfamily( this ); + s_DCS_Intermediate.setfamily( this ); + s_DCS_Passthrough.setfamily( this ); + s_DCS_Ignore.setfamily( this ); + s_OSC_String.setfamily( this ); + s_SOS_PM_APC_String.setfamily( this ); + } +}; } #endif diff --git a/src/terminal/parsertransition.h b/src/terminal/parsertransition.h index 5a31f017f..0982e149b 100644 --- a/src/terminal/parsertransition.h +++ b/src/terminal/parsertransition.h @@ -38,34 +38,40 @@ #include "parseraction.h" namespace Parser { - class State; +class State; - class Transition { - public: - // Transition is only a courier for an Action; it should - // never create/delete one on its own. - ActionPointer action; - State *next_state; +class Transition +{ +public: + // Transition is only a courier for an Action; it should + // never create/delete one on its own. + ActionPointer action; + State* next_state; - Transition( const Transition &x ) - : action( x.action ), next_state( x.next_state ) {} - Transition &operator=( const Transition &t ) { - action = t.action; - next_state = t.next_state; + Transition( const Transition& x ) + : action( x.action ) + , next_state( x.next_state ) + {} + Transition& operator=( const Transition& t ) + { + action = t.action; + next_state = t.next_state; - return *this; - } - Transition( ActionPointer s_action = shared::make_shared(), - State *s_next_state = NULL ) - : action( s_action ), next_state( s_next_state ) {} + return *this; + } + Transition( ActionPointer s_action = shared::make_shared(), State* s_next_state = NULL ) + : action( s_action ) + , next_state( s_next_state ) + {} - // This is only ever used in the 1-argument form; - // we use this instead of an initializer to - // tell Coverity the object never owns *action. - Transition( State *s_next_state, - ActionPointer s_action = shared::make_shared() ) - : action( s_action ), next_state( s_next_state ) {} - }; + // This is only ever used in the 1-argument form; + // we use this instead of an initializer to + // tell Coverity the object never owns *action. + Transition( State* s_next_state, ActionPointer s_action = shared::make_shared() ) + : action( s_action ) + , next_state( s_next_state ) + {} +}; } #endif diff --git a/src/terminal/terminal.cc b/src/terminal/terminal.cc index f7dd15876..f8fbe33d4 100644 --- a/src/terminal/terminal.cc +++ b/src/terminal/terminal.cc @@ -33,27 +33,33 @@ #include #include #include -#include #include +#include #include "terminal.h" using namespace Terminal; Emulator::Emulator( size_t s_width, size_t s_height ) - : fb( s_width, s_height ), dispatch(), user() {} + : fb( s_width, s_height ) + , dispatch() + , user() +{} -std::string Emulator::read_octets_to_host( void ) { +std::string Emulator::read_octets_to_host( void ) +{ std::string ret = dispatch.terminal_to_host; dispatch.terminal_to_host.clear(); return ret; } -void Emulator::execute( const Parser::Execute *act ) { +void Emulator::execute( const Parser::Execute* act ) +{ dispatch.dispatch( CONTROL, act, &fb ); } -void Emulator::print( const Parser::Print *act ) { +void Emulator::print( const Parser::Print* act ) +{ assert( act->char_present ); const wchar_t ch = act->ch; @@ -62,64 +68,59 @@ void Emulator::print( const Parser::Print *act ) { * Check for printing ISO 8859-1 first, it's a cheap way to detect * some common narrow characters. */ - const int chwidth = - ch == L'\0' ? -1 : ( Cell::isprint_iso8859_1( ch ) ? 1 : wcwidth( ch ) ); + const int chwidth = ch == L'\0' ? -1 : ( Cell::isprint_iso8859_1( ch ) ? 1 : wcwidth( ch ) ); - Cell *this_cell = fb.get_mutable_cell(); + Cell* this_cell = fb.get_mutable_cell(); switch ( chwidth ) { - case 1: /* normal character */ - case 2: /* wide character */ - if ( fb.ds.auto_wrap_mode && fb.ds.next_print_will_wrap ) { - fb.get_mutable_row( -1 )->set_wrap( true ); - fb.ds.move_col( 0 ); - fb.move_rows_autoscroll( 1 ); - this_cell = NULL; - } else if ( fb.ds.auto_wrap_mode && ( chwidth == 2 ) - && ( fb.ds.get_cursor_col() == fb.ds.get_width() - 1 ) ) { - /* wrap 2-cell chars if no room, even without will-wrap flag */ - fb.reset_cell( this_cell ); - fb.get_mutable_row( -1 )->set_wrap( false ); - /* There doesn't seem to be a consistent way to get the - downstream terminal emulator to set the wrap-around - copy-and-paste flag on a row that ends with an empty cell - because a wide char was wrapped to the next line. */ - fb.ds.move_col( 0 ); - fb.move_rows_autoscroll( 1 ); - this_cell = NULL; - } - - if ( fb.ds.insert_mode ) { - for ( int i = 0; i < chwidth; i++ ) { - fb.insert_cell( fb.ds.get_cursor_row(), fb.ds.get_cursor_col() ); + case 1: /* normal character */ + case 2: /* wide character */ + if ( fb.ds.auto_wrap_mode && fb.ds.next_print_will_wrap ) { + fb.get_mutable_row( -1 )->set_wrap( true ); + fb.ds.move_col( 0 ); + fb.move_rows_autoscroll( 1 ); + this_cell = NULL; + } else if ( fb.ds.auto_wrap_mode && ( chwidth == 2 ) + && ( fb.ds.get_cursor_col() == fb.ds.get_width() - 1 ) ) { + /* wrap 2-cell chars if no room, even without will-wrap flag */ + fb.reset_cell( this_cell ); + fb.get_mutable_row( -1 )->set_wrap( false ); + /* There doesn't seem to be a consistent way to get the + downstream terminal emulator to set the wrap-around + copy-and-paste flag on a row that ends with an empty cell + because a wide char was wrapped to the next line. */ + fb.ds.move_col( 0 ); + fb.move_rows_autoscroll( 1 ); + this_cell = NULL; + } + + if ( fb.ds.insert_mode ) { + for ( int i = 0; i < chwidth; i++ ) { + fb.insert_cell( fb.ds.get_cursor_row(), fb.ds.get_cursor_col() ); + } + this_cell = NULL; } - this_cell = NULL; - } - if ( !this_cell ) { - this_cell = fb.get_mutable_cell(); - } + if ( !this_cell ) { + this_cell = fb.get_mutable_cell(); + } - fb.reset_cell( this_cell ); - this_cell->append( ch ); - this_cell->set_wide( chwidth == 2 ); /* chwidth had better be 1 or 2 here */ - fb.apply_renditions_to_cell( this_cell ); + fb.reset_cell( this_cell ); + this_cell->append( ch ); + this_cell->set_wide( chwidth == 2 ); /* chwidth had better be 1 or 2 here */ + fb.apply_renditions_to_cell( this_cell ); - if ( chwidth == 2 - && fb.ds.get_cursor_col() + 1 - < fb.ds.get_width() ) { /* erase overlapped cell */ - fb.reset_cell( fb.get_mutable_cell( fb.ds.get_cursor_row(), - fb.ds.get_cursor_col() + 1 ) ); - } + if ( chwidth == 2 && fb.ds.get_cursor_col() + 1 < fb.ds.get_width() ) { /* erase overlapped cell */ + fb.reset_cell( fb.get_mutable_cell( fb.ds.get_cursor_row(), fb.ds.get_cursor_col() + 1 ) ); + } - fb.ds.move_col( chwidth, true, true ); + fb.ds.move_col( chwidth, true, true ); - break; - case 0: /* combining character */ + break; + case 0: /* combining character */ { - Cell *combining_cell = - fb.get_combining_cell(); /* can be null if we were resized */ - if ( combining_cell == NULL ) { /* character is now offscreen */ + Cell* combining_cell = fb.get_combining_cell(); /* can be null if we were resized */ + if ( combining_cell == NULL ) { /* character is now offscreen */ break; } @@ -136,25 +137,29 @@ void Emulator::print( const Parser::Print *act ) { if ( !combining_cell->full() ) { combining_cell->append( ch ); } - } - break; - case -1: /* unprintable character */ break; - default: assert( !"unexpected character width from wcwidth()" ); break; + } break; + case -1: /* unprintable character */ + break; + default: + assert( !"unexpected character width from wcwidth()" ); + break; } } -void Emulator::CSI_dispatch( const Parser::CSI_Dispatch *act ) { +void Emulator::CSI_dispatch( const Parser::CSI_Dispatch* act ) +{ dispatch.dispatch( CSI, act, &fb ); } -void Emulator::OSC_end( const Parser::OSC_End *act ) { +void Emulator::OSC_end( const Parser::OSC_End* act ) +{ dispatch.OSC_dispatch( act, &fb ); } -void Emulator::Esc_dispatch( const Parser::Esc_Dispatch *act ) { +void Emulator::Esc_dispatch( const Parser::Esc_Dispatch* act ) +{ /* handle 7-bit ESC-encoding of C1 control characters */ - if ( ( dispatch.get_dispatch_chars().size() == 0 ) && ( 0x40 <= act->ch ) - && ( act->ch <= 0x5F ) ) { + if ( ( dispatch.get_dispatch_chars().size() == 0 ) && ( 0x40 <= act->ch ) && ( act->ch <= 0x5F ) ) { Parser::Esc_Dispatch act2 = *act; act2.ch += 0x40; dispatch.dispatch( CONTROL, &act2, &fb ); @@ -163,11 +168,13 @@ void Emulator::Esc_dispatch( const Parser::Esc_Dispatch *act ) { } } -void Emulator::resize( size_t s_width, size_t s_height ) { +void Emulator::resize( size_t s_width, size_t s_height ) +{ fb.resize( s_width, s_height ); } -bool Emulator::operator==( Emulator const &x ) const { +bool Emulator::operator==( Emulator const& x ) const +{ /* dispatcher and user are irrelevant for us */ return fb == x.fb; } diff --git a/src/terminal/terminal.h b/src/terminal/terminal.h index f75b06128..30e04b58a 100644 --- a/src/terminal/terminal.h +++ b/src/terminal/terminal.h @@ -33,10 +33,10 @@ #ifndef TERMINAL_CPP #define TERMINAL_CPP -#include -#include #include +#include #include +#include #include "parseraction.h" #include "terminaldispatcher.h" @@ -45,43 +45,44 @@ #include "terminaluserinput.h" namespace Terminal { - class Emulator { - friend void Parser::Print::act_on_terminal( Emulator * ) const; - friend void Parser::Execute::act_on_terminal( Emulator * ) const; - friend void Parser::Clear::act_on_terminal( Emulator * ) const; - friend void Parser::Param::act_on_terminal( Emulator * ) const; - friend void Parser::Collect::act_on_terminal( Emulator * ) const; - friend void Parser::CSI_Dispatch::act_on_terminal( Emulator * ) const; - friend void Parser::Esc_Dispatch::act_on_terminal( Emulator * ) const; - friend void Parser::OSC_Start::act_on_terminal( Emulator * ) const; - friend void Parser::OSC_Put::act_on_terminal( Emulator * ) const; - friend void Parser::OSC_End::act_on_terminal( Emulator * ) const; - - friend void Parser::UserByte::act_on_terminal( Emulator * ) const; - friend void Parser::Resize::act_on_terminal( Emulator * ) const; - - private: - Framebuffer fb; - Dispatcher dispatch; - UserInput user; - - /* action methods */ - void print( const Parser::Print *act ); - void execute( const Parser::Execute *act ); - void CSI_dispatch( const Parser::CSI_Dispatch *act ); - void Esc_dispatch( const Parser::Esc_Dispatch *act ); - void OSC_end( const Parser::OSC_End *act ); - void resize( size_t s_width, size_t s_height ); - - public: - Emulator( size_t s_width, size_t s_height ); - - std::string read_octets_to_host( void ); - - const Framebuffer &get_fb( void ) const { return fb; } - - bool operator==( Emulator const &x ) const; - }; +class Emulator +{ + friend void Parser::Print::act_on_terminal( Emulator* ) const; + friend void Parser::Execute::act_on_terminal( Emulator* ) const; + friend void Parser::Clear::act_on_terminal( Emulator* ) const; + friend void Parser::Param::act_on_terminal( Emulator* ) const; + friend void Parser::Collect::act_on_terminal( Emulator* ) const; + friend void Parser::CSI_Dispatch::act_on_terminal( Emulator* ) const; + friend void Parser::Esc_Dispatch::act_on_terminal( Emulator* ) const; + friend void Parser::OSC_Start::act_on_terminal( Emulator* ) const; + friend void Parser::OSC_Put::act_on_terminal( Emulator* ) const; + friend void Parser::OSC_End::act_on_terminal( Emulator* ) const; + + friend void Parser::UserByte::act_on_terminal( Emulator* ) const; + friend void Parser::Resize::act_on_terminal( Emulator* ) const; + +private: + Framebuffer fb; + Dispatcher dispatch; + UserInput user; + + /* action methods */ + void print( const Parser::Print* act ); + void execute( const Parser::Execute* act ); + void CSI_dispatch( const Parser::CSI_Dispatch* act ); + void Esc_dispatch( const Parser::Esc_Dispatch* act ); + void OSC_end( const Parser::OSC_End* act ); + void resize( size_t s_width, size_t s_height ); + +public: + Emulator( size_t s_width, size_t s_height ); + + std::string read_octets_to_host( void ); + + const Framebuffer& get_fb( void ) const { return fb; } + + bool operator==( Emulator const& x ) const; +}; } #endif diff --git a/src/terminal/terminaldispatcher.cc b/src/terminal/terminaldispatcher.cc index 7225b79e6..3ba2d14b6 100644 --- a/src/terminal/terminaldispatcher.cc +++ b/src/terminal/terminaldispatcher.cc @@ -45,14 +45,16 @@ using namespace Terminal; static const size_t MAXIMUM_CLIPBOARD_SIZE = 16 * 1024; Dispatcher::Dispatcher() - : params(), - parsed_params(), - parsed( false ), - dispatch_chars(), - OSC_string(), - terminal_to_host() {} - -void Dispatcher::newparamchar( const Parser::Param *act ) { + : params() + , parsed_params() + , parsed( false ) + , dispatch_chars() + , OSC_string() + , terminal_to_host() +{} + +void Dispatcher::newparamchar( const Parser::Param* act ) +{ assert( act->char_present ); assert( ( act->ch == ';' ) || ( ( act->ch >= '0' ) && ( act->ch <= '9' ) ) ); if ( params.length() < 100 ) { @@ -62,37 +64,40 @@ void Dispatcher::newparamchar( const Parser::Param *act ) { parsed = false; } -void Dispatcher::collect( const Parser::Collect *act ) { +void Dispatcher::collect( const Parser::Collect* act ) +{ assert( act->char_present ); if ( ( dispatch_chars.length() < 8 ) /* never should need more than 2 */ - && ( act->ch <= 255 ) ) { /* ignore non-8-bit */ + && ( act->ch <= 255 ) ) { /* ignore non-8-bit */ dispatch_chars.push_back( act->ch ); } } -void Dispatcher::clear( const Parser::Clear *act __attribute( ( unused ) ) ) { +void Dispatcher::clear( const Parser::Clear* act __attribute( ( unused ) ) ) +{ params.clear(); dispatch_chars.clear(); parsed = false; } -void Dispatcher::parse_params( void ) { +void Dispatcher::parse_params( void ) +{ if ( parsed ) { return; } parsed_params.clear(); - const char *str = params.c_str(); - const char *segment_begin = str; + const char* str = params.c_str(); + const char* segment_begin = str; while ( 1 ) { - const char *segment_end = strchr( segment_begin, ';' ); + const char* segment_end = strchr( segment_begin, ';' ); if ( segment_end == NULL ) { break; } errno = 0; - char *endptr; + char* endptr; long val = strtol( segment_begin, &endptr, 10 ); if ( endptr == segment_begin ) { val = -1; @@ -112,7 +117,7 @@ void Dispatcher::parse_params( void ) { /* get last param */ errno = 0; - char *endptr; + char* endptr; long val = strtol( segment_begin, &endptr, 10 ); if ( endptr == segment_begin ) { val = -1; @@ -130,22 +135,25 @@ void Dispatcher::parse_params( void ) { parsed = true; } -int Dispatcher::getparam( size_t N, int defaultval ) { +int Dispatcher::getparam( size_t N, int defaultval ) +{ int ret = defaultval; if ( !parsed ) { parse_params(); } if ( parsed_params.size() > N ) { - ret = parsed_params[ N ]; + ret = parsed_params[N]; } - if ( ret < 1 ) ret = defaultval; + if ( ret < 1 ) + ret = defaultval; return ret; } -int Dispatcher::param_count( void ) { +int Dispatcher::param_count( void ) +{ if ( !parsed ) { parse_params(); } @@ -153,46 +161,47 @@ int Dispatcher::param_count( void ) { return parsed_params.size(); } -std::string Dispatcher::str( void ) { - char assum[ 64 ]; - snprintf( assum, 64, "[dispatch=\"%s\" params=\"%s\"]", - dispatch_chars.c_str(), params.c_str() ); +std::string Dispatcher::str( void ) +{ + char assum[64]; + snprintf( assum, 64, "[dispatch=\"%s\" params=\"%s\"]", dispatch_chars.c_str(), params.c_str() ); return std::string( assum ); } /* construct on first use to avoid static initialization order crash */ -DispatchRegistry &Terminal::get_global_dispatch_registry( void ) { +DispatchRegistry& Terminal::get_global_dispatch_registry( void ) +{ static DispatchRegistry global_dispatch_registry; return global_dispatch_registry; } -static void register_function( Function_Type type, - const std::string &dispatch_chars, Function f ) { +static void register_function( Function_Type type, const std::string& dispatch_chars, Function f ) +{ switch ( type ) { - case ESCAPE: - get_global_dispatch_registry().escape.insert( - dispatch_map_t::value_type( dispatch_chars, f ) ); - break; - case CSI: - get_global_dispatch_registry().CSI.insert( - dispatch_map_t::value_type( dispatch_chars, f ) ); - break; - case CONTROL: - get_global_dispatch_registry().control.insert( - dispatch_map_t::value_type( dispatch_chars, f ) ); - break; + case ESCAPE: + get_global_dispatch_registry().escape.insert( dispatch_map_t::value_type( dispatch_chars, f ) ); + break; + case CSI: + get_global_dispatch_registry().CSI.insert( dispatch_map_t::value_type( dispatch_chars, f ) ); + break; + case CONTROL: + get_global_dispatch_registry().control.insert( dispatch_map_t::value_type( dispatch_chars, f ) ); + break; } } -Function::Function( Function_Type type, const std::string &dispatch_chars, - void ( *s_function )( Framebuffer *, Dispatcher * ), +Function::Function( Function_Type type, + const std::string& dispatch_chars, + void ( *s_function )( Framebuffer*, Dispatcher* ), bool s_clears_wrap_state ) - : function( s_function ), clears_wrap_state( s_clears_wrap_state ) { + : function( s_function ) + , clears_wrap_state( s_clears_wrap_state ) +{ register_function( type, dispatch_chars, *this ); } -void Dispatcher::dispatch( Function_Type type, const Parser::Action *act, - Framebuffer *fb ) { +void Dispatcher::dispatch( Function_Type type, const Parser::Action* act, Framebuffer* fb ) +{ /* add final char to dispatch key */ if ( ( type == ESCAPE ) || ( type == CSI ) ) { assert( act->char_present ); @@ -202,17 +211,23 @@ void Dispatcher::dispatch( Function_Type type, const Parser::Action *act, collect( &act2 ); } - dispatch_map_t *map = NULL; + dispatch_map_t* map = NULL; switch ( type ) { - case ESCAPE: map = &get_global_dispatch_registry().escape; break; - case CSI: map = &get_global_dispatch_registry().CSI; break; - case CONTROL: map = &get_global_dispatch_registry().control; break; + case ESCAPE: + map = &get_global_dispatch_registry().escape; + break; + case CSI: + map = &get_global_dispatch_registry().CSI; + break; + case CONTROL: + map = &get_global_dispatch_registry().control; + break; } std::string key = dispatch_chars; if ( type == CONTROL ) { assert( act->ch <= 255 ); - char ctrlstr[ 2 ] = { (char)act->ch, 0 }; + char ctrlstr[2] = { (char)act->ch, 0 }; key = std::string( ctrlstr, 1 ); } @@ -228,21 +243,22 @@ void Dispatcher::dispatch( Function_Type type, const Parser::Action *act, i->second.function( fb, this ); } -void Dispatcher::OSC_put( const Parser::OSC_Put *act ) { +void Dispatcher::OSC_put( const Parser::OSC_Put* act ) +{ assert( act->char_present ); if ( OSC_string.size() < MAXIMUM_CLIPBOARD_SIZE ) { OSC_string.push_back( act->ch ); } } -void Dispatcher::OSC_start( const Parser::OSC_Start *act - __attribute( ( unused ) ) ) { +void Dispatcher::OSC_start( const Parser::OSC_Start* act __attribute( ( unused ) ) ) +{ OSC_string.clear(); } -bool Dispatcher::operator==( const Dispatcher &x ) const { - return ( params == x.params ) && ( parsed_params == x.parsed_params ) - && ( parsed == x.parsed ) && ( dispatch_chars == x.dispatch_chars ) - && ( OSC_string == x.OSC_string ) - && ( terminal_to_host == x.terminal_to_host ); +bool Dispatcher::operator==( const Dispatcher& x ) const +{ + return ( params == x.params ) && ( parsed_params == x.parsed_params ) && ( parsed == x.parsed ) + && ( dispatch_chars == x.dispatch_chars ) && ( OSC_string == x.OSC_string ) + && ( terminal_to_host == x.terminal_to_host ); } diff --git a/src/terminal/terminaldispatcher.h b/src/terminal/terminaldispatcher.h index 7998a3aef..5109aac95 100644 --- a/src/terminal/terminaldispatcher.h +++ b/src/terminal/terminaldispatcher.h @@ -38,85 +38,100 @@ #include namespace Parser { - class Action; - class Param; - class Collect; - class Clear; - class Esc_Dispatch; - class CSI_Dispatch; - class Execute; - class OSC_Start; - class OSC_Put; - class OSC_End; +class Action; +class Param; +class Collect; +class Clear; +class Esc_Dispatch; +class CSI_Dispatch; +class Execute; +class OSC_Start; +class OSC_Put; +class OSC_End; } namespace Terminal { - class Framebuffer; - class Dispatcher; - - enum Function_Type { ESCAPE, CSI, CONTROL }; - - class Function { - public: - Function() : function( NULL ), clears_wrap_state( true ) {} - Function( Function_Type type, const std::string &dispatch_chars, - void ( *s_function )( Framebuffer *, Dispatcher * ), - bool s_clears_wrap_state = true ); - void ( *function )( Framebuffer *, Dispatcher * ); - bool clears_wrap_state; - }; - - typedef std::map dispatch_map_t; - - class DispatchRegistry { - public: - dispatch_map_t escape; - dispatch_map_t CSI; - dispatch_map_t control; - - DispatchRegistry() : escape(), CSI(), control() {} - }; - - DispatchRegistry &get_global_dispatch_registry( void ); - - class Dispatcher { - private: - std::string params; - std::vector parsed_params; - bool parsed; - - std::string dispatch_chars; - std::vector OSC_string; /* only used to set the window title */ - - void parse_params( void ); - - public: - static const int PARAM_MAX = 65535; - /* prevent evil escape sequences from causing long loops */ - - std::string terminal_to_host; /* this is the reply string */ - - Dispatcher(); - int getparam( size_t N, int defaultval ); - int param_count( void ); - - void newparamchar( const Parser::Param *act ); - void collect( const Parser::Collect *act ); - void clear( const Parser::Clear *act ); - - std::string str( void ); - - void dispatch( Function_Type type, const Parser::Action *act, - Framebuffer *fb ); - std::string get_dispatch_chars( void ) const { return dispatch_chars; } - std::vector get_OSC_string( void ) const { return OSC_string; } - - void OSC_put( const Parser::OSC_Put *act ); - void OSC_start( const Parser::OSC_Start *act ); - void OSC_dispatch( const Parser::OSC_End *act, Framebuffer *fb ); - - bool operator==( const Dispatcher &x ) const; - }; +class Framebuffer; +class Dispatcher; + +enum Function_Type +{ + ESCAPE, + CSI, + CONTROL +}; + +class Function +{ +public: + Function() + : function( NULL ) + , clears_wrap_state( true ) + {} + Function( Function_Type type, + const std::string& dispatch_chars, + void ( *s_function )( Framebuffer*, Dispatcher* ), + bool s_clears_wrap_state = true ); + void ( *function )( Framebuffer*, Dispatcher* ); + bool clears_wrap_state; +}; + +typedef std::map dispatch_map_t; + +class DispatchRegistry +{ +public: + dispatch_map_t escape; + dispatch_map_t CSI; + dispatch_map_t control; + + DispatchRegistry() + : escape() + , CSI() + , control() + {} +}; + +DispatchRegistry& get_global_dispatch_registry( void ); + +class Dispatcher +{ +private: + std::string params; + std::vector parsed_params; + bool parsed; + + std::string dispatch_chars; + std::vector OSC_string; /* only used to set the window title */ + + void parse_params( void ); + +public: + static const int PARAM_MAX = 65535; + /* prevent evil escape sequences from causing long loops */ + + std::string terminal_to_host; /* this is the reply string */ + + Dispatcher(); + int getparam( size_t N, int defaultval ); + int param_count( void ); + + void newparamchar( const Parser::Param* act ); + void collect( const Parser::Collect* act ); + void clear( const Parser::Clear* act ); + + std::string str( void ); + + void dispatch( Function_Type type, const Parser::Action* act, Framebuffer* fb ); + std::string get_dispatch_chars( void ) const { return dispatch_chars; } + std::vector get_OSC_string( void ) const { return OSC_string; } + + void OSC_put( const Parser::OSC_Put* act ); + void OSC_start( const Parser::OSC_Start* act ); + void OSC_dispatch( const Parser::OSC_End* act, Framebuffer* fb ); + + bool operator==( const Dispatcher& x ) const; +}; } #endif diff --git a/src/terminal/terminaldisplay.cc b/src/terminal/terminaldisplay.cc index a09600ed0..fd650ff4c 100644 --- a/src/terminal/terminaldisplay.cc +++ b/src/terminal/terminaldisplay.cc @@ -39,28 +39,30 @@ using namespace Terminal; /* Print a new "frame" to the terminal, using ANSI/ECMA-48 escape codes. */ -static const Renditions &initial_rendition( void ) { +static const Renditions& initial_rendition( void ) +{ const static Renditions blank = Renditions( 0 ); return blank; } -std::string Display::open() const { +std::string Display::open() const +{ return std::string( smcup ? smcup : "" ) + std::string( "\033[?1h" ); } -std::string Display::close() const { - return std::string( - "\033[?1l\033[0m\033[?25h" - "\033[?1003l\033[?1002l\033[?1001l\033[?1000l" - "\033[?1015l\033[?1006l\033[?1005l" ) - + std::string( rmcup ? rmcup : "" ); +std::string Display::close() const +{ + return std::string( "\033[?1l\033[0m\033[?25h" + "\033[?1003l\033[?1002l\033[?1001l\033[?1000l" + "\033[?1015l\033[?1006l\033[?1005l" ) + + std::string( rmcup ? rmcup : "" ); } -std::string Display::new_frame( bool initialized, const Framebuffer &last, - const Framebuffer &f ) const { +std::string Display::new_frame( bool initialized, const Framebuffer& last, const Framebuffer& f ) const +{ FrameState frame( last ); - char tmp[ 64 ]; + char tmp[64]; /* has bell been rung? */ if ( f.get_bell_count() != frame.last_frame.get_bell_count() ) { @@ -70,17 +72,14 @@ std::string Display::new_frame( bool initialized, const Framebuffer &last, /* has icon name or window title changed? */ if ( has_title && f.is_title_initialized() - && ( ( !initialized ) - || ( f.get_icon_name() != frame.last_frame.get_icon_name() ) - || ( f.get_window_title() - != frame.last_frame.get_window_title() ) ) ) { + && ( ( !initialized ) || ( f.get_icon_name() != frame.last_frame.get_icon_name() ) + || ( f.get_window_title() != frame.last_frame.get_window_title() ) ) ) { /* set icon name and window title */ if ( f.get_icon_name() == f.get_window_title() ) { /* write combined Icon Name and Window Title */ frame.append( "\033]0;" ); - const title_type &window_title( f.get_window_title() ); - for ( title_type::const_iterator i = window_title.begin(); - i != window_title.end(); i++ ) { + const title_type& window_title( f.get_window_title() ); + for ( title_type::const_iterator i = window_title.begin(); i != window_title.end(); i++ ) { frame.append( *i ); } frame.append( '\007' ); @@ -88,17 +87,15 @@ std::string Display::new_frame( bool initialized, const Framebuffer &last, } else { /* write Icon Name */ frame.append( "\033]1;" ); - const title_type &icon_name( f.get_icon_name() ); - for ( title_type::const_iterator i = icon_name.begin(); - i != icon_name.end(); i++ ) { + const title_type& icon_name( f.get_icon_name() ); + for ( title_type::const_iterator i = icon_name.begin(); i != icon_name.end(); i++ ) { frame.append( *i ); } frame.append( '\007' ); frame.append( "\033]2;" ); - const title_type &window_title( f.get_window_title() ); - for ( title_type::const_iterator i = window_title.begin(); - i != window_title.end(); i++ ) { + const title_type& window_title( f.get_window_title() ); + for ( title_type::const_iterator i = window_title.begin(); i != window_title.end(); i++ ) { frame.append( *i ); } frame.append( '\007' ); @@ -108,25 +105,22 @@ std::string Display::new_frame( bool initialized, const Framebuffer &last, /* has clipboard changed? */ if ( f.get_clipboard() != frame.last_frame.get_clipboard() ) { frame.append( "\033]52;c;" ); - const title_type &clipboard( f.get_clipboard() ); - for ( title_type::const_iterator i = clipboard.begin(); - i != clipboard.end(); i++ ) { + const title_type& clipboard( f.get_clipboard() ); + for ( title_type::const_iterator i = clipboard.begin(); i != clipboard.end(); i++ ) { frame.append( *i ); } frame.append( '\007' ); } /* has reverse video state changed? */ - if ( ( !initialized ) - || ( f.ds.reverse_video != frame.last_frame.ds.reverse_video ) ) { + if ( ( !initialized ) || ( f.ds.reverse_video != frame.last_frame.ds.reverse_video ) ) { /* set reverse video */ snprintf( tmp, 64, "\033[?5%c", ( f.ds.reverse_video ? 'h' : 'l' ) ); frame.append( tmp ); } /* has size changed? */ - if ( ( !initialized ) - || ( f.ds.get_width() != frame.last_frame.ds.get_width() ) + if ( ( !initialized ) || ( f.ds.get_width() != frame.last_frame.ds.get_width() ) || ( f.ds.get_height() != frame.last_frame.ds.get_height() ) ) { /* reset scrolling region */ frame.append( "\033[r" ); @@ -153,11 +147,9 @@ std::string Display::new_frame( bool initialized, const Framebuffer &last, Framebuffer::rows_type rows( frame.last_frame.get_rows() ); /* Extend rows if we've gotten a resize and new is wider than old */ if ( frame.last_frame.ds.get_width() < f.ds.get_width() ) { - for ( Framebuffer::rows_type::iterator p = rows.begin(); p != rows.end(); - p++ ) { + for ( Framebuffer::rows_type::iterator p = rows.begin(); p != rows.end(); p++ ) { *p = make_shared( **p ); - ( *p )->cells.resize( f.ds.get_width(), - Cell( f.ds.get_background_rendition() ) ); + ( *p )->cells.resize( f.ds.get_width(), Cell( f.ds.get_background_rendition() ) ); } } /* Add rows if we've gotten a resize and new is taller than old */ @@ -175,8 +167,8 @@ std::string Display::new_frame( bool initialized, const Framebuffer &last, int scroll_height = 0; for ( int row = 0; row < f.ds.get_height(); row++ ) { - const Row *new_row = f.get_row( 0 ); - const Row *old_row = &*rows.at( row ); + const Row* new_row = f.get_row( 0 ); + const Row* old_row = &*rows.at( row ); if ( !( new_row == old_row || *new_row == *old_row ) ) { continue; } @@ -189,11 +181,8 @@ std::string Display::new_frame( bool initialized, const Framebuffer &last, scroll_height = 1; /* how big is the region that was scrolled? */ - for ( int region_height = 1; - lines_scrolled + region_height < f.ds.get_height(); - region_height++ ) { - if ( *f.get_row( region_height ) - == *rows.at( lines_scrolled + region_height ) ) { + for ( int region_height = 1; lines_scrolled + region_height < f.ds.get_height(); region_height++ ) { + if ( *f.get_row( region_height ) == *rows.at( lines_scrolled + region_height ) ) { scroll_height = region_height + 1; } else { break; @@ -220,11 +209,10 @@ std::string Display::new_frame( bool initialized, const Framebuffer &last, assert( bottom_margin < f.ds.get_height() ); - /* Common case: if we're already on the bottom line and we're scrolling - * the whole screen, just do a CR and LFs. + /* Common case: if we're already on the bottom line and we're scrolling the whole + * screen, just do a CR and LFs. */ - if ( scroll_height + lines_scrolled == f.ds.get_height() - && frame.cursor_y + 1 == f.ds.get_height() ) { + if ( scroll_height + lines_scrolled == f.ds.get_height() && frame.cursor_y + 1 == f.ds.get_height() ) { frame.append( '\r' ); frame.append( lines_scrolled, '\n' ); frame.cursor_x = 0; @@ -283,25 +271,20 @@ std::string Display::new_frame( bool initialized, const Framebuffer &last, frame.update_rendition( f.ds.get_renditions(), !initialized ); /* has bracketed paste mode changed? */ - if ( ( !initialized ) - || ( f.ds.bracketed_paste != frame.last_frame.ds.bracketed_paste ) ) { + if ( ( !initialized ) || ( f.ds.bracketed_paste != frame.last_frame.ds.bracketed_paste ) ) { frame.append( f.ds.bracketed_paste ? "\033[?2004h" : "\033[?2004l" ); } /* has mouse reporting mode changed? */ - if ( ( !initialized ) - || ( f.ds.mouse_reporting_mode - != frame.last_frame.ds.mouse_reporting_mode ) ) { + if ( ( !initialized ) || ( f.ds.mouse_reporting_mode != frame.last_frame.ds.mouse_reporting_mode ) ) { if ( f.ds.mouse_reporting_mode == DrawState::MOUSE_REPORTING_NONE ) { frame.append( "\033[?1003l" ); frame.append( "\033[?1002l" ); frame.append( "\033[?1001l" ); frame.append( "\033[?1000l" ); } else { - if ( frame.last_frame.ds.mouse_reporting_mode - != DrawState::MOUSE_REPORTING_NONE ) { - snprintf( tmp, sizeof( tmp ), "\033[?%dl", - frame.last_frame.ds.mouse_reporting_mode ); + if ( frame.last_frame.ds.mouse_reporting_mode != DrawState::MOUSE_REPORTING_NONE ) { + snprintf( tmp, sizeof( tmp ), "\033[?%dl", frame.last_frame.ds.mouse_reporting_mode ); frame.append( tmp ); } snprintf( tmp, sizeof( tmp ), "\033[?%dh", f.ds.mouse_reporting_mode ); @@ -310,25 +293,19 @@ std::string Display::new_frame( bool initialized, const Framebuffer &last, } /* has mouse focus mode changed? */ - if ( ( !initialized ) - || ( f.ds.mouse_focus_event - != frame.last_frame.ds.mouse_focus_event ) ) { + if ( ( !initialized ) || ( f.ds.mouse_focus_event != frame.last_frame.ds.mouse_focus_event ) ) { frame.append( f.ds.mouse_focus_event ? "\033[?1004h" : "\033[?1004l" ); } /* has mouse encoding mode changed? */ - if ( ( !initialized ) - || ( f.ds.mouse_encoding_mode - != frame.last_frame.ds.mouse_encoding_mode ) ) { + if ( ( !initialized ) || ( f.ds.mouse_encoding_mode != frame.last_frame.ds.mouse_encoding_mode ) ) { if ( f.ds.mouse_encoding_mode == DrawState::MOUSE_ENCODING_DEFAULT ) { frame.append( "\033[?1015l" ); frame.append( "\033[?1006l" ); frame.append( "\033[?1005l" ); } else { - if ( frame.last_frame.ds.mouse_encoding_mode - != DrawState::MOUSE_ENCODING_DEFAULT ) { - snprintf( tmp, sizeof( tmp ), "\033[?%dl", - frame.last_frame.ds.mouse_encoding_mode ); + if ( frame.last_frame.ds.mouse_encoding_mode != DrawState::MOUSE_ENCODING_DEFAULT ) { + snprintf( tmp, sizeof( tmp ), "\033[?%dl", frame.last_frame.ds.mouse_encoding_mode ); frame.append( tmp ); } snprintf( tmp, sizeof( tmp ), "\033[?%dh", f.ds.mouse_encoding_mode ); @@ -339,20 +316,23 @@ std::string Display::new_frame( bool initialized, const Framebuffer &last, return frame.str; } -bool Display::put_row( bool initialized, FrameState &frame, - const Framebuffer &f, int frame_y, const Row &old_row, - bool wrap ) const { - char tmp[ 64 ]; +bool Display::put_row( bool initialized, + FrameState& frame, + const Framebuffer& f, + int frame_y, + const Row& old_row, + bool wrap ) const +{ + char tmp[64]; int frame_x = 0; - const Row &row = *f.get_row( frame_y ); - const Row::cells_type &cells = row.cells; - const Row::cells_type &old_cells = old_row.cells; + const Row& row = *f.get_row( frame_y ); + const Row::cells_type& cells = row.cells; + const Row::cells_type& old_cells = old_row.cells; - /* If we're forced to write the first column because of wrap, go ahead and do - * so. */ + /* If we're forced to write the first column because of wrap, go ahead and do so. */ if ( wrap ) { - const Cell &cell = cells.at( 0 ); + const Cell& cell = cells.at( 0 ); frame.update_rendition( cell.get_renditions() ); frame.append_cell( cell ); frame_x += cell.get_width(); @@ -373,7 +353,7 @@ bool Display::put_row( bool initialized, FrameState &frame, /* iterate for every cell */ while ( frame_x < row_width ) { - const Cell &cell = cells.at( frame_x ); + const Cell& cell = cells.at( frame_x ); /* Does cell need to be drawn? Skip all this. */ if ( initialized && !clear_count && ( cell == old_cells.at( frame_x ) ) ) { @@ -399,8 +379,7 @@ bool Display::put_row( bool initialized, FrameState &frame, /* Move to the right position. */ frame.append_silent_move( frame_y, frame_x - clear_count ); frame.update_rendition( blank_renditions ); - bool can_use_erase = - has_bce || ( frame.current_rendition == initial_rendition() ); + bool can_use_erase = has_bce || ( frame.current_rendition == initial_rendition() ); if ( can_use_erase && has_ech && clear_count > 4 ) { snprintf( tmp, 64, "\033[%dX", clear_count ); frame.append( tmp ); @@ -409,8 +388,8 @@ bool Display::put_row( bool initialized, FrameState &frame, frame.cursor_x = frame_x; } clear_count = 0; - // If the current character is *another* empty cell in a different - // rendition, we restart counting and continue here + // If the current character is *another* empty cell in a different rendition, + // we restart counting and continue here if ( cell.empty() ) { blank_renditions = cell.get_renditions(); clear_count = 1; @@ -450,8 +429,7 @@ bool Display::put_row( bool initialized, FrameState &frame, frame.append_silent_move( frame_y, frame_x - clear_count ); frame.update_rendition( blank_renditions ); - bool can_use_erase = - has_bce || ( frame.current_rendition == initial_rendition() ); + bool can_use_erase = has_bce || ( frame.current_rendition == initial_rendition() ); if ( can_use_erase && !wrap_this ) { frame.append( "\033[K" ); } else { @@ -480,20 +458,22 @@ bool Display::put_row( bool initialized, FrameState &frame, return false; } -FrameState::FrameState( const Framebuffer &s_last ) - : str(), - cursor_x( 0 ), - cursor_y( 0 ), - current_rendition( 0 ), - cursor_visible( s_last.ds.cursor_visible ), - last_frame( s_last ) { - /* Preallocate for better performance. Make a guess-- doesn't matter for - * correctness */ +FrameState::FrameState( const Framebuffer& s_last ) + : str() + , cursor_x( 0 ) + , cursor_y( 0 ) + , current_rendition( 0 ) + , cursor_visible( s_last.ds.cursor_visible ) + , last_frame( s_last ) +{ + /* Preallocate for better performance. Make a guess-- doesn't matter for correctness */ str.reserve( last_frame.ds.get_width() * last_frame.ds.get_height() * 4 ); } -void FrameState::append_silent_move( int y, int x ) { - if ( cursor_x == x && cursor_y == y ) return; +void FrameState::append_silent_move( int y, int x ) +{ + if ( cursor_x == x && cursor_y == y ) + return; /* turn off cursor if necessary before moving cursor */ if ( cursor_visible ) { append( "\033[?25l" ); @@ -502,7 +482,8 @@ void FrameState::append_silent_move( int y, int x ) { append_move( y, x ); } -void FrameState::append_move( int y, int x ) { +void FrameState::append_move( int y, int x ) +{ const int last_x = cursor_x; const int last_y = cursor_y; cursor_x = x; @@ -524,12 +505,13 @@ void FrameState::append_move( int y, int x ) { } // More optimizations are possible. } - char tmp[ 64 ]; + char tmp[64]; snprintf( tmp, 64, "\033[%d;%dH", y + 1, x + 1 ); append( tmp ); } -void FrameState::update_rendition( const Renditions &r, bool force ) { +void FrameState::update_rendition( const Renditions& r, bool force ) +{ if ( force || !( current_rendition == r ) ) { /* print renditions */ append_string( r.sgr() ); diff --git a/src/terminal/terminaldisplay.h b/src/terminal/terminaldisplay.h index c3b3a4e7e..17e29a467 100644 --- a/src/terminal/terminaldisplay.h +++ b/src/terminal/terminaldisplay.h @@ -36,55 +36,59 @@ #include "terminalframebuffer.h" namespace Terminal { - /* variables used within a new_frame */ - class FrameState { - public: - std::string str; +/* variables used within a new_frame */ +class FrameState +{ +public: + std::string str; - int cursor_x, cursor_y; - Renditions current_rendition; - bool cursor_visible; + int cursor_x, cursor_y; + Renditions current_rendition; + bool cursor_visible; - const Framebuffer &last_frame; + const Framebuffer& last_frame; - FrameState( const Framebuffer &s_last ); + FrameState( const Framebuffer& s_last ); - void append( char c ) { str.append( 1, c ); } - void append( size_t s, char c ) { str.append( s, c ); } - void append( wchar_t wc ) { Cell::append_to_str( str, wc ); } - void append( const char *s ) { str.append( s ); } - void append_string( const std::string &append ) { str.append( append ); } + void append( char c ) { str.append( 1, c ); } + void append( size_t s, char c ) { str.append( s, c ); } + void append( wchar_t wc ) { Cell::append_to_str( str, wc ); } + void append( const char* s ) { str.append( s ); } + void append_string( const std::string& append ) { str.append( append ); } - void append_cell( const Cell &cell ) { cell.print_grapheme( str ); } - void append_silent_move( int y, int x ); - void append_move( int y, int x ); - void update_rendition( const Renditions &r, bool force = false ); - }; + void append_cell( const Cell& cell ) { cell.print_grapheme( str ); } + void append_silent_move( int y, int x ); + void append_move( int y, int x ); + void update_rendition( const Renditions& r, bool force = false ); +}; - class Display { - private: - bool has_ech; /* erase character is part of vt200 but not supported by tmux - (or by "screen" terminfo entry, which is what tmux - advertises) */ +class Display +{ +private: + bool has_ech; /* erase character is part of vt200 but not supported by tmux + (or by "screen" terminfo entry, which is what tmux advertises) */ - bool has_bce; /* erases result in cell filled with background color */ + bool has_bce; /* erases result in cell filled with background color */ - bool has_title; /* supports window title and icon name */ + bool has_title; /* supports window title and icon name */ - const char *smcup, *rmcup; /* enter and exit alternate screen mode */ + const char *smcup, *rmcup; /* enter and exit alternate screen mode */ - bool put_row( bool initialized, FrameState &frame, const Framebuffer &f, - int frame_y, const Row &old_row, bool wrap ) const; + bool put_row( bool initialized, + FrameState& frame, + const Framebuffer& f, + int frame_y, + const Row& old_row, + bool wrap ) const; - public: - std::string open() const; - std::string close() const; +public: + std::string open() const; + std::string close() const; - std::string new_frame( bool initialized, const Framebuffer &last, - const Framebuffer &f ) const; + std::string new_frame( bool initialized, const Framebuffer& last, const Framebuffer& f ) const; - Display( bool use_environment ); - }; + Display( bool use_environment ); +}; } #endif diff --git a/src/terminal/terminaldisplayinit.cc b/src/terminal/terminaldisplayinit.cc index f98e8715f..3a3bbd16c 100644 --- a/src/terminal/terminaldisplayinit.cc +++ b/src/terminal/terminaldisplayinit.cc @@ -62,45 +62,49 @@ using namespace Terminal; -static bool ti_flag( const char *capname ) { - int val = tigetflag( const_cast( capname ) ); +static bool ti_flag( const char* capname ) +{ + int val = tigetflag( const_cast( capname ) ); if ( val == -1 ) { - throw std::invalid_argument( - std::string( "Invalid terminfo boolean capability " ) + capname ); + throw std::invalid_argument( std::string( "Invalid terminfo boolean capability " ) + capname ); } return val; } -static const char *ti_str( const char *capname ) { - const char *val = tigetstr( const_cast( capname ) ); - if ( val == (const char *)-1 ) { - throw std::invalid_argument( - std::string( "Invalid terminfo string capability " ) + capname ); +static const char* ti_str( const char* capname ) +{ + const char* val = tigetstr( const_cast( capname ) ); + if ( val == (const char*)-1 ) { + throw std::invalid_argument( std::string( "Invalid terminfo string capability " ) + capname ); } return val; } Display::Display( bool use_environment ) - : has_ech( true ), - has_bce( true ), - has_title( true ), - smcup( NULL ), - rmcup( NULL ) { + : has_ech( true ) + , has_bce( true ) + , has_title( true ) + , smcup( NULL ) + , rmcup( NULL ) +{ if ( use_environment ) { int errret = -2; - int ret = setupterm( (char *)0, 1, &errret ); + int ret = setupterm( (char*)0, 1, &errret ); if ( ret != OK ) { switch ( errret ) { - case 1: - throw std::runtime_error( - "Terminal is hardcopy and cannot be used by curses applications." ); - break; - case 0: throw std::runtime_error( "Unknown terminal type." ); break; - case -1: - throw std::runtime_error( "Terminfo database could not be found." ); - break; - default: throw std::runtime_error( "Unknown terminfo error." ); break; + case 1: + throw std::runtime_error( "Terminal is hardcopy and cannot be used by curses applications." ); + break; + case 0: + throw std::runtime_error( "Unknown terminal type." ); + break; + case -1: + throw std::runtime_error( "Terminfo database could not be found." ); + break; + default: + throw std::runtime_error( "Unknown terminfo error." ); + break; } } @@ -113,18 +117,14 @@ Display::Display( bool use_environment ) /* Check if we can set the window title and icon name. terminfo does not have reliable information on this, so we hardcode a whitelist of terminal type prefixes. */ - static const char *const title_term_types[] = { - "xterm", "rxvt", "kterm", "Eterm", "alacritty", "screen", "tmux" - }; + static const char* const title_term_types[] + = { "xterm", "rxvt", "kterm", "Eterm", "alacritty", "screen", "tmux" }; has_title = false; - const char *term_type = getenv( "TERM" ); + const char* term_type = getenv( "TERM" ); if ( term_type ) { - for ( size_t i = 0; - i < sizeof( title_term_types ) / sizeof( const char * ); i++ ) { - if ( 0 - == strncmp( term_type, title_term_types[ i ], - strlen( title_term_types[ i ] ) ) ) { + for ( size_t i = 0; i < sizeof( title_term_types ) / sizeof( const char* ); i++ ) { + if ( 0 == strncmp( term_type, title_term_types[i], strlen( title_term_types[i] ) ) ) { has_title = true; break; } diff --git a/src/terminal/terminalframebuffer.cc b/src/terminal/terminalframebuffer.cc index 2084eed18..7edcdf1be 100644 --- a/src/terminal/terminalframebuffer.cc +++ b/src/terminal/terminalframebuffer.cc @@ -39,13 +39,15 @@ using namespace Terminal; Cell::Cell( color_type background_color ) - : contents(), - renditions( background_color ), - wide( false ), - fallback( false ), - wrap( false ) {} - -void Cell::reset( color_type background_color ) { + : contents() + , renditions( background_color ) + , wide( false ) + , fallback( false ) + , wrap( false ) +{} + +void Cell::reset( color_type background_color ) +{ contents.clear(); renditions = Renditions( background_color ); wide = false; @@ -53,49 +55,52 @@ void Cell::reset( color_type background_color ) { wrap = false; } -void DrawState::reinitialize_tabs( unsigned int start ) { +void DrawState::reinitialize_tabs( unsigned int start ) +{ assert( default_tabs ); for ( unsigned int i = start; i < tabs.size(); i++ ) { - tabs[ i ] = ( ( i % 8 ) == 0 ); + tabs[i] = ( ( i % 8 ) == 0 ); } } DrawState::DrawState( int s_width, int s_height ) - : width( s_width ), - height( s_height ), - cursor_col( 0 ), - cursor_row( 0 ), - combining_char_col( 0 ), - combining_char_row( 0 ), - default_tabs( true ), - tabs( s_width ), - scrolling_region_top_row( 0 ), - scrolling_region_bottom_row( height - 1 ), - renditions( 0 ), - save(), - next_print_will_wrap( false ), - origin_mode( false ), - auto_wrap_mode( true ), - insert_mode( false ), - cursor_visible( true ), - reverse_video( false ), - bracketed_paste( false ), - mouse_reporting_mode( MOUSE_REPORTING_NONE ), - mouse_focus_event( false ), - mouse_alternate_scroll( false ), - mouse_encoding_mode( MOUSE_ENCODING_DEFAULT ), - application_mode_cursor_keys( false ) { + : width( s_width ) + , height( s_height ) + , cursor_col( 0 ) + , cursor_row( 0 ) + , combining_char_col( 0 ) + , combining_char_row( 0 ) + , default_tabs( true ) + , tabs( s_width ) + , scrolling_region_top_row( 0 ) + , scrolling_region_bottom_row( height - 1 ) + , renditions( 0 ) + , save() + , next_print_will_wrap( false ) + , origin_mode( false ) + , auto_wrap_mode( true ) + , insert_mode( false ) + , cursor_visible( true ) + , reverse_video( false ) + , bracketed_paste( false ) + , mouse_reporting_mode( MOUSE_REPORTING_NONE ) + , mouse_focus_event( false ) + , mouse_alternate_scroll( false ) + , mouse_encoding_mode( MOUSE_ENCODING_DEFAULT ) + , application_mode_cursor_keys( false ) +{ reinitialize_tabs( 0 ); } Framebuffer::Framebuffer( int s_width, int s_height ) - : rows(), - icon_name(), - window_title(), - clipboard(), - bell_count( 0 ), - title_initialized( false ), - ds( s_width, s_height ) { + : rows() + , icon_name() + , window_title() + , clipboard() + , bell_count( 0 ) + , title_initialized( false ) + , ds( s_width, s_height ) +{ assert( s_height > 0 ); assert( s_width > 0 ); const size_t w = s_width; @@ -103,16 +108,18 @@ Framebuffer::Framebuffer( int s_width, int s_height ) rows = rows_type( s_height, row_pointer( make_shared( w, c ) ) ); } -Framebuffer::Framebuffer( const Framebuffer &other ) - : rows( other.rows ), - icon_name( other.icon_name ), - window_title( other.window_title ), - clipboard( other.clipboard ), - bell_count( other.bell_count ), - title_initialized( other.title_initialized ), - ds( other.ds ) {} +Framebuffer::Framebuffer( const Framebuffer& other ) + : rows( other.rows ) + , icon_name( other.icon_name ) + , window_title( other.window_title ) + , clipboard( other.clipboard ) + , bell_count( other.bell_count ) + , title_initialized( other.title_initialized ) + , ds( other.ds ) +{} -Framebuffer &Framebuffer::operator=( const Framebuffer &other ) { +Framebuffer& Framebuffer::operator=( const Framebuffer& other ) +{ if ( this != &other ) { rows = other.rows; icon_name = other.icon_name; @@ -125,7 +132,8 @@ Framebuffer &Framebuffer::operator=( const Framebuffer &other ) { return *this; } -void Framebuffer::scroll( int N ) { +void Framebuffer::scroll( int N ) +{ if ( N >= 0 ) { delete_line( ds.get_scrolling_region_top_row(), N ); } else { @@ -133,19 +141,26 @@ void Framebuffer::scroll( int N ) { } } -void DrawState::new_grapheme( void ) { +void DrawState::new_grapheme( void ) +{ combining_char_col = cursor_col; combining_char_row = cursor_row; } -void DrawState::snap_cursor_to_border( void ) { - if ( cursor_row < limit_top() ) cursor_row = limit_top(); - if ( cursor_row > limit_bottom() ) cursor_row = limit_bottom(); - if ( cursor_col < 0 ) cursor_col = 0; - if ( cursor_col >= width ) cursor_col = width - 1; +void DrawState::snap_cursor_to_border( void ) +{ + if ( cursor_row < limit_top() ) + cursor_row = limit_top(); + if ( cursor_row > limit_bottom() ) + cursor_row = limit_bottom(); + if ( cursor_col < 0 ) + cursor_col = 0; + if ( cursor_col >= width ) + cursor_col = width - 1; } -void DrawState::move_row( int N, bool relative ) { +void DrawState::move_row( int N, bool relative ) +{ if ( relative ) { cursor_row += N; } else { @@ -157,7 +172,8 @@ void DrawState::move_row( int N, bool relative ) { next_print_will_wrap = false; } -void DrawState::move_col( int N, bool relative, bool implicit ) { +void DrawState::move_col( int N, bool relative, bool implicit ) +{ if ( implicit ) { new_grapheme(); } @@ -179,7 +195,8 @@ void DrawState::move_col( int N, bool relative, bool implicit ) { } } -void Framebuffer::move_rows_autoscroll( int rows ) { +void Framebuffer::move_rows_autoscroll( int rows ) +{ /* don't scroll if outside the scrolling region */ if ( ( ds.get_cursor_row() < ds.get_scrolling_region_top_row() ) || ( ds.get_cursor_row() > ds.get_scrolling_region_bottom_row() ) ) { @@ -200,40 +217,47 @@ void Framebuffer::move_rows_autoscroll( int rows ) { ds.move_row( rows, true ); } -Cell *Framebuffer::get_combining_cell( void ) { - if ( ( ds.get_combining_char_col() < 0 ) - || ( ds.get_combining_char_row() < 0 ) +Cell* Framebuffer::get_combining_cell( void ) +{ + if ( ( ds.get_combining_char_col() < 0 ) || ( ds.get_combining_char_row() < 0 ) || ( ds.get_combining_char_col() >= ds.get_width() ) || ( ds.get_combining_char_row() >= ds.get_height() ) ) { return NULL; } /* can happen if a resize came in between */ - return get_mutable_cell( ds.get_combining_char_row(), - ds.get_combining_char_col() ); + return get_mutable_cell( ds.get_combining_char_row(), ds.get_combining_char_col() ); } -void DrawState::set_tab( void ) { tabs[ cursor_col ] = true; } +void DrawState::set_tab( void ) +{ + tabs[cursor_col] = true; +} -void DrawState::clear_tab( int col ) { tabs[ col ] = false; } +void DrawState::clear_tab( int col ) +{ + tabs[col] = false; +} -int DrawState::get_next_tab( int count ) const { +int DrawState::get_next_tab( int count ) const +{ if ( count >= 0 ) { for ( int i = cursor_col + 1; i < width; i++ ) { - if ( tabs[ i ] && --count == 0 ) { + if ( tabs[i] && --count == 0 ) { return i; } } return -1; } for ( int i = cursor_col - 1; i > 0; i-- ) { - if ( tabs[ i ] && ++count == 0 ) { + if ( tabs[i] && ++count == 0 ) { return i; } } return 0; } -void DrawState::set_scrolling_region( int top, int bottom ) { +void DrawState::set_scrolling_region( int top, int bottom ) +{ if ( height < 1 ) { return; } @@ -241,7 +265,8 @@ void DrawState::set_scrolling_region( int top, int bottom ) { scrolling_region_top_row = top; scrolling_region_bottom_row = bottom; - if ( scrolling_region_top_row < 0 ) scrolling_region_top_row = 0; + if ( scrolling_region_top_row < 0 ) + scrolling_region_top_row = 0; if ( scrolling_region_bottom_row >= height ) scrolling_region_bottom_row = height - 1; @@ -255,15 +280,18 @@ void DrawState::set_scrolling_region( int top, int bottom ) { } } -int DrawState::limit_top( void ) const { +int DrawState::limit_top( void ) const +{ return origin_mode ? scrolling_region_top_row : 0; } -int DrawState::limit_bottom( void ) const { +int DrawState::limit_bottom( void ) const +{ return origin_mode ? scrolling_region_bottom_row : height - 1; } -void Framebuffer::apply_renditions_to_cell( Cell *cell ) { +void Framebuffer::apply_renditions_to_cell( Cell* cell ) +{ if ( !cell ) { cell = get_mutable_cell(); } @@ -271,13 +299,15 @@ void Framebuffer::apply_renditions_to_cell( Cell *cell ) { } SavedCursor::SavedCursor() - : cursor_col( 0 ), - cursor_row( 0 ), - renditions( 0 ), - auto_wrap_mode( true ), - origin_mode( false ) {} - -void DrawState::save_cursor( void ) { + : cursor_col( 0 ) + , cursor_row( 0 ) + , renditions( 0 ) + , auto_wrap_mode( true ) + , origin_mode( false ) +{} + +void DrawState::save_cursor( void ) +{ save.cursor_col = cursor_col; save.cursor_row = cursor_row; save.renditions = renditions; @@ -285,7 +315,8 @@ void DrawState::save_cursor( void ) { save.origin_mode = origin_mode; } -void DrawState::restore_cursor( void ) { +void DrawState::restore_cursor( void ) +{ cursor_col = save.cursor_col; cursor_row = save.cursor_row; renditions = save.renditions; @@ -296,7 +327,8 @@ void DrawState::restore_cursor( void ) { new_grapheme(); } -void Framebuffer::insert_line( int before_row, int count ) { +void Framebuffer::insert_line( int before_row, int count ) +{ if ( ( before_row < ds.get_scrolling_region_top_row() ) || ( before_row > ds.get_scrolling_region_bottom_row() + 1 ) ) { return; @@ -312,17 +344,16 @@ void Framebuffer::insert_line( int before_row, int count ) { } // delete old rows - rows_type::iterator start = - rows.begin() + ds.get_scrolling_region_bottom_row() + 1 - scroll; + rows_type::iterator start = rows.begin() + ds.get_scrolling_region_bottom_row() + 1 - scroll; rows.erase( start, start + scroll ); // insert new rows start = rows.begin() + before_row; rows.insert( start, scroll, newrow() ); } -void Framebuffer::delete_line( int row, int count ) { - if ( ( row < ds.get_scrolling_region_top_row() ) - || ( row > ds.get_scrolling_region_bottom_row() ) ) { +void Framebuffer::delete_line( int row, int count ) +{ + if ( ( row < ds.get_scrolling_region_top_row() ) || ( row > ds.get_scrolling_region_bottom_row() ) ) { return; } @@ -344,32 +375,40 @@ void Framebuffer::delete_line( int row, int count ) { } Row::Row( const size_t s_width, const color_type background_color ) - : cells( s_width, Cell( background_color ) ), gen( get_gen() ) {} + : cells( s_width, Cell( background_color ) ) + , gen( get_gen() ) +{} -uint64_t Row::get_gen() const { +uint64_t Row::get_gen() const +{ static uint64_t gen_counter = 0; return gen_counter++; } -void Row::insert_cell( int col, color_type background_color ) { +void Row::insert_cell( int col, color_type background_color ) +{ cells.insert( cells.begin() + col, Cell( background_color ) ); cells.pop_back(); } -void Row::delete_cell( int col, color_type background_color ) { +void Row::delete_cell( int col, color_type background_color ) +{ cells.push_back( Cell( background_color ) ); cells.erase( cells.begin() + col ); } -void Framebuffer::insert_cell( int row, int col ) { +void Framebuffer::insert_cell( int row, int col ) +{ get_mutable_row( row )->insert_cell( col, ds.get_background_rendition() ); } -void Framebuffer::delete_cell( int row, int col ) { +void Framebuffer::delete_cell( int row, int col ) +{ get_mutable_row( row )->delete_cell( col, ds.get_background_rendition() ); } -void Framebuffer::reset( void ) { +void Framebuffer::reset( void ) +{ int width = ds.get_width(), height = ds.get_height(); ds = DrawState( width, height ); rows = rows_type( height, newrow() ); @@ -378,7 +417,8 @@ void Framebuffer::reset( void ) { /* do not reset bell_count */ } -void Framebuffer::soft_reset( void ) { +void Framebuffer::soft_reset( void ) +{ ds.insert_mode = false; ds.origin_mode = false; ds.cursor_visible = true; /* per xterm and gnome-terminal */ @@ -388,7 +428,8 @@ void Framebuffer::soft_reset( void ) { ds.clear_saved_cursor(); } -void Framebuffer::resize( int s_width, int s_height ) { +void Framebuffer::resize( int s_width, int s_height ) +{ assert( s_width > 0 ); assert( s_height > 0 ); @@ -403,15 +444,15 @@ void Framebuffer::resize( int s_width, int s_height ) { if ( oldwidth == s_width ) { return; } - for ( rows_type::iterator i = rows.begin(); i != rows.end() && *i != blankrow; - i++ ) { + for ( rows_type::iterator i = rows.begin(); i != rows.end() && *i != blankrow; i++ ) { *i = make_shared( **i ); ( *i )->set_wrap( false ); ( *i )->cells.resize( s_width, Cell( ds.get_background_rendition() ) ); } } -void DrawState::resize( int s_width, int s_height ) { +void DrawState::resize( int s_width, int s_height ) +{ if ( ( width != s_width ) || ( height != s_height ) ) { /* reset entire scrolling region on any resize */ /* xterm and rxvt-unicode do this. gnome-terminal only @@ -439,10 +480,14 @@ void DrawState::resize( int s_width, int s_height ) { } Renditions::Renditions( color_type s_background ) - : foreground_color( 0 ), background_color( s_background ), attributes( 0 ) {} + : foreground_color( 0 ) + , background_color( s_background ) + , attributes( 0 ) +{} /* This routine cannot be used to set a color beyond the 16-color set. */ -void Renditions::set_rendition( color_type num ) { +void Renditions::set_rendition( color_type num ) +{ if ( num == 0 ) { clear_attributes(); foreground_color = background_color = 0; @@ -460,39 +505,50 @@ void Renditions::set_rendition( color_type num ) { if ( ( 30 <= num ) && ( num <= 37 ) ) { /* foreground color in 8-color set */ foreground_color = num; return; - } else if ( ( 40 <= num ) - && ( num <= 47 ) ) { /* background color in 8-color set */ + } else if ( ( 40 <= num ) && ( num <= 47 ) ) { /* background color in 8-color set */ background_color = num; return; - } else if ( ( 90 <= num ) - && ( num <= 97 ) ) { /* foreground color in 16-color set */ + } else if ( ( 90 <= num ) && ( num <= 97 ) ) { /* foreground color in 16-color set */ foreground_color = num - 90 + 38; return; - } else if ( ( 100 <= num ) - && ( num <= 107 ) ) { /* background color in 16-color set */ + } else if ( ( 100 <= num ) && ( num <= 107 ) ) { /* background color in 16-color set */ background_color = num - 100 + 48; return; } bool value = num < 9; switch ( num ) { - case 1: - case 22: set_attribute( bold, value ); break; - case 3: - case 23: set_attribute( italic, value ); break; - case 4: - case 24: set_attribute( underlined, value ); break; - case 5: - case 25: set_attribute( blink, value ); break; - case 7: - case 27: set_attribute( inverse, value ); break; - case 8: - case 28: set_attribute( invisible, value ); break; - default: break; /* ignore unknown rendition */ - } -} - -void Renditions::set_foreground_color( int num ) { + case 1: + case 22: + set_attribute( bold, value ); + break; + case 3: + case 23: + set_attribute( italic, value ); + break; + case 4: + case 24: + set_attribute( underlined, value ); + break; + case 5: + case 25: + set_attribute( blink, value ); + break; + case 7: + case 27: + set_attribute( inverse, value ); + break; + case 8: + case 28: + set_attribute( invisible, value ); + break; + default: + break; /* ignore unknown rendition */ + } +} + +void Renditions::set_foreground_color( int num ) +{ if ( ( 0 <= num ) && ( num <= 255 ) ) { foreground_color = 30 + num; } else if ( is_true_color( num ) ) { @@ -500,7 +556,8 @@ void Renditions::set_foreground_color( int num ) { } } -void Renditions::set_background_color( int num ) { +void Renditions::set_background_color( int num ) +{ if ( ( 0 <= num ) && ( num <= 255 ) ) { background_color = 40 + num; } else if ( is_true_color( num ) ) { @@ -508,17 +565,24 @@ void Renditions::set_background_color( int num ) { } } -std::string Renditions::sgr( void ) const { +std::string Renditions::sgr( void ) const +{ std::string ret; - char col[ 64 ]; + char col[64]; ret.append( "\033[0" ); - if ( get_attribute( bold ) ) ret.append( ";1" ); - if ( get_attribute( italic ) ) ret.append( ";3" ); - if ( get_attribute( underlined ) ) ret.append( ";4" ); - if ( get_attribute( blink ) ) ret.append( ";5" ); - if ( get_attribute( inverse ) ) ret.append( ";7" ); - if ( get_attribute( invisible ) ) ret.append( ";8" ); + if ( get_attribute( bold ) ) + ret.append( ";1" ); + if ( get_attribute( italic ) ) + ret.append( ";3" ); + if ( get_attribute( underlined ) ) + ret.append( ";4" ); + if ( get_attribute( blink ) ) + ret.append( ";5" ); + if ( get_attribute( inverse ) ) + ret.append( ";7" ); + if ( get_attribute( invisible ) ) + ret.append( ";8" ); if ( foreground_color ) { // Since foreground_color is a 25-bit field, it is promoted to an int when @@ -526,9 +590,12 @@ std::string Renditions::sgr( void ) const { // https://timsong-cpp.github.io/cppwp/n4659/conv.prom#5.) The correct // printf format specifier is thus %d. if ( is_true_color( foreground_color ) ) { - snprintf( col, sizeof( col ), ";38;2;%d;%d;%d", + snprintf( col, + sizeof( col ), + ";38;2;%d;%d;%d", ( foreground_color >> 16 ) & 0xff, - ( foreground_color >> 8 ) & 0xff, foreground_color & 0xff ); + ( foreground_color >> 8 ) & 0xff, + foreground_color & 0xff ); } else if ( foreground_color > 37 ) { /* use 256-color set */ snprintf( col, sizeof( col ), ";38;5;%d", foreground_color - 30 ); } else { /* ANSI foreground color */ @@ -544,9 +611,12 @@ std::string Renditions::sgr( void ) const { if ( background_color ) { // See comment above about bit-field promotion; it applies here as well. if ( is_true_color( background_color ) ) { - snprintf( col, sizeof( col ), ";48;2;%d;%d;%d", + snprintf( col, + sizeof( col ), + ";48;2;%d;%d;%d", ( background_color >> 16 ) & 0xff, - ( background_color >> 8 ) & 0xff, background_color & 0xff ); + ( background_color >> 8 ) & 0xff, + background_color & 0xff ); } else if ( background_color > 47 ) { /* use 256-color set */ snprintf( col, sizeof( col ), ";48;5;%d", background_color - 40 ); } else { /* ANSI background color */ @@ -561,14 +631,16 @@ std::string Renditions::sgr( void ) const { return ret; } -void Row::reset( color_type background_color ) { +void Row::reset( color_type background_color ) +{ gen = get_gen(); for ( cells_type::iterator i = cells.begin(); i != cells.end(); i++ ) { i->reset( background_color ); } } -void Framebuffer::prefix_window_title( const title_type &s ) { +void Framebuffer::prefix_window_title( const title_type& s ) +{ if ( icon_name == window_title ) { /* preserve equivalence */ icon_name.insert( icon_name.begin(), s.begin(), s.end() ); @@ -576,20 +648,19 @@ void Framebuffer::prefix_window_title( const title_type &s ) { window_title.insert( window_title.begin(), s.begin(), s.end() ); } -std::string Cell::debug_contents( void ) const { +std::string Cell::debug_contents( void ) const +{ if ( contents.empty() ) { return "'_' ()"; } std::string chars( 1, '\'' ); print_grapheme( chars ); chars.append( "' [" ); - const char *lazycomma = ""; - char buf[ 64 ]; - for ( content_type::const_iterator i = contents.begin(); i < contents.end(); - i++ ) { + const char* lazycomma = ""; + char buf[64]; + for ( content_type::const_iterator i = contents.begin(); i < contents.end(); i++ ) { - snprintf( buf, sizeof buf, "%s0x%02x", lazycomma, - static_cast( *i ) ); + snprintf( buf, sizeof buf, "%s0x%02x", lazycomma, static_cast( *i ) ); chars.append( buf ); lazycomma = ", "; } @@ -597,7 +668,8 @@ std::string Cell::debug_contents( void ) const { return chars; } -bool Cell::compare( const Cell &other ) const { +bool Cell::compare( const Cell& other ) const +{ bool ret = false; std::string grapheme, other_grapheme; @@ -607,14 +679,15 @@ bool Cell::compare( const Cell &other ) const { if ( grapheme != other_grapheme ) { ret = true; - fprintf( stderr, "Graphemes: '%s' vs. '%s'\n", grapheme.c_str(), - other_grapheme.c_str() ); + fprintf( stderr, "Graphemes: '%s' vs. '%s'\n", grapheme.c_str(), other_grapheme.c_str() ); } if ( !contents_match( other ) ) { // ret = true; - fprintf( stderr, "Contents: %s (%ld) vs. %s (%ld)\n", - debug_contents().c_str(), static_cast( contents.size() ), + fprintf( stderr, + "Contents: %s (%ld) vs. %s (%ld)\n", + debug_contents().c_str(), + static_cast( contents.size() ), other.debug_contents().c_str(), static_cast( other.contents.size() ) ); } diff --git a/src/terminal/terminalframebuffer.h b/src/terminal/terminalframebuffer.h index 783911660..9109d8e00 100644 --- a/src/terminal/terminalframebuffer.h +++ b/src/terminal/terminalframebuffer.h @@ -47,440 +47,445 @@ /* Terminal framebuffer */ namespace Terminal { - using shared::make_shared; - using shared::shared_ptr; - typedef uint32_t color_type; - - class Renditions { - public: - typedef enum { - bold, - faint, - italic, - underlined, - blink, - inverse, - invisible, - SIZE - } attribute_type; - - private: - static const uint64_t true_color_mask = 0x1000000; - uint64_t foreground_color : 25; - uint64_t background_color : 25; - uint64_t attributes : 8; - - public: - Renditions( color_type s_background ); - void set_foreground_color( int num ); - void set_background_color( int num ); - void set_rendition( color_type num ); - std::string sgr( void ) const; - - static unsigned int make_true_color( unsigned int r, unsigned int g, - unsigned int b ) { - return true_color_mask | ( r << 16 ) | ( g << 8 ) | b; +using shared::make_shared; +using shared::shared_ptr; +typedef uint32_t color_type; + +class Renditions +{ +public: + typedef enum + { + bold, + faint, + italic, + underlined, + blink, + inverse, + invisible, + SIZE + } attribute_type; + +private: + static const uint64_t true_color_mask = 0x1000000; + uint64_t foreground_color : 25; + uint64_t background_color : 25; + uint64_t attributes : 8; + +public: + Renditions( color_type s_background ); + void set_foreground_color( int num ); + void set_background_color( int num ); + void set_rendition( color_type num ); + std::string sgr( void ) const; + + static unsigned int make_true_color( unsigned int r, unsigned int g, unsigned int b ) + { + return true_color_mask | ( r << 16 ) | ( g << 8 ) | b; + } + + static bool is_true_color( unsigned int color ) { return ( color & true_color_mask ) != 0; } + + // unsigned int get_foreground_rendition() const { return foreground_color; } + unsigned int get_background_rendition() const { return background_color; } + + bool operator==( const Renditions& x ) const + { + return ( attributes == x.attributes ) && ( foreground_color == x.foreground_color ) + && ( background_color == x.background_color ); + } + void set_attribute( attribute_type attr, bool val ) + { + attributes = val ? ( attributes | ( 1 << attr ) ) : ( attributes & ~( 1 << attr ) ); + } + bool get_attribute( attribute_type attr ) const { return attributes & ( 1 << attr ); } + void clear_attributes() { attributes = 0; } +}; + +class Cell +{ +private: + typedef std::string content_type; /* can be std::string, std::vector, or __gnu_cxx::__vstring */ + content_type contents; + Renditions renditions; + unsigned int wide : 1; /* 0 = narrow, 1 = wide */ + unsigned int fallback : 1; /* first character is combining character */ + unsigned int wrap : 1; + +private: + Cell(); + +public: + Cell( color_type background_color ); + + void reset( color_type background_color ); + + bool operator==( const Cell& x ) const + { + return ( ( contents == x.contents ) && ( fallback == x.fallback ) && ( wide == x.wide ) + && ( renditions == x.renditions ) && ( wrap == x.wrap ) ); + } + + bool operator!=( const Cell& x ) const { return !operator==( x ); } + + /* Accessors for contents field */ + std::string debug_contents( void ) const; + + bool empty( void ) const { return contents.empty(); } + /* 32 seems like a reasonable limit on combining characters */ + bool full( void ) const { return contents.size() >= 32; } + void clear( void ) { contents.clear(); } + + bool is_blank( void ) const + { + // XXX fix. + return ( contents.empty() || contents == " " || contents == "\xC2\xA0" ); + } + + bool contents_match( const Cell& other ) const + { + return ( is_blank() && other.is_blank() ) || ( contents == other.contents ); + } + + bool compare( const Cell& other ) const; + + // Is this a printing ISO 8859-1 character? + static bool isprint_iso8859_1( const wchar_t c ) + { + return ( c <= 0xff && c >= 0xa0 ) || ( c <= 0x7e && c >= 0x20 ); + } + + static void append_to_str( std::string& dest, const wchar_t c ) + { + /* ASCII? Cheat. */ + if ( static_cast( c ) <= 0x7f ) { + dest.push_back( static_cast( c ) ); + return; } - - static bool is_true_color( unsigned int color ) { - return ( color & true_color_mask ) != 0; - } - - // unsigned int get_foreground_rendition() const { return foreground_color; - // } - unsigned int get_background_rendition() const { return background_color; } - - bool operator==( const Renditions &x ) const { - return ( attributes == x.attributes ) - && ( foreground_color == x.foreground_color ) - && ( background_color == x.background_color ); - } - void set_attribute( attribute_type attr, bool val ) { - attributes = val ? ( attributes | ( 1 << attr ) ) : - ( attributes & ~( 1 << attr ) ); - } - bool get_attribute( attribute_type attr ) const { - return attributes & ( 1 << attr ); - } - void clear_attributes() { attributes = 0; } - }; - - class Cell { - private: - typedef std::string - content_type; /* can be std::string, std::vector, or - __gnu_cxx::__vstring */ - content_type contents; - Renditions renditions; - unsigned int wide : 1; /* 0 = narrow, 1 = wide */ - unsigned int fallback : 1; /* first character is combining character */ - unsigned int wrap : 1; - - private: - Cell(); - - public: - Cell( color_type background_color ); - - void reset( color_type background_color ); - - bool operator==( const Cell &x ) const { - return ( ( contents == x.contents ) && ( fallback == x.fallback ) - && ( wide == x.wide ) && ( renditions == x.renditions ) - && ( wrap == x.wrap ) ); - } - - bool operator!=( const Cell &x ) const { return !operator==( x ); } - - /* Accessors for contents field */ - std::string debug_contents( void ) const; - - bool empty( void ) const { return contents.empty(); } - /* 32 seems like a reasonable limit on combining characters */ - bool full( void ) const { return contents.size() >= 32; } - void clear( void ) { contents.clear(); } - - bool is_blank( void ) const { - // XXX fix. - return ( contents.empty() || contents == " " || contents == "\xC2\xA0" ); - } - - bool contents_match( const Cell &other ) const { - return ( is_blank() && other.is_blank() ) - || ( contents == other.contents ); - } - - bool compare( const Cell &other ) const; - - // Is this a printing ISO 8859-1 character? - static bool isprint_iso8859_1( const wchar_t c ) { - return ( c <= 0xff && c >= 0xa0 ) || ( c <= 0x7e && c >= 0x20 ); - } - - static void append_to_str( std::string &dest, const wchar_t c ) { - /* ASCII? Cheat. */ - if ( static_cast( c ) <= 0x7f ) { - dest.push_back( static_cast( c ) ); - return; - } - static mbstate_t ps = mbstate_t(); - char tmp[ MB_LEN_MAX ]; - size_t ignore = wcrtomb( NULL, 0, &ps ); - (void)ignore; - size_t len = wcrtomb( tmp, c, &ps ); - dest.append( tmp, len ); - } - - void append( const wchar_t c ) { - /* ASCII? Cheat. */ - if ( static_cast( c ) <= 0x7f ) { - contents.push_back( static_cast( c ) ); - return; - } - static mbstate_t ps = mbstate_t(); - char tmp[ MB_LEN_MAX ]; - size_t ignore = wcrtomb( NULL, 0, &ps ); - (void)ignore; - size_t len = wcrtomb( tmp, c, &ps ); - contents.insert( contents.end(), tmp, tmp + len ); - } - - void print_grapheme( std::string &output ) const { - if ( contents.empty() ) { - output.append( 1, ' ' ); - return; - } - /* - * cells that begin with combining character get combiner - * attached to no-break space - */ - if ( fallback ) { - output.append( "\xC2\xA0" ); - } - output.append( contents ); - } - - /* Other accessors */ - const Renditions &get_renditions( void ) const { return renditions; } - Renditions &get_renditions( void ) { return renditions; } - void set_renditions( const Renditions &r ) { renditions = r; } - bool get_wide( void ) const { return wide; } - void set_wide( bool w ) { wide = w; } - unsigned int get_width( void ) const { return wide + 1; } - bool get_fallback( void ) const { return fallback; } - void set_fallback( bool f ) { fallback = f; } - bool get_wrap( void ) const { return wrap; } - void set_wrap( bool f ) { wrap = f; } - }; - - class Row { - public: - typedef std::vector cells_type; - cells_type cells; - // gen is a generation counter. It can be used to quickly rule - // out the possibility of two rows being identical; this is useful - // in scrolling. - uint64_t gen; - - private: - Row(); - - public: - Row( const size_t s_width, const color_type background_color ); - - void insert_cell( int col, color_type background_color ); - void delete_cell( int col, color_type background_color ); - - void reset( color_type background_color ); - - bool operator==( const Row &x ) const { - return ( gen == x.gen && cells == x.cells ); - } - - bool get_wrap( void ) const { return cells.back().get_wrap(); } - void set_wrap( bool w ) { cells.back().set_wrap( w ); } - - uint64_t get_gen() const; - }; - - class SavedCursor { - public: - int cursor_col, cursor_row; - Renditions renditions; - /* not implemented: character set shift state */ - bool auto_wrap_mode; - bool origin_mode; - /* not implemented: state of selective erase */ - - SavedCursor(); - }; - - class DrawState { - private: - int width, height; - - void new_grapheme( void ); - void snap_cursor_to_border( void ); - - int cursor_col, cursor_row; - int combining_char_col, combining_char_row; - - bool default_tabs; - std::vector tabs; - - void reinitialize_tabs( unsigned int start ); - - int scrolling_region_top_row, scrolling_region_bottom_row; - - Renditions renditions; - - SavedCursor save; - - public: - bool next_print_will_wrap; - bool origin_mode; - bool auto_wrap_mode; - bool insert_mode; - bool cursor_visible; - bool reverse_video; - bool bracketed_paste; - - enum MouseReportingMode { - MOUSE_REPORTING_NONE = 0, - MOUSE_REPORTING_X10 = 9, - MOUSE_REPORTING_VT220 = 1000, - MOUSE_REPORTING_VT220_HILIGHT = 1001, - MOUSE_REPORTING_BTN_EVENT = 1002, - MOUSE_REPORTING_ANY_EVENT = 1003 - } mouse_reporting_mode; - - bool mouse_focus_event; // 1004 - bool mouse_alternate_scroll; // 1007 - - enum MouseEncodingMode { - MOUSE_ENCODING_DEFAULT = 0, - MOUSE_ENCODING_UTF8 = 1005, - MOUSE_ENCODING_SGR = 1006, - MOUSE_ENCODING_URXVT = 1015 - } mouse_encoding_mode; - - bool application_mode_cursor_keys; - - /* bold, etc. */ - - void move_row( int N, bool relative = false ); - void move_col( int N, bool relative = false, bool implicit = false ); - - int get_cursor_col( void ) const { return cursor_col; } - int get_cursor_row( void ) const { return cursor_row; } - int get_combining_char_col( void ) const { return combining_char_col; } - int get_combining_char_row( void ) const { return combining_char_row; } - int get_width( void ) const { return width; } - int get_height( void ) const { return height; } - - void set_tab( void ); - void clear_tab( int col ); - void clear_default_tabs( void ) { default_tabs = false; } - /* Default tabs can't be restored without resetting the draw state. */ - int get_next_tab( int count ) const; - - void set_scrolling_region( int top, int bottom ); - - int get_scrolling_region_top_row( void ) const { - return scrolling_region_top_row; + static mbstate_t ps = mbstate_t(); + char tmp[MB_LEN_MAX]; + size_t ignore = wcrtomb( NULL, 0, &ps ); + (void)ignore; + size_t len = wcrtomb( tmp, c, &ps ); + dest.append( tmp, len ); + } + + void append( const wchar_t c ) + { + /* ASCII? Cheat. */ + if ( static_cast( c ) <= 0x7f ) { + contents.push_back( static_cast( c ) ); + return; } - int get_scrolling_region_bottom_row( void ) const { - return scrolling_region_bottom_row; + static mbstate_t ps = mbstate_t(); + char tmp[MB_LEN_MAX]; + size_t ignore = wcrtomb( NULL, 0, &ps ); + (void)ignore; + size_t len = wcrtomb( tmp, c, &ps ); + contents.insert( contents.end(), tmp, tmp + len ); + } + + void print_grapheme( std::string& output ) const + { + if ( contents.empty() ) { + output.append( 1, ' ' ); + return; } - - int limit_top( void ) const; - int limit_bottom( void ) const; - - void set_foreground_color( int x ) { renditions.set_foreground_color( x ); } - void set_background_color( int x ) { renditions.set_background_color( x ); } - void add_rendition( color_type x ) { renditions.set_rendition( x ); } - const Renditions &get_renditions( void ) const { return renditions; } - Renditions &get_renditions( void ) { return renditions; } - int get_background_rendition( void ) const { - return renditions.get_background_rendition(); - } - - void save_cursor( void ); - void restore_cursor( void ); - void clear_saved_cursor( void ) { save = SavedCursor(); } - - void resize( int s_width, int s_height ); - - DrawState( int s_width, int s_height ); - - bool operator==( const DrawState &x ) const { - /* only compare fields that affect display */ - return ( width == x.width ) && ( height == x.height ) - && ( cursor_col == x.cursor_col ) && ( cursor_row == x.cursor_row ) - && ( cursor_visible == x.cursor_visible ) - && ( reverse_video == x.reverse_video ) - && ( renditions == x.renditions ) - && ( bracketed_paste == x.bracketed_paste ) - && ( mouse_reporting_mode == x.mouse_reporting_mode ) - && ( mouse_focus_event == x.mouse_focus_event ) - && ( mouse_alternate_scroll == x.mouse_alternate_scroll ) - && ( mouse_encoding_mode == x.mouse_encoding_mode ); - } - }; - - class Framebuffer { - // To minimize copying of rows and cells, we use shared_ptr to - // share unchanged rows between multiple Framebuffers. If we - // write to a row in a Framebuffer and it is shared with other - // owners, we copy it first. The shared_ptr naturally manages the - // usage of the actual rows themselves. - // - // We gain a couple of free extras by doing this: - // - // * A quick check for equality between rows in different - // Framebuffers is to simply compare the pointer values. If they - // are equal, then the rows are obviously identical. - // * If no row is shared, the frame has not been modified. - public: - typedef std::vector title_type; - typedef shared_ptr row_pointer; - typedef std::vector - rows_type; /* can be either std::vector or std::deque */ - - private: - rows_type rows; - title_type icon_name; - title_type window_title; - title_type clipboard; - unsigned int bell_count; - bool title_initialized; /* true if the window title has been set via an OSC - */ - - row_pointer newrow( void ) { - const size_t w = ds.get_width(); - const color_type c = ds.get_background_rendition(); - return make_shared( w, c ); - } - - public: - Framebuffer( int s_width, int s_height ); - Framebuffer( const Framebuffer &other ); - Framebuffer &operator=( const Framebuffer &other ); - DrawState ds; - - const rows_type &get_rows() const { return rows; } - - void scroll( int N ); - void move_rows_autoscroll( int rows ); - - inline const Row *get_row( int row ) const { - if ( row == -1 ) row = ds.get_cursor_row(); - - return rows.at( row ).get(); - } - - inline const Cell *get_cell( int row = -1, int col = -1 ) const { - if ( row == -1 ) row = ds.get_cursor_row(); - if ( col == -1 ) col = ds.get_cursor_col(); - - return &rows.at( row )->cells.at( col ); + /* + * cells that begin with combining character get combiner + * attached to no-break space + */ + if ( fallback ) { + output.append( "\xC2\xA0" ); } - - Row *get_mutable_row( int row ) { - if ( row == -1 ) row = ds.get_cursor_row(); - row_pointer &mutable_row = rows.at( row ); - // If the row is shared, copy it. - if ( !mutable_row.unique() ) { - mutable_row = make_shared( *mutable_row ); - } - return mutable_row.get(); + output.append( contents ); + } + + /* Other accessors */ + const Renditions& get_renditions( void ) const { return renditions; } + Renditions& get_renditions( void ) { return renditions; } + void set_renditions( const Renditions& r ) { renditions = r; } + bool get_wide( void ) const { return wide; } + void set_wide( bool w ) { wide = w; } + unsigned int get_width( void ) const { return wide + 1; } + bool get_fallback( void ) const { return fallback; } + void set_fallback( bool f ) { fallback = f; } + bool get_wrap( void ) const { return wrap; } + void set_wrap( bool f ) { wrap = f; } +}; + +class Row +{ +public: + typedef std::vector cells_type; + cells_type cells; + // gen is a generation counter. It can be used to quickly rule + // out the possibility of two rows being identical; this is useful + // in scrolling. + uint64_t gen; + +private: + Row(); + +public: + Row( const size_t s_width, const color_type background_color ); + + void insert_cell( int col, color_type background_color ); + void delete_cell( int col, color_type background_color ); + + void reset( color_type background_color ); + + bool operator==( const Row& x ) const { return ( gen == x.gen && cells == x.cells ); } + + bool get_wrap( void ) const { return cells.back().get_wrap(); } + void set_wrap( bool w ) { cells.back().set_wrap( w ); } + + uint64_t get_gen() const; +}; + +class SavedCursor +{ +public: + int cursor_col, cursor_row; + Renditions renditions; + /* not implemented: character set shift state */ + bool auto_wrap_mode; + bool origin_mode; + /* not implemented: state of selective erase */ + + SavedCursor(); +}; + +class DrawState +{ +private: + int width, height; + + void new_grapheme( void ); + void snap_cursor_to_border( void ); + + int cursor_col, cursor_row; + int combining_char_col, combining_char_row; + + bool default_tabs; + std::vector tabs; + + void reinitialize_tabs( unsigned int start ); + + int scrolling_region_top_row, scrolling_region_bottom_row; + + Renditions renditions; + + SavedCursor save; + +public: + bool next_print_will_wrap; + bool origin_mode; + bool auto_wrap_mode; + bool insert_mode; + bool cursor_visible; + bool reverse_video; + bool bracketed_paste; + + enum MouseReportingMode + { + MOUSE_REPORTING_NONE = 0, + MOUSE_REPORTING_X10 = 9, + MOUSE_REPORTING_VT220 = 1000, + MOUSE_REPORTING_VT220_HILIGHT = 1001, + MOUSE_REPORTING_BTN_EVENT = 1002, + MOUSE_REPORTING_ANY_EVENT = 1003 + } mouse_reporting_mode; + + bool mouse_focus_event; // 1004 + bool mouse_alternate_scroll; // 1007 + + enum MouseEncodingMode + { + MOUSE_ENCODING_DEFAULT = 0, + MOUSE_ENCODING_UTF8 = 1005, + MOUSE_ENCODING_SGR = 1006, + MOUSE_ENCODING_URXVT = 1015 + } mouse_encoding_mode; + + bool application_mode_cursor_keys; + + /* bold, etc. */ + + void move_row( int N, bool relative = false ); + void move_col( int N, bool relative = false, bool implicit = false ); + + int get_cursor_col( void ) const { return cursor_col; } + int get_cursor_row( void ) const { return cursor_row; } + int get_combining_char_col( void ) const { return combining_char_col; } + int get_combining_char_row( void ) const { return combining_char_row; } + int get_width( void ) const { return width; } + int get_height( void ) const { return height; } + + void set_tab( void ); + void clear_tab( int col ); + void clear_default_tabs( void ) { default_tabs = false; } + /* Default tabs can't be restored without resetting the draw state. */ + int get_next_tab( int count ) const; + + void set_scrolling_region( int top, int bottom ); + + int get_scrolling_region_top_row( void ) const { return scrolling_region_top_row; } + int get_scrolling_region_bottom_row( void ) const { return scrolling_region_bottom_row; } + + int limit_top( void ) const; + int limit_bottom( void ) const; + + void set_foreground_color( int x ) { renditions.set_foreground_color( x ); } + void set_background_color( int x ) { renditions.set_background_color( x ); } + void add_rendition( color_type x ) { renditions.set_rendition( x ); } + const Renditions& get_renditions( void ) const { return renditions; } + Renditions& get_renditions( void ) { return renditions; } + int get_background_rendition( void ) const { return renditions.get_background_rendition(); } + + void save_cursor( void ); + void restore_cursor( void ); + void clear_saved_cursor( void ) { save = SavedCursor(); } + + void resize( int s_width, int s_height ); + + DrawState( int s_width, int s_height ); + + bool operator==( const DrawState& x ) const + { + /* only compare fields that affect display */ + return ( width == x.width ) && ( height == x.height ) && ( cursor_col == x.cursor_col ) + && ( cursor_row == x.cursor_row ) && ( cursor_visible == x.cursor_visible ) + && ( reverse_video == x.reverse_video ) && ( renditions == x.renditions ) + && ( bracketed_paste == x.bracketed_paste ) && ( mouse_reporting_mode == x.mouse_reporting_mode ) + && ( mouse_focus_event == x.mouse_focus_event ) && ( mouse_alternate_scroll == x.mouse_alternate_scroll ) + && ( mouse_encoding_mode == x.mouse_encoding_mode ); + } +}; + +class Framebuffer +{ + // To minimize copying of rows and cells, we use shared_ptr to + // share unchanged rows between multiple Framebuffers. If we + // write to a row in a Framebuffer and it is shared with other + // owners, we copy it first. The shared_ptr naturally manages the + // usage of the actual rows themselves. + // + // We gain a couple of free extras by doing this: + // + // * A quick check for equality between rows in different + // Framebuffers is to simply compare the pointer values. If they + // are equal, then the rows are obviously identical. + // * If no row is shared, the frame has not been modified. +public: + typedef std::vector title_type; + typedef shared_ptr row_pointer; + typedef std::vector rows_type; /* can be either std::vector or std::deque */ + +private: + rows_type rows; + title_type icon_name; + title_type window_title; + title_type clipboard; + unsigned int bell_count; + bool title_initialized; /* true if the window title has been set via an OSC */ + + row_pointer newrow( void ) + { + const size_t w = ds.get_width(); + const color_type c = ds.get_background_rendition(); + return make_shared( w, c ); + } + +public: + Framebuffer( int s_width, int s_height ); + Framebuffer( const Framebuffer& other ); + Framebuffer& operator=( const Framebuffer& other ); + DrawState ds; + + const rows_type& get_rows() const { return rows; } + + void scroll( int N ); + void move_rows_autoscroll( int rows ); + + inline const Row* get_row( int row ) const + { + if ( row == -1 ) + row = ds.get_cursor_row(); + + return rows.at( row ).get(); + } + + inline const Cell* get_cell( int row = -1, int col = -1 ) const + { + if ( row == -1 ) + row = ds.get_cursor_row(); + if ( col == -1 ) + col = ds.get_cursor_col(); + + return &rows.at( row )->cells.at( col ); + } + + Row* get_mutable_row( int row ) + { + if ( row == -1 ) + row = ds.get_cursor_row(); + row_pointer& mutable_row = rows.at( row ); + // If the row is shared, copy it. + if ( !mutable_row.unique() ) { + mutable_row = make_shared( *mutable_row ); } + return mutable_row.get(); + } - Cell *get_mutable_cell( int row = -1, int col = -1 ) { - if ( row == -1 ) row = ds.get_cursor_row(); - if ( col == -1 ) col = ds.get_cursor_col(); + Cell* get_mutable_cell( int row = -1, int col = -1 ) + { + if ( row == -1 ) + row = ds.get_cursor_row(); + if ( col == -1 ) + col = ds.get_cursor_col(); - return &get_mutable_row( row )->cells.at( col ); - } + return &get_mutable_row( row )->cells.at( col ); + } - Cell *get_combining_cell( void ); + Cell* get_combining_cell( void ); - void apply_renditions_to_cell( Cell *cell ); + void apply_renditions_to_cell( Cell* cell ); - void insert_line( int before_row, int count ); - void delete_line( int row, int count ); + void insert_line( int before_row, int count ); + void delete_line( int row, int count ); - void insert_cell( int row, int col ); - void delete_cell( int row, int col ); + void insert_cell( int row, int col ); + void delete_cell( int row, int col ); - void reset( void ); - void soft_reset( void ); + void reset( void ); + void soft_reset( void ); - void set_title_initialized( void ) { title_initialized = true; } - bool is_title_initialized( void ) const { return title_initialized; } - void set_icon_name( const title_type &s ) { icon_name = s; } - void set_window_title( const title_type &s ) { window_title = s; } - void set_clipboard( const title_type &s ) { clipboard = s; } - const title_type &get_icon_name( void ) const { return icon_name; } - const title_type &get_window_title( void ) const { return window_title; } - const title_type &get_clipboard( void ) const { return clipboard; } + void set_title_initialized( void ) { title_initialized = true; } + bool is_title_initialized( void ) const { return title_initialized; } + void set_icon_name( const title_type& s ) { icon_name = s; } + void set_window_title( const title_type& s ) { window_title = s; } + void set_clipboard( const title_type& s ) { clipboard = s; } + const title_type& get_icon_name( void ) const { return icon_name; } + const title_type& get_window_title( void ) const { return window_title; } + const title_type& get_clipboard( void ) const { return clipboard; } - void prefix_window_title( const title_type &s ); + void prefix_window_title( const title_type& s ); - void resize( int s_width, int s_height ); + void resize( int s_width, int s_height ); - void reset_cell( Cell *c ) { c->reset( ds.get_background_rendition() ); } - void reset_row( Row *r ) { r->reset( ds.get_background_rendition() ); } + void reset_cell( Cell* c ) { c->reset( ds.get_background_rendition() ); } + void reset_row( Row* r ) { r->reset( ds.get_background_rendition() ); } - void ring_bell( void ) { bell_count++; } - unsigned int get_bell_count( void ) const { return bell_count; } + void ring_bell( void ) { bell_count++; } + unsigned int get_bell_count( void ) const { return bell_count; } - bool operator==( const Framebuffer &x ) const { - return ( rows == x.rows ) && ( window_title == x.window_title ) - && ( clipboard == x.clipboard ) && ( bell_count == x.bell_count ) - && ( ds == x.ds ); - } - }; + bool operator==( const Framebuffer& x ) const + { + return ( rows == x.rows ) && ( window_title == x.window_title ) && ( clipboard == x.clipboard ) + && ( bell_count == x.bell_count ) && ( ds == x.ds ); + } +}; } #endif diff --git a/src/terminal/terminalfunctions.cc b/src/terminal/terminalfunctions.cc index 44a7424ee..9e6b42f7a 100644 --- a/src/terminal/terminalfunctions.cc +++ b/src/terminal/terminalfunctions.cc @@ -30,10 +30,10 @@ also delete it here. */ -#include -#include #include +#include #include +#include #include "parseraction.h" #include "terminaldispatcher.h" @@ -43,69 +43,86 @@ using namespace Terminal; /* Terminal functions -- routines activated by CSI, escape or a control char */ -static void clearline( Framebuffer *fb, int row, int start, int end ) { +static void clearline( Framebuffer* fb, int row, int start, int end ) +{ for ( int col = start; col <= end; col++ ) { fb->reset_cell( fb->get_mutable_cell( row, col ) ); } } /* erase in line */ -static void CSI_EL( Framebuffer *fb, Dispatcher *dispatch ) { +static void CSI_EL( Framebuffer* fb, Dispatcher* dispatch ) +{ switch ( dispatch->getparam( 0, 0 ) ) { - case 0: /* default: active position to end of line, inclusive */ - clearline( fb, -1, fb->ds.get_cursor_col(), fb->ds.get_width() - 1 ); - break; - case 1: /* start of screen to active position, inclusive */ - clearline( fb, -1, 0, fb->ds.get_cursor_col() ); - break; - case 2: /* all of line */ fb->reset_row( fb->get_mutable_row( -1 ) ); break; - default: break; + case 0: /* default: active position to end of line, inclusive */ + clearline( fb, -1, fb->ds.get_cursor_col(), fb->ds.get_width() - 1 ); + break; + case 1: /* start of screen to active position, inclusive */ + clearline( fb, -1, 0, fb->ds.get_cursor_col() ); + break; + case 2: /* all of line */ + fb->reset_row( fb->get_mutable_row( -1 ) ); + break; + default: + break; } } static Function func_CSI_EL( CSI, "K", CSI_EL ); /* erase in display */ -static void CSI_ED( Framebuffer *fb, Dispatcher *dispatch ) { +static void CSI_ED( Framebuffer* fb, Dispatcher* dispatch ) +{ switch ( dispatch->getparam( 0, 0 ) ) { - case 0: /* active position to end of screen, inclusive */ - clearline( fb, -1, fb->ds.get_cursor_col(), fb->ds.get_width() - 1 ); - for ( int y = fb->ds.get_cursor_row() + 1; y < fb->ds.get_height(); y++ ) { - fb->reset_row( fb->get_mutable_row( y ) ); - } - break; - case 1: /* start of screen to active position, inclusive */ - for ( int y = 0; y < fb->ds.get_cursor_row(); y++ ) { - fb->reset_row( fb->get_mutable_row( y ) ); - } - clearline( fb, -1, 0, fb->ds.get_cursor_col() ); - break; - case 2: /* entire screen */ - for ( int y = 0; y < fb->ds.get_height(); y++ ) { - fb->reset_row( fb->get_mutable_row( y ) ); - } - break; - default: break; + case 0: /* active position to end of screen, inclusive */ + clearline( fb, -1, fb->ds.get_cursor_col(), fb->ds.get_width() - 1 ); + for ( int y = fb->ds.get_cursor_row() + 1; y < fb->ds.get_height(); y++ ) { + fb->reset_row( fb->get_mutable_row( y ) ); + } + break; + case 1: /* start of screen to active position, inclusive */ + for ( int y = 0; y < fb->ds.get_cursor_row(); y++ ) { + fb->reset_row( fb->get_mutable_row( y ) ); + } + clearline( fb, -1, 0, fb->ds.get_cursor_col() ); + break; + case 2: /* entire screen */ + for ( int y = 0; y < fb->ds.get_height(); y++ ) { + fb->reset_row( fb->get_mutable_row( y ) ); + } + break; + default: + break; } } static Function func_CSI_ED( CSI, "J", CSI_ED ); /* cursor movement -- relative and absolute */ -static void CSI_cursormove( Framebuffer *fb, Dispatcher *dispatch ) { +static void CSI_cursormove( Framebuffer* fb, Dispatcher* dispatch ) +{ int num = dispatch->getparam( 0, 1 ); - switch ( dispatch->get_dispatch_chars()[ 0 ] ) { - case 'A': fb->ds.move_row( -num, true ); break; - case 'B': fb->ds.move_row( num, true ); break; - case 'C': fb->ds.move_col( num, true ); break; - case 'D': fb->ds.move_col( -num, true ); break; - case 'H': - case 'f': - fb->ds.move_row( dispatch->getparam( 0, 1 ) - 1 ); - fb->ds.move_col( dispatch->getparam( 1, 1 ) - 1 ); - break; - default: break; + switch ( dispatch->get_dispatch_chars()[0] ) { + case 'A': + fb->ds.move_row( -num, true ); + break; + case 'B': + fb->ds.move_row( num, true ); + break; + case 'C': + fb->ds.move_col( num, true ); + break; + case 'D': + fb->ds.move_col( -num, true ); + break; + case 'H': + case 'f': + fb->ds.move_row( dispatch->getparam( 0, 1 ) - 1 ); + fb->ds.move_col( dispatch->getparam( 1, 1 ) - 1 ); + break; + default: + break; } } @@ -117,24 +134,24 @@ static Function func_CSI_cursormove_H( CSI, "H", CSI_cursormove ); static Function func_CSI_cursormove_f( CSI, "f", CSI_cursormove ); /* device attributes */ -static void CSI_DA( Framebuffer *fb __attribute( ( unused ) ), - Dispatcher *dispatch ) { +static void CSI_DA( Framebuffer* fb __attribute( ( unused ) ), Dispatcher* dispatch ) +{ dispatch->terminal_to_host.append( "\033[?62c" ); /* plain vt220 */ } static Function func_CSI_DA( CSI, "c", CSI_DA ); /* secondary device attributes */ -static void CSI_SDA( Framebuffer *fb __attribute( ( unused ) ), - Dispatcher *dispatch ) { +static void CSI_SDA( Framebuffer* fb __attribute( ( unused ) ), Dispatcher* dispatch ) +{ dispatch->terminal_to_host.append( "\033[>1;10;0c" ); /* plain vt220 */ } static Function func_CSI_SDA( CSI, ">c", CSI_SDA ); /* screen alignment diagnostic */ -static void Esc_DECALN( Framebuffer *fb, - Dispatcher *dispatch __attribute( ( unused ) ) ) { +static void Esc_DECALN( Framebuffer* fb, Dispatcher* dispatch __attribute( ( unused ) ) ) +{ for ( int y = 0; y < fb->ds.get_height(); y++ ) { for ( int x = 0; x < fb->ds.get_width(); x++ ) { fb->reset_cell( fb->get_mutable_cell( y, x ) ); @@ -146,8 +163,8 @@ static void Esc_DECALN( Framebuffer *fb, static Function func_Esc_DECALN( ESCAPE, "#8", Esc_DECALN ); /* line feed */ -static void Ctrl_LF( Framebuffer *fb, - Dispatcher *dispatch __attribute( ( unused ) ) ) { +static void Ctrl_LF( Framebuffer* fb, Dispatcher* dispatch __attribute( ( unused ) ) ) +{ fb->move_rows_autoscroll( 1 ); } @@ -158,32 +175,32 @@ static Function func_Ctrl_VT( CONTROL, "\x0b", Ctrl_LF ); static Function func_Ctrl_FF( CONTROL, "\x0c", Ctrl_LF ); /* carriage return */ -static void Ctrl_CR( Framebuffer *fb, - Dispatcher *dispatch __attribute( ( unused ) ) ) { +static void Ctrl_CR( Framebuffer* fb, Dispatcher* dispatch __attribute( ( unused ) ) ) +{ fb->ds.move_col( 0 ); } static Function func_Ctrl_CR( CONTROL, "\x0d", Ctrl_CR ); /* backspace */ -static void Ctrl_BS( Framebuffer *fb, - Dispatcher *dispatch __attribute( ( unused ) ) ) { +static void Ctrl_BS( Framebuffer* fb, Dispatcher* dispatch __attribute( ( unused ) ) ) +{ fb->ds.move_col( -1, true ); } static Function func_Ctrl_BS( CONTROL, "\x08", Ctrl_BS ); /* reverse index -- like a backwards line feed */ -static void Ctrl_RI( Framebuffer *fb, - Dispatcher *dispatch __attribute( ( unused ) ) ) { +static void Ctrl_RI( Framebuffer* fb, Dispatcher* dispatch __attribute( ( unused ) ) ) +{ fb->move_rows_autoscroll( -1 ); } static Function func_Ctrl_RI( CONTROL, "\x8D", Ctrl_RI ); /* newline */ -static void Ctrl_NEL( Framebuffer *fb, - Dispatcher *dispatch __attribute( ( unused ) ) ) { +static void Ctrl_NEL( Framebuffer* fb, Dispatcher* dispatch __attribute( ( unused ) ) ) +{ fb->ds.move_col( 0 ); fb->move_rows_autoscroll( 1 ); } @@ -191,7 +208,8 @@ static void Ctrl_NEL( Framebuffer *fb, static Function func_Ctrl_NEL( CONTROL, "\x85", Ctrl_NEL ); /* horizontal tab */ -static void HT_n( Framebuffer *fb, size_t count ) { +static void HT_n( Framebuffer* fb, size_t count ) +{ int col = fb->ds.get_next_tab( count ); if ( col == -1 ) { /* no tabs, go to end of line */ col = fb->ds.get_width() - 1; @@ -205,15 +223,16 @@ static void HT_n( Framebuffer *fb, size_t count ) { fb->ds.next_print_will_wrap = wrap_state_save; } -static void Ctrl_HT( Framebuffer *fb, - Dispatcher *dispatch __attribute( ( unused ) ) ) { +static void Ctrl_HT( Framebuffer* fb, Dispatcher* dispatch __attribute( ( unused ) ) ) +{ HT_n( fb, 1 ); } static Function func_Ctrl_HT( CONTROL, "\x09", Ctrl_HT, false ); -static void CSI_CxT( Framebuffer *fb, Dispatcher *dispatch ) { +static void CSI_CxT( Framebuffer* fb, Dispatcher* dispatch ) +{ int param = dispatch->getparam( 0, 1 ); - if ( dispatch->get_dispatch_chars()[ 0 ] == 'Z' ) { + if ( dispatch->get_dispatch_chars()[0] == 'Z' ) { param = -param; } if ( param == 0 ) { @@ -226,77 +245,87 @@ static Function func_CSI_CHT( CSI, "I", CSI_CxT, false ); static Function func_CSI_CBT( CSI, "Z", CSI_CxT, false ); /* horizontal tab set */ -static void Ctrl_HTS( Framebuffer *fb, - Dispatcher *dispatch __attribute( ( unused ) ) ) { +static void Ctrl_HTS( Framebuffer* fb, Dispatcher* dispatch __attribute( ( unused ) ) ) +{ fb->ds.set_tab(); } static Function func_Ctrl_HTS( CONTROL, "\x88", Ctrl_HTS ); /* tabulation clear */ -static void CSI_TBC( Framebuffer *fb, Dispatcher *dispatch ) { +static void CSI_TBC( Framebuffer* fb, Dispatcher* dispatch ) +{ int param = dispatch->getparam( 0, 0 ); switch ( param ) { - case 0: /* clear this tab stop */ - fb->ds.clear_tab( fb->ds.get_cursor_col() ); - break; - case 3: /* clear all tab stops */ - fb->ds.clear_default_tabs(); - for ( int x = 0; x < fb->ds.get_width(); x++ ) { - fb->ds.clear_tab( x ); - } - break; - default: break; + case 0: /* clear this tab stop */ + fb->ds.clear_tab( fb->ds.get_cursor_col() ); + break; + case 3: /* clear all tab stops */ + fb->ds.clear_default_tabs(); + for ( int x = 0; x < fb->ds.get_width(); x++ ) { + fb->ds.clear_tab( x ); + } + break; + default: + break; } } /* TBC preserves wrap state */ static Function func_CSI_TBC( CSI, "g", CSI_TBC, false ); -static bool *get_DEC_mode( int param, Framebuffer *fb ) { +static bool* get_DEC_mode( int param, Framebuffer* fb ) +{ switch ( param ) { - case 1: /* cursor key mode */ return &( fb->ds.application_mode_cursor_keys ); - case 3: /* 80/132. Ignore but clear screen. */ - /* clear screen */ - fb->ds.move_row( 0 ); - fb->ds.move_col( 0 ); - for ( int y = 0; y < fb->ds.get_height(); y++ ) { - fb->reset_row( fb->get_mutable_row( y ) ); - } - return NULL; - case 5: /* reverse video */ return &( fb->ds.reverse_video ); - case 6: /* origin */ - fb->ds.move_row( 0 ); - fb->ds.move_col( 0 ); - return &( fb->ds.origin_mode ); - case 7: /* auto wrap */ return &( fb->ds.auto_wrap_mode ); - case 25: return &( fb->ds.cursor_visible ); - case 1004: /* xterm mouse focus event */ return &( fb->ds.mouse_focus_event ); - case 1007: /* xterm mouse alternate scroll */ - return &( fb->ds.mouse_alternate_scroll ); - case 2004: /* bracketed paste */ return &( fb->ds.bracketed_paste ); - default: break; + case 1: /* cursor key mode */ + return &( fb->ds.application_mode_cursor_keys ); + case 3: /* 80/132. Ignore but clear screen. */ + /* clear screen */ + fb->ds.move_row( 0 ); + fb->ds.move_col( 0 ); + for ( int y = 0; y < fb->ds.get_height(); y++ ) { + fb->reset_row( fb->get_mutable_row( y ) ); + } + return NULL; + case 5: /* reverse video */ + return &( fb->ds.reverse_video ); + case 6: /* origin */ + fb->ds.move_row( 0 ); + fb->ds.move_col( 0 ); + return &( fb->ds.origin_mode ); + case 7: /* auto wrap */ + return &( fb->ds.auto_wrap_mode ); + case 25: + return &( fb->ds.cursor_visible ); + case 1004: /* xterm mouse focus event */ + return &( fb->ds.mouse_focus_event ); + case 1007: /* xterm mouse alternate scroll */ + return &( fb->ds.mouse_alternate_scroll ); + case 2004: /* bracketed paste */ + return &( fb->ds.bracketed_paste ); + default: + break; } return NULL; } /* helper for CSI_DECSM and CSI_DECRM */ -static void set_if_available( bool *mode, bool value ) { +static void set_if_available( bool* mode, bool value ) +{ if ( mode ) { *mode = value; } } /* set private mode */ -static void CSI_DECSM( Framebuffer *fb, Dispatcher *dispatch ) { +static void CSI_DECSM( Framebuffer* fb, Dispatcher* dispatch ) +{ for ( int i = 0; i < dispatch->param_count(); i++ ) { int param = dispatch->getparam( i, 0 ); if ( param == 9 || ( param >= 1000 && param <= 1003 ) ) { - fb->ds.mouse_reporting_mode = - (Terminal::DrawState::MouseReportingMode)param; + fb->ds.mouse_reporting_mode = (Terminal::DrawState::MouseReportingMode)param; } else if ( param == 1005 || param == 1006 || param == 1015 ) { - fb->ds.mouse_encoding_mode = - (Terminal::DrawState::MouseEncodingMode)param; + fb->ds.mouse_encoding_mode = (Terminal::DrawState::MouseEncodingMode)param; } else { set_if_available( get_DEC_mode( param, fb ), true ); } @@ -304,7 +333,8 @@ static void CSI_DECSM( Framebuffer *fb, Dispatcher *dispatch ) { } /* clear private mode */ -static void CSI_DECRM( Framebuffer *fb, Dispatcher *dispatch ) { +static void CSI_DECRM( Framebuffer* fb, Dispatcher* dispatch ) +{ for ( int i = 0; i < dispatch->param_count(); i++ ) { int param = dispatch->getparam( i, 0 ); if ( param == 9 || ( param >= 1000 && param <= 1003 ) ) { @@ -321,7 +351,8 @@ static void CSI_DECRM( Framebuffer *fb, Dispatcher *dispatch ) { static Function func_CSI_DECSM( CSI, "?h", CSI_DECSM, false ); static Function func_CSI_DECRM( CSI, "?l", CSI_DECRM, false ); -static bool *get_ANSI_mode( int param, Framebuffer *fb ) { +static bool* get_ANSI_mode( int param, Framebuffer* fb ) +{ if ( param == 4 ) { /* insert/replace mode */ return &( fb->ds.insert_mode ); } @@ -329,9 +360,10 @@ static bool *get_ANSI_mode( int param, Framebuffer *fb ) { } /* set mode */ -static void CSI_SM( Framebuffer *fb, Dispatcher *dispatch ) { +static void CSI_SM( Framebuffer* fb, Dispatcher* dispatch ) +{ for ( int i = 0; i < dispatch->param_count(); i++ ) { - bool *mode = get_ANSI_mode( dispatch->getparam( i, 0 ), fb ); + bool* mode = get_ANSI_mode( dispatch->getparam( i, 0 ), fb ); if ( mode ) { *mode = true; } @@ -339,9 +371,10 @@ static void CSI_SM( Framebuffer *fb, Dispatcher *dispatch ) { } /* clear mode */ -static void CSI_RM( Framebuffer *fb, Dispatcher *dispatch ) { +static void CSI_RM( Framebuffer* fb, Dispatcher* dispatch ) +{ for ( int i = 0; i < dispatch->param_count(); i++ ) { - bool *mode = get_ANSI_mode( dispatch->getparam( i, 0 ), fb ); + bool* mode = get_ANSI_mode( dispatch->getparam( i, 0 ), fb ); if ( mode ) { *mode = false; } @@ -352,12 +385,12 @@ static Function func_CSI_SM( CSI, "h", CSI_SM ); static Function func_CSI_RM( CSI, "l", CSI_RM ); /* set top and bottom margins */ -static void CSI_DECSTBM( Framebuffer *fb, Dispatcher *dispatch ) { +static void CSI_DECSTBM( Framebuffer* fb, Dispatcher* dispatch ) +{ int top = dispatch->getparam( 0, 1 ); int bottom = dispatch->getparam( 1, fb->ds.get_height() ); - if ( ( bottom <= top ) || ( top > fb->ds.get_height() ) - || ( top == 0 && bottom == 1 ) ) { + if ( ( bottom <= top ) || ( top > fb->ds.get_height() ) || ( top == 0 && bottom == 1 ) ) { return; /* invalid, xterm ignores */ } @@ -369,34 +402,32 @@ static void CSI_DECSTBM( Framebuffer *fb, Dispatcher *dispatch ) { static Function func_CSI_DECSTMB( CSI, "r", CSI_DECSTBM ); /* terminal bell */ -static void Ctrl_BEL( Framebuffer *fb, - Dispatcher *dispatch __attribute( ( unused ) ) ) { +static void Ctrl_BEL( Framebuffer* fb, Dispatcher* dispatch __attribute( ( unused ) ) ) +{ fb->ring_bell(); } static Function func_Ctrl_BEL( CONTROL, "\x07", Ctrl_BEL ); /* select graphics rendition -- e.g., bold, blinking, etc. */ -static void CSI_SGR( Framebuffer *fb, Dispatcher *dispatch ) { +static void CSI_SGR( Framebuffer* fb, Dispatcher* dispatch ) +{ for ( int i = 0; i < dispatch->param_count(); i++ ) { int rendition = dispatch->getparam( i, 0 ); /* We need to special-case the handling of [34]8 ; 5 ; Ps, because Ps of 0 in that case does not mean reset to default, even though it means that otherwise (as usually renditions are applied in order). */ - if ( ( rendition == 38 || rendition == 48 ) - && ( dispatch->param_count() - i >= 3 ) + if ( ( rendition == 38 || rendition == 48 ) && ( dispatch->param_count() - i >= 3 ) && ( dispatch->getparam( i + 1, -1 ) == 5 ) ) { - ( rendition == 38 ) ? - fb->ds.set_foreground_color( dispatch->getparam( i + 2, 0 ) ) : - fb->ds.set_background_color( dispatch->getparam( i + 2, 0 ) ); + ( rendition == 38 ) ? fb->ds.set_foreground_color( dispatch->getparam( i + 2, 0 ) ) + : fb->ds.set_background_color( dispatch->getparam( i + 2, 0 ) ); i += 2; continue; } /* True color support: ESC[ ... [34]8;2;;; ... m */ - if ( ( rendition == 38 || rendition == 48 ) - && ( dispatch->param_count() - i >= 5 ) + if ( ( rendition == 38 || rendition == 48 ) && ( dispatch->param_count() - i >= 5 ) && ( dispatch->getparam( i + 1, -1 ) == 2 ) ) { unsigned int red = dispatch->getparam( i + 2, 0 ); unsigned int green = dispatch->getparam( i + 3, 0 ); @@ -418,18 +449,16 @@ static void CSI_SGR( Framebuffer *fb, Dispatcher *dispatch ) { } } -static Function func_CSI_SGR( - CSI, "m", CSI_SGR, - false ); /* changing renditions doesn't clear wrap flag */ +static Function func_CSI_SGR( CSI, "m", CSI_SGR, false ); /* changing renditions doesn't clear wrap flag */ /* save and restore cursor */ -static void Esc_DECSC( Framebuffer *fb, - Dispatcher *dispatch __attribute( ( unused ) ) ) { +static void Esc_DECSC( Framebuffer* fb, Dispatcher* dispatch __attribute( ( unused ) ) ) +{ fb->ds.save_cursor(); } -static void Esc_DECRC( Framebuffer *fb, - Dispatcher *dispatch __attribute( ( unused ) ) ) { +static void Esc_DECRC( Framebuffer* fb, Dispatcher* dispatch __attribute( ( unused ) ) ) +{ fb->ds.restore_cursor(); } @@ -437,27 +466,29 @@ static Function func_Esc_DECSC( ESCAPE, "7", Esc_DECSC ); static Function func_Esc_DECRC( ESCAPE, "8", Esc_DECRC ); /* device status report -- e.g., cursor position (used by resize) */ -static void CSI_DSR( Framebuffer *fb, Dispatcher *dispatch ) { +static void CSI_DSR( Framebuffer* fb, Dispatcher* dispatch ) +{ int param = dispatch->getparam( 0, 0 ); switch ( param ) { - case 5: /* device status report requested */ - dispatch->terminal_to_host.append( "\033[0n" ); - break; - case 6: /* report of active position requested */ - char cpr[ 32 ]; - snprintf( cpr, 32, "\033[%d;%dR", fb->ds.get_cursor_row() + 1, - fb->ds.get_cursor_col() + 1 ); - dispatch->terminal_to_host.append( cpr ); - break; - default: break; + case 5: /* device status report requested */ + dispatch->terminal_to_host.append( "\033[0n" ); + break; + case 6: /* report of active position requested */ + char cpr[32]; + snprintf( cpr, 32, "\033[%d;%dR", fb->ds.get_cursor_row() + 1, fb->ds.get_cursor_col() + 1 ); + dispatch->terminal_to_host.append( cpr ); + break; + default: + break; } } static Function func_CSI_DSR( CSI, "n", CSI_DSR ); /* insert line */ -static void CSI_IL( Framebuffer *fb, Dispatcher *dispatch ) { +static void CSI_IL( Framebuffer* fb, Dispatcher* dispatch ) +{ int lines = dispatch->getparam( 0, 1 ); fb->insert_line( fb->ds.get_cursor_row(), lines ); @@ -470,7 +501,8 @@ static void CSI_IL( Framebuffer *fb, Dispatcher *dispatch ) { static Function func_CSI_IL( CSI, "L", CSI_IL ); /* delete line */ -static void CSI_DL( Framebuffer *fb, Dispatcher *dispatch ) { +static void CSI_DL( Framebuffer* fb, Dispatcher* dispatch ) +{ int lines = dispatch->getparam( 0, 1 ); fb->delete_line( fb->ds.get_cursor_row(), lines ); @@ -483,7 +515,8 @@ static void CSI_DL( Framebuffer *fb, Dispatcher *dispatch ) { static Function func_CSI_DL( CSI, "M", CSI_DL ); /* insert characters */ -static void CSI_ICH( Framebuffer *fb, Dispatcher *dispatch ) { +static void CSI_ICH( Framebuffer* fb, Dispatcher* dispatch ) +{ int cells = dispatch->getparam( 0, 1 ); for ( int i = 0; i < cells; i++ ) { @@ -494,7 +527,8 @@ static void CSI_ICH( Framebuffer *fb, Dispatcher *dispatch ) { static Function func_CSI_ICH( CSI, "@", CSI_ICH ); /* delete character */ -static void CSI_DCH( Framebuffer *fb, Dispatcher *dispatch ) { +static void CSI_DCH( Framebuffer* fb, Dispatcher* dispatch ) +{ int cells = dispatch->getparam( 0, 1 ); for ( int i = 0; i < cells; i++ ) { @@ -505,7 +539,8 @@ static void CSI_DCH( Framebuffer *fb, Dispatcher *dispatch ) { static Function func_CSI_DCH( CSI, "P", CSI_DCH ); /* line position absolute */ -static void CSI_VPA( Framebuffer *fb, Dispatcher *dispatch ) { +static void CSI_VPA( Framebuffer* fb, Dispatcher* dispatch ) +{ int row = dispatch->getparam( 0, 1 ); fb->ds.move_row( row - 1 ); } @@ -513,16 +548,18 @@ static void CSI_VPA( Framebuffer *fb, Dispatcher *dispatch ) { static Function func_CSI_VPA( CSI, "d", CSI_VPA ); /* character position absolute */ -static void CSI_HPA( Framebuffer *fb, Dispatcher *dispatch ) { +static void CSI_HPA( Framebuffer* fb, Dispatcher* dispatch ) +{ int col = dispatch->getparam( 0, 1 ); fb->ds.move_col( col - 1 ); } -static Function func_CSI_CHA( CSI, "G", CSI_HPA ); /* ECMA-48 name: CHA */ +static Function func_CSI_CHA( CSI, "G", CSI_HPA ); /* ECMA-48 name: CHA */ static Function func_CSI_HPA( CSI, "\x60", CSI_HPA ); /* ECMA-48 name: HPA */ /* erase character */ -static void CSI_ECH( Framebuffer *fb, Dispatcher *dispatch ) { +static void CSI_ECH( Framebuffer* fb, Dispatcher* dispatch ) +{ int num = dispatch->getparam( 0, 1 ); int limit = fb->ds.get_cursor_col() + num - 1; if ( limit >= fb->ds.get_width() ) { @@ -535,46 +572,43 @@ static void CSI_ECH( Framebuffer *fb, Dispatcher *dispatch ) { static Function func_CSI_ECH( CSI, "X", CSI_ECH ); /* reset to initial state */ -static void Esc_RIS( Framebuffer *fb, - Dispatcher *dispatch __attribute( ( unused ) ) ) { +static void Esc_RIS( Framebuffer* fb, Dispatcher* dispatch __attribute( ( unused ) ) ) +{ fb->reset(); } static Function func_Esc_RIS( ESCAPE, "c", Esc_RIS ); /* soft reset */ -static void CSI_DECSTR( Framebuffer *fb, - Dispatcher *dispatch __attribute( ( unused ) ) ) { +static void CSI_DECSTR( Framebuffer* fb, Dispatcher* dispatch __attribute( ( unused ) ) ) +{ fb->soft_reset(); } static Function func_CSI_DECSTR( CSI, "!p", CSI_DECSTR ); /* xterm uses an Operating System Command to set the window title */ -void Dispatcher::OSC_dispatch( const Parser::OSC_End *act - __attribute( ( unused ) ), - Framebuffer *fb ) { +void Dispatcher::OSC_dispatch( const Parser::OSC_End* act __attribute( ( unused ) ), Framebuffer* fb ) +{ /* handle osc copy clipboard sequence 52;c; */ - if ( OSC_string.size() >= 5 && OSC_string[ 0 ] == L'5' - && OSC_string[ 1 ] == L'2' && OSC_string[ 2 ] == L';' - && OSC_string[ 3 ] == L'c' && OSC_string[ 4 ] == L';' ) { - Terminal::Framebuffer::title_type clipboard( OSC_string.begin() + 5, - OSC_string.end() ); + if ( OSC_string.size() >= 5 && OSC_string[0] == L'5' && OSC_string[1] == L'2' && OSC_string[2] == L';' + && OSC_string[3] == L'c' && OSC_string[4] == L';' ) { + Terminal::Framebuffer::title_type clipboard( OSC_string.begin() + 5, OSC_string.end() ); fb->set_clipboard( clipboard ); /* handle osc terminal title sequence */ } else if ( OSC_string.size() >= 1 ) { long cmd_num = -1; int offset = 0; - if ( OSC_string[ 0 ] == L';' ) { + if ( OSC_string[0] == L';' ) { /* OSC of the form "\033];\007" */ cmd_num = 0; /* treat it as as a zero */ offset = 1; - } else if ( ( OSC_string.size() >= 2 ) && ( OSC_string[ 1 ] == L';' ) ) { + } else if ( ( OSC_string.size() >= 2 ) && ( OSC_string[1] == L';' ) ) { /* OSC of the form "\033]X;<title>\007" where X can be: * 0: set icon name and window title * 1: set icon name * 2: set window title */ - cmd_num = OSC_string[ 0 ] - L'0'; + cmd_num = OSC_string[0] - L'0'; offset = 2; } bool set_icon = cmd_num == 0 || cmd_num == 1; @@ -582,8 +616,7 @@ void Dispatcher::OSC_dispatch( const Parser::OSC_End *act if ( set_icon || set_title ) { fb->set_title_initialized(); int title_length = std::min( OSC_string.size(), (size_t)256 ); - Terminal::Framebuffer::title_type newtitle( - OSC_string.begin() + offset, OSC_string.begin() + title_length ); + Terminal::Framebuffer::title_type newtitle( OSC_string.begin() + offset, OSC_string.begin() + title_length ); if ( set_icon ) { fb->set_icon_name( newtitle ); } @@ -595,14 +628,16 @@ void Dispatcher::OSC_dispatch( const Parser::OSC_End *act } /* scroll down or terminfo indn */ -static void CSI_SD( Framebuffer *fb, Dispatcher *dispatch ) { +static void CSI_SD( Framebuffer* fb, Dispatcher* dispatch ) +{ fb->scroll( dispatch->getparam( 0, 1 ) ); } static Function func_CSI_SD( CSI, "S", CSI_SD ); /* scroll up or terminfo rin */ -static void CSI_SU( Framebuffer *fb, Dispatcher *dispatch ) { +static void CSI_SU( Framebuffer* fb, Dispatcher* dispatch ) +{ fb->scroll( -dispatch->getparam( 0, 1 ) ); } diff --git a/src/terminal/terminaluserinput.cc b/src/terminal/terminaluserinput.cc index 545373c6d..4553c730f 100644 --- a/src/terminal/terminaluserinput.cc +++ b/src/terminal/terminaluserinput.cc @@ -36,8 +36,8 @@ using namespace Terminal; using std::string; -string UserInput::input( const Parser::UserByte *act, - bool application_mode_cursor_keys ) { +string UserInput::input( const Parser::UserByte* act, bool application_mode_cursor_keys ) +{ /* The user will always be in application mode. If stm is not in application mode, convert user's cursor control function to an ANSI cursor control sequence */ @@ -49,34 +49,33 @@ string UserInput::input( const Parser::UserByte *act, two octets in UTF-8. Fortunately nobody seems to send this. */ switch ( state ) { - case Ground: - if ( act->c == 0x1b ) { /* ESC */ - state = ESC; - } - return string( &act->c, 1 ); + case Ground: + if ( act->c == 0x1b ) { /* ESC */ + state = ESC; + } + return string( &act->c, 1 ); - case ESC: - if ( act->c == 'O' ) { /* ESC O = 7-bit SS3 */ - state = SS3; - return string(); - } - state = Ground; - return string( &act->c, 1 ); + case ESC: + if ( act->c == 'O' ) { /* ESC O = 7-bit SS3 */ + state = SS3; + return string(); + } + state = Ground; + return string( &act->c, 1 ); - case SS3: - state = Ground; - if ( ( !application_mode_cursor_keys ) && ( act->c >= 'A' ) - && ( act->c <= 'D' ) ) { - char translated_cursor[ 2 ] = { '[', act->c }; - return string( translated_cursor, 2 ); - } else { - char original_cursor[ 2 ] = { 'O', act->c }; - return string( original_cursor, 2 ); - } + case SS3: + state = Ground; + if ( ( !application_mode_cursor_keys ) && ( act->c >= 'A' ) && ( act->c <= 'D' ) ) { + char translated_cursor[2] = { '[', act->c }; + return string( translated_cursor, 2 ); + } else { + char original_cursor[2] = { 'O', act->c }; + return string( original_cursor, 2 ); + } - default: - assert( !"unexpected state" ); - state = Ground; - return string(); + default: + assert( !"unexpected state" ); + state = Ground; + return string(); } } diff --git a/src/terminal/terminaluserinput.h b/src/terminal/terminaluserinput.h index eb05aff58..5ff9942c2 100644 --- a/src/terminal/terminaluserinput.h +++ b/src/terminal/terminaluserinput.h @@ -33,25 +33,32 @@ #ifndef TERMINALUSERINPUT_HPP #define TERMINALUSERINPUT_HPP -#include <string> #include "parseraction.h" +#include <string> namespace Terminal { - class UserInput { - public: - enum UserInputState { Ground, ESC, SS3 }; +class UserInput +{ +public: + enum UserInputState + { + Ground, + ESC, + SS3 + }; - private: - UserInputState state; +private: + UserInputState state; - public: - UserInput() : state( Ground ) {} +public: + UserInput() + : state( Ground ) + {} - std::string input( const Parser::UserByte *act, - bool application_mode_cursor_keys ); + std::string input( const Parser::UserByte* act, bool application_mode_cursor_keys ); - bool operator==( const UserInput &x ) const { return state == x.state; } - }; + bool operator==( const UserInput& x ) const { return state == x.state; } +}; } #endif diff --git a/src/tests/base64.cc b/src/tests/base64.cc index 5ef4c2409..ba7b532db 100644 --- a/src/tests/base64.cc +++ b/src/tests/base64.cc @@ -48,25 +48,24 @@ #include "prng.h" // #include "test_utils.h" -#define KEY_LEN 16 +#define KEY_LEN 16 #define NONCE_LEN 12 -#define TAG_LEN 16 +#define TAG_LEN 16 bool verbose = false; -static void test_base64( void ) { +static void test_base64( void ) +{ /* run through a test vector */ - char encoded[ 25 ]; - uint8_t decoded[ 16 ]; + char encoded[25]; + uint8_t decoded[16]; size_t b64_len = 24; size_t raw_len = 16; - for ( base64_test_row *row = static_base64_vector; *row->native != '\0'; - row++ ) { + for ( base64_test_row* row = static_base64_vector; *row->native != '\0'; row++ ) { memset( encoded, '\0', sizeof encoded ); memset( decoded, '\0', sizeof decoded ); - base64_encode( static_cast<const uint8_t *>( row->native ), raw_len, - encoded, b64_len ); + base64_encode( static_cast<const uint8_t*>( row->native ), raw_len, encoded, b64_len ); fatal_assert( b64_len == 24 ); fatal_assert( !memcmp( row->encoded, encoded, sizeof encoded ) ); @@ -77,12 +76,11 @@ static void test_base64( void ) { if ( verbose ) { printf( "validation PASSED\n" ); } - /* try 0..255 in the last byte; make sure the final two characters are output - * properly */ - uint8_t source[ 16 ]; + /* try 0..255 in the last byte; make sure the final two characters are output properly */ + uint8_t source[16]; memset( source, '\0', sizeof source ); for ( int i = 0; i < 256; i++ ) { - source[ 15 ] = i; + source[15] = i; base64_encode( source, raw_len, encoded, b64_len ); fatal_assert( b64_len == 24 ); @@ -99,15 +97,14 @@ static void test_base64( void ) { for ( int i = 0; i < ( 1 << 17 ); i++ ) { Base64Key key1( prng ); Base64Key key2( key1.printable_key() ); - fatal_assert( key1.printable_key() == key2.printable_key() - && !memcmp( key1.data(), key2.data(), 16 ) ); + fatal_assert( key1.printable_key() == key2.printable_key() && !memcmp( key1.data(), key2.data(), 16 ) ); } if ( verbose ) { printf( "random PASSED\n" ); } /* test bad keys */ - const char *bad_keys[] = { + const char* bad_keys[] = { "", "AAAAAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAAAAA=", @@ -123,7 +120,7 @@ static void test_base64( void ) { "AAAAAAAAAA==", NULL, }; - for ( const char **key = bad_keys; *key != NULL; key++ ) { + for ( const char** key = bad_keys; *key != NULL; key++ ) { b64_len = 24; raw_len = 16; fatal_assert( !base64_decode( *key, b64_len, decoded, &raw_len ) ); @@ -133,14 +130,15 @@ static void test_base64( void ) { } } -int main( int argc, char *argv[] ) { - if ( argc >= 2 && strcmp( argv[ 1 ], "-v" ) == 0 ) { +int main( int argc, char* argv[] ) +{ + if ( argc >= 2 && strcmp( argv[1], "-v" ) == 0 ) { verbose = true; } try { test_base64(); - } catch ( const std::exception &e ) { + } catch ( const std::exception& e ) { fprintf( stderr, "Error: %s\r\n", e.what() ); return 1; } diff --git a/src/tests/base64_vector.h b/src/tests/base64_vector.h index 3822045fa..44afd250d 100644 --- a/src/tests/base64_vector.h +++ b/src/tests/base64_vector.h @@ -1,6 +1,7 @@ -struct base64_test_row { - const unsigned char native[ 17 ]; - const char encoded[ 25 ]; +struct base64_test_row +{ + const unsigned char native[17]; + const char encoded[25]; }; -typedef base64_test_row *base64_test_vector; +typedef base64_test_row* base64_test_vector; extern base64_test_row static_base64_vector[]; diff --git a/src/tests/encrypt-decrypt.cc b/src/tests/encrypt-decrypt.cc index 8a2a8756d..ce71b4a9b 100644 --- a/src/tests/encrypt-decrypt.cc +++ b/src/tests/encrypt-decrypt.cc @@ -56,22 +56,24 @@ bool verbose = false; #define NONCE_FMT "%016" PRIx64 -static std::string random_payload( void ) { +static std::string random_payload( void ) +{ const size_t len = prng.uint32() % MESSAGE_SIZE_MAX; - char buf[ MESSAGE_SIZE_MAX ]; + char buf[MESSAGE_SIZE_MAX]; prng.fill( buf, len ); std::string payload( buf, len ); return payload; } -static void test_bad_decrypt( Session &decryption_session ) { +static void test_bad_decrypt( Session& decryption_session ) +{ std::string bad_ct = random_payload(); bool got_exn = false; try { decryption_session.decrypt( bad_ct ); - } catch ( const CryptoException &e ) { + } catch ( const CryptoException& e ) { got_exn = true; /* The "bad decrypt" exception needs to be non-fatal, otherwise we are @@ -86,7 +88,8 @@ static void test_bad_decrypt( Session &decryption_session ) { } /* Generate a single key and initial nonce, then perform some encryptions. */ -static void test_one_session( void ) { +static void test_one_session( void ) +{ Base64Key key; Session encryption_session( key ); Session decryption_session( key ); @@ -107,16 +110,14 @@ static void test_one_session( void ) { hexdump( plaintext, "pt" ); } - std::string ciphertext = - encryption_session.encrypt( Message( nonce, plaintext ) ); + std::string ciphertext = encryption_session.encrypt( Message( nonce, plaintext ) ); if ( verbose ) { hexdump( ciphertext, "ct" ); } Message decrypted = decryption_session.decrypt( ciphertext ); if ( verbose ) { - printf( DUMP_NAME_FMT NONCE_FMT "\n", "dec nonce", - decrypted.nonce.val() ); + printf( DUMP_NAME_FMT NONCE_FMT "\n", "dec nonce", decrypted.nonce.val() ); hexdump( decrypted.text, "dec pt" ); } @@ -135,15 +136,16 @@ static void test_one_session( void ) { } } -int main( int argc, char *argv[] ) { - if ( argc >= 2 && strcmp( argv[ 1 ], "-v" ) == 0 ) { +int main( int argc, char* argv[] ) +{ + if ( argc >= 2 && strcmp( argv[1], "-v" ) == 0 ) { verbose = true; } for ( size_t i = 0; i < NUM_SESSIONS; i++ ) { try { test_one_session(); - } catch ( const CryptoException &e ) { + } catch ( const CryptoException& e ) { fprintf( stderr, "Crypto exception: %s\r\n", e.what() ); return 1; } diff --git a/src/tests/inpty.cc b/src/tests/inpty.cc index 57928d964..1c480d9fa 100644 --- a/src/tests/inpty.cc +++ b/src/tests/inpty.cc @@ -55,7 +55,8 @@ #include "pty_compat.h" #include "swrite.h" -int main( int argc, char *argv[] ) { +int main( int argc, char* argv[] ) +{ if ( argc < 2 ) { fprintf( stderr, "usage: inpty COMMAND [ARGS...]\n" ); return 1; @@ -91,7 +92,7 @@ int main( int argc, char *argv[] ) { perror( "close" ); exit( 1 ); } - if ( execvp( argv[ 1 ], argv + 1 ) < 0 ) { + if ( execvp( argv[1], argv + 1 ) < 0 ) { perror( "execve" ); exit( 1 ); } @@ -99,7 +100,7 @@ int main( int argc, char *argv[] ) { } while ( 1 ) { - char buf[ 1024 ]; + char buf[1024]; ssize_t bytes_read = read( master, buf, sizeof( buf ) ); if ( bytes_read == 0 || ( bytes_read < 0 && errno == EIO ) ) { /* EOF */ break; @@ -117,8 +118,7 @@ int main( int argc, char *argv[] ) { } if ( WIFSIGNALED( wstatus ) ) { - fprintf( stderr, "inpty: child exited with signal %d\n", - WTERMSIG( wstatus ) ); + fprintf( stderr, "inpty: child exited with signal %d\n", WTERMSIG( wstatus ) ); raise( WTERMSIG( wstatus ) ); return -1; } else { diff --git a/src/tests/is-utf8-locale.cc b/src/tests/is-utf8-locale.cc index 57b0122ee..bfc112aca 100644 --- a/src/tests/is-utf8-locale.cc +++ b/src/tests/is-utf8-locale.cc @@ -34,8 +34,8 @@ #include "locale_utils.h" -int main( int argc __attribute__( ( unused ) ), - char **argv __attribute__( ( unused ) ) ) { +int main( int argc __attribute__( ( unused ) ), char** argv __attribute__( ( unused ) ) ) +{ set_native_locale(); if ( !is_utf8_locale() ) { fprintf( stderr, "not a UTF-8 locale\n" ); diff --git a/src/tests/nonce-incr.cc b/src/tests/nonce-incr.cc index 47902354d..fc39f5738 100644 --- a/src/tests/nonce-incr.cc +++ b/src/tests/nonce-incr.cc @@ -38,7 +38,8 @@ #include "network.h" -int main() { +int main() +{ std::set<uint64_t> nonces; const unsigned int NUM_EXAMPLES = 1000000; diff --git a/src/tests/ocb-aes.cc b/src/tests/ocb-aes.cc index aa60249b1..d40a758e1 100644 --- a/src/tests/ocb-aes.cc +++ b/src/tests/ocb-aes.cc @@ -48,45 +48,54 @@ #include "shared.h" #include "test_utils.h" -#define KEY_LEN 16 +#define KEY_LEN 16 #define NONCE_LEN 12 -#define TAG_LEN 16 +#define TAG_LEN 16 using Crypto::AlignedBuffer; bool verbose = false; -static bool equal( const AlignedBuffer &a, const AlignedBuffer &b ) { +static bool equal( const AlignedBuffer& a, const AlignedBuffer& b ) +{ return ( a.len() == b.len() ) && !memcmp( a.data(), b.data(), a.len() ); } typedef shared::shared_ptr<AlignedBuffer> AlignedPointer; -static AlignedBuffer *get_ctx( const AlignedBuffer &key ) { - AlignedBuffer *ctx_buf = new AlignedBuffer( ae_ctx_sizeof() ); +static AlignedBuffer* get_ctx( const AlignedBuffer& key ) +{ + AlignedBuffer* ctx_buf = new AlignedBuffer( ae_ctx_sizeof() ); fatal_assert( ctx_buf ); - fatal_assert( AE_SUCCESS - == ae_init( (ae_ctx *)ctx_buf->data(), key.data(), key.len(), - NONCE_LEN, TAG_LEN ) ); + fatal_assert( AE_SUCCESS == ae_init( (ae_ctx*)ctx_buf->data(), key.data(), key.len(), NONCE_LEN, TAG_LEN ) ); return ctx_buf; } -static void scrap_ctx( AlignedBuffer &ctx_buf ) { - fatal_assert( AE_SUCCESS == ae_clear( (ae_ctx *)ctx_buf.data() ) ); +static void scrap_ctx( AlignedBuffer& ctx_buf ) +{ + fatal_assert( AE_SUCCESS == ae_clear( (ae_ctx*)ctx_buf.data() ) ); } -static void test_encrypt( const AlignedBuffer &key, const AlignedBuffer &nonce, - const AlignedBuffer &plaintext, - const AlignedBuffer &assoc, - const AlignedBuffer &expected_ciphertext ) { +static void test_encrypt( const AlignedBuffer& key, + const AlignedBuffer& nonce, + const AlignedBuffer& plaintext, + const AlignedBuffer& assoc, + const AlignedBuffer& expected_ciphertext ) +{ AlignedPointer ctx_buf( get_ctx( key ) ); - ae_ctx *ctx = (ae_ctx *)ctx_buf->data(); + ae_ctx* ctx = (ae_ctx*)ctx_buf->data(); AlignedBuffer observed_ciphertext( plaintext.len() + TAG_LEN ); - const int ret = ae_encrypt( ctx, nonce.data(), plaintext.data(), - plaintext.len(), assoc.data(), assoc.len(), - observed_ciphertext.data(), NULL, AE_FINALIZE ); + const int ret = ae_encrypt( ctx, + nonce.data(), + plaintext.data(), + plaintext.len(), + assoc.data(), + assoc.len(), + observed_ciphertext.data(), + NULL, + AE_FINALIZE ); if ( verbose ) { printf( "ret %d\n", ret ); @@ -99,19 +108,27 @@ static void test_encrypt( const AlignedBuffer &key, const AlignedBuffer &nonce, scrap_ctx( *ctx_buf ); } -static void test_decrypt( const AlignedBuffer &key, const AlignedBuffer &nonce, - const AlignedBuffer &ciphertext, - const AlignedBuffer &assoc, - const AlignedBuffer &expected_plaintext, - bool valid ) { +static void test_decrypt( const AlignedBuffer& key, + const AlignedBuffer& nonce, + const AlignedBuffer& ciphertext, + const AlignedBuffer& assoc, + const AlignedBuffer& expected_plaintext, + bool valid ) +{ AlignedPointer ctx_buf( get_ctx( key ) ); - ae_ctx *ctx = (ae_ctx *)ctx_buf->data(); + ae_ctx* ctx = (ae_ctx*)ctx_buf->data(); AlignedBuffer observed_plaintext( ciphertext.len() - TAG_LEN ); - const int ret = ae_decrypt( ctx, nonce.data(), ciphertext.data(), - ciphertext.len(), assoc.data(), assoc.len(), - observed_plaintext.data(), NULL, AE_FINALIZE ); + const int ret = ae_decrypt( ctx, + nonce.data(), + ciphertext.data(), + ciphertext.len(), + assoc.data(), + assoc.len(), + observed_plaintext.data(), + NULL, + AE_FINALIZE ); if ( verbose ) { printf( "ret %d\n", ret ); @@ -130,10 +147,15 @@ static void test_decrypt( const AlignedBuffer &key, const AlignedBuffer &nonce, scrap_ctx( *ctx_buf ); } -static void test_vector( const char *key_p, const char *nonce_p, - size_t assoc_len, const char *assoc_p, - size_t plaintext_len, const char *plaintext_p, - size_t ciphertext_len, const char *ciphertext_p ) { +static void test_vector( const char* key_p, + const char* nonce_p, + size_t assoc_len, + const char* assoc_p, + size_t plaintext_len, + const char* plaintext_p, + size_t ciphertext_len, + const char* ciphertext_p ) +{ AlignedBuffer key( KEY_LEN, key_p ); AlignedBuffer nonce( NONCE_LEN, nonce_p ); @@ -157,8 +179,7 @@ static void test_vector( const char *key_p, const char *nonce_p, PRNG prng; for ( size_t i = 0; i < 64; i++ ) { AlignedBuffer bad_ct( ciphertext.len(), ciphertext.data() ); - ( (uint8_t *)bad_ct.data() )[ prng.uint32() % bad_ct.len() ] ^= - ( 1 << ( prng.uint8() % 8 ) ); + ( (uint8_t*)bad_ct.data() )[prng.uint32() % bad_ct.len()] ^= ( 1 << ( prng.uint8() % 8 ) ); test_decrypt( key, nonce, bad_ct, assoc, plaintext, false ); } @@ -167,313 +188,327 @@ static void test_vector( const char *key_p, const char *nonce_p, } } -#define TEST_VECTOR( _key, _nonce, _assoc, _pt, _ct ) \ - test_vector( _key, _nonce, sizeof( _assoc ) - 1, _assoc, sizeof( _pt ) - 1, \ - _pt, sizeof( _ct ) - 1, _ct ) +#define TEST_VECTOR( _key, _nonce, _assoc, _pt, _ct ) \ + test_vector( _key, _nonce, sizeof( _assoc ) - 1, _assoc, sizeof( _pt ) - 1, _pt, sizeof( _ct ) - 1, _ct ) -static void test_all_vectors( void ) { - /* Test vectors from - * http://tools.ietf.org/html/draft-krovetz-ocb-03#appendix-A */ +static void test_all_vectors( void ) +{ + /* Test vectors from http://tools.ietf.org/html/draft-krovetz-ocb-03#appendix-A */ - const char ietf_key[] = - "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"; + const char ietf_key[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"; const char ietf_nonce[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B"; - TEST_VECTOR( - ietf_key, ietf_nonce, "" /* associated data */ - , - "" /* plaintext */ - /* ciphertext including tag */ - , - "\x19\x7B\x9C\x3C\x44\x1D\x3C\x83\xEA\xFB\x2B\xEF\x63\x3B\x91\x82" ); - - TEST_VECTOR( - ietf_key, ietf_nonce, "\x00\x01\x02\x03\x04\x05\x06\x07", - "\x00\x01\x02\x03\x04\x05\x06\x07", - "\x92\xB6\x57\x13\x0A\x74\xB8\x5A\x16\xDC\x76\xA4\x6D\x47\xE1\xEA" - "\xD5\x37\x20\x9E\x8A\x96\xD1\x4E" ); - - TEST_VECTOR( - ietf_key, ietf_nonce, "\x00\x01\x02\x03\x04\x05\x06\x07", "", - "\x98\xB9\x15\x52\xC8\xC0\x09\x18\x50\x44\xE3\x0A\x6E\xB2\xFE\x21" ); - - TEST_VECTOR( - ietf_key, ietf_nonce, "", "\x00\x01\x02\x03\x04\x05\x06\x07", - "\x92\xB6\x57\x13\x0A\x74\xB8\x5A\x97\x1E\xFF\xCA\xE1\x9A\xD4\x71" - "\x6F\x88\xE8\x7B\x87\x1F\xBE\xED" ); - - TEST_VECTOR( - ietf_key, ietf_nonce, - "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", - "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", - "\xBE\xA5\xE8\x79\x8D\xBE\x71\x10\x03\x1C\x14\x4D\xA0\xB2\x61\x22" - "\x77\x6C\x99\x24\xD6\x72\x3A\x1F\xC4\x52\x45\x32\xAC\x3E\x5B\xEB" ); - - TEST_VECTOR( - ietf_key, ietf_nonce, - "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", "", - "\x7D\xDB\x8E\x6C\xEA\x68\x14\x86\x62\x12\x50\x96\x19\xB1\x9C\xC6" ); - - TEST_VECTOR( - ietf_key, ietf_nonce, "", - "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", - "\xBE\xA5\xE8\x79\x8D\xBE\x71\x10\x03\x1C\x14\x4D\xA0\xB2\x61\x22" - "\x13\xCC\x8B\x74\x78\x07\x12\x1A\x4C\xBB\x3E\x4B\xD6\xB4\x56\xAF" ); - - TEST_VECTOR( - ietf_key, ietf_nonce, - "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" - "\x10\x11\x12\x13\x14\x15\x16\x17", - "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" - "\x10\x11\x12\x13\x14\x15\x16\x17", - "\xBE\xA5\xE8\x79\x8D\xBE\x71\x10\x03\x1C\x14\x4D\xA0\xB2\x61\x22" - "\xFC\xFC\xEE\x7A\x2A\x8D\x4D\x48\x5F\xA9\x4F\xC3\xF3\x88\x20\xF1" - "\xDC\x3F\x3D\x1F\xD4\xE5\x5E\x1C" ); - - TEST_VECTOR( - ietf_key, ietf_nonce, - "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" - "\x10\x11\x12\x13\x14\x15\x16\x17", - "", "\x28\x20\x26\xDA\x30\x68\xBC\x9F\xA1\x18\x68\x1D\x55\x9F\x10\xF6" ); - - TEST_VECTOR( - ietf_key, ietf_nonce, "", - "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" - "\x10\x11\x12\x13\x14\x15\x16\x17", - "\xBE\xA5\xE8\x79\x8D\xBE\x71\x10\x03\x1C\x14\x4D\xA0\xB2\x61\x22" - "\xFC\xFC\xEE\x7A\x2A\x8D\x4D\x48\x6E\xF2\xF5\x25\x87\xFD\xA0\xED" - "\x97\xDC\x7E\xED\xE2\x41\xDF\x68" ); - - TEST_VECTOR( - ietf_key, ietf_nonce, - "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" - "\x10\x11\x12\x13\x14\x15\x16\x17", - "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" - "\x10\x11\x12\x13\x14\x15\x16\x17", - "\xBE\xA5\xE8\x79\x8D\xBE\x71\x10\x03\x1C\x14\x4D\xA0\xB2\x61\x22" - "\xFC\xFC\xEE\x7A\x2A\x8D\x4D\x48\x5F\xA9\x4F\xC3\xF3\x88\x20\xF1" - "\xDC\x3F\x3D\x1F\xD4\xE5\x5E\x1C" ); - - TEST_VECTOR( - ietf_key, ietf_nonce, - "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11" - "\x12\x13\x14\x15\x16\x17", - "", "\x28\x20\x26\xDA\x30\x68\xBC\x9F\xA1\x18\x68\x1D\x55\x9F\x10\xF6" ); - - TEST_VECTOR( - ietf_key, ietf_nonce, "", - "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" - "\x10\x11\x12\x13\x14\x15\x16\x17", - "\xBE\xA5\xE8\x79\x8D\xBE\x71\x10\x03\x1C\x14\x4D\xA0\xB2\x61\x22" - "\xFC\xFC\xEE\x7A\x2A\x8D\x4D\x48\x6E\xF2\xF5\x25\x87\xFD\xA0\xED" - "\x97\xDC\x7E\xED\xE2\x41\xDF\x68" ); - - TEST_VECTOR( - ietf_key, ietf_nonce, - "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" - "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F", - "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" - "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F", - "\xBE\xA5\xE8\x79\x8D\xBE\x71\x10\x03\x1C\x14\x4D\xA0\xB2\x61\x22" - "\xCE\xAA\xB9\xB0\x5D\xF7\x71\xA6\x57\x14\x9D\x53\x77\x34\x63\xCB" - "\xB2\xA0\x40\xDD\x3B\xD5\x16\x43\x72\xD7\x6D\x7B\xB6\x82\x42\x40" ); - - TEST_VECTOR( - ietf_key, ietf_nonce, - "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" - "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F", - "", "\xE1\xE0\x72\x63\x3B\xAD\xE5\x1A\x60\xE8\x59\x51\xD9\xC4\x2A\x1B" ); - - TEST_VECTOR( - ietf_key, ietf_nonce, "", - "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" - "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F", - "\xBE\xA5\xE8\x79\x8D\xBE\x71\x10\x03\x1C\x14\x4D\xA0\xB2\x61\x22" - "\xCE\xAA\xB9\xB0\x5D\xF7\x71\xA6\x57\x14\x9D\x53\x77\x34\x63\xCB" - "\x4A\x3B\xAE\x82\x44\x65\xCF\xDA\xF8\xC4\x1F\xC5\x0C\x7D\xF9\xD9" ); - - TEST_VECTOR( - ietf_key, ietf_nonce, - "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" - "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" - "\x20\x21\x22\x23\x24\x25\x26\x27", - "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" - "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" - "\x20\x21\x22\x23\x24\x25\x26\x27", - "\xBE\xA5\xE8\x79\x8D\xBE\x71\x10\x03\x1C\x14\x4D\xA0\xB2\x61\x22" - "\xCE\xAA\xB9\xB0\x5D\xF7\x71\xA6\x57\x14\x9D\x53\x77\x34\x63\xCB" - "\x68\xC6\x57\x78\xB0\x58\xA6\x35\x65\x9C\x62\x32\x11\xDE\xEA\x0D" - "\xE3\x0D\x2C\x38\x18\x79\xF4\xC8" ); - - TEST_VECTOR( - ietf_key, ietf_nonce, - "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" - "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" - "\x20\x21\x22\x23\x24\x25\x26\x27", - "", "\x7A\xEB\x7A\x69\xA1\x68\x7D\xD0\x82\xCA\x27\xB0\xD9\xA3\x70\x96" ); - - TEST_VECTOR( - ietf_key, ietf_nonce, "", - "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" - "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" - "\x20\x21\x22\x23\x24\x25\x26\x27", - "\xBE\xA5\xE8\x79\x8D\xBE\x71\x10\x03\x1C\x14\x4D\xA0\xB2\x61\x22" - "\xCE\xAA\xB9\xB0\x5D\xF7\x71\xA6\x57\x14\x9D\x53\x77\x34\x63\xCB" - "\x68\xC6\x57\x78\xB0\x58\xA6\x35\x06\x0C\x84\x67\xF4\xAB\xAB\x5E" - "\x8B\x3C\x20\x67\xA2\xE1\x15\xDC" ); + TEST_VECTOR( ietf_key, + ietf_nonce, + "" /* associated data */ + , + "" /* plaintext */ + /* ciphertext including tag */ + , + "\x19\x7B\x9C\x3C\x44\x1D\x3C\x83\xEA\xFB\x2B\xEF\x63\x3B\x91\x82" ); + + TEST_VECTOR( ietf_key, + ietf_nonce, + "\x00\x01\x02\x03\x04\x05\x06\x07", + "\x00\x01\x02\x03\x04\x05\x06\x07", + "\x92\xB6\x57\x13\x0A\x74\xB8\x5A\x16\xDC\x76\xA4\x6D\x47\xE1\xEA" + "\xD5\x37\x20\x9E\x8A\x96\xD1\x4E" ); + + TEST_VECTOR( ietf_key, + ietf_nonce, + "\x00\x01\x02\x03\x04\x05\x06\x07", + "", + "\x98\xB9\x15\x52\xC8\xC0\x09\x18\x50\x44\xE3\x0A\x6E\xB2\xFE\x21" ); + + TEST_VECTOR( ietf_key, + ietf_nonce, + "", + "\x00\x01\x02\x03\x04\x05\x06\x07", + "\x92\xB6\x57\x13\x0A\x74\xB8\x5A\x97\x1E\xFF\xCA\xE1\x9A\xD4\x71" + "\x6F\x88\xE8\x7B\x87\x1F\xBE\xED" ); + + TEST_VECTOR( ietf_key, + ietf_nonce, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", + "\xBE\xA5\xE8\x79\x8D\xBE\x71\x10\x03\x1C\x14\x4D\xA0\xB2\x61\x22" + "\x77\x6C\x99\x24\xD6\x72\x3A\x1F\xC4\x52\x45\x32\xAC\x3E\x5B\xEB" ); + + TEST_VECTOR( ietf_key, + ietf_nonce, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", + "", + "\x7D\xDB\x8E\x6C\xEA\x68\x14\x86\x62\x12\x50\x96\x19\xB1\x9C\xC6" ); + + TEST_VECTOR( ietf_key, + ietf_nonce, + "", + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", + "\xBE\xA5\xE8\x79\x8D\xBE\x71\x10\x03\x1C\x14\x4D\xA0\xB2\x61\x22" + "\x13\xCC\x8B\x74\x78\x07\x12\x1A\x4C\xBB\x3E\x4B\xD6\xB4\x56\xAF" ); + + TEST_VECTOR( ietf_key, + ietf_nonce, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" + "\x10\x11\x12\x13\x14\x15\x16\x17", + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" + "\x10\x11\x12\x13\x14\x15\x16\x17", + "\xBE\xA5\xE8\x79\x8D\xBE\x71\x10\x03\x1C\x14\x4D\xA0\xB2\x61\x22" + "\xFC\xFC\xEE\x7A\x2A\x8D\x4D\x48\x5F\xA9\x4F\xC3\xF3\x88\x20\xF1" + "\xDC\x3F\x3D\x1F\xD4\xE5\x5E\x1C" ); + + TEST_VECTOR( ietf_key, + ietf_nonce, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" + "\x10\x11\x12\x13\x14\x15\x16\x17", + "", + "\x28\x20\x26\xDA\x30\x68\xBC\x9F\xA1\x18\x68\x1D\x55\x9F\x10\xF6" ); + + TEST_VECTOR( ietf_key, + ietf_nonce, + "", + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" + "\x10\x11\x12\x13\x14\x15\x16\x17", + "\xBE\xA5\xE8\x79\x8D\xBE\x71\x10\x03\x1C\x14\x4D\xA0\xB2\x61\x22" + "\xFC\xFC\xEE\x7A\x2A\x8D\x4D\x48\x6E\xF2\xF5\x25\x87\xFD\xA0\xED" + "\x97\xDC\x7E\xED\xE2\x41\xDF\x68" ); + + TEST_VECTOR( ietf_key, + ietf_nonce, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" + "\x10\x11\x12\x13\x14\x15\x16\x17", + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" + "\x10\x11\x12\x13\x14\x15\x16\x17", + "\xBE\xA5\xE8\x79\x8D\xBE\x71\x10\x03\x1C\x14\x4D\xA0\xB2\x61\x22" + "\xFC\xFC\xEE\x7A\x2A\x8D\x4D\x48\x5F\xA9\x4F\xC3\xF3\x88\x20\xF1" + "\xDC\x3F\x3D\x1F\xD4\xE5\x5E\x1C" ); + + TEST_VECTOR( ietf_key, + ietf_nonce, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17", + "", + "\x28\x20\x26\xDA\x30\x68\xBC\x9F\xA1\x18\x68\x1D\x55\x9F\x10\xF6" ); + + TEST_VECTOR( ietf_key, + ietf_nonce, + "", + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" + "\x10\x11\x12\x13\x14\x15\x16\x17", + "\xBE\xA5\xE8\x79\x8D\xBE\x71\x10\x03\x1C\x14\x4D\xA0\xB2\x61\x22" + "\xFC\xFC\xEE\x7A\x2A\x8D\x4D\x48\x6E\xF2\xF5\x25\x87\xFD\xA0\xED" + "\x97\xDC\x7E\xED\xE2\x41\xDF\x68" ); + + TEST_VECTOR( ietf_key, + ietf_nonce, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" + "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F", + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" + "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F", + "\xBE\xA5\xE8\x79\x8D\xBE\x71\x10\x03\x1C\x14\x4D\xA0\xB2\x61\x22" + "\xCE\xAA\xB9\xB0\x5D\xF7\x71\xA6\x57\x14\x9D\x53\x77\x34\x63\xCB" + "\xB2\xA0\x40\xDD\x3B\xD5\x16\x43\x72\xD7\x6D\x7B\xB6\x82\x42\x40" ); + + TEST_VECTOR( ietf_key, + ietf_nonce, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" + "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F", + "", + "\xE1\xE0\x72\x63\x3B\xAD\xE5\x1A\x60\xE8\x59\x51\xD9\xC4\x2A\x1B" ); + + TEST_VECTOR( ietf_key, + ietf_nonce, + "", + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" + "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F", + "\xBE\xA5\xE8\x79\x8D\xBE\x71\x10\x03\x1C\x14\x4D\xA0\xB2\x61\x22" + "\xCE\xAA\xB9\xB0\x5D\xF7\x71\xA6\x57\x14\x9D\x53\x77\x34\x63\xCB" + "\x4A\x3B\xAE\x82\x44\x65\xCF\xDA\xF8\xC4\x1F\xC5\x0C\x7D\xF9\xD9" ); + + TEST_VECTOR( ietf_key, + ietf_nonce, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" + "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" + "\x20\x21\x22\x23\x24\x25\x26\x27", + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" + "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" + "\x20\x21\x22\x23\x24\x25\x26\x27", + "\xBE\xA5\xE8\x79\x8D\xBE\x71\x10\x03\x1C\x14\x4D\xA0\xB2\x61\x22" + "\xCE\xAA\xB9\xB0\x5D\xF7\x71\xA6\x57\x14\x9D\x53\x77\x34\x63\xCB" + "\x68\xC6\x57\x78\xB0\x58\xA6\x35\x65\x9C\x62\x32\x11\xDE\xEA\x0D" + "\xE3\x0D\x2C\x38\x18\x79\xF4\xC8" ); + + TEST_VECTOR( ietf_key, + ietf_nonce, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" + "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" + "\x20\x21\x22\x23\x24\x25\x26\x27", + "", + "\x7A\xEB\x7A\x69\xA1\x68\x7D\xD0\x82\xCA\x27\xB0\xD9\xA3\x70\x96" ); + + TEST_VECTOR( ietf_key, + ietf_nonce, + "", + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" + "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" + "\x20\x21\x22\x23\x24\x25\x26\x27", + "\xBE\xA5\xE8\x79\x8D\xBE\x71\x10\x03\x1C\x14\x4D\xA0\xB2\x61\x22" + "\xCE\xAA\xB9\xB0\x5D\xF7\x71\xA6\x57\x14\x9D\x53\x77\x34\x63\xCB" + "\x68\xC6\x57\x78\xB0\x58\xA6\x35\x06\x0C\x84\x67\xF4\xAB\xAB\x5E" + "\x8B\x3C\x20\x67\xA2\xE1\x15\xDC" ); /* Some big texts. These were originally encrypted using this program; they are regression tests. */ - TEST_VECTOR( - "\x06\xF8\x9F\x69\xDA\x49\xDA\xD7\x68\x48\xFF\xB3\x60\xB6\x8F\x00", - "\xDC\xBF\x85\x18\x23\xD9\x67\x85\x45\x59\x6F\xAD", "", - "\xC4\x8E\x1F\x04\x10\x2F\xA5\x58\x68\x42\x62\xF3\x1B\xE7\x63\xA7" - "\x77\x89\x64\x16\xE6\xB0\xF7\xFA\xFE\xF0\xB9\x50\x22\xDC\xCE\x78" - "\xA5\x01\xA4\x2D\xA2\x0F\x50\xEA\x9A\xAE\x23\x60\x1C\xC9\x11\x84" - "\x5F\xD0\x0A\x88\x99\xCD\xF1\x1B\x7C\xF9\x71\xC2\xD8\xE3\x7B\xB1" - "\xBC\x91\xCE\x10\xDA\xED\xBF\xA5\xDF\x96\x69\x7A\xFA\xCA\x9A\x91" - "\x40\xF9\x8F\xF1\xFE\x5A\x2B\x21\x17\xA5\xAE\x97\xBD\x0B\x68\xE0" - "\x58\x7A\xB4\x10\x89\xDE\x30\x12\xB7\x14\xEB\xE8\xFA\xA5\x87\x7A" - "\x7E\xEA\xD0\x34\x0B\xAF\x73\x0B\x1C\xA7\xC5\xCB\x84\x15\x5F\x45" - "\x53\x8E\x27\xD7\xA0\x7D\xAF\x99\x05\x6E\x9F\xF4\xCD\xE5\xA1\x11" - "\x43\xBD\x7A\x24\xA3\xB7\xB6\x92\x7C\xB7\xD8\x6F\x17\x78\xB3\x30" - "\x53\x6E\x46\x14\x11\x86\xF6\x70\x2E\x25\x8E\x54\xF8\x70\x2F\x47" - "\x2B\xF8\xF6\xC3\xEE\xFB\x9B\x7D\xF0\x73\xAD\x24\xC0\xE9\x58\xA8" - "\x79\xDC\x92\x25\x6D\xF3\x9D\xA8\x8F\x07\xA3\xE7\xAB\xF4\xBC\x32" - "\x29\xB6\xEF\xDB\x20\x42\x51\xCF\xD5\x57\xDA\x14\xC7\x2A\xB3\x19" - "\xDE\x31\xF7\x77\x95\x8D\x33\x57\x1D\xEB\x9A\x80\x98\x4D\x95\x07" - "\xEB\x38\x42\xEB\xE0\xAB\x2D\xF3\x9E\x16\xFA\x6D\x06\x62\x41\x58" - "\x81\xBF\x3D\x01\x1A\xF7\xBA\x53\xCE\x60\xEF\x86\xC9\x11\xED\x89" - "\x5B\xCF\x98\xB4\xD3\xD4\xAC\xB9\x71\x69\xEE\xF6\xA7\x77\x4E\x46" - "\x0F\xF7\x1D\x7D\x36\x4E\x86\x15\xCD\xF3\xD3\x5C\xAA\x97\x74\xCC" - "\x5D\xD6\xF0\x5C\x62\x27\x0D\x4B\x01\xDD\x8B\xE6\x2C\x72\x99\xBA" - "\x5B\x95\x87\x0F\xB9\x9A\xBE\xA2\x42\x5E\x7D\x1B\x19\x08\xBC\xEF" - "\x66\x24\x2F\xB3\xFC\xE7\xDA\xB1\x79\x51\xE9\x3B\x45\x66\xDC\xD8" - "\x0F\xA7\x56\xBF\x56\x15\x4B\x15\xCC\x3E\x9F\x44\xB9\xED\xC2\x0A" - "\x7C\xA9\x6D\x87\xCD\xE2\x00\x9F\x2F\x2C\xF0\xBC\x1B\xB0\x27\xE8" - "\x46\x3E\x06\x1E\xD5\xB6\xB4\x82\xF7\x88\xB7\x48\xF3\x58\xB0\x23" - "\x6D\xC2\xD3\x85\x9D\x1F\xE5\x30\xFC\xC8\x46\x62\xD1\xE1\xAE\x3B" - "\x3A\xA9\x57\xE0\xD7\x8F\x7E\x4D\x59\x7D\x7A\xEB\xBF\xD3\x10\x00" - "\xA0\xE4\x76\x76\xE3\xA8\x14\xD0\x03\xBF\x1F\x6A\xF9\x11\xCE\x98" - "\x2C\x2A\x86\x25\x77\x85\x14\x76\xD4\x51\xAB\xC7\x3A\xA7\xE1\xF7" - "\x23\xF7\x2B\xA3\xBA\xE4\x0B\xA4\x81\x9A\x83\x98\x69\xC3\x1C\x8A" - "\xBD\x26\x12\x36\x22\x9D\xCE\x85\x5D\xA3\xA0\xDF\x66\xD0\x59\xF6" - "\x47\xF2\xC5\x37\xF1\x62\x0D\x0C\x45\x5B\xE5\xFE\x3C\x8D\x28\x75", - "\xa1\xd8\xa0\xe0\x75\x5c\xb4\xf4\xab\x59\x6d\x14\xfc\x2e\x75\x54" - "\xa3\x35\x4f\x57\x69\x48\x7a\x46\x17\x5f\xd9\x34\x50\xf9\x35\xe5" - "\x6f\xee\x27\xdb\x28\x0f\x06\x0b\xaf\xd5\x50\x4e\x20\x78\x35\xd6" - "\x4d\xa0\x18\xe8\x6c\x5b\x07\xbb\xb6\xd0\x3f\x4a\x0e\x14\x32\xaf" - "\x0d\x6a\x5d\xb6\xe4\x36\xb0\x1c\xae\x2e\x75\x85\x19\x53\x9d\xf2" - "\xc6\xc6\xf5\x29\x4a\x5d\x73\xd6\xcd\x3a\xec\x38\x15\x7b\x1f\x3d" - "\x19\x8f\x7f\x85\x53\x75\xfe\x6c\x8a\x5d\x4f\x05\x3f\x16\x5e\x73" - "\x9c\xbe\xbe\xdb\xe8\xb2\x3e\xea\x0f\x2e\x2c\xf3\x2c\x9c\x56\x5b" - "\xf7\xf2\xed\x87\x07\xfb\x87\x74\x09\xda\xb8\xad\x57\xc0\xa0\x79" - "\xc6\x69\x1c\x79\x08\x69\x35\x18\xc4\x54\xca\x6b\xed\x89\xa0\x27" - "\x32\x19\x1f\xaf\xff\x12\x1c\x1b\x08\xa6\x9f\x0e\xe3\x01\x98\x77" - "\xdb\x75\xdf\x87\x67\x6d\xd9\xb4\x23\x39\xd0\x81\x54\xf8\x89\x18" - "\x5c\xbd\xb7\x4d\xf4\xb1\x8b\x37\x2e\x9b\x20\x29\x9f\x95\x9e\xdd" - "\x73\x2c\xdb\x37\xe5\x7d\x9f\x8a\x79\xff\x8f\x5b\x99\x10\xe1\xe9" - "\x1d\xcb\x1f\x17\xef\x7d\xb7\xd1\x50\x23\x4a\x38\x92\xfb\xbe\x1c" - "\xff\x23\x68\x3a\xb9\xc8\xbc\xa0\xab\xa7\xbe\xc8\x84\xce\x66\xa7" - "\x11\x17\xc6\x48\x91\x4d\x77\xe1\x64\xc4\x26\x08\xcd\xb4\xea\x10" - "\x42\x60\x5a\x7c\x5a\x72\xba\xb4\x93\xf7\x02\xa1\xd4\x44\xdb\x1a" - "\x4a\xc3\xb1\xea\x69\x74\xea\x18\xb3\x5a\x27\x09\x6f\x5b\x1f\x30" - "\xe2\xeb\x2a\x37\x5e\xd2\xe2\x23\xec\xbc\xcb\xcb\x65\x41\xed\x0e" - "\x23\xda\x71\x45\xf3\x3f\x7d\x44\x73\xd7\x14\x4d\xab\x03\xf7\x7d" - "\x24\x33\x9d\x25\x83\x1f\x3d\xf3\xc9\x34\x42\x6c\x2f\x61\xa2\x83" - "\xa0\x0f\xb6\x28\xe8\x27\xf0\x91\xf6\xc5\x7e\xa1\x74\x74\xaf\xa7" - "\x7f\xba\x99\x29\xb2\x91\x9f\xf0\xf7\x71\x1f\xf0\x0b\xd6\xd9\xf9" - "\x72\xaa\x04\x09\x5d\x75\x76\x5f\x18\xc8\xd5\xd5\x84\x1a\x40\x3f" - "\xe5\x38\xe4\x38\xdf\xf9\x0d\x79\xdc\x71\xc8\xa8\xef\x86\x4e\x26" - "\xf4\xc2\x46\xf4\xe0\x64\xd6\x5e\xfb\x1c\x47\x58\x3d\x87\x7c\xba" - "\xa3\xf5\x98\xdc\xd5\xdf\xaf\x62\x96\xee\x4e\x39\x32\x4c\x6d\xd2" - "\x0a\x6f\xf8\x34\x98\x76\xae\x21\xa1\x41\x3d\x96\xfc\x52\xdb\xdd" - "\xf3\x9a\xb1\xf3\x78\x3d\xb8\x2f\xae\xae\x7d\xe0\x4b\xb2\xdf\x2b" - "\x12\xac\xee\xfb\xf8\x54\x60\xea\x74\xd5\xde\x43\x7b\x38\x45\x5f" - "\xa0\xb8\xe8\xcc\x8a\xe3\xcc\x0c\x92\xe6\xb1\xb0\xe2\xc1\x99\xca" - "\x1b\xa1\xac\x6e\x7a\x8a\xa0\x20\x3d\xeb\x29\x8b\xf4\x55\x41\x62" ); - - TEST_VECTOR( - "\x7A\x54\x0D\x3E\x56\x38\xF7\xC6\xCF\xAB\xF9\x56\xDC\xCA\x14\x23", - "\x9B\x0E\xC1\x15\xD5\xE6\xC9\xAB\xE6\x88\x2A\x18", "", - "\x52\xDB\xA7\x44\x2B\x1C\x9C\x24\x4D\xF3\xA1\xE4\x53\x7B\x9B\xB2" - "\x25\xC5\xA3\x81\x42\x23\xA9\xB4\x12\xF8\xFC\xE4\xF6\x8E\x20\xD4" - "\x59\x7B\x39\x2D\x5D\x7C\x6E\xB7\x51\x02\x90\x7A\x8E\xAA\x30\xD0" - "\xEB\xDF\x70\x09\x5A\xEC\xFB\xD4\xDB\x0B\xE9\x1B\x79\xAF\x40\xA3" - "\xC9\xD1\x3F\x0E\x7E\x9B\xA8\xF2\x4E\xA2\xAE\x81\xE7\x8F\xE9\x4A" - "\xF8\x84\x38\x20\x9B\xCB\x0D\x9E\x46\x87\xCC\x0C\x71\xF2\x4C\xE5" - "\x57\x47\xFB\x52\x1D\x0C\x92\xCD\x9B\xD0\xA3\xA3\xFE\x44\x4F\x2A" - "\x2D\x7D\xC8\x48\x87\x71\x8A\x83\x83\x43\x52\xD9\x87\x72\x0A\x1F" - "\x72\x7D\xE0\x0D\xE4\xBA\x38\x2D\xAB\x89\x85\x34\xFE\x30\xE9\x47" - "\x99\x69\x96\x37\x3B\x88\x0D\x08\x5B\x41\xF0\x55\x3A\x90\xB6\x5D" - "\xC9\xB8\xFA\x22\xEB\x54\x67\x1B\x43\x3B\x2A\x13\xDF\x76\x71\xBF" - "\x8F\xBA\xF6\x5F\xE0\xAE\x84\x80\xD3\x9A\x9E\xFE\x35\x29\x0C\x44" - "\xB8\x3B\xC8\x58\x3F\x51\x18\xF0\x8E\x3F\xE0\xFE\xFF\x55\xE1\xFD" - "\x79\xED\x71\x6D\xB9\xBE\xF0\x76\x25\x4E\x6F\xA2\x49\x5B\xEC\x20" - "\x61\x95\x65\x67\xBF\xA3\x73\x18\x65\x7C\x2F\x94\x29\x3B\x57\x7D" - "\x78\x6A\xBD\x22\x2B\x17\x5E\xDA\x2B\x4E\xC3\xA5\xF0\x9A\xD9\x1C" - "\xCF\xC4\xDD\x7E\x07\xB4\xE6\x50\xD0\x9D\xAF\x86\x9D\x3F\xFE\x70" - "\x64\x18\xBA\x32\x90\xE5\x63\xA0\x08\x3D\x1D\xCE\xB2\x77\x31\x59" - "\xD4\xB4\x03\x2C\xE2\x15\x11\x17\xD1\xBA\x5E\x1E\x7D\x38\x09\xCF" - "\x25\x3E\x3D\x89\x7E\x13\xAE\x11\xFA\xCD\x46\x23\x86\xC5\x78\xC8" - "\x1A\xE8\x8F\x9A\x9C\xCE\xBE\x01\x5D\x70\x56\xA8\x84\x07\x07\x2A" - "\x1C\xD4\x33\x8B\x2F\x01\x0F\xD0\xCC\xCD\x29\xEC\x73\x6E\xDE\xB2" - "\xBC\xA7\x32\x6A\x12\x93\x13\xCD\xE0\xA9\x55\x97\x36\x6B\xDA\xC5" - "\xC5\xD2\x44\x80\xBD\x00\x37\xD7\x21\x80\x27\x1F\x2E\x02\x76\x1A" - "\x57\xA5\x5F\xCE\x8B\x20\x6A\x6A\x0F\x70\x9B\xDB\x07\x64\x96\x7B" - "\x43\xFD\xCA\xBF\x9D\x52\xEB\x24\x7B\x1B\xEE\x43\x10\x2C\xDB\x92" - "\xA1\xA8\xA9\xF7\x2F\xD2\x39\xA8\x85\x9C\xFE\x2C\x2A\xCF\x52\x73" - "\xFB\xCA\x20\xAD\xC9\xDD\xFC\x4A\x91\x39\x6C\x7C\x84\x67\xC5\xE4" - "\x9B\x3E\x3D\x6B\x56\x3B\x2B\xDC\x8A\x46\xF6\x7C\x36\xF9\x27\x29" - "\x37\x38\x7C\x9D\xA0\x6E\x5D\x4C\xE5\xB2\x6F\x0C\xDC\xEF\xFE\x35" - "\xFE\x3D\x56\x40\x7F\xBD\x4D\xDD\x40\x79\xDD\xA7\x0A\x7B\xA2\xCE" - "\x22\x38\x94\xEA\x90\xF5\x95\xB6\xE6\x6F\x14\xFB\xA2", - "\xec\xa9\xcc\x30\x66\x6c\x04\x16\x21\x8d\xc8\x15\x47\xa2\x18\xcf" - "\x19\x90\x4f\x82\x27\x25\xa2\x1e\xfa\x1c\xe4\x58\x78\x43\x52\x4c" - "\xac\x24\xde\xcb\xad\x80\x05\x7a\xeb\x2d\xc0\x33\x05\x31\x25\x44" - "\xd7\x11\xa1\xf2\xcb\x09\x6f\xf0\x14\x3c\x3f\xf2\xc7\x79\xfb\x3f" - "\xb0\x0a\x65\xae\xd7\xe5\x5d\x35\x0c\xb4\x69\x7a\x89\x6b\xa9\xdc" - "\x02\x69\x96\xd2\x9f\xe7\x3c\x99\xd4\xd3\x55\x97\xc4\x59\xad\xc4" - "\x0c\x7b\xf8\x47\x1c\xbe\x36\x2a\x53\x6b\xb1\x21\x5f\xc1\x6e\xca" - "\x0a\x4f\x16\x3a\xf0\xd4\x12\xa6\xf8\x68\x9f\x12\xad\x36\x4c\xd8" - "\x5a\x5b\x17\xb8\xbd\xc7\x2c\x48\x51\x7d\x45\x74\x00\xb0\x02\xe9" - "\x1b\xd6\x0c\x41\xa7\x5d\x65\xca\x68\xa7\x3e\x3c\xf5\xaa\x9b\xbd" - "\x25\x98\x00\xd8\x4d\xbc\xd1\x7a\x25\x34\x92\x24\xa4\x84\x62\x63" - "\x2c\x40\xa5\x58\x81\x90\xf1\x0f\x75\xaa\x70\xe4\x4e\x0f\xa3\x03" - "\x90\xd1\x07\x18\x0a\x50\x9a\x3e\x28\x1f\x33\xb7\x11\xed\x3c\x2c" - "\x40\xc8\xd7\xe3\x12\xdc\xef\x94\x93\x7b\x11\xc3\x24\x51\x61\xbf" - "\x8b\xa4\xa4\x5c\x85\x0d\x50\x49\x45\x69\xbe\x5b\x36\x90\x84\x30" - "\x66\x67\x76\x3d\xcc\x02\x8b\x9f\xb7\x90\x57\xef\xe1\x21\x34\x65" - "\x3e\xca\xbf\x70\x1d\x76\x63\xbf\xae\x1f\xb2\x55\xf0\x87\x3e\x42" - "\xf9\x71\x28\x02\x06\x9e\xf7\x6a\x47\x3b\xda\x38\x54\x66\xd9\xaf" - "\xba\x7b\xec\xbf\xe3\x52\x63\x02\x8b\xa7\xad\x1d\x76\x16\xa2\x20" - "\x38\xec\x40\xb7\xc8\x35\x6b\xc2\x80\x9d\x20\x02\xc6\x34\xdb\x65" - "\xd8\x27\x0b\xc5\x2d\x85\xe4\xdc\x85\xae\x10\x36\x01\xdb\x4b\xaf" - "\x44\x79\xea\x23\x21\xa0\x83\xa3\x91\xf5\xc5\x16\x9b\xeb\x43\x92" - "\x1f\x88\xd2\x00\x60\x40\xe9\x52\x0b\x39\x86\x3b\x9e\x3b\x9a\x4a" - "\x31\xdf\xb6\x57\x78\x38\xcf\x77\x7c\x0c\xf4\x14\x90\x25\xed\x27" - "\xd2\x86\x20\x4c\x1a\x52\xeb\xbe\x1e\xac\x2b\xce\xb7\x72\x86\x87" - "\xfd\xac\x11\x90\xc5\xea\x96\xcb\xdc\x89\xe9\x77\xf0\x83\xc3\xa7" - "\xa7\xd1\xe1\xc9\x7e\x89\xb3\x4e\xf1\x12\xa3\x9c\xfe\x66\xcc\x5d" - "\xcf\x1d\x5a\x11\x21\x2f\x10\x66\x37\x5f\xd7\x35\xeb\x09\x62\x99" - "\xa6\xf8\xc7\xc7\xef\xd3\xf0\x56\x2b\xa7\x14\x65\x6a\xce\xa9\x68" - "\xe7\xa4\x89\xb4\x1e\x16\x99\xbf\x8d\x2d\x5e\x67\xb4\x3a\x0b\xf3" - "\x37\x14\x1e\x5d\xc6\xb4\xb5\x9e\xa5\x69\xa4\xaf\xcc\x0f\x46\xe9" - "\xd5\xbb\x10\x49\x07\x0d\x92\x42\x0c\x04\xb9\xdf\xa4\xb5\xef\xcc" - "\x05\x81\x3f\xc1\x21\x12\x2c\x33\xb7\x79\xfd\x5d\x8a" ); + TEST_VECTOR( "\x06\xF8\x9F\x69\xDA\x49\xDA\xD7\x68\x48\xFF\xB3\x60\xB6\x8F\x00", + "\xDC\xBF\x85\x18\x23\xD9\x67\x85\x45\x59\x6F\xAD", + "", + "\xC4\x8E\x1F\x04\x10\x2F\xA5\x58\x68\x42\x62\xF3\x1B\xE7\x63\xA7" + "\x77\x89\x64\x16\xE6\xB0\xF7\xFA\xFE\xF0\xB9\x50\x22\xDC\xCE\x78" + "\xA5\x01\xA4\x2D\xA2\x0F\x50\xEA\x9A\xAE\x23\x60\x1C\xC9\x11\x84" + "\x5F\xD0\x0A\x88\x99\xCD\xF1\x1B\x7C\xF9\x71\xC2\xD8\xE3\x7B\xB1" + "\xBC\x91\xCE\x10\xDA\xED\xBF\xA5\xDF\x96\x69\x7A\xFA\xCA\x9A\x91" + "\x40\xF9\x8F\xF1\xFE\x5A\x2B\x21\x17\xA5\xAE\x97\xBD\x0B\x68\xE0" + "\x58\x7A\xB4\x10\x89\xDE\x30\x12\xB7\x14\xEB\xE8\xFA\xA5\x87\x7A" + "\x7E\xEA\xD0\x34\x0B\xAF\x73\x0B\x1C\xA7\xC5\xCB\x84\x15\x5F\x45" + "\x53\x8E\x27\xD7\xA0\x7D\xAF\x99\x05\x6E\x9F\xF4\xCD\xE5\xA1\x11" + "\x43\xBD\x7A\x24\xA3\xB7\xB6\x92\x7C\xB7\xD8\x6F\x17\x78\xB3\x30" + "\x53\x6E\x46\x14\x11\x86\xF6\x70\x2E\x25\x8E\x54\xF8\x70\x2F\x47" + "\x2B\xF8\xF6\xC3\xEE\xFB\x9B\x7D\xF0\x73\xAD\x24\xC0\xE9\x58\xA8" + "\x79\xDC\x92\x25\x6D\xF3\x9D\xA8\x8F\x07\xA3\xE7\xAB\xF4\xBC\x32" + "\x29\xB6\xEF\xDB\x20\x42\x51\xCF\xD5\x57\xDA\x14\xC7\x2A\xB3\x19" + "\xDE\x31\xF7\x77\x95\x8D\x33\x57\x1D\xEB\x9A\x80\x98\x4D\x95\x07" + "\xEB\x38\x42\xEB\xE0\xAB\x2D\xF3\x9E\x16\xFA\x6D\x06\x62\x41\x58" + "\x81\xBF\x3D\x01\x1A\xF7\xBA\x53\xCE\x60\xEF\x86\xC9\x11\xED\x89" + "\x5B\xCF\x98\xB4\xD3\xD4\xAC\xB9\x71\x69\xEE\xF6\xA7\x77\x4E\x46" + "\x0F\xF7\x1D\x7D\x36\x4E\x86\x15\xCD\xF3\xD3\x5C\xAA\x97\x74\xCC" + "\x5D\xD6\xF0\x5C\x62\x27\x0D\x4B\x01\xDD\x8B\xE6\x2C\x72\x99\xBA" + "\x5B\x95\x87\x0F\xB9\x9A\xBE\xA2\x42\x5E\x7D\x1B\x19\x08\xBC\xEF" + "\x66\x24\x2F\xB3\xFC\xE7\xDA\xB1\x79\x51\xE9\x3B\x45\x66\xDC\xD8" + "\x0F\xA7\x56\xBF\x56\x15\x4B\x15\xCC\x3E\x9F\x44\xB9\xED\xC2\x0A" + "\x7C\xA9\x6D\x87\xCD\xE2\x00\x9F\x2F\x2C\xF0\xBC\x1B\xB0\x27\xE8" + "\x46\x3E\x06\x1E\xD5\xB6\xB4\x82\xF7\x88\xB7\x48\xF3\x58\xB0\x23" + "\x6D\xC2\xD3\x85\x9D\x1F\xE5\x30\xFC\xC8\x46\x62\xD1\xE1\xAE\x3B" + "\x3A\xA9\x57\xE0\xD7\x8F\x7E\x4D\x59\x7D\x7A\xEB\xBF\xD3\x10\x00" + "\xA0\xE4\x76\x76\xE3\xA8\x14\xD0\x03\xBF\x1F\x6A\xF9\x11\xCE\x98" + "\x2C\x2A\x86\x25\x77\x85\x14\x76\xD4\x51\xAB\xC7\x3A\xA7\xE1\xF7" + "\x23\xF7\x2B\xA3\xBA\xE4\x0B\xA4\x81\x9A\x83\x98\x69\xC3\x1C\x8A" + "\xBD\x26\x12\x36\x22\x9D\xCE\x85\x5D\xA3\xA0\xDF\x66\xD0\x59\xF6" + "\x47\xF2\xC5\x37\xF1\x62\x0D\x0C\x45\x5B\xE5\xFE\x3C\x8D\x28\x75", + "\xa1\xd8\xa0\xe0\x75\x5c\xb4\xf4\xab\x59\x6d\x14\xfc\x2e\x75\x54" + "\xa3\x35\x4f\x57\x69\x48\x7a\x46\x17\x5f\xd9\x34\x50\xf9\x35\xe5" + "\x6f\xee\x27\xdb\x28\x0f\x06\x0b\xaf\xd5\x50\x4e\x20\x78\x35\xd6" + "\x4d\xa0\x18\xe8\x6c\x5b\x07\xbb\xb6\xd0\x3f\x4a\x0e\x14\x32\xaf" + "\x0d\x6a\x5d\xb6\xe4\x36\xb0\x1c\xae\x2e\x75\x85\x19\x53\x9d\xf2" + "\xc6\xc6\xf5\x29\x4a\x5d\x73\xd6\xcd\x3a\xec\x38\x15\x7b\x1f\x3d" + "\x19\x8f\x7f\x85\x53\x75\xfe\x6c\x8a\x5d\x4f\x05\x3f\x16\x5e\x73" + "\x9c\xbe\xbe\xdb\xe8\xb2\x3e\xea\x0f\x2e\x2c\xf3\x2c\x9c\x56\x5b" + "\xf7\xf2\xed\x87\x07\xfb\x87\x74\x09\xda\xb8\xad\x57\xc0\xa0\x79" + "\xc6\x69\x1c\x79\x08\x69\x35\x18\xc4\x54\xca\x6b\xed\x89\xa0\x27" + "\x32\x19\x1f\xaf\xff\x12\x1c\x1b\x08\xa6\x9f\x0e\xe3\x01\x98\x77" + "\xdb\x75\xdf\x87\x67\x6d\xd9\xb4\x23\x39\xd0\x81\x54\xf8\x89\x18" + "\x5c\xbd\xb7\x4d\xf4\xb1\x8b\x37\x2e\x9b\x20\x29\x9f\x95\x9e\xdd" + "\x73\x2c\xdb\x37\xe5\x7d\x9f\x8a\x79\xff\x8f\x5b\x99\x10\xe1\xe9" + "\x1d\xcb\x1f\x17\xef\x7d\xb7\xd1\x50\x23\x4a\x38\x92\xfb\xbe\x1c" + "\xff\x23\x68\x3a\xb9\xc8\xbc\xa0\xab\xa7\xbe\xc8\x84\xce\x66\xa7" + "\x11\x17\xc6\x48\x91\x4d\x77\xe1\x64\xc4\x26\x08\xcd\xb4\xea\x10" + "\x42\x60\x5a\x7c\x5a\x72\xba\xb4\x93\xf7\x02\xa1\xd4\x44\xdb\x1a" + "\x4a\xc3\xb1\xea\x69\x74\xea\x18\xb3\x5a\x27\x09\x6f\x5b\x1f\x30" + "\xe2\xeb\x2a\x37\x5e\xd2\xe2\x23\xec\xbc\xcb\xcb\x65\x41\xed\x0e" + "\x23\xda\x71\x45\xf3\x3f\x7d\x44\x73\xd7\x14\x4d\xab\x03\xf7\x7d" + "\x24\x33\x9d\x25\x83\x1f\x3d\xf3\xc9\x34\x42\x6c\x2f\x61\xa2\x83" + "\xa0\x0f\xb6\x28\xe8\x27\xf0\x91\xf6\xc5\x7e\xa1\x74\x74\xaf\xa7" + "\x7f\xba\x99\x29\xb2\x91\x9f\xf0\xf7\x71\x1f\xf0\x0b\xd6\xd9\xf9" + "\x72\xaa\x04\x09\x5d\x75\x76\x5f\x18\xc8\xd5\xd5\x84\x1a\x40\x3f" + "\xe5\x38\xe4\x38\xdf\xf9\x0d\x79\xdc\x71\xc8\xa8\xef\x86\x4e\x26" + "\xf4\xc2\x46\xf4\xe0\x64\xd6\x5e\xfb\x1c\x47\x58\x3d\x87\x7c\xba" + "\xa3\xf5\x98\xdc\xd5\xdf\xaf\x62\x96\xee\x4e\x39\x32\x4c\x6d\xd2" + "\x0a\x6f\xf8\x34\x98\x76\xae\x21\xa1\x41\x3d\x96\xfc\x52\xdb\xdd" + "\xf3\x9a\xb1\xf3\x78\x3d\xb8\x2f\xae\xae\x7d\xe0\x4b\xb2\xdf\x2b" + "\x12\xac\xee\xfb\xf8\x54\x60\xea\x74\xd5\xde\x43\x7b\x38\x45\x5f" + "\xa0\xb8\xe8\xcc\x8a\xe3\xcc\x0c\x92\xe6\xb1\xb0\xe2\xc1\x99\xca" + "\x1b\xa1\xac\x6e\x7a\x8a\xa0\x20\x3d\xeb\x29\x8b\xf4\x55\x41\x62" ); + + TEST_VECTOR( "\x7A\x54\x0D\x3E\x56\x38\xF7\xC6\xCF\xAB\xF9\x56\xDC\xCA\x14\x23", + "\x9B\x0E\xC1\x15\xD5\xE6\xC9\xAB\xE6\x88\x2A\x18", + "", + "\x52\xDB\xA7\x44\x2B\x1C\x9C\x24\x4D\xF3\xA1\xE4\x53\x7B\x9B\xB2" + "\x25\xC5\xA3\x81\x42\x23\xA9\xB4\x12\xF8\xFC\xE4\xF6\x8E\x20\xD4" + "\x59\x7B\x39\x2D\x5D\x7C\x6E\xB7\x51\x02\x90\x7A\x8E\xAA\x30\xD0" + "\xEB\xDF\x70\x09\x5A\xEC\xFB\xD4\xDB\x0B\xE9\x1B\x79\xAF\x40\xA3" + "\xC9\xD1\x3F\x0E\x7E\x9B\xA8\xF2\x4E\xA2\xAE\x81\xE7\x8F\xE9\x4A" + "\xF8\x84\x38\x20\x9B\xCB\x0D\x9E\x46\x87\xCC\x0C\x71\xF2\x4C\xE5" + "\x57\x47\xFB\x52\x1D\x0C\x92\xCD\x9B\xD0\xA3\xA3\xFE\x44\x4F\x2A" + "\x2D\x7D\xC8\x48\x87\x71\x8A\x83\x83\x43\x52\xD9\x87\x72\x0A\x1F" + "\x72\x7D\xE0\x0D\xE4\xBA\x38\x2D\xAB\x89\x85\x34\xFE\x30\xE9\x47" + "\x99\x69\x96\x37\x3B\x88\x0D\x08\x5B\x41\xF0\x55\x3A\x90\xB6\x5D" + "\xC9\xB8\xFA\x22\xEB\x54\x67\x1B\x43\x3B\x2A\x13\xDF\x76\x71\xBF" + "\x8F\xBA\xF6\x5F\xE0\xAE\x84\x80\xD3\x9A\x9E\xFE\x35\x29\x0C\x44" + "\xB8\x3B\xC8\x58\x3F\x51\x18\xF0\x8E\x3F\xE0\xFE\xFF\x55\xE1\xFD" + "\x79\xED\x71\x6D\xB9\xBE\xF0\x76\x25\x4E\x6F\xA2\x49\x5B\xEC\x20" + "\x61\x95\x65\x67\xBF\xA3\x73\x18\x65\x7C\x2F\x94\x29\x3B\x57\x7D" + "\x78\x6A\xBD\x22\x2B\x17\x5E\xDA\x2B\x4E\xC3\xA5\xF0\x9A\xD9\x1C" + "\xCF\xC4\xDD\x7E\x07\xB4\xE6\x50\xD0\x9D\xAF\x86\x9D\x3F\xFE\x70" + "\x64\x18\xBA\x32\x90\xE5\x63\xA0\x08\x3D\x1D\xCE\xB2\x77\x31\x59" + "\xD4\xB4\x03\x2C\xE2\x15\x11\x17\xD1\xBA\x5E\x1E\x7D\x38\x09\xCF" + "\x25\x3E\x3D\x89\x7E\x13\xAE\x11\xFA\xCD\x46\x23\x86\xC5\x78\xC8" + "\x1A\xE8\x8F\x9A\x9C\xCE\xBE\x01\x5D\x70\x56\xA8\x84\x07\x07\x2A" + "\x1C\xD4\x33\x8B\x2F\x01\x0F\xD0\xCC\xCD\x29\xEC\x73\x6E\xDE\xB2" + "\xBC\xA7\x32\x6A\x12\x93\x13\xCD\xE0\xA9\x55\x97\x36\x6B\xDA\xC5" + "\xC5\xD2\x44\x80\xBD\x00\x37\xD7\x21\x80\x27\x1F\x2E\x02\x76\x1A" + "\x57\xA5\x5F\xCE\x8B\x20\x6A\x6A\x0F\x70\x9B\xDB\x07\x64\x96\x7B" + "\x43\xFD\xCA\xBF\x9D\x52\xEB\x24\x7B\x1B\xEE\x43\x10\x2C\xDB\x92" + "\xA1\xA8\xA9\xF7\x2F\xD2\x39\xA8\x85\x9C\xFE\x2C\x2A\xCF\x52\x73" + "\xFB\xCA\x20\xAD\xC9\xDD\xFC\x4A\x91\x39\x6C\x7C\x84\x67\xC5\xE4" + "\x9B\x3E\x3D\x6B\x56\x3B\x2B\xDC\x8A\x46\xF6\x7C\x36\xF9\x27\x29" + "\x37\x38\x7C\x9D\xA0\x6E\x5D\x4C\xE5\xB2\x6F\x0C\xDC\xEF\xFE\x35" + "\xFE\x3D\x56\x40\x7F\xBD\x4D\xDD\x40\x79\xDD\xA7\x0A\x7B\xA2\xCE" + "\x22\x38\x94\xEA\x90\xF5\x95\xB6\xE6\x6F\x14\xFB\xA2", + "\xec\xa9\xcc\x30\x66\x6c\x04\x16\x21\x8d\xc8\x15\x47\xa2\x18\xcf" + "\x19\x90\x4f\x82\x27\x25\xa2\x1e\xfa\x1c\xe4\x58\x78\x43\x52\x4c" + "\xac\x24\xde\xcb\xad\x80\x05\x7a\xeb\x2d\xc0\x33\x05\x31\x25\x44" + "\xd7\x11\xa1\xf2\xcb\x09\x6f\xf0\x14\x3c\x3f\xf2\xc7\x79\xfb\x3f" + "\xb0\x0a\x65\xae\xd7\xe5\x5d\x35\x0c\xb4\x69\x7a\x89\x6b\xa9\xdc" + "\x02\x69\x96\xd2\x9f\xe7\x3c\x99\xd4\xd3\x55\x97\xc4\x59\xad\xc4" + "\x0c\x7b\xf8\x47\x1c\xbe\x36\x2a\x53\x6b\xb1\x21\x5f\xc1\x6e\xca" + "\x0a\x4f\x16\x3a\xf0\xd4\x12\xa6\xf8\x68\x9f\x12\xad\x36\x4c\xd8" + "\x5a\x5b\x17\xb8\xbd\xc7\x2c\x48\x51\x7d\x45\x74\x00\xb0\x02\xe9" + "\x1b\xd6\x0c\x41\xa7\x5d\x65\xca\x68\xa7\x3e\x3c\xf5\xaa\x9b\xbd" + "\x25\x98\x00\xd8\x4d\xbc\xd1\x7a\x25\x34\x92\x24\xa4\x84\x62\x63" + "\x2c\x40\xa5\x58\x81\x90\xf1\x0f\x75\xaa\x70\xe4\x4e\x0f\xa3\x03" + "\x90\xd1\x07\x18\x0a\x50\x9a\x3e\x28\x1f\x33\xb7\x11\xed\x3c\x2c" + "\x40\xc8\xd7\xe3\x12\xdc\xef\x94\x93\x7b\x11\xc3\x24\x51\x61\xbf" + "\x8b\xa4\xa4\x5c\x85\x0d\x50\x49\x45\x69\xbe\x5b\x36\x90\x84\x30" + "\x66\x67\x76\x3d\xcc\x02\x8b\x9f\xb7\x90\x57\xef\xe1\x21\x34\x65" + "\x3e\xca\xbf\x70\x1d\x76\x63\xbf\xae\x1f\xb2\x55\xf0\x87\x3e\x42" + "\xf9\x71\x28\x02\x06\x9e\xf7\x6a\x47\x3b\xda\x38\x54\x66\xd9\xaf" + "\xba\x7b\xec\xbf\xe3\x52\x63\x02\x8b\xa7\xad\x1d\x76\x16\xa2\x20" + "\x38\xec\x40\xb7\xc8\x35\x6b\xc2\x80\x9d\x20\x02\xc6\x34\xdb\x65" + "\xd8\x27\x0b\xc5\x2d\x85\xe4\xdc\x85\xae\x10\x36\x01\xdb\x4b\xaf" + "\x44\x79\xea\x23\x21\xa0\x83\xa3\x91\xf5\xc5\x16\x9b\xeb\x43\x92" + "\x1f\x88\xd2\x00\x60\x40\xe9\x52\x0b\x39\x86\x3b\x9e\x3b\x9a\x4a" + "\x31\xdf\xb6\x57\x78\x38\xcf\x77\x7c\x0c\xf4\x14\x90\x25\xed\x27" + "\xd2\x86\x20\x4c\x1a\x52\xeb\xbe\x1e\xac\x2b\xce\xb7\x72\x86\x87" + "\xfd\xac\x11\x90\xc5\xea\x96\xcb\xdc\x89\xe9\x77\xf0\x83\xc3\xa7" + "\xa7\xd1\xe1\xc9\x7e\x89\xb3\x4e\xf1\x12\xa3\x9c\xfe\x66\xcc\x5d" + "\xcf\x1d\x5a\x11\x21\x2f\x10\x66\x37\x5f\xd7\x35\xeb\x09\x62\x99" + "\xa6\xf8\xc7\xc7\xef\xd3\xf0\x56\x2b\xa7\x14\x65\x6a\xce\xa9\x68" + "\xe7\xa4\x89\xb4\x1e\x16\x99\xbf\x8d\x2d\x5e\x67\xb4\x3a\x0b\xf3" + "\x37\x14\x1e\x5d\xc6\xb4\xb5\x9e\xa5\x69\xa4\xaf\xcc\x0f\x46\xe9" + "\xd5\xbb\x10\x49\x07\x0d\x92\x42\x0c\x04\xb9\xdf\xa4\xb5\xef\xcc" + "\x05\x81\x3f\xc1\x21\x12\x2c\x33\xb7\x79\xfd\x5d\x8a" ); } /* http://tools.ietf.org/html/draft-krovetz-ocb-03#appendix-A also specifies an iterative test algorithm, which we implement here. */ -static void test_iterative( void ) { +static void test_iterative( void ) +{ /* Key is always all zeros */ AlignedBuffer key( KEY_LEN ); memset( key.data(), 0, KEY_LEN ); AlignedPointer ctx_buf( get_ctx( key ) ); - ae_ctx *ctx = (ae_ctx *)ctx_buf->data(); + ae_ctx* ctx = (ae_ctx*)ctx_buf->data(); AlignedBuffer nonce( NONCE_LEN ); memset( nonce.data(), 0, NONCE_LEN ); @@ -481,7 +516,7 @@ static void test_iterative( void ) { /* The loop below fills this buffer in order. Each iteration adds 2*i + 3*TAG_LEN bytes. */ AlignedBuffer accumulator( 22400 ); - uint8_t *acc = (uint8_t *)accumulator.data(); + uint8_t* acc = (uint8_t*)accumulator.data(); for ( size_t i = 0; i < 128; i++ ) { /* i bytes of zeros */ @@ -489,27 +524,24 @@ static void test_iterative( void ) { memset( s.data(), 0, s.len() ); /* Nonce is 11 bytes of zeros followed by 1 byte i */ - ( (uint8_t *)nonce.data() )[ 11 ] = i; + ( (uint8_t*)nonce.data() )[11] = i; /* We can't write directly to acc because it might not be aligned. */ AlignedBuffer out( s.len() + TAG_LEN ); /* OCB-ENCRYPT(K,N,S,S) */ - fatal_assert( 0 <= ae_encrypt( ctx, nonce.data(), s.data(), s.len(), - s.data(), s.len(), out.data(), NULL, - AE_FINALIZE ) ); + fatal_assert( + 0 <= ae_encrypt( ctx, nonce.data(), s.data(), s.len(), s.data(), s.len(), out.data(), NULL, AE_FINALIZE ) ); memcpy( acc, out.data(), s.len() + TAG_LEN ); acc += s.len() + TAG_LEN; /* OCB-ENCRYPT(K,N,<empty string>,S) */ - fatal_assert( 0 <= ae_encrypt( ctx, nonce.data(), s.data(), s.len(), NULL, - 0, out.data(), NULL, AE_FINALIZE ) ); + fatal_assert( 0 <= ae_encrypt( ctx, nonce.data(), s.data(), s.len(), NULL, 0, out.data(), NULL, AE_FINALIZE ) ); memcpy( acc, out.data(), s.len() + TAG_LEN ); acc += s.len() + TAG_LEN; /* OCB-ENCRYPT(K,N,S,<empty string>) */ - fatal_assert( 0 <= ae_encrypt( ctx, nonce.data(), NULL, 0, s.data(), - s.len(), out.data(), NULL, AE_FINALIZE ) ); + fatal_assert( 0 <= ae_encrypt( ctx, nonce.data(), NULL, 0, s.data(), s.len(), out.data(), NULL, AE_FINALIZE ) ); memcpy( acc, out.data(), TAG_LEN ); acc += TAG_LEN; } @@ -517,14 +549,12 @@ static void test_iterative( void ) { /* OCB-ENCRYPT(K,N,C,<empty string>) */ AlignedBuffer out( TAG_LEN ); memset( nonce.data(), 0, NONCE_LEN ); - fatal_assert( 0 <= ae_encrypt( ctx, nonce.data(), NULL, 0, accumulator.data(), - accumulator.len(), out.data(), NULL, - AE_FINALIZE ) ); + fatal_assert( + 0 <= ae_encrypt( + ctx, nonce.data(), NULL, 0, accumulator.data(), accumulator.len(), out.data(), NULL, AE_FINALIZE ) ); /* Check this final tag against the known value */ - AlignedBuffer correct( - TAG_LEN, - "\xB2\xB4\x1C\xBF\x9B\x05\x03\x7D\xA7\xF1\x6C\x24\xA3\x5C\x1C\x94" ); + AlignedBuffer correct( TAG_LEN, "\xB2\xB4\x1C\xBF\x9B\x05\x03\x7D\xA7\xF1\x6C\x24\xA3\x5C\x1C\x94" ); fatal_assert( equal( out, correct ) ); if ( verbose ) { @@ -533,15 +563,16 @@ static void test_iterative( void ) { scrap_ctx( *ctx_buf ); } -int main( int argc, char *argv[] ) { - if ( argc >= 2 && strcmp( argv[ 1 ], "-v" ) == 0 ) { +int main( int argc, char* argv[] ) +{ + if ( argc >= 2 && strcmp( argv[1], "-v" ) == 0 ) { verbose = true; } try { test_all_vectors(); test_iterative(); - } catch ( const std::exception &e ) { + } catch ( const std::exception& e ) { fprintf( stderr, "Error: %s\r\n", e.what() ); return 1; } diff --git a/src/tests/test_utils.cc b/src/tests/test_utils.cc index 95c3bf64e..2ef26b7fd 100644 --- a/src/tests/test_utils.cc +++ b/src/tests/test_utils.cc @@ -34,22 +34,25 @@ #include "test_utils.h" -void hexdump( const void *buf, size_t len, const char *name ) { - const unsigned char *data = (const unsigned char *)buf; +void hexdump( const void* buf, size_t len, const char* name ) +{ + const unsigned char* data = (const unsigned char*)buf; printf( DUMP_NAME_FMT, name ); for ( size_t i = 0; i < len; i++ ) { // Although data[i] is an unsigned char, it will be promoted to a signed int // when passed as an argument. Explicitly cast it back to an unsigned type // so it can be printed in hex. - printf( "%02x", static_cast<unsigned>( data[ i ] ) ); + printf( "%02x", static_cast<unsigned>( data[i] ) ); } printf( "\n" ); } -void hexdump( const Crypto::AlignedBuffer &buf, const char *name ) { +void hexdump( const Crypto::AlignedBuffer& buf, const char* name ) +{ hexdump( buf.data(), buf.len(), name ); } -void hexdump( const std::string &buf, const char *name ) { +void hexdump( const std::string& buf, const char* name ) +{ hexdump( buf.data(), buf.size(), name ); } diff --git a/src/tests/test_utils.h b/src/tests/test_utils.h index 41e6b3f38..b8dc12d52 100644 --- a/src/tests/test_utils.h +++ b/src/tests/test_utils.h @@ -39,8 +39,8 @@ #define DUMP_NAME_FMT "%-10s " -void hexdump( const void *buf, size_t len, const char *name ); -void hexdump( const Crypto::AlignedBuffer &buf, const char *name ); -void hexdump( const std::string &buf, const char *name ); +void hexdump( const void* buf, size_t len, const char* name ); +void hexdump( const Crypto::AlignedBuffer& buf, const char* name ); +void hexdump( const std::string& buf, const char* name ); #endif diff --git a/src/util/dos_assert.h b/src/util/dos_assert.h index 418a3d74f..0288e6ae2 100644 --- a/src/util/dos_assert.h +++ b/src/util/dos_assert.h @@ -38,17 +38,19 @@ #include "crypto.h" -static void dos_detected( const char *expression, const char *file, int line, - const char *function ) { - char buffer[ 2048 ]; - snprintf( buffer, 2048, - "Illegal counterparty input (possible denial of service) in " - "function %s at %s:%d, failed test: %s\n", - function, file, line, expression ); +static void dos_detected( const char* expression, const char* file, int line, const char* function ) +{ + char buffer[2048]; + snprintf( buffer, + 2048, + "Illegal counterparty input (possible denial of service) in function %s at %s:%d, failed test: %s\n", + function, + file, + line, + expression ); throw Crypto::CryptoException( buffer ); } -#define dos_assert( expr ) \ - ( ( expr ) ? (void)0 : dos_detected( #expr, __FILE__, __LINE__, __func__ ) ) +#define dos_assert( expr ) ( ( expr ) ? (void)0 : dos_detected( #expr, __FILE__, __LINE__, __func__ ) ) #endif diff --git a/src/util/fatal_assert.h b/src/util/fatal_assert.h index 441c4e35e..db183162a 100644 --- a/src/util/fatal_assert.h +++ b/src/util/fatal_assert.h @@ -36,15 +36,17 @@ #include <stdio.h> #include <stdlib.h> -static void fatal_error( const char *expression, const char *file, int line, - const char *function ) { +static void fatal_error( const char* expression, const char* file, int line, const char* function ) +{ fprintf( stderr, "Fatal assertion failure in function %s at %s:%d\nFailed test: %s\n", - function, file, line, expression ); + function, + file, + line, + expression ); abort(); } -#define fatal_assert( expr ) \ - ( ( expr ) ? (void)0 : fatal_error( #expr, __FILE__, __LINE__, __func__ ) ) +#define fatal_assert( expr ) ( ( expr ) ? (void)0 : fatal_error( #expr, __FILE__, __LINE__, __func__ ) ) #endif diff --git a/src/util/locale_utils.cc b/src/util/locale_utils.cc index b341d884e..63e8ff51c 100644 --- a/src/util/locale_utils.cc +++ b/src/util/locale_utils.cc @@ -45,30 +45,33 @@ #include "locale_utils.h" -const std::string LocaleVar::str( void ) const { +const std::string LocaleVar::str( void ) const +{ if ( name.empty() ) { return std::string( "[no charset variables]" ); } return name + "=" + value; } -const LocaleVar get_ctype( void ) { +const LocaleVar get_ctype( void ) +{ /* Reimplement the search logic, just for diagnostics */ - if ( const char *all = getenv( "LC_ALL" ) ) { + if ( const char* all = getenv( "LC_ALL" ) ) { return LocaleVar( "LC_ALL", all ); - } else if ( const char *ctype = getenv( "LC_CTYPE" ) ) { + } else if ( const char* ctype = getenv( "LC_CTYPE" ) ) { return LocaleVar( "LC_CTYPE", ctype ); - } else if ( const char *lang = getenv( "LANG" ) ) { + } else if ( const char* lang = getenv( "LANG" ) ) { return LocaleVar( "LANG", lang ); } return LocaleVar( "", "" ); } -const char *locale_charset( void ) { +const char* locale_charset( void ) +{ static const char ASCII_name[] = "US-ASCII"; /* Produce more pleasant name of US-ASCII */ - const char *ret = nl_langinfo( CODESET ); + const char* ret = nl_langinfo( CODESET ); if ( strcmp( ret, "ANSI_X3.4-1968" ) == 0 ) { ret = ASCII_name; @@ -77,26 +80,25 @@ const char *locale_charset( void ) { return ret; } -bool is_utf8_locale( void ) { +bool is_utf8_locale( void ) +{ /* Verify locale calls for UTF-8 */ - if ( strcmp( locale_charset(), "UTF-8" ) != 0 - && strcmp( locale_charset(), "utf-8" ) != 0 ) { + if ( strcmp( locale_charset(), "UTF-8" ) != 0 && strcmp( locale_charset(), "utf-8" ) != 0 ) { return false; } return true; } -void set_native_locale( void ) { +void set_native_locale( void ) +{ /* Adopt native locale */ if ( NULL == setlocale( LC_ALL, "" ) ) { int saved_errno = errno; if ( saved_errno == ENOENT ) { LocaleVar ctype( get_ctype() ); - fprintf( stderr, "The locale requested by %s isn't available here.\n", - ctype.str().c_str() ); + fprintf( stderr, "The locale requested by %s isn't available here.\n", ctype.str().c_str() ); if ( !ctype.name.empty() ) { - fprintf( stderr, "Running `locale-gen %s' may be necessary.\n\n", - ctype.value.c_str() ); + fprintf( stderr, "Running `locale-gen %s' may be necessary.\n\n", ctype.value.c_str() ); } } else { errno = saved_errno; @@ -105,7 +107,8 @@ void set_native_locale( void ) { } } -void clear_locale_variables( void ) { +void clear_locale_variables( void ) +{ unsetenv( "LANG" ); unsetenv( "LANGUAGE" ); unsetenv( "LC_CTYPE" ); diff --git a/src/util/locale_utils.h b/src/util/locale_utils.h index 761f887f1..3a1945cfa 100644 --- a/src/util/locale_utils.h +++ b/src/util/locale_utils.h @@ -35,16 +35,19 @@ #include <string> -class LocaleVar { +class LocaleVar +{ public: const std::string name, value; - LocaleVar( const char *s_name, const char *s_value ) - : name( s_name ), value( s_value ) {} + LocaleVar( const char* s_name, const char* s_value ) + : name( s_name ) + , value( s_value ) + {} const std::string str( void ) const; }; const LocaleVar get_ctype( void ); -const char *locale_charset( void ); +const char* locale_charset( void ); bool is_utf8_locale( void ); void set_native_locale( void ); void clear_locale_variables( void ); diff --git a/src/util/pty_compat.cc b/src/util/pty_compat.cc index 42b92168f..55003c8e2 100644 --- a/src/util/pty_compat.cc +++ b/src/util/pty_compat.cc @@ -45,11 +45,11 @@ #include "pty_compat.h" #ifndef HAVE_FORKPTY -pid_t my_forkpty( int *amaster, char *name, const struct termios *termp, - const struct winsize *winp ) { +pid_t my_forkpty( int* amaster, char* name, const struct termios* termp, const struct winsize* winp ) +{ /* For Solaris and AIX */ int master, slave; - char *slave_name; + char* slave_name; pid_t pid; #ifdef _AIX @@ -91,8 +91,7 @@ pid_t my_forkpty( int *amaster, char *name, const struct termios *termp, } #ifndef _AIX - if ( ioctl( slave, I_PUSH, "ptem" ) < 0 - || ioctl( slave, I_PUSH, "ldterm" ) < 0 ) { + if ( ioctl( slave, I_PUSH, "ptem" ) < 0 || ioctl( slave, I_PUSH, "ldterm" ) < 0 ) { perror( "ioctl(I_PUSH)" ); close( slave ); close( master ); @@ -100,9 +99,11 @@ pid_t my_forkpty( int *amaster, char *name, const struct termios *termp, } #endif - if ( amaster != NULL ) *amaster = master; + if ( amaster != NULL ) + *amaster = master; - if ( name != NULL ) strcpy( name, slave_name ); + if ( name != NULL ) + strcpy( name, slave_name ); if ( termp != NULL ) { if ( tcsetattr( slave, TCSAFLUSH, termp ) < 0 ) { @@ -130,46 +131,51 @@ pid_t my_forkpty( int *amaster, char *name, const struct termios *termp, pid = fork(); switch ( pid ) { - case -1: /* Error */ perror( "fork()" ); return -1; - case 0: /* Child */ - if ( setsid() < 0 ) perror( "setsid" ); -#ifdef TIOCSCTTY - if ( ioctl( slave, TIOCSCTTY, NULL ) < 0 ) { - perror( "ioctl" ); + case -1: /* Error */ + perror( "fork()" ); return -1; - } -#else - { - int dummy_fd; - dummy_fd = open( slave_name, O_RDWR ); - if ( dummy_fd < 0 ) { - perror( "open(slave_name)" ); + case 0: /* Child */ + if ( setsid() < 0 ) + perror( "setsid" ); +#ifdef TIOCSCTTY + if ( ioctl( slave, TIOCSCTTY, NULL ) < 0 ) { + perror( "ioctl" ); return -1; } - close( dummy_fd ); - } +#else + { + int dummy_fd; + dummy_fd = open( slave_name, O_RDWR ); + if ( dummy_fd < 0 ) { + perror( "open(slave_name)" ); + return -1; + } + close( dummy_fd ); + } #endif /* TIOCSCTTY */ - close( master ); - dup2( slave, STDIN_FILENO ); - dup2( slave, STDOUT_FILENO ); - dup2( slave, STDERR_FILENO ); - return 0; - default: /* Parent */ close( slave ); return pid; + close( master ); + dup2( slave, STDIN_FILENO ); + dup2( slave, STDOUT_FILENO ); + dup2( slave, STDERR_FILENO ); + return 0; + default: /* Parent */ + close( slave ); + return pid; } } #endif #ifndef HAVE_CFMAKERAW -void my_cfmakeraw( struct termios *termios_p ) { - termios_p->c_iflag &= - ~( IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON ); +void my_cfmakeraw( struct termios* termios_p ) +{ + termios_p->c_iflag &= ~( IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON ); termios_p->c_oflag &= ~OPOST; termios_p->c_lflag &= ~( ECHO | ECHONL | ICANON | ISIG | IEXTEN ); termios_p->c_cflag &= ~( CSIZE | PARENB ); termios_p->c_cflag |= CS8; - termios_p->c_cc[ VMIN ] = 1; // read() is satisfied after 1 char - termios_p->c_cc[ VTIME ] = 0; // No timer + termios_p->c_cc[VMIN] = 1; // read() is satisfied after 1 char + termios_p->c_cc[VTIME] = 0; // No timer } #endif #endif diff --git a/src/util/pty_compat.h b/src/util/pty_compat.h index 9ad9f3024..11dfdd330 100644 --- a/src/util/pty_compat.h +++ b/src/util/pty_compat.h @@ -42,9 +42,8 @@ #define cfmakeraw my_cfmakeraw #endif -pid_t my_forkpty( int *amaster, char *name, const struct termios *termp, - const struct winsize *winp ); +pid_t my_forkpty( int* amaster, char* name, const struct termios* termp, const struct winsize* winp ); -void my_cfmakeraw( struct termios *termios_p ); +void my_cfmakeraw( struct termios* termios_p ); #endif diff --git a/src/util/select.cc b/src/util/select.cc index 278f3b5b2..573e7314f 100644 --- a/src/util/select.cc +++ b/src/util/select.cc @@ -38,10 +38,11 @@ sigset_t Select::dummy_sigset; unsigned int Select::verbose = 0; -void Select::handle_signal( int signum ) { +void Select::handle_signal( int signum ) +{ fatal_assert( signum >= 0 ); fatal_assert( signum <= MAX_SIGNAL_NUMBER ); - Select &sel = get_instance(); - sel.got_signal[ signum ] = 1; + Select& sel = get_instance(); + sel.got_signal[signum] = 1; } diff --git a/src/util/select.h b/src/util/select.h index f02d0cb39..9ba226695 100644 --- a/src/util/select.h +++ b/src/util/select.h @@ -47,9 +47,11 @@ Any signals blocked by calling sigprocmask() outside this code will still be received during Select::select(). So don't do that. */ -class Select { +class Select +{ public: - static Select &get_instance( void ) { + static Select& get_instance( void ) + { /* COFU may or may not be thread-safe, depending on compiler */ static Select instance; return instance; @@ -58,13 +60,13 @@ class Select { private: Select() : max_fd( -1 ) - /* These initializations are not used; they are just - here to appease -Weffc++. */ - , - all_fds( dummy_fd_set ), - read_fds( dummy_fd_set ), - empty_sigset( dummy_sigset ), - consecutive_polls( 0 ) { + /* These initializations are not used; they are just + here to appease -Weffc++. */ + , all_fds( dummy_fd_set ) + , read_fds( dummy_fd_set ) + , empty_sigset( dummy_sigset ) + , consecutive_polls( 0 ) + { FD_ZERO( &all_fds ); FD_ZERO( &read_fds ); @@ -72,19 +74,21 @@ class Select { fatal_assert( 0 == sigemptyset( &empty_sigset ) ); } - void clear_got_signal( void ) { - for ( volatile sig_atomic_t *p = got_signal; - p < got_signal + sizeof( got_signal ) / sizeof( *got_signal ); p++ ) { + void clear_got_signal( void ) + { + for ( volatile sig_atomic_t* p = got_signal; p < got_signal + sizeof( got_signal ) / sizeof( *got_signal ); + p++ ) { *p = 0; } } /* not implemented */ - Select( const Select & ); - Select &operator=( const Select & ); + Select( const Select& ); + Select& operator=( const Select& ); public: - void add_fd( int fd ) { + void add_fd( int fd ) + { if ( fd > max_fd ) { max_fd = fd; } @@ -93,7 +97,8 @@ class Select { void clear_fds( void ) { FD_ZERO( &all_fds ); } - static void add_signal( int signum ) { + static void add_signal( int signum ) + { fatal_assert( signum >= 0 ); fatal_assert( signum <= MAX_SIGNAL_NUMBER ); @@ -113,7 +118,8 @@ class Select { } /* timeout unit: milliseconds; negative timeout means wait forever */ - int select( int timeout ) { + int select( int timeout ) + { memcpy( &read_fds, &all_fds, sizeof( read_fds ) ); clear_got_signal(); @@ -123,21 +129,19 @@ class Select { } if ( timeout == 0 && ++consecutive_polls >= MAX_POLLS ) { if ( verbose > 1 && consecutive_polls == MAX_POLLS ) { - fprintf( stderr, "%s: got %d polls, rate limiting.\n", __func__, - MAX_POLLS ); + fprintf( stderr, "%s: got %d polls, rate limiting.\n", __func__, MAX_POLLS ); } timeout = 1; } else if ( timeout != 0 && consecutive_polls ) { if ( verbose > 1 && consecutive_polls >= MAX_POLLS ) { - fprintf( stderr, "%s: got %d consecutive polls\n", __func__, - consecutive_polls ); + fprintf( stderr, "%s: got %d consecutive polls\n", __func__, consecutive_polls ); } consecutive_polls = 0; } #ifdef HAVE_PSELECT struct timespec ts; - struct timespec *tsp = NULL; + struct timespec* tsp = NULL; if ( timeout >= 0 ) { ts.tv_sec = timeout / 1000; @@ -145,11 +149,10 @@ class Select { tsp = &ts; } - int ret = - ::pselect( max_fd + 1, &read_fds, NULL, NULL, tsp, &empty_sigset ); + int ret = ::pselect( max_fd + 1, &read_fds, NULL, NULL, tsp, &empty_sigset ); #else struct timeval tv; - struct timeval *tvp = NULL; + struct timeval* tvp = NULL; sigset_t old_sigset; if ( timeout >= 0 ) { @@ -186,7 +189,7 @@ class Select { bool read( int fd ) #if FD_ISSET_IS_CONST - const + const #endif { assert( FD_ISSET( fd, &all_fds ) ); @@ -194,25 +197,30 @@ class Select { } /* This method consumes a signal notification. */ - bool signal( int signum ) { + bool signal( int signum ) + { fatal_assert( signum >= 0 ); fatal_assert( signum <= MAX_SIGNAL_NUMBER ); /* XXX This requires a guard against concurrent signals. */ - bool rv = got_signal[ signum ]; - got_signal[ signum ] = 0; + bool rv = got_signal[signum]; + got_signal[signum] = 0; return rv; } /* This method does not consume signal notifications. */ - bool any_signal( void ) const { + bool any_signal( void ) const + { bool rv = false; for ( int i = 0; i < MAX_SIGNAL_NUMBER; i++ ) { - rv |= got_signal[ i ]; + rv |= got_signal[i]; } return rv; } - static void set_verbose( unsigned int s_verbose ) { verbose = s_verbose; } + static void set_verbose( unsigned int s_verbose ) + { + verbose = s_verbose; + } private: static const int MAX_SIGNAL_NUMBER = 64; @@ -226,7 +234,7 @@ class Select { /* We assume writes to got_signal are atomic, though we also try to mask out concurrent signal handlers. */ - volatile sig_atomic_t got_signal[ MAX_SIGNAL_NUMBER + 1 ]; + volatile sig_atomic_t got_signal[MAX_SIGNAL_NUMBER + 1]; fd_set all_fds, read_fds; diff --git a/src/util/shared.h b/src/util/shared.h index 6e90d469a..e16b185db 100644 --- a/src/util/shared.h +++ b/src/util/shared.h @@ -45,35 +45,38 @@ namespace shared { #ifdef HAVE_STD_SHARED_PTR - using std::make_shared; - using std::shared_ptr; +using std::make_shared; +using std::shared_ptr; #else #ifdef HAVE_STD_TR1_SHARED_PTR - using std::tr1::shared_ptr; +using std::tr1::shared_ptr; - // make_shared emulation. - template <typename Tp> - inline shared_ptr<Tp> make_shared() { - return shared_ptr<Tp>( new Tp() ); - } - template <typename Tp, typename A1> - inline shared_ptr<Tp> make_shared( const A1 &a1 ) { - return shared_ptr<Tp>( new Tp( a1 ) ); - } - template <typename Tp, typename A1, typename A2> - inline shared_ptr<Tp> make_shared( const A1 &a1, const A2 &a2 ) { - return shared_ptr<Tp>( new Tp( a1, a2 ) ); - } - template <typename Tp, typename A1, typename A2, typename A3> - inline shared_ptr<Tp> make_shared( const A1 &a1, const A2 &a2, - const A3 &a3 ) { - return shared_ptr<Tp>( new Tp( a1, a2, a3 ) ); - } - template <typename Tp, typename A1, typename A2, typename A3, typename A4> - inline shared_ptr<Tp> make_shared( const A1 &a1, const A2 &a2, const A3 &a3, - const A4 &a4 ) { - return shared_ptr<Tp>( new Tp( a1, a2, a3, a4 ) ); - } +// make_shared emulation. +template<typename Tp> +inline shared_ptr<Tp> make_shared() +{ + return shared_ptr<Tp>( new Tp() ); +} +template<typename Tp, typename A1> +inline shared_ptr<Tp> make_shared( const A1& a1 ) +{ + return shared_ptr<Tp>( new Tp( a1 ) ); +} +template<typename Tp, typename A1, typename A2> +inline shared_ptr<Tp> make_shared( const A1& a1, const A2& a2 ) +{ + return shared_ptr<Tp>( new Tp( a1, a2 ) ); +} +template<typename Tp, typename A1, typename A2, typename A3> +inline shared_ptr<Tp> make_shared( const A1& a1, const A2& a2, const A3& a3 ) +{ + return shared_ptr<Tp>( new Tp( a1, a2, a3 ) ); +} +template<typename Tp, typename A1, typename A2, typename A3, typename A4> +inline shared_ptr<Tp> make_shared( const A1& a1, const A2& a2, const A3& a3, const A4& a4 ) +{ + return shared_ptr<Tp>( new Tp( a1, a2, a3, a4 ) ); +} #else #error Need a shared_ptr class. Try Boost::TR1. #endif diff --git a/src/util/swrite.cc b/src/util/swrite.cc index b59e99888..6f38f032c 100644 --- a/src/util/swrite.cc +++ b/src/util/swrite.cc @@ -36,12 +36,12 @@ #include "swrite.h" -int swrite( int fd, const char *str, ssize_t len ) { +int swrite( int fd, const char* str, ssize_t len ) +{ ssize_t total_bytes_written = 0; ssize_t bytes_to_write = ( len >= 0 ) ? len : (ssize_t)strlen( str ); while ( total_bytes_written < bytes_to_write ) { - ssize_t bytes_written = write( fd, str + total_bytes_written, - bytes_to_write - total_bytes_written ); + ssize_t bytes_written = write( fd, str + total_bytes_written, bytes_to_write - total_bytes_written ); if ( bytes_written <= 0 ) { perror( "write" ); return -1; diff --git a/src/util/swrite.h b/src/util/swrite.h index e75bf7ed3..74d65ed36 100644 --- a/src/util/swrite.h +++ b/src/util/swrite.h @@ -33,6 +33,6 @@ #ifndef SWRITE_HPP #define SWRITE_HPP -int swrite( int fd, const char *str, ssize_t len = -1 ); +int swrite( int fd, const char* str, ssize_t len = -1 ); #endif diff --git a/src/util/timestamp.cc b/src/util/timestamp.cc index 1ffd3b328..c871b87a6 100644 --- a/src/util/timestamp.cc +++ b/src/util/timestamp.cc @@ -60,7 +60,8 @@ static uint64_t millis_cache = -1; -uint64_t frozen_timestamp( void ) { +uint64_t frozen_timestamp( void ) +{ if ( millis_cache == uint64_t( -1 ) ) { freeze_timestamp(); } @@ -68,7 +69,8 @@ uint64_t frozen_timestamp( void ) { return millis_cache; } -void freeze_timestamp( void ) { +void freeze_timestamp( void ) +{ // Try all our clock sources till we get something. This could // break if a source only sometimes works in a given process. #if HAVE_CLOCK_GETTIME @@ -78,10 +80,10 @@ void freeze_timestamp( void ) { if ( #if defined( __APPLE__ ) && defined( __MACH__ ) - // Check for presence, for OS X SDK >= 10.12 and runtime < 10.12 - &clock_gettime != NULL && + // Check for presence, for OS X SDK >= 10.12 and runtime < 10.12 + &clock_gettime != NULL && #endif - clock_gettime( CLOCKTYPE, &tp ) == 0 ) { + clock_gettime( CLOCKTYPE, &tp ) == 0 ) { uint64_t millis = tp.tv_nsec / 1000000; millis += uint64_t( tp.tv_sec ) * 1000;