<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def proxy_protocol(self, error='raise', default=None, limit=None, authenticate=False):
 """ Parses, and optionally authenticates, proxy protocol information from request. Note that ``self.request`` is wrapped by ``SocketBuffer``. :param error: How read (``exc.ReadError``) and parse (``exc.ParseError``) errors are handled. One of: - "raise" to propagate. - "unread" to suppress exceptions and unread back to socket. :param default: What to return when no ``ProxyInfo`` was found. Only meaningful with error "unread". :param limit: Maximum number of bytes to read when probing request for ``ProxyInfo``. :returns: Parsed ``ProxyInfo`` instance or **default** if none found. """

        if error not in ('raise', 'unread'):
            raise ValueError('error="{0}" is not  "raise" or "unread""')
        if not isinstance(self.request, SocketBuffer):
            self.request = SocketBuffer(self.request)
        if default == 'peer':
            default = ProxyInfo(
                self.client_address[0], self.client_address[1],
                self.client_address[0], self.client_address[1],
            )
        try:
            line = read_line(
                self.request.sock,
                self.request.buf,
                limit=limit,
            )
        except exc.ReadError:
            if error == 'raise':
                raise
            return default
        try:
            info = parse_line(line)
        except exc.ParseError:
            if error == 'raise':
                raise
            self.request.unread(line)
            return default
        if authenticate and not self.proxy_authenticate(info):
            logger.info('authentication failed - %s', info)
            return default
        return info