123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- #ifndef COVERTPROTOCOLBIDIRECTIONAL_H
- #define COVERTPROTOCOLBIDIRECTIONAL_H
- #include <fstream>
- #include <iostream>
- #include <string>
- #include <type_traits>
- #include "CovertProtocol.hpp"
- /**
- * @class CovertProtocolBidirectional
- *
- * A bidirectional Covert Channel protocol with a variable size template.
- *
- * The protocol works bidirectional so the active side uses send to encode data to be sent and the passive side uses receive to extract data. And the passive
- * side uses send to send ACKs and and the active side uses receive to receive ACKs.
- *
- * @param N number of bytes which can be used to transmit data
- * @param PASSIVE passive mode
- */
- template <int N, bool PASSIVE> class CovertProtocolBidirectional {
- static_assert(N >= 2);
- public:
- /**
- * CovertProtocolBidirectional constructor
- */
- CovertProtocolBidirectional() : segment(PASSIVE ? 1 : 0) { lastData = new uint8_t[N](); }
- /**
- * CovertProtocol destructor
- */
- ~CovertProtocolBidirectional() { delete[](lastData); }
- /**
- * Starts sending a file.
- *
- * Starts sending a file if no transmission is running and the file exists.
- *
- * @param fileName name of the file in the file directory
- * @return true - file will be sent | false - file was not accepted
- */
- bool sendFile(const std::string &fileName) {
- if constexpr (PASSIVE) {
- return false;
- }
- return protocol.sendFile(fileName);
- }
- /**
- * send encodes the data into the data array
- *
- * @param data must be an array of size N
- */
- void send(uint8_t *const data) {
- if (sendSegment()) {
- std::memcpy(data, lastData, N);
- return;
- }
- if constexpr (!PASSIVE) {
- protocol.send(data + 1);
- }
- data[0] = (segment << 6);
- // save data to lastData
- std::memcpy(lastData, data, N);
- }
- /**
- * receive extracts data from the data array
- *
- * @param data must be an array of size N
- */
- void receive(const uint8_t *const data) {
- uint8_t seg = data[0] >> 6;
- std::cerr << "segment: " << (int)segment << "\tack: " << (int)lastACKedSegment << "\tseg: " << (int)seg << std::endl;
- if (receiveSegment(seg)) {
- return;
- }
- if constexpr (PASSIVE) {
- protocol.receive(data + 1);
- }
- }
- private:
- /**
- * current segment counter
- */
- uint8_t segment;
- /**
- * last acknowledged segment counter
- */
- uint8_t lastACKedSegment = 0;
- /**
- * lastData sent
- */
- uint8_t *lastData;
- /**
- * Simple protocol
- */
- CovertProtocol<N - 1, PASSIVE> protocol;
- /**
- * Evaluates received segment number and increases own segment number if necessary
- *
- * @param seg received segment number
- * @return true if segment should discarded
- */
- inline bool receiveSegment(uint8_t seg) {
- if constexpr (PASSIVE) {
- if (seg == segment && seg == increaseSegment(lastACKedSegment, 1)) {
- lastACKedSegment = seg;
- return false;
- } else {
- std::cerr << "Throwing this packet away" << std::endl;
- return true;
- }
- } else {
- if (seg == increaseSegment(segment, 1) && seg == increaseSegment(lastACKedSegment, 2)) {
- lastACKedSegment = increaseSegment(lastACKedSegment, 1);
- return false;
- } else {
- std::cerr << "Throwing this packet away" << std::endl;
- return true;
- }
- }
- }
- /**
- * Returns true if the segment should be repeated.
- *
- * @return true if segment should be repeated
- */
- inline bool sendSegment() {
- if (segment == lastACKedSegment) {
- segment = increaseSegment(segment, 1);
- return false;
- } else {
- return true;
- }
- }
- /**
- * Calculates seg + inc
- * @return seg + inc
- */
- inline uint8_t increaseSegment(uint8_t seg, uint8_t inc) { return seg + inc & 0x3; }
- };
- #endif
|