Last active
August 29, 2015 14:15
-
-
Save aleksihakli/a586facc1b6bfede0c78 to your computer and use it in GitHub Desktop.
Custom and very naíve packet composition example of a C++ network programming exercise
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef BUFFER_HH | |
#define BUFFER_HH | |
// Variadic template (C++11) std::string bufferer | |
#include <string> | |
#include <sstream> | |
namespace { | |
void _buffer(const std::stringstream&) {} | |
template <typename H, typename... T> | |
void _buffer(std::stringstream& sbuffer, H head, T... tail) { | |
sbuffer << head; | |
_buffer(sbuffer, tail...); | |
} | |
} // anonymous namespace | |
void buffer(const std::string& str); | |
template <typename... L> | |
std::string buffer(L... list) { | |
std::stringstream sbuffer; | |
_buffer(sbuffer, list...); | |
return sbuffer.str(); | |
} | |
#endif // BUFFER_HH |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef PACKET_HH | |
#define PACKET_HH | |
// Naive UDP packet construct for an URL checking service for an exercise | |
#include <cassert> | |
#include <string> | |
#include <algorithm> | |
#include "buffer.hh" | |
// All LEN_* lengths are in bytes | |
const size_t LEN_REQUEST_MIN = 16; | |
const size_t LEN_REQUEST_MAX = 2000; | |
const size_t LEN_VERSION = 1; | |
const size_t LEN_DIRECTION = 1; | |
const size_t LEN_PACKET_LENGTH = 1; | |
const size_t LEN_SID = 1; | |
const size_t LEN_TID = 1; | |
const size_t LEN_URLLEN = 1; | |
const size_t LEN_MACLEN = 2; | |
const std::string PACKET_SERVER_ID = "S"; // packet is going to a server | |
std::string HMAC_SHA256(const std::string& contents) { | |
return contents; // just for a dummy placeholder, use imagination | |
} | |
struct UDPURLRequest { | |
std::string version; // protocol version | |
std::string direction; // network or client | |
std::string length; // whole package length | |
std::string SID; // some arbitrary session ID | |
std::string TID; // some arbitrary timestamp | |
std::string urllen; // URL length | |
std::string URL; // varying length | |
std::string maclen; // checksum length | |
std::string checksum; // varying length | |
UDPURLRequest () { } | |
UDPURLRequest (const std::string& version | |
, const std::string& SID | |
, const std::string& TID | |
, const std::string& URL) | |
: version(version) | |
, direction(PACKET_SERVER_ID) | |
, SID(SID) | |
, TID(TID) | |
, URL(URL) | |
{ | |
} | |
// Convert struct contents into a string for sending over network | |
// TODO: Endianness should be converted to Network Byte Order before sending | |
std::string tostr () { | |
// Length is fields 1-7 and doesn't include MAC data | |
length = std::to_string(LEN_VERSION + LEN_DIRECTION + LEN_PACKET_LENGTH | |
+ LEN_SID + LEN_TID + LEN_URLLEN + URL.length()); | |
urllen = std::to_string(URL.length()); | |
// Contents of fields 1-7 for checksum calculation | |
std::string contents = buffer(version, direction, length, SID, TID, urllen, URL); | |
checksum = HMAC_SHA256(contents); | |
maclen = std::to_string(checksum.length()); | |
// Actual string representation of the whole package | |
// TODO: Convert to Network Byte Order | |
std::string str = db::buffer(contents, maclen, checksum); | |
assert(str.length() >= LEN_REQUEST_MIN); | |
assert(str.length() <= LEN_REQUEST_MAX); | |
return str; | |
} | |
// Write struct contents into given buffer in Network Byte Order | |
// char* buf size shall be at least 2000 bytes. | |
void write (char* buf) { | |
std::string payload(tostr()); | |
std::copy(payload.begin(), payload.end(), buf); | |
}; | |
}; | |
#endif // PACKET_HH |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment