A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
qkd-app-004.cc
Go to the documentation of this file.
1/*
2 * Copyright(c) 2020 DOTFEESA www.tk.etf.unsa.ba
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 *
7 *
8 * Author: Emir Dervisevic <emir.dervisevic@etf.unsa.ba>
9 * Miralem Mehic <miralem.mehic@ieee.org>
10 */
11
12#include "ns3/address.h"
13#include "ns3/address-utils.h"
14#include "ns3/log.h"
15#include "ns3/inet-socket-address.h"
16#include "ns3/inet6-socket-address.h"
17#include "ns3/node.h"
18#include "ns3/socket.h"
19#include "ns3/udp-socket-factory.h"
20#include "ns3/tcp-socket-factory.h"
21#include "ns3/simulator.h"
22#include "ns3/socket-factory.h"
23#include "ns3/packet.h"
24#include "ns3/trace-source-accessor.h"
25#include "qkd-app-004.h"
26
27namespace ns3 {
28
29NS_LOG_COMPONENT_DEFINE("QKDApp004");
30
32
33TypeId
35{
36 static TypeId tid = TypeId("ns3::QKDApp004")
38 .SetGroupName("Applications")
39 .AddConstructor<QKDApp004>()
40 .AddAttribute("Protocol", "The type of protocol to use.",
44 .AddAttribute("LengthOfAuthenticationTag",
45 "The default length of the authentication tag",
46 UintegerValue(256), //32 bytes
49 .AddAttribute("EncryptionType",
50 "The type of encryption to be used(0-unencrypted, 1-OTP, 2-AES)",
54 .AddAttribute("AuthenticationType",
55 "The type of authentication to be used(0-unauthenticated, 1-VMAC, 2-MD5, 3-SHA1)",
59 .AddAttribute("AESLifetime",
60 "Lifetime of AES key expressed in number of packets",
64 .AddAttribute("UseCrypto",
65 "Should crypto functions be performed(0-No, 1-Yes)",
69 .AddAttribute("LengthOfKeyBufferForEncryption",
70 "How many keys to store in local buffer of QKDApp004 for encryption?",
71 UintegerValue(10),
74 .AddAttribute("LengthOfKeyBufferForAuthentication",
75 "How many keys to store in local buffer of QKDApp004 for authentication?",
76 UintegerValue(10),
79 .AddAttribute("SocketToKMSHoldTime","How long(seconds) should QKDApp004 wait to close socket to KMS after receiving REST response?",
80 TimeValue(Seconds(0.5)),
83
84 .AddTraceSource("Tx", "A new packet is created and is sent",
86 "ns3::Packet::TracedCallback")
87 .AddTraceSource("TxSig", "A new signaling packet is created and is sent",
89 "ns3::Packet::TracedCallback")
90 .AddTraceSource("TxKMS", "A new packet is created and is sent to local KMS",
92 "ns3::Packet::TracedCallback")
93 .AddTraceSource("Rx", "A new packet is received",
95 "ns3::Packet::TracedCallback")
96 .AddTraceSource("RxSig", "A new signaling packet is received",
98 "ns3::Packet::TracedCallback")
99 .AddTraceSource("RxKMS", "A new packet is received from local KMS",
101 "ns3::Packet::TracedCallback")
102 .AddTraceSource("StateTransition",
103 "Trace fired upon every QKDApp state transition.",
105 "ns3::Application::StateTransitionCallback")
106 .AddTraceSource("PacketEncrypted",
107 "The change trance for currenly ecrypted packet",
109 "ns3::QKDCrypto::PacketEncrypted")
110 .AddTraceSource("PacketDecrypted",
111 "The change trance for currenly decrypted packet",
113 "ns3::QKDCrypto::PacketDecrypted")
114 .AddTraceSource("PacketAuthenticated",
115 "The change trance for currenly authenticated packet",
117 "ns3::QKDCrypto::PacketAuthenticated")
118 .AddTraceSource("PacketDeAuthenticated",
119 "The change trance for currenly deauthenticated packet",
121 "ns3::QKDCrypto::PacketDeAuthenticated")
122 .AddTraceSource("Mx", "Missed send packet call",
124 "ns3::Packet::TracedCallback")
125 ;
126
127 return tid;
128}
129
130
132
133/**
134 * ********************************************************************************************
135
136 * SETUP
137
138 * ********************************************************************************************
139 */
140
142 : m_signalingSocketApp(nullptr),
143 m_dataSocketApp(nullptr),
144 m_socketToKMS(nullptr),
145 m_packetSize(0),
146 m_dataRate(0),
147 m_sendEvent(),
148 m_packetsSent(0),
149 m_dataSent(0),
150 m_master(0),
151 m_encryptor(0),
152 m_state(NOT_STARTED)
153{
155}
156
161
162void
164{
165 NS_LOG_FUNCTION(this);
166
167 //Data sockets
168 m_dataSocketApp = nullptr;
169 //Signaling sockets
170 m_signalingSocketApp = nullptr;
171 //KMS sockets
172 m_socketToKMS = nullptr;
173
175}
176
177void
179 std::string socketType,
180 std::string appId,
181 std::string remoteAppId,
182 const Address& appAddress,
184 const Address& kmAddress,
185 std::string type
186){
187 Setup(
189 appId,
193 kmAddress,
194 0,
195 0,
196 type
197 );
198}
199
200void
202 std::string socketType,
203 std::string appId,
204 std::string remoteAppId,
205 const Address& appAddress,
207 const Address& kmAddress,
210 std::string type
211)
212{
213 NS_LOG_FUNCTION(this);
214 if(type == "alice")
215 m_master = 1;
216 else
217 m_master = 0;
218
220 if(!remoteAppAddress.IsInvalid())
222
224 if(!appAddress.IsInvalid())
226
227 NS_LOG_FUNCTION(this << kmAddress);
228 if(!kmAddress.IsInvalid())
230
232 NS_LOG_FUNCTION(this << "Peer IP " << InetSocketAddress::ConvertFrom(m_peer).GetIpv4() << " and port " << m_portSignaling );
233
235 m_appId = appId;
236
240
241 //Initialize key stream sessions
244
247
251
253
254}
255
256/**
257 * ********************************************************************************************
258
259 * SCHEDULE functions
260
261 * ********************************************************************************************
262 */
263void
265{
266 NS_LOG_FUNCTION(this);
267 if(GetState() != STOPPED && GetState() != NOT_STARTED){
268 NS_LOG_FUNCTION(this << "is running!");
269 double delay = m_packetSize * 8 / static_cast<double>(m_dataRate.GetBitRate());
270 NS_LOG_FUNCTION(this << "scheduled in" << Seconds(delay) );
271 Time tNext(Seconds(delay));
273
274 }else
275 NS_LOG_FUNCTION(this << "is" << GetAppStateString(GetState()));
276
277}
278
279
280/**
281 * ********************************************************************************************
282
283 * SOCKET functions
284
285 * ********************************************************************************************
286 */
287
288void
290{
291 NS_LOG_FUNCTION(this);
292 if(!m_socketToKMS)
294
296 if(m_socketToKMS->GetPeerName(temp) != 0 ) {
300 );
305 );
309 );
318 );
322 NS_LOG_FUNCTION(this << "send socket created" << m_socketToKMS);
323
324 }else
325 NS_LOG_FUNCTION(this << "socket exists" << m_socketToKMS);
326
327}
328
329
330void
332{
333 NS_LOG_FUNCTION(this);
334
335 ////////////////
336 // SIGNALING SOCKET
337 ////////////////
338
340 {
341
345 );
346
350 );
351
353
355 {
356 NS_LOG_FUNCTION(this << "Let's create signaling socket to peer APP!");
357
362 );
367 );
371 );
372 if(m_master)
374 }
375
377 {
378 if(m_master)
379 {
380 NS_LOG_FUNCTION(this << "Let's connect to peer!");
381
383 NS_LOG_DEBUG(this << " Connect() return value= " << ret << " GetErrNo= " << m_signalingSocketApp->GetErrno()
384 << ".");
385 NS_ASSERT_MSG(m_signalingSocketApp, "Failed creating socket.");
386
387 }else{
389 {
390 NS_FATAL_ERROR("Failed to bind socket");
391 }
392 NS_LOG_FUNCTION(this << "PEER Listen");
394 }
395 }
396 }
397
398 ////////////////
399 // DATA SOCKET
400 ////////////////
401
403 {
404
408 );
409
413 );
414
415 if(!m_dataSocketApp)
416 {
417 NS_LOG_FUNCTION(this << "Let's create DATA socket to peer APP!");
418
419 if(m_socketType == "tcp")
421 else
423
427 );
432 );
436 );
437 if(m_master)
439 }
440
442 {
443 if(m_master)
444 {
445 NS_LOG_FUNCTION(this << "Let's connect to DATA peer!");
446
448 NS_LOG_DEBUG(this << " Connect() return value= " << ret << " GetErrNo= " << m_dataSocketApp->GetErrno()
449 << ".");
450 NS_ASSERT_MSG(m_dataSocketApp, "Failed creating DATA socket.");
451
452 }else{
454 {
455 NS_FATAL_ERROR("Failed to bind DATA socket");
456 }
457 NS_LOG_FUNCTION(this << "PEER DATA Listen");
459 }
460 }
461
462 }else
463 NS_LOG_FUNCTION(this << "sockets exists" << m_signalingSocketApp << m_dataSocketApp);
464
465}
466
467
468bool
470{
471 NS_LOG_FUNCTION(this << socket << from
472 << InetSocketAddress::ConvertFrom(from).GetIpv4()
473 << InetSocketAddress::ConvertFrom(from).GetPort()
474 );
475 NS_LOG_FUNCTION(this << "requested on" << socket);
476 return true; //Accept the connection request
477}
478
479
480bool
482{
483 NS_LOG_FUNCTION(this << socket << from
484 << InetSocketAddress::ConvertFrom(from).GetIpv4()
485 << InetSocketAddress::ConvertFrom(from).GetPort()
486 );
487 NS_LOG_FUNCTION(this << "requested on socket " << socket);
489
490 return true;
491}
492
493bool
495{
496 NS_LOG_FUNCTION(this << socket << from
497 << InetSocketAddress::ConvertFrom(from).GetIpv4()
498 << InetSocketAddress::ConvertFrom(from).GetPort()
499 );
500 NS_LOG_FUNCTION(this << "requested on socket " << socket);
502
503 return true;
504}
505
506
507void
509{
511 NS_LOG_FUNCTION(this << socket << from
512 << InetSocketAddress::ConvertFrom(from).GetIpv4()
513 << InetSocketAddress::ConvertFrom(from).GetPort()
514 );
515 NS_LOG_FUNCTION(this << "accepted on" << socket);
516 socket->SetRecvCallback(MakeCallback(&QKDApp004::HandleReadFromKMS, this));
518
519}
520
521void
523{
524 NS_LOG_FUNCTION(this << s << from
525 << InetSocketAddress::ConvertFrom(from).GetIpv4()
526 << InetSocketAddress::ConvertFrom(from).GetPort()
527 );
528 m_dataSocketApp = s;
529 NS_LOG_FUNCTION(this << "accepted on socket " << s);
530 s->SetRecvCallback(MakeCallback(&QKDApp004::HandleReadFromApp, this));
531
532}
533
534void
536{
537 NS_LOG_FUNCTION(this << s << from
538 << InetSocketAddress::ConvertFrom(from).GetIpv4()
539 << InetSocketAddress::ConvertFrom(from).GetPort()
540 );
542 NS_LOG_FUNCTION(this << "accepted on socket " << s);
543 s->SetRecvCallback(MakeCallback(&QKDApp004::HandleReadSignalingFromApp, this));
544
545}
546
547void
549{
550 NS_LOG_FUNCTION(this << socket << "succeeded via socket " << socket);
551}
552
553void
555{
556 NS_LOG_FUNCTION(this << socket << "failed via socket " << socket);
557}
558
559void
561{
562 NS_LOG_FUNCTION(this << s << "succeeded via socket " << s);
564}
565
566void
568{
569 NS_LOG_FUNCTION(this << socket << "failed via socket " << socket);
570}
571
572void
574{
575 NS_LOG_FUNCTION(this << s << "succeeded via socket " << s);
577}
578
579void
581{
582 NS_LOG_FUNCTION(this << socket << "failed via socket " << socket);
583}
584
585void
587{
588 NS_LOG_FUNCTION(this << socket);
589}
590
591void
593{
594 NS_LOG_FUNCTION(this << socket);
595}
596
597void
599{
600 NS_LOG_FUNCTION(this << socket);
601 if(socket == m_socketToKMS){
605 );
606 m_socketToKMS = nullptr;
607 }
608}
609
610void
612{
613 NS_LOG_FUNCTION(this << socket);
614 if(socket == m_socketToKMS){
618 );
619 m_socketToKMS = nullptr;
620
621 }
622}
623
624void
626{
627 NS_LOG_FUNCTION(this << socket);
628}
629void
631{
632 NS_LOG_FUNCTION(this << socket);
633}
634
635void
640
641void
646
647void
649{
650 NS_LOG_FUNCTION(this << socket);
651 if(GetState() == STOPPED) return;
652 Ptr<Packet> packet;
653 Address from;
654 while((packet = socket->RecvFrom(from))){
655 if(packet->GetSize() == 0) //EOF
656 break;
657
658 NS_LOG_FUNCTION(this
659 << packet << "PACKETID: " << packet->GetUid()
660 << " of size: " << packet->GetSize()
661 );
662
664 NS_LOG_FUNCTION("At time " << Simulator::Now().GetSeconds()
665 << "s packet from KMS received "
666 << packet->GetSize() << " bytes from "
668 << " port " << InetSocketAddress::ConvertFrom(from).GetPort()
669 );
670
671 }
672 PacketReceivedFromKMS(packet, from, socket);
673 }
675
676}
677
678void
680{
681 NS_LOG_FUNCTION(this << m_queue_kms.size());
683
684 //Check is the socket to KMS active and connected
686 {
688 }else{
689 if(m_queue_kms.size() > 0){
690 uint32_t c = 0;
691 auto it = m_queue_kms.begin();
692 while(it != m_queue_kms.end()){
693 NS_LOG_FUNCTION(this << c << m_queue_kms.size() << GetSessionScope( it->scope ));
694 PushHttpKmsRequest(it->uri, it->scope);
695 if(it->packet ) {
696 m_txKmsTrace(GetId(), it->packet);
697 m_socketToKMS->Send(it->packet);
698
699 }
700 m_queue_kms.erase(it);
701 c++;
702
703 }
704 }
705 }
706}
707
708void
710{
711 NS_LOG_FUNCTION(this << p->GetUid() << p->GetSize() << from);
712
713 // Initialize or retrieve buffer
714 Ptr<Packet> &buffer = m_buffer_kms[from];
715 if (!buffer) buffer = Create<Packet>(0);
716 buffer->AddAtEnd(p);
717
718 HTTPMessageParser parser;
719 while (buffer->GetSize() > 0) {
720 // Copy buffer to string for parsing
721 std::string bufferStr(buffer->GetSize(), '\0');
722 buffer->CopyData(reinterpret_cast<uint8_t*>(&bufferStr[0]), bufferStr.size());
723
724 // Try to extract one complete HTTP message
725 std::string httpMsgStr;
726 size_t httpMsgSize = 0;
727 if (!parser.TryExtractHttpMessage(bufferStr, httpMsgStr, httpMsgSize)) {
728 NS_LOG_DEBUG("[DEBUG] Fragmented or incomplete HTTP message. Awaiting more data.");
729 break;
730 }
731
732 // Parse HTTP message
734 parser.Parse(&request, httpMsgStr);
735
736 if (request.IsFragmented() || request.GetSize() == 0) {
737 NS_LOG_DEBUG("[DEBUG] Detected fragmented or invalid HTTP message. Waiting for more data...");
738 break;
739 }
740
741 // Remove parsed message from buffer
742 Ptr<Packet> completePacket = buffer->CreateFragment(0, static_cast<uint32_t>(httpMsgSize));
743 buffer->RemoveAtStart(static_cast<uint32_t>(httpMsgSize));
744
747
748 NS_LOG_DEBUG("[DEBUG] Processed HTTP message, UID: " << p->GetUid());
749 NS_LOG_DEBUG("[DEBUG] Remaining buffer size: " << buffer->GetSize());
750 }
751}
752
753
754void
756{
757 NS_LOG_FUNCTION(this << socket);
758 Ptr<Packet> packet;
759 Address from;
760 while((packet = socket->RecvFrom(from))){
761 if(packet->GetSize() == 0) //EOF
762 break;
763
764 NS_LOG_FUNCTION(this << packet
765 << "PACKETID: " << packet->GetUid()
766 << " of size: " << packet->GetSize()
767 );
769 NS_LOG_FUNCTION( this << "At time " << Simulator::Now().GetSeconds()
770 << "s packet from APP pair received "
771 << packet->GetSize() << " bytes from "
773 << " port " << InetSocketAddress::ConvertFrom(from).GetPort() << "\n");
774
775 }
776 DataPacketReceived(packet, from, socket);
777 }
778}
779
780void
782{
783 NS_LOG_FUNCTION( this << m_master << p->GetUid() << p->GetSize() << from );
785
786 if(GetState() == READY)
787 { //Must be ready to receive data
788 QKDAppHeader header;
789 Ptr<Packet> buffer;
790
791 auto itBuffer = m_buffer_qkdapp.find(from);
792 if(itBuffer == m_buffer_qkdapp.end())
793 itBuffer = m_buffer_qkdapp.insert(std::make_pair(from, Create<Packet>(0))).first;
794
795 buffer = itBuffer->second;
796 buffer->AddAtEnd(p);
797 buffer->PeekHeader(header);
798 NS_ABORT_IF(header.GetLength() == 0);
799
800 while(buffer->GetSize() >= header.GetLength())
801 {
802 NS_LOG_DEBUG("Removing packet of size " << header.GetLength() << " from buffer of size " << buffer->GetSize());
803 Ptr<Packet> completePacket = buffer->CreateFragment(0, static_cast<uint32_t>(header.GetLength()));
804 buffer->RemoveAtStart(static_cast<uint32_t>(header.GetLength()));
805
807 completePacket->RemoveHeader(header);
808 NS_LOG_FUNCTION(this << "received qkdapp header" << header);
809
810 ProcessDataPacket(header, completePacket, socket);
811 if(buffer->GetSize() > header.GetSerializedSize())
812 buffer->PeekHeader(header);
813 else
814 break;
815 }
816
817 }else
818 NS_LOG_DEBUG(this << "invalid state " << GetAppStateString());
819
820}
821
822void
824{
825 NS_LOG_FUNCTION(this << socket);
826 Ptr<Packet> packet;
827 Address from;
828 while((packet = socket->RecvFrom(from))){
829 if(packet->GetSize() == 0) //EOF
830 break;
831
832 NS_LOG_FUNCTION(this << packet
833 << "PACKETID: " << packet->GetUid()
834 << " of size: " << packet->GetSize()
835 );
837 NS_LOG_FUNCTION( this << "At time " << Simulator::Now().GetSeconds()
838 << "s signaling packet from APP pair received "
839 << packet->GetSize() << " bytes from "
841 << " port " << InetSocketAddress::ConvertFrom(from).GetPort() << "\n");
842
843 }
844 SignalingPacketReceivedFromApp(packet, from, socket);
845 }
846}
847void
849{
850 NS_LOG_FUNCTION(this << p->GetUid() << p->GetSize() << from);
851
852 // Maintain or create buffer for the sender
853 Ptr<Packet> &buffer = m_buffer_sig[from];
854 if (!buffer) buffer = Create<Packet>(0);
855 buffer->AddAtEnd(p);
856
857 HTTPMessageParser parser;
859
860 while (true) {
861 if (buffer->GetSize() == 0)
862 break;
863
864 // Copy buffer content to a string
865 std::string payload(buffer->GetSize(), '\0');
866 buffer->CopyData(reinterpret_cast<uint8_t*>(&payload[0]), buffer->GetSize());
867
868 parser.Parse(&request, payload);
869
870 if (request.IsFragmented() || request.GetSize() == 0 ||
871 buffer->GetSize() < request.GetSize() ||
872 request.GetStatusMessage() == "Undefined")
873 {
874 NS_LOG_FUNCTION(this << "Incomplete/fragmented HTTP message, waiting for more data.");
875 break;
876 }
877
878 Ptr<Packet> completePacket = buffer->CreateFragment(0, static_cast<uint32_t>(request.GetSize()));
879 buffer->RemoveAtStart(static_cast<uint32_t>(request.GetSize()));
880
883
884 NS_LOG_DEBUG("Processed HTTP message: " << request.ToString());
885 NS_LOG_DEBUG("Remaining in buffer: " << buffer->GetSize());
886 }
887}
888
889
890
891void
893{
894 NS_LOG_FUNCTION(this << "sent via socket " << socket);
895}
896
897
898/**
899 * ********************************************************************************************
900
901 * KEY BUFFER functions
902
903 * ********************************************************************************************
904 */
905
906void
908{
909 NS_LOG_FUNCTION(this);
910
911 NS_ASSERT(m_master); //Only Sender QKDApp
912 bool encStream {true}, authStream {true};
913 NS_LOG_FUNCTION(this << m_encStream->GetId() << m_encStream->IsVerified() << m_authStream->GetId() << m_authStream->IsVerified());
914 if(!m_encStream->GetId().empty() && !m_encStream->IsVerified())
915 encStream = false;
916 if(!m_authStream->GetId().empty() && !m_authStream->IsVerified())
917 authStream = false;
918
921 NS_LOG_FUNCTION(this << "sessions establihed" << m_encStream->GetId() << m_authStream->GetId());
924
925 }else
926 NS_LOG_FUNCTION(this << "key stream sessions are NOT established");
927
928}
929
930void
932{
933 NS_LOG_FUNCTION(this);
934 bool encQueueReady {false};
935 bool authQueueReady {false};
936 if(m_encStream->IsVerified() && m_encStream->GetKeyCount() < m_encStream->GetSize())
937 GetKeyFromKMS(m_encStream->GetId());
938 else
939 encQueueReady = true;
940
941 if(m_authStream->IsVerified() && m_authStream->GetKeyCount() < m_authStream->GetSize())
942 GetKeyFromKMS(m_authStream->GetId());
943 else
944 authQueueReady = true;
945
947 if(!m_master){
948 NS_LOG_FUNCTION(this << m_master << "queues established");
951
952 }else if(m_master){
954 NS_LOG_FUNCTION(this << "both sides establihed queues");
957
958 }else{
959 NS_LOG_FUNCTION(this << m_master << "queues established");
961
962 }
963 }
964 }
965}
966
967
968/**
969 * ********************************************************************************************
970
971 * HTTP handling to KMS
972
973 * ********************************************************************************************
974 */
975void
977{
978 NS_LOG_FUNCTION(this << uri << sessionType);
979 m_httpRequestsKMS.insert(std::make_pair(uri, sessionType));
980}
981
984{
985 NS_LOG_FUNCTION(this << uri);
987 auto it = m_httpRequestsKMS.find("http://" + uri);
988 if(it != m_httpRequestsKMS.end()){
989 sessionType = it->second;
990 m_httpRequestsKMS.erase(it);
991 }else
992 NS_LOG_DEBUG(this << "could not map response " << uri);
993
994 return sessionType;
995
996}
997
998/**
999 * ********************************************************************************************
1000
1001 * APPLICATION functions
1002
1003 * ********************************************************************************************
1004 */
1005void
1007{
1008 NS_LOG_FUNCTION(this << m_master << m_local << m_peer);
1009
1010 m_packetsSent = 0;
1012 NS_FATAL_ERROR(this << "invalid encryption type" << m_encryption
1013 << "allowed values are(0-unencrypted, 1-OTP, 2-AES)");
1015 NS_FATAL_ERROR(this << "invalid authentication type" << m_authentication
1016 << "allowed values are(0-unauthenticated, 1-VMAC, 3-SHA2)");
1017 if(m_aesLifetime < 0){
1018 NS_FATAL_ERROR(this << "invalid AES lifetime " << m_aesLifetime
1019 << "the value must be positive");
1021 NS_FATAL_ERROR(this << "invalid AES lifetime " << m_aesLifetime
1022 << "the value must be larger than packet size " << m_packetSize);
1023
1024 if(m_encryption == 1) //OTP encryption
1026
1027 if(GetState() == INITIALIZED){
1032 );
1033 AppTransitionTree(); //Transition states
1034 PrepareSocketToApp(); //Create sink sockets for peer QKD applications
1035
1036 }else
1037 NS_FATAL_ERROR(this << "invalid state " << GetAppStateString() << " for StartApplication()");
1038
1039}
1040
1041void
1043{
1044 NS_LOG_FUNCTION(this);
1045
1047
1048 if(m_master){ //Only Sender App004 calls CLOSE
1049 if(!m_encStream->GetId().empty())
1050 Close(m_encStream->GetId()); //CLOSE encryption key stream session
1051 //NS_LOG_FUNCTION(this << "close" << "enc");
1052 if(!m_authStream->GetId().empty())
1053 Close(m_authStream->GetId()); //CLOSE authentication key stream session
1054 //NS_LOG_FUNCTION(this << "close" << "auth");
1055
1056 }else{ //Replica QKDApp closes sockets to the KMS
1058 else NS_LOG_WARN("QKDApp004 found null m_socketToKMS to close in StopApplication");
1059 }
1060
1061 //Closing app send and sink sockets
1063 else NS_LOG_WARN("QKDApp004 found null m_dataSocketApp to close in StopApplication");
1064
1066 else NS_LOG_WARN("QKDApp004 found null m_signalingSocketApp to close in StopApplication");
1067
1069 else NS_LOG_WARN("QKDApp004 found null m_socketToKMS to close in StopApplication");
1070
1071 //Clear key stream sessions
1072 m_encStream->ClearStream();
1073 m_authStream->ClearStream();
1074
1076
1077}
1078
1079void
1081{
1082 NS_LOG_FUNCTION(this);
1083
1086
1088 if(GetState() == READY) {
1089 SetState(SEND_DATA); //Direct call from SceduleTx()
1090 }
1091
1092 if(GetState() == SEND_DATA){ //Only in SEND_DATA can app send data
1093
1095 uint32_t encKeyId {0};
1096 uint32_t authKeyId {0}; //Necessary for headers
1098 if(GetEncryptionKeySize() ){ //Obtain encryption key!
1099 encKey = m_encStream->GetKey(m_packetSize);
1100 if(!encKey){
1101 NS_LOG_ERROR(this << "no encryption key available");
1102 SetState(READY);
1103 return;
1104
1105 }else{
1106 encKey->UseLifetime(m_packetSize);
1107 if(encKey->GetLifetime() == 0)
1108 GetKeyFromKMS(m_encStream->GetId());
1109 encKeyId = encKey->GetIndex();
1110 if(m_useCrypto) encryptedMsg = m_encryptor->EncryptMsg(confidentialMsg, encKey->GetKeyString());
1111 NS_LOG_FUNCTION(this << "\nConfidential message:\t\t" << confidentialMsg.size() << confidentialMsg
1112 << "\nEncryption key ID:\t\t" << encKey->GetIndex() << encKey->GetKeyString()
1113 << "\nEncrypted message:\t\t" << m_encryptor->Base64Encode(encryptedMsg));
1114 }
1115
1116 }
1117 if(GetAuthenticationKeySize() ){//Obtain authentication
1118 authKey = m_authStream->GetKey();
1119 if(!authKey){
1120 NS_LOG_ERROR(this << "no autentication key available");
1121 SetState(READY);
1122 return;
1123
1124 }else{
1125 GetKeyFromKMS(m_authStream->GetId());
1126 authKeyId = authKey->GetIndex();
1127 if(m_useCrypto) authTag = m_encryptor->Authenticate(encryptedMsg, authKey->GetKeyString());
1128 NS_LOG_FUNCTION(this << "\nAuthentication key ID:\t\t" << authKey->GetIndex() << authKey->GetKeyString()
1129 << "\nAuthentication tag:\t\t" << authTag);
1130 }
1131
1133 authTag = m_encryptor->Authenticate(encryptedMsg, "");
1134 NS_LOG_FUNCTION(this << "\nAuthentication tag:\t\t" << authTag);
1135
1136 }
1137 //Create packet with protected/unprotected data
1138 std::string msg = encryptedMsg;
1139 Ptr<Packet> packet = Create<Packet>((uint8_t*) msg.c_str(), msg.length() );
1140 NS_ASSERT(packet );
1142
1143 //Add qkd header!
1146 qHeader.SetEncryptionKeyId(std::to_string(encKeyId));
1147 qHeader.SetAuthenticated(m_authenticationType);
1148 qHeader.SetAuthenticationKeyId(std::to_string(authKeyId));
1149 qHeader.SetAuthTag(authTag);
1150 qHeader.SetLength(packet->GetSize() + qHeader.GetSerializedSize());
1151 packet->AddHeader(qHeader);
1152
1153 //Send packet!
1154 m_txTrace(GetId(), packet);
1155 m_dataSocketApp->Send(packet);
1156 m_packetsSent++;
1157 m_dataSent += packet->GetSize();
1158
1159 NS_LOG_FUNCTION(this << "packet sent" << packet->GetUid() << packet->GetSize());
1160 SetState(READY);
1161 ScheduleTx();
1162
1163 }else if(GetState() == WAIT){
1164 m_mxTrace(GetId(), nullptr);
1165 ScheduleTx();
1166 NS_LOG_FUNCTION(this << "unable to send data" << GetAppStateString(GetState()));
1167
1168 }else
1169 NS_FATAL_ERROR(this << "invalid state" << GetAppStateString(GetState()));
1170
1171}
1172
1173void
1175{
1176 NS_LOG_FUNCTION(this);
1177 NS_ASSERT(!m_master); //Only receiver App014
1178
1180 std::string payload = PacketToString(packet); //Read the packet data
1181 m_packetSize = payload.size();
1184
1185 NS_LOG_FUNCTION(this << "\n\nreceived payload" << m_encryptor->Base64Encode(payload));
1186
1188 std::string decryptedMsg;
1189 bool authSuccessful {true};
1191 {
1192 //Authentication requires QKD key
1193 if(!m_authStream->SyncStream(std::stoi(header.GetAuthenticationKeyId()))) //Key has been changed
1194 GetKeyFromKMS(m_authStream->GetId());
1195
1196 Ptr<AppKey> authKey {m_authStream->GetKey()}; //Obtain new authentication key(note that the stream is in sync before this)
1197 if(!authKey){ //Packet received out of sync(dealyed packet). Packet is dropped!
1198 NS_LOG_DEBUG(this << "key missing " << std::stoi(header.GetAuthenticationKeyId()) << " packet is DROPPED");
1199 SetState(READY);
1200 return;
1201
1202 }else
1203 GetKeyFromKMS(m_authStream->GetId());
1204
1205 NS_LOG_FUNCTION(this << "authentication key" << authKey->GetIndex() << authKey->GetKeyString());
1206 if(m_useCrypto) //Authentication
1207 if(!m_encryptor->CheckAuthentication(payload, header.GetAuthTag(), authKey->GetKeyString())) //Check AuthTag
1208 authSuccessful = false;
1209
1210 }else if(header.GetAuthenticated() && m_useCrypto){ //Authentication does not require quantum key
1211 if(!m_encryptor->CheckAuthentication(payload, header.GetAuthTag(), ""))
1212 authSuccessful = false;
1213
1214 }
1215 if(authSuccessful)
1216 NS_LOG_FUNCTION(this << "authentication successful");
1217 else{
1218 NS_LOG_DEBUG(this << "authentication failed -> packet is dropped");
1219 return;
1220 }
1221
1222 //Perform decryption
1223 if(header.GetEncrypted())
1224 {
1225 if(!m_encStream->SyncStream(std::stoi(header.GetEncryptionKeyId()))) //Synchronization
1226 GetKeyFromKMS(m_encStream->GetId()); //Calling get_key request
1227
1228 Ptr<AppKey> encKey {m_encStream->GetKey(m_packetSize)}; //Obtain new encryption key
1229 if(!encKey){ //Out of sync(delayed packet)! Packet is dropped!
1230 NS_LOG_DEBUG(this << "key missing " << std::stoi(header.GetEncryptionKeyId()) << " packet is DROPPED");
1231 GetKeyFromKMS(m_encStream->GetId());
1232 SetState(READY);
1233 return;
1234
1235 }else if(encKey->GetLifetime() == 0)
1236 GetKeyFromKMS(m_encStream->GetId());
1237
1238 NS_LOG_FUNCTION(this << "decryption key" << encKey->GetIndex() << encKey->GetKeyString());
1239 if(m_useCrypto && authSuccessful){//Packet is decrypted only when it is succesfully authenticated
1240 decryptedMsg = m_encryptor->DecryptMsg(payload, encKey->GetKeyString());
1241 NS_LOG_FUNCTION(this << "decrypted message\n" << decryptedMsg);
1242
1243 }else if(authSuccessful)//Fake decryption process
1244 NS_LOG_FUNCTION(this << "decrypted message" << payload);
1245
1246 else //Receiving unprotected packet
1247 NS_LOG_FUNCTION(this << "received message" << payload);
1248
1249 SetState(READY);
1250
1251 }
1252}
1253
1254void
1256{
1257 NS_LOG_FUNCTION(this << packet->GetUid() << packet->GetSize());
1258 std::string methodName {ReadUri(header.GetRequestUri())[5]};
1259 if(methodName == "open_connect" && GetState() != STOPPED)
1261
1262 else if(methodName == "get_key" && GetState() != STOPPED)
1263 ProcessGetKeyResponse(header);
1264
1265 else if(methodName == "close" && GetState() != STOPPED)
1266 ProcessCloseResponse(header);
1267
1268 else
1269 NS_LOG_DEBUG(this << "invalid method" << methodName);
1270
1271}
1272
1273/**
1274 * ********************************************************************************************
1275
1276 * KEY MANAGEMENT functions
1277
1278 * ********************************************************************************************
1279 */
1280
1281void
1283{
1284 NS_LOG_FUNCTION(this << ksid << sessionType);
1288 else
1290
1291 NS_LOG_FUNCTION(this << m_master << ksid << sessionType << keySize);
1293
1294 nlohmann::json msgBody {
1295 {"Source", GetId()},
1296 {"Destination", GetPeerId()}
1297 //{"Qos", {{"priority", 2}} }
1298 };
1299 if(!m_master)
1300 msgBody["Key_stream_ID"] = ksid;
1301 else
1302 msgBody["QoS"]["Key_chunk_size"] = keySize;
1303
1304 //Create packet
1305 std::string reqUri {"http://"+IpToString(GetKmsIp())+"/api/v1/keys/"+GetPeerId()+"/open_connect"};
1306 HTTPMessage httpMessage;
1307 httpMessage.CreateRequest(reqUri, "POST", msgBody.dump());
1308 httpMessage.SetHeader("User-Agent", "QKDApp004_" + GetId());
1309 std::string hMessage = httpMessage.ToString();
1310 Ptr<Packet> packet = Create<Packet>(
1311 (uint8_t*)(hMessage).c_str(),
1312 hMessage.size()
1313 );
1314 NS_ASSERT(packet );
1315
1316 Address temp; //check whether the socket to KMS is active and connected
1317 if(m_socketToKMS)
1318 {
1320 m_txKmsTrace(GetId(),packet);
1321 m_socketToKMS->Send(packet);
1322 NS_LOG_FUNCTION(this << "packet sent" << packet->GetUid() << packet->GetSize() << m_socketToKMS);
1323 }else{
1326 packet, //packet
1327 reqUri,
1329 };
1330 m_queue_kms.push_back(kmsPacket);
1331 NS_LOG_FUNCTION(this << "packet enqueued" << packet->GetUid() << packet->GetSize() << m_socketToKMS);
1332 }
1333}
1334
1335void
1337{
1338 NS_LOG_FUNCTION(this << m_master << ksid);
1339 if(GetState() == QKDApp004::STOPPED) return;
1340
1341 std::string reqUri = "http://" + IpToString(GetKmsIp()) + "/api/v1/keys/" + ksid + "/get_key";
1342 nlohmann::json msgBody {{"Key_stream_ID", ksid}};
1343
1344 //Create packet
1345 HTTPMessage httpMessage;
1346 httpMessage.CreateRequest(reqUri, "POST", msgBody.dump());
1347 httpMessage.SetHeader("User-Agent", "QKDApp004_" + GetId());
1348 std::string hMessage = httpMessage.ToString();
1349 Ptr<Packet> packet = Create<Packet>(
1350 (uint8_t*)(hMessage).c_str(),
1351 hMessage.size()
1352 );
1353 NS_ASSERT(packet );
1354
1355 Address temp; //Check whether the socket to KMS is active and connected
1357 {
1360 packet,
1361 reqUri,
1362 KeyStreamSession::ENCRYPTION //not important
1363 };
1364 m_queue_kms.push_back(kmsPacket);
1365 NS_LOG_FUNCTION(this << "packet enqueud" << packet->GetUid() << packet->GetSize() << m_socketToKMS);
1366
1367 }else{
1368 PushHttpKmsRequest(reqUri); //open_connect->0, get_key->1, close->2; encKey->0, authKey->1
1369 m_txKmsTrace(GetId(),packet);
1370 m_socketToKMS->Send(packet);
1371 NS_LOG_FUNCTION(this << "packet sent" << packet->GetUid() << packet->GetSize() << m_socketToKMS);
1372
1373 }
1374}
1375
1376void
1377QKDApp004::Close(std::string ksid)
1378{
1379 NS_LOG_FUNCTION(this << m_master << ksid);
1380 if(m_encStream->GetId() == ksid)
1381 m_encStream->ClearStream();
1382 else if(m_authStream->GetId() == ksid)
1383 m_authStream->ClearStream();
1384 else
1385 NS_LOG_ERROR(this << "unknown ksid" << ksid);
1386
1387 std::string reqUri {"http://" + IpToString(GetKmsIp()) + "/api/v1/keys/" + ksid + "/close"};
1388 //Create packet
1389 HTTPMessage httpMessage;
1390 httpMessage.CreateRequest(reqUri, "GET");
1391 httpMessage.SetHeader("User-Agent", "QKDApp004_" + GetId());
1392 std::string hMessage = httpMessage.ToString();
1393 Ptr<Packet> packet = Create<Packet>(
1394 (uint8_t*)(hMessage).c_str(),
1395 hMessage.size()
1396 );
1397 NS_ASSERT(packet );
1398
1399 Address temp; //check whether the socket to KMS is active and connected
1400 if(m_socketToKMS)
1401 {
1403 m_txKmsTrace(GetId(),packet);
1404 m_socketToKMS->Send(packet);
1405 NS_LOG_FUNCTION(this << "packet sent" << packet->GetUid() << packet->GetSize() << m_socketToKMS);
1406
1407 }else{
1410 packet,
1411 reqUri,
1412 KeyStreamSession::ENCRYPTION //not important
1413 };
1414 m_queue_kms.push_back(kmsPacket);
1415 NS_LOG_FUNCTION(this << "packet enqueued" << packet->GetUid() << packet->GetSize() << m_socketToKMS);
1416 }
1417
1418}
1419
1420void
1422{
1423 NS_LOG_FUNCTION(this << m_master);
1424
1426 std::string payload = header.GetMessageBodyString(); //Read HTTP body message
1427 nlohmann::json jOpenConnect; //Read JSON data structure from message
1428 if(!payload.empty()){
1429 try{
1430 jOpenConnect = nlohmann::json::parse(payload);
1431 }catch(...){
1432 NS_FATAL_ERROR(this << "json parse error");
1433 }
1434
1435 }
1436
1437 std::string ksid;
1438 if(m_master){
1439 if(header.GetStatus() == HTTPMessage::Ok){
1440 if(jOpenConnect.contains("Key_stream_ID")) ksid = jOpenConnect["Key_stream_ID"];
1441 NS_ASSERT(!ksid.empty());
1442
1444 m_encStream->SetId(ksid);
1445 else
1446 m_authStream->SetId(ksid);
1447
1448 SendKsid(ksid, sessionType);
1449
1450 }else
1451 NS_LOG_ERROR(this << "open_connect refused " << jOpenConnect["status"]);
1452
1453 }else{//!m_master
1455 ksid = m_encStream->GetId();
1456 else
1457 ksid = m_authStream->GetId();
1458
1459 if(header.GetStatus() == HTTPMessage::Ok){
1461 m_encStream->SetVerified(true);
1462 else
1463 m_authStream->SetVerified(true);
1464
1466
1467 }else{
1468 NS_LOG_FUNCTION(this << "open_connect refused");
1470 m_encStream->ClearStream();
1471 else
1472 m_authStream->ClearStream();
1473
1475
1476 }
1477 }
1478}
1479
1480void
1482{
1483 NS_LOG_FUNCTION(this);
1484 std::string payload {header.GetMessageBodyString()};
1485 std::string ksid;
1488 ksid = m_encStream->GetId();
1489 else
1490 ksid = m_authStream->GetId();
1491 NS_ASSERT(!ksid.empty());
1492
1493 nlohmann::json jGetKeyResponse;
1494 if(!payload.empty())
1495 try{
1496 jGetKeyResponse = nlohmann::json::parse(payload);
1497 }catch(...){
1498 NS_FATAL_ERROR( this << "JSON parse error!");
1499 }
1500
1501 if(header.GetStatus() == HTTPMessage::Ok){
1502 uint32_t index = -1;
1503 std::string keyValue;
1504 if(jGetKeyResponse.contains("index")) index = jGetKeyResponse["index"];
1505 if(jGetKeyResponse.contains("Key_buffer")) keyValue = jGetKeyResponse["Key_buffer"];
1506 NS_ASSERT(index >= 0 || !keyValue.empty());
1507
1513 m_encStream->AddKey(key);
1514 else
1515 m_authStream->AddKey(key);
1516
1518 CheckQueues();
1519 else if(GetState() == WAIT){
1520 if( !(GetEncryptionKeySize() && m_encStream->GetKeyCount() == 0) &&
1521 !(GetAuthenticationKeySize() && m_authStream->GetKeyCount() == 0) )
1522 SetState(READY);
1523 }
1524
1525 }else{ //Process status field of response(ETSI004 defined: 2, 3, 8) @toDo
1527 Time t {"300ms"};
1529
1530 }else if(m_master){
1531 Time t {"500ms"};
1533
1534 }else if(!m_master)
1535 NS_LOG_DEBUG(this << "unexpected get_key error on receiver App004");
1536
1537 }
1538}
1539
1540void
1542{
1543 NS_LOG_FUNCTION(this << header.GetStatus());
1545 if(m_httpRequestsKMS.empty()){ //Sockets are closed when both CLOSE responses are received!
1547 }
1548
1549 if(header.GetStatus() != HTTPMessage::Ok) NS_LOG_DEBUG(this);
1550 std::string ksid {};
1552 m_encStream->ClearStream();
1553 else
1554 m_authStream->ClearStream();
1555
1556}
1557
1558void
1560{
1561 NS_LOG_FUNCTION(this << m_master);
1562 if(m_master){ //Sender App004 processes responses from peer Receiver App004
1563 std::string method { ReadUri( header.GetRequestUri() )[5] };
1564 if(method == "send_ksid"){ //Sender App004 processes send_ksid response
1565 if(ReadUri( header.GetRequestUri() )[6] != "?ksid=" || ReadUri( header.GetRequestUri() )[8] != "&scope=") NS_LOG_DEBUG(this);
1566
1567 std::string ksid { ReadUri( header.GetRequestUri() )[7] };
1568 std::string scope { ReadUri( header.GetRequestUri() )[9] };
1569 NS_LOG_FUNCTION(this << "emir" << ksid << scope);
1570 NS_ASSERT(!ksid.empty() || !scope.empty());
1571 if(header.GetStatus() == HTTPMessage::Ok){ //status code 200
1572 if(scope == "enc"){
1573 if(m_encStream->GetId() != ksid) NS_LOG_DEBUG(this << "ksid not matching scope");
1574 m_encStream->SetVerified(true);
1575
1576 }else if(scope == "auth"){
1577 if(m_authStream->GetId() != ksid) NS_LOG_DEBUG(this << "ksid not matching scope");
1578 m_authStream->SetVerified(true);
1579
1580 }else
1581 NS_LOG_DEBUG(this << "unknown scope" << scope);
1582
1584
1585 }else{ //status code not 200
1586 NS_LOG_DEBUG(this << "unexpected SEND_KSID error");
1587 Close(ksid);
1588
1589 }
1590 }else if(method == "establish_queues"){
1595
1596 }
1597 }else
1598 NS_LOG_DEBUG(this << "invalid method" << method);
1599
1600 }else{ //Receiver App004 processes requests from peer Sender App004
1601 std::string method { ReadUri(header.GetUri())[4] };
1602 if(method == "send_ksid")
1603 { //Receiver App004 receives SEND_KSID request
1604
1605 if(ReadUri(header.GetUri())[5] != "?ksid=" || ReadUri(header.GetUri())[7] != "&scope=")
1606 NS_LOG_DEBUG(this);
1607
1608 std::string ksid { ReadUri(header.GetUri())[6] };
1609 std::string scope { ReadUri(header.GetUri())[8] };
1610 NS_ASSERT(!ksid.empty() || !scope.empty());
1611
1613 if(scope == "enc"){
1614 m_encStream->SetId(ksid); //Register KSID for encryption
1616 }
1617 else if(scope == "auth"){
1618 m_authStream->SetId(ksid); //Register KSID for autentication
1620 }
1621 else
1622 NS_LOG_DEBUG(this << "unknown scope" << scope);
1623
1625 OpenConnect(ksid, type); //Send OpenConnect to local KMS!
1626
1627 }else if(method == "establish_queues"){ //ESTABLISH_QUEUES request
1629 CheckQueues();
1630
1631 }else
1632 NS_LOG_DEBUG(this << "invalid method" << method);
1633
1634 }
1635
1636}
1637
1638/**
1639 * ********************************************************************************************
1640
1641 * Application SIGNALING
1642
1643 * ********************************************************************************************
1644 */
1645void
1647{
1649
1652
1653 HTTPMessage httpMessage;
1654 if(m_master){ //Sender App004 sends send_ksid request
1655
1656 std::string uri = "http://" + IpToString( GetPeerIp() ) + "/api/v1/" + GetPeerId() + "/send_ksid/?" + "ksid=/" + ksid + "/&scope=/" + GetSessionScope(sessionType);
1657 httpMessage.CreateRequest(uri, "GET");
1658 NS_LOG_FUNCTION(this << uri << httpMessage.GetUri());
1659 httpMessage.SetHeader("User-Agent", "QKDApp004_" + GetId());
1660
1661 }else{ //Receiver App004 sends send_ksid response
1662 httpMessage.CreateResponse(statusCode, "", {
1663 {"Content-Type", "application/json; charset=utf-8"},
1664 {"Request URI", "http://" + IpToString( GetIp() ) + "/api/v1/" + GetId() + "/send_ksid/?" + "ksid=/" + ksid + "/&scope=/" + GetSessionScope(sessionType)} //reconstruct req uri
1665 });
1666
1667 }
1668 std::string hMessage = httpMessage.ToString();
1669 Ptr<Packet> packet = Create<Packet>(
1670 (uint8_t*)(hMessage).c_str(),
1671 hMessage.size()
1672 );
1673 NS_ASSERT(packet );
1674
1675 m_txSigTrace(GetId(), packet);
1676 m_signalingSocketApp->Send(packet);
1677
1678 if(m_master)
1679 NS_LOG_FUNCTION(this << "Request sent" << packet->GetUid() << packet->GetSize() << httpMessage.GetUri());
1680 else
1681 NS_LOG_FUNCTION(this << "Response sent" << packet->GetUid() << packet->GetSize() << httpMessage.GetStatus());
1682
1683}
1684
1685void
1687{
1688 NS_LOG_FUNCTION(this << m_master);
1689
1690 HTTPMessage httpMessage;
1691 if(m_master){
1692 httpMessage.CreateRequest("http://" + IpToString( GetPeerIp() ) + "/api/v1/" + GetPeerId() + "/establish_queues", "GET");
1693 httpMessage.SetHeader("User-Agent", "QKDApp004_" + GetId());
1694
1695 }else{
1696 httpMessage.CreateResponse(HTTPMessage::Ok, "", {
1697 {"Content-Type", "application/json; charset=utf-8"},
1698 {"Request URI", "http://" + IpToString( GetIp() ) + "/api/v1/" + GetId() + "/establish_queues"} //reconstruct req uri
1699 });
1700
1701 }
1702 std::string hMessage = httpMessage.ToString();
1703 Ptr<Packet> packet = Create<Packet>(
1704 (uint8_t*)(hMessage).c_str(),
1705 hMessage.size()
1706 );
1707 NS_ASSERT(packet );
1708
1709 m_txSigTrace(GetId(), packet);
1710 m_signalingSocketApp->Send(packet);
1711
1712 if(m_master)
1713 NS_LOG_FUNCTION(this << "Request sent" << packet->GetUid() << packet->GetSize() << httpMessage.GetUri());
1714 else
1715 NS_LOG_FUNCTION(this << "Response sent" << packet->GetUid() << packet->GetSize() << httpMessage.GetStatus());
1716
1717}
1718
1719void
1721{
1722 NS_LOG_FUNCTION(this << m_master);
1723
1725 if(GetEncryptionKeySize() && m_encStream->GetId().empty())
1726 OpenConnect("", KeyStreamSession::ENCRYPTION); //Establish association for a set of future encryption keys
1727
1728 if(GetAuthenticationKeySize() && m_authStream->GetId().empty())
1729 OpenConnect("", KeyStreamSession::AUTHENTICATION); //Establish association for a set of future authentication keys
1730
1731}
1732
1733void
1738
1739
1740/**
1741 * ********************************************************************************************
1742
1743 * STATE functions
1744
1745 * ********************************************************************************************
1746 */
1747
1748void
1750{
1751 NS_LOG_FUNCTION(this);
1752 if(m_master){ //Transitions for Primary QKDApp
1753 if(GetState() == INITIALIZED){
1754 if(GetEncryptionKeySize() == 0 && GetAuthenticationKeySize() == 0){ //QKD key material not needed!
1755 SetState(READY);
1756 SendPacket(); //Immediately sends unprotected packets
1757
1758 }else{ //Establish key stream sessions for a set of future QKD keys
1761 CreateKeyStreamSessions(); //Call OPEN_CONNECT
1762
1763 }
1764
1765 }else if(GetState() == ASSOCIATIONS_ESTABLISHED){
1768 CheckQueues();
1769
1770 }else if(GetState() == KEY_QUEUES_ESTABLISHED){
1771 SetState(READY);
1772 SendPacket(); //Start sending packets!
1773
1774 }else
1775 NS_FATAL_ERROR(this << "invalid entry state" << GetState() <<
1776 "for AppTransitionTree()");
1777
1778 }else if(!m_master){ //Data transmision state transition for Replica QKDApp
1779 if(GetState() == INITIALIZED){
1780 SetState(READY);
1782
1783 }else if(GetState() == KEY_QUEUES_ESTABLISHED){
1784 SetState(READY);
1786
1787 }else
1788 NS_FATAL_ERROR(this << "invalid entry state" << GetState() <<
1789 "for AppTransitionTree()");
1790 }
1791
1792}
1793
1794
1797{
1798 return m_state;
1799}
1800
1801std::string
1803{
1804 switch(state)
1805 {
1806 case NOT_STARTED:
1807 return "NOT_STARTED";
1808 break;
1809 case INITIALIZED:
1810 return "INITIALIZED";
1811 break;
1813 return "ESTABLISHING_ASSOCIATIONS";
1814 break;
1816 return "ASSOCIATIONS_ESTABLISHED";
1817 break;
1819 return "ESTABLISHING_KEY_QUEUES";
1820 break;
1822 return "KEY_QUEUES_ESTABLISHED";
1823 break;
1824 case READY:
1825 return "READY";
1826 break;
1827 case WAIT:
1828 return "WAIT";
1829 break;
1830 case SEND_DATA:
1831 return "SEND_DATA";
1832 break;
1833 case DECRYPT_DATA:
1834 return "DECRYPT_DATA";
1835 break;
1836 case STOPPED:
1837 return "STOPPED";
1838 break;
1839 default:
1840 NS_FATAL_ERROR("Unknown state");
1841 return "FATAL_ERROR";
1842 break;
1843 }
1844}
1845
1846
1847std::string
1849{
1850 return GetAppStateString(GetState());
1851}
1852
1853void
1855{
1856 const std::string oldState = GetAppStateString();
1857 const std::string newState = GetAppStateString(state);
1858
1859 //Check transition matrix! @toDo
1860 if(oldState == "SEND_DATA" && newState == "READY") {
1861 if ((!m_encStream->GetId().empty() && m_encStream->GetKeyCount() == 0) ||
1862 (!m_authStream->GetId().empty() && m_authStream->GetKeyCount() == 0)
1863 )
1864 state = QKDApp004::State::WAIT; //Queues are empty. Go to state WAIT!
1865
1866 }
1867 m_state = state;
1868 NS_LOG_FUNCTION( this << "QKDApp" << oldState << "-->" << GetAppStateString(state) );
1869 //m_appStateTransitionTrace(oldState, newState);
1870
1871}
1872
1873/**
1874 * ********************************************************************************************
1875
1876 * ADDTIONAL functions
1877
1878 * ********************************************************************************************
1879 */
1880
1881void
1929
1930std::string
1932{
1933 NS_LOG_FUNCTION(this);
1934
1935 if(msgLength == 0)
1937
1938 //Generate random string with same size as merged key string
1939 std::string confidentialMessage;
1940 static const char alphanum[] =
1941 "0123456789"
1942 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1943 "abcdefghijklmnopqrstuvwxyz";
1944 for(std::size_t i = 0; i < msgLength; ++i){
1945 confidentialMessage += alphanum[rand() %(sizeof(alphanum) - 1)];
1946 }
1947
1948 return confidentialMessage;
1949
1950}
1951
1954{
1955 switch(m_encryptionType){
1957 return 0;
1958 break;
1960 return m_packetSize * 8;
1961 break;
1963 return CryptoPP::AES::MAX_KEYLENGTH * 8; //In bits 256! Quantum resistant!
1964 break;
1965 }
1966 return 0;
1967}
1968
1971{
1972 switch(m_authenticationType){
1974 return 0;
1975 break;
1977 return CryptoPP::AES::DEFAULT_KEYLENGTH * 8; //Use with AES. In bits 128 bits!
1978 break;
1980 return 0; //NoKey
1981 break;
1983 return 0; //NoKey
1984 break;
1985 }
1986 return 0;
1987}
1988
1995
2002
2009
2010std::string
2012{
2013 NS_LOG_FUNCTION(this << address);
2014 std::ostringstream lkmsAddressTemp;
2015 address.Print(lkmsAddressTemp);
2016 return lkmsAddressTemp.str();
2017}
2018
2019std::string
2021{
2022 NS_LOG_FUNCTION( this );
2023
2024 uint8_t *buffer = new uint8_t[packet->GetSize()];
2025 packet->CopyData(buffer, packet->GetSize());
2026 std::string payload = std::string((char*)buffer, packet->GetSize());
2027 delete[] buffer;
2028
2029 return payload;
2030}
2031
2032std::vector<std::string>
2034{
2035 NS_LOG_FUNCTION(this << s );
2036
2037 std::string delimiter {"/"}, token;
2038 size_t pos = 0;
2039 std::vector<std::string> uriParams;
2040 while((pos = s.find(delimiter)) != std::string::npos){
2041 token = s.substr(0, pos);
2042 if(!token.empty())
2043 uriParams.push_back(token);
2044
2045 s.erase(0, pos + delimiter.length());
2046
2047 }
2048 if(!s.empty())
2049 uriParams.push_back(s);
2050
2051 return uriParams;
2052}
2053
2054
2055} // Namespace ns3
a polymophic address class
Definition address.h:90
@ AUTHENTICATION
Definition app-key.h:43
The base class for all ns3 applications.
Definition application.h:51
void DoDispose() override
Destructor implementation.
Ptr< Node > GetNode() const
Class for representing data rates.
Definition data-rate.h:78
uint64_t GetBitRate() const
Get the underlying bitrate.
Definition data-rate.cc:234
An identifier for simulation events.
Definition event-id.h:45
bool IsPending() const
This method is syntactic sugar for !IsExpired().
Definition event-id.cc:65
The basic class to represent both HTTP requests and responses.
Definition http.h:77
std::string GetRequestUri() const
Definition http.h:430
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:632
std::string GetUri() const
Grab the uri.
Definition http.h:518
void CreateRequest(const std::string &url, const std::string &method)
Definition http.h:735
std::string GetMessageBodyString()
Definition http.h:713
HTTPMessage & SetHeader(const std::string &name, const std::string &value)
Set a header in the map to the value provided.
Definition http.h:409
void CreateResponse(const HttpStatus status)
Definition http.h:781
HTTPMessage::HttpStatus GetStatus() const
To be returned with a status code in a response is a status text describing the status code by text r...
Definition http.h:168
A basic class to parse a HTTP message, both request and response.
Definition http.h:936
an Inet address class
static bool IsMatchingType(const Address &address)
Ipv4Address GetIpv4() const
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.
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:66
Establish secure communication on application lavel to use the key and test LKSM.
Definition qkd-app-004.h:60
void HandlePeerErrorFromKMS(Ptr< Socket > socket)
Handle a connection error from KMS.
void PushHttpKmsRequest(std::string uri, KeyStreamSession::Type sessionType=KeyStreamSession::ENCRYPTION)
Add HTTP request to queue to map response later.
void HandlePeerCloseFromApp(Ptr< Socket > socket)
Handle a connection close from peer QKD application.
std::multimap< std::string, KeyStreamSession::Type > m_httpRequestsKMS
void HandleReadFromApp(Ptr< Socket > socket)
Handle a packet received by the QKD application from peer QKD application.
State GetState() const
Returns the current state of the application.
TracedCallback< Ptr< Packet >, std::string > m_deauthenticationTrace
trace callback for authentication check
void ConnectionToKMSSucceeded(Ptr< Socket > socket)
Callback function after the connection to the KMS is complete.
std::string GetAppStateString() const
Returns the current state of the application in string format.
Ipv4Address GetIp()
Get application Ipv4 address.
DataRate m_dataRate
Ptr< Socket > m_dataSocketApp
void SendKsid(std::string ksid, KeyStreamSession::Type sessionType, HTTPMessage::HttpStatus statusCode=HTTPMessage::Ok)
Sends SEND_KSID request(for sender App004) or response(for receiver App004)
void ConnectionToKMSFailed(Ptr< Socket > socket)
Callback function after the connection to the KMS has failed.
void HandleAcceptFromKMS(Ptr< Socket > s, const Address &from)
Handle an incoming connection from KMS.
uint32_t m_useCrypto
void OpenConnect(std::string ksid, KeyStreamSession::Type sessionType)
QKDApp reserves an association(Key_stream_ID)
std::vector< std::string > ReadUri(std::string s)
void RegisterAckTime(Time oldRtt, Time newRtt)
Ptr< Socket > m_socketToKMS
bool m_isSignalingConnectedToApp
uint32_t m_keyBufferLengthEncryption
TracedCallback< const std::string &, Ptr< const Packet > > m_rxSigTrace
Traced Callback: received signaling packets.
uint32_t m_encryption
Ptr< Socket > m_signalingSocketApp
void ProcessSignalingPacketFromApp(HTTPMessage &header, Ptr< Socket > socket)
Process signaling packets from peer QKD application.
void ProcessOpenConnectResponse(HTTPMessage &header)
Process response from KMS on OPEN_CONNECT call.
void ProcessGetKeyResponse(HTTPMessage &header)
Process Get Key response from KMS.
TracedCallback< Ptr< Packet >, std::string > m_authenticationTrace
trace callback for authentication
bool ConnectionRequestedSignalingFromApp(Ptr< Socket > socket, const Address &address)
Callback function after the connection for response from KMS has been received.
uint32_t m_keyBufferLengthAuthentication
uint32_t m_packetsSent
TracedCallback< Ptr< Packet > > m_encryptionTrace
trace callback for encryption
ns3::TracedCallback< const std::string &, const std::string & > m_stateTransitionTrace
The StateTransition trace source.
void CreateKeyStreamSessions()
std::string m_socketType
std::unordered_map< Address, Ptr< Packet >, AddressHash > m_buffer_qkdapp
Buffer for received packets(fragmentation)
uint32_t m_packetSize
void Setup(std::string socketType, std::string appId, std::string remoteAppId, const Address &appAddress, const Address &remoteAppAddress, const Address &kmAddress, std::string type)
Ptr< KeyStreamSession > m_authStream
void DataToKMSSend(Ptr< Socket >, uint32_t)
Callback function to notify that data to KMS has been sent.
TracedCallback< const std::string &, Ptr< const Packet > > m_mxTrace
Traced Callback: missed send packet call.
void HandleAcceptSignalingFromApp(Ptr< Socket > s, const Address &from)
Handle a signaling incoming connection from peer QKD application.
uint32_t m_aesLifetime
bool m_primaryQueueEstablished
void PrepareSocketToKMS()
Prepare send socket to communicate with KMS Application.
void StartApplication() override
void HandleReadSignalingFromApp(Ptr< Socket > socket)
Handle a signaling packet received by the QKD application from peer QKD application.
bool m_isDataConnectedToApp
TracedCallback< const std::string &, Ptr< const Packet > > m_rxTrace
Traced Callback: received data packets.
std::string m_dstAppId
TracedCallback< const std::string &, Ptr< const Packet > > m_rxKmsTrace
Traced Callback: received packets from KMS.
void CheckStreamSessions()
Check if the associations are successfuly established.
void HandleAcceptFromApp(Ptr< Socket > s, const Address &from)
Handle an incoming connection from peer QKD application.
QKDEncryptor::EncryptionType m_encryptionType
uint32_t GetEncryptionKeySize()
Get key size for defined encryption algorithm.
void ConnectionSignalingToAppFailed(Ptr< Socket > socket)
Callback function after the signaling connection to the APP has.
EventId m_sendEvent
void EstablishQueues()
Sends ESTABLISH_QUEUES request(for sende App004) or response(for receiver App004)
void Close(std::string ksid)
Terminate the association.
void HandlePeerErrorSignalingFromApp(Ptr< Socket > socket)
Handle a signaling connection error from peer QKD application.
Ptr< KeyStreamSession > m_encStream
~QKDApp004() override
static TypeId GetTypeId()
Get the type ID.
void ProcessPacketsToKMSFromQueue()
void SetCryptoSettings(uint32_t encryptionType, uint32_t authenticationType, uint32_t authenticationTagLengthInBits)
Set encryption and authentication type.
uint32_t GetAuthenticationKeySize()
Get key size for defined authentication algorithm.
void StopApplication() override
Application specific shutdown code.
bool ConnectionRequestedFromKMS(Ptr< Socket > socket, const Address &address)
Callback function after the connection for response from KMS has been received.
uint32_t m_dataSent
uint16_t m_portSignaling
void ProcessCloseResponse(HTTPMessage &header)
Process response from KMS on CLOSE call.
void PacketReceivedFromKMS(const Ptr< Packet > &p, const Address &from, Ptr< Socket > socket)
Check for tcp segmentation of packets received from KMS.
std::string GetPacketContent(uint32_t msgLength=0)
Get the packet payload content.
bool m_replicaQueueEstablished
void ConnectionSignalingToAppSucceeded(Ptr< Socket > socket)
Callback function after the signaling connection to the APP is complete.
void ConnectionToAppSucceeded(Ptr< Socket > socket)
Callback function after the connection to the APP is complete.
bool ConnectionRequestedFromApp(Ptr< Socket > socket, const Address &address)
Callback function after the connection for response from KMS has been received.
void SetState(State state)
Set state.
void SendPacket()
QKDApp encrypts the data with obtained keys and sends this encrypted data to the peer QKDApp.
void SignalingPacketReceivedFromApp(const Ptr< Packet > &p, const Address &from, Ptr< Socket > socket)
Check for tcp segmentation of signaling packets received from APP.
void ProcessDataPacket(QKDAppHeader header, Ptr< Packet > packet, Ptr< Socket > socket)
Process data packets from peer QKD application.
Ipv4Address GetPeerIp()
Get peer application Ipv4 address.
void HandlePeerErrorFromApp(Ptr< Socket > socket)
Handle a connection error from peer QKD application.
QKDEncryptor::AuthenticationType m_authenticationType
Ptr< QKDEncryptor > m_encryptor
void HandlePeerCloseSignalingFromApp(Ptr< Socket > socket)
Handle a signaling connection close from peer QKD application.
std::string GetSessionScope(KeyStreamSession::Type type)
uint32_t m_authenticationTagLengthInBits
length of the authentication tag in bits(32 by default)
void GetKeyFromKMS(std::string ksid)
Obtain the required amount of key material.
uint32_t m_master
State
QKD App states(App) States that refer to QKDApp data transmision!
Definition qkd-app-004.h:74
@ ESTABLISHING_ASSOCIATIONS
Definition qkd-app-004.h:77
void ProcessResponseFromKMS(HTTPMessage &header, Ptr< Packet > packet, Ptr< Socket > socket)
Process response from KMS application.
void HandlePeerCloseToKMS(Ptr< Socket > socket)
Handle a connection close to KMS.
void CheckQueues()
Application establishing key queues before establishing data traffic.
std::string IpToString(Ipv4Address address)
uint32_t m_authentication
std::string GetId()
Get application identifier.
std::unordered_map< Address, Ptr< Packet >, AddressHash > m_buffer_sig
Buffer for received packets(fragmentation)
void ConnectionToAppFailed(Ptr< Socket > socket)
Callback function after the connection to the APP has failed.
void HandlePeerCloseFromKMS(Ptr< Socket > socket)
Handle a connection close from KMS.
TracedCallback< Ptr< Packet > > m_decryptionTrace
trace callback for decryption
Ipv4Address GetKmsIp()
Get KMS Ipv4 address.
void HandleReadFromKMS(Ptr< Socket > socket)
Handle a packet received by the QKD application from KMS application.
std::string PacketToString(Ptr< Packet > packet)
Convert packet to string.
static uint32_t m_applicationCounts
void AppTransitionTree()
Transition tree of the application.
TracedCallback< const std::string &, Ptr< const Packet > > m_txKmsTrace
Traced Callback: transmitted packets to KMS.
void DataPacketReceived(const Ptr< Packet > &p, const Address &from, Ptr< Socket > socket)
Check for tcp segmentation of signaling packets received from KMS.
std::string GetPeerId()
Get peer application identifier.
std::vector< KMSPacket > m_queue_kms
void HandlePeerErrorToKMS(Ptr< Socket > socket)
Handle a connection error to KMS.
TracedCallback< const std::string &, Ptr< const Packet > > m_txSigTrace
Traced Callback: transmitted signaling packets.
void DoDispose() override
Destructor implementation.
std::unordered_map< Address, Ptr< Packet >, AddressHash > m_buffer_kms
Buffer for received packets(fragmentation)
void PrepareSocketToApp()
Prepare send socket to communicate with QKD Application.
TracedCallback< const std::string &, Ptr< const Packet > > m_txTrace
Traced Callback: transmitted data packets.
KeyStreamSession::Type PopHttpKmsRequest(std::string uri)
Pop HTTP request from the queue(mapping response)
std::string m_appId
QKD app packet header that carries info about used encryption, auth tag and other.
uint32_t GetLength() const
std::string GetAuthTag() const
uint32_t GetEncrypted() const
void SetEncrypted(uint32_t value)
uint32_t GetSerializedSize() const override
std::string GetEncryptionKeyId() const
std::string GetAuthenticationKeyId() const
uint32_t GetAuthenticated() const
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:560
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:274
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
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:76
virtual Socket::SocketErrno GetErrno() const =0
Get last error number.
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:94
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:103
virtual int GetPeerName(Address &address) const =0
Get the peer address of a connected socket.
virtual int Connect(const Address &address)=0
Initiate a connection to a remote host.
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:85
void SetRecvCallback(Callback< void, Ptr< Socket > > receivedData)
Notify application when new data is available to be read.
Definition socket.cc:117
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:61
virtual int Close()=0
Close a socket.
virtual int Bind(const Address &address)=0
Allocate a local endpoint for this socket.
virtual int Listen()=0
Listen for incoming connections.
static TypeId GetTypeId()
Get the type ID.
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
AttributeValue implementation for Time.
Definition nstime.h:1431
a unique identifier for an interface.
Definition type-id.h:49
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
AttributeValue implementation for TypeId.
Definition type-id.h:641
static TypeId GetTypeId()
Get the type ID.
Hold an unsigned integer type.
Definition uinteger.h:34
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition assert.h:75
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition nstime.h:1452
Callback< R, Args... > MakeNullCallback()
Definition callback.h:727
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_ABORT_IF(cond)
Abnormal program termination if a condition is true.
Definition abort.h:65
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition log.h:243
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition log.h:250
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1344
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition nstime.h:1432
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition callback.h:684
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition uinteger.h:35
Ptr< const AttributeChecker > MakeTypeIdChecker()
Definition type-id.cc:1335
Ptr< const AttributeAccessor > MakeTypeIdAccessor(T1 a1)
Definition type-id.h:641
static const uint32_t packetSize
Packet size generated at the AP.