Skip to content

Commit

Permalink
better error handling during parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
mackuba committed Jul 1, 2023
1 parent 47ea89d commit 9fe5090
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 9 deletions.
11 changes: 11 additions & 0 deletions lib/skyfall/errors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,15 @@ class DecodeError < StandardError

class UnsupportedError < StandardError
end

class SubscriptionError < StandardError
attr_reader :error_type, :error_message

def initialize(error_type, error_message = nil)
@error_type = error_type
@error_message = error_message

super("Subscription error: #{error_type}" + (error_message ? " (#{error_message})" : ""))
end
end
end
37 changes: 28 additions & 9 deletions lib/skyfall/websocket_message.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,7 @@ class WebsocketMessage
attr_reader :type, :repo, :time, :seq, :commit, :prev, :blocks, :operations

def initialize(data)
objects = CBOR.decode_sequence(data)
raise DecodeError.new("Invalid number of objects: #{objects.length}") unless objects.length == 2

@type_object, @data_object = objects
raise DecodeError.new("Invalid object type: #{@type_object}") unless @type_object.is_a?(Hash)
raise DecodeError.new("Invalid object type: #{@data_object}") unless @data_object.is_a?(Hash)
raise DecodeError.new("Missing data: #{@type_object}") unless @type_object['op'] && @type_object['t']
raise DecodeError.new("Invalid message type: #{@type_object['t']}") unless @type_object['t'].start_with?('#')
raise UnsupportedError.new("Unexpected CBOR object: #{@type_object}") unless @type_object['op'] == 1
@type_object, @data_object = decode_cbor_objects(data)

@type = @type_object['t'][1..-1].to_sym
@operations = []
Expand Down Expand Up @@ -54,5 +46,32 @@ def inspect
vars = keys.map { |v| "#{v}=#{instance_variable_get(v).inspect}" }.join(", ")
"#<#{self.class}:0x#{object_id} #{vars}>"
end

private

def decode_cbor_objects(data)
objects = CBOR.decode_sequence(data)

if objects.length < 2
raise DecodeError.new("Malformed message: #{objects.inspect}")
elsif objects.length > 2
raise DecodeError.new("Invalid number of objects: #{objects.length}")
end

type_object, data_object = objects

if data_object['error']
raise SubscriptionError.new(data_object['error'], data_object['message'])
end

raise DecodeError.new("Invalid object type: #{type_object}") unless type_object.is_a?(Hash)
raise UnsupportedError.new("Unexpected CBOR object: #{type_object}") unless type_object['op'] == 1
raise DecodeError.new("Missing data: #{type_object} #{objects.inspect}") unless type_object['op'] && type_object['t']
raise DecodeError.new("Invalid message type: #{type_object['t']}") unless type_object['t'].start_with?('#')

raise DecodeError.new("Invalid object type: #{data_object}") unless data_object.is_a?(Hash)

[type_object, data_object]
end
end
end

0 comments on commit 9fe5090

Please sign in to comment.