From 70a6beb8b9c7752afb018ec62e7febc9d3d9b146 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Wed, 16 Feb 2011 19:49:43 +0100 Subject: [PATCH 1/2] Added some basic echo functionality --- ebin/ggs.app | 3 +- src/ggs_coordinator.erl | 14 ++- src/ggs_dispatcher.erl | 30 ++++- src/ggs_gamevm.erl | 2 +- src/ggs_player.erl | 19 ++- src/ggs_sup.erl | 9 +- src/ggs_table.erl | 22 ++-- src/helpers.erl | 4 + src/old/ggs_app.erl | 14 --- src/old/ggs_backup.erl | 41 ------- src/old/ggs_mnesia_controller_server.erl | 68 ----------- src/old/ggs_protocol.erl | 49 -------- src/old/ggs_server.erl | 141 ----------------------- src/old/ggs_server_sup.erl | 48 -------- src/old/ggs_sup.erl | 34 ------ src/old/js_runner.erl | 13 --- src/old/start_ggs.erl | 7 -- 17 files changed, 70 insertions(+), 448 deletions(-) create mode 100644 src/helpers.erl delete mode 100644 src/old/ggs_app.erl delete mode 100644 src/old/ggs_backup.erl delete mode 100644 src/old/ggs_mnesia_controller_server.erl delete mode 100644 src/old/ggs_protocol.erl delete mode 100644 src/old/ggs_server.erl delete mode 100644 src/old/ggs_server_sup.erl delete mode 100644 src/old/ggs_sup.erl delete mode 100644 src/old/js_runner.erl delete mode 100644 src/old/start_ggs.erl diff --git a/ebin/ggs.app b/ebin/ggs.app index 3315864..b3ea744 100644 --- a/ebin/ggs.app +++ b/ebin/ggs.app @@ -3,7 +3,8 @@ {vsn, "0.1.0"}, {modules, [ ggs_app, - ggs_sup + ggs_sup, + ggs_dispatcher ]}, {registered, [ggs_sup]}, {applications, [kernel, stdlib]}, diff --git a/src/ggs_coordinator.erl b/src/ggs_coordinator.erl index 4f38c6a..9acffe4 100644 --- a/src/ggs_coordinator.erl +++ b/src/ggs_coordinator.erl @@ -1,18 +1,19 @@ -module(ggs_coordinator). %% API Exports --export([start_link/1, stop/1]). +-export([start_link/0, stop/1]). %% gen_server callback exports -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). +-define(SERVER, ?MODULE). %% @doc This module act as "the man in the middle". %% Creates the starting connection between table and players. %% @doc Starts the coordinator process. start_link() -> - not_implemented. + gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). %% @doc Terminates the coordinator process. stop(_Reason) -> @@ -40,12 +41,12 @@ respawn_table(_Token) -> not_implemented. %% @doc Removes a player from coordinator. -remove_player(From, Player) -> +remove_player(_From, _Player) -> not_implemented. %% gen_server callbacks -init([Port]) -> +init([]) -> {ok, ok}. handle_call(_Message, _From, State) -> @@ -54,8 +55,11 @@ handle_call(_Message, _From, State) -> handle_cast(_Message, State) -> {noreply, State}. +handle_info(_Message, State) -> + {noreply, State}. + terminate(normal, _State) -> ok. -code_change(_OldVsn, State, Extra) -> +code_change(_OldVsn, State, _Extra) -> {ok, State}. diff --git a/src/ggs_dispatcher.erl b/src/ggs_dispatcher.erl index bc3327a..4b47ba3 100644 --- a/src/ggs_dispatcher.erl +++ b/src/ggs_dispatcher.erl @@ -1,5 +1,7 @@ -module(ggs_dispatcher). +-behaviour(gen_server). + %% API Exports -export([start_link/1, stop/1]). @@ -7,6 +9,8 @@ -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). +-define(SERVER, ?MODULE). + %% @doc This module is the entry-point for clients connecting to GGS. This is %% the module responsible for: @@ -20,19 +24,21 @@ %% Port = Integer %% Pid = # start_link(Port) -> - not_implemented. + gen_server:start_link({local, ?SERVER}, ?MODULE, [Port], []). %% @doc Stops the dispatcher with the specified reason. %% @spec stop(Reason) -> ok. %% Reason = String -stop(Reason) -> not_implemented. +stop(_Reason) -> not_implemented. %% gen_server callbacks %% @doc Initiate the dispatcher. This is called from gen_server init([Port]) -> - {ok, ok}. + {ok, LSock} = gen_tcp:listen(Port, [{active, true}, + {reuseaddr, true}]), + {ok, LSock, 0}. handle_call(_Message, _From, State) -> {noreply, State}. @@ -40,8 +46,24 @@ handle_call(_Message, _From, State) -> handle_cast(_Message, State) -> {noreply, State}. +handle_info({tcp, _Socket, RawData}, State) -> + io:format("Got connect request!~n"), + {noreply, State}; + +handle_info({tcp_closed, Socket}, State) -> + gen_tcp:close(Socket), + {stop, "Client closed socket", State}; + +%% @doc This is our function for accepting connections. When a client connects, +%% it will immediately time out due to timing settings set in init and here, +%% and when it does, we accept the connection. +handle_info(timeout, LSock) -> + {ok, Sock} = gen_tcp:accept(LSock), + spawn(ggs_player, start_link, [Sock]), + {noreply, LSock, 0}. + terminate(normal, _State) -> ok. -code_change(_OldVsn, State, Extra) -> +code_change(_OldVsn, State, _Extra) -> {ok, State}. diff --git a/src/ggs_gamevm.erl b/src/ggs_gamevm.erl index 8116a96..1a8f547 100644 --- a/src/ggs_gamevm.erl +++ b/src/ggs_gamevm.erl @@ -1,4 +1,4 @@ --module(ggs_vm_runner). +-module(ggs_gamevm). -export([start_link/0, define/2, user_command/4]). %% @doc This module is responsible for running the game VM:s. You can issue %% commands to a vm using this module. diff --git a/src/ggs_player.erl b/src/ggs_player.erl index b5815af..87c003c 100644 --- a/src/ggs_player.erl +++ b/src/ggs_player.erl @@ -12,21 +12,32 @@ %% an argument for storage and later usage. Creates a unique player token %% identifying the player. %% @spec start_link(Socket::socket()) -> ok -start_link(Socket) -> not_implemented. +start_link(Socket) -> + loop(Socket). %% @doc Handles incoming messages from the GGS and forwards them through the player %% socket to the player. %% @spec notify(Player::Pid(), From::Pid(), %% {Command::String(), Message::string()}) -> ok -notify(Player, From, Message) -> not_implemented. +notify(_Player, _From, _Message) -> not_implemented. %% @doc Get the player token uniquely representing the player. %% @spec get_token() -> string() -get_token() -> not_implemented. +get_token(_Player) -> not_implemented. %% @doc Properly terminates the player process. The player token will be destroyed. %% Makes table token unreferenced and destroys the process in the end. %% @spec stop(Table::pid()) -> Reason::string() -stop(Table) -> not_implemented. +stop(_Table) -> not_implemented. + + +%% Internals + +loop(Socket) -> + receive {tcp, Socket, Data} -> % Just echo for now.. + gen_tcp:send(Socket,Data), + loop(Socket) + end. + diff --git a/src/ggs_sup.erl b/src/ggs_sup.erl index bfb2617..05fab65 100644 --- a/src/ggs_sup.erl +++ b/src/ggs_sup.erl @@ -2,17 +2,12 @@ -behaviour(supervisor). %% API --export([start/1, start_link/1]). +-export([start_link/1]). %% Supervisor callbacks -export([init/1]). -define(SERVER, ?MODULE). -start(Port) -> - [FirstArg] = Port, - {IntPort, _} = string:to_integer(FirstArg), - start_link(IntPort). - start_link(Port) -> supervisor:start_link({local, ?SERVER}, ?MODULE, [Port]). @@ -29,7 +24,7 @@ init([Port]) -> permanent, 2000, worker, - [ggs_dispatcher] + [ggs_coordinator] }, Children = [Dispatcher, Coordinator], diff --git a/src/ggs_table.erl b/src/ggs_table.erl index 87a623a..e00b840 100644 --- a/src/ggs_table.erl +++ b/src/ggs_table.erl @@ -10,27 +10,27 @@ ]). % @doc returns a new table -start_link(Token) -> - not_implemented(). +start_link(_Token) -> + helpers:not_implemented(). % @doc adds a player to a table -add_player(Table, Player) -> - not_implemented(). +add_player(_Table, _Player) -> + helpers:not_implemented(). % @doc removes player form a table -remove_player(Table, Player) -> - not_implemented(). +remove_player(_Table, _Player) -> + helpers:not_implemented(). % @doc stops the table process -stop(Table) -> - not_implemented(). +stop(_Table, _Msg) -> + helpers:not_implemented(). % @doc notifies the table with a message from a player -notify(Table, Player, Message) -> - not_implemented(). +notify(_Table, _Player, _Message) -> + helpers:not_implemented(). % loop -% private helpers \ No newline at end of file +% private helpers diff --git a/src/helpers.erl b/src/helpers.erl new file mode 100644 index 0000000..1bf7825 --- /dev/null +++ b/src/helpers.erl @@ -0,0 +1,4 @@ +-module(helpers). + +not_implemented() -> + exit("Not implemented"). diff --git a/src/old/ggs_app.erl b/src/old/ggs_app.erl deleted file mode 100644 index d8b2e60..0000000 --- a/src/old/ggs_app.erl +++ /dev/null @@ -1,14 +0,0 @@ --module(ggs_app). --behaviour(application). --export([start/2, stop/1]). - -start(_StartType, _StartArgs) -> - case ggs_sup:start_link(9000) of - {ok, Pid} -> - {ok, Pid}; - Other -> - {error, Other} - end. - -stop(_State) -> - ok. diff --git a/src/old/ggs_backup.erl b/src/old/ggs_backup.erl deleted file mode 100644 index 30c80a2..0000000 --- a/src/old/ggs_backup.erl +++ /dev/null @@ -1,41 +0,0 @@ --module(ggs_backup). --behaviour(gen_server). - -%% API --export([start_link/0 ]). - -%% 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, {port, lsock, client_vm_map = []}). - -start_link() -> - gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). - -init([]) -> - {ok, #state{port = -1, lsock = -1, client_vm_map = -1}, 0}. - -handle_call(get_backup, _From, State) -> - BackedUpState = case State of - #state{port = -1, lsock = -1, client_vm_map = -1} -> - not_initialized; - Other -> - Other - end, - {reply, {backup_state, BackedUpState}, State}. - -handle_cast({set_backup, NewState}, _State) -> - {noreply, NewState}. - -handle_info(_Msg, State) -> - {noreply, State}. - -code_change(_OldVsn, State, _Extra) -> - {ok, State}. - -terminate(_Reason, _State) -> - ok. diff --git a/src/old/ggs_mnesia_controller_server.erl b/src/old/ggs_mnesia_controller_server.erl deleted file mode 100644 index c1f8a10..0000000 --- a/src/old/ggs_mnesia_controller_server.erl +++ /dev/null @@ -1,68 +0,0 @@ --module(ggs_mnesia_controller_server). --behaviour(gen_server). - -%% API --export([start_link/0, - stop/0 - ]). - -%% 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, {}). - -%%%==================================================== -%%% API -%%%==================================================== - -%%----------------------------------------------------- -%% @doc Starts the server -%% @end -%%----------------------------------------------------- -start_link() -> - gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). - -%%----------------------------------------------------- -%% @doc Stops the server. -%% @spec stop() -> ok -%% @end -%%----------------------------------------------------- -stop() -> - gen_server:cast(?SERVER, stop). - -%%----------------------------------------------------- -%% gen_server callbacks -%%----------------------------------------------------- - -init([]) -> - mnesia:create_schema([node()]), - mnesia:start(), - {ok, {}, 0}. - -handle_cast(a, State) -> - {noreply, State}. - -% Request a value from the Mnesia database -handle_call({getValue, _Key},_From,State) -> - {reply,value_of_key_requested_goes_here, State}; - -% Set a value in the Mnesia database -handle_call({setValue, _Key, Value},_From,State) -> - {reply,value_set_or_updated, State}. - -handle_info(timeout, State) -> - {noreply, State}. - -terminate(_Reason, _State) -> - ok. - -code_change(_OldVsn, State, _Extra) -> - {ok, State}. - -%%----------------------------------------------------- -%% Internal functions -%%----------------------------------------------------- diff --git a/src/old/ggs_protocol.erl b/src/old/ggs_protocol.erl deleted file mode 100644 index 46c1ba1..0000000 --- a/src/old/ggs_protocol.erl +++ /dev/null @@ -1,49 +0,0 @@ --module(ggs_protocol). --export([parse/1]). - -parse(Data) -> - Parsed = do_parse(Data, []), - prettify(Parsed). - -do_parse(Data, ParsedMessage) -> - NewLinePos = string:chr(Data, $\n), - Line = string:substr(Data, 1, NewLinePos-1), - Tokens = re:split(Line, ": ", [{return, list}]), - case handle(Tokens) of - {Command, more} -> - do_parse(string:substr(Data, NewLinePos+1), ParsedMessage ++ [Command]); - {separator, data_next} -> - {_, Value} = lists:keyfind(content_len, 1, ParsedMessage), - {ContentLength, []} = string:to_integer(Value), - {ParsedMessage, handle_data(string:substr(Data, NewLinePos+1), ContentLength)} - end. - -handle([[]]) -> - {separator, data_next}; -handle(["Server-Command", Param]) -> - {{srv_cmd, Param}, more}; -handle(["Content-Length", Param]) -> - {{content_len, Param}, more}; -handle(["Token", Param]) -> - {{token, Param}, more}; -handle(["Content-Type", Param]) -> - {{content_type, Param}, more}. - -handle_data(Data, Length) -> - {data, string:substr(Data,1,Length)}. - - -%% Helpers -prettify({Args, Data}) -> - case lists:keyfind(srv_cmd, 1, Args) of - {_, Value} -> - gen_server:cast(ggs_server, {srv_cmd, Value, Args, Data}); - _Other -> - case lists:keyfind(game_cmd, 1, Args) of - {_, Value} -> - gen_server:cast(ggs_server, {game_cmd, Value, Args, Data}); - _ -> - ok - end - end. - diff --git a/src/old/ggs_server.erl b/src/old/ggs_server.erl deleted file mode 100644 index 34d297f..0000000 --- a/src/old/ggs_server.erl +++ /dev/null @@ -1,141 +0,0 @@ -%%%---------------------------------------------------- -%%% @author Jonatan Pålsson -%%% @copyright 2010 Jonatan Pålsson -%%% @doc RPC over TCP server -%%% @end -%%%---------------------------------------------------- - --module(ggs_server). --behaviour(gen_server). - -%% API --export([start_link/1, - start_link/0, - stop/0 - ]). - -%% gen_server callbacks --export([init/1, handle_call/3, handle_cast/2, - handle_info/2, terminate/2, code_change/3]). - - --define(SERVER, ?MODULE). --define(DEFAULT_PORT, 1055). - --record(state, {port, lsock, client_vm_map = []}). - -%%%==================================================== -%%% API -%%%==================================================== - -%%----------------------------------------------------- -%% @doc Starts the server -%% @end -%%----------------------------------------------------- -start_link(Port) -> - gen_server:start_link({local, ?SERVER}, ?MODULE, [Port], []). - -start_link() -> - start_link(?DEFAULT_PORT). - -%%----------------------------------------------------- -%% @doc Stops the server. -%% @spec stop() -> ok -%% @end -%%----------------------------------------------------- -stop() -> - gen_server:cast(?SERVER, stop). - -%%----------------------------------------------------- -%% gen_server callbacks -%%----------------------------------------------------- - -init([Port]) -> - case gen_server:call(ggs_backup, get_backup) of - {backup_state, not_initialized} -> - {ok, LSock} = gen_tcp:listen(Port, [{active, true}, - {reuseaddr, true}]), - {ok, #state{port = Port, lsock = LSock}, 0}; - {backup_state, State} -> - {ok, LSock} = gen_tcp:listen(Port, [{active, true}, - {reuseaddr, true}]), - {ok, State#state{lsock = LSock}, 0} - end. - -handle_call({backup_state, OldState}, _From, State) -> - io:format("Received old state from backup~n"), - {noreply, OldState}. - - -handle_info({tcp, Socket, RawData}, State) -> - ggs_protocol:parse(RawData), - {noreply, State#state{lsock = Socket}}; - -handle_info({tcp_closed, Socket}, State) -> - gen_tcp:close(Socket), - {stop, "Client closed socket", State}; - -handle_info(timeout, #state{lsock = LSock} = State) -> - {ok, _Sock} = gen_tcp:accept(LSock), - {noreply, State}; - -handle_info(Other, State) -> - erlang:display(Other). - -terminate(_Reason, _State) -> - ok. - -code_change(_OldVsn, State, _Extra) -> - {ok, State}. - -%%----------------------------------------------------- -%% Internal functions -%%----------------------------------------------------- -handle_cast(stop, State) -> - {stop, normal, State}; - -% Handle javascript defines -handle_cast({define, Token, SourceCode}, State) -> - GameVM = getJSVM(Token, State), - ggs_vm_runner:define(GameVM, SourceCode), - send(State#state.lsock, Token, "Okay, defined that for you!"), - {noreply, State}; - -% Handle javascript calls -handle_cast({call, Token, Command}, State) -> - GameVM = getJSVM(Token, State), - ggs_vm_runner:user_command(GameVM, "User", Command, []), - %send(State#state.lsock, Token, "JS says:", binary_to_list(Ret)), Unessecary - {noreply, State}; - -% Set the new state to the reference generated, and JSVM associated -handle_cast({hello, _, _}, State) -> - GameVM = ggs_vm_runner:start_link(), - Client = getRef(), - send(State#state.lsock, Client, "This is your refID"), - OldMap = State#state.client_vm_map, - NewState = State#state{client_vm_map = OldMap ++ [{Client, GameVM}]}, - gen_server:cast(ggs_backup, {set_backup, NewState}), - {noreply, NewState}. - -%%----------------------------------------------------- -%% Helpers -%%----------------------------------------------------- -getRef() -> - %{A1,A2,A3} = now(), - %#random:seed(A1, A2, A3), - %random:uniform(1000). - string:strip(os:cmd("uuidgen"), right, $\n ). - -getJSVM(RefID, State) -> - VMs = State#state.client_vm_map, - erlang:display(RefID), - erlang:display(VMs), - {value, {_,VM}} = lists:keysearch(RefID, 1, VMs), - VM. - -send(Socket, RefID, String) -> - gen_tcp:send(Socket, string:join([RefID,String,"\n"], " ")). - -send(Socket, RefID, String1, String2) -> - gen_tcp:send(Socket, string:join([RefID,String1, String2,"\n"], " ")). diff --git a/src/old/ggs_server_sup.erl b/src/old/ggs_server_sup.erl deleted file mode 100644 index 23d32f7..0000000 --- a/src/old/ggs_server_sup.erl +++ /dev/null @@ -1,48 +0,0 @@ --module(ggs_server_sup). --behaviour(supervisor). - -%% API --export([start/1, start_link/1]). - -%% Supervisor callbacks --export([init/1]). --define(SERVER, ?MODULE). - -start(Port) -> - [FirstArg] = Port, - {IntPort, _} = string:to_integer(FirstArg), - start_link(IntPort). - -start_link(Port) -> - supervisor:start_link({local, ?SERVER}, ?MODULE, [Port]). - -init([Port]) -> - GGSServer = {ggs_server, - {ggs_server, start_link, [Port]}, - permanent, - 2000, - worker, - [ggs_server] - }, - Backup = {ggs_backup, - {ggs_backup, start_link, []}, - permanent, - 2000, - worker, - [ggs_backup] - }, - MnesiaServer = {ggs_mnesia_controller_server, - {ggs_mnesia_controller_server, start_link, []}, - permanent, - 2000, - worker, - [ggs_mnesia_controller_server] - }, - Children = [MnesiaServer, Backup, GGSServer], - - RestartStrategy = { one_for_one, % Restart only crashing child - 10, % Allow ten crashes per.. - 1 % 1 second, then crash supervisor. - }, - {ok, {RestartStrategy, Children}}. - diff --git a/src/old/ggs_sup.erl b/src/old/ggs_sup.erl deleted file mode 100644 index ee6f8cd..0000000 --- a/src/old/ggs_sup.erl +++ /dev/null @@ -1,34 +0,0 @@ --module(ggs_sup). --behaviour(supervisor). - -%% API --export([start/1, start_link/1]). - -%% Supervisor callbacks --export([init/1]). --define(SERVER, ?MODULE). - -start(Port) -> - [FirstArg] = Port, - {IntPort, _} = string:to_integer(FirstArg), - start_link(IntPort). - -start_link(Port) -> - supervisor:start_link({local, ?SERVER}, ?MODULE, [Port]). - -init([Port]) -> - Server = {ggs_server_sup, - {ggs_server_sup, start_link, [Port]}, - permanent, - 2000, - worker, - [ggs_server_sup] - }, - Children = [Server], - - RestartStrategy = { one_for_one, % Restart only crashing child - 10, % Allow ten crashes per.. - 1 % 1 second, then crash supervisor. - }, - {ok, {RestartStrategy, Children}}. - diff --git a/src/old/js_runner.erl b/src/old/js_runner.erl deleted file mode 100644 index ca866c4..0000000 --- a/src/old/js_runner.erl +++ /dev/null @@ -1,13 +0,0 @@ --module(js_runner). --export([define/2,call/3, boot/0]). - -boot() -> - erlang_js:start(), - {ok, Port} = js_driver:new(), - Port. - -define(Port, Data) -> - ok = js:define(Port, list_to_binary(Data)). - -call(Port, Func, Params) -> - js:call(Port, list_to_binary(Func), Params). diff --git a/src/old/start_ggs.erl b/src/old/start_ggs.erl deleted file mode 100644 index 3955715..0000000 --- a/src/old/start_ggs.erl +++ /dev/null @@ -1,7 +0,0 @@ --module(start_ggs). --export([start/0]). - -start() -> - application:start(inets), - application:start(erlang_js), - application:start(ggs). From ec78283a4640ab4e126cb65c0ea39f1005bc86ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Wed, 16 Feb 2011 19:49:43 +0100 Subject: [PATCH 2/2] Added some basic echo functionality --- ebin/ggs.app | 3 +- src/ggs_coordinator.erl | 14 ++- src/ggs_dispatcher.erl | 30 ++++- src/ggs_gamevm.erl | 2 +- src/ggs_player.erl | 24 +++- src/ggs_sup.erl | 9 +- src/ggs_table.erl | 22 ++-- src/helpers.erl | 4 + src/old/ggs_app.erl | 14 --- src/old/ggs_backup.erl | 41 ------- src/old/ggs_mnesia_controller_server.erl | 68 ----------- src/old/ggs_protocol.erl | 49 -------- src/old/ggs_server.erl | 141 ----------------------- src/old/ggs_server_sup.erl | 48 -------- src/old/ggs_sup.erl | 34 ------ src/old/js_runner.erl | 13 --- src/old/start_ggs.erl | 7 -- 17 files changed, 75 insertions(+), 448 deletions(-) create mode 100644 src/helpers.erl delete mode 100644 src/old/ggs_app.erl delete mode 100644 src/old/ggs_backup.erl delete mode 100644 src/old/ggs_mnesia_controller_server.erl delete mode 100644 src/old/ggs_protocol.erl delete mode 100644 src/old/ggs_server.erl delete mode 100644 src/old/ggs_server_sup.erl delete mode 100644 src/old/ggs_sup.erl delete mode 100644 src/old/js_runner.erl delete mode 100644 src/old/start_ggs.erl diff --git a/ebin/ggs.app b/ebin/ggs.app index 3315864..b3ea744 100644 --- a/ebin/ggs.app +++ b/ebin/ggs.app @@ -3,7 +3,8 @@ {vsn, "0.1.0"}, {modules, [ ggs_app, - ggs_sup + ggs_sup, + ggs_dispatcher ]}, {registered, [ggs_sup]}, {applications, [kernel, stdlib]}, diff --git a/src/ggs_coordinator.erl b/src/ggs_coordinator.erl index 4f38c6a..9acffe4 100644 --- a/src/ggs_coordinator.erl +++ b/src/ggs_coordinator.erl @@ -1,18 +1,19 @@ -module(ggs_coordinator). %% API Exports --export([start_link/1, stop/1]). +-export([start_link/0, stop/1]). %% gen_server callback exports -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). +-define(SERVER, ?MODULE). %% @doc This module act as "the man in the middle". %% Creates the starting connection between table and players. %% @doc Starts the coordinator process. start_link() -> - not_implemented. + gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). %% @doc Terminates the coordinator process. stop(_Reason) -> @@ -40,12 +41,12 @@ respawn_table(_Token) -> not_implemented. %% @doc Removes a player from coordinator. -remove_player(From, Player) -> +remove_player(_From, _Player) -> not_implemented. %% gen_server callbacks -init([Port]) -> +init([]) -> {ok, ok}. handle_call(_Message, _From, State) -> @@ -54,8 +55,11 @@ handle_call(_Message, _From, State) -> handle_cast(_Message, State) -> {noreply, State}. +handle_info(_Message, State) -> + {noreply, State}. + terminate(normal, _State) -> ok. -code_change(_OldVsn, State, Extra) -> +code_change(_OldVsn, State, _Extra) -> {ok, State}. diff --git a/src/ggs_dispatcher.erl b/src/ggs_dispatcher.erl index bc3327a..4b47ba3 100644 --- a/src/ggs_dispatcher.erl +++ b/src/ggs_dispatcher.erl @@ -1,5 +1,7 @@ -module(ggs_dispatcher). +-behaviour(gen_server). + %% API Exports -export([start_link/1, stop/1]). @@ -7,6 +9,8 @@ -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). +-define(SERVER, ?MODULE). + %% @doc This module is the entry-point for clients connecting to GGS. This is %% the module responsible for: @@ -20,19 +24,21 @@ %% Port = Integer %% Pid = # start_link(Port) -> - not_implemented. + gen_server:start_link({local, ?SERVER}, ?MODULE, [Port], []). %% @doc Stops the dispatcher with the specified reason. %% @spec stop(Reason) -> ok. %% Reason = String -stop(Reason) -> not_implemented. +stop(_Reason) -> not_implemented. %% gen_server callbacks %% @doc Initiate the dispatcher. This is called from gen_server init([Port]) -> - {ok, ok}. + {ok, LSock} = gen_tcp:listen(Port, [{active, true}, + {reuseaddr, true}]), + {ok, LSock, 0}. handle_call(_Message, _From, State) -> {noreply, State}. @@ -40,8 +46,24 @@ handle_call(_Message, _From, State) -> handle_cast(_Message, State) -> {noreply, State}. +handle_info({tcp, _Socket, RawData}, State) -> + io:format("Got connect request!~n"), + {noreply, State}; + +handle_info({tcp_closed, Socket}, State) -> + gen_tcp:close(Socket), + {stop, "Client closed socket", State}; + +%% @doc This is our function for accepting connections. When a client connects, +%% it will immediately time out due to timing settings set in init and here, +%% and when it does, we accept the connection. +handle_info(timeout, LSock) -> + {ok, Sock} = gen_tcp:accept(LSock), + spawn(ggs_player, start_link, [Sock]), + {noreply, LSock, 0}. + terminate(normal, _State) -> ok. -code_change(_OldVsn, State, Extra) -> +code_change(_OldVsn, State, _Extra) -> {ok, State}. diff --git a/src/ggs_gamevm.erl b/src/ggs_gamevm.erl index 8116a96..1a8f547 100644 --- a/src/ggs_gamevm.erl +++ b/src/ggs_gamevm.erl @@ -1,4 +1,4 @@ --module(ggs_vm_runner). +-module(ggs_gamevm). -export([start_link/0, define/2, user_command/4]). %% @doc This module is responsible for running the game VM:s. You can issue %% commands to a vm using this module. diff --git a/src/ggs_player.erl b/src/ggs_player.erl index b5815af..a459499 100644 --- a/src/ggs_player.erl +++ b/src/ggs_player.erl @@ -12,21 +12,37 @@ %% an argument for storage and later usage. Creates a unique player token %% identifying the player. %% @spec start_link(Socket::socket()) -> ok -start_link(Socket) -> not_implemented. +start_link(Socket) -> + loop(Socket). %% @doc Handles incoming messages from the GGS and forwards them through the player %% socket to the player. %% @spec notify(Player::Pid(), From::Pid(), %% {Command::String(), Message::string()}) -> ok -notify(Player, From, Message) -> not_implemented. +notify(_Player, _From, _Message) -> not_implemented. %% @doc Get the player token uniquely representing the player. %% @spec get_token() -> string() -get_token() -> not_implemented. +get_token(_Player) -> not_implemented. %% @doc Properly terminates the player process. The player token will be destroyed. %% Makes table token unreferenced and destroys the process in the end. %% @spec stop(Table::pid()) -> Reason::string() -stop(Table) -> not_implemented. +stop(_Table) -> not_implemented. + + +%% Internals + +loop(Socket) -> + % The socket is in 'active' mode, and that means we are pushed any data + % that arrives on it, we do not need to recv() manually. Since the socket + % was opened in our parent process, we need to change the owner of it to + % us, otherwise these messages end up in our parent. + erlang:port_connect(Socket, self()), + receive {tcp, Socket, Data} -> % Just echo for now.. + gen_tcp:send(Socket,Data), + loop(Socket) + end. + diff --git a/src/ggs_sup.erl b/src/ggs_sup.erl index bfb2617..05fab65 100644 --- a/src/ggs_sup.erl +++ b/src/ggs_sup.erl @@ -2,17 +2,12 @@ -behaviour(supervisor). %% API --export([start/1, start_link/1]). +-export([start_link/1]). %% Supervisor callbacks -export([init/1]). -define(SERVER, ?MODULE). -start(Port) -> - [FirstArg] = Port, - {IntPort, _} = string:to_integer(FirstArg), - start_link(IntPort). - start_link(Port) -> supervisor:start_link({local, ?SERVER}, ?MODULE, [Port]). @@ -29,7 +24,7 @@ init([Port]) -> permanent, 2000, worker, - [ggs_dispatcher] + [ggs_coordinator] }, Children = [Dispatcher, Coordinator], diff --git a/src/ggs_table.erl b/src/ggs_table.erl index 87a623a..e00b840 100644 --- a/src/ggs_table.erl +++ b/src/ggs_table.erl @@ -10,27 +10,27 @@ ]). % @doc returns a new table -start_link(Token) -> - not_implemented(). +start_link(_Token) -> + helpers:not_implemented(). % @doc adds a player to a table -add_player(Table, Player) -> - not_implemented(). +add_player(_Table, _Player) -> + helpers:not_implemented(). % @doc removes player form a table -remove_player(Table, Player) -> - not_implemented(). +remove_player(_Table, _Player) -> + helpers:not_implemented(). % @doc stops the table process -stop(Table) -> - not_implemented(). +stop(_Table, _Msg) -> + helpers:not_implemented(). % @doc notifies the table with a message from a player -notify(Table, Player, Message) -> - not_implemented(). +notify(_Table, _Player, _Message) -> + helpers:not_implemented(). % loop -% private helpers \ No newline at end of file +% private helpers diff --git a/src/helpers.erl b/src/helpers.erl new file mode 100644 index 0000000..1bf7825 --- /dev/null +++ b/src/helpers.erl @@ -0,0 +1,4 @@ +-module(helpers). + +not_implemented() -> + exit("Not implemented"). diff --git a/src/old/ggs_app.erl b/src/old/ggs_app.erl deleted file mode 100644 index d8b2e60..0000000 --- a/src/old/ggs_app.erl +++ /dev/null @@ -1,14 +0,0 @@ --module(ggs_app). --behaviour(application). --export([start/2, stop/1]). - -start(_StartType, _StartArgs) -> - case ggs_sup:start_link(9000) of - {ok, Pid} -> - {ok, Pid}; - Other -> - {error, Other} - end. - -stop(_State) -> - ok. diff --git a/src/old/ggs_backup.erl b/src/old/ggs_backup.erl deleted file mode 100644 index 30c80a2..0000000 --- a/src/old/ggs_backup.erl +++ /dev/null @@ -1,41 +0,0 @@ --module(ggs_backup). --behaviour(gen_server). - -%% API --export([start_link/0 ]). - -%% 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, {port, lsock, client_vm_map = []}). - -start_link() -> - gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). - -init([]) -> - {ok, #state{port = -1, lsock = -1, client_vm_map = -1}, 0}. - -handle_call(get_backup, _From, State) -> - BackedUpState = case State of - #state{port = -1, lsock = -1, client_vm_map = -1} -> - not_initialized; - Other -> - Other - end, - {reply, {backup_state, BackedUpState}, State}. - -handle_cast({set_backup, NewState}, _State) -> - {noreply, NewState}. - -handle_info(_Msg, State) -> - {noreply, State}. - -code_change(_OldVsn, State, _Extra) -> - {ok, State}. - -terminate(_Reason, _State) -> - ok. diff --git a/src/old/ggs_mnesia_controller_server.erl b/src/old/ggs_mnesia_controller_server.erl deleted file mode 100644 index c1f8a10..0000000 --- a/src/old/ggs_mnesia_controller_server.erl +++ /dev/null @@ -1,68 +0,0 @@ --module(ggs_mnesia_controller_server). --behaviour(gen_server). - -%% API --export([start_link/0, - stop/0 - ]). - -%% 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, {}). - -%%%==================================================== -%%% API -%%%==================================================== - -%%----------------------------------------------------- -%% @doc Starts the server -%% @end -%%----------------------------------------------------- -start_link() -> - gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). - -%%----------------------------------------------------- -%% @doc Stops the server. -%% @spec stop() -> ok -%% @end -%%----------------------------------------------------- -stop() -> - gen_server:cast(?SERVER, stop). - -%%----------------------------------------------------- -%% gen_server callbacks -%%----------------------------------------------------- - -init([]) -> - mnesia:create_schema([node()]), - mnesia:start(), - {ok, {}, 0}. - -handle_cast(a, State) -> - {noreply, State}. - -% Request a value from the Mnesia database -handle_call({getValue, _Key},_From,State) -> - {reply,value_of_key_requested_goes_here, State}; - -% Set a value in the Mnesia database -handle_call({setValue, _Key, Value},_From,State) -> - {reply,value_set_or_updated, State}. - -handle_info(timeout, State) -> - {noreply, State}. - -terminate(_Reason, _State) -> - ok. - -code_change(_OldVsn, State, _Extra) -> - {ok, State}. - -%%----------------------------------------------------- -%% Internal functions -%%----------------------------------------------------- diff --git a/src/old/ggs_protocol.erl b/src/old/ggs_protocol.erl deleted file mode 100644 index 46c1ba1..0000000 --- a/src/old/ggs_protocol.erl +++ /dev/null @@ -1,49 +0,0 @@ --module(ggs_protocol). --export([parse/1]). - -parse(Data) -> - Parsed = do_parse(Data, []), - prettify(Parsed). - -do_parse(Data, ParsedMessage) -> - NewLinePos = string:chr(Data, $\n), - Line = string:substr(Data, 1, NewLinePos-1), - Tokens = re:split(Line, ": ", [{return, list}]), - case handle(Tokens) of - {Command, more} -> - do_parse(string:substr(Data, NewLinePos+1), ParsedMessage ++ [Command]); - {separator, data_next} -> - {_, Value} = lists:keyfind(content_len, 1, ParsedMessage), - {ContentLength, []} = string:to_integer(Value), - {ParsedMessage, handle_data(string:substr(Data, NewLinePos+1), ContentLength)} - end. - -handle([[]]) -> - {separator, data_next}; -handle(["Server-Command", Param]) -> - {{srv_cmd, Param}, more}; -handle(["Content-Length", Param]) -> - {{content_len, Param}, more}; -handle(["Token", Param]) -> - {{token, Param}, more}; -handle(["Content-Type", Param]) -> - {{content_type, Param}, more}. - -handle_data(Data, Length) -> - {data, string:substr(Data,1,Length)}. - - -%% Helpers -prettify({Args, Data}) -> - case lists:keyfind(srv_cmd, 1, Args) of - {_, Value} -> - gen_server:cast(ggs_server, {srv_cmd, Value, Args, Data}); - _Other -> - case lists:keyfind(game_cmd, 1, Args) of - {_, Value} -> - gen_server:cast(ggs_server, {game_cmd, Value, Args, Data}); - _ -> - ok - end - end. - diff --git a/src/old/ggs_server.erl b/src/old/ggs_server.erl deleted file mode 100644 index 34d297f..0000000 --- a/src/old/ggs_server.erl +++ /dev/null @@ -1,141 +0,0 @@ -%%%---------------------------------------------------- -%%% @author Jonatan Pålsson -%%% @copyright 2010 Jonatan Pålsson -%%% @doc RPC over TCP server -%%% @end -%%%---------------------------------------------------- - --module(ggs_server). --behaviour(gen_server). - -%% API --export([start_link/1, - start_link/0, - stop/0 - ]). - -%% gen_server callbacks --export([init/1, handle_call/3, handle_cast/2, - handle_info/2, terminate/2, code_change/3]). - - --define(SERVER, ?MODULE). --define(DEFAULT_PORT, 1055). - --record(state, {port, lsock, client_vm_map = []}). - -%%%==================================================== -%%% API -%%%==================================================== - -%%----------------------------------------------------- -%% @doc Starts the server -%% @end -%%----------------------------------------------------- -start_link(Port) -> - gen_server:start_link({local, ?SERVER}, ?MODULE, [Port], []). - -start_link() -> - start_link(?DEFAULT_PORT). - -%%----------------------------------------------------- -%% @doc Stops the server. -%% @spec stop() -> ok -%% @end -%%----------------------------------------------------- -stop() -> - gen_server:cast(?SERVER, stop). - -%%----------------------------------------------------- -%% gen_server callbacks -%%----------------------------------------------------- - -init([Port]) -> - case gen_server:call(ggs_backup, get_backup) of - {backup_state, not_initialized} -> - {ok, LSock} = gen_tcp:listen(Port, [{active, true}, - {reuseaddr, true}]), - {ok, #state{port = Port, lsock = LSock}, 0}; - {backup_state, State} -> - {ok, LSock} = gen_tcp:listen(Port, [{active, true}, - {reuseaddr, true}]), - {ok, State#state{lsock = LSock}, 0} - end. - -handle_call({backup_state, OldState}, _From, State) -> - io:format("Received old state from backup~n"), - {noreply, OldState}. - - -handle_info({tcp, Socket, RawData}, State) -> - ggs_protocol:parse(RawData), - {noreply, State#state{lsock = Socket}}; - -handle_info({tcp_closed, Socket}, State) -> - gen_tcp:close(Socket), - {stop, "Client closed socket", State}; - -handle_info(timeout, #state{lsock = LSock} = State) -> - {ok, _Sock} = gen_tcp:accept(LSock), - {noreply, State}; - -handle_info(Other, State) -> - erlang:display(Other). - -terminate(_Reason, _State) -> - ok. - -code_change(_OldVsn, State, _Extra) -> - {ok, State}. - -%%----------------------------------------------------- -%% Internal functions -%%----------------------------------------------------- -handle_cast(stop, State) -> - {stop, normal, State}; - -% Handle javascript defines -handle_cast({define, Token, SourceCode}, State) -> - GameVM = getJSVM(Token, State), - ggs_vm_runner:define(GameVM, SourceCode), - send(State#state.lsock, Token, "Okay, defined that for you!"), - {noreply, State}; - -% Handle javascript calls -handle_cast({call, Token, Command}, State) -> - GameVM = getJSVM(Token, State), - ggs_vm_runner:user_command(GameVM, "User", Command, []), - %send(State#state.lsock, Token, "JS says:", binary_to_list(Ret)), Unessecary - {noreply, State}; - -% Set the new state to the reference generated, and JSVM associated -handle_cast({hello, _, _}, State) -> - GameVM = ggs_vm_runner:start_link(), - Client = getRef(), - send(State#state.lsock, Client, "This is your refID"), - OldMap = State#state.client_vm_map, - NewState = State#state{client_vm_map = OldMap ++ [{Client, GameVM}]}, - gen_server:cast(ggs_backup, {set_backup, NewState}), - {noreply, NewState}. - -%%----------------------------------------------------- -%% Helpers -%%----------------------------------------------------- -getRef() -> - %{A1,A2,A3} = now(), - %#random:seed(A1, A2, A3), - %random:uniform(1000). - string:strip(os:cmd("uuidgen"), right, $\n ). - -getJSVM(RefID, State) -> - VMs = State#state.client_vm_map, - erlang:display(RefID), - erlang:display(VMs), - {value, {_,VM}} = lists:keysearch(RefID, 1, VMs), - VM. - -send(Socket, RefID, String) -> - gen_tcp:send(Socket, string:join([RefID,String,"\n"], " ")). - -send(Socket, RefID, String1, String2) -> - gen_tcp:send(Socket, string:join([RefID,String1, String2,"\n"], " ")). diff --git a/src/old/ggs_server_sup.erl b/src/old/ggs_server_sup.erl deleted file mode 100644 index 23d32f7..0000000 --- a/src/old/ggs_server_sup.erl +++ /dev/null @@ -1,48 +0,0 @@ --module(ggs_server_sup). --behaviour(supervisor). - -%% API --export([start/1, start_link/1]). - -%% Supervisor callbacks --export([init/1]). --define(SERVER, ?MODULE). - -start(Port) -> - [FirstArg] = Port, - {IntPort, _} = string:to_integer(FirstArg), - start_link(IntPort). - -start_link(Port) -> - supervisor:start_link({local, ?SERVER}, ?MODULE, [Port]). - -init([Port]) -> - GGSServer = {ggs_server, - {ggs_server, start_link, [Port]}, - permanent, - 2000, - worker, - [ggs_server] - }, - Backup = {ggs_backup, - {ggs_backup, start_link, []}, - permanent, - 2000, - worker, - [ggs_backup] - }, - MnesiaServer = {ggs_mnesia_controller_server, - {ggs_mnesia_controller_server, start_link, []}, - permanent, - 2000, - worker, - [ggs_mnesia_controller_server] - }, - Children = [MnesiaServer, Backup, GGSServer], - - RestartStrategy = { one_for_one, % Restart only crashing child - 10, % Allow ten crashes per.. - 1 % 1 second, then crash supervisor. - }, - {ok, {RestartStrategy, Children}}. - diff --git a/src/old/ggs_sup.erl b/src/old/ggs_sup.erl deleted file mode 100644 index ee6f8cd..0000000 --- a/src/old/ggs_sup.erl +++ /dev/null @@ -1,34 +0,0 @@ --module(ggs_sup). --behaviour(supervisor). - -%% API --export([start/1, start_link/1]). - -%% Supervisor callbacks --export([init/1]). --define(SERVER, ?MODULE). - -start(Port) -> - [FirstArg] = Port, - {IntPort, _} = string:to_integer(FirstArg), - start_link(IntPort). - -start_link(Port) -> - supervisor:start_link({local, ?SERVER}, ?MODULE, [Port]). - -init([Port]) -> - Server = {ggs_server_sup, - {ggs_server_sup, start_link, [Port]}, - permanent, - 2000, - worker, - [ggs_server_sup] - }, - Children = [Server], - - RestartStrategy = { one_for_one, % Restart only crashing child - 10, % Allow ten crashes per.. - 1 % 1 second, then crash supervisor. - }, - {ok, {RestartStrategy, Children}}. - diff --git a/src/old/js_runner.erl b/src/old/js_runner.erl deleted file mode 100644 index ca866c4..0000000 --- a/src/old/js_runner.erl +++ /dev/null @@ -1,13 +0,0 @@ --module(js_runner). --export([define/2,call/3, boot/0]). - -boot() -> - erlang_js:start(), - {ok, Port} = js_driver:new(), - Port. - -define(Port, Data) -> - ok = js:define(Port, list_to_binary(Data)). - -call(Port, Func, Params) -> - js:call(Port, list_to_binary(Func), Params). diff --git a/src/old/start_ggs.erl b/src/old/start_ggs.erl deleted file mode 100644 index 3955715..0000000 --- a/src/old/start_ggs.erl +++ /dev/null @@ -1,7 +0,0 @@ --module(start_ggs). --export([start/0]). - -start() -> - application:start(inets), - application:start(erlang_js), - application:start(ggs).