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
+
+
+
+
+
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
+
+
+
+
+
+
+
+
+ |
+
+
+ |
+
+
+ |
+ |
+
+
+ |
+
+
+
+
+
+
+ |
+
+
+ |
+
+
+ |
+ |
+
+
+ |
+
+
+
+
+
+
+ |
+
+
+ |
+
+
+ |
+ |
+
+
+ |
+
+
+
+
+
+
+ |
+
+
+ |
+
+
+ |
+ |
+
+
+ |
+
+
+
+
+ |
+
+
+ |
+ |
+ |  |
+ | |
+
+ 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
+
+
+
 |
|
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
+
+
+
+
+
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
+
+
+
+
+
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.
-
-
-
-
-
-
-This design was shamlessly stolen from
-http://hadess.net/.
-and recoded in Erlang.
-
-
-
-
+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
|