thrift_runtime_socket (thrift_runtime v0.7.0)

View Source

Socket plumbing shared by the client and the server connection.

Sockets are tagged — {tcp, gen_tcp:socket()} or {ssl, ssl:sslsocket()} — so every helper dispatches on the tag and the rest of the runtime carries one socket type. Plain TCP is the default; passing ssl_opts (a list of ssl:tls_server_option() on the server, ssl:tls_client_option() on the client) switches the listen/connect path to TLS.

Two framing modes, mirroring the classic Thrift transports:

  • framed — every message is prefixed with its big-endian i32 length; a max_frame_size guards against hostile sizes.
  • buffered — raw byte stream; message boundaries come from the protocol itself: extract_message/4 probes the envelope and payload struct with the protocol module's decode functions, which answer more while the input is a truncated but valid encoding; a truncated message that grows past max_frame_size is rejected, the same bound framed mode applies to the length prefix.
  • http — each Thrift message rides as the body of one HTTP/1.1 exchange; thrift_runtime_http provides the framing (requests on the server, responses on the client) with the same more semantics, and max_frame_size bounds the body. The two directions parse differently, so the endpoints call it directly instead of going through extract_message/4.

Socket reads happen in the owning processes via {active, N} delivery — this module only provides the pure frame splitter over accumulated buffers plus the send/listen/accept/connect helpers.

Summary

Functions

Accepts one connection from the listen socket.

Closes the socket.

Connects to Host:Port; with SslOpts (a list of ssl:tls_client_option()) the connection is TLS, otherwise plain TCP.

Hands the socket to Pid, which becomes its controlling process.

Splits one complete message off the front of Buffer.

Listens with the standard socket options (binary, passive, raw) plus backlog from Opts.

The remote endpoint of the socket, for the connection events.

Sends iodata over the socket.

Arms {active, N} delivery on the socket.

Types

socket()

-type socket() :: {tcp, gen_tcp:socket()} | {ssl, ssl:sslsocket()}.

transport()

-type transport() :: buffered | framed | http.

Functions

accept/3

-spec accept(socket(), AcceptTimeout :: timeout(), HandshakeTimeout :: timeout()) ->
                {ok, socket()} | {error, term()}.

Accepts one connection from the listen socket.

AcceptTimeout slices the wait so the caller (the acceptor) stays responsive between accepts; on TLS the subsequent handshake gets HandshakeTimeout of silence before failing.

close/1

-spec close(socket()) -> ok.

Closes the socket.

connect(Host, Port, SslOpts, Timeout)

-spec connect(inet:socket_address() | inet:hostname(),
              inet:port_number(),
              SslOpts :: [term()] | undefined,
              timeout()) ->
                 {ok, socket()} | {error, term()}.

Connects to Host:Port; with SslOpts (a list of ssl:tls_client_option()) the connection is TLS, otherwise plain TCP.

controlling_process/2

-spec controlling_process(socket(), pid()) -> ok | {error, term()}.

Hands the socket to Pid, which becomes its controlling process.

extract_message/4

-spec extract_message(binary(), transport(), module(), MaxFrameSize :: pos_integer()) ->
                         {ok, Message :: binary(), Leftover :: binary()} | more | {error, term()}.

Splits one complete message off the front of Buffer.

more means the buffer holds a truncated but so-far valid encoding — wait for more bytes. framed counts the length prefix against MaxFrameSize; buffered probes completeness with ProtocolMod (the envelope plus a skip-everything payload struct), so any protocol implementing thrift_runtime_protocol with streaming-friendly more semantics works.

Errors mean the bytes cannot form a valid message: the stream is unrecoverable and the owning connection must close.

listen/1

-spec listen(map()) -> {ok, socket()} | {error, term()}.

Listens with the standard socket options (binary, passive, raw) plus backlog from Opts.

With ssl_opts in Opts (a list of ssl:tls_server_option()) the listener is TLS. The listen socket stays passive; accepted connections switch themselves to {active, N} delivery after taking ownership.

peername/1

-spec peername(socket()) -> {ok, {inet:ip_address(), inet:port_number()}} | {error, term()}.

The remote endpoint of the socket, for the connection events.

send/2

-spec send(socket(), iodata()) -> ok | {error, term()}.

Sends iodata over the socket.

set_active/2

-spec set_active(socket(), pos_integer()) -> ok.

Arms {active, N} delivery on the socket.

The passive->active flow is what the connections re-arm on tcp_passive/ssl_passive after each consumed batch.