Fix compile warnings in SimpleClientServer for Linux
[platform/upstream/iotivity.git] / resource / csdk / stack / samples / linux / SimpleClientServer / occlientbasicops.cpp
1 //******************************************************************
2 //
3 // Copyright 2014 Intel Mobile Communications GmbH 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 //      http://www.apache.org/licenses/LICENSE-2.0
11 //
12 // Unless required by applicable law or agreed to in writing, software
13 // distributed under the License is distributed on an "AS IS" BASIS,
14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 // See the License for the specific language governing permissions and
16 // limitations under the License.
17 //
18 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <signal.h>
24 #include <unistd.h>
25 #include <stdint.h>
26 #include <sstream>
27
28 #include "ocstack.h"
29 #include "logger.h"
30 #include "occlientbasicops.h"
31 #include "cJSON.h"
32 #include "oic_malloc.h"
33 #include "oic_string.h"
34
35 #define MAX_IP_ADDR_ST_SZ  16 //string size of "155.255.255.255" (15 + 1)
36 #define MAX_PORT_ST_SZ  6     //string size of "65535" (5 + 1)
37
38 static int IPV4_ADDR_SIZE = 16;
39 static int UNICAST_DISCOVERY = 0;
40 static int TEST_CASE = 0;
41
42 static const char UNICAST_DISCOVERY_QUERY[] = "coap://%s:6298/oic/res";
43 static std::string putPayload = "{\"oic\":[{\"rep\":{\"power\":15,\"state\":true}}]}";
44
45 //The following variable determines the interface protocol (IP, etc)
46 //to be used for sending unicast messages. Default set to IP.
47 static OCConnectivityType OC_CONNTYPE = CT_ADAPTER_IP;
48 static const char * MULTICAST_RESOURCE_DISCOVERY_QUERY = "/oic/res";
49
50 int gQuitFlag = 0;
51
52 struct ResourceNode *resourceList;
53 /*
54  * SIGINT handler: set gQuitFlag to 1 for graceful termination
55  * */
56 void handleSigInt(int signum)
57 {
58     if (signum == SIGINT)
59     {
60         gQuitFlag = 1;
61     }
62 }
63
64 static void PrintUsage()
65 {
66     OC_LOG(INFO, TAG, "Usage : occlient -u <0|1> -t <1|2|3> -c <0|1>");
67     OC_LOG(INFO, TAG, "-u <0|1> : Perform multicast/unicast discovery of resources");
68     OC_LOG(INFO, TAG, "-t 1 : Discover Resources");
69     OC_LOG(INFO, TAG, "-t 2 : Discover Resources and"
70             " Initiate Nonconfirmable Get/Put/Post Requests");
71     OC_LOG(INFO, TAG, "-t 3 : Discover Resources and Initiate "
72             "Confirmable Get/Put/Post Requests");
73     OC_LOG(INFO, TAG, "-c <0|1> : IPv4/IPv6 (IPv6 not currently supported)");
74     OC_LOG(INFO, TAG, "Default connectivityType IPv4");
75 }
76
77 /*
78  * Returns the first resource in the list
79  */
80 const ResourceNode * getResource()
81 {
82     return resourceList;
83 }
84
85 OCStackResult InvokeOCDoResource(std::ostringstream &query, OCMethod method,
86                                  OCConnectivityType connType, OCQualityOfService qos,
87         OCClientResponseHandler cb, OCHeaderOption * options, uint8_t numOptions)
88 {
89     OCStackResult ret;
90     OCCallbackData cbData;
91
92     cbData.cb = cb;
93     cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
94     cbData.cd = NULL;
95
96     ret = OCDoResource(NULL, method, query.str().c_str(), 0,
97         (method == OC_REST_PUT || method == OC_REST_POST) ? putPayload.c_str() : NULL,
98          connType, qos, &cbData, options, numOptions);
99
100     if (ret != OC_STACK_OK)
101     {
102         OC_LOG_V(ERROR, TAG, "OCDoResource returns error %d with method %d",
103                  ret, method);
104     }
105
106     return ret;
107 }
108
109 OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle,
110                                 OCClientResponse * clientResponse)
111 {
112     if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
113     {
114         OC_LOG(INFO, TAG, "<====Callback Context for PUT received successfully====>");
115     }
116     else
117     {
118         OC_LOG(ERROR, TAG, "<====Callback Context for PUT fail====>");
119     }
120
121     if(clientResponse)
122     {
123         OC_LOG_V(INFO, TAG,"PUT Response: %s \nFrom %s:%d\n",
124                  clientResponse->resJSONPayload, clientResponse->devAddr.addr, clientResponse->devAddr.port);
125     }
126     else
127     {
128         OC_LOG(ERROR, TAG, "<====PUT Callback fail to receive clientResponse====>\n");
129     }
130     return OC_STACK_DELETE_TRANSACTION;
131 }
132
133 OCStackApplicationResult postReqCB(void *ctx, OCDoHandle handle,
134                           OCClientResponse *clientResponse)
135 {
136     if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
137     {
138         OC_LOG(INFO, TAG, "<====Callback Context for POST received successfully====>");
139     }
140     else
141     {
142         OC_LOG(ERROR, TAG, "<====Callback Context for POST fail====>");
143     }
144
145     if(clientResponse)
146     {
147         OC_LOG_V(INFO, TAG,"POST Response: %s \nFrom %s:%d\n",
148                     clientResponse->resJSONPayload, clientResponse->devAddr.addr, clientResponse->devAddr.port);
149     }
150     else
151     {
152         OC_LOG(ERROR, TAG, "<====POST Callback fail to receive clientResponse====>\n");
153     }
154
155     return OC_STACK_DELETE_TRANSACTION;
156 }
157
158 OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle,
159                            OCClientResponse * clientResponse)
160 {
161     if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
162     {
163         OC_LOG(INFO, TAG, "<====Callback Context for GET received successfully====>");
164     }
165     else
166     {
167         OC_LOG(ERROR, TAG, "<====Callback Context for GET fail====>");
168     }
169
170     if (clientResponse)
171     {
172         OC_LOG_V(INFO, TAG,"Get Response: %s \nFrom %s:%d\n",
173                 clientResponse->resJSONPayload, clientResponse->devAddr.addr, clientResponse->devAddr.port);
174
175         if (clientResponse->numRcvdVendorSpecificHeaderOptions > 0 )
176         {
177             OC_LOG (INFO, TAG, "Received vendor specific options");
178             uint8_t i = 0;
179             OCHeaderOption * rcvdOptions = clientResponse->rcvdVendorSpecificHeaderOptions;
180             for (i = 0; i < clientResponse->numRcvdVendorSpecificHeaderOptions; i++)
181             {
182                 if (((OCHeaderOption) rcvdOptions[i]).protocolID == OC_COAP_ID)
183                 {
184                     OC_LOG_V(INFO, TAG, "Received option with OC_COAP_ID and ID %u with",
185                             ((OCHeaderOption)rcvdOptions[i]).optionID );
186
187                     OC_LOG_BUFFER(INFO, TAG, ((OCHeaderOption)rcvdOptions[i]).optionData,
188                         MAX_HEADER_OPTION_DATA_LENGTH);
189                 }
190             }
191         }
192     }
193     else
194     {
195         OC_LOG(ERROR, TAG, "<====GET Callback fail to receive clientResponse====>\n");
196     }
197     return OC_STACK_DELETE_TRANSACTION;
198 }
199
200 /*
201  * This is a function called back when a device is discovered
202  */
203 OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle,
204         OCClientResponse * clientResponse)
205 {
206     if (ctx == (void*)DEFAULT_CONTEXT_VALUE)
207     {
208         OC_LOG(INFO, TAG, "\n<====Callback Context for DISCOVERY query "
209                "received successfully====>");
210     }
211     else
212     {
213         OC_LOG(ERROR, TAG, "\n<====Callback Context for DISCOVERY fail====>");
214     }
215
216     if (clientResponse)
217     {
218         OC_LOG_V(INFO, TAG,
219                 "Device Discovered %s \n @ %s:%d\n",
220                 clientResponse->resJSONPayload, clientResponse->devAddr.addr, clientResponse->devAddr.port);
221
222         collectUniqueResource(clientResponse);
223     }
224     else
225     {
226         OC_LOG(ERROR, TAG, "<====DISCOVERY Callback fail to receive clientResponse====>\n");
227     }
228     return (UNICAST_DISCOVERY) ?
229            OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION ;
230 }
231
232 int InitPutRequest(OCQualityOfService qos)
233 {
234     std::ostringstream query;
235     //Get most recently inserted resource
236     const ResourceNode * resource  = getResource();
237
238     if(!resource)
239     {
240         OC_LOG_V(ERROR, TAG, "Resource null, can't do PUT request\n");
241         return -1;
242     }
243     query << "coap://" << resource->ip << ":" << resource->port << resource->uri ;
244     OC_LOG_V(INFO, TAG,"Executing InitPutRequest, Query: %s", query.str().c_str());
245
246     return (InvokeOCDoResource(query, OC_REST_PUT, resource->connType,
247            ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
248             putReqCB, NULL, 0));
249 }
250
251 int InitPostRequest(OCQualityOfService qos)
252 {
253     OCStackResult result;
254     std::ostringstream query;
255     //Get most recently inserted resource
256     const ResourceNode * resource  = getResource();
257
258     if(!resource)
259     {
260         OC_LOG_V(ERROR, TAG, "Resource null, can't do POST request\n");
261         return -1;
262     }
263
264     query << "coap://" << resource->ip << ":" << resource->port << resource->uri ;
265     OC_LOG_V(INFO, TAG,"Executing InitPostRequest, Query: %s", query.str().c_str());
266
267     // First POST operation (to create an LED instance)
268     result = InvokeOCDoResource(query, OC_REST_POST, resource->connType,
269             ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
270             postReqCB, NULL, 0);
271     if (OC_STACK_OK != result)
272     {
273         // Error can happen if for example, network connectivity is down
274         OC_LOG(ERROR, TAG, "First POST call did not succeed");
275     }
276
277     // Second POST operation (to create an LED instance)
278     result = InvokeOCDoResource(query, OC_REST_POST, resource->connType,
279             ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
280             postReqCB, NULL, 0);
281     if (OC_STACK_OK != result)
282     {
283         OC_LOG(ERROR, TAG, "Second POST call did not succeed");
284     }
285
286     // This POST operation will update the original resourced /a/led
287     return (InvokeOCDoResource(query, OC_REST_POST,resource->connType,
288                 ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
289                 postReqCB, NULL, 0));
290 }
291
292 int InitGetRequest(OCQualityOfService qos)
293 {
294     std::ostringstream query;
295     //Get most recently inserted resource
296     const ResourceNode * resource  = getResource();
297
298     if(!resource)
299     {
300         OC_LOG_V(ERROR, TAG, "Resource null, can't do GET request\n");
301         return -1;
302     }
303     query << "coap://" << resource->ip << ":" << resource->port << resource->uri ;
304     OC_LOG_V(INFO, TAG,"Executing InitGetRequest, Query: %s", query.str().c_str());
305
306     return (InvokeOCDoResource(query, OC_REST_GET, resource->connType,
307             (qos == OC_HIGH_QOS)?OC_HIGH_QOS:OC_LOW_QOS, getReqCB, NULL, 0));
308 }
309
310 int InitDiscovery()
311 {
312     OCStackResult ret;
313     OCCallbackData cbData;
314     /* Start a discovery query*/
315     char szQueryUri[64] = {};
316     if (UNICAST_DISCOVERY)
317     {
318         char ipv4addr[IPV4_ADDR_SIZE];
319         printf("Enter IPv4 address of the Server hosting "
320                "resource (Ex: 192.168.0.15)\n");
321         if (fgets(ipv4addr, IPV4_ADDR_SIZE, stdin))
322         {
323             //Strip newline char from ipv4addr
324             StripNewLineChar(ipv4addr);
325             snprintf(szQueryUri, sizeof(szQueryUri), UNICAST_DISCOVERY_QUERY, ipv4addr);
326         }
327         else
328         {
329             OC_LOG(ERROR, TAG, "!! Bad input for IPV4 address. !!");
330             return OC_STACK_INVALID_PARAM;
331         }
332     }
333     else
334     {
335         strcpy(szQueryUri, MULTICAST_RESOURCE_DISCOVERY_QUERY);
336     }
337     cbData.cb = discoveryReqCB;
338     cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
339     cbData.cd = NULL;
340     if (UNICAST_DISCOVERY)
341     {
342         ret = OCDoResource(NULL, OC_REST_GET, szQueryUri, 0, 0, OC_CONNTYPE,
343                 OC_LOW_QOS, &cbData, NULL, 0);
344     }
345     else
346     {
347         ret = OCDoResource(NULL, OC_REST_DISCOVER, szQueryUri, 0, 0, CT_DEFAULT,
348                 OC_LOW_QOS, &cbData, NULL, 0);
349     }
350
351     if (ret != OC_STACK_OK)
352     {
353         OC_LOG(ERROR, TAG, "OCStack resource error");
354     }
355     return ret;
356 }
357
358 const char *getIPAddr(const OCClientResponse *clientResponse)
359 {
360     if (!clientResponse)
361     {
362         return "";
363     }
364
365     const OCDevAddr *devAddr = &clientResponse->devAddr;
366     char *ipaddr = (char *) OICCalloc(1, strlen(devAddr->addr));
367     if (ipaddr)
368     {
369         snprintf(ipaddr, MAX_IP_ADDR_ST_SZ, "%s", devAddr->addr);
370     }
371     else
372     {
373         OC_LOG(ERROR, TAG, "Memory not allocated to ipaddr");
374     }
375     return ipaddr;
376 }
377
378 const char *getPort(const OCClientResponse *clientResponse)
379 {
380     if(!clientResponse)
381     {
382         return "";
383     }
384
385     char *port = NULL;
386     if((port = (char *)OICCalloc(1, MAX_PORT_ST_SZ)))
387     {
388         snprintf(port, MAX_PORT_ST_SZ, "%d", clientResponse->devAddr.port);
389     }
390     else
391     {
392         OC_LOG(ERROR, TAG, "Memory not allocated to port");
393     }
394     return port;
395 }
396
397 int parseJSON(const char * resJSONPayload, char ** sid_c,
398               char *** uri_c, int * totalRes)
399 {
400     cJSON * root = NULL;
401     cJSON * oc = NULL;
402
403     root = cJSON_Parse((char *)(resJSONPayload));
404
405     if (!root)
406     {
407         OC_LOG(ERROR, TAG, "JSON Parsing Error");
408         return OC_STACK_INVALID_JSON;
409     }
410
411     oc = cJSON_GetObjectItem(root,"oic");
412     if (!oc)
413     {
414         OC_LOG(ERROR, TAG, "Invalid JSON : Missing oc object");
415         return OC_STACK_INVALID_JSON;
416     }
417
418     * totalRes = cJSON_GetArraySize(oc);
419
420     if(oc->type == cJSON_Array)
421     {
422         cJSON * resource = cJSON_GetArrayItem(oc, 0);
423
424         if(!resource)
425         {
426             return OC_STACK_INVALID_JSON;
427         }
428
429         if (cJSON_GetObjectItem(resource, "sid"))
430         {
431             char * sid = cJSON_GetObjectItem(resource, "sid")->valuestring;
432             if((* sid_c = (char *)OICCalloc(1, strlen (sid) + 1)))
433             {
434                 memcpy(* sid_c, sid, strlen(sid) + 1);
435             }
436             else
437             {
438                 OC_LOG(ERROR, TAG, "Memory not allocated to sid");
439                 return OC_STACK_NO_MEMORY;
440             }
441         }
442         else
443         {
444             OC_LOG(ERROR, TAG, "Invalid JSON : Missing sid object");
445             return OC_STACK_INVALID_JSON;
446         }
447
448         if(!(* uri_c =  (char ** )OICMalloc ((* totalRes) * sizeof(char *))))
449         {
450             OC_LOG(ERROR, TAG, "Memory not allocated to uri_c array");
451             return OC_STACK_NO_MEMORY;
452         }
453
454         int i = 0;
455
456         while(true)
457         {
458             if (cJSON_GetObjectItem(resource, "href"))
459             {
460                 char *uri= cJSON_GetObjectItem(resource, "href")->valuestring;
461                 if(((*uri_c)[i] = (char *)OICCalloc(1, strlen (uri) + 1)))
462                 {
463                     memcpy((*uri_c)[i], uri, strlen(uri) + 1);
464                 }
465                 else
466                 {
467                     OC_LOG(ERROR, TAG, "Memory not allocated to uri");
468                     return OC_STACK_NO_MEMORY;
469                 }
470                 i++;
471                 if(i >= (* totalRes))
472                     break;
473                 resource = cJSON_GetArrayItem(oc, i);
474             }
475             else
476             {
477                OC_LOG(ERROR, TAG, "Invalid JSON : Missing uri object");
478                return OC_STACK_INVALID_JSON;
479            }
480         }
481     }
482     else
483     {
484         return OC_STACK_INVALID_JSON;
485         OC_LOG(ERROR, TAG, "Invalid JSON : oc object type is not an array");
486     }
487     return OC_STACK_OK;
488 }
489
490 void queryResource()
491 {
492     printf("\n");
493     switch(TEST_CASE)
494     {
495         case TEST_DISCOVER_REQ:
496             break;
497         case TEST_NON_CON_OP:
498             InitGetRequest(OC_LOW_QOS);
499             InitPutRequest(OC_LOW_QOS);
500             InitPostRequest(OC_LOW_QOS);
501             break;
502         case TEST_CON_OP:
503             InitGetRequest(OC_HIGH_QOS);
504             InitPutRequest(OC_HIGH_QOS);
505             InitPostRequest(OC_HIGH_QOS);
506             break;
507         default:
508             PrintUsage();
509             break;
510     }
511     printf("\n");
512 }
513
514
515 void collectUniqueResource(const OCClientResponse * clientResponse)
516 {
517     char * sid = NULL;
518     char ** uri = NULL;
519     int totalRes = 0;
520     int i;
521
522     if(parseJSON(clientResponse->resJSONPayload, & sid, & uri, &totalRes)
523             != OC_STACK_OK)
524     {
525         OC_LOG(ERROR, TAG, "Error while parsing JSON payload in OCClientResponse");
526
527         OICFree(sid);
528         for (i = 0; i < totalRes; i++)
529         {
530             OICFree(uri[i]);
531         }
532         OICFree(uri);
533
534        return;
535     }
536
537     for(i = 0; i < totalRes; i++)
538     {
539         if(insertResource(sid, uri[i], clientResponse) == 1)
540         {
541             printf("%s%s%s%s\n",sid, ":", uri[i], " is new");
542             printResourceList();
543             queryResource();
544         }
545         else
546         {
547             printf("%s%s%s%s\n\n",sid, ":", uri[i], " has been seen before");
548         }
549     }
550
551     OICFree(sid);
552     for (i = 0; i < totalRes; i++)
553     {
554         OICFree(uri[i]);
555     }
556     OICFree(uri);
557 }
558
559 /* This function searches for the resource(sid:uri) in the ResourceList.
560  * If the Resource is found in the list then it returns 0 else insert
561  * the resource to front of the list and returns 1.
562  */
563 int insertResource(const char * sid, char const * uri,
564             const OCClientResponse * clientResponse)
565 {
566     ResourceNode * iter = resourceList;
567     char * sid_cpy =  OICStrdup(sid);
568     char * uri_cpy = OICStrdup(uri);
569
570     //Checking if the resource(sid:uri) is new
571     while(iter)
572     {
573         if((strcmp(iter->sid, sid) == 0) && (strcmp(iter->uri, uri) == 0))
574         {
575             OICFree(sid_cpy);
576             OICFree(uri_cpy);
577             return 0;
578         }
579         else
580         {
581             iter = iter->next;
582         }
583     }
584
585     //Creating new ResourceNode
586     if((iter = (ResourceNode *) OICMalloc(sizeof(ResourceNode))))
587     {
588         iter->sid = sid_cpy;
589         iter->uri = uri_cpy;
590         iter->ip = getIPAddr(clientResponse);
591         iter->port = getPort(clientResponse);
592         iter->connType = clientResponse->connType;
593         iter->next = NULL;
594     }
595     else
596     {
597         OC_LOG(ERROR, TAG, "Memory not allocated to ResourceNode");
598         OICFree(sid_cpy);
599         OICFree(uri_cpy);
600         return -1;
601     }
602
603     //Adding new ResourceNode to front of the ResourceList
604     if(!resourceList)
605     {
606         resourceList = iter;
607     }
608     else
609     {
610         iter->next = resourceList;
611         resourceList = iter;
612     }
613     return 1;
614 }
615
616 void printResourceList()
617 {
618     ResourceNode * iter;
619     iter = resourceList;
620     printf("\nResource List\n");
621     while(iter)
622     {
623         printf("*****************************************************\n");
624         printf("sid = %s \n",iter->sid);
625         printf("uri = %s\n", iter->uri);
626         printf("ip = %s\n", iter->ip);
627         printf("port = %s\n", iter->port);
628         switch (iter->connType & CT_MASK_ADAPTER)
629         {
630             case CT_ADAPTER_IP:
631                 printf("connType = %s\n","IPv4");
632                 break;
633             case OC_ADAPTER_GATT_BTLE:
634                 printf("connType = %s\n","BLE");
635                 break;
636             case OC_ADAPTER_RFCOMM_BTEDR:
637                 printf("connType = %s\n","BT");
638                 break;
639             default:
640                 printf("connType = %s\n","Invalid connType");
641                 break;
642         }
643         printf("*****************************************************\n");
644         iter = iter->next;
645     }
646 }
647
648 void freeResourceList()
649 {
650     OC_LOG(INFO, TAG, "Freeing ResourceNode List");
651     ResourceNode * temp;
652     while(resourceList)
653     {
654         temp = resourceList;
655         resourceList = resourceList->next;
656         OICFree((void *)temp->sid);
657         OICFree((void *)temp->uri);
658         OICFree((void *)temp->ip);
659         OICFree((void *)temp->port);
660         OICFree(temp);
661     }
662     resourceList = NULL;
663 }
664
665 int main(int argc, char* argv[])
666 {
667     int opt;
668     resourceList = NULL;
669     while ((opt = getopt(argc, argv, "u:t:c:")) != -1)
670     {
671         switch(opt)
672         {
673             case 'u':
674                 UNICAST_DISCOVERY = atoi(optarg);
675                 break;
676             case 't':
677                 TEST_CASE = atoi(optarg);
678                 break;
679             case 'c':
680                 OC_CONNTYPE = CT_ADAPTER_IP;
681                 break;
682             default:
683                 PrintUsage();
684                 return -1;
685         }
686     }
687
688     if ((UNICAST_DISCOVERY != 0 && UNICAST_DISCOVERY != 1) ||
689             (TEST_CASE < TEST_DISCOVER_REQ || TEST_CASE >= MAX_TESTS) )
690     {
691         PrintUsage();
692         return -1;
693     }
694
695     /* Initialize OCStack*/
696     if (OCInit(NULL, 0, OC_CLIENT) != OC_STACK_OK)
697     {
698         OC_LOG(ERROR, TAG, "OCStack init error");
699         return 0;
700     }
701
702     InitDiscovery();
703
704     // Break from loop with Ctrl+C
705     signal(SIGINT, handleSigInt);
706
707     while (!gQuitFlag)
708     {
709         if (OCProcess() != OC_STACK_OK)
710         {
711             OC_LOG(ERROR, TAG, "OCStack process error");
712             return 0;
713         }
714         sleep(2);
715     }
716
717     freeResourceList();
718     OC_LOG(INFO, TAG, "Exiting occlient main loop...");
719     if (OCStop() != OC_STACK_OK)
720     {
721         OC_LOG(ERROR, TAG, "OCStack stop error");
722     }
723     return 0;
724 }
725
726