osmo-cc-misdn-endpoint/src/libmisdnuser/include/mISDN/mbuffer.h

260 lines
5.3 KiB
C

/* mbuffer.h
*
* Author Karsten Keil <kkeil@linux-pingi.de>
*
* Copyright 2007 by Karsten Keil <kkeil@novell.com>
* Copyright 2011 by Karsten Keil <kkeil@linux-pingi.de>
*
* This code is free software; you can redistribute it and/or modify
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
* version 2.1 as published by the Free Software Foundation.
*
* This code 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.
*
*/
#ifndef _MBUFFER_H
#define _MBUFFER_H
#ifdef __cplusplus
extern "C" {
#endif
#include <sys/socket.h>
#include <pthread.h>
#include <semaphore.h>
#include <mISDN/mISDNif.h>
#include <mISDN/mlayer3.h>
#ifndef eprint
#define eprint(fmt, ...) mi_printf(__FILE__, __LINE__, __PRETTY_FUNCTION__, 1, fmt, ##__VA_ARGS__)
extern int mi_printf(const char *file, int line, const char *func, int lev, const char *fmt, ...) __attribute__ ((format (printf,5,6)));
#endif
struct mqueue {
struct mbuffer *prev;
struct mbuffer *next;
pthread_mutex_t lock;
int len;
};
#ifdef MEMLEAK_DEBUG
struct lhead {
struct lhead *prev;
struct lhead *next;
};
#endif
struct mbuffer {
struct mbuffer *prev;
struct mbuffer *next;
struct mqueue *list;
int refcnt;
struct mISDNhead *h;
struct sockaddr_mISDN addr;
unsigned char *head;
unsigned char *data;
unsigned char *tail;
unsigned char *end;
unsigned char *chead;
unsigned char *ctail;
unsigned char *cend;
int len;
struct l3_head l3h;
struct l3_msg l3;
#ifdef MEMLEAK_DEBUG
struct lhead Alist;
char d_fn[80];
int d_ln;
#endif
} __attribute__((__may_alias__));
#define MBUFFER_DATA_SIZE 280
/*
* init mbuffer caching
* @parameter count of cached mbuffers
*/
extern void init_mbuffer(int);
/*
* free the cache
*/
extern void cleanup_mbuffer(void);
#ifdef MEMLEAK_DEBUG
/*
* alloc a new mbuffer
*/
extern struct mbuffer *__alloc_mbuffer(const char *file, int lineno, const char *func);
/*
* free the message
*/
extern void __free_mbuffer(struct mbuffer *, const char *file, int lineno, const char *func);
#define alloc_mbuffer() __alloc_mbuffer(__FILE__, __LINE__, __PRETTY_FUNCTION__)
#define free_mbuffer(p) __free_mbuffer(p, __FILE__, __LINE__, __PRETTY_FUNCTION__)
#else
/*
* alloc a new mbuffer
*/
extern struct mbuffer *alloc_mbuffer(void);
/*
* free the message
*/
extern void free_mbuffer(struct mbuffer *);
#endif
static inline void
mqueue_init(struct mqueue *q)
{
pthread_mutex_init(&q->lock, NULL);
q->len = 0;
q->prev = (struct mbuffer *)q;
q->next = (struct mbuffer *)q;
}
static inline int mqueue_len(struct mqueue *q)
{
return(q->len);
}
static inline void mqueue_head(struct mqueue *q, struct mbuffer *newm)
{
pthread_mutex_lock(&q->lock);
newm->list = q;
q->len++;
q->next->prev = newm;
newm->next = q->next;
newm->prev = (struct mbuffer *)q;
q->next = newm;
pthread_mutex_unlock(&q->lock);
}
static inline void mqueue_tail(struct mqueue *q, struct mbuffer *newm)
{
pthread_mutex_lock(&q->lock);
newm->list = q;
q->len++;
q->prev->next = newm;
newm->next = (struct mbuffer *)q;;
newm->prev = q->prev;
q->prev = newm;
pthread_mutex_unlock(&q->lock);
}
static inline struct mbuffer *mdequeue(struct mqueue *q)
{
struct mbuffer *next, *prev, *result;
pthread_mutex_lock(&q->lock);
prev = (struct mbuffer *)q;
next = prev->next;
result = NULL;
if (next != prev) {
result = next;
next = next->next;
q->len--;
next->prev = prev;
prev->next = next;
result->list = NULL;
}
pthread_mutex_unlock(&q->lock);
return result;
}
static __inline__ void mqueue_purge(struct mqueue *q)
{
struct mbuffer *mb;
while ((mb = mdequeue(q))!=NULL)
free_mbuffer(mb);
}
static __inline__ unsigned char *msg_put(struct mbuffer *msg, unsigned int len)
{
unsigned char *tmp = msg->tail;
msg->tail += len;
msg->len += len;
if (msg->tail > msg->end) {
eprint("msg_over_panic msg(%p) data(%p) head(%p)\n",
msg, msg->data, msg->head);
return NULL;
}
return tmp;
}
static __inline__ unsigned char *msg_push(struct mbuffer *msg, unsigned int len)
{
msg->data -= len;
msg->len += len;
if(msg->data < msg->head)
{
eprint("msg_under_panic msg(%p) data(%p) head(%p)\n",
msg, msg->data, msg->head);
return NULL;
}
return msg->data;
}
static __inline__ unsigned char *__msg_pull(struct mbuffer *msg, unsigned int len)
{
unsigned char *tmp = msg->data;
msg->len -= len;
msg->data += len;
return tmp;
}
static __inline__ unsigned char * msg_pull(struct mbuffer *msg, unsigned int len)
{
if (len > (unsigned int)msg->len)
return NULL;
return (unsigned char *)__msg_pull(msg,len);
}
static __inline__ int msg_headroom(struct mbuffer *msg)
{
return msg->data - msg->head;
}
static __inline__ int msg_tailroom(struct mbuffer *msg)
{
return msg->end-msg->tail;
}
static __inline__ void msg_reserve(struct mbuffer *msg, unsigned int len)
{
msg->data += len;
msg->tail += len;
}
static __inline__ void __msg_trim(struct mbuffer *msg, unsigned int len)
{
msg->len = len;
msg->tail = msg->data + len;
}
static __inline__ void msg_trim(struct mbuffer *msg, unsigned int len)
{
if ((unsigned int)msg->len > len) {
__msg_trim(msg, len);
}
}
#ifdef __cplusplus
}
#endif
#endif