Module: Zerg::Support::Sockets::ProtocolAdapter

Defined in:
lib/zerg_support/sockets/protocol_adapter.rb

Overview

Adapts generic Protocol modules to modules that can extend sockets.

Defined Under Namespace

Classes: StateBase

Class Method Summary collapse

Class Method Details

.adapter_module(protocol_module, object_name = nil) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/zerg_support/sockets/protocol_adapter.rb', line 6

def self.adapter_module(protocol_module, object_name = nil)    
  unless object_name
    object_name = /(^|:)([^:]*)Protocol$/.
        match(protocol_module.name)[2].split(/(?=[A-Z])/).join('_').downcase
  end
  
  state_class = Class.new StateBase
  state_class.send :include, protocol_module
  state_class.class_eval do
    # Called by the protocol when an entire object is available.
    define_method :"received_#{object_name}" do |object|
      @recv_object_buffer << object
    end
  end
  
  adapter = Module.new
  adapter.module_eval do
    # Receives an object from a socket.
    define_method :"recv_#{object_name}" do
      @zerg_protocol_adapter_state ||= state_class.new self
      while @zerg_protocol_adapter_state.recv_object_buffer.empty?
        begin
          data = recv 65536
        rescue SystemCallError  # The other side closed the socket forcibly.
          break
        end
        break if data.empty?  # The other side closed the socket.

        @zerg_protocol_adapter_state.received_bytes data
      end
      @zerg_protocol_adapter_state.recv_object_buffer.shift
    end

    # Sends an object across a socket.
    define_method :"send_#{object_name}" do |object|
      @zerg_protocol_adapter_state ||= state_class.new self
      @zerg_protocol_adapter_state.send :"send_#{object_name}", object
    end
  end
  
  adapter
end