2019-07-16 21:06:43 +00:00
|
|
|
.Dd July 16, 2019
|
|
|
|
.Dt ETHERMESS 7
|
|
|
|
.Os
|
|
|
|
.Sh NAME
|
|
|
|
.Nm EtherMess
|
|
|
|
.Nd messaging protocol for bare Ethernet
|
|
|
|
.Sh DESCRIPTION
|
|
|
|
.Nm
|
|
|
|
is a protocol for direct messaging over raw Ethernet frames.
|
2019-07-17 13:15:10 +00:00
|
|
|
.Ss Byte order
|
|
|
|
.Nm
|
|
|
|
uses network byte order when representing values larger than 8 bits.
|
|
|
|
That is, 0xAABB will be encoded as 0xAA 0xBB.
|
|
|
|
.Ss Packet format
|
2019-07-16 21:06:43 +00:00
|
|
|
The structure of an Ethernet frame containing an EtherMess packet is as
|
|
|
|
follows:
|
|
|
|
.TS
|
|
|
|
allbox;
|
|
|
|
lb lb lb lb
|
|
|
|
l l l l
|
|
|
|
^ l l l
|
|
|
|
^ l l l
|
|
|
|
l l l l
|
|
|
|
^ l l l
|
|
|
|
l l l l
|
|
|
|
l l l l.
|
|
|
|
Part Field Length (B) Contents
|
|
|
|
Ethernet header Destination 6 Recipient's MAC
|
|
|
|
Source 6 Sender's MAC
|
|
|
|
EtherType 2 0xDA7A
|
|
|
|
EtherMess header Version 1 0x00
|
|
|
|
Packet type 1 (defined below)
|
2019-07-17 13:15:10 +00:00
|
|
|
Payload 0 - 1498 (depends on packet type)
|
|
|
|
Padding 0 - 1498 0x00
|
2019-07-16 21:06:43 +00:00
|
|
|
.TE
|
|
|
|
.Pp
|
|
|
|
Padding may always be present, and it can be any length that fits into the
|
|
|
|
Ethernet frame after the headers and the payload.
|
|
|
|
Only requirement for padding is that it has to be all zero bytes.
|
2019-07-17 13:15:10 +00:00
|
|
|
If this requirement is violated, the packet must be ignored even if it
|
|
|
|
otherwise parses fine.
|
2019-07-16 21:06:43 +00:00
|
|
|
.Pp
|
|
|
|
NOTE: Frame check sequence is not present in the table above, as at least
|
2019-07-17 13:15:10 +00:00
|
|
|
on Linux if raw Ethernet frames are read and written using
|
2019-07-16 21:06:43 +00:00
|
|
|
.Xr packet 7
|
|
|
|
it gets stripped off and added by the lower level drivers.
|
2019-07-17 13:15:10 +00:00
|
|
|
.Ss Packet types
|
2019-07-16 21:06:43 +00:00
|
|
|
.Bl -tag -width Ds
|
|
|
|
.It Speak version (0x00)
|
|
|
|
.TS
|
|
|
|
allbox;
|
|
|
|
lb lb lb
|
|
|
|
l l l.
|
|
|
|
Field Length (B) Contents
|
|
|
|
Version 1 EtherMess protocol version
|
|
|
|
.TE
|
|
|
|
.Pp
|
|
|
|
Tells the recipient to speak the given version of the protocol.
|
2019-07-17 13:15:10 +00:00
|
|
|
Should be generated whenever an EtherMess packet with a version one doesn't
|
|
|
|
speak is received.
|
2019-07-16 21:06:43 +00:00
|
|
|
.It Status request (0x01)
|
2019-07-18 11:30:42 +00:00
|
|
|
Requests the recipient to announce its status and nick.
|
2019-07-16 21:06:43 +00:00
|
|
|
Upon receiving this packet, a status packet should be sent to the sender.
|
|
|
|
.It Status (0x02)
|
|
|
|
.TS
|
|
|
|
allbox;
|
|
|
|
lb lb lb
|
|
|
|
l l l.
|
|
|
|
Field Length (B) Contents
|
|
|
|
Status 1 (defined below)
|
|
|
|
Nick length 1 Length of the nick field in bytes
|
|
|
|
Nick 0 - 255 Nick encoded as utf-8
|
|
|
|
.TE
|
|
|
|
.Pp
|
|
|
|
Informs the recipient about the current status and the nick of the sender.
|
|
|
|
.Pp
|
|
|
|
Allowed values for the status field are:
|
|
|
|
.Bl -tag -width Ds
|
|
|
|
.It 0x00
|
|
|
|
Available
|
|
|
|
.It 0x01
|
|
|
|
Unavailable
|
|
|
|
.It 0x02
|
|
|
|
Offline
|
|
|
|
.El
|
|
|
|
.Pp
|
|
|
|
The nick field must contain valid utf-8.
|
2019-07-17 13:15:10 +00:00
|
|
|
That is, it must not contain overlong encoding, codepoints over U+10FFFF,
|
2019-07-16 21:06:43 +00:00
|
|
|
or surrogate pairs.
|
|
|
|
.Pp
|
2019-07-17 13:15:10 +00:00
|
|
|
Additionally, the nick must not contain any non-characters (U+xxFFFE,
|
2019-07-16 21:06:43 +00:00
|
|
|
U+xxFFFF, U+FDD0 - U+FDED), C0 control characters (U+00 - U+1F), C1 control
|
|
|
|
characters (U+80 - U+9F), or the codepoints U+2028 LINE SEPARATOR and
|
|
|
|
U+2029 PARAGRAPH SEPARATOR.
|
|
|
|
.Pp
|
2019-07-17 13:15:10 +00:00
|
|
|
The packet must be ignored if
|
|
|
|
.Bl -bullet
|
|
|
|
.It
|
|
|
|
Status is not one of the recognized values.
|
|
|
|
.It
|
2019-07-18 11:30:42 +00:00
|
|
|
Nick length is more than the remaining size of the packet.
|
2019-07-17 13:15:10 +00:00
|
|
|
.It
|
|
|
|
Nick is not valid utf-8.
|
|
|
|
.It
|
|
|
|
Nick contains disallowed codepoints.
|
|
|
|
.El
|
2019-07-16 21:06:43 +00:00
|
|
|
.It Msgid request (0x03)
|
2019-07-18 11:30:42 +00:00
|
|
|
Requests the recipient to announce the message ID of the next message it is
|
2019-07-17 13:15:10 +00:00
|
|
|
expecting from the sender.
|
|
|
|
Upon receiving this packet, a msgid packet should be sent to the sender.
|
2019-07-16 21:06:43 +00:00
|
|
|
.It Msgid (0x04)
|
2019-07-17 13:15:10 +00:00
|
|
|
.TS
|
|
|
|
allbox;
|
|
|
|
lb lb lb
|
|
|
|
l l l.
|
|
|
|
Field Length (B) Contents
|
2019-07-18 11:30:42 +00:00
|
|
|
Msgid 2 Expected ID of the next message
|
2019-07-17 13:15:10 +00:00
|
|
|
.TE
|
|
|
|
.Pp
|
2019-07-18 11:30:42 +00:00
|
|
|
Announces the next message ID that the sender expects from the recipient.
|
|
|
|
Generally speaking, this should be one greater than the message ID last
|
|
|
|
received from that recipient.
|
|
|
|
However, an implementation may randomize the message ID upon each request.
|
2019-07-17 13:15:10 +00:00
|
|
|
.Pp
|
|
|
|
For special cases, see the Msgid section.
|
2019-07-16 21:06:43 +00:00
|
|
|
.It Message (0x05)
|
2019-07-17 13:15:10 +00:00
|
|
|
.TS
|
|
|
|
allbox;
|
|
|
|
lb lb lb
|
|
|
|
l l l.
|
|
|
|
Field Length (B) Contents
|
|
|
|
Msgid 2 ID of the message
|
|
|
|
Length 2 Length of the message field in bytes
|
|
|
|
Message 0 - 1494 Message encoded as utf-8
|
|
|
|
.TE
|
|
|
|
.Pp
|
|
|
|
Is used to transmit messages.
|
|
|
|
Upon receiving this packet, an ACK packet should be sent to the sender.
|
|
|
|
.Pp
|
|
|
|
If the message ID is considered to be in the future (for details see the
|
|
|
|
Msgid section), the message should be displayed to the user and the next
|
|
|
|
message ID to expect should be made msgid + 1.
|
|
|
|
If instead the ID is considered to be in the past, the message should be
|
2019-07-17 13:20:38 +00:00
|
|
|
skipped as a repeat.
|
2019-07-18 11:30:42 +00:00
|
|
|
Note however that even in this case an ACK should be generated.
|
2019-07-17 13:15:10 +00:00
|
|
|
.Pp
|
2019-07-18 11:30:42 +00:00
|
|
|
The message field has similar requirements to the nick field regarding its
|
2019-07-17 13:15:10 +00:00
|
|
|
encoding and contents, except that the message field may additionally
|
|
|
|
contain the codepoints U+0A LINE FEED and U+09 CHARACTER TABULATION.
|
|
|
|
.Pp
|
|
|
|
The packet must be fully ignored (no ACK) if
|
|
|
|
.Bl -bullet
|
|
|
|
.It
|
|
|
|
Message length is more than 1494 or the remaining size of the packet.
|
|
|
|
.It
|
|
|
|
Message is not valid utf-8.
|
|
|
|
.It
|
|
|
|
Message contains disallowed codepoints.
|
|
|
|
.El
|
2019-07-16 21:06:43 +00:00
|
|
|
.It ACK (0x06)
|
2019-07-17 13:15:10 +00:00
|
|
|
.TS
|
|
|
|
allbox;
|
|
|
|
lb lb lb
|
|
|
|
l l l.
|
|
|
|
Field Length (B) Contents
|
|
|
|
Msgid 2 ID of the received message
|
|
|
|
.TE
|
|
|
|
.Pp
|
|
|
|
Confirms that the sender has received a message with the given message ID
|
|
|
|
from the recipient.
|
|
|
|
.Pp
|
|
|
|
If the message ID matches a message sent by the recipient, the recipient
|
|
|
|
should consider that message to be received and not transmit it again in
|
|
|
|
the future.
|
|
|
|
On the other hand if the recipient doesn't recognize that message ID, the
|
|
|
|
packet should be ignored.
|
2019-07-16 21:06:43 +00:00
|
|
|
.El
|
2019-07-17 13:15:10 +00:00
|
|
|
.Ss Msgid
|
|
|
|
Message IDs in
|
|
|
|
.Nm
|
|
|
|
are unsigned 16 bit integers.
|
|
|
|
.Pp
|
|
|
|
They are unique to each sender and recipient pair.
|
|
|
|
This means that the message IDs of messages A sends to B are completely
|
|
|
|
unrelated to the IDs of messages A sends to C or messages B sends to A.
|
|
|
|
.Pp
|
2019-07-18 11:30:42 +00:00
|
|
|
Because they are 16 bit (which is comparably small) and the initial value
|
|
|
|
is randomized, there is a possibility of a rollover.
|
|
|
|
For that reason, a simple comparison of
|
|
|
|
.Li received_msgid >= next_expected_msgid
|
|
|
|
doesn't work.
|
2019-07-17 13:15:10 +00:00
|
|
|
The correct way to test if a message ID is considered to be in the future
|
|
|
|
is to do
|
|
|
|
.Li (received_msgid - next_expected_msgid) modulus 2^16
|
|
|
|
and see if the result is in the range of [0, 0x8000].
|
|
|
|
.Pp
|
|
|
|
There are special cases for if the recipient doesn't know what the ID of
|
|
|
|
the next message they receive should be.
|
|
|
|
If they have received a message, it should be accepted and the next ID to
|
|
|
|
expect should be set to the ID of the message plus one, just like if the
|
2019-07-18 11:30:42 +00:00
|
|
|
message ID was considered to be in the future (though it may be marked as
|
|
|
|
a possible repeat).
|
2019-07-17 13:15:10 +00:00
|
|
|
If they have received an msgid request packet, they should set the next ID
|
|
|
|
to expect to a random value and send that value in the msgid packet.
|
|
|
|
.Pp
|
2019-07-18 11:30:42 +00:00
|
|
|
Implementations should not store the next message IDs persistently.
|
2019-07-17 13:15:10 +00:00
|
|
|
This is because if those values are out of date, messages sent by the
|
|
|
|
implementation may be silently dropped.
|
2019-07-18 11:30:42 +00:00
|
|
|
Storing the next message ID to expect is safer, though a value of more than
|
|
|
|
0x8000 out of date will lead to valid messages being dropped by the
|
|
|
|
implementation itself.
|
2019-07-17 13:15:10 +00:00
|
|
|
.Ss Sending a message
|
|
|
|
To send a message, the sender should first figure out the correct message
|
|
|
|
ID to use.
|
|
|
|
If they have cached the next message ID to use for the recipient, they
|
|
|
|
should use it.
|
|
|
|
Otherwise they should send an msgid request packet to the recipient.
|
|
|
|
.Pp
|
|
|
|
If the recipient doesn't answer the msgid request, the sender should retry
|
|
|
|
the transmission a few times.
|
|
|
|
The reference implementation,
|
|
|
|
.Xr ethermess 1 ,
|
2019-07-18 11:30:42 +00:00
|
|
|
will attempt to transmit at most 5 times, and uses a randomized timeout of
|
2019-07-17 13:15:10 +00:00
|
|
|
around 1 to 1.5 seconds.
|
|
|
|
Implementations should randomize the retry timeout to reduce chances of
|
|
|
|
packet collisions with other
|
|
|
|
.Nm
|
|
|
|
implementations.
|
|
|
|
If there is still no msgid packet, the message should be considered to have
|
|
|
|
failed to send.
|
|
|
|
.Pp
|
|
|
|
Once the message ID to use is known, the sender should send the message to
|
2019-07-18 11:30:42 +00:00
|
|
|
the recipient and wait for an ACK with the same message ID (note that the
|
|
|
|
sender might receive ACKs for different message).
|
2019-07-17 13:15:10 +00:00
|
|
|
The transmission should have a similar timeout and retry mechanism as with
|
|
|
|
the msgid request.
|
|
|
|
If no matching ACK is received, the message should be considered to have
|
|
|
|
failed to send, but the implementation may keep it around in case an ACK
|
|
|
|
with its message ID is received later.
|
|
|
|
.Pp
|
2019-07-18 11:30:42 +00:00
|
|
|
After sending the message, regardless of whether an ACK was received for
|
|
|
|
it or not, the sender should update its cached value of the next message
|
|
|
|
ID to use when sending to the target to the message ID of the message that
|
|
|
|
was sent plus one.
|
2019-07-17 13:15:10 +00:00
|
|
|
.Ss Changing one's own nick or status
|
|
|
|
When a user changes their nick or status, they should broadcast (send to
|
|
|
|
the MAC FF:FF:FF:FF:FF:FF) the status and nick with the status packet.
|
|
|
|
.Ss Offline timeout
|
|
|
|
An implementation should keep track of when it has last received a valid
|
|
|
|
packet from its peers.
|
|
|
|
If it has been more than 5 minutes, the implementation should consider the
|
|
|
|
peer to have quit.
|
|
|
|
The quit notification displayed to the user should mark that this was
|
|
|
|
because of the timeout and not due to a status packet with an offline
|
|
|
|
status.
|
|
|
|
.Pp
|
|
|
|
To avoid being considered to have quit, an implementation should
|
|
|
|
periodically broadcast a status packet containing its current status and
|
|
|
|
nick.
|
|
|
|
The period used by
|
|
|
|
.Xr ethermess 1
|
|
|
|
is in the range of 60 to 64 seconds.
|
|
|
|
The period should be randomized in order to avoid packet collisions with
|
|
|
|
other
|
|
|
|
.Nm
|
|
|
|
implementations.
|
|
|
|
.Ss Finding peers
|
|
|
|
To find peers, an implementation should broadcast a status request package.
|
|
|
|
Alternatively it may wait until it receives a keep-alive status broadcast
|
|
|
|
from all of its peers.
|
|
|
|
.Ss Getting the status of a peer
|
2019-07-18 11:30:42 +00:00
|
|
|
An implementation should keep a cache of statuses and nicks and update it
|
2019-07-17 13:15:10 +00:00
|
|
|
whenever a status packet is received.
|
|
|
|
.Pp
|
2019-07-18 11:30:42 +00:00
|
|
|
If the cache doesn't contain a given peer, the implementation may request
|
|
|
|
the status using the status request packet targeted at that peer.
|
|
|
|
The timeout and retry mechanism should be designed to avoid spamminess and
|
2019-07-17 13:15:10 +00:00
|
|
|
minimize the possibility of packet collisions.
|
|
|
|
.Pp
|
|
|
|
An implementation may also implement a user-initiated status check by first
|
2019-07-18 11:30:42 +00:00
|
|
|
looking at the cache and then, regardless of whether it was in the cache or
|
|
|
|
not, sending a status request packet.
|
2019-07-17 13:15:10 +00:00
|
|
|
This way the user can both receive an answer fast and in case the cached
|
|
|
|
value was outdated get the correct result once it arrives.
|
2019-07-17 18:48:14 +00:00
|
|
|
.Ss Starting up
|
|
|
|
An implementation should broadcast its status and nick on startup.
|
2019-07-17 13:15:10 +00:00
|
|
|
.Ss Shutting down
|
|
|
|
When an implementation exits, it should broadcast a status packet with the
|
|
|
|
status set to 0x02 (offline) and nick set to the current nick.
|
2019-07-16 21:06:43 +00:00
|
|
|
.Sh SEE ALSO
|
|
|
|
.Xr ethermess 1
|