1 //******************************************************************
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
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
11 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21 #include "iotivity_config.h"
35 #ifdef HAVE_SYS_TIME_H
38 #include <boost/config.hpp>
41 #include "oic_malloc.h"
42 #include "oic_string.h"
45 #include "ocserverslow.h"
46 #include "ocpayload.h"
47 #include "payload_logging.h"
49 volatile sig_atomic_t gQuitFlag = 0;
51 static std::list<OCEntityHandlerRequest *> gRequestList;
52 BOOST_STATIC_CONSTEXPR unsigned int SLOW_RESPONSE_DELAY_SEC = 5;
54 static LEDResource LED;
56 BOOST_STATIC_CONSTEXPR unsigned int SAMPLE_MAX_NUM_POST_INSTANCE = 2;
57 static LEDResource gLedInstance[SAMPLE_MAX_NUM_POST_INSTANCE];
59 //char *gResourceUri= const_cast<char *>("/a/led");
60 char *gResourceUri= (char *)"/a/led";
62 //This function takes the request as an input and returns the response
64 OCRepPayload* constructResponse (OCEntityHandlerRequest *ehRequest)
66 LEDResource *currLEDResource = &LED;
68 OIC_LOG(INFO, TAG, "Entering constructResponse");
70 if (ehRequest->resource == gLedInstance[0].handle)
72 OIC_LOG(INFO, TAG, "handle 0");
73 currLEDResource = &gLedInstance[0];
74 gResourceUri = const_cast<char *>("a/led/0");
76 else if (ehRequest->resource == gLedInstance[1].handle)
78 OIC_LOG(INFO, TAG, "handle 1");
79 currLEDResource = &gLedInstance[1];
80 gResourceUri = const_cast<char *>("a/led/1");
83 if(OC_REST_PUT == ehRequest->method)
85 if(ehRequest->payload && ehRequest->payload->type != PAYLOAD_TYPE_REPRESENTATION)
87 OIC_LOG(ERROR, TAG, ("Incoming payload not a representation"));
91 OCRepPayload *putPayload = reinterpret_cast<OCRepPayload*> (ehRequest->payload);
96 if (OCRepPayloadGetPropBool(putPayload, "state", &state))
98 currLEDResource->state = state;
100 if (OCRepPayloadGetPropInt (putPayload, "power", &power))
102 currLEDResource->power = power;
106 OCRepPayload *response = OCRepPayloadCreate();
110 OIC_LOG_V(ERROR, TAG, "Memory allocation for response payload failed.");
113 OCRepPayloadSetUri (response, gResourceUri);
114 OCRepPayloadSetPropBool(response, "state", currLEDResource->state);
115 OCRepPayloadSetPropInt(response, "power", currLEDResource->power);
120 void ProcessGetPutRequest (OCEntityHandlerRequest *ehRequest)
122 OIC_LOG(INFO, TAG, "Entering ProcessGetPutRequest");
124 OCRepPayload *getResp = constructResponse(ehRequest);
128 OIC_LOG(ERROR, TAG, "Failed to construct response");
132 OCEntityHandlerResponse response;
134 // Format the response. Note this requires some info about the request
135 response.requestHandle = ehRequest->requestHandle;
136 response.resourceHandle = ehRequest->resource;
137 response.ehResult = OC_EH_OK;
138 response.payload = reinterpret_cast<OCPayload*> (getResp);
139 response.numSendVendorSpecificHeaderOptions = 0;
140 memset(response.sendVendorSpecificHeaderOptions,
141 0, sizeof response.sendVendorSpecificHeaderOptions);
142 memset(response.resourceUri, 0, sizeof(response.resourceUri));
143 // Indicate that response is NOT in a persistent buffer
144 response.persistentBufferFlag = 0;
147 if (OCDoResponse(&response) != OC_STACK_OK)
149 OIC_LOG(ERROR, TAG, "Error sending response");
155 OCEntityHandlerRequest *CopyRequest(OCEntityHandlerRequest *entityHandlerRequest)
157 OIC_LOG(INFO, TAG, "Copying received request for slow response");
159 OCEntityHandlerRequest *copyOfRequest =
160 (OCEntityHandlerRequest *)OICMalloc(sizeof(OCEntityHandlerRequest));
165 memcpy(copyOfRequest, entityHandlerRequest, sizeof(OCEntityHandlerRequest));
168 if (copyOfRequest->query)
170 copyOfRequest->query = OICStrdup(entityHandlerRequest->query);
171 if(!copyOfRequest->query)
173 OIC_LOG(ERROR, TAG, "Copy failed due to allocation failure");
174 OICFree(copyOfRequest);
179 if (entityHandlerRequest->payload)
181 copyOfRequest->payload = reinterpret_cast<OCPayload*>
182 (OCRepPayloadClone ((OCRepPayload*) entityHandlerRequest->payload));
185 // Ignore vendor specific header options for example
186 copyOfRequest->numRcvdVendorSpecificHeaderOptions = 0;
187 copyOfRequest->rcvdVendorSpecificHeaderOptions = NULL;
192 OIC_LOG(INFO, TAG, "Copied client request");
196 OIC_LOG(ERROR, TAG, "Error copying client request");
198 return copyOfRequest;
201 #if !defined(SIGALRM)
202 void AlarmHandler(int sig);
203 int WINAPI AlarmThread(void *seconds)
205 sleep((unsigned int)seconds);
210 void alarm(unsigned int seconds)
212 CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)AlarmThread, (void*)seconds, 0, NULL);
216 OCEntityHandlerResult OCEntityHandlerCb (OCEntityHandlerFlag flag,
217 OCEntityHandlerRequest *entityHandlerRequest, void* /*callbackParam*/)
219 OCEntityHandlerResult result = OC_EH_ERROR;
220 OCEntityHandlerRequest *request = NULL;
222 OIC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
224 if (flag & OC_REQUEST_FLAG)
226 OIC_LOG(INFO, TAG, "Flag includes OC_REQUEST_FLAG");
227 if (entityHandlerRequest)
229 OIC_LOG_V (INFO, TAG, "request query %s from client",
230 entityHandlerRequest->query);
231 OIC_LOG_PAYLOAD (INFO, entityHandlerRequest->payload);
233 // Make deep copy of received request and queue it for slow processing
234 request = CopyRequest(entityHandlerRequest);
239 OIC_LOG(INFO, TAG, "Scheduling slow response for received request");
240 gRequestList.push_back(request);
241 // Indicate to the stack that this is a slow response
243 // Start the slow response alarm
244 alarm(SLOW_RESPONSE_DELAY_SEC);
248 OIC_LOG(ERROR, TAG, "Error queuing request for slow response");
249 // Indicate to the stack that this is a slow response
250 result = OC_EH_ERROR;
255 OIC_LOG(ERROR, TAG, "Invalid request");
256 result = OC_EH_ERROR;
262 /* SIGINT handler: set gQuitFlag to 1 for graceful termination */
263 void handleSigInt(int signum)
265 if (signum == SIGINT)
271 // SIGINT alarm handler: alarm set by entity handler. Does
272 // slow response when fired
273 void AlarmHandler(int sig)
279 OIC_LOG (INFO, TAG, "Server starting slow response");
280 if (gRequestList.empty())
282 OIC_LOG (INFO, TAG, "No requests to service");
286 // Get the request from the list
287 OCEntityHandlerRequest *entityHandlerRequest = gRequestList.front();
288 gRequestList.pop_front();
289 if (entityHandlerRequest->method == OC_REST_GET)
291 OIC_LOG (INFO, TAG, "Received OC_REST_GET from client");
292 ProcessGetPutRequest (entityHandlerRequest);
294 else if (entityHandlerRequest->method == OC_REST_PUT)
296 OIC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
297 ProcessGetPutRequest (entityHandlerRequest);
301 OIC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
302 entityHandlerRequest->method);
305 OICFree(entityHandlerRequest->query);
306 OCPayloadDestroy(entityHandlerRequest->payload);
307 OICFree(entityHandlerRequest);
309 // If there are more requests in list, re-arm the alarm signal
310 if (gRequestList.empty())
312 alarm(SLOW_RESPONSE_DELAY_SEC);
317 int main(int /*argc*/, char** /*argv[]*/)
319 OIC_LOG(DEBUG, TAG, "OCServer is starting...");
321 if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
323 OIC_LOG(ERROR, TAG, "OCStack init error");
327 // Declare and create the example resource: LED
328 createLEDResource(gResourceUri, &LED, false, 42);
331 // Initialize slow response alarm
332 signal(SIGALRM, AlarmHandler);
335 // Break from loop with Ctrl-C
336 OIC_LOG(INFO, TAG, "Entering ocserver main loop...");
337 signal(SIGINT, handleSigInt);
341 if (OCProcess() != OC_STACK_OK)
343 OIC_LOG(ERROR, TAG, "OCStack process error");
349 OIC_LOG(INFO, TAG, "Exiting ocserver main loop...");
352 if (!gRequestList.empty())
354 for (auto iter = gRequestList.begin(); iter != gRequestList.end(); ++iter)
356 OICFree((*iter)->query);
357 OCPayloadDestroy((*iter)->payload);
360 gRequestList.clear();
363 if (OCStop() != OC_STACK_OK)
365 OIC_LOG(ERROR, TAG, "OCStack process error");
371 int createLEDResource (char *uri, LEDResource *ledResource, bool resourceState, int resourcePower)
375 OIC_LOG(ERROR, TAG, "Resource URI cannot be NULL");
379 ledResource->state = resourceState;
380 ledResource->power= resourcePower;
381 OCStackResult res = OCCreateResource(&(ledResource->handle),
383 OC_RSRVD_INTERFACE_DEFAULT,
387 OC_DISCOVERABLE|OC_OBSERVABLE);
388 OIC_LOG_V(INFO, TAG, "Created LED resource with result: %s", getResult(res));