Packages

A small riemann fake server.

Current section

Files

Jump to
katja_echo src katja_echo_udp.erl
Raw

src/katja_echo_udp.erl

%%%-------------------------------------------------------------------
%% @hidden
%% @doc Module responsible for receiving UDP packets.
%% @end
%%%-------------------------------------------------------------------
-module(katja_echo_udp).
-behaviour(gen_server).
%% API
-export([start_link/1,
stop/1]).
%% gen_server callbacks
-export([init/1,
handle_call/3,
handle_cast/2,
handle_info/2,
terminate/2,
code_change/3]).
-define(SERVER, ?MODULE).
-record(state, {
socket = undefined,
callback = undefined,
errors = #{} :: map()
}).
-type state() :: #state{}.
-include_lib("katja_echo_pb.hrl").
%%%===================================================================
%%% API
%%%===================================================================
%%--------------------------------------------------------------------
%% @doc
%% Starts the server
%% @end
%%--------------------------------------------------------------------
-spec start_link(Opts :: katja_echo:katja_echo_options()) -> {ok, pid()}.
start_link(Opts) ->
gen_server:start_link({local, ?SERVER}, ?MODULE, [Opts], []).
%%--------------------------------------------------------------------
%% @doc
%% Stop the server
%% @end
%%--------------------------------------------------------------------
-spec stop(Pid :: pid()) -> ok.
stop(Pid) ->
gen_server:stop(Pid).
%%%===================================================================
%%% gen_server callbacks
%%%===================================================================
%%--------------------------------------------------------------------
%% @private
%% @doc
%% Initializes the server
%% @end
%%--------------------------------------------------------------------
-spec init(Args :: list()) -> {ok, State :: state()}.
init([Opts]) ->
Port = proplists:get_value(port, Opts),
{ok, Socket} = gen_udp:open(Port, [binary, {active, true}]),
Cbk = katja_echo:callback(Opts),
{ok, #state{socket = Socket, callback = Cbk}}.
%%--------------------------------------------------------------------
%% @private
%% @doc
%% Handling call messages
%% @end
%%--------------------------------------------------------------------
-spec handle_call(_Request, _From, State :: state()) -> {reply, ok, State :: state()}.
handle_call(stop, _From, State) ->
{stop, normal, ok, State};
handle_call(_Request, _From, State) ->
Reply = ok,
{reply, Reply, State}.
%%--------------------------------------------------------------------
%% @private
%% @doc
%% Handling cast messages
%% @end
%%--------------------------------------------------------------------
-spec handle_cast(_Msg, State :: state()) -> {noreply, State :: state()}.
handle_cast(_Msg, State) ->
{noreply, State}.
%%--------------------------------------------------------------------
%% @private
%% @doc
%% Handling all non call/cast messages
%% @end
%%--------------------------------------------------------------------
-spec handle_info(_Info, State :: state()) -> {noreply, State :: state()}.
handle_info({udp, _Socket, _IP, _InPortNo, Packet},
#state{callback = Cbk, errors = Errors} = State) ->
NState =
case katja_echo:decode(udp, Packet) of
{ok, #riemannpb_msg{ok=true, events = Events}} ->
ok = katja_echo:events(Cbk, Events),
State;
{error, #riemannpb_msg{ok=false, error=Reason}} ->
Errors0 = maps:update_with(Reason, fun katja_echo:incr/1, 1, Errors),
State#state{errors = Errors0};
{error, Reason} ->
Errors0 = maps:update_with(Reason, fun katja_echo:incr/1, 1, Errors),
State#state{errors = Errors0}
end,
{noreply, NState};
handle_info(_Info, State) ->
%lager:error("Unknown udp message: ~p", [Info]),
{noreply, State}.
%%--------------------------------------------------------------------
%% @private
%% @doc
%% This function is called by a gen_server when it is about to
%% terminate. It should be the opposite of Module:init/1 and do any
%% necessary cleaning up. When it returns, the gen_server terminates
%% with Reason. The return value is ignored.
%% @end
%%--------------------------------------------------------------------
-spec terminate(_Reason, _State) -> ok.
terminate(_Reason, _State) ->
ok.
%%--------------------------------------------------------------------
%% @private
%% @doc
%% Convert process state when code is changed
%% @end
%%--------------------------------------------------------------------
-spec code_change(_OldVsn, State, _Extra) -> {ok, State}.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
%%%===================================================================
%%% Internal functions
%%%===================================================================