Class: RiderServer::Server

Inherits:
Object show all
Includes:
Logger
Defined in:
lib/rider_server/server.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Logger

configure_logger, log, #log

Constructor Details

#initialize(config) ⇒ Server

Returns a new instance of Server.



24
25
26
27
28
29
# File 'lib/rider_server/server.rb', line 24

def initialize(config)
  @config = config
  @status = :stopped

  RiderServer::Logger.configure_logger(level: @config.log_level)
end

Instance Attribute Details

#statusObject (readonly)

The status of the server, either :running or :stopped



22
23
24
# File 'lib/rider_server/server.rb', line 22

def status
  @status
end

Instance Method Details

#runObject

Start the servers main event loop. This will bind to the configured host and port, and create threads for sending and recieving requests.



34
35
36
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
106
107
# File 'lib/rider_server/server.rb', line 34

def run
  socket = listen(@config.host, @config.port)
  request_count = 0

  responses = Thread::Queue.new
  operations = RiderServer.create_operation_handler(@config, responses)

  loop do
    @status = :running
    client = socket[0].accept

    request_count += 1

    threads = []
    threads << Thread.new {
      log.debug "Starting response thread"
      loop do
        response = responses.pop

        if response == :shutdown
          break
        end

        begin
          output = response.bencode
        rescue => e
          log.error "Error encoding response: #{e}\n #{e.backtrace.join("\n")}"
          response = Response.new(response.to_h)
          response.set("ex", e.inspect)
          response.set("out", e.full_message)
          response.status("eval-error")
          output = response.bencode
        end

        if log.debug?
          log.debug "Sending response #{response.to_h}"
        else
          log.info "Sending response #{response.inspect}"
        end
        client.write(output)
        # Try to allow time for the client to read the response
        sleep 0.01
      end
    }

    threads << Thread.new {
      parser = BEncode::Parser.new(client)
      loop do
        # Peek at the next character, and exit if it is nil
        c = client.getc
        if c.nil?
          responses.push :shutdown
          log.debug("Connection closed, closing")
          break
        end
        client.ungetc(c)

        operation = parser.parse!

        log.debug(operation.inspect)

        begin
          operations.handle(::RiderServer::Request.new(operation))
        rescue => e
          log.error "Error handling request: #{e}\n #{e.backtrace}"
        end
      end
    }
    threads.each { |thr| thr.join }

    client.close
    @status = :stopped
  end
end