1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "apacket_reader.h"
18 
19 #include "adb.h"
20 #include "adb_trace.h"
21 
APacketReader()22 APacketReader::APacketReader() {
23     prepare_for_next_packet();
24 }
25 
add_packet(std::unique_ptr<apacket> packet)26 void APacketReader::add_packet(std::unique_ptr<apacket> packet) {
27     VLOG(USB) << "Got packet " << command_to_string(packet->msg.command)
28               << ", size=" << packet->msg.data_length;
29     packets_.emplace_back(std::move(packet));
30     prepare_for_next_packet();
31 }
32 
add_bytes(Block && block)33 APacketReader::AddResult APacketReader::add_bytes(Block&& block) noexcept {
34     if (block.remaining() == 0) {
35         return OK;
36     }
37 
38     VLOG(USB) << "Received " << block.remaining() << " bytes";
39 
40     header_.fillFrom(block);
41     if (!header_.is_full()) {
42         // We don't have a full header. Nothing much we can do here, except wait for the next block.
43         return OK;
44     }
45 
46     // From here, we have a full header and we can peek to see how much payload is expected.
47     auto m = reinterpret_cast<amessage*>(header_.data());
48 
49     // Is the packet buggy?
50     if (m->data_length > MAX_PAYLOAD) {
51         VLOG(USB) << "Payload > " << MAX_PAYLOAD;
52         prepare_for_next_packet();
53         return ERROR;
54     }
55 
56     // Is it a packet without payload? If it is, we have an apacket.
57     if (m->data_length == 0) {
58         packet_ = std::make_unique<apacket>();
59         packet_->msg = *reinterpret_cast<amessage*>(header_.data());
60         packet_->payload = Block{0};
61         add_packet(std::move(packet_));
62         return add_bytes(std::move(block));
63     }
64 
65     // In most cases (when the USB layer works as intended) this should be where we have the header
66     // but no payload. The odds of using a fast (std::move) are good but we don't know yet. If
67     // there is nothing remaining, wait until payload packet shows up.
68     if (block.remaining() == 0) {
69         VLOG(USB) << "Packet " << command_to_string(m->command) << " needs " << m->data_length
70                   << " bytes.";
71         return OK;
72     }
73 
74     // We just received the first block for the packet payload. We may be able to use
75     // std::move (fast). If we can't std::move it, we allocate to store the payload as a fallback
76     // mechanism (slow).
77     if (!packet_) {
78         packet_ = std::make_unique<apacket>();
79         packet_->msg = *reinterpret_cast<amessage*>(header_.data());
80 
81         if (block.position() == 0 && block.remaining() == packet_->msg.data_length) {
82             // The block is exactly the expected size and nothing was read from it.
83             // Move it and we are done.
84             VLOG(USB) << "Zero-copy";
85             packet_->payload = std::move(block);
86             add_packet(std::move(packet_));
87             return OK;
88         } else {
89             VLOG(USB) << "Falling back: Allocating block " << packet_->msg.data_length;
90             packet_->payload.resize(packet_->msg.data_length);
91         }
92     }
93 
94     // Fallback (we could not std::move). Fill the payload with incoming block.
95     packet_->payload.fillFrom(block);
96 
97     // If we have all the bytes we needed for the payload, we have a packet. Add it to the list.
98     if (packet_->payload.is_full()) {
99         packet_->payload.rewind();
100         add_packet(std::move(packet_));
101     } else {
102         VLOG(USB) << "Need " << packet_->payload.remaining() << " bytes to full packet";
103     }
104 
105     // If we still have more data, start parsing the next packet via recursion.
106     if (block.remaining() > 0) {
107         VLOG(USB) << "Detected block with merged payload-header (remaining=" << block.remaining()
108                   << " bytes)";
109         return add_bytes(std::move(block));
110     }
111 
112     return OK;
113 }
114 
get_packets()115 std::vector<std::unique_ptr<apacket>> APacketReader::get_packets() noexcept {
116     auto ret = std::move(packets_);
117     // We moved the vector so it is in undefined state. clear() sets it back into a known state
118     packets_.clear();
119     return ret;
120 }
121 
prepare_for_next_packet()122 void APacketReader::prepare_for_next_packet() {
123     header_.rewind();
124     packet_ = std::unique_ptr<apacket>(nullptr);
125 }
126