xref: /aosp_15_r20/external/openthread/src/cli/cli_tcp.cpp (revision cfb92d1480a9e65faed56933e9c12405f45898b4)
1*cfb92d14SAndroid Build Coastguard Worker /*
2*cfb92d14SAndroid Build Coastguard Worker  *  Copyright (c) 2021, The OpenThread Authors.
3*cfb92d14SAndroid Build Coastguard Worker  *  All rights reserved.
4*cfb92d14SAndroid Build Coastguard Worker  *
5*cfb92d14SAndroid Build Coastguard Worker  *  Redistribution and use in source and binary forms, with or without
6*cfb92d14SAndroid Build Coastguard Worker  *  modification, are permitted provided that the following conditions are met:
7*cfb92d14SAndroid Build Coastguard Worker  *  1. Redistributions of source code must retain the above copyright
8*cfb92d14SAndroid Build Coastguard Worker  *     notice, this list of conditions and the following disclaimer.
9*cfb92d14SAndroid Build Coastguard Worker  *  2. Redistributions in binary form must reproduce the above copyright
10*cfb92d14SAndroid Build Coastguard Worker  *     notice, this list of conditions and the following disclaimer in the
11*cfb92d14SAndroid Build Coastguard Worker  *     documentation and/or other materials provided with the distribution.
12*cfb92d14SAndroid Build Coastguard Worker  *  3. Neither the name of the copyright holder nor the
13*cfb92d14SAndroid Build Coastguard Worker  *     names of its contributors may be used to endorse or promote products
14*cfb92d14SAndroid Build Coastguard Worker  *     derived from this software without specific prior written permission.
15*cfb92d14SAndroid Build Coastguard Worker  *
16*cfb92d14SAndroid Build Coastguard Worker  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17*cfb92d14SAndroid Build Coastguard Worker  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18*cfb92d14SAndroid Build Coastguard Worker  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19*cfb92d14SAndroid Build Coastguard Worker  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20*cfb92d14SAndroid Build Coastguard Worker  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21*cfb92d14SAndroid Build Coastguard Worker  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22*cfb92d14SAndroid Build Coastguard Worker  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23*cfb92d14SAndroid Build Coastguard Worker  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24*cfb92d14SAndroid Build Coastguard Worker  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25*cfb92d14SAndroid Build Coastguard Worker  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26*cfb92d14SAndroid Build Coastguard Worker  *  POSSIBILITY OF SUCH DAMAGE.
27*cfb92d14SAndroid Build Coastguard Worker  */
28*cfb92d14SAndroid Build Coastguard Worker 
29*cfb92d14SAndroid Build Coastguard Worker /**
30*cfb92d14SAndroid Build Coastguard Worker  * @file
31*cfb92d14SAndroid Build Coastguard Worker  *   This file implements a TCP CLI tool.
32*cfb92d14SAndroid Build Coastguard Worker  */
33*cfb92d14SAndroid Build Coastguard Worker 
34*cfb92d14SAndroid Build Coastguard Worker #include "openthread-core-config.h"
35*cfb92d14SAndroid Build Coastguard Worker 
36*cfb92d14SAndroid Build Coastguard Worker #include "cli_config.h"
37*cfb92d14SAndroid Build Coastguard Worker 
38*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_TCP_ENABLE && OPENTHREAD_CONFIG_CLI_TCP_ENABLE
39*cfb92d14SAndroid Build Coastguard Worker 
40*cfb92d14SAndroid Build Coastguard Worker #include "cli_tcp.hpp"
41*cfb92d14SAndroid Build Coastguard Worker 
42*cfb92d14SAndroid Build Coastguard Worker #include <openthread/nat64.h>
43*cfb92d14SAndroid Build Coastguard Worker #include <openthread/tcp.h>
44*cfb92d14SAndroid Build Coastguard Worker 
45*cfb92d14SAndroid Build Coastguard Worker #include "cli/cli.hpp"
46*cfb92d14SAndroid Build Coastguard Worker #include "common/encoding.hpp"
47*cfb92d14SAndroid Build Coastguard Worker #include "common/timer.hpp"
48*cfb92d14SAndroid Build Coastguard Worker 
49*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_TLS_ENABLE
50*cfb92d14SAndroid Build Coastguard Worker #include <mbedtls/debug.h>
51*cfb92d14SAndroid Build Coastguard Worker #include <mbedtls/ecjpake.h>
52*cfb92d14SAndroid Build Coastguard Worker #include "crypto/mbedtls.hpp"
53*cfb92d14SAndroid Build Coastguard Worker #endif
54*cfb92d14SAndroid Build Coastguard Worker 
55*cfb92d14SAndroid Build Coastguard Worker namespace ot {
56*cfb92d14SAndroid Build Coastguard Worker namespace Cli {
57*cfb92d14SAndroid Build Coastguard Worker 
58*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_TLS_ENABLE
59*cfb92d14SAndroid Build Coastguard Worker const int TcpExample::sCipherSuites[] = {MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8,
60*cfb92d14SAndroid Build Coastguard Worker                                          MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, 0};
61*cfb92d14SAndroid Build Coastguard Worker #endif
62*cfb92d14SAndroid Build Coastguard Worker 
TcpExample(otInstance * aInstance,OutputImplementer & aOutputImplementer)63*cfb92d14SAndroid Build Coastguard Worker TcpExample::TcpExample(otInstance *aInstance, OutputImplementer &aOutputImplementer)
64*cfb92d14SAndroid Build Coastguard Worker     : Utils(aInstance, aOutputImplementer)
65*cfb92d14SAndroid Build Coastguard Worker     , mInitialized(false)
66*cfb92d14SAndroid Build Coastguard Worker     , mEndpointConnected(false)
67*cfb92d14SAndroid Build Coastguard Worker     , mEndpointConnectedFastOpen(false)
68*cfb92d14SAndroid Build Coastguard Worker     , mSendBusy(false)
69*cfb92d14SAndroid Build Coastguard Worker     , mUseCircularSendBuffer(true)
70*cfb92d14SAndroid Build Coastguard Worker     , mUseTls(false)
71*cfb92d14SAndroid Build Coastguard Worker     , mTlsHandshakeComplete(false)
72*cfb92d14SAndroid Build Coastguard Worker     , mBenchmarkBytesTotal(0)
73*cfb92d14SAndroid Build Coastguard Worker     , mBenchmarkBytesUnsent(0)
74*cfb92d14SAndroid Build Coastguard Worker     , mBenchmarkTimeUsed(0)
75*cfb92d14SAndroid Build Coastguard Worker {
76*cfb92d14SAndroid Build Coastguard Worker     mEndpointAndCircularSendBuffer.mEndpoint   = &mEndpoint;
77*cfb92d14SAndroid Build Coastguard Worker     mEndpointAndCircularSendBuffer.mSendBuffer = &mSendBuffer;
78*cfb92d14SAndroid Build Coastguard Worker }
79*cfb92d14SAndroid Build Coastguard Worker 
80*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_TLS_ENABLE
MbedTlsDebugOutput(void * ctx,int level,const char * file,int line,const char * str)81*cfb92d14SAndroid Build Coastguard Worker void TcpExample::MbedTlsDebugOutput(void *ctx, int level, const char *file, int line, const char *str)
82*cfb92d14SAndroid Build Coastguard Worker {
83*cfb92d14SAndroid Build Coastguard Worker     TcpExample &tcpExample = *static_cast<TcpExample *>(ctx);
84*cfb92d14SAndroid Build Coastguard Worker 
85*cfb92d14SAndroid Build Coastguard Worker     tcpExample.OutputLine("%s:%d:%d: %s", file, line, level, str);
86*cfb92d14SAndroid Build Coastguard Worker }
87*cfb92d14SAndroid Build Coastguard Worker #endif
88*cfb92d14SAndroid Build Coastguard Worker 
89*cfb92d14SAndroid Build Coastguard Worker /**
90*cfb92d14SAndroid Build Coastguard Worker  * @cli tcp init
91*cfb92d14SAndroid Build Coastguard Worker  * @code
92*cfb92d14SAndroid Build Coastguard Worker  * tcp init tls
93*cfb92d14SAndroid Build Coastguard Worker  * Done
94*cfb92d14SAndroid Build Coastguard Worker  * @endcode
95*cfb92d14SAndroid Build Coastguard Worker  * @cparam tcp init [@ca{mode}] [@ca{size}]
96*cfb92d14SAndroid Build Coastguard Worker  * * The `mode` has three possible values:
97*cfb92d14SAndroid Build Coastguard Worker  *   * `tls`: Specifies that the TCP connection between two nodes should also
98*cfb92d14SAndroid Build Coastguard Worker  *     use the TLS protocol on top of TCP. When two nodes communicate over TCP,
99*cfb92d14SAndroid Build Coastguard Worker  *     both nodes must either use TLS or neither node should use TLS because
100*cfb92d14SAndroid Build Coastguard Worker  *     a non-TLS endpoint cannot communicate with a TLS endpoint.
101*cfb92d14SAndroid Build Coastguard Worker  *   * `linked` or `circular`: Either one of these options means that TLS
102*cfb92d14SAndroid Build Coastguard Worker  *     is not to be used, and the specified buffering type should be used for TCP
103*cfb92d14SAndroid Build Coastguard Worker  *     buffering. The behavior of `linked` and `circular` is identical. Examine the code
104*cfb92d14SAndroid Build Coastguard Worker  *     for the differences between these two buffering types.
105*cfb92d14SAndroid Build Coastguard Worker  *     Two endpoints of a TCP connection are not required to use the same buffering type.
106*cfb92d14SAndroid Build Coastguard Worker  * * The `size` parameter sets the size of the receive buffer to associate with the
107*cfb92d14SAndroid Build Coastguard Worker  *   example TCP endpoint. If left unspecified, the maximum size is used. The
108*cfb92d14SAndroid Build Coastguard Worker  *   maximum size is set in `OPENTHREAD_CONFIG_CLI_TCP_RECEIVE_BUFFER_SIZE`.
109*cfb92d14SAndroid Build Coastguard Worker  * @par
110*cfb92d14SAndroid Build Coastguard Worker  * Initializes the example TCP listener and the example TCP endpoint provided
111*cfb92d14SAndroid Build Coastguard Worker  * by the `tcp` CLI.
112*cfb92d14SAndroid Build Coastguard Worker  * @sa otTcpListenerInitialize
113*cfb92d14SAndroid Build Coastguard Worker  * @sa otTcpEndpointInitialize
114*cfb92d14SAndroid Build Coastguard Worker  */
Process(Arg aArgs[])115*cfb92d14SAndroid Build Coastguard Worker template <> otError TcpExample::Process<Cmd("init")>(Arg aArgs[])
116*cfb92d14SAndroid Build Coastguard Worker {
117*cfb92d14SAndroid Build Coastguard Worker     otError error = OT_ERROR_NONE;
118*cfb92d14SAndroid Build Coastguard Worker     size_t  receiveBufferSize;
119*cfb92d14SAndroid Build Coastguard Worker 
120*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(!mInitialized, error = OT_ERROR_ALREADY);
121*cfb92d14SAndroid Build Coastguard Worker 
122*cfb92d14SAndroid Build Coastguard Worker     if (aArgs[0].IsEmpty())
123*cfb92d14SAndroid Build Coastguard Worker     {
124*cfb92d14SAndroid Build Coastguard Worker         mUseCircularSendBuffer = true;
125*cfb92d14SAndroid Build Coastguard Worker         mUseTls                = false;
126*cfb92d14SAndroid Build Coastguard Worker         receiveBufferSize      = sizeof(mReceiveBufferBytes);
127*cfb92d14SAndroid Build Coastguard Worker     }
128*cfb92d14SAndroid Build Coastguard Worker     else
129*cfb92d14SAndroid Build Coastguard Worker     {
130*cfb92d14SAndroid Build Coastguard Worker         if (aArgs[0] == "linked")
131*cfb92d14SAndroid Build Coastguard Worker         {
132*cfb92d14SAndroid Build Coastguard Worker             mUseCircularSendBuffer = false;
133*cfb92d14SAndroid Build Coastguard Worker             mUseTls                = false;
134*cfb92d14SAndroid Build Coastguard Worker         }
135*cfb92d14SAndroid Build Coastguard Worker         else if (aArgs[0] == "circular")
136*cfb92d14SAndroid Build Coastguard Worker         {
137*cfb92d14SAndroid Build Coastguard Worker             mUseCircularSendBuffer = true;
138*cfb92d14SAndroid Build Coastguard Worker             mUseTls                = false;
139*cfb92d14SAndroid Build Coastguard Worker         }
140*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_TLS_ENABLE
141*cfb92d14SAndroid Build Coastguard Worker         else if (aArgs[0] == "tls")
142*cfb92d14SAndroid Build Coastguard Worker         {
143*cfb92d14SAndroid Build Coastguard Worker             mUseCircularSendBuffer = true;
144*cfb92d14SAndroid Build Coastguard Worker             mUseTls                = true;
145*cfb92d14SAndroid Build Coastguard Worker 
146*cfb92d14SAndroid Build Coastguard Worker             mbedtls_x509_crt_init(&mSrvCert);
147*cfb92d14SAndroid Build Coastguard Worker             mbedtls_pk_init(&mPKey);
148*cfb92d14SAndroid Build Coastguard Worker 
149*cfb92d14SAndroid Build Coastguard Worker             mbedtls_ssl_init(&mSslContext);
150*cfb92d14SAndroid Build Coastguard Worker             mbedtls_ssl_config_init(&mSslConfig);
151*cfb92d14SAndroid Build Coastguard Worker             mbedtls_ssl_conf_rng(&mSslConfig, Crypto::MbedTls::CryptoSecurePrng, nullptr);
152*cfb92d14SAndroid Build Coastguard Worker             mbedtls_ssl_conf_authmode(&mSslConfig, MBEDTLS_SSL_VERIFY_NONE);
153*cfb92d14SAndroid Build Coastguard Worker             mbedtls_ssl_conf_ciphersuites(&mSslConfig, sCipherSuites);
154*cfb92d14SAndroid Build Coastguard Worker 
155*cfb92d14SAndroid Build Coastguard Worker #if (MBEDTLS_VERSION_NUMBER >= 0x03020000)
156*cfb92d14SAndroid Build Coastguard Worker             mbedtls_ssl_conf_min_tls_version(&mSslConfig, MBEDTLS_SSL_VERSION_TLS1_2);
157*cfb92d14SAndroid Build Coastguard Worker             mbedtls_ssl_conf_max_tls_version(&mSslConfig, MBEDTLS_SSL_VERSION_TLS1_2);
158*cfb92d14SAndroid Build Coastguard Worker #else
159*cfb92d14SAndroid Build Coastguard Worker             mbedtls_ssl_conf_min_version(&mSslConfig, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3);
160*cfb92d14SAndroid Build Coastguard Worker             mbedtls_ssl_conf_max_version(&mSslConfig, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3);
161*cfb92d14SAndroid Build Coastguard Worker #endif
162*cfb92d14SAndroid Build Coastguard Worker 
163*cfb92d14SAndroid Build Coastguard Worker #if (MBEDTLS_VERSION_NUMBER >= 0x03000000)
164*cfb92d14SAndroid Build Coastguard Worker #include "crypto/mbedtls.hpp"
165*cfb92d14SAndroid Build Coastguard Worker             int rv = mbedtls_pk_parse_key(&mPKey, reinterpret_cast<const unsigned char *>(sSrvKey), sSrvKeyLength,
166*cfb92d14SAndroid Build Coastguard Worker                                           nullptr, 0, Crypto::MbedTls::CryptoSecurePrng, nullptr);
167*cfb92d14SAndroid Build Coastguard Worker #else
168*cfb92d14SAndroid Build Coastguard Worker             int rv = mbedtls_pk_parse_key(&mPKey, reinterpret_cast<const unsigned char *>(sSrvKey), sSrvKeyLength,
169*cfb92d14SAndroid Build Coastguard Worker                                           nullptr, 0);
170*cfb92d14SAndroid Build Coastguard Worker #endif
171*cfb92d14SAndroid Build Coastguard Worker             if (rv != 0)
172*cfb92d14SAndroid Build Coastguard Worker             {
173*cfb92d14SAndroid Build Coastguard Worker                 OutputLine("mbedtls_pk_parse_key returned %d", rv);
174*cfb92d14SAndroid Build Coastguard Worker             }
175*cfb92d14SAndroid Build Coastguard Worker 
176*cfb92d14SAndroid Build Coastguard Worker             rv = mbedtls_x509_crt_parse(&mSrvCert, reinterpret_cast<const unsigned char *>(sSrvPem), sSrvPemLength);
177*cfb92d14SAndroid Build Coastguard Worker             if (rv != 0)
178*cfb92d14SAndroid Build Coastguard Worker             {
179*cfb92d14SAndroid Build Coastguard Worker                 OutputLine("mbedtls_x509_crt_parse (1) returned %d", rv);
180*cfb92d14SAndroid Build Coastguard Worker             }
181*cfb92d14SAndroid Build Coastguard Worker             rv = mbedtls_x509_crt_parse(&mSrvCert, reinterpret_cast<const unsigned char *>(sCasPem), sCasPemLength);
182*cfb92d14SAndroid Build Coastguard Worker             if (rv != 0)
183*cfb92d14SAndroid Build Coastguard Worker             {
184*cfb92d14SAndroid Build Coastguard Worker                 OutputLine("mbedtls_x509_crt_parse (2) returned %d", rv);
185*cfb92d14SAndroid Build Coastguard Worker             }
186*cfb92d14SAndroid Build Coastguard Worker             rv = mbedtls_ssl_setup(&mSslContext, &mSslConfig);
187*cfb92d14SAndroid Build Coastguard Worker             if (rv != 0)
188*cfb92d14SAndroid Build Coastguard Worker             {
189*cfb92d14SAndroid Build Coastguard Worker                 OutputLine("mbedtls_ssl_setup returned %d", rv);
190*cfb92d14SAndroid Build Coastguard Worker             }
191*cfb92d14SAndroid Build Coastguard Worker         }
192*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_CONFIG_TLS_ENABLE
193*cfb92d14SAndroid Build Coastguard Worker         else
194*cfb92d14SAndroid Build Coastguard Worker         {
195*cfb92d14SAndroid Build Coastguard Worker             ExitNow(error = OT_ERROR_INVALID_ARGS);
196*cfb92d14SAndroid Build Coastguard Worker         }
197*cfb92d14SAndroid Build Coastguard Worker 
198*cfb92d14SAndroid Build Coastguard Worker         if (aArgs[1].IsEmpty())
199*cfb92d14SAndroid Build Coastguard Worker         {
200*cfb92d14SAndroid Build Coastguard Worker             receiveBufferSize = sizeof(mReceiveBufferBytes);
201*cfb92d14SAndroid Build Coastguard Worker         }
202*cfb92d14SAndroid Build Coastguard Worker         else
203*cfb92d14SAndroid Build Coastguard Worker         {
204*cfb92d14SAndroid Build Coastguard Worker             uint32_t windowSize;
205*cfb92d14SAndroid Build Coastguard Worker 
206*cfb92d14SAndroid Build Coastguard Worker             SuccessOrExit(error = aArgs[1].ParseAsUint32(windowSize));
207*cfb92d14SAndroid Build Coastguard Worker 
208*cfb92d14SAndroid Build Coastguard Worker             receiveBufferSize = windowSize + ((windowSize + 7) >> 3);
209*cfb92d14SAndroid Build Coastguard Worker             VerifyOrExit(receiveBufferSize <= sizeof(mReceiveBufferBytes) && receiveBufferSize != 0,
210*cfb92d14SAndroid Build Coastguard Worker                          error = OT_ERROR_INVALID_ARGS);
211*cfb92d14SAndroid Build Coastguard Worker         }
212*cfb92d14SAndroid Build Coastguard Worker     }
213*cfb92d14SAndroid Build Coastguard Worker 
214*cfb92d14SAndroid Build Coastguard Worker     otTcpCircularSendBufferInitialize(&mSendBuffer, mSendBufferBytes, sizeof(mSendBufferBytes));
215*cfb92d14SAndroid Build Coastguard Worker 
216*cfb92d14SAndroid Build Coastguard Worker     {
217*cfb92d14SAndroid Build Coastguard Worker         otTcpEndpointInitializeArgs endpointArgs;
218*cfb92d14SAndroid Build Coastguard Worker 
219*cfb92d14SAndroid Build Coastguard Worker         ClearAllBytes(endpointArgs);
220*cfb92d14SAndroid Build Coastguard Worker         endpointArgs.mEstablishedCallback = HandleTcpEstablishedCallback;
221*cfb92d14SAndroid Build Coastguard Worker 
222*cfb92d14SAndroid Build Coastguard Worker         if (mUseCircularSendBuffer)
223*cfb92d14SAndroid Build Coastguard Worker         {
224*cfb92d14SAndroid Build Coastguard Worker             endpointArgs.mForwardProgressCallback = HandleTcpForwardProgressCallback;
225*cfb92d14SAndroid Build Coastguard Worker         }
226*cfb92d14SAndroid Build Coastguard Worker         else
227*cfb92d14SAndroid Build Coastguard Worker         {
228*cfb92d14SAndroid Build Coastguard Worker             endpointArgs.mSendDoneCallback = HandleTcpSendDoneCallback;
229*cfb92d14SAndroid Build Coastguard Worker         }
230*cfb92d14SAndroid Build Coastguard Worker 
231*cfb92d14SAndroid Build Coastguard Worker         endpointArgs.mReceiveAvailableCallback = HandleTcpReceiveAvailableCallback;
232*cfb92d14SAndroid Build Coastguard Worker         endpointArgs.mDisconnectedCallback     = HandleTcpDisconnectedCallback;
233*cfb92d14SAndroid Build Coastguard Worker         endpointArgs.mContext                  = this;
234*cfb92d14SAndroid Build Coastguard Worker         endpointArgs.mReceiveBuffer            = mReceiveBufferBytes;
235*cfb92d14SAndroid Build Coastguard Worker         endpointArgs.mReceiveBufferSize        = receiveBufferSize;
236*cfb92d14SAndroid Build Coastguard Worker 
237*cfb92d14SAndroid Build Coastguard Worker         SuccessOrExit(error = otTcpEndpointInitialize(GetInstancePtr(), &mEndpoint, &endpointArgs));
238*cfb92d14SAndroid Build Coastguard Worker     }
239*cfb92d14SAndroid Build Coastguard Worker 
240*cfb92d14SAndroid Build Coastguard Worker     {
241*cfb92d14SAndroid Build Coastguard Worker         otTcpListenerInitializeArgs listenerArgs;
242*cfb92d14SAndroid Build Coastguard Worker 
243*cfb92d14SAndroid Build Coastguard Worker         ClearAllBytes(listenerArgs);
244*cfb92d14SAndroid Build Coastguard Worker         listenerArgs.mAcceptReadyCallback = HandleTcpAcceptReadyCallback;
245*cfb92d14SAndroid Build Coastguard Worker         listenerArgs.mAcceptDoneCallback  = HandleTcpAcceptDoneCallback;
246*cfb92d14SAndroid Build Coastguard Worker         listenerArgs.mContext             = this;
247*cfb92d14SAndroid Build Coastguard Worker 
248*cfb92d14SAndroid Build Coastguard Worker         error = otTcpListenerInitialize(GetInstancePtr(), &mListener, &listenerArgs);
249*cfb92d14SAndroid Build Coastguard Worker 
250*cfb92d14SAndroid Build Coastguard Worker         if (error != OT_ERROR_NONE)
251*cfb92d14SAndroid Build Coastguard Worker         {
252*cfb92d14SAndroid Build Coastguard Worker             IgnoreReturnValue(otTcpEndpointDeinitialize(&mEndpoint));
253*cfb92d14SAndroid Build Coastguard Worker             ExitNow();
254*cfb92d14SAndroid Build Coastguard Worker         }
255*cfb92d14SAndroid Build Coastguard Worker     }
256*cfb92d14SAndroid Build Coastguard Worker 
257*cfb92d14SAndroid Build Coastguard Worker     mInitialized = true;
258*cfb92d14SAndroid Build Coastguard Worker 
259*cfb92d14SAndroid Build Coastguard Worker exit:
260*cfb92d14SAndroid Build Coastguard Worker     if (error != OT_ERROR_NONE)
261*cfb92d14SAndroid Build Coastguard Worker     {
262*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_TLS_ENABLE
263*cfb92d14SAndroid Build Coastguard Worker         if (mUseTls)
264*cfb92d14SAndroid Build Coastguard Worker         {
265*cfb92d14SAndroid Build Coastguard Worker             mbedtls_ssl_config_free(&mSslConfig);
266*cfb92d14SAndroid Build Coastguard Worker             mbedtls_ssl_free(&mSslContext);
267*cfb92d14SAndroid Build Coastguard Worker 
268*cfb92d14SAndroid Build Coastguard Worker             mbedtls_pk_free(&mPKey);
269*cfb92d14SAndroid Build Coastguard Worker             mbedtls_x509_crt_free(&mSrvCert);
270*cfb92d14SAndroid Build Coastguard Worker         }
271*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_CONFIG_TLS_ENABLE
272*cfb92d14SAndroid Build Coastguard Worker 
273*cfb92d14SAndroid Build Coastguard Worker         otTcpCircularSendBufferForceDiscardAll(&mSendBuffer);
274*cfb92d14SAndroid Build Coastguard Worker         OT_UNUSED_VARIABLE(otTcpCircularSendBufferDeinitialize(&mSendBuffer));
275*cfb92d14SAndroid Build Coastguard Worker     }
276*cfb92d14SAndroid Build Coastguard Worker 
277*cfb92d14SAndroid Build Coastguard Worker     return error;
278*cfb92d14SAndroid Build Coastguard Worker }
279*cfb92d14SAndroid Build Coastguard Worker 
280*cfb92d14SAndroid Build Coastguard Worker /**
281*cfb92d14SAndroid Build Coastguard Worker  * @cli tcp deinit
282*cfb92d14SAndroid Build Coastguard Worker  * @code
283*cfb92d14SAndroid Build Coastguard Worker  * tcp deinit
284*cfb92d14SAndroid Build Coastguard Worker  * Done
285*cfb92d14SAndroid Build Coastguard Worker  * @endcode
286*cfb92d14SAndroid Build Coastguard Worker  * @par api_copy
287*cfb92d14SAndroid Build Coastguard Worker  * #otTcpEndpointDeinitialize
288*cfb92d14SAndroid Build Coastguard Worker  */
Process(Arg aArgs[])289*cfb92d14SAndroid Build Coastguard Worker template <> otError TcpExample::Process<Cmd("deinit")>(Arg aArgs[])
290*cfb92d14SAndroid Build Coastguard Worker {
291*cfb92d14SAndroid Build Coastguard Worker     otError error = OT_ERROR_NONE;
292*cfb92d14SAndroid Build Coastguard Worker     otError endpointError;
293*cfb92d14SAndroid Build Coastguard Worker     otError bufferError;
294*cfb92d14SAndroid Build Coastguard Worker     otError listenerError;
295*cfb92d14SAndroid Build Coastguard Worker 
296*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
297*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(mInitialized, error = OT_ERROR_INVALID_STATE);
298*cfb92d14SAndroid Build Coastguard Worker 
299*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_TLS_ENABLE
300*cfb92d14SAndroid Build Coastguard Worker     if (mUseTls)
301*cfb92d14SAndroid Build Coastguard Worker     {
302*cfb92d14SAndroid Build Coastguard Worker         mbedtls_ssl_config_free(&mSslConfig);
303*cfb92d14SAndroid Build Coastguard Worker         mbedtls_ssl_free(&mSslContext);
304*cfb92d14SAndroid Build Coastguard Worker 
305*cfb92d14SAndroid Build Coastguard Worker         mbedtls_pk_free(&mPKey);
306*cfb92d14SAndroid Build Coastguard Worker         mbedtls_x509_crt_free(&mSrvCert);
307*cfb92d14SAndroid Build Coastguard Worker     }
308*cfb92d14SAndroid Build Coastguard Worker #endif
309*cfb92d14SAndroid Build Coastguard Worker 
310*cfb92d14SAndroid Build Coastguard Worker     endpointError = otTcpEndpointDeinitialize(&mEndpoint);
311*cfb92d14SAndroid Build Coastguard Worker     mSendBusy     = false;
312*cfb92d14SAndroid Build Coastguard Worker 
313*cfb92d14SAndroid Build Coastguard Worker     otTcpCircularSendBufferForceDiscardAll(&mSendBuffer);
314*cfb92d14SAndroid Build Coastguard Worker     bufferError = otTcpCircularSendBufferDeinitialize(&mSendBuffer);
315*cfb92d14SAndroid Build Coastguard Worker 
316*cfb92d14SAndroid Build Coastguard Worker     listenerError = otTcpListenerDeinitialize(&mListener);
317*cfb92d14SAndroid Build Coastguard Worker     mInitialized  = false;
318*cfb92d14SAndroid Build Coastguard Worker 
319*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = endpointError);
320*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = bufferError);
321*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = listenerError);
322*cfb92d14SAndroid Build Coastguard Worker 
323*cfb92d14SAndroid Build Coastguard Worker exit:
324*cfb92d14SAndroid Build Coastguard Worker     return error;
325*cfb92d14SAndroid Build Coastguard Worker }
326*cfb92d14SAndroid Build Coastguard Worker 
327*cfb92d14SAndroid Build Coastguard Worker /**
328*cfb92d14SAndroid Build Coastguard Worker  * @cli tcp bind
329*cfb92d14SAndroid Build Coastguard Worker  * @code
330*cfb92d14SAndroid Build Coastguard Worker  * tcp bind :: 30000
331*cfb92d14SAndroid Build Coastguard Worker  * Done
332*cfb92d14SAndroid Build Coastguard Worker  * @endcode
333*cfb92d14SAndroid Build Coastguard Worker  * @cparam tcp bind @ca{ip} @ca{port}
334*cfb92d14SAndroid Build Coastguard Worker  * * `ip`: IPv6 address to bind to. If you wish to have the TCP/IPv6 stack assign
335*cfb92d14SAndroid Build Coastguard Worker  *   the binding IPv6 address, use the unspecified IPv6 address: `::`.
336*cfb92d14SAndroid Build Coastguard Worker  * * `port`: TCP port number to bind to.
337*cfb92d14SAndroid Build Coastguard Worker  * @par
338*cfb92d14SAndroid Build Coastguard Worker  * Associates an IPv6 address and a port to the example TCP endpoint provided by
339*cfb92d14SAndroid Build Coastguard Worker  * the `tcp` CLI. Associating the TCP endpoint to an IPv6
340*cfb92d14SAndroid Build Coastguard Worker  * address and port is referred to as "naming the TCP endpoint." This binds the
341*cfb92d14SAndroid Build Coastguard Worker  * endpoint for communication. @moreinfo{@tcp}.
342*cfb92d14SAndroid Build Coastguard Worker  * @sa otTcpBind
343*cfb92d14SAndroid Build Coastguard Worker  */
Process(Arg aArgs[])344*cfb92d14SAndroid Build Coastguard Worker template <> otError TcpExample::Process<Cmd("bind")>(Arg aArgs[])
345*cfb92d14SAndroid Build Coastguard Worker {
346*cfb92d14SAndroid Build Coastguard Worker     otError    error;
347*cfb92d14SAndroid Build Coastguard Worker     otSockAddr sockaddr;
348*cfb92d14SAndroid Build Coastguard Worker 
349*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(mInitialized, error = OT_ERROR_INVALID_STATE);
350*cfb92d14SAndroid Build Coastguard Worker 
351*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = aArgs[0].ParseAsIp6Address(sockaddr.mAddress));
352*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = aArgs[1].ParseAsUint16(sockaddr.mPort));
353*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(aArgs[2].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
354*cfb92d14SAndroid Build Coastguard Worker 
355*cfb92d14SAndroid Build Coastguard Worker     error = otTcpBind(&mEndpoint, &sockaddr);
356*cfb92d14SAndroid Build Coastguard Worker 
357*cfb92d14SAndroid Build Coastguard Worker exit:
358*cfb92d14SAndroid Build Coastguard Worker     return error;
359*cfb92d14SAndroid Build Coastguard Worker }
360*cfb92d14SAndroid Build Coastguard Worker 
361*cfb92d14SAndroid Build Coastguard Worker /**
362*cfb92d14SAndroid Build Coastguard Worker  * @cli tcp connect
363*cfb92d14SAndroid Build Coastguard Worker  * @code
364*cfb92d14SAndroid Build Coastguard Worker  * tcp connect fe80:0:0:0:a8df:580a:860:ffa4 30000
365*cfb92d14SAndroid Build Coastguard Worker  * Done
366*cfb92d14SAndroid Build Coastguard Worker  * TCP: Connection established
367*cfb92d14SAndroid Build Coastguard Worker  * @endcode
368*cfb92d14SAndroid Build Coastguard Worker  * @code
369*cfb92d14SAndroid Build Coastguard Worker  * tcp connect 172.17.0.1 1234
370*cfb92d14SAndroid Build Coastguard Worker  * Connecting to synthesized IPv6 address: fdde:ad00:beef:2:0:0:ac11:1
371*cfb92d14SAndroid Build Coastguard Worker  * Done
372*cfb92d14SAndroid Build Coastguard Worker  * @endcode
373*cfb92d14SAndroid Build Coastguard Worker  * @cparam tcp connect @ca{ip} @ca{port} [@ca{fastopen}]
374*cfb92d14SAndroid Build Coastguard Worker  * * `ip`: IP address of the peer The address can be an IPv4 address,
375*cfb92d14SAndroid Build Coastguard Worker  *   which gets synthesized to an IPv6 address using the preferred
376*cfb92d14SAndroid Build Coastguard Worker  *   NAT64 prefix from the network data. The command returns `InvalidState`
377*cfb92d14SAndroid Build Coastguard Worker  *   when the preferred NAT64 prefix is unavailable.
378*cfb92d14SAndroid Build Coastguard Worker  * * `port`: TCP port number of the peer.
379*cfb92d14SAndroid Build Coastguard Worker  * * `fastopen`: This parameter is optional. If set to `fast`, TCP Fast Open is enabled
380*cfb92d14SAndroid Build Coastguard Worker  *   for this connection. Otherwise, if this parameter is set to `slow` or not used,
381*cfb92d14SAndroid Build Coastguard Worker  *   TCP Fast Open is disabled.
382*cfb92d14SAndroid Build Coastguard Worker  * @par
383*cfb92d14SAndroid Build Coastguard Worker  * Establishes a connection with the specified peer.
384*cfb92d14SAndroid Build Coastguard Worker  * @par
385*cfb92d14SAndroid Build Coastguard Worker  * If the connection establishment is successful, the resulting TCP connection
386*cfb92d14SAndroid Build Coastguard Worker  * is associated with the example TCP endpoint. @moreinfo{@tcp}.
387*cfb92d14SAndroid Build Coastguard Worker  * @sa otTcpConnect
388*cfb92d14SAndroid Build Coastguard Worker  */
Process(Arg aArgs[])389*cfb92d14SAndroid Build Coastguard Worker template <> otError TcpExample::Process<Cmd("connect")>(Arg aArgs[])
390*cfb92d14SAndroid Build Coastguard Worker {
391*cfb92d14SAndroid Build Coastguard Worker     otError    error;
392*cfb92d14SAndroid Build Coastguard Worker     otSockAddr sockaddr;
393*cfb92d14SAndroid Build Coastguard Worker     bool       nat64Synth;
394*cfb92d14SAndroid Build Coastguard Worker     uint32_t   flags;
395*cfb92d14SAndroid Build Coastguard Worker 
396*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(mInitialized, error = OT_ERROR_INVALID_STATE);
397*cfb92d14SAndroid Build Coastguard Worker 
398*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = ParseToIp6Address(GetInstancePtr(), aArgs[0], sockaddr.mAddress, nat64Synth));
399*cfb92d14SAndroid Build Coastguard Worker 
400*cfb92d14SAndroid Build Coastguard Worker     if (nat64Synth)
401*cfb92d14SAndroid Build Coastguard Worker     {
402*cfb92d14SAndroid Build Coastguard Worker         OutputFormat("Connecting to synthesized IPv6 address: ");
403*cfb92d14SAndroid Build Coastguard Worker         OutputIp6AddressLine(sockaddr.mAddress);
404*cfb92d14SAndroid Build Coastguard Worker     }
405*cfb92d14SAndroid Build Coastguard Worker 
406*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = aArgs[1].ParseAsUint16(sockaddr.mPort));
407*cfb92d14SAndroid Build Coastguard Worker 
408*cfb92d14SAndroid Build Coastguard Worker     if (aArgs[2].IsEmpty())
409*cfb92d14SAndroid Build Coastguard Worker     {
410*cfb92d14SAndroid Build Coastguard Worker         flags = OT_TCP_CONNECT_NO_FAST_OPEN;
411*cfb92d14SAndroid Build Coastguard Worker     }
412*cfb92d14SAndroid Build Coastguard Worker     else
413*cfb92d14SAndroid Build Coastguard Worker     {
414*cfb92d14SAndroid Build Coastguard Worker         if (aArgs[2] == "slow")
415*cfb92d14SAndroid Build Coastguard Worker         {
416*cfb92d14SAndroid Build Coastguard Worker             flags = OT_TCP_CONNECT_NO_FAST_OPEN;
417*cfb92d14SAndroid Build Coastguard Worker         }
418*cfb92d14SAndroid Build Coastguard Worker         else if (aArgs[2] == "fast")
419*cfb92d14SAndroid Build Coastguard Worker         {
420*cfb92d14SAndroid Build Coastguard Worker             flags = 0;
421*cfb92d14SAndroid Build Coastguard Worker         }
422*cfb92d14SAndroid Build Coastguard Worker         else
423*cfb92d14SAndroid Build Coastguard Worker         {
424*cfb92d14SAndroid Build Coastguard Worker             ExitNow(error = OT_ERROR_INVALID_ARGS);
425*cfb92d14SAndroid Build Coastguard Worker         }
426*cfb92d14SAndroid Build Coastguard Worker 
427*cfb92d14SAndroid Build Coastguard Worker         VerifyOrExit(aArgs[3].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
428*cfb92d14SAndroid Build Coastguard Worker     }
429*cfb92d14SAndroid Build Coastguard Worker 
430*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_TLS_ENABLE
431*cfb92d14SAndroid Build Coastguard Worker     if (mUseTls)
432*cfb92d14SAndroid Build Coastguard Worker     {
433*cfb92d14SAndroid Build Coastguard Worker         int rv = mbedtls_ssl_config_defaults(&mSslConfig, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM,
434*cfb92d14SAndroid Build Coastguard Worker                                              MBEDTLS_SSL_PRESET_DEFAULT);
435*cfb92d14SAndroid Build Coastguard Worker         if (rv != 0)
436*cfb92d14SAndroid Build Coastguard Worker         {
437*cfb92d14SAndroid Build Coastguard Worker             OutputLine("mbedtls_ssl_config_defaults returned %d", rv);
438*cfb92d14SAndroid Build Coastguard Worker         }
439*cfb92d14SAndroid Build Coastguard Worker     }
440*cfb92d14SAndroid Build Coastguard Worker #endif
441*cfb92d14SAndroid Build Coastguard Worker 
442*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = otTcpConnect(&mEndpoint, &sockaddr, flags));
443*cfb92d14SAndroid Build Coastguard Worker     mEndpointConnected         = true;
444*cfb92d14SAndroid Build Coastguard Worker     mEndpointConnectedFastOpen = ((flags & OT_TCP_CONNECT_NO_FAST_OPEN) == 0);
445*cfb92d14SAndroid Build Coastguard Worker 
446*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_TLS_ENABLE
447*cfb92d14SAndroid Build Coastguard Worker     if (mUseTls && mEndpointConnectedFastOpen)
448*cfb92d14SAndroid Build Coastguard Worker     {
449*cfb92d14SAndroid Build Coastguard Worker         PrepareTlsHandshake();
450*cfb92d14SAndroid Build Coastguard Worker         ContinueTlsHandshake();
451*cfb92d14SAndroid Build Coastguard Worker     }
452*cfb92d14SAndroid Build Coastguard Worker #endif
453*cfb92d14SAndroid Build Coastguard Worker 
454*cfb92d14SAndroid Build Coastguard Worker exit:
455*cfb92d14SAndroid Build Coastguard Worker     return error;
456*cfb92d14SAndroid Build Coastguard Worker }
457*cfb92d14SAndroid Build Coastguard Worker 
458*cfb92d14SAndroid Build Coastguard Worker /**
459*cfb92d14SAndroid Build Coastguard Worker  * @cli tcp send
460*cfb92d14SAndroid Build Coastguard Worker  * @code
461*cfb92d14SAndroid Build Coastguard Worker  * tcp send hello
462*cfb92d14SAndroid Build Coastguard Worker  * Done
463*cfb92d14SAndroid Build Coastguard Worker  * @endcode
464*cfb92d14SAndroid Build Coastguard Worker  * @cparam tcp send @ca{message}
465*cfb92d14SAndroid Build Coastguard Worker  * The `message` parameter contains the message you want to send to the
466*cfb92d14SAndroid Build Coastguard Worker  * remote TCP endpoint.
467*cfb92d14SAndroid Build Coastguard Worker  * @par
468*cfb92d14SAndroid Build Coastguard Worker  * Sends data over the TCP connection associated with the example TCP endpoint
469*cfb92d14SAndroid Build Coastguard Worker  * that is provided with the `tcp` CLI. @moreinfo{@tcp}.
470*cfb92d14SAndroid Build Coastguard Worker  */
Process(Arg aArgs[])471*cfb92d14SAndroid Build Coastguard Worker template <> otError TcpExample::Process<Cmd("send")>(Arg aArgs[])
472*cfb92d14SAndroid Build Coastguard Worker {
473*cfb92d14SAndroid Build Coastguard Worker     otError error;
474*cfb92d14SAndroid Build Coastguard Worker 
475*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(mInitialized, error = OT_ERROR_INVALID_STATE);
476*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(mBenchmarkBytesTotal == 0, error = OT_ERROR_BUSY);
477*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(!aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
478*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(aArgs[1].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
479*cfb92d14SAndroid Build Coastguard Worker 
480*cfb92d14SAndroid Build Coastguard Worker     if (mUseCircularSendBuffer)
481*cfb92d14SAndroid Build Coastguard Worker     {
482*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_TLS_ENABLE
483*cfb92d14SAndroid Build Coastguard Worker         if (mUseTls)
484*cfb92d14SAndroid Build Coastguard Worker         {
485*cfb92d14SAndroid Build Coastguard Worker             int rv = mbedtls_ssl_write(&mSslContext, reinterpret_cast<unsigned char *>(aArgs[0].GetCString()),
486*cfb92d14SAndroid Build Coastguard Worker                                        aArgs[0].GetLength());
487*cfb92d14SAndroid Build Coastguard Worker 
488*cfb92d14SAndroid Build Coastguard Worker             if (rv < 0 && rv != MBEDTLS_ERR_SSL_WANT_WRITE && rv != MBEDTLS_ERR_SSL_WANT_READ)
489*cfb92d14SAndroid Build Coastguard Worker             {
490*cfb92d14SAndroid Build Coastguard Worker                 ExitNow(error = OT_ERROR_FAILED);
491*cfb92d14SAndroid Build Coastguard Worker             }
492*cfb92d14SAndroid Build Coastguard Worker 
493*cfb92d14SAndroid Build Coastguard Worker             error = OT_ERROR_NONE;
494*cfb92d14SAndroid Build Coastguard Worker         }
495*cfb92d14SAndroid Build Coastguard Worker         else
496*cfb92d14SAndroid Build Coastguard Worker #endif
497*cfb92d14SAndroid Build Coastguard Worker         {
498*cfb92d14SAndroid Build Coastguard Worker             size_t written;
499*cfb92d14SAndroid Build Coastguard Worker 
500*cfb92d14SAndroid Build Coastguard Worker             SuccessOrExit(error = otTcpCircularSendBufferWrite(&mEndpoint, &mSendBuffer, aArgs[0].GetCString(),
501*cfb92d14SAndroid Build Coastguard Worker                                                                aArgs[0].GetLength(), &written, 0));
502*cfb92d14SAndroid Build Coastguard Worker         }
503*cfb92d14SAndroid Build Coastguard Worker     }
504*cfb92d14SAndroid Build Coastguard Worker     else
505*cfb92d14SAndroid Build Coastguard Worker     {
506*cfb92d14SAndroid Build Coastguard Worker         VerifyOrExit(!mSendBusy, error = OT_ERROR_BUSY);
507*cfb92d14SAndroid Build Coastguard Worker 
508*cfb92d14SAndroid Build Coastguard Worker         mSendLink.mNext   = nullptr;
509*cfb92d14SAndroid Build Coastguard Worker         mSendLink.mData   = mSendBufferBytes;
510*cfb92d14SAndroid Build Coastguard Worker         mSendLink.mLength = OT_MIN(aArgs[0].GetLength(), sizeof(mSendBufferBytes));
511*cfb92d14SAndroid Build Coastguard Worker         memcpy(mSendBufferBytes, aArgs[0].GetCString(), mSendLink.mLength);
512*cfb92d14SAndroid Build Coastguard Worker 
513*cfb92d14SAndroid Build Coastguard Worker         SuccessOrExit(error = otTcpSendByReference(&mEndpoint, &mSendLink, 0));
514*cfb92d14SAndroid Build Coastguard Worker         mSendBusy = true;
515*cfb92d14SAndroid Build Coastguard Worker     }
516*cfb92d14SAndroid Build Coastguard Worker 
517*cfb92d14SAndroid Build Coastguard Worker exit:
518*cfb92d14SAndroid Build Coastguard Worker     return error;
519*cfb92d14SAndroid Build Coastguard Worker }
520*cfb92d14SAndroid Build Coastguard Worker 
Process(Arg aArgs[])521*cfb92d14SAndroid Build Coastguard Worker template <> otError TcpExample::Process<Cmd("benchmark")>(Arg aArgs[])
522*cfb92d14SAndroid Build Coastguard Worker {
523*cfb92d14SAndroid Build Coastguard Worker     otError error = OT_ERROR_NONE;
524*cfb92d14SAndroid Build Coastguard Worker 
525*cfb92d14SAndroid Build Coastguard Worker     /**
526*cfb92d14SAndroid Build Coastguard Worker      * @cli tcp benchmark result
527*cfb92d14SAndroid Build Coastguard Worker      * @code
528*cfb92d14SAndroid Build Coastguard Worker      * tcp benchmark result
529*cfb92d14SAndroid Build Coastguard Worker      * TCP Benchmark Status: Ongoing
530*cfb92d14SAndroid Build Coastguard Worker      * Done
531*cfb92d14SAndroid Build Coastguard Worker      * @endcode
532*cfb92d14SAndroid Build Coastguard Worker      * @code
533*cfb92d14SAndroid Build Coastguard Worker      * tcp benchmark result
534*cfb92d14SAndroid Build Coastguard Worker      * TCP Benchmark Status: Completed
535*cfb92d14SAndroid Build Coastguard Worker      * TCP Benchmark Complete: Transferred 73728 bytes in 7056 milliseconds
536*cfb92d14SAndroid Build Coastguard Worker      * TCP Goodput: 83.592 kb/s
537*cfb92d14SAndroid Build Coastguard Worker      * @endcode
538*cfb92d14SAndroid Build Coastguard Worker      * @par
539*cfb92d14SAndroid Build Coastguard Worker      * Shows the latest result of the TCP benchmark test. Possible status values:
540*cfb92d14SAndroid Build Coastguard Worker      * * Ongoing
541*cfb92d14SAndroid Build Coastguard Worker      * * Completed
542*cfb92d14SAndroid Build Coastguard Worker      * * Untested
543*cfb92d14SAndroid Build Coastguard Worker      * @par
544*cfb92d14SAndroid Build Coastguard Worker      * This command is primarily intended for creating scripts that automate
545*cfb92d14SAndroid Build Coastguard Worker      * the TCP benchmark test.
546*cfb92d14SAndroid Build Coastguard Worker      */
547*cfb92d14SAndroid Build Coastguard Worker     if (aArgs[0] == "result")
548*cfb92d14SAndroid Build Coastguard Worker     {
549*cfb92d14SAndroid Build Coastguard Worker         OutputFormat("TCP Benchmark Status: ");
550*cfb92d14SAndroid Build Coastguard Worker 
551*cfb92d14SAndroid Build Coastguard Worker         if (mBenchmarkBytesTotal != 0)
552*cfb92d14SAndroid Build Coastguard Worker         {
553*cfb92d14SAndroid Build Coastguard Worker             OutputLine("Ongoing");
554*cfb92d14SAndroid Build Coastguard Worker         }
555*cfb92d14SAndroid Build Coastguard Worker         else if (mBenchmarkTimeUsed != 0)
556*cfb92d14SAndroid Build Coastguard Worker         {
557*cfb92d14SAndroid Build Coastguard Worker             OutputLine("Completed");
558*cfb92d14SAndroid Build Coastguard Worker             OutputBenchmarkResult();
559*cfb92d14SAndroid Build Coastguard Worker         }
560*cfb92d14SAndroid Build Coastguard Worker         else
561*cfb92d14SAndroid Build Coastguard Worker         {
562*cfb92d14SAndroid Build Coastguard Worker             OutputLine("Untested");
563*cfb92d14SAndroid Build Coastguard Worker         }
564*cfb92d14SAndroid Build Coastguard Worker     }
565*cfb92d14SAndroid Build Coastguard Worker     /**
566*cfb92d14SAndroid Build Coastguard Worker      * @cli tcp benchmark run
567*cfb92d14SAndroid Build Coastguard Worker      * @code
568*cfb92d14SAndroid Build Coastguard Worker      * tcp benchmark run
569*cfb92d14SAndroid Build Coastguard Worker      * Done
570*cfb92d14SAndroid Build Coastguard Worker      * TCP Benchmark Complete: Transferred 73728 bytes in 7233 milliseconds
571*cfb92d14SAndroid Build Coastguard Worker      * TCP Goodput: 81.546 kb/s
572*cfb92d14SAndroid Build Coastguard Worker      * @endcode
573*cfb92d14SAndroid Build Coastguard Worker      * @cparam tcp benchmark run [@ca{size}]
574*cfb92d14SAndroid Build Coastguard Worker      * Use the `size` parameter to specify the number of bytes to send
575*cfb92d14SAndroid Build Coastguard Worker      * for the benchmark. If you do not use the `size` parameter, the default
576*cfb92d14SAndroid Build Coastguard Worker      * value (`OPENTHREAD_CONFIG_CLI_TCP_DEFAULT_BENCHMARK_SIZE`) is used.
577*cfb92d14SAndroid Build Coastguard Worker      * @par
578*cfb92d14SAndroid Build Coastguard Worker      * Transfers the specified number of bytes using the TCP connection
579*cfb92d14SAndroid Build Coastguard Worker      * currently associated with the example TCP endpoint provided by the `tcp` CLI.
580*cfb92d14SAndroid Build Coastguard Worker      * @note You must establish a TCP connection before you run this command.
581*cfb92d14SAndroid Build Coastguard Worker      */
582*cfb92d14SAndroid Build Coastguard Worker     else if (aArgs[0] == "run")
583*cfb92d14SAndroid Build Coastguard Worker     {
584*cfb92d14SAndroid Build Coastguard Worker         VerifyOrExit(!mSendBusy, error = OT_ERROR_BUSY);
585*cfb92d14SAndroid Build Coastguard Worker         VerifyOrExit(mBenchmarkBytesTotal == 0, error = OT_ERROR_BUSY);
586*cfb92d14SAndroid Build Coastguard Worker 
587*cfb92d14SAndroid Build Coastguard Worker         if (aArgs[1].IsEmpty())
588*cfb92d14SAndroid Build Coastguard Worker         {
589*cfb92d14SAndroid Build Coastguard Worker             mBenchmarkBytesTotal = OPENTHREAD_CONFIG_CLI_TCP_DEFAULT_BENCHMARK_SIZE;
590*cfb92d14SAndroid Build Coastguard Worker         }
591*cfb92d14SAndroid Build Coastguard Worker         else
592*cfb92d14SAndroid Build Coastguard Worker         {
593*cfb92d14SAndroid Build Coastguard Worker             SuccessOrExit(error = aArgs[1].ParseAsUint32(mBenchmarkBytesTotal));
594*cfb92d14SAndroid Build Coastguard Worker             VerifyOrExit(mBenchmarkBytesTotal != 0, error = OT_ERROR_INVALID_ARGS);
595*cfb92d14SAndroid Build Coastguard Worker         }
596*cfb92d14SAndroid Build Coastguard Worker 
597*cfb92d14SAndroid Build Coastguard Worker         VerifyOrExit(aArgs[2].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
598*cfb92d14SAndroid Build Coastguard Worker 
599*cfb92d14SAndroid Build Coastguard Worker         mBenchmarkStart       = TimerMilli::GetNow();
600*cfb92d14SAndroid Build Coastguard Worker         mBenchmarkBytesUnsent = mBenchmarkBytesTotal;
601*cfb92d14SAndroid Build Coastguard Worker 
602*cfb92d14SAndroid Build Coastguard Worker         if (mUseCircularSendBuffer)
603*cfb92d14SAndroid Build Coastguard Worker         {
604*cfb92d14SAndroid Build Coastguard Worker             SuccessOrExit(error = ContinueBenchmarkCircularSend());
605*cfb92d14SAndroid Build Coastguard Worker         }
606*cfb92d14SAndroid Build Coastguard Worker         else
607*cfb92d14SAndroid Build Coastguard Worker         {
608*cfb92d14SAndroid Build Coastguard Worker             uint32_t benchmarkLinksLeft =
609*cfb92d14SAndroid Build Coastguard Worker                 (mBenchmarkBytesTotal + sizeof(mSendBufferBytes) - 1) / sizeof(mSendBufferBytes);
610*cfb92d14SAndroid Build Coastguard Worker             uint32_t toSendOut = OT_MIN(OT_ARRAY_LENGTH(mBenchmarkLinks), benchmarkLinksLeft);
611*cfb92d14SAndroid Build Coastguard Worker 
612*cfb92d14SAndroid Build Coastguard Worker             /* We could also point the linked buffers directly to sBenchmarkData. */
613*cfb92d14SAndroid Build Coastguard Worker             memset(mSendBufferBytes, 'a', sizeof(mSendBufferBytes));
614*cfb92d14SAndroid Build Coastguard Worker 
615*cfb92d14SAndroid Build Coastguard Worker             for (uint32_t i = 0; i != toSendOut; i++)
616*cfb92d14SAndroid Build Coastguard Worker             {
617*cfb92d14SAndroid Build Coastguard Worker                 mBenchmarkLinks[i].mNext   = nullptr;
618*cfb92d14SAndroid Build Coastguard Worker                 mBenchmarkLinks[i].mData   = mSendBufferBytes;
619*cfb92d14SAndroid Build Coastguard Worker                 mBenchmarkLinks[i].mLength = sizeof(mSendBufferBytes);
620*cfb92d14SAndroid Build Coastguard Worker 
621*cfb92d14SAndroid Build Coastguard Worker                 if (i == 0 && mBenchmarkBytesTotal % sizeof(mSendBufferBytes) != 0)
622*cfb92d14SAndroid Build Coastguard Worker                 {
623*cfb92d14SAndroid Build Coastguard Worker                     mBenchmarkLinks[i].mLength = mBenchmarkBytesTotal % sizeof(mSendBufferBytes);
624*cfb92d14SAndroid Build Coastguard Worker                 }
625*cfb92d14SAndroid Build Coastguard Worker 
626*cfb92d14SAndroid Build Coastguard Worker                 error = otTcpSendByReference(&mEndpoint, &mBenchmarkLinks[i],
627*cfb92d14SAndroid Build Coastguard Worker                                              i == toSendOut - 1 ? 0 : OT_TCP_SEND_MORE_TO_COME);
628*cfb92d14SAndroid Build Coastguard Worker                 VerifyOrExit(error == OT_ERROR_NONE, mBenchmarkBytesTotal = 0);
629*cfb92d14SAndroid Build Coastguard Worker             }
630*cfb92d14SAndroid Build Coastguard Worker         }
631*cfb92d14SAndroid Build Coastguard Worker     }
632*cfb92d14SAndroid Build Coastguard Worker     else
633*cfb92d14SAndroid Build Coastguard Worker     {
634*cfb92d14SAndroid Build Coastguard Worker         error = OT_ERROR_INVALID_ARGS;
635*cfb92d14SAndroid Build Coastguard Worker     }
636*cfb92d14SAndroid Build Coastguard Worker 
637*cfb92d14SAndroid Build Coastguard Worker exit:
638*cfb92d14SAndroid Build Coastguard Worker     return error;
639*cfb92d14SAndroid Build Coastguard Worker }
640*cfb92d14SAndroid Build Coastguard Worker 
641*cfb92d14SAndroid Build Coastguard Worker /**
642*cfb92d14SAndroid Build Coastguard Worker  * @cli tcp sendend
643*cfb92d14SAndroid Build Coastguard Worker  * @code
644*cfb92d14SAndroid Build Coastguard Worker  * tcp sendend
645*cfb92d14SAndroid Build Coastguard Worker  * Done
646*cfb92d14SAndroid Build Coastguard Worker  * @endcode
647*cfb92d14SAndroid Build Coastguard Worker  * @par
648*cfb92d14SAndroid Build Coastguard Worker  * Sends the "end of stream" signal over the TCP connection
649*cfb92d14SAndroid Build Coastguard Worker  * associated with the example TCP endpoint provided by the `tcp` CLI. This
650*cfb92d14SAndroid Build Coastguard Worker  * alerts the peer that it will not receive any more data over this TCP connection.
651*cfb92d14SAndroid Build Coastguard Worker  * @sa otTcpSendEndOfStream
652*cfb92d14SAndroid Build Coastguard Worker  */
Process(Arg aArgs[])653*cfb92d14SAndroid Build Coastguard Worker template <> otError TcpExample::Process<Cmd("sendend")>(Arg aArgs[])
654*cfb92d14SAndroid Build Coastguard Worker {
655*cfb92d14SAndroid Build Coastguard Worker     otError error;
656*cfb92d14SAndroid Build Coastguard Worker 
657*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(mInitialized, error = OT_ERROR_INVALID_STATE);
658*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
659*cfb92d14SAndroid Build Coastguard Worker 
660*cfb92d14SAndroid Build Coastguard Worker     error = otTcpSendEndOfStream(&mEndpoint);
661*cfb92d14SAndroid Build Coastguard Worker 
662*cfb92d14SAndroid Build Coastguard Worker exit:
663*cfb92d14SAndroid Build Coastguard Worker     return error;
664*cfb92d14SAndroid Build Coastguard Worker }
665*cfb92d14SAndroid Build Coastguard Worker 
666*cfb92d14SAndroid Build Coastguard Worker /**
667*cfb92d14SAndroid Build Coastguard Worker  * @cli tcp abort
668*cfb92d14SAndroid Build Coastguard Worker  * @code
669*cfb92d14SAndroid Build Coastguard Worker  * tcp abort
670*cfb92d14SAndroid Build Coastguard Worker  * TCP: Connection reset
671*cfb92d14SAndroid Build Coastguard Worker  * Done
672*cfb92d14SAndroid Build Coastguard Worker  * @endcode
673*cfb92d14SAndroid Build Coastguard Worker  * @par
674*cfb92d14SAndroid Build Coastguard Worker  * Unceremoniously ends the TCP connection associated with the
675*cfb92d14SAndroid Build Coastguard Worker  * example TCP endpoint, transitioning the TCP endpoint to the closed state.
676*cfb92d14SAndroid Build Coastguard Worker  * @sa otTcpAbort
677*cfb92d14SAndroid Build Coastguard Worker  */
Process(Arg aArgs[])678*cfb92d14SAndroid Build Coastguard Worker template <> otError TcpExample::Process<Cmd("abort")>(Arg aArgs[])
679*cfb92d14SAndroid Build Coastguard Worker {
680*cfb92d14SAndroid Build Coastguard Worker     otError error;
681*cfb92d14SAndroid Build Coastguard Worker 
682*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
683*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(mInitialized, error = OT_ERROR_INVALID_STATE);
684*cfb92d14SAndroid Build Coastguard Worker 
685*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = otTcpAbort(&mEndpoint));
686*cfb92d14SAndroid Build Coastguard Worker     mEndpointConnected         = false;
687*cfb92d14SAndroid Build Coastguard Worker     mEndpointConnectedFastOpen = false;
688*cfb92d14SAndroid Build Coastguard Worker 
689*cfb92d14SAndroid Build Coastguard Worker exit:
690*cfb92d14SAndroid Build Coastguard Worker     return error;
691*cfb92d14SAndroid Build Coastguard Worker }
692*cfb92d14SAndroid Build Coastguard Worker 
693*cfb92d14SAndroid Build Coastguard Worker /**
694*cfb92d14SAndroid Build Coastguard Worker  * @cli tcp listen
695*cfb92d14SAndroid Build Coastguard Worker  * @code
696*cfb92d14SAndroid Build Coastguard Worker  * tcp listen :: 30000
697*cfb92d14SAndroid Build Coastguard Worker  * Done
698*cfb92d14SAndroid Build Coastguard Worker  * @endcode
699*cfb92d14SAndroid Build Coastguard Worker  * @cparam tcp listen @ca{ip} @ca{port}
700*cfb92d14SAndroid Build Coastguard Worker  * The following parameters are required:
701*cfb92d14SAndroid Build Coastguard Worker  * * `ip`: IPv6 address or the unspecified IPv6 address (`::`) of the example
702*cfb92d14SAndroid Build Coastguard Worker  *   TCP listener provided by the `tcp` CLI.
703*cfb92d14SAndroid Build Coastguard Worker  * * `port`: TCP port of the example TCP listener.
704*cfb92d14SAndroid Build Coastguard Worker  *   If no TCP connection is associated with the example TCP endpoint, then any
705*cfb92d14SAndroid Build Coastguard Worker  *   incoming connections matching the specified IPv6 address and port are accepted
706*cfb92d14SAndroid Build Coastguard Worker  *   and are associated with the example TCP endpoint.
707*cfb92d14SAndroid Build Coastguard Worker  * @par
708*cfb92d14SAndroid Build Coastguard Worker  * Uses the example TCP listener to listen for incoming connections on the
709*cfb92d14SAndroid Build Coastguard Worker  * specified IPv6 address and port. @moreinfo{@tcp}.
710*cfb92d14SAndroid Build Coastguard Worker  * @sa otTcpListen
711*cfb92d14SAndroid Build Coastguard Worker  */
Process(Arg aArgs[])712*cfb92d14SAndroid Build Coastguard Worker template <> otError TcpExample::Process<Cmd("listen")>(Arg aArgs[])
713*cfb92d14SAndroid Build Coastguard Worker {
714*cfb92d14SAndroid Build Coastguard Worker     otError    error;
715*cfb92d14SAndroid Build Coastguard Worker     otSockAddr sockaddr;
716*cfb92d14SAndroid Build Coastguard Worker 
717*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(mInitialized, error = OT_ERROR_INVALID_STATE);
718*cfb92d14SAndroid Build Coastguard Worker 
719*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = aArgs[0].ParseAsIp6Address(sockaddr.mAddress));
720*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = aArgs[1].ParseAsUint16(sockaddr.mPort));
721*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(aArgs[2].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
722*cfb92d14SAndroid Build Coastguard Worker 
723*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = otTcpStopListening(&mListener));
724*cfb92d14SAndroid Build Coastguard Worker     error = otTcpListen(&mListener, &sockaddr);
725*cfb92d14SAndroid Build Coastguard Worker 
726*cfb92d14SAndroid Build Coastguard Worker exit:
727*cfb92d14SAndroid Build Coastguard Worker     return error;
728*cfb92d14SAndroid Build Coastguard Worker }
729*cfb92d14SAndroid Build Coastguard Worker 
730*cfb92d14SAndroid Build Coastguard Worker /**
731*cfb92d14SAndroid Build Coastguard Worker  * @cli tcp stoplistening
732*cfb92d14SAndroid Build Coastguard Worker  * @code
733*cfb92d14SAndroid Build Coastguard Worker  * tcp stoplistening
734*cfb92d14SAndroid Build Coastguard Worker  * Done
735*cfb92d14SAndroid Build Coastguard Worker  * @endcode
736*cfb92d14SAndroid Build Coastguard Worker  * @par
737*cfb92d14SAndroid Build Coastguard Worker  * Instructs the example TCP listener to stop listening for incoming TCP connections.
738*cfb92d14SAndroid Build Coastguard Worker  * @sa otTcpStopListening
739*cfb92d14SAndroid Build Coastguard Worker  */
Process(Arg aArgs[])740*cfb92d14SAndroid Build Coastguard Worker template <> otError TcpExample::Process<Cmd("stoplistening")>(Arg aArgs[])
741*cfb92d14SAndroid Build Coastguard Worker {
742*cfb92d14SAndroid Build Coastguard Worker     otError error;
743*cfb92d14SAndroid Build Coastguard Worker 
744*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
745*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(mInitialized, error = OT_ERROR_INVALID_STATE);
746*cfb92d14SAndroid Build Coastguard Worker 
747*cfb92d14SAndroid Build Coastguard Worker     error = otTcpStopListening(&mListener);
748*cfb92d14SAndroid Build Coastguard Worker 
749*cfb92d14SAndroid Build Coastguard Worker exit:
750*cfb92d14SAndroid Build Coastguard Worker     return error;
751*cfb92d14SAndroid Build Coastguard Worker }
752*cfb92d14SAndroid Build Coastguard Worker 
Process(Arg aArgs[])753*cfb92d14SAndroid Build Coastguard Worker otError TcpExample::Process(Arg aArgs[])
754*cfb92d14SAndroid Build Coastguard Worker {
755*cfb92d14SAndroid Build Coastguard Worker #define CmdEntry(aCommandString)                                  \
756*cfb92d14SAndroid Build Coastguard Worker     {                                                             \
757*cfb92d14SAndroid Build Coastguard Worker         aCommandString, &TcpExample::Process<Cmd(aCommandString)> \
758*cfb92d14SAndroid Build Coastguard Worker     }
759*cfb92d14SAndroid Build Coastguard Worker 
760*cfb92d14SAndroid Build Coastguard Worker     static constexpr Command kCommands[] = {
761*cfb92d14SAndroid Build Coastguard Worker         CmdEntry("abort"), CmdEntry("benchmark"), CmdEntry("bind"), CmdEntry("connect"), CmdEntry("deinit"),
762*cfb92d14SAndroid Build Coastguard Worker         CmdEntry("init"),  CmdEntry("listen"),    CmdEntry("send"), CmdEntry("sendend"), CmdEntry("stoplistening"),
763*cfb92d14SAndroid Build Coastguard Worker     };
764*cfb92d14SAndroid Build Coastguard Worker 
765*cfb92d14SAndroid Build Coastguard Worker     static_assert(BinarySearch::IsSorted(kCommands), "kCommands is not sorted");
766*cfb92d14SAndroid Build Coastguard Worker 
767*cfb92d14SAndroid Build Coastguard Worker     otError        error = OT_ERROR_INVALID_COMMAND;
768*cfb92d14SAndroid Build Coastguard Worker     const Command *command;
769*cfb92d14SAndroid Build Coastguard Worker 
770*cfb92d14SAndroid Build Coastguard Worker     if (aArgs[0].IsEmpty() || (aArgs[0] == "help"))
771*cfb92d14SAndroid Build Coastguard Worker     {
772*cfb92d14SAndroid Build Coastguard Worker         OutputCommandTable(kCommands);
773*cfb92d14SAndroid Build Coastguard Worker         ExitNow(error = aArgs[0].IsEmpty() ? error : OT_ERROR_NONE);
774*cfb92d14SAndroid Build Coastguard Worker     }
775*cfb92d14SAndroid Build Coastguard Worker 
776*cfb92d14SAndroid Build Coastguard Worker     command = BinarySearch::Find(aArgs[0].GetCString(), kCommands);
777*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(command != nullptr);
778*cfb92d14SAndroid Build Coastguard Worker 
779*cfb92d14SAndroid Build Coastguard Worker     error = (this->*command->mHandler)(aArgs + 1);
780*cfb92d14SAndroid Build Coastguard Worker 
781*cfb92d14SAndroid Build Coastguard Worker exit:
782*cfb92d14SAndroid Build Coastguard Worker     return error;
783*cfb92d14SAndroid Build Coastguard Worker }
784*cfb92d14SAndroid Build Coastguard Worker 
HandleTcpEstablishedCallback(otTcpEndpoint * aEndpoint)785*cfb92d14SAndroid Build Coastguard Worker void TcpExample::HandleTcpEstablishedCallback(otTcpEndpoint *aEndpoint)
786*cfb92d14SAndroid Build Coastguard Worker {
787*cfb92d14SAndroid Build Coastguard Worker     static_cast<TcpExample *>(otTcpEndpointGetContext(aEndpoint))->HandleTcpEstablished(aEndpoint);
788*cfb92d14SAndroid Build Coastguard Worker }
789*cfb92d14SAndroid Build Coastguard Worker 
HandleTcpSendDoneCallback(otTcpEndpoint * aEndpoint,otLinkedBuffer * aData)790*cfb92d14SAndroid Build Coastguard Worker void TcpExample::HandleTcpSendDoneCallback(otTcpEndpoint *aEndpoint, otLinkedBuffer *aData)
791*cfb92d14SAndroid Build Coastguard Worker {
792*cfb92d14SAndroid Build Coastguard Worker     static_cast<TcpExample *>(otTcpEndpointGetContext(aEndpoint))->HandleTcpSendDone(aEndpoint, aData);
793*cfb92d14SAndroid Build Coastguard Worker }
794*cfb92d14SAndroid Build Coastguard Worker 
HandleTcpForwardProgressCallback(otTcpEndpoint * aEndpoint,size_t aInSendBuffer,size_t aBacklog)795*cfb92d14SAndroid Build Coastguard Worker void TcpExample::HandleTcpForwardProgressCallback(otTcpEndpoint *aEndpoint, size_t aInSendBuffer, size_t aBacklog)
796*cfb92d14SAndroid Build Coastguard Worker {
797*cfb92d14SAndroid Build Coastguard Worker     static_cast<TcpExample *>(otTcpEndpointGetContext(aEndpoint))
798*cfb92d14SAndroid Build Coastguard Worker         ->HandleTcpForwardProgress(aEndpoint, aInSendBuffer, aBacklog);
799*cfb92d14SAndroid Build Coastguard Worker }
800*cfb92d14SAndroid Build Coastguard Worker 
HandleTcpReceiveAvailableCallback(otTcpEndpoint * aEndpoint,size_t aBytesAvailable,bool aEndOfStream,size_t aBytesRemaining)801*cfb92d14SAndroid Build Coastguard Worker void TcpExample::HandleTcpReceiveAvailableCallback(otTcpEndpoint *aEndpoint,
802*cfb92d14SAndroid Build Coastguard Worker                                                    size_t         aBytesAvailable,
803*cfb92d14SAndroid Build Coastguard Worker                                                    bool           aEndOfStream,
804*cfb92d14SAndroid Build Coastguard Worker                                                    size_t         aBytesRemaining)
805*cfb92d14SAndroid Build Coastguard Worker {
806*cfb92d14SAndroid Build Coastguard Worker     static_cast<TcpExample *>(otTcpEndpointGetContext(aEndpoint))
807*cfb92d14SAndroid Build Coastguard Worker         ->HandleTcpReceiveAvailable(aEndpoint, aBytesAvailable, aEndOfStream, aBytesRemaining);
808*cfb92d14SAndroid Build Coastguard Worker }
809*cfb92d14SAndroid Build Coastguard Worker 
HandleTcpDisconnectedCallback(otTcpEndpoint * aEndpoint,otTcpDisconnectedReason aReason)810*cfb92d14SAndroid Build Coastguard Worker void TcpExample::HandleTcpDisconnectedCallback(otTcpEndpoint *aEndpoint, otTcpDisconnectedReason aReason)
811*cfb92d14SAndroid Build Coastguard Worker {
812*cfb92d14SAndroid Build Coastguard Worker     static_cast<TcpExample *>(otTcpEndpointGetContext(aEndpoint))->HandleTcpDisconnected(aEndpoint, aReason);
813*cfb92d14SAndroid Build Coastguard Worker }
814*cfb92d14SAndroid Build Coastguard Worker 
HandleTcpAcceptReadyCallback(otTcpListener * aListener,const otSockAddr * aPeer,otTcpEndpoint ** aAcceptInto)815*cfb92d14SAndroid Build Coastguard Worker otTcpIncomingConnectionAction TcpExample::HandleTcpAcceptReadyCallback(otTcpListener    *aListener,
816*cfb92d14SAndroid Build Coastguard Worker                                                                        const otSockAddr *aPeer,
817*cfb92d14SAndroid Build Coastguard Worker                                                                        otTcpEndpoint   **aAcceptInto)
818*cfb92d14SAndroid Build Coastguard Worker {
819*cfb92d14SAndroid Build Coastguard Worker     return static_cast<TcpExample *>(otTcpListenerGetContext(aListener))
820*cfb92d14SAndroid Build Coastguard Worker         ->HandleTcpAcceptReady(aListener, aPeer, aAcceptInto);
821*cfb92d14SAndroid Build Coastguard Worker }
822*cfb92d14SAndroid Build Coastguard Worker 
HandleTcpAcceptDoneCallback(otTcpListener * aListener,otTcpEndpoint * aEndpoint,const otSockAddr * aPeer)823*cfb92d14SAndroid Build Coastguard Worker void TcpExample::HandleTcpAcceptDoneCallback(otTcpListener    *aListener,
824*cfb92d14SAndroid Build Coastguard Worker                                              otTcpEndpoint    *aEndpoint,
825*cfb92d14SAndroid Build Coastguard Worker                                              const otSockAddr *aPeer)
826*cfb92d14SAndroid Build Coastguard Worker {
827*cfb92d14SAndroid Build Coastguard Worker     static_cast<TcpExample *>(otTcpListenerGetContext(aListener))->HandleTcpAcceptDone(aListener, aEndpoint, aPeer);
828*cfb92d14SAndroid Build Coastguard Worker }
829*cfb92d14SAndroid Build Coastguard Worker 
HandleTcpEstablished(otTcpEndpoint * aEndpoint)830*cfb92d14SAndroid Build Coastguard Worker void TcpExample::HandleTcpEstablished(otTcpEndpoint *aEndpoint)
831*cfb92d14SAndroid Build Coastguard Worker {
832*cfb92d14SAndroid Build Coastguard Worker     OT_UNUSED_VARIABLE(aEndpoint);
833*cfb92d14SAndroid Build Coastguard Worker     OutputLine("TCP: Connection established");
834*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_TLS_ENABLE
835*cfb92d14SAndroid Build Coastguard Worker     if (mUseTls && !mEndpointConnectedFastOpen)
836*cfb92d14SAndroid Build Coastguard Worker     {
837*cfb92d14SAndroid Build Coastguard Worker         PrepareTlsHandshake();
838*cfb92d14SAndroid Build Coastguard Worker         ContinueTlsHandshake();
839*cfb92d14SAndroid Build Coastguard Worker     }
840*cfb92d14SAndroid Build Coastguard Worker #endif
841*cfb92d14SAndroid Build Coastguard Worker }
842*cfb92d14SAndroid Build Coastguard Worker 
HandleTcpSendDone(otTcpEndpoint * aEndpoint,otLinkedBuffer * aData)843*cfb92d14SAndroid Build Coastguard Worker void TcpExample::HandleTcpSendDone(otTcpEndpoint *aEndpoint, otLinkedBuffer *aData)
844*cfb92d14SAndroid Build Coastguard Worker {
845*cfb92d14SAndroid Build Coastguard Worker     OT_UNUSED_VARIABLE(aEndpoint);
846*cfb92d14SAndroid Build Coastguard Worker     OT_ASSERT(!mUseCircularSendBuffer); // this callback is not used when using the circular send buffer
847*cfb92d14SAndroid Build Coastguard Worker 
848*cfb92d14SAndroid Build Coastguard Worker     if (mBenchmarkBytesTotal == 0)
849*cfb92d14SAndroid Build Coastguard Worker     {
850*cfb92d14SAndroid Build Coastguard Worker         // If the benchmark encountered an error, we might end up here. So,
851*cfb92d14SAndroid Build Coastguard Worker         // tolerate some benchmark links finishing in this case.
852*cfb92d14SAndroid Build Coastguard Worker         if (aData == &mSendLink)
853*cfb92d14SAndroid Build Coastguard Worker         {
854*cfb92d14SAndroid Build Coastguard Worker             OT_ASSERT(mSendBusy);
855*cfb92d14SAndroid Build Coastguard Worker             mSendBusy = false;
856*cfb92d14SAndroid Build Coastguard Worker         }
857*cfb92d14SAndroid Build Coastguard Worker     }
858*cfb92d14SAndroid Build Coastguard Worker     else
859*cfb92d14SAndroid Build Coastguard Worker     {
860*cfb92d14SAndroid Build Coastguard Worker         OT_ASSERT(aData != &mSendLink);
861*cfb92d14SAndroid Build Coastguard Worker         OT_ASSERT(mBenchmarkBytesUnsent >= aData->mLength);
862*cfb92d14SAndroid Build Coastguard Worker 
863*cfb92d14SAndroid Build Coastguard Worker         mBenchmarkBytesUnsent -= aData->mLength; // could be less than sizeof(mSendBufferBytes) for the first link
864*cfb92d14SAndroid Build Coastguard Worker 
865*cfb92d14SAndroid Build Coastguard Worker         if (mBenchmarkBytesUnsent >= OT_ARRAY_LENGTH(mBenchmarkLinks) * sizeof(mSendBufferBytes))
866*cfb92d14SAndroid Build Coastguard Worker         {
867*cfb92d14SAndroid Build Coastguard Worker             aData->mLength = sizeof(mSendBufferBytes);
868*cfb92d14SAndroid Build Coastguard Worker 
869*cfb92d14SAndroid Build Coastguard Worker             if (otTcpSendByReference(&mEndpoint, aData, 0) != OT_ERROR_NONE)
870*cfb92d14SAndroid Build Coastguard Worker             {
871*cfb92d14SAndroid Build Coastguard Worker                 OutputLine("TCP Benchmark Failed");
872*cfb92d14SAndroid Build Coastguard Worker                 mBenchmarkBytesTotal = 0;
873*cfb92d14SAndroid Build Coastguard Worker             }
874*cfb92d14SAndroid Build Coastguard Worker         }
875*cfb92d14SAndroid Build Coastguard Worker         else if (mBenchmarkBytesUnsent == 0)
876*cfb92d14SAndroid Build Coastguard Worker         {
877*cfb92d14SAndroid Build Coastguard Worker             CompleteBenchmark();
878*cfb92d14SAndroid Build Coastguard Worker         }
879*cfb92d14SAndroid Build Coastguard Worker     }
880*cfb92d14SAndroid Build Coastguard Worker }
881*cfb92d14SAndroid Build Coastguard Worker 
HandleTcpForwardProgress(otTcpEndpoint * aEndpoint,size_t aInSendBuffer,size_t aBacklog)882*cfb92d14SAndroid Build Coastguard Worker void TcpExample::HandleTcpForwardProgress(otTcpEndpoint *aEndpoint, size_t aInSendBuffer, size_t aBacklog)
883*cfb92d14SAndroid Build Coastguard Worker {
884*cfb92d14SAndroid Build Coastguard Worker     OT_UNUSED_VARIABLE(aEndpoint);
885*cfb92d14SAndroid Build Coastguard Worker     OT_UNUSED_VARIABLE(aBacklog);
886*cfb92d14SAndroid Build Coastguard Worker     OT_ASSERT(mUseCircularSendBuffer); // this callback is only used when using the circular send buffer
887*cfb92d14SAndroid Build Coastguard Worker 
888*cfb92d14SAndroid Build Coastguard Worker     otTcpCircularSendBufferHandleForwardProgress(&mSendBuffer, aInSendBuffer);
889*cfb92d14SAndroid Build Coastguard Worker 
890*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_TLS_ENABLE
891*cfb92d14SAndroid Build Coastguard Worker     if (mUseTls)
892*cfb92d14SAndroid Build Coastguard Worker     {
893*cfb92d14SAndroid Build Coastguard Worker         ContinueTlsHandshake();
894*cfb92d14SAndroid Build Coastguard Worker     }
895*cfb92d14SAndroid Build Coastguard Worker #endif
896*cfb92d14SAndroid Build Coastguard Worker 
897*cfb92d14SAndroid Build Coastguard Worker     /* Handle case where we're in a benchmark. */
898*cfb92d14SAndroid Build Coastguard Worker     if (mBenchmarkBytesTotal != 0)
899*cfb92d14SAndroid Build Coastguard Worker     {
900*cfb92d14SAndroid Build Coastguard Worker         if (mBenchmarkBytesUnsent != 0)
901*cfb92d14SAndroid Build Coastguard Worker         {
902*cfb92d14SAndroid Build Coastguard Worker             /* Continue sending out data if there's data we haven't sent. */
903*cfb92d14SAndroid Build Coastguard Worker             IgnoreError(ContinueBenchmarkCircularSend());
904*cfb92d14SAndroid Build Coastguard Worker         }
905*cfb92d14SAndroid Build Coastguard Worker         else if (aInSendBuffer == 0)
906*cfb92d14SAndroid Build Coastguard Worker         {
907*cfb92d14SAndroid Build Coastguard Worker             /* Handle case where all data is sent out and the send buffer has drained. */
908*cfb92d14SAndroid Build Coastguard Worker             CompleteBenchmark();
909*cfb92d14SAndroid Build Coastguard Worker         }
910*cfb92d14SAndroid Build Coastguard Worker     }
911*cfb92d14SAndroid Build Coastguard Worker }
912*cfb92d14SAndroid Build Coastguard Worker 
HandleTcpReceiveAvailable(otTcpEndpoint * aEndpoint,size_t aBytesAvailable,bool aEndOfStream,size_t aBytesRemaining)913*cfb92d14SAndroid Build Coastguard Worker void TcpExample::HandleTcpReceiveAvailable(otTcpEndpoint *aEndpoint,
914*cfb92d14SAndroid Build Coastguard Worker                                            size_t         aBytesAvailable,
915*cfb92d14SAndroid Build Coastguard Worker                                            bool           aEndOfStream,
916*cfb92d14SAndroid Build Coastguard Worker                                            size_t         aBytesRemaining)
917*cfb92d14SAndroid Build Coastguard Worker {
918*cfb92d14SAndroid Build Coastguard Worker     OT_UNUSED_VARIABLE(aBytesRemaining);
919*cfb92d14SAndroid Build Coastguard Worker     OT_ASSERT(aEndpoint == &mEndpoint);
920*cfb92d14SAndroid Build Coastguard Worker 
921*cfb92d14SAndroid Build Coastguard Worker     /* If we get data before the handshake completes, then this is a TFO connection. */
922*cfb92d14SAndroid Build Coastguard Worker     if (!mEndpointConnected)
923*cfb92d14SAndroid Build Coastguard Worker     {
924*cfb92d14SAndroid Build Coastguard Worker         mEndpointConnected         = true;
925*cfb92d14SAndroid Build Coastguard Worker         mEndpointConnectedFastOpen = true;
926*cfb92d14SAndroid Build Coastguard Worker 
927*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_TLS_ENABLE
928*cfb92d14SAndroid Build Coastguard Worker         if (mUseTls)
929*cfb92d14SAndroid Build Coastguard Worker         {
930*cfb92d14SAndroid Build Coastguard Worker             PrepareTlsHandshake();
931*cfb92d14SAndroid Build Coastguard Worker         }
932*cfb92d14SAndroid Build Coastguard Worker #endif
933*cfb92d14SAndroid Build Coastguard Worker     }
934*cfb92d14SAndroid Build Coastguard Worker 
935*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_TLS_ENABLE
936*cfb92d14SAndroid Build Coastguard Worker     if (mUseTls && ContinueTlsHandshake())
937*cfb92d14SAndroid Build Coastguard Worker     {
938*cfb92d14SAndroid Build Coastguard Worker         ExitNow();
939*cfb92d14SAndroid Build Coastguard Worker     }
940*cfb92d14SAndroid Build Coastguard Worker #endif
941*cfb92d14SAndroid Build Coastguard Worker 
942*cfb92d14SAndroid Build Coastguard Worker     if ((mTlsHandshakeComplete || !mUseTls) && aBytesAvailable > 0)
943*cfb92d14SAndroid Build Coastguard Worker     {
944*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_TLS_ENABLE
945*cfb92d14SAndroid Build Coastguard Worker         if (mUseTls)
946*cfb92d14SAndroid Build Coastguard Worker         {
947*cfb92d14SAndroid Build Coastguard Worker             uint8_t buffer[500];
948*cfb92d14SAndroid Build Coastguard Worker 
949*cfb92d14SAndroid Build Coastguard Worker             for (;;)
950*cfb92d14SAndroid Build Coastguard Worker             {
951*cfb92d14SAndroid Build Coastguard Worker                 int rv = mbedtls_ssl_read(&mSslContext, buffer, sizeof(buffer));
952*cfb92d14SAndroid Build Coastguard Worker 
953*cfb92d14SAndroid Build Coastguard Worker                 if (rv < 0)
954*cfb92d14SAndroid Build Coastguard Worker                 {
955*cfb92d14SAndroid Build Coastguard Worker                     if (rv == MBEDTLS_ERR_SSL_WANT_READ)
956*cfb92d14SAndroid Build Coastguard Worker                     {
957*cfb92d14SAndroid Build Coastguard Worker                         break;
958*cfb92d14SAndroid Build Coastguard Worker                     }
959*cfb92d14SAndroid Build Coastguard Worker 
960*cfb92d14SAndroid Build Coastguard Worker                     OutputLine("TLS receive failure: %d", rv);
961*cfb92d14SAndroid Build Coastguard Worker                 }
962*cfb92d14SAndroid Build Coastguard Worker                 else
963*cfb92d14SAndroid Build Coastguard Worker                 {
964*cfb92d14SAndroid Build Coastguard Worker                     OutputLine("TLS: Received %u bytes: %.*s", static_cast<unsigned>(rv), rv,
965*cfb92d14SAndroid Build Coastguard Worker                                reinterpret_cast<const char *>(buffer));
966*cfb92d14SAndroid Build Coastguard Worker                 }
967*cfb92d14SAndroid Build Coastguard Worker             }
968*cfb92d14SAndroid Build Coastguard Worker             OutputLine("(TCP: Received %u bytes)", static_cast<unsigned>(aBytesAvailable));
969*cfb92d14SAndroid Build Coastguard Worker         }
970*cfb92d14SAndroid Build Coastguard Worker         else
971*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_CONFIG_TLS_ENABLE
972*cfb92d14SAndroid Build Coastguard Worker         {
973*cfb92d14SAndroid Build Coastguard Worker             const otLinkedBuffer *data;
974*cfb92d14SAndroid Build Coastguard Worker             size_t                totalReceived = 0;
975*cfb92d14SAndroid Build Coastguard Worker 
976*cfb92d14SAndroid Build Coastguard Worker             IgnoreError(otTcpReceiveByReference(aEndpoint, &data));
977*cfb92d14SAndroid Build Coastguard Worker 
978*cfb92d14SAndroid Build Coastguard Worker             for (; data != nullptr; data = data->mNext)
979*cfb92d14SAndroid Build Coastguard Worker             {
980*cfb92d14SAndroid Build Coastguard Worker                 OutputLine("TCP: Received %u bytes: %.*s", static_cast<unsigned>(data->mLength),
981*cfb92d14SAndroid Build Coastguard Worker                            static_cast<unsigned>(data->mLength), reinterpret_cast<const char *>(data->mData));
982*cfb92d14SAndroid Build Coastguard Worker                 totalReceived += data->mLength;
983*cfb92d14SAndroid Build Coastguard Worker             }
984*cfb92d14SAndroid Build Coastguard Worker 
985*cfb92d14SAndroid Build Coastguard Worker             OT_ASSERT(aBytesAvailable == totalReceived);
986*cfb92d14SAndroid Build Coastguard Worker             IgnoreReturnValue(otTcpCommitReceive(aEndpoint, totalReceived, 0));
987*cfb92d14SAndroid Build Coastguard Worker         }
988*cfb92d14SAndroid Build Coastguard Worker     }
989*cfb92d14SAndroid Build Coastguard Worker 
990*cfb92d14SAndroid Build Coastguard Worker     if (aEndOfStream)
991*cfb92d14SAndroid Build Coastguard Worker     {
992*cfb92d14SAndroid Build Coastguard Worker         OutputLine("TCP: Reached end of stream");
993*cfb92d14SAndroid Build Coastguard Worker     }
994*cfb92d14SAndroid Build Coastguard Worker 
995*cfb92d14SAndroid Build Coastguard Worker     ExitNow();
996*cfb92d14SAndroid Build Coastguard Worker 
997*cfb92d14SAndroid Build Coastguard Worker exit:
998*cfb92d14SAndroid Build Coastguard Worker     return;
999*cfb92d14SAndroid Build Coastguard Worker }
1000*cfb92d14SAndroid Build Coastguard Worker 
HandleTcpDisconnected(otTcpEndpoint * aEndpoint,otTcpDisconnectedReason aReason)1001*cfb92d14SAndroid Build Coastguard Worker void TcpExample::HandleTcpDisconnected(otTcpEndpoint *aEndpoint, otTcpDisconnectedReason aReason)
1002*cfb92d14SAndroid Build Coastguard Worker {
1003*cfb92d14SAndroid Build Coastguard Worker     static const char *const kReasonStrings[] = {
1004*cfb92d14SAndroid Build Coastguard Worker         "Disconnected",            // (0) OT_TCP_DISCONNECTED_REASON_NORMAL
1005*cfb92d14SAndroid Build Coastguard Worker         "Connection refused",      // (1) OT_TCP_DISCONNECTED_REASON_REFUSED
1006*cfb92d14SAndroid Build Coastguard Worker         "Connection reset",        // (2) OT_TCP_DISCONNECTED_REASON_RESET
1007*cfb92d14SAndroid Build Coastguard Worker         "Entered TIME-WAIT state", // (3) OT_TCP_DISCONNECTED_REASON_TIME_WAIT
1008*cfb92d14SAndroid Build Coastguard Worker         "Connection timed out",    // (4) OT_TCP_DISCONNECTED_REASON_TIMED_OUT
1009*cfb92d14SAndroid Build Coastguard Worker     };
1010*cfb92d14SAndroid Build Coastguard Worker 
1011*cfb92d14SAndroid Build Coastguard Worker     OT_UNUSED_VARIABLE(aEndpoint);
1012*cfb92d14SAndroid Build Coastguard Worker 
1013*cfb92d14SAndroid Build Coastguard Worker     static_assert(0 == OT_TCP_DISCONNECTED_REASON_NORMAL, "OT_TCP_DISCONNECTED_REASON_NORMAL value is incorrect");
1014*cfb92d14SAndroid Build Coastguard Worker     static_assert(1 == OT_TCP_DISCONNECTED_REASON_REFUSED, "OT_TCP_DISCONNECTED_REASON_REFUSED value is incorrect");
1015*cfb92d14SAndroid Build Coastguard Worker     static_assert(2 == OT_TCP_DISCONNECTED_REASON_RESET, "OT_TCP_DISCONNECTED_REASON_RESET value is incorrect");
1016*cfb92d14SAndroid Build Coastguard Worker     static_assert(3 == OT_TCP_DISCONNECTED_REASON_TIME_WAIT, "OT_TCP_DISCONNECTED_REASON_TIME_WAIT value is incorrect");
1017*cfb92d14SAndroid Build Coastguard Worker     static_assert(4 == OT_TCP_DISCONNECTED_REASON_TIMED_OUT, "OT_TCP_DISCONNECTED_REASON_TIMED_OUT value is incorrect");
1018*cfb92d14SAndroid Build Coastguard Worker 
1019*cfb92d14SAndroid Build Coastguard Worker     OutputLine("TCP: %s", Stringify(aReason, kReasonStrings));
1020*cfb92d14SAndroid Build Coastguard Worker 
1021*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_TLS_ENABLE
1022*cfb92d14SAndroid Build Coastguard Worker     if (mUseTls)
1023*cfb92d14SAndroid Build Coastguard Worker     {
1024*cfb92d14SAndroid Build Coastguard Worker         mbedtls_ssl_session_reset(&mSslContext);
1025*cfb92d14SAndroid Build Coastguard Worker     }
1026*cfb92d14SAndroid Build Coastguard Worker #endif
1027*cfb92d14SAndroid Build Coastguard Worker 
1028*cfb92d14SAndroid Build Coastguard Worker     // We set this to false even for the TIME-WAIT state, so that we can reuse
1029*cfb92d14SAndroid Build Coastguard Worker     // the active socket if an incoming connection comes in instead of waiting
1030*cfb92d14SAndroid Build Coastguard Worker     // for the 2MSL timeout.
1031*cfb92d14SAndroid Build Coastguard Worker     mEndpointConnected         = false;
1032*cfb92d14SAndroid Build Coastguard Worker     mEndpointConnectedFastOpen = false;
1033*cfb92d14SAndroid Build Coastguard Worker     mSendBusy                  = false;
1034*cfb92d14SAndroid Build Coastguard Worker 
1035*cfb92d14SAndroid Build Coastguard Worker     // Mark the benchmark as inactive if the connection was disconnected.
1036*cfb92d14SAndroid Build Coastguard Worker     mBenchmarkBytesTotal  = 0;
1037*cfb92d14SAndroid Build Coastguard Worker     mBenchmarkBytesUnsent = 0;
1038*cfb92d14SAndroid Build Coastguard Worker 
1039*cfb92d14SAndroid Build Coastguard Worker     otTcpCircularSendBufferForceDiscardAll(&mSendBuffer);
1040*cfb92d14SAndroid Build Coastguard Worker }
1041*cfb92d14SAndroid Build Coastguard Worker 
HandleTcpAcceptReady(otTcpListener * aListener,const otSockAddr * aPeer,otTcpEndpoint ** aAcceptInto)1042*cfb92d14SAndroid Build Coastguard Worker otTcpIncomingConnectionAction TcpExample::HandleTcpAcceptReady(otTcpListener    *aListener,
1043*cfb92d14SAndroid Build Coastguard Worker                                                                const otSockAddr *aPeer,
1044*cfb92d14SAndroid Build Coastguard Worker                                                                otTcpEndpoint   **aAcceptInto)
1045*cfb92d14SAndroid Build Coastguard Worker {
1046*cfb92d14SAndroid Build Coastguard Worker     otTcpIncomingConnectionAction action;
1047*cfb92d14SAndroid Build Coastguard Worker 
1048*cfb92d14SAndroid Build Coastguard Worker     OT_UNUSED_VARIABLE(aListener);
1049*cfb92d14SAndroid Build Coastguard Worker 
1050*cfb92d14SAndroid Build Coastguard Worker     if (mEndpointConnected)
1051*cfb92d14SAndroid Build Coastguard Worker     {
1052*cfb92d14SAndroid Build Coastguard Worker         OutputFormat("TCP: Ignoring incoming connection request from ");
1053*cfb92d14SAndroid Build Coastguard Worker         OutputSockAddr(*aPeer);
1054*cfb92d14SAndroid Build Coastguard Worker         OutputLine(" (active socket is busy)");
1055*cfb92d14SAndroid Build Coastguard Worker 
1056*cfb92d14SAndroid Build Coastguard Worker         ExitNow(action = OT_TCP_INCOMING_CONNECTION_ACTION_DEFER);
1057*cfb92d14SAndroid Build Coastguard Worker     }
1058*cfb92d14SAndroid Build Coastguard Worker 
1059*cfb92d14SAndroid Build Coastguard Worker     *aAcceptInto = &mEndpoint;
1060*cfb92d14SAndroid Build Coastguard Worker     action       = OT_TCP_INCOMING_CONNECTION_ACTION_ACCEPT;
1061*cfb92d14SAndroid Build Coastguard Worker 
1062*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_TLS_ENABLE
1063*cfb92d14SAndroid Build Coastguard Worker     /*
1064*cfb92d14SAndroid Build Coastguard Worker      * Natural to wait until the AcceptDone callback but with TFO we could get data before that
1065*cfb92d14SAndroid Build Coastguard Worker      * so it doesn't make sense to wait until then.
1066*cfb92d14SAndroid Build Coastguard Worker      */
1067*cfb92d14SAndroid Build Coastguard Worker     if (mUseTls)
1068*cfb92d14SAndroid Build Coastguard Worker     {
1069*cfb92d14SAndroid Build Coastguard Worker         int rv;
1070*cfb92d14SAndroid Build Coastguard Worker 
1071*cfb92d14SAndroid Build Coastguard Worker         rv = mbedtls_ssl_config_defaults(&mSslConfig, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM,
1072*cfb92d14SAndroid Build Coastguard Worker                                          MBEDTLS_SSL_PRESET_DEFAULT);
1073*cfb92d14SAndroid Build Coastguard Worker         if (rv != 0)
1074*cfb92d14SAndroid Build Coastguard Worker         {
1075*cfb92d14SAndroid Build Coastguard Worker             OutputLine("mbedtls_ssl_config_defaults returned %d", rv);
1076*cfb92d14SAndroid Build Coastguard Worker         }
1077*cfb92d14SAndroid Build Coastguard Worker 
1078*cfb92d14SAndroid Build Coastguard Worker         mbedtls_ssl_conf_ca_chain(&mSslConfig, mSrvCert.next, nullptr);
1079*cfb92d14SAndroid Build Coastguard Worker         rv = mbedtls_ssl_conf_own_cert(&mSslConfig, &mSrvCert, &mPKey);
1080*cfb92d14SAndroid Build Coastguard Worker 
1081*cfb92d14SAndroid Build Coastguard Worker         if (rv != 0)
1082*cfb92d14SAndroid Build Coastguard Worker         {
1083*cfb92d14SAndroid Build Coastguard Worker             OutputLine("mbedtls_ssl_conf_own_cert returned %d", rv);
1084*cfb92d14SAndroid Build Coastguard Worker         }
1085*cfb92d14SAndroid Build Coastguard Worker     }
1086*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_CONFIG_TLS_ENABLE
1087*cfb92d14SAndroid Build Coastguard Worker 
1088*cfb92d14SAndroid Build Coastguard Worker exit:
1089*cfb92d14SAndroid Build Coastguard Worker     return action;
1090*cfb92d14SAndroid Build Coastguard Worker }
1091*cfb92d14SAndroid Build Coastguard Worker 
HandleTcpAcceptDone(otTcpListener * aListener,otTcpEndpoint * aEndpoint,const otSockAddr * aPeer)1092*cfb92d14SAndroid Build Coastguard Worker void TcpExample::HandleTcpAcceptDone(otTcpListener *aListener, otTcpEndpoint *aEndpoint, const otSockAddr *aPeer)
1093*cfb92d14SAndroid Build Coastguard Worker {
1094*cfb92d14SAndroid Build Coastguard Worker     OT_UNUSED_VARIABLE(aListener);
1095*cfb92d14SAndroid Build Coastguard Worker     OT_UNUSED_VARIABLE(aEndpoint);
1096*cfb92d14SAndroid Build Coastguard Worker 
1097*cfb92d14SAndroid Build Coastguard Worker     mEndpointConnected = true;
1098*cfb92d14SAndroid Build Coastguard Worker     OutputFormat("Accepted connection from ");
1099*cfb92d14SAndroid Build Coastguard Worker     OutputSockAddrLine(*aPeer);
1100*cfb92d14SAndroid Build Coastguard Worker }
1101*cfb92d14SAndroid Build Coastguard Worker 
ContinueBenchmarkCircularSend(void)1102*cfb92d14SAndroid Build Coastguard Worker otError TcpExample::ContinueBenchmarkCircularSend(void)
1103*cfb92d14SAndroid Build Coastguard Worker {
1104*cfb92d14SAndroid Build Coastguard Worker     otError error = OT_ERROR_NONE;
1105*cfb92d14SAndroid Build Coastguard Worker     size_t  freeSpace;
1106*cfb92d14SAndroid Build Coastguard Worker 
1107*cfb92d14SAndroid Build Coastguard Worker     while (mBenchmarkBytesUnsent != 0 && (freeSpace = otTcpCircularSendBufferGetFreeSpace(&mSendBuffer)) != 0)
1108*cfb92d14SAndroid Build Coastguard Worker     {
1109*cfb92d14SAndroid Build Coastguard Worker         size_t   toSendThisIteration = OT_MIN(mBenchmarkBytesUnsent, sBenchmarkDataLength);
1110*cfb92d14SAndroid Build Coastguard Worker         uint32_t flag                = (toSendThisIteration < freeSpace && toSendThisIteration < mBenchmarkBytesUnsent)
1111*cfb92d14SAndroid Build Coastguard Worker                                            ? OT_TCP_CIRCULAR_SEND_BUFFER_WRITE_MORE_TO_COME
1112*cfb92d14SAndroid Build Coastguard Worker                                            : 0;
1113*cfb92d14SAndroid Build Coastguard Worker         size_t   written             = 0;
1114*cfb92d14SAndroid Build Coastguard Worker 
1115*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_TLS_ENABLE
1116*cfb92d14SAndroid Build Coastguard Worker         if (mUseTls)
1117*cfb92d14SAndroid Build Coastguard Worker         {
1118*cfb92d14SAndroid Build Coastguard Worker             int rv = mbedtls_ssl_write(&mSslContext, reinterpret_cast<const unsigned char *>(sBenchmarkData),
1119*cfb92d14SAndroid Build Coastguard Worker                                        toSendThisIteration);
1120*cfb92d14SAndroid Build Coastguard Worker 
1121*cfb92d14SAndroid Build Coastguard Worker             if (rv > 0)
1122*cfb92d14SAndroid Build Coastguard Worker             {
1123*cfb92d14SAndroid Build Coastguard Worker                 written = static_cast<size_t>(rv);
1124*cfb92d14SAndroid Build Coastguard Worker                 OT_ASSERT(written <= mBenchmarkBytesUnsent);
1125*cfb92d14SAndroid Build Coastguard Worker             }
1126*cfb92d14SAndroid Build Coastguard Worker             else if (rv != MBEDTLS_ERR_SSL_WANT_WRITE && rv != MBEDTLS_ERR_SSL_WANT_READ)
1127*cfb92d14SAndroid Build Coastguard Worker             {
1128*cfb92d14SAndroid Build Coastguard Worker                 ExitNow(error = OT_ERROR_FAILED);
1129*cfb92d14SAndroid Build Coastguard Worker             }
1130*cfb92d14SAndroid Build Coastguard Worker 
1131*cfb92d14SAndroid Build Coastguard Worker             error = OT_ERROR_NONE;
1132*cfb92d14SAndroid Build Coastguard Worker         }
1133*cfb92d14SAndroid Build Coastguard Worker         else
1134*cfb92d14SAndroid Build Coastguard Worker #endif
1135*cfb92d14SAndroid Build Coastguard Worker         {
1136*cfb92d14SAndroid Build Coastguard Worker             SuccessOrExit(error = otTcpCircularSendBufferWrite(&mEndpoint, &mSendBuffer, sBenchmarkData,
1137*cfb92d14SAndroid Build Coastguard Worker                                                                toSendThisIteration, &written, flag));
1138*cfb92d14SAndroid Build Coastguard Worker         }
1139*cfb92d14SAndroid Build Coastguard Worker         mBenchmarkBytesUnsent -= written;
1140*cfb92d14SAndroid Build Coastguard Worker     }
1141*cfb92d14SAndroid Build Coastguard Worker 
1142*cfb92d14SAndroid Build Coastguard Worker exit:
1143*cfb92d14SAndroid Build Coastguard Worker     if (error != OT_ERROR_NONE)
1144*cfb92d14SAndroid Build Coastguard Worker     {
1145*cfb92d14SAndroid Build Coastguard Worker         OutputLine("TCP Benchmark Failed");
1146*cfb92d14SAndroid Build Coastguard Worker         mBenchmarkBytesTotal  = 0;
1147*cfb92d14SAndroid Build Coastguard Worker         mBenchmarkBytesUnsent = 0;
1148*cfb92d14SAndroid Build Coastguard Worker     }
1149*cfb92d14SAndroid Build Coastguard Worker 
1150*cfb92d14SAndroid Build Coastguard Worker     return error;
1151*cfb92d14SAndroid Build Coastguard Worker }
1152*cfb92d14SAndroid Build Coastguard Worker 
OutputBenchmarkResult(void)1153*cfb92d14SAndroid Build Coastguard Worker void TcpExample::OutputBenchmarkResult(void)
1154*cfb92d14SAndroid Build Coastguard Worker {
1155*cfb92d14SAndroid Build Coastguard Worker     uint32_t thousandTimesGoodput =
1156*cfb92d14SAndroid Build Coastguard Worker         (1000 * (mBenchmarkLastBytesTotal << 3) + (mBenchmarkTimeUsed >> 1)) / mBenchmarkTimeUsed;
1157*cfb92d14SAndroid Build Coastguard Worker 
1158*cfb92d14SAndroid Build Coastguard Worker     OutputLine("TCP Benchmark Complete: Transferred %lu bytes in %lu milliseconds", ToUlong(mBenchmarkLastBytesTotal),
1159*cfb92d14SAndroid Build Coastguard Worker                ToUlong(mBenchmarkTimeUsed));
1160*cfb92d14SAndroid Build Coastguard Worker     OutputLine("TCP Goodput: %lu.%03u kb/s", ToUlong(thousandTimesGoodput / 1000),
1161*cfb92d14SAndroid Build Coastguard Worker                static_cast<uint16_t>(thousandTimesGoodput % 1000));
1162*cfb92d14SAndroid Build Coastguard Worker }
1163*cfb92d14SAndroid Build Coastguard Worker 
CompleteBenchmark(void)1164*cfb92d14SAndroid Build Coastguard Worker void TcpExample::CompleteBenchmark(void)
1165*cfb92d14SAndroid Build Coastguard Worker {
1166*cfb92d14SAndroid Build Coastguard Worker     mBenchmarkTimeUsed       = TimerMilli::GetNow() - mBenchmarkStart;
1167*cfb92d14SAndroid Build Coastguard Worker     mBenchmarkLastBytesTotal = mBenchmarkBytesTotal;
1168*cfb92d14SAndroid Build Coastguard Worker 
1169*cfb92d14SAndroid Build Coastguard Worker     OutputBenchmarkResult();
1170*cfb92d14SAndroid Build Coastguard Worker 
1171*cfb92d14SAndroid Build Coastguard Worker     mBenchmarkBytesTotal = 0;
1172*cfb92d14SAndroid Build Coastguard Worker }
1173*cfb92d14SAndroid Build Coastguard Worker 
1174*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_TLS_ENABLE
PrepareTlsHandshake(void)1175*cfb92d14SAndroid Build Coastguard Worker void TcpExample::PrepareTlsHandshake(void)
1176*cfb92d14SAndroid Build Coastguard Worker {
1177*cfb92d14SAndroid Build Coastguard Worker     int rv;
1178*cfb92d14SAndroid Build Coastguard Worker 
1179*cfb92d14SAndroid Build Coastguard Worker     rv = mbedtls_ssl_set_hostname(&mSslContext, "localhost");
1180*cfb92d14SAndroid Build Coastguard Worker 
1181*cfb92d14SAndroid Build Coastguard Worker     if (rv != 0)
1182*cfb92d14SAndroid Build Coastguard Worker     {
1183*cfb92d14SAndroid Build Coastguard Worker         OutputLine("mbedtls_ssl_set_hostname returned %d", rv);
1184*cfb92d14SAndroid Build Coastguard Worker     }
1185*cfb92d14SAndroid Build Coastguard Worker 
1186*cfb92d14SAndroid Build Coastguard Worker     rv = mbedtls_ssl_set_hs_ecjpake_password(&mSslContext, reinterpret_cast<const unsigned char *>(sEcjpakePassword),
1187*cfb92d14SAndroid Build Coastguard Worker                                              sEcjpakePasswordLength);
1188*cfb92d14SAndroid Build Coastguard Worker     if (rv != 0)
1189*cfb92d14SAndroid Build Coastguard Worker     {
1190*cfb92d14SAndroid Build Coastguard Worker         OutputLine("mbedtls_ssl_set_hs_ecjpake_password returned %d", rv);
1191*cfb92d14SAndroid Build Coastguard Worker     }
1192*cfb92d14SAndroid Build Coastguard Worker 
1193*cfb92d14SAndroid Build Coastguard Worker     mbedtls_ssl_set_bio(&mSslContext, &mEndpointAndCircularSendBuffer, otTcpMbedTlsSslSendCallback,
1194*cfb92d14SAndroid Build Coastguard Worker                         otTcpMbedTlsSslRecvCallback, nullptr);
1195*cfb92d14SAndroid Build Coastguard Worker     mTlsHandshakeComplete = false;
1196*cfb92d14SAndroid Build Coastguard Worker }
1197*cfb92d14SAndroid Build Coastguard Worker 
ContinueTlsHandshake(void)1198*cfb92d14SAndroid Build Coastguard Worker bool TcpExample::ContinueTlsHandshake(void)
1199*cfb92d14SAndroid Build Coastguard Worker {
1200*cfb92d14SAndroid Build Coastguard Worker     bool wasNotAlreadyDone = false;
1201*cfb92d14SAndroid Build Coastguard Worker     int  rv;
1202*cfb92d14SAndroid Build Coastguard Worker 
1203*cfb92d14SAndroid Build Coastguard Worker     if (!mTlsHandshakeComplete)
1204*cfb92d14SAndroid Build Coastguard Worker     {
1205*cfb92d14SAndroid Build Coastguard Worker         rv = mbedtls_ssl_handshake(&mSslContext);
1206*cfb92d14SAndroid Build Coastguard Worker 
1207*cfb92d14SAndroid Build Coastguard Worker         if (rv == 0)
1208*cfb92d14SAndroid Build Coastguard Worker         {
1209*cfb92d14SAndroid Build Coastguard Worker             OutputLine("TLS Handshake Complete");
1210*cfb92d14SAndroid Build Coastguard Worker             mTlsHandshakeComplete = true;
1211*cfb92d14SAndroid Build Coastguard Worker         }
1212*cfb92d14SAndroid Build Coastguard Worker         else if (rv != MBEDTLS_ERR_SSL_WANT_READ && rv != MBEDTLS_ERR_SSL_WANT_WRITE)
1213*cfb92d14SAndroid Build Coastguard Worker         {
1214*cfb92d14SAndroid Build Coastguard Worker             OutputLine("TLS Handshake Failed: %d", rv);
1215*cfb92d14SAndroid Build Coastguard Worker         }
1216*cfb92d14SAndroid Build Coastguard Worker 
1217*cfb92d14SAndroid Build Coastguard Worker         wasNotAlreadyDone = true;
1218*cfb92d14SAndroid Build Coastguard Worker     }
1219*cfb92d14SAndroid Build Coastguard Worker 
1220*cfb92d14SAndroid Build Coastguard Worker     return wasNotAlreadyDone;
1221*cfb92d14SAndroid Build Coastguard Worker }
1222*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_CONFIG_TLS_ENABLE
1223*cfb92d14SAndroid Build Coastguard Worker 
1224*cfb92d14SAndroid Build Coastguard Worker } // namespace Cli
1225*cfb92d14SAndroid Build Coastguard Worker } // namespace ot
1226*cfb92d14SAndroid Build Coastguard Worker 
1227*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_CONFIG_TCP_ENABLE && OPENTHREAD_CONFIG_CLI_TCP_ENABLE
1228