Merge branch 'resource-container'
[platform/upstream/iotivity.git] / resource / csdk / stack / samples / linux / SimpleClientServer / occlientcoll.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 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <signal.h>
25 #include <unistd.h>
26 #include <ocstack.h>
27 #include <iostream>
28 #include <sstream>
29 #include "ocpayload.h"
30 #include "payload_logging.h"
31 #include "logger.h"
32 const char *getResult(OCStackResult result);
33 std::string getQueryStrForGetPut();
34
35 #define TAG ("occlient")
36 #define DEFAULT_CONTEXT_VALUE 0x99
37 #ifndef MAX_LENGTH_IPv4_ADDR
38 #define MAX_LENGTH_IPv4_ADDR 16
39 #endif
40
41 typedef enum
42 {
43     TEST_INVALID = 0,
44     TEST_GET_DEFAULT,
45     TEST_GET_BATCH,
46     TEST_GET_LINK_LIST,
47     TEST_PUT_DEFAULT,
48     TEST_PUT_BATCH,
49     TEST_PUT_LINK_LIST,
50     TEST_UNKNOWN_RESOURCE_GET_DEFAULT,
51     TEST_UNKNOWN_RESOURCE_GET_BATCH,
52     TEST_UNKNOWN_RESOURCE_GET_LINK_LIST,
53     MAX_TESTS
54 } CLIENT_TEST;
55
56 /**
57  * List of connectivity types that can be initiated from the client
58  * Required for user input validation
59  */
60 typedef enum {
61     CT_ADAPTER_DEFAULT = 0,
62     CT_IP,
63     MAX_CT
64 } CLIENT_ConnectivityType_TYPE;
65
66 unsigned static int TestType = TEST_INVALID;
67 unsigned static int ConnectivityType = 0;
68
69 typedef struct
70 {
71     char text[30];
72     CLIENT_TEST test;
73 } testToTextMap;
74
75 testToTextMap queryInterface[] = {
76         {"invalid", TEST_INVALID},
77         {"?if=oic.if.baseline", TEST_GET_DEFAULT},
78         {"?if=oic.if.b", TEST_GET_BATCH},
79         {"?if=oic.if.ll", TEST_GET_LINK_LIST},
80         {"?if=oic.if.baseline", TEST_UNKNOWN_RESOURCE_GET_DEFAULT},
81         {"?if=oic.if.b", TEST_UNKNOWN_RESOURCE_GET_BATCH},
82         {"?if=oic.if.ll", TEST_UNKNOWN_RESOURCE_GET_LINK_LIST},
83         {"?if=oic.if.baseline", TEST_PUT_DEFAULT},
84         {"?if=oic.if.b", TEST_PUT_BATCH},
85         {"?if=oic.if.ll", TEST_PUT_LINK_LIST},
86 };
87
88
89 //The following variable determines the interface protocol (IP, etc)
90 //to be used for sending unicast messages. Default set to IP.
91 static OCConnectivityType ConnType = CT_ADAPTER_IP;
92 static const char * RESOURCE_DISCOVERY_QUERY = "/oic/res";
93
94 // The handle for the observe registration
95 OCDoHandle gObserveDoHandle;
96 // After this crosses a threshold client deregisters for further observations
97 int gNumObserveNotifies = 1;
98
99 int gQuitFlag = 0;
100 /* SIGINT handler: set gQuitFlag to 1 for graceful termination */
101 void handleSigInt(int signum)
102 {
103     if (signum == SIGINT)
104     {
105         gQuitFlag = 1;
106     }
107 }
108
109 // Forward Declaration
110 OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse);
111 int InitGetRequestToUnavailableResource(OCClientResponse * clientResponse);
112 int InitObserveRequest(OCClientResponse * clientResponse);
113 int InitPutRequest(OCClientResponse * clientResponse);
114 int InitGetRequest(OCClientResponse * clientResponse);
115 int InitDiscovery();
116
117 OCPayload* putPayload()
118 {
119     OCRepPayload* payload = OCRepPayloadCreate();
120
121     if(!payload)
122     {
123         std::cout << "Failed to create put payload object"<<std::endl;
124         std::exit(1);
125     }
126
127     OCRepPayloadSetPropInt(payload, "power", 15);
128     OCRepPayloadSetPropBool(payload, "state", true);
129
130     return (OCPayload*) payload;
131 }
132
133 void PrintUsage()
134 {
135     OIC_LOG(INFO, TAG, "Usage : occlientcoll -t <Test Case> -c <CA connectivity Type>");
136     OIC_LOG(INFO, TAG, "-c 0 : Default auto-selection");
137     OIC_LOG(INFO, TAG, "-c 1 : IP Connectivity Type");
138     OIC_LOG(INFO, TAG, "Test Case 1 : Discover Resources && Initiate GET Request on an "\
139             "available resource using default interface.");
140     OIC_LOG(INFO, TAG, "Test Case 2 : Discover Resources && Initiate GET Request on an "\
141                  "available resource using batch interface.");
142     OIC_LOG(INFO, TAG, "Test Case 3 : Discover Resources && Initiate GET Request on an "\
143                  "available resource using link list interface.");
144     OIC_LOG(INFO, TAG, "Test Case 4 : Discover Resources && Initiate GET & PUT Request on an "\
145                  "available resource using default interface.");
146     OIC_LOG(INFO, TAG, "Test Case 5 : Discover Resources && Initiate GET & PUT Request on an "\
147                  "available resource using batch interface.");
148     OIC_LOG(INFO, TAG, "Test Case 6 : Discover Resources && Initiate GET & PUT Request on an "\
149                  "available resource using link list interface.");
150     OIC_LOG(INFO, TAG, "Test Case 7 : Discover Resources && Initiate GET Request on an "\
151                  "unavailable resource using default interface.");
152     OIC_LOG(INFO, TAG, "Test Case 8 : Discover Resources && Initiate GET Request on an "\
153                  "unavailable resource using batch interface.");
154     OIC_LOG(INFO, TAG, "Test Case 9 : Discover Resources && Initiate GET Request on an "\
155                  "unavailable resource using link list interface.");
156 }
157
158 OCStackApplicationResult putReqCB(void* ctx, OCDoHandle /*handle*/,
159                                   OCClientResponse * clientResponse)
160 {
161     if(clientResponse == NULL)
162     {
163         OIC_LOG(INFO, TAG, "The clientResponse is NULL");
164         return   OC_STACK_DELETE_TRANSACTION;
165     }
166     if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
167     {
168         OIC_LOG_V(INFO, TAG, "Callback Context for PUT query recvd successfully");
169         OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
170     }
171
172     return OC_STACK_KEEP_TRANSACTION;
173 }
174
175 OCStackApplicationResult getReqCB(void* ctx, OCDoHandle /*handle*/,
176                                   OCClientResponse * clientResponse)
177 {
178     OIC_LOG_V(INFO, TAG, "StackResult: %s",
179             getResult(clientResponse->result));
180     if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
181     {
182         OIC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
183         if(clientResponse->sequenceNumber == 0)
184         {
185             OIC_LOG_V(INFO, TAG, "Callback Context for GET query recvd successfully");
186             OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
187         }
188         else
189         {
190             OIC_LOG_V(INFO, TAG, "Callback Context for Get recvd successfully %d",
191                     gNumObserveNotifies);
192             OIC_LOG_PAYLOAD(INFO, clientResponse->payload);;
193             gNumObserveNotifies++;
194             if (gNumObserveNotifies == 3)
195             {
196                 if (OCCancel (gObserveDoHandle, OC_LOW_QOS, NULL, 0) != OC_STACK_OK)
197                 {
198                     OIC_LOG(ERROR, TAG, "Observe cancel error");
199                 }
200             }
201         }
202     }
203     if(TestType == TEST_PUT_DEFAULT || TestType == TEST_PUT_BATCH || TestType == TEST_PUT_LINK_LIST)
204     {
205         InitPutRequest(clientResponse);
206     }
207     return OC_STACK_KEEP_TRANSACTION;
208 }
209
210 // This is a function called back when a device is discovered
211 OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle /*handle*/,
212                                         OCClientResponse * clientResponse)
213 {
214     OIC_LOG(INFO, TAG,
215             "Entering discoveryReqCB (Application Layer CB)");
216     OIC_LOG_V(INFO, TAG, "StackResult: %s",
217             getResult(clientResponse->result));
218
219     if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
220     {
221         OIC_LOG_V(INFO, TAG, "Callback Context recvd successfully");
222     }
223
224     OIC_LOG_V(INFO, TAG,
225             "Device =============> Discovered @ %s:%d",
226             clientResponse->devAddr.addr,
227             clientResponse->devAddr.port);
228     OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
229
230     ConnType = clientResponse->connType;
231
232     if(TestType == TEST_UNKNOWN_RESOURCE_GET_DEFAULT || TestType == TEST_UNKNOWN_RESOURCE_GET_BATCH ||\
233             TestType == TEST_UNKNOWN_RESOURCE_GET_LINK_LIST)
234     {
235         InitGetRequestToUnavailableResource(clientResponse);
236     }
237     else
238     {
239         InitGetRequest(clientResponse);
240     }
241     return OC_STACK_KEEP_TRANSACTION;
242 }
243
244
245 int InitGetRequestToUnavailableResource(OCClientResponse * clientResponse)
246 {
247     OCStackResult ret;
248     OCCallbackData cbData;
249     std::ostringstream getQuery;
250     getQuery << "/SomeUnknownResource";
251     cbData.cb = getReqCB;
252     cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
253     cbData.cd = NULL;
254
255     ret = OCDoResource(NULL, OC_REST_GET, getQuery.str().c_str(),
256                        &clientResponse->devAddr, 0, ConnType, OC_LOW_QOS,
257                        &cbData, NULL, 0);
258     if (ret != OC_STACK_OK)
259     {
260         OIC_LOG(ERROR, TAG, "OCStack resource error");
261     }
262     return ret;
263 }
264
265
266 int InitObserveRequest(OCClientResponse * clientResponse)
267 {
268     OCStackResult ret;
269     OCCallbackData cbData;
270     OCDoHandle handle;
271     std::ostringstream obsReg;
272     obsReg << getQueryStrForGetPut();
273     cbData.cb = getReqCB;
274     cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
275     cbData.cd = NULL;
276     OIC_LOG_V(INFO, TAG, "OBSERVE payload from client =");
277     OCPayload* payload = putPayload();
278     OIC_LOG_PAYLOAD(INFO, payload);
279     OCPayloadDestroy(payload);
280
281     ret = OCDoResource(&handle, OC_REST_OBSERVE, obsReg.str().c_str(),
282                        &clientResponse->devAddr, 0, ConnType,
283                        OC_LOW_QOS, &cbData, NULL, 0);
284     if (ret != OC_STACK_OK)
285     {
286         OIC_LOG(ERROR, TAG, "OCStack resource error");
287     }
288     else
289     {
290         gObserveDoHandle = handle;
291     }
292     return ret;
293 }
294
295
296 int InitPutRequest(OCClientResponse * clientResponse)
297 {
298     OCStackResult ret;
299     OCCallbackData cbData;
300     //* Make a PUT query*/
301     std::ostringstream getQuery;
302     getQuery << "coap://" << clientResponse->devAddr.addr << ":" <<
303             clientResponse->devAddr.port <<
304             "/a/room" << queryInterface[TestType].text;
305     cbData.cb = putReqCB;
306     cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
307     cbData.cd = NULL;
308     OIC_LOG_V(INFO, TAG, "PUT payload from client = ");
309     OCPayload* payload = putPayload();
310     OIC_LOG_PAYLOAD(INFO, payload);
311     OCPayloadDestroy(payload);
312
313     ret = OCDoResource(NULL, OC_REST_PUT, getQuery.str().c_str(),
314                        &clientResponse->devAddr, putPayload(), ConnType,
315                        OC_LOW_QOS, &cbData, NULL, 0);
316     if (ret != OC_STACK_OK)
317     {
318         OIC_LOG(ERROR, TAG, "OCStack resource error");
319     }
320     return ret;
321 }
322
323
324 int InitGetRequest(OCClientResponse * clientResponse)
325 {
326     OCStackResult ret;
327     OCCallbackData cbData;
328
329     //* Make a GET query*/
330     std::ostringstream getQuery;
331     getQuery << "/a/room" << queryInterface[TestType].text;
332
333     std::cout << "Get Query: " << getQuery.str() << std::endl;
334
335     cbData.cb = getReqCB;
336     cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
337     cbData.cd = NULL;
338     ret = OCDoResource(NULL, OC_REST_GET, getQuery.str().c_str(),
339                        &clientResponse->devAddr, 0, ConnType, OC_LOW_QOS,
340                        &cbData, NULL, 0);
341     if (ret != OC_STACK_OK)
342     {
343         OIC_LOG(ERROR, TAG, "OCStack resource error");
344     }
345     return ret;
346 }
347
348 int InitDiscovery()
349 {
350     OCStackResult ret;
351     OCCallbackData cbData;
352     /* Start a discovery query*/
353     char szQueryUri[64] = { 0 };
354
355     strcpy(szQueryUri, RESOURCE_DISCOVERY_QUERY);
356
357     cbData.cb = discoveryReqCB;
358     cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
359     cbData.cd = NULL;
360     ret = OCDoResource(NULL, OC_REST_DISCOVER, szQueryUri, NULL, 0, ConnType,
361                         OC_LOW_QOS,
362             &cbData, NULL, 0);
363     if (ret != OC_STACK_OK)
364     {
365         OIC_LOG(ERROR, TAG, "OCStack resource error");
366     }
367     return ret;
368 }
369
370 int main(int argc, char* argv[])
371 {
372     int opt;
373
374     while ((opt = getopt(argc, argv, "t:c:")) != -1)
375     {
376         switch (opt)
377         {
378             case 't':
379                 TestType = atoi(optarg);
380                 break;
381             case 'c':
382                 ConnectivityType = atoi(optarg);
383                 break;
384             default:
385                 PrintUsage();
386                 return -1;
387         }
388     }
389     if ((TestType <= TEST_INVALID || TestType >= MAX_TESTS) ||
390         ConnectivityType >= MAX_CT)
391     {
392         PrintUsage();
393         return -1;
394     }
395
396     /* Initialize OCStack*/
397     if (OCInit(NULL, 0, OC_CLIENT) != OC_STACK_OK)
398     {
399         OIC_LOG(ERROR, TAG, "OCStack init error");
400         return 0;
401     }
402
403     if(ConnectivityType == CT_ADAPTER_DEFAULT || ConnectivityType == CT_IP)
404     {
405         ConnType = CT_ADAPTER_IP;
406     }
407     else
408     {
409         OIC_LOG(INFO, TAG, "Default Connectivity type selected...");
410         ConnType = CT_ADAPTER_IP;
411     }
412
413     InitDiscovery();
414
415     // Break from loop with Ctrl+C
416     OIC_LOG(INFO, TAG, "Entering occlient main loop...");
417     signal(SIGINT, handleSigInt);
418     while (!gQuitFlag)
419     {
420
421         if (OCProcess() != OC_STACK_OK)
422         {
423             OIC_LOG(ERROR, TAG, "OCStack process error");
424             return 0;
425         }
426
427         sleep(2);
428     } OIC_LOG(INFO, TAG, "Exiting occlient main loop...");
429
430     if (OCStop() != OC_STACK_OK)
431     {
432         OIC_LOG(ERROR, TAG, "OCStack stop error");
433     }
434
435     return 0;
436 }
437
438 std::string getQueryStrForGetPut()
439 {
440     return "/a/room";
441 }
442