'Parse a bytestring as a full PROXY protocol header line.
@param line: A bytestring that represents a valid HAProxy PROXY
protocol header line.
@type line: bytes
@return: A L{_interfaces.IProxyInfo} containing the parsed data.
@raises InvalidProxyHeader: If the bytestring does not represent a
valid PROXY header.
@raises InvalidNetworkProtocol: When no protocol can be parsed or is
not one of the allowed values.
@raises MissingAddressData: When the protocol is TCP* but the header
does not contain a complete set of addresses and ports.'

@classmethod
def parse(cls, line):

    originalLine = line
    proxyStr = None
    networkProtocol = None
    sourceAddr = None
    sourcePort = None
    destAddr = None
    destPort = None
    with convertError(ValueError, InvalidProxyHeader):
        (proxyStr, line) = line.split('    ', 1)
    if (proxyStr != cls.PROXYSTR):
        raise InvalidProxyHeader()
    with convertError(ValueError, InvalidNetworkProtocol):
        (networkProtocol, line) = line.split('    ', 1)
    if (networkProtocol not in cls.ALLOWED_NET_PROTOS):
        raise InvalidNetworkProtocol()
    if (networkProtocol == cls.UNKNOWN_PROTO):
        return _info.ProxyInfo(originalLine, None, None)
    with convertError(ValueError, MissingAddressData):
        (sourceAddr, line) = line.split('    ', 1)
    with convertError(ValueError, MissingAddressData):
        (destAddr, line) = line.split('    ', 1)
    with convertError(ValueError, MissingAddressData):
        (sourcePort, line) = line.split('    ', 1)
    with convertError(ValueError, MissingAddressData):
        destPort = line.split('    ')[0]
    if (networkProtocol == cls.TCP4_PROTO):
        return _info.ProxyInfo(originalLine, address.IPv4Address('TCP', sourceAddr, int(sourcePort)), address.IPv4Address('TCP', destAddr, int(destPort)))
    return _info.ProxyInfo(originalLine, address.IPv6Address('TCP', sourceAddr, int(sourcePort)), address.IPv6Address('TCP', destAddr, int(destPort)))
