summaryrefslogtreecommitdiff
path: root/proto.h
blob: d07aec1679b7853163e5f7ee5274f79e152b768d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#pragma once

/* SPDX-License-Identifier: Unlicense */

#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>

/*

FRAME FORMAT
============

Every frame contents:

    0               1               2               3
    0 1 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |      Protocol version (0)     |          Frame type           |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                         Connection ID                         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                                                               :
   :                             Data                              :
   :                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Connection ID is zero for FT_HANDSHAKE, otherwise it must always be set to the
one received with FT_HANDSHAKE_RESP frame.

Data for FT_HANDSHAKE:

    0               1               2               3
    0 1 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                     Requested tick period                     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Data for FT_HANDSHAKE_RESP:

    0               1               2               3
    0 1 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                      Actual tick period                       |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

If FT_HANDSHAKE_RESP is received by the client then connection is considered
to be established.


Data for FT_SYN and FT_SYNACK:

    0               1               2               3
    0 1 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                  Current tick counter value                   |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                          RESERVED                           |L|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                 Previous ping roundtrip time                  |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                        Resend counter                         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Where:
    `Resend counter` - Number of times this frame has been sent without getting
    a response.
    `L` - bit indicating that previous ping response is not yet received, which
    means that it is essentially lost.
    `D` - bit indicating that connection should be terminated by either client
    or server initiative.

Data for FT_ACK:

    0               1               2               3
    0 1 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                  Current tick counter value                   |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+


EXCHANGE SEQUENCE
=================

Legend:
">" - client > server
"<" - client < server

> FT_HANDSHAKE(requested_parameters)
< FT_HANDSHAKE_RESP(actually_applied parameters)
(connection established)
< FT_SYN(tick=0)
> FT_SYNACK(tick=0)
< FT_ACK(tick=0)
(1 tick goes by)
< FT_SYN(tick=1)
> FT_SYNACK(tick=1)
< FT_ACK(tick=1)
(1 tick goes by)
...

 */

enum frame_type {
    FT_NONE = 0, ///< Not an actual type
    FT_HANDSHAKE, ///< From client
    FT_HANDSHAKE_RESP, ///< From server
    FT_SYN, ///< From server
    FT_SYNACK, ///< From client
    FT_ACK, ///< From server
    /// From server, in response to invalid connection_id or invalid tick period
    /// requested. Or from client as an immediate disconnect request without
    /// awaiting any response.
    FT_RST,
    FT_MAX, ///< Not an actual type
};

struct frame {
    uint32_t addr;
    uint32_t connection_id;
    uint16_t port;
    enum frame_type type;
    union {
        struct frame_data_handshake {
            uint32_t tick_period;
        } handshake; // FT_HANDSHAKE, FT_HANDSHAKE_RESP
        struct frame_data_syn {
            uint32_t tick;
            uint32_t roundtrip_prev;
            uint32_t repeat;
            bool prev_is_lost;
        } syn; // FT_SYN, FT_SYNACK
        struct frame_data_ack {
            uint32_t tick;
        } ack; // FT_ACK
    };
};

struct frame ParseFrame(void const *buffer, size_t buffer_size);
size_t SerializeFrame(void *buffer, size_t buffer_size, struct frame const *);