diff --git a/rebar b/rebar new file mode 100755 index 0000000..6535247 Binary files /dev/null and b/rebar differ diff --git a/src/erlmines.app.src b/src/erlmines.app.src new file mode 100644 index 0000000..cb85890 --- /dev/null +++ b/src/erlmines.app.src @@ -0,0 +1,12 @@ +{application, erlmines, + [ + {description, ""}, + {vsn, "1"}, + {registered, [erlmines_app, erlmines_sup, erlmines]}, + {applications, [ + kernel, + stdlib + ]}, + {mod, { erlmines_app, []}}, + {env, []} + ]}. diff --git a/src/udp_server.erl b/src/udp_server.erl new file mode 100644 index 0000000..0a32000 --- /dev/null +++ b/src/udp_server.erl @@ -0,0 +1,136 @@ +%% @author Masahito Ikuta [http://d.hatena.ne.jp/cooldaemon/] +%% @copyright Masahito Ikuta 2008 +%% @doc UDP Server Behaviour. + +%% Copyright 2008 Masahito Ikuta +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. + +-module(udp_server). +-behaviour(supervisor). + +-include("udp_server.hrl"). + +-export([behaviour_info/1]). + +-export([start_link/1, start_link/2, start_link/3]). +-export([stop/0, stop/1]). +-export([init/1]). + +-export([receiver_start_link/3]). +-export([receiver_init/3]). + +% Behaviour Callbacks +behaviour_info(callbacks) -> [{handle_call, 4}, {handle_info, 2}]; +behaviour_info(_Other) -> undefined. + +% Supervisor +%% External APIs +start_link(Module) -> + start_link(Module, #udp_server_option{}). + +start_link(RegistName, Module) when is_atom(Module) -> + start_link(RegistName, Module, #udp_server_option{}); +start_link(Module, Option) -> + start_link({local, ?MODULE}, Module, Option). + +start_link({Dest, Name}=RegistName, Module, Option) -> + supervisor:start_link( + {Dest, supervisor_name(Name)}, + ?MODULE, + [RegistName, Module, Option] + ). + +stop() -> + stop(?MODULE). + +stop(Name) -> + case whereis(supervisor_name(Name)) of + Pid when is_pid(Pid) -> + exit(Pid, normal), + ok; + _ -> not_started + end. + +supervisor_name(Name) -> + list_to_atom(atom_to_list(Name) ++ "_sup"). + +%% Callbacks +init([{_Dest, Name}=RegistName, Module, Option]) -> + #udp_server_option{ + max_restarts = MaxRestarts, + time = Time, + shutdown = Shutdown + } = Option, + {ok, {{one_for_one, MaxRestarts, Time}, [ + { + Name, + {?MODULE, receiver_start_link, [RegistName, Module, Option]}, + permanent, + Shutdown, + worker, + [] + } + ]}}. + +% ProcLib - udp_server_receiver +%% External APIs +receiver_start_link({Dest, Name}, Module, Option) -> + {ok, Pid} + = proc_lib:start_link(?MODULE, receiver_init, [self(), Module, Option]), + case Dest of + local -> register(Name, Pid); + _Global -> global:register_name(Name, Pid) + end, + {ok, Pid}. + +%% Callbacks +receiver_init(Parent, Module, Option) -> + case gen_udp:open( + Option#udp_server_option.port, + Option#udp_server_option.option + ) of + {ok, Socket} -> + proc_lib:init_ack(Parent, {ok, self()}), + recv( + proplists:get_value(active, Option#udp_server_option.option), + Socket, Module, Option + ); + {error, Reason} -> + exit({error, Reason}) + end. + +recv(false, Socket, Module, Option) -> + case gen_udp:recv( + Socket, + Option#udp_server_option.recv_length, + Option#udp_server_option.recv_timeout + ) of + {ok, {Address, Port, Packet}} -> + Module:handle_call(Socket, Address, Port, Packet), + recv(false, Socket, Module, Option); + {error, Reason} -> + exit({error, Reason}) + end; + +recv(_Active, Socket, Module, Option) -> + receive + {udp, Socket, Address, Port, Packet} -> + Module:handle_call(Socket, Address, Port, Packet), + recv(true, Socket, Module, Option); + OtherMessage -> + Module:handle_info(Socket, OtherMessage), + recv(true, Socket, Module, Option) + after Option#udp_server_option.recv_timeout -> + exit({error, udp_timeout}) + end. diff --git a/src/udp_server.hrl b/src/udp_server.hrl new file mode 100644 index 0000000..4b850aa --- /dev/null +++ b/src/udp_server.hrl @@ -0,0 +1,39 @@ +%% @author Masahito Ikuta [http://d.hatena.ne.jp/cooldaemon/] +%% @copyright Masahito Ikuta 2008 +%% @doc UDP Server Include file. + +%% Copyright 2008 Masahito Ikuta +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. + +%% @type udp_server_option() = +%% {option(), port(), max_restarts(), time(), shutdown(), +%% recv_length(), recv_timeout()}. +%% A data structure holding the options. +%% @type option() = [term()]. +%% @type port() = integer(). +%% @type max_restarts() = integer(). +%% @type time() = integer(). +%% @type shutdown() = integer(). +%% @type recv_length() = integer(). +%% @type recv_timeout() = integer() | infinity. +-record(udp_server_option, { + option = [binary], + port = 4000, + max_restarts = 3, + time = 60, + shutdown = 2000, + recv_length = 0, + recv_timeout = infinity +}). +