Ravn::Net::
Protocol
module
The Ravn
Helios local (P2P) messaging protocol
The valid protocol headers for this version, as normalized Symbols. See ::normalize_header
- VERSION
The version of the protocol supported by this verison of the library.
check_message_fields( fields )
Check the given hash
for well-formedness and required fields. Raises a Ravn::Net::Protocol::Error if there’s a problem.
def check_message_fields( fields )
raise Ravn::Net::MessageError,
"malformed event: expected a Hash, got a %p instead" % [ fields.class ] unless
fields.is_a?( Hash )
data = fields['data']
raise Ravn::Net::MessageError,
"malformed event: expected data field to be a Hash, got a %p instead" %
[ data.class ] unless data.is_a?( Hash )
version = fields['version'] or raise Ravn::Net::MessageError,
"missing required `version` field"
raise Ravn::Net::MessageError, "mismatched protocol versions" unless
Ravn::Net::Protocol.version == fields['version'].to_i
end
decode( headers, zre_event )
Decode the given zre_event
and return it as a Ravn::Net::Message
.
def decode( headers, zre_event )
type = Ravn::Net::Protocol.type_from_zre_event( zre_event )
fields = {}
case zre_event.type
when :SHOUT, :WHISPER
data = zre_event.multipart_msg[ 1 ] or
raise Ravn::Net::MessageError, "empty payload for %s event" % [ zre_event.type ]
fields = MessagePack.unpack( data )
self.check_message_fields( fields )
fields = self.normalize_fields( fields )
fields[ :origin_event ] = zre_event
self.log.debug "Unpacked message fields: %p" % [ fields ]
when :ENTER, :EXIT, :JOIN, :LEAVE, :EVASIVE, :SILENT, :LEADER, :STOP
fields = {
origin_event: zre_event,
source: zre_event.peer_uuid,
data: { peer_name: zre_event.peer_name, group: zre_event.group }
}
else
raise ArgumentError, "Unhandled ZRE event: %p" % [ zre_event ]
end
return Ravn::Net::Message.new( type, fields )
end
Return the given message
as the ZRE group it should be broadcast on, the message’s type, and, and an encoded data payload.
def encode( message )
group, type = message.type.split( '.', 2 )
data = MessagePack.pack( message.fields )
return group, type, data
end
normalize_fields( fields )
Return a copy of the given fields
with keys transformed to Symbols and invalid pairs removed.
def normalize_fields( fields )
fields = fields.transform_keys( &:to_sym ).filter do |key, _|
Ravn::Net::Message.valid_fields.include?( key )
end
fields[ :data ] = fields[ :data ].transform_keys( &:to_sym )
return fields
end
supported_version?( version )
Return true
if the specified protocol version
is supported.
def supported_version?( version )
return version.to_i == self.version
end
type_from_control_zre_event( event )
Return the type of message that will be created when wrapping the given ZRE control event
.
def type_from_control_zre_event( event )
return "mesh.%s" % [ event.type.to_s.downcase ]
end
type_from_message_zre_event( event )
Return the type of message that will created when wrapping the given ZRE message event
.
def type_from_message_zre_event( event )
return nil unless event.multipart?
type_suffix = event.msg.dup.force_encoding( 'utf-8' )
raise ArgumentError, "type frame isn't encoded as UTF-8" unless type_suffix.valid_encoding?
if event.type == :SHOUT
prefix = event.group or raise ArgumentError, "invalid event: no group"
return "%s.%s" % [ prefix, type_suffix ]
elsif event.type == :WHISPER
return "direct.%s" % [ type_suffix ]
else
return nil
end
end
type_from_zre_event( event )
Return the type string of the message that will be read from the given event
.
def type_from_zre_event( event )
case event.type
when :ENTER, :EXIT, :JOIN, :LEAVE, :EVASIVE, :SILENT, :STOP, :LEADER
return self.type_from_control_zre_event( event )
when :SHOUT, :WHISPER
return self.type_from_message_zre_event( event )
else
raise "Can't wrap %s ZRE events!" % [ event.type ]
end
end
Return the integer version of the Protocol
.
def version
return VERSION
end