terence zhang / wakaama-core
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers uri.c Source File

uri.c

00001 /*******************************************************************************
00002  *
00003  * Copyright (c) 2013, 2014 Intel Corporation and others.
00004  * All rights reserved. This program and the accompanying materials
00005  * are made available under the terms of the Eclipse Public License v1.0
00006  * and Eclipse Distribution License v1.0 which accompany this distribution.
00007  *
00008  * The Eclipse Public License is available at
00009  *    http://www.eclipse.org/legal/epl-v10.html
00010  * The Eclipse Distribution License is available at
00011  *    http://www.eclipse.org/org/documents/edl-v10.php.
00012  *
00013  * Contributors:
00014  *    David Navarro, Intel Corporation - initial API and implementation
00015  *    Fabien Fleutot - Please refer to git log
00016  *    Toby Jaffey - Please refer to git log
00017  *    Bosch Software Innovations GmbH - Please refer to git log
00018  *    Pascal Rieux - Please refer to git log
00019  *    
00020  *******************************************************************************/
00021 
00022 /*
00023  Copyright (c) 2013, 2014 Intel Corporation
00024 
00025  Redistribution and use in source and binary forms, with or without modification,
00026  are permitted provided that the following conditions are met:
00027 
00028      * Redistributions of source code must retain the above copyright notice,
00029        this list of conditions and the following disclaimer.
00030      * Redistributions in binary form must reproduce the above copyright notice,
00031        this list of conditions and the following disclaimer in the documentation
00032        and/or other materials provided with the distribution.
00033      * Neither the name of Intel Corporation nor the names of its contributors
00034        may be used to endorse or promote products derived from this software
00035        without specific prior written permission.
00036 
00037  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00038  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00039  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00040  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
00041  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00042  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00043  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00044  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
00045  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
00046  THE POSSIBILITY OF SUCH DAMAGE.
00047 
00048  David Navarro <david.navarro@intel.com>
00049 
00050 */
00051 
00052 #include "internals.h"
00053 #include <stdlib.h>
00054 #include <string.h>
00055 #include <ctype.h>
00056 
00057 
00058 static int prv_parseNumber(uint8_t * uriString,
00059                             size_t uriLength,
00060                             size_t * headP)
00061 {
00062     int result = 0;
00063 
00064     if (uriString[*headP] == '/')
00065     {
00066         // empty Object Instance ID with resource ID is not allowed
00067         return -1;
00068     }
00069     while (*headP < uriLength && uriString[*headP] != '/')
00070     {
00071         if ('0' <= uriString[*headP] && uriString[*headP] <= '9')
00072         {
00073             result += uriString[*headP] - '0';
00074             result *= 10;
00075         }
00076         else
00077         {
00078             return -1;
00079         }
00080         *headP += 1;
00081     }
00082 
00083     result /= 10;
00084     return result;
00085 }
00086 
00087 
00088 int uri_getNumber(uint8_t * uriString,
00089                    size_t uriLength)
00090 {
00091     size_t index = 0;
00092 
00093     return prv_parseNumber(uriString, uriLength, &index);
00094 }
00095 
00096 
00097 lwm2m_uri_t * uri_decode(char * altPath,
00098                          multi_option_t *uriPath)
00099 {
00100     lwm2m_uri_t * uriP;
00101     int readNum;
00102 
00103     LOG_ARG("altPath: \"%s\"", altPath);
00104 
00105     uriP = (lwm2m_uri_t *)lwm2m_malloc(sizeof(lwm2m_uri_t));
00106     if (NULL == uriP) return NULL;
00107 
00108     memset(uriP, 0, sizeof(lwm2m_uri_t));
00109 
00110     // Read object ID
00111     if (NULL != uriPath
00112      && URI_REGISTRATION_SEGMENT_LEN == uriPath->len
00113      && 0 == strncmp(URI_REGISTRATION_SEGMENT, (char *)uriPath->data, uriPath->len))
00114     {
00115         uriP->flag |= LWM2M_URI_FLAG_REGISTRATION;
00116         uriPath = uriPath->next;
00117         if (uriPath == NULL) return uriP;
00118     }
00119     else if (NULL != uriPath
00120      && URI_BOOTSTRAP_SEGMENT_LEN == uriPath->len
00121      && 0 == strncmp(URI_BOOTSTRAP_SEGMENT, (char *)uriPath->data, uriPath->len))
00122     {
00123         uriP->flag |= LWM2M_URI_FLAG_BOOTSTRAP;
00124         uriPath = uriPath->next;
00125         if (uriPath != NULL) goto error;
00126         return uriP;
00127     }
00128 
00129     if ((uriP->flag & LWM2M_URI_MASK_TYPE) != LWM2M_URI_FLAG_REGISTRATION)
00130     {
00131         // Read altPath if any
00132         if (altPath != NULL)
00133         {
00134             int i;
00135             if (NULL == uriPath)
00136             {
00137                 lwm2m_free(uriP);
00138                 return NULL;
00139             }
00140             for (i = 0 ; i < uriPath->len ; i++)
00141             {
00142                 if (uriPath->data[i] != altPath[i+1])
00143                 {
00144                     lwm2m_free(uriP);
00145                     return NULL;
00146                 }
00147             }
00148             uriPath = uriPath->next;
00149         }
00150         if (NULL == uriPath || uriPath->len == 0)
00151         {
00152             uriP->flag |= LWM2M_URI_FLAG_DELETE_ALL;
00153             return uriP;
00154         }
00155     }
00156 
00157     readNum = uri_getNumber(uriPath->data, uriPath->len);
00158     if (readNum < 0 || readNum > LWM2M_MAX_ID) goto error;
00159     uriP->objectId = (uint16_t)readNum;
00160     uriP->flag |= LWM2M_URI_FLAG_OBJECT_ID;
00161     uriPath = uriPath->next;
00162 
00163     if ((uriP->flag & LWM2M_URI_MASK_TYPE) == LWM2M_URI_FLAG_REGISTRATION)
00164     {
00165         if (uriPath != NULL) goto error;
00166         return uriP;
00167     }
00168     uriP->flag |= LWM2M_URI_FLAG_DM;
00169 
00170     if (uriPath == NULL) return uriP;
00171 
00172     // Read object instance
00173     if (uriPath->len != 0)
00174     {
00175         readNum = uri_getNumber(uriPath->data, uriPath->len);
00176         if (readNum < 0 || readNum >= LWM2M_MAX_ID) goto error;
00177         uriP->instanceId = (uint16_t)readNum;
00178         uriP->flag |= LWM2M_URI_FLAG_INSTANCE_ID;
00179     }
00180     uriPath = uriPath->next;
00181 
00182     if (uriPath == NULL) return uriP;
00183 
00184     // Read resource ID
00185     if (uriPath->len != 0)
00186     {
00187         // resource ID without an instance ID is not allowed
00188         if ((uriP->flag & LWM2M_URI_FLAG_INSTANCE_ID) == 0) goto error;
00189 
00190         readNum = uri_getNumber(uriPath->data, uriPath->len);
00191         if (readNum < 0 || readNum > LWM2M_MAX_ID) goto error;
00192         uriP->resourceId = (uint16_t)readNum;
00193         uriP->flag |= LWM2M_URI_FLAG_RESOURCE_ID;
00194     }
00195 
00196     // must be the last segment
00197     if (NULL == uriPath->next)
00198     {
00199         LOG_URI(uriP);
00200         return uriP;
00201     }
00202 
00203 error:
00204     LOG("Exiting on error");
00205     lwm2m_free(uriP);
00206     return NULL;
00207 }
00208 
00209 int lwm2m_stringToUri(const char * buffer,
00210                       size_t buffer_len,
00211                       lwm2m_uri_t * uriP)
00212 {
00213     size_t head;
00214     int readNum;
00215 
00216     LOG_ARG("buffer_len: %u, buffer: \"%.*s\"", buffer_len, buffer_len, buffer);
00217 
00218     if (buffer == NULL || buffer_len == 0 || uriP == NULL) return 0;
00219 
00220     memset(uriP, 0, sizeof(lwm2m_uri_t));
00221 
00222     // Skip any white space
00223     head = 0;
00224     while (head < buffer_len && isspace(buffer[head]&0xFF))
00225     {
00226         head++;
00227     }
00228     if (head == buffer_len) return 0;
00229 
00230     // Check the URI start with a '/'
00231     if (buffer[head] != '/') return 0;
00232     head++;
00233     if (head == buffer_len) return 0;
00234 
00235     // Read object ID
00236     readNum = prv_parseNumber((uint8_t *)buffer, buffer_len, &head);
00237     if (readNum < 0 || readNum > LWM2M_MAX_ID) return 0;
00238     uriP->objectId = (uint16_t)readNum;
00239     uriP->flag |= LWM2M_URI_FLAG_OBJECT_ID;
00240 
00241     if (buffer[head] == '/') head += 1;
00242     if (head >= buffer_len)
00243     {
00244         LOG_ARG("Parsed characters: %u", head);
00245         LOG_URI(uriP);
00246         return head;
00247     }
00248 
00249     readNum = prv_parseNumber((uint8_t *)buffer, buffer_len, &head);
00250     if (readNum < 0 || readNum >= LWM2M_MAX_ID) return 0;
00251     uriP->instanceId = (uint16_t)readNum;
00252     uriP->flag |= LWM2M_URI_FLAG_INSTANCE_ID;
00253 
00254     if (buffer[head] == '/') head += 1;
00255     if (head >= buffer_len)
00256     {
00257         LOG_ARG("Parsed characters: %u", head);
00258         LOG_URI(uriP);
00259         return head;
00260     }
00261 
00262     readNum = prv_parseNumber((uint8_t *)buffer, buffer_len, &head);
00263     if (readNum < 0 || readNum >= LWM2M_MAX_ID) return 0;
00264     uriP->resourceId = (uint16_t)readNum;
00265     uriP->flag |= LWM2M_URI_FLAG_RESOURCE_ID;
00266 
00267     if (head != buffer_len) return 0;
00268 
00269     LOG_ARG("Parsed characters: %u", head);
00270     LOG_URI(uriP);
00271 
00272     return head;
00273 }
00274 
00275 int uri_toString(lwm2m_uri_t * uriP,
00276                  uint8_t * buffer,
00277                  size_t bufferLen,
00278                  uri_depth_t * depthP)
00279 {
00280     size_t head;
00281     int res;
00282 
00283     LOG_ARG("bufferLen: %u", bufferLen);
00284     LOG_URI(uriP);
00285 
00286     buffer[0] = '/';
00287 
00288     if (uriP == NULL)
00289     {
00290         if (depthP) *depthP = URI_DEPTH_OBJECT;
00291         return 1;
00292     }
00293 
00294     head = 1;
00295 
00296     res = utils_intToText(uriP->objectId, buffer + head, bufferLen - head);
00297     if (res <= 0) return -1;
00298     head += res;
00299     if (head >= bufferLen - 1) return -1;
00300     if (depthP) *depthP = URI_DEPTH_OBJECT_INSTANCE;
00301 
00302     if (LWM2M_URI_IS_SET_INSTANCE(uriP))
00303     {
00304         buffer[head] = '/';
00305         head++;
00306         res = utils_intToText(uriP->instanceId, buffer + head, bufferLen - head);
00307         if (res <= 0) return -1;
00308         head += res;
00309         if (head >= bufferLen - 1) return -1;
00310         if (depthP) *depthP = URI_DEPTH_RESOURCE;
00311         if (LWM2M_URI_IS_SET_RESOURCE(uriP))
00312         {
00313             buffer[head] = '/';
00314             head++;
00315             res = utils_intToText(uriP->resourceId, buffer + head, bufferLen - head);
00316             if (res <= 0) return -1;
00317             head += res;
00318             if (head >= bufferLen - 1) return -1;
00319             if (depthP) *depthP = URI_DEPTH_RESOURCE_INSTANCE;
00320         }
00321     }
00322 
00323     buffer[head] = '/';
00324     head++;
00325 
00326     LOG_ARG("length: %u, buffer: \"%.*s\"", head, head, buffer);
00327 
00328     return head;
00329 }