121 lines
4 KiB
Erlang
121 lines
4 KiB
Erlang
-module(ggs_network).
|
|
-export([connect/0,append_key_value_strings_to_dict/2,key_value_string_to_list/1]).
|
|
-export([read/2, send_command/3]).
|
|
|
|
%For quickcheck
|
|
-export([receive_content/1,receive_data/3]).
|
|
|
|
connect() ->
|
|
%{ok,Socket} = gen_tcp:connect("ggs.jeena.net", 9000,[{active, false}]),
|
|
{ok,Socket} = gen_tcp:connect("localhost", 9000,[{active, false}]).
|
|
|
|
read(Socket, Ref) ->
|
|
Content = receive_content(Socket),
|
|
Headers = extract_headers(Content),
|
|
ContentSize = dict:fetch("Content-Size", Headers),
|
|
ContentSizeI = list_to_integer(lists:nth(1, ContentSize)),
|
|
Data = receive_data(Socket, ContentSizeI, ""),
|
|
%io:format("Headers: ~s~n", [Content]),
|
|
%io:format("Data: ~s~n", [Data]),
|
|
received_command(Headers, Data, Ref).
|
|
|
|
receive_content(Socket) ->
|
|
receive_content_(0, "", Socket).
|
|
|
|
receive_content_(Amount, Headers, Socket) ->
|
|
{ok, Char1} = gen_tcp:recv(Socket, 1),
|
|
case Char1 of
|
|
"\n" -> case Amount of
|
|
1 -> Headers;
|
|
_ -> receive_content_(Amount + 1,
|
|
Headers ++ Char1,
|
|
Socket)
|
|
end;
|
|
_ -> receive_content_(0, Headers ++ Char1, Socket)
|
|
end.
|
|
|
|
receive_data(_, 0, Headers) ->
|
|
Headers;
|
|
receive_data(Socket, ContentSize, Headers) ->
|
|
{ok, Char} = gen_tcp:recv(Socket, 1),
|
|
receive_data(Socket, ContentSize - 1, Headers ++ Char).
|
|
|
|
received_command(Headers, Data, Ref) ->
|
|
{ok, CommandList} = dict:find("Client-Command", Headers),
|
|
Command = lists:nth(1, CommandList),
|
|
case Command of
|
|
"hello" ->
|
|
pong_bot:set_game_token(Data, Ref),
|
|
send_command("ready", "", Ref);
|
|
"defined" ->
|
|
ok;
|
|
Command ->
|
|
pong_bot:ggsNetworkReceivedCommandWithArgs(Command, Data, Ref)
|
|
end.
|
|
|
|
make_message(ServerOrGame, Command, Args, Ref) ->
|
|
GameToken = pong_bot:get_game_token(Ref),
|
|
StrGameToken = string:concat("Token: ", GameToken),
|
|
StrGameTokenln = string:concat(StrGameToken, "\n"),
|
|
StrCommand = string:concat("-Command: ", Command),
|
|
StrCommandln = string:concat(StrCommand, "\n"),
|
|
StrFullCommand = string:concat(ServerOrGame, StrCommandln),
|
|
StrContentLength = string:concat("Content-Length: ", integer_to_list(length(Args))),
|
|
StrContentLengthln = string:concat(StrContentLength, "\n\n"),
|
|
StrTokenCommand = string:concat(StrGameTokenln, StrFullCommand),
|
|
Message = string:concat(StrTokenCommand, StrContentLengthln),
|
|
MessageWithArgs = string:concat(Message, list_concat(Args,[])),
|
|
MessageWithArgs.
|
|
|
|
send_command(Command, Args, Ref) ->
|
|
write(make_message("Game", Command, Args, Ref), Ref).
|
|
|
|
write(Message, Ref) ->
|
|
Socket = gen_server:call({global, {pong_bot, Ref}}, socket),
|
|
gen_tcp:send(Socket, Message).
|
|
|
|
list_concat([],Ret) ->
|
|
Ret;
|
|
list_concat([E|ES],Ret) ->
|
|
NewRet = string:concat(Ret,E),
|
|
list_concat(ES,NewRet).
|
|
|
|
%%%Packet parsing.%%%
|
|
|
|
|
|
extract_headers(Source) ->
|
|
HeaderList = string:tokens(Source, "\n"),
|
|
key_value_strings_to_dict(HeaderList).
|
|
|
|
%%%Low-level internals.%%%
|
|
|
|
|
|
%%["K1: V1","K2: V2","KN: VN" ...] -> Dict
|
|
key_value_strings_to_dict(Strings) ->
|
|
Dict = dict:new(),
|
|
append_key_value_strings_to_dict(Strings,Dict).
|
|
|
|
%%["K1: V1","K2: V2","KN: VN" ...], Dict -> NewDict
|
|
append_key_value_strings_to_dict([Str|Strings],Dict) ->
|
|
KeyValueList = key_value_string_to_list(Str),
|
|
case length(KeyValueList) of
|
|
2 ->
|
|
NewDict = append_string_pair_to_dict(Dict,lists:nth(1,KeyValueList),lists:nth(2,KeyValueList)),
|
|
append_key_value_strings_to_dict(Strings,NewDict);
|
|
_ ->
|
|
append_key_value_strings_to_dict(Strings,Dict)
|
|
end;
|
|
append_key_value_strings_to_dict([],Dict) ->
|
|
Dict.
|
|
|
|
|
|
%%"Hello: "World!" -> ["Hello","World!"]
|
|
key_value_string_to_list(KeyValueString) ->
|
|
string:tokens(KeyValueString, ": ").
|
|
|
|
|
|
%%Append a key str1 and a value str2 to the dict Dict
|
|
append_string_pair_to_dict(Dict, Str1, Str2) ->
|
|
dict:append(Str1, Str2, Dict).
|
|
|
|
|