bad merge.
Conflicts: src/ggs_server.erl
This commit is contained in:
commit
25ad4fb37b
19 changed files with 300 additions and 123 deletions
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
*.swp
|
||||||
|
*.dump
|
||||||
|
*.beam
|
||||||
|
Mnesia.*
|
5
.gitmodules
vendored
5
.gitmodules
vendored
|
@ -1,6 +1,3 @@
|
||||||
[submodule "erlang_js"]
|
[submodule "erlang_js"]
|
||||||
path = erlang_js
|
path = erlang_js
|
||||||
url = https://github.com/basho/erlang_js.git
|
url = https://github.com/jonte/erlang_js.git
|
||||||
[submodule "erlv8"]
|
|
||||||
path = erlv8
|
|
||||||
url = https://github.com/beamjs/erlv8.git
|
|
||||||
|
|
9
HOWTO
9
HOWTO
|
@ -1,18 +1,21 @@
|
||||||
|
PREREQUISITES:
|
||||||
|
python version 2.x set to default.
|
||||||
|
|
||||||
INSTALL
|
INSTALL
|
||||||
1. Cd into directory where you to have the project
|
1. Cd into directory where you to have the project
|
||||||
2. git-clone git@github.com:jeena/GGS.git (remember to have a local key)
|
2. git clone git@github.com:jeena/GGS.git (remember to have a local key)
|
||||||
3. cd GGS/
|
3. cd GGS/
|
||||||
4. git submodule init
|
4. git submodule init
|
||||||
5. git submodule update
|
5. git submodule update
|
||||||
6. cd erlang_js
|
6. cd erlang_js
|
||||||
7. make
|
7. make
|
||||||
8. make test (If not all tests are passed then you are screwed!)
|
8. make test (Optional. It has to work though.)
|
||||||
10. cd ../
|
10. cd ../
|
||||||
11. ./build
|
11. ./build
|
||||||
12.
|
12.
|
||||||
|
|
||||||
USAGE
|
USAGE
|
||||||
1. start a second terminal
|
1. start a second terminal
|
||||||
2. telnet localhost 7000
|
2. in new terminal do command: ./python_client 9000
|
||||||
3. back to first terminal
|
3. back to first terminal
|
||||||
4. ./start
|
4. ./start
|
||||||
|
|
2
build
2
build
|
@ -3,4 +3,4 @@
|
||||||
for i in `find src -name "*.erl"`
|
for i in `find src -name "*.erl"`
|
||||||
do
|
do
|
||||||
erlc -o ebin $i
|
erlc -o ebin $i
|
||||||
done
|
done
|
17
client
Normal file
17
client
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#!/usr/bin/env ruby -wKU
|
||||||
|
|
||||||
|
require 'socket' # Sockets are in standard library
|
||||||
|
|
||||||
|
hostname = 'localhost'
|
||||||
|
port = 7000
|
||||||
|
|
||||||
|
s = TCPSocket.open(hostname, port)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
s.print(q.chop)
|
||||||
|
|
||||||
|
while line = s.gets # Read lines from the socket
|
||||||
|
puts "Got Echo: " + line.chop # And print with platform line terminator
|
||||||
|
end
|
||||||
|
s.close # Close the socket when done
|
|
@ -3,8 +3,7 @@
|
||||||
{vsn, "0.1.0"},
|
{vsn, "0.1.0"},
|
||||||
{modules, [
|
{modules, [
|
||||||
ggs_app,
|
ggs_app,
|
||||||
ggs_sup,
|
ggs_sup
|
||||||
ggs_server
|
|
||||||
]},
|
]},
|
||||||
{registered, [ggs_sup]},
|
{registered, [ggs_sup]},
|
||||||
{applications, [kernel, stdlib]},
|
{applications, [kernel, stdlib]},
|
||||||
|
|
1
erlv8
1
erlv8
|
@ -1 +0,0 @@
|
||||||
Subproject commit 688e5036864eed01f7aefb6ee8b3a4c22961012f
|
|
|
@ -12,8 +12,16 @@
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
GameServer.addGame(game_name, main());
|
GameServer.addGame(game_name, main());
|
||||||
GameServer.addClient(game_name, new TicTacToeClient(frames.player1.document.getElementById("p1"), GameServer));
|
GameServer.addClient(
|
||||||
GameServer.addClient(game_name, new TicTacToeClient(frames.player2.document.getElementById("p2"), GameServer));
|
game_name,
|
||||||
|
new TicTacToeClient(frames.player1.document.getElementById("p1"),
|
||||||
|
GameServer
|
||||||
|
));
|
||||||
|
GameServer.addClient(
|
||||||
|
game_name,
|
||||||
|
new TicTacToeClient(frames.player2.document.getElementById("p2"),
|
||||||
|
GameServer
|
||||||
|
));
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<link rel="stylesheet" href="css/screen.css" type="text/css" media="screen">
|
<link rel="stylesheet" href="css/screen.css" type="text/css" media="screen">
|
||||||
|
|
0
games/tic-tac-toe-js/proxy.rb
Normal file
0
games/tic-tac-toe-js/proxy.rb
Normal file
|
@ -1,22 +1,78 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
import sys
|
import sys, time, socket
|
||||||
|
|
||||||
import socket
|
|
||||||
|
|
||||||
HOST = 'localhost' # The remote host
|
HOST = 'localhost' # The remote host
|
||||||
PORT = int(sys.argv[1]) # The same port as used by the server
|
PORT = int(sys.argv[1]) # The same port as used by the server
|
||||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
s.connect((HOST, PORT))
|
s.connect((HOST, PORT))
|
||||||
s.send('__hello 0')
|
|
||||||
|
# Say hello
|
||||||
|
|
||||||
|
print "Saying hello to server"
|
||||||
|
s.send(
|
||||||
|
"Command: hello\n\
|
||||||
|
Content-Type: text\n\
|
||||||
|
Content-Length: 0\n\
|
||||||
|
\n\
|
||||||
|
")
|
||||||
fs = s.makefile()
|
fs = s.makefile()
|
||||||
data = fs.readline()
|
data = fs.readline()
|
||||||
token = data.split(" ")[0]
|
token = data.split(" ")[0]
|
||||||
print "Token:", token
|
print "Token:", token
|
||||||
|
print "Data: ", ' '.join(data.split(" ")[1:])
|
||||||
|
|
||||||
s.send(token+" __echo 0 msg")
|
# Define ourselves a function!
|
||||||
data = s.recv(1024)
|
|
||||||
print data
|
print "Defining a function called myFun"
|
||||||
|
s.send(
|
||||||
|
"Token: %s\n\
|
||||||
|
Command: define\n\
|
||||||
|
Content-Type: text\n\
|
||||||
|
Content-Length: 49\n\
|
||||||
|
\n\
|
||||||
|
function myFun() {return 'Hello World!' ;}" % token)
|
||||||
|
fs = s.makefile()
|
||||||
|
data = fs.readline()
|
||||||
|
print "Token:", token
|
||||||
|
print "Data: ", ' '.join(data.split(" ")[1:])
|
||||||
|
|
||||||
|
# Call that function!
|
||||||
|
|
||||||
|
print "Calling myFun"
|
||||||
|
s.send(
|
||||||
|
"Token: %s\n\
|
||||||
|
Command: call\n\
|
||||||
|
Content-Type: text\n\
|
||||||
|
Content-Length: 6\n\
|
||||||
|
\n\
|
||||||
|
myFun" % token)
|
||||||
|
fs = s.makefile()
|
||||||
|
data = fs.readline()
|
||||||
|
print "Token:", token
|
||||||
|
print "Data: ", ' '.join(data.split(" ")[1:])
|
||||||
|
|
||||||
s.close()
|
s.close()
|
||||||
|
|
||||||
|
"""
|
||||||
|
HOST = 'localhost' # The remote host
|
||||||
|
PORT = int(sys.argv[1]) # The same port as used by the server
|
||||||
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
s.connect((HOST, PORT))
|
||||||
|
# Call that function!
|
||||||
|
|
||||||
|
print "Calling myFun"
|
||||||
|
s.send(
|
||||||
|
"Token: %s\n\
|
||||||
|
Command: call\n\
|
||||||
|
Content-Type: text\n\
|
||||||
|
Content-Length: 6\n\
|
||||||
|
\n\
|
||||||
|
myFun" % token)
|
||||||
|
fs = s.makefile()
|
||||||
|
data = fs.readline()
|
||||||
|
print "Token:", token
|
||||||
|
print "Data: ", ' '.join(data.split(" ")[1:])
|
||||||
|
|
||||||
|
s.close()
|
||||||
|
"""
|
||||||
|
|
41
src/ggs_backup.erl
Normal file
41
src/ggs_backup.erl
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
-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.
|
68
src/ggs_mnesia_controller_server.erl
Normal file
68
src/ggs_mnesia_controller_server.erl
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
-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
|
||||||
|
%%-----------------------------------------------------
|
|
@ -1,36 +1,39 @@
|
||||||
%% This is a parser for JSON implemented using mochijson2
|
|
||||||
%% Don't feed it anything other than valid JSON.
|
|
||||||
|
|
||||||
-module(ggs_protocol).
|
-module(ggs_protocol).
|
||||||
-export([parse/1]).
|
-export([parse/1]).
|
||||||
|
|
||||||
parse(Data) ->
|
parse(Data) ->
|
||||||
Message = string:tokens(Data, " "),
|
Message =string:tokens(Data, "\n"),
|
||||||
io:format(Message),
|
% Turn "A: B" pairs into "{A, B}" tuples, for searching.
|
||||||
case Message of
|
MsgKV = lists:map((fun(Str) ->
|
||||||
["__get_vms"] ->
|
list_to_tuple(string:tokens(Str, ": ")) end
|
||||||
{vms};
|
), Message),
|
||||||
[RefID, "__error", Size, Message ] ->
|
% Hacky way to build a tuple, filter out not_found later on
|
||||||
{ok, you_said_error};
|
Processed = {
|
||||||
[_, "__boot", _ ] ->
|
case lists:keysearch("Command", 1, MsgKV) of
|
||||||
{ok, you_said_boot};
|
{value,{_, "define"}} ->
|
||||||
[RefID, "__stop", _] ->
|
define;
|
||||||
{ok, you_said_stop};
|
{value,{_, "call"}} ->
|
||||||
[RefID, "__start", _] ->
|
call;
|
||||||
{ok, you_said_start};
|
{value,{_, "hello"}} ->
|
||||||
["__hello", _] ->
|
hello;
|
||||||
{hello};
|
false ->
|
||||||
[RefID, "__define",_, JavaScript ] ->
|
not_found
|
||||||
{ok, you_said_define};
|
end,
|
||||||
[RefID, "__echo", Length, Msg ] ->
|
case lists:keysearch("Token", 1, MsgKV) of
|
||||||
{Ref, _} = string:to_integer(RefID),
|
{value,{_, Value}} ->
|
||||||
{echo, Ref, Length, Msg};
|
Value;
|
||||||
[RefID, Command, _, Parameter ] ->
|
false ->
|
||||||
{cmd, Command, Parameter};
|
not_found
|
||||||
%% Debugging tools, not for production use
|
end,
|
||||||
["__crash"] ->
|
case lists:keysearch("Content-Length", 1, MsgKV) of
|
||||||
{crash, 0};
|
{value,{_, Value}} ->
|
||||||
%% End debugging tools
|
{Length, _} = string:to_integer(Value),
|
||||||
Other ->
|
[_|Cont] = re:split(Data, "\n\n",[{return,list}]),
|
||||||
{out_of_bounds, Other}
|
Content = string:join(Cont, "\n\n"),
|
||||||
end.
|
Payload = string:substr(Content,1,Length),
|
||||||
|
Payload;
|
||||||
|
false ->
|
||||||
|
not_found
|
||||||
|
end
|
||||||
|
},
|
||||||
|
gen_server:cast(ggs_server, Processed).
|
||||||
|
|
|
@ -1,54 +0,0 @@
|
||||||
%%%----------------------------------------------------
|
|
||||||
%%% @author Jonatan Pålsson <Jonatan.p@gmail.com>
|
|
||||||
%%% @copyright 2010 Jonatan Pålsson
|
|
||||||
%%% @end
|
|
||||||
%%%----------------------------------------------------
|
|
||||||
|
|
||||||
-module(ggs_server).
|
|
||||||
|
|
||||||
% import
|
|
||||||
-import(ggs_network).
|
|
||||||
|
|
||||||
%% API
|
|
||||||
-export([start_link/0, start_link/1, stop/0 ]).
|
|
||||||
%-export([crash/0, vms/0, hello/0, echo/0]).
|
|
||||||
-export([get_count/0]).
|
|
||||||
|
|
||||||
|
|
||||||
%%%====================================================
|
|
||||||
%%% API
|
|
||||||
%%%====================================================
|
|
||||||
|
|
||||||
%%-----------------------------------------------------
|
|
||||||
%% @doc Starts the server
|
|
||||||
%% @end
|
|
||||||
%%-----------------------------------------------------
|
|
||||||
start_link() ->
|
|
||||||
ggs_network:start_link().
|
|
||||||
|
|
||||||
start_link(Port) ->
|
|
||||||
ggs_network:start_link(Port).
|
|
||||||
|
|
||||||
|
|
||||||
%%-----------------------------------------------------
|
|
||||||
%% @doc Fetches the number of requests made to this server
|
|
||||||
%% @spec get_count() -> {ok, Count}
|
|
||||||
%% where
|
|
||||||
%% Count = integer()
|
|
||||||
%% @end
|
|
||||||
%%-----------------------------------------------------
|
|
||||||
get_count() ->
|
|
||||||
ggs_network:get_count(get_count).
|
|
||||||
|
|
||||||
%crash() -> gss_network:crash().
|
|
||||||
%vms() -> gss_network:vms().
|
|
||||||
%hello() -> gss_network:hello().
|
|
||||||
%echo() -> gss_network:echo().
|
|
||||||
|
|
||||||
%%-----------------------------------------------------
|
|
||||||
%% @doc Stops the server.
|
|
||||||
%% @spec stop() -> ok
|
|
||||||
%% @end
|
|
||||||
%%-----------------------------------------------------
|
|
||||||
stop() ->
|
|
||||||
ggs_network:stop().
|
|
48
src/ggs_server_sup.erl
Normal file
48
src/ggs_server_sup.erl
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
-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}}.
|
||||||
|
|
|
@ -17,12 +17,12 @@ start_link(Port) ->
|
||||||
supervisor:start_link({local, ?SERVER}, ?MODULE, [Port]).
|
supervisor:start_link({local, ?SERVER}, ?MODULE, [Port]).
|
||||||
|
|
||||||
init([Port]) ->
|
init([Port]) ->
|
||||||
Server = {ggs_server,
|
Server = {ggs_server_sup,
|
||||||
{ggs_server, start_link, [Port]},
|
{ggs_server_sup, start_link, [Port]},
|
||||||
permanent,
|
permanent,
|
||||||
2000,
|
2000,
|
||||||
worker,
|
worker,
|
||||||
[ggs_server]
|
[ggs_server_sup]
|
||||||
},
|
},
|
||||||
Children = [Server],
|
Children = [Server],
|
||||||
|
|
||||||
|
|
|
@ -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).
|
|
|
@ -3,4 +3,5 @@
|
||||||
|
|
||||||
start() ->
|
start() ->
|
||||||
application:start(inets),
|
application:start(inets),
|
||||||
|
application:start(erlang_js),
|
||||||
application:start(ggs).
|
application:start(ggs).
|
||||||
|
|
2
start
2
start
|
@ -1,3 +1,3 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
erl -boot start_sasl -pa erlang_js/ebin/ -pa ebin -pa src -s start_ggs
|
erl -sname ggs -mnesia -boot start_sasl -pa erlang_js/ebin/ -pa ebin -pa src -s start_ggs
|
||||||
|
|
Reference in a new issue