23 #include "ns3/address.h"
25 #include "ns3/nstime.h"
26 #include "ns3/socket.h"
27 #include "ns3/simulator.h"
28 #include "ns3/tcp-socket-factory.h"
29 #include "ns3/packet.h"
30 #include "ns3/uinteger.h"
31 #include "ns3/trace-source-accessor.h"
32 #include "ns3/qkd-control.h"
51 static TypeId tid =
TypeId (
"ns3::QKDKeyManagerSystemApplication")
53 .SetGroupName(
"Applications")
56 .AddAttribute (
"Protocol",
"The type of protocol to use.",
60 .AddAttribute (
"LocalAddress",
"The ipv4 address of the application",
63 MakeIpv4AddressChecker ())
64 .AddAttribute (
"MaximalKeysPerRequest",
65 "The maximal number of keys per request (ESTI QKD 014)",
68 MakeUintegerChecker<uint32_t> ())
69 .AddAttribute (
"MinimalKeySize",
70 "The minimal size of key QKDApp can request",
73 MakeUintegerChecker<uint32_t> ())
74 .AddAttribute (
"MaximalKeySize",
75 "The maximal size of key QKDApp can request",
78 MakeUintegerChecker<uint32_t> ())
79 .AddAttribute (
"DefaultKeySize",
80 "The default size of the key",
83 MakeUintegerChecker<uint32_t> ())
84 .AddAttribute (
"MaliciousRequestBlocking",
85 "Does KMS detects and blocks malicious get_key_004 request?",
88 MakeUintegerChecker<uint32_t> ())
89 .AddAttribute (
"ETSI004_DefaultTTL",
90 "Default value of ETSI004 TTL (in seconds)",
93 MakeUintegerChecker<uint32_t> ())
94 .AddAttribute (
"MaxKeyRate",
"The maximal key rate (encryption+authentication) provided by the KMS (QoS settings).",
97 MakeDataRateChecker ())
98 .AddAttribute (
"MinKeyRate",
"The minimal key rate (encryption+authentication) provided by the KMS (QoS settings).",
101 MakeDataRateChecker ())
102 .AddAttribute (
"QoS_maxrate_threshold",
103 "The treshold for processing low-priority requests",
106 MakeDoubleChecker<double> ())
108 .AddTraceSource (
"Tx",
"A new packet is created and is sent to the APP",
110 "ns3::QKDKeyManagerSystemApplication::Tx")
111 .AddTraceSource (
"Rx",
"A packet from the APP has been received",
113 "ns3::QKDKeyManagerSystemApplication::Rx")
114 .AddTraceSource (
"TxKMSs",
"A new packet is created and is sent to the APP",
116 "ns3::QKDKeyManagerSystemApplication::TxKMSs")
117 .AddTraceSource (
"RxKMSs",
"A packet from the APP has been received",
119 "ns3::QKDKeyManagerSystemApplication::RxKMSs")
121 .AddTraceSource (
"NewKeyGeneratedEmir",
"The trace to monitor key material received from QL",
123 "ns3::QKDKeyManagerSystemApplication::NewKeyGeneratedEmir")
124 .AddTraceSource (
"KeyServedEmir",
"The trace to monitor key material served to QKD Apps",
126 "ns3:QKDKeyManagerSystemApplication::KeyServedEmir")
128 .AddTraceSource (
"NewKeyGenerated",
"The trace to monitor key material received from QL",
130 "ns3::QKDKeyManagerSystemApplication::NewKeyGenerated")
132 .AddTraceSource (
"KeyServedEtsi014",
"The thece to monitor key usage by etsi 014",
134 "ns3::QKDKeyManagerSystemApplication::KeyServedEtsi014")
136 .AddTraceSource (
"KeyServedEtsi004",
"The thece to monitor key usage by etsi 004",
138 "ns3::QKDKeyManagerSystemApplication::KeyServedEtsi004")
140 .AddTraceSource (
"DropKMSRequest",
"Drop a request from the queue disc",
142 "ns3::QKDKeyManagerSystemApplication::TracedCallback")
144 .AddTraceSource (
"ProvidedQoSResponse",
"Provide QoS response to key material request",
146 "ns3::QKDKeyManagerSystemApplication::ProvidedQoSResponse")
162 m_random = CreateObject<UniformRandomVariable> ();
255 sendSocket->
Connect ( receiveAddress );
260 <<
"Create the response socket " << sendSocket
283 it->second.first = s;
307 NS_LOG_FUNCTION (
this <<
"QKDKeyManagerSystemApplication Connection succeeded");
311 if(j->first == socket){
312 uint32_t response = j->first->Send(j->second);
313 response = j->first->Send(j->second);
316 NS_LOG_FUNCTION(
this << j->first <<
"Sending packet from the queue!" << response );
327 NS_LOG_FUNCTION (
this <<
"QKDKeyManagerSystemApplication KMSs Connection succeeded");
334 NS_LOG_FUNCTION (
this <<
"QKDKeyManagerSystemApplication, Connection Failed");
341 NS_LOG_FUNCTION (
this <<
"QKDKeyManagerSystemApplication, Connection Failed");
360 NS_LOG_FUNCTION (
this <<
"QKDKeyManagerSystemApplication KMS-SDN Connection succeeded");
368 if(j->first == socket || !j->first){
383 NS_LOG_FUNCTION (
this <<
"QKDKeyManagerSystemApplication KMS-SDN Connection failed");
442 if(sendingSocket->
GetPeerName(connectedAddress) == 0){
443 sendingSocket->
Send(packet);
460 std::map<Ipv4Address, std::pair<Ptr<Socket>,
Ptr<Socket> > >::iterator it;
463 if ( it->second.first == socket )
466 sendingSocket->
Send(packet);
485 std::pair<Ptr<Socket>,
Ptr<Socket> > pair = i->second;
488 NS_LOG_FUNCTION(
this <<
"Let's create a new send socket to reach KMS!");
513 sendSocket->
Connect ( peerAddress );
516 i->second.second = sendSocket;
519 <<
"Create the send socket " << sendSocket
520 <<
" from KMS to KMS which is on " << kmsDstAddress
524 NS_LOG_FUNCTION(
this <<
"Socket to peer KMS exist. No action required");
546 std::pair<Ptr<Socket>,
Ptr<Socket> > pair = i->second;
564 while ((packet = socket->
RecvFrom (from)))
566 if (packet->
GetSize () == 0)
break;
574 <<
"s KMS received packet ID: "
575 << packet->
GetUid () <<
" of "
576 << packet->
GetSize () <<
" bytes from "
579 <<
" total Rx " <<
m_totalRx <<
" bytes");
594 while ((packet = socket->
RecvFrom (from)))
607 <<
"s KMS received packet ID: "
608 << packet->
GetUid () <<
" of "
609 << packet->
GetSize () <<
" bytes from KMS "
612 <<
" total Rx " <<
m_totalRx <<
" bytes");
627 while ((packet = socket->
RecvFrom (from)))
640 <<
"s KMS received packet ID: "
641 << packet->
GetUid () <<
" of "
642 << packet->
GetSize () <<
" bytes from KMS "
645 <<
" total Rx " <<
m_totalRx <<
" bytes");
656 std::string receivedStatus = p->
ToString();
660 if (receivedStatus.find(
"Fragment") != std::string::npos) {
664 std::make_pair (from, Create<Packet> (0))
667 buffer = itBuffer->second;
678 uint8_t *b1 =
new uint8_t[buffer->
GetSize ()];
680 std::string requestString = std::string((
char*)b1);
685 parser.Parse(&request, requestString);
698 uint8_t *b2 =
new uint8_t[completePacket->
GetSize ()];
700 std::string s2 = std::string((
char*)b2);
703 parser.Parse(&request2, s2);
721 std::string receivedStatus = p->
ToString();
725 if (receivedStatus.find(
"Fragment") != std::string::npos) {
729 std::make_pair (from, Create<Packet> (0))
732 buffer = itBuffer->second;
743 uint8_t *b1 =
new uint8_t[buffer->
GetSize ()];
745 std::string requestString = std::string((
char*)b1);
749 parser.Parse(&request, requestString);
762 uint8_t *b2 =
new uint8_t[completePacket->
GetSize ()];
764 std::string s2 = std::string((
char*)b2);
767 parser.Parse(&request2, s2);
785 std::string receivedStatus = p->
ToString();
789 if (receivedStatus.find(
"Fragment") != std::string::npos) {
793 std::make_pair (from, Create<Packet> (0))
796 buffer = itBuffer->second;
807 uint8_t *b1 =
new uint8_t[buffer->
GetSize ()];
809 std::string requestString = std::string((
char*)b1);
813 parser.Parse(&request, requestString);
828 uint8_t *b2 =
new uint8_t[completePacket->
GetSize ()];
830 std::string s2 = std::string((
char*)b2);
833 parser.Parse(&request2, s2);
840 if(request2.
GetUri() !=
""){
938 <<
"Sink KMS socket listens on "
940 <<
" and port " << sdnPort
941 <<
" for SDN packets"
979 if(j->second) j->second->Close();
992 NS_LOG_FUNCTION(
this <<
"Scheduling new event in an attempt to fill association buffer " << ksid <<
" ...");
993 uint32_t scheduleID {0};
995 if(
action ==
"CheckAssociation"){
1020 std::string slave_SAE_ID;
1025 uriParams.size() > 3 &&
1026 uriParams[1] ==
"api" &&
1027 uriParams[2] ==
"v1" &&
1028 uriParams[3] ==
"keys"
1031 std::string receivedAddressStr (uriParams[0]);
1033 NS_LOG_FUNCTION(
this <<
"received address" << receivedAddressStr << receivedAddress);
1038 slave_SAE_ID = uriParams[4];
1039 ksid = uriParams[4];
1044 NS_LOG_FUNCTION (
this <<
"slave_SAE_ID: " << slave_SAE_ID <<
"requestType: " << requestType );
1051 NS_LOG_FUNCTION (
this <<
"Fetch status from QKD buffers for connection to destination node" << slave_SAE_ID );
1062 std::ostringstream srcKmsAddressTemp;
1063 srcKmsAddress.
Print(srcKmsAddressTemp);
1064 std::string srcKME = srcKmsAddressTemp.str ();
1067 std::ostringstream dstKmsAddressTemp;
1068 dstKmsAddress.
Print(dstKmsAddressTemp);
1069 std::string dstKME = dstKmsAddressTemp.str ();
1073 j[
"source_KME_ID"] = srcKME;
1074 j[
"target_KME_ID"] = dstKME;
1076 j[
"slave_SAE_ID"] = slave_SAE_ID;
1081 j[
"stored_key_count"] = buffer->GetKeyCountBit();
1082 j[
"max_key_count"] = buffer->GetMaxKeyCount();
1084 j[
"stored_key_count"] = 0;
1085 j[
"max_key_count"] = 0;
1091 j[
"max_SAE_ID_count"] = 0;
1093 std::string msg = j.dump();
1098 {
"Content-Type",
"application/json; charset=utf-8"},
1099 {
"Request URI", headerIn.
GetUri() }
1101 std::string hMessage = httpMessage.
ToString();
1103 (uint8_t*) (hMessage).c_str(),
1108 NS_LOG_FUNCTION (
this <<
"Sending Response to ETSI_QKD_014_GET_STATUS\n PacketID: " << packet->
GetUid() <<
" of size: " << packet->
GetSize() << hMessage );
1118 uint32_t keyNumber = 1;
1133 if(headerIn.
GetMethod() == HTTPMessage::HttpMethod::GET){
1135 while(
k <
int(uriParams.size())){
1136 if(uriParams[
k] ==
"number")
1137 keyNumber = std::stoi(uriParams[
k+1]);
1138 else if(uriParams[
k] ==
"size")
1139 keySize = std::stoi(uriParams[
k+1]);
1142 jrequest = {{
"number", keyNumber}, {
"size", keySize}};
1144 }
else if(headerIn.
GetMethod() == HTTPMessage::HttpMethod::POST){
1147 jrequest = nlohmann::json::parse(payload);
1148 if (jrequest.contains(
"number"))
1149 keyNumber = jrequest[
"number"];
1150 if (jrequest.contains(
"size"))
1151 keySize = uint32_t(jrequest[
"size"]);
1153 NS_FATAL_ERROR(
this <<
"JSON parse error of the received payload: " << payload <<
"\t" << payload.length() );
1160 if(!errorDataStructure.empty()){
1162 NS_LOG_FUNCTION(
this <<
"Get key request error" << errorDataStructure.dump() );
1164 if(errorDataStructure.contains(
"message")){
1165 if(errorDataStructure[
"message"] ==
"keys are being transformed"){
1166 statusCode = HTTPMessage::HttpStatus::ServiceUnavailable;
1169 }
else if(errorDataStructure[
"message"] ==
"insufficient amount of key material")
1170 statusCode = HTTPMessage::HttpStatus::ServiceUnavailable;
1172 errorDataStructure[
"ksid"] = ksid;
1173 std::string msg = errorDataStructure.dump();
1178 {
"Content-Type",
"application/json; charset=utf-8"},
1179 {
"Request URI", headerIn.
GetUri() }
1181 std::string hMessage = httpMessage.
ToString();
1183 (uint8_t*) (hMessage).c_str(),
1188 NS_LOG_FUNCTION (
this <<
"1185 Sending Response to ETSI_QKD_014_GET_KEY\n PacketID: " << packet->
GetUid() <<
" of size: " << packet->
GetSize() << hMessage );
1193 std::vector<Ptr<QKDKey>> keys {};
1196 buffer->RecordTargetSize(keySize);
1197 for(uint32_t i = 0; i < keyNumber; i++){
1198 keys.push_back(buffer->FetchKeyBySize(keySize));
1206 jkeys[
"ksid"] = ksid;
1207 std::string msg = jkeys.dump();
1215 {
"Content-Type",
"application/json; charset=utf-8"},
1216 {
"Request URI", headerIn.
GetUri() }
1218 std::string hMessage = httpMessage.
ToString();
1220 (uint8_t*) (hMessage).c_str(),
1225 NS_LOG_FUNCTION(
this <<
"1221 Sending Response to ETSI_QKD_014_GET_KEY\n PacketID: " << packet->
GetUid() <<
" of size: " << packet->
GetSize() << hMessage );
1229 for(uint32_t i=0; i<keys.size(); i++){
1244 NS_LOG_FUNCTION(
this <<
"Processing ETSI 014 get_key_with_key_ids request" );
1257 jkeyIDs = nlohmann::json::parse(payload);
1262 std::vector<std::string> keyIDs;
1263 for (nlohmann::json::iterator it = jkeyIDs[
"key_IDs"].begin(); it != jkeyIDs[
"key_IDs"].end(); ++it)
1264 keyIDs.push_back((it.value())[
"key_ID"]);
1269 std::vector<Ptr<QKDKey>> keys {};
1271 for(uint32_t i = 0; i < keyIDs.size(); i++){
1285 uint32_t number = keys.size();
1286 uint32_t size = keys[0]->GetSizeInBits();
1290 std::string msg = jkeys.dump();
1295 {
"Content-Type",
"application/json; charset=utf-8"},
1296 {
"Request URI", headerIn.
GetUri() }
1298 std::string hMessage = httpMessage.
ToString();
1300 (uint8_t*) (hMessage).c_str(),
1305 NS_LOG_FUNCTION (
this <<
"Sending Response to ETSI_QKD_014_GET_KEY\n PacketID: " << packet->
GetUid() <<
" of size: " << packet->
GetSize() << hMessage );
1309 for(uint32_t i=0; i<keys.size(); i++){
1316 nlohmann::json errorDataStructure = {{
"messsage",
"key access error"}};
1317 std::string msg = errorDataStructure.dump();
1321 httpMessage.
CreateResponse(HTTPMessage::HttpStatus::BadRequest, msg, {
1322 {
"Content-Type",
"application/json; charset=utf-8"},
1323 {
"Request URI", headerIn.
GetUri() }
1325 std::string hMessage = httpMessage.
ToString();
1327 (uint8_t*) (hMessage).c_str(),
1332 NS_LOG_FUNCTION(
this <<
"Sending Response to ETSI_QKD_014_GET_KEY\n PacketID: " << packet->
GetUid() <<
" of size: " << packet->
GetSize() << hMessage );
1378 std::cout <<
"packet dropped! \n";
1400 std::string keyId = payloadContent[
"key_id"];
1401 std::string keyValue = payloadContent[
"key"];
1402 uint32_t srcNodeId = payloadContent[
"src_id"];
1403 uint32_t dstNodeId = payloadContent[
"dst_id"];
1408 Ptr<QKDKey> newKey = Create<QKDKey> (keyId, keyValue);
1409 AddNewKey(newKey, srcNodeId, dstNodeId);
1425 if(headerIn.
GetUri() !=
"")
1440 uriParams.size() > 3 &&
1441 uriParams[1] ==
"api" &&
1442 uriParams[2] ==
"v1" &&
1443 uriParams[3] ==
"keys" &&
1444 uriParams[5] ==
"register_qkd_link"
1452 sdnResponse = nlohmann::json::parse(payload);
1453 double QKDLinkStatsUpdateInterval = 0;
1454 std::string keyAssociationIdString;
1455 uint32_t registrationAccepted = 0;
1457 if (sdnResponse.contains(
"accepted")) registrationAccepted = sdnResponse[
"accepted"];
1458 if (sdnResponse.contains(
"qkd_link_update_interval")) QKDLinkStatsUpdateInterval = sdnResponse[
"qkd_link_update_interval"];
1459 if (sdnResponse.contains(
"key_association_id")) keyAssociationIdString = sdnResponse[
"key_association_id"];
1461 NS_ASSERT(QKDLinkStatsUpdateInterval > 1);
1462 NS_LOG_FUNCTION(
this << keyAssociationIdString << registrationAccepted << QKDLinkStatsUpdateInterval);
1463 UUID keyAssociationId =
UUID{keyAssociationIdString};
1465 if(registrationAccepted){
1473 NS_LOG_FUNCTION(
this <<
"SDN approved registration of QKD LINK between nodes " << keyAssociationId);
1475 Seconds(QKDLinkStatsUpdateInterval),
1479 QKDLinkStatsUpdateInterval
1484 NS_LOG_FUNCTION(
this <<
"SDN FORBIDES registration of QKD LINK between nodes " << keyAssociationId);
1514 keyAssociation.
SetSKR(buffer->GetAverageKeyGenerationRate());
1520 double ratio = buffer->GetAverageKeyGenerationRate() - buffer->GetAverageKeyConsumptionRate();
1533 j[
"key_association_id"] = keyAssociation.
GetId().
string();
1537 double skr = keyAssociation.
GetSKR();
1539 j[
"qkdl_performance_skr"] = skr;
1543 j[
"qkdl_performance_expected_consumption"] = expectedConsumption;
1547 j[
"qkdl_performance_eskr"] = eskr;
1549 NS_LOG_FUNCTION(
this <<
"Prepared JSON_PACKET_TO_SDN:" << j.dump() << skr << expectedConsumption << eskr );
1551 std::string msg = j.dump();
1555 std::ostringstream sdnAddressTemp;
1556 sdnAddress.
Print(sdnAddressTemp);
1558 std::ostringstream skmsAddressTemp;
1560 std::string skmsAddressString = skmsAddressTemp.str();
1562 std::string headerUri =
"http://" + sdnAddressTemp.str ();
1563 headerUri +=
"/api/v1/keys/" + skmsAddressString +
"/key_association_status";
1568 std::string hMessage = httpMessage.
ToString();
1570 (uint8_t*) (hMessage).c_str(),
1575 NS_LOG_FUNCTION (
this <<
"Sending KEY_ASSOCIATION_STATUS to SDN CONTROLLER\n PacketID: "
1589 keyAssociation.
GetId(),
1607 uriParams.size() > 3 &&
1608 uriParams[1] ==
"api" &&
1609 uriParams[2] ==
"v1" &&
1610 uriParams[3] ==
"keys" &&
1611 uriParams[5] ==
"register_qkd_link"
1622 std::vector<std::string>
1626 std::vector<std::string> uriParams;
1629 std::string delimiter =
"/";
1632 while ((pos = s.find(delimiter)) != std::string::npos) {
1633 token = s.substr(0, pos);
1634 if(token.length() > 0){
1635 uriParams.push_back(token);
1637 s.erase(0, pos + delimiter.length());
1640 uriParams.push_back(s);
1656 NS_LOG_FUNCTION(
this <<
"krecA" << uriParams[0] << uriParams[1] << uriParams[2] << uriParams[3] );
1658 uriParams.size() > 3 &&
1659 uriParams[1] ==
"api" &&
1660 uriParams[2] ==
"v1" &&
1661 (uriParams[3] ==
"associations" ||
1662 uriParams[3] ==
"keys")
1670 std::string ksid = uriParams[5];
1673 }
else if(requestType ==
FILL){
1674 std::string ksid = uriParams[5];
1680 std::string ksid = uriParams[5];
1698 else if(methodType ==
FILL)
1731 std::map<Ipv4Address, uint32_t>::iterator it =
m_flagedIPAdr.find(ipAdr);
1734 NS_LOG_FUNCTION (
this <<
"This request has been flaged as potentialy malicious!"
1735 <<
"This IPAddress" << ipAdr <<
"will be penalized after the next offense!");
1737 NS_LOG_FUNCTION (
this <<
"KMS identified request coming from" << ipAdr <<
"as malicious request."
1738 <<
"This IPAddress is now blocked!");
1757 NS_LOG_FUNCTION(
this <<
"Checking the state of the association " << ksid <<
" ...");
1758 std::map<std::string, Association004>::iterator it =
m_associations004.find(ksid);
1760 NS_LOG_DEBUG(
this <<
" Key stream association identified with " << ksid <<
" does not exists!" );
1763 (it->second).tempBuffer.empty() &&
1764 ((it->second).buffer.empty() || !(it->second).buffer.begin()->second.ready)
1767 std::map<std::string, uint32_t>::iterator it2 =
m_sessionList.find(ksid);
1770 NS_LOG_FUNCTION(
this <<
"SESSION with KSID " << ksid <<
" was favored in the m_session_list!");
1772 NS_LOG_FUNCTION(
this <<
"SESSION with KSID " << ksid <<
" was not located in m_session_list!");
1776 std::map<std::string, uint32_t>::iterator it2 =
m_sessionList.find(ksid);
1779 NS_LOG_FUNCTION(
this <<
"SESSION with KSID " << ksid <<
" was removed from the m_session_list!");
1781 NS_LOG_FUNCTION(
this <<
"SESSION with KSID " << ksid <<
" was not located in m_session_list!");
1799 jOpenConnectRequest = nlohmann::json::parse(payload);
1805 std::string dstSaeId;
1806 std::string srcSaeId;
1808 if(jOpenConnectRequest.contains(
"Key_stream_ID")) ksid = jOpenConnectRequest[
"Key_stream_ID"];
1809 if(jOpenConnectRequest.contains(
"Source")) srcSaeId = jOpenConnectRequest[
"Source"];
1810 if(jOpenConnectRequest.contains(
"Destination")) dstSaeId = jOpenConnectRequest[
"Destination"];
1820 bool callByMaster {ksid.empty()};
1824 uint32_t
type = std::stoi(uriParams[6]);
1829 }
else if(
type == 1) {
1854 NS_LOG_FUNCTION(
this <<
"Processing OPEN_CONNECT request submitted by the primary QKDApp ...");
1859 bool acceptRequest =
ProcessQoSRequest(appConnection, conn, inQos, providedQoS, ksid);
1875 jOpenConnectResponse[
"Key_stream_ID"] = ksid;
1876 jOpenConnectResponse[
"QoS"] = {
1877 {
"priority", providedQoS.
priority},
1878 {
"max_bps", providedQoS.
maxRate},
1879 {
"min_bps", providedQoS.
minRate},
1880 {
"jitter", providedQoS.
jitter},
1881 {
"timeout", providedQoS.
timeout},
1882 {
"key_chunk_size", providedQoS.
chunkSize},
1883 {
"TTL", providedQoS.
TTL}
1885 std::string msg = jOpenConnectResponse.dump();
1890 {
"Content-Type",
"application/json; charset=utf-8"},
1891 {
"Request URI", headerIn.
GetUri() }
1893 std::string hMessage = httpMessage.
ToString();
1895 (uint8_t*) (hMessage).c_str(),
1914 httpMessage.
CreateResponse(HTTPMessage::HttpStatus::BadRequest,
"", {
1915 {
"Request URI", headerIn.
GetUri() }
1917 std::string hMessage = httpMessage.
ToString();
1919 (uint8_t*) (hMessage).c_str(),
1932 std::map<std::string, Association004>::iterator it =
m_associations004.find(ksid);
1934 NS_LOG_DEBUG(
this <<
" Key stream association identified with " << ksid <<
" does not exists!" );
1936 }
else if ((it->second).srcSaeId !=
UUID{srcSaeId}) {
1937 NS_LOG_FUNCTION(
this <<
"KSID is not registered for this application" << (it->second).dstSaeId << srcSaeId );
1941 (it->second).peerRegistered =
true;
1949 {
"Request URI", headerIn.
GetUri() }
1951 std::string hMessage = httpMessage.
ToString();
1953 (uint8_t*) (hMessage).c_str(),
1968 NS_LOG_FUNCTION(
this <<
"Processing get_key request (ETSI 004)" << ksid );
1970 std::map<std::string, Association004>::iterator it =
m_associations004.find(ksid);
1975 NS_LOG_DEBUG(
this <<
" Key stream association identified with " << ksid <<
" does not exists!" );
1979 httpMessage.
CreateResponse(HTTPMessage::HttpStatus::BadRequest,
"", {
1980 {
"Request URI", headerIn.
GetUri() }
1982 std::string hMessage = httpMessage.
ToString();
1984 (uint8_t*) (hMessage).c_str(),
1994 if( !(it->second).buffer.empty() && (it->second).buffer.begin()->second.ready )
2004 index = (it->second).buffer.begin()->first;
2005 key = (it->second).buffer.begin()->second.key;
2006 (it->second).buffer.erase((it->second).buffer.begin());
2007 if(it->second.associationDirection == 0){
2012 jresponse[
"index"] = index;
2013 jresponse[
"Key_buffer"] = key;
2015 std::string msg = jresponse.dump();
2020 {
"Content-Type",
"application/json; charset=utf-8"},
2021 {
"Request URI", headerIn.
GetUri() }
2023 std::string hMessage = httpMessage.
ToString();
2025 (uint8_t*) (hMessage).c_str(),
2040 <<
"AverageKeyGenerationRate:" << conn.
GetSKR()
2052 NS_LOG_FUNCTION(
this <<
"Association was not found!" << it->second.dstSaeId.string() );
2056 httpMessage.
CreateResponse(HTTPMessage::HttpStatus::BadRequest,
"", {
2057 {
"Request URI", headerIn.
GetUri() }
2059 std::string hMessage = httpMessage.
ToString();
2061 (uint8_t*) (hMessage).c_str(),
2073 NS_LOG_FUNCTION(
this <<
"No keys available in the association buffer. Responding on the request ...");
2077 httpMessage.
CreateResponse(HTTPMessage::HttpStatus::BadRequest,
"", {
2078 {
"Request URI", headerIn.
GetUri() }
2080 std::string hMessage = httpMessage.
ToString();
2082 (uint8_t*) (hMessage).c_str(),
2115 std::map<std::string, Association004>::iterator it =
m_associations004.find(ksid);
2117 NS_LOG_DEBUG(
this <<
" Key stream association identified with " << ksid <<
" does not exists!" );
2124 if(!it->second.buffer.empty()){
2126 query.
sync_index = it->second.buffer.begin()->first;
2137 NS_LOG_FUNCTION(
this <<
"Releasing key stream association buffer. Synchronizing with peed KMS ... ");
2147 std::string msg = msgBody.dump();
2149 std::ostringstream peerkmsAddressTemp;
2150 (it->second).dstKmsNode.Print(peerkmsAddressTemp);
2151 std::string headerUri =
"http://" + peerkmsAddressTemp.str();
2152 headerUri +=
"/api/v1/associations/close_kms/" + ksid;
2157 std::string hMessage = httpMessage.
ToString();
2159 (uint8_t*) (hMessage).c_str(),
2166 sendSocket->
Send(packet);
2167 NS_LOG_FUNCTION(
this <<
"Synchronization information for releasing key stream association sent to peer KMS"
2184 std::map<std::string, Association004>::iterator it =
m_associations004.find(ksid);
2186 NS_LOG_DEBUG(
this <<
" Key stream association identified with " << ksid <<
" does not exists!" );
2195 msgBody[
"Source"] = (it->second).srcSaeId.string();
2196 msgBody[
"Destination"] = (it->second).dstSaeId.string();
2197 msgBody[
"QoS"][
"key_chunk_size"] = (it->second).qos.chunkSize;
2198 msgBody[
"QoS"][
"max_bps"] = (it->second).qos.maxRate;
2199 msgBody[
"QoS"][
"min_bps"] = (it->second).qos.minRate;
2200 msgBody[
"QoS"][
"jitter"] = (it->second).qos.jitter;
2201 msgBody[
"QoS"][
"priority"] = (it->second).qos.priority;
2202 msgBody[
"QoS"][
"timeout"] = (it->second).qos.timeout;
2203 msgBody[
"QoS"][
"TTL"] = (it->second).qos.TTL;
2206 msgBody[
"Key_stream_ID"] = ksid;
2207 std::string msg = msgBody.dump();
2209 std::ostringstream peerkmsAddressTemp;
2210 (it->second).dstKmsNode.Print(peerkmsAddressTemp);
2211 std::string headerUri =
"http://" + peerkmsAddressTemp.str();
2212 headerUri +=
"/api/v1/associations/new_app";
2217 std::string hMessage = httpMessage.
ToString();
2219 (uint8_t*) (hMessage).c_str(),
2231 sendSocket->
Send(packet);
2232 NS_LOG_FUNCTION(
this <<
"NEW_APP: KMS informs peer KMS on new association established!" );
2242 jNewAppRequest = nlohmann::json::parse(payload);
2247 std::string srcSaeId;
2248 std::string dstSaeId;
2251 if(jNewAppRequest.contains(
"Destination")) dstSaeId = jNewAppRequest[
"Destination"];
2252 if(jNewAppRequest.contains(
"Source")) srcSaeId = jNewAppRequest[
"Source"];
2253 if(jNewAppRequest.contains(
"Key_stream_ID")) ksid = jNewAppRequest[
"Key_stream_ID"];
2256 NS_ASSERT(srcSaeId.length()>0 || dstSaeId.length()>0 || !ksid.empty());
2258 bool qosAgreed {
true};
2289 {
"Request URI", headerIn.
GetUri() }
2291 std::string hMessage = httpMessage.
ToString();
2293 (uint8_t*) (hMessage).c_str(),
2298 NS_LOG_FUNCTION(
this <<
"NEW_APP request accepted. Association created." );
2317 NS_FATAL_ERROR(
this <<
"Response cannot be mapped! HttpQuery empty!" );
2319 std::string ksid = it->second[0].ksid;
2338 jOpenConnectResponse[
"Key_stream_ID"] = it->second[0].ksid;
2339 std::string msg = jOpenConnectResponse.dump();
2344 {
"Content-Type",
"application/json; charset=utf-8"},
2345 {
"Request URI", headerIn.
GetUri() }
2347 std::string hMessage = httpMessage.
ToString();
2349 (uint8_t*) (hMessage).c_str(),
2365 std::string ksid = it->second[0].ksid;
2380 std::map<std::string, Association004>::iterator it =
m_associations004.find(ksid);
2394 std::map<std::string, Association004>::iterator it =
m_associations004.find(ksid);
2396 NS_LOG_DEBUG(
this <<
" Key stream association identified with " << ksid <<
" does not exists!" );
2405 std::ostringstream peerkmsAddressTemp;
2406 dstKms.
Print(peerkmsAddressTemp);
2407 std::string headerUri =
"http://" + peerkmsAddressTemp.str ();
2408 headerUri +=
"/api/v1/associations/register/" + ksid;
2413 std::string hMessage = httpMessage.
ToString();
2415 (uint8_t*) (hMessage).c_str(),
2425 sendSocket->
Send(packet);
2432 std::map<std::string, Association004>::iterator it =
m_associations004.find(ksid);
2434 (it->second).peerRegistered =
true;
2440 {
"Content-Type",
"application/json; charset=utf-8"},
2441 {
"Request URI", headerIn.
GetUri() }
2443 std::string hMessage = httpMessage.
ToString();
2445 (uint8_t*) (hMessage).c_str(),
2454 NS_LOG_DEBUG(
this <<
" Key stream association identified with " << ksid <<
" does not exists!" );
2456 }
else if((it->second).peerRegistered ==
true){
2457 NS_LOG_FUNCTION(
this <<
"The peer application for asscotiation " << ksid <<
" has already been connected.");
2468 NS_FATAL_ERROR(
this <<
"Response cannot be mapped! HttpQuery empty!" );
2473 NS_LOG_FUNCTION(
this <<
"/register error! Releasing established association" << it->second[0].ksid );
2474 std::map<std::string, Association004>::iterator it1 =
m_associations004.find(it->second[0].ksid);
2493 jAddKeysRequest = nlohmann::json::parse(payload);
2498 std::map<std::string, Association004>::iterator it =
m_associations004.find(ksid);
2500 NS_LOG_DEBUG(
this <<
" Key stream association identified with " << ksid <<
" does not exists!" );
2504 UUID dstSaeId = it->second.dstSaeId;
2516 for(nlohmann::json::iterator it = jAddKeysRequest[
"keys"].begin(); it != jAddKeysRequest[
"keys"].end(); ++it){
2517 if(buffer->ProbeKeyStatus( (it.value())[
"key_ID"],
QKDKey::READY ))
2526 for(nlohmann::json::iterator it = jAddKeysRequest[
"keys"].begin(); it != jAddKeysRequest[
"keys"].end(); ++it){
2527 Ptr<QKDKey> key = buffer->FetchKeyByID( (it.value())[
"key_ID"]);
2532 NS_LOG_FUNCTION(
this <<
"Replica KMS added keys " << jAddKeysRequest.dump()
2533 <<
" to dedicated association key store " << ksid );
2538 {
"Request URI", headerIn.
GetUri() }
2540 std::string hMessage = httpMessage.
ToString();
2542 (uint8_t*) (hMessage).c_str(),
2547 NS_LOG_FUNCTION(
this <<
"Replica KMS sending response on FILL request "
2552 NS_LOG_FUNCTION(
this <<
"Replica KMS reject FILL request " << jAddKeysRequest.dump()
2553 <<
" for association " << ksid );
2557 httpMessage.
CreateResponse(HTTPMessage::HttpStatus::BadRequest,
"", {
2558 {
"Request URI", headerIn.
GetUri() }
2560 std::string hMessage = httpMessage.
ToString();
2562 (uint8_t*) (hMessage).c_str(),
2567 NS_LOG_FUNCTION(
this <<
"Replica KMS sending response on FILL request "
2583 NS_FATAL_ERROR(
this <<
"Response cannot be mapped! HttpQuery empty!" );
2585 std::string ksid = it->second[0].ksid;
2587 std::map<std::string, Association004>::iterator a =
m_associations004.find(ksid);
2589 NS_LOG_DEBUG(
this <<
" Key stream association identified with " << ksid <<
" does not exists!" );
2604 NS_FATAL_ERROR(
this <<
"QKDBuffer for this connection cannot be found" );
2607 NS_LOG_FUNCTION(
this <<
"Filling association dedicated key store" << ksid );
2608 for(std::vector<std::string>::iterator i = a->second.tempBuffer.begin(); i < a->
second.tempBuffer.end(); ++i){
2613 a->second.tempBuffer.clear();
2616 NS_LOG_FUNCTION(
this <<
"Releasing reservation of keys " << a->second.tempBuffer );
2617 for(std::vector<std::string>::iterator i = a->second.tempBuffer.begin(); i < a->
second.tempBuffer.end(); ++i)
2618 buffer->ReleaseReservation(*i);
2619 a->second.tempBuffer.clear();
2629 NS_LOG_FUNCTION(
this <<
"target size" << keySize <<
"target number" << keyNumber <<
"ksid SAE" << ksid.
string() );
2640 buffer->RecordTargetSize(keySize);
2642 bool transformSetReady =
false;
2644 std::vector<std::string> toTransformKeyIDs {};
2645 uint32_t targetSize {keySize*keyNumber};
2646 while(!transformSetReady){
2647 Ptr<QKDKey> key = buffer->SearchOptimalKeyToTransform(targetSize);
2650 buffer->ReserveKey(key->GetId());
2651 toTransformKeyIDs.push_back(key->GetId());
2652 if(key->GetSizeInBits() >= targetSize)
2653 transformSetReady =
true;
2655 targetSize -= key->GetSizeInBits();
2659 std::vector<std::string> transformKeyIDs;
2661 while(
k++<keyNumber){
2669 NS_LOG_FUNCTION(
this <<
"to_transform_key_IDs" << toTransformKeyIDs );
2673 jtransform[
"ksid"] = ksid.
string();
2674 jtransform[
"transform_key_size"] = keySize;
2675 jtransform[
"transform_key_number"] = keyNumber;
2676 for(
size_t i = 0; i < transformKeyIDs.size(); i++)
2677 jtransform[
"transform_key_IDs"].push_back({{
"key_ID", transformKeyIDs[i]}});
2678 jtransform[
"surplus_key_ID"] = surplusKeyId;
2679 for(
size_t i = 0; i < toTransformKeyIDs.size(); i++)
2680 jtransform[
"to_transform_key_IDs"].push_back({{
"key_ID", toTransformKeyIDs[i]}});
2682 std::string msg = jtransform.dump();
2691 std::ostringstream peerkmsAddressTemp;
2692 dstKms.
Print(peerkmsAddressTemp);
2693 std::string headerUri =
"http://" + peerkmsAddressTemp.str ();
2694 headerUri +=
"/api/v1/keys/transform_keys";
2699 std::string hMessage = httpMessage.
ToString();
2701 (uint8_t*) (hMessage).c_str(),
2708 httpRequest.
method_type = RequestType::TRANSFORM_KEYS;
2716 sendSocket->
Send(packet);
2720 NS_FATAL_ERROR(
this <<
"QKD buffer for this connection was not found!" );
2733 jtransformRequest = nlohmann::json::parse(payload);
2738 uint32_t keySize {0}, keyNumber {0};
2739 std::vector<std::string> toTransformKeyIDs {}, transformKeyIDs {};
2740 std::string surplusKeyId {};
2743 if(jtransformRequest.contains(
"transform_key_size"))
2744 keySize = jtransformRequest[
"transform_key_size"];
2745 if(jtransformRequest.contains(
"transform_key_number"))
2746 keyNumber = jtransformRequest[
"transform_key_number"];
2747 if(jtransformRequest.contains(
"surplus_key_ID"))
2748 surplusKeyId = jtransformRequest[
"surplus_key_ID"];
2749 if(jtransformRequest.contains(
"transform_key_IDs")){
2751 nlohmann::json::iterator it = jtransformRequest[
"transform_key_IDs"].begin();
2752 it != jtransformRequest[
"transform_key_IDs"].end();
2755 transformKeyIDs.push_back((it.value())[
"key_ID"]);
2757 if(jtransformRequest.contains(
"to_transform_key_IDs")){
2759 nlohmann::json::iterator it = jtransformRequest[
"to_transform_key_IDs"].begin();
2760 it != jtransformRequest[
"to_transform_key_IDs"].end();
2763 toTransformKeyIDs.push_back((it.value())[
"key_ID"]);
2765 if(jtransformRequest.contains(
"ksid")){
2766 ksid = jtransformRequest[
"ksid"];
2774 NS_LOG_FUNCTION(
this << keySize << keyNumber <<
"\ntransform_key_IDs"<< transformKeyIDs
2775 <<
"\nto_transform_key_IDs" << toTransformKeyIDs <<
"\nsurplus_key_ID" << surplusKeyId <<
"\nksid" << ksid );
2777 if(ksid.size() == 0){
2778 NS_FATAL_ERROR(
this <<
"No ksid specified!" << jtransformRequest.dump() );
2792 bool keysExist {
true};
2793 for(
size_t i = 0; i < toTransformKeyIDs.size(); i++){
2794 keysExist = buffer->ProbeKeyStatus(toTransformKeyIDs[i],
QKDKey::READY);
2800 uint32_t keySizeInBytes = keySize/8;
2801 std::string mergedKey {};
2802 for(
size_t i = 0; i < toTransformKeyIDs.size(); i++){
2803 mergedKey += (buffer->FetchKeyByID(toTransformKeyIDs[i], 1))->GetKeyString();
2805 for(
size_t i = 0; i < transformKeyIDs.size(); i++){
2806 std::string keyString = mergedKey.substr(0, keySizeInBytes);
2807 mergedKey.erase(0, keySizeInBytes);
2808 Ptr<QKDKey> key = CreateObject<QKDKey> (transformKeyIDs[i], keyString);
2809 buffer->AddNewKey(key,1);
2811 if(!mergedKey.empty()){
2812 Ptr<QKDKey> key = CreateObject<QKDKey> (surplusKeyId, mergedKey);
2813 buffer->AddNewKey(key,1);
2818 std::string msg = jResponse.dump();
2823 {
"Content-Type",
"application/json; charset=utf-8"},
2824 {
"Request URI", headerIn.
GetUri() }
2826 std::string hMessage = httpMessage.
ToString();
2828 (uint8_t*) (hMessage).c_str(),
2839 std::string msg = jResponse.dump();
2843 httpMessage.
CreateResponse(HTTPMessage::HttpStatus::BadRequest, msg, {
2844 {
"Content-Type",
"application/json; charset=utf-8"},
2845 {
"Request URI", headerIn.
GetUri() }
2847 std::string hMessage = httpMessage.
ToString();
2849 (uint8_t*) (hMessage).c_str(),
2858 NS_FATAL_ERROR(
this <<
"No QKD buffer found for this connection!" );
2872 jTransformResponse = nlohmann::json::parse(payload);
2874 NS_FATAL_ERROR(
this <<
"JSON parse error! Received payload:" << payload );
2877 std::string ksid =
"";
2878 if(jTransformResponse.contains(
"sae_id")) ksid = jTransformResponse[
"sae_id"];
2879 if(ksid.empty() && jTransformResponse.contains(
"ksid")) ksid = jTransformResponse[
"ksid"];
2893 HttpQuery transformPar = (it->second)[0];
2897 NS_FATAL_ERROR(
this <<
"HTTP response cannot be mapped: HTTP query to destination KMS does not exist!" );
2898 else if(it->second.empty())
2899 NS_FATAL_ERROR(
this <<
"HTTP response cannot be mapped: HTTP query is empty!" );
2906 bool keysExist {
true};
2907 for(
size_t i = 0; i < toTransformKeyIDs.size(); i++){
2908 keysExist = buffer->ProbeKeyStatus(toTransformKeyIDs[i],
QKDKey::RESERVED);
2913 uint32_t keySizeInBytes = keySize/8;
2914 std::string mergedKey {};
2915 for(
size_t i = 0; i < toTransformKeyIDs.size(); i++){
2916 mergedKey += (buffer->FetchKeyByID(toTransformKeyIDs[i], 1))->GetKeyString();
2918 for(
size_t i = 0; i < keyNumber; i++){
2919 std::string keyString = mergedKey.substr(0, keySizeInBytes);
2920 mergedKey.erase(0, keySizeInBytes);
2921 Ptr<QKDKey> key = CreateObject<QKDKey> (transformKeyIDs[i], keyString);
2922 buffer->AddNewKey(key,1);
2924 if(!mergedKey.empty()){
2925 Ptr<QKDKey> key = CreateObject<QKDKey> (surplusKeyId, mergedKey);
2926 buffer->AddNewKey(key,1);
2931 NS_FATAL_ERROR(
this <<
"KMS mistreated reserved keys: keys not found!" );
2934 NS_LOG_FUNCTION(
this <<
"Releasing reserved keys for failed transformation!");
2937 for(
size_t i = 0; i < toTransformKeyIDs.size(); i++){
2938 buffer->ReleaseReservation(toTransformKeyIDs[i]);
2940 NS_LOG_FUNCTION(
this <<
"Reserved keys are released" << toTransformKeyIDs );
2953 jcloseRequest = nlohmann::json::parse(payload);
2958 std::string surplusKeyId {};
2959 uint32_t syncIndex {0};
2960 if(jcloseRequest.contains(
"surplus_key_ID"))
2961 surplusKeyId = jcloseRequest[
"surplus_key_ID"];
2962 if(jcloseRequest.contains(
"sync_index"))
2963 syncIndex = jcloseRequest[
"sync_index"];
2965 std::map<std::string, Association004>::iterator it =
m_associations004.find(ksid);
2967 NS_LOG_FUNCTION(
this <<
"KSID not registered on KMS, or is already closed!" );
2971 httpMessage.
CreateResponse(HTTPMessage::HttpStatus::NotAcceptable,
"", {
2972 {
"Request URI", headerIn.
GetUri() }
2974 std::string hMessage = httpMessage.
ToString();
2976 (uint8_t*) (hMessage).c_str(),
2985 it->second.peerRegistered =
false;
2987 uint32_t localSyncIndex {0};
2988 if(it->second.buffer.begin() != it->second.buffer.end())
2989 localSyncIndex = it->second.buffer.begin()->first;
2994 if(!surplusKeyId.empty() && syncIndex > localSyncIndex){
2997 uint32_t presentKeyMaterial {0};
2998 for (std::map<uint32_t, ChunkKey>::iterator it2 = it->second.buffer.begin(); it2 != it->second.buffer.find(syncIndex); ++it2){
3001 presentKeyMaterial += it2->second.chunkSize;
3009 if(!surplusKeyId.empty() && syncIndex < localSyncIndex)
3010 syncIndex = localSyncIndex;
3013 if(empty && !surplusKeyId.empty())
3020 if(!surplusKeyId.empty())
3021 jresponse[
"sync_index"] = syncIndex;
3023 jresponse[
"flag_empty"] =
true;
3026 std::string msg = jresponse.dump();
3031 {
"Content-Type",
"application/json; charset=utf-8"},
3032 {
"Request URI", headerIn.
GetUri() }
3034 std::string hMessage = httpMessage.
ToString();
3036 (uint8_t*) (hMessage).c_str(),
3051 std::map<std::string, Association004>::iterator it =
m_associations004.find(ksid);
3053 NS_LOG_DEBUG(
this <<
" Key stream association identified with " << ksid <<
" does not exists!" );
3057 if(surplusKeyId.empty()){
3060 std::string preservedKeyString {};
3061 std::map<uint32_t, ChunkKey>::iterator a = it->second.buffer.find(syncIndex);
3062 while(a != it->second.buffer.end()){
3063 preservedKeyString += a->second.key;
3067 if(!preservedKeyString.empty()){
3069 UUID ksid = it->second.ksid;
3081 NS_LOG_FUNCTION(
this <<
"Releasing dedicated association buffer ... " );
3083 NS_LOG_FUNCTION(
this << preservedKeyString.size() <<
" bit of key material preserved ... " );
3084 NS_LOG_FUNCTION(
this <<
"Assigning ID to preserved key material ... " );
3085 Ptr<QKDKey> key = CreateObject<QKDKey> (surplusKeyId, preservedKeyString);
3086 buffer->AddNewKey(key, 1);
3087 NS_LOG_FUNCTION(
this <<
"Preserved key material added to the QKD buffer "
3088 << surplusKeyId << preservedKeyString.size() );
3095 NS_LOG_FUNCTION(
this <<
"Key stream association identified with " << ksid <<
"is removed!" );
3102 NS_LOG_FUNCTION(
this <<
"Processing response on KMS /close request ... " );
3106 jcloseResponse = nlohmann::json::parse(payload);
3116 std::string ksid = it->second[0].ksid;
3117 std::map<std::string, Association004>::iterator a =
m_associations004.find(ksid);
3119 NS_LOG_DEBUG(
this <<
" Key stream association identified with " << ksid <<
" does not exists!" );
3125 uint32_t presentKeyMaterial {0};
3126 for (std::map<uint32_t, ChunkKey>::iterator it2 = a->second.buffer.begin(); it2 != a->second.buffer.end(); ++it2){
3127 presentKeyMaterial += it2->second.chunkSize;
3136 uint32_t peerSyncIndex {0};
3137 uint32_t localSyncIndex {it->second[0].sync_index};
3138 if(jcloseResponse.contains(
"sync_index")){
3139 peerSyncIndex = jcloseResponse[
"sync_index"];
3140 if(peerSyncIndex > localSyncIndex)
3141 localSyncIndex = peerSyncIndex;
3144 uint32_t presentKeyMaterial {0};
3145 for (std::map<uint32_t, ChunkKey>::iterator it2 = a->second.buffer.begin(); it2 != a->second.buffer.find(localSyncIndex); ++it2){
3147 presentKeyMaterial += it2->second.chunkSize;
3153 ReleaseAssociation(it->second[0].ksid, it->second[0].surplus_key_ID, localSyncIndex);
3157 uint32_t presentKeyMaterial {0};
3158 for (std::map<uint32_t, ChunkKey>::iterator it2 = a->second.buffer.begin(); it2 != a->second.buffer.end(); ++it2){
3159 presentKeyMaterial += it2->second.chunkSize;
3190 it->second.push_back(request);
3201 if(!it->second.empty())
3202 it->second.erase(it->second.begin());
3206 NS_FATAL_ERROR(
this <<
"HTTP query to destination KMS does not exist!" );
3216 methodType = it->second.begin()->method_type;
3218 NS_FATAL_ERROR(
this <<
"HTTP response cannot be mapped: HTTP query is empty!" );
3234 std::pair<std::multimap<UUID, Ptr<Socket> >::iterator, std::multimap<uint32_t, Ptr<Socket> >::iterator > ret;
3238 std::multimap<UUID, Ptr<Socket> >::iterator it = ret.first;
3248 std::pair<std::multimap<UUID, Ptr<Socket> >::iterator, std::multimap<UUID, Ptr<Socket> >::iterator > ret;
3252 std::multimap<UUID, Ptr<Socket> >::iterator it = ret.first;
3265 std::map<Ipv4Address, std::pair<Ptr<Socket>,
Ptr<Socket> > >::iterator it;
3268 if ((it->second).first == socket) {
3269 dstKMSAddress = it->first;
3274 return dstKMSAddress;
3292 }
else if(s ==
"enc_keys") {
3296 }
else if(s ==
"dec_keys"){
3300 }
else if (s ==
"open_connect"){
3304 }
else if (s ==
"get_key") {
3308 }
else if (s ==
"close") {
3312 }
else if (s ==
"new_app") {
3316 }
else if (s ==
"register") {
3320 }
else if (s ==
"fill") {
3324 }
else if (s ==
"store_pp_key") {
3328 }
else if (s ==
"transform_keys") {
3332 }
else if (s ==
"close_kms") {
3371 std::string keyAssociationIdParam
3375 <<
"srcNodeId: " << srcNodeId
3376 <<
"dstNodeId: " << dstNodeId
3378 <<
"kmsDstAddress: " << kmsDstAddress
3379 <<
"keyAssociationIdParam: " << keyAssociationIdParam
3385 std::string keyAssociationId = keyAssociationIdParam;
3386 if(keyAssociationId.empty()){
3398 lr->AddKeyAssociationEntry(newEntry);
3403 UUID{keyAssociationId},
3413 lr->AddKeyAssociationEntry(newEntry);
3416 NS_LOG_FUNCTION (
this <<
"Create sink socket to listen requests exchanged between KMSs!" );
3420 sinkSocket->
Bind (sinkAddress);
3438 std::make_pair(sinkSocket, sendSocket)
3450 std::ostringstream mkmsAddressTemp;
3452 std::string mkmsAddressString = mkmsAddressTemp.str();
3454 std::ostringstream skmsAddressTemp;
3455 kmsDstAddress.
Print(skmsAddressTemp);
3456 std::string skmsAddressString = skmsAddressTemp.str();
3460 j[
"master_SAE_ID"] = srcNodeId;
3461 j[
"slave_SAE_ID"] = dstNodeId;
3462 j[
"next_hop_id"] = dstNodeId;
3463 j[
"key_association_id"] = keyAssociationId;
3465 j[
"master_kms_address"] = mkmsAddressString;
3466 j[
"slave_kms_address"] = skmsAddressString;
3468 NS_LOG_FUNCTION(
this <<
"Prepared JSON_PACKET_TO_SDN:" << j.dump() );
3470 std::string msg = j.dump();
3474 std::ostringstream sdnAddressTemp;
3475 sdnAddress.
Print(sdnAddressTemp);
3477 std::string headerUri =
"http://" + sdnAddressTemp.str ();
3478 headerUri +=
"/api/v1/keys/" + skmsAddressString +
"/register_qkd_link";
3483 std::string hMessage = httpMessage.
ToString();
3485 (uint8_t*) (hMessage).c_str(),
3491 NS_LOG_FUNCTION (
this <<
"Sending QKD_LINK_REGISTER to SDN CONTROLLER\n PacketID: "
3492 << packetToSdn->
GetUid() <<
" of size: " << packetToSdn->
GetSize()
3504 return keyAssociationId;
3517 uint32_t priority = 0,
3518 double expirationTime = 100
3521 NS_LOG_FUNCTION(
this <<
"keyId: \t" <<
"srcSaeId:" << srcSaeId <<
"dstSaeId:" << dstSaeId <<
"type:" <<
type);
3527 lr->AssignKeyAssociation( srcSaeId, dstSaeId,
type, priority, conn );
3553 UUID keyAssociationId,
3554 UUID applicationEntryId,
3559 uint32_t priority = 0,
3560 double expirationTime = 100
3564 <<
"keyId:" << keyAssociationId
3565 <<
"applicationEntryId:" << applicationEntryId
3566 <<
"srcSaeId:" << srcSaeId
3567 <<
"dstSaeId:" << dstSaeId
3572 if(
type ==
"etsi004_enc") {
3574 }
else if(
type ==
"etsi004_auth") {
3576 }
else if(
type ==
"etsi014_enc") {
3578 }
else if(
type ==
"etsi014_auth") {
3610 newEntry.
SetId(applicationEntryId);
3612 lr->AddApplicationEntry(newEntry);
3613 lr->UpdateQKDApplications(connectionId, newEntry.
GetId());
3620 std::ostringstream mkmsAddressTemp;
3622 std::string mkmsAddressString = mkmsAddressTemp.str();
3624 std::ostringstream skmsAddressTemp;
3626 std::string skmsAddressString = skmsAddressTemp.str();
3630 j[
"key_association_id"] = connectionId.
string();
3631 j[
"application_entry_id"] = appId.
string();
3632 j[
"client_SAE_ID"] = srcSaeId.
string();
3633 j[
"server_SAE_ID"] = dstSaeId.
string();
3635 j[
"priority"] = priority;
3636 j[
"expirationTime"] = expirationTime;
3637 j[
"master_kms_address"] = mkmsAddressString;
3638 j[
"slave_kms_address"] = skmsAddressString;
3640 NS_LOG_FUNCTION(
this <<
"Prepared JSON_PACKET_TO_SDN:" << j.dump() );
3642 std::string msg = j.dump();
3646 std::ostringstream sdnAddressTemp;
3647 sdnAddress.
Print(sdnAddressTemp);
3649 std::string headerUri =
"http://" + sdnAddressTemp.str ();
3650 headerUri +=
"/api/v1/keys/" + skmsAddressString +
"/register_sae_link";
3655 std::string hMessage = httpMessage.
ToString();
3657 (uint8_t*) (hMessage).c_str(),
3664 NS_LOG_FUNCTION (
this <<
"Sending SAE_REGISTER to SDN CONTROLLER\n PacketID: "
3687 std::string srcSaeId,
3688 std::string dstSaeId,
3693 UUID srcId (srcSaeId);
3694 UUID dstId (dstSaeId);
3700 lr->LookupApplicationBySaeIDsAndType(srcId, dstId,
type, output);
3721 lr->LookupApplication(tempId, output);
3737 UUID tempId (appId);
3741 lr->LookupKeyAssociationByApplicationId(tempId, output);
3758 lr->LookupKeyAssociationByDestinationNodeId(srcNodeId, dstNodeId, output);
3774 lr->LookupKeyAssociationById(keyAssociationId, output);
3785 lr->SaveKeyAssociation(entry);
3819 uint32_t keyNumber = 1;
3821 if(jrequest.contains(
"number")){
3822 keyNumber = jrequest[
"number"];
3824 if(jrequest.contains(
"size")){
3825 keySize = jrequest[
"size"];
3835 jError[
"message"] = std::string {
"requested parameters do not adhere to KMS rules"};
3840 jError[
"details"].push_back({{
"number_unsupported", msgDetail}});
3841 }
else if(keyNumber <= 0){
3842 std::string msgDetail =
"requested number of keys can not be lower or equal to zero";
3844 jError[
"details"].push_back({{
"number_unsupported", msgDetail}});
3849 jError[
"details"].push_back({{
"size_unsupported", msgDetail}});
3853 jError[
"details"].push_back({{
"size_unsupported", msgDetail}});
3854 }
else if(keySize % 8 != 0){
3855 std::string msgDetail =
"size shall be a multiple of 8";
3857 jError[
"details"].push_back({{
"size_unsupported", msgDetail}});
3865 NS_LOG_FUNCTION(
this << conn.
GetId() <<
"\nTarget key size: " << keySize <<
"\nTarget number: "
3866 << keyNumber <<
"\nRequired amount of key material: " << keySize*keyNumber);
3867 NS_LOG_FUNCTION(
this << conn.
GetId() <<
"\nAmount of key material in buffer: " << buffer->GetKeyCountBit()
3868 <<
"\nAmount of key material ready to be served: " << buffer->GetReadyKeyCountBit()
3869 <<
"\nAmount of key material part of target set: " << buffer->GetTargetKeyCountBit());
3870 if(buffer && keySize*keyNumber > buffer->GetReadyKeyCountBit()){
3871 jError[
"message"] = std::string {
"insufficient amount of key material"};
3873 }
else if(buffer && buffer->GetKeyCount(keySize) < keyNumber){
3875 if(buffer->GetReadyKeyCountBit() - buffer->GetTargetKeyCountBit() < keySize*keyNumber){
3876 jError[
"message"] =
"insufficient amount of key material";
3879 jError[
"message"] =
"keys are being transformed";
3893 NS_LOG_FUNCTION(
this << key->GetId() << key->GetSizeInBits() << srcNodeId << dstNodeId );
3895 bool output =
false;
3902 output = buffer->AddNewKey(key,0);
3905 double generationRate = buffer->GetAverageKeyGenerationRate();
3906 keyAssociation.
SetSKR(generationRate);
3909 double averageConsumptionRate = buffer->GetAverageKeyConsumptionRate();
3914 double ratio = generationRate - expectedConsumptionRate;
3920 <<
"keyAssociationId:" << keyAssociation.
GetId()
3921 <<
"AverageKeyGenerationRate:" << keyAssociation.
GetSKR()
3947 NS_LOG_FUNCTION(
this <<
"Create JSON Key Container data structure!");
3949 for(uint32_t i = 0; i < keys.size(); i++){
3951 std::string encodedKey =
Base64Encode(keys[i]->ConsumeKeyString());
3953 jkeys[
"keys"].push_back({ {
"key_ID", keys[i]->GetId()}, {
"key", encodedKey} });
3974 output = ksidRaw.
string();
3985 NS_LOG_FUNCTION(
this <<
"Checking the state of the association " << ksid <<
" ...");
3986 std::map<std::string, Association004>::iterator it =
m_associations004.find(ksid);
3988 NS_LOG_DEBUG(
this <<
" Key stream association identified with " << ksid <<
" does not exists!" );
3992 if(it->second.associationDirection == 0 && it->second.peerRegistered){
3994 (it->second).tempBuffer.empty() &&
3995 ((it->second).buffer.empty() || !(it->second).buffer.begin()->second.ready)
3999 it->second.qos.maxRate,
4000 it->second.qos.priority
4004 }
else if(it->second.associationDirection == 1){
4005 NS_FATAL_ERROR(
this <<
"This function must not be called on replica KMS for a given association " << ksid);
4013 std::map<std::string, Association004>::iterator it;
4017 if( it->second.qos.TTL < currentTime ) {
4019 <<
"ksid: " << (it->second).ksid
4020 <<
"srcSaeId: " << (it->second).srcSaeId
4021 <<
"dstSaeId: " << (it->second).dstSaeId
4022 <<
" with TTL time: " << it->second.qos.TTL
4038 std::map<std::string, Association004>::iterator it =
m_associations004.find(ksid);
4040 NS_LOG_DEBUG(
this <<
" Key stream association identified with " << ksid <<
" does not exists!" );
4044 UUID dstSae = (it->second).dstSaeId;
4057 buffer->GetReadyKeyCountBit() - buffer->GetTargetKeyCountBit() < keyAmount &&
4058 buffer->GetReadyKeyCountBit() - buffer->GetTargetKeyCountBit() >= it->second.qos.chunkSize
4061 keyAmount = it->second.qos.chunkSize;
4062 }
else if(buffer->GetReadyKeyCountBit() - buffer->GetTargetKeyCountBit() < it->second.qos.chunkSize){
4063 NS_LOG_FUNCTION(
this <<
"Not enough key material to assign to the association dedicated buffer!" );
4069 bool addKeysReady =
false;
4070 while(!addKeysReady){
4071 Ptr<QKDKey> key = buffer->SearchOptimalKeyToTransform(keyAmount);
4074 buffer->ReserveKey(key->GetId());
4075 jkeyIDs[
"keys"].push_back({ {
"key_ID", key->GetId()} });
4076 (it->second).tempBuffer.push_back(key->GetId());
4078 if(key->GetSizeInBits() >= keyAmount){
4079 addKeysReady =
true;
4082 keyAmount -= key->GetSizeInBits();
4084 NS_LOG_FUNCTION(
this <<
"Found key " << key->GetId() <<
" of size " << key->GetSizeInBits() <<
" to transform.\n Remaining key ammount to find: " << keyAmount);
4088 std::ostringstream peerkmsAddressTemp;
4089 dstKms.
Print(peerkmsAddressTemp);
4090 std::string headerUri =
"http://" + peerkmsAddressTemp.str ();
4091 headerUri +=
"/api/v1/associations/fill/" + ksid;
4093 std::string msg = jkeyIDs.dump();
4098 std::string hMessage = httpMessage.
ToString();
4100 (uint8_t*) (hMessage).c_str(),
4114 sendSocket->
Send(packet);
4115 NS_LOG_FUNCTION(
this <<
"Proposal of keys to fill association " << ksid
4116 <<
" dedicated store is sent!" << packet->
GetUid() << packet->
GetSize() << headerUri << msg );
4118 NS_FATAL_ERROR(
this <<
"QKD Buffer for this connection is not found!" );
4127 std::map<std::string, Association004>::iterator it =
m_associations004.find(ksid);
4129 NS_LOG_DEBUG(
this <<
" Key stream association identified with " << ksid <<
" does not exists!" );
4133 uint32_t keyChunkSize = (it->second).qos.chunkSize /8;
4134 std::string secretKey = key->ConsumeKeyString();
4136 NS_LOG_FUNCTION(
this <<
"Secret key size (bytes) " << secretKey.size() );
4138 uint32_t startingIndex = (it->second).lastIndex;
4139 bool startingInReady =
true;
4141 if((it->second).buffer.rbegin() != (it->second).buffer.rend()){
4142 startingIndex = (it->second).buffer.rbegin()->first;
4143 if( ((it->second).buffer.rbegin()->second).ready !=
true )
4144 startingInReady =
false;
4147 }
else if((it->second).lastIndex != 0)
4150 NS_LOG_FUNCTION (
this <<
"Chunk size (bytes), Start Index, Start Ready" << keyChunkSize << startingIndex << startingInReady);
4152 while (!secretKey.empty())
4154 if(!startingInReady)
4156 uint32_t currentChunkSize = ( (it->second).buffer.rbegin()->second ).key.size();
4158 uint32_t diff = keyChunkSize - currentChunkSize;
4161 std::string incompleteChunkKey = (it->second).buffer.rbegin()->second.key;
4162 if(secretKey.size() >= diff){
4163 std::string diffKey = secretKey.substr(0, diff);
4164 std::string temp = secretKey.substr(diff);
4166 std::string completeKey = incompleteChunkKey+diffKey;
4167 NS_LOG_FUNCTION(
this << incompleteChunkKey << diffKey << completeKey);
4169 (it->second).buffer.rbegin()->second.key = completeKey;
4170 (it->second).buffer.rbegin()->second.ready =
true;
4172 NS_LOG_FUNCTION(
this << startingIndex << (it->second).buffer.rbegin()->second.key );
4175 startingInReady =
true;
4177 std::string completeKey = incompleteChunkKey+secretKey;
4179 (it->second).buffer.rbegin()->second.key = completeKey;
4185 if (secretKey.size() >= keyChunkSize)
4188 len = secretKey.size();
4192 key = secretKey.substr(0, len);
4193 temp = secretKey.substr(len);
4200 keyC.
index = startingIndex;
4202 if (len == keyChunkSize)
4207 (it->second).buffer.insert(std::make_pair(startingIndex, keyC));
4212 (it->second).lastIndex = startingIndex - 1;
4213 NS_LOG_FUNCTION(
this <<
"Last index stored is " << (it->second).lastIndex );
4216 NS_LOG_FUNCTION(
this <<
"Is association empty:" << (it->second).buffer.empty() );
4217 NS_LOG_FUNCTION(
this <<
"Is association first key ready:" << (it->second).buffer.begin()->second.ready );
4218 NS_LOG_FUNCTION(
this <<
"How many keys do we have in association:" << (it->second).buffer.size() );
4226 CryptoPP::StringSource(input,
true,
4227 new CryptoPP::Base64Encoder(
4228 new CryptoPP::StringSink(output)
4238 CryptoPP::StringSource(input,
true,
4239 new CryptoPP::Base64Decoder(
4240 new CryptoPP::StringSink(output)
4260 if (jOpenConnectRequest.contains(
"QoS")) {
4261 if (jOpenConnectRequest[
"QoS"].contains(
"key_chunk_size")) inQos.
chunkSize = jOpenConnectRequest[
"QoS"][
"key_chunk_size"];
4262 if (jOpenConnectRequest[
"QoS"].contains(
"max_bps")) inQos.
maxRate = jOpenConnectRequest[
"QoS"][
"max_bps"];
4263 if (jOpenConnectRequest[
"QoS"].contains(
"min_bps")) inQos.
minRate = jOpenConnectRequest[
"QoS"][
"min_bps"];
4264 if (jOpenConnectRequest[
"QoS"].contains(
"jitter")) inQos.
jitter = jOpenConnectRequest[
"QoS"][
"jitter"];
4265 if (jOpenConnectRequest[
"QoS"].contains(
"priority")) inQos.
priority = jOpenConnectRequest[
"QoS"][
"priority"];
4266 if (jOpenConnectRequest[
"QoS"].contains(
"timeout")) inQos.
timeout = jOpenConnectRequest[
"QoS"][
"timeout"];
4267 if (jOpenConnectRequest[
"QoS"].contains(
"TTL")) inQos.
TTL = jOpenConnectRequest[
"QoS"][
"TTL"];
4288 std::string srcSaeId,
4289 std::string dstSaeId,
4293 std::string appConnectionId
4299 association004.
srcSaeId = srcSaeId;
4300 association004.
dstSaeId = dstSaeId;
4301 association004.
qos = inQos;
4305 ksid = appConnectionId;
4312 association004.
ksid = ksid;
4331 <<
"minRate:" << inQos.
minRate
4332 <<
"maxRate:" << inQos.
maxRate
4335 <<
"jitter:" << inQos.
jitter
4336 <<
"timeout:" << inQos.
timeout
4337 <<
"TTL:" << inQos.
TTL
4350 <<
"keyAssociationId:" << keyAssociation.
GetId()
4351 <<
"SKR:" << keyAssociation.
GetSKR()
4353 <<
"ratioSKR:" << ratioSKR
4357 uint32_t processWithQos = 1;
4402 std::map<std::string, uint32_t>::iterator it2 =
m_sessionList.find(ksid);
4404 NS_LOG_FUNCTION(
this <<
"SESSION with KSID " << ksid <<
" was located in the m_session_list!");
4406 NS_LOG_FUNCTION(
this <<
"SESSION with KSID " << ksid <<
" was *NOT* located in m_session_list!");
4407 NS_LOG_FUNCTION(
this <<
"WE HAVE NO ENOUGH RESOURCES TO SERVE UNTRUSTED APPS AT THE MOMENT!");
4427 uint32_t chunkSizeDoubled = (inQos.
chunkSize*1);
4428 uint32_t requestedNumberOfChunkKeys = 0;
4430 requestedNumberOfChunkKeys = 1;
4432 requestedNumberOfChunkKeys = ceil(inQos.
maxRate/chunkSizeDoubled);
4434 uint32_t supportedNumberOfChunkKeys = round (keyAssociation.
GetEffectiveSKR()/chunkSizeDoubled);
4435 uint32_t priorityThreshold = round(supportedNumberOfChunkKeys/2);
4436 uint32_t providedNumberOfChunkKeys;
4439 providedNumberOfChunkKeys =
m_random->
GetValue (priorityThreshold, supportedNumberOfChunkKeys);
4444 if(providedNumberOfChunkKeys > requestedNumberOfChunkKeys)
4445 providedNumberOfChunkKeys = requestedNumberOfChunkKeys;
4447 NS_LOG_FUNCTION(
this <<
"requestedNumberOfChunkKeys:" << requestedNumberOfChunkKeys);
4448 NS_LOG_FUNCTION(
this <<
"supportedNumberOfChunkKeys:" << supportedNumberOfChunkKeys);
4450 NS_LOG_FUNCTION(
this <<
"providedNumberOfChunkKeys:" << providedNumberOfChunkKeys);
4458 std::map<std::string, uint32_t>::iterator it2 =
m_sessionList.find(ksid);
4460 providedTTL *= it2->second;
4461 NS_LOG_FUNCTION(
this <<
"SESSION with KSID " << ksid <<
" was located in the m_session_list!");
4463 NS_LOG_FUNCTION(
this <<
"SESSION with KSID " << ksid <<
" was *NOT* located in m_session_list!");
4466 if(providedTTL > inQos.
TTL) providedTTL = inQos.
TTL;
4467 outQos.
TTL = providedTTL;
4481 requestedNumberOfChunkKeys,
4482 supportedNumberOfChunkKeys,
4483 providedNumberOfChunkKeys,
4494 uint32_t chunkSizeDoubled = (inQos.
chunkSize);
4495 uint32_t supportedNumberOfChunkKeys = round (keyAssociation.
GetEffectiveSKR()/chunkSizeDoubled);
4496 uint32_t requestedNumberOfChunkKeys = ceil (inQos.
maxRate/chunkSizeDoubled);
4497 uint32_t providedNumberOfChunkKeys = requestedNumberOfChunkKeys;
4498 uint32_t priorityThreshold = 0;
4500 if(requestedNumberOfChunkKeys > supportedNumberOfChunkKeys)
4503 providedNumberOfChunkKeys = 0;
4506 NS_LOG_FUNCTION(
this <<
"requestedNumberOfChunkKeys:" << requestedNumberOfChunkKeys);
4507 NS_LOG_FUNCTION(
this <<
"supportedNumberOfChunkKeys:" << supportedNumberOfChunkKeys);
4509 NS_LOG_FUNCTION(
this <<
"providedNumberOfChunkKeys:" << providedNumberOfChunkKeys);
4515 requestedNumberOfChunkKeys,
4516 supportedNumberOfChunkKeys,
4517 providedNumberOfChunkKeys,
4535 keyId = keyIdRaw.
string();
a polymophic address class
The base class for all ns3 applications.
void DoDispose() override
Destructor implementation.
Class for representing data rates.
uint64_t GetBitRate() const
Get the underlying bitrate.
This class can be used to hold variables of floating point type such as 'double' or 'float'.
An identifier for simulation events.
The basic class to represent both HTTP requests and responses.
uint16_t GetStatusCode() const
Get the status code for this message.
std::string GetRequestUri() const
std::string ToString()
Takes the headers added to the message along with the body and outputs it to a std::string for use in...
std::string GetUri() const
Grab the uri.
void CreateRequest(const std::string &url, const std::string &method)
std::string GetMessageBodyString()
void CreateResponse(const HttpStatus status)
HTTPMessage::HttpMethod GetMethod() const
std::string GetStatusMessage() const
Get the current status message for this message.
A basic class to parse a HTTP message, both request and response.
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.
void Print(std::ostream &os) const
Print this address to the given output stream.
static Ipv4Address GetAny()
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
void RemoveAtStart(uint32_t size)
Remove size bytes from the start of the current packet.
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
Create a new packet which contains a fragment of the original packet.
uint64_t GetUid() const
Returns the packet's Uid.
std::string ToString() const
Return a string representation of the packet.
void PrintRegistryInfo()
Print the registry information.
ConnectionType
The connection types.
@ ETSI_QKD_004_AUTHENTICATION
@ ETSI_QKD_014_AUTHENTICATION
@ ETSI_QKD_004_ENCRYPTION
@ ETSI_QKD_014_ENCRYPTION
UUID GetSrcSaeId()
Get the source (sender) application identifier.
void SetId(UUID value)
Set the application identifier.
bool IsValid()
Check if entry is valid.
UUID GetId()
Get the application identifier.
Ipv4Address GetDestinationKmsAddress() const
Get the destination KMS IP address.
QKDConnectionRegister is a class used to keep details about distant QKD links and applications.
Ipv4Address GetDestinationKmsAddress() const
Get destination KMS Address.
void SetExpectedConsumption(double value)
void PrintRegistryInfo()
Print registry info.
Ptr< QKDBuffer > GetSourceBuffer()
double GetExpectedConsumption()
Ipv4Address GetSourceKmsAddress() const
Get source KMS Address.
void SetUpdateStatusInterval(double statusInterval)
double GetUpdateStatusInterval()
void SetSKR(double value)
void SetEffectiveSKR(double value)
Address m_sdnControllerAddress
The SDN controller address.
void ProcessRegisterResponse(HTTPMessage header, Ptr< Socket > socket)
Process the REGISTER response.
uint32_t GetMaxKeyPerRequest()
Get maximum number of keys that can be supplied via a single response (ETSI QKD 014).
uint32_t m_port
Local port to bind to.
QKDApplicationEntry GetApplicationConnectionDetails(std::string saeId)
Get the application connection details.
TracedCallback< const std::string &, Ptr< QKDKey > > m_keyServedETSI014Trace
A trace for the consumed keys by the ETSI 014 clients.
void HandlePeerCloseKMSs(Ptr< Socket > socket)
Handle a connection close from the KMS.
void DataSend(Ptr< Socket >, uint32_t)
Callback function for the data sent.
Ptr< QKDKMSQueueLogic > m_queueLogic
The KMS Queue Logic for the ETSI 004 QoS handling.
void SendToSocketPairKMS(Ptr< Socket > socket, Ptr< Packet > packet)
Send the packet to the pair socket.
RequestType
Request methods.
@ ETSI_QKD_014_GET_KEY
Integer equivalent = 1.
@ ETSI_QKD_014_GET_KEY_WITH_KEY_IDS
Integer equivalent = 2.
@ ETSI_QKD_004_OPEN_CONNECT
@ ETSI_QKD_014_GET_STATUS
Integer equivalent = 0.
void HandleAccept(Ptr< Socket > s, const Address &from)
Handle an incoming connection from the application.
std::map< std::string, Association004 > m_associations004
The list of active key stream sessions.
Ptr< Socket > GetSendSocketKMS(Ipv4Address kmsDstAddress)
Obtain the send socket.
uint32_t m_default_ttl
The default value of TTL.
void DataToSDNSend(Ptr< Socket >, uint32_t)
Callback function for the data sent to the SDN controller.
uint32_t GetTotalRx() const
Get the total amount of received bytes.
void HttpKMSAddQuery(Ipv4Address dstKms, HttpQuery request)
Remember the HTTP request made to the peer KMS.
uint32_t ScheduleCheckAssociation(Time t, std::string action, std::string ksid)
Schedule the next event in the attempt to fill the key stream session buffer.
void ProcessRegisterRequest(HTTPMessage header, std::string ksid, Ptr< Socket > socket)
Process the REGISTER request.
QKDKeyAssociationLinkEntry GetKeyAssociationByNodeIds(uint32_t srcNodeId, uint32_t dstNodeId)
Get the key association link details.
std::multimap< UUID, Ptr< Socket > > m_http004App
The list of HTTP requests (without response) set to the application.
Ipv4Address GetDestinationKmsAddress(Ptr< Socket > socket)
Get the destiantion KMS IP address based on the connected socket.
void Http004AppQuery(UUID saeId, Ptr< Socket > socket)
Remember the HTTP request received from the application.
nlohmann::json Check014GetKeyRequest(nlohmann::json request, QKDKeyAssociationLinkEntry conn)
Validate the request and probe if the KMS can meet the request requirements.
void HandleAcceptKMSs(Ptr< Socket > s, const Address &from)
Handle an incoming connection from the KMS.
void CreateNew004Association(std::string srcSaeId, std::string dstSaeId, QKDKeyManagerSystemApplication::QoS &inQos, Ipv4Address dstKms, std::string &ksid, std::string appConnectionId)
Create a new key stream session.
std::map< Ipv4Address, std::pair< Ptr< Socket >, Ptr< Socket > > > m_socketPairsKMS
The accepted sockets for the communication between KMSs.
void HandleAcceptSDN(Ptr< Socket > s, const Address &from)
Handle an incoming connection from the SDN.
uint32_t m_totalRx
Total bytes received.
void PurgeExpiredAssociations()
Purge (delete) the expired ETSI 004 key stream sessions based on the QoS - TTL value.
void ProcessPacketKMSs(HTTPMessage header, Ptr< Packet > packet, Ptr< Socket > socket)
Process incoming request at the KM link.
std::string Base64Encode(std::string input)
Base64 encoder.
void ConnectionSucceeded(Ptr< Socket > socket)
Callback function after the connection to the APP is complete.
std::string GenerateKeyId()
Generate unique key identifier.
void ProcessRequestKMS(HTTPMessage header, Ptr< Socket > socket)
Process request from the peer KMS.
std::map< Ptr< Socket >, Ptr< Packet > > m_packetQueues
Buffering unsend messages due to the connection problems.
void TransformKeys(uint32_t keySize, uint32_t keyNumber, UUID slave_SAE_ID)
Transform a number of keys to a given size.
void NewAppRequest(std::string ksid)
Make a NEW_APP request to the peer KMS.
void HttpKMSCompleteQuery(Ipv4Address dstKms)
Remove the HTTP request from the list.
TracedCallback< Ptr< const Packet >, const Address & > m_rxTrace
A trace for the received packets from the applications.
void ProcessResponseKMS(HTTPMessage header, Ptr< Packet > packet, Ptr< Socket > socket)
Process response from the peer KMS.
void SetSocket(std::string type, Ptr< Socket > socket)
Set the sink socket.
void SendQKDLinkStatusToSDN(UUID linkId, double updatePeriod)
Send the QKD link statistics to the SDN controller.
std::string AddNewLink(uint32_t srcSaeId, uint32_t dstSaeId, Ipv4Address kmsDstAddress, Ptr< QKDBuffer > srcBuffer)
Register a new QKD link, or a pair of post-processing applications.
TracedCallback< const std::string &, const uint32_t &, const uint32_t & > m_keyServedETSI004Trace
A trace for the consumed keys by the ETSI 004 clients.
static uint32_t nKMS
The number of created KMSs.
void RegisterRequest(std::string ksid)
Send the REGISTER request.
QKDKeyManagerSystemApplication::RequestType FetchRequestType(std::string s)
Read the request method from the request URI.
void ProcessAddKeysRequest(HTTPMessage h, Ptr< Socket > socket, std::string ksid)
Process the FILL request.
uint32_t m_sdnSupportEnabled
The support for the SDN.
uint32_t m_kms_id
The KMS identifier.
TypeId m_tid
The object type identifier.
void ProcessCloseRequest(std::string ksid, HTTPMessage header, Ptr< Socket > socket)
static TypeId GetTypeId(void)
Get the type ID.
void NegotiateKeysForAssociation(std::string ksid, uint32_t keyAmount=1024, uint32_t priority=0)
Add new keys to the key stream session buffer.
void DataSendKMSs(Ptr< Socket >, uint32_t)
Callback function for the data sent to the peer KMS.
void CheckSessionList(std::string ksid)
Check whether a new OPEN_CONNECT was received before the previously established session expired.
Ipv4Address GetAddress()
Get the local IP address.
void HandleReadKMSs(Ptr< Socket > socket)
Handle a packet received from the KMS.
void HandlePeerError(Ptr< Socket > socket)
Handle a connection error from the application.
void HandlePeerErrorSDN(Ptr< Socket > socket)
Handle a connection error from the SDN.
void SetNode(Ptr< Node > n)
Set the node.
double m_qos_maxrate_threshold
The maximal rate threshold.
void ProcessResponseSDN(HTTPMessage header, Ptr< Packet > packet, Ptr< Socket > socket)
Process response from the SDN controller.
TracedCallback< const Ipv4Address &, Ptr< const Packet > > m_dropTrace
A trace for the dropped packets.
void HandlePeerClose(Ptr< Socket > socket)
Handle an connection close from the application.
TracedCallback< Ptr< const Packet >, const Address & > m_rxTraceKMSs
A trace for the received packets from the peer KMS.
nlohmann::json CreateKeyContainer(std::vector< Ptr< QKDKey >> keys)
Create the key container data structure.
QKDApplicationEntry GetApplicationConnectionDetailsBySaeIDsAndType(std::string srcSaeId, std::string dstSaeId, QKDApplicationEntry::ConnectionType type)
Get the application connection details.
void PrepareSinkSocket()
Prepare the sink socket.
uint32_t m_maliciousBlocking
Should KMS detect and block malicious requests?
std::map< Ptr< Socket >, Ptr< Socket > > m_socketPairs
The accepted sockets.
void PacketReceivedKMSs(const Ptr< Packet > &p, const Address &from, Ptr< Socket > socket)
Assemble a byte stream from the peer KMS to extract the HTTP message.
void ProcessTransformRequest(HTTPMessage header, Ptr< Socket > socket)
Process the transform request.
TracedCallback< const uint32_t & > m_newKeyGeneratedTraceEmir
A trace for the generated keys.
void ProcessGetKey004Request(std::string ksid, HTTPMessage header, Ptr< Socket > socket)
Ptr< Socket > GetSocketFromHttp004AppQuery(UUID saeId)
Lookup the HTTP request and obtain connected socket.
void ProcessOpenConnectRequest(HTTPMessage header, Ptr< Socket > socket)
std::map< Ptr< Socket >, Ptr< Socket > > GetAcceptedSockets(void) const
Get the list of all the accepted sockets.
void ProcessNewAppResponse(HTTPMessage header, Ptr< Socket > socket)
Process the NEW_APP response.
Ptr< Node > GetNode()
Get the node.
bool CheckDoSAttack(HTTPMessage headerIn, Ptr< Socket > socket)
Check for the DoS attack.
void CheckAssociation(std::string ksid)
Check the state of a single key stream session.
Ptr< Socket > m_sinkSocketFromSDN
The sink socket from the SND controller.
void ProcessKMSCloseRequest(HTTPMessage header, Ptr< Socket > socket, std::string ksid)
Process the close request from the peer KMS.
RequestType HttpQueryMethod(Ipv4Address dstKms)
Map the HTTP response and obtain the request method.
std::map< Ipv4Address, uint32_t > m_flagedIPAdr
A list of flaged IP addresses.
uint32_t m_maxKeyPerRequest
The maximal number of keys per request application can ask for.
QKDKeyAssociationLinkEntry GetKeyAssociationById(UUID keyAssociationId)
Get the key association link details.
void ProcessKMSCloseResponse(HTTPMessage header, Ptr< Socket > socket)
Process close response from the peer KMS.
void SaveKeyAssociation(QKDKeyAssociationLinkEntry &rt)
Add the key association.
void ConnectionToSDNSucceeded(Ptr< Socket > socket)
Callback function after the connection to the SDN controller is complete.
void AddKeyToAssociationDedicatedStore(std::string ksid, Ptr< QKDKey > key)
Add the key to the key stream session buffer.
bool connectedToSDN
Is conncted to the SDN controller?
void HandlePeerErrorKMSs(Ptr< Socket > socket)
Handle a connection error from the KMS.
DataRate m_minKeyRate
The minimal key rate.
std::map< Ptr< Socket >, Ptr< Packet > > m_packetQueuesToSDN
Buffering unsend messages due to the connection problems.
uint32_t m_defaultKeySize
The default key size KMS will deliver if the size was not defined in the request.
std::vector< std::string > ProcessUriParams(std::string s)
Read the URI parameters in a vector.
void ConnectionToSDNFailed(Ptr< Socket > socket)
Callback function after the connection to the SDN controller has failed.
void ProcessRequestSDN(HTTPMessage header, Ptr< Packet > packet, Ptr< Socket > socket)
Process request from the SDN controller.
void SendToSocketPair(Ptr< Socket > socket, Ptr< Packet > packet)
Send the packet to the pair socket.
TracedCallback< Ptr< const Packet >, const Address & > m_rxTraceSDN
A trace for the received packets from the SDN controller.
uint32_t m_maxKeySize
The maximal size of the key application can request.
Ptr< Socket > m_sinkSocket
The sink socket.
uint32_t m_totalRxKMSs
Total bytes sent between KMSs.
void PacketReceivedSDN(const Ptr< Packet > &p, const Address &from, Ptr< Socket > socket)
Assemble a byte stream from the SDN to extract the HTTP message.
void ProcessTransformResponse(HTTPMessage header, Ptr< Socket > socket)
Process the transform response.
void HandleReadSDN(Ptr< Socket > socket)
Handle a packet received from the SDN.
void HandleRead(Ptr< Socket > socket)
Handle a packet received from the application.
DataRate m_maxKeyRate
The maximal key rate.
QKDKeyAssociationLinkEntry GetKeyAssociationLinkDetailsByApplicationId(std::string appId)
Get the key association link details.
void ReadJsonQos(QKDKeyManagerSystemApplication::QoS &inQos, nlohmann::json jOpenConnectRequest)
Read the QoS parameters from the JSON OPEN_CONNECT structure.
std::unordered_map< Address, Ptr< Packet >, AddressHash > m_bufferKMS
The buffer for the received packets from the peer KMS (TCP segmentation).
QKDApplicationEntry RegisterApplicationEntry(UUID keyAssociationId, UUID applicationEntryId, UUID srcSaeId, UUID dstSaeId, std::string type, Ipv4Address dstKmsAddress, uint32_t priority, double expirationTime)
Register a new pair of QKD applications.
void StartApplication(void)
Start the KMS Application.
bool ProcessQoSRequest(QKDApplicationEntry &appConnection, QKDKeyAssociationLinkEntry &keyAssociation, QKDKeyManagerSystemApplication::QoS &inQos, QKDKeyManagerSystemApplication::QoS &outQos, std::string ksid)
Process the QoS requirements.
TracedCallback< const std::string &, const std::string &, const uint32_t &, const uint32_t &, const uint32_t &, const uint32_t &, const uint32_t & > m_providedQoS
A trace for the admitted QoS.
void ProcessNewAppRequest(HTTPMessage header, Ptr< Socket > socket)
virtual ~QKDKeyManagerSystemApplication()
Destructor.
bool AddNewKey(Ptr< QKDKey > key, uint32_t srcNodeId, uint32_t dstNodeId)
Add new keys to the QKD buffer.
std::string GenerateKsid()
Generate a new key stream session identifier (ksid).
std::map< std::string, uint32_t > m_sessionList
A list of sessions.
std::map< Ipv4Address, std::vector< HttpQuery > > m_httpRequestsQueryKMS
The list of HTTP request (without response) sent to the peer KMS.
uint32_t m_minKeySize
The minimal size of the key application can request.
void PacketReceived(const Ptr< Packet > &p, const Address &from, Ptr< Socket > socket)
Assemble a byte stream from the application to extract the HTTP message.
void StopApplication(void)
Stop the KMS Application.
TracedCallback< Ptr< const Packet > > m_txTraceKMSs
A trace for the sent packets to the peer KMS.
virtual void DoDispose(void)
Destructor implementation.
void ReleaseAssociation(std::string ksid, std::string surplusKeyId, uint32_t syncIndex)
Release the key stream session.
void HandlePeerCloseSDN(Ptr< Socket > socket)
Handle a connection close from the SDN.
void ConnectionFailedKMSs(Ptr< Socket > socket)
Callback function after the connection to the peer KMS has failed.
void ConnectionFailed(Ptr< Socket > socket)
Callback function after the connection to the APP has failed.
void ProcessRequest(HTTPMessage header, Ptr< Packet > packet, Ptr< Socket > socket)
Process incoming requests from the service layer, i.e., QKD applications.
TracedCallback< const uint32_t & > m_keyServedTraceEmir
A trace for the consumed keys.
TracedCallback< Ptr< const Packet > > m_txTrace
A trace for the sent packets to the applications.
void ConnectToSDNController()
Connect to the SDN controller.
Ptr< Socket > GetSocket(void) const
Get the sink socket.
Ptr< Socket > m_sendSocketToSDN
The send socket to the SDN controller.
Ptr< UniformRandomVariable > m_random
The uniform random variable.
void ConnectionSucceededKMSs(Ptr< Socket > socket)
Callback function after the connection to the peer KMS is complete.
uint32_t GetId()
Get the KMS identifier.
void ProcessAddKeysResponse(HTTPMessage header, Ptr< Socket > socket)
Process the FILL response.
void CheckSocketsKMS(Ipv4Address dstSaeId)
Prepare the send socket to communicate with the peer KMS.
uint32_t m_kms_key_id
The counter value to assure generation of the unique key identifiers.
QKDKeyManagerSystemApplication()
Constructor.
std::string Base64Decode(std::string input)
Base64 decoder.
uint32_t GetPort()
Get the local port.
TracedCallback< const uint32_t &, const uint32_t & > m_newKeyGeneratedTrace
A trace for the generated keys.
Ipv4Address m_local
Local address to bind to.
void Http004AppQueryComplete(UUID saeId)
Remove the HTTP request from the list.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
static Time Now()
Return the current simulation virtual time.
virtual int Send(Ptr< Packet > p, uint32_t flags)=0
Send data (or dummy data) to the remote host.
virtual Socket::SocketType GetSocketType() const =0
void SetCloseCallbacks(Callback< void, Ptr< Socket >> normalClose, Callback< void, Ptr< Socket >> errorClose)
Detect socket recv() events such as graceful shutdown or error.
void SetAcceptCallback(Callback< bool, Ptr< Socket >, const Address & > connectionRequest, Callback< void, Ptr< Socket >, const Address & > newConnectionCreated)
Accept connection requests from remote hosts.
void SetRecvCallback(Callback< void, Ptr< Socket >> receivedData)
Notify application when new data is available to be read.
virtual int ShutdownRecv()=0
void SetDataSentCallback(Callback< void, Ptr< Socket >, uint32_t > dataSent)
Notify application when a packet has been sent from transport protocol (non-standard socket call)
virtual int GetPeerName(Address &address) const =0
Get the peer address of a connected socket.
virtual int ShutdownSend()=0
virtual int Connect(const Address &address)=0
Initiate a connection to a remote host.
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...
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.
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.
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()
Get the type ID.
Simulation virtual time values and global simulation resolution.
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
a unique identifier for an interface.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Universally unique identifier (UUID)
static UUID Random()
Generate random UUID4 (randomly or pseudo-randomly generated version)
static UUID Nil()
Generate nil UUID0 (all bits set to zero)
std::string string() const
Get string from the current UUID in format "00000000-0000-0000-0000-000000000000".
static TypeId GetTypeId()
Get the type ID.
Hold an unsigned integer type.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Callback< R, Args... > MakeNullCallback()
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
#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.
Time Seconds(double value)
Construct a Time in the indicated unit.
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
NLOHMANN_BASIC_JSON_TPL_DECLARATION std::string to_string(const NLOHMANN_BASIC_JSON_TPL &j)
user-defined to_string function for JSON values
basic_json<> json
default JSON class
Every class exported by the ns3 library is enclosed in the ns3 namespace.
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...
Ptr< const AttributeChecker > MakeTypeIdChecker()
std::string GetQKDApplicationEntryText(const uint16_t statusCode)
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Ptr< const AttributeAccessor > MakeTypeIdAccessor(T1 a1)
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
The key stream session details.
uint32_t associationDirection
The key within the key stream session buffer.
The HTTP request details.
std::vector< std::string > transform_key_IDs
uint32_t transform_key_number
uint32_t transform_key_size
std::string surplus_key_ID
std::vector< std::string > to_transform_key_IDs
The Quality of service indicators.