#include "proxyp/Elements.h"
#include "sbuf/Stream.h"
+#include <algorithm>
#include <limits>
+#include <vector>
-const ProxyProtocol::FieldMap ProxyProtocol::PseudoHeaderFields = {
- { SBuf(":version"), ProxyProtocol::Two::htPseudoVersion },
- { SBuf(":command"), ProxyProtocol::Two::htPseudoCommand },
- { SBuf(":src_addr"), ProxyProtocol::Two::htPseudoSrcAddr },
- { SBuf(":dst_addr"), ProxyProtocol::Two::htPseudoDstAddr },
- { SBuf(":src_port"), ProxyProtocol::Two::htPseudoSrcPort },
- { SBuf(":dst_port"), ProxyProtocol::Two::htPseudoDstPort }
+namespace ProxyProtocol {
+namespace Two {
+
+/// a mapping between pseudo header names and ids
+typedef std::vector< std::pair<SBuf, FieldType> > FieldMap;
+static const FieldMap PseudoHeaderFields = {
+ { SBuf(":version"), htPseudoVersion },
+ { SBuf(":command"), htPseudoCommand },
+ { SBuf(":src_addr"), htPseudoSrcAddr },
+ { SBuf(":dst_addr"), htPseudoDstAddr },
+ { SBuf(":src_port"), htPseudoSrcPort },
+ { SBuf(":dst_port"), htPseudoDstPort }
};
-namespace ProxyProtocol {
+} // namespace Two
+
static Two::FieldType NameToFieldType(const SBuf &);
static Two::FieldType IntegerToFieldType(const SBuf &);
+
} // namespace ProxyProtocol
+const SBuf &
+ProxyProtocol::PseudoFieldTypeToFieldName(const Two::FieldType fieldType)
+{
+ const auto it = std::find_if(Two::PseudoHeaderFields.begin(), Two::PseudoHeaderFields.end(),
+ [fieldType](const Two::FieldMap::value_type &item) {
+ return item.second == fieldType;
+ });
+
+ assert(it != Two::PseudoHeaderFields.end());
+ return it->first;
+}
+
/// FieldNameToFieldType() helper that handles pseudo headers
ProxyProtocol::Two::FieldType
ProxyProtocol::NameToFieldType(const SBuf &name)
{
- const auto it = PseudoHeaderFields.find(name);
- if (it != PseudoHeaderFields.end())
+ const auto it = std::find_if(Two::PseudoHeaderFields.begin(), Two::PseudoHeaderFields.end(),
+ [&name](const Two::FieldMap::value_type &item) {
+ return item.first == name;
+ });
+
+ if (it != Two::PseudoHeaderFields.end())
return it->second;
static const SBuf pseudoMark(":");
// IDs for PROXY protocol header pseudo-headers.
// Larger than 255 to avoid clashes with possible TLV type IDs.
- htPseudoVersion = 0x101,
- htPseudoCommand = 0x102,
- htPseudoSrcAddr = 0x103,
- htPseudoDstAddr = 0x104,
- htPseudoSrcPort = 0x105,
- htPseudoDstPort = 0x106
+ htPseudoBegin = 0x101, // smallest pseudo-header value (for iteration)
+ htPseudoVersion,
+ htPseudoCommand,
+ htPseudoSrcAddr,
+ htPseudoDstAddr,
+ htPseudoSrcPort,
+ htPseudoDstPort,
+ htPseudoEnd // largest pseudo-header value plus 1 (for iteration)
} FieldType;
/// PROXY protocol 'command' field value
} // namespace Two
-typedef std::map<SBuf, Two::FieldType> FieldMap;
-/// a mapping between pseudo header names and ids
-extern const FieldMap PseudoHeaderFields;
+/// \returns human-friendly PROXY protocol field name for the given field type
+/// from the [htPseudoBegin,htPseudoEnd) range
+const SBuf &PseudoFieldTypeToFieldName(const Two::FieldType);
/// Parses human-friendly PROXY protocol field type representation.
/// Only pseudo headers can (and should) be represented by their names.
*/
#include "squid.h"
+#include "base/EnumIterator.h"
#include "proxyp/Elements.h"
#include "proxyp/Header.h"
#include "sbuf/Stream.h"
ProxyProtocol::Header::toMime() const
{
SBufStream result;
- for (const auto &p: PseudoHeaderFields) {
- const auto value = getValues(p.second);
+ for (const auto fieldType: EnumRange(Two::htPseudoBegin, Two::htPseudoEnd)) {
+ const auto value = getValues(fieldType);
if (!value.isEmpty())
- result << p.first << ": " << value << "\r\n";
+ result << PseudoFieldTypeToFieldName(fieldType) << ": " << value << "\r\n";
}
// cannot reuse Header::getValues(): need the original TLVs layout
for (const auto &tlv: tlvs)