|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+extern crate rmp_serde as rmps;
|
|
|
2
|
+extern crate serde;
|
|
|
3
|
+
|
|
|
4
|
+use rmps::Serializer;
|
|
|
5
|
+use serde::Serialize;
|
|
|
6
|
+use twfss::protocol;
|
|
|
7
|
+
|
|
|
8
|
+fn print_serialized_deserialized(packet: protocol::Packet) {
|
|
|
9
|
+ let mut buf = Vec::new();
|
|
|
10
|
+ packet
|
|
|
11
|
+ .serialize(
|
|
|
12
|
+ &mut Serializer::new(&mut buf)
|
|
|
13
|
+ .with_struct_map()
|
|
|
14
|
+ .with_string_variants(),
|
|
|
15
|
+ )
|
|
|
16
|
+ .unwrap();
|
|
|
17
|
+ println!("Serialized: {:?}", buf);
|
|
|
18
|
+ let packet: protocol::Packet = rmps::decode::from_slice(&buf).unwrap();
|
|
|
19
|
+ println!("Deserialized: {:?}\n", packet);
|
|
|
20
|
+}
|
|
|
21
|
+
|
|
|
22
|
+fn main() {
|
|
|
23
|
+ // Open questions:
|
|
|
24
|
+ // - Do we actually need the "response" field? Actually, separating the ID range so that
|
|
|
25
|
+ // server->client events get IDs from the range between 2^31 and above would be enough.
|
|
|
26
|
+
|
|
|
27
|
+ // The low-level protocol needs to implement two basic pieces of functionality: It needs to be
|
|
|
28
|
+ // able to implement remote procedure calls from the client to the server, and it needs to
|
|
|
29
|
+ // provide a method for the server to send asynchronous events. A protocol for both cases is
|
|
|
30
|
+ // outlined below, where each packet is sent as one WebSocket message.
|
|
|
31
|
+ //
|
|
|
32
|
+ // Remote procedure call:
|
|
|
33
|
+ // - The client allocates an ID from the range between 0..2^31-1 that is not currently in use
|
|
|
34
|
+ // for another RPC in progress.
|
|
|
35
|
+ // - The client prepares a packet with this ID, "response = false", and the appropriate
|
|
|
36
|
+ // payload and sends the packet to the server.
|
|
|
37
|
+ // - The server receives the packet, processes the request and sends a packet back with the
|
|
|
38
|
+ // identical ID and "response = true".
|
|
|
39
|
+ // - In case of an error, the payload has the type "Error" which in turn contains the error
|
|
|
40
|
+ // type.
|
|
|
41
|
+ // - Unpon reception of the response, the client is free to reuse the ID for further RPCs.
|
|
|
42
|
+ // Note that this protocol does not allow the client to cancel an RPC that is currently in
|
|
|
43
|
+ // progress - implementing such functionality is difficult, error-prone, and most likely not
|
|
|
44
|
+ // worth the effort.
|
|
|
45
|
+ //
|
|
|
46
|
+ // Server-side event:
|
|
|
47
|
+ // - The server creates a packet with the ID 2^31 and the event content and sends it to the
|
|
|
48
|
+ // client.
|
|
|
49
|
+ // Note that the client does not have any method to acknowledge event reception. As events are
|
|
|
50
|
+ // asynchronous compared to RPCs on the same connection, the event type needs to be designed in
|
|
|
51
|
+ // a way that no such temporal information is necessary to process the events.
|
|
|
52
|
+ // TODO: Example to demonstrate the problem.
|
|
|
53
|
+
|
|
|
54
|
+ println!("Without request content:");
|
|
|
55
|
+ let packet = protocol::Packet {
|
|
|
56
|
+ id: 42,
|
|
|
57
|
+ response: false,
|
|
|
58
|
+ payload: protocol::PacketPayload::ServerInfo,
|
|
|
59
|
+ };
|
|
|
60
|
+ print_serialized_deserialized(packet);
|
|
|
61
|
+ // Should be: [131, 162, 105, 100, 42, 168, 114, 101, 115, 112, 111, 110, 115, 101, 194, 167, 112, 97, 121, 108, 111, 97, 100, 129, 170, 83, 101, 114, 118, 101, 114, 73, 110, 102, 111, 192]
|
|
|
62
|
+
|
|
|
63
|
+ println!("\nWith request content:");
|
|
|
64
|
+ let packet = protocol::Packet {
|
|
|
65
|
+ id: 42,
|
|
|
66
|
+ response: true,
|
|
|
67
|
+ payload: protocol::PacketPayload::ServerInfoResponse(protocol::ServerInfoResponse {
|
|
|
68
|
+ version: "0.1".to_owned(),
|
|
|
69
|
+ }),
|
|
|
70
|
+ };
|
|
|
71
|
+ print_serialized_deserialized(packet);
|
|
|
72
|
+ // Should be: [131, 162, 105, 100, 42, 168, 114, 101, 115, 112, 111, 110, 115, 101, 194, 167, 112, 97, 121, 108, 111, 97, 100, 129, 178, 83, 101, 114, 118, 101, 114, 73, 110, 102, 111, 82, 101, 115, 112, 111, 110, 115, 101, 129, 167, 118, 101, 114, 115, 105, 111, 110, 163, 48, 46, 49]
|
|
|
73
|
+
|
|
|
74
|
+ println!("Error:");
|
|
|
75
|
+ let packet = protocol::Packet {
|
|
|
76
|
+ id: 42,
|
|
|
77
|
+ response: true,
|
|
|
78
|
+ payload: protocol::PacketPayload::Error(protocol::Error::InvalidParameter),
|
|
|
79
|
+ };
|
|
|
80
|
+ print_serialized_deserialized(packet);
|
|
|
81
|
+ // Should be: [131, 162, 105, 100, 42, 168, 114, 101, 115, 112, 111, 110, 115, 101, 195, 167, 112, 97, 121, 108, 111, 97, 100, 129, 165, 69, 114, 114, 111, 114, 129, 176, 73, 110, 118, 97, 108, 105, 100, 80, 97, 114, 97, 109, 101, 116, 101, 114, 192]
|
|
|
82
|
+}
|