<commit_before>-module(capwap_ac).

-behaviour(gen_fsm).

%% API
-export([start_link/1, accept/3, get_peer_data/1, take_over/1, new_station/3]).

%% gen_fsm callbacks
-export([init/1, listen/2, idle/2, join/2, configure/2, data_check/2, run/2,
	 idle/3, join/3, configure/3, data_check/3, run/3,
	 handle_event/3,
	 handle_sync_event/4, handle_info/3, terminate/3, code_change/4]).

-export([handle_packet/3, handle_data/5]).

-include_lib("public_key/include/OTP-PUB-KEY.hrl").
-include("capwap_debug.hrl").
-include("capwap_packet.hrl").

-define(SERVER, ?MODULE).

%% TODO: convert constants into configuration values
-define(IDLE_TIMEOUT, 30 * 1000).
-define(RetransmitInterval, 3 * 1000).
-define(MaxRetransmit, 5).

-record(state, {
	  id,
	  peer,
	  peer_data,
	  flow_switch,
	  socket,
	  session,
	  mac_types,
	  tunnel_modes,
	  mac_mode,
	  tunnel_mode,
	  last_response,
	  last_request,
	  retransmit_timer,
	  retransmit_counter,
	  seqno = 0,
	  event_log
}).

-ifdef(debug).
-define(SERVER_OPTS, [{debug, [trace]}]).
-else.
-define(SERVER_OPTS, []).
-endif.

%%%===================================================================
%%% API
%%%===================================================================

%%--------------------------------------------------------------------
%% @doc
%% Creates a gen_fsm process which calls Module:init/1 to
%% initialize. To ensure a synchronized start-up procedure, this
%% function does not return until Module:init/1 has returned.
%%
%% @spec start_link() -> {ok, Pid} | ignore | {error, Error}
%% @end
%%--------------------------------------------------------------------
start_link(Peer) ->
    gen_fsm:start_link(?MODULE, [Peer], ?SERVER_OPTS).

handle_packet(_Address, _Port, Packet) ->
    try	capwap_packet:decode(control, Packet) of
	{Header, {discovery_request, 1, Seq, Elements}} ->
	    Answer = answer_discover(Seq, Elements, Header),
	    {reply, Answer};
	{Header, {join_request, 1, Seq, Elements}} ->
	    handle_plain_join(Seq, Elements, Header);
	Pkt ->
	    lager:warning("unexpected CAPWAP packet: ~p", [Pkt]),
	    {error, not_capwap}
    catch
	Class:Error ->
	    lager:error("failure: ~p:~p", [Class, Error]),
	    {error, not_capwap}
    end.

handle_data(FlowSwitch, Sw, Address, Port, Packet) ->
    lager:debug("capwap_data: ~p, ~p, ~p~n", [Address, Port, Packet]),
    try	capwap_packet:decode(data, Packet) of
	{Header, PayLoad} ->
	    KeepAlive = proplists:get_bool('keep-alive', Header#capwap_header.flags),
	    handle_capwap_data(FlowSwitch, Sw, Address, Port, Header, KeepAlive, PayLoad);
	_ ->
	    {error, not_capwap}
    catch
	_:_ ->
	    {error, not_capwap}
    end.

accept(WTP, Type, Socket) ->
    gen_fsm:send_event(WTP, {accept, Type, Socket}).

get_peer_data(WTP) ->
    gen_fsm:sync_send_all_state_event(WTP, get_peer_data).

take_over(WTP) ->
    gen_fsm:sync_send_all_state_event(WTP, {take_over, self()}).

new_station(WTP, BSS, SA) ->
    gen_fsm:sync_send_event(WTP, {new_station, BSS, SA}).

%%%===================================================================
%%% gen_fsm callbacks
%%%===================================================================

%%--------------------------------------------------------------------
%% @private
%% @doc
%% Whenever a gen_fsm is started using gen_fsm:start/[3,4] or
%% gen_fsm:start_link/[3,4], this function is called by the new
%% process to initialize.
%%
%% @spec init(Args) -> {ok, StateName, State} |
%%                     {ok, StateName, State, Timeout} |
%%                     ignore |
%%                     {stop, StopReason}
%% @end
%%--------------------------------------------------------------------
init([Peer]) ->
    %process_flag(trap_exit, true),
    capwap_wtp_reg:register(Peer),
    {ok, listen, #state{peer = Peer}, 5000}.

%%--------------------------------------------------------------------
%% @private
%% @doc
%% There should be one instance of this function for each possible
%% state name. Whenever a gen_fsm receives an event sent using
%% gen_fsm:send_event/2, the instance of this function with the same
%% name as the current state name StateName is called to handle
%% the event. It is also called if a timeout occurs.
%%
%% @spec state_name(Event, State) ->
%%                   {next_state, NextStateName, NextState} |
%%                   {next_state, NextStateName, NextState, Timeout} |
%%                   {stop, Reason, NewState}
%% @end
%%--------------------------------------------------------------------
listen({accept, udp, Socket}, State) ->
    capwap_udp:setopts(Socket, [{active, true}, {mode, binary}]),
    lager:info("udp_accept: ~p~n", [Socket]),<commit_msg>Revert "don't use process flag"<commit_after>-module(capwap_ac).

-behaviour(gen_fsm).

%% API
-export([start_link/1, accept/3, get_peer_data/1, take_over/1, new_station/3]).

%% gen_fsm callbacks
-export([init/1, listen/2, idle/2, join/2, configure/2, data_check/2, run/2,
	 idle/3, join/3, configure/3, data_check/3, run/3,
	 handle_event/3,
	 handle_sync_event/4, handle_info/3, terminate/3, code_change/4]).

-export([handle_packet/3, handle_data/5]).

-include_lib("public_key/include/OTP-PUB-KEY.hrl").
-include("capwap_debug.hrl").
-include("capwap_packet.hrl").

-define(SERVER, ?MODULE).

%% TODO: convert constants into configuration values
-define(IDLE_TIMEOUT, 30 * 1000).
-define(RetransmitInterval, 3 * 1000).
-define(MaxRetransmit, 5).

-record(state, {
	  id,
	  peer,
	  peer_data,
	  flow_switch,
	  socket,
	  session,
	  mac_types,
	  tunnel_modes,
	  mac_mode,
	  tunnel_mode,
	  last_response,
	  last_request,
	  retransmit_timer,
	  retransmit_counter,
	  seqno = 0,
	  event_log
}).

-ifdef(debug).
-define(SERVER_OPTS, [{debug, [trace]}]).
-else.
-define(SERVER_OPTS, []).
-endif.

%%%===================================================================
%%% API
%%%===================================================================

%%--------------------------------------------------------------------
%% @doc
%% Creates a gen_fsm process which calls Module:init/1 to
%% initialize. To ensure a synchronized start-up procedure, this
%% function does not return until Module:init/1 has returned.
%%
%% @spec start_link() -> {ok, Pid} | ignore | {error, Error}
%% @end
%%--------------------------------------------------------------------
start_link(Peer) ->
    gen_fsm:start_link(?MODULE, [Peer], ?SERVER_OPTS).

handle_packet(_Address, _Port, Packet) ->
    try	capwap_packet:decode(control, Packet) of
	{Header, {discovery_request, 1, Seq, Elements}} ->
	    Answer = answer_discover(Seq, Elements, Header),
	    {reply, Answer};
	{Header, {join_request, 1, Seq, Elements}} ->
	    handle_plain_join(Seq, Elements, Header);
	Pkt ->
	    lager:warning("unexpected CAPWAP packet: ~p", [Pkt]),
	    {error, not_capwap}
    catch
	Class:Error ->
	    lager:error("failure: ~p:~p", [Class, Error]),
	    {error, not_capwap}
    end.

handle_data(FlowSwitch, Sw, Address, Port, Packet) ->
    lager:debug("capwap_data: ~p, ~p, ~p~n", [Address, Port, Packet]),
    try	capwap_packet:decode(data, Packet) of
	{Header, PayLoad} ->
	    KeepAlive = proplists:get_bool('keep-alive', Header#capwap_header.flags),
	    handle_capwap_data(FlowSwitch, Sw, Address, Port, Header, KeepAlive, PayLoad);
	_ ->
	    {error, not_capwap}
    catch
	_:_ ->
	    {error, not_capwap}
    end.

accept(WTP, Type, Socket) ->
    gen_fsm:send_event(WTP, {accept, Type, Socket}).

get_peer_data(WTP) ->
    gen_fsm:sync_send_all_state_event(WTP, get_peer_data).

take_over(WTP) ->
    gen_fsm:sync_send_all_state_event(WTP, {take_over, self()}).

new_station(WTP, BSS, SA) ->
    gen_fsm:sync_send_event(WTP, {new_station, BSS, SA}).

%%%===================================================================
%%% gen_fsm callbacks
%%%===================================================================

%%--------------------------------------------------------------------
%% @private
%% @doc
%% Whenever a gen_fsm is started using gen_fsm:start/[3,4] or
%% gen_fsm:start_link/[3,4], this function is called by the new
%% process to initialize.
%%
%% @spec init(Args) -> {ok, StateName, State} |
%%                     {ok, StateName, State, Timeout} |
%%                     ignore |
%%                     {stop, StopReason}
%% @end
%%--------------------------------------------------------------------
init([Peer]) ->
    process_flag(trap_exit, true),
    capwap_wtp_reg:register(Peer),
    {ok, listen, #state{peer = Peer}, 5000}.

%%--------------------------------------------------------------------
%% @private
%% @doc
%% There should be one instance of this function for each possible
%% state name. Whenever a gen_fsm receives an event sent using
%% gen_fsm:send_event/2, the instance of this function with the same
%% name as the current state name StateName is called to handle
%% the event. It is also called if a timeout occurs.
%%
%% @spec state_name(Event, State) ->
%%                   {next_state, NextStateName, NextState} |
%%                   {next_state, NextStateName, NextState, Timeout} |
%%                   {stop, Reason, NewState}
%% @end
%%--------------------------------------------------------------------
listen({accept, udp, Socket}, State) ->
    capwap_udp:setopts(Socket, [{active, true}, {mode, binary}]),
    lager:info("udp_accept: ~p~n", [Socket]),
{'fraction_non_alphanumeric': 0.28001280546366447, 'fraction_numerical': 0.010671219720414044, 'mean_word_length': 2.744306831801838, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1154940', 'n_tokens_mistral': 3138, 'n_tokens_neox': 2964, 'n_words': 669}