diff options
Diffstat (limited to '3rdparty/openpgm-svn-r1085/pgm/include/pgm/skbuff.h')
-rw-r--r-- | 3rdparty/openpgm-svn-r1085/pgm/include/pgm/skbuff.h | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/3rdparty/openpgm-svn-r1085/pgm/include/pgm/skbuff.h b/3rdparty/openpgm-svn-r1085/pgm/include/pgm/skbuff.h new file mode 100644 index 0000000..0701dfb --- /dev/null +++ b/3rdparty/openpgm-svn-r1085/pgm/include/pgm/skbuff.h @@ -0,0 +1,243 @@ +/* vim:ts=8:sts=8:sw=4:noai:noexpandtab + * + * PGM socket buffers + * + * Copyright (c) 2006-2009 Miru Limited. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PGM_SKBUFF_H__ +#define __PGM_SKBUFF_H__ + +#include <string.h> + +struct pgm_sk_buff_t; + +#include <pgm/types.h> +#include <pgm/atomic.h> +#include <pgm/mem.h> +#include <pgm/list.h> +#include <pgm/time.h> +#include <pgm/packet.h> +#include <pgm/tsi.h> +#include <pgm/socket.h> + +PGM_BEGIN_DECLS + +struct pgm_sk_buff_t { + pgm_list_t link_; + + pgm_sock_t* restrict sock; + pgm_time_t tstamp; + pgm_tsi_t tsi; + + uint32_t sequence; + uint32_t __padding; /* push alignment of pgm_sk_buff_t::cb to 8 bytes */ + + char cb[48]; /* control buffer */ + + uint16_t len; /* actual data */ + unsigned zero_padded:1; + + struct pgm_header* pgm_header; + struct pgm_opt_fragment* pgm_opt_fragment; +#define of_apdu_first_sqn pgm_opt_fragment->opt_sqn +#define of_frag_offset pgm_opt_fragment->opt_frag_off +#define of_apdu_len pgm_opt_fragment->opt_frag_len + struct pgm_opt_pgmcc_data* pgm_opt_pgmcc_data; + struct pgm_data* pgm_data; + + void *head, /* all may-alias */ + *data, + *tail, + *end; + uint32_t truesize; + volatile uint32_t users; /* atomic */ +}; + +void pgm_skb_over_panic (const struct pgm_sk_buff_t*const, const uint16_t) PGM_GNUC_NORETURN; +void pgm_skb_under_panic (const struct pgm_sk_buff_t*const, const uint16_t) PGM_GNUC_NORETURN; +bool pgm_skb_is_valid (const struct pgm_sk_buff_t*const) PGM_GNUC_PURE PGM_GNUC_WARN_UNUSED_RESULT; + +/* attribute __pure__ only valid for platforms with atomic ops. + * attribute __malloc__ not used as only part of the memory should be aliased. + * attribute __alloc_size__ does not allow headroom. + */ +static inline struct pgm_sk_buff_t* pgm_alloc_skb (const uint16_t) PGM_GNUC_WARN_UNUSED_RESULT; + +static inline +struct pgm_sk_buff_t* +pgm_alloc_skb ( + const uint16_t size + ) +{ + struct pgm_sk_buff_t* skb; + + skb = (struct pgm_sk_buff_t*)pgm_malloc (size + sizeof(struct pgm_sk_buff_t)); + if (PGM_UNLIKELY(pgm_mem_gc_friendly)) { + memset (skb, 0, size + sizeof(struct pgm_sk_buff_t)); + skb->zero_padded = 1; + } else { + memset (skb, 0, sizeof(struct pgm_sk_buff_t)); + } + skb->truesize = size + sizeof(struct pgm_sk_buff_t); + pgm_atomic_write32 (&skb->users, 1); + skb->head = skb + 1; + skb->data = skb->tail = skb->head; + skb->end = (char*)skb->data + size; + return skb; +} + +/* increase reference count */ +static inline +struct pgm_sk_buff_t* +pgm_skb_get ( + struct pgm_sk_buff_t*const skb + ) +{ + pgm_atomic_inc32 (&skb->users); + return skb; +} + +static inline +void +pgm_free_skb ( + struct pgm_sk_buff_t*const skb + ) +{ + if (pgm_atomic_exchange_and_add32 (&skb->users, (uint32_t)-1) == 1) + pgm_free (skb); +} + +/* add data */ +static inline +void* +pgm_skb_put ( + struct pgm_sk_buff_t* const skb, + const uint16_t len + ) +{ + void* tmp = skb->tail; + skb->tail = (char*)skb->tail + len; + skb->len += len; + if (PGM_UNLIKELY(skb->tail > skb->end)) + pgm_skb_over_panic (skb, len); + return tmp; +} + +static inline +void* +__pgm_skb_pull ( + struct pgm_sk_buff_t*const skb, + const uint16_t len + ) +{ + skb->len -= len; + return skb->data = (char*)skb->data + len; +} + +/* remove data from start of buffer */ +static inline +void* +pgm_skb_pull ( + struct pgm_sk_buff_t*const skb, + const uint16_t len + ) +{ + return PGM_UNLIKELY(len > skb->len) ? NULL : __pgm_skb_pull (skb, len); +} + +static inline uint16_t pgm_skb_headroom (const struct pgm_sk_buff_t*const) PGM_GNUC_PURE PGM_GNUC_WARN_UNUSED_RESULT; +static inline uint16_t pgm_skb_tailroom (const struct pgm_sk_buff_t*const) PGM_GNUC_PURE PGM_GNUC_WARN_UNUSED_RESULT; + +static inline +uint16_t +pgm_skb_headroom ( + const struct pgm_sk_buff_t*const skb + ) +{ + return (char*)skb->data - (char*)skb->head; +} + +static inline +uint16_t +pgm_skb_tailroom ( + const struct pgm_sk_buff_t*const skb + ) +{ + return (char*)skb->end - (char*)skb->tail; +} + +/* reserve space to add data */ +static inline +void +pgm_skb_reserve ( + struct pgm_sk_buff_t*const skb, + const uint16_t len + ) +{ + skb->data = (char*)skb->data + len; + skb->tail = (char*)skb->tail + len; + if (PGM_UNLIKELY(skb->tail > skb->end)) + pgm_skb_over_panic (skb, len); + if (PGM_UNLIKELY(skb->data < skb->head)) + pgm_skb_under_panic (skb, len); +} + +static inline struct pgm_sk_buff_t* pgm_skb_copy (const struct pgm_sk_buff_t* const) PGM_GNUC_WARN_UNUSED_RESULT; + +static inline +struct pgm_sk_buff_t* +pgm_skb_copy ( + const struct pgm_sk_buff_t* const skb + ) +{ + struct pgm_sk_buff_t* newskb; + newskb = (struct pgm_sk_buff_t*)pgm_malloc (skb->truesize); + memcpy (newskb, skb, PGM_OFFSETOF(struct pgm_sk_buff_t, pgm_header)); + newskb->zero_padded = 0; + newskb->truesize = skb->truesize; + pgm_atomic_write32 (&newskb->users, 1); + newskb->head = newskb + 1; + newskb->end = (char*)newskb->head + ((char*)skb->end - (char*)skb->head); + newskb->data = (char*)newskb->head + ((char*)skb->data - (char*)skb->head); + newskb->tail = (char*)newskb->head + ((char*)skb->tail - (char*)skb->head); + newskb->pgm_header = skb->pgm_header ? (struct pgm_header*)((char*)newskb->head + ((char*)skb->pgm_header - (char*)skb->head)) : skb->pgm_header; + newskb->pgm_opt_fragment = skb->pgm_opt_fragment ? (struct pgm_opt_fragment*)((char*)newskb->head + ((char*)skb->pgm_opt_fragment - (char*)skb->head)) : skb->pgm_opt_fragment; + newskb->pgm_data = skb->pgm_data ? (struct pgm_data*)((char*)newskb->head + ((char*)skb->pgm_data - (char*)skb->head)) : skb->pgm_data; + memcpy (newskb->head, skb->head, (char*)skb->end - (char*)skb->head); + return newskb; +} + +static inline +void +pgm_skb_zero_pad ( + struct pgm_sk_buff_t* const skb, + const uint16_t len + ) +{ + if (skb->zero_padded) + return; + + const uint16_t tailroom = MIN(pgm_skb_tailroom (skb), len); + if (tailroom > 0) + memset (skb->tail, 0, tailroom); + skb->zero_padded = 1; +} + +PGM_END_DECLS + +#endif /* __PGM_SKBUFF_H__ */ |