Proxy.C
1
2//
3// Copyright (c) 2025, Isode Limited, London, England.
4// All rights reserved.
5//
6// Acquisition and use of this software and related materials for any
7// purpose requires a written licence agreement from Isode
8// Limited, or a written licence from an organisation licenced by Isode
9// Limited to grant such a licence.
10//
11
12#include <event/lib/Proxy.h>
13#include <cctype>
14
15namespace Stream {
16 // These are utilities for implementing the PROXY protocol,
17 // https://github.com/haproxy/haproxy/blob/master/doc/proxy-protocol.txt
18
19 bool read_ipv4(string_iter& start, const string_iter end, std::uint32_t& addr)
20 {
21 auto p(start);
22 while (p != end && (std::isdigit(*p) || '.' == *p)) {
23 ++p;
24 }
25 if (!(p == end || ' ' == *p)) {
26 return false;
27 }
28 std::string tmp(start, p);
29 int r = inet_pton(AF_INET, tmp.c_str(), &addr);
30 if (1 == r) {
31 start = (p == end) ? p : p+1;
32 return true;
33 }
34 return false;
35 }
36
37 bool read_ipv6(string_iter& start, const string_iter end, in6_addr & addr)
38 {
39 auto p(start);
40 while (p != end && (std::isdigit(*p) || ':' == *p || ('a' <= *p && 'f' >= *p) ||
41 ('A' <= *p && 'F' >= *p))) {
42 ++p;
43 }
44 if (!(p == end || ' ' == *p)) {
45 return false;
46 }
47 std::string tmp(start, p);
48 int r = inet_pton(AF_INET6, tmp.c_str(), &addr);
49 if (1 == r) {
50 start = (p == end) ? p : p+1;
51 return true;
52 }
53 return false;
54 }
55
56 bool read_port(string_iter& start, string_iter end, std::uint16_t& port)
57 {
58 auto p(start);
59 bool in_digits = false;
60 while (p != end && isdigit(*p)) {
61 in_digits = true;
62 ++p;
63 }
64 if (!in_digits) {
65 return false;
66 }
67 if (!(p == end || ' ' == *p)) {
68 return false;
69 }
70 const std::string port_str(start, p);
71 if (port_str.length() > 5) {
72 return false;
73 }
74 auto port_int = std::atoi(port_str.c_str());
75 if (port_int > 65535) {
76 return false;
77 }
78 port = port_int;
79 start = (p == end) ? p : p+1;
80 return true;
81 }
82
83 bool read_proxy_ipv4(const std::string& addr, ipv4_addr& proxy_header)
84 {
85 auto end(addr.end());
86 auto p(addr.begin());
87 if (!read_ipv4(p, end, proxy_header.src_addr)) {
88 return false;
89 }
90 if (!read_ipv4(p, end, proxy_header.dst_addr)) {
91 return false;
92 }
93 if (!read_port(p, end, proxy_header.src_port)) {
94 return false;
95 }
96 if (!read_port(p, end, proxy_header.dst_port)) {
97 return false;
98 }
99 return true;
100 }
101
102 bool read_proxy_ipv6(const std::string& addr, ipv6_addr& proxy_header)
103 {
104 auto end(addr.end());
105 auto p(addr.begin());
106 if (!read_ipv6(p, end, proxy_header.src_addr)) {
107 return false;
108 }
109 if (!read_ipv6(p, end, proxy_header.dst_addr)) {
110 return false;
111 }
112 if (!read_port(p, end, proxy_header.src_port)) {
113 return false;
114 }
115 if (!read_port(p, end, proxy_header.dst_port)) {
116 return false;
117 }
118 return true;
119 }
120}
Interface between a user of a stream and the provider of a stream.

All rights reserved © 2002 - 2024 Isode Ltd.