Skip to content

Commit 44ba346

Browse files
committed
update erlang lib
1 parent a26cbdb commit 44ba346

File tree

12 files changed

+570
-0
lines changed

12 files changed

+570
-0
lines changed

erlang/lib/Makefile

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
.SUFFIXES: .erl .beam
2+
3+
ERLC = erlc +debuginfo
4+
5+
.erl.beam:
6+
${ERLC} -W $<
7+
8+
.yrl.erl:
9+
${ERLC} -W $<
10+
11+
MODS = lib_files_find
12+
13+
all:compile
14+
15+
compile: ${MODS:%=%.beam} subdirs
16+
17+
subdirs:
18+
cd lib_chan; make
19+
cd lib_misc; make
20+
21+
.PHONY:clean
22+
23+
clean:
24+
rm -rf *.beam erl_crash.dump
25+
cd lib_chan; make clean
26+
cd lib_misc; make clean

erlang/lib/lib_chan/Makefile

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
.SUFFIXES: .erl .beam .yrl
2+
3+
all: compile
4+
5+
ERLC = erlc +debug_info
6+
7+
MODS = kvs mode_name_server lib_chan lib_chan_cs lib_chan_mm lib_chan_auth
8+
9+
.erl.beam:
10+
${ERLC} -W $<
11+
12+
compile: ${MODS:%=%.beam}
13+
14+
.PHONY:clean
15+
16+
clean:
17+
rm -rf *.beam erl_crash.dump

erlang/lib/lib_chan/chan.conf

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
{port, 1234}.
2+
{service, nameServer, password, "ABXy45", mfa, mode_name_server, start_me_up, notUsed}.

erlang/lib/lib_chan/kvs.erl

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
-module(kvs).
2+
-export([start/0, store/2, lookup/1]).
3+
4+
start() -> register(kvs, spawn(fun() -> loop() end)).
5+
6+
store(Key, Value) -> rpc({store, Key, Value}).
7+
8+
lookup(Key) -> rpc({lookup, Key}).
9+
10+
rpc(Q) ->
11+
kvs ! {self(), Q},
12+
receive
13+
{kvs, Reply} ->
14+
Reply
15+
end.
16+
17+
loop() ->
18+
receive
19+
{From, {store, Key, Value}} ->
20+
put(Key, {ok, Value}),
21+
From ! {kvs, true},
22+
loop();
23+
{From, {lookup, Key}} ->
24+
From ! {kvs, get(Key)},
25+
loop()
26+
end.
27+
28+
%%
29+
%% kvs:start().
30+
%%
31+
%% rpc:call(server@centos, kvs, store, [weather, fine]).
32+
%% rpc:call(server@centos, kvs, lookup, [weather]).
33+
%%

erlang/lib/lib_chan/lib_chan.erl

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
-module(lib_chan).
2+
3+
-export([cast/2, start_server/0, start_server/1, connect/5, disconnect/1, rpc/2]).
4+
5+
-import(lists, [map/2, member/2, foreach/2]).
6+
-import(lib_chan_mm, [send/2, close/1]).
7+
8+
start_server() ->
9+
case os:getenv("HOME") of
10+
false ->
11+
exit({ebadEnv, "HOME"});
12+
Home ->
13+
start_server(Home ++ "/.erlang/lib_chan.conf")
14+
end.
15+
16+
start_server(ConfigFile) ->
17+
io:format("lib_chan startting : ~p~n", [ConfigFile]),
18+
case file:consult(ConfigFile) of
19+
{ok, ConfigData} ->
20+
io:format("ConfigData = ~p~n", [ConfigData]),
21+
case check_terms(ConfigData) of
22+
[] ->
23+
start_server1(ConfigData);
24+
Errors ->
25+
exit({eDeaemonConfig, Errors})
26+
end;
27+
{error, Why} ->
28+
exit({eDeaemonConfig, Why})
29+
end.
30+
31+
32+
check_terms(ConfigData) ->
33+
L = map(fun check_term/1, ConfigData) ,
34+
[X || {error, X} <- L].
35+
36+
check_term({port, P}) when is_integer(P) -> ok;
37+
check_term({service, _, password, _, mfa, _, _, _}) -> ok;
38+
check_term(X) -> {error, {badTerm, X}}.
39+
40+
start_server1(ConfigData) ->
41+
register(lib_chan, spawn(fun() -> start_server2(ConfigData) end)).
42+
43+
start_server2(ConfigData) ->
44+
[Port] = [P || {port, P} <- ConfigData],
45+
start_port_server(Port, ConfigData).
46+
47+
start_port_server(Port, ConfigData) ->
48+
lib_chan_cs:start_raw_server(Port, fun(Socket) ->
49+
start_port_instance(Socket, ConfigData) end,
50+
100,
51+
4).
52+
53+
start_port_instance(Socket, ConfigData) ->
54+
55+
S = self(),
56+
Controller = spawn_link(fun() -> start_erl_port_server(S, ConfigData) end),
57+
lib_chan_mm:loop(Socket, Controller).
58+
59+
start_erl_port_server(MM, ConfigData) ->
60+
receive
61+
{chan, MM, {startService, Mod, ArgC}} ->
62+
case get_service_definition(Mod, ConfigData) of
63+
{yes, Pwd, MFA} ->
64+
case Pwd of
65+
none ->
66+
send(MM, ack),
67+
really_start(MM, ArgC, MFA);
68+
_ ->
69+
do_authentication(Pwd, MM, ArgC, MFA)
70+
end;
71+
no ->
72+
io:format("sending bad service ~n"),
73+
send(MM, badService),
74+
close(MM)
75+
end;
76+
Any ->
77+
io:format(" === Erl port service got : ~p ~p~n", [MM, Any]),
78+
exit({protocolViolation, Any})
79+
end.
80+
81+
do_authentication(Pwd, MM, ArgC, MFA) ->
82+
C = lib_chan_auth:make_challenge(),
83+
send(MM, {challenge, C}),
84+
receive
85+
{chan, MM, {response, R}} ->
86+
case lib_chan_auth:is_response_correct(C, R, Pwd) of
87+
true ->
88+
send(MM, ack),
89+
really_start(MM, ArgC, MFA);
90+
false ->
91+
send(MM, authFail),
92+
close(MM)
93+
end
94+
end.
95+
96+
really_start(MM, ArgC, {Mod, Func, ArgS}) ->
97+
%% authentication worked so now we're off
98+
case (catch apply(Mod, Func, [MM, ArgC, ArgS])) of
99+
{'EXIT', normal} ->
100+
true;
101+
{'EXIT', Why} ->
102+
io:format("server error : ~p~n", [Why]);
103+
Why ->
104+
io:format("server error should die with exit(normal) was : ~p~n", [Why])
105+
end.
106+
107+
108+
get_service_definition(Mod, [{service, Mod, password, Pwd, mfa, M, F, A} | _]) ->
109+
{yes, Pwd, {M, F, A}};
110+
get_service_definition(Name, [_ | T]) ->
111+
get_service_definition(Name, T);
112+
get_service_definition(_, []) ->
113+
no.
114+
115+
116+
connect(Host, Port, Service, Secret, ArgC) ->
117+
S = self(),
118+
MM = spawn(fun() -> connect(S, Host, Port) end),
119+
receive
120+
{MM, ok} ->
121+
case authentication(MM, Service, Secret, ArgC) of
122+
ok -> {ok, MM};
123+
Error -> Error
124+
end;
125+
{MM, Error} ->
126+
Error
127+
end.
128+
129+
connect(Parent, Host, Port) ->
130+
case lib_chan_cs:start_raw_client(Host, Port, 4) of
131+
{ok, Socket} ->
132+
Parent ! {self(), ok},
133+
lib_chan_mm:loop(Socket, Parent);
134+
Error ->
135+
Parent ! {self(), Error}
136+
end.
137+
138+
authentication(MM, Service, Secret, ArgC) ->
139+
send(MM, {startService, Service, ArgC}),
140+
% we should get back a challenge or a ack or close socket
141+
receive
142+
{chan, MM, ack} ->
143+
ok;
144+
{chan, MM, {challenge, C}} ->
145+
R = lib_chan_auth:make_response(C, Secret),
146+
send(MM, {response, R}),
147+
receive
148+
{chan, MM, ack} ->
149+
ok;
150+
{chan, MM, authFail} ->
151+
wait_close(MM),
152+
{error, authentication};
153+
Other ->
154+
{error, Other}
155+
end;
156+
{chan, MM, badService} ->
157+
wait_close(MM),
158+
{error, badService};
159+
Other ->
160+
{error, Other}
161+
end.
162+
163+
wait_close(MM) ->
164+
receive
165+
{chan_closed, MM} ->
166+
true
167+
after 5000 ->
168+
io:format("**error lib_chan~n"),
169+
true
170+
end.
171+
172+
disconnect(MM) -> close(MM).
173+
174+
rpc(MM, Q) ->
175+
send(MM, Q),
176+
receive
177+
{chan, MM, Reply} ->
178+
Reply
179+
end.
180+
181+
cast(MM, Q) ->
182+
send(MM, Q).
183+

erlang/lib/lib_chan/lib_chan_auth.erl

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
-module(lib_chan_auth).
2+
3+
-export([make_challenge/0, make_response/2, is_response_correct/3]).
4+
5+
make_challenge() ->
6+
random_string(25).
7+
8+
make_response(Challenge, Secret) ->
9+
erlang:md5(Challenge ++ Secret).
10+
11+
is_response_correct(Challenge, Response, Secret) ->
12+
case erlang:md5(Challenge ++ Secret) of
13+
Response -> true;
14+
_ -> false
15+
end.
16+
17+
random_string(N) -> random_seed(), random_string(N, []).
18+
19+
random_string(0, D) -> D;
20+
random_string(N, D) ->
21+
random_string(N - 1, [rand:uniform(26) - 1 + $a | D]).
22+
23+
random_seed() ->
24+
{_, _, X} = erlang:timestamp(),
25+
{H, M, S} = time(),
26+
H1 = H * X rem 32767,
27+
M1 = M * X rem 32767,
28+
S1 = S * X rem 32767,
29+
put(random_seed, {H1, M1, S1}).

0 commit comments

Comments
 (0)