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