aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorMicael Karlberg <[email protected]>2018-07-04 15:18:18 +0200
committerMicael Karlberg <[email protected]>2018-09-18 14:50:18 +0200
commite39e25d84405e13ca0ce476e3ba473510e5548de (patch)
tree217ac95a480968372496b2b3b5d978826860f076 /lib
parentdce68cf27f2dd1721bd316594a29ff99a0de7bb9 (diff)
downloadotp-e39e25d84405e13ca0ce476e3ba473510e5548de.tar.gz
otp-e39e25d84405e13ca0ce476e3ba473510e5548de.tar.bz2
otp-e39e25d84405e13ca0ce476e3ba473510e5548de.zip
[socket-nif] Fixed (dgram) recv
Fixed handling of recvfrom (used by dgram sockets). Had forgot to do select(read) when we got block from the call to recvfrom. Argh! Also updated the (simple) test server and client to to be able to use udp (dgram+udp). OTP-14831
Diffstat (limited to 'lib')
-rw-r--r--lib/kernel/test/Makefile1
-rw-r--r--lib/kernel/test/socket_client.erl252
-rw-r--r--lib/kernel/test/socket_lib.erl129
-rw-r--r--lib/kernel/test/socket_server.erl237
4 files changed, 462 insertions, 157 deletions
diff --git a/lib/kernel/test/Makefile b/lib/kernel/test/Makefile
index 07e7922d3d..051fac25af 100644
--- a/lib/kernel/test/Makefile
+++ b/lib/kernel/test/Makefile
@@ -25,6 +25,7 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
# ----------------------------------------------------
SOCKET_MODULES = \
+ socket_lib \
socket_server \
socket_client
diff --git a/lib/kernel/test/socket_client.erl b/lib/kernel/test/socket_client.erl
index a284777046..0b570e1f71 100644
--- a/lib/kernel/test/socket_client.erl
+++ b/lib/kernel/test/socket_client.erl
@@ -1,17 +1,34 @@
-%%%-------------------------------------------------------------------
-%%% @author Micael Karlberg <[email protected]>
-%%% @copyright (C) 2018, Micael Karlberg
-%%% @doc
-%%%
-%%% @end
-%%% Created : 27 Jun 2018 by Micael Karlberg <[email protected]>
-%%%-------------------------------------------------------------------
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
-module(socket_client).
--export([start/1]).
+-export([
+ start/1,
+ start_tcp/1, start_tcp/2,
+ start_udp/1, start_udp/2
+ ]).
+
+-define(LIB, socket_lib).
--define(REQ, 0).
--define(REP, 1).
+-record(client, {socket, type, dest, msg_id = 1}).
start(Port) ->
start_tcp(Port).
@@ -19,22 +36,77 @@ start(Port) ->
start_tcp(Port) ->
start(inet, stream, tcp, Port).
+start_tcp(Addr, Port) when (size(Addr) =:= 4) ->
+ start(inet, stream, tcp, Addr, Port);
+start_tcp(Addr, Port) when (size(Addr) =:= 8) ->
+ start(inet6, stream, tcp, Addr, Port).
+
+
+start_udp(Port) ->
+ start(inet, dgram, udp, Port).
+
+start_udp(Addr, Port) when (size(Addr) =:= 4) ->
+ start(inet, dgram, udp, Addr, Port);
+start_udp(Addr, Port) when (size(Addr) =:= 8) ->
+ start(inet6, dgram, udp, Addr, Port).
+
+
start(Domain, Type, Proto, Port) ->
+ start(Domain, Type, Proto, which_addr(Domain), Port).
+
+start(Domain, Type, Proto, Addr, Port) ->
+ put(sname, "starter"),
+ SA = #{family => Domain,
+ addr => Addr,
+ port => Port},
+ do_start(Domain, Type, Proto, SA).
+
+do_start(Domain, stream = Type, Proto, SA) ->
try do_init(Domain, Type, Proto) of
Sock ->
- connect(Sock, Domain, Port),
+ connect(Sock, SA),
+ i("connected: "
+ "~n From: ~p"
+ "~n To: ~p",
+ [
+ case socket:sockname(Sock) of
+ {ok, Name} -> Name;
+ {error, _} = NE -> NE
+ end,
+ case socket:peername(Sock) of
+ {ok, Name} -> Name;
+ {error, _} = PE -> PE
+ end
+ ]),
%% Give the server some time...
- p("wait some", []),
- %% sleep(5000),
+ i("wait some", []),
+ ?LIB:sleep(5000),
%% ok = socket:close(Sock),
- send_loop(Sock)
+ send_loop(#client{socket = Sock,
+ type = Type})
+ catch
+ throw:E ->
+ e("Failed initiate: "
+ "~n Error: ~p", [E])
+ end;
+do_start(Domain, dgram = Type, Proto, SA) ->
+ try do_init(Domain, Type, Proto) of
+ Sock ->
+ %% Give the server some time...
+ i("wait some", []),
+ ?LIB:sleep(5000),
+ %% ok = socket:close(Sock),
+ send_loop(#client{socket = Sock,
+ type = Type,
+ dest = SA})
catch
throw:E ->
e("Failed initiate: "
"~n Error: ~p", [E])
end.
-do_init(Domain, Type, Proto) ->
+
+do_init(Domain, stream = Type, Proto) ->
i("try (socket) open"),
Sock = case socket:open(Domain, Type, Proto) of
{ok, S} ->
@@ -48,8 +120,23 @@ do_init(Domain, Type, Proto) ->
Sock;
{error, BReason} ->
throw({bind, BReason})
+ end;
+do_init(Domain, dgram = Type, Proto) ->
+ i("try (socket) open"),
+ Sock = case socket:open(Domain, Type, Proto) of
+ {ok, S} ->
+ S;
+ {error, OReason} ->
+ throw({open, OReason})
+ end,
+ case socket:bind(Sock, any) of
+ {ok, _} ->
+ Sock;
+ {error, BReason} ->
+ throw({bind, BReason})
end.
+
which_addr(Domain) ->
Iflist = case inet:getifaddrs() of
{ok, IFL} ->
@@ -60,16 +147,11 @@ which_addr(Domain) ->
which_addr(Domain, Iflist).
-connect(Sock, Domain, Port) ->
- Addr = which_addr(Domain),
- SA = #{family => Domain,
- addr => Addr,
- port => Port},
+connect(Sock, SA) ->
i("try (socket) connect to:"
"~n ~p", [SA]),
case socket:connect(Sock, SA) of
ok ->
- i("connected"),
ok;
{error, Reason} ->
e("connect failure: "
@@ -78,22 +160,23 @@ connect(Sock, Domain, Port) ->
end.
-send_loop(Sock) ->
- send_loop(Sock, 1).
-
-send_loop(Sock, N) when (N =< 10) ->
+send_loop(#client{msg_id = N} = C) when (N =< 10) ->
i("try send request ~w", [N]),
- Req = enc_req_msg(N, "hejsan"),
- case socket:send(Sock, Req) of
+ Req = ?LIB:enc_req_msg(N, "hejsan"),
+ case send(C, Req) of
ok ->
i("request ~w sent - now try read answer", [N]),
- case socket:recv(Sock, 0) of
- {ok, Msg} ->
- i("received ~w bytes of data", [size(Msg)]),
- case dec_msg(Msg) of
+ case recv(C) of
+ {ok, {Source, Msg}} ->
+ i("received ~w bytes of data~s",
+ [size(Msg), case Source of
+ undefined -> "";
+ _ -> ?LIB:f(" from:~n ~p", [Source])
+ end]),
+ case ?LIB:dec_msg(Msg) of
{reply, N, Reply} ->
i("received reply ~w: ~p", [N, Reply]),
- send_loop(Sock, N+1)
+ send_loop(C#client{msg_id = N+1})
end;
{error, RReason} ->
e("Failed recv response for request ~w: "
@@ -105,7 +188,7 @@ send_loop(Sock, N) when (N =< 10) ->
"~n ~p", [SReason]),
exit({failed_send, SReason})
end;
-send_loop(Sock, _N) ->
+send_loop(#client{socket = Sock}) ->
i("we are done - close the socket when: "
"~n ~p", [socket:info()]),
ok = socket:close(Sock),
@@ -113,6 +196,25 @@ send_loop(Sock, _N) ->
"~n ~p", [socket:info()]).
+send(#client{socket = Sock, type = stream}, Msg) ->
+ socket:send(Sock, Msg);
+send(#client{socket = Sock, type = dgram, dest = Dest}, Msg) ->
+ %% i("try send to: "
+ %% "~n ~p", [Dest]),
+ %% ok = socket:setopt(Sock, otp, debug, true),
+ socket:sendto(Sock, Msg, Dest).
+
+recv(#client{socket = Sock, type = stream}) ->
+ case socket:recv(Sock) of
+ {ok, Msg} ->
+ {ok, {undefined, Msg}};
+ {error, _} = ERROR ->
+ ERROR
+ end;
+recv(#client{socket = Sock, type = dgram}) ->
+ socket:recvfrom(Sock).
+
+
which_addr(_Domain, []) ->
throw(no_address);
which_addr(Domain, [{Name, IFO}|_IFL]) when (Name =/= "lo") ->
@@ -130,68 +232,66 @@ which_addr2(Domain, [_|IFO]) ->
%% ---
-enc_req_msg(N, Data) ->
- enc_msg(?REQ, N, Data).
+%% enc_req_msg(N, Data) ->
+%% enc_msg(?REQ, N, Data).
-enc_rep_msg(N, Data) ->
- enc_msg(?REP, N, Data).
+%% enc_rep_msg(N, Data) ->
+%% enc_msg(?REP, N, Data).
-enc_msg(Type, N, Data) when is_list(Data) ->
- enc_msg(Type, N, list_to_binary(Data));
-enc_msg(Type, N, Data)
- when is_integer(Type) andalso is_integer(N) andalso is_binary(Data) ->
- <<Type:32/integer, N:32/integer, Data/binary>>.
+%% enc_msg(Type, N, Data) when is_list(Data) ->
+%% enc_msg(Type, N, list_to_binary(Data));
+%% enc_msg(Type, N, Data)
+%% when is_integer(Type) andalso is_integer(N) andalso is_binary(Data) ->
+%% <<Type:32/integer, N:32/integer, Data/binary>>.
-dec_msg(<<?REQ:32/integer, N:32/integer, Data/binary>>) ->
- {request, N, Data};
-dec_msg(<<?REP:32/integer, N:32/integer, Data/binary>>) ->
- {reply, N, Data}.
+%% dec_msg(<<?REQ:32/integer, N:32/integer, Data/binary>>) ->
+%% {request, N, Data};
+%% dec_msg(<<?REP:32/integer, N:32/integer, Data/binary>>) ->
+%% {reply, N, Data}.
%% ---
-sleep(T) ->
- receive after T -> ok end.
+%% sleep(T) ->
+%% receive after T -> ok end.
%% ---
-formated_timestamp() ->
- format_timestamp(os:timestamp()).
+%% formated_timestamp() ->
+%% format_timestamp(os:timestamp()).
-format_timestamp(Now) ->
- N2T = fun(N) -> calendar:now_to_local_time(N) end,
- format_timestamp(Now, N2T, true).
+%% format_timestamp(Now) ->
+%% N2T = fun(N) -> calendar:now_to_local_time(N) end,
+%% format_timestamp(Now, N2T, true).
-format_timestamp({_N1, _N2, N3} = N, N2T, true) ->
- FormatExtra = ".~.2.0w",
- ArgsExtra = [N3 div 10000],
- format_timestamp(N, N2T, FormatExtra, ArgsExtra);
-format_timestamp({_N1, _N2, _N3} = N, N2T, false) ->
- FormatExtra = "",
- ArgsExtra = [],
- format_timestamp(N, N2T, FormatExtra, ArgsExtra).
+%% format_timestamp({_N1, _N2, N3} = N, N2T, true) ->
+%% FormatExtra = ".~.2.0w",
+%% ArgsExtra = [N3 div 10000],
+%% format_timestamp(N, N2T, FormatExtra, ArgsExtra);
+%% format_timestamp({_N1, _N2, _N3} = N, N2T, false) ->
+%% FormatExtra = "",
+%% ArgsExtra = [],
+%% format_timestamp(N, N2T, FormatExtra, ArgsExtra).
-format_timestamp(N, N2T, FormatExtra, ArgsExtra) ->
- {Date, Time} = N2T(N),
- {YYYY,MM,DD} = Date,
- {Hour,Min,Sec} = Time,
- FormatDate =
- io_lib:format("~.4w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w" ++ FormatExtra,
- [YYYY, MM, DD, Hour, Min, Sec] ++ ArgsExtra),
- lists:flatten(FormatDate).
+%% format_timestamp(N, N2T, FormatExtra, ArgsExtra) ->
+%% {Date, Time} = N2T(N),
+%% {YYYY,MM,DD} = Date,
+%% {Hour,Min,Sec} = Time,
+%% FormatDate =
+%% io_lib:format("~.4w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w" ++ FormatExtra,
+%% [YYYY, MM, DD, Hour, Min, Sec] ++ ArgsExtra),
+%% lists:flatten(FormatDate).
%% ---
e(F, A) ->
- p("<ERROR> " ++ F, A).
+ ?LIB:e(F, A).
i(F) ->
- i(F, []).
+ ?LIB:i(F).
+
i(F, A) ->
- p("*** " ++ F, A).
-
-p(F, A) ->
- io:format("[client,~p][~s] " ++ F ++ "~n", [self(),formated_timestamp()|A]).
+ ?LIB:i(F, A).
diff --git a/lib/kernel/test/socket_lib.erl b/lib/kernel/test/socket_lib.erl
new file mode 100644
index 0000000000..0eed81d61a
--- /dev/null
+++ b/lib/kernel/test/socket_lib.erl
@@ -0,0 +1,129 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(socket_lib).
+
+-export([
+ sleep/1,
+ enc_req_msg/2, enc_rep_msg/2,
+ enc_msg/3, dec_msg/1,
+ request/3, reply/4,
+ f/2,
+ i/1, i/2,
+ e/2
+ ]).
+
+
+-define(REQ, 0).
+-define(REP, 1).
+
+
+%% ---
+
+sleep(T) ->
+ receive after T -> ok end.
+
+
+%% ---
+
+enc_req_msg(N, Data) ->
+ enc_msg(?REQ, N, Data).
+
+enc_rep_msg(N, Data) ->
+ enc_msg(?REP, N, Data).
+
+enc_msg(Type, N, Data) when is_list(Data) ->
+ enc_msg(Type, N, list_to_binary(Data));
+enc_msg(Type, N, Data)
+ when is_integer(Type) andalso is_integer(N) andalso is_binary(Data) ->
+ <<Type:32/integer, N:32/integer, Data/binary>>.
+
+dec_msg(<<?REQ:32/integer, N:32/integer, Data/binary>>) ->
+ {request, N, Data};
+dec_msg(<<?REP:32/integer, N:32/integer, Data/binary>>) ->
+ {reply, N, Data}.
+
+
+%% ---
+
+request(Tag, Pid, Request) ->
+ Ref = make_ref(),
+ Pid ! {Tag, self(), Ref, Request},
+ receive
+ {Tag, Pid, Ref, Reply} ->
+ Reply
+ end.
+
+reply(Tag, Pid, Ref, Reply) ->
+ Pid ! {Tag, self(), Ref, Reply}.
+
+
+%% ---
+
+f(F, A) ->
+ lists:flatten(io_lib:format(F, A)).
+
+
+%% ---
+
+e(F, A) ->
+ p("<ERROR> " ++ F, A).
+
+i(F) ->
+ i(F, []).
+i(F, A) ->
+ p("*** " ++ F, A).
+
+p(F, A) ->
+ p(get(sname), F, A).
+
+p(SName, F, A) ->
+ io:format("[~s,~p][~s] " ++ F ++ "~n",
+ [SName,self(),formated_timestamp()|A]).
+
+
+%% ---
+
+formated_timestamp() ->
+ format_timestamp(os:timestamp()).
+
+format_timestamp(Now) ->
+ N2T = fun(N) -> calendar:now_to_local_time(N) end,
+ format_timestamp(Now, N2T, true).
+
+format_timestamp({_N1, _N2, N3} = N, N2T, true) ->
+ FormatExtra = ".~.2.0w",
+ ArgsExtra = [N3 div 10000],
+ format_timestamp(N, N2T, FormatExtra, ArgsExtra);
+format_timestamp({_N1, _N2, _N3} = N, N2T, false) ->
+ FormatExtra = "",
+ ArgsExtra = [],
+ format_timestamp(N, N2T, FormatExtra, ArgsExtra).
+
+format_timestamp(N, N2T, FormatExtra, ArgsExtra) ->
+ {Date, Time} = N2T(N),
+ {YYYY,MM,DD} = Date,
+ {Hour,Min,Sec} = Time,
+ FormatDate =
+ io_lib:format("~.4w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w" ++ FormatExtra,
+ [YYYY, MM, DD, Hour, Min, Sec] ++ ArgsExtra),
+ lists:flatten(FormatDate).
+
+
diff --git a/lib/kernel/test/socket_server.erl b/lib/kernel/test/socket_server.erl
index dde605b624..702f040434 100644
--- a/lib/kernel/test/socket_server.erl
+++ b/lib/kernel/test/socket_server.erl
@@ -1,21 +1,34 @@
-%%%-------------------------------------------------------------------
-%%% @author Micael Karlberg <[email protected]>
-%%% @copyright (C) 2018, Micael Karlberg
-%%% @doc
-%%%
-%%% @end
-%%% Created : 27 Jun 2018 by Micael Karlberg <[email protected]>
-%%%-------------------------------------------------------------------
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
-module(socket_server).
--export([start/0]).
+-export([start/0,
+ start_tcp/0,
+ start_udp/0]).
--define(REQ, 0).
--define(REP, 1).
+-define(LIB, socket_lib).
--record(manager, {acceptor, handler_id, handlers}).
+-record(manager, {acceptor, handler_id, handlers}).
-record(acceptor, {socket, manager}).
--record(handler, {socket, manager}).
+-record(handler, {socket, type, manager}).
start() ->
start_tcp().
@@ -23,6 +36,9 @@ start() ->
start_tcp() ->
start(inet, stream, tcp).
+start_udp() ->
+ start(inet, dgram, udp).
+
start(Domain, Type, Proto) ->
put(sname, "starter"),
i("try start manager"),
@@ -51,13 +67,13 @@ manager_stop(Pid, Reason) ->
manager_request(Pid, {stop, Reason}).
manager_request(Pid, Request) ->
- request(manager, Pid, Request).
+ ?LIB:request(manager, Pid, Request).
manager_reply(Pid, Ref, Reply) ->
- reply(manager, Pid, Ref, Reply).
+ ?LIB:reply(manager, Pid, Ref, Reply).
-manager_init(Domain, Type, Proto) ->
+manager_init(Domain, stream = Type, Proto) ->
put(sname, "manager"),
i("try start acceptor"),
case acceptor_start(Domain, Type, Proto) of
@@ -68,8 +84,44 @@ manager_init(Domain, Type, Proto) ->
handlers = []});
{error, Reason} ->
exit({failed_starting_acceptor, Reason})
+ end;
+manager_init(Domain, dgram = Type, Proto) ->
+ put(sname, "manager"),
+ i("try open socket"),
+ case socket:open(Domain, Type, Proto) of
+ {ok, Sock} ->
+ Addr = which_addr(Domain),
+ SA = #{family => Domain,
+ addr => Addr},
+ case socket:bind(Sock, SA) of
+ {ok, _P} ->
+ ok;
+ {error, BReason} ->
+ throw({bind, BReason})
+ end,
+ i("try start handler for"
+ "~n ~p", [case socket:sockname(Sock) of
+ {ok, Name} -> Name;
+ {error, _} = E -> E
+ end]),
+ case handler_start(1, Sock) of
+ {ok, {Pid, MRef}} ->
+ i("handler (~p) started", [Pid]),
+ handler_continue(Pid),
+ manager_loop(#manager{handler_id = 2, % Just in case
+ handlers = [{Pid, MRef, 1}]});
+ {error, SReason} ->
+ e("Failed starting handler: "
+ "~n ~p", [SReason]),
+ exit({failed_start_handler, SReason})
+ end;
+ {error, OReason} ->
+ e("Failed open socket: "
+ "~n ~p", [OReason]),
+ exit({failed_open_socket, OReason})
end.
+
manager_loop(M) ->
receive
{'DOWN', MRef, process, Pid, Reason} ->
@@ -262,7 +314,11 @@ acceptor_loop(#acceptor{socket = LSock} = A) ->
end.
acceptor_handle_accept_success(#acceptor{manager = Manager}, Sock) ->
- i("try start handler"),
+ i("try start handler for peer"
+ "~n ~p", [case socket:peername(Sock) of
+ {ok, Peer} -> Peer;
+ {error, _} = E -> E
+ end]),
case manager_start_handler(Manager, Sock) of
{ok, Pid} ->
i("handler (~p) started - now change 'ownership'", [Pid]),
@@ -309,10 +365,10 @@ handler_continue(Pid) ->
handler_request(Pid, continue).
handler_request(Pid, Request) ->
- request(handler, Pid, Request).
+ ?LIB:request(handler, Pid, Request).
handler_reply(Pid, Ref, Reply) ->
- reply(handler, Pid, Ref, Reply).
+ ?LIB:reply(handler, Pid, Ref, Reply).
handler_init(Manager, ID, Sock) ->
@@ -321,23 +377,30 @@ handler_init(Manager, ID, Sock) ->
Manager ! {handler, self(), ok},
receive
{handler, Pid, Ref, continue} ->
- i("continue"),
+ i("got continue"),
handler_reply(Pid, Ref, ok),
+ {ok, Type} = socket:getopt(Sock, socket, type),
%% socket:setopt(Socket, otp, debug, true),
handler_loop(#handler{manager = Manager,
+ type = Type,
socket = Sock})
end.
-handler_loop(#handler{socket = Socket} = H) ->
- case socket:recv(Socket) of
- {ok, Msg} ->
- i("received ~w bytes of data", [size(Msg)]),
- case dec_msg(Msg) of
+handler_loop(H) ->
+ i("try read message"),
+ case recv(H) of
+ {ok, {Source, Msg}} ->
+ i("received ~w bytes of data~s",
+ [size(Msg), case Source of
+ undefined -> "";
+ _ -> f(" from:~n ~p", [Source])
+ end]),
+ case ?LIB:dec_msg(Msg) of
{request, N, Req} ->
i("received request ~w: "
"~n ~p", [N, Req]),
- Reply = enc_rep_msg(N, "hoppsan"),
- case socket:send(Socket, Reply) of
+ Reply = ?LIB:enc_rep_msg(N, "hoppsan"),
+ case send(H, Reply, Source) of
ok ->
i("successfully sent reply ~w", [N]),
handler_loop(H);
@@ -360,87 +423,99 @@ handler_loop(#handler{socket = Socket} = H) ->
end.
+recv(#handler{socket = Sock, type = stream}) ->
+ case socket:recv(Sock) of
+ {ok, Msg} ->
+ {ok, {undefined, Msg}};
+ {error, _} = ERROR ->
+ ERROR
+ end;
+recv(#handler{socket = Sock, type = dgram}) ->
+ %% ok = socket:setopt(Sock, otp, debug, true),
+ socket:recvfrom(Sock).
+
+
+send(#handler{socket = Sock, type = stream}, Msg, _) ->
+ socket:send(Sock, Msg);
+send(#handler{socket = Sock, type = dgram}, Msg, Dest) ->
+ socket:sendto(Sock, Msg, Dest).
+
+
%% =========================================================================
-enc_req_msg(N, Data) ->
- enc_msg(?REQ, N, Data).
+%% enc_req_msg(N, Data) ->
+%% enc_msg(?REQ, N, Data).
-enc_rep_msg(N, Data) ->
- enc_msg(?REP, N, Data).
+%% enc_rep_msg(N, Data) ->
+%% enc_msg(?REP, N, Data).
-enc_msg(Type, N, Data) when is_list(Data) ->
- enc_msg(Type, N, list_to_binary(Data));
-enc_msg(Type, N, Data)
- when is_integer(Type) andalso is_integer(N) andalso is_binary(Data) ->
- <<Type:32/integer, N:32/integer, Data/binary>>.
+%% enc_msg(Type, N, Data) when is_list(Data) ->
+%% enc_msg(Type, N, list_to_binary(Data));
+%% enc_msg(Type, N, Data)
+%% when is_integer(Type) andalso is_integer(N) andalso is_binary(Data) ->
+%% <<Type:32/integer, N:32/integer, Data/binary>>.
-dec_msg(<<?REQ:32/integer, N:32/integer, Data/binary>>) ->
- {request, N, Data};
-dec_msg(<<?REP:32/integer, N:32/integer, Data/binary>>) ->
- {reply, N, Data}.
+%% dec_msg(<<?REQ:32/integer, N:32/integer, Data/binary>>) ->
+%% {request, N, Data};
+%% dec_msg(<<?REP:32/integer, N:32/integer, Data/binary>>) ->
+%% {reply, N, Data}.
%% ---
-request(Tag, Pid, Request) ->
- Ref = make_ref(),
- Pid ! {Tag, self(), Ref, Request},
- receive
- {Tag, Pid, Ref, Reply} ->
- Reply
- end.
+%% request(Tag, Pid, Request) ->
+%% Ref = make_ref(),
+%% Pid ! {Tag, self(), Ref, Request},
+%% receive
+%% {Tag, Pid, Ref, Reply} ->
+%% Reply
+%% end.
-reply(Tag, Pid, Ref, Reply) ->
- Pid ! {Tag, self(), Ref, Reply}.
+%% reply(Tag, Pid, Ref, Reply) ->
+%% Pid ! {Tag, self(), Ref, Reply}.
%% ---
-formated_timestamp() ->
- format_timestamp(os:timestamp()).
+%% formated_timestamp() ->
+%% format_timestamp(os:timestamp()).
-format_timestamp(Now) ->
- N2T = fun(N) -> calendar:now_to_local_time(N) end,
- format_timestamp(Now, N2T, true).
+%% format_timestamp(Now) ->
+%% N2T = fun(N) -> calendar:now_to_local_time(N) end,
+%% format_timestamp(Now, N2T, true).
-format_timestamp({_N1, _N2, N3} = N, N2T, true) ->
- FormatExtra = ".~.2.0w",
- ArgsExtra = [N3 div 10000],
- format_timestamp(N, N2T, FormatExtra, ArgsExtra);
-format_timestamp({_N1, _N2, _N3} = N, N2T, false) ->
- FormatExtra = "",
- ArgsExtra = [],
- format_timestamp(N, N2T, FormatExtra, ArgsExtra).
+%% format_timestamp({_N1, _N2, N3} = N, N2T, true) ->
+%% FormatExtra = ".~.2.0w",
+%% ArgsExtra = [N3 div 10000],
+%% format_timestamp(N, N2T, FormatExtra, ArgsExtra);
+%% format_timestamp({_N1, _N2, _N3} = N, N2T, false) ->
+%% FormatExtra = "",
+%% ArgsExtra = [],
+%% format_timestamp(N, N2T, FormatExtra, ArgsExtra).
-format_timestamp(N, N2T, FormatExtra, ArgsExtra) ->
- {Date, Time} = N2T(N),
- {YYYY,MM,DD} = Date,
- {Hour,Min,Sec} = Time,
- FormatDate =
- io_lib:format("~.4w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w" ++ FormatExtra,
- [YYYY, MM, DD, Hour, Min, Sec] ++ ArgsExtra),
- lists:flatten(FormatDate).
+%% format_timestamp(N, N2T, FormatExtra, ArgsExtra) ->
+%% {Date, Time} = N2T(N),
+%% {YYYY,MM,DD} = Date,
+%% {Hour,Min,Sec} = Time,
+%% FormatDate =
+%% io_lib:format("~.4w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w" ++ FormatExtra,
+%% [YYYY, MM, DD, Hour, Min, Sec] ++ ArgsExtra),
+%% lists:flatten(FormatDate).
%% ---
f(F, A) ->
- lists:flatten(io_lib:format(F, A)).
+ ?LIB:f(F, A).
e(F, A) ->
- p("<ERROR> " ++ F, A).
+ ?LIB:e(F, A).
i(F) ->
- i(F, []).
-i(F, A) ->
- p("*** " ++ F, A).
+ ?LIB:i(F).
-p(F, A) ->
- p(get(sname), F, A).
+i(F, A) ->
+ ?LIB:i(F, A).
-p(SName, F, A) ->
- io:format("[~s,~p][~s] " ++ F ++ "~n",
- [SName,self(),formated_timestamp()|A]).
-