Class: ManiaRPC::ManiaConnection

Inherits:
Object
  • Object
show all
Includes:
XMLRPC::ParserWriterChooseMixin
Defined in:
lib/maniaplanet_rpc/maniaplanet_client.rb

Instance Method Summary collapse

Constructor Details

#initialize(ip, port, callback) ⇒ ManiaConnection

Returns a new instance of ManiaConnection.



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/maniaplanet_rpc/maniaplanet_client.rb', line 9

def initialize(ip, port, callback)
  @callback = callback
  @request_handle = 0x80000000
  @ip = ip
  @port = port
  @send_queue = Queue.new
  begin
    @socket = TCPSocket.new ip, port
  rescue
    puts "Failed to establish a connection, is the ManiaPlanet server really running?"
    exit
  end
  @protocol = 0
  handshake
end

Instance Method Details

#call(method, *args) ⇒ Object



50
51
52
53
54
# File 'lib/maniaplanet_rpc/maniaplanet_client.rb', line 50

def call(method, *args)
  @request_handle = @request_handle + 1
  @send_queue.push [@request_handle, create().methodCall(method, *args)]
  @request_handle - 0x80000000
end

#handshakeObject



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/maniaplanet_rpc/maniaplanet_client.rb', line 25

def handshake
  header = @socket.recv(4).unpack "Vsize"

  if header[0] > 64
    raise Exception, "Wrong low-level protocol header!"
  end

  handshake = @socket.recv header[0]

  if handshake == "GBXRemote 1"
    @protocol = 1
  elsif handshake == "GBXRemote 2"
    @protocol = 2
  else
    raise Exception, "Unknown protocol version!"
  end
end

#readObject



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/maniaplanet_rpc/maniaplanet_client.rb', line 61

def read
  if IO.select([@socket], nil, nil, 0) != nil
    if @protocol == 1
      content = @socket.recv 4
      if content.bytesize == 0
        raise Exception, "Cannot read size!"
      end
      result = content.unpack "Vsize"
      size = result[0]
      receive_handle = @request_handle
    else
      content = @socket.recv 8
      if content.bytesize == 0
        raise Exception, "Cannot read size/handle!"
      end
      result = content.unpack "Vsize/Vhandle"
      size = result[0]
      receive_handle = result[1]
    end

    if receive_handle == 0 || size == 0
      raise Exception, "Connection interrupted!"
    end

    if size > 4096 * 1024
      raise Exception, "Response too large!"
    end

    response = ""
    response_length = 0

    while response_length < size
      response << @socket.recv(size - response_length)
      response_length = response.bytesize
    end

    begin # Response
      response = parser().parseMethodResponse(response)
      @callback.response_map[receive_handle].call response
    rescue Exception # Callback
      response = parser().parseMethodCall(response)
      @callback.parse_callback response
    end
  end
end

#startObject



43
44
45
46
47
48
# File 'lib/maniaplanet_rpc/maniaplanet_client.rb', line 43

def start
  loop do
    sleep(1.0/24.0)
    tick
  end
end

#tickObject



56
57
58
59
# File 'lib/maniaplanet_rpc/maniaplanet_client.rb', line 56

def tick
  write
  read
end

#writeObject



107
108
109
110
111
112
113
114
115
116
117
# File 'lib/maniaplanet_rpc/maniaplanet_client.rb', line 107

def write
  while @send_queue.length > 0
    request = @send_queue.pop
    if @protocol == 1
      bytes = [request[1].bytesize, request[1]].pack("Va*")
    else
      bytes = [request[1].bytesize, request[0], request[1]].pack("VVa*")
    end
    @socket.write bytes
  end
end