Condor
Condor is a minimal library for building scalable TCP servers in Erlang.
Quick Overview
-module(ping_server). -behaviour(condor_listener). %% condor_listener callbacks -export([init/1]). -export([handle_packet/2]). -export([handle_info/2]). -export([terminate/2]). init([]) -> {ok, undefined}. handle_packet(<<"stop">>, State) -> {send_and_stop, <<"ok">>, normal, State}; handle_packet(<<"ping">>, State) -> {send, <<"pong">>, State}. handle_info(_Msg, State) -> {ok, State}. terminate(_Reason, _State) -> ok.
Features
- Reusable supervised connection acceptors
- Neat packet frames and buffers
API
Start a Listener
condor:start_listener(Name, Opts, Module, InitialState) ->
{ok, Pid} | {error, Reason}
Name = atom()
Opts = #{
ip => inet:ip_address(),
port => inet:port_number(),
max_acceptors => non_neg_integer(),
len => 1 | 2,
timeout => non_neg_integer()
}
Module = atom()
InitialState = any()
Pid = pid()
Reason = any()
Opts:
ip: to what IP Condor should bind.port: on what port Condor should listen.max_acceptors: maximum number of socket acceptors, or in other words, maximum number of concurrent connections.len: length of the indicator of a packet’s size.timeout: the time limit, in milliseconds, for a packet to be buffered.
Default Opts:
#{
ip => {127, 0, 0, 1},
len => 2,
timeout => 10000,
max_acceptors => 100
}
Stop a Listener
condor:stop_listener(Name) -> ok Name = atom()
Condor Listener Callbacks
Behaviour: condor_listener
init(State) -> Result
handle_packet(Packet, State) -> Result
handle_info(Msg, State) -> Result
terminate(Reason, State) -> ok
Result = {ok, State}
| {send, Packet, State}
| {stop, Reason, State}
| {send_and_stop, Packet, Reason, State}
Packet = binary()
State = any()
Reason = atom()
Events that invoke callbacks:
event callback module ----- --------------- new connection ---> Module:init/1 new packet ---> Module:handle_packet/2 receiving a message ---> Module:handle_info/2 packet timeout ---> Module:handle_info/2 connection termination ---> Module:terminate/2
Condor takes care of framing packets. Each packet frame consists of two
segments: Len | Packet.
Len indicates the length of Packet in big-endian order.
The length of Len is two bytes by default, though it can be modified with
the len option.
Condor also takes care of buffering. So, Module:handle_packet/2 is called
only when an entire packet is received. That is, when Packet is buffered
according to the value of Len. Len will then be stripped off, and only
Packet will be passed to Module:handle_packet/2. However, if Packet is
not received completely in Timeout milliseconds (which would be specified
in Opts), Module:handle_info/2 will be invoked with Msg being
{timeout, Buffer :: binary()}.
A callback’s Result:
{send, Packet, State}sendsPacket(in the frame:Len | Packet).{stop, Reason, State}terminates the connection.{send_and_stop, Packet, Reason, State}sendsPacket(in the frame:Len | Packet), and then terminates the connection.
License
Apache License, Version 2.0