Class: RBus::Message::Reader

Inherits:
Object
  • Object
show all
Includes:
HeaderFields, MessageTypes
Defined in:
lib/rbus/message/reader.rb

Overview

Reads and parses a message

Constant Summary

Constants included from HeaderFields

HeaderFields::DESTINATION, HeaderFields::ERROR_NAME, HeaderFields::INTERFACE, HeaderFields::MEMBER, HeaderFields::PATH, HeaderFields::REPLY_SERIAL, HeaderFields::SENDER, HeaderFields::SIGNATURE

Constants included from MessageTypes

MessageTypes::ERROR, MessageTypes::INVALID, MessageTypes::METHOD_CALL, MessageTypes::METHOD_RETURN, MessageTypes::SIGNAL

Instance Method Summary collapse

Constructor Details

#initialize(transport) ⇒ Reader

Returns a new instance of Reader.



32
33
34
# File 'lib/rbus/message/reader.rb', line 32

def initialize(transport)
  @transport = transport
end

Instance Method Details

#read_messageObject

Read one message from the transport, unmarshal and return



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/rbus/message/reader.rb', line 37

def read_message
  header = @transport.read(12)
  return nil if header.nil?
  
  endian = header.dbus_unmarshal('y')
  header_info = header.dbus_unmarshal('yyyyuu', endian)
  
  unless header_info[3] == VERSION::PROTOCOL
    raise InvalidProtocolException, "Message with version '#{header_info[3]}'"
  end
  
  # Read first header length, then header fields
  hl_raw = @transport.read(4)
  header_length = hl_raw.dbus_unmarshal('u', endian)
  hf_raw = @transport.read(header_length)
  
  # Hack:
  # The padding in the middle is because we do not start on a
  # 8-byte boundary and the dbus_marshal method is doing the
  # right thing... it's a TODO. :)
  header_fields = (hl_raw + "\0\0\0\0" + hf_raw).dbus_unmarshal('a(yv)', endian)

  # Go to 8-byte boundary
  @transport.read(-(header+hl_raw+hf_raw).length & 7)

  body = @transport.read(header_info[4])
  #Log.debug(body)

  klass = 
    case header_info[1]
      when METHOD_CALL
        MethodCall
      when METHOD_RETURN
        MethodReturn
      when ERROR
        Error
      when SIGNAL
        Signal
      else
        raise MessageException, "Invalid message type #{header_info[1]}"
    end

  message = klass.new
  message.flags = header_info[2]

  header_fields.each do |hf|
    case hf[0]
      when PATH
        message.object_path = hf[1].object
      when INTERFACE
        message.interface = hf[1].object
      when MEMBER
        message.member = hf[1].object
      when ERROR_NAME
        # TODO
      when REPLY_SERIAL
        message.serial = hf[1].object
      when DESTINATION
        message.destination = hf[1].object
      when SENDER
        message.sender = hf[1].object
      when SIGNATURE
        message.signature = hf[1].object
        message.arguments = body.dbus_unmarshal(hf[1].object, endian)
    end
  end
  #Log.debug(message)
  message
end