Modifying version number for building on tizen 3.0
[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 #include <unistd.h>
25 #include <signal.h>
26 #include <pthread.h>
27 #include "ocstack.h"
28 #include "logger.h"
29 #include "cJSON.h"
30 #include "ocserverbasicops.h"
31
32 //string length of "/a/led/" + std::numeric_limits<int>::digits10 + '\0'"
33 // 7 + 9 + 1 = 17
34 const int URI_MAXSIZE = 17;
35
36 volatile sig_atomic_t gQuitFlag = 0;
37
38 static LEDResource LED;
39 // This variable determines instance number of the LED resource.
40 // Used by POST method to create a new instance of LED resource.
41 static int gCurrLedInstance = 0;
42 #define SAMPLE_MAX_NUM_POST_INSTANCE  2
43 static LEDResource gLedInstance[SAMPLE_MAX_NUM_POST_INSTANCE];
44
45 char *gResourceUri= (char *)"/a/led";
46
47 static uint16_t OC_WELL_KNOWN_PORT = 5683;
48
49 //This function takes the request as an input and returns the response
50 //in JSON format.
51 char* constructJsonResponse (OCEntityHandlerRequest *ehRequest)
52 {
53     cJSON *json = cJSON_CreateObject();
54     cJSON *format;
55     char *jsonResponse;
56     LEDResource *currLEDResource = &LED;
57
58     if (ehRequest->resource == gLedInstance[0].handle)
59     {
60         currLEDResource = &gLedInstance[0];
61         gResourceUri = (char *) "a/led/0";
62     }
63     else if (ehRequest->resource == gLedInstance[1].handle)
64     {
65         currLEDResource = &gLedInstance[1];
66         gResourceUri = (char *) "a/led/1";
67     }
68
69     if(OC_REST_PUT == ehRequest->method)
70     {
71         cJSON *putJson = cJSON_Parse((char *)ehRequest->reqJSONPayload);
72         currLEDResource->state = ( !strcmp(cJSON_GetObjectItem(putJson,"state")->valuestring ,
73                 "on") ? true:false);
74         currLEDResource->power = cJSON_GetObjectItem(putJson,"power")->valuedouble;
75         cJSON_Delete(putJson);
76     }
77
78     cJSON_AddStringToObject(json,"href",gResourceUri);
79     cJSON_AddItemToObject(json, "rep", format=cJSON_CreateObject());
80     cJSON_AddStringToObject(format, "state", (char *) (currLEDResource->state ? "on":"off"));
81     cJSON_AddNumberToObject(format, "power", currLEDResource->power);
82
83     jsonResponse = cJSON_Print(json);
84     cJSON_Delete(json);
85     return jsonResponse;
86 }
87
88 OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
89 {
90     OCEntityHandlerResult ehResult;
91     char *getResp = constructJsonResponse(ehRequest);
92
93     if (maxPayloadSize > strlen ((char *)getResp))
94     {
95         strncpy(payload, getResp, strlen((char *)getResp));
96         ehResult = OC_EH_OK;
97     }
98     else
99     {
100         OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
101                 maxPayloadSize);
102         ehResult = OC_EH_ERROR;
103     }
104
105     free(getResp);
106
107     return ehResult;
108 }
109
110 OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
111 {
112     OCEntityHandlerResult ehResult;
113     char *putResp = constructJsonResponse(ehRequest);
114
115     if (maxPayloadSize > strlen ((char *)putResp))
116     {
117         strncpy(payload, putResp, strlen((char *)putResp));
118         ehResult = OC_EH_OK;
119     }
120     else
121     {
122         OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
123                 maxPayloadSize);
124         ehResult = OC_EH_ERROR;
125     }
126
127     free(putResp);
128
129     return ehResult;
130 }
131
132 OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
133 {
134     char *respPLPost_led = NULL;
135     cJSON *json;
136     cJSON *format;
137     OCEntityHandlerResult ehResult;
138
139     /*
140      * The entity handler determines how to process a POST request.
141      * Per the REST paradigm, POST can also be used to update representation of existing
142      * resource or create a new resource.
143      * In the sample below, if the POST is for /a/led then a new instance of the LED
144      * resource is created with default representation (if representation is included in
145      * POST payload it can be used as initial values) as long as the instance is
146      * lesser than max new instance count. Once max instance count is reached, POST on
147      * /a/led updated the representation of /a/led (just like PUT)
148      */
149
150     if (ehRequest->resource == LED.handle)
151     {
152         if (gCurrLedInstance < SAMPLE_MAX_NUM_POST_INSTANCE)
153         {
154             // Create new LED instance
155             char newLedUri[URI_MAXSIZE ];
156             snprintf(newLedUri, URI_MAXSIZE, "/a/led/%d", gCurrLedInstance);
157
158             json = cJSON_CreateObject();
159
160             cJSON_AddStringToObject(json,"href",gResourceUri);
161             cJSON_AddItemToObject(json, "rep", format=cJSON_CreateObject());
162             cJSON_AddStringToObject(format, "createduri", (char *) newLedUri);
163
164             if (0 == createLEDResource (newLedUri, &gLedInstance[gCurrLedInstance], false, 0))
165             {
166                 OC_LOG (INFO, TAG, "Created new LED instance");
167                 gLedInstance[gCurrLedInstance].state = 0;
168                 gLedInstance[gCurrLedInstance].power = 0;
169                 gCurrLedInstance++;
170                 respPLPost_led = cJSON_Print(json);
171             }
172
173             cJSON_Delete(json);
174         }
175         else
176         {
177             respPLPost_led = constructJsonResponse(ehRequest);
178         }
179     }
180     else
181     {
182         for (int i = 0; i < SAMPLE_MAX_NUM_POST_INSTANCE; i++)
183         {
184             if (ehRequest->resource == gLedInstance[i].handle)
185             {
186                 if (i == 0)
187                 {
188                     respPLPost_led = constructJsonResponse(ehRequest);
189                     break;
190                 }
191                 else if (i == 1)
192                 {
193                     respPLPost_led = constructJsonResponse(ehRequest);
194                 }
195             }
196         }
197     }
198
199     if ((respPLPost_led != NULL) && (maxPayloadSize > strlen ((char *)respPLPost_led)))
200     {
201         strncpy(payload, respPLPost_led, strlen((char *)respPLPost_led));
202         ehResult = OC_EH_OK;
203     }
204     else
205     {
206         OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
207                 maxPayloadSize);
208         ehResult = OC_EH_ERROR;
209     }
210
211     free(respPLPost_led);
212
213     return ehResult;
214 }
215
216 OCEntityHandlerResult
217 OCEntityHandlerCb (OCEntityHandlerFlag flag,
218         OCEntityHandlerRequest *entityHandlerRequest)
219 {
220     OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
221
222     OCEntityHandlerResult ehResult = OC_EH_ERROR;
223     OCEntityHandlerResponse response;
224     char payload[MAX_RESPONSE_LENGTH] = {0};
225
226     if (flag & OC_INIT_FLAG)
227     {
228         OC_LOG (INFO, TAG, "Flag includes OC_INIT_FLAG");
229         ehResult = OC_EH_OK;
230     }
231     if (flag & OC_REQUEST_FLAG)
232     {
233         OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
234         if (entityHandlerRequest)
235         {
236             if (OC_REST_GET == entityHandlerRequest->method)
237             {
238                 OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
239                 ehResult = ProcessGetRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
240             }
241             else if (OC_REST_PUT == entityHandlerRequest->method)
242             {
243                 OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
244                 ehResult = ProcessPutRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
245             }
246             else if (OC_REST_POST == entityHandlerRequest->method)
247             {
248                 OC_LOG (INFO, TAG, "Received OC_REST_POST from client");
249                 ehResult = ProcessPostRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
250             }
251             else
252             {
253                 OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
254                         entityHandlerRequest->method);
255             }
256
257             if (ehResult == OC_EH_OK)
258             {
259                 // Format the response.  Note this requires some info about the request
260                 response.requestHandle = entityHandlerRequest->requestHandle;
261                 response.resourceHandle = entityHandlerRequest->resource;
262                 response.ehResult = ehResult;
263                 response.payload = (unsigned char *)payload;
264                 response.payloadSize = strlen(payload);
265                 response.numSendVendorSpecificHeaderOptions = 0;
266                 memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
267                 memset(response.resourceUri, 0, sizeof(response.resourceUri));
268                 // Indicate that response is NOT in a persistent buffer
269                 response.persistentBufferFlag = 0;
270
271                 // Send the response
272                 if (OCDoResponse(&response) != OC_STACK_OK)
273                 {
274                     OC_LOG(ERROR, TAG, "Error sending response");
275                     ehResult = OC_EH_ERROR;
276                 }
277             }
278         }
279     }
280     return ehResult;
281 }
282
283 /* SIGINT handler: set gQuitFlag to 1 for graceful termination */
284 void handleSigInt(int signum)
285 {
286     if (signum == SIGINT)
287     {
288         gQuitFlag = 1;
289     }
290 }
291
292 int main(int argc, char* argv[])
293 {
294     uint8_t addr[20] = {0};
295     uint8_t* paddr = NULL;
296     uint16_t port = OC_WELL_KNOWN_PORT;
297     uint8_t ifname[] = "eth0";
298
299     OC_LOG(DEBUG, TAG, "OCServer is starting...");
300     /*Get Ip address on defined interface and initialize coap on it with random port number
301      * this port number will be used as a source port in all coap communications*/
302     if ( OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr,
303                 sizeof(addr)) == ERR_SUCCESS)
304     {
305         OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
306         paddr = addr;
307     }
308
309     if (OCInit((char *) paddr, port, OC_SERVER) != OC_STACK_OK)
310     {
311         OC_LOG(ERROR, TAG, "OCStack init error");
312         return 0;
313     }
314
315     /*
316      * Declare and create the example resource: LED
317      */
318     createLEDResource(gResourceUri, &LED, false, 0);
319
320     // Break from loop with Ctrl-C
321     OC_LOG(INFO, TAG, "Entering ocserver main loop...");
322     signal(SIGINT, handleSigInt);
323     while (!gQuitFlag)
324     {
325         if (OCProcess() != OC_STACK_OK)
326         {
327             OC_LOG(ERROR, TAG, "OCStack process error");
328             return 0;
329         }
330
331         sleep(2);
332     }
333
334     OC_LOG(INFO, TAG, "Exiting ocserver main loop...");
335
336     if (OCStop() != OC_STACK_OK)
337     {
338         OC_LOG(ERROR, TAG, "OCStack process error");
339     }
340
341     return 0;
342 }
343
344 int createLEDResource (char *uri, LEDResource *ledResource, bool resourceState, int resourcePower)
345 {
346     if (!uri)
347     {
348         OC_LOG(ERROR, TAG, "Resource URI cannot be NULL");
349         return -1;
350     }
351
352     ledResource->state = resourceState;
353     ledResource->power= resourcePower;
354     OCStackResult res = OCCreateResource(&(ledResource->handle),
355             "core.led",
356             "oc.mi.def",
357             uri,
358             OCEntityHandlerCb,
359             OC_DISCOVERABLE|OC_OBSERVABLE);
360     OC_LOG_V(INFO, TAG, "Created LED resource with result: %s", getResult(res));
361
362     return 0;
363 }