Class: Gopher::Dispatcher

Inherits:
EventMachine::Connection
  • Object
show all
Defined in:
lib/gopher2000/dispatcher.rb

Overview

Handle communication between Server and the actual gopher Application

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#appObject

the Application we are running



11
12
13
# File 'lib/gopher2000/dispatcher.rb', line 11

def app
  @app
end

Instance Method Details

#call!(request) ⇒ Object

generate a request object from an incoming selector, and dispatch it to the app

Parameters:

  • request (Request)

    Request object to handle

Returns:

  • Response object



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/gopher2000/dispatcher.rb', line 52

def call!(request)
  operation = proc {
    app.dispatch(request)
  }
  callback = proc {|result|
    send_response result
    close_connection_after_writing
  }

  #
  # if we don't want to block on slow calls, use EM#defer
  # @see http://eventmachine.rubyforge.org/EventMachine.html#M000486
  #
  if app.non_blocking?
    EventMachine.defer( operation, callback )
  else
    callback.call(operation.call)
  end
end

#end_of_transmissionObject

Add the period on a line by itself that closes the connection

Returns:

  • valid string to mark end of transmission as specified in RFC1436



93
94
95
# File 'lib/gopher2000/dispatcher.rb', line 93

def end_of_transmission
  [Gopher::Rendering::LINE_ENDING, ".", Gopher::Rendering::LINE_ENDING].join
end

#receive_data(data) ⇒ Object

called by EventMachine when there's an incoming request

Parameters:

  • selector (String)

    incoming selector

Returns:

  • Response object



28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/gopher2000/dispatcher.rb', line 28

def receive_data data
  (@buf ||= '') << data
  first_line = true

  ip_address = remote_ip
  while line = @buf.slice!(/(.*)\r?\n/)
    is_proxy = first_line && line.match?(/^PROXY TCP[4,6] /)
    receive_line(line, ip_address) unless is_proxy
    ip_address = line.split(/ /)[2] if is_proxy

    first_line = false
  end
end

#receive_line(line, ip_address) ⇒ Object

Invoked with lines received over the network



43
44
45
# File 'lib/gopher2000/dispatcher.rb', line 43

def receive_line(line, ip_address)
  call! Request.new(line, ip_address)
end

#remote_ipObject

get the IP address of the client

Returns:

  • ip address



17
18
19
# File 'lib/gopher2000/dispatcher.rb', line 17

def remote_ip
  Socket.unpack_sockaddr_in(get_peername).last
end

#send_response(response) ⇒ Object

send the response back to the client

Parameters:



76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/gopher2000/dispatcher.rb', line 76

def send_response(response)
  case response
  when Gopher::Response then send_response(response.body)
  when String then send_data(response + end_of_transmission)
  when StringIO then send_data(response.read + end_of_transmission)
  when File
    while chunk = response.read(8192) do
      send_data(chunk)
    end
    response.close
  end
end