GeoNetworkingLayer.cc 8.96 KB
Newer Older
garciay's avatar
garciay committed
1
2
#include <chrono>

garciay's avatar
garciay committed
3
4
5
6
7
#include "GeoNetworkingLayer.hh"
#include "GeoNetworkingTypes.hh"

#include "loggers.hh"

garciay's avatar
garciay committed
8
9
using namespace LibItsGeoNetworking__TypesAndValues;

10
GeoNetworkingLayer::GeoNetworkingLayer(const std::string & p_type, const std::string & param) : TLayer<LibItsGeoNetworking__TestSystem::GeoNetworkingPort>(p_type), _params(), _codec(), _beacon(NULL), _thread(NULL), _sendData(), _running(FALSE) {
garciay's avatar
garciay committed
11
  loggers::get_instance().log(">>> GeoNetworkingLayer::GeoNetworkingLayer: %s, %s", to_string().c_str(), param.c_str());
garciay's avatar
garciay committed
12
13
  // Setup parameters
  Params::convert(_params, param);
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  // Sanity checks
  INTEGER latitude;
  Params::const_iterator it = _params.find(Params::latitude);
  if (it != _params.cend()) {
    latitude = str2int(CHARSTRING(it->second.c_str()));
  }
  INTEGER longitude;
  it = _params.find(Params::longitude);
  if (it != _params.cend()) {
    longitude = str2int(CHARSTRING(it->second.c_str()));
  }
  OCTETSTRING ll_address;
  it = _params.find(Params::ll_address);
  if (it != _params.cend()) {
    ll_address = str2oct(CHARSTRING(it->second.c_str()));
  }
  // Add broadcast address if needed
  it = _params.find("mac_bc");
garciay's avatar
garciay committed
32
33
34
  if (it == _params.cend()) {
    _params.insert(std::pair<std::string, std::string>(std::string("mac_bc"), "FFFFFFFFFFFF"));
  }
garciay's avatar
garciay committed
35
36
37
38
39
40
41
42
43
44
45
46
47
  // Prepare the static part of the TestSystem beacon
  // TODO Add a method
  _beacon = new GeoNetworkingPdu();
  HeaderTST h;
  h.beaconHdr() = BeaconHeaderType(
				   HeaderType(HeaderType::e__beacon),
				   0
				   );
  ExtendedHeader eh;
  eh.beaconHeader() = BeaconHeader(
				   LongPosVector(
						 GN__Address(
							     TypeOfAddress(TypeOfAddress::e__manual),
48
							     StationType(StationType::e__roadSideUnit),
garciay's avatar
garciay committed
49
							     33,
50
							     ll_address
garciay's avatar
garciay committed
51
52
							     ),
						 0,
53
54
						 latitude,
						 longitude,
garciay's avatar
garciay committed
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
						 int2bit(0, 1),
						 0,
						 0
						 )
				   );
  _beacon->basicHeader() = BasicHeader(
				       0,
				       BasicNextHeader(
						       BasicNextHeader::e__commonHeader
						       ),
				       0,
				       Lifetime(
						4,
						LtBase(LtBase::e__50ms)
						),
				       5
				       );
  _beacon->gnPacket().packet() = GnNonSecuredPacket(
						    CommonHeader(
								 NextHeader(
									    NextHeader::e__any
									    ),
								 0,
								 h,
								 TrafficClass(
									      SCF(SCF::e__scfDisabled),
									      ChannelOffload(ChannelOffload::e__choffDisabled),
									     0
									     ),
								 int2bit(0, 8),
								 0,
								 1,
								 0
								 ),
						    OPTIONAL<ExtendedHeader>(eh),
90
						    OPTIONAL<GnRawPayload>()
garciay's avatar
garciay committed
91
92
93
94
						    );
  _beacon->gnPacket().packet().payload().set_to_omit();
  _beacon->gnPacket().securedMsg().set_to_omit();
  //  loggers::get_instance().log_msg("GeoNetworkingLayer::GeoNetworkingLayer: beacon value: ", *p._beacon);
95
96
}

garciay's avatar
garciay committed
97
GeoNetworkingLayer::~GeoNetworkingLayer() {
garciay's avatar
garciay committed
98
99
  stop_beaconing();
  delete _beacon;
garciay's avatar
garciay committed
100
101
}
void GeoNetworkingLayer::sendMsg(const LibItsGeoNetworking__TestSystem::GeoNetworkingReq& p, Params& params) {
garciay's avatar
garciay committed
102
  loggers::get_instance().log(">>> GeoNetworkingLayer::sendMsg");
garciay's avatar
garciay committed
103
104

  // Encode GeoNetworking PDU
garciay's avatar
garciay committed
105
106
  OCTETSTRING data;
  _codec.encode(p.msgOut(), data);
garciay's avatar
garciay committed
107
  sendData(data, params);
garciay's avatar
garciay committed
108
109
}

garciay's avatar
garciay committed
110
void GeoNetworkingLayer::sendData(OCTETSTRING& data, Params& params) {
garciay's avatar
garciay committed
111
  loggers::get_instance().log_msg(">>> GeoNetworkingLayer::sendData: ", data);
112
113
114
115
  while (_sendData.try_lock() == FALSE) {
    // not ready yet
    std::this_thread::sleep_for(std::chrono::milliseconds(1));
  } // End of 'while' statement
garciay's avatar
garciay committed
116
  sendToAllLayers(data, params);
117
118
  _sendData.unlock();
  loggers::get_instance().log("<<< GeoNetworkingLayer::sendData");
garciay's avatar
garciay committed
119
120
}

garciay's avatar
garciay committed
121
void GeoNetworkingLayer::receiveData(OCTETSTRING& data, Params& params) { 
garciay's avatar
garciay committed
122
  loggers::get_instance().log_msg(">>> GeoNetworkingLayer::receiveData: ", data);
garciay's avatar
garciay committed
123
124
  // Decode the payload
  LibItsGeoNetworking__TestSystem::GeoNetworkingInd p;
125
  _codec.decode(data, p.msgIn(), &params);
garciay's avatar
garciay committed
126
  // Add lower layers parameters
garciay's avatar
garciay committed
127
  // 1. Destination MAC address
garciay's avatar
garciay committed
128
  Params::const_iterator it = params.find(Params::mac_dst);
garciay's avatar
garciay committed
129
  if (it != params.cend()) {
130
    loggers::get_instance().log("GeoNetworkingLayer::receiveData: dst=%s", it->second.c_str());
garciay's avatar
garciay committed
131
132
    p.macDestinationAddress() = str2oct(CHARSTRING(it->second.c_str()));
  } else {
garciay's avatar
garciay committed
133
    p.macDestinationAddress() = str2oct(CHARSTRING(_params["mac_bc"].c_str()));
garciay's avatar
garciay committed
134
135
136
137
  }
  // 2. ssp
  it = params.find(Params::ssp);
  if (it != params.cend()) {
138
    loggers::get_instance().log("GeoNetworkingLayer::receiveData: ssp=%s", it->second.c_str());
garciay's avatar
garciay committed
139
140
141
    p.ssp() = str2bit(CHARSTRING(it->second.c_str()));
  } else {
    p.ssp().set_to_omit();
garciay's avatar
garciay committed
142
  }
garciay's avatar
garciay committed
143
144
145
  // 3. its_aid
  it = params.find(Params::its_aid);
  if (it != params.cend()) {
146
    loggers::get_instance().log("GeoNetworkingLayer::receiveData: its_aid=%s", it->second.c_str());
garciay's avatar
garciay committed
147
148
149
150
151
    p.its__aid() = std::stoi(it->second.c_str());
  } else {
    p.its__aid().set_to_omit();
  }
  
152
153
154
155
156
157
158
159
160
161
  // Pass the GeoNetworking raw payload to the upper layers if any
  it = params.find(Params::gn_payload);
  if (it != params.cend()) {
    loggers::get_instance().log("GeoNetworkingLayer::receiveData: gn_payload=%s", it->second.c_str());
    OCTETSTRING os(str2oct(CHARSTRING(it->second.c_str())));
    receiveToAllLayers(os, params);
  } else {
    loggers::get_instance().warning("GeoNetworkingLayer::receiveData: No payload to pass to upper layers");
  }
  // Pass it to the ports
garciay's avatar
garciay committed
162
  toAllUpperPorts(p, params);
garciay's avatar
garciay committed
163
164
}

garciay's avatar
garciay committed
165
void GeoNetworkingLayer::start_beaconing() {
garciay's avatar
garciay committed
166
167
  loggers::get_instance().log(">>> GeoNetworkingLayer::start_beaconing");

garciay's avatar
garciay committed
168
169
170
171
172
173
174
175
176
177
178
  // Create the offline reader thread
  _thread = new std::thread(&GeoNetworkingLayer::run_beaconing, (void *)this);
  if (_thread == NULL) {
    loggers::get_instance().error("GeoNetworkingLayer::start_beaconing: Failed to start beaconing thread");
  }
  // Wait for the thread
  while (_running == FALSE) {
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
  }
  // Thread was started
  loggers::get_instance().log("<<< PcapLayer::PcapLayer");    
garciay's avatar
garciay committed
179
180
181
182
183
184
185
186
187
188
189
190
191
}

void GeoNetworkingLayer::stop_beaconing() {
  loggers::get_instance().log(">>> GeoNetworkingLayer::stop_beaconing");
  if (_thread != NULL) {
    _running = FALSE;
    // Wait for the working thread to terminate
    _thread->join();
    loggers::get_instance().log("GeoNetworkingLayer::stop_beaconing: Thread were stops");
    _thread = NULL;
  }
}

garciay's avatar
garciay committed
192
193
194
195
196
197
void* GeoNetworkingLayer::run_beaconing(void* p_this) {
  loggers::get_instance().log(">>> GeoNetworkingLayer::run_beaconing");

  // Pointer the main object
  GeoNetworkingLayer& p = *static_cast<GeoNetworkingLayer *>(p_this);
  Params params(p._params);
198
  std::chrono::milliseconds expiry(1000); // Default is set to 1 second
garciay's avatar
garciay committed
199
200
  Params::const_iterator it = params.find("TsBeaconInterval");
  if (it != params.cend()) {
201
    expiry = std::chrono::milliseconds(std::stoul(it->second));
garciay's avatar
garciay committed
202
203
204
205
206
207
  }
  ExtendedHeader* eh = static_cast<ExtendedHeader *>(p._beacon->gnPacket().packet().extendedHeader().get_opt_value());
  if (eh == NULL) {
    loggers::get_instance().error("GeoNetworkingLayer::run_beaconing: Wrong cast");
  }
  GeoNetworkingCodec codec;
208
  // Start beaconing
garciay's avatar
garciay committed
209
  p._running = TRUE;
210
211
  std::this_thread::sleep_for(std::chrono::milliseconds(100));
  while (p._running == TRUE) { // Loop while _running flag is up
garciay's avatar
garciay committed
212
    // Update timestamp
213
    unsigned long long ms = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count() - 1072911600000L; // TODO Add method such as its_tme() & its_time_mod()
garciay's avatar
garciay committed
214
    eh->beaconHeader().srcPosVector().timestamp__() = ms;
215
216
217
218
    // Encode message using TITAN because of payload in omited
    TTCN_Buffer encoding_buffer;
    p._beacon->encode(*(p._beacon->get_descriptor()), encoding_buffer, TTCN_EncDec::CT_RAW);
    OCTETSTRING data(encoding_buffer.get_len(), encoding_buffer.get_data());
garciay's avatar
garciay committed
219
220
221
    // Send it
    p.sendData(data, params);
    // Timer
222
223
224
    ms = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count() + expiry.count();
    while ((p._running == TRUE) && (ms > std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count()));
  } // End of 'while' statement<
garciay's avatar
garciay committed
225
226
227
228
229
  
  loggers::get_instance().log("<<< GeoNetworkingLayer::run_beaconing");
  return NULL;
}

garciay's avatar
garciay committed
230
class GeoNetworkingFactory: public LayerFactory {
garciay's avatar
garciay committed
231
  static GeoNetworkingFactory _f;
garciay's avatar
garciay committed
232
public:
garciay's avatar
garciay committed
233
234
235
  GeoNetworkingFactory();
  virtual Layer * createLayer(const std::string & type,
			      const std::string & param);
garciay's avatar
garciay committed
236
237
238
};

GeoNetworkingFactory::GeoNetworkingFactory() {
garciay's avatar
garciay committed
239
240
241
  // Register factory
  loggers::get_instance().log(">>> GeoNetworkingFactory::GeoNetworkingFactory");
  LayerStackBuilder::RegisterLayerFactory("GN", this);
garciay's avatar
garciay committed
242
243
244
}

Layer * GeoNetworkingFactory::createLayer(const std::string & type, const std::string & param) {
garciay's avatar
garciay committed
245
  return new GeoNetworkingLayer(type, param);
garciay's avatar
garciay committed
246
247
248
}

GeoNetworkingFactory GeoNetworkingFactory::_f;