7 #include "log/logger.hpp"
9 #define BUFFER_SIZE 8192
11 #define SLIP_ESCAPE_CHAR ( (char) 0xDB)
12 #define SLIP_PACKET ( (char) 0xC0)
14 char hexDigit( char c ) {
30 std::string toHex( const char* buf, int len ) {
31 std::string data = "000000";
33 for( int i = 0; i < len; i++ ) {
34 data.append( 1, ' ' );
35 data.append( 1, hexDigit( ( buf[i] >> 4 ) & 0xF ) );
36 data.append( 1, hexDigit( buf[i] & 0xF ) );
42 SlipBIO::SlipBIO() : buffer( std::vector<char>( BUFFER_SIZE ) ), decodeTarget( 0 ), decodePos( 0 ), rawPos( 0 ), failed( false ) {
45 void SlipBIO::setTarget( std::shared_ptr<OpensslBIO> target ) {
46 this->target = target;
49 SlipBIO::SlipBIO( std::shared_ptr<OpensslBIO> target ) : target( target ), buffer( std::vector<char>( BUFFER_SIZE ) ), decodeTarget( 0 ), decodePos( 0 ), rawPos( 0 ), failed( false ) {
52 SlipBIO::~SlipBIO() {}
54 int SlipBIO::write( const char* buf, int num ) {
56 logger::debug( "Out: " << toHex( buf, num ) );
61 for( int i = 0; i < num; i++ ) {
62 if( ( buf[i] == SLIP_PACKET ) || ( buf[i] == SLIP_ESCAPE_CHAR ) ) {
67 int totalLen = num + badOnes + 1; // 2
68 char* targetPtr = ( char* ) malloc( totalLen );
74 std::shared_ptr<char> t = std::shared_ptr<char>( targetPtr, free );
77 for( int i = 0; i < num; i++ ) {
78 if( buf[i] == SLIP_PACKET ) {
79 targetPtr[j++] = SLIP_ESCAPE_CHAR;
80 targetPtr[j++] = ( char )0xDC;
81 } else if( buf[i] == SLIP_ESCAPE_CHAR ) {
82 targetPtr[j++] = SLIP_ESCAPE_CHAR;
83 targetPtr[j++] = ( char )0xDD;
85 targetPtr[j++] = buf[i];
89 targetPtr[j++] = SLIP_PACKET;
95 int dlen = target->write( targetPtr + sent, std::min( 1024, j - sent ) );
98 throw "Error, target write failed";
99 } else if( dlen == 0 ) {
114 int SlipBIO::read( char* buf, int size ) {
115 // while we have no data to decode or unmasking does not yield a full package
116 while( !packageLeft && ( decodePos >= rawPos || !unmask() ) ) {
118 // we have no data, read more
119 if( buffer.size() - rawPos < 64 ) {
120 // not enough space... package is too big
125 int len = target->read( buffer.data() + rawPos, buffer.capacity() - rawPos );
138 int len = std::min( decodeTarget, ( unsigned int ) size );
139 // a package finished, return it
140 std::copy( buffer.data(), buffer.data() + len, buf );
141 // move the buffer contents back
142 std::copy( buffer.data() + len, buffer.data() + decodeTarget, buffer.data() );
145 if( decodeTarget == 0 ) {
150 logger::debug( "in: " << toHex( buf, len ) );
156 long SlipBIO::ctrl( int cmod, long arg1, void* arg2 ) {
161 if( cmod == BIO_CTRL_RESET ) {
162 char resetSequence[] = {SLIP_ESCAPE_CHAR, 0, SLIP_PACKET};
163 target->write( resetSequence, 3 );
167 logger::note( "Resetting SLIP layer" );
171 return target->ctrl( cmod, arg1, arg2 );
174 const char* SlipBIO::getName() {
178 bool SlipBIO::unmask() {
179 unsigned int j = decodeTarget;
181 for( unsigned int i = decodePos; i < rawPos; i++ ) {
182 if( buffer[i] == SLIP_ESCAPE_CHAR ) {
187 buffer[decodeTarget] = buffer[i - 1];
188 decodePos = decodeTarget;
189 rawPos = decodePos + 1;
190 return 0;// no packet
191 } else if( buffer[i] == ( char )0xdc ) {
192 buffer[j++] = SLIP_PACKET;
193 } else if( buffer[i] == ( char )0xdd ) {
194 buffer[j++] = SLIP_ESCAPE_CHAR;
195 } else if( buffer[i] == SLIP_PACKET ) {
205 } else if( buffer[i] == SLIP_PACKET ) {
209 // copy rest to bufferfer i to len
217 buffer[j++] = buffer[i];