Adapted to LoRa Semtech + Nucleo

Dependents:   LoRaWAN-lmic-app LoRaWAN-lmic-app LoRaWAN-test-10secs LoRaPersonalizedDeviceForEverynet ... more

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