• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "transport_util.h"
18 
19 #include <gtest/gtest.h>
20 
21 #include <stdbool.h>
22 #include <stddef.h>
23 #include <stdint.h>
24 #include <string.h>
25 #include <chrono>
26 #include <thread>
27 
28 #include "chpp/app.h"
29 #include "chpp/common/discovery.h"
30 #include "chpp/common/gnss.h"
31 #include "chpp/common/gnss_types.h"
32 #include "chpp/common/standard_uuids.h"
33 #include "chpp/common/wifi.h"
34 #include "chpp/common/wifi_types.h"
35 #include "chpp/common/wwan.h"
36 #include "chpp/crc.h"
37 #include "chpp/log.h"
38 #include "chpp/macros.h"
39 #include "chpp/memory.h"
40 #include "chpp/platform/platform_link.h"
41 #include "chpp/platform/utils.h"
42 #include "chpp/services/discovery.h"
43 #include "chpp/services/loopback.h"
44 #include "chpp/transport.h"
45 #include "chre/pal/wwan.h"
46 
47 namespace chpp::test {
48 
49 /**
50  * Validates a ChppTestResponse. Since the error field within the
51  * ChppAppHeader struct is optional (and not used for common services), this
52  * function returns the error field to be checked if desired, depending on the
53  * service.
54  *
55  * @param buf Buffer containing response.
56  * @param ackSeq Ack sequence to be verified.
57  * @param handle Handle number to be verified
58  * @param transactionID Transaction ID to be verified.
59  *
60  * @return The error field within the ChppAppHeader struct that is used by some
61  * but not all services.
62  */
validateChppTestResponse(void * buf,uint8_t ackSeq,uint8_t handle,uint8_t transactionID)63 uint8_t validateChppTestResponse(void *buf, uint8_t ackSeq, uint8_t handle,
64                                  uint8_t transactionID) {
65   struct ChppTestResponse response = *(ChppTestResponse *)buf;
66 
67   // Check preamble
68   EXPECT_EQ(response.preamble0, kChppPreamble0);
69   EXPECT_EQ(response.preamble1, kChppPreamble1);
70 
71   // Check response transport headers
72   EXPECT_EQ(response.transportHeader.packetCode, CHPP_TRANSPORT_ERROR_NONE);
73   EXPECT_EQ(response.transportHeader.ackSeq, ackSeq);
74 
75   // Check response app headers
76   EXPECT_EQ(response.appHeader.handle, handle);
77   EXPECT_EQ(response.appHeader.type, CHPP_MESSAGE_TYPE_SERVICE_RESPONSE);
78   EXPECT_EQ(response.appHeader.transaction, transactionID);
79 
80   // Return optional response error to be checked if desired
81   return response.appHeader.error;
82 }
83 
84 /**
85  * Aborts a packet and validates state.
86  *
87  * @param transportcontext Maintains status for each transport layer instance.
88  */
endAndValidatePacket(struct ChppTransportState * transportContext)89 void endAndValidatePacket(struct ChppTransportState *transportContext) {
90   chppRxPacketCompleteCb(transportContext);
91   EXPECT_EQ(transportContext->rxStatus.state, CHPP_STATE_PREAMBLE);
92   EXPECT_EQ(transportContext->rxStatus.locInDatagram, 0);
93   EXPECT_EQ(transportContext->rxDatagram.length, 0);
94 }
95 
96 /**
97  * Adds a preamble to a certain location in a buffer, and increases the location
98  * accordingly, to account for the length of the added preamble.
99  *
100  * @param buf Buffer.
101  * @param location Location to add the preamble, which its value will be
102  * increased accordingly.
103  */
addPreambleToBuf(uint8_t * buf,size_t * location)104 void addPreambleToBuf(uint8_t *buf, size_t *location) {
105   buf[(*location)++] = kChppPreamble0;
106   buf[(*location)++] = kChppPreamble1;
107 }
108 
109 /**
110  * Adds a transport header (with default values) to a certain location in a
111  * buffer, and increases the location accordingly, to account for the length of
112  * the added transport header.
113  *
114  * @param buf Buffer.
115  * @param location Location to add the transport header, which its value will be
116  * increased accordingly.
117  *
118  * @return Pointer to the added transport header (e.g. to modify its fields).
119  */
addTransportHeaderToBuf(uint8_t * buf,size_t * location)120 ChppTransportHeader *addTransportHeaderToBuf(uint8_t *buf, size_t *location) {
121   size_t oldLoc = *location;
122 
123   // Default values for initial, minimum size request packet
124   ChppTransportHeader transHeader = {};
125   transHeader.flags = CHPP_TRANSPORT_FLAG_FINISHED_DATAGRAM;
126   transHeader.packetCode = CHPP_TRANSPORT_ERROR_NONE;
127   transHeader.ackSeq = 1;
128   transHeader.seq = 0;
129   transHeader.length = sizeof(ChppAppHeader);
130   transHeader.reserved = 0;
131 
132   memcpy(&buf[*location], &transHeader, sizeof(transHeader));
133   *location += sizeof(transHeader);
134 
135   return (ChppTransportHeader *)&buf[oldLoc];
136 }
137 
138 /**
139  * Adds an app header (with default values) to a certain location in a buffer,
140  * and increases the location accordingly, to account for the length of the
141  * added app header.
142  *
143  * @param buf Buffer.
144  * @param location Location to add the app header, which its value will be
145  * increased accordingly.
146  *
147  * @return Pointer to the added app header (e.g. to modify its fields).
148  */
addAppHeaderToBuf(uint8_t * buf,size_t * location)149 ChppAppHeader *addAppHeaderToBuf(uint8_t *buf, size_t *location) {
150   size_t oldLoc = *location;
151 
152   // Default values - to be updated later as necessary
153   ChppAppHeader appHeader = {};
154   appHeader.handle = CHPP_HANDLE_NEGOTIATED_RANGE_START;
155   appHeader.type = CHPP_MESSAGE_TYPE_CLIENT_REQUEST;
156   appHeader.transaction = 0;
157   appHeader.error = CHPP_APP_ERROR_NONE;
158   appHeader.command = 0;
159 
160   memcpy(&buf[*location], &appHeader, sizeof(appHeader));
161   *location += sizeof(appHeader);
162 
163   return (ChppAppHeader *)&buf[oldLoc];
164 }
165 
166 /**
167  * Adds a transport footer to a certain location in a buffer, and increases the
168  * location accordingly, to account for the length of the added preamble.
169  *
170  * @param buf Buffer.
171  * @param location Location to add the footer. The value of location will be
172  * increased accordingly.
173  *
174  */
addTransportFooterToBuf(uint8_t * buf,size_t * location)175 void addTransportFooterToBuf(uint8_t *buf, size_t *location) {
176   uint32_t *checksum = (uint32_t *)&buf[*location];
177 
178   *checksum = chppCrc32(0, &buf[CHPP_PREAMBLE_LEN_BYTES],
179                         *location - CHPP_PREAMBLE_LEN_BYTES);
180 
181   *location += sizeof(ChppTransportFooter);
182 }
183 
184 /**
185  * Opens a service and checks to make sure it was opened correctly.
186  *
187  * @param transportContext Transport layer context.
188  * @param buf Buffer.
189  * @param ackSeq Ack sequence of the packet to be sent out
190  * @param seq Sequence number of the packet to be sent out.
191  * @param handle Handle of the service to be opened.
192  * @param transactionID Transaction ID for the open request.
193  * @param command Open command.
194  */
openService(ChppTransportState * transportContext,uint8_t * buf,uint8_t ackSeq,uint8_t seq,uint8_t handle,uint8_t transactionID,uint16_t command,struct ChppLinuxLinkState & chppLinuxLinkContext)195 void openService(ChppTransportState *transportContext, uint8_t *buf,
196                  uint8_t ackSeq, uint8_t seq, uint8_t handle,
197                  uint8_t transactionID, uint16_t command,
198                  struct ChppLinuxLinkState &chppLinuxLinkContext) {
199   size_t len = 0;
200 
201   addPreambleToBuf(buf, &len);
202 
203   ChppTransportHeader *transHeader = addTransportHeaderToBuf(buf, &len);
204   transHeader->ackSeq = ackSeq;
205   transHeader->seq = seq;
206 
207   ChppAppHeader *appHeader = addAppHeaderToBuf(buf, &len);
208   appHeader->handle = handle;
209   appHeader->transaction = transactionID;
210   appHeader->command = command;
211 
212   addTransportFooterToBuf(buf, &len);
213 
214   // Send header + payload (if any) + footer
215   EXPECT_TRUE(chppRxDataCb(transportContext, buf, len));
216 
217   // Check for correct state
218   uint8_t nextSeq = transHeader->seq + 1;
219   EXPECT_EQ(transportContext->rxStatus.expectedSeq, nextSeq);
220   EXPECT_EQ(transportContext->rxStatus.state, CHPP_STATE_PREAMBLE);
221 
222   // Wait for response
223   waitForLinkSendDone();
224 
225   // Validate common response fields
226   EXPECT_EQ(validateChppTestResponse(chppLinuxLinkContext.buf, nextSeq, handle,
227                                      transactionID),
228             CHPP_APP_ERROR_NONE);
229 
230   // Check response length
231   EXPECT_EQ(sizeof(ChppTestResponse), CHPP_PREAMBLE_LEN_BYTES +
232                                           sizeof(ChppTransportHeader) +
233                                           sizeof(ChppAppHeader));
234   EXPECT_EQ(transportContext->linkBufferSize,
235             sizeof(ChppTestResponse) + sizeof(ChppTransportFooter));
236 }
237 
238 /**
239  * Sends a command to a service and checks for errors.
240  *
241  * @param transportContext Transport layer context.
242  * @param buf Buffer.
243  * @param ackSeq Ack sequence of the packet to be sent out
244  * @param seq Sequence number of the packet to be sent out.
245  * @param handle Handle of the service to be opened.
246  * @param transactionID Transaction ID for the open request.
247  * @param command Command to be sent.
248  */
sendCommandToService(ChppTransportState * transportContext,uint8_t * buf,uint8_t ackSeq,uint8_t seq,uint8_t handle,uint8_t transactionID,uint16_t command,struct ChppLinuxLinkState & chppLinuxLinkContext)249 void sendCommandToService(ChppTransportState *transportContext, uint8_t *buf,
250                           uint8_t ackSeq, uint8_t seq, uint8_t handle,
251                           uint8_t transactionID, uint16_t command,
252                           struct ChppLinuxLinkState &chppLinuxLinkContext) {
253   size_t len = 0;
254 
255   addPreambleToBuf(buf, &len);
256 
257   ChppTransportHeader *transHeader = addTransportHeaderToBuf(buf, &len);
258   transHeader->ackSeq = ackSeq;
259   transHeader->seq = seq;
260 
261   ChppAppHeader *appHeader = addAppHeaderToBuf(buf, &len);
262   appHeader->handle = handle;
263   appHeader->transaction = transactionID;
264   appHeader->command = command;
265 
266   addTransportFooterToBuf(buf, &len);
267 
268   // Send header + payload (if any) + footer
269   EXPECT_TRUE(chppRxDataCb(transportContext, buf, len));
270 
271   // Check for correct state
272   uint8_t nextSeq = transHeader->seq + 1;
273   EXPECT_EQ(transportContext->rxStatus.expectedSeq, nextSeq);
274   EXPECT_EQ(transportContext->rxStatus.state, CHPP_STATE_PREAMBLE);
275 
276   // Wait for response
277   waitForLinkSendDone();
278 
279   // Validate common response fields
280   EXPECT_EQ(validateChppTestResponse(chppLinuxLinkContext.buf, nextSeq, handle,
281                                      transactionID),
282             CHPP_APP_ERROR_NONE);
283 }
284 
285 /**
286  * Find service handle by name.
287  *
288  * @param appContext App context.
289  * @param name Service name.
290  * @param handle Output service handle if found.
291  *
292  * @return True if service found, false otherwise.
293  */
findServiceHandle(ChppAppState * appContext,const char * name,uint8_t * handle)294 bool findServiceHandle(ChppAppState *appContext, const char *name,
295                        uint8_t *handle) {
296   for (uint8_t i = 0; i < appContext->registeredServiceCount; i++) {
297     if (0 == strcmp(appContext->registeredServices[i]->descriptor.name, name)) {
298       *handle = appContext->registeredServiceStates[i]->handle;
299       return true;
300     }
301   }
302   return false;
303 }
304 
305 }  // namespace chpp::test
306