1 //******************************************************************
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
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
11 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
30 #include "occlientbasicops.h"
34 #define TAG "occlientbasicops"
35 static int UNICAST_DISCOVERY = 0;
36 static int TEST_CASE = 0;
38 static int IPV4_ADDR_SIZE = 16;
39 static char UNICAST_DISCOVERY_QUERY[] = "coap://%s:6298/oic/res";
40 static char MULTICAST_DISCOVERY_QUERY[] = "/oic/res";
42 static std::string putPayload = "{\"oic\":[{\"rep\":{\"state\":\"off\",\"power\":10}}]}";
43 static std::string coapServerIP;
44 static std::string coapServerPort;
45 static std::string coapServerResource;
46 static int coapSecureResource;
47 static OCConnectivityType ocConnType;
50 //Secure Virtual Resource database for Iotivity Client application
51 //It contains Client's Identity and the PSK credentials
52 //of other devices which the client trusts
53 static char CRED_FILE[] = "oic_svr_db_client.json";
58 /* SIGINT handler: set gQuitFlag to 1 for graceful termination */
59 void handleSigInt(int signum)
67 static void PrintUsage()
69 OC_LOG(INFO, TAG, "Usage : occlient -u <0|1> -t <1|2|3>");
70 OC_LOG(INFO, TAG, "-u <0|1> : Perform multicast/unicast discovery of resources");
71 OC_LOG(INFO, TAG, "-t 1 : Discover Resources");
72 OC_LOG(INFO, TAG, "-t 2 : Discover Resources and"
73 " Initiate Nonconfirmable Get/Put/Post Requests");
74 OC_LOG(INFO, TAG, "-t 3 : Discover Resources and Initiate Confirmable Get/Put/Post Requests");
77 OCStackResult InvokeOCDoResource(std::ostringstream &query,
78 OCMethod method, OCQualityOfService qos,
79 OCClientResponseHandler cb, OCHeaderOption * options, uint8_t numOptions)
82 OCCallbackData cbData;
85 cbData.context = NULL;
88 ret = OCDoResource(NULL, method, query.str().c_str(), 0,
89 (method == OC_REST_PUT || method == OC_REST_POST) ? putPayload.c_str() : NULL,
90 ocConnType, qos, &cbData, options, numOptions);
92 if (ret != OC_STACK_OK)
94 OC_LOG_V(ERROR, TAG, "OCDoResource returns error %d with method %d", ret, method);
100 OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse)
102 OC_LOG(INFO, TAG, "Callback Context for PUT recvd successfully");
106 OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
107 OC_LOG_V(INFO, TAG, "JSON = %s =============> Put Response", clientResponse->resJSONPayload);
109 return OC_STACK_DELETE_TRANSACTION;
112 OCStackApplicationResult postReqCB(void *ctx, OCDoHandle handle, OCClientResponse *clientResponse)
114 OC_LOG(INFO, TAG, "Callback Context for POST recvd successfully");
118 OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
119 OC_LOG_V(INFO, TAG, "JSON = %s =============> Post Response",
120 clientResponse->resJSONPayload);
122 return OC_STACK_DELETE_TRANSACTION;
125 OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse)
127 OC_LOG(INFO, TAG, "Callback Context for GET query recvd successfully");
131 OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
132 OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
133 OC_LOG_V(INFO, TAG, "JSON = %s =============> Get Response",
134 clientResponse->resJSONPayload);
136 return OC_STACK_DELETE_TRANSACTION;
139 // This is a function called back when a device is discovered
140 OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle,
141 OCClientResponse * clientResponse)
143 OC_LOG(INFO, TAG, "Callback Context for DISCOVER query recvd successfully");
147 OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
149 "Device =============> Discovered %s @ %s:%d",
150 clientResponse->resJSONPayload, clientResponse->devAddr.addr, clientResponse->devAddr.port);
152 ocConnType = clientResponse->connType;
154 if (parseClientResponse(clientResponse) != -1)
158 case TEST_NON_CON_OP:
159 InitGetRequest(OC_LOW_QOS);
160 InitPutRequest(OC_LOW_QOS);
161 //InitPostRequest(OC_LOW_QOS);
164 InitGetRequest(OC_HIGH_QOS);
165 InitPutRequest(OC_HIGH_QOS);
166 //InitPostRequest(OC_HIGH_QOS);
172 return (UNICAST_DISCOVERY) ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION ;
176 int InitPutRequest(OCQualityOfService qos)
178 OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
179 std::ostringstream query;
180 query << (coapSecureResource ? "coaps://" : "coap://") << coapServerIP
181 << ":" << coapServerPort << coapServerResource;
182 return (InvokeOCDoResource(query, OC_REST_PUT,
183 ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS), putReqCB, NULL, 0));
186 int InitPostRequest(OCQualityOfService qos)
188 OCStackResult result;
189 OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
190 std::ostringstream query;
191 query << (coapSecureResource ? "coaps://" : "coap://") << coapServerIP
192 << ":" << coapServerPort << coapServerResource;
194 // First POST operation (to create an LED instance)
195 result = InvokeOCDoResource(query, OC_REST_POST,
196 ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
198 if (OC_STACK_OK != result)
200 // Error can happen if for example, network connectivity is down
201 OC_LOG(INFO, TAG, "First POST call did not succeed");
204 // Second POST operation (to create an LED instance)
205 result = InvokeOCDoResource(query, OC_REST_POST,
206 ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
208 if (OC_STACK_OK != result)
210 OC_LOG(INFO, TAG, "Second POST call did not succeed");
213 // This POST operation will update the original resourced /a/led
214 return (InvokeOCDoResource(query, OC_REST_POST,
215 ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
216 postReqCB, NULL, 0));
219 int InitGetRequest(OCQualityOfService qos)
221 OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
222 std::ostringstream query;
223 query << (coapSecureResource ? "coaps://" : "coap://") << coapServerIP
224 << ":" << coapServerPort << coapServerResource;
226 return (InvokeOCDoResource(query, OC_REST_GET, (qos == OC_HIGH_QOS)?
227 OC_HIGH_QOS:OC_LOW_QOS, getReqCB, NULL, 0));
234 OCCallbackData cbData;
235 char szQueryUri[MAX_URI_LENGTH] = { 0 };
236 OCConnectivityType discoveryReqConnType;
238 if (UNICAST_DISCOVERY)
240 char ipv4addr[IPV4_ADDR_SIZE];
241 printf("Enter IPv4 address of the Server hosting secure resource (Ex: 11.12.13.14)\n");
242 if (fgets(ipv4addr, IPV4_ADDR_SIZE, stdin))
244 //Strip newline char from ipv4addr
245 StripNewLineChar(ipv4addr);
246 snprintf(szQueryUri, sizeof(szQueryUri), UNICAST_DISCOVERY_QUERY, ipv4addr);
250 OC_LOG(ERROR, TAG, "!! Bad input for IPV4 address. !!");
251 return OC_STACK_INVALID_PARAM;
253 discoveryReqConnType = CT_ADAPTER_IP;
254 method = OC_REST_GET;
258 //Send discovery request on Wifi and Ethernet interface
259 discoveryReqConnType = CT_DEFAULT;
260 strcpy(szQueryUri, MULTICAST_DISCOVERY_QUERY);
261 method = OC_REST_DISCOVER;
264 cbData.cb = discoveryReqCB;
265 cbData.context = NULL;
268 /* Start a discovery query*/
269 OC_LOG_V(INFO, TAG, "Initiating %s Resource Discovery : %s\n",
270 (UNICAST_DISCOVERY) ? "Unicast" : "Multicast",
273 ret = OCDoResource(NULL, method, szQueryUri, 0, 0,
274 discoveryReqConnType, OC_LOW_QOS,
276 if (ret != OC_STACK_OK)
278 OC_LOG(ERROR, TAG, "OCStack resource error");
283 FILE* client_fopen(const char *path, const char *mode)
286 return fopen(CRED_FILE, mode);
289 int main(int argc, char* argv[])
292 struct timespec timeout;
294 while ((opt = getopt(argc, argv, "u:t:")) != -1)
299 UNICAST_DISCOVERY = atoi(optarg);
302 TEST_CASE = atoi(optarg);
310 if ((UNICAST_DISCOVERY != 0 && UNICAST_DISCOVERY != 1) ||
311 (TEST_CASE < TEST_DISCOVER_REQ || TEST_CASE >= MAX_TESTS) )
317 // Initialize Persistent Storage for SVR database
318 OCPersistentStorage ps = {};
319 ps.open = client_fopen;
324 OCRegisterPersistentStorageHandler(&ps);
326 /* Initialize OCStack*/
327 if (OCInit(NULL, 0, OC_CLIENT_SERVER) != OC_STACK_OK)
329 OC_LOG(ERROR, TAG, "OCStack init error");
336 timeout.tv_nsec = 100000000L;
338 // Break from loop with Ctrl+C
339 OC_LOG(INFO, TAG, "Entering occlient main loop...");
340 signal(SIGINT, handleSigInt);
343 if (OCProcess() != OC_STACK_OK)
345 OC_LOG(ERROR, TAG, "OCStack process error");
349 nanosleep(&timeout, NULL);
351 OC_LOG(INFO, TAG, "Exiting occlient main loop...");
353 if (OCStop() != OC_STACK_OK)
355 OC_LOG(ERROR, TAG, "OCStack stop error");
361 std::string getPortTBServer(OCClientResponse * clientResponse)
363 if(!clientResponse) return "";
364 std::ostringstream ss;
365 ss << clientResponse->devAddr.port;
369 int parseClientResponse(OCClientResponse * clientResponse)
375 // Initialize all global variables
376 coapServerResource.clear();
377 coapServerPort.clear();
378 coapServerIP.clear();
379 coapSecureResource = 0;
381 root = cJSON_Parse((char *)(clientResponse->resJSONPayload));
387 oc = cJSON_GetObjectItem(root,"oic");
393 if (oc->type == cJSON_Array)
395 int numRsrcs = cJSON_GetArraySize(oc);
396 for(int i = 0; i < numRsrcs; i++)
398 cJSON * resource = cJSON_GetArrayItem(oc, i);
399 if (cJSON_GetObjectItem(resource, "href"))
401 coapServerResource.assign(cJSON_GetObjectItem(resource, "href")->valuestring);
405 coapServerResource = "";
407 OC_LOG_V(INFO, TAG, "Uri -- %s", coapServerResource.c_str());
409 cJSON * prop = cJSON_GetObjectItem(resource,"prop");
412 cJSON * policy = cJSON_GetObjectItem(prop,"p");
415 // If this is a secure resource, the info about the port at which the
416 // resource is hosted on server is embedded inside discovery JSON response
417 if (cJSON_GetObjectItem(policy, "sec"))
419 if ((cJSON_GetObjectItem(policy, "sec")->valueint) == 1)
421 coapSecureResource = 1;
424 OC_LOG_V(INFO, TAG, "Secure -- %s", coapSecureResource == 1 ? "YES" : "NO");
425 if (cJSON_GetObjectItem(policy, "port"))
427 port = cJSON_GetObjectItem(policy, "port")->valueint;
428 OC_LOG_V(INFO, TAG, "Hosting Server Port (embedded inside JSON) -- %u", port);
430 std::ostringstream ss;
432 coapServerPort = ss.str();
437 // If we discovered a secure resource, exit from here
438 if (coapSecureResource)
446 coapServerIP = clientResponse->devAddr.addr;
449 coapServerPort = getPortTBServer(clientResponse);
450 OC_LOG_V(INFO, TAG, "Hosting Server Port -- %s", coapServerPort.c_str());