1# Understanding asockets 2 3The data structure of asocket, with their queue, amessage, and apackets are described 4in [internals.md](internals.md). But understanding asocket, how they are used, and how they are 5paired is non-trivial. This document hopefully explains how bytes flow through them. 6 7## Why ADB needs asocket 8 9The concept of `asocket` was created to achieve two things. 10 11- Carry multiple streams over a single pipe (originally that meant USB only). 12- Manage congestion (propagate back-pressure). 13 14With the introduction of TCP support, an abstraction layer (transport) was created 15but TCP multiplexing was not leveraged. Even when using TCP, a transport still uses `asocket` 16to multiplex streams. 17 18## Data direction and asocket peers 19 20- A asocket is uni-directional. It only allows data to be `enqueue`d. 21- A asocket is paired with a peer asocket which handles traffic in the opposite direction. 22 23## Types of asocket 24 25There are several types of `asocket`. Some are easy to understand because they 26extend `asocket`. 27 28- JdwpSocket 29- JdwpTracker 30- SinkSocket 31- SourceSocket 32 33However there are "undeclared" types, whose behavior differs only via the `asocket` 34function pointers. 35 36- Local Socket (LS) 37- Remote Socket (RS) 38- Smart Socket (SS) 39- Local Service Socket (LSS) 40 41 42## Local socket (abbreviated LS) 43 44A LS interfaces with a file descriptor to forward a stream of bytes 45without altering it (as opposed to a LSS). 46To perform its task, a LS leverages fdevent to request FDE_READ/FDE_WRITE notification. 47 48``` 49 LOCAL SOCKET TRANSPORT 50 ┌────────────────────────────────────────────────┐ ┌──┐ 51 ┌──┐ write(3) │ ┌─────┐ enqueue() │ │ 52 │ │◄─────────┼──┤Queue├─────────────◄──────────────◄──────────┼─────────(A_WRTE)◄── 53 │fd│ │ └─────┘ │ │ │ 54 │ ├──────────►─────────────────┐ │ │ │ 55 └──┘ read(3) └─────────────────┼──────────────────────────────┘ │ │ 56 ▼ └──┘ 57 peer.enqueue() 58``` 59 60A_WRTE apackets are forwarded directly to the LS by the transport. The transport 61is able to route the apacket to the local asocket by using `apacket.msg1` which 62points to the target local asocket `id`. 63 64### Write to fd and Back-pressure 65 66When a payload is enqueued, an LS tries to write as much as possible to its `fd`. 67After the write attempt, the LS stores in its queue what could not be written. 68Based on the volume of data in the queue, it sets `FDE_WRITE` and allows/forbids 69more data to come. 70 71- If there is data in the queue, the LS always requests `FDE_WRITE` events so it 72can write the outstanding data. 73- If there is less than `MAX_PAYLOAD` in the queue, LS calls ready on its peer (a RS), 74so an A_OKAY apacket is sent (which trigger another A_WRTE packet to be send). 75- If there is more than `MAX_PAYLOAD` in the queue, back-pressure is propagated by not 76calling `peer->ready`. This will trigger the other side to not send more A_WRTE until 77the volume of data in the queue has decreased. 78 79### Read from fd and Back-pressure 80 81When it is created, a LS requests FDE_READ from fdevent. When it triggers, it reads 82as much as possible from the `fd` (within MAX_PAYLOAD to make sure transport will take it). 83The data is then enqueueed on the peer. 84 85If `peer.enqueue` indicates that the peer cannot take more updates, the LS deletes 86the FDE_READ request. 87It is re-installed when A_OKAY is received by transport. 88 89## Remote socket (abbreviated RS) 90 91A RS handles outbound traffic and interfaces with a transport. It is simple 92compared to a LS since it merely translates function calls into transport packets. 93 94- enqueue -> A_WRTE 95- ready -> A_OKAY 96- close -> A_CLSE on RS and peer. 97- shutdown-> A_CLSE 98 99A RS is often paired with a LS or a LSS. 100``` 101 LOCAL SOCKET (THIS) TRANSPORT 102 ┌────────────────────────────────────────────────┐ ┌──┐ 103 ┌──┐ write(3) │ ┌─────┐ enqueue() │ │ │ 104 │ │◄─────────┼──┤Queue├─────────────◄──────────────◄──────────┼─────────(A_WRTE)◄── 105 │fd│ │ └─────┘ │ │ │ 106 │ ├──────────►─────────────────┐ │ ─ │ │ 107 └──┘ read(3) └─────────────────┼──────────────────────────────┘ │ │ 108 │ │ │ 109 ┌─────────────────▼─────────────────▲────────────┐ │ │ 110 │ │ │ │ │ 111 │ │ │ │ │ 112 │ └─────────────────────►──────────────────(A_WRTE)───► 113 │ enqueue() │ │ │ 114 └────────────────────────────────────────────────┘ └──┘ 115 REMOTE SOCKET (PEER) 116``` 117 118### RS creation 119 120A RS is always created by the transport layer (on A_OKAY or A_OPEN) and paired with a LS or LSS. 121 122- Upon A_OPEN: The transport creates a LSS to handle inbound traffic and peers it with 123a RS to handle outbound traffic. 124 125- Upon A_OKAY: When receiving this packet, the transport always checks if there is a 126LS with the id matching `msg1`. If there is and it does not have a peer yet, a RS is 127created, which completes a bi-directional chain. 128 129## Local Service Socket (LSS) 130 131A LSS is a wrapper around a `fd` (which is used to build a LS). The purpose is to process 132inbound and outbound traffic when it needs modification. e.g.: The "framebuffer" service 133involves invoking executable `screencap` and generating a header describing the payload 134before forwarding the color payload. This could not be done with a "simple" LS. 135 136The `fd` created by the LSS is often a pipe backed by a thread. 137 138## Smart Socket (abbreviated SS) 139 140These Smart sockets are only created on the host by adb server on accept(3) by the listener 141service. They interface with a TCP socket. 142 143Upon creation, a SS enqueue does not forward anything until the [smart protocol](services.md) 144has provided a target device and a service to invoke. 145 146When these two conditions are met, the SS selects a transport and A_OPEN the service 147on the device. It gives the TCP socket fd to a LS and creates a RS to build a data flow 148similar to what was described in the Local Socket section. 149 150## Examples of dataflow 151 152### Package Manager (Device service) 153 154Let's take the example of the command `adb install -S <SIZE> -`. There are several install 155strategies but for the sake of simplicity, let's focus on the one resulting in invoking 156`pm install -S <SIZE> -` on the device and then streaming the content of the APK. 157 158In the beginning there is only a listener service, waiting for `connect(3)` on the server. 159 160``` 161 ADB Client ADB Server TRANSPORT ADBd 162┌──────────────────────┐ ┌─────────────────┐ │ ┌─────────────────┐ 163│ │ │ │ │ │ │ 164│ │ │ │ │ │ │ 165│ │ │ │ │ │ │ 166│ tcp * ───►* alistener │ │ │ │ 167│ │ │ │ │ │ │ 168│ │ │ │ │ │ │ 169└──────────────────────┘ └─────────────────┘ │ └─────────────────┘ 170 171┌──────────┐ ┌───────┐ 172│ APK │ │Console│ 173└──────────┘ └───────┘ 174``` 175 176Upon `accept(3)`, the listener service creates a SS and gives it the socket `fd`. 177Then the client starts writing to the socket `|host:transport:XXXXXXX| |exec:pm pm install -S <SIZE> ->|`. 178 179``` 180 ADB Client ADB Server TRANSPORT ADBd 181┌──────────────────────┐ ┌─────────────────┐ │ ┌─────────────────┐ 182│ │ │ │ │ │ │ 183│ │ │ │ │ │ │ 184│ │ │ │ │ │ │ 185│ tcp * ───►* SS │ │ │ │ 186│ │ │ │ │ │ │ 187│ │ │ │ │ │ │ 188└──────────────────────┘ └─────────────────┘ │ └─────────────────┘ 189 190┌──────────┐ ┌───────┐ 191│ APK │ │Console│ 192└──────────┘ └───────┘ 193``` 194 195The SS buffers the smart protocol requests until it has everything it needs from 196the client. 197The first part, `host:transport:XXXXXXX` lets the SS know which transport to use (it 198contains the device identified `XXXXXXX`). The second part is the service to execute 199`exec:pm pm install -S <SIZE> -`. 200 201When it has both, the SS creates a LS to handle the TCP `fd`, and creates a RS to let 202the LS talk to the transport. The last thing the SS does before replacing itself with a 203LS (and giving it its socket fd) is sending an A_OPEN apacket. 204 205``` 206 ADB Client ADB Server TRANSPORT ADBd 207┌──────────────────────┐ ┌─────────────────┐ │ ┌─────────────────┐ 208│ │ │ │ │ │ │ 209│ │ │ │ │ │ │ 210│ │ │ │ │ │ │ 211│ tcp * ◄───►* LS │ │ │ │ 212│ │ │ │ │ │ │ │ 213│ │ │ └─────────► RS─┼──────┼─►───┼──────►A_OPEN │ 214└──────────────────────┘ └─────────────────┘ │ └─────────────────┘ 215 216┌──────────┐ ┌───────┐ 217│ APK │ │Console│ 218└──────────┘ └───────┘ 219``` 220So far only one side of the pipeline has been set up. 221 222Upon reception of the A_OPEN on the device side, `pm` is invoked via `fork/exec`. 223A socket pair end is given to a LS. A RS is also created to handle bytes generated by `pm`. 224Now we have a full pipeline able to handle bidirectional streams. 225 226``` 227 ADB Client ADB Server TRANSPORT ADBd 228┌──────────────────────┐ ┌─────────────────┐ │ ┌─────────────────┐ 229│ │ │ │ │ │ │ 230│ │ │ ┌──────────────┼──◄───┼─────┼─RS ◄───┐ │ 231│ │ │ ▼ │ │ │ │ │ 232│ ┌───────────►tcp * ◄───►* LS │ │ │ │ │ 233│ │ │ │ │ │ │ │ │ │ │ 234│ │ │ │ │ └─────────► RS─┼──────┼─►───┼──────►LS │ 235└─────┼─────────────┼──┘ └─────────────────┘ │ └────────▲────────┘ 236 │ │ │ 237┌─────┴────┐ ┌────▼──┐ ┌─────▼────┐ 238│ APK │ │Console│ │ PM │ 239└──────────┘ └───────┘ └──────────┘ 240``` 241 242At this point the client can `write(3)` the content of the apk to feed it to `pm`. 243It is also able to `read(3)` to show the output of `pm` in the console. 244 245