aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/Twisted/py2/twisted/protocols/haproxy/_v2parser.py
diff options
context:
space:
mode:
authorshmel1k <shmel1k@ydb.tech>2023-11-26 18:16:14 +0300
committershmel1k <shmel1k@ydb.tech>2023-11-26 18:43:30 +0300
commitb8cf9e88f4c5c64d9406af533d8948deb050d695 (patch)
tree218eb61fb3c3b96ec08b4d8cdfef383104a87d63 /contrib/python/Twisted/py2/twisted/protocols/haproxy/_v2parser.py
parent523f645a83a0ec97a0332dbc3863bb354c92a328 (diff)
downloadydb-b8cf9e88f4c5c64d9406af533d8948deb050d695.tar.gz
add kikimr_configure
Diffstat (limited to 'contrib/python/Twisted/py2/twisted/protocols/haproxy/_v2parser.py')
-rw-r--r--contrib/python/Twisted/py2/twisted/protocols/haproxy/_v2parser.py215
1 files changed, 215 insertions, 0 deletions
diff --git a/contrib/python/Twisted/py2/twisted/protocols/haproxy/_v2parser.py b/contrib/python/Twisted/py2/twisted/protocols/haproxy/_v2parser.py
new file mode 100644
index 0000000000..94c495ffe2
--- /dev/null
+++ b/contrib/python/Twisted/py2/twisted/protocols/haproxy/_v2parser.py
@@ -0,0 +1,215 @@
+# -*- test-case-name: twisted.protocols.haproxy.test.test_v2parser -*-
+
+# Copyright (c) Twisted Matrix Laboratories.
+# See LICENSE for details.
+
+"""
+IProxyParser implementation for version two of the PROXY protocol.
+"""
+
+import binascii
+import struct
+
+from constantly import Values, ValueConstant
+
+from zope.interface import implementer
+from twisted.internet import address
+from twisted.python import compat
+
+from ._exceptions import (
+ convertError, InvalidProxyHeader, InvalidNetworkProtocol,
+ MissingAddressData
+)
+from . import _info
+from . import _interfaces
+
+class NetFamily(Values):
+ """
+ Values for the 'family' field.
+ """
+ UNSPEC = ValueConstant(0x00)
+ INET = ValueConstant(0x10)
+ INET6 = ValueConstant(0x20)
+ UNIX = ValueConstant(0x30)
+
+
+
+class NetProtocol(Values):
+ """
+ Values for 'protocol' field.
+ """
+ UNSPEC = ValueConstant(0)
+ STREAM = ValueConstant(1)
+ DGRAM = ValueConstant(2)
+
+
+_HIGH = 0b11110000
+_LOW = 0b00001111
+_LOCALCOMMAND = 'LOCAL'
+_PROXYCOMMAND = 'PROXY'
+
+@implementer(_interfaces.IProxyParser)
+class V2Parser(object):
+ """
+ PROXY protocol version two header parser.
+
+ Version two of the PROXY protocol is a binary format.
+ """
+
+ PREFIX = b'\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A'
+ VERSIONS = [32]
+ COMMANDS = {0: _LOCALCOMMAND, 1: _PROXYCOMMAND}
+ ADDRESSFORMATS = {
+ # TCP4
+ 17: '!4s4s2H',
+ 18: '!4s4s2H',
+ # TCP6
+ 33: '!16s16s2H',
+ 34: '!16s16s2H',
+ # UNIX
+ 49: '!108s108s',
+ 50: '!108s108s',
+ }
+
+ def __init__(self):
+ self.buffer = b''
+
+
+ def feed(self, data):
+ """
+ Consume a chunk of data and attempt to parse it.
+
+ @param data: A bytestring.
+ @type data: bytes
+
+ @return: A two-tuple containing, in order, a L{_interfaces.IProxyInfo}
+ and any bytes fed to the parser that followed the end of the
+ header. Both of these values are None until a complete header is
+ parsed.
+
+ @raises InvalidProxyHeader: If the bytes fed to the parser create an
+ invalid PROXY header.
+ """
+ self.buffer += data
+ if len(self.buffer) < 16:
+ raise InvalidProxyHeader()
+
+ size = struct.unpack('!H', self.buffer[14:16])[0] + 16
+ if len(self.buffer) < size:
+ return (None, None)
+
+ header, remaining = self.buffer[:size], self.buffer[size:]
+ self.buffer = b''
+ info = self.parse(header)
+ return (info, remaining)
+
+
+ @staticmethod
+ def _bytesToIPv4(bytestring):
+ """
+ Convert packed 32-bit IPv4 address bytes into a dotted-quad ASCII bytes
+ representation of that address.
+
+ @param bytestring: 4 octets representing an IPv4 address.
+ @type bytestring: L{bytes}
+
+ @return: a dotted-quad notation IPv4 address.
+ @rtype: L{bytes}
+ """
+ return b'.'.join(
+ ('%i' % (ord(b),)).encode('ascii')
+ for b in compat.iterbytes(bytestring)
+ )
+
+
+ @staticmethod
+ def _bytesToIPv6(bytestring):
+ """
+ Convert packed 128-bit IPv6 address bytes into a colon-separated ASCII
+ bytes representation of that address.
+
+ @param bytestring: 16 octets representing an IPv6 address.
+ @type bytestring: L{bytes}
+
+ @return: a dotted-quad notation IPv6 address.
+ @rtype: L{bytes}
+ """
+ hexString = binascii.b2a_hex(bytestring)
+ return b':'.join(
+ ('%x' % (int(hexString[b:b+4], 16),)).encode('ascii')
+ for b in range(0, 32, 4)
+ )
+
+
+ @classmethod
+ def parse(cls, line):
+ """
+ Parse a bytestring as a full PROXY protocol header.
+
+ @param line: A bytestring that represents a valid HAProxy PROXY
+ protocol version 2 header.
+ @type line: bytes
+
+ @return: A L{_interfaces.IProxyInfo} containing the
+ parsed data.
+
+ @raises InvalidProxyHeader: If the bytestring does not represent a
+ valid PROXY header.
+ """
+ prefix = line[:12]
+ addrInfo = None
+ with convertError(IndexError, InvalidProxyHeader):
+ # Use single value slices to ensure bytestring values are returned
+ # instead of int in PY3.
+ versionCommand = ord(line[12:13])
+ familyProto = ord(line[13:14])
+
+ if prefix != cls.PREFIX:
+ raise InvalidProxyHeader()
+
+ version, command = versionCommand & _HIGH, versionCommand & _LOW
+ if version not in cls.VERSIONS or command not in cls.COMMANDS:
+ raise InvalidProxyHeader()
+
+ if cls.COMMANDS[command] == _LOCALCOMMAND:
+ return _info.ProxyInfo(line, None, None)
+
+ family, netproto = familyProto & _HIGH, familyProto & _LOW
+ with convertError(ValueError, InvalidNetworkProtocol):
+ family = NetFamily.lookupByValue(family)
+ netproto = NetProtocol.lookupByValue(netproto)
+ if (
+ family is NetFamily.UNSPEC or
+ netproto is NetProtocol.UNSPEC
+ ):
+ return _info.ProxyInfo(line, None, None)
+
+ addressFormat = cls.ADDRESSFORMATS[familyProto]
+ addrInfo = line[16:16+struct.calcsize(addressFormat)]
+ if family is NetFamily.UNIX:
+ with convertError(struct.error, MissingAddressData):
+ source, dest = struct.unpack(addressFormat, addrInfo)
+ return _info.ProxyInfo(
+ line,
+ address.UNIXAddress(source.rstrip(b'\x00')),
+ address.UNIXAddress(dest.rstrip(b'\x00')),
+ )
+
+ addrType = 'TCP'
+ if netproto is NetProtocol.DGRAM:
+ addrType = 'UDP'
+ addrCls = address.IPv4Address
+ addrParser = cls._bytesToIPv4
+ if family is NetFamily.INET6:
+ addrCls = address.IPv6Address
+ addrParser = cls._bytesToIPv6
+
+ with convertError(struct.error, MissingAddressData):
+ info = struct.unpack(addressFormat, addrInfo)
+ source, dest, sPort, dPort = info
+
+ return _info.ProxyInfo(
+ line,
+ addrCls(addrType, addrParser(source), sPort),
+ addrCls(addrType, addrParser(dest), dPort),
+ )