class PCP::Message

Represent a message that can be sent via PCP::Client

Attributes

envelope[R]

Read access to the @envelope property

@api public @return [Hash<Symbol,Object>]

Public Class Methods

new(envelope_or_bytes = {}) click to toggle source

Construct a new message or decode one

@api public @param envelope_or_bytes [Hash<Symbol,Object>,Array<Integer>]

When supplied a Hash it is taken as being a collection of
envelope fields.
When supplied an Array it is taken as being an array of
byte values, a message in wire format.

@return a new object

# File lib/pcp/message.rb, line 24
def initialize(envelope_or_bytes = {})
  @chunks = ['', '']

  case envelope_or_bytes
  when Array
    # it's bytes
    decode(envelope_or_bytes)
  when Hash
    # it's an envelope
    default_envelope = {:id => SecureRandom.uuid}
    @envelope = default_envelope.merge(envelope_or_bytes)
  else
    raise ArgumentError, "Unhandled type"
  end
end

Public Instance Methods

[](key) click to toggle source

Get an envelope field

@api public @param key [Symbol] @return value associated with that key

# File lib/pcp/message.rb, line 65
def [](key)
  @envelope[key]
end
[]=(key, value) click to toggle source

Set an envelope field

@api public @param key [Symbol] @param value @return value

# File lib/pcp/message.rb, line 56
def []=(key, value)
  @envelope[key] = value
end
data() click to toggle source

Get the content of the data chunk

@api public @return current content of the data chunk

# File lib/pcp/message.rb, line 73
def data
  @chunks[0]
end
data=(value) click to toggle source

Sets the content for the data chunk

@api public @param value @return value

# File lib/pcp/message.rb, line 82
def data=(value)
  @chunks[0] = value
end
debug() click to toggle source

Get the content of the debug chunk

@api public @return current content of the debug chunk

# File lib/pcp/message.rb, line 90
def debug
  @chunks[1]
end
debug=(value) click to toggle source

Sets the content for the debug chunk

@api public @param value @return value

# File lib/pcp/message.rb, line 99
def debug=(value)
  @chunks[1] = value
end
encode() click to toggle source

Encodes the message as an array of byte values

@api public @return [Array<Integer>]

# File lib/pcp/message.rb, line 107
def encode
  chunks = []

  @chunks.each_index do |i|
    chunks << frame_chunk(i + 2, @chunks[i])
  end

  validate

  [1, frame_chunk(1, envelope.to_json), chunks].flatten
end
expires(seconds) click to toggle source

Set the expiry of the message

@api public @param seconds [Numeric] @return the object itself

# File lib/pcp/message.rb, line 45
def expires(seconds)
  @envelope[:expires] = (Time.now + seconds).utc.iso8601
  self
end
validate() click to toggle source

Validate the data in message against schema

@api public @return ignore

# File lib/pcp/message.rb, line 123
def validate
  RSchema.validate!(PCP::Protocol::Envelope, envelope)
end

Private Instance Methods

decode(bytes) click to toggle source

Decodes an array of bytes into the message

@api private @param bytes [Array<Integer>] @return ignore

# File lib/pcp/message.rb, line 134
def decode(bytes)
  version = bytes.shift

  unless version == 1
    raise "Can only handle type 1 messages"
  end

  while bytes.size > 0
    type = bytes.shift
    size = bytes.take(4).pack('C*').unpack('N')[0]
    bytes = bytes.drop(4)

    body = bytes.take(size).pack('C*')
    bytes = bytes.drop(size)

    if type == 1
      parsed = JSON.parse(body)
      @envelope = {}
      parsed.each do |k,v|
        @envelope[k.to_sym] = v
      end
      validate
    else
      @chunks[type - 2] = body
    end
  end
end
frame_chunk(type, body) click to toggle source

Frames a piece of data as a message chunk of given type

@api private @param type [Integer] @param body [String] @return [Array<Integer>]

# File lib/pcp/message.rb, line 168
def frame_chunk(type, body)
  size = [body.bytesize].pack('N').unpack('C*')
  [type, size, body.bytes.to_a].flatten
end