eric liang / cantcoap

Fork of cantcoap by Ashley Mills

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers cantcoap.cpp Source File

cantcoap.cpp

00001 /*
00002 Copyright (c) 2013, Ashley Mills.
00003 All rights reserved.
00004 
00005 Redistribution and use in source and binary forms, with or without
00006 modification, are permitted provided that the following conditions are met: 
00007 
00008 1. Redistributions of source code must retain the above copyright notice, this
00009    list of conditions and the following disclaimer. 
00010 2. Redistributions in binary form must reproduce the above copyright notice,
00011    this list of conditions and the following disclaimer in the documentation
00012    and/or other materials provided with the distribution. 
00013 
00014 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00015 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00016 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00017 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
00018 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00019 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00020 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00021 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00022 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00023 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00024  */
00025 
00026 // version, 2 bits
00027 // type, 2 bits
00028     // 00 Confirmable
00029     // 01 Non-confirmable
00030     // 10 Acknowledgement
00031     // 11 Reset
00032 
00033 // token length, 4 bits
00034 // length of token in bytes (only 0 to 8 bytes allowed)
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037 #include <stdint.h>
00038 #include <string.h>
00039 #include <inet.h>
00040 #include "cantcoap.h"
00041 
00042 // for debugging output you need https://mbed.org/users/donatien/code/DebugLib/
00043 #define __DEBUG__ 0 // INFO
00044 #ifndef __MODULE__
00045    #define __MODULE__ "cantcoap.cpp"
00046 #endif
00047 
00048 
00049 //#include "dbg.h"
00050 // some extra debug stuff
00051 #if __DEBUG__ > 0
00052    #define INFOX(...)  do { fprintf(stderr,__VA_ARGS__); } while(0)
00053    #define INFOLX(...) do { fprintf(stderr,"[INFO] %s:%d ",__MODULE__,__LINE__); fprintf(stderr,__VA_ARGS__); } while(0) 
00054    #define DBGLX(...)  do { fprintf(stderr,"[DBG] %s:%d ",__MODULE__,__LINE__); fprintf(stderr,__VA_ARGS__); } while(0)
00055    #define DBG_PDU()   do { printBin(); } while(0)
00056 #else
00057    #define INFOX(...)  do{} while(0)
00058    #define INFOLX(...) do{} while(0)
00059    #define DBGLX(...)  do{} while(0)
00060    #define DBG_PDU()   do{} while(0)
00061 #endif
00062 
00063 #define DBG(...) do{} while(0)
00064    #define DBGX(...)  do{} while(0)
00065    #define INFO(...)  do{} while(0)   
00066 /// Memory-managed constructor. Buffer for PDU is dynamically sized and allocated by the object.
00067 /**
00068  * When using this constructor, the CoapPDU class will allocate space for the PDU.
00069  * Contrast this with the parameterized constructors, which allow the use of an external buffer.
00070  *
00071  * Note, the PDU container and space can be reused by issuing a CoapPDU::reset(). If the new PDU exceeds the 
00072  * space of the previously allocated memory, then further memory will be dynamically allocated.
00073  *
00074  * Deleting the object will free the Object container and all dynamically allocated memory.
00075  *
00076  * \note It would have been nice to use something like UDP_CORK or MSG_MORE, to allow separate buffers 
00077  * for token, options, and payload but these FLAGS aren't implemented for UDP in LwIP so stuck with one buffer for now.
00078  *
00079  * CoAP version defaults to 1.
00080  *
00081  * \sa CoapPDU::CoapPDU(uint8_t *pdu, int pduLength), CoapPDU::CoapPDU::(uint8_t *buffer, int bufferLength, int pduLength), 
00082  * CoapPDU:CoapPDU()~
00083  *
00084  */
00085 CoapPDU::CoapPDU() {
00086     // pdu
00087     _pdu = (uint8_t*)calloc(4,sizeof(uint8_t));
00088     _pduLength = 4;
00089     _bufferLength = _pduLength;
00090 
00091     //options
00092     _numOptions = 0;
00093     _maxAddedOptionNumber = 0;
00094 
00095     // payload
00096     _payloadPointer = NULL;
00097     _payloadLength = 0;
00098 
00099     _constructedFromBuffer = 0;
00100 
00101     setVersion(1);
00102 }
00103 
00104 /// Construct a PDU using an external buffer. No copy of the buffer is made.
00105 /**
00106  * This constructor is normally used where a PDU has been received over the network, and it's length is known.
00107  * In this case the CoapPDU object is probably going to be used as a temporary container to access member values.
00108  *
00109  * It is assumed that \b pduLength is the length of the actual CoAP PDU, and consequently the buffer will also be this size,
00110  * contrast this with CoapPDU::CoapPDU(uint8_t *buffer, int bufferLength, int pduLength) which allows the buffer to 
00111  * be larger than the PDU.
00112  *
00113  * A PDU constructed in this manner must be validated with CoapPDU::validate() before the member variables will be accessible.
00114  *
00115  * \warning The validation call parses the PDU structure to set some internal parameters. If you do
00116  * not validate the PDU, then the behaviour of member access functions will be undefined.
00117  * 
00118  * The buffer can be reused by issuing a CoapPDU::reset() but the class will not change the size of the buffer. If the
00119  * newly constructed PDU exceeds the size of the buffer, the function called (for example CoapPDU::addOption) will fail.
00120  *
00121  * Deleting this object will only delete the Object container and will not delete the PDU buffer.
00122  *
00123  * @param pdu A pointer to an array of bytes which comprise the CoAP PDU
00124  * @param pduLength The length of the CoAP PDU pointed to by \b pdu
00125 
00126  * \sa CoapPDU::CoapPDU(), CoapPDU::CoapPDU(uint8_t *buffer, int bufferLength, int pduLength)
00127  */
00128 CoapPDU::CoapPDU(uint8_t *pdu, int pduLength) {
00129     int bufferLength = pduLength;
00130     // sanity
00131     if(pduLength<4&&pduLength!=0) {
00132         DBG("PDU cannot have a length less than 4");
00133     }
00134 
00135     // pdu
00136     _pdu = pdu;
00137     _bufferLength = bufferLength;
00138     if(pduLength==0) {
00139         // this is actually a fresh pdu, header always exists
00140         _pduLength = 4;
00141         // make sure header is zeroed
00142         _pdu[0] = 0x00; _pdu[1] = 0x00; _pdu[2] = 0x00; _pdu[3] = 0x00;
00143         setVersion(1);
00144     } else {
00145         _pduLength = pduLength;
00146     }
00147 
00148     _constructedFromBuffer = 1;
00149 
00150     // options
00151     _numOptions = 0;
00152     _maxAddedOptionNumber = 0;
00153 
00154     // payload
00155     _payloadPointer = NULL;
00156     _payloadLength = 0;
00157 }
00158 
00159 /// Construct object from external buffer that may be larger than actual PDU.
00160 /**
00161  * This differs from CoapPDU::CoapPDU(uint8_t *pdu, int pduLength) in that the buffer may be larger
00162  * than the actual CoAP PDU contained int the buffer. This is typically used when a large buffer is reused
00163  * multiple times. Note that \b pduLength can be 0.
00164  * 
00165  * If an actual CoAP PDU is passed in the buffer, \b pduLength should match its length. CoapPDU::validate() must
00166  * be called to initiate the object before member functions can be used.
00167  *
00168  * A PDU constructed in this manner must be validated with CoapPDU::validate() before the member variables will be accessible.
00169  *
00170  * \warning The validation call parses the PDU structure to set some internal parameters. If you do
00171  * not validate the PDU, then the behaviour of member access functions will be undefined.
00172  * 
00173  * The buffer can be reused by issuing a CoapPDU::reset() but the class will not change the size of the buffer. If the
00174  * newly constructed PDU exceeds the size of the buffer, the function called (for example CoapPDU::addOption) will fail.
00175  *
00176  * Deleting this object will only delete the Object container and will not delete the PDU buffer.
00177  *
00178  * \param buffer A buffer which either contains a CoAP PDU or is intended to be used to construct one.
00179  * \param bufferLength The length of the buffer
00180  * \param pduLength If the buffer contains a CoAP PDU, this specifies the length of the PDU within the buffer.
00181  *
00182  * \sa CoapPDU::CoapPDU(), CoapPDU::CoapPDU(uint8_t *pdu, int pduLength)
00183  */
00184 CoapPDU::CoapPDU(uint8_t *buffer, int bufferLength, int pduLength) {
00185     // sanity
00186     if(pduLength<4&&pduLength!=0) {
00187         DBG("PDU cannot have a length less than 4");
00188     }
00189 
00190     // pdu
00191     _pdu = buffer;
00192     _bufferLength = bufferLength;
00193     if(pduLength==0) {
00194         // this is actually a fresh pdu, header always exists
00195         _pduLength = 4;
00196         // make sure header is zeroed
00197         _pdu[0] = 0x00; _pdu[1] = 0x00; _pdu[2] = 0x00; _pdu[3] = 0x00;
00198         setVersion(1);
00199     } else {
00200         _pduLength = pduLength;
00201     }
00202 
00203     _constructedFromBuffer = 1;
00204 
00205     // options
00206     _numOptions = 0;
00207     _maxAddedOptionNumber = 0;
00208 
00209     // payload
00210     _payloadPointer = NULL;
00211     _payloadLength = 0;
00212 }
00213 
00214 /// Reset CoapPDU container so it can be reused to build a new PDU.
00215 /**
00216  * This resets the CoapPDU container, setting the pdu length, option count, etc back to zero. The
00217  * PDU can then be populated as if it were newly constructed.
00218  *
00219  * Note that the space available will depend on how the CoapPDU was originally constructed:
00220  * -# CoapPDU::CoapPDU()
00221  *
00222  *  Available space initially be \b _pduLength. But further space will be allocated as needed on demand, 
00223  *    limited only by the OS/environment.
00224  *
00225  * -# CoapPDU::CoapPDU(uint8_t *pdu, int pduLength)
00226  *
00227  *      Space is limited by the variable \b pduLength. The PDU cannot exceed \b pduLength bytes.
00228  *       
00229  * -# CoapPDU::CoapPDU(uint8_t *buffer, int bufferLength, int pduLength)
00230  *
00231  *      Space is limited by the variable \b bufferLength. The PDU cannot exceed \b bufferLength bytes.
00232  *
00233  * \return 0 on success, 1 on failure.
00234  */
00235 int CoapPDU::reset() {
00236     // pdu
00237     memset(_pdu,0x00,_bufferLength);
00238     // packet always has at least a header
00239     _pduLength = 4;
00240 
00241     // options
00242     _numOptions = 0;
00243     _maxAddedOptionNumber = 0;
00244     // payload
00245     _payloadPointer = NULL;
00246     _payloadLength = 0;
00247     return 0;
00248 }
00249 
00250 /// Validates a PDU constructed using an external buffer.
00251 /**
00252  * When a CoapPDU is constructed using an external buffer, the programmer must call this function to
00253  * check that the received PDU is a valid CoAP PDU.
00254  *
00255  * \warning The validation call parses the PDU structure to set some internal parameters. If you do
00256  * not validate the PDU, then the behaviour of member access functions will be undefined.
00257  *
00258  * \return 1 if the PDU validates correctly, 0 if not. XXX maybe add some error codes
00259  */
00260 int CoapPDU::validate() {
00261     if(_pduLength<4) {
00262         DBG("PDU has to be a minimum of 4 bytes. This: %d bytes",_pduLength);
00263         return 0;
00264     }
00265 
00266     // check header
00267     //   0                   1                   2                   3
00268    //  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
00269    // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00270    // |Ver| T |  TKL  |      Code     |          Message ID           |
00271    // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00272    // |   Token (if any, TKL bytes) ...
00273    // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00274    // |   Options (if any) ...
00275    // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00276    // |1 1 1 1 1 1 1 1|    Payload (if any) ...
00277    // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00278 
00279     DBG("Version: %d",getVersion());
00280     DBG("Type: %d",getType());
00281 
00282     // token length must be between 0 and 8
00283     int tokenLength = getTokenLength();
00284     if(tokenLength<0||tokenLength>8) {
00285         DBG("Invalid token length: %d",tokenLength);
00286         return 0;
00287     }
00288     DBG("Token length: %d",tokenLength);
00289     // check total length
00290     if((COAP_HDR_SIZE+tokenLength)>_pduLength) {
00291         DBG("Token length would make pdu longer than actual length.");
00292         return 0;
00293     }
00294 
00295     // check that code is valid
00296     CoapPDU::Code code = getCode(); 
00297     if(code<COAP_EMPTY ||
00298         (code>COAP_DELETE&&code<COAP_CREATED) ||
00299         (code>COAP_CONTENT&&code<COAP_BAD_REQUEST) ||
00300         (code>COAP_NOT_ACCEPTABLE&&code<COAP_PRECONDITION_FAILED) ||
00301         (code==0x8E) ||
00302         (code>COAP_UNSUPPORTED_CONTENT_FORMAT&&code<COAP_INTERNAL_SERVER_ERROR) ||
00303         (code>COAP_PROXYING_NOT_SUPPORTED) ) {
00304         DBG("Invalid CoAP code: %d",code);
00305         return 0;
00306     }
00307     DBG("CoAP code: %d",code);
00308 
00309     // token can be anything so nothing to check
00310 
00311     // check that options all make sense
00312     uint16_t optionDelta =0, optionNumber = 0, optionValueLength = 0;
00313     int totalLength = 0;
00314 
00315     // first option occurs after token
00316     int optionPos = COAP_HDR_SIZE + getTokenLength();
00317 
00318     // may be 0 options
00319     if(optionPos==_pduLength) {
00320         DBG("No options. No payload.");
00321         _numOptions = 0;
00322         _payloadLength = 0;
00323         return 1;
00324     }
00325 
00326     int bytesRemaining = _pduLength-optionPos;
00327     int numOptions = 0;
00328     uint8_t upperNibble = 0x00, lowerNibble = 0x00;
00329 
00330     // walk over options and record information
00331     while(1) {
00332         // check for payload marker
00333         if(bytesRemaining>0) {
00334             uint8_t optionHeader = _pdu[optionPos];
00335             if(optionHeader==0xFF) {
00336                 // payload
00337                 if(bytesRemaining>1) {
00338                     _payloadPointer = &_pdu[optionPos+1];
00339                     _payloadLength = (bytesRemaining-1);
00340                     _numOptions = numOptions;
00341                     DBG("Payload found, length: %d",_payloadLength);
00342                     return 1;
00343                 }
00344                 // payload marker but no payload
00345                 _payloadPointer = NULL;
00346                 _payloadLength = 0;
00347                 DBG("Payload marker but no payload.");
00348                 return 0;
00349             }
00350 
00351             // check that option delta and option length are valid values
00352             upperNibble = (optionHeader & 0xF0) >> 4;
00353             lowerNibble = (optionHeader & 0x0F);
00354             if(upperNibble==0x0F||lowerNibble==0x0F) {
00355                 DBG("Expected option header or payload marker, got: 0x%x%x",upperNibble,lowerNibble);
00356                 return 0;
00357             }
00358             DBG("Option header byte appears sane: 0x%x%x",upperNibble,lowerNibble);
00359         } else {
00360             DBG("No more data. No payload.");
00361             _payloadPointer = NULL;
00362             _payloadLength = 0;
00363             _numOptions = numOptions;
00364             return 1;
00365         }
00366 
00367         // skip over option header byte
00368         bytesRemaining--;
00369 
00370         // check that there is enough space for the extended delta and length bytes (if any)
00371         int headerBytesNeeded = computeExtraBytes(upperNibble);
00372         DBG("%d extra bytes needed for extended delta",headerBytesNeeded);
00373         if(headerBytesNeeded>bytesRemaining) {
00374             DBG("Not enough space for extended option delta, needed %d, have %d.",headerBytesNeeded,bytesRemaining);
00375             return 0;
00376         }
00377         headerBytesNeeded += computeExtraBytes(lowerNibble);
00378         if(headerBytesNeeded>bytesRemaining) {
00379             DBG("Not enough space for extended option length, needed %d, have %d.",
00380                 (headerBytesNeeded-computeExtraBytes(upperNibble)),bytesRemaining);
00381             return 0;
00382         }
00383         DBG("Enough space for extended delta and length: %d, continuing.",headerBytesNeeded);
00384 
00385         // extract option details
00386         optionDelta = getOptionDelta(&_pdu[optionPos]);
00387         optionNumber += optionDelta;
00388         optionValueLength = getOptionValueLength(&_pdu[optionPos]);
00389         DBG("Got option: %d with length %d",optionNumber,optionValueLength);
00390         // compute total length
00391         totalLength = 1; // mandatory header
00392         totalLength += computeExtraBytes(optionDelta);
00393         totalLength += computeExtraBytes(optionValueLength);
00394         totalLength += optionValueLength;
00395         // check there is enough space
00396         if(optionPos+totalLength>_pduLength) {
00397             DBG("Not enough space for option payload, needed %d, have %d.",(totalLength-headerBytesNeeded-1),_pduLength-optionPos);
00398             return 0;
00399         }
00400         DBG("Enough space for option payload: %d %d",optionValueLength,(totalLength-headerBytesNeeded-1));
00401 
00402         // recompute bytesRemaining
00403         bytesRemaining -= totalLength;
00404         bytesRemaining++; // correct for previous --
00405 
00406         // move to next option
00407         optionPos += totalLength; 
00408 
00409         // inc number of options XXX
00410         numOptions++;
00411     }
00412 
00413     return 1;
00414 }
00415 
00416 /// Destructor. Does not free buffer if constructor passed an external buffer.
00417 /**
00418  * The destructor acts differently, depending on how the object was initially constructed (from buffer or not):
00419  *
00420  * -# CoapPDU::CoapPDU()
00421  *
00422  *  Complete object is destroyed.
00423  *
00424  * -# CoapPDU::CoapPDU(uint8_t *pdu, int pduLength)
00425  *
00426  *      Only object container is destroyed. \b pdu is left intact.
00427  *       
00428  * -# CoapPDU::CoapPDU(uint8_t *buffer, int bufferLength, int pduLength)
00429  *
00430  *      Only object container is destroyed. \b pdu is left intact.
00431  *
00432  */
00433 CoapPDU::~CoapPDU() {
00434     if(!_constructedFromBuffer) {
00435         free(_pdu);
00436     }
00437 }
00438 
00439 /// Returns a pointer to the internal buffer.
00440 uint8_t* CoapPDU::getPDUPointer() {
00441     return _pdu;
00442 }
00443 
00444 /// Set the PDU length to the length specified.
00445 /**
00446  * This is used when re-using a PDU container before calling CoapPDU::validate() as it
00447  * is not possible to deduce the length of a PDU since the payload has no length marker.
00448  * \param len The length of the PDU
00449  */
00450 void CoapPDU::setPDULength(int len) {
00451     _pduLength = len;
00452 }
00453 
00454 /// Shorthand function for setting a resource URI.
00455 /**
00456  * Calls CoapPDU::setURI(uri,strlen(uri).
00457  */
00458 int CoapPDU::setURI(char *uri) {
00459     return setURI(uri,strlen(uri));
00460 }
00461 
00462 /// Shorthand function for setting a resource URI.
00463 /**
00464  * This will parse the supplied \b uri and construct enough URI_PATH CoAP options to encode it.
00465  * The options are added to the PDU.
00466  * 
00467  * At present queries are not handled. TODO Implement queries.
00468  *
00469  * \note This uses an internal buffer of 16 bytes to manipulate strings. The internal buffer will be
00470  * expanded dynamically if necessary (path component longer than 16 bytes). The internal buffer will
00471  * be freed before the function returns.
00472  * 
00473  * \param uri The uri to parse.
00474  * \param urilen The length of the uri to parse.
00475  *
00476  * \return 1 on success, 0 on failure.
00477  */
00478 int CoapPDU::setURI(char *uri, int urilen) {
00479     // only '/' and alphabetic chars allowed
00480     // very simple splitting done
00481 
00482     // sanitation
00483     if(urilen<=0||uri==NULL) {
00484         DBG("Null or zero-length uri passed.");
00485         return 1;
00486     }
00487 
00488     // single character URI path (including '/' case)
00489     if(urilen==1) {
00490         addOption(COAP_OPTION_URI_PATH,1,(uint8_t*)uri);
00491         return 0;
00492     }
00493 
00494     // local vars
00495     char *startP=uri,*endP=NULL;
00496     int oLen = 0;
00497     int bufSpace = 16;
00498     char *uriBuf = (char*)malloc(bufSpace*sizeof(char));
00499     if(uriBuf==NULL) {
00500         DBG("Error allocating temporary memory.");
00501         return 1;
00502     }
00503 
00504     while(1) {
00505         // stop at end of string
00506         if(*startP==0x00||*(startP+1)==0x00) {
00507             break;
00508         }
00509 
00510         // ignore leading slash
00511         if(*startP=='/') {
00512             DBG("Skipping leading slash");
00513             startP++;
00514         }
00515 
00516         // find next split point
00517         endP = strchr(startP,'/');
00518 
00519         // might not be another slash
00520         if(endP==NULL) {
00521             DBG("Ending out of slash");
00522             endP = uri+urilen;
00523         }
00524 
00525         // get length of segment
00526         oLen = endP-startP;
00527 
00528         // copy sequence, make space if necessary
00529         if((oLen+1)>bufSpace) {
00530             char *newBuf = (char*)realloc(uriBuf,oLen+1);
00531             if(newBuf==NULL) {
00532                 DBG("Error making space for temporary buffer");
00533                 free(uriBuf);
00534                 return 1;
00535             }
00536             uriBuf = newBuf;
00537         }
00538 
00539         // copy into temporary buffer
00540         memcpy(uriBuf,startP,oLen);
00541         uriBuf[oLen] = 0x00;
00542         DBG("Adding URI_PATH %s",uriBuf);
00543         // add option
00544         if(addOption(COAP_OPTION_URI_PATH,oLen,(uint8_t*)uriBuf)!=0) {
00545             DBG("Error adding option");
00546             return 1;
00547         }
00548         startP = endP;
00549     }
00550 
00551     // clean up
00552     free(uriBuf);
00553     return 0;
00554 }
00555 /// Shorthand for adding a URI QUERY to the option list.
00556 /**
00557  * Adds a new option to the CoAP PDU that encodes a URI_QUERY.
00558  *
00559  * \param query The uri query to encode.
00560  * \return 0 on success, 1 on failure.
00561  */
00562 int CoapPDU::addURIQuery(char *query) {
00563     return addOption(COAP_OPTION_URI_QUERY,strlen(query),(uint8_t*)query);
00564 }
00565 
00566 /// Concatenates any URI_PATH elements into a single string.
00567 /**
00568  * Parses the PDU options and extracts all URI_PATH elements, concatenating them into a single string with slash separators.
00569  * The produced string will be null terminated.
00570  * 
00571  * \param dst Buffer into which to copy the concatenated path elements.
00572  * \param dstlen Length of buffer.
00573  * \param outLen Pointer to integer, into which URI length will be placed.
00574  *
00575  * \return 0 on success, 1 on failure. \b outLen will contain the length of the concatenated elements.
00576  */
00577 int CoapPDU::getURI(char *dst, int dstlen, int *outLen) {
00578     if(outLen==NULL) {
00579         DBG("Output length pointer is NULL");
00580         return 1;
00581     }
00582 
00583     if(dst==NULL) {
00584         DBG("NULL destination buffer");
00585         *outLen = 0;
00586         return 1;
00587     }
00588 
00589     // check destination space
00590     if(dstlen<=0) {
00591         *dst = 0x00;
00592         *outLen = 0;
00593         DBG("Destination buffer too small (0)!");
00594         return 1;
00595     }
00596     // check option count
00597     if(_numOptions==0) {
00598         *dst = 0x00;
00599         *outLen = 0;
00600         return 0;
00601     }
00602     // get options
00603     CoapPDU::CoapOption *options = getOptions();
00604     if(options==NULL) {
00605         *dst = 0x00;
00606         *outLen = 0;
00607         return 0;
00608     }
00609     // iterate over options to construct URI
00610     CoapOption *o = NULL;
00611     int bytesLeft = dstlen-1; // space for 0x00
00612     int oLen = 0;
00613     // add slash at beggining
00614     if(bytesLeft>=1) {
00615         *dst = '/';
00616         dst++;
00617         bytesLeft--;
00618     } else {
00619         DBG("No space for initial slash needed 1, got %d",bytesLeft);
00620         return 1;
00621     }
00622     for(int i=0; i<_numOptions; i++) {
00623         o = &options[i];
00624         oLen = o->optionValueLength;
00625         if(o->optionNumber==COAP_OPTION_URI_PATH) {
00626             // check space
00627             if(oLen>bytesLeft) {
00628                 DBG("Destination buffer too small, needed %d, got %d",oLen,bytesLeft);
00629                 return 1;
00630             }
00631 
00632             // case where single '/' exists
00633             if(oLen==1&&o->optionValuePointer[0]=='/') {
00634                 *dst = 0x00;
00635                 *outLen = 1;
00636                 return 0;
00637             }
00638 
00639             // copy URI path component
00640             memcpy(dst,o->optionValuePointer,oLen);
00641 
00642             // adjust counters
00643             dst += oLen;
00644             bytesLeft -= oLen;
00645 
00646             // add slash following (don't know at this point if another option is coming)
00647             if(bytesLeft>=1) {
00648                 *dst = '/';
00649                 dst++;
00650                 bytesLeft--;
00651             } else {
00652                 DBG("Ran out of space after processing option");
00653                 return 1;
00654             }
00655         }
00656     }
00657 
00658     // remove terminating slash
00659     dst--;
00660     bytesLeft++;
00661     // add null terminating byte (always space since reserved)
00662     *dst = 0x00;
00663     *outLen = (dstlen-1)-bytesLeft;
00664     return 0;
00665 }
00666 
00667 /// Sets the CoAP version.
00668 /**
00669  * \param version CoAP version between 0 and 3.
00670  * \return 0 on success, 1 on failure.
00671  */
00672 int CoapPDU::setVersion(uint8_t version) {
00673     if(version>3) {
00674         return 0;
00675     }
00676 
00677     _pdu[0] &= 0x3F;
00678     _pdu[0] |= (version << 6);
00679     return 1;
00680 }
00681         
00682 /**
00683  * Gets the CoAP Version.
00684  * @return The CoAP version between 0 and 3.
00685  */
00686 uint8_t CoapPDU::getVersion() {
00687     return (_pdu[0]&0xC0)>>6;
00688 }
00689 
00690 /**
00691  * Sets the type of this CoAP PDU. 
00692  * \param mt The type, one of: 
00693  * - COAP_CONFIRMABLE
00694  * - COAP_NON_CONFIRMABLE
00695  * - COAP_ACKNOWLEDGEMENT
00696  * - COAP_RESET.
00697  */
00698 void CoapPDU::setType(CoapPDU::Type mt) {
00699     _pdu[0] &= 0xCF;
00700     _pdu[0] |= mt;
00701 }
00702 
00703 /// Returns the type of the PDU.
00704 CoapPDU::Type CoapPDU::getType() {
00705     return (CoapPDU::Type)(_pdu[0]&0x30);
00706 }
00707 
00708 
00709 /// Set the token length.
00710 /**
00711  * \param tokenLength The length of the token in bytes, between 0 and 8.
00712  * \return 0 on success, 1 on failure.
00713  */
00714 int CoapPDU::setTokenLength(uint8_t tokenLength) {
00715     if(tokenLength>8)
00716         return 1;
00717 
00718     _pdu[0] &= 0xF0;
00719     _pdu[0] |= tokenLength;
00720     return 0;
00721 }
00722 
00723 /// Returns the token length.
00724 int CoapPDU::getTokenLength() {
00725     return _pdu[0] & 0x0F;
00726 }
00727 
00728 /// Returns a pointer to the PDU token.
00729 uint8_t* CoapPDU::getTokenPointer() {
00730     if(getTokenLength()==0) {
00731         return NULL;
00732     }
00733     return &_pdu[4];
00734 }
00735 
00736 /// Set the PDU token to the supplied byte sequence.
00737 /**
00738  * This sets the PDU token to \b token and sets the token length to \b tokenLength.
00739  * \param token A sequence of bytes representing the token.
00740  * \param tokenLength The length of the byte sequence.
00741  * \return 0 on success, 1 on failure.
00742  */
00743 int CoapPDU::setToken(uint8_t *token, uint8_t tokenLength) {
00744     DBG("Setting token");
00745     if(token==NULL) {
00746         DBG("NULL pointer passed as token reference");
00747         return 1;
00748     }
00749 
00750     if(tokenLength==0) {
00751         DBG("Token has zero length");
00752         return 1;
00753     }
00754 
00755     // if tokenLength has not changed, just copy the new value
00756     uint8_t oldTokenLength = getTokenLength();
00757     if(tokenLength==oldTokenLength) {
00758         memcpy((void*)&_pdu[4],token,tokenLength);
00759         return 0;
00760     }
00761 
00762     // otherwise compute new length of PDU
00763     uint8_t oldPDULength = _pduLength;
00764     _pduLength -= oldTokenLength;
00765     _pduLength += tokenLength;
00766 
00767     // now, have to shift old memory around, but shift direction depends
00768     // whether pdu is now bigger or smaller
00769     if(_pduLength>oldPDULength) {
00770         // new PDU is bigger, need to allocate space for new PDU
00771         if(!_constructedFromBuffer) {
00772             uint8_t *newMemory = (uint8_t*)realloc(_pdu,_pduLength);
00773             if(newMemory==NULL) {
00774                 // malloc failed
00775                 DBG("Failed to allocate memory for token");
00776                 _pduLength = oldPDULength;
00777                 return 1;
00778             }
00779             _pdu = newMemory;
00780             _bufferLength = _pduLength;
00781         } else {
00782             // constructed from buffer, check space
00783             if(_pduLength>_bufferLength) {
00784                 DBG("Buffer too small to contain token, needed %d, got %d.",_pduLength-oldPDULength,_bufferLength-oldPDULength);
00785                 _pduLength = oldPDULength;
00786                 return 1;
00787             }
00788         }
00789 
00790         // and then shift everything after token up to end of new PDU
00791         // memory overlaps so do this manually so to avoid additional mallocs
00792         int shiftOffset = _pduLength-oldPDULength;
00793         int shiftAmount = _pduLength-tokenLength-COAP_HDR_SIZE; // everything after token
00794         shiftPDUUp(shiftOffset,shiftAmount);
00795 
00796         // now copy the token into the new space and set official token length
00797         memcpy((void*)&_pdu[4],token,tokenLength);
00798         setTokenLength(tokenLength);
00799 
00800         // and return success
00801         return 0;
00802     }
00803 
00804     // new PDU is smaller, copy the new token value over the old one
00805     memcpy((void*)&_pdu[4],token,tokenLength);
00806     // and shift everything after the new token down
00807     int startLocation = COAP_HDR_SIZE+tokenLength;
00808     int shiftOffset = oldPDULength-_pduLength;
00809     int shiftAmount = oldPDULength-oldTokenLength-COAP_HDR_SIZE;
00810     shiftPDUDown(startLocation,shiftOffset,shiftAmount);
00811     // then reduce size of buffer
00812     if(!_constructedFromBuffer) {
00813         uint8_t *newMemory = (uint8_t*)realloc(_pdu,_pduLength);
00814         if(newMemory==NULL) {
00815             // malloc failed, PDU in inconsistent state
00816             DBG("Failed to shrink PDU for new token. PDU probably broken");
00817             return 1;
00818         }
00819         _pdu = newMemory;
00820         _bufferLength = _pduLength;
00821     }
00822 
00823     // and officially set the new tokenLength
00824     setTokenLength(tokenLength);
00825     return 0;
00826 }
00827 
00828 /// Sets the CoAP response code
00829 void CoapPDU::setCode(CoapPDU::Code code) {
00830     _pdu[1] = code;
00831     // there is a limited set of response codes
00832 }
00833 
00834 /// Gets the CoAP response code
00835 CoapPDU::Code CoapPDU::getCode() {
00836     return (CoapPDU::Code)_pdu[1];
00837 }
00838 
00839 
00840 /// Converts a http status code as an integer, to a CoAP code.
00841 /**
00842  * \param httpStatus the HTTP status code as an integer (e.g 200)
00843  * \return The correct corresponding CoapPDU::Code on success,
00844  * CoapPDU::COAP_UNDEFINED_CODE on failure.
00845  */
00846 CoapPDU::Code CoapPDU::httpStatusToCode(int httpStatus) {
00847     switch(httpStatus) {
00848         case 1:
00849             return CoapPDU::COAP_GET;
00850         case 2:
00851             return CoapPDU::COAP_POST;
00852         case 3:
00853             return CoapPDU::COAP_PUT;
00854         case 4:
00855             return CoapPDU::COAP_DELETE;
00856         case 201:
00857             return CoapPDU::COAP_CREATED;
00858         case 202:
00859             return CoapPDU::COAP_DELETED;
00860         case 203:
00861             return CoapPDU::COAP_VALID;
00862         case 204:
00863             return CoapPDU::COAP_CHANGED;
00864         case 205:
00865             return CoapPDU::COAP_CONTENT;
00866         case 400:
00867             return CoapPDU::COAP_BAD_REQUEST;
00868         case 401:
00869             return CoapPDU::COAP_UNAUTHORIZED;
00870         case 402:
00871             return CoapPDU::COAP_BAD_OPTION;
00872         case 403:
00873             return CoapPDU::COAP_FORBIDDEN;
00874         case 404:
00875             return CoapPDU::COAP_NOT_FOUND;
00876         case 405:
00877             return CoapPDU::COAP_METHOD_NOT_ALLOWED;
00878         case 406:
00879             return CoapPDU::COAP_NOT_ACCEPTABLE;
00880         case 412:
00881             return CoapPDU::COAP_PRECONDITION_FAILED;
00882         case 413:
00883             return CoapPDU::COAP_REQUEST_ENTITY_TOO_LARGE;
00884         case 415:
00885             return CoapPDU::COAP_UNSUPPORTED_CONTENT_FORMAT;
00886         case 500:
00887             return CoapPDU::COAP_INTERNAL_SERVER_ERROR;
00888         case 501:
00889             return CoapPDU::COAP_NOT_IMPLEMENTED;
00890         case 502:
00891             return CoapPDU::COAP_BAD_GATEWAY;
00892         case 503:
00893             return CoapPDU::COAP_SERVICE_UNAVAILABLE;
00894         case 504:
00895             return CoapPDU::COAP_GATEWAY_TIMEOUT;
00896         case 505:
00897             return CoapPDU::COAP_PROXYING_NOT_SUPPORTED;
00898         default:
00899             return CoapPDU::COAP_UNDEFINED_CODE;
00900     }
00901 }
00902 
00903 /// Set messageID to the supplied value.
00904 /**
00905  * \param messageID A 16bit message id.
00906  * \return 0 on success, 1 on failure.
00907  */
00908 int CoapPDU::setMessageID(uint16_t messageID) {
00909     // message ID is stored in network byte order
00910     uint16_t networkOrder = htons(messageID);
00911     // bytes 2 and 3 hold the ID
00912     _pdu[2] &= 0x00;
00913     _pdu[2] |= (networkOrder >> 8);    // MSB
00914     _pdu[3] &= 0x00;
00915     _pdu[3] |= (networkOrder & 0x00FF); // LSB
00916     return 0;
00917 }
00918 
00919 /// Returns the 16 bit message ID of the PDU.
00920 uint16_t CoapPDU::getMessageID() {
00921     // mesasge ID is stored in network byteorder
00922     uint16_t networkOrder = 0x0000;
00923     networkOrder |= _pdu[2];
00924     networkOrder <<= 8;
00925     networkOrder |= _pdu[3];
00926     return ntohs(networkOrder);
00927 }
00928 
00929 /// Returns the length of the PDU.
00930 int CoapPDU::getPDULength() {
00931     return _pduLength;
00932 }
00933 
00934 /// Return the number of options that the PDU has.
00935 int CoapPDU::getNumOptions() {
00936     return _numOptions;
00937 }
00938 
00939 
00940 /**
00941  * This returns the options as a sequence of structs.
00942  */
00943 CoapPDU::CoapOption* CoapPDU::getOptions() {
00944     DBG("getOptions() called, %d options.",_numOptions);
00945 
00946     uint16_t optionDelta =0, optionNumber = 0, optionValueLength = 0;
00947     int totalLength = 0;
00948 
00949     if(_numOptions==0) {
00950         return NULL;
00951     }
00952 
00953     // malloc space for options
00954     CoapOption *options = (CoapOption*)malloc(_numOptions*sizeof(CoapOption));
00955 
00956     // first option occurs after token
00957     int optionPos = COAP_HDR_SIZE + getTokenLength();
00958 
00959     // walk over options and record information
00960     for(int i=0; i<_numOptions; i++) {
00961         // extract option details
00962         optionDelta = getOptionDelta(&_pdu[optionPos]);
00963         optionNumber += optionDelta;
00964         optionValueLength = getOptionValueLength(&_pdu[optionPos]);
00965         // compute total length
00966         totalLength = 1; // mandatory header
00967         totalLength += computeExtraBytes(optionDelta);
00968         totalLength += computeExtraBytes(optionValueLength);
00969         totalLength += optionValueLength;
00970         // record option details
00971         options[i].optionNumber = optionNumber;
00972         options[i].optionDelta = optionDelta;
00973         options[i].optionValueLength = optionValueLength;
00974         options[i].totalLength = totalLength;
00975         options[i].optionPointer = &_pdu[optionPos];
00976         options[i].optionValuePointer = &_pdu[optionPos+totalLength-optionValueLength];
00977         // move to next option
00978         optionPos += totalLength; 
00979     }
00980 
00981     return options;
00982 }
00983 
00984 /// Add an option to the PDU.
00985 /**
00986  * Unlike other implementations, options can be added in any order, and in-memory manipulation will be
00987  * performed to ensure the correct ordering of options (they use a delta encoding of option numbers).
00988  * Re-ordering memory like this incurs a small performance cost, so if you care about this, then you
00989  * might want to add options in ascending order of option number.
00990  * \param optionNumber The number of the option, see the enum CoapPDU::Option for shorthand notations.
00991  * \param optionLength The length of the option payload in bytes.
00992  * \param optionValue A pointer to the byte sequence that is the option payload (bytes will be copied).
00993  * \return 0 on success, 1 on failure.
00994  */
00995 int CoapPDU::addOption(uint16_t insertedOptionNumber, uint16_t optionValueLength, uint8_t *optionValue) {
00996     // this inserts the option in memory, and re-computes the deltas accordingly
00997     // prevOption <-- insertionPosition
00998     // nextOption
00999 
01000     // find insertion location and previous option number
01001     uint16_t prevOptionNumber = 0; // option number of option before insertion point
01002     int insertionPosition = findInsertionPosition(insertedOptionNumber,&prevOptionNumber);
01003     DBG("inserting option at position %d, after option with number: %hu",insertionPosition,prevOptionNumber);
01004 
01005     // compute option delta length
01006     uint16_t optionDelta = insertedOptionNumber-prevOptionNumber;
01007     uint8_t extraDeltaBytes = computeExtraBytes(optionDelta);
01008 
01009     // compute option length length
01010     uint16_t extraLengthBytes = computeExtraBytes(optionValueLength);
01011 
01012     // compute total length of option
01013     uint16_t optionLength = COAP_OPTION_HDR_BYTE + extraDeltaBytes + extraLengthBytes + optionValueLength;
01014 
01015     // if this is at the end of the PDU, job is done, just malloc and insert
01016     if(insertionPosition==_pduLength) {
01017         DBG("Inserting at end of PDU");
01018         // optionNumber must be biggest added
01019         _maxAddedOptionNumber = insertedOptionNumber;
01020 
01021         // set new PDU length and allocate space for extra option
01022         int oldPDULength = _pduLength;
01023         _pduLength += optionLength;
01024         if(!_constructedFromBuffer) {
01025             uint8_t *newMemory = (uint8_t*)realloc(_pdu,_pduLength);
01026             if(newMemory==NULL) {
01027                 DBG("Failed to allocate memory for option.");
01028                 _pduLength = oldPDULength;
01029                 // malloc failed
01030                 return 1;
01031             }
01032             _pdu = newMemory;
01033             _bufferLength = _pduLength;
01034         } else {
01035             // constructed from buffer, check space
01036             if(_pduLength>_bufferLength) {
01037                 DBG("Buffer too small for new option: needed %d, got %d.",_pduLength-oldPDULength,_bufferLength-oldPDULength);
01038                 _pduLength = oldPDULength;
01039                 return 1;
01040             }
01041         }
01042         
01043         // insert option at position
01044         insertOption(insertionPosition,optionDelta,optionValueLength,optionValue);
01045         _numOptions++;
01046         return 0;
01047     }
01048     // XXX could do 0xFF pdu payload case for changing of dynamically allocated application space SDUs < yeah, if you're insane
01049 
01050     // the next option might (probably) needs it's delta changing
01051     // I want to take this into account when allocating space for the new
01052     // option, to avoid having to do two mallocs, first get info about this option
01053     int nextOptionDelta = getOptionDelta(&_pdu[insertionPosition]);
01054     int nextOptionNumber = prevOptionNumber + nextOptionDelta;
01055     int nextOptionDeltaBytes = computeExtraBytes(nextOptionDelta);
01056     // recompute option delta, relative to inserted option
01057     int newNextOptionDelta = nextOptionNumber-insertedOptionNumber;
01058     int newNextOptionDeltaBytes = computeExtraBytes(newNextOptionDelta);
01059     // determine adjustment
01060     int optionDeltaAdjustment = newNextOptionDeltaBytes-nextOptionDeltaBytes;
01061 
01062     // create space for new option, including adjustment space for option delta
01063     DBG_PDU();
01064     DBG("Creating space");
01065     int mallocLength = optionLength+optionDeltaAdjustment;
01066     int oldPDULength = _pduLength;
01067     _pduLength += mallocLength;
01068 
01069     if(!_constructedFromBuffer) {
01070         uint8_t *newMemory = (uint8_t*)realloc(_pdu,_pduLength);
01071         if(newMemory==NULL) {
01072             DBG("Failed to allocate memory for option");
01073             _pduLength = oldPDULength;
01074             return 1; 
01075         }
01076         _pdu = newMemory;
01077         _bufferLength = _pduLength;
01078     } else {
01079         // constructed from buffer, check space
01080         if(_pduLength>_bufferLength) {
01081             DBG("Buffer too small to contain option, needed %d, got %d.",_pduLength-oldPDULength,_bufferLength-oldPDULength);
01082             _pduLength = oldPDULength;
01083             return 1;
01084         }
01085     }
01086 
01087     // move remainder of PDU data up to create hole for new option
01088     DBG_PDU();
01089     DBG("Shifting PDU.");
01090     shiftPDUUp(mallocLength,_pduLength-(insertionPosition+mallocLength));
01091     DBG_PDU();
01092 
01093     // adjust option delta bytes of following option
01094     // move the option header to the correct position
01095     int nextHeaderPos = insertionPosition+mallocLength;
01096     _pdu[nextHeaderPos-optionDeltaAdjustment] = _pdu[nextHeaderPos];
01097     nextHeaderPos -= optionDeltaAdjustment;
01098     // and set the new value
01099     setOptionDelta(nextHeaderPos, newNextOptionDelta);
01100 
01101     // new option shorter
01102     // p p n n x x x x x
01103     // p p n n x x x x x -
01104     // p p - n n x x x x x
01105     // p p - - n x x x x x
01106     // p p o o n x x x x x
01107 
01108     // new option longer
01109     // p p n n x x x x x
01110     // p p n n x x x x x - - -
01111     // p p - - - n n x x x x x
01112     // p p - - n n n x x x x x
01113     // p p o o n n n x x x x x
01114 
01115     // note, it can only ever be shorter or the same since if an option was inserted the delta got smaller
01116     // but I'll leave that little comment in, just to show that it would work even if the delta got bigger
01117 
01118     // now insert the new option into the gap
01119     DBGLX("Inserting new option...");
01120     insertOption(insertionPosition,optionDelta,optionValueLength,optionValue);
01121     DBGX("done\r\n");
01122     DBG_PDU();
01123 
01124     // done, mark it with B! 
01125     return 0;
01126 }
01127 
01128 /// Allocate space for a payload.
01129 /**
01130  * For dynamically constructed PDUs, this will allocate space for a payload in the object
01131  * and return a pointer to it. If the PDU was constructed from a buffer, this doesn't
01132  * malloc anything, it just changes the _pduLength and returns the payload pointer.
01133  *
01134  * \note The pointer returned points into the PDU buffer.
01135  * \param len The length of the payload buffer to allocate.
01136  * \return Either a pointer to the payload buffer, or NULL if there wasn't enough space / allocation failed.
01137  */
01138 uint8_t* CoapPDU::mallocPayload(int len) {
01139     DBG("Entering mallocPayload");
01140     // sanity checks
01141     if(len==0) {
01142         DBG("Cannot allocate a zero length payload");
01143         return NULL;
01144     }
01145 
01146     // further sanity
01147     if(len==_payloadLength) {
01148         DBG("Space for payload of specified length already exists");
01149         if(_payloadPointer==NULL) {
01150             DBG("Garbage PDU. Payload length is %d, but existing _payloadPointer NULL",_payloadLength);
01151             return NULL;
01152         }
01153         return _payloadPointer;
01154     }
01155 
01156     DBG("_bufferLength: %d, _pduLength: %d, _payloadLength: %d",_bufferLength,_pduLength,_payloadLength);
01157 
01158     // might be making payload bigger (including bigger than 0) or smaller
01159     int markerSpace = 1;
01160     int payloadSpace = len;
01161     // is this a resizing?
01162     if(_payloadLength!=0) {
01163         // marker already exists
01164         markerSpace = 0;
01165         // compute new payload length (can be negative if shrinking payload)
01166         payloadSpace = len-_payloadLength;
01167     }
01168 
01169     // make space for payload (and payload marker if necessary)
01170     int newLen = _pduLength+payloadSpace+markerSpace;
01171     if(!_constructedFromBuffer) {
01172         uint8_t* newPDU = (uint8_t*)realloc(_pdu,newLen);
01173         if(newPDU==NULL) {
01174             DBG("Cannot allocate (or shrink) space for payload");
01175             return NULL;
01176         }
01177         _pdu = newPDU;
01178         _bufferLength = newLen;
01179     } else {
01180         // constructed from buffer, check space
01181         DBG("newLen: %d, _bufferLength: %d",newLen,_bufferLength);
01182         if(newLen>_bufferLength) {
01183             DBG("Buffer too small to contain desired payload, needed %d, got %d.",newLen-_pduLength,_bufferLength-_pduLength);
01184             return NULL;
01185         }
01186     }
01187 
01188     // deal with fresh allocation case separately
01189     if(_payloadPointer==NULL) {
01190         // set payload marker
01191         _pdu[_pduLength] = 0xFF;
01192         // payload at end of old PDU
01193         _payloadPointer = &_pdu[_pduLength+1];
01194         _pduLength = newLen;
01195         _payloadLength = len;
01196         return _payloadPointer;
01197     }
01198 
01199     // otherwise, just adjust length of PDU
01200     _pduLength = newLen;
01201     _payloadLength = len;
01202     DBG("Leaving mallocPayload");
01203     return _payloadPointer;
01204 }
01205 
01206 /// Set the payload to the byte sequence specified. Allocates memory in dynamic PDU if necessary.
01207 /**
01208  * This will set the payload to \b payload. It will allocate memory in the case where the PDU was
01209  * constructed without an external buffer.
01210  *
01211  * This will fail either if the fixed buffer isn't big enough, or if memory could not be allocated
01212  * in the non-external-buffer case.
01213  * 
01214  * \param payload Pointer to payload byte sequence.
01215  * \param len Length of payload byte sequence.
01216  * \return 0 on success, 1 on failure.
01217  */
01218 int CoapPDU::setPayload(uint8_t *payload, int len) {
01219     if(payload==NULL) {
01220         DBG("NULL payload pointer.");
01221         return 1;
01222     }
01223 
01224     uint8_t *payloadPointer = mallocPayload(len);
01225     if(payloadPointer==NULL) {
01226         DBG("Allocation of payload failed");
01227         return 1;
01228     }
01229 
01230     // copy payload contents
01231     memcpy(payloadPointer,payload,len);
01232 
01233     return 0;
01234 }
01235 
01236 /// Returns a pointer to the payload buffer.
01237 uint8_t* CoapPDU::getPayloadPointer() {
01238     return _payloadPointer;
01239 }
01240 
01241 /// Gets the length of the payload buffer.
01242 int CoapPDU::getPayloadLength() {
01243     return _payloadLength;
01244 }
01245 
01246 /// Returns a pointer to a buffer which is a copy of the payload buffer (dynamically allocated).
01247 uint8_t* CoapPDU::getPayloadCopy() {
01248     if(_payloadLength==0) {
01249         return NULL;
01250     }
01251 
01252     // malloc space for copy
01253     uint8_t *payload = (uint8_t*)malloc(_payloadLength);
01254     if(payload==NULL) {
01255         DBG("Unable to allocate memory for payload");
01256         return NULL;
01257     }
01258 
01259     // copy and return
01260     memcpy(payload,_payloadPointer,_payloadLength);
01261     return payload;
01262 }
01263 
01264 /// Shorthand for setting the content-format option.
01265 /**
01266  * Sets the content-format to the specified value (adds an option). 
01267  * \param format The content format, one of:
01268  *
01269  * - COAP_CONTENT_FORMAT_TEXT_PLAIN
01270  * - COAP_CONTENT_FORMAT_APP_LINK
01271  * - COAP_CONTENT_FORMAT_APP_XML
01272  * - COAP_CONTENT_FORMAT_APP_OCTET
01273  * - COAP_CONTENT_FORMAT_APP_EXI
01274  * - COAP_CONTENT_FORMAT_APP_JSON
01275  *
01276  * \return 0 on success, 1 on failure.
01277  */
01278 int CoapPDU::setContentFormat(CoapPDU::ContentFormat format) {
01279     if(format==0) {
01280         // minimal representation means null option value
01281         if(addOption(CoapPDU::COAP_OPTION_CONTENT_FORMAT,0,NULL)!=0) {
01282             DBG("Error setting content format");
01283             return 1;
01284         }
01285         return 0;
01286     }
01287 
01288     uint8_t c[2];
01289 
01290     // just use 1 byte if can do it
01291     if(format<256) {
01292         c[0] = format;
01293         if(addOption(CoapPDU::COAP_OPTION_CONTENT_FORMAT,1,c)!=0) {
01294             DBG("Error setting content format");
01295             return 1;
01296         }
01297         return 0;
01298     }
01299 
01300     uint16_t networkOrder = htons(format);
01301     c[0] &= 0x00;
01302     c[0] |= (networkOrder >> 8);     // MSB
01303     c[1] &= 0x00;
01304     c[1] |= (networkOrder & 0x00FF); // LSB
01305     if(addOption(CoapPDU::COAP_OPTION_CONTENT_FORMAT,2,c)!=0) {
01306         DBG("Error setting content format");
01307         return 1;
01308     }
01309     return 0;
01310 }
01311 
01312 /// PRIVATE PRIVATE PRIVATE PRIVATE PRIVATE PRIVATE PRIVATE
01313 /// PRIVATE PRIVATE PRIVATE PRIVATE PRIVATE PRIVATE PRIVATE
01314 
01315 /// Moves a block of bytes to end of PDU from given offset.
01316 /**
01317  * This moves the block of bytes _pdu[_pduLength-1-shiftOffset-shiftAmount] ... _pdu[_pduLength-1-shiftOffset]
01318  * to the end of the PDU.
01319  * \param shiftOffset End of block to move, relative to end of PDU (-1).
01320  * \param shiftAmount Length of block to move.
01321  */
01322 void CoapPDU::shiftPDUUp(int shiftOffset, int shiftAmount) {
01323     DBG("shiftOffset: %d, shiftAmount: %d",shiftOffset,shiftAmount);
01324     int destPointer = _pduLength-1;
01325     int srcPointer  = destPointer-shiftOffset;
01326     while(shiftAmount--) {
01327         _pdu[destPointer] = _pdu[srcPointer];
01328         destPointer--;
01329         srcPointer--;
01330     }
01331 }
01332 
01333 /// Moves a block of bytes down a specified number of steps. 
01334 /**
01335  * Moves the block of bytes _pdu[startLocation+shiftOffset] ... _pdu[startLocation+shiftOffset+shiftAmount]
01336  * down to \b startLocation.
01337  * \param startLocation Index where to shift the block to.
01338  * \param shiftOffset Where the block starts, relative to start index.
01339  * \param shiftAmount Length of block to shift.
01340  */
01341 void CoapPDU::shiftPDUDown(int startLocation, int shiftOffset, int shiftAmount) {
01342     DBG("startLocation: %d, shiftOffset: %d, shiftAmount: %d",startLocation,shiftOffset,shiftAmount);
01343     int srcPointer = startLocation+shiftOffset;
01344     while(shiftAmount--) {
01345         _pdu[startLocation] = _pdu[srcPointer];
01346         startLocation++;
01347         srcPointer++;
01348     }
01349 }
01350 
01351 /// Gets the payload length of an option.
01352 /**
01353  * \param option Pointer to location of option in PDU.
01354  * \return The 16 bit option-payload length.
01355  */
01356 uint16_t CoapPDU::getOptionValueLength(uint8_t *option) {
01357     uint16_t delta = (option[0] & 0xF0) >> 4;
01358     uint16_t length = (option[0] & 0x0F);
01359     // no extra bytes
01360     if(length<13) {
01361         return length;
01362     }
01363     
01364     // extra bytes skip header
01365     int offset = 1;
01366     // skip extra option delta bytes
01367     if(delta==13) {
01368         offset++;
01369     } else if(delta==14) {
01370         offset+=2;
01371     }
01372 
01373     // process length
01374     if(length==13) {
01375         return (option[offset]+13);
01376     } else {
01377         // need to convert to host order
01378         uint16_t networkOrder = 0x0000;
01379         networkOrder |= option[offset++];
01380         networkOrder <<= 8;
01381         networkOrder |= option[offset];
01382         uint16_t hostOrder = ntohs(networkOrder);
01383         return hostOrder+269;
01384     }
01385 
01386 }
01387 
01388 /// Gets the delta of an option.
01389 /**
01390  * \param option Pointer to location of option in PDU.
01391  * \return The 16 bit delta.
01392  */
01393 uint16_t CoapPDU::getOptionDelta(uint8_t *option) {
01394     uint16_t delta = (option[0] & 0xF0) >> 4;
01395     if(delta<13) {
01396         return delta;
01397     } else if(delta==13) {
01398         // single byte option delta
01399         return (option[1]+13);
01400     } else if(delta==14) {
01401         // double byte option delta
01402         // need to convert to host order
01403         uint16_t networkOrder = 0x0000;
01404         networkOrder |= option[1];
01405         networkOrder <<= 8;
01406         networkOrder |= option[2];
01407         uint16_t hostOrder = ntohs(networkOrder);
01408         return hostOrder+269;
01409     } else {
01410         // should only ever occur in payload marker
01411         return delta;
01412     }
01413 }
01414 
01415 /// Finds the insertion position in the current list of options for the specified option.
01416 /**
01417  * \param optionNumber The option's number.
01418  * \param prevOptionNumber A pointer to a uint16_t which will store the option number of the option previous
01419  * to the insertion point.
01420  * \return 0 on success, 1 on failure. \b prevOptionNumber will contain the option number of the option
01421  * before the insertion position (for example 0 if no options have been inserted).
01422  */
01423 int CoapPDU::findInsertionPosition(uint16_t optionNumber, uint16_t *prevOptionNumber) {
01424     // zero this for safety
01425     *prevOptionNumber = 0x00;
01426 
01427     DBG("_pduLength: %d",_pduLength);
01428 
01429     // if option is bigger than any currently stored, it goes at the end
01430     // this includes the case that no option has yet been added
01431     if( (optionNumber >= _maxAddedOptionNumber) || (_pduLength == (COAP_HDR_SIZE+getTokenLength())) ) {
01432         *prevOptionNumber = _maxAddedOptionNumber;
01433         return _pduLength;
01434     }
01435 
01436     // otherwise walk over the options
01437     int optionPos = COAP_HDR_SIZE + getTokenLength();
01438     uint16_t optionDelta = 0, optionValueLength = 0;
01439     uint16_t currentOptionNumber = 0;
01440     while(optionPos<_pduLength && _pdu[optionPos]!=0xFF) {
01441         optionDelta = getOptionDelta(&_pdu[optionPos]);
01442         currentOptionNumber += optionDelta;
01443         optionValueLength = getOptionValueLength(&_pdu[optionPos]);
01444         // test if this is insertion position
01445         if(currentOptionNumber>optionNumber) {
01446             return optionPos;
01447         }
01448         // keep track of the last valid option number
01449         *prevOptionNumber = currentOptionNumber;
01450         // move onto next option
01451         optionPos += computeExtraBytes(optionDelta);
01452         optionPos += computeExtraBytes(optionValueLength);
01453         optionPos += optionValueLength;
01454         optionPos++; // (for mandatory option header byte)
01455     }
01456     return optionPos;
01457 
01458 }
01459 
01460 /// CoAP uses a minimal-byte representation for length fields. This returns the number of bytes needed to represent a given length.
01461 int CoapPDU::computeExtraBytes(uint16_t n) {
01462     if(n<13) {
01463         return 0;
01464     }
01465 
01466     if(n<269) { 
01467         return 1;
01468     }
01469     
01470     return 2;
01471 }
01472 
01473 /// Set the option delta to the specified value.
01474 /** 
01475  * This assumes space has been made for the option delta.
01476  * \param optionPosition The index of the option in the PDU.
01477  * \param optionDelta The option delta value to set.
01478  */
01479 void CoapPDU::setOptionDelta(int optionPosition, uint16_t optionDelta) {
01480     int headerStart = optionPosition;
01481     // clear the old option delta bytes
01482     _pdu[headerStart] &= 0x0F;
01483 
01484     // set the option delta bytes
01485     if(optionDelta<13) {
01486         _pdu[headerStart] |= (optionDelta << 4);
01487     } else if(optionDelta<269) {
01488        // 1 extra byte
01489         _pdu[headerStart] |= 0xD0; // 13 in first nibble
01490         _pdu[++optionPosition] &= 0x00;
01491         _pdu[optionPosition] |= (optionDelta-13);
01492     } else {
01493         // 2 extra bytes, network byte order uint16_t
01494         _pdu[headerStart] |= 0xE0; // 14 in first nibble
01495         optionDelta = htons(optionDelta-269);
01496         _pdu[++optionPosition] &= 0x00;
01497         _pdu[optionPosition] |= (optionDelta >> 8);     // MSB
01498         _pdu[++optionPosition] &= 0x00;
01499         _pdu[optionPosition] |= (optionDelta & 0x00FF); // LSB
01500     }
01501 }
01502 
01503 /// Insert an option in-memory at the specified location.
01504 /**
01505  * This assumes that there is enough space at the location specified.
01506  * \param insertionPosition Position in the PDU where the option should be placed.
01507  * \param optionDelta The delta value for the option.
01508  * \param optionValueLength The length of the option value.
01509  * \param optionValue A pointer to the sequence of bytes representing the option value.
01510  * \return 0 on success, 1 on failure.
01511  */
01512 int CoapPDU::insertOption(
01513     int insertionPosition,
01514     uint16_t optionDelta, 
01515     uint16_t optionValueLength,
01516     uint8_t *optionValue) {
01517 
01518     int headerStart = insertionPosition;
01519 
01520     // clear old option header start
01521     _pdu[headerStart] &= 0x00;
01522 
01523     // set the option delta bytes
01524     if(optionDelta<13) {
01525         _pdu[headerStart] |= (optionDelta << 4);
01526     } else if(optionDelta<269) {
01527        // 1 extra byte
01528         _pdu[headerStart] |= 0xD0; // 13 in first nibble
01529         _pdu[++insertionPosition] &= 0x00;
01530         _pdu[insertionPosition] |= (optionDelta-13);
01531     } else {
01532         // 2 extra bytes, network byte order uint16_t
01533         _pdu[headerStart] |= 0xE0; // 14 in first nibble
01534         optionDelta = htons(optionDelta-269);
01535         _pdu[++insertionPosition] &= 0x00;
01536         _pdu[insertionPosition] |= (optionDelta >> 8);     // MSB
01537         _pdu[++insertionPosition] &= 0x00;
01538         _pdu[insertionPosition] |= (optionDelta & 0x00FF); // LSB
01539     }
01540 
01541     // set the option value length bytes
01542     if(optionValueLength<13) {
01543         _pdu[headerStart] |= (optionValueLength & 0x000F);
01544     } else if(optionValueLength<269) {
01545         _pdu[headerStart] |= 0x0D; // 13 in second nibble
01546         _pdu[++insertionPosition] &= 0x00;
01547         _pdu[insertionPosition] |= (optionValueLength-13);
01548     } else {
01549         _pdu[headerStart] |= 0x0E; // 14 in second nibble
01550         // this is in network byte order
01551         DBG("optionValueLength: %u",optionValueLength);
01552         uint16_t networkOrder = htons(optionValueLength-269);
01553         _pdu[++insertionPosition] &= 0x00;
01554         _pdu[insertionPosition] |= (networkOrder >> 8);     // MSB
01555         _pdu[++insertionPosition] &= 0x00;
01556         _pdu[insertionPosition] |= (networkOrder & 0x00FF); // LSB
01557     }
01558 
01559     // and finally copy the option value itself
01560     memcpy(&_pdu[++insertionPosition],optionValue,optionValueLength);
01561 
01562     return 0;
01563 }
01564 
01565 // DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG
01566 // DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG
01567 
01568 /// Prints the PDU in human-readable format.
01569 void CoapPDU::printHuman() {
01570     INFOX("__________________\r\n");
01571     if(_constructedFromBuffer) {
01572         INFOX("PDU was constructed from buffer of %d bytes\r\n",_bufferLength);
01573     }
01574     INFOX("PDU is %d bytes long\r\n",_pduLength);
01575     INFOX("CoAP Version: %d\r\n",getVersion());
01576     INFOX("Message Type: ");
01577     switch(getType()) {
01578         case COAP_CONFIRMABLE:
01579             INFOX("Confirmable\r\n");
01580         break;
01581 
01582         case COAP_NON_CONFIRMABLE:
01583             INFOX("Non-Confirmable\r\n");
01584         break;
01585 
01586         case COAP_ACKNOWLEDGEMENT:
01587             INFOX("Acknowledgement\r\n");
01588         break;
01589 
01590         case COAP_RESET:
01591             INFOX("Reset\r\n");
01592         break;
01593     }
01594     INFOX("Token length: %d\r\n",getTokenLength());
01595     INFOX("Code: ");
01596     switch(getCode()) {
01597         case COAP_EMPTY:
01598             INFOX("0.00 Empty");
01599         break;
01600         case COAP_GET:
01601             INFOX("0.01 GET");
01602         break;
01603         case COAP_POST:
01604             INFOX("0.02 POST");
01605         break;
01606         case COAP_PUT:
01607             INFOX("0.03 PUT");
01608         break;
01609         case COAP_DELETE:
01610             INFOX("0.04 DELETE");
01611         break;
01612         case COAP_CREATED:
01613             INFOX("2.01 Created");
01614         break;
01615         case COAP_DELETED:
01616             INFOX("2.02 Deleted");
01617         break;
01618         case COAP_VALID:
01619             INFOX("2.03 Valid");
01620         break;
01621         case COAP_CHANGED:
01622             INFOX("2.04 Changed");
01623         break;
01624         case COAP_CONTENT:
01625             INFOX("2.05 Content");
01626         break;
01627         case COAP_BAD_REQUEST:
01628             INFOX("4.00 Bad Request");
01629         break;
01630         case COAP_UNAUTHORIZED:
01631             INFOX("4.01 Unauthorized");
01632         break;
01633         case COAP_BAD_OPTION:
01634             INFOX("4.02 Bad Option");
01635         break;
01636         case COAP_FORBIDDEN:
01637             INFOX("4.03 Forbidden");
01638         break;
01639         case COAP_NOT_FOUND:
01640             INFOX("4.04 Not Found");
01641         break;
01642         case COAP_METHOD_NOT_ALLOWED:
01643             INFOX("4.05 Method Not Allowed");
01644         break;
01645         case COAP_NOT_ACCEPTABLE:
01646             INFOX("4.06 Not Acceptable");
01647         break;
01648         case COAP_PRECONDITION_FAILED:
01649             INFOX("4.12 Precondition Failed");
01650         break;
01651         case COAP_REQUEST_ENTITY_TOO_LARGE:
01652             INFOX("4.13 Request Entity Too Large");
01653         break;
01654         case COAP_UNSUPPORTED_CONTENT_FORMAT:
01655             INFOX("4.15 Unsupported Content-Format");
01656         break;
01657         case COAP_INTERNAL_SERVER_ERROR:
01658             INFOX("5.00 Internal Server Error");
01659         break;
01660         case COAP_NOT_IMPLEMENTED:
01661             INFOX("5.01 Not Implemented");
01662         break;
01663         case COAP_BAD_GATEWAY:
01664             INFOX("5.02 Bad Gateway");
01665         break;
01666         case COAP_SERVICE_UNAVAILABLE:
01667             INFOX("5.03 Service Unavailable");
01668         break;
01669         case COAP_GATEWAY_TIMEOUT:
01670             INFOX("5.04 Gateway Timeout");
01671         break;
01672         case COAP_PROXYING_NOT_SUPPORTED:
01673             INFOX("5.05 Proxying Not Supported");
01674         break;
01675         case COAP_UNDEFINED_CODE:
01676             INFOX("Undefined Code");
01677         break;
01678     }
01679     INFOX("\r\n");
01680 
01681     // print message ID
01682     INFOX("Message ID: %u\r\n",getMessageID());
01683 
01684     // print token value
01685     int tokenLength = getTokenLength();
01686     uint8_t *tokenPointer = getPDUPointer()+COAP_HDR_SIZE;
01687     if(tokenLength==0) {
01688         INFOX("No token.\r\n");
01689     } else {
01690         INFOX("Token of %d bytes.\r\n",tokenLength);
01691         INFOX("   Value: 0x");
01692         for(int j=0; j<tokenLength; j++) {
01693             INFOX("%.2x",tokenPointer[j]);
01694         }
01695         INFOX("\r\n");
01696     }
01697 
01698     // print options
01699     CoapPDU::CoapOption* options = getOptions();
01700     INFOX("%d options:\r\n",_numOptions);
01701     for(int i=0; i<_numOptions; i++) {
01702         INFOX("OPTION (%d/%d)\r\n",i,_numOptions);
01703         INFOX("   Option number (delta): %hu (%hu)\r\n",options[i].optionNumber,options[i].optionDelta);
01704         INFOX("   Name: ");
01705         switch(options[i].optionNumber) {
01706             case COAP_OPTION_IF_MATCH:
01707                 INFOX("IF_MATCH");
01708             break;
01709             case COAP_OPTION_URI_HOST:
01710                 INFOX("URI_HOST");
01711             break;
01712             case COAP_OPTION_ETAG:
01713                 INFOX("ETAG");
01714             break;
01715             case COAP_OPTION_IF_NONE_MATCH:
01716                 INFOX("IF_NONE_MATCH");
01717             break;
01718             case COAP_OPTION_OBSERVE:
01719                 INFOX("OBSERVE");
01720             break;
01721             case COAP_OPTION_URI_PORT:
01722                 INFOX("URI_PORT");
01723             break;
01724             case COAP_OPTION_LOCATION_PATH:
01725                 INFOX("LOCATION_PATH");
01726             break;
01727             case COAP_OPTION_URI_PATH:
01728                 INFOX("URI_PATH");
01729             break;
01730             case COAP_OPTION_CONTENT_FORMAT:
01731                 INFOX("CONTENT_FORMAT");
01732             break;
01733             case COAP_OPTION_MAX_AGE:
01734                 INFOX("MAX_AGE");
01735             break;
01736             case COAP_OPTION_URI_QUERY:
01737                 INFOX("URI_QUERY");
01738             break;
01739             case COAP_OPTION_ACCEPT:
01740                 INFOX("ACCEPT");
01741             break;
01742             case COAP_OPTION_LOCATION_QUERY:
01743                 INFOX("LOCATION_QUERY");
01744             break;
01745             case COAP_OPTION_PROXY_URI:
01746                 INFOX("PROXY_URI");
01747             break;
01748             case COAP_OPTION_PROXY_SCHEME:
01749                 INFOX("PROXY_SCHEME");
01750             break;
01751             case COAP_OPTION_BLOCK1:
01752                 INFOX("BLOCK1");
01753             break;
01754             case COAP_OPTION_BLOCK2:
01755                 INFOX("BLOCK2");
01756             break;
01757             case COAP_OPTION_SIZE1:
01758                 INFOX("SIZE1");
01759             break;
01760             case COAP_OPTION_SIZE2:
01761                 INFOX("SIZE2");
01762             break;
01763             default:
01764                 INFOX("Unknown option");
01765             break;
01766         }
01767         INFOX("\r\n");
01768         INFOX("   Value length: %u\r\n",options[i].optionValueLength);
01769         INFOX("   Value: \"");
01770         for(int j=0; j<options[i].optionValueLength; j++) {
01771             char c = options[i].optionValuePointer[j];
01772             if((c>='!'&&c<='~')||c==' ') {
01773                 INFOX("%c",c);
01774             } else {
01775                 INFOX("\\%.2d",c);
01776             }
01777         }
01778         INFOX("\"\r\n");
01779     }
01780     
01781     // print payload
01782     if(_payloadLength==0) {
01783         INFOX("No payload.\r\n");
01784     } else {
01785         INFOX("Payload of %d bytes\r\n",_payloadLength);
01786         INFOX("   Value: \"");
01787         for(int j=0; j<_payloadLength; j++) {
01788             char c = _payloadPointer[j];
01789             if((c>='!'&&c<='~')||c==' ') {
01790                 INFOX("%c",c);
01791             } else {
01792                 INFOX("\\%.2x",c);
01793             }
01794         }
01795         INFO("\"\r\n");
01796     }
01797     INFOX("__________________\r\n");
01798 }
01799 
01800 /// Prints the PDU as a c array (useful for debugging or hardcoding PDUs)
01801 void CoapPDU::printPDUAsCArray() {
01802     printf("const uint8_t array[] = {\r\n   ");
01803     for(int i=0; i<_pduLength; i++) {
01804         printf("0x%.2x, ",_pdu[i]);
01805     }
01806     printf("\r\n};\r\n");
01807 }
01808 
01809 /// A routine for printing an option in human-readable format.
01810 /**
01811  * \param option This is a pointer to where the option begins in the PDU.
01812  */
01813 void CoapPDU::printOptionHuman(uint8_t *option) {
01814     // compute some useful stuff
01815     uint16_t optionDelta = getOptionDelta(option);
01816     uint16_t optionValueLength = getOptionValueLength(option);
01817     int extraDeltaBytes = computeExtraBytes(optionDelta);
01818     int extraValueLengthBytes = computeExtraBytes(optionValueLength);
01819     int totalLength = 1+extraDeltaBytes+extraValueLengthBytes+optionValueLength;
01820 
01821     if(totalLength>_pduLength) {
01822         totalLength = &_pdu[_pduLength-1]-option;
01823         DBG("New length: %u",totalLength);
01824     }
01825 
01826     // print summary
01827     DBG("~~~~~~ Option ~~~~~~");
01828     DBG("Delta: %u, Value length: %u",optionDelta,optionValueLength);
01829 
01830     // print all bytes
01831     DBG("All bytes (%d):",totalLength);
01832     for(int i=0; i<totalLength; i++) {
01833         if(i%4==0) {
01834             DBG(" ");
01835             DBGX("   %.2d ",i);
01836         }
01837         CoapPDU::printBinary(option[i]); DBGX(" ");
01838     }
01839     DBG(" "); DBG(" ");
01840 
01841     // print header byte
01842     DBG("Header byte:");
01843     DBGX("   ");
01844     CoapPDU::printBinary(*option++);
01845     DBG(" "); DBG(" ");
01846 
01847     // print extended delta bytes
01848     if(extraDeltaBytes) {
01849         DBG("Extended delta bytes (%d) in network order: ",extraDeltaBytes);
01850         DBGX("   ");
01851         while(extraDeltaBytes--) {
01852             CoapPDU::printBinary(*option++); DBGX(" ");
01853         }
01854     } else {
01855         DBG("No extended delta bytes");
01856     }
01857     DBG(" "); DBG(" ");
01858 
01859     // print extended value length bytes
01860     if(extraValueLengthBytes) {
01861         DBG("Extended value length bytes (%d) in network order: ",extraValueLengthBytes);
01862         DBGX("   ");
01863         while(extraValueLengthBytes--) {
01864             CoapPDU::printBinary(*option++); DBGX(" ");
01865         }
01866     } else {
01867         DBG("No extended value length bytes");
01868     }
01869     DBG(" ");
01870 
01871     // print option value
01872     DBG("Option value bytes:");
01873     for(int i=0; i<optionValueLength; i++) {
01874         if(i%4==0) {
01875             DBG(" ");
01876             DBGX("   %.2d ",i);
01877         }
01878         CoapPDU::printBinary(*option++);
01879         DBGX(" ");
01880     }
01881     DBG(" ");
01882 }
01883 
01884 /// Dumps the PDU header in hex.
01885 void CoapPDU::printHex() {
01886     printf("Hexdump dump of PDU\r\n");
01887     printf("%.2x %.2x %.2x %.2x",_pdu[0],_pdu[1],_pdu[2],_pdu[3]);
01888 }
01889 
01890 /// Dumps the entire PDU in binary.
01891 void CoapPDU::printBin() {
01892     for(int i=0; i<_pduLength; i++) {
01893         if(i%4==0) {
01894             printf("\r\n");
01895             printf("%.2d ",i);
01896         } 
01897         CoapPDU::printBinary(_pdu[i]); printf(" ");
01898     }
01899     printf("\r\n");
01900 }
01901 
01902 /// Prints a single byte in binary.
01903 void CoapPDU::printBinary(uint8_t b) {
01904     printf("%d%d%d%d%d%d%d%d",
01905         (b&0x80)&&0x01,
01906         (b&0x40)&&0x01,
01907         (b&0x20)&&0x01,
01908         (b&0x10)&&0x01,
01909         (b&0x08)&&0x01,
01910         (b&0x04)&&0x01,
01911         (b&0x02)&&0x01,
01912         (b&0x01)&&0x01);
01913 }
01914 
01915 /// Dumps the PDU as a byte sequence to stdout.
01916 void CoapPDU::print() {
01917     fwrite(_pdu,1,_pduLength,stdout);
01918 }