WIP: new server protocol
This commit is contained in:
parent
5dd91c7311
commit
a74b1b1e3a
|
@ -22,7 +22,7 @@ def get_db(dbfile, stderr=sys.stderr):
|
|||
raise DBError("Unable to create/open db file %s: %s" % (dbfile, e))
|
||||
db.row_factory = sqlite3.Row
|
||||
|
||||
VERSION = 1
|
||||
VERSION = 2
|
||||
if must_create:
|
||||
schema = get_schema(VERSION)
|
||||
db.executescript(schema)
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
|
||||
-- note: anything which isn't an boolean, integer, or human-readable unicode
|
||||
-- string, (i.e. binary strings) will be stored as hex
|
||||
|
||||
CREATE TABLE `version`
|
||||
(
|
||||
`version` INTEGER -- contains one row, set to 1
|
||||
);
|
||||
|
||||
CREATE TABLE `messages`
|
||||
(
|
||||
`appid` VARCHAR,
|
||||
`channelid` VARCHAR,
|
||||
`side` VARCHAR,
|
||||
`phase` VARCHAR, -- numeric or string
|
||||
-- phase="_allocate" and "_deallocate" are used internally
|
||||
`body` VARCHAR,
|
||||
`server_rx` INTEGER,
|
||||
`msgid` VARCHAR
|
||||
);
|
||||
CREATE INDEX `messages_idx` ON `messages` (`appid`, `channelid`);
|
||||
|
||||
CREATE TABLE `usage`
|
||||
(
|
||||
`type` VARCHAR, -- "rendezvous" or "transit"
|
||||
`started` INTEGER, -- seconds since epoch, rounded to one day
|
||||
`result` VARCHAR, -- happy, scary, lonely, errory, pruney
|
||||
-- rendezvous moods:
|
||||
-- "happy": both sides close with mood=happy
|
||||
-- "scary": any side closes with mood=scary (bad MAC, probably wrong pw)
|
||||
-- "lonely": any side closes with mood=lonely (no response from 2nd side)
|
||||
-- "errory": any side closes with mood=errory (other errors)
|
||||
-- "pruney": channels which get pruned for inactivity
|
||||
-- "crowded": three or more sides were involved
|
||||
-- transit moods:
|
||||
-- "errory": this side have the wrong handshake
|
||||
-- "lonely": good handshake, but the other side never showed up
|
||||
-- "happy": both sides gave correct handshake
|
||||
`total_bytes` INTEGER, -- for transit, total bytes relayed (both directions)
|
||||
`total_time` INTEGER, -- seconds from start to closed, or None
|
||||
`waiting_time` INTEGER -- seconds from start to 2nd side appearing, or None
|
||||
);
|
||||
CREATE INDEX `usage_idx` ON `usage` (`started`);
|
98
src/wormhole/server/db-schemas/v2.sql
Normal file
98
src/wormhole/server/db-schemas/v2.sql
Normal file
|
@ -0,0 +1,98 @@
|
|||
|
||||
-- note: anything which isn't an boolean, integer, or human-readable unicode
|
||||
-- string, (i.e. binary strings) will be stored as hex
|
||||
|
||||
CREATE TABLE `version`
|
||||
(
|
||||
`version` INTEGER -- contains one row, set to 2
|
||||
);
|
||||
|
||||
|
||||
-- Wormhole codes use a "nameplate": a short identifier which is only used to
|
||||
-- reference a specific (long-named) mailbox. The codes only use numeric
|
||||
-- nameplates, but the protocol and server allow can use arbitrary strings.
|
||||
CREATE TABLE `nameplates`
|
||||
(
|
||||
`app_id` VARCHAR,
|
||||
`id` VARCHAR PRIMARY KEY,
|
||||
`mailbox_id` VARCHAR, -- really a foreign key
|
||||
`side1` VARCHAR, -- side name, or NULL
|
||||
`side2` VARCHAR -- side name, or NULL
|
||||
);
|
||||
CREATE INDEX `nameplates_idx` ON `nameplates` (`app_id`, `id`);
|
||||
CREATE INDEX `nameplates_mailbox_idx` ON `nameplates` (`app_id`, `mailbox_id`);
|
||||
|
||||
-- Clients exchange messages through a "mailbox", which has a long (randomly
|
||||
-- unique) identifier and a queue of messages.
|
||||
CREATE TABLE `mailboxes`
|
||||
(
|
||||
`app_id` VARCHAR,
|
||||
`id` VARCHAR,
|
||||
`side1` VARCHAR -- side name, or NULL
|
||||
`side2` VARCHAR -- side name, or NULL
|
||||
-- timing data for the (optional) linked nameplate
|
||||
`nameplate_started` INTEGER, -- time when related nameplace was opened
|
||||
`nameplate_second` INTEGER, -- time when second side opened
|
||||
`nameplate_closed` INTEGER, -- time when closed
|
||||
-- timing data for the mailbox itself
|
||||
`started` INTEGER, -- time when opened
|
||||
`second` INTEGER, -- time when second side opened
|
||||
`closed` INTEGER -- time when closed
|
||||
);
|
||||
CREATE INDEX `mailboxes_idx` ON `mailboxes` (`app_id`, `id`);
|
||||
|
||||
CREATE TABLE `messages`
|
||||
(
|
||||
`app_id` VARCHAR,
|
||||
`mailbox_id` VARCHAR,
|
||||
`side` VARCHAR,
|
||||
`phase` VARCHAR, -- numeric or string
|
||||
`body` VARCHAR,
|
||||
`server_rx` INTEGER,
|
||||
`msg_id` VARCHAR
|
||||
);
|
||||
CREATE INDEX `messages_idx` ON `messages` (`app_id`, `mailbox_id`);
|
||||
|
||||
CREATE TABLE `nameplate_usage`
|
||||
(
|
||||
`started` INTEGER, -- seconds since epoch, rounded to "blur time"
|
||||
`total_time` INTEGER, -- seconds from open to last close
|
||||
`result` VARCHAR, -- happy, lonely, pruney, crowded
|
||||
-- nameplate moods:
|
||||
-- "happy": two sides open and close
|
||||
-- "lonely": one side opens and closes (no response from 2nd side)
|
||||
-- "pruney": channels which get pruned for inactivity
|
||||
-- "crowded": three or more sides were involved
|
||||
`waiting_time` INTEGER -- seconds from start to 2nd side appearing, or None
|
||||
);
|
||||
CREATE INDEX `nameplate_usage_idx` ON `nameplate_usage` (`started`);
|
||||
|
||||
CREATE TABLE `mailbox_usage`
|
||||
(
|
||||
`started` INTEGER, -- seconds since epoch, rounded to "blur time"
|
||||
`total_time` INTEGER, -- seconds from open to last close
|
||||
`waiting_time` INTEGER, -- seconds from start to 2nd side appearing, or None
|
||||
`result` VARCHAR -- happy, scary, lonely, errory, pruney
|
||||
-- rendezvous moods:
|
||||
-- "happy": both sides close with mood=happy
|
||||
-- "scary": any side closes with mood=scary (bad MAC, probably wrong pw)
|
||||
-- "lonely": any side closes with mood=lonely (no response from 2nd side)
|
||||
-- "errory": any side closes with mood=errory (other errors)
|
||||
-- "pruney": channels which get pruned for inactivity
|
||||
-- "crowded": three or more sides were involved
|
||||
);
|
||||
CREATE INDEX `mailbox_usage_idx` ON `mailbox_usage` (`started`);
|
||||
|
||||
CREATE TABLE `transit_usage`
|
||||
(
|
||||
`started` INTEGER, -- seconds since epoch, rounded to "blur time"
|
||||
`total_time` INTEGER, -- seconds from open to last close
|
||||
`waiting_time` INTEGER, -- seconds from start to 2nd side appearing, or None
|
||||
`total_bytes` INTEGER, -- total bytes relayed (both directions)
|
||||
`result` VARCHAR -- happy, scary, lonely, errory, pruney
|
||||
-- transit moods:
|
||||
-- "errory": one side gave the wrong handshake
|
||||
-- "lonely": good handshake, but the other side never showed up
|
||||
-- "happy": both sides gave correct handshake
|
||||
);
|
||||
CREATE INDEX `transit_usage_idx` ON `transit_usage` (`started`);
|
|
@ -3,26 +3,47 @@ from twisted.internet import reactor
|
|||
from twisted.python import log
|
||||
from autobahn.twisted import websocket
|
||||
|
||||
# Each WebSocket connection is bound to one "appid", one "side", and zero or
|
||||
# more "channelids". The connection's appid and side are set by the "bind"
|
||||
# message (which must be the first message on the connection). Both must be
|
||||
# set before any other message (allocate, claim, watch, add, deallocate) will
|
||||
# be accepted. Short channel IDs can be obtained from the server with an
|
||||
# "allocate" message. Longer ones can be selected independently by the
|
||||
# client. Channels are maintained (saved from deletion) by a "claim" message
|
||||
# (and also incidentally by "allocate"). Channels are deleted when the last
|
||||
# claim is released with "release".
|
||||
# The WebSocket allows the client to send "commands" to the server, and the
|
||||
# server to send "responses" to the client. Note that commands and responses
|
||||
# are not necessarily one-to-one. All commands provoke an "ack" response
|
||||
# (with a copy of the original message) for timing, testing, and
|
||||
# synchronization purposes. All commands and responses are JSON-encoded.
|
||||
|
||||
# All websocket messages are JSON-encoded. The client can send us "inbound"
|
||||
# messages (marked as "->" below), which may (or may not) provoke immediate
|
||||
# (or delayed) "outbound" messages (marked as "<-"). There is no guaranteed
|
||||
# correlation between requests and responses. In this list, "A -> B" means
|
||||
# that some time after A is received, at least one message of type B will be
|
||||
# sent out (probably).
|
||||
# Each WebSocket connection is bound to one "appid" and one "side", which are
|
||||
# set by the "bind" command (which must be the first command on the
|
||||
# connection), and must be set before any other command will be accepted.
|
||||
|
||||
# All outbound messages include a "server_tx" key, which is a float (seconds
|
||||
# since epoch) with the server clock just before the outbound message was
|
||||
# written to the socket. Unrecognized keys will be ignored.
|
||||
# Each connection can be bound to a single "mailbox" (a two-sided
|
||||
# store-and-forward queue, identified by the "mailbox id": a long, randomly
|
||||
# unique string identifier) by using the "open" command. This protects the
|
||||
# mailbox from idle closure, enables the "add" command (to put new messages
|
||||
# in the queue), and triggers delivery of past and future messages via the
|
||||
# "message" response. The "close" command removes the binding (but note that
|
||||
# it does not enable the subsequent binding of a second mailbox). When the
|
||||
# last side closes a mailbox, its contents are deleted.
|
||||
|
||||
# Additionally, the connection can be bound a single "nameplate", which is
|
||||
# short identifier that makes up the first component of a wormhole code. Each
|
||||
# nameplate points to a single long-id "mailbox". The "allocate" message
|
||||
# determines the shortest available numeric nameplate, reserves it, and
|
||||
# returns the nameplate id. "list" returns a list of all numeric nameplates
|
||||
# which currently have only one side active (i.e. they are waiting for a
|
||||
# partner). The "claim" message reserves an arbitrary nameplate id (perhaps
|
||||
# the receiver of a wormhole connection typed in a code they got from the
|
||||
# sender, or perhaps the two sides agreed upon a code offline and are both
|
||||
# typing it in), and the "release" message releases it. When every side that
|
||||
# has claimed the nameplate has also released it, the nameplate is
|
||||
# deallocated (but they will probably keep the underlying mailbox open).
|
||||
|
||||
# Inbound (client to server) commands are marked as "->" below. Unrecognized
|
||||
# inbound keys will be ignored. Outbound (server to client) responses use
|
||||
# "<-". There is no guaranteed correlation between requests and responses. In
|
||||
# this list, "A -> B" means that some time after A is received, at least one
|
||||
# message of type B will be sent out (probably).
|
||||
|
||||
# All responses include a "server_tx" key, which is a float (seconds since
|
||||
# epoch) with the server clock just before the outbound response was written
|
||||
# to the socket.
|
||||
|
||||
# connection -> welcome
|
||||
# <- {type: "welcome", welcome: {}} # .welcome keys are all optional:
|
||||
|
@ -31,19 +52,21 @@ from autobahn.twisted import websocket
|
|||
# error: all clients display mesage, then terminate with error
|
||||
# -> {type: "bind", appid:, side:}
|
||||
#
|
||||
# -> {type: "list"} -> channelids
|
||||
# <- {type: "channelids", channelids: [int..]}
|
||||
# -> {type: "allocate"} -> allocated
|
||||
# <- {type: "allocated", channelid: int}
|
||||
# -> {type: "claim", channelid: int}
|
||||
# -> {type: "list"} -> nameplates
|
||||
# <- {type: "nameplates", nameplates: [str..]}
|
||||
# -> {type: "allocate"} -> nameplate, mailbox
|
||||
# <- {type: "nameplate", nameplate: str}
|
||||
# -> {type: "claim", nameplate: str} -> mailbox
|
||||
# <- {type: "mailbox", mailbox: str}
|
||||
# -> {type: "release"}
|
||||
#
|
||||
# -> {type: "watch", channelid: int} -> message
|
||||
# sends old messages and more in future
|
||||
# <- {type: "message", channelid: int, message: {phase:, body:}} # body is hex
|
||||
# -> {type: "add", channelid: int, phase: str, body: hex} # will send echo
|
||||
# -> {type: "open", mailbox: str} -> message
|
||||
# sends old messages now, and subscribes to deliver future messages
|
||||
# <- {type: "message", message: {phase:, body:}} # body is hex
|
||||
# -> {type: "add", phase: str, body: hex} # will send echo in a "message"
|
||||
#
|
||||
# -> {type: "release", channelid: int, mood: str} -> deallocated
|
||||
# <- {type: "released", channelid: int, status: waiting|deleted}
|
||||
# -> {type: "close", mood: str} -> closed
|
||||
# <- {type: "closed", status: waiting|deleted}
|
||||
#
|
||||
# <- {type: "error", error: str, orig: {}} # in response to malformed msgs
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user