1 /*
2 * Copyright (c) 2021, The OpenThread Authors.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. Neither the name of the copyright holder nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <openthread/config.h>
30
31 #include "test_platform.h"
32 #include "test_util.hpp"
33
34 #include "common/arg_macros.hpp"
35 #include "common/array.hpp"
36 #include "common/as_core_type.hpp"
37 #include "common/time.hpp"
38 #include "instance/instance.hpp"
39 #include "net/dns_dso.hpp"
40
41 namespace ot {
42
43 #if OPENTHREAD_CONFIG_DNS_DSO_ENABLE
44
45 extern "C" {
46
47 static uint32_t sNow = 0;
48 static uint32_t sAlarmTime;
49 static bool sAlarmOn = false;
50 static otInstance *sInstance;
51
52 // Logs a message and adds current time (sNow) as "<hours>:<min>:<secs>.<msec>"
53 #define Log(...) \
54 printf("%02u:%02u:%02u.%03u " OT_FIRST_ARG(__VA_ARGS__) "\n", (sNow / 36000000), (sNow / 60000) % 60, \
55 (sNow / 1000) % 60, sNow % 1000 OT_REST_ARGS(__VA_ARGS__))
56
otPlatAlarmMilliStop(otInstance *)57 void otPlatAlarmMilliStop(otInstance *) { sAlarmOn = false; }
58
otPlatAlarmMilliStartAt(otInstance *,uint32_t aT0,uint32_t aDt)59 void otPlatAlarmMilliStartAt(otInstance *, uint32_t aT0, uint32_t aDt)
60 {
61 sAlarmOn = true;
62 sAlarmTime = aT0 + aDt;
63
64 Log(" otPlatAlarmMilliStartAt(time:%u.%03u, dt:%u.%03u)", sAlarmTime / 1000, sAlarmTime % 1000,
65 (sAlarmTime - sNow) / 1000, (sAlarmTime - sNow) % 1000);
66 }
67
otPlatAlarmMilliGetNow(void)68 uint32_t otPlatAlarmMilliGetNow(void) { return sNow; }
69
70 } // extern "C"
71
AdvanceTime(uint32_t aDuration)72 void AdvanceTime(uint32_t aDuration)
73 {
74 uint32_t time = sNow + aDuration;
75
76 Log(" AdvanceTime for %u.%03u", aDuration / 1000, aDuration % 1000);
77
78 while (TimeMilli(sAlarmTime) <= TimeMilli(time))
79 {
80 sNow = sAlarmTime;
81 otPlatAlarmMilliFired(sInstance);
82 }
83
84 sNow = time;
85 }
86
87 namespace Dns {
88
89 OT_TOOL_PACKED_BEGIN
90 class TestTlv : public Dso::Tlv
91 {
92 public:
93 static constexpr Type kType = 0xf800;
94
Init(uint8_t aValue)95 void Init(uint8_t aValue)
96 {
97 Tlv::Init(kType, sizeof(*this) - sizeof(Tlv));
98 mValue = aValue;
99 }
100
IsValid(void) const101 bool IsValid(void) const { return GetSize() >= sizeof(*this); }
GetValue(void) const102 uint8_t GetValue(void) const { return mValue; }
103
104 private:
105 uint8_t mValue;
106
107 } OT_TOOL_PACKED_END;
108
109 extern "C" void otPlatDsoSend(otPlatDsoConnection *aConnection, otMessage *aMessage);
110
111 class Connection : public Dso::Connection
112 {
113 friend void otPlatDsoSend(otPlatDsoConnection *aConnection, otMessage *aMessage);
114
115 public:
Connection(Instance & aInstance,const char * aName,const Ip6::SockAddr & aLocalSockAddr,const Ip6::SockAddr & aPeerSockAddr)116 explicit Connection(Instance &aInstance,
117 const char *aName,
118 const Ip6::SockAddr &aLocalSockAddr,
119 const Ip6::SockAddr &aPeerSockAddr)
120 : Dso::Connection(aInstance, aPeerSockAddr, sCallbacks)
121 , mName(aName)
122 , mLocalSockAddr(aLocalSockAddr)
123 {
124 ClearTestFlags();
125 }
126
GetName(void) const127 const char *GetName(void) const { return mName; }
GetLocalSockAddr(void) const128 const Ip6::SockAddr &GetLocalSockAddr(void) const { return mLocalSockAddr; }
129
ClearTestFlags(void)130 void ClearTestFlags(void)
131 {
132 mDidGetConnectedSignal = false;
133 mDidGetSessionEstablishedSignal = false;
134 mDidGetDisconnectSignal = false;
135 mDidSendMessage = false;
136 mDidReceiveMessage = false;
137 mDidProcessRequest = false;
138 mDidProcessUnidirectional = false;
139 mDidProcessResponse = false;
140 }
141
DidGetConnectedSignal(void) const142 bool DidGetConnectedSignal(void) const { return mDidGetConnectedSignal; }
DidGetSessionEstablishedSignal(void) const143 bool DidGetSessionEstablishedSignal(void) const { return mDidGetSessionEstablishedSignal; }
DidGetDisconnectSignal(void) const144 bool DidGetDisconnectSignal(void) const { return mDidGetDisconnectSignal; }
DidSendMessage(void) const145 bool DidSendMessage(void) const { return mDidSendMessage; }
DidReceiveMessage(void) const146 bool DidReceiveMessage(void) const { return mDidReceiveMessage; }
DidProcessRequest(void) const147 bool DidProcessRequest(void) const { return mDidProcessRequest; }
DidProcessUnidirectional(void) const148 bool DidProcessUnidirectional(void) const { return mDidProcessUnidirectional; }
DidProcessResponse(void) const149 bool DidProcessResponse(void) const { return mDidProcessResponse; }
150
GetLastRxTestTlvValue(void) const151 uint8_t GetLastRxTestTlvValue(void) const { return mLastRxTestTlvValue; }
GetLastRxResponseCode(void) const152 Dns::Header::Response GetLastRxResponseCode(void) const { return mLastRxResponseCode; }
153
SendTestRequestMessage(uint8_t aValue=0,uint32_t aResponseTimeout=Dso::kResponseTimeout)154 void SendTestRequestMessage(uint8_t aValue = 0, uint32_t aResponseTimeout = Dso::kResponseTimeout)
155 {
156 MessageId messageId;
157
158 mLastTxTestTlvValue = aValue;
159 SuccessOrQuit(SendRequestMessage(PrepareTestMessage(aValue), messageId, aResponseTimeout));
160 }
161
SendTestUnidirectionalMessage(uint8_t aValue=0)162 void SendTestUnidirectionalMessage(uint8_t aValue = 0)
163 {
164 mLastTxTestTlvValue = aValue;
165 SuccessOrQuit(SendUnidirectionalMessage(PrepareTestMessage(aValue)));
166 }
167
168 private:
PrepareTestMessage(uint8_t aValue)169 Message &PrepareTestMessage(uint8_t aValue)
170 {
171 TestTlv testTlv;
172 Message *message = NewMessage();
173
174 VerifyOrQuit(message != nullptr);
175 testTlv.Init(aValue);
176 SuccessOrQuit(message->Append(testTlv));
177
178 return *message;
179 }
180
ParseTestMessage(const Message & aMessage)181 void ParseTestMessage(const Message &aMessage)
182 {
183 TestTlv testTlv;
184 Dso::Tlv tlv;
185 uint16_t offset = aMessage.GetOffset();
186
187 // Test message MUST only contain Test TLV and Encryption
188 // Padding TLV.
189
190 SuccessOrQuit(aMessage.Read(offset, testTlv));
191 VerifyOrQuit(testTlv.GetType() == TestTlv::kType);
192 VerifyOrQuit(testTlv.IsValid());
193 offset += testTlv.GetSize();
194 mLastRxTestTlvValue = testTlv.GetValue();
195
196 SuccessOrQuit(aMessage.Read(offset, tlv));
197 VerifyOrQuit(tlv.GetType() == Dso::Tlv::kEncryptionPaddingType);
198 offset += tlv.GetSize();
199
200 VerifyOrQuit(offset == aMessage.GetLength());
201 }
202
SendTestResponseMessage(MessageId aResponseId,uint8_t aValue)203 void SendTestResponseMessage(MessageId aResponseId, uint8_t aValue)
204 {
205 mLastTxTestTlvValue = aValue;
206 SuccessOrQuit(SendResponseMessage(PrepareTestMessage(aValue), aResponseId));
207 }
208
209 //---------------------------------------------------------------------
210 // Callback methods
211
HandleConnected(void)212 void HandleConnected(void) { mDidGetConnectedSignal = true; }
HandleSessionEstablished(void)213 void HandleSessionEstablished(void) { mDidGetSessionEstablishedSignal = true; }
HandleDisconnected(void)214 void HandleDisconnected(void) { mDidGetDisconnectSignal = true; }
215
ProcessRequestMessage(MessageId aMessageId,const Message & aMessage,Dso::Tlv::Type aPrimaryTlvType)216 Error ProcessRequestMessage(MessageId aMessageId, const Message &aMessage, Dso::Tlv::Type aPrimaryTlvType)
217 {
218 Error error = kErrorNone;
219
220 Log(" ProcessRequestMessage(primaryTlv:0x%04x) on %s", aPrimaryTlvType, mName);
221 mDidProcessRequest = true;
222
223 VerifyOrExit(aPrimaryTlvType == TestTlv::kType, error = kErrorNotFound);
224 ParseTestMessage(aMessage);
225 SendTestResponseMessage(aMessageId, mLastRxTestTlvValue);
226
227 exit:
228 return error;
229 }
230
ProcessUnidirectionalMessage(const Message & aMessage,Dso::Tlv::Type aPrimaryTlvType)231 Error ProcessUnidirectionalMessage(const Message &aMessage, Dso::Tlv::Type aPrimaryTlvType)
232 {
233 Log(" ProcessUnidirectionalMessage(primaryTlv:0x%04x) on %s", aPrimaryTlvType, mName);
234 mDidProcessUnidirectional = true;
235
236 if (aPrimaryTlvType == TestTlv::kType)
237 {
238 ParseTestMessage(aMessage);
239 }
240
241 return kErrorNone;
242 }
243
ProcessResponseMessage(const Dns::Header & aHeader,const Message & aMessage,Dso::Tlv::Type aResponseTlvType,Dso::Tlv::Type aRequestTlvType)244 Error ProcessResponseMessage(const Dns::Header &aHeader,
245 const Message &aMessage,
246 Dso::Tlv::Type aResponseTlvType,
247 Dso::Tlv::Type aRequestTlvType)
248 {
249 Error error = kErrorNone;
250
251 mDidProcessResponse = true;
252 mLastRxResponseCode = aHeader.GetResponseCode();
253 Log(" ProcessResponseMessage(responseTlv:0x%04x) on %s (response-Code:%u) ", aResponseTlvType, mName,
254 mLastRxResponseCode);
255
256 VerifyOrExit(mLastRxResponseCode == Dns::Header::kResponseSuccess);
257
258 // During test we only expect a Test TLV response with
259 // a matching TLV value to what was sent last.
260
261 VerifyOrQuit(aResponseTlvType == TestTlv::kType);
262 VerifyOrQuit(aRequestTlvType == TestTlv::kType);
263 ParseTestMessage(aMessage);
264 VerifyOrQuit(mLastRxTestTlvValue == mLastTxTestTlvValue);
265
266 exit:
267 return error;
268 }
269
HandleConnected(Dso::Connection & aConnection)270 static void HandleConnected(Dso::Connection &aConnection)
271 {
272 static_cast<Connection &>(aConnection).HandleConnected();
273 }
274
HandleSessionEstablished(Dso::Connection & aConnection)275 static void HandleSessionEstablished(Dso::Connection &aConnection)
276 {
277 static_cast<Connection &>(aConnection).HandleSessionEstablished();
278 }
279
HandleDisconnected(Dso::Connection & aConnection)280 static void HandleDisconnected(Dso::Connection &aConnection)
281 {
282 static_cast<Connection &>(aConnection).HandleDisconnected();
283 }
284
ProcessRequestMessage(Dso::Connection & aConnection,MessageId aMessageId,const Message & aMessage,Dso::Tlv::Type aPrimaryTlvType)285 static Error ProcessRequestMessage(Dso::Connection &aConnection,
286 MessageId aMessageId,
287 const Message &aMessage,
288 Dso::Tlv::Type aPrimaryTlvType)
289 {
290 return static_cast<Connection &>(aConnection).ProcessRequestMessage(aMessageId, aMessage, aPrimaryTlvType);
291 }
292
ProcessUnidirectionalMessage(Dso::Connection & aConnection,const Message & aMessage,Dso::Tlv::Type aPrimaryTlvType)293 static Error ProcessUnidirectionalMessage(Dso::Connection &aConnection,
294 const Message &aMessage,
295 Dso::Tlv::Type aPrimaryTlvType)
296 {
297 return static_cast<Connection &>(aConnection).ProcessUnidirectionalMessage(aMessage, aPrimaryTlvType);
298 }
299
ProcessResponseMessage(Dso::Connection & aConnection,const Dns::Header & aHeader,const Message & aMessage,Dso::Tlv::Type aResponseTlvType,Dso::Tlv::Type aRequestTlvType)300 static Error ProcessResponseMessage(Dso::Connection &aConnection,
301 const Dns::Header &aHeader,
302 const Message &aMessage,
303 Dso::Tlv::Type aResponseTlvType,
304 Dso::Tlv::Type aRequestTlvType)
305 {
306 return static_cast<Connection &>(aConnection)
307 .ProcessResponseMessage(aHeader, aMessage, aResponseTlvType, aRequestTlvType);
308 }
309
310 const char *mName;
311 Ip6::SockAddr mLocalSockAddr;
312 bool mDidGetConnectedSignal;
313 bool mDidGetSessionEstablishedSignal;
314 bool mDidGetDisconnectSignal;
315 bool mDidSendMessage;
316 bool mDidReceiveMessage;
317 bool mDidProcessRequest;
318 bool mDidProcessUnidirectional;
319 bool mDidProcessResponse;
320 uint8_t mLastTxTestTlvValue;
321 uint8_t mLastRxTestTlvValue;
322 Dns::Header::Response mLastRxResponseCode;
323
324 static Callbacks sCallbacks;
325 };
326
327 Dso::Connection::Callbacks Connection::sCallbacks(Connection::HandleConnected,
328 Connection::HandleSessionEstablished,
329 Connection::HandleDisconnected,
330 Connection::ProcessRequestMessage,
331 Connection::ProcessUnidirectionalMessage,
332 Connection::ProcessResponseMessage);
333
334 static constexpr uint16_t kMaxConnections = 5;
335
336 static Array<Connection *, kMaxConnections> sConnections;
337
FindPeerConnection(const Connection & aConnetion)338 static Connection *FindPeerConnection(const Connection &aConnetion)
339 {
340 Connection *peerConn = nullptr;
341
342 for (Connection *conn : sConnections)
343 {
344 if (conn->GetLocalSockAddr() == aConnetion.GetPeerSockAddr())
345 {
346 peerConn = conn;
347 break;
348 }
349 }
350
351 return peerConn;
352 }
353
354 extern "C" {
355
356 static bool sDsoListening = false;
357
358 // This test flag indicates whether the `otPlatDso` API should
359 // forward a sent message to the peer connection. It can be set to
360 // `false` to drop the messages to test timeout behaviors on the
361 // peer.
362 static bool sTestDsoForwardMessageToPeer = true;
363
364 // This test flag indicate whether when disconnecting a connection
365 // (using `otPlatDsoDisconnect()` to signal the peer connection about
366 // the disconnect. Default behavior is set to `true`. It can be set
367 // to `false` to test certain timeout behavior on peer side.
368 static bool sTestDsoSignalDisconnectToPeer = true;
369
otPlatDsoEnableListening(otInstance *,bool aEnable)370 void otPlatDsoEnableListening(otInstance *, bool aEnable)
371 {
372 Log(" otPlatDsoEnableListening(%s)", aEnable ? "true" : "false");
373 sDsoListening = aEnable;
374 }
375
otPlatDsoConnect(otPlatDsoConnection * aConnection,const otSockAddr * aPeerSockAddr)376 void otPlatDsoConnect(otPlatDsoConnection *aConnection, const otSockAddr *aPeerSockAddr)
377 {
378 Connection &conn = *static_cast<Connection *>(aConnection);
379 Connection *peerConn = nullptr;
380 const Ip6::SockAddr &peerSockAddr = AsCoreType(aPeerSockAddr);
381
382 Log(" otPlatDsoConnect(%s, aPeer:0x%04x)", conn.GetName(), peerSockAddr.GetPort());
383
384 VerifyOrQuit(conn.GetPeerSockAddr() == peerSockAddr);
385 VerifyOrQuit(conn.GetState() == Connection::kStateConnecting);
386
387 if (!sDsoListening)
388 {
389 Log(" Server is not listening");
390 ExitNow();
391 }
392
393 peerConn = static_cast<Connection *>(otPlatDsoAccept(otPlatDsoGetInstance(aConnection), aPeerSockAddr));
394
395 if (peerConn == nullptr)
396 {
397 Log(" Request rejected");
398 ExitNow();
399 }
400
401 Log(" Request accepted");
402 VerifyOrQuit(peerConn->GetState() == Connection::kStateConnecting);
403
404 Log(" Signalling `Connected` on peer connection (%s)", peerConn->GetName());
405 otPlatDsoHandleConnected(peerConn);
406
407 Log(" Signalling `Connected` on connection (%s)", conn.GetName());
408 otPlatDsoHandleConnected(aConnection);
409
410 exit:
411 return;
412 }
413
otPlatDsoSend(otPlatDsoConnection * aConnection,otMessage * aMessage)414 void otPlatDsoSend(otPlatDsoConnection *aConnection, otMessage *aMessage)
415 {
416 Connection &conn = *static_cast<Connection *>(aConnection);
417 Connection *peerConn = nullptr;
418
419 Log(" otPlatDsoSend(%s), message-len:%u", conn.GetName(), AsCoreType(aMessage).GetLength());
420
421 VerifyOrQuit(conn.GetState() != Connection::kStateDisconnected);
422 VerifyOrQuit(conn.GetState() != Connection::kStateConnecting);
423 conn.mDidSendMessage = true;
424
425 if (sTestDsoForwardMessageToPeer)
426 {
427 peerConn = FindPeerConnection(conn);
428 VerifyOrQuit(peerConn != nullptr);
429
430 VerifyOrQuit(peerConn->GetState() != Connection::kStateDisconnected);
431 VerifyOrQuit(peerConn->GetState() != Connection::kStateConnecting);
432
433 Log(" Sending the message to peer connection (%s)", peerConn->GetName());
434
435 peerConn->mDidReceiveMessage = true;
436 otPlatDsoHandleReceive(peerConn, aMessage);
437 }
438 else
439 {
440 Log(" Dropping the message");
441 }
442 }
443
otPlatDsoDisconnect(otPlatDsoConnection * aConnection,otPlatDsoDisconnectMode aMode)444 void otPlatDsoDisconnect(otPlatDsoConnection *aConnection, otPlatDsoDisconnectMode aMode)
445 {
446 Connection &conn = *static_cast<Connection *>(aConnection);
447 Connection *peerConn = nullptr;
448
449 Log(" otPlatDsoDisconnect(%s, mode:%s)", conn.GetName(),
450 (aMode == OT_PLAT_DSO_DISCONNECT_MODE_GRACEFULLY_CLOSE) ? "close" : "abort");
451
452 VerifyOrQuit(conn.GetState() == Connection::kStateDisconnected);
453
454 if (sTestDsoSignalDisconnectToPeer)
455 {
456 peerConn = FindPeerConnection(conn);
457
458 if (peerConn == nullptr)
459 {
460 Log(" No peer connection found");
461 }
462 else if (peerConn->GetState() == Connection::kStateDisconnected)
463 {
464 Log(" Peer connection (%s) already disconnected", peerConn->GetName());
465 }
466 else
467 {
468 Log(" Signaling `Disconnected` on peer connection (%s)", peerConn->GetName());
469 otPlatDsoHandleDisconnected(peerConn, aMode);
470 }
471 }
472 }
473
474 } // extern "C"
475
AcceptConnection(Instance & aInstance,const Ip6::SockAddr & aPeerSockAddr)476 Dso::Connection *AcceptConnection(Instance &aInstance, const Ip6::SockAddr &aPeerSockAddr)
477 {
478 OT_UNUSED_VARIABLE(aInstance);
479
480 Connection *rval = nullptr;
481
482 Log(" AcceptConnection(peer:0x%04x)", aPeerSockAddr.GetPort());
483
484 for (Connection *conn : sConnections)
485 {
486 if (conn->GetLocalSockAddr() == aPeerSockAddr)
487 {
488 VerifyOrQuit(conn->GetState() == Connection::kStateDisconnected);
489 rval = conn;
490 break;
491 }
492 }
493
494 if (rval != nullptr)
495 {
496 Log(" Accepting and returning connection %s", rval->GetName());
497 }
498 else
499 {
500 Log(" Rejecting");
501 }
502
503 return rval;
504 }
505
506 static constexpr uint8_t kKeepAliveTestIterations = 3;
507
VerifyKeepAliveExchange(Connection & aClientConn,Connection & aServerConn,uint32_t aKeepAliveInterval,uint8_t aNumIterations=kKeepAliveTestIterations)508 static void VerifyKeepAliveExchange(Connection &aClientConn,
509 Connection &aServerConn,
510 uint32_t aKeepAliveInterval,
511 uint8_t aNumIterations = kKeepAliveTestIterations)
512 {
513 for (uint8_t n = 0; n < aNumIterations; n++)
514 {
515 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
516 Log("Test Keep Alive message exchange, iter %d", n + 1);
517
518 aClientConn.ClearTestFlags();
519 aServerConn.ClearTestFlags();
520
521 AdvanceTime(aKeepAliveInterval - 1);
522 VerifyOrQuit(!aClientConn.DidSendMessage());
523 VerifyOrQuit(!aServerConn.DidReceiveMessage());
524 Log("No message before keep alive timeout");
525
526 AdvanceTime(1);
527 VerifyOrQuit(aClientConn.DidSendMessage());
528 VerifyOrQuit(aServerConn.DidReceiveMessage());
529 Log("KeepAlive message exchanged after keep alive time elapses");
530 }
531 }
532
TestDso(void)533 void TestDso(void)
534 {
535 static constexpr uint16_t kPortA = 0xaaaa;
536 static constexpr uint16_t kPortB = 0xbbbb;
537
538 static constexpr Dso::Tlv::Type kUnknownTlvType = 0xf801;
539
540 static constexpr uint32_t kRetryDelayInterval = TimeMilli::SecToMsec(3600);
541 static constexpr uint32_t kLongResponseTimeout = Dso::kResponseTimeout + TimeMilli::SecToMsec(17);
542
543 Instance &instance = *static_cast<Instance *>(testInitInstance());
544 Ip6::SockAddr serverSockAddr(kPortA);
545 Ip6::SockAddr clientSockAddr(kPortB);
546 Connection serverConn(instance, "serverConn", serverSockAddr, clientSockAddr);
547 Connection clientConn(instance, "clinetConn", clientSockAddr, serverSockAddr);
548 Message *message;
549 Dso::Tlv tlv;
550 Connection::MessageId messageId;
551
552 sNow = 0;
553 sInstance = &instance;
554
555 SuccessOrQuit(sConnections.PushBack(&serverConn));
556 SuccessOrQuit(sConnections.PushBack(&clientConn));
557
558 VerifyOrQuit(serverConn.GetPeerSockAddr() == clientSockAddr);
559 VerifyOrQuit(clientConn.GetPeerSockAddr() == serverSockAddr);
560
561 VerifyOrQuit(serverConn.GetState() == Connection::kStateDisconnected);
562 VerifyOrQuit(clientConn.GetState() == Connection::kStateDisconnected);
563
564 instance.Get<Dso>().StartListening(AcceptConnection);
565
566 VerifyOrQuit(instance.Get<Dso>().FindClientConnection(clientSockAddr) == nullptr);
567 VerifyOrQuit(instance.Get<Dso>().FindServerConnection(clientSockAddr) == nullptr);
568 VerifyOrQuit(instance.Get<Dso>().FindClientConnection(serverSockAddr) == nullptr);
569 VerifyOrQuit(instance.Get<Dso>().FindServerConnection(serverSockAddr) == nullptr);
570
571 Log("-------------------------------------------------------------------------------------------");
572 Log("Connect from client to server");
573
574 clientConn.Connect();
575
576 VerifyOrQuit(clientConn.GetState() == Connection::kStateConnectedButSessionless);
577 VerifyOrQuit(serverConn.GetState() == Connection::kStateConnectedButSessionless);
578
579 VerifyOrQuit(clientConn.IsClient());
580 VerifyOrQuit(!clientConn.IsServer());
581
582 VerifyOrQuit(!serverConn.IsClient());
583 VerifyOrQuit(serverConn.IsServer());
584
585 // Note that we find connection with a peer address
586 VerifyOrQuit(instance.Get<Dso>().FindClientConnection(serverSockAddr) == &clientConn);
587 VerifyOrQuit(instance.Get<Dso>().FindServerConnection(serverSockAddr) == nullptr);
588 VerifyOrQuit(instance.Get<Dso>().FindClientConnection(clientSockAddr) == nullptr);
589 VerifyOrQuit(instance.Get<Dso>().FindServerConnection(clientSockAddr) == &serverConn);
590
591 VerifyOrQuit(clientConn.DidGetConnectedSignal());
592 VerifyOrQuit(!clientConn.DidGetSessionEstablishedSignal());
593 VerifyOrQuit(!clientConn.DidGetDisconnectSignal());
594
595 VerifyOrQuit(serverConn.DidGetConnectedSignal());
596 VerifyOrQuit(!serverConn.DidGetSessionEstablishedSignal());
597 VerifyOrQuit(!serverConn.DidGetDisconnectSignal());
598
599 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
600 Log("Send keep alive message to establish connection");
601
602 clientConn.ClearTestFlags();
603 serverConn.ClearTestFlags();
604
605 SuccessOrQuit(clientConn.SendKeepAliveMessage());
606
607 VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
608 VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
609
610 VerifyOrQuit(!clientConn.DidGetConnectedSignal());
611 VerifyOrQuit(clientConn.DidGetSessionEstablishedSignal());
612 VerifyOrQuit(!clientConn.DidGetDisconnectSignal());
613
614 VerifyOrQuit(!serverConn.DidGetConnectedSignal());
615 VerifyOrQuit(serverConn.DidGetSessionEstablishedSignal());
616 VerifyOrQuit(!serverConn.DidGetDisconnectSignal());
617
618 VerifyOrQuit(clientConn.GetKeepAliveInterval() == Dso::kDefaultTimeout);
619 VerifyOrQuit(clientConn.GetInactivityTimeout() == Dso::kDefaultTimeout);
620 VerifyOrQuit(serverConn.GetKeepAliveInterval() == Dso::kDefaultTimeout);
621 VerifyOrQuit(serverConn.GetInactivityTimeout() == Dso::kDefaultTimeout);
622
623 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
624 Log("Close connection");
625
626 clientConn.ClearTestFlags();
627 serverConn.ClearTestFlags();
628
629 clientConn.Disconnect(Connection::kGracefullyClose, Connection::kReasonInactivityTimeout);
630
631 VerifyOrQuit(clientConn.GetState() == Connection::kStateDisconnected);
632 VerifyOrQuit(clientConn.GetDisconnectReason() == Connection::kReasonInactivityTimeout);
633
634 VerifyOrQuit(serverConn.GetState() == Connection::kStateDisconnected);
635 VerifyOrQuit(serverConn.GetDisconnectReason() == Connection::kReasonPeerClosed);
636
637 VerifyOrQuit(!clientConn.DidGetConnectedSignal());
638 VerifyOrQuit(!clientConn.DidGetSessionEstablishedSignal());
639 VerifyOrQuit(!clientConn.DidGetDisconnectSignal());
640
641 VerifyOrQuit(!serverConn.DidGetConnectedSignal());
642 VerifyOrQuit(!serverConn.DidGetSessionEstablishedSignal());
643 VerifyOrQuit(serverConn.DidGetDisconnectSignal());
644
645 VerifyOrQuit(instance.Get<Dso>().FindClientConnection(clientSockAddr) == nullptr);
646 VerifyOrQuit(instance.Get<Dso>().FindServerConnection(clientSockAddr) == nullptr);
647 VerifyOrQuit(instance.Get<Dso>().FindClientConnection(serverSockAddr) == nullptr);
648 VerifyOrQuit(instance.Get<Dso>().FindServerConnection(serverSockAddr) == nullptr);
649
650 Log("-------------------------------------------------------------------------------------------");
651 Log("Connection timeout when server is not listening");
652
653 instance.Get<Dso>().StopListening();
654
655 clientConn.ClearTestFlags();
656
657 clientConn.Connect();
658 VerifyOrQuit(clientConn.GetState() == Connection::kStateConnecting);
659 VerifyOrQuit(instance.Get<Dso>().FindClientConnection(serverSockAddr) == &clientConn);
660 VerifyOrQuit(instance.Get<Dso>().FindServerConnection(serverSockAddr) == nullptr);
661
662 AdvanceTime(Dso::kConnectingTimeout);
663
664 VerifyOrQuit(clientConn.GetState() == Connection::kStateDisconnected);
665 VerifyOrQuit(clientConn.GetDisconnectReason() == Connection::kReasonFailedToConnect);
666 VerifyOrQuit(instance.Get<Dso>().FindClientConnection(serverSockAddr) == nullptr);
667 VerifyOrQuit(instance.Get<Dso>().FindServerConnection(serverSockAddr) == nullptr);
668
669 VerifyOrQuit(!clientConn.DidGetConnectedSignal());
670 VerifyOrQuit(!clientConn.DidGetSessionEstablishedSignal());
671 VerifyOrQuit(clientConn.DidGetDisconnectSignal());
672
673 Log("-------------------------------------------------------------------------------------------");
674 Log("Keep Alive Timeout behavior");
675
676 // Keep Alive timeout smaller than min value should be rejected.
677 VerifyOrQuit(clientConn.SetTimeouts(Dso::kInfiniteTimeout, Dso::kMinKeepAliveInterval - 1) == kErrorInvalidArgs);
678
679 instance.Get<Dso>().StartListening(AcceptConnection);
680 SuccessOrQuit(serverConn.SetTimeouts(Dso::kInfiniteTimeout, Dso::kMinKeepAliveInterval));
681
682 VerifyOrQuit(serverConn.GetKeepAliveInterval() == Dso::kMinKeepAliveInterval);
683 VerifyOrQuit(serverConn.GetInactivityTimeout() == Dso::kInfiniteTimeout);
684
685 clientConn.Connect();
686 SuccessOrQuit(clientConn.SendKeepAliveMessage());
687 VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
688 VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
689
690 VerifyOrQuit(serverConn.GetKeepAliveInterval() == Dso::kMinKeepAliveInterval);
691 VerifyOrQuit(serverConn.GetInactivityTimeout() == Dso::kInfiniteTimeout);
692 VerifyOrQuit(clientConn.GetKeepAliveInterval() == Dso::kMinKeepAliveInterval);
693 VerifyOrQuit(clientConn.GetInactivityTimeout() == Dso::kInfiniteTimeout);
694
695 VerifyKeepAliveExchange(clientConn, serverConn, Dso::kMinKeepAliveInterval);
696
697 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
698 Log("Change Keep Alive interval on server");
699
700 clientConn.ClearTestFlags();
701 serverConn.ClearTestFlags();
702
703 SuccessOrQuit(serverConn.SetTimeouts(Dso::kInfiniteTimeout, Dso::kDefaultTimeout));
704
705 VerifyOrQuit(serverConn.DidSendMessage());
706 VerifyOrQuit(clientConn.DidReceiveMessage());
707 VerifyOrQuit(!clientConn.DidSendMessage());
708
709 VerifyOrQuit(serverConn.GetKeepAliveInterval() == Dso::kDefaultTimeout);
710 VerifyOrQuit(serverConn.GetInactivityTimeout() == Dso::kInfiniteTimeout);
711 VerifyOrQuit(clientConn.GetKeepAliveInterval() == Dso::kDefaultTimeout);
712 VerifyOrQuit(clientConn.GetInactivityTimeout() == Dso::kInfiniteTimeout);
713
714 VerifyKeepAliveExchange(clientConn, serverConn, Dso::kDefaultTimeout);
715
716 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
717 Log("Keep Alive timer clear on message send or receive");
718
719 clientConn.ClearTestFlags();
720 serverConn.ClearTestFlags();
721
722 AdvanceTime(Dso::kDefaultTimeout / 2);
723
724 clientConn.SendTestUnidirectionalMessage();
725 VerifyOrQuit(clientConn.DidSendMessage());
726 VerifyOrQuit(serverConn.DidReceiveMessage());
727 VerifyOrQuit(!serverConn.DidSendMessage());
728 VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
729 VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
730 Log("Sent unidirectional message (client->server) at half the keep alive interval");
731 VerifyKeepAliveExchange(clientConn, serverConn, Dso::kDefaultTimeout, 1);
732
733 clientConn.ClearTestFlags();
734 serverConn.ClearTestFlags();
735
736 AdvanceTime(Dso::kDefaultTimeout / 2);
737
738 serverConn.SendTestUnidirectionalMessage();
739 VerifyOrQuit(serverConn.DidSendMessage());
740 VerifyOrQuit(clientConn.DidReceiveMessage());
741 VerifyOrQuit(!clientConn.DidSendMessage());
742 VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
743 VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
744 Log("Sent unidirectional message (server->client) at half the keep alive interval");
745 VerifyKeepAliveExchange(clientConn, serverConn, Dso::kDefaultTimeout, 1);
746
747 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
748 Log("Keep Alive timeout on server");
749
750 clientConn.ClearTestFlags();
751 serverConn.ClearTestFlags();
752
753 Log("Drop all sent message (drop Keep Alive msg from client->server)");
754 sTestDsoForwardMessageToPeer = false;
755
756 AdvanceTime(Dso::kDefaultTimeout);
757 VerifyOrQuit(clientConn.DidSendMessage());
758 VerifyOrQuit(!serverConn.DidReceiveMessage());
759 VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
760 VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
761
762 Log("Sever waits for twice the interval before Keep Alive timeout");
763 AdvanceTime(Dso::kDefaultTimeout);
764
765 VerifyOrQuit(serverConn.GetState() == Connection::kStateDisconnected);
766 VerifyOrQuit(serverConn.GetDisconnectReason() == Connection::kReasonKeepAliveTimeout);
767
768 VerifyOrQuit(clientConn.GetState() == Connection::kStateDisconnected);
769 VerifyOrQuit(clientConn.GetDisconnectReason() == Connection::kReasonPeerAborted);
770 Log("Server aborted connection on Keep Alive timeout");
771 sTestDsoForwardMessageToPeer = true;
772
773 Log("-------------------------------------------------------------------------------------------");
774 Log("Inactivity Timeout behavior");
775
776 SuccessOrQuit(serverConn.SetTimeouts(Dso::kDefaultTimeout, Dso::kMinKeepAliveInterval));
777
778 VerifyOrQuit(serverConn.GetKeepAliveInterval() == Dso::kMinKeepAliveInterval);
779 VerifyOrQuit(serverConn.GetInactivityTimeout() == Dso::kDefaultTimeout);
780
781 clientConn.Connect();
782 SuccessOrQuit(clientConn.SendKeepAliveMessage());
783 VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
784 VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
785
786 VerifyOrQuit(serverConn.GetKeepAliveInterval() == Dso::kMinKeepAliveInterval);
787 VerifyOrQuit(serverConn.GetInactivityTimeout() == Dso::kDefaultTimeout);
788 VerifyOrQuit(clientConn.GetKeepAliveInterval() == Dso::kMinKeepAliveInterval);
789 VerifyOrQuit(clientConn.GetInactivityTimeout() == Dso::kDefaultTimeout);
790
791 Log("Sending a unidirectional message should clear inactivity timer");
792 AdvanceTime(Dso::kDefaultTimeout / 2);
793 clientConn.SendTestUnidirectionalMessage();
794
795 AdvanceTime(Dso::kDefaultTimeout - 1);
796 VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
797 VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
798 Log("Client keeps the connection up to the inactivity timeout");
799
800 AdvanceTime(1);
801 VerifyOrQuit(clientConn.GetState() == Connection::kStateDisconnected);
802 VerifyOrQuit(clientConn.GetDisconnectReason() == Connection::kReasonInactivityTimeout);
803 VerifyOrQuit(serverConn.GetState() == Connection::kStateDisconnected);
804 VerifyOrQuit(serverConn.GetDisconnectReason() == Connection::kReasonPeerClosed);
805 Log("Client closes the connection gracefully on inactivity timeout");
806
807 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
808 Log("Increasing inactivity timeout in middle");
809
810 clientConn.Connect();
811 SuccessOrQuit(clientConn.SendKeepAliveMessage());
812 VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
813 VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
814
815 AdvanceTime(TimeMilli::SecToMsec(10));
816 Log("After 10 sec elapses, change the inactivity timeout from 15 to 20 sec");
817 SuccessOrQuit(serverConn.SetTimeouts(TimeMilli::SecToMsec(20), Dso::kMinKeepAliveInterval));
818
819 AdvanceTime(TimeMilli::SecToMsec(10) - 1);
820 VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
821 VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
822 Log("Client keeps the connection up to new 20 sec inactivity timeout");
823
824 AdvanceTime(1);
825 VerifyOrQuit(clientConn.GetState() == Connection::kStateDisconnected);
826 VerifyOrQuit(clientConn.GetDisconnectReason() == Connection::kReasonInactivityTimeout);
827 VerifyOrQuit(serverConn.GetState() == Connection::kStateDisconnected);
828 VerifyOrQuit(serverConn.GetDisconnectReason() == Connection::kReasonPeerClosed);
829 Log("Client closes the connection gracefully on inactivity timeout of 20 sec");
830
831 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
832 Log("Decreasing inactivity timeout in middle");
833
834 clientConn.Connect();
835 SuccessOrQuit(clientConn.SendKeepAliveMessage());
836 VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
837 VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
838
839 AdvanceTime(TimeMilli::SecToMsec(10));
840 Log("After 10 sec elapses, change the inactivity timeout from 15 to 10 sec");
841 SuccessOrQuit(serverConn.SetTimeouts(TimeMilli::SecToMsec(10), Dso::kMinKeepAliveInterval));
842
843 AdvanceTime(0);
844 VerifyOrQuit(clientConn.GetState() == Connection::kStateDisconnected);
845 VerifyOrQuit(clientConn.GetDisconnectReason() == Connection::kReasonInactivityTimeout);
846 VerifyOrQuit(serverConn.GetState() == Connection::kStateDisconnected);
847 VerifyOrQuit(serverConn.GetDisconnectReason() == Connection::kReasonPeerClosed);
848 Log("Client closes the connection gracefully on new shorter inactivity timeout of 10 sec");
849
850 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
851 Log("Changing inactivity timeout from infinite to finite");
852
853 SuccessOrQuit(serverConn.SetTimeouts(Dso::kDefaultTimeout, Dso::kInfiniteTimeout));
854 clientConn.Connect();
855 SuccessOrQuit(clientConn.SendKeepAliveMessage());
856 VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
857 VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
858
859 AdvanceTime(TimeMilli::SecToMsec(6));
860 Log("After 6 sec, change the inactivity to infinite");
861 SuccessOrQuit(serverConn.SetTimeouts(Dso::kInfiniteTimeout, Dso::kInfiniteTimeout));
862
863 AdvanceTime(TimeMilli::SecToMsec(4));
864 Log("After 4 sec, change the inactivity timeout from infinite to 20 sec");
865 SuccessOrQuit(serverConn.SetTimeouts(TimeMilli::SecToMsec(20), Dso::kInfiniteTimeout));
866
867 AdvanceTime(TimeMilli::SecToMsec(10) - 1);
868 VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
869 VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
870
871 AdvanceTime(1);
872 VerifyOrQuit(clientConn.GetState() == Connection::kStateDisconnected);
873 VerifyOrQuit(clientConn.GetDisconnectReason() == Connection::kReasonInactivityTimeout);
874 VerifyOrQuit(serverConn.GetState() == Connection::kStateDisconnected);
875 VerifyOrQuit(serverConn.GetDisconnectReason() == Connection::kReasonPeerClosed);
876 Log("Client closes the connection gracefully after 20 sec since last activity");
877
878 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
879 Log("Tracking activity while inactivity timeout is infinite");
880
881 SuccessOrQuit(serverConn.SetTimeouts(Dso::kInfiniteTimeout, Dso::kInfiniteTimeout));
882 clientConn.Connect();
883 SuccessOrQuit(clientConn.SendKeepAliveMessage());
884 VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
885 VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
886
887 AdvanceTime(TimeMilli::SecToMsec(7));
888 Log("After 7 sec, send a test message, this clears inactivity timer");
889 serverConn.SendTestUnidirectionalMessage();
890
891 AdvanceTime(TimeMilli::SecToMsec(10));
892 Log("After 10 sec, change the inactivity timeout from infinite to 15 sec");
893 SuccessOrQuit(serverConn.SetTimeouts(TimeMilli::SecToMsec(15), Dso::kInfiniteTimeout));
894
895 AdvanceTime(TimeMilli::SecToMsec(5) - 1);
896 VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
897 VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
898
899 AdvanceTime(1);
900 VerifyOrQuit(clientConn.GetState() == Connection::kStateDisconnected);
901 VerifyOrQuit(clientConn.GetDisconnectReason() == Connection::kReasonInactivityTimeout);
902 VerifyOrQuit(serverConn.GetState() == Connection::kStateDisconnected);
903 VerifyOrQuit(serverConn.GetDisconnectReason() == Connection::kReasonPeerClosed);
904 Log("Client closes the connection gracefully after 15 sec since last activity");
905
906 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
907 Log("Inactivity timeout on server");
908
909 clientConn.Connect();
910 SuccessOrQuit(clientConn.SendKeepAliveMessage());
911 VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
912 VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
913
914 SuccessOrQuit(serverConn.SetTimeouts(Dso::kDefaultTimeout, Dso::kInfiniteTimeout));
915
916 Log("Wait for inactivity timeout and ensure client disconnect");
917 Log("Configure test for client not to signal its disconnect to server");
918 sTestDsoSignalDisconnectToPeer = false;
919
920 AdvanceTime(Dso::kDefaultTimeout);
921 VerifyOrQuit(clientConn.GetState() == Connection::kStateDisconnected);
922 VerifyOrQuit(clientConn.GetDisconnectReason() == Connection::kReasonInactivityTimeout);
923 VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
924 sTestDsoSignalDisconnectToPeer = true;
925
926 Log("Server should disconnect after twice the inactivity timeout");
927 AdvanceTime(Dso::kDefaultTimeout - 1);
928 VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
929 AdvanceTime(1);
930 VerifyOrQuit(serverConn.GetState() == Connection::kStateDisconnected);
931 VerifyOrQuit(serverConn.GetDisconnectReason() == Connection::kReasonInactivityTimeout);
932
933 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
934 Log("Server reducing inactivity timeout to expired (on server)");
935
936 clientConn.Connect();
937 SuccessOrQuit(clientConn.SendKeepAliveMessage());
938 VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
939 VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
940 SuccessOrQuit(serverConn.SetTimeouts(Dso::kDefaultTimeout, Dso::kInfiniteTimeout));
941
942 AdvanceTime(TimeMilli::SecToMsec(10));
943 Log("After 11 sec elapses, change the inactivity timeout from 15 to 2 sec");
944 SuccessOrQuit(serverConn.SetTimeouts(TimeMilli::SecToMsec(2), Dso::kMinKeepAliveInterval));
945
946 sTestDsoSignalDisconnectToPeer = false;
947 AdvanceTime(0);
948 VerifyOrQuit(clientConn.GetState() == Connection::kStateDisconnected);
949 VerifyOrQuit(clientConn.GetDisconnectReason() == Connection::kReasonInactivityTimeout);
950 sTestDsoSignalDisconnectToPeer = true;
951 Log("Client closes the connection gracefully on expired timeout");
952 Log("Configure test for client not to signal its disconnect to server");
953
954 AdvanceTime(Dso::kMinServerInactivityWaitTime - 1);
955 VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
956 AdvanceTime(1);
957 VerifyOrQuit(serverConn.GetState() == Connection::kStateDisconnected);
958 VerifyOrQuit(serverConn.GetDisconnectReason() == Connection::kReasonInactivityTimeout);
959 Log("Server wait for kMinServerInactivityWaitTime (5 sec) before closing on expired timeout");
960
961 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
962 Log("Long-lived operation");
963
964 clientConn.Connect();
965 SuccessOrQuit(clientConn.SendKeepAliveMessage());
966 VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
967 VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
968 SuccessOrQuit(serverConn.SetTimeouts(Dso::kDefaultTimeout, Dso::kInfiniteTimeout));
969
970 clientConn.SetLongLivedOperation(true);
971 serverConn.SetLongLivedOperation(true);
972
973 AdvanceTime(2 * Dso::kDefaultTimeout);
974 VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
975 VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
976
977 clientConn.SetLongLivedOperation(false);
978 AdvanceTime(0);
979 VerifyOrQuit(clientConn.GetState() == Connection::kStateDisconnected);
980 VerifyOrQuit(serverConn.GetState() == Connection::kStateDisconnected);
981
982 Log("-------------------------------------------------------------------------------------------");
983 Log("Request, response, and unidirectional message exchange");
984
985 SuccessOrQuit(serverConn.SetTimeouts(Dso::kDefaultTimeout, Dso::kDefaultTimeout));
986 clientConn.Connect();
987
988 VerifyOrQuit(clientConn.GetState() == Connection::kStateConnectedButSessionless);
989 VerifyOrQuit(serverConn.GetState() == Connection::kStateConnectedButSessionless);
990
991 clientConn.ClearTestFlags();
992 serverConn.ClearTestFlags();
993
994 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
995 Log("Establish connection using test message request/response");
996 clientConn.SendTestRequestMessage();
997
998 VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
999 VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
1000 VerifyOrQuit(serverConn.DidProcessRequest());
1001 VerifyOrQuit(clientConn.DidProcessResponse());
1002
1003 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
1004 Log("Send unidirectional test message");
1005
1006 serverConn.ClearTestFlags();
1007 clientConn.SendTestUnidirectionalMessage(0x10);
1008 VerifyOrQuit(serverConn.DidProcessUnidirectional());
1009 VerifyOrQuit(serverConn.GetLastRxTestTlvValue() == 0x10);
1010
1011 clientConn.ClearTestFlags();
1012 serverConn.SendTestUnidirectionalMessage(0x20);
1013 VerifyOrQuit(clientConn.DidProcessUnidirectional());
1014 VerifyOrQuit(clientConn.GetLastRxTestTlvValue() == 0x20);
1015
1016 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
1017 Log("Exchange request and response");
1018
1019 clientConn.ClearTestFlags();
1020 serverConn.ClearTestFlags();
1021 serverConn.SendTestRequestMessage(0x30);
1022 VerifyOrQuit(clientConn.DidProcessRequest());
1023 VerifyOrQuit(!clientConn.DidProcessResponse());
1024 VerifyOrQuit(!serverConn.DidProcessRequest());
1025 VerifyOrQuit(serverConn.DidProcessResponse());
1026 VerifyOrQuit(serverConn.GetLastRxTestTlvValue() == 0x30);
1027 VerifyOrQuit(clientConn.GetLastRxTestTlvValue() == 0x30);
1028
1029 clientConn.ClearTestFlags();
1030 serverConn.ClearTestFlags();
1031 clientConn.SendTestRequestMessage(0x40);
1032 VerifyOrQuit(!clientConn.DidProcessRequest());
1033 VerifyOrQuit(clientConn.DidProcessResponse());
1034 VerifyOrQuit(serverConn.DidProcessRequest());
1035 VerifyOrQuit(!serverConn.DidProcessResponse());
1036 VerifyOrQuit(serverConn.GetLastRxTestTlvValue() == 0x40);
1037 VerifyOrQuit(clientConn.GetLastRxTestTlvValue() == 0x40);
1038
1039 VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
1040 VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
1041
1042 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
1043 Log("Send unknown TLV request");
1044
1045 clientConn.ClearTestFlags();
1046 serverConn.ClearTestFlags();
1047
1048 message = clientConn.NewMessage();
1049 VerifyOrQuit(message != nullptr);
1050 tlv.Init(kUnknownTlvType, 0);
1051 SuccessOrQuit(message->Append(tlv));
1052 SuccessOrQuit(clientConn.SendRequestMessage(*message, messageId));
1053
1054 VerifyOrQuit(!clientConn.DidProcessRequest());
1055 VerifyOrQuit(clientConn.DidProcessResponse());
1056 VerifyOrQuit(serverConn.DidProcessRequest());
1057 VerifyOrQuit(!serverConn.DidProcessResponse());
1058 VerifyOrQuit(clientConn.GetLastRxResponseCode() == Dns::Header::kDsoTypeNotImplemented);
1059 Log("Received a response with DSO Type Unknown error code");
1060
1061 VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
1062 VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
1063
1064 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
1065 Log("Send unknown TLV unidirectional");
1066
1067 clientConn.ClearTestFlags();
1068 serverConn.ClearTestFlags();
1069
1070 message = clientConn.NewMessage();
1071 VerifyOrQuit(message != nullptr);
1072 tlv.Init(kUnknownTlvType, 0);
1073 SuccessOrQuit(message->Append(tlv));
1074 SuccessOrQuit(clientConn.SendUnidirectionalMessage(*message));
1075 VerifyOrQuit(serverConn.DidProcessUnidirectional());
1076 Log("Unknown TLV unidirectional is correctly ignored");
1077 VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
1078 VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
1079
1080 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
1081 Log("Send malformed/invalid request");
1082
1083 clientConn.ClearTestFlags();
1084 serverConn.ClearTestFlags();
1085
1086 message = clientConn.NewMessage();
1087 VerifyOrQuit(message != nullptr);
1088 tlv.Init(Dso::Tlv::kEncryptionPaddingType, 0);
1089 SuccessOrQuit(message->Append(tlv));
1090
1091 SuccessOrQuit(serverConn.SendRequestMessage(*message, messageId));
1092 VerifyOrQuit(clientConn.GetState() == Connection::kStateDisconnected);
1093 VerifyOrQuit(serverConn.GetState() == Connection::kStateDisconnected);
1094 VerifyOrQuit(clientConn.GetDisconnectReason() == Connection::kReasonPeerMisbehavior);
1095 VerifyOrQuit(serverConn.GetDisconnectReason() == Connection::kReasonPeerAborted);
1096 VerifyOrQuit(clientConn.DidGetDisconnectSignal());
1097 VerifyOrQuit(serverConn.DidGetDisconnectSignal());
1098 Log("Client aborted on invalid request message");
1099
1100 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
1101 Log("Response timeout during session establishment");
1102
1103 clientConn.ClearTestFlags();
1104 serverConn.ClearTestFlags();
1105
1106 SuccessOrQuit(serverConn.SetTimeouts(Dso::kResponseTimeout, Dso::kInfiniteTimeout));
1107 clientConn.Connect();
1108 VerifyOrQuit(clientConn.GetState() == Connection::kStateConnectedButSessionless);
1109 VerifyOrQuit(serverConn.GetState() == Connection::kStateConnectedButSessionless);
1110
1111 sTestDsoForwardMessageToPeer = false;
1112 clientConn.SendTestRequestMessage();
1113 sTestDsoForwardMessageToPeer = true;
1114
1115 VerifyOrQuit(clientConn.GetState() == Connection::kStateEstablishingSession);
1116 VerifyOrQuit(serverConn.GetState() == Connection::kStateConnectedButSessionless);
1117
1118 sTestDsoSignalDisconnectToPeer = false;
1119 AdvanceTime(Dso::kResponseTimeout);
1120 sTestDsoSignalDisconnectToPeer = true;
1121 VerifyOrQuit(clientConn.GetState() == Connection::kStateDisconnected);
1122 VerifyOrQuit(clientConn.GetDisconnectReason() == Connection::kReasonResponseTimeout);
1123 VerifyOrQuit(clientConn.DidGetDisconnectSignal());
1124 VerifyOrQuit(serverConn.GetState() == Connection::kStateConnectedButSessionless);
1125 Log("Client disconnected after response timeout");
1126
1127 AdvanceTime(Dso::kResponseTimeout);
1128 VerifyOrQuit(serverConn.GetState() == Connection::kStateDisconnected);
1129 VerifyOrQuit(serverConn.GetDisconnectReason() == Connection::kReasonInactivityTimeout);
1130 VerifyOrQuit(serverConn.DidGetDisconnectSignal());
1131 Log("Server disconnected after twice the inactivity timeout");
1132
1133 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
1134 Log("Response timeout after session establishment");
1135
1136 clientConn.ClearTestFlags();
1137 serverConn.ClearTestFlags();
1138
1139 SuccessOrQuit(serverConn.SetTimeouts(Dso::kInfiniteTimeout, Dso::kInfiniteTimeout));
1140 clientConn.Connect();
1141 SuccessOrQuit(clientConn.SendKeepAliveMessage());
1142 VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
1143 VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
1144
1145 sTestDsoForwardMessageToPeer = false;
1146 serverConn.SendTestRequestMessage();
1147 sTestDsoForwardMessageToPeer = true;
1148
1149 VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
1150 VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
1151
1152 AdvanceTime(Dso::kResponseTimeout - 1);
1153 VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
1154 VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
1155
1156 AdvanceTime(1);
1157 VerifyOrQuit(serverConn.GetState() == Connection::kStateDisconnected);
1158 VerifyOrQuit(clientConn.GetState() == Connection::kStateDisconnected);
1159 VerifyOrQuit(serverConn.GetDisconnectReason() == Connection::kReasonResponseTimeout);
1160 VerifyOrQuit(clientConn.GetDisconnectReason() == Connection::kReasonPeerAborted);
1161 VerifyOrQuit(serverConn.DidGetDisconnectSignal());
1162 VerifyOrQuit(clientConn.DidGetDisconnectSignal());
1163
1164 clientConn.ClearTestFlags();
1165 serverConn.ClearTestFlags();
1166
1167 SuccessOrQuit(serverConn.SetTimeouts(Dso::kInfiniteTimeout, Dso::kInfiniteTimeout));
1168 clientConn.Connect();
1169 SuccessOrQuit(clientConn.SendKeepAliveMessage());
1170 VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
1171 VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
1172
1173 sTestDsoForwardMessageToPeer = false;
1174 serverConn.SendTestRequestMessage(0, kLongResponseTimeout);
1175 sTestDsoForwardMessageToPeer = true;
1176
1177 VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
1178 VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
1179
1180 AdvanceTime(kLongResponseTimeout - 1);
1181 VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
1182 VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
1183
1184 AdvanceTime(1);
1185 VerifyOrQuit(serverConn.GetState() == Connection::kStateDisconnected);
1186 VerifyOrQuit(clientConn.GetState() == Connection::kStateDisconnected);
1187 VerifyOrQuit(serverConn.GetDisconnectReason() == Connection::kReasonResponseTimeout);
1188 VerifyOrQuit(clientConn.GetDisconnectReason() == Connection::kReasonPeerAborted);
1189 VerifyOrQuit(serverConn.DidGetDisconnectSignal());
1190 VerifyOrQuit(clientConn.DidGetDisconnectSignal());
1191
1192 Log("-------------------------------------------------------------------------------------------");
1193 Log("Retry Delay message");
1194
1195 clientConn.ClearTestFlags();
1196 serverConn.ClearTestFlags();
1197
1198 SuccessOrQuit(serverConn.SetTimeouts(Dso::kInfiniteTimeout, Dso::kInfiniteTimeout));
1199 clientConn.Connect();
1200 SuccessOrQuit(clientConn.SendKeepAliveMessage());
1201 VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
1202 VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
1203
1204 SuccessOrQuit(serverConn.SendRetryDelayMessage(kRetryDelayInterval, Dns::Header::kResponseServerFailure));
1205
1206 VerifyOrQuit(clientConn.GetState() == Connection::kStateDisconnected);
1207 VerifyOrQuit(serverConn.GetState() == Connection::kStateDisconnected);
1208 VerifyOrQuit(clientConn.DidGetDisconnectSignal());
1209 VerifyOrQuit(serverConn.DidGetDisconnectSignal());
1210 VerifyOrQuit(clientConn.GetDisconnectReason() == Connection::kReasonServerRetryDelayRequest);
1211 VerifyOrQuit(serverConn.GetDisconnectReason() == Connection::kReasonPeerClosed);
1212
1213 VerifyOrQuit(clientConn.GetRetryDelay() == kRetryDelayInterval);
1214 VerifyOrQuit(clientConn.GetRetryDelayErrorCode() == Dns::Header::kResponseServerFailure);
1215
1216 Log("End of test");
1217
1218 testFreeInstance(&instance);
1219 }
1220
1221 } // namespace Dns
1222
1223 #endif // OPENTHREAD_CONFIG_DNS_DSO_ENABLE
1224
1225 } // namespace ot
1226
main(void)1227 int main(void)
1228 {
1229 #if OPENTHREAD_CONFIG_DNS_DSO_ENABLE
1230 ot::Dns::TestDso();
1231 printf("All tests passed\n");
1232 #else
1233 printf("DSO feature is not enabled\n");
1234 #endif
1235
1236 return 0;
1237 }
1238