blob: 00f1d4e12cbd0df35605722447156c3b9be392c6 [file] [log] [blame] [view]
# Vanadium Chat
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][client-web] and a [shell
client][client-shell].
Please file bugs and feature requests in our [issue tracker][issue-tracker].
## Running a chat client
<a name="client-web"></a>
### Running the web client
1. Install the [Vanadium Chrome Extension][vanadium-extension].
2. Visit the chat webpage: <https://chat.v.io/>
<a name="client-shell"></a>
### Running the shell client
These instructions assume you have an up-to-date [Vanadium development
environment][vanadium-installation] 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
<a name="architecture"></a>
## Chat architecture
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:
1. Chat clients mount themselves on a [mounttable server][mounttable], so that
peers can find them.
2. All RPCs are routed through a Vanadium proxy, which allows connections to
peers who might be behing a NAT.
3. A web server is used to serve web assets to chat clients.
### Client discoverability
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][mounttable] 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][blessings]. 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.
### Sending messages
Each chat client implements a `Chat` interface defined in the [VDL][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.
<a name="developing"></a>
## Developing Vanadium Chat
This section describes how to set up a local environment to run the chat
clients, and how to build and test the clients.
### Running mounttabled and proxyd locally
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".
### Generating VDL dependencies
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.
### Developing the web client
The web client is a [single page application][spa] written with [React][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][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`.
### Developing the shell client
The shell client is written in Go with the [Gocui][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`.
[blessings]: https://vanadium.github.io/glossary.html#blessing
[client-shell]: #client-shell
[client-web]: #client-web
[gocui]: https://github.com/jroimartin/gocui
[issue-tracker]: https://github.com/vanadium/chat/issues
[mounttable]: https://vanadium.github.io/glossary.html#mount-table
[react]: http://facebook.github.io/react/
[spa]: http://en.wikipedia.org/wiki/Single-page_application
[vanadium-extension]: https://chrome.google.com/webstore/detail/vanadium-extension/jcaelnibllfoobpedofhlaobfcoknpap
[vanadium-installation]: https://vanadium.github.io/installation/
[vdl]: https://vanadium.github.io/glossary.html#vandium-definition-language-vdl-