update splash

This commit is contained in:
Alfred E. Heggestad 2010-11-03 11:34:14 +00:00
commit 6648fd2393
282 changed files with 45451 additions and 0 deletions

109
Makefile Normal file
View file

@ -0,0 +1,109 @@
#
# Makefile
#
# Copyright (C) 2010 Creytiv.com
#
# Master version number
VER_MAJOR := 0
VER_MINOR := 1
VER_PATCH := 0
PROJECT := re
VERSION := 0.1.0
MK := mk/re.mk
include $(MK)
# List of modules
MODULES += sip sipreg sipsess
MODULES += uri httpauth
MODULES += stun turn ice
MODULES += natbd
MODULES += rtp sdp g711 jbuf telev
MODULES += dns
MODULES += md5 crc32 sha hmac base64
MODULES += udp sa net tcp tls
MODULES += list mbuf hash
MODULES += fmt tmr main mem dbg sys lock mqueue
MODULES += mod conf
INSTALL := install
ifeq ($(DESTDIR),)
PREFIX := /usr/local
else
PREFIX := /usr
endif
ifeq ($(LIBDIR),)
LIBDIR := $(PREFIX)/lib
endif
INCDIR := $(PREFIX)/include/re
MKDIR := $(PREFIX)/share/re
CFLAGS += -Iinclude
MODMKS := $(patsubst %,src/%/mod.mk,$(MODULES))
SHARED := libre$(LIB_SUFFIX)
STATIC := libre.a
include $(MODMKS)
OBJS ?= $(patsubst %.c,$(BUILD)/%.o,$(SRCS))
all: $(SHARED) $(STATIC)
-include $(OBJS:.o=.d)
$(SHARED): $(OBJS)
@echo " LD $@"
@$(LD) $(LFLAGS) $(SH_LFLAGS) $^ $(LIBS) -o $@
$(STATIC): $(OBJS)
@echo " AR $@"
@$(AR) $(AFLAGS) $@ $^
ifneq ($(RANLIB),)
@$(RANLIB) $@
endif
$(BUILD)/%.o: src/%.c $(BUILD) Makefile $(MK) $(MODMKS)
@echo " CC $@"
@$(CC) $(CFLAGS) -c $< -o $@ $(DFLAGS)
$(BUILD): Makefile $(MK) $(MODMKS)
@mkdir -p $(patsubst %,$(BUILD)/%,$(sort $(dir $(SRCS))))
@touch $@
.PHONY: clean
clean:
@rm -rf $(SHARED) $(STATIC) test.d test.o test $(BUILD)/
install: $(SHARED) $(STATIC)
@mkdir -p $(DESTDIR)$(LIBDIR) $(DESTDIR)$(INCDIR) $(DESTDIR)$(MKDIR)
$(INSTALL) -m 0644 $(shell find include -name "*.h") \
$(DESTDIR)$(INCDIR)
$(INSTALL) -m 0755 $(SHARED) $(DESTDIR)$(LIBDIR)
$(INSTALL) -m 0755 $(STATIC) $(DESTDIR)$(LIBDIR)
$(INSTALL) -m 0644 $(MK) $(DESTDIR)$(MKDIR)
-include test.d
test.o: test.c Makefile $(MK)
@echo " CC $@"
@$(CC) $(CFLAGS) -c $< -o $@ $(DFLAGS)
test$(BIN_SUFFIX): test.o $(SHARED) $(STATIC)
@echo " LD $@"
@$(LD) $(LFLAGS) $< -L. -lre $(LIBS) -o $@
sym: $(SHARED)
@nm $(SHARED) | grep " U " | perl -pe 's/\s*U\s+(.*)/$${1}/' \
> docs/symbols.txt
@echo "$(SHARED) is using `cat docs/symbols.txt | wc -l ` symbols"

5
debian/changelog vendored Normal file
View file

@ -0,0 +1,5 @@
libre (0.1.0) unstable; urgency=low
* version 0.1.0
-- Alfred E. Heggestad <aeh@db.org> Fri, 5 Nov 2010 05:11:10 +0100

1
debian/compat vendored Normal file
View file

@ -0,0 +1 @@
7

34
debian/control vendored Normal file
View file

@ -0,0 +1,34 @@
Source: libre
Section: comm
Priority: optional
Maintainer: Alfred E. Heggestad <aeh@db.org>
Build-Depends: debhelper (>= 4.0.0)
Standards-Version: 3.6.2
Package: libre
Architecture: any
Section: libs
Depends: ${shlibs:Depends}
Description: Generic library for real-time communications with async IO support
.
Design goals:
.
- Portable POSIX source code (ANSI C89 and ISO C99 standard)
- Robust, fast, low memory footprint
- RFC compliance
- IPv4 and IPv6 support
Package: libre-dev
Architecture: any
Section: libdevel
Depends: libre (= ${Source-Version}), ${shlibs:Depends}
Description: Generic library for real-time communications with async IO support (development files)
.
Design goals:
.
- Portable POSIX source code (ANSI C89 and ISO C99 standard)
- Robust, fast, low memory footprint
- RFC compliance
- IPv4 and IPv6 support
.
This package is only the library development files.

9
debian/copyright vendored Normal file
View file

@ -0,0 +1,9 @@
This package was debianized by Alfred E. Heggestad <aeh@db.org>
It was downloaded from http://www.creytiv.com/
Copyright Holder: Creytiv.com
License:
BSD License

2
debian/docs vendored Normal file
View file

@ -0,0 +1,2 @@
docs/README
docs/TODO

3
debian/libre-dev.dirs vendored Normal file
View file

@ -0,0 +1,3 @@
usr/include
usr/lib
usr/share

3
debian/libre-dev.files vendored Normal file
View file

@ -0,0 +1,3 @@
usr/include
usr/lib/libre.a
usr/share/re

1
debian/libre.dirs vendored Normal file
View file

@ -0,0 +1 @@
usr/lib

1
debian/libre.files vendored Normal file
View file

@ -0,0 +1 @@
/usr/lib/libre.so

88
debian/rules vendored Executable file
View file

@ -0,0 +1,88 @@
#!/usr/bin/make -f
# -*- makefile -*-
# Sample debian/rules that uses debhelper.
# This file was originally written by Joey Hess and Craig Small.
# As a special exception, when this file is copied by dh-make into a
# dh-make output file, you may use that output file without restriction.
# This special exception was added by Craig Small in version 0.37 of dh-make.
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
configure: configure-stamp
configure-stamp:
dh_testdir
# Add here commands to configure the package.
touch configure-stamp
build: build-stamp
build-stamp: configure-stamp
dh_testdir
# Add here commands to compile the package.
$(MAKE) RELEASE=1
touch $@
clean:
dh_testdir
dh_testroot
rm -f build-stamp configure-stamp
# Add here commands to clean up after the build process.
-$(MAKE) clean
dh_clean
install: build
dh_testdir
dh_testroot
dh_clean -k
dh_installdirs
# Add here commands to install the package into debian/tmp
mkdir $(CURDIR)/debian/tmp
$(MAKE) install DESTDIR=$(CURDIR)/debian/tmp
dh_movefiles
# Build architecture-independent files here.
binary-indep: build install
# We have nothing to do by default.
# Build architecture-dependent files here.
binary-arch: build install
dh_testdir
dh_testroot
dh_installchangelogs
dh_installdocs
dh_installexamples
# dh_install
# dh_installmenu
# dh_installdebconf
# dh_installlogrotate
# dh_installemacsen
# dh_installpam
# dh_installmime
# dh_installinit
# dh_installcron
# dh_installinfo
dh_installman
dh_link
dh_strip
dh_compress
dh_fixperms
# dh_perl
# dh_python
# dh_makeshlibs
dh_installdeb
dh_shlibdeps
dh_gencontrol
dh_md5sums
dh_builddeb
binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary install configure

31
docs/COPYING Normal file
View file

@ -0,0 +1,31 @@
Copyright (c) 2010, Alfred E. Heggestad
Copyright (c) 2010, Creytiv.com
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the Creytiv.com nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

146
docs/README Normal file
View file

@ -0,0 +1,146 @@
README
------
libre - "Generic library for real-time communications with async IO support"
Copyright (C) 2010 Creytiv.com
Distributed under BSD license
Design goals:
* Portable POSIX source code (ANSI C89 and ISO C99 standard)
* Robust, fast, low memory footprint
* RFC compliance
* IPv4 and IPv6 support
Modules:
name: status: description:
* base64 testing Base-64 encoding/decoding functions
* conf testing Configuration file parser
* crc32 testing 32-bit CRC defined in ITU V.42
* dbg testing Debug printing
* dns testing DNS resolving (NAPTR, SRV, A)
* fmt testing Formatted printing and regular expression
* g711 stable G.711 codec
* hash testing Hashmap table
* hmac testing HMAC: Keyed-Hashing for Message Authentication
* httpauth unstable HTTP-based Authentication (RFC 2617)
* ice development Interactive Connectivity Establishment (ICE)
* jbuf testing Jitter buffer
* list stable Sortable doubly-linked list handling
* lock testing Resource locking functions
* main testing Main poll loop
* mbuf stable Linear memory buffers
* md5 stable The MD5 Message-Digest Algorithm (RFC 1321)
* mem stable Memory referencing
* mod testing Run-time module loading
* mqueue unstable Thread-safe message queue
* natbd unstable NAT Behavior Discovery using STUN
* net unstable Networking routines
* rtp testing Real-time Transport Protocol
* sa stable Socket Address functions
* sdp unstable Session Description Protocol
* sha testing Secure Hash Standard, NIST, FIPS PUB 180-1
* sip unstable Core SIP library
* sipreg testing SIP register client
* sipsess unstable SIP Sessions
* stun unstable Session Traversal Utilities for NAT (STUN)
* sys testing System information
* tcp testing TCP transport
* telev testing Telephony Events (RFC 4733)
* tls unstable Transport Layer Security
* tmr stable Timer handling
* turn unstable Obtaining Relay Addresses from STUN (TURN)
* udp testing UDP transport
* uri testing Generic URI library
legend:
"stable" - Code complete; Stable code and stable API
"testing" - Code complete, but API might change
"unstable" - Code complete but not completely tested
"development" - Code is under development
Features:
* RFC 1321 - The MD5 Message-Digest Algorithm
* RFC 1886 - DNS Extensions to support IP version 6
* RFC 2032 - RTP Payload Format for H.261 Video Streams
* RFC 2617 - HTTP Authentication: Basic and Digest Access Authentication
* RFC 2782 - A DNS RR for Specifying the Location of Services (DNS SRV)
* RFC 2915 - The Naming Authority Pointer (NAPTR) DNS Resource Record
* RFC 3261 - SIP: Session Initiation Protocol
* RFC 3263 - Locating SIP Servers
* RFC 3264 - An Offer/Answer Model with SDP
* RFC 3327 - SIP Extension Header Field for Registering Non-Adjacent Contacts
* RFC 3428 - SIP Extension for Instant Messaging
* RFC 3489 - STUN - Simple Traversal of UDP Through NATs
* RFC 3550 - RTP: A Transport Protocol for Real-Time Applications
* RFC 3551 - RTP Profile for Audio and Video Conferences with Minimal Control
* RFC 3555 - MIME Type Registration of RTP Payload Formats
* RFC 3556 - SDP Bandwidth Modifiers for RTCP Bandwidth
* RFC 3581 - An Extension to SIP for Symmetric Response Routing
* RFC 3605 - RTCP attribute in SDP
* RFC 3969 - The IANA URI Parameter Registry for SIP
* RFC 3994 - Indication of Message Composition for Instant Messaging
* RFC 4346 - The TLS Protocol Version 1.1
* RFC 4566 - SDP: Session Description Protocol
* RFC 4585 - Extended RTP Profile for RTCP-Based Feedback
* RFC 4733 - RTP Payload for DTMF Digits, Telephony Tones, and Teleph. Signals
* RFC 4961 - Symmetric RTP / RTP Control Protocol (RTCP)
* RFC 5118 - SIP Torture Test Messages for IPv6
* RFC 5245 - Interactive Connectivity Establishment (ICE)
* RFC 5389 - Session Traversal Utilities for NAT (STUN)
* RFC 5766 - Traversal Using Relays around NAT (TURN)
* RFC 5768 - Indicating Support for ICE in SIP
* RFC 5769 - Test vectors for STUN
* RFC 5780 - NAT Behaviour Discovery Using STUN
* RFC 6026 - Correct Transaction Handling for 2xx Resp. to SIP INVITE Requests
* Symmetric RTP
* draft-ietf-behave-turn-ipv6-08 - TURN Extension for IPv4/IPv6 Transition
* ITU-T G.711 Appendix I and Appendix II
Supported platforms:
* Linux
* FreeBSD
* OpenBSD
* NetBSD
* Symbian OS
* Solaris
* Windows
* Apple Mac OS X
Supported compilers:
* gcc (v2.9x to v4.x)
* gcce
* ms vc2003 compiler
* codewarrior
Feedback:
- Please send feedback to <libre@creytiv.com>
Coding guidelines:
* Use enum for constants where appropriate
* Use const as much as possible (where appropriate)
* Use C99 data types (intN_t, uintN_t, bool)
* Hide data-types in .c files where possible (use struct foo)
* Avoid malloc/free, use mem_alloc/mem_deref instead
* CVS/svn/git tags are NOT allowed in the code!
* Avoid bit-fields in structs which are not portable
* Use dummy handlers for timing-critical callbacks
* return err, return alloced objects as pointer-pointers
* in allocating functions, first arg is always double pointer
* Use POSIX error-codes; EINVAL for invalid args, EBADMSG for
parse errors and EPROTO for protocol errors

11
docs/TODO Normal file
View file

@ -0,0 +1,11 @@
TODO
-------------------------------------------------------------------------------
Version v0.1.1
SIP Outbound support - client+server
tmr: scaling using binary heap or hash
Add support for SIP SUBSCRIBE/NOTIFY
Add support for Call-Transfer in SIP Session
-------------------------------------------------------------------------------

7
docs/main.dox Normal file
View file

@ -0,0 +1,7 @@
/**
* \mainpage libre Development Documentation
*
* Development documentation for libre
*
* \section modules modules
*/

137
docs/symbols.txt Normal file
View file

@ -0,0 +1,137 @@
BIO_new@@OPENSSL_0.9.8
BIO_new_socket@@OPENSSL_0.9.8
BIO_s_mem@@OPENSSL_0.9.8
BIO_write@@OPENSSL_0.9.8
ERR_free_strings@@OPENSSL_0.9.8
ERR_get_error@@OPENSSL_0.9.8
EVP_sha1@@OPENSSL_0.9.8
HMAC@@OPENSSL_0.9.8
MD5@@OPENSSL_0.9.8
RAND_bytes@@OPENSSL_0.9.8
SSL_CTX_free@@OPENSSL_0.9.8
SSL_CTX_load_verify_locations@@OPENSSL_0.9.8
SSL_CTX_new@@OPENSSL_0.9.8
SSL_CTX_set_default_passwd_cb@@OPENSSL_0.9.8
SSL_CTX_set_default_passwd_cb_userdata@@OPENSSL_0.9.8
SSL_CTX_use_PrivateKey_file@@OPENSSL_0.9.8
SSL_CTX_use_certificate_chain_file@@OPENSSL_0.9.8
SSL_accept@@OPENSSL_0.9.8
SSL_connect@@OPENSSL_0.9.8
SSL_free@@OPENSSL_0.9.8
SSL_get_error@@OPENSSL_0.9.8
SSL_get_peer_certificate@@OPENSSL_0.9.8
SSL_get_verify_result@@OPENSSL_0.9.8
SSL_library_init@@OPENSSL_0.9.8
SSL_load_error_strings@@OPENSSL_0.9.8
SSL_new@@OPENSSL_0.9.8
SSL_read@@OPENSSL_0.9.8
SSL_set_bio@@OPENSSL_0.9.8
SSL_shutdown@@OPENSSL_0.9.8
SSL_state@@OPENSSL_0.9.8
SSL_write@@OPENSSL_0.9.8
SSLv23_method@@OPENSSL_0.9.8
X509_NAME_get_text_by_NID@@OPENSSL_0.9.8
X509_get_subject_name@@OPENSSL_0.9.8
__ctype_b_loc@@GLIBC_2.3
__errno_location@@GLIBC_2.2.5
__isinf@@GLIBC_2.2.5
__isnan@@GLIBC_2.2.5
__isoc99_fscanf@@GLIBC_2.7
__res_close@@GLIBC_2.2.5
__res_init@@GLIBC_2.2.5
__res_state@@GLIBC_2.2.5
__sysv_signal@@GLIBC_2.2.5
accept@@GLIBC_2.2.5
atoi@@GLIBC_2.2.5
bind@@GLIBC_2.2.5
chdir@@GLIBC_2.2.5
close@@GLIBC_2.2.5
connect@@GLIBC_2.2.5
crc32
ctime@@GLIBC_2.2.5
dlclose@@GLIBC_2.2.5
dlerror@@GLIBC_2.2.5
dlopen@@GLIBC_2.2.5
dlsym@@GLIBC_2.2.5
epoll_create@@GLIBC_2.3.2
epoll_ctl@@GLIBC_2.3.2
epoll_wait@@GLIBC_2.3.2
exit@@GLIBC_2.2.5
fclose@@GLIBC_2.2.5
fcntl@@GLIBC_2.2.5
fflush@@GLIBC_2.2.5
fopen@@GLIBC_2.2.5
fork@@GLIBC_2.2.5
free@@GLIBC_2.2.5
freeaddrinfo@@GLIBC_2.2.5
freeifaddrs@@GLIBC_2.3
freopen@@GLIBC_2.2.5
fwrite@@GLIBC_2.2.5
gai_strerror@@GLIBC_2.2.5
getaddrinfo@@GLIBC_2.2.5
gethostbyname@@GLIBC_2.2.5
gethostname@@GLIBC_2.2.5
getifaddrs@@GLIBC_2.3
getpeername@@GLIBC_2.2.5
getpid@@GLIBC_2.2.5
getsockname@@GLIBC_2.2.5
getsockopt@@GLIBC_2.2.5
gettimeofday@@GLIBC_2.2.5
htonl@@GLIBC_2.2.5
htons@@GLIBC_2.2.5
if_indextoname@@GLIBC_2.2.5
inet_ntop@@GLIBC_2.2.5
inet_pton@@GLIBC_2.2.5
ioctl@@GLIBC_2.2.5
listen@@GLIBC_2.2.5
malloc@@GLIBC_2.2.5
memcmp@@GLIBC_2.2.5
memcpy@@GLIBC_2.2.5
memmove@@GLIBC_2.2.5
memset@@GLIBC_2.2.5
ntohl@@GLIBC_2.2.5
ntohs@@GLIBC_2.2.5
open@@GLIBC_2.2.5
pipe@@GLIBC_2.2.5
poll@@GLIBC_2.2.5
pthread_getspecific@@GLIBC_2.2.5
pthread_key_create@@GLIBC_2.2.5
pthread_mutex_init@@GLIBC_2.2.5
pthread_mutex_lock@@GLIBC_2.2.5
pthread_mutex_unlock@@GLIBC_2.2.5
pthread_once@@GLIBC_2.2.5
pthread_rwlock_destroy@@GLIBC_2.2.5
pthread_rwlock_init@@GLIBC_2.2.5
pthread_rwlock_rdlock@@GLIBC_2.2.5
pthread_rwlock_tryrdlock@@GLIBC_2.2.5
pthread_rwlock_trywrlock@@GLIBC_2.2.5
pthread_rwlock_unlock@@GLIBC_2.2.5
pthread_rwlock_wrlock@@GLIBC_2.2.5
pthread_self@@GLIBC_2.2.5
pthread_setspecific@@GLIBC_2.2.5
read@@GLIBC_2.2.5
realloc@@GLIBC_2.2.5
recv@@GLIBC_2.2.5
recvfrom@@GLIBC_2.2.5
select@@GLIBC_2.2.5
send@@GLIBC_2.2.5
sendto@@GLIBC_2.2.5
setrlimit@@GLIBC_2.2.5
setsid@@GLIBC_2.2.5
setsockopt@@GLIBC_2.2.5
socket@@GLIBC_2.2.5
srand@@GLIBC_2.2.5
stderr@@GLIBC_2.2.5
stdin@@GLIBC_2.2.5
stdout@@GLIBC_2.2.5
strcasecmp@@GLIBC_2.2.5
strcmp@@GLIBC_2.2.5
strerror@@GLIBC_2.2.5
strlen@@GLIBC_2.2.5
strncasecmp@@GLIBC_2.2.5
strncpy@@GLIBC_2.2.5
time@@GLIBC_2.2.5
tolower@@GLIBC_2.2.5
umask@@GLIBC_2.2.5
uname@@GLIBC_2.2.5
write@@GLIBC_2.2.5

53
include/re.h Normal file
View file

@ -0,0 +1,53 @@
/**
* @file re.h Wrapper for all header files
*
* Copyright (C) 2010 Creytiv.com
*/
#ifdef __cplusplus
extern "C" {
#endif
/* Basic types */
#include "re_types.h"
#include "re_fmt.h"
#include "re_mbuf.h"
#include "re_list.h"
#include "re_sa.h"
/* Library modules */
#include "re_base64.h"
#include "re_conf.h"
#include "re_crc32.h"
#include "re_dns.h"
#include "re_g711.h"
#include "re_hash.h"
#include "re_httpauth.h"
#include "re_ice.h"
#include "re_jbuf.h"
#include "re_lock.h"
#include "re_main.h"
#include "re_md5.h"
#include "re_mem.h"
#include "re_mod.h"
#include "re_mqueue.h"
#include "re_net.h"
#include "re_rtp.h"
#include "re_sdp.h"
#include "re_uri.h"
#include "re_sip.h"
#include "re_sipreg.h"
#include "re_sipsess.h"
#include "re_stun.h"
#include "re_natbd.h"
#include "re_sys.h"
#include "re_tcp.h"
#include "re_telev.h"
#include "re_tmr.h"
#include "re_tls.h"
#include "re_turn.h"
#include "re_udp.h"
#ifdef __cplusplus
}
#endif

9
include/re_base64.h Normal file
View file

@ -0,0 +1,9 @@
/**
* @file re_base64.h Interface to Base64 encoding/decoding functions
*
* Copyright (C) 2010 Creytiv.com
*/
int base64_encode(const uint8_t *in, size_t ilen, char *out, size_t *olen);
int base64_decode(const char *in, size_t ilen, uint8_t *out, size_t *olen);

73
include/re_bitv.h Normal file
View file

@ -0,0 +1,73 @@
/**
* @file re_bitv.h Interface to Bit Vector functions
*
* Copyright (C) 2010 Creytiv.com
*/
typedef unsigned long bitv_t;
enum {
BITS_SZ = (8*sizeof(bitv_t)),
BITS_MASK = (BITS_SZ-1)
};
#define BITV_NELEM(nbits) (((nbits) + (BITS_SZ) - 1) / (BITS_SZ))
#define BITV_DECL(name, nbits) bitv_t (name)[BITV_NELEM(nbits)]
static inline uint32_t index2offset(uint32_t i)
{
return i/BITS_SZ;
}
static inline bitv_t index2bit(uint32_t i)
{
return (bitv_t)1<<(i & BITS_MASK);
}
/*
* Public API
*/
static inline void bitv_init(bitv_t *bv, uint32_t nbits, bool val)
{
memset(bv, val?0xff:0x00, BITV_NELEM(nbits)*sizeof(bitv_t));
}
static inline void bitv_set(bitv_t *bv, uint32_t i)
{
bv[index2offset(i)] |= index2bit(i);
}
static inline void bitv_clr(bitv_t *bv, uint32_t i)
{
bv[index2offset(i)] &= ~index2bit(i);
}
static inline void bitv_assign(bitv_t *bv, uint32_t i, bool val)
{
if (val)
bitv_set(bv, i);
else
bitv_clr(bv, i);
}
static inline bool bitv_val(const bitv_t *bv, uint32_t i)
{
return 0 != (bv[index2offset(i)] & index2bit(i));
}
static inline void bitv_toggle(bitv_t *bv, uint32_t i)
{
bv[index2offset(i)] ^= index2bit(i);
}
static inline void bitv_assign_range(bitv_t *bv, uint32_t i, uint32_t n,
bool val)
{
while (n--)
bitv_assign(bv, i+n, val);
}

18
include/re_conf.h Normal file
View file

@ -0,0 +1,18 @@
/**
* @file re_conf.h Interface to configuration
*
* Copyright (C) 2010 Creytiv.com
*/
struct conf;
typedef int (conf_h)(const struct pl *val, void *arg);
int conf_alloc(struct conf **confp, const char *filename);
int conf_alloc_buf(struct conf **confp, const uint8_t *buf, size_t sz);
int conf_get(struct conf *conf, const char *name, struct pl *pl);
int conf_get_str(struct conf *conf, const char *name, char *str,
size_t size);
int conf_get_u32(struct conf *conf, const char *name, uint32_t *num);
int conf_apply(struct conf *conf, const char *name, conf_h *ch, void *arg);

12
include/re_crc32.h Normal file
View file

@ -0,0 +1,12 @@
/**
* @file re_crc32.h Interface to CRC-32 functions
*
* Copyright (C) 2010 Creytiv.com
*/
#ifdef USE_ZLIB
#include <zlib.h>
#else
uint32_t crc32(uint32_t crc, const void *buf, uint32_t size);
#endif

193
include/re_dbg.h Normal file
View file

@ -0,0 +1,193 @@
/**
* @file re_dbg.h Interface to debugging module
*
* Copyright (C) 2010 Creytiv.com
*/
#ifdef __cplusplus
extern "C" {
#endif
/** Debug levels */
enum {
DBG_EMERG = 0, /**< System is unusable */
DBG_ALERT = 1, /**< Action must be taken immediately */
DBG_CRIT = 2, /**< Critical conditions */
DBG_ERR = 3, /**< Error conditions */
DBG_WARNING = 4, /**< Warning conditions */
DBG_NOTICE = 5, /**< Normal but significant condition */
DBG_INFO = 6, /**< Informational */
DBG_DEBUG = 7 /**< Debug-level messages */
};
/**
* @def DEBUG_MODULE
*
* Module name defined by application
*/
/**
* @def DEBUG_LEVEL
*
* Debug level defined by application
*/
#ifndef DEBUG_MODULE
# warning "DEBUG_MODULE is not defined"
#define DEBUG_MODULE "?"
#endif
#ifndef DEBUG_LEVEL
# warning "DEBUG_LEVEL is not defined"
#define DEBUG_LEVEL 7
#endif
/**
* @def DEBUG_WARNING(...)
*
* Print warning message
*/
/**
* @def DEBUG_NOTICE(...)
*
* Print notice message
*/
/**
* @def DEBUG_INFO(...)
*
* Print info message
*/
/**
* @def DEBUG_PRINTF(...)
*
* Print debug message
*/
/* Check for ISO C99 variable argument macros */
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) \
|| (__GNUC__ >= 3)
#if (DEBUG_LEVEL >= 4)
#define DEBUG_WARNING(...) \
dbg_printf(DBG_WARNING, DEBUG_MODULE ": " __VA_ARGS__)
#else
#define DEBUG_WARNING(...)
#endif
#if (DEBUG_LEVEL >= 5)
#define DEBUG_NOTICE(...) \
dbg_printf(DBG_NOTICE, DEBUG_MODULE ": " __VA_ARGS__)
#else
#define DEBUG_NOTICE(...)
#endif
#if (DEBUG_LEVEL >= 6)
#define DEBUG_INFO(...) \
dbg_printf(DBG_INFO, DEBUG_MODULE ": " __VA_ARGS__)
#else
#define DEBUG_INFO(...)
#endif
#if (DEBUG_LEVEL >= 7)
#define DEBUG_PRINTF(...) \
dbg_printf(DBG_DEBUG, DEBUG_MODULE ": " __VA_ARGS__)
#else
#define DEBUG_PRINTF(...)
#endif
/* GNU extensions for variable argument macros */
#elif defined(__GNUC__)
#if (DEBUG_LEVEL >= 4)
#define DEBUG_WARNING(a...) dbg_printf(DBG_WARNING, DEBUG_MODULE ": " a)
#else
#define DEBUG_WARNING(a...)
#endif
#if (DEBUG_LEVEL >= 5)
#define DEBUG_NOTICE(a...) dbg_printf(DBG_NOTICE, DEBUG_MODULE ": " a)
#else
#define DEBUG_NOTICE(a...)
#endif
#if (DEBUG_LEVEL >= 6)
#define DEBUG_INFO(a...) dbg_printf(DBG_INFO, DEBUG_MODULE ": " a)
#else
#define DEBUG_INFO(a...)
#endif
#if (DEBUG_LEVEL >= 7)
#define DEBUG_PRINTF(a...) dbg_printf(DBG_DEBUG, DEBUG_MODULE ": " a)
#else
#define DEBUG_PRINTF(a...)
#endif
/* No variable argument macros */
#else
#if (DEBUG_LEVEL >= 4)
#define DEBUG_WARNING dbg_warning
#else
#define DEBUG_WARNING dbg_noprintf
#endif
#if (DEBUG_LEVEL >= 5)
#define DEBUG_NOTICE dbg_notice
#else
#define DEBUG_NOTICE dbg_noprintf
#endif
#if (DEBUG_LEVEL >= 6)
#define DEBUG_INFO dbg_info
#else
#define DEBUG_INFO dbg_noprintf
#endif
#if (DEBUG_LEVEL >= 7)
#define DEBUG_PRINTF dbg_noprintf
#else
#define DEBUG_PRINTF dbg_noprintf
#endif
#endif
/** Debug flags */
enum dbg_flags {
DBG_NONE = 0, /**< No debug flags */
DBG_TIME = 1<<0, /**< Print timestamp flag */
DBG_ANSI = 1<<1, /**< Print ANSI color codes */
DBG_ALL = DBG_TIME|DBG_ANSI /**< All flags enabled */
};
/**
* Defines the debug print handler
*
* @param level Debug level
* @param p Debug string
* @param len String length
* @param arg Handler argument
*/
typedef void (dbg_print_h)(int level, const char *p, size_t len, void *arg);
void dbg_init(int level, enum dbg_flags flags);
void dbg_close(void);
int dbg_logfile_set(const char *name);
void dbg_handler_set(dbg_print_h *ph, void *arg);
void dbg_printf(int level, const char *fmt, ...);
void dbg_noprintf(const char *fmt, ...);
void dbg_warning(const char *fmt, ...);
void dbg_notice(const char *fmt, ...);
void dbg_info(const char *fmt, ...);
const char *dbg_level_str(int level);
#ifdef __cplusplus
}
#endif

192
include/re_dns.h Normal file
View file

@ -0,0 +1,192 @@
/**
* @file re_dns.h Interface to DNS module
*
* Copyright (C) 2010 Creytiv.com
*/
enum {
DNS_PORT = 53,
DNS_HEADER_SIZE = 12
};
enum {
DNS_OPCODE_QUERY = 0,
DNS_OPCODE_IQUERY = 1,
DNS_OPCODE_STATUS = 2,
DNS_OPCODE_NOTIFY = 4
};
enum {
DNS_RCODE_OK = 0,
DNS_RCODE_FMT_ERR = 1,
DNS_RCODE_SRV_FAIL = 2,
DNS_RCODE_NAME_ERR = 3,
DNS_RCODE_NOT_IMPL = 4,
DNS_RCODE_REFUSED = 5,
DNS_RCODE_NOT_AUTH = 9
};
enum {
DNS_TYPE_A = 0x0001,
DNS_TYPE_NS = 0x0002,
DNS_TYPE_CNAME = 0x0005,
DNS_TYPE_SOA = 0x0006,
DNS_TYPE_PTR = 0x000c,
DNS_TYPE_MX = 0x000f,
DNS_TYPE_AAAA = 0x001c,
DNS_TYPE_SRV = 0x0021,
DNS_TYPE_NAPTR = 0x0023,
DNS_QTYPE_IXFR = 0x00fb,
DNS_QTYPE_AXFR = 0x00fc,
DNS_QTYPE_ANY = 0x00ff
};
enum {
DNS_CLASS_IN = 0x0001,
DNS_QCLASS_ANY = 0x00ff
};
struct dnshdr {
uint16_t id;
bool qr;
uint8_t opcode;
bool aa;
bool tc;
bool rd;
bool ra;
uint8_t z;
uint8_t rcode;
uint16_t nq;
uint16_t nans;
uint16_t nauth;
uint16_t nadd;
};
struct dnsrr {
struct le le;
struct le le_priv;
char *name;
uint16_t type;
uint16_t dnsclass;
int64_t ttl;
uint16_t rdlen;
union {
struct {
uint32_t addr;
} a;
struct {
char *nsdname;
} ns;
struct {
char *cname;
} cname;
struct {
char *mname;
char *rname;
uint32_t serial;
uint32_t refresh;
uint32_t retry;
uint32_t expire;
uint32_t ttlmin;
} soa;
struct {
char *ptrdname;
} ptr;
struct {
uint16_t pref;
char *exchange;
} mx;
struct {
uint8_t addr[16];
} aaaa;
struct {
uint16_t pri;
uint16_t weight;
uint16_t port;
char *target;
} srv;
struct {
uint16_t order;
uint16_t pref;
char *flags;
char *services;
char *regexp;
char *replace;
} naptr;
} rdata;
};
struct hash;
typedef void(dns_query_h)(int err, const struct dnshdr *hdr,
struct list *ansl, struct list *authl,
struct list *addl, void *arg);
typedef bool(dns_rrlist_h)(struct dnsrr *rr, void *arg);
int dns_hdr_encode(struct mbuf *mb, const struct dnshdr *hdr);
int dns_hdr_decode(struct mbuf *mb, struct dnshdr *hdr);
const char *dns_hdr_opcodename(uint8_t opcode);
const char *dns_hdr_rcodename(uint8_t rcode);
struct dnsrr *dns_rr_alloc(void);
int dns_rr_encode(struct mbuf *mb, const struct dnsrr *rr, int64_t ttl_offs,
struct hash *ht_dname, size_t start);
int dns_rr_decode(struct mbuf *mb, struct dnsrr **rr, size_t start);
bool dns_rr_cmp(const struct dnsrr *rr1, const struct dnsrr *rr2, bool rdata);
const char *dns_rr_typename(uint16_t type);
const char *dns_rr_classname(uint16_t dnsclass);
int dns_rr_print(struct re_printf *pf, const struct dnsrr *rr);
int dns_dname_encode(struct mbuf *mb, const char *name,
struct hash *ht_dname, size_t start, bool comp);
int dns_dname_decode(struct mbuf *mb, char **name, size_t start);
int dns_cstr_encode(struct mbuf *mb, const char *str);
int dns_cstr_decode(struct mbuf *mb, char **str);
void dns_rrlist_sort(struct list *rrl, uint16_t type);
struct dnsrr *dns_rrlist_apply(struct list *rrl, const char *name,
uint16_t type, uint16_t dnsclass,
bool recurse, dns_rrlist_h *rrlh, void *arg);
struct dnsrr *dns_rrlist_apply2(struct list *rrl, const char *name,
uint16_t type1, uint16_t type2,
uint16_t dnsclass, bool recurse,
dns_rrlist_h *rrlh, void *arg);
struct dnsrr *dns_rrlist_find(struct list *rrl, const char *name,
uint16_t type, uint16_t dnsclass, bool recurse);
/* DNS Client */
struct sa;
struct dnsc;
struct dns_query;
struct dnsc_conf {
uint32_t query_hash_size;
uint32_t tcp_hash_size;
uint32_t conn_timeout; /* in [ms] */
uint32_t idle_timeout; /* in [ms] */
bool udp_conn;
};
int dnsc_alloc(struct dnsc **dcpp, const struct dnsc_conf *conf,
const struct sa *srvv, uint32_t srvc);
int dnsc_srv_set(struct dnsc *dnsc, const struct sa *srvv, uint32_t srvc);
int dnsc_query(struct dns_query **qp, struct dnsc *dnsc, const char *name,
uint16_t type, uint16_t dnsclass,
bool rd, dns_query_h *qh, void *arg);
int dnsc_query_srv(struct dns_query **qp, struct dnsc *dnsc, const char *name,
uint16_t type, uint16_t dnsclass, int proto,
const struct sa *srvv, const uint32_t *srvc,
bool rd, dns_query_h *qh, void *arg);
int dnsc_notify(struct dns_query **qp, struct dnsc *dnsc, const char *name,
uint16_t type, uint16_t dnsclass, const struct dnsrr *ans_rr,
int proto, const struct sa *srvv, const uint32_t *srvc,
dns_query_h *qh, void *arg);
/* DNS System functions */
int dns_srv_get(char *domain, size_t dsize, struct sa *srvv, uint32_t *n);

118
include/re_fmt.h Normal file
View file

@ -0,0 +1,118 @@
/**
* @file re_fmt.h Interface to formatted text functions
*
* Copyright (C) 2010 Creytiv.com
*/
#include <stdarg.h>
#include <stdio.h>
struct mbuf;
/** Defines a pointer-length string type */
struct pl {
const char *p; /**< Pointer to string */
size_t l; /**< Length of string */
};
/** Initialise a pointer-length object from a constant string */
#define PL(s) {(s), sizeof((s))-1}
/** Pointer-length Initializer */
#define PL_INIT {NULL, 0}
extern const struct pl pl_null;
void pl_set_str(struct pl *pl, const char *str);
void pl_set_mbuf(struct pl *pl, const struct mbuf *mb);
uint32_t pl_u32(const struct pl *pl);
uint32_t pl_x32(const struct pl *pl);
uint64_t pl_u64(const struct pl *pl);
bool pl_isset(const struct pl *pl);
int pl_strcpy(const struct pl *pl, char *str, size_t size);
int pl_strdup(char **dst, const struct pl *src);
int pl_dup(struct pl *dst, const struct pl *src);
int pl_strcmp(const struct pl *pl, const char *str);
int pl_strcasecmp(const struct pl *pl, const char *str);
int pl_cmp(const struct pl *pl1, const struct pl *pl2);
int pl_casecmp(const struct pl *pl1, const struct pl *pl2);
const char *pl_strchr(const struct pl *pl, char c);
/** Advance pl position/length by +/- N bytes */
static inline void pl_advance(struct pl *pl, ssize_t n)
{
pl->p += n;
pl->l -= n;
}
/* Formatted printing */
/**
* Defines the re_vhprintf() print handler
*
* @param p String to print
* @param size Size of string to print
* @param arg Handler argument
*/
typedef int(re_vprintf_h)(const char *p, size_t size, void *arg);
/** Defines a print backend */
struct re_printf {
re_vprintf_h *vph; /**< Print handler */
void *arg; /**< Handler agument */
};
/**
* Defines the %H print handler
*
* @param pf Print backend
* @param arg Handler argument
*/
typedef int(re_printf_h)(struct re_printf *pf, void *arg);
int re_vhprintf(const char *fmt, va_list ap, re_vprintf_h *vph, void *arg);
int re_vfprintf(FILE *stream, const char *fmt, va_list ap);
int re_vprintf(const char *fmt, va_list ap);
int re_vsnprintf(char *str, size_t size, const char *fmt, va_list ap);
int re_vsdprintf(char **strp, const char *fmt, va_list ap);
int re_hprintf(struct re_printf *pf, const char *fmt, ...);
int re_fprintf(FILE *stream, const char *fmt, ...);
int re_printf(const char *fmt, ...);
int re_snprintf(char *str, size_t size, const char *fmt, ...);
int re_sdprintf(char **strp, const char *fmt, ...);
/* Regular expressions */
int re_regex(const char *ptr, size_t len, const char *expr, ...);
/* Character functions */
uint8_t ch_hex(char ch);
/* String functions */
int str_hex(uint8_t *hex, size_t len, const char *str);
void str_ncpy(char *dst, const char *src, size_t n);
int str_dup(char **dst, const char *src);
int str_casecmp(const char *s1, const char *s2);
size_t str_len(const char *s);
/* time */
int fmt_human_time(struct re_printf *pf, const uint32_t *seconds);
void hexdump(FILE *f, const void *p, size_t len);
/* param */
typedef void (fmt_param_h)(const struct pl *name, const struct pl *val,
void *arg);
bool fmt_param_get(const struct pl *pl, const char *pname, struct pl *val);
void fmt_param_apply(const struct pl *pl, fmt_param_h *ph, void *arg);

47
include/re_g711.h Normal file
View file

@ -0,0 +1,47 @@
/**
* @file re_g711.h Interface to G.711 codec
*
* Copyright (C) 2010 Creytiv.com
*/
extern const uint8_t g711_l2u[4096];
extern const uint8_t g711_l2A[2048];
extern const int16_t g711_u2l[256];
extern const int16_t g711_A2l[256];
static inline uint8_t g711_pcm2ulaw(int16_t l)
{
const uint8_t mask = (l < 0) ? 0x7f : 0xff;
if (l < 0)
l = -l;
if (l < 4)
return 0xff & mask;
l -= 4;
l >>= 3;
return g711_l2u[l] & mask;
}
static inline uint8_t g711_pcm2alaw(int16_t l)
{
const uint8_t mask = (l < 0) ? 0x7f : 0xff;
if (l < 0)
l = -l;
l >>= 4;
return g711_l2A[l] & mask;
}
static inline int16_t g711_ulaw2pcm(uint8_t u)
{
return g711_u2l[u];
}
static inline int16_t g711_alaw2pcm(uint8_t a)
{
return g711_A2l[a];
}

29
include/re_hash.h Normal file
View file

@ -0,0 +1,29 @@
/**
* @file re_hash.h Interface to hashmap table
*
* Copyright (C) 2010 Creytiv.com
*/
struct hash;
struct pl;
int hash_alloc(struct hash **hp, uint32_t bsize);
void hash_append(struct hash *h, uint32_t key, struct le *le, void *data);
void hash_unlink(struct le *le);
struct le *hash_lookup(const struct hash *h, uint32_t key, list_apply_h *ah,
void *arg);
struct le *hash_apply(const struct hash *h, list_apply_h *ah, void *arg);
struct list *hash_list(const struct hash *h, uint32_t key);
uint32_t hash_bsize(const struct hash *h);
void hash_flush(struct hash *h);
/* Hash functions */
uint32_t hash_joaat(const uint8_t *key, size_t len);
uint32_t hash_joaat_ci(const char *str, size_t len);
uint32_t hash_joaat_str(const char *str);
uint32_t hash_joaat_str_ci(const char *str);
uint32_t hash_joaat_pl(const struct pl *pl);
uint32_t hash_joaat_pl_ci(const struct pl *pl);

13
include/re_hmac.h Normal file
View file

@ -0,0 +1,13 @@
/**
* @file re_hmac.h Interface to HMAC functions
*
* Copyright (C) 2010 Creytiv.com
*/
void hmac_sha1(const uint8_t *k, /* secret key */
size_t lk, /* length of the key in bytes */
const uint8_t *d, /* data */
size_t ld, /* length of data in bytes */
uint8_t* out, /* output buffer, at least "t" bytes */
size_t t);

58
include/re_httpauth.h Normal file
View file

@ -0,0 +1,58 @@
/**
* @file re_httpauth.h Interface to HTTP Authentication
*
* Copyright (C) 2010 Creytiv.com
*/
/** Authentication type */
enum httpauth_hdr {
HTTPAUTH_WWW,
HTTPAUTH_PROXY
};
/* Client code */
struct httpauth_digest_chall {
enum httpauth_hdr hdr;
struct pl realm;
struct pl nonce;
/* optional */
struct pl opaque;
struct pl stale;
struct pl algorithm;
struct pl qop;
};
int httpauth_digest_challenge_decode(struct httpauth_digest_chall *chall,
const struct pl *hval);
int httpauth_digest_response_encode(struct mbuf *mb, const struct pl *hname,
const struct httpauth_digest_chall *chall,
const struct pl *username,
const struct pl *uri,
const struct pl *cnonce,
const struct pl *qop,
const struct pl *nc,
const uint8_t *digest);
/* Server code */
struct httpauth_digest_resp {
struct pl realm;
struct pl nonce;
struct pl response;
struct pl nc;
struct pl cnonce;
struct pl qop;
struct pl username;
struct pl uri;
};
int httpauth_digest_authenticate(struct httpauth_digest_resp *resp,
bool *auth, const struct pl *method,
const char *ha1);
int httpauth_digest_decode_response(struct httpauth_digest_resp *resp,
const struct pl *hval);
int httpauth_digest_encode_challenge(struct mbuf *mb, const struct pl *hname,
const struct pl *realm);

67
include/re_ice.h Normal file
View file

@ -0,0 +1,67 @@
/**
* @file re_ice.h Interface to Interactive Connectivity Establishment (ICE)
*
* Copyright (C) 2010 Creytiv.com
*/
enum ice_mode {
ICE_MODE_FULL,
ICE_MODE_LITE
};
enum ice_compid {
ICE_COMPID_RTP = 1,
ICE_COMPID_RTCP = 2
};
struct ice;
struct icem;
typedef void (ice_gather_h)(int err, uint16_t scode, const char *reason,
void *arg);
typedef void (ice_connchk_h)(int err, bool update, void *arg);
/* ICE Session */
int ice_alloc(struct ice **icep, enum ice_mode mode, bool offerer);
void ice_set_offerer(struct ice *ice, bool offerer);
int ice_sdp_decode(struct ice *ice, const char *name, const char *value);
int ice_conncheck_start(struct ice *ice);
int ice_debug(struct re_printf *pf, const struct ice *ice);
struct list *ice_medialist(const struct ice *ice);
const char *ice_ufrag(const struct ice *ice);
const char *ice_pwd(const struct ice *ice);
/* ICE Media */
int icem_alloc(struct icem **icemp, struct ice *ice, int proto, int layer,
ice_gather_h *gh, ice_connchk_h *chkh, void *arg);
int icem_comp_add(struct icem *icem, uint8_t compid, void *sock);
int icem_cand_add(struct icem *icem, uint8_t compid, uint16_t lprio,
const char *ifname, const struct sa *addr);
int icem_gather_srflx(struct icem *icem, const struct sa *stun_srv);
int icem_gather_relay(struct icem *icem, const struct sa *stun_srv,
const char *username, const char *password);
bool icem_verify_support(struct icem *icem, uint8_t compid,
const struct sa *raddr);
int icem_add_chan(struct icem *icem, uint8_t compid, const struct sa *raddr);
bool icem_mismatch(const struct icem *icem);
int icem_sdp_decode(struct icem *icem, const char *name, const char *value);
int icem_debug(struct re_printf *pf, const struct icem *icem);
struct list *icem_lcandl(const struct icem *icem);
const struct sa *icem_cand_default(struct icem *icem, uint8_t compid);
const struct sa *icem_selected_laddr(const struct icem *icem, uint8_t compid);
struct cand;
bool ice_remotecands_avail(const struct icem *icem);
int ice_cand_encode(struct re_printf *pf, const struct cand *cand);
int ice_remotecands_encode(struct re_printf *pf, const struct icem *icem);
extern const char ice_attr_cand[];
extern const char ice_attr_lite[];
extern const char ice_attr_mismatch[];
extern const char ice_attr_pwd[];
extern const char ice_attr_remote_cand[];
extern const char ice_attr_ufrag[];

28
include/re_jbuf.h Normal file
View file

@ -0,0 +1,28 @@
/**
* @file re_jbuf.h Interface to Jitter Buffer
*
* Copyright (C) 2010 Creytiv.com
*/
struct jbuf;
struct rtp_header;
/** Jitter buffer statistics */
struct jbuf_stat {
uint32_t n_put; /**< Number of frames put into jitter buffer */
uint32_t n_get; /**< Number of frames got from jitter buffer */
uint32_t n_oos; /**< Number of out-of-sequence frames */
uint32_t n_dups; /**< Number of duplicate frames detected */
uint32_t n_late; /**< Number of frames arriving too late */
uint32_t n_lost; /**< Number of lost frames */
uint32_t n_overflow; /**< Number of overflows */
uint32_t n_underflow; /**< Number of underflows */
uint32_t n_flush; /**< Number of times jitter buffer flushed */
};
int jbuf_alloc(struct jbuf **jbp, uint32_t min, uint32_t max);
int jbuf_put(struct jbuf *jb, const struct rtp_header *hdr, void *mem);
int jbuf_get(struct jbuf *jb, struct rtp_header *hdr, void **mem);
void jbuf_flush(struct jbuf *jb);
int jbuf_stats(const struct jbuf *jb, struct jbuf_stat *jstat);
int jbuf_debug(struct re_printf *pf, const struct jbuf *jb);

95
include/re_list.h Normal file
View file

@ -0,0 +1,95 @@
/**
* @file re_list.h Interface to Linked List
*
* Copyright (C) 2010 Creytiv.com
*/
/** Linked-list element */
struct le {
struct le *prev; /**< Previous element */
struct le *next; /**< Next element */
struct list *list; /**< Parent list (NULL if not linked-in) */
void *data; /**< User-data */
};
/** List Element Initializer */
#define LE_INIT {NULL, NULL, NULL, NULL}
/** Defines a linked list */
struct list {
struct le *head; /**< First list element */
struct le *tail; /**< Last list element */
};
/** Linked list Initializer */
#define LIST_INIT {NULL, NULL}
/**
* Defines the list apply handler
*
* @param le List element
* @param arg Handler argument
*
* @return true to stop traversing, false to continue
*/
typedef bool (list_apply_h)(struct le *le, void *arg);
/**
* Defines the list sort handler
*
* @param le1 Current list element
* @param le2 Next list element
* @param arg Handler argument
*
* @return true if sorted, otherwise false
*/
typedef bool (list_sort_h)(struct le *le1, struct le *le2, void *arg);
void list_init(struct list *list);
void list_flush(struct list *list);
void list_append(struct list *list, struct le *le, void *data);
void list_prepend(struct list *list, struct le *le, void *data);
void list_insert_before(struct list *list, struct le *le, struct le *ile,
void *data);
void list_insert_after(struct list *list, struct le *le, struct le *ile,
void *data);
void list_unlink(struct le *le);
void list_sort(struct list *list, list_sort_h *sh, void *arg);
struct le *list_apply(const struct list *list, bool fwd, list_apply_h *ah,
void *arg);
struct le *list_head(const struct list *list);
struct le *list_tail(const struct list *list);
uint32_t list_count(const struct list *list);
/**
* Get the user-data from a list element
*
* @param le List element
*
* @return Pointer to user-data
*/
static inline void *list_ledata(const struct le *le)
{
return le ? le->data : NULL;
}
static inline bool list_contains(const struct list *list, const struct le *le)
{
return le ? le->list == list : false;
}
static inline bool list_isempty(const struct list *list)
{
return list ? list->head == NULL : true;
}
#define LIST_FOREACH(list, le) \
for ((le) = list_head((list)); (le); (le) = (le)->next)

18
include/re_lock.h Normal file
View file

@ -0,0 +1,18 @@
/**
* @file re_lock.h Interface to locking functions
*
* Copyright (C) 2010 Creytiv.com
*/
struct lock;
int lock_alloc(struct lock **lp);
void lock_read_get(struct lock *l);
void lock_write_get(struct lock *l);
int lock_read_try(struct lock *l);
int lock_write_try(struct lock *l);
void lock_rel(struct lock *l);

67
include/re_main.h Normal file
View file

@ -0,0 +1,67 @@
/**
* @file re_main.h Interface to main polling routine
*
* Copyright (C) 2010 Creytiv.com
*/
enum {
#ifndef FD_READ
FD_READ = 1<<0,
#endif
#ifndef FD_WRITE
FD_WRITE = 1<<1,
#endif
FD_EXCEPT = 1<<2
};
/**
* File descriptor event handler
*
* @param flags Event flags
* @param arg Handler argument
*/
typedef void (fd_h)(int flags, void *arg);
/**
* Thread-safe signal handler
*
* @param sig Signal number
*/
typedef void (re_signal_h)(int sig);
int fd_listen(int fd, int flags, fd_h *fh, void *arg);
void fd_close(int fd);
int fd_setsize(int maxfds);
void fd_debug(void);
int libre_init(void);
void libre_close(void);
int re_main(re_signal_h *signalh);
void re_cancel(void);
int re_debug(struct re_printf *pf, void *unused);
int re_thread_init(void);
void re_thread_close(void);
void re_thread_enter(void);
void re_thread_leave(void);
/** Polling methods */
enum poll_method {
METHOD_NULL = 0,
METHOD_POLL,
METHOD_SELECT,
METHOD_EPOLL,
METHOD_ACTSCHED,
/* sep */
METHOD_MAX
};
int poll_method_set(enum poll_method method);
enum poll_method poll_method_best(void);
const char *poll_method_name(enum poll_method method);
int poll_method_type(enum poll_method *method, const struct pl *name);

165
include/re_mbuf.h Normal file
View file

@ -0,0 +1,165 @@
/**
* @file re_mbuf.h Interface to memory buffers
*
* Copyright (C) 2010 Creytiv.com
*/
#include <stdarg.h>
#ifndef RELEASE
#define MBUF_DEBUG 1 /**< Mbuf debugging (0 or 1) */
#endif
#if MBUF_DEBUG
/** Check that mbuf position does not exceed end */
#define MBUF_CHECK_POS(mb) \
if ((mb) && (mb)->pos > (mb)->end) { \
BREAKPOINT; \
}
/** Check that mbuf end does not exceed size */
#define MBUF_CHECK_END(mb) \
if ((mb) && (mb)->end > (mb)->size) { \
BREAKPOINT; \
}
#else
#define MBUF_CHECK_POS(mb)
#define MBUF_CHECK_END(mb)
#endif
/** Defines a memory buffer */
struct mbuf {
uint8_t *buf; /**< Buffer memory */
size_t size; /**< Size of buffer */
size_t pos; /**< Position in buffer */
size_t end; /**< End of buffer */
};
struct pl;
struct mbuf *mbuf_alloc(size_t size);
struct mbuf *mbuf_alloc_ref(struct mbuf *mbr);
void mbuf_init(struct mbuf *mb);
void mbuf_reset(struct mbuf *mb);
int mbuf_resize(struct mbuf *mb, size_t size);
void mbuf_trim(struct mbuf *mb);
int mbuf_write_mem(struct mbuf *mb, const uint8_t *buf, size_t size);
int mbuf_write_u8(struct mbuf *mb, uint8_t v);
int mbuf_write_u16(struct mbuf *mb, uint16_t v);
int mbuf_write_u32(struct mbuf *mb, uint32_t v);
int mbuf_write_u64(struct mbuf *mb, uint64_t v);
int mbuf_write_str(struct mbuf *mb, const char *str);
int mbuf_write_pl(struct mbuf *mb, const struct pl *pl);
int mbuf_read_mem(struct mbuf *mb, uint8_t *buf, size_t size);
uint8_t mbuf_read_u8(struct mbuf *mb);
uint16_t mbuf_read_u16(struct mbuf *mb);
uint32_t mbuf_read_u32(struct mbuf *mb);
uint64_t mbuf_read_u64(struct mbuf *mb);
int mbuf_read_str(struct mbuf *mb, char *str, size_t size);
int mbuf_strdup(struct mbuf *mb, char **strp, size_t len);
int mbuf_vprintf(struct mbuf *mb, const char *fmt, va_list ap);
int mbuf_printf(struct mbuf *mb, const char *fmt, ...);
int mbuf_write_pl_skip(struct mbuf *mb, const struct pl *pl,
const struct pl *skip);
/**
* Get the buffer from the current position
*
* @param mb Memory buffer
*
* @return Current buffer
*/
static inline uint8_t *mbuf_buf(const struct mbuf *mb)
{
return mb ? mb->buf + mb->pos : NULL;
}
/**
* Get number of bytes left in a memory buffer, from current position to end
*
* @param mb Memory buffer
*
* @return Number of bytes left
*/
static inline size_t mbuf_get_left(const struct mbuf *mb)
{
return mb ? (mb->end - mb->pos) : 0;
}
/**
* Get available space in buffer (size - pos)
*
* @param mb Memory buffer
*
* @return Number of bytes available in buffer
*/
static inline size_t mbuf_get_space(const struct mbuf *mb)
{
return mb ? (mb->size - mb->pos) : 0;
}
/**
* Set absolute position
*
* @param mb Memory buffer
* @param pos Position
*/
static inline void mbuf_set_pos(struct mbuf *mb, size_t pos)
{
mb->pos = pos;
MBUF_CHECK_POS(mb);
}
/**
* Set absolute end
*
* @param mb Memory buffer
* @param end End position
*/
static inline void mbuf_set_end(struct mbuf *mb, size_t end)
{
mb->end = end;
MBUF_CHECK_END(mb);
}
/**
* Advance position +/- N bytes
*
* @param mb Memory buffer
* @param n Number of bytes to advance
*/
static inline void mbuf_advance(struct mbuf *mb, ssize_t n)
{
mb->pos += n;
MBUF_CHECK_POS(mb);
}
/**
* Rewind position and end to the beginning of buffer
*
* @param mb Memory buffer
*/
static inline void mbuf_rewind(struct mbuf *mb)
{
mb->pos = mb->end = 0;
}
/**
* Set position to the end of the buffer
*
* @param mb Memory buffer
*/
static inline void mbuf_skip_to_end(struct mbuf *mb)
{
mb->pos = mb->end;
}

14
include/re_md5.h Normal file
View file

@ -0,0 +1,14 @@
/**
* @file re_md5.h Interface to MD5 functions
*
* Copyright (C) 2010 Creytiv.com
*/
enum {
MD5_SIZE = 16, /**< Number of bytes in MD5 hash */
MD5_STR_SIZE = 2*MD5_SIZE + 1 /**< Number of bytes in MD5 string */
};
void md5(const uint8_t *d, size_t n, uint8_t *md);
int md5_printf(uint8_t *md, const char *fmt, ...);

37
include/re_mem.h Normal file
View file

@ -0,0 +1,37 @@
/**
* @file re_mem.h Interface to Memory management with reference counting
*
* Copyright (C) 2010 Creytiv.com
*/
/**
* Defines the memory destructor handler, which is called when the reference
* of a memory object goes down to zero
*
* @param data Pointer to memory object
*/
typedef void (mem_destroy_h)(void *data);
/** Memory Statistics */
struct memstat {
size_t bytes_cur; /**< Current bytes allocated */
size_t bytes_peak; /**< Peak bytes allocated */
size_t blocks_cur; /**< Current blocks allocated */
size_t blocks_peak; /**< Peak blocks allocated */
size_t size_min; /**< Lowest block size allocated */
size_t size_max; /**< Largest block size allocated */
};
void *mem_alloc(size_t size, mem_destroy_h *dh);
void *mem_zalloc(size_t size, mem_destroy_h *dh);
void *mem_realloc(void *data, size_t size);
void *mem_ref(void *data);
void *mem_deref(void *data);
uint32_t mem_nrefs(const void *data);
void mem_debug(void);
void mem_threshold_set(ssize_t n);
struct re_printf;
int mem_status(struct re_printf *pf, void *unused);
int mem_get_stat(struct memstat *mstat);

77
include/re_mod.h Normal file
View file

@ -0,0 +1,77 @@
/**
* @file re_mod.h Interface to loadable modules
*
* Copyright (C) 2010 Creytiv.com
*/
/**
* @def MOD_PRE
*
* Module Prefix
*
* @def MOD_EXT
*
* Module Extension
*/
#if defined (WIN32)
#define MOD_PRE ""
#define MOD_EXT ".dll"
#elif defined (__SYMBIAN32__)
#define MOD_PRE "mod_"
#define MOD_EXT ".dll"
#else
#define MOD_PRE ""
#define MOD_EXT ".so"
#endif
/** Symbol to enable exporting of functions from a module */
#ifdef WIN32
#define EXPORT_SYM __declspec(dllexport)
#else
#define EXPORT_SYM
#endif
/* ----- Module API ----- */
/**
* Defines the module initialisation handler
*
* @return 0 for success, otherwise errorcode
*/
typedef int (mod_init_h)(void);
/**
* Defines the module close handler
*
* @return 0 for success, otherwise errorcode
*/
typedef int (mod_close_h)(void);
struct mod;
struct re_printf;
/** Defines the module export */
struct mod_export {
const char *name; /**< Module name */
const char *type; /**< Module type */
mod_init_h *init; /**< Module init handler */
mod_close_h *close; /**< Module close handler */
};
/* ----- Application API ----- */
void mod_init(void);
void mod_close(void);
int mod_load(struct mod **mp, const char *name);
int mod_add(struct mod **mp, const struct mod_export *me);
struct mod *mod_find(const char *name);
const struct mod_export *mod_export(const struct mod *m);
int mod_debug(struct re_printf *pf, void *unused);

12
include/re_mqueue.h Normal file
View file

@ -0,0 +1,12 @@
/**
* @file re_mqueue.h Thread Safe Message Queue
*
* Copyright (C) 2010 Creytiv.com
*/
struct mqueue;
typedef void (mqueue_h)(int id, void *data);
int mqueue_alloc(struct mqueue **mqp);
int mqueue_push(struct mqueue *mq, mqueue_h *h, int id, void *data);

128
include/re_natbd.h Normal file
View file

@ -0,0 +1,128 @@
/**
* @file re_natbd.h NAT Behavior Discovery Using STUN
* draft-ietf-behave-nat-behavior-discovery-06
*
* Copyright (C) 2010 Creytiv.com
*/
/** NAT Mapping/Filtering types - See RFC 4787 for definitions */
enum nat_type {
NAT_TYPE_UNKNOWN = 0, /**< Unknown type */
NAT_TYPE_ENDP_INDEP = 1, /**< Endpoint-Independent */
NAT_TYPE_ADDR_DEP = 2, /**< Address-Dependent */
NAT_TYPE_ADDR_PORT_DEP = 3 /**< Address and Port-Dependent */
};
/* Strings */
const char *nat_type_str(enum nat_type type);
/*
* Diagnosing NAT Hairpinning
*/
struct nat_hairpinning;
/**
* Defines the NAT Hairpinning handler
*/
typedef void (nat_hairpinning_h)(int err, bool supported, void *arg);
int nat_hairpinning_alloc(struct nat_hairpinning **nhp,
const struct sa *srv, int proto,
const struct stun_conf *conf,
nat_hairpinning_h *hph, void *arg);
int nat_hairpinning_start(struct nat_hairpinning *nh);
/*
* Determining NAT Mapping Behavior
*/
struct nat_mapping;
/**
* Defines the NAT Mapping handler
*
* @param err Errorcode
* @param type NAT Mapping type
* @param arg Handler argument
*/
typedef void (nat_mapping_h)(int err, enum nat_type map, void *arg);
int nat_mapping_alloc(struct nat_mapping **nmp, const struct sa *laddr,
const struct sa *srv, int proto,
const struct stun_conf *conf,
nat_mapping_h *mh, void *arg);
int nat_mapping_start(struct nat_mapping *nm);
/*
* Determining NAT Filtering Behavior
*/
struct nat_filtering;
/**
* Defines the NAT Filtering handler
*
* @param err Errorcode
* @param type NAT Filtering type
* @param arg Handler argument
*/
typedef void (nat_filtering_h)(int err, enum nat_type filt, void *arg);
int nat_filtering_alloc(struct nat_filtering **nfp, const struct sa *srv,
const struct stun_conf *conf,
nat_filtering_h *fh, void *arg);
int nat_filtering_start(struct nat_filtering *nf);
/*
* Binding Lifetime Discovery
*/
/** Defines the NAT lifetime interval */
struct nat_lifetime;
struct nat_lifetime_interval {
uint32_t min; /**< Minimum lifetime interval in [seconds] */
uint32_t cur; /**< Current lifetime interval in [seconds] */
uint32_t max; /**< Maximum lifetime interval in [seconds] */
};
/**
* Defines the NAT Lifetime handler
*
* @param err Errorcode
* @param i NAT Lifetime intervals
* @param arg Handler argument
*/
typedef void (nat_lifetime_h)(int err, const struct nat_lifetime_interval *i,
void *arg);
int nat_lifetime_alloc(struct nat_lifetime **nlp, const struct sa *srv,
uint32_t interval, const struct stun_conf *conf,
nat_lifetime_h *lh, void *arg);
int nat_lifetime_start(struct nat_lifetime *nl);
/*
* Detecting Generic ALGs
*/
struct nat_genalg;
/**
* Defines the NAT Generic ALG handler
*
* @param err Errorcode
* @param errcode STUN Error code (if set)
* @param status Generic ALG status (-1=not detected, 1=detected)
* @param map Mapped network address
* @param arg Handler argument
*/
typedef void (nat_genalg_h)(int err, uint16_t scode, const char *reason,
int status, const struct sa *map, void *arg);
int nat_genalg_alloc(struct nat_genalg **ngp, const struct sa *srv, int proto,
const struct stun_conf *conf,
nat_genalg_h *gh, void *arg);
int nat_genalg_start(struct nat_genalg *ng);

135
include/re_net.h Normal file
View file

@ -0,0 +1,135 @@
/**
* @file re_net.h Interface to Networking module.
*
* Copyright (C) 2010 Creytiv.com
*/
#ifdef CYGWIN
#include <ws2tcpip.h>
#include <winsock2.h>
#elif defined(WIN32)
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <sys/types.h>
#ifndef _BSD_SOCKLEN_T_
#define _BSD_SOCKLEN_T_ int /**< Defines the BSD socket length type */
#endif
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
#ifndef HAVE_GAI_STRERROR
/** stub */
#ifndef gai_strerror
#define gai_strerror(err) "?"
#endif
#endif
/** Length of IPv4 address string */
#ifndef INET_ADDRSTRLEN
#define INET_ADDRSTRLEN 16
#endif
/** Length of IPv6 address string */
#ifndef INET6_ADDRSTRLEN
#define INET6_ADDRSTRLEN 46
#endif
/** Length of IPv4/v6 address string */
#ifdef HAVE_INET6
#define NET_ADDRSTRLEN INET6_ADDRSTRLEN
#else
#define NET_ADDRSTRLEN INET_ADDRSTRLEN
#endif
/* forward declarations */
struct sa;
/* Net generic */
int net_hostaddr(int af, struct sa *ip);
int net_default_source_addr_get(int af, struct sa *ip);
/* Net sockets */
int net_sock_init(void);
void net_sock_close(void);
/* Net socket options */
int net_sockopt_blocking_set(int fd, bool blocking);
int net_sockopt_reuse_set(int fd, bool reuse);
/* Net interface (if.c) */
/**
* Defines the interface address handled - called once per interface
*
* @param ifname Name of the interface
* @param sa IP address of the interface
* @param arg Handler argument
*
* @return true to stop traversing, false to continue
*/
typedef bool (net_ifaddr_h)(const char *ifname, const struct sa *sa,
void *arg);
int net_if_getname(char *ifname, size_t sz, int af, const struct sa *ip);
int net_if_getaddr(const char *ifname, int af, struct sa *ip);
int net_if_getaddr4(const char *ifname, int af, struct sa *ip);
int net_if_list(net_ifaddr_h *ifh, void *arg);
int net_if_apply(net_ifaddr_h *ifh, void *arg);
int net_if_debug(struct re_printf *pf, void *unused);
/* Net interface (ifaddrs.c) */
int net_getifaddrs(net_ifaddr_h *ifh, void *arg);
/* Net route */
/**
* Defines the routing table handler - called once per route entry
*
* @param ifname Interface name
* @param dst Destination IP address/network
* @param dstlen Prefix length of destination
* @param gw Gateway IP address
* @param arg Handler argument
*
* @return true to stop traversing, false to continue
*/
typedef bool (net_rt_h)(const char *ifname, const struct sa *dst,
int dstlen, const struct sa *gw, void *arg);
int net_rt_list(net_rt_h *rth, void *arg);
int net_rt_default_get(int af, char *ifname, size_t size);
int net_rt_debug(struct re_printf *pf, void *unused);
/* Network connection */
/**
* Defines the network connection handler
*
* @param err Error code
* @param id Associated ID
*/
typedef void (net_conn_h)(int err, uint32_t id);
int net_conn_start(net_conn_h *ch, uint32_t id, bool prompt);
void net_conn_stop(void);
/* Net strings */
const char *net_proto2name(int proto);
const char *net_af2name(int af);
/* todo: this does not really belong here.. */
#ifdef __SYMBIAN32__
int kerr2errno(int kerr);
#endif

231
include/re_rtp.h Normal file
View file

@ -0,0 +1,231 @@
/**
* @file re_rtp.h Interface to Real-time Transport Protocol
*
* Copyright (C) 2010 Creytiv.com
*/
enum {
RTP_VERSION = 2, /**< Defines the RTP version we support */
RTCP_VERSION = 2, /**< Supported RTCP Version */
RTP_HEADER_SIZE = 12 /**< Number of bytes in RTP Header */
};
/** Defines the RTP header */
struct rtp_header {
uint8_t ver; /**< RTP version number */
bool pad; /**< Padding bit */
bool ext; /**< Extension bit */
uint8_t cc; /**< CSRC count */
bool m; /**< Marker bit */
uint8_t pt; /**< Payload type */
uint16_t seq; /**< Sequence number */
uint32_t ts; /**< Timestamp */
uint32_t ssrc; /**< Synchronization source */
uint32_t csrc[16]; /**< Contributing sources */
struct {
uint16_t type; /**< Defined by profile */
uint16_t len; /**< Number of 32-bit words */
} x;
};
/** RTCP Packet Types */
enum rtcp_type {
RTCP_FIR = 192, /**< Full INTRA-frame Request (RFC 2032) */
RTCP_NACK = 193, /**< Negative Acknowledgement (RFC 2032) */
RTCP_SR = 200, /**< Sender Report */
RTCP_RR = 201, /**< Receiver Report */
RTCP_SDES = 202, /**< Source Description */
RTCP_BYE = 203, /**< Goodbye */
RTCP_APP = 204, /**< Application-defined */
RTCP_RTPFB = 205, /**< Transport layer FB message (RFC 4585) */
RTCP_PSFB = 206, /**< Payload-specific FB message (RFC 4585) */
RTCP_XR = 207, /**< Extended Report (RFC 3611) */
RTCP_AVB = 208, /**< AVB RTCP Packet (IEEE1733) */
};
/** SDES Types */
enum rtcp_sdes_type {
RTCP_SDES_END = 0, /**< End of SDES list */
RTCP_SDES_CNAME = 1, /**< Canonical name */
RTCP_SDES_NAME = 2, /**< User name */
RTCP_SDES_EMAIL = 3, /**< User's electronic mail address */
RTCP_SDES_PHONE = 4, /**< User's phone number */
RTCP_SDES_LOC = 5, /**< Geographic user location */
RTCP_SDES_TOOL = 6, /**< Name of application or tool */
RTCP_SDES_NOTE = 7, /**< Notice about the source */
RTCP_SDES_PRIV = 8 /**< Private extension */
};
/** Transport Layer Feedback Messages */
enum rtcp_rtpfb {
RTCP_RTPFB_GNACK = 1 /**< Generic NACK */
};
/** Payload-Specific Feedback Messages */
enum rtcp_psfb {
RTCP_PSFB_PLI = 1, /**< Picture Loss Indication (PLI) */
RTCP_PSFB_SLI = 2, /**< Slice Loss Indication (SLI) */
};
/** Reception report block */
struct rtcp_rr {
uint32_t ssrc; /**< Data source being reported */
unsigned int fraction:8; /**< Fraction lost since last SR/RR */
int lost:24; /**< Cumul. no. pkts lost (signed!) */
uint32_t last_seq; /**< Extended last seq. no. received */
uint32_t jitter; /**< Interarrival jitter */
uint32_t lsr; /**< Last SR packet from this source */
uint32_t dlsr; /**< Delay since last SR packet */
};
/** SDES item */
struct rtcp_sdes_item {
enum rtcp_sdes_type type; /**< Type of item (enum rtcp_sdes_type) */
uint8_t length; /**< Length of item (in octets) */
char *data; /**< Text, not null-terminated */
};
/** One RTCP Message */
struct rtcp_msg {
/** RTCP Header */
struct rtcp_hdr {
unsigned int version:2; /**< Protocol version */
unsigned int p:1; /**< Padding flag */
unsigned int count:5; /**< Varies by packet type */
unsigned int pt:8; /**< RTCP packet type */
uint16_t length; /**< Packet len in words */
} hdr;
union {
/** Sender report (SR) */
struct {
uint32_t ssrc; /**< Sender generating report */
uint32_t ntp_sec; /**< NTP timestamp - seconds */
uint32_t ntp_frac; /**< NTP timestamp - fractions */
uint32_t rtp_ts; /**< RTP timestamp */
uint32_t psent; /**< RTP packets sent */
uint32_t osent; /**< RTP octets sent */
struct rtcp_rr *rrv; /**< Reception report blocks */
} sr;
/** Reception report (RR) */
struct {
uint32_t ssrc; /**< Receiver generating report*/
struct rtcp_rr *rrv; /**< Reception report blocks */
} rr;
/** Source Description (SDES) */
struct rtcp_sdes {
uint32_t src; /**< First SSRC/CSRC */
struct rtcp_sdes_item *itemv; /**< SDES items */
uint32_t n; /**< Number of SDES items */
} *sdesv;
/** BYE */
struct {
uint32_t *srcv; /**< List of sources */
char *reason; /**< Reason for leaving (opt.) */
} bye;
/** Application-defined (APP) */
struct {
uint32_t src; /**< SSRC/CSRC */
char name[4]; /**< Name (ASCII) */
uint8_t *data; /**< Application data (32 bits) */
size_t data_len; /**< Number of data bytes */
} app;
/** Full INTRA-frame Request (FIR) packet */
struct {
uint32_t ssrc; /**< SSRC for sender of this packet */
} fir;
/** Negative ACKnowledgements (NACK) packet */
struct {
uint32_t ssrc; /**< SSRC for sender of this packet */
uint16_t fsn; /**< First Sequence Number lost */
uint16_t blp; /**< Bitmask of lost packets */
} nack;
/** Feedback (RTPFB or PSFB) packet */
struct {
uint32_t ssrc_packet;
uint32_t ssrc_media;
uint32_t n;
/** Feedback Control Information (FCI) */
union {
struct gnack {
uint16_t pid;
uint16_t blp;
} *gnackv;
struct sli {
uint16_t first;
uint16_t number;
uint8_t picid;
} *sliv;
void *p;
} fci;
} fb;
} r;
};
struct rtcp_stats {
struct {
uint32_t sent;
int lost;
uint32_t jit;
} tx;
struct {
uint32_t sent;
int lost;
uint32_t jit;
} rx;
};
struct sa;
struct re_printf;
struct rtp_sock;
typedef void (rtp_recv_h)(const struct sa *src, const struct rtp_header *hdr,
struct mbuf *mb, void *arg);
typedef void (rtcp_recv_h)(const struct sa *src, struct rtcp_msg *msg,
void *arg);
/* RTP api */
int rtp_alloc(struct rtp_sock **rsp);
int rtp_listen(struct rtp_sock **rsp, int proto, const struct sa *ip,
uint16_t min_port, uint16_t max_port, bool enable_rtcp,
rtp_recv_h *recvh, rtcp_recv_h *rtcph, void *arg);
int rtp_hdr_encode(struct mbuf *mb, const struct rtp_header *hdr);
int rtp_hdr_decode(struct rtp_header *hdr, struct mbuf *mb);
int rtp_encode(struct rtp_sock *rs, bool marker, uint8_t pt,
uint32_t ts, struct mbuf *mb);
int rtp_decode(struct rtp_sock *rs, struct mbuf *mb, struct rtp_header *hdr);
int rtp_send(struct rtp_sock *rs, const struct sa *dst,
bool marker, uint8_t pt, uint32_t ts, struct mbuf *mb);
int rtp_debug(struct re_printf *pf, const struct rtp_sock *rs);
void *rtp_sock(const struct rtp_sock *rs);
uint32_t rtp_sess_ssrc(const struct rtp_sock *rs);
const struct sa *rtp_local(const struct rtp_sock *rs);
/* RTCP session api */
void rtcp_start(struct rtp_sock *rs, const char *cname,
const struct sa *peer);
void rtcp_set_srate(struct rtp_sock *rs, uint32_t sr_tx, uint32_t sr_rx);
int rtcp_send_app(struct rtp_sock *rs, const char name[4],
const uint8_t *data, size_t len);
int rtcp_send_fir(struct rtp_sock *rs, uint32_t ssrc);
int rtcp_send_nack(struct rtp_sock *rs, uint16_t fsn, uint16_t blp);
int rtcp_send_pli(struct rtp_sock *rs, uint32_t fb_ssrc);
int rtcp_debug(struct re_printf *pf, const struct rtp_sock *rs);
void *rtcp_sock(const struct rtp_sock *rs);
int rtcp_stats(struct rtp_sock *rs, uint32_t ssrc, struct rtcp_stats *stats);
/* RTCP utils */
int rtcp_encode(struct mbuf *mb, enum rtcp_type type, uint32_t count, ...);
int rtcp_decode(struct rtcp_msg **msgp, struct mbuf *mb);
int rtcp_msg_print(struct re_printf *pf, const struct rtcp_msg *msg);
int rtcp_sdes_encode(struct mbuf *mb, uint32_t src, uint32_t itemc, ...);
const char *rtcp_type_name(enum rtcp_type type);
const char *rtcp_sdes_name(enum rtcp_sdes_type sdes);

55
include/re_sa.h Normal file
View file

@ -0,0 +1,55 @@
/**
* @file re_sa.h Interface to Socket Address
*
* Copyright (C) 2010 Creytiv.com
*/
#if defined(WIN32)
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#endif
struct pl;
enum sa_flag {
SA_ADDR = 1<<0,
SA_PORT = 1<<1,
SA_ALL = SA_ADDR | SA_PORT
};
struct sa {
union {
struct sockaddr sa;
struct sockaddr_in in;
#ifdef HAVE_INET6
struct sockaddr_in6 in6;
#endif
} u;
socklen_t len;
};
void sa_init(struct sa *sa, int af);
int sa_set(struct sa *sa, const struct pl *addr, uint16_t port);
int sa_set_str(struct sa *sa, const char *addr, uint16_t port);
void sa_set_in(struct sa *sa, uint32_t addr, uint16_t port);
void sa_set_in6(struct sa *sa, const uint8_t *addr, uint16_t port);
int sa_set_sa(struct sa *sa, const struct sockaddr *s);
void sa_set_port(struct sa *sa, uint16_t port);
int sa_decode(struct sa *sa, const char *str, size_t len);
int sa_af(const struct sa *sa);
uint32_t sa_in(const struct sa *sa);
void sa_in6(const struct sa *sa, uint8_t *addr);
int sa_ntop(const struct sa *sa, char *buf, int size);
uint16_t sa_port(const struct sa *sa);
bool sa_isset(const struct sa *sa, int flag);
uint32_t sa_hash(const struct sa *sa, int flag);
void sa_cpy(struct sa *dst, const struct sa *src);
bool sa_cmp(const struct sa *l, const struct sa *r, int flag);
bool sa_is_linklocal(const struct sa *sa);
bool sa_is_loopback(const struct sa *sa);
bool sa_is_any(const struct sa *sa);

153
include/re_sdp.h Normal file
View file

@ -0,0 +1,153 @@
/**
* @file re_sdp.h Interface to Session Description Protocol (SDP)
*
* Copyright (C) 2010 Creytiv.com
*/
enum {
SDP_VERSION = 0
};
enum sdp_dir {
SDP_INACTIVE = 0,
SDP_RECVONLY = 1,
SDP_SENDONLY = 2,
SDP_SENDRECV = 3,
};
/** SDP Bandwidth type */
enum sdp_bandwidth {
SDP_BANDWIDTH_MIN = 0,
SDP_BANDWIDTH_CT = 0, /**< [kbit/s] Conference Total */
SDP_BANDWIDTH_AS, /**< [kbit/s] Application Specific */
SDP_BANDWIDTH_RS, /**< [bit/s] RTCP Senders (RFC 3556) */
SDP_BANDWIDTH_RR, /**< [bit/s] RTCP Receivers (RFC 3556) */
SDP_BANDWIDTH_TIAS, /**< [bit/s] Transport Independent Application
Specific Maximum (RFC 3890) */
SDP_BANDWIDTH_MAX,
};
struct sdp_format;
typedef bool(sdp_fmtp_cmp_h)(const char *params1, const char *params2,
void *data);
typedef bool(sdp_format_h)(struct sdp_format *fmt, void *arg);
typedef bool(sdp_attr_h)(const char *name, const char *value, void *arg);
struct sdp_format {
struct le le;
char *id;
char *params;
char *name;
sdp_fmtp_cmp_h *cmph;
void *data;
bool ref;
bool sup;
int pt;
uint32_t srate;
uint8_t ch;
};
/* session */
struct sdp_session;
int sdp_session_alloc(struct sdp_session **sessp, const struct sa *laddr);
void sdp_session_set_laddr(struct sdp_session *sess, const struct sa *laddr);
void sdp_session_set_lbandwidth(struct sdp_session *sess,
enum sdp_bandwidth type, int32_t bw);
int sdp_session_set_lattr(struct sdp_session *sess, bool replace,
const char *name, const char *value, ...);
void sdp_session_del_lattr(struct sdp_session *sess, const char *name);
int32_t sdp_session_rbandwidth(const struct sdp_session *sess,
enum sdp_bandwidth type);
const char *sdp_session_rattr(const struct sdp_session *sess,
const char *name);
const char *sdp_session_rattr_apply(const struct sdp_session *sess,
const char *name,
sdp_attr_h *attrh, void *arg);
const struct list *sdp_session_medial(const struct sdp_session *sess,
bool local);
int sdp_session_debug(struct re_printf *pf, const struct sdp_session *sess);
/* media */
struct sdp_media;
int sdp_media_add(struct sdp_media **mp, struct sdp_session *sess,
const char *name, uint16_t port, const char *proto);
void sdp_media_set_disabled(struct sdp_media *m, bool disabled);
void sdp_media_set_lport(struct sdp_media *m, uint16_t port);
void sdp_media_set_laddr(struct sdp_media *m, const struct sa *laddr);
void sdp_media_set_lbandwidth(struct sdp_media *m, enum sdp_bandwidth type,
int32_t bw);
void sdp_media_set_lport_rtcp(struct sdp_media *m, uint16_t port);
void sdp_media_set_laddr_rtcp(struct sdp_media *m, const struct sa *laddr);
void sdp_media_set_ldir(struct sdp_media *m, enum sdp_dir dir);
int sdp_media_set_lattr(struct sdp_media *m, bool replace,
const char *name, const char *value, ...);
void sdp_media_del_lattr(struct sdp_media *m, const char *name);
uint16_t sdp_media_rport(const struct sdp_media *m);
const struct sa *sdp_media_raddr(const struct sdp_media *m);
void sdp_media_raddr_rtcp(const struct sdp_media *m, struct sa *raddr);
int32_t sdp_media_rbandwidth(const struct sdp_media *m,
enum sdp_bandwidth type);
enum sdp_dir sdp_media_ldir(const struct sdp_media *m);
enum sdp_dir sdp_media_rdir(const struct sdp_media *m);
enum sdp_dir sdp_media_dir(const struct sdp_media *m);
const struct sdp_format *sdp_media_lformat(const struct sdp_media *m, int pt);
const struct sdp_format *sdp_media_rformat(const struct sdp_media *m,
const char *name);
struct sdp_format *sdp_media_format(const struct sdp_media *m,
bool local, const char *id,
int pt, const char *name,
int32_t srate, int8_t ch);
struct sdp_format *sdp_media_format_apply(const struct sdp_media *m,
bool local, const char *id,
int pt, const char *name,
int32_t srate, int8_t ch,
sdp_format_h *fmth, void *arg);
const struct list *sdp_media_format_lst(const struct sdp_media *m, bool local);
const char *sdp_media_rattr(const struct sdp_media *m, const char *name);
const char *sdp_media_rattr_apply(const struct sdp_media *m, const char *name,
sdp_attr_h *attrh, void *arg);
const char *sdp_media_name(const struct sdp_media *m);
int sdp_media_debug(struct re_printf *pf, const struct sdp_media *m);
/* format */
int sdp_format_add(struct sdp_format **fmtp, struct sdp_media *m,
bool prepend, const char *id, const char *name,
uint32_t srate, uint8_t ch,
sdp_fmtp_cmp_h *cmph, void *data, bool ref,
const char *params, ...);
int sdp_format_set_params(struct sdp_format *fmt, const char *params, ...);
bool sdp_format_cmp(const struct sdp_format *fmt1,
const struct sdp_format *fmt2);
int sdp_format_debug(struct re_printf *pf, const struct sdp_format *fmt);
/* encode/decode */
int sdp_encode(struct mbuf **mbp, struct sdp_session *sess, bool offer);
int sdp_decode(struct sdp_session *sess, struct mbuf *mb, bool offer);
/* strings */
const char *sdp_dir_name(enum sdp_dir dir);
const char *sdp_bandwidth_name(enum sdp_bandwidth type);
extern const char sdp_attr_fmtp[];
extern const char sdp_attr_maxptime[];
extern const char sdp_attr_ptime[];
extern const char sdp_attr_rtcp[];
extern const char sdp_attr_rtpmap[];
extern const char sdp_media_audio[];
extern const char sdp_media_video[];
extern const char sdp_media_text[];
extern const char sdp_proto_rtpavp[];
extern const char sdp_proto_rtpsavp[];

34
include/re_sha.h Normal file
View file

@ -0,0 +1,34 @@
/**
* @file re_sha.h Interface to SHA (Secure Hash Standard) functions
*
* Copyright (C) 2010 Creytiv.com
*/
#ifdef USE_OPENSSL
#include <openssl/sha.h>
#else
/* public api for steve reid's public domain SHA-1 implementation */
/* this file is in the public domain */
/** SHA-1 Context */
typedef struct {
uint32_t state[5]; /**< Context state */
uint32_t count[2]; /**< Counter */
uint8_t buffer[64]; /**< SHA-1 buffer */
} SHA1_CTX;
/** SHA-1 Context (OpenSSL compat) */
typedef SHA1_CTX SHA_CTX;
/** SHA-1 Digest size in bytes */
#define SHA1_DIGEST_SIZE 20
/** SHA-1 Digest size in bytes (OpenSSL compat) */
#define SHA_DIGEST_LENGTH SHA1_DIGEST_SIZE
void SHA1_Init(SHA1_CTX* context);
void SHA1_Update(SHA1_CTX* context, const uint8_t* data, const size_t len);
void SHA1_Final(uint8_t digest[SHA1_DIGEST_SIZE], SHA1_CTX* context);
#endif

319
include/re_sip.h Normal file
View file

@ -0,0 +1,319 @@
/**
* @file re_sip.h Session Initiation Protocol
*
* Copyright (C) 2010 Creytiv.com
*/
enum {
SIP_PORT = 5060,
SIP_PORT_TLS = 5061,
};
enum sip_transp {
SIP_TRANSP_NONE = -1,
SIP_TRANSP_UDP = 0,
SIP_TRANSP_TCP,
SIP_TRANSP_TLS,
SIP_TRANSPC,
};
enum sip_hdrid {
SIP_HDR_ACCEPT = 3186,
SIP_HDR_ACCEPT_CONTACT = 232,
SIP_HDR_ACCEPT_ENCODING = 708,
SIP_HDR_ACCEPT_LANGUAGE = 2867,
SIP_HDR_ACCEPT_RESOURCE_PRIORITY = 1848,
SIP_HDR_ALERT_INFO = 274,
SIP_HDR_ALLOW = 2429,
SIP_HDR_ALLOW_EVENTS = 66,
SIP_HDR_ANSWER_MODE = 2905,
SIP_HDR_AUTHENTICATION_INFO = 3144,
SIP_HDR_AUTHORIZATION = 2503,
SIP_HDR_CALL_ID = 3095,
SIP_HDR_CALL_INFO = 586,
SIP_HDR_CONTACT = 229,
SIP_HDR_CONTENT_DISPOSITION = 1425,
SIP_HDR_CONTENT_ENCODING = 580,
SIP_HDR_CONTENT_LANGUAGE = 3371,
SIP_HDR_CONTENT_LENGTH = 3861,
SIP_HDR_CONTENT_TYPE = 809,
SIP_HDR_CSEQ = 746,
SIP_HDR_DATE = 1027,
SIP_HDR_ENCRYPTION = 3125,
SIP_HDR_ERROR_INFO = 21,
SIP_HDR_EVENT = 3286,
SIP_HDR_EXPIRES = 1983,
SIP_HDR_FROM = 1963,
SIP_HDR_HIDE = 283,
SIP_HDR_HISTORY_INFO = 2582,
SIP_HDR_IDENTITY = 2362,
SIP_HDR_IDENTITY_INFO = 980,
SIP_HDR_IN_REPLY_TO = 1577,
SIP_HDR_JOIN = 3479,
SIP_HDR_MAX_BREADTH = 3701,
SIP_HDR_MAX_FORWARDS = 3549,
SIP_HDR_MIME_VERSION = 3659,
SIP_HDR_MIN_EXPIRES = 1121,
SIP_HDR_MIN_SE = 2847,
SIP_HDR_ORGANIZATION = 3247,
SIP_HDR_P_ACCESS_NETWORK_INFO = 1662,
SIP_HDR_P_ANSWER_STATE = 42,
SIP_HDR_P_ASSERTED_IDENTITY = 1233,
SIP_HDR_P_ASSOCIATED_URI = 900,
SIP_HDR_P_CALLED_PARTY_ID = 3347,
SIP_HDR_P_CHARGING_FUNCTION_ADDRESSES = 2171,
SIP_HDR_P_CHARGING_VECTOR = 25,
SIP_HDR_P_DCS_TRACE_PARTY_ID = 3027,
SIP_HDR_P_DCS_OSPS = 1788,
SIP_HDR_P_DCS_BILLING_INFO = 2017,
SIP_HDR_P_DCS_LAES = 693,
SIP_HDR_P_DCS_REDIRECT = 1872,
SIP_HDR_P_EARLY_MEDIA = 2622,
SIP_HDR_P_MEDIA_AUTHORIZATION = 1035,
SIP_HDR_P_PREFERRED_IDENTITY = 1263,
SIP_HDR_P_PROFILE_KEY = 1904,
SIP_HDR_P_REFUSED_URI_LIST = 1047,
SIP_HDR_P_SERVED_USER = 1588,
SIP_HDR_P_USER_DATABASE = 2827,
SIP_HDR_P_VISITED_NETWORK_ID = 3867,
SIP_HDR_PATH = 2741,
SIP_HDR_PERMISSION_MISSING = 1409,
SIP_HDR_PRIORITY = 3520,
SIP_HDR_PRIV_ANSWER_MODE = 2476,
SIP_HDR_PRIVACY = 3150,
SIP_HDR_PROXY_AUTHENTICATE = 116,
SIP_HDR_PROXY_AUTHORIZATION = 2363,
SIP_HDR_PROXY_REQUIRE = 3562,
SIP_HDR_RACK = 2523,
SIP_HDR_REASON = 3732,
SIP_HDR_RECORD_ROUTE = 278,
SIP_HDR_REFER_SUB = 2458,
SIP_HDR_REFER_TO = 1521,
SIP_HDR_REFERRED_BY = 3456,
SIP_HDR_REJECT_CONTACT = 285,
SIP_HDR_REPLACES = 2534,
SIP_HDR_REPLY_TO = 2404,
SIP_HDR_REQUEST_DISPOSITION = 3715,
SIP_HDR_REQUIRE = 3905,
SIP_HDR_RESOURCE_PRIORITY = 1643,
SIP_HDR_RESPONSE_KEY = 1548,
SIP_HDR_RETRY_AFTER = 409,
SIP_HDR_ROUTE = 661,
SIP_HDR_RSEQ = 445,
SIP_HDR_SECURITY_CLIENT = 1358,
SIP_HDR_SECURITY_SERVER = 811,
SIP_HDR_SECURITY_VERIFY = 519,
SIP_HDR_SERVER = 973,
SIP_HDR_SERVICE_ROUTE = 1655,
SIP_HDR_SESSION_EXPIRES = 1979,
SIP_HDR_SIP_ETAG = 1997,
SIP_HDR_SIP_IF_MATCH = 3056,
SIP_HDR_SUBJECT = 1043,
SIP_HDR_SUBSCRIPTION_STATE = 2884,
SIP_HDR_SUPPORTED = 119,
SIP_HDR_TARGET_DIALOG = 3450,
SIP_HDR_TIMESTAMP = 938,
SIP_HDR_TO = 1449,
SIP_HDR_TRIGGER_CONSENT = 3180,
SIP_HDR_UNSUPPORTED = 982,
SIP_HDR_USER_AGENT = 4064,
SIP_HDR_VIA = 3961,
SIP_HDR_WARNING = 2108,
SIP_HDR_WWW_AUTHENTICATE = 2763,
SIP_HDR_NONE = -1
};
enum {
SIP_T1 = 500,
SIP_T2 = 4000,
SIP_T4 = 5000,
};
struct sip_via {
struct pl transp;
struct pl sentby;
struct sa addr;
struct pl params;
struct pl branch;
struct pl val;
};
struct sip_addr {
struct pl dname;
struct pl auri;
struct uri uri;
struct pl params;
};
struct sip_taddr {
struct pl dname;
struct pl auri;
struct uri uri;
struct pl params;
struct pl tag;
struct pl val;
};
struct sip_cseq {
struct pl met;
uint32_t num;
};
struct sip_hdr {
struct le le;
struct le he;
struct pl name;
struct pl val;
enum sip_hdrid id;
};
struct sip_msg {
struct sa src;
struct sa dst;
struct pl ver;
struct pl met;
struct pl ruri;
struct uri uri;
uint16_t scode;
struct pl reason;
struct list hdrl;
struct sip_via via;
struct sip_taddr to;
struct sip_taddr from;
struct sip_cseq cseq;
struct pl callid;
struct pl maxfwd;
struct pl expires;
struct pl ctype;
struct pl clen;
struct hash *hdrht;
struct mbuf *mb;
void *sock;
uint64_t tag;
enum sip_transp tp;
bool req;
};
struct sip_loopstate {
uint32_t failc;
uint16_t last_scode;
};
struct sip;
struct sip_lsnr;
struct sip_request;
struct sip_strans;
struct sip_auth;
struct sip_dialog;
struct dnsc;
typedef bool(sip_msg_h)(const struct sip_msg *msg, void *arg);
typedef int(sip_send_h)(enum sip_transp tp, const struct sa *src,
const struct sa *dst, struct mbuf *mb, void *arg);
typedef void(sip_resp_h)(int err, const struct sip_msg *msg, void *arg);
typedef void(sip_cancel_h)(void *arg);
typedef void(sip_exit_h)(void *arg);
typedef int(sip_auth_h)(char **username, char **password, const char *realm,
void *arg);
typedef bool(sip_hdr_h)(const struct sip_hdr *hdr, const struct sip_msg *msg,
void *arg);
/* sip */
int sip_alloc(struct sip **sipp, struct dnsc *dnsc, uint32_t ctsz,
uint32_t stsz, uint32_t tcsz, const char *software,
sip_exit_h *exith, void *arg);
int sip_transp_add(struct sip *sip, enum sip_transp tp,
const struct sa *laddr, ...);
void sip_transp_flush(struct sip *sip);
void sip_close(struct sip *sip, bool force);
int sip_listen(struct sip_lsnr **lsnrp, struct sip *sip, bool req,
sip_msg_h *msgh, void *arg);
int sip_debug(struct re_printf *pf, const struct sip *sip);
int sip_send(struct sip *sip, void *sock, enum sip_transp tp,
const struct sa *dst, struct mbuf *mb);
const char *sip_transp_name(enum sip_transp tp);
const char *sip_transp_param(enum sip_transp tp);
/* request */
int sip_request(struct sip_request **reqp, struct sip *sip, bool stateful,
const char *met, int metl, const char *uri, int uril,
const struct uri *route, struct mbuf *mb,
sip_send_h *sendh, sip_resp_h *resph, void *arg);
int sip_requestf(struct sip_request **reqp, struct sip *sip, bool stateful,
const char *met, const char *uri, const struct uri *route,
struct sip_auth *auth, sip_send_h *sendh, sip_resp_h *resph,
void *arg, const char *fmt, ...);
int sip_drequestf(struct sip_request **reqp, struct sip *sip, bool stateful,
const char *met, struct sip_dialog *dlg, uint32_t cseq,
struct sip_auth *auth, sip_send_h *sendh, sip_resp_h *resph,
void *arg, const char *fmt, ...);
void sip_request_cancel(struct sip_request *req);
bool sip_request_loops(struct sip_loopstate *ls, uint16_t scode);
void sip_loopstate_reset(struct sip_loopstate *ls);
/* reply */
int sip_strans_alloc(struct sip_strans **stp, struct sip *sip,
const struct sip_msg *msg, sip_cancel_h *cancelh,
void *arg);
int sip_strans_reply(struct sip_strans **stp, struct sip *sip,
const struct sip_msg *msg, const struct sa *dst,
uint16_t scode, struct mbuf *mb);
int sip_treplyf(struct sip_strans **stp, struct mbuf **mbp, struct sip *sip,
const struct sip_msg *msg, bool rec_route, uint16_t scode,
const char *reason, const char *fmt, ...);
int sip_treply(struct sip_strans **stp, struct sip *sip,
const struct sip_msg *msg, uint16_t scode, const char *reason);
int sip_replyf(struct sip *sip, const struct sip_msg *msg, uint16_t scode,
const char *reason, const char *fmt, ...);
int sip_reply(struct sip *sip, const struct sip_msg *msg, uint16_t scode,
const char *reason);
void sip_reply_addr(struct sa *addr, const struct sip_msg *msg, bool rport);
/* auth */
int sip_auth_authenticate(struct sip_auth *auth, const struct sip_msg *msg);
int sip_auth_alloc(struct sip_auth **authp, sip_auth_h *authh,
void *arg, bool ref);
/* dialog */
int sip_dialog_alloc(struct sip_dialog **dlgp,
const char *uri, const char *to_uri,
const char *from_name, const char *from_uri,
const char *routev[], uint32_t routec);
int sip_dialog_accept(struct sip_dialog **dlgp, const struct sip_msg *msg);
int sip_dialog_create(struct sip_dialog *dlg, const struct sip_msg *msg);
int sip_dialog_update(struct sip_dialog *dlg, const struct sip_msg *msg);
bool sip_dialog_rseq_valid(struct sip_dialog *dlg, const struct sip_msg *msg);
const char *sip_dialog_callid(const struct sip_dialog *dlg);
bool sip_dialog_cmp(const struct sip_dialog *dlg, const struct sip_msg *msg);
/* msg */
int sip_msg_decode(struct sip_msg **msgp, struct mbuf *mb);
const struct sip_hdr *sip_msg_hdr(const struct sip_msg *msg,
enum sip_hdrid id);
const struct sip_hdr *sip_msg_hdr_apply(const struct sip_msg *msg,
bool fwd, enum sip_hdrid id,
sip_hdr_h *h, void *arg);
const struct sip_hdr *sip_msg_xhdr(const struct sip_msg *msg,
const char *name);
const struct sip_hdr *sip_msg_xhdr_apply(const struct sip_msg *msg,
bool fwd, const char *name,
sip_hdr_h *h, void *arg);
struct tcp_conn *sip_msg_tcpconn(const struct sip_msg *msg);
void sip_msg_dump(const struct sip_msg *msg);
int sip_addr_decode(struct sip_addr *addr, const struct pl *pl);
int sip_via_decode(struct sip_via *via, const struct pl *pl);
int sip_cseq_decode(struct sip_cseq *cseq, const struct pl *pl);
int sip_param_decode(const struct pl *pl, const char *name, struct pl *val);
int sip_param_exists(const struct pl *pl, const char *name, struct pl *end);

15
include/re_sipreg.h Normal file
View file

@ -0,0 +1,15 @@
/**
* @file re_sipreg.h SIP Registration
*
* Copyright (C) 2010 Creytiv.com
*/
struct sipreg;
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 *cuser, const char *routev[], uint32_t routec,
sip_auth_h *authh, void *aarg, bool ref,
sip_resp_h *resph, void *arg,
const char *params, const char *fmt, ...);

59
include/re_sipsess.h Normal file
View file

@ -0,0 +1,59 @@
/**
* @file re_sipsess.h SIP Session
*
* Copyright (C) 2010 Creytiv.com
*/
struct sipsess_sock;
struct sipsess;
typedef void (sipsess_conn_h)(const struct sip_msg *msg, void *arg);
typedef int (sipsess_offer_h)(struct mbuf **descp, const struct sip_msg *msg,
void *arg);
typedef int (sipsess_answer_h)(const struct sip_msg *msg, void *arg);
typedef void (sipsess_progr_h)(const struct sip_msg *msg, void *arg);
typedef void (sipsess_estab_h)(const struct sip_msg *msg, void *arg);
typedef void (sipsess_info_h)(struct sip *sip, const struct sip_msg *msg,
void *arg);
typedef void (sipsess_refer_h)(struct sip *sip, const struct sip_msg *msg,
void *arg);
typedef void (sipsess_close_h)(int err, const struct sip_msg *msg, void *arg);
int sipsess_listen(struct sipsess_sock **sockp, struct sip *sip,
int htsize, sipsess_conn_h *connh, void *arg);
int sipsess_connect(struct sipsess **sessp, struct sipsess_sock *sock,
const char *to_uri, const char *from_name,
const char *from_uri, const char *cuser,
const char *routev[], uint32_t routec,
const char *ctype, struct mbuf *desc,
sip_auth_h *authh, void *aarg, bool aref,
sipsess_offer_h *offerh, sipsess_answer_h *answerh,
sipsess_progr_h *progrh, sipsess_estab_h *estabh,
sipsess_info_h *infoh, sipsess_refer_h *referh,
sipsess_close_h *closeh, void *arg, const char *fmt, ...);
int sipsess_accept(struct sipsess **sessp, struct sipsess_sock *sock,
const struct sip_msg *msg, uint16_t scode,
const char *reason, const char *cuser, const char *ctype,
struct mbuf *desc,
sip_auth_h *authh, void *aarg, bool aref,
sipsess_offer_h *offerh, sipsess_answer_h *answerh,
sipsess_estab_h *estabh, sipsess_info_h *infoh,
sipsess_refer_h *referh, sipsess_close_h *closeh,
void *arg, const char *fmt, ...);
int sipsess_progress(struct sipsess *sess, uint16_t scode,
const char *reason, struct mbuf *desc,
const char *fmt, ...);
int sipsess_answer(struct sipsess *sess, uint16_t scode, const char *reason,
struct mbuf *desc, const char *fmt, ...);
int sipsess_reject(struct sipsess *sess, uint16_t scode, const char *reason,
const char *fmt, ...);
int sipsess_modify(struct sipsess *sess, struct mbuf *desc);
int sipsess_info(struct sipsess *sess, const char *ctype, struct mbuf *body,
sip_resp_h *resph, void *arg);
void sipsess_close_all(struct sipsess_sock *sock);
struct sip_dialog *sipsess_dialog(struct sipsess *sess);

278
include/re_stun.h Normal file
View file

@ -0,0 +1,278 @@
/**
* @file re_stun.h Session Traversal Utilities for (NAT) (STUN)
*
* Copyright (C) 2010 Creytiv.com
*/
enum {
STUN_PORT = 3478, /**< STUN Port number */
STUN_HEADER_SIZE = 20, /**< Number of bytes in header */
STUN_ATTR_HEADER_SIZE = 4, /**< Size of attribute header */
STUN_TID_SIZE = 12, /**< Number of bytes in transaction ID */
STUN_DEFAULT_RTO = 500, /**< Default Retrans Timeout in [ms] */
STUN_DEFAULT_RC = 7, /**< Default number of retransmits */
STUN_DEFAULT_RM = 16, /**< Wait time after last request is sent */
STUN_DEFAULT_TI = 39500 /**< Reliable timeout */
};
/** STUN Address Family */
enum stun_af {
STUN_AF_IPv4 = 0x01, /**< IPv4 Address Family */
STUN_AF_IPv6 = 0x02 /**< IPv6 Address Family */
};
/** STUN Methods */
enum stun_method {
STUN_METHOD_BINDING = 0x001,
STUN_METHOD_ALLOCATE = 0x003,
STUN_METHOD_REFRESH = 0x004,
STUN_METHOD_SEND = 0x006,
STUN_METHOD_DATA = 0x007,
STUN_METHOD_CREATEPERM = 0x008,
STUN_METHOD_CHANBIND = 0x009,
};
/** STUN Message class */
enum stun_msg_class {
STUN_CLASS_REQUEST = 0x0, /**< STUN Request */
STUN_CLASS_INDICATION = 0x1, /**< STUN Indication */
STUN_CLASS_SUCCESS_RESP = 0x2, /**< STUN Success Response */
STUN_CLASS_ERROR_RESP = 0x3 /**< STUN Error Response */
};
/** STUN Attributes */
enum stun_attrib {
/* Comprehension-required range (0x0000-0x7FFF) */
STUN_ATTR_MAPPED_ADDR = 0x0001,
STUN_ATTR_CHANGE_REQ = 0x0003,
STUN_ATTR_USERNAME = 0x0006,
STUN_ATTR_MSG_INTEGRITY = 0x0008,
STUN_ATTR_ERR_CODE = 0x0009,
STUN_ATTR_UNKNOWN_ATTR = 0x000a,
STUN_ATTR_CHANNEL_NUMBER = 0x000c,
STUN_ATTR_LIFETIME = 0x000d,
STUN_ATTR_XOR_PEER_ADDR = 0x0012,
STUN_ATTR_DATA = 0x0013,
STUN_ATTR_REALM = 0x0014,
STUN_ATTR_NONCE = 0x0015,
STUN_ATTR_XOR_RELAY_ADDR = 0x0016,
STUN_ATTR_REQ_ADDR_FAMILY = 0x0017,
STUN_ATTR_EVEN_PORT = 0x0018,
STUN_ATTR_REQ_TRANSPORT = 0x0019,
STUN_ATTR_DONT_FRAGMENT = 0x001a,
STUN_ATTR_XOR_MAPPED_ADDR = 0x0020,
STUN_ATTR_RSV_TOKEN = 0x0022,
STUN_ATTR_PRIORITY = 0x0024,
STUN_ATTR_USE_CAND = 0x0025,
STUN_ATTR_PADDING = 0x0026,
STUN_ATTR_RESP_PORT = 0x0027,
/* Comprehension-optional range (0x8000-0xFFFF) */
STUN_ATTR_SOFTWARE = 0x8022,
STUN_ATTR_ALT_SERVER = 0x8023,
STUN_ATTR_FINGERPRINT = 0x8028,
STUN_ATTR_CONTROLLED = 0x8029,
STUN_ATTR_CONTROLLING = 0x802a,
STUN_ATTR_RESP_ORIGIN = 0x802b,
STUN_ATTR_OTHER_ADDR = 0x802c,
};
struct stun_change_req {
bool ip;
bool port;
};
struct stun_errcode {
uint16_t code;
char *reason;
};
struct stun_unknown_attr {
uint16_t typev[8];
uint32_t typec;
};
struct stun_even_port {
bool r;
};
struct stun_attr {
struct le le;
uint16_t type;
union {
/* generic types */
struct sa sa;
char *str;
uint64_t uint64;
uint32_t uint32;
uint16_t uint16;
uint8_t uint8;
struct mbuf mb;
/* actual attributes */
struct sa mapped_addr;
struct stun_change_req change_req;
char *username;
uint8_t msg_integrity[20];
struct stun_errcode err_code;
struct stun_unknown_attr unknown_attr;
uint16_t channel_number;
uint32_t lifetime;
struct sa xor_peer_addr;
struct mbuf data;
char *realm;
char *nonce;
struct sa xor_relay_addr;
uint8_t req_addr_family;
struct stun_even_port even_port;
uint8_t req_transport;
struct sa xor_mapped_addr;
uint64_t rsv_token;
uint32_t priority;
struct mbuf padding;
uint16_t resp_port;
char *software;
struct sa alt_server;
uint32_t fingerprint;
uint64_t controlled;
uint64_t controlling;
struct sa resp_origin;
struct sa other_addr;
} v;
};
struct stun_conf {
uint32_t rto;
uint32_t rc;
uint32_t rm;
uint32_t ti;
uint8_t tos; /**< Type-of-service field */
};
extern const char *stun_software;
struct stun;
struct stun_msg;
struct stun_ctrans;
typedef void(stun_resp_h)(int err, uint16_t scode, const char *reason,
const struct stun_msg *msg, void *arg);
typedef void(stun_ind_h)(struct stun_msg *msg, void *arg);
typedef bool(stun_attr_h)(const struct stun_attr *attr, void *arg);
int stun_alloc(struct stun **stunp, const struct stun_conf *conf,
stun_ind_h *indh, void *arg);
struct stun_conf *stun_conf(struct stun *stun);
int stun_send(int proto, void *sock, const struct sa *dst, struct mbuf *mb);
int stun_recv(struct stun *stun, struct mbuf *mb);
int stun_ctrans_recv(struct stun *stun, const struct stun_msg *msg,
const struct stun_unknown_attr *ua);
struct re_printf;
int stun_debug(struct re_printf *pf, const struct stun *stun);
int stun_request(struct stun_ctrans **ctp, struct stun *stun, int proto,
void *sock, const struct sa *dst, size_t presz,
uint16_t method, const uint8_t *key, size_t keylen, bool fp,
stun_resp_h *resph, void *arg, uint32_t attrc, ...);
int stun_reply(int proto, void *sock, const struct sa *dst, size_t presz,
const struct stun_msg *req, const uint8_t *key,
size_t keylen, bool fp, uint32_t attrc, ...);
int stun_ereply(int proto, void *sock, const struct sa *dst, size_t presz,
const struct stun_msg *req, uint16_t scode,
const char *reason, const uint8_t *key, size_t keylen,
bool fp, uint32_t attrc, ...);
int stun_indication(int proto, void *sock, const struct sa *dst, size_t presz,
uint16_t method, const uint8_t *key, size_t keylen,
bool fp, uint32_t attrc, ...);
int stun_msg_encode(struct mbuf *mb, uint16_t method, uint8_t cls,
const uint8_t *tid, const struct stun_errcode *ec,
const uint8_t *key, size_t keylen, bool fp,
uint8_t padding, uint32_t attrc, ...);
int stun_msg_decode(struct stun_msg **msgpp, struct mbuf *mb,
struct stun_unknown_attr *ua);
uint16_t stun_msg_type(const struct stun_msg *msg);
uint16_t stun_msg_class(const struct stun_msg *msg);
uint16_t stun_msg_method(const struct stun_msg *msg);
bool stun_msg_mcookie(const struct stun_msg *msg);
const uint8_t *stun_msg_tid(const struct stun_msg *msg);
struct stun_attr *stun_msg_attr(const struct stun_msg *msg, uint16_t type);
struct stun_attr *stun_msg_attr_apply(const struct stun_msg *msg,
stun_attr_h *h, void *arg);
int stun_msg_chk_mi(const struct stun_msg *msg, const uint8_t *key,
size_t keylen);
int stun_msg_chk_fingerprint(const struct stun_msg *msg);
void stun_msg_dump(const struct stun_msg *msg);
const char *stun_class_name(uint16_t cls);
const char *stun_method_name(uint16_t method);
const char *stun_attr_name(uint16_t type);
/* DNS Discovery of a STUN Server */
extern const char *stun_proto_udp;
extern const char *stun_proto_tcp;
extern const char *stun_usage_binding;
extern const char *stuns_usage_binding;
extern const char *stun_usage_relay;
extern const char *stuns_usage_relay;
extern const char *stun_usage_behavior;
extern const char *stuns_usage_behavior;
/**
* Defines the STUN Server Discovery handler
*
* @param err Errorcode
* @param srv IP Address and port of STUN Server
* @param arg Handler argument
*/
typedef void (stun_dns_h)(int err, const struct sa *srv, void *arg);
struct stun_dns;
struct dnsc;
int stun_server_discover(struct stun_dns **dnsp, struct dnsc *dnsc,
const char *service, const char *proto,
int af, const char *domain, uint16_t port,
stun_dns_h *dnsh, void *arg);
/* NAT Keepalives */
struct stun_keepalive;
/**
* Defines the STUN Keepalive Mapped-Address handler
*
* @param err Errorcode
* @param map Mapped Address
* @param arg Handler argument
*/
typedef void (stun_mapped_addr_h)(int err, const struct sa *map, void *arg);
int stun_keepalive_alloc(struct stun_keepalive **skap,
int proto, void *sock, int layer,
const struct sa *dst, const struct stun_conf *conf,
stun_mapped_addr_h *mah, void *arg);
void stun_keepalive_enable(struct stun_keepalive *ska, uint32_t interval);
/* STUN Reason Phrase */
extern const char *stun_reason_300;
extern const char *stun_reason_400;
extern const char *stun_reason_401;
extern const char *stun_reason_403;
extern const char *stun_reason_420;
extern const char *stun_reason_437;
extern const char *stun_reason_438;
extern const char *stun_reason_440;
extern const char *stun_reason_441;
extern const char *stun_reason_442;
extern const char *stun_reason_443;
extern const char *stun_reason_486;
extern const char *stun_reason_500;
extern const char *stun_reason_508;

75
include/re_sys.h Normal file
View file

@ -0,0 +1,75 @@
/**
* @file re_sys.h Interface to system module
*
* Copyright (C) 2010 Creytiv.com
*/
#ifndef VERSION
#define VERSION "?"
#endif
/**
* @def ARCH
*
* Architecture
*/
#ifndef ARCH
#ifdef __SYMBIAN32__
#if defined(__WINS__)
#define ARCH "WINS"
#elif defined(__MARM__)
#define ARCH "ARM"
#elif defined(__MARM_ARMI__)
#define ARCH "ARMI"
#elif defined(EKA2)
#define ARCH "EKA2"
#else
#define ARCH "Symbian Arch"
#endif
#else
#define ARCH "?"
#endif
#endif
/**
* @def OS
*
* Operating System
*/
#ifndef OS
#ifdef __SYMBIAN32__
#define OS "Symbian"
#elif defined (WIN32)
#define OS "win32"
#else
#define OS "?"
#endif
#endif
struct re_printf;
int sys_rel_get(uint32_t *rel, uint32_t *maj, uint32_t *min,
uint32_t *patch);
int sys_kernel_get(struct re_printf *pf, void *unused);
int sys_build_get(struct re_printf *pf, void *unused);
const char *sys_arch_get(void);
const char *sys_os_get(void);
const char *sys_libre_version_get(void);
int sys_coredump_set(bool enable);
int sys_daemon(void);
uint16_t sys_ltohs(uint16_t v);
uint32_t sys_ltohl(uint32_t v);
uint64_t sys_htonll(uint64_t v);
uint64_t sys_ntohll(uint64_t v);
/* Random */
void rand_init(void);
uint16_t rand_u16(void);
uint32_t rand_u32(void);
uint64_t rand_u64(void);
char rand_char(void);
void rand_str(char *str, size_t size);
void rand_bytes(uint8_t *p, size_t size);

101
include/re_tcp.h Normal file
View file

@ -0,0 +1,101 @@
/**
* @file re_tcp.h Interface to Transport Control Protocol
*
* Copyright (C) 2010 Creytiv.com
*/
struct sa;
struct tcp_sock;
struct tcp_conn;
/**
* Defines the incoming TCP connection handler
*
* @param peer Network address of peer
* @param arg Handler argument
*/
typedef void (tcp_conn_h)(const struct sa *peer, void *arg);
/**
* Defines the TCP connection established handler
*
* @param arg Handler argument
*/
typedef void (tcp_estab_h)(void *arg);
/**
* Defines the TCP connection data send handler
*
* @param arg Handler argument
*/
typedef void (tcp_send_h)(void *arg);
/**
* Defines the TCP connection data receive handler
*
* @param mb Buffer with data
* @param arg Handler argument
*/
typedef void (tcp_recv_h)(struct mbuf *mb, void *arg);
/**
* Defines the TCP connection close handler
*
* @param err Error code
* @param arg Handler argument
*/
typedef void (tcp_close_h)(int err, void *arg);
/* TCP Socket */
int tcp_sock_alloc(struct tcp_sock **tsp, const struct sa *local,
tcp_conn_h *ch, void *arg);
int tcp_sock_bind(struct tcp_sock *ts, const struct sa *local);
int tcp_sock_listen(struct tcp_sock *ts, int backlog);
int tcp_accept(struct tcp_conn **tcp, struct tcp_sock *ts, tcp_estab_h *eh,
tcp_recv_h *rh, tcp_close_h *ch, void *arg);
void tcp_reject(struct tcp_sock *ts);
int tcp_sock_local_get(const struct tcp_sock *ts, struct sa *local);
/* TCP Connection */
int tcp_conn_alloc(struct tcp_conn **tcp, const struct sa *peer,
tcp_estab_h *eh, tcp_recv_h *rh, tcp_close_h *ch,
void *arg);
int tcp_conn_bind(struct tcp_conn *tc, const struct sa *local);
int tcp_conn_connect(struct tcp_conn *tc, const struct sa *peer);
int tcp_send(struct tcp_conn *tc, struct mbuf *mb);
int tcp_set_send(struct tcp_conn *tc, tcp_send_h *sendh);
void tcp_conn_rxsz_set(struct tcp_conn *tc, size_t rxsz);
int tcp_conn_local_get(const struct tcp_conn *tc, struct sa *local);
int tcp_conn_peer_get(const struct tcp_conn *tc, struct sa *peer);
int tcp_conn_fd(const struct tcp_conn *tc);
/* High-level API */
int tcp_listen(struct tcp_sock **tsp, const struct sa *local,
tcp_conn_h *ch, void *arg);
int tcp_connect(struct tcp_conn **tcp, const struct sa *peer,
tcp_estab_h *eh, tcp_recv_h *rh, tcp_close_h *ch, void *arg);
int tcp_local_get(const struct tcp_sock *ts, struct sa *local);
#ifdef __SYMBIAN32__
struct RSocketServ;
struct RConnection;
void tcp_rconn_set(struct RSocketServ *sockSrv, struct RConnection *rconn);
#endif
/* Helper API */
typedef bool (tcp_helper_estab_h)(int *err, bool active, void *arg);
typedef bool (tcp_helper_send_h)(int *err, struct mbuf *mb, void *arg);
typedef bool (tcp_helper_recv_h)(int *err, struct mbuf *mb, bool *estab,
void *arg);
struct tcp_helper;
int tcp_register_helper(struct tcp_helper **thp, struct tcp_conn *tc, int *fd,
tcp_helper_estab_h *eh, tcp_helper_send_h *sh,
tcp_helper_recv_h *rh, void *arg);

22
include/re_telev.h Normal file
View file

@ -0,0 +1,22 @@
/**
* @file re_telev.h Interface to Telephony Events (RFC 4733)
*
* Copyright (C) 2010 Creytiv.com
*/
enum {
TELEV_PTIME = 50,
TELEV_SRATE = 8000
};
struct telev;
extern const char telev_rtpfmt[];
int telev_alloc(struct telev **tp, uint32_t ptime);
int telev_send(struct telev *tel, int event, bool end);
int telev_recv(struct telev *tel, struct mbuf *mb, int *event, bool *end);
int telev_poll(struct telev *tel, bool *marker, struct mbuf *mb);
int telev_digit2code(int digit);
int telev_code2digit(int code);

17
include/re_tls.h Normal file
View file

@ -0,0 +1,17 @@
/**
* @file re_tls.h Interface to Transport Layer Security
*
* Copyright (C) 2010 Creytiv.com
*/
struct tls;
struct tls_conn;
int tls_alloc(struct tls **tlsp, const char *keyfile, const char *pwd);
int tls_add_ca(struct tls *tls, const char *capath);
int tls_verify_cert(struct tls_conn *tc, char *cn, size_t cn_size);
int tls_start_tcp(struct tls_conn **ptc, struct tls *tls,
struct tcp_conn *tcp);

33
include/re_tmr.h Normal file
View file

@ -0,0 +1,33 @@
/**
* @file re_tmr.h Interface to timer implementation
*
* Copyright (C) 2010 Creytiv.com
*/
/**
* Defines the timeout handler
*
* @param arg Handler argument
*/
typedef void (tmr_h)(void *arg);
/** Defines a timer */
struct tmr {
struct le le; /**< Linked list element */
struct list *tmrl; /**< Parent list */
tmr_h *th; /**< Timeout handler */
void *arg; /**< Handler argument */
uint64_t jfs; /**< Jiffies for timeout */
};
void tmr_poll(struct list *tmrl);
uint64_t tmr_jiffies(void);
uint64_t tmr_next_timeout(struct list *tmrl);
void tmr_debug(void);
void tmr_init(struct tmr *tmr);
void tmr_start(struct tmr *tmr, uint64_t delay, tmr_h *th, void *arg);
void tmr_cancel(struct tmr *tmr);
uint64_t tmr_get_expire(const struct tmr *tmr);

28
include/re_turn.h Normal file
View file

@ -0,0 +1,28 @@
/**
* @file re_turn.h Interface to TURN implementation
*
* Copyright (C) 2010 Creytiv.com
*/
enum {
TURN_DEFAULT_LIFETIME = 600, /**< Default lifetime is 10 minutes */
TURN_MAX_LIFETIME = 3600 /**< Maximum lifetime is 1 hour */
};
typedef void(turnc_h)(int err, uint16_t scode, const char *reason,
const struct sa *relay_addr,
const struct sa *mapped_addr,
void *arg);
typedef void(turnc_perm_h)(void *arg);
typedef void(turnc_chan_h)(void *arg);
struct turnc;
int turnc_alloc(struct turnc **turncp, const struct stun_conf *conf, int proto,
void *sock, int layer, const struct sa *srv,
const char *username, const char *password,
uint32_t lifetime, turnc_h *th, void *arg);
int turnc_add_perm(struct turnc *turnc, const struct sa *peer,
turnc_perm_h *ph, void *arg);
int turnc_add_chan(struct turnc *turnc, const struct sa *peer,
turnc_chan_h *ch, void *arg);

234
include/re_types.h Normal file
View file

@ -0,0 +1,234 @@
/**
* @file re_types.h Defines basic types
*
* Copyright (C) 2010 Creytiv.com
*/
#include <sys/types.h>
#ifdef _MSC_VER
#include <stdlib.h>
#endif
/*
* Basic integral types from C99
*/
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#else
#ifndef __int8_t_defined
#define __int8_t_defined
/* Hack for OpenBSD */
#ifndef __BIT_TYPES_DEFINED__
#if defined(_CHAR_IS_SIGNED)
typedef char int8_t;
#elif defined(__STDC__)
typedef signed char int8_t;
#else
typedef char int8_t;
#endif
typedef signed short int int16_t;
typedef signed int int32_t;
typedef signed long long int int64_t;
#ifndef __uint32_t_defined
#define __uint32_t_defined
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long int uint64_t;
#endif
#endif /* __BIT_TYPES_DEFINED__ */
#endif /* __int8_t_defined */
#ifndef __ssize_t_defined
typedef long ssize_t;
#define __ssize_t_defined
#endif
#ifndef WIN32
typedef uint32_t socklen_t;
#endif
#endif
/*
* Hack for Solaris which does not define int64_t/uint64_t for strict ANSI C
*/
#ifdef SOLARIS
#if !(__STDC__ - 0 == 0 && !defined(_NO_LONGLONG))
typedef signed long long int int64_t;
typedef unsigned long long int uint64_t;
#endif
#endif
/*
* Boolean type
* see http://www.opengroup.org/onlinepubs/000095399/basedefs/stdbool.h.html
* www.gnu.org/software/autoconf/manual/html_node/Particular-Headers.html
*/
#ifdef HAVE_STDBOOL_H
# include <stdbool.h>
#else
# ifndef HAVE__BOOL
# ifdef __cplusplus
typedef bool _Bool;
# else
# define _Bool signed char
# endif
# endif
# define bool _Bool
# define false 0
# define true 1
# define __bool_true_false_are_defined 1
#endif
/* Needed for MS compiler */
#ifdef _MSC_VER
#define inline _inline
#endif
/*
* Misc macros
*/
/** Defines the NULL pointer */
#ifndef NULL
#define NULL ((void *)0)
#endif
/** Get number of elements in an array */
#undef ARRAY_SIZE
#define ARRAY_SIZE(a) ((sizeof(a))/(sizeof((a)[0])))
/** Align a value to the boundary of mask */
#define ALIGN_MASK(x, mask) (((x)+(mask))&~(mask))
/** Get the minimal value */
#undef MIN
#define MIN(a,b) (((a)<(b)) ? (a) : (b))
/** Get the maximal value */
#undef MAX
#define MAX(a,b) (((a)>(b)) ? (a) : (b))
/** Get the minimal value */
#undef min
#define min(x,y) MIN(x, y)
/** Get the maximal value */
#undef max
#define max(x,y) MAX(x, y)
/** Defines a soft breakpoint */
#if (defined(__i386__) || defined(__x86_64__)) && !defined(__SYMBIAN32__)
#define BREAKPOINT __asm__("int $0x03")
#else
#define BREAKPOINT
#endif
/* Error codes */
#include <errno.h>
/* Duplication of error codes. Values are from linux asm-generic/errno.h */
/** No data available */
#ifndef ENODATA
#define ENODATA 61
#endif
/** Protocol error */
#ifndef EPROTO
#define EPROTO 71
#endif
/** Not a data message */
#ifndef EBADMSG
#define EBADMSG 74
#endif
/** Value too large for defined data type */
#ifndef EOVERFLOW
#define EOVERFLOW 75
#endif
/** Accessing a corrupted shared library */
#ifndef ELIBBAD
#define ELIBBAD 80
#endif
/** Destination address required */
#ifndef EDESTADDRREQ
#define EDESTADDRREQ 89
#endif
/** Protocol not supported */
#ifndef EPROTONOSUPPORT
#define EPROTONOSUPPORT 93
#endif
/** Operation not supported on transport endpoint */
#ifndef ENOTSUP
#define ENOTSUP 95
#endif
/** Address family not supported by protocol */
#ifndef EAFNOSUPPORT
#define EAFNOSUPPORT 97
#endif
/** Cannot assign requested address */
#ifndef EADDRNOTAVAIL
#define EADDRNOTAVAIL 99
#endif
/** Software caused connection abort */
#ifndef ECONNABORTED
#define ECONNABORTED 103
#endif
/** Connection reset by peer */
#ifndef ECONNRESET
#define ECONNRESET 104
#endif
/** Transport endpoint is not connected */
#ifndef ENOTCONN
#define ENOTCONN 107
#endif
/** Connection timed out */
#ifndef ETIMEDOUT
#define ETIMEDOUT 110
#endif
/** Connection refused */
#ifndef ECONNREFUSED
#define ECONNREFUSED 111
#endif
/** Operation already in progress */
#ifndef EALREADY
#define EALREADY 114
#endif
/** Operation now in progress */
#ifndef EINPROGRESS
#define EINPROGRESS 115
#endif
/** Authentication error */
#ifndef EAUTH
#define EAUTH 116
#endif

58
include/re_udp.h Normal file
View file

@ -0,0 +1,58 @@
/**
* @file re_udp.h Interface to User Datagram Protocol
*
* Copyright (C) 2010 Creytiv.com
*/
struct sa;
struct udp_sock;
/**
* Defines the UDP Receive handler
*
* @param src Source address
* @param mb Datagram buffer
* @param arg Handler argument
*/
typedef void (udp_recv_h)(const struct sa *src, struct mbuf *mb, void *arg);
int udp_listen(struct udp_sock **usp, const struct sa *local,
udp_recv_h *rh, void *arg);
void udp_connect(struct udp_sock *us, bool conn);
int udp_send(struct udp_sock *us, const struct sa *dst, struct mbuf *mb);
int udp_send_anon(const struct sa *dst, struct mbuf *mb);
int udp_local_get(const struct udp_sock *us, struct sa *local);
int udp_setsockopt(struct udp_sock *us, int level, int optname,
const void *optval, uint32_t optlen);
int udp_sockbuf_set(struct udp_sock *us, int size);
void udp_rxsz_set(struct udp_sock *us, size_t rxsz);
void udp_rxbuf_presz_set(struct udp_sock *us, size_t rx_presz);
void udp_handler_set(struct udp_sock *us, udp_recv_h *rh, void *arg);
int udp_thread_attach(struct udp_sock *us);
void udp_thread_detach(struct udp_sock *us);
int udp_sock_fd(const struct udp_sock *us, int af);
/* Helper API */
typedef bool (udp_helper_send_h)(int *err, struct sa *dst,
struct mbuf *mb, void *arg);
typedef bool (udp_helper_recv_h)(struct sa *src,
struct mbuf *mb, void *arg);
struct udp_helper;
int udp_register_helper(struct udp_helper **uhp, struct udp_sock *us,
int *fd, int layer,
udp_helper_send_h *sh, udp_helper_recv_h *rh,
void *arg);
#ifdef __SYMBIAN32__
struct RConnection;
struct RSocketServ;
void udp_rconn_set(struct RSocketServ *sockSrv, struct RConnection *rconn);
#endif

43
include/re_uri.h Normal file
View file

@ -0,0 +1,43 @@
/**
* @file re_uri.h Interface to URI module
*
* Copyright (C) 2010 Creytiv.com
*/
/** Defines a URI - Uniform Resource Identifier */
struct uri {
struct pl scheme; /**< URI scheme e.g. "sip:" "sips:" */
struct pl user; /**< Username */
struct pl password; /**< Optional password */
struct pl host; /**< Hostname or IP-address */
int af; /**< Address family of host IP-address */
uint16_t port; /**< Port number */
struct pl params; /**< Optional URI-parameters */
struct pl headers; /**< Optional URI-headers */
};
typedef int (uri_apply_h)(const struct pl *name, const struct pl *val,
void *arg);
struct re_printf;
int uri_encode(struct re_printf *pf, const struct uri *uri);
int uri_decode(struct uri *uri, const struct pl *pl);
int uri_param_get(const struct pl *pl, const struct pl *pname,
struct pl *pvalue);
int uri_params_apply(const struct pl *pl, uri_apply_h *ah, void *arg);
int uri_header_get(const struct pl *pl, const struct pl *hname,
struct pl *hvalue);
int uri_headers_apply(const struct pl *pl, uri_apply_h *ah, void *arg);
bool uri_cmp(const struct uri *l, const struct uri *r);
/* Special URI escaping/unescaping */
int uri_user_escape(struct re_printf *pf, const struct pl *pl);
int uri_user_unescape(struct re_printf *pf, const struct pl *pl);
int uri_password_escape(struct re_printf *pf, const struct pl *pl);
int uri_password_unescape(struct re_printf *pf, const struct pl *pl);
int uri_param_escape(struct re_printf *pf, const struct pl *pl);
int uri_param_unescape(struct re_printf *pf, const struct pl *pl);
int uri_header_escape(struct re_printf *pf, const struct pl *pl);
int uri_header_unescape(struct re_printf *pf, const struct pl *pl);

252
mk/Doxyfile Normal file
View file

@ -0,0 +1,252 @@
# Doxyfile 1.4.7
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
PROJECT_NAME = libre
PROJECT_NUMBER = 0.1.0
OUTPUT_DIRECTORY = ../re-dox
CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English
#USE_WINDOWS_ENCODING = NO
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ABBREVIATE_BRIEF = "The $name class" \
"The $name widget" \
"The $name file" \
is \
provides \
specifies \
contains \
represents \
a \
an \
the
ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = NO
FULL_PATH_NAMES = NO
STRIP_FROM_PATH =
STRIP_FROM_INC_PATH =
SHORT_NAMES = NO
JAVADOC_AUTOBRIEF = YES
MULTILINE_CPP_IS_BRIEF = NO
#DETAILS_AT_TOP = NO
INHERIT_DOCS = YES
SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 8
ALIASES =
OPTIMIZE_OUTPUT_FOR_C = YES
OPTIMIZE_OUTPUT_JAVA = NO
#BUILTIN_STL_SUPPORT = NO
DISTRIBUTE_GROUP_DOC = NO
SUBGROUPING = YES
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
EXTRACT_ALL = NO
EXTRACT_PRIVATE = NO
EXTRACT_STATIC = NO
EXTRACT_LOCAL_CLASSES = YES
EXTRACT_LOCAL_METHODS = NO
HIDE_UNDOC_MEMBERS = YES
HIDE_UNDOC_CLASSES = YES
HIDE_FRIEND_COMPOUNDS = NO
HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO
CASE_SENSE_NAMES = YES
HIDE_SCOPE_NAMES = NO
SHOW_INCLUDE_FILES = YES
INLINE_INFO = YES
SORT_MEMBER_DOCS = YES
SORT_BRIEF_DOCS = NO
SORT_BY_SCOPE_NAME = NO
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
SHOW_DIRECTORIES = NO
FILE_VERSION_FILTER =
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
QUIET = YES
WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = NO
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = include src
FILE_PATTERNS = *.c \
*.h \
*.dox
RECURSIVE = YES
EXCLUDE = test.c \
include/re_bitv.h \
src/md5/md5.h src/md5/md5.c \
src/conf include/re_conf.h \
src/dns include/re_dns.h \
src/httpauth include/re_httpauth.h \
src/ice include/re_ice.h \
src/lock include/re_lock.h \
src/sdp include/re_sdp.h \
src/stun include/re_stun.h \
src/tcp include/re_tcp.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_PATTERNS = */.svn/* *src/sip* *include/re_sip*
EXAMPLE_PATH =
EXAMPLE_PATTERNS = *
EXAMPLE_RECURSIVE = NO
IMAGE_PATH =
INPUT_FILTER =
FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
#---------------------------------------------------------------------------
# configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER = YES
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES
#REFERENCES_LINK_SOURCE = YES
#USE_HTAGS = NO
VERBATIM_HEADERS = YES
#---------------------------------------------------------------------------
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
ALPHABETICAL_INDEX = YES
COLS_IN_ALPHA_INDEX = 5
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# configuration options related to the HTML output
#---------------------------------------------------------------------------
GENERATE_HTML = YES
HTML_OUTPUT = html
HTML_FILE_EXTENSION = .html
HTML_HEADER =
HTML_FOOTER =
HTML_STYLESHEET =
HTML_ALIGN_MEMBERS = YES
GENERATE_HTMLHELP = NO
CHM_FILE =
HHC_LOCATION =
GENERATE_CHI = NO
BINARY_TOC = NO
TOC_EXPAND = NO
DISABLE_INDEX = NO
ENUM_VALUES_PER_LINE = 4
GENERATE_TREEVIEW = NO
TREEVIEW_WIDTH = 250
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------
GENERATE_LATEX = NO
LATEX_OUTPUT = latex
LATEX_CMD_NAME = latex
MAKEINDEX_CMD_NAME = makeindex
COMPACT_LATEX = NO
PAPER_TYPE = a4wide
EXTRA_PACKAGES =
LATEX_HEADER =
PDF_HYPERLINKS = NO
USE_PDFLATEX = NO
LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------
GENERATE_RTF = NO
RTF_OUTPUT = rtf
COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
#---------------------------------------------------------------------------
# configuration options related to the man page output
#---------------------------------------------------------------------------
GENERATE_MAN = NO
MAN_OUTPUT = man
MAN_EXTENSION = .3
MAN_LINKS = NO
#---------------------------------------------------------------------------
# configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML = NO
XML_OUTPUT = xml
XML_SCHEMA =
XML_DTD =
XML_PROGRAMLISTING = YES
#---------------------------------------------------------------------------
# configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# configuration options related to the Perl module output
#---------------------------------------------------------------------------
GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
PERLMOD_PRETTY = YES
PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
SEARCH_INCLUDES = YES
INCLUDE_PATH = include
INCLUDE_FILE_PATTERNS =
PREDEFINED = HAVE_INTTYPES_H HAVE_INET6 HAVE_STDBOOL_H
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration::additions related to external references
#---------------------------------------------------------------------------
TAGFILES =
GENERATE_TAGFILE =
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = YES
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = YES
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
GROUP_GRAPHS = YES
UML_LOOK = NO
TEMPLATE_RELATIONS = NO
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
#CALL_GRAPH = YES todo: disabled to run faster
#CALLER_GRAPH = YES
GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES
DOT_IMAGE_FORMAT = png
DOT_PATH =
DOTFILE_DIRS =
#MAX_DOT_GRAPH_WIDTH = 1024
#MAX_DOT_GRAPH_HEIGHT = 1024
#MAX_DOT_GRAPH_DEPTH = 1000
DOT_TRANSPARENT = NO
DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
DOT_CLEANUP = YES
#---------------------------------------------------------------------------
# Configuration::additions related to the search engine
#---------------------------------------------------------------------------
SEARCHENGINE = NO

2
mk/exclude Normal file
View file

@ -0,0 +1,2 @@
debian/
rpm/

750
mk/re.mk Normal file
View file

@ -0,0 +1,750 @@
#
# re.mk - common make rules
#
# Copyright (C) 2010 Creytiv.com
#
# Imported variables:
#
# PROJECT Project name
# VERSION Version number
# CC Compiler
# GCOV If non-empty, enable GNU Coverage testing
# GPROF If non-empty, enable GNU Profiling
# OPT_SPEED If non-empty, optimize for speed
# OPT_SIZE If non-empty, optimize for size
# USE_OPENSSL If non-empty, link to libssl library
# USE_ZLIB If non-empty, link to libz library
# SYSROOT System root of library and include files
# SYSROOT_ALT Alternative system root of library and include files
# EXTRA_CFLAGS Extra compiler flags appended to CFLAGS
# EXTRA_LFLAGS Extra linker flags appended to LFLAGS
#
# Exported variables:
#
# CC Compiler
# CCACHE Compiler ccache tool
# CFLAGS Compiler flags
# DFLAGS Dependency generator flags
# LFLAGS Common linker flags
# SH_LFLAGS Linker flags for shared libraries
# MOD_LFLAGS Linker flags for dynamic modules
# APP_LFLAGS Linker flags for applications using modules
# LIBS Libraries to link against
# LIB_SUFFIX Suffix for shared libraries
# MOD_SUFFIX Suffix for dynamic modules
# BIN_SUFFIX Suffix for binary executables
#
ifneq ($(RELEASE),)
CFLAGS += -DRELEASE
OPT_SPEED=1
endif
# Default system root
ifeq ($(SYSROOT),)
SYSROOT := /usr
endif
# Alternative Systemroot
ifeq ($(SYSROOT_ALT),)
SYSROOT_ALT := $(shell [ -d /sw/include ] && echo "/sw")
endif
ifeq ($(SYSROOT_ALT),)
SYSROOT_ALT := $(shell [ -d /opt/local/include ] && echo "/opt/local")
endif
ifneq ($(SYSROOT_ALT),)
CFLAGS += -I$(SYSROOT_ALT)/include
LFLAGS += -L$(SYSROOT_ALT)/lib
endif
##############################################################################
#
# Compiler section
#
# find compiler name & version
ifeq ($(CC),)
CC := gcc
endif
ifeq ($(CC),cc)
CC := gcc
endif
LD := $(CC)
CC_LONGVER := $(shell if $(CC) -v 2>/dev/null; then \
$(CC) -v 2>&1 ;\
else \
$(CC) -V 2>&1 ; \
fi )
# find-out the compiler's name
ifneq (,$(findstring gcc, $(CC_LONGVER)))
CC_NAME := gcc
CC_VER := $(word 1,$(CC)) $(shell $(CC) - --version|head -n 1|\
cut -d" " -f 3|\
sed -e 's/^.*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/'\
-e 's/^[^0-9].*\([0-9][0-9]*\.[0-9][0-9]*\).*/\1/')
# sun sed is a little brain damaged => this complicated expression
MKDEP := $(CC) -MM
#transform gcc version into 2.9x, 3.x or 4.x
CC_SHORTVER := $(shell echo "$(CC_VER)" | cut -d" " -f 2| \
sed -e 's/[^0-9]*-\(.*\)/\1/'| \
sed -e 's/2\.9.*/2.9x/' -e 's/3\.[0-3]\..*/3.0/' -e \
's/3\.[0-3]/3.0/' -e 's/3\.[4-9]\..*/3.4/' -e\
's/3\.[4-9]/3.4/' -e 's/4\.[0-9]\..*/4.x/' -e\
's/4\.[0-9]/4.x/' )
endif
ifneq (, $(findstring Sun, $(CC_LONGVER)))
CC_NAME := suncc
CC_SHORTVER := $(shell echo "$(CC_LONGVER)"|head -n 1| \
sed -e 's/.*\([0-9]\.[0-9]\).*/\1/g' )
CC_VER := $(CC) $(CC_SHORTVER)
MKDEP := $(CC) -xM1
endif
ifneq (, $(findstring Intel(R) C++ Compiler, $(CC_LONGVER)))
# very nice: gcc compatible
CC_NAME := icc
CC_FULLVER := $(shell echo "$(CC_LONGVER)"|head -n 1| \
sed -e 's/.*Version \([0-9]\.[0-9]\.[0-9]*\).*/\1/g')
CC_SHORTVER := $(shell echo "$(CC_FULLVER)" | cut -d. -f1,2 )
CC_VER := $(CC) $(CC_FULLVER)
MKDEP := $(CC) -MM
endif
ifeq (,$(CC_NAME))
#not found
CC_NAME := $(CC)
CC_SHORTVER := unknown
CC_VER := unknown
MKDEP := gcc -MM
$(warning Unknown compiler $(CC)\; supported compilers: \
gcc, sun cc, intel icc )
endif
# Compiler warning flags
CFLAGS += -Wall
CFLAGS += -Wmissing-declarations
CFLAGS += -Wmissing-prototypes
CFLAGS += -Wstrict-prototypes
CFLAGS += -Wbad-function-cast
CFLAGS += -Wsign-compare
CFLAGS += -Wnested-externs
CFLAGS += -Wshadow
CFLAGS += -Waggregate-return
CFLAGS += -Wcast-align
ifeq ($(CC_SHORTVER),4.x)
CFLAGS += -Wextra
CFLAGS += -Wold-style-definition
CFLAGS += -Wdeclaration-after-statement
endif
CFLAGS += -g
ifneq ($(OPT_SPEED),)
CFLAGS += -O3 # Optimize for speed - takes longer to compile!
OPTIMIZE := 1
endif
ifneq ($(OPT_SIZE),)
CFLAGS += -Os # Optimize for size - takes longer to compile!
OPTIMIZE := 1
endif
ifneq ($(OPTIMIZE),)
CFLAGS += -Wuninitialized
ifneq ($(CC_SHORTVER), 2.9x)
CFLAGS += -Wno-strict-aliasing
endif
endif
# Compiler dependency flags
ifeq ($(CC_SHORTVER), 2.9x)
DFLAGS = -MD
else
DFLAGS = -MD -MF $(@:.o=.d) -MT $@
endif
##############################################################################
#
# OS section
#
MACHINE := $(shell $(CC) -dumpmachine)
OS := $(shell uname -s | sed -e s/SunOS/solaris/ | tr "[A-Z]" "[a-z]")
#ARCH := $(shell echo $(MACHINE) | sed -e 's/\([^-]*\)-.*/\1/')
# TODO get ARCH from first tuple in CC -dumpmachine which is more future proof
ifeq ($(MACHINE), i386-mingw32)
OS := win32
ARCH := i386
endif
ifeq ($(MACHINE), i486-mingw32)
OS := win32
ARCH := i486
endif
ifeq ($(MACHINE), i586-mingw32msvc)
OS := win32
ARCH := i586
endif
ifeq ($(MACHINE), i686-pc-cygwin)
OS := cygwin
ARCH := i686
endif
ifeq ($(MACHINE), mipsel-linux-uclibc)
OS := linux
ARCH := mipsel
endif
ifeq ($(MACHINE), bfin-linux-uclibc)
OS := linux
ARCH := bfin
endif
ifeq ($(MACHINE), bfin-uclinux)
OS := linux
ARCH := bfin
endif
ifeq ($(MACHINE), arm-apple-darwin)
OS := darwin
ARCH := arm
CROSS_COMPILE ?= $(MACHINE)-
CFLAGS += -F/Developer/SDKs/MacOSX10.4u.sdk/System/Library/Frameworks
endif
ifeq ($(MACHINE), arm-apple-darwin9)
OS := darwin
ARCH := arm
CROSS_COMPILE ?= $(MACHINE)-
ROOT := /Developer//Platforms/iPhoneOS.platform/Developer
SDK := $(ROOT)/SDKs/iPhoneOS3.0.sdk
CFLAGS += -F$(SDK)/System/Library/Frameworks/
CFLAGS += -I$(SDK)/usr/include
CFLAGS += -I$(SDK)/usr/lib/gcc/arm-apple-darwin9/4.2.1/include
CFLAGS += -isysroot $(SDK)
LFLAGS += -F$(SDK)/System/Library/Frameworks
LFLAGS += -L$(SDK)/usr/lib
LFLAGS += -L$(SDK)/usr/lib/gcc/arm-apple-darwin9/4.2.1/
endif
# default
LIB_SUFFIX := .so
MOD_SUFFIX := .so
BIN_SUFFIX :=
ifeq ($(OS),solaris)
CFLAGS += -fPIC -DSOLARIS
LIBS += -ldl -lsocket -lnsl
LFLAGS += -fPIC
SH_LFLAGS += -G
MOD_LFLAGS +=
APP_LFLAGS +=
AR := ar
AFLAGS := cru
endif
ifeq ($(OS),linux)
CFLAGS += -fPIC -DLINUX
LIBS += -ldl
LFLAGS += -fPIC
SH_LFLAGS += -shared
MOD_LFLAGS +=
APP_LFLAGS += -rdynamic
AR := ar
AFLAGS := cru
endif
ifeq ($(OS),darwin)
CFLAGS += -fPIC -dynamic -DDARWIN
CFLAGS += -Wshorten-64-to-32
DFLAGS := -MD
LFLAGS += -fPIC
SH_LFLAGS += -dynamiclib -dylib
ifneq ($(VERSION),)
SH_LFLAGS += -current_version $(VERSION)
SH_LFLAGS += -compatibility_version $(VERSION)
endif
MOD_LFLAGS += -undefined dynamic_lookup
APP_LFLAGS +=
AR := ar
AFLAGS := cru
LIB_SUFFIX := .dylib
ARCH := $(shell echo $(MACHINE) | \
sed -e 's/\([^-]*\)-.*/\1/')
endif
ifeq ($(OS),netbsd)
CFLAGS += -fPIC -DNETBSD
LFLAGS += -fPIC
SH_LFLAGS += -shared
MOD_LFLAGS +=
APP_LFLAGS += -rdynamic
AR := ar
AFLAGS := cru
endif
ifeq ($(OS),freebsd)
CFLAGS += -fPIC -DFREEBSD
LFLAGS += -fPIC
SH_LFLAGS += -shared
MOD_LFLAGS +=
APP_LFLAGS += -rdynamic
AR := ar
AFLAGS := cru
endif
ifeq ($(OS),openbsd)
CFLAGS += -fPIC -DOPENBSD
LFLAGS += -fPIC
SH_LFLAGS += -shared
MOD_LFLAGS +=
APP_LFLAGS += -rdynamic
AR := ar
AFLAGS := cru
endif
ifeq ($(OS),win32)
CFLAGS += -DWIN32 -D_WIN32_WINNT=0x0501
LIBS += -lwsock32 -lws2_32 -liphlpapi
LFLAGS +=
SH_LFLAGS += -shared
MOD_LFLAGS +=
APP_LFLAGS += -Wl,-E
AR := ar
AFLAGS := cru
CROSS_COMPILE := $(MACHINE)-
RANLIB := $(CROSS_COMPILE)ranlib
LIB_SUFFIX := .dll
MOD_SUFFIX := .dll
BIN_SUFFIX := .exe
SYSROOT := /usr/$(MACHINE)/
endif
ifeq ($(OS),cygwin)
CFLAGS += -DCYGWIN -D_WIN32_WINNT=0x0501
LIBS += -lwsock32 -lws2_32
LFLAGS +=
SH_LFLAGS += -shared
MOD_LFLAGS +=
APP_LFLAGS += -Wl,-E
AR := ar
AFLAGS := cru
endif
CFLAGS += -DOS=\"$(OS)\"
ifeq ($(CC_SHORTVER),2.9x)
CFLAGS += -Wno-long-long
else
CFLAGS += -std=c99
PEDANTIC := 1
endif # CC_SHORTVER
ifneq ($(PEDANTIC),)
CFLAGS += -pedantic
endif
##############################################################################
#
# Architecture section
#
ifeq ($(OS),solaris)
GETARCH=uname -p
else
GETARCH=uname -m
endif
ifeq ($(ARCH),)
ARCH := $(shell $(GETARCH) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
-e s/armv4l/arm/ -e "s/Power Macintosh/ppc/" \
-e "s/cobalt/mips2/" \
-e s/amd64/x86_64/ )
endif
# fix sparc -> sparc64
ifeq ($(ARCH),sparc)
ifeq ($(shell uname -m),sun4u)
ARCH := sparc64
endif
endif
CFLAGS += -DARCH=\"$(ARCH)\"
ifeq ($(ARCH),mipsel)
CFLAGS += -march=mips32
endif
##############################################################################
#
# External libraries section
#
USE_OPENSSL := $(shell [ -f $(SYSROOT)/include/openssl/ssl.h ] || \
[ -f $(SYSROOT_ALT)/include/openssl/ssl.h ] && echo "yes")
USE_ZLIB := $(shell [ -f $(SYSROOT)/include/zlib.h ] || \
[ -f $(SYSROOT_ALT)/include/zlib.h ] && echo "yes")
ifneq ($(USE_OPENSSL),)
CFLAGS += -DUSE_OPENSSL -DUSE_TLS
LIBS += -lssl -lcrypto
USE_TLS := yes
endif
ifneq ($(USE_ZLIB),)
CFLAGS += -DUSE_ZLIB
LIBS += -lz
endif
ifneq ($(OS),win32)
HAVE_PTHREAD := $(shell [ -f $(SYSROOT)/include/pthread.h ] && echo "1")
ifneq ($(HAVE_PTHREAD),)
HAVE_PTHREAD_RWLOCK := 1
CFLAGS += -DHAVE_PTHREAD
HAVE_LIBPTHREAD := 1
ifneq ($(HAVE_LIBPTHREAD),)
LIBS += -lpthread
endif
endif
ifneq ($(ARCH),mipsel)
HAVE_GETIFADDRS := $(shell [ -f $(SYSROOT)/include/ifaddrs.h ] && echo "1")
ifneq ($(HAVE_GETIFADDRS),)
CFLAGS += -DHAVE_GETIFADDRS
endif
endif
endif
HAVE_GETOPT := $(shell [ -f $(SYSROOT)/include/getopt.h ] && echo "1")
ifneq ($(HAVE_GETOPT),)
CFLAGS += -DHAVE_GETOPT
endif
HAVE_INTTYPES_H := $(shell [ -f $(SYSROOT)/include/inttypes.h ] && echo "1")
ifneq ($(HAVE_INTTYPES_H),)
CFLAGS += -DHAVE_INTTYPES_H
endif
HAVE_NET_ROUTE_H := $(shell [ -f $(SYSROOT)/include/net/route.h ] && echo "1")
ifneq ($(HAVE_NET_ROUTE_H),)
CFLAGS += -DHAVE_NET_ROUTE_H
endif
HAVE_SYS_SYSCTL_H := \
$(shell [ -f $(SYSROOT)/include/sys/sysctl.h ] && echo "1")
ifneq ($(HAVE_SYS_SYSCTL_H),)
CFLAGS += -DHAVE_SYS_SYSCTL_H
endif
CFLAGS += -DHAVE_STDBOOL_H
HAVE_INET6 := 1
ifneq ($(HAVE_INET6),)
CFLAGS += -DHAVE_INET6
endif
ifeq ($(OS),win32)
CFLAGS += -DHAVE_SELECT
CFLAGS += -DHAVE_IO_H
else
HAVE_SYSLOG := $(shell [ -f $(SYSROOT)/include/syslog.h ] && echo "1")
HAVE_DLFCN_H := $(shell [ -f $(SYSROOT)/include/dlfcn.h ] && echo "1")
ifneq ($(OS),darwin)
HAVE_EPOLL := $(shell [ -f $(SYSROOT)/include/sys/epoll.h ] && echo "1")
endif
HAVE_LIBRESOLV := $(shell [ -f $(SYSROOT)/include/resolv.h ] && echo "1")
ifneq ($(HAVE_LIBRESOLV),)
CFLAGS += -DHAVE_LIBRESOLV
ifneq ($(OS),freebsd)
LIBS += -lresolv
endif
endif
ifneq ($(HAVE_SYSLOG),)
CFLAGS += -DHAVE_SYSLOG
endif
CFLAGS += -DHAVE_FORK
CFLAGS += -DHAVE_INET_NTOP
CFLAGS += -DHAVE_PWD_H
ifneq ($(OS),darwin)
CFLAGS += -DHAVE_POLL # Darwin: poll() does not support devices
CFLAGS += -DHAVE_INET_PTON
endif
CFLAGS += -DHAVE_SELECT -DHAVE_SELECT_H
CFLAGS += -DHAVE_SETRLIMIT
CFLAGS += -DHAVE_SIGNAL
CFLAGS += -DHAVE_SYS_TIME_H
ifneq ($(HAVE_EPOLL),)
CFLAGS += -DHAVE_EPOLL
endif
CFLAGS += -DHAVE_UNAME
CFLAGS += -DHAVE_UNISTD_H
ifneq ($(OS),cygwin)
CFLAGS += -DHAVE_STRINGS_H
CFLAGS += -DHAVE_GAI_STRERROR
endif
endif
##############################################################################
#
# Misc tools section
#
CCACHE := $(shell [ -e /usr/bin/ccache ] 2>/dev/null \
|| [ -e /opt/local/bin/ccache ] \
&& echo "ccache")
CFLAGS += -DVERSION=\"$(VERSION)\"
# Enable gcov Coverage testing
#
# - generated during build: .gcno files
# - generated during exec: .gcda files
#
ifneq ($(GCOV),)
CFLAGS += -fprofile-arcs -ftest-coverage
LFLAGS += -fprofile-arcs -ftest-coverage
# Disable ccache
CCACHE :=
endif
# gprof - GNU Profiling
#
# - generated during exec: gmon.out
#
ifneq ($(GPROF),)
CFLAGS += -pg
LFLAGS += -pg
# Disable ccache
CCACHE :=
endif
CC := $(CCACHE) $(CC)
CFLAGS += $(EXTRA_CFLAGS)
LFLAGS += $(EXTRA_LFLAGS)
BUILD := build-$(ARCH)
default: all
.PHONY: distclean
distclean:
@rm -rf build* *core*
@rm -f *stamp $(BIN)
@rm -f `find . -name "*.[oda]"` `find . -name "*.so"`
@rm -f `find . -name "*~"` `find . -name "\.\#*"`
@rm -f `find . -name "*.orig"` `find . -name "*.rej"`
@rm -f `find . -name "*.previous"` `find . -name "*.gcov"`
@rm -f `find . -name "*.exe"` `find . -name "*.dll"`
@rm -f `find . -name "*.dylib"`
.PHONY: info
info:
@echo "info - $(PROJECT) version $(VERSION)"
@echo " MODULES: $(MODULES)"
# @echo " SRCS: $(SRCS)"
@echo " MACHINE: $(MACHINE)"
@echo " ARCH: $(ARCH)"
@echo " OS: $(OS)"
@echo " BUILD: $(BUILD)"
@echo " CCACHE: $(CCACHE)"
@echo " CC: $(CC_NAME) $(CC_SHORTVER)"
@echo " CFLAGS: $(CFLAGS)"
@echo " DFLAGS: $(DFLAGS)"
@echo " LFLAGS: $(LFLAGS)"
@echo " SH_LFLAGS: $(SH_LFLAGS)"
@echo " MOD_LFLAGS: $(MOD_LFLAGS)"
@echo " APP_LFLAGS: $(APP_LFLAGS)"
@echo " LIBS: $(LIBS)"
@echo " LIBRE_MK: $(LIBRE_MK)"
@echo " LIBRE_INC: $(LIBRE_INC)"
@echo " LIBRE_SO: $(LIBRE_SO)"
@echo " USE_OPENSSL: $(USE_OPENSSL)"
@echo " USE_ZLIB: $(USE_ZLIB)"
@echo " GCOV: $(GCOV)"
@echo " GPROF: $(GPROF)"
@echo " CROSS_COMPILE: $(CROSS_COMPILE)"
@echo " SYSROOT: $(SYSROOT)"
@echo " SYSROOT_ALT: $(SYSROOT_ALT)"
@echo " LIB_SUFFIX: $(LIB_SUFFIX)"
@echo " MOD_SUFFIX: $(MOD_SUFFIX)"
@echo " BIN_SUFFIX: $(BIN_SUFFIX)"
##############################################################################
#
# Packaging section
#
TAR_SRC := $(PROJECT)-$(VERSION)
release:
@rm -rf ../$(TAR_SRC)
@svn export . ../$(TAR_SRC)
@if [ -f ../$(TAR_SRC)/mk/exclude ]; then \
cat ../$(TAR_SRC)/mk/exclude \
| sed 's|^|../$(TAR_SRC)/|' | xargs -t rm -rf ; \
rm -f ../$(TAR_SRC)/mk/exclude ; \
fi
@cd .. && rm -f $(TAR_SRC).tar.gz \
&& tar -zcf $(TAR_SRC).tar.gz $(TAR_SRC) \
&& echo "created release tarball `pwd`/$(TAR_SRC).tar.gz"
tar:
@rm -rf ../$(TAR_SRC)
@svn export . ../$(TAR_SRC)
@cd .. && rm -f $(TAR_SRC).tar.gz \
&& tar -zcf $(TAR_SRC).tar.gz $(TAR_SRC) \
&& echo "created source tarball `pwd`/$(TAR_SRC).tar.gz"
# Debian
.PHONY: deb
deb:
dpkg-buildpackage -rfakeroot
# RPM
RPM := $(shell [ -d /usr/src/rpm ] 2>/dev/null && echo "rpm")
ifeq ($(RPM),)
RPM := $(shell [ -d /usr/src/redhat ] 2>/dev/null && echo "redhat")
endif
.PHONY: rpm
rpm: tar
sudo cp ../$(PROJECT)-$(VERSION).tar.gz /usr/src/$(RPM)/SOURCES
sudo rpmbuild -ba rpm/$(PROJECT).spec
##############################################################################
#
# Library and header files location section - in prioritised order
#
# - relative path
# - local installation
# - system installation
#
# Include path
LIBRE_INC := $(shell [ -f ../re/include/re.h ] && echo "../re/include")
ifeq ($(LIBRE_INC),)
LIBRE_INC := $(shell [ -f /usr/local/include/re/re.h ] && \
echo "/usr/local/include/re")
endif
ifeq ($(LIBRE_INC),)
LIBRE_INC := $(shell [ -f /usr/include/re/re.h ] && echo "/usr/include/re")
endif
# Library path
LIBRE_SO := $(shell [ -f ../re/libre$(LIB_SUFFIX) ] && echo "../re")
ifeq ($(LIBRE_SO),)
LIBRE_SO := $(shell [ -f /usr/local/lib/libre$(LIB_SUFFIX) ] \
&& echo "/usr/local/lib")
endif
ifeq ($(LIBRE_SO),)
LIBRE_SO := $(shell [ -f /usr/lib/libre$(LIB_SUFFIX) ] && echo "/usr/lib")
endif
ifeq ($(LIBRE_SO),)
LIBRE_SO := $(shell [ -f /usr/lib64/libre$(LIB_SUFFIX) ] && echo "/usr/lib64")
endif
##############################################################################
#
# Splint section
#
SPLINT_OPTIONS += +unixlib
SPLINT_OPTIONS += +skipsysheaders
SPLINT_OPTIONS += -noeffect # Statement has no effect: (void)reg
SPLINT_OPTIONS += -compdef # Passed storage buf not completely..
SPLINT_OPTIONS += -mustfreefresh # Fresh storage st not released before
SPLINT_OPTIONS += -nullret # Null storage returned as non-null
SPLINT_OPTIONS += -compmempass
SPLINT_OPTIONS += -observertrans # Observer storage returned without..
SPLINT_OPTIONS += -fixedformalarray # e.g. param: int linesize[4]
SPLINT_OPTIONS += +voidabstract
# these options can be tuned:
SPLINT_OPTIONS += -mayaliasunique # Parameter 1 (ua->stat.rphrase)
SPLINT_OPTIONS += -boolops # Left operand of && is non-boolean
SPLINT_OPTIONS += -nullpass # Possibly null storage resp passed..
SPLINT_OPTIONS += -type
SPLINT_OPTIONS += -mustfreeonly # Implicitly only storage ua->callt..
SPLINT_OPTIONS += -nullassign
SPLINT_OPTIONS += -unrecog # Unrecognized identifier: strdup
SPLINT_OPTIONS += -unqualifiedtrans # Unqualified storage ua->lhost assign
SPLINT_OPTIONS += -temptrans # Implicitly temp storage assigned to
SPLINT_OPTIONS += -usereleased
SPLINT_OPTIONS += -predboolint
SPLINT_OPTIONS += -statictrans
SPLINT_OPTIONS += -globstate # Function returns with global..
SPLINT_OPTIONS += -compdestroy # Only storage call->conf derived
SPLINT_OPTIONS += -onlytrans # Only storage alias->mb assigned
SPLINT_OPTIONS += -shiftimplementation
SPLINT_OPTIONS += -shiftnegative
SPLINT_OPTIONS += -predboolothers
SPLINT_OPTIONS += -nullstate # Null storage ct->timer_a derivable..
SPLINT_OPTIONS += -redef # Enum member T1 defined more than once
SPLINT_OPTIONS += -usedef # Variable tv used before definition
SPLINT_OPTIONS += -dependenttrans # Dependent storage m returned as..
SPLINT_OPTIONS += -immediatetrans # Immediate address &xyz returned
SPLINT_OPTIONS += -branchstate # Storage is released in one path
SPLINT_OPTIONS += -kepttrans # Kept storage le assigned to implic..
SPLINT_OPTIONS += -incondefs
SPLINT_OPTIONS += -exportlocal
SPLINT_OPTIONS += -nullderef
SPLINT_OPTIONS += -fullinitblock # problem in main/main.c init block
SPLINT_OPTIONS += -evalorder # problem with e.g. foo(rand(), rand())
SPLINT_OPTIONS += -uniondef # union in struct sa
SPLINT_OPTIONS += -realcompare # tping: comp double types rtt < 0
SPLINT_OPTIONS += -fcnuse
SPLINT_OPTIONS += -retvalother # Return value ignored (not int)
SPLINT_OPTIONS += -Iinclude -I$(LIBRE_INC)
SPLINT_OPTIONS += -DHAVE_GETOPT -DHAVE_POLL -DHAVE_STDBOOL_H
SPLINT_OPTIONS += -DHAVE_INET_NTOP -DHAVE_INET_PTON -DHAVE_INET6
# ignore these files for now
SPLINT_IGNORE := src/tls/openssl/tls.c src/tls/openssl/tls_tcp.c
SPLINT_IGNORE += src/dns/darwin/srv.c
SPLINT_SOURCES += $(filter-out $(SPLINT_IGNORE), $(patsubst %,src/%,$(SRCS)))
splint-sources:
@echo $(SPLINT_SOURCES)
splint-all:
@splint $(SPLINT_LIBS) $(SPLINT_OPTIONS) $(SPLINT_SOURCES)
splint:
@for n in $(SPLINT_SOURCES); do \
splint $(SPLINT_LIBS) $(SPLINT_OPTIONS) $${n} 2>/dev/null ; \
done
splint-verbose:
@for n in $(SPLINT_SOURCES); do \
echo "running splint on $${n}"; \
splint $(SPLINT_LIBS) $(SPLINT_OPTIONS) $${n} ; \
done
splint-test:
@splint $(SPLINT_LIBS) $(SPLINT_OPTIONS) test.c
###############################################################################
#
# Documentation section
#
DOX_DIR=../$(PROJECT)-dox
DOX_TAR=$(PROJECT)-dox-$(VERSION)
$(DOX_DIR):
@mkdir $@
$(DOX_DIR)/Doxyfile: mk/Doxyfile Makefile
@cp $< $@
@perl -pi -e 's/PROJECT_NUMBER\s*=.*/PROJECT_NUMBER = $(VERSION)/' \
$(DOX_DIR)/Doxyfile
.PHONY:
dox: $(DOX_DIR) $(DOX_DIR)/Doxyfile
@doxygen $(DOX_DIR)/Doxyfile 2>&1 | grep -v DEBUG_ ; true
@cd .. && rm -f $(DOX_TAR).tar.gz && \
tar -zcf $(DOX_TAR).tar.gz $(PROJECT)-dox > /dev/null && \
echo "Doxygen docs in `pwd`/$(DOX_TAR).tar.gz"

59
mk/symbian/bld.inf Normal file
View file

@ -0,0 +1,59 @@
/**
* @file bld.inf Symbian build information
*
* Copyright (C) 2010 Creytiv.com
*/
PRJ_EXPORTS
..\..\include\re.h \epoc32\include\re\re.h
..\..\include\re_base64.h \epoc32\include\re\re_base64.h
..\..\include\re_bitv.h \epoc32\include\re\re_bitv.h
..\..\include\re_conf.h \epoc32\include\re\re_conf.h
..\..\include\re_crc32.h \epoc32\include\re\re_crc32.h
..\..\include\re_dbg.h \epoc32\include\re\re_dbg.h
..\..\include\re_dns.h \epoc32\include\re\re_dns.h
..\..\include\re_fmt.h \epoc32\include\re\re_fmt.h
..\..\include\re_g711.h \epoc32\include\re\re_g711.h
..\..\include\re_hash.h \epoc32\include\re\re_hash.h
..\..\include\re_hmac.h \epoc32\include\re\re_hmac.h
..\..\include\re_httpauth.h \epoc32\include\re\re_httpauth.h
..\..\include\re_ice.h \epoc32\include\re\re_ice.h
..\..\include\re_jbuf.h \epoc32\include\re\re_jbuf.h
..\..\include\re_list.h \epoc32\include\re\re_list.h
..\..\include\re_lock.h \epoc32\include\re\re_lock.h
..\..\include\re_main.h \epoc32\include\re\re_main.h
..\..\include\re_mbuf.h \epoc32\include\re\re_mbuf.h
..\..\include\re_md5.h \epoc32\include\re\re_md5.h
..\..\include\re_mem.h \epoc32\include\re\re_mem.h
..\..\include\re_mod.h \epoc32\include\re\re_mod.h
..\..\include\re_mqueue.h \epoc32\include\re\re_mqueue.h
..\..\include\re_natbd.h \epoc32\include\re\re_natbd.h
..\..\include\re_net.h \epoc32\include\re\re_net.h
..\..\include\re_rtp.h \epoc32\include\re\re_rtp.h
..\..\include\re_sa.h \epoc32\include\re\re_sa.h
..\..\include\re_sdp.h \epoc32\include\re\re_sdp.h
..\..\include\re_sha.h \epoc32\include\re\re_sha.h
..\..\include\re_sip.h \epoc32\include\re\re_sip.h
..\..\include\re_sipreg.h \epoc32\include\re\re_sipreg.h
..\..\include\re_sipsess.h \epoc32\include\re\re_sipsess.h
..\..\include\re_stun.h \epoc32\include\re\re_stun.h
..\..\include\re_sys.h \epoc32\include\re\re_sys.h
..\..\include\re_tcp.h \epoc32\include\re\re_tcp.h
..\..\include\re_telev.h \epoc32\include\re\re_telev.h
..\..\include\re_tls.h \epoc32\include\re\re_tls.h
..\..\include\re_tmr.h \epoc32\include\re\re_tmr.h
..\..\include\re_turn.h \epoc32\include\re\re_turn.h
..\..\include\re_types.h \epoc32\include\re\re_types.h
..\..\include\re_udp.h \epoc32\include\re\re_udp.h
..\..\include\re_uri.h \epoc32\include\re\re_uri.h
PRJ_MMPFILES
re.mmp
redns.mmp
resdp.mmp
resip.mmp
resipsess.mmp
restun.mmp

10
mk/symbian/dll.cpp Normal file
View file

@ -0,0 +1,10 @@
#include <e32def.h>
#include <e32std.h>
#ifndef EKA2
GLDEF_C TInt E32Dll(TDllReason /*aReason*/)
{
return KErrNone;
}
#endif

31
mk/symbian/ecrt.cpp Normal file
View file

@ -0,0 +1,31 @@
/**
* @file ecrt.cpp ECRT wrapper for Symbian OS
*
* Copyright (C) 2010 Creytiv.com
*/
#include <stdlib.h>
#include <stdio.h>
#include <e32base.h>
#include <e32cons.h>
#include <sys/reent.h>
_LIT(KAppName, "retest");
extern "C" int main(int argc, char** argv);
TInt E32Main()
{
__UHEAP_MARK;
CTrapCleanup* cleanup = CTrapCleanup::New();
int ret = 0;
TRAPD(err, ret = main(0, NULL));
if (err)
printf("main left with error %d\n", err);
if (ret)
printf("main returned %d\n", ret);
__ASSERT_ALWAYS(!err, User::Panic(KAppName, err));
CloseSTDLIB();
delete cleanup;
__UHEAP_MARKEND;
return err;
}

154
mk/symbian/re.mmp Normal file
View file

@ -0,0 +1,154 @@
/**
* @file re.mmp Symbian makefile for libre
*
* Copyright (C) 2010 Creytiv.com
*/
TARGET re.lib
TARGETTYPE lib
TARGETPATH system\libs
UID 0x10000fd3 0x200112fa
#ifdef EKA2
VENDORID 0
CAPABILITY NetworkServices
#endif
MACRO HAVE_SYS_TIME_H
MACRO HAVE_UNISTD_H
MACRO HAVE_ACTSCHED
#ifndef EKA2
SOURCEPATH .
SOURCE dll.cpp
#endif
SOURCEPATH ..\..\src\base64
SOURCE b64.c
SOURCEPATH ..\..\src\conf
SOURCE conf.c
SOURCEPATH ..\..\src\crc32
SOURCE crc32.c
SOURCEPATH ..\..\src\dbg
SOURCE dbg.c
SOURCEPATH ..\..\src\fmt
SOURCE ch.c
SOURCE hexdump.c
SOURCE pl.c
SOURCE print.c
SOURCE prm.c
SOURCE regex.c
SOURCE str.c
SOURCE time.c
SOURCEPATH ..\..\src\g711
SOURCE g711.c
SOURCEPATH ..\..\src\hash
SOURCE hash.c
SOURCE func.c
SOURCEPATH ..\..\src\hmac
SOURCE hmac_sha1.c
SOURCEPATH ..\..\src\httpauth
SOURCE basic.c
SOURCE digest.c
SOURCEPATH ..\..\src\jbuf
SOURCE jbuf.c
SOURCEPATH ..\..\src\list
SOURCE list.c
SOURCEPATH ..\..\src\lock
SOURCE symbian\rmutex.cpp
SOURCEPATH ..\..\src\main
SOURCE init.c
SOURCE main.c
SOURCE method.c
SOURCE symbian\actsched.cpp
SOURCEPATH ..\..\src\mbuf
SOURCE mbuf.c
SOURCEPATH ..\..\src\md5
SOURCE md5.c
SOURCE wrap.c
SOURCEPATH ..\..\src\mem
SOURCE mem.c
SOURCEPATH ..\..\src\mod
SOURCE mod.c
SOURCE symbian\rlib.cpp
SOURCEPATH ..\..\src\net
SOURCE sock.c
SOURCE netstr.c
SOURCE if.c
SOURCE rt.c
SOURCE net.c
SOURCE symbian\sif.cpp
SOURCE symbian\snet.cpp
SOURCE symbian\srt.cpp
SOURCE symbian\rconn.cpp
SOURCEPATH ..\..\src\rtp
SOURCE fb.c
SOURCE member.c
SOURCE ntp.c
SOURCE pkt.c
SOURCE rr.c
SOURCE rtcp.c
SOURCE rtp.c
SOURCE sdes.c
SOURCE sess.c
SOURCE source.c
SOURCEPATH ..\..\src\sa
SOURCE ntop.c
SOURCE pton.c
SOURCE sa.c
SOURCEPATH ..\..\src\sha
SOURCE sha1.c
SOURCEPATH ..\..\src\sys
SOURCE daemon.c
SOURCE endian.c
SOURCE rand.c
SOURCE sys.c
SOURCEPATH ..\..\src\telev
SOURCE telev.c
SOURCEPATH ..\..\src\tmr
SOURCE tmr.c
SOURCEPATH ..\..\src\udp
SOURCE symbian\udp.cpp
SOURCEPATH ..\..\src\tcp
SOURCE tcp_high.c
SOURCE symbian\tcp.cpp
SOURCEPATH ..\..\src\uri
SOURCE ucmp.c
SOURCE uri.c
SOURCE uric.c
USERINCLUDE . ..\..\include
SYSTEMINCLUDE \epoc32\include
SYSTEMINCLUDE \epoc32\include\libc
SYSTEMINCLUDE ..\..\include
#ifndef EKA2
LIBRARY estlib.lib euser.lib
LIBRARY esock.lib insock.lib
#endif
EXPORTUNFROZEN

38
mk/symbian/redns.mmp Normal file
View file

@ -0,0 +1,38 @@
/**
* @file redns.mmp Symbian makefile for libre DNS
*
* Copyright (C) 2010 Creytiv.com
*/
TARGET redns.lib
TARGETTYPE lib
TARGETPATH system\libs
UID 0x10000fd3 0x20011309
#ifdef EKA2
VENDORID 0
CAPABILITY NetworkServices
#endif
SOURCEPATH .
SOURCE dll.cpp
SOURCEPATH ..\..\src\dns
SOURCE client.c
SOURCE cstr.c
SOURCE dname.c
SOURCE hdr.c
SOURCE ns.c
SOURCE rr.c
SOURCE rrlist.c
SOURCE symbian\srv.cpp
USERINCLUDE .
SYSTEMINCLUDE \epoc32\include
SYSTEMINCLUDE \epoc32\include\libc
SYSTEMINCLUDE ..\..\include
#ifndef EKA2
LIBRARY estlib.lib euser.lib
LIBRARY esock.lib insock.lib
#endif
EXPORTUNFROZEN

36
mk/symbian/resdp.mmp Normal file
View file

@ -0,0 +1,36 @@
/**
* @file resdp.mmp Symbian makefile for libre SDP
*
* Copyright (C) 2010 Creytiv.com
*/
TARGET resdp.lib
TARGETTYPE lib
TARGETPATH system\libs
UID 0x10000fd3 0x2001130C
#ifdef EKA2
VENDORID 0
CAPABILITY NetworkServices
#endif
SOURCEPATH .
SOURCE dll.cpp
SOURCEPATH ..\..\src\sdp
SOURCE attr.c
SOURCE format.c
SOURCE media.c
SOURCE msg.c
SOURCE session.c
SOURCE str.c
USERINCLUDE . ..\..\include
SYSTEMINCLUDE \epoc32\include
SYSTEMINCLUDE \epoc32\include\libc
SYSTEMINCLUDE ..\..\include
#ifndef EKA2
LIBRARY estlib.lib euser.lib
LIBRARY esock.lib insock.lib
#endif
EXPORTUNFROZEN

50
mk/symbian/resip.mmp Normal file
View file

@ -0,0 +1,50 @@
/**
* @file resip.mmp Symbian makefile for libre SIP
*
* Copyright (C) 2010 Creytiv.com
*/
TARGET resip.lib
TARGETTYPE lib
TARGETPATH system\libs
UID 0x10000fd3 0x2001130A
#ifdef EKA2
VENDORID 0
CAPABILITY NetworkServices
#endif
SOURCEPATH .
SOURCE dll.cpp
SOURCEPATH ..\..\src\httpauth
SOURCE basic.c
SOURCE digest.c
SOURCEPATH ..\..\src\sip
SOURCE addr.c
SOURCE auth.c
SOURCE cseq.c
SOURCE ctrans.c
SOURCE dialog.c
SOURCE msg.c
SOURCE param.c
SOURCE reply.c
SOURCE request.c
SOURCE sip.c
SOURCE strans.c
SOURCE transp.c
SOURCE via.c
SOURCEPATH ..\..\src\sipreg
SOURCE reg.c
USERINCLUDE . ..\..\include
SYSTEMINCLUDE \epoc32\include
SYSTEMINCLUDE \epoc32\include\libc
SYSTEMINCLUDE ..\..\include
#ifndef EKA2
LIBRARY estlib.lib euser.lib
LIBRARY esock.lib insock.lib
#endif
EXPORTUNFROZEN

40
mk/symbian/resipsess.mmp Normal file
View file

@ -0,0 +1,40 @@
/**
* @file resipsess.mmp Symbian makefile for libre SIP Session
*
* Copyright (C) 2010 Creytiv.com
*/
TARGET resipsess.lib
TARGETTYPE lib
TARGETPATH system\libs
UID 0x10000fd3 0x2001130D
#ifdef EKA2
VENDORID 0
CAPABILITY NetworkServices
#endif
SOURCEPATH .
SOURCE dll.cpp
SOURCEPATH ..\..\src\sipsess
SOURCE accept.c
SOURCE ack.c
SOURCE close.c
SOURCE connect.c
SOURCE info.c
SOURCE listen.c
SOURCE modify.c
SOURCE reply.c
SOURCE request.c
SOURCE sess.c
USERINCLUDE . ..\..\include
SYSTEMINCLUDE \epoc32\include
SYSTEMINCLUDE \epoc32\include\libc
SYSTEMINCLUDE ..\..\include
#ifndef EKA2
LIBRARY estlib.lib euser.lib
LIBRARY esock.lib insock.lib
#endif
EXPORTUNFROZEN

69
mk/symbian/restun.mmp Normal file
View file

@ -0,0 +1,69 @@
/**
* @file restun.mmp Symbian makefile for libre STUN
*
* Copyright (C) 2010 Creytiv.com
*/
TARGET restun.lib
TARGETTYPE lib
TARGETPATH system\libs
UID 0x10000fd3 0x2001130B
#ifdef EKA2
VENDORID 0
CAPABILITY NetworkServices
#endif
SOURCEPATH .
SOURCE dll.cpp
SOURCEPATH ..\..\src\ice
SOURCE cand.c
SOURCE candpair.c
SOURCE chklist.c
SOURCE comp.c
SOURCE connchk.c
SOURCE gather.c
SOURCE ice.c
SOURCE icem.c
SOURCE icesdp.c
SOURCE icestr.c
SOURCE stunsrv.c
SOURCE triggq.c
SOURCE util.c
SOURCEPATH ..\..\src\natbd
SOURCE filtering.c
SOURCE genalg.c
SOURCE hairpinning.c
SOURCE lifetime.c
SOURCE mapping.c
SOURCE natstr.c
SOURCEPATH ..\..\src\stun
SOURCE addr.c
SOURCE attr.c
SOURCE ctrans.c
SOURCE dnsdisc.c
SOURCE hdr.c
SOURCE ind.c
SOURCE keepalive.c
SOURCE msg.c
SOURCE rep.c
SOURCE req.c
SOURCE stun.c
SOURCEPATH ..\..\src\turn
SOURCE chan.c
SOURCE perm.c
SOURCE turnc.c
USERINCLUDE . ..\..\include
SYSTEMINCLUDE \epoc32\include
SYSTEMINCLUDE \epoc32\include\libc
SYSTEMINCLUDE ..\..\include
#ifndef EKA2
LIBRARY estlib.lib euser.lib
LIBRARY esock.lib insock.lib
#endif
EXPORTUNFROZEN

815
mk/win32/re.vcproj Normal file
View file

@ -0,0 +1,815 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="re-win32"
ProjectGUID="{40B28DF6-4B4A-411A-9EB7-8D80C2A29B9D}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="..\..\Win32\Debug"
IntermediateDirectory="c:\tmp\re\Win32\Debug"
ConfigurationType="4"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
InlineFunctionExpansion="0"
AdditionalIncludeDirectories="..\..\include"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;HAVE_SELECT;HAVE_IO_H;_CRT_SECURE_NO_DEPRECATE"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"
DisableSpecificWarnings="4142"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLibrarianTool"
AdditionalOptions="Iphlpapi.lib"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="Win32\Release"
IntermediateDirectory="Win32\Release"
ConfigurationType="4"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="include"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;HAVE_SELECT;HAVE_IO_H;_CRT_SECURE_NO_DEPRECATE"
RuntimeLibrary="2"
UsePrecompiledHeader="2"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"
DisableSpecificWarnings="4142"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLibrarianTool"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
<Filter
Name="base64"
Filter="">
<File
RelativePath="..\..\src\base64\b64.c">
</File>
</Filter>
<Filter
Name="conf"
Filter="">
<File
RelativePath="..\..\src\conf\conf.c">
</File>
</Filter>
<Filter
Name="crc32"
Filter="">
<File
RelativePath="..\..\src\crc32\crc32.c">
</File>
</Filter>
<Filter
Name="dbg"
Filter="">
<File
RelativePath="..\..\src\dbg\dbg.c">
</File>
</Filter>
<Filter
Name="dns"
Filter="">
<File
RelativePath="..\..\src\dns\client.c">
</File>
<File
RelativePath="..\..\src\dns\cstr.c">
</File>
<File
RelativePath="..\..\src\dns\dname.c">
</File>
<File
RelativePath="..\..\src\dns\hdr.c">
</File>
<File
RelativePath="..\..\src\dns\ns.c">
</File>
<File
RelativePath="..\..\src\dns\rr.c">
</File>
<File
RelativePath="..\..\src\dns\rrlist.c">
</File>
<File
RelativePath="..\..\src\dns\win32\srv.c">
</File>
</Filter>
<Filter
Name="fmt"
Filter="">
<File
RelativePath="..\..\src\fmt\ch.c">
</File>
<File
RelativePath="..\..\src\fmt\pl.c">
</File>
<File
RelativePath="..\..\src\fmt\print.c">
</File>
<File
RelativePath="..\..\src\fmt\prm.c">
</File>
<File
RelativePath="..\..\src\fmt\regex.c">
</File>
<File
RelativePath="..\..\src\fmt\str.c">
</File>
<File
RelativePath="..\..\src\fmt\time.c">
</File>
</Filter>
<Filter
Name="g711"
Filter="">
<File
RelativePath="..\..\src\g711\g711.c">
</File>
</Filter>
<Filter
Name="hash"
Filter="">
<File
RelativePath="..\..\src\hash\func.c">
</File>
<File
RelativePath="..\..\src\hash\hash.c">
</File>
</Filter>
<Filter
Name="hmac"
Filter="">
<File
RelativePath="..\..\src\hmac\hmac_sha1.c">
</File>
</Filter>
<Filter
Name="httpauth"
Filter="">
<File
RelativePath="..\..\src\httpauth\basic.c">
</File>
<File
RelativePath="..\..\src\httpauth\digest.c">
</File>
</Filter>
<Filter
Name="ice"
Filter="">
<File
RelativePath="..\..\src\ice\cand.c">
</File>
<File
RelativePath="..\..\src\ice\candpair.c">
</File>
<File
RelativePath="..\..\src\ice\chklist.c">
</File>
<File
RelativePath="..\..\src\ice\comp.c">
</File>
<File
RelativePath="..\..\src\ice\connchk.c">
</File>
<File
RelativePath="..\..\src\ice\gather.c">
</File>
<File
RelativePath="..\..\src\ice\ice.c">
</File>
<File
RelativePath="..\..\src\ice\icem.c">
</File>
<File
RelativePath="..\..\src\ice\icesdp.c">
</File>
<File
RelativePath="..\..\src\ice\icestr.c">
</File>
<File
RelativePath="..\..\src\ice\stunsrv.c">
</File>
<File
RelativePath="..\..\src\ice\triggq.c">
</File>
<File
RelativePath="..\..\src\ice\util.c">
</File>
</Filter>
<Filter
Name="jbuf"
Filter="">
<File
RelativePath="..\..\src\jbuf\jbuf.c">
</File>
<File
RelativePath="..\..\src\jbuf\mod.mk">
</File>
</Filter>
<Filter
Name="list"
Filter="">
<File
RelativePath="..\..\src\list\list.c">
</File>
<File
RelativePath="..\..\src\list\mod.mk">
</File>
</Filter>
<Filter
Name="lock"
Filter="">
<File
RelativePath="..\..\src\lock\win32\lock.c">
</File>
</Filter>
<Filter
Name="main"
Filter="">
<File
RelativePath="..\..\src\main\init.c">
</File>
<File
RelativePath="..\..\src\main\main.c">
</File>
<File
RelativePath="..\..\src\main\main.h">
</File>
<File
RelativePath="..\..\src\main\method.c">
</File>
<File
RelativePath="..\..\src\main\mod.mk">
</File>
<File
RelativePath="..\..\src\main\symbian">
</File>
</Filter>
<Filter
Name="mbuf"
Filter="">
<File
RelativePath="..\..\src\mbuf\mbuf.c">
</File>
</Filter>
<Filter
Name="md5"
Filter="">
<File
RelativePath="..\..\src\md5\md5.c">
</File>
<File
RelativePath="..\..\src\md5\md5.h">
</File>
<File
RelativePath="..\..\src\md5\wrap.c">
</File>
</Filter>
<Filter
Name="mem"
Filter="">
<File
RelativePath="..\..\src\mem\mem.c">
</File>
</Filter>
<Filter
Name="mod"
Filter="">
<File
RelativePath="..\..\src\mod\win32\dll.c">
</File>
<File
RelativePath="..\..\src\mod\mod.c">
</File>
<File
RelativePath="..\..\src\mod\mod_internal.h">
</File>
</Filter>
<Filter
Name="natbd"
Filter="">
<File
RelativePath="..\..\src\natbd\filtering.c">
</File>
<File
RelativePath="..\..\src\natbd\genalg.c">
</File>
<File
RelativePath="..\..\src\natbd\hairpinning.c">
</File>
<File
RelativePath="..\..\src\natbd\lifetime.c">
</File>
<File
RelativePath="..\..\src\natbd\mapping.c">
</File>
<File
RelativePath="..\..\src\natbd\natstr.c">
</File>
</Filter>
<Filter
Name="net"
Filter="">
<File
RelativePath="..\..\src\net\if.c">
</File>
<File
RelativePath="..\..\src\net\net.c">
</File>
<File
RelativePath="..\..\src\net\netstr.c">
</File>
<File
RelativePath="..\..\src\net\rt.c">
</File>
<File
RelativePath="..\..\src\net\sock.c">
</File>
<File
RelativePath="..\..\src\net\sockopt.c">
</File>
<File
RelativePath="..\..\src\net\win32\wif.c">
</File>
</Filter>
<Filter
Name="rtp"
Filter="">
<File
RelativePath="..\..\src\rtp\fb.c">
</File>
<File
RelativePath="..\..\src\rtp\member.c">
</File>
<File
RelativePath="..\..\src\rtp\ntp.c">
</File>
<File
RelativePath="..\..\src\rtp\pkt.c">
</File>
<File
RelativePath="..\..\src\rtp\rr.c">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)/$(InputName)1.obj"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)/$(InputName)1.obj"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\rtp\rtcp.c">
</File>
<File
RelativePath="..\..\src\rtp\rtp.c">
</File>
<File
RelativePath="..\..\src\rtp\sdes.c">
</File>
<File
RelativePath="..\..\src\rtp\sess.c">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)/$(InputName)1.obj"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)/$(InputName)1.obj"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\rtp\source.c">
</File>
</Filter>
<Filter
Name="sa"
Filter="">
<File
RelativePath="..\..\src\sa\ntop.c">
</File>
<File
RelativePath="..\..\src\sa\pton.c">
</File>
<File
RelativePath="..\..\src\sa\sa.c">
</File>
<File
RelativePath="..\..\src\sa\sa.h">
</File>
</Filter>
<Filter
Name="sdp"
Filter="">
<File
RelativePath="..\..\src\sdp\attr.c">
</File>
<File
RelativePath="..\..\src\sdp\format.c">
</File>
<File
RelativePath="..\..\src\sdp\media.c">
</File>
<File
RelativePath="..\..\src\sdp\msg.c">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)/$(InputName)2.obj"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)/$(InputName)2.obj"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\sdp\session.c">
</File>
<File
RelativePath="..\..\src\sdp\str.c">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)/$(InputName)1.obj"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)/$(InputName)1.obj"/>
</FileConfiguration>
</File>
</Filter>
<Filter
Name="sha"
Filter="">
<File
RelativePath="..\..\src\sha\sha1.c">
</File>
</Filter>
<Filter
Name="sip"
Filter="">
<File
RelativePath="..\..\src\sip\addr.c">
</File>
<File
RelativePath="..\..\src\sip\auth.c">
</File>
<File
RelativePath="..\..\src\sip\cseq.c">
</File>
<File
RelativePath="..\..\src\sip\ctrans.c">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)/$(InputName)1.obj"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)/$(InputName)1.obj"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\sip\dialog.c">
</File>
<File
RelativePath="..\..\src\sip\msg.c">
</File>
<File
RelativePath="..\..\src\sip\param.c">
</File>
<File
RelativePath="..\..\src\sip\reply.c">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)/$(InputName)1.obj"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)/$(InputName)1.obj"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\sip\request.c">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)/$(InputName)1.obj"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)/$(InputName)1.obj"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\sip\sip.c">
</File>
<File
RelativePath="..\..\src\sip\strans.c">
</File>
<File
RelativePath="..\..\src\sip\transp.c">
</File>
<File
RelativePath="..\..\src\sip\via.c">
</File>
</Filter>
<Filter
Name="sipreg"
Filter="">
<File
RelativePath="..\..\src\sipreg\reg.c">
</File>
</Filter>
<Filter
Name="sipsess"
Filter="">
<File
RelativePath="..\..\src\sipsess\accept.c">
</File>
<File
RelativePath="..\..\src\sipsess\ack.c">
</File>
<File
RelativePath="..\..\src\sipsess\close.c">
</File>
<File
RelativePath="..\..\src\sipsess\connect.c">
</File>
<File
RelativePath="..\..\src\sipsess\info.c">
</File>
<File
RelativePath="..\..\src\sipsess\listen.c">
</File>
<File
RelativePath="..\..\src\sipsess\modify.c">
</File>
<File
RelativePath="..\..\src\sipsess\reply.c">
</File>
<File
RelativePath="..\..\src\sipsess\request.c">
</File>
<File
RelativePath="..\..\src\sipsess\sess.c">
</File>
</Filter>
<Filter
Name="stun"
Filter="">
<File
RelativePath="..\..\src\stun\addr.c">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)/$(InputName)1.obj"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)/$(InputName)1.obj"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\stun\attr.c">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)/$(InputName)1.obj"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)/$(InputName)1.obj"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\stun\ctrans.c">
</File>
<File
RelativePath="..\..\src\stun\dnsdisc.c">
</File>
<File
RelativePath="..\..\src\stun\hdr.c">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)/$(InputName)1.obj"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)/$(InputName)1.obj"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\stun\ind.c">
</File>
<File
RelativePath="..\..\src\stun\keepalive.c">
</File>
<File
RelativePath="..\..\src\stun\msg.c">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)/$(InputName)1.obj"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)/$(InputName)1.obj"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\stun\rep.c">
</File>
<File
RelativePath="..\..\src\stun\req.c">
</File>
<File
RelativePath="..\..\src\stun\stun.c">
</File>
<File
RelativePath="..\..\src\stun\stunstr.c">
</File>
</Filter>
<Filter
Name="sys"
Filter="">
<File
RelativePath="..\..\src\sys\daemon.c">
</File>
<File
RelativePath="..\..\src\sys\endian.c">
</File>
<File
RelativePath="..\..\src\sys\rand.c">
</File>
<File
RelativePath="..\..\src\sys\sys.c">
</File>
</Filter>
<Filter
Name="tcp"
Filter="">
<File
RelativePath="..\..\src\tcp\tcp.c">
</File>
<File
RelativePath="..\..\src\tcp\tcp_high.c">
</File>
</Filter>
<Filter
Name="tmr"
Filter="">
<File
RelativePath="..\..\src\tmr\tmr.c">
</File>
</Filter>
<Filter
Name="turn"
Filter="">
<File
RelativePath="..\..\src\turn\chan.c">
</File>
<File
RelativePath="..\..\src\turn\perm.c">
</File>
<File
RelativePath="..\..\src\turn\turnc.c">
</File>
</Filter>
<Filter
Name="udp"
Filter="">
<File
RelativePath="..\..\src\udp\udp.c">
</File>
</Filter>
<Filter
Name="uri"
Filter="">
<File
RelativePath="..\..\src\uri\ucmp.c">
</File>
<File
RelativePath="..\..\src\uri\uri.c">
</File>
<File
RelativePath="..\..\src\uri\uric.c">
</File>
</Filter>
<Filter
Name="telev"
Filter="">
<File
RelativePath="..\..\src\telev\telev.c">
</File>
</Filter>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

61
rpm/re.spec Normal file
View file

@ -0,0 +1,61 @@
%define name re
%define ver 0.1.0
%define rel 3
Summary: Generic library for real-time communications with async IO support
Name: %name
Version: %ver
Release: %rel
License: BSD
Group: Applications/Devel
Source0: file://%{name}-%{version}.tar.gz
URL: http://www.creytiv.com/
Vendor: Creytiv
Packager: Alfred E. Heggestad <aeh@db.org>
BuildRoot: /var/tmp/%{name}-build-root
%description
Generic library for real-time communications with async IO support
%package devel
Summary: libre development files
Group: Development/Libraries
Requires: %{name} = %{version}
%description devel
libre development files.
%prep
%setup
%build
make RELEASE=1
%install
rm -rf $RPM_BUILD_ROOT
make DESTDIR=$RPM_BUILD_ROOT install \
%ifarch x86_64
LIBDIR=/usr/lib64
%endif
%clean
rm -rf $RPM_BUILD_ROOT
%post -p /sbin/ldconfig
%postun -p /sbin/ldconfig
%files
%defattr(644,root,root,755)
%attr(755,root,root) %{_libdir}/libre*.so*
%files devel
%defattr(644,root,root,755)
%{_includedir}/re/*.h
/usr/share/re/re.mk
%{_libdir}/libre*.a
%changelog
* Fri Nov 5 2010 Alfred E. Heggestad <aeh@db.org> -
- Initial build.

126
src/base64/b64.c Normal file
View file

@ -0,0 +1,126 @@
/**
* @file b64.c Base64 encoding/decoding functions
*
* Copyright (C) 2010 Creytiv.com
*/
#include <re_types.h>
#include <re_base64.h>
static const char b64_table[65] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
/**
* Base-64 encode a buffer
*
* @param in Input buffer
* @param ilen Length of input buffer
* @param out Output buffer
* @param olen Size of output buffer, actual written on return
*
* @return 0 if success, otherwise errorcode
*/
int base64_encode(const uint8_t *in, size_t ilen, char *out, size_t *olen)
{
const uint8_t *in_end = in + ilen;
const char *o = out;
if (!in || !out || !olen)
return EINVAL;
if (*olen < ilen*4/3)
return EOVERFLOW;
for (; in < in_end; ) {
uint32_t v;
int pad = 0;
v = *in++ << 16;
if (in < in_end) {
v |= *in++ << 8;
}
else {
++pad;
}
if (in < in_end) {
v |= *in++ << 0;
}
else {
++pad;
}
*out++ = b64_table[v>>18 & 0x3f];
*out++ = b64_table[v>>12 & 0x3f];
*out++ = (pad >= 2) ? '=' : b64_table[v>>6 & 0x3f];
*out++ = (pad >= 1) ? '=' : b64_table[v>>0 & 0x3f];
}
*olen = out - o;
return 0;
}
/* convert char -> 6-bit value */
static inline uint32_t b64val(char c)
{
if ('A' <= c && c <= 'Z')
return c - 'A' + 0;
else if ('a' <= c && c <= 'z')
return c - 'a' + 26;
else if ('0' <= c && c <= '9')
return c - '0' + 52;
else if ('+' == c)
return 62;
else if ('/' == c)
return 63;
else if ('=' == c)
return 1<<24; /* special trick */
else
return 0;
}
/**
* Decode a Base-64 encoded string
*
* @param in Input buffer
* @param ilen Length of input buffer
* @param out Output buffer
* @param olen Size of output buffer, actual written on return
*
* @return 0 if success, otherwise errorcode
*/
int base64_decode(const char *in, size_t ilen, uint8_t *out, size_t *olen)
{
const char *in_end = in + ilen;
const uint8_t *o = out;
if (!in || !out || !olen)
return EINVAL;
if (*olen < ilen*3/4)
return EOVERFLOW;
for (;in < in_end; ) {
uint32_t v;
v = b64val(*in++) << 18;
v |= b64val(*in++) << 12;
v |= b64val(*in++) << 6;
v |= b64val(*in++) << 0;
*out++ = v>>16;
if (!(v & (1<<30)))
*out++ = (v>>8) & 0xff;
if (!(v & (1<<24)))
*out++ = (v>>0) & 0xff;
}
*olen = out - o;
return 0;
}

5
src/base64/mod.mk Normal file
View file

@ -0,0 +1,5 @@
#
# mod.mk
#
SRCS += base64/b64.c

199
src/conf/conf.c Normal file
View file

@ -0,0 +1,199 @@
/**
* @file conf.c Configuration file parser
*
* Copyright (C) 2010 Creytiv.com
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_IO_H
#include <io.h>
#endif
#include <re_types.h>
#include <re_fmt.h>
#include <re_mem.h>
#include <re_mbuf.h>
#include <re_conf.h>
#ifdef WIN32
#define open _open
#define read _read
#define close _close
#endif
struct conf {
struct mbuf *mb;
};
static int load_file(struct mbuf *mb, const char *filename)
{
int err = 0, fd = open(filename, O_RDONLY);
if (fd < 0)
return errno;
for (;;) {
uint8_t buf[1024];
const ssize_t n = read(fd, (void *)buf, sizeof(buf));
if (n < 0) {
err = errno;
break;
}
else if (n == 0)
break;
err |= mbuf_write_mem(mb, buf, n);
}
(void)close(fd);
return err;
}
static void conf_destructor(void *data)
{
struct conf *conf = data;
mem_deref(conf->mb);
}
int conf_alloc(struct conf **confp, const char *filename)
{
struct conf *conf;
int err = 0;
if (!confp)
return EINVAL;
conf = mem_zalloc(sizeof(*conf), conf_destructor);
if (!conf)
return ENOMEM;
conf->mb = mbuf_alloc(1024);
if (!conf->mb) {
err = ENOMEM;
goto out;
}
err |= mbuf_write_u8(conf->mb, '\n');
if (filename)
err |= load_file(conf->mb, filename);
out:
if (err)
mem_deref(conf);
else
*confp = conf;
return err;
}
int conf_alloc_buf(struct conf **confp, const uint8_t *buf, size_t sz)
{
struct conf *conf;
int err;
err = conf_alloc(&conf, NULL);
if (err)
return err;
err = mbuf_write_mem(conf->mb, buf, sz);
if (err)
mem_deref(conf);
else
*confp = conf;
return err;
}
int conf_get(struct conf *conf, const char *name, struct pl *pl)
{
char expr[512];
struct pl spl;
if (!conf || !name || !pl)
return EINVAL;
spl.p = (const char *)conf->mb->buf;
spl.l = conf->mb->end;
(void)re_snprintf(expr, sizeof(expr),
"[\r\n]+[ \t]*%s[ \t]+[~ \t\r\n]+", name);
return re_regex(spl.p, spl.l, expr, NULL, NULL, NULL, pl);
}
int conf_get_str(struct conf *conf, const char *name, char *str,
size_t size)
{
struct pl pl;
int err;
if (!conf || !name || !str || !size)
return EINVAL;
err = conf_get(conf, name, &pl);
if (err)
return err;
return pl_strcpy(&pl, str, size);
}
int conf_get_u32(struct conf *conf, const char *name, uint32_t *num)
{
struct pl pl;
int err;
if (!conf || !name || !num)
return EINVAL;
err = conf_get(conf, name, &pl);
if (err)
return err;
*num = pl_u32(&pl);
return 0;
}
int conf_apply(struct conf *conf, const char *name, conf_h *ch, void *arg)
{
char expr[512];
struct pl pl, val;
int err = 0;
if (!conf || !name || !ch)
return EINVAL;
pl.p = (const char *)conf->mb->buf;
pl.l = conf->mb->end;
(void)re_snprintf(expr, sizeof(expr),
"[\r\n]+[ \t]*%s[ \t]+[~ \t\r\n]+", name);
while (!re_regex(pl.p, pl.l, expr, NULL, NULL, NULL, &val)) {
err = ch(&val, arg);
if (err)
break;
pl.l -= val.p + val.l - pl.p;
pl.p = val.p + val.l;
}
return err;
}

5
src/conf/mod.mk Normal file
View file

@ -0,0 +1,5 @@
#
# mod.mk
#
SRCS += conf/conf.c

109
src/crc32/crc32.c Normal file
View file

@ -0,0 +1,109 @@
/*-
* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
* code or tables extracted from it, as desired without restriction.
*/
/*
* First, the polynomial itself and its table of feedback terms. The
* polynomial is
* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
*
* Note that we take it "backwards" and put the highest-order term in
* the lowest-order bit. The X^32 term is "implied"; the LSB is the
* X^31 term, etc. The X^0 term (usually shown as "+1") results in
* the MSB being 1
*
* Note that the usual hardware shift register implementation, which
* is what we're using (we're merely optimizing it by doing eight-bit
* chunks at a time) shifts bits into the lowest-order term. In our
* implementation, that means shifting towards the right. Why do we
* do it this way? Because the calculated CRC must be transmitted in
* order from highest-order term to lowest-order term. UARTs transmit
* characters in order from LSB to MSB. By storing the CRC this way
* we hand it to the UART in the order low-byte to high-byte; the UART
* sends each low-bit to hight-bit; and the result is transmission bit
* by bit from highest- to lowest-order term without requiring any bit
* shuffling on our part. Reception works similarly
*
* The feedback terms table consists of 256, 32-bit entries. Notes
*
* The table can be generated at runtime if desired; code to do so
* is shown later. It might not be obvious, but the feedback
* terms simply represent the results of eight shift/xor opera
* tions for all combinations of data and CRC register values
*
* The values must be right-shifted by eight bits by the "updcrc
* logic; the shift must be unsigned (bring in zeroes). On some
* hardware you could probably optimize the shift in assembler by
* using byte-swap instructions
* polynomial $edb88320
*
*
* CRC32 code derived from work by Gary S. Brown.
*/
#include <re_types.h>
#include <re_crc32.h>
static const uint32_t crc32_tab[] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
/**
* A function that calculates the CRC-32 based on the table above is
* given below for documentation purposes. An equivalent implementation
* of this function that's actually used in the kernel can be found
* in sys/libkern.h, where it can be inlined.
*/
uint32_t crc32(uint32_t crc, const void *buf, uint32_t size)
{
const uint8_t *p = buf;
crc = ~crc;
while (size--)
crc = crc32_tab[(crc ^ *p++) & 0xff] ^ (crc >> 8);
return crc ^ ~0U;
}

7
src/crc32/mod.mk Normal file
View file

@ -0,0 +1,7 @@
#
# mod.mk
#
ifeq ($(USE_ZLIB),)
SRCS += crc32/crc32.c
endif

326
src/dbg/dbg.c Normal file
View file

@ -0,0 +1,326 @@
/**
* @file dbg.c Debug printing
*
* Copyright (C) 2010 Creytiv.com
*/
#include <stdio.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_PTHREAD
#include <stdlib.h>
#include <pthread.h>
#endif
#include <time.h>
#include <re_types.h>
#include <re_fmt.h>
#include <re_list.h>
#include <re_tmr.h>
#define DEBUG_MODULE "dbg"
#define DEBUG_LEVEL 0
#include <re_dbg.h>
/** Debug configuration */
static struct {
uint64_t tick; /**< Init ticks */
int level; /**< Current debug level */
enum dbg_flags flags; /**< Debug flags */
dbg_print_h *ph; /**< Optional print handler */
void *arg; /**< Handler argument */
FILE *f; /**< Logfile */
#ifdef HAVE_PTHREAD
pthread_mutex_t mutex; /**< Thread locking */
#endif
} dbg = {
0,
DBG_INFO,
DBG_ANSI,
NULL,
NULL,
NULL,
#ifdef HAVE_PTHREAD
PTHREAD_MUTEX_INITIALIZER,
#endif
};
#ifdef HAVE_PTHREAD
static inline void dbg_lock(void)
{
pthread_mutex_lock(&dbg.mutex);
}
static inline void dbg_unlock(void)
{
pthread_mutex_unlock(&dbg.mutex);
}
#else
#define dbg_lock() /**< Stub */
#define dbg_unlock() /**< Stub */
#endif
/**
* Initialise debug printing
*
* @param level Debug level
* @param flags Debug flags
*/
void dbg_init(int level, enum dbg_flags flags)
{
dbg.tick = tmr_jiffies();
dbg.level = level;
dbg.flags = flags;
}
/**
* Close debugging
*/
void dbg_close(void)
{
if (dbg.f) {
(void)fclose(dbg.f);
dbg.f = NULL;
}
}
/**
* Set debug logfile
*
* @param name Name of the logfile, NULL to close
*
* @return 0 if success, otherwise errorcode
*/
int dbg_logfile_set(const char *name)
{
time_t t;
dbg_close();
if (!name)
return 0;
dbg.f = fopen(name, "a+");
if (!dbg.f)
return errno;
(void)time(&t);
(void)re_fprintf(dbg.f, "\n===== Log Started: %s", ctime(&t));
(void)fflush(dbg.f);
return 0;
}
/**
* Set optional debug print handler
*
* @param ph Print handler
* @param arg Handler argument
*/
void dbg_handler_set(dbg_print_h *ph, void *arg)
{
dbg.ph = ph;
dbg.arg = arg;
}
/* NOTE: This function should not allocate memory */
static void dbg_vprintf(int level, const char *fmt, va_list ap)
{
if (level > dbg.level)
return;
/* Print handler? */
if (dbg.ph)
return;
dbg_lock();
if (dbg.flags & DBG_ANSI) {
switch (level) {
case DBG_WARNING:
(void)re_fprintf(stderr, "\x1b[31m"); /* Red */
break;
case DBG_NOTICE:
(void)re_fprintf(stderr, "\x1b[33m"); /* Yellow */
break;
case DBG_INFO:
(void)re_fprintf(stderr, "\x1b[32m"); /* Green */
break;
default:
break;
}
}
if (dbg.flags & DBG_TIME) {
const uint64_t ticks = tmr_jiffies();
if (0 == dbg.tick)
dbg.tick = tmr_jiffies();
(void)re_fprintf(stderr, "[%09llu] ", ticks - dbg.tick);
}
(void)re_vfprintf(stderr, fmt, ap);
if (dbg.flags & DBG_ANSI && level < DBG_DEBUG)
(void)re_fprintf(stderr, "\x1b[;m");
dbg_unlock();
}
/* Formatted output to print handler and/or logfile */
static void dbg_fmt_vprintf(int level, const char *fmt, va_list ap)
{
char buf[256];
int len;
if (level > dbg.level)
return;
if (!dbg.ph && !dbg.f)
return;
dbg_lock();
len = re_vsnprintf(buf, sizeof(buf), fmt, ap);
if (len <= 0)
goto out;
/* Print handler? */
if (dbg.ph) {
dbg.ph(level, buf, len, dbg.arg);
}
/* Output to file */
if (dbg.f) {
(void)fwrite(buf, 1, len, dbg.f);
(void)fflush(dbg.f);
}
out:
dbg_unlock();
}
/**
* Print a formatted debug message
*
* @param level Debug level
* @param fmt Formatted string
*/
void dbg_printf(int level, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
dbg_vprintf(level, fmt, ap);
va_end(ap);
va_start(ap, fmt);
dbg_fmt_vprintf(level, fmt, ap);
va_end(ap);
}
/**
* Print a formatted debug message to /dev/null
*
* @param fmt Formatted string
*/
void dbg_noprintf(const char *fmt, ...)
{
(void)fmt;
}
/**
* Print a formatted warning message
*
* @param fmt Formatted string
*/
void dbg_warning(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
dbg_vprintf(DBG_WARNING, fmt, ap);
va_end(ap);
va_start(ap, fmt);
dbg_fmt_vprintf(DBG_WARNING, fmt, ap);
va_end(ap);
}
/**
* Print a formatted notice message
*
* @param fmt Formatted string
*/
void dbg_notice(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
dbg_vprintf(DBG_NOTICE, fmt, ap);
va_end(ap);
va_start(ap, fmt);
dbg_fmt_vprintf(DBG_NOTICE, fmt, ap);
va_end(ap);
}
/**
* Print a formatted info message
*
* @param fmt Formatted string
*/
void dbg_info(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
dbg_vprintf(DBG_INFO, fmt, ap);
va_end(ap);
va_start(ap, fmt);
dbg_fmt_vprintf(DBG_INFO, fmt, ap);
va_end(ap);
}
/**
* Get the name of the debug level
*
* @param level Debug level
*
* @return String with debug level name
*/
const char *dbg_level_str(int level)
{
switch (level) {
case DBG_EMERG: return "EMERGENCY";
case DBG_ALERT: return "ALERT";
case DBG_CRIT: return "CRITICAL";
case DBG_ERR: return "ERROR";
case DBG_WARNING: return "WARNING";
case DBG_NOTICE: return "NOTICE";
case DBG_INFO: return "INFO";
case DBG_DEBUG: return "DEBUG";
default: return "???";
}
}

6
src/dbg/mod.mk Normal file
View file

@ -0,0 +1,6 @@
#
# mod.mk
#
SRCS += dbg/dbg.c

853
src/dns/client.c Normal file
View file

@ -0,0 +1,853 @@
/**
* @file client.c DNS Client
*
* Copyright (C) 2010 Creytiv.com
*/
#include <string.h>
#include <re_types.h>
#include <re_fmt.h>
#include <re_mem.h>
#include <re_mbuf.h>
#include <re_list.h>
#include <re_hash.h>
#include <re_tmr.h>
#include <re_sa.h>
#include <re_udp.h>
#include <re_tcp.h>
#include <re_sys.h>
#include <re_dns.h>
#define DEBUG_MODULE "dnsc"
#define DEBUG_LEVEL 5
#include <re_dbg.h>
enum {
NTX_MAX = 20,
QUERY_HASH_SIZE = 16,
TCP_HASH_SIZE = 2,
CONN_TIMEOUT = 10 * 1000,
IDLE_TIMEOUT = 30 * 1000,
};
struct tcpconn {
struct le le;
struct list ql;
struct tmr tmr;
struct sa srv;
struct tcp_conn *conn;
struct mbuf *mb;
bool connected;
uint16_t flen;
struct dnsc *dnsc; /* parent */
};
struct dns_query {
struct le le;
struct le le_tc;
struct tmr tmr;
struct mbuf mb;
struct list rrlv[3];
char *name;
const struct sa *srvv;
const uint32_t *srvc;
struct tcpconn *tc;
struct dnsc *dnsc; /* parent */
struct dns_query **qp; /* app ref */
uint32_t ntx;
uint16_t id;
uint16_t type;
uint16_t dnsclass;
uint8_t opcode;
dns_query_h *qh;
void *arg;
};
struct dnsquery {
struct dnshdr hdr;
char *name;
uint16_t type;
uint16_t dnsclass;
};
struct dnsc {
struct dnsc_conf conf;
struct hash *ht_query;
struct hash *ht_tcpconn;
struct udp_sock *us;
struct sa *srvv;
uint32_t srvc;
};
static const struct dnsc_conf default_conf = {
QUERY_HASH_SIZE,
TCP_HASH_SIZE,
CONN_TIMEOUT,
IDLE_TIMEOUT,
false
};
static void tcpconn_close(struct tcpconn *tc, int err);
static int send_tcp(struct dns_query *q);
static void udp_timeout_handler(void *arg);
static bool rr_unlink_handler(struct le *le, void *arg)
{
struct dnsrr *rr = le->data;
(void)arg;
list_unlink(&rr->le_priv);
mem_deref(rr);
return false;
}
static void query_abort(struct dns_query *q)
{
if (q->tc) {
list_unlink(&q->le_tc);
q->tc = mem_deref(q->tc);
}
tmr_cancel(&q->tmr);
hash_unlink(&q->le);
}
static void query_destructor(void *data)
{
struct dns_query *q = data;
uint32_t i;
query_abort(q);
mbuf_reset(&q->mb);
mem_deref(q->name);
for (i=0; i<ARRAY_SIZE(q->rrlv); i++)
(void)list_apply(&q->rrlv[i], true, rr_unlink_handler, NULL);
}
static void query_handler(struct dns_query *q, int err,
const struct dnshdr *hdr, struct list *ansl,
struct list *authl, struct list *addl)
{
/* deref here - before calling handler */
if (q->qp)
*q->qp = NULL;
/* The handler must only be called _once_ */
if (q->qh) {
q->qh(err, hdr, ansl, authl, addl, q->arg);
q->qh = NULL;
}
/* in case we have more (than one) q refs */
query_abort(q);
}
static bool query_close_handler(struct le *le, void *arg)
{
struct dns_query *q = le->data;
(void)arg;
query_handler(q, ECONNABORTED, NULL, NULL, NULL, NULL);
mem_deref(q);
return false;
}
static bool query_cmp_handler(struct le *le, void *arg)
{
struct dns_query *q = le->data;
struct dnsquery *dq = arg;
if (q->id != dq->hdr.id)
return false;
if (q->opcode != dq->hdr.opcode)
return false;
if (q->type != dq->type)
return false;
if (q->dnsclass != dq->dnsclass)
return false;
if (str_casecmp(q->name, dq->name))
return false;
return true;
}
static int reply_recv(struct dnsc *dnsc, struct mbuf *mb)
{
struct dns_query *q = NULL;
uint32_t i, j, nv[3];
struct dnsquery dq;
int err = 0;
if (!dnsc || !mb)
return EINVAL;
dq.name = NULL;
if (dns_hdr_decode(mb, &dq.hdr) || !dq.hdr.qr) {
err = EBADMSG;
goto out;
}
err = dns_dname_decode(mb, &dq.name, 0);
if (err)
goto out;
if (mbuf_get_left(mb) < 4) {
err = EBADMSG;
goto out;
}
dq.type = ntohs(mbuf_read_u16(mb));
dq.dnsclass = ntohs(mbuf_read_u16(mb));
q = list_ledata(hash_lookup(dnsc->ht_query, hash_joaat_str_ci(dq.name),
query_cmp_handler, &dq));
if (!q) {
err = ENOENT;
goto out;
}
/* try next server */
if (dq.hdr.rcode == DNS_RCODE_SRV_FAIL && q->ntx < *q->srvc) {
if (!q->tc) /* try next UDP server immediately */
tmr_start(&q->tmr, 0, udp_timeout_handler, q);
err = EPROTO;
goto out;
}
nv[0] = dq.hdr.nans;
nv[1] = dq.hdr.nauth;
nv[2] = dq.hdr.nadd;
for (i=0; i<ARRAY_SIZE(nv); i++) {
for (j=0; j<nv[i]; j++) {
struct dnsrr *rr = NULL;
err = dns_rr_decode(mb, &rr, 0);
if (err) {
query_handler(q, err, NULL, NULL, NULL, NULL);
mem_deref(q);
goto out;
}
list_append(&q->rrlv[i], &rr->le_priv, rr);
}
}
if (q->type == DNS_QTYPE_AXFR) {
struct dnsrr *rrh, *rrt;
rrh = list_ledata(list_head(&q->rrlv[0]));
rrt = list_ledata(list_tail(&q->rrlv[0]));
/* Wait for last AXFR reply with terminating SOA record */
if (dq.hdr.rcode == DNS_RCODE_OK && dq.hdr.nans > 0 &&
(!rrt || rrt->type != DNS_TYPE_SOA || rrh == rrt)) {
DEBUG_INFO("waiting for last SOA record in reply\n");
goto out;
}
}
query_handler(q, 0, &dq.hdr, &q->rrlv[0], &q->rrlv[1], &q->rrlv[2]);
mem_deref(q);
out:
mem_deref(dq.name);
return err;
}
static void udp_recv_handler(const struct sa *src, struct mbuf *mb, void *arg)
{
(void)src;
(void)reply_recv(arg, mb);
}
static void tcp_recv_handler(struct mbuf *mbrx, void *arg)
{
struct tcpconn *tc = arg;
struct mbuf *mb = tc->mb;
int err = 0;
size_t n;
next:
/* frame length */
if (!tc->flen) {
n = min(2 - mb->end, mbuf_get_left(mbrx));
err = mbuf_write_mem(mb, mbuf_buf(mbrx), n);
if (err)
goto error;
mbrx->pos += n;
if (mb->end < 2)
return;
mb->pos = 0;
tc->flen = ntohs(mbuf_read_u16(mb));
mb->pos = 0;
mb->end = 0;
}
/* content */
n = min(tc->flen - mb->end, mbuf_get_left(mbrx));
err = mbuf_write_mem(mb, mbuf_buf(mbrx), n);
if (err)
goto error;
mbrx->pos += n;
if (mb->end < tc->flen)
return;
mb->pos = 0;
err = reply_recv(tc->dnsc, mb);
if (err)
goto error;
/* reset tcp buffer */
tc->flen = 0;
mb->pos = 0;
mb->end = 0;
/* more data ? */
if (mbuf_get_left(mbrx) > 0) {
DEBUG_INFO("%u bytes of tcp data left\n", mbuf_get_left(mbrx));
goto next;
}
return;
error:
tcpconn_close(tc, err);
}
static void tcpconn_timeout_handler(void *arg)
{
struct tcpconn *tc = arg;
DEBUG_NOTICE("tcp (%J) %s timeout \n", &tc->srv,
tc->connected ? "idle" : "connect");
tcpconn_close(tc, ETIMEDOUT);
}
static void tcp_estab_handler(void *arg)
{
struct tcpconn *tc = arg;
struct le *le = list_head(&tc->ql);
int err = 0;
DEBUG_INFO("connection (%J) established\n", &tc->srv);
while (le) {
struct dns_query *q = le->data;
le = le->next;
q->mb.pos = 0;
err = tcp_send(tc->conn, &q->mb);
if (err)
break;
DEBUG_INFO("tcp send %J\n", &tc->srv);
}
if (err) {
tcpconn_close(tc, err);
return;
}
tmr_start(&tc->tmr, tc->dnsc->conf.idle_timeout,
tcpconn_timeout_handler, tc);
tc->connected = true;
}
static void tcp_close_handler(int err, void *arg)
{
struct tcpconn *tc = arg;
DEBUG_NOTICE("connection (%J) closed: %s\n", &tc->srv, strerror(err));
tcpconn_close(tc, err);
}
static bool tcpconn_cmp_handler(struct le *le, void *arg)
{
const struct tcpconn *tc = le->data;
/* avoid trying this connection if dead */
if (!tc->conn)
return false;
return sa_cmp(&tc->srv, arg, SA_ALL);
}
static bool tcpconn_fail_handler(struct le *le, void *arg)
{
struct dns_query *q = le->data;
int err = *((int *)arg);
list_unlink(&q->le_tc);
q->tc = mem_deref(q->tc);
if (q->ntx >= *q->srvc) {
DEBUG_WARNING("all servers failed, giving up!!\n");
err = err ? err : ECONNREFUSED;
goto out;
}
/* try next server(s) */
err = send_tcp(q);
if (err) {
DEBUG_WARNING("all servers failed, giving up\n");
goto out;
}
out:
if (err) {
query_handler(q, err, NULL, NULL, NULL, NULL);
mem_deref(q);
}
return false;
}
static void tcpconn_close(struct tcpconn *tc, int err)
{
if (!tc)
return;
/* avoid trying this connection again (e.g. same address) */
tc->conn = mem_deref(tc->conn);
(void)list_apply(&tc->ql, true, tcpconn_fail_handler, &err);
mem_deref(tc);
}
static void tcpconn_destructor(void *arg)
{
struct tcpconn *tc = arg;
hash_unlink(&tc->le);
tmr_cancel(&tc->tmr);
mem_deref(tc->conn);
mem_deref(tc->mb);
}
static int tcpconn_alloc(struct tcpconn **tcpp, struct dnsc *dnsc,
const struct sa *srv)
{
struct tcpconn *tc;
int err = ENOMEM;
if (!tcpp || !dnsc || !srv)
return EINVAL;
tc = mem_zalloc(sizeof(struct tcpconn), tcpconn_destructor);
if (!tc)
goto out;
hash_append(dnsc->ht_tcpconn, sa_hash(srv, SA_ALL), &tc->le, tc);
tc->srv = *srv;
tc->dnsc = dnsc;
tc->mb = mbuf_alloc(1500);
if (!tc->mb)
goto out;
err = tcp_connect(&tc->conn, srv, tcp_estab_handler,
tcp_recv_handler, tcp_close_handler, tc);
if (err)
goto out;
tmr_start(&tc->tmr, tc->dnsc->conf.conn_timeout,
tcpconn_timeout_handler, tc);
out:
if (err)
mem_deref(tc);
else
*tcpp = tc;
return err;
}
static int send_tcp(struct dns_query *q)
{
const struct sa *srv;
struct tcpconn *tc;
int err = 0;
if (!q)
return EINVAL;
while (q->ntx < *q->srvc) {
srv = &q->srvv[q->ntx++];
DEBUG_NOTICE("trying tcp server#%u: %J\n", q->ntx-1, srv);
tc = list_ledata(hash_lookup(q->dnsc->ht_tcpconn,
sa_hash(srv, SA_ALL),
tcpconn_cmp_handler,
(void *)srv));
if (!tc) {
err = tcpconn_alloc(&tc, q->dnsc, srv);
if (err)
continue;
}
if (tc->connected) {
q->mb.pos = 0;
err = tcp_send(tc->conn, &q->mb);
if (err) {
tcpconn_close(tc, err);
continue;
}
tmr_start(&tc->tmr, tc->dnsc->conf.idle_timeout,
tcpconn_timeout_handler, tc);
DEBUG_NOTICE("tcp send %J\n", srv);
}
list_append(&tc->ql, &q->le_tc, q);
q->tc = mem_ref(tc);
break;
}
return err;
}
static void tcp_timeout_handler(void *arg)
{
struct dns_query *q = arg;
query_handler(q, ETIMEDOUT, NULL, NULL, NULL, NULL);
mem_deref(q);
}
static int send_udp(struct dns_query *q)
{
const struct sa *srv;
int err = ETIMEDOUT;
uint32_t i;
if (!q)
return EINVAL;
for (i=0; i<*q->srvc; i++) {
srv = &q->srvv[q->ntx++%*q->srvc];
DEBUG_INFO("trying udp server#%u: %J\n", i, srv);
q->mb.pos = 0;
err = udp_send(q->dnsc->us, srv, &q->mb);
if (!err)
break;
}
return err;
}
static void udp_timeout_handler(void *arg)
{
struct dns_query *q = arg;
int err = ETIMEDOUT;
if (q->ntx >= NTX_MAX)
goto out;
err = send_udp(q);
if (err)
goto out;
tmr_start(&q->tmr, 1000<<MIN(2, q->ntx - 2),
udp_timeout_handler, q);
out:
if (err) {
query_handler(q, err, NULL, NULL, NULL, NULL);
mem_deref(q);
}
}
static int query(struct dns_query **qp, struct dnsc *dnsc, uint8_t opcode,
const char *name, uint16_t type, uint16_t dnsclass,
const struct dnsrr *ans_rr, int proto,
const struct sa *srvv, const uint32_t *srvc,
bool aa, bool rd, dns_query_h *qh, void *arg)
{
struct dns_query *q = NULL;
struct dnshdr hdr;
int err = 0;
uint32_t i;
if (!dnsc || !name || !srvv || !srvc || !(*srvc))
return EINVAL;
if (DNS_QTYPE_AXFR == type)
proto = IPPROTO_TCP;
q = mem_zalloc(sizeof(*q), query_destructor);
if (!q)
goto nmerr;
hash_append(dnsc->ht_query, hash_joaat_str_ci(name), &q->le, q);
tmr_init(&q->tmr);
mbuf_init(&q->mb);
for (i=0; i<ARRAY_SIZE(q->rrlv); i++)
list_init(&q->rrlv[i]);
err = str_dup(&q->name, name);
if (err)
goto error;
q->srvv = srvv;
q->srvc = srvc;
q->id = rand_u16();
q->type = type;
q->opcode = opcode;
q->dnsclass = dnsclass;
q->dnsc = dnsc;
memset(&hdr, 0, sizeof(hdr));
hdr.id = q->id;
hdr.opcode = q->opcode;
hdr.aa = aa;
hdr.rd = rd;
hdr.nq = 1;
hdr.nans = ans_rr ? 1 : 0;
if (proto == IPPROTO_TCP)
q->mb.pos += 2;
err = dns_hdr_encode(&q->mb, &hdr);
if (err)
goto error;
err = dns_dname_encode(&q->mb, name, NULL, 0, false);
if (err)
goto error;
err |= mbuf_write_u16(&q->mb, htons(type));
err |= mbuf_write_u16(&q->mb, htons(dnsclass));
if (err)
goto error;
if (ans_rr) {
err = dns_rr_encode(&q->mb, ans_rr, 0, NULL, 0);
if (err)
goto error;
}
q->qh = qh;
q->arg = arg;
switch (proto) {
case IPPROTO_TCP:
q->mb.pos = 0;
(void)mbuf_write_u16(&q->mb, htons(q->mb.end - 2));
err = send_tcp(q);
if (err)
goto error;
tmr_start(&q->tmr, 60 * 1000, tcp_timeout_handler, q);
break;
case IPPROTO_UDP:
err = send_udp(q);
if (err)
goto error;
tmr_start(&q->tmr, 500, udp_timeout_handler, q);
break;
default:
err = EPROTONOSUPPORT;
goto error;
}
if (qp) {
q->qp = qp;
*qp = q;
}
return 0;
nmerr:
err = ENOMEM;
error:
mem_deref(q);
return err;
}
int dnsc_query(struct dns_query **qp, struct dnsc *dnsc, const char *name,
uint16_t type, uint16_t dnsclass,
bool rd, dns_query_h *qh, void *arg)
{
if (!dnsc)
return EINVAL;
return query(qp, dnsc, DNS_OPCODE_QUERY, name, type, dnsclass, NULL,
IPPROTO_UDP, dnsc->srvv, &dnsc->srvc, false, rd, qh, arg);
}
int dnsc_query_srv(struct dns_query **qp, struct dnsc *dnsc, const char *name,
uint16_t type, uint16_t dnsclass, int proto,
const struct sa *srvv, const uint32_t *srvc,
bool rd, dns_query_h *qh, void *arg)
{
return query(qp, dnsc, DNS_OPCODE_QUERY, name, type, dnsclass,
NULL, proto, srvv, srvc, false, rd, qh, arg);
}
int dnsc_notify(struct dns_query **qp, struct dnsc *dnsc, const char *name,
uint16_t type, uint16_t dnsclass, const struct dnsrr *ans_rr,
int proto, const struct sa *srvv, const uint32_t *srvc,
dns_query_h *qh, void *arg)
{
return query(qp, dnsc, DNS_OPCODE_NOTIFY, name, type, dnsclass,
ans_rr, proto, srvv, srvc, true, false, qh, arg);
}
static void dnsc_destructor(void *data)
{
struct dnsc *dnsc = data;
(void)hash_apply(dnsc->ht_query, query_close_handler, NULL);
hash_flush(dnsc->ht_tcpconn);
mem_deref(dnsc->ht_tcpconn);
mem_deref(dnsc->ht_query);
mem_deref(dnsc->us);
mem_deref(dnsc->srvv);
}
int dnsc_alloc(struct dnsc **dcpp, const struct dnsc_conf *conf,
const struct sa *srvv, uint32_t srvc)
{
struct dnsc *dnsc;
int err;
if (!dcpp)
return EINVAL;
dnsc = mem_zalloc(sizeof(*dnsc), dnsc_destructor);
if (!dnsc)
return ENOMEM;
if (conf)
dnsc->conf = *conf;
else
dnsc->conf = default_conf;
err = dnsc_srv_set(dnsc, srvv, srvc);
if (err)
goto out;
err = udp_listen(&dnsc->us, NULL, udp_recv_handler, dnsc);
if (err)
goto out;
/* Experimental code:
* Connected UDP sockets will only work if we have one UDP socket
* per UDP server. Connected UDP socket is used to get ICMP
* messages for unreachable DNS Servers.
*/
if (dnsc->conf.udp_conn)
udp_connect(dnsc->us, true);
err = hash_alloc(&dnsc->ht_query, dnsc->conf.query_hash_size);
if (err)
goto out;
err = hash_alloc(&dnsc->ht_tcpconn, dnsc->conf.tcp_hash_size);
if (err)
goto out;
out:
if (err)
mem_deref(dnsc);
else
*dcpp = dnsc;
return err;
}
int dnsc_srv_set(struct dnsc *dnsc, const struct sa *srvv, uint32_t srvc)
{
const size_t sz = srvc * sizeof(*srvv);
struct sa *v = NULL;
if (!dnsc)
return EINVAL;
if (srvv && srvc) {
v = mem_alloc(sz, NULL);
if (!v)
return ENOMEM;
memcpy(v, srvv, sz);
}
dnsc->srvv = mem_deref(dnsc->srvv);
dnsc->srvv = v;
dnsc->srvc = srvc;
return 0;
}

45
src/dns/cstr.c Normal file
View file

@ -0,0 +1,45 @@
/**
* @file cstr.c DNS character strings encoding
*
* Copyright (C) 2010 Creytiv.com
*/
#include <string.h>
#include <re_types.h>
#include <re_fmt.h>
#include <re_list.h>
#include <re_mem.h>
#include <re_mbuf.h>
#include <re_dns.h>
int dns_cstr_encode(struct mbuf *mb, const char *str)
{
uint8_t len;
int err = 0;
if (!mb || !str)
return EINVAL;
len = (uint8_t)strlen(str);
err |= mbuf_write_u8(mb, len);
err |= mbuf_write_mem(mb, (const uint8_t *)str, len);
return err;
}
int dns_cstr_decode(struct mbuf *mb, char **str)
{
uint8_t len;
if (!mb || !str || (mbuf_get_left(mb) < 1))
return EINVAL;
len = mbuf_read_u8(mb);
if (mbuf_get_left(mb) < len)
return EBADMSG;
return mbuf_strdup(mb, str, len);
}

83
src/dns/darwin/srv.c Normal file
View file

@ -0,0 +1,83 @@
/**
* @file darwin/srv.c Get DNS Server IP code for Mac OS X
*
* Copyright (C) 2010 Creytiv.com
*/
#include <re_types.h>
#include <re_fmt.h>
#include <re_mbuf.h>
#include <re_list.h>
#include <re_sa.h>
#include <re_dns.h>
#include "../dns.h"
#define __CF_USE_FRAMEWORK_INCLUDES__
#include <SystemConfiguration/SystemConfiguration.h>
int get_darwin_dns(char *domain, size_t dsize, struct sa *nsv, uint32_t *n)
{
#if TARGET_OS_IPHONE
(void)domain;
(void)dsize;
(void)nsv;
(void)n;
return ENOSYS;
#else
SCDynamicStoreContext context = {0, NULL, NULL, NULL, NULL};
CFArrayRef addresses, domains;
SCDynamicStoreRef store;
CFStringRef key, dom;
CFDictionaryRef dict;
uint32_t c, i;
int err = ENOENT;
if (!nsv || !n)
return EINVAL;
store = SCDynamicStoreCreate(NULL, CFSTR("get_darwin_dns"),
NULL, &context);
if (!store)
return ENOENT;
key = CFSTR("State:/Network/Global/DNS");
dict = SCDynamicStoreCopyValue(store, key);
if (!dict)
goto out1;
addresses = CFDictionaryGetValue(dict, kSCPropNetDNSServerAddresses);
if (!addresses)
goto out;
c = (uint32_t)CFArrayGetCount(addresses);
*n = min(*n, c);
for (i=0; i<*n; i++) {
CFStringRef address = CFArrayGetValueAtIndex(addresses, i);
char str[64];
CFStringGetCString(address, str, sizeof(str),
kCFStringEncodingUTF8);
err = sa_set_str(&nsv[i], str, DNS_PORT);
if (err)
break;
}
domains = CFDictionaryGetValue(dict, kSCPropNetDNSSearchDomains);
if (!domains)
goto out;
if (CFArrayGetCount(domains) < 1)
goto out;
dom = CFArrayGetValueAtIndex(domains, 0);
CFStringGetCString(dom, domain, dsize, kCFStringEncodingUTF8);
out:
CFRelease(dict);
out1:
CFRelease(store);
return err;
#endif
}

195
src/dns/dname.c Normal file
View file

@ -0,0 +1,195 @@
/**
* @file dname.c DNS domain names
*
* Copyright (C) 2010 Creytiv.com
*/
#include <re_types.h>
#include <re_fmt.h>
#include <re_list.h>
#include <re_hash.h>
#include <re_mem.h>
#include <re_mbuf.h>
#include <re_net.h>
#include <re_dns.h>
#define COMP_MASK 0xc0
#define OFFSET_MASK 0x3fff
struct dname {
struct le he;
size_t pos;
char *name;
};
static void destructor(void *arg)
{
struct dname *dn = arg;
hash_unlink(&dn->he);
mem_deref(dn->name);
}
static void dname_append(struct hash *ht_dname, const char *name, size_t pos)
{
struct dname *dn;
if (!ht_dname || pos > OFFSET_MASK || !*name)
return;
dn = mem_zalloc(sizeof(*dn), destructor);
if (!dn)
return;
if (str_dup(&dn->name, name)) {
mem_deref(dn);
return;
}
hash_append(ht_dname, hash_joaat_str_ci(name), &dn->he, dn);
dn->pos = pos;
}
static bool lookup_handler(struct le *le, void *arg)
{
struct dname *dn = le->data;
return 0 == str_casecmp(dn->name, arg);
}
static inline struct dname *dname_lookup(struct hash *ht_dname,
const char *name)
{
return list_ledata(hash_lookup(ht_dname, hash_joaat_str_ci(name),
lookup_handler, (void *)name));
}
static inline int dname_encode_pointer(struct mbuf *mb, size_t pos)
{
return mbuf_write_u16(mb, htons(pos | (COMP_MASK<<8)));
}
int dns_dname_encode(struct mbuf *mb, const char *name,
struct hash *ht_dname, size_t start, bool comp)
{
struct dname *dn;
size_t pos;
int err;
if (!mb || !name)
return EINVAL;
dn = dname_lookup(ht_dname, name);
if (dn && comp)
return dname_encode_pointer(mb, dn->pos);
pos = mb->pos;
if (!dn)
dname_append(ht_dname, name, pos - start);
err = mbuf_write_u8(mb, 0);
if ('.' == name[0] && '\0' == name[1])
return err;
while (err == 0) {
const size_t lablen = mb->pos - pos - 1;
if ('\0' == *name) {
if (!lablen)
break;
mb->buf[pos] = lablen;
err |= mbuf_write_u8(mb, 0);
break;
}
else if ('.' == *name) {
if (!lablen)
return EINVAL;
mb->buf[pos] = lablen;
dn = dname_lookup(ht_dname, name + 1);
if (dn && comp) {
err |= dname_encode_pointer(mb, dn->pos);
break;
}
pos = mb->pos;
if (!dn)
dname_append(ht_dname, name + 1, pos - start);
err |= mbuf_write_u8(mb, 0);
}
else {
err |= mbuf_write_u8(mb, *name);
}
++name;
}
return err;
}
int dns_dname_decode(struct mbuf *mb, char **name, size_t start)
{
bool comp = false;
size_t pos = 0;
char buf[256];
uint32_t i = 0;
if (!mb || !name)
return EINVAL;
while (mbuf_get_left(mb)) {
uint8_t len = mb->buf[mb->pos++];
if (!len) {
if (comp)
mb->pos = pos;
buf[i++] = '\0';
*name = mem_alloc(i, NULL);
if (!*name)
return ENOMEM;
str_ncpy(*name, buf, i);
return 0;
}
else if ((len & COMP_MASK) == COMP_MASK) {
uint16_t offset;
--mb->pos;
offset = ntohs(mbuf_read_u16(mb)) & OFFSET_MASK;
if (!comp) {
pos = mb->pos;
comp = true;
}
mb->pos = offset + start;
continue;
}
else if (len > mbuf_get_left(mb))
break;
else if (len > sizeof(buf) - i - 2)
break;
if (i > 0)
buf[i++] = '.';
while (len--)
buf[i++] = mb->buf[mb->pos++];
}
return EINVAL;
}

16
src/dns/dns.h Normal file
View file

@ -0,0 +1,16 @@
/**
* @file dns.h Internal DNS header file
*
* Copyright (C) 2010 Creytiv.com
*/
#ifdef HAVE_LIBRESOLV
int get_resolv_dns(char *domain, size_t dsize, struct sa *nsv, uint32_t *n);
#endif
#ifdef WIN32
int get_windns(char *domain, size_t dsize, struct sa *nav, uint32_t *n);
#endif
#ifdef DARWIN
int get_darwin_dns(char *domain, size_t dsize, struct sa *nsv, uint32_t *n);
#endif

107
src/dns/hdr.c Normal file
View file

@ -0,0 +1,107 @@
/**
* @file dns/hdr.c DNS header encoding
*
* Copyright (C) 2010 Creytiv.com
*/
#include <re_types.h>
#include <re_fmt.h>
#include <re_list.h>
#include <re_mbuf.h>
#include <re_net.h>
#include <re_dns.h>
enum {
QUERY_RESPONSE = 15,
OPCODE = 11,
AUTH_ANSWER = 10,
TRUNCATED = 9,
RECURSION_DESIRED = 8,
RECURSION_AVAILABLE = 7,
ZERO = 4
};
int dns_hdr_encode(struct mbuf *mb, const struct dnshdr *hdr)
{
uint16_t flags = 0;
int err = 0;
if (!mb || !hdr)
return EINVAL;
flags |= hdr->qr <<QUERY_RESPONSE;
flags |= hdr->opcode <<OPCODE;
flags |= hdr->aa <<AUTH_ANSWER;
flags |= hdr->tc <<TRUNCATED;
flags |= hdr->rd <<RECURSION_DESIRED;
flags |= hdr->ra <<RECURSION_AVAILABLE;
flags |= hdr->z <<ZERO;
flags |= hdr->rcode;
err |= mbuf_write_u16(mb, htons(hdr->id));
err |= mbuf_write_u16(mb, htons(flags));
err |= mbuf_write_u16(mb, htons(hdr->nq));
err |= mbuf_write_u16(mb, htons(hdr->nans));
err |= mbuf_write_u16(mb, htons(hdr->nauth));
err |= mbuf_write_u16(mb, htons(hdr->nadd));
return err;
}
int dns_hdr_decode(struct mbuf *mb, struct dnshdr *hdr)
{
uint16_t flags = 0;
if (!mb || !hdr || (mbuf_get_left(mb) < DNS_HEADER_SIZE))
return EINVAL;
hdr->id = ntohs(mbuf_read_u16(mb));
flags = ntohs(mbuf_read_u16(mb));
hdr->qr = 0x1 & (flags >> QUERY_RESPONSE);
hdr->opcode = 0xf & (flags >> OPCODE);
hdr->aa = 0x1 & (flags >> AUTH_ANSWER);
hdr->tc = 0x1 & (flags >> TRUNCATED);
hdr->rd = 0x1 & (flags >> RECURSION_DESIRED);
hdr->ra = 0x1 & (flags >> RECURSION_AVAILABLE);
hdr->z = 0x7 & (flags >> ZERO);
hdr->rcode = 0xf & (flags >> 0);
hdr->nq = ntohs(mbuf_read_u16(mb));
hdr->nans = ntohs(mbuf_read_u16(mb));
hdr->nauth = ntohs(mbuf_read_u16(mb));
hdr->nadd = ntohs(mbuf_read_u16(mb));
return 0;
}
const char *dns_hdr_opcodename(uint8_t opcode)
{
switch (opcode) {
case DNS_OPCODE_QUERY: return "QUERY";
case DNS_OPCODE_IQUERY: return "IQUERY";
case DNS_OPCODE_STATUS: return "STATUS";
case DNS_OPCODE_NOTIFY: return "NOTIFY";
default: return "??";
}
}
const char *dns_hdr_rcodename(uint8_t rcode)
{
switch (rcode) {
case DNS_RCODE_OK: return "OK";
case DNS_RCODE_FMT_ERR: return "Format Error";
case DNS_RCODE_SRV_FAIL: return "Server Failure";
case DNS_RCODE_NAME_ERR: return "Name Error";
case DNS_RCODE_NOT_IMPL: return "Not Implemented";
case DNS_RCODE_REFUSED: return "Refused";
case DNS_RCODE_NOT_AUTH: return "Server Not Authoritative for zone";
default: return "??";
}
}

26
src/dns/mod.mk Normal file
View file

@ -0,0 +1,26 @@
#
# mod.mk
#
SRCS += dns/client.c
SRCS += dns/cstr.c
SRCS += dns/dname.c
SRCS += dns/hdr.c
SRCS += dns/ns.c
SRCS += dns/rr.c
SRCS += dns/rrlist.c
ifneq ($(HAVE_LIBRESOLV),)
SRCS += dns/res.c
endif
ifeq ($(OS),win32)
SRCS += dns/win32/srv.c
endif
ifeq ($(OS),darwin)
SRCS += dns/darwin/srv.c
# add libraries for darwin dns servers
LFLAGS += -framework SystemConfiguration -framework CoreFoundation
endif

117
src/dns/ns.c Normal file
View file

@ -0,0 +1,117 @@
/**
* @file ns.c DNS Nameserver configuration
*
* Copyright (C) 2010 Creytiv.com
*/
#include <stdio.h>
#include <string.h>
#include <re_types.h>
#include <re_fmt.h>
#include <re_mbuf.h>
#include <re_list.h>
#include <re_sa.h>
#include <re_dns.h>
#include "dns.h"
#define DEBUG_MODULE "ns"
#define DEBUG_LEVEL 5
#include <re_dbg.h>
#ifdef __SYMBIAN32__
extern int get_symbiandns(struct sa *nsv, uint32_t *n);
#endif
static int parse_resolv_conf(char *domain, size_t dsize,
struct sa *srvv, uint32_t *n)
{
FILE *f;
struct pl dom = pl_null;
uint32_t i = 0;
int err = 0;
if (!srvv || !n || !*n)
return EINVAL;
f = fopen("/etc/resolv.conf", "r");
if (!f)
return errno;
for (;;) {
char line[128];
struct pl srv;
size_t len;
if (1 != fscanf(f, "%127[^\n]\n", line))
break;
if ('#' == line[0])
continue;
len = str_len(line);
/* Set domain if not already set */
if (!pl_isset(&dom)) {
if (0 == re_regex(line, len, "domain [^ ]+", &dom)) {
(void)pl_strcpy(&dom, domain, dsize);
}
if (0 == re_regex(line, len, "search [^ ]+", &dom)) {
(void)pl_strcpy(&dom, domain, dsize);
}
}
/* Use the first entry */
if (i < *n && 0 == re_regex(line, len, "nameserver [^\n]+",
&srv)) {
err = sa_set(&srvv[i], &srv, DNS_PORT);
if (err) {
DEBUG_WARNING("sa_set: %r (%s)\n",
&srv, strerror(err));
}
++i;
}
}
*n = i;
(void)fclose(f);
return err;
}
int dns_srv_get(char *domain, size_t dsize, struct sa *srvv, uint32_t *n)
{
int err;
/* Try them all in prioritized order */
#ifdef HAVE_LIBRESOLV
err = get_resolv_dns(domain, dsize, srvv, n);
if (!err)
return 0;
#endif
#ifdef DARWIN
err = get_darwin_dns(domain, dsize, srvv, n);
if (!err)
return 0;
#endif
err = parse_resolv_conf(domain, dsize, srvv, n);
if (!err)
return 0;
#ifdef WIN32
err = get_windns(domain, dsize, srvv, n);
#endif
#ifdef __SYMBIAN32__
err = get_symbiandns(srvv, n);
#endif
return err;
}

56
src/dns/res.c Normal file
View file

@ -0,0 +1,56 @@
/**
* @file res.c Get DNS Server IP using libresolv
*
* Copyright (C) 2010 Creytiv.com
*/
#define _BSD_SOURCE 1
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include <re_types.h>
#include <re_fmt.h>
#include <re_mbuf.h>
#include <re_list.h>
#include <re_sa.h>
#include <re_dns.h>
#include "dns.h"
/**
* Generic way of fetching Nameserver IP-addresses, using libresolv
*
* @note we could use res_getservers() but it is not available on Linux
* @note only IPv4 is supported
*/
int get_resolv_dns(char *domain, size_t dsize, struct sa *nsv, uint32_t *n)
{
uint32_t i;
int ret, err;
ret = res_init();
if (0 != ret)
return ENOENT;
if (_res.dnsrch[0])
str_ncpy(domain, _res.dnsrch[0], dsize);
else if (_res.defdname)
str_ncpy(domain, _res.defdname, dsize);
*n = min(*n, (uint32_t)_res.nscount);
if (!*n) {
err = ENOENT;
goto out;
}
err = 0;
for (i=0; i<*n && !err; i++) {
struct sockaddr_in *addr = &_res.nsaddr_list[i];
err |= sa_set_sa(&nsv[i], (struct sockaddr *)addr);
}
out:
res_close();
return err;
}

574
src/dns/rr.c Normal file
View file

@ -0,0 +1,574 @@
/**
* @file dns/rr.c DNS Resource Records
*
* Copyright (C) 2010 Creytiv.com
*/
#include <string.h>
#include <re_types.h>
#include <re_fmt.h>
#include <re_list.h>
#include <re_mem.h>
#include <re_mbuf.h>
#include <re_net.h>
#include <re_sa.h>
#include <re_dns.h>
static void rr_destructor(void *data)
{
struct dnsrr *rr = data;
mem_deref(rr->name);
switch (rr->type) {
case DNS_TYPE_NS:
mem_deref(rr->rdata.ns.nsdname);
break;
case DNS_TYPE_CNAME:
mem_deref(rr->rdata.cname.cname);
break;
case DNS_TYPE_SOA:
mem_deref(rr->rdata.soa.mname);
mem_deref(rr->rdata.soa.rname);
break;
case DNS_TYPE_PTR:
mem_deref(rr->rdata.ptr.ptrdname);
break;
case DNS_TYPE_MX:
mem_deref(rr->rdata.mx.exchange);
break;
case DNS_TYPE_SRV:
mem_deref(rr->rdata.srv.target);
break;
case DNS_TYPE_NAPTR:
mem_deref(rr->rdata.naptr.flags);
mem_deref(rr->rdata.naptr.services);
mem_deref(rr->rdata.naptr.regexp);
mem_deref(rr->rdata.naptr.replace);
break;
}
}
struct dnsrr *dns_rr_alloc(void)
{
return mem_zalloc(sizeof(struct dnsrr), rr_destructor);
}
int dns_rr_encode(struct mbuf *mb, const struct dnsrr *rr, int64_t ttl_offs,
struct hash *ht_dname, size_t start)
{
uint32_t ttl;
uint16_t len;
size_t start_rdata;
int err = 0;
if (!mb || !rr)
return EINVAL;
ttl = (uint32_t)((rr->ttl > ttl_offs) ? (rr->ttl - ttl_offs) : 0);
err |= dns_dname_encode(mb, rr->name, ht_dname, start, true);
err |= mbuf_write_u16(mb, htons(rr->type));
err |= mbuf_write_u16(mb, htons(rr->dnsclass));
err |= mbuf_write_u32(mb, htonl(ttl));
err |= mbuf_write_u16(mb, htons(rr->rdlen));
start_rdata = mb->pos;
switch (rr->type) {
case DNS_TYPE_A:
err |= mbuf_write_u32(mb, htonl(rr->rdata.a.addr));
break;
case DNS_TYPE_NS:
err |= dns_dname_encode(mb, rr->rdata.ns.nsdname,
ht_dname, start, true);
break;
case DNS_TYPE_CNAME:
err |= dns_dname_encode(mb, rr->rdata.cname.cname,
ht_dname, start, true);
break;
case DNS_TYPE_SOA:
err |= dns_dname_encode(mb, rr->rdata.soa.mname,
ht_dname, start, true);
err |= dns_dname_encode(mb, rr->rdata.soa.rname,
ht_dname, start, true);
err |= mbuf_write_u32(mb, htonl(rr->rdata.soa.serial));
err |= mbuf_write_u32(mb, htonl(rr->rdata.soa.refresh));
err |= mbuf_write_u32(mb, htonl(rr->rdata.soa.retry));
err |= mbuf_write_u32(mb, htonl(rr->rdata.soa.expire));
err |= mbuf_write_u32(mb, htonl(rr->rdata.soa.ttlmin));
break;
case DNS_TYPE_PTR:
err |= dns_dname_encode(mb, rr->rdata.ptr.ptrdname,
ht_dname, start, true);
break;
case DNS_TYPE_MX:
err |= mbuf_write_u16(mb, htons(rr->rdata.mx.pref));
err |= dns_dname_encode(mb, rr->rdata.mx.exchange,
ht_dname, start, true);
break;
case DNS_TYPE_AAAA:
err |= mbuf_write_mem(mb, rr->rdata.aaaa.addr, 16);
break;
case DNS_TYPE_SRV:
err |= mbuf_write_u16(mb, htons(rr->rdata.srv.pri));
err |= mbuf_write_u16(mb, htons(rr->rdata.srv.weight));
err |= mbuf_write_u16(mb, htons(rr->rdata.srv.port));
err |= dns_dname_encode(mb, rr->rdata.srv.target,
ht_dname, start, false);
break;
case DNS_TYPE_NAPTR:
err |= mbuf_write_u16(mb, htons(rr->rdata.naptr.order));
err |= mbuf_write_u16(mb, htons(rr->rdata.naptr.pref));
err |= dns_cstr_encode(mb, rr->rdata.naptr.flags);
err |= dns_cstr_encode(mb, rr->rdata.naptr.services);
err |= dns_cstr_encode(mb, rr->rdata.naptr.regexp);
err |= dns_dname_encode(mb, rr->rdata.naptr.replace,
ht_dname, start, false);
break;
default:
err = EINVAL;
break;
}
len = mb->pos - start_rdata;
mb->pos = start_rdata - 2;
err |= mbuf_write_u16(mb, htons(len));
mb->pos += len;
return err;
}
int dns_rr_decode(struct mbuf *mb, struct dnsrr **rr, size_t start)
{
int err = 0;
struct dnsrr *lrr;
if (!mb || !rr)
return EINVAL;
lrr = dns_rr_alloc();
if (!lrr)
return ENOMEM;
err = dns_dname_decode(mb, &lrr->name, start);
if (err)
goto error;
if (mbuf_get_left(mb) < 10)
goto fmerr;
lrr->type = ntohs(mbuf_read_u16(mb));
lrr->dnsclass = ntohs(mbuf_read_u16(mb));
lrr->ttl = ntohl(mbuf_read_u32(mb));
lrr->rdlen = ntohs(mbuf_read_u16(mb));
if (mbuf_get_left(mb) < lrr->rdlen)
goto fmerr;
switch (lrr->type) {
case DNS_TYPE_A:
if (lrr->rdlen != 4)
goto fmerr;
lrr->rdata.a.addr = ntohl(mbuf_read_u32(mb));
break;
case DNS_TYPE_NS:
err = dns_dname_decode(mb, &lrr->rdata.ns.nsdname, start);
if (err)
goto error;
break;
case DNS_TYPE_CNAME:
err = dns_dname_decode(mb, &lrr->rdata.cname.cname, start);
if (err)
goto error;
break;
case DNS_TYPE_SOA:
err = dns_dname_decode(mb, &lrr->rdata.soa.mname, start);
if (err)
goto error;
err = dns_dname_decode(mb, &lrr->rdata.soa.rname, start);
if (err)
goto error;
if (mbuf_get_left(mb) < 20)
goto fmerr;
lrr->rdata.soa.serial = ntohl(mbuf_read_u32(mb));
lrr->rdata.soa.refresh = ntohl(mbuf_read_u32(mb));
lrr->rdata.soa.retry = ntohl(mbuf_read_u32(mb));
lrr->rdata.soa.expire = ntohl(mbuf_read_u32(mb));
lrr->rdata.soa.ttlmin = ntohl(mbuf_read_u32(mb));
break;
case DNS_TYPE_PTR:
err = dns_dname_decode(mb, &lrr->rdata.ptr.ptrdname, start);
if (err)
goto error;
break;
case DNS_TYPE_MX:
if (mbuf_get_left(mb) < 2)
goto fmerr;
lrr->rdata.mx.pref = ntohs(mbuf_read_u16(mb));
err = dns_dname_decode(mb, &lrr->rdata.mx.exchange, start);
if (err)
goto error;
break;
case DNS_TYPE_AAAA:
if (lrr->rdlen != 16)
goto fmerr;
err = mbuf_read_mem(mb, lrr->rdata.aaaa.addr, 16);
if (err)
goto error;
break;
case DNS_TYPE_SRV:
if (mbuf_get_left(mb) < 6)
goto fmerr;
lrr->rdata.srv.pri = ntohs(mbuf_read_u16(mb));
lrr->rdata.srv.weight = ntohs(mbuf_read_u16(mb));
lrr->rdata.srv.port = ntohs(mbuf_read_u16(mb));
err = dns_dname_decode(mb, &lrr->rdata.srv.target, start);
if (err)
goto error;
break;
case DNS_TYPE_NAPTR:
if (mbuf_get_left(mb) < 4)
goto fmerr;
lrr->rdata.naptr.order = ntohs(mbuf_read_u16(mb));
lrr->rdata.naptr.pref = ntohs(mbuf_read_u16(mb));
err = dns_cstr_decode(mb, &lrr->rdata.naptr.flags);
if (err)
goto error;
err = dns_cstr_decode(mb, &lrr->rdata.naptr.services);
if (err)
goto error;
err = dns_cstr_decode(mb, &lrr->rdata.naptr.regexp);
if (err)
goto error;
err = dns_dname_decode(mb, &lrr->rdata.naptr.replace, start);
if (err)
goto error;
break;
default:
mb->pos += lrr->rdlen;
break;
}
*rr = lrr;
return 0;
fmerr:
err = EINVAL;
error:
mem_deref(lrr);
return err;
}
bool dns_rr_cmp(const struct dnsrr *rr1, const struct dnsrr *rr2, bool rdata)
{
if (!rr1 || !rr2)
return false;
if (rr1 == rr2)
return true;
if (rr1->type != rr2->type)
return false;
if (rr1->dnsclass != rr2->dnsclass)
return false;
if (str_casecmp(rr1->name, rr2->name))
return false;
if (!rdata)
return true;
switch (rr1->type) {
case DNS_TYPE_A:
if (rr1->rdata.a.addr != rr2->rdata.a.addr)
return false;
break;
case DNS_TYPE_NS:
if (str_casecmp(rr1->rdata.ns.nsdname, rr2->rdata.ns.nsdname))
return false;
break;
case DNS_TYPE_CNAME:
if (str_casecmp(rr1->rdata.cname.cname,
rr2->rdata.cname.cname))
return false;
break;
case DNS_TYPE_SOA:
if (str_casecmp(rr1->rdata.soa.mname, rr2->rdata.soa.mname))
return false;
if (str_casecmp(rr1->rdata.soa.rname, rr2->rdata.soa.rname))
return false;
if (rr1->rdata.soa.serial != rr2->rdata.soa.serial)
return false;
if (rr1->rdata.soa.refresh != rr2->rdata.soa.refresh)
return false;
if (rr1->rdata.soa.retry != rr2->rdata.soa.retry)
return false;
if (rr1->rdata.soa.expire != rr2->rdata.soa.expire)
return false;
if (rr1->rdata.soa.ttlmin != rr2->rdata.soa.ttlmin)
return false;
break;
case DNS_TYPE_PTR:
if (str_casecmp(rr1->rdata.ptr.ptrdname,
rr2->rdata.ptr.ptrdname))
return false;
break;
case DNS_TYPE_MX:
if (rr1->rdata.mx.pref != rr2->rdata.mx.pref)
return false;
if (str_casecmp(rr1->rdata.mx.exchange,
rr2->rdata.mx.exchange))
return false;
break;
case DNS_TYPE_AAAA:
if (memcmp(rr1->rdata.aaaa.addr, rr2->rdata.aaaa.addr, 16))
return false;
break;
case DNS_TYPE_SRV:
if (rr1->rdata.srv.pri != rr2->rdata.srv.pri)
return false;
if (rr1->rdata.srv.weight != rr2->rdata.srv.weight)
return false;
if (rr1->rdata.srv.port != rr2->rdata.srv.port)
return false;
if (str_casecmp(rr1->rdata.srv.target, rr2->rdata.srv.target))
return false;
break;
case DNS_TYPE_NAPTR:
if (rr1->rdata.naptr.order != rr2->rdata.naptr.order)
return false;
if (rr1->rdata.naptr.pref != rr2->rdata.naptr.pref)
return false;
/* todo check case sensitiveness */
if (str_casecmp(rr1->rdata.naptr.flags,
rr2->rdata.naptr.flags))
return false;
/* todo check case sensitiveness */
if (str_casecmp(rr1->rdata.naptr.services,
rr2->rdata.naptr.services))
return false;
/* todo check case sensitiveness */
if (str_casecmp(rr1->rdata.naptr.regexp,
rr2->rdata.naptr.regexp))
return false;
/* todo check case sensitiveness */
if (str_casecmp(rr1->rdata.naptr.replace,
rr2->rdata.naptr.replace))
return false;
break;
default:
return false;
}
return true;
}
const char *dns_rr_typename(uint16_t type)
{
switch (type) {
case DNS_TYPE_A: return "A";
case DNS_TYPE_NS: return "NS";
case DNS_TYPE_CNAME: return "CNAME";
case DNS_TYPE_SOA: return "SOA";
case DNS_TYPE_PTR: return "PTR";
case DNS_TYPE_MX: return "MX";
case DNS_TYPE_AAAA: return "AAAA";
case DNS_TYPE_SRV: return "SRV";
case DNS_TYPE_NAPTR: return "NAPTR";
case DNS_QTYPE_IXFR: return "IXFR";
case DNS_QTYPE_AXFR: return "AXFR";
case DNS_QTYPE_ANY: return "ANY";
default: return "??";
}
}
const char *dns_rr_classname(uint16_t dnsclass)
{
switch (dnsclass) {
case DNS_CLASS_IN: return "IN";
case DNS_QCLASS_ANY: return "ANY";
default: return "??";
}
}
int dns_rr_print(struct re_printf *pf, const struct dnsrr *rr)
{
static const size_t w = 24;
struct sa sa;
size_t n, l;
int err;
if (!pf || !rr)
return EINVAL;
l = str_len(rr->name);
n = (w > l) ? w - l : 0;
err = re_hprintf(pf, "%s.", rr->name);
while (n--)
err |= pf->vph(" ", 1, pf->arg);
err |= re_hprintf(pf, " %10lld %-4s %-7s ",
rr->ttl,
dns_rr_classname(rr->dnsclass),
dns_rr_typename(rr->type));
switch (rr->type) {
case DNS_TYPE_A:
sa_set_in(&sa, rr->rdata.a.addr, 0);
err |= re_hprintf(pf, "%j", &sa);
break;
case DNS_TYPE_NS:
err |= re_hprintf(pf, "%s.", rr->rdata.ns.nsdname);
break;
case DNS_TYPE_CNAME:
err |= re_hprintf(pf, "%s.", rr->rdata.cname.cname);
break;
case DNS_TYPE_SOA:
err |= re_hprintf(pf, "%s. %s. %u %u %u %u %u",
rr->rdata.soa.mname,
rr->rdata.soa.rname,
rr->rdata.soa.serial,
rr->rdata.soa.refresh,
rr->rdata.soa.retry,
rr->rdata.soa.expire,
rr->rdata.soa.ttlmin);
break;
case DNS_TYPE_PTR:
err |= re_hprintf(pf, "%s.", rr->rdata.ptr.ptrdname);
break;
case DNS_TYPE_MX:
err |= re_hprintf(pf, "%3u %s.", rr->rdata.mx.pref,
rr->rdata.mx.exchange);
break;
case DNS_TYPE_AAAA:
sa_set_in6(&sa, rr->rdata.aaaa.addr, 0);
err |= re_hprintf(pf, "%j", &sa);
break;
case DNS_TYPE_SRV:
err |= re_hprintf(pf, "%3u %3u %u %s.",
rr->rdata.srv.pri,
rr->rdata.srv.weight,
rr->rdata.srv.port,
rr->rdata.srv.target);
break;
case DNS_TYPE_NAPTR:
err |= re_hprintf(pf, "%3u %3u \"%s\" \"%s\" \"%s\" %s.",
rr->rdata.naptr.order,
rr->rdata.naptr.pref,
rr->rdata.naptr.flags,
rr->rdata.naptr.services,
rr->rdata.naptr.regexp,
rr->rdata.naptr.replace);
break;
default:
err |= re_hprintf(pf, "?");
break;
}
return err;
}

146
src/dns/rrlist.c Normal file
View file

@ -0,0 +1,146 @@
/**
* @file rrlist.c DNS Resource Records list
*
* Copyright (C) 2010 Creytiv.com
*/
#include <re_types.h>
#include <re_list.h>
#include <re_mbuf.h>
#include <re_fmt.h>
#include <re_dns.h>
enum {
CNAME_RECURSE_MAX = 16,
};
static bool std_sort_handler(struct le *le1, struct le *le2, void *arg)
{
struct dnsrr *rr1 = le1->data;
struct dnsrr *rr2 = le2->data;
const uint16_t type = *(uint16_t *)arg;
if (type != rr1->type)
return type != rr2->type;
if (type != rr2->type)
return true;
switch (type) {
case DNS_TYPE_MX:
return rr1->rdata.mx.pref <= rr2->rdata.mx.pref;
case DNS_TYPE_SRV:
if (rr1->rdata.srv.pri == rr2->rdata.srv.pri) {
if (rr1->rdata.srv.weight)
return 0 != rr2->rdata.srv.weight;
return true;
}
return rr1->rdata.srv.pri < rr2->rdata.srv.pri;
case DNS_TYPE_NAPTR:
if (rr1->rdata.naptr.order == rr2->rdata.naptr.order)
return rr1->rdata.naptr.pref <= rr2->rdata.naptr.pref;
return rr1->rdata.naptr.order < rr2->rdata.naptr.order;
default:
break;
}
return true;
}
void dns_rrlist_sort(struct list *rrl, uint16_t type)
{
list_sort(rrl, std_sort_handler, &type);
/* todo add SRV postprocessing for weighted load balancing. */
}
static struct dnsrr *rrlist_apply(struct list *rrl, const char *name,
uint16_t type1, uint16_t type2,
uint16_t dnsclass,
bool recurse, uint32_t depth,
dns_rrlist_h *rrlh, void *arg)
{
struct le *le = list_head(rrl);
if (depth > CNAME_RECURSE_MAX)
return NULL;
while (le) {
struct dnsrr *rr = le->data;
le = le->next;
if (name && str_casecmp(name, rr->name))
continue;
if (type1 != DNS_QTYPE_ANY && type2 != DNS_QTYPE_ANY &&
rr->type != type1 && rr->type != type2 &&
(rr->type != DNS_TYPE_CNAME || !recurse))
continue;
if (dnsclass != DNS_QCLASS_ANY && rr->dnsclass != dnsclass)
continue;
if (!rrlh || rrlh(rr, arg))
return rr;
if (recurse &&
DNS_QTYPE_ANY != type1 && DNS_QTYPE_ANY != type2 &&
DNS_TYPE_CNAME != type1 && DNS_TYPE_CNAME != type2 &&
DNS_TYPE_CNAME == rr->type) {
rr = rrlist_apply(rrl, rr->rdata.cname.cname, type1,
type2, dnsclass, recurse, ++depth,
rrlh, arg);
if (rr)
return rr;
}
}
return NULL;
}
struct dnsrr *dns_rrlist_apply(struct list *rrl, const char *name,
uint16_t type, uint16_t dnsclass,
bool recurse, dns_rrlist_h *rrlh, void *arg)
{
return rrlist_apply(rrl, name, type, type, dnsclass,
recurse, 0, rrlh, arg);
}
struct dnsrr *dns_rrlist_apply2(struct list *rrl, const char *name,
uint16_t type1, uint16_t type2,
uint16_t dnsclass, bool recurse,
dns_rrlist_h *rrlh, void *arg)
{
return rrlist_apply(rrl, name, type1, type2, dnsclass,
recurse, 0, rrlh, arg);
}
static bool find_handler(struct dnsrr *rr, void *arg)
{
uint16_t type = *(uint16_t *)arg;
return rr->type == type;
}
struct dnsrr *dns_rrlist_find(struct list *rrl, const char *name,
uint16_t type, uint16_t dnsclass, bool recurse)
{
return rrlist_apply(rrl, name, type, type, dnsclass,
recurse, 0, find_handler, &type);
}

82
src/dns/symbian/srv.cpp Normal file
View file

@ -0,0 +1,82 @@
/**
* @file srv.cpp Get DNS Server IP code for Symbian OS
*
* Copyright (C) 2010 Creytiv.com
*/
#include <es_sock.h>
#include <in_sock.h>
extern "C" {
#include <re_types.h>
#include <re_fmt.h>
#include <re_list.h>
#include <re_sa.h>
#include <re_net.h>
#include <re_dns.h>
extern int get_symbiandns(struct sa *nsv, uint32_t *n);
}
int get_symbiandns(struct sa *nsv, uint32_t *n)
{
RSocketServ serv;
RSocket sock;
uint32_t i = 0;
int ret;
if (!nsv || !n || !*n)
return EINVAL;
ret = serv.Connect();
if (KErrNone != ret)
return kerr2errno(ret);
ret = sock.Open(serv, KAfInet, KSockStream, KProtocolInetTcp);
if (KErrNone != ret) {
serv.Close();
return kerr2errno(ret);
}
sock.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl);
TPckgBuf<TSoInetInterfaceInfo> ifinfo;
while (sock.GetOpt(KSoInetNextInterface, KSolInetIfCtrl,
ifinfo)==KErrNone) {
struct sa sa;
if (EIfUp != ifinfo().iState)
continue;
sa_set_in(&sa, ifinfo().iAddress.Address(), 0);
if (sa_is_loopback(&sa))
continue;
if (sa_is_linklocal(&sa))
continue;
if (ifinfo().iNameSer1.Address()) {
sa_set_in(&nsv[i], ifinfo().iNameSer1.Address(),
DNS_PORT);
++i;
}
if (i >= *n)
break;
if (ifinfo().iNameSer2.Address()) {
sa_set_in(&nsv[i], ifinfo().iNameSer2.Address(),
DNS_PORT);
++i;
}
if (i >= *n)
break;
}
sock.Close();
serv.Close();
*n = i;
return 0;
}

101
src/dns/win32/srv.c Normal file
View file

@ -0,0 +1,101 @@
/**
* @file win32/srv.c Get DNS Server IP code for Windows
*
* Copyright (C) 2010 Creytiv.com
*/
#include <winsock2.h>
#include <iphlpapi.h>
#include <io.h>
#include <re_types.h>
#include <re_fmt.h>
#include <re_mbuf.h>
#include <re_list.h>
#include <re_sa.h>
#include <re_dns.h>
#include "../dns.h"
#define DEBUG_MODULE "win32/srv"
#define DEBUG_LEVEL 5
#include <re_dbg.h>
int get_windns(char *domain, size_t dsize, struct sa *srvv, uint32_t *n)
{
FIXED_INFO * FixedInfo = NULL;
ULONG ulOutBufLen;
DWORD dwRetVal;
IP_ADDR_STRING * pIPAddr;
HANDLE hLib;
union {
FARPROC proc;
DWORD (WINAPI *_GetNetworkParams)(FIXED_INFO*, DWORD*);
} u;
uint32_t i;
int err;
if (!srvv || !n || !*n)
return EINVAL;
hLib = LoadLibrary(TEXT("iphlpapi.dll"));
if (!hLib)
return ENOSYS;
u.proc = GetProcAddress(hLib, TEXT("GetNetworkParams"));
if (!u.proc) {
err = ENOSYS;
goto out;
}
FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, sizeof( FIXED_INFO ));
ulOutBufLen = sizeof( FIXED_INFO );
if (ERROR_BUFFER_OVERFLOW == (*u._GetNetworkParams)(FixedInfo,
&ulOutBufLen)) {
GlobalFree( FixedInfo );
FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, ulOutBufLen);
}
if ((dwRetVal = (*u._GetNetworkParams)( FixedInfo, &ulOutBufLen ))) {
DEBUG_WARNING("couldn't get network params (%d)\n", dwRetVal);
err = ENOENT;
goto out;
}
str_ncpy(domain, FixedInfo->DomainName, dsize);
#if 0
printf( "Host Name: %s\n", FixedInfo->HostName);
printf( "Domain Name: %s\n", FixedInfo->DomainName);
printf( "DNS Servers:\n" );
printf( "\t%s\n", FixedInfo->DnsServerList.IpAddress.String );
#endif
i = 0;
pIPAddr = &FixedInfo->DnsServerList;
while (pIPAddr && strlen(pIPAddr->IpAddress.String) > 0) {
err = sa_set_str(&srvv[i], pIPAddr->IpAddress.String,
DNS_PORT);
if (err) {
DEBUG_WARNING("sa_set_str: %s (%s)\n",
pIPAddr->IpAddress.String,
strerror(err));
}
DEBUG_INFO("dns ip %u: %j\n", i, &srvv[i]);
++i;
pIPAddr = pIPAddr ->Next;
if (i >= *n)
break;
}
*n = i;
DEBUG_INFO("got %u nameservers\n", i);
err = i>0 ? 0 : ENOENT;
out:
if (FixedInfo)
GlobalFree(FixedInfo);
FreeLibrary(hLib);
return err;
}

29
src/fmt/ch.c Normal file
View file

@ -0,0 +1,29 @@
/**
* @file ch.c Character format functions
*
* Copyright (C) 2010 Creytiv.com
*/
#include <re_types.h>
#include <re_fmt.h>
/**
* Convert a ascii hex character to binary format
*
* @param ch Ascii hex character
*
* @return Binary value
*/
uint8_t ch_hex(char ch)
{
if ('0' <= ch && ch <= '9')
return ch - '0';
else if ('A' <= ch && ch <= 'F')
return ch - 'A' + 10;
else if ('a' <= ch && ch <= 'f')
return ch - 'a' + 10;
return 0;
}

57
src/fmt/hexdump.c Normal file
View file

@ -0,0 +1,57 @@
/**
* @file hexdump.c Hexadecimal dumping
*
* Copyright (C) 2010 Creytiv.com
*/
#include <ctype.h>
#include <re_types.h>
#include <re_fmt.h>
/**
* Hexadecimal dump of binary buffer. Similar output to HEXDUMP(1)
*
* @param f File stream for output (e.g. stderr, stdout)
* @param p Pointer to data
* @param len Number of bytes
*/
void hexdump(FILE *f, const void *p, size_t len)
{
const uint8_t *buf = p;
uint32_t j;
size_t i;
if (!f || !buf)
return;
for (i=0; i < len; i += 16) {
(void)re_fprintf(f, "%08x ", i);
for (j=0; j<16; j++) {
const size_t pos = i+j;
if (pos < len)
(void)re_fprintf(f, " %02x", buf[pos]);
else
(void)re_fprintf(f, " ");
if (j == 7)
(void)re_fprintf(f, " ");
}
(void)re_fprintf(f, " |");
for (j=0; j<16; j++) {
const size_t pos = i+j;
uint8_t v;
if (pos >= len)
break;
v = buf[pos];
(void)re_fprintf(f, "%c", isprint(v) ? v : '.');
if (j == 7)
(void)re_fprintf(f, " ");
}
(void)re_fprintf(f, "|\n");
}
}

13
src/fmt/mod.mk Normal file
View file

@ -0,0 +1,13 @@
#
# mod.mk
#
SRCS += fmt/ch.c
SRCS += fmt/hexdump.c
SRCS += fmt/pl.c
SRCS += fmt/print.c
SRCS += fmt/prm.c
SRCS += fmt/regex.c
SRCS += fmt/str.c
SRCS += fmt/time.c

419
src/fmt/pl.c Normal file
View file

@ -0,0 +1,419 @@
/**
* @file pl.c Pointer-length functions
*
* Copyright (C) 2010 Creytiv.com
*/
#include <ctype.h>
#include <sys/types.h>
#ifdef HAVE_STRINGS_H
#define __EXTENSIONS__ 1
#include <strings.h>
#endif
#include <string.h>
#include <stdlib.h>
#include <re_types.h>
#include <re_mem.h>
#include <re_mbuf.h>
#include <re_fmt.h>
/** Pointer-length NULL initialiser */
const struct pl pl_null = {NULL, 0};
/**
* Initialise a pointer-length object from a NULL-terminated string
*
* @param pl Pointer-length object to be initialised
* @param str NULL-terminated string
*/
void pl_set_str(struct pl *pl, const char *str)
{
if (!pl || !str)
return;
pl->p = str;
pl->l = strlen(str);
}
/**
* Initialise a pointer-length object from current position and
* length of a memory buffer
*
* @param pl Pointer-length object to be initialised
* @param mb Memory buffer
*/
void pl_set_mbuf(struct pl *pl, const struct mbuf *mb)
{
if (!pl || !mb)
return;
pl->p = (char *)mbuf_buf(mb);
pl->l = mbuf_get_left(mb);
}
/**
* Convert a pointer-length object to a numeric 32-bit value
*
* @param pl Pointer-length object
*
* @return 32-bit value
*/
uint32_t pl_u32(const struct pl *pl)
{
uint32_t v=0, mul=1;
const char *p;
if (!pl || !pl->p)
return 0;
p = &pl->p[pl->l];
while (p > pl->p) {
const uint8_t c = *--p - '0';
if (c > 9)
return 0;
v += mul * c;
mul *= 10;
}
return v;
}
/**
* Convert a hex pointer-length object to a numeric 32-bit value
*
* @param pl Pointer-length object
*
* @return 32-bit value
*/
uint32_t pl_x32(const struct pl *pl)
{
uint32_t v=0, mul=1;
const char *p;
if (!pl || !pl->p)
return 0;
p = &pl->p[pl->l];
while (p > pl->p) {
const char ch = *--p;
uint8_t c;
if ('0' <= ch && ch <= '9')
c = ch - '0';
else if ('A' <= ch && ch <= 'F')
c = ch - 'A' + 10;
else if ('a' <= ch && ch <= 'f')
c = ch - 'a' + 10;
else
return 0;
v += mul * c;
mul *= 16;
}
return v;
}
/**
* Convert a pointer-length object to a numeric 64-bit value
*
* @param pl Pointer-length object
*
* @return 64-bit value
*/
uint64_t pl_u64(const struct pl *pl)
{
uint64_t v=0, mul=1;
const char *p;
if (!pl || !pl->p)
return 0;
p = &pl->p[pl->l];
while (p > pl->p) {
const uint8_t c = *--p - '0';
if (c > 9)
return 0;
v += mul * c;
mul *= 10;
}
return v;
}
/**
* Check if pointer-length object is set
*
* @param pl Pointer-length object
*
* @return true if set, false if not set
*/
bool pl_isset(const struct pl *pl)
{
return pl ? pl->p && pl->l : false;
}
/**
* Copy a pointer-length object to a NULL-terminated string
*
* @param pl Pointer-length object
* @param str Buffer for NULL-terminated string
* @param size Size of buffer
*
* @return 0 if success, otherwise errorcode
*/
int pl_strcpy(const struct pl *pl, char *str, size_t size)
{
size_t len;
if (!pl || !pl->p || !str || !size)
return EINVAL;
len = min(pl->l, size-1);
memcpy(str, pl->p, len);
str[len] = '\0';
return 0;
}
/**
* Duplicate a pointer-length object to a NULL-terminated string
*
* @param dst Pointer to destination string (set on return)
* @param src Source pointer-length object
*
* @return 0 if success, otherwise errorcode
*/
int pl_strdup(char **dst, const struct pl *src)
{
char *p;
if (!dst || !src || !src->p)
return EINVAL;
p = mem_alloc(src->l+1, NULL);
if (!p)
return ENOMEM;
memcpy(p, src->p, src->l);
p[src->l] = '\0';
*dst = p;
return 0;
}
/**
* Duplicate a pointer-length object to a new pointer-length object
*
* @param dst Destination pointer-length object (set on return)
* @param src Source pointer-length object
*
* @return 0 if success, otherwise errorcode
*/
int pl_dup(struct pl *dst, const struct pl *src)
{
char *p;
if (!dst || !src || !src->p)
return EINVAL;
p = mem_alloc(src->l, NULL);
if (!p)
return ENOMEM;
memcpy(p, src->p, src->l);
dst->p = p;
dst->l = src->l;
return 0;
}
/**
* Compare a pointer-length object with a NULL-terminated string
* (case-sensitive)
*
* @param pl Pointer-length object
* @param str NULL-terminated string
*
* @return 0 if match, otherwise errorcode
*/
int pl_strcmp(const struct pl *pl, const char *str)
{
struct pl s;
if (!pl || !str)
return EINVAL;
pl_set_str(&s, str);
return pl_cmp(pl, &s);
}
/**
* Compare a pointer-length object with a NULL-terminated string
* (case-insensitive)
*
* @param pl Pointer-length object
* @param str NULL-terminated string
*
* @return 0 if match, otherwise errorcode
*/
int pl_strcasecmp(const struct pl *pl, const char *str)
{
struct pl s;
if (!pl || !str)
return EINVAL;
pl_set_str(&s, str);
return pl_casecmp(pl, &s);
}
/**
* Compare two pointer-length objects (case-sensitive)
*
* @param pl1 First pointer-length object
* @param pl2 Second pointer-length object
*
* @return 0 if match, otherwise errorcode
*/
int pl_cmp(const struct pl *pl1, const struct pl *pl2)
{
if (!pl1 || !pl2)
return EINVAL;
/* Different length -> no match */
if (pl1->l != pl2->l)
return EINVAL;
/*
* ~35% speed increase for fmt/pl test
*/
/* The two pl's are the same */
if (pl1 == pl2) {
return 0;
}
/* Two different pl's pointing to same string */
if (pl1->p == pl2->p && pl1->l == pl2->l) {
return 0;
}
return 0 == memcmp(pl1->p, pl2->p, pl1->l) ? 0 : EINVAL;
}
#ifndef HAVE_STRINGS_H
static int casecmp(const struct pl *pl, const char *str)
{
size_t i = 0;
#define LOWER(d) ((d) | 0x20202020)
const uint32_t *p1 = (uint32_t *)pl->p;
const uint32_t *p2 = (uint32_t *)str;
const size_t len = pl->l & ~0x3;
/* Skip any unaligned pointers */
if (((size_t)pl->p) & (sizeof(void *) - 1))
goto next;
if (((size_t)str) & (sizeof(void *) - 1))
goto next;
/* Compare word-wise */
for (; i<len; i+=4) {
if (LOWER(*p1++) != LOWER(*p2++))
return EINVAL;
}
next:
/* Compare byte-wise */
for (; i<pl->l; i++) {
if (tolower(pl->p[i]) != tolower(str[i]))
return EINVAL;
}
return 0;
}
#endif
/**
* Compare two pointer-length objects (case-insensitive)
*
* @param pl1 First pointer-length object
* @param pl2 Second pointer-length object
*
* @return 0 if match, otherwise errorcode
*/
int pl_casecmp(const struct pl *pl1, const struct pl *pl2)
{
if (!pl1 || !pl2)
return EINVAL;
/* Different length -> no match */
if (pl1->l != pl2->l)
return EINVAL;
/*
* ~35% speed increase for fmt/pl test
*/
/* The two pl's are the same */
if (pl1 == pl2) {
return 0;
}
/* Two different pl's pointing to same string */
if (pl1->p == pl2->p && pl1->l == pl2->l) {
return 0;
}
#ifdef HAVE_STRINGS_H
return 0 == strncasecmp(pl1->p, pl2->p, pl1->l) ? 0 : EINVAL;
#else
return casecmp(pl1, pl2->p);
#endif
}
/**
* Locate character in pointer-length string
*
* @param pl Pointer-length string
* @param c Character to locate
*
* @return Pointer to first char if found, otherwise NULL
*/
const char *pl_strchr(const struct pl *pl, char c)
{
const char *p, *end;
if (!pl)
return NULL;
end = pl->p + pl->l;
for (p = pl->p; p < end; p++) {
if (*p == c)
return p;
}
return NULL;
}

759
src/fmt/print.c Normal file
View file

@ -0,0 +1,759 @@
/**
* @file print.c Formatted printing
*
* Copyright (C) 2010 Creytiv.com
*/
#include <string.h>
#include <re_types.h>
#include <re_sa.h>
#include <re_fmt.h>
#include <re_mem.h>
#include <math.h>
#ifdef _MSC_VER
#include <float.h>
#define isinf(d) (!_finite(d))
#define isnan(d) _isnan(d)
#endif
#ifdef SOLARIS
#include <ieeefp.h>
#undef isinf
#define isinf(a) (fpclass((a)) == FP_NINF || fpclass((a)) == FP_PINF)
#undef isnan
#define isnan(a) isnand((a))
#endif
enum length_modifier {
LENMOD_NONE = 0,
LENMOD_LONG = 1,
LENMOD_LONG_LONG = 2,
LENMOD_SIZE = 42,
};
enum {
DEC_SIZE = 42,
NUM_SIZE = 64
};
static const char prfx_neg[] = "-";
static const char prfx_hex[] = "0x";
static const char str_nil[] = "(nil)";
static int write_padded(const char *p, size_t sz, size_t pad, char pch,
bool plr, const char *prfx, re_vprintf_h *vph,
void *arg)
{
const size_t prfx_len = str_len(prfx);
int err = 0;
pad -= MIN(pad, prfx_len);
if (prfx && pch == '0')
err |= vph(prfx, prfx_len, arg);
while (!plr && (pad-- > sz))
err |= vph(&pch, 1, arg);
if (prfx && pch != '0')
err |= vph(prfx, prfx_len, arg);
if (p && sz)
err |= vph(p, sz, arg);
while (plr && pad-- > sz)
err |= vph(&pch, 1, arg);
return err;
}
static uint32_t local_itoa(char *buf, uint64_t n, uint8_t base, bool uc)
{
char c, *p = buf + NUM_SIZE;
uint32_t len = 1;
const char a = uc ? 'A' : 'a';
*--p = '\0';
do {
const uint64_t dv = n / base;
const uint64_t mul = dv * base;
c = (char)(n - mul);
if (c < 10)
*--p = '0' + c;
else
*--p = a + (c - 10);
n = dv;
++len;
} while (n != 0);
memmove(buf, p, len);
return len - 1;
}
static size_t local_ftoa(char *buf, double n, size_t dp)
{
char *p = buf;
long long a = (long long)n;
double b = n - (double)a;
b = (b < 0) ? -b : b;
/* integral part */
p += local_itoa(p, (a < 0) ? -a : a, 10, false);
*p++ = '.';
/* decimal digits */
while (dp--) {
char v;
b *= 10;
v = (char)b;
b -= v;
*p++ = '0' + (char)v;
}
*p = '\0';
return p - buf;
}
/**
* Print a formatted string
*
* Extensions:
*
* %b (char *, size_t) Buffer string with pointer and length
* %r (struct pl) Pointer-length object
* %w (uint8_t *, size_t) Binary buffer to hexadecimal format
* %j (struct sa *) Socket address - address part only
* %J (struct sa *) Socket address and port - like 1.2.3.4:1234
* %H (re_printf_h *, void *) Print handler with argument
* %v (char *fmt, va_list *) Variable argument list
*
* Reserved for the future:
*
* %k
* %y
*
*/
int re_vhprintf(const char *fmt, va_list ap, re_vprintf_h *vph, void *arg)
{
uint8_t base, *bptr;
char pch, ch, num[NUM_SIZE], addr[64];
enum length_modifier lenmod = LENMOD_NONE;
struct re_printf pf;
bool fm = false, plr = false;
const struct pl *pl;
size_t pad = 0, fpad = -1, len, i;
const char *str, *p = fmt, *p0 = fmt;
const struct sa *sa;
re_printf_h *ph;
void *ph_arg;
va_list *apl;
int err = 0;
void *ptr;
uint64_t n;
int64_t sn;
bool uc = false;
double dbl;
if (!fmt || !vph)
return EINVAL;
pf.vph = vph;
pf.arg = arg;
for (;*p && !err; p++) {
if (!fm) {
if (*p != '%')
continue;
pch = ' ';
plr = false;
pad = 0;
fpad = -1;
lenmod = LENMOD_NONE;
uc = false;
if (p > p0)
err |= vph(p0, p - p0, arg);
fm = true;
continue;
}
fm = false;
base = 10;
switch (*p) {
case '-':
plr = true;
fm = true;
break;
case '.':
fpad = pad;
pad = 0;
fm = true;
break;
case '%':
ch = '%';
err |= vph(&ch, 1, arg);
break;
case 'b':
str = va_arg(ap, const char *);
len = va_arg(ap, size_t);
err |= write_padded(str, str ? len : 0, pad, ' ',
plr, NULL, vph, arg);
break;
case 'c':
ch = va_arg(ap, int);
err |= write_padded(&ch, 1, pad, ' ', plr, NULL,
vph, arg);
break;
case 'd':
case 'i':
switch (lenmod) {
case LENMOD_SIZE:
sn = va_arg(ap, ssize_t);
break;
default:
case LENMOD_LONG_LONG:
sn = va_arg(ap, signed long long);
break;
case LENMOD_LONG:
sn = va_arg(ap, signed long);
break;
case LENMOD_NONE:
sn = va_arg(ap, signed);
break;
}
len = local_itoa(num, (sn < 0) ? -sn : sn, base,
false);
err |= write_padded(num, len, pad,
plr ? ' ' : pch, plr,
(sn < 0) ? prfx_neg : NULL,
vph, arg);
break;
case 'f':
case 'F':
dbl = va_arg(ap, double);
if (fpad == (size_t)-1) {
fpad = pad;
pad = 0;
}
if (isinf(dbl)) {
err |= write_padded("inf", 3, fpad,
' ', plr, NULL, vph, arg);
}
else if (isnan(dbl)) {
err |= write_padded("nan", 3, fpad,
' ', plr, NULL, vph, arg);
}
else {
len = local_ftoa(num, dbl,
pad ? min(pad, DEC_SIZE) : 6);
err |= write_padded(num, len, fpad,
plr ? ' ' : pch, plr,
(dbl<0) ? prfx_neg : NULL,
vph, arg);
}
break;
case 'H':
ph = va_arg(ap, re_printf_h *);
ph_arg = va_arg(ap, void *);
if (ph)
err |= ph(&pf, ph_arg);
break;
case 'l':
++lenmod;
fm = true;
break;
case 'p':
ptr = va_arg(ap, void *);
if (ptr) {
len = local_itoa(num, (unsigned long int)ptr,
16, false);
err |= write_padded(num, len, pad,
plr ? ' ' : pch, plr,
prfx_hex, vph, arg);
}
else {
err |= write_padded(str_nil,
sizeof(str_nil) - 1,
pad, ' ', plr, NULL,
vph, arg);
}
break;
case 'r':
pl = va_arg(ap, const struct pl *);
err |= write_padded(pl ? pl->p : NULL,
(pl && pl->p) ? pl->l : 0,
pad, ' ', plr, NULL, vph, arg);
break;
case 's':
str = va_arg(ap, const char *);
err |= write_padded(str, str_len(str), pad,
' ', plr, NULL, vph, arg);
break;
case 'X':
uc = true;
/*@fallthrough@*/
case 'x':
base = 16;
/*@fallthrough@*/
case 'u':
switch (lenmod) {
case LENMOD_SIZE:
n = va_arg(ap, size_t);
break;
default:
case LENMOD_LONG_LONG:
n = va_arg(ap, unsigned long long);
break;
case LENMOD_LONG:
n = va_arg(ap, unsigned long);
break;
case LENMOD_NONE:
n = va_arg(ap, unsigned);
break;
}
len = local_itoa(num, n, base, uc);
err |= write_padded(num, len, pad,
plr ? ' ' : pch, plr, NULL,
vph, arg);
break;
case 'v':
str = va_arg(ap, char *);
apl = va_arg(ap, va_list *);
if (!str || !apl)
break;
err |= re_vhprintf(str, *apl, vph, arg);
break;
case 'W':
uc = true;
/*@fallthrough@*/
case 'w':
bptr = va_arg(ap, uint8_t *);
len = va_arg(ap, size_t);
len = bptr ? len : 0;
pch = plr ? ' ' : pch;
while (!plr && pad-- > (len * 2))
err |= vph(&pch, 1, arg);
for (i=0; i<len; i++) {
const uint8_t v = *bptr++;
uint32_t l = local_itoa(num, v, 16, uc);
err |= write_padded(num, l, 2, '0',
false, NULL, vph, arg);
}
while (plr && pad-- > (len * 2))
err |= vph(&pch, 1, arg);
break;
case 'z':
lenmod = LENMOD_SIZE;
fm = true;
break;
case 'j':
sa = va_arg(ap, struct sa *);
if (!sa)
break;
if (sa_ntop(sa, addr, sizeof(addr))) {
err |= write_padded("?", 1, pad, ' ',
plr, NULL, vph, arg);
break;
}
err |= write_padded(addr, strlen(addr), pad, ' ',
plr, NULL, vph, arg);
break;
case 'J':
sa = va_arg(ap, struct sa *);
if (!sa)
break;
if (sa_ntop(sa, addr, sizeof(addr))) {
err |= write_padded("?", 1, pad, ' ',
plr, NULL, vph, arg);
break;
}
#ifdef HAVE_INET6
if (AF_INET6 == sa_af(sa)) {
ch = '[';
err |= vph(&ch, 1, arg);
}
#endif
err |= write_padded(addr, strlen(addr), pad, ' ',
plr, NULL, vph, arg);
#ifdef HAVE_INET6
if (AF_INET6 == sa_af(sa)) {
ch = ']';
err |= vph(&ch, 1, arg);
}
#endif
ch = ':';
err |= vph(&ch, 1, arg);
len = local_itoa(num, sa_port(sa), 10, false);
err |= write_padded(num, len, pad,
plr ? ' ' : pch, plr, NULL,
vph, arg);
break;
default:
if (('0' <= *p) && (*p <= '9')) {
if (!pad && ('0' == *p)) {
pch = '0';
}
else {
pad *= 10;
pad += *p - '0';
}
fm = true;
break;
}
ch = '?';
err |= vph(&ch, 1, arg);
break;
}
if (!fm)
p0 = p + 1;
}
if (!fm && p > p0)
err |= vph(p0, p - p0, arg);
return err;
}
static int print_handler(const char *p, size_t size, void *arg)
{
struct pl *pl = arg;
if (size > pl->l)
return ENOMEM;
memcpy((void *)pl->p, p, size);
pl_advance(pl, size);
return 0;
}
struct dyn_print {
char *str;
char *p;
size_t l;
size_t size;
};
static int print_handler_dyn(const char *p, size_t size, void *arg)
{
struct dyn_print *dp = arg;
if (size > dp->l - 1) {
const size_t new_size = MAX(dp->size + size, dp->size * 2);
char *str = mem_realloc(dp->str, new_size);
if (!str)
return ENOMEM;
dp->str = str;
dp->l += new_size - dp->size;
dp->p = dp->str + new_size - dp->l;
dp->size = new_size;
}
memcpy(dp->p, p, size);
dp->p += size;
dp->l -= size;
return 0;
}
/**
* Print a formatted string to a file stream, using va_list
*
* @param stream File stream for the output
* @param fmt Formatted string
* @param ap Variable-arguments list
*
* @return The number of characters printed, or -1 if error
*/
int re_vfprintf(FILE *stream, const char *fmt, va_list ap)
{
char buf[4096]; /* TODO: avoid static, use print_handler_dyn ? */
struct pl pl;
size_t n;
if (!stream)
return -1;
pl.p = buf;
pl.l = sizeof(buf);
if (0 != re_vhprintf(fmt, ap, print_handler, &pl))
return -1;
n = sizeof(buf) - pl.l;
if (1 != fwrite(buf, n, 1, stream))
return -1;
return (int)n;
}
/**
* Print a formatted string to stdout, using va_list
*
* @param fmt Formatted string
* @param ap Variable-arguments list
*
* @return The number of characters printed, or -1 if error
*/
int re_vprintf(const char *fmt, va_list ap)
{
return re_vfprintf(stdout, fmt, ap);
}
/**
* Print a formatted string to a buffer, using va_list
*
* @param str Buffer for output string
* @param size Size of buffer
* @param fmt Formatted string
* @param ap Variable-arguments list
*
* @return The number of characters printed, or -1 if error
*/
int re_vsnprintf(char *str, size_t size, const char *fmt, va_list ap)
{
struct pl pl;
int err;
if (!str || !size)
return -1;
pl.p = str;
pl.l = size - 1;
err = re_vhprintf(fmt, ap, print_handler, &pl);
str[size - pl.l - 1] = '\0';
return err ? -1 : (int)(size - pl.l - 1);
}
/**
* Print a formatted string to a dynamically allocated buffer, using va_list
*
* @param strp Pointer for output string
* @param fmt Formatted string
* @param ap Variable-arguments list
*
* @return 0 if success, otherwise errorcode
*/
int re_vsdprintf(char **strp, const char *fmt, va_list ap)
{
struct dyn_print dp;
int err;
if (!strp)
return EINVAL;
dp.size = 16;
dp.str = mem_alloc(dp.size, NULL);
if (!dp.str)
return ENOMEM;
dp.p = dp.str;
dp.l = dp.size;
err = re_vhprintf(fmt, ap, print_handler_dyn, &dp);
if (err)
goto out;
*dp.p = '\0';
out:
if (err)
mem_deref(dp.str);
else
*strp = dp.str;
return err;
}
/**
* Print a formatted string
*
* @param pf Print backend
* @param fmt Formatted string
*
* @return 0 if success, otherwise errorcode
*/
int re_hprintf(struct re_printf *pf, const char *fmt, ...)
{
va_list ap;
int err;
if (!pf)
return EINVAL;
va_start(ap, fmt);
err = re_vhprintf(fmt, ap, pf->vph, pf->arg);
va_end(ap);
return err;
}
/**
* Print a formatted string to a file stream
*
* @param stream File stream for output
* @param fmt Formatted string
*
* @return The number of characters printed, or -1 if error
*/
int re_fprintf(FILE *stream, const char *fmt, ...)
{
va_list ap;
int n;
va_start(ap, fmt);
n = re_vfprintf(stream, fmt, ap);
va_end(ap);
return n;
}
/**
* Print a formatted string to stdout
*
* @param fmt Formatted string
*
* @return The number of characters printed, or -1 if error
*/
int re_printf(const char *fmt, ...)
{
va_list ap;
int n;
va_start(ap, fmt);
n = re_vprintf(fmt, ap);
va_end(ap);
return n;
}
/**
* Print a formatted string to a buffer
*
* @param str Buffer for output string
* @param size Size of buffer
* @param fmt Formatted string
*
* @return The number of characters printed, or -1 if error
*/
int re_snprintf(char *str, size_t size, const char *fmt, ...)
{
va_list ap;
int n;
va_start(ap, fmt);
n = re_vsnprintf(str, size, fmt, ap);
va_end(ap);
return n;
}
/**
* Print a formatted string to a buffer
*
* @param strp Buffer pointer for output string
* @param fmt Formatted string
*
* @return 0 if success, otherwise errorcode
*/
int re_sdprintf(char **strp, const char *fmt, ...)
{
va_list ap;
int err;
va_start(ap, fmt);
err = re_vsdprintf(strp, fmt, ap);
va_end(ap);
return err;
}

42
src/fmt/prm.c Normal file
View file

@ -0,0 +1,42 @@
/**
* @file prm.c Generic parameter decoding
*
* Copyright (C) 2010 Creytiv.com
*/
#include <re_types.h>
#include <re_fmt.h>
bool fmt_param_get(const struct pl *pl, const char *pname, struct pl *val)
{
char expr[128];
if (!pl)
return false;
(void)re_snprintf(expr, sizeof(expr), "%s[=]*[^;]*", pname);
return 0 == re_regex(pl->p, pl->l, expr, NULL, val);
}
void fmt_param_apply(const struct pl *pl, fmt_param_h *ph, void *arg)
{
size_t i;
if (!pl || !ph)
return;
for (i=0; i<pl->l; ) {
struct pl lws, name, eq, val, s;
lws.l = eq.l = s.l = val.l = 0;
if (re_regex(&pl->p[i], pl->l - i, "[ ]*[^;=]+[=]*[^;]*[;]*",
&lws, &name, &eq, &val, &s))
break;
ph(&name, &val, arg);
i += (lws.l + name.l + eq.l + val.l + s.l);
}
}

254
src/fmt/regex.c Normal file
View file

@ -0,0 +1,254 @@
/**
* @file regex.c Implements basic regular expressions
*
* Copyright (C) 2010 Creytiv.com
*/
#include <ctype.h>
#include <re_types.h>
#include <re_fmt.h>
/** Defines a character range */
struct chr {
uint8_t min; /**< Minimum value */
uint8_t max; /**< Maximum value */
};
static bool expr_match(const struct chr *chrv, uint32_t n, uint8_t c,
bool neg)
{
uint32_t i;
for (i=0; i<n; i++) {
if (c < chrv[i].min)
continue;
if (c > chrv[i].max)
continue;
break;
}
return neg ? (i == n) : (i != n);
}
/**
* Parse a string using basic regular expressions. Any number of matching
* expressions can be given, and each match will be stored in a "struct pl"
* pointer-length type.
*
* @param ptr String to parse
* @param len Length of string
* @param expr Regular expressions string
*
* @return 0 if success, otherwise errorcode
*
* Example:
*
* We parse the buffer for any numerical values, to get a match we must have
* 1 or more occurences of the digits 0-9. The result is stored in 'num',
* which is of pointer-length type and will point to the first location in
* the buffer that contains "42".
*
* <pre>
const char buf[] = "foo 42 bar";
struct pl num;
int err = re_regex(buf, strlen(buf), "[0-9]+", &num);
here num contains a pointer to '42'
* </pre>
*/
int re_regex(const char *ptr, size_t len, const char *expr, ...)
{
struct chr chrv[64];
const char *p, *ep;
bool fm, range = false, ec = false, neg = false, qesc = false;
uint32_t n = 0;
va_list ap;
bool eesc;
size_t l;
if (!ptr || !expr)
return EINVAL;
again:
eesc = false;
fm = false;
l = len--;
p = ptr++;
ep = expr;
va_start(ap, expr);
if (!l)
goto out;
for (; *ep; ep++) {
if ('\\' == *ep && !eesc) {
eesc = true;
continue;
}
if (!fm) {
/* Start of character class */
if ('[' == *ep && !eesc) {
n = 0;
fm = true;
ec = false;
neg = false;
range = false;
qesc = false;
continue;
}
if (!l)
break;
if (tolower(*ep) != tolower(*p))
goto again;
eesc = false;
++p;
--l;
continue;
}
/* End of character class */
else if (ec) {
uint32_t nm, nmin, nmax;
struct pl lpl, *pl = va_arg(ap, struct pl *);
bool quote = false, esc = false;
/* Match 0 or more times */
if ('*' == *ep) {
nmin = 0;
nmax = -1;
}
/* Match 1 or more times */
else if ('+' == *ep) {
nmin = 1;
nmax = -1;
}
/* Match exactly n times */
else if ('1' <= *ep && *ep <= '9') {
nmin = *ep - '0';
nmax = *ep - '0';
}
else
break;
fm = false;
lpl.p = p;
lpl.l = 0;
for (nm = 0; l && nm < nmax; nm++, p++, l--, lpl.l++) {
if (qesc) {
if (esc) {
esc = false;
continue;
}
switch (*p) {
case '\\':
esc = true;
continue;
case '"':
quote = !quote;
continue;
}
if (quote)
continue;
}
if (!expr_match(chrv, n, tolower(*p), neg))
break;
}
/* Strip quotes */
if (qesc && lpl.l > 1 &&
lpl.p[0] == '"' && lpl.p[lpl.l - 1] == '"') {
lpl.p += 1;
lpl.l -= 2;
nm -= 2;
}
if ((nm < nmin) || (nm > nmax))
goto again;
if (pl)
*pl = lpl;
eesc = false;
continue;
}
if (eesc) {
eesc = false;
goto chr;
}
switch (*ep) {
/* End of character class */
case ']':
ec = true;
continue;
/* Negate with quote escape */
case '~':
if (n)
break;
qesc = true;
neg = true;
continue;
/* Negate */
case '^':
if (n)
break;
neg = true;
continue;
/* Range */
case '-':
if (!n || range)
break;
range = true;
--n;
continue;
}
chr:
chrv[n].max = tolower(*ep);
if (range)
range = false;
else
chrv[n].min = tolower(*ep);
if (++n > ARRAY_SIZE(chrv))
break;
}
out:
va_end(ap);
if (fm)
return EINVAL;
return *ep ? ENOENT : 0;
}

124
src/fmt/str.c Normal file
View file

@ -0,0 +1,124 @@
/**
* @file fmt/str.c String format functions
*
* Copyright (C) 2010 Creytiv.com
*/
#undef __STRICT_ANSI__ /* for mingw32 */
#include <string.h>
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#include <re_types.h>
#include <re_mem.h>
#include <re_fmt.h>
/**
* Convert a ascii hex string to binary format
*
* @param hex Destinatin binary buffer
* @param len Length of binary buffer
* @param str Source ascii string
*
* @return 0 if success, otherwise errorcode
*/
int str_hex(uint8_t *hex, size_t len, const char *str)
{
size_t i;
if (!hex || !str || (strlen(str) != (2 * len)))
return EINVAL;
for (i=0; i<len*2; i+=2) {
hex[i/2] = ch_hex(str[i]) << 4;
hex[i/2] += ch_hex(str[i+1]);
}
return 0;
}
/**
* Copy a 0-terminated string with maximum length
*
* @param dst Destinatin string
* @param src Source string
* @param n Maximum size of destination, including 0-terminator
*/
void str_ncpy(char *dst, const char *src, size_t n)
{
if (!dst || !src || !n)
return;
(void)strncpy(dst, src, n-1);
dst[n-1] = '\0'; /* strncpy does not null terminate if overflow */
}
/**
* Duplicate a 0-terminated string
*
* @param dst Pointer to destination string (set on return)
* @param src Source string
*
* @return 0 if success, otherwise errorcode
*/
int str_dup(char **dst, const char *src)
{
char *p;
size_t sz;
if (!dst || !src)
return EINVAL;
sz = strlen(src) + 1;
p = mem_alloc(sz, NULL);
if (!p)
return ENOMEM;
memcpy(p, src, sz);
*dst = p;
return 0;
}
/**
* Compare two 0-terminated strings
*
* @param s1 First string
* @param s2 Second string
*
* @return an integer less than, equal to, or greater than zero if s1 is found
* respectively, to be less than, to match, or be greater than s2
*/
int str_casecmp(const char *s1, const char *s2)
{
/* Same strings -> equal */
if (s1 == s2)
return 0;
if (!s1 || !s2)
return 1;
#ifdef WIN32
return _stricmp(s1, s2);
#else
return strcasecmp(s1, s2);
#endif
}
/**
* Calculate the length of a string, safe version.
*
* @param s String
*
* @return Length of the string
*/
size_t str_len(const char *s)
{
return s ? strlen(s) : 0;
}

Some files were not shown because too many files have changed in this diff Show more