1 //******************************************************************
3 // Copyright 2014 Intel Corporation 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 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
23 #include "ocstackinternal.h"
24 #include "ocobserve.h"
30 #define MOD_NAME PCF("ocobserve")
32 #define TAG PCF("OCStackObserve")
34 #define VERIFY_NON_NULL(arg) { if (!arg) {OC_LOG(FATAL, TAG, #arg " is NULL"); goto exit;} }
36 static struct ObserveResourceServer *serverObsList = NULL;
38 OCStackResult AddObserver (const char *resUri,
43 OCResource *resHandle);
44 OCStackResult DeleteObserver (uint8_t *token, size_t tokenLength);
46 OCStackResult ProcessObserveRequest (OCResource *resource, OCRequest *request)
49 OCEntityHandlerRequest *ehReq = request->entityHandlerRequest;
50 OCObserveReq *obs = request->observe;
52 OC_LOG(INFO, TAG, "Entering ProcessObserveRequest");
53 if (strcmp ((char *)obs->option, OC_RESOURCE_OBSERVE_REGISTER) == 0) {
56 return OC_STACK_ERROR;
58 // Register new observation
59 request->entityHandlerRequest->resource = (OCResourceHandle)resource;
60 result = resource->entityHandler(OC_OBSERVE_FLAG, request->entityHandlerRequest);
61 if (OC_STACK_OK == result)
63 // Add subscriber to the server observation list
64 result = AddObserver ((const char*)(request->resourceUrl), (const char *)(ehReq->query),
65 obs->token->token, obs->token->tokenLength, obs->subAddr, resource);
68 } else if (strcmp ((char *)obs->option, OC_RESOURCE_OBSERVE_DEREGISTER) == 0) {
69 // Deregister observation
70 result = DeleteObserver (obs->token->token, obs->token->tokenLength);
74 OC_LOG(ERROR, TAG, "Invalid CoAP observe option");
75 return OC_STACK_INVALID_OBSERVE_PARAM;
79 OCStackResult SendObserverNotification (OCResourceHandle handle, OCResource *resPtr)
83 ObserveResourceServer *obsRes = serverObsList;
84 OCEntityHandlerRequest entityHandlerReq;
85 unsigned char bufRes[MAX_RESPONSE_LENGTH] = {0};
87 * TODO: In the current releast all observes are set as non-confirmable since the
88 * entity handler does not have a way to specify the message QoS - add a parameter.
89 * Sending all observes NON does not confirm with the observe draft (ver14).
91 OCQualityOfService qos = OC_NON_CONFIRMABLE;
93 // Increment the sequence number
94 resPtr->sequenceNum += 1;
95 if (resPtr->sequenceNum == MAX_SEQUENCE_NUMBER)
96 resPtr->sequenceNum = 1;
98 // Find clients that are observing this resource
100 if (obsRes->resource == handle) {
101 // Invoke the entity handler for the client to process the query according to
102 // the new representation
104 entityHandlerReq.resource = handle;
105 entityHandlerReq.query = obsRes->query;
106 entityHandlerReq.method = OC_REST_GET;
107 entityHandlerReq.reqJSONPayload = NULL;
108 entityHandlerReq.resJSONPayload = bufRes;
109 entityHandlerReq.resJSONPayloadLen = MAX_RESPONSE_LENGTH;
110 // Even if entity handler for a resource is not successful we continue calling
111 // entity handler for other resources
112 result = resPtr->entityHandler (OC_REQUEST_FLAG, &entityHandlerReq);
113 if (OC_STACK_OK == result)
115 OCCoAPSendMessage (obsRes->addr, result, qos, obsRes->token,
116 (const char *)entityHandlerReq.resJSONPayload,
117 resPtr->sequenceNum);
120 obsRes = obsRes->next;
124 OC_LOG(INFO, TAG, "Resource has no observers");
125 return OC_STACK_NO_OBSERVERS;
130 OCStackResult AddObserver (const char *resUri,
135 OCResource *resHandle)
137 ObserveResourceServer *obsNode;
140 obsNode = (ObserveResourceServer *) OCMalloc(sizeof(ObserveResourceServer));
142 obsNode->resUri = (unsigned char *)OCMalloc(sizeof(strlen(resUri)+1));
143 VERIFY_NON_NULL (obsNode->resUri);
144 memcpy (obsNode->resUri, resUri, sizeof(strlen(resUri)+1));
145 obsNode->query = (unsigned char *)OCMalloc(sizeof(strlen(query)+1));
146 VERIFY_NON_NULL (obsNode->query);
147 memcpy (obsNode->query, query, sizeof(strlen(query)+1));
148 obsNode->token = (OCCoAPToken *)OCMalloc(sizeof(OCCoAPToken));
149 VERIFY_NON_NULL (obsNode->token);
150 tokPtr = obsNode->token;
151 memcpy (tokPtr->token, token, sizeof(OCCoAPToken));
152 tokPtr->tokenLength = tokenLength;
153 obsNode->addr = (OCDevAddr *)OCMalloc(sizeof(OCDevAddr));
154 VERIFY_NON_NULL (obsNode->addr);
155 memcpy (obsNode->addr, addr, sizeof(OCDevAddr));
156 obsNode->resource = resHandle;
158 LL_APPEND (serverObsList, obsNode);
163 OCFree(obsNode->resUri);
164 OCFree(obsNode->query);
165 OCFree(obsNode->token);
166 OCFree(obsNode->addr);
168 return OC_STACK_NO_MEMORY;
171 ObserveResourceServer* GetObserver (const uint8_t *token, const size_t tokenLength)
173 ObserveResourceServer *out = NULL;
177 LL_FOREACH (serverObsList, out)
179 if((out->token->tokenLength == tokenLength) &&
180 (memcmp(out->token->token, token, tokenLength) == 0)) {
185 OC_LOG(INFO, MOD_NAME, PCF("Observer node not found!!"));
189 OCStackResult DeleteObserver (uint8_t *token, size_t tokenLength)
191 ObserveResourceServer *obsNode = NULL;
193 obsNode = GetObserver (token, tokenLength);
195 LL_DELETE (serverObsList, obsNode);
196 OCFree(obsNode->resUri);
197 OCFree(obsNode->query);
198 OCFree(obsNode->token);
199 OCFree(obsNode->addr);
203 return OC_STACK_ERROR;
206 void DeleteObserverList()
208 ObserveResourceServer *out;
209 ObserveResourceServer *tmp;
210 LL_FOREACH_SAFE (serverObsList, out, tmp)
212 DeleteObserver (out->token->token, out->token->tokenLength);
214 serverObsList = NULL;