Skip to content

Instantly share code, notes, and snippets.

@aleksihakli
Last active August 29, 2015 14:15
Show Gist options
  • Save aleksihakli/a586facc1b6bfede0c78 to your computer and use it in GitHub Desktop.
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
#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
#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