bricks v0.1.0 Bricks.Connector.Tcp View Source

A Connector for TCP sockets, using :gen_tcp

Belongs to application :bricks

Create Options

All

Ordering: Required first, then alphabetical

OptionType(s)DefaultRaw gen_tcp option
:hostbinary(REQUIRED)(POSITIONAL)
:portpos_integer(REQUIRED)(POSITIONAL)
:connect_timeouttimeout5000(POSITIONAL)
:bam_windowSocket.window10(NONE)
:activeSocket.activetrue:active
:bind_to_devicebinary(NONE):bind_to_device
:buffernon_neg_integer(UNKNOWN):buffer
:delay_send?booleanfalse:delay_send
:deliver:port, :term(UNKNOWN):deliver
:dont_route?boolean(false?):dontroute
:exit_on_close?booleantrue:exit_on_close
:header_sizenon_neg_integer(NONE):header
:high_msgq_watermarkpos_integer(UNKNOWN):high_msgq_watermark
:high_watermarknon_neg_integer(UNKNOWN):high_watermark
:ipv4?booleantrue:inet, :ipv6_v6only
:ipv6?booleanfalse:inet6, :ipv6_v6only
:keepalive?booleanfalse:keepalive
:line_delimiterchar?\n:line_delimiter
:linger?linger(NONE):linger
:local_portSocket.port_num0 (random):port
:low_msgq_watermarkpos_integer(UNKNOWN):low_msgq_watermark
:low_watermarknon_neg_integer(UNKNOWN):low_watermark
:network_interfaceSocket.host(NONE:ip, :ifaddr
:network_namespacebinary(NONE):netns
:nodelay?booleanfalse:nodelay
:packet_typepacket_type:raw:packet
:packet_sizepos_integer0 (no limit):packet_size
:prioritynon_neg_integer(NONE):priority
:raw_fdnon_neg_integer(NONE):fd
:receive_buffernon_neg_integer(NONE):recbuf
:receive_tclass?booleanfalse?:recvtclass
:receive_tos?booleanfalse?:recvtos
:receive_ttl?booleanfalse?:recvttl
:receive_timeouttimeout5000(POSITIONAL)
:send_timeouttimeout5000:send_timeout
:reuse_addr?booleanfalse:reuseaddr
:send_timeout_close?booleantrue:send_timeout_close
:show_econnreset?booleanfalse:show_econnreset
:send_buffernon_neg_integer(NONE):sndbuf
:tosnon_neg_integer(NONE):tos
:tclassnon_neg_integer(NONE):tclass
:tcp_moduleatom(SEE DOCS):tcp_module

Destination Selection

OptionTypeDefaultRaw gen_tcp option
:hostbinary(REQUIRED)(POSITIONAL)
:portpos_integer(REQUIRED)(POSITIONAL)

IP Version Selection

OptionTypeDefaultRaw gen_tcp option
:ipv4?booleantrue:inet, :ipv6_v6only
:ipv6?booleanfalse:inet6, :ipv6_v6only

These options toggle which IP versions may be used. At least one must be true or you will get an error.

Timeouts

OptionTypeDefaultRaw gen_tcp option
:connect_timeouttimeout5000(POSITIONAL)
:receive_timeouttimeout5000(POSITIONAL)
:send_timeouttimeout5000:send_timeout

These toggle how long you are prepared to wait for an operation to complete before a timeout error is returned. They are standard erlang timeout values: non-negative integers or :infinity.

Activity Control

OptionTypeDefaultRaw gen_tcp option
:activeSocket.activetrue:active
:bam_windowSocket.window10(NONE)

See discussion on socket activity modes in the Bricks.Socket module documentation for more information.

Erlang Options

OptionTypeDefaultRaw gen_tcp option
:buffernon_neg_integer(UNKNOWN):buffer
:delay_send?booleanfalse:delay_send
:exit_on_close?booleantrue:exit_on_close
:header_sizenon_neg_integer(NONE):header
:high_msgq_watermarkpos_integer(UNKNOWN):high_msgq_watermark
:high_watermarknon_neg_integer(UNKNOWN):high_watermark
:line_delimiterchar?\n:line_delimiter
:low_msgq_watermarkpos_integer(UNKNOWN):low_msgq_watermark
:low_watermarknon_neg_integer(UNKNOWN):low_watermark
:packet_typepacket_type:raw:packet
:send_timeout_close?booleantrue:send_timeout_close
:show_econnreset?booleanfalse:show_econnreset
:tcp_moduleatom(SEE DOCS):tcp_module
:tcp_optsproplist[](ANY)

:buffer

The size of the user-level buffer used by the driver. Not to be confused with options :send_buffer and :receive_buffer, which correspond to the Kernel socket buffers. For TCP it is recommended to have val(buffer) >= val(recbuf) to avoid performance issues because of unnecessary copying. However, as the size set for recbuf usually become larger, you are encouraged to use getopts/2 to analyze the behavior of your operating system.

Note that this is also the maximum amount of data that can be received from a single recv call. If you are using higher than normal MTU consider setting buffer higher.

:delay_send?

Normally, when an Erlang process sends to a socket, the driver tries to send the data immediately. If that fails, the driver uses any means available to queue up the message to be sent whenever the operating system says it can handle it. Setting delay_send: true makes all messages queue up. The messages sent to the network are then larger but fewer. The option affects the scheduling of send requests versus Erlang processes instead of changing any real property of the socket. The option is implementation-specific.

:exit_on_close?

The only reason to set it to false is if you want to continue sending data to the socket after a close is detected, for example, if the peer uses :gen_tcp.shutdown/2 to shut down the write side.

:header_size

This option is only meaningful if option binary was specified when the socket was created. If option header is specified, the first Size number bytes of data received from the socket are elements of a list, and the remaining data is a binary specified as the tail of the same list. For example, if set to 2, the data received matches [byte1,byte2|binary]

:high_msgq_watermark

The socket message queue is set to a busy state when the amount of data on the message queue reaches this limit. Notice that this limit only concerns data that has not yet reached the ERTS internal socket implementation. Defaults to 8 kB.

Senders of data to the socket are suspended if either the socket message queue is busy or the socket itself is busy.

For more information, see options :low_msgq_watermark, :high_watermark, and :low_watermark.

Notice that distribution sockets disable the use of :high_msgq_watermark and :low_msgq_watermark. Instead use the distribution buffer busy limit, which is a similar feature.

:high_watermark

The socket is set to a busy state when the amount of data queued internally by the ERTS socket implementation reaches this limit. Defaults to 8 kB.

Senders of data to the socket are suspended if either the socket message queue is busy or the socket itself is busy.

For more information, see options low_watermark, high_msgq_watermark, and low_msqg_watermark.

:line_delimiter

Sets the line delimiting character for line-oriented protocols (:line). Defaults to ?.

:low_msgq_watermark

If the socket message queue is in a busy state, the socket message queue is set in a not busy state when the amount of data queued in the message queue falls below this limit. Notice that this limit only concerns data that has not yet reached the ERTS internal socket implementation. Defaults to 4 kB.

Senders that are suspended because of either a busy message queue or a busy socket are resumed when the socket message queue and the socket are not busy.

For more information, see options :high_msgq_watermark, :high_watermark, and :low_watermark.

Notice that distribution sockets disable the use of :high_msgq_watermark and :low_msgq_watermark. Instead they use the distribution buffer busy limit, which is a similar feature.

:low_watermark

If the socket is in a busy state, the socket is set in a not busy state when the amount of data queued internally by the ERTS socket implementation falls below this limit. Defaults to 4 kB.

Senders that are suspended because of a busy message queue or a busy socket are resumed when the socket message queue and the socket are not busy.

For more information, see options :high_watermark, :high_msgq_watermark, and :low_msgq_watermark.

:packet_type

Defines the type of packets to use for a socket. Possible values:

:raw | 0 : No packaging is done.

1 | 2 | 4 : Packets consist of a header specifying the number of bytes in the packet, followed by that number of bytes. The header length can be one, two, or four bytes, and containing an unsigned integer in big-endian byte order. Each send operation generates the header, and the header is stripped off on each receive operation. The 4-byte header is limited to 2Gb.

:asn1 | :cdr | :sunrm | :fcgi | :tpkt | :line : These packet types only have effect on receiving. When sending a packet, it is the responsibility of the application to supply a correct header. On receiving, however, one message is sent to the controlling process for each complete packet received, and, similarly, each call to :gen_tcp.recv/2,3 returns one complete packet. The header is not stripped off.

The meanings of the packet types are as follows:

  • :asn1 - ASN.1 BER
  • :sunrm - Sun’s RPC encoding
  • :cdr - CORBA (GIOP 1.1)
  • :fcgi - Fast CGI
  • :tpkt - TPKT format [RFC1006]
  • :line - Line mode, a packet is a line-terminated with newline, lines longer than the receive buffer are truncated
:http | :http_bin

The Hypertext Transfer Protocol. The packets are returned with the format according to HttpPacket described in :erlang.decode_packet/3 in ERTS. A socket in passive mode returns {:ok, packet} from :gen_tcp.recv while an active socket sends messages like {http, socket_handle, packet}.

:httph | :httph_bin

These two types are often not needed, as the socket automatically switches from :http/:http_bin to :httph/:httph_bin internally after the first line is read. However, there can be occasions when they are useful, such as parsing trailers from chunked encoding.

:send_timeout_close?

Used together with :send_timeout to specify whether the socket is to be automatically closed when the send operation returns {:error,:timeout}. The recommended setting is true, which automatically closes the socket.

:show_econnreset?

When this option is set to false, which is default, an RST received from the TCP peer is treated as a normal close (as though an FIN was sent). A caller to :gen_tcp.recv/2 gets {:error, :closed}. In active mode, the controlling process receives a {:tcp_closed, socket_handle} message, indicating that the peer has closed the connection.

Setting this option to true allows you to distinguish between a connection that was closed normally, and one that was aborted (intentionally or unintentionally) by the TCP peer. A call to :gen_tcp.recv/2 returns {:error, :econnreset}. In active mode, the controlling process receives a {:tcp_error, socket_handle, :econnreset} message before the usual {:tcp_closed, socket_handle}, as is the case for any other socket error. Calls to :gen_tcp.send/2 also returns {:error, :econnreset} when it is detected that a TCP peer has sent an RST.

A connected socket returned from :gen_tcp.accept/1 inherits the :show_econnreset? setting from the listening socket.

:tcp_module

Overrides which callback module is used. Defaults to :inet_tcp for IPv4 and :inet6_tcp for IPv6.

:tcp_opts

Raw gen_tcp/inet options proplist. Appended to options.

OS options

OptionTypeDefaultRaw gen_tcp option
:bind_to_devicebinary(NONE):bind_to_device
:deliver:port, :term(UNKNOWN):deliver
:dont_route?boolean(false?):dontroute
:keepalive?booleanfalse:keepalive
:lingerlinger(NONE):linger
:local_portSocket.port_num0 (random):port
:network_interfaceSocket.host(NONE:ip, :ifaddr
:network_namespacebinary(NONE):netns
:nodelay?booleanfalse:nodelay
:packet_sizepos_integer0 (no limit):packet_size
:prioritynon_neg_integer(NONE):priority
:raw_fdnon_neg_integer(NONE):fd
:receive_buffernon_neg_integer(NONE):recbuf
:receive_tclass?booleanfalse?:recvtclass
:receive_tos?booleanfalse?:recvtos
:receive_ttl?booleanfalse?:recvttl
:reuse_addr?booleanfalse:reuseaddr
:send_buffernon_neg_integer(NONE):sndbuf
:tosnon_neg_integer(NONE):tos
:tclassnon_neg_integer(NONE):tclass

:bind_to_device

Binds a socket to a specific network interface. This option must be used in a function call that creates a socket, that is, :gen_tcp.connect/3,4, :gen_tcp.listen/2, :gen_udp.open/1,2, or :gen_sctp.open/0,1,2.

Unlike getifaddrs/0, Ifname is encoded a binary. In the unlikely case that a system is using non-7-bit-ASCII characters in network device names, special care has to be taken when encoding this argument.

This option uses the Linux-specific socket option SO_BINDTODEVICE, such as in Linux kernel 2.0.30 or later, and therefore only exists when the runtime system is compiled for such an operating system.

Before Linux 3.8, this socket option could be set, but could not retrieved with getopts/2. Since Linux 3.8, it is readable.

The virtual machine also needs elevated privileges, either running as superuser or (for Linux) having capability CAP_NET_RAW.

The primary use case for this option is to bind sockets into Linux VRF instances.

:deliver

When active: true, data is delivered on the form port : {socket_handle, {:data, [h1,..hsz | data]}} or term : {:tcp, socket_handle, [h1..hsz | data]}

:dont_route?

Enables/disables routing bypass for outgoing messages.

:keepalive?

Enables/disables periodic transmission on a connected socket when no other data is exchanged. If the other end does not respond, the connection is considered broken and an error message is sent to the controlling process. Defaults to disabled.

:linger

Determines the time-out, in seconds, for flushing unsent data in the :gen_tcp.close/1 socket call. If the first component of the value tuple is false, the second is ignored. This means that :gen_tcp.close/1 returns immediately, not waiting for data to be flushed. Otherwise, the second component is the flushing time-out, in seconds.

:local_port

Local port number to use for the outgoing socket.

:network_interface

If the host has many network interfaces, this option specifies which one to use.

:network_namespace

Sets a network namespace for the socket. Parameter s a filename defining the namespace, for example, “/var/run/netns/example”, typically created by command ip netns add example. This option must be used in a function call that creates a socket, that is, :gen_tcp.connect/3,4, :gen_tcp.listen/2, :gen_udp.open/1,2, or :gen_sctp.open/0,1,2.

This option uses the Linux-specific syscall setns(), such as in Linux kernel 3.0 or later, and therefore only exists when the runtime system is compiled for such an operating system.

The virtual machine also needs elevated privileges, either running as superuser or (for Linux) having capability CAP_SYS_ADMIN according to the documentation for setns(2). However, during testing also CAP_SYS_PTRACE and CAP_DAC_READ_SEARCH have proven to be necessary.

Example:

setcap cap_sys_admin,cap_sys_ptrace,cap_dac_read_search+epi beam.smp

Notice that the filesystem containing the virtual machine executable (beam.smp in the example) must be local, mounted without flag nosetuid, support extended attributes, and the kernel must support file capabilities. All this runs out of the box on at least Ubuntu 12.04 LTS, except that SCTP sockets appear to not support network namespaces.

Namespace is a filename and is encoded and decoded as discussed in module file, with the following exceptions:

  • Emulator flag +fnu is ignored.

  • :inet.getopts/2 for this option returns a binary for the filename if the stored filename cannot be decoded. This is only to occur if you set the option using a binary that cannot be decoded with the emulator’s filename encoding: :file.native_name_encoding/0.

:nodelay?

If true, option TCP_NODELAY is turned on for the socket, which means that also small amounts of data are sent immediately.

:packet_size

Sets the maximum allowed length of the packet body. If the packet header indicates that the length of the packet is longer than the maximum allowed length, the packet is considered invalid. The same occurs if the packet header is too large for the socket receive buffer.

For line-oriented protocols (line, http*), option packet_size also guarantees that lines up to the indicated length are accepted and not considered invalid because of internal buffer limitations.

:priority

Sets the SO_PRIORITY socket level option on platforms where this is implemented. The behavior and allowed range varies between different systems. The option is ignored on platforms where it is not implemented. Use with caution.

:raw_fd

If a socket has somehow been connected without using gen_tcp, use this option to pass the file descriptor for it. If :network_interface and/or :port options are combined with this option, the fd is bound to the specified interface and port before connecting. If these options are not specified, it is assumed that the fd is already bound appropriately.

:receive_buffer

The minimum size of the receive buffer to use for the socket. You are encouraged to use :inet.getopts/2 to retrieve the size set by your operating system.

:receive_tclass?

If set to true activates returning the received TCLASS value on platforms that implements the protocol IPPROTO_IPV6 option IPV6_RECVTCLASS or IPV6_2292RECVTCLASS for the socket. The value is returned as a {:tclass,tclass} tuple regardless of if the platform returns an IPV6_TCLASS or an IPV6_RECVTCLASS CMSG value.

For packet oriented sockets that supports receiving ancillary data with the payload data (gen_udp and gen_sctp), the TCLASS value is returned in an extended return tuple contained in an ancillary data list. For stream oriented sockets (gen_tcp) the only way to get the TCLASS value is if the platform supports the pktoptions option.

:receive_tos?

If set to true activates returning the received TOS value on platforms that implements the protocol IPPROTO_IP option IP_RECVTOS for the socket. The value is returned as a {:tos,tos} tuple regardless of if the platform returns an IP_TOS or an IP_RECVTOS CMSG value.

For packet oriented sockets that supports receiving ancillary data with the payload data (:gen_udp and :gen_sctp), the TOS value is returned in an extended return tuple contained in an ancillary data list. For stream oriented sockets (:gen_tcp) the only way to get the TOS value is if the platform supports the pktoptions option.

:receive_ttl?

If set to true activates returning the received TTL value on platforms that implements the protocol IPPROTO_IP option IP_RECVTTL for the socket. The value is returned as a {:ttl,ttl} tuple regardless of if the platform returns an IP_TTL or an IP_RECVTTL CMSG value.

For packet oriented sockets that supports receiving ancillary data with the payload data (:gen_udp and :gen_sctp), the TTL value is returned in an extended return tuple contained in an ancillary data list. For stream oriented sockets (;gen_tcp) the only way to get the TTL value is if the platform supports the pktoptions option.

:reuse_addr?

Allows or disallows local reuse of port numbers. By default, reuse is disallowed.

:send_buffer

The minimum size of the send buffer to use for the socket. You are encouraged to use getopts/2, to retrieve the size set by your operating system.

:tos

Sets IP_TOS IP level options on platforms where this is implemented. The behavior and allowed range varies between different systems. The option is ignored on platforms where it is not implemented. Use with caution.

:tclass

Sets IPV6_TCLASS IP level options on platforms where this is implemented. The behavior and allowed range varies between different systems. The option is ignored on platforms where it is not implemented. Use with caution.

Link to this section Summary

Types

Options for create/1

Valid linger value. See docs for info

The errors that create/1 may return

Packet type for inbuilt message parsing facilities

t()

TCP Connector State

Functions

Creates a Bricks.Connector which uses this module as a callback and the provided options to open and configure the socket

Link to this section Types

Link to this type create_opts() View Source
create_opts() :: %{
  :host => binary(),
  :port => pos_integer(),
  optional(:connect_timeout) => timeout(),
  optional(:receive_timeout) => timeout(),
  optional(:bam_window) => Bricks.Socket.window(),
  optional(:active) => Bricks.Socket.active(),
  optional(:bind_to_device) => binary(),
  optional(:buffer) => non_neg_integer(),
  optional(:delay_send?) => boolean(),
  optional(:deliver) => :port | :term,
  optional(:dont_route?) => boolean(),
  optional(:exit_on_close?) => boolean(),
  optional(:header_size) => non_neg_integer(),
  optional(:high_msgq_watermark) => pos_integer(),
  optional(:high_watermark) => non_neg_integer(),
  optional(:ipv4?) => boolean(),
  optional(:ipv6?) => boolean(),
  optional(:keepalive?) => boolean(),
  optional(:line_delimiter) => char(),
  optional(:linger) => {boolean(), pos_integer()},
  optional(:local_port) => Bricks.Socket.port_num(),
  optional(:low_msgq_watermark) => pos_integer(),
  optional(:low_watermark) => non_neg_integer(),
  optional(:network_interface) => binary() | :inet.socket_address(),
  optional(:network_namespace) => binary(),
  optional(:nodelay?) => boolean(),
  optional(:packet_type) => :raw | 1 | 2 | 4,
  optional(:packet_size) => pos_integer(),
  optional(:priority) => non_neg_integer(),
  optional(:raw_fd) => non_neg_integer(),
  optional(:receive_buffer) => non_neg_integer(),
  optional(:receive_tclass?) => boolean(),
  optional(:receive_tos?) => boolean(),
  optional(:receive_ttl?) => boolean(),
  optional(:reuse_addr?) => boolean(),
  optional(:send_timeout) => timeout(),
  optional(:send_timeout_close?) => boolean(),
  optional(:show_econnreset?) => boolean(),
  optional(:send_buffer) => non_neg_integer(),
  optional(:tcp_module) => atom(),
  optional(:tcp_opts) => [term()],
  optional(:tos) => non_neg_integer(),
  optional(:tclass) => non_neg_integer()
}

Options for create/1

Valid linger value. See docs for info

The errors that create/1 may return

Link to this type packet_type() View Source
packet_type() ::
  :raw
  | 0
  | 1
  | 2
  | 4
  | :asn1
  | :cdr
  | :sunrm
  | :fcgi
  | :tpkt
  | :line
  | :http
  | :http_bin
  | :httph
  | :httph_bin

Packet type for inbuilt message parsing facilities

Link to this type t() View Source
t() :: %Bricks.Connector.Tcp{
  active: Bricks.Socket.active(),
  bam_window: Bricks.Socket.window(),
  connect_timeout: timeout(),
  host: Bricks.Socket.host(),
  port: Bricks.Socket.port_num(),
  receive_timeout: timeout(),
  tcp_opts: [term()]
}

TCP Connector State

Link to this section Functions

Creates a Bricks.Connector which uses this module as a callback and the provided options to open and configure the socket.

See module documentation for more information about the options