A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
qkd-key-manager-system-application.cc
Go to the documentation of this file.
1/*
2 * Copyright(c) 2024 DOTFEESA www.tk.etf.unsa.ba
3 *
4 *
5 * Author: Emir Dervisevic <emir.dervisevic@etf.unsa.ba>
6 * Miralem Mehic <miralem.mehic@ieee.org>
7 */
8
9#include "ns3/log.h"
10#include "ns3/qcen-control.h"
11#include "ns3/address.h"
12#include "ns3/node.h"
13#include "ns3/nstime.h"
14#include "ns3/socket.h"
15#include "ns3/simulator.h"
16#include "ns3/tcp-socket-factory.h"
17#include "ns3/packet.h"
18#include "ns3/uinteger.h"
19#include "ns3/trace-source-accessor.h"
20#include "http.h"
21#include "json.h"
22#include <iostream>
23#include <fstream>
24#include <string>
25
27
28namespace ns3 {
29
30NS_LOG_COMPONENT_DEFINE("QKDKeyManagerSystemApplication");
31
32NS_OBJECT_ENSURE_REGISTERED(QKDKeyManagerSystemApplication);
33
34TypeId
36{
37 static TypeId tid = TypeId("ns3::QKDKeyManagerSystemApplication")
39 .SetGroupName("Applications")
40 .AddConstructor<QKDKeyManagerSystemApplication>()
41 .AddAttribute("Protocol", "The type of protocol to use.",
45 .AddAttribute("LocalAddress", "The ipv4 address of the application",
49 .AddAttribute("MaximalKeysPerRequest",
50 "The maximal number of keys per request(ESTI QKD 014)",
51 UintegerValue(20),
54 .AddAttribute("MinimalKeySize",
55 "The minimal size of key QKDApp can request",
56 UintegerValue(32), //in bits
59 .AddAttribute("MaximalKeySize",
60 "The maximal size of key QKDApp can request",
61 UintegerValue(10240), //in bits
64 .AddAttribute("BufferList", "The list of Qbuffers needed for plotting QKDGraphs.",
68 .AddTraceSource("Tx", "A new packet is created and is sent to the APP",
70 "ns3::QKDKeyManagerSystemApplication::Tx")
71 .AddTraceSource("Rx", "A packet from the APP has been received",
73 "ns3::QKDKeyManagerSystemApplication::Rx")
74 .AddTraceSource("TxKMSs", "A new packet is created and is sent to the APP",
76 "ns3::QKDKeyManagerSystemApplication::TxKMSs")
77 .AddTraceSource("RxKMSs", "A packet from the APP has been received",
79 "ns3::QKDKeyManagerSystemApplication::RxKMSs")
80 .AddTraceSource("QKDKeyGenerated", "The trace to monitor key material received from QL",
82 "ns3::QKDKeyManagerSystemApplication::QKDKeyGenerated")
83 .AddTraceSource("KeyServed", "The trece to monitor key usage",
85 "ns3::QKDKeyManagerSystemApplication::KeyServed")
86 .AddTraceSource("KeyConsumedLink", "The trece to monitor p2p key usage",
88 "ns3::QKDKeyManagerSystemApplication::KeyConsumedLink")
89 .AddTraceSource("RelayConsumption", "The trace to monitor key material consumed for key relay",
91 "ns3::QKDKeyManagerSystemApplication::RelayConsumption")
92 .AddTraceSource("WasteRelay", "The trace to monitor failed relays",
94 "ns3::QKDKeyManagerSystemApplication::WasteRelay")
95
96 ;
97 return tid;
98}
99
109
114
115
122
123std::string
125{
126 NS_LOG_FUNCTION(this);
127 std::ostringstream srcKmsAddressTemp;
128 address.Print(srcKmsAddressTemp); //IPv4Address to string
129 return srcKmsAddressTemp.str();
130}
131
132void
134{
135 NS_LOG_FUNCTION(this);
136 m_controller = controller;
137 GetController()->AssignKeyManager( GetNode() );
138}
139
140void
146
153
154void
155QKDKeyManagerSystemApplication::UpdateLinkState(uint32_t dstKmNodeId) //Should always be for point-to-point links! Is it enough to check on fill?(do not cosider state of S-Buffer)
156{
157 NS_LOG_FUNCTION(this << GetNode()->GetId() << dstKmNodeId);
158 if(!GetCenController())
159 {
160 NS_LOG_FUNCTION(this << "Do nothing since centralized controller is not set!");
161 return; //Do nothing since centralized controller is not set!
162 }
163
166
167 Ptr<SBuffer> sBuffer {GetSBuffer(dstKmNodeId, "enc")};
168 NS_ASSERT(sBuffer);
169
170 auto it = m_link_states.find(dstKmNodeId);
171 if(it == m_link_states.end()) NS_FATAL_ERROR(this << "Link not found!");
172 if(it->second != 3 && qBuffer->GetState() == 3){// && sBuffer->GetSBitCount() < sBuffer->GetMthr()){
173 NS_LOG_FUNCTION(this << "Link going down.");
174 std::cout << "\nLink going DOWN: " << GetNode()->GetId() << "--" << dstKmNodeId << "at time -- " << Simulator::Now() << std::endl;
175 GetCenController()->LinkDown(GetNode()->GetId(),dstKmNodeId);
176 it->second = 3;
177 }else if(it->second == 3 && qBuffer->GetBitCount() > qBuffer->GetMthr() && sBuffer->GetSBitCount() > sBuffer->GetMthr()){//qBuffer->GetState() != 3){// && sBuffer->GetSBitCount() > sBuffer->GetMthr()){
178 NS_LOG_FUNCTION(this << "Link going up.");
179 std::cout << "\nLink going UP: " << GetNode()->GetId() << "--" << dstKmNodeId << "at time -- " << Simulator::Now() << std::endl;
181 it->second = 0;
182 }
183
184}
185
192
193void
199
202{
204 Ipv4Address address;
205 auto it = m_peerAddressTable.find(dstKmNodeId);
206 if(it!=m_peerAddressTable.end())
207 address = it->second;
208 else
209 NS_LOG_ERROR(this << "Entry not found");
210
211 return address;
212}
213
214void
218)
219{
220 NS_LOG_FUNCTION(this << dstId);
221 //Create Q-Buffer
223 buffer->Init(
224 dstId,
225 bufferConf->GetMmin(),
226 bufferConf->GetMthr(),
227 bufferConf->GetMmax(),
228 bufferConf->GetBitCount(),
229 bufferConf->GetKeySize()
230 );
231
232 buffer->SetIndex( m_qbuffersVector.size() );
233 m_qbuffers.insert(std::make_pair(dstId, buffer) );
234 m_qbuffersVector.push_back(buffer);
235
236 NS_LOG_FUNCTION(this << "NEW QBUFFER created on KMS " << GetNode()->GetId() << " with index " << buffer->GetIndex() << " - " << m_qbuffersVector.size() );;
237
238 m_link_states.insert(std::make_pair(dstId, 3));
239 //Create S-Buffers for this Q-Buffer
240
242 SBufferEnc->SetRemoteNodeId(dstId);
243 SBufferEnc->Initialize();
244 SBufferEnc->SetDescription ("-Encryption");
245 m_keys_enc.insert(std::make_pair(dstId, SBufferEnc));
246 SBufferEnc->SetIndex( m_qbuffersVector.size() );
247 m_qbuffersVector.push_back(SBufferEnc);
248 m_qbuffers.insert(std::make_pair(dstId, buffer) );
249 NS_LOG_FUNCTION(this << "NEW SBUFFER:ENC created on KMS " << GetNode()->GetId() << " with index " << SBufferEnc->GetIndex() << " - " << m_qbuffersVector.size() );;
250
252 SBufferDec->SetRemoteNodeId(dstId);
253 SBufferDec->Initialize();
254 SBufferDec->SetDescription ("-Decryption");
255 m_keys_dec.insert(std::make_pair(dstId, SBufferDec));
256 SBufferDec->SetIndex( m_qbuffersVector.size() );
257 m_qbuffersVector.push_back(SBufferDec);
258 m_qbuffers.insert(std::make_pair(dstId, buffer) );
259 NS_LOG_FUNCTION(this << "NEW SBUFFER:DNC created on KMS " << GetNode()->GetId() << " with index " << SBufferDec->GetIndex() << " - " << m_qbuffersVector.size() );;
260
262}
263
264void
266{
268
269 //First initialize S-buffers(symmetric enc and dec capacities)
270 auto it = m_keys_enc.find(dstKmNodeId);
271 if(it!=m_keys_enc.end())
272 {
273 it->second->Initialize();
274 it->second->SetRemoteNodeId(dstKmNodeId);
275 it->second->SetKeySize(
276 GetQBuffer(dstKmNodeId)->GetKeySize() //Not USED, nor important!
277 );
278 it->second->SetType(SBuffer::Type::LOCAL_SBUFFER);
279 }else
280 NS_LOG_FUNCTION(this << "Unexpected error: s-buffer(enc) not found!");
281
282 auto it1 = m_keys_dec.find(dstKmNodeId);
283 if(it1!=m_keys_dec.end())
284 {
285 it1->second->Initialize();
286 it1->second->SetRemoteNodeId(dstKmNodeId);
287 it1->second->SetKeySize(
288 GetQBuffer(dstKmNodeId)->GetKeySize() //Not USED, nor important!
289 );
290 it1->second->SetType(SBuffer::Type::LOCAL_SBUFFER);
291 }else
292 NS_LOG_FUNCTION(this << "Unexpected error: s-buffer(dec) not found!");
293
294 //Only primary KM node decides to FILL the S-Buffers if possible
295 if(GetNode()->GetId() > dstKmNodeId)
297}
298
299void
301{
303
304 //Differentiate LOCAL_SBUFFER and RELAY_SBUFFER
305 auto ie = m_keys_enc.find(dstKmNodeId); //Fetch s-buffer
306 NS_ASSERT(ie != m_keys_enc.end());
307
308 //LOCAL_SBUFFER, Fill from Q-Buffer
309 if(ie->second->GetType() == SBuffer::Type::LOCAL_SBUFFER)
310 {
311 NS_LOG_FUNCTION(this << "Checking SBuffer::Type::LOCAL_SBUFFER");
312
313 //Check also the dec buffer for LOCAL_SBUFFER type
314 auto id = m_keys_dec.find(dstKmNodeId);
315 NS_ASSERT(id != m_keys_dec.end());
316
317 //Check buffers states
318 uint32_t encState = ie->second->GetState();
319 NS_LOG_FUNCTION(this << "LOCAL_SBUFFER::State::Enc" << encState << ie->second->GetBitCount() ); //testing
320
321 uint32_t decState = id->second->GetState();
322 NS_LOG_FUNCTION(this << "LOCAL_SBUFFER::State::Dec" << decState << id->second->GetBitCount() ); //testing
323
324 //If Q-Buffer is EMPTY then we cannot fill S-Buffers!
325 if(GetQBuffer(dstKmNodeId)->GetState() == 3)
326 {
327 NS_LOG_FUNCTION(this << "QBuffer is EMPTY! Exiting!");
329 return; //Force exit from function!
330 }
331
332 NS_LOG_FUNCTION(this
333 << "BitCount: " << ie->second->GetSBitCount()
334 << "\n SBitCount: " << ie->second->GetBitCount()
335 << "\n Max: " << ie->second->GetMmax()
336 );
337
338 if(
339 ie->second->GetBitCount() >= ie->second->GetMmax() &&
340 id->second->GetBitCount() >= id->second->GetMmax()
341 ){
342 NS_LOG_FUNCTION(this << "SBuffers are full! No need for fill!");
343 return;
344 }
345
346 //Amount of keys available at Q-buffer
347 uint32_t qBufferBits = GetQBuffer(dstKmNodeId)->GetBitCount() - GetQBuffer(dstKmNodeId)->GetMmin();
348 uint32_t encDemand = ie->second->GetMmax() - ie->second->GetBitCount();
349 uint32_t decDemand = id->second->GetMmax() - id->second->GetBitCount();
350 if(encState && decState)
351 { //Both enc and dec s-buffers require charging(states != READY)
352 double decreaseProcentage = 0.05;
356 }
357 Fill(dstKmNodeId, "enc", encDemand);
358 Fill(dstKmNodeId, "dec", decDemand);
359 }else if(encState){
361 encDemand = qBufferBits; //Assign all available key material from q-buffer
362 Fill(dstKmNodeId, "enc", encDemand);
363 }else if(decState){
365 decDemand = qBufferBits; //Assign all available key material from q-buffer
366 Fill(dstKmNodeId, "dec", decDemand);
367 }else
368 NS_LOG_FUNCTION(this << "LOCAL_SBUFFER(s)" << dstKmNodeId << "are in READY state!");
369
370 }else if(ie->second->GetType() == SBuffer::Type::RELAY_SBUFFER){ //RELAY_SBUFFER
371
372 NS_LOG_FUNCTION(this << "Checking SBuffer::Type::RELAY_SBUFFER");
373
374 uint32_t encState = ie->second->GetState(); //Check s-buffer state
375 NS_LOG_FUNCTION(this << "RELAY_SBUFFER::State" << encState); //testing
376 if(encState)
377 { //Triger relay to fill
378 QKDLocationRegisterEntry conn = GetController()->GetRoute(dstKmNodeId); //Get route information
379 uint32_t nextHop = conn.GetNextHop(); //Identify LOCAL_SBUFFER accessed for relay purposes
380 uint32_t encDemand = ie->second->GetMmax() - ie->second->GetBitCount(); //This is desired amount to relay!
381
382 NS_LOG_FUNCTION(this << "33333:" << nextHop << encDemand);
383
384 Ptr<SBuffer> sBuffer = GetSBuffer(nextHop, "enc"); //@todo id1125
385 NS_ASSERT(sBuffer);
386
387 uint32_t sBufferBits = sBuffer->GetDefaultKeyCount()*sBuffer->GetKeySize(); //Available amount of key material in LOCAL_SBUFFER
388
389 NS_LOG_FUNCTION(this << "How many keys in S-Buffer" << sBuffer->GetSKeyCount()
390 << "Hot many bits in S-Buffer" << sBufferBits);
391
392 if(20*ie->second->GetKeySize() < encDemand)
393 encDemand = 20*ie->second->GetKeySize(); //No more than 20 keys!!!(@toDo failed relay should decrease this value, and succesfull relay should increse it till 20)
394
396 encDemand = sBufferBits; //Assign all available key material from q-buffer
397
398 NS_LOG_FUNCTION(this << "encDemand:" << encDemand << "KeySize: " << ie->second->GetKeySize() << "sBufferBits:" << sBufferBits);
399
401
402 }else
403 NS_LOG_FUNCTION(this << "RELAY_SBUFFER" << dstKmNodeId << "is in READY state!");
404
405 }
406}
407
408void
410{
412 QKDLocationRegisterEntry conn = GetController()->GetRoute(dstKmNodeId); //Get connection details
413 NS_LOG_FUNCTION(this << "NEXT HOP:" << conn.GetNextHop());
414
415 if(amount == 0){
416 NS_LOG_FUNCTION(this << "Source cannot perform relay due to the lack of key material!");
417 return;
418 }
419
420 //QKDLocationRegisterEntry conn = GetController()->GetRoute(dstKmNodeId); //Get connection details
421 Ptr<SBuffer> relayBuffer = m_keys_enc.find(dstKmNodeId)->second; //Get RELAY_SBUFFER
423 if(relayBuffer->IsRelayActive())
424 {
425 NS_LOG_FUNCTION(this << "RELAY ACTIVE");
426 return;
427 } else {
428 relayBuffer->SetRelayState(true);
429 }
430
431 Ptr<SBuffer> localBuffer = m_keys_enc.find(conn.GetNextHop())->second; //Get LOCAL_SBUFFER
433
434 //Obtain necessary amount of keys from LOCAL_SBUFFER, Mark them as INIT, stored them in RELAY_SBUFFER
435 //NOTE: Keys must be in default size! We now assume all Q(and S) buffers have same default key size!
436 // We will extend this with relay and skey_create combined!
437 // Greater the amount, greater the possibility of relay to fail!
438 // Similar to SECOQC -- use of TCP congestion -- we should implement
439 // incremental key relay until it failes, and then decrease it if it does!
440 nlohmann::json relayPayload; //RELAY method payload -- This is RELAY-BEGIN
441 std::vector<std::string> keyIds {};
442 relayPayload["source_node_id"] = GetNode()->GetId(); //This KM node ID
443 relayPayload["destination_node_id"] = conn.GetDestinationKmNodeId(); //Destination KM node ID
444 relayPayload["encryption_type"] = "OTP"; //Only OTP is supported now
445 while(true){
446 Ptr<QKDKey> key = localBuffer->GetKey(relayBuffer->GetKeySize()); //Get key from sBuffer(key MUST be in default size!)
447 NS_ASSERT(key);
448 relayPayload["keys"].push_back({ {"key_ID", key->GetId()} }); //Add keyId object to JSON
449 keyIds.push_back(key->GetId());
450 NS_LOG_FUNCTION(this << "key state" << key->GetState());
451 //First store the key to relay SBuffer and trigger QKDPlot (new key added)
452 relayBuffer->StoreKey(key, true); //Store keys to RELAY_SBUFFER
453 //Then mark the key as INIT and also trigger QKDPlot (key removed)
454 relayBuffer->MarkKey(key->GetId(), QKDKey::INIT); //Keys are marked INIT until relay is completed!
456 GetNode()->GetId(),
457 GetNode()->GetId(),
458 conn.GetNextHop(),
459 key->GetSizeInBits()
460 );
461 if(key->GetSizeInBits() + relayBuffer->GetKeySize() > amount) //To be sure that we not exceed capacity of S-Buffer
462 break;
463 else
464 amount -= key->GetSizeInBits();
465 }
466
467 if(GetNode()->GetId() > conn.GetNextHop()) //this is master KMS //if not master, the relay request will trigger check
468 SBufferClientCheck(conn.GetNextHop()); //run sbuffer client check for LOCAL Sbuffer
469
471 std::string headerUri = "http://" + GetAddressString(nextHopAddress);
472 headerUri += "/api/v1/keys/relay";
473
474 std::string reqId {GenerateUUID()}; //HTTP request ID! Help parameter for simulation of proxies!
475 headerUri += "/?req_id=/" + reqId; //We include our Request ID in URI. It helps map responses in chain of proxies.
476
477 std::string msg = relayPayload.dump();
478
479 //Create packet
480 HTTPMessage httpMessage;
481 httpMessage.CreateRequest(headerUri, "POST", msg);
482 std::string hMessage = httpMessage.ToString();
484 (uint8_t*)(hMessage).c_str(),
485 hMessage.size()
486 );
487 NS_ASSERT(packet);
488
489 CheckSocketsKMS( nextHopAddress ); //Check connection to peer KMS!
492
493 /**
494 * Chain of responsibility pattern. HTTP chain of proxies!
495 */
498 query.method_type = RELAY_KEYS;
499 query.peerNodeId = dstKmNodeId;
500 query.prev_hop_id = GetNode()->GetId(); //Previous is ME, response reached ME!
501 query.keyIds = keyIds;
503
504 sendSocket->Send(packet);
505 NS_LOG_FUNCTION(this << "Packet sent" << conn.GetNextHop()
506 << packet->GetUid() << packet->GetSize());
507
508}
509
510void
513 std::string direction,
515)
516{
517 NS_LOG_FUNCTION(this << dstKmNodeId << direction << amount);
518
519 Ptr<SBuffer> sBuffer;
520 if(direction == "enc" || direction == "dec"){
521 sBuffer = GetSBuffer(dstKmNodeId, direction);
522 NS_ASSERT(sBuffer);
523 }else{
524 auto it = m_associations004.find(direction);
525 if(it == m_associations004.end())
526 NS_FATAL_ERROR(this << "Unknown key stream session" << direction);
527
528 sBuffer = it->second.stre_buffer;
529 }
530
533
534 nlohmann::json fillPayload; //FILL method payload
535 std::vector<std::string> keyIds;
536 fillPayload["source_node_id"] = GetNode()->GetId(); //This KM node ID
537 if(direction == "enc") //For the peer KM node, the s-buffer type is oposite!!!
538 fillPayload["s_buffer_type"] = "dec"; //s-buffer type
539 else if(direction == "dec")
540 fillPayload["s_buffer_type"] = "enc";
541 else{
542 fillPayload["s_buffer_type"] = "stream";
543 fillPayload["ksid"] = direction;
544 }
545
546
547 while(true)
548 {
549 if(
550 sBuffer->GetBitCount() + sBuffer->GetKeySize() > sBuffer->GetMmax() &&
551 fillPayload["s_buffer_type"] != "stream"
552 ){
553 //To be sure that we not exceed capacity of S-Buffer
554 NS_LOG_FUNCTION(this << "To be sure that we not exceed capacity of S-Buffer!");
555 break;
556 }
557
558 if(amount < sBuffer->GetKeySize())
559 {
560 NS_LOG_FUNCTION(this << "amount < sBuffer->GetKeySize()" << amount << sBuffer->GetKeySize());
561 break;
562 }
563
564 Ptr<QKDKey> key = qBuffer->GetKey(); //Get random key from qBuffer
565 NS_ASSERT(key);
566 NS_LOG_FUNCTION(this << "We obtained random key from qBUFFER: " << key->GetId());
567
568 fillPayload["keys"].push_back({ {"key_ID", key->GetId()} }); //Add keyId object to JSON
569 keyIds.push_back(key->GetId());
570 sBuffer->StoreKey(key, true);
571 sBuffer->MarkKey(key->GetId(), QKDKey::INIT);
572
573 if(key->GetSizeInBits() > amount)
574 {
575 NS_LOG_DEBUG(this << "Trying to FILL beyond buffer capacity! " << key->GetSizeInBits() << " / " << sBuffer->GetKeySize());
576 //NS_FATAL_ERROR(this << "Trying to FILL beyond buffer capacity! " << key->GetSizeInBits() << " / " << sBuffer->GetKeySize());
577 break;
578 }
579 else
580 amount -= key->GetSizeInBits();
581 }
582
583 if(fillPayload["keys"].empty())
584 {
585 NS_LOG_FUNCTION(this << "fillPayload is EMPTY!");
586 return;
587 }
588
589 UpdateLinkState(dstKmNodeId); //Only on fill update state down.
590
592 std::string headerUri = "http://" + GetAddressString(peerAddress);
593 headerUri += "/api/v1/sbuffers/fill";
594
595 std::string msg = fillPayload.dump();
596 NS_LOG_FUNCTION(this << headerUri << msg);
597 //Create packet
598 HTTPMessage httpMessage;
599 httpMessage.CreateRequest(headerUri, "POST", msg);
600 std::string hMessage = httpMessage.ToString();
602 (uint8_t*)(hMessage).c_str(),
603 hMessage.size()
604 );
605 NS_ASSERT(packet);
606
607 CheckSocketsKMS( peerAddress ); //Check connection to peer KMS!
610
613 query.peerNodeId = dstKmNodeId;
614 query.sBuffer = direction;
615 query.keyIds = keyIds;
617
618 sendSocket->Send(packet);
619 NS_LOG_FUNCTION(this << "Packet sent" << dstKmNodeId
620 << packet->GetUid() << packet->GetSize());
621
622}
623
626{
627 NS_LOG_FUNCTION(this << dstKmNodeId << type);
628 if(type == "enc"){
629 auto it = m_keys_enc.find(dstKmNodeId);
630 if(it != m_keys_enc.end())
631 return it->second;
632 }else if(type == "dec"){
633 auto it = m_keys_dec.find(dstKmNodeId);
634 if(it != m_keys_dec.end())
635 return it->second;
636 }else
637 NS_LOG_FUNCTION(this << "unknown type" << type);
638
639 return NULL;
640}
641
642void
645 std::string moduleId
646)
647{
648 NS_LOG_FUNCTION(this << dstId << moduleId);
649 m_qkdmodules.insert(std::make_pair(moduleId, dstId) );
650}
651
654{
656
657 for (auto it = m_qbuffers.begin(); it != m_qbuffers.end(); ++it)
658 {
659 Ptr<QBuffer> qbuffer = it->second;
660 if(it->first == remoteKmNodeId && qbuffer->GetInstanceTypeId().GetName() == type)
661 {
662 return qbuffer;
663 }
664 }
665 NS_FATAL_ERROR(this << "Buffer not found!");
666
667 return nullptr;
668}
669
670/**
671 * ********************************************************************************************
672 * SOCKET functions
673 * ********************************************************************************************
674 */
675
682
683void
685{
686 NS_LOG_FUNCTION(this << type << socket);
687 m_sinkSocket = socket;
688}
689
690void
692{
693 NS_LOG_FUNCTION(this);
694 if(m_sinkSocket) {
695 //m_sinkSocket->Close();
696 m_sinkSocket = nullptr;
697 }
698
699 std::map<Ipv4Address, std::pair<Ptr<Socket>, Ptr<Socket> > >::iterator it;
700 for( it = m_socketPairsKMS.begin(); !(it == m_socketPairsKMS.end()); it++ ){
701 if(it->second.first) {
702 //it->second.first->Close();
703 it->second.first = nullptr;
704 }
705 if(it->second.second) {
706 //it->second.second->Close();
707 it->second.second = nullptr;
708 }
709 }
711}
712
713void
719
720void
722{
723 NS_LOG_FUNCTION(this
724 << s
725 << from
726 << InetSocketAddress::ConvertFrom(from).GetIpv4()
728 );
729
731
732 //Check is it necessary to create response socket
734 auto it = m_socketPairsKMS.find(destKMS);
735 if( it != m_socketPairsKMS.end() )
736 it->second.first = s; //Set receiving socket
737 else{
739 m_socketPairsKMS.insert(
740 std::make_pair(
741 destKMS,
742 std::make_pair(s, sendSocket)
743 )
744 );
745 }
746
748
749}
750
751void
753{
754 NS_LOG_FUNCTION(this << socket);
755 NS_LOG_FUNCTION(this << "QKDKeyManagerSystemApplication Connection succeeded");
756
757 std::map<Ptr<Socket>, Ptr<Packet> >::iterator j;
758 for(j = m_packetQueues.begin(); !(j == m_packetQueues.end()); j++){
759 if(j->first == socket){
760 uint32_t response = j->first->Send(j->second);
761 response = j->first->Send(j->second);
762 m_txTrace(j->second);
763 m_packetQueues.erase(j);
764 NS_LOG_FUNCTION(this << j->first << "Sending packet from the queue!" << response );
765 }
766 }
767}
768
769void
771{
772 NS_LOG_FUNCTION(this << socket);
773 NS_LOG_FUNCTION(this << "QKDKeyManagerSystemApplication KMSs Connection succeeded");
774}
775
776void
778{
779 NS_LOG_FUNCTION(this << socket);
780 NS_LOG_FUNCTION(this << "QKDKeyManagerSystemApplication, Connection Failed");
781}
782
783void
785{
786 NS_LOG_FUNCTION(this << socket);
787 NS_LOG_FUNCTION(this << "QKDKeyManagerSystemApplication, Connection Failed");
788}
789
790void
795
796void
801
802void
807
808void
813
814void
819
820void
825
826void
828{
829 NS_LOG_FUNCTION( this << socket);
830
831 //check if socket is connected
832 //https://www.nsnam.org/doxygen/classns3_1_1_socket.html#a78a3c37a539d2e70869bb82cc60fbb09
834
835 //send the packet only if connected!
836 if(socket->GetPeerName(connectedAddress) == 0){
837 socket->Send(packet);
838 m_txTrace(packet);
839 NS_LOG_FUNCTION(this << packet->GetUid() << "sent via socket " << socket);
840 //otherwise wait in the queue
841 }else{
842 m_packetQueues.insert( std::make_pair( socket , packet) );
843 NS_LOG_FUNCTION(this << packet->GetUid() << "enqued for socket " << socket);
844 }
845}
846
847void
849{
850 NS_LOG_FUNCTION( this << socket );
851
852 std::map<Ipv4Address, std::pair<Ptr<Socket>, Ptr<Socket> > >::iterator it;
853 for( it = m_socketPairsKMS.begin(); !(it == m_socketPairsKMS.end()); it++ )
854 //we do not have info about KMS destination address ?
855 if( it->second.first == socket )
856 {
857 Ptr<Socket> sendingSocket = it->second.second;
858 sendingSocket->Send(packet);
859 NS_LOG_FUNCTION( this << "Packet ID" << packet->GetUid() << "Sending socket" << sendingSocket );
860 }
861}
862
863void
865{
867 //Local KMS should create socket to send data to peer KMS
868 //Local KMS should check if the socket for this connection already exists?
869 //Local KMS can have connections to multiple KMS systems - neighbor and distant KMSs
870 auto i = m_socketPairsKMS.find( kmsDstAddress );
871
872 if(i == m_socketPairsKMS.end()){
873 NS_LOG_FUNCTION( this << "No connection between KMS defined!"); //@toDo: include HTTP response!
876 }else{
877
878 std::pair<Ptr<Socket>, Ptr<Socket> > pair = i->second;
879 if(!pair.second){
880
881 NS_LOG_FUNCTION(this << "Let's create a new send socket to reach KMS!");
882
885
886 if(sinkSocket->GetSocketType() != Socket::NS3_SOCK_STREAM &&
887 sinkSocket->GetSocketType() != Socket::NS3_SOCK_SEQPACKET)
888 {
889 NS_LOG_FUNCTION("Create UDP socket!");
891 }else{
892 NS_LOG_FUNCTION("Create TCP socket!");
894 //disable Nagle’s algorithm
895 sendSocket->SetAttribute("TcpNoDelay", BooleanValue(true));
896 }
897 //sendSocket->ShutdownRecv();
898 sendSocket->SetConnectCallback(
902
905 8080
906 );
907 sendSocket->Bind();
908 sendSocket->Connect( peerAddress );
909
910 //update socket pair entry
911 i->second.second = sendSocket;
912
913 NS_LOG_FUNCTION(this
914 << "Create the send socket " << sendSocket
915 << " from KMS to KMS which is on " << kmsDstAddress
916 );
917
918 }else{
919 NS_LOG_FUNCTION(this << "Socket to peer KMS exist. No action required");
920 }
921
922 }
923}
924
927{
929 //Local KMS should create socket to send data to peer KMS
930 //Local KMS should check if the socket for this connection already exists?
931 //Local KMS can have connections to multiple KMS systems - neighbor and distant KMSs
932 auto i = m_socketPairsKMS.find( kmsDstAddress );
933
934 if(i == m_socketPairsKMS.end()){
935
936 NS_FATAL_ERROR( this << "No connection between KMS defined!"); //@toDo: include HTTP response!
937 return NULL;
938
939 } else {
940
941 std::pair<Ptr<Socket>, Ptr<Socket> > pair = i->second;
942 NS_ASSERT(pair.first);
943 NS_ASSERT(pair.second);
944 Ptr<Socket> sendSocket = pair.second;
945
946 return sendSocket;
947 }
948}
949
950
951void
953{
954
955 NS_LOG_FUNCTION(this << socket);
956
957 Ptr<Packet> packet;
958 Address from;
959 while((packet = socket->RecvFrom(from)))
960 {
961 if(packet->GetSize() == 0)
962 { //EOF
963 break;
964 }
965
966 m_totalRx += packet->GetSize();
967 NS_LOG_FUNCTION(this << packet << "PACKETID: " << packet->GetUid() << " of size: " << packet->GetSize() );
968
970 {
971 NS_LOG_FUNCTION(this << "At time " << Simulator::Now().GetSeconds()
972 << "s KMS received packet ID: "
973 << packet->GetUid() << " of "
974 << packet->GetSize() << " bytes from "
976 << " port " << InetSocketAddress::ConvertFrom(from).GetPort()
977 << " total Rx " << m_totalRx << " bytes");
978 }
979
980 m_rxTrace(packet, from);
981 PacketReceived(packet, from, socket);
982 }
983}
984
985void
987{
988 NS_LOG_FUNCTION(this << socket);
989
990 Ptr<Packet> packet;
991 Address from;
992 while((packet = socket->RecvFrom(from)))
993 {
994 if(packet->GetSize() == 0)
995 { //EOF
996 break;
997 }
998
999 m_totalRxKMSs += packet->GetSize();
1000 NS_LOG_FUNCTION(this << packet << "PACKETID: " << packet->GetUid() << " of size: " << packet->GetSize() );
1001
1003 {
1004 NS_LOG_FUNCTION(this << "At time " << Simulator::Now().GetSeconds()
1005 << "s KMS received packet ID: "
1006 << packet->GetUid() << " of "
1007 << packet->GetSize() << " bytes from KMS "
1009 << " port " << InetSocketAddress::ConvertFrom(from).GetPort()
1010 << " total Rx " << m_totalRx << " bytes");
1011 }
1012
1013 m_rxTraceKMSs(packet, from);
1014 PacketReceivedKMSs(packet, from, socket);
1015 }
1016}
1017
1018
1019void
1021{
1022 NS_LOG_FUNCTION(this << p->GetUid() << p->GetSize() << from);
1023
1024 // Buffer management per sender
1025 Ptr<Packet> &buffer = m_buffer[from];
1026 if (!buffer) buffer = Create<Packet>(0);
1027
1028 buffer->AddAtEnd(p);
1029 NS_LOG_DEBUG("[DEBUG] Buffer after appending packet UID " << p->GetUid() << ": " << buffer->GetSize() << " bytes");
1030
1031 // Parse the HTTP message
1032 HTTPMessageParser parser;
1033
1034 while (buffer->GetSize() > 0) {
1035 // Copy raw buffer data into a string
1036 std::string bufferStr(buffer->GetSize(), '\0');
1037 buffer->CopyData(reinterpret_cast<uint8_t*>(&bufferStr[0]), bufferStr.size());
1038
1039 // Try to extract exactly one full HTTP message
1040 std::string singleMessage;
1041 size_t messageSize = 0;
1042 if (!parser.TryExtractHttpMessage(bufferStr, singleMessage, messageSize)) {
1043 NS_LOG_DEBUG("[DEBUG] HTTP message is incomplete or fragmented, waiting for more data...");
1044 break;
1045 }
1046
1048 parser.Parse(&request, singleMessage);
1049
1050 NS_LOG_DEBUG("[DEBUG] Parsed HTTP message:\n" << request.ToString());
1051 NS_LOG_DEBUG("[DEBUG] Total HTTP message size: " << messageSize);
1052
1053 // Slice the packet and remove from buffer
1054 Ptr<Packet> completePacket = buffer->CreateFragment(0, static_cast<uint32_t>(messageSize));
1055 buffer->RemoveAtStart(static_cast<uint32_t>(messageSize));
1056
1058
1059 NS_LOG_DEBUG("[DEBUG] Remaining buffer size: " << buffer->GetSize());
1060 }
1061}
1062
1063
1064void
1066{
1067 NS_LOG_FUNCTION(this << p->GetUid() << p->GetSize() << from);
1068
1069 // Retrieve or create buffer
1070 Ptr<Packet> &buffer = m_bufferKMS[from];
1071 if (!buffer)
1072 buffer = Create<Packet>(0);
1073
1074 buffer->AddAtEnd(p);
1075 NS_LOG_DEBUG("[DEBUG] Buffer after adding packet UID " << p->GetUid() << ": " << buffer->GetSize() << " bytes");
1076
1077 HTTPMessageParser parser;
1078 while (buffer->GetSize() > 0) {
1079 // Copy current buffer to string
1080 std::string bufferStr(buffer->GetSize(), '\0');
1081 buffer->CopyData(reinterpret_cast<uint8_t*>(&bufferStr[0]), bufferStr.size());
1082
1083 // Try to extract a single HTTP message from the buffer
1084 std::string singleMessage;
1085 size_t messageSize = 0;
1086 if (!parser.TryExtractHttpMessage(bufferStr, singleMessage, messageSize)) {
1087 NS_LOG_DEBUG("[DEBUG] HTTP message is incomplete or fragmented, waiting for more data...");
1088 break;
1089 }
1090
1091 // Parse the extracted message
1092 HTTPMessage httpMessage;
1093 parser.Parse(&httpMessage, singleMessage);
1094
1095 NS_LOG_DEBUG("[DEBUG] Parsed HTTP headers:\n" << httpMessage.ToString());
1096 NS_LOG_DEBUG("[DEBUG] Parsed Content-Length: " << httpMessage.GetContentLength());
1097 NS_LOG_DEBUG("[DEBUG] Total HTTP message size (headers + body): " << messageSize);
1098
1099 // Create packet from parsed message
1100 Ptr<Packet> messagePacket = buffer->CreateFragment(0, messageSize);
1101 buffer->RemoveAtStart(messageSize);
1102
1103 ProcessPacketKMSs(httpMessage, messagePacket, socket);
1104 NS_LOG_DEBUG("[DEBUG] Remaining buffer size: " << buffer->GetSize());
1105 }
1106}
1107
1108
1109
1110/**
1111 * ********************************************************************************************
1112
1113 * APPLICATION functions
1114
1115 * ********************************************************************************************
1116 */
1117
1118void
1119QKDKeyManagerSystemApplication::StartApplication() // Called at time specified by Start
1120{
1121 NS_LOG_FUNCTION(this);
1123}
1124
1125void
1126QKDKeyManagerSystemApplication::PrepareSinkSocket() // Called at time specified by Start
1127{
1128
1129 NS_LOG_FUNCTION(this);
1130
1131 // Create the sink socket if not already
1132 if(!m_sinkSocket){
1134 NS_LOG_FUNCTION(this << "Create the sink KMS socket!" << m_sinkSocket);
1135 }
1136
1137 NS_LOG_FUNCTION(this << "Sink KMS socket listens on " << Ipv4Address::GetAny() << " and port " << m_port << " for APP requests" );
1138 //NS_LOG_FUNCTION(this << "Sink KMS socket listens on " << m_local << " and port " << m_port << " for APP requests" );
1139
1140 //InetSocketAddress sinkAddress = InetSocketAddress(m_local, m_port);
1142
1145 //m_sinkSocket->ShutdownSend();
1148 MakeNullCallback<bool, Ptr<Socket>, const Address &>(),
1150 );
1154 );
1155
1156}
1157
1158void
1159QKDKeyManagerSystemApplication::StopApplication() // Called at time specified by Stop
1160{
1161 NS_LOG_FUNCTION(this);
1162 if(m_sinkSocket)
1163 {
1166 }
1167}
1168
1169void
1171{
1172 NS_LOG_FUNCTION(this << "Scheduling new event in an attempt to fill association buffer " << ksid << " ...");
1173 if(action == "CheckEtsi004Association")
1174 {
1175 auto it = m_scheduledChecks.find(ksid);
1176 if(it==m_scheduledChecks.end())
1177 {
1179 m_scheduledChecks.insert( std::make_pair( ksid , event) );
1180 NS_LOG_FUNCTION(this << "NEW event successfully scheduled!" << action << ksid << t);
1181 } else {
1182 NS_LOG_FUNCTION(this << "Event already scheduled!" << action << ksid);
1183 }
1184 }else
1185 NS_FATAL_ERROR(this << "Invalid action as the function input recived " << action);
1186}
1187
1188void
1190{
1191 NS_LOG_FUNCTION(this << "Postponing ReleaseAssociation for slave KMS!" << ksid << surplusKeyId << syncIndex << " ...");
1192 if(action == "ReleaseAssociation")
1193 {
1194 auto it = m_scheduledChecks.find(ksid);
1195 if(it==m_scheduledChecks.end())
1196 {
1197 std::string temp = ksid + "-" + surplusKeyId + "-" + std::to_string(syncIndex);
1199 m_scheduledChecks.insert( std::make_pair( temp , event) );
1200 NS_LOG_FUNCTION(this << "NEW event successfully scheduled!" << action << ksid);
1201 } else {
1202 NS_LOG_FUNCTION(this << "Event already scheduled!" << action << ksid);
1203 }
1204 }else
1205 NS_FATAL_ERROR(this << "Invalid action as the function input recived " << action);
1206}
1207
1208/**
1209 * ********************************************************************************************
1210
1211 * Southbound interface functions(ETSI 014 & ETSI 004)
1212
1213 * ********************************************************************************************
1214 */
1215
1216void
1218{
1219 NS_LOG_FUNCTION(this << headerIn.GetUri() << packet->GetUid());
1220 NS_ASSERT(!headerIn.GetUri().empty());
1221
1222 auto uriParams = ReadUri(headerIn.GetUri());
1223 std::string ksid, remoteAppId; //Read ksid or remoteAppId
1225
1226 if(
1227 uriParams.size() > 3 &&
1228 uriParams[1] == "api" &&
1229 uriParams[2] == "v1" &&
1230 uriParams[3] == "keys"
1231 ){
1232 std::string receivedAddressStr(uriParams[0]);
1233 Ipv4Address receivedAddress = Ipv4Address(receivedAddressStr.c_str()); //string to IPv4Address
1234 if(receivedAddress != GetAddress()){
1235 NS_LOG_LOGIC( this << "The request is not for me!\t" << receivedAddress << "\t" << GetAddress() << "\t" << headerIn.GetUri());
1236 return; //Do nothing
1237 }
1239 ksid = uriParams[4];
1241 }
1242
1244 {
1245 //Process GET_STATUS request
1246 QKDLocationRegisterEntry conn = GetController()->GetRoute(remoteAppId); //Get Route Info
1247 /**@todo id1124
1248 * What if remote App ID is not known? Respond with an error.
1249 */
1250 NS_LOG_FUNCTION(this << "emira" << conn.GetDestinationKmNodeId());
1251 Ptr<SBuffer> sBuffer = GetSBuffer(conn.GetDestinationKmNodeId(), "enc");
1252 if(!sBuffer)
1253 {
1254 NS_LOG_FUNCTION(this << "The S-Buffer does not exists! This is new virtual connection!");
1255
1256 uint32_t srcNodeId = GetNode()->GetId();
1257 uint32_t dstNodeId = conn.GetDestinationKmNodeId();
1258 sBuffer = CreateRelaySBuffer(srcNodeId, dstNodeId, "(RELAY)");
1259 m_keys_enc.insert(std::make_pair(dstNodeId, sBuffer)); //Store a pointer to new sBuffer
1260 m_keys_dec.insert(std::make_pair(dstNodeId, sBuffer)); //Store a pointer to new sBuffer
1261 SBufferClientCheck(conn.GetDestinationKmNodeId()); //Start relaying keys
1262 }
1263 NS_ASSERT(sBuffer);
1264
1265 nlohmann::json j = { //Status data format
1266 {"soruce_KME_ID", GetAddressString(GetAddress())}, //Local KM Ipv4 address
1267 {"target_KME_ID", GetAddressString(conn.GetDestinationKmsAddress())}, //Destination KM Ipv4 address
1268 {"master_SAE_ID", GetController()->GetApplicationId(remoteAppId)}, //Local Application ID defined as UUID
1269 {"slave_SAE_ID", remoteAppId}, //Remote Application ID defined as UUID
1270 {"key_size", sBuffer->GetKeySize()}, //Default key size for this QKD buffer
1271 {"stored_key_count", sBuffer->GetSKeyCount()}, //Stored key(default size) count
1272 {"max_key_count", uint32_t(sBuffer->GetMmax() / sBuffer->GetKeySize())}, //Maximum key count
1273 {"max_key_per_request", GetMaxKeyPerRequest()}, //Defined by the KM!
1274 {"max_key_size", m_maxKeySize}, //Can be defined by KM! QKDBuffers should not have this limitation!
1275 {"min_key_size", m_minKeySize}, //Can be defined by KM! QKDBuffers should not have this limitation!
1276 {"max_SAE_ID_count", 0}
1277 };
1278
1279 uint32_t sBitCountTemp = sBuffer->GetSBitCount();
1280 NS_LOG_FUNCTION( this << "sBuffer->GetSBitCount " << sBitCountTemp );
1281
1282 HTTPMessage httpMessage; //Create response!
1283 httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok, j.dump(), {
1284 {"Content-Type", "application/json; charset=utf-8"},
1285 {"Request URI", headerIn.GetUri() }
1286 });
1287 std::string hMessage = httpMessage.ToString();
1288 Ptr<Packet> packet = Create<Packet>(
1289 (uint8_t*)(hMessage).c_str(),
1290 hMessage.size()
1291 );
1292 NS_ASSERT(packet);
1293
1294 NS_LOG_FUNCTION(this << "Sending response:" << uriParams[5] << "\tPacketID: " << packet->GetUid() << " of size: " << packet->GetSize() << hMessage );
1295 SendToSocketPair(socket, packet);
1296
1297 }else if(requestType == ETSI_QKD_014_GET_KEY){ //Process GET_KEY
1298
1299 QKDLocationRegisterEntry conn = GetController()->GetRoute(remoteAppId); //@todo id1124
1300 Ptr<SBuffer> sBuffer = GetSBuffer(conn.GetDestinationKmNodeId(), "enc"); //@todo id1125
1301 NS_ASSERT(sBuffer);
1302
1303 uint32_t keyNumber {1}, keySize {sBuffer->GetKeySize()}; //Set default values
1304 nlohmann::json jrequest; //Read request parameters
1305 if(headerIn.GetMethod() == HTTPMessage::HttpMethod::GET){
1306 int k = 6;
1307 while(k < int(uriParams.size())){ //Read number and size from URI
1308 if(uriParams[k] == "number")
1309 keyNumber = std::stoi(uriParams[k+1]);
1310 else if(uriParams[k] == "size")
1311 keySize = std::stoi(uriParams[k+1]); //Key size in bits!
1312 k += 2;
1313 }
1314 NS_LOG_FUNCTION(this << keyNumber << keySize);
1315 }else if(headerIn.GetMethod() == HTTPMessage::HttpMethod::POST){ //Read number and size from payload
1316 std::string payload = headerIn.GetMessageBodyString(); //Read payload
1317 try{ //Try parse JSON
1318 jrequest = nlohmann::json::parse(payload);
1319 if(jrequest.contains("number"))
1320 keyNumber = jrequest["number"];
1321 if(jrequest.contains("size"))
1322 keySize = uint32_t(jrequest["size"]);
1323 }catch(...){
1324 NS_FATAL_ERROR( this << "JSON parse error of the received payload: " << payload << "\t" << payload.length() );
1325 }
1326 }else
1327 NS_FATAL_ERROR(this << "Invalid HTTP request method" << headerIn.GetMethod()); //@toDo: include HTTP response
1328
1329 NS_LOG_FUNCTION(this << "Validate request and probe ability to serve!");
1330 nlohmann::json errorDataStructure = Check014GetKeyRequest(keyNumber, keySize, sBuffer);
1332 std::string msg;
1333 if(!errorDataStructure.empty())
1334 {
1335 NS_LOG_DEBUG(this << "We have an error. Request is not valid, or KM is unable to serve!");
1337 msg = errorDataStructure.dump();
1338 }else{
1339 NS_LOG_FUNCTION(this << "The request is valid. KM can serve key(s)");
1340
1341 std::vector<std::string> candidateSetIds {};
1342 std::string mergedKey, surplusKeyId;
1344 while(true)
1345 {
1346 NS_LOG_FUNCTION(this << "Form a transform set, and a large merged key!");
1347 uint32_t tempTarget {0};
1348 if(targetSize <= sBuffer->GetKeySize())
1350
1351 Ptr<QKDKey> candidateKey = sBuffer->GetTransformCandidate(tempTarget);
1353
1354 candidateSetIds.push_back(candidateKey->GetId());
1355 mergedKey += candidateKey->GetKeyString();
1356
1357 if(candidateKey->GetState() == QKDKey::INIT)
1358 surplusKeyId = candidateKey->GetId();
1359
1360 if(candidateKey->GetSizeInBits() >= targetSize)
1361 break;
1362 else
1363 targetSize -= candidateKey->GetSizeInBits();
1364 }
1365
1366 NS_LOG_FUNCTION(this << "Now create supply keys!");
1367 std::vector<std::string> supplyKeyIds {};
1368 std::vector<Ptr<QKDKey>> supplyKeys {};
1369 uint32_t k{0};
1370 while(k++<keyNumber){
1371 std::string skeyId = GenerateUUID();
1372 std::string keyString = mergedKey.substr(0, keySize/8);
1373 mergedKey.erase(0, keySize/8);
1374
1376 supplyKeys.push_back(tempKey);
1377 supplyKeyIds.push_back(skeyId);
1378
1379 //Record amount of served key to the end-user application
1380 m_keyServedTrace(
1382 tempKey->GetId(),
1383 tempKey->GetSizeInBits()
1384 );
1385
1386 if(sBuffer->GetType() == SBuffer::LOCAL_SBUFFER) //Then this is p2p connection!
1387 m_keyConsumedLink(
1388 GetNode()->GetId(), //Source
1389 conn.GetDestinationKmNodeId(), //Destination
1390 //tempKey->GetId(),
1391 tempKey->GetSizeInBits()
1392 );
1393
1394 }
1395 NS_ASSERT(mergedKey.empty());
1396
1397 //Create response on get_key
1398 nlohmann::json jkeys = CreateKeyContainer(supplyKeys);
1399 msg = jkeys.dump();
1400
1401
1402 //Send skey_create message to peer KM node
1403 NS_LOG_FUNCTION( this << "key_size" << keySize ); //Testing @rm
1404 NS_LOG_FUNCTION( this << "key_number" << keyNumber);
1405 NS_LOG_FUNCTION( this << "supply_key_IDs" << supplyKeyIds );
1406 NS_LOG_FUNCTION( this << "candidate_set_IDs" << candidateSetIds );
1407 NS_LOG_FUNCTION( this << "surplus_key_ID" << surplusKeyId);
1408
1409 //Create HTTP message transform
1410 nlohmann::json jtransform;
1411 jtransform["source_node_id"] = GetNode()->GetId(); //Currently to find S-Buffer on remote KM @todo use KM ID
1412 jtransform["target_SAE_ID"] = remoteAppId;
1413 jtransform["key_size"] = keySize;
1414 jtransform["key_number"] = keyNumber;
1415 for(size_t i = 0; i < supplyKeyIds.size(); i++)
1416 jtransform["supply_key_ID"].push_back({{"key_ID", supplyKeyIds[i]}});
1417 for(size_t i = 0; i < candidateSetIds.size(); i++)
1418 jtransform["candidate_set_ID"].push_back({{"key_ID", candidateSetIds[i]}});
1419
1420 std::string msg1 = jtransform.dump();
1421 NS_LOG_FUNCTION( this << "Transform payload" << msg1 ); //Testing @rm
1422 Ipv4Address dstKms = conn.GetDestinationKmsAddress(); //Destination KMS adress
1423 CheckSocketsKMS(dstKms); //Check connection to peer KMS!
1424 Ptr<Socket> sendSocket = GetSendSocketKMS(dstKms); //Get send socket to peer KMS
1425 NS_ASSERT(sendSocket); //Check
1426
1427 //Create packet
1428 std::string headerUri = "http://" + GetAddressString(dstKms);
1429 headerUri += "/api/v1/sbuffers/skey_create";
1430
1431 HTTPMessage httpMessage;
1432 httpMessage.CreateRequest(headerUri, "POST", msg1);
1433 std::string hMessage = httpMessage.ToString();
1434 Ptr<Packet> packet = Create<Packet>(
1435 (uint8_t*)(hMessage).c_str(),
1436 hMessage.size()
1437 );
1438 NS_ASSERT(packet);
1439
1440 HttpQuery httpRequest;
1441 httpRequest.method_type = RequestType::TRANSFORM_KEYS;
1442 httpRequest.peerNodeId = conn.GetDestinationKmNodeId();
1443 httpRequest.surplus_key_ID = surplusKeyId;
1444 HttpKMSAddQuery(dstKms, httpRequest); //Remember request to properly map response!
1445
1446 sendSocket->Send(packet);
1447 NS_LOG_FUNCTION(this << "SKEY_CREATE request sent to peer KM" << packet->GetUid() << packet->GetSize());
1448
1449 }
1450
1451 if(sBuffer->GetType() == SBuffer::RELAY_SBUFFER || GetNode()->GetId() > conn.GetDestinationKmNodeId()){
1452 SBufferClientCheck(conn.GetDestinationKmNodeId());
1453 }
1454
1455 //create packet
1456 HTTPMessage httpMessage;
1457 httpMessage.CreateResponse(statusCode, msg, {
1458 {"Content-Type", "application/json; charset=utf-8"},
1459 {"Request URI", headerIn.GetUri() }
1460 });
1461 std::string hMessage = httpMessage.ToString();
1462 Ptr<Packet> packet = Create<Packet>(
1463 (uint8_t*)(hMessage).c_str(),
1464 hMessage.size()
1465 );
1466 NS_ASSERT(packet);
1467
1468 NS_LOG_FUNCTION(this << "\nSending PacketID: " << packet->GetUid() << " of size: " << packet->GetSize() << hMessage);
1469
1470 //SendToSocketPair(socket, packet);
1472
1473 }else if(requestType == ETSI_QKD_014_GET_KEY_WITH_KEY_IDS){ //Process GET_KEY_WITH_KEY_IDS
1474 QKDLocationRegisterEntry conn = GetController()->GetRoute(remoteAppId); //@todo id1124
1475 Ptr<SBuffer> sBuffer = GetSBuffer(conn.GetDestinationKmNodeId(), "dec");
1476 NS_ASSERT(sBuffer);
1477
1478 nlohmann::json jkeyIDs;
1479 try{
1480 jkeyIDs = nlohmann::json::parse(headerIn.GetMessageBodyString()); //Parse packet payload to JSON structure
1481 }catch(...){
1482 NS_FATAL_ERROR( this << "JSON parse error!" );
1483 }
1484
1485 std::vector<std::string> keyIDs; //Vector containing keyIDs
1486 for(nlohmann::json::iterator it = jkeyIDs["key_IDs"].begin(); it != jkeyIDs["key_IDs"].end(); ++it)
1487 keyIDs.push_back((it.value())["key_ID"]); //keyIDs read from JSON
1488
1489 //Fetch keys with defined keyIDs from buffer
1490 std::vector<Ptr<QKDKey>> keys {};
1491 bool error {false};
1492 for(const auto &el : keyIDs){
1493 Ptr<QKDKey> tempKey = sBuffer->GetSupplyKey(el);
1494 if(tempKey){
1495 NS_LOG_FUNCTION(this << "krec007" << el << "succeeded");
1496 keys.push_back(tempKey);
1497 m_keyServedTrace(
1499 tempKey->GetId(),
1500 tempKey->GetSizeInBits()
1501 );
1502
1503 if(sBuffer->GetType() == SBuffer::LOCAL_SBUFFER) //Then this is p2p connection!
1504 m_keyConsumedLink(
1505 GetNode()->GetId(), //Source
1506 conn.GetDestinationKmNodeId(), //Destination
1507 //tempKey->GetId(),
1508 tempKey->GetSizeInBits()
1509 );
1510
1511 }else //The key is not present in SBuffer
1512 error = true;
1513
1514 }
1515
1516 std::string msg;
1518 if(!error){
1519 nlohmann::json jkeys = CreateKeyContainer(keys);
1520 msg = jkeys.dump();
1521
1522 }else{
1524 msg = nlohmann::json{ {"message", "key not found"} }.dump();
1525 NS_LOG_FUNCTION(this << msg);
1526 }
1527
1528 //create packet
1529 HTTPMessage httpMessage;
1530 httpMessage.CreateResponse(statusCode, msg, {
1531 {"Content-Type", "application/json; charset=utf-8"},
1532 {"Request URI", headerIn.GetUri() }
1533 });
1534
1535 std::string hMessage = httpMessage.ToString();
1536 Ptr<Packet> packet = Create<Packet>(
1537 (uint8_t*)(hMessage).c_str(),
1538 hMessage.size()
1539 );
1540 NS_ASSERT(packet);
1541
1542 NS_LOG_FUNCTION(this << "Sending Response to ETSI_QKD_014_GET_KEY\n PacketID: " << packet->GetUid() << " of size: " << packet->GetSize() << hMessage );
1543 SendToSocketPair(socket, packet);
1544
1545 } else if(requestType == ETSI_QKD_004_OPEN_CONNECT) {
1546
1547 //m_queueLogic->Enqueue(headerIn);
1548 //HTTPMessage h2 = m_queueLogic->Dequeue();
1549
1550 ProcessOpenConnectRequest(headerIn, socket);
1551
1552
1553 } else if(requestType == ETSI_QKD_004_GET_KEY) {
1554 ProcessGetKey004Request(ksid, headerIn, socket); //@toDo "" should be ksid, read from uri param
1555 } else if(requestType == ETSI_QKD_004_CLOSE) {
1556 ProcessCloseRequest(ksid, headerIn, socket);
1557
1558 } else if(requestType == STORE_KEY) {
1559
1560 std::string payload = headerIn.GetMessageBodyString(); //Read payload
1561 nlohmann::json payloadContent;
1562 try{
1563 payloadContent = nlohmann::json::parse(payload); //Parse payload to JSON
1564 }catch(...){
1565 NS_LOG_FUNCTION( this << "JSON parse error!"); //Catch parse error
1566 }
1567
1568 //Read JSON structure
1569 std::string keyValue, keyId, moduleId, matchingModuleId;
1570 if(payloadContent.contains("key_ID"))
1571 keyId = payloadContent["key_ID"]; //Read key ID(Mandatory)
1572 else{
1573 NS_LOG_ERROR(this << "QKD-key ID missing!");
1574 return;
1575 }
1576 if(payloadContent.contains("key"))
1577 {
1578 std::string keyValueBase64 = payloadContent["key"]; //Read key value(Mandatory)
1579 keyValue = m_encryptor->Base64Decode(keyValueBase64); //Read key value(Mandatory)
1580 }else{
1581 NS_LOG_ERROR(this << "QKD-key value missing!");
1582 return;
1583 }
1584 moduleId = payloadContent["qkd_module_ID"]; //Read local QKD module ID(Mandatory)
1585 matchingModuleId = payloadContent["matching_qkd_module_ID"]; //Read peer QKD module ID(Mandatory)
1586
1587 NS_LOG_INFO(this << "\nRequest:\t" << "STORE_KEY"
1588 << "\nKeyID:\t" << keyId
1589 << "\nKeyValue:\t" << keyValue
1590 << "\nKeySize(bits):\t" << keyValue.size()*8
1591 << "\nQKD Module ID:\t" << moduleId
1592 << "\nMatching QKD Module ID:\t" << matchingModuleId);
1593
1594 /**
1595 * Currently we will go with the following idea:
1596 * - KM with a higher Node ID is selected as a master.
1597 * - Master and slave reformats keys to a default size for THIS connection!
1598 * - Master and slave KM store keys. Keys are marked as READY.
1599 * Key IDs are:
1600 * for master: HASH-SHA1(QKD-key ID | QKD module ID | matching QKD module ID | chunk number)
1601 * for slave: HASH-SHA1(QKD-key ID | matching QKD module ID | QKD module ID | chunk number)
1602 *
1603 * The verfication procedure is not implemented. It should be similar to a Q3P STORE subprotocol.
1604 */
1605
1606 //Determine the destination KM node based on QKD module ID
1607 auto it = m_qkdmodules.find(moduleId);
1608 uint32_t dstNodeId;
1609 if(it!=m_qkdmodules.end())
1610 dstNodeId = it->second;
1611 else
1612 NS_FATAL_ERROR(this << "Unknown module ID");
1613
1614 //Determine a KM role
1615 bool isMaster {false};
1616 if(GetNode()->GetId() > dstNodeId)
1617 isMaster = true; //This node, with higher node ID, takes role of a master!
1618
1619 /**
1620 * In my opinion, KM should not transform the QKD-key in different block sizes,
1621 * but rather choose one, most appropriate. In fact, when provisioning keys,
1622 * KM would have to rendezvous with peer KM anyway, so the question is really
1623 * about key transformation operation and memory organization in key storage.
1624 *
1625 * @toDo How to choose this default key size?
1626 */
1627 Ptr<QBuffer> buffer = GetQBuffer(dstNodeId); //Select QKD buffer
1628 if(!buffer){
1629 NS_LOG_ERROR(this << "Buffer not found!");
1630 return;
1631 }
1632 Ptr<QKDEncryptor> encryptor = Create<QKDEncryptor>(64); //64 bits long key IDs. Collisions->0
1633 uint32_t keySizeInBits = keyValue.size() ? keyValue.size()*8 : 0;
1634 if(isMaster)
1635 m_qkdKeyGeneratedTrace(moduleId, keyId, keySizeInBits);
1636 else
1637 m_qkdKeyGeneratedTrace(matchingModuleId, keyId, keySizeInBits);
1638
1639 NS_LOG_FUNCTION(this << "keySizeInBytes:" << keyValue.size());
1640
1641 NS_LOG_FUNCTION(this << "keySizeInBits:" << keySizeInBits);
1642
1643 std::string hashInput;
1644 if(isMaster)
1645 hashInput = keyId + moduleId + matchingModuleId; //HASH input for master
1646 else
1647 hashInput = keyId + matchingModuleId + moduleId; //HASH input for slave
1648 NS_ASSERT(!hashInput.empty());
1649
1650 uint16_t blockIndex {0};
1651 uint32_t blockSize {buffer->GetKeySize()/8}; //Current default key size for connection
1652
1653 NS_LOG_FUNCTION(this << "blockSize:" << blockSize);
1654
1655 while(!keyValue.empty())
1656 {
1657 std::string keyValueTemp {keyValue};
1658 if(keyValue.size() >= blockSize)
1659 keyValueTemp = keyValue.substr(0, blockSize); //Take portion of the QKD-key value for KMA-key
1660 std::string completeHashInput = hashInput + std::to_string(blockIndex); //Complete HASH input
1661 std::string blockKeyId {encryptor->SHA1(completeHashInput)}; //Generate KMA-key ID based on the HASH output
1662 Ptr<QKDKey> newKey = Create<QKDKey>(blockKeyId, keyValueTemp); //Create a QKDKey object to represent KMA-key
1663 newKey->SetModuleId(moduleId);
1664 buffer->StoreKey(newKey); //Store KMA-key in QKD buffer
1665 keyValue.erase(0, blockSize); //Update QKD-key value
1666 blockIndex++;
1667 }
1668
1669 UpdateLinkState(dstNodeId); //Update link state on generation for link UP.
1670
1671 if(isMaster)
1672 SBufferClientCheck(dstNodeId); //We should check the state of the s-buffers now that there is fresh key material
1673
1674 }
1675}
1676
1677void
1678QKDKeyManagerSystemApplication::ProcessPacketKMSs(HTTPMessage headerIn, Ptr<Packet> packet, Ptr<Socket> socket)
1679{
1680 NS_LOG_FUNCTION(this);
1681 if(headerIn.GetUri() != "") //Process request!
1682 ProcessRequestKMS(headerIn, socket);
1683 else //Process response!
1684 ProcessResponseKMS(headerIn, packet, socket);
1685}
1686
1687
1688void
1689QKDKeyManagerSystemApplication::ProcessRequestKMS(HTTPMessage headerIn, Ptr<Socket> socket)
1690{
1691 NS_LOG_FUNCTION(this);
1693 std::string s = headerIn.GetUri();
1694 std::string delimiter = "/";
1695
1696 size_t pos = 0;
1697 std::string token;
1698 std::vector<std::string> uriParams;
1699 while((pos = s.find(delimiter)) != std::string::npos){
1700 token = s.substr(0, pos);
1701 if(!token.empty()){
1702 uriParams.push_back(token);
1703 }
1704 s.erase(0, pos + delimiter.length());
1705 }
1706 if(!s.empty()){
1707 uriParams.push_back(s);
1708 }
1709 requestType = FetchRequestType(uriParams[4]); // new_app, register, fill, transform_keys, close, relay_keys
1710
1711 if(requestType == NEW_APP)
1712 ProcessNewAppRequest(headerIn, socket);
1713 else if(requestType == REGISTER){
1714 std::string ksid = uriParams[5];
1715 NS_ASSERT( !ksid.empty() );
1716 ProcessRegisterRequest(headerIn, ksid, socket);
1717 }else if(requestType == FILL){
1718 std::string resource = uriParams[3];
1719 ProcessFillRequest(headerIn, resource, socket);
1720 }else if(requestType == TRANSFORM_KEYS){
1721 ProcessSKeyCreateRequest(headerIn, socket);
1722 }else if(requestType == ETSI_QKD_004_KMS_CLOSE){
1723 std::string ksid = uriParams[5];
1724 NS_ASSERT( !ksid.empty() );
1725 ProcessKMSCloseRequest(headerIn, socket, ksid);
1726 }else if(requestType == RELAY_KEYS){
1727 ProcessRelayRequest(headerIn, socket);
1728 }else
1729 NS_FATAL_ERROR( this << "Invalid request made to this KMS!" );
1730}
1731
1732void
1733QKDKeyManagerSystemApplication::ProcessResponseKMS(HTTPMessage headerIn, Ptr<Packet> packet, Ptr<Socket> socket)
1734{
1735 NS_LOG_FUNCTION( this << "Processing peer KMS response" << headerIn.GetRequestUri());
1736
1737 if(headerIn.GetRequestUri() != ""){
1738 std::vector<std::string> uriParams = ReadUri(headerIn.GetRequestUri());
1739 NS_LOG_FUNCTION(this << uriParams[4]);
1740 RequestType methodType = FetchRequestType(uriParams[4]);
1741
1742 if(methodType == NEW_APP)
1743 ProcessNewAppResponse(headerIn, socket);
1744 else if(methodType == REGISTER)
1745 ProcessRegisterResponse(headerIn, socket);
1746 else if(methodType == FILL)
1747 ProcessFillResponse(headerIn, Ipv4Address(uriParams[0].c_str()));
1748 else if(methodType == TRANSFORM_KEYS)
1749 ProcessSKeyCreateResponse(headerIn, socket);
1750 else if(methodType == ETSI_QKD_004_KMS_CLOSE)
1751 ProcessKMSCloseResponse(headerIn, socket);
1752 else if(methodType == RELAY_KEYS)
1753 ProcessRelayResponse(headerIn);
1754 else
1755 NS_FATAL_ERROR( this << "Invalid request method!" );
1756 }
1757
1758}
1759
1760
1761/**
1762 * ********************************************************************************************
1763
1764 * ETSI004 APP-KMS functions
1765
1766 * ********************************************************************************************
1767 */
1768
1769void
1770QKDKeyManagerSystemApplication::ProcessOpenConnectRequest(HTTPMessage headerIn, Ptr<Socket> socket)
1771{
1772 NS_LOG_FUNCTION(this << headerIn.GetMessageBodyString());
1773 std::string payload = headerIn.GetMessageBodyString();
1774 nlohmann::json jOpenConnectRequest;
1775 try{
1776 jOpenConnectRequest = nlohmann::json::parse(payload);
1777 }catch(...) {
1778 NS_FATAL_ERROR( this << "JSON parse error!" );
1779 }
1780
1781 std::string ksid;
1782 std::string srcSaeId;
1783 std::string dstSaeId;
1785 if(jOpenConnectRequest.contains("Destination"))
1786 dstSaeId = jOpenConnectRequest["Destination"];
1787 if(jOpenConnectRequest.contains("Source"))
1788 srcSaeId = jOpenConnectRequest["Source"];
1789 if(jOpenConnectRequest.contains("Key_stream_ID"))
1790 ksid = jOpenConnectRequest["Key_stream_ID"];
1791 ReadJsonQos(inQos, jOpenConnectRequest);
1792 NS_ASSERT(!srcSaeId.empty() || !dstSaeId.empty());
1793
1794 /**
1795 * @toDo
1796 * First some sort of CAC is neccessary. Do we have enough resources to allow this association?
1797 * Second, even if it seems that we do not have resources, if the request has high priority
1798 * can we gather enough key material that is reserved for different associations that have
1799 * lower priority. Or allow association, and from now on do not fill low priority association
1800 * and generated key use to fill this high priority association.
1801 *
1802 * For now, in the point-to-point link scenario, the open_connect request is always accepted!
1803 */
1804
1805 QKDLocationRegisterEntry conn = GetController()->GetRoute(dstSaeId);
1806 bool callByMaster {ksid.empty()};
1807 if(callByMaster){ //Request made by master SAE!
1808 ksid = CreateKeyStreamSession(srcSaeId, dstSaeId, inQos, ksid); //Create new key stream session!
1809 if(conn.GetHop() == 1){ //Point-to-point connection
1810 nlohmann::json jOpenConnectResponse {{"Key_stream_ID", ksid}}; //Key_stream_ID in response!
1811 HTTPMessage httpMessage;
1812 httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok, jOpenConnectResponse.dump(), {
1813 {"Content-Type", "application/json; charset=utf-8"},
1814 {"Request URI", headerIn.GetUri() }
1815 });
1816 std::string hMessage = httpMessage.ToString();
1817 Ptr<Packet> packet = Create<Packet>(
1818 (uint8_t*)(hMessage).c_str(),
1819 hMessage.size()
1820 );
1821 NS_ASSERT(packet);
1822 SendToSocketPair(socket, packet); //Respond to SAE!
1823
1824 }else{ //Not-Supported
1825 NS_FATAL_ERROR(this << "ETSI QKD 004 is supported only for point-to-point connections");
1826 return;
1827 }
1828
1829 NewAppRequest(ksid); //Send NEW_APP notification
1830
1831 }else{ //Request made by slave SAE!
1832 auto it = m_associations004.find(ksid);
1833 if(it == m_associations004.end()){
1834 NS_LOG_ERROR(this << "Key stream association identified with " << ksid << "does not exists!");
1835 //@toDo error response
1836 return;
1837
1838 }else if((it->second).srcSaeId != srcSaeId){
1839 NS_LOG_ERROR(this << "KSID is not registered for this application" <<(it->second).dstSaeId << srcSaeId);
1840 //@toDo error response
1841 return;
1842
1843 }else{
1844 (it->second).peerRegistered = true; //Change the sate of key stream session to active!
1845 RegisterRequest(ksid); //Send REGISTER notification
1846 HTTPMessage httpMessage;
1847 httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok, "", {
1848 {"Content-Type", "application/json; charset=utf-8"},
1849 {"Request URI", headerIn.GetUri() }
1850 });
1851 std::string hMessage = httpMessage.ToString();
1852 Ptr<Packet> packet = Create<Packet>(
1853 (uint8_t*)(hMessage).c_str(),
1854 hMessage.size()
1855 );
1856 NS_ASSERT(packet);
1857 SendToSocketPair(socket, packet); //Respond to SAE!
1858 }
1859
1860 }
1861
1862}
1863
1864void
1865QKDKeyManagerSystemApplication::ProcessGetKey004Request(std::string ksid, HTTPMessage headerIn, Ptr<Socket> socket)
1866{
1867 NS_LOG_FUNCTION( this << "Processing get_key request(ETSI 004)" << ksid );
1868 auto it = m_associations004.find(ksid);
1869 if(it == m_associations004.end()){
1870 NS_LOG_DEBUG( this << "Key stream association identified with " << ksid << "does not exists!" );
1871
1872 //create packet
1873 HTTPMessage httpMessage;
1874 httpMessage.CreateResponse(HTTPMessage::HttpStatus::BadRequest, "", {
1875 {"Request URI", headerIn.GetUri() }
1876 });
1877 std::string hMessage = httpMessage.ToString();
1878 Ptr<Packet> packet = Create<Packet>(
1879 (uint8_t*)(hMessage).c_str(),
1880 hMessage.size()
1881 );
1882 NS_ASSERT(packet);
1883
1884 SendToSocketPair(socket, packet);
1885 return;
1886 }
1887
1888 //PeerRegistered must be true @toDo - first check this(in case of QKDApp004 this will never happen)
1889 NS_LOG_FUNCTION(this << "EMIRS" << it->second.stre_buffer->GetStreamKeyCount() << it->second.peerRegistered);
1890
1891 if( it->second.peerRegistered && it->second.stre_buffer->GetStreamKeyCount())
1892 { //Check
1893 Ptr<QKDKey> keyChunk = it->second.stre_buffer->GetStreamKey();
1894 if(GetNode()->GetId() > it->second.dstNodeId)
1895 CheckEtsi004Association(ksid); //Check if new keys need to be negotiated
1896
1897 nlohmann::json jresponse {
1898 {"index", std::stoi(keyChunk->GetId())},
1899 {"Key_buffer", keyChunk->GetKeyString()}
1900 };
1901 //No Metadata
1902 std::string msg = jresponse.dump();
1903
1904 //create packet
1905 HTTPMessage httpMessage;
1906 httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok, msg, {
1907 {"Content-Type", "application/json; charset=utf-8"},
1908 {"Request URI", headerIn.GetUri() }
1909 });
1910 std::string hMessage = httpMessage.ToString();
1911 Ptr<Packet> packet = Create<Packet>(
1912 (uint8_t*)(hMessage).c_str(),
1913 hMessage.size()
1914 );
1915 NS_ASSERT(packet);
1916 SendToSocketPair(socket, packet);
1917
1918 m_keyServedTrace(it->second.srcSaeId, keyChunk->GetId(), keyChunk->GetSizeInBits()); //trace served key material etsi 004
1919 m_keyConsumedLink( //Is always p2p link now for 004
1920 it->second.srcNodeId, //Source
1921 it->second.dstNodeId, //Destination
1922 //{ksid + keyChunk->GetId()}, //Key ID should be combination of ksid+index!
1923 keyChunk->GetSizeInBits() //Size of key
1924 );
1925
1926 }else{
1927 //Respond with an error. Currently this is the only error on GetKey004, therefore no message is included. @toDo
1928 NS_LOG_FUNCTION(this << "No keys available in the association buffer. Responding on the request ...");
1929
1930 auto itSchedule = m_scheduledChecks.find(ksid);
1931 if(itSchedule!=m_scheduledChecks.end())
1932 {
1933 NS_LOG_FUNCTION(this << "The CheckEtsi004Association for ksid ("<< ksid << ") is already scheduled!");
1934 }else{
1935 CheckEtsi004Association(ksid);
1936 }
1937
1938 //create packet
1939 HTTPMessage httpMessage;
1940 httpMessage.CreateResponse(HTTPMessage::HttpStatus::BadRequest, "", {
1941 {"Request URI", headerIn.GetUri() }
1942 });
1943 std::string hMessage = httpMessage.ToString();
1944 Ptr<Packet> packet = Create<Packet>(
1945 (uint8_t*)(hMessage).c_str(),
1946 hMessage.size()
1947 );
1948 NS_ASSERT(packet);
1949
1950 SendToSocketPair(socket, packet);
1951 }
1952
1953}
1954
1955void
1956QKDKeyManagerSystemApplication::ProcessCloseRequest(std::string ksid, HTTPMessage headerIn, Ptr<Socket> socket)
1957{
1958 NS_LOG_FUNCTION( this << "Processing CLOSE request ... " << ksid );
1959 auto it = m_associations004.find(ksid);
1960 if(it == m_associations004.end()){
1961 NS_LOG_DEBUG( this << "Key stream association identified with " << ksid << "does not exists!" );
1962 return;
1963 }
1964
1965 HttpQuery query;
1966 query.method_type = ETSI_QKD_004_KMS_CLOSE; //Close made to peer KMS
1967 query.ksid = ksid; //Remember ksid
1968 if(it->second.stre_buffer->GetStreamKeyCount()){
1969 query.surplus_key_ID = GenerateUUID(); //Generate keyId to empty key stream association
1970 query.sync_index = it->second.stre_buffer->GetNextIndex(); //Take the first index in the buffer!
1971 }
1972
1973 NS_LOG_FUNCTION( this << "Releasing key stream association buffer. Synchronizing with peer KMS ..." );
1974 CheckSocketsKMS((it->second).dstKmsAddr ); //Check connection to peer KMS!
1975 Ptr<Socket> sendSocket = GetSendSocketKMS((it->second).dstKmsAddr );
1976 NS_ASSERT(sendSocket);
1977
1978 nlohmann::json msgBody;
1979 if(!query.surplus_key_ID.empty()){
1980 msgBody["surplus_key_ID"] = query.surplus_key_ID;
1981 msgBody["sync_index"] = query.sync_index;
1982 }
1983 std::string msg = msgBody.dump();
1984
1985 std::string headerUri = "http://" + GetAddressString((it->second).dstKmsAddr); //Uri starts with destination KMS address
1986 headerUri += "/api/v1/associations/close_kms/" + ksid;
1987
1988 //Create packet
1989 HTTPMessage httpMessage;
1990 httpMessage.CreateRequest(headerUri, "POST", msg);
1991 std::string hMessage = httpMessage.ToString();
1992 Ptr<Packet> packet = Create<Packet>(
1993 (uint8_t*)(hMessage).c_str(),
1994 hMessage.size()
1995 );
1996 NS_ASSERT(packet);
1997
1998 HttpKMSAddQuery((it->second).dstKmsAddr, query); //Save this query made to the peer KMS!
1999
2000 sendSocket->Send(packet);
2001 NS_LOG_FUNCTION( this << "Synchronization information for releasing key stream association sent to peer KMS"
2002 << packet->GetUid() << packet->GetSize() );
2003
2004}
2005
2006
2008QKDKeyManagerSystemApplication::CreateRelaySBuffer(uint32_t srcNodeId, uint32_t dstNodeId, std::string description)
2009{
2010 NS_LOG_FUNCTION(this << srcNodeId << dstNodeId << description);
2011
2012 Ptr<SBuffer> sBuffer = GetController()->CreateRSBuffer(dstNodeId); //QKDNController Create new S-Buffer
2013 sBuffer->SetType(SBuffer::Type::RELAY_SBUFFER);
2014 sBuffer->Initialize();
2015 sBuffer->SetDescription (description);
2016 sBuffer->SetIndex( m_qbuffersVector.size() );
2017
2018 m_qbuffersVector.push_back(sBuffer);
2019 m_qbuffers.insert(std::make_pair(dstNodeId, sBuffer) );
2020
2022 uint32_t applicationIndex = 0;
2023 for(uint32_t i = 0; i < GetNode()->GetNApplications(); ++i)
2024 {
2025 kms = GetNode()->GetApplication(i)->GetObject <QKDKeyManagerSystemApplication>();
2026 applicationIndex = i;
2027 if(kms) break;
2028 }
2029 sBuffer->SetSrcKMSApplicationIndex(applicationIndex);
2030
2031 //CREATE QKD GRAPH
2032 QKDGraphManager *QKDGraphManager = QKDGraphManager::getInstance();
2033 std::string graphTitle = "SBUFFER (RELAY): " + std::to_string(srcNodeId) + " - " + std::to_string(dstNodeId);
2034 Ptr<Node> dstNode = NodeList::GetNode(dstNodeId);
2036 GetNode(),
2037 dstNode,
2038 sBuffer->GetIndex(),
2039 sBuffer->GetSrcKMSApplicationIndex(),
2040 graphTitle,
2041 "png",
2042 sBuffer
2043 );
2044
2045
2046 return sBuffer;
2047}
2048
2049/**
2050 * ********************************************************************************************
2051
2052 * KMS-KMS functions
2053
2054 * ********************************************************************************************
2055 */
2056
2057void
2058QKDKeyManagerSystemApplication::ProcessRelayRequest(HTTPMessage headerIn, Ptr<Socket> socket)
2059{
2060 NS_LOG_FUNCTION(this << headerIn.GetUri());
2061 std::vector<std::string> uriParams {ReadUri(headerIn.GetUri())};
2062 std::string reqId = uriParams[6];
2063 NS_LOG_FUNCTION(this << reqId);
2064
2065 std::string payload = headerIn.GetMessageBodyString();
2066 nlohmann::json jRelayPayload;
2067 try{
2068 jRelayPayload = nlohmann::json::parse(payload);
2069 }catch(...){
2070 NS_FATAL_ERROR( this << "JSON parse error!" );
2071 }
2072
2073 uint32_t srcNodeId {0}, dstNodeId {0};
2074 if(jRelayPayload.contains("source_node_id"))
2075 srcNodeId = jRelayPayload["source_node_id"];
2076 if(jRelayPayload.contains("destination_node_id"))
2077 dstNodeId = jRelayPayload["destination_node_id"];
2078 NS_ASSERT(srcNodeId && dstNodeId);
2079 NS_LOG_FUNCTION(this << srcNodeId << GetNode()->GetId() << dstNodeId);
2080
2081 bool terminateRelay {false};
2082 std::vector<std::string> keyIds {}, keys {};
2083 if(!jRelayPayload.contains("repeater_node_id"))
2084 {
2085 NS_LOG_FUNCTION(this << "Is this first node in path?");
2086 Ptr<SBuffer> sBuffer = GetSBuffer(srcNodeId, "dec"); //Get decryption buffer!
2087 NS_ASSERT(sBuffer);
2088 std::string keyId;
2089 for(nlohmann::json::iterator it = jRelayPayload["keys"].begin(); it != jRelayPayload["keys"].end(); ++it)
2090 {
2091 //Ptr<QKDKey> key = sBuffer->QBuffer::GetKey((it.value())["key_ID"] );
2092 keyId = (it.value())["key_ID"];
2093 Ptr<QKDKey> key = sBuffer->GetKey(keyId);
2094 //First error: no keys to relay on first hop(not normal case)
2095 if(!key){
2096 NS_LOG_FUNCTION(this << "Relay key with ID" <<(it.value())["key_ID"] << "not found! Relay is terminated!");
2097 terminateRelay = true;
2098 continue;
2099 //continue to spent same key material(easy version)
2100 //(harder: first hop can move keys back to S-Buffer, and same will be done at source!)
2101 }
2102 NS_LOG_FUNCTION(this << "\nFirstNode -> Relay key -> ID: " << key->GetId()
2103 << "\nFirstNode -> Relay key -> key: " << key->GetKeyString());
2104 keyIds.push_back(key->GetId());
2105 keys.push_back(key->GetKeyString());
2106 }
2107
2108 if(GetNode()->GetId() > srcNodeId)//this is master KMS
2109 SBufferClientCheck(srcNodeId); //run sbuffer client check for LOCAL Sbuffer
2110
2111 }else{ //Read {KeyId, eKey, eKeyId}, decrypt eKey!
2112
2113 NS_LOG_FUNCTION(this << "Read {KeyId, eKey, eKeyId}, decrypt eKey!");
2114
2115 uint32_t previousNodeId = jRelayPayload["repeater_node_id"];
2116 std::vector<std::string> ekeys {}, ekeyIds {};
2117 Ptr<SBuffer> decBuffer = GetSBuffer(previousNodeId, "dec");
2118 NS_ASSERT(decBuffer);
2119 Ptr<QKDEncryptor> decryptor = CreateObject<QKDEncryptor>();
2120 std::string keyId;
2121 for(nlohmann::json::iterator it = jRelayPayload["keys"].begin(); it != jRelayPayload["keys"].end(); ++it)
2122 {
2123 ekeys.push_back((it.value())["ekey"] );
2124 ekeyIds.push_back((it.value())["ekey_ID"] );
2125 keyIds.push_back((it.value())["key_ID"] );
2126 //Get ekey_ID
2127 //Ptr<QKDKey> key = decBuffer->QBuffer::GetKey((it.value())["ekey_ID"] );
2128 keyId = (it.value())["ekey_ID"];
2129 Ptr<QKDKey> key = decBuffer->GetKey(keyId);
2130 if(!key){
2131 //Second error: no keys to decrypt relay keys(not normal case)
2132 NS_LOG_FUNCTION(this << "Decryption key with ID" <<(it.value())["ekey_ID"] << "is not found! Relay is terminated!");
2133 terminateRelay = true;
2134 }
2135 keys.push_back( decryptor->COTP(key->GetKeyString(),(it.value())["ekey"]) );
2136 }
2137
2138 if(GetNode()->GetId() > previousNodeId) //this is master KMS
2139 SBufferClientCheck(previousNodeId); //run sbuffer client check for LOCAL Sbuffer
2140 }
2141
2142 //If it is relay node encrypt keys to next Hop
2143 if(GetNode()->GetId() != dstNodeId && !terminateRelay)//
2144 {
2145 NS_LOG_FUNCTION(this << "Forwarding relay");
2146 QKDLocationRegisterEntry conn = GetController()->GetRoute(dstNodeId);
2147 Ptr<SBuffer> encBuffer = GetSBuffer(conn.GetNextHop(), "enc");
2148 NS_ASSERT(encBuffer);
2149
2150 uint32_t availableKeysCount = encBuffer->GetDefaultKeyCount(keyIds.size());
2151 //Third error: no keys to forward relay!(common case -> should be tested before obtaining actual keys!)
2152 //Check the availability of keys at forwarding QKD link!
2153 NS_LOG_FUNCTION(this << "zzz:" << availableKeysCount << keyIds.size() );
2154 if(encBuffer->GetDefaultKeyCount(keyIds.size()) != keyIds.size())
2155 {
2156 terminateRelay = true;
2157 uint32_t previousNodeId;
2158 if(jRelayPayload.contains("repeater_node_id")){ //Is this first node in path?
2159 previousNodeId = jRelayPayload["repeater_node_id"];
2160 }else{
2161 if(jRelayPayload.contains("source_node_id"))
2162 previousNodeId = jRelayPayload["source_node_id"];
2163 }
2164 NS_LOG_FUNCTION(this << previousNodeId);
2165 //Onda je dovoljno pratiti waste na source node kao vezu source-this node
2166 //m_keyWasteRelay( previousNodeId, GetNode()->GetId(), keyIds.size()*encBuffer->GetKeySize() );
2167
2168 NS_LOG_FUNCTION(this << "Relay Failed!");
2169 //Respond with error! Include Node ID in response!
2170 nlohmann::json jrelayResponse{ {"node-id", GetNode()->GetId()} };
2171 std::string msg = jrelayResponse.dump();
2172 //create packet
2173 HTTPMessage httpMessage;
2174 httpMessage.CreateResponse(HTTPMessage::HttpStatus::BadRequest, msg, {
2175 {"Request URI", headerIn.GetUri() }
2176 });
2177 std::string hMessage = httpMessage.ToString();
2178 Ptr<Packet> packet = Create<Packet>(
2179 (uint8_t*)(hMessage).c_str(),
2180 hMessage.size()
2181 );
2182 NS_ASSERT(packet);
2183
2184 NS_LOG_FUNCTION(this << "Sending response" << packet->GetUid() << packet->GetSize() );
2185 Ipv4Address peerAddress = GetPeerKmAddress(previousNodeId);
2186 //Ipv4Address peerAddress = GetController()->GetRoute(previousNodeId).GetNextHopAddress();
2187 Ptr<Socket> sendSocket = GetSendSocketKMS(peerAddress);
2188 sendSocket->Send(packet);
2189
2190 return;
2191
2192 }
2193
2194 Ptr<QKDEncryptor> encryptor = CreateObject<QKDEncryptor>(); //Get Encryptor to relay keys to destination
2195 NS_ASSERT(encryptor);
2196
2197 nlohmann::json jRelay;
2198
2199 uint32_t encDefaultKeySize = encBuffer->GetKeySize();
2200 for(uint32_t i = 0; i < keyIds.size(); i++)
2201 {
2202 NS_LOG_FUNCTION(this << i << keyIds.size() << encDefaultKeySize);
2203 Ptr<QKDKey> encKey = encBuffer->GetKey(encDefaultKeySize); //Get key with default key size!
2204 if(encKey){
2205 NS_LOG_FUNCTION(this << "\nMiddleNode -> Relay key -> eKeyId" << encKey->GetId()
2206 << "\nMiddleNode -> Relay key -> keyId" << keyIds[i]);
2207 std::string encryptedKey = encryptor->COTP(encKey->GetKeyString(), keys[i]); //key, input
2208 NS_LOG_FUNCTION(this << "\nMiddleNode -> Relay key -> ekey" << encryptedKey);
2209 jRelay["keys"].push_back({ {"key_ID", keyIds[i]}, {"ekey_ID", encKey->GetId()}, {"ekey", encryptedKey} });
2210 m_keyConsumedRelay(
2211 GetNode()->GetId(),
2212 GetNode()->GetId(),
2213 conn.GetNextHop(),
2214 encKey->GetSizeInBits()
2215 );
2216 }
2217 }
2218 if(GetNode()->GetId() > conn.GetNextHop()) //this is master KMS
2219 SBufferClientCheck(conn.GetNextHop()); //run sbuffer client check for LOCAL Sbuffer
2220 jRelay["source_node_id"] = srcNodeId;
2221 jRelay["destination_node_id"] = dstNodeId;
2222 jRelay["repeater_node_id"] = GetNode()->GetId();
2223
2224 //m_keyConsumedRelay( GetNode()->GetId(), GetNode()->GetId(), conn.GetNextHop(), keyIds.size()*encBuffer->GetKeySize() );
2225
2226 Ipv4Address nextHopAddress = GetPeerKmAddress(conn.GetNextHop());
2227 std::string headerUri = "http://" + GetAddressString(nextHopAddress);
2228 headerUri += "/api/v1/keys/relay/?req_id=/" + reqId;
2229 std::string msg = jRelay.dump();
2230
2231 //Create packet
2232 HTTPMessage httpMessage;
2233 httpMessage.CreateRequest(headerUri, "POST", msg);
2234 std::string hMessage = httpMessage.ToString();
2235 Ptr<Packet> packet = Create<Packet>(
2236 (uint8_t*)(hMessage).c_str(),
2237 hMessage.size()
2238 );
2239 NS_ASSERT(packet);
2240
2241 CheckSocketsKMS( nextHopAddress ); //Check connection to peer KMS!
2242 Ptr<Socket> sendSocket = GetSendSocketKMS( nextHopAddress );
2243
2244 HttpQuery query;
2245 query.method_type = RELAY_KEYS; //Relay
2246 query.req_id = reqId;
2247 query.peerNodeId = conn.GetNextHop(); //Peer -- next hop
2248 if(jRelayPayload.contains("repeater_node_id"))
2249 query.prev_hop_id = jRelayPayload["repeater_node_id"];
2250 else
2251 query.prev_hop_id = srcNodeId;
2252 query.request_uri = headerIn.GetUri();
2253 HttpProxyRequestAdd(query);
2254
2255 sendSocket->Send(packet);
2256 NS_LOG_FUNCTION(this << "Packet sent" << conn.GetNextHop()
2257 << packet->GetUid() << packet->GetSize());
2258
2259 }else if(!terminateRelay)
2260 {
2261 //Destination reached
2262 NS_LOG_FUNCTION(this << "Destination reached!");
2263 NS_LOG_FUNCTION(this << "srcNodeId:" << srcNodeId);
2264 Ptr<SBuffer> sBuffer = GetSBuffer(srcNodeId, "dec");
2265 if(!sBuffer)
2266 {
2267 NS_LOG_FUNCTION(this << "The S-Buffer does not exists! This is new virtual connection!");
2268 uint32_t dstNodeId = GetNode()->GetId();
2269 sBuffer = CreateRelaySBuffer(dstNodeId, srcNodeId, "(RELAY)");
2270 m_keys_enc.insert(std::make_pair(srcNodeId, sBuffer)); //Store a pointer to new sBuffer
2271 m_keys_dec.insert(std::make_pair(srcNodeId, sBuffer)); //Store a pointer to new sBuffer
2272 }
2273 NS_ASSERT(sBuffer);
2274 NS_LOG_FUNCTION(this << keyIds.size() << keys.size());
2275 for(uint32_t i = 0; i < keyIds.size(); i++){ //Add keys to RELAY_SBUFFER -- "dec"
2276 Ptr<QKDKey> key = CreateObject<QKDKey>(keyIds[i], keys[i]);
2277 NS_LOG_FUNCTION(this << "relay key added" << keyIds[i]);
2278 sBuffer->StoreKey(key, true);
2279 }
2280 //@toDo Response to prev_hop
2281
2282 //create packet
2283 HTTPMessage httpMessage;
2284 httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok, "", {
2285 {"Content-Type", "application/json; charset=utf-8"},
2286 {"Request URI", headerIn.GetUri() }
2287 });
2288 std::string hMessage = httpMessage.ToString();
2289 Ptr<Packet> packet = Create<Packet>(
2290 (uint8_t*)(hMessage).c_str(),
2291 hMessage.size()
2292 );
2293 NS_ASSERT(packet);
2294
2295 uint32_t previousNodeId = jRelayPayload["repeater_node_id"]; //It has this field for sure!!!
2296 Ipv4Address peerAddress = GetPeerKmAddress(previousNodeId);
2297
2298 NS_LOG_FUNCTION( this
2299 << "Sending response"
2300 << headerIn.GetUri()
2301 << packet->GetUid()
2302 << packet->GetSize()
2303 << "previousNodeId:"
2304 << previousNodeId
2305 << "peerAddress:"
2306 << peerAddress
2307 << hMessage
2308 );
2309
2310 //Ipv4Address peerAddress = GetController()->GetRoute(previousNodeId).GetNextHopAddress();
2311 Ptr<Socket> sendSocket = GetSendSocketKMS(peerAddress);
2312 NS_ASSERT(sendSocket);
2313 uint32_t outcome = sendSocket->Send(packet);
2314 NS_LOG_INFO(this << "outcome of sending packet:" << outcome);
2315
2316 }
2317
2318}
2319
2320void
2321QKDKeyManagerSystemApplication::ProcessRelayResponse(HTTPMessage headerIn)
2322{
2323
2324 std::vector<std::string> uriParams = ReadUri(headerIn.GetRequestUri());
2325 std::string payload = headerIn.GetMessageBodyString();
2326 std::string reqId = uriParams[6];
2327 Ipv4Address from = uriParams[0].c_str();
2328 NS_LOG_FUNCTION(this << reqId << from);
2329
2330 HttpQuery sQuery = GetProxyQuery(reqId); //Find query!
2331 uint32_t prevHop = sQuery.prev_hop_id; //Get previous node
2332
2333 if(prevHop != GetNode()->GetId()){
2334 //create packet
2335 HTTPMessage httpMessage;
2336 httpMessage.CreateResponse(headerIn.GetStatus(), payload, {
2337 {"Content-Type", "application/json; charset=utf-8"},
2338 {"Request URI", sQuery.request_uri }
2339 });
2340 std::string hMessage = httpMessage.ToString();
2341 Ptr<Packet> packet = Create<Packet>(
2342 (uint8_t*)(hMessage).c_str(),
2343 hMessage.size()
2344 );
2345 NS_ASSERT(packet);
2346
2347
2348 //PrevHopAddress? for now we take it from routing table! if routing is changed it will not work!
2349 Ipv4Address peerAddress = GetPeerKmAddress(prevHop);
2350 //Ipv4Address peerAddress = GetController()->GetRoute(prevHop).GetNextHopAddress();
2351 CheckSocketsKMS(peerAddress);
2352 Ptr<Socket> sendSocket = GetSendSocketKMS(peerAddress);
2353 NS_ASSERT(sendSocket);
2354
2355 NS_LOG_FUNCTION( this << "Forwarding response" << packet->GetUid() << packet->GetSize() );
2356 sendSocket->Send(packet);
2357
2358 }else{
2359
2360 //Response have reached the source
2361 NS_LOG_FUNCTION(this << "Response have reached the source!" << headerIn.GetStatus());
2362 Ptr<SBuffer> relayBuffer = GetSBuffer(sQuery.peerNodeId, "enc");
2363 NS_ASSERT(relayBuffer);
2364 std::vector<std::string> keyIds = sQuery.keyIds;
2365 bool fail {headerIn.GetStatus() != HTTPMessage::HttpStatus::Ok};
2366 for(const auto& keyId : keyIds){
2367 if(headerIn.GetStatus() == HTTPMessage::HttpStatus::Ok)
2368 relayBuffer->MarkKey(keyId, QKDKey::READY);
2369 else{
2370 /*nlohmann::json jrelayResponse;
2371 try{
2372 jrelayResponse = nlohmann::json::parse(payload);
2373 }catch(...){
2374 NS_FATAL_ERROR(this << "JSON parse error!");
2375 }
2376 uint32_t dstNodeFail;
2377 if(jrelayResponse.contains("node-id"))
2378 dstNodeFail = jrelayResponse["node-id"];
2379 else
2380 NS_LOG_ERROR(this << "Response is missing mandatory 'node-id' value!");
2381 m_keyWasteRelay(GetNode()->GetId(), dstNodeFail, relayBuffer->GetKeySize());*/
2382 relayBuffer->MarkKey(keyId, QKDKey::OBSOLETE);
2383 }
2384 }
2385 relayBuffer->SetRelayState(false);
2386 NS_LOG_FUNCTION(this << "\nAmount of key material in RELAY s-buffer (READY): " << relayBuffer->GetSBitCount());
2387 if(fail){
2388 //SBufferClientCheck(sQuery.peerNodeId);
2389 NS_LOG_FUNCTION(this << "relay fail");
2390 }
2391
2392 }
2393
2394 RemoveProxyQuery(reqId);
2395}
2396
2397void
2398QKDKeyManagerSystemApplication::NewAppRequest(std::string ksid)
2399{
2400 NS_LOG_FUNCTION(this << ksid);
2401 auto it = m_associations004.find(ksid);
2402 if(it == m_associations004.end()){
2403 NS_LOG_DEBUG( this << "Key stream association identified with " << ksid << "does not exists!" );
2404 return;
2405 }
2406
2407 CheckSocketsKMS((it->second).dstKmsAddr ); //Check connection to peer KMS!
2408 Ptr<Socket> sendSocket = GetSendSocketKMS((it->second).dstKmsAddr );
2409 NS_ASSERT(sendSocket);
2410
2411 nlohmann::json msgBody = {
2412 {"Source",(it->second).srcSaeId},
2413 {"Destination",(it->second).dstSaeId},
2414 {"QoS", {
2415 {"Key_chunk_size",(it->second).qos.chunkSize}
2416 }},
2417 {"Key_stream_ID", ksid}
2418 };
2419 std::string msg = msgBody.dump();
2420
2421 std::ostringstream peerkmsAddressTemp;
2422 (it->second).dstKmsAddr.Print(peerkmsAddressTemp); //IPv4Address to string
2423 std::string headerUri = "http://" + peerkmsAddressTemp.str(); //Uri starts with destination KMS address
2424 headerUri += "/api/v1/associations/new_app";
2425
2426 //Create packet
2427 HTTPMessage httpMessage;
2428 httpMessage.CreateRequest(headerUri, "POST", msg);
2429 std::string hMessage = httpMessage.ToString();
2430 Ptr<Packet> packet = Create<Packet>(
2431 (uint8_t*)(hMessage).c_str(),
2432 hMessage.size()
2433 );
2434 NS_ASSERT(packet);
2435
2436 HttpQuery query;
2437 query.method_type = RequestType::NEW_APP;
2438 query.source_sae =(it->second).srcSaeId;
2439 query.destination_sae =(it->second).dstSaeId;
2440 query.ksid = ksid;
2441 HttpKMSAddQuery((it->second).dstKmsAddr, query);
2442
2443 sendSocket->Send(packet);
2444 NS_LOG_FUNCTION( this << "NEW_APP: KMS informs peer KMS on new association established!" );
2445}
2446
2447void
2448QKDKeyManagerSystemApplication::ProcessNewAppRequest(HTTPMessage headerIn, Ptr<Socket> socket)
2449{
2450 NS_LOG_FUNCTION(this << "Processing NEW_APP request!");
2451 std::string payload = headerIn.GetMessageBodyString();
2452 nlohmann::json jNewAppRequest;
2453 try{
2454 jNewAppRequest = nlohmann::json::parse(payload);
2455 }catch(...){
2456 NS_FATAL_ERROR( this << "JSON parse error!" );
2457 }
2458
2459 //uint32_t srcSaeId = -1, dstSaeId = -1;
2460 std::string srcSaeId, dstSaeId;
2462 std::string ksid;
2463 if(jNewAppRequest.contains("Destination"))
2464 dstSaeId = jNewAppRequest["Destination"];
2465 if(jNewAppRequest.contains("Source"))
2466 srcSaeId = jNewAppRequest["Source"];
2467 if(jNewAppRequest.contains("Key_stream_ID"))
2468 ksid = jNewAppRequest["Key_stream_ID"];
2469 ReadJsonQos(inQoS, jNewAppRequest);
2470 NS_ASSERT(!srcSaeId.empty() || !dstSaeId.empty() || !ksid.empty());
2471
2472 bool qosAgreed {true}; //Check if the QoS can be met! @toDo
2473 if(qosAgreed){
2474 CreateKeyStreamSession(dstSaeId, srcSaeId, inQoS, ksid);
2475 /* Send positive response on the NEW_APP request! In case where
2476 it is not point-to-point conncetion between the source and the destination
2477 msg will carry destination_kms address. @toDoR */
2478
2479 //create packet
2480 HTTPMessage httpMessage;
2481 httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok, "", {
2482 {"Content-Type", "application/json; charset=utf-8"},
2483 {"Request URI", headerIn.GetUri() }
2484 });
2485 std::string hMessage = httpMessage.ToString();
2486 Ptr<Packet> packet = Create<Packet>(
2487 (uint8_t*)(hMessage).c_str(),
2488 hMessage.size()
2489 );
2490 NS_ASSERT(packet);
2491
2492 NS_LOG_FUNCTION( this << "NEW_APP request accepted. Association created." );
2493
2494 auto it = m_associations004.find(ksid);
2495 if(it == m_associations004.end())
2496 NS_FATAL_ERROR(this);
2497
2498 Ipv4Address dstKms =(it->second).dstKmsAddr; //Read destination KMS address from the association entry
2499 CheckSocketsKMS( dstKms ); //Check connection to dstKms
2500 Ptr<Socket> sendSocket = GetSendSocketKMS( dstKms ); //Obtain send socket object to reach dstKms
2501 NS_ASSERT(sendSocket);
2502 sendSocket->Send(packet);
2503
2504 }else{
2505 NS_LOG_ERROR(this << "QoS requirements can not be satisfied");
2506 return;
2507 }
2508
2509}
2510
2511void
2512QKDKeyManagerSystemApplication::ProcessNewAppResponse(HTTPMessage headerIn, Ptr<Socket> socket)
2513{
2514 NS_LOG_FUNCTION( this << "Processing NEW_APP response" );
2515 std::vector<std::string> uriParams = ReadUri(headerIn.GetRequestUri());
2516 Ipv4Address dstKms = uriParams[0].c_str();
2517 NS_LOG_FUNCTION(this << dstKms);
2518 auto it = m_httpRequestsQueryKMS.find(dstKms);
2519 if(it == m_httpRequestsQueryKMS.end() ||(it->second).empty())
2520 NS_FATAL_ERROR( this << "Response cannot be mapped! HttpQuery empty!" );
2521
2522 std::string dstSaeId = it->second[0].destination_sae;
2523 if(headerIn.GetStatus() == 200){ //Status OK
2524 if(GetController()->GetRoute(dstSaeId).GetHop() == 1) //dstKms for point-to-point scenario!
2525 HttpKMSCompleteQuery(dstKms); //Point-to-point scenario. Response just as acknowledgement!
2526 else{//@toDo Trusted relay scenario. QKDApp is waiting for OPEN_CONNECT response!
2527 bool QoS {true}; //Read QoS from response, calculate its own, and make response!
2528 if(QoS){
2529 nlohmann::json jOpenConnectResponse;
2530 jOpenConnectResponse["Key_stream_ID"] = it->second[0].ksid;
2531 std::string msg = jOpenConnectResponse.dump();
2532
2533 //create packet
2534 HTTPMessage httpMessage;
2535 httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok, msg, {
2536 {"Content-Type", "application/json; charset=utf-8"},
2537 {"Request URI", headerIn.GetUri() }
2538 });
2539 std::string hMessage = httpMessage.ToString();
2540 Ptr<Packet> packet = Create<Packet>(
2541 (uint8_t*)(hMessage).c_str(),
2542 hMessage.size()
2543 );
2544 NS_ASSERT(packet);
2545
2546 Ptr<Socket> responseSocket = GetSocketFromHttp004AppQuery(it->second[0].source_sae);
2547 Http004AppQueryComplete(it->second[0].source_sae);
2548 HttpKMSCompleteQuery(dstKms);
2549 CheckSocketsKMS( dstKms ); //Check connection to dstKms
2550 Ptr<Socket> sendSocket = GetSendSocketKMS( dstKms ); //Obtain send socket object to reach dstKms
2551 NS_ASSERT(sendSocket);
2552 sendSocket->Send(packet);
2553 }else{
2554 //Respond to the QKDApp with QoS that can be offered! @toDo Trusted relay scenario
2555 }
2556 }
2557
2558 }else{ //Status indicating error!
2559 std::string ksid = it->second[0].ksid;
2560 if(GetController()->GetRoute(dstSaeId).GetHop() == 1) //dstKms for point-to-point scenario!
2561 HttpKMSCompleteQuery(dstKms); //Point-to-point scenario. Response just as acknowledgement!
2562 else{
2563 //Check the error! @toDo Respond to peer QKDApp in case of Trusted relay scenario!
2564 HttpKMSCompleteQuery(dstKms);
2565 }
2566 auto it = m_associations004.find(ksid);
2567 if(it != m_associations004.end()){
2568 m_associations004.erase(it); //Myb not erase, but for a few seconds mark as closed, and then erase! @toDo
2569 }else{
2570 NS_FATAL_ERROR(this << "Closing non existing association!");
2571 }
2572 }
2573
2574}
2575
2576void
2577QKDKeyManagerSystemApplication::RegisterRequest(std::string ksid)
2578{
2579 NS_LOG_FUNCTION( this << ksid);
2580 auto it = m_associations004.find(ksid); //Find association entry identified with ksid
2581 if(it == m_associations004.end()){
2582 NS_LOG_DEBUG( this << "Key stream association identified with " << ksid << "does not exists!" );
2583 return;
2584 }
2585
2586 Ipv4Address dstKms =(it->second).dstKmsAddr; //Read destination KMS address from the association entry
2587 CheckSocketsKMS( dstKms ); //Check connection to dstKms
2588 Ptr<Socket> sendSocket = GetSendSocketKMS( dstKms ); //Obtain send socket object to reach dstKms
2589 NS_ASSERT(sendSocket);
2590
2591 std::string headerUri = "http://" + GetAddressString(dstKms);
2592 headerUri += "/api/v1/associations/register/" + ksid; //Create an URI for the register request
2593
2594 //Create packet
2595 HTTPMessage httpMessage;
2596 httpMessage.CreateRequest(headerUri, "GET");
2597 std::string hMessage = httpMessage.ToString();
2598 Ptr<Packet> packet = Create<Packet>(
2599 (uint8_t*)(hMessage).c_str(),
2600 hMessage.size()
2601 );
2602 NS_ASSERT(packet);
2603
2604 HttpQuery query;
2605 query.method_type = REGISTER;
2606 query.ksid = ksid;
2607 HttpKMSAddQuery(dstKms, query); //Remember HTTP query to be able to map response later
2608
2609 sendSocket->Send(packet); //Send the packet to dstKms
2610}
2611
2612void
2613QKDKeyManagerSystemApplication::ProcessRegisterRequest( HTTPMessage headerIn , std::string ksid, Ptr<Socket> socket)
2614{
2615 NS_LOG_FUNCTION(this << "Processing register request " << ksid);
2616
2617 auto it = m_associations004.find(ksid); //Find association entry identified with ksid
2618 if(it != m_associations004.end() && ! ((it->second).peerRegistered))
2619 NS_LOG_FUNCTION(this << "Key stream session has been registered!");
2620 else if(it != m_associations004.end() && (it->second).peerRegistered )
2621 NS_LOG_FUNCTION(this << "Key stream session has already been registered!");
2622 else{
2623 NS_LOG_FUNCTION(this << "Key stream association identified with " << ksid << "does not exists!");
2624 return; //@toDo004
2625 }
2626
2627 (it->second).peerRegistered = true; //The peer application is registered if not already
2628
2629 //create packet
2630 HTTPMessage httpMessage;
2631 httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok, "", {
2632 {"Content-Type", "application/json; charset=utf-8"},
2633 {"Request URI", headerIn.GetUri() }
2634 });
2635 std::string hMessage = httpMessage.ToString();
2636 Ptr<Packet> packet = Create<Packet>(
2637 (uint8_t*)(hMessage).c_str(),
2638 hMessage.size()
2639 );
2640 NS_ASSERT(packet);
2641
2642 CheckSocketsKMS( it->second.dstKmsAddr ); //Check connection to peer KMS!
2643 Ptr<Socket> sendSocket = GetSendSocketKMS( it->second.dstKmsAddr );
2644 NS_ASSERT(sendSocket);
2645 sendSocket->Send(packet);
2646
2647 //If master KMS monitor association. If slave do nothing!
2648 if(it->second.srcNodeId > it->second.dstNodeId){
2649 NS_LOG_FUNCTION(this << "MASTER KMS 004!");
2650 CheckEtsi004Association(ksid); //KMS starts monitoring the active association
2651 }
2652}
2653
2654void
2655QKDKeyManagerSystemApplication::ProcessRegisterResponse(HTTPMessage headerIn, Ptr<Socket> socket)
2656{
2657 NS_LOG_FUNCTION( this << "Processing /register response!");
2658 std::vector<std::string> uriParams = ReadUri(headerIn.GetRequestUri());
2659 std::string ksid;
2660 NS_LOG_FUNCTION(this << uriParams[4] << uriParams[5]);
2661 if(uriParams[4] != "register"){
2662 NS_LOG_ERROR(this << "Not a register response! Invalid HTTP mapping!");
2663 return;
2664 }else if(!uriParams[5].empty())
2665 ksid = uriParams[5];
2666
2667 auto it1 = m_associations004.find(ksid);
2668 if(it1 == m_associations004.end()){
2669 NS_LOG_ERROR(this << "Association with given KSID" << ksid << "cannot be found!");
2670 return;
2671 }
2672
2673 Ipv4Address dstKms =(it1->second.dstKmsAddr);
2674 auto it = m_httpRequestsQueryKMS.find(dstKms);
2675 if(it == m_httpRequestsQueryKMS.end() ||(it->second).empty())
2676 NS_FATAL_ERROR( this << "Response cannot be mapped! HttpQuery empty!" );
2677
2678 if(headerIn.GetStatus() == HTTPMessage::HttpStatus::Ok){
2679 NS_LOG_FUNCTION( this << "Successful notification REGISTER" );
2680 if(it1->second.srcNodeId > it1->second.dstNodeId){
2681 NS_LOG_FUNCTION(this << "MASTER KMS 004");
2682 CheckEtsi004Association(ksid);
2683 }
2684 }else{
2685 NS_LOG_FUNCTION( this << "/register error! Releasing established association" << ksid );
2686 if(it1 != m_associations004.end()){
2687 m_associations004.erase(it1); //Myb not erase, but for a few seconds mark as closed, and then erase! @toDo
2688 }else{
2689 NS_FATAL_ERROR(this << "Closing non existing association!");
2690 }
2691 }
2692 HttpKMSCompleteQuery(dstKms);
2693
2694}
2695
2696void
2697QKDKeyManagerSystemApplication::ProcessFillRequest(HTTPMessage headerIn, std::string resource, Ptr<Socket> socket)
2698{
2699 NS_LOG_FUNCTION(this);
2700
2701 std::string payload = headerIn.GetMessageBodyString();
2702 nlohmann::json jFillPayload;
2703 try{
2704 jFillPayload = nlohmann::json::parse(payload);
2705 }catch(...){
2706 NS_FATAL_ERROR( this << "JSON parse error!" );
2707 }
2708
2709 //Read peer KM node ID
2710 uint32_t peerNodeId = 100000;
2711 std::string sBufferType, ksid;
2712 if(jFillPayload.contains("source_node_id"))
2713 peerNodeId = jFillPayload["source_node_id"];
2714 if(jFillPayload.contains("s_buffer_type"))
2715 sBufferType = jFillPayload["s_buffer_type"];
2716
2717 if(sBufferType == "stream"){
2718 if(jFillPayload.contains("ksid"))
2719 ksid = jFillPayload["ksid"];
2720 else
2721 NS_FATAL_ERROR(this << "Mandatory parametar -- ksid -- not received");
2722 }
2723 NS_ASSERT(peerNodeId != 100000);
2724
2725 NS_LOG_FUNCTION(this << "sBufferType:" << sBufferType);
2726
2727 Ptr<QBuffer> qBuffer = GetQBuffer(peerNodeId);
2728 Ptr<SBuffer> sBuffer;
2729 if(sBufferType != "stream")
2730 {
2731 sBuffer = GetSBuffer(peerNodeId, sBufferType);
2732 if(!sBuffer)
2733 {
2734 NS_LOG_FUNCTION(this << "Establishment of relay s-Buffer!");
2735 uint32_t srcNodeId = GetNode()->GetId();
2736 uint32_t dstNodeId = peerNodeId;
2737 sBuffer = CreateRelaySBuffer(srcNodeId, dstNodeId, "(RELAY)");
2738 m_keys_enc.insert(std::make_pair(peerNodeId, sBuffer)); //Store a pointer to new sBuffer
2739 m_keys_dec.insert(std::make_pair(peerNodeId, sBuffer)); //Store a pointer to new sBuffer
2740 }
2741 }else if(sBufferType == "stream"){
2742 auto it = m_associations004.find(ksid);
2743 if(it == m_associations004.end()){
2744 NS_FATAL_ERROR(this << "Unknown ksid" << ksid);
2745 return;
2746 }
2747 sBuffer = it->second.stre_buffer;
2748 }
2749 NS_ASSERT(sBuffer || qBuffer);
2750
2751 //Obtain keys!
2752 bool storeSuccesfull = true;
2753 nlohmann::json resultKeyIds;
2754 for(nlohmann::json::iterator it = jFillPayload["keys"].begin(); it != jFillPayload["keys"].end(); ++it){
2755 Ptr<QKDKey> key = qBuffer->GetKey((it.value())["key_ID"] );
2756 if(key)
2757 {
2758 NS_LOG_FUNCTION(this << key->GetId() << key->GetKeyString());
2759 NS_LOG_FUNCTION(this << "Let's try to save key " << key->GetId() << " in sBuffer: " << sBuffer->GetDescription() );
2760 storeSuccesfull = true;
2761 if(sBufferType != "stream")
2762 {
2763 storeSuccesfull = sBuffer->StoreKey(key, true);
2764 if(!storeSuccesfull)
2765 {
2766 NS_LOG_FUNCTION(this << "Unable to store key " << key->GetId() << " in SBUFFER! Return it back to QBuffer!");
2767 qBuffer->StoreKey(key, true);
2768 }else{
2769 sBuffer->MarkKey( key->GetId(), QKDKey::READY );
2770 }
2771 } else {
2772 sBuffer->InsertKeyToStreamSession(key); //Insert key to stream directly
2773 }
2774 if(storeSuccesfull)
2775 resultKeyIds["keys_accepted"].push_back( { {"key_ID", key->GetId()} } );
2776 else
2777 resultKeyIds["keys_rejected"].push_back( { {"key_ID", key->GetId()} } );
2778 }
2779 }
2780
2781 NS_LOG_FUNCTION(this << "FILL complete, check the state of S-Buffer" << sBuffer->GetSKeyCount());
2782 NS_LOG_FUNCTION(this << "FILL complete, but how many in default size: " << sBuffer->GetDefaultKeyCount() << sBuffer->GetKeySize());
2783
2784 UpdateLinkState(peerNodeId);
2785
2786 HTTPMessage httpMessage;
2787 if(storeSuccesfull)
2788 {
2789 NS_LOG_FUNCTION(this << resultKeyIds.dump());
2790 httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok, resultKeyIds.dump(), {
2791 {"Content-Type", "application/json; charset=utf-8"},
2792 {"Request URI", headerIn.GetUri() }
2793 });
2794 }else{
2795 httpMessage.CreateResponse(HTTPMessage::HttpStatus::NotAcceptable, resultKeyIds.dump(), {
2796 {"Content-Type", "application/json; charset=utf-8"},
2797 {"Request URI", headerIn.GetUri() }
2798 });
2799 }
2800 std::string hMessage = httpMessage.ToString();
2801 Ptr<Packet> packet = Create<Packet>(
2802 (uint8_t*)(hMessage).c_str(),
2803 hMessage.size()
2804 );
2805 NS_ASSERT(packet);
2806
2807 NS_LOG_FUNCTION( this << "Sending response" << packet->GetUid() << packet->GetSize() << hMessage );
2808 //Ipv4Address peerKMAddress = GetController()->GetRoute(peerNodeId).GetNextHopAddress();
2809 Ipv4Address peerKMAddress = GetPeerKmAddress(peerNodeId);
2810 CheckSocketsKMS(peerKMAddress);
2811 Ptr<Socket> sendSocket = GetSendSocketKMS(peerKMAddress);
2812 NS_ASSERT(sendSocket);
2813 sendSocket->Send(packet);
2814}
2815
2816void
2817QKDKeyManagerSystemApplication::ProcessFillResponse(HTTPMessage headerIn, Ipv4Address from)
2818{
2819 NS_LOG_FUNCTION(this << headerIn.GetRequestUri());
2820
2821 //Ipv4Address peerAddress = GetDestinationKmsAddress(socket);
2822 Ipv4Address dstKms { ReadUri(headerIn.GetRequestUri())[0].c_str() };
2823 auto it = m_httpRequestsQueryKMS.find(dstKms);
2824 for(;;){
2825 if(it == m_httpRequestsQueryKMS.end() ||(it->second).empty())
2826 NS_FATAL_ERROR( this << "Response cannot be mapped! HttpQuery empty!" );
2827 if(it->second[0].method_type != FILL){
2828 NS_LOG_ERROR(this << "invalid mapping");
2829 HttpKMSCompleteQuery(dstKms);
2830 }else
2831 break;
2832 NS_LOG_FUNCTION(this << it->second[0].method_type << it->second[0].sBuffer);
2833 }
2834
2835 if(headerIn.GetStatus() == HTTPMessage::HttpStatus::Ok)
2836 { //ACK message
2837 NS_LOG_FUNCTION(this << "We received HTTP OK(ack)!");
2838 }else{
2839 NS_LOG_ERROR(this << " *** Unexpected error received! *** ");
2840 }
2841
2842 std::string payload { headerIn.GetMessageBodyString() };
2843 nlohmann::json resultKeyIds;
2844 try{
2845 resultKeyIds = nlohmann::json::parse(payload);
2846 }catch(...){
2847 NS_FATAL_ERROR(this << "json parse error");
2848 }
2849
2850 uint32_t peerNodeId =(it->second)[0].peerNodeId;
2851 Ptr<QBuffer> qBuffer = GetQBuffer(peerNodeId);
2852 std::string sBufferType =(it->second)[0].sBuffer;
2853 Ptr<SBuffer> sBuffer;
2854 if(sBufferType == "enc" || sBufferType == "dec"){
2855 sBuffer = GetSBuffer(peerNodeId, sBufferType);
2856 NS_ASSERT(sBuffer);
2857 }else{ //Find stream buffer
2858 auto it {m_associations004.find(sBufferType)};
2859 if(it == m_associations004.end())
2860 NS_FATAL_ERROR(this << "unknwon ksid" << sBufferType);
2861 else
2862 sBuffer = it->second.stre_buffer;
2863 }
2864 std::vector<std::string> keyIds =(it->second)[0].keyIds;
2865
2866 NS_LOG_FUNCTION(this << "First take all ACCEPTED keys from response. Mark them ready. Remove them from local keyIds!");
2867 for(nlohmann::json::iterator it = resultKeyIds["keys_accepted"].begin(); it != resultKeyIds["keys_accepted"].end(); ++it)
2868 {
2869 std::string keyId {(it.value())["key_ID"]};
2870 auto a { std::find( keyIds.begin(), keyIds.end(), keyId ) };
2871 if(a != keyIds.end())
2872 keyIds.erase(a);
2873 else
2874 NS_FATAL_ERROR(this << "unknown key " <<(it.value())["key_ID"]);
2875
2876 if(sBufferType == "enc" || sBufferType == "dec"){
2877 sBuffer->MarkKey( keyId, QKDKey::READY );
2878 } else {
2879 //association move keys from its store to stream
2880 //Ptr<QKDKey> key { sBuffer->QBuffer::GetKey(keyId) }; //This will remove key from store!
2881 Ptr<QKDKey> key { sBuffer->GetKey(keyId, false) }; //This will remove key from store!
2882 if(key)
2883 {
2884 key->SwitchToState( QKDKey::READY );
2885 sBuffer->InsertKeyToStreamSession(key);
2886 } else{
2887 NS_FATAL_ERROR(this << "unknown key " << keyId);
2888 }
2889 }
2890 }
2891
2892 //CHECK rejected keyIds
2893 NS_LOG_FUNCTION(this << "Now check REJECTED keys from response. Return them to QBuffer!");
2894 for(nlohmann::json::iterator it = resultKeyIds["keys_rejected"].begin(); it != resultKeyIds["keys_rejected"].end(); ++it)
2895 {
2896 std::string keyId {(it.value())["key_ID"]};
2897 auto a { std::find( keyIds.begin(), keyIds.end(), keyId ) };
2898 if(a != keyIds.end())
2899 keyIds.erase(a);
2900 else
2901 NS_FATAL_ERROR(this << "unknown key " <<(it.value())["key_ID"]);
2902
2903 NS_LOG_FUNCTION(this << "Return key " << keyId << " to QBuffer!");
2904 Ptr<QKDKey> key = sBuffer->GetKey( keyId, false);
2905 key->SwitchToState( QKDKey::READY );
2906 qBuffer->StoreKey(key, false);
2907 }
2908
2909 NS_LOG_FUNCTION(this << "FILL complete, check the state of S-Buffer: " << sBuffer->GetSKeyCount());
2910
2911 UpdateLinkState(peerNodeId);
2912 //Then remaining keys in keyIds should be marked obsolute! This will remove them from store!
2913 NS_LOG_FUNCTION(this << "rejected keys " << keyIds.size() << keyIds);
2914 for(const auto& el: keyIds)
2915 sBuffer->MarkKey(el, QKDKey::OBSOLETE); //This will remove key from store!
2916
2917
2918
2919 HttpKMSCompleteQuery(dstKms);
2920}
2921
2922void
2923QKDKeyManagerSystemApplication::ProcessSKeyCreateRequest(HTTPMessage headerIn, Ptr<Socket> socket)
2924{
2925 NS_LOG_FUNCTION( this << socket );
2926 std::string payload = headerIn.GetMessageBodyString();
2927 nlohmann::json jPayload;
2928 try {
2929 jPayload = nlohmann::json::parse(payload);
2930 } catch(...) {
2931 NS_FATAL_ERROR( this << "JSON parse error!" );
2932 }
2933 //Read JSON parameters
2934 uint32_t keySize {0}, keyNumber {0};
2935 std::vector<std::string> candidateSetIds {}, supplyKeyIds {};
2936 std::string surplusKeyId, targetSaeId;
2937
2938 uint32_t peerNodeId;
2939 if(jPayload.contains("source_node_id"))
2940 peerNodeId = jPayload["source_node_id"];
2941 if(jPayload.contains("target_SAE_ID"))
2942 targetSaeId = jPayload["target_SAE_ID"];
2943 if(jPayload.contains("key_size"))
2944 keySize = jPayload["key_size"];
2945 if(jPayload.contains("key_number"))
2946 keyNumber = jPayload["key_number"]; //@toDo why is keyNumber always = 1, jtransformRequest["transform_key_number"] holds correct values, but keyNumber is 1?
2947 if(jPayload.contains("supply_key_ID")){
2948 for(
2949 nlohmann::json::iterator it = jPayload["supply_key_ID"].begin();
2950 it != jPayload["supply_key_ID"].end();
2951 ++it
2952 ){
2953 supplyKeyIds.push_back((it.value())["key_ID"]);
2954 }
2955 }
2956 if(jPayload.contains("candidate_set_ID")){
2957 for(
2958 nlohmann::json::iterator it = jPayload["candidate_set_ID"].begin();
2959 it != jPayload["candidate_set_ID"].end();
2960 ++it
2961 )
2962 candidateSetIds.push_back((it.value())["key_ID"]);
2963 }
2964 NS_ASSERT(keySize || keyNumber);
2965 NS_ASSERT(!supplyKeyIds.empty() || !candidateSetIds.empty() || !targetSaeId.empty());
2966
2967 //We read the request values, now we should create supply keys
2968 NS_LOG_FUNCTION(this << "\nSource KM node ID:\t" << peerNodeId
2969 << "\nTarget SAE ID:" << targetSaeId << "\nKey size:\t" << keySize
2970 << "\nKey number:\t" << keyNumber << "\nSupply key IDs:\t"<< supplyKeyIds
2971 << "\nCandidateSetIDs:" << candidateSetIds);
2972
2973 Ptr<SBuffer> sBuffer = GetSBuffer(peerNodeId, "dec");
2974 NS_ASSERT(sBuffer);
2975 if(sBuffer)
2976 {
2977 //We assume that all keys exists and we can create supply keys!
2978 uint32_t targetSize = keySize*keyNumber;
2979 std::string mergedKey {};
2980 Ptr<QKDKey> tempKey;
2981 for(size_t i = 0; i < candidateSetIds.size(); i++)
2982 {
2983 if(i != candidateSetIds.size()-1)
2984 {
2985 tempKey = sBuffer->GetKey(candidateSetIds[i], true);
2986 mergedKey += tempKey->GetKeyString(); //GetKey will also remove key from SBuffer
2987 NS_LOG_FUNCTION(this << "em94" << targetSize << mergedKey);
2988 }else{
2989 uint32_t size = targetSize - mergedKey.size()*8;
2990 NS_LOG_FUNCTION(this << "em95" << targetSize << mergedKey.size()*8 << size << "\n" << mergedKey);
2991 mergedKey +=(sBuffer->GetHalfKey(candidateSetIds[i], size))->GetKeyString(); //This function should modify key
2992 }
2993 }
2994
2995 for(size_t i = 0; i < supplyKeyIds.size(); i++)
2996 { //Should use keyNumber but the previus read is invalid! @toDo
2997 std::string keyString = mergedKey.substr(0, keySize/8);
2998 mergedKey.erase(0, keySize/8);
2999 Ptr<QKDKey> skey = CreateObject<QKDKey>(supplyKeyIds[i], keyString);
3000 sBuffer->StoreSupplyKey(skey);
3001 }
3002
3003 //create packet
3004 HTTPMessage httpMessage;
3005 httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok, "", {
3006 {"Content-Type", "application/json; charset=utf-8"},
3007 {"Request URI", headerIn.GetUri() }
3008 });
3009 std::string hMessage = httpMessage.ToString();
3010 Ptr<Packet> packet = Create<Packet>(
3011 (uint8_t*)(hMessage).c_str(),
3012 hMessage.size()
3013 );
3014 NS_ASSERT(packet);
3015
3016 QKDLocationRegisterEntry conn = GetController()->GetRoute(peerNodeId); //Get route information
3017 Ipv4Address dstKms = conn.GetDestinationKmsAddress();
3018 CheckSocketsKMS( dstKms ); //Check connection to peer KMS!
3019 Ptr<Socket> sendSocket = GetSendSocketKMS( dstKms );
3020 NS_ASSERT(sendSocket);
3021 sendSocket->Send(packet);
3022
3023 NS_LOG_FUNCTION( this << "Sending packed id " << packet->GetUid() << " of size " << packet->GetSize());
3024
3025 //SendToSocketPairKMS(socket, packet);
3026
3027 }else
3028 NS_FATAL_ERROR( this << "No s-buffer found for this connection!" );
3029
3030}
3031
3032void
3033QKDKeyManagerSystemApplication::ProcessSKeyCreateResponse(HTTPMessage headerIn, Ptr<Socket> socket)
3034{
3035 NS_LOG_FUNCTION(this);
3036 std::string payload = headerIn.GetMessageBodyString(); //Read payload
3037
3038 std::vector<std::string> uriParams {ReadUri(headerIn.GetRequestUri())};
3039
3040 Ipv4Address peerAddress = uriParams[0].c_str();
3041 auto it = m_httpRequestsQueryKMS.find(peerAddress);
3042 if(it == m_httpRequestsQueryKMS.end()){
3043 NS_LOG_ERROR(this);
3044 return;
3045 }
3046
3047 if(headerIn.GetStatus() == HTTPMessage::HttpStatus::Ok)
3048 { //ACK message
3049
3050 NS_LOG_FUNCTION(this << "We received HTTP OK(ack)!");
3051
3052 if(it->second[0].surplus_key_ID.empty())
3053 { //There is nothing to perform on this ACK response
3054 NS_LOG_FUNCTION(this << "2895");
3055 HttpKMSCompleteQuery(peerAddress);
3056 return;
3057 }
3058
3059 Ptr<SBuffer> sBuffer = GetSBuffer(it->second[0].peerNodeId, "enc");
3060 NS_ASSERT(sBuffer);
3061 std::string surplusKeyId {(it->second[0]).surplus_key_ID};
3062 sBuffer->MarkKey(surplusKeyId, QKDKey::READY);
3063
3064 }else{
3065 NS_LOG_ERROR(this << "Unexpected error");
3066 }
3067
3068 NS_LOG_FUNCTION(this << "2908");
3069 HttpKMSCompleteQuery(peerAddress);
3070}
3071
3072void
3073QKDKeyManagerSystemApplication::ProcessKMSCloseRequest(HTTPMessage headerIn, Ptr<Socket> socket, std::string ksid)
3074{
3075 NS_LOG_FUNCTION(this << ksid);
3076 std::string payload = headerIn.GetMessageBodyString(); //Read the packet payload
3077 nlohmann::json jcloseRequest;
3078 try {
3079 jcloseRequest = nlohmann::json::parse(payload);
3080 } catch(...) {
3081 NS_FATAL_ERROR(this << "json parse error");
3082 }
3083
3084 std::string surplusKeyId {};
3085 uint32_t syncIndex {0};
3086 if(jcloseRequest.contains("surplus_key_ID"))
3087 surplusKeyId = jcloseRequest["surplus_key_ID"];
3088 if(jcloseRequest.contains("sync_index"))
3089 syncIndex = jcloseRequest["sync_index"];
3090
3091 auto it = m_associations004.find(ksid);
3092 if(it == m_associations004.end()){ //Key stream association does not exists(peer error, or association already released)
3093 NS_LOG_DEBUG(this << "unknown ksid " << ksid);
3094
3095 //create packet
3096 HTTPMessage httpMessage;
3097 httpMessage.CreateResponse(HTTPMessage::HttpStatus::NotAcceptable, "", {
3098 {"Content-Type", "application/json; charset=utf-8"},
3099 {"Request URI", headerIn.GetUri() }
3100 });
3101 std::string hMessage = httpMessage.ToString();
3102 Ptr<Packet> packet = Create<Packet>(
3103 (uint8_t*)(hMessage).c_str(),
3104 hMessage.size()
3105 );
3106 NS_ASSERT(packet);
3107
3108 NS_LOG_FUNCTION(this << "packet sent " << packet->GetUid() << packet->GetSize());
3109 CheckSocketsKMS( it->second.dstKmsAddr ); //Check connection to peer KMS!
3110 Ptr<Socket> sendSocket = GetSendSocketKMS( it->second.dstKmsAddr );
3111 NS_ASSERT(sendSocket);
3112 sendSocket->Send(packet);
3113
3114 }else{
3115 it->second.peerRegistered = false; //QKDApp is no longer registered for particular association!
3116 bool empty {false};
3117 uint32_t localSyncIndex {0};
3118 if(it->second.stre_buffer->GetStreamKeyCount()) //Replica association buffer is not empty!
3119 localSyncIndex = it->second.stre_buffer->GetNextIndex(); //The oldest index in dedicated association buffer!
3120 else
3121 empty = true;
3122
3123 if(!surplusKeyId.empty() && syncIndex < localSyncIndex) //Only if peer KMS dedicated association buffer is not empty(known by the surplusKeyId presence)
3124 syncIndex = localSyncIndex; //KMSs synchronize on largest index that exists at both peers!
3125
3126 bool flag {false};
3127 if(empty && !surplusKeyId.empty())
3128 flag = true; //If replica empty, primary not. Replica sends flag insted of index!
3129
3130 if(GetNode()->GetId() < it->second.dstNodeId) //Is master? If master schedule!
3131 ReleaseAssociation(ksid, surplusKeyId, syncIndex);
3132 else
3133 ScheduleReleaseAssociation(Time("20ms"), "ReleaseAssociation", ksid, surplusKeyId, syncIndex);
3134
3135 nlohmann::json jresponse;
3136 if(!flag){
3137 if(!surplusKeyId.empty())
3138 jresponse["sync_index"] = syncIndex;
3139 }else
3140 jresponse["flag_empty"] = true;
3141
3142 //create packet
3143 HTTPMessage httpMessage;
3144 httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok, jresponse.dump(), {
3145 {"Content-Type", "application/json; charset=utf-8"},
3146 {"Request URI", headerIn.GetUri()}
3147 });
3148 std::string hMessage = httpMessage.ToString();
3149 Ptr<Packet> packet = Create<Packet>(
3150 (uint8_t*)(hMessage).c_str(),
3151 hMessage.size()
3152 );
3153 NS_ASSERT(packet);
3154
3155 NS_LOG_FUNCTION(this << "packet sent" << packet->GetUid() << packet->GetSize());
3156 CheckSocketsKMS( it->second.dstKmsAddr ); //Check connection to peer KMS!
3157 Ptr<Socket> sendSocket = GetSendSocketKMS( it->second.dstKmsAddr );
3158 NS_ASSERT(sendSocket);
3159 sendSocket->Send(packet);
3160
3161 }
3162}
3163
3164void
3165QKDKeyManagerSystemApplication::ReleaseAssociation(std::string ksid, std::string surplusKeyId, uint32_t syncIndex)
3166{
3167 NS_LOG_FUNCTION(this << ksid << surplusKeyId << syncIndex);
3168
3169 std::string temp = ksid + "-" + surplusKeyId + "-" + std::to_string(syncIndex);
3170 auto itSchedule = m_scheduledChecks.find(temp);
3171 if(itSchedule!=m_scheduledChecks.end())
3172 m_scheduledChecks.erase(itSchedule);
3173
3174 auto it = m_associations004.find(ksid);
3175 if(it == m_associations004.end()){ //Key stream association does not exists
3176 NS_LOG_DEBUG(this << "unkwnon ksid " << ksid);
3177 return;
3178 }
3179
3180 if(surplusKeyId.empty())
3181 { //Remove key stream
3182 m_associations004.erase(it);
3183 }else{
3184 std::string preservedKeyString;
3185 uint32_t presentKeyMaterial {0};
3186 //Remove keys to sync index. Trace consumed keys
3187 while(it->second.stre_buffer->GetNextIndex() && it->second.stre_buffer->GetNextIndex() < syncIndex){ //@toDo GetNextIndex could be 0, but for now, we assume association is closed(released) sometimes after
3188 NS_LOG_FUNCTION(this << "emir1" << it->second.stre_buffer->GetNextIndex());
3189 Ptr<QKDKey> key = it->second.stre_buffer->GetStreamKey();
3190 presentKeyMaterial += key->GetSizeInBits();
3191 m_keyServedTrace(it->second.srcSaeId, key->GetId(), key->GetSizeInBits());
3192 m_keyConsumedLink( //Is always p2p link now for 004
3193 it->second.srcNodeId, //Source
3194 it->second.dstNodeId, //Destination
3195 //{ksid + key->GetId()}, //Key ID should be combination of ksid+index!
3196 key->GetSizeInBits() //Size of key
3197 );
3198
3199 }
3200 //Get remaining keys, and group them in one string
3201 while(true){
3202 Ptr<QKDKey> key = it->second.stre_buffer->GetStreamKey();
3203 if(key)
3204 preservedKeyString += key->GetKeyString();
3205 else
3206 break;
3207
3208 }
3209 if(!preservedKeyString.empty()){
3210 Ptr<QBuffer> qBuffer = GetQBuffer(GetController()->GetRoute(it->second.dstSaeId).GetDestinationKmNodeId());
3211 if(qBuffer){
3212 NS_LOG_FUNCTION(this << "preserved key material" << preservedKeyString.size());
3213 Ptr<QKDEncryptor> encryptor = Create<QKDEncryptor>(64); //64 bits long key IDs. Collisions->0
3214 std::string hashInput {surplusKeyId + ksid}; //HASH input for key id
3215 NS_ASSERT(!hashInput.empty());
3216
3217 uint32_t blockSize {qBuffer->GetKeySize()/8}, blockNum {0}; //Current default key size for connection
3218 while(!preservedKeyString.empty()){
3219 std::string keyValueTemp {preservedKeyString};
3220 if(preservedKeyString.size() >= blockSize)
3221 keyValueTemp = preservedKeyString.substr(0, blockSize); //Take portion of the QKD-key value for KMA-key
3222 std::string completeHashInput = hashInput + std::to_string(blockNum++); //Complete HASH input
3223 std::string blockKeyId {encryptor->SHA1(completeHashInput)}; //Generate KMA-key ID based on the HASH output
3224 NS_LOG_FUNCTION(this << "store key " << blockKeyId << keyValueTemp);
3225 Ptr<QKDKey> tempKey = Create<QKDKey>(blockKeyId, keyValueTemp);
3226 qBuffer->StoreKey(tempKey); //Store KMA-key in QKD buffer
3227 preservedKeyString.erase(0, blockSize); //Update QKD-key value
3228 }
3229
3230 }else
3231 NS_FATAL_ERROR(this << "unknown q-buffer");
3232
3233 }
3234 m_associations004.erase(it);
3235
3236 }
3237
3238}
3239
3240void
3241QKDKeyManagerSystemApplication::ProcessKMSCloseResponse(HTTPMessage headerIn, Ptr<Socket> socket)
3242{
3243 NS_LOG_FUNCTION(this);
3244 std::string payload = headerIn.GetMessageBodyString();
3245 nlohmann::json jcloseResponse;
3246 try{
3247 jcloseResponse = nlohmann::json::parse(payload);
3248 }catch(...){
3249 NS_FATAL_ERROR(this << "json parse error");
3250 }
3251
3252 Ipv4Address dstKms { ReadUri(headerIn.GetRequestUri())[0].c_str() };
3253 auto it = m_httpRequestsQueryKMS.find(dstKms);
3254 if(it == m_httpRequestsQueryKMS.end()){
3255 NS_LOG_ERROR(this << "unable to map response; query empty");
3256 return;
3257
3258 }
3259 std::string ksid { ReadUri(headerIn.GetRequestUri())[5].c_str() };
3260 auto a = m_associations004.find(ksid);
3261 if(a == m_associations004.end()){
3262 NS_LOG_DEBUG(this << "unknown ksid " << ksid);
3263 return;
3264
3265 }
3266 if(headerIn.GetStatus() == HTTPMessage::NotAcceptable){ //Remove key stream. Trace discarded key material
3267 //must record key consumed
3268 uint32_t presentKeyMaterial {0};
3269 while(true){
3270 Ptr<QKDKey> key {a->second.stre_buffer->GetStreamKey()};
3271 if(key){
3272 presentKeyMaterial += key->GetSizeInBits();
3273 m_keyServedTrace(a->second.srcSaeId, key->GetId(), key->GetSizeInBits());
3274 m_keyConsumedLink(a->second.srcNodeId, a->second.dstNodeId, key->GetSizeInBits());
3275 }else
3276 break;
3277
3278 }
3279 m_associations004.erase(a); //Remove key stream.
3280
3281 }else if(headerIn.GetStatus() == HTTPMessage::Ok){ //Perserve key material if any. Remove key stream. Trace discarded key material
3282 uint32_t peerSyncIndex {0}, localSyncIndex {it->second[0].sync_index};
3283 if(jcloseResponse.contains("sync_index")){
3284 peerSyncIndex = jcloseResponse["sync_index"];
3285 if(peerSyncIndex > localSyncIndex)
3286 localSyncIndex = peerSyncIndex;
3287
3288 ReleaseAssociation(it->second[0].ksid, it->second[0].surplus_key_ID, localSyncIndex);
3289
3290 }else{
3291 //must record key consumed
3292 //must record key consumed
3293 uint32_t presentKeyMaterial {0};
3294 while(true){
3295 Ptr<QKDKey> key {a->second.stre_buffer->GetStreamKey()};
3296 if(key){
3297 NS_LOG_FUNCTION(this << key->GetId());
3298 presentKeyMaterial += key->GetSizeInBits();
3299 m_keyServedTrace(a->second.srcSaeId, key->GetId(), key->GetSizeInBits());
3300 m_keyConsumedLink(a->second.srcNodeId, a->second.dstNodeId, key->GetSizeInBits());
3301 }else
3302 break;
3303
3304 }
3305 m_associations004.erase(a);
3306
3307 }
3308
3309 }else
3310 NS_FATAL_ERROR(this << "unknown status code" << headerIn.GetStatus());
3311
3312 HttpKMSCompleteQuery(dstKms);
3313
3314}
3315
3316/**
3317 * ********************************************************************************************
3318
3319 * HTTP handling
3320
3321 * ********************************************************************************************
3322 */
3323
3324void
3325QKDKeyManagerSystemApplication::HttpKMSAddQuery(Ipv4Address dstKms, HttpQuery request)
3326{
3327 NS_LOG_FUNCTION( this << dstKms);
3328 auto it = m_httpRequestsQueryKMS.find(dstKms);
3329 if(it != m_httpRequestsQueryKMS.end())
3330 it->second.push_back(request);
3331 else
3332 m_httpRequestsQueryKMS.insert(std::make_pair(dstKms, std::vector<HttpQuery> {request}));
3333}
3334
3335void
3336QKDKeyManagerSystemApplication::HttpKMSCompleteQuery(Ipv4Address dstKms)
3337{
3338 NS_LOG_FUNCTION( this );
3339 auto it = m_httpRequestsQueryKMS.find(dstKms);
3340 if(it != m_httpRequestsQueryKMS.end())
3341 {
3342 if(!it->second.empty())
3343 {
3344 it->second.erase(it->second.begin());
3345 }else{
3346 NS_FATAL_ERROR( this << "HTTP query for this KMS is empty!");
3347 }
3348 }else{
3349 NS_FATAL_ERROR( this << "HTTP query to destination KMS does not exist!" );
3350 }
3351}
3352
3354QKDKeyManagerSystemApplication::HttpQueryMethod(Ipv4Address dstKms)
3355{
3356 NS_LOG_FUNCTION( this );
3358 auto it = m_httpRequestsQueryKMS.find(dstKms);
3359 if(it!=m_httpRequestsQueryKMS.end())
3360 methodType = it->second.begin()->method_type;
3361 else
3362 NS_FATAL_ERROR( this << "HTTP response cannot be mapped: HTTP query is empty!" );
3363 return methodType;
3364}
3365
3366void
3367QKDKeyManagerSystemApplication::Http004AppQuery( std::string saeId, Ptr<Socket> socket )
3368{
3369 NS_LOG_FUNCTION( this << saeId << socket );
3370 m_http004App.insert(std::make_pair(saeId, socket));
3371}
3372
3373void
3374QKDKeyManagerSystemApplication::Http004AppQueryComplete(std::string saeId)
3375{
3376 NS_LOG_FUNCTION( this << saeId );
3377 //Must use equal_range
3378 std::pair<std::multimap<std::string, Ptr<Socket> >::iterator, std::multimap<std::string, Ptr<Socket> >::iterator > ret;
3379 ret = m_http004App.equal_range(saeId);
3380
3381 if(ret.first == ret.second)
3382 NS_FATAL_ERROR( this << "Query is empty" );
3383
3384 std::multimap<std::string, Ptr<Socket> >::iterator it = ret.first;
3385 m_http004App.erase(it);
3386
3387}
3388
3390QKDKeyManagerSystemApplication::GetSocketFromHttp004AppQuery(std::string saeId)
3391{
3392 NS_LOG_FUNCTION( this << saeId );
3393
3394 std::pair<std::multimap<std::string, Ptr<Socket> >::iterator, std::multimap<std::string, Ptr<Socket> >::iterator > ret;
3395 ret = m_http004App.equal_range(saeId);
3396 if(ret.first == ret.second)
3397 NS_FATAL_ERROR( this << "sae query is not registered" );
3398 auto it = ret.first;
3399
3400 NS_LOG_FUNCTION( this << saeId << it->second);
3401 return it->second;
3402
3403}
3404
3405
3406void
3407QKDKeyManagerSystemApplication::HttpProxyRequestAdd(HttpQuery query)
3408{
3409 NS_LOG_FUNCTION(this << query.req_id);
3410 m_httpProxyRequests.insert( std::make_pair(query.req_id, query) );
3411}
3412
3414QKDKeyManagerSystemApplication::GetProxyQuery(std::string reqId)
3415{
3416 NS_LOG_FUNCTION(this << reqId);
3417 HttpQuery query;
3418 auto it = m_httpProxyRequests.find(reqId);
3419 if(it == m_httpProxyRequests.end()){
3420 NS_FATAL_ERROR(this << "Unknown proxy request ID:" << reqId << "\tMapping of response failed!");
3421 //NS_LOG_DEBUG(this << "Unknown proxy request ID:" << reqId << "\tMapping of response failed!");
3422 } else
3423 query = it->second;
3424
3425 return query;
3426}
3427
3428void
3429QKDKeyManagerSystemApplication::RemoveProxyQuery(std::string reqId)
3430{
3431 NS_LOG_FUNCTION(this << reqId);
3432 auto it = m_httpProxyRequests.find(reqId);
3433 if(it == m_httpProxyRequests.end()){
3434 NS_FATAL_ERROR(this << "Unknown proxy request ID:" << reqId << "\tRemove failed!");
3435 //NS_LOG_DEBUG(this << "Unknown proxy request ID:" << reqId << "\tRemove failed!");
3436
3437 } else
3438 m_httpProxyRequests.erase(it);
3439
3440}
3441
3442
3444QKDKeyManagerSystemApplication::GetDestinationKmsAddress(Ptr<Socket> socket)
3445{
3446 NS_LOG_FUNCTION( this );
3447 Ipv4Address dstKMSAddress;
3448
3449 std::map<Ipv4Address, std::pair<Ptr<Socket>, Ptr<Socket> > >::iterator it;
3450 for(it = m_socketPairsKMS.begin(); it != m_socketPairsKMS.end(); ++it)
3451 {
3452 if((it->second).first == socket) {
3453 dstKMSAddress = it->first;
3454 break;
3455 }
3456 }
3457
3458 return dstKMSAddress;
3459}
3460
3462QKDKeyManagerSystemApplication::GetMaxKeyPerRequest(){
3463 return m_maxKeyPerRequest;
3464}
3465
3467QKDKeyManagerSystemApplication::FetchRequestType(std::string s)
3468{
3469
3470 NS_LOG_FUNCTION(this << s );
3471
3472 RequestType output;
3473
3474 if(s == "status"){
3475
3476 return ETSI_QKD_014_GET_STATUS;
3477
3478 } else if(s == "enc_keys") {
3479
3480 return ETSI_QKD_014_GET_KEY;
3481
3482 } else if(s == "dec_keys"){
3483
3484 return ETSI_QKD_014_GET_KEY_WITH_KEY_IDS;
3485
3486 } else if(s == "open_connect"){
3487
3488 return ETSI_QKD_004_OPEN_CONNECT;
3489
3490 } else if(s == "get_key") {
3491
3492 return ETSI_QKD_004_GET_KEY;
3493
3494 } else if(s == "close") {
3495
3496 return ETSI_QKD_004_CLOSE;
3497
3498 } else if(s == "new_app") {
3499
3500 return NEW_APP;
3501
3502 } else if(s == "register") {
3503
3504 return REGISTER;
3505
3506 } else if(s == "fill") {
3507
3508 return FILL;
3509
3510 } else if(s == "store_key") {
3511
3512 return STORE_KEY;
3513
3514 } else if(s == "skey_create") {
3515
3516 return TRANSFORM_KEYS;
3517
3518 } else if(s == "close_kms") {
3519
3520 return ETSI_QKD_004_KMS_CLOSE;
3521
3522 } else if(s == "relay") {
3523
3524 return RELAY_KEYS;
3525
3526 } else {
3527
3528 NS_FATAL_ERROR(this << "Unknown Type: " << s);
3529 }
3530
3531 return output;
3532}
3533
3534
3535void
3536QKDKeyManagerSystemApplication::EstablishKMLinkSockets(Ipv4Address remoteKmAddress)
3537{
3538 NS_LOG_FUNCTION(this << "Create sink socket to listen requests exchanged between KMSs!");
3539
3540 InetSocketAddress sinkAddress = InetSocketAddress(m_local, 8080);
3541 Ptr<Socket> sinkSocket = Socket::CreateSocket(GetNode(), m_tid);
3542 sinkSocket->Bind(sinkAddress);
3543 sinkSocket->Listen();
3544 //sinkSocket->ShutdownSend();
3545 sinkSocket->SetRecvCallback(MakeCallback(&QKDKeyManagerSystemApplication::HandleReadKMSs, this));
3546 sinkSocket->SetAcceptCallback(
3547 MakeNullCallback<bool, Ptr<Socket>, const Address &>(),
3548 MakeCallback(&QKDKeyManagerSystemApplication::HandleAcceptKMSs, this)
3549 );
3550 sinkSocket->SetCloseCallbacks(
3551 MakeCallback(&QKDKeyManagerSystemApplication::HandlePeerCloseKMSs, this),
3552 MakeCallback(&QKDKeyManagerSystemApplication::HandlePeerErrorKMSs, this)
3553 );
3554
3555 //Store this socket for further use. Later we will create the send socket as well
3556 Ptr<Socket> sendSocket = 0;
3557 m_socketPairsKMS.insert(
3558 std::make_pair(
3559 remoteKmAddress,
3560 std::make_pair(sinkSocket, sendSocket)
3561 )
3562 );
3563
3564}
3565
3566
3567nlohmann::json
3568QKDKeyManagerSystemApplication::Check014GetKeyRequest(
3569 uint32_t number,
3570 uint32_t size,
3571 Ptr<SBuffer> buffer
3572)
3573{
3574 NS_LOG_FUNCTION(this << number << size << GetMaxKeyPerRequest() << m_maxKeySize << m_minKeySize << size % 8);
3575
3576 NS_LOG_FUNCTION(this <<(number > GetMaxKeyPerRequest()));
3577 NS_LOG_FUNCTION(this <<(number <= 0));
3578 NS_LOG_FUNCTION(this <<(size > m_maxKeySize));
3579 NS_LOG_FUNCTION(this <<(size < m_minKeySize));
3580 NS_LOG_FUNCTION(this <<(size % 8));
3581
3582 nlohmann::json jError;
3583 if( //Validation check
3584 number > GetMaxKeyPerRequest() ||
3585 number <= 0 ||
3586 size > m_maxKeySize ||
3587 size < m_minKeySize ||
3588 size % 8
3589 ){
3590 jError["message"] = std::string {"requested parameters do not adhere to KM rules"};
3591 if(number > GetMaxKeyPerRequest()){
3592 std::string msgDetail = "requested number of keys(" + std::to_string(number) + ") is higher then a maximum number of keys(" + std::to_string(GetMaxKeyPerRequest()) + ") per request allowed by KMS";
3593 jError["details"].push_back({{"number_unsupported", msgDetail}});
3594
3595 }else if(number <= 0){
3596 std::string msgDetail = "requested number of keys can not be lower or equal to zero";
3597 jError["details"].push_back({{"number_unsupported", msgDetail}});
3598 }
3599
3600 if(size > m_maxKeySize){
3601 std::string msgDetail = "requested size of keys(" + std::to_string(size) + ") is higher then a maximum size of key(" + std::to_string(m_maxKeySize) + ") that KMS can deliver";
3602 jError["details"].push_back({{"size_unsupported", msgDetail}});
3603
3604 }else if(size < m_minKeySize){
3605 std::string msgDetail = "requested size of keys(" + std::to_string(size) + ") is lower then a minimum size of key(" + std::to_string(m_minKeySize) + ") that KMS can deliver";
3606 jError["details"].push_back({{"size_unsupported", msgDetail}});
3607
3608 }else if(size % 8){
3609 std::string msgDetail = "size shall be a multiple of 8";
3610 jError["details"].push_back({{"size_unsupported", msgDetail}});
3611 }
3612
3613
3614 }else{ //Others - ability to serve
3615 uint32_t availableKeyBits = buffer->GetSBitCount();
3616 NS_LOG_FUNCTION(this << "\nTarget key size: " << size << "\nTarget number: " << number
3617 << "\nRequired amount of key material: " << size*number
3618 << "\nAmount of key material in s-buffer(READY): " << availableKeyBits);
3619 if(size*number > availableKeyBits) //Check if there is enough key material!
3620 jError = {{"message", "insufficient amount of key material"}};
3621 }
3622
3623 return jError;
3624}
3625
3626
3627nlohmann::json
3628QKDKeyManagerSystemApplication::CreateKeyContainer(std::vector<Ptr<QKDKey>> keys)
3629{
3630 NS_LOG_FUNCTION(this);
3631 nlohmann::json jkeys;
3632 for(uint32_t i = 0; i < keys.size(); i++){
3633 if(keys[i])
3634 {
3635 // Convert to bytes
3636 std::string byteKey = keys[i]->ConsumeKeyString();
3637 // Convert to Base64 for JSON storage
3638 std::string encodedKey = m_encryptor->Base64Encode(byteKey);
3639 NS_LOG_FUNCTION(this << "KEY" << i+1 << keys[i]->GetId() << encodedKey << "\n");
3640 jkeys["keys"].push_back({ {"key_ID", keys[i]->GetId()}, {"key", encodedKey} });
3641 }
3642
3643 }
3644 return jkeys;
3645
3646}
3647
3648/**
3649 * ********************************************************************************************
3650
3651 * KMS 004 Association operations, monitoring
3652
3653 * ********************************************************************************************
3654 */
3655
3656 std::string
3657 QKDKeyManagerSystemApplication::GenerateUUID()
3658 {
3659 NS_LOG_FUNCTION(this);
3660 std::string output;
3661 UUID ksidRaw = UUID::Sequential();
3662 output = ksidRaw.string();
3663 NS_LOG_FUNCTION(this << output);
3664 return output;
3665 }
3666
3667void
3668QKDKeyManagerSystemApplication::CheckEtsi004Association(std::string ksid)
3669{
3670 NS_LOG_FUNCTION(this << ksid);
3671
3672 auto itSchedule = m_scheduledChecks.find(ksid);
3673 if(itSchedule!=m_scheduledChecks.end())
3674 m_scheduledChecks.erase(itSchedule);
3675
3676 auto it = m_associations004.find(ksid);
3677 if(it == m_associations004.end()){
3678 NS_LOG_DEBUG(this << "unknown ksid" << ksid);
3679 return;
3680 }
3681
3682 if(it->second.peerRegistered &&(it->second).stre_buffer->GetStreamKeyCount() < 2)
3683 {
3684 //Check
3685 /**
3686 * @toDo
3687 * The amount of key material to be assigned to the association must be determined by the QoS parameters.
3688 */
3689 Ptr<QBuffer> qBuffer = GetQBuffer(it->second.dstNodeId);
3690 uint32_t availableKeys = qBuffer->GetBitCount();
3691 uint32_t availableKeyChunks = std::floor(availableKeys / it->second.qos.chunkSize);
3692
3693 NS_LOG_FUNCTION(this << availableKeys << it->second.qos.chunkSize << availableKeyChunks);
3694
3695 if(availableKeyChunks >= 6){
3696 NS_LOG_FUNCTION(this << "Fill only 6 keys at time!");
3697 availableKeyChunks = 6;
3698 } else if(availableKeyChunks >= 2){
3699 NS_LOG_FUNCTION(this << "Fill with available amount - 1!");
3700 availableKeyChunks--;
3701 } else if(availableKeyChunks == 0){
3702 NS_LOG_FUNCTION(this << "Shedule new attempt!");
3703 ScheduleCheckEtsi004Association(Time("2s"), "CheckEtsi004Association", ksid);
3704 return;
3705 }
3706 Fill(it->second.dstNodeId, ksid, availableKeyChunks*it->second.qos.chunkSize); //Starts reservation of keys for the association
3707
3708 }else if(!it->second.peerRegistered)
3709 NS_LOG_ERROR(this << "peer not registered " << ksid);
3710
3711}
3712
3713void
3714QKDKeyManagerSystemApplication::ReadJsonQos(
3716 nlohmann::json jOpenConnectRequest)
3717{
3718
3719 if(jOpenConnectRequest.contains("QoS")) { //Only Key_chunk_size from the QoS perspective supported!
3720
3721 if(jOpenConnectRequest["QoS"].contains("Key_chunk_size"))
3722 inQos.chunkSize = jOpenConnectRequest["QoS"]["Key_chunk_size"];
3723
3724 }
3725 NS_ASSERT(inQos.chunkSize >= 0);
3726}
3727
3728std::vector<std::string>
3729QKDKeyManagerSystemApplication::ReadUri(std::string s)
3730{
3731 NS_LOG_FUNCTION(this);
3732
3733 std::string delimiter {"/"}, token;
3734 size_t pos = 0;
3735 std::vector<std::string> uriParams;
3736 while((pos = s.find(delimiter)) != std::string::npos){
3737 token = s.substr(0, pos);
3738 if(!token.empty())
3739 uriParams.push_back(token);
3740
3741 s.erase(0, pos + delimiter.length());
3742
3743 }
3744 if(!s.empty())
3745 uriParams.push_back(s);
3746
3747 return uriParams;
3748}
3749
3750std::string
3751QKDKeyManagerSystemApplication::CreateKeyStreamSession(
3752 std::string srcSaeId,
3753 std::string dstSaeId,
3755 std::string ksid
3756){
3757 NS_LOG_FUNCTION(this << srcSaeId << dstSaeId << ksid);
3758
3759 Ptr<SBuffer> SBufferStream = CreateObject<SBuffer>(SBuffer::STREAM_SBUFFER, inQos.chunkSize);
3760 SBufferStream->Initialize();
3761 SBufferStream->SetDescription ("(STREAM)");
3762 SBufferStream->SetIndex( m_qbuffersVector.size() );
3763 uint32_t dstNodeId = GetController()->GetRoute(dstSaeId).GetDestinationKmNodeId();
3764 m_qbuffersVector.push_back(SBufferStream);
3765 m_qbuffers.insert(std::make_pair(dstNodeId, SBufferStream) );
3766
3768 uint32_t applicationIndex = 0;
3769 for(uint32_t i = 0; i < GetNode()->GetNApplications(); ++i)
3770 {
3771 kms = GetNode()->GetApplication(i)->GetObject <QKDKeyManagerSystemApplication>();
3772 applicationIndex = i;
3773 if(kms) break;
3774 }
3775 SBufferStream->SetSrcKMSApplicationIndex(applicationIndex);
3776
3777 //CREATE QKD GRAPH
3778 QKDGraphManager *QKDGraphManager = QKDGraphManager::getInstance();
3779 uint32_t srcNodeId = GetNode()->GetId();
3780 std::string graphTitle = "SBUFFER (STREAM): " + std::to_string(srcNodeId) + "-SAE(" + srcSaeId + ") - " + std::to_string(dstNodeId) + "-SAE(" + dstSaeId + ")" ;
3781
3782 Ptr<Node> dstNode = NodeList::GetNode(dstNodeId);
3783
3785 GetNode(),
3786 dstNode,
3787 SBufferStream->GetIndex(),
3788 SBufferStream->GetSrcKMSApplicationIndex(),
3789 graphTitle,
3790 "png",
3791 SBufferStream
3792 );
3793
3795 srcSaeId,
3796 dstSaeId,
3797 GetNode()->GetId(),
3798 dstNodeId,
3799 GetController()->GetRoute(dstSaeId).GetDestinationKmsAddress(),
3800 inQos,
3801 true, //registered
3802 SBufferStream
3803 };
3804 if(ksid.empty()){
3805 ksid = GenerateUUID();
3806 newKeyStreamSession.peerRegistered = false;
3807 }
3808
3809 m_associations004.insert(std::make_pair(ksid, newKeyStreamSession));
3810
3811 return ksid;
3812}
3813
3814std::string
3815QKDKeyManagerSystemApplication::GenerateRandomString(const int len, const uint32_t seed){
3816 std::string tmp_s;
3817 static const char alphanum[] =
3818 "0123456789"
3819 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
3820 "abcdefghijklmnopqrstuvwxyz";
3821 //if(seed == 0)
3822 // srand( m_kms_key_id );
3823 //else
3824 // srand( seed );
3825 for(int i = 0; i < len; ++i){
3826 tmp_s += alphanum[rand() %(sizeof(alphanum) - 1)];
3827 }
3828 return tmp_s;
3829}
3830
3831} // Namespace ns3
iter_impl< basic_json > iterator
an iterator for a basic_json container
Definition json.h:20337
a polymophic address class
Definition address.h:90
The base class for all ns3 applications.
Definition application.h:51
void DoDispose() override
Destructor implementation.
AttributeValue implementation for Boolean.
Definition boolean.h:26
An identifier for simulation events.
Definition event-id.h:45
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
@ POST
Http Method Post.
Definition http.h:86
@ GET
Http Method GET.
Definition http.h:83
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
void CreateResponse(const HttpStatus status)
Definition http.h:781
size_t GetContentLength() const
Return the size of the binary body vector.
Definition http.h:722
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.
static Ipv4Address GetAny()
AttributeValue implementation for Ipv4Address.
uint32_t GetId() const
Definition node.cc:106
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:66
void CreateGraphForBuffer(Ptr< Node > srcKMSNode, Ptr< Node > dstKMSNode, uint32_t bufferID, uint32_t srcKMSApplicationIndex, std::string graphName, std::string graphType, Ptr< QBuffer > buff)
Connect new QBuffer/Sbuffer to QKDTotalGraph.
QKDNetSim implements Key Management System(KMS) as an application that listens on TCP port 80.
uint32_t GetMaxKeyPerRequest()
Get maximum number of keys per request(ETSI QKD 014)
void HandlePeerCloseKMSs(Ptr< Socket > socket)
Handle an connection close.
Ptr< QKDKMSQueueLogic > m_queueLogic
KMS Queue Logic for ETSI 004 QoS handling.
void SendToSocketPairKMS(Ptr< Socket > socket, Ptr< Packet > packet)
Send packet to the pair socket.
void HandleAccept(Ptr< Socket > s, const Address &from)
Handle an incoming connection.
void StopApplication() override
Stop KMS Application.
std::map< std::string, Association004 > m_associations004
Ptr< Socket > GetSendSocketKMS(Ipv4Address kmsDstAddress)
Obtain send socket.
Ptr< QCenController > m_cen_controller
Asigned Q centralized controler for routing!
std::map< uint32_t, Ipv4Address > m_peerAddressTable
IP address of peer KM nodes.
uint32_t GetTotalRx() const
Get the total amount of bytes received.
void ScheduleReleaseAssociation(Time t, std::string action, std::string ksid, std::string surplusKeyId, uint32_t syncIndex)
void HttpKMSAddQuery(Ipv4Address dstKms, HttpQuery request)
remember HTTP request made to peer KMS
void HandleAcceptKMSs(Ptr< Socket > s, const Address &from)
Handle an incoming connection.
std::vector< Ptr< QBuffer > > m_qbuffersVector
The list of QBuffers is necessary for plotting.
std::map< Ipv4Address, std::pair< Ptr< Socket >, Ptr< Socket > > > m_socketPairsKMS
we do not know which KMS is going to initialize new TCP connection to peer KMS.
void ProcessPacketKMSs(HTTPMessage header, Ptr< Packet > packet, Ptr< Socket > socket)
QKD key manager system application process the request peer KMS, and complete certain actions to resp...
void ConnectionSucceeded(Ptr< Socket > socket)
@toDo:following functions
std::map< Ptr< Socket >, Ptr< Packet > > m_packetQueues
Buffering unsend messages due to connection problems.
void StartSBufferClients(uint32_t dstKmNodeId)
Start s-buffers control – monitoring.
std::map< uint32_t, uint32_t > m_link_states
Notified link states!
std::string GetAddressString(Ipv4Address address)
Get address as string.
TracedCallback< Ptr< const Packet >, const Address & > m_rxTrace
Traced Callback: received packets, source address.
void Fill(uint32_t dstKmNodeId, std::string direction, uint32_t amount)
Fill s-buffer.
void SetSocket(std::string type, Ptr< Socket > socket)
Set sink socket.
Ptr< Socket > GetSocket() const
Get sink socket.
void SetPeerKmAddress(uint32_t dstKmNodeId, Ipv4Address dstKmAddress)
Set peer KM node address.
Ptr< QBuffer > GetQBuffer(uint32_t remoteKmNodeId, std::string type="ns3::QBuffer")
Get q-buffer established with remote key manager.
QKDKeyManagerSystemApplication::RequestType FetchRequestType(std::string s)
Get request type.
void SBufferClientCheck(uint32_t dstKmNodeId)
check s-buffer levels
void SetCenController(Ptr< QCenController > controller)
void HandleReadKMSs(Ptr< Socket > socket)
Handle a packet received by the KMS from KMS.
void HandlePeerError(Ptr< Socket > socket)
Handle an connection error.
void HandlePeerClose(Ptr< Socket > socket)
Handle an connection close.
TracedCallback< Ptr< const Packet >, const Address & > m_rxTraceKMSs
std::map< std::string, uint32_t > m_qkdmodules
QKD modules and KM node ID they connect to.
Ptr< QKDControl > GetController()
Get QKDN controller object.
void PacketReceivedKMSs(const Ptr< Packet > &p, const Address &from, Ptr< Socket > socket)
Assemble byte stream to extract HTTPMessage.
std::map< uint32_t, Ptr< QBuffer > > m_qbuffers
Q-buffers for every QKD connection.
Ptr< SBuffer > GetSBuffer(uint32_t dstKmNodeId, std::string type)
TracedCallback< const uint32_t &, const uint32_t &, const uint32_t &, const uint32_t & > m_keyConsumedRelay
void CreateQBuffer(uint32_t dstId, Ptr< QBuffer > bufferConf)
Create Q buffer shared with remote key manager node.
void Relay(uint32_t dstKmNodeId, uint32_t amount)
Start key relay function.
TracedCallback< const std::string &, const std::string &, const uint32_t & > m_keyServedTrace
void DoDispose() override
Destructor implementation.
void HandlePeerErrorKMSs(Ptr< Socket > socket)
Handle an connection error.
void UpdateLinkState(uint32_t dstKmNodeId)
Check the QKD link state to given destination.
std::map< uint32_t, Ptr< SBuffer > > m_keys_dec
LOCAL S-buffers for the inbound point-to-poit usage.
void SetController(Ptr< QKDControl > controller)
Assign QKDN controller.
~QKDKeyManagerSystemApplication() override
QKDKeyManagerSystemApplication destructor.
void SendToSocketPair(Ptr< Socket > socket, Ptr< Packet > packet)
Send packet to the pair socket.
std::vector< std::string > ReadUri(std::string s)
Read parameters from URI.
Ptr< SBuffer > CreateRelaySBuffer(uint32_t srcNodeId, uint32_t dstNodeId, std::string description)
Help function to create relay SBuffers.
uint32_t m_totalRxKMSs
Total bytes received between KMSs.
void StartApplication() override
Start KMS Application.
void HandleRead(Ptr< Socket > socket)
Handle a packet received by the KMS application.
TracedCallback< const uint32_t &, const uint32_t &, const uint32_t & > m_keyWasteRelay
std::unordered_map< Address, Ptr< Packet >, AddressHash > m_bufferKMS
Buffer for received packets(TCP segmentation)
Ptr< QKDControl > m_controller
Asigned QKDN controller.
std::map< uint32_t, Ptr< SBuffer > > m_keys_enc
LOCAL S-buffers for the outbound point-to-point usage.
TracedCallback< const std::string &, const std::string &, const uint32_t & > m_qkdKeyGeneratedTrace
TracedCallback< const uint32_t &, const uint32_t &, const uint32_t & > m_keyConsumedLink
void EstablishKMLinkSockets(Ipv4Address remoteKmAddress)
Create sink socket to listen requests exchanged between KMSs.
void RegisterQKDModule(uint32_t dstId, std::string moduleId)
Registers a QKD module in key manager.
void PacketReceived(const Ptr< Packet > &p, const Address &from, Ptr< Socket > socket)
Assemble byte stream to extract HTTPMessage.
TracedCallback< Ptr< const Packet > > m_txTraceKMSs
void ReleaseAssociation(std::string ksid, std::string surplusKeyId, uint32_t syncIndex)
release key stream association
void ProcessRequest(HTTPMessage header, Ptr< Packet > packet, Ptr< Socket > socket)
QKD key manager system application process the request from QKDApp, and complete certain actions to r...
void ScheduleCheckEtsi004Association(Time t, std::string action, std::string ksid)
schedule next event in an attempt to fill association buffer
TracedCallback< Ptr< const Packet > > m_txTrace
std::unordered_map< Address, Ptr< Packet >, AddressHash > m_buffer
Buffer for received packets(TCP segmentation)
void CheckEtsi004Association(std::string ksid)
Check the state of a single assocation.
void CheckSocketsKMS(Ipv4Address dstSaeId)
Prepare send socket to communicate with peer KMS Application.
QKDKeyManagerSystemApplication()
QKDKeyManagerSystemApplication constructor.
Introspection did not find any typical Config paths.
Ipv4Address GetDestinationKmsAddress() const
Get destination KMS Address.
uint32_t GetNextHop() const
Get next hop.
uint32_t GetHop() const
Get hop.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:560
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
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
@ NS3_SOCK_STREAM
Definition socket.h:97
@ NS3_SOCK_SEQPACKET
Definition socket.h:98
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
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
Universally unique identifier(UUID)
Definition uuid.h:35
std::string string() const
Get string from the current UUID in format "00000000-0000-0000-0000-000000000000".
Definition uuid.cc:74
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
ObjectPtrContainerValue ObjectVectorValue
ObjectVectorValue is an alias for ObjectPtrContainerValue.
Ptr< const AttributeAccessor > MakeObjectVectorAccessor(U T::*memberVariable)
MakeAccessorHelper implementation for ObjectVector.
Callback< R, Args... > MakeNullCallback()
Definition callback.h:727
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#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_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:271
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition log.h:264
#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.
@ error
throw a parse_error exception in case of a tag
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...
Definition callback.h:684
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition uinteger.h:35
Ptr< const AttributeAccessor > MakeIpv4AddressAccessor(T1 a1)
Ptr< const AttributeChecker > MakeTypeIdChecker()
Definition type-id.cc:1335
Ptr< const AttributeChecker > MakeIpv4AddressChecker()
Ptr< const AttributeAccessor > MakeTypeIdAccessor(T1 a1)
Definition type-id.h:641