Vanadium Chat is a peer-to-peer chat application that demonstrates common usage patterns for the Vanadium libraries.
There are currently two clients: a web client and a shell client.
Please file bugs and feature requests in our issue tracker.
-
Install the Vanadium Chrome Extension.
-
Visit the chat webpage: https://chat.v.io/
These instructions assume you have an up-to-date Vanadium development
environment inside $JIRI_ROOT
.
In order to run the shell client:
cd $JIRI_ROOT/release/projects/chat
make run-shell
This will generate Vanadium credentials (a new principal and a blessing) the first time it is run, which may prompt you for your Google Account password and caveats on the blessing in your web browser. You will also be prompted to select a password for encrypting the credentials on local disk. This is optional.
If you'd only like to build the binary, not run it:
cd $JIRI_ROOT/release/projects/chat
make build-shell
Vanadium Chat is a peer-to-peer chat application. That means that clients connect directly to each-other when sending messages.
A side effect of its peer-to-peer nature is that messages are not guaranteed to arrive in the same order at all clients.
There is currently no storage of chat history. Aside from tracking the list of chat room peers, the application is stateless.
The chat application relies on servers for three things:
-
Chat clients mount themselves on a mounttable server, so that peers can find them.
-
All RPCs are routed through a Vanadium proxy, which allows connections to peers who might be behing a NAT.
-
A web server is used to serve web assets to chat clients.
A particular directory in the namespace --
users/vanadium.bot@gmail.com/apps/chat/public
-- has been created with
permissions that allow anybody to mount and glob inside that directory.
The following command sets the Resolve
permission on
users/vanadium.bot@gmail.com
to allow anybody to resolve names inside that
directory.
namespace permissions set users/vanadium.bot@gmail.com - << EOF
{
"Admin":{
"In":["dev.v.io/u/vanadium.bot@gmail.com"]
},
"Resolve":{
"In":["..."]
}
}
EOF
The next command sets the Read
and Create
permissions for
users/vanadium.bot@gmail.com/apps/chat
, to allow anybody to list the names
inside that directory, and create a new name in that directory.
namespace permissions set users/vanadium.bot@gmail.com/apps/chat - << EOF
{
"Admin":{
"In":["dev.v.io/u/vanadium.bot@gmail.com"]
},
"Read":{
"In":["..."]
},
"Create":{
"In":["..."]
}
}
EOF
When a client joins the chat room, it generates a random string and attempts to
mount itself in the public mounttable server under the name
users/vanadium.bot@gmail.com/apps/chat/public/<random_string>
. If that name
is already taken, the client will pick a new random string and try again.
The client sets permissions on that name which prevent peers from mounting on the same name, but allow them to resolve that name to the client's endpoint. The client essentially "owns" that particular name in the mounttable.
To find other peers, the client sends a Glob
RPC to the mounttable, asking
for all names matching users/vanadium.bot@gmail.com/apps/chat/public/*
. The
results of this Glob correspond to peers in the chat room. Each result
contains the peer's endpoint and its blessing pattern. The
blessing pattern is used to identify the peer in the chat UI, and to ensure
that messages are only sent to intended recipients.
Chat currently only supports a single chat room called public
, but eventually
it will support multiple rooms, including private rooms visible to only certain
clients.
Each chat client implements a Chat
interface defined in the VDL file
clients/shell/src/chat/vdl/chat.vdl
.
This interface has a single method, called SendMessage
, which takes a string
argument (the message) and returns an error, which can be nil.
type Chat interface {
// SendMessage sends a message to a user.
SendMessage(text string) error {}
}
When a client Alice wants to send a message to her peer Bob, she finds Bob's
entry in the results of the mounttable Glob
. She invokes a Vanadium RPC on
that name, calling the SendMessage
method with her message. She passes in
Bob's expected remote blessings to the RPC to ensure that the message will
only be sent to Bob, and not to some other malicious client who might have
somehow mounted under Bob's name. Any returned error indicates an error in
transmission.
This section describes how to set up a local environment to run the chat clients, and how to build and test the clients.
To get the chat environment running locally, you will need to run the mounttable and proxyd servers with a valid identity. The following script will request an identity from the identity service and run mounttabled and proxyd with that identity.
./tools/services.sh
You will be prompted to log in with your Google account in order to get an identity. You will also be asked to select a blessing. Leave the values at their default setting and click "Bless".
Once the identity is in place, the script runs mounttabled on port 8101, and proxyd on port 8100. The proxy mounts itself in the mounttable under the name "proxy".
The chat.vdl
file defines the server interface implemented by each chat client.
That file can be found in clients/shell/src/chat/vdl/chat.vdl
.
Running make gen-vdl
will build the generated JavaScript and Go files in
clients/web/js/chat/vdl/index.js
and clients/shell/src/vdl/chat.vdl.go
which are included by the web and shell clients, respectively.
The web client is a single page application written with React.
All code is inside clients/web
. The Vanadium-specific code is in
clients/web/js/channel.js
.
A web server is used to serve the js, html, and css to the browser. You will need the Vanadium extension to run the app.
You can build the web assets and run the web server with the following command:
NOMINIFY=1 make serve-web
This will run the web server on port 4000. The NOMINIFY environment variable prevents the code from being minified, making debugging easier.
Once the web server is running, visit the chat app page, and pass the names of the mountable and proxyd in query params:
http://localhost:4000?mounttable=/localhost:8101&proxy=proxy
There is a simple suite of web client tests in clients/web/test
. You can run
the web client tests with make test-web
.
The shell client is written in Go with the Gocui UI library. All
the chat code is in clients/shell/src/chat
. The entry-point is in
clients/shell/src/chat/main.go
. The Vanadium-specific code is in
clients/shell/src/chat/channel.go
.
The chat binary is built into clients/shell/bin/chat
. You can build it with:
make build-shell
In order for the chat client to talk to the mounttable and proxy servers, you will need to get an identity from the identity server:
export V23_CREDENTIALS=/tmp/vanadium-credentials
$JIRI_ROOT/release/go/bin/principal seekblessings
Then run the binary and pass in the v23.namespace.root and v23.proxy flags.
./clients/shell/bin/chat --mounttable=/localhost:8101 --proxy=proxy
There is a simple suite of tests for the shell client in
clients/shell/src/channel_test.go
. You can run these tests with make test-shell
.