Fix crash in ssl retransmission thread
[platform/upstream/iotivity.git] / resource / src / OCAccountManager.cpp
1 /* ****************************************************************
2  *
3  * Copyright 2016 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 "OCAccountManager.h"
22 #include "OCUtilities.h"
23
24 #include "ocstack.h"
25
26 #define VERIFY_NON_EMPTY(arg, log_message, ret) \
27     if ((arg).empty()) \
28     { \
29         oclog() << log_message << std::flush; \
30         return result_guard(ret); \
31     } \
32
33 namespace OC {
34
35 using OC::result_guard;
36 using OC::checked_guard;
37
38 OCAccountManager::OCAccountManager(std::weak_ptr<IClientWrapper> clientWrapper,
39                                    const std::string& host,
40                                    OCConnectivityType connectivityType)
41  : m_clientWrapper(clientWrapper), m_host(host), m_userUuid(""),
42    m_invitationObserveHandle(nullptr), m_groupObserveHandle(nullptr), m_connType(connectivityType)
43 {
44     if (m_host.empty() || m_clientWrapper.expired())
45     {
46         throw OCException(OC::Exception::INVALID_PARAM);
47     }
48
49     const char* di = OCGetServerInstanceIDString();
50     if (!di)
51     {
52         oclog() << "The mode should be Server or Both to generate UUID" << std::flush;
53         throw OCException(OC::Exception::INVALID_PARAM);
54     }
55
56     m_deviceID.append(di);
57     checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, m_defaultQos);
58 }
59
60 OCAccountManager::~OCAccountManager()
61 {
62 }
63
64 std::string OCAccountManager::host() const
65 {
66     return m_host;
67 }
68
69 OCConnectivityType OCAccountManager::connectivityType() const
70 {
71     return m_connType;
72 }
73
74 OCStackResult OCAccountManager::signUp(const std::string& authProvider,
75                                        const std::string& authCode,
76                                        PostCallback cloudConnectHandler)
77 {
78     return result_guard(signUp(authProvider, authCode, QueryParamsMap(), cloudConnectHandler));
79 }
80
81 OCStackResult OCAccountManager::signUp(const std::string& authProvider,
82                                        const std::string& authCode,
83                                        const QueryParamsMap& options,
84                                        PostCallback cloudConnectHandler)
85 {
86     VERIFY_NON_EMPTY(authProvider, "authProvider cannot be empty.", OC_STACK_INVALID_PARAM);
87     VERIFY_NON_EMPTY(authCode, "authCode cannot be empty.", OC_STACK_INVALID_PARAM);
88
89     std::string uri = m_host + OC_RSRVD_ACCOUNT_URI;
90
91     OCRepresentation rep;
92     rep.setValue<std::string>(OC_RSRVD_DEVICE_ID, m_deviceID);
93     rep.setValue<std::string>(OC_RSRVD_AUTHPROVIDER, authProvider);
94     rep.setValue<std::string>(OC_RSRVD_AUTHCODE, authCode);
95
96     if (!options.empty())
97     {
98         for (auto iter : options)
99         {
100             rep.setValue(iter.first, iter.second);
101         }
102     }
103
104     return checked_guard(m_clientWrapper.lock(), &IClientWrapper::PostResourceRepresentation,
105                          OCDevAddr(), uri, rep, QueryParamsMap(), HeaderOptions(),
106                          m_connType, cloudConnectHandler, m_defaultQos);
107 }
108
109 OCStackResult OCAccountManager::signIn(const std::string& userUuid,
110                                        const std::string& accessToken,
111                                        PostCallback cloudConnectHandler)
112 {
113     VERIFY_NON_EMPTY(userUuid, "userUuid cannot be empty.", OC_STACK_INVALID_PARAM);
114     VERIFY_NON_EMPTY(accessToken, "accessToken cannot be empty.", OC_STACK_INVALID_PARAM);
115
116     OCStackResult result = result_guard(signInOut(userUuid, accessToken, true,
117                                                   cloudConnectHandler));
118     if (OC_STACK_OK == result)
119     {
120         m_userUuid = userUuid;
121     }
122
123     return result;
124 }
125
126 OCStackResult OCAccountManager::signOut(const std::string& accessToken,
127                                         PostCallback cloudConnectHandler)
128 {
129     VERIFY_NON_EMPTY(m_userUuid, "Need to sign-in first.", OC_STACK_ERROR);
130     VERIFY_NON_EMPTY(accessToken, "accessToken cannot be empty.", OC_STACK_INVALID_PARAM);
131
132     OCStackResult result = result_guard(signInOut(m_userUuid, accessToken, false,
133                                                   cloudConnectHandler));
134     if (OC_STACK_OK == result)
135     {
136         m_userUuid = "";
137     }
138
139     return result;
140 }
141
142 OCStackResult OCAccountManager::signInOut(const std::string& userUuid,
143                                           const std::string& accessToken,
144                                           bool isSignIn,
145                                           PostCallback cloudConnectHandler)
146 {
147     std::string uri = m_host + OC_RSRVD_ACCOUNT_SESSION_URI;
148
149     OCRepresentation rep;
150
151     if (isSignIn)
152     {
153         rep.setValue<std::string>(OC_RSRVD_USER_UUID, userUuid);
154     }
155     rep.setValue<std::string>(OC_RSRVD_DEVICE_ID, m_deviceID);
156     rep.setValue<std::string>(OC_RSRVD_ACCESS_TOKEN, accessToken);
157     rep.setValue<bool>(OC_RSRVD_LOGIN, isSignIn);
158
159     return checked_guard(m_clientWrapper.lock(), &IClientWrapper::PostResourceRepresentation,
160                          OCDevAddr(), uri, rep, QueryParamsMap(), HeaderOptions(),
161                          m_connType, cloudConnectHandler, m_defaultQos);
162 }
163
164 OCStackResult OCAccountManager::refreshAccessToken(const std::string& userUuid,
165                                                    const std::string& refreshToken,
166                                                    PostCallback cloudConnectHandler)
167 {
168     VERIFY_NON_EMPTY(userUuid, "userUuid cannot be empty.", OC_STACK_INVALID_PARAM);
169     VERIFY_NON_EMPTY(refreshToken, "refreshToken cannot be empty.", OC_STACK_INVALID_PARAM);
170
171     std::string uri = m_host + OC_RSRVD_ACCOUNT_TOKEN_REFRESH_URI;
172
173     OCRepresentation rep;
174     rep.setValue<std::string>(OC_RSRVD_USER_UUID, userUuid);
175     rep.setValue<std::string>(OC_RSRVD_DEVICE_ID, m_deviceID);
176     rep.setValue<std::string>(OC_RSRVD_GRANT_TYPE, std::string(OC_RSRVD_GRANT_TYPE_REFRESH_TOKEN));
177     rep.setValue<std::string>(OC_RSRVD_REFRESH_TOKEN, refreshToken);
178
179     return checked_guard(m_clientWrapper.lock(), &IClientWrapper::PostResourceRepresentation,
180                          OCDevAddr(), uri, rep, QueryParamsMap(), HeaderOptions(),
181                          m_connType, cloudConnectHandler, m_defaultQos);
182 }
183
184 OCStackResult OCAccountManager::searchUser(const QueryParamsMap& queryParams,
185                                            GetCallback cloudConnectHandler)
186 {
187     VERIFY_NON_EMPTY(queryParams, "queryParams cannot be empty.", OC_STACK_INVALID_PARAM);
188
189     std::string uri = m_host + OC_RSRVD_ACCOUNT_SEARCH_URI;
190
191     return checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetResourceRepresentation,
192                          OCDevAddr(), uri, queryParams, HeaderOptions(),
193                          m_connType, cloudConnectHandler, m_defaultQos);
194 }
195
196 OCStackResult OCAccountManager::deleteDevice(const std::string& accessToken,
197                                              const std::string& deviceId,
198                                              DeleteCallback cloudConnectHandler)
199 {
200     VERIFY_NON_EMPTY(accessToken, "accessToken cannot be empty.", OC_STACK_INVALID_PARAM);
201     VERIFY_NON_EMPTY(deviceId, "deviceId cannot be empty.", OC_STACK_INVALID_PARAM);
202
203     std::string uri = m_host + OC_RSRVD_ACCOUNT_URI
204                       + "?" + OC_RSRVD_ACCESS_TOKEN + "=" + accessToken
205                       + ";" + OC_RSRVD_DEVICE_ID + "=" + deviceId;
206
207     return checked_guard(m_clientWrapper.lock(), &IClientWrapper::DeleteResource,
208                          OCDevAddr(), uri, HeaderOptions(),
209                          m_connType, cloudConnectHandler, m_defaultQos);
210 }
211
212 OCStackResult OCAccountManager::createGroup(PostCallback cloudConnectHandler)
213 {
214     return result_guard(createGroup(QueryParamsMap(), cloudConnectHandler));
215 }
216
217 OCStackResult OCAccountManager::createGroup(const QueryParamsMap& queryParams,
218                                             PostCallback cloudConnectHandler)
219 {
220     VERIFY_NON_EMPTY(m_userUuid, "Need to sign-in first.", OC_STACK_ERROR);
221
222     std::string uri = m_host + OC_RSRVD_ACL_GROUP_URI;
223
224     std::vector<std::string> members{m_userUuid};
225
226     OCRepresentation rep;
227     rep.setValue<std::string>(OC_RSRVD_OWNER, m_userUuid);
228     rep.setValue<std::vector<std::string>>(OC_RSRVD_MEMBERS, members);
229
230     if (!queryParams.empty())
231     {
232         for (auto iter : queryParams)
233         {
234             rep.setValue(iter.first, iter.second);
235         }
236     }
237
238     return checked_guard(m_clientWrapper.lock(), &IClientWrapper::PostResourceRepresentation,
239                          OCDevAddr(), uri, rep, QueryParamsMap(), HeaderOptions(),
240                          m_connType, cloudConnectHandler, m_defaultQos);
241 }
242
243 OCStackResult OCAccountManager::deleteGroup(const std::string& groupId,
244                                             DeleteCallback cloudConnectHandler)
245 {
246     VERIFY_NON_EMPTY(m_userUuid, "Need to sign-in first.", OC_STACK_ERROR);
247     VERIFY_NON_EMPTY(groupId, "groupId cannot be empty.", OC_STACK_INVALID_PARAM);
248
249     std::string uri = m_host + OC_RSRVD_ACL_GROUP_URI + "/" + groupId
250                       + "?" + OC_RSRVD_OWNER + "=" + m_userUuid;
251
252     return checked_guard(m_clientWrapper.lock(), &IClientWrapper::DeleteResource,
253                          OCDevAddr(), uri, HeaderOptions(),
254                          m_connType, cloudConnectHandler, m_defaultQos);
255 }
256
257 OCStackResult OCAccountManager::getGroupInfoAll(GetCallback cloudConnectHandler)
258 {
259     VERIFY_NON_EMPTY(m_userUuid, "Need to sign-in first.", OC_STACK_ERROR);
260
261     std::string uri = m_host + OC_RSRVD_ACL_GROUP_URI;
262
263     QueryParamsMap query = {};
264     query.insert(std::make_pair(OC_RSRVD_MEMBERS, m_userUuid));
265
266     return checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetResourceRepresentation,
267                          OCDevAddr(), uri, query, HeaderOptions(), m_connType,
268                          cloudConnectHandler, m_defaultQos);
269 }
270
271 OCStackResult OCAccountManager::getGroupInfo(const std::string& groupId,
272                                              GetCallback cloudConnectHandler)
273 {
274     VERIFY_NON_EMPTY(m_userUuid, "Need to sign-in first.", OC_STACK_ERROR);
275     VERIFY_NON_EMPTY(groupId, "groupId cannot be empty.", OC_STACK_INVALID_PARAM);
276
277     std::string uri = m_host + OC_RSRVD_ACL_GROUP_URI + "/" + groupId;
278
279     QueryParamsMap query = {};
280     query.insert(std::make_pair(OC_RSRVD_MEMBERS, m_userUuid));
281
282     return checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetResourceRepresentation,
283                          OCDevAddr(), uri, query, HeaderOptions(),
284                          m_connType, cloudConnectHandler, m_defaultQos);
285 }
286
287 OCStackResult OCAccountManager::addPropertyValueToGroup(const std::string& groupId,
288                                                         const OCRepresentation propertyValue,
289                                                         PostCallback cloudConnectHandler)
290 {
291     VERIFY_NON_EMPTY(groupId, "groupId cannot be empty.", OC_STACK_INVALID_PARAM);
292
293     std::string uri = m_host + OC_RSRVD_ACL_GROUP_URI + "/" + groupId;
294
295     QueryParamsMap query = {};
296     query.insert(std::make_pair(OC_RSRVD_OPERATION, OC_RSRVD_ADD));
297
298     return checked_guard(m_clientWrapper.lock(), &IClientWrapper::PostResourceRepresentation,
299                          OCDevAddr(), uri, propertyValue, query, HeaderOptions(),
300                          m_connType, cloudConnectHandler, m_defaultQos);
301 }
302
303 OCStackResult OCAccountManager::deletePropertyValueFromGroup(const std::string& groupId,
304                                                              const OCRepresentation propertyValue,
305                                                              PostCallback cloudConnectHandler)
306 {
307     VERIFY_NON_EMPTY(groupId, "groupId cannot be empty.", OC_STACK_INVALID_PARAM);
308
309     std::string uri = m_host + OC_RSRVD_ACL_GROUP_URI + "/" + groupId;
310
311     QueryParamsMap query = {};
312     query.insert(std::make_pair(OC_RSRVD_OPERATION, OC_RSRVD_DELETE));
313
314     return checked_guard(m_clientWrapper.lock(), &IClientWrapper::PostResourceRepresentation,
315                          OCDevAddr(), uri, propertyValue, query, HeaderOptions(),
316                          m_connType, cloudConnectHandler, m_defaultQos);
317 }
318
319 OCStackResult OCAccountManager::updatePropertyValueOnGroup(const std::string& groupId,
320                                                            const OCRepresentation propertyValue,
321                                                            PostCallback cloudConnectHandler)
322 {
323     VERIFY_NON_EMPTY(groupId, "groupId cannot be empty.", OC_STACK_INVALID_PARAM);
324
325     std::string uri = m_host + OC_RSRVD_ACL_GROUP_URI + "/" + groupId;
326
327     return checked_guard(m_clientWrapper.lock(), &IClientWrapper::PostResourceRepresentation,
328                          OCDevAddr(), uri, propertyValue, QueryParamsMap(), HeaderOptions(),
329                          m_connType, cloudConnectHandler, m_defaultQos);
330 }
331
332 OCStackResult OCAccountManager::observeGroup(ObserveCallback cloudConnectHandler)
333 {
334     VERIFY_NON_EMPTY(m_userUuid, "Need to sign-in first.", OC_STACK_ERROR);
335
336     std::string uri = m_host + OC_RSRVD_ACL_GROUP_URI;
337
338     QueryParamsMap query = {};
339     query.insert(std::make_pair(OC_RSRVD_MEMBERS, m_userUuid));
340
341     return checked_guard(m_clientWrapper.lock(), &IClientWrapper::ObserveResource,
342                          ObserveType::Observe, &m_groupObserveHandle, OCDevAddr(), uri,
343                          query, HeaderOptions(), cloudConnectHandler, m_defaultQos);
344 }
345
346 OCStackResult OCAccountManager::cancelObserveGroup()
347 {
348     VERIFY_NON_EMPTY(m_userUuid, "Need to sign-in first.", OC_STACK_ERROR);
349
350     if (nullptr == m_groupObserveHandle)
351     {
352         oclog() << "observeGroup() has not been done." << std::flush;
353         return result_guard(OC_STACK_INVALID_PARAM);
354     }
355
356     std::string uri = m_host + OC_RSRVD_ACL_GROUP_URI
357                       + "?" + OC_RSRVD_MEMBERS + "=" + m_userUuid;
358
359     OCStackResult result = checked_guard(m_clientWrapper.lock(),
360                                          &IClientWrapper::CancelObserveResource,
361                                          m_groupObserveHandle, (const char*)"", uri,
362                                          HeaderOptions(), m_defaultQos);
363     if (OC_STACK_OK == result)
364     {
365         m_groupObserveHandle = nullptr;
366     }
367
368     return result;
369 }
370
371 OCStackResult OCAccountManager::observeInvitation(ObserveCallback cloudConnectHandler)
372 {
373     std::string uri = m_host + OC_RSRVD_ACL_INVITE_URI;
374
375     return checked_guard(m_clientWrapper.lock(), &IClientWrapper::ObserveResource,
376                          ObserveType::Observe, &m_invitationObserveHandle, OCDevAddr(), uri,
377                          QueryParamsMap(), HeaderOptions(), cloudConnectHandler, m_defaultQos);
378 }
379
380 OCStackResult OCAccountManager::cancelObserveInvitation()
381 {
382     if (nullptr == m_invitationObserveHandle)
383     {
384         oclog() << "observeInvitation() has not been done." << std::flush;
385         return result_guard(OC_STACK_INVALID_PARAM);
386     }
387
388     std::string uri = m_host + OC_RSRVD_ACL_INVITE_URI;
389
390     OCStackResult result = checked_guard(m_clientWrapper.lock(),
391                                          &IClientWrapper::CancelObserveResource,
392                                          m_invitationObserveHandle,
393                                          (const char*)"", uri, HeaderOptions(), m_defaultQos);
394     if (OC_STACK_OK == result)
395     {
396         m_invitationObserveHandle = nullptr;
397     }
398
399     return result;
400 }
401
402 OCStackResult OCAccountManager::sendInvitation(const std::string& groupId,
403                                                const std::string& userUuid,
404                                                PostCallback cloudConnectHandler)
405 {
406     VERIFY_NON_EMPTY(m_userUuid, "Need to sign-in first.", OC_STACK_ERROR);
407     VERIFY_NON_EMPTY(groupId, "groupId cannot be empty.", OC_STACK_INVALID_PARAM);
408     VERIFY_NON_EMPTY(userUuid, "userUuid cannot be empty.", OC_STACK_INVALID_PARAM);
409
410     std::string uri = m_host + OC_RSRVD_ACL_INVITE_URI;
411
412     OCRepresentation invitation;
413     invitation.setValue<std::string>(OC_RSRVD_GROUP_ID, groupId);
414     invitation.setValue<std::string>(OC_RSRVD_MEMBER_ID, userUuid);
415
416     std::vector<OCRepresentation> invite{invitation};
417
418     OCRepresentation rep;
419     rep.setValue<std::string>(OC_RSRVD_USER_UUID, m_userUuid);
420     rep.setValue<std::vector<OCRepresentation>>(OC_RSRVD_INVITE, invite);
421
422     return checked_guard(m_clientWrapper.lock(), &IClientWrapper::PostResourceRepresentation,
423                          OCDevAddr(), uri, rep, QueryParamsMap(), HeaderOptions(),
424                          m_connType, cloudConnectHandler, m_defaultQos);
425 }
426
427 OCStackResult OCAccountManager::cancelInvitation(const std::string& groupId,
428                                                  const std::string& userUuid,
429                                                  DeleteCallback cloudConnectHandler)
430 {
431     VERIFY_NON_EMPTY(groupId, "groupId cannot be empty.", OC_STACK_INVALID_PARAM);
432     VERIFY_NON_EMPTY(userUuid, "userUuid cannot be empty.", OC_STACK_INVALID_PARAM);
433
434     std::string uri = m_host + OC_RSRVD_ACL_INVITE_URI + "?" + OC_RSRVD_GROUP_ID + "=" + groupId
435                       + ";" + OC_RSRVD_MEMBER_ID + "=" + userUuid;
436
437     return checked_guard(m_clientWrapper.lock(), &IClientWrapper::DeleteResource,
438                          OCDevAddr(), uri, HeaderOptions(),
439                          m_connType, cloudConnectHandler, m_defaultQos);
440 }
441
442 OCStackResult OCAccountManager::replyToInvitation(const std::string& groupId,
443                                                   const bool accept,
444                                                   DeleteCallback cloudConnectHandler)
445 {
446     VERIFY_NON_EMPTY(groupId, "groupId cannot be empty.", OC_STACK_INVALID_PARAM);
447
448     std::string isAccept = accept ? "1" : "0";
449
450     std::string uri = m_host + OC_RSRVD_ACL_INVITE_URI + "?" + OC_RSRVD_GROUP_ID + "=" + groupId
451                       + ";" + OC_RSRVD_ACCEPT + "=" + isAccept;
452
453     return checked_guard(m_clientWrapper.lock(), &IClientWrapper::DeleteResource,
454                          OCDevAddr(), uri, HeaderOptions(),
455                          m_connType, cloudConnectHandler, m_defaultQos);
456 }
457
458 } // namespace OC