Merge test folder of test branch
[iotivity.git] / test / src / common / commonutil / c_cpp / CloudCommonUtil.cpp
1 /******************************************************************
2  *
3  * Copyright 2017 Samsung Electronics 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 "CloudCommonUtil.h"
22
23 string CloudCommonUtil::g_authprovider = "github";
24 string CloudCommonUtil::g_authCode = "";
25 string CloudCommonUtil::g_uid = "";
26 string CloudCommonUtil::g_accessToken = "";
27 Configuration g_cloudPropFile(CLOUD_PROP_FILE);
28 Configuration g_configPropFile(CONFIG_PROP_FILE);
29
30 static int g_isCbInvoked = CALLBACK_NOT_INVOKED;
31 OCAccountManager::Ptr accountMgr = nullptr;
32
33 std::string CloudCommonUtil::getDefaultIp()
34 {
35     string ci_server_ip = "";
36 #ifdef __LINUX__
37     ci_server_ip = g_configPropFile.getProperties(CI_SERVER_ETHERNET_IP_KEY);
38 #elif __TIZEN__
39     ci_server_ip = g_configPropFile.getProperties(CI_SERVER_WIFI_IP_KEY);
40 #endif
41
42     return ci_server_ip;
43 }
44
45 std::string CloudCommonUtil::getDefaultHostAddess()
46 {
47     string hostAddress = "";
48
49 #ifdef __TLS_ON__
50     hostAddress = COAP_TLSON_PREFIX;
51 #else
52     hostAddress = COAP_TLSOFF_PREFIX;
53 #endif
54
55 #ifdef __LINUX__
56     string ci_server_ip = g_configPropFile.getProperties(CI_SERVER_ETHERNET_IP_KEY);
57 #elif __TIZEN__
58     string ci_server_ip = g_configPropFile.getProperties(CI_SERVER_WIFI_IP_KEY);
59 #endif
60
61     string local_host = ci_server_ip + ":" + to_string(REMOTE_CI_SERVER_PORT);
62     hostAddress += local_host;
63     hostAddress.erase(std::remove(hostAddress.begin(), hostAddress.end(), '\n'), hostAddress.end());
64
65     return hostAddress;
66 }
67
68 OCDevAddr CloudCommonUtil::getDefaultEndPoint()
69 {
70     OCDevAddr endPoint;
71
72 #ifdef __LINUX__
73     string ci_server_ip = g_configPropFile.getProperties(CI_SERVER_ETHERNET_IP_KEY);
74 #elif __TIZEN__
75     string ci_server_ip = g_configPropFile.getProperties(CI_SERVER_WIFI_IP_KEY);
76 #endif
77
78     memset(&endPoint, 0, sizeof(endPoint));
79     strncpy(endPoint.addr, ci_server_ip.c_str(), sizeof(endPoint.addr));
80     endPoint.port = OC_MULTICAST_PORT;
81
82     return endPoint;
83 }
84
85 #ifdef __SECURED__
86 OicCloud_t* CloudCommonUtil::getCloudServer()
87 {
88     OicCloud_t *cloud = (OicCloud_t *)OICCalloc(1,sizeof(OicCloud_t));
89     if (NULL == cloud)
90     {
91         IOTIVITYTEST_LOG(ERROR, "[CSC Helper] cloud calloc failed");
92         return NULL;
93     }
94     cloud->cis = (char *)OICCalloc(1,1024 * 4);
95     if (NULL == cloud)
96     {
97         IOTIVITYTEST_LOG(ERROR, "[CSC Helper] cloud->cis calloc failed");
98         OICFree(cloud);
99         return NULL;
100     }
101     cloud->apn = (char *)OICCalloc(1,512);
102     if (NULL == cloud->apn)
103     {
104         IOTIVITYTEST_LOG(ERROR, "[CSC Helper] cloud->apn calloc failed");
105         OICFree(cloud->cis);
106         OICFree(cloud);
107         return NULL;
108     }
109     cloud->at = (char *)OICCalloc(1,1024);
110     if (NULL == cloud->at)
111     {
112         IOTIVITYTEST_LOG(ERROR, "[CSC Helper] cloud->at calloc failed");
113         OICFree(cloud->apn);
114         OICFree(cloud->cis);
115         OICFree(cloud);
116         return NULL;
117     }
118
119     string ci_server_ip;
120
121 #ifdef __LINUX__
122     ci_server_ip = g_configPropFile.getProperties(CI_SERVER_ETHERNET_IP_KEY);
123 #elif __TIZEN__
124     ci_server_ip = g_configPropFile.getProperties(CI_SERVER_WIFI_IP_KEY);
125 #endif
126
127     ci_server_ip = ci_server_ip + ":" + std::to_string(OC_MULTICAST_PORT);
128     strncpy(cloud->cis, ci_server_ip.c_str(), sizeof(cloud->cis));
129
130
131     return cloud;
132 }
133 #endif
134
135 std::string CloudCommonUtil::readfile(std::string filename)
136 {
137     __FUNC_IN__
138     FILE *fp;
139     char buff[100];
140
141     fp = fopen(filename.c_str(), "r");
142
143     if (NULL == fp)
144     {
145         IOTIVITYTEST_LOG(ERROR, "[CSC Helper] ERROR Opening File : %s", filename.c_str());
146     }
147
148     if (NULL == fgets(buff, 100, (FILE*) fp))
149     {
150         IOTIVITYTEST_LOG(ERROR, "[CSC Helper] Unable to Get input from File: %s", filename.c_str());
151     }
152
153     fclose(fp);
154
155     IOTIVITYTEST_LOG(DEBUG, "[CSC Helper] Recieved Data : %s", buff);
156
157     __FUNC_OUT__
158     return std::string(buff);
159 }
160
161 void CloudCommonUtil::create_file(string filename, string data)
162 {
163     FILE *fp;
164     fp = fopen(filename.c_str(), "w+");
165     fprintf(fp, "%s", data.c_str());
166     fclose(fp);
167 }
168
169 static int waitCallbackRet()
170 {
171     IOTIVITYTEST_LOG(DEBUG, "Waiting for Callback to be invoked");
172
173     for (int i = 0; CALLBACK_TIMEOUT > i; ++i)
174     {
175         if (CALLBACK_INVOKED == g_isCbInvoked)
176         {
177             return CALLBACK_INVOKED;
178         }
179
180         if (CALLBACK_CODE_MISMATCH == g_isCbInvoked)
181         {
182             return CALLBACK_CODE_MISMATCH;
183         }
184
185         sleep(DELAY_SHORT);
186         printf("Second Elapsed : %d seconds\n", i);
187
188         if (OC_STACK_OK != OCProcess())
189         {
190             printf("OCStack process error\n");
191             return CALLBACK_NOT_INVOKED;
192         }
193     }
194
195     return CALLBACK_NOT_INVOKED;
196 }
197
198 void CloudCommonUtil::init_string(Stringstr *str)
199 {
200     str->len = 0;
201     str->ptr = (char*) malloc(str->len + 1);
202     if (str->ptr == NULL)
203     {
204         fprintf(stderr, "malloc() failed\n");
205         exit (EXIT_FAILURE);
206     }
207     str->ptr[0] = '\0';
208 }
209
210 size_t writefunc(void *ptr, size_t size, size_t nmemb, Stringstr *str)
211 {
212     size_t new_len = str->len + size * nmemb;
213     str->ptr = (char*) realloc(str->ptr, new_len + 1);
214     if (str->ptr == NULL)
215     {
216         fprintf(stderr, "realloc() failed\n");
217         exit (EXIT_FAILURE);
218     }
219     memcpy(str->ptr + str->len, ptr, size * nmemb);
220     str->ptr[new_len] = '\0';
221     str->len = new_len;
222
223     return size * nmemb;
224 }
225
226 char* CloudCommonUtil::get_authenticity_token(const char* responseText)
227 {
228     char* authLast = NULL;
229     char* auth_token = (char*) strstr(responseText,
230             "<input type=\"hidden\" name=\"authenticity_token\" value=\"");
231     auth_token = strstr(auth_token, "value=\"");
232     auth_token = &auth_token[strlen("value=\"")];
233     authLast = strstr(auth_token, "\" />");
234     auth_token[(authLast - auth_token)] = '\0';
235     return auth_token;
236 }
237
238 char* CloudCommonUtil::get_auth_token_code(const char* resposeTxt, char *code)
239 {
240     char* authLast = NULL;
241
242     int len;
243     char* auth_token = (char*) strstr(resposeTxt,
244             "<a href=\"http://www.example.com/oauth_callback/?code=");
245
246     authLast = strstr(auth_token, "\">");
247     auth_token[(authLast - auth_token)] = '\0';
248
249     auth_token = strstr(auth_token, "code=");
250     auth_token = strstr(auth_token, "=");
251
252     len = strlen(auth_token);
253     memset(code, 0, len);
254     strncpy(code, auth_token + 1, len - 1);
255     return code;
256 }
257
258 char const* CloudCommonUtil::getgithubcode(const char *gitlogin, const char *gitpassword,
259         char *code)
260 {
261     char demoPost[1000] =
262     { 0 };
263     char *auth_text = NULL;
264     char *auth_url_text = NULL;
265     char *code_text = NULL;
266     CURL *curl;
267     CURLcode res;
268
269     struct curl_slist *cookies;
270     struct curl_slist *nc;
271
272     int i;
273     int http_code = 0;
274     Stringstr str;
275     init_string(&str);
276
277     curl_global_init(CURL_GLOBAL_ALL);
278
279     //get login page
280     curl = curl_easy_init();
281
282     if (curl)
283     {
284         //Get Github login page
285         curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
286         curl_easy_setopt(curl, CURLOPT_URL, INIT_GET_LOGIN_URL);
287         curl_easy_setopt(curl, CURLOPT_COOKIEFILE, ""); /* start cookie engine */
288         curl_easy_setopt(curl, CURLOPT_AUTOREFERER, 1L);
289
290         curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
291         curl_easy_setopt(curl, CURLOPT_COOKIELIST, "ALL"); // clear all cookies
292         curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);
293
294         curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
295         curl_easy_setopt(curl, CURLOPT_WRITEDATA, &str);
296
297         res = curl_easy_perform(curl);
298
299         if (res != CURLE_OK)
300         {
301             fprintf(stderr, "Curl perform failed: %s\n", curl_easy_strerror(res));
302             return "";
303         }
304
305         auth_text = get_authenticity_token(str.ptr);
306         auth_url_text = curl_easy_escape(curl, auth_text, strlen(auth_text));
307
308         snprintf(demoPost, 1000, "%s%s%s%s%s%s%s", PAR_POST_VAL, AUTHENTICITY_TOKEN, auth_url_text,
309                 "&login=", gitlogin, "&password=", gitpassword);
310
311         free(str.ptr);
312
313         init_string(&str);
314         res = curl_easy_getinfo(curl, CURLINFO_COOKIELIST, &cookies);
315         if (res != CURLE_OK)
316         {
317             fprintf(stderr, "Curl curl_easy_getinfo failed: %s\n", curl_easy_strerror(res));
318             exit(1);
319         }
320
321         //github login
322         curl_easy_setopt(curl, CURLOPT_URL, LOGIN_URL);
323         curl_easy_setopt(curl, CURLOPT_POST, 1L); /* start cookie engine */
324         curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
325         curl_easy_setopt(curl, CURLOPT_WRITEDATA, &str);
326         curl_easy_setopt(curl, CURLOPT_POSTFIELDS, demoPost);
327
328         nc = cookies, i = 1;
329         while (nc)
330         {
331             curl_easy_setopt(curl, CURLOPT_COOKIELIST, nc->data);
332             nc = nc->next;
333             i++;
334         }
335
336         res = curl_easy_perform(curl);
337         res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
338         IOTIVITYTEST_LOG(INFO, "Resposecode from Github: %d", http_code);
339         res = curl_easy_getinfo(curl, CURLINFO_COOKIELIST, &cookies);
340
341         if (res != CURLE_OK)
342         {
343             fprintf(stderr, "Curl curl_easy_getinfo failed: %s\n", curl_easy_strerror(res));
344             exit(1);
345         }
346         free(str.ptr);
347
348         //request for cloud code
349         init_string(&str);
350         curl_easy_setopt(curl, CURLOPT_URL, IOTIVITY_CLOUD_URL);
351         curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);
352
353         curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
354         curl_easy_setopt(curl, CURLOPT_WRITEDATA, &str);
355         nc = cookies, i = 1;
356         while (nc)
357         {
358             curl_easy_setopt(curl, CURLOPT_COOKIELIST, nc->data);
359             nc = nc->next;
360             i++;
361         }
362         res = curl_easy_perform(curl);
363         if (res != CURLE_OK)
364         {
365             fprintf(stderr, "Curl perform failed: %s\n", curl_easy_strerror(res));
366             return (char*) "";
367         }
368
369         code_text = get_auth_token_code(str.ptr, code);
370
371         curl_easy_cleanup(curl);
372     }
373     curl_global_cleanup();
374     free(str.ptr);
375
376     return code_text;
377 }
378
379 /*
380  * Get Auth Code From  Github
381  */
382 char* CloudCommonUtil::getGitLoginAuthCodeMain()
383 {
384     __FUNC_IN__
385     char *code = (char*) calloc(30, sizeof(char));
386     string github_user_id = g_configPropFile.getProperties(GITHUB_USER_KEY);
387     string github_password = g_configPropFile.getProperties(GITHUB_PASSWORD_KEY);
388     code = (char*) getgithubcode(github_user_id.c_str(), github_password.c_str(), code);
389     IOTIVITYTEST_LOG(INFO, "Auth Code: %s", code);
390     __FUNC_OUT__
391     return code;
392 }
393
394 void CloudCommonUtil::printRepresentation(OCRepresentation rep)
395 {
396     for (auto itr = rep.begin(); itr != rep.end(); ++itr)
397     {
398         cout << "\t" << itr->attrname() << ":\t" << itr->getValueToString() << endl;
399
400         if (itr->attrname().compare("accesstoken") == 0)
401         {
402             CloudCommonUtil::g_accessToken = itr->getValueToString();
403             g_cloudPropFile.setProperties(CLOUD_ACCESSTOKEN_KEY, CloudCommonUtil::g_accessToken);
404
405         }
406
407         if (itr->attrname().compare("uid") == 0)
408         {
409             CloudCommonUtil::g_uid = itr->getValueToString();
410             g_cloudPropFile.setProperties(CLOUD_UID_KEY, CloudCommonUtil::g_uid);
411         }
412
413         if (itr->attrname().compare("aclid") == 0)
414         {
415             IOTIVITYTEST_LOG(INFO, "ACL ID : %s", itr->getValueToString().c_str());
416
417         }
418
419         if (itr->attrname().compare("aceid") == 0)
420         {
421             IOTIVITYTEST_LOG(INFO, "ACE ID : %s", itr->getValueToString().c_str());
422         }
423     }
424 }
425
426 OCRepresentation CloudCommonUtil::parseOCClientResponse(OCClientResponse* clientResponse)
427 {
428     __FUNC_OUT__
429     if (nullptr == clientResponse)
430     {
431         IOTIVITYTEST_LOG(ERROR, "clientResponse is NULL");
432         return OCRepresentation();
433     }
434
435     if (nullptr == clientResponse->payload
436             || PAYLOAD_TYPE_REPRESENTATION != clientResponse->payload->type)
437     {
438         IOTIVITYTEST_LOG(ERROR, "clientResponse->payload is NULL");
439         return OCRepresentation();
440     }
441
442     if (PAYLOAD_TYPE_REPRESENTATION != clientResponse->payload->type)
443     {
444         IOTIVITYTEST_LOG(ERROR, "clientResponse is not of PAYLOAD_TYPE_REPRESENTATION");
445         return OCRepresentation();
446     }
447
448     MessageContainer oc;
449     oc.setPayload(clientResponse->payload);
450
451     std::vector< OCRepresentation >::const_iterator it = oc.representations().begin();
452     if (it == oc.representations().end())
453     {
454         return OCRepresentation();
455     }
456
457     // first one is considered the root, everything else is considered a child of this one.
458     OCRepresentation root = *it;
459     root.setDevAddr(clientResponse->devAddr);
460     root.setUri(clientResponse->resourceUri);
461     ++it;
462
463     std::for_each(it, oc.representations().end(), [&root](const OCRepresentation& repItr)
464     {   root.addChild(repItr);});
465
466     __FUNC_OUT__
467     return root;
468 }
469
470 static void handleLoginoutCB(const HeaderOptions &, const OCRepresentation &rep, const int ecode)
471 {
472     IOTIVITYTEST_LOG(INFO, "Auth response received code: %d", ecode);
473     if (rep.getPayload() != NULL)
474     {
475         CloudCommonUtil::printRepresentation(rep);
476     }
477
478     g_isCbInvoked = CALLBACK_INVOKED;
479 }
480
481 static void signInOutCB(const HeaderOptions &, const OCRepresentation &rep, const int ecode)
482 {
483     IOTIVITYTEST_LOG(INFO, "Auth response received code: %d", ecode);
484     if (rep.getPayload() != NULL)
485     {
486         CloudCommonUtil::printRepresentation(rep);
487     }
488
489     g_isCbInvoked =
490             (OC_STACK_RESOURCE_CHANGED == ecode) ? CALLBACK_INVOKED : CALLBACK_CODE_MISMATCH;
491 }
492
493 /*
494  * Sign Up in Cloud
495  */
496 bool CloudCommonUtil::signUp(OCAccountManager::Ptr accountMgr)
497 {
498     __FUNC_IN__
499
500     char* g_chAuthCode = CloudCommonUtil::getGitLoginAuthCodeMain();
501     CloudCommonUtil::g_authCode = string(g_chAuthCode);
502     IOTIVITYTEST_LOG(INFO, "[Cloud Common] AuthCode for SignUp %s",
503             CloudCommonUtil::g_authCode.c_str());
504     OCStackResult result = accountMgr->signUp(CloudCommonUtil::g_authprovider,
505             CloudCommonUtil::g_authCode, handleLoginoutCB);
506
507     IOTIVITYTEST_LOG(INFO, "[Cloud Common] signUp returns %s",
508             CommonUtil::getOCStackResult(result));
509
510     if (OC_STACK_OK != result)
511     {
512         IOTIVITYTEST_LOG(ERROR, "[Cloud Common] signUp returns %s",
513                 CommonUtil::getOCStackResult(result));
514         free(g_chAuthCode);
515         return false;
516     }
517
518     if (OC_STACK_OK == result)
519     {
520         if (CALLBACK_INVOKED != waitCallbackRet())
521         {
522             IOTIVITYTEST_LOG(ERROR, "[Cloud Common] Callback Not Invoked");
523             free(g_chAuthCode);
524             return false;
525         }
526     }
527     g_cloudPropFile.save();
528     __FUNC_OUT__
529     return true;
530 }
531
532 /*
533  * Sign Up in Cloud
534  */
535 bool CloudCommonUtil::signUp(OCAccountManager::Ptr accountMgr, std::string authCode)
536 {
537     __FUNC_IN__
538
539     OCStackResult result = accountMgr->signUp(CloudCommonUtil::g_authprovider, authCode.c_str(),
540             handleLoginoutCB);
541
542     IOTIVITYTEST_LOG(INFO, "[Cloud Common] signUp returns %s",
543             CommonUtil::getOCStackResult(result));
544
545     if (OC_STACK_OK != result)
546     {
547         IOTIVITYTEST_LOG(ERROR, "[Cloud Common] signUp returns %s",
548                 CommonUtil::getOCStackResult(result));
549         return false;
550     }
551
552     if (OC_STACK_OK == result)
553     {
554         if (CALLBACK_INVOKED != waitCallbackRet())
555         {
556             IOTIVITYTEST_LOG(ERROR, "[Cloud Common] Callback Not Invoked");
557             return false;
558         }
559     }
560     g_cloudPropFile.save();
561     __FUNC_OUT__
562     return true;
563 }
564
565 /*
566  * Sign In in Cloud
567  */
568 bool CloudCommonUtil::signIn(OCAccountManager::Ptr accountMgr)
569 {
570     __FUNC_IN__
571     g_isCbInvoked = CALLBACK_NOT_INVOKED;
572
573     CloudCommonUtil::g_uid = g_cloudPropFile.getProperties(CLOUD_UID_KEY);
574     CloudCommonUtil::g_accessToken = g_cloudPropFile.getProperties(CLOUD_ACCESSTOKEN_KEY);
575
576     OCStackResult result = accountMgr->signIn(CloudCommonUtil::g_uid,
577             CloudCommonUtil::g_accessToken, signInOutCB);
578     IOTIVITYTEST_LOG(INFO, "[Cloud Common] signIn returns %s",
579             CommonUtil::getOCStackResult(result));
580     IOTIVITYTEST_LOG(INFO, "[Cloud Common] UUID = %s   ACCESSTOKE = %s ", g_uid.c_str(),
581             g_accessToken.c_str());
582
583     if (OC_STACK_OK != result)
584     {
585         IOTIVITYTEST_LOG(ERROR, "[Cloud Common] signIn returns %s",
586                 CommonUtil::getOCStackResult(result));
587         return false;
588     }
589
590     if (OC_STACK_OK == result)
591     {
592         if (CALLBACK_INVOKED != waitCallbackRet())
593         {
594             IOTIVITYTEST_LOG(ERROR, "[Cloud Common] Callback Error : %d", g_isCbInvoked);
595
596             return false;
597         }
598     }
599
600     return true;
601     __FUNC_OUT__
602 }
603
604 bool CloudCommonUtil::signOut(OCAccountManager::Ptr accountMgr)
605 {
606     __FUNC_IN__
607     g_isCbInvoked = CALLBACK_NOT_INVOKED;
608
609     CloudCommonUtil::g_accessToken = g_cloudPropFile.getProperties(CLOUD_ACCESSTOKEN_KEY);
610
611     OCStackResult result = accountMgr->signOut(CloudCommonUtil::g_accessToken, signInOutCB);
612     IOTIVITYTEST_LOG(INFO, "[Cloud Common] signOut returns %s",
613             CommonUtil::getOCStackResult(result));
614
615     if (OC_STACK_OK != result)
616     {
617         IOTIVITYTEST_LOG(ERROR, "[Cloud Common] signOut returns %s",
618                 CommonUtil::getOCStackResult(result));
619         return false;
620     }
621
622     if (OC_STACK_OK == result)
623     {
624         if (CALLBACK_INVOKED != waitCallbackRet())
625         {
626             IOTIVITYTEST_LOG(ERROR, "[Cloud Common] Callback Error : %d", g_isCbInvoked);
627             return false;
628         }
629     }
630     __FUNC_OUT__
631     return true;
632 }