Class: Revactor::Filter::Packet

Inherits:
Object
  • Object
show all
Defined in:
lib/revactor/filters/packet.rb

Overview

A filter for “packet” protocols which are framed using a fix-sized length prefix followed by a message body, such as DRb. Either 16-bit or 32-bit prefixes are supported.

Instance Method Summary collapse

Constructor Details

#initialize(size = 4) ⇒ Packet

Returns a new instance of Packet.



17
18
19
20
21
22
23
24
25
26
27
# File 'lib/revactor/filters/packet.rb', line 17

def initialize(size = 4)
  unless size == 2 or size == 4
    raise ArgumentError, 'only 2 or 4 byte prefixes are supported' 
  end
  
  @prefix_size = size
  @data_size = 0
  
  @mode = :prefix
  @buffer = IO::Buffer.new
end

Instance Method Details

#decode(data) ⇒ Object

Callback for processing incoming frames



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/revactor/filters/packet.rb', line 30

def decode(data)
  received = []
  @buffer << data

  begin  
    if @mode == :prefix
      break if @buffer.size < @prefix_size
      prefix = @buffer.read @prefix_size
      @data_size = prefix.unpack(@prefix_size == 2 ? 'n' : 'N').first
      @mode = :data
    end
  
    break if @buffer.size < @data_size
    received << @buffer.read(@data_size)
    @mode = :prefix
  end until @buffer.empty?
  
  received
end

#encode(*data) ⇒ Object

Send a packet with a specified size prefix



51
52
53
54
55
56
# File 'lib/revactor/filters/packet.rb', line 51

def encode(*data)
  data.inject('') do |s, d|
    raise ArgumentError, 'packet too long for prefix length' if d.size >= 256 ** @prefix_size
    s << [d.size].pack(@prefix_size == 2 ? 'n' : 'N') << d
  end
end