module Fluent::PluginHelper::SocketOption

Constants

FORMAT_STRUCT_LINGER
FORMAT_STRUCT_LINGER_WINDOWS

ref: docs.microsoft.com/en-us/windows/win32/api/winsock/ns-winsock-linger

FORMAT_STRUCT_TIMEVAL

Public Instance Methods

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) click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# 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