NetSim Source Code Help v14.4
All 13 Components
 
Loading...
Searching...
No Matches
CoAP.c
1/************************************************************************************
2* Copyright (C) 2023 *
3* TETCOS, Bangalore. India *
4* *
5* Tetcos owns the intellectual property rights in the Product and its content. *
6* The copying, redistribution, reselling or publication of any or all of the *
7* Product or its content without express prior written consent of Tetcos is *
8* prohibited. Ownership and / or any other right relating to the software and all *
9* intellectual property rights therein shall remain at all times with Tetcos. *
10* *
11* Author: Siddharth Makadia *
12* *
13* ---------------------------------------------------------------------------------*/
14
15#include "Application.h"
16#include "CoAP.h"
17#include "main.h"
18#include "Stack.h"
19
20#define COAP_REQUEST_SIZE 12
21#define COAP_ACK_SIZE 8
22
23#define COAP_ACT_REQUIRED_DEFAULT TRUE
24#define COAP_MULTICAST_RESPONSE_DEFAULT TRUE
25#define COAP_VARIABLE_RESPONSE_TIME_DEFAULT 5
26#define COAP_PIGGYBACKED_TIME_DEFAULT 2000
27#define COAP_ACK_RESPONSE_TIME_DEFAULT 1000
28
29#define COAP_ACK_TIMEOUT_DEFAULT 2000 //in milliseconds
30#define COAP_ACK_RANDOM_FACTOR_DEFAULT 1.5
31#define COAP_MAX_RETRANSMIT_DEFAULT 4
32#define COAP_NSTART_DEFAULT 1
33#define COAP_DEFAULT_LEISURE_DEFAULT 5 //in seconds
34#define COAP_PROBING_RATE_DEFAULT 1 //in byte/second
35
36
37int fn_NetSim_Application_ConfigureCOAPTraffic(ptrAPPLICATION_INFO appInfo, void* xmlNetSimNode)
38{
39 char* szVal;
40 APP_COAP_INFO* info = calloc(1, sizeof * info);
41 void* xmlChild;
42 appInfo->appData = info;
43 xmlChild = fn_NetSim_xmlGetChildElement(xmlNetSimNode, "COAP_REQUEST_INTERARRIVAL_TIME", 0);
44 if (xmlChild)
45 {
46 szVal = fn_NetSim_xmlConfig_GetVal(xmlChild, "DISTRIBUTION", 1);
47 if (szVal)
48 info->pageIATDistribution = fn_NetSim_Config_GetDistribution(szVal);
49 free(szVal);
50 szVal = fn_NetSim_xmlConfig_GetVal(xmlChild, "VALUE", 1);
51 if (szVal)
52 info->pageIAT = atof(szVal) * SECOND;
53 free(szVal);
54 }
55 else
56 return 0;
57 xmlChild = fn_NetSim_xmlGetChildElement(xmlNetSimNode, "PAGE_PROPERTY", 0);
58 if (xmlChild)
59 {
60 szVal = fn_NetSim_xmlConfig_GetVal(xmlChild, "PAGE_SIZE", 1);
61 if (szVal)
62 info->pageSize = atof(szVal);
63 free(szVal);
64 szVal = fn_NetSim_xmlConfig_GetVal(xmlChild, "PAGE_SIZE_DISTRIBUTION", 1);
65 if (szVal)
66 info->pageSizeDistribution = fn_NetSim_Config_GetDistribution(szVal);
67 free(szVal);
68 }
69
70 xmlChild = fn_NetSim_xmlGetChildElement(xmlNetSimNode, "COAP_PROPERTY", 0);
71
72
73 if (xmlChild) {
74 getXmlVar(&info->ackRequired, ACT_REQUIRED, xmlChild, 1, _BOOL, COAP);
75 getXmlVar(&info->multicastResponse, MULTICAST_RESPONSE, xmlChild, 1, _BOOL, COAP);
76 getXmlVar(&info->variableResponseTime, VARIABLE_RESPONSE_TIME, xmlChild, 1, _INT, COAP);
77 getXmlVar(&info->piggybackedTime, PIGGYBACKED_TIME, xmlChild, 0, _INT, COAP);
78 getXmlVar(&info->ackResponseTime, ACK_RESPONSE_TIME, xmlChild, 0, _INT, COAP);
79 getXmlVar(&info->ackTimeOut, ACK_TIMEOUT, xmlChild, 0, _INT, COAP);
80 getXmlVar(&info->ackRandomFactor, ACK_RANDOM_FACTOR, xmlChild, 0, _DOUBLE, COAP);
81 getXmlVar(&info->maxRetransmit, MAX_RETRANSMIT, xmlChild, 0, _INT, COAP);
82 getXmlVar(&info->nstart, NSTART, xmlChild, 1, _INT, COAP);
83 getXmlVar(&info->defaultLeisure, DEFAULT_LEISURE, xmlChild, 1, _INT, COAP);
84 getXmlVar(&info->probingRate, PROBING_RATE, xmlChild, 1, _INT, COAP);
85
86 COAP_Data* pCOAPData = calloc(1, sizeof * pCOAPData);
87 info->pCOAPData = pCOAPData;
88
89 info->pCOAPData->Response_Received = 0;
90 info->pCOAPData->RequestACK_Received = 0;
91 info->pCOAPData->Request_Received = 0;
92 info->pCOAPData->ResponseACK_Received = 0;
93
94 info->pCOAPData->_RETRANSMIT = 0;
95 }
96 return 1;
97}
98
99void fn_NetSim_Application_COAP_AppIn(ptrAPPLICATION_INFO pstruappinfo, NetSim_PACKET* pstruPacket) {
100
101 COAP_Header* pCOAPHeader = pstruPacket->pstruAppData->Packet_AppProtocol;
102 APP_COAP_INFO* info = pstruappinfo->appData;
103 COAP_Data* pCOAPData = info->pCOAPData;
104
105 //check for request Duplicate detection
106 if (pCOAPHeader->Code == REQUEST && pCOAPHeader->Type != ACKNOWLEDGEMENT) {
107 if (pCOAPData->Request_messageID == pCOAPHeader->MessageID && pCOAPData->Request_tokenValue == pCOAPHeader->tokenvalue) {
108 return;
109 }
110 else {
111 pCOAPData->Request_messageID = pCOAPHeader->MessageID;
112 pCOAPData->Request_tokenValue = pCOAPHeader->tokenvalue;
113 }
114 }
115 //check for response Duplicate detection
116 if (pCOAPHeader->Code == RESPONSE) {
117 if (pCOAPData->Response_messageID == pCOAPHeader->MessageID && pCOAPData->Response_tokenValue == pCOAPHeader->tokenvalue) {
118 return;
119 }
120 else {
121 pCOAPData->Response_messageID = pCOAPHeader->MessageID;
122 pCOAPData->Response_tokenValue = pCOAPHeader->tokenvalue;
123 }
124 }
125
126 //check of request
127 if (pCOAPHeader->Code == REQUEST) {
128
129 //check for ack and piggybacked condition
130 if (pCOAPHeader->Type == CONFIRMABLE && info->variableResponseTime > info->piggybackedTime) {
131
132 fn_NetSim_Application_COAP_Sent_ACK(pstruappinfo, pstruPacket);
133
134 }
135 //send response
136 if (pCOAPHeader->Type != ACKNOWLEDGEMENT) {
137
138 fn_NetSim_Application_COAP_ProcessRequest(pstruappinfo, pstruPacket);
139
140 }
141 }
142 //check for Response
143 if (pCOAPHeader->Code == RESPONSE) {
144 //check for Response and send ACK
145 if ((pCOAPHeader->Type == CONFIRMABLE || pCOAPHeader->Type == ACKNOWLEDGEMENT) && pCOAPHeader->Code == RESPONSE) {
146 fn_NetSim_Application_COAP_Sent_ACK(pstruappinfo, pstruPacket);
147 pstruEventDetails->dEventTime = pstruEventDetails->dEventTime - info->ackResponseTime * MILLISECOND;
148 }
149 //Start the next timer event to sent the request packet again after receiving the response and ACK
150 fn_NetSim_Application_COAP_Start(pstruappinfo, pstruEventDetails);
151
152 }
153
154
155 //check for Ack Packet
156 if (pCOAPHeader->Type == ACKNOWLEDGEMENT) {
157 if (!strcmp(pstruEventDetails->pPacket->szPacketType, "COAP_REQUEST") || !strcmp(pstruEventDetails->pPacket->szPacketType, "COAP_REQUEST_ACK"))
158 info->pCOAPData->Response_Received = 1;
159
160 }
161
162
163}
164
165int fn_NetSim_Application_COAP_Start(ptrAPPLICATION_INFO appInfo, NetSim_EVENTDETAILS* pstruEventDetails) {
166 fn_NetSim_Application_StartCOAPAPP(appInfo, pstruEventDetails->dEventTime);
167 return 1;
168}
169
170int fn_NetSim_Application_StartCOAPAPP(ptrAPPLICATION_INFO appInfo, double time) {
171
172 if (appInfo->dEndTime <= time)
173 return 0;
174
175 fnCreatePort(appInfo);
176
177 NETSIM_ID nSource = appInfo->sourceList[0];
178 NETSIM_ID nDestination = appInfo->destList[0];
179
180 //Create the socket buffer
181 fnCreateSocketBuffer(appInfo);
182 APP_COAP_INFO* info = appInfo->appData;
183
184 if (appInfo->nTransmissionType == MULTICAST)
185 {
186 fnNetSimError("In NETSIM, COAP application can't be configured as multicast.\n"
187 "Stopping application...\n");
188 return -1;
189 }
190
191 //Generate the app start event
192 fn_NetSim_Application_COAP_Genrate_RequestPacket(appInfo, nSource, nDestination, time, "COAP_REQUEST");
193
194 // Setting COAP application header
195 COAP_Header* pCOAPHeader = fn_NetSim_Application_COAP_GenrateHeader(info);
196
197 pstruEventDetails->pPacket->pstruAppData->nApplicationProtocol = PROTOCOL_APPLICATION;
198 pstruEventDetails->pPacket->pstruAppData->Packet_AppProtocol = pCOAPHeader;
199 fnpAddEvent(pstruEventDetails);
200
201
202 //fnpAddEvent(pstruEventDetails);
203
204 // Create a new Event for Stop and Wait method
205
206
207 return 0;
208}
209
210int fn_NetSim_Application_COAP_ProcessRequest(ptrAPPLICATION_INFO pstruappinfo, NetSim_PACKET* pstruPacket)
211{
212 NETSIM_ID nSourceId = get_first_dest_from_packet(pstruPacket);
213 NETSIM_ID nDestinationId = pstruPacket->nSourceId;
214 APP_COAP_INFO* info = pstruappinfo->appData;
215 if (info->multicastResponse == FALSE && pstruappinfo->nTransmissionType == MULTICAST)
216 {
217 return 0;
218 }
219
220 COAP_Header* pCOAPHeader = pstruEventDetails->pPacket->pstruAppData->Packet_AppProtocol;
221
222 //int ackreqired = pCOAPHeader->Type;
223
224
225 fn_NetSim_Application_COAP_Genrate_Packet(pstruappinfo, nSourceId, nDestinationId, 0.0, "COAP_RESPONSE");
226 int messageID = pCOAPHeader->MessageID;
227 int tokenValue = pCOAPHeader->tokenvalue;
228
229 //genrate and modify COAP header
230 COAP_Header* pCOAPHeaderNew = fn_NetSim_Application_COAP_GenrateHeader(info);
231 //Piggybacked condition check
232 if (info->variableResponseTime < info->piggybackedTime && pCOAPHeaderNew->Type == CONFIRMABLE) {
233 pCOAPHeaderNew->Type = ACKNOWLEDGEMENT;
234 pCOAPHeaderNew->Code = RESPONSE;
235 pCOAPHeaderNew->MessageID = messageID;
236 pCOAPHeaderNew->tokenvalue = tokenValue;
237 }
238 else
239 {
240 //pCOAPHeaderNew->Type = CONFIRMABLE;
241 pCOAPHeaderNew->Code = RESPONSE;
242 pCOAPHeaderNew->MessageID = rand() % 65535;
243 pCOAPHeaderNew->tokenvalue = tokenValue;
244 }
245
246 pstruEventDetails->pPacket->pstruAppData->nApplicationProtocol = PROTOCOL_APPLICATION;
247 pstruEventDetails->pPacket->pstruAppData->Packet_AppProtocol = pCOAPHeaderNew;
248 fnpAddEvent(pstruEventDetails);
249
250 return 1;
251}
252
253
254int fn_NetSim_Application_COAP_Sent_ACK(ptrAPPLICATION_INFO pstruappinfo, NetSim_PACKET* pstruPacket) {
255
256 NETSIM_ID nSourceId = get_first_dest_from_packet(pstruPacket);
257 NETSIM_ID nDestinationId = pstruPacket->nSourceId;
258 APP_COAP_INFO* info = pstruappinfo->appData;
259
260 COAP_Header* pCOAPHeader = pstruEventDetails->pPacket->pstruAppData->Packet_AppProtocol;
261 int messageID = pCOAPHeader->MessageID;
262 //generate and modify COAP header
263 COAP_Header* pCOAPHeaderNew = fn_NetSim_Application_COAP_GenrateHeader(info);
264 if (pCOAPHeader->Code == REQUEST) {
265 fn_NetSim_Application_COAP_Genrate_Packet(pstruappinfo, nSourceId, nDestinationId, 0.0, "COAP_REQUEST_ACK");
266 }
267 else {
268 fn_NetSim_Application_COAP_Genrate_Packet(pstruappinfo, nSourceId, nDestinationId, 0.0, "COAP_RESPONSE_ACK");
269 }
270
271 pCOAPHeaderNew->Type = ACKNOWLEDGEMENT;
272 pCOAPHeaderNew->Code = REQUEST;
273 pCOAPHeaderNew->MessageID = messageID;
274 pCOAPHeaderNew->tokenvalue = 0;
275
276 pstruEventDetails->pPacket->pstruAppData->nApplicationProtocol = PROTOCOL_APPLICATION;
277 pstruEventDetails->pPacket->pstruAppData->Packet_AppProtocol = pCOAPHeaderNew;
278
279 fnpAddEvent(pstruEventDetails);
280 return 1;
281}
282
283
284int fn_NetSim_Application_COAP_Genrate_RequestPacket(ptrAPPLICATION_INFO appInfo, NETSIM_ID nSource, NETSIM_ID nDestination, double time, char* PacketType) {
285 double arrivalTime;
286 APP_COAP_INFO* info = appInfo->appData;
287
288 do
289 {
290 fnDistribution(info->pageIATDistribution,
291 &arrivalTime,
292 &(NETWORK->ppstruDeviceList[nSource - 1]->ulSeed[0]),
293 &(NETWORK->ppstruDeviceList[nSource - 1]->ulSeed[1]),
294 &(info->pageIAT));
295 } while (arrivalTime <= 0.0);
296
297 pstruEventDetails->dEventTime = time + arrivalTime;
298 pstruEventDetails->dPacketSize = COAP_REQUEST_SIZE;
299 pstruEventDetails->nApplicationId = appInfo->id;
300 pstruEventDetails->nDeviceId = nDestination;
301 pstruEventDetails->nDeviceType = DEVICE_TYPE(nDestination);
302 pstruEventDetails->nEventType = TIMER_EVENT;
303 pstruEventDetails->nInterfaceId = 0;
304 pstruEventDetails->nPacketId = 0;
305 pstruEventDetails->nProtocolId = PROTOCOL_APPLICATION;
306 pstruEventDetails->nSegmentId = 0;
307 pstruEventDetails->nSubEventType = event_APP_START;
308 pstruEventDetails->pPacket = fn_NetSim_Application_GeneratePacket(appInfo,
309 pstruEventDetails->dEventTime,
310 nDestination,
311 1,
312 &nSource,
313 0,
314 appInfo->nAppType,
315 appInfo->qos,
316 appInfo->destPort,
317 appInfo->sourcePort);
318 pstruEventDetails->pPacket->nControlDataType = packet_COAP_REQUEST;
319 pstruEventDetails->pPacket->nPacketType = PacketType_COAP;
320 strcpy(pstruEventDetails->pPacket->szPacketType, PacketType);
321
322 pstruEventDetails->szOtherDetails = appInfo;
323 pstruEventDetails->pPacket->pstruAppData->nPacketFragment = Segment_Unfragment;
324 return 1;
325}
326
327int fn_NetSim_Application_COAP_Genrate_Packet(ptrAPPLICATION_INFO pstruappinfo, NETSIM_ID nSourceId, NETSIM_ID nDestinationId, double size, char* PacketType) {
328
329 APP_COAP_INFO* info = pstruappinfo->appData;
330 //COAP_Header* pCOAPHeader = pstruEventDetails->pPacket->pstruAppData->Packet_AppProtocol;
331 if (!strcmp(PacketType, "COAP_RESPONSE")) {
332 do
333 {
334 fnDistribution(info->pageSizeDistribution, &size,
335 &(NETWORK->ppstruDeviceList[nSourceId - 1]->ulSeed[0]),
336 &(NETWORK->ppstruDeviceList[nSourceId - 1]->ulSeed[1]),
337 &(info->pageSize));
338 } while (size <= 0.0);
339 pstruEventDetails->dEventTime = pstruEventDetails->dEventTime + info->variableResponseTime * MILLISECOND;
340 }
341 else {
342 double ackSize = COAP_ACK_SIZE;
343 do
344 {
345
346 fnDistribution(info->pageSizeDistribution, &size,
347 &(NETWORK->ppstruDeviceList[nSourceId - 1]->ulSeed[0]),
348 &(NETWORK->ppstruDeviceList[nSourceId - 1]->ulSeed[1]),
349 &(ackSize));
350 } while (size <= 0.0);
351 pstruEventDetails->dEventTime = pstruEventDetails->dEventTime + info->ackResponseTime * MILLISECOND;
352 }
353
354 pstruEventDetails->dPacketSize = size;
355 pstruEventDetails->nEventType = APPLICATION_OUT_EVENT;
356 pstruEventDetails->nPacketId = ++pstruappinfo->nPacketId;
357 pstruEventDetails->nProtocolId = PROTOCOL_APPLICATION;
358 pstruEventDetails->nSubEventType = 0;
359 pstruEventDetails->nPacketId = 0;
360 pstruEventDetails->pPacket = fn_NetSim_Application_GeneratePacket(pstruappinfo,
361 pstruEventDetails->dEventTime,
362 nSourceId,
363 1,
364 &nDestinationId,
365 pstruEventDetails->nPacketId,
366 TRAFFIC_COAP,
367 pstruappinfo->qos,
368 pstruappinfo->sourcePort,
369 pstruappinfo->destPort);
370 pstruEventDetails->szOtherDetails = pstruappinfo;
371 pstruEventDetails->pPacket->nControlDataType = packet_COAP_REQUEST;
372 pstruEventDetails->pPacket->nPacketType = PacketType_COAP;
373 strcpy(pstruEventDetails->pPacket->szPacketType, PacketType);
374 pstruEventDetails->pPacket->pstruAppData->nAppEndFlag = 1;
375 pstruEventDetails->pPacket->pstruAppData->nPacketFragment = Segment_Unfragment;
376 return 1;
377}
378
379COAP_Header* fn_NetSim_Application_COAP_CopyHeader(COAP_Header* src) {
380
381 COAP_Header* pCOAPHeader = calloc(1, sizeof * pCOAPHeader);
382 pCOAPHeader->Version = 1;
383 pCOAPHeader->Type = src->Type;
384 pCOAPHeader->TokenLength = src->TokenLength;
385 pCOAPHeader->Code = src->Code;
386 pCOAPHeader->MessageID = src->MessageID;
387 pCOAPHeader->tokenvalue = src->tokenvalue;
388
389 COAP_Options* pCOAPOptions;
390 pCOAPOptions = calloc(1, sizeof * pCOAPOptions);
391 pCOAPOptions->optionDelta = src->Options->optionDelta;
392 pCOAPOptions->optionLength = src->Options->optionLength;
393 pCOAPOptions->optionvalue = src->Options->optionvalue;
394 pCOAPHeader->Options = pCOAPOptions;
395 return pCOAPHeader;
396}
397
398COAP_Header* fn_NetSim_Application_COAP_GenrateHeader(APP_COAP_INFO* info) {
399 COAP_Header* pCOAPHeader = calloc(1, sizeof * pCOAPHeader);
400
401 pCOAPHeader->Version = 1;
402 pCOAPHeader->Type = (info->ackRequired == TRUE) ? CONFIRMABLE : NON_CONFIRMABLE;
403 pCOAPHeader->TokenLength = 2;
404 pCOAPHeader->Code = REQUEST;
405 pCOAPHeader->MessageID = rand() % 65535;
406 pCOAPHeader->tokenvalue = rand() % 4294967296;
407
408 COAP_Options* pCOAPOptions;
409 pCOAPOptions = calloc(1, sizeof * pCOAPOptions);
410 pCOAPOptions->optionDelta = 0;
411 pCOAPOptions->optionLength = 0;
412
413 // if required set nCOAPOptions->optionvalue
414
415 pCOAPHeader->Options = pCOAPOptions;
416
417 return pCOAPHeader;
418}