From 3c15d3a37088a7db442bf40fdb880a0f178df3de Mon Sep 17 00:00:00 2001 From: Kallfaktorn Date: Thu, 3 Feb 2011 14:06:27 +0100 Subject: [PATCH 01/49] mnesia cleanup to keep erlang convention --- Mnesia/gamedb.erl | 31 -------------- Mnesia/gamedb.hrl | 6 --- Mnesia/gamedb_usage.txt | 12 ------ games/tic-tac-toe-js/js/TicTacToeClient.js | 2 +- games/tic-tac-toe/TODO | 8 +--- games/tic-tac-toe/e.png | Bin 2565 -> 187 bytes games/tic-tac-toe/tictactoeboard.py | 11 +++++ games/tic-tac-toe/tictactoeboard.pyc | Bin 2379 -> 2379 bytes src/ggs_server.erl | 46 ++++----------------- 9 files changed, 22 insertions(+), 94 deletions(-) delete mode 100644 Mnesia/gamedb.erl delete mode 100644 Mnesia/gamedb.hrl delete mode 100644 Mnesia/gamedb_usage.txt diff --git a/Mnesia/gamedb.erl b/Mnesia/gamedb.erl deleted file mode 100644 index 9d6bbbe..0000000 --- a/Mnesia/gamedb.erl +++ /dev/null @@ -1,31 +0,0 @@ -%Test Mnesia --module(gamedb). --import(mnesia). --export([init/0,insert_player/1,example_player/0,read_player/1,test_player/0]). --include("gamedb.hrl"). - -init() -> - mnesia:create_table(player, [{attributes, record_info(fields, player)}]). - -test_player() -> - insert_player(example_player()), - read_player(0001). - -insert_player(Player) -> - Fun = fun() -> - mnesia:write(Player) - end, - mnesia:transaction(Fun). - -example_player() -> - #player{id = 0001, - name = "Tux"}. - -read_player(Player_Key) -> - Fun = fun() -> - [P] = mnesia:read(player, Player_Key), - Name = P#player.name, - io:format("Player name: ~s~n",[Name]) - end, - mnesia:transaction(Fun). - diff --git a/Mnesia/gamedb.hrl b/Mnesia/gamedb.hrl deleted file mode 100644 index 1ae9c8f..0000000 --- a/Mnesia/gamedb.hrl +++ /dev/null @@ -1,6 +0,0 @@ -%% gamedb.hrl - --record(player, {id, name}). - - - diff --git a/Mnesia/gamedb_usage.txt b/Mnesia/gamedb_usage.txt deleted file mode 100644 index b3a07a0..0000000 --- a/Mnesia/gamedb_usage.txt +++ /dev/null @@ -1,12 +0,0 @@ -1. From terminal: erl -mnesia dir '"/home/user/dir/to/GGS/GameDB.Player"' -2. mnesia:create_schema([node()]). -3. mnesia:start(). -4. c(gamedb). -5. gamedb:init(). -6. mnesia:info(). -7. gamedb:test_player(). - -Last output should be: - Player name: Tux - {atomic,ok} - diff --git a/games/tic-tac-toe-js/js/TicTacToeClient.js b/games/tic-tac-toe-js/js/TicTacToeClient.js index 80f8ef1..79e4064 100644 --- a/games/tic-tac-toe-js/js/TicTacToeClient.js +++ b/games/tic-tac-toe-js/js/TicTacToeClient.js @@ -90,4 +90,4 @@ TicTacToeClient.prototype.updateBoard = function(gameBoardData) { this.spots[k++].innerHTML = t; } } -} \ No newline at end of file +} diff --git a/games/tic-tac-toe/TODO b/games/tic-tac-toe/TODO index 07c0710..a957a1f 100644 --- a/games/tic-tac-toe/TODO +++ b/games/tic-tac-toe/TODO @@ -1,12 +1,6 @@ -- background image -- subimages for game_area:s -- subimages for game markers (X or 0) -- rectangle collision on game_area:s +- background - redraw background then all game_area:s -- board_state: a hashtable where key is game_area_index - and value is either'x' 'o' or ' ' - board contains nr_of_squares = 9 board contains array of squares with nr_of_squares elements board contains x, y, width and height board contains a frame diff --git a/games/tic-tac-toe/e.png b/games/tic-tac-toe/e.png index 4cbf977f58bdbe47864f563ba90a313820b2af27..1b1d7f7bb08b08b11a4f2d93597d2cfb9ba1360e 100644 GIT binary patch delta 117 zcmZn_+08h?ke@Bd+uel$41PNAuAiu<5G~KA!xiM)-VYSC_H=O!i8%cBoFO9v0|&Fh q*81l&58P)Ky5RY0{>tfF@Blq-Mh)h~7JYG5klCKDelF{r5}E+K7A{=? delta 2516 zcmV;_2`l!y0fiKhF_A+Ze;W<~D#mMS{{R39mq|oHR9FecSqW?u*BPF9bL}zS_4-_& zT)}{WU=twWDv*RAg@mez(v(&$&@?GZTbhunh@`3_B_Wk)m9&Y1N}wu*G-;8V6bghQ z!l}gE*cf6PU&S`|+UsMzyR*A9^IreAV~^Gt?-675tvvhBd;jtMf5-dZ%$g;HFsTf! z^G@%+xB09*`H3}rZegq_sA5?*cIIo-C{;<$>0%f*RDHqw-f#L2>;iETY1g~-}T2{a^z1xySp zF$C+ayF-_zL~g9Wz7wwXTeyr|hzim5a7`dwGo9rin_jhU9S&4NeG!a7fas+d4|Qm|;+C=jqD@Wro7<+VcLHe{bkq2ZwDKApDoQ$D9H+*qQv zjc0UD$i4$O0V^wtESsDOBL#!kq>^Yb8>t)=gl|G3javJ=dgneS+zI!(Z#E-6j4V8Z z{K`cXY1QQAYvg55jUXPQX&9LTERYS?Rw`c}*L^)$e+lA%k7W=mXCm2&qz)Ec<1%bq z#sn52+O~K`^C)8RW!h#%H*$T8%h|wk_F=vaLlm7z+)iWVh_0z^O?qDst z>u+iuf46n72m5-61`q_~%;0k;NfVlpO@$Jqy9BDeyN*Fu_^eJ6(OJPRPCJ4eixWYj z>nXq*PzTm%F`L^9Ix1#4j;J23X|vw-5kqW*`8Hvk5X|6tzt*7&g~e%4E)fdGvBCrb zyEusxJ#|91J9XoMAb%Z!KRC%?lv zTr}!5Af{t68VAX*vwH_+2Qh^j)cW-}SOXmkA;ufD`l}b{{Y3AVc(+HMe~c9%omjbg zrsq$uYo0b5>A09c|EOSrJi&_I`WEi5g7yTue3(62H9r&)ArvHJ0R}#^BW-!5II#e1 ze*vbRJ-^j^I-`YPdUp?ERIorh>95e*cF~qe7>Q$kT|X<&n`s|Zczym8*tK&o8s-|`>OVwzo;KX#~BPn0k+F%uT z{@q%($}(+x;OxJWIlM;|EildHzr?u~e~US5+lvnW#Z$I0qp-l{prK+2a%Q6Rl|Vuv z;b5cg`5SUt9IJk4DO&(7cbJDmCK4y=hf7V(q z6mNw`9T+&!OoG=am1r9R%l(1X8}i@r_Y|dN@`7Yr`ZP2EvG@UaJA%hru3#Hq@KcHm zQW>~PbRR{QXz;YTB>_J^n@yBt$r?~YV9qjQuI0_WK!6BbSuRZ&{|@9@ZFvpQLPtpi ziLUd22@}01)S}`5&sq^nXCR6^f6Mcng-3#btW<1n`2Km4AU+i zeMN%`MD9&e&IZ89(%zal5VS!cmIL$0n*MO3>u5v|u<*7pFpS!zR{=>PCtG-jQ_Rb? zPbqfH&9|4zVva0k8N7>%rhQy}29T{RnL8jI^~CUpLPWH?!iewT01w7Af2sy+m(p;& zc}I2UVL*mro+^!W7y{9a1nD6hE7G7 zi;t}0;lxgQn5K22c>-T~e?!efo*)b}5ILx}zEJCD&D$$GK7|S!2^?gXHgsCr7~*Fa zs6jZHQmP}Sg~;Ov$GE5+h^Vz)?LEjL0Iee1aEniT1+&Xkm0sXfqLhW#6xF7 z0|zS@(@4l4X3xVJIn}uxNh3c=~*iw zIq_hb>P+X%nUM&Cf3q{t_t35v=jE3iSi3cr(^&0N8V}yuR@;42dx=4Iti;VV_adiq4$eDmCwL_l6ZLl6T`r! znV-LLVZo0LOfa7mtXRVdX#?4!;?l<_l)d`-{)ny_GjQz)f7E_b_bb2J1+<|DY7`z^*-G5kM&rto^(sgY<@6L-yjG3?=INJ0^Z}>KCOwka+Z#oxAD#T-p~KjyrZrEx;Txh!&1uLq1JgT@3mwy-$Fx$UmbU|(2MO_RwGe`5;^jvAF{iWcb&1(HEy@{BPo zLVRJxXjG=jWQeha71AOn8n0P+0g5acG$v1K+@@GE1T^te&DDWme~}|A)8+C;VvTJTZ3D`4cOvCYsc(77Zbe9=u2Pd1VF1OaY(_G6Zmci=(zd;!OymI2N z@EhEmO1uZAW)1oO-dzsd^LDJxL^!8EtH0c<_~HG`A=&O}JI>^oz=CK+U#kY}(%ZoY etT<3&m;MK;KXf^>gn3f{0000tbXthrpNE$#?X=rQb{9?nD;xx{ delta 16 XcmX>tbXthrpNE(0V3*TIb{9?nEB^$> diff --git a/src/ggs_server.erl b/src/ggs_server.erl index d7be36e..f440cde 100644 --- a/src/ggs_server.erl +++ b/src/ggs_server.erl @@ -1,13 +1,15 @@ %%%---------------------------------------------------- %%% @author Jonatan PÃ¥lsson %%% @copyright 2010 Jonatan PÃ¥lsson -%%% @doc RPC over TCP server %%% @end %%%---------------------------------------------------- -module(ggs_server). -behaviour(gen_server). +% import +-import(ggs_connection). + %% API -export([start_link/1, start_link/0, @@ -16,8 +18,7 @@ ]). %% gen_server callbacks --export([init/1, handle_call/3, handle_cast/2, - handle_info/2, terminate/2, code_change/3]). +-export([terminate/2, code_change/3]). -define(SERVER, ?MODULE). @@ -61,28 +62,6 @@ stop() -> %%----------------------------------------------------- %% gen_server callbacks %%----------------------------------------------------- - -init([Port]) -> - {ok, LSock} = gen_tcp:listen(Port, [{active, true}, - {reuseaddr, true}]), - {ok, #state{port = Port, lsock = LSock}, 0}. - -handle_call(get_count, _From, State) -> - {reply, {ok, State#state.client_vm_map}, State}. - -handle_cast(stop, State) -> - {stop, normal, State}. - -handle_info({tcp, Socket, RawData}, State) -> - NewState = do_JSCall(Socket, RawData, State), - OldMap = State#state.client_vm_map, - io:format("Old map: ~p NewState: ~p~n", [OldMap, NewState]), - {noreply, State#state{client_vm_map = OldMap ++ [NewState]}}; - -handle_info(timeout, #state{lsock = LSock} = State) -> - {ok, _Sock} = gen_tcp:accept(LSock), - {noreply, State}. - terminate(_Reason, _State) -> ok. @@ -92,7 +71,6 @@ code_change(_OldVsn, State, _Extra) -> %%----------------------------------------------------- %% Internal functions %%----------------------------------------------------- - do_JSCall(Socket, Data, State) -> JSVM = js_runner:boot(), js_runner:define(JSVM, "function userCommand(cmd, par) {return cmd+' '+ par}"), @@ -103,23 +81,23 @@ do_JSCall(Socket, Data, State) -> Ret = js_runner:call(JSVM, "userCommand", [list_to_binary(Command), list_to_binary(Parameter)]), - send(Socket, "RefID", "JS says: ", Ret), + connection:send(Socket, "RefID", "JS says: ", Ret), []; % Set the new state to the reference generated, and JSVM associated {hello} -> Client = getRef(), - send(Socket, Client, "__ok_hello"), + connection:send(Socket, Client, "__ok_hello"), {Client, JSVM}; {echo, RefID, _, MSG} -> - send(Socket, RefID, "Your VM is ", getJSVM(RefID, State)), + connection:send(Socket, RefID, "Your VM is ", getJSVM(RefID, State)), []; {crash, Zero} -> 10/Zero; {vms} -> - send(Socket, "RefID", State); + connection:send(Socket, "RefID", State); % Set the new state to [] Other -> - send(Socket, "RefID", "__error"), + ggs_connection:send(Socket, "RefID", "__error"), [] end, % Return the new state @@ -136,9 +114,3 @@ getJSVM(RefID, State) -> VMs = State#state.client_vm_map, {value, {_,VM}} = lists:keysearch(RefID, 1, VMs), VM. - -send(Socket, RefID, String) -> - gen_tcp:send(Socket, io_lib:fwrite("~p ~p~n", [RefID,String])). - -send(Socket, RefID, String1, String2) -> - gen_tcp:send(Socket, io_lib:fwrite("~p ~p ~p~n", [RefID, String1, String2])). From f59d59814a627b55732edbf2b7a2838eaa00d58c Mon Sep 17 00:00:00 2001 From: Kallfaktorn Date: Thu, 3 Feb 2011 14:09:57 +0100 Subject: [PATCH 02/49] renaming Mnesia/ to mnesia/ --- mnesia/.gamedb.erl.swp | Bin 0 -> 12288 bytes mnesia/gamedb.erl | 50 ++++++++++++++++++++++++++++++++++++++++ mnesia/gamedb.hrl | 6 +++++ mnesia/gamedb_usage.txt | 12 ++++++++++ 4 files changed, 68 insertions(+) create mode 100644 mnesia/.gamedb.erl.swp create mode 100644 mnesia/gamedb.erl create mode 100644 mnesia/gamedb.hrl create mode 100644 mnesia/gamedb_usage.txt diff --git a/mnesia/.gamedb.erl.swp b/mnesia/.gamedb.erl.swp new file mode 100644 index 0000000000000000000000000000000000000000..469b1f85b2ecf7663f6f99f957c41243aa53c9d9 GIT binary patch literal 12288 zcmeI2zfTlF6vqcEQBk9XjV9wE^c~uUwxG9A3wj3SpnmAjS;oFXpP_fq7W5WsLG#cJs2}=` z*tenA&^%Ow94N`@1lEK?CIUo&2oM1xKm>@u|3rXec*zmXaifJFiH1>upT8UXg)*~~ z>5#r#WV<)}R~3ve1=%yL;PBeT2;Jn`8LfGIzc+H@1JWO|Mq+22omqCbw2|9xebwV&MdL9H&}jaz%JyTka;4q><#@S!BC3>)Gzy4_c#PjEwfs92d$g zeDw@9$s((11KAk4Xhgj&_xgNpO&Ft9Jx0hyu4N<8?xOOSg8Y(_Z5Pkd9xtpfAbI60 zlk|Vj0invbZ5$|a&pud5`Hgn$%6u+6_TAF$9KtKfl`zmIKWF2tIK{3yRjS4AN?}1q zeKFlpwTffYEh!vShrbk{ec%Od40`En@qpXv@LICLF(fp^C$W{KAKaj^+l+SvsEbH) z>}FiYzERkptP}oRXk`n+an@anrYxtnjUZgrs@XD}k2uvTuc1mxM0`dXBXtxd^zbqf jn-*N!@$V9T6Fa9h3+=0-$)+b%yW9vo`z7sdlVX1X$Qr-k literal 0 HcmV?d00001 diff --git a/mnesia/gamedb.erl b/mnesia/gamedb.erl new file mode 100644 index 0000000..751eb92 --- /dev/null +++ b/mnesia/gamedb.erl @@ -0,0 +1,50 @@ +%%%%---------------------------------------------------- +%%% @author Mattias Pettersson +%%% @copyright 2011 Mattias Pettersson +%%% @doc Database for runtime game variable storage. +%%% @end + + Test Mnesia +-module(gamedb). +-import(mnesia). +-export([init/0,insert_player/1,example_player/0,read_player/1,test_player/0]). +-include("gamedb.hrl"). + +%%----------------------------------------------------- +%% Creation +%%----------------------------------------------------- +init() -> + mnesia:create_table(player, [{attributes, record_info(fields, player)}]). + +%%----------------------------------------------------- +%% Test +%%----------------------------------------------------- +test_player() -> + insert_player(example_player()), + read_player(0001). + +example_player() -> + #player{id = 0001, + name = "Tux"}. + +%%----------------------------------------------------- +%% Insertions +%%----------------------------------------------------- +insert_player(Player) -> + Fun = fun() -> + mnesia:write(Player) + end, + mnesia:transaction(Fun). + + +%%----------------------------------------------------- +%% Querries +%%----------------------------------------------------- +read_player(Player_Key) -> + Fun = fun() -> + [P] = mnesia:read(player, Player_Key), + Name = P#player.name, + io:format("Player name: ~s~n",[Name]) + end, + mnesia:transaction(Fun). + diff --git a/mnesia/gamedb.hrl b/mnesia/gamedb.hrl new file mode 100644 index 0000000..1ae9c8f --- /dev/null +++ b/mnesia/gamedb.hrl @@ -0,0 +1,6 @@ +%% gamedb.hrl + +-record(player, {id, name}). + + + diff --git a/mnesia/gamedb_usage.txt b/mnesia/gamedb_usage.txt new file mode 100644 index 0000000..b3a07a0 --- /dev/null +++ b/mnesia/gamedb_usage.txt @@ -0,0 +1,12 @@ +1. From terminal: erl -mnesia dir '"/home/user/dir/to/GGS/GameDB.Player"' +2. mnesia:create_schema([node()]). +3. mnesia:start(). +4. c(gamedb). +5. gamedb:init(). +6. mnesia:info(). +7. gamedb:test_player(). + +Last output should be: + Player name: Tux + {atomic,ok} + From 468d701c0df622de612b916fc770af70032eccf7 Mon Sep 17 00:00:00 2001 From: niklas Date: Thu, 3 Feb 2011 17:54:23 +0100 Subject: [PATCH 03/49] Change to ggs_server(not finished) --- src/ggs_server.erl | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/ggs_server.erl b/src/ggs_server.erl index d7be36e..bbb0e90 100644 --- a/src/ggs_server.erl +++ b/src/ggs_server.erl @@ -47,8 +47,11 @@ start_link() -> %% Count = integer() %% @end %%----------------------------------------------------- -get_count() -> - gen_server:call(?SERVER, get_count). +get_count() -> gen_server:call(?SERVER, get_count). +_crash() -> gen_server:call(?SERVER, _crash). +_vms() -> gen_server:call(?SERVER, _vms). +_hello() -> gen_server:call(?SERVER, _hello). +_echo() -> gen_server:call(?SERVER, {_echo, RefID, _, MSG}). %%----------------------------------------------------- %% @doc Stops the server. @@ -68,7 +71,27 @@ init([Port]) -> {ok, #state{port = Port, lsock = LSock}, 0}. handle_call(get_count, _From, State) -> - {reply, {ok, State#state.client_vm_map}, State}. + {reply, {ok, State#state.client_vm_map}, State}; + +handle_call(_crash, _From, State) -> + Zero/10. + {reply, sdas , State}; + +%handle_call(_hello, _From, State) -> +% Client = getRef(); +% send(Socket, Client, "_ok_hello"), +% {Client, JVSM) +%{reply, Client, State}; + +%handle_call(_vms, _From, State) -> +% send(Socket, "RefID", State) +%{reply, , State}; + +%handle_call(_echo, RefID, _, MSG) -> +%{reply, ,State}; + +handle_call(_Message, _From, State) + {reply, error, State}. handle_cast(stop, State) -> {stop, normal, State}. From 71fa6f30ba69d1502f57df24d80ba77849aa2604 Mon Sep 17 00:00:00 2001 From: Kallfaktorn Date: Fri, 4 Feb 2011 14:10:23 +0100 Subject: [PATCH 04/49] Moved the parts of network out of server. Partly added extensions to tic-tac-toe py. --- games/tic-tac-toe/data.py | 15 ++++ games/tic-tac-toe/data.pyc | Bin 0 -> 531 bytes games/tic-tac-toe/player.py | 15 ++++ games/tic-tac-toe/server.py | 23 +++++ games/tic-tac-toe/test_data.py | 14 +++ src/.ggs_connection.erl.swp | Bin 0 -> 12288 bytes src/ggs_network.beam | Bin 0 -> 2820 bytes src/ggs_network.erl | 160 +++++++++++++++++++++++++++++++++ src/ggs_server.beam | Bin 0 -> 616 bytes src/ggs_server.erl | 84 +++-------------- 10 files changed, 237 insertions(+), 74 deletions(-) create mode 100644 games/tic-tac-toe/data.py create mode 100644 games/tic-tac-toe/data.pyc create mode 100644 games/tic-tac-toe/player.py create mode 100644 games/tic-tac-toe/server.py create mode 100644 games/tic-tac-toe/test_data.py create mode 100644 src/.ggs_connection.erl.swp create mode 100644 src/ggs_network.beam create mode 100644 src/ggs_network.erl create mode 100644 src/ggs_server.beam diff --git a/games/tic-tac-toe/data.py b/games/tic-tac-toe/data.py new file mode 100644 index 0000000..b83c3ad --- /dev/null +++ b/games/tic-tac-toe/data.py @@ -0,0 +1,15 @@ +def greatest_sequence(match, pattern): + m = match + p = pattern + size = 0 + max_size = 0 + + for p in pattern: + if m == p: + size += 1 + else: + if size > max_size: + max_size = size + size = 0 + + return max_size diff --git a/games/tic-tac-toe/data.pyc b/games/tic-tac-toe/data.pyc new file mode 100644 index 0000000000000000000000000000000000000000..682dfaaa9031d0195431a988ddaa757e082356a8 GIT binary patch literal 531 zcmb_YO-sW-5S?tBR-`$2^X4@dyGK!^hziAn?V$%jkg_C88rn_L{eUXT%^&WYRM3M* zcQbF_%)FhvWI0JrucuGX8U0!j_#MI}fSl-)=oKWQRVq-)7?6bgqkOgrW3WbfuWc1rWO{7E5Zsj?I-K;YD_JO`o%CgP=@p{ZGFM(roA+>rIfd1@>-^g3eb7~=*@!y_ qP&7JjF{V*8i4rkEo`^-tlD{winC#iVIprU5YwA4g^sG0?{=NWR({FA7 literal 0 HcmV?d00001 diff --git a/games/tic-tac-toe/player.py b/games/tic-tac-toe/player.py new file mode 100644 index 0000000..081112c --- /dev/null +++ b/games/tic-tac-toe/player.py @@ -0,0 +1,15 @@ +from pygame.mouse import get_pos +from point import Point + +class Player(object): + def __init__(self, id, shape, board): + self.shape = shape + self.board = board + self.id = id + + + def turn(self): + #Ask mouse for position + board.make_turn(Point(get_pos()[0],get_pos()[1])) + + diff --git a/games/tic-tac-toe/server.py b/games/tic-tac-toe/server.py new file mode 100644 index 0000000..91e32b5 --- /dev/null +++ b/games/tic-tac-toe/server.py @@ -0,0 +1,23 @@ +#server.py +import json +from socket import socket, AF_INET, SOCK_STREAM + + +class server(object): + def __init__(self, port=None): + self.port = port + self.world = GGS.init() + self.socket = socket(AF_INET, SOCK_STREAM) + self.socket.connect(("www.???.com", 80)) + + def turn(self, id, index): + rows = sqrt(board.nr_of_rectangles) + x = int(index / rows) + y = int(index % rows) + + json.dumps({"x": x, "y": y} + world.callCommand("tictactoe", "set", json.dumps({"x": x, "y": y})) + + sent = 0 + length = len( + while sent diff --git a/games/tic-tac-toe/test_data.py b/games/tic-tac-toe/test_data.py new file mode 100644 index 0000000..38282f0 --- /dev/null +++ b/games/tic-tac-toe/test_data.py @@ -0,0 +1,14 @@ +import unittest +import data + + +class TestData(unittest.TestCase): + def setUp(self): + array = [0,1,1,1,3,4,5,2,2,3,3,3,3,3,33,4,2,2] + + self.assertTrue(data.greatest_sequence(array, 3) == 5) + +if __name__ == '__main__': + unittest.main() + + diff --git a/src/.ggs_connection.erl.swp b/src/.ggs_connection.erl.swp new file mode 100644 index 0000000000000000000000000000000000000000..0c009f8287377d2e3763a3fb7610231c3237d3fb GIT binary patch literal 12288 zcmeI2O>Z1E7{^^+M0qKoqMo?8TdkN?XJ3-EAceGwl!%h3+pLndm(^7W&e$W5 zH=){YkdU|{!I^9M0Eiwz;sQv$@CmqagL`?A;O}|aYywf~wg)QN%3m`c+m9drp2wC} z@pkLxTARMpSRg2`6LRL$wf0X-7s$022}!jSJV-*tG&jx1l^q@@QXbcO@O^*UU^7v2 zpjaG-V$kF&Vt8D+veitL-y955&zC}QUx!jO(0X9RzF7j6z#|igm=49FN1 zorLbcO2}R4b0~m(Xd7xnSD`;o5%LH0JMre&y z^<_eSfqsPUL0>^0^cM8jON4v_-GN5XD)c7wJoFs&EOa0D7QTi)hWbziItx9(`pg>d znswS@30MM_fF)oFSOWih0yHZFE521sA2M4uN3~j?rI2cs zUSH|Z6&6J)MQs)%b%ft6aU`VTNp#y_!hO$iBmXLIxzsbX$Mn(!1M_{JXy>Z=UUSI~ z6G6niQ1qpv!-Ta5CfkPGeY#$L=44BCi-HeSx3 zr`>COFEh~_kKfH)4CP{9s+eh~f^HN87EKbA{Y)i~N^ZoRwDjOQ7G4@JT+2OZ9P%LV zS6YNWf%Mk54E9MPZnC{qrddI+=F;l*jn$1qXhz6hv=^CM3>cRqkZZ;nT1^;k#d6J6 zN_}Z=$I`x%amGI7YL}}bUbsvPbBJ2ZqJy9nvG7@{oxI0U;6;>2CbC)Ezpc1*3u!R1 zh}90b#>L#BKzzOT;MJ7#Gp8St`28$_R64T_V#sAHDiSD>N+V7kJY0G>2VL4KlG_Y= zSQ#lkOgRez)c+ z8=X?jj*O5x|G;o^y2h_24#=rcH|M9Ssh+BuZEmXO1Z^%9&kH@AsiYpuU>I@7+}}3) zo@?_JF3xl^nQ?R(v*a&<^vhu7dx++@6`$SNyIWtp&fM)ePSPaacrX6QIlisWAw4IR#yLT%N4tb)`)M{Du*Ms?|c4- z_8^S9o?o>pOD4yi^eE&I9WOeGGohHt!~;9DD|Xd(!x*?@pjhZsZLc0ity0OZg;HR< z<*4Jq)+VBp2Ym-vg|=UHT;R8??P?BQk6(=C0 zf4BvseCQknf%e#w)b$QVeUQYf0$;lvtGf>F5p)fA?0tAw1cL-kv-aV@w*1m`3t`FPW05o8qWJ&GV*e3Q494wTGy1R7_rF!hGg&dX-;Qd6Mqd z4B?EJyhDU@{LX@b3m3&?JYfh|GMDMq{7rrErp||TLWgxj&D^AySj`yKau^un$CGBx z)K%d+H#NGOjS075bxIRtmiZgK!?=b{cg%RJsj7mUfXNjwnanFH9aIw30QNet&ka*; zB%>tscw37x##NnuE;TcbOjIex=JQG`&~9B2J)^XO;szPjK!!D@geuD^)Inxrh9I|s;_?dEaXSp! zlm=a?paWMGxpLrohC@%HvUZLM@=A2&g1ky$;~b8-kZWvf(S7Xy-B*Kq2WWX8KTjd? z8W`%3Xe~1|WCZ5})^%V_gSEYx8wrW4AXl2xff%{S&GCggy24X5k&3bFd8LzXqe^Gn zQKo2I(KRJ)C>sR1QDKJCscuzalE*hH>*E=vLy*^Vv!?R2&IhP$+y>?yiL^wNZrqf4 z6wO>6h#9vRH5vekIBNgj9W$(#x`?HBu}ADk7wKYMS}`)-rO`&V4NFU)!r(w5V;0lp(lI6{kZBrN zHU^Bd0u^(GbWZ2ynMVB>EM~|_Zk_`RY?bD)sMtp+bv9`o<`9(URk7sue1)euEWY!?)(9YM_vJoda!ynLWC`F#+kgb2}*O* zQfV5nlTA>X1WHrq2^H41<&|ED-h0mnLFrZFgJ9OdtZTzMTcFj8kvA>9uW}#c*a``= z_&s3qNeYl{>K2g_5na1fOhmp ztyB@G z?`JQ(7ysd@uC7-P#r)H^j=a6{iMD;mK7D2NkH6Ud&6B_S!u(HHzIkHj=j|WNU%Qd{ zMf+d=Idk^Wv(J^!w)wr^IP$^q8-H$kSorMSTXScgIrF>y(Kn7f(Q`LDyX)sK{D*YR zJn|$VJG~NWfVG5rZULY^836v@SGFu%!KQqx3KzJk?84PFYnpqrfnUnrbD!;lDdaUY5roi?{{lLRLn{CP literal 0 HcmV?d00001 diff --git a/src/ggs_network.erl b/src/ggs_network.erl new file mode 100644 index 0000000..1ee46f6 --- /dev/null +++ b/src/ggs_network.erl @@ -0,0 +1,160 @@ +%%%---------------------------------------------------- +%%% @author Jonatan Pålsson +%%% @copyright 2010 Jonatan Pålsson +%%% @doc RPC over TCP server +%%% @end +%%%---------------------------------------------------- +%%% @author Mattias Pettersson +%%% @doc Socket module for GGS +%%% @end +%%%---------------------------------------------------- + + +-module(ggs_network). + +-behaviour(gen_server). + +%define +-define(SERVER, ?MODULE). +-define(DEFAULT_PORT, 1055). + + +% export +-export([start_link/0,start_link/1]). +-export([init/1, handle_call/3, handle_cast/2, handle_info/2]). +-export([get_count/1, send/3, send/4]). +-export([stop/0]). + +%% gen_server callbacks +-export([terminate/2, code_change/3]). + +%state +-record(state, {port, lsock, client_vm_map = []}). + + +%%----------------------------------------------------- +%% @doc Starts gen_server +%% @end +%%----------------------------------------------------- +start_link() -> + start_link(?DEFAULT_PORT). + +start_link(Port) -> + process_flag(trap_exit, true), + gen_server:start_link({local, ?SERVER}, ?MODULE, [Port], []). + +%%----------------------------------------------------- +%% Creation +%%----------------------------------------------------- +init([Port]) -> + {ok, LSock} = gen_tcp:listen(Port, [{active, true}, + {reuseaddr, true}]), + {ok, #state{port = Port, lsock = LSock}, 0}. + +%%----------------------------------------------------- +%% @doc Fetches the number of requests made to this server +%% @spec get_count() -> {ok, Count} +%% where +%% Count = integer() +%% @end +%%----------------------------------------------------- +get_count(get_count) -> + gen_server:call(?SERVER, get_count). + +%%----------------------------------------------------- +%% @doc Stops the server. +%% @spec stop() -> ok +%% @end +%%----------------------------------------------------- +stop() -> + gen_server:cast(?SERVER, stop). + +%%----------------------------------------------------- +%% Handlers +%%----------------------------------------------------- +handle_call(get_count, _From, State) -> + {reply, {ok, State#state.client_vm_map}, State}. + +handle_cast(stop, State) -> + {stop, normal, State}. + +handle_info({tcp, Socket, RawData}, State) -> %parameters coming from gen_server + NewState = do_JSCall(Socket, RawData, State), %TODO + OldMap = State#state.client_vm_map, + io:format("Old map: ~p NewState: ~p~n", [OldMap, NewState]), + {noreply, State#state{client_vm_map = OldMap ++ [NewState]}}; + +handle_info(timeout, #state{lsock = LSock} = State) -> + {ok, _Sock} = gen_tcp:accept(LSock), + {noreply, State}. + + +%%----------------------------------------------------- +%% TCP Calls +%%----------------------------------------------------- +send(Socket, RefID, String) -> + gen_tcp:send(Socket, io_lib:fwrite("~p ~p~n", [RefID,String])). + +send(Socket, RefID, String1, String2) -> + gen_tcp:send(Socket, io_lib:fwrite("~p ~p ~p~n", [RefID, String1, String2])). + + +%%----------------------------------------------------- +%% gen_server callbacks +%%----------------------------------------------------- +terminate(_Reason, _State) -> + ok. + +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + +%%----------------------------------------------------- +%% Internal functions +%%----------------------------------------------------- +do_JSCall(Socket, Data, State) -> + JSVM = js_runner:boot(), + js_runner:define(JSVM, "function userCommand(cmd, par) {return cmd+' '+ par}"), + Parsed = ggs_protocol:parse(Data), + NewState = case Parsed of + {cmd, Command, Parameter} -> + % Set the new state to [] + Ret = js_runner:call(JSVM, "userCommand", + [list_to_binary(Command), + list_to_binary(Parameter)]), + connection:send(Socket, "RefID", "JS says: ", Ret), + []; + % Set the new state to the reference generated, and JSVM associated + {hello} -> + Client = getRef(), + connection:send(Socket, Client, "__ok_hello"), + {Client, JSVM}; + {echo, RefID, _, MSG} -> + connection:send(Socket, RefID, "Your VM is ", getJSVM(RefID, State)), + []; + {crash, Zero} -> + 10/Zero; + {vms} -> + connection:send(Socket, "RefID", State); + % Set the new state to [] + Other -> + ggs_connection:send(Socket, "RefID", "__error"), + [] + end, + % Return the new state + NewState. + +%%----------------------------------------------------- +%% Helpers +%%----------------------------------------------------- +getRef() -> + {A1,A2,A3} = now(), + random:seed(A1, A2, A3), + random:uniform(1000). + +%%----------------------------------------------------- +%% Helpers +%%----------------------------------------------------- +getJSVM(RefID, State) -> + VMs = State#state.client_vm_map, + {value, {_,VM}} = lists:keysearch(RefID, 1, VMs), + VM. diff --git a/src/ggs_server.beam b/src/ggs_server.beam new file mode 100644 index 0000000000000000000000000000000000000000..8818249268afb82e14ee2ed7b316d9b5a9b4d5c5 GIT binary patch literal 616 zcmY+Cv2GJV5Qb;>&KGPGaXMbWiV_JLUqDDSDb83Sie#L~MwB?~^X7cEZ}+sjHZ+kU zAt4HiJVKiEl$2EIQ`7StnK^6`M*435`DZjc(%##X!3zL>_U5qjuH$q803VThBg^c_ zO0$xtW}PsuNrsZ{lQ#24<%|}&n%6VwMyXyZ=Ub=CW}zp`g&gJTTnExDgvy>!#{(On zt0xlgNRbes=p)-mz(OAF0BfPa_ECl`>4zaZ<kpXs{ zL|91J56nXLEAgI^(K_{D=*)YZ3&%xCXAcPw5AhL-jb>|I!*iplm*NppN66o3e)##n znOp1nV?0SyG?0fgXf_3T9HDu%2Wbl4(<$v)?bdP5pnmpcfnPS|6Yy46Rf!5g_o6?~ zFK+I>erw+T-2K32v+l7v$IkCnzfb*Jx^%f#c2*_$mKL)))Lyk;w_lRyyS$LoV2m68 z7F_sZThzoJRRXJ*CY5tIh^M-cF}|*nlQK8L$+$E+GomPRmBoKwIX*fX#@3|qzyGF< Lm04$O9qt78!%2Cj literal 0 HcmV?d00001 diff --git a/src/ggs_server.erl b/src/ggs_server.erl index f440cde..c3514e7 100644 --- a/src/ggs_server.erl +++ b/src/ggs_server.erl @@ -5,27 +5,19 @@ %%%---------------------------------------------------- -module(ggs_server). --behaviour(gen_server). % import --import(ggs_connection). +-import(ggs_network). %% API --export([start_link/1, - start_link/0, +-export([start/0, + start/1, get_count/0, stop/0 ]). -%% gen_server callbacks --export([terminate/2, code_change/3]). --define(SERVER, ?MODULE). --define(DEFAULT_PORT, 1055). - --record(state, {port, lsock, client_vm_map = []}). - %%%==================================================== %%% API %%%==================================================== @@ -34,12 +26,12 @@ %% @doc Starts the server %% @end %%----------------------------------------------------- -start_link(Port) -> - process_flag(trap_exit, true), - gen_server:start_link({local, ?SERVER}, ?MODULE, [Port], []). +start() -> + ggs_network:start_link(). + +start(Port) -> + ggs_network:start_link(Port). -start_link() -> - start_link(?DEFAULT_PORT). %%----------------------------------------------------- %% @doc Fetches the number of requests made to this server @@ -49,7 +41,7 @@ start_link() -> %% @end %%----------------------------------------------------- get_count() -> - gen_server:call(?SERVER, get_count). + ggs_network:get_count(get_count). %%----------------------------------------------------- %% @doc Stops the server. @@ -57,60 +49,4 @@ get_count() -> %% @end %%----------------------------------------------------- stop() -> - gen_server:cast(?SERVER, stop). - -%%----------------------------------------------------- -%% gen_server callbacks -%%----------------------------------------------------- -terminate(_Reason, _State) -> - ok. - -code_change(_OldVsn, State, _Extra) -> - {ok, State}. - -%%----------------------------------------------------- -%% Internal functions -%%----------------------------------------------------- -do_JSCall(Socket, Data, State) -> - JSVM = js_runner:boot(), - js_runner:define(JSVM, "function userCommand(cmd, par) {return cmd+' '+ par}"), - Parsed = ggs_protocol:parse(Data), - NewState = case Parsed of - {cmd, Command, Parameter} -> - % Set the new state to [] - Ret = js_runner:call(JSVM, "userCommand", - [list_to_binary(Command), - list_to_binary(Parameter)]), - connection:send(Socket, "RefID", "JS says: ", Ret), - []; - % Set the new state to the reference generated, and JSVM associated - {hello} -> - Client = getRef(), - connection:send(Socket, Client, "__ok_hello"), - {Client, JSVM}; - {echo, RefID, _, MSG} -> - connection:send(Socket, RefID, "Your VM is ", getJSVM(RefID, State)), - []; - {crash, Zero} -> - 10/Zero; - {vms} -> - connection:send(Socket, "RefID", State); - % Set the new state to [] - Other -> - ggs_connection:send(Socket, "RefID", "__error"), - [] - end, - % Return the new state - NewState. -%%----------------------------------------------------- -%% Helpers -%%----------------------------------------------------- -getRef() -> - {A1,A2,A3} = now(), - random:seed(A1, A2, A3), - random:uniform(1000). - -getJSVM(RefID, State) -> - VMs = State#state.client_vm_map, - {value, {_,VM}} = lists:keysearch(RefID, 1, VMs), - VM. + ggs_network:stop(). From 730b29e5cbcc8c1ccb31847a5e668e23f5b725be Mon Sep 17 00:00:00 2001 From: Kallfaktorn Date: Fri, 4 Feb 2011 14:21:48 +0100 Subject: [PATCH 05/49] Moving ggs_server parts to ggs_network. Stop method changed. --- src/ggs_server.erl | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/ggs_server.erl b/src/ggs_server.erl index f6131a2..41cfee3 100644 --- a/src/ggs_server.erl +++ b/src/ggs_server.erl @@ -57,10 +57,7 @@ _echo() -> gen_server:call(?SERVER, {_echo, RefID, _, MSG}). %% @end %%----------------------------------------------------- stop() -> -<<<<<<< HEAD ggs_network:stop(). -======= - gen_server:cast(?SERVER, stop). %%----------------------------------------------------- %% gen_server callbacks From 68658bf74c1437c3b3342c2949061a8e76aee330 Mon Sep 17 00:00:00 2001 From: Kallfaktorn Date: Fri, 4 Feb 2011 14:35:57 +0100 Subject: [PATCH 06/49] Resolving conflicts of ggs_network and ggs_server. --- src/ggs_network.erl | 11 ++++- src/ggs_server.erl | 112 ++------------------------------------------ 2 files changed, 15 insertions(+), 108 deletions(-) diff --git a/src/ggs_network.erl b/src/ggs_network.erl index 1ee46f6..5489069 100644 --- a/src/ggs_network.erl +++ b/src/ggs_network.erl @@ -22,7 +22,8 @@ % export -export([start_link/0,start_link/1]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2]). --export([get_count/1, send/3, send/4]). +-export([get_count/1,crash/0,vms/0,hello/0,echo/0]). +-export([send/3, send/4]). -export([stop/0]). %% gen_server callbacks @@ -61,6 +62,14 @@ init([Port]) -> get_count(get_count) -> gen_server:call(?SERVER, get_count). +crash() -> gen_server:call(?server, _crash). +vms() -> gen_server:call(?SERVER, _vms). +hello() -> gen_server:call(?SERVER, _hello). +echo() -> gen_server:call(?SERVER, {_echo, RefID, _, MSG}). + + + + %%----------------------------------------------------- %% @doc Stops the server. %% @spec stop() -> ok diff --git a/src/ggs_server.erl b/src/ggs_server.erl index 41cfee3..95a53dd 100644 --- a/src/ggs_server.erl +++ b/src/ggs_server.erl @@ -40,16 +40,13 @@ start(Port) -> %% Count = integer() %% @end %%----------------------------------------------------- -<<<<<<< HEAD get_count() -> ggs_network:get_count(get_count). -======= -get_count() -> gen_server:call(?SERVER, get_count). -_crash() -> gen_server:call(?SERVER, _crash). -_vms() -> gen_server:call(?SERVER, _vms). -_hello() -> gen_server:call(?SERVER, _hello). -_echo() -> gen_server:call(?SERVER, {_echo, RefID, _, MSG}). ->>>>>>> 02b72e54457112cb8d576cdcf3e982d2e34407fc + +_crash() -> gen_network:crash(). +_vms() -> gen_network:vms(). +_hello() -> gen_network:hello(). +_echo() -> gen_network:echo(). %%----------------------------------------------------- %% @doc Stops the server. @@ -58,102 +55,3 @@ _echo() -> gen_server:call(?SERVER, {_echo, RefID, _, MSG}). %%----------------------------------------------------- stop() -> ggs_network:stop(). - -%%----------------------------------------------------- -%% gen_server callbacks -%%----------------------------------------------------- - -init([Port]) -> - {ok, LSock} = gen_tcp:listen(Port, [{active, true}, - {reuseaddr, true}]), - {ok, #state{port = Port, lsock = LSock}, 0}. - -handle_call(get_count, _From, State) -> - {reply, {ok, State#state.client_vm_map}, State}; - -handle_call(_crash, _From, State) -> - Zero/10. - {reply, sdas , State}; - -%handle_call(_hello, _From, State) -> -% Client = getRef(); -% send(Socket, Client, "_ok_hello"), -% {Client, JVSM) -%{reply, Client, State}; - -%handle_call(_vms, _From, State) -> -% send(Socket, "RefID", State) -%{reply, , State}; - -%handle_call(_echo, RefID, _, MSG) -> -%{reply, ,State}; - -handle_call(_Message, _From, State) - {reply, error, State}. - -handle_cast(stop, State) -> - {stop, normal, State}. - -handle_info({tcp, Socket, RawData}, State) -> - NewState = do_JSCall(Socket, RawData, State), - OldMap = State#state.client_vm_map, - io:format("Old map: ~p NewState: ~p~n", [OldMap, NewState]), - {noreply, State#state{client_vm_map = OldMap ++ [NewState]}}; - -handle_info(timeout, #state{lsock = LSock} = State) -> - {ok, _Sock} = gen_tcp:accept(LSock), - {noreply, State}. - -terminate(_Reason, _State) -> - ok. - -code_change(_OldVsn, State, _Extra) -> - {ok, State}. - -%%----------------------------------------------------- -%% Internal functions -%%----------------------------------------------------- -do_JSCall(Socket, Data, State) -> - JSVM = js_runner:boot(), - js_runner:define(JSVM, "function userCommand(cmd, par) {return cmd+' '+ par}"), - Parsed = ggs_protocol:parse(Data), - NewState = case Parsed of - {cmd, Command, Parameter} -> - % Set the new state to [] - Ret = js_runner:call(JSVM, "userCommand", - [list_to_binary(Command), - list_to_binary(Parameter)]), - connection:send(Socket, "RefID", "JS says: ", Ret), - []; - % Set the new state to the reference generated, and JSVM associated - {hello} -> - Client = getRef(), - connection:send(Socket, Client, "__ok_hello"), - {Client, JSVM}; - {echo, RefID, _, MSG} -> - connection:send(Socket, RefID, "Your VM is ", getJSVM(RefID, State)), - []; - {crash, Zero} -> - 10/Zero; - {vms} -> - connection:send(Socket, "RefID", State); - % Set the new state to [] - Other -> - ggs_connection:send(Socket, "RefID", "__error"), - [] - end, - % Return the new state - NewState. -%%----------------------------------------------------- -%% Helpers -%%----------------------------------------------------- -getRef() -> - {A1,A2,A3} = now(), - random:seed(A1, A2, A3), - random:uniform(1000). - -getJSVM(RefID, State) -> - VMs = State#state.client_vm_map, - {value, {_,VM}} = lists:keysearch(RefID, 1, VMs), - VM. ->>>>>>> 02b72e54457112cb8d576cdcf3e982d2e34407fc From ffeaa3bdc1741ddb1d3ab080a6d2a4988820cbd6 Mon Sep 17 00:00:00 2001 From: Kallfaktorn Date: Fri, 4 Feb 2011 14:46:29 +0100 Subject: [PATCH 07/49] Fixed spelling errors line in ggs_server line 46-49. --- src/ggs_server.erl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ggs_server.erl b/src/ggs_server.erl index 95a53dd..aed9a0f 100644 --- a/src/ggs_server.erl +++ b/src/ggs_server.erl @@ -43,10 +43,10 @@ start(Port) -> get_count() -> ggs_network:get_count(get_count). -_crash() -> gen_network:crash(). -_vms() -> gen_network:vms(). -_hello() -> gen_network:hello(). -_echo() -> gen_network:echo(). +_crash() -> gss_network:crash(). +_vms() -> gss_network:vms(). +_hello() -> gss_network:hello(). +_echo() -> gss_network:echo(). %%----------------------------------------------------- %% @doc Stops the server. From ea4fdfc362191b1f3313deac541f638f59c0b2f0 Mon Sep 17 00:00:00 2001 From: Kallfaktorn Date: Fri, 4 Feb 2011 14:58:21 +0100 Subject: [PATCH 08/49] Buggfixes in server and network. --- src/ggs_network.erl | 11 ++++++----- src/ggs_server.erl | 17 +++++++---------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/ggs_network.erl b/src/ggs_network.erl index 5489069..97e2568 100644 --- a/src/ggs_network.erl +++ b/src/ggs_network.erl @@ -22,7 +22,8 @@ % export -export([start_link/0,start_link/1]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2]). --export([get_count/1,crash/0,vms/0,hello/0,echo/0]). +%-export([get_count/1,crash/0,vms/0,hello/0,echo/0]). +-export([get_count/1]). -export([send/3, send/4]). -export([stop/0]). @@ -62,10 +63,10 @@ init([Port]) -> get_count(get_count) -> gen_server:call(?SERVER, get_count). -crash() -> gen_server:call(?server, _crash). -vms() -> gen_server:call(?SERVER, _vms). -hello() -> gen_server:call(?SERVER, _hello). -echo() -> gen_server:call(?SERVER, {_echo, RefID, _, MSG}). +%crash() -> gen_server:call(?SERVER, crash). +%vms() -> gen_server:call(?SERVER, vms). +%hello() -> gen_server:call(?SERVER, hello). +%echo() -> gen_server:call(?SERVER, {echo, RefID, _, MSG}). diff --git a/src/ggs_server.erl b/src/ggs_server.erl index aed9a0f..f47c064 100644 --- a/src/ggs_server.erl +++ b/src/ggs_server.erl @@ -10,12 +10,9 @@ -import(ggs_network). %% API --export([start/0, - start/1, - get_count/0, - stop/0 - ]). - +-export([start/0, start/1, stop/0 ]). +%-export([crash/0, vms/0, hello/0, echo/0]). +-export([get_count/0]). %%%==================================================== @@ -43,10 +40,10 @@ start(Port) -> get_count() -> ggs_network:get_count(get_count). -_crash() -> gss_network:crash(). -_vms() -> gss_network:vms(). -_hello() -> gss_network:hello(). -_echo() -> gss_network:echo(). +%crash() -> gss_network:crash(). +%vms() -> gss_network:vms(). +%hello() -> gss_network:hello(). +%echo() -> gss_network:echo(). %%----------------------------------------------------- %% @doc Stops the server. From 386e386ecf62424b0764f6e0711e1aa96fea18a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Fri, 4 Feb 2011 16:33:42 +0100 Subject: [PATCH 09/49] ggs_server needs start_link/0 and start_link/1 to function --- src/ggs_network.beam | Bin 2820 -> 0 bytes src/ggs_server.beam | Bin 616 -> 0 bytes src/ggs_server.erl | 6 +++--- 3 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 src/ggs_network.beam delete mode 100644 src/ggs_server.beam diff --git a/src/ggs_network.beam b/src/ggs_network.beam deleted file mode 100644 index c5531b6b4340e2b4bbcbad0ab9a4d291efacd769..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2820 zcmZ8jeQX>@6`$SNyIWtp&fM)ePSPaacrX6QIlisWAw4IR#yLT%N4tb)`)M{Du*Ms?|c4- z_8^S9o?o>pOD4yi^eE&I9WOeGGohHt!~;9DD|Xd(!x*?@pjhZsZLc0ity0OZg;HR< z<*4Jq)+VBp2Ym-vg|=UHT;R8??P?BQk6(=C0 zf4BvseCQknf%e#w)b$QVeUQYf0$;lvtGf>F5p)fA?0tAw1cL-kv-aV@w*1m`3t`FPW05o8qWJ&GV*e3Q494wTGy1R7_rF!hGg&dX-;Qd6Mqd z4B?EJyhDU@{LX@b3m3&?JYfh|GMDMq{7rrErp||TLWgxj&D^AySj`yKau^un$CGBx z)K%d+H#NGOjS075bxIRtmiZgK!?=b{cg%RJsj7mUfXNjwnanFH9aIw30QNet&ka*; zB%>tscw37x##NnuE;TcbOjIex=JQG`&~9B2J)^XO;szPjK!!D@geuD^)Inxrh9I|s;_?dEaXSp! zlm=a?paWMGxpLrohC@%HvUZLM@=A2&g1ky$;~b8-kZWvf(S7Xy-B*Kq2WWX8KTjd? z8W`%3Xe~1|WCZ5})^%V_gSEYx8wrW4AXl2xff%{S&GCggy24X5k&3bFd8LzXqe^Gn zQKo2I(KRJ)C>sR1QDKJCscuzalE*hH>*E=vLy*^Vv!?R2&IhP$+y>?yiL^wNZrqf4 z6wO>6h#9vRH5vekIBNgj9W$(#x`?HBu}ADk7wKYMS}`)-rO`&V4NFU)!r(w5V;0lp(lI6{kZBrN zHU^Bd0u^(GbWZ2ynMVB>EM~|_Zk_`RY?bD)sMtp+bv9`o<`9(URk7sue1)euEWY!?)(9YM_vJoda!ynLWC`F#+kgb2}*O* zQfV5nlTA>X1WHrq2^H41<&|ED-h0mnLFrZFgJ9OdtZTzMTcFj8kvA>9uW}#c*a``= z_&s3qNeYl{>K2g_5na1fOhmp ztyB@G z?`JQ(7ysd@uC7-P#r)H^j=a6{iMD;mK7D2NkH6Ud&6B_S!u(HHzIkHj=j|WNU%Qd{ zMf+d=Idk^Wv(J^!w)wr^IP$^q8-H$kSorMSTXScgIrF>y(Kn7f(Q`LDyX)sK{D*YR zJn|$VJG~NWfVG5rZULY^836v@SGFu%!KQqx3KzJk?84PFYnpqrfnUnrbD!;lDdaUY5roi?{{lLRLn{CP diff --git a/src/ggs_server.beam b/src/ggs_server.beam deleted file mode 100644 index 8818249268afb82e14ee2ed7b316d9b5a9b4d5c5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 616 zcmY+Cv2GJV5Qb;>&KGPGaXMbWiV_JLUqDDSDb83Sie#L~MwB?~^X7cEZ}+sjHZ+kU zAt4HiJVKiEl$2EIQ`7StnK^6`M*435`DZjc(%##X!3zL>_U5qjuH$q803VThBg^c_ zO0$xtW}PsuNrsZ{lQ#24<%|}&n%6VwMyXyZ=Ub=CW}zp`g&gJTTnExDgvy>!#{(On zt0xlgNRbes=p)-mz(OAF0BfPa_ECl`>4zaZ<kpXs{ zL|91J56nXLEAgI^(K_{D=*)YZ3&%xCXAcPw5AhL-jb>|I!*iplm*NppN66o3e)##n znOp1nV?0SyG?0fgXf_3T9HDu%2Wbl4(<$v)?bdP5pnmpcfnPS|6Yy46Rf!5g_o6?~ zFK+I>erw+T-2K32v+l7v$IkCnzfb*Jx^%f#c2*_$mKL)))Lyk;w_lRyyS$LoV2m68 z7F_sZThzoJRRXJ*CY5tIh^M-cF}|*nlQK8L$+$E+GomPRmBoKwIX*fX#@3|qzyGF< Lm04$O9qt78!%2Cj diff --git a/src/ggs_server.erl b/src/ggs_server.erl index f47c064..097151f 100644 --- a/src/ggs_server.erl +++ b/src/ggs_server.erl @@ -10,7 +10,7 @@ -import(ggs_network). %% API --export([start/0, start/1, stop/0 ]). +-export([start_link/0, start_link/1, stop/0 ]). %-export([crash/0, vms/0, hello/0, echo/0]). -export([get_count/0]). @@ -23,10 +23,10 @@ %% @doc Starts the server %% @end %%----------------------------------------------------- -start() -> +start_link() -> ggs_network:start_link(). -start(Port) -> +start_link(Port) -> ggs_network:start_link(Port). From cb53cd6908fe8939e4f38dd991fee89c4932ec8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Fri, 4 Feb 2011 16:35:36 +0100 Subject: [PATCH 10/49] ggs_connection / connection modules do not exist, removing them from send calls --- src/ggs_network.erl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ggs_network.erl b/src/ggs_network.erl index 97e2568..be1b9d1 100644 --- a/src/ggs_network.erl +++ b/src/ggs_network.erl @@ -131,23 +131,23 @@ do_JSCall(Socket, Data, State) -> Ret = js_runner:call(JSVM, "userCommand", [list_to_binary(Command), list_to_binary(Parameter)]), - connection:send(Socket, "RefID", "JS says: ", Ret), + send(Socket, "RefID", "JS says: ", Ret), []; % Set the new state to the reference generated, and JSVM associated {hello} -> Client = getRef(), - connection:send(Socket, Client, "__ok_hello"), + send(Socket, Client, "__ok_hello"), {Client, JSVM}; {echo, RefID, _, MSG} -> - connection:send(Socket, RefID, "Your VM is ", getJSVM(RefID, State)), + send(Socket, RefID, "Your VM is ", getJSVM(RefID, State)), []; {crash, Zero} -> 10/Zero; {vms} -> - connection:send(Socket, "RefID", State); + send(Socket, "RefID", State); % Set the new state to [] Other -> - ggs_connection:send(Socket, "RefID", "__error"), + send(Socket, "RefID", "__error"), [] end, % Return the new state From 05d5b60a9f5501641173f25688c2b81ef8296b9f Mon Sep 17 00:00:00 2001 From: Kallfaktorn Date: Mon, 14 Feb 2011 15:36:53 +0100 Subject: [PATCH 11/49] merge with master. --- src/ggs_server.erl | 156 +++++++++++++++++++++++++++++++++++++++++++++ src/js_runner.erl | 33 ++++++++++ 2 files changed, 189 insertions(+) create mode 100644 src/ggs_server.erl create mode 100644 src/js_runner.erl diff --git a/src/ggs_server.erl b/src/ggs_server.erl new file mode 100644 index 0000000..aae268e --- /dev/null +++ b/src/ggs_server.erl @@ -0,0 +1,156 @@ +%%%---------------------------------------------------- +%%% @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, Payload}, State) -> + JSVM = getJSVM(Token, State), + %js_runner:define(JSVM, Payload), + JSVM!{define,self(),Payload}, + send(State#state.lsock, Token, "Okay, defined that for you!"), + {noreply, State}; + +% Handle javascript calls +handle_cast({call, Token, Payload}, State) -> + io:format("test1~n"), + io:format("Got call request: ~p~n", [Payload]), + io:format("test2~n"), + JSVM = getJSVM(Token, State), + JSVM!{get_port, self()}, + receive + {ok, Port} -> erlang:display(erlang:port_info(Port)), + io:format("test1~n") + end, + %erlang:display(erlang:port_info(Port)), + %{ok, Ret} = js_runner:call(JSVM, Payload, []), + JSVM!{call, self(), Payload, []}, + receive + {ok, Ret} -> + send(State#state.lsock, Token, "JS says:", binary_to_list(Ret)), + {noreply, State} + end; +% Set the new state to the reference generated, and JSVM associated +handle_cast({hello, _, _}, State) -> + JSVM = js_runner:boot(), + Client = getRef(), + send(State#state.lsock, Client, "This is your refID"), + OldMap = State#state.client_vm_map, + JSVM!{get_port, self()}, + receive + {ok, Port} -> NewState = State#state{client_vm_map = OldMap ++ [{Client, Port}]}, + gen_server:cast(ggs_backup, {set_backup, NewState}), + {noreply, NewState} + end. +%%----------------------------------------------------- +%% 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/js_runner.erl b/src/js_runner.erl new file mode 100644 index 0000000..65511e9 --- /dev/null +++ b/src/js_runner.erl @@ -0,0 +1,33 @@ +-module(js_runner). +-export([boot/0]). + +%Mattias +boot() -> + erlang_js:start(), + {ok, Port} = js_driver:new(), + PortPid = spawn(fun() -> port_process(Port) end ), + PortPid. + + +port_process(Port) -> +receive + {get_port, From} -> + From!{ok,Port}, + port_process(Port); + {define, From, Data} -> + ok = js:define(From, list_to_binary(Data)), + From!{ok}, + port_process(Port); + {call, From, Func, Params} -> + {ok,Ret} = js:call(From, list_to_binary(Func), Params), %Port unsure + From!{ok,Ret}, + port_process(Port) +end. + +%These two babies will be ambigiuous +%define(Port, Data) -> +% port_pid!{define,self(),Port,Data}. + + +%call(Port, Func, Params) -> +% port_pid!{call, self(), Port, Func, Params}. From 5d9a67b60c57adf2d10b7e02afcba31ffb202ed3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Mon, 14 Feb 2011 17:18:24 +0100 Subject: [PATCH 12/49] Protocol halfway ported --- erlang_js | 2 +- python_client | 8 ++--- src/ggs_protocol.erl | 80 +++++++++++++++++++++++++------------------- src/ggs_server.erl | 32 +++++++++--------- 4 files changed, 66 insertions(+), 56 deletions(-) diff --git a/erlang_js b/erlang_js index cbac148..5350ed2 160000 --- a/erlang_js +++ b/erlang_js @@ -1 +1 @@ -Subproject commit cbac148c440a93db44bad767a43c6d8619f6871f +Subproject commit 5350ed21606606dbee5ecb07e974f2abb9106270 diff --git a/python_client b/python_client index 4dd82ae..e707115 100755 --- a/python_client +++ b/python_client @@ -11,7 +11,7 @@ s.connect((HOST, PORT)) print "Saying hello to server" s.send( -"Command: hello\n\ +"Server-Command: hello\n\ Content-Type: text\n\ Content-Length: 0\n\ \n\ @@ -27,7 +27,7 @@ print "Data: ", ' '.join(data.split(" ")[1:]) print "Defining a function called myFun" s.send( "Token: %s\n\ -Command: define\n\ +Server-Command: define\n\ Content-Type: text\n\ Content-Length: 42\n\ \n\ @@ -42,7 +42,7 @@ print "Data: ", ' '.join(data.split(" ")[1:]) print "Calling myFun" s.send( "Token: %s\n\ -Command: call\n\ +Server-Command: call\n\ Content-Type: text\n\ Content-Length: 6\n\ \n\ @@ -63,7 +63,7 @@ s.connect((HOST, PORT)) print "Calling myFun" s.send( "Token: %s\n\ -Command: call\n\ +Server-Command: call\n\ Content-Type: text\n\ Content-Length: 6\n\ \n\ diff --git a/src/ggs_protocol.erl b/src/ggs_protocol.erl index ede5115..46c1ba1 100644 --- a/src/ggs_protocol.erl +++ b/src/ggs_protocol.erl @@ -2,38 +2,48 @@ -export([parse/1]). parse(Data) -> - Message =string:tokens(Data, "\n"), - % Turn "A: B" pairs into "{A, B}" tuples, for searching. - MsgKV = lists:map((fun(Str) -> - list_to_tuple(string:tokens(Str, ": ")) end - ), Message), - % Hacky way to build a tuple, filter out not_found later on - Processed = { - case lists:keysearch("Command", 1, MsgKV) of - {value,{_, "define"}} -> - define; - {value,{_, "call"}} -> - call; - {value,{_, "hello"}} -> - hello; - false -> - not_found - end, - case lists:keysearch("Token", 1, MsgKV) of - {value,{_, Value}} -> - Value; - false -> - not_found - end, - case lists:keysearch("Content-Length", 1, MsgKV) of - {value,{_, Value}} -> - {Length, _} = string:to_integer(Value), - [_|Cont] = re:split(Data, "\n\n",[{return,list}]), - Content = string:join(Cont, "\n\n"), - Payload = string:substr(Content,1,Length), - Payload; - false -> - not_found - end - }, - gen_server:cast(ggs_server, Processed). + 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/ggs_server.erl b/src/ggs_server.erl index 68b1625..4a116fa 100644 --- a/src/ggs_server.erl +++ b/src/ggs_server.erl @@ -95,30 +95,30 @@ handle_cast(stop, State) -> {stop, normal, State}; % Handle javascript defines -handle_cast({define, Token, Payload}, State) -> - JSVM = getJSVM(Token, State), - js_runner:define(JSVM, Payload), - send(State#state.lsock, Token, "Okay, defined that for you!"), +handle_cast({srv_cmd, "define", Args, Data}, State) -> + %JSVM = getJSVM(Token, State), + %js_runner:define(JSVM, Payload), + send(State#state.lsock, "Token", "Okay, defined that for you!"), {noreply, State}; % Handle javascript calls -handle_cast({call, Token, Payload}, State) -> - io:format("Got call request: ~p~n", [Payload]), - JSVM = getJSVM(Token, State), - erlang:display(erlang:port_info(JSVM)), - {ok, Ret} = js_runner:call(JSVM, Payload, []),%Payload, []), - send(State#state.lsock, Token, "JS says:", binary_to_list(Ret)), +handle_cast({srv_cmd, "call", Args, Data}, State) -> + %io:format("Got call request: ~p~n", [Payload]), + %JSVM = getJSVM(Token, State), + %erlang:display(erlang:port_info(JSVM)), + %{ok, Ret} = js_runner:call(JSVM, Payload, []),%Payload, []), + %send(State#state.lsock, Token, "JS says:", binary_to_list(Ret)), {noreply, State}; % Set the new state to the reference generated, and JSVM associated -handle_cast({hello, _, _}, State) -> - JSVM = js_runner:boot(), +handle_cast({srv_cmd, "hello", Headers, Data}, State) -> + %JSVM = js_runner:boot(), 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, JSVM}]}, - gen_server:cast(ggs_backup, {set_backup, NewState}), - {noreply, NewState}. + %OldMap = State#state.client_vm_map, + %NewState = State#state{client_vm_map = OldMap ++ [{Client, JSVM}]}, + %gen_server:cast(ggs_backup, {set_backup, NewState}), + {noreply, State}. %NewState %%----------------------------------------------------- %% Helpers %%----------------------------------------------------- From 973f2fcf980311e58049a0ead4f6a4064b98a712 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Mon, 14 Feb 2011 17:18:24 +0100 Subject: [PATCH 13/49] Protocol halfway ported --- erlang_js | 2 +- python_client | 8 ++--- src/ggs_protocol.erl | 80 +++++++++++++++++++++++++------------------- src/ggs_server.erl | 32 +++++++++--------- 4 files changed, 66 insertions(+), 56 deletions(-) diff --git a/erlang_js b/erlang_js index cbac148..5350ed2 160000 --- a/erlang_js +++ b/erlang_js @@ -1 +1 @@ -Subproject commit cbac148c440a93db44bad767a43c6d8619f6871f +Subproject commit 5350ed21606606dbee5ecb07e974f2abb9106270 diff --git a/python_client b/python_client index 4dd82ae..e707115 100755 --- a/python_client +++ b/python_client @@ -11,7 +11,7 @@ s.connect((HOST, PORT)) print "Saying hello to server" s.send( -"Command: hello\n\ +"Server-Command: hello\n\ Content-Type: text\n\ Content-Length: 0\n\ \n\ @@ -27,7 +27,7 @@ print "Data: ", ' '.join(data.split(" ")[1:]) print "Defining a function called myFun" s.send( "Token: %s\n\ -Command: define\n\ +Server-Command: define\n\ Content-Type: text\n\ Content-Length: 42\n\ \n\ @@ -42,7 +42,7 @@ print "Data: ", ' '.join(data.split(" ")[1:]) print "Calling myFun" s.send( "Token: %s\n\ -Command: call\n\ +Server-Command: call\n\ Content-Type: text\n\ Content-Length: 6\n\ \n\ @@ -63,7 +63,7 @@ s.connect((HOST, PORT)) print "Calling myFun" s.send( "Token: %s\n\ -Command: call\n\ +Server-Command: call\n\ Content-Type: text\n\ Content-Length: 6\n\ \n\ diff --git a/src/ggs_protocol.erl b/src/ggs_protocol.erl index ede5115..46c1ba1 100644 --- a/src/ggs_protocol.erl +++ b/src/ggs_protocol.erl @@ -2,38 +2,48 @@ -export([parse/1]). parse(Data) -> - Message =string:tokens(Data, "\n"), - % Turn "A: B" pairs into "{A, B}" tuples, for searching. - MsgKV = lists:map((fun(Str) -> - list_to_tuple(string:tokens(Str, ": ")) end - ), Message), - % Hacky way to build a tuple, filter out not_found later on - Processed = { - case lists:keysearch("Command", 1, MsgKV) of - {value,{_, "define"}} -> - define; - {value,{_, "call"}} -> - call; - {value,{_, "hello"}} -> - hello; - false -> - not_found - end, - case lists:keysearch("Token", 1, MsgKV) of - {value,{_, Value}} -> - Value; - false -> - not_found - end, - case lists:keysearch("Content-Length", 1, MsgKV) of - {value,{_, Value}} -> - {Length, _} = string:to_integer(Value), - [_|Cont] = re:split(Data, "\n\n",[{return,list}]), - Content = string:join(Cont, "\n\n"), - Payload = string:substr(Content,1,Length), - Payload; - false -> - not_found - end - }, - gen_server:cast(ggs_server, Processed). + 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/ggs_server.erl b/src/ggs_server.erl index 68b1625..4a116fa 100644 --- a/src/ggs_server.erl +++ b/src/ggs_server.erl @@ -95,30 +95,30 @@ handle_cast(stop, State) -> {stop, normal, State}; % Handle javascript defines -handle_cast({define, Token, Payload}, State) -> - JSVM = getJSVM(Token, State), - js_runner:define(JSVM, Payload), - send(State#state.lsock, Token, "Okay, defined that for you!"), +handle_cast({srv_cmd, "define", Args, Data}, State) -> + %JSVM = getJSVM(Token, State), + %js_runner:define(JSVM, Payload), + send(State#state.lsock, "Token", "Okay, defined that for you!"), {noreply, State}; % Handle javascript calls -handle_cast({call, Token, Payload}, State) -> - io:format("Got call request: ~p~n", [Payload]), - JSVM = getJSVM(Token, State), - erlang:display(erlang:port_info(JSVM)), - {ok, Ret} = js_runner:call(JSVM, Payload, []),%Payload, []), - send(State#state.lsock, Token, "JS says:", binary_to_list(Ret)), +handle_cast({srv_cmd, "call", Args, Data}, State) -> + %io:format("Got call request: ~p~n", [Payload]), + %JSVM = getJSVM(Token, State), + %erlang:display(erlang:port_info(JSVM)), + %{ok, Ret} = js_runner:call(JSVM, Payload, []),%Payload, []), + %send(State#state.lsock, Token, "JS says:", binary_to_list(Ret)), {noreply, State}; % Set the new state to the reference generated, and JSVM associated -handle_cast({hello, _, _}, State) -> - JSVM = js_runner:boot(), +handle_cast({srv_cmd, "hello", Headers, Data}, State) -> + %JSVM = js_runner:boot(), 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, JSVM}]}, - gen_server:cast(ggs_backup, {set_backup, NewState}), - {noreply, NewState}. + %OldMap = State#state.client_vm_map, + %NewState = State#state{client_vm_map = OldMap ++ [{Client, JSVM}]}, + %gen_server:cast(ggs_backup, {set_backup, NewState}), + {noreply, State}. %NewState %%----------------------------------------------------- %% Helpers %%----------------------------------------------------- From 1e08fe0015b936fdecfaceb4177e628d2d25b275 Mon Sep 17 00:00:00 2001 From: Kallfaktorn Date: Mon, 14 Feb 2011 17:50:22 +0100 Subject: [PATCH 14/49] Interface modifications. Methods for vm handling. --- src/ggs_server.erl | 43 ++++++++++++++----------------------------- src/ggs_vm_runner.erl | 28 ++++++++++++++++++++++++++++ src/js_runner.erl | 33 --------------------------------- 3 files changed, 42 insertions(+), 62 deletions(-) create mode 100644 src/ggs_vm_runner.erl delete mode 100644 src/js_runner.erl diff --git a/src/ggs_server.erl b/src/ggs_server.erl index aae268e..34d297f 100644 --- a/src/ggs_server.erl +++ b/src/ggs_server.erl @@ -95,44 +95,29 @@ handle_cast(stop, State) -> {stop, normal, State}; % Handle javascript defines -handle_cast({define, Token, Payload}, State) -> - JSVM = getJSVM(Token, State), - %js_runner:define(JSVM, Payload), - JSVM!{define,self(),Payload}, +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, Payload}, State) -> - io:format("test1~n"), - io:format("Got call request: ~p~n", [Payload]), - io:format("test2~n"), - JSVM = getJSVM(Token, State), - JSVM!{get_port, self()}, - receive - {ok, Port} -> erlang:display(erlang:port_info(Port)), - io:format("test1~n") - end, - %erlang:display(erlang:port_info(Port)), - %{ok, Ret} = js_runner:call(JSVM, Payload, []), - JSVM!{call, self(), Payload, []}, - receive - {ok, Ret} -> - send(State#state.lsock, Token, "JS says:", binary_to_list(Ret)), - {noreply, State} - end; +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) -> - JSVM = js_runner:boot(), + GameVM = ggs_vm_runner:start_link(), Client = getRef(), send(State#state.lsock, Client, "This is your refID"), OldMap = State#state.client_vm_map, - JSVM!{get_port, self()}, - receive - {ok, Port} -> NewState = State#state{client_vm_map = OldMap ++ [{Client, Port}]}, - gen_server:cast(ggs_backup, {set_backup, NewState}), - {noreply, NewState} - end. + NewState = State#state{client_vm_map = OldMap ++ [{Client, GameVM}]}, + gen_server:cast(ggs_backup, {set_backup, NewState}), + {noreply, NewState}. + %%----------------------------------------------------- %% Helpers %%----------------------------------------------------- diff --git a/src/ggs_vm_runner.erl b/src/ggs_vm_runner.erl new file mode 100644 index 0000000..cf633f0 --- /dev/null +++ b/src/ggs_vm_runner.erl @@ -0,0 +1,28 @@ +-module(ggs_vm_runner). +-export([start_link/0, define/2, user_command/4]). + +%Mattias +start_link() -> + erlang_js:start(), + {ok, Port} = js_driver:new(), + js:define(Port, <<"function userCommand(user, command, args){}">>), + PortPid = spawn_link(fun() -> loop(Port) end ), + PortPid. + + +loop(Port) -> +receive + {define, SourceCode} -> + ok = js:define(Port, list_to_binary(SourceCode)), + loop(Port); + {user_command, User, Command, Args} -> + {ok, Ret} = js:call(Port, <<"userCommand">>, list_to_binary([User,Command,Args])), + loop(Port) +end. + + +define(GameVM, SourceCode) -> + GameVM ! {define,SourceCode}. + +user_command(GameVM, User, Command, Args) -> + GameVM ! {user_command, User, Command, Args}. diff --git a/src/js_runner.erl b/src/js_runner.erl deleted file mode 100644 index 65511e9..0000000 --- a/src/js_runner.erl +++ /dev/null @@ -1,33 +0,0 @@ --module(js_runner). --export([boot/0]). - -%Mattias -boot() -> - erlang_js:start(), - {ok, Port} = js_driver:new(), - PortPid = spawn(fun() -> port_process(Port) end ), - PortPid. - - -port_process(Port) -> -receive - {get_port, From} -> - From!{ok,Port}, - port_process(Port); - {define, From, Data} -> - ok = js:define(From, list_to_binary(Data)), - From!{ok}, - port_process(Port); - {call, From, Func, Params} -> - {ok,Ret} = js:call(From, list_to_binary(Func), Params), %Port unsure - From!{ok,Ret}, - port_process(Port) -end. - -%These two babies will be ambigiuous -%define(Port, Data) -> -% port_pid!{define,self(),Port,Data}. - - -%call(Port, Func, Params) -> -% port_pid!{call, self(), Port, Func, Params}. From 76148b39d0b783c58f5fddf32190c0b2935dc7aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Wed, 16 Feb 2011 15:08:37 +0100 Subject: [PATCH 15/49] Started new structure --- src/ggs_coordinator.erl | 0 src/ggs_dispatcher.erl | 0 src/ggs_gamevm.erl | 0 src/ggs_player.erl | 0 src/ggs_table.erl | 0 src/{ => old}/ggs_app.erl | 0 src/{ => old}/ggs_backup.erl | 0 src/{ => old}/ggs_mnesia_controller_server.erl | 0 src/{ => old}/ggs_protocol.erl | 0 src/{ => old}/ggs_server.erl | 0 src/{ => old}/ggs_server_sup.erl | 0 src/{ => old}/ggs_sup.erl | 0 src/{ => old}/js_runner.erl | 0 src/{ => old}/start_ggs.erl | 0 14 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/ggs_coordinator.erl create mode 100644 src/ggs_dispatcher.erl create mode 100644 src/ggs_gamevm.erl create mode 100644 src/ggs_player.erl create mode 100644 src/ggs_table.erl rename src/{ => old}/ggs_app.erl (100%) rename src/{ => old}/ggs_backup.erl (100%) rename src/{ => old}/ggs_mnesia_controller_server.erl (100%) rename src/{ => old}/ggs_protocol.erl (100%) rename src/{ => old}/ggs_server.erl (100%) rename src/{ => old}/ggs_server_sup.erl (100%) rename src/{ => old}/ggs_sup.erl (100%) rename src/{ => old}/js_runner.erl (100%) rename src/{ => old}/start_ggs.erl (100%) diff --git a/src/ggs_coordinator.erl b/src/ggs_coordinator.erl new file mode 100644 index 0000000..e69de29 diff --git a/src/ggs_dispatcher.erl b/src/ggs_dispatcher.erl new file mode 100644 index 0000000..e69de29 diff --git a/src/ggs_gamevm.erl b/src/ggs_gamevm.erl new file mode 100644 index 0000000..e69de29 diff --git a/src/ggs_player.erl b/src/ggs_player.erl new file mode 100644 index 0000000..e69de29 diff --git a/src/ggs_table.erl b/src/ggs_table.erl new file mode 100644 index 0000000..e69de29 diff --git a/src/ggs_app.erl b/src/old/ggs_app.erl similarity index 100% rename from src/ggs_app.erl rename to src/old/ggs_app.erl diff --git a/src/ggs_backup.erl b/src/old/ggs_backup.erl similarity index 100% rename from src/ggs_backup.erl rename to src/old/ggs_backup.erl diff --git a/src/ggs_mnesia_controller_server.erl b/src/old/ggs_mnesia_controller_server.erl similarity index 100% rename from src/ggs_mnesia_controller_server.erl rename to src/old/ggs_mnesia_controller_server.erl diff --git a/src/ggs_protocol.erl b/src/old/ggs_protocol.erl similarity index 100% rename from src/ggs_protocol.erl rename to src/old/ggs_protocol.erl diff --git a/src/ggs_server.erl b/src/old/ggs_server.erl similarity index 100% rename from src/ggs_server.erl rename to src/old/ggs_server.erl diff --git a/src/ggs_server_sup.erl b/src/old/ggs_server_sup.erl similarity index 100% rename from src/ggs_server_sup.erl rename to src/old/ggs_server_sup.erl diff --git a/src/ggs_sup.erl b/src/old/ggs_sup.erl similarity index 100% rename from src/ggs_sup.erl rename to src/old/ggs_sup.erl diff --git a/src/js_runner.erl b/src/old/js_runner.erl similarity index 100% rename from src/js_runner.erl rename to src/old/js_runner.erl diff --git a/src/start_ggs.erl b/src/old/start_ggs.erl similarity index 100% rename from src/start_ggs.erl rename to src/old/start_ggs.erl From ac63eb124bfd255d7d85a420e5247228417f4148 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Wed, 16 Feb 2011 15:48:55 +0100 Subject: [PATCH 16/49] Added specification and documentation for the dispatcher --- src/ggs_dispatcher.erl | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/ggs_dispatcher.erl b/src/ggs_dispatcher.erl index e69de29..8f89ceb 100644 --- a/src/ggs_dispatcher.erl +++ b/src/ggs_dispatcher.erl @@ -0,0 +1,21 @@ +-module(ggs_dispatcher). +-export([start_link/1, stop/1]). + +%% @doc This module is the entry-point for clients connecting to GGS. This is +%% the module responsible for: +%% * Greeting a connecting client, and associating a socket for it +%% * Spawning a ggs_player for the connecting client, passing the socket + +%% @doc Starts a new dispatcher with the specified port. Registers this +%% dispatcher under the name "ggs_dispatcher". The pid of the dispatcher +%% is returned. +%% @spec start_link(Port) -> Pid +%% Port = Integer +%% Pid = # +start_link(Port) -> + not_implemented. + +%% @doc Stops the dispatcher with the specified reason. +%% @spec stop(Reason) -> ok. +%% Reason = String +stop(Reason) -> not_implemented. From e4bdc05bc816f4b314544f0a8a0baea9631e4cf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Wed, 16 Feb 2011 16:05:48 +0100 Subject: [PATCH 17/49] Added documentation for ggs_gamevm.erl --- src/ggs_gamevm.erl | 50 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/ggs_gamevm.erl b/src/ggs_gamevm.erl index e69de29..8116a96 100644 --- a/src/ggs_gamevm.erl +++ b/src/ggs_gamevm.erl @@ -0,0 +1,50 @@ +-module(ggs_vm_runner). +-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. + +%% @doc Create a new VM process. The process ID is returned and can be used +%% with for example the define method of this module. +start_link() -> + erlang_js:start(), %% @TODO: should only be done once + PortPid = spawn_link( fun() -> + process_flag(trap_exit, true), + {ok, Port} = js_driver:new(), + js:define(Port, <<"function userCommand(user, command, args){return 'Hello world';}">>), + loop(Port) + end ), + PortPid. + +%% @doc Define some new code on the specified VM, returns the atom ok. +define(GameVM, SourceCode) -> + GameVM ! {define,SourceCode}, + ok. + +%% @doc Execute a user command on the specified VM. This function is +%% asynchronous, and returns ok. +%% @spec user_command(GameVM, User, Command, Args) -> ok +%% GameVM = process IS of VM +%% Player = the player running the command +%% Command = a game command to run +%% Args = arguments for the Command parameter +user_command(GameVM, Player, Command, Args) -> + Ref = make_ref(), + GameVM ! {user_command, Player, Command, Args, self(), Ref}, + ok. + +%% Helper functions + +loop(Port) -> + receive + {define, SourceCode} -> + ok = js:define(Port, list_to_binary(SourceCode)), + loop(Port); + {user_command, User, Command, Args, From, Ref} -> + {ok, Ret} = js:call(Port, <<"userCommand">>, + [ list_to_binary(User), + list_to_binary(Command), + list_to_binary(Args) + ]), + From ! {Ref, Ret}, + loop(Port) + end. From ae1856e1f2a96381f77425ee03a6545bd314e93a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Wed, 16 Feb 2011 16:50:57 +0100 Subject: [PATCH 18/49] Added supervisor structure --- src/ggs_app.erl | 14 ++++++++++++++ src/ggs_sup.erl | 41 +++++++++++++++++++++++++++++++++++++++++ src/start_ggs.erl | 7 +++++++ 3 files changed, 62 insertions(+) create mode 100644 src/ggs_app.erl create mode 100644 src/ggs_sup.erl create mode 100644 src/start_ggs.erl diff --git a/src/ggs_app.erl b/src/ggs_app.erl new file mode 100644 index 0000000..d8b2e60 --- /dev/null +++ b/src/ggs_app.erl @@ -0,0 +1,14 @@ +-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/ggs_sup.erl b/src/ggs_sup.erl new file mode 100644 index 0000000..bfb2617 --- /dev/null +++ b/src/ggs_sup.erl @@ -0,0 +1,41 @@ +-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]) -> + Dispatcher = {ggs_dispatcher, + {ggs_dispatcher, start_link, [Port]}, + permanent, + 2000, + worker, + [ggs_dispatcher] + }, + Coordinator = {ggs_coordinator, + {ggs_coordinator, start_link, []}, + permanent, + 2000, + worker, + [ggs_dispatcher] + }, + Children = [Dispatcher, Coordinator], + + 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/start_ggs.erl b/src/start_ggs.erl new file mode 100644 index 0000000..3955715 --- /dev/null +++ b/src/start_ggs.erl @@ -0,0 +1,7 @@ +-module(start_ggs). +-export([start/0]). + +start() -> + application:start(inets), + application:start(erlang_js), + application:start(ggs). From 3b94f5da2447f14119f4004a0fd15f590822cac9 Mon Sep 17 00:00:00 2001 From: Kallfaktorn Date: Wed, 16 Feb 2011 17:11:27 +0100 Subject: [PATCH 19/49] Added edoc to player. --- src/ggs_player.erl | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/ggs_player.erl b/src/ggs_player.erl index e69de29..bdfcf7d 100644 --- a/src/ggs_player.erl +++ b/src/ggs_player.erl @@ -0,0 +1,22 @@ + + + +%% @spec start_link(GameToken::string()) -> socket() +%% @doc Spawn a new player process. +start_link(Socket) -> end. + + +%% @spec notify(Player::Pid(), From::Pid(), +%% {Command::String(), Message::string()}) -> ok +%% @doc send a message to a player. +notify(Player, From, Message) -> end. + + +%% @spec get_token() -> string() +%% @doc Get the player token. +get_token() -> end. + + +%% @spec stop(Table::pid()) -> Reason::string() +%% @doc Properly terminates the process. +stop(Table) -> end. From e09b3cbd143facecb87714029fb31c6972c4b453 Mon Sep 17 00:00:00 2001 From: Kallfaktorn Date: Wed, 16 Feb 2011 17:28:55 +0100 Subject: [PATCH 20/49] Refined ggs_player. --- src/ggs_player.erl | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/ggs_player.erl b/src/ggs_player.erl index bdfcf7d..4a24ef4 100644 --- a/src/ggs_player.erl +++ b/src/ggs_player.erl @@ -1,22 +1,26 @@ +-module(ggs_player). +-export([start_link/1, notify/3, get_token/1, stop/1]). +%% @doc This module handles communication between a player and GGS. This module is +%%responsible for: +%% * the storage of the player socket, player token and a table token. - -%% @spec start_link(GameToken::string()) -> socket() -%% @doc Spawn a new player process. -start_link(Socket) -> end. +%% @doc Spawns a new player process. +%% @spec start_link(Socket::socket()) -> ok +start_link(Socket) -> not_implemented. %% @spec notify(Player::Pid(), From::Pid(), %% {Command::String(), Message::string()}) -> ok %% @doc send a message to a player. -notify(Player, From, Message) -> end. +notify(Player, From, Message) -> not_implemented. %% @spec get_token() -> string() %% @doc Get the player token. -get_token() -> end. +get_token() -> not_implemented. %% @spec stop(Table::pid()) -> Reason::string() %% @doc Properly terminates the process. -stop(Table) -> end. +stop(Table) -> not_implemented. From c42bd46c44c211eee59a325a7d9bcf798bd324c0 Mon Sep 17 00:00:00 2001 From: niklas Date: Wed, 16 Feb 2011 16:56:06 +0100 Subject: [PATCH 21/49] Initial interface --- src/ggs_coordinator.erl | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/ggs_coordinator.erl b/src/ggs_coordinator.erl index e69de29..ed9c4e3 100644 --- a/src/ggs_coordinator.erl +++ b/src/ggs_coordinator.erl @@ -0,0 +1,38 @@ +-module(ggs_coordinator). +-export(). + +%% @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. + +%% @doc Terminates the coordinator process. +stop() -> + not_implemented. + +%% @doc Creates a unique token for the table. +join_table() -> + not_implemented. + +%% @doc +create_table() -> + not_implemented. + +%% @doc This is the first function run by a newly created players. +%% Generates a unique token that we use to identify the player. +join_lobby() -> + not_implemented. + +%% @doc Act as a supervisor to player and respawns player when it gets bad data. +respawn_player(Player, Socket) -> + not_implemented. + +%% @doc Act as a supervisor to table and respawns table when it gets bad data. +respawn_table() -> + not_implemented. + +%% @doc Removes a player from coordinator. +remove_player(From, Player) -> + not_implemented. From c23e79de240b0c20d85f6a30188f96a4793c147f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Wed, 16 Feb 2011 17:05:22 +0100 Subject: [PATCH 22/49] Updated ggs_dispatcher with gen_server functionality --- src/ggs_dispatcher.erl | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/ggs_dispatcher.erl b/src/ggs_dispatcher.erl index 8f89ceb..bc3327a 100644 --- a/src/ggs_dispatcher.erl +++ b/src/ggs_dispatcher.erl @@ -1,6 +1,13 @@ -module(ggs_dispatcher). + +%% API Exports -export([start_link/1, stop/1]). +%% gen_server callback exports +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, + code_change/3]). + + %% @doc This module is the entry-point for clients connecting to GGS. This is %% the module responsible for: %% * Greeting a connecting client, and associating a socket for it @@ -19,3 +26,22 @@ start_link(Port) -> %% @spec stop(Reason) -> ok. %% Reason = String stop(Reason) -> not_implemented. + + +%% gen_server callbacks + +%% @doc Initiate the dispatcher. This is called from gen_server +init([Port]) -> + {ok, ok}. + +handle_call(_Message, _From, State) -> + {noreply, State}. + +handle_cast(_Message, State) -> + {noreply, State}. + +terminate(normal, _State) -> + ok. + +code_change(_OldVsn, State, Extra) -> + {ok, State}. From 702a887117cf9c1992b2d4b6997ee1e28a2d6065 Mon Sep 17 00:00:00 2001 From: Kallfaktorn Date: Wed, 16 Feb 2011 18:03:48 +0100 Subject: [PATCH 23/49] Completed edoc of player. --- src/ggs_player.erl | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/ggs_player.erl b/src/ggs_player.erl index 4a24ef4..b5815af 100644 --- a/src/ggs_player.erl +++ b/src/ggs_player.erl @@ -3,24 +3,30 @@ %% @doc This module handles communication between a player and GGS. This module is %%responsible for: -%% * the storage of the player socket, player token and a table token. +%% * The storage of the player socket, player token and a table token. +%% * Ability to fetch a player token. +%% * Forwarding messages from players to the game +%% * Remove a player from GGS -%% @doc Spawns a new player process. +%% @doc Spawns a process representing the player in GGS. Takes the player socket as +%% 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. +%% @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 -%% @doc send a message to a player. notify(Player, From, Message) -> not_implemented. - +%% @doc Get the player token uniquely representing the player. %% @spec get_token() -> string() -%% @doc Get the player token. get_token() -> 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() -%% @doc Properly terminates the process. stop(Table) -> not_implemented. From a801008cd9438971db21a54d1b5b910e34716733 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Wed, 16 Feb 2011 17:11:51 +0100 Subject: [PATCH 24/49] Initial interface --- src/ggs_network.erl | 170 ------------------------------------------ src/ggs_table.erl | 36 +++++++++ src/ggs_vm_runner.erl | 28 ------- 3 files changed, 36 insertions(+), 198 deletions(-) delete mode 100644 src/ggs_network.erl delete mode 100644 src/ggs_vm_runner.erl diff --git a/src/ggs_network.erl b/src/ggs_network.erl deleted file mode 100644 index be1b9d1..0000000 --- a/src/ggs_network.erl +++ /dev/null @@ -1,170 +0,0 @@ -%%%---------------------------------------------------- -%%% @author Jonatan Pålsson -%%% @copyright 2010 Jonatan Pålsson -%%% @doc RPC over TCP server -%%% @end -%%%---------------------------------------------------- -%%% @author Mattias Pettersson -%%% @doc Socket module for GGS -%%% @end -%%%---------------------------------------------------- - - --module(ggs_network). - --behaviour(gen_server). - -%define --define(SERVER, ?MODULE). --define(DEFAULT_PORT, 1055). - - -% export --export([start_link/0,start_link/1]). --export([init/1, handle_call/3, handle_cast/2, handle_info/2]). -%-export([get_count/1,crash/0,vms/0,hello/0,echo/0]). --export([get_count/1]). --export([send/3, send/4]). --export([stop/0]). - -%% gen_server callbacks --export([terminate/2, code_change/3]). - -%state --record(state, {port, lsock, client_vm_map = []}). - - -%%----------------------------------------------------- -%% @doc Starts gen_server -%% @end -%%----------------------------------------------------- -start_link() -> - start_link(?DEFAULT_PORT). - -start_link(Port) -> - process_flag(trap_exit, true), - gen_server:start_link({local, ?SERVER}, ?MODULE, [Port], []). - -%%----------------------------------------------------- -%% Creation -%%----------------------------------------------------- -init([Port]) -> - {ok, LSock} = gen_tcp:listen(Port, [{active, true}, - {reuseaddr, true}]), - {ok, #state{port = Port, lsock = LSock}, 0}. - -%%----------------------------------------------------- -%% @doc Fetches the number of requests made to this server -%% @spec get_count() -> {ok, Count} -%% where -%% Count = integer() -%% @end -%%----------------------------------------------------- -get_count(get_count) -> - gen_server:call(?SERVER, get_count). - -%crash() -> gen_server:call(?SERVER, crash). -%vms() -> gen_server:call(?SERVER, vms). -%hello() -> gen_server:call(?SERVER, hello). -%echo() -> gen_server:call(?SERVER, {echo, RefID, _, MSG}). - - - - -%%----------------------------------------------------- -%% @doc Stops the server. -%% @spec stop() -> ok -%% @end -%%----------------------------------------------------- -stop() -> - gen_server:cast(?SERVER, stop). - -%%----------------------------------------------------- -%% Handlers -%%----------------------------------------------------- -handle_call(get_count, _From, State) -> - {reply, {ok, State#state.client_vm_map}, State}. - -handle_cast(stop, State) -> - {stop, normal, State}. - -handle_info({tcp, Socket, RawData}, State) -> %parameters coming from gen_server - NewState = do_JSCall(Socket, RawData, State), %TODO - OldMap = State#state.client_vm_map, - io:format("Old map: ~p NewState: ~p~n", [OldMap, NewState]), - {noreply, State#state{client_vm_map = OldMap ++ [NewState]}}; - -handle_info(timeout, #state{lsock = LSock} = State) -> - {ok, _Sock} = gen_tcp:accept(LSock), - {noreply, State}. - - -%%----------------------------------------------------- -%% TCP Calls -%%----------------------------------------------------- -send(Socket, RefID, String) -> - gen_tcp:send(Socket, io_lib:fwrite("~p ~p~n", [RefID,String])). - -send(Socket, RefID, String1, String2) -> - gen_tcp:send(Socket, io_lib:fwrite("~p ~p ~p~n", [RefID, String1, String2])). - - -%%----------------------------------------------------- -%% gen_server callbacks -%%----------------------------------------------------- -terminate(_Reason, _State) -> - ok. - -code_change(_OldVsn, State, _Extra) -> - {ok, State}. - -%%----------------------------------------------------- -%% Internal functions -%%----------------------------------------------------- -do_JSCall(Socket, Data, State) -> - JSVM = js_runner:boot(), - js_runner:define(JSVM, "function userCommand(cmd, par) {return cmd+' '+ par}"), - Parsed = ggs_protocol:parse(Data), - NewState = case Parsed of - {cmd, Command, Parameter} -> - % Set the new state to [] - Ret = js_runner:call(JSVM, "userCommand", - [list_to_binary(Command), - list_to_binary(Parameter)]), - send(Socket, "RefID", "JS says: ", Ret), - []; - % Set the new state to the reference generated, and JSVM associated - {hello} -> - Client = getRef(), - send(Socket, Client, "__ok_hello"), - {Client, JSVM}; - {echo, RefID, _, MSG} -> - send(Socket, RefID, "Your VM is ", getJSVM(RefID, State)), - []; - {crash, Zero} -> - 10/Zero; - {vms} -> - send(Socket, "RefID", State); - % Set the new state to [] - Other -> - send(Socket, "RefID", "__error"), - [] - end, - % Return the new state - NewState. - -%%----------------------------------------------------- -%% Helpers -%%----------------------------------------------------- -getRef() -> - {A1,A2,A3} = now(), - random:seed(A1, A2, A3), - random:uniform(1000). - -%%----------------------------------------------------- -%% Helpers -%%----------------------------------------------------- -getJSVM(RefID, State) -> - VMs = State#state.client_vm_map, - {value, {_,VM}} = lists:keysearch(RefID, 1, VMs), - VM. diff --git a/src/ggs_table.erl b/src/ggs_table.erl index e69de29..87a623a 100644 --- a/src/ggs_table.erl +++ b/src/ggs_table.erl @@ -0,0 +1,36 @@ +%% @doc This module represents a Player with a Socket and a Token + +-module(ggs_table). +-export([ + start_link/1, + add_player/2, + remove_player/2, + stop/2, + notify/3 +]). + +% @doc returns a new table +start_link(Token) -> + not_implemented(). + +% @doc adds a player to a table +add_player(Table, Player) -> + not_implemented(). + +% @doc removes player form a table +remove_player(Table, Player) -> + not_implemented(). + +% @doc stops the table process +stop(Table) -> + not_implemented(). + +% @doc notifies the table with a message from a player +notify(Table, Player, Message) -> + not_implemented(). + + +% loop + + +% private helpers \ No newline at end of file diff --git a/src/ggs_vm_runner.erl b/src/ggs_vm_runner.erl deleted file mode 100644 index cf633f0..0000000 --- a/src/ggs_vm_runner.erl +++ /dev/null @@ -1,28 +0,0 @@ --module(ggs_vm_runner). --export([start_link/0, define/2, user_command/4]). - -%Mattias -start_link() -> - erlang_js:start(), - {ok, Port} = js_driver:new(), - js:define(Port, <<"function userCommand(user, command, args){}">>), - PortPid = spawn_link(fun() -> loop(Port) end ), - PortPid. - - -loop(Port) -> -receive - {define, SourceCode} -> - ok = js:define(Port, list_to_binary(SourceCode)), - loop(Port); - {user_command, User, Command, Args} -> - {ok, Ret} = js:call(Port, <<"userCommand">>, list_to_binary([User,Command,Args])), - loop(Port) -end. - - -define(GameVM, SourceCode) -> - GameVM ! {define,SourceCode}. - -user_command(GameVM, User, Command, Args) -> - GameVM ! {user_command, User, Command, Args}. From 4927d47065cac9d6fa19c2c5b8f99f2699c79a92 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Wed, 16 Feb 2011 17:17:03 +0100 Subject: [PATCH 25/49] renamed test to unit_tests --- {tests => unit_tests}/ggs_protocol_test.erl | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {tests => unit_tests}/ggs_protocol_test.erl (100%) diff --git a/tests/ggs_protocol_test.erl b/unit_tests/ggs_protocol_test.erl similarity index 100% rename from tests/ggs_protocol_test.erl rename to unit_tests/ggs_protocol_test.erl From db7c99adb17d4af875b8f96d27648748e5c33bc6 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Wed, 16 Feb 2011 17:17:56 +0100 Subject: [PATCH 26/49] removed unnecessary files --- unit_tests/ggs_protocol_test.erl | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 unit_tests/ggs_protocol_test.erl diff --git a/unit_tests/ggs_protocol_test.erl b/unit_tests/ggs_protocol_test.erl deleted file mode 100644 index 2230cbf..0000000 --- a/unit_tests/ggs_protocol_test.erl +++ /dev/null @@ -1,6 +0,0 @@ --module(ggs_protocol_test). --export([test_parse/0]). - -test_parse() -> - Ret = ggs_protocol:parse("<> __define JavaScript"), - io:format("~p~n", [Ret]). From 5d71202a00b70664616ee6650a51f790473ffa9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Wed, 16 Feb 2011 17:19:00 +0100 Subject: [PATCH 27/49] Added OTP structure to ggs_coordinator --- src/ggs_coordinator.erl | 39 +++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/src/ggs_coordinator.erl b/src/ggs_coordinator.erl index ed9c4e3..4f38c6a 100644 --- a/src/ggs_coordinator.erl +++ b/src/ggs_coordinator.erl @@ -1,5 +1,11 @@ -module(ggs_coordinator). --export(). + +%% API Exports +-export([start_link/1, stop/1]). + +%% gen_server callback exports +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, + code_change/3]). %% @doc This module act as "the man in the middle". %% Creates the starting connection between table and players. @@ -9,15 +15,15 @@ start_link() -> not_implemented. %% @doc Terminates the coordinator process. -stop() -> +stop(_Reason) -> not_implemented. -%% @doc Creates a unique token for the table. -join_table() -> +%% @doc Joins table with specified token +join_table(_Token) -> not_implemented. -%% @doc -create_table() -> +%% @doc Create a new table +create_table(_Params) -> not_implemented. %% @doc This is the first function run by a newly created players. @@ -26,13 +32,30 @@ join_lobby() -> not_implemented. %% @doc Act as a supervisor to player and respawns player when it gets bad data. -respawn_player(Player, Socket) -> +respawn_player(_Player, _Socket) -> not_implemented. %% @doc Act as a supervisor to table and respawns table when it gets bad data. -respawn_table() -> +respawn_table(_Token) -> not_implemented. %% @doc Removes a player from coordinator. remove_player(From, Player) -> not_implemented. + +%% gen_server callbacks + +init([Port]) -> + {ok, ok}. + +handle_call(_Message, _From, State) -> + {noreply, State}. + +handle_cast(_Message, State) -> + {noreply, State}. + +terminate(normal, _State) -> + ok. + +code_change(_OldVsn, State, Extra) -> + {ok, State}. From 62be1f04cc570c9fab2f6cdfa4bb5982b64bb050 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Wed, 16 Feb 2011 17:23:58 +0100 Subject: [PATCH 28/49] changed not_implemented to a function --- src/ggs_coordinator.erl | 16 ++++++++-------- src/ggs_dispatcher.erl | 4 ++-- src/ggs_player.erl | 12 ++++++++---- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/ggs_coordinator.erl b/src/ggs_coordinator.erl index 4f38c6a..1081077 100644 --- a/src/ggs_coordinator.erl +++ b/src/ggs_coordinator.erl @@ -12,36 +12,36 @@ %% @doc Starts the coordinator process. start_link() -> - not_implemented. + not_implemented(). %% @doc Terminates the coordinator process. stop(_Reason) -> - not_implemented. + not_implemented(). %% @doc Joins table with specified token join_table(_Token) -> - not_implemented. + not_implemented(). %% @doc Create a new table create_table(_Params) -> - not_implemented. + not_implemented(). %% @doc This is the first function run by a newly created players. %% Generates a unique token that we use to identify the player. join_lobby() -> - not_implemented. + not_implemented(). %% @doc Act as a supervisor to player and respawns player when it gets bad data. respawn_player(_Player, _Socket) -> - not_implemented. + not_implemented(). %% @doc Act as a supervisor to table and respawns table when it gets bad data. respawn_table(_Token) -> - not_implemented. + not_implemented(). %% @doc Removes a player from coordinator. remove_player(From, Player) -> - not_implemented. + not_implemented(). %% gen_server callbacks diff --git a/src/ggs_dispatcher.erl b/src/ggs_dispatcher.erl index bc3327a..69d5481 100644 --- a/src/ggs_dispatcher.erl +++ b/src/ggs_dispatcher.erl @@ -20,12 +20,12 @@ %% Port = Integer %% Pid = # start_link(Port) -> - not_implemented. + not_implemented(). %% @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 diff --git a/src/ggs_player.erl b/src/ggs_player.erl index b5815af..6eb31c9 100644 --- a/src/ggs_player.erl +++ b/src/ggs_player.erl @@ -12,21 +12,25 @@ %% 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) -> + not_implemented(). %% @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() -> + 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(). 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 29/49] 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 30/49] 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). From 4be808049e0de12cd0a2cb5ea08353bd251884f0 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Wed, 16 Feb 2011 20:53:36 +0100 Subject: [PATCH 31/49] added ggs_logger module and implemented some ggs_table stuff --- src/ggs_coordinator.erl | 16 ++++++++-------- src/ggs_dispatcher.erl | 4 ++-- src/ggs_logger.erl | 8 ++++++++ src/ggs_player.erl | 8 ++++---- src/ggs_table.erl | 39 ++++++++++++++++++++++++++++++--------- 5 files changed, 52 insertions(+), 23 deletions(-) create mode 100644 src/ggs_logger.erl diff --git a/src/ggs_coordinator.erl b/src/ggs_coordinator.erl index 1081077..21bb641 100644 --- a/src/ggs_coordinator.erl +++ b/src/ggs_coordinator.erl @@ -12,36 +12,36 @@ %% @doc Starts the coordinator process. start_link() -> - not_implemented(). + ggs_logger:not_implemented(). %% @doc Terminates the coordinator process. stop(_Reason) -> - not_implemented(). + ggs_logger:not_implemented(). %% @doc Joins table with specified token join_table(_Token) -> - not_implemented(). + ggs_logger:not_implemented(). %% @doc Create a new table create_table(_Params) -> - not_implemented(). + ggs_logger:not_implemented(). %% @doc This is the first function run by a newly created players. %% Generates a unique token that we use to identify the player. join_lobby() -> - not_implemented(). + ggs_logger:not_implemented(). %% @doc Act as a supervisor to player and respawns player when it gets bad data. respawn_player(_Player, _Socket) -> - not_implemented(). + ggs_logger:not_implemented(). %% @doc Act as a supervisor to table and respawns table when it gets bad data. respawn_table(_Token) -> - not_implemented(). + ggs_logger:not_implemented(). %% @doc Removes a player from coordinator. remove_player(From, Player) -> - not_implemented(). + ggs_logger:not_implemented(). %% gen_server callbacks diff --git a/src/ggs_dispatcher.erl b/src/ggs_dispatcher.erl index 69d5481..fadb96d 100644 --- a/src/ggs_dispatcher.erl +++ b/src/ggs_dispatcher.erl @@ -20,12 +20,12 @@ %% Port = Integer %% Pid = # start_link(Port) -> - not_implemented(). + ggs_logger:not_implemented(). %% @doc Stops the dispatcher with the specified reason. %% @spec stop(Reason) -> ok. %% Reason = String -stop(Reason) -> not_implemented(). +stop(Reason) -> ggs_logger:not_implemented(). %% gen_server callbacks diff --git a/src/ggs_logger.erl b/src/ggs_logger.erl new file mode 100644 index 0000000..40a9595 --- /dev/null +++ b/src/ggs_logger.erl @@ -0,0 +1,8 @@ +-module(ggs_logger). +-export(not_implemented/0, log/2). + +not_implemented() -> + exit(not_implemented). + +log(Format, Args) -> + error_logger:info_msg(Format, Args). \ No newline at end of file diff --git a/src/ggs_player.erl b/src/ggs_player.erl index 6eb31c9..ae20ae8 100644 --- a/src/ggs_player.erl +++ b/src/ggs_player.erl @@ -13,7 +13,7 @@ %% identifying the player. %% @spec start_link(Socket::socket()) -> ok start_link(Socket) -> - not_implemented(). + ggs_logger:not_implemented(). %% @doc Handles incoming messages from the GGS and forwards them through the player @@ -21,16 +21,16 @@ start_link(Socket) -> %% @spec notify(Player::Pid(), From::Pid(), %% {Command::String(), Message::string()}) -> ok notify(Player, From, Message) -> - not_implemented(). + ggs_logger:not_implemented(). %% @doc Get the player token uniquely representing the player. %% @spec get_token() -> string() get_token() -> - not_implemented(). + ggs_logger: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(). + ggs_logger:not_implemented(). diff --git a/src/ggs_table.erl b/src/ggs_table.erl index 87a623a..5c0cbf0 100644 --- a/src/ggs_table.erl +++ b/src/ggs_table.erl @@ -1,5 +1,3 @@ -%% @doc This module represents a Player with a Socket and a Token - -module(ggs_table). -export([ start_link/1, @@ -9,28 +7,51 @@ notify/3 ]). +%% @doc This module represents a Player with a Socket and a Token + % @doc returns a new table -start_link(Token) -> - not_implemented(). +start_link(Token, Socket) -> + spawn_link(fun(Token, Socket) -> + GameVM = ggs_gamevm:start_link(); + loop(Token, Socket, GameVM, []) + ). % @doc adds a player to a table add_player(Table, Player) -> - not_implemented(). + ggs_logger:not_implemented(). % @doc removes player form a table remove_player(Table, Player) -> - not_implemented(). + ggs_logger:not_implemented(). % @doc stops the table process stop(Table) -> - not_implemented(). + Table ! {'EXIT', self(), normal} % @doc notifies the table with a message from a player notify(Table, Player, Message) -> - not_implemented(). + Table ! {notify, Player, Message}. % loop - +loop(Token, Socket, GameVM, PlayerList) -> + receive + {add_player, Player} -> + NewPlayerList = list:append(PlayerList, [Player]), + loop(Token, Socket, GameVM, NewPlayerList); + {remove_player, Player} -> + NewPlayerList = list:delete(Player, PlayerList), + loop(Token, Socket, GameVM, NewPlayerList); + {notify, Player, Message} -> + case Message of + {server, define, Args} -> + ggs_gamevm:define(GameVM, Args), + loop(Token, Socket, GameVM, PlayerList); + {game, Command, Args} -> + ggs_gamevm:user_command(GameVM, Player, Command, Args), + loop(Token, Socket, GameVM, PlayerList); + end + end. + % private helpers \ No newline at end of file From 2455f5582ce6858065143330c47299cd89529a24 Mon Sep 17 00:00:00 2001 From: Kallfaktorn Date: Wed, 16 Feb 2011 21:18:32 +0100 Subject: [PATCH 32/49] Added ggs_player_test skeleton. Return in player start_link is now {ok, Pid} | {error, Reason}. --- src/ggs_player.erl | 9 +++++---- tests/ggs_player_test.erl | 23 +++++++++++++++++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 tests/ggs_player_test.erl diff --git a/src/ggs_player.erl b/src/ggs_player.erl index 79d0d06..2a9aee1 100644 --- a/src/ggs_player.erl +++ b/src/ggs_player.erl @@ -11,7 +11,7 @@ %% @doc Spawns a process representing the player in GGS. Takes the player socket as %% an argument for storage and later usage. Creates a unique player token %% identifying the player. -%% @spec start_link(Socket::socket()) -> ok +%% @spec start_link(Socket::socket()) -> {ok, Pid} | {error, Reason} start_link(Socket) -> loop(Socket). @@ -27,10 +27,11 @@ notify(Player, From, Message) -> get_token(_Player) -> helpers: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. +%% @doc Properly terminates the player process. The player token will be lost +%% together with the table token. It should also close the player socket and the +%% process should return in the end. %% @spec stop(Table::pid()) -> Reason::string() -stop(_Table) -> +stop(_Player,_Table) -> helpers:not_implemented(). %% Internals diff --git a/tests/ggs_player_test.erl b/tests/ggs_player_test.erl new file mode 100644 index 0000000..fc13eb5 --- /dev/null +++ b/tests/ggs_player_test.erl @@ -0,0 +1,23 @@ +-include_lib("eunit/include/eunit.hrl"). +-import(ggs_player). + +%% @doc start_link should always return ok for any valid socket. A valid socket +%% should always return {ok, Pid} and {error, Reason} otherwise. +start_link_test() -> + helpers:not_implemented(). + +%% @doc Given that start_link returned {ok, Player}. Notify shall always return ok and +%% deliver a specified message through the socket. +notify_test() -> + helpers:not_implemented(). + +%% @doc Given that start_link returned {ok, Player}. get_token shall always return a valid +%% player token. a valid token should be unique. +get_token_test() -> + helpers:not_implemented(). + +%% @doc Given that start_link returned {ok, Pid}. There shouldn't be possible to +%% execute this function with the same Player and Table arguments twice. +stop_test() -> + helpers:not_implemented(). + From 8a780adb2d8a89e78a191dea856f289d94e17555 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Thu, 17 Feb 2011 01:01:54 +0100 Subject: [PATCH 33/49] changed to a gen_server --- src/ggs_table.erl | 132 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 92 insertions(+), 40 deletions(-) diff --git a/src/ggs_table.erl b/src/ggs_table.erl index e9c1518..cf22ddc 100644 --- a/src/ggs_table.erl +++ b/src/ggs_table.erl @@ -1,53 +1,105 @@ --module(ggs_table). --export([ - start_link/1, - add_player/2, - remove_player/2, - stop/2, - notify/3 -]). - %% @doc This module represents a Player with a Socket and a Token +-module(ggs_table). +-behaviour(gen_server). + +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, + terminate/2, code_change/3]). + +-record(state, { token, players, socket, game_vm } ). + +%% API +-export([start_link/2, + add_player/2, + remove_player/2, + stop/1, + notify/3]). + +-include_lib("eunit/include/eunit.hrl"). + +%% ---------------------------------------------------------------------- +% API implementation + % @doc returns a new table start_link(Token, Socket) -> - spawn_link(fun(Token, Socket) -> - GameVM = ggs_gamevm:start_link(); - loop(Token, Socket, GameVM, []) - ). + GameVM = ggs_gamevm:start_link(), + {ok, Pid} = gen_server:start_link(?MODULE, [Token, Socket, GameVM], []), + Pid. + +%% @private +call(Pid, Msg) -> + gen_server:call(Pid, Msg, infinity). % @doc adds a player to a table add_player(Table, Player) -> - ggs_logger:not_implemented(). - + call(Table, {add_player, Player}). + % @doc removes player form a table remove_player(Table, Player) -> - ggs_logger:not_implemented(). - + call(Table, {remove_player, Player}). + % @doc stops the table process stop(Table) -> - Table ! {'EXIT', self(), normal} - + gen_server:cast(Table, stop). + % @doc notifies the table with a message from a player notify(Table, Player, Message) -> - Table ! {notify, Player, Message}. - -% loop -loop(Token, Socket, GameVM, PlayerList) -> - receive - {add_player, Player} -> - NewPlayerList = list:append(PlayerList, [Player]), - loop(Token, Socket, GameVM, NewPlayerList); - {remove_player, Player} -> - NewPlayerList = list:delete(Player, PlayerList), - loop(Token, Socket, GameVM, NewPlayerList); - {notify, Player, Message} -> - case Message of - {server, define, Args} -> - ggs_gamevm:define(GameVM, Args), - loop(Token, Socket, GameVM, PlayerList); - {game, Command, Args} -> - ggs_gamevm:user_command(GameVM, Player, Command, Args), - loop(Token, Socket, GameVM, PlayerList); - end - end. + gen_server:cast(Table, {notify, Player, Message}). + +%% ---------------------------------------------------------------------- + +%% @private +init([Token, Socket, GameVM]) -> + {ok, #state { token = Token, + socket = Socket, + game_vm = GameVM, + players = [] }}. + +%% @private +handle_call({add_player, Player}, _From, #state { players = Players } = State) -> + {reply, ok, State#state { players = [Player | Players] }}; +handle_call({remove_player, Player}, _From, #state { players = Players } = State) -> + {reply, ok, State#state { players = Players -- [Player] }}; +handle_call(Msg, _From, State) -> + error_logger:error_report([unknown_msg, Msg]), + {reply, ok, State}. + +%% @private +handle_cast({notify, Player, Message}, #state { game_vm = GameVM } = State) -> + case Message of + {server, define, Args} -> + ggs_gamevm:define(GameVM, Args); + {game, Command, Args} -> + ggs_gamevm:user_command(GameVM, Player, Command, Args) + end, + {noreply, State}; +handle_cast(stop, State) -> + {stop, normal, State}; +handle_cast(Msg, S) -> + error_logger:error_report([unknown_msg, Msg]), + {noreply, S}. + +%% @private +handle_info(Msg, S) -> + error_logger:error_report([unknown_msg, Msg]), + {noreply, S}. + +%% @private +terminate(_Reason, _State) -> + ok. + +%% @private +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + + +%% ---------------------------------------------------------------------- + +% Tests + +%% @private +start_link_test() -> + ClientToken = "123", + Pid = start_link(ClientToken, none), + ?assertNot(Pid =:= undefined). From 6865e7368412a4f55b786092d746bce05c6aa0a4 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Thu, 17 Feb 2011 01:57:09 +0100 Subject: [PATCH 34/49] changed from stop/1 to stop/2 in export --- src/ggs_player.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ggs_player.erl b/src/ggs_player.erl index 2a9aee1..c3695af 100644 --- a/src/ggs_player.erl +++ b/src/ggs_player.erl @@ -1,5 +1,5 @@ -module(ggs_player). --export([start_link/1, notify/3, get_token/1, stop/1]). +-export([start_link/1, notify/3, get_token/1, stop/2]). %% @doc This module handles communication between a player and GGS. This module is %%responsible for: From d018034b7f55ff4449a5984f5eb70e68f7c74fb9 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Thu, 17 Feb 2011 01:57:29 +0100 Subject: [PATCH 35/49] added another test --- src/ggs_table.erl | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/ggs_table.erl b/src/ggs_table.erl index cf22ddc..db247c4 100644 --- a/src/ggs_table.erl +++ b/src/ggs_table.erl @@ -61,6 +61,8 @@ handle_call({add_player, Player}, _From, #state { players = Players } = State) - {reply, ok, State#state { players = [Player | Players] }}; handle_call({remove_player, Player}, _From, #state { players = Players } = State) -> {reply, ok, State#state { players = Players -- [Player] }}; +handle_call(get_player_list, _From, #state { players = Players } = State) -> + {reply, {ok, Players}, State}; handle_call(Msg, _From, State) -> error_logger:error_report([unknown_msg, Msg]), {reply, ok, State}. @@ -98,8 +100,15 @@ code_change(_OldVsn, State, _Extra) -> % Tests -%% @private start_link_test() -> ClientToken = "123", Pid = start_link(ClientToken, none), ?assertNot(Pid =:= undefined). + +add_player_test() -> + Table = start_link("123", none), + Player = "test", %ggs_player:start_link(none), + add_player(Table, Player), + {ok, [Player]} = gen_server:call(Table, get_player_list). + + From ea1557e2d74ca72bf2afcbf6d09aeef83b24190b Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Thu, 17 Feb 2011 02:28:14 +0100 Subject: [PATCH 36/49] added a notify test --- src/ggs_table.erl | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/src/ggs_table.erl b/src/ggs_table.erl index db247c4..1e4f323 100644 --- a/src/ggs_table.erl +++ b/src/ggs_table.erl @@ -101,14 +101,38 @@ code_change(_OldVsn, State, _Extra) -> % Tests start_link_test() -> - ClientToken = "123", - Pid = start_link(ClientToken, none), - ?assertNot(Pid =:= undefined). + Table = start_link("123", none), + ?assertNot(Table =:= undefined). add_player_test() -> Table = start_link("123", none), - Player = "test", %ggs_player:start_link(none), + Player = test_player, add_player(Table, Player), {ok, [Player]} = gen_server:call(Table, get_player_list). +remove_player_test() -> + Table = start_link("123", none), + Player = test_player, + Player2 = test_player2, + add_player(Table, Player), + {ok, [Player]} = gen_server:call(Table, get_player_list), + add_player(Table, Player2), + {ok, [Player2, Player]} = gen_server:call(Table, get_player_list), + remove_player(Table, Player), + {ok, [Player2]} = gen_server:call(Table, get_player_list), + remove_player(Table, Player2), + {ok, []} = gen_server:call(Table, get_player_list). +stop_test() -> + Table = start_link("123", none), + ok = stop(Table). + +% @private +notify_test() -> + Table = start_link("123", none), + Player = test_player, + Message = {server, define, "function helloWorld(x) { }"}, + ok = notify(Table, Player, Message). + %Message2 = {game, "helloWorld", "test"}, + %ok = notify(Table, Player, Message2). + \ No newline at end of file From 94d9dc6d7f546b0e4613bb66510488f181934bd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Thu, 17 Feb 2011 08:33:55 +0100 Subject: [PATCH 37/49] ggs_logger got lost somewhere? I added it again, also replaced all references to helpers with ggs_logger --- src/ggs_coordinator.erl | 14 +++++++------- src/ggs_dispatcher.erl | 2 +- src/ggs_logger.erl | 8 ++++++++ src/ggs_player.erl | 6 +++--- tests/ggs_player_test.erl | 8 ++++---- 5 files changed, 23 insertions(+), 15 deletions(-) create mode 100644 src/ggs_logger.erl diff --git a/src/ggs_coordinator.erl b/src/ggs_coordinator.erl index 2a755f0..4e6b623 100644 --- a/src/ggs_coordinator.erl +++ b/src/ggs_coordinator.erl @@ -17,32 +17,32 @@ start_link() -> %% @doc Terminates the coordinator process. stop(_Reason) -> - helpers:not_implemented(). + ggs_logger:not_implemented(). %% @doc Joins table with specified token join_table(_Token) -> - helpers:not_implemented(). + ggs_logger:not_implemented(). %% @doc Create a new table create_table(_Params) -> - helpers:not_implemented(). + ggs_logger:not_implemented(). %% @doc This is the first function run by a newly created players. %% Generates a unique token that we use to identify the player. join_lobby() -> - helpers:not_implemented(). + ggs_logger:not_implemented(). %% @doc Act as a supervisor to player and respawns player when it gets bad data. respawn_player(_Player, _Socket) -> - helpers:not_implemented(). + ggs_logger:not_implemented(). %% @doc Act as a supervisor to table and respawns table when it gets bad data. respawn_table(_Token) -> - helpers:not_implemented(). + ggs_logger:not_implemented(). %% @doc Removes a player from coordinator. remove_player(_From, _Player) -> - helpers:not_implemented(). + ggs_logger:not_implemented(). %% gen_server callbacks diff --git a/src/ggs_dispatcher.erl b/src/ggs_dispatcher.erl index 4e353da..49dcf4b 100644 --- a/src/ggs_dispatcher.erl +++ b/src/ggs_dispatcher.erl @@ -29,7 +29,7 @@ start_link(Port) -> %% @doc Stops the dispatcher with the specified reason. %% @spec stop(Reason) -> ok. %% Reason = String -stop(_Reason) -> helpers:not_implemented(). +stop(_Reason) -> ggs_logger:not_implemented(). %% gen_server callbacks diff --git a/src/ggs_logger.erl b/src/ggs_logger.erl new file mode 100644 index 0000000..49f5abc --- /dev/null +++ b/src/ggs_logger.erl @@ -0,0 +1,8 @@ +-module(ggs_logger). +-export([not_implemented/0, log/2]). + +not_implemented() -> + exit(not_implemented). + +log(Format, Args) -> + error_logger:info_msg(Format, Args). diff --git a/src/ggs_player.erl b/src/ggs_player.erl index c3695af..37c8496 100644 --- a/src/ggs_player.erl +++ b/src/ggs_player.erl @@ -20,19 +20,19 @@ start_link(Socket) -> %% @spec notify(Player::Pid(), From::Pid(), %% {Command::String(), Message::string()}) -> ok notify(Player, From, Message) -> - helpers:not_implemented(). + ggs_logger:not_implemented(). %% @doc Get the player token uniquely representing the player. %% @spec get_token() -> string() get_token(_Player) -> - helpers:not_implemented(). + ggs_logger:not_implemented(). %% @doc Properly terminates the player process. The player token will be lost %% together with the table token. It should also close the player socket and the %% process should return in the end. %% @spec stop(Table::pid()) -> Reason::string() stop(_Player,_Table) -> - helpers:not_implemented(). + ggs_logger:not_implemented(). %% Internals diff --git a/tests/ggs_player_test.erl b/tests/ggs_player_test.erl index fc13eb5..1067f71 100644 --- a/tests/ggs_player_test.erl +++ b/tests/ggs_player_test.erl @@ -4,20 +4,20 @@ %% @doc start_link should always return ok for any valid socket. A valid socket %% should always return {ok, Pid} and {error, Reason} otherwise. start_link_test() -> - helpers:not_implemented(). + ggs_logger:not_implemented(). %% @doc Given that start_link returned {ok, Player}. Notify shall always return ok and %% deliver a specified message through the socket. notify_test() -> - helpers:not_implemented(). + ggs_logger:not_implemented(). %% @doc Given that start_link returned {ok, Player}. get_token shall always return a valid %% player token. a valid token should be unique. get_token_test() -> - helpers:not_implemented(). + ggs_logger:not_implemented(). %% @doc Given that start_link returned {ok, Pid}. There shouldn't be possible to %% execute this function with the same Player and Table arguments twice. stop_test() -> - helpers:not_implemented(). + ggs_logger:not_implemented(). From 654aa837ddacc2623b418173a48072f6b22873de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Thu, 17 Feb 2011 09:35:39 +0100 Subject: [PATCH 38/49] Added some tests for coordinator --- src/ggs_coordinator.erl | 7 +++++-- tests/ggs_coordinator_test.erl | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 tests/ggs_coordinator_test.erl diff --git a/src/ggs_coordinator.erl b/src/ggs_coordinator.erl index 4e6b623..a28fc2a 100644 --- a/src/ggs_coordinator.erl +++ b/src/ggs_coordinator.erl @@ -16,8 +16,8 @@ start_link() -> gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). %% @doc Terminates the coordinator process. -stop(_Reason) -> - ggs_logger:not_implemented(). +stop(Reason) -> + gen_server:cast(ggs_coordinator, {stop, Reason}). %% @doc Joins table with specified token join_table(_Token) -> @@ -52,6 +52,9 @@ init([]) -> handle_call(_Message, _From, State) -> {noreply, State}. +handle_cast({stop, Reason}, State) -> + {stop, normal, state}; + handle_cast(_Message, State) -> {noreply, State}. diff --git a/tests/ggs_coordinator_test.erl b/tests/ggs_coordinator_test.erl new file mode 100644 index 0000000..03b5389 --- /dev/null +++ b/tests/ggs_coordinator_test.erl @@ -0,0 +1,16 @@ +-module(ggs_coordinator_test). +-include_lib("eunit/include/eunit.hrl"). + +start_link_test() -> + {ok, Coord} = ggs_coordinator:start_link(), % Start + PInfo = erlang:process_info(Coord), % Check process info + ggs_coordinator:stop(""), % Clean up + timer:sleep(100), % Wait for cleaning.. + ?assert((PInfo /= undefined)). % Did the server start? + +stop_test() -> + ok = ggs_coordinator:stop(""), % Extra cleaning + {ok, Coord} = ggs_coordinator:start_link(), % Start server + ggs_coordinator:stop("Terminate now"), % Send stop message + timer:sleep(100), % Wait for cleaning.. + ?assert((erlang:process_info(Coord) == undefined)). % Did it stop? From 391af1a96af8b2f603459181bedcd1e191668a89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Thu, 17 Feb 2011 10:04:54 +0100 Subject: [PATCH 39/49] Added more tests & functionality. (failing join table, create_table_test with force) --- src/ggs_coordinator.erl | 21 ++++++++++++++------- tests/ggs_coordinator_test.erl | 17 +++++++++++++++++ 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/ggs_coordinator.erl b/src/ggs_coordinator.erl index a28fc2a..2a5d509 100644 --- a/src/ggs_coordinator.erl +++ b/src/ggs_coordinator.erl @@ -1,7 +1,7 @@ -module(ggs_coordinator). %% API Exports --export([start_link/0, stop/1]). +-export([start_link/0, stop/1, join_table/1, create_table/1]). %% gen_server callback exports -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, @@ -19,13 +19,14 @@ start_link() -> stop(Reason) -> gen_server:cast(ggs_coordinator, {stop, Reason}). -%% @doc Joins table with specified token -join_table(_Token) -> - ggs_logger:not_implemented(). +%% @doc Joins table with specified token, returns {error, no_such_table} +%% if the specified table token does not exist +join_table(Token) -> + gen_server:call(ggs_coordinator, {join_table, Token}). -%% @doc Create a new table -create_table(_Params) -> - ggs_logger:not_implemented(). +%% @doc Create a new table, return {error, Reason} or {ok, TableToken} +create_table(Params) -> + gen_server:call(ggs_coordinator, {create_table, Params}). %% @doc This is the first function run by a newly created players. %% Generates a unique token that we use to identify the player. @@ -49,6 +50,12 @@ remove_player(_From, _Player) -> init([]) -> {ok, ok}. +handle_call({join_table, Table}, From, State) -> + {reply, {error, no_such_table}, State}; + +handle_call({create_table, {force, TID}}, From, State) -> + {reply, {ok, TID}, State}; + handle_call(_Message, _From, State) -> {noreply, State}. diff --git a/tests/ggs_coordinator_test.erl b/tests/ggs_coordinator_test.erl index 03b5389..ba05c95 100644 --- a/tests/ggs_coordinator_test.erl +++ b/tests/ggs_coordinator_test.erl @@ -14,3 +14,20 @@ stop_test() -> ggs_coordinator:stop("Terminate now"), % Send stop message timer:sleep(100), % Wait for cleaning.. ?assert((erlang:process_info(Coord) == undefined)). % Did it stop? + +join_bad_table_test() -> + {ok, _Coord} = ggs_coordinator:start_link(), + Response = ggs_coordinator:join_table("Nonexistant table"), + ggs_coordinator:stop(""), + timer:sleep(100), + ?assert(Response == {error, no_such_table}). + + +create_table_test() -> + {ok, _Coord} = ggs_coordinator:start_link(), + % Forcibly create a table. This functionality should be disabled + % in the production system, but is pretty nice for testing. + Response = ggs_coordinator:create_table({force, 1337}), + ggs_coordinator:stop(""), + timer:sleep(100), + ?assert(Response == {ok, 1337}). From 818205e19b505580ee66c2836e97617c12455f5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Thu, 17 Feb 2011 12:12:12 +0100 Subject: [PATCH 40/49] Now we store the tables when they are created --- src/ggs_coordinator.erl | 10 ++++++-- start_test | 2 +- tests/ggs_coordinator_test.erl | 47 ++++++++++++++++++++-------------- 3 files changed, 37 insertions(+), 22 deletions(-) diff --git a/src/ggs_coordinator.erl b/src/ggs_coordinator.erl index 2a5d509..c6e01d6 100644 --- a/src/ggs_coordinator.erl +++ b/src/ggs_coordinator.erl @@ -8,6 +8,11 @@ code_change/3]). -define(SERVER, ?MODULE). +-record(co_state, + {players = [], % List of all player processes + player_table_map = [], % Players <-> Table map + table_state_map = []}). % Table <-> Table state map + %% @doc This module act as "the man in the middle". %% Creates the starting connection between table and players. @@ -48,13 +53,14 @@ remove_player(_From, _Player) -> %% gen_server callbacks init([]) -> - {ok, ok}. + {ok, #co_state{}}. handle_call({join_table, Table}, From, State) -> {reply, {error, no_such_table}, State}; handle_call({create_table, {force, TID}}, From, State) -> - {reply, {ok, TID}, State}; + TIDs = State#co_state.player_table_map, + {reply, {ok, TID}, State#co_state{player_table_map = [TID | TIDs]}}; handle_call(_Message, _From, State) -> {noreply, State}. diff --git a/start_test b/start_test index 5920151..76050c1 100755 --- a/start_test +++ b/start_test @@ -1,3 +1,3 @@ #!/usr/bin/env bash -erl -boot start_sasl -pa ebin_test -pa erlang_js/ebin/ -pa erlv8/ebin -pa ebin -pa src -eval 'ggs_protocol_test:test_parse().' +erl -boot start_sasl -pa ebin_test -pa erlang_js/ebin/ -pa ebin -pa src -eval 'ggs_coordinator_test:test().' diff --git a/tests/ggs_coordinator_test.erl b/tests/ggs_coordinator_test.erl index ba05c95..ccc9256 100644 --- a/tests/ggs_coordinator_test.erl +++ b/tests/ggs_coordinator_test.erl @@ -1,33 +1,42 @@ -module(ggs_coordinator_test). -include_lib("eunit/include/eunit.hrl"). -start_link_test() -> - {ok, Coord} = ggs_coordinator:start_link(), % Start - PInfo = erlang:process_info(Coord), % Check process info - ggs_coordinator:stop(""), % Clean up - timer:sleep(100), % Wait for cleaning.. - ?assert((PInfo /= undefined)). % Did the server start? +coordinator_test_() -> + {foreach, + fun() -> + {ok, _Coord} = ggs_coordinator:start_link(), + timer:sleep(100) + end, + fun(_X) -> + ggs_coordinator:stop("End of test"), + timer:sleep(100) + end, + [ + fun test_start_link/0, + fun test_stop/0, + fun test_join_bad_table/0, + fun test_create_table/0 + ] + }. -stop_test() -> +test_start_link() -> + % Check process info + PInfo = whereis(ggs_coordinator), + ?assert((PInfo /= undefined)). % Did the server start? + +test_stop() -> ok = ggs_coordinator:stop(""), % Extra cleaning - {ok, Coord} = ggs_coordinator:start_link(), % Start server - ggs_coordinator:stop("Terminate now"), % Send stop message - timer:sleep(100), % Wait for cleaning.. - ?assert((erlang:process_info(Coord) == undefined)). % Did it stop? + timer:sleep(100), + % Did it stop? + ?assert((whereis(ggs_coordinator)) == undefined). -join_bad_table_test() -> - {ok, _Coord} = ggs_coordinator:start_link(), +test_join_bad_table() -> Response = ggs_coordinator:join_table("Nonexistant table"), - ggs_coordinator:stop(""), - timer:sleep(100), ?assert(Response == {error, no_such_table}). -create_table_test() -> - {ok, _Coord} = ggs_coordinator:start_link(), +test_create_table() -> % Forcibly create a table. This functionality should be disabled % in the production system, but is pretty nice for testing. Response = ggs_coordinator:create_table({force, 1337}), - ggs_coordinator:stop(""), - timer:sleep(100), ?assert(Response == {ok, 1337}). From 3f417692339b7d727b0ec37295bf10e489fc4f66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Thu, 17 Feb 2011 12:57:41 +0100 Subject: [PATCH 41/49] Now we have join_table, create_table and join_lobby + test cases --- src/ggs_coordinator.erl | 30 +++++++++++++++++++++++------- src/helpers.erl | 4 ++++ tests/ggs_coordinator_test.erl | 15 +++++++++++++-- 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/src/ggs_coordinator.erl b/src/ggs_coordinator.erl index c6e01d6..756bb2c 100644 --- a/src/ggs_coordinator.erl +++ b/src/ggs_coordinator.erl @@ -1,7 +1,8 @@ -module(ggs_coordinator). %% API Exports --export([start_link/0, stop/1, join_table/1, create_table/1]). +-export([start_link/0, stop/1, join_table/1, create_table/1, join_lobby/0, + respawn_player/2, respawn_table/1, remove_player/2]). %% gen_server callback exports -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, @@ -11,7 +12,8 @@ -record(co_state, {players = [], % List of all player processes player_table_map = [], % Players <-> Table map - table_state_map = []}). % Table <-> Table state map + table_state_map = [], + tables = []}). % Table <-> Table state map %% @doc This module act as "the man in the middle". %% Creates the starting connection between table and players. @@ -36,7 +38,7 @@ create_table(Params) -> %% @doc This is the first function run by a newly created players. %% Generates a unique token that we use to identify the player. join_lobby() -> - ggs_logger:not_implemented(). + gen_server:call(ggs_coordinator, join_lobby). %% @doc Act as a supervisor to player and respawns player when it gets bad data. respawn_player(_Player, _Socket) -> @@ -55,12 +57,26 @@ remove_player(_From, _Player) -> init([]) -> {ok, #co_state{}}. -handle_call({join_table, Table}, From, State) -> - {reply, {error, no_such_table}, State}; +handle_call(join_lobby, _From, State) -> + Token = helpers:get_new_token(), + {reply, {ok, Token}, State}; + +handle_call({join_table, Table}, _From, State) -> + Tables = State#co_state.tables, + case lists:keyfind(Table, 1, Tables) of + {Table} -> + {reply, {ok, Table}, State}; %% @TODO: Also add player to table + false -> + {reply, {error, no_such_table}, State} + end; handle_call({create_table, {force, TID}}, From, State) -> - TIDs = State#co_state.player_table_map, - {reply, {ok, TID}, State#co_state{player_table_map = [TID | TIDs]}}; + TIDMap = State#co_state.player_table_map, + Tables = State#co_state.tables, + {reply, {ok, TID}, State#co_state{ + player_table_map = [{From, TID} | TIDMap], + tables = [{TID} | TID] + }}; handle_call(_Message, _From, State) -> {noreply, State}. diff --git a/src/helpers.erl b/src/helpers.erl index 1bf7825..3a42fbf 100644 --- a/src/helpers.erl +++ b/src/helpers.erl @@ -1,4 +1,8 @@ -module(helpers). +-export([not_implemented/0, get_new_token/0]). not_implemented() -> exit("Not implemented"). + +get_new_token() -> + string:strip(os:cmd("uuidgen"), right, $\n ). diff --git a/tests/ggs_coordinator_test.erl b/tests/ggs_coordinator_test.erl index ccc9256..6ec41c6 100644 --- a/tests/ggs_coordinator_test.erl +++ b/tests/ggs_coordinator_test.erl @@ -15,7 +15,7 @@ coordinator_test_() -> fun test_start_link/0, fun test_stop/0, fun test_join_bad_table/0, - fun test_create_table/0 + fun test_join_lobby/0 ] }. @@ -34,9 +34,20 @@ test_join_bad_table() -> Response = ggs_coordinator:join_table("Nonexistant table"), ?assert(Response == {error, no_such_table}). +test_join_lobby() -> + {Response, _} = ggs_coordinator:join_lobby(), + ?assert(Response /= error). -test_create_table() -> +%% 'Manual' tests + +create_table_test() -> + {ok, _Coord} = ggs_coordinator:start_link(), + timer:sleep(100), % Forcibly create a table. This functionality should be disabled % in the production system, but is pretty nice for testing. Response = ggs_coordinator:create_table({force, 1337}), ?assert(Response == {ok, 1337}). + +join_good_table_test() -> + Response = ggs_coordinator:join_table(1337), + ?assert(Response == {ok, 1337}). From e38bab50545c71f20bd7234e6c6034bc965f5511 Mon Sep 17 00:00:00 2001 From: niklas Date: Thu, 17 Feb 2011 13:52:56 +0100 Subject: [PATCH 42/49] Modified player test --- tests/ggs_player_test.erl | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/tests/ggs_player_test.erl b/tests/ggs_player_test.erl index 1067f71..be38135 100644 --- a/tests/ggs_player_test.erl +++ b/tests/ggs_player_test.erl @@ -4,20 +4,24 @@ %% @doc start_link should always return ok for any valid socket. A valid socket %% should always return {ok, Pid} and {error, Reason} otherwise. start_link_test() -> - ggs_logger:not_implemented(). + ggs_logger:not_implemented(). %% @doc Given that start_link returned {ok, Player}. Notify shall always return ok and %% deliver a specified message through the socket. notify_test() -> - ggs_logger:not_implemented(). - + Player = start_link("bad arg"), + Message = {"something", ""}, + Ret = ggs_player:notify(Player, self(), Message) + ?assertNot(ok =:= Ret). + %% @doc Given that start_link returned {ok, Player}. get_token shall always return a valid %% player token. a valid token should be unique. get_token_test() -> - ggs_logger:not_implemented(). + ggs_logger:not_implemented(). -%% @doc Given that start_link returned {ok, Pid}. There shouldn't be possible to +%% @doc Given that start_link returned {ok, Pid}. There shouldn't be possible to %% execute this function with the same Player and Table arguments twice. stop_test() -> - ggs_logger:not_implemented(). - + Player = start_link(something), + Table = test, + ok = stop(Player, Table). From 041fee24419644398c9841ebd2b6450076053891 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Thu, 17 Feb 2011 14:14:32 +0100 Subject: [PATCH 43/49] removed Token and Socket --- src/ggs_table.erl | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/ggs_table.erl b/src/ggs_table.erl index 1e4f323..3c0237d 100644 --- a/src/ggs_table.erl +++ b/src/ggs_table.erl @@ -1,4 +1,4 @@ -%% @doc This module represents a Player with a Socket and a Token +%% @doc This module represents a table with players -module(ggs_table). -behaviour(gen_server). @@ -7,10 +7,10 @@ -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). --record(state, { token, players, socket, game_vm } ). +-record(state, { players, game_vm } ). %% API --export([start_link/2, +-export([start_link/0, add_player/2, remove_player/2, stop/1, @@ -22,9 +22,9 @@ % API implementation % @doc returns a new table -start_link(Token, Socket) -> +start_link() -> GameVM = ggs_gamevm:start_link(), - {ok, Pid} = gen_server:start_link(?MODULE, [Token, Socket, GameVM], []), + {ok, Pid} = gen_server:start_link(?MODULE, [GameVM], []), Pid. %% @private @@ -50,11 +50,8 @@ notify(Table, Player, Message) -> %% ---------------------------------------------------------------------- %% @private -init([Token, Socket, GameVM]) -> - {ok, #state { token = Token, - socket = Socket, - game_vm = GameVM, - players = [] }}. +init([GameVM]) -> + {ok, #state { game_vm = GameVM, players = [] }}. %% @private handle_call({add_player, Player}, _From, #state { players = Players } = State) -> @@ -97,21 +94,20 @@ code_change(_OldVsn, State, _Extra) -> %% ---------------------------------------------------------------------- - % Tests start_link_test() -> - Table = start_link("123", none), + Table = start_link(), ?assertNot(Table =:= undefined). add_player_test() -> - Table = start_link("123", none), + Table = start_link(), Player = test_player, add_player(Table, Player), {ok, [Player]} = gen_server:call(Table, get_player_list). remove_player_test() -> - Table = start_link("123", none), + Table = start_link(), Player = test_player, Player2 = test_player2, add_player(Table, Player), @@ -124,12 +120,12 @@ remove_player_test() -> {ok, []} = gen_server:call(Table, get_player_list). stop_test() -> - Table = start_link("123", none), + Table = start_link(), ok = stop(Table). % @private notify_test() -> - Table = start_link("123", none), + Table = start_link(), Player = test_player, Message = {server, define, "function helloWorld(x) { }"}, ok = notify(Table, Player, Message). From 44d26278ccc34a0c9a2d2718c063bd496d43bee1 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Thu, 17 Feb 2011 20:05:12 +0100 Subject: [PATCH 44/49] rewrite to gen_server and added tests --- src/ggs_gamevm.erl | 126 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 97 insertions(+), 29 deletions(-) diff --git a/src/ggs_gamevm.erl b/src/ggs_gamevm.erl index 1a8f547..15cbb64 100644 --- a/src/ggs_gamevm.erl +++ b/src/ggs_gamevm.erl @@ -1,24 +1,34 @@ --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. +-module(ggs_gamevm). +-behaviour(gen_server). + +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, + terminate/2, code_change/3]). + +-record(state, { port, table } ). + +%% API +-export([start_link/1, define/2, user_command/4, stop/1, call_js/2]). + +-include_lib("eunit/include/eunit.hrl"). + + +%% ---------------------------------------------------------------------- +% API implementation + %% @doc Create a new VM process. The process ID is returned and can be used %% with for example the define method of this module. -start_link() -> +start_link(Table) -> erlang_js:start(), %% @TODO: should only be done once - PortPid = spawn_link( fun() -> - process_flag(trap_exit, true), - {ok, Port} = js_driver:new(), - js:define(Port, <<"function userCommand(user, command, args){return 'Hello world';}">>), - loop(Port) - end ), - PortPid. + {ok, Pid} = gen_server:start_link(?MODULE, [Table], []), + Pid. %% @doc Define some new code on the specified VM, returns the atom ok. define(GameVM, SourceCode) -> - GameVM ! {define,SourceCode}, - ok. + gen_server:cast(GameVM, {define, SourceCode}). %% @doc Execute a user command on the specified VM. This function is %% asynchronous, and returns ok. @@ -28,23 +38,81 @@ define(GameVM, SourceCode) -> %% Command = a game command to run %% Args = arguments for the Command parameter user_command(GameVM, Player, Command, Args) -> - Ref = make_ref(), - GameVM ! {user_command, Player, Command, Args, self(), Ref}, + gen_server:cast(GameVM, {user_command, Player, Command, Args}). + +%% @private +% only for tests +call_js(GameVM, SourceCode) -> + gen_server:call(GameVM, {eval, SourceCode}). + +% @doc stops the gamevm process +stop(GameVM) -> + gen_server:cast(GameVM, stop). + + +%% ---------------------------------------------------------------------- + +%% @private +init([Table]) -> + process_flag(trap_exit, true), + {ok, Port} = js_driver:new(), + %% @TODO: add here default JS API instead + {ok, #state { port = Port, table = Table }}. + +%% private +% only needed for the tests +handle_call({eval, SourceCode}, _From, #state { port = Port } = State) -> + {ok, Ret} = js:eval(Port, list_to_binary(SourceCode)), + {reply, Ret, State}. + +%% @private +handle_cast({define, SourceCode}, #state { port = Port } = State) -> + ok = js:define(Port, list_to_binary(SourceCode)), + {noreply, State}; +handle_cast({user_command, Player, Command, Args}, #state { port = Port } = State) -> + Arguments = string:sub(string:join([Player, Command, Args], ","), "'", "\'"), + Js = list_to_binary(string:concat(string:concat("userCommand(", Arguments), ");")), + js_driver:define_js(Port, Js), + {noreply, State}; +handle_cast(stop, State) -> + {stop, normal, State}; +handle_cast(Msg, S) -> + error_logger:error_report([unknown_msg, Msg]), + {noreply, S}. + +%% @private +handle_info(Msg, S) -> + error_logger:error_report([unknown_msg, Msg]), + {noreply, S}. + +%% @private +terminate(_Reason, _State) -> ok. -%% Helper functions +%% @private +code_change(_OldVsn, State, _Extra) -> + {ok, State}. -loop(Port) -> - receive - {define, SourceCode} -> - ok = js:define(Port, list_to_binary(SourceCode)), - loop(Port); - {user_command, User, Command, Args, From, Ref} -> - {ok, Ret} = js:call(Port, <<"userCommand">>, - [ list_to_binary(User), - list_to_binary(Command), - list_to_binary(Args) - ]), - From ! {Ref, Ret}, - loop(Port) - end. +%% ---------------------------------------------------------------------- +% Tests + +start_link_test() -> + erlang_js:start(), %% @TODO: should only be done once + GameVM = start_link(test_table), + ?assertNot(GameVM =:= undefined). + +define_test() -> + GameVM = start_link(test_table), + define(GameVM, "function hello(test) { return test; }"), + ?assertMatch(<<"jeena">>, gen_server:call(GameVM, {eval, "hello('jeena')"})). + +stop_test() -> + GameVM = start_link(test_table), + ok = stop(GameVM). + +user_command_test() -> + GameVM = start_link(test_table), + define(GameVM, "var t = '';\nfunction userCommand(user, command, args) { t = user + command + args; }\n"), + user_command(GameVM, "'jeena'", "'thecommand'", "'theargs'"), + ?assertMatch(<<"jeenathecommandtheargs">>, gen_server:call(GameVM, {eval, "t;"})). + From dd9b92bf43b7969d896209b2aad98371c9d31b33 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Thu, 17 Feb 2011 20:14:45 +0100 Subject: [PATCH 45/49] fixed escaping problem --- src/ggs_gamevm.erl | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/ggs_gamevm.erl b/src/ggs_gamevm.erl index 15cbb64..6493c9f 100644 --- a/src/ggs_gamevm.erl +++ b/src/ggs_gamevm.erl @@ -70,7 +70,8 @@ handle_cast({define, SourceCode}, #state { port = Port } = State) -> ok = js:define(Port, list_to_binary(SourceCode)), {noreply, State}; handle_cast({user_command, Player, Command, Args}, #state { port = Port } = State) -> - Arguments = string:sub(string:join([Player, Command, Args], ","), "'", "\'"), + Arguments = string:concat("'", string:concat( + string:join([js_escape(Player), js_escape(Command), js_escape(Args)], "','"), "'")), Js = list_to_binary(string:concat(string:concat("userCommand(", Arguments), ");")), js_driver:define_js(Port, Js), {noreply, State}; @@ -93,6 +94,9 @@ terminate(_Reason, _State) -> code_change(_OldVsn, State, _Extra) -> {ok, State}. +js_escape(S) -> + lists:flatmap(fun($\') -> [$\\, $\']; (X) -> [X] end, S). + %% ---------------------------------------------------------------------- % Tests @@ -113,6 +117,6 @@ stop_test() -> user_command_test() -> GameVM = start_link(test_table), define(GameVM, "var t = '';\nfunction userCommand(user, command, args) { t = user + command + args; }\n"), - user_command(GameVM, "'jeena'", "'thecommand'", "'theargs'"), - ?assertMatch(<<"jeenathecommandtheargs">>, gen_server:call(GameVM, {eval, "t;"})). + user_command(GameVM, "'jeena", "thecommand", "theargs'"), + ?assertMatch(<<"'jeenathecommandtheargs'">>, gen_server:call(GameVM, {eval, "t;"})). From 883cf9e9d714a79645df9b67068e2b5ec13e56a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Thu, 17 Feb 2011 23:17:04 +0100 Subject: [PATCH 46/49] Now we have some myltiplayer action! --- src/ggs_coordinator.erl | 21 ++++---- src/ggs_gamevm_e.erl | 41 +++++++++++++++ src/ggs_player.erl | 40 ++++++++++---- src/ggs_table.erl | 112 +++++++++++++++++++++++++--------------- 4 files changed, 151 insertions(+), 63 deletions(-) create mode 100644 src/ggs_gamevm_e.erl diff --git a/src/ggs_coordinator.erl b/src/ggs_coordinator.erl index 756bb2c..733ff8d 100644 --- a/src/ggs_coordinator.erl +++ b/src/ggs_coordinator.erl @@ -61,21 +61,24 @@ handle_call(join_lobby, _From, State) -> Token = helpers:get_new_token(), {reply, {ok, Token}, State}; -handle_call({join_table, Table}, _From, State) -> +handle_call({join_table, Table}, From, State) -> + {FromPlayer, _Ref} = From, Tables = State#co_state.tables, case lists:keyfind(Table, 1, Tables) of - {Table} -> - {reply, {ok, Table}, State}; %% @TODO: Also add player to table + {TableID, TablePID} -> + ggs_table:add_player(TablePID, FromPlayer), + {reply, {ok, TablePID}, State}; false -> {reply, {error, no_such_table}, State} end; -handle_call({create_table, {force, TID}}, From, State) -> - TIDMap = State#co_state.player_table_map, - Tables = State#co_state.tables, - {reply, {ok, TID}, State#co_state{ - player_table_map = [{From, TID} | TIDMap], - tables = [{TID} | TID] +handle_call({create_table, {force, TableID}}, From, State) -> + TableIDMap = State#co_state.player_table_map, + Tables = State#co_state.tables, + NewTableProc = ggs_table:start_link(), + {reply, {ok, TableID}, State#co_state{ + player_table_map = [{From, TableID} | TableIDMap], + tables = [{TableID, NewTableProc} | Tables] }}; handle_call(_Message, _From, State) -> diff --git a/src/ggs_gamevm_e.erl b/src/ggs_gamevm_e.erl new file mode 100644 index 0000000..76b9350 --- /dev/null +++ b/src/ggs_gamevm_e.erl @@ -0,0 +1,41 @@ +-module(ggs_gamevm_e). +-export([start_link/1, 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. + +%% @doc Create a new VM process. The process ID is returned and can be used +%% with for example the define method of this module. +start_link(Table) -> + PortPid = spawn( fun() -> + loop(Table) + end ), + PortPid. + +%% @doc Define some new code on the specified VM, returns the atom ok. +define(GameVM, SourceCode) -> + GameVM ! {define,SourceCode}, + ok. + +%% @doc Execute a user command on the specified VM. This function is +%% asynchronous, and returns ok. +%% @spec user_command(GameVM, User, Command, Args) -> ok +%% GameVM = process IS of VM +%% Player = the player running the command +%% Command = a game command to run +%% Args = arguments for the Command parameter +user_command(GameVM, Player, Command, Args) -> + Ref = make_ref(), + GameVM ! {user_command, Player, Command, Args, self(), Ref}, + ok. + +%% Helper functions + +loop(Table) -> + receive + {define, SourceCode} -> + loop(Table); + {user_command, _User, Command, _Args, _From, _Ref} -> + io:format("GameVM received a message~n"), + ggs_table:notify_all_players(Table, Command), + loop(Table) + end. diff --git a/src/ggs_player.erl b/src/ggs_player.erl index 37c8496..af92ad9 100644 --- a/src/ggs_player.erl +++ b/src/ggs_player.erl @@ -1,5 +1,9 @@ -module(ggs_player). -export([start_link/1, notify/3, get_token/1, stop/2]). +-record(pl_state, + {token, % Player's token + socket, % Player's socket + table}). % Player's table %% @doc This module handles communication between a player and GGS. This module is %%responsible for: @@ -13,14 +17,28 @@ %% identifying the player. %% @spec start_link(Socket::socket()) -> {ok, Pid} | {error, Reason} start_link(Socket) -> - 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()), + {ok, Token} = ggs_coordinator:join_lobby(), + TableStatus = ggs_coordinator:join_table(1337), + case TableStatus of + {ok, Table} -> + loop(#pl_state{socket = Socket, token = Token, table = Table}); + {error, no_such_table} -> + ggs_coordinator:create_table({force, 1337}), + {ok, Table} = ggs_coordinator:join_table(1337), + loop(#pl_state{socket = Socket, token = Token, table = Table}) + end. %% @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) -> - ggs_logger:not_implemented(). + Player ! {notify, From, Message}. %% @doc Get the player token uniquely representing the player. %% @spec get_token() -> string() @@ -36,13 +54,13 @@ stop(_Player,_Table) -> %% 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) +loop(#pl_state{token = Token, socket = Socket, table = Table} = State) -> + receive + {tcp, Socket, Data} -> % Just echo for now.. + io:format("Notifying table..~n"), + ggs_table:notify_game(Table, Token, Data), + loop(State); + {notify, From, Message} -> + gen_tcp:send(Socket, Message), + loop(State) end. diff --git a/src/ggs_table.erl b/src/ggs_table.erl index 1e4f323..53c27e9 100644 --- a/src/ggs_table.erl +++ b/src/ggs_table.erl @@ -5,12 +5,13 @@ %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, - terminate/2, code_change/3]). + terminate/2, code_change/3, notify_all_players/2, notify_game/3, + add_player/2]). -record(state, { token, players, socket, game_vm } ). %% API --export([start_link/2, +-export([start_link/0, add_player/2, remove_player/2, stop/1, @@ -22,9 +23,8 @@ % API implementation % @doc returns a new table -start_link(Token, Socket) -> - GameVM = ggs_gamevm:start_link(), - {ok, Pid} = gen_server:start_link(?MODULE, [Token, Socket, GameVM], []), +start_link() -> + {ok, Pid} = gen_server:start_link(?MODULE, [], []), Pid. %% @private @@ -47,22 +47,34 @@ stop(Table) -> notify(Table, Player, Message) -> gen_server:cast(Table, {notify, Player, Message}). +notify_all_players(Table, Message) -> + gen_server:cast(Table, {notify_all_players, Message}). + +notify_game(Table, From, Message) -> + io:format("Notify game called on"), + erlang:display(Table), + io:format("~n"), + gen_server:cast(Table, {notify_game, Message, From}). + %% ---------------------------------------------------------------------- %% @private -init([Token, Socket, GameVM]) -> - {ok, #state { token = Token, - socket = Socket, +init([]) -> + GameVM = ggs_gamevm_e:start_link(self()), + {ok, #state { game_vm = GameVM, players = [] }}. %% @private handle_call({add_player, Player}, _From, #state { players = Players } = State) -> {reply, ok, State#state { players = [Player | Players] }}; + handle_call({remove_player, Player}, _From, #state { players = Players } = State) -> {reply, ok, State#state { players = Players -- [Player] }}; + handle_call(get_player_list, _From, #state { players = Players } = State) -> {reply, {ok, Players}, State}; + handle_call(Msg, _From, State) -> error_logger:error_report([unknown_msg, Msg]), {reply, ok, State}. @@ -71,11 +83,25 @@ handle_call(Msg, _From, State) -> handle_cast({notify, Player, Message}, #state { game_vm = GameVM } = State) -> case Message of {server, define, Args} -> - ggs_gamevm:define(GameVM, Args); + ggs_gamevm_e:define(GameVM, Args); {game, Command, Args} -> - ggs_gamevm:user_command(GameVM, Player, Command, Args) + ggs_gamevm_e:user_command(GameVM, Player, Command, Args) end, {noreply, State}; + +handle_cast({notify_game, Message, From}, #state { game_vm = GameVM } = State) -> + io:format("notify_game message received~n"), + ggs_gamevm_e:user_command(GameVM, From, Message, ""), + {noreply, State}; + +handle_cast({notify_all_players, Message}, #state{players = Players} = State) -> + io:format("Notifying all players... ~p~n", [Players]), + lists:foreach(fun(P) -> + io:format("Notifying ~p~n", [P]), + ggs_player:notify(P, "Server", Message) + end, Players), + {noreply, State}; + handle_cast(stop, State) -> {stop, normal, State}; handle_cast(Msg, S) -> @@ -100,39 +126,39 @@ code_change(_OldVsn, State, _Extra) -> % Tests -start_link_test() -> - Table = start_link("123", none), - ?assertNot(Table =:= undefined). +%start_link_test() -> +% Table = start_link("123", none), +% ?assertNot(Table =:= undefined). +% +%add_player_test() -> +% Table = start_link("123", none), +% Player = test_player, +% add_player(Table, Player), +% {ok, [Player]} = gen_server:call(Table, get_player_list). -add_player_test() -> - Table = start_link("123", none), - Player = test_player, - add_player(Table, Player), - {ok, [Player]} = gen_server:call(Table, get_player_list). - -remove_player_test() -> - Table = start_link("123", none), - Player = test_player, - Player2 = test_player2, - add_player(Table, Player), - {ok, [Player]} = gen_server:call(Table, get_player_list), - add_player(Table, Player2), - {ok, [Player2, Player]} = gen_server:call(Table, get_player_list), - remove_player(Table, Player), - {ok, [Player2]} = gen_server:call(Table, get_player_list), - remove_player(Table, Player2), - {ok, []} = gen_server:call(Table, get_player_list). - -stop_test() -> - Table = start_link("123", none), - ok = stop(Table). - -% @private -notify_test() -> - Table = start_link("123", none), - Player = test_player, - Message = {server, define, "function helloWorld(x) { }"}, - ok = notify(Table, Player, Message). +%remove_player_test() -> +% Table = start_link("123", none), +% Player = test_player, +% Player2 = test_player2, +% add_player(Table, Player), +% {ok, [Player]} = gen_server:call(Table, get_player_list), +% add_player(Table, Player2), +% {ok, [Player2, Player]} = gen_server:call(Table, get_player_list), +% remove_player(Table, Player), +% {ok, [Player2]} = gen_server:call(Table, get_player_list), +% remove_player(Table, Player2), +% {ok, []} = gen_server:call(Table, get_player_list). +% +%stop_test() -> +% Table = start_link("123", none), +% ok = stop(Table). +% +%% @private +%notify_test() -> +% Table = start_link("123", none), +% Player = test_player, +% Message = {server, define, "function helloWorld(x) { }"}, +% ok = notify(Table, Player, Message). %Message2 = {game, "helloWorld", "test"}, %ok = notify(Table, Player, Message2). - \ No newline at end of file + From b3d8c5ba991192f1cd50fe57abb93466bc8d18bc Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Mon, 21 Feb 2011 15:43:39 +0100 Subject: [PATCH 47/49] added more test --- src/ggs_gamevm.erl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ggs_gamevm.erl b/src/ggs_gamevm.erl index 6493c9f..acfe2fb 100644 --- a/src/ggs_gamevm.erl +++ b/src/ggs_gamevm.erl @@ -120,3 +120,9 @@ user_command_test() -> user_command(GameVM, "'jeena", "thecommand", "theargs'"), ?assertMatch(<<"'jeenathecommandtheargs'">>, gen_server:call(GameVM, {eval, "t;"})). +user_command2_test() -> + GameVM = start_link(test_table), + define(GameVM, "var t = '';\nfunction userCommand(user, command, args) { t = callErlang('erlang time') + ''; }\n"), + user_command(GameVM, "jeena", "test", ""), + io:format("test ~p~n", [binary_to_list(gen_server:call(GameVM, {eval, "t;"}))]), + ?assertMatch(<<"rt">>, gen_server:call(GameVM, {eval, "t;"})). From 08e0be70e2c15446ebac33aba64d66b95093cfe2 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Mon, 21 Feb 2011 20:54:43 +0100 Subject: [PATCH 48/49] fixed test with js callback --- erlang_js | 2 +- src/ggs_gamevm.erl | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/erlang_js b/erlang_js index 5350ed2..2f2785f 160000 --- a/erlang_js +++ b/erlang_js @@ -1 +1 @@ -Subproject commit 5350ed21606606dbee5ecb07e974f2abb9106270 +Subproject commit 2f2785fafb0da6db75810eb6fa97d09c58257588 diff --git a/src/ggs_gamevm.erl b/src/ggs_gamevm.erl index acfe2fb..294eb10 100644 --- a/src/ggs_gamevm.erl +++ b/src/ggs_gamevm.erl @@ -119,10 +119,15 @@ user_command_test() -> define(GameVM, "var t = '';\nfunction userCommand(user, command, args) { t = user + command + args; }\n"), user_command(GameVM, "'jeena", "thecommand", "theargs'"), ?assertMatch(<<"'jeenathecommandtheargs'">>, gen_server:call(GameVM, {eval, "t;"})). + +to_string({A, B, C}) -> + "{" ++ integer_to_list(A) ++ ", " ++ integer_to_list(B) ++ ", " ++ integer_to_list(C) ++ "}". user_command2_test() -> GameVM = start_link(test_table), define(GameVM, "var t = '';\nfunction userCommand(user, command, args) { t = callErlang('erlang time') + ''; }\n"), - user_command(GameVM, "jeena", "test", ""), - io:format("test ~p~n", [binary_to_list(gen_server:call(GameVM, {eval, "t;"}))]), - ?assertMatch(<<"rt">>, gen_server:call(GameVM, {eval, "t;"})). + user_command(GameVM, "", "", ""), + T = to_string(erlang:time()), + io:format("test ~p~n", [T]), + ?assertMatch(T, binary_to_list(gen_server:call(GameVM, {eval, "t;"}))). + From e03f3cf69d475b2aa90a133cdd39835dcc3c1781 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Tue, 22 Feb 2011 00:15:21 +0100 Subject: [PATCH 49/49] better js_erlang_test --- src/ggs_gamevm.erl | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/ggs_gamevm.erl b/src/ggs_gamevm.erl index 294eb10..6dd19a7 100644 --- a/src/ggs_gamevm.erl +++ b/src/ggs_gamevm.erl @@ -120,14 +120,11 @@ user_command_test() -> user_command(GameVM, "'jeena", "thecommand", "theargs'"), ?assertMatch(<<"'jeenathecommandtheargs'">>, gen_server:call(GameVM, {eval, "t;"})). -to_string({A, B, C}) -> - "{" ++ integer_to_list(A) ++ ", " ++ integer_to_list(B) ++ ", " ++ integer_to_list(C) ++ "}". - -user_command2_test() -> +js_erlang_test() -> GameVM = start_link(test_table), define(GameVM, "var t = '';\nfunction userCommand(user, command, args) { t = callErlang('erlang time') + ''; }\n"), user_command(GameVM, "", "", ""), - T = to_string(erlang:time()), - io:format("test ~p~n", [T]), - ?assertMatch(T, binary_to_list(gen_server:call(GameVM, {eval, "t;"}))). + {A, B, C} = erlang:time(), + T = "{" ++ integer_to_list(A) ++ ", " ++ integer_to_list(B) ++ ", " ++ integer_to_list(C) ++ "}", + ?assertMatch(T, binary_to_list(gen_server:call(GameVM, {eval, "t;"}))).