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 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
30 #include "oic_malloc.h"
31 #include "oic_string.h"
34 #include "ocserverslow.h"
35 #include "ocpayload.h"
37 volatile sig_atomic_t gQuitFlag = 0;
39 static std::list<OCEntityHandlerRequest *> gRequestList;
40 static constexpr unsigned int SLOW_RESPONSE_DELAY_SEC = 5;
42 static LEDResource LED;
44 static constexpr unsigned int SAMPLE_MAX_NUM_POST_INSTANCE = 2;
45 static LEDResource gLedInstance[SAMPLE_MAX_NUM_POST_INSTANCE];
47 //char *gResourceUri= const_cast<char *>("/a/led");
48 char *gResourceUri= (char *)"/a/led";
50 //This function takes the request as an input and returns the response
52 OCRepPayload* constructResponse (OCEntityHandlerRequest *ehRequest)
54 LEDResource *currLEDResource = &LED;
56 OC_LOG(INFO, TAG, "Entering constructResponse");
58 if (ehRequest->resource == gLedInstance[0].handle)
60 OC_LOG(INFO, TAG, "handle 0");
61 currLEDResource = &gLedInstance[0];
62 gResourceUri = const_cast<char *>("a/led/0");
64 else if (ehRequest->resource == gLedInstance[1].handle)
66 OC_LOG(INFO, TAG, "handle 1");
67 currLEDResource = &gLedInstance[1];
68 gResourceUri = const_cast<char *>("a/led/1");
71 if(OC_REST_PUT == ehRequest->method)
73 if(ehRequest->payload && ehRequest->payload->type != PAYLOAD_TYPE_REPRESENTATION)
75 OC_LOG(ERROR, TAG, PCF("Incoming payload not a representation"));
79 OCRepPayload *putPayload = reinterpret_cast<OCRepPayload*> (ehRequest->payload);
84 if (OCRepPayloadGetPropBool(putPayload, "state", &state))
86 currLEDResource->state = state;
88 if (OCRepPayloadGetPropInt (putPayload, "power", &power))
90 currLEDResource->power = power;
94 OCRepPayload *response = OCRepPayloadCreate();
98 OC_LOG_V(ERROR, TAG, "Memory allocation for response payload failed.");
101 OCRepPayloadSetUri (response, gResourceUri);
102 OCRepPayloadSetPropBool(response, "state", currLEDResource->state);
103 OCRepPayloadSetPropInt(response, "power", currLEDResource->power);
108 void ProcessGetPutRequest (OCEntityHandlerRequest *ehRequest)
110 OC_LOG(INFO, TAG, "Entering ProcessGetPutRequest");
112 OCRepPayload *getResp = constructResponse(ehRequest);
116 OC_LOG(ERROR, TAG, "Failed to construct response");
120 OCEntityHandlerResponse response;
122 // Format the response. Note this requires some info about the request
123 response.requestHandle = ehRequest->requestHandle;
124 response.resourceHandle = ehRequest->resource;
125 response.ehResult = OC_EH_OK;
126 response.payload = reinterpret_cast<OCPayload*> (getResp);
127 response.numSendVendorSpecificHeaderOptions = 0;
128 memset(response.sendVendorSpecificHeaderOptions,
129 0, sizeof response.sendVendorSpecificHeaderOptions);
130 memset(response.resourceUri, 0, sizeof(response.resourceUri));
131 // Indicate that response is NOT in a persistent buffer
132 response.persistentBufferFlag = 0;
135 if (OCDoResponse(&response) != OC_STACK_OK)
137 OC_LOG(ERROR, TAG, "Error sending response");
143 OCEntityHandlerRequest *CopyRequest(OCEntityHandlerRequest *entityHandlerRequest)
145 OC_LOG(INFO, TAG, "Copying received request for slow response");
147 OCEntityHandlerRequest *copyOfRequest =
148 (OCEntityHandlerRequest *)OICMalloc(sizeof(OCEntityHandlerRequest));
153 memcpy(copyOfRequest, entityHandlerRequest, sizeof(OCEntityHandlerRequest));
156 if (copyOfRequest->query)
158 copyOfRequest->query = OICStrdup(entityHandlerRequest->query);
159 if(!copyOfRequest->query)
161 OC_LOG(ERROR, TAG, "Copy failed due to allocation failure");
162 OICFree(copyOfRequest);
167 if (entityHandlerRequest->payload)
169 copyOfRequest->payload = reinterpret_cast<OCPayload*>
170 (OCRepPayloadClone ((OCRepPayload*) entityHandlerRequest->payload));
173 // Ignore vendor specific header options for example
174 copyOfRequest->numRcvdVendorSpecificHeaderOptions = 0;
175 copyOfRequest->rcvdVendorSpecificHeaderOptions = NULL;
180 OC_LOG(INFO, TAG, "Copied client request");
184 OC_LOG(ERROR, TAG, "Error copying client request");
186 return copyOfRequest;
189 OCEntityHandlerResult OCEntityHandlerCb (OCEntityHandlerFlag flag,
190 OCEntityHandlerRequest *entityHandlerRequest, void* callbackParam)
192 OCEntityHandlerResult result = OC_EH_ERROR;
193 OCEntityHandlerRequest *request = NULL;
195 OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
197 if (flag & OC_REQUEST_FLAG)
199 OC_LOG(INFO, TAG, "Flag includes OC_REQUEST_FLAG");
200 if (entityHandlerRequest)
202 OC_LOG_V (INFO, TAG, "request query %s from client",
203 entityHandlerRequest->query);
204 OC_LOG_PAYLOAD (INFO, TAG, entityHandlerRequest->payload);
206 // Make deep copy of received request and queue it for slow processing
207 request = CopyRequest(entityHandlerRequest);
212 OC_LOG(INFO, TAG, "Scheduling slow response for received request");
213 gRequestList.push_back(request);
214 // Indicate to the stack that this is a slow response
216 // Start the slow response alarm
217 alarm(SLOW_RESPONSE_DELAY_SEC);
221 OC_LOG(ERROR, TAG, "Error queuing request for slow response");
222 // Indicate to the stack that this is a slow response
223 result = OC_EH_ERROR;
228 OC_LOG(ERROR, TAG, "Invalid request");
229 result = OC_EH_ERROR;
235 /* SIGINT handler: set gQuitFlag to 1 for graceful termination */
236 void handleSigInt(int signum)
238 if (signum == SIGINT)
244 // SIGINT alarm handler: alarm set by entity handler. Does
245 // slow response when fired
246 void AlarmHandler(int sig)
250 OC_LOG (INFO, TAG, "Server starting slow response");
251 if (gRequestList.empty())
253 OC_LOG (INFO, TAG, "No requests to service");
257 // Get the request from the list
258 OCEntityHandlerRequest *entityHandlerRequest = gRequestList.front();
259 gRequestList.pop_front();
260 if (entityHandlerRequest->method == OC_REST_GET)
262 OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
263 ProcessGetPutRequest (entityHandlerRequest);
265 else if (entityHandlerRequest->method == OC_REST_PUT)
267 OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
268 ProcessGetPutRequest (entityHandlerRequest);
272 OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
273 entityHandlerRequest->method);
276 OICFree(entityHandlerRequest->query);
277 OCPayloadDestroy(entityHandlerRequest->payload);
278 OICFree(entityHandlerRequest);
280 // If there are more requests in list, re-arm the alarm signal
281 if (gRequestList.empty())
283 alarm(SLOW_RESPONSE_DELAY_SEC);
288 int main(int argc, char* argv[])
290 OC_LOG(DEBUG, TAG, "OCServer is starting...");
292 if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
294 OC_LOG(ERROR, TAG, "OCStack init error");
298 // Declare and create the example resource: LED
299 createLEDResource(gResourceUri, &LED, false, 42);
301 // Initialize slow response alarm
302 signal(SIGALRM, AlarmHandler);
304 // Break from loop with Ctrl-C
305 OC_LOG(INFO, TAG, "Entering ocserver main loop...");
306 signal(SIGINT, handleSigInt);
310 if (OCProcess() != OC_STACK_OK)
312 OC_LOG(ERROR, TAG, "OCStack process error");
318 OC_LOG(INFO, TAG, "Exiting ocserver main loop...");
321 if (!gRequestList.empty())
323 for (auto iter = gRequestList.begin(); iter != gRequestList.end(); ++iter)
325 OICFree((*iter)->query);
326 OCPayloadDestroy((*iter)->payload);
329 gRequestList.clear();
332 if (OCStop() != OC_STACK_OK)
334 OC_LOG(ERROR, TAG, "OCStack process error");
340 int createLEDResource (char *uri, LEDResource *ledResource, bool resourceState, int resourcePower)
344 OC_LOG(ERROR, TAG, "Resource URI cannot be NULL");
348 ledResource->state = resourceState;
349 ledResource->power= resourcePower;
350 OCStackResult res = OCCreateResource(&(ledResource->handle),
352 OC_RSRVD_INTERFACE_DEFAULT,
356 OC_DISCOVERABLE|OC_OBSERVABLE);
357 OC_LOG_V(INFO, TAG, "Created LED resource with result: %s", getResult(res));