1syntax = "proto3";
2
3package protocol;
4
5import "ext.proto";
6import "repos/protobuf/gogoproto/gogo.proto";
7
8// --- Pre-auth ---
9
10message Hello {
11    string device_name    = 1;
12    string client_name    = 2;
13    string client_version = 3;
14}
15
16// --- Header ---
17
18message Header {
19    MessageType        type        = 1;
20    MessageCompression compression = 2;
21}
22
23enum MessageType {
24    MESSAGE_TYPE_CLUSTER_CONFIG    = 0;
25    MESSAGE_TYPE_INDEX             = 1;
26    MESSAGE_TYPE_INDEX_UPDATE      = 2;
27    MESSAGE_TYPE_REQUEST           = 3;
28    MESSAGE_TYPE_RESPONSE          = 4;
29    MESSAGE_TYPE_DOWNLOAD_PROGRESS = 5;
30    MESSAGE_TYPE_PING              = 6;
31    MESSAGE_TYPE_CLOSE             = 7;
32}
33
34enum MessageCompression {
35    MESSAGE_COMPRESSION_NONE = 0;
36    MESSAGE_COMPRESSION_LZ4  = 1 [(ext.enumgoname) = "MessageCompressionLZ4"];
37}
38
39// --- Actual messages ---
40
41// Cluster Config
42
43message ClusterConfig {
44    repeated Folder folders = 1;
45}
46
47message Folder {
48    string id                   = 1 [(ext.goname) = "ID"];
49    string label                = 2;
50    bool   read_only            = 3;
51    bool   ignore_permissions   = 4;
52    bool   ignore_delete        = 5;
53    bool   disable_temp_indexes = 6;
54    bool   paused               = 7;
55
56    repeated Device devices = 16;
57}
58
59message Device {
60    bytes           id                         = 1 [(ext.goname) = "ID", (ext.device_id) = true];
61    string          name                       = 2;
62    repeated string addresses                  = 3;
63    Compression     compression                = 4;
64    string          cert_name                  = 5;
65    int64           max_sequence               = 6;
66    bool            introducer                 = 7;
67    uint64          index_id                   = 8 [(ext.goname) = "IndexID", (ext.gotype) = "IndexID"];
68    bool            skip_introduction_removals = 9;
69    bytes           encryption_password_token  = 10;
70}
71
72enum Compression {
73    COMPRESSION_METADATA = 0;
74    COMPRESSION_NEVER    = 1;
75    COMPRESSION_ALWAYS   = 2;
76}
77
78// Index and Index Update
79
80message Index {
81    string            folder = 1;
82    repeated FileInfo files  = 2;
83}
84
85message IndexUpdate {
86    string            folder = 1;
87    repeated FileInfo files  = 2;
88}
89
90message FileInfo {
91    option (gogoproto.goproto_stringer) = false;
92
93    // The field ordering here optimizes for struct size / alignment --
94    // large types come before smaller ones.
95
96    string             name           = 1;
97    int64              size           = 3;
98    int64              modified_s     = 5;
99    uint64             modified_by    = 12 [(ext.gotype) = "ShortID"];
100    Vector             version        = 9;
101    int64              sequence       = 10;
102    repeated BlockInfo blocks         = 16;
103    string             symlink_target = 17;
104    bytes              blocks_hash    = 18;
105    bytes              encrypted      = 19;
106    FileInfoType       type           = 2;
107    uint32             permissions    = 4;
108    int32              modified_ns    = 11;
109    int32              block_size     = 13 [(ext.goname) = "RawBlockSize"];
110
111    // The local_flags fields stores flags that are relevant to the local
112    // host only. It is not part of the protocol, doesn't get sent or
113    // received (we make sure to zero it), nonetheless we need it on our
114    // struct and to be able to serialize it to/from the database.
115    uint32 local_flags = 1000;
116    // The version_hash is an implementation detail and not part of the wire
117    // format.
118    bytes version_hash = 1001;
119
120    bool deleted        = 6;
121    bool invalid        = 7 [(ext.goname) = "RawInvalid"];
122    bool no_permissions = 8;
123}
124
125enum FileInfoType {
126    FILE_INFO_TYPE_FILE              = 0;
127    FILE_INFO_TYPE_DIRECTORY         = 1;
128    FILE_INFO_TYPE_SYMLINK_FILE      = 2 [deprecated = true];
129    FILE_INFO_TYPE_SYMLINK_DIRECTORY = 3 [deprecated = true];
130    FILE_INFO_TYPE_SYMLINK           = 4;
131}
132
133message BlockInfo {
134    option (gogoproto.goproto_stringer) = false;
135    bytes  hash      = 3;
136    int64  offset    = 1;
137    int32  size      = 2;
138    uint32 weak_hash = 4;
139}
140
141message Vector {
142    repeated Counter counters = 1;
143}
144
145message Counter {
146    uint64 id    = 1 [(ext.goname) = "ID", (ext.gotype) = "ShortID"];
147    uint64 value = 2;
148}
149
150// Request
151
152message Request {
153    int32  id             = 1 [(ext.goname) = "ID"];
154    string folder         = 2;
155    string name           = 3;
156    int64  offset         = 4;
157    int32  size           = 5;
158    bytes  hash           = 6;
159    bool   from_temporary = 7;
160    uint32 weak_hash      = 8;
161    int32  block_no       = 9;
162}
163
164// Response
165
166message Response {
167    int32     id   = 1 [(ext.goname) = "ID"];
168    bytes     data = 2;
169    ErrorCode code = 3;
170}
171
172enum ErrorCode {
173    ERROR_CODE_NO_ERROR     = 0;
174    ERROR_CODE_GENERIC      = 1;
175    ERROR_CODE_NO_SUCH_FILE = 2;
176    ERROR_CODE_INVALID_FILE = 3;
177}
178
179// DownloadProgress
180
181message DownloadProgress {
182    string                              folder  = 1;
183    repeated FileDownloadProgressUpdate updates = 2;
184}
185
186message FileDownloadProgressUpdate {
187    FileDownloadProgressUpdateType update_type   = 1;
188    string                         name          = 2;
189    Vector                         version       = 3;
190    repeated int32                 block_indexes = 4 [packed=false];
191    int32                          block_size    = 5;
192}
193
194enum FileDownloadProgressUpdateType {
195    FILE_DOWNLOAD_PROGRESS_UPDATE_TYPE_APPEND = 0;
196    FILE_DOWNLOAD_PROGRESS_UPDATE_TYPE_FORGET = 1;
197}
198
199// Ping
200
201message Ping {
202}
203
204// Close
205
206message Close {
207    string reason = 1;
208}
209
210