def deserialize_header(cls, data): """ Deserialize message's header :param data: bytes :return: datastructures.MessageHeader """ try: header = datastructures.MessageHeader( *struct.unpack(cls.HDR_FORMAT, data), ) except (struct.error, TypeError) as e: raise exceptions.HeaderError() from e logger.debug("deserialize_header(): %r", header) if not settings.MIN_TIMESTAMP < header.timestamp < \ settings.MAX_TIMESTAMP: raise exceptions.HeaderError( "Invalid timestamp {got}. Should be between {min_} and {max_}". format( got=header.timestamp, min_=settings.MIN_TIMESTAMP, max_=settings.MAX_TIMESTAMP, )) from golem_messages.message import registered_message_types if header.type_ not in registered_message_types: raise exceptions.HeaderError( "Unknown message type {got}".format(got=header.type_), ) return header
def override_timestamp(msg: 'Message', timestamp: int) -> None: new_hdr = datastructures.MessageHeader( msg.TYPE, timestamp, msg.encrypted, ) msg.header = new_hdr
def test_inequal_header_type(self): msg1 = message.RandVal(rand_val=1) msg2 = clone_message(msg1) msg2.header = datastructures.MessageHeader( msg1.header.type_ + 1, msg1.header.timestamp, msg1.header.encrypted, ) self.assertNotEqual(msg1, msg2)
def send_to_concent(msg: message.base.Message, signing_key: bytes, concent_variant: dict) -> typing.Optional[bytes]: """Sends a message to the concent server :return: Raw reply message, None or exception :rtype: Bytes|None """ logger.debug('send_to_concent(): Updating timestamp msg %r', msg) # Delayed messages are prepared before they're needed # and only sent to Concent if they're not cancelled # before. This can cause a situation where previously # prepared message will be too old to send when enqueued. # Also messages with no delay could have stayed in queue # long enough to eat significant amount of Message Transport Time # SEE: golem_messages.constants header = msg_datastructures.MessageHeader( msg.header.type_, # Using this tricky approach instead of time.time() # because of AppVeyor issues. calendar.timegm(time.gmtime()), msg.header.encrypted, ) msg.header = header logger.debug('send_to_concent(): Encrypting msg %r', msg) # if signature already exists, it must be set to None explicitly if msg.sig is not None: msg.sig = None data = golem_messages.dump(msg, signing_key, concent_variant['pubkey']) logger.debug('send_to_concent(): data: %r', data) concent_post_url = urljoin(concent_variant['url'], '/api/v1/send/') headers = { 'Content-Type': 'application/octet-stream', 'X-Golem-Messages': golem_messages.__version__, } try: logger.debug( 'send_to_concent(): POST %r hdr: %r', concent_post_url, headers, ) response = requests.post( concent_post_url, data=data, headers=headers, **ssl_kwargs(concent_variant), ) except requests.exceptions.RequestException as e: logger.warning('Concent RequestException %r', e) response = e.response verify_response(response) return response.content or None
def test_verify_updated_header(self): msg = message.Hello() self.add_sig(msg) msg2 = factories.helpers.clone_message( msg, override_header=datastructures.MessageHeader( msg.TYPE, msg.timestamp + 667, msg.encrypted, )) with self.assertRaises(exceptions.InvalidSignature): msg2.verify_signature(self.keys.raw_pubkey)
def __init__(self, header: datastructures.MessageHeader = None, sig=None, slots=None, deserialized=False, **kwargs): """Create a new message :param deserialized: was message created by .deserialize()? """ # Child message slots try: self.load_slots(slots) except exceptions.FieldError: raise except Exception as e: raise exceptions.MessageError('Load slots failed') from e # Set attributes for key in kwargs: if getattr(self, key, None) is None: try: setattr(self, key, kwargs[key]) except AttributeError: raise AttributeError("Can't set attribute `%s` on `%s`" % (key, self.__class__.__name__)) if deserialized and not (header and header.timestamp): warnings.warn('Message without header {}'.format(self), RuntimeWarning) # Header if header is None: header = datastructures.MessageHeader( self.TYPE, # Since epoch differs between OS, we use calendar.timegm() # instead of time.time() to unify it. calendar.timegm(time.gmtime()), False, ) self.header = header self.sig = sig
def test_timestamp_and_timezones(self, *_): epoch_t = 1475238345 def set_tz(tz): os.environ['TZ'] = tz try: time.tzset() except AttributeError: raise unittest.SkipTest("tzset required") set_tz('Europe/Warsaw') warsaw_time = time.localtime(epoch_t) msg_pre = message.Hello(header=datastructures.MessageHeader( message.Hello.TYPE, epoch_t, False, )) data = shortcuts.dump(msg_pre, None, None) set_tz('US/Eastern') msg_post = shortcuts.load(data, None, None) newyork_time = time.localtime(msg_post.timestamp) self.assertNotEqual(warsaw_time, newyork_time) self.assertEqual(time.gmtime(epoch_t), time.gmtime(msg_post.timestamp))
def encrypted(self, value): self.header = datastructures.MessageHeader( self.header.type_, self.header.timestamp, value, )