JNP3 16/17

Dependencies:   mbed nRF24L01P

Committer:
Bartosz Stebel
Date:
Tue Jan 17 11:05:46 2017 +0100
Revision:
31:413ba83b8c0b
coap patches

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Bartosz Stebel 31:413ba83b8c0b 1 /*
Bartosz Stebel 31:413ba83b8c0b 2 Copyright (c) 2013, Ashley Mills.
Bartosz Stebel 31:413ba83b8c0b 3 All rights reserved.
Bartosz Stebel 31:413ba83b8c0b 4
Bartosz Stebel 31:413ba83b8c0b 5 Redistribution and use in source and binary forms, with or without
Bartosz Stebel 31:413ba83b8c0b 6 modification, are permitted provided that the following conditions are met:
Bartosz Stebel 31:413ba83b8c0b 7
Bartosz Stebel 31:413ba83b8c0b 8 1. Redistributions of source code must retain the above copyright notice, this
Bartosz Stebel 31:413ba83b8c0b 9 list of conditions and the following disclaimer.
Bartosz Stebel 31:413ba83b8c0b 10 2. Redistributions in binary form must reproduce the above copyright notice,
Bartosz Stebel 31:413ba83b8c0b 11 this list of conditions and the following disclaimer in the documentation
Bartosz Stebel 31:413ba83b8c0b 12 and/or other materials provided with the distribution.
Bartosz Stebel 31:413ba83b8c0b 13
Bartosz Stebel 31:413ba83b8c0b 14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
Bartosz Stebel 31:413ba83b8c0b 15 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
Bartosz Stebel 31:413ba83b8c0b 16 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
Bartosz Stebel 31:413ba83b8c0b 17 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
Bartosz Stebel 31:413ba83b8c0b 18 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
Bartosz Stebel 31:413ba83b8c0b 19 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
Bartosz Stebel 31:413ba83b8c0b 20 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
Bartosz Stebel 31:413ba83b8c0b 21 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Bartosz Stebel 31:413ba83b8c0b 22 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
Bartosz Stebel 31:413ba83b8c0b 23 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Bartosz Stebel 31:413ba83b8c0b 24 */
Bartosz Stebel 31:413ba83b8c0b 25
Bartosz Stebel 31:413ba83b8c0b 26 // version, 2 bits
Bartosz Stebel 31:413ba83b8c0b 27 // type, 2 bits
Bartosz Stebel 31:413ba83b8c0b 28 // 00 Confirmable
Bartosz Stebel 31:413ba83b8c0b 29 // 01 Non-confirmable
Bartosz Stebel 31:413ba83b8c0b 30 // 10 Acknowledgement
Bartosz Stebel 31:413ba83b8c0b 31 // 11 Reset
Bartosz Stebel 31:413ba83b8c0b 32
Bartosz Stebel 31:413ba83b8c0b 33 // token length, 4 bits
Bartosz Stebel 31:413ba83b8c0b 34 // length of token in bytes (only 0 to 8 bytes allowed)
Bartosz Stebel 31:413ba83b8c0b 35 #include <stdio.h>
Bartosz Stebel 31:413ba83b8c0b 36 #include <stdlib.h>
Bartosz Stebel 31:413ba83b8c0b 37 #include <stdint.h>
Bartosz Stebel 31:413ba83b8c0b 38 #include <string.h>
Bartosz Stebel 31:413ba83b8c0b 39 #include <inet.h>
Bartosz Stebel 31:413ba83b8c0b 40 #include "cantcoap.h"
Bartosz Stebel 31:413ba83b8c0b 41
Bartosz Stebel 31:413ba83b8c0b 42 // for debugging output you need https://mbed.org/users/donatien/code/DebugLib/
Bartosz Stebel 31:413ba83b8c0b 43 #define __DEBUG__ 3 // INFO
Bartosz Stebel 31:413ba83b8c0b 44 #ifndef __MODULE__
Bartosz Stebel 31:413ba83b8c0b 45 #define __MODULE__ "cantcoap.cpp"
Bartosz Stebel 31:413ba83b8c0b 46 #endif
Bartosz Stebel 31:413ba83b8c0b 47 //#include "dbg.h"
Bartosz Stebel 31:413ba83b8c0b 48 // some extra debug stuff
Bartosz Stebel 31:413ba83b8c0b 49 #if __DEBUG__ > 0
Bartosz Stebel 31:413ba83b8c0b 50 #define INFOX(...) do { fprintf(stderr,__VA_ARGS__); } while(0)
Bartosz Stebel 31:413ba83b8c0b 51 #define INFOLX(...) do { fprintf(stderr,"[INFO] %s:%d ",__MODULE__,__LINE__); fprintf(stderr,__VA_ARGS__); } while(0)
Bartosz Stebel 31:413ba83b8c0b 52 #define DBGLX(...) do { fprintf(stderr,"[DBG] %s:%d ",__MODULE__,__LINE__); fprintf(stderr,__VA_ARGS__); } while(0)
Bartosz Stebel 31:413ba83b8c0b 53 #define DBG_PDU() do { printBin(); } while(0)
Bartosz Stebel 31:413ba83b8c0b 54 #else
Bartosz Stebel 31:413ba83b8c0b 55 #define INFOX(...) do{} while(0)
Bartosz Stebel 31:413ba83b8c0b 56 #define INFOLX(...) do{} while(0)
Bartosz Stebel 31:413ba83b8c0b 57 #define DBGLX(...) do{} while(0)
Bartosz Stebel 31:413ba83b8c0b 58 #define DBG_PDU() do{} while(0)
Bartosz Stebel 31:413ba83b8c0b 59 #endif
Bartosz Stebel 31:413ba83b8c0b 60 #define INFO(...) do{} while(0)
Bartosz Stebel 31:413ba83b8c0b 61 #define DBGX(...) do{} while(0)
Bartosz Stebel 31:413ba83b8c0b 62 #define DBG(...) do{} while(0)
Bartosz Stebel 31:413ba83b8c0b 63
Bartosz Stebel 31:413ba83b8c0b 64
Bartosz Stebel 31:413ba83b8c0b 65 /// Memory-managed constructor. Buffer for PDU is dynamically sized and allocated by the object.
Bartosz Stebel 31:413ba83b8c0b 66 /**
Bartosz Stebel 31:413ba83b8c0b 67 * When using this constructor, the CoapPDU class will allocate space for the PDU.
Bartosz Stebel 31:413ba83b8c0b 68 * Contrast this with the parameterized constructors, which allow the use of an external buffer.
Bartosz Stebel 31:413ba83b8c0b 69 *
Bartosz Stebel 31:413ba83b8c0b 70 * Note, the PDU container and space can be reused by issuing a CoapPDU::reset(). If the new PDU exceeds the
Bartosz Stebel 31:413ba83b8c0b 71 * space of the previously allocated memory, then further memory will be dynamically allocated.
Bartosz Stebel 31:413ba83b8c0b 72 *
Bartosz Stebel 31:413ba83b8c0b 73 * Deleting the object will free the Object container and all dynamically allocated memory.
Bartosz Stebel 31:413ba83b8c0b 74 *
Bartosz Stebel 31:413ba83b8c0b 75 * \note It would have been nice to use something like UDP_CORK or MSG_MORE, to allow separate buffers
Bartosz Stebel 31:413ba83b8c0b 76 * for token, options, and payload but these FLAGS aren't implemented for UDP in LwIP so stuck with one buffer for now.
Bartosz Stebel 31:413ba83b8c0b 77 *
Bartosz Stebel 31:413ba83b8c0b 78 * CoAP version defaults to 1.
Bartosz Stebel 31:413ba83b8c0b 79 *
Bartosz Stebel 31:413ba83b8c0b 80 * \sa CoapPDU::CoapPDU(uint8_t *pdu, int pduLength), CoapPDU::CoapPDU::(uint8_t *buffer, int bufferLength, int pduLength),
Bartosz Stebel 31:413ba83b8c0b 81 * CoapPDU:CoapPDU()~
Bartosz Stebel 31:413ba83b8c0b 82 *
Bartosz Stebel 31:413ba83b8c0b 83 */
Bartosz Stebel 31:413ba83b8c0b 84 CoapPDU::CoapPDU() {
Bartosz Stebel 31:413ba83b8c0b 85 // pdu
Bartosz Stebel 31:413ba83b8c0b 86 _pdu = (uint8_t*)calloc(4,sizeof(uint8_t));
Bartosz Stebel 31:413ba83b8c0b 87 _pduLength = 4;
Bartosz Stebel 31:413ba83b8c0b 88 _bufferLength = _pduLength;
Bartosz Stebel 31:413ba83b8c0b 89
Bartosz Stebel 31:413ba83b8c0b 90 //options
Bartosz Stebel 31:413ba83b8c0b 91 _numOptions = 0;
Bartosz Stebel 31:413ba83b8c0b 92 _maxAddedOptionNumber = 0;
Bartosz Stebel 31:413ba83b8c0b 93
Bartosz Stebel 31:413ba83b8c0b 94 // payload
Bartosz Stebel 31:413ba83b8c0b 95 _payloadPointer = NULL;
Bartosz Stebel 31:413ba83b8c0b 96 _payloadLength = 0;
Bartosz Stebel 31:413ba83b8c0b 97
Bartosz Stebel 31:413ba83b8c0b 98 _constructedFromBuffer = 0;
Bartosz Stebel 31:413ba83b8c0b 99
Bartosz Stebel 31:413ba83b8c0b 100 setVersion(1);
Bartosz Stebel 31:413ba83b8c0b 101 }
Bartosz Stebel 31:413ba83b8c0b 102
Bartosz Stebel 31:413ba83b8c0b 103 /// Construct a PDU using an external buffer. No copy of the buffer is made.
Bartosz Stebel 31:413ba83b8c0b 104 /**
Bartosz Stebel 31:413ba83b8c0b 105 * This constructor is normally used where a PDU has been received over the network, and it's length is known.
Bartosz Stebel 31:413ba83b8c0b 106 * In this case the CoapPDU object is probably going to be used as a temporary container to access member values.
Bartosz Stebel 31:413ba83b8c0b 107 *
Bartosz Stebel 31:413ba83b8c0b 108 * It is assumed that \b pduLength is the length of the actual CoAP PDU, and consequently the buffer will also be this size,
Bartosz Stebel 31:413ba83b8c0b 109 * contrast this with CoapPDU::CoapPDU(uint8_t *buffer, int bufferLength, int pduLength) which allows the buffer to
Bartosz Stebel 31:413ba83b8c0b 110 * be larger than the PDU.
Bartosz Stebel 31:413ba83b8c0b 111 *
Bartosz Stebel 31:413ba83b8c0b 112 * A PDU constructed in this manner must be validated with CoapPDU::validate() before the member variables will be accessible.
Bartosz Stebel 31:413ba83b8c0b 113 *
Bartosz Stebel 31:413ba83b8c0b 114 * \warning The validation call parses the PDU structure to set some internal parameters. If you do
Bartosz Stebel 31:413ba83b8c0b 115 * not validate the PDU, then the behaviour of member access functions will be undefined.
Bartosz Stebel 31:413ba83b8c0b 116 *
Bartosz Stebel 31:413ba83b8c0b 117 * The buffer can be reused by issuing a CoapPDU::reset() but the class will not change the size of the buffer. If the
Bartosz Stebel 31:413ba83b8c0b 118 * newly constructed PDU exceeds the size of the buffer, the function called (for example CoapPDU::addOption) will fail.
Bartosz Stebel 31:413ba83b8c0b 119 *
Bartosz Stebel 31:413ba83b8c0b 120 * Deleting this object will only delete the Object container and will not delete the PDU buffer.
Bartosz Stebel 31:413ba83b8c0b 121 *
Bartosz Stebel 31:413ba83b8c0b 122 * @param pdu A pointer to an array of bytes which comprise the CoAP PDU
Bartosz Stebel 31:413ba83b8c0b 123 * @param pduLength The length of the CoAP PDU pointed to by \b pdu
Bartosz Stebel 31:413ba83b8c0b 124
Bartosz Stebel 31:413ba83b8c0b 125 * \sa CoapPDU::CoapPDU(), CoapPDU::CoapPDU(uint8_t *buffer, int bufferLength, int pduLength)
Bartosz Stebel 31:413ba83b8c0b 126 */
Bartosz Stebel 31:413ba83b8c0b 127 CoapPDU::CoapPDU(uint8_t *pdu, int pduLength) {
Bartosz Stebel 31:413ba83b8c0b 128 int bufferLength = pduLength;
Bartosz Stebel 31:413ba83b8c0b 129 // sanity
Bartosz Stebel 31:413ba83b8c0b 130 if(pduLength<4&&pduLength!=0) {
Bartosz Stebel 31:413ba83b8c0b 131 DBG("PDU cannot have a length less than 4");
Bartosz Stebel 31:413ba83b8c0b 132 }
Bartosz Stebel 31:413ba83b8c0b 133
Bartosz Stebel 31:413ba83b8c0b 134 // pdu
Bartosz Stebel 31:413ba83b8c0b 135 _pdu = pdu;
Bartosz Stebel 31:413ba83b8c0b 136 _bufferLength = bufferLength;
Bartosz Stebel 31:413ba83b8c0b 137 if(pduLength==0) {
Bartosz Stebel 31:413ba83b8c0b 138 // this is actually a fresh pdu, header always exists
Bartosz Stebel 31:413ba83b8c0b 139 _pduLength = 4;
Bartosz Stebel 31:413ba83b8c0b 140 // make sure header is zeroed
Bartosz Stebel 31:413ba83b8c0b 141 _pdu[0] = 0x00; _pdu[1] = 0x00; _pdu[2] = 0x00; _pdu[3] = 0x00;
Bartosz Stebel 31:413ba83b8c0b 142 setVersion(1);
Bartosz Stebel 31:413ba83b8c0b 143 } else {
Bartosz Stebel 31:413ba83b8c0b 144 _pduLength = pduLength;
Bartosz Stebel 31:413ba83b8c0b 145 }
Bartosz Stebel 31:413ba83b8c0b 146
Bartosz Stebel 31:413ba83b8c0b 147 _constructedFromBuffer = 1;
Bartosz Stebel 31:413ba83b8c0b 148
Bartosz Stebel 31:413ba83b8c0b 149 // options
Bartosz Stebel 31:413ba83b8c0b 150 _numOptions = 0;
Bartosz Stebel 31:413ba83b8c0b 151 _maxAddedOptionNumber = 0;
Bartosz Stebel 31:413ba83b8c0b 152
Bartosz Stebel 31:413ba83b8c0b 153 // payload
Bartosz Stebel 31:413ba83b8c0b 154 _payloadPointer = NULL;
Bartosz Stebel 31:413ba83b8c0b 155 _payloadLength = 0;
Bartosz Stebel 31:413ba83b8c0b 156 }
Bartosz Stebel 31:413ba83b8c0b 157
Bartosz Stebel 31:413ba83b8c0b 158 /// Construct object from external buffer that may be larger than actual PDU.
Bartosz Stebel 31:413ba83b8c0b 159 /**
Bartosz Stebel 31:413ba83b8c0b 160 * This differs from CoapPDU::CoapPDU(uint8_t *pdu, int pduLength) in that the buffer may be larger
Bartosz Stebel 31:413ba83b8c0b 161 * than the actual CoAP PDU contained int the buffer. This is typically used when a large buffer is reused
Bartosz Stebel 31:413ba83b8c0b 162 * multiple times. Note that \b pduLength can be 0.
Bartosz Stebel 31:413ba83b8c0b 163 *
Bartosz Stebel 31:413ba83b8c0b 164 * If an actual CoAP PDU is passed in the buffer, \b pduLength should match its length. CoapPDU::validate() must
Bartosz Stebel 31:413ba83b8c0b 165 * be called to initiate the object before member functions can be used.
Bartosz Stebel 31:413ba83b8c0b 166 *
Bartosz Stebel 31:413ba83b8c0b 167 * A PDU constructed in this manner must be validated with CoapPDU::validate() before the member variables will be accessible.
Bartosz Stebel 31:413ba83b8c0b 168 *
Bartosz Stebel 31:413ba83b8c0b 169 * \warning The validation call parses the PDU structure to set some internal parameters. If you do
Bartosz Stebel 31:413ba83b8c0b 170 * not validate the PDU, then the behaviour of member access functions will be undefined.
Bartosz Stebel 31:413ba83b8c0b 171 *
Bartosz Stebel 31:413ba83b8c0b 172 * The buffer can be reused by issuing a CoapPDU::reset() but the class will not change the size of the buffer. If the
Bartosz Stebel 31:413ba83b8c0b 173 * newly constructed PDU exceeds the size of the buffer, the function called (for example CoapPDU::addOption) will fail.
Bartosz Stebel 31:413ba83b8c0b 174 *
Bartosz Stebel 31:413ba83b8c0b 175 * Deleting this object will only delete the Object container and will not delete the PDU buffer.
Bartosz Stebel 31:413ba83b8c0b 176 *
Bartosz Stebel 31:413ba83b8c0b 177 * \param buffer A buffer which either contains a CoAP PDU or is intended to be used to construct one.
Bartosz Stebel 31:413ba83b8c0b 178 * \param bufferLength The length of the buffer
Bartosz Stebel 31:413ba83b8c0b 179 * \param pduLength If the buffer contains a CoAP PDU, this specifies the length of the PDU within the buffer.
Bartosz Stebel 31:413ba83b8c0b 180 *
Bartosz Stebel 31:413ba83b8c0b 181 * \sa CoapPDU::CoapPDU(), CoapPDU::CoapPDU(uint8_t *pdu, int pduLength)
Bartosz Stebel 31:413ba83b8c0b 182 */
Bartosz Stebel 31:413ba83b8c0b 183 CoapPDU::CoapPDU(uint8_t *buffer, int bufferLength, int pduLength) {
Bartosz Stebel 31:413ba83b8c0b 184 // sanity
Bartosz Stebel 31:413ba83b8c0b 185 if(pduLength<4&&pduLength!=0) {
Bartosz Stebel 31:413ba83b8c0b 186 DBG("PDU cannot have a length less than 4");
Bartosz Stebel 31:413ba83b8c0b 187 }
Bartosz Stebel 31:413ba83b8c0b 188
Bartosz Stebel 31:413ba83b8c0b 189 // pdu
Bartosz Stebel 31:413ba83b8c0b 190 _pdu = buffer;
Bartosz Stebel 31:413ba83b8c0b 191 _bufferLength = bufferLength;
Bartosz Stebel 31:413ba83b8c0b 192 if(pduLength==0) {
Bartosz Stebel 31:413ba83b8c0b 193 // this is actually a fresh pdu, header always exists
Bartosz Stebel 31:413ba83b8c0b 194 _pduLength = 4;
Bartosz Stebel 31:413ba83b8c0b 195 // make sure header is zeroed
Bartosz Stebel 31:413ba83b8c0b 196 _pdu[0] = 0x00; _pdu[1] = 0x00; _pdu[2] = 0x00; _pdu[3] = 0x00;
Bartosz Stebel 31:413ba83b8c0b 197 setVersion(1);
Bartosz Stebel 31:413ba83b8c0b 198 } else {
Bartosz Stebel 31:413ba83b8c0b 199 _pduLength = pduLength;
Bartosz Stebel 31:413ba83b8c0b 200 }
Bartosz Stebel 31:413ba83b8c0b 201
Bartosz Stebel 31:413ba83b8c0b 202 _constructedFromBuffer = 1;
Bartosz Stebel 31:413ba83b8c0b 203
Bartosz Stebel 31:413ba83b8c0b 204 // options
Bartosz Stebel 31:413ba83b8c0b 205 _numOptions = 0;
Bartosz Stebel 31:413ba83b8c0b 206 _maxAddedOptionNumber = 0;
Bartosz Stebel 31:413ba83b8c0b 207
Bartosz Stebel 31:413ba83b8c0b 208 // payload
Bartosz Stebel 31:413ba83b8c0b 209 _payloadPointer = NULL;
Bartosz Stebel 31:413ba83b8c0b 210 _payloadLength = 0;
Bartosz Stebel 31:413ba83b8c0b 211 }
Bartosz Stebel 31:413ba83b8c0b 212
Bartosz Stebel 31:413ba83b8c0b 213 /// Reset CoapPDU container so it can be reused to build a new PDU.
Bartosz Stebel 31:413ba83b8c0b 214 /**
Bartosz Stebel 31:413ba83b8c0b 215 * This resets the CoapPDU container, setting the pdu length, option count, etc back to zero. The
Bartosz Stebel 31:413ba83b8c0b 216 * PDU can then be populated as if it were newly constructed.
Bartosz Stebel 31:413ba83b8c0b 217 *
Bartosz Stebel 31:413ba83b8c0b 218 * Note that the space available will depend on how the CoapPDU was originally constructed:
Bartosz Stebel 31:413ba83b8c0b 219 * -# CoapPDU::CoapPDU()
Bartosz Stebel 31:413ba83b8c0b 220 *
Bartosz Stebel 31:413ba83b8c0b 221 * Available space initially be \b _pduLength. But further space will be allocated as needed on demand,
Bartosz Stebel 31:413ba83b8c0b 222 * limited only by the OS/environment.
Bartosz Stebel 31:413ba83b8c0b 223 *
Bartosz Stebel 31:413ba83b8c0b 224 * -# CoapPDU::CoapPDU(uint8_t *pdu, int pduLength)
Bartosz Stebel 31:413ba83b8c0b 225 *
Bartosz Stebel 31:413ba83b8c0b 226 * Space is limited by the variable \b pduLength. The PDU cannot exceed \b pduLength bytes.
Bartosz Stebel 31:413ba83b8c0b 227 *
Bartosz Stebel 31:413ba83b8c0b 228 * -# CoapPDU::CoapPDU(uint8_t *buffer, int bufferLength, int pduLength)
Bartosz Stebel 31:413ba83b8c0b 229 *
Bartosz Stebel 31:413ba83b8c0b 230 * Space is limited by the variable \b bufferLength. The PDU cannot exceed \b bufferLength bytes.
Bartosz Stebel 31:413ba83b8c0b 231 *
Bartosz Stebel 31:413ba83b8c0b 232 * \return 0 on success, 1 on failure.
Bartosz Stebel 31:413ba83b8c0b 233 */
Bartosz Stebel 31:413ba83b8c0b 234 int CoapPDU::reset() {
Bartosz Stebel 31:413ba83b8c0b 235 // pdu
Bartosz Stebel 31:413ba83b8c0b 236 memset(_pdu,0x00,_bufferLength);
Bartosz Stebel 31:413ba83b8c0b 237 // packet always has at least a header
Bartosz Stebel 31:413ba83b8c0b 238 _pduLength = 4;
Bartosz Stebel 31:413ba83b8c0b 239
Bartosz Stebel 31:413ba83b8c0b 240 // options
Bartosz Stebel 31:413ba83b8c0b 241 _numOptions = 0;
Bartosz Stebel 31:413ba83b8c0b 242 _maxAddedOptionNumber = 0;
Bartosz Stebel 31:413ba83b8c0b 243 // payload
Bartosz Stebel 31:413ba83b8c0b 244 _payloadPointer = NULL;
Bartosz Stebel 31:413ba83b8c0b 245 _payloadLength = 0;
Bartosz Stebel 31:413ba83b8c0b 246 return 0;
Bartosz Stebel 31:413ba83b8c0b 247 }
Bartosz Stebel 31:413ba83b8c0b 248
Bartosz Stebel 31:413ba83b8c0b 249 /// Validates a PDU constructed using an external buffer.
Bartosz Stebel 31:413ba83b8c0b 250 /**
Bartosz Stebel 31:413ba83b8c0b 251 * When a CoapPDU is constructed using an external buffer, the programmer must call this function to
Bartosz Stebel 31:413ba83b8c0b 252 * check that the received PDU is a valid CoAP PDU.
Bartosz Stebel 31:413ba83b8c0b 253 *
Bartosz Stebel 31:413ba83b8c0b 254 * \warning The validation call parses the PDU structure to set some internal parameters. If you do
Bartosz Stebel 31:413ba83b8c0b 255 * not validate the PDU, then the behaviour of member access functions will be undefined.
Bartosz Stebel 31:413ba83b8c0b 256 *
Bartosz Stebel 31:413ba83b8c0b 257 * \return 1 if the PDU validates correctly, 0 if not. XXX maybe add some error codes
Bartosz Stebel 31:413ba83b8c0b 258 */
Bartosz Stebel 31:413ba83b8c0b 259 int CoapPDU::validate() {
Bartosz Stebel 31:413ba83b8c0b 260 if(_pduLength<4) {
Bartosz Stebel 31:413ba83b8c0b 261 DBG("PDU has to be a minimum of 4 bytes. This: %d bytes",_pduLength);
Bartosz Stebel 31:413ba83b8c0b 262 return 0;
Bartosz Stebel 31:413ba83b8c0b 263 }
Bartosz Stebel 31:413ba83b8c0b 264
Bartosz Stebel 31:413ba83b8c0b 265 // check header
Bartosz Stebel 31:413ba83b8c0b 266 // 0 1 2 3
Bartosz Stebel 31:413ba83b8c0b 267 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
Bartosz Stebel 31:413ba83b8c0b 268 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Bartosz Stebel 31:413ba83b8c0b 269 // |Ver| T | TKL | Code | Message ID |
Bartosz Stebel 31:413ba83b8c0b 270 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Bartosz Stebel 31:413ba83b8c0b 271 // | Token (if any, TKL bytes) ...
Bartosz Stebel 31:413ba83b8c0b 272 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Bartosz Stebel 31:413ba83b8c0b 273 // | Options (if any) ...
Bartosz Stebel 31:413ba83b8c0b 274 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Bartosz Stebel 31:413ba83b8c0b 275 // |1 1 1 1 1 1 1 1| Payload (if any) ...
Bartosz Stebel 31:413ba83b8c0b 276 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Bartosz Stebel 31:413ba83b8c0b 277
Bartosz Stebel 31:413ba83b8c0b 278 DBG("Version: %d",getVersion());
Bartosz Stebel 31:413ba83b8c0b 279 DBG("Type: %d",getType());
Bartosz Stebel 31:413ba83b8c0b 280
Bartosz Stebel 31:413ba83b8c0b 281 // token length must be between 0 and 8
Bartosz Stebel 31:413ba83b8c0b 282 int tokenLength = getTokenLength();
Bartosz Stebel 31:413ba83b8c0b 283 if(tokenLength<0||tokenLength>8) {
Bartosz Stebel 31:413ba83b8c0b 284 DBG("Invalid token length: %d",tokenLength);
Bartosz Stebel 31:413ba83b8c0b 285 return 0;
Bartosz Stebel 31:413ba83b8c0b 286 }
Bartosz Stebel 31:413ba83b8c0b 287 DBG("Token length: %d",tokenLength);
Bartosz Stebel 31:413ba83b8c0b 288 // check total length
Bartosz Stebel 31:413ba83b8c0b 289 if((COAP_HDR_SIZE+tokenLength)>_pduLength) {
Bartosz Stebel 31:413ba83b8c0b 290 DBG("Token length would make pdu longer than actual length.");
Bartosz Stebel 31:413ba83b8c0b 291 return 0;
Bartosz Stebel 31:413ba83b8c0b 292 }
Bartosz Stebel 31:413ba83b8c0b 293
Bartosz Stebel 31:413ba83b8c0b 294 // check that code is valid
Bartosz Stebel 31:413ba83b8c0b 295 CoapPDU::Code code = getCode();
Bartosz Stebel 31:413ba83b8c0b 296 if(code<COAP_EMPTY ||
Bartosz Stebel 31:413ba83b8c0b 297 (code>COAP_DELETE&&code<COAP_CREATED) ||
Bartosz Stebel 31:413ba83b8c0b 298 (code>COAP_CONTENT&&code<COAP_BAD_REQUEST) ||
Bartosz Stebel 31:413ba83b8c0b 299 (code>COAP_NOT_ACCEPTABLE&&code<COAP_PRECONDITION_FAILED) ||
Bartosz Stebel 31:413ba83b8c0b 300 (code==0x8E) ||
Bartosz Stebel 31:413ba83b8c0b 301 (code>COAP_UNSUPPORTED_CONTENT_FORMAT&&code<COAP_INTERNAL_SERVER_ERROR) ||
Bartosz Stebel 31:413ba83b8c0b 302 (code>COAP_PROXYING_NOT_SUPPORTED) ) {
Bartosz Stebel 31:413ba83b8c0b 303 DBG("Invalid CoAP code: %d",code);
Bartosz Stebel 31:413ba83b8c0b 304 return 0;
Bartosz Stebel 31:413ba83b8c0b 305 }
Bartosz Stebel 31:413ba83b8c0b 306 DBG("CoAP code: %d",code);
Bartosz Stebel 31:413ba83b8c0b 307
Bartosz Stebel 31:413ba83b8c0b 308 // token can be anything so nothing to check
Bartosz Stebel 31:413ba83b8c0b 309
Bartosz Stebel 31:413ba83b8c0b 310 // check that options all make sense
Bartosz Stebel 31:413ba83b8c0b 311 uint16_t optionDelta =0, optionNumber = 0, optionValueLength = 0;
Bartosz Stebel 31:413ba83b8c0b 312 int totalLength = 0;
Bartosz Stebel 31:413ba83b8c0b 313
Bartosz Stebel 31:413ba83b8c0b 314 // first option occurs after token
Bartosz Stebel 31:413ba83b8c0b 315 int optionPos = COAP_HDR_SIZE + getTokenLength();
Bartosz Stebel 31:413ba83b8c0b 316
Bartosz Stebel 31:413ba83b8c0b 317 // may be 0 options
Bartosz Stebel 31:413ba83b8c0b 318 if(optionPos==_pduLength) {
Bartosz Stebel 31:413ba83b8c0b 319 DBG("No options. No payload.");
Bartosz Stebel 31:413ba83b8c0b 320 _numOptions = 0;
Bartosz Stebel 31:413ba83b8c0b 321 _payloadLength = 0;
Bartosz Stebel 31:413ba83b8c0b 322 return 1;
Bartosz Stebel 31:413ba83b8c0b 323 }
Bartosz Stebel 31:413ba83b8c0b 324
Bartosz Stebel 31:413ba83b8c0b 325 int bytesRemaining = _pduLength-optionPos;
Bartosz Stebel 31:413ba83b8c0b 326 int numOptions = 0;
Bartosz Stebel 31:413ba83b8c0b 327 uint8_t upperNibble = 0x00, lowerNibble = 0x00;
Bartosz Stebel 31:413ba83b8c0b 328
Bartosz Stebel 31:413ba83b8c0b 329 // walk over options and record information
Bartosz Stebel 31:413ba83b8c0b 330 while(1) {
Bartosz Stebel 31:413ba83b8c0b 331 // check for payload marker
Bartosz Stebel 31:413ba83b8c0b 332 if(bytesRemaining>0) {
Bartosz Stebel 31:413ba83b8c0b 333 uint8_t optionHeader = _pdu[optionPos];
Bartosz Stebel 31:413ba83b8c0b 334 if(optionHeader==0xFF) {
Bartosz Stebel 31:413ba83b8c0b 335 // payload
Bartosz Stebel 31:413ba83b8c0b 336 if(bytesRemaining>1) {
Bartosz Stebel 31:413ba83b8c0b 337 _payloadPointer = &_pdu[optionPos+1];
Bartosz Stebel 31:413ba83b8c0b 338 _payloadLength = (bytesRemaining-1);
Bartosz Stebel 31:413ba83b8c0b 339 _numOptions = numOptions;
Bartosz Stebel 31:413ba83b8c0b 340 DBG("Payload found, length: %d",_payloadLength);
Bartosz Stebel 31:413ba83b8c0b 341 return 1;
Bartosz Stebel 31:413ba83b8c0b 342 }
Bartosz Stebel 31:413ba83b8c0b 343 // payload marker but no payload
Bartosz Stebel 31:413ba83b8c0b 344 _payloadPointer = NULL;
Bartosz Stebel 31:413ba83b8c0b 345 _payloadLength = 0;
Bartosz Stebel 31:413ba83b8c0b 346 DBG("Payload marker but no payload.");
Bartosz Stebel 31:413ba83b8c0b 347 return 0;
Bartosz Stebel 31:413ba83b8c0b 348 }
Bartosz Stebel 31:413ba83b8c0b 349
Bartosz Stebel 31:413ba83b8c0b 350 // check that option delta and option length are valid values
Bartosz Stebel 31:413ba83b8c0b 351 upperNibble = (optionHeader & 0xF0) >> 4;
Bartosz Stebel 31:413ba83b8c0b 352 lowerNibble = (optionHeader & 0x0F);
Bartosz Stebel 31:413ba83b8c0b 353 if(upperNibble==0x0F||lowerNibble==0x0F) {
Bartosz Stebel 31:413ba83b8c0b 354 DBG("Expected option header or payload marker, got: 0x%x%x",upperNibble,lowerNibble);
Bartosz Stebel 31:413ba83b8c0b 355 return 0;
Bartosz Stebel 31:413ba83b8c0b 356 }
Bartosz Stebel 31:413ba83b8c0b 357 DBG("Option header byte appears sane: 0x%x%x",upperNibble,lowerNibble);
Bartosz Stebel 31:413ba83b8c0b 358 } else {
Bartosz Stebel 31:413ba83b8c0b 359 DBG("No more data. No payload.");
Bartosz Stebel 31:413ba83b8c0b 360 _payloadPointer = NULL;
Bartosz Stebel 31:413ba83b8c0b 361 _payloadLength = 0;
Bartosz Stebel 31:413ba83b8c0b 362 _numOptions = numOptions;
Bartosz Stebel 31:413ba83b8c0b 363 return 1;
Bartosz Stebel 31:413ba83b8c0b 364 }
Bartosz Stebel 31:413ba83b8c0b 365
Bartosz Stebel 31:413ba83b8c0b 366 // skip over option header byte
Bartosz Stebel 31:413ba83b8c0b 367 bytesRemaining--;
Bartosz Stebel 31:413ba83b8c0b 368
Bartosz Stebel 31:413ba83b8c0b 369 // check that there is enough space for the extended delta and length bytes (if any)
Bartosz Stebel 31:413ba83b8c0b 370 int headerBytesNeeded = computeExtraBytes(upperNibble);
Bartosz Stebel 31:413ba83b8c0b 371 DBG("%d extra bytes needed for extended delta",headerBytesNeeded);
Bartosz Stebel 31:413ba83b8c0b 372 if(headerBytesNeeded>bytesRemaining) {
Bartosz Stebel 31:413ba83b8c0b 373 DBG("Not enough space for extended option delta, needed %d, have %d.",headerBytesNeeded,bytesRemaining);
Bartosz Stebel 31:413ba83b8c0b 374 return 0;
Bartosz Stebel 31:413ba83b8c0b 375 }
Bartosz Stebel 31:413ba83b8c0b 376 headerBytesNeeded += computeExtraBytes(lowerNibble);
Bartosz Stebel 31:413ba83b8c0b 377 if(headerBytesNeeded>bytesRemaining) {
Bartosz Stebel 31:413ba83b8c0b 378 DBG("Not enough space for extended option length, needed %d, have %d.",
Bartosz Stebel 31:413ba83b8c0b 379 (headerBytesNeeded-computeExtraBytes(upperNibble)),bytesRemaining);
Bartosz Stebel 31:413ba83b8c0b 380 return 0;
Bartosz Stebel 31:413ba83b8c0b 381 }
Bartosz Stebel 31:413ba83b8c0b 382 DBG("Enough space for extended delta and length: %d, continuing.",headerBytesNeeded);
Bartosz Stebel 31:413ba83b8c0b 383
Bartosz Stebel 31:413ba83b8c0b 384 // extract option details
Bartosz Stebel 31:413ba83b8c0b 385 optionDelta = getOptionDelta(&_pdu[optionPos]);
Bartosz Stebel 31:413ba83b8c0b 386 optionNumber += optionDelta;
Bartosz Stebel 31:413ba83b8c0b 387 optionValueLength = getOptionValueLength(&_pdu[optionPos]);
Bartosz Stebel 31:413ba83b8c0b 388 DBG("Got option: %d with length %d",optionNumber,optionValueLength);
Bartosz Stebel 31:413ba83b8c0b 389 // compute total length
Bartosz Stebel 31:413ba83b8c0b 390 totalLength = 1; // mandatory header
Bartosz Stebel 31:413ba83b8c0b 391 totalLength += computeExtraBytes(optionDelta);
Bartosz Stebel 31:413ba83b8c0b 392 totalLength += computeExtraBytes(optionValueLength);
Bartosz Stebel 31:413ba83b8c0b 393 totalLength += optionValueLength;
Bartosz Stebel 31:413ba83b8c0b 394 // check there is enough space
Bartosz Stebel 31:413ba83b8c0b 395 if(optionPos+totalLength>_pduLength) {
Bartosz Stebel 31:413ba83b8c0b 396 DBG("Not enough space for option payload, needed %d, have %d.",(totalLength-headerBytesNeeded-1),_pduLength-optionPos);
Bartosz Stebel 31:413ba83b8c0b 397 return 0;
Bartosz Stebel 31:413ba83b8c0b 398 }
Bartosz Stebel 31:413ba83b8c0b 399 DBG("Enough space for option payload: %d %d",optionValueLength,(totalLength-headerBytesNeeded-1));
Bartosz Stebel 31:413ba83b8c0b 400
Bartosz Stebel 31:413ba83b8c0b 401 // recompute bytesRemaining
Bartosz Stebel 31:413ba83b8c0b 402 bytesRemaining -= totalLength;
Bartosz Stebel 31:413ba83b8c0b 403 bytesRemaining++; // correct for previous --
Bartosz Stebel 31:413ba83b8c0b 404
Bartosz Stebel 31:413ba83b8c0b 405 // move to next option
Bartosz Stebel 31:413ba83b8c0b 406 optionPos += totalLength;
Bartosz Stebel 31:413ba83b8c0b 407
Bartosz Stebel 31:413ba83b8c0b 408 // inc number of options XXX
Bartosz Stebel 31:413ba83b8c0b 409 numOptions++;
Bartosz Stebel 31:413ba83b8c0b 410 }
Bartosz Stebel 31:413ba83b8c0b 411
Bartosz Stebel 31:413ba83b8c0b 412 return 1;
Bartosz Stebel 31:413ba83b8c0b 413 }
Bartosz Stebel 31:413ba83b8c0b 414
Bartosz Stebel 31:413ba83b8c0b 415 /// Destructor. Does not free buffer if constructor passed an external buffer.
Bartosz Stebel 31:413ba83b8c0b 416 /**
Bartosz Stebel 31:413ba83b8c0b 417 * The destructor acts differently, depending on how the object was initially constructed (from buffer or not):
Bartosz Stebel 31:413ba83b8c0b 418 *
Bartosz Stebel 31:413ba83b8c0b 419 * -# CoapPDU::CoapPDU()
Bartosz Stebel 31:413ba83b8c0b 420 *
Bartosz Stebel 31:413ba83b8c0b 421 * Complete object is destroyed.
Bartosz Stebel 31:413ba83b8c0b 422 *
Bartosz Stebel 31:413ba83b8c0b 423 * -# CoapPDU::CoapPDU(uint8_t *pdu, int pduLength)
Bartosz Stebel 31:413ba83b8c0b 424 *
Bartosz Stebel 31:413ba83b8c0b 425 * Only object container is destroyed. \b pdu is left intact.
Bartosz Stebel 31:413ba83b8c0b 426 *
Bartosz Stebel 31:413ba83b8c0b 427 * -# CoapPDU::CoapPDU(uint8_t *buffer, int bufferLength, int pduLength)
Bartosz Stebel 31:413ba83b8c0b 428 *
Bartosz Stebel 31:413ba83b8c0b 429 * Only object container is destroyed. \b pdu is left intact.
Bartosz Stebel 31:413ba83b8c0b 430 *
Bartosz Stebel 31:413ba83b8c0b 431 */
Bartosz Stebel 31:413ba83b8c0b 432 CoapPDU::~CoapPDU() {
Bartosz Stebel 31:413ba83b8c0b 433 if(!_constructedFromBuffer) {
Bartosz Stebel 31:413ba83b8c0b 434 free(_pdu);
Bartosz Stebel 31:413ba83b8c0b 435 }
Bartosz Stebel 31:413ba83b8c0b 436 }
Bartosz Stebel 31:413ba83b8c0b 437
Bartosz Stebel 31:413ba83b8c0b 438 /// Returns a pointer to the internal buffer.
Bartosz Stebel 31:413ba83b8c0b 439 uint8_t* CoapPDU::getPDUPointer() {
Bartosz Stebel 31:413ba83b8c0b 440 return _pdu;
Bartosz Stebel 31:413ba83b8c0b 441 }
Bartosz Stebel 31:413ba83b8c0b 442
Bartosz Stebel 31:413ba83b8c0b 443 /// Set the PDU length to the length specified.
Bartosz Stebel 31:413ba83b8c0b 444 /**
Bartosz Stebel 31:413ba83b8c0b 445 * This is used when re-using a PDU container before calling CoapPDU::validate() as it
Bartosz Stebel 31:413ba83b8c0b 446 * is not possible to deduce the length of a PDU since the payload has no length marker.
Bartosz Stebel 31:413ba83b8c0b 447 * \param len The length of the PDU
Bartosz Stebel 31:413ba83b8c0b 448 */
Bartosz Stebel 31:413ba83b8c0b 449 void CoapPDU::setPDULength(int len) {
Bartosz Stebel 31:413ba83b8c0b 450 _pduLength = len;
Bartosz Stebel 31:413ba83b8c0b 451 }
Bartosz Stebel 31:413ba83b8c0b 452
Bartosz Stebel 31:413ba83b8c0b 453 /// Shorthand function for setting a resource URI.
Bartosz Stebel 31:413ba83b8c0b 454 /**
Bartosz Stebel 31:413ba83b8c0b 455 * Calls CoapPDU::setURI(uri,strlen(uri).
Bartosz Stebel 31:413ba83b8c0b 456 */
Bartosz Stebel 31:413ba83b8c0b 457 int CoapPDU::setURI(char *uri) {
Bartosz Stebel 31:413ba83b8c0b 458 return setURI(uri,strlen(uri));
Bartosz Stebel 31:413ba83b8c0b 459 }
Bartosz Stebel 31:413ba83b8c0b 460
Bartosz Stebel 31:413ba83b8c0b 461 /// Shorthand function for setting a resource URI.
Bartosz Stebel 31:413ba83b8c0b 462 /**
Bartosz Stebel 31:413ba83b8c0b 463 * This will parse the supplied \b uri and construct enough URI_PATH CoAP options to encode it.
Bartosz Stebel 31:413ba83b8c0b 464 * The options are added to the PDU.
Bartosz Stebel 31:413ba83b8c0b 465 *
Bartosz Stebel 31:413ba83b8c0b 466 * At present queries are not handled. TODO Implement queries.
Bartosz Stebel 31:413ba83b8c0b 467 *
Bartosz Stebel 31:413ba83b8c0b 468 * \note This uses an internal buffer of 16 bytes to manipulate strings. The internal buffer will be
Bartosz Stebel 31:413ba83b8c0b 469 * expanded dynamically if necessary (path component longer than 16 bytes). The internal buffer will
Bartosz Stebel 31:413ba83b8c0b 470 * be freed before the function returns.
Bartosz Stebel 31:413ba83b8c0b 471 *
Bartosz Stebel 31:413ba83b8c0b 472 * \param uri The uri to parse.
Bartosz Stebel 31:413ba83b8c0b 473 * \param urilen The length of the uri to parse.
Bartosz Stebel 31:413ba83b8c0b 474 *
Bartosz Stebel 31:413ba83b8c0b 475 * \return 1 on success, 0 on failure.
Bartosz Stebel 31:413ba83b8c0b 476 */
Bartosz Stebel 31:413ba83b8c0b 477 int CoapPDU::setURI(char *uri, int urilen) {
Bartosz Stebel 31:413ba83b8c0b 478 // only '/' and alphabetic chars allowed
Bartosz Stebel 31:413ba83b8c0b 479 // very simple splitting done
Bartosz Stebel 31:413ba83b8c0b 480
Bartosz Stebel 31:413ba83b8c0b 481 // sanitation
Bartosz Stebel 31:413ba83b8c0b 482 if(urilen<=0||uri==NULL) {
Bartosz Stebel 31:413ba83b8c0b 483 DBG("Null or zero-length uri passed.");
Bartosz Stebel 31:413ba83b8c0b 484 return 1;
Bartosz Stebel 31:413ba83b8c0b 485 }
Bartosz Stebel 31:413ba83b8c0b 486
Bartosz Stebel 31:413ba83b8c0b 487 // single character URI path (including '/' case)
Bartosz Stebel 31:413ba83b8c0b 488 if(urilen==1) {
Bartosz Stebel 31:413ba83b8c0b 489 addOption(COAP_OPTION_URI_PATH,1,(uint8_t*)uri);
Bartosz Stebel 31:413ba83b8c0b 490 return 0;
Bartosz Stebel 31:413ba83b8c0b 491 }
Bartosz Stebel 31:413ba83b8c0b 492
Bartosz Stebel 31:413ba83b8c0b 493 // local vars
Bartosz Stebel 31:413ba83b8c0b 494 char *startP=uri,*endP=NULL;
Bartosz Stebel 31:413ba83b8c0b 495 int oLen = 0;
Bartosz Stebel 31:413ba83b8c0b 496 int bufSpace = 16;
Bartosz Stebel 31:413ba83b8c0b 497 char *uriBuf = (char*)malloc(bufSpace*sizeof(char));
Bartosz Stebel 31:413ba83b8c0b 498 if(uriBuf==NULL) {
Bartosz Stebel 31:413ba83b8c0b 499 DBG("Error allocating temporary memory.");
Bartosz Stebel 31:413ba83b8c0b 500 return 1;
Bartosz Stebel 31:413ba83b8c0b 501 }
Bartosz Stebel 31:413ba83b8c0b 502
Bartosz Stebel 31:413ba83b8c0b 503 while(1) {
Bartosz Stebel 31:413ba83b8c0b 504 // stop at end of string
Bartosz Stebel 31:413ba83b8c0b 505 if(*startP==0x00||*(startP+1)==0x00) {
Bartosz Stebel 31:413ba83b8c0b 506 break;
Bartosz Stebel 31:413ba83b8c0b 507 }
Bartosz Stebel 31:413ba83b8c0b 508
Bartosz Stebel 31:413ba83b8c0b 509 // ignore leading slash
Bartosz Stebel 31:413ba83b8c0b 510 if(*startP=='/') {
Bartosz Stebel 31:413ba83b8c0b 511 DBG("Skipping leading slash");
Bartosz Stebel 31:413ba83b8c0b 512 startP++;
Bartosz Stebel 31:413ba83b8c0b 513 }
Bartosz Stebel 31:413ba83b8c0b 514
Bartosz Stebel 31:413ba83b8c0b 515 // find next split point
Bartosz Stebel 31:413ba83b8c0b 516 endP = strchr(startP,'/');
Bartosz Stebel 31:413ba83b8c0b 517
Bartosz Stebel 31:413ba83b8c0b 518 // might not be another slash
Bartosz Stebel 31:413ba83b8c0b 519 if(endP==NULL) {
Bartosz Stebel 31:413ba83b8c0b 520 DBG("Ending out of slash");
Bartosz Stebel 31:413ba83b8c0b 521 endP = uri+urilen;
Bartosz Stebel 31:413ba83b8c0b 522 }
Bartosz Stebel 31:413ba83b8c0b 523
Bartosz Stebel 31:413ba83b8c0b 524 // get length of segment
Bartosz Stebel 31:413ba83b8c0b 525 oLen = endP-startP;
Bartosz Stebel 31:413ba83b8c0b 526
Bartosz Stebel 31:413ba83b8c0b 527 // copy sequence, make space if necessary
Bartosz Stebel 31:413ba83b8c0b 528 if((oLen+1)>bufSpace) {
Bartosz Stebel 31:413ba83b8c0b 529 char *newBuf = (char*)realloc(uriBuf,oLen+1);
Bartosz Stebel 31:413ba83b8c0b 530 if(newBuf==NULL) {
Bartosz Stebel 31:413ba83b8c0b 531 DBG("Error making space for temporary buffer");
Bartosz Stebel 31:413ba83b8c0b 532 free(uriBuf);
Bartosz Stebel 31:413ba83b8c0b 533 return 1;
Bartosz Stebel 31:413ba83b8c0b 534 }
Bartosz Stebel 31:413ba83b8c0b 535 uriBuf = newBuf;
Bartosz Stebel 31:413ba83b8c0b 536 }
Bartosz Stebel 31:413ba83b8c0b 537
Bartosz Stebel 31:413ba83b8c0b 538 // copy into temporary buffer
Bartosz Stebel 31:413ba83b8c0b 539 memcpy(uriBuf,startP,oLen);
Bartosz Stebel 31:413ba83b8c0b 540 uriBuf[oLen] = 0x00;
Bartosz Stebel 31:413ba83b8c0b 541 DBG("Adding URI_PATH %s",uriBuf);
Bartosz Stebel 31:413ba83b8c0b 542 // add option
Bartosz Stebel 31:413ba83b8c0b 543 if(addOption(COAP_OPTION_URI_PATH,oLen,(uint8_t*)uriBuf)!=0) {
Bartosz Stebel 31:413ba83b8c0b 544 DBG("Error adding option");
Bartosz Stebel 31:413ba83b8c0b 545 return 1;
Bartosz Stebel 31:413ba83b8c0b 546 }
Bartosz Stebel 31:413ba83b8c0b 547 startP = endP;
Bartosz Stebel 31:413ba83b8c0b 548 }
Bartosz Stebel 31:413ba83b8c0b 549
Bartosz Stebel 31:413ba83b8c0b 550 // clean up
Bartosz Stebel 31:413ba83b8c0b 551 free(uriBuf);
Bartosz Stebel 31:413ba83b8c0b 552 return 0;
Bartosz Stebel 31:413ba83b8c0b 553 }
Bartosz Stebel 31:413ba83b8c0b 554 /// Shorthand for adding a URI QUERY to the option list.
Bartosz Stebel 31:413ba83b8c0b 555 /**
Bartosz Stebel 31:413ba83b8c0b 556 * Adds a new option to the CoAP PDU that encodes a URI_QUERY.
Bartosz Stebel 31:413ba83b8c0b 557 *
Bartosz Stebel 31:413ba83b8c0b 558 * \param query The uri query to encode.
Bartosz Stebel 31:413ba83b8c0b 559 * \return 0 on success, 1 on failure.
Bartosz Stebel 31:413ba83b8c0b 560 */
Bartosz Stebel 31:413ba83b8c0b 561 int CoapPDU::addURIQuery(char *query) {
Bartosz Stebel 31:413ba83b8c0b 562 return addOption(COAP_OPTION_URI_QUERY,strlen(query),(uint8_t*)query);
Bartosz Stebel 31:413ba83b8c0b 563 }
Bartosz Stebel 31:413ba83b8c0b 564
Bartosz Stebel 31:413ba83b8c0b 565 /// Concatenates any URI_PATH elements into a single string.
Bartosz Stebel 31:413ba83b8c0b 566 /**
Bartosz Stebel 31:413ba83b8c0b 567 * Parses the PDU options and extracts all URI_PATH elements, concatenating them into a single string with slash separators.
Bartosz Stebel 31:413ba83b8c0b 568 * The produced string will be null terminated.
Bartosz Stebel 31:413ba83b8c0b 569 *
Bartosz Stebel 31:413ba83b8c0b 570 * \param dst Buffer into which to copy the concatenated path elements.
Bartosz Stebel 31:413ba83b8c0b 571 * \param dstlen Length of buffer.
Bartosz Stebel 31:413ba83b8c0b 572 * \param outLen Pointer to integer, into which URI length will be placed.
Bartosz Stebel 31:413ba83b8c0b 573 *
Bartosz Stebel 31:413ba83b8c0b 574 * \return 0 on success, 1 on failure. \b outLen will contain the length of the concatenated elements.
Bartosz Stebel 31:413ba83b8c0b 575 */
Bartosz Stebel 31:413ba83b8c0b 576 int CoapPDU::getURI(char *dst, int dstlen, int *outLen) {
Bartosz Stebel 31:413ba83b8c0b 577 if(outLen==NULL) {
Bartosz Stebel 31:413ba83b8c0b 578 DBG("Output length pointer is NULL");
Bartosz Stebel 31:413ba83b8c0b 579 return 1;
Bartosz Stebel 31:413ba83b8c0b 580 }
Bartosz Stebel 31:413ba83b8c0b 581
Bartosz Stebel 31:413ba83b8c0b 582 if(dst==NULL) {
Bartosz Stebel 31:413ba83b8c0b 583 DBG("NULL destination buffer");
Bartosz Stebel 31:413ba83b8c0b 584 *outLen = 0;
Bartosz Stebel 31:413ba83b8c0b 585 return 1;
Bartosz Stebel 31:413ba83b8c0b 586 }
Bartosz Stebel 31:413ba83b8c0b 587
Bartosz Stebel 31:413ba83b8c0b 588 // check destination space
Bartosz Stebel 31:413ba83b8c0b 589 if(dstlen<=0) {
Bartosz Stebel 31:413ba83b8c0b 590 *dst = 0x00;
Bartosz Stebel 31:413ba83b8c0b 591 *outLen = 0;
Bartosz Stebel 31:413ba83b8c0b 592 DBG("Destination buffer too small (0)!");
Bartosz Stebel 31:413ba83b8c0b 593 return 1;
Bartosz Stebel 31:413ba83b8c0b 594 }
Bartosz Stebel 31:413ba83b8c0b 595 // check option count
Bartosz Stebel 31:413ba83b8c0b 596 if(_numOptions==0) {
Bartosz Stebel 31:413ba83b8c0b 597 *dst = 0x00;
Bartosz Stebel 31:413ba83b8c0b 598 *outLen = 0;
Bartosz Stebel 31:413ba83b8c0b 599 return 0;
Bartosz Stebel 31:413ba83b8c0b 600 }
Bartosz Stebel 31:413ba83b8c0b 601 // get options
Bartosz Stebel 31:413ba83b8c0b 602 CoapPDU::CoapOption *options = getOptions();
Bartosz Stebel 31:413ba83b8c0b 603 if(options==NULL) {
Bartosz Stebel 31:413ba83b8c0b 604 *dst = 0x00;
Bartosz Stebel 31:413ba83b8c0b 605 *outLen = 0;
Bartosz Stebel 31:413ba83b8c0b 606 return 0;
Bartosz Stebel 31:413ba83b8c0b 607 }
Bartosz Stebel 31:413ba83b8c0b 608 // iterate over options to construct URI
Bartosz Stebel 31:413ba83b8c0b 609 CoapOption *o = NULL;
Bartosz Stebel 31:413ba83b8c0b 610 int bytesLeft = dstlen-1; // space for 0x00
Bartosz Stebel 31:413ba83b8c0b 611 int oLen = 0;
Bartosz Stebel 31:413ba83b8c0b 612 // add slash at beggining
Bartosz Stebel 31:413ba83b8c0b 613 if(bytesLeft>=1) {
Bartosz Stebel 31:413ba83b8c0b 614 *dst = '/';
Bartosz Stebel 31:413ba83b8c0b 615 dst++;
Bartosz Stebel 31:413ba83b8c0b 616 bytesLeft--;
Bartosz Stebel 31:413ba83b8c0b 617 } else {
Bartosz Stebel 31:413ba83b8c0b 618 DBG("No space for initial slash needed 1, got %d",bytesLeft);
Bartosz Stebel 31:413ba83b8c0b 619 return 1;
Bartosz Stebel 31:413ba83b8c0b 620 }
Bartosz Stebel 31:413ba83b8c0b 621 for(int i=0; i<_numOptions; i++) {
Bartosz Stebel 31:413ba83b8c0b 622 o = &options[i];
Bartosz Stebel 31:413ba83b8c0b 623 oLen = o->optionValueLength;
Bartosz Stebel 31:413ba83b8c0b 624 if(o->optionNumber==COAP_OPTION_URI_PATH) {
Bartosz Stebel 31:413ba83b8c0b 625 // check space
Bartosz Stebel 31:413ba83b8c0b 626 if(oLen>bytesLeft) {
Bartosz Stebel 31:413ba83b8c0b 627 DBG("Destination buffer too small, needed %d, got %d",oLen,bytesLeft);
Bartosz Stebel 31:413ba83b8c0b 628 return 1;
Bartosz Stebel 31:413ba83b8c0b 629 }
Bartosz Stebel 31:413ba83b8c0b 630
Bartosz Stebel 31:413ba83b8c0b 631 // case where single '/' exists
Bartosz Stebel 31:413ba83b8c0b 632 if(oLen==1&&o->optionValuePointer[0]=='/') {
Bartosz Stebel 31:413ba83b8c0b 633 *dst = 0x00;
Bartosz Stebel 31:413ba83b8c0b 634 *outLen = 1;
Bartosz Stebel 31:413ba83b8c0b 635 return 0;
Bartosz Stebel 31:413ba83b8c0b 636 }
Bartosz Stebel 31:413ba83b8c0b 637
Bartosz Stebel 31:413ba83b8c0b 638 // copy URI path component
Bartosz Stebel 31:413ba83b8c0b 639 memcpy(dst,o->optionValuePointer,oLen);
Bartosz Stebel 31:413ba83b8c0b 640
Bartosz Stebel 31:413ba83b8c0b 641 // adjust counters
Bartosz Stebel 31:413ba83b8c0b 642 dst += oLen;
Bartosz Stebel 31:413ba83b8c0b 643 bytesLeft -= oLen;
Bartosz Stebel 31:413ba83b8c0b 644
Bartosz Stebel 31:413ba83b8c0b 645 // add slash following (don't know at this point if another option is coming)
Bartosz Stebel 31:413ba83b8c0b 646 if(bytesLeft>=1) {
Bartosz Stebel 31:413ba83b8c0b 647 *dst = '/';
Bartosz Stebel 31:413ba83b8c0b 648 dst++;
Bartosz Stebel 31:413ba83b8c0b 649 bytesLeft--;
Bartosz Stebel 31:413ba83b8c0b 650 } else {
Bartosz Stebel 31:413ba83b8c0b 651 DBG("Ran out of space after processing option");
Bartosz Stebel 31:413ba83b8c0b 652 return 1;
Bartosz Stebel 31:413ba83b8c0b 653 }
Bartosz Stebel 31:413ba83b8c0b 654 }
Bartosz Stebel 31:413ba83b8c0b 655 }
Bartosz Stebel 31:413ba83b8c0b 656
Bartosz Stebel 31:413ba83b8c0b 657 // remove terminating slash
Bartosz Stebel 31:413ba83b8c0b 658 dst--;
Bartosz Stebel 31:413ba83b8c0b 659 bytesLeft++;
Bartosz Stebel 31:413ba83b8c0b 660 // add null terminating byte (always space since reserved)
Bartosz Stebel 31:413ba83b8c0b 661 *dst = 0x00;
Bartosz Stebel 31:413ba83b8c0b 662 *outLen = (dstlen-1)-bytesLeft;
Bartosz Stebel 31:413ba83b8c0b 663 return 0;
Bartosz Stebel 31:413ba83b8c0b 664 }
Bartosz Stebel 31:413ba83b8c0b 665
Bartosz Stebel 31:413ba83b8c0b 666 /// Sets the CoAP version.
Bartosz Stebel 31:413ba83b8c0b 667 /**
Bartosz Stebel 31:413ba83b8c0b 668 * \param version CoAP version between 0 and 3.
Bartosz Stebel 31:413ba83b8c0b 669 * \return 0 on success, 1 on failure.
Bartosz Stebel 31:413ba83b8c0b 670 */
Bartosz Stebel 31:413ba83b8c0b 671 int CoapPDU::setVersion(uint8_t version) {
Bartosz Stebel 31:413ba83b8c0b 672 if(version>3) {
Bartosz Stebel 31:413ba83b8c0b 673 return 0;
Bartosz Stebel 31:413ba83b8c0b 674 }
Bartosz Stebel 31:413ba83b8c0b 675
Bartosz Stebel 31:413ba83b8c0b 676 _pdu[0] &= 0x3F;
Bartosz Stebel 31:413ba83b8c0b 677 _pdu[0] |= (version << 6);
Bartosz Stebel 31:413ba83b8c0b 678 return 1;
Bartosz Stebel 31:413ba83b8c0b 679 }
Bartosz Stebel 31:413ba83b8c0b 680
Bartosz Stebel 31:413ba83b8c0b 681 /**
Bartosz Stebel 31:413ba83b8c0b 682 * Gets the CoAP Version.
Bartosz Stebel 31:413ba83b8c0b 683 * @return The CoAP version between 0 and 3.
Bartosz Stebel 31:413ba83b8c0b 684 */
Bartosz Stebel 31:413ba83b8c0b 685 uint8_t CoapPDU::getVersion() {
Bartosz Stebel 31:413ba83b8c0b 686 return (_pdu[0]&0xC0)>>6;
Bartosz Stebel 31:413ba83b8c0b 687 }
Bartosz Stebel 31:413ba83b8c0b 688
Bartosz Stebel 31:413ba83b8c0b 689 /**
Bartosz Stebel 31:413ba83b8c0b 690 * Sets the type of this CoAP PDU.
Bartosz Stebel 31:413ba83b8c0b 691 * \param mt The type, one of:
Bartosz Stebel 31:413ba83b8c0b 692 * - COAP_CONFIRMABLE
Bartosz Stebel 31:413ba83b8c0b 693 * - COAP_NON_CONFIRMABLE
Bartosz Stebel 31:413ba83b8c0b 694 * - COAP_ACKNOWLEDGEMENT
Bartosz Stebel 31:413ba83b8c0b 695 * - COAP_RESET.
Bartosz Stebel 31:413ba83b8c0b 696 */
Bartosz Stebel 31:413ba83b8c0b 697 void CoapPDU::setType(CoapPDU::Type mt) {
Bartosz Stebel 31:413ba83b8c0b 698 _pdu[0] &= 0xCF;
Bartosz Stebel 31:413ba83b8c0b 699 _pdu[0] |= mt;
Bartosz Stebel 31:413ba83b8c0b 700 }
Bartosz Stebel 31:413ba83b8c0b 701
Bartosz Stebel 31:413ba83b8c0b 702 /// Returns the type of the PDU.
Bartosz Stebel 31:413ba83b8c0b 703 CoapPDU::Type CoapPDU::getType() {
Bartosz Stebel 31:413ba83b8c0b 704 return (CoapPDU::Type)(_pdu[0]&0x30);
Bartosz Stebel 31:413ba83b8c0b 705 }
Bartosz Stebel 31:413ba83b8c0b 706
Bartosz Stebel 31:413ba83b8c0b 707
Bartosz Stebel 31:413ba83b8c0b 708 /// Set the token length.
Bartosz Stebel 31:413ba83b8c0b 709 /**
Bartosz Stebel 31:413ba83b8c0b 710 * \param tokenLength The length of the token in bytes, between 0 and 8.
Bartosz Stebel 31:413ba83b8c0b 711 * \return 0 on success, 1 on failure.
Bartosz Stebel 31:413ba83b8c0b 712 */
Bartosz Stebel 31:413ba83b8c0b 713 int CoapPDU::setTokenLength(uint8_t tokenLength) {
Bartosz Stebel 31:413ba83b8c0b 714 if(tokenLength>8)
Bartosz Stebel 31:413ba83b8c0b 715 return 1;
Bartosz Stebel 31:413ba83b8c0b 716
Bartosz Stebel 31:413ba83b8c0b 717 _pdu[0] &= 0xF0;
Bartosz Stebel 31:413ba83b8c0b 718 _pdu[0] |= tokenLength;
Bartosz Stebel 31:413ba83b8c0b 719 return 0;
Bartosz Stebel 31:413ba83b8c0b 720 }
Bartosz Stebel 31:413ba83b8c0b 721
Bartosz Stebel 31:413ba83b8c0b 722 /// Returns the token length.
Bartosz Stebel 31:413ba83b8c0b 723 int CoapPDU::getTokenLength() {
Bartosz Stebel 31:413ba83b8c0b 724 return _pdu[0] & 0x0F;
Bartosz Stebel 31:413ba83b8c0b 725 }
Bartosz Stebel 31:413ba83b8c0b 726
Bartosz Stebel 31:413ba83b8c0b 727 /// Returns a pointer to the PDU token.
Bartosz Stebel 31:413ba83b8c0b 728 uint8_t* CoapPDU::getTokenPointer() {
Bartosz Stebel 31:413ba83b8c0b 729 if(getTokenLength()==0) {
Bartosz Stebel 31:413ba83b8c0b 730 return NULL;
Bartosz Stebel 31:413ba83b8c0b 731 }
Bartosz Stebel 31:413ba83b8c0b 732 return &_pdu[4];
Bartosz Stebel 31:413ba83b8c0b 733 }
Bartosz Stebel 31:413ba83b8c0b 734
Bartosz Stebel 31:413ba83b8c0b 735 /// Set the PDU token to the supplied byte sequence.
Bartosz Stebel 31:413ba83b8c0b 736 /**
Bartosz Stebel 31:413ba83b8c0b 737 * This sets the PDU token to \b token and sets the token length to \b tokenLength.
Bartosz Stebel 31:413ba83b8c0b 738 * \param token A sequence of bytes representing the token.
Bartosz Stebel 31:413ba83b8c0b 739 * \param tokenLength The length of the byte sequence.
Bartosz Stebel 31:413ba83b8c0b 740 * \return 0 on success, 1 on failure.
Bartosz Stebel 31:413ba83b8c0b 741 */
Bartosz Stebel 31:413ba83b8c0b 742 int CoapPDU::setToken(uint8_t *token, uint8_t tokenLength) {
Bartosz Stebel 31:413ba83b8c0b 743 DBG("Setting token");
Bartosz Stebel 31:413ba83b8c0b 744 if(token==NULL) {
Bartosz Stebel 31:413ba83b8c0b 745 DBG("NULL pointer passed as token reference");
Bartosz Stebel 31:413ba83b8c0b 746 return 1;
Bartosz Stebel 31:413ba83b8c0b 747 }
Bartosz Stebel 31:413ba83b8c0b 748
Bartosz Stebel 31:413ba83b8c0b 749 if(tokenLength==0) {
Bartosz Stebel 31:413ba83b8c0b 750 DBG("Token has zero length");
Bartosz Stebel 31:413ba83b8c0b 751 return 1;
Bartosz Stebel 31:413ba83b8c0b 752 }
Bartosz Stebel 31:413ba83b8c0b 753
Bartosz Stebel 31:413ba83b8c0b 754 // if tokenLength has not changed, just copy the new value
Bartosz Stebel 31:413ba83b8c0b 755 uint8_t oldTokenLength = getTokenLength();
Bartosz Stebel 31:413ba83b8c0b 756 if(tokenLength==oldTokenLength) {
Bartosz Stebel 31:413ba83b8c0b 757 memcpy((void*)&_pdu[4],token,tokenLength);
Bartosz Stebel 31:413ba83b8c0b 758 return 0;
Bartosz Stebel 31:413ba83b8c0b 759 }
Bartosz Stebel 31:413ba83b8c0b 760
Bartosz Stebel 31:413ba83b8c0b 761 // otherwise compute new length of PDU
Bartosz Stebel 31:413ba83b8c0b 762 uint8_t oldPDULength = _pduLength;
Bartosz Stebel 31:413ba83b8c0b 763 _pduLength -= oldTokenLength;
Bartosz Stebel 31:413ba83b8c0b 764 _pduLength += tokenLength;
Bartosz Stebel 31:413ba83b8c0b 765
Bartosz Stebel 31:413ba83b8c0b 766 // now, have to shift old memory around, but shift direction depends
Bartosz Stebel 31:413ba83b8c0b 767 // whether pdu is now bigger or smaller
Bartosz Stebel 31:413ba83b8c0b 768 if(_pduLength>oldPDULength) {
Bartosz Stebel 31:413ba83b8c0b 769 // new PDU is bigger, need to allocate space for new PDU
Bartosz Stebel 31:413ba83b8c0b 770 if(!_constructedFromBuffer) {
Bartosz Stebel 31:413ba83b8c0b 771 uint8_t *newMemory = (uint8_t*)realloc(_pdu,_pduLength);
Bartosz Stebel 31:413ba83b8c0b 772 if(newMemory==NULL) {
Bartosz Stebel 31:413ba83b8c0b 773 // malloc failed
Bartosz Stebel 31:413ba83b8c0b 774 DBG("Failed to allocate memory for token");
Bartosz Stebel 31:413ba83b8c0b 775 _pduLength = oldPDULength;
Bartosz Stebel 31:413ba83b8c0b 776 return 1;
Bartosz Stebel 31:413ba83b8c0b 777 }
Bartosz Stebel 31:413ba83b8c0b 778 _pdu = newMemory;
Bartosz Stebel 31:413ba83b8c0b 779 _bufferLength = _pduLength;
Bartosz Stebel 31:413ba83b8c0b 780 } else {
Bartosz Stebel 31:413ba83b8c0b 781 // constructed from buffer, check space
Bartosz Stebel 31:413ba83b8c0b 782 if(_pduLength>_bufferLength) {
Bartosz Stebel 31:413ba83b8c0b 783 DBG("Buffer too small to contain token, needed %d, got %d.",_pduLength-oldPDULength,_bufferLength-oldPDULength);
Bartosz Stebel 31:413ba83b8c0b 784 _pduLength = oldPDULength;
Bartosz Stebel 31:413ba83b8c0b 785 return 1;
Bartosz Stebel 31:413ba83b8c0b 786 }
Bartosz Stebel 31:413ba83b8c0b 787 }
Bartosz Stebel 31:413ba83b8c0b 788
Bartosz Stebel 31:413ba83b8c0b 789 // and then shift everything after token up to end of new PDU
Bartosz Stebel 31:413ba83b8c0b 790 // memory overlaps so do this manually so to avoid additional mallocs
Bartosz Stebel 31:413ba83b8c0b 791 int shiftOffset = _pduLength-oldPDULength;
Bartosz Stebel 31:413ba83b8c0b 792 int shiftAmount = _pduLength-tokenLength-COAP_HDR_SIZE; // everything after token
Bartosz Stebel 31:413ba83b8c0b 793 shiftPDUUp(shiftOffset,shiftAmount);
Bartosz Stebel 31:413ba83b8c0b 794
Bartosz Stebel 31:413ba83b8c0b 795 // now copy the token into the new space and set official token length
Bartosz Stebel 31:413ba83b8c0b 796 memcpy((void*)&_pdu[4],token,tokenLength);
Bartosz Stebel 31:413ba83b8c0b 797 setTokenLength(tokenLength);
Bartosz Stebel 31:413ba83b8c0b 798
Bartosz Stebel 31:413ba83b8c0b 799 // and return success
Bartosz Stebel 31:413ba83b8c0b 800 return 0;
Bartosz Stebel 31:413ba83b8c0b 801 }
Bartosz Stebel 31:413ba83b8c0b 802
Bartosz Stebel 31:413ba83b8c0b 803 // new PDU is smaller, copy the new token value over the old one
Bartosz Stebel 31:413ba83b8c0b 804 memcpy((void*)&_pdu[4],token,tokenLength);
Bartosz Stebel 31:413ba83b8c0b 805 // and shift everything after the new token down
Bartosz Stebel 31:413ba83b8c0b 806 int startLocation = COAP_HDR_SIZE+tokenLength;
Bartosz Stebel 31:413ba83b8c0b 807 int shiftOffset = oldPDULength-_pduLength;
Bartosz Stebel 31:413ba83b8c0b 808 int shiftAmount = oldPDULength-oldTokenLength-COAP_HDR_SIZE;
Bartosz Stebel 31:413ba83b8c0b 809 shiftPDUDown(startLocation,shiftOffset,shiftAmount);
Bartosz Stebel 31:413ba83b8c0b 810 // then reduce size of buffer
Bartosz Stebel 31:413ba83b8c0b 811 if(!_constructedFromBuffer) {
Bartosz Stebel 31:413ba83b8c0b 812 uint8_t *newMemory = (uint8_t*)realloc(_pdu,_pduLength);
Bartosz Stebel 31:413ba83b8c0b 813 if(newMemory==NULL) {
Bartosz Stebel 31:413ba83b8c0b 814 // malloc failed, PDU in inconsistent state
Bartosz Stebel 31:413ba83b8c0b 815 DBG("Failed to shrink PDU for new token. PDU probably broken");
Bartosz Stebel 31:413ba83b8c0b 816 return 1;
Bartosz Stebel 31:413ba83b8c0b 817 }
Bartosz Stebel 31:413ba83b8c0b 818 _pdu = newMemory;
Bartosz Stebel 31:413ba83b8c0b 819 _bufferLength = _pduLength;
Bartosz Stebel 31:413ba83b8c0b 820 }
Bartosz Stebel 31:413ba83b8c0b 821
Bartosz Stebel 31:413ba83b8c0b 822 // and officially set the new tokenLength
Bartosz Stebel 31:413ba83b8c0b 823 setTokenLength(tokenLength);
Bartosz Stebel 31:413ba83b8c0b 824 return 0;
Bartosz Stebel 31:413ba83b8c0b 825 }
Bartosz Stebel 31:413ba83b8c0b 826
Bartosz Stebel 31:413ba83b8c0b 827 /// Sets the CoAP response code
Bartosz Stebel 31:413ba83b8c0b 828 void CoapPDU::setCode(CoapPDU::Code code) {
Bartosz Stebel 31:413ba83b8c0b 829 _pdu[1] = code;
Bartosz Stebel 31:413ba83b8c0b 830 // there is a limited set of response codes
Bartosz Stebel 31:413ba83b8c0b 831 }
Bartosz Stebel 31:413ba83b8c0b 832
Bartosz Stebel 31:413ba83b8c0b 833 /// Gets the CoAP response code
Bartosz Stebel 31:413ba83b8c0b 834 CoapPDU::Code CoapPDU::getCode() {
Bartosz Stebel 31:413ba83b8c0b 835 return (CoapPDU::Code)_pdu[1];
Bartosz Stebel 31:413ba83b8c0b 836 }
Bartosz Stebel 31:413ba83b8c0b 837
Bartosz Stebel 31:413ba83b8c0b 838
Bartosz Stebel 31:413ba83b8c0b 839 /// Converts a http status code as an integer, to a CoAP code.
Bartosz Stebel 31:413ba83b8c0b 840 /**
Bartosz Stebel 31:413ba83b8c0b 841 * \param httpStatus the HTTP status code as an integer (e.g 200)
Bartosz Stebel 31:413ba83b8c0b 842 * \return The correct corresponding CoapPDU::Code on success,
Bartosz Stebel 31:413ba83b8c0b 843 * CoapPDU::COAP_UNDEFINED_CODE on failure.
Bartosz Stebel 31:413ba83b8c0b 844 */
Bartosz Stebel 31:413ba83b8c0b 845 CoapPDU::Code CoapPDU::httpStatusToCode(int httpStatus) {
Bartosz Stebel 31:413ba83b8c0b 846 switch(httpStatus) {
Bartosz Stebel 31:413ba83b8c0b 847 case 1:
Bartosz Stebel 31:413ba83b8c0b 848 return CoapPDU::COAP_GET;
Bartosz Stebel 31:413ba83b8c0b 849 case 2:
Bartosz Stebel 31:413ba83b8c0b 850 return CoapPDU::COAP_POST;
Bartosz Stebel 31:413ba83b8c0b 851 case 3:
Bartosz Stebel 31:413ba83b8c0b 852 return CoapPDU::COAP_PUT;
Bartosz Stebel 31:413ba83b8c0b 853 case 4:
Bartosz Stebel 31:413ba83b8c0b 854 return CoapPDU::COAP_DELETE;
Bartosz Stebel 31:413ba83b8c0b 855 case 201:
Bartosz Stebel 31:413ba83b8c0b 856 return CoapPDU::COAP_CREATED;
Bartosz Stebel 31:413ba83b8c0b 857 case 202:
Bartosz Stebel 31:413ba83b8c0b 858 return CoapPDU::COAP_DELETED;
Bartosz Stebel 31:413ba83b8c0b 859 case 203:
Bartosz Stebel 31:413ba83b8c0b 860 return CoapPDU::COAP_VALID;
Bartosz Stebel 31:413ba83b8c0b 861 case 204:
Bartosz Stebel 31:413ba83b8c0b 862 return CoapPDU::COAP_CHANGED;
Bartosz Stebel 31:413ba83b8c0b 863 case 205:
Bartosz Stebel 31:413ba83b8c0b 864 return CoapPDU::COAP_CONTENT;
Bartosz Stebel 31:413ba83b8c0b 865 case 400:
Bartosz Stebel 31:413ba83b8c0b 866 return CoapPDU::COAP_BAD_REQUEST;
Bartosz Stebel 31:413ba83b8c0b 867 case 401:
Bartosz Stebel 31:413ba83b8c0b 868 return CoapPDU::COAP_UNAUTHORIZED;
Bartosz Stebel 31:413ba83b8c0b 869 case 402:
Bartosz Stebel 31:413ba83b8c0b 870 return CoapPDU::COAP_BAD_OPTION;
Bartosz Stebel 31:413ba83b8c0b 871 case 403:
Bartosz Stebel 31:413ba83b8c0b 872 return CoapPDU::COAP_FORBIDDEN;
Bartosz Stebel 31:413ba83b8c0b 873 case 404:
Bartosz Stebel 31:413ba83b8c0b 874 return CoapPDU::COAP_NOT_FOUND;
Bartosz Stebel 31:413ba83b8c0b 875 case 405:
Bartosz Stebel 31:413ba83b8c0b 876 return CoapPDU::COAP_METHOD_NOT_ALLOWED;
Bartosz Stebel 31:413ba83b8c0b 877 case 406:
Bartosz Stebel 31:413ba83b8c0b 878 return CoapPDU::COAP_NOT_ACCEPTABLE;
Bartosz Stebel 31:413ba83b8c0b 879 case 412:
Bartosz Stebel 31:413ba83b8c0b 880 return CoapPDU::COAP_PRECONDITION_FAILED;
Bartosz Stebel 31:413ba83b8c0b 881 case 413:
Bartosz Stebel 31:413ba83b8c0b 882 return CoapPDU::COAP_REQUEST_ENTITY_TOO_LARGE;
Bartosz Stebel 31:413ba83b8c0b 883 case 415:
Bartosz Stebel 31:413ba83b8c0b 884 return CoapPDU::COAP_UNSUPPORTED_CONTENT_FORMAT;
Bartosz Stebel 31:413ba83b8c0b 885 case 500:
Bartosz Stebel 31:413ba83b8c0b 886 return CoapPDU::COAP_INTERNAL_SERVER_ERROR;
Bartosz Stebel 31:413ba83b8c0b 887 case 501:
Bartosz Stebel 31:413ba83b8c0b 888 return CoapPDU::COAP_NOT_IMPLEMENTED;
Bartosz Stebel 31:413ba83b8c0b 889 case 502:
Bartosz Stebel 31:413ba83b8c0b 890 return CoapPDU::COAP_BAD_GATEWAY;
Bartosz Stebel 31:413ba83b8c0b 891 case 503:
Bartosz Stebel 31:413ba83b8c0b 892 return CoapPDU::COAP_SERVICE_UNAVAILABLE;
Bartosz Stebel 31:413ba83b8c0b 893 case 504:
Bartosz Stebel 31:413ba83b8c0b 894 return CoapPDU::COAP_GATEWAY_TIMEOUT;
Bartosz Stebel 31:413ba83b8c0b 895 case 505:
Bartosz Stebel 31:413ba83b8c0b 896 return CoapPDU::COAP_PROXYING_NOT_SUPPORTED;
Bartosz Stebel 31:413ba83b8c0b 897 default:
Bartosz Stebel 31:413ba83b8c0b 898 return CoapPDU::COAP_UNDEFINED_CODE;
Bartosz Stebel 31:413ba83b8c0b 899 }
Bartosz Stebel 31:413ba83b8c0b 900 }
Bartosz Stebel 31:413ba83b8c0b 901
Bartosz Stebel 31:413ba83b8c0b 902 /// Set messageID to the supplied value.
Bartosz Stebel 31:413ba83b8c0b 903 /**
Bartosz Stebel 31:413ba83b8c0b 904 * \param messageID A 16bit message id.
Bartosz Stebel 31:413ba83b8c0b 905 * \return 0 on success, 1 on failure.
Bartosz Stebel 31:413ba83b8c0b 906 */
Bartosz Stebel 31:413ba83b8c0b 907 int CoapPDU::setMessageID(uint16_t messageID) {
Bartosz Stebel 31:413ba83b8c0b 908 // message ID is stored in network byte order
Bartosz Stebel 31:413ba83b8c0b 909 uint16_t networkOrder = htons(messageID);
Bartosz Stebel 31:413ba83b8c0b 910 // bytes 2 and 3 hold the ID
Bartosz Stebel 31:413ba83b8c0b 911 _pdu[2] &= 0x00;
Bartosz Stebel 31:413ba83b8c0b 912 _pdu[2] |= (networkOrder >> 8); // MSB
Bartosz Stebel 31:413ba83b8c0b 913 _pdu[3] &= 0x00;
Bartosz Stebel 31:413ba83b8c0b 914 _pdu[3] |= (networkOrder & 0x00FF); // LSB
Bartosz Stebel 31:413ba83b8c0b 915 return 0;
Bartosz Stebel 31:413ba83b8c0b 916 }
Bartosz Stebel 31:413ba83b8c0b 917
Bartosz Stebel 31:413ba83b8c0b 918 /// Returns the 16 bit message ID of the PDU.
Bartosz Stebel 31:413ba83b8c0b 919 uint16_t CoapPDU::getMessageID() {
Bartosz Stebel 31:413ba83b8c0b 920 // mesasge ID is stored in network byteorder
Bartosz Stebel 31:413ba83b8c0b 921 uint16_t networkOrder = 0x0000;
Bartosz Stebel 31:413ba83b8c0b 922 networkOrder |= _pdu[2];
Bartosz Stebel 31:413ba83b8c0b 923 networkOrder <<= 8;
Bartosz Stebel 31:413ba83b8c0b 924 networkOrder |= _pdu[3];
Bartosz Stebel 31:413ba83b8c0b 925 return ntohs(networkOrder);
Bartosz Stebel 31:413ba83b8c0b 926 }
Bartosz Stebel 31:413ba83b8c0b 927
Bartosz Stebel 31:413ba83b8c0b 928 /// Returns the length of the PDU.
Bartosz Stebel 31:413ba83b8c0b 929 int CoapPDU::getPDULength() {
Bartosz Stebel 31:413ba83b8c0b 930 return _pduLength;
Bartosz Stebel 31:413ba83b8c0b 931 }
Bartosz Stebel 31:413ba83b8c0b 932
Bartosz Stebel 31:413ba83b8c0b 933 /// Return the number of options that the PDU has.
Bartosz Stebel 31:413ba83b8c0b 934 int CoapPDU::getNumOptions() {
Bartosz Stebel 31:413ba83b8c0b 935 return _numOptions;
Bartosz Stebel 31:413ba83b8c0b 936 }
Bartosz Stebel 31:413ba83b8c0b 937
Bartosz Stebel 31:413ba83b8c0b 938
Bartosz Stebel 31:413ba83b8c0b 939 /**
Bartosz Stebel 31:413ba83b8c0b 940 * This returns the options as a sequence of structs.
Bartosz Stebel 31:413ba83b8c0b 941 */
Bartosz Stebel 31:413ba83b8c0b 942 CoapPDU::CoapOption* CoapPDU::getOptions() {
Bartosz Stebel 31:413ba83b8c0b 943 DBG("getOptions() called, %d options.",_numOptions);
Bartosz Stebel 31:413ba83b8c0b 944
Bartosz Stebel 31:413ba83b8c0b 945 uint16_t optionDelta =0, optionNumber = 0, optionValueLength = 0;
Bartosz Stebel 31:413ba83b8c0b 946 int totalLength = 0;
Bartosz Stebel 31:413ba83b8c0b 947
Bartosz Stebel 31:413ba83b8c0b 948 if(_numOptions==0) {
Bartosz Stebel 31:413ba83b8c0b 949 return NULL;
Bartosz Stebel 31:413ba83b8c0b 950 }
Bartosz Stebel 31:413ba83b8c0b 951
Bartosz Stebel 31:413ba83b8c0b 952 // malloc space for options
Bartosz Stebel 31:413ba83b8c0b 953 CoapOption *options = (CoapOption*)malloc(_numOptions*sizeof(CoapOption));
Bartosz Stebel 31:413ba83b8c0b 954
Bartosz Stebel 31:413ba83b8c0b 955 // first option occurs after token
Bartosz Stebel 31:413ba83b8c0b 956 int optionPos = COAP_HDR_SIZE + getTokenLength();
Bartosz Stebel 31:413ba83b8c0b 957
Bartosz Stebel 31:413ba83b8c0b 958 // walk over options and record information
Bartosz Stebel 31:413ba83b8c0b 959 for(int i=0; i<_numOptions; i++) {
Bartosz Stebel 31:413ba83b8c0b 960 // extract option details
Bartosz Stebel 31:413ba83b8c0b 961 optionDelta = getOptionDelta(&_pdu[optionPos]);
Bartosz Stebel 31:413ba83b8c0b 962 optionNumber += optionDelta;
Bartosz Stebel 31:413ba83b8c0b 963 optionValueLength = getOptionValueLength(&_pdu[optionPos]);
Bartosz Stebel 31:413ba83b8c0b 964 // compute total length
Bartosz Stebel 31:413ba83b8c0b 965 totalLength = 1; // mandatory header
Bartosz Stebel 31:413ba83b8c0b 966 totalLength += computeExtraBytes(optionDelta);
Bartosz Stebel 31:413ba83b8c0b 967 totalLength += computeExtraBytes(optionValueLength);
Bartosz Stebel 31:413ba83b8c0b 968 totalLength += optionValueLength;
Bartosz Stebel 31:413ba83b8c0b 969 // record option details
Bartosz Stebel 31:413ba83b8c0b 970 options[i].optionNumber = optionNumber;
Bartosz Stebel 31:413ba83b8c0b 971 options[i].optionDelta = optionDelta;
Bartosz Stebel 31:413ba83b8c0b 972 options[i].optionValueLength = optionValueLength;
Bartosz Stebel 31:413ba83b8c0b 973 options[i].totalLength = totalLength;
Bartosz Stebel 31:413ba83b8c0b 974 options[i].optionPointer = &_pdu[optionPos];
Bartosz Stebel 31:413ba83b8c0b 975 options[i].optionValuePointer = &_pdu[optionPos+totalLength-optionValueLength];
Bartosz Stebel 31:413ba83b8c0b 976 // move to next option
Bartosz Stebel 31:413ba83b8c0b 977 optionPos += totalLength;
Bartosz Stebel 31:413ba83b8c0b 978 }
Bartosz Stebel 31:413ba83b8c0b 979
Bartosz Stebel 31:413ba83b8c0b 980 return options;
Bartosz Stebel 31:413ba83b8c0b 981 }
Bartosz Stebel 31:413ba83b8c0b 982
Bartosz Stebel 31:413ba83b8c0b 983 /// Add an option to the PDU.
Bartosz Stebel 31:413ba83b8c0b 984 /**
Bartosz Stebel 31:413ba83b8c0b 985 * Unlike other implementations, options can be added in any order, and in-memory manipulation will be
Bartosz Stebel 31:413ba83b8c0b 986 * performed to ensure the correct ordering of options (they use a delta encoding of option numbers).
Bartosz Stebel 31:413ba83b8c0b 987 * Re-ordering memory like this incurs a small performance cost, so if you care about this, then you
Bartosz Stebel 31:413ba83b8c0b 988 * might want to add options in ascending order of option number.
Bartosz Stebel 31:413ba83b8c0b 989 * \param optionNumber The number of the option, see the enum CoapPDU::Option for shorthand notations.
Bartosz Stebel 31:413ba83b8c0b 990 * \param optionLength The length of the option payload in bytes.
Bartosz Stebel 31:413ba83b8c0b 991 * \param optionValue A pointer to the byte sequence that is the option payload (bytes will be copied).
Bartosz Stebel 31:413ba83b8c0b 992 * \return 0 on success, 1 on failure.
Bartosz Stebel 31:413ba83b8c0b 993 */
Bartosz Stebel 31:413ba83b8c0b 994 int CoapPDU::addOption(uint16_t insertedOptionNumber, uint16_t optionValueLength, uint8_t *optionValue) {
Bartosz Stebel 31:413ba83b8c0b 995 // this inserts the option in memory, and re-computes the deltas accordingly
Bartosz Stebel 31:413ba83b8c0b 996 // prevOption <-- insertionPosition
Bartosz Stebel 31:413ba83b8c0b 997 // nextOption
Bartosz Stebel 31:413ba83b8c0b 998
Bartosz Stebel 31:413ba83b8c0b 999 // find insertion location and previous option number
Bartosz Stebel 31:413ba83b8c0b 1000 uint16_t prevOptionNumber = 0; // option number of option before insertion point
Bartosz Stebel 31:413ba83b8c0b 1001 int insertionPosition = findInsertionPosition(insertedOptionNumber,&prevOptionNumber);
Bartosz Stebel 31:413ba83b8c0b 1002 DBG("inserting option at position %d, after option with number: %hu",insertionPosition,prevOptionNumber);
Bartosz Stebel 31:413ba83b8c0b 1003
Bartosz Stebel 31:413ba83b8c0b 1004 // compute option delta length
Bartosz Stebel 31:413ba83b8c0b 1005 uint16_t optionDelta = insertedOptionNumber-prevOptionNumber;
Bartosz Stebel 31:413ba83b8c0b 1006 uint8_t extraDeltaBytes = computeExtraBytes(optionDelta);
Bartosz Stebel 31:413ba83b8c0b 1007
Bartosz Stebel 31:413ba83b8c0b 1008 // compute option length length
Bartosz Stebel 31:413ba83b8c0b 1009 uint16_t extraLengthBytes = computeExtraBytes(optionValueLength);
Bartosz Stebel 31:413ba83b8c0b 1010
Bartosz Stebel 31:413ba83b8c0b 1011 // compute total length of option
Bartosz Stebel 31:413ba83b8c0b 1012 uint16_t optionLength = COAP_OPTION_HDR_BYTE + extraDeltaBytes + extraLengthBytes + optionValueLength;
Bartosz Stebel 31:413ba83b8c0b 1013
Bartosz Stebel 31:413ba83b8c0b 1014 // if this is at the end of the PDU, job is done, just malloc and insert
Bartosz Stebel 31:413ba83b8c0b 1015 if(insertionPosition==_pduLength) {
Bartosz Stebel 31:413ba83b8c0b 1016 DBG("Inserting at end of PDU");
Bartosz Stebel 31:413ba83b8c0b 1017 // optionNumber must be biggest added
Bartosz Stebel 31:413ba83b8c0b 1018 _maxAddedOptionNumber = insertedOptionNumber;
Bartosz Stebel 31:413ba83b8c0b 1019
Bartosz Stebel 31:413ba83b8c0b 1020 // set new PDU length and allocate space for extra option
Bartosz Stebel 31:413ba83b8c0b 1021 int oldPDULength = _pduLength;
Bartosz Stebel 31:413ba83b8c0b 1022 _pduLength += optionLength;
Bartosz Stebel 31:413ba83b8c0b 1023 if(!_constructedFromBuffer) {
Bartosz Stebel 31:413ba83b8c0b 1024 uint8_t *newMemory = (uint8_t*)realloc(_pdu,_pduLength);
Bartosz Stebel 31:413ba83b8c0b 1025 if(newMemory==NULL) {
Bartosz Stebel 31:413ba83b8c0b 1026 DBG("Failed to allocate memory for option.");
Bartosz Stebel 31:413ba83b8c0b 1027 _pduLength = oldPDULength;
Bartosz Stebel 31:413ba83b8c0b 1028 // malloc failed
Bartosz Stebel 31:413ba83b8c0b 1029 return 1;
Bartosz Stebel 31:413ba83b8c0b 1030 }
Bartosz Stebel 31:413ba83b8c0b 1031 _pdu = newMemory;
Bartosz Stebel 31:413ba83b8c0b 1032 _bufferLength = _pduLength;
Bartosz Stebel 31:413ba83b8c0b 1033 } else {
Bartosz Stebel 31:413ba83b8c0b 1034 // constructed from buffer, check space
Bartosz Stebel 31:413ba83b8c0b 1035 if(_pduLength>_bufferLength) {
Bartosz Stebel 31:413ba83b8c0b 1036 DBG("Buffer too small for new option: needed %d, got %d.",_pduLength-oldPDULength,_bufferLength-oldPDULength);
Bartosz Stebel 31:413ba83b8c0b 1037 _pduLength = oldPDULength;
Bartosz Stebel 31:413ba83b8c0b 1038 return 1;
Bartosz Stebel 31:413ba83b8c0b 1039 }
Bartosz Stebel 31:413ba83b8c0b 1040 }
Bartosz Stebel 31:413ba83b8c0b 1041
Bartosz Stebel 31:413ba83b8c0b 1042 // insert option at position
Bartosz Stebel 31:413ba83b8c0b 1043 insertOption(insertionPosition,optionDelta,optionValueLength,optionValue);
Bartosz Stebel 31:413ba83b8c0b 1044 _numOptions++;
Bartosz Stebel 31:413ba83b8c0b 1045 return 0;
Bartosz Stebel 31:413ba83b8c0b 1046 }
Bartosz Stebel 31:413ba83b8c0b 1047 // XXX could do 0xFF pdu payload case for changing of dynamically allocated application space SDUs < yeah, if you're insane
Bartosz Stebel 31:413ba83b8c0b 1048
Bartosz Stebel 31:413ba83b8c0b 1049 // the next option might (probably) needs it's delta changing
Bartosz Stebel 31:413ba83b8c0b 1050 // I want to take this into account when allocating space for the new
Bartosz Stebel 31:413ba83b8c0b 1051 // option, to avoid having to do two mallocs, first get info about this option
Bartosz Stebel 31:413ba83b8c0b 1052 int nextOptionDelta = getOptionDelta(&_pdu[insertionPosition]);
Bartosz Stebel 31:413ba83b8c0b 1053 int nextOptionNumber = prevOptionNumber + nextOptionDelta;
Bartosz Stebel 31:413ba83b8c0b 1054 int nextOptionDeltaBytes = computeExtraBytes(nextOptionDelta);
Bartosz Stebel 31:413ba83b8c0b 1055 // recompute option delta, relative to inserted option
Bartosz Stebel 31:413ba83b8c0b 1056 int newNextOptionDelta = nextOptionNumber-insertedOptionNumber;
Bartosz Stebel 31:413ba83b8c0b 1057 int newNextOptionDeltaBytes = computeExtraBytes(newNextOptionDelta);
Bartosz Stebel 31:413ba83b8c0b 1058 // determine adjustment
Bartosz Stebel 31:413ba83b8c0b 1059 int optionDeltaAdjustment = newNextOptionDeltaBytes-nextOptionDeltaBytes;
Bartosz Stebel 31:413ba83b8c0b 1060
Bartosz Stebel 31:413ba83b8c0b 1061 // create space for new option, including adjustment space for option delta
Bartosz Stebel 31:413ba83b8c0b 1062 DBG_PDU();
Bartosz Stebel 31:413ba83b8c0b 1063 DBG("Creating space");
Bartosz Stebel 31:413ba83b8c0b 1064 int mallocLength = optionLength+optionDeltaAdjustment;
Bartosz Stebel 31:413ba83b8c0b 1065 int oldPDULength = _pduLength;
Bartosz Stebel 31:413ba83b8c0b 1066 _pduLength += mallocLength;
Bartosz Stebel 31:413ba83b8c0b 1067
Bartosz Stebel 31:413ba83b8c0b 1068 if(!_constructedFromBuffer) {
Bartosz Stebel 31:413ba83b8c0b 1069 uint8_t *newMemory = (uint8_t*)realloc(_pdu,_pduLength);
Bartosz Stebel 31:413ba83b8c0b 1070 if(newMemory==NULL) {
Bartosz Stebel 31:413ba83b8c0b 1071 DBG("Failed to allocate memory for option");
Bartosz Stebel 31:413ba83b8c0b 1072 _pduLength = oldPDULength;
Bartosz Stebel 31:413ba83b8c0b 1073 return 1;
Bartosz Stebel 31:413ba83b8c0b 1074 }
Bartosz Stebel 31:413ba83b8c0b 1075 _pdu = newMemory;
Bartosz Stebel 31:413ba83b8c0b 1076 _bufferLength = _pduLength;
Bartosz Stebel 31:413ba83b8c0b 1077 } else {
Bartosz Stebel 31:413ba83b8c0b 1078 // constructed from buffer, check space
Bartosz Stebel 31:413ba83b8c0b 1079 if(_pduLength>_bufferLength) {
Bartosz Stebel 31:413ba83b8c0b 1080 DBG("Buffer too small to contain option, needed %d, got %d.",_pduLength-oldPDULength,_bufferLength-oldPDULength);
Bartosz Stebel 31:413ba83b8c0b 1081 _pduLength = oldPDULength;
Bartosz Stebel 31:413ba83b8c0b 1082 return 1;
Bartosz Stebel 31:413ba83b8c0b 1083 }
Bartosz Stebel 31:413ba83b8c0b 1084 }
Bartosz Stebel 31:413ba83b8c0b 1085
Bartosz Stebel 31:413ba83b8c0b 1086 // move remainder of PDU data up to create hole for new option
Bartosz Stebel 31:413ba83b8c0b 1087 DBG_PDU();
Bartosz Stebel 31:413ba83b8c0b 1088 DBG("Shifting PDU.");
Bartosz Stebel 31:413ba83b8c0b 1089 shiftPDUUp(mallocLength,_pduLength-(insertionPosition+mallocLength));
Bartosz Stebel 31:413ba83b8c0b 1090 DBG_PDU();
Bartosz Stebel 31:413ba83b8c0b 1091
Bartosz Stebel 31:413ba83b8c0b 1092 // adjust option delta bytes of following option
Bartosz Stebel 31:413ba83b8c0b 1093 // move the option header to the correct position
Bartosz Stebel 31:413ba83b8c0b 1094 int nextHeaderPos = insertionPosition+mallocLength;
Bartosz Stebel 31:413ba83b8c0b 1095 _pdu[nextHeaderPos-optionDeltaAdjustment] = _pdu[nextHeaderPos];
Bartosz Stebel 31:413ba83b8c0b 1096 nextHeaderPos -= optionDeltaAdjustment;
Bartosz Stebel 31:413ba83b8c0b 1097 // and set the new value
Bartosz Stebel 31:413ba83b8c0b 1098 setOptionDelta(nextHeaderPos, newNextOptionDelta);
Bartosz Stebel 31:413ba83b8c0b 1099
Bartosz Stebel 31:413ba83b8c0b 1100 // new option shorter
Bartosz Stebel 31:413ba83b8c0b 1101 // p p n n x x x x x
Bartosz Stebel 31:413ba83b8c0b 1102 // p p n n x x x x x -
Bartosz Stebel 31:413ba83b8c0b 1103 // p p - n n x x x x x
Bartosz Stebel 31:413ba83b8c0b 1104 // p p - - n x x x x x
Bartosz Stebel 31:413ba83b8c0b 1105 // p p o o n x x x x x
Bartosz Stebel 31:413ba83b8c0b 1106
Bartosz Stebel 31:413ba83b8c0b 1107 // new option longer
Bartosz Stebel 31:413ba83b8c0b 1108 // p p n n x x x x x
Bartosz Stebel 31:413ba83b8c0b 1109 // p p n n x x x x x - - -
Bartosz Stebel 31:413ba83b8c0b 1110 // p p - - - n n x x x x x
Bartosz Stebel 31:413ba83b8c0b 1111 // p p - - n n n x x x x x
Bartosz Stebel 31:413ba83b8c0b 1112 // p p o o n n n x x x x x
Bartosz Stebel 31:413ba83b8c0b 1113
Bartosz Stebel 31:413ba83b8c0b 1114 // note, it can only ever be shorter or the same since if an option was inserted the delta got smaller
Bartosz Stebel 31:413ba83b8c0b 1115 // but I'll leave that little comment in, just to show that it would work even if the delta got bigger
Bartosz Stebel 31:413ba83b8c0b 1116
Bartosz Stebel 31:413ba83b8c0b 1117 // now insert the new option into the gap
Bartosz Stebel 31:413ba83b8c0b 1118 DBGLX("Inserting new option...");
Bartosz Stebel 31:413ba83b8c0b 1119 insertOption(insertionPosition,optionDelta,optionValueLength,optionValue);
Bartosz Stebel 31:413ba83b8c0b 1120 DBGX("done\r\n");
Bartosz Stebel 31:413ba83b8c0b 1121 DBG_PDU();
Bartosz Stebel 31:413ba83b8c0b 1122
Bartosz Stebel 31:413ba83b8c0b 1123 // done, mark it with B!
Bartosz Stebel 31:413ba83b8c0b 1124 return 0;
Bartosz Stebel 31:413ba83b8c0b 1125 }
Bartosz Stebel 31:413ba83b8c0b 1126
Bartosz Stebel 31:413ba83b8c0b 1127 /// Allocate space for a payload.
Bartosz Stebel 31:413ba83b8c0b 1128 /**
Bartosz Stebel 31:413ba83b8c0b 1129 * For dynamically constructed PDUs, this will allocate space for a payload in the object
Bartosz Stebel 31:413ba83b8c0b 1130 * and return a pointer to it. If the PDU was constructed from a buffer, this doesn't
Bartosz Stebel 31:413ba83b8c0b 1131 * malloc anything, it just changes the _pduLength and returns the payload pointer.
Bartosz Stebel 31:413ba83b8c0b 1132 *
Bartosz Stebel 31:413ba83b8c0b 1133 * \note The pointer returned points into the PDU buffer.
Bartosz Stebel 31:413ba83b8c0b 1134 * \param len The length of the payload buffer to allocate.
Bartosz Stebel 31:413ba83b8c0b 1135 * \return Either a pointer to the payload buffer, or NULL if there wasn't enough space / allocation failed.
Bartosz Stebel 31:413ba83b8c0b 1136 */
Bartosz Stebel 31:413ba83b8c0b 1137 uint8_t* CoapPDU::mallocPayload(int len) {
Bartosz Stebel 31:413ba83b8c0b 1138 DBG("Entering mallocPayload");
Bartosz Stebel 31:413ba83b8c0b 1139 // sanity checks
Bartosz Stebel 31:413ba83b8c0b 1140 if(len==0) {
Bartosz Stebel 31:413ba83b8c0b 1141 DBG("Cannot allocate a zero length payload");
Bartosz Stebel 31:413ba83b8c0b 1142 return NULL;
Bartosz Stebel 31:413ba83b8c0b 1143 }
Bartosz Stebel 31:413ba83b8c0b 1144
Bartosz Stebel 31:413ba83b8c0b 1145 // further sanity
Bartosz Stebel 31:413ba83b8c0b 1146 if(len==_payloadLength) {
Bartosz Stebel 31:413ba83b8c0b 1147 DBG("Space for payload of specified length already exists");
Bartosz Stebel 31:413ba83b8c0b 1148 if(_payloadPointer==NULL) {
Bartosz Stebel 31:413ba83b8c0b 1149 DBG("Garbage PDU. Payload length is %d, but existing _payloadPointer NULL",_payloadLength);
Bartosz Stebel 31:413ba83b8c0b 1150 return NULL;
Bartosz Stebel 31:413ba83b8c0b 1151 }
Bartosz Stebel 31:413ba83b8c0b 1152 return _payloadPointer;
Bartosz Stebel 31:413ba83b8c0b 1153 }
Bartosz Stebel 31:413ba83b8c0b 1154
Bartosz Stebel 31:413ba83b8c0b 1155 DBG("_bufferLength: %d, _pduLength: %d, _payloadLength: %d",_bufferLength,_pduLength,_payloadLength);
Bartosz Stebel 31:413ba83b8c0b 1156
Bartosz Stebel 31:413ba83b8c0b 1157 // might be making payload bigger (including bigger than 0) or smaller
Bartosz Stebel 31:413ba83b8c0b 1158 int markerSpace = 1;
Bartosz Stebel 31:413ba83b8c0b 1159 int payloadSpace = len;
Bartosz Stebel 31:413ba83b8c0b 1160 // is this a resizing?
Bartosz Stebel 31:413ba83b8c0b 1161 if(_payloadLength!=0) {
Bartosz Stebel 31:413ba83b8c0b 1162 // marker already exists
Bartosz Stebel 31:413ba83b8c0b 1163 markerSpace = 0;
Bartosz Stebel 31:413ba83b8c0b 1164 // compute new payload length (can be negative if shrinking payload)
Bartosz Stebel 31:413ba83b8c0b 1165 payloadSpace = len-_payloadLength;
Bartosz Stebel 31:413ba83b8c0b 1166 }
Bartosz Stebel 31:413ba83b8c0b 1167
Bartosz Stebel 31:413ba83b8c0b 1168 // make space for payload (and payload marker if necessary)
Bartosz Stebel 31:413ba83b8c0b 1169 int newLen = _pduLength+payloadSpace+markerSpace;
Bartosz Stebel 31:413ba83b8c0b 1170 if(!_constructedFromBuffer) {
Bartosz Stebel 31:413ba83b8c0b 1171 uint8_t* newPDU = (uint8_t*)realloc(_pdu,newLen);
Bartosz Stebel 31:413ba83b8c0b 1172 if(newPDU==NULL) {
Bartosz Stebel 31:413ba83b8c0b 1173 DBG("Cannot allocate (or shrink) space for payload");
Bartosz Stebel 31:413ba83b8c0b 1174 return NULL;
Bartosz Stebel 31:413ba83b8c0b 1175 }
Bartosz Stebel 31:413ba83b8c0b 1176 _pdu = newPDU;
Bartosz Stebel 31:413ba83b8c0b 1177 _bufferLength = newLen;
Bartosz Stebel 31:413ba83b8c0b 1178 } else {
Bartosz Stebel 31:413ba83b8c0b 1179 // constructed from buffer, check space
Bartosz Stebel 31:413ba83b8c0b 1180 DBG("newLen: %d, _bufferLength: %d",newLen,_bufferLength);
Bartosz Stebel 31:413ba83b8c0b 1181 if(newLen>_bufferLength) {
Bartosz Stebel 31:413ba83b8c0b 1182 DBG("Buffer too small to contain desired payload, needed %d, got %d.",newLen-_pduLength,_bufferLength-_pduLength);
Bartosz Stebel 31:413ba83b8c0b 1183 return NULL;
Bartosz Stebel 31:413ba83b8c0b 1184 }
Bartosz Stebel 31:413ba83b8c0b 1185 }
Bartosz Stebel 31:413ba83b8c0b 1186
Bartosz Stebel 31:413ba83b8c0b 1187 // deal with fresh allocation case separately
Bartosz Stebel 31:413ba83b8c0b 1188 if(_payloadPointer==NULL) {
Bartosz Stebel 31:413ba83b8c0b 1189 // set payload marker
Bartosz Stebel 31:413ba83b8c0b 1190 _pdu[_pduLength] = 0xFF;
Bartosz Stebel 31:413ba83b8c0b 1191 // payload at end of old PDU
Bartosz Stebel 31:413ba83b8c0b 1192 _payloadPointer = &_pdu[_pduLength+1];
Bartosz Stebel 31:413ba83b8c0b 1193 _pduLength = newLen;
Bartosz Stebel 31:413ba83b8c0b 1194 _payloadLength = len;
Bartosz Stebel 31:413ba83b8c0b 1195 return _payloadPointer;
Bartosz Stebel 31:413ba83b8c0b 1196 }
Bartosz Stebel 31:413ba83b8c0b 1197
Bartosz Stebel 31:413ba83b8c0b 1198 // otherwise, just adjust length of PDU
Bartosz Stebel 31:413ba83b8c0b 1199 _pduLength = newLen;
Bartosz Stebel 31:413ba83b8c0b 1200 _payloadLength = len;
Bartosz Stebel 31:413ba83b8c0b 1201 DBG("Leaving mallocPayload");
Bartosz Stebel 31:413ba83b8c0b 1202 return _payloadPointer;
Bartosz Stebel 31:413ba83b8c0b 1203 }
Bartosz Stebel 31:413ba83b8c0b 1204
Bartosz Stebel 31:413ba83b8c0b 1205 /// Set the payload to the byte sequence specified. Allocates memory in dynamic PDU if necessary.
Bartosz Stebel 31:413ba83b8c0b 1206 /**
Bartosz Stebel 31:413ba83b8c0b 1207 * This will set the payload to \b payload. It will allocate memory in the case where the PDU was
Bartosz Stebel 31:413ba83b8c0b 1208 * constructed without an external buffer.
Bartosz Stebel 31:413ba83b8c0b 1209 *
Bartosz Stebel 31:413ba83b8c0b 1210 * This will fail either if the fixed buffer isn't big enough, or if memory could not be allocated
Bartosz Stebel 31:413ba83b8c0b 1211 * in the non-external-buffer case.
Bartosz Stebel 31:413ba83b8c0b 1212 *
Bartosz Stebel 31:413ba83b8c0b 1213 * \param payload Pointer to payload byte sequence.
Bartosz Stebel 31:413ba83b8c0b 1214 * \param len Length of payload byte sequence.
Bartosz Stebel 31:413ba83b8c0b 1215 * \return 0 on success, 1 on failure.
Bartosz Stebel 31:413ba83b8c0b 1216 */
Bartosz Stebel 31:413ba83b8c0b 1217 int CoapPDU::setPayload(uint8_t *payload, int len) {
Bartosz Stebel 31:413ba83b8c0b 1218 if(payload==NULL) {
Bartosz Stebel 31:413ba83b8c0b 1219 DBG("NULL payload pointer.");
Bartosz Stebel 31:413ba83b8c0b 1220 return 1;
Bartosz Stebel 31:413ba83b8c0b 1221 }
Bartosz Stebel 31:413ba83b8c0b 1222
Bartosz Stebel 31:413ba83b8c0b 1223 uint8_t *payloadPointer = mallocPayload(len);
Bartosz Stebel 31:413ba83b8c0b 1224 if(payloadPointer==NULL) {
Bartosz Stebel 31:413ba83b8c0b 1225 DBG("Allocation of payload failed");
Bartosz Stebel 31:413ba83b8c0b 1226 return 1;
Bartosz Stebel 31:413ba83b8c0b 1227 }
Bartosz Stebel 31:413ba83b8c0b 1228
Bartosz Stebel 31:413ba83b8c0b 1229 // copy payload contents
Bartosz Stebel 31:413ba83b8c0b 1230 memcpy(payloadPointer,payload,len);
Bartosz Stebel 31:413ba83b8c0b 1231
Bartosz Stebel 31:413ba83b8c0b 1232 return 0;
Bartosz Stebel 31:413ba83b8c0b 1233 }
Bartosz Stebel 31:413ba83b8c0b 1234
Bartosz Stebel 31:413ba83b8c0b 1235 /// Returns a pointer to the payload buffer.
Bartosz Stebel 31:413ba83b8c0b 1236 uint8_t* CoapPDU::getPayloadPointer() {
Bartosz Stebel 31:413ba83b8c0b 1237 return _payloadPointer;
Bartosz Stebel 31:413ba83b8c0b 1238 }
Bartosz Stebel 31:413ba83b8c0b 1239
Bartosz Stebel 31:413ba83b8c0b 1240 /// Gets the length of the payload buffer.
Bartosz Stebel 31:413ba83b8c0b 1241 int CoapPDU::getPayloadLength() {
Bartosz Stebel 31:413ba83b8c0b 1242 return _payloadLength;
Bartosz Stebel 31:413ba83b8c0b 1243 }
Bartosz Stebel 31:413ba83b8c0b 1244
Bartosz Stebel 31:413ba83b8c0b 1245 /// Returns a pointer to a buffer which is a copy of the payload buffer (dynamically allocated).
Bartosz Stebel 31:413ba83b8c0b 1246 uint8_t* CoapPDU::getPayloadCopy() {
Bartosz Stebel 31:413ba83b8c0b 1247 if(_payloadLength==0) {
Bartosz Stebel 31:413ba83b8c0b 1248 return NULL;
Bartosz Stebel 31:413ba83b8c0b 1249 }
Bartosz Stebel 31:413ba83b8c0b 1250
Bartosz Stebel 31:413ba83b8c0b 1251 // malloc space for copy
Bartosz Stebel 31:413ba83b8c0b 1252 uint8_t *payload = (uint8_t*)malloc(_payloadLength);
Bartosz Stebel 31:413ba83b8c0b 1253 if(payload==NULL) {
Bartosz Stebel 31:413ba83b8c0b 1254 DBG("Unable to allocate memory for payload");
Bartosz Stebel 31:413ba83b8c0b 1255 return NULL;
Bartosz Stebel 31:413ba83b8c0b 1256 }
Bartosz Stebel 31:413ba83b8c0b 1257
Bartosz Stebel 31:413ba83b8c0b 1258 // copy and return
Bartosz Stebel 31:413ba83b8c0b 1259 memcpy(payload,_payloadPointer,_payloadLength);
Bartosz Stebel 31:413ba83b8c0b 1260 return payload;
Bartosz Stebel 31:413ba83b8c0b 1261 }
Bartosz Stebel 31:413ba83b8c0b 1262
Bartosz Stebel 31:413ba83b8c0b 1263 /// Shorthand for setting the content-format option.
Bartosz Stebel 31:413ba83b8c0b 1264 /**
Bartosz Stebel 31:413ba83b8c0b 1265 * Sets the content-format to the specified value (adds an option).
Bartosz Stebel 31:413ba83b8c0b 1266 * \param format The content format, one of:
Bartosz Stebel 31:413ba83b8c0b 1267 *
Bartosz Stebel 31:413ba83b8c0b 1268 * - COAP_CONTENT_FORMAT_TEXT_PLAIN
Bartosz Stebel 31:413ba83b8c0b 1269 * - COAP_CONTENT_FORMAT_APP_LINK
Bartosz Stebel 31:413ba83b8c0b 1270 * - COAP_CONTENT_FORMAT_APP_XML
Bartosz Stebel 31:413ba83b8c0b 1271 * - COAP_CONTENT_FORMAT_APP_OCTET
Bartosz Stebel 31:413ba83b8c0b 1272 * - COAP_CONTENT_FORMAT_APP_EXI
Bartosz Stebel 31:413ba83b8c0b 1273 * - COAP_CONTENT_FORMAT_APP_JSON
Bartosz Stebel 31:413ba83b8c0b 1274 *
Bartosz Stebel 31:413ba83b8c0b 1275 * \return 0 on success, 1 on failure.
Bartosz Stebel 31:413ba83b8c0b 1276 */
Bartosz Stebel 31:413ba83b8c0b 1277 int CoapPDU::setContentFormat(CoapPDU::ContentFormat format) {
Bartosz Stebel 31:413ba83b8c0b 1278 if(format==0) {
Bartosz Stebel 31:413ba83b8c0b 1279 // minimal representation means null option value
Bartosz Stebel 31:413ba83b8c0b 1280 if(addOption(CoapPDU::COAP_OPTION_CONTENT_FORMAT,0,NULL)!=0) {
Bartosz Stebel 31:413ba83b8c0b 1281 DBG("Error setting content format");
Bartosz Stebel 31:413ba83b8c0b 1282 return 1;
Bartosz Stebel 31:413ba83b8c0b 1283 }
Bartosz Stebel 31:413ba83b8c0b 1284 return 0;
Bartosz Stebel 31:413ba83b8c0b 1285 }
Bartosz Stebel 31:413ba83b8c0b 1286
Bartosz Stebel 31:413ba83b8c0b 1287 uint8_t c[2];
Bartosz Stebel 31:413ba83b8c0b 1288
Bartosz Stebel 31:413ba83b8c0b 1289 // just use 1 byte if can do it
Bartosz Stebel 31:413ba83b8c0b 1290 if(format<256) {
Bartosz Stebel 31:413ba83b8c0b 1291 c[0] = format;
Bartosz Stebel 31:413ba83b8c0b 1292 if(addOption(CoapPDU::COAP_OPTION_CONTENT_FORMAT,1,c)!=0) {
Bartosz Stebel 31:413ba83b8c0b 1293 DBG("Error setting content format");
Bartosz Stebel 31:413ba83b8c0b 1294 return 1;
Bartosz Stebel 31:413ba83b8c0b 1295 }
Bartosz Stebel 31:413ba83b8c0b 1296 return 0;
Bartosz Stebel 31:413ba83b8c0b 1297 }
Bartosz Stebel 31:413ba83b8c0b 1298
Bartosz Stebel 31:413ba83b8c0b 1299 uint16_t networkOrder = htons(format);
Bartosz Stebel 31:413ba83b8c0b 1300 c[0] &= 0x00;
Bartosz Stebel 31:413ba83b8c0b 1301 c[0] |= (networkOrder >> 8); // MSB
Bartosz Stebel 31:413ba83b8c0b 1302 c[1] &= 0x00;
Bartosz Stebel 31:413ba83b8c0b 1303 c[1] |= (networkOrder & 0x00FF); // LSB
Bartosz Stebel 31:413ba83b8c0b 1304 if(addOption(CoapPDU::COAP_OPTION_CONTENT_FORMAT,2,c)!=0) {
Bartosz Stebel 31:413ba83b8c0b 1305 DBG("Error setting content format");
Bartosz Stebel 31:413ba83b8c0b 1306 return 1;
Bartosz Stebel 31:413ba83b8c0b 1307 }
Bartosz Stebel 31:413ba83b8c0b 1308 return 0;
Bartosz Stebel 31:413ba83b8c0b 1309 }
Bartosz Stebel 31:413ba83b8c0b 1310
Bartosz Stebel 31:413ba83b8c0b 1311 /// PRIVATE PRIVATE PRIVATE PRIVATE PRIVATE PRIVATE PRIVATE
Bartosz Stebel 31:413ba83b8c0b 1312 /// PRIVATE PRIVATE PRIVATE PRIVATE PRIVATE PRIVATE PRIVATE
Bartosz Stebel 31:413ba83b8c0b 1313
Bartosz Stebel 31:413ba83b8c0b 1314 /// Moves a block of bytes to end of PDU from given offset.
Bartosz Stebel 31:413ba83b8c0b 1315 /**
Bartosz Stebel 31:413ba83b8c0b 1316 * This moves the block of bytes _pdu[_pduLength-1-shiftOffset-shiftAmount] ... _pdu[_pduLength-1-shiftOffset]
Bartosz Stebel 31:413ba83b8c0b 1317 * to the end of the PDU.
Bartosz Stebel 31:413ba83b8c0b 1318 * \param shiftOffset End of block to move, relative to end of PDU (-1).
Bartosz Stebel 31:413ba83b8c0b 1319 * \param shiftAmount Length of block to move.
Bartosz Stebel 31:413ba83b8c0b 1320 */
Bartosz Stebel 31:413ba83b8c0b 1321 void CoapPDU::shiftPDUUp(int shiftOffset, int shiftAmount) {
Bartosz Stebel 31:413ba83b8c0b 1322 DBG("shiftOffset: %d, shiftAmount: %d",shiftOffset,shiftAmount);
Bartosz Stebel 31:413ba83b8c0b 1323 int destPointer = _pduLength-1;
Bartosz Stebel 31:413ba83b8c0b 1324 int srcPointer = destPointer-shiftOffset;
Bartosz Stebel 31:413ba83b8c0b 1325 while(shiftAmount--) {
Bartosz Stebel 31:413ba83b8c0b 1326 _pdu[destPointer] = _pdu[srcPointer];
Bartosz Stebel 31:413ba83b8c0b 1327 destPointer--;
Bartosz Stebel 31:413ba83b8c0b 1328 srcPointer--;
Bartosz Stebel 31:413ba83b8c0b 1329 }
Bartosz Stebel 31:413ba83b8c0b 1330 }
Bartosz Stebel 31:413ba83b8c0b 1331
Bartosz Stebel 31:413ba83b8c0b 1332 /// Moves a block of bytes down a specified number of steps.
Bartosz Stebel 31:413ba83b8c0b 1333 /**
Bartosz Stebel 31:413ba83b8c0b 1334 * Moves the block of bytes _pdu[startLocation+shiftOffset] ... _pdu[startLocation+shiftOffset+shiftAmount]
Bartosz Stebel 31:413ba83b8c0b 1335 * down to \b startLocation.
Bartosz Stebel 31:413ba83b8c0b 1336 * \param startLocation Index where to shift the block to.
Bartosz Stebel 31:413ba83b8c0b 1337 * \param shiftOffset Where the block starts, relative to start index.
Bartosz Stebel 31:413ba83b8c0b 1338 * \param shiftAmount Length of block to shift.
Bartosz Stebel 31:413ba83b8c0b 1339 */
Bartosz Stebel 31:413ba83b8c0b 1340 void CoapPDU::shiftPDUDown(int startLocation, int shiftOffset, int shiftAmount) {
Bartosz Stebel 31:413ba83b8c0b 1341 DBG("startLocation: %d, shiftOffset: %d, shiftAmount: %d",startLocation,shiftOffset,shiftAmount);
Bartosz Stebel 31:413ba83b8c0b 1342 int srcPointer = startLocation+shiftOffset;
Bartosz Stebel 31:413ba83b8c0b 1343 while(shiftAmount--) {
Bartosz Stebel 31:413ba83b8c0b 1344 _pdu[startLocation] = _pdu[srcPointer];
Bartosz Stebel 31:413ba83b8c0b 1345 startLocation++;
Bartosz Stebel 31:413ba83b8c0b 1346 srcPointer++;
Bartosz Stebel 31:413ba83b8c0b 1347 }
Bartosz Stebel 31:413ba83b8c0b 1348 }
Bartosz Stebel 31:413ba83b8c0b 1349
Bartosz Stebel 31:413ba83b8c0b 1350 /// Gets the payload length of an option.
Bartosz Stebel 31:413ba83b8c0b 1351 /**
Bartosz Stebel 31:413ba83b8c0b 1352 * \param option Pointer to location of option in PDU.
Bartosz Stebel 31:413ba83b8c0b 1353 * \return The 16 bit option-payload length.
Bartosz Stebel 31:413ba83b8c0b 1354 */
Bartosz Stebel 31:413ba83b8c0b 1355 uint16_t CoapPDU::getOptionValueLength(uint8_t *option) {
Bartosz Stebel 31:413ba83b8c0b 1356 uint16_t delta = (option[0] & 0xF0) >> 4;
Bartosz Stebel 31:413ba83b8c0b 1357 uint16_t length = (option[0] & 0x0F);
Bartosz Stebel 31:413ba83b8c0b 1358 // no extra bytes
Bartosz Stebel 31:413ba83b8c0b 1359 if(length<13) {
Bartosz Stebel 31:413ba83b8c0b 1360 return length;
Bartosz Stebel 31:413ba83b8c0b 1361 }
Bartosz Stebel 31:413ba83b8c0b 1362
Bartosz Stebel 31:413ba83b8c0b 1363 // extra bytes skip header
Bartosz Stebel 31:413ba83b8c0b 1364 int offset = 1;
Bartosz Stebel 31:413ba83b8c0b 1365 // skip extra option delta bytes
Bartosz Stebel 31:413ba83b8c0b 1366 if(delta==13) {
Bartosz Stebel 31:413ba83b8c0b 1367 offset++;
Bartosz Stebel 31:413ba83b8c0b 1368 } else if(delta==14) {
Bartosz Stebel 31:413ba83b8c0b 1369 offset+=2;
Bartosz Stebel 31:413ba83b8c0b 1370 }
Bartosz Stebel 31:413ba83b8c0b 1371
Bartosz Stebel 31:413ba83b8c0b 1372 // process length
Bartosz Stebel 31:413ba83b8c0b 1373 if(length==13) {
Bartosz Stebel 31:413ba83b8c0b 1374 return (option[offset]+13);
Bartosz Stebel 31:413ba83b8c0b 1375 } else {
Bartosz Stebel 31:413ba83b8c0b 1376 // need to convert to host order
Bartosz Stebel 31:413ba83b8c0b 1377 uint16_t networkOrder = 0x0000;
Bartosz Stebel 31:413ba83b8c0b 1378 networkOrder |= option[offset++];
Bartosz Stebel 31:413ba83b8c0b 1379 networkOrder <<= 8;
Bartosz Stebel 31:413ba83b8c0b 1380 networkOrder |= option[offset];
Bartosz Stebel 31:413ba83b8c0b 1381 uint16_t hostOrder = ntohs(networkOrder);
Bartosz Stebel 31:413ba83b8c0b 1382 return hostOrder+269;
Bartosz Stebel 31:413ba83b8c0b 1383 }
Bartosz Stebel 31:413ba83b8c0b 1384
Bartosz Stebel 31:413ba83b8c0b 1385 }
Bartosz Stebel 31:413ba83b8c0b 1386
Bartosz Stebel 31:413ba83b8c0b 1387 /// Gets the delta of an option.
Bartosz Stebel 31:413ba83b8c0b 1388 /**
Bartosz Stebel 31:413ba83b8c0b 1389 * \param option Pointer to location of option in PDU.
Bartosz Stebel 31:413ba83b8c0b 1390 * \return The 16 bit delta.
Bartosz Stebel 31:413ba83b8c0b 1391 */
Bartosz Stebel 31:413ba83b8c0b 1392 uint16_t CoapPDU::getOptionDelta(uint8_t *option) {
Bartosz Stebel 31:413ba83b8c0b 1393 uint16_t delta = (option[0] & 0xF0) >> 4;
Bartosz Stebel 31:413ba83b8c0b 1394 if(delta<13) {
Bartosz Stebel 31:413ba83b8c0b 1395 return delta;
Bartosz Stebel 31:413ba83b8c0b 1396 } else if(delta==13) {
Bartosz Stebel 31:413ba83b8c0b 1397 // single byte option delta
Bartosz Stebel 31:413ba83b8c0b 1398 return (option[1]+13);
Bartosz Stebel 31:413ba83b8c0b 1399 } else if(delta==14) {
Bartosz Stebel 31:413ba83b8c0b 1400 // double byte option delta
Bartosz Stebel 31:413ba83b8c0b 1401 // need to convert to host order
Bartosz Stebel 31:413ba83b8c0b 1402 uint16_t networkOrder = 0x0000;
Bartosz Stebel 31:413ba83b8c0b 1403 networkOrder |= option[1];
Bartosz Stebel 31:413ba83b8c0b 1404 networkOrder <<= 8;
Bartosz Stebel 31:413ba83b8c0b 1405 networkOrder |= option[2];
Bartosz Stebel 31:413ba83b8c0b 1406 uint16_t hostOrder = ntohs(networkOrder);
Bartosz Stebel 31:413ba83b8c0b 1407 return hostOrder+269;
Bartosz Stebel 31:413ba83b8c0b 1408 } else {
Bartosz Stebel 31:413ba83b8c0b 1409 // should only ever occur in payload marker
Bartosz Stebel 31:413ba83b8c0b 1410 return delta;
Bartosz Stebel 31:413ba83b8c0b 1411 }
Bartosz Stebel 31:413ba83b8c0b 1412 }
Bartosz Stebel 31:413ba83b8c0b 1413
Bartosz Stebel 31:413ba83b8c0b 1414 /// Finds the insertion position in the current list of options for the specified option.
Bartosz Stebel 31:413ba83b8c0b 1415 /**
Bartosz Stebel 31:413ba83b8c0b 1416 * \param optionNumber The option's number.
Bartosz Stebel 31:413ba83b8c0b 1417 * \param prevOptionNumber A pointer to a uint16_t which will store the option number of the option previous
Bartosz Stebel 31:413ba83b8c0b 1418 * to the insertion point.
Bartosz Stebel 31:413ba83b8c0b 1419 * \return 0 on success, 1 on failure. \b prevOptionNumber will contain the option number of the option
Bartosz Stebel 31:413ba83b8c0b 1420 * before the insertion position (for example 0 if no options have been inserted).
Bartosz Stebel 31:413ba83b8c0b 1421 */
Bartosz Stebel 31:413ba83b8c0b 1422 int CoapPDU::findInsertionPosition(uint16_t optionNumber, uint16_t *prevOptionNumber) {
Bartosz Stebel 31:413ba83b8c0b 1423 // zero this for safety
Bartosz Stebel 31:413ba83b8c0b 1424 *prevOptionNumber = 0x00;
Bartosz Stebel 31:413ba83b8c0b 1425
Bartosz Stebel 31:413ba83b8c0b 1426 DBG("_pduLength: %d",_pduLength);
Bartosz Stebel 31:413ba83b8c0b 1427
Bartosz Stebel 31:413ba83b8c0b 1428 // if option is bigger than any currently stored, it goes at the end
Bartosz Stebel 31:413ba83b8c0b 1429 // this includes the case that no option has yet been added
Bartosz Stebel 31:413ba83b8c0b 1430 if( (optionNumber >= _maxAddedOptionNumber) || (_pduLength == (COAP_HDR_SIZE+getTokenLength())) ) {
Bartosz Stebel 31:413ba83b8c0b 1431 *prevOptionNumber = _maxAddedOptionNumber;
Bartosz Stebel 31:413ba83b8c0b 1432 return _pduLength;
Bartosz Stebel 31:413ba83b8c0b 1433 }
Bartosz Stebel 31:413ba83b8c0b 1434
Bartosz Stebel 31:413ba83b8c0b 1435 // otherwise walk over the options
Bartosz Stebel 31:413ba83b8c0b 1436 int optionPos = COAP_HDR_SIZE + getTokenLength();
Bartosz Stebel 31:413ba83b8c0b 1437 uint16_t optionDelta = 0, optionValueLength = 0;
Bartosz Stebel 31:413ba83b8c0b 1438 uint16_t currentOptionNumber = 0;
Bartosz Stebel 31:413ba83b8c0b 1439 while(optionPos<_pduLength && _pdu[optionPos]!=0xFF) {
Bartosz Stebel 31:413ba83b8c0b 1440 optionDelta = getOptionDelta(&_pdu[optionPos]);
Bartosz Stebel 31:413ba83b8c0b 1441 currentOptionNumber += optionDelta;
Bartosz Stebel 31:413ba83b8c0b 1442 optionValueLength = getOptionValueLength(&_pdu[optionPos]);
Bartosz Stebel 31:413ba83b8c0b 1443 // test if this is insertion position
Bartosz Stebel 31:413ba83b8c0b 1444 if(currentOptionNumber>optionNumber) {
Bartosz Stebel 31:413ba83b8c0b 1445 return optionPos;
Bartosz Stebel 31:413ba83b8c0b 1446 }
Bartosz Stebel 31:413ba83b8c0b 1447 // keep track of the last valid option number
Bartosz Stebel 31:413ba83b8c0b 1448 *prevOptionNumber = currentOptionNumber;
Bartosz Stebel 31:413ba83b8c0b 1449 // move onto next option
Bartosz Stebel 31:413ba83b8c0b 1450 optionPos += computeExtraBytes(optionDelta);
Bartosz Stebel 31:413ba83b8c0b 1451 optionPos += computeExtraBytes(optionValueLength);
Bartosz Stebel 31:413ba83b8c0b 1452 optionPos += optionValueLength;
Bartosz Stebel 31:413ba83b8c0b 1453 optionPos++; // (for mandatory option header byte)
Bartosz Stebel 31:413ba83b8c0b 1454 }
Bartosz Stebel 31:413ba83b8c0b 1455 return optionPos;
Bartosz Stebel 31:413ba83b8c0b 1456
Bartosz Stebel 31:413ba83b8c0b 1457 }
Bartosz Stebel 31:413ba83b8c0b 1458
Bartosz Stebel 31:413ba83b8c0b 1459 /// CoAP uses a minimal-byte representation for length fields. This returns the number of bytes needed to represent a given length.
Bartosz Stebel 31:413ba83b8c0b 1460 int CoapPDU::computeExtraBytes(uint16_t n) {
Bartosz Stebel 31:413ba83b8c0b 1461 if(n<13) {
Bartosz Stebel 31:413ba83b8c0b 1462 return 0;
Bartosz Stebel 31:413ba83b8c0b 1463 }
Bartosz Stebel 31:413ba83b8c0b 1464
Bartosz Stebel 31:413ba83b8c0b 1465 if(n<269) {
Bartosz Stebel 31:413ba83b8c0b 1466 return 1;
Bartosz Stebel 31:413ba83b8c0b 1467 }
Bartosz Stebel 31:413ba83b8c0b 1468
Bartosz Stebel 31:413ba83b8c0b 1469 return 2;
Bartosz Stebel 31:413ba83b8c0b 1470 }
Bartosz Stebel 31:413ba83b8c0b 1471
Bartosz Stebel 31:413ba83b8c0b 1472 /// Set the option delta to the specified value.
Bartosz Stebel 31:413ba83b8c0b 1473 /**
Bartosz Stebel 31:413ba83b8c0b 1474 * This assumes space has been made for the option delta.
Bartosz Stebel 31:413ba83b8c0b 1475 * \param optionPosition The index of the option in the PDU.
Bartosz Stebel 31:413ba83b8c0b 1476 * \param optionDelta The option delta value to set.
Bartosz Stebel 31:413ba83b8c0b 1477 */
Bartosz Stebel 31:413ba83b8c0b 1478 void CoapPDU::setOptionDelta(int optionPosition, uint16_t optionDelta) {
Bartosz Stebel 31:413ba83b8c0b 1479 int headerStart = optionPosition;
Bartosz Stebel 31:413ba83b8c0b 1480 // clear the old option delta bytes
Bartosz Stebel 31:413ba83b8c0b 1481 _pdu[headerStart] &= 0x0F;
Bartosz Stebel 31:413ba83b8c0b 1482
Bartosz Stebel 31:413ba83b8c0b 1483 // set the option delta bytes
Bartosz Stebel 31:413ba83b8c0b 1484 if(optionDelta<13) {
Bartosz Stebel 31:413ba83b8c0b 1485 _pdu[headerStart] |= (optionDelta << 4);
Bartosz Stebel 31:413ba83b8c0b 1486 } else if(optionDelta<269) {
Bartosz Stebel 31:413ba83b8c0b 1487 // 1 extra byte
Bartosz Stebel 31:413ba83b8c0b 1488 _pdu[headerStart] |= 0xD0; // 13 in first nibble
Bartosz Stebel 31:413ba83b8c0b 1489 _pdu[++optionPosition] &= 0x00;
Bartosz Stebel 31:413ba83b8c0b 1490 _pdu[optionPosition] |= (optionDelta-13);
Bartosz Stebel 31:413ba83b8c0b 1491 } else {
Bartosz Stebel 31:413ba83b8c0b 1492 // 2 extra bytes, network byte order uint16_t
Bartosz Stebel 31:413ba83b8c0b 1493 _pdu[headerStart] |= 0xE0; // 14 in first nibble
Bartosz Stebel 31:413ba83b8c0b 1494 optionDelta = htons(optionDelta-269);
Bartosz Stebel 31:413ba83b8c0b 1495 _pdu[++optionPosition] &= 0x00;
Bartosz Stebel 31:413ba83b8c0b 1496 _pdu[optionPosition] |= (optionDelta >> 8); // MSB
Bartosz Stebel 31:413ba83b8c0b 1497 _pdu[++optionPosition] &= 0x00;
Bartosz Stebel 31:413ba83b8c0b 1498 _pdu[optionPosition] |= (optionDelta & 0x00FF); // LSB
Bartosz Stebel 31:413ba83b8c0b 1499 }
Bartosz Stebel 31:413ba83b8c0b 1500 }
Bartosz Stebel 31:413ba83b8c0b 1501
Bartosz Stebel 31:413ba83b8c0b 1502 /// Insert an option in-memory at the specified location.
Bartosz Stebel 31:413ba83b8c0b 1503 /**
Bartosz Stebel 31:413ba83b8c0b 1504 * This assumes that there is enough space at the location specified.
Bartosz Stebel 31:413ba83b8c0b 1505 * \param insertionPosition Position in the PDU where the option should be placed.
Bartosz Stebel 31:413ba83b8c0b 1506 * \param optionDelta The delta value for the option.
Bartosz Stebel 31:413ba83b8c0b 1507 * \param optionValueLength The length of the option value.
Bartosz Stebel 31:413ba83b8c0b 1508 * \param optionValue A pointer to the sequence of bytes representing the option value.
Bartosz Stebel 31:413ba83b8c0b 1509 * \return 0 on success, 1 on failure.
Bartosz Stebel 31:413ba83b8c0b 1510 */
Bartosz Stebel 31:413ba83b8c0b 1511 int CoapPDU::insertOption(
Bartosz Stebel 31:413ba83b8c0b 1512 int insertionPosition,
Bartosz Stebel 31:413ba83b8c0b 1513 uint16_t optionDelta,
Bartosz Stebel 31:413ba83b8c0b 1514 uint16_t optionValueLength,
Bartosz Stebel 31:413ba83b8c0b 1515 uint8_t *optionValue) {
Bartosz Stebel 31:413ba83b8c0b 1516
Bartosz Stebel 31:413ba83b8c0b 1517 int headerStart = insertionPosition;
Bartosz Stebel 31:413ba83b8c0b 1518
Bartosz Stebel 31:413ba83b8c0b 1519 // clear old option header start
Bartosz Stebel 31:413ba83b8c0b 1520 _pdu[headerStart] &= 0x00;
Bartosz Stebel 31:413ba83b8c0b 1521
Bartosz Stebel 31:413ba83b8c0b 1522 // set the option delta bytes
Bartosz Stebel 31:413ba83b8c0b 1523 if(optionDelta<13) {
Bartosz Stebel 31:413ba83b8c0b 1524 _pdu[headerStart] |= (optionDelta << 4);
Bartosz Stebel 31:413ba83b8c0b 1525 } else if(optionDelta<269) {
Bartosz Stebel 31:413ba83b8c0b 1526 // 1 extra byte
Bartosz Stebel 31:413ba83b8c0b 1527 _pdu[headerStart] |= 0xD0; // 13 in first nibble
Bartosz Stebel 31:413ba83b8c0b 1528 _pdu[++insertionPosition] &= 0x00;
Bartosz Stebel 31:413ba83b8c0b 1529 _pdu[insertionPosition] |= (optionDelta-13);
Bartosz Stebel 31:413ba83b8c0b 1530 } else {
Bartosz Stebel 31:413ba83b8c0b 1531 // 2 extra bytes, network byte order uint16_t
Bartosz Stebel 31:413ba83b8c0b 1532 _pdu[headerStart] |= 0xE0; // 14 in first nibble
Bartosz Stebel 31:413ba83b8c0b 1533 optionDelta = htons(optionDelta-269);
Bartosz Stebel 31:413ba83b8c0b 1534 _pdu[++insertionPosition] &= 0x00;
Bartosz Stebel 31:413ba83b8c0b 1535 _pdu[insertionPosition] |= (optionDelta >> 8); // MSB
Bartosz Stebel 31:413ba83b8c0b 1536 _pdu[++insertionPosition] &= 0x00;
Bartosz Stebel 31:413ba83b8c0b 1537 _pdu[insertionPosition] |= (optionDelta & 0x00FF); // LSB
Bartosz Stebel 31:413ba83b8c0b 1538 }
Bartosz Stebel 31:413ba83b8c0b 1539
Bartosz Stebel 31:413ba83b8c0b 1540 // set the option value length bytes
Bartosz Stebel 31:413ba83b8c0b 1541 if(optionValueLength<13) {
Bartosz Stebel 31:413ba83b8c0b 1542 _pdu[headerStart] |= (optionValueLength & 0x000F);
Bartosz Stebel 31:413ba83b8c0b 1543 } else if(optionValueLength<269) {
Bartosz Stebel 31:413ba83b8c0b 1544 _pdu[headerStart] |= 0x0D; // 13 in second nibble
Bartosz Stebel 31:413ba83b8c0b 1545 _pdu[++insertionPosition] &= 0x00;
Bartosz Stebel 31:413ba83b8c0b 1546 _pdu[insertionPosition] |= (optionValueLength-13);
Bartosz Stebel 31:413ba83b8c0b 1547 } else {
Bartosz Stebel 31:413ba83b8c0b 1548 _pdu[headerStart] |= 0x0E; // 14 in second nibble
Bartosz Stebel 31:413ba83b8c0b 1549 // this is in network byte order
Bartosz Stebel 31:413ba83b8c0b 1550 DBG("optionValueLength: %u",optionValueLength);
Bartosz Stebel 31:413ba83b8c0b 1551 uint16_t networkOrder = htons(optionValueLength-269);
Bartosz Stebel 31:413ba83b8c0b 1552 _pdu[++insertionPosition] &= 0x00;
Bartosz Stebel 31:413ba83b8c0b 1553 _pdu[insertionPosition] |= (networkOrder >> 8); // MSB
Bartosz Stebel 31:413ba83b8c0b 1554 _pdu[++insertionPosition] &= 0x00;
Bartosz Stebel 31:413ba83b8c0b 1555 _pdu[insertionPosition] |= (networkOrder & 0x00FF); // LSB
Bartosz Stebel 31:413ba83b8c0b 1556 }
Bartosz Stebel 31:413ba83b8c0b 1557
Bartosz Stebel 31:413ba83b8c0b 1558 // and finally copy the option value itself
Bartosz Stebel 31:413ba83b8c0b 1559 memcpy(&_pdu[++insertionPosition],optionValue,optionValueLength);
Bartosz Stebel 31:413ba83b8c0b 1560
Bartosz Stebel 31:413ba83b8c0b 1561 return 0;
Bartosz Stebel 31:413ba83b8c0b 1562 }
Bartosz Stebel 31:413ba83b8c0b 1563
Bartosz Stebel 31:413ba83b8c0b 1564 // DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG
Bartosz Stebel 31:413ba83b8c0b 1565 // DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG
Bartosz Stebel 31:413ba83b8c0b 1566
Bartosz Stebel 31:413ba83b8c0b 1567 /// Prints the PDU in human-readable format.
Bartosz Stebel 31:413ba83b8c0b 1568 void CoapPDU::printHuman() {
Bartosz Stebel 31:413ba83b8c0b 1569 INFOX("__________________\r\n");
Bartosz Stebel 31:413ba83b8c0b 1570 if(_constructedFromBuffer) {
Bartosz Stebel 31:413ba83b8c0b 1571 INFOX("PDU was constructed from buffer of %d bytes\r\n",_bufferLength);
Bartosz Stebel 31:413ba83b8c0b 1572 }
Bartosz Stebel 31:413ba83b8c0b 1573 INFOX("PDU is %d bytes long\r\n",_pduLength);
Bartosz Stebel 31:413ba83b8c0b 1574 INFOX("CoAP Version: %d\r\n",getVersion());
Bartosz Stebel 31:413ba83b8c0b 1575 INFOX("Message Type: ");
Bartosz Stebel 31:413ba83b8c0b 1576 switch(getType()) {
Bartosz Stebel 31:413ba83b8c0b 1577 case COAP_CONFIRMABLE:
Bartosz Stebel 31:413ba83b8c0b 1578 INFOX("Confirmable\r\n");
Bartosz Stebel 31:413ba83b8c0b 1579 break;
Bartosz Stebel 31:413ba83b8c0b 1580
Bartosz Stebel 31:413ba83b8c0b 1581 case COAP_NON_CONFIRMABLE:
Bartosz Stebel 31:413ba83b8c0b 1582 INFOX("Non-Confirmable\r\n");
Bartosz Stebel 31:413ba83b8c0b 1583 break;
Bartosz Stebel 31:413ba83b8c0b 1584
Bartosz Stebel 31:413ba83b8c0b 1585 case COAP_ACKNOWLEDGEMENT:
Bartosz Stebel 31:413ba83b8c0b 1586 INFOX("Acknowledgement\r\n");
Bartosz Stebel 31:413ba83b8c0b 1587 break;
Bartosz Stebel 31:413ba83b8c0b 1588
Bartosz Stebel 31:413ba83b8c0b 1589 case COAP_RESET:
Bartosz Stebel 31:413ba83b8c0b 1590 INFOX("Reset\r\n");
Bartosz Stebel 31:413ba83b8c0b 1591 break;
Bartosz Stebel 31:413ba83b8c0b 1592 }
Bartosz Stebel 31:413ba83b8c0b 1593 INFOX("Token length: %d\r\n",getTokenLength());
Bartosz Stebel 31:413ba83b8c0b 1594 INFOX("Code: ");
Bartosz Stebel 31:413ba83b8c0b 1595 switch(getCode()) {
Bartosz Stebel 31:413ba83b8c0b 1596 case COAP_EMPTY:
Bartosz Stebel 31:413ba83b8c0b 1597 INFOX("0.00 Empty");
Bartosz Stebel 31:413ba83b8c0b 1598 break;
Bartosz Stebel 31:413ba83b8c0b 1599 case COAP_GET:
Bartosz Stebel 31:413ba83b8c0b 1600 INFOX("0.01 GET");
Bartosz Stebel 31:413ba83b8c0b 1601 break;
Bartosz Stebel 31:413ba83b8c0b 1602 case COAP_POST:
Bartosz Stebel 31:413ba83b8c0b 1603 INFOX("0.02 POST");
Bartosz Stebel 31:413ba83b8c0b 1604 break;
Bartosz Stebel 31:413ba83b8c0b 1605 case COAP_PUT:
Bartosz Stebel 31:413ba83b8c0b 1606 INFOX("0.03 PUT");
Bartosz Stebel 31:413ba83b8c0b 1607 break;
Bartosz Stebel 31:413ba83b8c0b 1608 case COAP_DELETE:
Bartosz Stebel 31:413ba83b8c0b 1609 INFOX("0.04 DELETE");
Bartosz Stebel 31:413ba83b8c0b 1610 break;
Bartosz Stebel 31:413ba83b8c0b 1611 case COAP_CREATED:
Bartosz Stebel 31:413ba83b8c0b 1612 INFOX("2.01 Created");
Bartosz Stebel 31:413ba83b8c0b 1613 break;
Bartosz Stebel 31:413ba83b8c0b 1614 case COAP_DELETED:
Bartosz Stebel 31:413ba83b8c0b 1615 INFOX("2.02 Deleted");
Bartosz Stebel 31:413ba83b8c0b 1616 break;
Bartosz Stebel 31:413ba83b8c0b 1617 case COAP_VALID:
Bartosz Stebel 31:413ba83b8c0b 1618 INFOX("2.03 Valid");
Bartosz Stebel 31:413ba83b8c0b 1619 break;
Bartosz Stebel 31:413ba83b8c0b 1620 case COAP_CHANGED:
Bartosz Stebel 31:413ba83b8c0b 1621 INFOX("2.04 Changed");
Bartosz Stebel 31:413ba83b8c0b 1622 break;
Bartosz Stebel 31:413ba83b8c0b 1623 case COAP_CONTENT:
Bartosz Stebel 31:413ba83b8c0b 1624 INFOX("2.05 Content");
Bartosz Stebel 31:413ba83b8c0b 1625 break;
Bartosz Stebel 31:413ba83b8c0b 1626 case COAP_BAD_REQUEST:
Bartosz Stebel 31:413ba83b8c0b 1627 INFOX("4.00 Bad Request");
Bartosz Stebel 31:413ba83b8c0b 1628 break;
Bartosz Stebel 31:413ba83b8c0b 1629 case COAP_UNAUTHORIZED:
Bartosz Stebel 31:413ba83b8c0b 1630 INFOX("4.01 Unauthorized");
Bartosz Stebel 31:413ba83b8c0b 1631 break;
Bartosz Stebel 31:413ba83b8c0b 1632 case COAP_BAD_OPTION:
Bartosz Stebel 31:413ba83b8c0b 1633 INFOX("4.02 Bad Option");
Bartosz Stebel 31:413ba83b8c0b 1634 break;
Bartosz Stebel 31:413ba83b8c0b 1635 case COAP_FORBIDDEN:
Bartosz Stebel 31:413ba83b8c0b 1636 INFOX("4.03 Forbidden");
Bartosz Stebel 31:413ba83b8c0b 1637 break;
Bartosz Stebel 31:413ba83b8c0b 1638 case COAP_NOT_FOUND:
Bartosz Stebel 31:413ba83b8c0b 1639 INFOX("4.04 Not Found");
Bartosz Stebel 31:413ba83b8c0b 1640 break;
Bartosz Stebel 31:413ba83b8c0b 1641 case COAP_METHOD_NOT_ALLOWED:
Bartosz Stebel 31:413ba83b8c0b 1642 INFOX("4.05 Method Not Allowed");
Bartosz Stebel 31:413ba83b8c0b 1643 break;
Bartosz Stebel 31:413ba83b8c0b 1644 case COAP_NOT_ACCEPTABLE:
Bartosz Stebel 31:413ba83b8c0b 1645 INFOX("4.06 Not Acceptable");
Bartosz Stebel 31:413ba83b8c0b 1646 break;
Bartosz Stebel 31:413ba83b8c0b 1647 case COAP_PRECONDITION_FAILED:
Bartosz Stebel 31:413ba83b8c0b 1648 INFOX("4.12 Precondition Failed");
Bartosz Stebel 31:413ba83b8c0b 1649 break;
Bartosz Stebel 31:413ba83b8c0b 1650 case COAP_REQUEST_ENTITY_TOO_LARGE:
Bartosz Stebel 31:413ba83b8c0b 1651 INFOX("4.13 Request Entity Too Large");
Bartosz Stebel 31:413ba83b8c0b 1652 break;
Bartosz Stebel 31:413ba83b8c0b 1653 case COAP_UNSUPPORTED_CONTENT_FORMAT:
Bartosz Stebel 31:413ba83b8c0b 1654 INFOX("4.15 Unsupported Content-Format");
Bartosz Stebel 31:413ba83b8c0b 1655 break;
Bartosz Stebel 31:413ba83b8c0b 1656 case COAP_INTERNAL_SERVER_ERROR:
Bartosz Stebel 31:413ba83b8c0b 1657 INFOX("5.00 Internal Server Error");
Bartosz Stebel 31:413ba83b8c0b 1658 break;
Bartosz Stebel 31:413ba83b8c0b 1659 case COAP_NOT_IMPLEMENTED:
Bartosz Stebel 31:413ba83b8c0b 1660 INFOX("5.01 Not Implemented");
Bartosz Stebel 31:413ba83b8c0b 1661 break;
Bartosz Stebel 31:413ba83b8c0b 1662 case COAP_BAD_GATEWAY:
Bartosz Stebel 31:413ba83b8c0b 1663 INFOX("5.02 Bad Gateway");
Bartosz Stebel 31:413ba83b8c0b 1664 break;
Bartosz Stebel 31:413ba83b8c0b 1665 case COAP_SERVICE_UNAVAILABLE:
Bartosz Stebel 31:413ba83b8c0b 1666 INFOX("5.03 Service Unavailable");
Bartosz Stebel 31:413ba83b8c0b 1667 break;
Bartosz Stebel 31:413ba83b8c0b 1668 case COAP_GATEWAY_TIMEOUT:
Bartosz Stebel 31:413ba83b8c0b 1669 INFOX("5.04 Gateway Timeout");
Bartosz Stebel 31:413ba83b8c0b 1670 break;
Bartosz Stebel 31:413ba83b8c0b 1671 case COAP_PROXYING_NOT_SUPPORTED:
Bartosz Stebel 31:413ba83b8c0b 1672 INFOX("5.05 Proxying Not Supported");
Bartosz Stebel 31:413ba83b8c0b 1673 break;
Bartosz Stebel 31:413ba83b8c0b 1674 case COAP_UNDEFINED_CODE:
Bartosz Stebel 31:413ba83b8c0b 1675 INFOX("Undefined Code");
Bartosz Stebel 31:413ba83b8c0b 1676 break;
Bartosz Stebel 31:413ba83b8c0b 1677 }
Bartosz Stebel 31:413ba83b8c0b 1678 INFOX("\r\n");
Bartosz Stebel 31:413ba83b8c0b 1679
Bartosz Stebel 31:413ba83b8c0b 1680 // print message ID
Bartosz Stebel 31:413ba83b8c0b 1681 INFOX("Message ID: %u\r\n",getMessageID());
Bartosz Stebel 31:413ba83b8c0b 1682
Bartosz Stebel 31:413ba83b8c0b 1683 // print token value
Bartosz Stebel 31:413ba83b8c0b 1684 int tokenLength = getTokenLength();
Bartosz Stebel 31:413ba83b8c0b 1685 uint8_t *tokenPointer = getPDUPointer()+COAP_HDR_SIZE;
Bartosz Stebel 31:413ba83b8c0b 1686 if(tokenLength==0) {
Bartosz Stebel 31:413ba83b8c0b 1687 INFOX("No token.\r\n");
Bartosz Stebel 31:413ba83b8c0b 1688 } else {
Bartosz Stebel 31:413ba83b8c0b 1689 INFOX("Token of %d bytes.\r\n",tokenLength);
Bartosz Stebel 31:413ba83b8c0b 1690 INFOX(" Value: 0x");
Bartosz Stebel 31:413ba83b8c0b 1691 for(int j=0; j<tokenLength; j++) {
Bartosz Stebel 31:413ba83b8c0b 1692 INFOX("%.2x",tokenPointer[j]);
Bartosz Stebel 31:413ba83b8c0b 1693 }
Bartosz Stebel 31:413ba83b8c0b 1694 INFOX("\r\n");
Bartosz Stebel 31:413ba83b8c0b 1695 }
Bartosz Stebel 31:413ba83b8c0b 1696
Bartosz Stebel 31:413ba83b8c0b 1697 // print options
Bartosz Stebel 31:413ba83b8c0b 1698 CoapPDU::CoapOption* options = getOptions();
Bartosz Stebel 31:413ba83b8c0b 1699 INFOX("%d options:\r\n",_numOptions);
Bartosz Stebel 31:413ba83b8c0b 1700 for(int i=0; i<_numOptions; i++) {
Bartosz Stebel 31:413ba83b8c0b 1701 INFOX("OPTION (%d/%d)\r\n",i,_numOptions);
Bartosz Stebel 31:413ba83b8c0b 1702 INFOX(" Option number (delta): %hu (%hu)\r\n",options[i].optionNumber,options[i].optionDelta);
Bartosz Stebel 31:413ba83b8c0b 1703 INFOX(" Name: ");
Bartosz Stebel 31:413ba83b8c0b 1704 switch(options[i].optionNumber) {
Bartosz Stebel 31:413ba83b8c0b 1705 case COAP_OPTION_IF_MATCH:
Bartosz Stebel 31:413ba83b8c0b 1706 INFOX("IF_MATCH");
Bartosz Stebel 31:413ba83b8c0b 1707 break;
Bartosz Stebel 31:413ba83b8c0b 1708 case COAP_OPTION_URI_HOST:
Bartosz Stebel 31:413ba83b8c0b 1709 INFOX("URI_HOST");
Bartosz Stebel 31:413ba83b8c0b 1710 break;
Bartosz Stebel 31:413ba83b8c0b 1711 case COAP_OPTION_ETAG:
Bartosz Stebel 31:413ba83b8c0b 1712 INFOX("ETAG");
Bartosz Stebel 31:413ba83b8c0b 1713 break;
Bartosz Stebel 31:413ba83b8c0b 1714 case COAP_OPTION_IF_NONE_MATCH:
Bartosz Stebel 31:413ba83b8c0b 1715 INFOX("IF_NONE_MATCH");
Bartosz Stebel 31:413ba83b8c0b 1716 break;
Bartosz Stebel 31:413ba83b8c0b 1717 case COAP_OPTION_OBSERVE:
Bartosz Stebel 31:413ba83b8c0b 1718 INFOX("OBSERVE");
Bartosz Stebel 31:413ba83b8c0b 1719 break;
Bartosz Stebel 31:413ba83b8c0b 1720 case COAP_OPTION_URI_PORT:
Bartosz Stebel 31:413ba83b8c0b 1721 INFOX("URI_PORT");
Bartosz Stebel 31:413ba83b8c0b 1722 break;
Bartosz Stebel 31:413ba83b8c0b 1723 case COAP_OPTION_LOCATION_PATH:
Bartosz Stebel 31:413ba83b8c0b 1724 INFOX("LOCATION_PATH");
Bartosz Stebel 31:413ba83b8c0b 1725 break;
Bartosz Stebel 31:413ba83b8c0b 1726 case COAP_OPTION_URI_PATH:
Bartosz Stebel 31:413ba83b8c0b 1727 INFOX("URI_PATH");
Bartosz Stebel 31:413ba83b8c0b 1728 break;
Bartosz Stebel 31:413ba83b8c0b 1729 case COAP_OPTION_CONTENT_FORMAT:
Bartosz Stebel 31:413ba83b8c0b 1730 INFOX("CONTENT_FORMAT");
Bartosz Stebel 31:413ba83b8c0b 1731 break;
Bartosz Stebel 31:413ba83b8c0b 1732 case COAP_OPTION_MAX_AGE:
Bartosz Stebel 31:413ba83b8c0b 1733 INFOX("MAX_AGE");
Bartosz Stebel 31:413ba83b8c0b 1734 break;
Bartosz Stebel 31:413ba83b8c0b 1735 case COAP_OPTION_URI_QUERY:
Bartosz Stebel 31:413ba83b8c0b 1736 INFOX("URI_QUERY");
Bartosz Stebel 31:413ba83b8c0b 1737 break;
Bartosz Stebel 31:413ba83b8c0b 1738 case COAP_OPTION_ACCEPT:
Bartosz Stebel 31:413ba83b8c0b 1739 INFOX("ACCEPT");
Bartosz Stebel 31:413ba83b8c0b 1740 break;
Bartosz Stebel 31:413ba83b8c0b 1741 case COAP_OPTION_LOCATION_QUERY:
Bartosz Stebel 31:413ba83b8c0b 1742 INFOX("LOCATION_QUERY");
Bartosz Stebel 31:413ba83b8c0b 1743 break;
Bartosz Stebel 31:413ba83b8c0b 1744 case COAP_OPTION_PROXY_URI:
Bartosz Stebel 31:413ba83b8c0b 1745 INFOX("PROXY_URI");
Bartosz Stebel 31:413ba83b8c0b 1746 break;
Bartosz Stebel 31:413ba83b8c0b 1747 case COAP_OPTION_PROXY_SCHEME:
Bartosz Stebel 31:413ba83b8c0b 1748 INFOX("PROXY_SCHEME");
Bartosz Stebel 31:413ba83b8c0b 1749 break;
Bartosz Stebel 31:413ba83b8c0b 1750 case COAP_OPTION_BLOCK1:
Bartosz Stebel 31:413ba83b8c0b 1751 INFOX("BLOCK1");
Bartosz Stebel 31:413ba83b8c0b 1752 break;
Bartosz Stebel 31:413ba83b8c0b 1753 case COAP_OPTION_BLOCK2:
Bartosz Stebel 31:413ba83b8c0b 1754 INFOX("BLOCK2");
Bartosz Stebel 31:413ba83b8c0b 1755 break;
Bartosz Stebel 31:413ba83b8c0b 1756 case COAP_OPTION_SIZE1:
Bartosz Stebel 31:413ba83b8c0b 1757 INFOX("SIZE1");
Bartosz Stebel 31:413ba83b8c0b 1758 break;
Bartosz Stebel 31:413ba83b8c0b 1759 case COAP_OPTION_SIZE2:
Bartosz Stebel 31:413ba83b8c0b 1760 INFOX("SIZE2");
Bartosz Stebel 31:413ba83b8c0b 1761 break;
Bartosz Stebel 31:413ba83b8c0b 1762 default:
Bartosz Stebel 31:413ba83b8c0b 1763 INFOX("Unknown option");
Bartosz Stebel 31:413ba83b8c0b 1764 break;
Bartosz Stebel 31:413ba83b8c0b 1765 }
Bartosz Stebel 31:413ba83b8c0b 1766 INFOX("\r\n");
Bartosz Stebel 31:413ba83b8c0b 1767 INFOX(" Value length: %u\r\n",options[i].optionValueLength);
Bartosz Stebel 31:413ba83b8c0b 1768 INFOX(" Value: \"");
Bartosz Stebel 31:413ba83b8c0b 1769 for(int j=0; j<options[i].optionValueLength; j++) {
Bartosz Stebel 31:413ba83b8c0b 1770 char c = options[i].optionValuePointer[j];
Bartosz Stebel 31:413ba83b8c0b 1771 if((c>='!'&&c<='~')||c==' ') {
Bartosz Stebel 31:413ba83b8c0b 1772 INFOX("%c",c);
Bartosz Stebel 31:413ba83b8c0b 1773 } else {
Bartosz Stebel 31:413ba83b8c0b 1774 INFOX("\\%.2d",c);
Bartosz Stebel 31:413ba83b8c0b 1775 }
Bartosz Stebel 31:413ba83b8c0b 1776 }
Bartosz Stebel 31:413ba83b8c0b 1777 INFOX("\"\r\n");
Bartosz Stebel 31:413ba83b8c0b 1778 }
Bartosz Stebel 31:413ba83b8c0b 1779
Bartosz Stebel 31:413ba83b8c0b 1780 // print payload
Bartosz Stebel 31:413ba83b8c0b 1781 if(_payloadLength==0) {
Bartosz Stebel 31:413ba83b8c0b 1782 INFOX("No payload.\r\n");
Bartosz Stebel 31:413ba83b8c0b 1783 } else {
Bartosz Stebel 31:413ba83b8c0b 1784 INFOX("Payload of %d bytes\r\n",_payloadLength);
Bartosz Stebel 31:413ba83b8c0b 1785 INFOX(" Value: \"");
Bartosz Stebel 31:413ba83b8c0b 1786 for(int j=0; j<_payloadLength; j++) {
Bartosz Stebel 31:413ba83b8c0b 1787 char c = _payloadPointer[j];
Bartosz Stebel 31:413ba83b8c0b 1788 if((c>='!'&&c<='~')||c==' ') {
Bartosz Stebel 31:413ba83b8c0b 1789 INFOX("%c",c);
Bartosz Stebel 31:413ba83b8c0b 1790 } else {
Bartosz Stebel 31:413ba83b8c0b 1791 INFOX("\\%.2x",c);
Bartosz Stebel 31:413ba83b8c0b 1792 }
Bartosz Stebel 31:413ba83b8c0b 1793 }
Bartosz Stebel 31:413ba83b8c0b 1794 INFO("\"\r\n");
Bartosz Stebel 31:413ba83b8c0b 1795 }
Bartosz Stebel 31:413ba83b8c0b 1796 INFOX("__________________\r\n");
Bartosz Stebel 31:413ba83b8c0b 1797 }
Bartosz Stebel 31:413ba83b8c0b 1798
Bartosz Stebel 31:413ba83b8c0b 1799 /// Prints the PDU as a c array (useful for debugging or hardcoding PDUs)
Bartosz Stebel 31:413ba83b8c0b 1800 void CoapPDU::printPDUAsCArray() {
Bartosz Stebel 31:413ba83b8c0b 1801 printf("const uint8_t array[] = {\r\n ");
Bartosz Stebel 31:413ba83b8c0b 1802 for(int i=0; i<_pduLength; i++) {
Bartosz Stebel 31:413ba83b8c0b 1803 printf("0x%.2x, ",_pdu[i]);
Bartosz Stebel 31:413ba83b8c0b 1804 }
Bartosz Stebel 31:413ba83b8c0b 1805 printf("\r\n};\r\n");
Bartosz Stebel 31:413ba83b8c0b 1806 }
Bartosz Stebel 31:413ba83b8c0b 1807
Bartosz Stebel 31:413ba83b8c0b 1808 /// A routine for printing an option in human-readable format.
Bartosz Stebel 31:413ba83b8c0b 1809 /**
Bartosz Stebel 31:413ba83b8c0b 1810 * \param option This is a pointer to where the option begins in the PDU.
Bartosz Stebel 31:413ba83b8c0b 1811 */
Bartosz Stebel 31:413ba83b8c0b 1812 void CoapPDU::printOptionHuman(uint8_t *option) {
Bartosz Stebel 31:413ba83b8c0b 1813 // compute some useful stuff
Bartosz Stebel 31:413ba83b8c0b 1814 uint16_t optionDelta = getOptionDelta(option);
Bartosz Stebel 31:413ba83b8c0b 1815 uint16_t optionValueLength = getOptionValueLength(option);
Bartosz Stebel 31:413ba83b8c0b 1816 int extraDeltaBytes = computeExtraBytes(optionDelta);
Bartosz Stebel 31:413ba83b8c0b 1817 int extraValueLengthBytes = computeExtraBytes(optionValueLength);
Bartosz Stebel 31:413ba83b8c0b 1818 int totalLength = 1+extraDeltaBytes+extraValueLengthBytes+optionValueLength;
Bartosz Stebel 31:413ba83b8c0b 1819
Bartosz Stebel 31:413ba83b8c0b 1820 if(totalLength>_pduLength) {
Bartosz Stebel 31:413ba83b8c0b 1821 totalLength = &_pdu[_pduLength-1]-option;
Bartosz Stebel 31:413ba83b8c0b 1822 DBG("New length: %u",totalLength);
Bartosz Stebel 31:413ba83b8c0b 1823 }
Bartosz Stebel 31:413ba83b8c0b 1824
Bartosz Stebel 31:413ba83b8c0b 1825 // print summary
Bartosz Stebel 31:413ba83b8c0b 1826 DBG("~~~~~~ Option ~~~~~~");
Bartosz Stebel 31:413ba83b8c0b 1827 DBG("Delta: %u, Value length: %u",optionDelta,optionValueLength);
Bartosz Stebel 31:413ba83b8c0b 1828
Bartosz Stebel 31:413ba83b8c0b 1829 // print all bytes
Bartosz Stebel 31:413ba83b8c0b 1830 DBG("All bytes (%d):",totalLength);
Bartosz Stebel 31:413ba83b8c0b 1831 for(int i=0; i<totalLength; i++) {
Bartosz Stebel 31:413ba83b8c0b 1832 if(i%4==0) {
Bartosz Stebel 31:413ba83b8c0b 1833 DBG(" ");
Bartosz Stebel 31:413ba83b8c0b 1834 DBGX(" %.2d ",i);
Bartosz Stebel 31:413ba83b8c0b 1835 }
Bartosz Stebel 31:413ba83b8c0b 1836 CoapPDU::printBinary(option[i]); DBGX(" ");
Bartosz Stebel 31:413ba83b8c0b 1837 }
Bartosz Stebel 31:413ba83b8c0b 1838 DBG(" "); DBG(" ");
Bartosz Stebel 31:413ba83b8c0b 1839
Bartosz Stebel 31:413ba83b8c0b 1840 // print header byte
Bartosz Stebel 31:413ba83b8c0b 1841 DBG("Header byte:");
Bartosz Stebel 31:413ba83b8c0b 1842 DBGX(" ");
Bartosz Stebel 31:413ba83b8c0b 1843 CoapPDU::printBinary(*option++);
Bartosz Stebel 31:413ba83b8c0b 1844 DBG(" "); DBG(" ");
Bartosz Stebel 31:413ba83b8c0b 1845
Bartosz Stebel 31:413ba83b8c0b 1846 // print extended delta bytes
Bartosz Stebel 31:413ba83b8c0b 1847 if(extraDeltaBytes) {
Bartosz Stebel 31:413ba83b8c0b 1848 DBG("Extended delta bytes (%d) in network order: ",extraDeltaBytes);
Bartosz Stebel 31:413ba83b8c0b 1849 DBGX(" ");
Bartosz Stebel 31:413ba83b8c0b 1850 while(extraDeltaBytes--) {
Bartosz Stebel 31:413ba83b8c0b 1851 CoapPDU::printBinary(*option++); DBGX(" ");
Bartosz Stebel 31:413ba83b8c0b 1852 }
Bartosz Stebel 31:413ba83b8c0b 1853 } else {
Bartosz Stebel 31:413ba83b8c0b 1854 DBG("No extended delta bytes");
Bartosz Stebel 31:413ba83b8c0b 1855 }
Bartosz Stebel 31:413ba83b8c0b 1856 DBG(" "); DBG(" ");
Bartosz Stebel 31:413ba83b8c0b 1857
Bartosz Stebel 31:413ba83b8c0b 1858 // print extended value length bytes
Bartosz Stebel 31:413ba83b8c0b 1859 if(extraValueLengthBytes) {
Bartosz Stebel 31:413ba83b8c0b 1860 DBG("Extended value length bytes (%d) in network order: ",extraValueLengthBytes);
Bartosz Stebel 31:413ba83b8c0b 1861 DBGX(" ");
Bartosz Stebel 31:413ba83b8c0b 1862 while(extraValueLengthBytes--) {
Bartosz Stebel 31:413ba83b8c0b 1863 CoapPDU::printBinary(*option++); DBGX(" ");
Bartosz Stebel 31:413ba83b8c0b 1864 }
Bartosz Stebel 31:413ba83b8c0b 1865 } else {
Bartosz Stebel 31:413ba83b8c0b 1866 DBG("No extended value length bytes");
Bartosz Stebel 31:413ba83b8c0b 1867 }
Bartosz Stebel 31:413ba83b8c0b 1868 DBG(" ");
Bartosz Stebel 31:413ba83b8c0b 1869
Bartosz Stebel 31:413ba83b8c0b 1870 // print option value
Bartosz Stebel 31:413ba83b8c0b 1871 DBG("Option value bytes:");
Bartosz Stebel 31:413ba83b8c0b 1872 for(int i=0; i<optionValueLength; i++) {
Bartosz Stebel 31:413ba83b8c0b 1873 if(i%4==0) {
Bartosz Stebel 31:413ba83b8c0b 1874 DBG(" ");
Bartosz Stebel 31:413ba83b8c0b 1875 DBGX(" %.2d ",i);
Bartosz Stebel 31:413ba83b8c0b 1876 }
Bartosz Stebel 31:413ba83b8c0b 1877 CoapPDU::printBinary(*option++);
Bartosz Stebel 31:413ba83b8c0b 1878 DBGX(" ");
Bartosz Stebel 31:413ba83b8c0b 1879 }
Bartosz Stebel 31:413ba83b8c0b 1880 DBG(" ");
Bartosz Stebel 31:413ba83b8c0b 1881 }
Bartosz Stebel 31:413ba83b8c0b 1882
Bartosz Stebel 31:413ba83b8c0b 1883 /// Dumps the PDU header in hex.
Bartosz Stebel 31:413ba83b8c0b 1884 void CoapPDU::printHex() {
Bartosz Stebel 31:413ba83b8c0b 1885 printf("Hexdump dump of PDU\r\n");
Bartosz Stebel 31:413ba83b8c0b 1886 printf("%.2x %.2x %.2x %.2x",_pdu[0],_pdu[1],_pdu[2],_pdu[3]);
Bartosz Stebel 31:413ba83b8c0b 1887 }
Bartosz Stebel 31:413ba83b8c0b 1888
Bartosz Stebel 31:413ba83b8c0b 1889 /// Dumps the entire PDU in binary.
Bartosz Stebel 31:413ba83b8c0b 1890 void CoapPDU::printBin() {
Bartosz Stebel 31:413ba83b8c0b 1891 for(int i=0; i<_pduLength; i++) {
Bartosz Stebel 31:413ba83b8c0b 1892 if(i%4==0) {
Bartosz Stebel 31:413ba83b8c0b 1893 printf("\r\n");
Bartosz Stebel 31:413ba83b8c0b 1894 printf("%.2d ",i);
Bartosz Stebel 31:413ba83b8c0b 1895 }
Bartosz Stebel 31:413ba83b8c0b 1896 CoapPDU::printBinary(_pdu[i]); printf(" ");
Bartosz Stebel 31:413ba83b8c0b 1897 }
Bartosz Stebel 31:413ba83b8c0b 1898 printf("\r\n");
Bartosz Stebel 31:413ba83b8c0b 1899 }
Bartosz Stebel 31:413ba83b8c0b 1900
Bartosz Stebel 31:413ba83b8c0b 1901 /// Prints a single byte in binary.
Bartosz Stebel 31:413ba83b8c0b 1902 void CoapPDU::printBinary(uint8_t b) {
Bartosz Stebel 31:413ba83b8c0b 1903 printf("%d%d%d%d%d%d%d%d",
Bartosz Stebel 31:413ba83b8c0b 1904 (b&0x80)&&0x01,
Bartosz Stebel 31:413ba83b8c0b 1905 (b&0x40)&&0x01,
Bartosz Stebel 31:413ba83b8c0b 1906 (b&0x20)&&0x01,
Bartosz Stebel 31:413ba83b8c0b 1907 (b&0x10)&&0x01,
Bartosz Stebel 31:413ba83b8c0b 1908 (b&0x08)&&0x01,
Bartosz Stebel 31:413ba83b8c0b 1909 (b&0x04)&&0x01,
Bartosz Stebel 31:413ba83b8c0b 1910 (b&0x02)&&0x01,
Bartosz Stebel 31:413ba83b8c0b 1911 (b&0x01)&&0x01);
Bartosz Stebel 31:413ba83b8c0b 1912 }
Bartosz Stebel 31:413ba83b8c0b 1913
Bartosz Stebel 31:413ba83b8c0b 1914 /// Dumps the PDU as a byte sequence to stdout.
Bartosz Stebel 31:413ba83b8c0b 1915 void CoapPDU::print() {
Bartosz Stebel 31:413ba83b8c0b 1916 fwrite(_pdu,1,_pduLength,stdout);
Bartosz Stebel 31:413ba83b8c0b 1917 }