Exemplo n.º 1
0
    def _validate_cert(self):
        """internal method to validate the peer's SSL certificate, and to check the
    commonName of the certificate to ensure it matches the hostname we
    used to make this connection.  Does not support subjectAltName records
    in certificates.

    raises TTransportException if the certificate fails validation.
    """
        cert = self.handle.getpeercert()
        self.peercert = cert
        if 'subject' not in cert:
            raise TTransportException(
                type=TTransportException.NOT_OPEN,
                message='No SSL certificate found from %s:%s' %
                (self.host, self.port))
        fields = cert['subject']
        for field in fields:
            # ensure structure we get back is what we expect
            if not isinstance(field, tuple):
                continue
            cert_pair = field[0]
            if len(cert_pair) < 2:
                continue
            cert_key, cert_value = cert_pair[0:2]
            if cert_key != 'commonName':
                continue
            certhost = cert_value
            # this check should be performed by some sort of Access Manager
            if certhost == self.host:
                # success, cert commonName matches desired hostname
                self.is_valid = True
                return
            else:
                raise TTransportException(
                    type=TTransportException.UNKNOWN,
                    message=
                    'Hostname we connected to "%s" doesn\'t match certificate '
                    'provided commonName "%s"' % (self.host, certhost))
        raise TTransportException(
            type=TTransportException.UNKNOWN,
            message='Could not validate SSL certificate from '
            'host "%s".  Cert=%s' % (self.host, cert))
Exemplo n.º 2
0
 def open(self):
     super(TSSLSocket, self).open()
     if self._should_verify:
         self.peercert = self.handle.getpeercert()
         try:
             self._validate_callback(self.peercert, self._server_hostname)
             self.is_valid = True
         except TTransportException:
             raise
         except Exception as ex:
             raise TTransportException(TTransportException.UNKNOWN, str(ex))
Exemplo n.º 3
0
    def read(self, sz):
        if not self.is_open():
            raise TTransportException(type=TTransportException.NOT_OPEN,
                                      message='Called read on non-open pipe')
        buff = None
        err = None
        try:
            (err, buff) = win32file.ReadFile(self._handle, sz, None)
        except Exception as e:
            raise TTransportException(type=TTransportException.UNKNOWN,
                                      message='TPipe read failed')

        if err:
            raise TTransportException(
                type=TTransportException.UNKNOWN,
                message='TPipe read failed with GLE={}'.format(err))
        if len(buff) == 0:
            raise TTransportException(type=TTransportException.END_OF_FILE,
                                      message='TPipe read 0 bytes')
        return buff
Exemplo n.º 4
0
 def _checkReturnCode(retcode):
     if retcode == -1:
         errcode = WSAGetLastError()
         if errcode == WSAECONNREFUSED:
             # This error will be returned when Edenfs is not running
             raise TTransportException(type=TTransportException.NOT_OPEN,
                                       message="eden not running")
         elif errcode == WSAETIMEDOUT:
             raise socket.timeout()
         else:
             raise WindowsSocketException(errcode)
Exemplo n.º 5
0
 def test_request_flush_exception(self):
     ctx = FContext("fooid")
     frame = utils.mock_frame(ctx)
     e = TTransportException(type=TTransportExceptionType.END_OF_FILE,
                             message="oh no!")
     transport = FAsyncTransportImpl(e=e)
     with self.assertRaises(TTransportException) as cm:
         yield transport.request(ctx, frame)
     self.assertEqual(e, cm.exception)
     self.assertEqual(0, len(transport._futures))
     self.assertEqual(frame, transport._payload)
Exemplo n.º 6
0
    def open(self):
        if not self.transport.isOpen():
            self.transport.open()

        self.send_sasl_msg(self.START, self.sasl.mechanism)
        self.send_sasl_msg(self.OK, self.sasl.process())

        while True:
            status, challenge = self.recv_sasl_msg()
            if status == self.OK:
                self.send_sasl_msg(self.OK, self.sasl.process(challenge))
            elif status == self.COMPLETE:
                if not self.sasl.complete:
                    raise TTransportException("The server erroneously indicated "
                            "that SASL negotiation was complete")
                else:
                    break
            else:
                raise TTransportException("Bad SASL negotiation status: %d (%s)"
                        % (status, challenge))
Exemplo n.º 7
0
 def _validate_cert(self):
     cert = self.handle.getpeercert()
     self.peercert = cert
     if 'subject' not in cert:
         raise TTransportException(
             type=TTransportException.NOT_OPEN,
             message='No SSL certificate found from %s:%s' %
             (self.host, self.port))
     try:
         self._match_hostname(cert, self.host)
         self.is_valid = True
         return
     except CertificateError as ce:
         raise TTransportException(
             type=TTransportException.UNKNOWN,
             message='Certificate error with remote host: %s' % (ce))
     raise TTransportException(
         type=TTransportException.UNKNOWN,
         message='Could not validate SSL certificate from '
         'host "%s".  Cert=%s' % (self.host, cert))
Exemplo n.º 8
0
 def _do_open(self, family, socktype):
     plain_sock = socket.socket(family, socktype)
     try:
         return self._wrap_socket(plain_sock)
     except Exception as ex:
         plain_sock.close()
         msg = 'failed to initialize SSL'
         logger.exception(msg)
         raise TTransportException(type=TTransportException.NOT_OPEN,
                                   message=msg,
                                   inner=ex)
Exemplo n.º 9
0
    async def subscribe(self, topic: str, callback):
        if not self._nats_client.is_connected:
            raise TTransportException(TTransportExceptionType.NOT_OPEN,
                                      'Nats is not connected')
        if self.is_subscribed():
            raise TTransportException(TTransportExceptionType.ALREADY_OPEN,
                                      'Already subscribed to nats topic')

        async def nats_callback(message):
            ret = callback(TMemoryBuffer(message.data[4:]))
            if inspect.iscoroutine(ret):
                ret = await ret
            return ret

        self._sub_id = await self._nats_client.subscribe(
            'frugal.{0}'.format(topic),
            queue=self._queue,
            cb=nats_callback,
        )
        self._is_subscribed = True
Exemplo n.º 10
0
 def transform(self, buf):
     for trans_id in self.__write_transforms:
         if trans_id == TRANSFORM.ZLIB:
             buf = zlib.compress(buf)
         elif trans_id == TRANSFORM.SNAPPY:
             buf = snappy.compress(buf)
         else:
             raise TTransportException(
                 TTransportException.INVALID_TRANSFORM,
                 "Unknown transform during send")
     return buf
Exemplo n.º 11
0
    def connection(self):
        """Acquire a connection from the pool.

        This method is to be used with a context manager. It returns a
        connection from the pool, or blocks up to :attr:`timeout` seconds
        waiting for one if the pool is full and all connections are in use.

        When the context is exited, the connection is returned to the pool.
        However, if it was exited via an unexpected Thrift exception, the
        connection is closed instead because the state of the connection is
        unknown.

        """
        prot = self._acquire()
        try:
            yield prot
        except (TApplicationException, TProtocolException,
                TTransportException):
            # these exceptions usually indicate something low-level went wrong,
            # so it's safest to just close this connection because we don't
            # know what state it's in. the only other TException-derived errors
            # should be application level errors which should be safe for the
            # connection.
            prot.trans.close()
            raise
        except socket.timeout:
            # thrift doesn't re-wrap socket timeout errors appropriately so
            # we'll do it here for a saner exception hierarchy
            prot.trans.close()
            raise TTransportException(
                type=TTransportException.TIMED_OUT,
                message="timed out interacting with socket",
            )
        except socket.error as exc:
            prot.trans.close()
            raise TTransportException(
                type=TTransportException.UNKNOWN,
                message=str(exc),
            )
        finally:
            self._release(prot)
Exemplo n.º 12
0
def _urlfetch(url, body, validate_certificate, timeout, headers):
    from google.appengine.api import urlfetch
    from google.appengine.api.urlfetch_errors import DeadlineExceededError
    try:
        return urlfetch.fetch(url,
                              method=urlfetch.POST,
                              payload=body,
                              headers=headers,
                              validate_certificate=url.startswith('https://'),
                              deadline=timeout)
    except DeadlineExceededError:
        raise TTransportException(type=TTransportExceptionType.TIMED_OUT)
Exemplo n.º 13
0
    async def request(self, context: FContext, payload):
        self._preflight_request_check(payload)
        op_id = str(context._get_op_id())
        future = asyncio.Future()
        async with self._futures_lock:
            if op_id in self._futures:
                raise TTransportException(
                    type=TTransportExceptionType.UNKNOWN,
                    message="request already in flight for context")
            self._futures[op_id] = future

        try:
            with async_timeout.timeout(context.timeout / 1000):
                await self.flush(payload)
                return TMemoryBuffer(await future)
        except asyncio.TimeoutError:
            raise TTransportException(type=TTransportExceptionType.TIMED_OUT,
                                      message='request timed out') from None
        finally:
            async with self._futures_lock:
                del self._futures[op_id]
Exemplo n.º 14
0
 def protocol_id(self):
     if self._client_type == THeaderClientType.HEADERS:
         return self._protocol_id
     elif self._client_type in (THeaderClientType.FRAMED_BINARY, THeaderClientType.UNFRAMED_BINARY):
         return THeaderSubprotocolID.BINARY
     elif self._client_type in (THeaderClientType.FRAMED_COMPACT, THeaderClientType.UNFRAMED_COMPACT):
         return THeaderSubprotocolID.COMPACT
     else:
         raise TTransportException(
             TTransportException.INVALID_CLIENT_TYPE,
             "Protocol ID not know for client type %d" % self._client_type,
         )
 def __init__(self, host, port, proxy_host, proxy_port):
     TSocket.__init__(self, proxy_host, proxy_port)
     try:
         # Use IP address since sometimes proxy_host cannot resolve
         # external hostnames using unbound
         info = socket.getaddrinfo(host, None,
                                   socket.AF_INET | socket.AF_INET6,
                                   socket.SOCK_STREAM, socket.IPPROTO_TCP)
         self.remote_host = info[0][4][0]
     except socket.error as e:
         raise TTransportException(TTransportException.NOT_OPEN, str(e))
     self.remote_port = port
Exemplo n.º 16
0
    def open(self):
        try:
            addrs = self._resolveAddr()
            for addr in addrs:
                sock_family, sock_type, _, _, ip_port = addr
                plain_sock = socket.socket(sock_family, sock_type)
                self.handle = self._wrap_socket(plain_sock)
                self.handle.settimeout(self._timeout)
                try:
                    self.handle.connect(ip_port)
                except socket.error:
                    self.handle.close()
                    if addr is not addrs[-1]:
                        logger.warning(
                            'Error while connecting with %s. Trying next one.',
                            ip_port,
                            exc_info=True)
                        continue
                    else:
                        raise
                break
        except socket.error as e:
            if self._unix_socket:
                message = 'Could not connect to secure socket %s: %s' \
                          % (self._unix_socket, e)
            else:
                message = 'Could not connect to %s:%d: %s' \
                          % (self.host, self.port, e)
            logger.exception('Error while connecting with %s.', ip_port)
            raise TTransportException(TTransportException.NOT_OPEN, message)

        if self._should_verify:
            self.peercert = self.handle.getpeercert()
            try:
                self._validate_callback(self.peercert, self._server_hostname)
                self.is_valid = True
            except TTransportException:
                raise
            except Exception as ex:
                raise TTransportException(TTransportException.UNKNOWN, str(ex))
Exemplo n.º 17
0
    def _parse_header_format(self, buffer):
        # make BufferIO look like TTransport for varint helpers
        buffer_transport = TMemoryBuffer()
        buffer_transport._buffer = buffer

        buffer.read(2)  # discard the magic bytes
        self.flags, = U16.unpack(buffer.read(U16.size))
        self.sequence_id, = I32.unpack(buffer.read(I32.size))

        header_length = U16.unpack(buffer.read(U16.size))[0] * 4
        end_of_headers = buffer.tell() + header_length
        if end_of_headers > len(buffer.getvalue()):
            raise TTransportException(
                TTransportException.SIZE_LIMIT,
                "Header size is larger than whole frame.",
            )

        self._protocol_id = readVarint(buffer_transport)

        transforms = []
        transform_count = readVarint(buffer_transport)
        for _ in range(transform_count):
            transform_id = readVarint(buffer_transport)
            if transform_id not in READ_TRANSFORMS_BY_ID:
                raise TApplicationException(
                    TApplicationException.INVALID_TRANSFORM,
                    "Unknown transform: %d" % transform_id,
                )
            transforms.append(transform_id)
        transforms.reverse()

        headers = {}
        while buffer.tell() < end_of_headers:
            header_type = readVarint(buffer_transport)
            if header_type == TInfoHeaderType.KEY_VALUE:
                count = readVarint(buffer_transport)
                for _ in range(count):
                    key = _readString(buffer_transport)
                    value = _readString(buffer_transport)
                    headers[key] = value
            else:
                break  # ignore unknown headers
        self._read_headers = headers

        # skip padding / anything we didn't understand
        buffer.seek(end_of_headers)

        payload = buffer.read()
        for transform_id in transforms:
            transform_fn = READ_TRANSFORMS_BY_ID[transform_id]
            payload = transform_fn(payload)
        return BufferIO(payload)
Exemplo n.º 18
0
    def open(self, **kwargs):
        #===================================================================================================================
        # add by mz
        error_type = kwargs.get("error_type")
        if error_type:
            from thrift.transport.TTransport import TTransportException
            from thrift.protocol.TProtocol import TProtocolException
            from thrift.Thrift import TException, TApplicationException
            get_error = {
                "TTransportException": TTransportException(),
                "TProtocolException": TProtocolException(),
                "TException": TException(),
                "TApplicationException": TApplicationException()
            }
            error_ = get_error[error_type]
            raise error_
        from thrift.transport.TTransport import TTransportException
        #===================================================================================================================

        try:
            res0 = self._resolveAddr()
            for res in res0:
                self.handle = socket.socket(res[0], res[1])
                self.handle.settimeout(self._timeout)
                try:
                    self.handle.connect(res[4])
                except socket.error, e:
                    if res is not res0[-1]:
                        continue
                    else:
                        raise e
                break
        except socket.error, e:
            if self._unix_socket:
                message = 'Could not connect to socket %s' % self._unix_socket
            else:
                message = 'Could not connect to %s:%d' % (self.host, self.port)
            raise TTransportException(type=TTransportException.NOT_OPEN,
                                      message=message)
Exemplo n.º 19
0
    def open(self):
        if self.is_open():
            raise TTransportException(TTransportException.ALREADY_OPEN)

        h = None
        conns = 0
        while conns < self._max_conn_attempts:
            try:
                h = win32file.CreateFile(
                    self._pipe_name,
                    win32file.GENERIC_READ | win32file.GENERIC_WRITE, 0, None,
                    win32file.OPEN_EXISTING, win32file.FILE_FLAG_OVERLAPPED,
                    None)
            except pywintypes.error as e:
                if e.winerror != winerror.ERROR_PIPE_BUSY:
                    raise TTransportException(
                        TTransportException.NOT_OPEN,
                        'Failed to open connection to pipe: {}'.format(e))

            # Successfully connected, break out.
            if h is not None and h.handle != winerror.ERROR_INVALID_HANDLE:
                self._handle = h
                return

            # Wait for the connection to the pipe
            try:
                win32pipe.WaitNamedPipe(self._pipe_name, self._timeout)
            except Exception as e:
                if e.args[0] not in (winerror.ERROR_SEM_TIMEOUT,
                                     winerror.ERROR_PIPE_BUSY):
                    raise TTransportException(
                        type=TTransportException.UNKNOWN,
                        message='Client failed to connect to server with {}'.
                        format(e.args[0]))
            conns += 1

        raise TTransportException(
            type=TTransportException.UNKNOWN,
            message='Client exceeded max connection attempts')
Exemplo n.º 20
0
def readall(read_fn, sz):
    buff = b''
    have = 0
    while have < sz:
        chunk = read_fn(sz - have)
        have += len(chunk)
        buff += chunk

        if len(chunk) == 0:
            raise TTransportException(TTransportException.END_OF_FILE,
                                      "End of file reading from transport")

    return buff
Exemplo n.º 21
0
class TSSLSocketWithWildcardSAN(TSSLSocket.TSSLSocket):
    """
  This is a subclass of thrift's TSSLSocket which has been extended to add the missing
  functionality of validating wildcard certificates and certificates with SANs
  (subjectAlternativeName).

  The core of the validation logic is based on the python-ssl library:
  See <https://svn.python.org/projects/python/tags/r32/Lib/ssl.py>
  """
    def __init__(self,
                 host='localhost',
                 port=9090,
                 validate=True,
                 ca_certs=None,
                 unix_socket=None):
        cert_reqs = ssl.CERT_REQUIRED if validate else ssl.CERT_NONE
        # Set client protocol choice to be very permissive, as we rely on servers to enforce
        # good protocol selection. This value is forwarded to the ssl.wrap_socket() API during
        # open(). See https://docs.python.org/2/library/ssl.html#socket-creation for a table
        # that shows a better option is not readily available for sockets that use
        # wrap_socket().
        # THRIFT-3505 changes transport/TSSLSocket.py. The SSL_VERSION is passed to TSSLSocket
        # via a parameter.
        TSSLSocket.TSSLSocket.__init__(self,
                                       host=host,
                                       port=port,
                                       cert_reqs=cert_reqs,
                                       ca_certs=ca_certs,
                                       unix_socket=unix_socket,
                                       ssl_version=ssl.PROTOCOL_SSLv23)

    def _validate_cert(self):
        cert = self.handle.getpeercert()
        self.peercert = cert
        if 'subject' not in cert:
            raise TTransportException(
                type=TTransportException.NOT_OPEN,
                message='No SSL certificate found from %s:%s' %
                (self.host, self.port))
        try:
            self._match_hostname(cert, self.host)
            self.is_valid = True
            return
        except CertificateError, ce:
            raise TTransportException(
                type=TTransportException.UNKNOWN,
                message='Certificate error with remote host: %s' % (ce))
        raise TTransportException(
            type=TTransportException.UNKNOWN,
            message='Could not validate SSL certificate from '
            'host "%s".  Cert=%s' % (self.host, cert))
Exemplo n.º 22
0
    def _acquire(self):
        try:
            prot = self.pool.get(block=True, timeout=self.timeout)
        except queue.Empty:
            raise TTransportException(
                type=TTransportException.NOT_OPEN,
                message="timed out waiting for a connection slot",
            )

        for _ in self.retry_policy:
            if prot:
                if time.time() - prot.baseplate_birthdate < self.max_age:
                    return prot
                else:
                    prot.trans.close()
                    prot = None

            trans = _make_transport(self.endpoint)
            trans.setTimeout(self.timeout * 1000.)
            prot = self.protocol_factory.getProtocol(trans)

            try:
                prot.trans.open()
            except TTransportException as exc:
                logger.info("Failed to connect to %r: %s", self.endpoint, exc)
                prot = None
                continue

            prot.baseplate_birthdate = time.time()

            return prot

        self.pool.put(None)

        raise TTransportException(
            type=TTransportException.NOT_OPEN,
            message="giving up after multiple attempts to connect",
        )
Exemplo n.º 23
0
 def _recv_basePing(self, ctx):
     self._iprot.read_response_headers(ctx)
     _, mtype, _ = self._iprot.readMessageBegin()
     if mtype == TMessageType.EXCEPTION:
         x = TApplicationException()
         x.read(self._iprot)
         self._iprot.readMessageEnd()
         if x.type == TApplicationExceptionType.RESPONSE_TOO_LARGE:
             raise TTransportException(type=TTransportExceptionType.RESPONSE_TOO_LARGE, message=x.message)
         raise x
     result = basePing_result()
     result.read(self._iprot)
     self._iprot.readMessageEnd()
     return
Exemplo n.º 24
0
            def read_all(sz):  # thriftpy
                buff = b''
                have = 0
                while have < sz:
                    chunk = self._trans.read(sz - have)
                    have += len(chunk)
                    buff += chunk

                    if len(chunk) == 0:
                        raise TTransportException(
                            type=TTransportException.END_OF_FILE,
                            message="End of file reading from transport")

                return buff
Exemplo n.º 25
0
 def transform(self, buf):
     for trans_id in self.__write_transforms:
         if trans_id == TRANSFORM.ZLIB:
             buf = zlib.compress(buf)
         elif trans_id == TRANSFORM.SNAPPY:
             buf = snappy.compress(buf)
         elif trans_id == TRANSFORM.ZSTD:
             buf = zstd.ZstdCompressor(write_content_size=True).compress(buf)
         else:
             raise TTransportException(
                 TTransportException.INVALID_TRANSFORM,
                 "Unknown transform during send",
             )
     return buf
Exemplo n.º 26
0
    def _validate_cert(self):
        """internal method to validate the peer's SSL certificate, and to check the
    commonName of the certificate to ensure it matches the hostname we
    used to make this connection.  Does not support subjectAltName records
    in certificates.

    raises TTransportException if the certificate fails validation.
    """
        cert = self.handle.getpeercert()
        self.peercert = cert
        if 'subject' not in cert:
            raise TTransportException(
                type=TTransportException.NOT_OPEN,
                message='No SSL certificate found from %s:%s' %
                (self.host, self.port))

        hostName = self._read_cert_field(cert, 'subject', 'commonName')
        hostIp = self._read_cert_field(cert, 'subjectAltName', 'IP Address')

        if hostName is None:
            raise TTransportException(
                type=TTransportException.UNKNOWN,
                message='Could not validate SSL certificate from '
                'host "%s".  Cert=%s' % (self.host, cert))

        # this check should be performed by some sort of Access Manager
        if hostName == self.host or hostIp == self.host:
            # success, cert commonName matches desired hostname
            self.is_valid = True
            return
        else:
            raise TTransportException(
                type=TTransportException.UNKNOWN,
                message=
                'Hostname we connected to "%s" doesn\'t match certificate '
                'provided commonName "%s" or subjectAltName "%s"' %
                (self.host, hostName, hostIp))
Exemplo n.º 27
0
def legacy_validate_callback(cert, hostname):
    """legacy method to validate the peer's SSL certificate, and to check
    the commonName of the certificate to ensure it matches the hostname we
    used to make this connection.  Does not support subjectAltName records
    in certificates.

    raises TTransportException if the certificate fails validation.
    """
    if 'subject' not in cert:
        raise TTransportException(
            TTransportException.NOT_OPEN,
            'No SSL certificate found from %s' % hostname)
    fields = cert['subject']
    for field in fields:
        # ensure structure we get back is what we expect
        if not isinstance(field, tuple):
            continue
        cert_pair = field[0]
        if len(cert_pair) < 2:
            continue
        cert_key, cert_value = cert_pair[0:2]
        if cert_key != 'commonName':
            continue
        certhost = cert_value
        # this check should be performed by some sort of Access Manager
        if certhost == hostname:
            # success, cert commonName matches desired hostname
            return
        else:
            raise TTransportException(
                TTransportException.UNKNOWN,
                'Hostname we connected to "%s" doesn\'t match certificate '
                'provided commonName "%s"' % (hostname, certhost))
    raise TTransportException(
        TTransportException.UNKNOWN,
        'Could not validate SSL certificate from host "%s".  Cert=%s' %
        (hostname, cert))
Exemplo n.º 28
0
 def open(self):
     """Open a TIPC Socket"""
     try:
         srvaddr = (socket.TIPC_ADDR_NAME, self.port, 5, 0)
         self.handle = socket.socket(socket.AF_TIPC, socket.SOCK_STREAM)
     except Exception as e:
         logging.error('TIPC is not supported: ' + e.__str__())
         raise e
     try:
         self.handle.settimeout(None)
         self.handle.connect(srvaddr)
     except socket.error as e:
         message = 'Could not connect to TIPC:%d' % self.port
         raise TTransportException(type=TTransportException.NOT_OPEN,
                                   message=message)
Exemplo n.º 29
0
    def initiate_named_connect(self):
        conns = 0
        while conns < self._max_conn_attempts:
            try:
                ret = win32pipe.ConnectNamedPipe(self._handle,
                                                 self._overlapped)
            except Exception as e:
                raise TTransportException(
                    type=TTransportException.NOT_OPEN,
                    message='TConnectNamedPipe failed: {}'.format(str(e)))

            # Successfully connected, break out.
            if ret == winerror.ERROR_PIPE_CONNECTED:
                win32event.SetEvent(self._overlapped.hEvent)
                break
Exemplo n.º 30
0
    async def request(self, context: FContext, payload) -> TTransportBase:
        """
        Write the current buffer payload over the network and return the
        response.
        """
        self._preflight_request_check(payload)
        encoded = base64.b64encode(payload)

        status, text = await self._make_request(context, encoded)
        if status == 413:
            raise TTransportException(
                type=TTransportExceptionType.RESPONSE_TOO_LARGE,
                message='response was too large for the transport'
            )

        if status >= 300:
            raise TTransportException(
                type=TTransportExceptionType.UNKNOWN,
                message='request errored with code {0} and message {1}'.format(
                    status, str(text)
                )
            )

        decoded = base64.b64decode(text)
        if len(decoded) < 4:
            raise TTransportException(type=TTransportExceptionType.UNKNOWN,
                                      message='invalid frame size')

        if len(decoded) == 4:
            if any(decoded):
                raise TTransportException(type=TTransportExceptionType.UNKNOWN,
                                          message='missing data')
            # One-way method, drop response
            return

        return TMemoryBuffer(decoded[4:])
 def __init__(self, message=None):
     TTransportException.__init__(self, TTransportException.UNKNOWN, message)