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