📄 marshal.h
字号:
#ifndef CLASS_MARSHAL#define CLASS_MARSHAL#include <assert.h>#include <stdint.h>#include <stdlib.h>#include <stdio.h>#include <netinet/in.h>#include <sys/param.h>#include <vector>#include <map>#include <openssl/md5.h>#include "Common.h"class RingSet; // Need ot have forward declaration of ringset for infopacketuint32_t marshalHashName(char* in_name); //#define MAGIC_NUMBER 0x0A0B0C0D#define STRINGIFY(A) # A#define INDIRECT(A) STRINGIFY(A)#define MAGIC_NUMBER marshalHashName(INDIRECT(APPNAME))#define MAX_UDP_PACKET_SIZE 1400#define REQ_CONSTRAINT_N_TCP 1#define REQ_CLOSEST_N_TCP 2#define REQ_MEASURE_N_TCP 3#define REQ_CLOSEST_N_MERID_PING 4#define REQ_MEASURE_N_MERID_PING 5#define REQ_CLOSEST_N_DNS 6#define REQ_MEASURE_N_DNS 7//#define RET_MEASURE_N 8#define RET_RESPONSE 9#define GOSSIP 10#define PUSH 11#define PULL 12#define RET_PING_REQ 13#define PING 14#define PONG 15#define CREATE_RENDV 16#define RET_RENDV 17#define RET_ERROR 18#define RET_INFO 19#define REQ_CONSTRAINT_N_DNS 20#define REQ_CONSTRAINT_N_PING 21#define INFO_PACKET 22#define GOSSIP_PULL 23#ifdef MERIDIAN_DSL#define DSL_REQUEST 24#define DSL_REPLY 25#endif#ifdef PLANET_LAB_SUPPORT#define REQ_MEASURE_N_ICMP 26#define REQ_CLOSEST_N_ICMP 27#define REQ_CONSTRAINT_N_ICMP 28#endifclass BufferWrapper {private: bool errorFlag; const char* buf; int bufSize; int counter; public: BufferWrapper(const char* in_buf, int in_buf_size) : errorFlag(false), buf(in_buf), bufSize(in_buf_size), counter(0) {} char retrieve_char() { if (!errorFlag && ((counter + (int)sizeof(char)) <= bufSize)) { return buf[counter++]; } errorFlag = true; return 0; } const char* retrieve_buf(int in_buf_size) { if (!errorFlag && (in_buf_size >= 0) && ((counter + in_buf_size) <= bufSize)) { const char* retVal = buf + counter; counter += in_buf_size; return retVal; } errorFlag = true; return 0; } uint16_t retrieve_ushort() { if (!errorFlag && ((counter + (int)sizeof(uint16_t)) <= bufSize)) { uint16_t retVal; memcpy(&retVal, buf + counter, sizeof(uint16_t)); counter += sizeof(uint16_t); return retVal; } errorFlag = true; return 0; } uint32_t retrieve_uint() { if (!errorFlag && ((counter + (int)sizeof(uint32_t)) <= bufSize)) { uint32_t retVal; memcpy(&retVal, buf + counter, sizeof(uint32_t)); counter += sizeof(uint32_t); return retVal; } errorFlag = true; return 0; } int32_t retrieve_int() { if (!errorFlag && ((counter + (int)sizeof(int32_t)) <= bufSize)) { int32_t retVal; memcpy(&retVal, buf + counter, sizeof(int32_t)); counter += sizeof(int32_t); return retVal; } errorFlag = true; return 0; } uint32_t remainBufSize() { assert(bufSize >= counter); return (bufSize - counter); } uint32_t returnPos() { return counter; } bool error() { return errorFlag; } };typedef struct NodeIdent_t { uint32_t addr; uint16_t port;} NodeIdent;// Used in GOSSIPtypedef struct NodeIdentRendv_t { uint32_t addr; uint16_t port; uint32_t addrRendv; uint32_t portRendv; } NodeIdentRendv;typedef struct NodeIdentConst_t { uint32_t addr; uint16_t port; uint32_t latencyConstMS;} NodeIdentConst;typedef struct NodeIdentLat_t { uint32_t addr; uint16_t port; uint32_t latencyUS;} NodeIdentLat;typedef struct MeasuredResult_t { uint32_t addr; uint16_t port; uint32_t latencyUS;} MeasuredResult;struct ltNodeIdent { bool operator()(NodeIdent s1, NodeIdent s2) const { if ((s1.addr < s2.addr) || ((s1.addr == s2.addr) && (s1.port < s2.port))) { return true; } return false; }};struct ltNodeIdentConst { bool operator()(NodeIdentConst s1, NodeIdentConst s2) const { if ((s1.addr < s2.addr) || ((s1.addr == s2.addr) && (s1.port < s2.port))) { return true; } return false; }};struct ltNodeIdentRendv { bool operator()(NodeIdentRendv s1, NodeIdentRendv s2) const { if ((s1.addr < s2.addr) || ((s1.addr == s2.addr) && (s1.port < s2.port))) { return true; } return false; }};class RealPacket {private: char* packet; // Payload int size; // Payload size bool complete; // Determines rather packet complete NodeIdentRendv dest; uint32_t maxPacketSize; int pos; bool verifySpace(int typeSize) const { if ((uint32_t)(size + typeSize) > maxPacketSize) return false; return true; } public: RealPacket(const NodeIdentRendv& in_dest, uint32_t packetSize) : size(0), complete(true), dest(in_dest), maxPacketSize(packetSize), pos(0) { packet = (char*) malloc(sizeof(char) * maxPacketSize); } RealPacket(const NodeIdentRendv& in_dest) : size(0), complete(true), dest(in_dest), maxPacketSize(MAX_UDP_PACKET_SIZE), pos(0) { packet = (char*) malloc(sizeof(char) * maxPacketSize); } RealPacket(const NodeIdent& in_dest) : size(0), complete(true), maxPacketSize(MAX_UDP_PACKET_SIZE), pos(0) { dest.addr = in_dest.addr; dest.port = in_dest.port; dest.addrRendv = 0; dest.portRendv = 0; packet = (char*) malloc(sizeof(char) * maxPacketSize); } RealPacket(const NodeIdent& in_dest, uint32_t packetSize) : size(0), complete(true), maxPacketSize(packetSize), pos(0) { dest.addr = in_dest.addr; dest.port = in_dest.port; dest.addrRendv = 0; dest.portRendv = 0; packet = (char*) malloc(sizeof(char) * maxPacketSize); } ~RealPacket() { if (packet) free(packet); } int getPos() const { return pos; } void incrPos(int val) { if (val > 0) pos += val; } int getPacketSize() const { return maxPacketSize; } uint16_t getPort() const { return dest.port; } uint32_t getAddr() const { return dest.addr; } uint16_t getRendvPort() const { return dest.portRendv; } uint32_t getRendvAddr() const { return dest.addrRendv; } char* getPayLoad() const { return packet; } int getPayLoadSize() const { return size; } bool completeOkay() const { return complete; } void setPayLoadSize(int val) { if (!complete) return; if (val < 0 || ((uint32_t)val) > maxPacketSize) { complete = false; } else { size = val; } } void append_int(int32_t value) { if (!complete) return; // Already failed once if ((complete = verifySpace(sizeof(value)))) { memcpy(packet + size, &value, sizeof(int32_t)); size += sizeof(int32_t); } } void append_uint(uint32_t value) { if (!complete) return; // Already failed once if ((complete = verifySpace(sizeof(value)))) { memcpy(packet + size, &value, sizeof(uint32_t)); size += sizeof(uint32_t); } } void append_ushort(uint16_t value) { if (!complete) return; // Already failed once if ((complete = verifySpace(sizeof(value)))) { memcpy(packet + size, &value, sizeof(uint16_t)); size += sizeof(uint16_t); } } void append_char(char value) { if (!complete) return; // Already failed once if ((complete = verifySpace(sizeof(value)))) { packet[size] = value; size += sizeof(char); } } void append_str(const char* in_str, int in_size) { if (!complete || in_size <= 0) return; if ((complete = verifySpace(in_size))) { memcpy(packet + size, in_str, in_size); size += in_size; } } void append_packet(const RealPacket& in_packet) { int in_size = in_packet.getPayLoadSize(); if (!complete || in_size <= 0) return; if ((complete = verifySpace(in_size))) { memcpy(packet + size, in_packet.getPayLoad(), in_size); size += in_size; } } };class Packet {private: uint32_t req_id_1; uint32_t req_id_2;public: static uint64_t to64(uint32_t id_1, uint32_t id_2) { uint64_t tmp = id_1; tmp = tmp << 32; tmp |= id_2; return tmp; } static void to32(uint64_t id, uint32_t* id_1, uint32_t* id_2) { *id_1 = id >> 32; *id_2 = id & 0xFFFFFFFF; } // Explicitly specify firewall Packet(uint64_t id) { to32(id, &req_id_1, &req_id_2); } // Return request id uint64_t retReqID() const { return to64(req_id_1, req_id_2); } // Append id to RealPacket void write_id(RealPacket& inPacket) const { inPacket.append_uint(htonl(req_id_1)); inPacket.append_uint(htonl(req_id_2)); inPacket.append_uint(htonl(MAGIC_NUMBER)); } static int parseHeader( BufferWrapper& rb, char* queryType, uint64_t* queryID) { *queryType = rb.retrieve_char(); uint32_t queryID_1 = ntohl(rb.retrieve_uint()); uint32_t queryID_2 = ntohl(rb.retrieve_uint()); *queryID = to64(queryID_1, queryID_2); uint32_t magicNumber = ntohl(rb.retrieve_uint()); if (rb.error()) { return -1; } if (magicNumber != MAGIC_NUMBER) { return -1; // Cannot be correct packet } return 0; // Normal packet } virtual int createRealPacket(RealPacket& inPacket) const = 0; virtual char getPacketType() const = 0; virtual ~Packet() {}};class RendvHeaderPacket : public Packet {private: uint32_t rendv_addr; uint16_t rendv_port;public: // Explicitly specify firewall RendvHeaderPacket(uint64_t id, uint32_t in_rendv_addr, uint16_t in_rendv_port) : Packet(id), rendv_addr(in_rendv_addr), rendv_port(in_rendv_port) {} // Get rendavous address and port uint32_t getRendvAddr() const { return rendv_addr; } uint16_t getRendvPort() const { return rendv_port; } // Write header into RealPacket void write_rendv(RealPacket& inPacket) const { inPacket.append_uint(htonl(rendv_addr)); inPacket.append_ushort(htons(rendv_port)); } virtual ~RendvHeaderPacket() {}};class ReqGeneric : public RendvHeaderPacket {protected: vector<NodeIdent> targets; public: ReqGeneric(uint64_t id, uint32_t in_rendv_addr, uint16_t in_rendv_port) : RendvHeaderPacket(id, in_rendv_addr, in_rendv_port) {} template <class T> static ReqGeneric* parse(const char* buf, int numBytes) { BufferWrapper rb(buf, numBytes); char queryType = rb.retrieve_char(); if (rb.error() || queryType != T::type()) { ERROR_LOG("Wrong type received\n"); return NULL; } uint32_t queryID_1 = ntohl(rb.retrieve_uint()); uint32_t queryID_2 = ntohl(rb.retrieve_uint()); uint64_t queryID = to64(queryID_1, queryID_2); uint32_t magicNumber = ntohl(rb.retrieve_uint()); uint32_t rendvAddr = ntohl(rb.retrieve_uint()); uint16_t rendvPort = ntohs(rb.retrieve_ushort()); if (rb.error() || magicNumber != MAGIC_NUMBER) { ERROR_LOG("Wrong magic number in packet received\n"); return NULL; } ReqGeneric* ret = new T(queryID, rendvAddr, rendvPort); uint32_t numEntry = ntohl(rb.retrieve_uint()); NodeIdent tmpIdent; //while (!rb.error() && numEntry-- > 0) { for (uint32_t i = 0; (!rb.error() && i < numEntry); i++) { tmpIdent.addr = ntohl(rb.retrieve_uint()); tmpIdent.port = ntohs(rb.retrieve_ushort()); ret->addTarget(tmpIdent); } if (rb.error()) { delete ret; return NULL; } return ret; } virtual int createRealPacket(RealPacket& inPacket) const { uint32_t num_targets = targets.size(); if (num_targets == 0) { return -1; } inPacket.append_char(getPacketType()); write_id(inPacket); write_rendv(inPacket); inPacket.append_uint(htonl(num_targets)); for (uint32_t i = 0; i < num_targets; i++) { NodeIdent tmp = targets[i]; inPacket.append_uint(htonl(tmp.addr)); inPacket.append_ushort(htons(tmp.port)); } if (!inPacket.completeOkay()) { return -1; } return 0; } void addTarget(const NodeIdent& in_node) { targets.push_back(in_node); } const vector<NodeIdent>* returnTargets() { return &targets; } virtual char getPacketType() const = 0; virtual ~ReqGeneric() {} };// Destination cannot be behind firewallclass ReqMeasurePing : public ReqGeneric {public: ReqMeasurePing(uint64_t id, uint32_t in_rendv_addr, uint16_t in_rendv_port) : ReqGeneric(id, in_rendv_addr, in_rendv_port) {} template <class T> static ReqGeneric* parse(const char* buf, int numBytes) { assert(false); return NULL; } static char type() { return REQ_MEASURE_N_MERID_PING; } virtual char getPacketType() const { return type(); } virtual ~ReqMeasurePing() {} };// Destination cannot be behind firewallclass ReqMeasureTCP : public ReqGeneric {public: ReqMeasureTCP(uint64_t id, uint32_t in_rendv_addr, uint16_t in_rendv_port) : ReqGeneric(id, in_rendv_addr, in_rendv_port) {} template <class T> static ReqGeneric* parse(const char* buf, int numBytes) { assert(false); return NULL; } static char type() { return REQ_MEASURE_N_TCP; } virtual char getPacketType() const { return type(); } virtual ~ReqMeasureTCP() {} };// Destination cannot be behind firewallclass ReqMeasureDNS : public ReqGeneric {public: ReqMeasureDNS(uint64_t id, uint32_t in_rendv_addr, uint16_t in_rendv_port) : ReqGeneric(id, in_rendv_addr, in_rendv_port) {} template <class T> static ReqGeneric* parse(const char* buf, int numBytes) { assert(false); return NULL; } static char type() { return REQ_MEASURE_N_DNS; } virtual char getPacketType() const { return type(); } virtual ~ReqMeasureDNS() {} };#ifdef PLANET_LAB_SUPPORT// Destination cannot be behind firewallclass ReqMeasureICMP : public ReqGeneric {public: ReqMeasureICMP(uint64_t id, uint32_t in_rendv_addr, uint16_t in_rendv_port) : ReqGeneric(id, in_rendv_addr, in_rendv_port) {} template <class T> static ReqGeneric* parse(const char* buf, int numBytes) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -