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