terence zhang / wakaama
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers block1.c Source File

block1.c

00001 /*******************************************************************************
00002  *
00003  * Copyright (c) 2016 Intel Corporation and others.
00004  * All rights reserved. This program and the accompanying materials
00005  * are made available under the terms of the Eclipse Public License v1.0
00006  * and Eclipse Distribution License v1.0 which accompany this distribution.
00007  *
00008  * The Eclipse Public License is available at
00009  *    http://www.eclipse.org/legal/epl-v10.html
00010  * The Eclipse Distribution License is available at
00011  *    http://www.eclipse.org/org/documents/edl-v10.php.
00012  *
00013  * Contributors:
00014  *    Simon Bernard - initial API and implementation
00015  *
00016  *******************************************************************************/
00017 /*
00018  Copyright (c) 2016 Intel Corporation
00019 
00020  Redistribution and use in source and binary forms, with or without modification,
00021  are permitted provided that the following conditions are met:
00022 
00023      * Redistributions of source code must retain the above copyright notice,
00024        this list of conditions and the following disclaimer.
00025      * Redistributions in binary form must reproduce the above copyright notice,
00026        this list of conditions and the following disclaimer in the documentation
00027        and/or other materials provided with the distribution.
00028      * Neither the name of Intel Corporation nor the names of its contributors
00029        may be used to endorse or promote products derived from this software
00030        without specific prior written permission.
00031 
00032  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00033  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00034  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00035  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
00036  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00037  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00038  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00039  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
00040  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
00041  THE POSSIBILITY OF SUCH DAMAGE.
00042 */
00043 #include "internals.h"
00044 
00045 #include <stdlib.h>
00046 #include <string.h>
00047 #include <stdio.h>
00048 
00049 // the maximum payload transferred by block1 we accumulate per server
00050 #define MAX_BLOCK1_SIZE 4096
00051 
00052 coap_status_t coap_block1_handler(lwm2m_block1_data_t ** pBlock1Data,
00053                                   uint16_t mid,
00054                                   uint8_t * buffer,
00055                                   size_t length,
00056                                   uint16_t blockSize,
00057                                   uint32_t blockNum,
00058                                   bool blockMore,
00059                                   uint8_t ** outputBuffer,
00060                                   size_t * outputLength)
00061 {
00062     lwm2m_block1_data_t * block1Data = *pBlock1Data;;
00063 
00064     // manage new block1 transfer
00065     if (blockNum == 0)
00066     {
00067        // we already have block1 data for this server, clear it
00068        if (block1Data != NULL)
00069        {
00070            lwm2m_free(block1Data->block1buffer);
00071        }
00072        else
00073        {
00074            block1Data = lwm2m_malloc(sizeof(lwm2m_block1_data_t));
00075            *pBlock1Data = block1Data;
00076            if (NULL == block1Data) return COAP_500_INTERNAL_SERVER_ERROR;
00077        }
00078 
00079        block1Data->block1buffer = lwm2m_malloc(length);
00080        block1Data->block1bufferSize = length;
00081 
00082        // write new block in buffer
00083        memcpy(block1Data->block1buffer, buffer, length);
00084        block1Data->lastmid = mid;
00085     }
00086     // manage already started block1 transfer
00087     else
00088     {
00089        if (block1Data == NULL)
00090        {
00091            // we never receive the first block
00092            // TODO should we clean block1 data for this server ?
00093            return COAP_408_REQ_ENTITY_INCOMPLETE;
00094        }
00095 
00096        // If this is a retransmission, we already did that.
00097        if (block1Data->lastmid != mid)
00098        {
00099           uint8_t * oldBuffer = block1Data->block1buffer;
00100           size_t oldSize = block1Data->block1bufferSize;
00101 
00102           if (block1Data->block1bufferSize != blockSize * blockNum)
00103           {
00104               // we don't receive block in right order
00105               // TODO should we clean block1 data for this server ?
00106               return COAP_408_REQ_ENTITY_INCOMPLETE;
00107           }
00108 
00109           // is it too large?
00110           if (block1Data->block1bufferSize + length >= MAX_BLOCK1_SIZE) {
00111               return COAP_413_ENTITY_TOO_LARGE;
00112           }
00113           // re-alloc new buffer
00114           block1Data->block1bufferSize = oldSize+length;
00115           block1Data->block1buffer = lwm2m_malloc(block1Data->block1bufferSize);
00116           if (NULL == block1Data->block1buffer) return COAP_500_INTERNAL_SERVER_ERROR;
00117           memcpy(block1Data->block1buffer, oldBuffer, oldSize);
00118           lwm2m_free(oldBuffer);
00119 
00120           // write new block in buffer
00121           memcpy(block1Data->block1buffer + oldSize, buffer, length);
00122           block1Data->lastmid = mid;
00123        }
00124     }
00125 
00126     if (blockMore)
00127     {
00128         *outputLength = -1;
00129         return COAP_231_CONTINUE;
00130     }
00131     else
00132     {
00133         // buffer is full, set output parameter
00134         // we don't free it to be able to send retransmission
00135         *outputLength = block1Data->block1bufferSize;
00136         *outputBuffer = block1Data->block1buffer;
00137 
00138         return NO_ERROR;
00139     }
00140 }
00141 
00142 void free_block1_buffer(lwm2m_block1_data_t * block1Data)
00143 {
00144     if (block1Data != NULL)
00145     {
00146         // free block1 buffer
00147         lwm2m_free(block1Data->block1buffer);
00148         block1Data->block1bufferSize = 0 ;
00149 
00150         // free current element
00151         lwm2m_free(block1Data);
00152     }
00153 }