File server
Description
The contract
+NAME("file_server").
+VSN("ubf1.0").
+TYPES
info() = info;
description() = description;
services() = services;
contract() = contract;
file() = string();
ls() = ls;
files() = {files, [file()]};
getFile() = {get, file()};
noSuchFile() = noSuchFile.
+STATE start
ls() => files() & start;
getFile() => binary() & start
| noSuchFile() & stop.
+ANYSTATE
info() => string();
description() => string();
contract() => term().
| A telnet session
A full telnet session using the server can be found in the
quick start tutorial
An Erlang client
-module(file_client).
%% -compile(export_all).
-export([test/0]).
-import(lists, [map/2, foldl/3, filter/2]).
-import(client, [rpc/2]).
defaultPort() -> 2000.
s(X) -> {'#S', X}.
-define(S(X), {'#S',X}).
test() ->
{ok, Pid, Name} = client:connect(host(), defaultPort()),
{reply, Info, _} = client:rpc(Pid,
{startService, s("file_server"), []}),
io:format("Info=~p~n",[Info]),
{reply, {files, Fs}, start} = rpc(Pid, ls),
Files = map(fun(?S(I)) -> I end, Fs),
io:format("Files=~p~n",[Files]),
{reply, X, start} = rpc(Pid, {get, s("ubf.erl")}),
io:format("got ~p bytes~n",[size(X)]),
client:stop(Pid),
io:format("test worked~n"),
ok.
host() ->
case os:getenv("WHERE") of
"HOME" -> "localhost";
"WORK" -> "p2p.sics.se"
end.
| The Erlang file server plugin
-module(file_plugin).
-export([info/0, description/0,
managerStart/1, handlerStop/3,
handlerStart/2,
managerRpc/2, handlerRpc/4]).
-import(lists, [map/2, member/2]).
%% NOTE the following two lines
-compile({parse_transform,contract_parser}).
-add_contract("file_plugin").
-define(S(X), {'#S',X}).
s(X) -> {'#S', X}.
%% The initial state of the manager
info() -> "I am a mini file server".
description() -> "
Commands:
'ls'$ List files
{'get' File} => Length ~ ... ~ | noSuchFile
".
managerStart(_) -> {ok, myManagerState}.
managerRpc(secret, State) ->
{accept, welcomeToFTP, State};
managerRpc(_, State) ->
{reject, badPassword, State}.
handlerStart(_, ManagerPid) ->
Reply = s(info()),
HandlerState = start,
HandlerData = myFirstData0,
{accept, Reply, HandlerState, HandlerData}.
handlerStop(Pid, Reason, State) ->
io:format("Client stopped:~p ~p~n",[Pid, Reason]),
State.
handlerRpc(start, ls, State, Env) ->
{ok, Files} = file:list_dir("."),
Ret = map(fun(I) -> s(I) end, Files),
{{files, Ret}, start, State};
handlerRpc(start, {get, ?S(File)}, State, Env) ->
{ok, Files} = file:list_dir("."),
case member(File, Files) of
true ->
{ok, Bin} = file:read_file(File),
{Bin, start, State};
false ->
{noSuchFile, stop, State}
end;
handlerRpc(Any, info, State, _) ->
{s(info()), Any, State};
handlerRpc(Any, description, State, Manager) ->
{s(description()), Any, State}.
| |