예제 #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_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);
}