A Discrete-Event Network Simulator
API
sink.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 
3 /*
4 * Copyright (c) 2020 DLTLT
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation;
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 * Corresponding author: Niki Hrovatin <niki.hrovatin@famnit.upr.si>
20 */
21 
22 #include "sink.h"
23 
24 namespace ns3 {
25 
26 //Zagotovi, da se registrira TypeId
27 NS_OBJECT_ENSURE_REGISTERED (Sink);
28 
29 NS_LOG_COMPONENT_DEFINE ("sink");
30 
31 TypeId
33 {
34  static TypeId tid =
35  TypeId ("ns3::Sink")
36  .SetParent<Wsn_node> ()
37  .AddConstructor<Sink> ()
38  .AddAttribute ("NumNodes", "The number of sensor nodes in the simulation.",
39  TypeId::ATTR_CONSTRUCT | TypeId::ATTR_SET | TypeId::ATTR_GET,
40  UintegerValue (0), MakeUintegerAccessor (&Sink::m_numnodes),
41  MakeUintegerChecker<uint16_t> ())
42  .AddAttribute (
43  "OnionDelay", "The sink will start sending onion messagess after OnionDelay seconds.",
44  TypeId::ATTR_CONSTRUCT | TypeId::ATTR_SET | TypeId::ATTR_GET, UintegerValue (5),
45  MakeUintegerAccessor (&Sink::m_onionDelay), MakeUintegerChecker<uint32_t> ())
46  .AddAttribute ("FixedOnionSize", "Maintain a fixed onion size by adding padding.",
47  TypeId::ATTR_CONSTRUCT | TypeId::ATTR_SET | TypeId::ATTR_GET,
48  BooleanValue (true), MakeBooleanAccessor (&Sink::m_fixedOnionSize),
49  MakeBooleanChecker ())
50  .AddAttribute ("BodyOptions", "Modify the behaviour of the onion body",
51  EnumValue (BodyOptions::NO_Body), MakeEnumAccessor (&Sink::m_bodyOptions),
52  MakeEnumChecker (BodyOptions::NO_Body, "nobody", BodyOptions::Aggregate,
53  "aggregate", BodyOptions::FixedSize, "fixed",
55  .AddAttribute (
56  "BodySize", "Size of the onion body maintained fixed during the simulation",
57  TypeId::ATTR_CONSTRUCT | TypeId::ATTR_SET | TypeId::ATTR_GET, UintegerValue (128),
58  MakeUintegerAccessor (&Sink::m_bodySize), MakeUintegerChecker<uint16_t> ());
59 
60  return tid;
61 }
62 
64 {
65 }
66 
68 {
69  m_socket = 0;
70 }
71 
72 void
73 Sink::Setup (uint16_t *onionPathlengths, uint16_t numOnionLengths, int repeateTimes)
74 {
75  this->m_onionPathLengths = new uint16_t[numOnionLengths];
76  for (int i = 0; i < numOnionLengths; ++i)
77  {
78  this->m_onionPathLengths[i] = onionPathlengths[i];
79  }
80  this->m_numOnionLengths = numOnionLengths;
81  this->m_repeateTimes = repeateTimes;
82 }
83 
84 //callback, at a new connection
85 
86 void
87 Sink::Accept (Ptr<Socket> socket, const ns3::Address &from)
88 {
89  socket->SetRecvCallback (MakeCallback (&Sink::ReceivePacket, this));
90 }
91 
92 //callback, when a new packet is received
93 
94 void
95 Sink::ReceivePacket (Ptr<Socket> socket)
96 {
97  Address from;
98  Ptr<Packet> p = Wsn_node::RecvSegment (socket, from);
99 
100  if (p != NULL)
101  {
102  NotifyRx (p);
103 
104  InetSocketAddress address = InetSocketAddress::ConvertFrom (from);
106  p->RemoveHeader (sw);
108  sw.GetData (&message);
109 
110  if (message.has_h_shake ())
111  {
112  //register node
113  RecvHandshake (message.mutable_h_shake (), address);
114  }
115  else //onion message
116  {
117  //get the onion ID
118  o_sequenceNum = message.mutable_o_head ()->onionid ();
119 
120  //
121  if (o_sequenceNum == m_onionId - 1)
122  { //message IDs are equal, -1 since m_onionId is larger for one value
123 
124  //call that onion was received
126 
127  RecvOnion (message.mutable_o_body ());
128  }
129  else
130  { //the onion should be deleted
131  NS_LOG_INFO ("Ghost onion received, deleted with onion id: "
132  << o_sequenceNum << ", at ip: " << m_address
133  << ", at time: " << std::to_string (Simulator::Now ().GetSeconds ()));
134  }
135  }
136  }
137 }
138 
139 //execute when a new node register on the sink
140 
141 void
142 Sink::RecvHandshake (protomessage::ProtoPacket_Handshake *handshake_message, InetSocketAddress from)
143 {
144  std::string pk = handshake_message->publickey ();
145  m_nodeManager[from.GetIpv4 ().Get ()] = pk;
146 
147  //print output to file
148  m_outputManager->NewHandshake (m_nodeManager.size () - 1, from.GetIpv4 (), Simulator::Now ());
149 }
150 
151 //Execute at the recv of the onion
152 
153 void
155 {
156  m_outputManager->OnionRoutingRecv (Simulator::Now ());
157  m_outputManager->RecvOnion (Simulator::Now ());
158  Simulator::Schedule (Seconds (0.5), &Sink::SinkTasks, this);
159 }
160 
161 //defines the behaviour of the source how many OR sends, how to build the route ecc...
162 void
164 {
165 
167  {
168 
170  {
171 
172  //selet the route of the onion
175  //send the onion
177 
178  m_repeateCount++;
179  }
180  else
181  {
182  m_repeateCount = 0;
184  SinkTasks (); // call again with new params
185  }
186  }
187  else
188  {
189  //simulation ended, can print details of nodes
190  m_outputManager->PrintNodeDetails (m_nodeManager);
191 
192  //end simulation
193  Simulator::Stop ();
194  }
195 }
196 
197 //builds randomly the route to the sensor and back
198 //the length of the route is static!
199 //the route can have loops, but each node must not be placed consequently in the route
200 // the route must be of lentgh at least 3
201 void
202 Sink::SelectRoute (int *route, int routeLen)
203 {
204 
205  assert (routeLen >= 3); // the route must be of lentgh at least 3
206 
207  Ptr<UniformRandomVariable> x = CreateObject<UniformRandomVariable> ();
208  int node_id;
209 
210  //previous id -> previous and current must not be equal
211  int prev_id = -1;
212 
213  //build the route
214  int i = routeLen - 1;
215  while (i >= 0)
216  {
217  node_id = x->GetInteger (0, m_nodeManager.size () - 1);
218  if (node_id != prev_id)
219  {
220  route[i] = node_id;
221  i--;
222  }
223  prev_id = node_id;
224  }
225 }
226 
227 //prepare the route to call the onion routing on the new class or.h
228 
229 void
230 Sink::PrepareOnion (int *route, int routeLen)
231 {
232  int cipherLen = m_onionManager.OnionLength (routeLen + 1, 0, 0);
233  unsigned char cipher[cipherLen];
234 
235  unsigned char *ipRoute[routeLen + 1];
236 
237  unsigned char *keys[routeLen + 1];
238 
239  //sink details
240  keys[routeLen] = m_onionManager.StringToUchar (m_publickey);
241  ipRoute[routeLen] =
242  m_onionManager.IpToBuff (m_address.Get ()); //set sink node as the last node in the onion path
243 
244  //define an iterator
245  std::map<uint32_t, std::string>::iterator item;
246 
247  //fill other addresses and publickeys
248  for (int i = 0; i < routeLen; ++i)
249  {
250  item = m_nodeManager.begin ();
251  std::advance (item, route[i]);
252 
253  ipRoute[i] = m_onionManager.IpToBuff (item->first);
254 
255  keys[i] = m_onionManager.StringToUchar (item->second);
256  }
257 
258  m_onionManager.BuildOnion (cipher, ipRoute, keys, routeLen + 1);
259 
260  item = m_nodeManager.begin ();
261  std::advance (item, route[0]);
262  SendOnion (item->first, routeLen, cipher, cipherLen);
263 
264  //release memory
265  for (int i = 0; i < routeLen; ++i)
266  {
267  delete[] keys[i];
268  }
269 }
270 
271 void
272 Sink::SendOnion (uint32_t firstHop, int routeLen, unsigned char *cipher, int cipherLen)
273 {
274  //first convert cipher to string!!
275  std::string str_cipher = m_onionManager.UcharToString (cipher, cipherLen);
277 
278  //Create the onion head
279  onion.mutable_o_head ()->set_onion_message (str_cipher);
281 
282  // fixed onion head size
283  if (m_fixedOnionSize)
284  {
285  onion.mutable_o_head ()->set_padding ("");
286  }
287 
288  //Specify how the onion body must behave
289  std::string padding (m_bodySize, '0');
290  switch (m_bodyOptions)
291  {
293  break;
296  break;
298  onion.mutable_o_body ()->set_padding (padding);
299  break;
302  onion.mutable_o_body ()->set_padding (padding);
303  break;
304  }
305 
306  //Create the packet
307  SerializationWrapper sw (onion);
308  Ptr<Packet> p = Create<Packet> ();
309  p->AddHeader (sw);
310 
311  InetSocketAddress remote = InetSocketAddress (Ipv4Address (firstHop), m_port);
312 
313  NotifyTx (p);
314  Wsn_node::SendSegment (remote, p, true);
315 
316  m_onionValidator->StartOnion (m_onionId);
317  //increment onion sequence number
318  m_onionId++;
319 
320  m_outputManager->SendOnion (p->GetSize (), onion.mutable_o_head ()->ByteSizeLong (),
321  onion.mutable_o_body ()->ByteSizeLong (), routeLen,
322  Simulator::Now ());
323  m_outputManager->OnionRoutingSend (m_address, Ipv4Address (firstHop), p->GetSize (),
324  onion.mutable_o_head ()->ByteSizeLong (),
325  onion.mutable_o_body ()->ByteSizeLong (), Simulator::Now ());
326 }
327 
328 //Check if the onion is still in the network and valid each parameter milliseconds
329 void
331 {
332  //no onion running then -> send an onion
333  if (!m_onionValidator->OnionStatus ())
334  { //Onion was aborted start a new one
335 
336  m_repeateCount--; // decrease value of m_repeateCount to re do the same onion size
337  SinkTasks ();
338  }
339 
340  //reset the the timer
341  Simulator::Schedule (Seconds (5), &Sink::CheckOnion, this);
342 }
343 
344 // executes at the start of the application
345 void
347 {
348  //basic configuration
353 
354  //sprejme nov connection izvede callback
355  m_socket->SetAcceptCallback (MakeNullCallback<bool, Ptr<Socket>, const Address &> (),
356  MakeCallback (&Sink::Accept, this));
357 
358  m_onionDelay = m_delay * m_numnodes + 5000;
359 
360  Simulator::Schedule (MilliSeconds (m_onionDelay), &Sink::SinkTasks, this);
361 
362  //start checkin if the onion is alive, and check each 5 seconds if it is alive
363  Simulator::Schedule (MilliSeconds (m_onionDelay + 5000), &Sink::CheckOnion, this);
364 }
365 
366 void
368 {
369  if (m_socket)
370  {
371  m_socket->Close ();
372  }
373 }
374 
375 } // namespace ns3
ns3::Sink::SendOnion
void SendOnion(uint32_t firstHop, int routeLen, unsigned char *cipher, int cipherLen)
The method constructs the onion message as a protobuf object.
Definition: sink.cc:272
ns3::OnionManager::IpToBuff
unsigned char * IpToBuff(uint32_t in)
Convert an Ipv4 address given as an unsigned integer value to buffer array of 4Bytes.
Definition: onionmanager.cc:155
ns3::Wsn_node::m_socket
Ptr< Socket > m_socket
listening socket
Definition: wsn_node.h:228
protomessage::ProtoPacket::mutable_h_shake
::protomessage::ProtoPacket_Handshake * mutable_h_shake()
Definition: proto-packet.pb.h:1216
ns3::Wsn_node::RecvSegment
Ptr< Packet > RecvSegment(Ptr< Socket > socket)
method for receiving a segment calls ns3::Wsn_node::RecvSeg()
Definition: wsn_node.cc:249
ns3::Sink::m_onionId
int m_onionId
onion ID incremented each time a new onion is issued
Definition: sink.h:225
ns3::OnionManager::GetPKtoString
std::string GetPKtoString()
accessor
Definition: onionmanager.cc:103
ns3::Wsn_node::o_sequenceNum
int o_sequenceNum
sequence number of the onion, should be same as onion_id
Definition: wsn_node.h:241
ns3::Sink::m_publickey
std::string m_publickey
the encryption key: publickey
Definition: sink.h:231
ns3
Definition: sensornode-helper.cc:26
ns3::Wsn_node::SendSegment
void SendSegment(InetSocketAddress remote, Ptr< Packet > packet, bool b_onion)
Send a packet through a TCP connection to the remote address.
Definition: wsn_node.cc:217
protomessage::ProtoPacket::mutable_o_body
::protomessage::ProtoPacket_OnionBody * mutable_o_body()
Definition: proto-packet.pb.h:1396
protomessage::ProtoPacket_OnionBody::ByteSizeLong
size_t ByteSizeLong() const final
Definition: proto-packet.pb.cc:623
protomessage::ProtoPacket_OnionHead::onionid
int32_t onionid() const
Definition: proto-packet.pb.h:822
ns3::Wsn_node::m_onionValidator
Ptr< OnionValidator > m_onionValidator
Pointer to the ns3::OnionValidator.
Definition: wsn_node.h:226
ns3::OnionRouting::OnionLength
uint16_t OnionLength(uint16_t routeLen, uint16_t contentLen)
Definition: onion-routing.cc:180
ns3::Sink::m_bodySize
uint16_t m_bodySize
Definition: sink.h:215
ns3::OnionManager::UcharToString
std::string UcharToString(unsigned char *seq, int len)
Convert an array of unsigned chars to a std::string.
Definition: onionmanager.cc:147
ns3::OnionManager::StringToUchar
unsigned char * StringToUchar(std::string in)
Convert a string to an array of unsigned chars.
Definition: onionmanager.cc:138
ns3::Sink::m_repeateTimes
int m_repeateTimes
Integer specifying the number of times to generate the onion message for each value in the m_onionPat...
Definition: sink.h:218
ns3::Wsn_node::m_address
Ipv4Address m_address
ns3::Ipv4Address of this node
Definition: wsn_node.h:227
ns3::OnionManager::GetSKtoString
std::string GetSKtoString()
accessor
Definition: onionmanager.cc:111
ns3::Sink::Setup
void Setup(uint16_t *onionPathlengths, uint16_t numOnionLengths, int repeateTimes)
Setup sink node parameters after the application installation.
Definition: sink.cc:73
ns3::FixedSize
@ FixedSize
the onion body will have a fixed size specified by the ns3::Sink::BodySize attribute
Definition: enums.h:109
ns3::Sink::m_decoyNum
uint32_t m_decoyNum
dummy decoy value used to obfuscate the value carried in the onion body
Definition: sink.h:210
protomessage::ProtoPacket_Handshake::publickey
const std::string & publickey() const
Definition: proto-packet.pb.h:1090
ns3::Sink::m_repeateCount
int m_repeateCount
how many times the onion was sent at the current path length
Definition: sink.h:219
ns3::Sink::m_onionDelay
uint32_t m_onionDelay
The sink will start sending onion messagess after OnionDelay seconds.
Definition: sink.h:207
protomessage::ProtoPacket::mutable_o_head
::protomessage::ProtoPacket_OnionHead * mutable_o_head()
Definition: proto-packet.pb.h:1306
ns3::Sink::StartApplication
virtual void StartApplication(void)
1.Start the application run ns3::Wsn_node::Configure() 2.Generate new encryption keys 3....
Definition: sink.cc:346
ns3::Sink::CheckOnion
void CheckOnion(void)
Each five seconds call the ns3::OnionValidator and check if at least one onion message is alive Other...
Definition: sink.cc:330
protomessage::ProtoPacket_OnionBody::set_padding
void set_padding(ArgT0 &&arg0, ArgT... args)
protomessage::ProtoPacket_OnionHead::set_onion_message
void set_onion_message(ArgT0 &&arg0, ArgT... args)
ns3::Sink::~Sink
virtual ~Sink()
Default destructor.
Definition: sink.cc:67
ns3::Sink::StopApplication
virtual void StopApplication(void)
Stop the application.
Definition: sink.cc:367
ns3::Wsn_node::NotifyRx
void NotifyRx(Ptr< const Packet > packet)
Call to signal the receipt of a Packet at the application layer.
Definition: wsn_node.cc:82
ns3::Wsn_node::m_onionManager
OnionManager m_onionManager
The ns3::OnionManager object.
Definition: wsn_node.h:230
ns3::NO_Body
@ NO_Body
The onion message won't have an onion body.
Definition: enums.h:107
ns3::SerializationWrapper
Class for the serialization-deserialization of the messagess to send in packets.
Definition: serializationwrapper.h:54
ns3::Aggregate
@ Aggregate
The onion body will only aggregate a value.
Definition: enums.h:108
ns3::Sink::m_nodeManager
std::map< uint32_t, std::string > m_nodeManager
hashmap to manage data about nodes in the WSN// pair <IP,publickey>
Definition: sink.h:209
ns3::AggregateAndFixed
@ AggregateAndFixed
The onion body will aggregate a value and will maintain a fixed size apecified by the ns3::Sink::Body...
Definition: enums.h:110
ns3::Sink::m_bodyOptions
enum BodyOptions m_bodyOptions
Definition: sink.h:214
ns3::Wsn_node::m_outputManager
Ptr< OutputManager > m_outputManager
Pointer to the ns3::OutputManager.
Definition: wsn_node.h:225
protomessage::ProtoPacket_OnionBody
Definition: proto-packet.pb.h:271
ns3::Sink::m_fixedOnionSize
bool m_fixedOnionSize
maintain the onion size fixed by adding padding (after layer decryption)
Definition: sink.h:213
ns3::Wsn_node::m_port
uint16_t m_port
port of the application
Definition: wsn_node.h:224
protomessage::ProtoPacket::has_h_shake
bool has_h_shake() const
Definition: proto-packet.pb.h:1157
ns3::Sink::GetTypeId
static TypeId GetTypeId(void)
Register this type.
Definition: sink.cc:32
ns3::Wsn_node
The wsn node base class that manages the sending and receiving of packets and basic configuration of ...
Definition: wsn_node.h:61
ns3::OnionManager::GenerateNewKeyPair
void GenerateNewKeyPair(void)
Generate a new public/private keypair using the libsodium library.
Definition: onionmanager.cc:81
ns3::Sink::RecvHandshake
void RecvHandshake(protomessage::ProtoPacket_Handshake *handshake_data, InetSocketAddress from)
When receiving a new handshake with a node.
Definition: sink.cc:142
ns3::Sink::Sink
Sink()
Default constructor.
Definition: sink.cc:63
ns3::Sink::m_secretkey
std::string m_secretkey
the encryption key: secretkey
Definition: sink.h:232
ns3::OnionRouting::BuildOnion
int BuildOnion(uint8_t *cipher, uint8_t **route, uint16_t routeLen, uint8_t **keys, uint8_t *content, uint16_t contentLen)
Definition: onion-routing.cc:63
ns3::Sink::SinkTasks
void SinkTasks()
Schedule the creation of a new onion based on the path length specified in m_onionPathLengths If all ...
Definition: sink.cc:163
ns3::Wsn_node::NotifyTx
void NotifyTx(Ptr< const Packet > packet)
Call to signal the transmission of a Packet at the application layer.
Definition: wsn_node.cc:76
protomessage::ProtoPacket
Definition: proto-packet.pb.h:598
ns3::Sink::m_numnodes
uint16_t m_numnodes
The number of sensor nodes in the simulation.
Definition: sink.h:206
sink.h
protomessage::ProtoPacket_OnionHead::set_onionid
void set_onionid(int32_t value)
Definition: proto-packet.pb.h:830
ns3::Wsn_node::Configure
void Configure(void)
1.
Definition: wsn_node.cc:102
protomessage::ProtoPacket_Handshake
Definition: proto-packet.pb.h:442
ns3::Sink::ReceivePacket
void ReceivePacket(Ptr< Socket > socket)
Recieve a new packet from socket Check if the packet is a handshake packet or a packet containing an ...
Definition: sink.cc:95
ns3::Sink::Accept
void Accept(Ptr< Socket > socket, const ns3::Address &from)
Accept new TCP connections.
Definition: sink.cc:87
ns3::Sink::m_onionLengthIndex
int m_onionLengthIndex
index of the current onion path length
Definition: sink.h:220
protomessage::ProtoPacket_OnionBody::set_aggregatedvalue
void set_aggregatedvalue(int32_t value)
Definition: proto-packet.pb.h:1000
protomessage::ProtoPacket_OnionHead::set_padding
void set_padding(ArgT0 &&arg0, ArgT... args)
ns3::Wsn_node::OnionReceived
void OnionReceived(void)
Signal to the ns3::OnionValidator that the onion was corrctly received.
Definition: wsn_node.cc:331
ns3::Sink::SelectRoute
void SelectRoute(int *route, int routeLen)
The method builds the path of the onion message by randomly selecting sensor nodes from the m_nodeMan...
Definition: sink.cc:202
ns3::Sink::PrepareOnion
void PrepareOnion(int *route, int routeLen)
Method that constructs the onion head from route and routeLen parameters.
Definition: sink.cc:230
ns3::Sink::m_onionPathLengths
uint16_t * m_onionPathLengths
array holding onion path lengths
Definition: sink.h:221
ns3::Sink::RecvOnion
void RecvOnion(protomessage::ProtoPacket_OnionBody *onion_body)
Triggered when an onion message is received back at the sink node Data about the message is captured ...
Definition: sink.cc:154
ns3::SerializationWrapper::GetData
void GetData(protomessage::ProtoPacket *message)
Getter of the data in the protocol header.
Definition: serializationwrapper.cc:78
protomessage::ProtoPacket_OnionHead::ByteSizeLong
size_t ByteSizeLong() const final
Definition: proto-packet.pb.cc:361
ns3::Wsn_node::m_delay
uint16_t m_delay
delay after which the handshake process will start
Definition: wsn_node.h:229
ns3::Sink::m_numOnionLengths
uint16_t m_numOnionLengths
size of the array m_onionPathsLengths
Definition: sink.h:222