9 #include "io/opensslBIO.h"
10 #include "log/logger.hpp"
12 std::string toHexAndChecksum( const std::string& src ) {
15 ss << ':' << std::hex << std::setfill( '0' ) << std::uppercase;
18 ss << std::setw( 2 ) << ( ( ( uint32_t ) c ) & 0xFF );
22 ss << std::setw( 2 ) << ( ( ( uint32_t )( ~checksum ) ) & 0xFF );
27 void sendCommand( RecordHeader& head, const std::string& data, std::shared_ptr<OpensslBIO> bio ) {
30 logger::debugf( "Record payload length: %s", ss.str() );
33 head.totalLength = data.size();
36 size_t toTransfer = std::min( static_cast<size_t>( 0xF000 ), data.size() - pos );
37 head.payloadLength = toTransfer;
40 s += head.packToString();
41 s += data.substr( pos, toTransfer );
43 std::string res = toHexAndChecksum( s );
45 logger::debug( "FINE: RECORD output: ", res );
47 bio->write( res.data(), res.size() );
51 } while( pos < data.size() );
54 int32_t fromHexDigit( char c ) {
57 if( c >= '0' && c <= '9' ) {
61 if( c >= 'A' && c <= 'F' ) {
68 std::string parseCommand( RecordHeader& head, const std::string& input ) {
69 logger::debug( "FINE: RECORD input: ", input );
71 int32_t dlen = ( input.size() - 2 ) / 2;
75 std::string str( std::max( dlen, RECORD_HEADER_SIZE ), 0 );
77 for( int i = 0; i < dlen; i++ ) {
80 digit = fromHexDigit( input[i * 2 + 1] );
84 digit = fromHexDigit( input[i * 2 + 2] );
91 head.unpackFromString( str.substr( 0, RECORD_HEADER_SIZE ) );
92 uint32_t len = head.payloadLength;
93 uint32_t expectedTotalLength = ( RECORD_HEADER_SIZE + len + 1 /*checksum*/ ) * 2 + 2;
94 std::string data = str.substr( RECORD_HEADER_SIZE, str.size() - RECORD_HEADER_SIZE );
96 if( expectedTotalLength != input.size() ) {
98 ss << "Expected: " << expectedTotalLength << ", Got: " << input.size();
99 logger::error( ss.str() );
100 throw std::length_error( "Error, invalid length" );
103 if( checksum != -1 || error || dlen < RECORD_HEADER_SIZE ) {
104 throw std::runtime_error( "Error, invalid checksum" );
111 std::string parseCommandChunked( RecordHeader& head, std::shared_ptr<OpensslBIOWrapper> io ) {
112 logger::note( "reading" );
113 std::string payload = parseCommand( head, io->readLine() );
114 std::string all( head.totalLength, ' ' );
115 auto target = all.begin();
120 pos += head.payloadLength;
121 target = std::copy( payload.begin(), payload.end(), target );
123 if( pos >= head.totalLength ) {
127 logger::note( "chunk digested, reading next one" );
129 payload = parseCommand( head2, io->readLine() );
131 if( !head2.isFollowupOf( head ) ) {
132 throw std::runtime_error( "Error, header of follow up chunk was malformed" );