-
Notifications
You must be signed in to change notification settings - Fork 6
/
bithorde.proto
155 lines (138 loc) · 6.07 KB
/
bithorde.proto
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package bithorde;
enum HashType
{
SHA1 = 1;
SHA256 = 2;
TREE_TIGER = 3;
ED2K = 4;
}
enum CipherType {
CLEARTEXT = 0; // Cleartext
XOR = 1; // Very fast, pure-obfuscation. Keeps nosy people out, but not secure at all.
RC4 = 2; // ArcFour. Quite fast, but has some security-weaknesses. See http://en.wikipedia.org/wiki/RC4 for details.
AES_CTR = 3; // Highly secure, but comparatively slow/cpu-intensive. Size of cipher is determined by the key size.
}
enum Status {
NONE = 0;
SUCCESS = 1;
NOTFOUND = 2;
INVALID_HANDLE = 3;
WOULD_LOOP = 4;
DISCONNECTED = 5;
TIMEOUT = 6;
NORESOURCES = 7;
ERROR = 8;
}
message Identifier {
required HashType type = 1; // Type of hashId
required bytes id = 2; // Raw Hash-Digest of type.
}
message HandShake { // Must be first message in stream
required string name = 1;
required uint32 protoversion = 2 [default = 2];
optional bytes challenge = 3; // Set if sender requires authentication of other part.
}
/****************************************************************************************
* A word on authentication and encryption.
*
* Authentication works by each peer sending a challenge to other part, asking for
* proof that the other part has a copy of a secret pre-shared key. The challenge is
* fulfilled by the other part answering the HMAC-Sha256 of the message-parts.
*
* The parts may also in the second stage decide to inform it's messages will be
* encrypted. The cipher may be chosen by the sender from the Cipher-enumeration. To
* enable encryption, the sender must also include a cipheriv/nonce in the
* HandShakeConfirmation.
*
* The HandShake is finally confirmed and authenticated by HMAC[SHA256]-hashing:
* shared_key, recieved_challenge ~ cipher(as single byte-int) ~ cipheriv
*
* NOTE: There is currently no negotiation over supported Ciphers. Sender decides what
* cipher to use. The behavior if recipient cannot support that cipher is
* undefined.
***************************************************************************************/
message HandShakeConfirmed { // Must be second message in stream (or skipped if no challenge recieved)
optional CipherType cipher = 1; // Cipher used by sender.
optional bytes cipheriv = 2; // Set if sender is encrypting the rest of the conversation
required bytes authentication = 3; // HMAC<SHA256>(shared_key, recieved challenge ~ cipher ~ sent cipheriv)
}
/****************************************************************************************
* Binds one set of Asset-identifiers to a specific handle
* Re-binding new assets to already used handles is allowed.
* Binding to a zero-length list of identifiers, is allowed, releasing the asset.
***************************************************************************************/
message BindRead { // Client->Server initate Read-Only binding
required uint32 handle = 1;
repeated Identifier ids = 2;
// The requesters are an additive set, indicating downstream nodes interested in this
// asset. A router should add its own node to the set before forwarding, and keep
// upstreams informed about changes to the list by new BindReads. A loop can be
// detected by looking for the routers own, or an id from the upstreams as indicated
// by AssetStatus.servers, in this list.
repeated uint64 requesters = 3;
// Timeout in ms.
required uint32 timeout = 4;
}
message BindWrite { // Client->Server initiate Read/Write Binding
required uint32 handle = 1;
optional uint64 size = 2; // Exactly one of size or
optional string linkpath = 3; // linkpath must be set.
}
message AssetStatus { // Server->Client, confirm bind-status (respond to Bind-Read/Write, notify changes in availability, and notify asset gone)
required uint32 handle = 1;
required Status status = 2;
repeated Identifier ids = 3; // Used to notify client of new ids
optional uint64 size = 4; // Notify Client of known size
// How well the server will be able to serve this asset. The number is not absolute in
// any sense, but only relative to other assets in the same pipe. Each node estimates
// availability of assets by this number, factored in the availability and priority of
// the Serving-Friend itself. (Bandwidth, uptime, ...)
optional uint32 availability = 5;
// The servers are an additive set, indicating upstream nodes involved in serving this
// asset. Their use aids in early loop prevention for a special case. Routers serving
// an asset should add it's own id to the list, and inform downstream requesters of any
// updates to the list.
repeated uint64 servers = 6;
}
message Read {
message Request {
required uint32 reqId = 1;
required uint32 handle = 2;
required uint64 offset = 3;
required uint32 size = 4;
required uint32 timeout = 5;
}
message Response {
required uint32 reqId = 1;
required Status status = 2;
optional uint64 offset = 3;
optional bytes content = 4;
}
}
message DataSegment {
required uint32 handle = 1; // Asset handle for the data
required uint64 offset = 2; // Content start offset
required bytes content = 3; // Content to write
}
/****************************************************************************************
* Empty dummy-message to send when testing connectivity.
* Peer should respond with any type of message within the specified timeout (in milli-
* seconds) or be considered disconnected.
***************************************************************************************/
message Ping {
optional uint32 timeout = 1;
}
// Dummy message to document the stream message-ids itself.
// Makes no sense as a message or object.
message Stream
{
required HandShake handshake = 1;
repeated BindRead bindRead = 2;
repeated AssetStatus assetStatus = 3;
repeated Read.Request readReq = 5;
repeated Read.Response readRes = 6;
repeated BindWrite bindWrite = 7;
repeated DataSegment dataSeg = 8;
repeated HandShakeConfirmed handShakeConfirm = 9;
repeated Ping ping = 10;
}