protocol.txt revision f4ed516643ee8ed3a59ad1a8048f7ce5f47f93fb
1
2--- a replacement for aproto -------------------------------------------
3
4When it comes down to it, aproto's primary purpose is to forward
5various streams between the host computer and client device (in either
6direction).
7
8This replacement further simplifies the concept, reducing the protocol
9to an extremely straightforward model optimized to accomplish the
10forwarding of these streams and removing additional state or
11complexity.
12
13The host side becomes a simple comms bridge with no "UI", which will 
14be used by either commandline or interactive tools to communicate with 
15a device or emulator that is connected to the bridge.
16
17The protocol is designed to be straightforward and well-defined enough 
18that if it needs to be reimplemented in another environment (Java 
19perhaps), there should not problems ensuring perfect interoperability.
20
21The protocol discards the layering aproto has and should allow the 
22implementation to be much more robust.
23
24
25--- protocol overview and basics ---------------------------------------
26
27The transport layer deals in "messages", which consist of a 24 byte
28header followed (optionally) by a payload.  The header consists of 6
2932 bit words which are sent across the wire in little endian format.
30
31struct message {
32    unsigned command;       /* command identifier constant      */
33    unsigned arg0;          /* first argument                   */
34    unsigned arg1;          /* second argument                  */
35    unsigned data_length;   /* length of payload (0 is allowed) */
36    unsigned data_crc32;    /* crc32 of data payload            */
37    unsigned magic;         /* command ^ 0xffffffff             */
38};
39
40Receipt of an invalid message header, corrupt message payload, or an
41unrecognized command MUST result in the closing of the remote
42connection.  The protocol depends on shared state and any break in the
43message stream will result in state getting out of sync.
44
45The following sections describe the six defined message types in
46detail.  Their format is COMMAND(arg0, arg1, payload) where the payload
47is represented by a quoted string or an empty string if none should be
48sent.
49
50The identifiers "local-id" and "remote-id" are always relative to the
51*sender* of the message, so for a receiver, the meanings are effectively
52reversed.
53
54
55
56--- CONNECT(version, maxdata, "system-identity-string") ----------------
57
58The CONNECT message establishes the presence of a remote system.
59The version is used to ensure protocol compatibility and maxdata
60declares the maximum message body size that the remote system
61is willing to accept.
62
63Currently, version=0x01000000 and maxdata=4096
64
65Both sides send a CONNECT message when the connection between them is
66established.  Until a CONNECT message is received no other messages may
67be sent.  Any messages received before a CONNECT message MUST be ignored.
68
69If a CONNECT message is received with an unknown version or insufficiently
70large maxdata value, the connection with the other side must be closed.
71
72The system identity string should be "<systemtype>:<serialno>:<banner>"
73where systemtype is "bootloader", "device", or "host", serialno is some
74kind of unique ID (or empty), and banner is a human-readable version
75or identifier string.  The banner is used to transmit useful properties.
76
77
78--- AUTH(type, 0, "data") ----------------------------------------------
79
80The AUTH message informs the recipient that authentication is required to
81connect to the sender. If type is TOKEN(1), data is a random token that
82the recipient can sign with a private key. The recipient replies with an
83AUTH packet where type is SIGNATURE(2) and data is the signature. If the
84signature verification succeeds, the sender replies with a CONNECT packet.
85
86If the signature verification fails, the sender replies with a new AUTH
87packet and a new random token, so that the recipient can retry signing
88with a different private key.
89
90Once the recipient has tried all its private keys, it can reply with an
91AUTH packet where type is RSAPUBLICKEY(3) and data is the public key. If
92possible, an on-screen confirmation may be displayed for the user to
93confirm they want to install the public key on the device.
94
95
96--- OPEN(local-id, 0, "destination") -----------------------------------
97
98The OPEN message informs the recipient that the sender has a stream
99identified by local-id that it wishes to connect to the named
100destination in the message payload.  The local-id may not be zero.
101
102The OPEN message MUST result in either a READY message indicating that
103the connection has been established (and identifying the other end) or
104a CLOSE message, indicating failure.  An OPEN message also implies
105a READY message sent at the same time.
106
107Common destination naming conventions include:
108
109* "tcp:<host>:<port>" - host may be omitted to indicate localhost
110* "udp:<host>:<port>" - host may be omitted to indicate localhost
111* "local-dgram:<identifier>"
112* "local-stream:<identifier>"
113* "shell" - local shell service
114* "upload" - service for pushing files across (like aproto's /sync)
115* "fs-bridge" - FUSE protocol filesystem bridge
116
117
118--- READY(local-id, remote-id, "") -------------------------------------
119
120The READY message informs the recipient that the sender's stream
121identified by local-id is ready for write messages and that it is
122connected to the recipient's stream identified by remote-id.
123
124Neither the local-id nor the remote-id may be zero. 
125
126A READY message containing a remote-id which does not map to an open
127stream on the recipient's side is ignored.  The stream may have been
128closed while this message was in-flight.
129
130The local-id is ignored on all but the first READY message (where it
131is used to establish the connection).  Nonetheless, the local-id MUST
132not change on later READY messages sent to the same stream.
133
134
135
136--- WRITE(0, remote-id, "data") ----------------------------------------
137
138The WRITE message sends data to the recipient's stream identified by
139remote-id.  The payload MUST be <= maxdata in length.
140
141A WRITE message containing a remote-id which does not map to an open
142stream on the recipient's side is ignored.  The stream may have been
143closed while this message was in-flight.
144
145A WRITE message may not be sent until a READY message is received.
146Once a WRITE message is sent, an additional WRITE message may not be
147sent until another READY message has been received.  Recipients of
148a WRITE message that is in violation of this requirement will CLOSE
149the connection.
150
151
152--- CLOSE(local-id, remote-id, "") -------------------------------------
153
154The CLOSE message informs recipient that the connection between the
155sender's stream (local-id) and the recipient's stream (remote-id) is
156broken.  The remote-id MUST not be zero, but the local-id MAY be zero
157if this CLOSE indicates a failed OPEN.
158
159A CLOSE message containing a remote-id which does not map to an open
160stream on the recipient's side is ignored.  The stream may have
161already been closed by the recipient while this message was in-flight.
162
163The recipient should not respond to a CLOSE message in any way.  The
164recipient should cancel pending WRITEs or CLOSEs, but this is not a
165requirement, since they will be ignored.
166
167
168--- SYNC(online, sequence, "") -----------------------------------------
169
170The SYNC message is used by the io pump to make sure that stale
171outbound messages are discarded when the connection to the remote side
172is broken.  It is only used internally to the bridge and never valid
173to send across the wire.  
174
175* when the connection to the remote side goes offline, the io pump 
176  sends a SYNC(0, 0) and starts discarding all messages
177* when the connection to the remote side is established, the io pump
178  sends a SYNC(1, token) and continues to discard messages
179* when the io pump receives a matching SYNC(1, token), it once again
180  starts accepting messages to forward to the remote side
181
182
183--- message command constants ------------------------------------------
184
185#define A_SYNC 0x434e5953
186#define A_CNXN 0x4e584e43
187#define A_AUTH 0x48545541
188#define A_OPEN 0x4e45504f
189#define A_OKAY 0x59414b4f
190#define A_CLSE 0x45534c43
191#define A_WRTE 0x45545257
192
193
194
195--- implementation details ---------------------------------------------
196
197The core of the bridge program will use three threads.  One thread
198will be a select/epoll loop to handle io between various inbound and
199outbound connections and the connection to the remote side.
200
201The remote side connection will be implemented as two threads (one for
202reading, one for writing) and a datagram socketpair to provide the
203channel between the main select/epoll thread and the remote connection
204threadpair.  The reason for this is that for usb connections, the
205kernel interface on linux and osx does not allow you to do meaningful
206nonblocking IO.
207
208The endian swapping for the message headers will happen (as needed) in
209the remote connection threadpair and that the rest of the program will
210always treat message header values as native-endian.
211
212The bridge program will be able to have a number of mini-servers
213compiled in.  They will be published under known names (examples
214"shell", "fs-bridge", etc) and upon receiving an OPEN() to such a
215service, the bridge program will create a stream socketpair and spawn
216a thread or subprocess to handle the io.
217
218
219--- simplified / embedded implementation -------------------------------
220
221For limited environments, like the bootloader, it is allowable to
222support a smaller, fixed number of channels using pre-assigned channel
223ID numbers such that only one stream may be connected to a bootloader
224endpoint at any given time.  The protocol remains unchanged, but the
225"embedded" version of it is less dynamic.
226
227The bootloader will support two streams.  A "bootloader:debug" stream,
228which may be opened to get debug messages from the bootloader and a 
229"bootloader:control", stream which will support the set of basic 
230bootloader commands.
231
232Example command stream dialogues:  
233  "flash_kernel,2515049,........\n" "okay\n" 
234  "flash_ramdisk,5038,........\n" "fail,flash write error\n" 
235  "bogus_command......" <CLOSE>
236
237
238--- future expansion ---------------------------------------------------
239
240I plan on providing either a message or a special control stream so that
241the client device could ask the host computer to setup inbound socket
242translations on the fly on behalf of the client device.
243
244
245The initial design does handshaking to provide flow control, with a
246message flow that looks like:
247
248  >OPEN <READY >WRITE <READY >WRITE <READY >WRITE <CLOSE
249
250The far side may choose to issue the READY message as soon as it receives
251a WRITE or it may defer the READY until the write to the local stream
252succeeds.  A future version may want to do some level of windowing where
253multiple WRITEs may be sent without requiring individual READY acks.
254
255------------------------------------------------------------------------
256
257--- smartsockets -------------------------------------------------------
258
259Port 5037 is used for smart sockets which allow a client on the host
260side to request access to a service in the host adb daemon or in the
261remote (device) daemon.  The service is requested by ascii name,
262preceeded by a 4 digit hex length.  Upon successful connection an
263"OKAY" response is sent, otherwise a "FAIL" message is returned.  Once
264connected the client is talking to that (remote or local) service.
265
266client: <hex4> <service-name>
267server: "OKAY"
268
269client: <hex4> <service-name>
270server: "FAIL" <hex4> <reason>
271
272