コード例 #1
0
ファイル: fnet_netbuf.c プロジェクト: ErikZalm/fnet
/************************************************************************
* NAME: fnet_netbuf_new
*
* DESCRIPTION: Creates a new net_buf and allocates memory
*              for a new data buffer. 
*************************************************************************/
fnet_netbuf_t *fnet_netbuf_new( int len, int drain )
{
    fnet_netbuf_t   *nb;
    void            *nb_d;

    if(len < 0)
        return (fnet_netbuf_t *)0;


    nb = (fnet_netbuf_t *)fnet_malloc_netbuf(sizeof(fnet_netbuf_t));

    if((nb == 0) && drain)
    {
        fnet_prot_drain();
        nb = (fnet_netbuf_t *)fnet_malloc_netbuf(sizeof(fnet_netbuf_t));
    }

    if(nb == 0) /* If FNET_NETBUF_MALLOC_NOWAIT and no free memory for a new net_buf*/
    {
        return (fnet_netbuf_t *)0;
    }


    nb_d = fnet_malloc_netbuf((unsigned int)len + sizeof(int)/* For reference_counter */);

    if((nb_d == 0) && drain )
    {
        fnet_prot_drain();
        nb_d = fnet_malloc_netbuf((unsigned int)len + sizeof(int)/* For reference_counter */);
    }


    if(nb_d == 0) /* If FNET_NETBUF_MALLOC_NOWAIT and no free memory for data.*/
    {
        fnet_free_netbuf(nb);
        return (fnet_netbuf_t *)0;
    }

    nb->next = (fnet_netbuf_t *)0;
    nb->next_chain = (fnet_netbuf_t *)0;

    /* In memory net_buf's data is after the descriptor "data".*/
    
    ((int *)nb_d)[0] = 1; /* First element is used by the reference_counter.*/
    nb->data = &((int *)nb_d)[0];
    nb->data_ptr = &((int *)nb_d)[1];
    nb->length = (unsigned long)len;
    nb->total_length = (unsigned long)len;
    nb->flags = 0;

    return (nb);
}
コード例 #2
0
ファイル: fnet_netbuf.c プロジェクト: 8bitgeek/fnet
/************************************************************************
* NAME: fnet_netbuf_pullup
*
* DESCRIPTION: Create a data buffer for the first net_buf with the 
*              length len 
*************************************************************************/
fnet_return_t fnet_netbuf_pullup( fnet_netbuf_t **nb_ptr, fnet_size_t len)
{
    fnet_netbuf_t   *nb = *nb_ptr;
    fnet_size_t     tot_len = 0u;
    fnet_size_t     offset;
    fnet_netbuf_t   *tmp_nb;
    fnet_netbuf_t   *nb_run;
    void            *new_buf;
    
    /* Check length*/
    if(nb->total_length < len)
    {
        return FNET_OK;
    }
    
    if((nb->length >= len) || (len == 0u) || (nb == 0))
    {
        /* if function shouldn't do anything*/
        return FNET_OK;
    }

    tmp_nb = nb;

    tot_len += tmp_nb->length;

    /* search of the last buffer, from which the data have to be copied*/
    while((tot_len < len) && tmp_nb)
    {
        tmp_nb = tmp_nb->next;
        tot_len += tmp_nb->length;
    }

    new_buf = (struct net_buf_data *)fnet_malloc_netbuf((fnet_size_t)len + sizeof(fnet_uint32_t)/* For reference_counter */);

    if(new_buf == 0)
    {
        return FNET_ERR;
    }
       
    ((fnet_uint32_t *)new_buf)[0] = 1u; /* First element is used by the reference_counter.*/

    /* Copy into it the contents of first data buffer. Skip the reference counter (placed in the first bytes). */
    fnet_memcpy(&((fnet_uint32_t *)new_buf)[1], nb->data_ptr, nb->length);
    offset = nb->length;

    /* Free old data buffer (for the first net_buf) */
    if(((fnet_uint32_t *)nb->data)[0] == 1u)   /* If nobody uses this data buffer. */
    {
        fnet_free_netbuf(nb->data);
    }
    else                            /* Else decrement reference counter */
    {
        ((fnet_uint32_t *)nb->data)[0] = ((fnet_uint32_t *)nb->data)[0] - 1u;
    }

    /* Currently data buffer contains the contents of the first buffer */
    nb->data = &((fnet_uint32_t *)new_buf)[0];
    nb->data_ptr = &((fnet_uint32_t *)new_buf)[1];

    nb_run = nb->next;      /* Let's start from the next buffer */

    while(nb_run != tmp_nb) /* Copy full data buffers */
    {
        fnet_memcpy((fnet_uint8_t *)nb->data_ptr + offset, nb_run->data_ptr, nb_run->length);

        if(nb_run != tmp_nb)
        {
            offset += nb_run->length;
            nb_run = fnet_netbuf_free(nb_run);
        }
    }

    tot_len = len - offset;

    /* Copy the remaining part and change data pointer and length of the 
     * last net_buf, which is the source for the first net_buf */

    fnet_memcpy((fnet_uint8_t *)nb->data_ptr + offset, nb_run->data_ptr, tot_len);

    nb_run->length -= tot_len;

    if(nb_run->length == 0u)
    {
        nb_run = fnet_netbuf_free(nb_run);
    }
    else
    {
        nb_run->data_ptr = (fnet_uint8_t *)nb_run->data_ptr + tot_len;
    }

    /* Setting up the params of the first net_buf.*/
    nb->next = nb_run;

    nb->length = (fnet_size_t)len;

    *nb_ptr = nb;

    return FNET_OK;
}
コード例 #3
0
ファイル: fnet_netbuf.c プロジェクト: 8bitgeek/fnet
/************************************************************************
* NAME: fnet_netbuf_copy
*
* DESCRIPTION: Creates a new net_buf using data buffer, 
*              which was created before for another net_buf. 
*************************************************************************/
fnet_netbuf_t *fnet_netbuf_copy( fnet_netbuf_t *nb, fnet_size_t offset, fnet_size_t len, fnet_bool_t drain )
{
    fnet_netbuf_t   *loc_nb, *loc_nb_head, *tmp_nb;
    fnet_int32_t    tot_len = 0;
    fnet_size_t     tot_offset = 0u;

    tmp_nb = nb;

    do /* Calculate the total length of the buf for current net_buf chain.*/
    {
        tot_len += (fnet_int32_t)tmp_nb->length;
        tmp_nb = tmp_nb->next;
    } while (tmp_nb);

    if(len == FNET_NETBUF_COPYALL)
    {
        tot_len -= (fnet_int32_t)offset;
        len = (fnet_size_t)tot_len;
    }
    else
    {
        if(((len + offset) > (fnet_size_t)tot_len ) || ((fnet_size_t)tot_len < offset))
        {
            return (fnet_netbuf_t *)0;
        }    
    }
    /* In tot_len finally - the size of required net_buf data*/

    tmp_nb = nb;


    loc_nb = (fnet_netbuf_t *)fnet_malloc_netbuf(sizeof(fnet_netbuf_t));

    if((loc_nb == 0) && drain)
    {
        fnet_prot_drain();
        loc_nb = (fnet_netbuf_t *)fnet_malloc_netbuf(sizeof(fnet_netbuf_t));
    }

    if(loc_nb == 0)
    {
        return (fnet_netbuf_t *)0;
    }

    loc_nb_head = loc_nb; /* Save the head of net_buf chain.*/
    loc_nb->next_chain = (fnet_netbuf_t *)0;
    loc_nb->total_length = (fnet_size_t)len;
    loc_nb->flags = nb->flags;

    if(tmp_nb->length > offset) /* If offset less than size of 1st net_buf.*/
    {
        tot_offset = offset;
    }
    else /* Find corresponding net_buf and calculate the offset in it.*/
    {
        while((tot_offset += tmp_nb->length) <= offset)
        {
            tmp_nb = tmp_nb->next;
        }

        tot_offset = (tmp_nb->length + offset - tot_offset);
    }

    loc_nb->data = tmp_nb->data;

    loc_nb->data_ptr = (fnet_uint8_t *)tmp_nb->data_ptr + tot_offset;
    
    ((fnet_uint32_t *)loc_nb->data)[0] = ((fnet_uint32_t *)loc_nb->data)[0] + 1u;    /* Increment the the reference_counter.*/
    
    tot_len = (fnet_int32_t)(len - (tmp_nb->length - tot_offset));

    if(tot_len <= 0) /* If only one net_buf required.*/
    {
        loc_nb->length = (fnet_size_t)len;
    }
    else
    {
        loc_nb->length = tmp_nb->length - tot_offset;

        do
        {
            loc_nb->next = (fnet_netbuf_t *)fnet_malloc_netbuf(sizeof(fnet_netbuf_t));

            if((loc_nb->next == 0) && drain )
            {
                fnet_prot_drain();
                loc_nb->next = (fnet_netbuf_t *)fnet_malloc_netbuf(sizeof(fnet_netbuf_t));
            }

            if(loc_nb->next == 0) /* there is a need to erase all buffers,*/
            {                     /* which were created earlier.*/
                loc_nb_head = fnet_netbuf_free(loc_nb_head);

                while(loc_nb_head != loc_nb->next)
                {
                    tmp_nb = loc_nb_head->next;
                    fnet_free_netbuf(loc_nb_head);
                    loc_nb_head = tmp_nb;
                }
                
                return (fnet_netbuf_t *)0;
            }

            loc_nb = loc_nb->next;
            loc_nb->next_chain = (fnet_netbuf_t *)0;

            tmp_nb = tmp_nb->next;

            loc_nb->data = tmp_nb->data;
            loc_nb->flags = tmp_nb->flags; 

            ((fnet_uint32_t *)loc_nb->data)[0] = ((fnet_uint32_t *)loc_nb->data)[0] + 1u; /* Increment the the reference_counter.*/

            loc_nb->data_ptr = tmp_nb->data_ptr;

            tot_len -= (fnet_int32_t)tmp_nb->length;

            if(tot_len < 0) /* for correct calculation of length */
            {
                loc_nb->length = (fnet_size_t)(tot_len + (fnet_int32_t)tmp_nb->length);
            }
            else
            {
                loc_nb->length = tmp_nb->length;
            }
        } 
        while (tot_len > 0);
    }

    loc_nb->next = (fnet_netbuf_t *)0;
    
    return (loc_nb_head);
}