1 /*
2 * Copyright (c) 2024, 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 <stdarg.h>
30 #include <stdio.h>
31 #include <string.h>
32
33 #include "platform/nexus_core.hpp"
34 #include "platform/nexus_node.hpp"
35
36 namespace ot {
37 namespace Nexus {
38
39 typedef MeshCoP::Dtls Dtls;
40
41 static constexpr uint16_t kMaxNodes = 3;
42 static constexpr uint16_t kUdpPort = 1234;
43 static constexpr uint16_t kMessageSize = 100;
44 static constexpr uint16_t kMaxAttempts = 3;
45
46 static const uint8_t kPsk[] = {0x10, 0x20, 0x03, 0x15, 0x10, 0x00, 0x60, 0x16};
47
48 static Dtls::Session::ConnectEvent sDtlsEvent[kMaxNodes];
49 static Array<uint8_t, kMessageSize> sDtlsLastReceive[kMaxNodes];
50 static bool sDtlsAutoClosed[kMaxNodes];
51 static uint32_t sHeapSessionsAllocated = 0;
52
ConnectEventToString(Dtls::Session::ConnectEvent aEvent)53 const char *ConnectEventToString(Dtls::Session::ConnectEvent aEvent)
54 {
55 const char *str = "";
56
57 switch (aEvent)
58 {
59 case Dtls::Session::kConnected:
60 str = "kConnected";
61 break;
62 case Dtls::Session::kDisconnectedPeerClosed:
63 str = "kDisconnectedPeerClosed";
64 break;
65 case Dtls::Session::kDisconnectedLocalClosed:
66 str = "kDisconnectedLocalClosed";
67 break;
68 case Dtls::Session::kDisconnectedMaxAttempts:
69 str = "kDisconnectedMaxAttempts";
70 break;
71 case Dtls::Session::kDisconnectedError:
72 str = "kDisconnectedError";
73 break;
74 }
75
76 return str;
77 }
78
HandleReceive(void * aContext,uint8_t * aBuf,uint16_t aLength)79 void HandleReceive(void *aContext, uint8_t *aBuf, uint16_t aLength)
80 {
81 Node *node = static_cast<Node *>(aContext);
82
83 VerifyOrQuit(node != nullptr);
84 VerifyOrQuit(node->GetId() < kMaxNodes);
85
86 Log(" node%u: HandleReceive(aLength:%u)", node->GetId(), aLength);
87
88 sDtlsLastReceive[node->GetId()].Clear();
89
90 for (; aLength > 0; aLength--, aBuf++)
91 {
92 SuccessOrQuit(sDtlsLastReceive[node->GetId()].PushBack(*aBuf));
93 }
94 }
95
HandleConnectEvent(Dtls::Session::ConnectEvent aEvent,void * aContext)96 void HandleConnectEvent(Dtls::Session::ConnectEvent aEvent, void *aContext)
97 {
98 Node *node = static_cast<Node *>(aContext);
99
100 VerifyOrQuit(node != nullptr);
101 VerifyOrQuit(node->GetId() < kMaxNodes);
102 sDtlsEvent[node->GetId()] = aEvent;
103
104 Log(" node%u: HandleConnectEvent(%s)", node->GetId(), ConnectEventToString(aEvent));
105 }
106
HandleAutoClose(void * aContext)107 void HandleAutoClose(void *aContext)
108 {
109 Node *node = static_cast<Node *>(aContext);
110
111 VerifyOrQuit(node != nullptr);
112 VerifyOrQuit(node->GetId() < kMaxNodes);
113 sDtlsAutoClosed[node->GetId()] = true;
114
115 Log(" node%u: HandleAutoClose()", node->GetId());
116 }
117
PrepareMessage(Node & aNode)118 OwnedPtr<Message> PrepareMessage(Node &aNode)
119 {
120 Message *message = aNode.Get<MessagePool>().Allocate(Message::kTypeOther);
121 uint16_t length;
122
123 VerifyOrQuit(message != nullptr);
124
125 length = Random::NonCrypto::GetUint16InRange(1, kMessageSize);
126
127 for (uint16_t i = 0; i < length; i++)
128 {
129 SuccessOrQuit(message->Append(Random::NonCrypto::GetUint8()));
130 }
131
132 return OwnedPtr<Message>(message);
133 }
134
135 class DtlsTransportAndSingleSession : public InstanceLocator, public Dtls::Transport, public Dtls::Session
136 {
137 // A DTLS transport and single session
138 public:
DtlsTransportAndSingleSession(Node & aNode)139 explicit DtlsTransportAndSingleSession(Node &aNode)
140 : InstanceLocator(aNode.GetInstance())
141 , Dtls::Transport(aNode.GetInstance(), kWithLinkSecurity)
142 , Dtls::Session(static_cast<Dtls::Transport &>(*this))
143 , mNode(aNode)
144 {
145 SetAcceptCallback(HandleAccept, this);
146
147 VerifyOrQuit(!IsSessionInUse());
148 }
149
150 private:
HandleAccept(void * aContext,const Ip6::MessageInfo & aMessageInfo)151 static MeshCoP::SecureSession *HandleAccept(void *aContext, const Ip6::MessageInfo &aMessageInfo)
152 {
153 return static_cast<DtlsTransportAndSingleSession *>(aContext)->HandleAccept();
154 }
155
HandleAccept(void)156 Dtls::Session *HandleAccept(void)
157 {
158 Dtls::Session *session = IsSessionInUse() ? nullptr : static_cast<Dtls::Session *>(this);
159
160 Log(" node%u: HandleAccept(), %s", mNode.GetId(), (session != nullptr) ? "accepted" : "rejected");
161 return session;
162 }
163
164 Node &mNode;
165 };
166
167 class DtlsTransportAndHeapSession : public InstanceLocator, public Dtls::Transport
168 {
169 // A DTLS session with heap allocated sessions.
170
171 public:
DtlsTransportAndHeapSession(Node & aNode)172 explicit DtlsTransportAndHeapSession(Node &aNode)
173 : InstanceLocator(aNode.GetInstance())
174 , Dtls::Transport(aNode.GetInstance(), kWithLinkSecurity)
175 , mNode(aNode)
176 {
177 SetAcceptCallback(HandleAccept, this);
178 SetRemoveSessionCallback(HandleRemoveSession, this);
179 }
180
181 private:
182 class HeapDtlsSession : public Dtls::Session, public Heap::Allocatable<HeapDtlsSession>
183 {
184 friend Heap::Allocatable<HeapDtlsSession>;
185
186 private:
HeapDtlsSession(Dtls::Transport & aTransport)187 HeapDtlsSession(Dtls::Transport &aTransport)
188 : Dtls::Session(aTransport)
189 {
190 sHeapSessionsAllocated++;
191 }
192 };
193
HandleAccept(void * aContext,const Ip6::MessageInfo & aMessageInfo)194 static MeshCoP::SecureSession *HandleAccept(void *aContext, const Ip6::MessageInfo &aMessageInfo)
195 {
196 DtlsTransportAndHeapSession *transport;
197 HeapDtlsSession *session;
198
199 VerifyOrQuit(aContext != nullptr);
200 transport = static_cast<DtlsTransportAndHeapSession *>(aContext);
201
202 Log(" node%u: HandleAccept()", transport->mNode.GetId());
203
204 session = HeapDtlsSession::Allocate(*transport);
205 VerifyOrQuit(session != nullptr);
206
207 session->SetReceiveCallback(&ot::Nexus::HandleReceive, &transport->mNode);
208 session->SetConnectCallback(&ot::Nexus::HandleConnectEvent, &transport->mNode);
209
210 return session;
211 }
212
HandleRemoveSession(void * aContext,MeshCoP::SecureSession & aSesssion)213 static void HandleRemoveSession(void *aContext, MeshCoP::SecureSession &aSesssion)
214 {
215 DtlsTransportAndHeapSession *transport;
216
217 VerifyOrQuit(aContext != nullptr);
218 transport = static_cast<DtlsTransportAndHeapSession *>(aContext);
219
220 Log(" node%u: HandleRemoveSession()", transport->mNode.GetId());
221
222 VerifyOrQuit(sHeapSessionsAllocated > 0);
223
224 static_cast<HeapDtlsSession &>(aSesssion).Free();
225 sHeapSessionsAllocated--;
226 }
227
228 private:
229 Node &mNode;
230 };
231
TestDtlsSingleSession(void)232 void TestDtlsSingleSession(void)
233 {
234 Core nexus;
235 Node &node0 = nexus.CreateNode();
236 Node &node1 = nexus.CreateNode();
237 Node &node2 = nexus.CreateNode();
238
239 Log("------------------------------------------------------------------------------------------------------");
240 Log("TestDtlsSingleSession");
241
242 nexus.AdvanceTime(0);
243
244 // Form the topology: node0 leader, with node1 & node2 as its FTD children
245
246 node0.Form();
247 nexus.AdvanceTime(50 * Time::kOneSecondInMsec);
248 VerifyOrQuit(node0.Get<Mle::Mle>().IsLeader());
249
250 SuccessOrQuit(node1.Get<Mle::MleRouter>().SetRouterEligible(false));
251 node1.Join(node0);
252 nexus.AdvanceTime(20 * Time::kOneSecondInMsec);
253 VerifyOrQuit(node1.Get<Mle::Mle>().IsChild());
254
255 SuccessOrQuit(node2.Get<Mle::MleRouter>().SetRouterEligible(false));
256 node2.Join(node0);
257 nexus.AdvanceTime(20 * Time::kOneSecondInMsec);
258 VerifyOrQuit(node2.Get<Mle::Mle>().IsChild());
259
260 {
261 DtlsTransportAndSingleSession dtls0(node0);
262 DtlsTransportAndSingleSession dtls1(node1);
263 DtlsTransportAndSingleSession dtls2(node2);
264 Ip6::SockAddr sockAddr;
265
266 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
267 Log("Start DTLS (server) on node0 bound to port %u", kUdpPort);
268
269 SuccessOrQuit(dtls0.SetPsk(kPsk, sizeof(kPsk)));
270 dtls0.SetReceiveCallback(HandleReceive, &node0);
271 dtls0.SetConnectCallback(HandleConnectEvent, &node0);
272 SuccessOrQuit(dtls0.Open());
273 SuccessOrQuit(dtls0.Bind(kUdpPort));
274
275 nexus.AdvanceTime(1 * Time::kOneSecondInMsec);
276
277 VerifyOrQuit(dtls0.GetUdpPort() == kUdpPort);
278 VerifyOrQuit(!dtls0.IsConnectionActive());
279
280 sockAddr.SetAddress(node0.Get<Mle::Mle>().GetMeshLocalRloc());
281 sockAddr.SetPort(kUdpPort);
282
283 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
284 Log("Try to establish a DTLS connection from node 1 using a wrong PSK multiple times");
285
286 SuccessOrQuit(dtls1.SetPsk(kPsk, sizeof(kPsk) - 1));
287 dtls1.SetReceiveCallback(HandleReceive, &node1);
288 dtls1.SetConnectCallback(HandleConnectEvent, &node1);
289 SuccessOrQuit(dtls1.Open());
290
291 for (uint16_t iter = 0; iter <= kMaxAttempts + 1; iter++)
292 {
293 memset(sDtlsEvent, Dtls::Session::kConnected, sizeof(sDtlsEvent));
294
295 SuccessOrQuit(dtls1.Connect(sockAddr));
296 nexus.AdvanceTime(3 * Time::kOneSecondInMsec);
297
298 VerifyOrQuit(!dtls0.IsConnected());
299 VerifyOrQuit(!dtls1.IsConnected());
300
301 VerifyOrQuit(sDtlsEvent[node0.GetId()] == Dtls::Session::kDisconnectedError);
302 VerifyOrQuit(sDtlsEvent[node1.GetId()] == Dtls::Session::kDisconnectedError);
303 }
304
305 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
306 Log("Establish a DTLS connection from node1 with node0 using the correct PSK");
307
308 dtls1.Close();
309
310 SuccessOrQuit(dtls1.SetPsk(kPsk, sizeof(kPsk)));
311 dtls1.SetReceiveCallback(HandleReceive, &node1);
312 dtls1.SetConnectCallback(HandleConnectEvent, &node1);
313 SuccessOrQuit(dtls1.Open());
314 SuccessOrQuit(dtls1.Connect(sockAddr));
315
316 nexus.AdvanceTime(1 * Time::kOneSecondInMsec);
317
318 VerifyOrQuit(dtls0.IsConnected());
319 VerifyOrQuit(dtls1.IsConnected());
320
321 VerifyOrQuit(sDtlsEvent[node0.GetId()] == Dtls::Session::kConnected);
322 VerifyOrQuit(sDtlsEvent[node1.GetId()] == Dtls::Session::kConnected);
323
324 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
325 Log("Send message (random data and length) over DTLS session from node0 to node1");
326
327 for (uint16_t iter = 0; iter < 20; iter++)
328 {
329 OwnedPtr<Message> msg(PrepareMessage(node0));
330
331 SuccessOrQuit(dtls0.Send(*msg->Clone()));
332 nexus.AdvanceTime(100);
333
334 VerifyOrQuit(sDtlsLastReceive[node1.GetId()].GetLength() == msg->GetLength());
335 VerifyOrQuit(msg->CompareBytes(0, sDtlsLastReceive[node1.GetId()].GetArrayBuffer(), msg->GetLength()));
336 }
337
338 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
339 Log("Now send from node1 to node0");
340
341 for (uint16_t iter = 0; iter < 20; iter++)
342 {
343 OwnedPtr<Message> msg(PrepareMessage(node1));
344
345 SuccessOrQuit(dtls1.Send(*msg->Clone()));
346 nexus.AdvanceTime(100);
347
348 VerifyOrQuit(sDtlsLastReceive[node0.GetId()].GetLength() == msg->GetLength());
349 VerifyOrQuit(msg->CompareBytes(0, sDtlsLastReceive[node0.GetId()].GetArrayBuffer(), msg->GetLength()));
350 }
351
352 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
353 Log("Disconnect from node1 - validate the disconnect events (local/peer)");
354
355 dtls1.Disconnect();
356
357 nexus.AdvanceTime(3 * Time::kOneSecondInMsec);
358
359 VerifyOrQuit(!dtls0.IsConnected());
360 VerifyOrQuit(!dtls1.IsConnected());
361
362 VerifyOrQuit(sDtlsEvent[node0.GetId()] == Dtls::Session::kDisconnectedPeerClosed);
363 VerifyOrQuit(sDtlsEvent[node1.GetId()] == Dtls::Session::kDisconnectedLocalClosed);
364
365 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
366 Log("Establish a DTLS connection again");
367
368 SuccessOrQuit(dtls1.Connect(sockAddr));
369
370 nexus.AdvanceTime(1 * Time::kOneSecondInMsec);
371
372 VerifyOrQuit(dtls0.IsConnected());
373 VerifyOrQuit(dtls1.IsConnected());
374
375 VerifyOrQuit(sDtlsEvent[node0.GetId()] == Dtls::Session::kConnected);
376 VerifyOrQuit(sDtlsEvent[node1.GetId()] == Dtls::Session::kConnected);
377
378 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
379 Log("Try to connect from node2 - validate that it fails to connect since already connected");
380
381 SuccessOrQuit(dtls2.SetPsk(kPsk, sizeof(kPsk)));
382 dtls2.SetReceiveCallback(HandleReceive, &node2);
383 dtls2.SetReceiveCallback(HandleReceive, &node2);
384 SuccessOrQuit(dtls2.Open());
385 SuccessOrQuit(dtls2.Connect(sockAddr));
386
387 nexus.AdvanceTime(20 * Time::kOneSecondInMsec);
388
389 VerifyOrQuit(dtls0.IsConnected());
390 VerifyOrQuit(dtls1.IsConnected());
391 VerifyOrQuit(!dtls2.IsConnected());
392
393 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
394 Log("Disconnect from node0 - validate the disconnect events");
395
396 dtls0.Disconnect();
397
398 nexus.AdvanceTime(3 * Time::kOneSecondInMsec);
399
400 VerifyOrQuit(!dtls0.IsConnected());
401 VerifyOrQuit(!dtls1.IsConnected());
402 VerifyOrQuit(!dtls2.IsConnected());
403
404 VerifyOrQuit(sDtlsEvent[node0.GetId()] == Dtls::Session::kDisconnectedLocalClosed);
405 VerifyOrQuit(sDtlsEvent[node1.GetId()] == Dtls::Session::kDisconnectedPeerClosed);
406
407 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
408
409 dtls0.Close();
410 dtls1.Close();
411 dtls2.Close();
412
413 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
414
415 Log("Start DTLS (server) on node0 bound to port %u with auto-close max attempt %u", kUdpPort, kMaxAttempts);
416
417 memset(sDtlsAutoClosed, false, sizeof(sDtlsAutoClosed));
418
419 SuccessOrQuit(dtls0.SetMaxConnectionAttempts(kMaxAttempts, HandleAutoClose, &node0));
420 SuccessOrQuit(dtls0.SetPsk(kPsk, sizeof(kPsk)));
421 dtls0.SetReceiveCallback(HandleReceive, &node0);
422 dtls0.SetConnectCallback(HandleConnectEvent, &node0);
423 SuccessOrQuit(dtls0.Open());
424 SuccessOrQuit(dtls0.Bind(kUdpPort));
425
426 nexus.AdvanceTime(1 * Time::kOneSecondInMsec);
427
428 VerifyOrQuit(dtls0.GetUdpPort() == kUdpPort);
429 VerifyOrQuit(!dtls0.IsConnectionActive());
430
431 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
432 Log("Using wrong PSK try to establish DTLS connection with node0 %u times", kMaxAttempts - 1);
433
434 SuccessOrQuit(dtls1.SetPsk(kPsk, sizeof(kPsk) - 1));
435 dtls1.SetReceiveCallback(HandleReceive, &node1);
436 dtls1.SetConnectCallback(HandleConnectEvent, &node1);
437 SuccessOrQuit(dtls1.Open());
438
439 for (uint16_t iter = 0; iter < kMaxAttempts - 1; iter++)
440 {
441 memset(sDtlsEvent, Dtls::Session::kConnected, sizeof(sDtlsEvent));
442
443 SuccessOrQuit(dtls1.Connect(sockAddr));
444 nexus.AdvanceTime(3 * Time::kOneSecondInMsec);
445
446 VerifyOrQuit(!dtls0.IsConnected());
447 VerifyOrQuit(!dtls1.IsConnected());
448
449 VerifyOrQuit(sDtlsEvent[node0.GetId()] == Dtls::Session::kDisconnectedError);
450 VerifyOrQuit(sDtlsEvent[node1.GetId()] == Dtls::Session::kDisconnectedError);
451 }
452
453 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
454 Log("Using wrong PSK try one last time, validate the auto-close behavior");
455
456 memset(sDtlsEvent, Dtls::Session::kConnected, sizeof(sDtlsEvent));
457
458 SuccessOrQuit(dtls1.Connect(sockAddr));
459 nexus.AdvanceTime(3 * Time::kOneSecondInMsec);
460
461 VerifyOrQuit(sDtlsEvent[node0.GetId()] == Dtls::Session::kDisconnectedError);
462 VerifyOrQuit(sDtlsEvent[node1.GetId()] == Dtls::Session::kDisconnectedError);
463
464 VerifyOrQuit(sDtlsAutoClosed[node0.GetId()]);
465
466 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
467
468 dtls0.Close();
469 dtls1.Close();
470 dtls2.Close();
471 }
472 }
473
TestDtlsMultiSession(void)474 void TestDtlsMultiSession(void)
475 {
476 Core nexus;
477 Node &node0 = nexus.CreateNode();
478 Node &node1 = nexus.CreateNode();
479 Node &node2 = nexus.CreateNode();
480
481 Log("------------------------------------------------------------------------------------------------------");
482 Log("TestDtlsMultiSession");
483
484 nexus.AdvanceTime(0);
485
486 // Form the topology: node0 leader, with node1 & node2 as its FTD children
487
488 node0.Form();
489 nexus.AdvanceTime(50 * Time::kOneSecondInMsec);
490 VerifyOrQuit(node0.Get<Mle::Mle>().IsLeader());
491
492 SuccessOrQuit(node1.Get<Mle::MleRouter>().SetRouterEligible(false));
493 node1.Join(node0);
494 nexus.AdvanceTime(20 * Time::kOneSecondInMsec);
495 VerifyOrQuit(node1.Get<Mle::Mle>().IsChild());
496
497 SuccessOrQuit(node2.Get<Mle::MleRouter>().SetRouterEligible(false));
498 node2.Join(node0);
499 nexus.AdvanceTime(20 * Time::kOneSecondInMsec);
500 VerifyOrQuit(node2.Get<Mle::Mle>().IsChild());
501
502 {
503 DtlsTransportAndHeapSession dtls0(node0);
504 DtlsTransportAndSingleSession dtls1(node1);
505 DtlsTransportAndSingleSession dtls2(node2);
506 Ip6::SockAddr sockAddr;
507 uint16_t numSessions;
508
509 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
510 Log("Start DTLS (server) on node0 bound to port %u", kUdpPort);
511
512 SuccessOrQuit(dtls0.SetPsk(kPsk, sizeof(kPsk)));
513 SuccessOrQuit(dtls0.Open());
514 SuccessOrQuit(dtls0.Bind(kUdpPort));
515
516 nexus.AdvanceTime(1 * Time::kOneSecondInMsec);
517
518 VerifyOrQuit(dtls0.GetUdpPort() == kUdpPort);
519
520 sockAddr.SetAddress(node0.Get<Mle::Mle>().GetMeshLocalRloc());
521 sockAddr.SetPort(kUdpPort);
522
523 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
524 Log("Establish a DTLS connection with node 0 from node1");
525
526 memset(sDtlsEvent, Dtls::Session::kDisconnectedError, sizeof(sDtlsEvent));
527
528 SuccessOrQuit(dtls1.SetPsk(kPsk, sizeof(kPsk)));
529 dtls1.SetReceiveCallback(HandleReceive, &node1);
530 dtls1.SetConnectCallback(HandleConnectEvent, &node1);
531 SuccessOrQuit(dtls1.Open());
532 SuccessOrQuit(dtls1.Connect(sockAddr));
533
534 nexus.AdvanceTime(1 * Time::kOneSecondInMsec);
535
536 VerifyOrQuit(dtls1.IsConnected());
537
538 VerifyOrQuit(sDtlsEvent[node0.GetId()] == Dtls::Session::kConnected);
539 VerifyOrQuit(sDtlsEvent[node1.GetId()] == Dtls::Session::kConnected);
540
541 numSessions = 0;
542
543 for (MeshCoP::SecureSession &session : dtls0.GetSessions())
544 {
545 VerifyOrQuit(session.IsConnected());
546 numSessions++;
547 }
548
549 VerifyOrQuit(numSessions == 1);
550 VerifyOrQuit(sHeapSessionsAllocated == 1);
551
552 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
553 Log("Establish a second DTLS connection with node0 from node2");
554
555 memset(sDtlsEvent, Dtls::Session::kDisconnectedError, sizeof(sDtlsEvent));
556
557 SuccessOrQuit(dtls2.SetPsk(kPsk, sizeof(kPsk)));
558 dtls2.SetReceiveCallback(HandleReceive, &node2);
559 dtls2.SetConnectCallback(HandleConnectEvent, &node2);
560 SuccessOrQuit(dtls2.Open());
561 SuccessOrQuit(dtls2.Connect(sockAddr));
562
563 nexus.AdvanceTime(1 * Time::kOneSecondInMsec);
564
565 VerifyOrQuit(dtls2.IsConnected());
566
567 VerifyOrQuit(sDtlsEvent[node0.GetId()] == Dtls::Session::kConnected);
568 VerifyOrQuit(sDtlsEvent[node2.GetId()] == Dtls::Session::kConnected);
569
570 numSessions = 0;
571
572 for (MeshCoP::SecureSession &session : dtls0.GetSessions())
573 {
574 VerifyOrQuit(session.IsConnected());
575 numSessions++;
576 }
577
578 VerifyOrQuit(numSessions == 2);
579 VerifyOrQuit(sHeapSessionsAllocated == 2);
580
581 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
582 Log("Disconnect from node1 - validate the disconnect events");
583
584 dtls1.Disconnect();
585
586 nexus.AdvanceTime(3 * Time::kOneSecondInMsec);
587
588 VerifyOrQuit(!dtls1.IsConnected());
589
590 VerifyOrQuit(sDtlsEvent[node0.GetId()] == Dtls::Session::kDisconnectedPeerClosed);
591 VerifyOrQuit(sDtlsEvent[node1.GetId()] == Dtls::Session::kDisconnectedLocalClosed);
592
593 numSessions = 0;
594
595 for (MeshCoP::SecureSession &session : dtls0.GetSessions())
596 {
597 VerifyOrQuit(session.IsConnected());
598 numSessions++;
599 }
600
601 VerifyOrQuit(numSessions == 1);
602 VerifyOrQuit(sHeapSessionsAllocated == 1);
603
604 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
605 Log("Disconnect session with node2 from node0 (server) - validate the disconnect events");
606
607 memset(sDtlsEvent, Dtls::Session::kConnected, sizeof(sDtlsEvent));
608
609 dtls0.GetSessions().GetHead()->Disconnect();
610
611 nexus.AdvanceTime(3 * Time::kOneSecondInMsec);
612
613 VerifyOrQuit(!dtls2.IsConnected());
614
615 VerifyOrQuit(sDtlsEvent[node0.GetId()] == Dtls::Session::kDisconnectedLocalClosed);
616 VerifyOrQuit(sDtlsEvent[node2.GetId()] == Dtls::Session::kDisconnectedPeerClosed);
617
618 VerifyOrQuit(dtls0.GetSessions().IsEmpty());
619 VerifyOrQuit(sHeapSessionsAllocated == 0);
620
621 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
622 Log("Establish two DTLS connections from node1 and node2 at the same time");
623
624 memset(sDtlsEvent, Dtls::Session::kDisconnectedError, sizeof(sDtlsEvent));
625
626 SuccessOrQuit(dtls1.Connect(sockAddr));
627 SuccessOrQuit(dtls2.Connect(sockAddr));
628
629 nexus.AdvanceTime(1 * Time::kOneSecondInMsec);
630
631 VerifyOrQuit(dtls1.IsConnected());
632 VerifyOrQuit(dtls2.IsConnected());
633
634 VerifyOrQuit(sDtlsEvent[node0.GetId()] == Dtls::Session::kConnected);
635 VerifyOrQuit(sDtlsEvent[node1.GetId()] == Dtls::Session::kConnected);
636 VerifyOrQuit(sDtlsEvent[node2.GetId()] == Dtls::Session::kConnected);
637
638 numSessions = 0;
639
640 for (MeshCoP::SecureSession &session : dtls0.GetSessions())
641 {
642 VerifyOrQuit(session.IsConnected());
643 numSessions++;
644 }
645
646 VerifyOrQuit(numSessions == 2);
647 VerifyOrQuit(sHeapSessionsAllocated == 2);
648 }
649 }
650
651 } // namespace Nexus
652 } // namespace ot
653
main(void)654 int main(void)
655 {
656 ot::Nexus::TestDtlsSingleSession();
657 ot::Nexus::TestDtlsMultiSession();
658 printf("All tests passed\n");
659 return 0;
660 }
661