Merge "Partial Implementation of US1574:"
[platform/upstream/iotivity.git] / csdk / ubstack / src / ocmodelimpl.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 // ============================================================================
23 // Includes
24 // ============================================================================
25 #include "ocmodelimpl.h"
26 extern "C" {
27     #include "logger.h"
28 }
29
30 #include <stdlib.h>
31 #include <time.h>
32 #include <cstdlib>
33
34 // ============================================================================
35 // Namespace
36 // ============================================================================
37 namespace oc {
38 namespace ub {
39
40 static const char TAG[] = "OCModelImpl";
41
42 // Global variable used by friend async callback function to access the OCModelImpl instance
43 OCModelImpl *pModelImpl = 0;
44
45 /**
46  * Asynchronous callback friend function invoked by the OC Stack upon service discovery
47  *
48  * @param result         - OC stack result
49  * @param representation - handle to the representation of the resource
50  */
51 void asyncDoResourcesCallback(OCStackResult result, OCRepresentationHandle representation) {
52     OC_LOG(INFO, TAG, "Entering asyncDoResourcesCallback");
53
54     if (representation && (result == OC_STACK_OK)) {
55         OCResource *resource = (OCResource *)representation;
56         OC_LOG_V(INFO, TAG, "URI = %s", resource->uri);
57
58         // If the pointer is valid, make a call to the OCModelImpl instance method
59         if (pModelImpl) {
60             pModelImpl->addService(resource->uri);
61         }
62     }
63 }
64
65 // ============================================================================
66 // OCDiscoverServicesResult Implementation Class
67 // ============================================================================
68 class OCDiscoverServicesSuccess : public OCDiscoverServicesResult {
69 public:
70         virtual ~OCDiscoverServicesSuccess() {}
71
72 // ============================================================
73 // Public Method(s)
74 // ============================================================
75 public:
76         virtual OCQueryResultType getResult() const {
77                 return SUCCESS;
78         }
79
80         virtual const std::list<std::string>& getServiceList() const {
81                 return serviceList;
82         }
83
84 public:
85         std::list<std::string> serviceList;
86 };
87
88
89 // ============================================================================
90 // Model Factory
91 // ============================================================================
92 OCModel::SharedPtr OCModel::createModel() {
93     OC_LOG(INFO, TAG, "Entering OCModel::createModel");
94         return OCModelImpl::createModel();
95 }
96
97 OCModelImpl::SharedPtr OCModelImpl::createModel() {
98         // Get singleton of ModelImpl.
99     OC_LOG(INFO, TAG, "Entering OCModelImpl::createModel");
100         static SharedPtr instance = std::make_shared<OCModelImpl>();
101
102         return instance;
103 }
104 // ============================================================================
105 // Constructors & Destructors
106 // ============================================================================
107 OCModelImpl::OCModelImpl() {
108     OC_LOG(INFO, TAG, "Entering OCModel::OCModelImpl");
109
110     pModelImpl = this;
111     discoverCallback = 0;
112 }
113
114 OCModelImpl::~OCModelImpl() {
115     OC_LOG(INFO, TAG, "Entering OCModel::~OCModelImpl");
116     // Call OCStack layer
117     if (OCStop() != OC_STACK_OK) {
118         OC_LOG(ERROR, TAG, "Stack shutdown error");
119     }
120
121     discoverCallback = 0;
122         serviceList.clear();
123 }
124
125 // ============================================================================
126 // Public methods
127 // ============================================================================
128 /**
129  * Start the OC Stack.
130  *
131  * @param ipAddr
132  *     IP Address of host device
133  * @param port
134  *     Port of host device*
135  * @param mode
136  *     Host device is client, server, or client-server
137  *
138  * @return
139  *     true  - successfully started the OC Stack
140  *     false - error starting the OC Stack
141  */
142 bool OCModelImpl::start(const std::string ipAddr, int16_t port, OCStackMode mode) {
143     OC_LOG_V(INFO, TAG, "Entering OCModelImpl::start, IP = %s, port = %d", ipAddr.c_str(), (int)port);
144
145     // Call OCStack layer - initialize stack
146     if (OCInit(ipAddr.c_str(), port, (OCMode)mode) != OC_STACK_OK) {
147         OC_LOG(ERROR, TAG, "Stack initialization error");
148         return false;
149     }
150
151     // Call OCStack layer - enable device discovery and provide a callback
152     if (OCDoResource(OC_REST_GET, OC_EXPLICIT_DEVICE_DISCOVERY_URI, 0, 0, asyncDoResourcesCallback) != OC_STACK_OK) {
153         OC_LOG(ERROR, TAG, "Stack discovery error");
154         return false;
155     }
156     return true;
157 }
158
159 /**
160  * Get all services that have been discovered at time of call
161  *
162  * @param asyncReturnFunc - asynchronous callback function that is invoked
163  *                          by the OCModelImpl when service discovery
164  *                          is complete.  The callback will include
165  *                          status and a list of all discovered services
166  */
167 void OCModelImpl::discoverServices(OCDiscoverServicesFunction& asyncReturnFunc) {
168     OC_LOG(INFO, TAG, "Entering OCModelImpl::discoverServices");
169
170         mutex_lock_guard lock(serviceListMutex);
171
172         // Save the callback
173         discoverCallback = asyncReturnFunc;
174
175         // Invoke the callback immediately
176         invokeDiscoverCallback();
177 }
178
179 /**
180  * Add a service to the OCModelImpl
181  *
182  * @param url - URL of the service
183  * @return Total number of services in the OCModelImpl
184  */
185 uint16_t OCModelImpl::addService(const std::string url) {
186     OC_LOG_V(INFO, TAG, "Entering OCModelImpl::addService, service = %s", url.c_str());
187     serviceList.push_back(url);
188
189     invokeDiscoverCallback();
190     return (uint16_t)serviceList.size();
191 }
192
193 /**
194  * Internal methods that invokes the client callback (if it was previously set via discoverServices)
195  * Called when a new service is discovered.
196  */
197 void OCModelImpl::invokeDiscoverCallback() {
198     OC_LOG(INFO, TAG, "Entering OCModelImpl::invokeDiscoverCallback");
199     // Only invoke the callback if it has been set and and at least one service has been added
200     // to the service list
201     if (discoverCallback && (serviceList.size() > 0)) {
202         OC_LOG(INFO, TAG, "Invoking callback");
203
204         OCDiscoverServicesSuccess result;
205         // Insert from the model device list to the result device list
206         result.serviceList.insert(result.serviceList.end(), serviceList.begin(), serviceList.end());
207
208         // Invoke the callback
209         discoverCallback(result);
210     }
211 }
212
213 }
214 }