A Discrete-Event Network Simulator
API
qkd-app-004.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2020 DOTFEESA www.tk.etf.unsa.ba
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Emir Dervisevic <emir.dervisevic@etf.unsa.ba>
19  * Miralem Mehic <miralem.mehic@ieee.org>
20  */
21 
22 #include "ns3/address.h"
23 #include "ns3/address-utils.h"
24 #include "ns3/log.h"
25 #include "ns3/inet-socket-address.h"
26 #include "ns3/inet6-socket-address.h"
27 #include "ns3/node.h"
28 #include "ns3/socket.h"
29 #include "ns3/udp-socket-factory.h"
30 #include "ns3/tcp-socket-factory.h"
31 #include "ns3/simulator.h"
32 #include "ns3/socket-factory.h"
33 #include "ns3/packet.h"
34 #include "ns3/trace-source-accessor.h"
35 #include "qkd-app-004.h"
36 
37 namespace ns3 {
38 
39 NS_LOG_COMPONENT_DEFINE ("QKDApp004");
40 
41 NS_OBJECT_ENSURE_REGISTERED (QKDApp004);
42 
43 TypeId
45 {
46  static TypeId tid = TypeId ("ns3::QKDApp004")
48  .SetGroupName("Applications")
49  .AddConstructor<QKDApp004> ()
50  .AddAttribute ("Protocol", "The type of protocol to use.",
54  .AddAttribute ("LengthOfAuthenticationTag",
55  "The default length of the authentication tag",
56  UintegerValue (256), //32 bytes
58  MakeUintegerChecker<uint32_t> ())
59  .AddAttribute ("EncryptionType",
60  "The type of encryption to be used (0-unencrypted, 1-OTP, 2-AES)",
61  UintegerValue (2),
63  MakeUintegerChecker<uint32_t> ())
64  .AddAttribute ("AuthenticationType",
65  "The type of authentication to be used (0-unauthenticated, 1-VMAC, 2-MD5, 3-SHA1)",
66  UintegerValue (3),
68  MakeUintegerChecker<uint32_t> ())
69  .AddAttribute ("AESLifetime",
70  "Lifetime of AES key expressed in number of packets",
71  UintegerValue (1),
73  MakeUintegerChecker<uint32_t> ())
74  .AddAttribute ("UseCrypto",
75  "Should crypto functions be performed (0-No, 1-Yes)",
76  UintegerValue (0),
78  MakeUintegerChecker<uint32_t> ())
79  .AddAttribute ("LengthOfKeyBufferForEncryption",
80  "How many keys to store in local buffer of QKDApp004 for encryption?",
81  UintegerValue (10),
83  MakeUintegerChecker<uint32_t> ())
84  .AddAttribute ("LengthOfKeyBufferForAuthentication",
85  "How many keys to store in local buffer of QKDApp004 for authentication?",
86  UintegerValue (10),
88  MakeUintegerChecker<uint32_t> ())
89  .AddAttribute ("SocketToKMSHoldTime","How long (seconds) should QKDApp004 wait to close socket to KMS after receiving REST response?",
90  TimeValue (Seconds (0.5)),
92  MakeTimeChecker ())
93  .AddAttribute ("MaliciousApplication",
94  "Is this application malicious?",
95  UintegerValue (0), //default value: NO/FALSE
97  MakeUintegerChecker<uint32_t> ())
98  .AddAttribute ("DoSAttackIntensity",
99  "The time elapsed between successive malicious requests; For testing DoS/DDoS attacks;",
100  TimeValue (Seconds (0.1)), //default value: 100ms
102  MakeTimeChecker())
103  .AddAttribute ("MinDataRate", "The minimal data key rate (encryption+authentication) of the app (QoS settings).",
104  DataRateValue (DataRate ("0kb/s")),
107 
108  .AddAttribute ("Priority",
109  "QoS Priority (0 - default, 1 - premium)",
110  UintegerValue (0),
112  MakeUintegerChecker<uint32_t> ())
113  .AddAttribute ("TTL",
114  "QoS TTL - defines duration (seconds) of ETSI004 association",
115  UintegerValue (5),
117  MakeUintegerChecker<uint32_t> ())
118 
119 
120  .AddTraceSource ("Tx", "A new packet is created and is sent",
122  "ns3::Packet::TracedCallback")
123  .AddTraceSource ("TxSig", "A new signaling packet is created and is sent",
125  "ns3::Packet::TracedCallback")
126  .AddTraceSource ("TxKMS", "A new packet is created and is sent to local KMS",
128  "ns3::Packet::TracedCallback")
129  .AddTraceSource ("Rx", "A new packet is received",
131  "ns3::Packet::TracedCallback")
132  .AddTraceSource ("RxSig", "A new signaling packet is received",
134  "ns3::Packet::TracedCallback")
135  .AddTraceSource ("RxKMS", "A new packet is received from local KMS",
137  "ns3::Packet::TracedCallback")
138  .AddTraceSource ("StateTransition",
139  "Trace fired upon every QKDApp state transition.",
141  "ns3::Application::StateTransitionCallback")
142  .AddTraceSource ("PacketEncrypted",
143  "The change trance for currenly ecrypted packet",
145  "ns3::QKDCrypto::PacketEncrypted")
146  .AddTraceSource ("PacketDecrypted",
147  "The change trance for currenly decrypted packet",
149  "ns3::QKDCrypto::PacketDecrypted")
150  .AddTraceSource ("PacketAuthenticated",
151  "The change trance for currenly authenticated packet",
153  "ns3::QKDCrypto::PacketAuthenticated")
154  .AddTraceSource ("PacketDeAuthenticated",
155  "The change trance for currenly deauthenticated packet",
157  "ns3::QKDCrypto::PacketDeAuthenticated")
158  .AddTraceSource ("Mx", "Missed send packet call",
160  "ns3::Packet::TracedCallback")
161  .AddTraceSource ("KeyObtained", "Trace amount of obtained key material",
163  "ns3::QKDApp004::KeyObtained")
164  ;
165 
166  return tid;
167 }
168 
169 
170 uint32_t QKDApp004::m_applicationCounts = 0;
171 
181  : m_sendSignalingSocketApp (0),
182  m_sinkSignalingSocketApp (0),
183  m_sendDataSocketApp (0),
184  m_sinkDataSocketApp (0),
185  m_sendSocketToKMS (0),
186  m_sinkSocketFromKMS (0),
187  m_packetSize (0),
188  m_dataRate (0),
189  m_sendEvent (),
190  m_packetsSent (0),
191  m_dataSent (0),
192  m_master (0),
193  m_encryptor (0),
194  m_appState (NOT_STARTED)
195 {
197  m_id = UUID::Random();
198  m_random = CreateObject<UniformRandomVariable> ();
199 }
200 
202 {
203  //Data sockets
206  //Signaling sockets
209  //KMS sockets
210  m_sendSocketToKMS = 0;
212 }
213 
214 void
216  std::string socketType,
217  Address src,
218  Address dst,
219  Address kms,
220  UUID dstSaeId,
221  std::string type
222 ){
223  Setup(
224  socketType,
225  src,
226  dst,
227  kms,
228  dstSaeId,
229  0,
230  0,
231  DataRate ("0bps"),
232  type
233  );
234 }
235 
236 void
238  std::string socketType,
239  Address src,
240  Address dst,
241  Address kms,
242  UUID dstSaeId,
243  uint32_t packetSize,
244  uint32_t nPacketsSize,
245  DataRate dataRate,
246  std::string type
247 ){
248 
249  NS_LOG_FUNCTION(this << type << src << dst << packetSize << nPacketsSize << dataRate.GetBitRate());
250 
251  if(type == "alice"){
252  m_master = 1;
254  NS_ASSERT(dataRate.GetBitRate() > 0);
255  }else{
256  m_master = 0;
257  }
258 
259  m_local = src;
260  m_peer = dst;
261  m_kms = kms;
262  m_dstSaeId = dstSaeId;
263 
266  7080
267  );
270  7080
271  );
272 
274  m_dataRate = dataRate;
275  m_socketType = socketType;
276 
277 
280 
281 }
282 
290 void
292 {
293  NS_LOG_FUNCTION (this << m_appState);
294 
296  {
297  //NS_LOG_FUNCTION (this << "QKDApp is running!");
298  m_delay = m_packetSize * 8 / static_cast<double> (m_dataRate.GetBitRate ());
299  //NS_LOG_FUNCTION( this << "delay" << Seconds (delay) );
300  Time tNext (Seconds (m_delay));
302  } else {
303  NS_LOG_FUNCTION (this << "QKDApp is" << GetAppStateString(m_appState));
304  }
305 }
306 
307 void
309 {
310  NS_LOG_FUNCTION(this << eventId);
311 
312  std::map<uint32_t, EventId >::iterator eventEntry = m_scheduledEvents.find ( eventId );
313  if(eventEntry != m_scheduledEvents.end ()){
314  Simulator::Cancel (eventEntry->second);
315  }else{
316  NS_FATAL_ERROR ("Invalid entryId " << eventId );
317  }
318 
319 }
320 
321 
329 void
331 {
332  NS_LOG_FUNCTION(this);
333 
334  if(m_sinkSocketFromKMS == 0){
335  Address localAddress = InetSocketAddress(
336  //InetSocketAddress::ConvertFrom(m_kms).GetIpv4 (),
338  82
339  //InetSocketAddress::ConvertFrom(m_kms).GetPort ()+1
340  );
342 
343  if (m_sinkSocketFromKMS->Bind (localAddress) == -1)
344  NS_FATAL_ERROR ("Failed to bind socket");
345 
352  );
356  );
357  NS_LOG_FUNCTION (this << "Create new APP socket " << m_sinkSocketFromKMS
358  << " to listen packets from KMS on " << InetSocketAddress::ConvertFrom(localAddress).GetIpv4 ()
359  << " and port " << InetSocketAddress::ConvertFrom(localAddress).GetPort ()
360  );
361  }else{
362  NS_LOG_FUNCTION (this << "Socket to listen from local KMS exists!" << m_sinkSocketFromKMS);
363  }
364 
365 }
366 
367 void
369 {
370  NS_LOG_FUNCTION(this);
371 
372  if(m_sendSocketToKMS == 0)
374 
375  Address temp;
376  if(m_sendSocketToKMS->GetPeerName (temp) != 0) {
377  Address lkmsAddress = InetSocketAddress(
380  );
389  );
390  m_sendSocketToKMS->Connect ( lkmsAddress );
392  NS_LOG_FUNCTION (this << "Create new APP socket " << m_sendSocketToKMS << " to reach local KMS at "
393  << InetSocketAddress::ConvertFrom(m_kms).GetIpv4 () << ":" << InetSocketAddress::ConvertFrom(m_kms).GetPort ()
394  << "!");
395  }else{
396  NS_LOG_FUNCTION (this << "Active socket to reach local KMS exists!" << m_sendSocketToKMS);
397  }
398 
399 }
400 
401 void
403 {
404  NS_LOG_FUNCTION(this);
405 
407 
408  if(m_sendSignalingSocketApp == 0){
409 
410  if(m_socketType == "tcp"){
412  }else{
414  }
415 
416  NS_LOG_FUNCTION (this << "m_sendSignalingSocketApp:" << m_sendSignalingSocketApp
419  );
420 
425  }
426 
427  if(m_sendDataSocketApp == 0){
428 
429  if(m_socketType == "tcp"){
431  }else{
433  }
434 
435  NS_LOG_FUNCTION (this << "m_sendDataSocketApp:" << m_sendDataSocketApp
438  );
439 
444  }
445 
446  }else{
447  NS_LOG_FUNCTION (this << "Socket to reach peer app exists!" << m_sendSignalingSocketApp);
448  }
449 }
450 
451 void
453 {
454  NS_LOG_FUNCTION(this);
455 
456  if(m_sinkSignalingSocketApp == 0){
457 
458  if(m_socketType == "tcp")
460  else
462 
463  NS_LOG_FUNCTION (this << "m_sinkSignalingSocketApp:" << m_sinkSignalingSocketApp
466  );
467 
469  NS_FATAL_ERROR ("Failed to bind socket");
470 
475  MakeNullCallback<bool, Ptr<Socket>, const Address &> (),
477  );
481  );
482 
483  }else{
484  NS_LOG_FUNCTION (this << "Socket to listen signaling from peer app exists!" << m_sinkSignalingSocketApp);
485  }
486 
487 
488  if(m_sinkDataSocketApp == 0){
489 
490  if(m_socketType == "tcp")
492  else
494 
495  NS_LOG_FUNCTION (this << "m_sinkDataSocketApp:" << m_sinkDataSocketApp
498  );
499 
500  if (m_sinkDataSocketApp->Bind (m_local) == -1)
501  NS_FATAL_ERROR ("Failed to bind socket");
502 
507  MakeNullCallback<bool, Ptr<Socket>, const Address &> (),
509  );
513  );
514  }else{
515  NS_LOG_FUNCTION (this << "Socket to listen data from peer app exists!" << m_sinkSignalingSocketApp);
516  }
517 
518 }
519 
520 bool
522 {
523  NS_LOG_FUNCTION (this << socket << from
524  << InetSocketAddress::ConvertFrom(from).GetIpv4 ()
525  << InetSocketAddress::ConvertFrom(from).GetPort ()
526  );
527  NS_LOG_FUNCTION (this << "QKDApp Connection from KMS requested on socket " << socket);
528  return true; // Unconditionally accept the connection request.
529 
530 }
531 
532 void
534 {
535  Address peer;
536  NS_LOG_FUNCTION (this << socket << from
537  << InetSocketAddress::ConvertFrom(from).GetIpv4 ()
538  << InetSocketAddress::ConvertFrom(from).GetPort ()
539  );
540  NS_LOG_FUNCTION (this << "QKDApp Connection from KMS accepted on socket " << socket);
543 }
544 
545 void
547 {
548  NS_LOG_FUNCTION (this << s << from
549  << InetSocketAddress::ConvertFrom(from).GetIpv4 ()
550  << InetSocketAddress::ConvertFrom(from).GetPort ()
551  );
552 
553  NS_LOG_FUNCTION (this << "QKDApp Connection from APP accepted on socket " << s);
555 }
556 
557 void
559 {
560  NS_LOG_FUNCTION (this << s << from
561  << InetSocketAddress::ConvertFrom(from).GetIpv4 ()
562  << InetSocketAddress::ConvertFrom(from).GetPort ()
563  );
564 
565  NS_LOG_FUNCTION (this << "QKDApp Signaling Connection from APP accepted on socket " << s);
567 }
568 
569 void
571 {
572  NS_LOG_FUNCTION (this << socket << "QKDApp Connection to KMS succeeded via socket " << socket);
573 }
574 
575 void
577 {
578  NS_LOG_FUNCTION (this << socket << "QKDApp, Connection to KMS Failed via socket " << socket);
579 }
580 
581 void
583 {
584  NS_LOG_FUNCTION (this << socket << "QKDApp Connection to APP succeeded via socket " << socket);
585 }
586 
587 void
589 {
590  NS_LOG_FUNCTION (this << socket << "QKDApp, Connection to APP Failed via socket " << socket);
591 }
592 
593 void
595 {
596  NS_LOG_FUNCTION (this << socket << "QKDApp Signaling Connection to APP succeeded via socket " << socket);
597 }
598 
599 void
601 {
602  NS_LOG_FUNCTION (this << socket << "QKDApp, Connection to APP Failed via socket " << socket);
603 }
604 
605 void
607 {
608  NS_LOG_FUNCTION (this << socket);
609 }
610 
611 void
613 {
614  NS_LOG_FUNCTION (this << socket);
615 }
616 
617 void
619 {
620  NS_LOG_FUNCTION (this << socket);
621  if(socket == m_sendSocketToKMS) {
623  MakeNullCallback<void, Ptr<Socket> > (),
624  MakeNullCallback<void, Ptr<Socket> > ()
625  );
627  MakeNullCallback<void, Ptr<Socket> > (),
628  MakeNullCallback<void, Ptr<Socket> > ()
629  );
630  m_sendSocketToKMS = 0;
631  }
632 }
633 
634 void
636 {
637  NS_LOG_FUNCTION (this << socket);
638  if(socket == m_sendSocketToKMS) {
640  MakeNullCallback<void, Ptr<Socket> > (),
641  MakeNullCallback<void, Ptr<Socket> > ()
642  );
644  MakeNullCallback<void, Ptr<Socket> > (),
645  MakeNullCallback<void, Ptr<Socket> > ()
646  );
647  m_sendSocketToKMS = 0;
648  }
649 }
650 
651 void
653 {
654  NS_LOG_FUNCTION (this << socket);
655 }
656 void
658 {
659  NS_LOG_FUNCTION (this << socket);
660 }
661 
662 void
664 {
665  NS_LOG_FUNCTION (this << socket);
666 }
667 
668 void
670 {
671  NS_LOG_FUNCTION (this << socket);
672 }
673 
674 void
676 {
677  NS_LOG_FUNCTION (this << socket);
678 
679  Ptr<Packet> packet;
680  Address from;
681  while ((packet = socket->RecvFrom (from)))
682  {
683  if (packet->GetSize () == 0)
684  { //EOF
685  break;
686  }
687 
688  NS_LOG_FUNCTION (this
689  << packet << "PACKETID: " << packet->GetUid()
690  << " of size: " << packet->GetSize()
691  );
692 
694  {
695  NS_LOG_FUNCTION("At time " << Simulator::Now ().GetSeconds ()
696  << "s packet from KMS received "
697  << packet->GetSize () << " bytes from "
699  << " port " << InetSocketAddress::ConvertFrom (from).GetPort ()
700  );
701  }
702  PacketReceivedFromKMS (packet, from, socket);
703  }
704 
705  if(m_queue_kms.size() == 0){
706  NS_LOG_FUNCTION(this << "Close socket to KMS!");
707  if (m_sendSocketToKMS) {
708  Time tNext (m_holdTime);
710  }
711  }else{
714  }
715 }
716 
717 void
719 
720  NS_LOG_FUNCTION(this);
721  if (m_sendSocketToKMS && m_queue_kms.size() == 0) {
723  m_sendSocketToKMS = 0;
724  }
725 }
726 
727 void
729 
730  NS_LOG_FUNCTION (this << m_queue_kms.size() );
731 
732  //check whether the socket to KMS is active and connected
733  Address temp;
734  if(m_sendSocketToKMS == 0 || m_sendSocketToKMS->GetPeerName (temp) != 0) {
736  }else{
737  if(m_queue_kms.size() > 0){
738  uint32_t c = 0;
739  auto it = m_queue_kms.begin();
740  while (it != m_queue_kms.end())
741  {
742  NS_LOG_FUNCTION(this << c << m_queue_kms.size() << it->keyType );
743  Http004KMSQuery(it->uri, it->ksid, it->keyType);
744 
745  if(it->packet != 0) {
746  m_txKmsTrace (it->packet);
747  m_sendSocketToKMS->Send(it->packet);
748  }
749  m_queue_kms.erase(it);
750  c++;
751  }
752  }
753  }
754 }
755 
756 void
758 {
759  NS_LOG_FUNCTION ( this << p->GetUid() << p->GetSize() << from );
760  std::string receivedStatus = p->ToString();
761  NS_LOG_FUNCTION ( this << "\n\n\n" << p->GetUid() << p->GetSize() << receivedStatus << from );
762 
763  if(m_malicious)
764  return; //Malicious application does not process responses, it only overwhelms KMS by requests
765 
766  Ptr<Packet> buffer;
767  if (receivedStatus.find("Fragment") != std::string::npos) {
768  auto itBuffer = m_buffer_kms.find (from);
769  if (itBuffer == m_buffer_kms.end ()){
770  itBuffer = m_buffer_kms.insert (
771  std::make_pair (from, Create<Packet> (0))
772  ).first;
773  }
774  buffer = itBuffer->second;
775  buffer->AddAtEnd (p);
776  }else{
777  NS_LOG_FUNCTION(this << "Full packet received!");
778  buffer = p;
779  }
780 
781  HTTPMessageParser parser;
782  HTTPMessage request;
783 
784  //copy buffer payload to string
785  uint8_t *b1 = new uint8_t[buffer->GetSize ()];
786  buffer->CopyData(b1, buffer->GetSize ());
787  std::string requestString = std::string((char*)b1);
788  delete[] b1;
789 
790  NS_LOG_FUNCTION(this << "CONTENT OF THE BUFFER: \n" << requestString);
791 
792  NS_LOG_FUNCTION(this << "Packet payload:" << requestString);
793 
794  //parse HTTP message
795  parser.Parse(&request, requestString);
796  if(request.IsFragmented() || request.GetStatusMessage() == "Undefined")
797  {
798  NS_LOG_FUNCTION(this << "HTTP Content Parsed after merge with buffer: " << request.ToString() << "\n ***IsFragmented:" << request.IsFragmented() << "\n\n\n\n");
799  }else{
800  NS_LOG_FUNCTION(this << "Full packet received:" << request.ToString() );
801  }
802  NS_LOG_FUNCTION(this << "HTTPMessage Size:" << request.GetSize());
803 
804  while (buffer->GetSize () >= request.GetSize())
805  {
806  NS_LOG_DEBUG ("Parsing packet pid(" << p->GetUid() << ") of size " << request.GetSize ()
807  << " (Header size:" << request.GetHeadersSize()
808  << " content length:" << request.GetContentLength()
809  << ") from buffer of size " << buffer->GetSize ()
810  );
811  Ptr<Packet> completePacket = buffer->CreateFragment (0, static_cast<uint32_t> (request.GetSize () ));
812 
813  uint8_t *b2 = new uint8_t[completePacket->GetSize ()];
814  completePacket->CopyData(b2, completePacket->GetSize ());
815  std::string completePacketString = std::string((char*)b2);
816 
817  HTTPMessage completePacketHttp;
818  parser.Parse(&completePacketHttp, completePacketString);
819  delete[] b2;
820 
821  NS_LOG_FUNCTION(this << "completePacketHttp" << completePacketHttp.IsFragmented());
822 
823  if(completePacketHttp.IsFragmented() == false){
824  NS_LOG_FUNCTION( this << "821: " << buffer->GetSize() << completePacketHttp.GetSize() << request.GetSize() << completePacketHttp.IsFragmented() );
825  NS_LOG_FUNCTION(this << "Croped HTTP message: " << completePacketHttp.ToString());
826 
827  buffer->RemoveAtStart (static_cast<uint32_t> (completePacketHttp.GetSize () ));
828  m_rxKmsTrace (completePacket);
829  ProcessResponseFromKMS(completePacketHttp, completePacket, socket);
830  }
831  NS_LOG_FUNCTION(this << "Croped HTTP message: " << completePacketHttp.ToString());
832  NS_LOG_FUNCTION(this << "Remains in the buffer " << buffer->GetSize () );
833  break;
834  }
835 }
836 
837 void
839 {
840  NS_LOG_FUNCTION (this << socket);
841 
842  Ptr<Packet> packet;
843  Address from;
844  while ((packet = socket->RecvFrom (from)))
845  {
846  if (packet->GetSize () == 0)
847  { //EOF
848  break;
849  }
850 
851  NS_LOG_FUNCTION (this << packet
852  << "PACKETID: " << packet->GetUid()
853  << " of size: " << packet->GetSize()
854  );
855 
857  {
858  NS_LOG_FUNCTION( this << "At time " << Simulator::Now ().GetSeconds ()
859  << "s packet from APP pair received "
860  << packet->GetSize () << " bytes from "
862  << " port " << InetSocketAddress::ConvertFrom (from).GetPort () << "\n");
863  }
864 
865  DataPacketReceivedFromApp (packet, from, socket);
866  }
867 }
868 
869 void
871 {
872  NS_LOG_FUNCTION ( this << m_master << p->GetUid() << p->GetSize() << from );
873 
874  if (m_master == 0) { //Process encrypted data on Replica QKDApp
875 
876  if (m_appState == READY) { //Replica QKDApp MUST be in ready state to receive data
877 
878  QKDAppHeader header;
879  Ptr<Packet> buffer;
880 
881  auto itBuffer = m_buffer_qkdapp.find (from);
882  if (itBuffer == m_buffer_qkdapp.end ())
883  {
884  itBuffer = m_buffer_qkdapp.insert (std::make_pair (from, Create<Packet> (0))).first;
885  }
886 
887  buffer = itBuffer->second;
888  buffer->AddAtEnd (p);
889  buffer->PeekHeader (header);
890 
891  NS_ABORT_IF (header.GetLength () == 0);
892 
893  while (buffer->GetSize () >= header.GetLength ())
894  {
895  NS_LOG_DEBUG ("Removing packet of size " << header.GetLength () << " from buffer of size " << buffer->GetSize ());
896  Ptr<Packet> completePacket = buffer->CreateFragment (0, static_cast<uint32_t> (header.GetLength ()));
897  buffer->RemoveAtStart (static_cast<uint32_t> (header.GetLength ()));
898 
899  m_txTrace (completePacket, m_associations.first.ksid);
900  m_txTrace (completePacket, m_associations.second.ksid);
901 
902  completePacket->RemoveHeader (header);
903  NS_LOG_FUNCTION(this << "RECEIVED QKDAPP HEADER: " << header);
904 
905  ProcessDataPacketFromApp(header, completePacket, socket);
906 
907  if (buffer->GetSize () > header.GetSerializedSize ())
908  {
909  buffer->PeekHeader (header);
910  }
911  else
912  {
913  break;
914  }
915  }
916 
917  } else {
918  NS_LOG_FUNCTION( this << "Primary/Replica:" << m_master << "Invalid state " << GetAppStateString() );
919  }
920  }
921 
922 }
923 
924 void
926 {
927  NS_LOG_FUNCTION (this << socket);
928 
929  Ptr<Packet> packet;
930  Address from;
931  while ((packet = socket->RecvFrom (from)))
932  {
933  if (packet->GetSize () == 0)
934  { //EOF
935  break;
936  }
937 
938  NS_LOG_FUNCTION (this << packet
939  << "PACKETID: " << packet->GetUid()
940  << " of size: " << packet->GetSize()
941  );
942 
944  {
945  NS_LOG_FUNCTION( this << "At time " << Simulator::Now ().GetSeconds ()
946  << "s signaling packet from APP pair received "
947  << packet->GetSize () << " bytes from "
949  << " port " << InetSocketAddress::ConvertFrom (from).GetPort () << "\n");
950  }
951 
952  SignalingPacketReceivedFromApp (packet, from, socket);
953  }
954 }
955 
956 void
958 {
959  NS_LOG_FUNCTION ( this << p->GetUid() << p->GetSize() << from );
960  std::string receivedStatus = p->ToString();
961  NS_LOG_FUNCTION ( this << "\n\n\n" << p->GetUid() << p->GetSize() << receivedStatus << from );
962 
963  Ptr<Packet> buffer;
964  if (receivedStatus.find("Fragment") != std::string::npos) {
965  auto itBuffer = m_buffer_sig.find (from);
966  if (itBuffer == m_buffer_sig.end ()){
967  itBuffer = m_buffer_sig.insert (
968  std::make_pair (from, Create<Packet> (0))
969  ).first;
970  }
971  buffer = itBuffer->second;
972  buffer->AddAtEnd (p);
973  }else{
974  NS_LOG_FUNCTION(this << "Full packet received!");
975  buffer = p;
976  }
977 
978  HTTPMessageParser parser;
979  HTTPMessage request;
980 
981  //copy buffer payload to string
982  uint8_t *b1 = new uint8_t[buffer->GetSize ()];
983  buffer->CopyData(b1, buffer->GetSize ());
984  std::string requestString = std::string((char*)b1);
985  delete[] b1;
986 
987  //parse HTTP message
988  parser.Parse(&request, requestString);
989  if(request.IsFragmented() || request.GetStatusMessage() == "Undefined")
990  {
991  NS_LOG_FUNCTION(this << "HTTP Content Parsed after merge with buffer: " << request.ToString() << "\n ***IsFragmented:" << request.IsFragmented() << "\n\n\n\n");
992  }else{
993  NS_LOG_FUNCTION(this << "Full packet received:" << request.ToString());
994  }
995 
996  while (buffer->GetSize () >= request.GetSize())
997  {
998  NS_LOG_DEBUG ("Parsing packet pid(" << p->GetUid() << ") of size " << request.GetSize () << " from buffer of size " << buffer->GetSize ());
999  Ptr<Packet> completePacket = buffer->CreateFragment (0, static_cast<uint32_t> (request.GetSize () ));
1000 
1001  uint8_t *b2 = new uint8_t[completePacket->GetSize ()];
1002  completePacket->CopyData(b2, completePacket->GetSize ());
1003  std::string s2 = std::string((char*)b2);
1004 
1005  HTTPMessage request2;
1006  parser.Parse(&request2, s2);
1007  delete[] b2;
1008 
1009  if(request2.IsFragmented() == false){
1010  buffer->RemoveAtStart (static_cast<uint32_t> (request2.GetSize () ));
1011  m_rxSigTrace (completePacket);
1012  ProcessSignalingPacketFromApp(request2, socket);
1013  }
1014  NS_LOG_FUNCTION(this << "Croped HTTP message: " << request2.ToString());
1015  NS_LOG_FUNCTION(this << "Remains in the buffer " << buffer->GetSize () );
1016  break;
1017  }
1018 }
1019 
1020 void
1022 {
1023  NS_LOG_FUNCTION (this << "QKDApp Data to KMS Sent via socket " << socket);
1024 }
1025 
1026 
1035 void
1037 {
1038  NS_LOG_FUNCTION( this );
1039 
1040  m_primaryQueueEstablished = false;
1041  m_replicaQueueEstablished = false;
1042 
1043  //Association for encryption
1044  m_associations.first.ksid.clear();
1045  m_associations.first.verified = false;
1046  m_associations.first.queueSize = m_keyBufferLengthEncryption;
1047  m_associations.first.buffer.clear();
1048 
1049  //Association for authentication
1050  m_associations.second.ksid.clear();
1051  m_associations.second.verified = false;
1053  m_associations.second.buffer.clear();
1054 
1055 }
1056 
1057 void
1059 {
1060  NS_LOG_FUNCTION( this << "Checking associations ..." );
1061  NS_ASSERT(m_master); //Only Primary QKDApp checks associations states
1062  /*
1063  Function called after sendksidresponse is recieved.
1064  Main purpose is to check if associations are established!
1065  If they are, then switch application state to:
1066  ASSOCIATIONS_ESTABLISHED and moves on next state in AppTransitionTree
1067  */
1068  bool encAssociation = true;
1069  bool authAssociation = true;
1070  if(GetEncryptionKeySize() != 0 && !m_associations.first.verified)
1071  encAssociation = false;
1072  if(GetAuthenticationKeySize() != 0 && !m_associations.second.verified)
1073  authAssociation = false;
1074 
1075  if(encAssociation && authAssociation && m_appState == ESTABLISHING_ASSOCIATIONS){
1076  NS_LOG_FUNCTION( this << "All necessary associations are established" );
1079  }else
1080  NS_LOG_FUNCTION( this << "Necessary associations are NOT yet established" );
1081 
1082 }
1083 
1084 void
1086 {
1087  NS_LOG_FUNCTION( this << "Checking key queues ... " << m_master );
1088  bool encQueueReady = false;
1089  bool authQueueReady = false;
1090  if(m_associations.first.verified && m_associations.first.buffer.size() < m_associations.first.queueSize)
1091  GetKeyFromKMS(m_associations.first.ksid);
1092  else
1093  encQueueReady = true;
1094 
1095  if(m_associations.second.verified && m_associations.second.buffer.size() < m_associations.second.queueSize)
1096  GetKeyFromKMS(m_associations.second.ksid);
1097  else
1098  authQueueReady = true;
1099 
1100  if(authQueueReady && encQueueReady){
1101  if(!m_master){
1102  NS_LOG_FUNCTION( this << "Replica QKDApp established key queues" );
1105  }else if(m_master){
1107  NS_LOG_FUNCTION( this << "Both Primary and Replica QKDApp established queues!" );
1110  }else{
1111  NS_LOG_FUNCTION( this << "Primary QKDApp establihed queues! Waiting on Replica QKDApp ..." );
1113  }
1114  }
1115  }
1116 
1117 }
1118 
1121 {
1122  NS_LOG_FUNCTION( this << m_master << "Obtaining encryption key from the local QKDApp buffer ..." << m_associations.first.ksid );
1123  if(m_master){ //Primary QKDApp obtains encryption key
1124 
1125  NS_LOG_FUNCTION( this << "We have in total " << m_associations.first.buffer.size() << " encryption keys!");
1126 
1127  QKDApp004::QKDAppKey output;
1128  std::map<uint32_t, QKDAppKey>::iterator it = m_associations.first.buffer.begin();
1129  NS_ASSERT (it != m_associations.first.buffer.end());
1130 
1131  NS_LOG_FUNCTION( this << "The lifetime of the first key is " << (it->second).lifetime );
1132 
1133  output = it->second;
1134  (it->second).lifetime -= m_packetSize; //Decrease key lifetime by packet size!
1135  NS_LOG_FUNCTION( this << "Remaining lifetime: " << output.lifetime );
1136 
1137  uint32_t counter = 0;
1138  for(std::map<uint32_t, QKDAppKey>::iterator it2 = m_associations.first.buffer.begin(); it2 != m_associations.first.buffer.end();)
1139  {
1140 
1141  NS_LOG_FUNCTION(this << "Key " << counter++ << " of size " << output.key.size() << " and lifetime " << (it2->second).lifetime );
1142  if(int32_t ((it2->second).lifetime) <= 0)
1143  {
1144  //Key expires and is deleted!
1145  NS_LOG_FUNCTION( this << "Local encryption key erased " << it2->first << ". Key lifetime expired!" );
1146  m_associations.first.buffer.erase(it2++); //Delete expired key
1147  GetKeyFromKMS(m_associations.first.ksid, 0); //Make new get_key request to obtain the next key!
1148  }else{
1149  ++it2;
1150  }
1151  }
1152 
1153  NS_LOG_FUNCTION(this << "Returning key of size " << output.key.size());
1154  return output; //return encryption key
1155 
1156  }else{ //Replica QKDApp obtains encryption key
1157  std::map<uint32_t, QKDAppKey>::iterator it = m_associations.first.buffer.find(m_associations.first.keyActive),
1158  it1 = m_associations.first.buffer.begin();
1159 
1160  QKDApp004::QKDAppKey encKey;
1161  if(it == m_associations.first.buffer.end())
1162  {
1163  //Out of sync!
1164  //Key is not obtained in time, packet should be stored for delayed processing!
1165  encKey.key = ""; //return empty key
1166  }else
1167  encKey = it->second; //encryption key (keyActive previously read from the QKDApp header)
1168 
1169  std::map<uint32_t, QKDAppKey>::iterator a = m_associations.first.buffer.begin(),
1170  b = m_associations.first.buffer.end();
1171  while(a != b){
1172  NS_LOG_FUNCTION( this << "Local encryption key store entry (test - krecS)" << a->first );
1173  ++a;
1174  }
1175  while(it1 != it){ //Remove any key older then keyActive (NOTE: could cause problems with delayed packets!)
1176  NS_LOG_FUNCTION( this << "Local encryption key erased " << it1->first << ". Synchronization!" );
1177  m_associations.first.buffer.erase(it1); //Remove first entry - oldest key
1178  it1 = m_associations.first.buffer.begin();
1179  }
1180  return encKey; //return encryption key
1181  }
1182 
1183 }
1184 
1187 {
1188  NS_LOG_FUNCTION( this << m_master << "Obtaining authentication key from the local QKDApp buffer ..." << m_associations.second.ksid );
1189  if(m_master){
1190 
1191  NS_LOG_FUNCTION( this << "We have in total " << m_associations.second.buffer.size() << " authentication keys!");
1192 
1193  std::map<uint32_t, QKDAppKey>::iterator it = m_associations.second.buffer.begin();
1194  NS_ASSERT (it != m_associations.second.buffer.end());
1195 
1196  QKDApp004::QKDAppKey authKey = it->second; //Authentication key is the first key in synchronized local QKDApp buffer
1197 
1198  std::map<uint32_t, QKDAppKey>::iterator a = m_associations.second.buffer.begin(),
1199  b = m_associations.second.buffer.end();
1200  while(a != b){
1201  NS_LOG_FUNCTION( this << "Local authentication key store entry (test - krecM)" << a->first << a->second.key.size());
1202  ++a;
1203  }
1204 
1205  NS_LOG_FUNCTION( this << "Local authentication key erased " << it->first );
1206  m_associations.second.buffer.erase(it); //Authentication keys do not have lifetime! One use only!
1207  NS_LOG_FUNCTION( this << "Calling get_key request" );
1208  GetKeyFromKMS(m_associations.second.ksid, 0); //Make new get_key request to obtain the next key!
1209 
1210  return authKey; //return authentication key
1211 
1212  }else{
1213  std::map<uint32_t, QKDAppKey>::iterator it = m_associations.second.buffer.find(m_associations.second.keyActive),
1214  it1 = m_associations.second.buffer.begin();
1215  QKDApp004::QKDAppKey authKey;
1216  if(it == m_associations.second.buffer.end()){ //Out of sync!
1217  //Key is not obtained in time, packet should be stored for delayed processing!
1218  authKey.key = ""; //return empty key
1219  }else
1220  authKey = it->second; //authentication key (keyActive previously read from the QKDApp header)
1221  while(it1 != it){ //Remove any key older then keyActive (NOTE: could cause problems with delayed packets!)
1222  NS_LOG_FUNCTION( this << "Local authentication key erased " << it1->first );
1223  m_associations.second.buffer.erase(it1);
1224  it1 = m_associations.second.buffer.begin();
1225  }
1226  return authKey; //return authentication key
1227  }
1228 
1229 }
1230 
1231 
1232 
1240 void
1241 QKDApp004::Http004AppQuery (uint32_t methodType, std::string ksid)
1242 {
1243  NS_LOG_FUNCTION(this << methodType << ksid);
1244  m_httpRequestsApp.push_back (std::make_pair (methodType, ksid));
1245 }
1246 
1247 void
1249 {
1250  if(m_httpRequestsApp.size() > 0)
1251  m_httpRequestsApp.erase (m_httpRequestsApp.begin());
1252 }
1253 
1254 uint32_t
1256 {
1257  NS_LOG_FUNCTION( this );
1258  return (m_httpRequestsApp[0]).first;
1259 }
1260 
1261 std::string
1263 {
1264  NS_LOG_FUNCTION( this );
1265  return (m_httpRequestsApp[0]).second;
1266 }
1267 
1268 
1269 
1277 void
1278 QKDApp004::Http004KMSQuery (std::string uri, std::string ksid, uint32_t keyType)
1279 {
1280  NS_LOG_FUNCTION(this << uri << ksid << keyType );
1281 
1282  m_httpRequestsKMS.insert(
1283  std::make_pair(
1284  uri,
1285  std::make_pair(ksid, keyType)
1286  )
1287  );
1288 }
1289 
1290 void
1292 {
1293  NS_LOG_FUNCTION(this << uri << m_httpRequestsKMS.size());
1294 
1295  std::map<std::string, std::pair<std::string, uint32_t> >::iterator it = m_httpRequestsKMS.find(uri);
1296  if ( it != m_httpRequestsKMS.end () ){
1297  m_httpRequestsKMS.erase(it);
1298  }
1299 }
1300 
1301 uint32_t
1303 {
1304  NS_LOG_FUNCTION( this << uri );
1305  //OPEN_CONNECT 0, GET_KEY 1, CLOSE 2
1306 
1307  size_t pos = 0;
1308  std::string delimiter = "/";
1309  std::string token;
1310  std::vector<std::string> uriParams;
1311  while ((pos = uri.find(delimiter)) != std::string::npos) {
1312  token = uri.substr(0, pos);
1313  if(token.length() > 0){
1314  uriParams.push_back(token);
1315  }
1316  uri.erase(0, pos + delimiter.length());
1317  }
1318  if(uri.length() > 0){
1319  uriParams.push_back(uri);
1320  }
1321  for(uint32_t i=0; i< uriParams.size(); i++){
1322  if(uriParams[i] == "open_connect"){
1323  return 0;
1324  }else if(uriParams[i] == "get_key"){
1325  return 1;
1326  }else if(uriParams[i] == "close"){
1327  return 2;
1328  }
1329  }
1330  NS_FATAL_ERROR( "METHOD NOT FOUND " << uri );
1331  return 0;
1332 }
1333 
1334 std::string
1336 {
1337  NS_LOG_FUNCTION( this << uri << m_httpRequestsKMS.size() );
1338 
1339  //FETCH KSID FROM CACHE
1340  uri = "http://" + uri;
1341  std::map<std::string, std::pair<std::string, uint32_t> >::iterator it = m_httpRequestsKMS.find(uri);
1342  if ( it != m_httpRequestsKMS.end () ){
1343  return it->second.first;
1344  }
1345 
1346  //FETCH KSID FROM THE URI
1347  size_t pos = 0;
1348  std::string delimiter = "/";
1349  std::string token;
1350  std::vector<std::string> uriParams;
1351  while ((pos = uri.find(delimiter)) != std::string::npos) {
1352  token = uri.substr(0, pos);
1353  if(token.length() > 0){
1354  uriParams.push_back(token);
1355  }
1356  uri.erase(0, pos + delimiter.length());
1357  }
1358  if(uri.length() > 0){
1359  uriParams.push_back(uri);
1360  }
1361  for(uint32_t i=0; i< uriParams.size(); i++){
1362  NS_LOG_FUNCTION(this << i << uriParams[i]);
1363  if(uriParams[i] == "open_connect" || uriParams[i] == "get_key" || uriParams[i] == "close"){
1364  return uriParams[i-1];
1365  }
1366  }
1367 
1368  NS_FATAL_ERROR( "KSID NOT FOUND " << uri );
1369  return "";
1370 }
1371 
1372 uint32_t
1374 {
1375  NS_LOG_FUNCTION( this << uri );
1376  uri = "http://" + uri;
1377 
1378  std::map<std::string, std::pair<std::string, uint32_t> >::iterator it = m_httpRequestsKMS.find(uri);
1379  if ( it != m_httpRequestsKMS.end () ){
1380  return it->second.second;
1381  }
1382 
1383  NS_FATAL_ERROR( "KEY TYPE NOT FOUND " << uri );
1384  return 0;
1385 }
1386 
1387 
1393 void
1395 {
1396  NS_LOG_FUNCTION (this);
1397 
1398  //Check whether the socket to KMS is active and connected
1399  Address temp;
1400  if(m_sendSocketToKMS == 0 || m_sendSocketToKMS->GetPeerName (temp) != 0){
1402  }
1403 
1404  if(m_appState != READY)
1405  return; //Simple malicious application is stopped, abort!
1406 
1407  std::string message;
1408 
1409  if(1 || !m_maliciousPacket){ //Create malicious packet for the first time
1410 
1411  std::string maliciousKsid = UUID::Sequential().string();
1412 
1413  if(GetAppState() == QKDApp004::STOPPED) return;
1415 
1417  std::ostringstream lkmsAddressTemp;
1418  lkmsAddress.Print(lkmsAddressTemp); //IPv4Address to string
1419  std::string headerUri = "http://" + lkmsAddressTemp.str();
1420  //headerUri += "/api/v1/keys/" + maliciousKsid + "/get_key";
1421  headerUri += "/api/v1/keys/" + m_dstSaeId.string() + "/open_connect/1";
1422  NS_LOG_FUNCTION(this << "maliciousKsid: " << headerUri );
1423 
1424  nlohmann::json msgBody; //No metadata
1425  //msgBody["Key_stream_ID"] = maliciousKsid;
1426  msgBody["Source"] = m_id.string();
1427  msgBody["Destination"] = m_dstSaeId.string();
1428  msgBody["QoS"] = {
1429  {"priority", 0},
1430  {"max_bps", 50000},
1431  {"min_bps", 100},
1432  {"jitter", 100},
1433  {"timeout", 100},
1434  {"key_chunk_size", 100},
1435  {"TTL", 10}
1436  };
1437 
1438  message = msgBody.dump();
1439 
1440  //Create packet
1441  HTTPMessage httpMessage;
1442  httpMessage.CreateRequest(headerUri, "POST", message);
1443  std::string hMessage = httpMessage.ToString();
1444  m_maliciousPacket = Create<Packet> (
1445  (uint8_t*) (hMessage).c_str(),
1446  hMessage.size()
1447  );
1448 
1450  }
1451 
1452  //Send malicious packet to KMS
1453  NS_LOG_FUNCTION (this << "Sending malicious PACKETID: " << m_maliciousPacket->GetUid()
1454  << " of size: " << m_maliciousPacket->GetSize()
1455  << " with payload: " << message
1456  << " via socket " << m_sendSocketToKMS
1457  );
1460 
1461  //Schedule next malicious request to KMS
1463 
1464 }
1465 
1471 void
1473 {
1474 
1475  NS_LOG_FUNCTION( this << m_local << m_peer << m_master );
1476  m_packetsSent = 0;
1477 
1478  if(m_malicious && m_master){ //Does not need to validate config. parameters
1479  m_maliciousPacket = NULL;
1482  return; //do not proceed with the function
1483  }
1484 
1485  if(m_encryptionTypeInt < 0 || m_encryptionTypeInt > 2){
1486  NS_FATAL_ERROR( "Invalid encryption type " << m_encryptionTypeInt
1487  << ". Allowed values are (0-unencrypted, 1-OTP, 2-AES)" );
1488  }
1489  if(m_authenticationTypeInt < 0 || m_authenticationTypeInt > 3){
1490  NS_FATAL_ERROR( "Invalid authentication type " << m_authenticationTypeInt
1491  << ". Allowed values are (0-unauthenticated, 1-VMAC, 2-MD5, 3-SHA1)" );
1492  }
1493  if(m_aesLifetime < 0){
1494  NS_FATAL_ERROR( "Invalid AES lifetime " << m_aesLifetime
1495  << ". The value must be larger than zero." );
1496  } else if(m_aesLifetime != 0 && m_aesLifetime < m_packetSize)
1497  NS_FATAL_ERROR( "Invalid AES lifetime " << m_aesLifetime
1498  << ". The value must be larger than one packet size " << m_packetSize );
1499 
1500  if(m_encryptionTypeInt == 1)
1501  m_aesLifetime = m_packetSize; //For when OTP is applied
1502 
1503  if(m_appState == INITIALIZED){
1508  );
1509  AppTransitionTree(); //Transition states
1510  PrepareSinkSocketFromApp(); //Create sink sockets for peer QKD applications
1511 
1512  }else
1513  NS_FATAL_ERROR( "Invalid state " << GetAppStateString ()
1514  << " for StartApplication()." );
1515 
1516 }
1517 
1518 void
1520 {
1521  //@toDo: As any other responsible application, on stopping, application will call CLOSE
1522  // Application will wait for response (but it is optional) and then close sockets!
1523  NS_LOG_FUNCTION( this << "Stopping QKDApp ... " );
1524  if(m_sendEvent.IsRunning())
1526 
1527  if(m_master){ //Only Primary QKDApp calls CLOSE, as it is one responsible for the associations!
1528  NS_LOG_FUNCTION( this << "Closing assocaitions ... ");
1529  if(!m_associations.first.ksid.empty()) //Encrpytion association active
1530  Close(m_associations.first.ksid);
1531 
1532  if(!m_associations.second.ksid.empty()) //Authentication association active
1533  Close(m_associations.second.ksid);
1534 
1535  }else{ //Replica QKDApp closes sockets to the KMS also
1536  if(m_sendSocketToKMS)
1538  if(m_sendSocketToKMS)
1540  }
1541  //Closing send and sink sockets for QKDApp communication!
1550 
1552  InitializeAssociations(); //Clear associations records
1553  NS_LOG_FUNCTION( this << "Data and signaling sockets are closed. Data transmission is stopped ..." );
1554 }
1555 
1556 void
1558 {
1559  NS_LOG_FUNCTION( this );
1561 
1562  if (m_appState == READY) //Direct call from SceduleTx()
1564 
1565  NS_LOG_FUNCTION(this << "testkrec" << m_appState);
1566  if (m_appState == SEND_DATA) {
1567 
1568  if(m_sendDataSocketApp == 0) {
1570  }
1571 
1572  //Obtain secret keys!
1573  QKDApp004::QKDAppKey encKey;
1574  encKey.index = 0;
1575  QKDApp004::QKDAppKey authKey;
1576  authKey.index = 0;
1577 
1578  //Obtain encryption key!
1579  if (GetEncryptionKeySize() != 0){
1580  encKey = GetEncKey();
1581  if(encKey.key == ""){
1583  return;
1584  }
1585  }
1586 
1587  //Obtain authentication key from application key buffer!
1588  if (GetAuthenticationKeySize() != 0){
1589  authKey = GetAuthKey();
1590  if(authKey.key == ""){
1592  return;
1593  }
1594  }
1595 
1596 
1597  //Keys are not Base64 coded!
1598  NS_LOG_FUNCTION(this << "\nEncryption Key (krec)" << encKey.key << "\nAuthentication Key (krec)" << authKey.key);
1599 
1600  //Define confidential message
1601  std::string confidentialMsg = GetPacketContent();
1602  NS_LOG_FUNCTION( this << "Confidential message" << confidentialMsg.size() << confidentialMsg );
1603 
1604  std::string encryptedMsg;
1605  std::string authTag;
1606  if (m_useCrypto) {
1607 
1608  encryptedMsg = m_encryptor->EncryptMsg(confidentialMsg, encKey.key);
1609  NS_LOG_FUNCTION ( this << "Encryption key" << encKey.index << encKey.key
1610  << "Encrypted message" << m_encryptor->Base64Encode(encryptedMsg));
1611  if(GetAuthenticationKeySize() != 0)
1612  authTag = m_encryptor->Authenticate (encryptedMsg, authKey.key);
1613  else
1614  authTag = GetPacketContent(32);
1615  NS_LOG_FUNCTION( this << "Authentication key" << authKey.index << authKey.key
1616  << "Authentication tag" << authTag );
1617 
1618  } else {
1619 
1620  encryptedMsg = confidentialMsg;
1621  authTag = GetPacketContent(32); //Use random authTag
1622  NS_LOG_FUNCTION ( this << "Encryption key" << encKey.index << encKey.key );
1623  NS_LOG_FUNCTION( this << "Authentication key" << authKey.index << authKey.key );
1624  NS_LOG_FUNCTION( this << "Authentication Tag" << authTag);
1625 
1626  }
1627 
1628  //Create packet with protected/unprotected data
1629  std::string msg = encryptedMsg;
1630  Ptr<Packet> packet = Create<Packet> ( (uint8_t*) msg.c_str(), msg.length() );
1631  NS_ASSERT (packet != 0);
1632  m_authenticationTrace (packet, authTag);
1633 
1634  //Add qkd header!
1635  QKDAppHeader qHeader;
1636  qHeader.SetEncrypted(m_encryptionType);
1637  qHeader.SetEncryptionKeyId(std::to_string(encKey.index));
1639  qHeader.SetAuthenticationKeyId(std::to_string(authKey.index));
1640  qHeader.SetAuthTag(authTag);
1641  qHeader.SetLength(packet->GetSize() + qHeader.GetSerializedSize());
1642  packet->AddHeader(qHeader);
1643 
1644  //Send packet!
1645  m_txTrace (packet, m_associations.first.ksid);
1646  m_txTrace (packet, m_associations.second.ksid);
1647  m_sendDataSocketApp->Send (packet);
1648  m_packetsSent++;
1649  m_dataSent += packet->GetSize();
1650 
1651  NS_LOG_FUNCTION (this << "Sending protected packet: " << packet->GetUid() << " of size " << packet->GetSize() );
1652 
1653  SwitchAppState(READY); //Application should go in ready or wait! If buffer is empty go to WAIT.
1654  //When a number of keys are obtained again, go to READY state.
1655  ScheduleTx (); //Schedule new time instance to send data!
1656 
1657  } else if (m_appState == WAIT) {
1658 
1659  //m_txTrace (0, m_associations.first.ksid);
1660  //m_txTrace (0, m_associations.second.ksid);
1661 
1662  ScheduleTx ();
1663  NS_LOG_FUNCTION( this << "Application is currently unable to send new data! QKDApp state" << GetAppStateString(m_appState) );
1664 
1665  } else {
1666 
1667  NS_FATAL_ERROR( this << "Application is in invalid state!" );
1668 
1669  }
1670 
1671 }
1672 
1673 void
1675 {
1676  NS_LOG_FUNCTION( this << "Processing data packet from peer QKDApp" );
1677  if(!m_master){ //Only Replica QKDApp receives encrypted data!
1678  std::string payload = PacketToString(packet); //Read the packet data
1679  NS_LOG_FUNCTION( this << "Received data packet" << m_encryptor->Base64Encode(payload) );
1680 
1683  std::string decryptedMsg;
1684  bool authSuccessful = false;
1685 
1686  NS_LOG_FUNCTION( this << "Executing authentication check on received packet!" );
1687  if(GetAuthenticationKeySize() != 0){ //Authentication requires QKD key
1688  NS_LOG_FUNCTION(this << "VMAC authentciation" );
1689  if(uint32_t (std::stoi(header.GetAuthenticationKeyId())) > m_associations.second.keyActive){
1690  m_associations.second.keyActive = std::stoi(header.GetAuthenticationKeyId()); //new keyActive read from QKDApp header
1691  NS_LOG_FUNCTION( this << "Synchronization - calling get_key request" );
1692  GetKeyFromKMS(m_associations.second.ksid, 0); //Calling get_key request
1693  }
1694 
1695  QKDApp004::QKDAppKey authKey = GetAuthKey(); //Obtain authentication key
1696  if(authKey.key == ""){ //Packet received out of sync (dealyed packet). Packet is dropped!
1697  NS_LOG_FUNCTION( this << "Authentication key not available" << m_associations.second.keyActive << "Packet is dropped!" );
1699  return;
1700  }
1701 
1702  NS_LOG_FUNCTION( this << "Authentication key obtained from the local key store" << authKey.index << authKey.key );
1703  if(m_useCrypto){ //Perform actual authentication check
1704  //Check authTag
1705  if(m_encryptor->CheckAuthentication(payload, header.GetAuthTag(), authKey.key)) //Check AuthTag
1706  authSuccessful = true;
1707 
1708  }else //We assume packet is successfully authenticated
1709  authSuccessful = true;
1710 
1711  }else if(header.GetAuthenticated()){ //Authentication does not require quantum key
1712  if (m_useCrypto){
1713  if(m_encryptor->CheckAuthentication(payload, header.GetAuthTag(), ""))
1714  authSuccessful = true;
1715 
1716  }else //We assume packet is successfully authenticated
1717  authSuccessful = true;
1718 
1719  }else //No authentication services
1720  authSuccessful = true;
1721 
1722  if(authSuccessful)
1723  NS_LOG_FUNCTION( this << "Packet is successfully authenticated! Processing ... " );
1724  else
1725  NS_LOG_FUNCTION( this << "Authentication of received packet FAILED. Packet is dropped!" );
1726 
1727  //Perform decryption
1728  if (header.GetEncrypted()){
1729  NS_LOG_FUNCTION(this << "Decrypting received packet ... ");
1730  if(uint32_t (std::stoi(header.GetEncryptionKeyId())) > m_associations.first.keyActive){
1731  m_associations.first.keyActive = std::stoi(header.GetEncryptionKeyId()); //new keyActive index
1732  NS_LOG_FUNCTION( this << "Synchronization - calling get_key request" );
1733  GetKeyFromKMS(m_associations.first.ksid, 0); //Calling get_key request
1734  }
1735 
1736  QKDApp004::QKDAppKey encKey = GetEncKey(); //Obtain encryption key
1737  if(encKey.key == ""){ //Out of sync (delayed packet)! Packet is dropped!
1738  NS_LOG_FUNCTION( this << "Encyption key not available" << m_associations.first.keyActive << "Packet is dropped!" );
1740  return;
1741  }
1742 
1743  NS_LOG_FUNCTION( this << "Encryption key obained from the local key store " << encKey.index << encKey.key );
1744  if(m_useCrypto){
1745  if(authSuccessful){ //Packet is decrypted only when it is succesfully authenticated
1746  decryptedMsg = m_encryptor->DecryptMsg (payload, encKey.key);
1747  NS_LOG_FUNCTION( this << "Packet decrypted! Decrypted message: \n" << decryptedMsg );
1748  }
1749  }else{ //Fake decryption process
1750  if(authSuccessful)
1751  NS_LOG_FUNCTION( this << "Packet decrypted!" );
1752  }
1753 
1754  }else //Receiving unprotected packet
1755  NS_LOG_FUNCTION( this << "Packet received unprotected! Received message: \n" << payload );
1756 
1758 
1759  }else
1760  NS_FATAL_ERROR( this << "Only Replica QKDApp receives protected packets! Only unidirectional secure data communication!" );
1761 
1762 }
1763 
1764 
1765 void
1767 {
1768  NS_LOG_FUNCTION (this << "Processing response from KMS" << packet->GetUid() << packet->GetSize());
1769 
1770  std::string requestUri = header.GetRequestUri();
1771  NS_LOG_FUNCTION(this << requestUri);
1772 
1773  uint32_t etsiFunction = GetMethodFromHttp004KMSQuery(requestUri); //Map response to request
1774  //OPEN_CONNECT 0, GET_KEY 1, CLOSE 2
1775 
1776  if(etsiFunction == 0 && m_appState != STOPPED)
1777  { //Response on OPEN_CONNECT
1779  }else if(etsiFunction == 1 && m_appState != STOPPED){ //Response on GET_KEY
1780  ProcessGetKeyResponse(header);
1781  }else if(etsiFunction == 2 && m_appState != STOPPED){ //Response on CLOSE
1782  ProcessCloseResponse(header);
1783  }else
1784  NS_FATAL_ERROR (this << "Invalid ETSI QKD GS 004 function used in request");
1785 
1786  Http004KMSQueryComplete( requestUri ); //Remove request from http query
1787 }
1788 
1789 
1798 void
1799 QKDApp004::OpenConnect (std::string ksid, uint32_t keyType)
1800 {
1801  if(!m_master && m_associations.second.ksid == ksid){
1802  keyType = 1;
1803  }
1804 
1805  NS_LOG_FUNCTION( this << "OPEN_CONNECT(master, ksid, keyType)" <<
1806  m_master << ksid << keyType);
1807  NS_ASSERT(keyType >= 0);
1808  NS_ASSERT(keyType < 3);
1809 
1810  if(m_sinkSocketFromKMS == 0) {
1812  }
1813 
1814  uint64_t maxRate = GetMaxEncryptionKeyRate() + GetMaxAuthenticationKeyRate();
1815  uint64_t minRate = m_minDataRate.GetBitRate();
1816 
1817  NS_LOG_FUNCTION(this << maxRate << minRate);
1818 
1819  uint32_t keySize {0};
1820  if(!keyType) { //0 - encrption key
1821  keySize = GetEncryptionKeySize();
1822  }else{ //1 - authentication key
1823  keySize = GetAuthenticationKeySize();
1824  }
1825 
1826  if(m_master) NS_ASSERT(keySize != 0);
1827 
1828  NS_ASSERT(m_priority < 2);
1829 
1830  nlohmann::json msgBody;
1831  msgBody["Source"] = m_id.string();
1832  msgBody["Destination"] = m_dstSaeId.string();
1833  msgBody["QoS"] = {
1834  {"priority", m_priority},
1835  {"max_bps", maxRate},
1836  {"min_bps", minRate},
1837  {"jitter", 100},
1838  {"timeout", 100},
1839  {"key_chunk_size", keySize},
1840  {"TTL", m_ttl}
1841  };
1842 
1843  if(!m_master){
1844  msgBody["Key_stream_ID"] = ksid;
1845  }else{
1846  msgBody["QoS"]["key_chunk_size"] = keySize;
1847  }
1848 
1849  std::string message = msgBody.dump();
1850 
1852  std::ostringstream lkmsAddressTemp;
1853  lkmsAddress.Print(lkmsAddressTemp); //IPv4Address to string
1854  std::string headerUri = "http://" + lkmsAddressTemp.str();
1855  headerUri += "/api/v1/keys/" + m_dstSaeId.string() + "/open_connect/" + std::to_string(keyType);
1856 
1857  //Create packet
1858  HTTPMessage httpMessage;
1859  httpMessage.CreateRequest(headerUri, "POST", message);
1860  std::string hMessage = httpMessage.ToString();
1861  Ptr<Packet> packet = Create<Packet> (
1862  (uint8_t*) (hMessage).c_str(),
1863  hMessage.size()
1864  );
1865  NS_ASSERT (packet != 0);
1866 
1867  NS_LOG_FUNCTION (this << "Sending PACKETID: " << packet->GetUid()
1868  << " of size: " << packet->GetSize()
1869  << " via socket " << m_sendSocketToKMS
1870  );
1871  //check whether the socket to KMS is active and connected
1872  Address temp;
1873  if(m_sendSocketToKMS == 0 || m_sendSocketToKMS->GetPeerName(temp) != 0){
1875  QKDApp004::KMSPacket kmsPacket;
1876  kmsPacket.packet = packet;
1877  kmsPacket.methodType = 0;
1878  kmsPacket.uri = headerUri;
1879  if(m_master){
1880  kmsPacket.keyType = keyType;
1881  kmsPacket.ksid = "";
1882  }else{
1883  kmsPacket.keyType = 0;
1884  kmsPacket.ksid = ksid;
1885  }
1886  m_queue_kms.push_back(kmsPacket);
1887 
1888  }else{
1889  Http004KMSQuery(headerUri, ksid, keyType ); //OPEN_CONNECT 0, GET_KEY 1, CLOSE 2; encKey 0, authKey 1)
1890 
1891  m_txKmsTrace(packet);
1892  m_sendSocketToKMS->Send(packet);
1893  }
1894 }
1895 
1896 void
1897 QKDApp004::GetKeyFromKMS (std::string ksid, uint32_t index)
1898 {
1899  NS_LOG_FUNCTION( this << "GET_KEY (master,ksid,index)" << m_master << ksid << index );
1900 
1901  if(GetAppState() == QKDApp004::STOPPED) return;
1903 
1905  std::ostringstream lkmsAddressTemp;
1906  lkmsAddress.Print(lkmsAddressTemp); //IPv4Address to string
1907  std::string headerUri = "http://" + lkmsAddressTemp.str();
1908  headerUri += "/api/v1/keys/" + ksid + "/get_key/fresh/" + std::to_string(m_random->GetValue (0,1000000));
1909 
1910  nlohmann::json msgBody; //No metadata
1911  msgBody["Key_stream_ID"] = ksid;
1912  std::string message = msgBody.dump();
1913 
1914  //Create packet
1915  HTTPMessage httpMessage;
1916  httpMessage.CreateRequest(headerUri, "POST", message);
1917  std::string hMessage = httpMessage.ToString();
1918  Ptr<Packet> packet = Create<Packet> (
1919  (uint8_t*) (hMessage).c_str(),
1920  hMessage.size()
1921  );
1922  NS_ASSERT (packet != 0);
1923 
1924  NS_LOG_FUNCTION (this << "Sending PACKETID: " << packet->GetUid()
1925  << " of size: " << packet->GetSize()
1926  << " via socket " << m_sendSocketToKMS
1927  );
1928 
1929  //Check whether the socket to KMS is active and connected
1930  Address temp;
1931  if(m_sendSocketToKMS == 0 || m_sendSocketToKMS->GetPeerName (temp) != 0){
1933  QKDApp004::KMSPacket kmsPacket;
1934  kmsPacket.packet = packet;
1935  kmsPacket.methodType = 1;
1936  kmsPacket.keyType = 0;
1937  kmsPacket.ksid = ksid;
1938  kmsPacket.uri = headerUri;
1939  m_queue_kms.push_back(kmsPacket);
1940  }else{
1941  Http004KMSQuery(headerUri, ksid, 0); //(etsi 004 function: OPEN_CONNECT 0, GET_KEY 1, CLOSE 2; KSID)
1942  m_txKmsTrace (packet);
1943  m_sendSocketToKMS->Send(packet);
1944  }
1945 }
1946 
1947 void
1948 QKDApp004::Close (std::string ksid)
1949 {
1950  NS_LOG_FUNCTION( this << "Closing key stream association" << m_master << ksid );
1952 
1953  //Empty queues assigned to this association and association registry
1954  if(m_associations.first.ksid == ksid){//close encryption association
1955  //InitializeAssociation(ksid);
1956  NS_LOG_FUNCTION( this << "Encryption key stream association closed on QKDApp side!");
1957  }else if(m_associations.second.ksid == ksid){
1958  //InitializeAssociation(ksid);
1959  NS_LOG_FUNCTION( this << "Authentication key stream association closed on QKDApp side!");
1960  }else
1961  NS_FATAL_ERROR( this << "Closing association failed. Ksid not registered" << ksid );
1962 
1963  //Send CLOSE message to the local KMS
1965  std::ostringstream lkmsAddressTemp;
1966  lkmsAddress.Print(lkmsAddressTemp); //IPv4Address to string
1967  std::string headerUri = "http://" + lkmsAddressTemp.str ();
1968  headerUri += "/api/v1/keys/" + ksid + "/close";
1969 
1970  //Create packet
1971  HTTPMessage httpMessage;
1972  httpMessage.CreateRequest(headerUri, "GET");
1973  std::string hMessage = httpMessage.ToString();
1974  Ptr<Packet> packet = Create<Packet> (
1975  (uint8_t*) (hMessage).c_str(),
1976  hMessage.size()
1977  );
1978  NS_ASSERT (packet != 0);
1979 
1980  NS_LOG_FUNCTION (this << "Sending PACKETID: " << packet->GetUid()
1981  << " of size: " << packet->GetSize()
1982  << " via socket " << m_sendSocketToKMS
1983  );
1984 
1985  //check whether the socket to KMS is active and connected
1986  Address temp;
1987  if(m_sendSocketToKMS == 0 || m_sendSocketToKMS->GetPeerName (temp) != 0){
1989  QKDApp004::KMSPacket kmsPacket;
1990  kmsPacket.packet = packet;
1991  kmsPacket.methodType = 2;
1992  kmsPacket.keyType = 0;
1993  kmsPacket.ksid = ksid;
1994  kmsPacket.uri = headerUri;
1995  m_queue_kms.push_back(kmsPacket);
1996  }else{
1997  //Store request to HTTP requests store (to be able to map responses)
1998  Http004KMSQuery(headerUri, ksid, 2); //(etsi gs 004 function: OPEN_CONNECT 0, GET_KEY 1, CLOSE 2; KSID)
1999  m_txKmsTrace (packet);
2000  m_sendSocketToKMS->Send (packet);
2001  }
2002 
2003 }
2004 
2005 void
2007 {
2008  NS_LOG_FUNCTION( this << "Processing OPEN_CONNECT response!" << m_master );
2009 
2011 
2012  std::string payload = header.GetMessageBodyString(); //Read HTTP body message
2013  nlohmann::json jOpenConnect; //Read JSON data structure from message
2014  if(!payload.empty()){
2015  try{
2016  jOpenConnect = nlohmann::json::parse(payload);
2017  }catch(...){
2018  NS_FATAL_ERROR( this << "JSON parse error!");
2019  }
2020  }
2021 
2022  NS_LOG_FUNCTION(this << payload);
2023 
2024  std::string requestUri = header.GetRequestUri();
2025  HTTPMessage::HttpStatus responseStatus = header.GetStatus();
2026  if(
2027  responseStatus == HTTPMessage::HttpStatus::BadRequest ||
2028  responseStatus == HTTPMessage::HttpStatus::Unauthorized ||
2029  responseStatus == HTTPMessage::HttpStatus::ServiceUnavailable
2030  ){ //Process status field of response (ETSI004 defined: 1, 4, 5, 7)
2031 
2032  if(m_master){
2033 
2034  std::string ksid = GetKsidFromHttp004KMSQuery(requestUri);
2035  uint32_t keyType = GetKeyTypeFromHttp004KMSQuery(requestUri);
2036 
2037  Time t {"5s"};
2038  EventId event = Simulator::Schedule (t, &QKDApp004::OpenConnect, this, ksid, keyType);
2039  //@toDoFuture If (QoS is rejected){repeat request in few sec (stage-1)}else{report fatal_error}
2040  //uint32_t status004 = jOpenConnect["status"]; //Read status code for OPEN_CONNECT
2041  NS_LOG_FUNCTION( this << "QKDApp received ERROR on OPEN_CONNECT." );
2042 
2043  }else{
2044  std::string ksid = GetKsidFromHttp004KMSQuery(requestUri);
2045  ClearAssociation(ksid); //Clear key stream association
2046  SendKsidResponse(HTTPMessage::HttpStatus::ServiceUnavailable); //Send response on /connect indicating error!
2047  }
2048 
2049  }else if(responseStatus == HTTPMessage::HttpStatus::Ok){ //For ETSI004 status 0
2050  NS_LOG_FUNCTION( this << "Successful OPEN_CONNECT" );
2051  if(m_master){ //Primary QKDApp on OPEN_CONNECT response
2052 
2053  std::string ksid;
2054  if(jOpenConnect.contains("Key_stream_ID")) ksid = jOpenConnect["Key_stream_ID"];
2055  NS_ASSERT(!ksid.empty());
2056 
2057  uint32_t keyType = GetKeyTypeFromHttp004KMSQuery(requestUri);
2058  if(keyType == 0){
2059  NS_LOG_FUNCTION( this << "KSID " << ksid << " registered for encryption" );
2060  m_associations.first.ksid = ksid; //Register encryption ksid
2061  }else{
2062  NS_LOG_FUNCTION( this << "KSID " << ksid << " registered for authentication" );
2063  m_associations.second.ksid = ksid; //Register authentication ksid
2064  }
2065  SendKsidRequest(ksid, keyType); //Connect to peer QKDApp by sending ksid
2066 
2067  }else{ //Replica QKDApp on OPEN_CONNECT response
2068 
2069  std::string ksid = GetKsidFromHttp004KMSQuery(requestUri);
2070  if (m_associations.first.ksid == ksid)
2071  m_associations.first.verified = true; //Association is verified if it's established by both QKDApp!
2072  else if (m_associations.second.ksid == ksid)
2073  m_associations.second.verified = true; //Association is verified if it's established by both QKDApp!
2074  else{
2075  NS_FATAL_ERROR( this
2076  << "Unknown ksid: " << ksid << "\t"
2077  << m_associations.first.ksid << "\t"
2078  << m_associations.second.ksid
2079  );
2080  }
2081  SendKsidResponse(HTTPMessage::HttpStatus::Ok); //Send response on /connect indicating success!
2082  }
2083 
2084  }else
2085  NS_FATAL_ERROR( this << "Unsupported error status code" << responseStatus << "of response.");
2086 
2087 }
2088 
2089 void
2091 {
2092  NS_LOG_FUNCTION( this );
2093  std::string payload = header.GetMessageBodyString();
2094  std::string requestUri = header.GetRequestUri();
2095  std::string ksid = GetKsidFromHttp004KMSQuery(requestUri);
2096 
2097  nlohmann::json jGetKeyResponse;
2098  if(!payload.empty()){
2099  try{
2100  jGetKeyResponse = nlohmann::json::parse(payload);
2101  }catch (...){
2102  NS_FATAL_ERROR( this << "JSON parse error!");
2103  }
2104  }
2105 
2106  HTTPMessage::HttpStatus responseStatus = header.GetStatus();
2107  if(
2108  responseStatus == HTTPMessage::HttpStatus::BadRequest ||
2109  responseStatus == HTTPMessage::HttpStatus::Unauthorized ||
2110  responseStatus == HTTPMessage::HttpStatus::ServiceUnavailable
2111  ){
2112  //Process status field of response (ETSI004 defined: 2, 3, 8) @toDo
2113  //uint32_t status004 = jGetKeyResponse["status"];
2114  NS_LOG_FUNCTION( this << "QKDApp received ERROR on GET_KEY" );
2116  Time t {"300ms"};
2117  EventId event = Simulator::Schedule (t, &QKDApp004::GetKeyFromKMS, this, ksid, 0);
2118  }else if(m_master){
2119  Time t {"500ms"};
2120  EventId event = Simulator::Schedule (t, &QKDApp004::GetKeyFromKMS, this, ksid, 0);
2121  }else if(!m_master){
2122  NS_LOG_FUNCTION(this << "Association has been closed ...");
2123  }
2124 
2125  }else if(responseStatus == HTTPMessage::HttpStatus::Ok){ //For ETSI004 status 0
2126  uint32_t index = -1;
2127  std::string key;
2128  if (jGetKeyResponse.contains("index"))
2129  index = jGetKeyResponse["index"];
2130  if (jGetKeyResponse.contains("Key_buffer"))
2131  key = jGetKeyResponse["Key_buffer"];
2132  NS_ASSERT(index >= 0);
2133  NS_ASSERT(!key.empty());
2134 
2135  m_obtainedKeyMaterialTrace (key.size()*8);
2136 
2137  NS_LOG_FUNCTION( this << "Key obtained (master,ksid,index,key)" << m_master << ksid << index << key);
2138  QKDAppKey appKey;
2139  appKey.key = key;
2140  appKey.index = index;
2141  appKey.lifetime = m_aesLifetime;
2142 
2143  if(m_associations.first.ksid == ksid)
2144  m_associations.first.buffer.insert( std::make_pair(index, appKey) );
2145  else if(m_associations.second.ksid == ksid)
2146  m_associations.second.buffer.insert( std::make_pair(index, appKey) );
2147  else
2148  NS_FATAL_ERROR( this << "Association with ksid" << ksid << "does not exist on QKDApp" );
2149 
2151  CheckQueues();
2152  else if(m_appState == WAIT){ //If Auth key and Enc key are ready then go to READY state!
2153  bool ready = true;
2154  if(GetEncryptionKeySize() != 0 && m_associations.first.buffer.empty())
2155  ready = false;
2156  if(GetAuthenticationKeySize() != 0 && m_associations.second.buffer.empty())
2157  ready = false;
2158  if(ready)
2160  }
2161 
2162  }else{
2163  NS_FATAL_ERROR( this << "Unsupported status code" << responseStatus << " of the response.");
2164  }
2165 }
2166 
2167 void
2169 {
2170  NS_LOG_FUNCTION( this << "Processing response on CLOSE method ..." );
2171 
2172  std::string requestUri = header.GetRequestUri();
2173  std::string ksid = GetKsidFromHttp004KMSQuery(requestUri);
2174 
2175  if(m_httpRequestsKMS.empty()){ //Sockets are closed when both CLOSE responses are received!
2178  }
2179 
2180  //Application does not really need to process CLOSE response!
2181  HTTPMessage::HttpStatus responseStatus = header.GetStatus();
2182  if(
2183  responseStatus == HTTPMessage::HttpStatus::BadRequest ||
2184  responseStatus == HTTPMessage::HttpStatus::Unauthorized ||
2185  responseStatus == HTTPMessage::HttpStatus::ServiceUnavailable
2186  ){
2187  NS_LOG_FUNCTION( this << "QKDApp received error message on CLOSE method" );
2189 
2190  }else if(responseStatus == HTTPMessage::HttpStatus::Ok){
2191  NS_LOG_FUNCTION( this << "Application successfully closed association " << ksid );
2192  InitializeAssociations(); //Associations are initialized once again!
2193 
2194  }else{
2195  NS_FATAL_ERROR( this << "Unsupported error status code" << responseStatus << "of response.");
2196  }
2197 
2198 }
2199 
2200 void
2202 {
2203  NS_LOG_FUNCTION( this << "Processing singnaling packet received from peer QKDApp" );
2204 
2205  std::string payload = header.GetMessageBodyString();
2206 
2207  if(m_master){ //Primary QKDApp processes received signaling packet from Replica QKDApp
2208  uint32_t methodType = GetMethodFromHttp004AppQuery(); //Send_ksid or Create_queues
2209  if(methodType == 0){
2210  NS_LOG_FUNCTION( this << "SEND_KSID: Primary QKDApp received response from Replica QKDApp." );
2211  std::string ksid = GetKsidFromHttp004AppQuery();
2212  ProcessSendKsidResponse(header, ksid);
2213  }else if (methodType == 1){
2214  NS_LOG_FUNCTION( this << "ESTABLISH_QUEUES: Primary QKDApp received response from Replica QKDApp. Packet ID" );
2216  }
2218 
2219  }else{ //Replica QKDApp processes received signaling packet from Primary QKDApp.
2220 
2221  std::string s = header.GetUri();
2222  std::string delimiter = "/";
2223  size_t pos = 0;
2224  std::string token;
2225 
2226  std::vector<std::string> uriParams;
2227  while((pos = s.find(delimiter)) != std::string::npos){
2228  token = s.substr(0, pos);
2229  if(token.length() > 0){
2230  uriParams.push_back(token);
2231  }
2232  s.erase(0, pos + delimiter.length());
2233  }
2234  if(s.length() > 0){
2235  uriParams.push_back(s);
2236  }
2237 
2238  std::string requestType;
2239  if(
2240  uriParams.size() > 3 &&
2241  uriParams[1] == "api" &&
2242  uriParams[2] == "v1"
2243  ){
2244  requestType = uriParams[4];
2245  }
2246 
2247  NS_LOG_FUNCTION(this << requestType << s);
2248 
2249  if(requestType == "connect"){ //This is SEND_KSID message
2250 
2251  NS_LOG_FUNCTION( this << "Processing send_ksid request!" );
2252  std::string ksid = uriParams[5];
2253  NS_ASSERT(!ksid.empty());
2254  std::string cryptoT = uriParams[6];
2255  NS_ASSERT(!cryptoT.empty());
2256 
2257  if(cryptoT == "0")
2258  m_associations.first.ksid = ksid; //Register KSID for encryption
2259  else if(cryptoT == "1")
2260  m_associations.second.ksid = ksid; //Register KSID for autentication
2261  else
2262  NS_FATAL_ERROR( this << "Invalid purpose of the association!" );
2263 
2264  NS_LOG_FUNCTION(this << cryptoT << ksid);
2265 
2267  OpenConnect(ksid); //Send OpenConnect to local KMS!
2268 
2269  }else if(requestType == "establish_queues") { //process establish_queues notification
2270  NS_LOG_FUNCTION( this << "Processing establish_queues request!" );
2272  CheckQueues();
2273 
2274  } else {
2275  NS_FATAL_ERROR( this << "Invalid method received on app. RequestType:" << requestType << s );
2276  }
2277 
2278  }
2279 
2280 }
2281 
2290 void
2291 QKDApp004::SendKsidRequest (std::string ksid, uint32_t keyType)
2292 {
2293  NS_LOG_FUNCTION( this << ksid << keyType << this->GetId().string() ); //keyType is enc/auth identifier
2294  if(m_sendSignalingSocketApp == 0)
2296  if(m_sinkSignalingSocketApp == 0)
2298 
2299  NS_ASSERT(m_master); //Only primary QKDApp calls SendKsid
2300 
2302  std::stringstream ss;
2303  m_peerAddress.Print(ss);
2304  std::string headerUri = "http://" + ss.str();
2305 
2306  NS_LOG_FUNCTION(this << m_peer << headerUri << m_peerAddress << headerUri.size());
2307 
2308  headerUri += "/api/v1/" + this->GetId().string() + "/connect/" + ksid + "/" + std::to_string(keyType);
2309  NS_LOG_FUNCTION(this << headerUri);
2310 
2311  //Create packet
2312  HTTPMessage httpMessage;
2313  httpMessage.CreateRequest(headerUri, "GET");
2314  std::string hMessage = httpMessage.ToString();
2315  Ptr<Packet> packet = Create<Packet> (
2316  (uint8_t*) (hMessage).c_str(),
2317  hMessage.size()
2318  );
2319  NS_ASSERT (packet != 0);
2320 
2321  Http004AppQuery(0, ksid); //0-SendKSID method
2322 
2323  m_txSigTrace (packet);
2324  m_sendSignalingSocketApp->Send(packet);
2325  m_packetsSent++;
2326  m_dataSent += packet->GetSize();
2327  NS_LOG_FUNCTION( this << "SEND_KSID: Primary QKDApp sends KSID to Replica QKDApp" <<
2328  headerUri << ". Packet ID" << packet->GetUid() );
2329 }
2330 
2331 void
2333 {
2334  NS_LOG_FUNCTION( this << "Sending response on SEND_KSID to Primary QKDApp" << httpStatus << msg );
2335  if(m_sendSignalingSocketApp == 0)
2337  if(m_sinkSignalingSocketApp == 0)
2339  NS_ASSERT(!m_master);
2340 
2341  //create packet
2342  HTTPMessage httpMessage;
2343  if(!msg.empty()){
2344  httpMessage.CreateResponse(httpStatus, msg, {
2345  {"Content-Type", "application/json; charset=utf-8"}
2346  });
2347  }else{
2348  httpMessage.CreateResponse(httpStatus);
2349  }
2350 
2351  std::string hMessage = httpMessage.ToString();
2352  Ptr<Packet> packet = Create<Packet> (
2353  (uint8_t*) (hMessage).c_str(),
2354  hMessage.size()
2355  );
2356  NS_ASSERT (packet != 0);
2357 
2358  m_txSigTrace (packet);
2359  m_sendSignalingSocketApp->Send(packet);
2360  m_packetsSent++;
2361  m_dataSent += packet->GetSize();
2362 
2363  NS_LOG_FUNCTION( this << "SEND_KSID: Replica QKDApp sends respose to Primary QKDApp. Packet ID"
2364  << packet->GetUid() << packet->GetSize() );
2365 }
2366 
2367 void
2369 {
2370  NS_LOG_FUNCTION( this << "Processing /connect response (send_ksid)" );
2371  NS_ASSERT(m_master); //Only on Primary QKDApp can receive response on /connect
2372  if(header.GetStatus() == HTTPMessage::HttpStatus::Ok){
2373  if(m_associations.first.ksid == ksid)
2374  m_associations.first.verified = true; //Acknowledge peer application registered for ksid
2375  else if(m_associations.second.ksid == ksid)
2376  m_associations.second.verified = true; //Acknowledge peer application registered for ksid
2377  else
2378  NS_FATAL_ERROR( this );
2379  NS_LOG_FUNCTION( this << "Association successfully established between QKDApps " << ksid );
2380  CheckAssociationsState(); //Check if the QKDApp is ready to leave ESTABLISHING_ASSOCIATIONS state!
2381 
2382  }else{
2383  NS_LOG_FUNCTION( this << "/connect failed! " << ksid );
2384  Close(ksid); //Close established association
2385  }
2386 }
2387 
2388 void
2390 {
2391  NS_LOG_FUNCTION( this << "Primary QKDApp sending establish_queues notification to Replica QKDApp" );
2392  NS_ASSERT(m_master); //Only Primary QKDApp function
2393 
2395  std::stringstream ss;
2396  m_peerAddress.Print(ss);
2397  std::string headerUri = "http://" + ss.str();
2398  headerUri += "/api/v1/" + this->GetId().string() + "/establish_queues";
2399 
2400  //Create packet
2401  HTTPMessage httpMessage;
2402  httpMessage.CreateRequest(headerUri, "GET"); //GET for a notification message?
2403  std::string hMessage = httpMessage.ToString();
2404  Ptr<Packet> packet = Create<Packet> (
2405  (uint8_t*) (hMessage).c_str(),
2406  hMessage.size()
2407  );
2408  NS_ASSERT (packet != 0);
2409 
2410  Http004AppQuery(1, ""); //1 - establish_queues method!
2411 
2412  m_txSigTrace (packet);
2413  m_sendSignalingSocketApp->Send(packet);
2414  m_packetsSent++;
2415  m_dataSent += packet->GetSize();
2416 
2417  NS_LOG_FUNCTION(this << "Packet ID:" << packet->GetUid() << "Packet size:" << packet->GetSize() );
2418 
2419 }
2420 
2421 void
2423 {
2424  NS_LOG_FUNCTION( this << "Replica QKDApp sending response on /fill indicating success" );
2425  NS_ASSERT(!m_master); //Only Replica QKDApp function
2426 
2427  //create packet
2428  HTTPMessage httpMessage;
2429  httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok);
2430  std::string hMessage = httpMessage.ToString();
2431  Ptr<Packet> packet = Create<Packet> (
2432  (uint8_t*) (hMessage).c_str(),
2433  hMessage.size()
2434  );
2435  NS_ASSERT (packet != 0);
2436 
2437  m_txSigTrace (packet);
2438  m_sendSignalingSocketApp->Send(packet);
2439  m_packetsSent++;
2440  m_dataSent += packet->GetSize();
2441 
2442  NS_LOG_FUNCTION(this << "Packet ID" << packet->GetUid() << "Packet size" << packet->GetSize() );
2443 
2444 }
2445 
2446 void
2448 {
2449  NS_LOG_FUNCTION( this );
2450 
2452 
2456  }
2457 
2458 }
2459 
2460 void
2462 {
2463 
2464  NS_LOG_FUNCTION( this << "Establishing associations" );
2465  if(GetEncryptionKeySize() != 0 && m_associations.first.ksid == "")
2466  OpenConnect("", 0); //Establish association for a set of future encryption (0) keys
2467  if (GetAuthenticationKeySize() != 0 && m_associations.second.ksid == "")
2468  OpenConnect("", 1); //Establish association for a set of future authentication (1) keys
2469 }
2470 
2471 void
2473 {
2474  NS_LOG_FUNCTION( this << "Clearing key stream association on QKDApp" << ksid );
2475  if(m_associations.first.ksid == ksid){ //Clear association created for encryption
2476  m_associations.first.ksid.clear(); //Clear ksid
2477  m_associations.first.verified = false;
2478  m_associations.first.keyActive = 0;
2479  m_associations.first.buffer.clear(); //Clear any keys in buffer!
2480  }else if(m_associations.second.ksid == ksid){ //Clear association created for authentication
2481  m_associations.second.ksid.clear(); //Clear ksid
2482  m_associations.second.verified = false;
2483  m_associations.second.keyActive = 0;
2484  m_associations.second.buffer.clear(); //Clear any keys in buffer!
2485  }
2486  NS_LOG_FUNCTION( this << "Key stream association " << ksid << " cleared!" );
2487 }
2488 
2489 void
2491 {
2492  NS_LOG_FUNCTION (this << oldRtt << newRtt);
2493 }
2494 
2495 
2504 void
2506 {
2507 
2508  NS_LOG_FUNCTION( this << m_master );
2509  if(m_master){ //Transitions for Primary QKDApp
2510  if(m_appState == INITIALIZED){
2511  if (GetEncryptionKeySize() == 0 && GetAuthenticationKeySize() == 0){ //QKD key material not needed!
2514  SendPacket(); //Immediately sends unprotected packets
2515  }else{ //Establish associations for a set of future QKD keys
2518  CreateKeyStreamAssociations(); //Call OPEN_CONNECT
2519  }
2520  }else if(m_appState == ASSOCIATIONS_ESTABLISHED){
2522  CreateKeyQueues();
2523  CheckQueues();
2524  }else if(m_appState == KEY_QUEUES_ESTABLISHED){
2526  SendPacket(); //Start sending packets!
2527  }else{
2528  NS_FATAL_ERROR( this << "Invalid entry state" << m_appState <<
2529  "for AppTransitionTree()!" );
2530  }
2531 
2532  }else if(!m_master){ //Data transmision state transition for Replica QKDApp
2533  if(m_appState == INITIALIZED){
2535  }else if(m_appState == KEY_QUEUES_ESTABLISHED){
2536  if (m_associations.first.verified)
2537  m_associations.first.keyActive = m_associations.first.buffer.begin()->first;
2538  if (m_associations.second.verified)
2539  m_associations.second.keyActive = m_associations.second.buffer.begin()->first;
2542  }else{
2543  NS_FATAL_ERROR( this << "Invalid entry state" << m_appState <<
2544  "for AppTransitionTree()!" );
2545  }
2546 
2547  }
2548 
2549 }
2550 
2551 
2554 {
2555  return m_appState;
2556 }
2557 
2558 std::string
2560 {
2561  switch (state)
2562  {
2563  case NOT_STARTED:
2564  return "NOT_STARTED";
2565  break;
2566  case INITIALIZED:
2567  return "INITIALIZED";
2568  break;
2570  return "ESTABLISHING_ASSOCIATIONS";
2571  break;
2573  return "ASSOCIATIONS_ESTABLISHED";
2574  break;
2576  return "ESTABLISHING_KEY_QUEUES";
2577  break;
2579  return "KEY_QUEUES_ESTABLISHED";
2580  break;
2581  case READY:
2582  return "READY";
2583  break;
2584  case WAIT:
2585  return "WAIT";
2586  break;
2587  case SEND_DATA:
2588  return "SEND_DATA";
2589  break;
2590  case DECRYPT_DATA:
2591  return "DECRYPT_DATA";
2592  break;
2593  case STOPPED:
2594  return "STOPPED";
2595  break;
2596  default:
2597  NS_FATAL_ERROR ("Unknown state");
2598  return "FATAL_ERROR";
2599  break;
2600  }
2601 }
2602 
2603 
2604 std::string
2606 {
2607  return GetAppStateString (m_appState);
2608 }
2609 
2610 void
2612 {
2613 
2614  const std::string oldState = GetAppStateString ();
2615  const std::string newState = GetAppStateString (state);
2616 
2617  //Check transition matrix! @toDo
2618  if (oldState == "SEND_DATA" && newState == "READY") {
2619  if ( (m_associations.first.ksid != "" && m_associations.first.buffer.empty()) ||
2620  (m_associations.second.ksid != "" && m_associations.second.buffer.empty())
2621  )
2622  state = QKDApp004::QKDAppState::WAIT; //Queues are empty. Go to state WAIT!
2623  }
2624 
2625  m_appState = state;
2626  NS_LOG_FUNCTION( this << "QKDApp" << oldState << "-->" << GetAppStateString (state) );
2627  //m_appStateTransitionTrace(oldState, newState);
2628 
2629 }
2630 
2639 void
2641  uint32_t encryptionType,
2642  uint32_t authenticationType,
2643  uint32_t authenticationTagLengthInBits
2644 ){
2645 
2646  NS_LOG_FUNCTION (this << encryptionType << authenticationType << authenticationTagLengthInBits);
2647 
2648  switch (encryptionType){
2649  case 0:
2651  break;
2652  case 1:
2654  break;
2655  case 2:
2657  break;
2658  }
2659 
2660  switch (authenticationType){
2661  case 0:
2663  break;
2664  case 1:
2666  break;
2667  case 2:
2669  break;
2670  case 3:
2672  break;
2673  }
2674 
2675  if(m_encryptor == 0){
2676  m_encryptor = CreateObject<QKDEncryptor> (
2679  authenticationTagLengthInBits
2680  );
2681  }else{
2682  m_encryptor->ChangeSettings(
2685  authenticationTagLengthInBits
2686  );
2687  }
2688 
2689 }
2690 
2691 std::string
2692 QKDApp004::GetPacketContent(uint32_t msgLength)
2693 {
2694  NS_LOG_FUNCTION(this);
2695 
2696  if (msgLength == 0)
2697  msgLength = m_packetSize;
2698 
2699  //Generate random string with same size as merged key string
2700  std::string confidentialMessage;
2701  static const char alphanum[] =
2702  "0123456789"
2703  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
2704  "abcdefghijklmnopqrstuvwxyz";
2705 
2706  uint32_t randVal = 0;
2707  for (uint32_t i = 0; i < msgLength; ++i){
2708  randVal = round(m_random->GetValue (0, sizeof(alphanum) - 1));
2709  confidentialMessage += alphanum[ randVal ];
2710  }
2711 
2712  return confidentialMessage;
2713 
2714 }
2715 
2716 uint32_t
2718 {
2719  switch(m_encryptionType){
2721  return 0;
2722  break;
2724  return m_packetSize * 8;
2725  break;
2727  return CryptoPP::AES::MAX_KEYLENGTH * 8; //In bits 256! Quantum resistant!
2728  break;
2729  }
2730  return 0;
2731 }
2732 
2733 uint64_t
2735 {
2736  uint32_t rate = 0;
2737  switch(m_encryptionType){
2739 
2740  NS_LOG_FUNCTION(this << "UNENCRYPTED");
2741  return 0;
2742  break;
2743 
2745 
2746  NS_LOG_FUNCTION(this << "OTP:" << m_dataRate.GetBitRate());
2747  return m_dataRate.GetBitRate();
2748  break;
2749 
2751 
2752  //In bits 256! Quantum resistant!
2754  rate = CryptoPP::AES::MAX_KEYLENGTH * 8;
2755  }else{
2756  rate = round (
2757  (m_dataRate.GetBitRate()/m_aesLifetime) * CryptoPP::AES::MAX_KEYLENGTH * 8
2758  );
2759  }
2760  NS_LOG_FUNCTION(this << "AES:" << rate << m_dataRate.GetBitRate() << m_aesLifetime << CryptoPP::AES::MAX_KEYLENGTH * 8);
2761  return rate;
2762  break;
2763 
2764  }
2765  return rate;
2766 }
2767 
2768 uint32_t
2770 {
2771  uint32_t rate = 0;
2772  switch (m_authenticationType){
2774 
2775  NS_LOG_FUNCTION(this << "UNENCRYPTED");
2776  return 0;
2777  break;
2778 
2780 
2781  rate = CryptoPP::AES::DEFAULT_KEYLENGTH * 8; //Use with AES. In bits 128 bits!
2782  NS_LOG_FUNCTION(this << "QKDCRYPTO_AUTH_VMAC: " << rate);
2783  return rate;
2784  break;
2785 
2787 
2788  NS_LOG_FUNCTION(this << "QKDCRYPTO_AUTH_MD5");
2789  return 0; //NoKey
2790  break;
2791 
2793 
2794  NS_LOG_FUNCTION(this << "QKDCRYPTO_AUTH_SHA1");
2795  return 0; //NoKey
2796  break;
2797 
2798  }
2799  return rate;
2800 }
2801 
2802 uint64_t
2804 {
2807 
2808  uint32_t rate = 0;
2809  switch (m_authenticationType){
2811  return 0;
2812  break;
2814 
2815  //Use with AES. In bits 128 bits!
2816  if(m_aesLifetime){
2817 
2819  rate = CryptoPP::AES::DEFAULT_KEYLENGTH * 8;
2820  }else{
2821  rate = round (
2822  (m_dataRate.GetBitRate()/m_aesLifetime) * CryptoPP::AES::DEFAULT_KEYLENGTH * 8
2823  );
2824  }
2825  return rate;
2826 
2827  }else{
2828 
2830  rate = CryptoPP::AES::DEFAULT_KEYLENGTH * 8;
2831  }else{
2832  rate = round (
2833  (m_dataRate.GetBitRate()/m_packetSize) * CryptoPP::AES::DEFAULT_KEYLENGTH * 8
2834  );
2835  }
2836  return rate;
2837 
2838  }
2839  break;
2841  return 0; //NoKey
2842  break;
2844  return 0; //NoKey
2845  break;
2846  }
2847  return 0;
2848 }
2849 
2850 
2851 std::string
2853 {
2854  NS_LOG_FUNCTION( this );
2855 
2856  uint8_t *buffer = new uint8_t[packet->GetSize ()];
2857  packet->CopyData(buffer, packet->GetSize ());
2858  std::string payload = std::string((char*)buffer, packet->GetSize());
2859  delete[] buffer;
2860 
2861  return payload;
2862 }
2863 
2864 
2865 
2866 } // Namespace ns3
a polymophic address class
Definition: address.h:91
The base class for all ns3 applications.
Definition: application.h:61
Ptr< Node > GetNode() const
Definition: application.cc:104
Class for representing data rates.
Definition: data-rate.h:89
uint64_t GetBitRate() const
Get the underlying bitrate.
Definition: data-rate.cc:287
AttributeValue implementation for DataRate.
Definition: data-rate.h:298
An identifier for simulation events.
Definition: event-id.h:54
bool IsRunning(void) const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:71
The basic class to represent both HTTP requests and responses.
Definition: http.h:78
std::string GetRequestUri() const
Definition: http.h:431
std::string ToString()
Takes the headers added to the message along with the body and outputs it to a std::string for use in...
Definition: http.h:633
uint32_t GetSize()
Definition: http.h:686
std::string GetUri() const
Grab the uri.
Definition: http.h:519
void CreateRequest(const std::string &url, const std::string &method)
Definition: http.h:738
bool IsFragmented()
Definition: http.h:852
std::string GetMessageBodyString()
Definition: http.h:714
size_t GetContentLength()
Return the size of the binary body vector.
Definition: http.h:724
void CreateResponse(const HttpStatus status)
Definition: http.h:785
HTTPMessage::HttpStatus GetStatus()
To be returned with a status code in a response is a status text describing the status code by text r...
Definition: http.h:169
uint32_t GetHeadersSize()
Definition: http.h:681
std::string GetStatusMessage() const
Get the current status message for this message.
Definition: http.h:623
A basic class to parse a HTTP message, both request and response.
Definition: http.h:941
void Parse(HTTPMessage *httpMessage, const std::string &buffer)
Parse a std::string to a HTTP message.
Definition: http.h:951
an Inet address class
uint16_t GetPort(void) const
Ipv4Address GetIpv4(void) const
static bool IsMatchingType(const Address &address)
static InetSocketAddress ConvertFrom(const Address &address)
Returns an InetSocketAddress which corresponds to the input Address.
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:41
void Print(std::ostream &os) const
Print this address to the given output stream.
static Ipv4Address GetAny(void)
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Definition: object-base.cc:364
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:280
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:335
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:378
std::string ToString(void) const
Return a string representation of the packet.
Definition: packet.cc:426
void RemoveAtStart(uint32_t size)
Remove size bytes from the start of the current packet.
Definition: packet.cc:362
uint64_t GetUid(void) const
Returns the packet's Uid.
Definition: packet.cc:390
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:290
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
Create a new packet which contains a fragment of the original packet.
Definition: packet.cc:227
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:856
Establish secure communication on application lavel to use the key and test LKSM.
Definition: qkd-app-004.h:72
void ProcessDataPacketFromApp(QKDAppHeader header, Ptr< Packet > packet, Ptr< Socket > socket)
Process data packets from the peer QKD application.
void HandlePeerErrorFromKMS(Ptr< Socket > socket)
Handle a connection error from the KMS.
Definition: qkd-app-004.cc:612
Ptr< Socket > m_sinkSignalingSocketApp
The receiving socket for the signaling messages.
Definition: qkd-app-004.h:790
virtual void StopApplication(void)
Application specific shutdown code.
void HandlePeerCloseFromApp(Ptr< Socket > socket)
Handle a connection close from the peer QKD application.
Definition: qkd-app-004.cc:652
double m_delay
The time interval between two successive data transmissions (calculated based on the application data...
Definition: qkd-app-004.h:808
TracedCallback< Ptr< const Packet > > m_rxSigTrace
A trace for received signaling packets.
Definition: qkd-app-004.h:556
void HandleReadFromApp(Ptr< Socket > socket)
Handle a packet received from the peer QKD application.
Definition: qkd-app-004.cc:838
UUID m_dstSaeId
The peer application identifier.
Definition: qkd-app-004.h:835
TracedCallback< Ptr< Packet >, std::string > m_deauthenticationTrace
A trace callback for the authentication check event.
Definition: qkd-app-004.h:848
void CancelScheduledAction(uint32_t eventId)
Cancel the scheduled event.
Definition: qkd-app-004.cc:308
void ConnectionToKMSSucceeded(Ptr< Socket > socket)
Callback function after the connection to the KMS is complete.
Definition: qkd-app-004.cc:570
std::string GetAppStateString() const
Get the current state of the application in a string notation.
QKDAppState m_appState
The application state.
Definition: qkd-app-004.h:857
QKDAppKey GetAuthKey()
Get the authentication key from the queue.
void Http004AppQueryComplete(void)
Remove the request from the vector of HTTP requests made to the peer QKD application.
DataRate m_dataRate
The application data rate.
Definition: qkd-app-004.h:810
QKDApp004()
Constructor.
Definition: qkd-app-004.cc:180
void ConnectionToKMSFailed(Ptr< Socket > socket)
Callback function after the connection to the KMS has failed.
Definition: qkd-app-004.cc:576
void HandleAcceptFromKMS(Ptr< Socket > s, const Address &from)
Handle an incoming connection from the KMS.
Definition: qkd-app-004.cc:533
uint32_t m_useCrypto
Execute actual cryptographic algorithms?
Definition: qkd-app-004.h:840
void SendPacket(void)
Send the application packet (includes the generation of a random message and optional encryption or/a...
void OpenConnect(std::string ksid, uint32_t keyType=0)
Request a key stream session (an association) from the local KMS.
uint32_t GetMethodFromHttp004AppQuery(void)
Map the HTTP response from the peer QKD application and obtain the ETSI method type.
void PrepareSinkSocketFromKMS()
Prepare the sink socket to listen from the KMS Application.
Definition: qkd-app-004.cc:330
void RegisterAckTime(Time oldRtt, Time newRtt)
Register the acknowledgement time.
Address m_localSignaling
The local address for the signaling data transmission.
Definition: qkd-app-004.h:801
void SendMaliciousRequestToKMS()
Send a malicious request to the KMS.
static TypeId GetTypeId(void)
Get the type ID.
Definition: qkd-app-004.cc:44
uint32_t m_keyBufferLengthEncryption
The size of the encryption key queue at the application layer.
Definition: qkd-app-004.h:854
void ProcessSignalingPacketFromApp(HTTPMessage &header, Ptr< Socket > socket)
Process a signaling packets from the peer QKD application.
Time m_dosAttackIntensity
The intensity of the DoS attack.
Definition: qkd-app-004.h:824
QKDAppState
The QKD application states.
Definition: qkd-app-004.h:109
@ ESTABLISHING_ASSOCIATIONS
Definition: qkd-app-004.h:112
@ ASSOCIATIONS_ESTABLISHED
Definition: qkd-app-004.h:113
void ProcessOpenConnectResponse(HTTPMessage &header)
Process the OPEN_CONNECT response.
void ProcessGetKeyResponse(HTTPMessage &header)
Process the GET_KEY response.
TracedCallback< Ptr< Packet >, std::string > m_authenticationTrace
A trace callback for the authentication event.
Definition: qkd-app-004.h:847
UUID m_id
The application identifier.
Definition: qkd-app-004.h:834
uint32_t m_keyBufferLengthAuthentication
The size of the authentication key queue at the application layer.
Definition: qkd-app-004.h:855
uint32_t m_packetsSent
The number of sent data packets.
Definition: qkd-app-004.h:817
std::map< uint32_t, EventId > m_scheduledEvents
The map of scheduled events.
Definition: qkd-app-004.h:865
TracedCallback< Ptr< Packet > > m_encryptionTrace
A trace callback for the encryption event.
Definition: qkd-app-004.h:845
Address m_peer
The address of the peer for the data transmission.
Definition: qkd-app-004.h:797
void Http004KMSQueryComplete(std::string uri)
Remove the request from the vector of HTTP requests made to the KMS.
void GetKeyFromKMS(std::string ksid, uint32_t index=0)
Get key for the key stream.
ns3::TracedCallback< const std::string &, const std::string & > m_stateTransitionTrace
A trace for the application state transitions.
Definition: qkd-app-004.h:558
uint32_t GetKeyTypeFromHttp004KMSQuery(std::string uri)
Map the HTTP reponse from the KMS and obtain the key type.
std::string m_socketType
The sockets type.
Definition: qkd-app-004.h:805
std::unordered_map< Address, Ptr< Packet >, AddressHash > m_buffer_qkdapp
The buffer for received data packets (fragmentation).
Definition: qkd-app-004.h:863
uint32_t m_packetSize
The data packet size.
Definition: qkd-app-004.h:807
void DataToKMSSend(Ptr< Socket >, uint32_t)
Callback function to notify that data to KMS has been sent.
TracedCallback< Ptr< const Packet > > m_txSigTrace
A trace for transmitted signaling packets.
Definition: qkd-app-004.h:553
void PrepareSinkSocketFromApp()
Prepare the sink socket to listen from the peer QKD Application.
Definition: qkd-app-004.cc:452
void HandleAcceptSignalingFromApp(Ptr< Socket > s, const Address &from)
Handle a signaling incoming connection from the peer QKD application.
Definition: qkd-app-004.cc:558
uint32_t m_aesLifetime
The AES key lifetime.
Definition: qkd-app-004.h:844
void ClearAssociation(std::string ksid)
Delete all records of key stream session identified with a given KSID.
bool m_primaryQueueEstablished
Is the queue established at the sender application?
Definition: qkd-app-004.h:606
void ProcessSendKsidResponse(HTTPMessage &header, std::string ksid)
Process the SEND_KSID response.
virtual ~QKDApp004()
Destructor.
Definition: qkd-app-004.cc:201
Ptr< UniformRandomVariable > m_random
The uniform random variable.
Definition: qkd-app-004.h:609
void HandleReadSignalingFromApp(Ptr< Socket > socket)
Handle a signaling packet received from the peer QKD application.
Definition: qkd-app-004.cc:925
virtual void StartApplication(void)
EventId m_closeSocketEvent
The closing socket event.
Definition: qkd-app-004.h:814
TracedCallback< const uint32_t & > m_obtainedKeyMaterialTrace
A trace callback for the obtained key material.
Definition: qkd-app-004.h:850
void ProcessCreateQueuesResponse()
Start establishing key queues at the reciving application once requested by the sender.
std::string GetKsidFromHttp004AppQuery(void)
Map the HTTP response from the peer QKD application and obtain the key stream identifier.
Ptr< Socket > m_sendDataSocketApp
The sending socket for the data.
Definition: qkd-app-004.h:791
void HandleAcceptFromApp(Ptr< Socket > s, const Address &from)
Handle an incoming connection from the peer QKD application.
Definition: qkd-app-004.cc:546
uint32_t GetMethodFromHttp004KMSQuery(std::string uri)
Read the ETSI request method from the URI.
Address m_peerSignaling
The address of the peer for the signaling data transmission.
Definition: qkd-app-004.h:798
QKDEncryptor::EncryptionType m_encryptionType
The encryption algorithm.
Definition: qkd-app-004.h:851
Ptr< Packet > m_maliciousPacket
The malicious packet.
Definition: qkd-app-004.h:823
uint32_t GetEncryptionKeySize()
Get the required key size for the choosen encryption algorithm.
void ConnectionSignalingToAppFailed(Ptr< Socket > socket)
Callback function after the signaling connection to the APP has failed.
Definition: qkd-app-004.cc:600
Address m_kms
The local KMS address.
Definition: qkd-app-004.h:803
EventId m_sendEvent
The data transmission event.
Definition: qkd-app-004.h:813
void Close(std::string ksid)
Close the keys stream session (the association).
void HandlePeerErrorSignalingFromApp(Ptr< Socket > socket)
Handle a signaling connection error from the peer QKD application.
Definition: qkd-app-004.cc:669
Ptr< Socket > m_sinkSocketFromKMS
The receiving socket from the KMS.
Definition: qkd-app-004.h:795
void InitializeAssociations()
Initialize the key stream sessions.
uint32_t m_ttl
The time-to-live of the key stream session.
Definition: qkd-app-004.h:828
void ProcessPacketsToKMSFromQueue()
Process and send any remaining packets to the KMS.
Definition: qkd-app-004.cc:728
void CloseSocketToKms()
Close the connecting sockets with the KMS.
Definition: qkd-app-004.cc:718
uint32_t GetAuthenticationKeySize()
Get the required key size for the choosen authentication algorithm.
std::pair< Association004, Association004 > m_associations
A pair (encryption/authentication) of the establihed key stream session.
Definition: qkd-app-004.h:604
bool ConnectionRequestedFromKMS(Ptr< Socket > socket, const Address &address)
Callback function after the connection for response from the KMS has been received.
Definition: qkd-app-004.cc:521
uint32_t m_dataSent
The amount of the sent data.
Definition: qkd-app-004.h:818
void PrepareSendSocketToKMS()
Prepare the send socket to communicate with the KMS Application.
Definition: qkd-app-004.cc:368
uint64_t GetMaxEncryptionKeyRate()
Get the maximum key rate required for the encryption (QoS settings).
void ProcessCloseResponse(HTTPMessage &header)
Process the CLOSE response.
void PacketReceivedFromKMS(const Ptr< Packet > &p, const Address &from, Ptr< Socket > socket)
Check for the tcp segmentation of packets received from the KMS.
Definition: qkd-app-004.cc:757
std::string GetPacketContent(uint32_t msgLength=0)
Generate a random packet payload (the message).
bool m_replicaQueueEstablished
Is the queue established at the receiver application?
Definition: qkd-app-004.h:607
TracedCallback< Ptr< const Packet > > m_rxKmsTrace
A trace for received packets from the KMS.
Definition: qkd-app-004.h:557
void Http004KMSQuery(std::string uri, std::string ksid, uint32_t keyType)
Memories the HTTP request made to the local KMS.
void ConnectionSignalingToAppSucceeded(Ptr< Socket > socket)
Callback function after the signaling connection to the APP is complete.
Definition: qkd-app-004.cc:594
void ConnectionToAppSucceeded(Ptr< Socket > socket)
Callback function after the connection to the APP is complete.
Definition: qkd-app-004.cc:582
Time m_holdTime
The holding time before closing sockets.
Definition: qkd-app-004.h:815
std::map< std::string, std::pair< std::string, uint32_t > > m_httpRequestsKMS
A vector of HTTP requests set to the KMS.
Definition: qkd-app-004.h:832
std::vector< std::pair< uint32_t, std::string > > m_httpRequestsApp
A vector of HTTP requests sent to the peer application.
Definition: qkd-app-004.h:831
Ptr< Socket > m_sendSocketToKMS
The sending socket to the KMS.
Definition: qkd-app-004.h:794
TracedCallback< Ptr< const Packet > > m_txKmsTrace
A trace for transmitted packets to the KMS.
Definition: qkd-app-004.h:554
TracedCallback< Ptr< const Packet >, std::string > m_mxTrace
A trace for the missed time slots to send data (due to the lack of keys).
Definition: qkd-app-004.h:559
TypeId m_tid
The type identifier.
Definition: qkd-app-004.h:819
void SignalingPacketReceivedFromApp(const Ptr< Packet > &p, const Address &from, Ptr< Socket > socket)
Check for the tcp segmentation of the signaling packets received from the peer application.
Definition: qkd-app-004.cc:957
QKDAppState GetAppState() const
Get the current state of the application.
void HandlePeerErrorFromApp(Ptr< Socket > socket)
Handle a connection error from the peer QKD application.
Definition: qkd-app-004.cc:657
uint64_t GetMaxAuthenticationKeyRate()
Get the maximum key rate required for the authentication (QoS settings).
QKDEncryptor::AuthenticationType m_authenticationType
The authentication algorithm.
Definition: qkd-app-004.h:852
void CreateKeyQueuesResponse()
Once the receiving application establishes the queues, it sends a response to the sender application.
Ptr< QKDEncryptor > m_encryptor
The QKD encryptor.
Definition: qkd-app-004.h:853
void HandlePeerCloseSignalingFromApp(Ptr< Socket > socket)
Handle a signaling connection close from the peer QKD application.
Definition: qkd-app-004.cc:663
uint32_t m_priority
The application priority (QoS).
Definition: qkd-app-004.h:827
std::string GetKsidFromHttp004KMSQuery(std::string uri)
Map the HTTP response from the KMS and obtain the key stream identifier.
uint32_t m_authenticationTagLengthInBits
The size of the authentication tag in bits (32 by default).
Definition: qkd-app-004.h:843
Address m_local
The local address for the data transmission.
Definition: qkd-app-004.h:800
void SetEncryptionAndAuthenticationSettings(uint32_t encryptionType, uint32_t authenticationType, uint32_t authenticationTagLengthInBits)
Set the encryption and the authentication algorithms.
void SendKsidResponse(HTTPMessage::HttpStatus httpStatus, std::string msg="")
Send a response on the SEND_KSID request.
uint32_t m_master
Is a master (sender/primary) application?
Definition: qkd-app-004.h:820
void CreateKeyQueues()
Create the required key queues to store a set amount of keys from the respective key stream sessions.
void ProcessResponseFromKMS(HTTPMessage &header, Ptr< Packet > packet, Ptr< Socket > socket)
Process a response from the KMS application.
void HandlePeerCloseToKMS(Ptr< Socket > socket)
Handle a connection close to the KMS.
Definition: qkd-app-004.cc:618
void SwitchAppState(QKDAppState state)
Change the state of the application.
void CheckQueues()
Request new keys from the KMS until the key queues at the application layer are established with a se...
void CheckAssociationsState()
Check if the required key stream sessions are successfuly established.
std::unordered_map< Address, Ptr< Packet >, AddressHash > m_buffer_sig
The buffer for the received signaling packets (fragmentation).
Definition: qkd-app-004.h:862
void ConnectionToAppFailed(Ptr< Socket > socket)
Callback function after the connection to the APP has failed.
Definition: qkd-app-004.cc:588
void CreateKeyStreamAssociations()
void HandlePeerCloseFromKMS(Ptr< Socket > socket)
Handle a connection close from the KMS.
Definition: qkd-app-004.cc:606
TracedCallback< Ptr< Packet > > m_decryptionTrace
A trace callback for the decryption event.
Definition: qkd-app-004.h:846
UUID GetId(void)
Get the application identifier.
Definition: qkd-app-004.h:541
uint32_t m_malicious
Is a malicious application?
Definition: qkd-app-004.h:821
void AppTransitionTree(void)
Transition through a tree of the application states and trigger actions.
void HandleReadFromKMS(Ptr< Socket > socket)
Handle a packet received by the QKD application from the KMS application.
Definition: qkd-app-004.cc:675
Ptr< Socket > m_sendSignalingSocketApp
The sending socket for the signaling messages.
Definition: qkd-app-004.h:789
std::string PacketToString(Ptr< Packet > packet)
Convert the packet to a string.
DataRate m_minDataRate
The minimum application data rate.
Definition: qkd-app-004.h:811
static uint32_t m_applicationCounts
The number of running applications.
Definition: qkd-app-004.h:837
QKDAppKey GetEncKey()
Get the encryption key from the queue.
Ptr< Socket > m_sinkDataSocketApp
The receiving socket for the data.
Definition: qkd-app-004.h:792
TracedCallback< Ptr< const Packet >, std::string > m_txTrace
Definition: qkd-app-004.h:552
void ScheduleTx(void)
Schedule the next time slot to send the data.
Definition: qkd-app-004.cc:291
uint32_t m_encryptionTypeInt
The encryption algorithm.
Definition: qkd-app-004.h:841
TracedCallback< Ptr< const Packet >, std::string > m_rxTrace
A trace for received data packets.
Definition: qkd-app-004.h:555
void DataPacketReceivedFromApp(const Ptr< Packet > &p, const Address &from, Ptr< Socket > socket)
Check for the tcp segmentation of the signaling packets received from the KMS.
Definition: qkd-app-004.cc:870
void SendKsidRequest(std::string ksid, uint32_t input)
Inform the peer QKD application of the established key stream session.
void PrepareSendSocketToApp()
Prepare the send socket to communicate with the peer QKD Application.
Definition: qkd-app-004.cc:402
std::vector< KMSPacket > m_queue_kms
The queue of packets waiting for the transmission to the KMS.
Definition: qkd-app-004.h:859
void Http004AppQuery(uint32_t methodType, std::string ksid)
Memories the HTTP request made to the peer QKD application.
void HandlePeerErrorToKMS(Ptr< Socket > socket)
Handle a connection error to the KMS.
Definition: qkd-app-004.cc:635
std::unordered_map< Address, Ptr< Packet >, AddressHash > m_buffer_kms
The buffer for the received packets from the KMS (fragmentation).
Definition: qkd-app-004.h:861
void Setup(std::string socketType, Address src, Address dst, Address kms, UUID dstSaeId, std::string type)
Configure the application.
Definition: qkd-app-004.cc:215
uint32_t m_authenticationTypeInt
The authentication algorithm.
Definition: qkd-app-004.h:842
QKD app packet header that carries info about used encryption, auth tag and other.
std::string GetEncryptionKeyId(void) const
Read the encryption key identifier.
std::string GetAuthTag(void) const
Read the authentication tag.
uint32_t GetSerializedSize() const
Get the serialized size of a packet.
void SetEncryptionKeyId(std::string value)
Set the encryption key identifier.
void SetEncrypted(uint32_t value)
Set the encrypted field.
uint32_t GetLength(void) const
Get message length.
void SetLength(uint32_t value)
Set the message length.
void SetAuthenticated(uint32_t value)
Set the authentication field.
uint32_t GetAuthenticated(void) const
Read the authentication field.
void SetAuthTag(std::string value)
Set the authentication tag.
std::string GetAuthenticationKeyId(void) const
Read the authentication key identifier.
void SetAuthenticationKeyId(std::string keyID)
Set the authentication key identifier.
uint32_t GetEncrypted(void) const
Read the encrypted field.
static void Cancel(const EventId &id)
Set the cancel bit on this event: the event's associated function will not be invoked when it expires...
Definition: simulator.cc:268
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:556
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
virtual int Send(Ptr< Packet > p, uint32_t flags)=0
Send data (or dummy data) to the remote host.
void SetConnectCallback(Callback< void, Ptr< Socket > > connectionSucceeded, Callback< void, Ptr< Socket > > connectionFailed)
Specify callbacks to allow the caller to determine if the connection succeeds of fails.
Definition: socket.cc:84
void SetAcceptCallback(Callback< bool, Ptr< Socket >, const Address & > connectionRequest, Callback< void, Ptr< Socket >, const Address & > newConnectionCreated)
Accept connection requests from remote hosts.
Definition: socket.cc:104
virtual int Listen(void)=0
Listen for incoming connections.
void SetDataSentCallback(Callback< void, Ptr< Socket >, uint32_t > dataSent)
Notify application when a packet has been sent from transport protocol (non-standard socket call)
Definition: socket.cc:114
virtual int GetPeerName(Address &address) const =0
Get the peer address of a connected socket.
virtual int ShutdownSend(void)=0
virtual int Connect(const Address &address)=0
Initiate a connection to a remote host.
virtual int Close(void)=0
Close a socket.
void SetCloseCallbacks(Callback< void, Ptr< Socket > > normalClose, Callback< void, Ptr< Socket > > errorClose)
Detect socket recv() events such as graceful shutdown or error.
Definition: socket.cc:94
void SetRecvCallback(Callback< void, Ptr< Socket > > receivedData)
Notify application when new data is available to be read.
Definition: socket.cc:128
static Ptr< Socket > CreateSocket(Ptr< Node > node, TypeId tid)
This method wraps the creation of sockets that is performed on a given node by a SocketFactory specif...
Definition: socket.cc:71
virtual int Bind(const Address &address)=0
Allocate a local endpoint for this socket.
virtual Ptr< Packet > RecvFrom(uint32_t maxSize, uint32_t flags, Address &fromAddress)=0
Read a single packet from the socket and retrieve the sender address.
static TypeId GetTypeId(void)
Get the type ID.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
AttributeValue implementation for Time.
Definition: nstime.h:1308
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
AttributeValue implementation for TypeId.
Definition: type-id.h:595
Universally unique identifier (UUID)
Definition: uuid.h:35
static UUID Random()
Generate random UUID4 (randomly or pseudo-randomly generated version)
Definition: uuid.cc:148
static UUID Sequential()
Generate sequential UUID1 (time based version)
Definition: uuid.cc:92
std::string string() const
Get string from the current UUID in format "00000000-0000-0000-0000-000000000000".
Definition: uuid.cc:74
static TypeId GetTypeId(void)
Get the type ID.
Hold an unsigned integer type.
Definition: uinteger.h:44
double GetValue(double min, double max)
Get the next random value, as a double in the specified range .
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:67
Ptr< const AttributeAccessor > MakeDataRateAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: data-rate.h:298
Ptr< const AttributeChecker > MakeDataRateChecker(void)
Definition: data-rate.cc:30
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: nstime.h:1309
Ptr< const AttributeAccessor > MakeTypeIdAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: type-id.h:595
Ptr< const AttributeChecker > MakeTypeIdChecker(void)
Definition: type-id.cc:1226
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: uinteger.h:45
Callback< R, Ts... > MakeNullCallback(void)
Definition: callback.h:1688
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:165
#define NS_ABORT_IF(cond)
Abnormal program termination if a condition is true.
Definition: abort.h:77
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1244
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
basic_json<> json
default JSON class
Definition: json.h:3000
NLOHMANN_BASIC_JSON_TPL_DECLARATION std::string to_string(const NLOHMANN_BASIC_JSON_TPL &j)
user-defined to_string function for JSON values
Definition: json.h:25255
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:522
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:1648
A cryptographic key at the application layer.
Definition: qkd-app-004.h:586
static const uint32_t packetSize