Module: Fluent::PluginHelper::SocketOption

Included in:
Server, Socket
Defined in:
lib/fluent/plugin_helper/socket_option.rb

Constant Summary collapse

FORMAT_STRUCT_LINGER_WINDOWS =
'S!S!'
FORMAT_STRUCT_LINGER =

{ u_short l_onoff; u_short l_linger; }

'I!I!'
FORMAT_STRUCT_TIMEVAL =

{ int l_onoff; int l_linger; }

'L!L!'

Instance Method Summary collapse

Instance Method Details

#socket_option_set(sock, resolve_name: nil, nonblock: false, linger_timeout: nil, recv_timeout: nil, send_timeout: nil, receive_buffer_size: nil, send_keepalive_packet: nil) ⇒ Object



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
# File 'lib/fluent/plugin_helper/socket_option.rb', line 47

def socket_option_set(sock, resolve_name: nil, nonblock: false, linger_timeout: nil, recv_timeout: nil, send_timeout: nil, receive_buffer_size: nil, send_keepalive_packet: nil)
  unless resolve_name.nil?
    sock.do_not_reverse_lookup = !resolve_name
  end
  if nonblock
    sock.fcntl(Fcntl::F_SETFL, Fcntl::O_NONBLOCK)
  end
  if Fluent.windows?
    # To prevent closing socket forcibly on Windows,
    # this options shouldn't be set up when linger_timeout equals to 0 (including nil).
    # This unintended behavior always ocurrs on Windows when linger_timeout.to_i == 0.
    # This unintented behavior causes "Errno::ECONNRESET: An existing connection was forcibly
    # closed by the remote host." on Windows.
    if linger_timeout.to_i > 0
      if linger_timeout >= 2**16
        log.warn "maximum linger_timeout is 65535(2^16 - 1). Set to 65535 forcibly."
        linger_timeout = 2**16 - 1
      end
      optval = [1, linger_timeout.to_i].pack(FORMAT_STRUCT_LINGER_WINDOWS)
      socket_option_set_one(sock, :SO_LINGER, optval)
    end
  else
    if linger_timeout
      optval = [1, linger_timeout.to_i].pack(FORMAT_STRUCT_LINGER)
      socket_option_set_one(sock, :SO_LINGER, optval)
    end
  end
  if recv_timeout
    optval = [recv_timeout.to_i, 0].pack(FORMAT_STRUCT_TIMEVAL)
    socket_option_set_one(sock, :SO_RCVTIMEO, optval)
  end
  if send_timeout
    optval = [send_timeout.to_i, 0].pack(FORMAT_STRUCT_TIMEVAL)
    socket_option_set_one(sock, :SO_SNDTIMEO, optval)
  end
  if receive_buffer_size
    socket_option_set_one(sock, :SO_RCVBUF, receive_buffer_size.to_i)
  end
  if send_keepalive_packet
    socket_option_set_one(sock, :SO_KEEPALIVE, true)
  end
  sock
end

#socket_option_set_one(sock, option, value) ⇒ Object



91
92
93
94
95
# File 'lib/fluent/plugin_helper/socket_option.rb', line 91

def socket_option_set_one(sock, option, value)
  sock.setsockopt(::Socket::SOL_SOCKET, option, value)
rescue => e
  log.warn "failed to set socket option", sock: sock.class, option: option, value: value, error: e
end

#socket_option_validate!(protocol, resolve_name: nil, linger_timeout: nil, recv_timeout: nil, send_timeout: nil, receive_buffer_size: nil, send_keepalive_packet: nil) ⇒ Object

{ time_t tv_sec; suseconds_t tv_usec; }



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/fluent/plugin_helper/socket_option.rb', line 29

def socket_option_validate!(protocol, resolve_name: nil, linger_timeout: nil, recv_timeout: nil, send_timeout: nil, receive_buffer_size: nil, send_keepalive_packet: nil)
  unless resolve_name.nil?
    if protocol != :tcp && protocol != :udp && protocol != :tls
      raise ArgumentError, "BUG: resolve_name in available for tcp/udp/tls"
    end
  end
  if linger_timeout
    if protocol != :tcp && protocol != :tls
      raise ArgumentError, "BUG: linger_timeout is available for tcp/tls"
    end
  end
  if send_keepalive_packet
    if protocol != :tcp && protocol != :tls
      raise ArgumentError, "BUG: send_keepalive_packet is available for tcp/tls"
    end
  end
end