diff --git a/#ball.erl# b/#ball.erl# deleted file mode 100644 index 3cdf56e..0000000 --- a/#ball.erl# +++ /dev/null @@ -1,74 +0,0 @@ -%% ``The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved via the world wide web at http://www.erlang.org/. -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%% -%% The Initial Developer of the Original Code is Ericsson Utvecklings AB. -%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings -%% AB. All Rights Reserved.'' -%% -%% $Id$ -%% -%% ------------------------------------------------------------ -%% A simple demo showing a ball -%% bouncing in a window. -%% ------------------------------------------------------------ - --module(ball). - --export([start/0,init/0]). - -start() -> - spawn(ball,init,[]). - -init() -> - I= gs:start(), - W= gs:window(I,[{title,"Ball"},{width,300},{height,300},{map,true}]), - C= gs:canvas(W,[{width,300},{height,300},{bg,yellow}]), - B= gs:button(W,[{label, {text,"Quit Demo"}},{x,100}]), - Ball = gs:oval(C,[{coords,[{0,0},{50,50}]},{fill,red}]), - ball(Ball,0,0,5.5,4.1). - -ball(Ball,X,Y,DX,DY) -> - {NX,NDX} = cc(X,DX), - {NY,NDY} = cc(Y,DY), - gs:config(Ball,{move,{DX,DY}}), - receive - {gs,Id,click,_,_} -> exit(normal); - {gs,_,destroy,_,_} -> exit(normal) - after 20 -> - true - end, - ball(Ball,NX,NY,NDX,NDY). - -cc(X,DX) -> - if - DX>0 -> - if - X=<250 -> - {X+DX,DX}; - x>250 -> - {X-DX,-DX} - end; - DX<0 -> - if - X>=0 -> - {X+DX,DX}; - X<0 -> - {X-DX,-DX} - end - end. - -%% ------------------------------------------------------------ - - - - - - diff --git a/#irc_plugin.erl# b/#irc_plugin.erl# deleted file mode 100644 index 4ed5b19..0000000 --- a/#irc_plugin.erl# +++ /dev/null @@ -1,188 +0,0 @@ --module(irc_plugin). - --export([manager_start/2, client_stop/3, - managerStartState/0, handlerStartState/0, - manager_rpc/2, handle_rpc/4]). - --import(server, [sendEvent/2, ask_manager/2]). --import(lists, [delete/2, map/2, member/2, foreach/2]). - -%% NOTE the following two lines - --compile({parse_transform,contract_parser}). --add_contract("irc_plugin"). - --define(S(X), {'#S',X}). -s(X) -> {'#S', X}. - -managerStartState() -> new_seed(), ets:new(irc, []). - -handlerStartState() -> myHandlerState. - -%% manager_start(Args, State) is called every time a session is started -%% Args comes from client:start(Host,Port,Service,Args) -%% Service in the rcp:start must match name() -%% manager_start(Args, State) -> {accept, Reply, State} | {reject, Why, State} -%% State is the manager state. - -manager_start(_, ManagerState) -> - {accept, yes, start, [], ManagerState}. - -client_stop(Pid, Reason, Ets) -> - io:format("Client stopped:~p ~p~n",[Pid, Reason]), - {Nick, Groups} = facts(Ets, Pid), - io:format("Pid has nick~p is in groups~p~n",[Nick, Groups]), - ets:delete(Ets, {facts, Pid}), - ets:delete(Ets, {pid, Nick}), - foreach(fun(G) -> - Pids = pids(Ets, G), - Pids1 = delete(Pid, Pids), - ets:insert(Ets, {{group,G}, Pids1}), - broadcast_to_group(Pids1, {leaves, s(Nick), s(G)}) - end, Groups), - Ets. - -%% The manager state -%% Is what ?? -%% We know the Pid of the Client -%% The Nick of the client on the Pid -%% The set of groups that the client is joined to - -%% This is all in one ets table -%% {group, Name} => [Pids] (all the Pids in a group) -%% {group, "erlang"} => [Pid1, Pid2, ...] -%% {facts, Pid} => {Nick, [Group]} -%% The nick and the List of joined groups -%% for Pid -%% {pid, Nick} => Pid - -%% When somebody joins or leaves a group broadcast that -%% they have joined or leaved the group -%% When somebody dies remove their nick -%% and remove them from all groups - -pids(Ets, Name) -> - case ets:lookup(Ets, {group, Name}) of - [{_,L}] -> L; - [] -> [] - end. - -facts(Ets, Pid) -> - case ets:lookup(Ets, {facts, Pid}) of - [{_,L}] -> L; - [] -> [] - end. - -manager_rpc({join, Pid, Group}, Ets) -> - %% Nick (Pid) joins the group G - {Nick, Gs} = facts(Ets, Pid), - case member(Group, Gs) of - true -> {ok, Ets}; - false -> - ets:insert(Ets, {{facts, Pid}, {Nick,[Group|Gs]}}), - Pids = [Pid|pids(Ets, Group)], - ets:insert(Ets, {{group,Group}, Pids}), - broadcast_to_group(Pids, {joins, s(Nick), s(Group)}), - {ok, Ets} - end; -manager_rpc({leave, Pid, Group}, Ets) -> - {Nick, Gs} = facts(Ets, Pid), - case member(Group, Gs) of - false -> {ok, Ets}; - true -> - ets:insert(Ets, {{facts, Pid}, {Nick,delete(Group, Gs)}}), - Pids = delete(Pid, pids(Ets, Group)), - ets:insert(Ets, {{group,Group}, Pids}), - broadcast_to_group(Pids, {leaves, s(Nick), s(Group)}), - {ok, Ets} - end; -manager_rpc({msg, Pid, Group, Msg}, Ets) -> - {Nick, Gs} = facts(Ets, Pid), - case member(Group, Gs) of - false -> {notJoined, Ets}; - true -> - broadcast_to_group(pids(Ets, Group), - {msg, s(Nick), s(Group), s(Msg)}), - {ok, Ets} - end; -manager_rpc(groups, Ets) -> - M = ets:match(Ets, {{group,'$1'},'_'}), - io:format("Here Groups=~p~n",[M]), - Strs = map(fun([I]) -> s(I) end, M), - {Strs, Ets}; -manager_rpc(P={logon, Pid}, Ets) -> - Nick = random_nick(6), - case ets:lookup(Ets, {pid, Nick}) of - [] -> - ets:insert(Ets, {{pid, Nick}, Pid}), - ets:insert(Ets, {{facts,Pid}, {Nick, []}}), - {Nick, Ets}; - _ -> - manager_rpc(P, Ets) - end; -manager_rpc({change_nick,Old,New,Pid}, Ets) -> - case ets:lookup(Ets, {pid, New}) of - [] -> - ets:insert(Ets, {{pid, New}, Pid}), - ets:delete(Ets, {pid,Old}), - {_, Groups} = facts(Ets, Pid), - ets:insert(Ets, {{facts,Pid},{New, Groups}}), - %% Now tell all groups about the name change - foreach(fun(G) -> - Pids = pids(Ets, G), - broadcast_to_group(Pids, {changesName, - s(Old), s(New), - s(G)}) - end, Groups), - {ok, Ets}; - _ -> - {error, Ets} - end. - -broadcast_to_group(L, Msg) -> - foreach(fun(Pid) -> sendEvent(Pid, Msg) end, L). - -handle_rpc(start, logon, State, Manager) -> - R = ask_manager(Manager, {logon, self()}), - {{ok, s(R)}, active, R}; -handle_rpc(active, {join, ?S(Group)}, Nick, Manager) -> - ask_manager(Manager, {join, self(), Group}), - {ok, active, Nick}; -handle_rpc(active, {leave, ?S(Group)}, Nick, Manager) -> - ask_manager(Manager, {leave, self(), Group}), - {ok, active, Nick}; -handle_rpc(active, {msg, ?S(Group), ?S(Msg)}, Nick, Manager) -> - ask_manager(Manager, {msg, self(), Group, Msg}), - {ok, active, Nick}; -handle_rpc(active, {nick, ?S(New)}, Nick, Manager) -> - case ask_manager(Manager, {change_nick,Nick,New,self()}) of - ok -> - {nickChanged, active, New}; - error -> - {nickInUse, active, Nick} - end; -handle_rpc(active, groups, Nick, Manager) -> - Groups = ask_manager(Manager, groups), - {Groups, active, Nick}. - -random_nick(0) -> - []; -random_nick(N) -> - [$a + random:uniform(26) - 1|random_nick(N-1)]. - -new_seed() -> - {_,_,X} = erlang:now(), - {H,M,S} = time(), - H1 = H * X rem 32767, - M1 = M * X rem 32767, - S1 = S * X rem 32767, - put(random_seed, {H1,M1,S1}). - - - - - - - - - diff --git a/Makefile b/Makefile index 3bf5603..3a815ea 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ ERL = ubf proc_socket_server find server\ test ubf_driver ubf_test file_client\ contracts contract_manager client plugin_handler\ - leex contract_lex contract_yecc irc_client ubf_utils + leex contract_lex contract_yecc irc_client irc_client_gs ubf_utils PLUGINS = test_plugin file_plugin irc_plugin server_plugin diff --git a/ball.erl b/ball.erl deleted file mode 100644 index 1aa0df5..0000000 --- a/ball.erl +++ /dev/null @@ -1,68 +0,0 @@ -%% ``The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved via the world wide web at http://www.erlang.org/. -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%% -%% The Initial Developer of the Original Code is Ericsson Utvecklings AB. -%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings -%% AB. All Rights Reserved.'' -%% -%% $Id$ -%% -%% ------------------------------------------------------------ -%% A simple demo showing a ball -%% bouncing in a window. -%% ------------------------------------------------------------ - --module(ball). - --export([start/0,init/0]). - -start() -> - spawn(ball,init,[]). - -init() -> - I= gs:start(), - W= gs:window(I,[{title,"Ball"},{width,300},{height,300},{map,true}]), - C= gs:canvas(W,[{width,300},{height,300},{bg,yellow}]), - B= gs:button(W,[{label, {text,"Quit Demo"}},{x,100}]), - Ball = gs:oval(C,[{coords,[{0,0},{50,50}]},{fill,red}]), - ball(Ball,0,0,5.5,4.1). - -ball(Ball,X,Y,DX,DY) -> - {NX,NDX} = cc(X,DX), - {NY,NDY} = cc(Y,DY), - gs:config(Ball,{move,{DX,DY}}), - receive - {gs,Id,click,_,_} -> exit(normal); - {gs,_,destroy,_,_} -> exit(normal) - after 20 -> - true - end, - ball(Ball,NX,NY,NDX,NDY). - -cc(X,DX) -> - if - DX>0 -> - if - X=<250 -> - {X+DX,DX}; - x>250 -> - {X-DX,-DX} - end; - DX<0 -> - if - X>=0 -> - {X+DX,DX}; - X<0 -> - {X-DX,-DX} - end - end. - -%% ------------------------------------------------------------ diff --git a/client.beam b/client.beam index 928897a..b092761 100644 Binary files a/client.beam and b/client.beam differ diff --git a/contract_lex.beam b/contract_lex.beam index 4f3cd6e..855d048 100644 Binary files a/contract_lex.beam and b/contract_lex.beam differ diff --git a/contract_manager.beam b/contract_manager.beam index 7ecc5ce..28b1c77 100644 Binary files a/contract_manager.beam and b/contract_manager.beam differ diff --git a/contract_parser.beam b/contract_parser.beam index 29ecd4e..c6cc192 100644 Binary files a/contract_parser.beam and b/contract_parser.beam differ diff --git a/contract_yecc.beam b/contract_yecc.beam index 67da64e..5d69b30 100644 Binary files a/contract_yecc.beam and b/contract_yecc.beam differ diff --git a/contracts.beam b/contracts.beam index e27890e..b8ccfd4 100644 Binary files a/contracts.beam and b/contracts.beam differ diff --git a/doc/site/downloads.html b/doc/site/downloads.html new file mode 100644 index 0000000..1a778f4 --- /dev/null +++ b/doc/site/downloads.html @@ -0,0 +1,171 @@ + + + + +Site + +

  + + + + + +
+ + + + + + + + +
Documents
+ + + + + + + + + + + + +
+ + +
+Home +
White paper +
UBF(A) spec +
UBF(B) spec +
+
+

+ + + + + + + + +
Tutorials
+ + + + + + + + + + + + +
+ + +
+Quick start +
Erlang servers +
Java clients +
+
+

+ + + + + + + + +
Services
+ + + + + + + + + + + + +
+ + +
+IRC +
Message Box +
File server +
+
+

+ + + + + + + + +
Downloads
+ + + + + + + + + + + + +
+ + +
+Downloads +
+
+

+

+

+ + +
UBF(B)
+ + + + +
2002-03-05
+
+

Downloads

+ +
+ +
+
(  + +)
+
+ + diff --git a/doc/site/eserve.html b/doc/site/eserve.html new file mode 100644 index 0000000..e733892 --- /dev/null +++ b/doc/site/eserve.html @@ -0,0 +1,233 @@ + + + + +Site + +

  + + + + + +
+ + + + + + + + +
Documents
+ + + + + + + + + + + + +
+ + +
+Home +
White paper +
UBF(A) spec +
UBF(B) spec +
+
+

+ + + + + + + + +
Tutorials
+ + + + + + + + + + + + +
+ + +
+Quick start +
Erlang servers +
Java clients +
+
+

+ + + + + + + + +
Services
+ + + + + + + + + + + + +
+ + +
+IRC +
Message Box +
File server +
+
+

+ + + + + + + + +
Downloads
+ + + + + + + + + + + + +
+ + +
+Downloads +
+
+

+

+

+ + +
Quick start
+ + + + +
2002-03-05
+
+ + +
Erlang servers
+

an example of a server plugin +

-module(file_plugin).
+
+-export([manager_start/2, client_stop/3,
+	 managerStartState/0, handlerStartState/0, 
+	 manager_rpc/2, handle_rpc/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
+
+managerStartState() -> myManagerState.
+
+handlerStartState() -> myHandlerState.
+    
+%% manager_start(Args, State) is called every time a session is started
+%% Args comes from client:start(Host,Port,Service,Args)
+%% Service in the rcp:start must match name()
+%% manager_start(Args, State) -> {accept, Reply, State} | {reject, Why, State}
+%% State is the manager state.
+
+manager_start(_, ManagerState) ->
+    Reply = yesOffWeGo,
+    HandlerState = start,
+    HandlerData = myInitailData0,
+    {accept, Reply, HandlerState, HandlerData, ManagerState}.
+
+client_stop(Pid, Reason, State) ->
+    io:format("Client stopped:~p ~p~n",[Pid, Reason]),
+    State.
+
+manager_rpc(secret, State) ->
+    {accept, welcomeToFTP, State};
+manager_rpc(_, State) ->
+    {reject, badPassword, State}.
+
+handle_rpc(start, {logon, ?S("jimmy")}, State, Env) ->
+    {ok, active, State};
+handle_rpc(active, ls, State, Env) ->
+    {ok, Files} = file:list_dir("."),
+    Ret = map(fun(I) -> s(I) end, Files),
+    {{files, Ret}, active, State};
+handle_rpc(active, {get, ?S(File)}, State, Env) ->
+    {ok, Files} = file:list_dir("."),
+    case member(File, Files) of
+	true ->
+	    {ok, Bin} = file:read_file(File),
+	    {Bin, active, State};
+	false ->
+	    {noSuchFile, stop, State}
+    end.
+
+
+
+
+

+ +
+
(  + +)
+
+ + diff --git a/doc/site/home.html b/doc/site/home.html index 1c1265d..9f9f4ba 100644 --- a/doc/site/home.html +++ b/doc/site/home.html @@ -145,7 +145,26 @@ SIZE=-1>Downloads - + +
White paper
Warning
+ + + + +
2002-03-05
+
+

+Pre-release. Be warned. Things change frequently +

+ +
+
(  + +)
+

+ +
UBF Home
diff --git a/doc/site/javac.html b/doc/site/javac.html new file mode 100644 index 0000000..df2a856 --- /dev/null +++ b/doc/site/javac.html @@ -0,0 +1,171 @@ + + + + +Site + +

  +

2002-03-05
+ + + + +
+ + + + + + + + +
Documents
+ + + + + + + + + + + + +
+ + +
+Home +
White paper +
UBF(A) spec +
UBF(B) spec +
+
+

+ + + + + + + + +
Tutorials
+ + + + + + + + + + + + +
+ + +
+Quick start +
Erlang servers +
Java clients +
+
+

+ + + + + + + + +
Services
+ + + + + + + + + + + + +
+ + +
+IRC +
Message Box +
File server +
+
+

+ + + + + + + + +
Downloads
+ + + + + + + + + + + + +
+ + +
+Downloads +
+
+

+

+

+ + +
Quick start
+ + + + +
2002-03-05
+
+ + +
Java clients
+

Not yet written. +

+ +
+
(  + +)
+
+ + diff --git a/doc/site/messagebox.html b/doc/site/messagebox.html new file mode 100644 index 0000000..06d83f3 --- /dev/null +++ b/doc/site/messagebox.html @@ -0,0 +1,169 @@ + + + + +Site + +

  + + + + + +
+ + + + + + + + +
Documents
+ + + + + + + + + + + + +
+ + +
+Home +
White paper +
UBF(A) spec +
UBF(B) spec +
+
+

+ + + + + + + + +
Tutorials
+ + + + + + + + + + + + +
+ + +
+Quick start +
Erlang servers +
Java clients +
+
+

+ + + + + + + + +
Services
+ + + + + + + + + + + + +
+ + +
+IRC +
Message Box +
File server +
+
+

+ + + + + + + + +
Downloads
+ + + + + + + + + + + + +
+ + +
+Downloads +
+
+

+

+

+ + +
UBF(B)
+ + + + +
2002-03-05
+
+

Message box

+

Not yet wrtten - will be something like nntp. +

+ +
+
(  + +)
+
+ + diff --git a/doc/src/Makefile b/doc/src/Makefile index 0f21ed1..fd60ca8 100644 --- a/doc/src/Makefile +++ b/doc/src/Makefile @@ -1,7 +1,8 @@ ## Add your modules here -EHTML = home white irc file ubfb ubfb_quick ubfa ubfa_quick quick +EHTML = downloads eserve messagebox \ + javac home white irc file ubfb ubfb_quick ubfa ubfa_quick quick ## Do not change below this line diff --git a/doc/src/Makefile~ b/doc/src/Makefile~ index ddc92a5..0f21ed1 100644 --- a/doc/src/Makefile~ +++ b/doc/src/Makefile~ @@ -1,7 +1,7 @@ ## Add your modules here -EHTML = home white irc ftp ubfb ubfb_quick ubfa ubfa_quick quick +EHTML = home white irc file ubfb ubfb_quick ubfa ubfa_quick quick ## Do not change below this line diff --git a/doc/src/downloads.ehtml b/doc/src/downloads.ehtml new file mode 100644 index 0000000..0339f34 --- /dev/null +++ b/doc/src/downloads.ehtml @@ -0,0 +1,21 @@ +layout.mac + + +

+ +

Downloads

+ + +
+ + + + + + + diff --git a/doc/src/downloads.ehtml~ b/doc/src/downloads.ehtml~ new file mode 100644 index 0000000..34155e5 --- /dev/null +++ b/doc/src/downloads.ehtml~ @@ -0,0 +1,35 @@ +layout.mac + + +
+ +

File server

+ +

Description

+

The contract

+ +../../file_plugin.con + +

A telnet session

+ +

A full telnet session using the server can be found in the +quick start tutorial + +

An Erlang client

+../../file_client.erl + +

The Erlang file server plugin

+ +../../file_plugin.erl + +
+ + + + + + + diff --git a/doc/src/eserve.ehtml b/doc/src/eserve.ehtml new file mode 100644 index 0000000..e7a1b08 --- /dev/null +++ b/doc/src/eserve.ehtml @@ -0,0 +1,24 @@ +layout.mac + + +
+ +Erlang servers + + + +

an example of a server plugin + +../../file_plugin.erl + +

+ + + + + + + diff --git a/doc/src/eserver.ehtml b/doc/src/eserver.ehtml new file mode 100644 index 0000000..e7a1b08 --- /dev/null +++ b/doc/src/eserver.ehtml @@ -0,0 +1,24 @@ +layout.mac + + +
+ +Erlang servers + + + +

an example of a server plugin + +../../file_plugin.erl + +

+ + + + + + + diff --git a/doc/src/eserver.ehtml~ b/doc/src/eserver.ehtml~ new file mode 100644 index 0000000..c2145fb --- /dev/null +++ b/doc/src/eserver.ehtml~ @@ -0,0 +1,75 @@ +layout.mac + + +
+ +Quick start with UBF + +

This will jump start you with UBF. + +

All you need is an internet connection and Telnet to get started. +

First read the contract - in the next section. Then +fire up Telnet and investigate the server (by hand) - then you can see +what's really going on +The Contract +

+../../file_plugin.con +

+A telnet session + +

+The following is a telnet session. + +

User input is in red. Server output is in black, some lines have +been omitted: + +

+ +telnet enfield.sics.se 2000 +Trying 127.0.0.1... +Connected to localhost.localdomain. +Escape character is '^]'. +{'ubf1.0',"meta_server","I am a meta server +See http://www.sics.se/~joe/ubf.html +This server speaks Universal Binary Format 1.0 +For more information type 'description'$ at the dollar prompt +Remember the $ and quote marks :-) +"}$ +{'rpc',{'startService',"file_server",#}}$ + +{'rpcReply',{'ok','yesOffWeGo'},'start'}$ + +{'rpc',{'logon',"jimmy"}}$ + +{'rpcReply','ok','active'}$ + +{'rpc','ls'}$ + +{'rpcReply',{'files',#"ubf.erl"&"client.erl"& + ... + +{'rpc',{'get',"ubf.erl"}}$ + +{'rpcReply',7852~-module(ubf). + +-compile(export_all). + +-export([decode_init/0, decode/1, decode/2, encode/1, encode/2]). +-export([encode_print/1, ubf2term/1, deabstract/1]). + +... + +Connection closed by foreign host. +[joe@enfield joe]$ exit + +

+ + + + + + + diff --git a/doc/src/home.ehtml b/doc/src/home.ehtml index 9606600..515e9fc 100644 --- a/doc/src/home.ehtml +++ b/doc/src/home.ehtml @@ -1,7 +1,15 @@ layout.mac -
+

+Pre-release. Be warned. Things change frequently +

+

+

diff --git a/doc/src/home.ehtml~ b/doc/src/home.ehtml~ index d1d4a1b..9606600 100644 --- a/doc/src/home.ehtml~ +++ b/doc/src/home.ehtml~ @@ -1,53 +1,54 @@ layout.mac -
-

Magna virtus tua et vivebam etiam Et quoniam cum me, formasti mihi quasi -necesse esset nisi vero; illa prior. Item si cum in quam me urgeret -quod non est, innocentia est, fit, ut eam ut vides, haec ipsa tamen -loqui quoniam itaque. -

Iactabam domine, et confiteri me delicta mea, -deus, es domine, non servientibus (et magistris a paedagogis et mineris -ingentes miserias)? Salus tua, relicto te vult homo circumferens -mortalitem suam, circumferens mortalitem inrisormeus, cui loquor.

- -

Hocadum i et confiteri me delicta mea, -deus, es domine, non servientibus (et magistris a paedagogis et mineris -ingentes miserias)? Salus tua, relicto te vult homo circumferens -www.dedicated-servers.co.uk -ingentes miserias)? Salus tua, relicto te vult homo circumferens. - -

- -

- -

-

- -

+

UBF is a language for transporting and describing complex data structures across a network. It has two components:

    -
  • Recode this using a nice red color - done -
  • Make sure it passes html_check -
  • Change ehtml to write the output files in a different -directory -
  • Write a makefile for this. -
+
  • +UBF(A) is a data transport format, roughly +equivalent to well-formed XML. + +
  • UBF(B) is a programming langauge +for describing types in UBF(A) and protocols between clients +and servers. +UBF(B) is roughly equivalent to to Verified XML, +XML-schemas, SOAP and WDSL. + + + +

    While the XML series of languages had the goal of having a human +readable format the UBF languages take the opposite view and provide a +"machine friendly" format. + +

    UBF is designed to be easy to implement. As a proof of concept - UBF drivers +For Erlang, Oz, Java and TCL can be found in the download area. +Implementors are welcome to add new languages. + +

    UBF is designed to be "language neutral" - UBF(A) defines a +language neutral binary format for transporting data across a +network. UBF(B) is a type system for describing client/server +interactions which use UBF(A). + +

    Programming by Contract

    +
    + +
    + +

    Central to UBF is the idea of a "contract" which regulates the +set of legal conversations that can take place between a client and a server. + +

    A software component (the contract checker) is place between a client and server which checks that all interactions between thew client and server are legal. + +

    The digram shows a Java client talking to a C++ server. + + +

  • diff --git a/doc/src/javac.ehtml b/doc/src/javac.ehtml new file mode 100644 index 0000000..b6f3516 --- /dev/null +++ b/doc/src/javac.ehtml @@ -0,0 +1,22 @@ +layout.mac + + +
    + +Java clients + + + +

    Not yet written. + +

    + + + + + + + diff --git a/doc/src/javac.ehtml~ b/doc/src/javac.ehtml~ new file mode 100644 index 0000000..e7a1b08 --- /dev/null +++ b/doc/src/javac.ehtml~ @@ -0,0 +1,24 @@ +layout.mac + + +
    + +Erlang servers + + + +

    an example of a server plugin + +../../file_plugin.erl + +

    + + + + + + + diff --git a/doc/src/messagebox.ehtml b/doc/src/messagebox.ehtml new file mode 100644 index 0000000..aaa4ce5 --- /dev/null +++ b/doc/src/messagebox.ehtml @@ -0,0 +1,20 @@ +layout.mac + + +
    + +

    Message box

    + +

    Not yet wrtten - will be something like nntp. + +

    + + + + + + + diff --git a/doc/src/messagebox.ehtml~ b/doc/src/messagebox.ehtml~ new file mode 100644 index 0000000..34155e5 --- /dev/null +++ b/doc/src/messagebox.ehtml~ @@ -0,0 +1,35 @@ +layout.mac + + +
    + +

    File server

    + +

    Description

    +

    The contract

    + +../../file_plugin.con + +

    A telnet session

    + +

    A full telnet session using the server can be found in the +quick start tutorial + +

    An Erlang client

    +../../file_client.erl + +

    The Erlang file server plugin

    + +../../file_plugin.erl + +
    + + + + + + + diff --git a/file_client.beam b/file_client.beam index 4c274e2..b59ebeb 100644 Binary files a/file_client.beam and b/file_client.beam differ diff --git a/file_plugin.beam b/file_plugin.beam index 447cea3..a38bce6 100644 Binary files a/file_plugin.beam and b/file_plugin.beam differ diff --git a/find.beam b/find.beam index 0d4e480..433db70 100644 Binary files a/find.beam and b/find.beam differ diff --git a/irc_client b/irc_client index ae0e22c..25c9c6f 100755 --- a/irc_client +++ b/irc_client @@ -1,2 +1,3 @@ #! /bin/sh -erl -noshell -s irc_client batch $1 +make +erl -noshell -s irc_client_gs batch $1 diff --git a/irc_client.beam b/irc_client.beam index 83a2757..8ed7393 100644 Binary files a/irc_client.beam and b/irc_client.beam differ diff --git a/irc_client.erl b/irc_client.erl index abbe5e2..9f2482f 100644 --- a/irc_client.erl +++ b/irc_client.erl @@ -25,8 +25,6 @@ start(Nick) -> end, io:format("client stops~n"). - - loop(Pid, Group, Gs, Nick) -> io:format("Status: Nick=~s Group=~s Joined groups=~p~n",[Nick, Group, Gs]), case io:get_line('> ') of diff --git a/irc_client_gs.beam b/irc_client_gs.beam index d2e1e64..58490c5 100644 Binary files a/irc_client_gs.beam and b/irc_client_gs.beam differ diff --git a/irc_client_gs.erl b/irc_client_gs.erl index cf1e8b0..be97562 100644 --- a/irc_client_gs.erl +++ b/irc_client_gs.erl @@ -7,21 +7,34 @@ -define(S(X), {'#S',X}). s(X) -> {'#S', X}. -start() -> - spawn(fun() -> init1() end). +batch([Nick]) -> + start(atom_to_list(Nick)). + +start(Nick) -> + spawn(fun() -> init1(Nick) end). -init1() -> - {ok, Pid, Name} = client:start("localhost", 2000), - {reply, {ok,yes}, start} = rpc(Pid, {startService, s("irc"), []}), - Self = self(), - client:install_handler(Pid, fun(M) -> - send_self(M, Self) - end), - case rpc(Pid, logon) of - {reply, {ok,?S(Nick)}, active} -> - init(Pid, Nick); - _ -> - exit(connect) +init1(Nick) -> + case client:start("enfield.sics.se", 2000) of + {ok, Pid, Name} -> + {reply, {ok,yes}, start} = rpc(Pid, {startService, s("irc"), []}), + client:install_handler(Pid, fun print_msg/1), + {reply, _, _} = rpc(Pid, logon), + Self = self(), + client:install_handler(Pid, fun(M) -> + send_self(M, Self) + end), + case rpc(Pid, {nick, s(Nick)}) of + {reply, nickInUse, _} -> + client:stop(Pid), + io:format("Nick was in use try again~n"), + erlang:halt(); + {reply, nickChanged, active} -> + init(Pid, Nick) + end, + io:format("client stops~n"); + {error, socket} -> + io:format("Cannot make TCP connection~n"), + erlang:halt() end. init(Pid, Nick) -> @@ -32,6 +45,7 @@ init(Pid, Nick) -> L1 = gs:label(W, [{x,10},{y,10},{label,{text,"Nick:" ++ Nick}}]), E1=gs:entry(W, [{x,10},{y,40},{width, 120}]), gs:button(W,[{x,130},{y,40},{data, join},{label,{text,"Join Group"}}]), + gs:config(E1, {text, "erlang"}), E2=gs:entry(W, [{x,10},{y,70},{width, 120}]), gs:button(W,[{x,130},{y,70}, {data,nick},{label,{text,"Change Nick"}}]), gs:button(W,[{x,10},{y,110}, {data,quit}, {label,{text,"Quit"}}]), @@ -52,6 +66,17 @@ loop(S, Dict, Pid, L1, E1, E2) -> loop(S, Dict, Pid, L1, E1, E2) end, loop(S, Dict, Pid, L1, E1, E2); + {gs,_,click,{leave,Group},_} -> + io:format("I leave: ~s~n",[Group]), + case dict:find(Group, Dict) of + {ok, {W,_}} -> + gs:destroy(W), + Dict1 = dict:erase(Group, Dict), + rpc(Pid, {leave, s(Group)}), + loop(S, Dict1, Pid, L1, E1, E2); + error -> + loop(S, Dict, Pid, L1, E1, E2) + end; {gs,_,click,join,_} -> Group = gs:read(E1, text), io:format("Join:~s~n",[Group]), @@ -70,25 +95,40 @@ loop(S, Dict, Pid, L1, E1, E2) -> end end; {gs,_,click,quit,_} -> - exit(1); + erlang:halt(); {gs,Obj,keypress,G,['Return'|_]} -> Str = gs:read(Obj, text), + gs:config(Obj, {text, ""}), io:format("Send: ~s to ~s~n",[Str, G]), rpc(Pid, {msg, s(G), s(Str ++ "\n")}), loop(S, Dict, Pid, L1, E1, E2); + {gs,Obj,keypress,G,_} -> + loop(S, Dict, Pid, L1, E1, E2); + {event, {leaves, Who, Group}} -> + display(Group, Dict, Who ++ " leaves the group\n"), + loop(S, Dict, Pid, L1, E1, E2); + {event, {joins, Who, Group}} -> + display(Group, Dict, Who ++ " joins the group\n"), + loop(S, Dict, Pid, L1, E1, E2); + {event, {changesName, Old, New, Group}} -> + display(Group, Dict, Old ++ " changes name to " ++ New ++ "\n"), + loop(S, Dict, Pid, L1, E1, E2); {event, {msg, From, Group, Msg}} -> - case dict:find(Group, Dict) of - {ok, {W, Txt}} -> - gs:config(Txt, {insert, {'end', From ++ " > " ++ Msg}}); - error -> - io:format("Msg:~s ~s ~s~n",[From, Group, Msg]) - end, + display(Group, Dict, From ++ " > " ++ Msg), loop(S, Dict, Pid, L1, E1, E2); X -> io:format("man: got other: ~w~n",[X]), loop(S, Dict, Pid, L1, E1, E2) end. +display(Group, Dict, Str) -> + case dict:find(Group, Dict) of + {ok, {W, Txt}} -> + gs:config(Txt, {insert, {'end', Str}}); + error -> + io:format("Cannot display:~s ~s~n",[Group, Str]) + end. + new_group(S, Name) -> Width=450,Height=350, W = gs:window(S,[{title,"Name"}, @@ -125,3 +165,6 @@ print_msg(X) -> io:format("==> ~p~n",[Other]) end, fun print_msg/1. + + + diff --git a/irc_client_gs.erl~ b/irc_client_gs.erl~ new file mode 100644 index 0000000..5e3fad5 --- /dev/null +++ b/irc_client_gs.erl~ @@ -0,0 +1,170 @@ +-module(irc_client_gs). + +-compile(export_all). + +-import(client, [rpc/2]). + +-define(S(X), {'#S',X}). +s(X) -> {'#S', X}. + +batch([Nick]) -> + start(atom_to_list(Nick)). + +start(Nick) -> + spawn(fun() -> init1(Nick) end). + +init1(Nick) -> + case client:start("localhost", 2000) of + {ok, Pid, Name} -> + {reply, {ok,yes}, start} = rpc(Pid, {startService, s("irc"), []}), + client:install_handler(Pid, fun print_msg/1), + {reply, _, _} = rpc(Pid, logon), + Self = self(), + client:install_handler(Pid, fun(M) -> + send_self(M, Self) + end), + case rpc(Pid, {nick, s(Nick)}) of + {reply, nickInUse, _} -> + client:stop(Pid), + io:format("Nick was in use try again~n"), + erlang:halt(); + {reply, nickChanged, active} -> + init(Pid, Nick) + end, + io:format("client stops~n"); + {error, socket} -> + io:format("Cannot make TCP connection~n"), + erlang:halt() + end. + +init(Pid, Nick) -> + S=gs:start(), + Width=250,Height=170, + W= gs:window(S,[{title,"IRC client"}, + {width,Width},{height,Height},{map,true}]), + L1 = gs:label(W, [{x,10},{y,10},{label,{text,"Nick:" ++ Nick}}]), + E1=gs:entry(W, [{x,10},{y,40},{width, 120}]), + gs:button(W,[{x,130},{y,40},{data, join},{label,{text,"Join Group"}}]), + gs:config(E1, {text, "erlang"}), + E2=gs:entry(W, [{x,10},{y,70},{width, 120}]), + gs:button(W,[{x,130},{y,70}, {data,nick},{label,{text,"Change Nick"}}]), + gs:button(W,[{x,10},{y,110}, {data,quit}, {label,{text,"Quit"}}]), + loop(S, dict:new(), Pid, L1, E1,E2). + +loop(S, Dict, Pid, L1, E1, E2) -> + receive + {gs,_,click,nick,_} -> + Nick = gs:read(E2, text), + io:format("Change nick to:~s~n",[Nick]), + case rpc(Pid, {nick, s(Nick)}) of + {reply, nickInUse, _} -> + gs:config(E2, {text, "** bad nick **"}), + loop(S, Dict, Pid, L1, E1, E2); + {reply, nickChanged, active} -> + io:format("nick was changed~n"), + gs:config(L1, {label, {text, "Nick: " ++ Nick}}), + loop(S, Dict, Pid, L1, E1, E2) + end, + loop(S, Dict, Pid, L1, E1, E2); + {gs,_,click,{leave,Group},_} -> + io:format("I leave: ~s~n",[Group]), + case dict:find(Group, Dict) of + {ok, {W,_}} -> + gs:destroy(W), + Dict1 = dict:erase(Group, Dict), + rpc(Pid, {leave, s(Group)}), + loop(S, Dict1, Pid, L1, E1, E2); + error -> + loop(S, Dict, Pid, L1, E1, E2) + end; + {gs,_,click,join,_} -> + Group = gs:read(E1, text), + io:format("Join:~s~n",[Group]), + case Group of + "" -> + loop(S, Dict, Pid, L1, E1, E2); + _ -> + case dict:find(Group, Dict) of + {ok, W} -> + loop(S, Dict, Pid, L1, E1, E2); + error -> + W = new_group(S, Group), + rpc(Pid, {join, s(Group)}), + loop(S, dict:store(Group, W, Dict), Pid, + L1, E1, E2) + end + end; + {gs,_,click,quit,_} -> + erlang:halt(); + {gs,Obj,keypress,G,['Return'|_]} -> + Str = gs:read(Obj, text), + gs:config(Obj, {text, ""}), + io:format("Send: ~s to ~s~n",[Str, G]), + rpc(Pid, {msg, s(G), s(Str ++ "\n")}), + loop(S, Dict, Pid, L1, E1, E2); + {gs,Obj,keypress,G,_} -> + loop(S, Dict, Pid, L1, E1, E2); + {event, {leaves, Who, Group}} -> + display(Group, Dict, Who ++ " leaves the group\n"), + loop(S, Dict, Pid, L1, E1, E2); + {event, {joins, Who, Group}} -> + display(Group, Dict, Who ++ " joins the group\n"), + loop(S, Dict, Pid, L1, E1, E2); + {event, {changesName, Old, New, Group}} -> + display(Group, Dict, Old ++ " changes name to " ++ New ++ "\n"), + loop(S, Dict, Pid, L1, E1, E2); + {event, {msg, From, Group, Msg}} -> + display(Group, Dict, From ++ " > " ++ Msg), + loop(S, Dict, Pid, L1, E1, E2); + X -> + io:format("man: got other: ~w~n",[X]), + loop(S, Dict, Pid, L1, E1, E2) + end. + +display(Group, Dict, Str) -> + case dict:find(Group, Dict) of + {ok, {W, Txt}} -> + gs:config(Txt, {insert, {'end', Str}}); + error -> + io:format("Cannot display:~s ~s~n",[Group, Str]) + end. + +new_group(S, Name) -> + Width=450,Height=350, + W = gs:window(S,[{title,"Name"}, + {width,Width},{height,Height},{map,true}]), + L1 = gs:label(W, [{x,10},{y,10},{label,{text,"Group:" ++ Name}}]), + T1 = gs:editor(W, [{x,10},{y,40}, + {width,Width-20}, + {height,Height-120}, + {vscroll, right}]), + E1 = gs:entry(W, [{x,10},{y,Height-70},{width, Width-20}, + {data, Name}, + {keypress,true}]), + gs:button(W,[{x,10},{y,Height-35}, + {data, {leave, Name}},{label,{text,"Leave Group"}}]), + {W, T1}. + +send_self(Msg, Pid) -> + Pid ! {event, ubf:deabstract(Msg)}, + fun(I) -> send_self(I, Pid) end. + + +print_msg(X) -> + case ubf:deabstract(X) of + {joins, Who, Group} -> + io:format("~s joins the group ~s~n",[Who, Group]); + {leaves, Who, Group} -> + io:format("~s leaves the group ~s~n",[Who, Group]); + {msg, Who, Group, Msg} -> + io:format("Msg from ~s to ~s => ~s~n",[Who, Group,Msg]); + {changesName, Old, New, Group} -> + io:format("~s is now called ~s in group ~s~n", + [Old, New, Group]); + Other -> + io:format("==> ~p~n",[Other]) + end, + fun print_msg/1. + + + diff --git a/irc_plugin.beam b/irc_plugin.beam index 67f692e..4bc49d1 100644 Binary files a/irc_plugin.beam and b/irc_plugin.beam differ diff --git a/leex.beam b/leex.beam index a809076..612f501 100644 Binary files a/leex.beam and b/leex.beam differ diff --git a/plugin_handler.beam b/plugin_handler.beam index eb5d252..b618608 100644 Binary files a/plugin_handler.beam and b/plugin_handler.beam differ diff --git a/proc_socket_server.beam b/proc_socket_server.beam index ca2bd5e..a76781b 100644 Binary files a/proc_socket_server.beam and b/proc_socket_server.beam differ diff --git a/server.beam b/server.beam index 316bbd9..c7b6271 100644 Binary files a/server.beam and b/server.beam differ diff --git a/server_plugin.beam b/server_plugin.beam index 4d1b9bc..ae8fe79 100644 Binary files a/server_plugin.beam and b/server_plugin.beam differ diff --git a/test.beam b/test.beam index 08828ae..5a6ba5a 100644 Binary files a/test.beam and b/test.beam differ diff --git a/test_plugin.beam b/test_plugin.beam index f3ea72a..529e60c 100644 Binary files a/test_plugin.beam and b/test_plugin.beam differ diff --git a/ubf.beam b/ubf.beam index 42dd798..d8877a9 100644 Binary files a/ubf.beam and b/ubf.beam differ diff --git a/ubf_driver.beam b/ubf_driver.beam index 3e26f34..cf2b818 100644 Binary files a/ubf_driver.beam and b/ubf_driver.beam differ diff --git a/ubf_driver.erl b/ubf_driver.erl index 48bd12a..899ab79 100644 --- a/ubf_driver.erl +++ b/ubf_driver.erl @@ -35,7 +35,7 @@ loop(Socket, Pid, Cont) -> {Pid, Term} -> %% io:format("ubf_driver sending:~p~n",[Term]), Data = ubf:encode(Term), - io:format("ubf_driver sending:~s~n",[Data]), + %% io:format("ubf_driver sending:~s~n",[Data]), gen_tcp:send(Socket, Data), loop(Socket, Pid, Cont); stop -> @@ -49,7 +49,7 @@ loop(Socket, Pid, Cont) -> exit(socket_closed); {tcp, Socket, Data} -> T = binary_to_list(Data), - io:format("ubf driver received raw=|~s|~n",[T]), + %% io:format("ubf driver received raw=|~s|~n",[T]), Cont1 = ubf:decode(T, Cont), %% io:format("Cont1=~p~n",[Cont1]), handle_data(Socket, Pid, Cont1); diff --git a/ubf_test.beam b/ubf_test.beam index 6a2c196..7e86e8f 100644 Binary files a/ubf_test.beam and b/ubf_test.beam differ diff --git a/ubf_utils.beam b/ubf_utils.beam index 95474c0..3ab592b 100644 Binary files a/ubf_utils.beam and b/ubf_utils.beam differ