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 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
34 #ifdef HAVE_SYS_TIME_H
37 #include <boost/config.hpp>
40 #include "oic_malloc.h"
41 #include "oic_string.h"
44 #include "ocserverslow.h"
45 #include "ocpayload.h"
46 #include "payload_logging.h"
48 volatile sig_atomic_t gQuitFlag = 0;
50 static std::list<OCEntityHandlerRequest *> gRequestList;
51 BOOST_STATIC_CONSTEXPR unsigned int SLOW_RESPONSE_DELAY_SEC = 5;
53 static LEDResource LED;
55 BOOST_STATIC_CONSTEXPR unsigned int SAMPLE_MAX_NUM_POST_INSTANCE = 2;
56 static LEDResource gLedInstance[SAMPLE_MAX_NUM_POST_INSTANCE];
58 //char *gResourceUri= const_cast<char *>("/a/led");
59 char *gResourceUri= (char *)"/a/led";
61 //This function takes the request as an input and returns the response
63 OCRepPayload* constructResponse (OCEntityHandlerRequest *ehRequest)
65 LEDResource *currLEDResource = &LED;
67 OIC_LOG(INFO, TAG, "Entering constructResponse");
69 if (ehRequest->resource == gLedInstance[0].handle)
71 OIC_LOG(INFO, TAG, "handle 0");
72 currLEDResource = &gLedInstance[0];
73 gResourceUri = const_cast<char *>("a/led/0");
75 else if (ehRequest->resource == gLedInstance[1].handle)
77 OIC_LOG(INFO, TAG, "handle 1");
78 currLEDResource = &gLedInstance[1];
79 gResourceUri = const_cast<char *>("a/led/1");
82 if(OC_REST_PUT == ehRequest->method)
84 if(ehRequest->payload && ehRequest->payload->type != PAYLOAD_TYPE_REPRESENTATION)
86 OIC_LOG(ERROR, TAG, ("Incoming payload not a representation"));
90 OCRepPayload *putPayload = reinterpret_cast<OCRepPayload*> (ehRequest->payload);
95 if (OCRepPayloadGetPropBool(putPayload, "state", &state))
97 currLEDResource->state = state;
99 if (OCRepPayloadGetPropInt (putPayload, "power", &power))
101 currLEDResource->power = power;
105 OCRepPayload *response = OCRepPayloadCreate();
109 OIC_LOG_V(ERROR, TAG, "Memory allocation for response payload failed.");
112 OCRepPayloadSetUri (response, gResourceUri);
113 OCRepPayloadSetPropBool(response, "state", currLEDResource->state);
114 OCRepPayloadSetPropInt(response, "power", currLEDResource->power);
119 void ProcessGetPutRequest (OCEntityHandlerRequest *ehRequest)
121 OIC_LOG(INFO, TAG, "Entering ProcessGetPutRequest");
123 OCRepPayload *getResp = constructResponse(ehRequest);
127 OIC_LOG(ERROR, TAG, "Failed to construct response");
131 OCEntityHandlerResponse response;
133 // Format the response. Note this requires some info about the request
134 response.requestHandle = ehRequest->requestHandle;
135 response.resourceHandle = ehRequest->resource;
136 response.ehResult = OC_EH_OK;
137 response.payload = reinterpret_cast<OCPayload*> (getResp);
138 response.numSendVendorSpecificHeaderOptions = 0;
139 memset(response.sendVendorSpecificHeaderOptions,
140 0, sizeof response.sendVendorSpecificHeaderOptions);
141 memset(response.resourceUri, 0, sizeof(response.resourceUri));
142 // Indicate that response is NOT in a persistent buffer
143 response.persistentBufferFlag = 0;
146 if (OCDoResponse(&response) != OC_STACK_OK)
148 OIC_LOG(ERROR, TAG, "Error sending response");
154 OCEntityHandlerRequest *CopyRequest(OCEntityHandlerRequest *entityHandlerRequest)
156 OIC_LOG(INFO, TAG, "Copying received request for slow response");
158 OCEntityHandlerRequest *copyOfRequest =
159 (OCEntityHandlerRequest *)OICMalloc(sizeof(OCEntityHandlerRequest));
164 memcpy(copyOfRequest, entityHandlerRequest, sizeof(OCEntityHandlerRequest));
167 if (copyOfRequest->query)
169 copyOfRequest->query = OICStrdup(entityHandlerRequest->query);
170 if(!copyOfRequest->query)
172 OIC_LOG(ERROR, TAG, "Copy failed due to allocation failure");
173 OICFree(copyOfRequest);
178 if (entityHandlerRequest->payload)
180 copyOfRequest->payload = reinterpret_cast<OCPayload*>
181 (OCRepPayloadClone ((OCRepPayload*) entityHandlerRequest->payload));
184 // Ignore vendor specific header options for example
185 copyOfRequest->numRcvdVendorSpecificHeaderOptions = 0;
186 copyOfRequest->rcvdVendorSpecificHeaderOptions = NULL;
191 OIC_LOG(INFO, TAG, "Copied client request");
195 OIC_LOG(ERROR, TAG, "Error copying client request");
197 return copyOfRequest;
200 #if !defined(SIGALRM)
201 void AlarmHandler(int sig);
202 int WINAPI AlarmThread(void *seconds)
204 sleep((unsigned int)seconds);
209 void alarm(unsigned int seconds)
211 CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)AlarmThread, (void*)seconds, 0, NULL);
215 OCEntityHandlerResult OCEntityHandlerCb (OCEntityHandlerFlag flag,
216 OCEntityHandlerRequest *entityHandlerRequest, void* /*callbackParam*/)
218 OCEntityHandlerResult result = OC_EH_ERROR;
219 OCEntityHandlerRequest *request = NULL;
221 OIC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
223 if (flag & OC_REQUEST_FLAG)
225 OIC_LOG(INFO, TAG, "Flag includes OC_REQUEST_FLAG");
226 if (entityHandlerRequest)
228 OIC_LOG_V (INFO, TAG, "request query %s from client",
229 entityHandlerRequest->query);
230 OIC_LOG_PAYLOAD (INFO, entityHandlerRequest->payload);
232 // Make deep copy of received request and queue it for slow processing
233 request = CopyRequest(entityHandlerRequest);
238 OIC_LOG(INFO, TAG, "Scheduling slow response for received request");
239 gRequestList.push_back(request);
240 // Indicate to the stack that this is a slow response
242 // Start the slow response alarm
243 alarm(SLOW_RESPONSE_DELAY_SEC);
247 OIC_LOG(ERROR, TAG, "Error queuing request for slow response");
248 // Indicate to the stack that this is a slow response
249 result = OC_EH_ERROR;
254 OIC_LOG(ERROR, TAG, "Invalid request");
255 result = OC_EH_ERROR;
261 /* SIGINT handler: set gQuitFlag to 1 for graceful termination */
262 void handleSigInt(int signum)
264 if (signum == SIGINT)
270 // SIGINT alarm handler: alarm set by entity handler. Does
271 // slow response when fired
272 void AlarmHandler(int sig)
278 OIC_LOG (INFO, TAG, "Server starting slow response");
279 if (gRequestList.empty())
281 OIC_LOG (INFO, TAG, "No requests to service");
285 // Get the request from the list
286 OCEntityHandlerRequest *entityHandlerRequest = gRequestList.front();
287 gRequestList.pop_front();
288 if (entityHandlerRequest->method == OC_REST_GET)
290 OIC_LOG (INFO, TAG, "Received OC_REST_GET from client");
291 ProcessGetPutRequest (entityHandlerRequest);
293 else if (entityHandlerRequest->method == OC_REST_PUT)
295 OIC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
296 ProcessGetPutRequest (entityHandlerRequest);
300 OIC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
301 entityHandlerRequest->method);
304 OICFree(entityHandlerRequest->query);
305 OCPayloadDestroy(entityHandlerRequest->payload);
306 OICFree(entityHandlerRequest);
308 // If there are more requests in list, re-arm the alarm signal
309 if (gRequestList.empty())
311 alarm(SLOW_RESPONSE_DELAY_SEC);
316 int main(int /*argc*/, char** /*argv[]*/)
318 OIC_LOG(DEBUG, TAG, "OCServer is starting...");
320 if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
322 OIC_LOG(ERROR, TAG, "OCStack init error");
326 // Declare and create the example resource: LED
327 createLEDResource(gResourceUri, &LED, false, 42);
330 // Initialize slow response alarm
331 signal(SIGALRM, AlarmHandler);
334 // Break from loop with Ctrl-C
335 OIC_LOG(INFO, TAG, "Entering ocserver main loop...");
336 signal(SIGINT, handleSigInt);
340 if (OCProcess() != OC_STACK_OK)
342 OIC_LOG(ERROR, TAG, "OCStack process error");
348 OIC_LOG(INFO, TAG, "Exiting ocserver main loop...");
351 if (!gRequestList.empty())
353 for (auto iter = gRequestList.begin(); iter != gRequestList.end(); ++iter)
355 OICFree((*iter)->query);
356 OCPayloadDestroy((*iter)->payload);
359 gRequestList.clear();
362 if (OCStop() != OC_STACK_OK)
364 OIC_LOG(ERROR, TAG, "OCStack process error");
370 int createLEDResource (char *uri, LEDResource *ledResource, bool resourceState, int resourcePower)
374 OIC_LOG(ERROR, TAG, "Resource URI cannot be NULL");
378 ledResource->state = resourceState;
379 ledResource->power= resourcePower;
380 OCStackResult res = OCCreateResource(&(ledResource->handle),
382 OC_RSRVD_INTERFACE_DEFAULT,
386 OC_DISCOVERABLE|OC_OBSERVABLE);
387 OIC_LOG_V(INFO, TAG, "Created LED resource with result: %s", getResult(res));