Class: Vici::Transport
- Inherits:
-
Object
- Object
- Vici::Transport
- Defined in:
- lib/vici.rb
Overview
The Transport class implements to low level segmentation of packets to the underlying transport stream. Directly using this class is usually not required.
Constant Summary collapse
- CMD_REQUEST =
0- CMD_RESPONSE =
1- CMD_UNKNOWN =
2- EVENT_REGISTER =
3- EVENT_UNREGISTER =
4- EVENT_CONFIRM =
5- EVENT_UNKNOWN =
6- EVENT =
7
Instance Method Summary collapse
- #dispatch_event(name, message) ⇒ Object
-
#initialize(socket) ⇒ Transport
constructor
Create a transport layer using a provided socket for communication.
-
#read ⇒ Object
Read a packet from the transport socket.
- #read_and_dispatch_event ⇒ Object
- #read_and_dispatch_events ⇒ Object
-
#recv_all(len) ⇒ Object
Receive data from socket, until len bytes read.
-
#register(name, handler) ⇒ Object
Register a handler method for the given event name.
-
#request(name, message = nil) ⇒ Object
Send a command with a given name, and optionally a message.
-
#send_all(encoding) ⇒ Object
Send data to socket, until all bytes sent.
-
#unregister(name, handler) ⇒ Object
Unregister a handler method for the given event name.
-
#write(type, label, message) ⇒ Object
Write a packet prefixed by its length over the transport socket.
Constructor Details
#initialize(socket) ⇒ Transport
Create a transport layer using a provided socket for communication.
240 241 242 243 |
# File 'lib/vici.rb', line 240 def initialize(socket) @socket = socket @events = Hash.new end |
Instance Method Details
#dispatch_event(name, message) ⇒ Object
305 306 307 308 309 |
# File 'lib/vici.rb', line 305 def dispatch_event(name, ) @events[name].each do |handler| handler.call(name, ) end end |
#read ⇒ Object
Read a packet from the transport socket. Returns the packet type, and if available in the packet a label and the contained message.
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 |
# File 'lib/vici.rb', line 285 def read len = recv_all(4).unpack("N")[0] encoding = recv_all(len) type = encoding.unpack("c")[0] len = 1 case type when CMD_REQUEST, EVENT_REGISTER, EVENT_UNREGISTER, EVENT label = encoding[2, encoding[1].unpack("c")[0]] len += label.length + 1 when CMD_RESPONSE, CMD_UNKNOWN, EVENT_CONFIRM, EVENT_UNKNOWN label = nil else raise TransportError, "invalid message: #{type}" end if encoding.length == len return type, label, Message.new end return type, label, Message.new(encoding[len..-1]) end |
#read_and_dispatch_event ⇒ Object
311 312 313 314 315 316 317 318 319 |
# File 'lib/vici.rb', line 311 def read_and_dispatch_event type, label, = read p if type == EVENT dispatch_event(label, ) else raise TransportError, "unexpected message: #{type}" end end |
#read_and_dispatch_events ⇒ Object
321 322 323 324 325 326 327 328 329 330 |
# File 'lib/vici.rb', line 321 def read_and_dispatch_events loop do type, label, = read if type == EVENT dispatch_event(label, ) else return type, label, end end end |
#recv_all(len) ⇒ Object
Receive data from socket, until len bytes read
247 248 249 250 251 252 253 254 255 256 257 |
# File 'lib/vici.rb', line 247 def recv_all(len) encoding = "" while encoding.length < len do data = @socket.recv(len - encoding.length) if data.empty? raise TransportError, "connection closed" end encoding << data end encoding end |
#register(name, handler) ⇒ Object
Register a handler method for the given event name
350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 |
# File 'lib/vici.rb', line 350 def register(name, handler) write(EVENT_REGISTER, name, nil) type, label, = read_and_dispatch_events case type when EVENT_CONFIRM if @events.has_key?(name) @events[name] += [handler] else @events[name] = [handler]; end when EVENT_UNKNOWN raise EventUnknownError, name else raise EventError, "invalid response for #{name} register" end end |
#request(name, message = nil) ⇒ Object
Send a command with a given name, and optionally a message. Returns the reply message on success.
335 336 337 338 339 340 341 342 343 344 345 346 |
# File 'lib/vici.rb', line 335 def request(name, = nil) write(CMD_REQUEST, name, ) type, label, = read_and_dispatch_events case type when CMD_RESPONSE return when CMD_UNKNOWN raise CommandUnknownError, name else raise CommandError, "invalid response for #{name}" end end |
#send_all(encoding) ⇒ Object
Send data to socket, until all bytes sent
261 262 263 264 265 266 |
# File 'lib/vici.rb', line 261 def send_all(encoding) len = 0 while len < encoding.length do len += @socket.send(encoding[len..-1], 0) end end |
#unregister(name, handler) ⇒ Object
Unregister a handler method for the given event name
369 370 371 372 373 374 375 376 377 378 379 380 |
# File 'lib/vici.rb', line 369 def unregister(name, handler) write(EVENT_UNREGISTER, name, nil) type, label, = read_and_dispatch_events case type when EVENT_CONFIRM @events[name] -= [handler] when EVENT_UNKNOWN raise EventUnknownError, name else raise EventError, "invalid response for #{name} unregister" end end |
#write(type, label, message) ⇒ Object
Write a packet prefixed by its length over the transport socket. Type specifies the message, the optional label and message get appended.
271 272 273 274 275 276 277 278 279 280 |
# File 'lib/vici.rb', line 271 def write(type, label, ) encoding = "" if label encoding << label.length << label end if encoding << .encoding end send_all([encoding.length + 1, type].pack("Nc") + encoding) end |