%%%------------------------------------------------------------------- %%% File : sflow_gather.erl %%% Author : Jesper Louis Andersen %%% Description : Gather SFlow packets from a network socket. %%% %%% Created : 19 Dec 2007 by Jesper Louis Andersen %%%------------------------------------------------------------------- -module(sflow_gather). -behaviour(gen_event). %% API -export([start_link/0, add_handler/0]). %% gen_event callbacks -export([init/1, handle_event/2, handle_call/2, handle_info/2, terminate/2, code_change/3]). -define(SFLOW_DEFAULT_PORT, 6343). %% Default port for SFlow UDP packets -define(SERVER, ?MODULE). -record(state, {socket = none}). %%==================================================================== %% gen_event callbacks %%==================================================================== %%-------------------------------------------------------------------- %% Function: start_link() -> {ok,Pid} | {error,Error} %% Description: Creates an event manager. %%-------------------------------------------------------------------- start_link() -> gen_event:start_link({local, ?SERVER}). %%-------------------------------------------------------------------- %% Function: add_handler() -> ok | {'EXIT',Reason} | term() %% Description: Adds an event handler %%-------------------------------------------------------------------- add_handler() -> gen_event:add_handler(?SERVER, ?MODULE, []). %%==================================================================== %% gen_event callbacks %%==================================================================== %%-------------------------------------------------------------------- %% Function: init(Args) -> {ok, State} %% Description: Whenever a new event handler is added to an event manager, %% this function is called to initialize the event handler. %%-------------------------------------------------------------------- init([]) -> {ok, Socket} = gen_udp:open(?SFLOW_DEFAULT_PORT, [binary, inet, {active, true}]), {ok, #state{socket = Socket}}. %%-------------------------------------------------------------------- %% Function: %% handle_event(Event, State) -> {ok, State} | %% {swap_handler, Args1, State1, Mod2, Args2} | %% remove_handler %% Description:Whenever an event manager receives an event sent using %% gen_event:notify/2 or gen_event:sync_notify/2, this function is called for %% each installed event handler to handle the event. %%-------------------------------------------------------------------- handle_event(_Event, State) -> {ok, State}. %%-------------------------------------------------------------------- %% Function: %% handle_call(Request, State) -> {ok, Reply, State} | %% {swap_handler, Reply, Args1, State1, %% Mod2, Args2} | %% {remove_handler, Reply} %% Description: Whenever an event manager receives a request sent using %% gen_event:call/3,4, this function is called for the specified event %% handler to handle the request. %%-------------------------------------------------------------------- handle_call(_Request, State) -> Reply = ok, {ok, Reply, State}. %%-------------------------------------------------------------------- %% Function: %% handle_info(Info, State) -> {ok, State} | %% {swap_handler, Args1, State1, Mod2, Args2} | %% remove_handler %% Description: This function is called for each installed event handler when %% an event manager receives any other message than an event or a synchronous %% request (or a system message). %%-------------------------------------------------------------------- handle_info({udp, _Socket, _IP, _InPortNo, Packet}, State) -> {ok, DecodedPacket} = sflow_decoder:decode_packet(Packet), gen_event:notify(sflow_gather, {packet, DecodedPacket}), {ok, State}; handle_info(_Info, State) -> {ok, State}. %%-------------------------------------------------------------------- %% Function: terminate(Reason, State) -> void() %% Description:Whenever an event handler is deleted from an event manager, %% this function is called. It should be the opposite of Module:init/1 and %% do any necessary cleaning up. %%-------------------------------------------------------------------- terminate(_Reason, State) -> gen_udp:close(State#state.socket), ok. %%-------------------------------------------------------------------- %% Function: code_change(OldVsn, State, Extra) -> {ok, NewState} %% Description: Convert process state when code is changed %%-------------------------------------------------------------------- code_change(_OldVsn, State, _Extra) -> {ok, State}. %%-------------------------------------------------------------------- %%% Internal functions %%--------------------------------------------------------------------