1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
//
// protocol.hpp
// ~~~~~~~~~~~~
//
// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef PORTHOPPER_PROTOCOL_HPP
#define PORTHOPPER_PROTOCOL_HPP
#include <boost/array.hpp>
#include <boost/asio.hpp>
#include <cstring>
#include <iomanip>
#include <string>
#include <strstream>
// This request is sent by the client to the server over a TCP connection.
// The client uses it to perform three functions:
// - To request that data start being sent to a given port.
// - To request that data is no longer sent to a given port.
// - To change the target port to another.
class control_request
{
public:
// Construct an empty request. Used when receiving.
control_request()
{
}
// Create a request to start sending data to a given port.
static const control_request start(unsigned short port)
{
return control_request(0, port);
}
// Create a request to stop sending data to a given port.
static const control_request stop(unsigned short port)
{
return control_request(port, 0);
}
// Create a request to change the port that data is sent to.
static const control_request change(
unsigned short old_port, unsigned short new_port)
{
return control_request(old_port, new_port);
}
// Get the old port. Returns 0 for start requests.
unsigned short old_port() const
{
std::istrstream is(data_, encoded_port_size);
unsigned short port = 0;
is >> std::setw(encoded_port_size) >> std::hex >> port;
return port;
}
// Get the new port. Returns 0 for stop requests.
unsigned short new_port() const
{
std::istrstream is(data_ + encoded_port_size, encoded_port_size);
unsigned short port = 0;
is >> std::setw(encoded_port_size) >> std::hex >> port;
return port;
}
// Obtain buffers for reading from or writing to a socket.
boost::array<boost::asio::mutable_buffer, 1> to_buffers()
{
boost::array<boost::asio::mutable_buffer, 1> buffers
= { { boost::asio::buffer(data_) } };
return buffers;
}
private:
// Construct with specified old and new ports.
control_request(unsigned short old_port_number,
unsigned short new_port_number)
{
std::ostrstream os(data_, control_request_size);
os << std::setw(encoded_port_size) << std::hex << old_port_number;
os << std::setw(encoded_port_size) << std::hex << new_port_number;
}
// The length in bytes of a control_request and its components.
enum
{
encoded_port_size = 4, // 16-bit port in hex.
control_request_size = encoded_port_size * 2
};
// The encoded request data.
char data_[control_request_size];
};
// This frame is sent from the server to subscribed clients over UDP.
class frame
{
public:
// The maximum allowable length of the payload.
enum { payload_size = 32 };
// Construct an empty frame. Used when receiving.
frame()
{
}
// Construct a frame with specified frame number and payload.
frame(unsigned long frame_number, const std::string& payload_data)
{
std::ostrstream os(data_, frame_size);
os << std::setw(encoded_number_size) << std::hex << frame_number;
os << std::setw(payload_size)
<< std::setfill(' ') << payload_data.substr(0, payload_size);
}
// Get the frame number.
unsigned long number() const
{
std::istrstream is(data_, encoded_number_size);
unsigned long frame_number = 0;
is >> std::setw(encoded_number_size) >> std::hex >> frame_number;
return frame_number;
}
// Get the payload data.
const std::string payload() const
{
return std::string(data_ + encoded_number_size, payload_size);
}
// Obtain buffers for reading from or writing to a socket.
boost::array<boost::asio::mutable_buffer, 1> to_buffers()
{
boost::array<boost::asio::mutable_buffer, 1> buffers
= { { boost::asio::buffer(data_) } };
return buffers;
}
private:
// The length in bytes of a frame and its components.
enum
{
encoded_number_size = 8, // Frame number in hex.
frame_size = encoded_number_size + payload_size
};
// The encoded frame data.
char data_[frame_size];
};
#endif // PORTHOPPER_PROTOCOL_HPP
|