update docs/dox for >= testing modules

This commit is contained in:
Richard Aas 2011-03-01 11:11:08 +00:00
parent b8fb22fa71
commit 198703c7a0
75 changed files with 893 additions and 103 deletions

View file

@ -29,7 +29,7 @@ Modules:
* hash testing Hashmap table * hash testing Hashmap table
* hmac testing HMAC: Keyed-Hashing for Message Authentication * hmac testing HMAC: Keyed-Hashing for Message Authentication
* httpauth unstable HTTP-based Authentication (RFC 2617) * httpauth unstable HTTP-based Authentication (RFC 2617)
* ice development Interactive Connectivity Establishment (ICE) * ice unstable Interactive Connectivity Establishment (ICE)
* jbuf testing Jitter buffer * jbuf testing Jitter buffer
* list stable Sortable doubly-linked list handling * list stable Sortable doubly-linked list handling
* lock testing Resource locking functions * lock testing Resource locking functions
@ -38,7 +38,7 @@ Modules:
* md5 stable The MD5 Message-Digest Algorithm (RFC 1321) * md5 stable The MD5 Message-Digest Algorithm (RFC 1321)
* mem stable Memory referencing * mem stable Memory referencing
* mod testing Run-time module loading * mod testing Run-time module loading
* mqueue unstable Thread-safe message queue * mqueue testing Thread-safe message queue
* natbd unstable NAT Behavior Discovery using STUN * natbd unstable NAT Behavior Discovery using STUN
* net unstable Networking routines * net unstable Networking routines
* rtp testing Real-time Transport Protocol * rtp testing Real-time Transport Protocol
@ -54,7 +54,7 @@ Modules:
* telev testing Telephony Events (RFC 4733) * telev testing Telephony Events (RFC 4733)
* tls unstable Transport Layer Security * tls unstable Transport Layer Security
* tmr stable Timer handling * tmr stable Timer handling
* turn unstable Obtaining Relay Addresses from STUN (TURN) * turn testing Obtaining Relay Addresses from STUN (TURN)
* udp testing UDP transport * udp testing UDP transport
* uri testing Generic URI library * uri testing Generic URI library

View file

@ -57,6 +57,8 @@ static inline void pl_advance(struct pl *pl, ssize_t n)
* @param p String to print * @param p String to print
* @param size Size of string to print * @param size Size of string to print
* @param arg Handler argument * @param arg Handler argument
*
* @return 0 for success, otherwise errorcode
*/ */
typedef int(re_vprintf_h)(const char *p, size_t size, void *arg); typedef int(re_vprintf_h)(const char *p, size_t size, void *arg);
@ -71,6 +73,8 @@ struct re_printf {
* *
* @param pf Print backend * @param pf Print backend
* @param arg Handler argument * @param arg Handler argument
*
* @return 0 for success, otherwise errorcode
*/ */
typedef int(re_printf_h)(struct re_printf *pf, void *arg); typedef int(re_printf_h)(struct re_printf *pf, void *arg);

View file

@ -4,12 +4,20 @@
* Copyright (C) 2010 Creytiv.com * Copyright (C) 2010 Creytiv.com
*/ */
extern const uint8_t g711_l2u[4096]; extern const uint8_t g711_l2u[4096];
extern const uint8_t g711_l2A[2048]; extern const uint8_t g711_l2A[2048];
extern const int16_t g711_u2l[256]; extern const int16_t g711_u2l[256];
extern const int16_t g711_A2l[256]; extern const int16_t g711_A2l[256];
/**
* Encode one 16-bit PCM sample to U-law format
*
* @param l Signed PCM sample
*
* @return U-law byte
*/
static inline uint8_t g711_pcm2ulaw(int16_t l) static inline uint8_t g711_pcm2ulaw(int16_t l)
{ {
const uint8_t mask = (l < 0) ? 0x7f : 0xff; const uint8_t mask = (l < 0) ? 0x7f : 0xff;
@ -24,6 +32,13 @@ static inline uint8_t g711_pcm2ulaw(int16_t l)
} }
/**
* Encode one 16-bit PCM sample to A-law format
*
* @param l Signed PCM sample
*
* @return A-law byte
*/
static inline uint8_t g711_pcm2alaw(int16_t l) static inline uint8_t g711_pcm2alaw(int16_t l)
{ {
const uint8_t mask = (l < 0) ? 0x7f : 0xff; const uint8_t mask = (l < 0) ? 0x7f : 0xff;
@ -35,12 +50,26 @@ static inline uint8_t g711_pcm2alaw(int16_t l)
} }
/**
* Decode one U-law sample to 16-bit PCM sample
*
* @param u U-law byte
*
* @return Signed PCM sample
*/
static inline int16_t g711_ulaw2pcm(uint8_t u) static inline int16_t g711_ulaw2pcm(uint8_t u)
{ {
return g711_u2l[u]; return g711_u2l[u];
} }
/**
* Decode one A-law sample to 16-bit PCM sample
*
* @param A A-law byte
*
* @return Signed PCM sample
*/
static inline int16_t g711_alaw2pcm(uint8_t a) static inline int16_t g711_alaw2pcm(uint8_t a)
{ {
return g711_A2l[a]; return g711_A2l[a];

View file

@ -1,6 +1,5 @@
/** /**
* @file re_natbd.h NAT Behavior Discovery Using STUN * @file re_natbd.h NAT Behavior Discovery Using STUN (RFC 5780)
* draft-ietf-behave-nat-behavior-discovery-06
* *
* Copyright (C) 2010 Creytiv.com * Copyright (C) 2010 Creytiv.com
*/ */

View file

@ -1,5 +1,5 @@
/** /**
* @file re_rtp.h Interface to Real-time Transport Protocol * @file re_rtp.h Interface to Real-time Transport Protocol and RTCP
* *
* Copyright (C) 2010 Creytiv.com * Copyright (C) 2010 Creytiv.com
*/ */
@ -91,11 +91,11 @@ struct rtcp_sdes_item {
struct rtcp_msg { struct rtcp_msg {
/** RTCP Header */ /** RTCP Header */
struct rtcp_hdr { struct rtcp_hdr {
unsigned int version:2; /**< Protocol version */ unsigned int version:2; /**< Protocol version */
unsigned int p:1; /**< Padding flag */ unsigned int p:1; /**< Padding flag */
unsigned int count:5; /**< Varies by packet type */ unsigned int count:5; /**< Varies by packet type */
unsigned int pt:8; /**< RTCP packet type */ unsigned int pt:8; /**< RTCP packet type */
uint16_t length; /**< Packet len in words */ uint16_t length; /**< Packet length in words */
} hdr; } hdr;
union { union {
/** Sender report (SR) */ /** Sender report (SR) */
@ -170,6 +170,7 @@ struct rtcp_msg {
} r; } r;
}; };
/** RTCP Statistics */
struct rtcp_stats { struct rtcp_stats {
struct { struct {
uint32_t sent; uint32_t sent;

View file

@ -11,14 +11,18 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <netinet/in.h> #include <netinet/in.h>
#endif #endif
struct pl; struct pl;
/** Socket Address flags */
enum sa_flag { enum sa_flag {
SA_ADDR = 1<<0, SA_ADDR = 1<<0,
SA_PORT = 1<<1, SA_PORT = 1<<1,
SA_ALL = SA_ADDR | SA_PORT SA_ALL = SA_ADDR | SA_PORT
}; };
/** Defines a Socket Address */
struct sa { struct sa {
union { union {
struct sockaddr sa; struct sockaddr sa;

View file

@ -32,6 +32,13 @@ void tmr_cancel(struct tmr *tmr);
uint64_t tmr_get_expire(const struct tmr *tmr); uint64_t tmr_get_expire(const struct tmr *tmr);
/**
* Check if the timer is running
*
* @param tmr Timer to check
*
* @return true if running, false if not running
*/
static inline bool tmr_isrunning(const struct tmr *tmr) static inline bool tmr_isrunning(const struct tmr *tmr)
{ {
return tmr ? NULL != tmr->th : false; return tmr ? NULL != tmr->th : false;

View file

@ -75,8 +75,8 @@ FILE_VERSION_FILTER =
QUIET = YES QUIET = YES
WARNINGS = YES WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES WARN_IF_DOC_ERROR = NO
WARN_NO_PARAMDOC = NO WARN_NO_PARAMDOC = YES
WARN_FORMAT = "$file:$line: $text" WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE = WARN_LOGFILE =
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
@ -90,21 +90,17 @@ RECURSIVE = YES
EXCLUDE = test.c \ EXCLUDE = test.c \
include/re_bitv.h \ include/re_bitv.h \
src/md5/md5.h src/md5/md5.c \ src/md5/md5.h src/md5/md5.c \
src/conf include/re_conf.h \
src/dns include/re_dns.h \ src/dns include/re_dns.h \
src/httpauth include/re_httpauth.h \ src/httpauth include/re_httpauth.h \
src/ice include/re_ice.h \ src/ice include/re_ice.h \
src/lock include/re_lock.h \
src/sdp include/re_sdp.h \ src/sdp include/re_sdp.h \
src/sip/ include/re_sip.h \
src/sipsess/ include/re_sipsess.h \
src/stun include/re_stun.h \ src/stun include/re_stun.h \
src/tcp include/re_tcp.h \ src/tls include/re_tls.h
src/telev include/re_telev.h \
src/tls include/re_tls.h \
src/turn include/re_turn.h \
src/udp include/re_udp.h
EXCLUDE_SYMLINKS = NO EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS = */.svn/* *src/sip* *include/re_sip* EXCLUDE_PATTERNS = */.svn/*
EXAMPLE_PATH = EXAMPLE_PATH =
EXAMPLE_PATTERNS = * EXAMPLE_PATTERNS = *
EXAMPLE_RECURSIVE = NO EXAMPLE_RECURSIVE = NO

View file

@ -1,5 +1,7 @@
# #
# mod.mk # mod.mk
# #
# Copyright (C) 2010 Creytiv.com
#
SRCS += base64/b64.c SRCS += base64/b64.c

View file

@ -26,6 +26,11 @@
#endif #endif
/**
* Defines a Configuration state. The configuration data is stored in a
* linear buffer which can be used for reading key-value pairs of
* configuration data. The config data can be strings or numeric values.
*/
struct conf { struct conf {
struct mbuf *mb; struct mbuf *mb;
}; };
@ -65,6 +70,14 @@ static void conf_destructor(void *data)
} }
/**
* Load configuration from file
*
* @param confp Configuration object to be allocated
* @param filename Name of configuration file
*
* @return 0 if success, otherwise errorcode
*/
int conf_alloc(struct conf **confp, const char *filename) int conf_alloc(struct conf **confp, const char *filename)
{ {
struct conf *conf; struct conf *conf;
@ -97,6 +110,15 @@ int conf_alloc(struct conf **confp, const char *filename)
} }
/**
* Allocate configuration from a buffer
*
* @param confp Configuration object to be allocated
* @param buf Buffer containing configuration
* @param sz Size of configuration buffer
*
* @return 0 if success, otherwise errorcode
*/
int conf_alloc_buf(struct conf **confp, const uint8_t *buf, size_t sz) int conf_alloc_buf(struct conf **confp, const uint8_t *buf, size_t sz)
{ {
struct conf *conf; struct conf *conf;
@ -117,6 +139,15 @@ int conf_alloc_buf(struct conf **confp, const uint8_t *buf, size_t sz)
} }
/**
* Get the value of a configuration item PL string
*
* @param conf Configuration object
* @param name Name of config item key
* @param pl Value of config item, if present
*
* @return 0 if success, otherwise errorcode
*/
int conf_get(struct conf *conf, const char *name, struct pl *pl) int conf_get(struct conf *conf, const char *name, struct pl *pl)
{ {
char expr[512]; char expr[512];
@ -135,6 +166,16 @@ int conf_get(struct conf *conf, const char *name, struct pl *pl)
} }
/**
* Get the value of a configuration item string
*
* @param conf Configuration object
* @param name Name of config item key
* @param str Value of config item, if present
* @param size Size of string to store value
*
* @return 0 if success, otherwise errorcode
*/
int conf_get_str(struct conf *conf, const char *name, char *str, int conf_get_str(struct conf *conf, const char *name, char *str,
size_t size) size_t size)
{ {
@ -152,6 +193,15 @@ int conf_get_str(struct conf *conf, const char *name, char *str,
} }
/**
* Get the numeric value of a configuration item
*
* @param conf Configuration object
* @param name Name of config item key
* @param num Returned numeric value of config item, if present
*
* @return 0 if success, otherwise errorcode
*/
int conf_get_u32(struct conf *conf, const char *name, uint32_t *num) int conf_get_u32(struct conf *conf, const char *name, uint32_t *num)
{ {
struct pl pl; struct pl pl;
@ -170,6 +220,16 @@ int conf_get_u32(struct conf *conf, const char *name, uint32_t *num)
} }
/**
* Apply a function handler to all config items of a certain key
*
* @param conf Configuration object
* @param name Name of config item key
* @param ch Config item handler
* @param arg Handler argument
*
* @return 0 if success, otherwise errorcode
*/
int conf_apply(struct conf *conf, const char *name, conf_h *ch, void *arg) int conf_apply(struct conf *conf, const char *name, conf_h *ch, void *arg)
{ {
char expr[512]; char expr[512];

View file

@ -1,5 +1,7 @@
# #
# mod.mk # mod.mk
# #
# Copyright (C) 2010 Creytiv.com
#
SRCS += conf/conf.c SRCS += conf/conf.c

View file

@ -1,4 +1,6 @@
/*- /**
* @file crc32.c CRC32 Implementation
*
* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
* code or tables extracted from it, as desired without restriction. * code or tables extracted from it, as desired without restriction.
*/ */
@ -97,6 +99,12 @@ static const uint32_t crc32_tab[] = {
* given below for documentation purposes. An equivalent implementation * given below for documentation purposes. An equivalent implementation
* of this function that's actually used in the kernel can be found * of this function that's actually used in the kernel can be found
* in sys/libkern.h, where it can be inlined. * in sys/libkern.h, where it can be inlined.
*
* @param crc Initial CRC value
* @param buf Buffer to generate CRC from
* @param size Number of bytes in buffer
*
* @return CRC value
*/ */
uint32_t crc32(uint32_t crc, const void *buf, uint32_t size) uint32_t crc32(uint32_t crc, const void *buf, uint32_t size)
{ {

View file

@ -1,6 +1,8 @@
# #
# mod.mk # mod.mk
# #
# Copyright (C) 2010 Creytiv.com
#
ifeq ($(USE_ZLIB),) ifeq ($(USE_ZLIB),)
SRCS += crc32/crc32.c SRCS += crc32/crc32.c

View file

@ -1,6 +1,7 @@
# #
# mod.mk # mod.mk
# #
# Copyright (C) 2010 Creytiv.com
#
SRCS += dbg/dbg.c SRCS += dbg/dbg.c

View file

@ -1,7 +1,8 @@
# #
# mod.mk # mod.mk
# #
# Copyright (C) 2010 Creytiv.com
#
SRCS += dns/client.c SRCS += dns/client.c
SRCS += dns/cstr.c SRCS += dns/cstr.c

View file

@ -8,9 +8,9 @@
/** /**
* Convert a ascii hex character to binary format * Convert an ASCII hex character to binary format
* *
* @param ch Ascii hex character * @param ch ASCII hex character
* *
* @return Binary value * @return Binary value
*/ */

View file

@ -1,7 +1,8 @@
# #
# mod.mk # mod.mk
# #
# Copyright (C) 2010 Creytiv.com
#
SRCS += fmt/ch.c SRCS += fmt/ch.c
SRCS += fmt/hexdump.c SRCS += fmt/hexdump.c

View file

@ -130,8 +130,16 @@ static size_t local_ftoa(char *buf, double n, size_t dp)
/** /**
* Print a formatted string * Print a formatted string
* *
* @param fmt Formatted string
* @param ap Variable argument
* @param vph Print handler
* @param arg Handler argument
*
* @return 0 if success, otherwise errorcode
*
* Extensions: * Extensions:
* *
* <pre>
* %b (char *, size_t) Buffer string with pointer and length * %b (char *, size_t) Buffer string with pointer and length
* %r (struct pl) Pointer-length object * %r (struct pl) Pointer-length object
* %w (uint8_t *, size_t) Binary buffer to hexadecimal format * %w (uint8_t *, size_t) Binary buffer to hexadecimal format
@ -139,6 +147,7 @@ static size_t local_ftoa(char *buf, double n, size_t dp)
* %J (struct sa *) Socket address and port - like 1.2.3.4:1234 * %J (struct sa *) Socket address and port - like 1.2.3.4:1234
* %H (re_printf_h *, void *) Print handler with argument * %H (re_printf_h *, void *) Print handler with argument
* %v (char *fmt, va_list *) Variable argument list * %v (char *fmt, va_list *) Variable argument list
* </pre>
* *
* Reserved for the future: * Reserved for the future:
* *

View file

@ -7,6 +7,15 @@
#include <re_fmt.h> #include <re_fmt.h>
/**
* Fetch a semicolon separated parameter from a PL string
*
* @param pl PL string to search
* @param pname Parameter name
* @param val Parameter value, set on return
*
* @return true if found, false if not found
*/
bool fmt_param_get(const struct pl *pl, const char *pname, struct pl *val) bool fmt_param_get(const struct pl *pl, const char *pname, struct pl *val)
{ {
char expr[128]; char expr[128];
@ -20,6 +29,13 @@ bool fmt_param_get(const struct pl *pl, const char *pname, struct pl *val)
} }
/**
* Apply a function handler for each semicolon separated parameter
*
* @param pl PL string to search
* @param ph Parameter handler
* @param arg Handler argument
*/
void fmt_param_apply(const struct pl *pl, fmt_param_h *ph, void *arg) void fmt_param_apply(const struct pl *pl, fmt_param_h *ph, void *arg)
{ {
size_t i; size_t i;

View file

@ -1,6 +1,7 @@
# #
# mod.mk # mod.mk
# #
# Copyright (C) 2010 Creytiv.com
#
SRCS += g711/g711.c SRCS += g711/g711.c

View file

@ -1,7 +1,8 @@
# #
# mod.mk # mod.mk
# #
# Copyright (C) 2010 Creytiv.com
#
SRCS += hash/hash.c SRCS += hash/hash.c
SRCS += hash/func.c SRCS += hash/func.c

View file

@ -1,5 +1,7 @@
# #
# mod.mk # mod.mk
# #
# Copyright (C) 2010 Creytiv.com
#
SRCS += hmac/hmac_sha1.c SRCS += hmac/hmac_sha1.c

View file

@ -1,7 +1,8 @@
# #
# mod.mk # mod.mk
# #
# Copyright (C) 2010 Creytiv.com
#
#SRCS += httpauth/basic.c #SRCS += httpauth/basic.c
SRCS += httpauth/digest.c SRCS += httpauth/digest.c

View file

@ -17,13 +17,6 @@
#include <re_dbg.h> #include <re_dbg.h>
/*
* The jitter buffer is for incoming RTP packets. Sorting by 'timestamp' works
* fine for audio. However, this does not work so well for video or telephony
* events. A better approach is to sort them by the sequence number.
*/
#ifndef RELEASE #ifndef RELEASE
#define JBUF_STAT 1 /**< Jitter buffer statistics */ #define JBUF_STAT 1 /**< Jitter buffer statistics */
#endif #endif
@ -46,7 +39,12 @@ struct frame {
}; };
/** Defines a jitter buffer */ /**
* Defines a jitter buffer
*
* The jitter buffer is for incoming RTP packets, which are sorted by
* sequence number.
*/
struct jbuf { struct jbuf {
struct list pooll; /**< List of free frames in pool */ struct list pooll; /**< List of free frames in pool */
struct list framel; /**< List of buffered frames */ struct list framel; /**< List of buffered frames */
@ -389,6 +387,8 @@ int jbuf_stats(const struct jbuf *jb, struct jbuf_stat *jstat)
* *
* @param pf Print handler * @param pf Print handler
* @param jb Jitter buffer * @param jb Jitter buffer
*
* @return 0 if success, otherwise errorcode
*/ */
int jbuf_debug(struct re_printf *pf, const struct jbuf *jb) int jbuf_debug(struct re_printf *pf, const struct jbuf *jb)
{ {

View file

@ -1,6 +1,7 @@
# #
# mod.mk # mod.mk
# #
# Copyright (C) 2010 Creytiv.com
#
SRCS += jbuf/jbuf.c SRCS += jbuf/jbuf.c

View file

@ -1,6 +1,7 @@
# #
# mod.mk # mod.mk
# #
# Copyright (C) 2010 Creytiv.com
#
SRCS += list/list.c SRCS += list/list.c

View file

@ -21,6 +21,7 @@
#endif #endif
/** Defines a lock */
struct lock { struct lock {
pthread_mutex_t m; pthread_mutex_t m;
}; };
@ -37,6 +38,13 @@ static void lock_destructor(void *data)
} }
/**
* Allocate a new lock
*
* @param lp Pointer to allocated lock object
*
* @return 0 if success, otherwise errorcode
*/
int lock_alloc(struct lock **lp) int lock_alloc(struct lock **lp)
{ {
pthread_mutexattr_t attr; pthread_mutexattr_t attr;
@ -66,6 +74,11 @@ int lock_alloc(struct lock **lp)
} }
/**
* Get the lock for reading
*
* @param l Lock object
*/
void lock_read_get(struct lock *l) void lock_read_get(struct lock *l)
{ {
const int err = pthread_mutex_lock(&l->m); const int err = pthread_mutex_lock(&l->m);
@ -75,6 +88,11 @@ void lock_read_get(struct lock *l)
} }
/**
* Get the lock for writing
*
* @param l Lock object
*/
void lock_write_get(struct lock *l) void lock_write_get(struct lock *l)
{ {
const int err = pthread_mutex_lock(&l->m); const int err = pthread_mutex_lock(&l->m);
@ -84,18 +102,37 @@ void lock_write_get(struct lock *l)
} }
/**
* Attempt to get a lock for reading
*
* @param l Lock object
*
* @return 0 if success, otherwise errorcode
*/
int lock_read_try(struct lock *l) int lock_read_try(struct lock *l)
{ {
return pthread_mutex_trylock(&l->m); return pthread_mutex_trylock(&l->m);
} }
/**
* Attempt to get a lock for writing
*
* @param l Lock object
*
* @return 0 if success, otherwise errorcode
*/
int lock_write_try(struct lock *l) int lock_write_try(struct lock *l)
{ {
return pthread_mutex_trylock(&l->m); return pthread_mutex_trylock(&l->m);
} }
/**
* Release a lock
*
* @param l Lock object
*/
void lock_rel(struct lock *l) void lock_rel(struct lock *l)
{ {
const int err = pthread_mutex_unlock(&l->m); const int err = pthread_mutex_unlock(&l->m);

View file

@ -1,6 +1,8 @@
# #
# mod.mk # mod.mk
# #
# Copyright (C) 2010 Creytiv.com
#
ifdef HAVE_PTHREAD_RWLOCK ifdef HAVE_PTHREAD_RWLOCK
SRCS += lock/rwlock.c SRCS += lock/rwlock.c

View file

@ -69,7 +69,7 @@
enum { enum {
MAX_BLOCKING = 100, /**< Maximum ticks spent in handler */ MAX_BLOCKING = 100, /**< Maximum time spent in handler in [ms] */
#if defined (WIN32) || defined (CYGWIN) #if defined (WIN32) || defined (CYGWIN)
DEFAULT_MAXFDS = 8192 DEFAULT_MAXFDS = 8192
#else #else
@ -770,6 +770,8 @@ static void signal_handler(int sig)
* Main polling loop for async I/O events. This function will only return when * Main polling loop for async I/O events. This function will only return when
* re_cancel() is called or an error occured. * re_cancel() is called or an error occured.
* *
* @param signalh Optional Signal handler
*
* @return 0 if success, otherwise errorcode * @return 0 if success, otherwise errorcode
*/ */
int re_main(re_signal_h *signalh) int re_main(re_signal_h *signalh)
@ -866,6 +868,8 @@ void re_cancel(void)
* *
* @param pf Print handler where debug output is printed to * @param pf Print handler where debug output is printed to
* @param unused Unused parameter * @param unused Unused parameter
*
* @return 0 if success, otherwise errorcode
*/ */
int re_debug(struct re_printf *pf, void *unused) int re_debug(struct re_printf *pf, void *unused)
{ {
@ -1024,6 +1028,8 @@ void re_thread_leave(void)
/** /**
* Get the timer-list for this thread * Get the timer-list for this thread
* *
* @return Timer list
*
* @note only used by tmr module * @note only used by tmr module
*/ */
struct list *tmrl_get(void); struct list *tmrl_get(void);

View file

@ -1,7 +1,8 @@
# #
# mod.mk # mod.mk
# #
# Copyright (C) 2010 Creytiv.com
#
SRCS += main/init.c SRCS += main/init.c
SRCS += main/main.c SRCS += main/main.c

View file

@ -474,7 +474,17 @@ int mbuf_printf(struct mbuf *mb, const char *fmt, ...)
} }
/** todo: create substf variant */ /**
* Write a pointer-length string to a memory buffer, excluding a section
*
* @param mb Memory buffer
* @param pl Pointer-length string
* @param skip Part of pl to exclude
*
* @return 0 if success, otherwise errorcode
*
* @todo: create substf variante
*/
int mbuf_write_pl_skip(struct mbuf *mb, const struct pl *pl, int mbuf_write_pl_skip(struct mbuf *mb, const struct pl *pl,
const struct pl *skip) const struct pl *skip)
{ {
@ -501,6 +511,14 @@ int mbuf_write_pl_skip(struct mbuf *mb, const struct pl *pl,
} }
/**
* Debug the memory buffer
*
* @param pf Print handler
* @param mb Memory buffer
*
* @return 0 if success, otherwise errorcode
*/
int mbuf_debug(struct re_printf *pf, const struct mbuf *mb) int mbuf_debug(struct re_printf *pf, const struct mbuf *mb)
{ {
if (!mb) if (!mb)

View file

@ -1,6 +1,7 @@
# #
# mod.mk # mod.mk
# #
# Copyright (C) 2010 Creytiv.com
#
SRCS += mbuf/mbuf.c SRCS += mbuf/mbuf.c

View file

@ -1,6 +1,8 @@
# #
# mod.mk # mod.mk
# #
# Copyright (C) 2010 Creytiv.com
#
ifeq ($(USE_OPENSSL),) ifeq ($(USE_OPENSSL),)
SRCS += md5/md5.c SRCS += md5/md5.c

View file

@ -411,6 +411,8 @@ void mem_threshold_set(ssize_t n)
* *
* @param pf Print handler for debug output * @param pf Print handler for debug output
* @param unused Unused parameter * @param unused Unused parameter
*
* @return 0 if success, otherwise errorcode
*/ */
int mem_status(struct re_printf *pf, void *unused) int mem_status(struct re_printf *pf, void *unused)
{ {

View file

@ -1,6 +1,7 @@
# #
# mod.mk # mod.mk
# #
# Copyright (C) 2010 Creytiv.com
#
SRCS += mem/mem.c SRCS += mem/mem.c

View file

@ -215,6 +215,8 @@ const struct mod_export *mod_export(const struct mod *m)
* *
* @param pf Print handler for debug output * @param pf Print handler for debug output
* @param unused Unused parameter * @param unused Unused parameter
*
* @return 0 if success, otherwise errorcode
*/ */
int mod_debug(struct re_printf *pf, void *unused) int mod_debug(struct re_printf *pf, void *unused)
{ {

View file

@ -1,7 +1,8 @@
# #
# mod.mk # mod.mk
# #
# Copyright (C) 2010 Creytiv.com
#
SRCS += mod/mod.c SRCS += mod/mod.c

View file

@ -1,6 +1,8 @@
# #
# mod.mk # mod.mk
# #
# Copyright (C) 2010 Creytiv.com
#
SRCS += mqueue/mqueue.c SRCS += mqueue/mqueue.c

View file

@ -14,6 +14,13 @@
#define MAGIC 0x14553399 #define MAGIC 0x14553399
/**
* Defines a Thread-safe Message Queue
*
* The Message Queue can be used to communicate between two threads. The
* receiving thread must run the re_main() loop which will be woken up on
* incoming messages from other threads. The sender thread can be any thread.
*/
struct mqueue { struct mqueue {
int pfd[2]; int pfd[2];
}; };
@ -69,6 +76,13 @@ static void event_handler(int flags, void *arg)
} }
/**
* Allocate a new Message Queue
*
* @param mqp Pointer to allocated Message Queue
*
* @return 0 if success, otherwise errorcode
*/
int mqueue_alloc(struct mqueue **mqp) int mqueue_alloc(struct mqueue **mqp)
{ {
struct mqueue *mq; struct mqueue *mq;
@ -101,6 +115,16 @@ int mqueue_alloc(struct mqueue **mqp)
} }
/**
* Push a new message onto the Message Queue
*
* @param mq Message Queue
* @param h Message handler
* @param id General purpose Identifier
* @param data Application data
*
* @return 0 if success, otherwise errorcode
*/
int mqueue_push(struct mqueue *mq, mqueue_h *h, int id, void *data) int mqueue_push(struct mqueue *mq, mqueue_h *h, int id, void *data)
{ {
struct msg msg; struct msg msg;

View file

@ -1,7 +1,8 @@
# #
# mod.mk # mod.mk
# #
# Copyright (C) 2010 Creytiv.com
#
SRCS += natbd/filtering.c SRCS += natbd/filtering.c
SRCS += natbd/genalg.c SRCS += natbd/genalg.c

View file

@ -1,7 +1,8 @@
# #
# mod.mk # mod.mk
# #
# Copyright (C) 2010 Creytiv.com
#
# Generic files # Generic files
SRCS += net/if.c SRCS += net/if.c

View file

@ -77,8 +77,6 @@ int net_sock_init(void)
/** /**
* Cleanup network sockets * Cleanup network sockets
*
* @return 0 if success, otherwise errorcode
*/ */
void net_sock_close(void) void net_sock_close(void)
{ {

View file

@ -29,6 +29,15 @@ enum {
/* Encode functions */ /* Encode functions */
/**
* Encode an RTCP Generic NACK (GNACK) message
*
* @param mb Buffer to encode into
* @param pid Packet ID
* @param blp Bitmask of following lost packets (BLP)
*
* @return 0 for success, otherwise errorcode
*/
int rtcp_rtpfb_gnack_encode(struct mbuf *mb, uint16_t pid, uint16_t blp) int rtcp_rtpfb_gnack_encode(struct mbuf *mb, uint16_t pid, uint16_t blp)
{ {
int err; int err;
@ -38,6 +47,16 @@ int rtcp_rtpfb_gnack_encode(struct mbuf *mb, uint16_t pid, uint16_t blp)
} }
/**
* Encode an RTCP Slice Loss Indication (SLI) message
*
* @param mb Buffer to encode into
* @param first Macroblock (MB) address of the first lost macroblock
* @param number Number of lost macroblocks
* @param picid Picture ID
*
* @return 0 for success, otherwise errorcode
*/
int rtcp_psfb_sli_encode(struct mbuf *mb, uint16_t first, uint16_t number, int rtcp_psfb_sli_encode(struct mbuf *mb, uint16_t first, uint16_t number,
uint8_t picid) uint8_t picid)
{ {
@ -49,6 +68,14 @@ int rtcp_psfb_sli_encode(struct mbuf *mb, uint16_t first, uint16_t number,
/* Decode functions */ /* Decode functions */
/**
* Decode an RTCP Transport Layer Feedback Message
*
* @param mb Buffer to decode
* @param msg RTCP Message to decode into
*
* @return 0 for success, otherwise errorcode
*/
int rtcp_rtpfb_decode(struct mbuf *mb, struct rtcp_msg *msg) int rtcp_rtpfb_decode(struct mbuf *mb, struct rtcp_msg *msg)
{ {
size_t i, sz; size_t i, sz;
@ -81,6 +108,14 @@ int rtcp_rtpfb_decode(struct mbuf *mb, struct rtcp_msg *msg)
} }
/**
* Decode an RTCP Payload-Specific Feedback Message
*
* @param mb Buffer to decode
* @param msg RTCP Message to decode into
*
* @return 0 for success, otherwise errorcode
*/
int rtcp_psfb_decode(struct mbuf *mb, struct rtcp_msg *msg) int rtcp_psfb_decode(struct mbuf *mb, struct rtcp_msg *msg)
{ {
size_t i, sz; size_t i, sz;

View file

@ -1,7 +1,8 @@
# #
# mod.mk # mod.mk
# #
# Copyright (C) 2010 Creytiv.com
#
SRCS += rtp/fb.c SRCS += rtp/fb.c
SRCS += rtp/member.c SRCS += rtp/member.c

View file

@ -72,6 +72,16 @@ static void rtcp_destructor(void *data)
} }
/**
* Encode the RTCP Header
*
* @param mb Buffer to encode into
* @param count Number of sub-elemements
* @param type RTCP Packet type
* @param length Packet length in words
*
* @return 0 for success, otherwise errorcode
*/
int rtcp_hdr_encode(struct mbuf *mb, uint8_t count, enum rtcp_type type, int rtcp_hdr_encode(struct mbuf *mb, uint8_t count, enum rtcp_type type,
uint16_t length) uint16_t length)
{ {
@ -88,6 +98,14 @@ int rtcp_hdr_encode(struct mbuf *mb, uint8_t count, enum rtcp_type type,
} }
/**
* Decode the RTCP Header
*
* @param mb Buffer to decode from
* @param hdr RTCP Header to decode into
*
* @return 0 for success, otherwise errorcode
*/
int rtcp_hdr_decode(struct mbuf *mb, struct rtcp_hdr *hdr) int rtcp_hdr_decode(struct mbuf *mb, struct rtcp_hdr *hdr)
{ {
uint8_t b; uint8_t b;
@ -227,6 +245,15 @@ int rtcp_vencode(struct mbuf *mb, enum rtcp_type type, uint32_t count,
} }
/**
* Encode an RTCP Packet into a buffer
*
* @param mb Buffer to encode into
* @param type RTCP Packet type
* @param count Packet-specific count
*
* @return 0 for success, otherwise errorcode
*/
int rtcp_encode(struct mbuf *mb, enum rtcp_type type, uint32_t count, ...) int rtcp_encode(struct mbuf *mb, enum rtcp_type type, uint32_t count, ...)
{ {
va_list ap; va_list ap;
@ -240,7 +267,14 @@ int rtcp_encode(struct mbuf *mb, enum rtcp_type type, uint32_t count, ...)
} }
/** Allocate one RTCP message and decode from mbuf */ /**
* Decode one RTCP message from a buffer
*
* @param msgp Pointer to allocated RTCP Message
* @param mb Buffer to decode from
*
* @return 0 for success, otherwise errorcode
*/
int rtcp_decode(struct rtcp_msg **msgp, struct mbuf *mb) int rtcp_decode(struct rtcp_msg **msgp, struct mbuf *mb)
{ {
struct rtcp_msg *msg = NULL; struct rtcp_msg *msg = NULL;

View file

@ -42,6 +42,16 @@ static int rtcp_quick_send(struct rtp_sock *rs, enum rtcp_type type,
} }
/**
* Send an RTCP Application-Defined (APP) packet
*
* @param rs RTP Socket
* @param name Ascii name (4 octets)
* @param data Application-dependent data
* @param len Number of bytes of data
*
* @return 0 for success, otherwise errorcode
*/
int rtcp_send_app(struct rtp_sock *rs, const char name[4], int rtcp_send_app(struct rtp_sock *rs, const char name[4],
const uint8_t *data, size_t len) const uint8_t *data, size_t len)
{ {
@ -64,12 +74,29 @@ int rtcp_send_fir(struct rtp_sock *rs, uint32_t ssrc)
} }
/**
* Send an RTCP NACK packet
*
* @param rs RTP Socket
* @param fsn First Sequence Number lost
* @param blp Bitmask of lost packets
*
* @return 0 for success, otherwise errorcode
*/
int rtcp_send_nack(struct rtp_sock *rs, uint16_t fsn, uint16_t blp) int rtcp_send_nack(struct rtp_sock *rs, uint16_t fsn, uint16_t blp)
{ {
return rtcp_quick_send(rs, RTCP_NACK, 0, rtp_sess_ssrc(rs), fsn, blp); return rtcp_quick_send(rs, RTCP_NACK, 0, rtp_sess_ssrc(rs), fsn, blp);
} }
/**
* Send an RTCP Picture Loss Indication (PLI) packet
*
* @param rs RTP Socket
* @param fb_ssrc Feedback SSRC
*
* @return 0 for success, otherwise errorcode
*/
int rtcp_send_pli(struct rtp_sock *rs, uint32_t fb_ssrc) int rtcp_send_pli(struct rtp_sock *rs, uint32_t fb_ssrc)
{ {
return rtcp_quick_send(rs, RTCP_PSFB, RTCP_PSFB_PLI, return rtcp_quick_send(rs, RTCP_PSFB, RTCP_PSFB_PLI,
@ -115,6 +142,14 @@ const char *rtcp_sdes_name(enum rtcp_sdes_type sdes)
} }
/**
* Print an RTCP Message
*
* @param pf Print handler for debug output
* @param msg RTCP Message
*
* @return 0 if success, otherwise errorcode
*/
int rtcp_msg_print(struct re_printf *pf, const struct rtcp_msg *msg) int rtcp_msg_print(struct re_printf *pf, const struct rtcp_msg *msg)
{ {
size_t i, j; size_t i, j;

View file

@ -26,22 +26,30 @@
struct rtp_sock { struct rtp_sock {
/** Encode data */ /** Encode data */
struct { struct {
uint16_t seq; /**< Sequence number */ uint16_t seq; /**< Sequence number */
uint32_t ssrc; /**< Synchronizing source */ uint32_t ssrc; /**< Synchronizing source */
} enc; } enc;
int proto; int proto; /**< Transport Protocol */
void *sock_rtp; void *sock_rtp; /**< RTP Socket */
void *sock_rtcp; void *sock_rtcp; /**< RTCP Socket */
struct sa local; struct sa local; /**< Local RTP Address */
struct sa rtcp_peer; struct sa rtcp_peer; /**< RTCP address of Peer */
rtp_recv_h *recvh; rtp_recv_h *recvh; /**< RTP Receive handler */
rtcp_recv_h *rtcph; rtcp_recv_h *rtcph; /**< RTCP Receive handler */
void *arg; void *arg; /**< Handler argument */
struct rtcp_sess *rtcp; struct rtcp_sess *rtcp; /**< RTCP Session */
bool rtcp_mux; bool rtcp_mux; /**< RTP/RTCP multiplexing */
}; };
/**
* Encode the RTP header into a buffer
*
* @param mb Buffer to encode into
* @param hdr RTP Header to be encoded
*
* @return 0 if success, otherwise errorcode
*/
int rtp_hdr_encode(struct mbuf *mb, const struct rtp_header *hdr) int rtp_hdr_encode(struct mbuf *mb, const struct rtp_header *hdr)
{ {
uint8_t buf[2]; uint8_t buf[2];
@ -70,6 +78,14 @@ int rtp_hdr_encode(struct mbuf *mb, const struct rtp_header *hdr)
} }
/**
* Decode an RTP header from a buffer
*
* @param hdr RTP Header to decode into
* @param mb Buffer to decode from
*
* @return 0 if success, otherwise errorcode
*/
int rtp_hdr_decode(struct rtp_header *hdr, struct mbuf *mb) int rtp_hdr_decode(struct rtp_header *hdr, struct mbuf *mb)
{ {
uint8_t buf[2]; uint8_t buf[2];
@ -267,6 +283,21 @@ int rtp_alloc(struct rtp_sock **rsp)
} }
/**
* Listen on an RTP/RTCP Socket
*
* @param rsp Pointer to returned RTP socket
* @param proto Transport protocol
* @param ip Local IP address
* @param min_port Minimum port range
* @param max_port Maximum port range
* @param enable_rtcp True to enable RTCP Session
* @param recvh RTP Receive handler
* @param rtcph RTCP Receive handler
* @param arg Handler argument
*
* @return 0 for success, otherwise errorcode
*/
int rtp_listen(struct rtp_sock **rsp, int proto, const struct sa *ip, int rtp_listen(struct rtp_sock **rsp, int proto, const struct sa *ip,
uint16_t min_port, uint16_t max_port, bool enable_rtcp, uint16_t min_port, uint16_t max_port, bool enable_rtcp,
rtp_recv_h *recvh, rtcp_recv_h *rtcph, void *arg) rtp_recv_h *recvh, rtcp_recv_h *rtcph, void *arg)
@ -378,6 +409,18 @@ int rtp_decode(struct rtp_sock *rs, struct mbuf *mb,
} }
/**
* Send an RTP packet to a peer
*
* @param rs RTP Socket
* @param dst Destination address
* @param marker Marker bit
* @param pt Payload type
* @param ts Timestamp
* @param mb Payload buffer
*
* @return 0 for success, otherwise errorcode
*/
int rtp_send(struct rtp_sock *rs, const struct sa *dst, int rtp_send(struct rtp_sock *rs, const struct sa *dst,
bool marker, uint8_t pt, uint32_t ts, struct mbuf *mb) bool marker, uint8_t pt, uint32_t ts, struct mbuf *mb)
{ {
@ -411,36 +454,78 @@ int rtp_send(struct rtp_sock *rs, const struct sa *dst,
} }
/**
* Get the RTP transport socket from an RTP/RTCP Socket
*
* @param rs RTP Socket
*
* @return Transport socket for RTP
*/
void *rtp_sock(const struct rtp_sock *rs) void *rtp_sock(const struct rtp_sock *rs)
{ {
return rs ? rs->sock_rtp : NULL; return rs ? rs->sock_rtp : NULL;
} }
/**
* Get the RTCP transport socket from an RTP/RTCP Socket
*
* @param rs RTP Socket
*
* @return Transport socket for RTCP
*/
void *rtcp_sock(const struct rtp_sock *rs) void *rtcp_sock(const struct rtp_sock *rs)
{ {
return rs ? rs->sock_rtcp : NULL; return rs ? rs->sock_rtcp : NULL;
} }
/**
* Get the local RTP address for an RTP/RTCP Socket
*
* @param rs RTP Socket
*
* @return Local RTP address
*/
const struct sa *rtp_local(const struct rtp_sock *rs) const struct sa *rtp_local(const struct rtp_sock *rs)
{ {
return rs ? &rs->local : NULL; return rs ? &rs->local : NULL;
} }
/**
* Get the Synchronizing source for an RTP/RTCP Socket
*
* @param rs RTP Socket
*
* @return Synchronizing source
*/
uint32_t rtp_sess_ssrc(const struct rtp_sock *rs) uint32_t rtp_sess_ssrc(const struct rtp_sock *rs)
{ {
return rs ? rs->enc.ssrc : 0; return rs ? rs->enc.ssrc : 0;
} }
/**
* Get the RTCP-Session for an RTP/RTCP Socket
*
* @param rs RTP Socket
*
* @return RTCP-Session
*/
struct rtcp_sess *rtp_rtcp_sess(const struct rtp_sock *rs) struct rtcp_sess *rtp_rtcp_sess(const struct rtp_sock *rs)
{ {
return rs ? rs->rtcp : NULL; return rs ? rs->rtcp : NULL;
} }
/**
* Start the RTCP Session
*
* @param rs RTP Socket
* @param cname Canonical Name
* @param peer IP-Address of RTCP Peer
*/
void rtcp_start(struct rtp_sock *rs, const char *cname, void rtcp_start(struct rtp_sock *rs, const char *cname,
const struct sa *peer) const struct sa *peer)
{ {
@ -454,6 +539,12 @@ void rtcp_start(struct rtp_sock *rs, const char *cname,
} }
/**
* Enable RTCP-multiplexing on RTP-port
*
* @param rs RTP Socket
* @param enabled True to enable, false to disable
*/
void rtcp_enable_mux(struct rtp_sock *rs, bool enabled) void rtcp_enable_mux(struct rtp_sock *rs, bool enabled)
{ {
if (!rs) if (!rs)
@ -463,6 +554,14 @@ void rtcp_enable_mux(struct rtp_sock *rs, bool enabled)
} }
/**
* Send RTCP packet(s) to the Peer
*
* @param rs RTP Socket
* @param mb Buffer containing the RTCP Packet(s)
*
* @return 0 for success, otherwise errorcode
*/
int rtcp_send(struct rtp_sock *rs, struct mbuf *mb) int rtcp_send(struct rtp_sock *rs, struct mbuf *mb)
{ {
if (!rs || !rs->sock_rtcp || !sa_isset(&rs->rtcp_peer, SA_ALL)) if (!rs || !rs->sock_rtcp || !sa_isset(&rs->rtcp_peer, SA_ALL))

View file

@ -24,7 +24,15 @@ enum {
}; };
/** Encode one SDES chunk into mbuffer */ /**
* Encode one SDES chunk into mbuffer
*
* @param mb Buffer to encode into
* @param src First SSRC/CSRC
* @param itemc Number of SDES items to encode
*
* @return 0 if success, otherwise errorcode
*/
int rtcp_sdes_encode(struct mbuf *mb, uint32_t src, uint32_t itemc, ...) int rtcp_sdes_encode(struct mbuf *mb, uint32_t src, uint32_t itemc, ...)
{ {
va_list ap; va_list ap;
@ -70,6 +78,14 @@ int rtcp_sdes_encode(struct mbuf *mb, uint32_t src, uint32_t itemc, ...)
} }
/**
* Decode SDES items from a buffer
*
* @param mb Buffer to decode from
* @param sdes RTCP SDES to decode into
*
* @return 0 if success, otherwise errorcode
*/
int rtcp_sdes_decode(struct mbuf *mb, struct rtcp_sdes *sdes) int rtcp_sdes_decode(struct mbuf *mb, struct rtcp_sdes *sdes)
{ {
size_t start; size_t start;

View file

@ -264,6 +264,13 @@ int rtcp_sess_alloc(struct rtcp_sess **sessp, struct rtp_sock *rs)
} }
/**
* Set the Sampling-rate on an RTCP Session
*
* @param rs RTP Socket
* @param srate_tx Transmit samplerate
* @param srate_rx Receive samplerate
*/
void rtcp_set_srate(struct rtp_sock *rs, uint32_t srate_tx, uint32_t srate_rx) void rtcp_set_srate(struct rtp_sock *rs, uint32_t srate_tx, uint32_t srate_rx)
{ {
struct rtcp_sess *sess = rtp_rtcp_sess(rs); struct rtcp_sess *sess = rtp_rtcp_sess(rs);
@ -536,6 +543,15 @@ void rtcp_sess_rx_rtp(struct rtcp_sess *sess, uint16_t seq, uint32_t ts,
} }
/**
* Get the RTCP Statistics for a source
*
* @param rs RTP Socket
* @param ssrc Synchronization source
* @param stats RTCP Statistics, set on return
*
* @return 0 if success, otherwise errorcode
*/
int rtcp_stats(struct rtp_sock *rs, uint32_t ssrc, struct rtcp_stats *stats) int rtcp_stats(struct rtp_sock *rs, uint32_t ssrc, struct rtcp_stats *stats)
{ {
const struct rtcp_sess *sess = rtp_rtcp_sess(rs); const struct rtcp_sess *sess = rtp_rtcp_sess(rs);
@ -586,6 +602,14 @@ static bool debug_handler(struct le *le, void *arg)
} }
/**
* RTCP Debug handler, use with fmt %H
*
* @param pf Print function
* @param rs RTP Socket
*
* @return 0 if success, otherwise errorcode
*/
int rtcp_debug(struct re_printf *pf, const struct rtp_sock *rs) int rtcp_debug(struct re_printf *pf, const struct rtp_sock *rs)
{ {
const struct rtcp_sess *sess = rtp_rtcp_sess(rs); const struct rtcp_sess *sess = rtp_rtcp_sess(rs);

View file

@ -1,7 +1,8 @@
# #
# mod.mk # mod.mk
# #
# Copyright (C) 2010 Creytiv.com
#
SRCS += sa/ntop.c SRCS += sa/ntop.c
SRCS += sa/pton.c SRCS += sa/pton.c

View file

@ -16,6 +16,12 @@
#include <re_dbg.h> #include <re_dbg.h>
/**
* Initialize a Socket Address
*
* @param sa Socket Address
* @param af Address Family
*/
void sa_init(struct sa *sa, int af) void sa_init(struct sa *sa, int af)
{ {
if (!sa) if (!sa)
@ -27,6 +33,15 @@ void sa_init(struct sa *sa, int af)
} }
/**
* Set a Socket Address from a PL string
*
* @param sa Socket Address
* @param addr IP-address
* @param port Port number
*
* @return 0 if success, otherwise errorcode
*/
int sa_set(struct sa *sa, const struct pl *addr, uint16_t port) int sa_set(struct sa *sa, const struct pl *addr, uint16_t port)
{ {
char buf[64]; char buf[64];
@ -36,6 +51,15 @@ int sa_set(struct sa *sa, const struct pl *addr, uint16_t port)
} }
/**
* Set a Socket Address from a string
*
* @param sa Socket Address
* @param addr IP-address
* @param port Port number
*
* @return 0 if success, otherwise errorcode
*/
int sa_set_str(struct sa *sa, const char *addr, uint16_t port) int sa_set_str(struct sa *sa, const char *addr, uint16_t port)
{ {
int err; int err;
@ -69,6 +93,15 @@ int sa_set_str(struct sa *sa, const char *addr, uint16_t port)
} }
/**
* Set a Socket Address from an IPv4 address
*
* @param sa Socket Address
* @param addr IPv4 address in host order
* @param port Port number
*
* @return 0 if success, otherwise errorcode
*/
void sa_set_in(struct sa *sa, uint32_t addr, uint16_t port) void sa_set_in(struct sa *sa, uint32_t addr, uint16_t port)
{ {
if (!sa) if (!sa)
@ -81,6 +114,15 @@ void sa_set_in(struct sa *sa, uint32_t addr, uint16_t port)
} }
/**
* Set a Socket Address from an IPv6 address
*
* @param sa Socket Address
* @param addr IPv6 address
* @param port Port number
*
* @return 0 if success, otherwise errorcode
*/
void sa_set_in6(struct sa *sa, const uint8_t *addr, uint16_t port) void sa_set_in6(struct sa *sa, const uint8_t *addr, uint16_t port)
{ {
if (!sa) if (!sa)
@ -98,12 +140,21 @@ void sa_set_in6(struct sa *sa, const uint8_t *addr, uint16_t port)
} }
/**
* Set a Socket Address from a sockaddr
*
* @param sa Socket Address
* @param s Sockaddr
*
* @return 0 if success, otherwise errorcode
*/
int sa_set_sa(struct sa *sa, const struct sockaddr *s) int sa_set_sa(struct sa *sa, const struct sockaddr *s)
{ {
if (!sa || !s) if (!sa || !s)
return EINVAL; return EINVAL;
switch (s->sa_family) { switch (s->sa_family) {
case AF_INET: case AF_INET:
memcpy(&sa->u.in, s, sizeof(struct sockaddr_in)); memcpy(&sa->u.in, s, sizeof(struct sockaddr_in));
sa->len = sizeof(struct sockaddr_in); sa->len = sizeof(struct sockaddr_in);
@ -126,6 +177,12 @@ int sa_set_sa(struct sa *sa, const struct sockaddr *s)
} }
/**
* Set the port number on a Socket Address
*
* @param sa Socket Address
* @param port Port number
*/
void sa_set_port(struct sa *sa, uint16_t port) void sa_set_port(struct sa *sa, uint16_t port)
{ {
if (!sa) if (!sa)
@ -206,18 +263,38 @@ int sa_decode(struct sa *sa, const char *str, size_t len)
} }
/**
* Get the Address Family of a Socket Address
*
* @param sa Socket Address
*
* @return Address Family
*/
int sa_af(const struct sa *sa) int sa_af(const struct sa *sa)
{ {
return sa ? sa->u.sa.sa_family : AF_UNSPEC; return sa ? sa->u.sa.sa_family : AF_UNSPEC;
} }
/**
* Get the IPv4-address of a Socket Address
*
* @param sa Socket Address
*
* @return IPv4 address in host order
*/
uint32_t sa_in(const struct sa *sa) uint32_t sa_in(const struct sa *sa)
{ {
return sa ? ntohl(sa->u.in.sin_addr.s_addr) : 0; return sa ? ntohl(sa->u.in.sin_addr.s_addr) : 0;
} }
/**
* Get the IPv6-address of a Socket Address
*
* @param sa Socket Address
* @param addr On return, contains the IPv6-address
*/
void sa_in6(const struct sa *sa, uint8_t *addr) void sa_in6(const struct sa *sa, uint8_t *addr)
{ {
if (!sa || !addr) if (!sa || !addr)
@ -229,12 +306,28 @@ void sa_in6(const struct sa *sa, uint8_t *addr)
} }
/**
* Convert a Socket Address to Presentation format
*
* @param sa Socket Address
* @param buf Buffer to store presentation format
* @param size Buffer size
*
* @return 0 if success, otherwise errorcode
*/
int sa_ntop(const struct sa *sa, char *buf, int size) int sa_ntop(const struct sa *sa, char *buf, int size)
{ {
return net_inet_ntop(sa, buf, size); return net_inet_ntop(sa, buf, size);
} }
/**
* Get the port number from a Socket Address
*
* @param sa Socket Address
*
* @return Port number in host order
*/
uint16_t sa_port(const struct sa *sa) uint16_t sa_port(const struct sa *sa)
{ {
if (!sa) if (!sa)
@ -256,6 +349,14 @@ uint16_t sa_port(const struct sa *sa)
} }
/**
* Check if a Socket Address is set
*
* @param sa Socket Address
* @param flag Flags specifying which fields to check
*
* @return true if set, false if not set
*/
bool sa_isset(const struct sa *sa, int flag) bool sa_isset(const struct sa *sa, int flag)
{ {
if (!sa) if (!sa)
@ -291,6 +392,14 @@ bool sa_isset(const struct sa *sa, int flag)
} }
/**
* Calculate the hash value of a Socket Address
*
* @param sa Socket Address
* @param flag Flags specifying which fields to use
*
* @return Hash value
*/
uint32_t sa_hash(const struct sa *sa, int flag) uint32_t sa_hash(const struct sa *sa, int flag)
{ {
uint32_t v = 0; uint32_t v = 0;
@ -327,6 +436,12 @@ uint32_t sa_hash(const struct sa *sa, int flag)
} }
/**
* Copy a Socket Address
*
* @param dst Socket Address to be written
* @param src Socket Address to be copied
*/
void sa_cpy(struct sa *dst, const struct sa *src) void sa_cpy(struct sa *dst, const struct sa *src)
{ {
if (!dst || !src) if (!dst || !src)
@ -336,6 +451,15 @@ void sa_cpy(struct sa *dst, const struct sa *src)
} }
/**
* Compare two Socket Address objects
*
* @param l Socket Address number one
* @param r Socket Address number two
* @param flag Flags specifying which fields to use
*
* @return true if match, false if no match
*/
bool sa_cmp(const struct sa *l, const struct sa *r, int flag) bool sa_cmp(const struct sa *l, const struct sa *r, int flag)
{ {
if (!l || !r) if (!l || !r)
@ -396,6 +520,7 @@ bool sa_is_linklocal(const struct sa *sa)
return false; return false;
switch (sa_af(sa)) { switch (sa_af(sa)) {
case AF_INET: case AF_INET:
return IN_IS_ADDR_LINKLOCAL(sa->u.in.sin_addr.s_addr); return IN_IS_ADDR_LINKLOCAL(sa->u.in.sin_addr.s_addr);
@ -423,6 +548,7 @@ bool sa_is_loopback(const struct sa *sa)
return false; return false;
switch (sa_af(sa)) { switch (sa_af(sa)) {
case AF_INET: case AF_INET:
return INADDR_LOOPBACK == ntohl(sa->u.in.sin_addr.s_addr); return INADDR_LOOPBACK == ntohl(sa->u.in.sin_addr.s_addr);
@ -450,6 +576,7 @@ bool sa_is_any(const struct sa *sa)
return false; return false;
switch (sa_af(sa)) { switch (sa_af(sa)) {
case AF_INET: case AF_INET:
return INADDR_ANY == ntohl(sa->u.in.sin_addr.s_addr); return INADDR_ANY == ntohl(sa->u.in.sin_addr.s_addr);

View file

@ -1,7 +1,8 @@
# #
# mod.mk # mod.mk
# #
# Copyright (C) 2010 Creytiv.com
#
SRCS += sdp/attr.c SRCS += sdp/attr.c
SRCS += sdp/format.c SRCS += sdp/format.c

View file

@ -1,6 +1,8 @@
# #
# mod.mk # mod.mk
# #
# Copyright (C) 2010 Creytiv.com
#
ifeq ($(USE_OPENSSL),) ifeq ($(USE_OPENSSL),)
SRCS += sha/sha1.c SRCS += sha/sha1.c

View file

@ -1,5 +1,6 @@
/* /**
SHA-1 in C * @file sha1.c SHA-1 in C
By Steve Reid <sreid@sea-to-sky.net> By Steve Reid <sreid@sea-to-sky.net>
100% Public Domain 100% Public Domain
@ -183,7 +184,11 @@ void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64])
} }
/** SHA1Init - Initialize new context */ /**
* Initialize new context
*
* @param context SHA1-Context
*/
void SHA1_Init(SHA1_CTX* context) void SHA1_Init(SHA1_CTX* context)
{ {
/* SHA1 initialization constants */ /* SHA1 initialization constants */
@ -196,7 +201,13 @@ void SHA1_Init(SHA1_CTX* context)
} }
/** Run your data through this. */ /**
* Run your data through this
*
* @param context SHA1-Context
* @param data Buffer to run SHA1 on
* @param len Number of bytes
*/
void SHA1_Update(SHA1_CTX* context, const uint8_t* data, const size_t len) void SHA1_Update(SHA1_CTX* context, const uint8_t* data, const size_t len)
{ {
size_t i, j; size_t i, j;
@ -217,7 +228,12 @@ void SHA1_Update(SHA1_CTX* context, const uint8_t* data, const size_t len)
} }
/** Add padding and return the message digest. */ /**
* Add padding and return the message digest
*
* @param digest Generated message digest
* @param context SHA1-Context
*/
void SHA1_Final(uint8_t digest[SHA1_DIGEST_SIZE], SHA1_CTX* context) void SHA1_Final(uint8_t digest[SHA1_DIGEST_SIZE], SHA1_CTX* context)
{ {
uint32_t i; uint32_t i;

View file

@ -1,5 +1,5 @@
/** /**
* @file keepalive.c SIP Keepalive * @file sip/keepalive.c SIP Keepalive
* *
* Copyright (C) 2010 Creytiv.com * Copyright (C) 2010 Creytiv.com
*/ */

View file

@ -1,7 +1,8 @@
# #
# mod.mk # mod.mk
# #
# Copyright (C) 2010 Creytiv.com
#
SRCS += sip/addr.c SRCS += sip/addr.c
SRCS += sip/auth.c SRCS += sip/auth.c

View file

@ -1,6 +1,7 @@
# #
# mod.mk # mod.mk
# #
# Copyright (C) 2010 Creytiv.com
#
SRCS += sipreg/reg.c SRCS += sipreg/reg.c

View file

@ -22,6 +22,7 @@ enum {
}; };
/** Defines a SIP Registration client */
struct sipreg { struct sipreg {
struct sip_loopstate ls; struct sip_loopstate ls;
struct sa laddr; struct sa laddr;
@ -297,6 +298,29 @@ static int request(struct sipreg *reg, bool reset_ls)
} }
/**
* Allocate a SIP Registration client
*
* @param regp Pointer to allocated SIP Registration client
* @param sip SIP Stack instance
* @param reg_uri SIP Request URI
* @param to_uri SIP To-header URI
* @param from_uri SIP From-header URI
* @param expires Registration interval in [seconds]
* @param cuser Contact username
* @param routev Optional route vector
* @param routec Number of routes
* @param regid Register identification
* @param authh Authentication handler
* @param aarg Authentication handler argument
* @param aref True to ref argument
* @param resph Response handler
* @param arg Response handler argument
* @param params Optional Contact-header parameters
* @param fmt Formatted strings with extra SIP Headers
*
* @return 0 if success, otherwise errorcode
*/
int sipreg_register(struct sipreg **regp, struct sip *sip, const char *reg_uri, int sipreg_register(struct sipreg **regp, struct sip *sip, const char *reg_uri,
const char *to_uri, const char *from_uri, uint32_t expires, const char *to_uri, const char *from_uri, uint32_t expires,
const char *cuser, const char *routev[], uint32_t routec, const char *cuser, const char *routev[], uint32_t routec,

View file

@ -1,7 +1,8 @@
# #
# mod.mk # mod.mk
# #
# Copyright (C) 2010 Creytiv.com
#
SRCS += sipsess/sess.c SRCS += sipsess/sess.c
SRCS += sipsess/accept.c SRCS += sipsess/accept.c

View file

@ -1,5 +1,5 @@
/** /**
* @file keepalive.c STUN usage for NAT Keepalives * @file stun/keepalive.c STUN usage for NAT Keepalives
* *
* Copyright (C) 2010 Creytiv.com * Copyright (C) 2010 Creytiv.com
*/ */

View file

@ -1,7 +1,8 @@
# #
# mod.mk # mod.mk
# #
# Copyright (C) 2010 Creytiv.com
#
SRCS += sys/daemon.c SRCS += sys/daemon.c
SRCS += sys/endian.c SRCS += sys/endian.c

View file

@ -1,7 +1,8 @@
# #
# mod.mk # mod.mk
# #
# Copyright (C) 2010 Creytiv.com
#
SRCS += tcp/tcp.c SRCS += tcp/tcp.c
SRCS += tcp/tcp_high.c SRCS += tcp/tcp_high.c

View file

@ -82,6 +82,7 @@ struct tcp_conn {
}; };
/** Defines a TCP-Connection Helper */
struct tcp_helper { struct tcp_helper {
struct le le; struct le le;
int layer; int layer;
@ -1082,6 +1083,15 @@ int tcp_send(struct tcp_conn *tc, struct mbuf *mb)
} }
/**
* Set the send handler on a TCP Connection, which will be called
* every time it is ready to send data
*
* @param tc TCP Connection
* @param sendh TCP Send handler
*
* @return 0 if success, otherwise errorcode
*/
int tcp_set_send(struct tcp_conn *tc, tcp_send_h *sendh) int tcp_set_send(struct tcp_conn *tc, tcp_send_h *sendh)
{ {
if (!tc) if (!tc)
@ -1186,6 +1196,13 @@ void tcp_conn_rxsz_set(struct tcp_conn *tc, size_t rxsz)
} }
/**
* Get the file descriptor of a TCP Connection
*
* @param tc TCP-Connection
*
* @return File destriptor, or -1 if errors
*/
int tcp_conn_fd(const struct tcp_conn *tc) int tcp_conn_fd(const struct tcp_conn *tc)
{ {
return tc ? tc->fdc : -1; return tc ? tc->fdc : -1;
@ -1201,6 +1218,19 @@ static bool sort_handler(struct le *le1, struct le *le2, void *arg)
} }
/**
* Register a new TCP-helper on a TCP-Connection
*
* @param thp Pointer to allocated TCP helper
* @param tc TCP Connection
* @param layer Protocol layer; higher number means higher up in stack
* @param eh Established handler
* @param sh Send handler
* @param rh Receive handler
* @param arg Handler argument
*
* @return 0 if success, otherwise errorcode
*/
int tcp_register_helper(struct tcp_helper **thp, struct tcp_conn *tc, int tcp_register_helper(struct tcp_helper **thp, struct tcp_conn *tc,
int layer, int layer,
tcp_helper_estab_h *eh, tcp_helper_send_h *sh, tcp_helper_estab_h *eh, tcp_helper_send_h *sh,

View file

@ -1,6 +1,7 @@
# #
# mod.mk # mod.mk
# #
# Copyright (C) 2010 Creytiv.com
#
SRCS += telev/telev.c SRCS += telev/telev.c

View file

@ -67,6 +67,7 @@ struct telev_fmt {
}; };
/** Defines a Telephony Events state */
struct telev { struct telev {
/* tx */ /* tx */
struct mbuf *mb; struct mbuf *mb;
@ -134,6 +135,14 @@ static void destructor(void *arg)
} }
/**
* Allocate a new Telephony Events state
*
* @param tp Pointer to allocated object
* @param ptime Packet time in [ms]
*
* @return 0 if success, otherwise errorcode
*/
int telev_alloc(struct telev **tp, uint32_t ptime) int telev_alloc(struct telev **tp, uint32_t ptime)
{ {
struct telev *t; struct telev *t;
@ -166,6 +175,15 @@ int telev_alloc(struct telev **tp, uint32_t ptime)
} }
/**
* Send a Telephony Event
*
* @param tel Telephony Event state
* @param event The Event to send
* @param end End-of-event flag
*
* @return 0 if success, otherwise errorcode
*/
int telev_send(struct telev *tel, int event, bool end) int telev_send(struct telev *tel, int event, bool end)
{ {
size_t pos; size_t pos;
@ -184,6 +202,16 @@ int telev_send(struct telev *tel, int event, bool end)
} }
/**
* Receive a Telephony Event
*
* @param tel Telephony Event state
* @param mb Buffer to decode
* @param event The received event, set on return
* @param end End-of-event flag, set on return
*
* @return 0 if success, otherwise errorcode
*/
int telev_recv(struct telev *tel, struct mbuf *mb, int *event, bool *end) int telev_recv(struct telev *tel, struct mbuf *mb, int *event, bool *end)
{ {
struct telev_fmt fmt; struct telev_fmt fmt;
@ -217,6 +245,15 @@ int telev_recv(struct telev *tel, struct mbuf *mb, int *event, bool *end)
} }
/**
* Poll a Telephony Event state for sending
*
* @param tel Telephony Event state
* @param marker Marker bit, set on return
* @param mb Buffer with encoded data to send
*
* @return 0 if success, otherwise errorcode
*/
int telev_poll(struct telev *tel, bool *marker, struct mbuf *mb) int telev_poll(struct telev *tel, bool *marker, struct mbuf *mb)
{ {
bool mrk = false; bool mrk = false;

View file

@ -1,7 +1,8 @@
# #
# mod.mk # mod.mk
# #
# Copyright (C) 2010 Creytiv.com
#
ifneq ($(USE_OPENSSL),) ifneq ($(USE_OPENSSL),)
SRCS += tls/openssl/tls.c SRCS += tls/openssl/tls.c

View file

@ -1,6 +1,7 @@
# #
# mod.mk # mod.mk
# #
# Copyright (C) 2010 Creytiv.com
#
SRCS += tmr/tmr.c SRCS += tmr/tmr.c

View file

@ -34,7 +34,7 @@
enum { enum {
MAX_BLOCKING = 100, /**< Maximum ticks spent in handler */ MAX_BLOCKING = 100 /**< Maximum time spent in handler [ms] */
}; };
extern struct list *tmrl_get(void); extern struct list *tmrl_get(void);
@ -70,6 +70,8 @@ static void call_handler(tmr_h *th, void *arg)
/** /**
* Poll all timers in the current thread * Poll all timers in the current thread
*
* @param tmrl Timer list
*/ */
void tmr_poll(struct list *tmrl) void tmr_poll(struct list *tmrl)
{ {
@ -108,7 +110,7 @@ void tmr_poll(struct list *tmrl)
/** /**
* Get the timer jiffies in milliseconds * Get the timer jiffies in milliseconds
* *
* @return Jiffies [ms] * @return Jiffies in [ms]
*/ */
uint64_t tmr_jiffies(void) uint64_t tmr_jiffies(void)
{ {
@ -139,9 +141,11 @@ uint64_t tmr_jiffies(void)
/** /**
* Get number of ticks until the next timer timeout. * Get number of milliseconds until the next timer expires
* *
* @return Ticks, or 0 if no active timers. * @param tmrl Timer-list
*
* @return Number of [ms], or 0 if no active timers
*/ */
uint64_t tmr_next_timeout(struct list *tmrl) uint64_t tmr_next_timeout(struct list *tmrl)
{ {
@ -202,7 +206,7 @@ void tmr_init(struct tmr *tmr)
/** /**
* Start the timer on a timer object * Start a timer
* *
* @param tmr Timer to start * @param tmr Timer to start
* @param delay Timer delay in [ms] * @param delay Timer delay in [ms]

View file

@ -160,6 +160,16 @@ static int chanbind_request(struct chan *chan, bool reset_ls)
} }
/**
* Add a TURN Channel for a peer
*
* @param turnc TURN Client
* @param peer Peer IP-address
* @param ch Channel handler
* @param arg Handler argument
*
* @return 0 if success, otherwise errorcode
*/
int turnc_add_chan(struct turnc *turnc, const struct sa *peer, int turnc_add_chan(struct turnc *turnc, const struct sa *peer,
turnc_chan_h *ch, void *arg) turnc_chan_h *ch, void *arg)
{ {

View file

@ -1,7 +1,8 @@
# #
# mod.mk # mod.mk
# #
# Copyright (C) 2010 Creytiv.com
#
SRCS += turn/chan.c SRCS += turn/chan.c
SRCS += turn/perm.c SRCS += turn/perm.c

View file

@ -134,6 +134,16 @@ static int createperm_request(struct perm *perm, bool reset_ls)
} }
/**
* Add TURN Permission for a peer
*
* @param turnc TURN Client
* @param peer Peer IP-address
* @param ph Permission handler
* @param arg Handler argument
*
* @return 0 if success, otherwise errorcode
*/
int turnc_add_perm(struct turnc *turnc, const struct sa *peer, int turnc_add_perm(struct turnc *turnc, const struct sa *peer,
turnc_perm_h *ph, void *arg) turnc_perm_h *ph, void *arg)
{ {

View file

@ -369,6 +369,23 @@ static bool udp_recv_handler(struct sa *src, struct mbuf *mb, void *arg)
} }
/**
* Allocate a TURN Client
*
* @param turncp Pointer to allocated TURN Client
* @param conf Optional STUN Configuration
* @param proto Transport Protocol
* @param sock Transport socket
* @param layer Transport layer
* @param srv TURN Server IP-address
* @param username Authentication username
* @param password Authentication password
* @param lifetime Allocate lifetime in [seconds]
* @param th TURN handler
* @param arg Handler argument
*
* @return 0 if success, otherwise errorcode
*/
int turnc_alloc(struct turnc **turncp, const struct stun_conf *conf, int proto, int turnc_alloc(struct turnc **turncp, const struct stun_conf *conf, int proto,
void *sock, int layer, const struct sa *srv, void *sock, int layer, const struct sa *srv,
const char *username, const char *password, const char *username, const char *password,

View file

@ -13,16 +13,17 @@ struct loop_state {
struct channels; struct channels;
/** Defines a TURN Client */
struct turnc { struct turnc {
struct loop_state ls; struct loop_state ls; /**< Loop state */
struct udp_helper *uh; struct udp_helper *uh; /**< UDP Helper for the TURN Socket */
struct stun_ctrans *ct; struct stun_ctrans *ct; /**< Pending STUN Client Transaction */
char *username; char *username; /**< Authentication username */
char *password; char *password; /**< Authentication password */
struct sa psrv; struct sa psrv; /**< Previous TURN Server address */
struct sa srv; struct sa srv; /**< TURN Server address */
void *sock; void *sock; /**< Transport socket */
int proto; int proto; /**< Transport protocol */
struct stun *stun; /**< STUN Instance */ struct stun *stun; /**< STUN Instance */
uint32_t lifetime; /**< Allocation lifetime in [seconds]*/ uint32_t lifetime; /**< Allocation lifetime in [seconds]*/
struct tmr tmr; /**< Allocation refresh timer */ struct tmr tmr; /**< Allocation refresh timer */
@ -31,9 +32,9 @@ struct turnc {
uint8_t md5_hash[MD5_SIZE]; /**< Cached MD5-sum of credentials */ uint8_t md5_hash[MD5_SIZE]; /**< Cached MD5-sum of credentials */
char *nonce; /**< Saved NONCE value from server */ char *nonce; /**< Saved NONCE value from server */
char *realm; /**< Saved REALM value from server */ char *realm; /**< Saved REALM value from server */
struct hash *perms; struct hash *perms; /**< Hash-table of permissions */
struct channels *chans; struct channels *chans; /**< TURN Channels */
bool allocated; bool allocated; /**< Allocation was done flag */
}; };

View file

@ -1,6 +1,7 @@
# #
# mod.mk # mod.mk
# #
# Copyright (C) 2010 Creytiv.com
#
SRCS += udp/udp.c SRCS += udp/udp.c

View file

@ -72,7 +72,7 @@ struct udp_sock {
int err; /**< Cached error code */ int err; /**< Cached error code */
}; };
/** Defines a UDP helper */
struct udp_helper { struct udp_helper {
struct le le; struct le le;
int layer; int layer;
@ -577,7 +577,7 @@ int udp_setsockopt(struct udp_sock *us, int level, int optname,
* Set the send/receive buffer size on a UDP Socket * Set the send/receive buffer size on a UDP Socket
* *
* @param us UDP Socket * @param us UDP Socket
* @param size Buffer size * @param size Buffer size in bytes
* *
* @return 0 if success, otherwise errorcode * @return 0 if success, otherwise errorcode
*/ */
@ -642,6 +642,14 @@ void udp_handler_set(struct udp_sock *us, udp_recv_h *rh, void *arg)
} }
/**
* Get the File Descriptor from a UDP Socket
*
* @param us UDP Socket
* @param af Address Family
*
* @return File Descriptor, or -1 for errors
*/
int udp_sock_fd(const struct udp_sock *us, int af) int udp_sock_fd(const struct udp_sock *us, int af)
{ {
if (!us) if (!us)