Module: Midori::Server

Included in:
Connection
Defined in:
lib/midori/server.rb

Overview

Logic to EventMachine TCP Server, running inside Midori::Connection

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#apiClass

Returns inherited from Midori::API.

Returns:

  • (Class)

    inherited from Midori::API



12
# File 'lib/midori/server.rb', line 12

attr_accessor :request, :api, :websocket, :eventsource

#eventsourceMidori::EventSource

Returns defined eventsource instance.

Returns:



12
# File 'lib/midori/server.rb', line 12

attr_accessor :request, :api, :websocket, :eventsource

#requestMidori::Request

Returns raw request.

Returns:



12
13
14
# File 'lib/midori/server.rb', line 12

def request
  @request
end

#websocketMidori::WebSocket

Returns defined websocket instance.

Returns:



12
# File 'lib/midori/server.rb', line 12

attr_accessor :request, :api, :websocket, :eventsource

Instance Method Details

#call_event(event, args = []) ⇒ Object

To call a websocket event if it exist

Parameters:

  • event (Symbol)

    event name

  • args (Array) (defaults to: [])

    arg list



103
104
105
# File 'lib/midori/server.rb', line 103

def call_event(event, args = [])
  -> { @websocket.instance_exec(*args, &@websocket.events[event]) }.call unless @websocket.events[event].nil?
end

#receive_data(monitor) ⇒ Object

Logic of receiving data

Parameters:

  • monitor (String)

    the socket able to read



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/midori/server.rb', line 27

def receive_data(monitor)
  lambda do
    async_fiber(Fiber.new do
      begin
        _sock_domain, remote_port, _remote_hostname, remote_ip = monitor.io.peeraddr
        port, ip = remote_port, remote_ip
        @request.ip = ip
        @request.port = port
        data = monitor.io.read_nonblock(16_384)
        if @request.parsed? && @request.body_parsed?
          websocket_request(StringIO.new(data))
        else
          @request.parse(data)
          receive_new_request if @request.parsed && @request.body_parsed?
        end
      rescue => e
        close_connection
        @logger.warn "#{@request.ip} - - #{e.class} #{e.backtrace.join("\n")}".yellow
      end
    end)
  end.call
end

#receive_new_requestObject

Logic of receiving new request



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

def receive_new_request
  begin
    start_time = Time.now
    @response = @api.receive(request, self)
    now_time = Time.now
    @logger.info "#{@request.ip} - - \"#{@request.method} #{@request.path} HTTP/#{@request.protocol.join('.')}\" #{@response.status} #{sprintf("%.6f", now_time.to_f - start_time.to_f)}".green
    call_event(:open) if @request.websocket?
  rescue Midori::Exception::NotFound => e
    @response = Midori::Sandbox.capture(e)
  rescue => e
    @response = Midori::Sandbox.capture(e)
    @logger.error e.inspect.red
    @logger.warn e.backtrace.join("\n").yellow
  end
  unless @request.websocket? || @request.eventsource?
    send_data @response
    close_connection_after_writing
  end
end

#server_initialize(api, logger) ⇒ Object

Define server behaviour

Parameters:

  • api (Class)

    inherited from Midori::API

  • logger (Logger)

    global logger



17
18
19
20
21
22
23
# File 'lib/midori/server.rb', line 17

def server_initialize(api, logger)
  @api = api
  @logger = logger
  @request = Midori::Request.new
  @websocket = Midori::WebSocket.new(self)
  @eventsource = Midori::EventSource.new(self)
end

#websocket_request(data) ⇒ Object

Logic of receiving WebSocket request

Parameters:

  • data (StringIO)

    raw data



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
# File 'lib/midori/server.rb', line 73

def websocket_request(data)
  @websocket.decode(data)
  case @websocket.opcode
  when 0x1, 0x2
    call_event(:message, [@websocket.msg])
  when 0x9
    @websocket.pong(@websocket.msg)
    call_event(:ping)
  when 0xA
    call_event(:pong)
  end
rescue Midori::Exception::FrameEnd => _e
  call_event(:close)
  send_data "\b" # Opcode 0x8
  close_connection_after_writing
rescue Midori::Exception::PingPongSizeTooLarge => e
  @logger.warn e.inspect.yellow
  call_event(:error) # Too large ping request
  send_data "\b" # Opcode 0x8
  close_connection_after_writing
rescue => e
  call_event(:error)
  @logger.error e.inspect.red
  @logger.warn e.backtrace.join("\n").yellow
  close_connection_after_writing
end