Development of CoAP-HTTP Proxy
[platform/upstream/iotivity.git] / resource / csdk / stack / samples / linux / SimpleClientServer / ocserverbasicops.cpp
1 //******************************************************************
2 //
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
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
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
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.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdlib.h>
24 #ifdef HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27 #ifdef HAVE_WINDOWS_H
28 #include <windows.h>
29 #endif
30 #include <signal.h>
31 #ifdef HAVE_PTHREAD_H
32 #include <pthread.h>
33 #endif
34 #include "ocstack.h"
35 #include "logger.h"
36 #include "ocserverbasicops.h"
37 #include "ocpayload.h"
38
39 //string length of "/a/led/" + std::numeric_limits<int>::digits10 + '\0'"
40 // 7 + 9 + 1 = 17
41 const int URI_MAXSIZE = 17;
42
43 volatile sig_atomic_t gQuitFlag = 0;
44
45 static LEDResource LED;
46 // This variable determines instance number of the LED resource.
47 // Used by POST method to create a new instance of LED resource.
48 static int gCurrLedInstance = 0;
49 #define SAMPLE_MAX_NUM_POST_INSTANCE 2
50 static LEDResource gLedInstance[SAMPLE_MAX_NUM_POST_INSTANCE];
51
52 char *gResourceUri= (char *)"/a/led";
53
54 OCRepPayload* getPayload(const char* uri, int64_t power, bool state)
55 {
56     OCRepPayload* payload = OCRepPayloadCreate();
57     if(!payload)
58     {
59         OIC_LOG(ERROR, TAG, PCF("Failed to allocate Payload"));
60         return nullptr;
61     }
62
63     OCRepPayloadSetUri(payload, uri);
64     OCRepPayloadSetPropBool(payload, "state", state);
65     OCRepPayloadSetPropInt(payload, "power", power);
66
67     return payload;
68 }
69
70 //This function takes the request as an input and returns the response
71 OCRepPayload* constructResponse (OCEntityHandlerRequest *ehRequest)
72 {
73     if(ehRequest->payload && ehRequest->payload->type != PAYLOAD_TYPE_REPRESENTATION)
74     {
75         OIC_LOG(ERROR, TAG, PCF("Incoming payload not a representation"));
76         return nullptr;
77     }
78
79     OCRepPayload* input = reinterpret_cast<OCRepPayload*>(ehRequest->payload);
80
81     LEDResource *currLEDResource = &LED;
82
83     if (ehRequest->resource == gLedInstance[0].handle)
84     {
85         currLEDResource = &gLedInstance[0];
86         gResourceUri = (char *) "/a/led/0";
87     }
88     else if (ehRequest->resource == gLedInstance[1].handle)
89     {
90         currLEDResource = &gLedInstance[1];
91         gResourceUri = (char *) "/a/led/1";
92     }
93
94     if(OC_REST_PUT == ehRequest->method)
95     {
96         // Get pointer to query
97         int64_t pow;
98         if(OCRepPayloadGetPropInt(input, "power", &pow))
99         {
100             currLEDResource->power =pow;
101         }
102
103         bool state;
104         if(OCRepPayloadGetPropBool(input, "state", &state))
105         {
106             currLEDResource->state = state;
107         }
108     }
109
110     return getPayload(gResourceUri, currLEDResource->power, currLEDResource->state);
111 }
112
113 OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
114         OCRepPayload **payload)
115 {
116     OCEntityHandlerResult ehResult;
117     OCRepPayload *getResp = constructResponse(ehRequest);
118
119     if(getResp)
120     {
121         *payload = getResp;
122         ehResult = OC_EH_OK;
123      }
124     else
125     {
126         ehResult = OC_EH_ERROR;
127     }
128
129     return ehResult;
130 }
131
132 OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
133         OCRepPayload **payload)
134 {
135     OCEntityHandlerResult ehResult;
136     OCRepPayload *putResp = constructResponse(ehRequest);
137
138     if(putResp)
139     {
140         *payload = putResp;
141         ehResult = OC_EH_OK;
142     }
143     else
144     {
145         ehResult = OC_EH_ERROR;
146     }
147
148     return ehResult;
149 }
150
151 OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
152         OCEntityHandlerResponse *response, OCRepPayload **payload)
153 {
154     OCRepPayload *respPLPost_led = nullptr;
155     OCEntityHandlerResult ehResult = OC_EH_OK;
156
157     /*
158      * The entity handler determines how to process a POST request.
159      * Per the REST paradigm, POST can also be used to update representation of existing
160      * resource or create a new resource.
161      * In the sample below, if the POST is for /a/led then a new instance of the LED
162      * resource is created with default representation (if representation is included in
163      * POST payload it can be used as initial values) as long as the instance is
164      * lesser than max new instance count. Once max instance count is reached, POST on
165      * /a/led updated the representation of /a/led (just like PUT)
166      */
167
168     if (ehRequest->resource == LED.handle)
169     {
170         if (gCurrLedInstance < SAMPLE_MAX_NUM_POST_INSTANCE)
171         {
172             // Create new LED instance
173             char newLedUri[URI_MAXSIZE ];
174             snprintf(newLedUri, URI_MAXSIZE, "/a/led/%d", gCurrLedInstance);
175
176             respPLPost_led = OCRepPayloadCreate();
177             OCRepPayloadSetUri(respPLPost_led, gResourceUri);
178             OCRepPayloadSetPropString(respPLPost_led, "createduri", newLedUri);
179
180             if (0 == createLEDResource (newLedUri, &gLedInstance[gCurrLedInstance], false, 0))
181             {
182                 OIC_LOG (INFO, TAG, "Created new LED instance");
183                 gLedInstance[gCurrLedInstance].state = 0;
184                 gLedInstance[gCurrLedInstance].power = 0;
185                 gCurrLedInstance++;
186                 strncpy ((char *)response->resourceUri, newLedUri, MAX_URI_LENGTH);
187                 ehResult = OC_EH_RESOURCE_CREATED;
188             }
189         }
190         else
191         {
192             respPLPost_led = constructResponse(ehRequest);
193         }
194     }
195     else
196     {
197         for (int i = 0; i < SAMPLE_MAX_NUM_POST_INSTANCE; i++)
198         {
199             if (ehRequest->resource == gLedInstance[i].handle)
200             {
201                 if (i == 0)
202                 {
203                     respPLPost_led = constructResponse(ehRequest);
204                     break;
205                 }
206                 else if (i == 1)
207                 {
208                     respPLPost_led = constructResponse(ehRequest);
209                 }
210             }
211         }
212     }
213
214     if ((respPLPost_led != NULL))
215     {
216         *payload = respPLPost_led;
217         ehResult = OC_EH_OK;
218     }
219     else
220     {
221         OIC_LOG_V (INFO, TAG, "Payload was NULL");
222         ehResult = OC_EH_ERROR;
223     }
224
225     return ehResult;
226 }
227
228 OCEntityHandlerResult
229 OCEntityHandlerCb (OCEntityHandlerFlag flag,
230                    OCEntityHandlerRequest *entityHandlerRequest,
231                    void* /*callbackParam*/)
232 {
233     OIC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
234
235     OCEntityHandlerResult ehResult = OC_EH_ERROR;
236     OCEntityHandlerResponse response = { 0, 0, OC_EH_ERROR, 0, 0, { },{ 0 }, false };
237
238     // Validate pointer
239     if (!entityHandlerRequest)
240     {
241         OIC_LOG (ERROR, TAG, "Invalid request pointer");
242         return OC_EH_ERROR;
243     }
244
245     OCRepPayload* payload = nullptr;
246
247     if (flag & OC_REQUEST_FLAG)
248     {
249         OIC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
250         if (entityHandlerRequest)
251         {
252             if (OC_REST_GET == entityHandlerRequest->method)
253             {
254                 OIC_LOG (INFO, TAG, "Received OC_REST_GET from client");
255                 ehResult = ProcessGetRequest (entityHandlerRequest, &payload);
256             }
257             else if (OC_REST_PUT == entityHandlerRequest->method)
258             {
259                 OIC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
260                 ehResult = ProcessPutRequest (entityHandlerRequest, &payload);
261             }
262             else if (OC_REST_POST == entityHandlerRequest->method)
263             {
264                 OIC_LOG (INFO, TAG, "Received OC_REST_POST from client");
265                 ehResult = ProcessPostRequest (entityHandlerRequest, &response, &payload);
266             }
267             else
268             {
269                 OIC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
270                         entityHandlerRequest->method);
271             }
272
273             if (ehResult == OC_EH_OK && ehResult != OC_EH_FORBIDDEN)
274             {
275                 // Format the response.  Note this requires some info about the request
276                 response.requestHandle = entityHandlerRequest->requestHandle;
277                 response.resourceHandle = entityHandlerRequest->resource;
278                 response.ehResult = ehResult;
279                 response.payload = reinterpret_cast<OCPayload*>(payload);
280                 response.numSendVendorSpecificHeaderOptions = 0;
281                 memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
282                 memset(response.resourceUri, 0, sizeof(response.resourceUri));
283                 // Indicate that response is NOT in a persistent buffer
284                 response.persistentBufferFlag = 0;
285
286                 // Send the response
287                 if (OCDoResponse(&response) != OC_STACK_OK)
288                 {
289                     OIC_LOG(ERROR, TAG, "Error sending response");
290                     ehResult = OC_EH_ERROR;
291                 }
292             }
293         }
294     }
295
296     OCPayloadDestroy(response.payload);
297     return ehResult;
298 }
299
300 /* SIGINT handler: set gQuitFlag to 1 for graceful termination */
301 void handleSigInt(int signum)
302 {
303     if (signum == SIGINT)
304     {
305         gQuitFlag = 1;
306     }
307 }
308
309 int main(int /*argc*/, char* /*argv*/[])
310 {
311     OIC_LOG(DEBUG, TAG, "OCServer is starting...");
312     if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
313     {
314         OIC_LOG(ERROR, TAG, "OCStack init error");
315         return 0;
316     }
317
318     /*
319      * Declare and create the example resource: LED
320      */
321     createLEDResource(gResourceUri, &LED, false, 0);
322
323     // Break from loop with Ctrl-C
324     OIC_LOG(INFO, TAG, "Entering ocserver main loop...");
325     signal(SIGINT, handleSigInt);
326     while (!gQuitFlag)
327     {
328         if (OCProcess() != OC_STACK_OK)
329         {
330             OIC_LOG(ERROR, TAG, "OCStack process error");
331             return 0;
332         }
333
334         sleep(2);
335     }
336
337     OIC_LOG(INFO, TAG, "Exiting ocserver main loop...");
338
339     if (OCStop() != OC_STACK_OK)
340     {
341         OIC_LOG(ERROR, TAG, "OCStack process error");
342     }
343
344     return 0;
345 }
346
347 int createLEDResource (char *uri, LEDResource *ledResource, bool resourceState, int resourcePower)
348 {
349     if (!uri)
350     {
351         OIC_LOG(ERROR, TAG, "Resource URI cannot be NULL");
352         return -1;
353     }
354
355     ledResource->state = resourceState;
356     ledResource->power= resourcePower;
357     OCStackResult res = OCCreateResource(&(ledResource->handle),
358             "core.led",
359             OC_RSRVD_INTERFACE_DEFAULT,
360             uri,
361             OCEntityHandlerCb,
362             NULL,
363             OC_DISCOVERABLE|OC_OBSERVABLE);
364     OIC_LOG_V(INFO, TAG, "Created LED resource with result: %s", getResult(res));
365
366     return 0;
367 }
368