Ravn::Net::

Protocol module

The Ravn Helios local (P2P) messaging protocol

Constants

VALID_HEADERS

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.

Public Instance Methods

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.

# File lib/ravn/net/protocol.rb, line 175
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.

# File lib/ravn/net/protocol.rb, line 143
def decode( headers, zre_event )
        type = Ravn::Net::Protocol.type_from_zre_event( zre_event )
        fields = {}

        # Unpack the fields for message type events from the payload
        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
encode( message )

Return the given message as the ZRE group it should be broadcast on, the message’s type, and, and an encoded data payload.

# File lib/ravn/net/protocol.rb, line 134
def encode( message )
        group, type = message.type.split( '.', 2 )
        data = MessagePack.pack( message.fields )

        return group, type, data
end
node_headers()

A set of minimal headers that should be set on every node joining the network, returned as a Hash.

# File lib/ravn/net/protocol.rb, line 74
def node_headers
        return {
                ravn_net_version: Ravn::BDE::VERSION,
                helios_protocol_version: VERSION,
                content_type: 'application/messagepack',
                started_at: Ravn.time,
                node_id: Ravn::Net.node_id,
        }
end
normalize_fields( fields )

Return a copy of the given fields with keys transformed to Symbols and invalid pairs removed.

# File lib/ravn/net/protocol.rb, line 62
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
normalize_headers( header_hash )

Return a copy of the given header_hash that has its keys normalized to Symbols, and any invalid pairs removed.

# File lib/ravn/net/protocol.rb, line 50
def normalize_headers( header_hash )
        symbolized_hash = header_hash.transform_keys do |key|
                key.downcase.tr( '-', '_' ).to_sym
        end
        symbolized_hash.keep_if {|key, _| VALID_HEADERS.include?(key) }

        return symbolized_hash
end
supported_version?( version )

Return true if the specified protocol version is supported.

# File lib/ravn/net/protocol.rb, line 86
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.

# File lib/ravn/net/protocol.rb, line 108
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.

# File lib/ravn/net/protocol.rb, line 115
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.

# File lib/ravn/net/protocol.rb, line 94
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
version()

Return the integer version of the Protocol.

# File lib/ravn/net/protocol.rb, line 43
def version
        return VERSION
end