mirror of https://gerrit.osmocom.org/libosmocore
start to add doxygen documentation to libosmocore headers
This commit is contained in:
parent
300e78d3e5
commit
bd598e3c5e
|
@ -3,9 +3,13 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef int8_t sbit_t; /* soft bit (-127...127) */
|
||||
typedef uint8_t ubit_t; /* unpacked bit (0 or 1) */
|
||||
typedef uint8_t pbit_t; /* packed bis (8 bits in a byte) */
|
||||
/*! \file bits.h
|
||||
* \brief Osmocom bit level support code
|
||||
*/
|
||||
|
||||
typedef int8_t sbit_t; /*!< \brief soft bit (-127...127) */
|
||||
typedef uint8_t ubit_t; /*!< \brief unpacked bit (0 or 1) */
|
||||
typedef uint8_t pbit_t; /*!< \brief packed bis (8 bits in a byte) */
|
||||
|
||||
/*
|
||||
NOTE on the endianess of pbit_t:
|
||||
|
@ -13,7 +17,9 @@ typedef uint8_t pbit_t; /* packed bis (8 bits in a byte) */
|
|||
Bit i in a pbit_t array is array[i/8] & (1<<(7-i%8))
|
||||
*/
|
||||
|
||||
/* determine how many bytes we would need for 'num_bits' packed bits */
|
||||
/*! \brief determine how many bytes we would need for \a num_bits packed bits
|
||||
* \param[in] num_bits Number of packed bits
|
||||
*/
|
||||
static inline unsigned int osmo_pbit_bytesize(unsigned int num_bits)
|
||||
{
|
||||
unsigned int pbit_bytesize = num_bits / 8;
|
||||
|
@ -24,20 +30,42 @@ static inline unsigned int osmo_pbit_bytesize(unsigned int num_bits)
|
|||
return pbit_bytesize;
|
||||
}
|
||||
|
||||
/* convert unpacked bits to packed bits, return length in bytes */
|
||||
/*! \brief convert unpacked bits to packed bits, return length in bytes
|
||||
* \param[out] out output buffer of packed bits
|
||||
* \param[in] in input buffer of unpacked bits
|
||||
* \param[in] num_bits number of bits
|
||||
*/
|
||||
int osmo_ubit2pbit(pbit_t *out, const ubit_t *in, unsigned int num_bits);
|
||||
|
||||
/* convert packed bits to unpacked bits, return length in bytes */
|
||||
/*! \brief convert packed bits to unpacked bits, return length in bytes
|
||||
* \param[out] out output buffer of unpacked bits
|
||||
* \param[in] in input buffer of packed bits
|
||||
* \param[in] num_bits number of bits
|
||||
*/
|
||||
int osmo_pbit2ubit(ubit_t *out, const pbit_t *in, unsigned int num_bits);
|
||||
|
||||
/* convert unpacked bits to packed bits (extended options but slower),
|
||||
* return length in bytes (max written ofs of output buffer + 1) */
|
||||
/*! \brief convert unpacked bits to packed bits (extended options)
|
||||
* \param[out] out output buffer of packed bits
|
||||
* \param[in] out_ofs offset into output buffer
|
||||
* \param[in] in input buffer of unpacked bits
|
||||
* \param[in] in_ofs offset into input buffer
|
||||
* \param[in] num_bits number of bits
|
||||
* \param[in] lsb_mode Encode bits in LSB orde instead of MSB
|
||||
* \returns length in bytes (max written offset of output buffer + 1)
|
||||
*/
|
||||
int osmo_ubit2pbit_ext(pbit_t *out, unsigned int out_ofs,
|
||||
const ubit_t *in, unsigned int in_ofs,
|
||||
unsigned int num_bits, int lsb_mode);
|
||||
|
||||
/* convert packed bits to unpacked bits (extended options but slower),
|
||||
* return length in bytes (max written ofs of output buffer + 1) */
|
||||
/*! \brief convert packed bits to unpacked bits (extended options)
|
||||
* \param[out] out output buffer of unpacked bits
|
||||
* \param[in] out_ofs offset into output buffer
|
||||
* \param[in] in input buffer of packed bits
|
||||
* \param[in] in_ofs offset into input buffer
|
||||
* \param[in] num_bits number of bits
|
||||
* \param[in] lsb_mode Encode bits in LSB orde instead of MSB
|
||||
* \returns length in bytes (max written offset of output buffer + 1)
|
||||
*/
|
||||
int osmo_pbit2ubit_ext(ubit_t *out, unsigned int out_ofs,
|
||||
const pbit_t *in, unsigned int in_ofs,
|
||||
unsigned int num_bits, int lsb_mode);
|
||||
|
|
|
@ -1,11 +1,17 @@
|
|||
#ifndef _OSMOCORE_LOGGING_H
|
||||
#define _OSMOCORE_LOGGING_H
|
||||
|
||||
/*! \file logging.h
|
||||
* \brief Osmocom logging framework
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
|
||||
/*! \brief Maximum number of logging contexts */
|
||||
#define LOG_MAX_CTX 8
|
||||
/*! \brief Maximum number of logging filters */
|
||||
#define LOG_MAX_FILTERS 8
|
||||
|
||||
#define DEBUG
|
||||
|
@ -21,9 +27,21 @@
|
|||
|
||||
void logp(int subsys, char *file, int line, int cont, const char *format, ...) __attribute__ ((format (printf, 5, 6)));
|
||||
|
||||
/* new logging interface */
|
||||
/*! \brief Log a new message through the Osmocom logging framework
|
||||
* \param[in] ss logging subsystem (e.g. \ref DLGLOBAL)
|
||||
* \param[in] level logging level (e.g. \ref LOGL_NOTICE)
|
||||
* \param[in] fmt format string
|
||||
* \param[in] args variable argument list
|
||||
*/
|
||||
#define LOGP(ss, level, fmt, args...) \
|
||||
logp2(ss, level, __FILE__, __LINE__, 0, fmt, ##args)
|
||||
|
||||
/*! \brief Continue a log message through the Osmocom logging framework
|
||||
* \param[in] ss logging subsystem (e.g. \ref DLGLOBAL)
|
||||
* \param[in] level logging level (e.g. \ref LOGL_NOTICE)
|
||||
* \param[in] fmt format string
|
||||
* \param[in] args variable argument list
|
||||
*/
|
||||
#define LOGPC(ss, level, fmt, args...) \
|
||||
logp2(ss, level, __FILE__, __LINE__, 1, fmt, ##args)
|
||||
|
||||
|
@ -151,7 +169,12 @@ struct log_target *log_target_create_syslog(const char *ident, int option,
|
|||
int facility);
|
||||
int log_target_file_reopen(struct log_target *tgt);
|
||||
|
||||
/*! \brief Add a new logging target
|
||||
*/
|
||||
void log_add_target(struct log_target *target);
|
||||
|
||||
/*! \brief Deelete an existing logging target
|
||||
*/
|
||||
void log_del_target(struct log_target *target);
|
||||
|
||||
/* Generate command string for VTY use */
|
||||
|
|
|
@ -24,45 +24,85 @@
|
|||
#include <osmocom/core/linuxlist.h>
|
||||
#include <osmocom/core/utils.h>
|
||||
|
||||
/*! \file msgb.h
|
||||
* \brief Osmocom message buffers
|
||||
* The Osmocom message buffers are modelled after the 'struct skb'
|
||||
* inside the Linux kernel network stack. As they exist in userspace,
|
||||
* they are much simplified. However, terminology such as headroom,
|
||||
* tailroom, push/pull/put etc. remains the same.
|
||||
*/
|
||||
|
||||
#define MSGB_DEBUG
|
||||
|
||||
/*! \brief Osmocom message buffer */
|
||||
struct msgb {
|
||||
struct llist_head list;
|
||||
struct llist_head list; /*!< \brief linked list header */
|
||||
|
||||
|
||||
/* Part of which TRX logical channel we were received / transmitted */
|
||||
/* FIXME: move them into the control buffer */
|
||||
union {
|
||||
void *dst;
|
||||
void *dst; /*!< \brief reference of origin/destination */
|
||||
struct gsm_bts_trx *trx;
|
||||
};
|
||||
struct gsm_lchan *lchan;
|
||||
struct gsm_lchan *lchan; /*!< \brief logical channel */
|
||||
|
||||
/* the Layer1 header (if any) */
|
||||
unsigned char *l1h;
|
||||
/* the A-bis layer 2 header: OML, RSL(RLL), NS */
|
||||
unsigned char *l2h;
|
||||
/* the layer 3 header. For OML: FOM; RSL: 04.08; GPRS: BSSGP */
|
||||
unsigned char *l3h;
|
||||
/* the layer 4 header */
|
||||
unsigned char *l4h;
|
||||
unsigned char *l1h; /*!< \brief pointer to Layer1 header (if any) */
|
||||
unsigned char *l2h; /*!< \brief pointer to A-bis layer 2 header: OML, RSL(RLL), NS */
|
||||
unsigned char *l3h; /*!< \brief pointer to Layer 3 header. For OML: FOM; RSL: 04.08; GPRS: BSSGP */
|
||||
unsigned char *l4h; /*!< \brief pointer to layer 4 header */
|
||||
|
||||
/* the 'control buffer', large enough to contain 5 pointers */
|
||||
unsigned long cb[5];
|
||||
unsigned long cb[5]; /*!< \brief control buffer */
|
||||
|
||||
uint16_t data_len;
|
||||
uint16_t len;
|
||||
uint16_t data_len; /*!< \brief length of underlying data array */
|
||||
uint16_t len; /*!< \brief length of bytes used in msgb */
|
||||
|
||||
unsigned char *head;
|
||||
unsigned char *tail;
|
||||
unsigned char *data;
|
||||
unsigned char _data[0];
|
||||
unsigned char *head; /*!< \brief start of underlying memory buffer */
|
||||
unsigned char *tail; /*!< \brief end of message in buffer */
|
||||
unsigned char *data; /*!< \brief start of message in buffer */
|
||||
unsigned char _data[0]; /*!< \brief optional immediate data array */
|
||||
};
|
||||
|
||||
/*! \brief Allocate a new message buffer
|
||||
* \param[in] size Length in octets, including headroom
|
||||
* \param[in] name Human-readable name to be associated with msgb
|
||||
*
|
||||
* This function allocates a 'struct msgb' as well as the underlying
|
||||
* memory buffer for the actual message data (size specified by \a size)
|
||||
* using the talloc memory context previously set by \ref msgb_set_talloc_ctx
|
||||
*/
|
||||
extern struct msgb *msgb_alloc(uint16_t size, const char *name);
|
||||
|
||||
/*! \brief Release given message buffer
|
||||
* \param[in] m Message buffer to be free'd
|
||||
*/
|
||||
extern void msgb_free(struct msgb *m);
|
||||
|
||||
/*! \brief Enqueue message buffer to tail of a queue
|
||||
* \param[in] queue linked list header of queue
|
||||
* \param[in] msgb message buffer to be added to the queue
|
||||
*
|
||||
* The function will append the specified message buffer \a msg to the
|
||||
* queue implemented by \ref llist_head \a queue
|
||||
*/
|
||||
extern void msgb_enqueue(struct llist_head *queue, struct msgb *msg);
|
||||
|
||||
/*! \brief Dequeue message buffer from head of queue
|
||||
* \param[in] queue linked list header of queue
|
||||
* \returns message buffer (if any) or NULL if queue empty
|
||||
*
|
||||
* The function will remove the first message buffer from the queue
|
||||
* implemented by 'ref llist_head \a queue.
|
||||
*/
|
||||
extern struct msgb *msgb_dequeue(struct llist_head *queue);
|
||||
|
||||
/*! \brief Re-set all message buffer pointers
|
||||
* \param[in] m message buffer that is to be resetted
|
||||
*
|
||||
* This will re-set the various internal pointers into the underlying
|
||||
* message buffer, i.e. remvoe all headroom and treat the msgb as
|
||||
* completely empty. It also initializes the control buffer to zero.
|
||||
*/
|
||||
extern void msgb_reset(struct msgb *m);
|
||||
|
||||
#ifdef MSGB_DEBUG
|
||||
|
@ -74,41 +114,99 @@ extern void msgb_reset(struct msgb *m);
|
|||
#define MSGB_ABORT(msg, fmt, args ...)
|
||||
#endif
|
||||
|
||||
/*! \brief obtain L1 header of msgb */
|
||||
#define msgb_l1(m) ((void *)(m->l1h))
|
||||
/*! \brief obtain L2 header of msgb */
|
||||
#define msgb_l2(m) ((void *)(m->l2h))
|
||||
/*! \brief obtain L3 header of msgb */
|
||||
#define msgb_l3(m) ((void *)(m->l3h))
|
||||
/*! \brief obtain SMS header of msgb */
|
||||
#define msgb_sms(m) ((void *)(m->l4h))
|
||||
|
||||
/*! \brief determine length of L1 message
|
||||
* \param[in] msgb message buffer
|
||||
* \returns size of L1 message in bytes
|
||||
*
|
||||
* This function computes the number of bytes between the tail of the
|
||||
* message and the layer 1 header.
|
||||
*/
|
||||
static inline unsigned int msgb_l1len(const struct msgb *msgb)
|
||||
{
|
||||
return msgb->tail - (uint8_t *)msgb_l1(msgb);
|
||||
}
|
||||
|
||||
/*! \brief determine length of L2 message
|
||||
* \param[in] msgb message buffer
|
||||
* \returns size of L2 message in bytes
|
||||
*
|
||||
* This function computes the number of bytes between the tail of the
|
||||
* message and the layer 2 header.
|
||||
*/
|
||||
static inline unsigned int msgb_l2len(const struct msgb *msgb)
|
||||
{
|
||||
return msgb->tail - (uint8_t *)msgb_l2(msgb);
|
||||
}
|
||||
|
||||
/*! \brief determine length of L3 message
|
||||
* \param[in] msgb message buffer
|
||||
* \returns size of L3 message in bytes
|
||||
*
|
||||
* This function computes the number of bytes between the tail of the
|
||||
* message and the layer 3 header.
|
||||
*/
|
||||
static inline unsigned int msgb_l3len(const struct msgb *msgb)
|
||||
{
|
||||
return msgb->tail - (uint8_t *)msgb_l3(msgb);
|
||||
}
|
||||
|
||||
/*! \brief determine the length of the header
|
||||
* \param[in] msgb message buffer
|
||||
* \returns number of bytes between start of buffer and start of msg
|
||||
*
|
||||
* This function computes the length difference between the underlying
|
||||
* data buffer and the used section of the \a msgb.
|
||||
*/
|
||||
static inline unsigned int msgb_headlen(const struct msgb *msgb)
|
||||
{
|
||||
return msgb->len - msgb->data_len;
|
||||
}
|
||||
|
||||
/*! \brief determine how much tail room is left in msgb
|
||||
* \param[in] msgb message buffer
|
||||
* \returns number of bytes remaining at end of msgb
|
||||
*
|
||||
* This function computes the amount of octets left in the underlying
|
||||
* data buffer after the end of the message.
|
||||
*/
|
||||
static inline int msgb_tailroom(const struct msgb *msgb)
|
||||
{
|
||||
return (msgb->head + msgb->data_len) - msgb->tail;
|
||||
}
|
||||
|
||||
/*! \brief determine the amount of headroom in msgb
|
||||
* \param[in] msgb message buffer
|
||||
* \returns number of bytes left ahead of message start in msgb
|
||||
*
|
||||
* This function computes the amount of bytes left in the underlying
|
||||
* data buffer before the start of the actual message.
|
||||
*/
|
||||
static inline int msgb_headroom(const struct msgb *msgb)
|
||||
{
|
||||
return (msgb->data - msgb->head);
|
||||
}
|
||||
|
||||
/*! \brief append data to end of message buffer
|
||||
* \param[in] msgb message buffer
|
||||
* \param[in] len number of bytes to append to message
|
||||
* \returns pointer to start of newly-appended data
|
||||
*
|
||||
* This function will move the \a tail pointer of the message buffer \a
|
||||
* len bytes further, thus enlarging the message by \a len bytes.
|
||||
*
|
||||
* The return value is a pointer to start of the newly added section at
|
||||
* the end of the message and can be used for actually filling/copying
|
||||
* data into it.
|
||||
*/
|
||||
static inline unsigned char *msgb_put(struct msgb *msgb, unsigned int len)
|
||||
{
|
||||
unsigned char *tmp = msgb->tail;
|
||||
|
@ -119,17 +217,32 @@ static inline unsigned char *msgb_put(struct msgb *msgb, unsigned int len)
|
|||
msgb->len += len;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*! \brief append a uint8 value to the end of the message
|
||||
* \param[in] msgb message buffer
|
||||
* \param[in] word unsigned 8bit byte to be appended
|
||||
*/
|
||||
static inline void msgb_put_u8(struct msgb *msgb, uint8_t word)
|
||||
{
|
||||
uint8_t *space = msgb_put(msgb, 1);
|
||||
space[0] = word & 0xFF;
|
||||
}
|
||||
|
||||
/*! \brief append a uint16 value to the end of the message
|
||||
* \param[in] msgb message buffer
|
||||
* \param[in] word unsigned 16bit byte to be appended
|
||||
*/
|
||||
static inline void msgb_put_u16(struct msgb *msgb, uint16_t word)
|
||||
{
|
||||
uint8_t *space = msgb_put(msgb, 2);
|
||||
space[0] = word >> 8 & 0xFF;
|
||||
space[1] = word & 0xFF;
|
||||
}
|
||||
|
||||
/*! \brief append a uint32 value to the end of the message
|
||||
* \param[in] msgb message buffer
|
||||
* \param[in] word unsigned 32bit byte to be appended
|
||||
*/
|
||||
static inline void msgb_put_u32(struct msgb *msgb, uint32_t word)
|
||||
{
|
||||
uint8_t *space = msgb_put(msgb, 4);
|
||||
|
@ -138,6 +251,11 @@ static inline void msgb_put_u32(struct msgb *msgb, uint32_t word)
|
|||
space[2] = word >> 8 & 0xFF;
|
||||
space[3] = word & 0xFF;
|
||||
}
|
||||
|
||||
/*! \brief remove data from end of message
|
||||
* \param[in] msgb message buffer
|
||||
* \param[in] len number of bytes to remove from end
|
||||
*/
|
||||
static inline unsigned char *msgb_get(struct msgb *msgb, unsigned int len)
|
||||
{
|
||||
unsigned char *tmp = msgb->data;
|
||||
|
@ -145,21 +263,46 @@ static inline unsigned char *msgb_get(struct msgb *msgb, unsigned int len)
|
|||
msgb->len -= len;
|
||||
return tmp;
|
||||
}
|
||||
/*! \brief remove uint8 from end of message
|
||||
* \param[in] msgb message buffer
|
||||
* \returns 8bit value taken from end of msgb
|
||||
*/
|
||||
static inline uint8_t msgb_get_u8(struct msgb *msgb)
|
||||
{
|
||||
uint8_t *space = msgb_get(msgb, 1);
|
||||
return space[0];
|
||||
}
|
||||
/*! \brief remove uint16 from end of message
|
||||
* \param[in] msgb message buffer
|
||||
* \returns 16bit value taken from end of msgb
|
||||
*/
|
||||
static inline uint16_t msgb_get_u16(struct msgb *msgb)
|
||||
{
|
||||
uint8_t *space = msgb_get(msgb, 2);
|
||||
return space[0] << 8 | space[1];
|
||||
}
|
||||
/*! \brief remove uint32 from end of message
|
||||
* \param[in] msgb message buffer
|
||||
* \returns 32bit value taken from end of msgb
|
||||
*/
|
||||
static inline uint32_t msgb_get_u32(struct msgb *msgb)
|
||||
{
|
||||
uint8_t *space = msgb_get(msgb, 4);
|
||||
return space[0] << 24 | space[1] << 16 | space[2] << 8 | space[3];
|
||||
}
|
||||
|
||||
/*! \brief prepend (push) some data to start of message
|
||||
* \param[in] msgb message buffer
|
||||
* \param[in] len number of bytes to pre-pend
|
||||
* \returns pointer to newly added portion at start of \a msgb
|
||||
*
|
||||
* This function moves the \a data pointer of the \ref msgb further
|
||||
* to the front (by \a len bytes), thereby enlarging the message by \a
|
||||
* len bytes.
|
||||
*
|
||||
* The return value is a pointer to the newly added section in the
|
||||
* beginning of the message. It can be used to fill/copy data into it.
|
||||
*/
|
||||
static inline unsigned char *msgb_push(struct msgb *msgb, unsigned int len)
|
||||
{
|
||||
if (msgb_headroom(msgb) < (int) len)
|
||||
|
@ -169,19 +312,48 @@ static inline unsigned char *msgb_push(struct msgb *msgb, unsigned int len)
|
|||
msgb->len += len;
|
||||
return msgb->data;
|
||||
}
|
||||
/*! \brief remove (pull) a header from the front of the message buffer
|
||||
* \param[in] msgb message buffer
|
||||
* \param[in] len number of octets to be pulled
|
||||
* \returns pointer to new start of msgb
|
||||
*
|
||||
* This function moves the \a data pointer of the \ref msgb further back
|
||||
* in the message, thereby shrinking the size of the message by \a len
|
||||
* bytes.
|
||||
*/
|
||||
static inline unsigned char *msgb_pull(struct msgb *msgb, unsigned int len)
|
||||
{
|
||||
msgb->len -= len;
|
||||
return msgb->data += len;
|
||||
}
|
||||
|
||||
/* increase the headroom of an empty msgb, reducing the tailroom */
|
||||
/*! \brief Increase headroom of empty msgb, reducing the tailroom
|
||||
* \param[in] msg message buffer
|
||||
* \param[in] len amount of extra octets to be reserved as headroom
|
||||
*
|
||||
* This function reserves some memory at the beginning of the underlying
|
||||
* data buffer. The idea is to reserve space in case further headers
|
||||
* have to be pushed to the \ref msgb during further processing.
|
||||
*
|
||||
* Calling this function leads to undefined reusults if it is called on
|
||||
* a non-empty \ref msgb.
|
||||
*/
|
||||
static inline void msgb_reserve(struct msgb *msg, int len)
|
||||
{
|
||||
msg->data += len;
|
||||
msg->tail += len;
|
||||
}
|
||||
|
||||
/*! \brief Allocate message buffer with specified headroom
|
||||
* \param[in] size size in bytes, including headroom
|
||||
* \param[in] headroom headroom in bytes
|
||||
* \param[in] name human-readable name
|
||||
* \returns allocated message buffer with specified headroom
|
||||
*
|
||||
* This function is a convenience wrapper around \ref msgb_alloc
|
||||
* followed by \ref msgb_reserve in order to create a new \ref msgb with
|
||||
* user-specified amount of headroom.
|
||||
*/
|
||||
static inline struct msgb *msgb_alloc_headroom(int size, int headroom,
|
||||
const char *name)
|
||||
{
|
||||
|
@ -194,10 +366,22 @@ static inline struct msgb *msgb_alloc_headroom(int size, int headroom,
|
|||
}
|
||||
|
||||
/* non inline functions to ease binding */
|
||||
|
||||
/*! \brief get pointer to data section of message buffer
|
||||
* \param[in] msg message buffer
|
||||
* \returns pointer to data section of message buffer
|
||||
*/
|
||||
uint8_t *msgb_data(const struct msgb *msg);
|
||||
|
||||
/*! \brief get length of message buffer
|
||||
* \param[in] msg message buffer
|
||||
* \returns length of data section in message buffer
|
||||
*/
|
||||
uint16_t msgb_length(const struct msgb *msg);
|
||||
|
||||
/* set the talloc context for msgb_alloc[_headroom] */
|
||||
/*! \brief Set the talloc context for \ref msgb_alloc
|
||||
* \param[in] ctx talloc context to be used as root for msgb allocations
|
||||
*/
|
||||
void msgb_set_talloc_ctx(void *ctx);
|
||||
|
||||
#endif /* _MSGB_H */
|
||||
|
|
|
@ -3,20 +3,48 @@
|
|||
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
|
||||
/*! \file select.h
|
||||
* \brief select loop abstraction
|
||||
*/
|
||||
|
||||
/*! \brief Indicate interest in reading from the file descriptor */
|
||||
#define BSC_FD_READ 0x0001
|
||||
/*! \brief Indicate interest in writing to the file descriptor */
|
||||
#define BSC_FD_WRITE 0x0002
|
||||
/*! \brief Indicate interest in exceptions from the file descriptor */
|
||||
#define BSC_FD_EXCEPT 0x0004
|
||||
|
||||
/*! \brief Structure representing a file dsecriptor */
|
||||
struct osmo_fd {
|
||||
struct llist_head list;
|
||||
/*! linked list for internal management */
|
||||
struct llist_head list;
|
||||
/*! actual operating-system level file decriptor */
|
||||
int fd;
|
||||
/*! bit-mask or of \ref BSC_FD_READ, \ref BSC_FD_WRITE and/or
|
||||
* \ref BSC_FD_EXCEPT */
|
||||
unsigned int when;
|
||||
/*! call-back function to be called once file descriptor becomes
|
||||
* available */
|
||||
int (*cb)(struct osmo_fd *fd, unsigned int what);
|
||||
/*! data pointer passed through to call-back function */
|
||||
void *data;
|
||||
/*! private number, extending \a data */
|
||||
unsigned int priv_nr;
|
||||
};
|
||||
|
||||
/*! \brief Register a new file descriptor with select loop abstraction
|
||||
* \param[in] fd osmocom file descriptor to be registered
|
||||
*/
|
||||
int osmo_fd_register(struct osmo_fd *fd);
|
||||
|
||||
/*! \brief Unregister a file descriptor from select loop abstraction
|
||||
* \param[in] fd osmocom file descriptor to be unregistered
|
||||
*/
|
||||
void osmo_fd_unregister(struct osmo_fd *fd);
|
||||
|
||||
/*! \brief select main loop integration
|
||||
* \param[in] polling should we pollonly (1) or block on select (0)
|
||||
*/
|
||||
int osmo_select_main(int polling);
|
||||
|
||||
#endif /* _BSC_SELECT_H */
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
#ifndef _OSMOCORE_SOCKET_H
|
||||
#define _OSMOCORE_SOCKET_H
|
||||
|
||||
/*! \file socket.h
|
||||
* \brief Osmocom socket convenience functions
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct sockaddr;
|
||||
|
@ -10,16 +14,53 @@ struct sockaddr;
|
|||
#define OSMO_SOCK_F_BIND (1 << 1)
|
||||
#define OSMO_SOCK_F_NONBLOCK (1 << 2)
|
||||
|
||||
/*! \brief Initialize a socket (including bind/connect)
|
||||
* \param[in] family Address Family like AF_INET, AF_INET6, AF_UNSPEC
|
||||
* \param[in] type Socket type like SOCK_DGRAM, SOCK_STREAM
|
||||
* \param[in] proto Protocol like IPPROTO_TCP, IPPROTO_UDP
|
||||
* \param[in] host remote host name or IP address in string form
|
||||
* \param[in] port remote port number in host byte order
|
||||
* \param[in] flags flags like \ref OSMO_SOCK_F_CONNECT
|
||||
*
|
||||
* This function creates a new socket of the designated \a family, \a
|
||||
* type and \a proto and optionally binds or connects it, depending on
|
||||
* the value of \a flags parameter.
|
||||
*/
|
||||
int osmo_sock_init(uint16_t family, uint16_t type, uint8_t proto,
|
||||
const char *host, uint16_t port, unsigned int flags);
|
||||
|
||||
/*! \brief Initialize a socket and fill \ref osmo_fd
|
||||
* \param[out] osmocom file descriptor (will be filled in)
|
||||
* \param[in] family Address Family like AF_INET, AF_INET6, AF_UNSPEC
|
||||
* \param[in] type Socket type like SOCK_DGRAM, SOCK_STREAM
|
||||
* \param[in] proto Protocol like IPPROTO_TCP, IPPROTO_UDP
|
||||
* \param[in] host remote host name or IP address in string form
|
||||
* \param[in] port remote port number in host byte order
|
||||
* \param[in] flags flags like \ref OSMO_SOCK_F_CONNECT
|
||||
*
|
||||
* This function creates (and optionall binds/connects) a socket using
|
||||
* \ref osmo_sock_init, but also fills the \a ofd structure.
|
||||
*/
|
||||
int osmo_sock_init_ofd(struct osmo_fd *ofd, int family, int type, int proto,
|
||||
const char *host, uint16_t port, unsigned int flags);
|
||||
|
||||
/*! \brief Initialize a socket and fill \ref sockaddr
|
||||
* \param[out] ss socket address (will be filled in)
|
||||
* \param[in] type Socket type like SOCK_DGRAM, SOCK_STREAM
|
||||
* \param[in] proto Protocol like IPPROTO_TCP, IPPROTO_UDP
|
||||
* \param[in] flags flags like \ref OSMO_SOCK_F_CONNECT
|
||||
*
|
||||
* This function creates (and optionall binds/connects) a socket using
|
||||
* \ref osmo_sock_init, but also fills the \a ss structure.
|
||||
*/
|
||||
int osmo_sock_init_sa(struct sockaddr *ss, uint16_t type,
|
||||
uint8_t proto, unsigned int flags);
|
||||
|
||||
/* determine if the given address is a local address */
|
||||
/*! \brief Determine if the given address is a local address
|
||||
* \param[in] addr Socket Address
|
||||
* \param[in] addrlen Length of socket address in bytes
|
||||
* \returns 1 if address is local, 0 otherwise.
|
||||
*/
|
||||
int osmo_sockaddr_is_local(struct sockaddr *addr, unsigned int addrlen);
|
||||
|
||||
#endif /* _OSMOCORE_SOCKET_H */
|
||||
|
|
|
@ -1,33 +1,53 @@
|
|||
#ifndef _STATISTICS_H
|
||||
#define _STATISTICS_H
|
||||
|
||||
/*! \file statistics.h
|
||||
* \brief Common routines regarding statistics */
|
||||
|
||||
/*! structure representing a single counter */
|
||||
struct osmo_counter {
|
||||
struct llist_head list;
|
||||
const char *name;
|
||||
const char *description;
|
||||
unsigned long value;
|
||||
struct llist_head list; /*!< \brief internal list head */
|
||||
const char *name; /*!< \brief human-readable name */
|
||||
const char *description; /*!< \brief humn-readable description */
|
||||
unsigned long value; /*!< \brief current value */
|
||||
};
|
||||
|
||||
/*! \brief Increment counter */
|
||||
static inline void osmo_counter_inc(struct osmo_counter *ctr)
|
||||
{
|
||||
ctr->value++;
|
||||
}
|
||||
|
||||
/*! \brief Get current value of counter */
|
||||
static inline unsigned long osmo_counter_get(struct osmo_counter *ctr)
|
||||
{
|
||||
return ctr->value;
|
||||
}
|
||||
|
||||
/*! \brief Reset current value of counter to 0 */
|
||||
static inline void osmo_counter_reset(struct osmo_counter *ctr)
|
||||
{
|
||||
ctr->value = 0;
|
||||
}
|
||||
|
||||
/*! \brief Allocate a new counter */
|
||||
struct osmo_counter *osmo_counter_alloc(const char *name);
|
||||
|
||||
/*! \brief Free the specified counter
|
||||
* \param[ctr] Counter
|
||||
*/
|
||||
void osmo_counter_free(struct osmo_counter *ctr);
|
||||
|
||||
/*! \brief Iteate over all counters
|
||||
* \param[in] handle_counter Call-back function
|
||||
* \param[in] data Private dtata handed through to \a handle_counter
|
||||
*/
|
||||
int osmo_counters_for_each(int (*handle_counter)(struct osmo_counter *, void *), void *data);
|
||||
|
||||
/*! \brief Resolve counter by human-readable name
|
||||
* \param[in] name human-readable name of counter
|
||||
* \returns pointer to counter (\ref osmo_counter) or NULL otherwise
|
||||
*/
|
||||
struct osmo_counter *osmo_counter_get_by_name(const char *name);
|
||||
|
||||
#endif /* _STATISTICS_H */
|
||||
|
|
|
@ -18,6 +18,10 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/*! \file timer.h
|
||||
* \brief Osmocom timer handling routines
|
||||
*/
|
||||
|
||||
#ifndef TIMER_H
|
||||
#define TIMER_H
|
||||
|
||||
|
@ -41,27 +45,58 @@
|
|||
* the timers.
|
||||
*
|
||||
*/
|
||||
/*! \brief A structure representing a single instance of a timer */
|
||||
struct osmo_timer_list {
|
||||
struct llist_head entry;
|
||||
struct timeval timeout;
|
||||
unsigned int active : 1;
|
||||
unsigned int handled : 1;
|
||||
unsigned int in_list : 1;
|
||||
struct llist_head entry; /*!< \brief linked list header */
|
||||
struct timeval timeout; /*!< \brief expiration time */
|
||||
unsigned int active : 1; /*!< \brief is it active? */
|
||||
unsigned int handled : 1; /*!< \brief did we already handle it */
|
||||
unsigned int in_list : 1; /*!< \brief is it in the global list? */
|
||||
|
||||
void (*cb)(void*);
|
||||
void *data;
|
||||
void (*cb)(void*); /*!< \brief call-back called at timeout */
|
||||
void *data; /*!< \brief user data for callback */
|
||||
};
|
||||
|
||||
/**
|
||||
* timer management
|
||||
*/
|
||||
|
||||
/*! \brief add a new timer to the timer management
|
||||
* \param[in] timer the timer that should be added
|
||||
*/
|
||||
void osmo_timer_add(struct osmo_timer_list *timer);
|
||||
|
||||
/*! \brief schedule a timer at a given future relative time
|
||||
* \param[in] timer the to-be-added timer
|
||||
* \param[in] seconds number of seconds from now
|
||||
* \param[in] microseconds number of microseconds from now
|
||||
*
|
||||
* This function can be used to (re-)schedule a given timer at a
|
||||
* specified number of seconds+microseconds in the future. It will
|
||||
* internally add it to the timer management data structures, thus
|
||||
* osmo_timer_add() is automatically called.
|
||||
*/
|
||||
void osmo_timer_schedule(struct osmo_timer_list *timer, int seconds, int microseconds);
|
||||
|
||||
/*! \brief delete a timer from timer management
|
||||
* \param[in] timer the to-be-deleted timer
|
||||
*
|
||||
* This function can be used to delete a previously added/scheduled
|
||||
* timer from the timer management code.
|
||||
*/
|
||||
void osmo_timer_del(struct osmo_timer_list *timer);
|
||||
|
||||
/*! \brief check if given timer is still pending
|
||||
* \param[in] timer the to-be-checked timer
|
||||
* \return 1 if pending, 0 otherwise
|
||||
*
|
||||
* This function can be used to determine whether a given timer
|
||||
* has alredy expired (returns 0) or is still pending (returns 1)
|
||||
*/
|
||||
int osmo_timer_pending(struct osmo_timer_list *timer);
|
||||
|
||||
|
||||
/**
|
||||
/*
|
||||
* internal timer list management
|
||||
*/
|
||||
struct timeval *osmo_timers_nearest(void);
|
||||
|
|
|
@ -1,32 +1,93 @@
|
|||
#ifndef OSMOCORE_UTIL_H
|
||||
#define OSMOCORE_UTIL_H
|
||||
|
||||
/*! \file utils.h
|
||||
* \brief General-purpose utilities in the Osmocom core library
|
||||
*/
|
||||
|
||||
/*! \brief Determine number of elements in an array of static size */
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
/*! \brief Return the maximum of two specified values */
|
||||
#define OSMO_MAX(a, b) (a) >= (b) ? (a) : (b)
|
||||
/*! \brief Return the minimum of two specified values */
|
||||
#define OSMO_MIN(a, b) (a) >= (b) ? (b) : (a)
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*! \brief A mapping between human-readable string and numeric value */
|
||||
struct value_string {
|
||||
unsigned int value;
|
||||
const char *str;
|
||||
unsigned int value; /*!< \brief numeric value */
|
||||
const char *str; /*!< \brief human-readable string */
|
||||
};
|
||||
|
||||
/*! \fn get_value_string(const struct value_string *vs, uint32_t val)
|
||||
* \brief get human-readable string for given value
|
||||
* \param[in] vs Array of value_string tuples
|
||||
* \param[in] val Value to be converted
|
||||
* \returns pointer to human-readable string
|
||||
*/
|
||||
const char *get_value_string(const struct value_string *vs, uint32_t val);
|
||||
|
||||
/*! \fn get_string_value(const struct value_string *vs, const char *str)
|
||||
* \brief get numeric value for given human-readable string
|
||||
* \param[in] vs Array of value_string tuples
|
||||
* \param[in] str human-readable string
|
||||
* \returns numeric value (>0) or negative numer in case of error
|
||||
*/
|
||||
int get_string_value(const struct value_string *vs, const char *str);
|
||||
|
||||
/*! \fn osmo_bcd2char(uint8_t bcd)
|
||||
* \brief Convert BCD-encoded digit into printable character
|
||||
* \param[in] bcd A single BCD-encoded digit
|
||||
* \returns single printable character
|
||||
*/
|
||||
char osmo_bcd2char(uint8_t bcd);
|
||||
/* only works for numbers in ascci */
|
||||
uint8_t osmo_char2bcd(char c);
|
||||
|
||||
int osmo_hexparse(const char *str, uint8_t *b, int max_len);
|
||||
|
||||
/*! \fn osmo_hexdump(const unsigned char *buf, int len)
|
||||
* \brief Convert binary sequence to hexadecimal ASCII string
|
||||
* This function will print a sequence of bytes as hexadecimal numbers,
|
||||
* adding one space character between each byte (e.g. "1a ef d9")
|
||||
* \param[in] buf pointer to sequence of bytes
|
||||
* \param[in] len length of buf in number of bytes
|
||||
* \returns pointer to zero-terminated string
|
||||
*/
|
||||
char *osmo_hexdump(const unsigned char *buf, int len);
|
||||
|
||||
/*! \fn osmo_hexdump_nospc(const unsigned char *buf, int len)
|
||||
* \brief Convert binary sequence to hexadecimal ASCII string
|
||||
* This function will print a sequence of bytes as hexadecimal numbers,
|
||||
* without any space character between each byte (e.g. "1aefd9")
|
||||
* \param[in] buf pointer to sequence of bytes
|
||||
* \param[in] len length of buf in number of bytes
|
||||
* \returns pointer to zero-terminated string
|
||||
*/
|
||||
char *osmo_osmo_hexdump_nospc(const unsigned char *buf, int len);
|
||||
|
||||
/*! \fn osmo_ubit_dump(const uint8_t *bits, unsigned int len)
|
||||
* \brief Convert a sequence of unpacked bits to ASCII string
|
||||
* \param[in] bits A sequence of unpacked bits
|
||||
* \param[in] len Length of bits
|
||||
*/
|
||||
char *osmo_ubit_dump(const uint8_t *bits, unsigned int len);
|
||||
|
||||
#define osmo_static_assert(exp, name) typedef int dummy##name [(exp) ? 1 : -1];
|
||||
|
||||
/*! \fn osmo_str2lower(char *out, const char *in)
|
||||
* \brief Convert an entire string to lower case
|
||||
* \param[out] out output string, caller-allocated
|
||||
* \param[in] in input string
|
||||
*/
|
||||
void osmo_str2lower(char *out, const char *in);
|
||||
|
||||
/*! \fn osmo_str2upper(char *out, const char *in)
|
||||
* \brief Convert an entire string to upper case
|
||||
* \param[out] out output string, caller-allocated
|
||||
* \param[in] in input string
|
||||
*/
|
||||
void osmo_str2upper(char *out, const char *in);
|
||||
|
||||
#define OSMO_SNPRINTF_RET(ret, rem, offset, len) \
|
||||
|
|
|
@ -23,24 +23,59 @@
|
|||
#ifndef OSMO_WQUEUE_H
|
||||
#define OSMO_WQUEUE_H
|
||||
|
||||
/*! \file write_queue.h
|
||||
* \brief Osmocom write queues
|
||||
*/
|
||||
|
||||
#include <osmocom/core/select.h>
|
||||
#include <osmocom/core/msgb.h>
|
||||
|
||||
/*! write queue instance */
|
||||
struct osmo_wqueue {
|
||||
/*! \brief osmocom file descriptor */
|
||||
struct osmo_fd bfd;
|
||||
/*! \brief maximum length of write queue */
|
||||
unsigned int max_length;
|
||||
/*! \brief current length of write queue */
|
||||
unsigned int current_length;
|
||||
|
||||
/*! \brief actual linked list implementing the queue */
|
||||
struct llist_head msg_queue;
|
||||
|
||||
/*! \brief call-back in case qeueue is readable */
|
||||
int (*read_cb)(struct osmo_fd *fd);
|
||||
/*! \brief call-back in case qeueue is writable */
|
||||
int (*write_cb)(struct osmo_fd *fd, struct msgb *msg);
|
||||
/*! \brief call-back in case qeueue has exceptions */
|
||||
int (*except_cb)(struct osmo_fd *fd);
|
||||
};
|
||||
|
||||
/*! \brief Initialize a \ref osmo_wqueue structure
|
||||
* \param[in] queue Write queue to operate on
|
||||
* \param[in] max_length Maximum length of write queue
|
||||
*/
|
||||
void osmo_wqueue_init(struct osmo_wqueue *queue, int max_length);
|
||||
|
||||
/*! \brief Clear a \ref osmo_wqueue
|
||||
* \param[in] queue Write queue to be cleared
|
||||
*
|
||||
* This function will clear (remove/release) all messages in it.
|
||||
*/
|
||||
void osmo_wqueue_clear(struct osmo_wqueue *queue);
|
||||
|
||||
/*! \brief Enqueue a new \ref msgb into a write queue
|
||||
* \param[in] queue Write queue to be used
|
||||
* \param[in] data to-be-enqueued message buffer
|
||||
*/
|
||||
int osmo_wqueue_enqueue(struct osmo_wqueue *queue, struct msgb *data);
|
||||
|
||||
/*! \brief Select loop function for write queue handling
|
||||
* \param[in] fd osmocom file descriptor
|
||||
* \param[in] what bit-mask of events that have happened
|
||||
*
|
||||
* This function is provided so that it can be registered with the
|
||||
* select loop abstraction code (\ref osmo_fd::cb).
|
||||
*/
|
||||
int osmo_wqueue_bfd_cb(struct osmo_fd *fd, unsigned int what);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue