Imported Upstream version 1.0.0
[platform/upstream/iotivity.git] / resource / csdk / routing / src / routingmessageparser.c
1 /* ****************************************************************
2  *
3  * Copyright 2015 Samsung Electronics All Rights Reserved.
4  *
5  *
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  ******************************************************************/
20
21 #include <stdio.h>
22 #include <string.h>
23 #include "routingmessageparser.h"
24 #include "routingtablemanager.h"
25 #include "routingutility.h"
26 #include "ocpayload.h"
27 #include "ocpayloadcbor.h"
28 #include "oic_malloc.h"
29 #include "oic_string.h"
30 #include "include/logger.h"
31
32 /**
33  * Logging tag for module name.
34  */
35 #define TAG "RPM"
36
37 /**
38  * Table key to parser Payload Table.
39  */
40 static const char TABLE[] = "table";
41
42 /**
43  * Length key to get length Payload Array.
44  */
45 static const char LENGTH_PROP[] = "len";
46
47 /**
48  * Gateway key to parser Payload Table.
49  */
50 static const char GATEWAY[] = "gateway";
51
52 /**
53  * Route Cost key to parser Payload Table.
54  */
55 static const char ROUTE_COST[] = "routecost";
56
57 /**
58  * Sequence Number key to parser Payload Table.
59  */
60 static const char SEQ_NUM[] = "seqnum";
61
62 /**
63  * Response Type key to parser Payload Table.
64  */
65 static const char UPDATE_SEQ_NUM[] = "updateseqnum";
66
67 OCStackResult RMPConstructGatewayPayload(uint32_t gatewayId, OCRepPayload **payload)
68 {
69     OC_LOG(DEBUG, TAG, "RMPConstructGatewayPayload IN");
70     RM_NULL_CHECK_WITH_RET(payload, TAG, "payload");
71
72     *payload = OCRepPayloadCreate();
73     if(!*payload)
74     {
75         OC_LOG(ERROR, TAG, "Failed to allocate Payload");
76         return OC_STACK_ERROR;
77     }
78
79     (*payload)->base.type = PAYLOAD_TYPE_REPRESENTATION;
80     OCRepPayloadSetPropInt(*payload, GATEWAY, gatewayId);
81     OCRepPayloadSetPropInt(*payload, LENGTH_PROP, 0);
82
83     OC_LOG(DEBUG, TAG, "RMPConstructGatewayPayload OUT");
84
85     return OC_STACK_OK;
86 }
87
88 OCStackResult RMPConstructObserveResPayload(uint32_t gatewayId, uint32_t seqNum,
89                                             const u_linklist_t *routingtable, bool isUpdateSeqNeeded,
90                                             OCRepPayload **payload)
91 {
92     OC_LOG(DEBUG, TAG, "RMPConstructObserveResPayload IN");
93     RM_NULL_CHECK_WITH_RET(payload, TAG, "payload");
94
95     *payload =  (OCRepPayload *)OCRepPayloadCreate();
96     if(!*payload)
97     {
98         OC_LOG(ERROR, TAG, "Failed to allocate Payload");
99         return OC_STACK_ERROR;
100     }
101
102     (*payload)->base.type = PAYLOAD_TYPE_REPRESENTATION;
103     OCRepPayloadSetPropInt(*payload, GATEWAY, gatewayId);
104     OCRepPayloadSetPropInt(*payload, SEQ_NUM, seqNum);
105     OCRepPayloadSetPropBool(*payload, UPDATE_SEQ_NUM, isUpdateSeqNeeded);
106     if (NULL == routingtable)
107     {
108         OCRepPayloadSetPropInt(*payload, LENGTH_PROP, 0);
109         OC_LOG(DEBUG, TAG, "Routing Table NULL for ObserveRes Payload");
110         return OC_STACK_OK;
111     }
112
113     u_linklist_iterator_t *iterTable = NULL;
114     u_linklist_init_iterator(routingtable, &iterTable);
115
116     uint32_t len = u_linklist_length(routingtable);
117     const OCRepPayload *arrayPayload[len];
118
119     size_t dimensions[MAX_REP_ARRAY_DEPTH] = {len, 0, 0};
120
121     int i = 0;
122     while (NULL != iterTable)
123     {
124         RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
125
126         OCRepPayload *add = OCRepPayloadCreate();
127         if(!add)
128         {
129             OC_LOG(ERROR, TAG, "Failed to allocate Payload");
130             return OC_STACK_ERROR;
131         }
132
133         add->base.type = PAYLOAD_TYPE_REPRESENTATION;
134         OCRepPayloadSetPropInt(add, GATEWAY, entry->destination->gatewayId);
135         OCRepPayloadSetPropInt(add, ROUTE_COST, entry->routeCost);
136         arrayPayload[i] = add;
137
138         i++;
139         u_linklist_get_next(&iterTable);
140     }
141     OCRepPayloadSetPropInt(*payload, LENGTH_PROP, i);
142     if (i > 0)
143     {
144         bool res = OCRepPayloadSetPropObjectArray(*payload, TABLE, arrayPayload, dimensions);
145         if (!res)
146         {
147             OC_LOG(ERROR, TAG, "Failed to Construct Observer response Payload");
148             return OC_STACK_ERROR;
149         }
150     }
151
152     OC_LOG(DEBUG, TAG, "RMPConstructObserveResPayload OUT");
153     return OC_STACK_OK;
154 }
155
156 OCStackResult RMPConstructRemovalPayload(uint32_t gatewayId, uint32_t seqNum,
157                                          const u_linklist_t *removedGateways, bool isUpdateSeqNeeded,
158                                          OCRepPayload **removedPayload)
159 {
160     OC_LOG(DEBUG, TAG, "RMPConstructRemovalPayload IN");
161     RM_NULL_CHECK_WITH_RET(removedGateways, TAG, "removedGateways");
162     RM_NULL_CHECK_WITH_RET(removedPayload, TAG, "removedPayload");
163
164     u_linklist_iterator_t *iterTable = NULL;
165     u_linklist_init_iterator(removedGateways, &iterTable);
166
167     *removedPayload =  OCRepPayloadCreate();
168     if(!*removedPayload)
169     {
170         OC_LOG(ERROR, TAG, "Failed to allocate Payload");
171         return OC_STACK_ERROR;
172     }
173
174     uint32_t len = u_linklist_length(removedGateways);
175     const OCRepPayload *arrayPayload[len];
176
177     size_t dimensions[MAX_REP_ARRAY_DEPTH] = {len, 0, 0};
178
179     (*removedPayload)->base.type = PAYLOAD_TYPE_REPRESENTATION;
180     OCRepPayloadSetPropInt(*removedPayload, GATEWAY, gatewayId);
181     OCRepPayloadSetPropInt(*removedPayload, SEQ_NUM, seqNum);
182     OCRepPayloadSetPropBool(*removedPayload, UPDATE_SEQ_NUM, isUpdateSeqNeeded);
183
184     int i = 0;
185     while (NULL != iterTable)
186     {
187         RTMGatewayEntry_t *entry = (RTMGatewayEntry_t *) u_linklist_get_data(iterTable);
188         if (!entry)
189         {
190             u_linklist_get_next(&iterTable);
191             continue;
192         }
193         OCRepPayload *add = OCRepPayloadCreate();
194         if(!add)
195         {
196             OC_LOG(ERROR, TAG, "Failed to allocate Payload");
197             return OC_STACK_ERROR;
198         }
199
200         add->base.type = PAYLOAD_TYPE_REPRESENTATION;
201         OC_LOG_V(DEBUG, TAG, "Removing the gateway entry: %u", entry->destination->gatewayId);
202         OCRepPayloadSetPropInt(add, GATEWAY, entry->destination->gatewayId);
203         OCRepPayloadSetPropInt(add, ROUTE_COST, 0);
204         arrayPayload[i] = add;
205
206         i++;
207         u_linklist_get_next(&iterTable);
208     }
209     OCRepPayloadSetPropInt(*removedPayload, LENGTH_PROP, i);
210     bool res = OCRepPayloadSetPropObjectArray(*removedPayload, TABLE, arrayPayload, dimensions);
211     if (!res)
212     {
213         OC_LOG(ERROR, TAG, "Failed to Construct Removal Payload");
214         return OC_STACK_ERROR;
215     }
216
217     OC_LOG(DEBUG, TAG, "RMPConstructRemovalPayload OUT");
218     return OC_STACK_OK;
219 }
220
221 OCStackResult RMPParseRequestPayload(const uint8_t* payload, size_t payloadSize,
222                                      uint32_t *gatewayId)
223 {
224     OCPayload *ocPayload = NULL;
225     OCParsePayload(&ocPayload, PAYLOAD_TYPE_REPRESENTATION, payload, payloadSize);
226     OCRepPayload *repPayload = (OCRepPayload *)ocPayload;
227     OCStackResult res = RMPParseResponsePayload(repPayload, gatewayId, NULL, NULL, NULL);
228     if (OC_STACK_OK != res)
229     {
230         OC_LOG(DEBUG, TAG, "ParseResponsePayload failed");
231     }
232
233     return res;
234 }
235
236 OCStackResult RMPParseResponsePayload(const OCRepPayload *payload, uint32_t *gatewayId,
237                                       uint32_t *seqNum, u_linklist_t **gatewayTable,
238                                       bool *isUpdateSeqNeeded)
239 {
240     OC_LOG(DEBUG, TAG, "RMPParsePayload IN");
241     RM_NULL_CHECK_WITH_RET(payload, TAG, "payload");
242     RM_NULL_CHECK_WITH_RET(gatewayId, TAG, "gatewayId");
243
244     int64_t tempGateway = 0;
245     OCRepPayloadGetPropInt(payload, GATEWAY, &tempGateway);
246     *gatewayId = tempGateway;
247
248     if (NULL == gatewayId || 0 == *gatewayId)
249     {
250         return OC_STACK_COMM_ERROR;
251     }
252
253     if (NULL != seqNum)
254     {
255         int64_t tempSeq = 0;
256         OCRepPayloadGetPropInt(payload, SEQ_NUM, &tempSeq);
257         *seqNum = tempSeq;
258     }
259
260     int64_t length = 0;
261     OCRepPayloadGetPropInt(payload, LENGTH_PROP, &length);
262
263     if (NULL != isUpdateSeqNeeded)
264     {
265         OCRepPayloadGetPropBool(payload, UPDATE_SEQ_NUM, isUpdateSeqNeeded);
266     }
267
268     int len = length;
269     if (0 == len)
270     {
271         OC_LOG(DEBUG, TAG, "Parsed Gateway Payload");
272         return OC_STACK_OK;
273     }
274
275     if (NULL == gatewayTable)
276     {
277         OC_LOG(DEBUG, TAG, "gatewayTable is NULL");
278         return OC_STACK_OK;
279     }
280
281     OCRepPayload **responsePayload[len];
282
283     size_t dimensions[MAX_REP_ARRAY_DEPTH];
284     OCRepPayloadGetPropObjectArray(payload, TABLE, responsePayload, dimensions);
285
286     if (NULL == *responsePayload)
287     {
288         OC_LOG(DEBUG, TAG, "RMPParsePayload OUT");
289         return OC_STACK_OK;
290     }
291
292     *gatewayTable = u_linklist_create();
293     if (NULL == *gatewayTable)
294     {
295         OC_LOG(DEBUG, TAG, "Gateway table create failed");
296         return OC_STACK_ERROR;
297     }
298
299     for (int i = 0; i < len; i++)
300     {
301         RTMGatewayEntry_t *entry = (RTMGatewayEntry_t *)OICCalloc(1, sizeof(RTMGatewayEntry_t));
302
303         if (NULL == entry)
304         {
305             OC_LOG(DEBUG, TAG, "RTMGatewayEntry_t Calloc failed");
306             return OC_STACK_ERROR;
307         }
308         // Filling new Entry
309         entry->destination = (RTMGatewayId_t*)OICCalloc(1, sizeof(RTMGatewayId_t));
310         if (NULL == entry->destination)
311         {
312             OC_LOG(DEBUG, TAG, "Destination Calloc failed");
313             OICFree(entry);
314             return OC_STACK_ERROR;
315         }
316         entry->nextHop = (RTMGatewayId_t*)OICCalloc(1, sizeof(RTMGatewayId_t));
317         if (NULL == entry->nextHop)
318         {
319             OC_LOG(DEBUG, TAG, "nextHop Calloc failed");
320             OICFree(entry->destination);
321             OICFree(entry);
322             return OC_STACK_ERROR;
323         }
324
325         entry->nextHop->gatewayId = *gatewayId;
326
327         int64_t gatewayBuf;
328         int64_t routeCost;
329         OCRepPayloadGetPropInt(*((*responsePayload) + i), GATEWAY, &gatewayBuf);
330         OCRepPayloadGetPropInt(*((*responsePayload) + i), ROUTE_COST, &routeCost);
331
332         entry->destination->gatewayId = gatewayBuf;
333         entry->routeCost = routeCost;
334         u_linklist_add(*gatewayTable, (void *)entry);
335     }
336     OC_LOG(DEBUG, TAG, "RMPParsePayload OUT");
337     return OC_STACK_OK;
338 }
339
340 void RMPFreePayload(OCRepPayload *payload)
341 {
342     OC_LOG(DEBUG, TAG, "RMPFreePayload IN");
343     RM_NULL_CHECK_VOID(payload, TAG, "payload");
344     OCRepPayloadDestroy(payload);
345     OC_LOG(DEBUG, TAG, "RMPFreePayload OUT");
346 }