Merge "Partial Implementation of US1574:"
[platform/upstream/iotivity.git] / csdk / controller / src / remoting / LiteRemoting.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 // ============================================================================
22 // Includes
23 // ============================================================================
24 #include "LiteRemoting.h"
25
26 #include <boost/make_shared.hpp>
27 #include <boost/bind.hpp>
28 #include <functional>
29 #include <stdexcept>
30
31 #ifdef DEBUG
32 #include <android/log.h>
33 #endif
34
35 // ============================================================================
36 // Namespace
37 // ============================================================================
38 namespace remoting {
39
40   // ============================================================================
41   // Macros
42   // ============================================================================
43   // TODO:  Need application ID for Remoting
44   const std::string LiteRemoting::APPLICATION_UUID_STRING = "7A1B397B-B576-44C4-943F-000000000001";
45
46 // ============================================================================
47 // Macros
48 // ============================================================================
49 #ifdef DEBUG
50   #define LOG_PRINT(X)       __android_log_print(ANDROID_LOG_VERBOSE, "LiteRemoting", (X));
51 #else
52   #define LOG_PRINT(X)
53 #endif
54
55 // ============================================================================
56 // Constructor/Destructor/getInstance
57 // ============================================================================
58   //---------------------------------------------------------------------------
59   // Constructor
60   // Called by getInstance method (Singleton patter)
61   //---------------------------------------------------------------------------
62         LiteRemoting::LiteRemoting(PrivateConstructKey key) {
63
64           apiResultReady_ = false;
65
66 //  public static final String  applicationId = "7A1B397B-B576-44C4-943F-000000000001";
67 //  public static final UUID    applicationUUID = UUID.fromString(applicationId);
68
69           // Begin CCF API interaction
70           pCCFService_ = API::Service::createService();
71           if (pCCFService_)
72           {
73       pCCFService_->registerApplication();
74
75       UUID_t applicationId;
76       StringToUuid(APPLICATION_UUID_STRING.c_str(), &applicationId);
77
78       pCCFContext_ = pCCFService_->createContext(applicationId);
79
80       if (pCCFContext_)
81       {
82         doStartup();
83       }
84           }
85         }
86
87   //---------------------------------------------------------------------------
88   // Destructor
89   //---------------------------------------------------------------------------
90         LiteRemoting::~LiteRemoting() {
91           // Empty containers
92           sessionMap_.clear();
93           targetDeviceProxyMap_.clear();
94
95           // Turn off observer callbacks
96           pCCFContext_->setSessionObserver();
97           pCCFContext_->setUserObserver();
98
99           // CCF APP interaction
100           if (pCCFService_)
101           {
102             pCCFService_->deregisterApplication();
103           }
104         }
105
106   //---------------------------------------------------------------------------
107   // getInstance (Singleton pattern
108   //---------------------------------------------------------------------------
109         // Get singleton instance of LiteRemoting
110         boost::shared_ptr<LiteRemoting> LiteRemoting::getInstance() {
111           LOG_PRINT("LiteRemoting::getInstance()");
112
113                 static boost::shared_ptr<LiteRemoting> instance = boost::make_shared<LiteRemoting>(PrivateConstructKey());
114
115                 return instance;
116         }
117
118 // ============================================================================
119 // Methods
120 // ============================================================================
121         void LiteRemoting::doStartup() {
122
123           // Get the local session id
124           boost::unique_lock<boost::mutex> lock(mutex_);
125           queryMySessionId();
126           while (!apiResultReady_)
127           {
128             // TODO: maybe do cond_.timed_wait() ???
129             cond_.wait(lock);
130           }
131
132           // Get local session info
133           lock.lock();
134           queryMySessionInfo();
135     while (!apiResultReady_)
136     {
137       // TODO: maybe do cond_.timed_wait() ???
138       cond_.wait(lock);
139     }
140
141     // Now that we have local session info, set the session observer
142     pCCFContext_->setSessionObserver(boost::bind(&LiteRemoting::sessionObserver, this, _1));
143
144     // TODO:  set up connection observer
145
146     // TODO: set up device observer
147
148         }
149
150         void LiteRemoting::addSessionToMap(UUID_t sessionId) {
151     // Add session to the sessionMap
152     auto iter = sessionMap_.find(sessionId);
153     if (iter == sessionMap_.end() )
154     {
155       // sessionUUID not found, so add session
156       sessionMap_[sessionId] = boost::make_shared<LiteSessionImpl>(pCCFContext_, sessionId);
157     }
158         }
159
160         boost::shared_ptr<LiteSessionImpl> LiteRemoting::getSessionFromMap(UUID_t sessionId) {
161           boost::shared_ptr<LiteSessionImpl> pSession;
162           try {
163             pSession = sessionMap_.at(sessionId);
164           }
165           catch (const std::out_of_range& oor) {
166       // sessionId not found, so add session
167       sessionMap_[sessionId] = boost::make_shared<LiteSessionImpl>(pCCFContext_, sessionId);
168           }
169
170           return sessionMap_[sessionId];
171         }
172
173         void LiteRemoting::addTargetDeviceToMap(UUID_t targetDeviceId) {
174     // A LiteTargetDeviceProxy with this targetDeviceId was not found, so add
175     // Add target device to the targetDeviceProxyMap_
176     auto iter = targetDeviceProxyMap_.find(targetDeviceId);
177     if (iter == targetDeviceProxyMap_.end() )
178     {
179       // targetDeviceId not found, so add session
180       targetDeviceProxyMap_[targetDeviceId] = boost::make_shared<LiteTargetDeviceProxy>(targetDeviceId);
181     }
182
183         }
184
185         boost::shared_ptr<LiteTargetDeviceProxy> LiteRemoting::getTargetDeviceFromMap(UUID_t targetDeviceId) {
186     boost::shared_ptr<LiteTargetDeviceProxy> pTargetDevice;
187     try {
188       pTargetDevice = targetDeviceProxyMap_.at(targetDeviceId);
189     }
190     catch (const std::out_of_range& oor) {
191       // sessionId not found, so add session
192       targetDeviceProxyMap_[targetDeviceId] = boost::make_shared<LiteTargetDeviceProxy>(targetDeviceId);
193     }
194
195     return targetDeviceProxyMap_[targetDeviceId];
196
197         }
198
199         void LiteRemoting::handleNewTargetDevice(UUID_t targetDeviceId) {
200           addTargetDeviceToMap(targetDeviceId);
201           //session.sendDeviceArrival(device);
202         }
203
204         // TODO: socket parameter is faked with an int for now until I know how the connection info will be conveyed
205         void LiteRemoting::handleNewConnection(UUID_t sessionId, int socket) {
206           // Validate socket
207           if (socket == 0) {
208             return;
209           }
210
211           // Get the specified session and a new connection
212           boost::shared_ptr<LiteSessionImpl> pSession = getSessionFromMap(sessionId);
213           boost::shared_ptr<LiteConnection> pConnection = boost::make_shared<LiteConnection>(socket);
214           // TODO: add device info to connection
215
216           //    List<LiteDeviceProxy> deviceProxyList = new ArrayList<LiteDeviceProxy>();
217           //    synchronized (deviceProxySet) {
218           //      for(LiteDeviceProxy device : deviceProxySet) {
219           //        if (device.isLocal()) {
220           //          deviceProxyList.add(device);
221           //        }
222           //      }
223           //    }
224           //    for(LiteDeviceProxy device : deviceProxyList) {
225           //      try {
226           //        connection.sendDeviceArrival(device);
227           //      } catch (IOException e) {
228           //        e.printStackTrace();
229           //      }
230           //    }
231
232           // Add the new connection to the session
233           pSession->addConnection(pConnection);
234         }
235
236         void LiteRemoting::queryMySessionId() {
237           apiResultReady_ = false;
238
239     pCCFContext_->querySessionId([this](const API::SessionIdResult& sessionIdResult) -> void {
240
241       API::SessionIdResult::ResultType queryResult = sessionIdResult.getResult();
242       boost::lock_guard<boost::mutex> lock(mutex_);
243       switch (queryResult) {
244         case API::SessionIdResult::ResultType::Success:
245           LOG_PRINT("LiteRemoting::queryMySessionId() - queryResult == Success");
246           mySessionId_ = sessionIdResult.getSessionId();
247           apiResultReady_ = true;
248           break;
249         case API::SessionIdResult::ResultType::InternalError:
250           LOG_PRINT("LiteRemoting::queryMySessionId() - queryResult == InternalError");
251           break;
252         case API::SessionIdResult::ResultType::InvalidLocalSession:
253           LOG_PRINT("LiteRemoting::queryMySessionId() - queryResult == InvalidLocalSession");
254           break;
255         default:
256           LOG_PRINT("LiteRemoting::queryMySessionId() - queryResult == unknown");
257           break;
258       }
259       cond_.notify_one();
260     });
261         }
262
263         void LiteRemoting::queryMySessionInfo()
264         {
265     apiResultReady_ = false;
266
267 //    pCCFContext_->querySession(sessionUUID, std::bind(&LiteRemoting::querySessionObserver, this, _1));
268     pCCFContext_->querySession(mySessionId_, [this](const API::SessionQueryResult& sessionQueryResult) -> void {
269
270       API::QueryResultType queryResult = sessionQueryResult.getResult();
271       boost::lock_guard<boost::mutex> lock(mutex_);
272       switch (queryResult) {
273         case API::QueryResultType::Success:
274           LOG_PRINT("LiteRemoting::queryMySessionInfo() - queryResult == Success");
275           // TODO:  verify that CCF application is in the session application set?
276
277           // Add my local session to the sessionMap
278           addSessionToMap(mySessionId_);
279           sessionMap_[mySessionId_]->setPublicAvatarId(sessionQueryResult.getPublicAvatarId());
280           sessionMap_[mySessionId_]->setPrivateAvatarId(sessionQueryResult.getPrivateAvatarId());
281           sessionMap_[mySessionId_]->setPublicAvatarId(sessionQueryResult.getPublicAvatarId());
282           sessionMap_[mySessionId_]->setUserId(sessionQueryResult.getUserId());
283           sessionMap_[mySessionId_]->setIssuer(sessionQueryResult.getIssuer());
284           sessionMap_[mySessionId_]->setName(sessionQueryResult.getName());
285           sessionMap_[mySessionId_]->setStatusText(sessionQueryResult.getStatusText());
286           sessionMap_[mySessionId_]->setSecurityCode(sessionQueryResult.getSecurityCode());
287           sessionMap_[mySessionId_]->setApplicationSet(sessionQueryResult.getApplicationSet());
288
289           // TODO:  add more conditions before inviting to join session?
290           if (!sessionMap_[mySessionId_]->isConnected() && !sessionMap_[mySessionId_]->isInvited()) {
291             sessionMap_[mySessionId_]->invite();
292           }
293
294           apiResultReady_ = true;
295           break;
296         case API::QueryResultType::NotFound:
297           LOG_PRINT("LiteRemoting::queryMySessionInfo() - queryResult == NotFound");
298           break;
299         default:
300           LOG_PRINT("LiteRemoting::queryMySessionInfo() - queryResult == unknown");
301           break;
302       }
303       cond_.notify_one();
304     });
305         }
306
307 // ============================================================================
308 // Observers
309 // ============================================================================
310         void LiteRemoting::sessionObserver(const API::SessionEvent& sessionEvent)
311         {
312
313     UUID_t sessionId = sessionEvent.getSessionId();
314
315     // TODO: Need to put in logic for seeing what's changed.  Added, dropped, paused?
316 //    int changeMask = sessionEvent.getWhatChanged();
317
318     // See if we already have the session in the map.  If not, create and add
319     addSessionToMap(sessionId);
320         }
321
322 }