Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
wakaama/observe.c@0:f9d13e09cf11, 2017-04-24 (annotated)
- Committer:
- terencez
- Date:
- Mon Apr 24 23:03:31 2017 +0000
- Revision:
- 0:f9d13e09cf11
- Child:
- 3:a280069151ac
The first compiled submit.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
terencez | 0:f9d13e09cf11 | 1 | /******************************************************************************* |
terencez | 0:f9d13e09cf11 | 2 | * |
terencez | 0:f9d13e09cf11 | 3 | * Copyright (c) 2013, 2014 Intel Corporation and others. |
terencez | 0:f9d13e09cf11 | 4 | * All rights reserved. This program and the accompanying materials |
terencez | 0:f9d13e09cf11 | 5 | * are made available under the terms of the Eclipse Public License v1.0 |
terencez | 0:f9d13e09cf11 | 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. |
terencez | 0:f9d13e09cf11 | 7 | * |
terencez | 0:f9d13e09cf11 | 8 | * The Eclipse Public License is available at |
terencez | 0:f9d13e09cf11 | 9 | * http://www.eclipse.org/legal/epl-v10.html |
terencez | 0:f9d13e09cf11 | 10 | * The Eclipse Distribution License is available at |
terencez | 0:f9d13e09cf11 | 11 | * http://www.eclipse.org/org/documents/edl-v10.php. |
terencez | 0:f9d13e09cf11 | 12 | * |
terencez | 0:f9d13e09cf11 | 13 | * Contributors: |
terencez | 0:f9d13e09cf11 | 14 | * David Navarro, Intel Corporation - initial API and implementation |
terencez | 0:f9d13e09cf11 | 15 | * Toby Jaffey - Please refer to git log |
terencez | 0:f9d13e09cf11 | 16 | * |
terencez | 0:f9d13e09cf11 | 17 | *******************************************************************************/ |
terencez | 0:f9d13e09cf11 | 18 | |
terencez | 0:f9d13e09cf11 | 19 | /* |
terencez | 0:f9d13e09cf11 | 20 | Copyright (c) 2013, 2014 Intel Corporation |
terencez | 0:f9d13e09cf11 | 21 | |
terencez | 0:f9d13e09cf11 | 22 | Redistribution and use in source and binary forms, with or without modification, |
terencez | 0:f9d13e09cf11 | 23 | are permitted provided that the following conditions are met: |
terencez | 0:f9d13e09cf11 | 24 | |
terencez | 0:f9d13e09cf11 | 25 | * Redistributions of source code must retain the above copyright notice, |
terencez | 0:f9d13e09cf11 | 26 | this list of conditions and the following disclaimer. |
terencez | 0:f9d13e09cf11 | 27 | * Redistributions in binary form must reproduce the above copyright notice, |
terencez | 0:f9d13e09cf11 | 28 | this list of conditions and the following disclaimer in the documentation |
terencez | 0:f9d13e09cf11 | 29 | and/or other materials provided with the distribution. |
terencez | 0:f9d13e09cf11 | 30 | * Neither the name of Intel Corporation nor the names of its contributors |
terencez | 0:f9d13e09cf11 | 31 | may be used to endorse or promote products derived from this software |
terencez | 0:f9d13e09cf11 | 32 | without specific prior written permission. |
terencez | 0:f9d13e09cf11 | 33 | |
terencez | 0:f9d13e09cf11 | 34 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
terencez | 0:f9d13e09cf11 | 35 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
terencez | 0:f9d13e09cf11 | 36 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
terencez | 0:f9d13e09cf11 | 37 | IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, |
terencez | 0:f9d13e09cf11 | 38 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
terencez | 0:f9d13e09cf11 | 39 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
terencez | 0:f9d13e09cf11 | 40 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
terencez | 0:f9d13e09cf11 | 41 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
terencez | 0:f9d13e09cf11 | 42 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
terencez | 0:f9d13e09cf11 | 43 | THE POSSIBILITY OF SUCH DAMAGE. |
terencez | 0:f9d13e09cf11 | 44 | |
terencez | 0:f9d13e09cf11 | 45 | David Navarro <david.navarro@intel.com> |
terencez | 0:f9d13e09cf11 | 46 | |
terencez | 0:f9d13e09cf11 | 47 | */ |
terencez | 0:f9d13e09cf11 | 48 | |
terencez | 0:f9d13e09cf11 | 49 | #include "internals.h" |
terencez | 0:f9d13e09cf11 | 50 | #include <stdio.h> |
terencez | 0:f9d13e09cf11 | 51 | |
terencez | 0:f9d13e09cf11 | 52 | |
terencez | 0:f9d13e09cf11 | 53 | #ifdef LWM2M_CLIENT_MODE |
terencez | 0:f9d13e09cf11 | 54 | static lwm2m_observed_t * prv_findObserved(lwm2m_context_t * contextP, |
terencez | 0:f9d13e09cf11 | 55 | lwm2m_uri_t * uriP) |
terencez | 0:f9d13e09cf11 | 56 | { |
terencez | 0:f9d13e09cf11 | 57 | lwm2m_observed_t * targetP; |
terencez | 0:f9d13e09cf11 | 58 | |
terencez | 0:f9d13e09cf11 | 59 | targetP = contextP->observedList; |
terencez | 0:f9d13e09cf11 | 60 | while (targetP != NULL |
terencez | 0:f9d13e09cf11 | 61 | && (targetP->uri.objectId != uriP->objectId |
terencez | 0:f9d13e09cf11 | 62 | || targetP->uri.flag != uriP->flag |
terencez | 0:f9d13e09cf11 | 63 | || (LWM2M_URI_IS_SET_INSTANCE(uriP) && targetP->uri.instanceId != uriP->instanceId) |
terencez | 0:f9d13e09cf11 | 64 | || (LWM2M_URI_IS_SET_RESOURCE(uriP) && targetP->uri.resourceId != uriP->resourceId))) |
terencez | 0:f9d13e09cf11 | 65 | { |
terencez | 0:f9d13e09cf11 | 66 | targetP = targetP->next; |
terencez | 0:f9d13e09cf11 | 67 | } |
terencez | 0:f9d13e09cf11 | 68 | |
terencez | 0:f9d13e09cf11 | 69 | return targetP; |
terencez | 0:f9d13e09cf11 | 70 | } |
terencez | 0:f9d13e09cf11 | 71 | |
terencez | 0:f9d13e09cf11 | 72 | static obs_list_t * prv_getObservedList(lwm2m_context_t * contextP, |
terencez | 0:f9d13e09cf11 | 73 | lwm2m_uri_t * uriP) |
terencez | 0:f9d13e09cf11 | 74 | { |
terencez | 0:f9d13e09cf11 | 75 | obs_list_t * resultP; |
terencez | 0:f9d13e09cf11 | 76 | lwm2m_observed_t * targetP; |
terencez | 0:f9d13e09cf11 | 77 | |
terencez | 0:f9d13e09cf11 | 78 | resultP = NULL; |
terencez | 0:f9d13e09cf11 | 79 | |
terencez | 0:f9d13e09cf11 | 80 | targetP = contextP->observedList; |
terencez | 0:f9d13e09cf11 | 81 | while (targetP != NULL) |
terencez | 0:f9d13e09cf11 | 82 | { |
terencez | 0:f9d13e09cf11 | 83 | if (targetP->uri.objectId == uriP->objectId) |
terencez | 0:f9d13e09cf11 | 84 | { |
terencez | 0:f9d13e09cf11 | 85 | if (!LWM2M_URI_IS_SET_INSTANCE(uriP) |
terencez | 0:f9d13e09cf11 | 86 | || (targetP->uri.flag & LWM2M_URI_FLAG_INSTANCE_ID) == 0 |
terencez | 0:f9d13e09cf11 | 87 | || uriP->instanceId == targetP->uri.instanceId) |
terencez | 0:f9d13e09cf11 | 88 | { |
terencez | 0:f9d13e09cf11 | 89 | if (!LWM2M_URI_IS_SET_RESOURCE(uriP) |
terencez | 0:f9d13e09cf11 | 90 | || (targetP->uri.flag & LWM2M_URI_FLAG_RESOURCE_ID) == 0 |
terencez | 0:f9d13e09cf11 | 91 | || uriP->resourceId == targetP->uri.resourceId) |
terencez | 0:f9d13e09cf11 | 92 | { |
terencez | 0:f9d13e09cf11 | 93 | obs_list_t * newP; |
terencez | 0:f9d13e09cf11 | 94 | |
terencez | 0:f9d13e09cf11 | 95 | newP = (obs_list_t *)lwm2m_malloc(sizeof(obs_list_t)); |
terencez | 0:f9d13e09cf11 | 96 | if (newP != NULL) |
terencez | 0:f9d13e09cf11 | 97 | { |
terencez | 0:f9d13e09cf11 | 98 | newP->item = targetP; |
terencez | 0:f9d13e09cf11 | 99 | newP->next = resultP; |
terencez | 0:f9d13e09cf11 | 100 | resultP = newP; |
terencez | 0:f9d13e09cf11 | 101 | } |
terencez | 0:f9d13e09cf11 | 102 | } |
terencez | 0:f9d13e09cf11 | 103 | } |
terencez | 0:f9d13e09cf11 | 104 | } |
terencez | 0:f9d13e09cf11 | 105 | targetP = targetP->next; |
terencez | 0:f9d13e09cf11 | 106 | } |
terencez | 0:f9d13e09cf11 | 107 | |
terencez | 0:f9d13e09cf11 | 108 | return resultP; |
terencez | 0:f9d13e09cf11 | 109 | } |
terencez | 0:f9d13e09cf11 | 110 | |
terencez | 0:f9d13e09cf11 | 111 | static void prv_unlinkObserved(lwm2m_context_t * contextP, |
terencez | 0:f9d13e09cf11 | 112 | lwm2m_observed_t * observedP) |
terencez | 0:f9d13e09cf11 | 113 | { |
terencez | 0:f9d13e09cf11 | 114 | if (contextP->observedList == observedP) |
terencez | 0:f9d13e09cf11 | 115 | { |
terencez | 0:f9d13e09cf11 | 116 | contextP->observedList = contextP->observedList->next; |
terencez | 0:f9d13e09cf11 | 117 | } |
terencez | 0:f9d13e09cf11 | 118 | else |
terencez | 0:f9d13e09cf11 | 119 | { |
terencez | 0:f9d13e09cf11 | 120 | lwm2m_observed_t * parentP; |
terencez | 0:f9d13e09cf11 | 121 | |
terencez | 0:f9d13e09cf11 | 122 | parentP = contextP->observedList; |
terencez | 0:f9d13e09cf11 | 123 | while (parentP->next != NULL |
terencez | 0:f9d13e09cf11 | 124 | && parentP->next != observedP) |
terencez | 0:f9d13e09cf11 | 125 | { |
terencez | 0:f9d13e09cf11 | 126 | parentP = parentP->next; |
terencez | 0:f9d13e09cf11 | 127 | } |
terencez | 0:f9d13e09cf11 | 128 | if (parentP->next != NULL) |
terencez | 0:f9d13e09cf11 | 129 | { |
terencez | 0:f9d13e09cf11 | 130 | parentP->next = parentP->next->next; |
terencez | 0:f9d13e09cf11 | 131 | } |
terencez | 0:f9d13e09cf11 | 132 | } |
terencez | 0:f9d13e09cf11 | 133 | } |
terencez | 0:f9d13e09cf11 | 134 | |
terencez | 0:f9d13e09cf11 | 135 | static lwm2m_server_t * prv_findServer(lwm2m_context_t * contextP, |
terencez | 0:f9d13e09cf11 | 136 | void * fromSessionH) |
terencez | 0:f9d13e09cf11 | 137 | { |
terencez | 0:f9d13e09cf11 | 138 | lwm2m_server_t * targetP; |
terencez | 0:f9d13e09cf11 | 139 | |
terencez | 0:f9d13e09cf11 | 140 | targetP = contextP->serverList; |
terencez | 0:f9d13e09cf11 | 141 | while (targetP != NULL |
terencez | 0:f9d13e09cf11 | 142 | && targetP->sessionH != fromSessionH) |
terencez | 0:f9d13e09cf11 | 143 | { |
terencez | 0:f9d13e09cf11 | 144 | targetP = targetP->next; |
terencez | 0:f9d13e09cf11 | 145 | } |
terencez | 0:f9d13e09cf11 | 146 | |
terencez | 0:f9d13e09cf11 | 147 | return targetP; |
terencez | 0:f9d13e09cf11 | 148 | } |
terencez | 0:f9d13e09cf11 | 149 | |
terencez | 0:f9d13e09cf11 | 150 | static lwm2m_watcher_t * prv_findWatcher(lwm2m_observed_t * observedP, |
terencez | 0:f9d13e09cf11 | 151 | lwm2m_server_t * serverP) |
terencez | 0:f9d13e09cf11 | 152 | { |
terencez | 0:f9d13e09cf11 | 153 | lwm2m_watcher_t * targetP; |
terencez | 0:f9d13e09cf11 | 154 | |
terencez | 0:f9d13e09cf11 | 155 | targetP = observedP->watcherList; |
terencez | 0:f9d13e09cf11 | 156 | while (targetP != NULL |
terencez | 0:f9d13e09cf11 | 157 | && targetP->server != serverP) |
terencez | 0:f9d13e09cf11 | 158 | { |
terencez | 0:f9d13e09cf11 | 159 | targetP = targetP->next; |
terencez | 0:f9d13e09cf11 | 160 | } |
terencez | 0:f9d13e09cf11 | 161 | |
terencez | 0:f9d13e09cf11 | 162 | return targetP; |
terencez | 0:f9d13e09cf11 | 163 | } |
terencez | 0:f9d13e09cf11 | 164 | |
terencez | 0:f9d13e09cf11 | 165 | coap_status_t handle_observe_request(lwm2m_context_t * contextP, |
terencez | 0:f9d13e09cf11 | 166 | lwm2m_uri_t * uriP, |
terencez | 0:f9d13e09cf11 | 167 | void * fromSessionH, |
terencez | 0:f9d13e09cf11 | 168 | coap_packet_t * message, |
terencez | 0:f9d13e09cf11 | 169 | coap_packet_t * response) |
terencez | 0:f9d13e09cf11 | 170 | { |
terencez | 0:f9d13e09cf11 | 171 | lwm2m_observed_t * observedP; |
terencez | 0:f9d13e09cf11 | 172 | lwm2m_watcher_t * watcherP; |
terencez | 0:f9d13e09cf11 | 173 | lwm2m_server_t * serverP; |
terencez | 0:f9d13e09cf11 | 174 | |
terencez | 0:f9d13e09cf11 | 175 | LOG("handle_observe_request()\r\n"); |
terencez | 0:f9d13e09cf11 | 176 | |
terencez | 0:f9d13e09cf11 | 177 | if (!LWM2M_URI_IS_SET_INSTANCE(uriP) && LWM2M_URI_IS_SET_RESOURCE(uriP)) return COAP_400_BAD_REQUEST; |
terencez | 0:f9d13e09cf11 | 178 | if (message->token_len == 0) return COAP_400_BAD_REQUEST; |
terencez | 0:f9d13e09cf11 | 179 | |
terencez | 0:f9d13e09cf11 | 180 | serverP = prv_findServer(contextP, fromSessionH); |
terencez | 0:f9d13e09cf11 | 181 | if (serverP == NULL || serverP->status != STATE_REGISTERED) return COAP_401_UNAUTHORIZED; |
terencez | 0:f9d13e09cf11 | 182 | |
terencez | 0:f9d13e09cf11 | 183 | observedP = prv_findObserved(contextP, uriP); |
terencez | 0:f9d13e09cf11 | 184 | if (observedP == NULL) |
terencez | 0:f9d13e09cf11 | 185 | { |
terencez | 0:f9d13e09cf11 | 186 | observedP = (lwm2m_observed_t *)lwm2m_malloc(sizeof(lwm2m_observed_t)); |
terencez | 0:f9d13e09cf11 | 187 | if (observedP == NULL) return COAP_500_INTERNAL_SERVER_ERROR; |
terencez | 0:f9d13e09cf11 | 188 | memset(observedP, 0, sizeof(lwm2m_observed_t)); |
terencez | 0:f9d13e09cf11 | 189 | memcpy(&(observedP->uri), uriP, sizeof(lwm2m_uri_t)); |
terencez | 0:f9d13e09cf11 | 190 | observedP->next = contextP->observedList; |
terencez | 0:f9d13e09cf11 | 191 | contextP->observedList = observedP; |
terencez | 0:f9d13e09cf11 | 192 | } |
terencez | 0:f9d13e09cf11 | 193 | |
terencez | 0:f9d13e09cf11 | 194 | watcherP = prv_findWatcher(observedP, serverP); |
terencez | 0:f9d13e09cf11 | 195 | if (watcherP == NULL) |
terencez | 0:f9d13e09cf11 | 196 | { |
terencez | 0:f9d13e09cf11 | 197 | watcherP = (lwm2m_watcher_t *)lwm2m_malloc(sizeof(lwm2m_watcher_t)); |
terencez | 0:f9d13e09cf11 | 198 | if (watcherP == NULL) return COAP_500_INTERNAL_SERVER_ERROR; |
terencez | 0:f9d13e09cf11 | 199 | memset(watcherP, 0, sizeof(lwm2m_watcher_t)); |
terencez | 0:f9d13e09cf11 | 200 | watcherP->server = serverP; |
terencez | 0:f9d13e09cf11 | 201 | watcherP->tokenLen = message->token_len; |
terencez | 0:f9d13e09cf11 | 202 | memcpy(watcherP->token, message->token, message->token_len); |
terencez | 0:f9d13e09cf11 | 203 | watcherP->next = observedP->watcherList; |
terencez | 0:f9d13e09cf11 | 204 | observedP->watcherList = watcherP; |
terencez | 0:f9d13e09cf11 | 205 | } |
terencez | 0:f9d13e09cf11 | 206 | |
terencez | 0:f9d13e09cf11 | 207 | coap_set_header_observe(response, watcherP->counter++); |
terencez | 0:f9d13e09cf11 | 208 | |
terencez | 0:f9d13e09cf11 | 209 | return COAP_205_CONTENT; |
terencez | 0:f9d13e09cf11 | 210 | } |
terencez | 0:f9d13e09cf11 | 211 | |
terencez | 0:f9d13e09cf11 | 212 | void cancel_observe(lwm2m_context_t * contextP, |
terencez | 0:f9d13e09cf11 | 213 | uint16_t mid, |
terencez | 0:f9d13e09cf11 | 214 | void * fromSessionH) |
terencez | 0:f9d13e09cf11 | 215 | { |
terencez | 0:f9d13e09cf11 | 216 | lwm2m_observed_t * observedP; |
terencez | 0:f9d13e09cf11 | 217 | |
terencez | 0:f9d13e09cf11 | 218 | LOG("cancel_observe()\r\n"); |
terencez | 0:f9d13e09cf11 | 219 | |
terencez | 0:f9d13e09cf11 | 220 | for (observedP = contextP->observedList; |
terencez | 0:f9d13e09cf11 | 221 | observedP != NULL; |
terencez | 0:f9d13e09cf11 | 222 | observedP = observedP->next) |
terencez | 0:f9d13e09cf11 | 223 | { |
terencez | 0:f9d13e09cf11 | 224 | lwm2m_watcher_t * targetP = NULL; |
terencez | 0:f9d13e09cf11 | 225 | |
terencez | 0:f9d13e09cf11 | 226 | if (observedP->watcherList->lastMid == mid |
terencez | 0:f9d13e09cf11 | 227 | && observedP->watcherList->server->sessionH == fromSessionH) |
terencez | 0:f9d13e09cf11 | 228 | { |
terencez | 0:f9d13e09cf11 | 229 | targetP = observedP->watcherList; |
terencez | 0:f9d13e09cf11 | 230 | observedP->watcherList = observedP->watcherList->next; |
terencez | 0:f9d13e09cf11 | 231 | } |
terencez | 0:f9d13e09cf11 | 232 | else |
terencez | 0:f9d13e09cf11 | 233 | { |
terencez | 0:f9d13e09cf11 | 234 | lwm2m_watcher_t * parentP; |
terencez | 0:f9d13e09cf11 | 235 | |
terencez | 0:f9d13e09cf11 | 236 | parentP = observedP->watcherList; |
terencez | 0:f9d13e09cf11 | 237 | while (parentP->next != NULL |
terencez | 0:f9d13e09cf11 | 238 | && (parentP->next->lastMid != mid |
terencez | 0:f9d13e09cf11 | 239 | || parentP->next->server->sessionH != fromSessionH)) |
terencez | 0:f9d13e09cf11 | 240 | { |
terencez | 0:f9d13e09cf11 | 241 | parentP = parentP->next; |
terencez | 0:f9d13e09cf11 | 242 | } |
terencez | 0:f9d13e09cf11 | 243 | if (parentP->next != NULL) |
terencez | 0:f9d13e09cf11 | 244 | { |
terencez | 0:f9d13e09cf11 | 245 | targetP = parentP->next; |
terencez | 0:f9d13e09cf11 | 246 | parentP->next = parentP->next->next; |
terencez | 0:f9d13e09cf11 | 247 | } |
terencez | 0:f9d13e09cf11 | 248 | } |
terencez | 0:f9d13e09cf11 | 249 | if (targetP != NULL) |
terencez | 0:f9d13e09cf11 | 250 | { |
terencez | 0:f9d13e09cf11 | 251 | lwm2m_free(targetP); |
terencez | 0:f9d13e09cf11 | 252 | if (observedP->watcherList == NULL) |
terencez | 0:f9d13e09cf11 | 253 | { |
terencez | 0:f9d13e09cf11 | 254 | prv_unlinkObserved(contextP, observedP); |
terencez | 0:f9d13e09cf11 | 255 | lwm2m_free(observedP); |
terencez | 0:f9d13e09cf11 | 256 | } |
terencez | 0:f9d13e09cf11 | 257 | return; |
terencez | 0:f9d13e09cf11 | 258 | } |
terencez | 0:f9d13e09cf11 | 259 | } |
terencez | 0:f9d13e09cf11 | 260 | } |
terencez | 0:f9d13e09cf11 | 261 | |
terencez | 0:f9d13e09cf11 | 262 | void lwm2m_resource_value_changed(lwm2m_context_t * contextP, |
terencez | 0:f9d13e09cf11 | 263 | lwm2m_uri_t * uriP) |
terencez | 0:f9d13e09cf11 | 264 | { |
terencez | 0:f9d13e09cf11 | 265 | int result; |
terencez | 0:f9d13e09cf11 | 266 | obs_list_t * listP; |
terencez | 0:f9d13e09cf11 | 267 | lwm2m_watcher_t * watcherP; |
terencez | 0:f9d13e09cf11 | 268 | |
terencez | 0:f9d13e09cf11 | 269 | listP = prv_getObservedList(contextP, uriP); |
terencez | 0:f9d13e09cf11 | 270 | while (listP != NULL) |
terencez | 0:f9d13e09cf11 | 271 | { |
terencez | 0:f9d13e09cf11 | 272 | obs_list_t * targetP; |
terencez | 0:f9d13e09cf11 | 273 | char * buffer = NULL; |
terencez | 0:f9d13e09cf11 | 274 | int length = 0; |
terencez | 0:f9d13e09cf11 | 275 | |
terencez | 0:f9d13e09cf11 | 276 | result = object_read(contextP, &listP->item->uri, &buffer, &length); |
terencez | 0:f9d13e09cf11 | 277 | if (result == COAP_205_CONTENT) |
terencez | 0:f9d13e09cf11 | 278 | { |
terencez | 0:f9d13e09cf11 | 279 | coap_packet_t message[1]; |
terencez | 0:f9d13e09cf11 | 280 | |
terencez | 0:f9d13e09cf11 | 281 | coap_init_message(message, COAP_TYPE_NON, COAP_204_CHANGED, 0); |
terencez | 0:f9d13e09cf11 | 282 | coap_set_payload(message, buffer, length); |
terencez | 0:f9d13e09cf11 | 283 | |
terencez | 0:f9d13e09cf11 | 284 | for (watcherP = listP->item->watcherList ; watcherP != NULL ; watcherP = watcherP->next) |
terencez | 0:f9d13e09cf11 | 285 | { |
terencez | 0:f9d13e09cf11 | 286 | watcherP->lastMid = contextP->nextMID++; |
terencez | 0:f9d13e09cf11 | 287 | message->mid = watcherP->lastMid; |
terencez | 0:f9d13e09cf11 | 288 | coap_set_header_token(message, watcherP->token, watcherP->tokenLen); |
terencez | 0:f9d13e09cf11 | 289 | coap_set_header_observe(message, watcherP->counter++); |
terencez | 0:f9d13e09cf11 | 290 | (void)message_send(contextP, message, watcherP->server->sessionH); |
terencez | 0:f9d13e09cf11 | 291 | } |
terencez | 0:f9d13e09cf11 | 292 | } |
terencez | 0:f9d13e09cf11 | 293 | |
terencez | 0:f9d13e09cf11 | 294 | targetP = listP; |
terencez | 0:f9d13e09cf11 | 295 | listP = listP->next; |
terencez | 0:f9d13e09cf11 | 296 | lwm2m_free(targetP); |
terencez | 0:f9d13e09cf11 | 297 | } |
terencez | 0:f9d13e09cf11 | 298 | |
terencez | 0:f9d13e09cf11 | 299 | } |
terencez | 0:f9d13e09cf11 | 300 | #endif |
terencez | 0:f9d13e09cf11 | 301 | |
terencez | 0:f9d13e09cf11 | 302 | #ifdef LWM2M_SERVER_MODE |
terencez | 0:f9d13e09cf11 | 303 | static lwm2m_observation_t * prv_findObservationByURI(lwm2m_client_t * clientP, |
terencez | 0:f9d13e09cf11 | 304 | lwm2m_uri_t * uriP) |
terencez | 0:f9d13e09cf11 | 305 | { |
terencez | 0:f9d13e09cf11 | 306 | lwm2m_observation_t * targetP; |
terencez | 0:f9d13e09cf11 | 307 | |
terencez | 0:f9d13e09cf11 | 308 | targetP = clientP->observationList; |
terencez | 0:f9d13e09cf11 | 309 | while (targetP != NULL) |
terencez | 0:f9d13e09cf11 | 310 | { |
terencez | 0:f9d13e09cf11 | 311 | if (targetP->uri.objectId == uriP->objectId |
terencez | 0:f9d13e09cf11 | 312 | && targetP->uri.flag == uriP->flag |
terencez | 0:f9d13e09cf11 | 313 | && targetP->uri.instanceId == uriP->instanceId |
terencez | 0:f9d13e09cf11 | 314 | && targetP->uri.resourceId == uriP->resourceId) |
terencez | 0:f9d13e09cf11 | 315 | { |
terencez | 0:f9d13e09cf11 | 316 | return targetP; |
terencez | 0:f9d13e09cf11 | 317 | } |
terencez | 0:f9d13e09cf11 | 318 | |
terencez | 0:f9d13e09cf11 | 319 | targetP = targetP->next; |
terencez | 0:f9d13e09cf11 | 320 | } |
terencez | 0:f9d13e09cf11 | 321 | |
terencez | 0:f9d13e09cf11 | 322 | return targetP; |
terencez | 0:f9d13e09cf11 | 323 | } |
terencez | 0:f9d13e09cf11 | 324 | |
terencez | 0:f9d13e09cf11 | 325 | void observation_remove(lwm2m_client_t * clientP, |
terencez | 0:f9d13e09cf11 | 326 | lwm2m_observation_t * observationP) |
terencez | 0:f9d13e09cf11 | 327 | { |
terencez | 0:f9d13e09cf11 | 328 | if (clientP->observationList == observationP) |
terencez | 0:f9d13e09cf11 | 329 | { |
terencez | 0:f9d13e09cf11 | 330 | clientP->observationList = clientP->observationList->next; |
terencez | 0:f9d13e09cf11 | 331 | } |
terencez | 0:f9d13e09cf11 | 332 | else if (clientP->observationList != NULL) |
terencez | 0:f9d13e09cf11 | 333 | { |
terencez | 0:f9d13e09cf11 | 334 | lwm2m_observation_t * parentP; |
terencez | 0:f9d13e09cf11 | 335 | |
terencez | 0:f9d13e09cf11 | 336 | parentP = clientP->observationList; |
terencez | 0:f9d13e09cf11 | 337 | |
terencez | 0:f9d13e09cf11 | 338 | while (parentP->next != NULL |
terencez | 0:f9d13e09cf11 | 339 | && parentP->next != observationP) |
terencez | 0:f9d13e09cf11 | 340 | { |
terencez | 0:f9d13e09cf11 | 341 | parentP = parentP->next; |
terencez | 0:f9d13e09cf11 | 342 | } |
terencez | 0:f9d13e09cf11 | 343 | if (parentP->next != NULL) |
terencez | 0:f9d13e09cf11 | 344 | { |
terencez | 0:f9d13e09cf11 | 345 | parentP->next = parentP->next->next; |
terencez | 0:f9d13e09cf11 | 346 | } |
terencez | 0:f9d13e09cf11 | 347 | } |
terencez | 0:f9d13e09cf11 | 348 | |
terencez | 0:f9d13e09cf11 | 349 | lwm2m_free(observationP); |
terencez | 0:f9d13e09cf11 | 350 | } |
terencez | 0:f9d13e09cf11 | 351 | |
terencez | 0:f9d13e09cf11 | 352 | static void prv_obsRequestCallback(lwm2m_transaction_t * transacP, |
terencez | 0:f9d13e09cf11 | 353 | void * message) |
terencez | 0:f9d13e09cf11 | 354 | { |
terencez | 0:f9d13e09cf11 | 355 | lwm2m_observation_t * observationP = (lwm2m_observation_t *)transacP->userData; |
terencez | 0:f9d13e09cf11 | 356 | coap_packet_t * packet = (coap_packet_t *)message; |
terencez | 0:f9d13e09cf11 | 357 | uint8_t code; |
terencez | 0:f9d13e09cf11 | 358 | |
terencez | 0:f9d13e09cf11 | 359 | if (message == NULL) |
terencez | 0:f9d13e09cf11 | 360 | { |
terencez | 0:f9d13e09cf11 | 361 | code = COAP_503_SERVICE_UNAVAILABLE; |
terencez | 0:f9d13e09cf11 | 362 | } |
terencez | 0:f9d13e09cf11 | 363 | else if (packet->code == COAP_205_CONTENT |
terencez | 0:f9d13e09cf11 | 364 | && !IS_OPTION(packet, COAP_OPTION_OBSERVE)) |
terencez | 0:f9d13e09cf11 | 365 | { |
terencez | 0:f9d13e09cf11 | 366 | code = COAP_405_METHOD_NOT_ALLOWED; |
terencez | 0:f9d13e09cf11 | 367 | } |
terencez | 0:f9d13e09cf11 | 368 | else |
terencez | 0:f9d13e09cf11 | 369 | { |
terencez | 0:f9d13e09cf11 | 370 | code = packet->code; |
terencez | 0:f9d13e09cf11 | 371 | } |
terencez | 0:f9d13e09cf11 | 372 | |
terencez | 0:f9d13e09cf11 | 373 | if (code != COAP_205_CONTENT) |
terencez | 0:f9d13e09cf11 | 374 | { |
terencez | 0:f9d13e09cf11 | 375 | observationP->callback(((lwm2m_client_t*)transacP->peerP)->internalID, |
terencez | 0:f9d13e09cf11 | 376 | &observationP->uri, |
terencez | 0:f9d13e09cf11 | 377 | code, |
terencez | 0:f9d13e09cf11 | 378 | NULL, 0, |
terencez | 0:f9d13e09cf11 | 379 | observationP->userData); |
terencez | 0:f9d13e09cf11 | 380 | observation_remove(((lwm2m_client_t*)transacP->peerP), observationP); |
terencez | 0:f9d13e09cf11 | 381 | } |
terencez | 0:f9d13e09cf11 | 382 | else |
terencez | 0:f9d13e09cf11 | 383 | { |
terencez | 0:f9d13e09cf11 | 384 | observationP->clientP->observationList = (lwm2m_observation_t *)LWM2M_LIST_ADD(observationP->clientP->observationList, observationP); |
terencez | 0:f9d13e09cf11 | 385 | observationP->callback(((lwm2m_client_t*)transacP->peerP)->internalID, |
terencez | 0:f9d13e09cf11 | 386 | &observationP->uri, |
terencez | 0:f9d13e09cf11 | 387 | 0, |
terencez | 0:f9d13e09cf11 | 388 | packet->payload, packet->payload_len, |
terencez | 0:f9d13e09cf11 | 389 | observationP->userData); |
terencez | 0:f9d13e09cf11 | 390 | } |
terencez | 0:f9d13e09cf11 | 391 | } |
terencez | 0:f9d13e09cf11 | 392 | |
terencez | 0:f9d13e09cf11 | 393 | int lwm2m_observe(lwm2m_context_t * contextP, |
terencez | 0:f9d13e09cf11 | 394 | uint16_t clientID, |
terencez | 0:f9d13e09cf11 | 395 | lwm2m_uri_t * uriP, |
terencez | 0:f9d13e09cf11 | 396 | lwm2m_result_callback_t callback, |
terencez | 0:f9d13e09cf11 | 397 | void * userData) |
terencez | 0:f9d13e09cf11 | 398 | { |
terencez | 0:f9d13e09cf11 | 399 | lwm2m_client_t * clientP; |
terencez | 0:f9d13e09cf11 | 400 | lwm2m_transaction_t * transactionP; |
terencez | 0:f9d13e09cf11 | 401 | lwm2m_observation_t * observationP; |
terencez | 0:f9d13e09cf11 | 402 | uint8_t token[4]; |
terencez | 0:f9d13e09cf11 | 403 | |
terencez | 0:f9d13e09cf11 | 404 | if (!LWM2M_URI_IS_SET_INSTANCE(uriP) && LWM2M_URI_IS_SET_RESOURCE(uriP)) return COAP_400_BAD_REQUEST; |
terencez | 0:f9d13e09cf11 | 405 | |
terencez | 0:f9d13e09cf11 | 406 | clientP = (lwm2m_client_t *)lwm2m_list_find((lwm2m_list_t *)contextP->clientList, clientID); |
terencez | 0:f9d13e09cf11 | 407 | if (clientP == NULL) return COAP_404_NOT_FOUND; |
terencez | 0:f9d13e09cf11 | 408 | |
terencez | 0:f9d13e09cf11 | 409 | observationP = (lwm2m_observation_t *)lwm2m_malloc(sizeof(lwm2m_observation_t)); |
terencez | 0:f9d13e09cf11 | 410 | if (observationP == NULL) return COAP_500_INTERNAL_SERVER_ERROR; |
terencez | 0:f9d13e09cf11 | 411 | memset(observationP, 0, sizeof(lwm2m_observation_t)); |
terencez | 0:f9d13e09cf11 | 412 | |
terencez | 0:f9d13e09cf11 | 413 | transactionP = transaction_new(COAP_GET, uriP, contextP->nextMID++, ENDPOINT_CLIENT, (void *)clientP); |
terencez | 0:f9d13e09cf11 | 414 | if (transactionP == NULL) |
terencez | 0:f9d13e09cf11 | 415 | { |
terencez | 0:f9d13e09cf11 | 416 | lwm2m_free(observationP); |
terencez | 0:f9d13e09cf11 | 417 | return COAP_500_INTERNAL_SERVER_ERROR; |
terencez | 0:f9d13e09cf11 | 418 | } |
terencez | 0:f9d13e09cf11 | 419 | |
terencez | 0:f9d13e09cf11 | 420 | observationP->id = lwm2m_list_newId((lwm2m_list_t *)clientP->observationList); |
terencez | 0:f9d13e09cf11 | 421 | memcpy(&observationP->uri, uriP, sizeof(lwm2m_uri_t)); |
terencez | 0:f9d13e09cf11 | 422 | observationP->clientP = clientP; |
terencez | 0:f9d13e09cf11 | 423 | observationP->callback = callback; |
terencez | 0:f9d13e09cf11 | 424 | observationP->userData = userData; |
terencez | 0:f9d13e09cf11 | 425 | |
terencez | 0:f9d13e09cf11 | 426 | token[0] = clientP->internalID >> 8; |
terencez | 0:f9d13e09cf11 | 427 | token[1] = clientP->internalID & 0xFF; |
terencez | 0:f9d13e09cf11 | 428 | token[2] = observationP->id >> 8; |
terencez | 0:f9d13e09cf11 | 429 | token[3] = observationP->id & 0xFF; |
terencez | 0:f9d13e09cf11 | 430 | |
terencez | 0:f9d13e09cf11 | 431 | coap_set_header_observe(transactionP->message, 0); |
terencez | 0:f9d13e09cf11 | 432 | coap_set_header_token(transactionP->message, token, sizeof(token)); |
terencez | 0:f9d13e09cf11 | 433 | |
terencez | 0:f9d13e09cf11 | 434 | transactionP->callback = prv_obsRequestCallback; |
terencez | 0:f9d13e09cf11 | 435 | transactionP->userData = (void *)observationP; |
terencez | 0:f9d13e09cf11 | 436 | |
terencez | 0:f9d13e09cf11 | 437 | contextP->transactionList = (lwm2m_transaction_t *)LWM2M_LIST_ADD(contextP->transactionList, transactionP); |
terencez | 0:f9d13e09cf11 | 438 | |
terencez | 0:f9d13e09cf11 | 439 | return transaction_send(contextP, transactionP); |
terencez | 0:f9d13e09cf11 | 440 | } |
terencez | 0:f9d13e09cf11 | 441 | |
terencez | 0:f9d13e09cf11 | 442 | int lwm2m_observe_cancel(lwm2m_context_t * contextP, |
terencez | 0:f9d13e09cf11 | 443 | uint16_t clientID, |
terencez | 0:f9d13e09cf11 | 444 | lwm2m_uri_t * uriP, |
terencez | 0:f9d13e09cf11 | 445 | lwm2m_result_callback_t callback, |
terencez | 0:f9d13e09cf11 | 446 | void * userData) |
terencez | 0:f9d13e09cf11 | 447 | { |
terencez | 0:f9d13e09cf11 | 448 | lwm2m_client_t * clientP; |
terencez | 0:f9d13e09cf11 | 449 | lwm2m_observation_t * observationP; |
terencez | 0:f9d13e09cf11 | 450 | |
terencez | 0:f9d13e09cf11 | 451 | clientP = (lwm2m_client_t *)lwm2m_list_find((lwm2m_list_t *)contextP->clientList, clientID); |
terencez | 0:f9d13e09cf11 | 452 | if (clientP == NULL) return COAP_404_NOT_FOUND; |
terencez | 0:f9d13e09cf11 | 453 | |
terencez | 0:f9d13e09cf11 | 454 | observationP = prv_findObservationByURI(clientP, uriP); |
terencez | 0:f9d13e09cf11 | 455 | if (observationP == NULL) return COAP_404_NOT_FOUND; |
terencez | 0:f9d13e09cf11 | 456 | |
terencez | 0:f9d13e09cf11 | 457 | observation_remove(clientP, observationP); |
terencez | 0:f9d13e09cf11 | 458 | |
terencez | 0:f9d13e09cf11 | 459 | return 0; |
terencez | 0:f9d13e09cf11 | 460 | } |
terencez | 0:f9d13e09cf11 | 461 | |
terencez | 0:f9d13e09cf11 | 462 | void handle_observe_notify(lwm2m_context_t * contextP, |
terencez | 0:f9d13e09cf11 | 463 | void * fromSessionH, |
terencez | 0:f9d13e09cf11 | 464 | coap_packet_t * message) |
terencez | 0:f9d13e09cf11 | 465 | { |
terencez | 0:f9d13e09cf11 | 466 | uint8_t * tokenP; |
terencez | 0:f9d13e09cf11 | 467 | int token_len; |
terencez | 0:f9d13e09cf11 | 468 | uint16_t clientID; |
terencez | 0:f9d13e09cf11 | 469 | uint16_t obsID; |
terencez | 0:f9d13e09cf11 | 470 | lwm2m_client_t * clientP; |
terencez | 0:f9d13e09cf11 | 471 | lwm2m_observation_t * observationP; |
terencez | 0:f9d13e09cf11 | 472 | uint32_t count; |
terencez | 0:f9d13e09cf11 | 473 | |
terencez | 0:f9d13e09cf11 | 474 | token_len = coap_get_header_token(message, (const uint8_t **)&tokenP); |
terencez | 0:f9d13e09cf11 | 475 | if (token_len != sizeof(uint32_t)) return; |
terencez | 0:f9d13e09cf11 | 476 | |
terencez | 0:f9d13e09cf11 | 477 | if (1 != coap_get_header_observe(message, &count)) return; |
terencez | 0:f9d13e09cf11 | 478 | |
terencez | 0:f9d13e09cf11 | 479 | clientID = (tokenP[0] << 8) | tokenP[1]; |
terencez | 0:f9d13e09cf11 | 480 | obsID = (tokenP[2] << 8) | tokenP[3]; |
terencez | 0:f9d13e09cf11 | 481 | |
terencez | 0:f9d13e09cf11 | 482 | clientP = (lwm2m_client_t *)lwm2m_list_find((lwm2m_list_t *)contextP->clientList, clientID); |
terencez | 0:f9d13e09cf11 | 483 | if (clientP == NULL) return; |
terencez | 0:f9d13e09cf11 | 484 | |
terencez | 0:f9d13e09cf11 | 485 | observationP = (lwm2m_observation_t *)lwm2m_list_find((lwm2m_list_t *)clientP->observationList, obsID); |
terencez | 0:f9d13e09cf11 | 486 | if (observationP == NULL) |
terencez | 0:f9d13e09cf11 | 487 | { |
terencez | 0:f9d13e09cf11 | 488 | coap_packet_t resetMsg; |
terencez | 0:f9d13e09cf11 | 489 | |
terencez | 0:f9d13e09cf11 | 490 | coap_init_message(&resetMsg, COAP_TYPE_RST, 0, message->mid); |
terencez | 0:f9d13e09cf11 | 491 | |
terencez | 0:f9d13e09cf11 | 492 | message_send(contextP, &resetMsg, fromSessionH); |
terencez | 0:f9d13e09cf11 | 493 | } |
terencez | 0:f9d13e09cf11 | 494 | else |
terencez | 0:f9d13e09cf11 | 495 | { |
terencez | 0:f9d13e09cf11 | 496 | observationP->callback(clientID, |
terencez | 0:f9d13e09cf11 | 497 | &observationP->uri, |
terencez | 0:f9d13e09cf11 | 498 | (int)count, |
terencez | 0:f9d13e09cf11 | 499 | message->payload, message->payload_len, |
terencez | 0:f9d13e09cf11 | 500 | observationP->userData); |
terencez | 0:f9d13e09cf11 | 501 | } |
terencez | 0:f9d13e09cf11 | 502 | } |
terencez | 0:f9d13e09cf11 | 503 | #endif |