This is CoAP library with a focus on simplicity. It offers minimal CoAP PDU construction and decoding to and from byte buffers.

Dependents:   cantcoap_cellular_test yeswecancoap

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