365c8f662c5064f09529bd430694ee303fd9b951
[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 (IPv4, IPv6, etc)
46 //to be used for sending unicast messages. Default set to IPv4.
47 static OCConnectivityType OC_CONNTYPE = OC_IPV4;
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     uint8_t remoteIpAddr[4];
113     uint16_t remotePortNu;
114
115     if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
116     {
117         OC_LOG(INFO, TAG, "<====Callback Context for PUT received successfully====>");
118     }
119     else
120     {
121         OC_LOG(ERROR, TAG, "<====Callback Context for PUT fail====>");
122     }
123
124     if(clientResponse)
125     {
126         OCDevAddrToIPv4Addr((OCDevAddr *) clientResponse->addr, remoteIpAddr,
127                             remoteIpAddr + 1, remoteIpAddr + 2, remoteIpAddr + 3);
128         OCDevAddrToPort((OCDevAddr *) clientResponse->addr, &remotePortNu);
129
130         OC_LOG_V(INFO, TAG,"PUT Response: %s \nFrom %d.%d.%d.%d:%d\n",
131                  clientResponse->resJSONPayload, remoteIpAddr[0], remoteIpAddr[1],
132                 remoteIpAddr[2], remoteIpAddr[3], remotePortNu);
133     }
134     else
135     {
136         OC_LOG(ERROR, TAG, "<====PUT Callback fail to receive clientResponse====>\n");
137     }
138     return OC_STACK_DELETE_TRANSACTION;
139 }
140
141 OCStackApplicationResult postReqCB(void *ctx, OCDoHandle handle,
142                           OCClientResponse *clientResponse)
143 {
144     uint8_t remoteIpAddr[4];
145     uint16_t remotePortNu;
146
147     if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
148     {
149         OC_LOG(INFO, TAG, "<====Callback Context for POST received successfully====>");
150     }
151     else
152     {
153         OC_LOG(ERROR, TAG, "<====Callback Context for POST fail====>");
154     }
155
156     if(clientResponse)
157     {
158         OCDevAddrToIPv4Addr((OCDevAddr *) clientResponse->addr, remoteIpAddr,
159                             remoteIpAddr + 1, remoteIpAddr + 2, remoteIpAddr + 3);
160         OCDevAddrToPort((OCDevAddr *) clientResponse->addr, &remotePortNu);
161
162         OC_LOG_V(INFO, TAG,"POST Response: %s \nFrom %d.%d.%d.%d:%d\n",
163                     clientResponse->resJSONPayload, remoteIpAddr[0], remoteIpAddr[1],
164                     remoteIpAddr[2], remoteIpAddr[3], remotePortNu);
165     }
166     else
167     {
168         OC_LOG(ERROR, TAG, "<====POST Callback fail to receive clientResponse====>\n");
169     }
170
171     return OC_STACK_DELETE_TRANSACTION;
172 }
173
174 OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle,
175                            OCClientResponse * clientResponse)
176 {
177     uint8_t remoteIpAddr[4];
178     uint16_t remotePortNu;
179
180     if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
181     {
182         OC_LOG(INFO, TAG, "<====Callback Context for GET received successfully====>");
183     }
184     else
185     {
186         OC_LOG(ERROR, TAG, "<====Callback Context for GET fail====>");
187     }
188
189     if (clientResponse)
190     {
191         OCDevAddrToIPv4Addr((OCDevAddr *) clientResponse->addr, remoteIpAddr, remoteIpAddr + 1,
192                 remoteIpAddr + 2, remoteIpAddr + 3);
193         OCDevAddrToPort((OCDevAddr *) clientResponse->addr, &remotePortNu);
194
195         OC_LOG_V(INFO, TAG,"Get Response: %s \nFrom %d.%d.%d.%d:%d\n",
196                 clientResponse->resJSONPayload, remoteIpAddr[0], remoteIpAddr[1],
197                 remoteIpAddr[2], remoteIpAddr[3], remotePortNu);
198
199         if (clientResponse->rcvdVendorSpecificHeaderOptions
200                 && clientResponse->numRcvdVendorSpecificHeaderOptions)
201         {
202             OC_LOG (INFO, TAG, "Received vendor specific options");
203             uint8_t i = 0;
204             OCHeaderOption * rcvdOptions = clientResponse->rcvdVendorSpecificHeaderOptions;
205             for (i = 0; i < clientResponse->numRcvdVendorSpecificHeaderOptions; i++)
206             {
207                 if (((OCHeaderOption) rcvdOptions[i]).protocolID == OC_COAP_ID)
208                 {
209                     OC_LOG_V(INFO, TAG, "Received option with OC_COAP_ID and ID %u with",
210                             ((OCHeaderOption)rcvdOptions[i]).optionID );
211
212                     OC_LOG_BUFFER(INFO, TAG, ((OCHeaderOption)rcvdOptions[i]).optionData,
213                         MAX_HEADER_OPTION_DATA_LENGTH);
214                 }
215             }
216         }
217     }
218     else
219     {
220         OC_LOG(ERROR, TAG, "<====GET Callback fail to receive clientResponse====>\n");
221     }
222     return OC_STACK_DELETE_TRANSACTION;
223 }
224
225 /*
226  * This is a function called back when a device is discovered
227  */
228 OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle,
229         OCClientResponse * clientResponse)
230 {
231     uint8_t remoteIpAddr[4];
232     uint16_t remotePortNu;
233     if (ctx == (void*)DEFAULT_CONTEXT_VALUE)
234     {
235         OC_LOG(INFO, TAG, "\n<====Callback Context for DISCOVERY query "
236                "received successfully====>");
237     }
238     else
239     {
240         OC_LOG(ERROR, TAG, "\n<====Callback Context for DISCOVERY fail====>");
241     }
242
243     if (clientResponse)
244     {
245         OCDevAddrToIPv4Addr((OCDevAddr *) clientResponse->addr, remoteIpAddr,
246                 remoteIpAddr + 1, remoteIpAddr + 2, remoteIpAddr + 3);
247         OCDevAddrToPort((OCDevAddr *) clientResponse->addr, &remotePortNu);
248
249         OC_LOG_V(INFO, TAG,
250                 "Device Discovered %s \n @ %d.%d.%d.%d:%d\n",
251                 clientResponse->resJSONPayload, remoteIpAddr[0], remoteIpAddr[1],
252                 remoteIpAddr[2], remoteIpAddr[3], remotePortNu);
253
254         collectUniqueResource(clientResponse);
255     }
256     else
257     {
258         OC_LOG(ERROR, TAG, "<====DISCOVERY Callback fail to receive clientResponse====>\n");
259     }
260     return (UNICAST_DISCOVERY) ?
261            OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION ;
262 }
263
264 int InitPutRequest(OCQualityOfService qos)
265 {
266     std::ostringstream query;
267     //Get most recently inserted resource
268     const ResourceNode * resource  = getResource();
269
270     if(!resource)
271     {
272         OC_LOG_V(ERROR, TAG, "Resource null, can't do PUT request\n");
273         return -1;
274     }
275     query << "coap://" << resource->ip << ":" << resource->port << resource->uri ;
276     OC_LOG_V(INFO, TAG,"Executing InitPutRequest, Query: %s", query.str().c_str());
277
278     return (InvokeOCDoResource(query, OC_REST_PUT, resource->connType,
279            ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
280             putReqCB, NULL, 0));
281 }
282
283 int InitPostRequest(OCQualityOfService qos)
284 {
285     OCStackResult result;
286     std::ostringstream query;
287     //Get most recently inserted resource
288     const ResourceNode * resource  = getResource();
289
290     if(!resource)
291     {
292         OC_LOG_V(ERROR, TAG, "Resource null, can't do POST request\n");
293         return -1;
294     }
295
296     query << "coap://" << resource->ip << ":" << resource->port << resource->uri ;
297     OC_LOG_V(INFO, TAG,"Executing InitPostRequest, Query: %s", query.str().c_str());
298
299     // First POST operation (to create an LED instance)
300     result = InvokeOCDoResource(query, OC_REST_POST, resource->connType,
301             ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
302             postReqCB, NULL, 0);
303     if (OC_STACK_OK != result)
304     {
305         // Error can happen if for example, network connectivity is down
306         OC_LOG(ERROR, TAG, "First POST call did not succeed");
307     }
308
309     // Second POST operation (to create an LED instance)
310     result = InvokeOCDoResource(query, OC_REST_POST, resource->connType,
311             ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
312             postReqCB, NULL, 0);
313     if (OC_STACK_OK != result)
314     {
315         OC_LOG(ERROR, TAG, "Second POST call did not succeed");
316     }
317
318     // This POST operation will update the original resourced /a/led
319     return (InvokeOCDoResource(query, OC_REST_POST,resource->connType,
320                 ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
321                 postReqCB, NULL, 0));
322 }
323
324 int InitGetRequest(OCQualityOfService qos)
325 {
326     std::ostringstream query;
327     //Get most recently inserted resource
328     const ResourceNode * resource  = getResource();
329
330     if(!resource)
331     {
332         OC_LOG_V(ERROR, TAG, "Resource null, can't do GET request\n");
333         return -1;
334     }
335     query << "coap://" << resource->ip << ":" << resource->port << resource->uri ;
336     OC_LOG_V(INFO, TAG,"Executing InitGetRequest, Query: %s", query.str().c_str());
337
338     return (InvokeOCDoResource(query, OC_REST_GET, resource->connType,
339             (qos == OC_HIGH_QOS)?OC_HIGH_QOS:OC_LOW_QOS, getReqCB, NULL, 0));
340 }
341
342 int InitDiscovery()
343 {
344     OCStackResult ret;
345     OCCallbackData cbData;
346     /* Start a discovery query*/
347     char szQueryUri[64] = {};
348     if (UNICAST_DISCOVERY)
349     {
350         char ipv4addr[IPV4_ADDR_SIZE];
351         printf("Enter IPv4 address of the Server hosting "
352                "resource (Ex: 192.168.0.15)\n");
353         if (fgets(ipv4addr, IPV4_ADDR_SIZE, stdin))
354         {
355             //Strip newline char from ipv4addr
356             StripNewLineChar(ipv4addr);
357             snprintf(szQueryUri, sizeof(szQueryUri), UNICAST_DISCOVERY_QUERY, ipv4addr);
358         }
359         else
360         {
361             OC_LOG(ERROR, TAG, "!! Bad input for IPV4 address. !!");
362             return OC_STACK_INVALID_PARAM;
363         }
364     }
365     else
366     {
367         strcpy(szQueryUri, MULTICAST_RESOURCE_DISCOVERY_QUERY);
368     }
369     cbData.cb = discoveryReqCB;
370     cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
371     cbData.cd = NULL;
372     if (UNICAST_DISCOVERY)
373     {
374         ret = OCDoResource(NULL, OC_REST_GET, szQueryUri, 0, 0, OC_CONNTYPE,
375                 OC_LOW_QOS, &cbData, NULL, 0);
376     }
377     else
378     {
379         ret = OCDoResource(NULL, OC_REST_GET, szQueryUri, 0, 0, (OC_ALL),
380                 OC_LOW_QOS, &cbData, NULL, 0);
381     }
382
383     if (ret != OC_STACK_OK)
384     {
385         OC_LOG(ERROR, TAG, "OCStack resource error");
386     }
387     return ret;
388 }
389
390
391
392 const char * getIPAddr(const OCClientResponse * clientResponse)
393 {
394     uint8_t a, b, c, d;
395    if(!clientResponse || 0 != OCDevAddrToIPv4Addr(clientResponse->addr, &a, &b, &c, &d))
396     {
397         return "";
398     }
399
400     char * ipaddr = NULL;
401     if((ipaddr = (char *) OICCalloc(1, MAX_IP_ADDR_ST_SZ)))
402     {
403         snprintf(ipaddr, MAX_IP_ADDR_ST_SZ, "%d.%d.%d.%d", a,b,c,d);
404     }
405     else
406     {
407         OC_LOG(ERROR, TAG, "Memory not allocated to ipaddr");
408     }
409     return ipaddr;
410 }
411
412 const char * getPort(const OCClientResponse * clientResponse)
413 {
414     uint16_t p = 0;
415     if(!clientResponse || 0 != OCDevAddrToPort(clientResponse->addr, &p) )
416     {
417         return "";
418     }
419
420     char * port = NULL;
421     if((port = (char *) OICCalloc(1, MAX_PORT_ST_SZ)))
422     {
423         snprintf(port, MAX_PORT_ST_SZ, "%d", p);
424     }
425     else
426     {
427         OC_LOG(ERROR, TAG, "Memory not allocated to port");
428     }
429     return port;
430 }
431
432 int parseJSON(const char * resJSONPayload, char ** sid_c,
433               char *** uri_c, int * totalRes)
434 {
435     cJSON * root = NULL;
436     cJSON * oc = NULL;
437
438     root = cJSON_Parse((char *)(resJSONPayload));
439
440     if (!root)
441     {
442         OC_LOG(ERROR, TAG, "JSON Parsing Error");
443         return OC_STACK_INVALID_JSON;
444     }
445
446     oc = cJSON_GetObjectItem(root,"oic");
447     if (!oc)
448     {
449         OC_LOG(ERROR, TAG, "Invalid JSON : Missing oc object");
450         return OC_STACK_INVALID_JSON;
451     }
452
453     * totalRes = cJSON_GetArraySize(oc);
454
455     if(oc->type == cJSON_Array)
456     {
457         cJSON * resource = cJSON_GetArrayItem(oc, 0);
458
459         if(!resource)
460         {
461             return OC_STACK_INVALID_JSON;
462         }
463
464         if (cJSON_GetObjectItem(resource, "sid"))
465         {
466             char * sid = cJSON_GetObjectItem(resource, "sid")->valuestring;
467             if((* sid_c = (char *)OICCalloc(1, strlen (sid) + 1)))
468             {
469                 memcpy(* sid_c, sid, strlen(sid) + 1);
470             }
471             else
472             {
473                 OC_LOG(ERROR, TAG, "Memory not allocated to sid");
474                 return OC_STACK_NO_MEMORY;
475             }
476         }
477         else
478         {
479             OC_LOG(ERROR, TAG, "Invalid JSON : Missing sid object");
480             return OC_STACK_INVALID_JSON;
481         }
482
483         if(!(* uri_c =  (char ** )OICMalloc ((* totalRes) * sizeof(char *))))
484         {
485             OC_LOG(ERROR, TAG, "Memory not allocated to uri_c array");
486             return OC_STACK_NO_MEMORY;
487         }
488
489         int i = 0;
490
491         while(true)
492         {
493             if (cJSON_GetObjectItem(resource, "href"))
494             {
495                 char *uri= cJSON_GetObjectItem(resource, "href")->valuestring;
496                 if(((*uri_c)[i] = (char *)OICCalloc(1, strlen (uri) + 1)))
497                 {
498                     memcpy((*uri_c)[i], uri, strlen(uri) + 1);
499                 }
500                 else
501                 {
502                     OC_LOG(ERROR, TAG, "Memory not allocated to uri");
503                     return OC_STACK_NO_MEMORY;
504                 }
505                 i++;
506                 if(i >= (* totalRes))
507                     break;
508                 resource = cJSON_GetArrayItem(oc, i);
509             }
510             else
511             {
512                OC_LOG(ERROR, TAG, "Invalid JSON : Missing uri object");
513                return OC_STACK_INVALID_JSON;
514            }
515         }
516     }
517     else
518     {
519         return OC_STACK_INVALID_JSON;
520         OC_LOG(ERROR, TAG, "Invalid JSON : oc object type is not an array");
521     }
522     return OC_STACK_OK;
523 }
524
525 void queryResource()
526 {
527     printf("\n");
528     switch(TEST_CASE)
529     {
530         case TEST_DISCOVER_REQ:
531             break;
532         case TEST_NON_CON_OP:
533             InitGetRequest(OC_LOW_QOS);
534             InitPutRequest(OC_LOW_QOS);
535             InitPostRequest(OC_LOW_QOS);
536             break;
537         case TEST_CON_OP:
538             InitGetRequest(OC_HIGH_QOS);
539             InitPutRequest(OC_HIGH_QOS);
540             InitPostRequest(OC_HIGH_QOS);
541             break;
542         default:
543             PrintUsage();
544             break;
545     }
546     printf("\n");
547 }
548
549
550 void collectUniqueResource(const OCClientResponse * clientResponse)
551 {
552     char * sid = NULL;
553     char ** uri = NULL;
554     int totalRes = 0;
555     int i;
556
557     if(parseJSON(clientResponse->resJSONPayload, & sid, & uri, &totalRes)
558             != OC_STACK_OK)
559     {
560         OC_LOG(ERROR, TAG, "Error while parsing JSON payload in OCClientResponse");
561
562         OICFree(sid);
563         for (i = 0; i < totalRes; i++)
564         {
565             OICFree(uri[i]);
566         }
567         OICFree(uri);
568
569        return;
570     }
571
572     for(i = 0; i < totalRes; i++)
573     {
574         if(insertResource(sid, uri[i], clientResponse) == 1)
575         {
576             printf("%s%s%s%s\n",sid, ":", uri[i], " is new");
577             printResourceList();
578             queryResource();
579         }
580         else
581         {
582             printf("%s%s%s%s\n\n",sid, ":", uri[i], " has been seen before");
583         }
584     }
585
586     OICFree(sid);
587     for (i = 0; i < totalRes; i++)
588     {
589         OICFree(uri[i]);
590     }
591     OICFree(uri);
592 }
593
594 /* This function searches for the resource(sid:uri) in the ResourceList.
595  * If the Resource is found in the list then it returns 0 else insert
596  * the resource to front of the list and returns 1.
597  */
598 int insertResource(const char * sid, char const * uri,
599             const OCClientResponse * clientResponse)
600 {
601     ResourceNode * iter = resourceList;
602     char * sid_cpy =  OICStrdup(sid);
603     char * uri_cpy = OICStrdup(uri);
604
605     //Checking if the resource(sid:uri) is new
606     while(iter)
607     {
608         if((strcmp(iter->sid, sid) == 0) && (strcmp(iter->uri, uri) == 0))
609         {
610             OICFree(sid_cpy);
611             OICFree(uri_cpy);
612             return 0;
613         }
614         else
615         {
616             iter = iter->next;
617         }
618     }
619
620     //Creating new ResourceNode
621     if((iter = (ResourceNode *) OICMalloc(sizeof(ResourceNode))))
622     {
623         iter->sid = sid_cpy;
624         iter->uri = uri_cpy;
625         iter->ip = getIPAddr(clientResponse);
626         iter->port = getPort(clientResponse);
627         iter->connType = clientResponse->connType;
628         iter->next = NULL;
629     }
630     else
631     {
632         OC_LOG(ERROR, TAG, "Memory not allocated to ResourceNode");
633         OICFree(sid_cpy);
634         OICFree(uri_cpy);
635         return -1;
636     }
637
638     //Adding new ResourceNode to front of the ResourceList
639     if(!resourceList)
640     {
641         resourceList = iter;
642     }
643     else
644     {
645         iter->next = resourceList;
646         resourceList = iter;
647     }
648     return 1;
649 }
650
651 void printResourceList()
652 {
653     ResourceNode * iter;
654     iter = resourceList;
655     printf("\nResource List\n");
656     while(iter)
657     {
658         printf("*****************************************************\n");
659         printf("sid = %s \n",iter->sid);
660         printf("uri = %s\n", iter->uri);
661         printf("ip = %s\n", iter->ip);
662         printf("port = %s\n", iter->port);
663         switch (iter->connType)
664         {
665             case OC_IPV4:
666                 printf("connType = %s\n","IPv4");
667                 break;
668             case OC_IPV6:
669                 // TODO: Allow IPv6 when support is added
670                 printf("IPv6 not currently supported, default to IPv4\n");
671                 //printf("connType = %s\n","IPv6");
672                 printf("connType = %s\n","IPv4");
673                 break;
674             case OC_LE:
675                 printf("connType = %s\n","BLE");
676                 break;
677             case OC_EDR:
678                 printf("connType = %s\n","BT");
679                 break;
680             case OC_ALL:
681             default:
682                 printf("connType = %s\n","Invalid connType");
683                 break;
684         }
685         printf("*****************************************************\n");
686         iter = iter->next;
687     }
688 }
689
690 void freeResourceList()
691 {
692     OC_LOG(INFO, TAG, "Freeing ResourceNode List");
693     ResourceNode * temp;
694     while(resourceList)
695     {
696         temp = resourceList;
697         resourceList = resourceList->next;
698         OICFree((void *)temp->sid);
699         OICFree((void *)temp->uri);
700         OICFree((void *)temp->ip);
701         OICFree((void *)temp->port);
702         OICFree(temp);
703     }
704     resourceList = NULL;
705 }
706
707 int main(int argc, char* argv[])
708 {
709     int opt;
710     resourceList = NULL;
711     while ((opt = getopt(argc, argv, "u:t:c:")) != -1)
712     {
713         switch(opt)
714         {
715             case 'u':
716                 UNICAST_DISCOVERY = atoi(optarg);
717                 break;
718             case 't':
719                 TEST_CASE = atoi(optarg);
720                 break;
721             case 'c':
722                 // TODO: re-enable IPv4/IPv6 command line selection when IPv6 is supported
723                 // OC_CONNTYPE = OCConnectivityType(atoi(optarg));
724                 OC_CONNTYPE = OC_IPV4;
725                 OC_LOG(INFO, TAG, "Using default IPv4, IPv6 not currently supported.");
726                 break;
727             default:
728                 PrintUsage();
729                 return -1;
730         }
731     }
732
733     if ((UNICAST_DISCOVERY != 0 && UNICAST_DISCOVERY != 1) ||
734             (TEST_CASE < TEST_DISCOVER_REQ || TEST_CASE >= MAX_TESTS) )
735     {
736         PrintUsage();
737         return -1;
738     }
739
740     /* Initialize OCStack*/
741     if (OCInit(NULL, 0, OC_CLIENT) != OC_STACK_OK)
742     {
743         OC_LOG(ERROR, TAG, "OCStack init error");
744         return 0;
745     }
746
747     InitDiscovery();
748
749     // Break from loop with Ctrl+C
750     signal(SIGINT, handleSigInt);
751
752     while (!gQuitFlag)
753     {
754         if (OCProcess() != OC_STACK_OK)
755         {
756             OC_LOG(ERROR, TAG, "OCStack process error");
757             return 0;
758         }
759         sleep(2);
760     }
761
762     freeResourceList();
763     OC_LOG(INFO, TAG, "Exiting occlient main loop...");
764     if (OCStop() != OC_STACK_OK)
765     {
766         OC_LOG(ERROR, TAG, "OCStack stop error");
767     }
768     return 0;
769 }
770
771