MUTE is a word which means at least two things:
Q-MUTE is an alternative protocol, thought to be useable in the very same MUTE Network through double-stack nodes. This document describes the protocol.
The MUTE Network, up to day, is quite small, for various reasons. Adding a new incompatible protocol would thus have split even more this network, so the double-protocol feature seem to be quite essential.
This aim is achieved quite simply: the first byte of the normal MUTE Protocol is a “P” (from the word “PublicKey” - remember that normal MUTE protocol is quite ASCII-based), or byte 0x50. This protocol, as a successor, starts with the next byte: “Q” (or byte 0x51). This is the reason why the protocol is named Q-MUTE.
This method has at least a pair of advantages: first of all, we need to
read only one byte to decide about compatibility. Second, most programming
environment provide an ungetc
-like function or method, which
allows you to put back at least one byte just read. This allows
double-stack nodes to read a byte, know what stack to use, then put back
the byte and pass the control to the right protocol stack.
Q-MUTE is a protocol stack which needs an underlying communication environment, over which it makes some assumptions. That is, a node running the Q-MUTE Protocol Stack requires that he's able to communicate with at least another node through a channel which is full-duplex and that support an 8-bit-clean full-duplex stream abstraction (that is, it's possible to send a stream of data composed of arbitrary 8-bit bytes, on both directions without limitations). Such abstraction is usually satisfied by the common socket abstraction (but can also be implemented over HTTP or other such methods - for example to avoid firewalls).
Here it is a summary of the structure of the Q-MUTE Protocol Stack:
Note that the parallelism with current MUTE protocol makes able a double stack node to integrate even more the two stacks, making them communicate at each layer.
This specifications are quite formal: everything is defined in terms of layering of protocols, data structures, and functions each layer exports to higher levels. Each layer declares some data structures and functions, whose semantic is defined through the description of the network operations which must be accomplished. Their format is kept quite similar to that of RFCs.
Q-MUTE makes assumptions on the Stream Layer, but do not define it. A single Q-MUTE stack can use more Stream Layers at the same time. Currently, no Stream Layer for Q-MUTE is defined, even if such a definition for TCP/IP is trivial. Every Stream Layer has an associated code. The following data types must be defined for every given Stream Layer:
HostAddress
. It represents all data needed to identify a
potential connection between this host and another one. E.g., for TCP/IP
this would be a couple host/port.HostConnection
. It represents a connection.It must also implement those operations, with given semantics:
connect(HostAddress ha): HostConnection
.
This function establish a connection between two nodes. If no host
correspond to the given HostAddress
, this
function fails. Can also fail for other, unspecified reasons.send(HostConnection hc, byte[] data): void
.
This function sends a chunk of data of any size to given connection. If
hc
has been disconnect()
ed, send
fails. Can also fail for other, unspecified reasons.receive(HostConnection hc, int length):
byte[length]
. This function receives a chunk of data of any size
from given connection. If hc
has been
disconnect()
ed, receive
fails. Can also fail
for other, unspecified reasons.disconnect(HostConnection hc): void
. This
function removes an established connection. If no connection has been
established with given host, this function fails. It can fail for no
other reasons.serialize(HostAddress ha): byte[]
. This function takes
an host address, and serializes it in a sequence of bytes, the first of
which must be the code of the corresponding Stream Layer.deserialize(byte[] ser): HostAddress
. Do the reverse of
serialize()
What about listen()-like method? The QNP layer needs it
The QLP protocol works with an associated Stream Layer, which provides
its connect
, send
, receive
and
disconnect
functions.
We use here three more data types:
RSAPublicKey
.
RSAPrivateKey
.
QlpConnection
.
The QLP protocol defines the following operations:
qlp_init(RSAPublicKey public, RSAPrivateKey
private): void
. This function simply sets this node's public and
private key.
qlp_connect(HostAddress ha, int AES_key_length):
QlpConnection
. This function initializes a secure connection
between the two endpoints. AES_key_length
specifies the
length of the random generated AES key.
qlp_send(QlpConnection conn, byte[] data): void
. Sends
some data over the secure connection.qlp_receive(QlpConnection conn, int length):
byte[length]
. Receives some data from the secure connection.qlp_disconnect(QlpConnection conn): void
. Closes the
connection.Here the various operations are explained more in depths, telling what each function is exactly supposed to do.
qlp_init(RSAPublicKey public, RSAPrivateKey
private): void
. Nothing more than what has already been stated.
qlp_connect(HostAddress ha, int AES_key_length):
QlpConnection
. Connection presumes an exchange of keys. once this
function is called, a fresh, random AES Key is generated (we will call
it “our AES key”), whereas public and private keys are the
same given to qlp_init()
. Connection is initiated by
initiating a connection (through connect()
) and sending
the following data (through send()
):
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Protocol Ver. | Public Key Buffer Length..................... | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ............. | Public Key................................... | +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ | ............................................................. | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | AES Key Buffer Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | AES Key...................................................... | +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ | ............................................................. | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+Follows an explanation of the various fields:
qlp_send(QlpConnection conn, byte[] data): void
.
Encrypts data
through other node's AES key, and send it
through send()
.qlp_receive(QlpConnection conn, int length):
byte[length]
. Receives length
bytes through
receive()
, and decrypts them using our AES key.qlp_disconnect(QlpConnection conn): void
. Simply calls
disconnect()
. Usually, we don't need to
gracefully inform the partner about our desire to close the connection,
since underlying protocol will do it for us - so, this means it's OK this
way?
The QNP Protocol works with an associated QLP layer, which
provides its qlp_init
, qlp_connect
,
qlp_send
, qlp_receive
and
qlp_disconnect
.
We use here one more data types:
QNPConnection
.The QNP protocol defines the following operations:
qnp_init(RSAPublicKey public, RSAPrivateKey private):
void
. This function initializes the QLP and QNP layers.qnp_connect(HostAddress ha): QNPConnection
. This
function connects to given host, and includes it in the routing
tables.qnp_known_hosts(): HostAddress[]
. This function given
the list of all addresses for known Q-MUTE nodes Perhaps is better to tell “MUTE and Q-MUTE
nodes”? learned thanks to the informations other nodes gave
us.qnp_route(QNPMessage m): void
. This function routes a
single packet of data (message) through the hosts we've already
qnp_connect()
ed to.qnp_get(): QNPMessage
. This function reads a packet of
data (Message) which has arrived, if present.Here the various operations are explained more in depths, telling what each function is exactly supposed to do.
qnp_init(RSAPublicKey public, RSAPrivateKey private):
void
. Calls qlp_init(public, private)
; initialize
an internal list of HostAddress
(which we will call
“Host Address List”) to an empty list; initialize an internal
counter (which we will call “Internal Timestamp”) to a random
value.
qnp_connect(HostAddress ha): QNPConnection
.
Connection to given host address happens through the following steps:
qlp_connect(ha)
.0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Unique Name Length | Unique Name.................. | +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ | ............................................................. | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Timestamp | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Host Count | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Host Addresses............................................... | +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ | ............................................................. | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Accepted | +-+-+-+-+-+-+-+-+Follows an explanation of the various fields:
serialize()
function.deserialize()
of elements of Host Addresses
field to the Host Address List.qnp_route(QNPMessage m): void
.qnp_get(): QNPMessage
.