--- /dev/null
+#include "slipBio.h"
+
+#include <iostream>
+
+char hexDigit( char c ) {
+ if( c < 0 ) {
+ return 'x';
+ }
+
+ if( c < 10 ) {
+ return '0' + c;
+ }
+
+ if( c < 16 ) {
+ return 'A' + c - 10;
+ }
+
+ return 'x';
+}
+
+std::string toHex( const char* buf, int len ) {
+ char* c = ( char* ) malloc( len * 2 );
+
+ if( !c ) {
+ return "<malloc fail>";
+ }
+
+ std::shared_ptr<char> mem = std::shared_ptr<char>( c, free );
+
+ for( int i = 0; i < len; i++ ) {
+ c[i * 2] = hexDigit( ( buf[i] >> 4 ) & 0xF );
+ c[i * 2 + 1] = hexDigit( buf[i] & 0xF );
+ }
+
+ return std::string( mem.get(), len * 2 );
+}
+
+SlipBIO::SlipBIO( std::shared_ptr<OpensslBIO> target ) {
+ this->target = target;
+
+ this->buffer = std::vector<char>( 4096 );
+ this->decodeTarget = 0;
+ this->decodePos = 0;
+ this->rawPos = 0;
+
+ this->failed = false;
+}
+
+SlipBIO::~SlipBIO() {}
+
+int SlipBIO::write( const char* buf, int num ) {
+ int badOnes = 0;
+
+ for( int i = 0; i < num; i++ ) {
+ if( ( buf[i] == ( char )0xc0 ) || ( buf[i] == ( char )0xDB ) ) {
+ badOnes++;
+ }
+ }
+
+ int totalLen = num + badOnes + 2;
+ char* targetPtr = ( char* ) malloc( totalLen );
+
+ if( !targetPtr ) {
+ return -1;
+ }
+
+ std::shared_ptr<char> t = std::shared_ptr<char>( targetPtr, free );
+ int j = 0;
+ targetPtr[j++] = ( char )0xC0;
+
+ for( int i = 0; i < num; i++ ) {
+ if( buf[i] == ( char )0xc0 ) {
+ targetPtr[j++] = ( char )0xDB;
+ targetPtr[j++] = ( char )0xDC;
+ } else if( buf[i] == ( char )0xDB ) {
+ targetPtr[j++] = ( char )0xDB;
+ targetPtr[j++] = ( char )0xDD;
+ } else {
+ targetPtr[j++] = buf[i];
+ }
+ }
+
+ targetPtr[j++] = ( char )0xC0;
+
+ if( target->write( targetPtr, j ) != j ) {
+ throw "Error, target write failed";
+ }
+
+ std::cout << toHex( targetPtr, j ) << std::endl;
+ return num;
+}
+
+int SlipBIO::read( char* buf, int size ) {
+ if( ( unsigned int ) size < buffer.capacity() ) {
+ // fail...
+ }
+
+ // while we have no data to decode or unmasking does not yield a full package
+ while( decodePos >= rawPos || !unmask() ) {
+
+ // we have no data, read more
+ if( buffer.size() - rawPos < 64 ) {
+ // not enough space... package is too big
+ decodeTarget = 0;
+ failed = true;
+ }
+
+ int len = target->read( buffer.data() + rawPos, buffer.capacity() - rawPos );
+
+ if( len > 0 ) {
+ rawPos += len;
+ } else {
+ decodeTarget = 0;
+ failed = true;
+ }
+
+ }
+
+ // a package finished, return it
+ std::copy( buffer.data(), buffer.data() + decodeTarget, buf );
+ // move the buffer contents back
+
+ int len = decodeTarget;
+ decodeTarget = 0;
+
+ return len;
+}
+
+long SlipBIO::ctrl( int cmod, long arg1, void* arg2 ) {
+ ( void ) cmod;
+ ( void ) arg1;
+ ( void ) arg2;
+
+ return 0;
+}
+
+const char* SlipBIO::getName() {
+ return "SlipBIO";
+}
+
+bool SlipBIO::unmask() {
+ unsigned int j = decodeTarget;
+
+ for( unsigned int i = decodePos; i < rawPos; i++ ) {
+ if( buffer[i] == ( char ) 0xDB ) {
+ i++;
+
+ if( i >= rawPos ) {
+ decodeTarget = j;
+ buffer[decodeTarget] = buffer[i - 1];
+ decodePos = decodeTarget;
+ rawPos = decodePos + 1;
+ return 0;// no packet
+ } else if( buffer[i] == ( char )0xdc ) {
+ buffer[j++] = ( char ) 0xc0;
+ } else if( buffer[i] == ( char )0xdd ) {
+ buffer[j++] = ( char ) 0xdb;
+ } else {
+ decodeTarget = 0;
+ failed = true;
+ // failed package
+ // error
+ }
+ } else if( buffer[i] == ( char ) 0xc0 ) {
+ decodePos = i + 1;
+ decodeTarget = j;
+
+ // copy rest to bufferfer i to len
+ if( !failed ) {
+ return 1;
+ }
+
+ decodeTarget = 0;
+ failed = false;
+ } else {
+ buffer[j++] = buffer[i];
+ }
+ }
+
+ decodePos = j;
+ rawPos = j;
+ decodeTarget = j;
+
+ return 0;
+}
--- /dev/null
+#include <iostream>
+#include <cstring>
+
+#include <boost/test/unit_test.hpp>
+
+#include "bios.h"
+#include "slipBio.h"
+
+class OpensslBIOVector : public OpensslBIO {
+private:
+ std::vector<std::vector<char>>::iterator it, end;
+ std::vector<std::vector<char>> input;
+
+public:
+ std::vector<std::vector<char>> result = std::vector<std::vector<char>>();
+ OpensslBIOVector( std::vector<std::vector<char>> data ) {
+ input = data;
+ it = input.begin();
+ end = input.end();
+ }
+
+ int write( const char* buf, int num );
+ int read( char* buf, int size );
+ long ctrl( int cmod, long arg1, void* arg2 );
+
+ static const char* getName();
+};
+
+int OpensslBIOVector::write( const char* buf, int num ) {
+ result.push_back( std::vector<char>( buf, buf + num ) );
+ return num;
+}
+
+int OpensslBIOVector::read( char* buf, int size ) {
+ if( it == end ) {
+ return -1;
+ }
+
+ if( ( unsigned int ) size < it->size() ) {
+ throw "Error, to small buffer";
+ }
+
+ std::copy( it->begin(), it->end(), buf );
+ auto result = it->size();
+ it++;
+ return result;
+}
+
+long OpensslBIOVector::ctrl( int cmod, long arg1, void* arg2 ) {
+ ( void ) cmod;
+ ( void ) arg1;
+ ( void ) arg2;
+ return 0;
+}
+
+const char* OpensslBIOVector::getName() {
+ return "dummyBIO";
+}
+
+BOOST_AUTO_TEST_SUITE( TestSLIPBioWrapper )
+
+BOOST_AUTO_TEST_CASE( TestMockup ) {
+ std::vector<std::vector<char>> source = {{1, 2}, {1, 2, 3}, {1, 2, 3, 4}, {1, 2, 3, 4, 5}};
+
+ OpensslBIOVector* data = new OpensslBIOVector( source );
+
+ char buf[4096];
+
+ for( auto it = source.begin(); it != source.end(); it++ ) {
+ auto len = data->read( buf, sizeof( buf ) );
+ BOOST_CHECK_EQUAL( len, it->size() );
+ BOOST_CHECK_EQUAL_COLLECTIONS( buf, buf + len, it->begin(), it->end() );
+ BOOST_CHECK_EQUAL( data->write( buf, len ), len );
+ }
+
+ BOOST_CHECK_EQUAL( data->read( buf, sizeof( buf ) ), -1 );
+
+ for( unsigned int i = 0; i < source.size(); i++ ) {
+ BOOST_CHECK_EQUAL_COLLECTIONS( data->result[i].begin(), data->result[i].end(), source[i].begin(), source[i].end() );
+ }
+
+ delete data;
+}
+
+BOOST_AUTO_TEST_CASE( TestSLIP ) {
+ std::vector<std::vector<char>> source = { {1, 2, 3, 4, 5, ( char ) 0xc0, 1, ( char ) 0xc0}, {1, 2}, {( char ) 0xc0}, {1, ( char ) 0xdb}, {( char ) 0xdc}, {( char ) 0xc0, ( char )0xdb}, {( char ) 0xdd, 2}, {( char ) 0xc0}};
+ std::shared_ptr<OpensslBIOVector> data = std::shared_ptr<OpensslBIOVector>( new OpensslBIOVector( source ) );
+ char buf[4096];
+ SlipBIO* slip = new SlipBIO( data );
+ int res = slip->read( buf, sizeof( buf ) );
+ BOOST_CHECK_EQUAL( res, 5 );
+ res = slip->read( buf, sizeof( buf ) );
+ BOOST_CHECK_EQUAL( res, 1 );
+ res = slip->read( buf, sizeof( buf ) );
+ BOOST_CHECK_EQUAL( res, 2 );
+
+ res = slip->read( buf, sizeof( buf ) );
+ BOOST_CHECK_EQUAL( res, 2 );
+ char res2[] = {1, ( char ) 0xc0};
+ BOOST_CHECK_EQUAL_COLLECTIONS( buf, buf + 2, res2, res2 + 2 );
+
+ res = slip->read( buf, sizeof( buf ) );
+ BOOST_CHECK_EQUAL( res, 2 );
+ char res3[] = {( char ) 0xdb, 2};
+ BOOST_CHECK_EQUAL_COLLECTIONS( buf, buf + 2, res3, res3 + 2 );
+}
+
+BOOST_AUTO_TEST_SUITE_END()