Merge master to cloud-interface branch
[platform/upstream/iotivity.git] / resource / csdk / stack / samples / linux / SimpleClientServer / occlientslow.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 <iostream>
27 #include <sstream>
28 #include "ocstack.h"
29 #include "logger.h"
30 #include "occlientslow.h"
31 #include "oic_string.h"
32 #include "ocpayload.h"
33 #include "payload_logging.h"
34
35 // Tracking user input
36 static int UnicastDiscovery = 0;
37 static int TestCase = 0;
38 static int ConnectivityType = 0;
39
40 static std::string coapServerResource = "/a/led";
41
42 //The following variable determines the interface protocol (IP, etc)
43 //to be used for sending unicast messages. Default set to IP.
44 static OCConnectivityType AdapterType = CT_ADAPTER_IP;
45 static OCDevAddr endpoint;
46 static const char *RESOURCE_DISCOVERY_QUERY = "%s/oic/res";
47 void StripNewLineChar(char* str);
48
49 int gQuitFlag = 0;
50
51 /* SIGINT handler: set gQuitFlag to 1 for graceful termination */
52 void handleSigInt(int signum)
53 {
54     if (signum == SIGINT)
55     {
56         gQuitFlag = 1;
57     }
58 }
59
60 static void PrintUsage()
61 {
62     OC_LOG(INFO, TAG, "Usage : occlient -c <0|1> -u <0|1> -t <1|2|3>");
63     OC_LOG(INFO, TAG, "-c 0 : Default auto-selection");
64     OC_LOG(INFO, TAG, "-c 1 : IP Connectivity Type");
65     OC_LOG(INFO, TAG, "-u <0|1> : Perform multicast/unicast discovery of resources");
66     OC_LOG(INFO, TAG, "-t 1 : Discover Resources");
67     OC_LOG(INFO, TAG, "-t 2 : Discover Resources and Initiate Nonconfirmable Get Request");
68     OC_LOG(INFO, TAG, "-t 3 : Discover Resources and Initiate Confirmable Get Request");
69     OC_LOG(INFO, TAG, "-t 4 : Discover Resources and Initiate NonConfirmable Put Request");
70     OC_LOG(INFO, TAG, "-t 5 : Discover Resources and Initiate Confirmable Put Request");
71 }
72
73 OCPayload* putPayload()
74 {
75     OCRepPayload* payload = OCRepPayloadCreate();
76
77     if(!payload)
78     {
79         std::cout << "Failed to create put payload object"<<std::endl;
80         std::exit(1);
81     }
82
83     OCRepPayloadSetPropInt(payload, "power", 15);
84     OCRepPayloadSetPropBool(payload, "state", true);
85
86     return (OCPayload*) payload;
87 }
88
89 OCStackResult InvokeOCDoResource(std::ostringstream &query,
90         OCMethod method, OCDevAddr *dest, OCQualityOfService qos,
91         OCClientResponseHandler cb, OCHeaderOption * options, uint8_t numOptions)
92 {
93     OCStackResult ret;
94     OCCallbackData cbData;
95
96     cbData.cb = cb;
97     cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
98     cbData.cd = NULL;
99
100     ret = OCDoResource(NULL, method, query.str().c_str(), dest,
101             (method == OC_REST_PUT) ? putPayload() : NULL,
102             AdapterType, qos, &cbData, options, numOptions);
103
104     if (ret != OC_STACK_OK)
105     {
106         OC_LOG_V(ERROR, TAG, "OCDoResource returns error %d with method %d", ret, method);
107     }
108
109     return ret;
110 }
111
112 OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse)
113 {
114     if(clientResponse == NULL)
115     {
116         OC_LOG(INFO, TAG, "The clientResponse is NULL");
117         return   OC_STACK_DELETE_TRANSACTION;
118     }
119     if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
120     {
121         OC_LOG(INFO, TAG, "Callback Context for GET query recvd successfully");
122     }
123
124     OC_LOG_V(INFO, TAG, "StackResult: %s",  getResult(clientResponse->result));
125     OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
126     OC_LOG(INFO, TAG, "Get Response =============> ");
127     OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
128
129     if(clientResponse->rcvdVendorSpecificHeaderOptions &&
130             clientResponse->numRcvdVendorSpecificHeaderOptions)
131     {
132         OC_LOG (INFO, TAG, "Received vendor specific options");
133         uint8_t i = 0;
134         OCHeaderOption * rcvdOptions = clientResponse->rcvdVendorSpecificHeaderOptions;
135         for( i = 0; i < clientResponse->numRcvdVendorSpecificHeaderOptions; i++)
136         {
137             if(((OCHeaderOption)rcvdOptions[i]).protocolID == OC_COAP_ID)
138             {
139                 OC_LOG_V(INFO, TAG, "Received option with OC_COAP_ID and ID %u with",
140                         ((OCHeaderOption)rcvdOptions[i]).optionID );
141
142                 OC_LOG_BUFFER(INFO, TAG, ((OCHeaderOption)rcvdOptions[i]).optionData,
143                     MAX_HEADER_OPTION_DATA_LENGTH);
144             }
145         }
146     }
147     return OC_STACK_DELETE_TRANSACTION;
148 }
149
150 // This is a function called back when a device is discovered
151 OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle,
152         OCClientResponse * clientResponse)
153 {
154     if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
155     {
156         OC_LOG(INFO, TAG, "Callback Context for DISCOVER query recvd successfully");
157     }
158
159     if (clientResponse)
160     {
161         OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
162
163         OC_LOG_V(INFO, TAG, "Discovered @ %s:%u =============> ",
164             clientResponse->devAddr.addr, clientResponse->devAddr.port);
165         OC_LOG_PAYLOAD (INFO, TAG, clientResponse->payload);
166
167         endpoint = clientResponse->devAddr;
168
169         switch(TestCase)
170         {
171             case TEST_NON_CON_OP:
172                 InitGetRequest(OC_LOW_QOS);
173                 break;
174             case TEST_CON_OP:
175                 InitGetRequest(OC_HIGH_QOS);
176                 break;
177             case TEST_NON_CON_PUT:
178                 InitPutRequest(OC_LOW_QOS);
179                 break;
180             case TEST_CON_PUT:
181                 InitPutRequest(OC_HIGH_QOS);
182                 break;
183             default:
184                 PrintUsage();
185                 break;
186         }
187     }
188
189     return UnicastDiscovery ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION ;
190
191 }
192
193 int InitGetRequest(OCQualityOfService qos)
194 {
195     OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
196     std::ostringstream query;
197     query << coapServerResource;
198     OC_LOG_V (INFO, TAG, "Performing GET with query : %s", query.str().c_str());
199     return (InvokeOCDoResource(query, OC_REST_GET, &endpoint,
200                                (qos == OC_HIGH_QOS)? OC_HIGH_QOS : OC_LOW_QOS,
201                                getReqCB, NULL, 0));
202 }
203
204 int InitPutRequest(OCQualityOfService qos)
205 {
206     OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
207     std::ostringstream query;
208     query << coapServerResource;
209     OC_LOG_V (INFO, TAG, "Performing PUT with query : %s", query.str().c_str());
210     return (InvokeOCDoResource(query, OC_REST_PUT, &endpoint,
211                                (qos == OC_HIGH_QOS)?  OC_HIGH_QOS:OC_LOW_QOS,
212                                getReqCB, NULL, 0));
213 }
214
215 int InitDiscovery()
216 {
217     OCStackResult ret;
218     OCCallbackData cbData;
219     char queryUri[200];
220     char ipaddr[100] = { '\0' };
221
222     if (UnicastDiscovery)
223     {
224         OC_LOG(INFO, TAG, "Enter IP address (with optional port) of the Server hosting resource\n");
225         OC_LOG(INFO, TAG, "IPv4: 192.168.0.15:45454\n");
226         OC_LOG(INFO, TAG, "IPv6: [fe80::20c:29ff:fe1b:9c5]:45454\n");
227
228         if (fgets(ipaddr, sizeof (ipaddr), stdin))
229         {
230             StripNewLineChar(ipaddr); //Strip newline char from ipaddr
231         }
232         else
233         {
234             OC_LOG(ERROR, TAG, "!! Bad input for IP address. !!");
235             return OC_STACK_INVALID_PARAM;
236         }
237     }
238
239     snprintf(queryUri, sizeof (queryUri), RESOURCE_DISCOVERY_QUERY, ipaddr);
240
241     cbData.cb = discoveryReqCB;
242     cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
243     cbData.cd = NULL;
244
245     ret = OCDoResource(NULL, OC_REST_DISCOVER, queryUri, 0, 0, CT_DEFAULT,
246                        OC_LOW_QOS, &cbData, NULL, 0);
247     if (ret != OC_STACK_OK)
248     {
249         OC_LOG(ERROR, TAG, "OCStack resource error");
250     }
251     return ret;
252 }
253
254 int main(int argc, char* argv[])
255 {
256     int opt;
257
258     while ((opt = getopt(argc, argv, "u:t:c:")) != -1)
259     {
260         switch(opt)
261         {
262             case 'u':
263                 UnicastDiscovery = atoi(optarg);
264                 break;
265             case 't':
266                 TestCase = atoi(optarg);
267                 break;
268             case 'c':
269                 ConnectivityType = atoi(optarg);
270                 break;
271             default:
272                 PrintUsage();
273                 return -1;
274         }
275     }
276
277     if ((UnicastDiscovery != 0 && UnicastDiscovery != 1) ||
278             (TestCase < TEST_DISCOVER_REQ || TestCase >= MAX_TESTS) ||
279             (ConnectivityType < CT_ADAPTER_DEFAULT || ConnectivityType >= MAX_CT))
280     {
281         PrintUsage();
282         return -1;
283     }
284
285     /* Initialize OCStack*/
286     if (OCInit(NULL, 0, OC_CLIENT) != OC_STACK_OK)
287     {
288         OC_LOG(ERROR, TAG, "OCStack init error");
289         return 0;
290     }
291
292     if(ConnectivityType == CT_ADAPTER_DEFAULT || ConnectivityType == CT_IP)
293     {
294         AdapterType = CT_ADAPTER_IP;
295     }
296     else
297     {
298         OC_LOG(INFO, TAG, "Default Connectivity type selected...");
299         AdapterType = CT_ADAPTER_IP;
300     }
301
302     InitDiscovery();
303
304     // Break from loop with Ctrl+C
305     OC_LOG(INFO, TAG, "Entering occlient main loop...");
306     signal(SIGINT, handleSigInt);
307     while (!gQuitFlag)
308     {
309         if (OCProcess() != OC_STACK_OK)
310         {
311             OC_LOG(ERROR, TAG, "OCStack process error");
312             return 0;
313         }
314
315         sleep(2);
316     }
317     OC_LOG(INFO, TAG, "Exiting occlient main loop...");
318
319     if (OCStop() != OC_STACK_OK)
320     {
321         OC_LOG(ERROR, TAG, "OCStack stop error");
322     }
323
324     return 0;
325 }
326
327 std::string getQueryStrForGetPut(OCClientResponse * clientResponse)
328 {
329     return "/a/led";
330 }
331