Class: Lumberjack::Beats::Server

Inherits:
Object
  • Object
show all
Defined in:
lib/lumberjack/beats/server.rb

Constant Summary collapse

SOCKET_TIMEOUT =

seconds

1

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Server

Create a new Lumberjack server.

  • options is a hash. Valid options are:

  • :port - the port to listen on

  • :address - the host/address to bind to

  • :ssl_certificate - the path to the ssl cert to use

  • :ssl_key - the path to the ssl key to use

  • :ssl_key_passphrase - the key passphrase (optional)



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/lumberjack/beats/server.rb', line 25

def initialize(options={})
  @options = {
    :port => 0,
    :address => "0.0.0.0",
    :ssl => true,
    :ssl_certificate => nil,
    :ssl_key => nil,
    :ssl_key_passphrase => nil,
    :ssl_certificate_authorities => nil,
    :ssl_verify_mode => :none # By default we dont verify client
  }.merge(options)

  if @options[:ssl]
    if verify_client?(@options[:ssl_verify_mode]) && certificate_authorities.empty?
      raise "When `ssl_verify_mode` is set to `peer` OR `force_peer` you need to specify the `ssl_certificate_authorities`"
    end

    if !verify_client?(@options[:ssl_verify_mode]) && certificate_authorities.size > 0 
      raise "When `ssl_certificate_authorities` is configured you need to set `ssl_verify_mode` to either `peer` or `force_peer`"
    end

    if @options[:ssl_certificate].nil? || @options[:ssl_key].nil?
      raise "You must specify `ssl_certificate` AND `ssl_key`"
    end
  end

  @server = TCPServer.new(@options[:address], @options[:port])
  @close = Concurrent::AtomicBoolean.new
  @port = retrieve_current_port

  setup_ssl if ssl?
end

Instance Attribute Details

#portObject (readonly)

Returns the value of attribute port.



14
15
16
# File 'lib/lumberjack/beats/server.rb', line 14

def port
  @port
end

Instance Method Details

#accept(&block) ⇒ Object



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/lumberjack/beats/server.rb', line 91

def accept(&block)
  begin
    socket = @server.accept_nonblock
    # update the socket with a SSL layer
    socket = accept_ssl(socket) if ssl?

    if block_given?
      block.call(socket, self)
    else
      return Connection.new(socket, self)
    end
  rescue OpenSSL::SSL::SSLError, IOError, EOFError, Errno::EBADF
    socket.close rescue nil
    retry unless closed?
  rescue IO::WaitReadable, Errno::EAGAIN # Resource not ready yet, so lets try again
    begin
      IO.select([@server], nil, nil, SOCKET_TIMEOUT)
      retry unless closed?
    rescue IOError, Errno::EBADF => e # we currently closing
      raise e unless closed?
    end
  end
end

#accept_ssl(tcp_socket) ⇒ Object



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/lumberjack/beats/server.rb', line 115

def accept_ssl(tcp_socket)
  ssl_socket = OpenSSL::SSL::SSLSocket.new(tcp_socket, @ssl)
  ssl_socket.sync_close

  begin
    ssl_socket.accept_nonblock

    return ssl_socket
  rescue IO::WaitReadable # handshake
    IO.select([ssl_socket], nil, nil, SOCKET_TIMEOUT)
    retry unless closed?
  rescue IO::WaitWritable # handshake
    IO.select(nil, [ssl_socket], nil, SOCKET_TIMEOUT)
    retry unless closed?
  end
end

#closeObject



136
137
138
139
# File 'lib/lumberjack/beats/server.rb', line 136

def close
  @close.make_true
  @server.close unless @server.closed?
end

#closed?Boolean

Returns:

  • (Boolean)


132
133
134
# File 'lib/lumberjack/beats/server.rb', line 132

def closed?
  @close.value
end

#run(&block) ⇒ Object

Server#run method, allow the library to manage all the connection threads, this handing is quite minimal and don’t handler all the possible cases deconnection/connection.

To have a more granular control over the connection you should manage them yourself, see Server#accept method which return a Connection instance.



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/lumberjack/beats/server.rb', line 65

def run(&block)
  while !closed?
    connection = accept

    # Some exception may occur in the accept loop
    # we will try again in the next iteration
    # unless the server is closing
    next unless connection

    Thread.new(connection) do |connection|
      begin
        connection.run(&block)
      rescue Lumberjack::Beats::Connection::ConnectionClosed
        # Connection will raise a wrapped exception upstream,
        # but if the threads are managed by the library we can simply ignore it.
        #
        # Note: This follow the previous behavior of the perfect silence.
      end
    end
  end
end

#ssl?Boolean

def run

Returns:

  • (Boolean)


87
88
89
# File 'lib/lumberjack/beats/server.rb', line 87

def ssl?
  @options[:ssl]
end