def _recv_predicate(self, predicate, timeout='default', raise_eof=True):
        """
        Receive until predicate returns a positive integer.
        The returned number is the size to return.
        """

        if timeout == 'default':
            timeout = self._timeout

        self.timed_out = False

        start = time.time()
        try:
            while True:
                cut_at = predicate(self.buf)
                if cut_at > 0:
                    break
                if timeout is not None:
                    time_elapsed = time.time() - start
                    if time_elapsed > timeout:
                        raise socket.timeout
                    self._settimeout(timeout - time_elapsed)

                data = self._recv(4096)
                self._log_recv(data, False)
                self.buf += data

                if not data:
                    if raise_eof:
                        raise NetcatError("Connection dropped!")
                    cut_at = len(self.buf)
                    break

        except KeyboardInterrupt:
            self._print_header('\n======== Connection interrupted! ========')
            raise
        except socket.timeout:
            self.timed_out = True
            if self._raise_timeout:
                raise NetcatTimeout()
            return b''
        except socket.error as exc:
            raise NetcatError('Socket error: %r' % exc)

        self._settimeout(self._timeout)

        ret = self.buf[:cut_at]
        self.buf = self.buf[cut_at:]
        self._log_recv(ret, True)
        return ret
Receive until predicate returns a positive integer.
        The returned number is the size to return.