]> WPIA git - cassiopeia.git/blob - src/io/record.cpp
97e601549428b26a4de512e3deba1e7d711a2926
[cassiopeia.git] / src / io / record.cpp
1 #include "record.h"
2
3 #include <iomanip>
4 #include <iostream>
5 #include <memory>
6 #include <sstream>
7
8 #include "io/bios.h"
9 #include "io/opensslBIO.h"
10 #include "log/logger.hpp"
11
12 std::string toHexAndChecksum( const std::string& src ) {
13     char checksum = 0;
14     std::stringstream ss;
15     ss << ':' << std::hex << std::setfill( '0' ) << std::uppercase;
16
17     for( auto c : src ) {
18         ss << std::setw( 2 ) << ( ( ( uint32_t ) c ) & 0xFF );
19         checksum += c;
20     }
21
22     ss << std::setw( 2 ) << ( ( ( uint32_t )( ~checksum ) ) & 0xFF );
23     ss << '\n';
24     return ss.str();
25 }
26
27 void sendCommand( RecordHeader& head, const std::string& data, std::shared_ptr<OpensslBIO> bio ) {
28     std::stringstream ss;
29     ss << data.size();
30     logger::debugf( "Record payload length: %s", ss.str() ); 
31     if(data.size() > 0xFFFF){
32         logger::warn( "Data too big, need chunking" );
33     }
34     head.payloadLength = data.size();
35     std::string s;
36     s += head.packToString();
37     s += data;
38
39     std::string res = toHexAndChecksum( s );
40
41     logger::debug( "FINE: RECORD output: ", res );
42
43     bio->write( res.data(), res.size() );
44 }
45
46 int32_t fromHexDigit( char c ) {
47     int32_t res = -1;
48
49     if( c >= '0' && c <= '9' ) {
50         res = c - '0';
51     }
52
53     if( c >= 'A' && c <= 'F' ) {
54         res = c - 'A' + 10;
55     }
56
57     return res;
58 }
59
60 std::string parseCommand( RecordHeader& head, const std::string& input) {
61     logger::debug( "FINE: RECORD input: ", input );
62
63     int32_t dlen = ( input.size() - 2 ) / 2;
64     char checksum = 0;
65     bool error = false;
66
67     std::string str( std::max( dlen, RECORD_HEADER_SIZE ), 0 );
68
69     for( int i = 0; i < dlen; i++ ) {
70         int32_t digit;
71         int32_t accum;
72         digit = fromHexDigit( input[i * 2 + 1] );
73         error |= digit == -1;
74         accum = digit;
75         accum <<= 4;
76         digit = fromHexDigit( input[i * 2 + 2] );
77         error |= digit == -1;
78         accum += digit;
79         str[i] = accum;
80         checksum += str[i];
81     }
82
83     head.unpackFromString( str.substr( 0, RECORD_HEADER_SIZE ) );
84     uint32_t len = head.payloadLength;
85     uint32_t expectedTotalLength = ( RECORD_HEADER_SIZE + len + 1 /*checksum*/ ) * 2 + 2;
86     std::string data = str.substr( RECORD_HEADER_SIZE, str.size() - RECORD_HEADER_SIZE );
87
88     if( expectedTotalLength != input.size() ) {
89         std::stringstream ss;
90         ss << "Expected: " << expectedTotalLength << ", Got: " << input.size();
91         logger::error( ss.str() );
92         throw "Error, invalid length";
93     }
94     if( checksum != -1 || error || dlen < RECORD_HEADER_SIZE ) {
95         throw "Error, invalid checksum";
96     }
97
98     data.pop_back();
99
100     return data;
101 }
102
103 /*
104 int main( int argc, char* argv[] ) {
105     OpensslBIOWrapper *bio = new OpensslBIOWrapper(BIO_new_fd(0, 0));
106     std::string data = "halloPayload";
107     RecordHeader head;
108     head.command = 0x7;
109     head.flags = 1;
110     head.sessid = 13;
111     head.command_count = 0xA0B;
112     head.totalLength = 9;
113     sendCommand( head, data, std::shared_ptr<OpensslBIO>(bio) );
114     head.command = 0x8;
115
116     try {
117         std::string c = parseCommand( head, ":0700010D0000000B0A0900000000000C0068616C6C6F5061796C6F6164E6\n" );
118
119         std::cout << "res: " << std::endl;
120         std::cout << head.payloadLength << std::endl;
121         std::cout << c << std::endl;
122     } catch( char const* c ) {
123         std::cout << "err: " << c << std::endl;
124     }
125
126
127     return 0;
128 }
129 */