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",
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")),
98  .AddAttribute ("MinKeyRate", "The minimal key rate (encryption+authentication) provided by the KMS (QoS settings).",
99  DataRateValue (DataRate ("1kb/s")),
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 == 0){
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 == 0){
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 != 0);
548  NS_ASSERT (pair.second != 0);
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 
674  HTTPMessageParser parser;
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 
739  HTTPMessageParser parser;
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 
803  HTTPMessageParser parser;
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
904  << (m_sendSocketToSDN == 0)
908  );
909 
910  if(m_sdnControllerAddress.IsInvalid() == 0) {
911 
912  if(m_sendSocketToSDN == 0){
913  Address sdnAddr = InetSocketAddress(
916  );
925  m_sendSocketToSDN->Connect ( sdnAddr );
926  NS_LOG_FUNCTION (this << "Create new APP socket " << m_sendSocketToSDN << " to reach SDN Controller!");
927  }else{
928  NS_LOG_FUNCTION (this << "Socket to reach SDN Controller exists!" << m_sendSocketToSDN);
929  }
930 
931  if(!m_sinkSocketFromSDN){
932 
933  // Create the sink socket if not already
935  NS_LOG_FUNCTION (this << "Create the sink KMS socket!" << m_sinkSocketFromSDN);
936 
938  NS_LOG_FUNCTION (this
939  << "Sink KMS socket listens on "
940  << m_local
941  << " and port " << sdnPort
942  << " for SDN packets"
943  );
944  // InetSocketAddress sinkAddress = InetSocketAddress (m_local, sdnPort);
945  InetSocketAddress sinkAddress = InetSocketAddress (Ipv4Address::GetAny (), sdnPort);
946 
947  m_sinkSocket->Bind (sinkAddress);
948  m_sinkSocket->Listen ();
952  MakeNullCallback<bool, Ptr<Socket>, const Address &> (),
954  );
958  );
959 
960  }
961 
962  }
963 }
964 
965 void
966 QKDKeyManagerSystemApplication::StopApplication (void) // Called at time specified by Stop
967 {
968  NS_LOG_FUNCTION (this);
969 
970  std::map<Ptr<Socket>, Ptr<Socket> >::iterator j;
971  for (
972  j = m_socketPairs.begin ();
973  !(j == m_socketPairs.end ());
974  j++
975  ){
976  if(j->first != 0) {
977  j->first->Close();
978  j->first->SetRecvCallback (MakeNullCallback<void, Ptr<Socket> > ());
979  }
980  if(j->second != 0) j->second->Close();
981  }
982 
983  if (m_sinkSocket != 0)
984  {
985  m_sinkSocket->Close ();
987  }
988 }
989 
990 uint32_t
991 QKDKeyManagerSystemApplication::ScheduleCheckAssociation(Time t, std::string action, std::string ksid)
992 {
993  NS_LOG_FUNCTION(this << "Scheduling new event in an attempt to fill association buffer " << ksid << " ...");
994  uint32_t scheduleID {0};
995  EventId event;
996  if(action == "CheckAssociation"){
998  //scheduleID = event.GetUid();
999  //m_scheduledChecks.insert( std::make_pair( scheduleID , event) );
1000  NS_LOG_FUNCTION(this << "Event successfully scheduled!");
1001  }else
1002  NS_FATAL_ERROR(this << "Invalid action as the function input recived " << action);
1003 
1004  return scheduleID;
1005 }
1006 
1015 void
1017 {
1018  NS_LOG_FUNCTION (this);
1019 
1020  std::string ksid;
1021  std::string slave_SAE_ID;
1023  std::vector<std::string> uriParams = ProcessUriParams(headerIn.GetUri());
1024 
1025  if(
1026  uriParams.size() > 3 &&
1027  uriParams[1] == "api" &&
1028  uriParams[2] == "v1" &&
1029  uriParams[3] == "keys"
1030  ){
1031 
1032  std::string receivedAddressStr (uriParams[0]);
1033  Ipv4Address receivedAddress = Ipv4Address(receivedAddressStr.c_str()); //string to IPv4Address
1034  NS_LOG_FUNCTION(this << "received address" << receivedAddressStr << receivedAddress);
1035  if(receivedAddress != GetAddress()){
1036  NS_FATAL_ERROR ( this << "The request is not for me!\t" << receivedAddress << "\t" << GetAddress() << "\t" << headerIn.GetUri());
1037  //@toDo: redirect to top-level KMS
1038  }
1039  slave_SAE_ID = uriParams[4];
1040  ksid = uriParams[4];
1041  requestType = FetchRequestType(uriParams[5]);
1042  }
1043 
1044  NS_LOG_FUNCTION(this << "uri:" << headerIn.GetUri());
1045  NS_LOG_FUNCTION (this << "slave_SAE_ID: " << slave_SAE_ID << "requestType: " << requestType );
1046  if(requestType == ETSI_QKD_014_GET_STATUS){ //Process status request
1047 
1048  /*********************************
1049  * PROCESS GET_STATUS
1050  *********************************/
1051 
1052  NS_LOG_FUNCTION ( this << "Fetch status from QKD buffers for connection to destination node" << slave_SAE_ID );
1053 
1054  QKDApplicationEntry appConnection = GetApplicationConnectionDetails( ksid );
1055  NS_ASSERT(appConnection.IsValid());
1056  appConnection.PrintRegistryInfo();
1057 
1059  NS_ASSERT(conn.IsValid());
1060  conn.PrintRegistryInfo();
1061 
1062  Ipv4Address srcKmsAddress = GetAddress();
1063  std::ostringstream srcKmsAddressTemp;
1064  srcKmsAddress.Print(srcKmsAddressTemp); //IPv4Address to string
1065  std::string srcKME = srcKmsAddressTemp.str ();
1066 
1067  Ipv4Address dstKmsAddress = conn.GetDestinationKmsAddress();
1068  std::ostringstream dstKmsAddressTemp;
1069  dstKmsAddress.Print(dstKmsAddressTemp); //IPv4Address to string
1070  std::string dstKME = dstKmsAddressTemp.str ();
1071 
1072  //Status data format (ETSI014) of response!
1073  nlohmann::json j;
1074  j["source_KME_ID"] = srcKME;
1075  j["target_KME_ID"] = dstKME;
1076  j["master_SAE_ID"] = GetNode()->GetId();
1077  j["slave_SAE_ID"] = slave_SAE_ID;
1078  j["key_size"] = m_defaultKeySize; //conn.bufferAlice->GetKeySize();
1079 
1080  Ptr<QKDBuffer> buffer = conn.GetSourceBuffer();
1081  if(buffer){
1082  j["stored_key_count"] = buffer->GetKeyCountBit();
1083  j["max_key_count"] = buffer->GetMaxKeyCount();
1084  }else{
1085  j["stored_key_count"] = 0;
1086  j["max_key_count"] = 0;
1087  }
1088 
1089  j["max_key_per_request"] = GetMaxKeyPerRequest();
1090  j["max_key_size"] = m_maxKeySize; //conn.bufferAlice->GetMaxKeySizeBit();
1091  j["min_key_size"] = m_minKeySize; //conn.bufferAlice->GetMinKeySizeBit();
1092  j["max_SAE_ID_count"] = 0;
1093  NS_LOG_FUNCTION( this << "json_response:" << j.dump() );
1094  std::string msg = j.dump();
1095 
1096  //create packet
1097  HTTPMessage httpMessage;
1098  httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok, msg, {
1099  {"Content-Type", "application/json; charset=utf-8"},
1100  {"Request URI", headerIn.GetUri() }
1101  });
1102  std::string hMessage = httpMessage.ToString();
1103  Ptr<Packet> packet = Create<Packet> (
1104  (uint8_t*) (hMessage).c_str(),
1105  hMessage.size()
1106  );
1107  NS_ASSERT (packet != 0);
1108 
1109  NS_LOG_FUNCTION (this << "Sending Response to ETSI_QKD_014_GET_STATUS\n PacketID: " << packet->GetUid() << " of size: " << packet->GetSize() << hMessage );
1110  SendToSocketPair(socket, packet);
1111 
1112  }else if(requestType == ETSI_QKD_014_GET_KEY){
1113 
1114  /*********************************
1115  * PROCESS GET_KEY
1116  ********************************/
1117 
1118  NS_LOG_FUNCTION ( this << "Processing ETSI 014 get_key request" );
1119  uint32_t keyNumber = 1; //Default value
1120  uint32_t keySize = m_defaultKeySize; //Default value
1121  nlohmann::json jrequest; //JSON request structure
1122  nlohmann::json errorDataStructure; //JSON error response
1123 
1124  QKDApplicationEntry appConnection = GetApplicationConnectionDetails( ksid );
1125  NS_ASSERT(appConnection.IsValid());
1126  appConnection.PrintRegistryInfo();
1127 
1129  NS_ASSERT(conn.IsValid());
1130  conn.PrintRegistryInfo();
1131 
1132  NS_LOG_FUNCTION(this << conn.GetId() << headerIn.GetUri());
1133 
1134  if(headerIn.GetMethod() == HTTPMessage::HttpMethod::GET){
1135  int k = 5;
1136  while(k < int(uriParams.size())){ //Read number and size from URI
1137  if(uriParams[k] == "number")
1138  keyNumber = std::stoi(uriParams[k+1]);
1139  else if(uriParams[k] == "size")
1140  keySize = std::stoi(uriParams[k+1]); //Key size in bits!
1141  k += 2;
1142  }
1143  jrequest = {{"number", keyNumber}, {"size", keySize}}; //Create jrequest based on URI
1144 
1145  }else if(headerIn.GetMethod() == HTTPMessage::HttpMethod::POST){
1146  std::string payload = headerIn.GetMessageBodyString(); //Read payload
1147  try{ //Try parse JSON
1148  jrequest = nlohmann::json::parse(payload);
1149  if (jrequest.contains("number"))
1150  keyNumber = jrequest["number"];
1151  if (jrequest.contains("size"))
1152  keySize = uint32_t(jrequest["size"]); //Key size in bits!
1153  }catch(...){
1154  NS_FATAL_ERROR( this << "JSON parse error of the received payload: " << payload << "\t" << payload.length() );
1155  }
1156 
1157  }else
1158  NS_FATAL_ERROR(this << "Invalid HTTP request method" << headerIn.GetMethod()); //@toDo: include HTTP response?
1159 
1160  errorDataStructure = Check014GetKeyRequest(jrequest, conn); //Check get_key request!
1161  if(!errorDataStructure.empty()){ //Respond with error!
1162 
1163  NS_LOG_FUNCTION( this << "Get key request error" << errorDataStructure.dump() );
1164  HTTPMessage::HttpStatus statusCode = HTTPMessage::HttpStatus::BadRequest; //Response status code!
1165  if(errorDataStructure.contains("message")){
1166  if(errorDataStructure["message"] == "keys are being transformed"){
1167  statusCode = HTTPMessage::HttpStatus::ServiceUnavailable;
1168  conn.GetSourceBuffer()->RecordTargetSize(keySize);
1169  TransformKeys(keySize, keyNumber, UUID{ksid} ); //Transform keys
1170  }else if(errorDataStructure["message"] == "insufficient amount of key material")
1171  statusCode = HTTPMessage::HttpStatus::ServiceUnavailable;
1172  }
1173  errorDataStructure["ksid"] = ksid;
1174  std::string msg = errorDataStructure.dump();
1175 
1176  //create packet
1177  HTTPMessage httpMessage;
1178  httpMessage.CreateResponse(statusCode, msg, {
1179  {"Content-Type", "application/json; charset=utf-8"},
1180  {"Request URI", headerIn.GetUri() }
1181  });
1182  std::string hMessage = httpMessage.ToString();
1183  Ptr<Packet> packet = Create<Packet> (
1184  (uint8_t*) (hMessage).c_str(),
1185  hMessage.size()
1186  );
1187  NS_ASSERT (packet != 0);
1188 
1189  NS_LOG_FUNCTION (this << "1185 Sending Response to ETSI_QKD_014_GET_KEY\n PacketID: " << packet->GetUid() << " of size: " << packet->GetSize() << hMessage );
1190  SendToSocketPair(socket, packet);
1191 
1192  }else{ //Respond to get_key request!
1193 
1194  std::vector<Ptr<QKDKey>> keys {}; //Vector of QKD keys!
1195  Ptr<QKDBuffer> buffer = conn.GetSourceBuffer(); //Obtain the object of the corresponding QKD buffer!
1196  if(buffer){
1197  buffer->RecordTargetSize(keySize);
1198  for(uint32_t i = 0; i < keyNumber; i++){
1199  keys.push_back(buffer->FetchKeyBySize(keySize)); //Obtain keys!
1200  }
1201  }else {
1202  NS_FATAL_ERROR( this << "Buffer not found! ");
1203  }
1204 
1205  NS_ASSERT(keys.size() == keyNumber); //Unexpected error
1206  nlohmann::json jkeys = CreateKeyContainer(keys);
1207  jkeys["ksid"] = ksid;
1208  std::string msg = jkeys.dump();
1209  NS_LOG_FUNCTION( this << "json_response:" << msg );
1210 
1211  //@toDo: reserve these keys on peer KMS -> KMS to KMS reserve_keys
1212 
1213  //create packet
1214  HTTPMessage httpMessage;
1215  httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok, msg, {
1216  {"Content-Type", "application/json; charset=utf-8"},
1217  {"Request URI", headerIn.GetUri() }
1218  });
1219  std::string hMessage = httpMessage.ToString();
1220  Ptr<Packet> packet = Create<Packet> (
1221  (uint8_t*) (hMessage).c_str(),
1222  hMessage.size()
1223  );
1224  NS_ASSERT (packet != 0);
1225 
1226  NS_LOG_FUNCTION( this << "1221 Sending Response to ETSI_QKD_014_GET_KEY\n PacketID: " << packet->GetUid() << " of size: " << packet->GetSize() << hMessage );
1227  SendToSocketPair(socket, packet);
1228 
1229  //FIRE TRACE SOURCES
1230  for(uint32_t i=0; i<keys.size(); i++){
1231  m_keyServedETSI014Trace(ksid, keys[i]);
1232  }
1233 
1234  m_keyServedTraceEmir (keyNumber * keySize);
1235  //m_keyServedTrace(dstSaeId, keySizeServed); //Record amount of served key to the end-user application
1236  //m_keyServedWithKSIDTrace(ksid, dstSaeId, keySizeServed); //Record amount of served key to the end-user application
1237  }
1238 
1239  }else if(requestType == ETSI_QKD_014_GET_KEY_WITH_KEY_IDS){
1240 
1241  /*********************************
1242  * PROCESS GET_KEY_WITH_KEYIDs
1243  *********************************/
1244 
1245  NS_LOG_FUNCTION( this << "Processing ETSI 014 get_key_with_key_ids request" );
1246 
1247  QKDApplicationEntry appConnection = GetApplicationConnectionDetails( ksid );
1248  NS_ASSERT(appConnection.IsValid());
1249  appConnection.PrintRegistryInfo();
1250 
1252  NS_ASSERT(conn.IsValid());
1253  conn.PrintRegistryInfo();
1254 
1255  std::string payload = headerIn.GetMessageBodyString(); //Read payload
1256  nlohmann::json jkeyIDs;
1257  try{
1258  jkeyIDs = nlohmann::json::parse(payload); //Parse packet payload to JSON structure
1259  }catch(...){
1260  NS_FATAL_ERROR( this << "JSON parse error!" );
1261  }
1262 
1263  std::vector<std::string> keyIDs; //Vector containing keyIDs
1264  for (nlohmann::json::iterator it = jkeyIDs["key_IDs"].begin(); it != jkeyIDs["key_IDs"].end(); ++it)
1265  keyIDs.push_back((it.value())["key_ID"]); //keyIDs read from JSON
1266 
1267  NS_LOG_FUNCTION( this << "Requested key with key IDs:" << keyIDs);
1268  //Fetch keys with defined keyIDs from buffer
1269  Ptr<QKDBuffer> buffer = conn.GetSourceBuffer();
1270  std::vector<Ptr<QKDKey>> keys {};
1271  if(buffer){
1272  for(uint32_t i = 0; i < keyIDs.size(); i++){
1273  Ptr<QKDKey> k = buffer->FetchKeyByID(keyIDs[i]);
1274  keys.push_back(k);
1275  if(keys[i] == NULL){
1276  keys = {}; //Only complete acceptence or refusal supported for now!
1277  break;
1278  }
1279  }
1280  }else{
1281  NS_FATAL_ERROR( this << "No QKD key buffer defined!");
1282  }
1283 
1284  if(!keys.empty()){ //Respond to get_key_with_key_ids request
1285 
1286  uint32_t number = keys.size(); //number of keys
1287  uint32_t size = keys[0]->GetSizeInBits(); //size of key
1288 
1289  nlohmann::json jkeys = CreateKeyContainer(keys);
1290  NS_LOG_FUNCTION( this << "json_response:" << jkeys.dump() );
1291  std::string msg = jkeys.dump();
1292 
1293  //create packet
1294  HTTPMessage httpMessage;
1295  httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok, msg, {
1296  {"Content-Type", "application/json; charset=utf-8"},
1297  {"Request URI", headerIn.GetUri() }
1298  });
1299  std::string hMessage = httpMessage.ToString();
1300  Ptr<Packet> packet = Create<Packet> (
1301  (uint8_t*) (hMessage).c_str(),
1302  hMessage.size()
1303  );
1304  NS_ASSERT (packet != 0);
1305 
1306  NS_LOG_FUNCTION (this << "Sending Response to ETSI_QKD_014_GET_KEY\n PacketID: " << packet->GetUid() << " of size: " << packet->GetSize() << hMessage );
1307  SendToSocketPair(socket, packet);
1308 
1309  //FIRE TRACE SOURCE
1310  for(uint32_t i=0; i<keys.size(); i++){
1311  m_keyServedETSI014Trace(ksid, keys[i]);
1312  }
1313 
1314  m_keyServedTraceEmir(number * size);
1315 
1316  }else{ //Respond with error massage
1317  nlohmann::json errorDataStructure = {{"messsage", "key access error"}}; //@toDo: response includes details: keyIds that are non existing
1318  std::string msg = errorDataStructure.dump();
1319 
1320  //create packet
1321  HTTPMessage httpMessage;
1322  httpMessage.CreateResponse(HTTPMessage::HttpStatus::BadRequest, msg, {
1323  {"Content-Type", "application/json; charset=utf-8"},
1324  {"Request URI", headerIn.GetUri() }
1325  });
1326  std::string hMessage = httpMessage.ToString();
1327  Ptr<Packet> packet = Create<Packet> (
1328  (uint8_t*) (hMessage).c_str(),
1329  hMessage.size()
1330  );
1331  NS_ASSERT (packet != 0);
1332 
1333  NS_LOG_FUNCTION(this << "Sending Response to ETSI_QKD_014_GET_KEY\n PacketID: " << packet->GetUid() << " of size: " << packet->GetSize() << hMessage );
1334  SendToSocketPair(socket, packet);
1335  }
1336 
1337  } else if (requestType == ETSI_QKD_004_OPEN_CONNECT) {
1338 
1340  entry.socket = socket;
1341  entry.httpMessage = headerIn;
1342  entry.packet = packet;
1343  entry.ksid = ksid;
1344 
1345  if(m_queueLogic->Enqueue(entry) == false){
1346  Address adr;
1347  socket->GetPeerName(adr);
1349  Ipv4Address ipAdr = iaddr.GetIpv4();
1350  m_dropTrace(ipAdr, packet);
1351  }
1352  entry = m_queueLogic->Dequeue();
1354 
1355  } else if (requestType == ETSI_QKD_004_GET_KEY) {
1356 
1358  entry.socket = socket;
1359  entry.httpMessage = headerIn;
1360  entry.packet = packet;
1361  entry.ksid = ksid;
1362 
1363  /*
1364  Address adr;
1365  socket->GetPeerName(adr);
1366  InetSocketAddress iaddr = InetSocketAddress::ConvertFrom (adr);
1367  Ipv4Address ipAdr = iaddr.GetIpv4();
1368  NS_LOG_FUNCTION (this << "Sender IP address" << ipAdr);
1369 
1370  std::map<Ipv4Address, uint32_t>::iterator it = m_flagedIPAdr.find(ipAdr);
1371  if(it != m_flagedIPAdr.end() && it->second >= 2 && m_maliciousBlocking){
1372  m_dropTrace(ipAdr, packet);
1373  return; //Do not proceed to process this request!
1374  }
1375  NS_LOG_FUNCTION (this << "Sender IP address" << ipAdr << "\t maliciousCount:" << it->second);
1376  */
1377 
1378  if(m_queueLogic->Enqueue(entry) == false){
1379  std::cout << "packet dropped! \n";
1380 
1381  Address adr;
1382  socket->GetPeerName(adr);
1384  Ipv4Address ipAdr = iaddr.GetIpv4();
1385  m_dropTrace(ipAdr, packet);
1386  }
1387  entry = m_queueLogic->Dequeue();
1388  ProcessGetKey004Request(entry.ksid, entry.httpMessage, entry.socket);
1389 
1390  } else if (requestType == ETSI_QKD_004_CLOSE) {
1391  ProcessCloseRequest(ksid, headerIn, socket);
1392 
1393  } else if (requestType == STORE_PP_KEYS) {
1394 
1395  //Read payload
1396  std::string payload = headerIn.GetMessageBodyString();
1397  try {
1398 
1399  //Parse packet payload to JSON structure
1400  nlohmann::json payloadContent = nlohmann::json::parse(payload);
1401  std::string keyId = payloadContent["key_id"];
1402  std::string keyValue = payloadContent["key"];
1403  uint32_t srcNodeId = payloadContent["src_id"];
1404  uint32_t dstNodeId = payloadContent["dst_id"];
1405 
1406  NS_LOG_FUNCTION(this << "\nKeyID:\t" << keyId << "\n");
1407  //NS_LOG_FUNCTION(this << "\nKeyValue:\t" << keyValue << "\n");
1408 
1409  Ptr<QKDKey> newKey = Create<QKDKey> (keyId, keyValue);
1410  AddNewKey(newKey, srcNodeId, dstNodeId);
1411 
1412  m_newKeyGeneratedTrace(dstNodeId, newKey->GetSizeInBits());
1413  m_newKeyGeneratedTraceEmir(newKey->GetSizeInBits());
1414 
1415  } catch(...) {
1416  NS_LOG_FUNCTION( this << "JSON parse error!");
1417  }
1418 
1419  }
1420 }
1421 
1422 void
1424 {
1425  NS_LOG_FUNCTION (this);
1426  if(headerIn.GetUri() != "") //Process request!
1427  ProcessRequestKMS(headerIn, socket);
1428  else //Process response!
1429  ProcessResponseKMS(headerIn, packet, socket);
1430 }
1431 
1432 void
1434 {
1435  NS_LOG_FUNCTION( this << "Processing answer from SDN" );
1436 
1437  if(headerIn.GetStatusCode() == 200)
1438  {
1439  std::vector<std::string> uriParams = ProcessUriParams(headerIn.GetRequestUri());
1440  if(
1441  uriParams.size() > 3 &&
1442  uriParams[1] == "api" &&
1443  uriParams[2] == "v1" &&
1444  uriParams[3] == "keys" &&
1445  uriParams[5] == "register_qkd_link"
1446  ){
1447  NS_LOG_FUNCTION(this << "Processing register_qkd_link reponse!");
1448 
1449  std::string payload = headerIn.GetMessageBodyString();
1450  nlohmann::json sdnResponse;
1451  try{
1452 
1453  sdnResponse = nlohmann::json::parse(payload);
1454  double QKDLinkStatsUpdateInterval = 0;
1455  std::string keyAssociationIdString;
1456  uint32_t registrationAccepted = 0;
1457 
1458  if (sdnResponse.contains("accepted")) registrationAccepted = sdnResponse["accepted"];
1459  if (sdnResponse.contains("qkd_link_update_interval")) QKDLinkStatsUpdateInterval = sdnResponse["qkd_link_update_interval"];
1460  if (sdnResponse.contains("key_association_id")) keyAssociationIdString = sdnResponse["key_association_id"];
1461 
1462  NS_ASSERT(QKDLinkStatsUpdateInterval > 1);
1463  NS_LOG_FUNCTION(this << keyAssociationIdString << registrationAccepted << QKDLinkStatsUpdateInterval);
1464  UUID keyAssociationId = UUID{keyAssociationIdString};
1465 
1466  if(registrationAccepted){
1467 
1468  QKDKeyAssociationLinkEntry keyAssociation = GetKeyAssociationById( UUID{keyAssociationId} );
1469  NS_ASSERT(keyAssociation.IsValid());
1470  keyAssociation.PrintRegistryInfo();
1471  keyAssociation.SetUpdateStatusInterval(QKDLinkStatsUpdateInterval);
1472  SaveKeyAssociation(keyAssociation);
1473 
1474  NS_LOG_FUNCTION(this << "SDN approved registration of QKD LINK between nodes " << keyAssociationId);
1475  EventId event = Simulator::Schedule (
1476  Seconds(QKDLinkStatsUpdateInterval),
1478  this,
1479  keyAssociationId,
1480  QKDLinkStatsUpdateInterval
1481  );
1482 
1483  }else{
1484 
1485  NS_LOG_FUNCTION(this << "SDN FORBIDES registration of QKD LINK between nodes " << keyAssociationId);
1486 
1487  }
1488 
1489  }catch(...) {
1490  NS_FATAL_ERROR( this << "JSON parse error!" );
1491  }
1492 
1493  }
1494 
1495  //Status indicating error!
1496  }else{
1497 
1498  }
1499 }
1500 
1501 void
1503 {
1504  NS_LOG_FUNCTION(this << linkId << updatePeriod);
1505 
1506 
1507  QKDKeyAssociationLinkEntry keyAssociation = GetKeyAssociationById( linkId );
1508  NS_ASSERT(keyAssociation.IsValid());
1509  keyAssociation.PrintRegistryInfo();
1510 
1511  Ptr<QKDBuffer> buffer = keyAssociation.GetSourceBuffer();
1512  if(buffer){
1513 
1514  //Secret key rate generation (in bits per second) of the key association link.
1515  keyAssociation.SetSKR(buffer->GetAverageKeyGenerationRate());
1516 
1517  //Sum of all the application's bandwidth (in bits per second) on this particular key association link.
1518  keyAssociation.SetExpectedConsumption(buffer->GetAverageKeyConsumptionRate());
1519 
1520  //Effective secret key rate (in bits per second) generation of the key association link available after internal consumption
1521  double ratio = buffer->GetAverageKeyGenerationRate() - buffer->GetAverageKeyConsumptionRate();
1522  //if(ratio < 0) ratio = buffer->GetAverageKeyGenerationRate();
1523  //if ratio is negative, it means old keys are taken from the buffer (not from the newly secret key rate)
1524  keyAssociation.SetEffectiveSKR(ratio);
1525 
1526  SaveKeyAssociation(keyAssociation);
1527  }
1528 
1529  //Notify SDN Controller about the new QKD LINK
1530  //send the packet only if connected!
1532 
1533  nlohmann::json j;
1534  j["key_association_id"] = keyAssociation.GetId().string();
1535 
1536  //save to variable since GetSkr or other call sometimes return "null"
1537  //saving to variables convert these values to 0
1538  double skr = keyAssociation.GetSKR();
1539  NS_ASSERT(skr >=0 );
1540  j["qkdl_performance_skr"] = skr;
1541 
1542  double expectedConsumption = keyAssociation.GetExpectedConsumption();
1543  NS_ASSERT(expectedConsumption >=0 );
1544  j["qkdl_performance_expected_consumption"] = expectedConsumption;
1545 
1546  double eskr = keyAssociation.GetEffectiveSKR();
1547  NS_ASSERT(eskr >=0 );
1548  j["qkdl_performance_eskr"] = eskr;
1549 
1550  NS_LOG_FUNCTION( this << "Prepared JSON_PACKET_TO_SDN:" << j.dump() << skr << expectedConsumption << eskr );
1551 
1552  std::string msg = j.dump();
1553  HTTPMessage httpHead;
1554 
1556  std::ostringstream sdnAddressTemp;
1557  sdnAddress.Print(sdnAddressTemp); //IPv4Address to string
1558 
1559  std::ostringstream skmsAddressTemp;
1560  keyAssociation.GetDestinationKmsAddress().Print(skmsAddressTemp); //IPv4Address to string
1561  std::string skmsAddressString = skmsAddressTemp.str(); //Uri starts with destination KMS address
1562 
1563  std::string headerUri = "http://" + sdnAddressTemp.str ();
1564  headerUri += "/api/v1/keys/" + skmsAddressString + "/key_association_status";
1565 
1566  //Create packet
1567  HTTPMessage httpMessage;
1568  httpMessage.CreateRequest(headerUri, "POST", msg);
1569  std::string hMessage = httpMessage.ToString();
1570  Ptr<Packet> packet = Create<Packet> (
1571  (uint8_t*) (hMessage).c_str(),
1572  hMessage.size()
1573  );
1574  NS_ASSERT (packet != 0);
1575 
1576  NS_LOG_FUNCTION (this << "Sending KEY_ASSOCIATION_STATUS to SDN CONTROLLER\n PacketID: "
1577  << packet->GetUid() << " of size: " << packet->GetSize()
1578  << hMessage
1579  );
1580  m_sendSocketToSDN->Send(packet);
1581 
1582  }
1583 
1584  if(m_sdnSupportEnabled){
1585 
1586  EventId event = Simulator::Schedule (
1587  Seconds(updatePeriod),
1589  this,
1590  keyAssociation.GetId(),
1591  keyAssociation.GetUpdateStatusInterval()
1592  );
1593  }
1594 
1595 
1596 }
1597 
1598 void
1600 {
1601  NS_LOG_FUNCTION( this << "Processing request from SDN" );
1602 
1603  //Status OK
1604  if(headerIn.GetStatusCode() == 200)
1605  {
1606  std::vector<std::string> uriParams = ProcessUriParams(headerIn.GetRequestUri());
1607  if(
1608  uriParams.size() > 3 &&
1609  uriParams[1] == "api" &&
1610  uriParams[2] == "v1" &&
1611  uriParams[3] == "keys" &&
1612  uriParams[5] == "register_qkd_link"
1613  ){
1614  NS_LOG_FUNCTION(this << "Processing register_qkd_link reponse!");
1615  }
1616 
1617  //Status indicating error!
1618  }else{
1619 
1620  }
1621 }
1622 
1623 std::vector<std::string>
1625 {
1626  NS_LOG_FUNCTION(this << s);
1627  std::vector<std::string> uriParams;
1628 
1629  if(s.length() > 0){
1630  std::string delimiter = "/";
1631  size_t pos = 0;
1632  std::string token;
1633  while ((pos = s.find(delimiter)) != std::string::npos) {
1634  token = s.substr(0, pos);
1635  if(token.length() > 0){
1636  uriParams.push_back(token);
1637  }
1638  s.erase(0, pos + delimiter.length());
1639  }
1640  if(s.length() > 0)
1641  uriParams.push_back(s);
1642 
1643  NS_LOG_FUNCTION(this << uriParams[0]);
1644  }
1645 
1646  return uriParams;
1647 }
1648 
1649 
1650 void
1652 {
1653  NS_LOG_FUNCTION( this << "Processing request from peer KMS ... " );
1655  std::vector<std::string> uriParams = ProcessUriParams(headerIn.GetUri());
1656 
1657  NS_LOG_FUNCTION( this << "krecA" << uriParams[0] << uriParams[1] << uriParams[2] << uriParams[3] );
1658  if(
1659  uriParams.size() > 3 && //@toDo for etsi 004 functions add KMS address in URI!
1660  uriParams[1] == "api" &&
1661  uriParams[2] == "v1" &&
1662  (uriParams[3] == "associations" ||
1663  uriParams[3] == "keys")
1664  ){
1665  requestType = FetchRequestType(uriParams[4]); // new_app, register, fill, transform_keys, close
1666  }
1667 
1668  if(requestType == NEW_APP)
1669  ProcessNewAppRequest(headerIn, socket);
1670  else if(requestType == REGISTER){
1671  std::string ksid = uriParams[5];
1672  NS_ASSERT ( !ksid.empty() );
1673  ProcessRegisterRequest(headerIn, ksid, socket);
1674  }else if(requestType == FILL){
1675  std::string ksid = uriParams[5];
1676  NS_ASSERT ( !ksid.empty() );
1677  ProcessAddKeysRequest(headerIn, socket, ksid); //Process proposal of keys!
1678  }else if(requestType == TRANSFORM_KEYS){
1679  ProcessTransformRequest(headerIn, socket);
1680  }else if(requestType == ETSI_QKD_004_KMS_CLOSE){
1681  std::string ksid = uriParams[5];
1682  NS_ASSERT ( !ksid.empty() );
1683  ProcessKMSCloseRequest(headerIn, socket, ksid);
1684  }else
1685  NS_FATAL_ERROR( this << "Invalid request made to this KMS!" );
1686 }
1687 
1688 void
1690 {
1691  NS_LOG_FUNCTION( this << "Processing peer KMS response" );
1692  Ipv4Address dstKMS = GetDestinationKmsAddress(socket);
1694 
1695  if(methodType == NEW_APP)
1696  ProcessNewAppResponse(headerIn, socket);
1697  else if(methodType == REGISTER)
1698  ProcessRegisterResponse(headerIn, socket);
1699  else if(methodType == FILL)
1700  ProcessAddKeysResponse(headerIn, socket);
1701  else if(methodType == TRANSFORM_KEYS)
1702  ProcessTransformResponse(headerIn, socket);
1703  else if(methodType == ETSI_QKD_004_KMS_CLOSE)
1704  ProcessKMSCloseResponse(headerIn, socket);
1705  else
1706  NS_FATAL_ERROR( this << "Invalid request method!" );
1707 
1708 }
1709 
1710 
1719 bool
1721 {
1722  NS_LOG_FUNCTION(this);
1723 
1724  //Get the address of the application node making this malicious request
1725  Address adr;
1726  socket->GetPeerName(adr);
1728  Ipv4Address ipAdr = iaddr.GetIpv4();
1729  NS_LOG_FUNCTION (this << "Sender IP address" << ipAdr);
1730 
1731  if(m_maliciousBlocking){
1732  std::map<Ipv4Address, uint32_t>::iterator it = m_flagedIPAdr.find(ipAdr);
1733  if(it == m_flagedIPAdr.end()){
1734  m_flagedIPAdr.insert(std::make_pair(ipAdr, 1));
1735  NS_LOG_FUNCTION (this << "This request has been flaged as potentialy malicious!"
1736  << "This IPAddress" << ipAdr << "will be penalized after the next offense!");
1737  }else{
1738  NS_LOG_FUNCTION (this << "KMS identified request coming from" << ipAdr << "as malicious request."
1739  << "This IPAddress is now blocked!");
1740  it->second++;
1741  return true;
1742  }
1743  }
1744  return false;
1745 }
1746 
1753 void
1755 {
1756  NS_LOG_FUNCTION(this << ksid);
1757 
1758  NS_LOG_FUNCTION(this << "Checking the state of the association " << ksid << " ...");
1759  std::map<std::string, Association004>::iterator it = m_associations004.find(ksid);
1760  if(it == m_associations004.end()){
1761  NS_LOG_DEBUG( this << " Key stream association identified with " << ksid << " does not exists!" );
1762  }else{
1763  if(
1764  (it->second).tempBuffer.empty() &&
1765  ((it->second).buffer.empty() || !(it->second).buffer.begin()->second.ready)
1766  ){
1767  NS_LOG_FUNCTION(this << ksid << "SESSION EXPIRED!");
1768  std::map<std::string, uint32_t>::iterator it2 = m_sessionList.find(ksid);
1769  if(it2 != m_sessionList.end()){
1770  it2->second++;
1771  NS_LOG_FUNCTION(this << "SESSION with KSID " << ksid << " was favored in the m_session_list!");
1772  }else{
1773  NS_LOG_FUNCTION(this << "SESSION with KSID " << ksid << " was not located in m_session_list!");
1774  }
1775  }else{
1776  NS_LOG_FUNCTION(this << ksid << "SESSION DID NOT EXPIRE!");
1777  std::map<std::string, uint32_t>::iterator it2 = m_sessionList.find(ksid);
1778  if(it2 != m_sessionList.end()){
1779  m_sessionList.erase(it2);
1780  NS_LOG_FUNCTION(this << "SESSION with KSID " << ksid << " was removed from the m_session_list!");
1781  }else{
1782  NS_LOG_FUNCTION(this << "SESSION with KSID " << ksid << " was not located in m_session_list!");
1783  }
1784  }
1785  }
1786 }
1787 
1788 void
1790 {
1791  NS_LOG_FUNCTION(this << headerIn.GetUri());
1792 
1793  if(CheckDoSAttack(headerIn, socket)) return;
1794 
1795  std::string payload = headerIn.GetMessageBodyString();
1796  NS_LOG_FUNCTION( this << payload);
1797 
1798  nlohmann::json jOpenConnectRequest;
1799  try{
1800  jOpenConnectRequest = nlohmann::json::parse(payload);
1801  }catch(...) {
1802  NS_FATAL_ERROR( this << "JSON parse error!" );
1803  }
1804 
1805  std::string ksid;
1806  std::string dstSaeId;
1807  std::string srcSaeId;
1809  if(jOpenConnectRequest.contains("Key_stream_ID")) ksid = jOpenConnectRequest["Key_stream_ID"];
1810  if(jOpenConnectRequest.contains("Source")) srcSaeId = jOpenConnectRequest["Source"];
1811  if(jOpenConnectRequest.contains("Destination")) dstSaeId = jOpenConnectRequest["Destination"];
1812  NS_ASSERT (srcSaeId.length() > 0);
1813  NS_ASSERT (dstSaeId.length() > 0);
1814 
1815  NS_LOG_FUNCTION(this << ksid << srcSaeId << dstSaeId);
1816 
1817  if(ksid.length() > 0) CheckSessionList(ksid);
1818 
1819  ReadJsonQos(inQos, jOpenConnectRequest);
1820 
1821  bool callByMaster {ksid.empty()};
1822  if(callByMaster){
1823 
1824  std::vector<std::string> uriParams = ProcessUriParams(headerIn.GetUri());
1825  uint32_t type = std::stoi(uriParams[6]);
1826 
1828  if(type == 0) {
1830  }else if(type == 1) {
1832  }
1834  //1-etsi014 (encryption); 2-etsi014(auth); 3-etsi004(encryption); 4-etsi004(auth)
1835 
1836  //ksid is empty
1837  //we need to fetch QKD application entry (if any)
1838  QKDApplicationEntry appConnection = GetApplicationConnectionDetailsBySaeIDsAndType( srcSaeId, dstSaeId, linkType );
1839  appConnection.PrintRegistryInfo();
1840 
1841  //there is no connection found in our registry
1842  //we might connect to other networks (roaming) or ask SDN controller
1843  //about further actions. However, for now we throw exception!
1844  //we DO NOT create new SAE connection here since in case of DDoS attack
1845  // it would be very expensive decision. Registration of SAEs MUST be indidiviual task!
1846  NS_ASSERT(appConnection.IsValid());
1847 
1848  //now we have connection details.
1849  //let's find for associated key association link
1850  //if multiple links are associated, then randomly selected one!
1852  NS_ASSERT(conn.IsValid());
1853  conn.PrintRegistryInfo();
1854 
1855  NS_LOG_FUNCTION(this << "Processing OPEN_CONNECT request submitted by the primary QKDApp ...");
1856  Ipv4Address dstKms = conn.GetDestinationKmsAddress();
1857 
1858  //CAC verification
1860  bool acceptRequest = ProcessQoSRequest(appConnection, conn, inQos, providedQoS, ksid);
1861 
1862  if(acceptRequest){
1863 
1864  //Create association with provided QoS
1866  srcSaeId,
1867  dstSaeId,
1868  providedQoS,
1869  dstKms,
1870  ksid,
1871  appConnection.GetId().string()
1872  ); //Establish association
1873 
1874  if(conn.GetType() == 0){ // Direct point-to-point connection. Respond immediately
1875  nlohmann::json jOpenConnectResponse;
1876  jOpenConnectResponse["Key_stream_ID"] = ksid;
1877  jOpenConnectResponse["QoS"] = {
1878  {"priority", providedQoS.priority},
1879  {"max_bps", providedQoS.maxRate},
1880  {"min_bps", providedQoS.minRate},
1881  {"jitter", providedQoS.jitter},
1882  {"timeout", providedQoS.timeout},
1883  {"key_chunk_size", providedQoS.chunkSize},
1884  {"TTL", providedQoS.TTL}
1885  };
1886  std::string msg = jOpenConnectResponse.dump();
1887 
1888  //create packet
1889  HTTPMessage httpMessage;
1890  httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok, msg, {
1891  {"Content-Type", "application/json; charset=utf-8"},
1892  {"Request URI", headerIn.GetUri() }
1893  });
1894  std::string hMessage = httpMessage.ToString();
1895  Ptr<Packet> packet = Create<Packet> (
1896  (uint8_t*) (hMessage).c_str(),
1897  hMessage.size()
1898  );
1899  NS_ASSERT (packet != 0);
1900 
1901  SendToSocketPair(socket, packet);
1902 
1903  NS_LOG_FUNCTION(this << "KMS providing OK answer to OPEN_CONNECT!" << msg << packet->GetUid() << packet->GetSize());
1904 
1905  }else{ //Wait on NewAppResponse to respond to QKDApp
1906  Http004AppQuery(UUID{srcSaeId}, socket); //Query this received HTTP request!
1907  }
1908  NewAppRequest(ksid); //Send NEW_APP notification
1909  }else{
1910 
1911  NS_LOG_FUNCTION(this << "KMS is not able to answer to QoS request from the application " << appConnection.GetId().string());
1912 
1913  //create packet
1914  HTTPMessage httpMessage;
1915  httpMessage.CreateResponse(HTTPMessage::HttpStatus::BadRequest, "", {
1916  {"Request URI", headerIn.GetUri() }
1917  });
1918  std::string hMessage = httpMessage.ToString();
1919  Ptr<Packet> packet = Create<Packet> (
1920  (uint8_t*) (hMessage).c_str(),
1921  hMessage.size()
1922  );
1923  NS_ASSERT (packet != 0);
1924 
1925  SendToSocketPair(socket, packet);
1926 
1927  }
1928 
1929  } else {
1930 
1931  NS_LOG_FUNCTION( this << "OPEN_CONNECT by Replica SAE" );
1932  //Check if ksid has been registered for this SAE
1933  std::map<std::string, Association004>::iterator it = m_associations004.find(ksid);
1934  if (it == m_associations004.end()) {
1935  NS_LOG_DEBUG( this << " Key stream association identified with " << ksid << " does not exists!" );
1936  return;
1937  } else if ((it->second).srcSaeId != UUID{srcSaeId}) {
1938  NS_LOG_FUNCTION( this << "KSID is not registered for this application" << (it->second).dstSaeId << srcSaeId );
1939  //Respond with an error! //@toDo
1940  } else {
1941 
1942  (it->second).peerRegistered = true;
1943  RegisterRequest(ksid);
1944 
1945  //Respond to OPEN_CONNECT made by SAE
1946 
1947  //create packet
1948  HTTPMessage httpMessage;
1949  httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok, "", {
1950  {"Request URI", headerIn.GetUri() }
1951  });
1952  std::string hMessage = httpMessage.ToString();
1953  Ptr<Packet> packet = Create<Packet> (
1954  (uint8_t*) (hMessage).c_str(),
1955  hMessage.size()
1956  );
1957  NS_ASSERT (packet != 0);
1958 
1959  SendToSocketPair(socket, packet);
1960 
1961  }
1962  }
1963 
1964 }
1965 
1966 void
1968 {
1969  NS_LOG_FUNCTION( this << "Processing get_key request (ETSI 004)" << ksid );
1970 
1971  std::map<std::string, Association004>::iterator it = m_associations004.find(ksid);
1972  if(it == m_associations004.end()){
1973 
1974  if(CheckDoSAttack(headerIn, socket)) return;
1975 
1976  NS_LOG_DEBUG( this << " Key stream association identified with " << ksid << " does not exists!" );
1977 
1978  //create packet
1979  HTTPMessage httpMessage;
1980  httpMessage.CreateResponse(HTTPMessage::HttpStatus::BadRequest, "", {
1981  {"Request URI", headerIn.GetUri() }
1982  });
1983  std::string hMessage = httpMessage.ToString();
1984  Ptr<Packet> packet = Create<Packet> (
1985  (uint8_t*) (hMessage).c_str(),
1986  hMessage.size()
1987  );
1988  NS_ASSERT (packet != 0);
1989 
1990  SendToSocketPair(socket, packet);
1991  return;
1992  }
1993 
1994  //PeerRegistered must be true @toDo - first check this (in case of QKDApp004 this will never happen)
1995  if( !(it->second).buffer.empty() && (it->second).buffer.begin()->second.ready )
1996  {
1997 
1998  QKDApplicationEntry appConnection = GetApplicationConnectionDetails( ksid );
1999  if(appConnection.IsValid())
2000  {
2001  appConnection.PrintRegistryInfo();
2002 
2003  uint32_t index;
2004  std::string key;
2005  index = (it->second).buffer.begin()->first;
2006  key = (it->second).buffer.begin()->second.key;
2007  (it->second).buffer.erase((it->second).buffer.begin()); //Remove the key
2008  if(it->second.associationDirection == 0){
2009  CheckAssociation(ksid); //Check if new keys need to be negotiated
2010  }
2011 
2012  nlohmann::json jresponse;
2013  jresponse["index"] = index;
2014  jresponse["Key_buffer"] = key;
2015  //No Metadata
2016  std::string msg = jresponse.dump();
2017 
2018  //create packet
2019  HTTPMessage httpMessage;
2020  httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok, msg, {
2021  {"Content-Type", "application/json; charset=utf-8"},
2022  {"Request URI", headerIn.GetUri() }
2023  });
2024  std::string hMessage = httpMessage.ToString();
2025  Ptr<Packet> packet = Create<Packet> (
2026  (uint8_t*) (hMessage).c_str(),
2027  hMessage.size()
2028  );
2029  NS_ASSERT (packet != 0);
2030 
2031  SendToSocketPair(socket, packet);
2032 
2033  //TEST LINES - @toDo: remove after testing
2035  NS_ASSERT(conn.IsValid());
2036  conn.PrintRegistryInfo();
2037  NS_LOG_FUNCTION(this
2038  << conn.GetId()
2039  << headerIn.GetUri()
2040  << msg
2041  << "AverageKeyGenerationRate:" << conn.GetSKR()
2042  << "ExpectedConsumption:" << conn.GetExpectedConsumption()
2043  << "EffectiveSKR:" << conn.GetEffectiveSKR()
2044  );
2045  //end of test lines
2046 
2047  m_keyServedETSI004Trace(ksid, index, key.size()*8 );
2048  m_keyServedTraceEmir(key.size()*8);
2049 
2050  }else{
2051 
2052  //ASSOCIATION TTL EXPIRED AND REMOVED
2053  NS_LOG_FUNCTION(this << "Association was not found!" << it->second.dstSaeId.string() );
2054 
2055  //create packet
2056  HTTPMessage httpMessage;
2057  httpMessage.CreateResponse(HTTPMessage::HttpStatus::BadRequest, "", {
2058  {"Request URI", headerIn.GetUri() }
2059  });
2060  std::string hMessage = httpMessage.ToString();
2061  Ptr<Packet> packet = Create<Packet> (
2062  (uint8_t*) (hMessage).c_str(),
2063  hMessage.size()
2064  );
2065  NS_ASSERT (packet != 0);
2066 
2067  SendToSocketPair(socket, packet);
2068 
2069  }
2070 
2071  }else{
2072 
2073  //Respond with an error. Currently this is the only error on GetKey004, therefore no message is included. @toDo
2074  NS_LOG_FUNCTION(this << "No keys available in the association buffer. Responding on the request ...");
2075 
2076  //create packet
2077  HTTPMessage httpMessage;
2078  httpMessage.CreateResponse(HTTPMessage::HttpStatus::BadRequest, "", {
2079  {"Request URI", headerIn.GetUri() }
2080  });
2081  std::string hMessage = httpMessage.ToString();
2082  Ptr<Packet> packet = Create<Packet> (
2083  (uint8_t*) (hMessage).c_str(),
2084  hMessage.size()
2085  );
2086  NS_ASSERT (packet != 0);
2087 
2088  //TEST LINES - @toDo: remove after testing
2089  /*
2090  QKDApplicationEntry appConnection = GetApplicationConnectionDetails( it->second.dstSaeId.string() );
2091  NS_ASSERT(appConnection.IsValid());
2092  appConnection.PrintRegistryInfo();
2093  QKDKeyAssociationLinkEntry conn = GetKeyAssociationLinkDetailsByApplicationId( appConnection.GetId().string() );
2094  NS_ASSERT(conn.IsValid());
2095  conn.PrintRegistryInfo();
2096  NS_LOG_FUNCTION(this
2097  << conn.GetId()
2098  << headerIn.GetUri()
2099  << "AverageKeyGenerationRate:" << conn.GetSKR()
2100  << "ExpectedConsumption:" << conn.GetExpectedConsumption()
2101  << "EffectiveSKR:" << conn.GetEffectiveSKR()
2102  );
2103  */
2104  //end of test lines
2105 
2106  SendToSocketPair(socket, packet);
2107  }
2108 
2109 }
2110 
2111 void
2113 {
2114  NS_LOG_FUNCTION( this << "Processing CLOSE request ... " << ksid );
2115 
2116  std::map<std::string, Association004>::iterator it = m_associations004.find(ksid);
2117  if(it == m_associations004.end()){
2118  NS_LOG_DEBUG( this << " Key stream association identified with " << ksid << " does not exists!" );
2119  return;
2120  }
2121 
2122  HttpQuery query;
2123  query.method_type = ETSI_QKD_004_KMS_CLOSE; //Close made to peer KMS
2124  query.ksid = ksid; //Remember ksid
2125  if(!it->second.buffer.empty()){
2126  query.surplus_key_ID = GenerateKeyId(); //Generate keyId to empty key stream association
2127  query.sync_index = it->second.buffer.begin()->first; //Take the first index in the buffer!
2128  }
2129 
2130  QKDApplicationEntry appConnection = GetApplicationConnectionDetails( ksid );
2131  NS_ASSERT(appConnection.IsValid());
2132  appConnection.PrintRegistryInfo();
2133 
2135  NS_ASSERT(conn.IsValid());
2136  conn.PrintRegistryInfo();
2137 
2138  NS_LOG_FUNCTION( this << "Releasing key stream association buffer. Synchronizing with peed KMS ... ");
2139  CheckSocketsKMS( (it->second).dstKmsNode ); //Check connection to peer KMS!
2140  Ptr<Socket> sendSocket = GetSendSocketKMS ( (it->second).dstKmsNode );
2141  NS_ASSERT (sendSocket != 0);
2142 
2143  nlohmann::json msgBody;
2144  if(!query.surplus_key_ID.empty()){
2145  msgBody["surplus_key_ID"] = query.surplus_key_ID;
2146  msgBody["sync_index"] = query.sync_index;
2147  }
2148  std::string msg = msgBody.dump();
2149 
2150  std::ostringstream peerkmsAddressTemp;
2151  (it->second).dstKmsNode.Print(peerkmsAddressTemp); //IPv4Address to string
2152  std::string headerUri = "http://" + peerkmsAddressTemp.str(); //Uri starts with destination KMS address
2153  headerUri += "/api/v1/associations/close_kms/" + ksid;
2154 
2155  //Create packet
2156  HTTPMessage httpMessage;
2157  httpMessage.CreateRequest(headerUri, "POST", msg);
2158  std::string hMessage = httpMessage.ToString();
2159  Ptr<Packet> packet = Create<Packet> (
2160  (uint8_t*) (hMessage).c_str(),
2161  hMessage.size()
2162  );
2163  NS_ASSERT (packet != 0);
2164 
2165  HttpKMSAddQuery((it->second).dstKmsNode, query); //Save this query made to the peer KMS!
2166 
2167  sendSocket->Send(packet);
2168  NS_LOG_FUNCTION( this << "Synchronization information for releasing key stream association sent to peer KMS"
2169  << packet->GetUid() << packet->GetSize() );
2170 
2171 }
2172 
2173 
2181 void
2183 {
2184  NS_LOG_FUNCTION( this );
2185  std::map<std::string, Association004>::iterator it = m_associations004.find(ksid);
2186  if (it == m_associations004.end()){
2187  NS_LOG_DEBUG( this << " Key stream association identified with " << ksid << " does not exists!" );
2188  return;
2189  }
2190 
2191  CheckSocketsKMS( (it->second).dstKmsNode ); //Check connection to peer KMS!
2192  Ptr<Socket> sendSocket = GetSendSocketKMS ( (it->second).dstKmsNode );
2193  NS_ASSERT (sendSocket != 0);
2194 
2195  nlohmann::json msgBody;
2196  msgBody["Source"] = (it->second).srcSaeId.string();
2197  msgBody["Destination"] = (it->second).dstSaeId.string();
2198  msgBody["QoS"]["key_chunk_size"] = (it->second).qos.chunkSize;
2199  msgBody["QoS"]["max_bps"] = (it->second).qos.maxRate;
2200  msgBody["QoS"]["min_bps"] = (it->second).qos.minRate;
2201  msgBody["QoS"]["jitter"] = (it->second).qos.jitter;
2202  msgBody["QoS"]["priority"] = (it->second).qos.priority;
2203  msgBody["QoS"]["timeout"] = (it->second).qos.timeout;
2204  msgBody["QoS"]["TTL"] = (it->second).qos.TTL;
2205 
2206  //msgBody["source_kms"] = conn.GetSourceKmsAddress(); For App Advertising
2207  msgBody["Key_stream_ID"] = ksid;
2208  std::string msg = msgBody.dump();
2209 
2210  std::ostringstream peerkmsAddressTemp;
2211  (it->second).dstKmsNode.Print(peerkmsAddressTemp); //IPv4Address to string
2212  std::string headerUri = "http://" + peerkmsAddressTemp.str(); //Uri starts with destination KMS address
2213  headerUri += "/api/v1/associations/new_app";
2214 
2215  //Create packet
2216  HTTPMessage httpMessage;
2217  httpMessage.CreateRequest(headerUri, "POST", msg);
2218  std::string hMessage = httpMessage.ToString();
2219  Ptr<Packet> packet = Create<Packet> (
2220  (uint8_t*) (hMessage).c_str(),
2221  hMessage.size()
2222  );
2223  NS_ASSERT (packet != 0);
2224 
2225  HttpQuery query;
2226  query.method_type = RequestType::NEW_APP;
2227  query.source_sae = (it->second).srcSaeId;
2228  query.destination_sae = (it->second).dstSaeId;
2229  query.ksid = ksid;
2230  HttpKMSAddQuery((it->second).dstKmsNode, query);
2231 
2232  sendSocket->Send(packet);
2233  NS_LOG_FUNCTION( this << "NEW_APP: KMS informs peer KMS on new association established!" );
2234 }
2235 
2236 void
2238 {
2239  NS_LOG_FUNCTION( this << "Processing NEW_APP request!" );
2240  std::string payload = headerIn.GetMessageBodyString();
2241  nlohmann::json jNewAppRequest;
2242  try{
2243  jNewAppRequest = nlohmann::json::parse(payload);
2244  }catch (...){
2245  NS_FATAL_ERROR( this << "JSON parse error!" );
2246  }
2247 
2248  std::string srcSaeId;
2249  std::string dstSaeId;
2251  std::string ksid;
2252  if(jNewAppRequest.contains("Destination")) dstSaeId = jNewAppRequest["Destination"];
2253  if(jNewAppRequest.contains("Source")) srcSaeId = jNewAppRequest["Source"];
2254  if(jNewAppRequest.contains("Key_stream_ID")) ksid = jNewAppRequest["Key_stream_ID"];
2255 
2256  ReadJsonQos(inQoS, jNewAppRequest);
2257  NS_ASSERT(srcSaeId.length()>0 || dstSaeId.length()>0 || !ksid.empty());
2258 
2259  bool qosAgreed {true}; //Check if the QoS can be met! @toDo
2260  if(qosAgreed){
2261 
2262  NS_LOG_FUNCTION(this << srcSaeId << dstSaeId << ksid);
2263 
2264  QKDApplicationEntry appConnection = GetApplicationConnectionDetails( ksid );
2265  NS_ASSERT(appConnection.IsValid());
2266  appConnection.PrintRegistryInfo();
2267 
2268  Ipv4Address dstKms = appConnection.GetDestinationKmsAddress();
2269 
2270  /* If it is not point-to-point connection, msg will carry and source_kms!
2271  This value will be used instead of dstKms from the conn stats!
2272  However, the response on the NewAppRequest is sent via same route
2273  and will carry IP address of this KMS node. @toDoR */
2275  dstSaeId,
2276  srcSaeId,
2277  inQoS,
2278  dstKms,
2279  ksid,
2280  appConnection.GetId().string()
2281  );
2282 
2283  /* Send positive response on the NEW_APP request! In case where
2284  it is not point-to-point conncetion between the source and the destination
2285  msg will carry destination_kms address. @toDoR */
2286 
2287  //create packet
2288  HTTPMessage httpMessage;
2289  httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok, "", {
2290  {"Request URI", headerIn.GetUri() }
2291  });
2292  std::string hMessage = httpMessage.ToString();
2293  Ptr<Packet> packet = Create<Packet> (
2294  (uint8_t*) (hMessage).c_str(),
2295  hMessage.size()
2296  );
2297  NS_ASSERT (packet != 0);
2298 
2299  NS_LOG_FUNCTION( this << "NEW_APP request accepted. Association created." );
2300  SendToSocketPairKMS(socket, packet); //Send Packet to Socket pair
2301 
2302  }else{
2303  NS_LOG_FUNCTION( this << "QoS requirements can not be satisfied" );
2304  //@toDoEmir Respond with an error status code (carry new QoS)!
2305  }
2306 
2307 }
2308 
2309 void
2311 {
2312  NS_LOG_FUNCTION( this << "Processing NEW_APP response" );
2313 
2314  Ipv4Address dstKms = GetDestinationKmsAddress(socket);
2315  std::map<Ipv4Address, std::vector<HttpQuery> >::iterator it = m_httpRequestsQueryKMS.find(dstKms);
2316 
2317  if(it == m_httpRequestsQueryKMS.end() || (it->second).empty())
2318  NS_FATAL_ERROR( this << "Response cannot be mapped! HttpQuery empty!" );
2319 
2320  std::string ksid = it->second[0].ksid;
2321 
2322  if(headerIn.GetStatusCode() == 200){ //Status OK
2323 
2324  QKDApplicationEntry appConnection = GetApplicationConnectionDetails( ksid );
2325  NS_ASSERT(appConnection.IsValid());
2326  appConnection.PrintRegistryInfo();
2327 
2329  NS_ASSERT(conn.IsValid());
2330  conn.PrintRegistryInfo();
2331 
2332  if(conn.GetHop() == 1) {//dstKms for point-to-point scenario!
2333  HttpKMSCompleteQuery(dstKms); //Point-to-point scenario. Response just as acknowledgement!
2334 
2335  } else {//@toDo Trusted relay scenario. QKDApp is waiting for OPEN_CONNECT response!
2336  bool QoS {true}; //Read QoS from response, calculate its own, and make response!
2337  if(QoS){
2338  nlohmann::json jOpenConnectResponse;
2339  jOpenConnectResponse["Key_stream_ID"] = it->second[0].ksid;
2340  std::string msg = jOpenConnectResponse.dump();
2341 
2342  //create packet
2343  HTTPMessage httpMessage;
2344  httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok, msg, {
2345  {"Content-Type", "application/json; charset=utf-8"},
2346  {"Request URI", headerIn.GetUri() }
2347  });
2348  std::string hMessage = httpMessage.ToString();
2349  Ptr<Packet> packet = Create<Packet> (
2350  (uint8_t*) (hMessage).c_str(),
2351  hMessage.size()
2352  );
2353  NS_ASSERT (packet != 0);
2354 
2355  Ptr<Socket> responseSocket = GetSocketFromHttp004AppQuery(it->second[0].source_sae);
2356  Http004AppQueryComplete(it->second[0].source_sae);
2357  HttpKMSCompleteQuery(dstKms);
2358  SendToSocketPair(responseSocket, packet);
2359  }else{
2360  //Respond to the QKDApp with QoS that can be offered! @toDo Trusted relay scenario
2361  }
2362  }
2363 
2364  }else{ //Status indicating error!
2365 
2366  std::string ksid = it->second[0].ksid;
2367  QKDApplicationEntry appConnection = GetApplicationConnectionDetails( ksid );
2368  NS_ASSERT(appConnection.IsValid());
2369  appConnection.PrintRegistryInfo();
2370 
2372  NS_ASSERT(conn.IsValid());
2373  conn.PrintRegistryInfo();
2374 
2375  if(conn.GetHop() == 1) //dstKms for point-to-point scenario!
2376  HttpKMSCompleteQuery(dstKms); //Point-to-point scenario. Response just as acknowledgement!
2377  else{
2378  //Check the error! @toDo Respond to peer QKDApp in case of Trusted relay scenario!
2379  HttpKMSCompleteQuery(dstKms);
2380  }
2381  std::map<std::string, Association004>::iterator it = m_associations004.find(ksid);
2382  if(it != m_associations004.end()){
2383  m_associations004.erase(it); //Myb not erase, but for a few seconds mark as closed, and then erase! @toDo
2384  }else{
2385  NS_FATAL_ERROR(this << "Closing non existing association!");
2386  }
2387  }
2388 
2389 }
2390 
2391 void
2393 {
2394  NS_LOG_FUNCTION( this << ksid );
2395  std::map<std::string, Association004>::iterator it = m_associations004.find(ksid); //Find association entry identified with ksid
2396  if(it == m_associations004.end()){
2397  NS_LOG_DEBUG( this << " Key stream association identified with " << ksid << " does not exists!" );
2398  return;
2399  }
2400 
2401  Ipv4Address dstKms = (it->second).dstKmsNode; //Read destination KMS address from the association entry
2402 
2403  CheckSocketsKMS( dstKms ); //Check connection to dstKms
2404  Ptr<Socket> sendSocket = GetSendSocketKMS ( dstKms ); //Obtain send socket object to reach dstKms
2405 
2406  std::ostringstream peerkmsAddressTemp;
2407  dstKms.Print(peerkmsAddressTemp); //IPv4Address to string
2408  std::string headerUri = "http://" + peerkmsAddressTemp.str (); //Read an dstKms IP address to string
2409  headerUri += "/api/v1/associations/register/" + ksid; //Create an URI for the register request
2410 
2411  //Create packet
2412  HTTPMessage httpMessage;
2413  httpMessage.CreateRequest(headerUri, "GET");
2414  std::string hMessage = httpMessage.ToString();
2415  Ptr<Packet> packet = Create<Packet> (
2416  (uint8_t*) (hMessage).c_str(),
2417  hMessage.size()
2418  );
2419  NS_ASSERT (packet != 0);
2420 
2421  HttpQuery query;
2422  query.method_type = REGISTER;
2423  query.ksid = ksid;
2424  HttpKMSAddQuery(dstKms, query); //Remember HTTP query to be able to map response later
2425 
2426  sendSocket->Send(packet); //Send the packet to dstKms
2427 }
2428 
2429 void
2431 {
2432  NS_LOG_FUNCTION(this << "Processing register request " << ksid << headerIn.GetUri() );
2433  std::map<std::string, Association004>::iterator it = m_associations004.find(ksid); //Find association entry identified with ksid
2434  if(it != m_associations004.end() && (it->second).peerRegistered != true){
2435  (it->second).peerRegistered = true; //Acknowledge register notification, peer QKDApp is connected!
2436  //Send ack on this notification
2437 
2438  //create packet
2439  HTTPMessage httpMessage;
2440  httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok, "", {
2441  {"Content-Type", "application/json; charset=utf-8"},
2442  {"Request URI", headerIn.GetUri() }
2443  });
2444  std::string hMessage = httpMessage.ToString();
2445  Ptr<Packet> packet = Create<Packet> (
2446  (uint8_t*) (hMessage).c_str(),
2447  hMessage.size()
2448  );
2449  NS_ASSERT (packet != 0);
2450 
2451  SendToSocketPairKMS(socket, packet); //Sent response on register request
2452  CheckAssociation(ksid);
2453 
2454  }else if(it == m_associations004.end()){
2455  NS_LOG_DEBUG( this << " Key stream association identified with " << ksid << " does not exists!" );
2456  return;
2457  }else if((it->second).peerRegistered == true){
2458  NS_LOG_FUNCTION(this << "The peer application for asscotiation " << ksid << " has already been connected.");
2459  }
2460 }
2461 
2462 void
2464 {
2465  NS_LOG_FUNCTION( this << "Processing /register response!");
2466  Ipv4Address dstKms = GetDestinationKmsAddress(socket);
2467  std::map<Ipv4Address, std::vector<HttpQuery> >::iterator it = m_httpRequestsQueryKMS.find(dstKms);
2468  if(it == m_httpRequestsQueryKMS.end() || (it->second).empty())
2469  NS_FATAL_ERROR( this << "Response cannot be mapped! HttpQuery empty!" );
2470 
2471  if (headerIn.GetStatusCode() == HTTPMessage::Ok)
2472  NS_LOG_FUNCTION( this << "Successful notification REGISTER" );
2473  else {
2474  NS_LOG_FUNCTION( this << "/register error! Releasing established association" << it->second[0].ksid );
2475  std::map<std::string, Association004>::iterator it1 = m_associations004.find(it->second[0].ksid);
2476  if(it1 != m_associations004.end()){
2477  m_associations004.erase(it1); //Myb not erase, but for a few seconds mark as closed, and then erase! @toDo
2478  }else{
2479  NS_FATAL_ERROR(this << "Closing non existing association!");
2480  }
2481  }
2482  HttpKMSCompleteQuery(dstKms);
2483 
2484 }
2485 
2486 void
2488 {
2489  NS_LOG_FUNCTION( this << "Processing /fill request" << ksid );
2490  std::string payload = headerIn.GetMessageBodyString();
2491 
2492  nlohmann::json jAddKeysRequest;
2493  try{
2494  jAddKeysRequest = nlohmann::json::parse(payload);
2495  }catch (...){
2496  NS_FATAL_ERROR( this << "JSON parse error!" );
2497  }
2498 
2499  std::map<std::string, Association004>::iterator it = m_associations004.find(ksid);
2500  if(it == m_associations004.end()){
2501  NS_LOG_DEBUG( this << " Key stream association identified with " << ksid << " does not exists!" );
2502  return;
2503  }
2504  //Ipv4Address dstKms = it->second.dstKmsNode;
2505  UUID dstSaeId = it->second.dstSaeId;
2506  QKDApplicationEntry appConnection = GetApplicationConnectionDetails( ksid );
2507  NS_ASSERT(appConnection.IsValid());
2508  appConnection.PrintRegistryInfo();
2509 
2511  NS_ASSERT(conn.IsValid());
2512  conn.PrintRegistryInfo();
2513 
2514  Ptr<QKDBuffer> buffer = conn.GetSourceBuffer();
2515 
2516  bool accept = true; //For now, only full acceptance, or rejection!
2517  for(nlohmann::json::iterator it = jAddKeysRequest["keys"].begin(); it != jAddKeysRequest["keys"].end(); ++it){
2518  if(buffer->ProbeKeyStatus( (it.value())["key_ID"], QKDKey::READY ))
2519  continue;
2520  else{
2521  accept = false;
2522  break;
2523  }
2524  }
2525 
2526  if(accept){
2527  for(nlohmann::json::iterator it = jAddKeysRequest["keys"].begin(); it != jAddKeysRequest["keys"].end(); ++it){
2528  Ptr<QKDKey> key = buffer->FetchKeyByID( (it.value())["key_ID"]);
2530  }
2531 
2532  //Create positive response
2533  NS_LOG_FUNCTION( this << "Replica KMS added keys " << jAddKeysRequest.dump()
2534  << " to dedicated association key store " << ksid );
2535 
2536  //create packet
2537  HTTPMessage httpMessage;
2538  httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok, "", {
2539  {"Request URI", headerIn.GetUri() }
2540  });
2541  std::string hMessage = httpMessage.ToString();
2542  Ptr<Packet> packet = Create<Packet> (
2543  (uint8_t*) (hMessage).c_str(),
2544  hMessage.size()
2545  );
2546  NS_ASSERT (packet != 0);
2547 
2548  NS_LOG_FUNCTION( this << "Replica KMS sending response on FILL request "
2549  << ksid << packet->GetUid() << packet->GetSize() );
2550  SendToSocketPairKMS(socket, packet);
2551 
2552  }else{ //Keys negotiated to FILL the association key store are not available
2553  NS_LOG_FUNCTION( this << "Replica KMS reject FILL request " << jAddKeysRequest.dump()
2554  << " for association " << ksid );
2555 
2556  //create packet
2557  HTTPMessage httpMessage;
2558  httpMessage.CreateResponse(HTTPMessage::HttpStatus::BadRequest, "", {
2559  {"Request URI", headerIn.GetUri() }
2560  });
2561  std::string hMessage = httpMessage.ToString();
2562  Ptr<Packet> packet = Create<Packet> (
2563  (uint8_t*) (hMessage).c_str(),
2564  hMessage.size()
2565  );
2566  NS_ASSERT (packet != 0);
2567 
2568  NS_LOG_FUNCTION( this << "Replica KMS sending response on FILL request "
2569  << ksid << packet->GetUid() << packet->GetSize() );
2570  SendToSocketPair(socket, packet);
2571  }
2572 
2573 }
2574 
2575 void
2577 {
2578  NS_LOG_FUNCTION( this << "Processing FILL response" );
2579  std::string payload = headerIn.GetMessageBodyString();
2580 
2581  Ipv4Address dstKms = GetDestinationKmsAddress(socket);
2582  std::map<Ipv4Address, std::vector<HttpQuery> >::iterator it = m_httpRequestsQueryKMS.find(dstKms);
2583  if(it == m_httpRequestsQueryKMS.end() || (it->second).empty())
2584  NS_FATAL_ERROR( this << "Response cannot be mapped! HttpQuery empty!" );
2585 
2586  std::string ksid = it->second[0].ksid;
2587  NS_ASSERT(ksid != "");
2588  std::map<std::string, Association004>::iterator a = m_associations004.find(ksid);
2589  if(a == m_associations004.end()){
2590  NS_LOG_DEBUG( this << " Key stream association identified with " << ksid << " does not exists!" );
2591  return;
2592  }
2593 
2594  QKDApplicationEntry appConnection = GetApplicationConnectionDetails( ksid );
2595  NS_ASSERT(appConnection.IsValid());
2596  appConnection.PrintRegistryInfo();
2597 
2599  NS_ASSERT(conn.IsValid());
2600  conn.PrintRegistryInfo();
2601 
2602  Ptr<QKDBuffer> buffer = conn.GetSourceBuffer();
2603 
2604  if(!buffer)
2605  NS_FATAL_ERROR( this << "QKDBuffer for this connection cannot be found" );
2606 
2607  if (headerIn.GetStatusCode() == HTTPMessage::Ok){
2608  NS_LOG_FUNCTION( this << "Filling association dedicated key store" << ksid );
2609  for(std::vector<std::string>::iterator i = a->second.tempBuffer.begin(); i < a->second.tempBuffer.end(); ++i){
2610  Ptr<QKDKey> key = buffer->FetchKeyByID(*i);
2611  NS_ASSERT(key != NULL);
2613  }
2614  a->second.tempBuffer.clear(); //Release keys from tempBuffer
2615 
2616  }else{
2617  NS_LOG_FUNCTION( this << "Releasing reservation of keys " << a->second.tempBuffer );
2618  for(std::vector<std::string>::iterator i = a->second.tempBuffer.begin(); i < a->second.tempBuffer.end(); ++i)
2619  buffer->ReleaseReservation(*i);
2620  a->second.tempBuffer.clear();
2621  CheckAssociation(ksid); //Try FILL again
2622  }
2623  HttpKMSCompleteQuery(dstKms);
2624 
2625 }
2626 
2627 void
2628 QKDKeyManagerSystemApplication::TransformKeys (uint32_t keySize, uint32_t keyNumber, UUID ksid)
2629 {
2630  NS_LOG_FUNCTION( this << "target size" << keySize << "target number" << keyNumber << "ksid SAE" << ksid.string() );
2631 
2633  NS_ASSERT(appConnection.IsValid());
2634  appConnection.PrintRegistryInfo();
2635 
2637  NS_ASSERT(conn.IsValid());
2638  conn.PrintRegistryInfo();
2639 
2640  Ptr<QKDBuffer> buffer = conn.GetSourceBuffer();
2641  buffer->RecordTargetSize(keySize);
2642 
2643  bool transformSetReady = false;
2644  if(buffer){
2645  std::vector<std::string> toTransformKeyIDs {}; //Choice of keys to transform
2646  uint32_t targetSize {keySize*keyNumber};
2647  while(!transformSetReady){ //Form a transform set!
2648  Ptr<QKDKey> key = buffer->SearchOptimalKeyToTransform(targetSize);
2649  NS_ASSERT(key->GetId() != ""); //Check
2650  NS_ASSERT(key->GetSizeInBits() != 0); //Check
2651  buffer->ReserveKey(key->GetId()); //Reserve key for transformation! @toDo include reservation_type
2652  toTransformKeyIDs.push_back(key->GetId());
2653  if(key->GetSizeInBits() >= targetSize)
2654  transformSetReady = true;
2655  else
2656  targetSize -= key->GetSizeInBits();
2657  //@toDo: To avoid infinite while loop perform a check on toTransformKeyIDs.size() < m_maxTransformSet - defined by KMS
2658  }
2659  //Generate newKeyIds and optionaly suprplus keyIds
2660  std::vector<std::string> transformKeyIDs;
2661  uint32_t k {0};
2662  while(k++<keyNumber){
2663  transformKeyIDs.push_back(GenerateKeyId());
2664  }
2665  std::string surplusKeyId = GenerateKeyId();
2666  NS_LOG_FUNCTION( this << "transform_key_size" << keySize );
2667  NS_LOG_FUNCTION( this << "transform_key_number" << keyNumber);
2668  NS_LOG_FUNCTION( this << "transform_key_IDs" << transformKeyIDs );
2669  NS_LOG_FUNCTION( this << "surplus_key_ID" << surplusKeyId );
2670  NS_LOG_FUNCTION( this << "to_transform_key_IDs" << toTransformKeyIDs );
2671 
2672  //Create HTTP message transform
2673  nlohmann::json jtransform;
2674  jtransform["ksid"] = ksid.string(); //Must know to find QKDBuffer!
2675  jtransform["transform_key_size"] = keySize;
2676  jtransform["transform_key_number"] = keyNumber;
2677  for(size_t i = 0; i < transformKeyIDs.size(); i++)
2678  jtransform["transform_key_IDs"].push_back({{"key_ID", transformKeyIDs[i]}});
2679  jtransform["surplus_key_ID"] = surplusKeyId;
2680  for(size_t i = 0; i < toTransformKeyIDs.size(); i++)
2681  jtransform["to_transform_key_IDs"].push_back({{"key_ID", toTransformKeyIDs[i]}});
2682 
2683  std::string msg = jtransform.dump();
2684  NS_LOG_FUNCTION( this << "Transform payload" << msg );
2685  Ipv4Address dstKms = conn.GetDestinationKmsAddress(); //Destination KMS adress
2686  CheckSocketsKMS(dstKms); //Check connection to peer KMS!
2687  Ptr<Socket> sendSocket = GetSendSocketKMS(dstKms); //Get send socket to peer KMS
2688  NS_ASSERT (sendSocket != 0); //Check
2689 
2690  //Create packet
2691  HTTPMessage header;
2692  std::ostringstream peerkmsAddressTemp;
2693  dstKms.Print(peerkmsAddressTemp); //IPv4Address to string
2694  std::string headerUri = "http://" + peerkmsAddressTemp.str ();
2695  headerUri += "/api/v1/keys/transform_keys";
2696 
2697  //Create packet
2698  HTTPMessage httpMessage;
2699  httpMessage.CreateRequest(headerUri, "POST", msg);
2700  std::string hMessage = httpMessage.ToString();
2701  Ptr<Packet> packet = Create<Packet> (
2702  (uint8_t*) (hMessage).c_str(),
2703  hMessage.size()
2704  );
2705  NS_ASSERT (packet != 0);
2706 
2707  HttpQuery httpRequest;
2708  httpRequest.ksid = ksid.string(); //Must know to find QKDBuffer!
2709  httpRequest.method_type = RequestType::TRANSFORM_KEYS;
2710  httpRequest.transform_key_size = keySize;
2711  httpRequest.transform_key_number = keyNumber;
2712  httpRequest.transform_key_IDs = transformKeyIDs;
2713  httpRequest.to_transform_key_IDs = toTransformKeyIDs;
2714  httpRequest.surplus_key_ID = surplusKeyId;
2715  HttpKMSAddQuery(dstKms, httpRequest); //Remember request to properly map response!
2716 
2717  sendSocket->Send(packet);
2718  NS_LOG_FUNCTION( this << "Transform request sent" << packet->GetUid() << packet->GetSize() );
2719 
2720  }else{
2721  NS_FATAL_ERROR( this << "QKD buffer for this connection was not found!" );
2722  }
2723 
2724 }
2725 
2726 void
2728 {
2729  NS_LOG_FUNCTION( this << socket );
2730 
2731  std::string payload = headerIn.GetMessageBodyString();
2732  nlohmann::json jtransformRequest;
2733  try {
2734  jtransformRequest = nlohmann::json::parse(payload);
2735  } catch (...) {
2736  NS_FATAL_ERROR( this << "JSON parse error!" );
2737  }
2738  //Read JSON parameters
2739  uint32_t keySize {0}, keyNumber {0};
2740  std::vector<std::string> toTransformKeyIDs {}, transformKeyIDs {};
2741  std::string surplusKeyId {};
2742 
2743  std::string ksid;
2744  if(jtransformRequest.contains("transform_key_size"))
2745  keySize = jtransformRequest["transform_key_size"];
2746  if(jtransformRequest.contains("transform_key_number"))
2747  keyNumber = jtransformRequest["transform_key_number"]; //@toDo why is keyNumber always = 1, jtransformRequest["transform_key_number"] holds correct values, but keyNumber is 1?
2748  if(jtransformRequest.contains("surplus_key_ID"))
2749  surplusKeyId = jtransformRequest["surplus_key_ID"];
2750  if(jtransformRequest.contains("transform_key_IDs")){
2751  for(
2752  nlohmann::json::iterator it = jtransformRequest["transform_key_IDs"].begin();
2753  it != jtransformRequest["transform_key_IDs"].end();
2754  ++it
2755  )
2756  transformKeyIDs.push_back((it.value())["key_ID"]);
2757  }
2758  if(jtransformRequest.contains("to_transform_key_IDs")){
2759  for(
2760  nlohmann::json::iterator it = jtransformRequest["to_transform_key_IDs"].begin();
2761  it != jtransformRequest["to_transform_key_IDs"].end();
2762  ++it
2763  )
2764  toTransformKeyIDs.push_back((it.value())["key_ID"]);
2765  }
2766  if(jtransformRequest.contains("ksid")){
2767  ksid = jtransformRequest["ksid"];
2768  }
2769 
2770  NS_ASSERT(keySize != 0);
2771  NS_ASSERT(keyNumber =! 0);
2772  NS_ASSERT(!transformKeyIDs.empty());
2773  NS_ASSERT(!toTransformKeyIDs.empty());
2774 
2775  NS_LOG_FUNCTION( this << keySize << keyNumber << "\ntransform_key_IDs"<< transformKeyIDs
2776  << "\nto_transform_key_IDs" << toTransformKeyIDs << "\nsurplus_key_ID" << surplusKeyId << "\nksid" << ksid );
2777 
2778  if(ksid.size() == 0){
2779  NS_FATAL_ERROR( this << "No ksid specified!" << jtransformRequest.dump() );
2780  }
2781 
2782  QKDApplicationEntry appConnection = GetApplicationConnectionDetails( ksid );
2783  NS_ASSERT(appConnection.IsValid());
2784  appConnection.PrintRegistryInfo();
2785 
2787  NS_ASSERT(conn.IsValid());
2788  conn.PrintRegistryInfo();
2789 
2790 
2791  Ptr<QKDBuffer> buffer = conn.GetSourceBuffer();
2792  if(buffer){
2793  bool keysExist {true};
2794  for(size_t i = 0; i < toTransformKeyIDs.size(); i++){
2795  keysExist = buffer->ProbeKeyStatus(toTransformKeyIDs[i], QKDKey::READY); //Check if key exists and is READY
2796  if (!keysExist)
2797  break;
2798  }
2799  if(keysExist){ //Perform transformation and response OK
2800  NS_LOG_FUNCTION( this << "Performing transformation" );
2801  uint32_t keySizeInBytes = keySize/8;
2802  std::string mergedKey {};
2803  for(size_t i = 0; i < toTransformKeyIDs.size(); i++){
2804  mergedKey += (buffer->FetchKeyByID(toTransformKeyIDs[i], 1))->GetKeyString(); //Fetching will remove key from QKD buffer!
2805  }
2806  for(size_t i = 0; i < transformKeyIDs.size(); i++){ //Should use keyNumber but the previus read is invalid! @toDo
2807  std::string keyString = mergedKey.substr(0, keySizeInBytes);
2808  mergedKey.erase(0, keySizeInBytes);
2809  Ptr<QKDKey> key = CreateObject<QKDKey> (transformKeyIDs[i], keyString);
2810  buffer->AddNewKey(key,1);
2811  }
2812  if(!mergedKey.empty()){
2813  Ptr<QKDKey> key = CreateObject<QKDKey> (surplusKeyId, mergedKey);
2814  buffer->AddNewKey(key,1);
2815  }
2816 
2817  nlohmann::json jResponse;
2818  jResponse["sae_id"] = appConnection.GetSrcSaeId().string(); //it is destination saeId for the peer KMS
2819  std::string msg = jResponse.dump();
2820 
2821  //create packet
2822  HTTPMessage httpMessage;
2823  httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok, msg, {
2824  {"Content-Type", "application/json; charset=utf-8"},
2825  {"Request URI", headerIn.GetUri() }
2826  });
2827  std::string hMessage = httpMessage.ToString();
2828  Ptr<Packet> packet = Create<Packet> (
2829  (uint8_t*) (hMessage).c_str(),
2830  hMessage.size()
2831  );
2832  NS_ASSERT (packet != 0);
2833 
2834  SendToSocketPairKMS(socket, packet);
2835 
2836  }else{ //Response Error!
2837  NS_LOG_FUNCTION( this << "Check failed" );
2838  nlohmann::json jResponse;
2839  jResponse["sae_id"] = appConnection.GetSrcSaeId().string();
2840  std::string msg = jResponse.dump();
2841 
2842  //create packet
2843  HTTPMessage httpMessage;
2844  httpMessage.CreateResponse(HTTPMessage::HttpStatus::BadRequest, msg, {
2845  {"Content-Type", "application/json; charset=utf-8"},
2846  {"Request URI", headerIn.GetUri() }
2847  });
2848  std::string hMessage = httpMessage.ToString();
2849  Ptr<Packet> packet = Create<Packet> (
2850  (uint8_t*) (hMessage).c_str(),
2851  hMessage.size()
2852  );
2853  NS_ASSERT (packet != 0);
2854 
2855  SendToSocketPairKMS(socket, packet);
2856  }
2857 
2858  }else{
2859  NS_FATAL_ERROR( this << "No QKD buffer found for this connection!" );
2860  }
2861 
2862 }
2863 
2864 void
2866 {
2867  std::string payload = headerIn.GetMessageBodyString(); //Read payload
2868 
2869  NS_LOG_FUNCTION( this << payload );
2870 
2871  nlohmann::json jTransformResponse;
2872  try {
2873  jTransformResponse = nlohmann::json::parse(payload);
2874  } catch (...) {
2875  NS_FATAL_ERROR( this << "JSON parse error! Received payload:" << payload );
2876  }
2877 
2878  std::string ksid = "";
2879  if(jTransformResponse.contains("sae_id")) ksid = jTransformResponse["sae_id"];
2880  if(ksid.empty() && jTransformResponse.contains("ksid")) ksid = jTransformResponse["ksid"];
2881 
2882  Ipv4Address dstKms = GetDestinationKmsAddress(socket);
2883 
2884  QKDApplicationEntry appConnection = GetApplicationConnectionDetails( ksid );
2885  NS_ASSERT(appConnection.IsValid());
2886  appConnection.PrintRegistryInfo();
2887 
2889  NS_ASSERT(conn.IsValid());
2890  conn.PrintRegistryInfo();
2891 
2892  Ptr<QKDBuffer> buffer = conn.GetSourceBuffer();
2893  std::map<Ipv4Address, std::vector<HttpQuery> >::iterator it = m_httpRequestsQueryKMS.find(dstKms);
2894  HttpQuery transformPar = (it->second)[0];
2895  if (headerIn.GetStatusCode() == HTTPMessage::Ok){ //Transform keys
2896  //Read necessery transform parameters from HTTP query
2897  if(it == m_httpRequestsQueryKMS.end())
2898  NS_FATAL_ERROR( this << "HTTP response cannot be mapped: HTTP query to destination KMS does not exist!" );
2899  else if(it->second.empty())
2900  NS_FATAL_ERROR( this << "HTTP response cannot be mapped: HTTP query is empty!" );
2901  uint32_t keySize {transformPar.transform_key_size}, keyNumber {transformPar.transform_key_number};
2902  std::vector<std::string> toTransformKeyIDs {transformPar.to_transform_key_IDs},
2903  transformKeyIDs {transformPar.transform_key_IDs};
2904  std::string surplusKeyId {transformPar.surplus_key_ID};
2905  HttpKMSCompleteQuery(dstKms); //Clear this request from HTTP query (all parameters read!)
2906  NS_LOG_FUNCTION( this << "Transforming keys" );
2907  bool keysExist {true};
2908  for(size_t i = 0; i < toTransformKeyIDs.size(); i++){
2909  keysExist = buffer->ProbeKeyStatus(toTransformKeyIDs[i], QKDKey::RESERVED); //Check if key exists and is RESERVED
2910  if (!keysExist)
2911  break;
2912  }
2913  if(keysExist){
2914  uint32_t keySizeInBytes = keySize/8;
2915  std::string mergedKey {};
2916  for(size_t i = 0; i < toTransformKeyIDs.size(); i++){
2917  mergedKey += (buffer->FetchKeyByID(toTransformKeyIDs[i], 1))->GetKeyString(); //Fetching will remove key from QKD buffer!
2918  }
2919  for(size_t i = 0; i < keyNumber; i++){
2920  std::string keyString = mergedKey.substr(0, keySizeInBytes);
2921  mergedKey.erase(0, keySizeInBytes);
2922  Ptr<QKDKey> key = CreateObject<QKDKey> (transformKeyIDs[i], keyString);
2923  buffer->AddNewKey(key,1);
2924  }
2925  if(!mergedKey.empty()){
2926  Ptr<QKDKey> key = CreateObject<QKDKey> (surplusKeyId, mergedKey);
2927  buffer->AddNewKey(key,1);
2928  }
2929 
2930  NS_LOG_FUNCTION( this << "Transformation successfuly completed!" );
2931  }else{
2932  NS_FATAL_ERROR( this << "KMS mistreated reserved keys: keys not found!" );
2933  }
2934  }else{ //Release key reservation
2935  NS_LOG_FUNCTION( this << "Releasing reserved keys for failed transformation!");
2936  std::vector<std::string> toTransformKeyIDs {transformPar.to_transform_key_IDs};
2937  HttpKMSCompleteQuery(dstKms); //Clear this request from HTTP query (all parameters read!)
2938  for(size_t i = 0; i < toTransformKeyIDs.size(); i++){
2939  buffer->ReleaseReservation(toTransformKeyIDs[i]);
2940  }
2941  NS_LOG_FUNCTION( this << "Reserved keys are released" << toTransformKeyIDs );
2942  //@toDo Repeat TransformKeys? We have keySize, keyNumber, and dstKms! All we need!
2943  }
2944 
2945 }
2946 
2947 void
2949 {
2950  NS_LOG_FUNCTION( this << "Processing CLOSE from peer KMS" << ksid );
2951  std::string payload = headerIn.GetMessageBodyString(); //Read the packet payload
2952  nlohmann::json jcloseRequest;
2953  try {
2954  jcloseRequest = nlohmann::json::parse(payload);
2955  } catch (...) {
2956  NS_FATAL_ERROR( this << "JSON parse error!" );
2957  }
2958 
2959  std::string surplusKeyId {};
2960  uint32_t syncIndex {0};
2961  if(jcloseRequest.contains("surplus_key_ID"))
2962  surplusKeyId = jcloseRequest["surplus_key_ID"];
2963  if(jcloseRequest.contains("sync_index"))
2964  syncIndex = jcloseRequest["sync_index"];
2965 
2966  std::map<std::string, Association004>::iterator it = m_associations004.find(ksid);
2967  if(it == m_associations004.end()){ //Key stream association does not exists (peer error, or association already released)
2968  NS_LOG_FUNCTION( this << "KSID not registered on KMS, or is already closed!" );
2969 
2970  //create packet
2971  HTTPMessage httpMessage;
2972  httpMessage.CreateResponse(HTTPMessage::HttpStatus::NotAcceptable, "", {
2973  {"Request URI", headerIn.GetUri() }
2974  });
2975  std::string hMessage = httpMessage.ToString();
2976  Ptr<Packet> packet = Create<Packet> (
2977  (uint8_t*) (hMessage).c_str(),
2978  hMessage.size()
2979  );
2980  NS_ASSERT (packet != 0);
2981 
2982  NS_LOG_FUNCTION( this << "Sending response on CLOSE request " << packet->GetUid() << packet->GetSize() );
2983  SendToSocketPairKMS(socket, packet);
2984 
2985  }else{
2986  it->second.peerRegistered = false; //QKDApp is no longer registered for particular association!
2987  bool empty {false};
2988  uint32_t localSyncIndex {0};
2989  if(it->second.buffer.begin() != it->second.buffer.end()) //Replica association buffer is not empty!
2990  localSyncIndex = it->second.buffer.begin()->first; //The oldest index in dedicated association buffer!
2991  else
2992  empty = true;
2993 
2994  //record additional key consumption (some keys may not be perserved)
2995  if(!surplusKeyId.empty() && syncIndex > localSyncIndex){
2996  //must record key consumed
2997  NS_LOG_FUNCTION(this << "emiree" << syncIndex << localSyncIndex);
2998  uint32_t presentKeyMaterial {0};
2999  for (std::map<uint32_t, ChunkKey>::iterator it2 = it->second.buffer.begin(); it2 != it->second.buffer.find(syncIndex); ++it2){
3000  //from begining of buffer until SyncIndex all keys are not perserved
3001  NS_LOG_FUNCTION(this << it2->second.chunkSize);
3002  presentKeyMaterial += it2->second.chunkSize;
3003  }
3004  NS_LOG_FUNCTION(this << "emiree1" << presentKeyMaterial);
3005  m_keyServedTraceEmir(presentKeyMaterial);
3006  //m_keyServedTrace((it->second).dstSaeId, presentKeyMaterial);
3007  //m_keyServedWithKSIDTrace(ksid, (it->second).dstSaeId, presentKeyMaterial);
3008  }
3009 
3010  if(!surplusKeyId.empty() && syncIndex < localSyncIndex) //Only if peer KMS dedicated association buffer is not empty (known by the surplusKeyId presence)
3011  syncIndex = localSyncIndex; //KMSs synchronize on largest index that exists at both peers!
3012 
3013  bool flag {false};
3014  if(empty && !surplusKeyId.empty())
3015  flag = true; //If replica empty, primary not. Replica sends flag insted of index!
3016 
3017  ReleaseAssociation(ksid, surplusKeyId, syncIndex);
3018 
3019  nlohmann::json jresponse;
3020  if(!flag){
3021  if(!surplusKeyId.empty())
3022  jresponse["sync_index"] = syncIndex;
3023  }else{
3024  jresponse["flag_empty"] = true;
3025  }
3026 
3027  std::string msg = jresponse.dump();
3028 
3029  //create packet
3030  HTTPMessage httpMessage;
3031  httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok, msg, {
3032  {"Content-Type", "application/json; charset=utf-8"},
3033  {"Request URI", headerIn.GetUri() }
3034  });
3035  std::string hMessage = httpMessage.ToString();
3036  Ptr<Packet> packet = Create<Packet> (
3037  (uint8_t*) (hMessage).c_str(),
3038  hMessage.size()
3039  );
3040  NS_ASSERT (packet != 0);
3041 
3042  NS_LOG_FUNCTION( this << "Sending response on CLOSE" << msg << packet->GetUid() << packet->GetSize());
3043  SendToSocketPairKMS(socket, packet);
3044  }
3045 
3046 }
3047 
3048 void
3049 QKDKeyManagerSystemApplication::ReleaseAssociation (std::string ksid, std::string surplusKeyId, uint32_t syncIndex)
3050 {
3051  NS_LOG_FUNCTION( this << "Releasing association ... " << ksid );
3052  std::map<std::string, Association004>::iterator it = m_associations004.find(ksid);
3053  if(it == m_associations004.end()) { //Key stream association does not exists
3054  NS_LOG_DEBUG( this << " Key stream association identified with " << ksid << " does not exists!" );
3055  return;
3056  }
3057 
3058  if(surplusKeyId.empty()){
3059  m_associations004.erase(it);
3060  }else{
3061  std::string preservedKeyString {}; //First preserve remaining key material!
3062  std::map<uint32_t, ChunkKey>::iterator a = it->second.buffer.find(syncIndex);
3063  while(a != it->second.buffer.end()){
3064  preservedKeyString += a->second.key;
3065  ++a;
3066  }
3067 
3068  if(!preservedKeyString.empty()){
3069  //Ipv4Address dstKms = it->second.dstKmsNode; //Obtain dstKms adress from assocition entry
3070  UUID ksid = it->second.ksid;
3071 
3073  NS_ASSERT(appConnection.IsValid());
3074  appConnection.PrintRegistryInfo();
3075 
3077  NS_ASSERT(conn.IsValid());
3078  conn.PrintRegistryInfo();
3079 
3080  Ptr<QKDBuffer> buffer = conn.GetSourceBuffer();
3081  if(buffer){
3082  NS_LOG_FUNCTION( this << "Releasing dedicated association buffer ... " );
3083  NS_LOG_FUNCTION( this << "Preserving key material ... " );
3084  NS_LOG_FUNCTION( this << preservedKeyString.size() << " bit of key material preserved ... " );
3085  NS_LOG_FUNCTION( this << "Assigning ID to preserved key material ... " );
3086  Ptr<QKDKey> key = CreateObject<QKDKey> (surplusKeyId, preservedKeyString);
3087  buffer->AddNewKey(key, 1);
3088  NS_LOG_FUNCTION( this << "Preserved key material added to the QKD buffer "
3089  << surplusKeyId << preservedKeyString.size() );
3090  }else{
3091  NS_FATAL_ERROR( this << "QKD buffer not found!" );
3092  }
3093  }
3094  m_associations004.erase(it);
3095  }
3096  NS_LOG_FUNCTION( this << "Key stream association identified with " << ksid << "is removed!" );
3097 
3098 }
3099 
3100 void
3102 {
3103  NS_LOG_FUNCTION( this << "Processing response on KMS /close request ... " );
3104  std::string payload = headerIn.GetMessageBodyString();
3105  nlohmann::json jcloseResponse;
3106  try {
3107  jcloseResponse = nlohmann::json::parse(payload);
3108  } catch (...) {
3109  NS_FATAL_ERROR( this << "JSON parse error!" );
3110  }
3111 
3112  Ipv4Address dstKms = GetDestinationKmsAddress(socket);
3113  std::map<Ipv4Address, std::vector<HttpQuery> >::iterator it = m_httpRequestsQueryKMS.find(dstKms);
3114  if(it == m_httpRequestsQueryKMS.end())
3115  NS_FATAL_ERROR( this );
3116 
3117  std::string ksid = it->second[0].ksid;
3118  std::map<std::string, Association004>::iterator a = m_associations004.find(ksid);
3119  if(a == m_associations004.end()){
3120  NS_LOG_DEBUG( this << " Key stream association identified with " << ksid << " does not exists!" );
3121  return;
3122  }
3123 
3124  if(headerIn.GetStatusCode() == HTTPMessage::NotAcceptable){
3125  //must record key consumed
3126  uint32_t presentKeyMaterial {0};
3127  for (std::map<uint32_t, ChunkKey>::iterator it2 = a->second.buffer.begin(); it2 != a->second.buffer.end(); ++it2){
3128  presentKeyMaterial += it2->second.chunkSize;
3129  }
3130  m_keyServedTraceEmir(presentKeyMaterial);
3131  //m_keyServedTrace((a->second).dstSaeId, presentKeyMaterial);
3132  //m_keyServedWithKSIDTrace(ksid, (a->second).dstSaeId, presentKeyMaterial);
3133 
3134  m_associations004.erase(a); //Just delete association!
3135 
3136  }else if(headerIn.GetStatusCode() == HTTPMessage::Ok){
3137  uint32_t peerSyncIndex {0};
3138  uint32_t localSyncIndex {it->second[0].sync_index};
3139  if(jcloseResponse.contains("sync_index")){
3140  peerSyncIndex = jcloseResponse["sync_index"];
3141  if(peerSyncIndex > localSyncIndex)
3142  localSyncIndex = peerSyncIndex;
3143 
3144  //must record key consumed
3145  uint32_t presentKeyMaterial {0};
3146  for (std::map<uint32_t, ChunkKey>::iterator it2 = a->second.buffer.begin(); it2 != a->second.buffer.find(localSyncIndex); ++it2){
3147  //from begining of buffer until localSyncIndex all keys are not perserved
3148  presentKeyMaterial += it2->second.chunkSize;
3149  }
3150  //m_keyServedTrace((a->second).dstSaeId, presentKeyMaterial);
3151  //m_keyServedWithKSIDTrace(ksid, (a->second).dstSaeId, presentKeyMaterial);
3152  m_keyServedTraceEmir(presentKeyMaterial);
3153 
3154  ReleaseAssociation(it->second[0].ksid, it->second[0].surplus_key_ID, localSyncIndex);
3155  }else{
3156 
3157  //must record key consumed
3158  uint32_t presentKeyMaterial {0};
3159  for (std::map<uint32_t, ChunkKey>::iterator it2 = a->second.buffer.begin(); it2 != a->second.buffer.end(); ++it2){
3160  presentKeyMaterial += it2->second.chunkSize;
3161  }
3162  //m_keyServedTrace((a->second).dstSaeId, presentKeyMaterial);
3163  //m_keyServedWithKSIDTrace(ksid, (a->second).dstSaeId, presentKeyMaterial);
3164  m_keyServedTraceEmir(presentKeyMaterial);
3165 
3166  m_associations004.erase(a);
3167  }
3168 
3169  }else{
3170  NS_FATAL_ERROR( this << "Unknown http status code received" );
3171  }
3172 
3173  HttpKMSCompleteQuery(dstKms);
3174 
3175 }
3176 
3185 void
3187 {
3188  NS_LOG_FUNCTION( this );
3189  std::map<Ipv4Address, std::vector<HttpQuery> >::iterator it = m_httpRequestsQueryKMS.find(dstKms);
3190  if(it != m_httpRequestsQueryKMS.end())
3191  it->second.push_back(request);
3192  else
3193  m_httpRequestsQueryKMS.insert(std::make_pair(dstKms, std::vector<HttpQuery> {request}));
3194 }
3195 
3196 void
3198 {
3199  NS_LOG_FUNCTION( this );
3200  std::map<Ipv4Address, std::vector<HttpQuery> >::iterator it = m_httpRequestsQueryKMS.find(dstKms);
3201  if(it != m_httpRequestsQueryKMS.end())
3202  if(!it->second.empty())
3203  it->second.erase(it->second.begin());
3204  else
3205  NS_FATAL_ERROR( this << "HTTP query for this KMS is empty!");
3206  else
3207  NS_FATAL_ERROR( this << "HTTP query to destination KMS does not exist!" );
3208 }
3209 
3212 {
3213  NS_LOG_FUNCTION( this );
3215  std::map<Ipv4Address, std::vector<HttpQuery> >::iterator it = m_httpRequestsQueryKMS.find(dstKms);
3216  if(it!=m_httpRequestsQueryKMS.end())
3217  methodType = it->second.begin()->method_type;
3218  else
3219  NS_FATAL_ERROR( this << "HTTP response cannot be mapped: HTTP query is empty!" );
3220  return methodType;
3221 }
3222 
3223 void
3225 {
3226  NS_LOG_FUNCTION( this << saeId << socket );
3227  m_http004App.insert (std::make_pair (saeId, socket));
3228 }
3229 
3230 void
3232 {
3233  NS_LOG_FUNCTION( this << saeId );
3234  //Must use equal_range
3235  std::pair<std::multimap<UUID, Ptr<Socket> >::iterator, std::multimap<uint32_t, Ptr<Socket> >::iterator > ret;
3236  //ret = m_http004App.equal_range(saeId);
3237  //if (ret.first == ret.second) NS_FATAL_ERROR( this << "Query is empty" );
3238 
3239  std::multimap<UUID, Ptr<Socket> >::iterator it = ret.first;
3240  m_http004App.erase(it);
3241 
3242 }
3243 
3246 {
3247  NS_LOG_FUNCTION( this << saeId );
3248 
3249  std::pair<std::multimap<UUID, Ptr<Socket> >::iterator, std::multimap<UUID, Ptr<Socket> >::iterator > ret;
3250  //ret = m_http004App.equal_range(saeId);
3251  //if (ret.first == ret.second) NS_FATAL_ERROR( this << "sae query is not registered" );
3252 
3253  std::multimap<UUID, Ptr<Socket> >::iterator it = ret.first;
3254 
3255  NS_LOG_FUNCTION( this << saeId << it->second);
3256  return it->second;
3257 
3258 }
3259 
3262 {
3263  NS_LOG_FUNCTION( this );
3264  Ipv4Address dstKMSAddress;
3265 
3266  std::map<Ipv4Address, std::pair<Ptr<Socket>, Ptr<Socket> > >::iterator it;
3267  for (it = m_socketPairsKMS.begin(); it != m_socketPairsKMS.end(); ++it)
3268  {
3269  if ((it->second).first == socket) {
3270  dstKMSAddress = it->first;
3271  break;
3272  }
3273  }
3274 
3275  return dstKMSAddress;
3276 }
3277 
3278 uint32_t
3280  return m_maxKeyPerRequest;
3281 }
3282 
3285 {
3286  NS_LOG_FUNCTION(this << s);
3287  RequestType output = NONE;
3288 
3289  if(s == "status"){
3290 
3291  return ETSI_QKD_014_GET_STATUS;
3292 
3293  } else if(s == "enc_keys") {
3294 
3295  return ETSI_QKD_014_GET_KEY;
3296 
3297  } else if(s == "dec_keys"){
3298 
3300 
3301  } else if (s == "open_connect"){
3302 
3304 
3305  } else if (s == "get_key") {
3306 
3307  return ETSI_QKD_004_GET_KEY;
3308 
3309  } else if (s == "close") {
3310 
3311  return ETSI_QKD_004_CLOSE;
3312 
3313  } else if (s == "new_app") {
3314 
3315  return NEW_APP;
3316 
3317  } else if (s == "register") {
3318 
3319  return REGISTER;
3320 
3321  } else if (s == "fill") {
3322 
3323  return FILL;
3324 
3325  } else if (s == "store_pp_key") {
3326 
3327  return STORE_PP_KEYS;
3328 
3329  } else if (s == "transform_keys") {
3330 
3331  return TRANSFORM_KEYS;
3332 
3333  } else if (s == "close_kms") {
3334 
3335  return ETSI_QKD_004_KMS_CLOSE;
3336 
3337  } else {
3338 
3339  NS_FATAL_ERROR ("Unknown Type: " << s);
3340  }
3341 
3342  return output;
3343 }
3344 
3345 //function called from QKD Control
3346 //by default srcSaeId == srcNodeId where the link is installed
3347 std::string
3349  uint32_t srcNodeId,
3350  uint32_t dstNodeId,
3351  Ipv4Address kmsDstAddress,
3352  Ptr<QKDBuffer> srcBuffer
3353 ){
3354  return AddNewLink(
3355  srcNodeId,
3356  dstNodeId,
3357  kmsDstAddress,
3358  srcBuffer,
3359  ""
3360  );
3361 }
3362 
3363 
3364 //function called from QKD Control
3365 //by default srcSaeId == srcNodeId where the link is installed
3366 std::string
3368  uint32_t srcNodeId,
3369  uint32_t dstNodeId,
3370  Ipv4Address kmsDstAddress,
3371  Ptr<QKDBuffer> srcBuffer,
3372  std::string keyAssociationIdParam
3373 ){
3374 
3375  NS_LOG_FUNCTION( this
3376  << "srcNodeId: " << srcNodeId
3377  << "dstNodeId: " << dstNodeId
3378  << "m_local: " << m_local
3379  << "kmsDstAddress: " << kmsDstAddress
3380  << "keyAssociationIdParam: " << keyAssociationIdParam
3381  );
3382 
3384  NS_ASSERT (lr != 0);
3385 
3386  std::string keyAssociationId = keyAssociationIdParam;
3387  if(keyAssociationId.empty()){
3388  NS_LOG_FUNCTION(this << "empty!");
3389  QKDKeyAssociationLinkEntry newEntry(
3390  srcNodeId,
3391  dstNodeId,
3392  dstNodeId,//nextHop
3393  1,//dirrect p2p connection (number of hops)
3394  0,// 0-direct; 1-virtual
3395  m_local, //srcKMSAddress
3396  kmsDstAddress, //dstKMSaddress
3397  srcBuffer
3398  );
3399  lr->AddKeyAssociationEntry(newEntry);
3400  keyAssociationId = newEntry.GetId().string();
3401  }else{
3402  NS_LOG_FUNCTION(this << "NOT empty!" << keyAssociationId);
3403  QKDKeyAssociationLinkEntry newEntry(
3404  UUID{keyAssociationId},
3405  srcNodeId,
3406  dstNodeId,
3407  dstNodeId,//nextHop
3408  1,//dirrect p2p connection (number of hops)
3409  0,// 0-direct; 1-virtual
3410  m_local, //srcKMSAddress
3411  kmsDstAddress, //dstKMSaddress
3412  srcBuffer
3413  );
3414  lr->AddKeyAssociationEntry(newEntry);
3415  }
3416 
3417  NS_LOG_FUNCTION (this << "Create sink socket to listen requests exchanged between KMSs!" );
3418 
3419  InetSocketAddress sinkAddress = InetSocketAddress (m_local, 8080);
3420  Ptr<Socket> sinkSocket = Socket::CreateSocket (GetNode (), m_tid);
3421  sinkSocket->Bind (sinkAddress);
3422  sinkSocket->Listen ();
3423  sinkSocket->ShutdownSend ();
3425  sinkSocket->SetAcceptCallback (
3426  MakeNullCallback<bool, Ptr<Socket>, const Address &> (),
3428  );
3429  sinkSocket->SetCloseCallbacks (
3432  );
3433 
3434  //store this socket for further use. Later we will create the send socket as well
3435  Ptr<Socket> sendSocket = 0;
3436  m_socketPairsKMS.insert(
3437  std::make_pair(
3438  kmsDstAddress,
3439  std::make_pair(sinkSocket, sendSocket)
3440  )
3441  );
3442  NS_LOG_FUNCTION( this << kmsDstAddress << sinkSocket << sendSocket );
3443 
3444  //-----------------------
3445  //SEND DETAILS TO SDN CONTROLLER
3446  //-----------------------
3447 
3448 
3449  if(m_sdnSupportEnabled){
3450 
3451  std::ostringstream mkmsAddressTemp;
3452  m_local.Print(mkmsAddressTemp); //IPv4Address to string
3453  std::string mkmsAddressString = mkmsAddressTemp.str(); //Uri starts with destination KMS address
3454 
3455  std::ostringstream skmsAddressTemp;
3456  kmsDstAddress.Print(skmsAddressTemp); //IPv4Address to string
3457  std::string skmsAddressString = skmsAddressTemp.str(); //Uri starts with destination KMS address
3458 
3459  //Notify SDN Controller about the new QKD LINK
3460  nlohmann::json j;
3461  j["master_SAE_ID"] = srcNodeId;
3462  j["slave_SAE_ID"] = dstNodeId;
3463  j["next_hop_id"] = dstNodeId;
3464  j["key_association_id"] = keyAssociationId;
3465  j["hops"] = 0;
3466  j["master_kms_address"] = mkmsAddressString;
3467  j["slave_kms_address"] = skmsAddressString;
3468 
3469  NS_LOG_FUNCTION( this << "Prepared JSON_PACKET_TO_SDN:" << j.dump() );
3470 
3471  std::string msg = j.dump();
3472  HTTPMessage httpHead;
3473 
3475  std::ostringstream sdnAddressTemp;
3476  sdnAddress.Print(sdnAddressTemp); //IPv4Address to string
3477 
3478  std::string headerUri = "http://" + sdnAddressTemp.str ();
3479  headerUri += "/api/v1/keys/" + skmsAddressString + "/register_qkd_link";
3480 
3481  //Create packet
3482  HTTPMessage httpMessage;
3483  httpMessage.CreateRequest(headerUri, "POST", msg);
3484  std::string hMessage = httpMessage.ToString();
3485  Ptr<Packet> packetToSdn = Create<Packet> (
3486  (uint8_t*) (hMessage).c_str(),
3487  hMessage.size()
3488  );
3489 
3490  if(connectedToSDN)
3491  {
3492  NS_LOG_FUNCTION (this << "Sending QKD_LINK_REGISTER to SDN CONTROLLER\n PacketID: "
3493  << packetToSdn->GetUid() << " of size: " << packetToSdn->GetSize()
3494  << hMessage
3495  );
3496  m_sendSocketToSDN->Send(packetToSdn);
3497 
3498  //otherwise wait in the queue
3499  }else{
3500  m_packetQueuesToSDN.insert( std::make_pair( m_sendSocketToSDN , packetToSdn) );
3501  NS_LOG_FUNCTION(this << packetToSdn->GetUid() << "enqued for socket " << m_sendSocketToSDN);
3502  }
3503  }
3504 
3505  return keyAssociationId;
3506 }
3507 
3514  UUID srcSaeId,
3515  UUID dstSaeId,
3516  std::string type, //1-etsi014 (encryption); 2-etsi014(auth); 3-etsi004(encryption); 4-etsi004(auth)
3517  Ipv4Address dstKmsAddress,
3518  uint32_t priority = 0,
3519  double expirationTime = 100
3520 ){
3521 
3522  NS_LOG_FUNCTION( this << "keyId: \t" << "srcSaeId:" << srcSaeId << "dstSaeId:" << dstSaeId << "type:" << type);
3523 
3526  NS_ASSERT (lr != 0);
3527 
3528  lr->AssignKeyAssociation( srcSaeId, dstSaeId, type, priority, conn );
3529  NS_ASSERT(conn.IsValid());
3530  conn.PrintRegistryInfo();
3531  UUID keyAssociationId = conn.GetId();
3532  UUID applicationEntryId = UUID::Nil();
3533 
3534  return RegisterApplicationEntry(
3535  keyAssociationId,
3536  applicationEntryId,
3537  srcSaeId,
3538  dstSaeId,
3539  type,
3540  dstKmsAddress,
3541  priority,
3542  expirationTime
3543  );
3544 }
3545 
3554  UUID keyAssociationId,
3555  UUID applicationEntryId,
3556  UUID srcSaeId,
3557  UUID dstSaeId,
3558  std::string type, //1-etsi014; 2-etsi004
3559  Ipv4Address dstKmsAddress,
3560  uint32_t priority = 0,
3561  double expirationTime = 100
3562 ){
3563 
3564  NS_LOG_FUNCTION( this
3565  << "keyId:" << keyAssociationId
3566  << "applicationEntryId:" << applicationEntryId
3567  << "srcSaeId:" << srcSaeId
3568  << "dstSaeId:" << dstSaeId
3569  << "type:" << type
3570  );
3571 
3573  if(type == "etsi004_enc") {
3575  }else if(type == "etsi004_auth") {
3577  }else if(type == "etsi014_enc") {
3579  }else if(type == "etsi014_auth") {
3581  }
3582  NS_ASSERT (
3587  );
3588  //1-etsi014 (encryption); 2-etsi014(auth); 3-etsi004(encryption); 4-etsi004(auth)
3589 
3590  QKDKeyAssociationLinkEntry conn = GetKeyAssociationById( keyAssociationId );
3591  conn.PrintRegistryInfo();
3592  NS_ASSERT(conn.IsValid());
3593  UUID connectionId = conn.GetId();
3594  NS_LOG_FUNCTION( this << "connectionId FOUND: " << connectionId );
3595 
3597  NS_ASSERT (lr != 0);
3598 
3599  QKDApplicationEntry newEntry(
3600  connectionId,
3601  srcSaeId,
3602  dstSaeId,
3603  linkType,
3604  priority,
3605  expirationTime, //expirationTime
3606  m_local, //srcKMSAddress
3607  dstKmsAddress //dstKMSAddress
3608  );
3609 
3610  if(applicationEntryId != UUID::Nil())
3611  newEntry.SetId(applicationEntryId);
3612 
3613  lr->AddApplicationEntry(newEntry);
3614  lr->UpdateQKDApplications(connectionId, newEntry.GetId());
3615 
3616  //-----------------------
3617  //SEND DETAILS TO SDN CONTROLLER
3618  //-----------------------
3620 
3621  std::ostringstream mkmsAddressTemp;
3622  conn.GetSourceKmsAddress().Print(mkmsAddressTemp); //IPv4Address to string
3623  std::string mkmsAddressString = mkmsAddressTemp.str(); //Uri starts with destination KMS address
3624 
3625  std::ostringstream skmsAddressTemp;
3626  conn.GetDestinationKmsAddress().Print(skmsAddressTemp); //IPv4Address to string
3627  std::string skmsAddressString = skmsAddressTemp.str(); //Uri starts with destination KMS address
3628 
3629  UUID appId = newEntry.GetId();
3630  nlohmann::json j;
3631  j["key_association_id"] = connectionId.string();
3632  j["application_entry_id"] = appId.string();
3633  j["client_SAE_ID"] = srcSaeId.string();
3634  j["server_SAE_ID"] = dstSaeId.string();
3635  j["link_type"] = GetQKDApplicationEntryText(linkType);
3636  j["priority"] = priority;
3637  j["expirationTime"] = expirationTime;
3638  j["master_kms_address"] = mkmsAddressString;
3639  j["slave_kms_address"] = skmsAddressString;
3640 
3641  NS_LOG_FUNCTION( this << "Prepared JSON_PACKET_TO_SDN:" << j.dump() );
3642 
3643  std::string msg = j.dump();
3644  HTTPMessage httpHead;
3645 
3647  std::ostringstream sdnAddressTemp;
3648  sdnAddress.Print(sdnAddressTemp); //IPv4Address to string
3649 
3650  std::string headerUri = "http://" + sdnAddressTemp.str ();
3651  headerUri += "/api/v1/keys/" + skmsAddressString + "/register_sae_link";
3652 
3653  //Create packet
3654  HTTPMessage httpMessage;
3655  httpMessage.CreateRequest(headerUri, "POST", msg);
3656  std::string hMessage = httpMessage.ToString();
3657  Ptr<Packet> packet = Create<Packet> (
3658  (uint8_t*) (hMessage).c_str(),
3659  hMessage.size()
3660  );
3661  NS_ASSERT (packet != 0);
3662 
3663  //send the packet only if connected!
3664  if(connectedToSDN){
3665  NS_LOG_FUNCTION (this << "Sending SAE_REGISTER to SDN CONTROLLER\n PacketID: "
3666  << packet->GetUid() << " of size: " << packet->GetSize()
3667  << hMessage
3668  );
3669  m_sendSocketToSDN->Send(packet);
3670  //otherwise wait in the queue
3671  }else{
3672  m_packetQueuesToSDN.insert( std::make_pair( m_sendSocketToSDN , packet) );
3673  NS_LOG_FUNCTION(this << packet->GetUid() << "enqued for socket " << m_sendSocketToSDN);
3674  }
3675  }
3676 
3677  return newEntry;
3678 
3679 }
3680 
3681 
3682 /*
3683 * This function is called when we have exact SAEIDs of the app
3684 * Then we need to obtain full info about the app from the connection registry
3685 */
3688  std::string srcSaeId,
3689  std::string dstSaeId,
3691 ){
3692  NS_LOG_FUNCTION(this << srcSaeId << dstSaeId << type);
3693 
3694  UUID srcId (srcSaeId);
3695  UUID dstId (dstSaeId);
3696 
3697  QKDApplicationEntry output;
3699  NS_ASSERT (lr != 0);
3700 
3701  lr->LookupApplicationBySaeIDsAndType(srcId, dstId, type, output);
3702  NS_LOG_FUNCTION(this << output.GetId());
3703 
3704  return output;
3705 }
3706 
3707 
3708 
3709 /*
3710 * This function is called when we have ksid
3711 * Then we need to obtain full info about the app from the connection registry
3712 */
3715 {
3716  NS_LOG_FUNCTION(this << ksid);
3717 
3718  UUID tempId (ksid);
3719  QKDApplicationEntry output;
3721  NS_ASSERT (lr != 0);
3722  lr->LookupApplication(tempId, output);
3723  return output;
3724 }
3725 
3726 
3727 /*
3728 * This function is the base of CAC oriented approach.
3729 * Having appId we should find the QKD link (key association) which provides key to the app
3730 * However, if there are multiple key associations, connecition register should decide which
3731 * key association to use to respond to this call.
3732 */
3735 {
3736  NS_LOG_FUNCTION(this << appId);
3737 
3738  UUID tempId (appId);
3741  NS_ASSERT (lr != 0);
3742  lr->LookupKeyAssociationByApplicationId(tempId, output);
3743  return output;
3744 
3745 }
3746 
3747 /*
3748 * This function is called only when adding new key.
3749 * At the current version of post-processing apps we identify QKD links via dstNodeId
3750 */
3752 QKDKeyManagerSystemApplication::GetKeyAssociationByNodeIds(uint32_t srcNodeId, uint32_t dstNodeId)
3753 {
3754  NS_LOG_FUNCTION(this << srcNodeId << dstNodeId);
3755 
3758  NS_ASSERT (lr != 0);
3759  lr->LookupKeyAssociationByDestinationNodeId(srcNodeId, dstNodeId, output);
3760  return output;
3761 }
3762 
3763 /*
3764 * This function is called only when adding new key.
3765 * At the current version of post-processing apps we identify QKD links via dstNodeId
3766 */
3769 {
3770  NS_LOG_FUNCTION(this << keyAssociationId);
3771 
3774  NS_ASSERT (lr != 0);
3775  lr->LookupKeyAssociationById(keyAssociationId, output);
3776  return output;
3777 }
3778 
3779 void
3781 
3782  NS_LOG_FUNCTION(this << entry.GetId());
3783 
3785  NS_ASSERT (lr != 0);
3786  lr->SaveKeyAssociation(entry);
3787 }
3788 
3789 
3790 void
3792  m_node = n;
3793 }
3794 
3795 Ptr<Node>
3797  return m_node;
3798 }
3799 
3800 /*
3801  This funtion checks only Get key request - ETSI014!
3802  It performs check on number, size, additional_slave_SAEs, and some exstensions!
3803  If request is valid then empty JSON structure is returned from this function,
3804  else Error data structure described in ETSI014 is returned!
3805 
3806  In case "keys are being transformed" message is returned, the function should optionally
3807  return a number of keys that must be transformed. This is because the number of keys
3808  to transform can be different from the keyNumber parameter, and is defined as
3809  keyNumber-availableKeyNumber. Omitted by Emir (no need for this in v1) - number of keys
3810  to transform should be decided by KMS (via request monitoring).
3811 */
3814 {
3815 
3816  NS_LOG_FUNCTION(this << conn.GetId());
3817 
3818  //IMPORTANT NOTE: It is assumed that number and size allowed by KMS is same on both sides! Therefore,
3819  //one does not need to check those parametes in GetKeyWithKeyIDs request!
3820  uint32_t keyNumber = 1; //Default number - ETSI014.
3821  uint32_t keySize = m_defaultKeySize; //Default size - KMS defined / or buffer defined.
3822  if(jrequest.contains("number")){ //There is keyNumber specified in request
3823  keyNumber = jrequest["number"];
3824  }
3825  if(jrequest.contains("size")){ //There is keySize specified
3826  keySize = jrequest["size"]; //Key size in bits!
3827  }
3828  nlohmann::json jError; //Check the values of specified parameters!
3829  if( //Message 1: requested parameters do not adhere to KMS rules
3830  keyNumber > GetMaxKeyPerRequest() ||
3831  keyNumber <= 0 ||
3832  keySize > m_maxKeySize ||
3833  keySize < m_minKeySize ||
3834  keySize % 8 != 0
3835  ){ //Message 1!
3836  jError["message"] = std::string {"requested parameters do not adhere to KMS rules"};
3837  //Fill the details of error Message!
3838  if(keyNumber > GetMaxKeyPerRequest()){
3839  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";
3840  NS_LOG_FUNCTION(this << conn.GetId() << "ERROR: " << msgDetail);
3841  jError["details"].push_back({{"number_unsupported", msgDetail}});
3842  }else if(keyNumber <= 0){
3843  std::string msgDetail = "requested number of keys can not be lower or equal to zero";
3844  NS_LOG_FUNCTION(this << conn.GetId()<< "ERROR: " << msgDetail);
3845  jError["details"].push_back({{"number_unsupported", msgDetail}});
3846  }
3847  if(keySize > m_maxKeySize){
3848  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";
3849  NS_LOG_FUNCTION(this << conn.GetId()<< "ERROR: " << msgDetail);
3850  jError["details"].push_back({{"size_unsupported", msgDetail}});
3851  }else if(keySize < m_minKeySize){
3852  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";
3853  NS_LOG_FUNCTION(this << conn.GetId()<< "ERROR: " << msgDetail);
3854  jError["details"].push_back({{"size_unsupported", msgDetail}});
3855  }else if(keySize % 8 != 0){
3856  std::string msgDetail = "size shall be a multiple of 8";
3857  NS_LOG_FUNCTION(this << conn.GetId()<< "ERROR: " << msgDetail);
3858  jError["details"].push_back({{"size_unsupported", msgDetail}});
3859  }
3860  return jError;
3861 
3862  }else{
3863 
3864  Ptr<QKDBuffer> buffer = conn.GetSourceBuffer();
3865  NS_LOG_FUNCTION(this << "krecCheck");
3866  NS_LOG_FUNCTION(this << conn.GetId() << "\nTarget key size: " << keySize << "\nTarget number: "
3867  << keyNumber << "\nRequired amount of key material: " << keySize*keyNumber);
3868  NS_LOG_FUNCTION(this << conn.GetId() << "\nAmount of key material in buffer: " << buffer->GetKeyCountBit()
3869  << "\nAmount of key material ready to be served: " << buffer->GetReadyKeyCountBit()
3870  << "\nAmount of key material part of target set: " << buffer->GetTargetKeyCountBit());
3871  if(buffer && keySize*keyNumber > buffer->GetReadyKeyCountBit()){ //Check if there is enough key material!
3872  jError["message"] = std::string {"insufficient amount of key material"};
3873  return jError;
3874  }else if(buffer && buffer->GetKeyCount(keySize) < keyNumber){
3875  //Check the amount of key for transformation purpose:
3876  if(buffer->GetReadyKeyCountBit() - buffer->GetTargetKeyCountBit() < keySize*keyNumber){
3877  jError["message"] = "insufficient amount of key material";
3878  NS_LOG_FUNCTION(this << conn.GetId() << "ERROR: " << jError["message"]);
3879  }else{
3880  jError["message"] = "keys are being transformed";
3881  NS_LOG_FUNCTION(this << conn.GetId() << "ERROR: " << jError["message"]);
3882  }
3883  }
3884 
3885  }
3886 
3887  return jError;
3888 }
3889 
3890 
3891 bool
3892 QKDKeyManagerSystemApplication::AddNewKey(Ptr<QKDKey> key, uint32_t srcNodeId, uint32_t dstNodeId){
3893 
3894  NS_LOG_FUNCTION(this << key->GetId() << key->GetSizeInBits() << srcNodeId << dstNodeId );
3895 
3896  bool output = false;
3897  QKDKeyAssociationLinkEntry keyAssociation = GetKeyAssociationByNodeIds( srcNodeId, dstNodeId );
3898  Ptr<QKDBuffer> buffer = keyAssociation.GetSourceBuffer();
3899 
3900  if(buffer){
3901 
3902  NS_LOG_FUNCTION(this << "Add key to buffer " << buffer << keyAssociation.GetId());
3903  output = buffer->AddNewKey(key,0);
3904 
3905  //Secret key rate generation (in bits per second) of the key association link.
3906  double generationRate = buffer->GetAverageKeyGenerationRate();
3907  keyAssociation.SetSKR(generationRate);
3908 
3909  //Sum of all the application's bandwidth (in bits per second) on this particular key association link.
3910  double averageConsumptionRate = buffer->GetAverageKeyConsumptionRate();
3911  keyAssociation.SetExpectedConsumption(averageConsumptionRate);
3912 
3913  //Effective secret key rate (in bits per second) generation of the key association link available after internal consumption
3914  double expectedConsumptionRate = keyAssociation.GetExpectedConsumption();
3915  double ratio = generationRate - expectedConsumptionRate;
3916 
3917  //if ratio is negative, it means old keys are taken from the buffer (not from the newly secret key rate)
3918  keyAssociation.SetEffectiveSKR(ratio);
3919 
3920  NS_LOG_FUNCTION(this
3921  << "keyAssociationId:" << keyAssociation.GetId()
3922  << "AverageKeyGenerationRate:" << keyAssociation.GetSKR()
3923  << "ExpectedConsumption:" << keyAssociation.GetExpectedConsumption()
3924  << "EffectiveSKR:" << keyAssociation.GetEffectiveSKR()
3925  );
3926 
3927  SaveKeyAssociation(keyAssociation);
3928 
3929  }else{
3930  NS_FATAL_ERROR(this << "No buffer found!");
3931  }
3932 
3933  return output;
3934 
3935 }
3936 
3937 /*
3938  Create key container json data structure described in ETSI014.
3939  Limits the size of obtained key to requested size by QKDApp ->
3940  This should be changed in @futureBuild. In GetKeysFromBuffer KMS shall
3941  split or merge the keys and take keySize in consideration while searching for key!
3942  Now, we do not have description of such KMS beahviour (@futureBuild)!
3943 */
3946 {
3947 
3948  NS_LOG_FUNCTION( this << "Create JSON Key Container data structure!");
3949  nlohmann::json jkeys;
3950  for(uint32_t i = 0; i < keys.size(); i++){
3951  if(keys[i] != 0){
3952  std::string encodedKey = Base64Encode(keys[i]->ConsumeKeyString()); //Encode fetched key in Base64
3953  NS_LOG_FUNCTION(this << "KEY" << i+1 << keys[i]->GetId() << encodedKey << "\n");
3954  jkeys["keys"].push_back({ {"key_ID", keys[i]->GetId()}, {"key", encodedKey} });
3955  }
3956  }
3957  return jkeys;
3958 
3959 }
3960 
3968 std::string
3970 {
3971  NS_LOG_FUNCTION( this );
3972  std::string output;
3973  UUID ksidRaw = UUID::Random();
3974  //UUID ksidRaw = UUID::Sequential();
3975  output = ksidRaw.string();
3976  NS_LOG_FUNCTION(this << output);
3977  return output;
3978 }
3979 
3980 void
3982 {
3983  /*
3984  To check the state of a single association! Master!
3985  */
3986  NS_LOG_FUNCTION(this << "Checking the state of the association " << ksid << " ...");
3987  std::map<std::string, Association004>::iterator it = m_associations004.find(ksid);
3988  if(it == m_associations004.end()){
3989  NS_LOG_DEBUG( this << " Key stream association identified with " << ksid << " does not exists!" );
3990  return;
3991  }
3992 
3993  if(it->second.associationDirection == 0 && it->second.peerRegistered){ //Check
3994  if(
3995  (it->second).tempBuffer.empty() &&
3996  ((it->second).buffer.empty() || !(it->second).buffer.begin()->second.ready)
3997  ){
3999  ksid,
4000  it->second.qos.maxRate,
4001  it->second.qos.priority
4002  ); //Starts reservation of keys for the association
4003  }
4004 
4005  }else if(it->second.associationDirection == 1){
4006  NS_FATAL_ERROR(this << "This function must not be called on replica KMS for a given association " << ksid);
4007  }
4008 }
4009 
4010 void
4012 {
4013  NS_LOG_FUNCTION(this);
4014  std::map<std::string, Association004>::iterator it;
4015  int64_t currentTime = Simulator::Now ().GetSeconds();
4016  for (it = m_associations004.begin(); it != m_associations004.end();)
4017  {
4018  if( it->second.qos.TTL < currentTime ) {
4019  NS_LOG_FUNCTION(this << "remove association "
4020  << "ksid: " << (it->second).ksid
4021  << "srcSaeId: " << (it->second).srcSaeId
4022  << "dstSaeId: " << (it->second).dstSaeId
4023  << " with TTL time: " << it->second.qos.TTL
4024  );
4025  m_associations004.erase (it++);
4026  }else{
4027  it++;
4028  }
4029  }
4030 }
4031 
4032 
4033 void
4034 QKDKeyManagerSystemApplication::NegotiateKeysForAssociation (std::string ksid, uint32_t keyAmount, uint32_t priority)
4035 {
4036  NS_LOG_FUNCTION( this << ksid << keyAmount );
4038 
4039  std::map<std::string, Association004>::iterator it = m_associations004.find(ksid);
4040  if(it == m_associations004.end()){
4041  NS_LOG_DEBUG( this << " Key stream association identified with " << ksid << " does not exists!" );
4042  return;
4043  }
4044 
4045  UUID dstSae = (it->second).dstSaeId; //Obtain destination SAE
4046  QKDApplicationEntry appConnection = GetApplicationConnectionDetails( ksid );
4047  NS_ASSERT(appConnection.IsValid());
4048  appConnection.PrintRegistryInfo();
4049 
4051  NS_ASSERT(conn.IsValid());
4052  conn.PrintRegistryInfo();
4053 
4054  Ptr<QKDBuffer> buffer = conn.GetSourceBuffer(); //Buffer for this connection
4055  if(buffer){
4056  nlohmann::json jkeyIDs; //KeyIDs of the keys to fill the association buffer. Keys shall be marked reserved!
4057  if(
4058  buffer->GetReadyKeyCountBit() - buffer->GetTargetKeyCountBit() < keyAmount &&
4059  buffer->GetReadyKeyCountBit() - buffer->GetTargetKeyCountBit() >= it->second.qos.chunkSize
4060  ){
4061  //Minimum amount of key material that could be assigned to the association buffer
4062  keyAmount = it->second.qos.chunkSize;
4063  }else if(buffer->GetReadyKeyCountBit() - buffer->GetTargetKeyCountBit() < it->second.qos.chunkSize){
4064  NS_LOG_FUNCTION( this << "Not enough key material to assign to the association dedicated buffer!" );
4065  //for premium apps mantain the key assoications
4066  if(priority > 0) ScheduleCheckAssociation(Time ("500ms"), "CheckAssociation", ksid); //Shedule new attempt!
4067  return;
4068  }
4069 
4070  bool addKeysReady = false;
4071  while(!addKeysReady){
4072  Ptr<QKDKey> key = buffer->SearchOptimalKeyToTransform(keyAmount);
4073  NS_ASSERT(key->GetId() != ""); //Check
4074  NS_ASSERT(key->GetSizeInBits() != 0); //Check
4075  buffer->ReserveKey(key->GetId()); //Reserve key for transformation! @toDo include reservation_type
4076  jkeyIDs["keys"].push_back({ {"key_ID", key->GetId()} }); //Add keyId object to JSON
4077  (it->second).tempBuffer.push_back(key->GetId()); //Add keyId to tempBuffer
4078 
4079  if(key->GetSizeInBits() >= keyAmount){
4080  addKeysReady = true;
4081  keyAmount = 0;
4082  }else
4083  keyAmount -= key->GetSizeInBits();
4084 
4085  NS_LOG_FUNCTION(this << "Found key " << key->GetId() << " of size " << key->GetSizeInBits() << " to transform.\n Remaining key ammount to find: " << keyAmount);
4086  }
4087 
4088  Ipv4Address dstKms = (it->second).dstKmsNode;
4089  std::ostringstream peerkmsAddressTemp;
4090  dstKms.Print(peerkmsAddressTemp); //IPv4Address to string
4091  std::string headerUri = "http://" + peerkmsAddressTemp.str ();
4092  headerUri += "/api/v1/associations/fill/" + ksid;
4093 
4094  std::string msg = jkeyIDs.dump();
4095 
4096  //Create packet
4097  HTTPMessage httpMessage;
4098  httpMessage.CreateRequest(headerUri, "POST", msg);
4099  std::string hMessage = httpMessage.ToString();
4100  Ptr<Packet> packet = Create<Packet> (
4101  (uint8_t*) (hMessage).c_str(),
4102  hMessage.size()
4103  );
4104  NS_ASSERT (packet != 0);
4105 
4106  CheckSocketsKMS( dstKms ); //Check connection to peer KMS!
4107  Ptr<Socket> sendSocket = GetSendSocketKMS( dstKms );
4108 
4109  HttpQuery query;
4110  query.method_type = FILL;
4111  query.destination_sae = dstSae;
4112  query.ksid = ksid;
4113  HttpKMSAddQuery(dstKms, query);
4114 
4115  sendSocket->Send(packet);
4116  NS_LOG_FUNCTION( this << "Proposal of keys to fill association " << ksid
4117  << " dedicated store is sent!" << packet->GetUid() << packet->GetSize() << headerUri << msg );
4118  }else{
4119  NS_FATAL_ERROR( this << "QKD Buffer for this connection is not found!" );
4120  }
4121 
4122 }
4123 
4124 void
4126 {
4127  NS_LOG_FUNCTION( this << ksid << key->GetId() );
4128  std::map<std::string, Association004>::iterator it = m_associations004.find(ksid);
4129  if(it == m_associations004.end()){
4130  NS_LOG_DEBUG( this << " Key stream association identified with " << ksid << " does not exists!" );
4131  return;
4132  }
4133 
4134  uint32_t keyChunkSize = (it->second).qos.chunkSize /8; //Obtain chunk size (in bytes) from the QoS structure!
4135  std::string secretKey = key->ConsumeKeyString(); //Obtain key string
4136 
4137  NS_LOG_FUNCTION( this << "Secret key size (bytes) " << secretKey.size() );
4138  NS_LOG_FUNCTION( this << "Last index - " << (it->second).lastIndex );
4139  uint32_t startingIndex = (it->second).lastIndex; //Find the starting index to fill the buffer with the secret key
4140  bool startingInReady = true; //Is the starting index an existing index thats not ready, or a next to generate index!
4141 
4142  if((it->second).buffer.rbegin() != (it->second).buffer.rend()){
4143  startingIndex = (it->second).buffer.rbegin()->first;
4144  if( ((it->second).buffer.rbegin()->second).ready != true )
4145  startingInReady = false;
4146  else
4147  startingIndex++;
4148  }else if((it->second).lastIndex != 0)
4149  startingIndex++;
4150 
4151  NS_LOG_FUNCTION (this << "Chunk size (bytes), Start Index, Start Ready" << keyChunkSize << startingIndex << startingInReady);
4152  //Fill the content of the secret key into the buffer!
4153  while (!secretKey.empty())
4154  {
4155  if(!startingInReady)
4156  {
4157  uint32_t currentChunkSize = ( (it->second).buffer.rbegin()->second ).key.size(); //In bytes
4158  NS_LOG_FUNCTION( this << "currentChunkSize" << currentChunkSize);
4159  uint32_t diff = keyChunkSize - currentChunkSize; //In bytes
4160  NS_LOG_FUNCTION( this << "diff" << diff );
4161  //Check the size of the secretKey, is it enough to fill the diff
4162  std::string incompleteChunkKey = (it->second).buffer.rbegin()->second.key;
4163  if(secretKey.size() >= diff){
4164  std::string diffKey = secretKey.substr(0, diff);
4165  std::string temp = secretKey.substr(diff);
4166  secretKey = temp;
4167  std::string completeKey = incompleteChunkKey+diffKey;
4168  NS_LOG_FUNCTION( this << incompleteChunkKey << diffKey << completeKey);
4169 
4170  (it->second).buffer.rbegin()->second.key = completeKey;
4171  (it->second).buffer.rbegin()->second.ready = true;
4172 
4173  NS_LOG_FUNCTION( this << startingIndex << (it->second).buffer.rbegin()->second.key );
4174 
4175  startingIndex++;
4176  startingInReady = true;
4177  }else{
4178  std::string completeKey = incompleteChunkKey+secretKey;
4179  secretKey = "";
4180  (it->second).buffer.rbegin()->second.key = completeKey;
4181  startingIndex++; //Increase index
4182  }
4183 
4184  }else{
4185  uint32_t len; //len is in bytes
4186  if (secretKey.size() >= keyChunkSize)
4187  len = keyChunkSize;
4188  else
4189  len = secretKey.size();
4190 
4191  std::string temp; //Remaining secret key
4192  std::string key; //Key to store as a chunk
4193  key = secretKey.substr(0, len);
4194  temp = secretKey.substr(len);
4195  secretKey = temp;
4196 
4197  NS_LOG_FUNCTION( this << startingIndex << key);
4198 
4199  ChunkKey keyC;
4200  keyC.key = key;
4201  keyC.index = startingIndex;
4202  keyC.chunkSize = len*8; //In bits (variable not really needed)
4203  if (len == keyChunkSize)
4204  keyC.ready = true;
4205  else
4206  keyC.ready = false;
4207 
4208  (it->second).buffer.insert(std::make_pair(startingIndex, keyC));
4209  startingIndex++; //Increase index
4210  }
4211  }
4212 
4213  (it->second).lastIndex = startingIndex - 1;
4214  NS_LOG_FUNCTION( this << "Last index stored is " << (it->second).lastIndex );
4215 
4216  NS_LOG_FUNCTION(this << "ksid:" << ksid);
4217  NS_LOG_FUNCTION(this << "Is association empty:" << (it->second).buffer.empty() );
4218  NS_LOG_FUNCTION(this << "Is association first key ready:" << (it->second).buffer.begin()->second.ready );
4219  NS_LOG_FUNCTION(this << "How many keys do we have in association:" << (it->second).buffer.size() );
4220 
4221 }
4222 
4223 std::string
4225 {
4226  std::string output;
4227  CryptoPP::StringSource(input, true,
4228  new CryptoPP::Base64Encoder(
4229  new CryptoPP::StringSink(output)
4230  ) // Base64Encoder
4231  ); // StringSource
4232  return output;
4233 }
4234 
4235 std::string
4237 {
4238  std::string output;
4239  CryptoPP::StringSource(input, true,
4240  new CryptoPP::Base64Decoder(
4241  new CryptoPP::StringSink(output)
4242  ) // Base64Dencoder
4243  ); // StringSource
4244  return output;
4245 }
4246 
4247 void
4250  nlohmann::json jOpenConnectRequest
4251 ){
4252 
4253  inQos.chunkSize = 0;
4254  inQos.maxRate = 0;
4255  inQos.minRate = 0;
4256  inQos.jitter = 0;
4257  inQos.priority = 0;
4258  inQos.timeout = 0;
4259  inQos.TTL = 0;
4260 
4261  if (jOpenConnectRequest.contains("QoS")) {
4262  if (jOpenConnectRequest["QoS"].contains("key_chunk_size")) inQos.chunkSize = jOpenConnectRequest["QoS"]["key_chunk_size"];
4263  if (jOpenConnectRequest["QoS"].contains("max_bps")) inQos.maxRate = jOpenConnectRequest["QoS"]["max_bps"];
4264  if (jOpenConnectRequest["QoS"].contains("min_bps")) inQos.minRate = jOpenConnectRequest["QoS"]["min_bps"];
4265  if (jOpenConnectRequest["QoS"].contains("jitter")) inQos.jitter = jOpenConnectRequest["QoS"]["jitter"];
4266  if (jOpenConnectRequest["QoS"].contains("priority")) inQos.priority = jOpenConnectRequest["QoS"]["priority"];
4267  if (jOpenConnectRequest["QoS"].contains("timeout")) inQos.timeout = jOpenConnectRequest["QoS"]["timeout"];
4268  if (jOpenConnectRequest["QoS"].contains("TTL")) inQos.TTL = jOpenConnectRequest["QoS"]["TTL"];
4269  }
4270 
4271  NS_LOG_FUNCTION(this << inQos.chunkSize << inQos.maxRate << inQos.minRate << inQos.TTL);
4272 
4273  NS_ASSERT (inQos.chunkSize > 0);
4274  NS_ASSERT (inQos.maxRate >= 0);
4275  NS_ASSERT (inQos.minRate >= 0);
4276  NS_ASSERT (inQos.TTL > 0);
4277 
4278  NS_LOG_FUNCTION(this << "chunkSize:" << inQos.chunkSize);
4279  NS_LOG_FUNCTION(this << "max_bps:" << inQos.maxRate);
4280  NS_LOG_FUNCTION(this << "min_bps:" << inQos.minRate);
4281  NS_LOG_FUNCTION(this << "jitter:" << inQos.jitter);
4282  NS_LOG_FUNCTION(this << "priority:" << inQos.priority);
4283  NS_LOG_FUNCTION(this << "timeout:" << inQos.timeout);
4284  NS_LOG_FUNCTION(this << "TTL:" << inQos.TTL);
4285 }
4286 
4287 void
4289  std::string srcSaeId,
4290  std::string dstSaeId,
4292  Ipv4Address dstKms,
4293  std::string &ksid,
4294  std::string appConnectionId
4295 ){
4296  NS_LOG_FUNCTION( this << srcSaeId << dstSaeId << m_local << dstKms << ksid << appConnectionId);
4297  inQos.TTL += Simulator::Now ().GetSeconds();
4298 
4300  association004.srcSaeId = srcSaeId;
4301  association004.dstSaeId = dstSaeId;
4302  association004.qos = inQos;
4303  association004.dstKmsNode = dstKms;
4304  association004.lastIndex = 0;
4305  if(ksid.empty()){
4306  ksid = appConnectionId; //GenerateKsid();
4307  association004.associationDirection = 0; //Outbound
4308  association004.peerRegistered = false;
4309  }else{
4310  association004.associationDirection = 1; //Inbound
4311  association004.peerRegistered = true;
4312  }
4313  association004.ksid = ksid;
4314 
4315  NS_LOG_FUNCTION(this << ksid << appConnectionId);
4316 
4317  m_associations004.insert(std::make_pair (ksid, association004));
4318  m_sessionList.insert(std::make_pair (ksid, 1));
4319 }
4320 
4321 bool
4323  QKDApplicationEntry &appConnection,
4324  QKDKeyAssociationLinkEntry &keyAssociation,
4327  std::string ksid
4328 ){
4329 
4330  NS_LOG_FUNCTION( this
4331  << "ksid:" << ksid
4332  << "minRate:" << inQos.minRate
4333  << "maxRate:" << inQos.maxRate
4334  << "priority:" << inQos.priority
4335  << "chunkSize:" << inQos.chunkSize
4336  << "jitter:" << inQos.jitter
4337  << "timeout:" << inQos.timeout
4338  << "TTL:" << inQos.TTL
4339  << "eskr:" << keyAssociation.GetEffectiveSKR()
4340  << "consumption:" << keyAssociation.GetExpectedConsumption()
4341  );
4342 
4343 
4344  double ratioSKR;
4345  if(keyAssociation.GetExpectedConsumption() == 0)
4346  ratioSKR = 1;
4347  else
4348  ratioSKR = (double) keyAssociation.GetExpectedConsumption()/(double) keyAssociation.GetEffectiveSKR();
4349 
4350  NS_LOG_FUNCTION(this
4351  << "keyAssociationId:" << keyAssociation.GetId()
4352  << "SKR:" << keyAssociation.GetSKR()
4353  << "EffectiveSKR:" << keyAssociation.GetEffectiveSKR()
4354  << "ratioSKR:" << ratioSKR
4355  << "ExpectedConsumption:" << keyAssociation.GetExpectedConsumption()
4356  );
4357 
4358  uint32_t processWithQos = 1;
4359 
4360  if(processWithQos)
4361  {
4362 
4363  outQos = inQos;
4364  if(
4365  inQos.maxRate == 0 ||
4366  keyAssociation.GetEffectiveSKR() < m_minKeyRate.GetBitRate()
4367  ){
4368  NS_LOG_FUNCTION(this << "No resources available!");
4369  outQos.maxRate = 0;
4370 
4371  m_providedQoS(
4372  appConnection.GetId().string(),
4373  keyAssociation.GetId().string(),
4374  ceil(inQos.maxRate/inQos.chunkSize),
4375  round (keyAssociation.GetEffectiveSKR()/inQos.chunkSize),
4376  0,
4377  0,
4378  inQos.priority
4379  );
4380 
4381  return false;
4382 
4383  }else if (
4384  ratioSKR < m_qos_maxrate_threshold
4385  ) {
4386 
4387  if(inQos.priority == 0){
4388  NS_LOG_FUNCTION(this << "No resources for low-priority requests!");
4389  outQos.maxRate = 0;
4390 
4391  m_providedQoS(
4392  appConnection.GetId().string(),
4393  keyAssociation.GetId().string(),
4394  ceil(inQos.maxRate/inQos.chunkSize),
4395  round (keyAssociation.GetEffectiveSKR()/inQos.chunkSize),
4396  0,
4397  0,
4398  inQos.priority
4399  );
4400 
4401  return false;
4402  }else{
4403  std::map<std::string, uint32_t>::iterator it2 = m_sessionList.find(ksid);
4404  if(it2 != m_sessionList.end()){
4405  NS_LOG_FUNCTION(this << "SESSION with KSID " << ksid << " was located in the m_session_list!");
4406  }else{
4407  NS_LOG_FUNCTION(this << "SESSION with KSID " << ksid << " was *NOT* located in m_session_list!");
4408  NS_LOG_FUNCTION(this << "WE HAVE NO ENOUGH RESOURCES TO SERVE UNTRUSTED APPS AT THE MOMENT!");
4409  outQos.maxRate = 0;
4410 
4411  m_providedQoS(
4412  appConnection.GetId().string(),
4413  keyAssociation.GetId().string(),
4414  ceil(inQos.maxRate/inQos.chunkSize),
4415  round (keyAssociation.GetEffectiveSKR()/inQos.chunkSize),
4416  0,
4417  0,
4418  inQos.priority
4419  );
4420 
4421  return false;
4422  }
4423  }
4424 
4425  } else {
4426 
4428  uint32_t chunkSizeDoubled = (inQos.chunkSize*1);
4429  uint32_t requestedNumberOfChunkKeys = 0;
4430  if(inQos.maxRate >0 && inQos.maxRate < chunkSizeDoubled){
4431  requestedNumberOfChunkKeys = 1;
4432  }else{
4433  requestedNumberOfChunkKeys = ceil(inQos.maxRate/chunkSizeDoubled);
4434  }
4435  uint32_t supportedNumberOfChunkKeys = round (keyAssociation.GetEffectiveSKR()/chunkSizeDoubled);
4436  uint32_t priorityThreshold = round(supportedNumberOfChunkKeys/2);
4437  uint32_t providedNumberOfChunkKeys;
4438 
4439  if(inQos.priority == 1){
4440  providedNumberOfChunkKeys = m_random->GetValue (priorityThreshold, supportedNumberOfChunkKeys);
4441  }else{
4442  providedNumberOfChunkKeys = m_random->GetValue (1,priorityThreshold);
4443  }
4444  //even if we have enough resources, only give what is requested
4445  if(providedNumberOfChunkKeys > requestedNumberOfChunkKeys)
4446  providedNumberOfChunkKeys = requestedNumberOfChunkKeys;
4447 
4448  NS_LOG_FUNCTION(this << "requestedNumberOfChunkKeys:" << requestedNumberOfChunkKeys);
4449  NS_LOG_FUNCTION(this << "supportedNumberOfChunkKeys:" << supportedNumberOfChunkKeys);
4450  NS_LOG_FUNCTION(this << "priorityThreshold:" << priorityThreshold);
4451  NS_LOG_FUNCTION(this << "providedNumberOfChunkKeys:" << providedNumberOfChunkKeys);
4452  outQos.maxRate = providedNumberOfChunkKeys * inQos.chunkSize;
4454 
4456  uint32_t providedTTL = m_default_ttl;
4457  NS_LOG_FUNCTION(this << "DefaultTTL:" << m_default_ttl);
4458 
4459  std::map<std::string, uint32_t>::iterator it2 = m_sessionList.find(ksid);
4460  if(it2 != m_sessionList.end()){
4461  providedTTL *= it2->second;
4462  NS_LOG_FUNCTION(this << "SESSION with KSID " << ksid << " was located in the m_session_list!");
4463  }else{
4464  NS_LOG_FUNCTION(this << "SESSION with KSID " << ksid << " was *NOT* located in m_session_list!");
4465  }
4466  //even if we have enough resources, only give what is requested
4467  if(providedTTL > inQos.TTL) providedTTL = inQos.TTL;
4468  outQos.TTL = providedTTL;
4469  NS_LOG_FUNCTION(this << "providedTTL:" << providedTTL);
4471 
4472  NS_LOG_FUNCTION(this << outQos.chunkSize << outQos.maxRate << outQos.minRate << outQos.TTL);
4473 
4474  NS_ASSERT (outQos.chunkSize > 0);
4475  NS_ASSERT (outQos.maxRate >= 0);
4476  NS_ASSERT (outQos.minRate >= 0);
4477  NS_ASSERT (outQos.TTL > 0);
4478 
4479  m_providedQoS(
4480  appConnection.GetId().string(),
4481  keyAssociation.GetId().string(),
4482  requestedNumberOfChunkKeys,
4483  supportedNumberOfChunkKeys,
4484  providedNumberOfChunkKeys,
4485  priorityThreshold,
4486  inQos.priority
4487  );
4488 
4489  return true;
4490  }
4491 
4492  //old strict approach (provide requested keys or not)
4493  }else{
4494 
4495  uint32_t chunkSizeDoubled = (inQos.chunkSize);
4496  uint32_t supportedNumberOfChunkKeys = round (keyAssociation.GetEffectiveSKR()/chunkSizeDoubled);
4497  uint32_t requestedNumberOfChunkKeys = ceil (inQos.maxRate/chunkSizeDoubled);
4498  uint32_t providedNumberOfChunkKeys = requestedNumberOfChunkKeys;
4499  uint32_t priorityThreshold = 0;
4500 
4501  if(requestedNumberOfChunkKeys > supportedNumberOfChunkKeys)
4502  {
4503  outQos.maxRate = 0;
4504  providedNumberOfChunkKeys = 0;
4505  }
4506 
4507  NS_LOG_FUNCTION(this << "requestedNumberOfChunkKeys:" << requestedNumberOfChunkKeys);
4508  NS_LOG_FUNCTION(this << "supportedNumberOfChunkKeys:" << supportedNumberOfChunkKeys);
4509  NS_LOG_FUNCTION(this << "priorityThreshold:" << priorityThreshold);
4510  NS_LOG_FUNCTION(this << "providedNumberOfChunkKeys:" << providedNumberOfChunkKeys);
4511 
4512 
4513  m_providedQoS(
4514  appConnection.GetId().string(),
4515  keyAssociation.GetId().string(),
4516  requestedNumberOfChunkKeys,
4517  supportedNumberOfChunkKeys,
4518  providedNumberOfChunkKeys,
4519  priorityThreshold,
4520  inQos.priority
4521  );
4522  }
4523 
4524 
4525  return true;
4526 }
4527 
4528 
4529 
4530 std::string
4532 
4533  std::string keyId;
4534  //UUID keyIdRaw = UUID::Sequential();
4535  UUID keyIdRaw = UUID::Random();
4536  keyId = keyIdRaw.string();
4537  NS_LOG_FUNCTION(this << keyId);
4538  return keyId;
4539 }
4540 
4541 } // Namespace ns3
a polymophic address class
Definition: address.h:91
bool IsInvalid(void) const
Definition: address.cc:68
The base class for all ns3 applications.
Definition: application.h:61
virtual void DoDispose(void)
Destructor implementation.
Definition: application.cc:83
Class for representing data rates.
Definition: data-rate.h:89
uint64_t GetBitRate() const
Get the underlying bitrate.
Definition: data-rate.cc:287
AttributeValue implementation for DataRate.
Definition: data-rate.h:298
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:41
An identifier for simulation events.
Definition: event-id.h:54
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
void Parse(HTTPMessage *httpMessage, const std::string &buffer)
Parse a std::string to a HTTP message.
Definition: http.h:951
an Inet address class
uint16_t GetPort(void) const
Ipv4Address GetIpv4(void) const
static bool IsMatchingType(const Address &address)
static InetSocketAddress ConvertFrom(const Address &address)
Returns an InetSocketAddress which corresponds to the input Address.
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:41
void Print(std::ostream &os) const
Print this address to the given output stream.
static Ipv4Address GetAny(void)
AttributeValue implementation for Ipv4Address.
Definition: ipv4-address.h:341
uint32_t GetId(void) const
Definition: node.cc:109
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:335
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:378
std::string ToString(void) const
Return a string representation of the packet.
Definition: packet.cc:426
void RemoveAtStart(uint32_t size)
Remove size bytes from the start of the current packet.
Definition: packet.cc:362
uint64_t GetUid(void) const
Returns the packet's Uid.
Definition: packet.cc:390
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
Create a new packet which contains a fragment of the original packet.
Definition: packet.cc:227
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:856
Introspection did not find any typical Config paths.
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.
Introspection did not find any typical Config paths.
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(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:556
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
virtual int Send(Ptr< Packet > p, uint32_t flags)=0
Send data (or dummy data) to the remote host.
void SetConnectCallback(Callback< void, Ptr< Socket > > connectionSucceeded, Callback< void, Ptr< Socket > > connectionFailed)
Specify callbacks to allow the caller to determine if the connection succeeds of fails.
Definition: socket.cc:84
void SetAcceptCallback(Callback< bool, Ptr< Socket >, const Address & > connectionRequest, Callback< void, Ptr< Socket >, const Address & > newConnectionCreated)
Accept connection requests from remote hosts.
Definition: socket.cc:104
virtual int ShutdownRecv(void)=0
@ NS3_SOCK_STREAM
Definition: socket.h:105
@ NS3_SOCK_SEQPACKET
Definition: socket.h:106
virtual int Listen(void)=0
Listen for incoming connections.
void SetDataSentCallback(Callback< void, Ptr< Socket >, uint32_t > dataSent)
Notify application when a packet has been sent from transport protocol (non-standard socket call)
Definition: socket.cc:114
virtual int GetPeerName(Address &address) const =0
Get the peer address of a connected socket.
virtual int ShutdownSend(void)=0
virtual int Connect(const Address &address)=0
Initiate a connection to a remote host.
virtual int Close(void)=0
Close a socket.
void SetCloseCallbacks(Callback< void, Ptr< Socket > > normalClose, Callback< void, Ptr< Socket > > errorClose)
Detect socket recv() events such as graceful shutdown or error.
Definition: socket.cc:94
void SetRecvCallback(Callback< void, Ptr< Socket > > receivedData)
Notify application when new data is available to be read.
Definition: socket.cc:128
static Ptr< Socket > CreateSocket(Ptr< Node > node, TypeId tid)
This method wraps the creation of sockets that is performed on a given node by a SocketFactory specif...
Definition: socket.cc:71
virtual int Bind(const Address &address)=0
Allocate a local endpoint for this socket.
virtual Ptr< Packet > RecvFrom(uint32_t maxSize, uint32_t flags, Address &fromAddress)=0
Read a single packet from the socket and retrieve the sender address.
virtual enum Socket::SocketType GetSocketType(void) const =0
static TypeId GetTypeId(void)
Get the type ID.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:379
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
AttributeValue implementation for TypeId.
Definition: type-id.h:595
Universally unique identifier (UUID)
Definition: uuid.h:35
static UUID Random()
Generate random UUID4 (randomly or pseudo-randomly generated version)
Definition: uuid.cc:148
static UUID 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(void)
Get the type ID.
Hold an unsigned integer type.
Definition: uinteger.h:44
double GetValue(double min, double max)
Get the next random value, as a double in the specified range .
make Callback use a separate empty type
Definition: empty.h:34
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:67
Ptr< const AttributeAccessor > MakeDataRateAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: data-rate.h:298
Ptr< const AttributeChecker > MakeDataRateChecker(void)
Definition: data-rate.cc:30
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: double.h:42
Ptr< const AttributeChecker > MakeIpv4AddressChecker(void)
Ptr< const AttributeAccessor > MakeIpv4AddressAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: ipv4-address.h:341
Ptr< const AttributeAccessor > MakeTypeIdAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: type-id.h:595
Ptr< const AttributeChecker > MakeTypeIdChecker(void)
Definition: type-id.cc:1226
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: uinteger.h:45
Callback< R, Ts... > MakeNullCallback(void)
Definition: callback.h:1688
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:165
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1244
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
basic_json<> json
default JSON class
Definition: json.h:3000
NLOHMANN_BASIC_JSON_TPL_DECLARATION std::string to_string(const NLOHMANN_BASIC_JSON_TPL &j)
user-defined to_string function for JSON values
Definition: json.h:25255
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::string GetQKDApplicationEntryText(const uint16_t statusCode)
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:1648
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.