<commit_before>%% @author <NAME> <<EMAIL>>
%% @author <NAME>
%% @copyright 2008 <NAME>, <NAME>. All Rights Reserved.
%%
%% @doc
%% A gen_fsm
%%
-module(stomp_gateway).
-author('<NAME> <<EMAIL>>').
-author('<NAME>').
-behaviour(gen_fsm).

%% External exports
-export([start/1, start_link/1, stop/1, activate/1]).

%% gen_fsm callbacks
-export([init/1, handle_event/3, handle_sync_event/4, handle_info/3, terminate/3, code_change/4]).
-export([wait_for_activate/2, wait_for_command/2, wait_for_headers/2, wait_for_body/2]).

-record(frame, {command = [], headers = [], body = []}).
-define(frame, Frame#frame).
-record(state, {timeout = 5000, socket, frames_in = 0, frames_out = 0, session, frame = #frame{}, buffer = []}).
-define(state, State#state).

-include("simplemq.hrl").

%% @spec start(Socket) -> Result
%% where
%%      Socket = socket()
%%
%% @doc
%% start a stomp_gateway
%%
start(Socket) ->
    gen_fsm:start(?MODULE, Socket, []).

%% @spec start_link(Socket) -> Result
%% where
%%      Socket = socket()
%%
%% @doc
%% start a stomp_gateway
%%
start_link(Socket) ->
    gen_fsm:start_link(?MODULE, Socket, []).

%% @spec stop(Pid) -> ok
%% where
%%      Pid = pid()
%%
%% @doc
%% stop a stomp_gateway
%%
stop(Pid) ->
    gen_fsm:send_all_state_event(Pid, stop).

%% @spec activate(Pid) -> ok
%% where
%%      Pid = pid()
%%
%% @doc
%% activate the stomp_gateway
%%
activate(Pid) ->
    gen_fsm:send_event(Pid, activate).

%% @spec init(Socket) -> Result
%% where
%%      Socket = socket()
%%
%% @doc
%% gen_fsm callback
%%
init(Socket) ->
    State = #state{ socket = Socket },
    ?log([started]),
    {ok, wait_for_activate, State}.

%% @spec handle_event(Event, StateName, State) -> Result
%% where
%%      Event = term()
%%      StateName = atom()
%%      State = term()
%%
%% @doc
%% gen_fsm callback
%%
handle_event(stop, _StateName, State) ->
        {stop, normal, State};

handle_event({error, Reason, _Frame}, _StateName, State) ->
    F = #frame{
        command = "ERROR",
        headers = [{"message", Reason}]
    },
    ok = send_frame(?state.socket, F),
    {stop, Reason, State};

handle_event(#frame{ command = "CONNECT", headers = Headers } = Frame, StateName, State) ->
    Session = util:binary_to_hex(uuid:random()),
    Login = proplists:get_value("login", Headers),
    Passcode = proplists:get_value("passcode", Headers),
    case simplemq_server:auth(Login, Passcode) of
        ok ->
            F = #frame{
                command = "CONNECTED",
                headers = [{"session", Session}]
            },
            ok = send_frame(?state.socket, F),
            {next_state, StateName, State#state{ session = Session }};
        _ ->
            gen_fsm:send_all_state_event(self(), {error, auth_failed, Frame}),
            {next_state, StateName, State}
    end;

handle_event(#frame{ command = "SUBSCRIBE", headers = Headers } = Frame, StateName, State) ->
    {next_state, StateName, State};

handle_event(#frame{ command = "SEND", headers = Headers } = Frame, StateName, State) ->
    {next_state, StateName, State};

handle_event(Event, StateName, State) ->
    ?log([{state_name, StateName}, {handle_event, Event}]),
    {next_state, StateName, State}.

%% @spec handle_sync_event(Event, From, StateName, State) -> Result
%% where
%%      Event = term()
%%      From = pid()
%%      StateName = atom()
%%      State = term()
%%
%% @doc
%% gen_fsm callback
%%
handle_sync_event(Event, _From, StateName, State) ->
    ?log([{state_name, StateName}, {handle_sync_event, Event}]),
    {reply, error, StateName, State}.

%% @spec handle_info(Info, StateName, State) -> Result
%% where
%%      Info = timeout | term()
%%      StateName = atom()
%%      State = term()
%%
%% @doc
%% gen_fsm callback
%%
handle_info({tcp, _Socket, Data}, StateName, State) ->
    gen_fsm:send_event(self(), {tcp, Data}),
    {next_state, StateName, State};

handle_info({tcp_closed, _Socket}, _StateName, State) ->
    {stop, normal, State};

handle_info({tcp_error, _Socket, _Reason}, _StateName, State) ->
    {stop, normal, State};

handle_info(Info, StateName, State) ->
    ?log([{state_name, StateName}, {handle_info, Info}]),
    {next_state, StateName, State}.

%% @spec terminate(Reason, StateName, State) -> ok
%% where
%%      Reason = normal | shutdown | term()
%%      StateName = atom()
%%      State = term()
%%
%% @doc
%% gen_fsm callback
%%
terminate(_Reason, _StateName, _State) ->
    ?log(stopped),
    ok.

%% @spec code_change(OldVsn, StateName, State, Extra) -> Result
%% where
%%      OldVsn = term()
%%      StateName = atom()
%%      State = term()
%%      Extra = term()
%%<commit_msg> * add more log info<commit_after>%% @author <NAME> <akre<EMAIL>>
%% @author <NAME>
%% @copyright 2008 <NAME>, <NAME>. All Rights Reserved.
%%
%% @doc
%% A gen_fsm
%%
-module(stomp_gateway).
-author('<NAME> <<EMAIL>>').
-author('<NAME>').
-behaviour(gen_fsm).

%% External exports
-export([start/1, start_link/1, stop/1, activate/1]).

%% gen_fsm callbacks
-export([init/1, handle_event/3, handle_sync_event/4, handle_info/3, terminate/3, code_change/4]).
-export([wait_for_activate/2, wait_for_command/2, wait_for_headers/2, wait_for_body/2]).

-record(frame, {command = [], headers = [], body = []}).
-define(frame, Frame#frame).
-record(state, {timeout = 5000, socket, ip_address, port, frames_in = 0, frames_out = 0, session, frame = #frame{}, buffer = []}).
-define(state, State#state).

-include("simplemq.hrl").

%% @spec start(Socket) -> Result
%% where
%%      Socket = socket()
%%
%% @doc
%% start a stomp_gateway
%%
start(Socket) ->
    gen_fsm:start(?MODULE, Socket, []).

%% @spec start_link(Socket) -> Result
%% where
%%      Socket = socket()
%%
%% @doc
%% start a stomp_gateway
%%
start_link(Socket) ->
    gen_fsm:start_link(?MODULE, Socket, []).

%% @spec stop(Pid) -> ok
%% where
%%      Pid = pid()
%%
%% @doc
%% stop a stomp_gateway
%%
stop(Pid) ->
    gen_fsm:send_all_state_event(Pid, stop).

%% @spec activate(Pid) -> ok
%% where
%%      Pid = pid()
%%
%% @doc
%% activate the stomp_gateway
%%
activate(Pid) ->
    gen_fsm:send_event(Pid, activate).

%% @spec init(Socket) -> Result
%% where
%%      Socket = socket()
%%
%% @doc
%% gen_fsm callback
%%
init(Socket) ->
    {ok, {Address, Port}} = inet:peername(Socket),
    IP_Address = inet_parse:ntoa(Address),
    Session = util:binary_to_hex(uuid:random()),
    State = #state{
        socket = Socket,
        ip_address = IP_Address,
        port = Port,
        session = Session
    },
    ?log([
            {ip, IP_Address},
            {port, Port},
            {session, Session},
            started
        ]),
    {ok, wait_for_activate, State}.

%% @spec handle_event(Event, StateName, State) -> Result
%% where
%%      Event = term()
%%      StateName = atom()
%%      State = term()
%%
%% @doc
%% gen_fsm callback
%%
handle_event(stop, _StateName, State) ->
        {stop, normal, State};

handle_event({error, Reason, _Frame}, _StateName, State) ->
    F = #frame{
        command = "ERROR",
        headers = [{"message", Reason}]
    },
    ok = send_frame(?state.socket, F),
    {stop, Reason, State};

handle_event(#frame{ command = "CONNECT", headers = Headers } = Frame, StateName, State) ->
    Login = proplists:get_value("login", Headers),
    Passcode = proplists:get_value("passcode", Headers),
    case simplemq_server:auth(Login, Passcode) of
        ok ->
            F = #frame{
                command = "CONNECTED",
                headers = [{"session", ?state.session}]
            },
            ok = send_frame(?state.socket, F),
            {next_state, StateName, State};
        _ ->
            gen_fsm:send_all_state_event(self(), {error, auth_failed, Frame}),
            {next_state, StateName, State}
    end;

handle_event(#frame{ command = "SUBSCRIBE", headers = Headers } = Frame, StateName, State) ->
    {next_state, StateName, State};

handle_event(#frame{ command = "SEND", headers = Headers } = Frame, StateName, State) ->
    {next_state, StateName, State#state{ frames_in = ?state.frames_in + 1 }};

handle_event(Event, StateName, State) ->
    ?log([{state_name, StateName}, {handle_event, Event}]),
    {next_state, StateName, State}.

%% @spec handle_sync_event(Event, From, StateName, State) -> Result
%% where
%%      Event = term()
%%      From = pid()
%%      StateName = atom()
%%      State = term()
%%
%% @doc
%% gen_fsm callback
%%
handle_sync_event(Event, _From, StateName, State) ->
    ?log([{state_name, StateName}, {handle_sync_event, Event}]),
    {reply, error, StateName, State}.

%% @spec handle_info(Info, StateName, State) -> Result
%% where
%%      Info = timeout | term()
%%      StateName = atom()
%%      State = term()
%%
%% @doc
%% gen_fsm callback
%%
handle_info({tcp, _Socket, Data}, StateName, State) ->
    gen_fsm:send_event(self(), {tcp, Data}),
    {next_state, StateName, State};

handle_info({tcp_closed, _Socket}, _StateName, State) ->
    {stop, normal, State};

handle_info({tcp_error, _Socket, _Reason}, _StateName, State) ->
    {stop, normal, State};

handle_info(Info, StateName, State) ->
    ?log([{state_name, StateName}, {handle_info, Info}]),
    {next_state, StateName, State}.

%% @spec terminate(Reason, StateName, State) -> ok
%% where
%%      Reason = normal | shutdown | term()
%%      StateName = atom()
%%      State = term()
%%
%% @doc
%% gen_fsm callback
%%
terminate(_Reason, _StateName, State) ->
    ?log([
            {ip, ?state.ip_address},
            {port, ?state.port},
            {session, ?state.session},
            {frames_in, ?state.frames_in},
            {frames_out, ?state.frames_out},
            stopped
        ]),
    ok.

%% @spec code_change(OldVsn, StateName, State, Extra) -> Result
%% where
%%      OldVsn = term()
%%      StateName = atom()
%%      State = term()
%%      Extra = term()
%%
{'fraction_non_alphanumeric': 0.18189200162403574, 'fraction_numerical': 0.004973609419407227, 'mean_word_length': 3.310148731408574, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 81, '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': '5733539', 'n_tokens_mistral': 3416, 'n_tokens_neox': 3355, 'n_words': 765}