A Discrete-Event Network Simulator
API
qkd-key-manager-system-application.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2020 DOTFEESA www.tk.etf.unsa.ba
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Emir Dervisevic <emir.dervisevic@etf.unsa.ba>
19  * Miralem Mehic <miralem.mehic@ieee.org>
20  */
21 
22 #include "ns3/log.h"
23 #include "ns3/address.h"
24 #include "ns3/node.h"
25 #include "ns3/nstime.h"
26 #include "ns3/socket.h"
27 #include "ns3/simulator.h"
28 #include "ns3/tcp-socket-factory.h"
29 #include "ns3/packet.h"
30 #include "ns3/uinteger.h"
31 #include "ns3/trace-source-accessor.h"
32 #include "ns3/qkd-control.h"
33 #include "ns3/http.h"
34 #include "ns3/json.h"
35 
36 #include <iostream>
37 #include <fstream>
38 #include <string>
39 
41 
42 namespace ns3 {
43 
44 NS_LOG_COMPONENT_DEFINE ("QKDKeyManagerSystemApplication");
45 
46 NS_OBJECT_ENSURE_REGISTERED (QKDKeyManagerSystemApplication);
47 
48 TypeId
50 {
51  static TypeId tid = TypeId ("ns3::QKDKeyManagerSystemApplication")
53  .SetGroupName("Applications")
54  .AddConstructor<QKDKeyManagerSystemApplication> ()
55  //send params
56  .AddAttribute ("Protocol", "The type of protocol to use.",
60  .AddAttribute ("LocalAddress", "The ipv4 address of the application",
61  Ipv4AddressValue (),
62  MakeIpv4AddressAccessor (&QKDKeyManagerSystemApplication::m_local),
63  MakeIpv4AddressChecker ())
64  .AddAttribute ("MaximalKeysPerRequest",
65  "The maximal number of keys per request (ESTI QKD 014)",
66  UintegerValue (20),
68  MakeUintegerChecker<uint32_t> ())
69  .AddAttribute ("MinimalKeySize",
70  "The minimal size of key QKDApp can request",
71  UintegerValue (32), //in bits
73  MakeUintegerChecker<uint32_t> ())
74  .AddAttribute ("MaximalKeySize",
75  "The maximal size of key QKDApp can request",
76  UintegerValue (10240), //in bits
78  MakeUintegerChecker<uint32_t> ())
79  .AddAttribute ("DefaultKeySize",
80  "The default size of the key",
81  UintegerValue (512), //in bits
83  MakeUintegerChecker<uint32_t> ())
84  .AddAttribute ("MaliciousRequestBlocking",
85  "Does KMS detects and blocks malicious get_key_004 request?",
86  UintegerValue (0), //default: YES/TRUE
88  MakeUintegerChecker<uint32_t> ())
89  .AddAttribute ("ETSI004_DefaultTTL",
90  "Default value of ETSI004 TTL (in seconds)",
91  UintegerValue (10), //default: YES/TRUE
93  MakeUintegerChecker<uint32_t> ())
94  .AddAttribute ("MaxKeyRate", "The maximal key rate (encryption+authentication) provided by the KMS (QoS settings).",
95  DataRateValue (DataRate ("10kb/s")),
96  MakeDataRateAccessor (&QKDKeyManagerSystemApplication::m_maxKeyRate),
97  MakeDataRateChecker ())
98  .AddAttribute ("MinKeyRate", "The minimal key rate (encryption+authentication) provided by the KMS (QoS settings).",
99  DataRateValue (DataRate ("1kb/s")),
100  MakeDataRateAccessor (&QKDKeyManagerSystemApplication::m_minKeyRate),
101  MakeDataRateChecker ())
102  .AddAttribute ("QoS_maxrate_threshold",
103  "The treshold for processing low-priority requests",
104  DoubleValue (0.2),
106  MakeDoubleChecker<double> ())
107 
108  .AddTraceSource ("Tx", "A new packet is created and is sent to the APP",
110  "ns3::QKDKeyManagerSystemApplication::Tx")
111  .AddTraceSource ("Rx", "A packet from the APP has been received",
113  "ns3::QKDKeyManagerSystemApplication::Rx")
114  .AddTraceSource ("TxKMSs", "A new packet is created and is sent to the APP",
116  "ns3::QKDKeyManagerSystemApplication::TxKMSs")
117  .AddTraceSource ("RxKMSs", "A packet from the APP has been received",
119  "ns3::QKDKeyManagerSystemApplication::RxKMSs")
120  //**********************************************************************
121  .AddTraceSource ("NewKeyGeneratedEmir", "The trace to monitor key material received from QL",
123  "ns3::QKDKeyManagerSystemApplication::NewKeyGeneratedEmir")
124  .AddTraceSource ("KeyServedEmir", "The trace to monitor key material served to QKD Apps",
126  "ns3:QKDKeyManagerSystemApplication::KeyServedEmir")
127  //**********************************************************************
128  .AddTraceSource ("NewKeyGenerated", "The trace to monitor key material received from QL",
130  "ns3::QKDKeyManagerSystemApplication::NewKeyGenerated")
131 
132  .AddTraceSource ("KeyServedEtsi014", "The thece to monitor key usage by etsi 014",
134  "ns3::QKDKeyManagerSystemApplication::KeyServedEtsi014")
135 
136  .AddTraceSource ("KeyServedEtsi004", "The thece to monitor key usage by etsi 004",
138  "ns3::QKDKeyManagerSystemApplication::KeyServedEtsi004")
139 
140  .AddTraceSource ("DropKMSRequest", "Drop a request from the queue disc",
142  "ns3::QKDKeyManagerSystemApplication::TracedCallback")
143 
144  .AddTraceSource ("ProvidedQoSResponse", "Provide QoS response to key material request",
146  "ns3::QKDKeyManagerSystemApplication::ProvidedQoSResponse")
147  ;
148  return tid;
149 }
150 
152 
154 {
155  NS_LOG_FUNCTION (this);
156  m_totalRx = 0;
157  m_kms_id = ++nKMS+8000;
158  m_kms_key_id = 0;
159  connectedToSDN = false;
160 
161  m_queueLogic = CreateObject<QKDKMSQueueLogic> ();
162  m_random = CreateObject<UniformRandomVariable> ();
163  m_sdnSupportEnabled = false;
164 
165 }
166 
168 {
169  NS_LOG_FUNCTION (this);
170 }
171 
172 uint32_t
174  return m_kms_id;
175 }
176 
177 uint32_t
179 {
180  NS_LOG_FUNCTION (this);
181  return m_totalRx;
182 }
183 
184 std::map<Ptr<Socket>, Ptr<Socket> >
186 {
187  NS_LOG_FUNCTION (this);
188  return m_socketPairs;
189 }
190 
191 
192 
203 {
204  NS_LOG_FUNCTION (this);
205  return m_sinkSocket;
206 }
207 
208 void
210 {
211  NS_LOG_FUNCTION (this << type << socket);
212  m_sinkSocket = socket;
213 }
214 
215 void
217 {
218  NS_LOG_FUNCTION (this);
219  m_sinkSocket = 0;
220  m_socketPairs.clear ();
222 }
223 
224 void
226 {
227  NS_LOG_FUNCTION (this << s << from << InetSocketAddress::ConvertFrom(from).GetIpv4 ());
229 
230  std::map<Ptr<Socket>, Ptr<Socket> >::iterator i = m_socketPairs.find ( s );
231  if (i == m_socketPairs.end ()){
232 
233  Ptr<Socket> sendSocket;
234 
235  if (s->GetSocketType () != Socket::NS3_SOCK_STREAM &&
237  {
238  NS_LOG_FUNCTION("Create UDP socket!");
240  }else{
241  NS_LOG_FUNCTION("Create TCP socket!");
243  }
244  sendSocket->ShutdownRecv ();
245  sendSocket->SetConnectCallback (
249 
250  InetSocketAddress receiveAddress = InetSocketAddress (
251  InetSocketAddress::ConvertFrom(from).GetIpv4 (),
252  82//InetSocketAddress::ConvertFrom(from).GetPort ()
253  );
254  sendSocket->Bind ();
255  sendSocket->Connect ( receiveAddress );
256 
257  m_socketPairs.insert( std::make_pair( s , sendSocket) );
258 
259  NS_LOG_FUNCTION(this
260  << "Create the response socket " << sendSocket
261  << " from KMS to " << InetSocketAddress::ConvertFrom(from).GetIpv4 ()
262  << " and port " << InetSocketAddress::ConvertFrom(from).GetPort ()
263  );
264  }
265 }
266 
267 void
269 {
270  NS_LOG_FUNCTION (this
271  << s
272  << from
273  << InetSocketAddress::ConvertFrom(from).GetIpv4 ()
275  );
276 
278 
279  //Check is it necessary to create response socket
281  std::map<Ipv4Address, std::pair<Ptr<Socket>, Ptr<Socket> > >::iterator it = m_socketPairsKMS.find(destKMS);
282  if ( it != m_socketPairsKMS.end () )
283  it->second.first = s; //Set receiving socket
284 
285  CheckSocketsKMS(destKMS);
286 
287 }
288 
289 void
291 {
292  NS_LOG_FUNCTION (this
293  << s
294  << from
295  << InetSocketAddress::ConvertFrom(from).GetIpv4 ()
297  );
298 
300 }
301 
302 
303 void
305 {
306  NS_LOG_FUNCTION (this << socket);
307  NS_LOG_FUNCTION (this << "QKDKeyManagerSystemApplication Connection succeeded");
308 
309  std::map<Ptr<Socket>, Ptr<Packet> >::iterator j;
310  for (j = m_packetQueues.begin (); !(j == m_packetQueues.end ());){
311  if(j->first == socket){
312  uint32_t response = j->first->Send(j->second);
313  response = j->first->Send(j->second);
314  m_txTrace (j->second);
315  m_packetQueues.erase (j++);
316  NS_LOG_FUNCTION(this << j->first << "Sending packet from the queue!" << response );
317  }else{
318  ++j;
319  }
320  }
321 }
322 
323 void
325 {
326  NS_LOG_FUNCTION (this << socket);
327  NS_LOG_FUNCTION (this << "QKDKeyManagerSystemApplication KMSs Connection succeeded");
328 }
329 
330 void
332 {
333  NS_LOG_FUNCTION (this << socket);
334  NS_LOG_FUNCTION (this << "QKDKeyManagerSystemApplication, Connection Failed");
335 }
336 
337 void
339 {
340  NS_LOG_FUNCTION (this << socket);
341  NS_LOG_FUNCTION (this << "QKDKeyManagerSystemApplication, Connection Failed");
342 }
343 
344 void
346 {
347  NS_LOG_FUNCTION (this);
348 }
349 
350 void
352 {
353  NS_LOG_FUNCTION (this);
354 }
355 
356 void
358 {
359  NS_LOG_FUNCTION (this << socket << m_sendSocketToSDN);
360  NS_LOG_FUNCTION (this << "QKDKeyManagerSystemApplication KMS-SDN Connection succeeded");
361  connectedToSDN = true;
362 
363  if(socket == m_sendSocketToSDN){
364  NS_LOG_FUNCTION(this << "Check packets in queue!");
365  std::map<Ptr<Socket>, Ptr<Packet> >::iterator j;
366  for (j = m_packetQueuesToSDN.begin (); !(j == m_packetQueuesToSDN.end ());){
367  //it can happen that packet was not sent because socket was not connected
368  if(j->first == socket || !j->first){
369  uint32_t response = m_sendSocketToSDN->Send(j->second);
370  m_packetQueuesToSDN.erase (j++);
371  NS_LOG_FUNCTION(this << m_sendSocketToSDN << "Sending packet from the queue to SDN!" << response );
372  }else{
373  ++j;
374  }
375  }
376  }
377 }
378 
379 void
381 {
382  NS_LOG_FUNCTION (this << socket);
383  NS_LOG_FUNCTION (this << "QKDKeyManagerSystemApplication KMS-SDN Connection failed");
384 }
385 
386 void
388 {
389  NS_LOG_FUNCTION (this);
390 }
391 
392 void
394 {
395  NS_LOG_FUNCTION (this << socket);
396 }
397 
398 void
400 {
401  NS_LOG_FUNCTION (this << socket);
402 }
403 
404 void
406 {
407  NS_LOG_FUNCTION (this << socket);
408 }
409 
410 void
412 {
413  NS_LOG_FUNCTION (this << socket);
414 }
415 
416 void
418 {
419  NS_LOG_FUNCTION (this << socket);
420 }
421 
422 void
424 {
425  NS_LOG_FUNCTION (this << socket);
426 }
427 
428 void
430 {
431  NS_LOG_FUNCTION( this << socket);
432 
433  std::map<Ptr<Socket>, Ptr<Socket> >::iterator socketPair = m_socketPairs.find ( socket );
434  if (socketPair != m_socketPairs.end ()){
435 
436  Ptr<Socket> sendingSocket = socketPair->second;
437  //check if socket is connected
438  //https://www.nsnam.org/doxygen/classns3_1_1_socket.html#a78a3c37a539d2e70869bb82cc60fbb09
439  Address connectedAddress;
440 
441  //send the packet only if connected!
442  if(sendingSocket->GetPeerName(connectedAddress) == 0){
443  sendingSocket->Send(packet);
444  m_txTrace (packet);
445  NS_LOG_FUNCTION(this << packet->GetUid() << "sent via socket " << sendingSocket);
446 
447  //otherwise wait in the queue
448  }else{
449  m_packetQueues.insert( std::make_pair( sendingSocket , packet) );
450  NS_LOG_FUNCTION(this << packet->GetUid() << "enqued for socket " << sendingSocket);
451  }
452  }
453 }
454 
455 void
457 {
458  NS_LOG_FUNCTION( this << socket );
459 
460  std::map<Ipv4Address, std::pair<Ptr<Socket>, Ptr<Socket> > >::iterator it;
461  for ( it = m_socketPairsKMS.begin (); !(it == m_socketPairsKMS.end ()); it++ )
462  //we do not have info about KMS destination address ?
463  if ( it->second.first == socket )
464  {
465  Ptr<Socket> sendingSocket = it->second.second;
466  sendingSocket->Send(packet);
467  NS_LOG_FUNCTION( this << "Packet ID" << packet->GetUid() << "Sending socket" << sendingSocket );
468  }
469 }
470 
471 void
473 {
474  NS_LOG_FUNCTION( this << m_local << kmsDstAddress );
475 
476  //Local KMS should create socket to send data to peer KMS
477  //Local KMS should check if the socket for this connection already exists?
478  //Local KMS can have connections to multiple KMS systems - neighbor and distant KMSs
479  std::map<Ipv4Address, std::pair<Ptr<Socket>, Ptr<Socket> > >::iterator i = m_socketPairsKMS.find ( kmsDstAddress );
480 
481  if (i == m_socketPairsKMS.end ()){
482  NS_FATAL_ERROR ( this << "No connection between KMS defined!"); //@toDo: include HTTP response!
483  }else{
484 
485  std::pair<Ptr<Socket>, Ptr<Socket> > pair = i->second;
486  if(!pair.second){
487 
488  NS_LOG_FUNCTION(this << "Let's create a new send socket to reach KMS!");
489 
490  Ptr<Socket> sendSocket;
491  Ptr<Socket> sinkSocket = pair.first;
492 
493  if (sinkSocket->GetSocketType () != Socket::NS3_SOCK_STREAM &&
494  sinkSocket->GetSocketType () != Socket::NS3_SOCK_SEQPACKET)
495  {
496  NS_LOG_FUNCTION("Create UDP socket!");
498  }else{
499  NS_LOG_FUNCTION("Create TCP socket!");
501  }
502  sendSocket->ShutdownRecv ();
503  sendSocket->SetConnectCallback (
507 
508  InetSocketAddress peerAddress = InetSocketAddress (
509  kmsDstAddress,
510  8080
511  );
512  sendSocket->Bind ();
513  sendSocket->Connect ( peerAddress );
514 
515  //update socket pair entry
516  i->second.second = sendSocket;
517 
518  NS_LOG_FUNCTION(this
519  << "Create the send socket " << sendSocket
520  << " from KMS to KMS which is on " << kmsDstAddress
521  );
522 
523  }else{
524  NS_LOG_FUNCTION(this << "Socket to peer KMS exist. No action required");
525  }
526 
527  }
528 }
529 
532 {
533  NS_LOG_FUNCTION( this << kmsDstAddress );
534  //Local KMS should create socket to send data to peer KMS
535  //Local KMS should check if the socket for this connection already exists?
536  //Local KMS can have connections to multiple KMS systems - neighbor and distant KMSs
537  std::map<Ipv4Address, std::pair<Ptr<Socket>, Ptr<Socket> > >::iterator i = m_socketPairsKMS.find ( kmsDstAddress );
538 
539  if (i == m_socketPairsKMS.end ()){
540 
541  NS_FATAL_ERROR ( this << "No connection between KMS defined!"); //@toDo: include HTTP response!
542  return NULL;
543 
544  } else {
545 
546  std::pair<Ptr<Socket>, Ptr<Socket> > pair = i->second;
547  NS_ASSERT (pair.first);
548  NS_ASSERT (pair.second);
549  Ptr<Socket> sendSocket = pair.second;
550 
551  return sendSocket;
552  }
553 }
554 
555 
556 void
558 {
559 
560  NS_LOG_FUNCTION (this << socket);
561 
562  Ptr<Packet> packet;
563  Address from;
564  while ((packet = socket->RecvFrom (from)))
565  {
566  if (packet->GetSize () == 0) break;
567 
568  m_totalRx += packet->GetSize ();
569  NS_LOG_FUNCTION (this << packet << "PACKETID: " << packet->GetUid() << " of size: " << packet->GetSize() );
570 
572  {
573  NS_LOG_FUNCTION(this << "At time " << Simulator::Now ().GetSeconds ()
574  << "s KMS received packet ID: "
575  << packet->GetUid () << " of "
576  << packet->GetSize () << " bytes from "
578  << " port " << InetSocketAddress::ConvertFrom (from).GetPort ()
579  << " total Rx " << m_totalRx << " bytes");
580  }
581 
582  m_rxTrace (packet, from);
583  PacketReceived (packet, from, socket);
584  }
585 }
586 
587 void
589 {
590  NS_LOG_FUNCTION (this << socket);
591 
592  Ptr<Packet> packet;
593  Address from;
594  while ((packet = socket->RecvFrom (from)))
595  {
596  if (packet->GetSize () == 0)
597  { //EOF
598  break;
599  }
600 
601  m_totalRxKMSs += packet->GetSize ();
602  NS_LOG_FUNCTION (this << packet << "PACKETID: " << packet->GetUid() << " of size: " << packet->GetSize() );
603 
605  {
606  NS_LOG_FUNCTION(this << "At time " << Simulator::Now ().GetSeconds ()
607  << "s KMS received packet ID: "
608  << packet->GetUid () << " of "
609  << packet->GetSize () << " bytes from KMS "
611  << " port " << InetSocketAddress::ConvertFrom (from).GetPort ()
612  << " total Rx " << m_totalRx << " bytes");
613  }
614 
615  m_rxTraceKMSs (packet, from);
616  PacketReceivedKMSs (packet, from, socket);
617  }
618 }
619 
620 void
622 {
623  NS_LOG_FUNCTION (this << socket);
624 
625  Ptr<Packet> packet;
626  Address from;
627  while ((packet = socket->RecvFrom (from)))
628  {
629  if (packet->GetSize () == 0)
630  { //EOF
631  break;
632  }
633 
634  m_totalRxKMSs += packet->GetSize ();
635  NS_LOG_FUNCTION (this << packet << "PACKETID: " << packet->GetUid() << " of size: " << packet->GetSize() );
636 
638  {
639  NS_LOG_FUNCTION(this << "At time " << Simulator::Now ().GetSeconds ()
640  << "s KMS received packet ID: "
641  << packet->GetUid () << " of "
642  << packet->GetSize () << " bytes from KMS "
644  << " port " << InetSocketAddress::ConvertFrom (from).GetPort ()
645  << " total Rx " << m_totalRx << " bytes");
646 
647  PacketReceivedSDN(packet, from, socket);
648  m_rxTraceSDN (packet, from);
649  }
650 
651  }
652 }
653 void
655 {
656  std::string receivedStatus = p->ToString();
657  NS_LOG_FUNCTION ( this << "\n\n\n" << p->GetUid() << p->GetSize() << receivedStatus << from );
658 
659  Ptr<Packet> buffer;
660  if (receivedStatus.find("Fragment") != std::string::npos) {
661  auto itBuffer = m_bufferKMS.find (from);
662  if (itBuffer == m_bufferKMS.end ()){
663  itBuffer = m_bufferKMS.insert (
664  std::make_pair (from, Create<Packet> (0))
665  ).first;
666  }
667  buffer = itBuffer->second;
668  buffer->AddAtEnd (p);
669  }else{
670  NS_LOG_FUNCTION(this << "Full packet received!");
671  buffer = p;
672  }
673 
675  HTTPMessage request;
676 
677  //copy buffer payload to string
678  uint8_t *b1 = new uint8_t[buffer->GetSize ()];
679  buffer->CopyData(b1, buffer->GetSize ());
680  std::string requestString = std::string((char*)b1);
681  delete[] b1;
682 
683 
684  //parse HTTP message
685  parser.Parse(&request, requestString);
686  if(request.IsFragmented() || request.GetStatusMessage() == "Undefined")
687  {
688  NS_LOG_FUNCTION(this << "HTTP Content Parsed after merge with buffer: " << request.ToString() << "\n ***IsFragmented:" << request.IsFragmented() << "\n\n\n\n");
689  }else{
690  NS_LOG_FUNCTION(this << "Full packet received:" << request.ToString());
691  }
692 
693  while (buffer->GetSize () >= request.GetSize())
694  {
695  NS_LOG_DEBUG ("Parsing packet pid(" << p->GetUid() << ") of size " << request.GetSize () << " from buffer of size " << buffer->GetSize ());
696  Ptr<Packet> completePacket = buffer->CreateFragment (0, static_cast<uint32_t> (request.GetSize () ));
697 
698  uint8_t *b2 = new uint8_t[completePacket->GetSize ()];
699  completePacket->CopyData(b2, completePacket->GetSize ());
700  std::string s2 = std::string((char*)b2);
701 
702  HTTPMessage request2;
703  parser.Parse(&request2, s2);
704  delete[] b2;
705 
706  if(request2.IsFragmented() == false){
707  buffer->RemoveAtStart (static_cast<uint32_t> (request2.GetSize () ));
708  ProcessRequest(request2, completePacket, socket);
709  }
710  NS_LOG_FUNCTION(this << "Croped HTTP message: " << request2.ToString());
711  NS_LOG_FUNCTION(this << "Remains in the buffer " << buffer->GetSize () );
712  break;
713 
714  }
715 }
716 
717 void
719 {
720  NS_LOG_FUNCTION ( this << p->GetUid() << p->GetSize() << from );
721  std::string receivedStatus = p->ToString();
722  NS_LOG_FUNCTION ( this << "\n\n\n" << p->GetUid() << p->GetSize() << receivedStatus << from );
723 
724  Ptr<Packet> buffer;
725  if (receivedStatus.find("Fragment") != std::string::npos) {
726  auto itBuffer = m_bufferKMS.find (from);
727  if (itBuffer == m_bufferKMS.end ()){
728  itBuffer = m_bufferKMS.insert (
729  std::make_pair (from, Create<Packet> (0))
730  ).first;
731  }
732  buffer = itBuffer->second;
733  buffer->AddAtEnd (p);
734  }else{
735  NS_LOG_FUNCTION(this << "Full packet received!");
736  buffer = p;
737  }
738 
740  HTTPMessage request;
741 
742  //copy buffer payload to string
743  uint8_t *b1 = new uint8_t[buffer->GetSize ()];
744  buffer->CopyData(b1, buffer->GetSize ());
745  std::string requestString = std::string((char*)b1);
746  delete[] b1;
747 
748  //parse HTTP message
749  parser.Parse(&request, requestString);
750  if(request.IsFragmented() || request.GetStatusMessage() == "Undefined")
751  {
752  NS_LOG_FUNCTION(this << "HTTP Content Parsed after merge with buffer: " << request.ToString() << "\n ***IsFragmented:" << request.IsFragmented() << "\n\n\n\n");
753  }else{
754  NS_LOG_FUNCTION(this << "Full packet received:" << request.ToString());
755  }
756 
757  while (buffer->GetSize () >= request.GetSize())
758  {
759  NS_LOG_DEBUG ("Parsing packet pid(" << p->GetUid() << ") of size " << request.GetSize () << " from buffer of size " << buffer->GetSize ());
760  Ptr<Packet> completePacket = buffer->CreateFragment (0, static_cast<uint32_t> (request.GetSize () ));
761 
762  uint8_t *b2 = new uint8_t[completePacket->GetSize ()];
763  completePacket->CopyData(b2, completePacket->GetSize ());
764  std::string s2 = std::string((char*)b2);
765 
766  HTTPMessage request2;
767  parser.Parse(&request2, s2);
768  delete[] b2;
769 
770  if(request2.IsFragmented() == false){
771  buffer->RemoveAtStart (static_cast<uint32_t> (request2.GetSize () ));
772  ProcessPacketKMSs(request2, completePacket, socket);
773  }
774  NS_LOG_FUNCTION(this << "Croped HTTP message: " << request2.ToString());
775  NS_LOG_FUNCTION(this << "Remains in the buffer " << buffer->GetSize () );
776  break;
777  }
778 }
779 
780 
781 void
783 {
784  NS_LOG_FUNCTION ( this << p->GetUid() << p->GetSize() << from );
785  std::string receivedStatus = p->ToString();
786  NS_LOG_FUNCTION ( this << "\n\n\n" << p->GetUid() << p->GetSize() << receivedStatus << from );
787 
788  Ptr<Packet> buffer;
789  if (receivedStatus.find("Fragment") != std::string::npos) {
790  auto itBuffer = m_bufferKMS.find (from);
791  if (itBuffer == m_bufferKMS.end ()){
792  itBuffer = m_bufferKMS.insert (
793  std::make_pair (from, Create<Packet> (0))
794  ).first;
795  }
796  buffer = itBuffer->second;
797  buffer->AddAtEnd (p);
798  }else{
799  NS_LOG_FUNCTION(this << "Full packet received!");
800  buffer = p;
801  }
802 
804  HTTPMessage request;
805 
806  //copy buffer payload to string
807  uint8_t *b1 = new uint8_t[buffer->GetSize ()];
808  buffer->CopyData(b1, buffer->GetSize ());
809  std::string requestString = std::string((char*)b1);
810  delete[] b1;
811 
812  //parse HTTP message
813  parser.Parse(&request, requestString);
814  if(request.IsFragmented() || request.GetStatusMessage() == "Undefined")
815  {
816  NS_LOG_FUNCTION(this << "HTTP Content Parsed after merge with buffer: " << request.ToString() << "\n ***IsFragmented:" << request.IsFragmented() << "\n\n\n\n");
817  }else{
818  NS_LOG_FUNCTION(this << "Full packet received:" << request.ToString());
819  }
820 
821  NS_LOG_FUNCTION(this << "aaaaa: \t" << buffer->GetSize() << request.GetSize());
822 
823  while (buffer->GetSize () >= request.GetSize())
824  {
825  NS_LOG_DEBUG ("Parsing packet pid(" << p->GetUid() << ") of size " << request.GetSize () << " from buffer of size " << buffer->GetSize ());
826  Ptr<Packet> completePacket = buffer->CreateFragment (0, static_cast<uint32_t> (request.GetSize () ));
827 
828  uint8_t *b2 = new uint8_t[completePacket->GetSize ()];
829  completePacket->CopyData(b2, completePacket->GetSize ());
830  std::string s2 = std::string((char*)b2);
831 
832  HTTPMessage request2;
833  parser.Parse(&request2, s2);
834  delete[] b2;
835 
836  if(request2.IsFragmented() == false){
837  buffer->RemoveAtStart (static_cast<uint32_t> (request2.GetSize () ));
838 
839  NS_LOG_FUNCTION(this << " xxxxx: " << request2.GetUri() );
840  if(request2.GetUri() != ""){
841  ProcessRequestSDN(request2, completePacket, socket);
842  }else{
843  ProcessResponseSDN(request2, completePacket, socket);
844  }
845  }
846  NS_LOG_FUNCTION(this << "Croped HTTP message: " << request2.ToString());
847  NS_LOG_FUNCTION(this << "Remains in the buffer " << buffer->GetSize () );
848  break;
849 
850  }
851 }
852 
853 
862 void
863 QKDKeyManagerSystemApplication::StartApplication (void) // Called at time specified by Start
864 {
865  NS_LOG_FUNCTION(this);
869 }
870 
871 void
872 QKDKeyManagerSystemApplication::PrepareSinkSocket (void) // Called at time specified by Start
873 {
874  NS_LOG_FUNCTION (this);
875 
876  // Create the sink socket if not already
877  if (!m_sinkSocket){
879  NS_LOG_FUNCTION (this << "Create the sink KMS socket!" << m_sinkSocket);
880  }
881 
882  NS_LOG_FUNCTION (this << "Sink KMS socket listens on " << m_local << " and port " << m_port << " for APP requests" );
884 
885  m_sinkSocket->Bind (sinkAddress);
886  m_sinkSocket->Listen ();
890  MakeNullCallback<bool, Ptr<Socket>, const Address &> (),
892  );
896  );
897 }
898 
899 void
901 
902  NS_LOG_FUNCTION(this
907  );
908 
909  if(m_sdnControllerAddress.IsInvalid() == 0) {
910 
911  if(!m_sendSocketToSDN){
912  Address sdnAddr = InetSocketAddress(
915  );
924  m_sendSocketToSDN->Connect ( sdnAddr );
925  NS_LOG_FUNCTION (this << "Create new APP socket " << m_sendSocketToSDN << " to reach SDN Controller!");
926  }else{
927  NS_LOG_FUNCTION (this << "Socket to reach SDN Controller exists!" << m_sendSocketToSDN);
928  }
929 
930  if(!m_sinkSocketFromSDN){
931 
932  // Create the sink socket if not already
934  NS_LOG_FUNCTION (this << "Create the sink KMS socket!" << m_sinkSocketFromSDN);
935 
937  NS_LOG_FUNCTION (this
938  << "Sink KMS socket listens on "
939  << m_local
940  << " and port " << sdnPort
941  << " for SDN packets"
942  );
943  // InetSocketAddress sinkAddress = InetSocketAddress (m_local, sdnPort);
944  InetSocketAddress sinkAddress = InetSocketAddress (Ipv4Address::GetAny (), sdnPort);
945 
946  m_sinkSocket->Bind (sinkAddress);
947  m_sinkSocket->Listen ();
951  MakeNullCallback<bool, Ptr<Socket>, const Address &> (),
953  );
957  );
958 
959  }
960 
961  }
962 }
963 
964 void
965 QKDKeyManagerSystemApplication::StopApplication (void) // Called at time specified by Stop
966 {
967  NS_LOG_FUNCTION (this);
968 
969  std::map<Ptr<Socket>, Ptr<Socket> >::iterator j;
970  for (
971  j = m_socketPairs.begin ();
972  !(j == m_socketPairs.end ());
973  j++
974  ){
975  if(j->first) {
976  j->first->Close();
977  j->first->SetRecvCallback (MakeNullCallback<void, Ptr<Socket> > ());
978  }
979  if(j->second) j->second->Close();
980  }
981 
982  if (m_sinkSocket)
983  {
984  m_sinkSocket->Close ();
986  }
987 }
988 
989 uint32_t
991 {
992  NS_LOG_FUNCTION(this << "Scheduling new event in an attempt to fill association buffer " << ksid << " ...");
993  uint32_t scheduleID {0};
994  EventId event;
995  if(action == "CheckAssociation"){
997  //scheduleID = event.GetUid();
998  //m_scheduledChecks.insert( std::make_pair( scheduleID , event) );
999  NS_LOG_FUNCTION(this << "Event successfully scheduled!");
1000  }else
1001  NS_FATAL_ERROR(this << "Invalid action as the function input recived " << action);
1002 
1003  return scheduleID;
1004 }
1005 
1014 void
1016 {
1017  NS_LOG_FUNCTION (this);
1018 
1019  std::string ksid;
1020  std::string slave_SAE_ID;
1022  std::vector<std::string> uriParams = ProcessUriParams(headerIn.GetUri());
1023 
1024  if(
1025  uriParams.size() > 3 &&
1026  uriParams[1] == "api" &&
1027  uriParams[2] == "v1" &&
1028  uriParams[3] == "keys"
1029  ){
1030 
1031  std::string receivedAddressStr (uriParams[0]);
1032  Ipv4Address receivedAddress = Ipv4Address(receivedAddressStr.c_str()); //string to IPv4Address
1033  NS_LOG_FUNCTION(this << "received address" << receivedAddressStr << receivedAddress);
1034  if(receivedAddress != GetAddress()){
1035  NS_FATAL_ERROR ( this << "The request is not for me!\t" << receivedAddress << "\t" << GetAddress() << "\t" << headerIn.GetUri());
1036  //@toDo: redirect to top-level KMS
1037  }
1038  slave_SAE_ID = uriParams[4];
1039  ksid = uriParams[4];
1040  requestType = FetchRequestType(uriParams[5]);
1041  }
1042 
1043  NS_LOG_FUNCTION(this << "uri:" << headerIn.GetUri());
1044  NS_LOG_FUNCTION (this << "slave_SAE_ID: " << slave_SAE_ID << "requestType: " << requestType );
1045  if(requestType == ETSI_QKD_014_GET_STATUS){ //Process status request
1046 
1047  /*********************************
1048  * PROCESS GET_STATUS
1049  *********************************/
1050 
1051  NS_LOG_FUNCTION ( this << "Fetch status from QKD buffers for connection to destination node" << slave_SAE_ID );
1052 
1053  QKDApplicationEntry appConnection = GetApplicationConnectionDetails( ksid );
1054  NS_ASSERT(appConnection.IsValid());
1055  appConnection.PrintRegistryInfo();
1056 
1058  NS_ASSERT(conn.IsValid());
1059  conn.PrintRegistryInfo();
1060 
1061  Ipv4Address srcKmsAddress = GetAddress();
1062  std::ostringstream srcKmsAddressTemp;
1063  srcKmsAddress.Print(srcKmsAddressTemp); //IPv4Address to string
1064  std::string srcKME = srcKmsAddressTemp.str ();
1065 
1066  Ipv4Address dstKmsAddress = conn.GetDestinationKmsAddress();
1067  std::ostringstream dstKmsAddressTemp;
1068  dstKmsAddress.Print(dstKmsAddressTemp); //IPv4Address to string
1069  std::string dstKME = dstKmsAddressTemp.str ();
1070 
1071  //Status data format (ETSI014) of response!
1072  nlohmann::json j;
1073  j["source_KME_ID"] = srcKME;
1074  j["target_KME_ID"] = dstKME;
1075  j["master_SAE_ID"] = GetNode()->GetId();
1076  j["slave_SAE_ID"] = slave_SAE_ID;
1077  j["key_size"] = m_defaultKeySize; //conn.bufferAlice->GetKeySize();
1078 
1079  Ptr<QKDBuffer> buffer = conn.GetSourceBuffer();
1080  if(buffer){
1081  j["stored_key_count"] = buffer->GetKeyCountBit();
1082  j["max_key_count"] = buffer->GetMaxKeyCount();
1083  }else{
1084  j["stored_key_count"] = 0;
1085  j["max_key_count"] = 0;
1086  }
1087 
1088  j["max_key_per_request"] = GetMaxKeyPerRequest();
1089  j["max_key_size"] = m_maxKeySize; //conn.bufferAlice->GetMaxKeySizeBit();
1090  j["min_key_size"] = m_minKeySize; //conn.bufferAlice->GetMinKeySizeBit();
1091  j["max_SAE_ID_count"] = 0;
1092  NS_LOG_FUNCTION( this << "json_response:" << j.dump() );
1093  std::string msg = j.dump();
1094 
1095  //create packet
1096  HTTPMessage httpMessage;
1097  httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok, msg, {
1098  {"Content-Type", "application/json; charset=utf-8"},
1099  {"Request URI", headerIn.GetUri() }
1100  });
1101  std::string hMessage = httpMessage.ToString();
1102  Ptr<Packet> packet = Create<Packet> (
1103  (uint8_t*) (hMessage).c_str(),
1104  hMessage.size()
1105  );
1106  NS_ASSERT (packet);
1107 
1108  NS_LOG_FUNCTION (this << "Sending Response to ETSI_QKD_014_GET_STATUS\n PacketID: " << packet->GetUid() << " of size: " << packet->GetSize() << hMessage );
1109  SendToSocketPair(socket, packet);
1110 
1111  }else if(requestType == ETSI_QKD_014_GET_KEY){
1112 
1113  /*********************************
1114  * PROCESS GET_KEY
1115  ********************************/
1116 
1117  NS_LOG_FUNCTION ( this << "Processing ETSI 014 get_key request" );
1118  uint32_t keyNumber = 1; //Default value
1119  uint32_t keySize = m_defaultKeySize; //Default value
1120  nlohmann::json jrequest; //JSON request structure
1121  nlohmann::json errorDataStructure; //JSON error response
1122 
1123  QKDApplicationEntry appConnection = GetApplicationConnectionDetails( ksid );
1124  NS_ASSERT(appConnection.IsValid());
1125  appConnection.PrintRegistryInfo();
1126 
1128  NS_ASSERT(conn.IsValid());
1129  conn.PrintRegistryInfo();
1130 
1131  NS_LOG_FUNCTION(this << conn.GetId() << headerIn.GetUri());
1132 
1133  if(headerIn.GetMethod() == HTTPMessage::HttpMethod::GET){
1134  int k = 5;
1135  while(k < int(uriParams.size())){ //Read number and size from URI
1136  if(uriParams[k] == "number")
1137  keyNumber = std::stoi(uriParams[k+1]);
1138  else if(uriParams[k] == "size")
1139  keySize = std::stoi(uriParams[k+1]); //Key size in bits!
1140  k += 2;
1141  }
1142  jrequest = {{"number", keyNumber}, {"size", keySize}}; //Create jrequest based on URI
1143 
1144  }else if(headerIn.GetMethod() == HTTPMessage::HttpMethod::POST){
1145  std::string payload = headerIn.GetMessageBodyString(); //Read payload
1146  try{ //Try parse JSON
1147  jrequest = nlohmann::json::parse(payload);
1148  if (jrequest.contains("number"))
1149  keyNumber = jrequest["number"];
1150  if (jrequest.contains("size"))
1151  keySize = uint32_t(jrequest["size"]); //Key size in bits!
1152  }catch(...){
1153  NS_FATAL_ERROR( this << "JSON parse error of the received payload: " << payload << "\t" << payload.length() );
1154  }
1155 
1156  }else
1157  NS_FATAL_ERROR(this << "Invalid HTTP request method" << headerIn.GetMethod()); //@toDo: include HTTP response?
1158 
1159  errorDataStructure = Check014GetKeyRequest(jrequest, conn); //Check get_key request!
1160  if(!errorDataStructure.empty()){ //Respond with error!
1161 
1162  NS_LOG_FUNCTION( this << "Get key request error" << errorDataStructure.dump() );
1163  HTTPMessage::HttpStatus statusCode = HTTPMessage::HttpStatus::BadRequest; //Response status code!
1164  if(errorDataStructure.contains("message")){
1165  if(errorDataStructure["message"] == "keys are being transformed"){
1166  statusCode = HTTPMessage::HttpStatus::ServiceUnavailable;
1167  conn.GetSourceBuffer()->RecordTargetSize(keySize);
1168  TransformKeys(keySize, keyNumber, UUID{ksid} ); //Transform keys
1169  }else if(errorDataStructure["message"] == "insufficient amount of key material")
1170  statusCode = HTTPMessage::HttpStatus::ServiceUnavailable;
1171  }
1172  errorDataStructure["ksid"] = ksid;
1173  std::string msg = errorDataStructure.dump();
1174 
1175  //create packet
1176  HTTPMessage httpMessage;
1177  httpMessage.CreateResponse(statusCode, msg, {
1178  {"Content-Type", "application/json; charset=utf-8"},
1179  {"Request URI", headerIn.GetUri() }
1180  });
1181  std::string hMessage = httpMessage.ToString();
1182  Ptr<Packet> packet = Create<Packet> (
1183  (uint8_t*) (hMessage).c_str(),
1184  hMessage.size()
1185  );
1186  NS_ASSERT (packet);
1187 
1188  NS_LOG_FUNCTION (this << "1185 Sending Response to ETSI_QKD_014_GET_KEY\n PacketID: " << packet->GetUid() << " of size: " << packet->GetSize() << hMessage );
1189  SendToSocketPair(socket, packet);
1190 
1191  }else{ //Respond to get_key request!
1192 
1193  std::vector<Ptr<QKDKey>> keys {}; //Vector of QKD keys!
1194  Ptr<QKDBuffer> buffer = conn.GetSourceBuffer(); //Obtain the object of the corresponding QKD buffer!
1195  if(buffer){
1196  buffer->RecordTargetSize(keySize);
1197  for(uint32_t i = 0; i < keyNumber; i++){
1198  keys.push_back(buffer->FetchKeyBySize(keySize)); //Obtain keys!
1199  }
1200  }else {
1201  NS_FATAL_ERROR( this << "Buffer not found! ");
1202  }
1203 
1204  NS_ASSERT(keys.size() == keyNumber); //Unexpected error
1205  nlohmann::json jkeys = CreateKeyContainer(keys);
1206  jkeys["ksid"] = ksid;
1207  std::string msg = jkeys.dump();
1208  NS_LOG_FUNCTION( this << "json_response:" << msg );
1209 
1210  //@toDo: reserve these keys on peer KMS -> KMS to KMS reserve_keys
1211 
1212  //create packet
1213  HTTPMessage httpMessage;
1214  httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok, msg, {
1215  {"Content-Type", "application/json; charset=utf-8"},
1216  {"Request URI", headerIn.GetUri() }
1217  });
1218  std::string hMessage = httpMessage.ToString();
1219  Ptr<Packet> packet = Create<Packet> (
1220  (uint8_t*) (hMessage).c_str(),
1221  hMessage.size()
1222  );
1223  NS_ASSERT (packet);
1224 
1225  NS_LOG_FUNCTION( this << "1221 Sending Response to ETSI_QKD_014_GET_KEY\n PacketID: " << packet->GetUid() << " of size: " << packet->GetSize() << hMessage );
1226  SendToSocketPair(socket, packet);
1227 
1228  //FIRE TRACE SOURCES
1229  for(uint32_t i=0; i<keys.size(); i++){
1230  m_keyServedETSI014Trace(ksid, keys[i]);
1231  }
1232 
1233  m_keyServedTraceEmir (keyNumber * keySize);
1234  //m_keyServedTrace(dstSaeId, keySizeServed); //Record amount of served key to the end-user application
1235  //m_keyServedWithKSIDTrace(ksid, dstSaeId, keySizeServed); //Record amount of served key to the end-user application
1236  }
1237 
1238  }else if(requestType == ETSI_QKD_014_GET_KEY_WITH_KEY_IDS){
1239 
1240  /*********************************
1241  * PROCESS GET_KEY_WITH_KEYIDs
1242  *********************************/
1243 
1244  NS_LOG_FUNCTION( this << "Processing ETSI 014 get_key_with_key_ids request" );
1245 
1246  QKDApplicationEntry appConnection = GetApplicationConnectionDetails( ksid );
1247  NS_ASSERT(appConnection.IsValid());
1248  appConnection.PrintRegistryInfo();
1249 
1251  NS_ASSERT(conn.IsValid());
1252  conn.PrintRegistryInfo();
1253 
1254  std::string payload = headerIn.GetMessageBodyString(); //Read payload
1255  nlohmann::json jkeyIDs;
1256  try{
1257  jkeyIDs = nlohmann::json::parse(payload); //Parse packet payload to JSON structure
1258  }catch(...){
1259  NS_FATAL_ERROR( this << "JSON parse error!" );
1260  }
1261 
1262  std::vector<std::string> keyIDs; //Vector containing keyIDs
1263  for (nlohmann::json::iterator it = jkeyIDs["key_IDs"].begin(); it != jkeyIDs["key_IDs"].end(); ++it)
1264  keyIDs.push_back((it.value())["key_ID"]); //keyIDs read from JSON
1265 
1266  NS_LOG_FUNCTION( this << "Requested key with key IDs:" << keyIDs);
1267  //Fetch keys with defined keyIDs from buffer
1268  Ptr<QKDBuffer> buffer = conn.GetSourceBuffer();
1269  std::vector<Ptr<QKDKey>> keys {};
1270  if(buffer){
1271  for(uint32_t i = 0; i < keyIDs.size(); i++){
1272  Ptr<QKDKey> k = buffer->FetchKeyByID(keyIDs[i]);
1273  keys.push_back(k);
1274  if(!keys[i]){
1275  keys = {}; //Only complete acceptence or refusal supported for now!
1276  break;
1277  }
1278  }
1279  }else{
1280  NS_FATAL_ERROR( this << "No QKD key buffer defined!");
1281  }
1282 
1283  if(!keys.empty()){ //Respond to get_key_with_key_ids request
1284 
1285  uint32_t number = keys.size(); //number of keys
1286  uint32_t size = keys[0]->GetSizeInBits(); //size of key
1287 
1288  nlohmann::json jkeys = CreateKeyContainer(keys);
1289  NS_LOG_FUNCTION( this << "json_response:" << jkeys.dump() );
1290  std::string msg = jkeys.dump();
1291 
1292  //create packet
1293  HTTPMessage httpMessage;
1294  httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok, msg, {
1295  {"Content-Type", "application/json; charset=utf-8"},
1296  {"Request URI", headerIn.GetUri() }
1297  });
1298  std::string hMessage = httpMessage.ToString();
1299  Ptr<Packet> packet = Create<Packet> (
1300  (uint8_t*) (hMessage).c_str(),
1301  hMessage.size()
1302  );
1303  NS_ASSERT (packet);
1304 
1305  NS_LOG_FUNCTION (this << "Sending Response to ETSI_QKD_014_GET_KEY\n PacketID: " << packet->GetUid() << " of size: " << packet->GetSize() << hMessage );
1306  SendToSocketPair(socket, packet);
1307 
1308  //FIRE TRACE SOURCE
1309  for(uint32_t i=0; i<keys.size(); i++){
1310  m_keyServedETSI014Trace(ksid, keys[i]);
1311  }
1312 
1313  m_keyServedTraceEmir(number * size);
1314 
1315  }else{ //Respond with error massage
1316  nlohmann::json errorDataStructure = {{"messsage", "key access error"}}; //@toDo: response includes details: keyIds that are non existing
1317  std::string msg = errorDataStructure.dump();
1318 
1319  //create packet
1320  HTTPMessage httpMessage;
1321  httpMessage.CreateResponse(HTTPMessage::HttpStatus::BadRequest, msg, {
1322  {"Content-Type", "application/json; charset=utf-8"},
1323  {"Request URI", headerIn.GetUri() }
1324  });
1325  std::string hMessage = httpMessage.ToString();
1326  Ptr<Packet> packet = Create<Packet> (
1327  (uint8_t*) (hMessage).c_str(),
1328  hMessage.size()
1329  );
1330  NS_ASSERT (packet);
1331 
1332  NS_LOG_FUNCTION(this << "Sending Response to ETSI_QKD_014_GET_KEY\n PacketID: " << packet->GetUid() << " of size: " << packet->GetSize() << hMessage );
1333  SendToSocketPair(socket, packet);
1334  }
1335 
1336  } else if (requestType == ETSI_QKD_004_OPEN_CONNECT) {
1337 
1339  entry.socket = socket;
1340  entry.httpMessage = headerIn;
1341  entry.packet = packet;
1342  entry.ksid = ksid;
1343 
1344  if(m_queueLogic->Enqueue(entry) == false){
1345  Address adr;
1346  socket->GetPeerName(adr);
1348  Ipv4Address ipAdr = iaddr.GetIpv4();
1349  m_dropTrace(ipAdr, packet);
1350  }
1351  entry = m_queueLogic->Dequeue();
1353 
1354  } else if (requestType == ETSI_QKD_004_GET_KEY) {
1355 
1357  entry.socket = socket;
1358  entry.httpMessage = headerIn;
1359  entry.packet = packet;
1360  entry.ksid = ksid;
1361 
1362  /*
1363  Address adr;
1364  socket->GetPeerName(adr);
1365  InetSocketAddress iaddr = InetSocketAddress::ConvertFrom (adr);
1366  Ipv4Address ipAdr = iaddr.GetIpv4();
1367  NS_LOG_FUNCTION (this << "Sender IP address" << ipAdr);
1368 
1369  std::map<Ipv4Address, uint32_t>::iterator it = m_flagedIPAdr.find(ipAdr);
1370  if(it != m_flagedIPAdr.end() && it->second >= 2 && m_maliciousBlocking){
1371  m_dropTrace(ipAdr, packet);
1372  return; //Do not proceed to process this request!
1373  }
1374  NS_LOG_FUNCTION (this << "Sender IP address" << ipAdr << "\t maliciousCount:" << it->second);
1375  */
1376 
1377  if(m_queueLogic->Enqueue(entry) == false){
1378  std::cout << "packet dropped! \n";
1379 
1380  Address adr;
1381  socket->GetPeerName(adr);
1383  Ipv4Address ipAdr = iaddr.GetIpv4();
1384  m_dropTrace(ipAdr, packet);
1385  }
1386  entry = m_queueLogic->Dequeue();
1387  ProcessGetKey004Request(entry.ksid, entry.httpMessage, entry.socket);
1388 
1389  } else if (requestType == ETSI_QKD_004_CLOSE) {
1390  ProcessCloseRequest(ksid, headerIn, socket);
1391 
1392  } else if (requestType == STORE_PP_KEYS) {
1393 
1394  //Read payload
1395  std::string payload = headerIn.GetMessageBodyString();
1396  try {
1397 
1398  //Parse packet payload to JSON structure
1399  nlohmann::json payloadContent = nlohmann::json::parse(payload);
1400  std::string keyId = payloadContent["key_id"];
1401  std::string keyValue = payloadContent["key"];
1402  uint32_t srcNodeId = payloadContent["src_id"];
1403  uint32_t dstNodeId = payloadContent["dst_id"];
1404 
1405  NS_LOG_FUNCTION(this << "\nKeyID:\t" << keyId << "\n");
1406  //NS_LOG_FUNCTION(this << "\nKeyValue:\t" << keyValue << "\n");
1407 
1408  Ptr<QKDKey> newKey = Create<QKDKey> (keyId, keyValue);
1409  AddNewKey(newKey, srcNodeId, dstNodeId);
1410 
1411  m_newKeyGeneratedTrace(dstNodeId, newKey->GetSizeInBits());
1412  m_newKeyGeneratedTraceEmir(newKey->GetSizeInBits());
1413 
1414  } catch(...) {
1415  NS_LOG_FUNCTION( this << "JSON parse error!");
1416  }
1417 
1418  }
1419 }
1420 
1421 void
1423 {
1424  NS_LOG_FUNCTION (this);
1425  if(headerIn.GetUri() != "") //Process request!
1426  ProcessRequestKMS(headerIn, socket);
1427  else //Process response!
1428  ProcessResponseKMS(headerIn, packet, socket);
1429 }
1430 
1431 void
1433 {
1434  NS_LOG_FUNCTION( this << "Processing answer from SDN" );
1435 
1436  if(headerIn.GetStatusCode() == 200)
1437  {
1438  std::vector<std::string> uriParams = ProcessUriParams(headerIn.GetRequestUri());
1439  if(
1440  uriParams.size() > 3 &&
1441  uriParams[1] == "api" &&
1442  uriParams[2] == "v1" &&
1443  uriParams[3] == "keys" &&
1444  uriParams[5] == "register_qkd_link"
1445  ){
1446  NS_LOG_FUNCTION(this << "Processing register_qkd_link reponse!");
1447 
1448  std::string payload = headerIn.GetMessageBodyString();
1449  nlohmann::json sdnResponse;
1450  try{
1451 
1452  sdnResponse = nlohmann::json::parse(payload);
1453  double QKDLinkStatsUpdateInterval = 0;
1454  std::string keyAssociationIdString;
1455  uint32_t registrationAccepted = 0;
1456 
1457  if (sdnResponse.contains("accepted")) registrationAccepted = sdnResponse["accepted"];
1458  if (sdnResponse.contains("qkd_link_update_interval")) QKDLinkStatsUpdateInterval = sdnResponse["qkd_link_update_interval"];
1459  if (sdnResponse.contains("key_association_id")) keyAssociationIdString = sdnResponse["key_association_id"];
1460 
1461  NS_ASSERT(QKDLinkStatsUpdateInterval > 1);
1462  NS_LOG_FUNCTION(this << keyAssociationIdString << registrationAccepted << QKDLinkStatsUpdateInterval);
1463  UUID keyAssociationId = UUID{keyAssociationIdString};
1464 
1465  if(registrationAccepted){
1466 
1467  QKDKeyAssociationLinkEntry keyAssociation = GetKeyAssociationById( UUID{keyAssociationId} );
1468  NS_ASSERT(keyAssociation.IsValid());
1469  keyAssociation.PrintRegistryInfo();
1470  keyAssociation.SetUpdateStatusInterval(QKDLinkStatsUpdateInterval);
1471  SaveKeyAssociation(keyAssociation);
1472 
1473  NS_LOG_FUNCTION(this << "SDN approved registration of QKD LINK between nodes " << keyAssociationId);
1474  EventId event = Simulator::Schedule (
1475  Seconds(QKDLinkStatsUpdateInterval),
1477  this,
1478  keyAssociationId,
1479  QKDLinkStatsUpdateInterval
1480  );
1481 
1482  }else{
1483 
1484  NS_LOG_FUNCTION(this << "SDN FORBIDES registration of QKD LINK between nodes " << keyAssociationId);
1485 
1486  }
1487 
1488  }catch(...) {
1489  NS_FATAL_ERROR( this << "JSON parse error!" );
1490  }
1491 
1492  }
1493 
1494  //Status indicating error!
1495  }else{
1496 
1497  }
1498 }
1499 
1500 void
1502 {
1503  NS_LOG_FUNCTION(this << linkId << updatePeriod);
1504 
1505 
1506  QKDKeyAssociationLinkEntry keyAssociation = GetKeyAssociationById( linkId );
1507  NS_ASSERT(keyAssociation.IsValid());
1508  keyAssociation.PrintRegistryInfo();
1509 
1510  Ptr<QKDBuffer> buffer = keyAssociation.GetSourceBuffer();
1511  if(buffer){
1512 
1513  //Secret key rate generation (in bits per second) of the key association link.
1514  keyAssociation.SetSKR(buffer->GetAverageKeyGenerationRate());
1515 
1516  //Sum of all the application's bandwidth (in bits per second) on this particular key association link.
1517  keyAssociation.SetExpectedConsumption(buffer->GetAverageKeyConsumptionRate());
1518 
1519  //Effective secret key rate (in bits per second) generation of the key association link available after internal consumption
1520  double ratio = buffer->GetAverageKeyGenerationRate() - buffer->GetAverageKeyConsumptionRate();
1521  //if(ratio < 0) ratio = buffer->GetAverageKeyGenerationRate();
1522  //if ratio is negative, it means old keys are taken from the buffer (not from the newly secret key rate)
1523  keyAssociation.SetEffectiveSKR(ratio);
1524 
1525  SaveKeyAssociation(keyAssociation);
1526  }
1527 
1528  //Notify SDN Controller about the new QKD LINK
1529  //send the packet only if connected!
1531 
1532  nlohmann::json j;
1533  j["key_association_id"] = keyAssociation.GetId().string();
1534 
1535  //save to variable since GetSkr or other call sometimes return "null"
1536  //saving to variables convert these values to 0
1537  double skr = keyAssociation.GetSKR();
1538  NS_ASSERT(skr >=0 );
1539  j["qkdl_performance_skr"] = skr;
1540 
1541  double expectedConsumption = keyAssociation.GetExpectedConsumption();
1542  NS_ASSERT(expectedConsumption >=0 );
1543  j["qkdl_performance_expected_consumption"] = expectedConsumption;
1544 
1545  double eskr = keyAssociation.GetEffectiveSKR();
1546  NS_ASSERT(eskr >=0 );
1547  j["qkdl_performance_eskr"] = eskr;
1548 
1549  NS_LOG_FUNCTION( this << "Prepared JSON_PACKET_TO_SDN:" << j.dump() << skr << expectedConsumption << eskr );
1550 
1551  std::string msg = j.dump();
1552  HTTPMessage httpHead;
1553 
1555  std::ostringstream sdnAddressTemp;
1556  sdnAddress.Print(sdnAddressTemp); //IPv4Address to string
1557 
1558  std::ostringstream skmsAddressTemp;
1559  keyAssociation.GetDestinationKmsAddress().Print(skmsAddressTemp); //IPv4Address to string
1560  std::string skmsAddressString = skmsAddressTemp.str(); //Uri starts with destination KMS address
1561 
1562  std::string headerUri = "http://" + sdnAddressTemp.str ();
1563  headerUri += "/api/v1/keys/" + skmsAddressString + "/key_association_status";
1564 
1565  //Create packet
1566  HTTPMessage httpMessage;
1567  httpMessage.CreateRequest(headerUri, "POST", msg);
1568  std::string hMessage = httpMessage.ToString();
1569  Ptr<Packet> packet = Create<Packet> (
1570  (uint8_t*) (hMessage).c_str(),
1571  hMessage.size()
1572  );
1573  NS_ASSERT (packet);
1574 
1575  NS_LOG_FUNCTION (this << "Sending KEY_ASSOCIATION_STATUS to SDN CONTROLLER\n PacketID: "
1576  << packet->GetUid() << " of size: " << packet->GetSize()
1577  << hMessage
1578  );
1579  m_sendSocketToSDN->Send(packet);
1580 
1581  }
1582 
1583  if(m_sdnSupportEnabled){
1584 
1585  EventId event = Simulator::Schedule (
1586  Seconds(updatePeriod),
1588  this,
1589  keyAssociation.GetId(),
1590  keyAssociation.GetUpdateStatusInterval()
1591  );
1592  }
1593 
1594 
1595 }
1596 
1597 void
1599 {
1600  NS_LOG_FUNCTION( this << "Processing request from SDN" );
1601 
1602  //Status OK
1603  if(headerIn.GetStatusCode() == 200)
1604  {
1605  std::vector<std::string> uriParams = ProcessUriParams(headerIn.GetRequestUri());
1606  if(
1607  uriParams.size() > 3 &&
1608  uriParams[1] == "api" &&
1609  uriParams[2] == "v1" &&
1610  uriParams[3] == "keys" &&
1611  uriParams[5] == "register_qkd_link"
1612  ){
1613  NS_LOG_FUNCTION(this << "Processing register_qkd_link reponse!");
1614  }
1615 
1616  //Status indicating error!
1617  }else{
1618 
1619  }
1620 }
1621 
1622 std::vector<std::string>
1624 {
1625  NS_LOG_FUNCTION(this << s);
1626  std::vector<std::string> uriParams;
1627 
1628  if(s.length() > 0){
1629  std::string delimiter = "/";
1630  size_t pos = 0;
1631  std::string token;
1632  while ((pos = s.find(delimiter)) != std::string::npos) {
1633  token = s.substr(0, pos);
1634  if(token.length() > 0){
1635  uriParams.push_back(token);
1636  }
1637  s.erase(0, pos + delimiter.length());
1638  }
1639  if(s.length() > 0)
1640  uriParams.push_back(s);
1641 
1642  NS_LOG_FUNCTION(this << uriParams[0]);
1643  }
1644 
1645  return uriParams;
1646 }
1647 
1648 
1649 void
1651 {
1652  NS_LOG_FUNCTION( this << "Processing request from peer KMS ... " );
1654  std::vector<std::string> uriParams = ProcessUriParams(headerIn.GetUri());
1655 
1656  NS_LOG_FUNCTION( this << "krecA" << uriParams[0] << uriParams[1] << uriParams[2] << uriParams[3] );
1657  if(
1658  uriParams.size() > 3 && //@toDo for etsi 004 functions add KMS address in URI!
1659  uriParams[1] == "api" &&
1660  uriParams[2] == "v1" &&
1661  (uriParams[3] == "associations" ||
1662  uriParams[3] == "keys")
1663  ){
1664  requestType = FetchRequestType(uriParams[4]); // new_app, register, fill, transform_keys, close
1665  }
1666 
1667  if(requestType == NEW_APP)
1668  ProcessNewAppRequest(headerIn, socket);
1669  else if(requestType == REGISTER){
1670  std::string ksid = uriParams[5];
1671  NS_ASSERT ( !ksid.empty() );
1672  ProcessRegisterRequest(headerIn, ksid, socket);
1673  }else if(requestType == FILL){
1674  std::string ksid = uriParams[5];
1675  NS_ASSERT ( !ksid.empty() );
1676  ProcessAddKeysRequest(headerIn, socket, ksid); //Process proposal of keys!
1677  }else if(requestType == TRANSFORM_KEYS){
1678  ProcessTransformRequest(headerIn, socket);
1679  }else if(requestType == ETSI_QKD_004_KMS_CLOSE){
1680  std::string ksid = uriParams[5];
1681  NS_ASSERT ( !ksid.empty() );
1682  ProcessKMSCloseRequest(headerIn, socket, ksid);
1683  }else
1684  NS_FATAL_ERROR( this << "Invalid request made to this KMS!" );
1685 }
1686 
1687 void
1689 {
1690  NS_LOG_FUNCTION( this << "Processing peer KMS response" );
1691  Ipv4Address dstKMS = GetDestinationKmsAddress(socket);
1693 
1694  if(methodType == NEW_APP)
1695  ProcessNewAppResponse(headerIn, socket);
1696  else if(methodType == REGISTER)
1697  ProcessRegisterResponse(headerIn, socket);
1698  else if(methodType == FILL)
1699  ProcessAddKeysResponse(headerIn, socket);
1700  else if(methodType == TRANSFORM_KEYS)
1701  ProcessTransformResponse(headerIn, socket);
1702  else if(methodType == ETSI_QKD_004_KMS_CLOSE)
1703  ProcessKMSCloseResponse(headerIn, socket);
1704  else
1705  NS_FATAL_ERROR( this << "Invalid request method!" );
1706 
1707 }
1708 
1709 
1718 bool
1720 {
1721  NS_LOG_FUNCTION(this);
1722 
1723  //Get the address of the application node making this malicious request
1724  Address adr;
1725  socket->GetPeerName(adr);
1727  Ipv4Address ipAdr = iaddr.GetIpv4();
1728  NS_LOG_FUNCTION (this << "Sender IP address" << ipAdr);
1729 
1730  if(m_maliciousBlocking){
1731  std::map<Ipv4Address, uint32_t>::iterator it = m_flagedIPAdr.find(ipAdr);
1732  if(it == m_flagedIPAdr.end()){
1733  m_flagedIPAdr.insert(std::make_pair(ipAdr, 1));
1734  NS_LOG_FUNCTION (this << "This request has been flaged as potentialy malicious!"
1735  << "This IPAddress" << ipAdr << "will be penalized after the next offense!");
1736  }else{
1737  NS_LOG_FUNCTION (this << "KMS identified request coming from" << ipAdr << "as malicious request."
1738  << "This IPAddress is now blocked!");
1739  it->second++;
1740  return true;
1741  }
1742  }
1743  return false;
1744 }
1745 
1752 void
1754 {
1755  NS_LOG_FUNCTION(this << ksid);
1756 
1757  NS_LOG_FUNCTION(this << "Checking the state of the association " << ksid << " ...");
1758  std::map<std::string, Association004>::iterator it = m_associations004.find(ksid);
1759  if(it == m_associations004.end()){
1760  NS_LOG_DEBUG( this << " Key stream association identified with " << ksid << " does not exists!" );
1761  }else{
1762  if(
1763  (it->second).tempBuffer.empty() &&
1764  ((it->second).buffer.empty() || !(it->second).buffer.begin()->second.ready)
1765  ){
1766  NS_LOG_FUNCTION(this << ksid << "SESSION EXPIRED!");
1767  std::map<std::string, uint32_t>::iterator it2 = m_sessionList.find(ksid);
1768  if(it2 != m_sessionList.end()){
1769  it2->second++;
1770  NS_LOG_FUNCTION(this << "SESSION with KSID " << ksid << " was favored in the m_session_list!");
1771  }else{
1772  NS_LOG_FUNCTION(this << "SESSION with KSID " << ksid << " was not located in m_session_list!");
1773  }
1774  }else{
1775  NS_LOG_FUNCTION(this << ksid << "SESSION DID NOT EXPIRE!");
1776  std::map<std::string, uint32_t>::iterator it2 = m_sessionList.find(ksid);
1777  if(it2 != m_sessionList.end()){
1778  m_sessionList.erase(it2);
1779  NS_LOG_FUNCTION(this << "SESSION with KSID " << ksid << " was removed from the m_session_list!");
1780  }else{
1781  NS_LOG_FUNCTION(this << "SESSION with KSID " << ksid << " was not located in m_session_list!");
1782  }
1783  }
1784  }
1785 }
1786 
1787 void
1789 {
1790  NS_LOG_FUNCTION(this << headerIn.GetUri());
1791 
1792  if(CheckDoSAttack(headerIn, socket)) return;
1793 
1794  std::string payload = headerIn.GetMessageBodyString();
1795  NS_LOG_FUNCTION( this << payload);
1796 
1797  nlohmann::json jOpenConnectRequest;
1798  try{
1799  jOpenConnectRequest = nlohmann::json::parse(payload);
1800  }catch(...) {
1801  NS_FATAL_ERROR( this << "JSON parse error!" );
1802  }
1803 
1804  std::string ksid;
1805  std::string dstSaeId;
1806  std::string srcSaeId;
1808  if(jOpenConnectRequest.contains("Key_stream_ID")) ksid = jOpenConnectRequest["Key_stream_ID"];
1809  if(jOpenConnectRequest.contains("Source")) srcSaeId = jOpenConnectRequest["Source"];
1810  if(jOpenConnectRequest.contains("Destination")) dstSaeId = jOpenConnectRequest["Destination"];
1811  NS_ASSERT (srcSaeId.length() > 0);
1812  NS_ASSERT (dstSaeId.length() > 0);
1813 
1814  NS_LOG_FUNCTION(this << ksid << srcSaeId << dstSaeId);
1815 
1816  if(ksid.length() > 0) CheckSessionList(ksid);
1817 
1818  ReadJsonQos(inQos, jOpenConnectRequest);
1819 
1820  bool callByMaster {ksid.empty()};
1821  if(callByMaster){
1822 
1823  std::vector<std::string> uriParams = ProcessUriParams(headerIn.GetUri());
1824  uint32_t type = std::stoi(uriParams[6]);
1825 
1827  if(type == 0) {
1829  }else if(type == 1) {
1831  }
1833  //1-etsi014 (encryption); 2-etsi014(auth); 3-etsi004(encryption); 4-etsi004(auth)
1834 
1835  //ksid is empty
1836  //we need to fetch QKD application entry (if any)
1837  QKDApplicationEntry appConnection = GetApplicationConnectionDetailsBySaeIDsAndType( srcSaeId, dstSaeId, linkType );
1838  appConnection.PrintRegistryInfo();
1839 
1840  //there is no connection found in our registry
1841  //we might connect to other networks (roaming) or ask SDN controller
1842  //about further actions. However, for now we throw exception!
1843  //we DO NOT create new SAE connection here since in case of DDoS attack
1844  // it would be very expensive decision. Registration of SAEs MUST be indidiviual task!
1845  NS_ASSERT(appConnection.IsValid());
1846 
1847  //now we have connection details.
1848  //let's find for associated key association link
1849  //if multiple links are associated, then randomly selected one!
1851  NS_ASSERT(conn.IsValid());
1852  conn.PrintRegistryInfo();
1853 
1854  NS_LOG_FUNCTION(this << "Processing OPEN_CONNECT request submitted by the primary QKDApp ...");
1855  Ipv4Address dstKms = conn.GetDestinationKmsAddress();
1856 
1857  //CAC verification
1859  bool acceptRequest = ProcessQoSRequest(appConnection, conn, inQos, providedQoS, ksid);
1860 
1861  if(acceptRequest){
1862 
1863  //Create association with provided QoS
1865  srcSaeId,
1866  dstSaeId,
1867  providedQoS,
1868  dstKms,
1869  ksid,
1870  appConnection.GetId().string()
1871  ); //Establish association
1872 
1873  if(conn.GetType() == 0){ // Direct point-to-point connection. Respond immediately
1874  nlohmann::json jOpenConnectResponse;
1875  jOpenConnectResponse["Key_stream_ID"] = ksid;
1876  jOpenConnectResponse["QoS"] = {
1877  {"priority", providedQoS.priority},
1878  {"max_bps", providedQoS.maxRate},
1879  {"min_bps", providedQoS.minRate},
1880  {"jitter", providedQoS.jitter},
1881  {"timeout", providedQoS.timeout},
1882  {"key_chunk_size", providedQoS.chunkSize},
1883  {"TTL", providedQoS.TTL}
1884  };
1885  std::string msg = jOpenConnectResponse.dump();
1886 
1887  //create packet
1888  HTTPMessage httpMessage;
1889  httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok, msg, {
1890  {"Content-Type", "application/json; charset=utf-8"},
1891  {"Request URI", headerIn.GetUri() }
1892  });
1893  std::string hMessage = httpMessage.ToString();
1894  Ptr<Packet> packet = Create<Packet> (
1895  (uint8_t*) (hMessage).c_str(),
1896  hMessage.size()
1897  );
1898  NS_ASSERT (packet);
1899 
1900  SendToSocketPair(socket, packet);
1901 
1902  NS_LOG_FUNCTION(this << "KMS providing OK answer to OPEN_CONNECT!" << msg << packet->GetUid() << packet->GetSize());
1903 
1904  }else{ //Wait on NewAppResponse to respond to QKDApp
1905  Http004AppQuery(UUID{srcSaeId}, socket); //Query this received HTTP request!
1906  }
1907  NewAppRequest(ksid); //Send NEW_APP notification
1908  }else{
1909 
1910  NS_LOG_FUNCTION(this << "KMS is not able to answer to QoS request from the application " << appConnection.GetId().string());
1911 
1912  //create packet
1913  HTTPMessage httpMessage;
1914  httpMessage.CreateResponse(HTTPMessage::HttpStatus::BadRequest, "", {
1915  {"Request URI", headerIn.GetUri() }
1916  });
1917  std::string hMessage = httpMessage.ToString();
1918  Ptr<Packet> packet = Create<Packet> (
1919  (uint8_t*) (hMessage).c_str(),
1920  hMessage.size()
1921  );
1922  NS_ASSERT (packet);
1923 
1924  SendToSocketPair(socket, packet);
1925 
1926  }
1927 
1928  } else {
1929 
1930  NS_LOG_FUNCTION( this << "OPEN_CONNECT by Replica SAE" );
1931  //Check if ksid has been registered for this SAE
1932  std::map<std::string, Association004>::iterator it = m_associations004.find(ksid);
1933  if (it == m_associations004.end()) {
1934  NS_LOG_DEBUG( this << " Key stream association identified with " << ksid << " does not exists!" );
1935  return;
1936  } else if ((it->second).srcSaeId != UUID{srcSaeId}) {
1937  NS_LOG_FUNCTION( this << "KSID is not registered for this application" << (it->second).dstSaeId << srcSaeId );
1938  //Respond with an error! //@toDo
1939  } else {
1940 
1941  (it->second).peerRegistered = true;
1942  RegisterRequest(ksid);
1943 
1944  //Respond to OPEN_CONNECT made by SAE
1945 
1946  //create packet
1947  HTTPMessage httpMessage;
1948  httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok, "", {
1949  {"Request URI", headerIn.GetUri() }
1950  });
1951  std::string hMessage = httpMessage.ToString();
1952  Ptr<Packet> packet = Create<Packet> (
1953  (uint8_t*) (hMessage).c_str(),
1954  hMessage.size()
1955  );
1956  NS_ASSERT (packet);
1957 
1958  SendToSocketPair(socket, packet);
1959 
1960  }
1961  }
1962 
1963 }
1964 
1965 void
1967 {
1968  NS_LOG_FUNCTION( this << "Processing get_key request (ETSI 004)" << ksid );
1969 
1970  std::map<std::string, Association004>::iterator it = m_associations004.find(ksid);
1971  if(it == m_associations004.end()){
1972 
1973  if(CheckDoSAttack(headerIn, socket)) return;
1974 
1975  NS_LOG_DEBUG( this << " Key stream association identified with " << ksid << " does not exists!" );
1976 
1977  //create packet
1978  HTTPMessage httpMessage;
1979  httpMessage.CreateResponse(HTTPMessage::HttpStatus::BadRequest, "", {
1980  {"Request URI", headerIn.GetUri() }
1981  });
1982  std::string hMessage = httpMessage.ToString();
1983  Ptr<Packet> packet = Create<Packet> (
1984  (uint8_t*) (hMessage).c_str(),
1985  hMessage.size()
1986  );
1987  NS_ASSERT (packet);
1988 
1989  SendToSocketPair(socket, packet);
1990  return;
1991  }
1992 
1993  //PeerRegistered must be true @toDo - first check this (in case of QKDApp004 this will never happen)
1994  if( !(it->second).buffer.empty() && (it->second).buffer.begin()->second.ready )
1995  {
1996 
1997  QKDApplicationEntry appConnection = GetApplicationConnectionDetails( ksid );
1998  if(appConnection.IsValid())
1999  {
2000  appConnection.PrintRegistryInfo();
2001 
2002  uint32_t index;
2003  std::string key;
2004  index = (it->second).buffer.begin()->first;
2005  key = (it->second).buffer.begin()->second.key;
2006  (it->second).buffer.erase((it->second).buffer.begin()); //Remove the key
2007  if(it->second.associationDirection == 0){
2008  CheckAssociation(ksid); //Check if new keys need to be negotiated
2009  }
2010 
2011  nlohmann::json jresponse;
2012  jresponse["index"] = index;
2013  jresponse["Key_buffer"] = key;
2014  //No Metadata
2015  std::string msg = jresponse.dump();
2016 
2017  //create packet
2018  HTTPMessage httpMessage;
2019  httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok, msg, {
2020  {"Content-Type", "application/json; charset=utf-8"},
2021  {"Request URI", headerIn.GetUri() }
2022  });
2023  std::string hMessage = httpMessage.ToString();
2024  Ptr<Packet> packet = Create<Packet> (
2025  (uint8_t*) (hMessage).c_str(),
2026  hMessage.size()
2027  );
2028  NS_ASSERT (packet);
2029 
2030  SendToSocketPair(socket, packet);
2031 
2032  //TEST LINES - @toDo: remove after testing
2034  NS_ASSERT(conn.IsValid());
2035  conn.PrintRegistryInfo();
2036  NS_LOG_FUNCTION(this
2037  << conn.GetId()
2038  << headerIn.GetUri()
2039  << msg
2040  << "AverageKeyGenerationRate:" << conn.GetSKR()
2041  << "ExpectedConsumption:" << conn.GetExpectedConsumption()
2042  << "EffectiveSKR:" << conn.GetEffectiveSKR()
2043  );
2044  //end of test lines
2045 
2046  m_keyServedETSI004Trace(ksid, index, key.size()*8 );
2047  m_keyServedTraceEmir(key.size()*8);
2048 
2049  }else{
2050 
2051  //ASSOCIATION TTL EXPIRED AND REMOVED
2052  NS_LOG_FUNCTION(this << "Association was not found!" << it->second.dstSaeId.string() );
2053 
2054  //create packet
2055  HTTPMessage httpMessage;
2056  httpMessage.CreateResponse(HTTPMessage::HttpStatus::BadRequest, "", {
2057  {"Request URI", headerIn.GetUri() }
2058  });
2059  std::string hMessage = httpMessage.ToString();
2060  Ptr<Packet> packet = Create<Packet> (
2061  (uint8_t*) (hMessage).c_str(),
2062  hMessage.size()
2063  );
2064  NS_ASSERT (packet);
2065 
2066  SendToSocketPair(socket, packet);
2067 
2068  }
2069 
2070  }else{
2071 
2072  //Respond with an error. Currently this is the only error on GetKey004, therefore no message is included. @toDo
2073  NS_LOG_FUNCTION(this << "No keys available in the association buffer. Responding on the request ...");
2074 
2075  //create packet
2076  HTTPMessage httpMessage;
2077  httpMessage.CreateResponse(HTTPMessage::HttpStatus::BadRequest, "", {
2078  {"Request URI", headerIn.GetUri() }
2079  });
2080  std::string hMessage = httpMessage.ToString();
2081  Ptr<Packet> packet = Create<Packet> (
2082  (uint8_t*) (hMessage).c_str(),
2083  hMessage.size()
2084  );
2085  NS_ASSERT (packet);
2086 
2087  //TEST LINES - @toDo: remove after testing
2088  /*
2089  QKDApplicationEntry appConnection = GetApplicationConnectionDetails( it->second.dstSaeId.string() );
2090  NS_ASSERT(appConnection.IsValid());
2091  appConnection.PrintRegistryInfo();
2092  QKDKeyAssociationLinkEntry conn = GetKeyAssociationLinkDetailsByApplicationId( appConnection.GetId().string() );
2093  NS_ASSERT(conn.IsValid());
2094  conn.PrintRegistryInfo();
2095  NS_LOG_FUNCTION(this
2096  << conn.GetId()
2097  << headerIn.GetUri()
2098  << "AverageKeyGenerationRate:" << conn.GetSKR()
2099  << "ExpectedConsumption:" << conn.GetExpectedConsumption()
2100  << "EffectiveSKR:" << conn.GetEffectiveSKR()
2101  );
2102  */
2103  //end of test lines
2104 
2105  SendToSocketPair(socket, packet);
2106  }
2107 
2108 }
2109 
2110 void
2112 {
2113  NS_LOG_FUNCTION( this << "Processing CLOSE request ... " << ksid );
2114 
2115  std::map<std::string, Association004>::iterator it = m_associations004.find(ksid);
2116  if(it == m_associations004.end()){
2117  NS_LOG_DEBUG( this << " Key stream association identified with " << ksid << " does not exists!" );
2118  return;
2119  }
2120 
2121  HttpQuery query;
2122  query.method_type = ETSI_QKD_004_KMS_CLOSE; //Close made to peer KMS
2123  query.ksid = ksid; //Remember ksid
2124  if(!it->second.buffer.empty()){
2125  query.surplus_key_ID = GenerateKeyId(); //Generate keyId to empty key stream association
2126  query.sync_index = it->second.buffer.begin()->first; //Take the first index in the buffer!
2127  }
2128 
2129  QKDApplicationEntry appConnection = GetApplicationConnectionDetails( ksid );
2130  NS_ASSERT(appConnection.IsValid());
2131  appConnection.PrintRegistryInfo();
2132 
2134  NS_ASSERT(conn.IsValid());
2135  conn.PrintRegistryInfo();
2136 
2137  NS_LOG_FUNCTION( this << "Releasing key stream association buffer. Synchronizing with peed KMS ... ");
2138  CheckSocketsKMS( (it->second).dstKmsNode ); //Check connection to peer KMS!
2139  Ptr<Socket> sendSocket = GetSendSocketKMS ( (it->second).dstKmsNode );
2140  NS_ASSERT (sendSocket);
2141 
2142  nlohmann::json msgBody;
2143  if(!query.surplus_key_ID.empty()){
2144  msgBody["surplus_key_ID"] = query.surplus_key_ID;
2145  msgBody["sync_index"] = query.sync_index;
2146  }
2147  std::string msg = msgBody.dump();
2148 
2149  std::ostringstream peerkmsAddressTemp;
2150  (it->second).dstKmsNode.Print(peerkmsAddressTemp); //IPv4Address to string
2151  std::string headerUri = "http://" + peerkmsAddressTemp.str(); //Uri starts with destination KMS address
2152  headerUri += "/api/v1/associations/close_kms/" + ksid;
2153 
2154  //Create packet
2155  HTTPMessage httpMessage;
2156  httpMessage.CreateRequest(headerUri, "POST", msg);
2157  std::string hMessage = httpMessage.ToString();
2158  Ptr<Packet> packet = Create<Packet> (
2159  (uint8_t*) (hMessage).c_str(),
2160  hMessage.size()
2161  );
2162  NS_ASSERT (packet);
2163 
2164  HttpKMSAddQuery((it->second).dstKmsNode, query); //Save this query made to the peer KMS!
2165 
2166  sendSocket->Send(packet);
2167  NS_LOG_FUNCTION( this << "Synchronization information for releasing key stream association sent to peer KMS"
2168  << packet->GetUid() << packet->GetSize() );
2169 
2170 }
2171 
2172 
2180 void
2182 {
2183  NS_LOG_FUNCTION( this );
2184  std::map<std::string, Association004>::iterator it = m_associations004.find(ksid);
2185  if (it == m_associations004.end()){
2186  NS_LOG_DEBUG( this << " Key stream association identified with " << ksid << " does not exists!" );
2187  return;
2188  }
2189 
2190  CheckSocketsKMS( (it->second).dstKmsNode ); //Check connection to peer KMS!
2191  Ptr<Socket> sendSocket = GetSendSocketKMS ( (it->second).dstKmsNode );
2192  NS_ASSERT (sendSocket);
2193 
2194  nlohmann::json msgBody;
2195  msgBody["Source"] = (it->second).srcSaeId.string();
2196  msgBody["Destination"] = (it->second).dstSaeId.string();
2197  msgBody["QoS"]["key_chunk_size"] = (it->second).qos.chunkSize;
2198  msgBody["QoS"]["max_bps"] = (it->second).qos.maxRate;
2199  msgBody["QoS"]["min_bps"] = (it->second).qos.minRate;
2200  msgBody["QoS"]["jitter"] = (it->second).qos.jitter;
2201  msgBody["QoS"]["priority"] = (it->second).qos.priority;
2202  msgBody["QoS"]["timeout"] = (it->second).qos.timeout;
2203  msgBody["QoS"]["TTL"] = (it->second).qos.TTL;
2204 
2205  //msgBody["source_kms"] = conn.GetSourceKmsAddress(); For App Advertising
2206  msgBody["Key_stream_ID"] = ksid;
2207  std::string msg = msgBody.dump();
2208 
2209  std::ostringstream peerkmsAddressTemp;
2210  (it->second).dstKmsNode.Print(peerkmsAddressTemp); //IPv4Address to string
2211  std::string headerUri = "http://" + peerkmsAddressTemp.str(); //Uri starts with destination KMS address
2212  headerUri += "/api/v1/associations/new_app";
2213 
2214  //Create packet
2215  HTTPMessage httpMessage;
2216  httpMessage.CreateRequest(headerUri, "POST", msg);
2217  std::string hMessage = httpMessage.ToString();
2218  Ptr<Packet> packet = Create<Packet> (
2219  (uint8_t*) (hMessage).c_str(),
2220  hMessage.size()
2221  );
2222  NS_ASSERT (packet);
2223 
2224  HttpQuery query;
2225  query.method_type = RequestType::NEW_APP;
2226  query.source_sae = (it->second).srcSaeId;
2227  query.destination_sae = (it->second).dstSaeId;
2228  query.ksid = ksid;
2229  HttpKMSAddQuery((it->second).dstKmsNode, query);
2230 
2231  sendSocket->Send(packet);
2232  NS_LOG_FUNCTION( this << "NEW_APP: KMS informs peer KMS on new association established!" );
2233 }
2234 
2235 void
2237 {
2238  NS_LOG_FUNCTION( this << "Processing NEW_APP request!" );
2239  std::string payload = headerIn.GetMessageBodyString();
2240  nlohmann::json jNewAppRequest;
2241  try{
2242  jNewAppRequest = nlohmann::json::parse(payload);
2243  }catch (...){
2244  NS_FATAL_ERROR( this << "JSON parse error!" );
2245  }
2246 
2247  std::string srcSaeId;
2248  std::string dstSaeId;
2250  std::string ksid;
2251  if(jNewAppRequest.contains("Destination")) dstSaeId = jNewAppRequest["Destination"];
2252  if(jNewAppRequest.contains("Source")) srcSaeId = jNewAppRequest["Source"];
2253  if(jNewAppRequest.contains("Key_stream_ID")) ksid = jNewAppRequest["Key_stream_ID"];
2254 
2255  ReadJsonQos(inQoS, jNewAppRequest);
2256  NS_ASSERT(srcSaeId.length()>0 || dstSaeId.length()>0 || !ksid.empty());
2257 
2258  bool qosAgreed {true}; //Check if the QoS can be met! @toDo
2259  if(qosAgreed){
2260 
2261  NS_LOG_FUNCTION(this << srcSaeId << dstSaeId << ksid);
2262 
2263  QKDApplicationEntry appConnection = GetApplicationConnectionDetails( ksid );
2264  NS_ASSERT(appConnection.IsValid());
2265  appConnection.PrintRegistryInfo();
2266 
2267  Ipv4Address dstKms = appConnection.GetDestinationKmsAddress();
2268 
2269  /* If it is not point-to-point connection, msg will carry and source_kms!
2270  This value will be used instead of dstKms from the conn stats!
2271  However, the response on the NewAppRequest is sent via same route
2272  and will carry IP address of this KMS node. @toDoR */
2274  dstSaeId,
2275  srcSaeId,
2276  inQoS,
2277  dstKms,
2278  ksid,
2279  appConnection.GetId().string()
2280  );
2281 
2282  /* Send positive response on the NEW_APP request! In case where
2283  it is not point-to-point conncetion between the source and the destination
2284  msg will carry destination_kms address. @toDoR */
2285 
2286  //create packet
2287  HTTPMessage httpMessage;
2288  httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok, "", {
2289  {"Request URI", headerIn.GetUri() }
2290  });
2291  std::string hMessage = httpMessage.ToString();
2292  Ptr<Packet> packet = Create<Packet> (
2293  (uint8_t*) (hMessage).c_str(),
2294  hMessage.size()
2295  );
2296  NS_ASSERT (packet);
2297 
2298  NS_LOG_FUNCTION( this << "NEW_APP request accepted. Association created." );
2299  SendToSocketPairKMS(socket, packet); //Send Packet to Socket pair
2300 
2301  }else{
2302  NS_LOG_FUNCTION( this << "QoS requirements can not be satisfied" );
2303  //@toDoEmir Respond with an error status code (carry new QoS)!
2304  }
2305 
2306 }
2307 
2308 void
2310 {
2311  NS_LOG_FUNCTION( this << "Processing NEW_APP response" );
2312 
2313  Ipv4Address dstKms = GetDestinationKmsAddress(socket);
2314  std::map<Ipv4Address, std::vector<HttpQuery> >::iterator it = m_httpRequestsQueryKMS.find(dstKms);
2315 
2316  if(it == m_httpRequestsQueryKMS.end() || (it->second).empty())
2317  NS_FATAL_ERROR( this << "Response cannot be mapped! HttpQuery empty!" );
2318 
2319  std::string ksid = it->second[0].ksid;
2320 
2321  if(headerIn.GetStatusCode() == 200){ //Status OK
2322 
2323  QKDApplicationEntry appConnection = GetApplicationConnectionDetails( ksid );
2324  NS_ASSERT(appConnection.IsValid());
2325  appConnection.PrintRegistryInfo();
2326 
2328  NS_ASSERT(conn.IsValid());
2329  conn.PrintRegistryInfo();
2330 
2331  if(conn.GetHop() == 1) {//dstKms for point-to-point scenario!
2332  HttpKMSCompleteQuery(dstKms); //Point-to-point scenario. Response just as acknowledgement!
2333 
2334  } else {//@toDo Trusted relay scenario. QKDApp is waiting for OPEN_CONNECT response!
2335  bool QoS {true}; //Read QoS from response, calculate its own, and make response!
2336  if(QoS){
2337  nlohmann::json jOpenConnectResponse;
2338  jOpenConnectResponse["Key_stream_ID"] = it->second[0].ksid;
2339  std::string msg = jOpenConnectResponse.dump();
2340 
2341  //create packet
2342  HTTPMessage httpMessage;
2343  httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok, msg, {
2344  {"Content-Type", "application/json; charset=utf-8"},
2345  {"Request URI", headerIn.GetUri() }
2346  });
2347  std::string hMessage = httpMessage.ToString();
2348  Ptr<Packet> packet = Create<Packet> (
2349  (uint8_t*) (hMessage).c_str(),
2350  hMessage.size()
2351  );
2352  NS_ASSERT (packet);
2353 
2354  Ptr<Socket> responseSocket = GetSocketFromHttp004AppQuery(it->second[0].source_sae);
2355  Http004AppQueryComplete(it->second[0].source_sae);
2356  HttpKMSCompleteQuery(dstKms);
2357  SendToSocketPair(responseSocket, packet);
2358  }else{
2359  //Respond to the QKDApp with QoS that can be offered! @toDo Trusted relay scenario
2360  }
2361  }
2362 
2363  }else{ //Status indicating error!
2364 
2365  std::string ksid = it->second[0].ksid;
2366  QKDApplicationEntry appConnection = GetApplicationConnectionDetails( ksid );
2367  NS_ASSERT(appConnection.IsValid());
2368  appConnection.PrintRegistryInfo();
2369 
2371  NS_ASSERT(conn.IsValid());
2372  conn.PrintRegistryInfo();
2373 
2374  if(conn.GetHop() == 1) //dstKms for point-to-point scenario!
2375  HttpKMSCompleteQuery(dstKms); //Point-to-point scenario. Response just as acknowledgement!
2376  else{
2377  //Check the error! @toDo Respond to peer QKDApp in case of Trusted relay scenario!
2378  HttpKMSCompleteQuery(dstKms);
2379  }
2380  std::map<std::string, Association004>::iterator it = m_associations004.find(ksid);
2381  if(it != m_associations004.end()){
2382  m_associations004.erase(it); //Myb not erase, but for a few seconds mark as closed, and then erase! @toDo
2383  }else{
2384  NS_FATAL_ERROR(this << "Closing non existing association!");
2385  }
2386  }
2387 
2388 }
2389 
2390 void
2392 {
2393  NS_LOG_FUNCTION( this << ksid );
2394  std::map<std::string, Association004>::iterator it = m_associations004.find(ksid); //Find association entry identified with ksid
2395  if(it == m_associations004.end()){
2396  NS_LOG_DEBUG( this << " Key stream association identified with " << ksid << " does not exists!" );
2397  return;
2398  }
2399 
2400  Ipv4Address dstKms = (it->second).dstKmsNode; //Read destination KMS address from the association entry
2401 
2402  CheckSocketsKMS( dstKms ); //Check connection to dstKms
2403  Ptr<Socket> sendSocket = GetSendSocketKMS ( dstKms ); //Obtain send socket object to reach dstKms
2404 
2405  std::ostringstream peerkmsAddressTemp;
2406  dstKms.Print(peerkmsAddressTemp); //IPv4Address to string
2407  std::string headerUri = "http://" + peerkmsAddressTemp.str (); //Read an dstKms IP address to string
2408  headerUri += "/api/v1/associations/register/" + ksid; //Create an URI for the register request
2409 
2410  //Create packet
2411  HTTPMessage httpMessage;
2412  httpMessage.CreateRequest(headerUri, "GET");
2413  std::string hMessage = httpMessage.ToString();
2414  Ptr<Packet> packet = Create<Packet> (
2415  (uint8_t*) (hMessage).c_str(),
2416  hMessage.size()
2417  );
2418  NS_ASSERT (packet);
2419 
2420  HttpQuery query;
2421  query.method_type = REGISTER;
2422  query.ksid = ksid;
2423  HttpKMSAddQuery(dstKms, query); //Remember HTTP query to be able to map response later
2424 
2425  sendSocket->Send(packet); //Send the packet to dstKms
2426 }
2427 
2428 void
2430 {
2431  NS_LOG_FUNCTION(this << "Processing register request " << ksid << headerIn.GetUri() );
2432  std::map<std::string, Association004>::iterator it = m_associations004.find(ksid); //Find association entry identified with ksid
2433  if(it != m_associations004.end() && (it->second).peerRegistered != true){
2434  (it->second).peerRegistered = true; //Acknowledge register notification, peer QKDApp is connected!
2435  //Send ack on this notification
2436 
2437  //create packet
2438  HTTPMessage httpMessage;
2439  httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok, "", {
2440  {"Content-Type", "application/json; charset=utf-8"},
2441  {"Request URI", headerIn.GetUri() }
2442  });
2443  std::string hMessage = httpMessage.ToString();
2444  Ptr<Packet> packet = Create<Packet> (
2445  (uint8_t*) (hMessage).c_str(),
2446  hMessage.size()
2447  );
2448  NS_ASSERT (packet);
2449 
2450  SendToSocketPairKMS(socket, packet); //Sent response on register request
2451  CheckAssociation(ksid);
2452 
2453  }else if(it == m_associations004.end()){
2454  NS_LOG_DEBUG( this << " Key stream association identified with " << ksid << " does not exists!" );
2455  return;
2456  }else if((it->second).peerRegistered == true){
2457  NS_LOG_FUNCTION(this << "The peer application for asscotiation " << ksid << " has already been connected.");
2458  }
2459 }
2460 
2461 void
2463 {
2464  NS_LOG_FUNCTION( this << "Processing /register response!");
2465  Ipv4Address dstKms = GetDestinationKmsAddress(socket);
2466  std::map<Ipv4Address, std::vector<HttpQuery> >::iterator it = m_httpRequestsQueryKMS.find(dstKms);
2467  if(it == m_httpRequestsQueryKMS.end() || (it->second).empty())
2468  NS_FATAL_ERROR( this << "Response cannot be mapped! HttpQuery empty!" );
2469 
2470  if (headerIn.GetStatusCode() == HTTPMessage::Ok)
2471  NS_LOG_FUNCTION( this << "Successful notification REGISTER" );
2472  else {
2473  NS_LOG_FUNCTION( this << "/register error! Releasing established association" << it->second[0].ksid );
2474  std::map<std::string, Association004>::iterator it1 = m_associations004.find(it->second[0].ksid);
2475  if(it1 != m_associations004.end()){
2476  m_associations004.erase(it1); //Myb not erase, but for a few seconds mark as closed, and then erase! @toDo
2477  }else{
2478  NS_FATAL_ERROR(this << "Closing non existing association!");
2479  }
2480  }
2481  HttpKMSCompleteQuery(dstKms);
2482 
2483 }
2484 
2485 void
2487 {
2488  NS_LOG_FUNCTION( this << "Processing /fill request" << ksid );
2489  std::string payload = headerIn.GetMessageBodyString();
2490 
2491  nlohmann::json jAddKeysRequest;
2492  try{
2493  jAddKeysRequest = nlohmann::json::parse(payload);
2494  }catch (...){
2495  NS_FATAL_ERROR( this << "JSON parse error!" );
2496  }
2497 
2498  std::map<std::string, Association004>::iterator it = m_associations004.find(ksid);
2499  if(it == m_associations004.end()){
2500  NS_LOG_DEBUG( this << " Key stream association identified with " << ksid << " does not exists!" );
2501  return;
2502  }
2503  //Ipv4Address dstKms = it->second.dstKmsNode;
2504  UUID dstSaeId = it->second.dstSaeId;
2505  QKDApplicationEntry appConnection = GetApplicationConnectionDetails( ksid );
2506  NS_ASSERT(appConnection.IsValid());
2507  appConnection.PrintRegistryInfo();
2508 
2510  NS_ASSERT(conn.IsValid());
2511  conn.PrintRegistryInfo();
2512 
2513  Ptr<QKDBuffer> buffer = conn.GetSourceBuffer();
2514 
2515  bool accept = true; //For now, only full acceptance, or rejection!
2516  for(nlohmann::json::iterator it = jAddKeysRequest["keys"].begin(); it != jAddKeysRequest["keys"].end(); ++it){
2517  if(buffer->ProbeKeyStatus( (it.value())["key_ID"], QKDKey::READY ))
2518  continue;
2519  else{
2520  accept = false;
2521  break;
2522  }
2523  }
2524 
2525  if(accept){
2526  for(nlohmann::json::iterator it = jAddKeysRequest["keys"].begin(); it != jAddKeysRequest["keys"].end(); ++it){
2527  Ptr<QKDKey> key = buffer->FetchKeyByID( (it.value())["key_ID"]);
2529  }
2530 
2531  //Create positive response
2532  NS_LOG_FUNCTION( this << "Replica KMS added keys " << jAddKeysRequest.dump()
2533  << " to dedicated association key store " << ksid );
2534 
2535  //create packet
2536  HTTPMessage httpMessage;
2537  httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok, "", {
2538  {"Request URI", headerIn.GetUri() }
2539  });
2540  std::string hMessage = httpMessage.ToString();
2541  Ptr<Packet> packet = Create<Packet> (
2542  (uint8_t*) (hMessage).c_str(),
2543  hMessage.size()
2544  );
2545  NS_ASSERT (packet);
2546 
2547  NS_LOG_FUNCTION( this << "Replica KMS sending response on FILL request "
2548  << ksid << packet->GetUid() << packet->GetSize() );
2549  SendToSocketPairKMS(socket, packet);
2550 
2551  }else{ //Keys negotiated to FILL the association key store are not available
2552  NS_LOG_FUNCTION( this << "Replica KMS reject FILL request " << jAddKeysRequest.dump()
2553  << " for association " << ksid );
2554 
2555  //create packet
2556  HTTPMessage httpMessage;
2557  httpMessage.CreateResponse(HTTPMessage::HttpStatus::BadRequest, "", {
2558  {"Request URI", headerIn.GetUri() }
2559  });
2560  std::string hMessage = httpMessage.ToString();
2561  Ptr<Packet> packet = Create<Packet> (
2562  (uint8_t*) (hMessage).c_str(),
2563  hMessage.size()
2564  );
2565  NS_ASSERT (packet);
2566 
2567  NS_LOG_FUNCTION( this << "Replica KMS sending response on FILL request "
2568  << ksid << packet->GetUid() << packet->GetSize() );
2569  SendToSocketPair(socket, packet);
2570  }
2571 
2572 }
2573 
2574 void
2576 {
2577  NS_LOG_FUNCTION( this << "Processing FILL response" );
2578  std::string payload = headerIn.GetMessageBodyString();
2579 
2580  Ipv4Address dstKms = GetDestinationKmsAddress(socket);
2581  std::map<Ipv4Address, std::vector<HttpQuery> >::iterator it = m_httpRequestsQueryKMS.find(dstKms);
2582  if(it == m_httpRequestsQueryKMS.end() || (it->second).empty())
2583  NS_FATAL_ERROR( this << "Response cannot be mapped! HttpQuery empty!" );
2584 
2585  std::string ksid = it->second[0].ksid;
2586  NS_ASSERT(ksid != "");
2587  std::map<std::string, Association004>::iterator a = m_associations004.find(ksid);
2588  if(a == m_associations004.end()){
2589  NS_LOG_DEBUG( this << " Key stream association identified with " << ksid << " does not exists!" );
2590  return;
2591  }
2592 
2593  QKDApplicationEntry appConnection = GetApplicationConnectionDetails( ksid );
2594  NS_ASSERT(appConnection.IsValid());
2595  appConnection.PrintRegistryInfo();
2596 
2598  NS_ASSERT(conn.IsValid());
2599  conn.PrintRegistryInfo();
2600 
2601  Ptr<QKDBuffer> buffer = conn.GetSourceBuffer();
2602 
2603  if(!buffer)
2604  NS_FATAL_ERROR( this << "QKDBuffer for this connection cannot be found" );
2605 
2606  if (headerIn.GetStatusCode() == HTTPMessage::Ok){
2607  NS_LOG_FUNCTION( this << "Filling association dedicated key store" << ksid );
2608  for(std::vector<std::string>::iterator i = a->second.tempBuffer.begin(); i < a->second.tempBuffer.end(); ++i){
2609  Ptr<QKDKey> key = buffer->FetchKeyByID(*i);
2610  NS_ASSERT(key);
2612  }
2613  a->second.tempBuffer.clear(); //Release keys from tempBuffer
2614 
2615  }else{
2616  NS_LOG_FUNCTION( this << "Releasing reservation of keys " << a->second.tempBuffer );
2617  for(std::vector<std::string>::iterator i = a->second.tempBuffer.begin(); i < a->second.tempBuffer.end(); ++i)
2618  buffer->ReleaseReservation(*i);
2619  a->second.tempBuffer.clear();
2620  CheckAssociation(ksid); //Try FILL again
2621  }
2622  HttpKMSCompleteQuery(dstKms);
2623 
2624 }
2625 
2626 void
2627 QKDKeyManagerSystemApplication::TransformKeys (uint32_t keySize, uint32_t keyNumber, UUID ksid)
2628 {
2629  NS_LOG_FUNCTION( this << "target size" << keySize << "target number" << keyNumber << "ksid SAE" << ksid.string() );
2630 
2632  NS_ASSERT(appConnection.IsValid());
2633  appConnection.PrintRegistryInfo();
2634 
2636  NS_ASSERT(conn.IsValid());
2637  conn.PrintRegistryInfo();
2638 
2639  Ptr<QKDBuffer> buffer = conn.GetSourceBuffer();
2640  buffer->RecordTargetSize(keySize);
2641 
2642  bool transformSetReady = false;
2643  if(buffer){
2644  std::vector<std::string> toTransformKeyIDs {}; //Choice of keys to transform
2645  uint32_t targetSize {keySize*keyNumber};
2646  while(!transformSetReady){ //Form a transform set!
2647  Ptr<QKDKey> key = buffer->SearchOptimalKeyToTransform(targetSize);
2648  NS_ASSERT(key->GetId() != ""); //Check
2649  NS_ASSERT(key->GetSizeInBits() != 0); //Check
2650  buffer->ReserveKey(key->GetId()); //Reserve key for transformation! @toDo include reservation_type
2651  toTransformKeyIDs.push_back(key->GetId());
2652  if(key->GetSizeInBits() >= targetSize)
2653  transformSetReady = true;
2654  else
2655  targetSize -= key->GetSizeInBits();
2656  //@toDo: To avoid infinite while loop perform a check on toTransformKeyIDs.size() < m_maxTransformSet - defined by KMS
2657  }
2658  //Generate newKeyIds and optionaly suprplus keyIds
2659  std::vector<std::string> transformKeyIDs;
2660  uint32_t k {0};
2661  while(k++<keyNumber){
2662  transformKeyIDs.push_back(GenerateKeyId());
2663  }
2664  std::string surplusKeyId = GenerateKeyId();
2665  NS_LOG_FUNCTION( this << "transform_key_size" << keySize );
2666  NS_LOG_FUNCTION( this << "transform_key_number" << keyNumber);
2667  NS_LOG_FUNCTION( this << "transform_key_IDs" << transformKeyIDs );
2668  NS_LOG_FUNCTION( this << "surplus_key_ID" << surplusKeyId );
2669  NS_LOG_FUNCTION( this << "to_transform_key_IDs" << toTransformKeyIDs );
2670 
2671  //Create HTTP message transform
2672  nlohmann::json jtransform;
2673  jtransform["ksid"] = ksid.string(); //Must know to find QKDBuffer!
2674  jtransform["transform_key_size"] = keySize;
2675  jtransform["transform_key_number"] = keyNumber;
2676  for(size_t i = 0; i < transformKeyIDs.size(); i++)
2677  jtransform["transform_key_IDs"].push_back({{"key_ID", transformKeyIDs[i]}});
2678  jtransform["surplus_key_ID"] = surplusKeyId;
2679  for(size_t i = 0; i < toTransformKeyIDs.size(); i++)
2680  jtransform["to_transform_key_IDs"].push_back({{"key_ID", toTransformKeyIDs[i]}});
2681 
2682  std::string msg = jtransform.dump();
2683  NS_LOG_FUNCTION( this << "Transform payload" << msg );
2684  Ipv4Address dstKms = conn.GetDestinationKmsAddress(); //Destination KMS adress
2685  CheckSocketsKMS(dstKms); //Check connection to peer KMS!
2686  Ptr<Socket> sendSocket = GetSendSocketKMS(dstKms); //Get send socket to peer KMS
2687  NS_ASSERT (sendSocket); //Check
2688 
2689  //Create packet
2690  HTTPMessage header;
2691  std::ostringstream peerkmsAddressTemp;
2692  dstKms.Print(peerkmsAddressTemp); //IPv4Address to string
2693  std::string headerUri = "http://" + peerkmsAddressTemp.str ();
2694  headerUri += "/api/v1/keys/transform_keys";
2695 
2696  //Create packet
2697  HTTPMessage httpMessage;
2698  httpMessage.CreateRequest(headerUri, "POST", msg);
2699  std::string hMessage = httpMessage.ToString();
2700  Ptr<Packet> packet = Create<Packet> (
2701  (uint8_t*) (hMessage).c_str(),
2702  hMessage.size()
2703  );
2704  NS_ASSERT (packet);
2705 
2706  HttpQuery httpRequest;
2707  httpRequest.ksid = ksid.string(); //Must know to find QKDBuffer!
2708  httpRequest.method_type = RequestType::TRANSFORM_KEYS;
2709  httpRequest.transform_key_size = keySize;
2710  httpRequest.transform_key_number = keyNumber;
2711  httpRequest.transform_key_IDs = transformKeyIDs;
2712  httpRequest.to_transform_key_IDs = toTransformKeyIDs;
2713  httpRequest.surplus_key_ID = surplusKeyId;
2714  HttpKMSAddQuery(dstKms, httpRequest); //Remember request to properly map response!
2715 
2716  sendSocket->Send(packet);
2717  NS_LOG_FUNCTION( this << "Transform request sent" << packet->GetUid() << packet->GetSize() );
2718 
2719  }else{
2720  NS_FATAL_ERROR( this << "QKD buffer for this connection was not found!" );
2721  }
2722 
2723 }
2724 
2725 void
2727 {
2728  NS_LOG_FUNCTION( this << socket );
2729 
2730  std::string payload = headerIn.GetMessageBodyString();
2731  nlohmann::json jtransformRequest;
2732  try {
2733  jtransformRequest = nlohmann::json::parse(payload);
2734  } catch (...) {
2735  NS_FATAL_ERROR( this << "JSON parse error!" );
2736  }
2737  //Read JSON parameters
2738  uint32_t keySize {0}, keyNumber {0};
2739  std::vector<std::string> toTransformKeyIDs {}, transformKeyIDs {};
2740  std::string surplusKeyId {};
2741 
2742  std::string ksid;
2743  if(jtransformRequest.contains("transform_key_size"))
2744  keySize = jtransformRequest["transform_key_size"];
2745  if(jtransformRequest.contains("transform_key_number"))
2746  keyNumber = jtransformRequest["transform_key_number"]; //@toDo why is keyNumber always = 1, jtransformRequest["transform_key_number"] holds correct values, but keyNumber is 1?
2747  if(jtransformRequest.contains("surplus_key_ID"))
2748  surplusKeyId = jtransformRequest["surplus_key_ID"];
2749  if(jtransformRequest.contains("transform_key_IDs")){
2750  for(
2751  nlohmann::json::iterator it = jtransformRequest["transform_key_IDs"].begin();
2752  it != jtransformRequest["transform_key_IDs"].end();
2753  ++it
2754  )
2755  transformKeyIDs.push_back((it.value())["key_ID"]);
2756  }
2757  if(jtransformRequest.contains("to_transform_key_IDs")){
2758  for(
2759  nlohmann::json::iterator it = jtransformRequest["to_transform_key_IDs"].begin();
2760  it != jtransformRequest["to_transform_key_IDs"].end();
2761  ++it
2762  )
2763  toTransformKeyIDs.push_back((it.value())["key_ID"]);
2764  }
2765  if(jtransformRequest.contains("ksid")){
2766  ksid = jtransformRequest["ksid"];
2767  }
2768 
2769  NS_ASSERT(keySize != 0);
2770  NS_ASSERT(keyNumber =! 0);
2771  NS_ASSERT(!transformKeyIDs.empty());
2772  NS_ASSERT(!toTransformKeyIDs.empty());
2773 
2774  NS_LOG_FUNCTION( this << keySize << keyNumber << "\ntransform_key_IDs"<< transformKeyIDs
2775  << "\nto_transform_key_IDs" << toTransformKeyIDs << "\nsurplus_key_ID" << surplusKeyId << "\nksid" << ksid );
2776 
2777  if(ksid.size() == 0){
2778  NS_FATAL_ERROR( this << "No ksid specified!" << jtransformRequest.dump() );
2779  }
2780 
2781  QKDApplicationEntry appConnection = GetApplicationConnectionDetails( ksid );
2782  NS_ASSERT(appConnection.IsValid());
2783  appConnection.PrintRegistryInfo();
2784 
2786  NS_ASSERT(conn.IsValid());
2787  conn.PrintRegistryInfo();
2788 
2789 
2790  Ptr<QKDBuffer> buffer = conn.GetSourceBuffer();
2791  if(buffer){
2792  bool keysExist {true};
2793  for(size_t i = 0; i < toTransformKeyIDs.size(); i++){
2794  keysExist = buffer->ProbeKeyStatus(toTransformKeyIDs[i], QKDKey::READY); //Check if key exists and is READY
2795  if (!keysExist)
2796  break;
2797  }
2798  if(keysExist){ //Perform transformation and response OK
2799  NS_LOG_FUNCTION( this << "Performing transformation" );
2800  uint32_t keySizeInBytes = keySize/8;
2801  std::string mergedKey {};
2802  for(size_t i = 0; i < toTransformKeyIDs.size(); i++){
2803  mergedKey += (buffer->FetchKeyByID(toTransformKeyIDs[i], 1))->GetKeyString(); //Fetching will remove key from QKD buffer!
2804  }
2805  for(size_t i = 0; i < transformKeyIDs.size(); i++){ //Should use keyNumber but the previus read is invalid! @toDo
2806  std::string keyString = mergedKey.substr(0, keySizeInBytes);
2807  mergedKey.erase(0, keySizeInBytes);
2808  Ptr<QKDKey> key = CreateObject<QKDKey> (transformKeyIDs[i], keyString);
2809  buffer->AddNewKey(key,1);
2810  }
2811  if(!mergedKey.empty()){
2812  Ptr<QKDKey> key = CreateObject<QKDKey> (surplusKeyId, mergedKey);
2813  buffer->AddNewKey(key,1);
2814  }
2815 
2816  nlohmann::json jResponse;
2817  jResponse["sae_id"] = appConnection.GetSrcSaeId().string(); //it is destination saeId for the peer KMS
2818  std::string msg = jResponse.dump();
2819 
2820  //create packet
2821  HTTPMessage httpMessage;
2822  httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok, msg, {
2823  {"Content-Type", "application/json; charset=utf-8"},
2824  {"Request URI", headerIn.GetUri() }
2825  });
2826  std::string hMessage = httpMessage.ToString();
2827  Ptr<Packet> packet = Create<Packet> (
2828  (uint8_t*) (hMessage).c_str(),
2829  hMessage.size()
2830  );
2831  NS_ASSERT (packet);
2832 
2833  SendToSocketPairKMS(socket, packet);
2834 
2835  }else{ //Response Error!
2836  NS_LOG_FUNCTION( this << "Check failed" );
2837  nlohmann::json jResponse;
2838  jResponse["sae_id"] = appConnection.GetSrcSaeId().string();
2839  std::string msg = jResponse.dump();
2840 
2841  //create packet
2842  HTTPMessage httpMessage;
2843  httpMessage.CreateResponse(HTTPMessage::HttpStatus::BadRequest, msg, {
2844  {"Content-Type", "application/json; charset=utf-8"},
2845  {"Request URI", headerIn.GetUri() }
2846  });
2847  std::string hMessage = httpMessage.ToString();
2848  Ptr<Packet> packet = Create<Packet> (
2849  (uint8_t*) (hMessage).c_str(),
2850  hMessage.size()
2851  );
2852  NS_ASSERT (packet);
2853 
2854  SendToSocketPairKMS(socket, packet);
2855  }
2856 
2857  }else{
2858  NS_FATAL_ERROR( this << "No QKD buffer found for this connection!" );
2859  }
2860 
2861 }
2862 
2863 void
2865 {
2866  std::string payload = headerIn.GetMessageBodyString(); //Read payload
2867 
2868  NS_LOG_FUNCTION( this << payload );
2869 
2870  nlohmann::json jTransformResponse;
2871  try {
2872  jTransformResponse = nlohmann::json::parse(payload);
2873  } catch (...) {
2874  NS_FATAL_ERROR( this << "JSON parse error! Received payload:" << payload );
2875  }
2876 
2877  std::string ksid = "";
2878  if(jTransformResponse.contains("sae_id")) ksid = jTransformResponse["sae_id"];
2879  if(ksid.empty() && jTransformResponse.contains("ksid")) ksid = jTransformResponse["ksid"];
2880 
2881  Ipv4Address dstKms = GetDestinationKmsAddress(socket);
2882 
2883  QKDApplicationEntry appConnection = GetApplicationConnectionDetails( ksid );
2884  NS_ASSERT(appConnection.IsValid());
2885  appConnection.PrintRegistryInfo();
2886 
2888  NS_ASSERT(conn.IsValid());
2889  conn.PrintRegistryInfo();
2890 
2891  Ptr<QKDBuffer> buffer = conn.GetSourceBuffer();
2892  std::map<Ipv4Address, std::vector<HttpQuery> >::iterator it = m_httpRequestsQueryKMS.find(dstKms);
2893  HttpQuery transformPar = (it->second)[0];
2894  if (headerIn.GetStatusCode() == HTTPMessage::Ok){ //Transform keys
2895  //Read necessery transform parameters from HTTP query
2896  if(it == m_httpRequestsQueryKMS.end())
2897  NS_FATAL_ERROR( this << "HTTP response cannot be mapped: HTTP query to destination KMS does not exist!" );
2898  else if(it->second.empty())
2899  NS_FATAL_ERROR( this << "HTTP response cannot be mapped: HTTP query is empty!" );
2900  uint32_t keySize {transformPar.transform_key_size}, keyNumber {transformPar.transform_key_number};
2901  std::vector<std::string> toTransformKeyIDs {transformPar.to_transform_key_IDs},
2902  transformKeyIDs {transformPar.transform_key_IDs};
2903  std::string surplusKeyId {transformPar.surplus_key_ID};
2904  HttpKMSCompleteQuery(dstKms); //Clear this request from HTTP query (all parameters read!)
2905  NS_LOG_FUNCTION( this << "Transforming keys" );
2906  bool keysExist {true};
2907  for(size_t i = 0; i < toTransformKeyIDs.size(); i++){
2908  keysExist = buffer->ProbeKeyStatus(toTransformKeyIDs[i], QKDKey::RESERVED); //Check if key exists and is RESERVED
2909  if (!keysExist)
2910  break;
2911  }
2912  if(keysExist){
2913  uint32_t keySizeInBytes = keySize/8;
2914  std::string mergedKey {};
2915  for(size_t i = 0; i < toTransformKeyIDs.size(); i++){
2916  mergedKey += (buffer->FetchKeyByID(toTransformKeyIDs[i], 1))->GetKeyString(); //Fetching will remove key from QKD buffer!
2917  }
2918  for(size_t i = 0; i < keyNumber; i++){
2919  std::string keyString = mergedKey.substr(0, keySizeInBytes);
2920  mergedKey.erase(0, keySizeInBytes);
2921  Ptr<QKDKey> key = CreateObject<QKDKey> (transformKeyIDs[i], keyString);
2922  buffer->AddNewKey(key,1);
2923  }
2924  if(!mergedKey.empty()){
2925  Ptr<QKDKey> key = CreateObject<QKDKey> (surplusKeyId, mergedKey);
2926  buffer->AddNewKey(key,1);
2927  }
2928 
2929  NS_LOG_FUNCTION( this << "Transformation successfuly completed!" );
2930  }else{
2931  NS_FATAL_ERROR( this << "KMS mistreated reserved keys: keys not found!" );
2932  }
2933  }else{ //Release key reservation
2934  NS_LOG_FUNCTION( this << "Releasing reserved keys for failed transformation!");
2935  std::vector<std::string> toTransformKeyIDs {transformPar.to_transform_key_IDs};
2936  HttpKMSCompleteQuery(dstKms); //Clear this request from HTTP query (all parameters read!)
2937  for(size_t i = 0; i < toTransformKeyIDs.size(); i++){
2938  buffer->ReleaseReservation(toTransformKeyIDs[i]);
2939  }
2940  NS_LOG_FUNCTION( this << "Reserved keys are released" << toTransformKeyIDs );
2941  //@toDo Repeat TransformKeys? We have keySize, keyNumber, and dstKms! All we need!
2942  }
2943 
2944 }
2945 
2946 void
2948 {
2949  NS_LOG_FUNCTION( this << "Processing CLOSE from peer KMS" << ksid );
2950  std::string payload = headerIn.GetMessageBodyString(); //Read the packet payload
2951  nlohmann::json jcloseRequest;
2952  try {
2953  jcloseRequest = nlohmann::json::parse(payload);
2954  } catch (...) {
2955  NS_FATAL_ERROR( this << "JSON parse error!" );
2956  }
2957 
2958  std::string surplusKeyId {};
2959  uint32_t syncIndex {0};
2960  if(jcloseRequest.contains("surplus_key_ID"))
2961  surplusKeyId = jcloseRequest["surplus_key_ID"];
2962  if(jcloseRequest.contains("sync_index"))
2963  syncIndex = jcloseRequest["sync_index"];
2964 
2965  std::map<std::string, Association004>::iterator it = m_associations004.find(ksid);
2966  if(it == m_associations004.end()){ //Key stream association does not exists (peer error, or association already released)
2967  NS_LOG_FUNCTION( this << "KSID not registered on KMS, or is already closed!" );
2968 
2969  //create packet
2970  HTTPMessage httpMessage;
2971  httpMessage.CreateResponse(HTTPMessage::HttpStatus::NotAcceptable, "", {
2972  {"Request URI", headerIn.GetUri() }
2973  });
2974  std::string hMessage = httpMessage.ToString();
2975  Ptr<Packet> packet = Create<Packet> (
2976  (uint8_t*) (hMessage).c_str(),
2977  hMessage.size()
2978  );
2979  NS_ASSERT (packet);
2980 
2981  NS_LOG_FUNCTION( this << "Sending response on CLOSE request " << packet->GetUid() << packet->GetSize() );
2982  SendToSocketPairKMS(socket, packet);
2983 
2984  }else{
2985  it->second.peerRegistered = false; //QKDApp is no longer registered for particular association!
2986  bool empty {false};
2987  uint32_t localSyncIndex {0};
2988  if(it->second.buffer.begin() != it->second.buffer.end()) //Replica association buffer is not empty!
2989  localSyncIndex = it->second.buffer.begin()->first; //The oldest index in dedicated association buffer!
2990  else
2991  empty = true;
2992 
2993  //record additional key consumption (some keys may not be perserved)
2994  if(!surplusKeyId.empty() && syncIndex > localSyncIndex){
2995  //must record key consumed
2996  NS_LOG_FUNCTION(this << "emiree" << syncIndex << localSyncIndex);
2997  uint32_t presentKeyMaterial {0};
2998  for (std::map<uint32_t, ChunkKey>::iterator it2 = it->second.buffer.begin(); it2 != it->second.buffer.find(syncIndex); ++it2){
2999  //from begining of buffer until SyncIndex all keys are not perserved
3000  NS_LOG_FUNCTION(this << it2->second.chunkSize);
3001  presentKeyMaterial += it2->second.chunkSize;
3002  }
3003  NS_LOG_FUNCTION(this << "emiree1" << presentKeyMaterial);
3004  m_keyServedTraceEmir(presentKeyMaterial);
3005  //m_keyServedTrace((it->second).dstSaeId, presentKeyMaterial);
3006  //m_keyServedWithKSIDTrace(ksid, (it->second).dstSaeId, presentKeyMaterial);
3007  }
3008 
3009  if(!surplusKeyId.empty() && syncIndex < localSyncIndex) //Only if peer KMS dedicated association buffer is not empty (known by the surplusKeyId presence)
3010  syncIndex = localSyncIndex; //KMSs synchronize on largest index that exists at both peers!
3011 
3012  bool flag {false};
3013  if(empty && !surplusKeyId.empty())
3014  flag = true; //If replica empty, primary not. Replica sends flag insted of index!
3015 
3016  ReleaseAssociation(ksid, surplusKeyId, syncIndex);
3017 
3018  nlohmann::json jresponse;
3019  if(!flag){
3020  if(!surplusKeyId.empty())
3021  jresponse["sync_index"] = syncIndex;
3022  }else{
3023  jresponse["flag_empty"] = true;
3024  }
3025 
3026  std::string msg = jresponse.dump();
3027 
3028  //create packet
3029  HTTPMessage httpMessage;
3030  httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok, msg, {
3031  {"Content-Type", "application/json; charset=utf-8"},
3032  {"Request URI", headerIn.GetUri() }
3033  });
3034  std::string hMessage = httpMessage.ToString();
3035  Ptr<Packet> packet = Create<Packet> (
3036  (uint8_t*) (hMessage).c_str(),
3037  hMessage.size()
3038  );
3039  NS_ASSERT (packet);
3040 
3041  NS_LOG_FUNCTION( this << "Sending response on CLOSE" << msg << packet->GetUid() << packet->GetSize());
3042  SendToSocketPairKMS(socket, packet);
3043  }
3044 
3045 }
3046 
3047 void
3048 QKDKeyManagerSystemApplication::ReleaseAssociation (std::string ksid, std::string surplusKeyId, uint32_t syncIndex)
3049 {
3050  NS_LOG_FUNCTION( this << "Releasing association ... " << ksid );
3051  std::map<std::string, Association004>::iterator it = m_associations004.find(ksid);
3052  if(it == m_associations004.end()) { //Key stream association does not exists
3053  NS_LOG_DEBUG( this << " Key stream association identified with " << ksid << " does not exists!" );
3054  return;
3055  }
3056 
3057  if(surplusKeyId.empty()){
3058  m_associations004.erase(it);
3059  }else{
3060  std::string preservedKeyString {}; //First preserve remaining key material!
3061  std::map<uint32_t, ChunkKey>::iterator a = it->second.buffer.find(syncIndex);
3062  while(a != it->second.buffer.end()){
3063  preservedKeyString += a->second.key;
3064  ++a;
3065  }
3066 
3067  if(!preservedKeyString.empty()){
3068  //Ipv4Address dstKms = it->second.dstKmsNode; //Obtain dstKms adress from assocition entry
3069  UUID ksid = it->second.ksid;
3070 
3072  NS_ASSERT(appConnection.IsValid());
3073  appConnection.PrintRegistryInfo();
3074 
3076  NS_ASSERT(conn.IsValid());
3077  conn.PrintRegistryInfo();
3078 
3079  Ptr<QKDBuffer> buffer = conn.GetSourceBuffer();
3080  if(buffer){
3081  NS_LOG_FUNCTION( this << "Releasing dedicated association buffer ... " );
3082  NS_LOG_FUNCTION( this << "Preserving key material ... " );
3083  NS_LOG_FUNCTION( this << preservedKeyString.size() << " bit of key material preserved ... " );
3084  NS_LOG_FUNCTION( this << "Assigning ID to preserved key material ... " );
3085  Ptr<QKDKey> key = CreateObject<QKDKey> (surplusKeyId, preservedKeyString);
3086  buffer->AddNewKey(key, 1);
3087  NS_LOG_FUNCTION( this << "Preserved key material added to the QKD buffer "
3088  << surplusKeyId << preservedKeyString.size() );
3089  }else{
3090  NS_FATAL_ERROR( this << "QKD buffer not found!" );
3091  }
3092  }
3093  m_associations004.erase(it);
3094  }
3095  NS_LOG_FUNCTION( this << "Key stream association identified with " << ksid << "is removed!" );
3096 
3097 }
3098 
3099 void
3101 {
3102  NS_LOG_FUNCTION( this << "Processing response on KMS /close request ... " );
3103  std::string payload = headerIn.GetMessageBodyString();
3104  nlohmann::json jcloseResponse;
3105  try {
3106  jcloseResponse = nlohmann::json::parse(payload);
3107  } catch (...) {
3108  NS_FATAL_ERROR( this << "JSON parse error!" );
3109  }
3110 
3111  Ipv4Address dstKms = GetDestinationKmsAddress(socket);
3112  std::map<Ipv4Address, std::vector<HttpQuery> >::iterator it = m_httpRequestsQueryKMS.find(dstKms);
3113  if(it == m_httpRequestsQueryKMS.end())
3114  NS_FATAL_ERROR( this );
3115 
3116  std::string ksid = it->second[0].ksid;
3117  std::map<std::string, Association004>::iterator a = m_associations004.find(ksid);
3118  if(a == m_associations004.end()){
3119  NS_LOG_DEBUG( this << " Key stream association identified with " << ksid << " does not exists!" );
3120  return;
3121  }
3122 
3123  if(headerIn.GetStatusCode() == HTTPMessage::NotAcceptable){
3124  //must record key consumed
3125  uint32_t presentKeyMaterial {0};
3126  for (std::map<uint32_t, ChunkKey>::iterator it2 = a->second.buffer.begin(); it2 != a->second.buffer.end(); ++it2){
3127  presentKeyMaterial += it2->second.chunkSize;
3128  }
3129  m_keyServedTraceEmir(presentKeyMaterial);
3130  //m_keyServedTrace((a->second).dstSaeId, presentKeyMaterial);
3131  //m_keyServedWithKSIDTrace(ksid, (a->second).dstSaeId, presentKeyMaterial);
3132 
3133  m_associations004.erase(a); //Just delete association!
3134 
3135  }else if(headerIn.GetStatusCode() == HTTPMessage::Ok){
3136  uint32_t peerSyncIndex {0};
3137  uint32_t localSyncIndex {it->second[0].sync_index};
3138  if(jcloseResponse.contains("sync_index")){
3139  peerSyncIndex = jcloseResponse["sync_index"];
3140  if(peerSyncIndex > localSyncIndex)
3141  localSyncIndex = peerSyncIndex;
3142 
3143  //must record key consumed
3144  uint32_t presentKeyMaterial {0};
3145  for (std::map<uint32_t, ChunkKey>::iterator it2 = a->second.buffer.begin(); it2 != a->second.buffer.find(localSyncIndex); ++it2){
3146  //from begining of buffer until localSyncIndex all keys are not perserved
3147  presentKeyMaterial += it2->second.chunkSize;
3148  }
3149  //m_keyServedTrace((a->second).dstSaeId, presentKeyMaterial);
3150  //m_keyServedWithKSIDTrace(ksid, (a->second).dstSaeId, presentKeyMaterial);
3151  m_keyServedTraceEmir(presentKeyMaterial);
3152 
3153  ReleaseAssociation(it->second[0].ksid, it->second[0].surplus_key_ID, localSyncIndex);
3154  }else{
3155 
3156  //must record key consumed
3157  uint32_t presentKeyMaterial {0};
3158  for (std::map<uint32_t, ChunkKey>::iterator it2 = a->second.buffer.begin(); it2 != a->second.buffer.end(); ++it2){
3159  presentKeyMaterial += it2->second.chunkSize;
3160  }
3161  //m_keyServedTrace((a->second).dstSaeId, presentKeyMaterial);
3162  //m_keyServedWithKSIDTrace(ksid, (a->second).dstSaeId, presentKeyMaterial);
3163  m_keyServedTraceEmir(presentKeyMaterial);
3164 
3165  m_associations004.erase(a);
3166  }
3167 
3168  }else{
3169  NS_FATAL_ERROR( this << "Unknown http status code received" );
3170  }
3171 
3172  HttpKMSCompleteQuery(dstKms);
3173 
3174 }
3175 
3184 void
3186 {
3187  NS_LOG_FUNCTION( this );
3188  std::map<Ipv4Address, std::vector<HttpQuery> >::iterator it = m_httpRequestsQueryKMS.find(dstKms);
3189  if(it != m_httpRequestsQueryKMS.end())
3190  it->second.push_back(request);
3191  else
3192  m_httpRequestsQueryKMS.insert(std::make_pair(dstKms, std::vector<HttpQuery> {request}));
3193 }
3194 
3195 void
3197 {
3198  NS_LOG_FUNCTION( this );
3199  std::map<Ipv4Address, std::vector<HttpQuery> >::iterator it = m_httpRequestsQueryKMS.find(dstKms);
3200  if(it != m_httpRequestsQueryKMS.end())
3201  if(!it->second.empty())
3202  it->second.erase(it->second.begin());
3203  else
3204  NS_FATAL_ERROR( this << "HTTP query for this KMS is empty!");
3205  else
3206  NS_FATAL_ERROR( this << "HTTP query to destination KMS does not exist!" );
3207 }
3208 
3211 {
3212  NS_LOG_FUNCTION( this );
3214  std::map<Ipv4Address, std::vector<HttpQuery> >::iterator it = m_httpRequestsQueryKMS.find(dstKms);
3215  if(it!=m_httpRequestsQueryKMS.end())
3216  methodType = it->second.begin()->method_type;
3217  else
3218  NS_FATAL_ERROR( this << "HTTP response cannot be mapped: HTTP query is empty!" );
3219  return methodType;
3220 }
3221 
3222 void
3224 {
3225  NS_LOG_FUNCTION( this << saeId << socket );
3226  m_http004App.insert (std::make_pair (saeId, socket));
3227 }
3228 
3229 void
3231 {
3232  NS_LOG_FUNCTION( this << saeId );
3233  //Must use equal_range
3234  std::pair<std::multimap<UUID, Ptr<Socket> >::iterator, std::multimap<uint32_t, Ptr<Socket> >::iterator > ret;
3235  //ret = m_http004App.equal_range(saeId);
3236  //if (ret.first == ret.second) NS_FATAL_ERROR( this << "Query is empty" );
3237 
3238  std::multimap<UUID, Ptr<Socket> >::iterator it = ret.first;
3239  m_http004App.erase(it);
3240 
3241 }
3242 
3245 {
3246  NS_LOG_FUNCTION( this << saeId );
3247 
3248  std::pair<std::multimap<UUID, Ptr<Socket> >::iterator, std::multimap<UUID, Ptr<Socket> >::iterator > ret;
3249  //ret = m_http004App.equal_range(saeId);
3250  //if (ret.first == ret.second) NS_FATAL_ERROR( this << "sae query is not registered" );
3251 
3252  std::multimap<UUID, Ptr<Socket> >::iterator it = ret.first;
3253 
3254  NS_LOG_FUNCTION( this << saeId << it->second);
3255  return it->second;
3256 
3257 }
3258 
3261 {
3262  NS_LOG_FUNCTION( this );
3263  Ipv4Address dstKMSAddress;
3264 
3265  std::map<Ipv4Address, std::pair<Ptr<Socket>, Ptr<Socket> > >::iterator it;
3266  for (it = m_socketPairsKMS.begin(); it != m_socketPairsKMS.end(); ++it)
3267  {
3268  if ((it->second).first == socket) {
3269  dstKMSAddress = it->first;
3270  break;
3271  }
3272  }
3273 
3274  return dstKMSAddress;
3275 }
3276 
3277 uint32_t
3279  return m_maxKeyPerRequest;
3280 }
3281 
3284 {
3285  NS_LOG_FUNCTION(this << s);
3286  RequestType output = NONE;
3287 
3288  if(s == "status"){
3289 
3290  return ETSI_QKD_014_GET_STATUS;
3291 
3292  } else if(s == "enc_keys") {
3293 
3294  return ETSI_QKD_014_GET_KEY;
3295 
3296  } else if(s == "dec_keys"){
3297 
3299 
3300  } else if (s == "open_connect"){
3301 
3303 
3304  } else if (s == "get_key") {
3305 
3306  return ETSI_QKD_004_GET_KEY;
3307 
3308  } else if (s == "close") {
3309 
3310  return ETSI_QKD_004_CLOSE;
3311 
3312  } else if (s == "new_app") {
3313 
3314  return NEW_APP;
3315 
3316  } else if (s == "register") {
3317 
3318  return REGISTER;
3319 
3320  } else if (s == "fill") {
3321 
3322  return FILL;
3323 
3324  } else if (s == "store_pp_key") {
3325 
3326  return STORE_PP_KEYS;
3327 
3328  } else if (s == "transform_keys") {
3329 
3330  return TRANSFORM_KEYS;
3331 
3332  } else if (s == "close_kms") {
3333 
3334  return ETSI_QKD_004_KMS_CLOSE;
3335 
3336  } else {
3337 
3338  NS_FATAL_ERROR ("Unknown Type: " << s);
3339  }
3340 
3341  return output;
3342 }
3343 
3344 //function called from QKD Control
3345 //by default srcSaeId == srcNodeId where the link is installed
3346 std::string
3348  uint32_t srcNodeId,
3349  uint32_t dstNodeId,
3350  Ipv4Address kmsDstAddress,
3351  Ptr<QKDBuffer> srcBuffer
3352 ){
3353  return AddNewLink(
3354  srcNodeId,
3355  dstNodeId,
3356  kmsDstAddress,
3357  srcBuffer,
3358  ""
3359  );
3360 }
3361 
3362 
3363 //function called from QKD Control
3364 //by default srcSaeId == srcNodeId where the link is installed
3365 std::string
3367  uint32_t srcNodeId,
3368  uint32_t dstNodeId,
3369  Ipv4Address kmsDstAddress,
3370  Ptr<QKDBuffer> srcBuffer,
3371  std::string keyAssociationIdParam
3372 ){
3373 
3374  NS_LOG_FUNCTION( this
3375  << "srcNodeId: " << srcNodeId
3376  << "dstNodeId: " << dstNodeId
3377  << "m_local: " << m_local
3378  << "kmsDstAddress: " << kmsDstAddress
3379  << "keyAssociationIdParam: " << keyAssociationIdParam
3380  );
3381 
3383  NS_ASSERT (lr);
3384 
3385  std::string keyAssociationId = keyAssociationIdParam;
3386  if(keyAssociationId.empty()){
3387  NS_LOG_FUNCTION(this << "empty!");
3388  QKDKeyAssociationLinkEntry newEntry(
3389  srcNodeId,
3390  dstNodeId,
3391  dstNodeId,//nextHop
3392  1,//dirrect p2p connection (number of hops)
3393  0,// 0-direct; 1-virtual
3394  m_local, //srcKMSAddress
3395  kmsDstAddress, //dstKMSaddress
3396  srcBuffer
3397  );
3398  lr->AddKeyAssociationEntry(newEntry);
3399  keyAssociationId = newEntry.GetId().string();
3400  }else{
3401  NS_LOG_FUNCTION(this << "NOT empty!" << keyAssociationId);
3402  QKDKeyAssociationLinkEntry newEntry(
3403  UUID{keyAssociationId},
3404  srcNodeId,
3405  dstNodeId,
3406  dstNodeId,//nextHop
3407  1,//dirrect p2p connection (number of hops)
3408  0,// 0-direct; 1-virtual
3409  m_local, //srcKMSAddress
3410  kmsDstAddress, //dstKMSaddress
3411  srcBuffer
3412  );
3413  lr->AddKeyAssociationEntry(newEntry);
3414  }
3415 
3416  NS_LOG_FUNCTION (this << "Create sink socket to listen requests exchanged between KMSs!" );
3417 
3418  InetSocketAddress sinkAddress = InetSocketAddress (m_local, 8080);
3419  Ptr<Socket> sinkSocket = Socket::CreateSocket (GetNode (), m_tid);
3420  sinkSocket->Bind (sinkAddress);
3421  sinkSocket->Listen ();
3422  sinkSocket->ShutdownSend ();
3424  sinkSocket->SetAcceptCallback (
3425  MakeNullCallback<bool, Ptr<Socket>, const Address &> (),
3427  );
3428  sinkSocket->SetCloseCallbacks (
3431  );
3432 
3433  //store this socket for further use. Later we will create the send socket as well
3434  Ptr<Socket> sendSocket = 0;
3435  m_socketPairsKMS.insert(
3436  std::make_pair(
3437  kmsDstAddress,
3438  std::make_pair(sinkSocket, sendSocket)
3439  )
3440  );
3441  NS_LOG_FUNCTION( this << kmsDstAddress << sinkSocket << sendSocket );
3442 
3443  //-----------------------
3444  //SEND DETAILS TO SDN CONTROLLER
3445  //-----------------------
3446 
3447 
3448  if(m_sdnSupportEnabled){
3449 
3450  std::ostringstream mkmsAddressTemp;
3451  m_local.Print(mkmsAddressTemp); //IPv4Address to string
3452  std::string mkmsAddressString = mkmsAddressTemp.str(); //Uri starts with destination KMS address
3453 
3454  std::ostringstream skmsAddressTemp;
3455  kmsDstAddress.Print(skmsAddressTemp); //IPv4Address to string
3456  std::string skmsAddressString = skmsAddressTemp.str(); //Uri starts with destination KMS address
3457 
3458  //Notify SDN Controller about the new QKD LINK
3459  nlohmann::json j;
3460  j["master_SAE_ID"] = srcNodeId;
3461  j["slave_SAE_ID"] = dstNodeId;
3462  j["next_hop_id"] = dstNodeId;
3463  j["key_association_id"] = keyAssociationId;
3464  j["hops"] = 0;
3465  j["master_kms_address"] = mkmsAddressString;
3466  j["slave_kms_address"] = skmsAddressString;
3467 
3468  NS_LOG_FUNCTION( this << "Prepared JSON_PACKET_TO_SDN:" << j.dump() );
3469 
3470  std::string msg = j.dump();
3471  HTTPMessage httpHead;
3472 
3474  std::ostringstream sdnAddressTemp;
3475  sdnAddress.Print(sdnAddressTemp); //IPv4Address to string
3476 
3477  std::string headerUri = "http://" + sdnAddressTemp.str ();
3478  headerUri += "/api/v1/keys/" + skmsAddressString + "/register_qkd_link";
3479 
3480  //Create packet
3481  HTTPMessage httpMessage;
3482  httpMessage.CreateRequest(headerUri, "POST", msg);
3483  std::string hMessage = httpMessage.ToString();
3484  Ptr<Packet> packetToSdn = Create<Packet> (
3485  (uint8_t*) (hMessage).c_str(),
3486  hMessage.size()
3487  );
3488 
3489  if(connectedToSDN)
3490  {
3491  NS_LOG_FUNCTION (this << "Sending QKD_LINK_REGISTER to SDN CONTROLLER\n PacketID: "
3492  << packetToSdn->GetUid() << " of size: " << packetToSdn->GetSize()
3493  << hMessage
3494  );
3495  m_sendSocketToSDN->Send(packetToSdn);
3496 
3497  //otherwise wait in the queue
3498  }else{
3499  m_packetQueuesToSDN.insert( std::make_pair( m_sendSocketToSDN , packetToSdn) );
3500  NS_LOG_FUNCTION(this << packetToSdn->GetUid() << "enqued for socket " << m_sendSocketToSDN);
3501  }
3502  }
3503 
3504  return keyAssociationId;
3505 }
3506 
3513  UUID srcSaeId,
3514  UUID dstSaeId,
3515  std::string type, //1-etsi014 (encryption); 2-etsi014(auth); 3-etsi004(encryption); 4-etsi004(auth)
3516  Ipv4Address dstKmsAddress,
3517  uint32_t priority = 0,
3518  double expirationTime = 100
3519 ){
3520 
3521  NS_LOG_FUNCTION( this << "keyId: \t" << "srcSaeId:" << srcSaeId << "dstSaeId:" << dstSaeId << "type:" << type);
3522 
3525  NS_ASSERT (lr);
3526 
3527  lr->AssignKeyAssociation( srcSaeId, dstSaeId, type, priority, conn );
3528  NS_ASSERT(conn.IsValid());
3529  conn.PrintRegistryInfo();
3530  UUID keyAssociationId = conn.GetId();
3531  UUID applicationEntryId = UUID::Nil();
3532 
3533  return RegisterApplicationEntry(
3534  keyAssociationId,
3535  applicationEntryId,
3536  srcSaeId,
3537  dstSaeId,
3538  type,
3539  dstKmsAddress,
3540  priority,
3541  expirationTime
3542  );
3543 }
3544 
3553  UUID keyAssociationId,
3554  UUID applicationEntryId,
3555  UUID srcSaeId,
3556  UUID dstSaeId,
3557  std::string type, //1-etsi014; 2-etsi004
3558  Ipv4Address dstKmsAddress,
3559  uint32_t priority = 0,
3560  double expirationTime = 100
3561 ){
3562 
3563  NS_LOG_FUNCTION( this
3564  << "keyId:" << keyAssociationId
3565  << "applicationEntryId:" << applicationEntryId
3566  << "srcSaeId:" << srcSaeId
3567  << "dstSaeId:" << dstSaeId
3568  << "type:" << type
3569  );
3570 
3572  if(type == "etsi004_enc") {
3574  }else if(type == "etsi004_auth") {
3576  }else if(type == "etsi014_enc") {
3578  }else if(type == "etsi014_auth") {
3580  }
3581  NS_ASSERT (
3586  );
3587  //1-etsi014 (encryption); 2-etsi014(auth); 3-etsi004(encryption); 4-etsi004(auth)
3588 
3589  QKDKeyAssociationLinkEntry conn = GetKeyAssociationById( keyAssociationId );
3590  conn.PrintRegistryInfo();
3591  NS_ASSERT(conn.IsValid());
3592  UUID connectionId = conn.GetId();
3593  NS_LOG_FUNCTION( this << "connectionId FOUND: " << connectionId );
3594 
3596  NS_ASSERT (lr);
3597 
3598  QKDApplicationEntry newEntry(
3599  connectionId,
3600  srcSaeId,
3601  dstSaeId,
3602  linkType,
3603  priority,
3604  expirationTime, //expirationTime
3605  m_local, //srcKMSAddress
3606  dstKmsAddress //dstKMSAddress
3607  );
3608 
3609  if(applicationEntryId != UUID::Nil())
3610  newEntry.SetId(applicationEntryId);
3611 
3612  lr->AddApplicationEntry(newEntry);
3613  lr->UpdateQKDApplications(connectionId, newEntry.GetId());
3614 
3615  //-----------------------
3616  //SEND DETAILS TO SDN CONTROLLER
3617  //-----------------------
3619 
3620  std::ostringstream mkmsAddressTemp;
3621  conn.GetSourceKmsAddress().Print(mkmsAddressTemp); //IPv4Address to string
3622  std::string mkmsAddressString = mkmsAddressTemp.str(); //Uri starts with destination KMS address
3623 
3624  std::ostringstream skmsAddressTemp;
3625  conn.GetDestinationKmsAddress().Print(skmsAddressTemp); //IPv4Address to string
3626  std::string skmsAddressString = skmsAddressTemp.str(); //Uri starts with destination KMS address
3627 
3628  UUID appId = newEntry.GetId();
3629  nlohmann::json j;
3630  j["key_association_id"] = connectionId.string();
3631  j["application_entry_id"] = appId.string();
3632  j["client_SAE_ID"] = srcSaeId.string();
3633  j["server_SAE_ID"] = dstSaeId.string();
3634  j["link_type"] = GetQKDApplicationEntryText(linkType);
3635  j["priority"] = priority;
3636  j["expirationTime"] = expirationTime;
3637  j["master_kms_address"] = mkmsAddressString;
3638  j["slave_kms_address"] = skmsAddressString;
3639 
3640  NS_LOG_FUNCTION( this << "Prepared JSON_PACKET_TO_SDN:" << j.dump() );
3641 
3642  std::string msg = j.dump();
3643  HTTPMessage httpHead;
3644 
3646  std::ostringstream sdnAddressTemp;
3647  sdnAddress.Print(sdnAddressTemp); //IPv4Address to string
3648 
3649  std::string headerUri = "http://" + sdnAddressTemp.str ();
3650  headerUri += "/api/v1/keys/" + skmsAddressString + "/register_sae_link";
3651 
3652  //Create packet
3653  HTTPMessage httpMessage;
3654  httpMessage.CreateRequest(headerUri, "POST", msg);
3655  std::string hMessage = httpMessage.ToString();
3656  Ptr<Packet> packet = Create<Packet> (
3657  (uint8_t*) (hMessage).c_str(),
3658  hMessage.size()
3659  );
3660  NS_ASSERT (packet);
3661 
3662  //send the packet only if connected!
3663  if(connectedToSDN){
3664  NS_LOG_FUNCTION (this << "Sending SAE_REGISTER to SDN CONTROLLER\n PacketID: "
3665  << packet->GetUid() << " of size: " << packet->GetSize()
3666  << hMessage
3667  );
3668  m_sendSocketToSDN->Send(packet);
3669  //otherwise wait in the queue
3670  }else{
3671  m_packetQueuesToSDN.insert( std::make_pair( m_sendSocketToSDN , packet) );
3672  NS_LOG_FUNCTION(this << packet->GetUid() << "enqued for socket " << m_sendSocketToSDN);
3673  }
3674  }
3675 
3676  return newEntry;
3677 
3678 }
3679 
3680 
3681 /*
3682 * This function is called when we have exact SAEIDs of the app
3683 * Then we need to obtain full info about the app from the connection registry
3684 */
3687  std::string srcSaeId,
3688  std::string dstSaeId,
3690 ){
3691  NS_LOG_FUNCTION(this << srcSaeId << dstSaeId << type);
3692 
3693  UUID srcId (srcSaeId);
3694  UUID dstId (dstSaeId);
3695 
3696  QKDApplicationEntry output;
3698  NS_ASSERT (lr);
3699 
3700  lr->LookupApplicationBySaeIDsAndType(srcId, dstId, type, output);
3701  NS_LOG_FUNCTION(this << output.GetId());
3702 
3703  return output;
3704 }
3705 
3706 
3707 
3708 /*
3709 * This function is called when we have ksid
3710 * Then we need to obtain full info about the app from the connection registry
3711 */
3714 {
3715  NS_LOG_FUNCTION(this << ksid);
3716 
3717  UUID tempId (ksid);
3718  QKDApplicationEntry output;
3720  NS_ASSERT (lr);
3721  lr->LookupApplication(tempId, output);
3722  return output;
3723 }
3724 
3725 
3726 /*
3727 * This function is the base of CAC oriented approach.
3728 * Having appId we should find the QKD link (key association) which provides key to the app
3729 * However, if there are multiple key associations, connecition register should decide which
3730 * key association to use to respond to this call.
3731 */
3734 {
3735  NS_LOG_FUNCTION(this << appId);
3736 
3737  UUID tempId (appId);
3740  NS_ASSERT (lr);
3741  lr->LookupKeyAssociationByApplicationId(tempId, output);
3742  return output;
3743 
3744 }
3745 
3746 /*
3747 * This function is called only when adding new key.
3748 * At the current version of post-processing apps we identify QKD links via dstNodeId
3749 */
3751 QKDKeyManagerSystemApplication::GetKeyAssociationByNodeIds(uint32_t srcNodeId, uint32_t dstNodeId)
3752 {
3753  NS_LOG_FUNCTION(this << srcNodeId << dstNodeId);
3754 
3757  NS_ASSERT (lr);
3758  lr->LookupKeyAssociationByDestinationNodeId(srcNodeId, dstNodeId, output);
3759  return output;
3760 }
3761 
3762 /*
3763 * This function is called only when adding new key.
3764 * At the current version of post-processing apps we identify QKD links via dstNodeId
3765 */
3768 {
3769  NS_LOG_FUNCTION(this << keyAssociationId);
3770 
3773  NS_ASSERT (lr);
3774  lr->LookupKeyAssociationById(keyAssociationId, output);
3775  return output;
3776 }
3777 
3778 void
3780 
3781  NS_LOG_FUNCTION(this << entry.GetId());
3782 
3784  NS_ASSERT (lr);
3785  lr->SaveKeyAssociation(entry);
3786 }
3787 
3788 
3789 void
3791  m_node = n;
3792 }
3793 
3794 Ptr<Node>
3796  return m_node;
3797 }
3798 
3799 /*
3800  This funtion checks only Get key request - ETSI014!
3801  It performs check on number, size, additional_slave_SAEs, and some exstensions!
3802  If request is valid then empty JSON structure is returned from this function,
3803  else Error data structure described in ETSI014 is returned!
3804 
3805  In case "keys are being transformed" message is returned, the function should optionally
3806  return a number of keys that must be transformed. This is because the number of keys
3807  to transform can be different from the keyNumber parameter, and is defined as
3808  keyNumber-availableKeyNumber. Omitted by Emir (no need for this in v1) - number of keys
3809  to transform should be decided by KMS (via request monitoring).
3810 */
3813 {
3814 
3815  NS_LOG_FUNCTION(this << conn.GetId());
3816 
3817  //IMPORTANT NOTE: It is assumed that number and size allowed by KMS is same on both sides! Therefore,
3818  //one does not need to check those parametes in GetKeyWithKeyIDs request!
3819  uint32_t keyNumber = 1; //Default number - ETSI014.
3820  uint32_t keySize = m_defaultKeySize; //Default size - KMS defined / or buffer defined.
3821  if(jrequest.contains("number")){ //There is keyNumber specified in request
3822  keyNumber = jrequest["number"];
3823  }
3824  if(jrequest.contains("size")){ //There is keySize specified
3825  keySize = jrequest["size"]; //Key size in bits!
3826  }
3827  nlohmann::json jError; //Check the values of specified parameters!
3828  if( //Message 1: requested parameters do not adhere to KMS rules
3829  keyNumber > GetMaxKeyPerRequest() ||
3830  keyNumber <= 0 ||
3831  keySize > m_maxKeySize ||
3832  keySize < m_minKeySize ||
3833  keySize % 8 != 0
3834  ){ //Message 1!
3835  jError["message"] = std::string {"requested parameters do not adhere to KMS rules"};
3836  //Fill the details of error Message!
3837  if(keyNumber > GetMaxKeyPerRequest()){
3838  std::string msgDetail = "requested number of keys (" + std::to_string(keyNumber) + ") is higher then a maximum number of keys (" + std::to_string(GetMaxKeyPerRequest()) + ") per request allowed by KMS";
3839  NS_LOG_FUNCTION(this << conn.GetId() << "ERROR: " << msgDetail);
3840  jError["details"].push_back({{"number_unsupported", msgDetail}});
3841  }else if(keyNumber <= 0){
3842  std::string msgDetail = "requested number of keys can not be lower or equal to zero";
3843  NS_LOG_FUNCTION(this << conn.GetId()<< "ERROR: " << msgDetail);
3844  jError["details"].push_back({{"number_unsupported", msgDetail}});
3845  }
3846  if(keySize > m_maxKeySize){
3847  std::string msgDetail = "requested size of keys (" + std::to_string(keySize) + ") is higher then a maximum size of key (" + std::to_string(m_maxKeySize) + ") that KMS can deliver";
3848  NS_LOG_FUNCTION(this << conn.GetId()<< "ERROR: " << msgDetail);
3849  jError["details"].push_back({{"size_unsupported", msgDetail}});
3850  }else if(keySize < m_minKeySize){
3851  std::string msgDetail = "requested size of keys (" + std::to_string(keySize) + ") is lower then a minimum size of key (" + std::to_string(m_minKeySize) + ") that KMS can deliver";
3852  NS_LOG_FUNCTION(this << conn.GetId()<< "ERROR: " << msgDetail);
3853  jError["details"].push_back({{"size_unsupported", msgDetail}});
3854  }else if(keySize % 8 != 0){
3855  std::string msgDetail = "size shall be a multiple of 8";
3856  NS_LOG_FUNCTION(this << conn.GetId()<< "ERROR: " << msgDetail);
3857  jError["details"].push_back({{"size_unsupported", msgDetail}});
3858  }
3859  return jError;
3860 
3861  }else{
3862 
3863  Ptr<QKDBuffer> buffer = conn.GetSourceBuffer();
3864  NS_LOG_FUNCTION(this << "krecCheck");
3865  NS_LOG_FUNCTION(this << conn.GetId() << "\nTarget key size: " << keySize << "\nTarget number: "
3866  << keyNumber << "\nRequired amount of key material: " << keySize*keyNumber);
3867  NS_LOG_FUNCTION(this << conn.GetId() << "\nAmount of key material in buffer: " << buffer->GetKeyCountBit()
3868  << "\nAmount of key material ready to be served: " << buffer->GetReadyKeyCountBit()
3869  << "\nAmount of key material part of target set: " << buffer->GetTargetKeyCountBit());
3870  if(buffer && keySize*keyNumber > buffer->GetReadyKeyCountBit()){ //Check if there is enough key material!
3871  jError["message"] = std::string {"insufficient amount of key material"};
3872  return jError;
3873  }else if(buffer && buffer->GetKeyCount(keySize) < keyNumber){
3874  //Check the amount of key for transformation purpose:
3875  if(buffer->GetReadyKeyCountBit() - buffer->GetTargetKeyCountBit() < keySize*keyNumber){
3876  jError["message"] = "insufficient amount of key material";
3877  NS_LOG_FUNCTION(this << conn.GetId() << "ERROR: " << jError["message"]);
3878  }else{
3879  jError["message"] = "keys are being transformed";
3880  NS_LOG_FUNCTION(this << conn.GetId() << "ERROR: " << jError["message"]);
3881  }
3882  }
3883 
3884  }
3885 
3886  return jError;
3887 }
3888 
3889 
3890 bool
3891 QKDKeyManagerSystemApplication::AddNewKey(Ptr<QKDKey> key, uint32_t srcNodeId, uint32_t dstNodeId){
3892 
3893  NS_LOG_FUNCTION(this << key->GetId() << key->GetSizeInBits() << srcNodeId << dstNodeId );
3894 
3895  bool output = false;
3896  QKDKeyAssociationLinkEntry keyAssociation = GetKeyAssociationByNodeIds( srcNodeId, dstNodeId );
3897  Ptr<QKDBuffer> buffer = keyAssociation.GetSourceBuffer();
3898 
3899  if(buffer){
3900 
3901  NS_LOG_FUNCTION(this << "Add key to buffer " << buffer << keyAssociation.GetId());
3902  output = buffer->AddNewKey(key,0);
3903 
3904  //Secret key rate generation (in bits per second) of the key association link.
3905  double generationRate = buffer->GetAverageKeyGenerationRate();
3906  keyAssociation.SetSKR(generationRate);
3907 
3908  //Sum of all the application's bandwidth (in bits per second) on this particular key association link.
3909  double averageConsumptionRate = buffer->GetAverageKeyConsumptionRate();
3910  keyAssociation.SetExpectedConsumption(averageConsumptionRate);
3911 
3912  //Effective secret key rate (in bits per second) generation of the key association link available after internal consumption
3913  double expectedConsumptionRate = keyAssociation.GetExpectedConsumption();
3914  double ratio = generationRate - expectedConsumptionRate;
3915 
3916  //if ratio is negative, it means old keys are taken from the buffer (not from the newly secret key rate)
3917  keyAssociation.SetEffectiveSKR(ratio);
3918 
3919  NS_LOG_FUNCTION(this
3920  << "keyAssociationId:" << keyAssociation.GetId()
3921  << "AverageKeyGenerationRate:" << keyAssociation.GetSKR()
3922  << "ExpectedConsumption:" << keyAssociation.GetExpectedConsumption()
3923  << "EffectiveSKR:" << keyAssociation.GetEffectiveSKR()
3924  );
3925 
3926  SaveKeyAssociation(keyAssociation);
3927 
3928  }else{
3929  NS_FATAL_ERROR(this << "No buffer found!");
3930  }
3931 
3932  return output;
3933 
3934 }
3935 
3936 /*
3937  Create key container json data structure described in ETSI014.
3938  Limits the size of obtained key to requested size by QKDApp ->
3939  This should be changed in @futureBuild. In GetKeysFromBuffer KMS shall
3940  split or merge the keys and take keySize in consideration while searching for key!
3941  Now, we do not have description of such KMS beahviour (@futureBuild)!
3942 */
3945 {
3946 
3947  NS_LOG_FUNCTION( this << "Create JSON Key Container data structure!");
3948  nlohmann::json jkeys;
3949  for(uint32_t i = 0; i < keys.size(); i++){
3950  if(keys[i]){
3951  std::string encodedKey = Base64Encode(keys[i]->ConsumeKeyString()); //Encode fetched key in Base64
3952  NS_LOG_FUNCTION(this << "KEY" << i+1 << keys[i]->GetId() << encodedKey << "\n");
3953  jkeys["keys"].push_back({ {"key_ID", keys[i]->GetId()}, {"key", encodedKey} });
3954  }
3955  }
3956  return jkeys;
3957 
3958 }
3959 
3967 std::string
3969 {
3970  NS_LOG_FUNCTION( this );
3971  std::string output;
3972  UUID ksidRaw = UUID::Random();
3973  //UUID ksidRaw = UUID::Sequential();
3974  output = ksidRaw.string();
3975  NS_LOG_FUNCTION(this << output);
3976  return output;
3977 }
3978 
3979 void
3981 {
3982  /*
3983  To check the state of a single association! Master!
3984  */
3985  NS_LOG_FUNCTION(this << "Checking the state of the association " << ksid << " ...");
3986  std::map<std::string, Association004>::iterator it = m_associations004.find(ksid);
3987  if(it == m_associations004.end()){
3988  NS_LOG_DEBUG( this << " Key stream association identified with " << ksid << " does not exists!" );
3989  return;
3990  }
3991 
3992  if(it->second.associationDirection == 0 && it->second.peerRegistered){ //Check
3993  if(
3994  (it->second).tempBuffer.empty() &&
3995  ((it->second).buffer.empty() || !(it->second).buffer.begin()->second.ready)
3996  ){
3998  ksid,
3999  it->second.qos.maxRate,
4000  it->second.qos.priority
4001  ); //Starts reservation of keys for the association
4002  }
4003 
4004  }else if(it->second.associationDirection == 1){
4005  NS_FATAL_ERROR(this << "This function must not be called on replica KMS for a given association " << ksid);
4006  }
4007 }
4008 
4009 void
4011 {
4012  NS_LOG_FUNCTION(this);
4013  std::map<std::string, Association004>::iterator it;
4014  int64_t currentTime = Simulator::Now ().GetSeconds();
4015  for (it = m_associations004.begin(); it != m_associations004.end();)
4016  {
4017  if( it->second.qos.TTL < currentTime ) {
4018  NS_LOG_FUNCTION(this << "remove association "
4019  << "ksid: " << (it->second).ksid
4020  << "srcSaeId: " << (it->second).srcSaeId
4021  << "dstSaeId: " << (it->second).dstSaeId
4022  << " with TTL time: " << it->second.qos.TTL
4023  );
4024  m_associations004.erase (it++);
4025  }else{
4026  it++;
4027  }
4028  }
4029 }
4030 
4031 
4032 void
4033 QKDKeyManagerSystemApplication::NegotiateKeysForAssociation (std::string ksid, uint32_t keyAmount, uint32_t priority)
4034 {
4035  NS_LOG_FUNCTION( this << ksid << keyAmount );
4037 
4038  std::map<std::string, Association004>::iterator it = m_associations004.find(ksid);
4039  if(it == m_associations004.end()){
4040  NS_LOG_DEBUG( this << " Key stream association identified with " << ksid << " does not exists!" );
4041  return;
4042  }
4043 
4044  UUID dstSae = (it->second).dstSaeId; //Obtain destination SAE
4045  QKDApplicationEntry appConnection = GetApplicationConnectionDetails( ksid );
4046  NS_ASSERT(appConnection.IsValid());
4047  appConnection.PrintRegistryInfo();
4048 
4050  NS_ASSERT(conn.IsValid());
4051  conn.PrintRegistryInfo();
4052 
4053  Ptr<QKDBuffer> buffer = conn.GetSourceBuffer(); //Buffer for this connection
4054  if(buffer){
4055  nlohmann::json jkeyIDs; //KeyIDs of the keys to fill the association buffer. Keys shall be marked reserved!
4056  if(
4057  buffer->GetReadyKeyCountBit() - buffer->GetTargetKeyCountBit() < keyAmount &&
4058  buffer->GetReadyKeyCountBit() - buffer->GetTargetKeyCountBit() >= it->second.qos.chunkSize
4059  ){
4060  //Minimum amount of key material that could be assigned to the association buffer
4061  keyAmount = it->second.qos.chunkSize;
4062  }else if(buffer->GetReadyKeyCountBit() - buffer->GetTargetKeyCountBit() < it->second.qos.chunkSize){
4063  NS_LOG_FUNCTION( this << "Not enough key material to assign to the association dedicated buffer!" );
4064  //for premium apps mantain the key assoications
4065  if(priority > 0) ScheduleCheckAssociation(Time ("500ms"), "CheckAssociation", ksid); //Shedule new attempt!
4066  return;
4067  }
4068 
4069  bool addKeysReady = false;
4070  while(!addKeysReady){
4071  Ptr<QKDKey> key = buffer->SearchOptimalKeyToTransform(keyAmount);
4072  NS_ASSERT(key->GetId() != ""); //Check
4073  NS_ASSERT(key->GetSizeInBits() != 0); //Check
4074  buffer->ReserveKey(key->GetId()); //Reserve key for transformation! @toDo include reservation_type
4075  jkeyIDs["keys"].push_back({ {"key_ID", key->GetId()} }); //Add keyId object to JSON
4076  (it->second).tempBuffer.push_back(key->GetId()); //Add keyId to tempBuffer
4077 
4078  if(key->GetSizeInBits() >= keyAmount){
4079  addKeysReady = true;
4080  keyAmount = 0;
4081  }else
4082  keyAmount -= key->GetSizeInBits();
4083 
4084  NS_LOG_FUNCTION(this << "Found key " << key->GetId() << " of size " << key->GetSizeInBits() << " to transform.\n Remaining key ammount to find: " << keyAmount);
4085  }
4086 
4087  Ipv4Address dstKms = (it->second).dstKmsNode;
4088  std::ostringstream peerkmsAddressTemp;
4089  dstKms.Print(peerkmsAddressTemp); //IPv4Address to string
4090  std::string headerUri = "http://" + peerkmsAddressTemp.str ();
4091  headerUri += "/api/v1/associations/fill/" + ksid;
4092 
4093  std::string msg = jkeyIDs.dump();
4094 
4095  //Create packet
4096  HTTPMessage httpMessage;
4097  httpMessage.CreateRequest(headerUri, "POST", msg);
4098  std::string hMessage = httpMessage.ToString();
4099  Ptr<Packet> packet = Create<Packet> (
4100  (uint8_t*) (hMessage).c_str(),
4101  hMessage.size()
4102  );
4103  NS_ASSERT (packet);
4104 
4105  CheckSocketsKMS( dstKms ); //Check connection to peer KMS!
4106  Ptr<Socket> sendSocket = GetSendSocketKMS( dstKms );
4107 
4108  HttpQuery query;
4109  query.method_type = FILL;
4110  query.destination_sae = dstSae;
4111  query.ksid = ksid;
4112  HttpKMSAddQuery(dstKms, query);
4113 
4114  sendSocket->Send(packet);
4115  NS_LOG_FUNCTION( this << "Proposal of keys to fill association " << ksid
4116  << " dedicated store is sent!" << packet->GetUid() << packet->GetSize() << headerUri << msg );
4117  }else{
4118  NS_FATAL_ERROR( this << "QKD Buffer for this connection is not found!" );
4119  }
4120 
4121 }
4122 
4123 void
4125 {
4126  NS_LOG_FUNCTION( this << ksid << key->GetId() );
4127  std::map<std::string, Association004>::iterator it = m_associations004.find(ksid);
4128  if(it == m_associations004.end()){
4129  NS_LOG_DEBUG( this << " Key stream association identified with " << ksid << " does not exists!" );
4130  return;
4131  }
4132 
4133  uint32_t keyChunkSize = (it->second).qos.chunkSize /8; //Obtain chunk size (in bytes) from the QoS structure!
4134  std::string secretKey = key->ConsumeKeyString(); //Obtain key string
4135 
4136  NS_LOG_FUNCTION( this << "Secret key size (bytes) " << secretKey.size() );
4137  NS_LOG_FUNCTION( this << "Last index - " << (it->second).lastIndex );
4138  uint32_t startingIndex = (it->second).lastIndex; //Find the starting index to fill the buffer with the secret key
4139  bool startingInReady = true; //Is the starting index an existing index thats not ready, or a next to generate index!
4140 
4141  if((it->second).buffer.rbegin() != (it->second).buffer.rend()){
4142  startingIndex = (it->second).buffer.rbegin()->first;
4143  if( ((it->second).buffer.rbegin()->second).ready != true )
4144  startingInReady = false;
4145  else
4146  startingIndex++;
4147  }else if((it->second).lastIndex != 0)
4148  startingIndex++;
4149 
4150  NS_LOG_FUNCTION (this << "Chunk size (bytes), Start Index, Start Ready" << keyChunkSize << startingIndex << startingInReady);
4151  //Fill the content of the secret key into the buffer!
4152  while (!secretKey.empty())
4153  {
4154  if(!startingInReady)
4155  {
4156  uint32_t currentChunkSize = ( (it->second).buffer.rbegin()->second ).key.size(); //In bytes
4157  NS_LOG_FUNCTION( this << "currentChunkSize" << currentChunkSize);
4158  uint32_t diff = keyChunkSize - currentChunkSize; //In bytes
4159  NS_LOG_FUNCTION( this << "diff" << diff );
4160  //Check the size of the secretKey, is it enough to fill the diff
4161  std::string incompleteChunkKey = (it->second).buffer.rbegin()->second.key;
4162  if(secretKey.size() >= diff){
4163  std::string diffKey = secretKey.substr(0, diff);
4164  std::string temp = secretKey.substr(diff);
4165  secretKey = temp;
4166  std::string completeKey = incompleteChunkKey+diffKey;
4167  NS_LOG_FUNCTION( this << incompleteChunkKey << diffKey << completeKey);
4168 
4169  (it->second).buffer.rbegin()->second.key = completeKey;
4170  (it->second).buffer.rbegin()->second.ready = true;
4171 
4172  NS_LOG_FUNCTION( this << startingIndex << (it->second).buffer.rbegin()->second.key );
4173 
4174  startingIndex++;
4175  startingInReady = true;
4176  }else{
4177  std::string completeKey = incompleteChunkKey+secretKey;
4178  secretKey = "";
4179  (it->second).buffer.rbegin()->second.key = completeKey;
4180  startingIndex++; //Increase index
4181  }
4182 
4183  }else{
4184  uint32_t len; //len is in bytes
4185  if (secretKey.size() >= keyChunkSize)
4186  len = keyChunkSize;
4187  else
4188  len = secretKey.size();
4189 
4190  std::string temp; //Remaining secret key
4191  std::string key; //Key to store as a chunk
4192  key = secretKey.substr(0, len);
4193  temp = secretKey.substr(len);
4194  secretKey = temp;
4195 
4196  NS_LOG_FUNCTION( this << startingIndex << key);
4197 
4198  ChunkKey keyC;
4199  keyC.key = key;
4200  keyC.index = startingIndex;
4201  keyC.chunkSize = len*8; //In bits (variable not really needed)
4202  if (len == keyChunkSize)
4203  keyC.ready = true;
4204  else
4205  keyC.ready = false;
4206 
4207  (it->second).buffer.insert(std::make_pair(startingIndex, keyC));
4208  startingIndex++; //Increase index
4209  }
4210  }
4211 
4212  (it->second).lastIndex = startingIndex - 1;
4213  NS_LOG_FUNCTION( this << "Last index stored is " << (it->second).lastIndex );
4214 
4215  NS_LOG_FUNCTION(this << "ksid:" << ksid);
4216  NS_LOG_FUNCTION(this << "Is association empty:" << (it->second).buffer.empty() );
4217  NS_LOG_FUNCTION(this << "Is association first key ready:" << (it->second).buffer.begin()->second.ready );
4218  NS_LOG_FUNCTION(this << "How many keys do we have in association:" << (it->second).buffer.size() );
4219 
4220 }
4221 
4222 std::string
4224 {
4225  std::string output;
4226  CryptoPP::StringSource(input, true,
4227  new CryptoPP::Base64Encoder(
4228  new CryptoPP::StringSink(output)
4229  ) // Base64Encoder
4230  ); // StringSource
4231  return output;
4232 }
4233 
4234 std::string
4236 {
4237  std::string output;
4238  CryptoPP::StringSource(input, true,
4239  new CryptoPP::Base64Decoder(
4240  new CryptoPP::StringSink(output)
4241  ) // Base64Dencoder
4242  ); // StringSource
4243  return output;
4244 }
4245 
4246 void
4249  nlohmann::json jOpenConnectRequest
4250 ){
4251 
4252  inQos.chunkSize = 0;
4253  inQos.maxRate = 0;
4254  inQos.minRate = 0;
4255  inQos.jitter = 0;
4256  inQos.priority = 0;
4257  inQos.timeout = 0;
4258  inQos.TTL = 0;
4259 
4260  if (jOpenConnectRequest.contains("QoS")) {
4261  if (jOpenConnectRequest["QoS"].contains("key_chunk_size")) inQos.chunkSize = jOpenConnectRequest["QoS"]["key_chunk_size"];
4262  if (jOpenConnectRequest["QoS"].contains("max_bps")) inQos.maxRate = jOpenConnectRequest["QoS"]["max_bps"];
4263  if (jOpenConnectRequest["QoS"].contains("min_bps")) inQos.minRate = jOpenConnectRequest["QoS"]["min_bps"];
4264  if (jOpenConnectRequest["QoS"].contains("jitter")) inQos.jitter = jOpenConnectRequest["QoS"]["jitter"];
4265  if (jOpenConnectRequest["QoS"].contains("priority")) inQos.priority = jOpenConnectRequest["QoS"]["priority"];
4266  if (jOpenConnectRequest["QoS"].contains("timeout")) inQos.timeout = jOpenConnectRequest["QoS"]["timeout"];
4267  if (jOpenConnectRequest["QoS"].contains("TTL")) inQos.TTL = jOpenConnectRequest["QoS"]["TTL"];
4268  }
4269 
4270  NS_LOG_FUNCTION(this << inQos.chunkSize << inQos.maxRate << inQos.minRate << inQos.TTL);
4271 
4272  NS_ASSERT (inQos.chunkSize > 0);
4273  NS_ASSERT (inQos.maxRate >= 0);
4274  NS_ASSERT (inQos.minRate >= 0);
4275  NS_ASSERT (inQos.TTL > 0);
4276 
4277  NS_LOG_FUNCTION(this << "chunkSize:" << inQos.chunkSize);
4278  NS_LOG_FUNCTION(this << "max_bps:" << inQos.maxRate);
4279  NS_LOG_FUNCTION(this << "min_bps:" << inQos.minRate);
4280  NS_LOG_FUNCTION(this << "jitter:" << inQos.jitter);
4281  NS_LOG_FUNCTION(this << "priority:" << inQos.priority);
4282  NS_LOG_FUNCTION(this << "timeout:" << inQos.timeout);
4283  NS_LOG_FUNCTION(this << "TTL:" << inQos.TTL);
4284 }
4285 
4286 void
4288  std::string srcSaeId,
4289  std::string dstSaeId,
4291  Ipv4Address dstKms,
4292  std::string &ksid,
4293  std::string appConnectionId
4294 ){
4295  NS_LOG_FUNCTION( this << srcSaeId << dstSaeId << m_local << dstKms << ksid << appConnectionId);
4296  inQos.TTL += Simulator::Now ().GetSeconds();
4297 
4299  association004.srcSaeId = srcSaeId;
4300  association004.dstSaeId = dstSaeId;
4301  association004.qos = inQos;
4302  association004.dstKmsNode = dstKms;
4303  association004.lastIndex = 0;
4304  if(ksid.empty()){
4305  ksid = appConnectionId; //GenerateKsid();
4306  association004.associationDirection = 0; //Outbound
4307  association004.peerRegistered = false;
4308  }else{
4309  association004.associationDirection = 1; //Inbound
4310  association004.peerRegistered = true;
4311  }
4312  association004.ksid = ksid;
4313 
4314  NS_LOG_FUNCTION(this << ksid << appConnectionId);
4315 
4316  m_associations004.insert(std::make_pair (ksid, association004));
4317  m_sessionList.insert(std::make_pair (ksid, 1));
4318 }
4319 
4320 bool
4322  QKDApplicationEntry &appConnection,
4323  QKDKeyAssociationLinkEntry &keyAssociation,
4326  std::string ksid
4327 ){
4328 
4329  NS_LOG_FUNCTION( this
4330  << "ksid:" << ksid
4331  << "minRate:" << inQos.minRate
4332  << "maxRate:" << inQos.maxRate
4333  << "priority:" << inQos.priority
4334  << "chunkSize:" << inQos.chunkSize
4335  << "jitter:" << inQos.jitter
4336  << "timeout:" << inQos.timeout
4337  << "TTL:" << inQos.TTL
4338  << "eskr:" << keyAssociation.GetEffectiveSKR()
4339  << "consumption:" << keyAssociation.GetExpectedConsumption()
4340  );
4341 
4342 
4343  double ratioSKR;
4344  if(keyAssociation.GetExpectedConsumption() == 0)
4345  ratioSKR = 1;
4346  else
4347  ratioSKR = (double) keyAssociation.GetExpectedConsumption()/(double) keyAssociation.GetEffectiveSKR();
4348 
4349  NS_LOG_FUNCTION(this
4350  << "keyAssociationId:" << keyAssociation.GetId()
4351  << "SKR:" << keyAssociation.GetSKR()
4352  << "EffectiveSKR:" << keyAssociation.GetEffectiveSKR()
4353  << "ratioSKR:" << ratioSKR
4354  << "ExpectedConsumption:" << keyAssociation.GetExpectedConsumption()
4355  );
4356 
4357  uint32_t processWithQos = 1;
4358 
4359  if(processWithQos)
4360  {
4361 
4362  outQos = inQos;
4363  if(
4364  inQos.maxRate == 0 ||
4365  keyAssociation.GetEffectiveSKR() < m_minKeyRate.GetBitRate()
4366  ){
4367  NS_LOG_FUNCTION(this << "No resources available!");
4368  outQos.maxRate = 0;
4369 
4370  m_providedQoS(
4371  appConnection.GetId().string(),
4372  keyAssociation.GetId().string(),
4373  ceil(inQos.maxRate/inQos.chunkSize),
4374  round (keyAssociation.GetEffectiveSKR()/inQos.chunkSize),
4375  0,
4376  0,
4377  inQos.priority
4378  );
4379 
4380  return false;
4381 
4382  }else if (
4383  ratioSKR < m_qos_maxrate_threshold
4384  ) {
4385 
4386  if(inQos.priority == 0){
4387  NS_LOG_FUNCTION(this << "No resources for low-priority requests!");
4388  outQos.maxRate = 0;
4389 
4390  m_providedQoS(
4391  appConnection.GetId().string(),
4392  keyAssociation.GetId().string(),
4393  ceil(inQos.maxRate/inQos.chunkSize),
4394  round (keyAssociation.GetEffectiveSKR()/inQos.chunkSize),
4395  0,
4396  0,
4397  inQos.priority
4398  );
4399 
4400  return false;
4401  }else{
4402  std::map<std::string, uint32_t>::iterator it2 = m_sessionList.find(ksid);
4403  if(it2 != m_sessionList.end()){
4404  NS_LOG_FUNCTION(this << "SESSION with KSID " << ksid << " was located in the m_session_list!");
4405  }else{
4406  NS_LOG_FUNCTION(this << "SESSION with KSID " << ksid << " was *NOT* located in m_session_list!");
4407  NS_LOG_FUNCTION(this << "WE HAVE NO ENOUGH RESOURCES TO SERVE UNTRUSTED APPS AT THE MOMENT!");
4408  outQos.maxRate = 0;
4409 
4410  m_providedQoS(
4411  appConnection.GetId().string(),
4412  keyAssociation.GetId().string(),
4413  ceil(inQos.maxRate/inQos.chunkSize),
4414  round (keyAssociation.GetEffectiveSKR()/inQos.chunkSize),
4415  0,
4416  0,
4417  inQos.priority
4418  );
4419 
4420  return false;
4421  }
4422  }
4423 
4424  } else {
4425 
4427  uint32_t chunkSizeDoubled = (inQos.chunkSize*1);
4428  uint32_t requestedNumberOfChunkKeys = 0;
4429  if(inQos.maxRate >0 && inQos.maxRate < chunkSizeDoubled){
4430  requestedNumberOfChunkKeys = 1;
4431  }else{
4432  requestedNumberOfChunkKeys = ceil(inQos.maxRate/chunkSizeDoubled);
4433  }
4434  uint32_t supportedNumberOfChunkKeys = round (keyAssociation.GetEffectiveSKR()/chunkSizeDoubled);
4435  uint32_t priorityThreshold = round(supportedNumberOfChunkKeys/2);
4436  uint32_t providedNumberOfChunkKeys;
4437 
4438  if(inQos.priority == 1){
4439  providedNumberOfChunkKeys = m_random->GetValue (priorityThreshold, supportedNumberOfChunkKeys);
4440  }else{
4441  providedNumberOfChunkKeys = m_random->GetValue (1,priorityThreshold);
4442  }
4443  //even if we have enough resources, only give what is requested
4444  if(providedNumberOfChunkKeys > requestedNumberOfChunkKeys)
4445  providedNumberOfChunkKeys = requestedNumberOfChunkKeys;
4446 
4447  NS_LOG_FUNCTION(this << "requestedNumberOfChunkKeys:" << requestedNumberOfChunkKeys);
4448  NS_LOG_FUNCTION(this << "supportedNumberOfChunkKeys:" << supportedNumberOfChunkKeys);
4449  NS_LOG_FUNCTION(this << "priorityThreshold:" << priorityThreshold);
4450  NS_LOG_FUNCTION(this << "providedNumberOfChunkKeys:" << providedNumberOfChunkKeys);
4451  outQos.maxRate = providedNumberOfChunkKeys * inQos.chunkSize;
4453 
4455  uint32_t providedTTL = m_default_ttl;
4456  NS_LOG_FUNCTION(this << "DefaultTTL:" << m_default_ttl);
4457 
4458  std::map<std::string, uint32_t>::iterator it2 = m_sessionList.find(ksid);
4459  if(it2 != m_sessionList.end()){
4460  providedTTL *= it2->second;
4461  NS_LOG_FUNCTION(this << "SESSION with KSID " << ksid << " was located in the m_session_list!");
4462  }else{
4463  NS_LOG_FUNCTION(this << "SESSION with KSID " << ksid << " was *NOT* located in m_session_list!");
4464  }
4465  //even if we have enough resources, only give what is requested
4466  if(providedTTL > inQos.TTL) providedTTL = inQos.TTL;
4467  outQos.TTL = providedTTL;
4468  NS_LOG_FUNCTION(this << "providedTTL:" << providedTTL);
4470 
4471  NS_LOG_FUNCTION(this << outQos.chunkSize << outQos.maxRate << outQos.minRate << outQos.TTL);
4472 
4473  NS_ASSERT (outQos.chunkSize > 0);
4474  NS_ASSERT (outQos.maxRate >= 0);
4475  NS_ASSERT (outQos.minRate >= 0);
4476  NS_ASSERT (outQos.TTL > 0);
4477 
4478  m_providedQoS(
4479  appConnection.GetId().string(),
4480  keyAssociation.GetId().string(),
4481  requestedNumberOfChunkKeys,
4482  supportedNumberOfChunkKeys,
4483  providedNumberOfChunkKeys,
4484  priorityThreshold,
4485  inQos.priority
4486  );
4487 
4488  return true;
4489  }
4490 
4491  //old strict approach (provide requested keys or not)
4492  }else{
4493 
4494  uint32_t chunkSizeDoubled = (inQos.chunkSize);
4495  uint32_t supportedNumberOfChunkKeys = round (keyAssociation.GetEffectiveSKR()/chunkSizeDoubled);
4496  uint32_t requestedNumberOfChunkKeys = ceil (inQos.maxRate/chunkSizeDoubled);
4497  uint32_t providedNumberOfChunkKeys = requestedNumberOfChunkKeys;
4498  uint32_t priorityThreshold = 0;
4499 
4500  if(requestedNumberOfChunkKeys > supportedNumberOfChunkKeys)
4501  {
4502  outQos.maxRate = 0;
4503  providedNumberOfChunkKeys = 0;
4504  }
4505 
4506  NS_LOG_FUNCTION(this << "requestedNumberOfChunkKeys:" << requestedNumberOfChunkKeys);
4507  NS_LOG_FUNCTION(this << "supportedNumberOfChunkKeys:" << supportedNumberOfChunkKeys);
4508  NS_LOG_FUNCTION(this << "priorityThreshold:" << priorityThreshold);
4509  NS_LOG_FUNCTION(this << "providedNumberOfChunkKeys:" << providedNumberOfChunkKeys);
4510 
4511 
4512  m_providedQoS(
4513  appConnection.GetId().string(),
4514  keyAssociation.GetId().string(),
4515  requestedNumberOfChunkKeys,
4516  supportedNumberOfChunkKeys,
4517  providedNumberOfChunkKeys,
4518  priorityThreshold,
4519  inQos.priority
4520  );
4521  }
4522 
4523 
4524  return true;
4525 }
4526 
4527 
4528 
4529 std::string
4531 
4532  std::string keyId;
4533  //UUID keyIdRaw = UUID::Sequential();
4534  UUID keyIdRaw = UUID::Random();
4535  keyId = keyIdRaw.string();
4536  NS_LOG_FUNCTION(this << keyId);
4537  return keyId;
4538 }
4539 
4540 } // Namespace ns3
a polymophic address class
Definition: address.h:101
bool IsInvalid() const
Definition: address.cc:71
The base class for all ns3 applications.
Definition: application.h:62
void DoDispose() override
Destructor implementation.
Definition: application.cc:86
Class for representing data rates.
Definition: data-rate.h:89
uint64_t GetBitRate() const
Get the underlying bitrate.
Definition: data-rate.cc:305
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:42
An identifier for simulation events.
Definition: event-id.h:55
The basic class to represent both HTTP requests and responses.
Definition: http.h:78
uint16_t GetStatusCode() const
Get the status code for this message.
Definition: http.h:605
std::string GetRequestUri() const
Definition: http.h:431
std::string ToString()
Takes the headers added to the message along with the body and outputs it to a std::string for use in...
Definition: http.h:633
uint32_t GetSize()
Definition: http.h:686
std::string GetUri() const
Grab the uri.
Definition: http.h:519
void CreateRequest(const std::string &url, const std::string &method)
Definition: http.h:738
bool IsFragmented()
Definition: http.h:852
std::string GetMessageBodyString()
Definition: http.h:714
void CreateResponse(const HttpStatus status)
Definition: http.h:785
HTTPMessage::HttpMethod GetMethod() const
Definition: http.h:482
std::string GetStatusMessage() const
Get the current status message for this message.
Definition: http.h:623
A basic class to parse a HTTP message, both request and response.
Definition: http.h:941
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.
Definition: ipv4-address.h:42
void Print(std::ostream &os) const
Print this address to the given output stream.
static Ipv4Address GetAny()
uint32_t GetId() const
Definition: node.cc:117
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:471
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:354
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:861
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:400
void RemoveAtStart(uint32_t size)
Remove size bytes from the start of the current packet.
Definition: packet.cc:384
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
Create a new packet which contains a fragment of the original packet.
Definition: packet.cc:238
uint64_t GetUid() const
Returns the packet's Uid.
Definition: packet.cc:412
std::string ToString() const
Return a string representation of the packet.
Definition: packet.cc:448
void PrintRegistryInfo()
Print the registry information.
ConnectionType
The connection types.
@ ETSI_QKD_004_AUTHENTICATION
@ ETSI_QKD_014_AUTHENTICATION
@ ETSI_QKD_004_ENCRYPTION
@ ETSI_QKD_014_ENCRYPTION
@ NONE
UUID GetSrcSaeId()
Get the source (sender) application identifier.
void SetId(UUID value)
Set the application identifier.
bool IsValid()
Check if entry is valid.
UUID GetId()
Get the application identifier.
Ipv4Address GetDestinationKmsAddress() const
Get the destination KMS IP address.
QKDConnectionRegister is a class used to keep details about distant QKD links and applications.
double GetEffectiveSKR()
uint32_t GetHop()
Ipv4Address GetDestinationKmsAddress() const
Get destination KMS Address.
void SetExpectedConsumption(double value)
void PrintRegistryInfo()
Print registry info.
UUID GetId()
bool IsValid()
Ptr< QKDBuffer > GetSourceBuffer()
double GetSKR()
double GetExpectedConsumption()
Ipv4Address GetSourceKmsAddress() const
Get source KMS Address.
void SetUpdateStatusInterval(double statusInterval)
uint32_t GetType()
double GetUpdateStatusInterval()
void SetSKR(double value)
void SetEffectiveSKR(double value)
@ RESERVED
Definition: qkd-key.h:84
Address m_sdnControllerAddress
The SDN controller address.
void ProcessRegisterResponse(HTTPMessage header, Ptr< Socket > socket)
Process the REGISTER response.
uint32_t GetMaxKeyPerRequest()
Get maximum number of keys that can be supplied via a single response (ETSI QKD 014).
QKDApplicationEntry GetApplicationConnectionDetails(std::string saeId)
Get the application connection details.
TracedCallback< const std::string &, Ptr< QKDKey > > m_keyServedETSI014Trace
A trace for the consumed keys by the ETSI 014 clients.
void HandlePeerCloseKMSs(Ptr< Socket > socket)
Handle a connection close from the KMS.
void DataSend(Ptr< Socket >, uint32_t)
Callback function for the data sent.
Ptr< QKDKMSQueueLogic > m_queueLogic
The KMS Queue Logic for the ETSI 004 QoS handling.
void SendToSocketPairKMS(Ptr< Socket > socket, Ptr< Packet > packet)
Send the packet to the pair socket.
void HandleAccept(Ptr< Socket > s, const Address &from)
Handle an incoming connection from the application.
std::map< std::string, Association004 > m_associations004
The list of active key stream sessions.
Ptr< Socket > GetSendSocketKMS(Ipv4Address kmsDstAddress)
Obtain the send socket.
void DataToSDNSend(Ptr< Socket >, uint32_t)
Callback function for the data sent to the SDN controller.
uint32_t GetTotalRx() const
Get the total amount of received bytes.
void HttpKMSAddQuery(Ipv4Address dstKms, HttpQuery request)
Remember the HTTP request made to the peer KMS.
uint32_t ScheduleCheckAssociation(Time t, std::string action, std::string ksid)
Schedule the next event in the attempt to fill the key stream session buffer.
void ProcessRegisterRequest(HTTPMessage header, std::string ksid, Ptr< Socket > socket)
Process the REGISTER request.
QKDKeyAssociationLinkEntry GetKeyAssociationByNodeIds(uint32_t srcNodeId, uint32_t dstNodeId)
Get the key association link details.
std::multimap< UUID, Ptr< Socket > > m_http004App
The list of HTTP requests (without response) set to the application.
Ipv4Address GetDestinationKmsAddress(Ptr< Socket > socket)
Get the destiantion KMS IP address based on the connected socket.
void Http004AppQuery(UUID saeId, Ptr< Socket > socket)
Remember the HTTP request received from the application.
nlohmann::json Check014GetKeyRequest(nlohmann::json request, QKDKeyAssociationLinkEntry conn)
Validate the request and probe if the KMS can meet the request requirements.
void HandleAcceptKMSs(Ptr< Socket > s, const Address &from)
Handle an incoming connection from the KMS.
void CreateNew004Association(std::string srcSaeId, std::string dstSaeId, QKDKeyManagerSystemApplication::QoS &inQos, Ipv4Address dstKms, std::string &ksid, std::string appConnectionId)
Create a new key stream session.
std::map< Ipv4Address, std::pair< Ptr< Socket >, Ptr< Socket > > > m_socketPairsKMS
The accepted sockets for the communication between KMSs.
void HandleAcceptSDN(Ptr< Socket > s, const Address &from)
Handle an incoming connection from the SDN.
void PurgeExpiredAssociations()
Purge (delete) the expired ETSI 004 key stream sessions based on the QoS - TTL value.
void ProcessPacketKMSs(HTTPMessage header, Ptr< Packet > packet, Ptr< Socket > socket)
Process incoming request at the KM link.
std::string Base64Encode(std::string input)
Base64 encoder.
void ConnectionSucceeded(Ptr< Socket > socket)
Callback function after the connection to the APP is complete.
std::string GenerateKeyId()
Generate unique key identifier.
void ProcessRequestKMS(HTTPMessage header, Ptr< Socket > socket)
Process request from the peer KMS.
std::map< Ptr< Socket >, Ptr< Packet > > m_packetQueues
Buffering unsend messages due to the connection problems.
void TransformKeys(uint32_t keySize, uint32_t keyNumber, UUID slave_SAE_ID)
Transform a number of keys to a given size.
void NewAppRequest(std::string ksid)
Make a NEW_APP request to the peer KMS.
void HttpKMSCompleteQuery(Ipv4Address dstKms)
Remove the HTTP request from the list.
TracedCallback< Ptr< const Packet >, const Address & > m_rxTrace
A trace for the received packets from the applications.
void ProcessResponseKMS(HTTPMessage header, Ptr< Packet > packet, Ptr< Socket > socket)
Process response from the peer KMS.
void SetSocket(std::string type, Ptr< Socket > socket)
Set the sink socket.
void SendQKDLinkStatusToSDN(UUID linkId, double updatePeriod)
Send the QKD link statistics to the SDN controller.
std::string AddNewLink(uint32_t srcSaeId, uint32_t dstSaeId, Ipv4Address kmsDstAddress, Ptr< QKDBuffer > srcBuffer)
Register a new QKD link, or a pair of post-processing applications.
TracedCallback< const std::string &, const uint32_t &, const uint32_t & > m_keyServedETSI004Trace
A trace for the consumed keys by the ETSI 004 clients.
static uint32_t nKMS
The number of created KMSs.
void RegisterRequest(std::string ksid)
Send the REGISTER request.
QKDKeyManagerSystemApplication::RequestType FetchRequestType(std::string s)
Read the request method from the request URI.
void ProcessAddKeysRequest(HTTPMessage h, Ptr< Socket > socket, std::string ksid)
Process the FILL request.
uint32_t m_sdnSupportEnabled
The support for the SDN.
void ProcessCloseRequest(std::string ksid, HTTPMessage header, Ptr< Socket > socket)
void NegotiateKeysForAssociation(std::string ksid, uint32_t keyAmount=1024, uint32_t priority=0)
Add new keys to the key stream session buffer.
void DataSendKMSs(Ptr< Socket >, uint32_t)
Callback function for the data sent to the peer KMS.
void CheckSessionList(std::string ksid)
Check whether a new OPEN_CONNECT was received before the previously established session expired.
Ipv4Address GetAddress()
Get the local IP address.
void HandleReadKMSs(Ptr< Socket > socket)
Handle a packet received from the KMS.
void HandlePeerError(Ptr< Socket > socket)
Handle a connection error from the application.
void HandlePeerErrorSDN(Ptr< Socket > socket)
Handle a connection error from the SDN.
double m_qos_maxrate_threshold
The maximal rate threshold.
void ProcessResponseSDN(HTTPMessage header, Ptr< Packet > packet, Ptr< Socket > socket)
Process response from the SDN controller.
TracedCallback< const Ipv4Address &, Ptr< const Packet > > m_dropTrace
A trace for the dropped packets.
void HandlePeerClose(Ptr< Socket > socket)
Handle an connection close from the application.
TracedCallback< Ptr< const Packet >, const Address & > m_rxTraceKMSs
A trace for the received packets from the peer KMS.
nlohmann::json CreateKeyContainer(std::vector< Ptr< QKDKey >> keys)
Create the key container data structure.
QKDApplicationEntry GetApplicationConnectionDetailsBySaeIDsAndType(std::string srcSaeId, std::string dstSaeId, QKDApplicationEntry::ConnectionType type)
Get the application connection details.
uint32_t m_maliciousBlocking
Should KMS detect and block malicious requests?
std::map< Ptr< Socket >, Ptr< Socket > > m_socketPairs
The accepted sockets.
void PacketReceivedKMSs(const Ptr< Packet > &p, const Address &from, Ptr< Socket > socket)
Assemble a byte stream from the peer KMS to extract the HTTP message.
void ProcessTransformRequest(HTTPMessage header, Ptr< Socket > socket)
Process the transform request.
TracedCallback< const uint32_t & > m_newKeyGeneratedTraceEmir
A trace for the generated keys.
void ProcessGetKey004Request(std::string ksid, HTTPMessage header, Ptr< Socket > socket)
Ptr< Socket > GetSocketFromHttp004AppQuery(UUID saeId)
Lookup the HTTP request and obtain connected socket.
void ProcessOpenConnectRequest(HTTPMessage header, Ptr< Socket > socket)
std::map< Ptr< Socket >, Ptr< Socket > > GetAcceptedSockets(void) const
Get the list of all the accepted sockets.
void ProcessNewAppResponse(HTTPMessage header, Ptr< Socket > socket)
Process the NEW_APP response.
bool CheckDoSAttack(HTTPMessage headerIn, Ptr< Socket > socket)
Check for the DoS attack.
void CheckAssociation(std::string ksid)
Check the state of a single key stream session.
Ptr< Socket > m_sinkSocketFromSDN
The sink socket from the SND controller.
void ProcessKMSCloseRequest(HTTPMessage header, Ptr< Socket > socket, std::string ksid)
Process the close request from the peer KMS.
RequestType HttpQueryMethod(Ipv4Address dstKms)
Map the HTTP response and obtain the request method.
std::map< Ipv4Address, uint32_t > m_flagedIPAdr
A list of flaged IP addresses.
uint32_t m_maxKeyPerRequest
The maximal number of keys per request application can ask for.
QKDKeyAssociationLinkEntry GetKeyAssociationById(UUID keyAssociationId)
Get the key association link details.
void ProcessKMSCloseResponse(HTTPMessage header, Ptr< Socket > socket)
Process close response from the peer KMS.
void SaveKeyAssociation(QKDKeyAssociationLinkEntry &rt)
Add the key association.
void ConnectionToSDNSucceeded(Ptr< Socket > socket)
Callback function after the connection to the SDN controller is complete.
void AddKeyToAssociationDedicatedStore(std::string ksid, Ptr< QKDKey > key)
Add the key to the key stream session buffer.
bool connectedToSDN
Is conncted to the SDN controller?
void HandlePeerErrorKMSs(Ptr< Socket > socket)
Handle a connection error from the KMS.
std::map< Ptr< Socket >, Ptr< Packet > > m_packetQueuesToSDN
Buffering unsend messages due to the connection problems.
uint32_t m_defaultKeySize
The default key size KMS will deliver if the size was not defined in the request.
std::vector< std::string > ProcessUriParams(std::string s)
Read the URI parameters in a vector.
void ConnectionToSDNFailed(Ptr< Socket > socket)
Callback function after the connection to the SDN controller has failed.
void ProcessRequestSDN(HTTPMessage header, Ptr< Packet > packet, Ptr< Socket > socket)
Process request from the SDN controller.
void SendToSocketPair(Ptr< Socket > socket, Ptr< Packet > packet)
Send the packet to the pair socket.
TracedCallback< Ptr< const Packet >, const Address & > m_rxTraceSDN
A trace for the received packets from the SDN controller.
uint32_t m_maxKeySize
The maximal size of the key application can request.
uint32_t m_totalRxKMSs
Total bytes sent between KMSs.
void PacketReceivedSDN(const Ptr< Packet > &p, const Address &from, Ptr< Socket > socket)
Assemble a byte stream from the SDN to extract the HTTP message.
void ProcessTransformResponse(HTTPMessage header, Ptr< Socket > socket)
Process the transform response.
void HandleReadSDN(Ptr< Socket > socket)
Handle a packet received from the SDN.
void HandleRead(Ptr< Socket > socket)
Handle a packet received from the application.
QKDKeyAssociationLinkEntry GetKeyAssociationLinkDetailsByApplicationId(std::string appId)
Get the key association link details.
void ReadJsonQos(QKDKeyManagerSystemApplication::QoS &inQos, nlohmann::json jOpenConnectRequest)
Read the QoS parameters from the JSON OPEN_CONNECT structure.
std::unordered_map< Address, Ptr< Packet >, AddressHash > m_bufferKMS
The buffer for the received packets from the peer KMS (TCP segmentation).
QKDApplicationEntry RegisterApplicationEntry(UUID keyAssociationId, UUID applicationEntryId, UUID srcSaeId, UUID dstSaeId, std::string type, Ipv4Address dstKmsAddress, uint32_t priority, double expirationTime)
Register a new pair of QKD applications.
void StartApplication(void)
Start the KMS Application.
bool ProcessQoSRequest(QKDApplicationEntry &appConnection, QKDKeyAssociationLinkEntry &keyAssociation, QKDKeyManagerSystemApplication::QoS &inQos, QKDKeyManagerSystemApplication::QoS &outQos, std::string ksid)
Process the QoS requirements.
TracedCallback< const std::string &, const std::string &, const uint32_t &, const uint32_t &, const uint32_t &, const uint32_t &, const uint32_t & > m_providedQoS
A trace for the admitted QoS.
void ProcessNewAppRequest(HTTPMessage header, Ptr< Socket > socket)
bool AddNewKey(Ptr< QKDKey > key, uint32_t srcNodeId, uint32_t dstNodeId)
Add new keys to the QKD buffer.
std::string GenerateKsid()
Generate a new key stream session identifier (ksid).
std::map< std::string, uint32_t > m_sessionList
A list of sessions.
std::map< Ipv4Address, std::vector< HttpQuery > > m_httpRequestsQueryKMS
The list of HTTP request (without response) sent to the peer KMS.
uint32_t m_minKeySize
The minimal size of the key application can request.
void PacketReceived(const Ptr< Packet > &p, const Address &from, Ptr< Socket > socket)
Assemble a byte stream from the application to extract the HTTP message.
void StopApplication(void)
Stop the KMS Application.
TracedCallback< Ptr< const Packet > > m_txTraceKMSs
A trace for the sent packets to the peer KMS.
virtual void DoDispose(void)
Destructor implementation.
void ReleaseAssociation(std::string ksid, std::string surplusKeyId, uint32_t syncIndex)
Release the key stream session.
void HandlePeerCloseSDN(Ptr< Socket > socket)
Handle a connection close from the SDN.
void ConnectionFailedKMSs(Ptr< Socket > socket)
Callback function after the connection to the peer KMS has failed.
void ConnectionFailed(Ptr< Socket > socket)
Callback function after the connection to the APP has failed.
void ProcessRequest(HTTPMessage header, Ptr< Packet > packet, Ptr< Socket > socket)
Process incoming requests from the service layer, i.e., QKD applications.
TracedCallback< const uint32_t & > m_keyServedTraceEmir
A trace for the consumed keys.
TracedCallback< Ptr< const Packet > > m_txTrace
A trace for the sent packets to the applications.
void ConnectToSDNController()
Connect to the SDN controller.
Ptr< Socket > GetSocket(void) const
Get the sink socket.
Ptr< Socket > m_sendSocketToSDN
The send socket to the SDN controller.
Ptr< UniformRandomVariable > m_random
The uniform random variable.
void ConnectionSucceededKMSs(Ptr< Socket > socket)
Callback function after the connection to the peer KMS is complete.
void ProcessAddKeysResponse(HTTPMessage header, Ptr< Socket > socket)
Process the FILL response.
void CheckSocketsKMS(Ipv4Address dstSaeId)
Prepare the send socket to communicate with the peer KMS.
uint32_t m_kms_key_id
The counter value to assure generation of the unique key identifiers.
std::string Base64Decode(std::string input)
Base64 decoder.
TracedCallback< const uint32_t &, const uint32_t & > m_newKeyGeneratedTrace
A trace for the generated keys.
Ipv4Address m_local
Local address to bind to.
void Http004AppQueryComplete(UUID saeId)
Remove the HTTP request from the list.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
virtual int Send(Ptr< Packet > p, uint32_t flags)=0
Send data (or dummy data) to the remote host.
virtual Socket::SocketType GetSocketType() const =0
void SetCloseCallbacks(Callback< void, Ptr< Socket >> normalClose, Callback< void, Ptr< Socket >> errorClose)
Detect socket recv() events such as graceful shutdown or error.
Definition: socket.cc:96
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:105
void SetRecvCallback(Callback< void, Ptr< Socket >> receivedData)
Notify application when new data is available to be read.
Definition: socket.cc:128
virtual int ShutdownRecv()=0
@ NS3_SOCK_STREAM
Definition: socket.h:108
@ NS3_SOCK_SEQPACKET
Definition: socket.h:109
void SetDataSentCallback(Callback< void, Ptr< Socket >, uint32_t > dataSent)
Notify application when a packet has been sent from transport protocol (non-standard socket call)
Definition: socket.cc:114
virtual int GetPeerName(Address &address) const =0
Get the peer address of a connected socket.
virtual int ShutdownSend()=0
virtual int Connect(const Address &address)=0
Initiate a connection to a remote host.
static Ptr< Socket > CreateSocket(Ptr< Node > node, TypeId tid)
This method wraps the creation of sockets that is performed on a given node by a SocketFactory specif...
Definition: socket.cc:72
virtual int Close()=0
Close a socket.
virtual int Bind(const Address &address)=0
Allocate a local endpoint for this socket.
virtual int Listen()=0
Listen for incoming connections.
void SetConnectCallback(Callback< void, Ptr< Socket >> connectionSucceeded, Callback< void, Ptr< Socket >> connectionFailed)
Specify callbacks to allow the caller to determine if the connection succeeds of fails.
Definition: socket.cc:87
virtual Ptr< Packet > RecvFrom(uint32_t maxSize, uint32_t flags, Address &fromAddress)=0
Read a single packet from the socket and retrieve the sender address.
static TypeId GetTypeId()
Get the type ID.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:403
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
Universally unique identifier (UUID)
Definition: uuid.h:35
static UUID Random()
Generate random UUID4 (randomly or pseudo-randomly generated version)
Definition: uuid.cc:148
static UUID Nil()
Generate nil UUID0 (all bits set to zero)
Definition: uuid.h:86
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:45
double GetValue(double min, double max)
Get the next random value drawn from the distribution.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
Callback< R, Args... > MakeNullCallback()
Definition: callback.h:747
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
NLOHMANN_BASIC_JSON_TPL_DECLARATION std::string to_string(const NLOHMANN_BASIC_JSON_TPL &j)
user-defined to_string function for JSON values
Definition: json.h:25255
basic_json<> json
default JSON class
Definition: json.h:3000
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:704
Ptr< const AttributeChecker > MakeTypeIdChecker()
Definition: type-id.cc:1250
std::string GetQKDApplicationEntryText(const uint16_t statusCode)
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Definition: double.h:43
Ptr< const AttributeAccessor > MakeTypeIdAccessor(T1 a1)
Definition: type-id.h:598
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46
Definition: second.py:1
The KMS Queue elements.
std::string ksid
Ptr< Socket > socket
Ptr< Packet > packet
HTTPMessage httpMessage
The key within the key stream session buffer.