Commit 533e4b9b authored by Juliusz Chroboczek's avatar Juliusz Chroboczek

Version the protocol.

The handshake message now contains a list of supported protocol
versions.  Version mismatch is currently a warning, but it will be a
hard error in the future.
parent b55e531a
Galene 0.5.6 (unreleased): Galene 0.6 (unreleased):
* Version the protocol: the handshake message now contains a version
number, and the server will warn if it is incorrect. This will become
a hard error in the future.
* Rework the peer-to-peer file transfer protocol. It now lives in * Rework the peer-to-peer file transfer protocol. It now lives in
protocol.js, which makes it easy to use by third-party clients. protocol.js, which makes it easy to use by third-party clients.
* Extend the authorization protocol to allow the authorization server to * Extend the authorization protocol to allow the authorization server to
......
...@@ -81,12 +81,15 @@ start pipelining messages to the server. ...@@ -81,12 +81,15 @@ start pipelining messages to the server.
```javascript ```javascript
{ {
type: 'handshake', type: 'handshake',
version: ["1"],
id: id id: id
} }
``` ```
If the field `id` is absent, then the peer doesn't originate streams (it The version field contains an array of supported protocol versions; the
is a server). client may announce multiple versions, but the server will always reply
with a singleton. If the field `id` is absent, then the peer doesn't
originate streams.
A peer may, at any time, send a `ping` message. A peer may, at any time, send a `ping` message.
......
...@@ -110,6 +110,7 @@ func (c *webClient) PushClient(group, kind, id, username string, perms []string, ...@@ -110,6 +110,7 @@ func (c *webClient) PushClient(group, kind, id, username string, perms []string,
type clientMessage struct { type clientMessage struct {
Type string `json:"type"` Type string `json:"type"`
Version []string `json:"version"`
Kind string `json:"kind,omitempty"` Kind string `json:"kind,omitempty"`
Id string `json:"id,omitempty"` Id string `json:"id,omitempty"`
Replace string `json:"replace,omitempty"` Replace string `json:"replace,omitempty"`
...@@ -854,6 +855,15 @@ func StartClient(conn *websocket.Conn) (err error) { ...@@ -854,6 +855,15 @@ func StartClient(conn *websocket.Conn) (err error) {
return return
} }
versionError := true
if m.Version != nil {
for _, v := range m.Version {
if v == "1" {
versionError = false
}
}
}
c := &webClient{ c := &webClient{
id: m.Id, id: m.Id,
actionCh: make(chan struct{}, 1), actionCh: make(chan struct{}, 1),
...@@ -878,7 +888,7 @@ func StartClient(conn *websocket.Conn) (err error) { ...@@ -878,7 +888,7 @@ func StartClient(conn *websocket.Conn) (err error) {
c.close(e) c.close(e)
}() }()
return clientLoop(c, conn) return clientLoop(c, conn, versionError)
} }
type pushConnAction struct { type pushConnAction struct {
...@@ -950,7 +960,7 @@ func addnew(v string, l []string) []string { ...@@ -950,7 +960,7 @@ func addnew(v string, l []string) []string {
return l return l
} }
func clientLoop(c *webClient, ws *websocket.Conn) error { func clientLoop(c *webClient, ws *websocket.Conn, versionError bool) error {
read := make(chan interface{}, 1) read := make(chan interface{}, 1)
go clientReader(ws, read, c.done) go clientReader(ws, read, c.done)
...@@ -962,12 +972,25 @@ func clientLoop(c *webClient, ws *websocket.Conn) error { ...@@ -962,12 +972,25 @@ func clientLoop(c *webClient, ws *websocket.Conn) error {
defer ticker.Stop() defer ticker.Stop()
err := c.write(clientMessage{ err := c.write(clientMessage{
Type: "handshake", Type: "handshake",
Version: []string{"1"},
}) })
if err != nil { if err != nil {
return err return err
} }
if versionError {
c.write(clientMessage{
Type: "usermessage",
Kind: "warning",
Dest: c.id,
Privileged: true,
Value: "This client is using an unknown protocol version.\n" +
"Perhaps it needs upgrading?\n" +
"Trying to continue, things may break.",
})
}
for { for {
select { select {
case m, ok := <-read: case m, ok := <-read:
...@@ -1384,22 +1407,22 @@ func handleClientMessage(c *webClient, m clientMessage) error { ...@@ -1384,22 +1407,22 @@ func handleClientMessage(c *webClient, m clientMessage) error {
log.Printf("Join group: %v", err) log.Printf("Join group: %v", err)
} }
return c.write(clientMessage{ return c.write(clientMessage{
Type: "joined", Type: "joined",
Kind: "fail", Kind: "fail",
Group: m.Group, Group: m.Group,
Username: c.username, Username: c.username,
Value: s, Value: s,
}) })
} }
if redirect := g.Description().Redirect; redirect != "" { if redirect := g.Description().Redirect; redirect != "" {
// We normally redirect at the HTTP level, but the group // We normally redirect at the HTTP level, but the group
// description could have been edited in the meantime. // description could have been edited in the meantime.
return c.write(clientMessage{ return c.write(clientMessage{
Type: "joined", Type: "joined",
Kind: "redirect", Kind: "redirect",
Group: m.Group, Group: m.Group,
Username: c.username, Username: c.username,
Value: redirect, Value: redirect,
}) })
} }
c.group = g c.group = g
......
...@@ -223,6 +223,7 @@ function ServerConnection() { ...@@ -223,6 +223,7 @@ function ServerConnection() {
/** /**
* @typedef {Object} message * @typedef {Object} message
* @property {string} type * @property {string} type
* @property {Array<string>} [version]
* @property {string} [kind] * @property {string} [kind]
* @property {string} [id] * @property {string} [id]
* @property {string} [replace] * @property {string} [replace]
...@@ -289,6 +290,7 @@ ServerConnection.prototype.connect = async function(url) { ...@@ -289,6 +290,7 @@ ServerConnection.prototype.connect = async function(url) {
this.socket.onopen = function(e) { this.socket.onopen = function(e) {
sc.send({ sc.send({
type: 'handshake', type: 'handshake',
version: ["1"],
id: sc.id, id: sc.id,
}); });
if(sc.onconnected) if(sc.onconnected)
...@@ -322,6 +324,8 @@ ServerConnection.prototype.connect = async function(url) { ...@@ -322,6 +324,8 @@ ServerConnection.prototype.connect = async function(url) {
let m = JSON.parse(e.data); let m = JSON.parse(e.data);
switch(m.type) { switch(m.type) {
case 'handshake': case 'handshake':
if(!m.version || !m.version.includes('1'))
console.warn(`Unexpected protocol version ${m.version}.`);
break; break;
case 'offer': case 'offer':
sc.gotOffer(m.id, m.label, m.source, m.username, sc.gotOffer(m.id, m.label, m.source, m.username,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment