Exemplo n.º 1
0
def sign_message_with_transaction(transaction, key):
    """
    Signs a transaction message or transaction
    :param transaction dict:
    :param key str: A signing key
    returns message, txnid tuple: The first 16 characters
    of a sha256 hexdigest.
    """
    transaction['Nonce'] = time.time()
    pub = pybitcointools.encode_pubkey(pybitcointools.privkey_to_pubkey(key),
                                       "hex")
    transaction["public_key"] = pub
    sig = pybitcointools.ecdsa_sign(dict2cbor(transaction), key)
    transaction['Signature'] = sig

    txnid = hashlib.sha256(transaction['Signature']).hexdigest()[:16]
    message = {
        'Transaction': transaction,
        '__TYPE__': "/mktplace.transactions.MarketPlace/Transaction",
        '__NONCE__': time.time(),
    }
    cbor_serialized_mess = dict2cbor(message)
    signature = pybitcointools.ecdsa_sign(cbor_serialized_mess, key)
    message['__SIGNATURE__'] = signature
    return message, txnid
Exemplo n.º 2
0
def sign_message_with_transaction(transaction, key):
    """
    Signs a transaction message or transaction
    :param transaction dict:
    :param key str: A signing key
    returns message, txnid tuple: The first 16 characters
    of a sha256 hexdigest.
    """
    transaction['Nonce'] = time.time()
    pub = pybitcointools.encode_pubkey(pybitcointools.privkey_to_pubkey(key),
                                       "hex")
    transaction["public_key"] = pub
    sig = pybitcointools.ecdsa_sign(
        dict2cbor(transaction),
        key
    )
    transaction['Signature'] = sig

    txnid = hashlib.sha256(transaction['Signature']).hexdigest()[:16]
    message = {
        'Transaction': transaction,
        '__TYPE__': "/mktplace.transactions.MarketPlace/Transaction",
        '__NONCE__': time.time(),
    }
    cbor_serialized_mess = dict2cbor(message)
    signature = pybitcointools.ecdsa_sign(
        cbor_serialized_mess,
        key
    )
    message['__SIGNATURE__'] = signature
    return message, txnid
Exemplo n.º 3
0
 def create_order(self,
                  action,
                  order_type,
                  firm_id,
                  quantity,
                  isin=None,
                  cusip=None,
                  limit_price=None,
                  limit_yield=None,
                  object_id=None):
     update = {
         'UpdateType': 'CreateOrder',
         'Action': action,
         'OrderType': order_type,
         'FirmId': firm_id,
         'Quantity': quantity,
         'Nonce': create_nonce()
     }
     possible_updates = {
         'Isin': isin,
         'Cusip': cusip,
         'LimitPrice': limit_price,
         'LimitYield': limit_yield,
         'ObjectId': object_id
     }
     for k, v in possible_updates.iteritems():
         if v is not None:
             update[k] = v
     if "ObjectId" not in update:
         update["ObjectId"] = hashlib.sha256(dict2cbor(update)).hexdigest()
     return self.send_bond_update(update)
Exemplo n.º 4
0
def do_load(args, config):
    url = config.get('DEFAULT', 'url')
    key_file = config.get('DEFAULT', 'key_file')

    client = BondClient(base_url=url, keyfile=key_file)

    for filename in args.filename:
        try:
            with open(filename) as fd:
                data = yaml.load(fd)
        except IOError, ioe:
            raise ClientException("IOError: {}".format(str(ioe)))

        print "Loading file: {}".format(filename)

        with UpdateBatch(client):
            for i in xrange(0, len(data['Transactions'])):
                for j in xrange(0, len(data['Transactions'][i]["Updates"])):
                    update = data['Transactions'][i]["Updates"][j]
                    if "ObjectId" not in update:
                        update["ObjectId"] = \
                            hashlib.sha256(dict2cbor(update)).hexdigest()
                    print "Sending transaction {}, {}...".format(i, j)
                    print "Update ", update
                    client.send_bond_update(update)

        if args.wait:
            client.wait_for_commit()
Exemplo n.º 5
0
 def create_quote(self,
                  firm,
                  ask_qty,
                  ask_price,
                  bid_qty,
                  bid_price,
                  isin=None,
                  cusip=None,
                  object_id=None):
     update = {
         'UpdateType': 'CreateQuote',
         'Firm': firm,
         'AskQty': ask_qty,
         'AskPrice': ask_price,
         'BidQty': bid_qty,
         'BidPrice': bid_price,
         'Nonce': create_nonce()
     }
     if isin is not None:
         update['Isin'] = isin
     if cusip is not None:
         update['Cusip'] = cusip
     if object_id is not None:
         update['ObjectId'] = object_id
     if "ObjectId" not in update:
         update["ObjectId"] = hashlib.sha256(dict2cbor(update)).hexdigest()
     return self.send_bond_update(update)
Exemplo n.º 6
0
    def add_authorization_to_org(self, object_id, role, participant_id=None):
        """
            Add an authorization (participant/role combination) to an
            organization.
        Args:
            object_id: The object ID of the organization
            role: (str) "marketmaker" or "trader"
            participant_id: The participant ID that grants the authorization
                            or None to indicate the participant that created
                            the organization.

        Returns:
            Transaction ID
        """
        update = {
            'UpdateType': 'UpdateOrganizationAuthorization',
            'ObjectId': object_id,
            'Action': 'add',
            'Role': role,
            'Nonce': create_nonce()
        }
        if participant_id is not None:
            update['ParticipantId'] = participant_id
        if "ObjectId" not in update:
            update["ObjectId"] = hashlib.sha256(dict2cbor(update)).hexdigest()
        return self.send_bond_update(update)
Exemplo n.º 7
0
 def create_org(self,
                name,
                object_id=None,
                industry=None,
                ticker=None,
                pricing_src=None,
                authorization=None):
     update = {
         'UpdateType': 'CreateOrganization',
         'Name': name,
         'Nonce': create_nonce()
     }
     obj = {
         'ObjectId': object_id,
         'Industry': industry,
         'Ticker': ticker,
         'PricingSource': pricing_src,
         'Authorization': authorization
     }
     for k, v in obj.iteritems():
         if v is not None:
             update[k] = v
     if "ObjectId" not in update:
         update["ObjectId"] = hashlib.sha256(dict2cbor(update)).hexdigest()
     return self.send_bond_update(update)
Exemplo n.º 8
0
    def do_post(self, request):
        """
        Handle two types of HTTP POST requests:
         - gossip messages.  relayed to the gossip network as is
         - validator command and control (/command)
        """

        # break the path into its component parts
        components = request.path.split('/')
        while components and components[0] == '':
            components.pop(0)

        try:
            response = self.render_post(request, components, request.args)

            encoding = request.getHeader('Content-Type')
            request.responseHeaders.addRawHeader("content-type", encoding)
            if encoding == 'application/json':
                result = dict2json(response)
            else:
                result = dict2cbor(response)

            return result
        except Exception as e:
            LOGGER.warn('error processing http request %s; %s; %s',
                        request.path,
                        str(e),
                        traceback.format_exc(20))
            return self._encode_error_response(
                request,
                http.INTERNAL_SERVER_ERROR,
                e)
Exemplo n.º 9
0
    def do_post(self, request):
        """
        Handle two types of HTTP POST requests:
         - gossip messages.  relayed to the gossip network as is
         - validator command and control (/command)
        """

        # break the path into its component parts
        components = request.path.split('/')
        while components and components[0] == '':
            components.pop(0)

        try:
            response = self.render_post(request, components, request.args)

            encoding = request.getHeader('Content-Type')
            request.responseHeaders.addRawHeader("content-type", encoding)
            if encoding == 'application/json':
                result = dict2json(response)
            else:
                result = dict2cbor(response)

            return result
        except Exception as e:
            LOGGER.warn('error processing http request %s; %s; %s',
                        request.path, str(e), traceback.format_exc(20))
            return self._encode_error_response(request,
                                               http.INTERNAL_SERVER_ERROR, e)
Exemplo n.º 10
0
    def render_GET(self, request):
        """
        Handle a GET request on the HTTP interface. Three paths are accepted:
            /store[/<storename>[/<key>|*]]
            /block[/<blockid>]
            /transaction[/<txnid>]
        """
        # pylint: disable=invalid-name

        # split the request path removing leading duplicate slashes
        components = request.path.split('/')
        while components and components[0] == '':
            components.pop(0)

        prefix = components.pop(0) if components else 'error'

        if prefix not in self.GetPageMap:
            return self.error_response(request, http.BAD_REQUEST,
                                       'unknown request {0}', request.path)

        testonly = (request.method == 'HEAD')

        try:
            response = self.GetPageMap[prefix](components, request.args,
                                               testonly)

            if testonly:
                return ''

            cbor = (request.getHeader('Accept') == 'application/cbor')

            if cbor:
                request.responseHeaders.addRawHeader(b"content-type",
                                                     b"application/cbor")
                return dict2cbor(response)

            request.responseHeaders.addRawHeader(b"content-type",
                                                 b"application/json")

            pretty = 'p' in request.args
            if pretty:
                result = pretty_print_dict(response) + '\n'
            else:
                result = dict2json(response)

            return result

        except Error as e:
            return self.error_response(
                request, int(e.status),
                'exception while processing http request {0}; {1}',
                request.path, str(e))

        except:
            logger.warn('error processing http request %s; %s', request.path,
                        traceback.format_exc(20))
            return self.error_response(request, http.BAD_REQUEST,
                                       'error processing http request {0}',
                                       request.path)
Exemplo n.º 11
0
    def do_get(self, request):
        """
        Handle a GET request on the HTTP interface. Three paths are accepted:
            /store[/<storename>[/<key>|*]]
            /block[/<blockid>]
            /transaction[/<txnid>]
        """
        # pylint: disable=invalid-name

        # split the request path removing leading duplicate slashes
        components = request.path.split('/')
        while components and components[0] == '':
            components.pop(0)

        prefix = components.pop(0) if components else 'error'

        if prefix not in self.GetPageMap:
            # attempt to serve static content if present.
            resource = self.static_content.getChild(request.path[1:], request)
            return resource.render(request)

        test_only = (request.method == 'HEAD')

        try:
            response = self.GetPageMap[prefix](components, request.args,
                                               test_only)
            if test_only:
                return ''

            cbor = (request.getHeader('Accept') == 'application/cbor')

            if cbor:
                request.responseHeaders.addRawHeader(b"content-type",
                                                     b"application/cbor")
                return dict2cbor(response)

            request.responseHeaders.addRawHeader(b"content-type",
                                                 b"application/json")

            pretty = 'p' in request.args
            if pretty:
                result = pretty_print_dict(response) + '\n'
            else:
                result = dict2json(response)

            return result

        except Error as e:
            return self.error_response(
                request, int(e.status),
                'exception while processing http request {0}; {1}',
                request.path, str(e))

        except:
            logger.warn('error processing http request %s; %s', request.path,
                        traceback.format_exc(20))
            return self.error_response(request, http.BAD_REQUEST,
                                       'error processing http request {0}',
                                       request.path)
Exemplo n.º 12
0
    def do_get(self, request):
        """
        Handle a GET request on the HTTP interface. Three paths are accepted:
            /store[/<storename>[/<key>|*]]
            /block[/<blockid>]
            /transaction[/<txnid>]
        """
        # pylint: disable=invalid-name

        # split the request path removing leading duplicate slashes
        LOGGER.info("%s.do_get %s", self.__class__.__name__, request.path)
        components = request.path.split('/')
        while components and components[0] == '':
            components.pop(0)

        if components[0] != self.page_name:
            return self.error_response(request, http.NOT_FOUND,
                                       "Invalid page name: {}", request.path)
        else:
            components.pop(0)

        test_only = (request.method == 'HEAD')
        try:
            response = self.render_get(request, components, request.args)
            if test_only:
                return ''

            cbor = (request.getHeader('Accept') == 'application/cbor')

            if cbor:
                request.responseHeaders.addRawHeader(b"content-type",
                                                     b"application/cbor")
                return dict2cbor(response)

            request.responseHeaders.addRawHeader(b"content-type",
                                                 b"application/json")
            pretty = False
            if 'p' in request.args:
                pretty = request.args['p'] == ['1']

            if pretty:
                result = pretty_print_dict(response) + '\n'
            else:
                result = dict2json(response)

            return result

        except Error as e:
            return self.error_response(
                request, int(e.status),
                'exception while processing http request {0}; {1}',
                request.path, str(e))

        except:
            LOGGER.warn('error processing http request %s; %s', request.path,
                        traceback.format_exc(20))
            return self.error_response(request, http.BAD_REQUEST,
                                       'error processing http request {0}',
                                       request.path)
Exemplo n.º 13
0
 def create_participant(self, username, firm_id=None, object_id=None):
     update = {'UpdateType': 'CreateParticipant', 'Username': username}
     if firm_id is not None:
         update['FirmId'] = firm_id
     if object_id is not None:
         update['ObjectId'] = object_id
     else:
         update['ObjectId'] = hashlib.sha256(dict2cbor(update)).hexdigest()
     return self.send_bond_update(update)
    def postmsg(self, msgtype, info):
        """
        Post a transaction message to the validator, parse the returning CBOR
        and return the corresponding dictionary.
        """

        logger.debug(dict2json(info))

        data = dict2cbor(info)
        datalen = len(data)
        url = self.BaseURL + msgtype

        logger.debug(
            'post transaction to %s with DATALEN=%d, '
            'base64(DATA)=<%s>', url, datalen, base64.b64encode(data))

        try:
            request = urllib2.Request(url, data, {
                'Content-Type': 'application/cbor',
                'Content-Length': datalen
            })
            opener = urllib2.build_opener(self.ProxyHandler)
            response = opener.open(request, timeout=10)

        except urllib2.HTTPError as err:
            logger.warn('operation failed with response: %s', err.code)
            raise MessageException(
                'operation failed with response: {0}'.format(err.code))

        except urllib2.URLError as err:
            logger.warn('operation failed: %s', err.reason)
            raise MessageException('operation failed: {0}'.format(err.reason))

        except:
            logger.warn('no response from server')
            raise MessageException('no response from server')

        content = response.read()
        headers = response.info()
        response.close()

        encoding = headers.get('Content-Type')

        if encoding == 'application/json':
            value = json2dict(content)
        elif encoding == 'application/cbor':
            value = cbor2dict(content)
        else:
            logger.info('server responds with message %s of type %s', content,
                        encoding)
            return None

        logger.debug(pretty_print_dict(value))
        return value
Exemplo n.º 15
0
 def test_message_len(self):
     # Test the overriden len function
     # First case is when the msg has no data, creates data
     msg = Message({'__SIGNATURE__': "Test"})
     length = len(dict2cbor(msg.dump()))
     self.assertIsNone(msg._data)
     self.assertEquals(len(msg), length)
     # The second case is when the msg does have data
     msg2 = Message({"__SIGNATURE__": "Test"})
     msg2._data = "test data"
     self.assertEquals(len(msg2), len("test data"))
Exemplo n.º 16
0
 def create_settlement(self, order_id, object_id=None):
     update = {
         'UpdateType': 'CreateSettlement',
         'OrderId': order_id,
         'Nonce': create_nonce()
     }
     if object_id is not None:
         update['ObjectId'] = object_id
     if "ObjectId" not in update:
         update["ObjectId"] = hashlib.sha256(dict2cbor(update)).hexdigest()
     return self.send_bond_update(update)
Exemplo n.º 17
0
    def do_get(self, request):
        """
        Handle a GET request on the HTTP interface. Three paths are accepted:
            /store[/<storename>[/<key>|*]]
            /block[/<blockid>]
            /transaction[/<txnid>]
        """
        # pylint: disable=invalid-name

        # split the request path removing leading duplicate slashes
        LOGGER.info("%s.do_get %s", self.__class__.__name__, request.path)
        components = request.path.split('/')
        while components and components[0] == '':
            components.pop(0)

        if components[0] != self.page_name:
            return self._error_response(
                request,
                http.NOT_FOUND,
                "Invalid page name: {}", request.path)
        else:
            components.pop(0)

        test_only = (request.method == 'HEAD')
        try:
            response = self.render_get(request, components, request.args)
            if test_only:
                return ''

            cbor = (request.getHeader('Accept') == 'application/cbor')
            if cbor:
                request.responseHeaders.addRawHeader(b"content-type",
                                                     b"application/cbor")
                result = dict2cbor(response)
            else:
                request.responseHeaders.addRawHeader(b"content-type",
                                                     b"application/json")
                pretty = False
                if 'p' in request.args:
                    pretty = request.args['p'] == ['1']

                if pretty:
                    result = pretty_print_dict(response) + '\n'
                else:
                    result = dict2json(response)

            return result
        except Exception as e:
            LOGGER.warn('error processing http request %s; %s', request.path,
                        traceback.format_exc(20))
            return self._encode_error_response(
                request,
                http.INTERNAL_SERVER_ERROR,
                e)
Exemplo n.º 18
0
 def test_message_len(self):
     # Test the overriden len function
     # First case is when the msg has no data, creates data
     msg = Message({'__SIGNATURE__': "Test"})
     length = len(dict2cbor(msg.dump()))
     self.assertIsNone(msg._data)
     self.assertEqual(len(msg), length)
     # The second case is when the msg does have data
     msg2 = Message({"__SIGNATURE__": "Test"})
     msg2._data = "test data"
     self.assertEqual(len(msg2), len("test data"))
Exemplo n.º 19
0
    def postmsg(self, msgtype, info):
        """
        Post a transaction message to the validator, parse the returning CBOR
        and return the corresponding dictionary.
        """

        logger.debug(dict2json(info))

        data = dict2cbor(info)
        datalen = len(data)
        url = self.BaseURL + msgtype

        logger.debug('post transaction to %s with DATALEN=%d, '
                     'base64(DATA)=<%s>', url, datalen, base64.b64encode(data))

        try:
            request = urllib2.Request(url, data,
                                      {'Content-Type': 'application/cbor',
                                       'Content-Length': datalen})
            opener = urllib2.build_opener(self.ProxyHandler)
            response = opener.open(request, timeout=10)

        except urllib2.HTTPError as err:
            logger.warn('operation failed with response: %s', err.code)
            raise MessageException(
                'operation failed with response: {0}'.format(err.code))

        except urllib2.URLError as err:
            logger.warn('operation failed: %s', err.reason)
            raise MessageException('operation failed: {0}'.format(err.reason))

        except:
            logger.warn('no response from server')
            raise MessageException('no response from server')

        content = response.read()
        headers = response.info()
        response.close()

        encoding = headers.get('Content-Type')

        if encoding == 'application/json':
            value = json2dict(content)
        elif encoding == 'application/cbor':
            value = cbor2dict(content)
        else:
            logger.info('server responds with message %s of type %s', content,
                        encoding)
            return None

        logger.debug(pretty_print_dict(value))
        return value
Exemplo n.º 20
0
    def serialize(self, signable=False):
        """Generates a CBOR serialized dict containing the a SignatureKey
        to Signature mapping.

        Args:
            signable (bool): if signable is True, self.SignatureKey is
                removed from the dict prior to serialization to CBOR.

        Returns:
            bytes: a CBOR representation of a SignatureKey to Signature
                mapping.
        """
        dump = self.dump()

        if signable and self.SignatureKey in dump:
            del dump[self.SignatureKey]

        return dict2cbor(dump)
Exemplo n.º 21
0
    def serialize(self, signable=False):
        """Generates a CBOR serialized dict containing the a SignatureKey
        to Signature mapping.

        Args:
            signable (bool): if signable is True, self.SignatureKey is
                removed from the dict prior to serialization to CBOR.

        Returns:
            bytes: a CBOR representation of a SignatureKey to Signature
                mapping.
        """
        dump = self.dump()

        if signable and self.SignatureKey in dump:
            del dump[self.SignatureKey]

        return dict2cbor(dump)
Exemplo n.º 22
0
 def create_holding(self,
                    owner_id,
                    asset_type,
                    asset_id,
                    amount,
                    object_id=None):
     update = {
         'UpdateType': 'CreateHolding',
         'OwnerId': owner_id,
         'AssetType': asset_type,
         'AssetId': asset_id,
         'Amount': amount,
         'Nonce': create_nonce()
     }
     if object_id is not None:
         update['ObjectId'] = object_id
     if "ObjectId" not in update:
         update["ObjectId"] = hashlib.sha256(dict2cbor(update)).hexdigest()
     return self.send_bond_update(update)
    def commit_block_store(self, blockid, blockstore):
        """Associates the blockstore with the blockid and commits
        the blockstore to disk.

        Marks the blockstore read only as part of the process.

        Args:
            blockid (str): The identifier to associate with the block.
            blockstore (BlockStore): An initialized blockstore to be
                used as the root store.
        """

        # if we commit a block then we know that either this is the genesis
        # block or that the previous block is committed already
        assert blockstore.PreviousBlockID in self._persistmap

        blockstore.commit_block(blockid)
        self._blockmap[blockid] = blockstore
        self._persistmap[blockid] = dict2cbor(blockstore.dump_block(True))
        self._persistmap.sync()
Exemplo n.º 24
0
    def commit_block_store(self, blockid, blockstore):
        """Associates the blockstore with the blockid and commits
        the blockstore to disk.

        Marks the blockstore read only as part of the process.

        Args:
            blockid (str): The identifier to associate with the block.
            blockstore (global_store_manager.BlockStore): An initialized
                blockstore to be used as the root store.
        """

        # if we commit a block then we know that either this is the genesis
        # block or that the previous block is committed already
        assert blockstore.PreviousBlockID in self._persistmap

        blockstore.commit_block(blockid)
        self._blockmap[blockid] = blockstore
        self._persistmap[blockid] = dict2cbor(blockstore.dump_block(True))
        self._persistmap.sync()
Exemplo n.º 25
0
    def add_transaction_store(self, tname, tstore):
        """Registers a data store type with a particular transaction type.

        Args:
           tname (str): The name of the transaction type.
           tstore (KeyValueStore): The data store to associate with the
               transaction type.
        """

        # we should really only be adding transaction stores to the
        # root block, if this fails we need to think more about the
        # initialization
        assert len(self._blockmap) == 1

        rootstore = self._blockmap[self.RootBlockID]
        rootstore.add_transaction_store(tname, tstore)

        rootstore.commit_block(self.RootBlockID)
        self._blockmap[self.RootBlockID] = rootstore
        self._persistmap[self.RootBlockID] = \
            dict2cbor(rootstore.dump_block(True))
        self._persistmap.sync()
    def add_transaction_store(self, tname, tstore):
        """Registers a data store type with a particular transaction type.

        Args:
           tname (str): The name of the transaction type.
           tstore (KeyValueStore): The data store to associate with the
               transaction type.
        """

        # we should really only be adding transaction stores to the
        # root block, if this fails we need to think more about the
        # initialization
        assert len(self._blockmap) == 1

        rootstore = self._blockmap[self.RootBlockID]
        rootstore.add_transaction_store(tname, tstore)

        rootstore.commit_block(self.RootBlockID)
        self._blockmap[self.RootBlockID] = rootstore
        self._persistmap[self.RootBlockID] = \
            dict2cbor(rootstore.dump_block(True))
        self._persistmap.sync()
Exemplo n.º 27
0
    def do_post(self, request):
        """
        Handle two types of HTTP POST requests:
         - gossip messages.  relayed to the gossip network as is
         - validator command and control (/command)
        """

        # break the path into its component parts
        components = request.path.split('/')
        while components and components[0] == '':
            components.pop(0)

        try:
            response = self.render_post(request, components, request.args)

            encoding = request.getHeader('Content-Type')
            request.responseHeaders.addRawHeader("content-type", encoding)
            if encoding == 'application/json':
                result = dict2json(response.dump())
            else:
                result = dict2cbor(response.dump())

            return result

        except Error as e:
            return self.error_response(
                request, int(e.status),
                'exception while processing request {0}; {1}', request.path,
                str(e))

        except:
            LOGGER.info('exception while processing http request %s; %s',
                        request.path, traceback.format_exc(20))
            return self.error_response(request, http.BAD_REQUEST,
                                       'error processing http request {0}',
                                       request.path)
    def __init__(self, blockstorefile='blockstore', dbmode='c'):
        """Initialize a GlobalStoreManager, opening the database file.

        Args:
            blockstorefile (str): The name of the file to use for
                persistent data.
            dbmode (str): The mode used to open the file (see anydbm
                parameters).
        """
        logger.info('create blockstore from file %s with flag %s',
                    blockstorefile, dbmode)

        self._blockmap = {}
        self._persistmap = anydbm.open(blockstorefile, dbmode)

        rootstore = BlockStore()
        rootstore.commit_block(self.RootBlockID, )
        self._blockmap[self.RootBlockID] = rootstore
        self._persistmap[self.RootBlockID] = \
            dict2cbor(rootstore.dump_block(True))
        self._persistmap.sync()

        logger.debug('the persistent block store has %s keys',
                     len(self._persistmap))
Exemplo n.º 29
0
    def do_post(self, request):
        """
        Handle two types of HTTP POST requests:
         - gossip messages.  relayed to the gossip network as is
         - validator command and control (/command)
        """

        # break the path into its component parts
        components = request.path.split('/')
        while components and components[0] == '':
            components.pop(0)

        try:
            response = self.render_post(request, components, request.args)

            encoding = request.getHeader('Content-Type')
            request.responseHeaders.addRawHeader("content-type", encoding)
            if encoding == 'application/json':
                result = dict2json(response.dump())
            else:
                result = dict2cbor(response.dump())

            return result

        except Error as e:
            return self.error_response(
                request, int(e.status),
                'exception while processing request {0}; {1}',
                request.path, str(e))

        except:
            LOGGER.info('exception while processing http request %s; %s',
                        request.path, traceback.format_exc(20))
            return self.error_response(request, http.BAD_REQUEST,
                                       'error processing http request {0}',
                                       request.path)
Exemplo n.º 30
0
    def __init__(self, blockstorefile='blockstore', dbmode='c'):
        """Initialize a GlobalStoreManager, opening the database file.

        Args:
            blockstorefile (str): The name of the file to use for
                persistent data.
            dbmode (str): The mode used to open the file (see anydbm
                parameters).
        """
        logger.info('create blockstore from file %s with flag %s',
                    blockstorefile, dbmode)

        self._blockmap = {}
        self._persistmap = anydbm.open(blockstorefile, dbmode)

        rootstore = BlockStore()
        rootstore.commit_block(self.RootBlockID, )
        self._blockmap[self.RootBlockID] = rootstore
        self._persistmap[self.RootBlockID] = \
            dict2cbor(rootstore.dump_block(True))
        self._persistmap.sync()

        logger.debug('the persistent block store has %s keys',
                     len(self._persistmap))
Exemplo n.º 31
0
    def render_POST(self, request):
        """
        Handle two types of HTTP POST requests:
         - gossip messages.  relayed to the gossip network as is
         - validator command and control (/command)
        """
        # pylint: disable=invalid-name

        # break the path into its component parts
        components = request.path.split('/')
        while components and components[0] == '':
            components.pop(0)

        prefix = components.pop(0) if components else 'error'
        if prefix not in self.PostPageMap:
            prefix = 'default'

        encoding = request.getHeader('Content-Type')
        data = request.content.getvalue()

        # process non-gossip API requests
        if prefix == 'command':

            try:
                if encoding == 'application/json':
                    minfo = json2dict(data)
                else:
                    return self.error_response(request, http.BAD_REQUEST,
                                               'bad message encoding, {0}',
                                               encoding)
            except:
                logger.info('exception while decoding http request %s; %s',
                            request.path, traceback.format_exc(20))
                return self.error_response(
                    request, http.BAD_REQUEST,
                    'unable to decode incoming request {0}',
                    data)

            # process /command
            try:
                response = self.PostPageMap[prefix](request, components, minfo)
                request.responseHeaders.addRawHeader("content-type", encoding)
                result = dict2json(response)
                return result

            except Error as e:
                return self.error_response(
                    request, int(e.status),
                    'exception while processing request {0}; {1}',
                    request.path, str(e))

            except:
                logger.info('exception while processing http request %s; %s',
                            request.path, traceback.format_exc(20))
                return self.error_response(request, http.BAD_REQUEST,
                                           'error processing http request {0}',
                                           request.path)
        else:
            try:
                if encoding == 'application/json':
                    minfo = json2dict(data)
                elif encoding == 'application/cbor':
                    minfo = cbor2dict(data)
                else:
                    return self.error_response(request, http.BAD_REQUEST,
                                               'unknown message encoding, {0}',
                                               encoding)
                typename = minfo.get('__TYPE__', '**UNSPECIFIED**')
                if typename not in self.Ledger.MessageHandlerMap:
                    return self.error_response(
                        request, http.BAD_REQUEST,
                        'received request for unknown message type, {0}',
                        typename)

                msg = self.Ledger.MessageHandlerMap[typename][0](minfo)

            except:
                logger.info('exception while decoding http request %s; %s',
                            request.path, traceback.format_exc(20))
                return self.error_response(
                    request, http.BAD_REQUEST,
                    'unabled to decode incoming request {0}',
                    data)

            # determine if the message contains a valid transaction before
            # we send the message to the network

            # we need to start with a copy of the message due to cases
            # where side effects of the validity check may impact objects
            # related to msg
            mymsg = copy.deepcopy(msg)

            if hasattr(mymsg, 'Transaction') and mymsg.Transaction is not None:
                mytxn = mymsg.Transaction
                logger.info('starting local validation '
                            'for txn id: %s type: %s',
                            mytxn.Identifier,
                            mytxn.TransactionTypeName)
                blockid = self.Ledger.MostRecentCommittedBlockID

                realstoremap = self.Ledger.GlobalStoreMap.get_block_store(
                    blockid)
                tempstoremap = global_store_manager.BlockStore(realstoremap)
                if not tempstoremap:
                    logger.info('no store map for block %s', blockid)
                    return self.error_response(
                        request, http.BAD_REQUEST,
                        'unable to validate enclosed transaction {0}',
                        data)

                transtype = mytxn.TransactionTypeName
                if transtype not in tempstoremap.TransactionStores:
                    logger.info('transaction type %s not in global store map',
                                transtype)
                    return self.error_response(
                        request, http.BAD_REQUEST,
                        'unable to validate enclosed transaction {0}',
                        data)

                # clone a copy of the ledger's message queue so we can
                # temporarily play forward all locally submitted yet
                # uncommitted transactions
                myqueue = copy.deepcopy(self.Ledger.MessageQueue)

                # apply any enqueued messages
                while len(myqueue) > 0:
                    qmsg = myqueue.pop()
                    if qmsg and \
                       qmsg.MessageType in self.Ledger.MessageHandlerMap:
                        if (hasattr(qmsg, 'Transaction') and
                                qmsg.Transaction is not None):
                            mystore = tempstoremap.get_transaction_store(
                                qmsg.Transaction.TransactionTypeName)
                            if qmsg.Transaction.is_valid(mystore):
                                myqtxn = copy.copy(qmsg.Transaction)
                                myqtxn.apply(mystore)

                # apply any local pending transactions
                for txnid in self.Ledger.PendingTransactions.iterkeys():
                    pendtxn = self.Ledger.TransactionStore[txnid]
                    mystore = tempstoremap.get_transaction_store(
                        pendtxn.TransactionTypeName)
                    if pendtxn and pendtxn.is_valid(mystore):
                        mypendtxn = copy.copy(pendtxn)
                        logger.debug('applying pending transaction '
                                     '%s to temp store', txnid)
                        mypendtxn.apply(mystore)

                # determine validity of the POSTed transaction against our
                # new temporary state
                mystore = tempstoremap.get_transaction_store(
                    mytxn.TransactionTypeName)
                try:
                    mytxn.check_valid(mystore)
                except InvalidTransactionError as e:
                    logger.info('submitted transaction fails transaction '
                                'family validation check: %s; %s',
                                request.path, mymsg.dump())
                    return self.error_response(
                        request, http.BAD_REQUEST,
                        "enclosed transaction failed transaction "
                        "family validation check: {}".format(str(e)),
                        data)
                except:
                    logger.info('submitted transaction is '
                                'not valid %s; %s; %s',
                                request.path, mymsg.dump(),
                                traceback.format_exc(20))
                    return self.error_response(
                        request, http.BAD_REQUEST,
                        "enclosed transaction is not valid",
                        data)

                logger.info('transaction %s is valid',
                            msg.Transaction.Identifier)

            # and finally execute the associated method
            # and send back the results
            try:
                response = self.PostPageMap[prefix](request, components, msg)

                request.responseHeaders.addRawHeader("content-type", encoding)
                if encoding == 'application/json':
                    result = dict2json(response.dump())
                else:
                    result = dict2cbor(response.dump())

                return result

            except Error as e:
                return self.error_response(
                    request, int(e.status),
                    'exception while processing request {0}; {1}',
                    request.path, str(e))

            except:
                logger.info('exception while processing http request %s; %s',
                            request.path, traceback.format_exc(20))
                return self.error_response(request, http.BAD_REQUEST,
                                           'error processing http request {0}',
                                           request.path)
Exemplo n.º 32
0
 def test_unpack_message(self):
     # Make sure that the message can be unpacked after serliazation
     msg = Message({'__SIGNATURE__': "Test"})
     cbor = dict2cbor(msg.dump())
     msgdict = unpack_message_data(cbor)
     self.assertEquals(msg.dump(), msgdict)
Exemplo n.º 33
0
 def test_unpack_message(self):
     # Make sure that the message can be unpacked after serliazation
     msg = Message({'__SIGNATURE__': "Test"})
     cbor = dict2cbor(msg.dump())
     msgdict = unpack_message_data(cbor)
     self.assertEqual(msg.dump(), msgdict)
Exemplo n.º 34
0
    def _posturl(self, url, info, encoding='application/cbor'):
        """
        Post a transaction message to the validator, parse the returning CBOR
        and return the corresponding dictionary.
        """

        if encoding == 'application/json':
            data = dict2json(info)
        elif encoding == 'application/cbor':
            data = dict2cbor(info)
        else:
            LOGGER.error('unknown request encoding %s', encoding)
            return None

        datalen = len(data)

        LOGGER.debug('post transaction to %s with DATALEN=%d, DATA=<%s>', url,
                     datalen, data)

        try:
            request = urllib2.Request(url, data,
                                      {'Content-Type': 'application/cbor',
                                       'Content-Length': datalen})
            opener = urllib2.build_opener(self.proxy_handler)
            response = opener.open(request, timeout=10)

        except urllib2.HTTPError as err:
            LOGGER.error('peer operation on url %s failed with response: %d',
                         url, err.code)
            raise MessageException('operation failed with resonse: {0}'.format(
                err.code))

        except urllib2.URLError as err:
            LOGGER.error('peer operation on url %s failed: %s', url,
                         err.reason)
            raise MessageException('operation failed: {0}'.format(err.reason))

        except NameError as err:
            LOGGER.error('name error %s', err)
            raise MessageException('operation failed: {0}'.format(url))

        except:
            LOGGER.error('no response from peer server for url %s; %s', url,
                         sys.exc_info()[0])
            raise MessageException('no response from server')

        content = response.read()
        headers = response.info()
        response.close()

        encoding = headers.get('Content-Type')

        if encoding == 'application/json':
            value = json2dict(content)
        elif encoding == 'application/cbor':
            value = cbor2dict(content)
        else:
            LOGGER.info('server responds with message %s of unknown type %s',
                        content, encoding)
            value = OrderedDict()

        return value
Exemplo n.º 35
0
    def postmsg(self, msgtype, info):
        """
        Post a transaction message to the validator, parse the returning CBOR
        and return the corresponding dictionary.
        """

        data = dict2cbor(info)
        datalen = len(data)
        url = urlparse.urljoin(self._base_url, msgtype)

        LOGGER.debug('post transaction to %s with DATALEN=%d, DATA=<%s>', url,
                     datalen, data)

        try:
            request = urllib2.Request(url, data, {
                'Content-Type': 'application/cbor',
                'Content-Length': datalen
            })

            if self._cookie:
                request.add_header('cookie', self._cookie)

            opener = urllib2.build_opener(self._proxy_handler)
            response = opener.open(request, timeout=10)
            if not self._cookie:
                self._cookie = response.headers.get('Set-Cookie')
        except urllib2.HTTPError as err:
            content = err.read()
            if content is not None:
                headers = err.info()
                encoding = headers.get('Content-Type')

                if encoding == 'application/json':
                    value = json2dict(content)
                elif encoding == 'application/cbor':
                    value = cbor2dict(content)
                else:
                    LOGGER.warn('operation failed with response: %s', err.code)
                    raise MessageException(
                        'operation failed with response: {0}'.format(err.code))
                LOGGER.warn('operation failed with response: %s %s', err.code,
                            str(value))
                if "errorType" in value:
                    if value['errorType'] == "InvalidTransactionError":
                        raise InvalidTransactionError(
                            value['error'] if 'error' in value else value)
                    else:
                        raise MessageException(str(value))
            else:
                raise MessageException(
                    'operation failed with response: {0}'.format(err.code))
        except urllib2.URLError as err:
            LOGGER.warn('operation failed: %s', err.reason)
            raise MessageException('operation failed: {0}'.format(err.reason))

        except:
            LOGGER.warn('no response from server')
            raise MessageException('no response from server')

        content = response.read()
        headers = response.info()
        response.close()

        encoding = headers.get('Content-Type')

        if encoding == 'application/json':
            value = json2dict(content)
        elif encoding == 'application/cbor':
            value = cbor2dict(content)
        else:
            LOGGER.info('server responds with message %s of type %s', content,
                        encoding)
            return None

        LOGGER.debug(pretty_print_dict(value))
        return value
Exemplo n.º 36
0
 def create_id(self):
     return hashlib.sha256(dict2cbor(_serialize(
         self, self._update_type))).hexdigest()
Exemplo n.º 37
0
 def create_id(self):
     return hashlib.sha256(
         dict2cbor(_serialize(self, self._update_type))).hexdigest()
Exemplo n.º 38
0
    def _posturl(self, url, info, encoding='application/cbor'):
        """
        Post a transaction message to the validator, parse the returning CBOR
        and return the corresponding dictionary.
        """

        if encoding == 'application/json':
            data = dict2json(info)
        elif encoding == 'application/cbor':
            data = dict2cbor(info)
        else:
            LOGGER.error('unknown request encoding %s', encoding)
            return None

        datalen = len(data)

        LOGGER.debug('post transaction to %s with DATALEN=%d, DATA=<%s>', url,
                     datalen, data)

        try:
            request = urllib2.Request(url, data, {
                'Content-Type': 'application/cbor',
                'Content-Length': datalen
            })
            opener = urllib2.build_opener(self.proxy_handler)
            response = opener.open(request, timeout=10)

        except urllib2.HTTPError as err:
            LOGGER.error('peer operation on url %s failed with response: %d',
                         url, err.code)
            raise MessageException(
                'operation failed with response: {0}'.format(err.code))

        except urllib2.URLError as err:
            LOGGER.error('peer operation on url %s failed: %s', url,
                         err.reason)
            raise MessageException('operation failed: {0}'.format(err.reason))

        except NameError as err:
            LOGGER.error('name error %s', err)
            raise MessageException('operation failed: {0}'.format(url))

        except:
            LOGGER.error('no response from peer server for url %s; %s', url,
                         sys.exc_info()[0])
            raise MessageException('no response from server')

        content = response.read()
        headers = response.info()
        response.close()

        encoding = headers.get('Content-Type')

        if encoding == 'application/json':
            value = json2dict(content)
        elif encoding == 'application/cbor':
            value = cbor2dict(content)
        else:
            LOGGER.info('server responds with message %s of unknown type %s',
                        content, encoding)
            value = OrderedDict()

        return value
Exemplo n.º 39
0
 def __len__(self):
     if not self._data:
         self._data = dict2cbor(self.dump())
     return len(self._data)
Exemplo n.º 40
0
    def do_post(self, request):
        """
        Handle two types of HTTP POST requests:
         - gossip messages.  relayed to the gossip network as is
         - validator command and control (/command)
        """

        # break the path into its component parts

        components = request.path.split('/')
        while components and components[0] == '':
            components.pop(0)

        prefix = components.pop(0) if components else 'error'
        if prefix not in self.PostPageMap:
            prefix = 'default'

        encoding = request.getHeader('Content-Type')
        data = request.content.getvalue()

        # process non-gossip API requests
        if prefix == 'command':

            try:
                if encoding == 'application/json':
                    minfo = json2dict(data)
                else:
                    return self.error_response(request, http.BAD_REQUEST,
                                               'bad message encoding, {0}',
                                               encoding)
            except:
                logger.info('exception while decoding http request %s; %s',
                            request.path, traceback.format_exc(20))
                return self.error_response(
                    request, http.BAD_REQUEST,
                    'unable to decode incoming request {0}', data)

            # process /command
            try:
                response = self.PostPageMap[prefix](request, components, minfo)
                request.responseHeaders.addRawHeader("content-type", encoding)
                result = dict2json(response)
                return result

            except Error as e:
                return self.error_response(
                    request, int(e.status),
                    'exception while processing request {0}; {1}',
                    request.path, str(e))

            except:
                logger.info('exception while processing http request %s; %s',
                            request.path, traceback.format_exc(20))
                return self.error_response(
                    request, http.BAD_REQUEST,
                    'error processing http request {0}', request.path)
        else:
            try:
                if encoding == 'application/json':
                    minfo = json2dict(data)
                elif encoding == 'application/cbor':
                    minfo = cbor2dict(data)
                else:
                    return self.error_response(
                        request, http.BAD_REQUEST,
                        'unknown message encoding, {0}', encoding)
                typename = minfo.get('__TYPE__', '**UNSPECIFIED**')
                if typename not in self.Ledger.MessageHandlerMap:
                    return self.error_response(
                        request, http.BAD_REQUEST,
                        'received request for unknown message type, {0}',
                        typename)

                msg = self.Ledger.MessageHandlerMap[typename][0](minfo)

            except:
                logger.info('exception while decoding http request %s; %s',
                            request.path, traceback.format_exc(20))
                return self.error_response(
                    request, http.BAD_REQUEST,
                    'unabled to decode incoming request {0}', data)

            # determine if the message contains a valid transaction before
            # we send the message to the network

            # we need to start with a copy of the message due to cases
            # where side effects of the validity check may impact objects
            # related to msg
            mymsg = copy.deepcopy(msg)

            if hasattr(mymsg, 'Transaction') and mymsg.Transaction is not None:
                mytxn = mymsg.Transaction
                logger.info(
                    'starting local validation '
                    'for txn id: %s type: %s', mytxn.Identifier,
                    mytxn.TransactionTypeName)
                block_id = self.Ledger.MostRecentCommittedBlockID

                real_store_map = self.Ledger.GlobalStoreMap.get_block_store(
                    block_id)
                temp_store_map = \
                    global_store_manager.BlockStore(real_store_map)
                if not temp_store_map:
                    logger.info('no store map for block %s', block_id)
                    return self.error_response(
                        request, http.BAD_REQUEST,
                        'unable to validate enclosed transaction {0}', data)

                transaction_type = mytxn.TransactionTypeName
                if transaction_type not in temp_store_map.TransactionStores:
                    logger.info('transaction type %s not in global store map',
                                transaction_type)
                    return self.error_response(
                        request, http.BAD_REQUEST,
                        'unable to validate enclosed transaction {0}', data)

                # clone a copy of the ledger's message queue so we can
                # temporarily play forward all locally submitted yet
                # uncommitted transactions
                my_queue = copy.deepcopy(self.Ledger.MessageQueue)

                # apply any enqueued messages
                while len(my_queue) > 0:
                    qmsg = my_queue.pop()
                    if qmsg and \
                       qmsg.MessageType in self.Ledger.MessageHandlerMap:
                        if (hasattr(qmsg, 'Transaction')
                                and qmsg.Transaction is not None):
                            my_store = temp_store_map.get_transaction_store(
                                qmsg.Transaction.TransactionTypeName)
                            if qmsg.Transaction.is_valid(my_store):
                                myqtxn = copy.copy(qmsg.Transaction)
                                myqtxn.apply(my_store)

                # apply any local pending transactions
                for txn_id in self.Ledger.PendingTransactions.iterkeys():
                    pend_txn = self.Ledger.TransactionStore[txn_id]
                    my_store = temp_store_map.get_transaction_store(
                        pend_txn.TransactionTypeName)
                    if pend_txn and pend_txn.is_valid(my_store):
                        my_pend_txn = copy.copy(pend_txn)
                        logger.debug(
                            'applying pending transaction '
                            '%s to temp store', txn_id)
                        my_pend_txn.apply(my_store)

                # determine validity of the POSTed transaction against our
                # new temporary state
                my_store = temp_store_map.get_transaction_store(
                    mytxn.TransactionTypeName)
                try:
                    mytxn.check_valid(my_store)
                except InvalidTransactionError as e:
                    logger.info(
                        'submitted transaction fails transaction '
                        'family validation check: %s; %s', request.path,
                        mymsg.dump())
                    return self.error_response(
                        request, http.BAD_REQUEST,
                        "enclosed transaction failed transaction "
                        "family validation check: {}".format(str(e)), data)
                except:
                    logger.info(
                        'submitted transaction is '
                        'not valid %s; %s; %s', request.path, mymsg.dump(),
                        traceback.format_exc(20))
                    return self.error_response(
                        request, http.BAD_REQUEST,
                        "enclosed transaction is not valid", data)

                logger.info('transaction %s is valid',
                            msg.Transaction.Identifier)

            # and finally execute the associated method
            # and send back the results
            try:
                response = self.PostPageMap[prefix](request, components, msg)

                request.responseHeaders.addRawHeader("content-type", encoding)
                if encoding == 'application/json':
                    result = dict2json(response.dump())
                else:
                    result = dict2cbor(response.dump())

                return result

            except Error as e:
                return self.error_response(
                    request, int(e.status),
                    'exception while processing request {0}; {1}',
                    request.path, str(e))

            except:
                logger.info('exception while processing http request %s; %s',
                            request.path, traceback.format_exc(20))
                return self.error_response(
                    request, http.BAD_REQUEST,
                    'error processing http request {0}', request.path)
Exemplo n.º 41
0
 def __len__(self):
     if not self._data:
         self._data = dict2cbor(self.dump())
     return len(self._data)
Exemplo n.º 42
0
    def render_POST(self, request):
        """
        Handle a POST request on the HTTP interface. All message on the POST
        interface are gossip messages that should be relayed into the gossip
        network as is.
        """
        # pylint: disable=invalid-name

        # break the path into its component parts
        components = request.path.split('/')
        while components and components[0] == '':
            components.pop(0)

        prefix = components.pop(0) if components else 'error'
        if prefix not in self.PostPageMap:
            prefix = 'default'

        # process the message encoding
        encoding = request.getHeader('Content-Type')
        data = request.content.getvalue()

        try:
            if encoding == 'application/json':
                minfo = json2dict(data)
            elif encoding == 'application/cbor':
                minfo = cbor2dict(data)
            else:
                return self.error_response(request, http.BAD_REQUEST,
                                           'unknown message encoding, {0}',
                                           encoding)

            typename = minfo.get('__TYPE__', '**UNSPECIFIED**')
            if typename not in self.Ledger.MessageHandlerMap:
                return self.error_response(
                    request, http.BAD_REQUEST,
                    'received request for unknown message type, {0}', typename)

            msg = self.Ledger.MessageHandlerMap[typename][0](minfo)

        except:
            logger.info('exception while decoding http request %s; %s',
                        request.path, traceback.format_exc(20))
            return self.error_response(
                request, http.BAD_REQUEST,
                'unabled to decode incoming request {0}',
                data)

        # and finally execute the associated method and send back the results
        try:
            response = self.PostPageMap[prefix](request, components, msg)

            request.responseHeaders.addRawHeader("content-type", encoding)
            if encoding == 'application/json':
                result = dict2json(response.dump())
            else:
                result = dict2cbor(response.dump())

            return result

        except Error as e:
            return self.error_response(
                request, int(e.status),
                'exception while processing request {0}; {1}', request.path,
                str(e))

        except:
            logger.info('exception while processing http request %s; %s',
                        request.path, traceback.format_exc(20))
            return self.error_response(request, http.BAD_REQUEST,
                                       'error processing http request {0}',
                                       request.path)
Exemplo n.º 43
0
    def postmsg(self, msgtype, info):
        """
        Post a transaction message to the validator, parse the returning CBOR
        and return the corresponding dictionary.
        """

        data = dict2cbor(info)
        datalen = len(data)
        url = urlparse.urljoin(self._base_url, msgtype)

        LOGGER.debug('post transaction to %s with DATALEN=%d, DATA=<%s>', url,
                     datalen, data)

        try:
            request = urllib2.Request(url, data,
                                      {'Content-Type': 'application/cbor',
                                       'Content-Length': datalen})

            if self._cookie:
                request.add_header('cookie', self._cookie)

            opener = urllib2.build_opener(self._proxy_handler)
            response = opener.open(request, timeout=10)
            if not self._cookie:
                self._cookie = response.headers.get('Set-Cookie')
        except urllib2.HTTPError as err:
            content = err.read()
            if content is not None:
                headers = err.info()
                encoding = headers.get('Content-Type')

                if encoding == 'application/json':
                    value = json2dict(content)
                elif encoding == 'application/cbor':
                    value = cbor2dict(content)
                else:
                    LOGGER.warn('operation failed with response: %s', err.code)
                    raise MessageException(
                        'operation failed with response: {0}'.format(err.code))
                LOGGER.warn('operation failed with response: %s %s',
                            err.code, str(value))
                if "errorType" in value:
                    if value['errorType'] == "InvalidTransactionError":
                        raise InvalidTransactionError(
                            value['error'] if 'error' in value else value)
                    else:
                        raise MessageException(str(value))
            else:
                raise MessageException(
                    'operation failed with response: {0}'.format(err.code))
        except urllib2.URLError as err:
            LOGGER.warn('operation failed: %s', err.reason)
            raise MessageException('operation failed: {0}'.format(err.reason))

        except:
            LOGGER.warn('no response from server')
            raise MessageException('no response from server')

        content = response.read()
        headers = response.info()
        response.close()

        encoding = headers.get('Content-Type')

        if encoding == 'application/json':
            value = json2dict(content)
        elif encoding == 'application/cbor':
            value = cbor2dict(content)
        else:
            LOGGER.info('server responds with message %s of type %s', content,
                        encoding)
            return None

        LOGGER.debug(pretty_print_dict(value))
        return value
Exemplo n.º 44
0
    def render_POST(self, request):
        """
        Handle a POST request on the HTTP interface. All message on the POST
        interface are gossip messages that should be relayed into the gossip
        network as is.
        """
        # pylint: disable=invalid-name

        # break the path into its component parts
        components = request.path.split('/')
        while components and components[0] == '':
            components.pop(0)

        prefix = components.pop(0) if components else 'error'
        if prefix not in self.PostPageMap:
            prefix = 'default'

        # process the message encoding
        encoding = request.getHeader('Content-Type')
        data = request.content.getvalue()

        try:
            if encoding == 'application/json':
                minfo = json2dict(data)
            elif encoding == 'application/cbor':
                minfo = cbor2dict(data)
            else:
                return self.error_response(request, http.BAD_REQUEST,
                                           'unknown message encoding, {0}',
                                           encoding)

            typename = minfo.get('__TYPE__', '**UNSPECIFIED**')
            if typename not in self.Ledger.MessageHandlerMap:
                return self.error_response(
                    request, http.BAD_REQUEST,
                    'received request for unknown message type, {0}', typename)

            msg = self.Ledger.MessageHandlerMap[typename][0](minfo)

        except:
            logger.info('exception while decoding http request %s; %s',
                        request.path, traceback.format_exc(20))
            return self.error_response(
                request, http.BAD_REQUEST,
                'unabled to decode incoming request {0}', data)

        # and finally execute the associated method and send back the results
        try:
            response = self.PostPageMap[prefix](request, components, msg)

            request.responseHeaders.addRawHeader("content-type", encoding)
            if encoding == 'application/json':
                return dict2json(response.dump())
            else:
                return dict2cbor(response.dump())

        except Error as e:
            return self.error_response(
                request, int(e.status),
                'exception while processing request {0}; {1}', request.path,
                str(e))

        except:
            logger.info('exception while processing http request %s; %s',
                        request.path, traceback.format_exc(20))
            return self.error_response(request, http.BAD_REQUEST,
                                       'error processing http request {0}',
                                       request.path)