-module(ggs_network). -export([connect/0,append_key_value_strings_to_dict/2,key_value_string_to_list/1]). -export([read/1, send_command/2]). connect() -> {ok,Socket} = gen_tcp:connect("localhost", 9000,[{active, false}]), Socket. read(Socket) -> 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). 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) -> {ok, CommandList} = dict:find("Client-Command", Headers), Command = lists:nth(1, CommandList), case Command of "hello" -> io:format("Set game token~n"), pong_bot:set_game_token(Data), send_command("ready", ""); "defined" -> io:format("Defined~n"), ok; Command -> pong_bot:ggsNetworkReceivedCommandWithArgs(Command, Data) end. make_message(ServerOrGame, Command, Args) -> GameToken = pong_bot:get_game_token(), 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) -> write(make_message("Game", Command, Args)). write(Message) -> Socket = gen_server:call({global, pong_bot}, 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). %extract_data([]) -> % []; %extract_data([E|ES]) -> % io:format("~n~s~n~n~n~n", [E]), % KeyValueList = key_value_string_to_list(E), % case length(KeyValueList) of % 2 -> % extract_data(ES); % _ -> % E % end. %%%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).