Merge branch '1.1-rel'
[platform/upstream/iotivity.git] / resource / csdk / stack / samples / linux / secure / occlientdirectpairing.cpp
1 //******************************************************************\r
2 //\r
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.\r
4 //\r
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\r
6 //\r
7 // Licensed under the Apache License, Version 2.0 (the "License");\r
8 // you may not use this file except in compliance with the License.\r
9 // You may obtain a copy of the License at\r
10 //\r
11 //      http://www.apache.org/licenses/LICENSE-2.0\r
12 //\r
13 // Unless required by applicable law or agreed to in writing, software\r
14 // distributed under the License is distributed on an "AS IS" BASIS,\r
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
16 // See the License for the specific language governing permissions and\r
17 // limitations under the License.\r
18 //\r
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\r
20 \r
21 #include <stdio.h>\r
22 #include <stdlib.h>\r
23 #include <string.h>\r
24 #include <signal.h>\r
25 #include <unistd.h>\r
26 #include <pthread.h>\r
27 #include <iostream>\r
28 #include <sstream>\r
29 #include "ocstack.h"\r
30 #include "logger.h"\r
31 #include "ocpayload.h"\r
32 #include "payload_logging.h"\r
33 #include "oic_malloc.h"\r
34 #include "oic_string.h"\r
35 #include "utlist.h"\r
36 \r
37 #define TAG "occlient-directpairing"\r
38 \r
39 #define BOLD_BEGIN    "\033[1m"\r
40 #define RED_BEGIN      "\033[1;31m"\r
41 #define GREEN_BEGIN  "\033[1;92m"\r
42 #define COLOR_END      "\033[0m"\r
43 #define MAX_LINE (1024)\r
44 #define DP_DISCOVERY_TIMEOUT   3  // 3 sec\r
45 #define DP_PIN_LENGTH 8 // 8 digit\r
46 \r
47 static char DISCOVERY_QUERY[] = "%s/oic/res";\r
48 \r
49 //Secure Virtual Resource database for Iotivity Client application\r
50 //It contains Client's Identity and the PSK credentials\r
51 //of other devices which the client trusts\r
52 static char CRED_FILE[] = "oic_svr_db_client_directpairing.dat";
53
54 static const OCDPDev_t *discoveredDevs = NULL;\r
55 static const OCDPDev_t *pairedDevs = NULL;\r
56 \r
57 int gQuitFlag = 0;\r
58 \r
59 //-----------------------------------------------------------------------------\r
60 // Function prototype\r
61 //-----------------------------------------------------------------------------\r
62 \r
63 \r
64 \r
65 \r
66 //-----------------------------------------------------------------------------\r
67 // Function body\r
68 //-----------------------------------------------------------------------------\r
69 \r
70 /* SIGINT handler: set gQuitFlag to 1 for graceful termination */\r
71 void handleSigInt(int signum)\r
72 {\r
73     if (signum == SIGINT)\r
74     {\r
75         gQuitFlag = 1;\r
76     }\r
77 }\r
78 \r
79 const char *readline(const char *in, const char *defaultStr)\r
80 {\r
81     static char rbuffer[MAX_LINE] = {0,};\r
82     char *cptr, *p;\r
83 \r
84     size_t in_len = strlen(in);\r
85     for (size_t i=0; i<in_len; i++)\r
86     {\r
87         fprintf(stdout, "%c", in[i]);\r
88     }\r
89 \r
90     if (NULL != (cptr = fgets(rbuffer, MAX_LINE, stdin)))\r
91     {\r
92         /* kill preceding whitespace but leave \n so we're guaranteed to have something */\r
93         /*while(*cptr == ' ' || *cptr == '\t')\r
94         {\r
95             cptr++;\r
96         }*/\r
97 \r
98         if ( (p = strchr(cptr, '\n')) != NULL )\r
99         {\r
100             *p = '\0';\r
101         }\r
102 \r
103         if (strlen(cptr)==0 && defaultStr)\r
104         {\r
105             return defaultStr;\r
106         }\r
107         return cptr;\r
108     }\r
109     else\r
110     {\r
111         return 0;\r
112     }\r
113 }\r
114 \r
115 const char *getResult(OCStackResult result) {\r
116     switch (result) {\r
117     case OC_STACK_OK:\r
118         return "OC_STACK_OK";\r
119     case OC_STACK_RESOURCE_CREATED:\r
120         return "OC_STACK_RESOURCE_CREATED";\r
121     case OC_STACK_RESOURCE_DELETED:\r
122         return "OC_STACK_RESOURCE_DELETED";\r
123     case OC_STACK_INVALID_URI:\r
124         return "OC_STACK_INVALID_URI";\r
125     case OC_STACK_INVALID_QUERY:\r
126         return "OC_STACK_INVALID_QUERY";\r
127     case OC_STACK_INVALID_IP:\r
128         return "OC_STACK_INVALID_IP";\r
129     case OC_STACK_INVALID_PORT:\r
130         return "OC_STACK_INVALID_PORT";\r
131     case OC_STACK_INVALID_CALLBACK:\r
132         return "OC_STACK_INVALID_CALLBACK";\r
133     case OC_STACK_INVALID_METHOD:\r
134         return "OC_STACK_INVALID_METHOD";\r
135     case OC_STACK_NO_MEMORY:\r
136         return "OC_STACK_NO_MEMORY";\r
137     case OC_STACK_COMM_ERROR:\r
138         return "OC_STACK_COMM_ERROR";\r
139     case OC_STACK_INVALID_PARAM:\r
140         return "OC_STACK_INVALID_PARAM";\r
141     case OC_STACK_NOTIMPL:\r
142         return "OC_STACK_NOTIMPL";\r
143     case OC_STACK_NO_RESOURCE:\r
144         return "OC_STACK_NO_RESOURCE";\r
145     case OC_STACK_RESOURCE_ERROR:\r
146         return "OC_STACK_RESOURCE_ERROR";\r
147     case OC_STACK_SLOW_RESOURCE:\r
148         return "OC_STACK_SLOW_RESOURCE";\r
149     case OC_STACK_NO_OBSERVERS:\r
150         return "OC_STACK_NO_OBSERVERS";\r
151     #ifdef WITH_PRESENCE\r
152     case OC_STACK_PRESENCE_STOPPED:\r
153         return "OC_STACK_PRESENCE_STOPPED";\r
154     #endif\r
155     case OC_STACK_ERROR:\r
156         return "OC_STACK_ERROR";\r
157     default:\r
158         return "UNKNOWN";\r
159     }\r
160 }\r
161 \r
162 OCDPDev_t* getDev(const OCDPDev_t* pList, const uint32_t dev_num)\r
163 {\r
164     if(NULL == pList)\r
165     {\r
166         printf("     Device List is Empty..\n");\r
167         return NULL;\r
168     }\r
169 \r
170     OCDPDev_t* lst =  (OCDPDev_t*)pList;\r
171     for(size_t i=0; lst; )\r
172     {\r
173         if(dev_num == ++i)\r
174         {\r
175             return lst;\r
176         }\r
177         lst = lst->next;\r
178     }\r
179 \r
180     return NULL;  // in here |lst| is always |NULL|\r
181 }\r
182 \r
183 int printList(const OCDPDev_t* pList)\r
184 {\r
185     if(!pList)\r
186     {\r
187         printf("     Device List is Empty..\n\n");\r
188         return 0;\r
189     }\r
190 \r
191     const OCDPDev_t* lst = pList;\r
192     int lst_cnt = 0;\r
193     for( ; lst; )\r
194     {\r
195         printf("     [%d] ", ++lst_cnt);\r
196         for(int i=0; i<UUID_IDENTITY_SIZE; i++)\r
197         {\r
198             fprintf(stdout, "%c", (char)lst->deviceID.id[i]);\r
199         }\r
200         printf("\n");\r
201         lst = lst->next;\r
202     }\r
203     printf("\n");\r
204 \r
205     return lst_cnt;\r
206 }\r
207 \r
208 bool printPairingMethod(const OCDPDev_t* pDev)\r
209 {\r
210     printf("\n   * List of supported pairing method\n");\r
211 \r
212     if(!pDev || false == pDev->edp)\r
213     {\r
214         printf("     Invalid device or Not support direct-pairing..\n\n");\r
215         return false;\r
216     }\r
217 \r
218     if(!pDev->prm || 0 == pDev->prmLen)\r
219     {\r
220         printf("     Not exist any support method..\n\n");\r
221         return false;\r
222     }\r
223 \r
224     bool bAvailable = true;\r
225     for(size_t i=0; i<pDev->prmLen; i++)\r
226     {\r
227         printf("     [%ld] ", i+1);\r
228         switch (pDev->prm[i])\r
229         {\r
230             case DP_PRE_CONFIGURED:\r
231                 printf("Pre-Configured PIN");\r
232                 break;\r
233             case DP_RANDOM_PIN:\r
234                 printf("Random PIN");\r
235                 break;\r
236             default:\r
237                 printf("NOT Allowed (%d)", pDev->prm[i]);\r
238                 bAvailable = false;\r
239                 break;\r
240         }\r
241         printf("\n");\r
242     }\r
243     printf("\n");\r
244 \r
245     return bAvailable;\r
246 }\r
247 \r
248 // This is a function called back when a device is discovered\r
249 OCStackApplicationResult discoveryReqCB(void*, OCDoHandle,\r
250         OCClientResponse * clientResponse)\r
251 {\r
252     OIC_LOG(INFO, TAG, "Callback Context for DISCOVER query recvd successfully");\r
253 \r
254     if (clientResponse)\r
255     {\r
256         OIC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));\r
257         OIC_LOG_V(INFO, TAG,\r
258                 "Device =============> Discovered @ %s:%d",\r
259                 clientResponse->devAddr.addr,\r
260                 clientResponse->devAddr.port);\r
261 \r
262         if (clientResponse->result == OC_STACK_OK)\r
263         {\r
264             OIC_LOG_PAYLOAD(INFO, clientResponse->payload);\r
265         }\r
266     }\r
267 \r
268     return OC_STACK_DELETE_TRANSACTION;\r
269 \r
270 }\r
271 \r
272 // This is a function called back when direct-pairing status is changed\r
273 void pairingReqCB(OCDPDev_t* peer, OCStackResult result)\r
274 {\r
275     OIC_LOG(INFO, TAG, "Callback Context for Direct-Pairing establishment\n");\r
276 \r
277     if (OC_STACK_OK == result)\r
278     {\r
279         OIC_LOG_V(INFO, TAG,\r
280                 "Direct-Pairing SUCCESS =============> Target @ %s:%d\n",\r
281                 peer->endpoint.addr,\r
282                 peer->endpoint.port);\r
283     }\r
284     else\r
285     {\r
286         OIC_LOG(ERROR, TAG, "Direct-Pairing FAILED..\n");\r
287     }\r
288 }\r
289 \r
290 OCStackApplicationResult getReqCB(void * ctx, OCDoHandle handle, OCClientResponse *clientResponse)\r
291 {\r
292     OIC_LOG(INFO, TAG, "Callback Context for GET query recvd successfully");\r
293 \r
294     (void)ctx;\r
295     (void)handle;\r
296     if (clientResponse)\r
297     {\r
298         OIC_LOG_V(INFO, TAG, "StackResult: %s",  getResult(clientResponse->result));\r
299         OIC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);\r
300         OIC_LOG_PAYLOAD(INFO, clientResponse->payload);\r
301         if ((OCSecurityPayload*)clientResponse->payload)\r
302         {\r
303             OIC_LOG(INFO, TAG, PCF("=============> Get Response"));\r
304         }\r
305     }\r
306     return OC_STACK_DELETE_TRANSACTION;\r
307 }\r
308 \r
309 int DeviceDiscovery()\r
310 {\r
311     OCStackResult ret;\r
312     OCCallbackData cbData;\r
313     char queryUri[200];\r
314     char ipaddr[100] = { '\0' };\r
315 \r
316     snprintf(queryUri, sizeof (queryUri), DISCOVERY_QUERY, ipaddr);\r
317 \r
318     cbData.cb = discoveryReqCB;\r
319     cbData.context = NULL;\r
320     cbData.cd = NULL;\r
321 \r
322     /* Start a discovery query*/\r
323     OIC_LOG_V(INFO, TAG, "Resource Discovery : %s\n", queryUri);\r
324 \r
325     ret = OCDoResource(NULL, OC_REST_DISCOVER, queryUri, 0, 0, CT_DEFAULT,\r
326                        OC_LOW_QOS, &cbData, NULL, 0);\r
327     if (ret != OC_STACK_OK)\r
328     {\r
329         OIC_LOG(ERROR, TAG, "OCStack resource error");\r
330     }\r
331     return ret;\r
332 }\r
333 \r
334 OCStackResult DirectPairingDiscovery()\r
335 {\r
336     // initiate direct pairing discovery\r
337     OIC_LOG(INFO, TAG, "   Discovering Only Owned Devices on Network..");\r
338     discoveredDevs = OCDiscoverDirectPairingDevices(DP_DISCOVERY_TIMEOUT);\r
339     if(NULL == discoveredDevs)\r
340     {\r
341         OIC_LOG(ERROR, TAG, "OCDiscoverDirectPairingDevices API error");\r
342         return OC_STACK_ERROR;\r
343     }\r
344 \r
345     // display the discovered unowned list\r
346     printf("   > Discovered Direct-Pairing Support Devices\n");\r
347     printList(discoveredDevs);\r
348 \r
349     return OC_STACK_OK;\r
350 }\r
351 \r
352 OCStackResult DoDirectPairing(OCDPDev_t* peer, OCPrm_t pmSel, char *pinNumber)\r
353 {\r
354     if (NULL == peer || NULL == pinNumber)\r
355     {\r
356         OIC_LOG(ERROR, TAG, "invalid parameter");\r
357         return OC_STACK_INVALID_PARAM;\r
358     }\r
359 \r
360     // start direct pairing\r
361     OIC_LOG(INFO, TAG, "   Start Direct Pairing..");\r
362     if(OC_STACK_OK != OCDoDirectPairing(peer, pmSel, pinNumber, pairingReqCB))\r
363     {\r
364         OIC_LOG(ERROR, TAG, "OCDoDirectPairing API error");\r
365         return OC_STACK_ERROR;\r
366     }\r
367 \r
368     return OC_STACK_OK;\r
369 }\r
370 \r
371 OCStackResult SendGetRequest(OCDPDev_t* peer)\r
372 {\r
373     OIC_LOG(INFO, TAG, "Send Get REQ to Led server");\r
374 \r
375     char szQueryUri[] = "/a/led";\r
376     OCDoHandle handle;\r
377     OCCallbackData cbData;\r
378     OCDevAddr endpoint;\r
379     OCStackResult ret;\r
380 \r
381     memcpy(&endpoint, &peer->endpoint, sizeof(OCDevAddr));\r
382     endpoint.port = peer->securePort;\r
383     endpoint.flags = (OCTransportFlags)(endpoint.flags | OC_SECURE);\r
384 \r
385     cbData.cb = getReqCB;\r
386     cbData.context = NULL;\r
387     cbData.cd = NULL;\r
388 \r
389     OIC_LOG(INFO, TAG, "Request to /a/light ");\r
390     ret = OCDoResource(&handle, OC_REST_GET, szQueryUri,\r
391                &endpoint, NULL, peer->connType, OC_LOW_QOS, &cbData, NULL, 0);\r
392     if (ret != OC_STACK_OK)\r
393     {\r
394         OIC_LOG_V(ERROR, TAG, "OCDoResource returns error %d with method %d", ret, OC_REST_GET);\r
395     }\r
396 \r
397     return ret;\r
398 }\r
399 \r
400 FILE* client_fopen(const char *path, const char *mode)\r
401 {\r
402     (void)path;\r
403     return fopen(CRED_FILE, mode);\r
404 }\r
405 \r
406 void *CLInterface(void *data)\r
407 {\r
408     printf(RED_BEGIN"#Ready to operation ('h' for help)#\n"COLOR_END);\r
409 \r
410     (void)data;\r
411     OCStackResult ret;\r
412     char query[MAX_LINE] = {0,};\r
413     const char prompt[] = BOLD_BEGIN"IoTivity-DP#"COLOR_END" ";\r
414     const char* helpmsg[6] = {\r
415             GREEN_BEGIN"# h  (or help) : show help message"COLOR_END,\r
416             GREEN_BEGIN"# dd (DP device discovery) : discover Direct-Pairing devices"COLOR_END,\r
417             GREEN_BEGIN"# dp (start Direct-Pairing) : negotiate DP method & start Direct-Pairing"COLOR_END,\r
418             GREEN_BEGIN"# sd (send data) : send data to device"COLOR_END,\r
419             GREEN_BEGIN"# ll (list all device) : list all discovered/paired devices"COLOR_END,\r
420             GREEN_BEGIN"# q  (quit) : quit test"COLOR_END,\r
421         };\r
422 \r
423     for (size_t i=0; i<(sizeof(helpmsg)/sizeof(char*)); i++)\r
424     {\r
425         fprintf(stderr, "%s\n", helpmsg[i]);\r
426     }\r
427     printf("\n");\r
428 \r
429     // cli\r
430     for (;;)\r
431     {\r
432         const char *input = readline(prompt, NULL);\r
433         if (!input) {\r
434             continue;\r
435         }\r
436 \r
437         strncpy(query, input, MAX_LINE);\r
438         if (!strlen(query))\r
439         {\r
440             continue;\r
441         }\r
442         else if (!strcmp(query, "h") || !strcmp(query, "help"))\r
443         {\r
444             for (size_t i=0; i<(sizeof(helpmsg)/sizeof(char*)); i++)\r
445             {\r
446                 fprintf(stderr, "%s\n", helpmsg[i]);\r
447             }\r
448             continue;\r
449         }\r
450         else\r
451         {\r
452             if (!strcmp(query, "dd"))\r
453             {\r
454                 OIC_LOG(INFO, TAG, "- Direct-Pairing device discovery -");\r
455 \r
456                 ret = DirectPairingDiscovery();\r
457                 if (OC_STACK_OK != ret)\r
458                 {\r
459                     OIC_LOG(ERROR, TAG, "Error in DirectPairingDiscovery()");\r
460                 }\r
461             }\r
462             else if (!strcmp(query, "dp"))\r
463             {\r
464                 OIC_LOG(INFO, TAG, "- Negotiate DP method & Start Direct-Pairing -");\r
465 \r
466                 printf("\n   * List of  discovered device\n");\r
467                 printList(discoveredDevs);\r
468 \r
469                 // target peer\r
470                 OCDPDev_t *peer = NULL;\r
471                 long peerIdx;\r
472                 input = readline("   > Enter Peer Device Number to initiate Direct-Pairing: ", NULL);\r
473                 if (!input || !strlen(input))\r
474                 {\r
475                     continue;\r
476                 }\r
477                 char *ptr;\r
478                 peerIdx = strtol(input, &ptr, 10);\r
479 \r
480                 peer = getDev(discoveredDevs, (uint32_t)peerIdx);\r
481                 if (NULL == peer)\r
482                 {\r
483                     OIC_LOG(ERROR, TAG, "Not found the peer in discovered list");\r
484                     continue;\r
485                 }\r
486 \r
487                 // get pairing method\r
488                 long pmIdx;\r
489                 OCPrm_t pmSel = DP_NOT_ALLOWED;\r
490                 if (false == printPairingMethod(peer))\r
491                 {\r
492                     OIC_LOG(ERROR, TAG, "Target does not support the Direct-Pairing");\r
493                     continue;\r
494                 }\r
495                 input = readline("   > Enter pairing method: ", NULL);\r
496                 if (!input || !strlen(input))\r
497                 {\r
498                     continue;\r
499                 }\r
500                 pmIdx = strtol(input, &ptr, 10);\r
501                 printf("\n");\r
502                 if (0 >= pmIdx || peer->prmLen+1 < (size_t)pmIdx)\r
503                 {\r
504                     OIC_LOG(ERROR, TAG, "Invalid mode selection");\r
505                     continue;\r
506                 }\r
507                 pmSel = peer->prm[pmIdx-1];\r
508 \r
509                 // get PIN\r
510                 char pinNumber[DP_PIN_LENGTH+1];\r
511                 input = readline("   > Enter PIN Number for authentication (ex - '00000000' [8 digit] ): ", NULL);\r
512                 if (!input || DP_PIN_LENGTH != strlen(input))\r
513                 {\r
514                     OIC_LOG(ERROR, TAG, "Invalid PIN");\r
515                     continue;\r
516                 }\r
517                 sscanf(input, "%8s", pinNumber);
518                 printf("\n");
519 \r
520                 ret = DoDirectPairing(peer, pmSel, pinNumber);\r
521                 if (OC_STACK_OK != ret)\r
522                 {\r
523                     OIC_LOG(ERROR, TAG, "Error in DoDirectPairing()");\r
524                 }\r
525             }\r
526             else if (!strcmp(query, "sd"))\r
527             {\r
528                 OIC_LOG(INFO, TAG, "- Send data(GET Request) to device(led server) -");\r
529 \r
530                 //pairedDevs = OCGetDirectPairedDevices();\r
531                 //printList(pairedDevs);\r
532                 printList(discoveredDevs);\r
533 \r
534                 // target peer\r
535                 OCDPDev_t *peer = NULL;\r
536                 long peerIdx;\r
537                 input = readline("   > Enter Peer Device Number to initiate Direct-Pairing: ", NULL);\r
538                 if (!input || !strlen(input))\r
539                 {\r
540                     continue;\r
541                 }\r
542                 char *ptr;\r
543                 peerIdx = strtol(input, &ptr, 10);\r
544 \r
545                 //peer = getDev(pairedDevs, peerIdx);\r
546                 peer = getDev(discoveredDevs, (uint32_t)peerIdx);\r
547                 if (NULL == peer)\r
548                 {\r
549                     OIC_LOG(ERROR, TAG, "Not found the peer in discovered list");\r
550                     continue;\r
551                 }\r
552 \r
553                 // send Get Req\r
554                 ret = SendGetRequest(peer);\r
555                 if (OC_STACK_OK != ret)\r
556                 {\r
557                     OIC_LOG(ERROR, TAG, "Error in SendGetRequest()");\r
558                 }\r
559             }\r
560             else if (!strcmp(query, "ll"))\r
561             {\r
562                 OIC_LOG(INFO, TAG, "- List all discovered and paired devices) -");\r
563 \r
564                 printf("  > List of discovered devices\n");\r
565                 printList(discoveredDevs);\r
566                 printf("\n");\r
567 \r
568                 printf("  > List of paired devices\n");\r
569                 pairedDevs = OCGetDirectPairedDevices();\r
570                 printList(pairedDevs);\r
571                 printf("\n");\r
572             }\r
573             else if (!strcmp(query, "q"))\r
574             {\r
575                 printf("QUIT\n");\r
576                 gQuitFlag = 1;\r
577                 break;\r
578             }\r
579         }\r
580     }\r
581 \r
582     return 0;\r
583 }\r
584 \r
585 int main(void)\r
586 {\r
587     struct timespec timeout;\r
588 \r
589     // Initialize Persistent Storage for SVR database\r
590     OCPersistentStorage ps = { client_fopen, fread, fwrite, fclose, unlink };\r
591     OCRegisterPersistentStorageHandler(&ps);\r
592 \r
593     /* Initialize OCStack*/\r
594     if (OCInit(NULL, 0, OC_CLIENT_SERVER) != OC_STACK_OK)\r
595     {\r
596         OIC_LOG(ERROR, TAG, "OCStack init error");\r
597         return 0;\r
598     }\r
599 \r
600 //    DeviceDiscovery();\r
601 \r
602     timeout.tv_sec  = 0;\r
603     timeout.tv_nsec = 100000000L;\r
604 \r
605     // Break from loop with Ctrl+C\r
606     OIC_LOG(INFO, TAG, "Entering occlient main loop...");\r
607     signal(SIGINT, handleSigInt);\r
608 \r
609     // CLI\r
610     int thr_id;\r
611     pthread_t p_thread;\r
612     thr_id = pthread_create(&p_thread, NULL, CLInterface, (void *)NULL);\r
613     if (thr_id < 0)\r
614     {\r
615         OIC_LOG(ERROR, TAG, "create CLI Thread error");\r
616         return 0;\r
617     }\r
618 \r
619     // loop\r
620     while (!gQuitFlag)\r
621     {\r
622         if (OCProcess() != OC_STACK_OK)\r
623         {\r
624             OIC_LOG(ERROR, TAG, "OCStack process error");\r
625             return 0;\r
626         }\r
627 \r
628         nanosleep(&timeout, NULL);\r
629     }\r
630     OIC_LOG(INFO, TAG, "Exiting occlient main loop...");\r
631 \r
632     if (OCStop() != OC_STACK_OK)\r
633     {\r
634         OIC_LOG(ERROR, TAG, "OCStack stop error");\r
635     }\r
636 \r
637     return 0;\r
638 }\r