Class: Aikido::Zen::IPC::Server

Inherits:
Object
  • Object
show all
Includes:
Handshake::Server
Defined in:
lib/aikido/zen/ipc/ipc.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(secret, host = "127.0.0.1", port = 0, handshake_timeout: IPC::HANDSHAKE_TIMEOUT) ⇒ Server

Returns a new instance of Server.



306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
# File 'lib/aikido/zen/ipc/ipc.rb', line 306

def initialize(
  secret,
  host = "127.0.0.1",
  port = 0,
  handshake_timeout: IPC::HANDSHAKE_TIMEOUT
)
  @secret = secret
  @handshake_timeout = handshake_timeout

  @running = Concurrent::AtomicBoolean.new(false)

  @server = TCPServer.new(host, port)
  @host = @server.addr[3]
  @port = @server.addr[1]

  @sockets = Concurrent::Array.new
end

Instance Attribute Details

#hostObject (readonly)

Returns the value of attribute host.



291
292
293
# File 'lib/aikido/zen/ipc/ipc.rb', line 291

def host
  @host
end

#portObject (readonly)

Returns the value of attribute port.



292
293
294
# File 'lib/aikido/zen/ipc/ipc.rb', line 292

def port
  @port
end

Class Method Details

.start(secret, host = "127.0.0.1", port = 0, handshake_timeout: IPC::HANDSHAKE_TIMEOUT, &block) ⇒ Object



294
295
296
297
298
299
300
301
302
303
304
# File 'lib/aikido/zen/ipc/ipc.rb', line 294

def self.start(
  secret,
  host = "127.0.0.1",
  port = 0,
  handshake_timeout: IPC::HANDSHAKE_TIMEOUT,
  &block
)
  server = new(secret, host, port, handshake_timeout: handshake_timeout)
  server.start(&block)
  server
end

Instance Method Details

#accept(&block) ⇒ Object



324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
# File 'lib/aikido/zen/ipc/ipc.rb', line 324

def accept(&block)
  socket = @server.accept

  @sockets << socket

  Thread.new do
    begin
      handshake(socket, @secret, @handshake_timeout)
    rescue Handshake::Error
      # rejected connection
    else
      # accepted connection
      block.call(socket)
    end
  ensure
    @sockets.delete(socket)

    socket.close
  end
end

#closeObject



345
346
347
# File 'lib/aikido/zen/ipc/ipc.rb', line 345

def close
  @server.close
end

#start(&block) ⇒ Object

Raises:

  • (ArgumentError)


349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
# File 'lib/aikido/zen/ipc/ipc.rb', line 349

def start(&block)
  raise ArgumentError, "block required" unless block

  return false unless @running.make_true

  Thread.new do
    loop do
      accept do |socket|
        # accepted connection
        block.call(socket)
      end
    end
  rescue IOError
    # server stopped
  ensure
    @running.make_false

    close
  end

  true
end

#stop(&block) ⇒ Object



372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
# File 'lib/aikido/zen/ipc/ipc.rb', line 372

def stop(&block)
  return false unless @running.make_false

  block&.call

  close

  @sockets.each do |socket|
    # shutdown(SHUT_RDWR) wakes every thread in every process blocked in
    # read or write (or select) on the socket.
    socket.shutdown(Socket::SHUT_RDWR)
  rescue IOError
    # already closed
  end

  true
end