Files
xahaud/modules/ripple_app/network/ripple_ProxyHandshake.h
2013-07-31 16:43:25 -07:00

152 lines
3.5 KiB
C++

//------------------------------------------------------------------------------
/*
Copyright (c) 2011-2013, OpenCoin, Inc.
*/
//==============================================================================
#ifndef RIPPLE_PROXYYHANDSHAKE_H_INCLUDED
#define RIPPLE_PROXYYHANDSHAKE_H_INCLUDED
/** PROXY protocol handshake state machine.
The PROXY Protocol:
http://haproxy.1wt.eu/download/1.5/doc/proxy-protocol.txt
*/
class ProxyHandshake
{
public:
/** Status of the handshake state machine. */
enum Status
{
statusNone, // No handshake expected
statusHandshake, // Handshake in progress
statusFailed, // Handshake failed
statusOk, // Handshake succeeded
};
enum Proto
{
protoTcp4,
protoTcp6,
protoUnknown
};
/** PROXY information for IPv4 families. */
struct IPv4
{
struct Addr
{
int a;
int b;
int c;
int d;
bool chop (String& input);
};
Addr sourceAddr;
Addr destAddr;
int sourcePort;
int destPort;
};
/** PROXY information for IPv6 families. */
struct IPv6
{
struct Addr
{
int a;
int b;
int c;
int d;
};
Addr sourceAddr;
Addr destAddr;
int sourcePort;
int destPort;
};
/** Fully decoded PROXY information. */
struct Endpoints
{
Endpoints ()
: proto (protoUnknown)
{
}
Proto proto;
IPv4 ipv4; // valid if proto == protoTcp4
IPv6 ipv6; // valid if proto == protoTcp6;
};
//--------------------------------------------------------------------------
/** Parser for PROXY version 1. */
struct Version1
{
enum
{
// Maximum input buffer size needed, including a null
// terminator, as per the PROXY protocol specification.
maxBufferBytes = 108
};
Endpoints endpoints;
Version1 ();
/** Parse the header.
@param rawHeader a pointer to the header data
@return `true` If it was parsed successfully.
*/
bool parse (void const* headerData, size_t headerBytes);
};
//--------------------------------------------------------------------------
/** Create the handshake state.
If a handshake is expected, then it is required.
@param wantHandshake `false` to skip handshaking.
*/
explicit ProxyHandshake (bool expectHandshake = false);
~ProxyHandshake ();
inline Status getStatus () const noexcept
{
return m_status;
}
inline Endpoints const& getEndpoints () const noexcept
{
return m_endpoints;
};
/** Feed the handshaking state engine.
@return The number of bytes consumed in the input buffer.
*/
std::size_t feed (void const* inputBuffer, std::size_t inputBytes);
// Utility functions used by parsers
static int indexOfFirstNonNumber (String const& input);
static bool chop (String const& what, String& input);
static bool chopUInt (int* value, int limit, String& input);
private:
void parseLine ();
private:
enum
{
maxVersion1Bytes = 107 // including crlf, not including null term
};
Status m_status;
String m_buffer;
bool m_gotCR;
Endpoints m_endpoints;
};
#endif