ITS
denReceptionManagement.cpp
Go to the documentation of this file.
2 
5  ParameterNetwork *network)
6 {
7  m_paramGPS = gps;
8  m_paramAppli = appli;
9  m_paramDENM = denm;
10  m_geonet = gn;
11  m_paramConf = conf;
12  m_paramCan = can;
13  m_mutexReception = new QMutex;
14 
15  m_sequenceNumber = 0;
16  denm2app = new QUdpSocket(this);
17  denm2app->bind();
18  network->addPort("DENMReceptionManagement", denm2app->localPort());
19  quint16 port = network->denmDestinationPort(), portInfo = network->denmDestinationPortInfo();
20  appPort = network->internalPort("Application");
21 
22 
23  m_internalSocket = new QUdpSocket(this);
24  m_internalSocket->bind();
25  network->addBTPPort(port, portInfo, m_internalSocket->localPort());
26  qDebug() << network->internalBTPPort(port, portInfo);
27  QObject::connect(m_internalSocket, SIGNAL(readyRead()), this, SLOT(readDatagram()));
28 }
29 
31 {
32  denm2app->close();
33  m_internalSocket->close();
34 }
35 
37 {
38  printf("UtInitialize reception %d\n", m_receivedDENM.count());
39  QMutexLocker locker(m_mutexReception);
41  m_receivedDENM.clear();
42  m_sequenceNumber = 0;
43 }
44 
46 {
47  for(int i = 0 ; i < m_receivedDENM.size() ; i++)
48  {
49  m_receivedDENM[i]->m_reception->setTimer(-1);
50  }
51 }
53 {
54  m_sequenceNumber = sequenceNumber;
55 }
56 
57 //void denReceptionManagement::execute(){}
58 
60 {
61  QNetworkDatagram data;
62 
63  while(m_internalSocket->hasPendingDatagrams())
64  {
65  qDebug() << "Receiving DENM";
66  data = m_internalSocket->receiveDatagram();
67 
68  decodeDenm(data.data());
69  }
70 
71 }
72 
74 {
75  DENM_t *d = 0;
76  asn_dec_rval_t rval;
77 
78  rval = uper_decode_complete(NULL, &asn_DEF_DENM, (void**)&d, data.data(), data.length());
79 
80  if(rval.code == RC_OK)
81  {
82  if(d->header.protocolVersion != protocolVersion_currentVersion)
83  {
84  fprintf(stderr, "DENM received has wrong protocol version: %ld instead of %d\n", d->header.protocolVersion, protocolVersion_currentVersion);
85  return;
86  }
87 
88  if(d->header.messageID != messageID_denm)
89  {
90  fprintf(stderr, "DENM received has wrong message ID: %ld instead of %d\n", d->header.messageID, messageID_denm);
91  return;
92  }
93 
94  printf("DENM decoded :\n");
95  asn_fprint(stdout, &asn_DEF_DENM, d);
96 
97  denmReception(d);
98 
99  qDebug() << "New received DENM added size" << m_receivedDENM.size();
100 
101  }
102 }
103 
105 {
106  /* 1) Calculate expiration time for timer T_R_Validity */
107  quint64 receivedDetectionTime;
108  quint64 expiration;
109  quint32 validity = denm->denm.management.validityDuration ? *denm->denm.management.validityDuration : DefaultValidity;
110  asn_INTEGER2ulong((INTEGER_t*)&denm->denm.management.detectionTime, (long unsigned int*)&receivedDetectionTime);
111  expiration = receivedDetectionTime + validity * 1000;
112  QMutexLocker locker(m_mutexReception);
113 
114  /* 1) a. If the expiration time is in the past, discard the received DENM and omit execution of further steps. */
115  if(expiration < m_paramGPS->timestamp())
116  {
117  qDebug() << "Received DENM is expired expiration =" << expiration << "now = " << m_paramGPS->timestamp()
118  << "diff =" << (qint64)(expiration - m_paramGPS->timestamp()) << "received =" << receivedDetectionTime
119  << "validity =" << validity;
120  int found = haveDENM(denm->denm.management.actionID, m_receivedDENM);
121  if(found >= 0)
122  discardDENM(found);
123  return;
124  }
125 
126  /* 1) b. Otherwise, continue the operation. */
127 
128  /* 2) Lookup entries in the receiving ITS-S message table with the received actionID. */
129  ActionID_t actionID = denm->denm.management.actionID;
130  int found = haveDENM(actionID, m_receivedDENM);
131 
132  if(found < 0)
133  {
134  /* 2) a. If entry does not exist in the receiving ITS-S message table, check if termination data exists in the
135  * received DENM: */
136  if(denm->denm.management.termination)
137  {
138  /* 2) a. i. If yes, discard the received DENM and omit execution of further steps. */
139  qDebug() << "Received DENM is a terminated DENM of an unknown DENM";
140  return;
141  }
142  /* 2) a. ii. Otherwise, check SSP and CauseCode if available: */
143  /* TODO: Check SSP consistancy. */
144  /* 2) a. ii. 2. Otherwise create an entry in the receiving ITS-S message table with the received DENM and
145  * set the state to ACTIVE. */
147 
148  entry->setActionID(actionID);
149  entry->setDENM(*denm);
150  entry->m_reception = new denMessageTableReceptionThread(expiration);
151 
152  entry->setT_R_Validity(-1);
153  entry->moveToThread(entry->m_thread);
154  entry->m_thread->start();
155  qDebug() << "145 thread start";
156  m_receivedDENM.append(entry);
157 
158  found = haveDENM(actionID, m_receivedDENM);
159  qDebug() << "New received DENM added size" << m_receivedDENM.size();
160  }
161  else
162  {
163  /* 2) b. If entry does exist, in the receiving ITS-S message table, check if the received referenceTime is less than
164  * the entry referenceTime, or the received detectionTime is less than the entry detectionTime. */
165  quint64 receivedReferenceTime, tableDetectionTime, tableReferenceTime;
166  DENM_t tableDenm = m_receivedDENM.at(found)->denm();
167  asn_INTEGER2ulong((INTEGER_t*)&denm->denm.management.referenceTime, (long unsigned int*)&receivedReferenceTime);
168  asn_INTEGER2ulong((INTEGER_t*)&tableDenm.denm.management.detectionTime, (long unsigned int*)&tableDetectionTime);
169  asn_INTEGER2ulong((INTEGER_t*)&tableDenm.denm.management.referenceTime, (long unsigned int*)&tableReferenceTime);
170  if(receivedReferenceTime < tableReferenceTime || receivedDetectionTime < tableDetectionTime)
171  {
172  /* 2) b. i. If yes, discard the received DENM and omit execution of further steps. */
173  qDebug() << "Received DENM has wrong detectionTime or referenceTime:\n"
174  << "Received DT =" << receivedDetectionTime << "Table DT =" << tableDetectionTime << "diff =" <<
175  (qint64)(receivedDetectionTime - tableDetectionTime) << "\n"
176  << "Received RT =" << receivedReferenceTime << "Table RT =" << tableReferenceTime << "diff =" <<
177  (qint64)(receivedReferenceTime - tableReferenceTime);
178  return;
179  }
180  /* 2) b. ii. Otherwise, check if the received DENM is a repeated DENM of the entry, i.e. the received
181  * referenceTime equals to the entry referenceTime, the received detectionTime equals to the entry
182  * detectionTime, and the received termination value equals to the entry state. */
183  if(receivedReferenceTime == tableReferenceTime &&
184  receivedDetectionTime == tableDetectionTime)
185  {
186  if((!denm->denm.management.termination && !tableDenm.denm.management.termination) ||
187  (denm->denm.management.termination && tableDenm.denm.management.termination))
188  {
189  if(denm->denm.management.termination && (*denm->denm.management.termination == *tableDenm.denm.management.termination))
190  {
191  /* 2) b. ii. 1. If yes, discard the received DENM and omit exection of further steps. */
192  qDebug() << "Received DENM is a repeated DENM";
193  return;
194  }
195  }
196  }
197  /* 2) b. ii. 2. Otherwise, check SSP and CauseCode if available. */
198  /* TODO: Check SSP consistency. */
199  /* 2) b. ii. 2. b. Otherwise, update the entry in receiving ITS-S message table, set entry state according
200  * to the termination value of the received DENM. */
201  m_receivedDENM[found]->setDENM(*denm);
202  }
203 
204  /* 3) Start/restart T_R_Validity timer. */
205  qDebug() << "Start/Restart T_R_Validity";
206  m_receivedDENM[found]->setT_R_Validity(expiration - m_paramGPS->timestamp());
207  m_receivedDENM[found]->m_reception->m_T_R_Validity_timer.start();
208 
209  /* 4) Inform ITS-S applications of the DENM entry and state if applicable. */
210  QByteArray resUt;
211  QDataStream ds(&resUt, QIODevice::WriteOnly);
212  char msg[MSG_LENGTH];
214  ds << (quint8)0x17 << (quint16)((erval.encoded + 7) >> 3);
215  ds.writeRawData(QByteArray(msg, (erval.encoded + 7) >> 3), (erval.encoded + 7) >> 3);
216 
217  denm2app->writeDatagram(resUt, QHostAddress::LocalHost, appPort);
218  qDebug() << resUt.toHex() << "sent to" << QHostAddress::LocalHost << appPort;
219 
220  if(denm->denm.situation)
221  {
222  if(denm->denm.alacarte)
223  {
224  if(denm->denm.alacarte->impactReduction)
225  {
227  {
229  }
230  }
231  }
232  }
233  /* 5) End. */
234 
235  emit kaf(denm);
236 }
237 
239 {
240  DENM_t denm;
241  asn_enc_rval_t rval;
242  char msg[MSG_LENGTH] = {'\0'};
245  quint64 expirationTime;
246 
247  memset(&denm, 0, sizeof denm);
248 
250  denm.denm.management = fill_ManagementContainer(originatingActionID, &m_paramGPS->data(), &m_paramAppli->data());
251  denm.denm.situation = (SituationContainer_t*)calloc(1, sizeof *denm.denm.situation);
252  denm.denm.situation = s;
253  denm.denm.location = (LocationContainer_t*)calloc(1, sizeof *denm.denm.location);
254  denm.denm.location->traces.list.array = (PathHistory_t**)calloc(1, sizeof *denm.denm.location->traces.list.array);
255  PathHistory_t *p = (PathHistory_t*)calloc(1, sizeof *p);
256  denm.denm.location->traces.list.array[0] = (PathHistory_t*)calloc(1, sizeof *denm.denm.location->traces.list.array[0]);
258  denm.denm.alacarte = (AlacarteContainer_t*)calloc(1, sizeof *denm.denm.alacarte);
261  asn_fprint(NULL, &asn_DEF_DENM, &denm);
262 
263  rval = uper_encode_to_buffer(&asn_DEF_DENM, &denm, msg, MSG_LENGTH);
264  if(rval.encoded < 1)
265  {
266  qDebug() << "Unable to encode" << rval.failed_type->name;
267  return;
268  }
269 
270  if(!PassDenmToNetworkAndTransportLayerTrigger(data, msg, (rval.encoded + 7) / 8))
271  {
272  qDebug() << "Unable to pass DENM to N&T";
273  return;
274  }
275 
276  /* 8) Create an entry in the originating ITS-S message table and set the state to ACTIVE. */
277  asn_INTEGER2ulong((INTEGER_t*)&denm.denm.management.detectionTime, (long unsigned int*)&expirationTime);
278  expirationTime += DefaultValidity * 1000;
279  entry->setDENM(denm);
280  entry->setTrafficClass(data.trafficClass().toInt());
281  entry->setActionID(denm.denm.management.actionID);
282 
283  /* 9) Start/restart timer T_O_Validity. */
284  entry->setT_O_Validity(expirationTime - m_paramGPS->timestamp());
285 
287 }
288 
290 {
291  QMutexLocker locker(m_mutexReception);
292  int found = haveDENM(actionID, m_receivedDENM);
293 
294  if(found < 0)
295  {
296  qDebug() << actionID.originatingStationID << ":" << actionID.sequenceNumber << "not found in the received table size"
297  << m_receivedDENM.size();
299  return;
300  }
301 
302  DENM_t denm = m_receivedDENM.at(found)->denm();
303  DENM_t denmToSend;
304 
305  m_receivedDENM.removeAt(found);
306 
307  memset(&denmToSend, 0, sizeof denmToSend);
309  denmToSend.denm.management = denm.denm.management;
310 
313 
314  char msg[MSG_LENGTH] = {'\0'};
315  asn_enc_rval_t rval;
316 
317  asn_fprint(NULL, &asn_DEF_DENM, &denmToSend);
318  rval = uper_encode_to_buffer(&asn_DEF_DENM, &denmToSend, msg, MSG_LENGTH);
319  if(rval.encoded < 1)
320  {
321  qDebug() << "Unable to encode" << rval.failed_type->name;
323  }
324 
325  print_hexa((unsigned char*)msg, (rval.encoded + 7) / 8);
326  AppDenmTriggerData data(denm, termination.destinationArea());
327 
328  if(!PassDenmToNetworkAndTransportLayerTrigger(data, msg, (rval.encoded + 7) / 8))
329  {
330  qDebug() << "Unable to pass DENM to N&T";
331  return AppDENM_result(actionID, false, AppDenmResultData::cannotSendDENM, &denm);
332  }
333 
334  AppDenmTerminationIndication terminationIndication(actionID);
335 
336  denm2app->writeDatagram(terminationIndication.toBin(), QHostAddress::LocalHost, appPort);
337  return AppDENM_result(actionID, true, AppDenmResultData::success, &denm);
338 }
339 
341 {
343 
344  dr.payload = QByteArray(msg, denmLength);
345 
346  int foo;
347  if((foo = m_geonet->send(dr)) != GeoNet::geonetError_success)
348  {
349  qDebug() << "error " << foo;
350  return false;
351  }
352  return true;
353 }
354 
356 {
357  QByteArray msg;
358  AppDenmResultData result(actionID, success, failureNotification, denm, m_paramDENM);
359  msg = result.toBin();
360 
361  emit appDenmResult(msg);
362 }
363 
365 {
366  AppDenmTerminationIndication termination(m_receivedDENM.at(index)->actionID());
367 
368  if(m_receivedDENM[index]->m_reception)
369  {
370  m_receivedDENM[index]->m_reception->setTimer(-1);
371  }
372  m_receivedDENM.removeAt(index);
373 
374  denm2app->writeDatagram(termination.toBin(), QHostAddress::LocalHost, appPort);
375 }
376 
378 {
379  QMutexLocker locker(m_mutexReception);
380  int found = haveDENM(actionID, m_receivedDENM);
381 
382  if(found < 0)
383  {
384  qDebug() << "DENM" << actionID.originatingStationID << ":" << actionID.sequenceNumber <<
385  "not found in the received message table";
386  return;
387  }
388  discardDENM(found);
389 }
#define ASN_SEQUENCE_ADD(headptr, ptr)
denMessageTableReceptionThread * m_reception
gnDataRequest_t structure is the GN data request definition.
Definition: GNDataRequest.h:46
void setSequenceNumberSlot(quint16)
setSequenceNumberSlot Slot used when a new sequenceNumber is made.
TrafficClassData trafficClass() const
trafficClass Traffic class getter.
struct asn_TYPE_descriptor_s * failed_type
Definition: asn_codecs.h:55
DecentralizedEnvironmentalNotificationMessage_t denm
Definition: DENM.h:25
void discardDENM(int index)
discardDENM Discard DENM from DEN Message Table Reception.
#define MSG_LENGTH
void AppDENM_negation(AppDenmTerminationData termination, ActionID_t actionID)
AppDENM_negation Negation of a DENM.
bool fill_AlacarteContainer(AppDenmTriggerData data, AlacarteContainer_t *alacarte)
fill_AlacarteContainer Fills the AlacarteContainer.
void utInitialize()
utInitialize Slot used to initialize the DEN Reception Management.
StationID_t originatingStationID
Definition: ActionID.h:24
ItsPduHeader_t header
Definition: DENM.h:24
Termination_t * termination
asn_dec_rval_t uper_decode_complete(struct asn_codec_ctx_s *opt_codec_ctx, struct asn_TYPE_descriptor_s *type_descriptor, void **struct_ptr, const void *buffer, size_t size)
Definition: per_decoder.c:11
void print_hexa(const unsigned char *msg, int l, FILE *stream=stdout)
print_hexa Print a byte array.
Definition: api.cpp:89
struct ImpactReductionContainer * impactReduction
gnDataRequest_t gnDataRequestFromAppDenmTriggerData(AppDenmTriggerData data, ParameterGPS gps)
gnDataRequestFromAppDenmTriggerData Generate a GN Data Request from an AppDenmTriggerData.
void setActionID(ActionID_t a)
setActionID DENM&#39;s ActionID setter.
quint64 timestamp()
timestamp Timestamp getter.
SequenceNumber_t sequenceNumber
Definition: ActionID.h:25
FakeApplicationProvider * m_paramAppli
ParameterConfiguration * m_paramConf
ssize_t encoded
Definition: asn_codecs.h:48
QByteArray toBin()
toBin Encode an AppDenmTerminationIndication into a byte array.
ParameterCAN & data()
data CAN bus data getter.
int asn_long2INTEGER(INTEGER_t *i, long l)
Definition: INTEGER.c:882
void setT_R_Validity(qint64 t)
setT_R_Validity Set the T_R_Validity.
quint8 toInt()
toInt TrafficClassData encoder in a byte.
void setDENM(DENM_t d)
setDENM Set the DENM
TimestampIts_t referenceTime
void addBTPPort(quint16 port, quint16 portInfo, quint16 internal)
addBTPPort Add BTP port to the internal BTP ports.
QByteArray toBin()
toBin Encode the AppDenmResultData into a byte array.
DestinationAreaData destinationArea() const
destinationArea Destination area getter.
ValidityDuration_t * validityDuration
DEN Reception Management.
int asn_INTEGER2ulong(const INTEGER_t *i, unsigned long *l)
Definition: INTEGER.c:825
quint16 internalPort(QString service)
internalPort Get the internal BTP port from service name.
void setT_O_Validity(qint64 t)
setT_O_Validity T_O_Validity setter.
ParameterGPS & data()
data GPS data getter.
denReceptionManagement(FakeGPSProvider *gps, FakeApplicationProvider *appli, ParameterDENM *denm, GeoNet *gn, ParameterConfiguration *conf, FakeCANProvider *can, ParameterNetwork *network)
denReceptionManagement denReceptionManagement constructor.
bool fill_ManagementContainer(AppDenmTriggerData data, ManagementContainer_t *management, ParameterApplication *appli, ParameterGPS gps)
fill_ManagementContainer Fills the ManagementContainer.
void addPort(QString service, quint16 port)
addPort Add BTP port to the internal BTP ports from service name.
TimestampIts_t detectionTime
#define DefaultValidity
quint16 internalBTPPort(quint16 port, quint16 portInfo)
internalBTPPort Get the internal BTP port.
enum AppDenmResultData::failureNotification_enum e_failureNotification
The e_failureNotification enum defines the success or failure code.
void discardDENMFromReceivedTable(ActionID_t)
discardDENMFromReceivedTable Slot used when a DENM is discarded from Received Table.
void setActionID(ActionID_t a)
setActionID Set the DENM&#39;s ActionID.
enum asn_dec_rval_code_e code
Definition: asn_codecs.h:88
asn_enc_rval_t uper_encode_to_buffer(struct asn_TYPE_descriptor_s *type_descriptor, void *struct_ptr, void *buffer, size_t buffer_size)
Definition: per_encoder.c:33
int asn_fprint(FILE *stream, asn_TYPE_descriptor_t *td, const void *struct_ptr)
Definition: constr_TYPE.c:36
void killReceptionThreads()
killReceptionThreads Kills active threads.
RequestResponseIndication_t requestResponseIndication
StationID_t stationID() const
stationID Station ID getter.
Definition: DENM.h:23
ParameterApplication & data()
data Returns the vehicle status.
void setSequenceNumberSignal(quint16)
setSequenceNumberSignal Signal used when a new sequenceNumber is set.
void kaf(DENM_t *)
kaf Signal used to invoke KAF.
bool PassDenmToNetworkAndTransportLayerTrigger(AppDenmTriggerData data, char *msg, int denmLength)
PassDenmToNetworkAndTransportLayerTrigger Pass the response DENM to the N&T layer.
void denmReception(DENM_t *)
denmReception Reception of a DENM.
void decodeDenm(QByteArray data)
decodeDenm Decode DENM.
int send(gnDataRequest_t gnDR)
send Creates the BTP and then select the correct packet send option.
Definition: Geonet.cpp:497
asn_TYPE_descriptor_t asn_DEF_DENM
Definition: DENM.c:45
void AppDENM_result(ActionID_t actionID, bool success, AppDenmResultData::e_failureNotification failureNotification, DENM_t *denm)
AppDENM_result Notification to the Application layer of the success of DENM sent. ...
quint16 denmDestinationPortInfo() const
denmDestinationPortInfo DENM destination port info getter.
ItsPduHeader_t fill_ItsPduHeader(StationID_t stationID)
fill_ItsPduHeader Fills the ItsPduHeader.
QByteArray payload
Definition: GNDataRequest.h:60
quint16 denmDestinationPort() const
denmDestinationPort DENM destination port getter.
void readDatagram()
readDatagram Slot used to receive DENM.
Definition: Geonet.h:42
void setDENM(DENM_t d)
setDENM DENM setter.
QVector< denMessageTableReception * > m_receivedDENM
void sendRequestResponseIndication_Response(SituationContainer_t *s, ActionID_t originatingActionID)
sendRequestResponseIndication_Response Sends a RequestResponIndication DENM of type Response when a D...
int haveDENM(ActionID_t actionID, QVector< denMessageTableSource *> table)
haveDENM Check if the DENM exists in the denMessageTableSource
void setTrafficClass(quint8 t)
setTrafficClass DENM&#39;s traffic class setter.
void appDenmResult(QByteArray)
appDenmResult Signal used when notification is made to the Application layer.