Documents
Home
White paper
Paper
UBF(A) spec
UBF(B) spec
UBF(C) spec

Tutorials
Quick start
Erlang servers
Java clients

Services
IRC
Message Box
File server

Downloads
Downloads

UBF(B)
2002-03-05

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}.






)