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"
36 #include "payload_logging.h"
38 volatile sig_atomic_t gQuitFlag = 0;
40 static std::list<OCEntityHandlerRequest *> gRequestList;
41 static constexpr unsigned int SLOW_RESPONSE_DELAY_SEC = 5;
43 static LEDResource LED;
45 static constexpr unsigned int SAMPLE_MAX_NUM_POST_INSTANCE = 2;
46 static LEDResource gLedInstance[SAMPLE_MAX_NUM_POST_INSTANCE];
48 //char *gResourceUri= const_cast<char *>("/a/led");
49 char *gResourceUri= (char *)"/a/led";
51 //This function takes the request as an input and returns the response
53 OCRepPayload* constructResponse (OCEntityHandlerRequest *ehRequest)
55 LEDResource *currLEDResource = &LED;
57 OC_LOG(INFO, TAG, "Entering constructResponse");
59 if (ehRequest->resource == gLedInstance[0].handle)
61 OC_LOG(INFO, TAG, "handle 0");
62 currLEDResource = &gLedInstance[0];
63 gResourceUri = const_cast<char *>("a/led/0");
65 else if (ehRequest->resource == gLedInstance[1].handle)
67 OC_LOG(INFO, TAG, "handle 1");
68 currLEDResource = &gLedInstance[1];
69 gResourceUri = const_cast<char *>("a/led/1");
72 if(OC_REST_PUT == ehRequest->method)
74 if(ehRequest->payload && ehRequest->payload->type != PAYLOAD_TYPE_REPRESENTATION)
76 OC_LOG(ERROR, TAG, ("Incoming payload not a representation"));
80 OCRepPayload *putPayload = reinterpret_cast<OCRepPayload*> (ehRequest->payload);
85 if (OCRepPayloadGetPropBool(putPayload, "state", &state))
87 currLEDResource->state = state;
89 if (OCRepPayloadGetPropInt (putPayload, "power", &power))
91 currLEDResource->power = power;
95 OCRepPayload *response = OCRepPayloadCreate();
99 OC_LOG_V(ERROR, TAG, "Memory allocation for response payload failed.");
102 OCRepPayloadSetUri (response, gResourceUri);
103 OCRepPayloadSetPropBool(response, "state", currLEDResource->state);
104 OCRepPayloadSetPropInt(response, "power", currLEDResource->power);
109 void ProcessGetPutRequest (OCEntityHandlerRequest *ehRequest)
111 OC_LOG(INFO, TAG, "Entering ProcessGetPutRequest");
113 OCRepPayload *getResp = constructResponse(ehRequest);
117 OC_LOG(ERROR, TAG, "Failed to construct response");
121 OCEntityHandlerResponse response;
123 // Format the response. Note this requires some info about the request
124 response.requestHandle = ehRequest->requestHandle;
125 response.resourceHandle = ehRequest->resource;
126 response.ehResult = OC_EH_OK;
127 response.payload = reinterpret_cast<OCPayload*> (getResp);
128 response.numSendVendorSpecificHeaderOptions = 0;
129 memset(response.sendVendorSpecificHeaderOptions,
130 0, sizeof response.sendVendorSpecificHeaderOptions);
131 memset(response.resourceUri, 0, sizeof(response.resourceUri));
132 // Indicate that response is NOT in a persistent buffer
133 response.persistentBufferFlag = 0;
136 if (OCDoResponse(&response) != OC_STACK_OK)
138 OC_LOG(ERROR, TAG, "Error sending response");
144 OCEntityHandlerRequest *CopyRequest(OCEntityHandlerRequest *entityHandlerRequest)
146 OC_LOG(INFO, TAG, "Copying received request for slow response");
148 OCEntityHandlerRequest *copyOfRequest =
149 (OCEntityHandlerRequest *)OICMalloc(sizeof(OCEntityHandlerRequest));
154 memcpy(copyOfRequest, entityHandlerRequest, sizeof(OCEntityHandlerRequest));
157 if (copyOfRequest->query)
159 copyOfRequest->query = OICStrdup(entityHandlerRequest->query);
160 if(!copyOfRequest->query)
162 OC_LOG(ERROR, TAG, "Copy failed due to allocation failure");
163 OICFree(copyOfRequest);
168 if (entityHandlerRequest->payload)
170 copyOfRequest->payload = reinterpret_cast<OCPayload*>
171 (OCRepPayloadClone ((OCRepPayload*) entityHandlerRequest->payload));
174 // Ignore vendor specific header options for example
175 copyOfRequest->numRcvdVendorSpecificHeaderOptions = 0;
176 copyOfRequest->rcvdVendorSpecificHeaderOptions = NULL;
181 OC_LOG(INFO, TAG, "Copied client request");
185 OC_LOG(ERROR, TAG, "Error copying client request");
187 return copyOfRequest;
190 OCEntityHandlerResult OCEntityHandlerCb (OCEntityHandlerFlag flag,
191 OCEntityHandlerRequest *entityHandlerRequest, void* /*callbackParam*/)
193 OCEntityHandlerResult result = OC_EH_ERROR;
194 OCEntityHandlerRequest *request = NULL;
196 OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
198 if (flag & OC_REQUEST_FLAG)
200 OC_LOG(INFO, TAG, "Flag includes OC_REQUEST_FLAG");
201 if (entityHandlerRequest)
203 OC_LOG_V (INFO, TAG, "request query %s from client",
204 entityHandlerRequest->query);
205 OC_LOG_PAYLOAD (INFO, entityHandlerRequest->payload);
207 // Make deep copy of received request and queue it for slow processing
208 request = CopyRequest(entityHandlerRequest);
213 OC_LOG(INFO, TAG, "Scheduling slow response for received request");
214 gRequestList.push_back(request);
215 // Indicate to the stack that this is a slow response
217 // Start the slow response alarm
218 alarm(SLOW_RESPONSE_DELAY_SEC);
222 OC_LOG(ERROR, TAG, "Error queuing request for slow response");
223 // Indicate to the stack that this is a slow response
224 result = OC_EH_ERROR;
229 OC_LOG(ERROR, TAG, "Invalid request");
230 result = OC_EH_ERROR;
236 /* SIGINT handler: set gQuitFlag to 1 for graceful termination */
237 void handleSigInt(int signum)
239 if (signum == SIGINT)
245 // SIGINT alarm handler: alarm set by entity handler. Does
246 // slow response when fired
247 void AlarmHandler(int sig)
251 OC_LOG (INFO, TAG, "Server starting slow response");
252 if (gRequestList.empty())
254 OC_LOG (INFO, TAG, "No requests to service");
258 // Get the request from the list
259 OCEntityHandlerRequest *entityHandlerRequest = gRequestList.front();
260 gRequestList.pop_front();
261 if (entityHandlerRequest->method == OC_REST_GET)
263 OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
264 ProcessGetPutRequest (entityHandlerRequest);
266 else if (entityHandlerRequest->method == OC_REST_PUT)
268 OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
269 ProcessGetPutRequest (entityHandlerRequest);
273 OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
274 entityHandlerRequest->method);
277 OICFree(entityHandlerRequest->query);
278 OCPayloadDestroy(entityHandlerRequest->payload);
279 OICFree(entityHandlerRequest);
281 // If there are more requests in list, re-arm the alarm signal
282 if (gRequestList.empty())
284 alarm(SLOW_RESPONSE_DELAY_SEC);
289 int main(int /*argc*/, char** /*argv[]*/)
291 OC_LOG(DEBUG, TAG, "OCServer is starting...");
293 if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
295 OC_LOG(ERROR, TAG, "OCStack init error");
299 // Declare and create the example resource: LED
300 createLEDResource(gResourceUri, &LED, false, 42);
302 // Initialize slow response alarm
303 signal(SIGALRM, AlarmHandler);
305 // Break from loop with Ctrl-C
306 OC_LOG(INFO, TAG, "Entering ocserver main loop...");
307 signal(SIGINT, handleSigInt);
311 if (OCProcess() != OC_STACK_OK)
313 OC_LOG(ERROR, TAG, "OCStack process error");
319 OC_LOG(INFO, TAG, "Exiting ocserver main loop...");
322 if (!gRequestList.empty())
324 for (auto iter = gRequestList.begin(); iter != gRequestList.end(); ++iter)
326 OICFree((*iter)->query);
327 OCPayloadDestroy((*iter)->payload);
330 gRequestList.clear();
333 if (OCStop() != OC_STACK_OK)
335 OC_LOG(ERROR, TAG, "OCStack process error");
341 int createLEDResource (char *uri, LEDResource *ledResource, bool resourceState, int resourcePower)
345 OC_LOG(ERROR, TAG, "Resource URI cannot be NULL");
349 ledResource->state = resourceState;
350 ledResource->power= resourcePower;
351 OCStackResult res = OCCreateResource(&(ledResource->handle),
353 OC_RSRVD_INTERFACE_DEFAULT,
357 OC_DISCOVERABLE|OC_OBSERVABLE);
358 OC_LOG_V(INFO, TAG, "Created LED resource with result: %s", getResult(res));